aboutsummaryrefslogtreecommitdiff
path: root/src/lombok/eclipse
diff options
context:
space:
mode:
authorReinier Zwitserloot <reinier@tipit.to>2009-06-15 22:32:44 +0200
committerReinier Zwitserloot <reinier@tipit.to>2009-06-15 22:32:44 +0200
commiteebc3450e4272688e09d1eadbaa61ea171fff1f7 (patch)
treef9778910b6ee22666fab4ea860b604b258201ca3 /src/lombok/eclipse
parentd2ffd52636113c5737e32779938511ae68a1a0fe (diff)
downloadlombok-eebc3450e4272688e09d1eadbaa61ea171fff1f7.tar.gz
lombok-eebc3450e4272688e09d1eadbaa61ea171fff1f7.tar.bz2
lombok-eebc3450e4272688e09d1eadbaa61ea171fff1f7.zip
all eclipse AST Statements objects are now part of the custom AST we build for lombok.
This way something like @AutoClose on a local var declaration can walk up one node, find all mentions of the variable, and add a close call right after the last mention.
Diffstat (limited to 'src/lombok/eclipse')
-rw-r--r--src/lombok/eclipse/EclipseAST.java92
-rw-r--r--src/lombok/eclipse/EclipseASTAdapter.java3
-rw-r--r--src/lombok/eclipse/EclipseASTVisitor.java19
-rw-r--r--src/lombok/eclipse/TransformEclipseAST.java1
4 files changed, 85 insertions, 30 deletions
diff --git a/src/lombok/eclipse/EclipseAST.java b/src/lombok/eclipse/EclipseAST.java
index 8730849b..5450a9a9 100644
--- a/src/lombok/eclipse/EclipseAST.java
+++ b/src/lombok/eclipse/EclipseAST.java
@@ -60,6 +60,10 @@ public class EclipseAST {
visitor.visitLocal(child, (LocalDeclaration)n);
traverseChildren(visitor, child);
visitor.endVisitLocal(child, (LocalDeclaration)n);
+ } else if ( n instanceof Statement ) {
+ visitor.visitStatement(child, (Statement)n);
+ traverseChildren(visitor, child);
+ visitor.endVisitStatement(node, (Statement)n);
} else throw new AssertionError("Can't be reached");
}
}
@@ -142,10 +146,12 @@ public class EclipseAST {
Node parent;
final Collection<Node> children;
boolean handled;
+ private final boolean isStructurallySignificant;
Node(ASTNode node, Collection<Node> children) {
this.node = node;
this.children = children == null ? Collections.<Node>emptyList() : children;
+ this.isStructurallySignificant = calculateIsStructurallySignificant();
}
public void addError(String message) {
@@ -168,7 +174,39 @@ public class EclipseAST {
return node;
}
+ /** Returns the structurally significant node that encloses this one.
+ *
+ * @see #isStructurallySignificant()
+ */
public Node up() {
+ Node result = parent;
+ while ( result != null && !result.isStructurallySignificant() ) result = result.parent;
+ return result;
+ }
+
+ /**
+ * Structurally significant means: LocalDeclaration, TypeDeclaration, MethodDeclaration, ConstructorDeclaration,
+ * FieldDeclaration, Initializer, and CompilationUnitDeclaration.
+ * The rest is e.g. if statements, while loops, etc.
+ */
+ public boolean isStructurallySignificant() {
+ return isStructurallySignificant;
+ }
+
+ private boolean calculateIsStructurallySignificant() {
+ if ( node instanceof TypeDeclaration ) return true;
+ if ( node instanceof AbstractMethodDeclaration ) return true;
+ if ( node instanceof FieldDeclaration ) return true;
+ if ( node instanceof LocalDeclaration ) return true;
+ if ( node instanceof CompilationUnitDeclaration ) return true;
+ return false;
+ }
+
+ /**
+ * Returns the direct parent node in the AST tree of this node. For example, a local variable declaration's
+ * direct parent can be e.g. an If block, but its up() Node is the Method that contains it.
+ */
+ public Node directUp() {
return parent;
}
@@ -274,15 +312,20 @@ public class EclipseAST {
return childNodes;
}
+ private static <T> Collection<T> singleton(T item) {
+ if ( item == null ) return Collections.emptyList();
+ else return Collections.singleton(item);
+ }
+
private Node buildTree(FieldDeclaration field) {
if ( field instanceof Initializer ) return buildTree((Initializer)field);
if ( identityDetector.containsKey(field) ) return null;
- return putInMap(new Node(field, buildWithStatement(field.initialization)));
+ return putInMap(new Node(field, singleton(buildWithStatement(field.initialization))));
}
private Node buildTree(Initializer initializer) {
if ( identityDetector.containsKey(initializer) ) return null;
- return putInMap(new Node(initializer, buildWithStatement(initializer.block)));
+ return putInMap(new Node(initializer, singleton(buildWithStatement(initializer.block))));
}
private Collection<Node> buildTree(AbstractMethodDeclaration[] children) {
@@ -305,52 +348,40 @@ public class EclipseAST {
if ( children == null ) return Collections.emptyList();
List<Node> childNodes = new ArrayList<Node>();
for ( LocalDeclaration local : children ) {
- if ( !identityDetector.containsKey(local) ) {
- addIfNotNull(childNodes, buildTree(local));
- childNodes.addAll(buildWithStatement(local.initialization));
- }
+ addIfNotNull(childNodes, buildTree(local));
}
return childNodes;
}
private Node buildTree(LocalDeclaration local) {
if ( identityDetector.containsKey(local) ) return null;
- return putInMap(new Node(local, null));
+ return putInMap(new Node(local, singleton(buildWithStatement(local.initialization))));
}
private Collection<Node> buildTree(Statement[] children) {
if ( children == null ) return Collections.emptyList();
List<Node> childNodes = new ArrayList<Node>();
- for ( Statement child : children ) childNodes.addAll(buildWithStatement(child));
+ for ( Statement child : children ) addIfNotNull(childNodes, buildWithStatement(child));
return childNodes;
}
//Almost anything is a statement, so this method has a different name to avoid overloading confusion
- private Collection<Node> buildWithStatement(Statement child) {
- if ( child == null || identityDetector.containsKey(child) ) return Collections.emptyList();
- if ( child instanceof TypeDeclaration ) {
- Node n = buildTree((TypeDeclaration)child);
- return n == null ? Collections.<Node>emptyList() : Collections.singleton(n);
- }
+ private Node buildWithStatement(Statement child) {
+ if ( child == null || identityDetector.containsKey(child) ) return null;
+ if ( child instanceof TypeDeclaration ) return buildTree((TypeDeclaration)child);
+
+ if ( child instanceof LocalDeclaration ) return buildTree((LocalDeclaration)child);
- if ( child instanceof LocalDeclaration ) {
- List<Node> childNodes = new ArrayList<Node>();
- addIfNotNull(childNodes, buildTree((LocalDeclaration)child));
- identityDetector.put(child, null);
- childNodes.addAll(buildWithStatement(((LocalDeclaration)child).initialization));
- return childNodes;
- }
//We drill down because LocalDeclarations and TypeDeclarations can occur anywhere, even in, say,
//an if block, or even the expression on an assert statement!
- identityDetector.put(child, null);
return drill(child);
}
- private Collection<Node> drill(Statement child) {
+ private Node drill(Statement statement) {
List<Node> childNodes = new ArrayList<Node>();
- for ( FieldAccess fa : fieldsOf(child.getClass()) ) childNodes.addAll(buildWithField(child, fa));
- return childNodes;
+ for ( FieldAccess fa : fieldsOf(statement.getClass()) ) childNodes.addAll(buildWithField(statement, fa));
+ return new Node(statement, childNodes);
}
private static class FieldAccess {
@@ -362,6 +393,7 @@ public class EclipseAST {
this.dim = dim;
}
}
+
private static Map<Class<?>, Collection<FieldAccess>> fieldsOfASTClasses = new HashMap<Class<?>, Collection<FieldAccess>>();
private Collection<FieldAccess> fieldsOf(Class<?> c) {
Collection<FieldAccess> fields = fieldsOfASTClasses.get(c);
@@ -376,6 +408,7 @@ public class EclipseAST {
private void getFields(Class<?> c, Collection<FieldAccess> fields) {
if ( c == ASTNode.class || c == null ) return;
for ( Field f : c.getDeclaredFields() ) {
+ if ( Modifier.isStatic(f.getModifiers()) ) continue;
Class<?> t = f.getType();
int dim = 0;
while ( t.isArray() ) {
@@ -390,17 +423,16 @@ public class EclipseAST {
getFields(c.getSuperclass(), fields);
}
- private Collection<Node> buildWithField(Statement child, FieldAccess fa) {
- if ( Modifier.isStatic(fa.field.getModifiers()) ) return Collections.emptyList();
+ private Collection<Node> buildWithField(Statement statement, FieldAccess fa) {
List<Node> list = new ArrayList<Node>();
- buildWithField(child, fa, list);
+ buildWithField(statement, fa, list);
return list;
}
private void buildWithField(Statement child, FieldAccess fa, Collection<Node> list) {
try {
Object o = fa.field.get(child);
- if ( fa.dim == 0 ) list.addAll(buildWithStatement((Statement)o));
+ if ( fa.dim == 0 ) addIfNotNull(list, buildWithStatement((Statement)o));
else buildWithArray(o, list, fa.dim);
} catch ( IllegalAccessException e ) {
sneakyThrow(e);
@@ -410,7 +442,7 @@ public class EclipseAST {
private void buildWithArray(Object array, Collection<Node> list, int dim) {
if ( array == null ) return;
if ( dim == 1 ) for ( Object v : (Object[])array ) {
- list.addAll(buildWithStatement((Statement)v));
+ addIfNotNull(list, buildWithStatement((Statement)v));
} else for ( Object v : (Object[])array ) {
buildWithArray(v, list, dim-1);
}
diff --git a/src/lombok/eclipse/EclipseASTAdapter.java b/src/lombok/eclipse/EclipseASTAdapter.java
index a76380cf..50fded89 100644
--- a/src/lombok/eclipse/EclipseASTAdapter.java
+++ b/src/lombok/eclipse/EclipseASTAdapter.java
@@ -7,6 +7,7 @@ import org.eclipse.jdt.internal.compiler.ast.CompilationUnitDeclaration;
import org.eclipse.jdt.internal.compiler.ast.FieldDeclaration;
import org.eclipse.jdt.internal.compiler.ast.Initializer;
import org.eclipse.jdt.internal.compiler.ast.LocalDeclaration;
+import org.eclipse.jdt.internal.compiler.ast.Statement;
import org.eclipse.jdt.internal.compiler.ast.TypeDeclaration;
public abstract class EclipseASTAdapter implements EclipseASTVisitor {
@@ -22,4 +23,6 @@ public abstract class EclipseASTAdapter implements EclipseASTVisitor {
@Override public void endVisitMethod(Node node, AbstractMethodDeclaration method) {}
@Override public void visitLocal(Node node, LocalDeclaration local) {}
@Override public void endVisitLocal(Node node, LocalDeclaration local) {}
+ @Override public void visitStatement(Node node, Statement statement) {}
+ @Override public void endVisitStatement(Node node, Statement statement) {}
}
diff --git a/src/lombok/eclipse/EclipseASTVisitor.java b/src/lombok/eclipse/EclipseASTVisitor.java
index aff1cc38..ac4d0e33 100644
--- a/src/lombok/eclipse/EclipseASTVisitor.java
+++ b/src/lombok/eclipse/EclipseASTVisitor.java
@@ -12,6 +12,7 @@ import org.eclipse.jdt.internal.compiler.ast.ConstructorDeclaration;
import org.eclipse.jdt.internal.compiler.ast.FieldDeclaration;
import org.eclipse.jdt.internal.compiler.ast.Initializer;
import org.eclipse.jdt.internal.compiler.ast.LocalDeclaration;
+import org.eclipse.jdt.internal.compiler.ast.Statement;
import org.eclipse.jdt.internal.compiler.ast.TypeDeclaration;
import org.eclipse.jdt.internal.compiler.ast.TypeReference;
@@ -60,6 +61,14 @@ public interface EclipseASTVisitor {
void visitLocal(Node node, LocalDeclaration declaration);
void endVisitLocal(Node node, LocalDeclaration declaration);
+ /**
+ * Visits a statement that isn't any of the other visit methods (e.g. TypeDeclaration).
+ * @param node
+ * @param statement
+ */
+ void visitStatement(Node node, Statement statement);
+ void endVisitStatement(Node node, Statement statement);
+
public static class EclipseASTPrinter implements EclipseASTVisitor {
int indent = 0;
private void print(String text, Object... params) {
@@ -155,5 +164,15 @@ public interface EclipseASTVisitor {
indent--;
print("</%s %s %s>", type, str(local.type), str(local.name));
}
+
+ @Override public void visitStatement(Node node, Statement statement) {
+ print("<%s>", statement.getClass());
+ indent++;
+ }
+
+ @Override public void endVisitStatement(Node node, Statement statement) {
+ indent--;
+ print("</%s>", statement.getClass());
+ }
}
}
diff --git a/src/lombok/eclipse/TransformEclipseAST.java b/src/lombok/eclipse/TransformEclipseAST.java
index c9690953..f606733c 100644
--- a/src/lombok/eclipse/TransformEclipseAST.java
+++ b/src/lombok/eclipse/TransformEclipseAST.java
@@ -77,6 +77,7 @@ public class TransformEclipseAST {
String message = "Lombok can't parse this source: " + t.toString();
EclipseAST.addProblemToCompilationResult(fileName, ast, false, message, ast, 0, 0);
+ t.printStackTrace();
} catch ( Throwable t2 ) {
Eclipse.error("Can't create an error in the problems dialog while adding: " + t.toString(), t2);
}