diff options
Diffstat (limited to 'src/core/lombok')
-rw-r--r-- | src/core/lombok/core/AST.java | 28 | ||||
-rw-r--r-- | src/core/lombok/javac/JavacAST.java | 43 |
2 files changed, 59 insertions, 12 deletions
diff --git a/src/core/lombok/core/AST.java b/src/core/lombok/core/AST.java index 30297418..e6721b80 100644 --- a/src/core/lombok/core/AST.java +++ b/src/core/lombok/core/AST.java @@ -54,7 +54,7 @@ public abstract class AST<A extends AST<A, L, N>, L extends LombokNode<A, L, N>, private final String fileName; private final String packageDeclaration; private final ImportList imports; - Map<N, Void> identityDetector = new IdentityHashMap<N, Void>(); + Map<N, N> identityDetector = new IdentityHashMap<N, N>(); private Map<N, L> nodeMap = new IdentityHashMap<N, L>(); private boolean changed = false; @@ -105,7 +105,7 @@ public abstract class AST<A extends AST<A, L, N>, L extends LombokNode<A, L, N>, */ protected L putInMap(L node) { nodeMap.put(node.get(), node); - identityDetector.put(node.get(), null); + identityDetector.put(node.get(), node.get()); return node; } @@ -117,7 +117,7 @@ public abstract class AST<A extends AST<A, L, N>, L extends LombokNode<A, L, N>, /** Clears the registry that avoids endless loops, and empties the node map. The existing node map * object is left untouched, and instead a new map is created. */ protected void clearState() { - identityDetector = new IdentityHashMap<N, Void>(); + identityDetector = new IdentityHashMap<N, N>(); nodeMap = new IdentityHashMap<N, L>(); } @@ -127,9 +127,7 @@ public abstract class AST<A extends AST<A, L, N>, L extends LombokNode<A, L, N>, * case you should do nothing lest the AST build process loops endlessly. */ protected boolean setAndGetAsHandled(N node) { - if (identityDetector.containsKey(node)) return true; - identityDetector.put(node, null); - return false; + return identityDetector.put(node, node) != null; } public String getFileName() { @@ -234,14 +232,12 @@ public abstract class AST<A extends AST<A, L, N>, L extends LombokNode<A, L, N>, } } - for (Class<?> statementType : getStatementTypes()) { - if (statementType.isAssignableFrom(t)) { - f.setAccessible(true); - fields.add(new FieldAccess(f, dim)); - break; - } + if (shouldDrill(c, t, f.getName())) { + f.setAccessible(true); + fields.add(new FieldAccess(f, dim)); } } + getFields(c.getSuperclass(), fields); } @@ -258,6 +254,14 @@ public abstract class AST<A extends AST<A, L, N>, L extends LombokNode<A, L, N>, * though some platforms (such as Eclipse) group these under one common supertype. */ protected abstract Collection<Class<? extends N>> getStatementTypes(); + protected boolean shouldDrill(Class<?> parentType, Class<?> childType, String fieldName) { + for (Class<?> statementType : getStatementTypes()) { + if (statementType.isAssignableFrom(childType)) return true; + } + + return false; + } + /** * buildTree implementation that uses reflection to find all child nodes by way of inspecting * the fields. */ diff --git a/src/core/lombok/javac/JavacAST.java b/src/core/lombok/javac/JavacAST.java index 8197dae6..5a91258c 100644 --- a/src/core/lombok/javac/JavacAST.java +++ b/src/core/lombok/javac/JavacAST.java @@ -24,6 +24,7 @@ package lombok.javac; import java.lang.reflect.Field; import java.util.ArrayList; import java.util.Collection; +import java.util.Collections; import java.util.List; import javax.annotation.processing.Messager; @@ -39,6 +40,7 @@ import com.sun.tools.javac.model.JavacElements; import com.sun.tools.javac.model.JavacTypes; import com.sun.tools.javac.tree.JCTree; import com.sun.tools.javac.tree.JCTree.JCCatch; +import com.sun.tools.javac.tree.JCTree.JCTry; import com.sun.tools.javac.tree.TreeMaker; import com.sun.tools.javac.tree.JCTree.JCAnnotation; import com.sun.tools.javac.tree.JCTree.JCBlock; @@ -224,6 +226,46 @@ public class JavacAST extends AST<JavacAST, JavacNode, JCTree> { return putInMap(new JavacNode(this, local, childNodes, kind)); } + private static boolean JCTRY_RESOURCES_FIELD_INITIALIZED; + private static Field JCTRY_RESOURCES_FIELD; + + @SuppressWarnings("unchecked") + private static List<JCTree> getResourcesForTryNode(JCTry tryNode) { + if (!JCTRY_RESOURCES_FIELD_INITIALIZED) { + try { + JCTRY_RESOURCES_FIELD = JCTry.class.getField("resources"); + } catch (NoSuchFieldException ignore) { + // Java 1.6 or lower won't have this at all. + } catch (Exception ignore) { + // Shouldn't happen. Best thing we can do is just carry on and break on try/catch. + } + JCTRY_RESOURCES_FIELD_INITIALIZED = true; + } + + if (JCTRY_RESOURCES_FIELD == null) return Collections.emptyList(); + Object rv = null; + try { + rv = JCTRY_RESOURCES_FIELD.get(tryNode); + } catch (Exception ignore) {} + + if (rv instanceof List) return (List<JCTree>) rv; + return Collections.emptyList(); + } + + private JavacNode buildTry(JCTry tryNode) { + if (setAndGetAsHandled(tryNode)) return null; + List<JavacNode> childNodes = new ArrayList<JavacNode>(); + for (JCTree varDecl : getResourcesForTryNode(tryNode)) { + if (varDecl instanceof JCVariableDecl) { + addIfNotNull(childNodes, buildLocalVar((JCVariableDecl) varDecl, Kind.LOCAL)); + } + } + addIfNotNull(childNodes, buildStatement(tryNode.body)); + for (JCCatch jcc : tryNode.catchers) addIfNotNull(childNodes, buildTree(jcc, Kind.STATEMENT)); + addIfNotNull(childNodes, buildStatement(tryNode.finalizer)); + return putInMap(new JavacNode(this, tryNode, childNodes, Kind.STATEMENT)); + } + private JavacNode buildInitializer(JCBlock initializer) { if (setAndGetAsHandled(initializer)) return null; List<JavacNode> childNodes = new ArrayList<JavacNode>(); @@ -265,6 +307,7 @@ public class JavacAST extends AST<JavacAST, JavacNode, JCTree> { if (statement instanceof JCAnnotation) return null; if (statement instanceof JCClassDecl) return buildType((JCClassDecl)statement); if (statement instanceof JCVariableDecl) return buildLocalVar((JCVariableDecl)statement, Kind.LOCAL); + if (statement instanceof JCTry) return buildTry((JCTry) statement); if (setAndGetAsHandled(statement)) return null; |