mirror of
https://github.com/tiennm99/lombok.git
synced 2026-09-11 06:17:56 +00:00
Fixed issue #24 by refactoring the AST.Node class - taken it out, and in the process fixed a lot of type annoyance by adding more generics.
Also changed coding style from for/while/if/switch/catch/do ( expr ) {} to for (expr) {}, hence the changes _everywhere_.
This commit is contained in:
@@ -5,11 +5,6 @@
|
||||
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
|
||||
<classpathentry kind="lib" path="deps/lombok/org.eclipse.jdt.core_3.5.0.v_963.jar"/>
|
||||
<classpathentry kind="lib" path="deps/lombok/org.eclipse.jdt.ui_3.5.1.r351_v20090821-0800.jar"/>
|
||||
<classpathentry kind="src" path=".apt_generated">
|
||||
<attributes>
|
||||
<attribute name="optional" value="true"/>
|
||||
</attributes>
|
||||
</classpathentry>
|
||||
<classpathentry kind="lib" path="deps/lombok/org.eclipse.core.runtime_3.5.0.v20090525.jar"/>
|
||||
<classpathentry kind="lib" path="deps/lombok/org.eclipse.osgi_3.5.0.v20090520.jar"/>
|
||||
<classpathentry kind="lib" path="deps/lombok/org.eclipse.equinox.common_3.5.0.v20090520-1800.jar"/>
|
||||
|
||||
@@ -48,7 +48,7 @@ public class Lombok {
|
||||
* @return A dummy RuntimeException; this method never returns normally, it <em>always</em> throws an exception!
|
||||
*/
|
||||
public static RuntimeException sneakyThrow(Throwable t) {
|
||||
if ( t == null ) throw new NullPointerException("t");
|
||||
if (t == null) throw new NullPointerException("t");
|
||||
Lombok.<RuntimeException>sneakyThrow0(t);
|
||||
return null;
|
||||
}
|
||||
|
||||
+86
-329
@@ -39,26 +39,28 @@ import java.util.Map;
|
||||
* Lombok wraps the AST produced by a target platform into its own AST system, mostly because both Eclipse and javac
|
||||
* do not allow upward traversal (from a method to its owning type, for example).
|
||||
*
|
||||
* @param A Self-type.
|
||||
* @param L type of all LombokNodes.
|
||||
* @param N The common type of all AST nodes in the internal representation of the target platform.
|
||||
* For example, JCTree for javac, and ASTNode for Eclipse.
|
||||
* For example, JCTree for javac, and ASTNode for Eclipse.
|
||||
*/
|
||||
public abstract class AST<N> {
|
||||
public abstract class AST<A extends AST<A, L, N>, L extends LombokNode<A, L, N>, N> {
|
||||
/** The kind of node represented by a given AST.Node object. */
|
||||
public enum Kind {
|
||||
COMPILATION_UNIT, TYPE, FIELD, INITIALIZER, METHOD, ANNOTATION, ARGUMENT, LOCAL, STATEMENT;
|
||||
}
|
||||
|
||||
private Node top;
|
||||
private L top;
|
||||
private final String fileName;
|
||||
private Map<N, Void> identityDetector = new IdentityHashMap<N, Void>();
|
||||
private Map<N, Node> nodeMap = new IdentityHashMap<N, Node>();
|
||||
Map<N, Void> identityDetector = new IdentityHashMap<N, Void>();
|
||||
private Map<N, L> nodeMap = new IdentityHashMap<N, L>();
|
||||
|
||||
protected AST(String fileName) {
|
||||
this.fileName = fileName == null ? "(unknown).java" : fileName;
|
||||
}
|
||||
|
||||
/** Set the node object that wraps the internal Compilation Unit node. */
|
||||
protected void setTop(Node top) {
|
||||
protected void setTop(L top) {
|
||||
this.top = top;
|
||||
}
|
||||
|
||||
@@ -80,14 +82,14 @@ public abstract class AST<N> {
|
||||
* Puts the given node in the map so that javac/Eclipse's own internal AST object can be translated to
|
||||
* an AST.Node object. Also registers the object as visited to avoid endless loops.
|
||||
*/
|
||||
protected <T extends Node> T putInMap(T node) {
|
||||
protected L putInMap(L node) {
|
||||
nodeMap.put(node.get(), node);
|
||||
identityDetector.put(node.get(), null);
|
||||
return node;
|
||||
}
|
||||
|
||||
/** Returns the node map, that can map javac/Eclipse internal AST objects to AST.Node objects. */
|
||||
protected Map<N, Node> getNodeMap() {
|
||||
protected Map<N, L> getNodeMap() {
|
||||
return nodeMap;
|
||||
}
|
||||
|
||||
@@ -95,7 +97,7 @@ public abstract class AST<N> {
|
||||
* object is left untouched, and instead a new map is created. */
|
||||
protected void clearState() {
|
||||
identityDetector = new IdentityHashMap<N, Void>();
|
||||
nodeMap = new IdentityHashMap<N, Node>();
|
||||
nodeMap = new IdentityHashMap<N, L>();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -104,7 +106,7 @@ public abstract class AST<N> {
|
||||
* case you should do nothing lest the AST build process loops endlessly.
|
||||
*/
|
||||
protected boolean setAndGetAsHandled(N node) {
|
||||
if ( identityDetector.containsKey(node) ) return true;
|
||||
if (identityDetector.containsKey(node)) return true;
|
||||
identityDetector.put(node, null);
|
||||
return false;
|
||||
}
|
||||
@@ -114,23 +116,23 @@ public abstract class AST<N> {
|
||||
}
|
||||
|
||||
/** The AST.Node object representing the Compilation Unit. */
|
||||
public Node top() {
|
||||
public L top() {
|
||||
return top;
|
||||
}
|
||||
|
||||
/** Maps a javac/Eclipse internal AST Node to the appropriate AST.Node object. */
|
||||
public Node get(N node) {
|
||||
public L get(N node) {
|
||||
return nodeMap.get(node);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private Node replaceNewWithExistingOld(Map<N, Node> oldNodes, Node newNode) {
|
||||
Node oldNode = oldNodes.get(newNode.get());
|
||||
Node targetNode = oldNode == null ? newNode : oldNode;
|
||||
L replaceNewWithExistingOld(Map<N, L> oldNodes, L newNode) {
|
||||
L oldNode = oldNodes.get(newNode.get());
|
||||
L targetNode = oldNode == null ? newNode : oldNode;
|
||||
|
||||
List children = new ArrayList();
|
||||
for ( Node child : newNode.children ) {
|
||||
Node oldChild = replaceNewWithExistingOld(oldNodes, child);
|
||||
for (L child : newNode.children) {
|
||||
L oldChild = replaceNewWithExistingOld(oldNodes, child);
|
||||
children.add(oldChild);
|
||||
oldChild.parent = targetNode;
|
||||
}
|
||||
@@ -140,262 +142,8 @@ public abstract class AST<N> {
|
||||
return targetNode;
|
||||
}
|
||||
|
||||
/** An instance of this class wraps an Eclipse/javac internal node object. */
|
||||
public abstract class Node {
|
||||
protected final Kind kind;
|
||||
protected final N node;
|
||||
protected final List<? extends Node> children;
|
||||
protected Node parent;
|
||||
|
||||
/** This flag has no specified meaning; you can set and retrieve it.
|
||||
*
|
||||
* In practice, for annotation nodes it means: Some AnnotationHandler finished whatever changes were required,
|
||||
* and for all other nodes it means: This node was made by a lombok operation.
|
||||
*/
|
||||
protected boolean handled;
|
||||
|
||||
/** structurally significant are those nodes that can be annotated in java 1.6 or are method-like toplevels,
|
||||
* so fields, local declarations, method arguments, methods, types, the Compilation Unit itself, and initializers. */
|
||||
protected boolean isStructurallySignificant;
|
||||
|
||||
/**
|
||||
* Creates a new Node object that represents the provided node.
|
||||
*
|
||||
* Make sure you manually set the parent correctly.
|
||||
*
|
||||
* @param node The AST object in the target parser's own internal AST tree that this node object will represent.
|
||||
* @param children A list of child nodes. Passing in null results in the children list being empty, not null.
|
||||
* @param kind The kind of node represented by this object.
|
||||
*/
|
||||
protected Node(N node, List<? extends Node> children, Kind kind) {
|
||||
this.kind = kind;
|
||||
this.node = node;
|
||||
this.children = children == null ? new ArrayList<Node>() : children;
|
||||
for ( Node child : this.children ) child.parent = this;
|
||||
this.isStructurallySignificant = calculateIsStructurallySignificant();
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override public String toString() {
|
||||
return String.format("NODE %s (%s) %s%s",
|
||||
kind, node == null ? "(NULL)" : node.getClass(), handled ? "[HANDLED]" : "", node == null ? "" : node);
|
||||
}
|
||||
|
||||
/**
|
||||
* Convenient shortcut to the owning JavacAST object's getPackageDeclaration method.
|
||||
*
|
||||
* @see AST#getPackageDeclaration()
|
||||
*/
|
||||
public String getPackageDeclaration() {
|
||||
return AST.this.getPackageDeclaration();
|
||||
}
|
||||
|
||||
/**
|
||||
* Convenient shortcut to the owning JavacAST object's getImportStatements method.
|
||||
*
|
||||
* @see AST#getImportStatements()
|
||||
*/
|
||||
public Collection<String> getImportStatements() {
|
||||
return AST.this.getImportStatements();
|
||||
}
|
||||
|
||||
/**
|
||||
* See {@link #isStructurallySignificant}.
|
||||
*/
|
||||
protected abstract boolean calculateIsStructurallySignificant();
|
||||
|
||||
/**
|
||||
* Convenient shortcut to the owning JavacAST object's get method.
|
||||
*
|
||||
* @see AST#get(Object)
|
||||
*/
|
||||
public Node getNodeFor(N obj) {
|
||||
return AST.this.get(obj);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return The javac/Eclipse internal AST object wrapped by this AST.Node object.
|
||||
*/
|
||||
public N get() {
|
||||
return node;
|
||||
}
|
||||
|
||||
/**
|
||||
* Replaces the AST node represented by this node object with the provided node. This node must
|
||||
* have a parent, obviously, for this to work.
|
||||
*
|
||||
* Also affects the underlying (Eclipse/javac) AST.
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public Node replaceWith(N newN, Kind kind) {
|
||||
Node newNode = buildTree(newN, kind);
|
||||
newNode.parent = parent;
|
||||
for ( int i = 0 ; i < parent.children.size() ; i++ ) {
|
||||
if ( parent.children.get(i) == this ) ((List)parent.children).set(i, newNode);
|
||||
}
|
||||
|
||||
parent.replaceChildNode(get(), newN);
|
||||
return newNode;
|
||||
}
|
||||
|
||||
/**
|
||||
* Replaces the stated node with a new one. The old node must be a direct child of this node.
|
||||
*
|
||||
* Also affects the underlying (Eclipse/javac) AST.
|
||||
*/
|
||||
public void replaceChildNode(N oldN, N newN) {
|
||||
replaceStatementInNode(get(), oldN, newN);
|
||||
}
|
||||
|
||||
public Kind getKind() {
|
||||
return kind;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the name of your type (simple name), method, field, or local variable. Return null if this
|
||||
* node doesn't really have a name, such as initializers, while statements, etc.
|
||||
*/
|
||||
public abstract String getName();
|
||||
|
||||
/** 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;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns all children nodes.
|
||||
*
|
||||
* A copy is created, so changing the list has no effect. Also, while iterating through this list,
|
||||
* you may add, remove, or replace children without causing ConcurrentModificationExceptions.
|
||||
*/
|
||||
public Collection<? extends Node> down() {
|
||||
return new ArrayList<Node>(children);
|
||||
}
|
||||
|
||||
/**
|
||||
* returns the value of the 'handled' flag.
|
||||
*
|
||||
* @see #handled
|
||||
*/
|
||||
public boolean isHandled() {
|
||||
return handled;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the handled flag, then returns 'this'.
|
||||
*
|
||||
* @see #handled
|
||||
*/
|
||||
public Node setHandled() {
|
||||
this.handled = true;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convenient shortcut to the owning JavacAST object's top method.
|
||||
*
|
||||
* @see AST#top()
|
||||
*/
|
||||
public Node top() {
|
||||
return top;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convenient shortcut to the owning JavacAST object's getFileName method.
|
||||
*
|
||||
* @see AST#getFileName()
|
||||
*/
|
||||
public String getFileName() {
|
||||
return fileName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds the stated node as a direct child of this node.
|
||||
*
|
||||
* Does not change the underlying (javac/Eclipse) AST, only the wrapped view.
|
||||
*/
|
||||
@SuppressWarnings("unchecked") public Node add(N newChild, Kind kind) {
|
||||
Node n = buildTree(newChild, kind);
|
||||
if ( n == null ) return null;
|
||||
n.parent = this;
|
||||
((List)children).add(n);
|
||||
return n;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reparses the AST node represented by this node. Any existing nodes that occupy a different space in the AST are rehomed, any
|
||||
* nodes that no longer exist are removed, and new nodes are created.
|
||||
*
|
||||
* Careful - the node you call this on must not itself have been removed or rehomed - it rebuilds <i>all children</i>.
|
||||
*/
|
||||
public void rebuild() {
|
||||
Map<N, Node> oldNodes = new IdentityHashMap<N, Node>();
|
||||
gatherAndRemoveChildren(oldNodes);
|
||||
|
||||
Node newNode = buildTree(get(), kind);
|
||||
|
||||
replaceNewWithExistingOld(oldNodes, newNode);
|
||||
}
|
||||
|
||||
private void gatherAndRemoveChildren(Map<N, Node> map) {
|
||||
for ( Node child : children ) child.gatherAndRemoveChildren(map);
|
||||
identityDetector.remove(get());
|
||||
map.put(get(), this);
|
||||
children.clear();
|
||||
nodeMap.remove(get());
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes the stated node, which must be a direct child of this node, from the AST.
|
||||
*
|
||||
* Does not change the underlying (javac/Eclipse) AST, only the wrapped view.
|
||||
*/
|
||||
public void removeChild(Node child) {
|
||||
children.remove(child);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the handled flag on this node, and all child nodes, then returns this.
|
||||
*
|
||||
* @see #handled
|
||||
*/
|
||||
public Node recursiveSetHandled() {
|
||||
this.handled = true;
|
||||
for ( Node child : children ) child.recursiveSetHandled();
|
||||
return this;
|
||||
}
|
||||
|
||||
/** Generate a compiler error on this node. */
|
||||
public abstract void addError(String message);
|
||||
|
||||
/** Generate a compiler warning on this node. */
|
||||
public abstract void addWarning(String message);
|
||||
|
||||
/**
|
||||
* 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;
|
||||
}
|
||||
}
|
||||
|
||||
/** Build an AST.Node object for the stated internal (javac/Eclipse) AST Node object. */
|
||||
protected abstract Node buildTree(N item, Kind kind);
|
||||
protected abstract L buildTree(N item, Kind kind);
|
||||
|
||||
/**
|
||||
* Represents a field that contains AST children.
|
||||
@@ -420,7 +168,7 @@ public abstract class AST<N> {
|
||||
*/
|
||||
protected Collection<FieldAccess> fieldsOf(Class<?> c) {
|
||||
Collection<FieldAccess> fields = fieldsOfASTClasses.get(c);
|
||||
if ( fields != null ) return fields;
|
||||
if (fields != null) return fields;
|
||||
|
||||
fields = new ArrayList<FieldAccess>();
|
||||
getFields(c, fields);
|
||||
@@ -429,26 +177,26 @@ public abstract class AST<N> {
|
||||
}
|
||||
|
||||
private void getFields(Class<?> c, Collection<FieldAccess> fields) {
|
||||
if ( c == Object.class || c == null ) return;
|
||||
for ( Field f : c.getDeclaredFields() ) {
|
||||
if ( Modifier.isStatic(f.getModifiers()) ) continue;
|
||||
if (c == Object.class || c == null) return;
|
||||
for (Field f : c.getDeclaredFields()) {
|
||||
if (Modifier.isStatic(f.getModifiers())) continue;
|
||||
Class<?> t = f.getType();
|
||||
int dim = 0;
|
||||
|
||||
if ( t.isArray() ) {
|
||||
while ( t.isArray() ) {
|
||||
if (t.isArray()) {
|
||||
while (t.isArray()) {
|
||||
dim++;
|
||||
t = t.getComponentType();
|
||||
}
|
||||
} else if ( Collection.class.isAssignableFrom(t) ) {
|
||||
while ( Collection.class.isAssignableFrom(t) ) {
|
||||
} else {
|
||||
while (Collection.class.isAssignableFrom(t)) {
|
||||
dim++;
|
||||
t = getComponentType(f.getGenericType());
|
||||
}
|
||||
}
|
||||
|
||||
for ( Class<?> statementType : getStatementTypes() ) {
|
||||
if ( statementType.isAssignableFrom(t) ) {
|
||||
for (Class<?> statementType : getStatementTypes()) {
|
||||
if (statementType.isAssignableFrom(t)) {
|
||||
f.setAccessible(true);
|
||||
fields.add(new FieldAccess(f, dim));
|
||||
break;
|
||||
@@ -459,10 +207,12 @@ public abstract class AST<N> {
|
||||
}
|
||||
|
||||
private Class<?> getComponentType(Type type) {
|
||||
if ( type instanceof ParameterizedType ) {
|
||||
if (type instanceof ParameterizedType) {
|
||||
Type component = ((ParameterizedType)type).getActualTypeArguments()[0];
|
||||
return component instanceof Class<?> ? (Class<?>)component : Object.class;
|
||||
} else return Object.class;
|
||||
} else {
|
||||
return Object.class;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -473,8 +223,8 @@ public abstract class AST<N> {
|
||||
/**
|
||||
* buildTree implementation that uses reflection to find all child nodes by way of inspecting
|
||||
* the fields. */
|
||||
protected <T extends Node> Collection<T> buildWithField(Class<T> nodeType, N statement, FieldAccess fa) {
|
||||
List<T> list = new ArrayList<T>();
|
||||
protected Collection<L> buildWithField(Class<L> nodeType, N statement, FieldAccess fa) {
|
||||
List<L> list = new ArrayList<L>();
|
||||
buildWithField0(nodeType, statement, fa, list);
|
||||
return list;
|
||||
}
|
||||
@@ -483,8 +233,8 @@ public abstract class AST<N> {
|
||||
* Uses reflection to find the given direct child on the given statement, and replace it with a new child.
|
||||
*/
|
||||
protected boolean replaceStatementInNode(N statement, N oldN, N newN) {
|
||||
for ( FieldAccess fa : fieldsOf(statement.getClass()) ) {
|
||||
if ( replaceStatementInField(fa, statement, oldN, newN) ) return true;
|
||||
for (FieldAccess fa : fieldsOf(statement.getClass())) {
|
||||
if (replaceStatementInField(fa, statement, oldN, newN)) return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
@@ -493,42 +243,42 @@ public abstract class AST<N> {
|
||||
private boolean replaceStatementInField(FieldAccess fa, N statement, N oldN, N newN) {
|
||||
try {
|
||||
Object o = fa.field.get(statement);
|
||||
if ( o == null ) return false;
|
||||
if (o == null) return false;
|
||||
|
||||
if ( o == oldN ) {
|
||||
if (o == oldN) {
|
||||
fa.field.set(statement, newN);
|
||||
return true;
|
||||
}
|
||||
|
||||
if ( fa.dim > 0 ) {
|
||||
if ( o.getClass().isArray() ) {
|
||||
if (fa.dim > 0) {
|
||||
if (o.getClass().isArray()) {
|
||||
return replaceStatementInArray(o, oldN, newN);
|
||||
} else if ( Collection.class.isInstance(o) ) {
|
||||
} else if (Collection.class.isInstance(o)) {
|
||||
return replaceStatementInCollection(fa.field, statement, new ArrayList<Collection<?>>(), (Collection<?>)o, oldN, newN);
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
} catch ( IllegalAccessException e ) {
|
||||
} catch (IllegalAccessException e) {
|
||||
throw sneakyThrow(e);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private boolean replaceStatementInCollection(Field field, Object fieldRef, List<Collection<?>> chain, Collection<?> collection, N oldN, N newN) throws IllegalAccessException {
|
||||
if ( collection == null ) return false;
|
||||
if (collection == null) return false;
|
||||
|
||||
int idx = -1;
|
||||
for ( Object o : collection ) {
|
||||
for (Object o : collection) {
|
||||
idx++;
|
||||
if ( o == null ) continue;
|
||||
if ( Collection.class.isInstance(o) ) {
|
||||
if (o == null) continue;
|
||||
if (Collection.class.isInstance(o)) {
|
||||
Collection<?> newC = (Collection<?>)o;
|
||||
List<Collection<?>> newChain = new ArrayList<Collection<?>>(chain);
|
||||
newChain.add(newC);
|
||||
if ( replaceStatementInCollection(field, fieldRef, newChain, newC, oldN, newN) ) return true;
|
||||
if (replaceStatementInCollection(field, fieldRef, newChain, newC, oldN, newN)) return true;
|
||||
}
|
||||
if ( o == oldN ) {
|
||||
if (o == oldN) {
|
||||
setElementInASTCollection(field, fieldRef, chain, collection, idx, newN);
|
||||
return true;
|
||||
}
|
||||
@@ -540,21 +290,21 @@ public abstract class AST<N> {
|
||||
/** Override if your AST collection does not support the set method. Javac's for example, does not. */
|
||||
@SuppressWarnings("unchecked")
|
||||
protected void setElementInASTCollection(Field field, Object fieldRef, List<Collection<?>> chain, Collection<?> collection, int idx, N newN) throws IllegalAccessException {
|
||||
if ( collection instanceof List<?> ) {
|
||||
if (collection instanceof List<?>) {
|
||||
((List)collection).set(idx, newN);
|
||||
}
|
||||
}
|
||||
|
||||
private boolean replaceStatementInArray(Object array, N oldN, N newN) {
|
||||
if ( array == null ) return false;
|
||||
if (array == null) return false;
|
||||
|
||||
int len = Array.getLength(array);
|
||||
for ( int i = 0 ; i < len ; i++ ) {
|
||||
for (int i = 0; i < len; i++) {
|
||||
Object o = Array.get(array, i);
|
||||
if ( o == null ) continue;
|
||||
if ( o.getClass().isArray() ) {
|
||||
if ( replaceStatementInArray(o, oldN, newN) ) return true;
|
||||
} else if ( o == oldN ) {
|
||||
if (o == null) continue;
|
||||
if (o.getClass().isArray()) {
|
||||
if (replaceStatementInArray(o, oldN, newN)) return true;
|
||||
} else if (o == oldN) {
|
||||
Array.set(array, i, newN);
|
||||
return true;
|
||||
}
|
||||
@@ -564,39 +314,46 @@ public abstract class AST<N> {
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private <T extends Node> void buildWithField0(Class<T> nodeType, N child, FieldAccess fa, Collection<T> list) {
|
||||
private void buildWithField0(Class<L> nodeType, N child, FieldAccess fa, Collection<L> list) {
|
||||
try {
|
||||
Object o = fa.field.get(child);
|
||||
if ( o == null ) return;
|
||||
if ( fa.dim == 0 ) {
|
||||
Node node = buildTree((N)o, Kind.STATEMENT);
|
||||
if ( node != null ) list.add(nodeType.cast(node));
|
||||
} else if ( o.getClass().isArray() ) buildWithArray(nodeType, o, list, fa.dim);
|
||||
else if ( Collection.class.isInstance(o) ) buildWithCollection(nodeType, o, list, fa.dim);
|
||||
} catch ( IllegalAccessException e ) {
|
||||
if (o == null) return;
|
||||
if (fa.dim == 0) {
|
||||
L node = buildTree((N)o, Kind.STATEMENT);
|
||||
if (node != null) list.add(nodeType.cast(node));
|
||||
} else if (o.getClass().isArray()) {
|
||||
buildWithArray(nodeType, o, list, fa.dim);
|
||||
} else if (Collection.class.isInstance(o)) {
|
||||
buildWithCollection(nodeType, o, list, fa.dim);
|
||||
}
|
||||
} catch (IllegalAccessException e) {
|
||||
sneakyThrow(e);
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private <T extends Node> void buildWithArray(Class<T> nodeType, Object array, Collection<T> list, int dim) {
|
||||
if ( dim == 1 ) for ( Object v : (Object[])array ) {
|
||||
if ( v == null ) continue;
|
||||
Node node = buildTree((N)v, Kind.STATEMENT);
|
||||
if ( node != null ) list.add(nodeType.cast(node));
|
||||
} else for ( Object v : (Object[])array ) {
|
||||
if ( v == null ) return;
|
||||
buildWithArray(nodeType, v, list, dim-1);
|
||||
private void buildWithArray(Class<L> nodeType, Object array, Collection<L> list, int dim) {
|
||||
if (dim == 1) {
|
||||
for (Object v : (Object[])array) {
|
||||
if (v == null) continue;
|
||||
L node = buildTree((N)v, Kind.STATEMENT);
|
||||
if (node != null) list.add(nodeType.cast(node));
|
||||
}
|
||||
} else for (Object v : (Object[])array) {
|
||||
if (v == null) return;
|
||||
buildWithArray(nodeType, v, list, dim -1);
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private <T extends Node> void buildWithCollection(Class<T> nodeType, Object collection, Collection<T> list, int dim) {
|
||||
if ( dim == 1 ) for ( Object v : (Collection<?>)collection ) {
|
||||
if ( v == null ) continue;
|
||||
Node node = buildTree((N)v, Kind.STATEMENT);
|
||||
if ( node != null ) list.add(nodeType.cast(node));
|
||||
} else for ( Object v : (Collection<?>)collection ) {
|
||||
private void buildWithCollection(Class<L> nodeType, Object collection, Collection<L> list, int dim) {
|
||||
if (dim == 1) {
|
||||
for (Object v : (Collection<?>)collection) {
|
||||
if (v == null) continue;
|
||||
L node = buildTree((N)v, Kind.STATEMENT);
|
||||
if (node != null) list.add(nodeType.cast(node));
|
||||
}
|
||||
} else for (Object v : (Collection<?>)collection) {
|
||||
buildWithCollection(nodeType, v, list, dim-1);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -37,7 +37,7 @@ import java.util.Map;
|
||||
public class AnnotationValues<A extends Annotation> {
|
||||
private final Class<A> type;
|
||||
private final Map<String, AnnotationValue> values;
|
||||
private final AST<?>.Node ast;
|
||||
private final LombokNode<?, ?, ?> ast;
|
||||
|
||||
/**
|
||||
* Represents a single method on the annotation class. For example, the value() method on the Getter annotation.
|
||||
@@ -49,7 +49,7 @@ public class AnnotationValues<A extends Annotation> {
|
||||
/** Guesses for each raw expression. If the raw expression is a literal expression, the guess will
|
||||
* likely be right. If not, it'll be wrong. */
|
||||
public final List<Object> valueGuesses;
|
||||
private final AST<?>.Node node;
|
||||
private final LombokNode<?, ?, ?> node;
|
||||
private final boolean isExplicit;
|
||||
|
||||
/**
|
||||
@@ -59,7 +59,7 @@ public class AnnotationValues<A extends Annotation> {
|
||||
* For classes, supply the class name (qualified or not) as a string.<br />
|
||||
* For enums, supply the simple name part (everything after the last dot) as a string.<br />
|
||||
*/
|
||||
public AnnotationValue(AST<?>.Node node, String raw, Object valueGuess, boolean isExplicit) {
|
||||
public AnnotationValue(LombokNode<?, ?, ?> node, String raw, Object valueGuess, boolean isExplicit) {
|
||||
this.node = node;
|
||||
this.raws = Collections.singletonList(raw);
|
||||
this.valueGuesses = Collections.singletonList(valueGuess);
|
||||
@@ -69,7 +69,7 @@ public class AnnotationValues<A extends Annotation> {
|
||||
/**
|
||||
* Like the other constructor, but used for when the annotation method is initialized with an array value.
|
||||
*/
|
||||
public AnnotationValue(AST<?>.Node node, List<String> raws, List<Object> valueGuesses, boolean isExplicit) {
|
||||
public AnnotationValue(LombokNode<?, ?, ?> node, List<String> raws, List<Object> valueGuesses, boolean isExplicit) {
|
||||
this.node = node;
|
||||
this.raws = raws;
|
||||
this.valueGuesses = valueGuesses;
|
||||
@@ -117,7 +117,7 @@ public class AnnotationValues<A extends Annotation> {
|
||||
* @param values a Map of method names to AnnotationValue instances, for example 'value -> annotationValue instance'.
|
||||
* @param ast The Annotation node.
|
||||
*/
|
||||
public AnnotationValues(Class<A> type, Map<String, AnnotationValue> values, AST<?>.Node ast) {
|
||||
public AnnotationValues(Class<A> type, Map<String, AnnotationValue> values, LombokNode<?, ?, ?> ast) {
|
||||
this.type = type;
|
||||
this.values = values;
|
||||
this.ast = ast;
|
||||
@@ -162,50 +162,50 @@ public class AnnotationValues<A extends Annotation> {
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public A getInstance() {
|
||||
if ( cachedInstance != null ) return cachedInstance;
|
||||
if (cachedInstance != null) return cachedInstance;
|
||||
InvocationHandler invocations = new InvocationHandler() {
|
||||
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
|
||||
AnnotationValue v = values.get(method.getName());
|
||||
if ( v == null ) {
|
||||
if (v == null) {
|
||||
Object defaultValue = method.getDefaultValue();
|
||||
if ( defaultValue != null ) return defaultValue;
|
||||
if (defaultValue != null) return defaultValue;
|
||||
throw makeNoDefaultFail(v, method);
|
||||
}
|
||||
|
||||
boolean isArray = false;
|
||||
Class<?> expected = method.getReturnType();
|
||||
Object array = null;
|
||||
if ( expected.isArray() ) {
|
||||
if (expected.isArray()) {
|
||||
isArray = true;
|
||||
expected = expected.getComponentType();
|
||||
array = Array.newInstance(expected, v.valueGuesses.size());
|
||||
}
|
||||
|
||||
if ( !isArray && v.valueGuesses.size() > 1 ) {
|
||||
if (!isArray && v.valueGuesses.size() > 1) {
|
||||
throw new AnnotationValueDecodeFail(v,
|
||||
"Expected a single value, but " + method.getName() + " has an array of values", -1);
|
||||
}
|
||||
|
||||
if ( v.valueGuesses.size() == 0 && !isArray ) {
|
||||
if (v.valueGuesses.size() == 0 && !isArray) {
|
||||
Object defaultValue = method.getDefaultValue();
|
||||
if ( defaultValue == null ) throw makeNoDefaultFail(v, method);
|
||||
if (defaultValue == null) throw makeNoDefaultFail(v, method);
|
||||
return defaultValue;
|
||||
}
|
||||
|
||||
int idx = 0;
|
||||
for ( Object guess : v.valueGuesses ) {
|
||||
for (Object guess : v.valueGuesses) {
|
||||
Object result = guess == null ? null : guessToType(guess, expected, v, idx);
|
||||
if ( !isArray ) {
|
||||
if ( result == null ) {
|
||||
if (!isArray) {
|
||||
if (result == null) {
|
||||
Object defaultValue = method.getDefaultValue();
|
||||
if ( defaultValue == null ) throw makeNoDefaultFail(v, method);
|
||||
if (defaultValue == null) throw makeNoDefaultFail(v, method);
|
||||
return defaultValue;
|
||||
} else return result;
|
||||
} else {
|
||||
if ( result == null ) {
|
||||
if ( v.valueGuesses.size() == 1 ) {
|
||||
if (result == null) {
|
||||
if (v.valueGuesses.size() == 1) {
|
||||
Object defaultValue = method.getDefaultValue();
|
||||
if ( defaultValue == null ) throw makeNoDefaultFail(v, method);
|
||||
if (defaultValue == null) throw makeNoDefaultFail(v, method);
|
||||
return defaultValue;
|
||||
} else throw new AnnotationValueDecodeFail(v,
|
||||
"I can't make sense of this annotation value. Try using a fully qualified literal.", idx);
|
||||
@@ -222,69 +222,69 @@ public class AnnotationValues<A extends Annotation> {
|
||||
}
|
||||
|
||||
private Object guessToType(Object guess, Class<?> expected, AnnotationValue v, int pos) {
|
||||
if ( expected == int.class ) {
|
||||
if ( guess instanceof Integer || guess instanceof Short || guess instanceof Byte ) {
|
||||
if (expected == int.class) {
|
||||
if (guess instanceof Integer || guess instanceof Short || guess instanceof Byte) {
|
||||
return ((Number)guess).intValue();
|
||||
}
|
||||
}
|
||||
|
||||
if ( expected == long.class ) {
|
||||
if ( guess instanceof Long || guess instanceof Integer || guess instanceof Short || guess instanceof Byte ) {
|
||||
if (expected == long.class) {
|
||||
if (guess instanceof Long || guess instanceof Integer || guess instanceof Short || guess instanceof Byte) {
|
||||
return ((Number)guess).longValue();
|
||||
}
|
||||
}
|
||||
|
||||
if ( expected == short.class ) {
|
||||
if ( guess instanceof Integer || guess instanceof Short || guess instanceof Byte ) {
|
||||
if (expected == short.class) {
|
||||
if (guess instanceof Integer || guess instanceof Short || guess instanceof Byte) {
|
||||
int intVal = ((Number)guess).intValue();
|
||||
int shortVal = ((Number)guess).shortValue();
|
||||
if ( shortVal == intVal ) return shortVal;
|
||||
if (shortVal == intVal) return shortVal;
|
||||
}
|
||||
}
|
||||
|
||||
if ( expected == byte.class ) {
|
||||
if ( guess instanceof Integer || guess instanceof Short || guess instanceof Byte ) {
|
||||
if (expected == byte.class) {
|
||||
if (guess instanceof Integer || guess instanceof Short || guess instanceof Byte) {
|
||||
int intVal = ((Number)guess).intValue();
|
||||
int byteVal = ((Number)guess).byteValue();
|
||||
if ( byteVal == intVal ) return byteVal;
|
||||
if (byteVal == intVal) return byteVal;
|
||||
}
|
||||
}
|
||||
|
||||
if ( expected == double.class ) {
|
||||
if ( guess instanceof Number ) return ((Number)guess).doubleValue();
|
||||
if (expected == double.class) {
|
||||
if (guess instanceof Number) return ((Number)guess).doubleValue();
|
||||
}
|
||||
|
||||
if ( expected == float.class ) {
|
||||
if ( guess instanceof Number ) return ((Number)guess).floatValue();
|
||||
if (expected == float.class) {
|
||||
if (guess instanceof Number) return ((Number)guess).floatValue();
|
||||
}
|
||||
|
||||
if ( expected == boolean.class ) {
|
||||
if ( guess instanceof Boolean ) return ((Boolean)guess).booleanValue();
|
||||
if (expected == boolean.class) {
|
||||
if (guess instanceof Boolean) return ((Boolean)guess).booleanValue();
|
||||
}
|
||||
|
||||
if ( expected == char.class ) {
|
||||
if ( guess instanceof Character ) return ((Character)guess).charValue();
|
||||
if (expected == char.class) {
|
||||
if (guess instanceof Character) return ((Character)guess).charValue();
|
||||
}
|
||||
|
||||
if ( expected == String.class ) {
|
||||
if ( guess instanceof String ) return guess;
|
||||
if (expected == String.class) {
|
||||
if (guess instanceof String) return guess;
|
||||
}
|
||||
|
||||
if ( Enum.class.isAssignableFrom(expected) ) {
|
||||
if ( guess instanceof String ) {
|
||||
for ( Object enumConstant : expected.getEnumConstants() ) {
|
||||
if (Enum.class.isAssignableFrom(expected) ) {
|
||||
if (guess instanceof String) {
|
||||
for (Object enumConstant : expected.getEnumConstants()) {
|
||||
String target = ((Enum<?>)enumConstant).name();
|
||||
if ( target.equals(guess) ) return enumConstant;
|
||||
if (target.equals(guess)) return enumConstant;
|
||||
}
|
||||
throw new AnnotationValueDecodeFail(v,
|
||||
"Can't translate " + guess + " to an enum of type " + expected, pos);
|
||||
}
|
||||
}
|
||||
|
||||
if ( Class.class == expected ) {
|
||||
if ( guess instanceof String ) try {
|
||||
if (Class.class == expected) {
|
||||
if (guess instanceof String) try {
|
||||
return Class.forName(toFQ((String)guess));
|
||||
} catch ( ClassNotFoundException e ) {
|
||||
} catch (ClassNotFoundException e) {
|
||||
throw new AnnotationValueDecodeFail(v,
|
||||
"Can't translate " + guess + " to a class object.", pos);
|
||||
}
|
||||
@@ -334,7 +334,7 @@ public class AnnotationValues<A extends Annotation> {
|
||||
* The index-th item in the initializer will carry the error (you should only call this method if you know it's there!) */
|
||||
public void setError(String annotationMethodName, String message, int index) {
|
||||
AnnotationValue v = values.get(annotationMethodName);
|
||||
if ( v == null ) return;
|
||||
if (v == null) return;
|
||||
v.setError(message, index);
|
||||
}
|
||||
|
||||
@@ -342,7 +342,7 @@ public class AnnotationValues<A extends Annotation> {
|
||||
* The index-th item in the initializer will carry the error (you should only call this method if you know it's there!) */
|
||||
public void setWarning(String annotationMethodName, String message, int index) {
|
||||
AnnotationValue v = values.get(annotationMethodName);
|
||||
if ( v == null ) return;
|
||||
if (v == null) return;
|
||||
v.setWarning(message, index);
|
||||
}
|
||||
|
||||
@@ -354,9 +354,9 @@ public class AnnotationValues<A extends Annotation> {
|
||||
public List<String> getProbableFQTypes(String annotationMethodName) {
|
||||
List<String> result = new ArrayList<String>();
|
||||
AnnotationValue v = values.get(annotationMethodName);
|
||||
if ( v == null ) return Collections.emptyList();
|
||||
if (v == null) return Collections.emptyList();
|
||||
|
||||
for ( Object o : v.valueGuesses ) result.add(o == null ? null : toFQ(o.toString()));
|
||||
for (Object o : v.valueGuesses) result.add(o == null ? null : toFQ(o.toString()));
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -375,32 +375,32 @@ public class AnnotationValues<A extends Annotation> {
|
||||
boolean fqn = typeName.indexOf('.') > -1;
|
||||
String prefix = fqn ? typeName.substring(0, typeName.indexOf('.')) : typeName;
|
||||
|
||||
for ( String im : ast.getImportStatements() ) {
|
||||
for (String im : ast.getImportStatements()) {
|
||||
int idx = im.lastIndexOf('.');
|
||||
String simple = im;
|
||||
if ( idx > -1 ) simple = im.substring(idx+1);
|
||||
if ( simple.equals(prefix) ) {
|
||||
if (idx > -1) simple = im.substring(idx+1);
|
||||
if (simple.equals(prefix)) {
|
||||
return im + typeName.substring(prefix.length());
|
||||
}
|
||||
}
|
||||
|
||||
c = tryClass(typeName);
|
||||
if ( c != null ) return c.getName();
|
||||
if (c != null) return c.getName();
|
||||
|
||||
c = tryClass("java.lang." + typeName);
|
||||
if ( c != null ) return c.getName();
|
||||
if (c != null) return c.getName();
|
||||
|
||||
//Try star imports
|
||||
for ( String im : ast.getImportStatements() ) {
|
||||
if ( im.endsWith(".*") ) {
|
||||
for (String im : ast.getImportStatements()) {
|
||||
if (im.endsWith(".*")) {
|
||||
c = tryClass(im.substring(0, im.length() -1) + typeName);
|
||||
if ( c != null ) return c.getName();
|
||||
if (c != null) return c.getName();
|
||||
}
|
||||
}
|
||||
|
||||
if ( !fqn ) {
|
||||
if (!fqn) {
|
||||
String pkg = ast.getPackageDeclaration();
|
||||
if ( pkg != null ) return pkg + "." + typeName;
|
||||
if (pkg != null) return pkg + "." + typeName;
|
||||
}
|
||||
|
||||
return null;
|
||||
@@ -409,7 +409,7 @@ public class AnnotationValues<A extends Annotation> {
|
||||
private Class<?> tryClass(String name) {
|
||||
try {
|
||||
return Class.forName(name);
|
||||
} catch ( ClassNotFoundException e ) {
|
||||
} catch (ClassNotFoundException e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,297 @@
|
||||
/*
|
||||
* Copyright © 2009 Reinier Zwitserloot and Roel Spilker.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
package lombok.core;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.IdentityHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import lombok.core.AST.Kind;
|
||||
|
||||
/**
|
||||
* An instance of this class wraps an Eclipse/javac internal node object.
|
||||
*
|
||||
* @param A Type of our owning AST.
|
||||
* @param L self-type.
|
||||
* @param N The common type of all AST nodes in the internal representation of the target platform.
|
||||
* For example, JCTree for javac, and ASTNode for Eclipse.
|
||||
*/
|
||||
public abstract class LombokNode<A extends AST<A, L, N>, L extends LombokNode<A, L, N>, N> {
|
||||
protected final A ast;
|
||||
protected final Kind kind;
|
||||
protected final N node;
|
||||
protected final List<L> children;
|
||||
protected L parent;
|
||||
|
||||
/** This flag has no specified meaning; you can set and retrieve it.
|
||||
*
|
||||
* In practice, for annotation nodes it means: Some AnnotationHandler finished whatever changes were required,
|
||||
* and for all other nodes it means: This node was made by a lombok operation.
|
||||
*/
|
||||
protected boolean handled;
|
||||
|
||||
/** structurally significant are those nodes that can be annotated in java 1.6 or are method-like toplevels,
|
||||
* so fields, local declarations, method arguments, methods, types, the Compilation Unit itself, and initializers. */
|
||||
protected boolean isStructurallySignificant;
|
||||
|
||||
/**
|
||||
* Creates a new Node object that represents the provided node.
|
||||
*
|
||||
* @param ast The owning AST - this node is part of this AST's tree of nodes.
|
||||
* @param node The AST object in the target parser's own internal AST tree that this node object will represent.
|
||||
* @param children A list of child nodes. Passing in null results in the children list being empty, not null.
|
||||
* @param kind The kind of node represented by this object.
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
protected LombokNode(A ast, N node, List<L> children, Kind kind) {
|
||||
this.ast = ast;
|
||||
this.kind = kind;
|
||||
this.node = node;
|
||||
this.children = children == null ? new ArrayList<L>() : children;
|
||||
for (L child : this.children) child.parent = (L) this;
|
||||
this.isStructurallySignificant = calculateIsStructurallySignificant();
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override public String toString() {
|
||||
return String.format("NODE %s (%s) %s%s",
|
||||
kind, node == null ? "(NULL)" : node.getClass(), handled ? "[HANDLED]" : "", node == null ? "" : node);
|
||||
}
|
||||
|
||||
/**
|
||||
* Convenient shortcut to the owning ast object's {@code getPackageDeclaration} method.
|
||||
*
|
||||
* @see AST#getPackageDeclaration()
|
||||
*/
|
||||
public String getPackageDeclaration() {
|
||||
return ast.getPackageDeclaration();
|
||||
}
|
||||
|
||||
/**
|
||||
* Convenient shortcut to the owning ast object's {@code getImportStatements} method.
|
||||
*
|
||||
* @see AST#getImportStatements()
|
||||
*/
|
||||
public Collection<String> getImportStatements() {
|
||||
return ast.getImportStatements();
|
||||
}
|
||||
|
||||
/**
|
||||
* See {@link #isStructurallySignificant}.
|
||||
*/
|
||||
protected abstract boolean calculateIsStructurallySignificant();
|
||||
|
||||
/**
|
||||
* Convenient shortcut to the owning ast object's get method.
|
||||
*
|
||||
* @see AST#get(Object)
|
||||
*/
|
||||
public L getNodeFor(N obj) {
|
||||
return ast.get(obj);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return The javac/Eclipse internal AST object wrapped by this LombokNode object.
|
||||
*/
|
||||
public N get() {
|
||||
return node;
|
||||
}
|
||||
|
||||
/**
|
||||
* Replaces the AST node represented by this node object with the provided node. This node must
|
||||
* have a parent, obviously, for this to work.
|
||||
*
|
||||
* Also affects the underlying (Eclipse/javac) AST.
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public L replaceWith(N newN, Kind kind) {
|
||||
L newNode = ast.buildTree(newN, kind);
|
||||
newNode.parent = parent;
|
||||
for (int i = 0; i < parent.children.size(); i++) {
|
||||
if (parent.children.get(i) == this) ((List)parent.children).set(i, newNode);
|
||||
}
|
||||
|
||||
parent.replaceChildNode(get(), newN);
|
||||
return newNode;
|
||||
}
|
||||
|
||||
/**
|
||||
* Replaces the stated node with a new one. The old node must be a direct child of this node.
|
||||
*
|
||||
* Also affects the underlying (Eclipse/javac) AST.
|
||||
*/
|
||||
public void replaceChildNode(N oldN, N newN) {
|
||||
ast.replaceStatementInNode(get(), oldN, newN);
|
||||
}
|
||||
|
||||
public Kind getKind() {
|
||||
return kind;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the name of your type (simple name), method, field, or local variable. Return null if this
|
||||
* node doesn't really have a name, such as initializers, while statements, etc.
|
||||
*/
|
||||
public abstract String getName();
|
||||
|
||||
/** Returns the structurally significant node that encloses this one.
|
||||
*
|
||||
* @see #isStructurallySignificant()
|
||||
*/
|
||||
public L up() {
|
||||
L result = parent;
|
||||
while (result != null && !result.isStructurallySignificant) result = result.parent;
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 {@code up()} {@code LombokNode} is the {@code Method} that contains it.
|
||||
*/
|
||||
public L directUp() {
|
||||
return parent;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns all children nodes.
|
||||
*
|
||||
* A copy is created, so changing the list has no effect. Also, while iterating through this list,
|
||||
* you may add, remove, or replace children without causing {@code ConcurrentModificationException}s.
|
||||
*/
|
||||
public Collection<L> down() {
|
||||
return new ArrayList<L>(children);
|
||||
}
|
||||
|
||||
/**
|
||||
* returns the value of the 'handled' flag.
|
||||
*
|
||||
* @see #handled
|
||||
*/
|
||||
public boolean isHandled() {
|
||||
return handled;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the handled flag, then returns itself for chaining.
|
||||
*
|
||||
* @see #handled
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public L setHandled() {
|
||||
this.handled = true;
|
||||
return (L)this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convenient shortcut to the owning ast object's top method.
|
||||
*
|
||||
* @see AST#top()
|
||||
*/
|
||||
public L top() {
|
||||
return ast.top();
|
||||
}
|
||||
|
||||
/**
|
||||
* Convenient shortcut to the owning ast object's getFileName method.
|
||||
*
|
||||
* @see AST#getFileName()
|
||||
*/
|
||||
public String getFileName() {
|
||||
return ast.getFileName();
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds the stated node as a direct child of this node.
|
||||
*
|
||||
* Does not change the underlying (javac/Eclipse) AST, only the wrapped view.
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public L add(N newChild, Kind kind) {
|
||||
L n = ast.buildTree(newChild, kind);
|
||||
if (n == null) return null;
|
||||
n.parent = (L) this;
|
||||
((List)children).add(n);
|
||||
return n;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reparses the AST node represented by this node. Any existing nodes that occupy a different space in the AST are rehomed, any
|
||||
* nodes that no longer exist are removed, and new nodes are created.
|
||||
*
|
||||
* Careful - the node you call this on must not itself have been removed or rehomed - it rebuilds <i>all children</i>.
|
||||
*/
|
||||
public void rebuild() {
|
||||
Map<N, L> oldNodes = new IdentityHashMap<N, L>();
|
||||
gatherAndRemoveChildren(oldNodes);
|
||||
|
||||
L newNode = ast.buildTree(get(), kind);
|
||||
|
||||
ast.replaceNewWithExistingOld(oldNodes, newNode);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private void gatherAndRemoveChildren(Map<N, L> map) {
|
||||
for (L child : children) child.gatherAndRemoveChildren(map);
|
||||
ast.identityDetector.remove(get());
|
||||
map.put(get(), (L) this);
|
||||
children.clear();
|
||||
ast.getNodeMap().remove(get());
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes the stated node, which must be a direct child of this node, from the AST.
|
||||
*
|
||||
* Does not change the underlying (javac/Eclipse) AST, only the wrapped view.
|
||||
*/
|
||||
public void removeChild(L child) {
|
||||
children.remove(child);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the handled flag on this node, and all child nodes, then returns itself, for chaining.
|
||||
*
|
||||
* @see #handled
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public L recursiveSetHandled() {
|
||||
this.handled = true;
|
||||
for (L child : children) child.recursiveSetHandled();
|
||||
return (L) this;
|
||||
}
|
||||
|
||||
/** Generate a compiler error on this node. */
|
||||
public abstract void addError(String message);
|
||||
|
||||
/** Generate a compiler warning on this node. */
|
||||
public abstract void addWarning(String message);
|
||||
|
||||
/**
|
||||
* 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;
|
||||
}
|
||||
}
|
||||
@@ -78,7 +78,7 @@ public class SpiLoadUtil {
|
||||
public static <C> Iterable<C> findServices(final Class<C> target, final ClassLoader loader) throws IOException {
|
||||
Enumeration<URL> resources = loader.getResources("META-INF/services/" + target.getName());
|
||||
final Set<String> entries = new LinkedHashSet<String>();
|
||||
while ( resources.hasMoreElements() ) {
|
||||
while (resources.hasMoreElements()) {
|
||||
URL url = resources.nextElement();
|
||||
readServicesFromUrl(entries, url);
|
||||
}
|
||||
@@ -94,7 +94,7 @@ public class SpiLoadUtil {
|
||||
@Override public C next() {
|
||||
try {
|
||||
return target.cast(Class.forName(names.next(), true, loader).newInstance());
|
||||
} catch ( Throwable t ) {
|
||||
} catch (Throwable t) {
|
||||
throw Lombok.sneakyThrow(t);
|
||||
}
|
||||
}
|
||||
@@ -110,19 +110,21 @@ public class SpiLoadUtil {
|
||||
private static void readServicesFromUrl(Collection<String> list, URL url) throws IOException {
|
||||
InputStream in = url.openStream();
|
||||
try {
|
||||
if ( in == null ) return;
|
||||
if (in == null) return;
|
||||
BufferedReader r = new BufferedReader(new InputStreamReader(in, "UTF-8"));
|
||||
while ( true ) {
|
||||
while (true) {
|
||||
String line = r.readLine();
|
||||
if ( line == null ) break;
|
||||
if (line == null) break;
|
||||
int idx = line.indexOf('#');
|
||||
if ( idx != -1 ) line = line.substring(0, idx);
|
||||
if (idx != -1) line = line.substring(0, idx);
|
||||
line = line.trim();
|
||||
if ( line.length() == 0 ) continue;
|
||||
if (line.length() == 0) continue;
|
||||
list.add(line);
|
||||
}
|
||||
} finally {
|
||||
try { in.close(); } catch ( Throwable ignore ) {}
|
||||
try {
|
||||
in.close();
|
||||
} catch (Throwable ignore) {}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -134,14 +136,14 @@ public class SpiLoadUtil {
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public static Class<? extends Annotation> findAnnotationClass(Class<?> c, Class<?> base) {
|
||||
if ( c == Object.class || c == null ) return null;
|
||||
for ( Type iface : c.getGenericInterfaces() ) {
|
||||
if ( iface instanceof ParameterizedType ) {
|
||||
if (c == Object.class || c == null) return null;
|
||||
for (Type iface : c.getGenericInterfaces()) {
|
||||
if (iface instanceof ParameterizedType) {
|
||||
ParameterizedType p = (ParameterizedType)iface;
|
||||
if ( !base.equals(p.getRawType()) ) continue;
|
||||
if (!base.equals(p.getRawType())) continue;
|
||||
Type target = p.getActualTypeArguments()[0];
|
||||
if ( target instanceof Class<?> ) {
|
||||
if ( Annotation.class.isAssignableFrom((Class<?>) target) ) {
|
||||
if (target instanceof Class<?>) {
|
||||
if (Annotation.class.isAssignableFrom((Class<?>) target)) {
|
||||
return (Class<? extends Annotation>) target;
|
||||
}
|
||||
}
|
||||
@@ -151,10 +153,10 @@ public class SpiLoadUtil {
|
||||
}
|
||||
|
||||
Class<? extends Annotation> potential = findAnnotationClass(c.getSuperclass(), base);
|
||||
if ( potential != null ) return potential;
|
||||
for ( Class<?> iface : c.getInterfaces() ) {
|
||||
if (potential != null) return potential;
|
||||
for (Class<?> iface : c.getInterfaces()) {
|
||||
potential = findAnnotationClass(iface, base);
|
||||
if ( potential != null ) return potential;
|
||||
if (potential != null) return potential;
|
||||
}
|
||||
|
||||
return null;
|
||||
|
||||
@@ -64,12 +64,12 @@ public class TransformationsUtil {
|
||||
public static String toGetterName(CharSequence fieldName, boolean isBoolean) {
|
||||
final String prefix = isBoolean ? "is" : "get";
|
||||
|
||||
if ( fieldName.length() == 0 ) return prefix;
|
||||
if (fieldName.length() == 0) return prefix;
|
||||
|
||||
for ( String knownBooleanPrefix : KNOWN_BOOLEAN_PREFIXES ) {
|
||||
if ( !fieldName.toString().startsWith(knownBooleanPrefix) ) continue;
|
||||
if ( fieldName.length() > knownBooleanPrefix.length() &&
|
||||
!Character.isLowerCase(fieldName.charAt(knownBooleanPrefix.length())) ) {
|
||||
for (String knownBooleanPrefix : KNOWN_BOOLEAN_PREFIXES) {
|
||||
if (!fieldName.toString().startsWith(knownBooleanPrefix)) continue;
|
||||
if (fieldName.length() > knownBooleanPrefix.length() &&
|
||||
!Character.isLowerCase(fieldName.charAt(knownBooleanPrefix.length()))) {
|
||||
//The field is called something like 'isFoo' or 'hasFoo' or 'getFoo', so we shouldn't
|
||||
//prefix with 'is' but instead just use the field name as is. The isLowerCase check is so we don't turn
|
||||
//hashCodeGenerated, which so happens to start with 'has', into hasHCodeGenerated instead of isHashCodeGenerated.
|
||||
@@ -103,10 +103,10 @@ public class TransformationsUtil {
|
||||
}
|
||||
|
||||
private static String buildName(String prefix, String suffix) {
|
||||
if ( suffix.length() == 0 ) return prefix;
|
||||
if (suffix.length() == 0) return prefix;
|
||||
|
||||
char first = suffix.charAt(0);
|
||||
if ( Character.isLowerCase(first) ) {
|
||||
if (Character.isLowerCase(first)) {
|
||||
boolean useUpperCase = suffix.length() > 2 &&
|
||||
(Character.isTitleCase(suffix.charAt(1)) || Character.isUpperCase(suffix.charAt(1)));
|
||||
suffix = String.format("%s%s",
|
||||
@@ -117,14 +117,14 @@ public class TransformationsUtil {
|
||||
}
|
||||
|
||||
public static List<String> toAllGetterNames(CharSequence fieldName, boolean isBoolean) {
|
||||
if ( !isBoolean ) return Collections.singletonList(toGetterName(fieldName, false));
|
||||
if (!isBoolean) return Collections.singletonList(toGetterName(fieldName, false));
|
||||
|
||||
List<String> baseNames = new ArrayList<String>();
|
||||
baseNames.add(fieldName.toString());
|
||||
for ( String knownBooleanPrefix : KNOWN_BOOLEAN_PREFIXES ) {
|
||||
if ( !fieldName.toString().startsWith(knownBooleanPrefix) ) continue;
|
||||
if ( fieldName.length() > knownBooleanPrefix.length() &&
|
||||
!Character.isLowerCase(fieldName.charAt(knownBooleanPrefix.length())) ) {
|
||||
for (String knownBooleanPrefix : KNOWN_BOOLEAN_PREFIXES) {
|
||||
if (!fieldName.toString().startsWith(knownBooleanPrefix)) continue;
|
||||
if (fieldName.length() > knownBooleanPrefix.length() &&
|
||||
!Character.isLowerCase(fieldName.charAt(knownBooleanPrefix.length()))) {
|
||||
//The field is called something like 'isFoo' or 'hasFoo' or 'getFoo', so the practical fieldname
|
||||
//could also be 'foo'.
|
||||
baseNames.add(fieldName.toString().substring(knownBooleanPrefix.length()));
|
||||
@@ -134,12 +134,12 @@ public class TransformationsUtil {
|
||||
}
|
||||
|
||||
Set<String> names = new HashSet<String>();
|
||||
for ( String baseName : baseNames ) {
|
||||
if ( baseName.length() > 0 && Character.isLowerCase(baseName.charAt(0)) ) {
|
||||
for (String baseName : baseNames) {
|
||||
if (baseName.length() > 0 && Character.isLowerCase(baseName.charAt(0))) {
|
||||
baseName = Character.toTitleCase(baseName.charAt(0)) + baseName.substring(1);
|
||||
}
|
||||
|
||||
for ( String prefix : KNOWN_BOOLEAN_PREFIXES ) {
|
||||
for (String prefix : KNOWN_BOOLEAN_PREFIXES) {
|
||||
names.add(prefix + baseName);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -47,13 +47,13 @@ public class TypeLibrary {
|
||||
*/
|
||||
public void addType(String fullyQualifiedTypeName) {
|
||||
int idx = fullyQualifiedTypeName.lastIndexOf('.');
|
||||
if ( idx == -1 ) throw new IllegalArgumentException(
|
||||
if (idx == -1) throw new IllegalArgumentException(
|
||||
"Only fully qualified types are allowed (and stuff in the default package is not palatable to us either!)");
|
||||
|
||||
final String simpleName = fullyQualifiedTypeName.substring(idx +1);
|
||||
final String packageName = fullyQualifiedTypeName.substring(0, idx);
|
||||
|
||||
if ( simpleToQualifiedMap.put(fullyQualifiedTypeName, Collections.singleton(fullyQualifiedTypeName)) != null ) return;
|
||||
if (simpleToQualifiedMap.put(fullyQualifiedTypeName, Collections.singleton(fullyQualifiedTypeName)) != null) return;
|
||||
|
||||
addToMap(simpleName, fullyQualifiedTypeName);
|
||||
addToMap(packageName + ".*", fullyQualifiedTypeName);
|
||||
|
||||
@@ -46,7 +46,7 @@ public class TypeResolver {
|
||||
|
||||
private static Collection<String> makeImportList(String packageString, Collection<String> importStrings) {
|
||||
Set<String> imports = new HashSet<String>();
|
||||
if ( packageString != null ) imports.add(packageString + ".*");
|
||||
if (packageString != null) imports.add(packageString + ".*");
|
||||
imports.addAll(importStrings == null ? Collections.<String>emptySet() : importStrings);
|
||||
return imports;
|
||||
}
|
||||
@@ -56,27 +56,27 @@ public class TypeResolver {
|
||||
* that shadow type names listed in import statements. If such a shadowing occurs, no matches are returned
|
||||
* for any shadowed types, as you would expect.
|
||||
*/
|
||||
public Collection<String> findTypeMatches(AST<?>.Node context, String typeRef) {
|
||||
public Collection<String> findTypeMatches(LombokNode<?, ?, ?> context, String typeRef) {
|
||||
Collection<String> potentialMatches = library.findCompatible(typeRef);
|
||||
if ( potentialMatches.isEmpty() ) return Collections.emptyList();
|
||||
if (potentialMatches.isEmpty()) return Collections.emptyList();
|
||||
|
||||
int idx = typeRef.indexOf('.');
|
||||
if ( idx > -1 ) return potentialMatches;
|
||||
if (idx > -1) return potentialMatches;
|
||||
String simpleName = typeRef.substring(idx+1);
|
||||
|
||||
//If there's an import statement that explicitly imports a 'Getter' that isn't any of our potentials, return no matches.
|
||||
if ( nameConflictInImportList(simpleName, potentialMatches) ) return Collections.emptyList();
|
||||
if (nameConflictInImportList(simpleName, potentialMatches)) return Collections.emptyList();
|
||||
|
||||
//Check if any of our potentials is even imported in the first place. If not: no matches.
|
||||
potentialMatches = eliminateImpossibleMatches(potentialMatches);
|
||||
if ( potentialMatches.isEmpty() ) return Collections.emptyList();
|
||||
if (potentialMatches.isEmpty()) return Collections.emptyList();
|
||||
|
||||
//Find a lexically accessible type of the same simple name in the same Compilation Unit. If it exists: no matches.
|
||||
AST<?>.Node n = context;
|
||||
while ( n != null ) {
|
||||
if ( n.getKind() == Kind.TYPE ) {
|
||||
LombokNode<?, ?, ?> n = context;
|
||||
while (n != null) {
|
||||
if (n.getKind() == Kind.TYPE) {
|
||||
String name = n.getName();
|
||||
if ( name != null && name.equals(simpleName) ) return Collections.emptyList();
|
||||
if (name != null && name.equals(simpleName)) return Collections.emptyList();
|
||||
}
|
||||
n = n.up();
|
||||
}
|
||||
@@ -88,7 +88,7 @@ public class TypeResolver {
|
||||
private Collection<String> eliminateImpossibleMatches(Collection<String> potentialMatches) {
|
||||
Set<String> results = new HashSet<String>();
|
||||
|
||||
for ( String importedType : imports ) {
|
||||
for (String importedType : imports) {
|
||||
Collection<String> reduced = new HashSet<String>(library.findCompatible(importedType));
|
||||
reduced.retainAll(potentialMatches);
|
||||
results.addAll(reduced);
|
||||
@@ -98,9 +98,9 @@ public class TypeResolver {
|
||||
}
|
||||
|
||||
private boolean nameConflictInImportList(String simpleName, Collection<String> potentialMatches) {
|
||||
for ( String importedType : imports ) {
|
||||
if ( !toSimpleName(importedType).equals(simpleName) ) continue;
|
||||
if ( potentialMatches.contains(importedType) ) continue;
|
||||
for (String importedType : imports) {
|
||||
if (!toSimpleName(importedType).equals(simpleName)) continue;
|
||||
if (potentialMatches.contains(importedType)) continue;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -36,7 +36,6 @@ import lombok.core.TypeLibrary;
|
||||
import lombok.core.TypeResolver;
|
||||
import lombok.core.AST.Kind;
|
||||
import lombok.core.AnnotationValues.AnnotationValue;
|
||||
import lombok.eclipse.EclipseAST.Node;
|
||||
|
||||
import org.eclipse.core.runtime.ILog;
|
||||
import org.eclipse.core.runtime.IStatus;
|
||||
@@ -107,7 +106,7 @@ public class Eclipse {
|
||||
*/
|
||||
public static void error(CompilationUnitDeclaration cud, String message, String bundleName, Throwable error) {
|
||||
Bundle bundle = Platform.getBundle(bundleName);
|
||||
if ( bundle == null ) {
|
||||
if (bundle == null) {
|
||||
System.err.printf("Can't find bundle %s while trying to report error:\n%s\n", bundleName, message);
|
||||
return;
|
||||
}
|
||||
@@ -115,7 +114,7 @@ public class Eclipse {
|
||||
ILog log = Platform.getLog(bundle);
|
||||
|
||||
log.log(new Status(IStatus.ERROR, bundleName, message, error));
|
||||
if ( cud != null ) EclipseAST.addProblemToCompilationResult(cud, false, message + " - See error log.", 0, 0);
|
||||
if (cud != null) EclipseAST.addProblemToCompilationResult(cud, false, message + " - See error log.", 0, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -125,7 +124,7 @@ public class Eclipse {
|
||||
public static String toQualifiedName(char[][] typeName) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
boolean first = true;
|
||||
for ( char[] c : typeName ) {
|
||||
for (char[] c : typeName) {
|
||||
sb.append(first ? "" : ".").append(c);
|
||||
first = false;
|
||||
}
|
||||
@@ -148,10 +147,10 @@ public class Eclipse {
|
||||
* is complicated and there's no clone method on TypeParameter itself. This method can clone them.
|
||||
*/
|
||||
public static TypeParameter[] copyTypeParams(TypeParameter[] params, ASTNode source) {
|
||||
if ( params == null ) return null;
|
||||
if (params == null) return null;
|
||||
TypeParameter[] out = new TypeParameter[params.length];
|
||||
int idx = 0;
|
||||
for ( TypeParameter param : params ) {
|
||||
for (TypeParameter param : params) {
|
||||
TypeParameter o = new TypeParameter();
|
||||
setGeneratedBy(o, source);
|
||||
o.annotations = param.annotations;
|
||||
@@ -164,10 +163,10 @@ public class Eclipse {
|
||||
o.declarationEnd = param.declarationEnd;
|
||||
o.declarationSourceStart = param.declarationSourceStart;
|
||||
o.declarationSourceEnd = param.declarationSourceEnd;
|
||||
if ( param.bounds != null ) {
|
||||
if (param.bounds != null) {
|
||||
TypeReference[] b = new TypeReference[param.bounds.length];
|
||||
int idx2 = 0;
|
||||
for ( TypeReference ref : param.bounds ) b[idx2++] = copyType(ref, source);
|
||||
for (TypeReference ref : param.bounds) b[idx2++] = copyType(ref, source);
|
||||
o.bounds = b;
|
||||
}
|
||||
out[idx++] = o;
|
||||
@@ -180,10 +179,10 @@ public class Eclipse {
|
||||
* {@link #copyType(TypeReference)}.
|
||||
*/
|
||||
public static TypeReference[] copyTypes(TypeReference[] refs, ASTNode source) {
|
||||
if ( refs == null ) return null;
|
||||
if (refs == null) return null;
|
||||
TypeReference[] outs = new TypeReference[refs.length];
|
||||
int idx = 0;
|
||||
for ( TypeReference ref : refs ) {
|
||||
for (TypeReference ref : refs) {
|
||||
outs[idx++] = copyType(ref, source);
|
||||
}
|
||||
return outs;
|
||||
@@ -195,18 +194,18 @@ public class Eclipse {
|
||||
* method on TypeReference itself. This method can clone them.
|
||||
*/
|
||||
public static TypeReference copyType(TypeReference ref, ASTNode source) {
|
||||
if ( ref instanceof ParameterizedQualifiedTypeReference ) {
|
||||
if (ref instanceof ParameterizedQualifiedTypeReference) {
|
||||
ParameterizedQualifiedTypeReference iRef = (ParameterizedQualifiedTypeReference) ref;
|
||||
TypeReference[][] args = null;
|
||||
if ( iRef.typeArguments != null ) {
|
||||
if (iRef.typeArguments != null) {
|
||||
args = new TypeReference[iRef.typeArguments.length][];
|
||||
int idx = 0;
|
||||
for ( TypeReference[] inRefArray : iRef.typeArguments ) {
|
||||
if ( inRefArray == null ) args[idx++] = null;
|
||||
for (TypeReference[] inRefArray : iRef.typeArguments) {
|
||||
if (inRefArray == null) args[idx++] = null;
|
||||
else {
|
||||
TypeReference[] outRefArray = new TypeReference[inRefArray.length];
|
||||
int idx2 = 0;
|
||||
for ( TypeReference inRef : inRefArray ) {
|
||||
for (TypeReference inRef : inRefArray) {
|
||||
outRefArray[idx2++] = copyType(inRef, source);
|
||||
}
|
||||
args[idx++] = outRefArray;
|
||||
@@ -218,28 +217,28 @@ public class Eclipse {
|
||||
return typeRef;
|
||||
}
|
||||
|
||||
if ( ref instanceof ArrayQualifiedTypeReference ) {
|
||||
if (ref instanceof ArrayQualifiedTypeReference) {
|
||||
ArrayQualifiedTypeReference iRef = (ArrayQualifiedTypeReference) ref;
|
||||
TypeReference typeRef = new ArrayQualifiedTypeReference(iRef.tokens, iRef.dimensions(), iRef.sourcePositions);
|
||||
setGeneratedBy(typeRef, source);
|
||||
return typeRef;
|
||||
}
|
||||
|
||||
if ( ref instanceof QualifiedTypeReference ) {
|
||||
if (ref instanceof QualifiedTypeReference) {
|
||||
QualifiedTypeReference iRef = (QualifiedTypeReference) ref;
|
||||
TypeReference typeRef = new QualifiedTypeReference(iRef.tokens, iRef.sourcePositions);
|
||||
setGeneratedBy(typeRef, source);
|
||||
return typeRef;
|
||||
}
|
||||
|
||||
if ( ref instanceof ParameterizedSingleTypeReference ) {
|
||||
if (ref instanceof ParameterizedSingleTypeReference) {
|
||||
ParameterizedSingleTypeReference iRef = (ParameterizedSingleTypeReference) ref;
|
||||
TypeReference[] args = null;
|
||||
if ( iRef.typeArguments != null ) {
|
||||
if (iRef.typeArguments != null) {
|
||||
args = new TypeReference[iRef.typeArguments.length];
|
||||
int idx = 0;
|
||||
for ( TypeReference inRef : iRef.typeArguments ) {
|
||||
if ( inRef == null ) args[idx++] = null;
|
||||
for (TypeReference inRef : iRef.typeArguments) {
|
||||
if (inRef == null) args[idx++] = null;
|
||||
else args[idx++] = copyType(inRef, source);
|
||||
}
|
||||
}
|
||||
@@ -249,14 +248,14 @@ public class Eclipse {
|
||||
return typeRef;
|
||||
}
|
||||
|
||||
if ( ref instanceof ArrayTypeReference ) {
|
||||
if (ref instanceof ArrayTypeReference) {
|
||||
ArrayTypeReference iRef = (ArrayTypeReference) ref;
|
||||
TypeReference typeRef = new ArrayTypeReference(iRef.token, iRef.dimensions(), (long)iRef.sourceStart << 32 | iRef.sourceEnd);
|
||||
setGeneratedBy(typeRef, source);
|
||||
return typeRef;
|
||||
}
|
||||
|
||||
if ( ref instanceof Wildcard ) {
|
||||
if (ref instanceof Wildcard) {
|
||||
Wildcard wildcard = new Wildcard(((Wildcard)ref).kind);
|
||||
wildcard.sourceStart = ref.sourceStart;
|
||||
wildcard.sourceEnd = ref.sourceEnd;
|
||||
@@ -264,7 +263,7 @@ public class Eclipse {
|
||||
return wildcard;
|
||||
}
|
||||
|
||||
if ( ref instanceof SingleTypeReference ) {
|
||||
if (ref instanceof SingleTypeReference) {
|
||||
SingleTypeReference iRef = (SingleTypeReference) ref;
|
||||
TypeReference typeRef = new SingleTypeReference(iRef.token, (long)iRef.sourceStart << 32 | iRef.sourceEnd);
|
||||
setGeneratedBy(typeRef, source);
|
||||
@@ -284,10 +283,10 @@ public class Eclipse {
|
||||
if (annotations2 == null) annotations2 = new Annotation[0];
|
||||
Annotation[] outs = new Annotation[annotations1.length + annotations2.length];
|
||||
int idx = 0;
|
||||
for ( Annotation annotation : annotations1 ) {
|
||||
for (Annotation annotation : annotations1) {
|
||||
outs[idx++] = copyAnnotation(annotation, source);
|
||||
}
|
||||
for ( Annotation annotation : annotations2 ) {
|
||||
for (Annotation annotation : annotations2) {
|
||||
outs[idx++] = copyAnnotation(annotation, source);
|
||||
}
|
||||
return outs;
|
||||
@@ -328,10 +327,10 @@ public class Eclipse {
|
||||
*
|
||||
* This is a guess, but a decent one.
|
||||
*/
|
||||
public static boolean annotationTypeMatches(Class<? extends java.lang.annotation.Annotation> type, Node node) {
|
||||
if ( node.getKind() != Kind.ANNOTATION ) return false;
|
||||
public static boolean annotationTypeMatches(Class<? extends java.lang.annotation.Annotation> type, EclipseNode node) {
|
||||
if (node.getKind() != Kind.ANNOTATION) return false;
|
||||
TypeReference typeRef = ((Annotation)node.get()).type;
|
||||
if ( typeRef == null || typeRef.getTypeName() == null ) return false;
|
||||
if (typeRef == null || typeRef.getTypeName() == null) return false;
|
||||
String typeName = toQualifiedName(typeRef.getTypeName());
|
||||
|
||||
TypeLibrary library = new TypeLibrary();
|
||||
@@ -339,8 +338,8 @@ public class Eclipse {
|
||||
TypeResolver resolver = new TypeResolver(library, node.getPackageDeclaration(), node.getImportStatements());
|
||||
Collection<String> typeMatches = resolver.findTypeMatches(node, typeName);
|
||||
|
||||
for ( String match : typeMatches ) {
|
||||
if ( match.equals(type.getName()) ) return true;
|
||||
for (String match : typeMatches) {
|
||||
if (match.equals(type.getName())) return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
@@ -350,32 +349,32 @@ public class Eclipse {
|
||||
* Provides AnnotationValues with the data it needs to do its thing.
|
||||
*/
|
||||
public static <A extends java.lang.annotation.Annotation> AnnotationValues<A>
|
||||
createAnnotation(Class<A> type, final Node annotationNode) {
|
||||
createAnnotation(Class<A> type, final EclipseNode annotationNode) {
|
||||
final Annotation annotation = (Annotation) annotationNode.get();
|
||||
Map<String, AnnotationValue> values = new HashMap<String, AnnotationValue>();
|
||||
|
||||
final MemberValuePair[] pairs = annotation.memberValuePairs();
|
||||
for ( Method m : type.getDeclaredMethods() ) {
|
||||
if ( !Modifier.isPublic(m.getModifiers()) ) continue;
|
||||
for (Method m : type.getDeclaredMethods()) {
|
||||
if (!Modifier.isPublic(m.getModifiers())) continue;
|
||||
String name = m.getName();
|
||||
List<String> raws = new ArrayList<String>();
|
||||
List<Object> guesses = new ArrayList<Object>();
|
||||
Expression fullExpression = null;
|
||||
Expression[] expressions = null;
|
||||
|
||||
if ( pairs != null ) for ( MemberValuePair pair : pairs ) {
|
||||
if (pairs != null) for (MemberValuePair pair : pairs) {
|
||||
char[] n = pair.name;
|
||||
String mName = n == null ? "value" : new String(pair.name);
|
||||
if ( mName.equals(name) ) fullExpression = pair.value;
|
||||
if (mName.equals(name)) fullExpression = pair.value;
|
||||
}
|
||||
|
||||
boolean isExplicit = fullExpression != null;
|
||||
|
||||
if ( isExplicit ) {
|
||||
if ( fullExpression instanceof ArrayInitializer ) {
|
||||
if (isExplicit) {
|
||||
if (fullExpression instanceof ArrayInitializer) {
|
||||
expressions = ((ArrayInitializer)fullExpression).expressions;
|
||||
} else expressions = new Expression[] { fullExpression };
|
||||
if ( expressions != null ) for ( Expression ex : expressions ) {
|
||||
if (expressions != null) for (Expression ex : expressions) {
|
||||
StringBuffer sb = new StringBuffer();
|
||||
ex.print(0, sb);
|
||||
raws.add(sb.toString());
|
||||
@@ -389,10 +388,10 @@ public class Eclipse {
|
||||
values.put(name, new AnnotationValue(annotationNode, raws, guesses, isExplicit) {
|
||||
@Override public void setError(String message, int valueIdx) {
|
||||
Expression ex;
|
||||
if ( valueIdx == -1 ) ex = fullExpr;
|
||||
if (valueIdx == -1) ex = fullExpr;
|
||||
else ex = exprs != null ? exprs[valueIdx] : null;
|
||||
|
||||
if ( ex == null ) ex = annotation;
|
||||
if (ex == null) ex = annotation;
|
||||
|
||||
int sourceStart = ex.sourceStart;
|
||||
int sourceEnd = ex.sourceEnd;
|
||||
@@ -402,10 +401,10 @@ public class Eclipse {
|
||||
|
||||
@Override public void setWarning(String message, int valueIdx) {
|
||||
Expression ex;
|
||||
if ( valueIdx == -1 ) ex = fullExpr;
|
||||
if (valueIdx == -1) ex = fullExpr;
|
||||
else ex = exprs != null ? exprs[valueIdx] : null;
|
||||
|
||||
if ( ex == null ) ex = annotation;
|
||||
if (ex == null) ex = annotation;
|
||||
|
||||
int sourceStart = ex.sourceStart;
|
||||
int sourceEnd = ex.sourceEnd;
|
||||
@@ -419,9 +418,9 @@ public class Eclipse {
|
||||
}
|
||||
|
||||
private static Object calculateValue(Expression e) {
|
||||
if ( e instanceof Literal ) {
|
||||
if (e instanceof Literal) {
|
||||
((Literal)e).computeConstant();
|
||||
switch ( e.constant.typeID() ) {
|
||||
switch (e.constant.typeID()) {
|
||||
case TypeIds.T_int: return e.constant.intValue();
|
||||
case TypeIds.T_byte: return e.constant.byteValue();
|
||||
case TypeIds.T_short: return e.constant.shortValue();
|
||||
@@ -433,11 +432,11 @@ public class Eclipse {
|
||||
case TypeIds.T_JavaLangString: return e.constant.stringValue();
|
||||
default: return null;
|
||||
}
|
||||
} else if ( e instanceof ClassLiteralAccess ) {
|
||||
} else if (e instanceof ClassLiteralAccess) {
|
||||
return Eclipse.toQualifiedName(((ClassLiteralAccess)e).type.getTypeName());
|
||||
} else if ( e instanceof SingleNameReference ) {
|
||||
} else if (e instanceof SingleNameReference) {
|
||||
return new String(((SingleNameReference)e).token);
|
||||
} else if ( e instanceof QualifiedNameReference ) {
|
||||
} else if (e instanceof QualifiedNameReference) {
|
||||
String qName = Eclipse.toQualifiedName(((QualifiedNameReference)e).tokens);
|
||||
int idx = qName.lastIndexOf('.');
|
||||
return idx == -1 ? qName : qName.substring(idx+1);
|
||||
@@ -451,7 +450,7 @@ public class Eclipse {
|
||||
static {
|
||||
try {
|
||||
generatedByField = ASTNode.class.getDeclaredField("$generatedBy");
|
||||
} catch ( Throwable t ) {
|
||||
} catch (Throwable t) {
|
||||
throw Lombok.sneakyThrow(t);
|
||||
}
|
||||
}
|
||||
@@ -459,7 +458,7 @@ public class Eclipse {
|
||||
public static ASTNode getGeneratedBy(ASTNode node) {
|
||||
try {
|
||||
return (ASTNode) generatedByField.get(node);
|
||||
} catch ( Exception t ) {
|
||||
} catch (Exception t) {
|
||||
throw Lombok.sneakyThrow(t);
|
||||
}
|
||||
}
|
||||
@@ -471,7 +470,7 @@ public class Eclipse {
|
||||
public static ASTNode setGeneratedBy(ASTNode node, ASTNode source) {
|
||||
try {
|
||||
generatedByField.set(node, source);
|
||||
} catch ( Exception t ) {
|
||||
} catch (Exception t) {
|
||||
throw Lombok.sneakyThrow(t);
|
||||
}
|
||||
|
||||
|
||||
@@ -34,7 +34,6 @@ import org.eclipse.jdt.internal.compiler.ast.ASTNode;
|
||||
import org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration;
|
||||
import org.eclipse.jdt.internal.compiler.ast.Annotation;
|
||||
import org.eclipse.jdt.internal.compiler.ast.Argument;
|
||||
import org.eclipse.jdt.internal.compiler.ast.Clinit;
|
||||
import org.eclipse.jdt.internal.compiler.ast.CompilationUnitDeclaration;
|
||||
import org.eclipse.jdt.internal.compiler.ast.FieldDeclaration;
|
||||
import org.eclipse.jdt.internal.compiler.ast.ImportReference;
|
||||
@@ -50,7 +49,7 @@ import org.eclipse.jdt.internal.compiler.util.Util;
|
||||
* Wraps around Eclipse's internal AST view to add useful features as well as the ability to visit parents from children,
|
||||
* something Eclipse own AST system does not offer.
|
||||
*/
|
||||
public class EclipseAST extends AST<ASTNode> {
|
||||
public class EclipseAST extends AST<EclipseAST, EclipseNode, ASTNode> {
|
||||
/**
|
||||
* Creates a new EclipseAST of the provided Compilation Unit.
|
||||
*
|
||||
@@ -74,9 +73,9 @@ public class EclipseAST extends AST<ASTNode> {
|
||||
@Override public Collection<String> getImportStatements() {
|
||||
List<String> imports = new ArrayList<String>();
|
||||
CompilationUnitDeclaration cud = (CompilationUnitDeclaration) top().get();
|
||||
if ( cud.imports == null ) return imports;
|
||||
for ( ImportReference imp : cud.imports ) {
|
||||
if ( imp == null ) continue;
|
||||
if (cud.imports == null) return imports;
|
||||
for (ImportReference imp : cud.imports) {
|
||||
if (imp == null) continue;
|
||||
imports.add(Eclipse.toQualifiedName(imp.getImportName()));
|
||||
}
|
||||
|
||||
@@ -91,8 +90,8 @@ public class EclipseAST extends AST<ASTNode> {
|
||||
top().traverse(visitor);
|
||||
}
|
||||
|
||||
private void traverseChildren(EclipseASTVisitor visitor, Node node) {
|
||||
for ( Node child : node.down() ) {
|
||||
void traverseChildren(EclipseASTVisitor visitor, EclipseNode node) {
|
||||
for (EclipseNode child : node.down()) {
|
||||
child.traverse(visitor);
|
||||
}
|
||||
}
|
||||
@@ -108,17 +107,7 @@ public class EclipseAST extends AST<ASTNode> {
|
||||
return completeParse;
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override public Node top() {
|
||||
return (Node) super.top();
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override public Node get(ASTNode node) {
|
||||
return (Node) super.get(node);
|
||||
}
|
||||
|
||||
private class ParseProblem {
|
||||
class ParseProblem {
|
||||
final boolean isWarning;
|
||||
final String message;
|
||||
final int sourceStart;
|
||||
@@ -138,16 +127,16 @@ public class EclipseAST extends AST<ASTNode> {
|
||||
}
|
||||
|
||||
private void propagateProblems() {
|
||||
if ( queuedProblems.isEmpty() ) return;
|
||||
if (queuedProblems.isEmpty()) return;
|
||||
CompilationUnitDeclaration cud = (CompilationUnitDeclaration) top().get();
|
||||
if ( cud.compilationResult == null ) return;
|
||||
for ( ParseProblem problem : queuedProblems ) problem.addToCompilationResult();
|
||||
if (cud.compilationResult == null) return;
|
||||
for (ParseProblem problem : queuedProblems) problem.addToCompilationResult();
|
||||
queuedProblems.clear();
|
||||
}
|
||||
|
||||
private final List<ParseProblem> queuedProblems = new ArrayList<ParseProblem>();
|
||||
|
||||
private void addProblem(ParseProblem problem) {
|
||||
void addProblem(ParseProblem problem) {
|
||||
queuedProblems.add(problem);
|
||||
propagateProblems();
|
||||
}
|
||||
@@ -158,9 +147,9 @@ public class EclipseAST extends AST<ASTNode> {
|
||||
*/
|
||||
static void addProblemToCompilationResult(CompilationUnitDeclaration ast,
|
||||
boolean isWarning, String message, int sourceStart, int sourceEnd) {
|
||||
if ( ast.compilationResult == null ) return;
|
||||
if (ast.compilationResult == null) return;
|
||||
char[] fileNameArray = ast.getFileName();
|
||||
if ( fileNameArray == null ) fileNameArray = "(unknown).java".toCharArray();
|
||||
if (fileNameArray == null) fileNameArray = "(unknown).java".toCharArray();
|
||||
int lineNumber = 0;
|
||||
int columnNumber = 1;
|
||||
CompilationResult result = ast.compilationResult;
|
||||
@@ -197,171 +186,6 @@ public class EclipseAST extends AST<ASTNode> {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Eclipse specific version of the AST.Node class.
|
||||
*/
|
||||
public final class Node extends AST<ASTNode>.Node {
|
||||
/**
|
||||
* See the {@link AST.Node} constructor for information.
|
||||
*/
|
||||
Node(ASTNode node, List<Node> children, Kind kind) {
|
||||
super(node, children, kind);
|
||||
}
|
||||
|
||||
/**
|
||||
* Visits this node and all child nodes depth-first, calling the provided visitor's visit methods.
|
||||
*/
|
||||
public void traverse(EclipseASTVisitor visitor) {
|
||||
switch ( getKind() ) {
|
||||
case COMPILATION_UNIT:
|
||||
visitor.visitCompilationUnit(this, (CompilationUnitDeclaration)get());
|
||||
traverseChildren(visitor, this);
|
||||
visitor.endVisitCompilationUnit(this, (CompilationUnitDeclaration)get());
|
||||
break;
|
||||
case TYPE:
|
||||
visitor.visitType(this, (TypeDeclaration)get());
|
||||
traverseChildren(visitor, this);
|
||||
visitor.endVisitType(this, (TypeDeclaration)get());
|
||||
break;
|
||||
case FIELD:
|
||||
visitor.visitField(this, (FieldDeclaration)get());
|
||||
traverseChildren(visitor, this);
|
||||
visitor.endVisitField(this, (FieldDeclaration)get());
|
||||
break;
|
||||
case INITIALIZER:
|
||||
visitor.visitInitializer(this, (Initializer)get());
|
||||
traverseChildren(visitor, this);
|
||||
visitor.endVisitInitializer(this, (Initializer)get());
|
||||
break;
|
||||
case METHOD:
|
||||
if ( get() instanceof Clinit ) return;
|
||||
visitor.visitMethod(this, (AbstractMethodDeclaration)get());
|
||||
traverseChildren(visitor, this);
|
||||
visitor.endVisitMethod(this, (AbstractMethodDeclaration)get());
|
||||
break;
|
||||
case ARGUMENT:
|
||||
AbstractMethodDeclaration method = (AbstractMethodDeclaration)up().get();
|
||||
visitor.visitMethodArgument(this, (Argument)get(), method);
|
||||
traverseChildren(visitor, this);
|
||||
visitor.endVisitMethodArgument(this, (Argument)get(), method);
|
||||
break;
|
||||
case LOCAL:
|
||||
visitor.visitLocal(this, (LocalDeclaration)get());
|
||||
traverseChildren(visitor, this);
|
||||
visitor.endVisitLocal(this, (LocalDeclaration)get());
|
||||
break;
|
||||
case ANNOTATION:
|
||||
switch ( up().getKind() ) {
|
||||
case TYPE:
|
||||
visitor.visitAnnotationOnType((TypeDeclaration)up().get(), this, (Annotation)get());
|
||||
break;
|
||||
case FIELD:
|
||||
visitor.visitAnnotationOnField((FieldDeclaration)up().get(), this, (Annotation)get());
|
||||
break;
|
||||
case METHOD:
|
||||
visitor.visitAnnotationOnMethod((AbstractMethodDeclaration)up().get(), this, (Annotation)get());
|
||||
break;
|
||||
case ARGUMENT:
|
||||
visitor.visitAnnotationOnMethodArgument(
|
||||
(Argument)parent.get(),
|
||||
(AbstractMethodDeclaration)parent.directUp().get(),
|
||||
this, (Annotation)get());
|
||||
break;
|
||||
case LOCAL:
|
||||
visitor.visitAnnotationOnLocal((LocalDeclaration)parent.get(), this, (Annotation)get());
|
||||
break;
|
||||
default:
|
||||
throw new AssertionError("Annotion not expected as child of a " + up().getKind());
|
||||
}
|
||||
break;
|
||||
case STATEMENT:
|
||||
visitor.visitStatement(this, (Statement)get());
|
||||
traverseChildren(visitor, this);
|
||||
visitor.endVisitStatement(this, (Statement)get());
|
||||
break;
|
||||
default:
|
||||
throw new AssertionError("Unexpected kind during node traversal: " + getKind());
|
||||
}
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override public String getName() {
|
||||
final char[] n;
|
||||
if ( node instanceof TypeDeclaration ) n = ((TypeDeclaration)node).name;
|
||||
else if ( node instanceof FieldDeclaration ) n = ((FieldDeclaration)node).name;
|
||||
else if ( node instanceof AbstractMethodDeclaration ) n = ((AbstractMethodDeclaration)node).selector;
|
||||
else if ( node instanceof LocalDeclaration ) n = ((LocalDeclaration)node).name;
|
||||
else n = null;
|
||||
|
||||
return n == null ? null : new String(n);
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override public void addError(String message) {
|
||||
this.addError(message, this.get().sourceStart, this.get().sourceEnd);
|
||||
}
|
||||
|
||||
/** Generate a compiler error that shows the wavy underline from-to the stated character positions. */
|
||||
public void addError(String message, int sourceStart, int sourceEnd) {
|
||||
addProblem(new ParseProblem(false, message, sourceStart, sourceEnd));
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override public void addWarning(String message) {
|
||||
this.addWarning(message, this.get().sourceStart, this.get().sourceEnd);
|
||||
}
|
||||
|
||||
/** Generate a compiler warning that shows the wavy underline from-to the stated character positions. */
|
||||
public void addWarning(String message, int sourceStart, int sourceEnd) {
|
||||
addProblem(new ParseProblem(true, message, sourceStart, sourceEnd));
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override public Node up() {
|
||||
return (Node) super.up();
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override protected 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;
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override public Node getNodeFor(ASTNode obj) {
|
||||
return (Node) super.getNodeFor(obj);
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
public Node directUp() {
|
||||
return (Node) super.directUp();
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override public Collection<Node> down() {
|
||||
return (Collection<Node>) super.down();
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override public Node top() {
|
||||
return (Node) super.top();
|
||||
}
|
||||
|
||||
/**
|
||||
* Convenient shortcut to the owning EclipseAST object's isCompleteParse method.
|
||||
*
|
||||
* @see EclipseAST#isCompleteParse()
|
||||
*/
|
||||
public boolean isCompleteParse() {
|
||||
return completeParse;
|
||||
}
|
||||
}
|
||||
|
||||
private final CompilationUnitDeclaration compilationUnitDeclaration;
|
||||
private boolean completeParse;
|
||||
|
||||
@@ -370,15 +194,15 @@ public class EclipseAST extends AST<ASTNode> {
|
||||
}
|
||||
|
||||
/**
|
||||
* Call to move an EclipseAST generated for a diet parse to rebuild itself for the full parse -
|
||||
* Call this method to move an EclipseAST generated for a diet parse to rebuild itself for the full parse -
|
||||
* with filled in method bodies and such. Also propagates problems and errors, which in diet parse
|
||||
* mode can't be reliably added to the problems/warnings view.
|
||||
*/
|
||||
public void reparse() {
|
||||
propagateProblems();
|
||||
if ( completeParse ) return;
|
||||
if (completeParse) return;
|
||||
boolean newCompleteParse = isComplete(compilationUnitDeclaration);
|
||||
if ( !newCompleteParse ) return;
|
||||
if (!newCompleteParse) return;
|
||||
|
||||
top().rebuild();
|
||||
|
||||
@@ -390,8 +214,8 @@ public class EclipseAST extends AST<ASTNode> {
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override protected Node buildTree(ASTNode node, Kind kind) {
|
||||
switch ( kind ) {
|
||||
@Override protected EclipseNode buildTree(ASTNode node, Kind kind) {
|
||||
switch (kind) {
|
||||
case COMPILATION_UNIT:
|
||||
return buildCompilationUnit((CompilationUnitDeclaration) node);
|
||||
case TYPE:
|
||||
@@ -415,126 +239,126 @@ public class EclipseAST extends AST<ASTNode> {
|
||||
}
|
||||
}
|
||||
|
||||
private Node buildCompilationUnit(CompilationUnitDeclaration top) {
|
||||
if ( setAndGetAsHandled(top) ) return null;
|
||||
List<Node> children = buildTypes(top.types);
|
||||
return putInMap(new Node(top, children, Kind.COMPILATION_UNIT));
|
||||
private EclipseNode buildCompilationUnit(CompilationUnitDeclaration top) {
|
||||
if (setAndGetAsHandled(top)) return null;
|
||||
List<EclipseNode> children = buildTypes(top.types);
|
||||
return putInMap(new EclipseNode(this, top, children, Kind.COMPILATION_UNIT));
|
||||
}
|
||||
|
||||
private void addIfNotNull(Collection<Node> collection, Node n) {
|
||||
if ( n != null ) collection.add(n);
|
||||
private void addIfNotNull(Collection<EclipseNode> collection, EclipseNode n) {
|
||||
if (n != null) collection.add(n);
|
||||
}
|
||||
|
||||
private List<Node> buildTypes(TypeDeclaration[] children) {
|
||||
List<Node> childNodes = new ArrayList<Node>();
|
||||
if ( children != null ) for ( TypeDeclaration type : children ) addIfNotNull(childNodes, buildType(type));
|
||||
private List<EclipseNode> buildTypes(TypeDeclaration[] children) {
|
||||
List<EclipseNode> childNodes = new ArrayList<EclipseNode>();
|
||||
if (children != null) for (TypeDeclaration type : children) addIfNotNull(childNodes, buildType(type));
|
||||
return childNodes;
|
||||
}
|
||||
|
||||
private Node buildType(TypeDeclaration type) {
|
||||
if ( setAndGetAsHandled(type) ) return null;
|
||||
List<Node> childNodes = new ArrayList<Node>();
|
||||
private EclipseNode buildType(TypeDeclaration type) {
|
||||
if (setAndGetAsHandled(type)) return null;
|
||||
List<EclipseNode> childNodes = new ArrayList<EclipseNode>();
|
||||
childNodes.addAll(buildFields(type.fields));
|
||||
childNodes.addAll(buildTypes(type.memberTypes));
|
||||
childNodes.addAll(buildMethods(type.methods));
|
||||
childNodes.addAll(buildAnnotations(type.annotations));
|
||||
return putInMap(new Node(type, childNodes, Kind.TYPE));
|
||||
return putInMap(new EclipseNode(this, type, childNodes, Kind.TYPE));
|
||||
}
|
||||
|
||||
private Collection<Node> buildFields(FieldDeclaration[] children) {
|
||||
List<Node> childNodes = new ArrayList<Node>();
|
||||
if ( children != null ) for ( FieldDeclaration child : children ) addIfNotNull(childNodes, buildField(child));
|
||||
private Collection<EclipseNode> buildFields(FieldDeclaration[] children) {
|
||||
List<EclipseNode> childNodes = new ArrayList<EclipseNode>();
|
||||
if (children != null) for (FieldDeclaration child : children) addIfNotNull(childNodes, buildField(child));
|
||||
return childNodes;
|
||||
}
|
||||
|
||||
private static <T> List<T> singleton(T item) {
|
||||
List<T> list = new ArrayList<T>();
|
||||
if ( item != null ) list.add(item);
|
||||
if (item != null) list.add(item);
|
||||
return list;
|
||||
}
|
||||
|
||||
private Node buildField(FieldDeclaration field) {
|
||||
if ( field instanceof Initializer ) return buildInitializer((Initializer)field);
|
||||
if ( setAndGetAsHandled(field) ) return null;
|
||||
List<Node> childNodes = new ArrayList<Node>();
|
||||
private EclipseNode buildField(FieldDeclaration field) {
|
||||
if (field instanceof Initializer) return buildInitializer((Initializer)field);
|
||||
if (setAndGetAsHandled(field)) return null;
|
||||
List<EclipseNode> childNodes = new ArrayList<EclipseNode>();
|
||||
addIfNotNull(childNodes, buildStatement(field.initialization));
|
||||
childNodes.addAll(buildAnnotations(field.annotations));
|
||||
return putInMap(new Node(field, childNodes, Kind.FIELD));
|
||||
return putInMap(new EclipseNode(this, field, childNodes, Kind.FIELD));
|
||||
}
|
||||
|
||||
private Node buildInitializer(Initializer initializer) {
|
||||
if ( setAndGetAsHandled(initializer) ) return null;
|
||||
return putInMap(new Node(initializer, singleton(buildStatement(initializer.block)), Kind.INITIALIZER));
|
||||
private EclipseNode buildInitializer(Initializer initializer) {
|
||||
if (setAndGetAsHandled(initializer)) return null;
|
||||
return putInMap(new EclipseNode(this, initializer, singleton(buildStatement(initializer.block)), Kind.INITIALIZER));
|
||||
}
|
||||
|
||||
private Collection<Node> buildMethods(AbstractMethodDeclaration[] children) {
|
||||
List<Node> childNodes = new ArrayList<Node>();
|
||||
if ( children != null ) for (AbstractMethodDeclaration method : children ) addIfNotNull(childNodes, buildMethod(method));
|
||||
private Collection<EclipseNode> buildMethods(AbstractMethodDeclaration[] children) {
|
||||
List<EclipseNode> childNodes = new ArrayList<EclipseNode>();
|
||||
if (children != null) for (AbstractMethodDeclaration method : children) addIfNotNull(childNodes, buildMethod(method));
|
||||
return childNodes;
|
||||
}
|
||||
|
||||
private Node buildMethod(AbstractMethodDeclaration method) {
|
||||
if ( setAndGetAsHandled(method) ) return null;
|
||||
List<Node> childNodes = new ArrayList<Node>();
|
||||
private EclipseNode buildMethod(AbstractMethodDeclaration method) {
|
||||
if (setAndGetAsHandled(method)) return null;
|
||||
List<EclipseNode> childNodes = new ArrayList<EclipseNode>();
|
||||
childNodes.addAll(buildArguments(method.arguments));
|
||||
childNodes.addAll(buildStatements(method.statements));
|
||||
childNodes.addAll(buildAnnotations(method.annotations));
|
||||
return putInMap(new Node(method, childNodes, Kind.METHOD));
|
||||
return putInMap(new EclipseNode(this, method, childNodes, Kind.METHOD));
|
||||
}
|
||||
|
||||
//Arguments are a kind of LocalDeclaration. They can definitely contain lombok annotations, so we care about them.
|
||||
private Collection<Node> buildArguments(Argument[] children) {
|
||||
List<Node> childNodes = new ArrayList<Node>();
|
||||
if ( children != null ) for ( LocalDeclaration local : children ) {
|
||||
private Collection<EclipseNode> buildArguments(Argument[] children) {
|
||||
List<EclipseNode> childNodes = new ArrayList<EclipseNode>();
|
||||
if (children != null) for (LocalDeclaration local : children) {
|
||||
addIfNotNull(childNodes, buildLocal(local, Kind.ARGUMENT));
|
||||
}
|
||||
return childNodes;
|
||||
}
|
||||
|
||||
private Node buildLocal(LocalDeclaration local, Kind kind) {
|
||||
if ( setAndGetAsHandled(local) ) return null;
|
||||
List<Node> childNodes = new ArrayList<Node>();
|
||||
private EclipseNode buildLocal(LocalDeclaration local, Kind kind) {
|
||||
if (setAndGetAsHandled(local)) return null;
|
||||
List<EclipseNode> childNodes = new ArrayList<EclipseNode>();
|
||||
addIfNotNull(childNodes, buildStatement(local.initialization));
|
||||
childNodes.addAll(buildAnnotations(local.annotations));
|
||||
return putInMap(new Node(local, childNodes, kind));
|
||||
return putInMap(new EclipseNode(this, local, childNodes, kind));
|
||||
}
|
||||
|
||||
private Collection<Node> buildAnnotations(Annotation[] annotations) {
|
||||
List<Node> elements = new ArrayList<Node>();
|
||||
if ( annotations != null ) for ( Annotation an : annotations ) addIfNotNull(elements, buildAnnotation(an));
|
||||
private Collection<EclipseNode> buildAnnotations(Annotation[] annotations) {
|
||||
List<EclipseNode> elements = new ArrayList<EclipseNode>();
|
||||
if (annotations != null) for (Annotation an : annotations) addIfNotNull(elements, buildAnnotation(an));
|
||||
return elements;
|
||||
}
|
||||
|
||||
private Node buildAnnotation(Annotation annotation) {
|
||||
if ( annotation == null ) return null;
|
||||
if ( setAndGetAsHandled(annotation) ) return null;
|
||||
return putInMap(new Node(annotation, null, Kind.ANNOTATION));
|
||||
private EclipseNode buildAnnotation(Annotation annotation) {
|
||||
if (annotation == null) return null;
|
||||
if (setAndGetAsHandled(annotation)) return null;
|
||||
return putInMap(new EclipseNode(this, annotation, null, Kind.ANNOTATION));
|
||||
}
|
||||
|
||||
private Collection<Node> buildStatements(Statement[] children) {
|
||||
List<Node> childNodes = new ArrayList<Node>();
|
||||
if ( children != null ) for ( Statement child : children ) addIfNotNull(childNodes, buildStatement(child));
|
||||
private Collection<EclipseNode> buildStatements(Statement[] children) {
|
||||
List<EclipseNode> childNodes = new ArrayList<EclipseNode>();
|
||||
if (children != null) for (Statement child : children) addIfNotNull(childNodes, buildStatement(child));
|
||||
return childNodes;
|
||||
}
|
||||
|
||||
private Node buildStatement(Statement child) {
|
||||
if ( child == null ) return null;
|
||||
if ( child instanceof TypeDeclaration ) return buildType((TypeDeclaration)child);
|
||||
private EclipseNode buildStatement(Statement child) {
|
||||
if (child == null) return null;
|
||||
if (child instanceof TypeDeclaration) return buildType((TypeDeclaration)child);
|
||||
|
||||
if ( child instanceof LocalDeclaration ) return buildLocal((LocalDeclaration)child, Kind.LOCAL);
|
||||
if (child instanceof LocalDeclaration) return buildLocal((LocalDeclaration)child, Kind.LOCAL);
|
||||
|
||||
if ( setAndGetAsHandled(child) ) return null;
|
||||
if (setAndGetAsHandled(child)) return null;
|
||||
|
||||
return drill(child);
|
||||
}
|
||||
|
||||
private Node drill(Statement statement) {
|
||||
List<Node> childNodes = new ArrayList<Node>();
|
||||
for ( FieldAccess fa : fieldsOf(statement.getClass()) ) childNodes.addAll(buildWithField(Node.class, statement, fa));
|
||||
return putInMap(new Node(statement, childNodes, Kind.STATEMENT));
|
||||
private EclipseNode drill(Statement statement) {
|
||||
List<EclipseNode> childNodes = new ArrayList<EclipseNode>();
|
||||
for (FieldAccess fa : fieldsOf(statement.getClass())) childNodes.addAll(buildWithField(EclipseNode.class, statement, fa));
|
||||
return putInMap(new EclipseNode(this, statement, childNodes, Kind.STATEMENT));
|
||||
}
|
||||
|
||||
/** For Eclipse, only Statement counts, as Expression is a subclass of it, eventhough this isn't
|
||||
/** For Eclipse, only Statement counts, as Expression is a subclass of it, even though this isn't
|
||||
* entirely correct according to the JLS spec (only some expressions can be used as statements, not all of them). */
|
||||
@Override protected Collection<Class<? extends ASTNode>> getStatementTypes() {
|
||||
return Collections.<Class<? extends ASTNode>>singleton(Statement.class);
|
||||
|
||||
@@ -21,8 +21,6 @@
|
||||
*/
|
||||
package lombok.eclipse;
|
||||
|
||||
import lombok.eclipse.EclipseAST.Node;
|
||||
|
||||
import org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration;
|
||||
import org.eclipse.jdt.internal.compiler.ast.Annotation;
|
||||
import org.eclipse.jdt.internal.compiler.ast.Argument;
|
||||
@@ -39,65 +37,65 @@ import org.eclipse.jdt.internal.compiler.ast.TypeDeclaration;
|
||||
*/
|
||||
public abstract class EclipseASTAdapter implements EclipseASTVisitor {
|
||||
/** {@inheritDoc} */
|
||||
public void visitCompilationUnit(Node top, CompilationUnitDeclaration unit) {}
|
||||
public void visitCompilationUnit(EclipseNode top, CompilationUnitDeclaration unit) {}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
public void endVisitCompilationUnit(Node top, CompilationUnitDeclaration unit) {}
|
||||
public void endVisitCompilationUnit(EclipseNode top, CompilationUnitDeclaration unit) {}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
public void visitType(Node typeNode, TypeDeclaration type) {}
|
||||
public void visitType(EclipseNode typeNode, TypeDeclaration type) {}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
public void visitAnnotationOnType(TypeDeclaration type, Node annotationNode, Annotation annotation) {}
|
||||
public void visitAnnotationOnType(TypeDeclaration type, EclipseNode annotationNode, Annotation annotation) {}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
public void endVisitType(Node typeNode, TypeDeclaration type) {}
|
||||
public void endVisitType(EclipseNode typeNode, TypeDeclaration type) {}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
public void visitInitializer(Node initializerNode, Initializer initializer) {}
|
||||
public void visitInitializer(EclipseNode initializerNode, Initializer initializer) {}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
public void endVisitInitializer(Node initializerNode, Initializer initializer) {}
|
||||
public void endVisitInitializer(EclipseNode initializerNode, Initializer initializer) {}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
public void visitField(Node fieldNode, FieldDeclaration field) {}
|
||||
public void visitField(EclipseNode fieldNode, FieldDeclaration field) {}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
public void visitAnnotationOnField(FieldDeclaration field, Node annotationNode, Annotation annotation) {}
|
||||
public void visitAnnotationOnField(FieldDeclaration field, EclipseNode annotationNode, Annotation annotation) {}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
public void endVisitField(Node fieldNode, FieldDeclaration field) {}
|
||||
public void endVisitField(EclipseNode fieldNode, FieldDeclaration field) {}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
public void visitMethod(Node methodNode, AbstractMethodDeclaration method) {}
|
||||
public void visitMethod(EclipseNode methodNode, AbstractMethodDeclaration method) {}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
public void visitAnnotationOnMethod(AbstractMethodDeclaration method, Node annotationNode, Annotation annotation) {}
|
||||
public void visitAnnotationOnMethod(AbstractMethodDeclaration method, EclipseNode annotationNode, Annotation annotation) {}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
public void endVisitMethod(Node methodNode, AbstractMethodDeclaration method) {}
|
||||
public void endVisitMethod(EclipseNode methodNode, AbstractMethodDeclaration method) {}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
public void visitMethodArgument(Node argNode, Argument arg, AbstractMethodDeclaration method) {}
|
||||
public void visitMethodArgument(EclipseNode argNode, Argument arg, AbstractMethodDeclaration method) {}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
public void visitAnnotationOnMethodArgument(Argument arg, AbstractMethodDeclaration method, Node annotationNode, Annotation annotation) {}
|
||||
public void visitAnnotationOnMethodArgument(Argument arg, AbstractMethodDeclaration method, EclipseNode annotationNode, Annotation annotation) {}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
public void endVisitMethodArgument(Node argNode, Argument arg, AbstractMethodDeclaration method) {}
|
||||
public void endVisitMethodArgument(EclipseNode argNode, Argument arg, AbstractMethodDeclaration method) {}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
public void visitLocal(Node localNode, LocalDeclaration local) {}
|
||||
public void visitLocal(EclipseNode localNode, LocalDeclaration local) {}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
public void visitAnnotationOnLocal(LocalDeclaration local, Node annotationNode, Annotation annotation) {}
|
||||
public void visitAnnotationOnLocal(LocalDeclaration local, EclipseNode annotationNode, Annotation annotation) {}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
public void endVisitLocal(Node localNode, LocalDeclaration local) {}
|
||||
public void endVisitLocal(EclipseNode localNode, LocalDeclaration local) {}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
public void visitStatement(Node statementNode, Statement statement) {}
|
||||
public void visitStatement(EclipseNode statementNode, Statement statement) {}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
public void endVisitStatement(Node statementNode, Statement statement) {}
|
||||
public void endVisitStatement(EclipseNode statementNode, Statement statement) {}
|
||||
}
|
||||
|
||||
@@ -24,8 +24,6 @@ package lombok.eclipse;
|
||||
import java.io.PrintStream;
|
||||
import java.lang.reflect.Modifier;
|
||||
|
||||
import lombok.eclipse.EclipseAST.Node;
|
||||
|
||||
import org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration;
|
||||
import org.eclipse.jdt.internal.compiler.ast.Annotation;
|
||||
import org.eclipse.jdt.internal.compiler.ast.Argument;
|
||||
@@ -47,15 +45,15 @@ public interface EclipseASTVisitor {
|
||||
/**
|
||||
* Called at the very beginning and end.
|
||||
*/
|
||||
void visitCompilationUnit(Node top, CompilationUnitDeclaration unit);
|
||||
void endVisitCompilationUnit(Node top, CompilationUnitDeclaration unit);
|
||||
void visitCompilationUnit(EclipseNode top, CompilationUnitDeclaration unit);
|
||||
void endVisitCompilationUnit(EclipseNode top, CompilationUnitDeclaration unit);
|
||||
|
||||
/**
|
||||
* Called when visiting a type (a class, interface, annotation, enum, etcetera).
|
||||
*/
|
||||
void visitType(Node typeNode, TypeDeclaration type);
|
||||
void visitAnnotationOnType(TypeDeclaration type, Node annotationNode, Annotation annotation);
|
||||
void endVisitType(Node typeNode, TypeDeclaration type);
|
||||
void visitType(EclipseNode typeNode, TypeDeclaration type);
|
||||
void visitAnnotationOnType(TypeDeclaration type, EclipseNode annotationNode, Annotation annotation);
|
||||
void endVisitType(EclipseNode typeNode, TypeDeclaration type);
|
||||
|
||||
/**
|
||||
* Called when visiting a field of a class.
|
||||
@@ -63,46 +61,46 @@ public interface EclipseASTVisitor {
|
||||
* which are a subclass of FieldDeclaration, those do NOT result in a call to this method. They result
|
||||
* in a call to the visitInitializer method.
|
||||
*/
|
||||
void visitField(Node fieldNode, FieldDeclaration field);
|
||||
void visitAnnotationOnField(FieldDeclaration field, Node annotationNode, Annotation annotation);
|
||||
void endVisitField(Node fieldNode, FieldDeclaration field);
|
||||
void visitField(EclipseNode fieldNode, FieldDeclaration field);
|
||||
void visitAnnotationOnField(FieldDeclaration field, EclipseNode annotationNode, Annotation annotation);
|
||||
void endVisitField(EclipseNode fieldNode, FieldDeclaration field);
|
||||
|
||||
/**
|
||||
* Called for static and instance initializers. You can tell the difference via the modifier flag on the
|
||||
* ASTNode (8 for static, 0 for not static). The content is in the 'block', not in the 'initialization',
|
||||
* which would always be null for an initializer instance.
|
||||
*/
|
||||
void visitInitializer(Node initializerNode, Initializer initializer);
|
||||
void endVisitInitializer(Node initializerNode, Initializer initializer);
|
||||
void visitInitializer(EclipseNode initializerNode, Initializer initializer);
|
||||
void endVisitInitializer(EclipseNode initializerNode, Initializer initializer);
|
||||
|
||||
/**
|
||||
* Called for both methods (MethodDeclaration) and constructors (ConstructorDeclaration), but not for
|
||||
* Clinit objects, which are a vestigial Eclipse thing that never contain anything. Static initializers
|
||||
* show up as 'Initializer', in the visitInitializer method, with modifier bit STATIC set.
|
||||
*/
|
||||
void visitMethod(Node methodNode, AbstractMethodDeclaration method);
|
||||
void visitAnnotationOnMethod(AbstractMethodDeclaration method, Node annotationNode, Annotation annotation);
|
||||
void endVisitMethod(Node methodNode, AbstractMethodDeclaration method);
|
||||
void visitMethod(EclipseNode methodNode, AbstractMethodDeclaration method);
|
||||
void visitAnnotationOnMethod(AbstractMethodDeclaration method, EclipseNode annotationNode, Annotation annotation);
|
||||
void endVisitMethod(EclipseNode methodNode, AbstractMethodDeclaration method);
|
||||
|
||||
/**
|
||||
* Visits a method argument
|
||||
*/
|
||||
void visitMethodArgument(Node argNode, Argument arg, AbstractMethodDeclaration method);
|
||||
void visitAnnotationOnMethodArgument(Argument arg, AbstractMethodDeclaration method, Node annotationNode, Annotation annotation);
|
||||
void endVisitMethodArgument(Node argNode, Argument arg, AbstractMethodDeclaration method);
|
||||
void visitMethodArgument(EclipseNode argNode, Argument arg, AbstractMethodDeclaration method);
|
||||
void visitAnnotationOnMethodArgument(Argument arg, AbstractMethodDeclaration method, EclipseNode annotationNode, Annotation annotation);
|
||||
void endVisitMethodArgument(EclipseNode argNode, Argument arg, AbstractMethodDeclaration method);
|
||||
|
||||
/**
|
||||
* Visits a local declaration - that is, something like 'int x = 10;' on the method level.
|
||||
*/
|
||||
void visitLocal(Node localNode, LocalDeclaration local);
|
||||
void visitAnnotationOnLocal(LocalDeclaration local, Node annotationNode, Annotation annotation);
|
||||
void endVisitLocal(Node localNode, LocalDeclaration local);
|
||||
void visitLocal(EclipseNode localNode, LocalDeclaration local);
|
||||
void visitAnnotationOnLocal(LocalDeclaration local, EclipseNode annotationNode, Annotation annotation);
|
||||
void endVisitLocal(EclipseNode localNode, LocalDeclaration local);
|
||||
|
||||
/**
|
||||
* Visits a statement that isn't any of the other visit methods (e.g. TypeDeclaration).
|
||||
*/
|
||||
void visitStatement(Node statementNode, Statement statement);
|
||||
void endVisitStatement(Node statementNode, Statement statement);
|
||||
void visitStatement(EclipseNode statementNode, Statement statement);
|
||||
void endVisitStatement(EclipseNode statementNode, Statement statement);
|
||||
|
||||
/**
|
||||
* Prints the structure of an AST.
|
||||
@@ -135,33 +133,33 @@ public interface EclipseASTVisitor {
|
||||
|
||||
private void forcePrint(String text, Object... params) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
for ( int i = 0 ; i < indent ; i++ ) sb.append(" ");
|
||||
for (int i = 0; i < indent; i++) sb.append(" ");
|
||||
out.printf(sb.append(text).append('\n').toString(), params);
|
||||
out.flush();
|
||||
}
|
||||
|
||||
private void print(String text, Object... params) {
|
||||
if ( disablePrinting == 0 ) forcePrint(text, params);
|
||||
if (disablePrinting == 0) forcePrint(text, params);
|
||||
}
|
||||
|
||||
private String str(char[] c) {
|
||||
if ( c == null ) return "(NULL)";
|
||||
if (c == null) return "(NULL)";
|
||||
else return new String(c);
|
||||
}
|
||||
|
||||
private String str(TypeReference type) {
|
||||
if ( type == null ) return "(NULL)";
|
||||
if (type == null) return "(NULL)";
|
||||
char[][] c = type.getTypeName();
|
||||
StringBuilder sb = new StringBuilder();
|
||||
boolean first = true;
|
||||
for ( char[] d : c ) {
|
||||
for (char[] d : c) {
|
||||
sb.append(first ? "" : ".").append(new String(d));
|
||||
first = false;
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
public void visitCompilationUnit(Node node, CompilationUnitDeclaration unit) {
|
||||
public void visitCompilationUnit(EclipseNode node, CompilationUnitDeclaration unit) {
|
||||
out.println("---------------------------------------------------------");
|
||||
out.println(node.isCompleteParse() ? "COMPLETE" : "incomplete");
|
||||
|
||||
@@ -169,31 +167,31 @@ public interface EclipseASTVisitor {
|
||||
indent++;
|
||||
}
|
||||
|
||||
public void endVisitCompilationUnit(Node node, CompilationUnitDeclaration unit) {
|
||||
public void endVisitCompilationUnit(EclipseNode node, CompilationUnitDeclaration unit) {
|
||||
indent--;
|
||||
print("</CUD>");
|
||||
}
|
||||
|
||||
public void visitType(Node node, TypeDeclaration type) {
|
||||
public void visitType(EclipseNode node, TypeDeclaration type) {
|
||||
print("<TYPE %s%s>", str(type.name), Eclipse.isGenerated(type) ? " (GENERATED)" : "");
|
||||
indent++;
|
||||
if ( printContent ) {
|
||||
if (printContent) {
|
||||
print("%s", type);
|
||||
disablePrinting++;
|
||||
}
|
||||
}
|
||||
|
||||
public void visitAnnotationOnType(TypeDeclaration type, Node node, Annotation annotation) {
|
||||
public void visitAnnotationOnType(TypeDeclaration type, EclipseNode node, Annotation annotation) {
|
||||
forcePrint("<ANNOTATION%s: %s />", Eclipse.isGenerated(annotation) ? " (GENERATED)" : "", annotation);
|
||||
}
|
||||
|
||||
public void endVisitType(Node node, TypeDeclaration type) {
|
||||
if ( printContent ) disablePrinting--;
|
||||
public void endVisitType(EclipseNode node, TypeDeclaration type) {
|
||||
if (printContent) disablePrinting--;
|
||||
indent--;
|
||||
print("</TYPE %s>", str(type.name));
|
||||
}
|
||||
|
||||
public void visitInitializer(Node node, Initializer initializer) {
|
||||
public void visitInitializer(EclipseNode node, Initializer initializer) {
|
||||
Block block = initializer.block;
|
||||
boolean s = (block != null && block.statements != null);
|
||||
print("<%s INITIALIZER: %s%s>",
|
||||
@@ -201,95 +199,95 @@ public interface EclipseASTVisitor {
|
||||
s ? "filled" : "blank",
|
||||
Eclipse.isGenerated(initializer) ? " (GENERATED)" : "");
|
||||
indent++;
|
||||
if ( printContent ) {
|
||||
if ( initializer.block != null ) print("%s", initializer.block);
|
||||
if (printContent) {
|
||||
if (initializer.block != null) print("%s", initializer.block);
|
||||
disablePrinting++;
|
||||
}
|
||||
}
|
||||
|
||||
public void endVisitInitializer(Node node, Initializer initializer) {
|
||||
if ( printContent ) disablePrinting--;
|
||||
public void endVisitInitializer(EclipseNode node, Initializer initializer) {
|
||||
if (printContent) disablePrinting--;
|
||||
indent--;
|
||||
print("</%s INITIALIZER>", (initializer.modifiers & Modifier.STATIC) != 0 ? "static" : "instance");
|
||||
}
|
||||
|
||||
public void visitField(Node node, FieldDeclaration field) {
|
||||
public void visitField(EclipseNode node, FieldDeclaration field) {
|
||||
print("<FIELD%s %s %s = %s>", Eclipse.isGenerated(field) ? " (GENERATED)" : "",
|
||||
str(field.type), str(field.name), field.initialization);
|
||||
indent++;
|
||||
if ( printContent ) {
|
||||
if ( field.initialization != null ) print("%s", field.initialization);
|
||||
if (printContent) {
|
||||
if (field.initialization != null) print("%s", field.initialization);
|
||||
disablePrinting++;
|
||||
}
|
||||
}
|
||||
|
||||
public void visitAnnotationOnField(FieldDeclaration field, Node node, Annotation annotation) {
|
||||
public void visitAnnotationOnField(FieldDeclaration field, EclipseNode node, Annotation annotation) {
|
||||
forcePrint("<ANNOTATION%s: %s />", Eclipse.isGenerated(annotation) ? " (GENERATED)" : "", annotation);
|
||||
}
|
||||
|
||||
public void endVisitField(Node node, FieldDeclaration field) {
|
||||
if ( printContent ) disablePrinting--;
|
||||
public void endVisitField(EclipseNode node, FieldDeclaration field) {
|
||||
if (printContent) disablePrinting--;
|
||||
indent--;
|
||||
print("</FIELD %s %s>", str(field.type), str(field.name));
|
||||
}
|
||||
|
||||
public void visitMethod(Node node, AbstractMethodDeclaration method) {
|
||||
public void visitMethod(EclipseNode node, AbstractMethodDeclaration method) {
|
||||
String type = method instanceof ConstructorDeclaration ? "CONSTRUCTOR" : "METHOD";
|
||||
print("<%s %s: %s%s>", type, str(method.selector), method.statements != null ? "filled" : "blank",
|
||||
Eclipse.isGenerated(method) ? " (GENERATED)" : "");
|
||||
indent++;
|
||||
if ( printContent ) {
|
||||
if ( method.statements != null ) print("%s", method);
|
||||
if (printContent) {
|
||||
if (method.statements != null) print("%s", method);
|
||||
disablePrinting++;
|
||||
}
|
||||
}
|
||||
|
||||
public void visitAnnotationOnMethod(AbstractMethodDeclaration method, Node node, Annotation annotation) {
|
||||
public void visitAnnotationOnMethod(AbstractMethodDeclaration method, EclipseNode node, Annotation annotation) {
|
||||
forcePrint("<ANNOTATION%s: %s />", Eclipse.isGenerated(method) ? " (GENERATED)" : "", annotation);
|
||||
}
|
||||
|
||||
public void endVisitMethod(Node node, AbstractMethodDeclaration method) {
|
||||
if ( printContent ) disablePrinting--;
|
||||
public void endVisitMethod(EclipseNode node, AbstractMethodDeclaration method) {
|
||||
if (printContent) disablePrinting--;
|
||||
String type = method instanceof ConstructorDeclaration ? "CONSTRUCTOR" : "METHOD";
|
||||
indent--;
|
||||
print("</%s %s>", type, str(method.selector));
|
||||
}
|
||||
|
||||
public void visitMethodArgument(Node node, Argument arg, AbstractMethodDeclaration method) {
|
||||
public void visitMethodArgument(EclipseNode node, Argument arg, AbstractMethodDeclaration method) {
|
||||
print("<METHODARG%s %s %s = %s>", Eclipse.isGenerated(arg) ? " (GENERATED)" : "", str(arg.type), str(arg.name), arg.initialization);
|
||||
indent++;
|
||||
}
|
||||
|
||||
public void visitAnnotationOnMethodArgument(Argument arg, AbstractMethodDeclaration method, Node node, Annotation annotation) {
|
||||
public void visitAnnotationOnMethodArgument(Argument arg, AbstractMethodDeclaration method, EclipseNode node, Annotation annotation) {
|
||||
print("<ANNOTATION%s: %s />", Eclipse.isGenerated(annotation) ? " (GENERATED)" : "", annotation);
|
||||
}
|
||||
|
||||
public void endVisitMethodArgument(Node node, Argument arg, AbstractMethodDeclaration method) {
|
||||
public void endVisitMethodArgument(EclipseNode node, Argument arg, AbstractMethodDeclaration method) {
|
||||
indent--;
|
||||
print("</METHODARG %s %s>", str(arg.type), str(arg.name));
|
||||
}
|
||||
|
||||
public void visitLocal(Node node, LocalDeclaration local) {
|
||||
public void visitLocal(EclipseNode node, LocalDeclaration local) {
|
||||
print("<LOCAL%s %s %s = %s>", Eclipse.isGenerated(local) ? " (GENERATED)" : "", str(local.type), str(local.name), local.initialization);
|
||||
indent++;
|
||||
}
|
||||
|
||||
public void visitAnnotationOnLocal(LocalDeclaration local, Node node, Annotation annotation) {
|
||||
public void visitAnnotationOnLocal(LocalDeclaration local, EclipseNode node, Annotation annotation) {
|
||||
print("<ANNOTATION%s: %s />", Eclipse.isGenerated(annotation) ? " (GENERATED)" : "", annotation);
|
||||
}
|
||||
|
||||
public void endVisitLocal(Node node, LocalDeclaration local) {
|
||||
public void endVisitLocal(EclipseNode node, LocalDeclaration local) {
|
||||
indent--;
|
||||
print("</LOCAL %s %s>", str(local.type), str(local.name));
|
||||
}
|
||||
|
||||
public void visitStatement(Node node, Statement statement) {
|
||||
public void visitStatement(EclipseNode node, Statement statement) {
|
||||
print("<%s%s>", statement.getClass(), Eclipse.isGenerated(statement) ? " (GENERATED)" : "");
|
||||
indent++;
|
||||
print("%s", statement);
|
||||
}
|
||||
|
||||
public void endVisitStatement(Node node, Statement statement) {
|
||||
public void endVisitStatement(EclipseNode node, Statement statement) {
|
||||
indent--;
|
||||
print("</%s>", statement.getClass());
|
||||
}
|
||||
|
||||
@@ -50,5 +50,5 @@ public interface EclipseAnnotationHandler<T extends java.lang.annotation.Annotat
|
||||
* @return <code>true</code> if you don't want to be called again about this annotation during this
|
||||
* compile session (you've handled it), or <code>false</code> to indicate you aren't done yet.
|
||||
*/
|
||||
boolean handle(AnnotationValues<T> annotation, org.eclipse.jdt.internal.compiler.ast.Annotation ast, EclipseAST.Node annotationNode);
|
||||
boolean handle(AnnotationValues<T> annotation, org.eclipse.jdt.internal.compiler.ast.Annotation ast, EclipseNode annotationNode);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,175 @@
|
||||
/*
|
||||
* Copyright © 2009 Reinier Zwitserloot and Roel Spilker.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
package lombok.eclipse;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import lombok.core.AST.Kind;
|
||||
|
||||
import org.eclipse.jdt.internal.compiler.ast.ASTNode;
|
||||
import org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration;
|
||||
import org.eclipse.jdt.internal.compiler.ast.Annotation;
|
||||
import org.eclipse.jdt.internal.compiler.ast.Argument;
|
||||
import org.eclipse.jdt.internal.compiler.ast.Clinit;
|
||||
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;
|
||||
|
||||
/**
|
||||
* Eclipse specific version of the LombokNode class.
|
||||
*/
|
||||
public class EclipseNode extends lombok.core.LombokNode<EclipseAST, EclipseNode, ASTNode> {
|
||||
/** {@inheritDoc} */
|
||||
EclipseNode(EclipseAST ast, ASTNode node, List<EclipseNode> children, Kind kind) {
|
||||
super(ast, node, children, kind);
|
||||
}
|
||||
|
||||
/**
|
||||
* Visits this node and all child nodes depth-first, calling the provided visitor's visit methods.
|
||||
*/
|
||||
public void traverse(EclipseASTVisitor visitor) {
|
||||
switch (getKind()) {
|
||||
case COMPILATION_UNIT:
|
||||
visitor.visitCompilationUnit(this, (CompilationUnitDeclaration)get());
|
||||
ast.traverseChildren(visitor, this);
|
||||
visitor.endVisitCompilationUnit(this, (CompilationUnitDeclaration)get());
|
||||
break;
|
||||
case TYPE:
|
||||
visitor.visitType(this, (TypeDeclaration)get());
|
||||
ast.traverseChildren(visitor, this);
|
||||
visitor.endVisitType(this, (TypeDeclaration)get());
|
||||
break;
|
||||
case FIELD:
|
||||
visitor.visitField(this, (FieldDeclaration)get());
|
||||
ast.traverseChildren(visitor, this);
|
||||
visitor.endVisitField(this, (FieldDeclaration)get());
|
||||
break;
|
||||
case INITIALIZER:
|
||||
visitor.visitInitializer(this, (Initializer)get());
|
||||
ast.traverseChildren(visitor, this);
|
||||
visitor.endVisitInitializer(this, (Initializer)get());
|
||||
break;
|
||||
case METHOD:
|
||||
if (get() instanceof Clinit) return;
|
||||
visitor.visitMethod(this, (AbstractMethodDeclaration)get());
|
||||
ast.traverseChildren(visitor, this);
|
||||
visitor.endVisitMethod(this, (AbstractMethodDeclaration)get());
|
||||
break;
|
||||
case ARGUMENT:
|
||||
AbstractMethodDeclaration method = (AbstractMethodDeclaration)up().get();
|
||||
visitor.visitMethodArgument(this, (Argument)get(), method);
|
||||
ast.traverseChildren(visitor, this);
|
||||
visitor.endVisitMethodArgument(this, (Argument)get(), method);
|
||||
break;
|
||||
case LOCAL:
|
||||
visitor.visitLocal(this, (LocalDeclaration)get());
|
||||
ast.traverseChildren(visitor, this);
|
||||
visitor.endVisitLocal(this, (LocalDeclaration)get());
|
||||
break;
|
||||
case ANNOTATION:
|
||||
switch (up().getKind()) {
|
||||
case TYPE:
|
||||
visitor.visitAnnotationOnType((TypeDeclaration)up().get(), this, (Annotation)get());
|
||||
break;
|
||||
case FIELD:
|
||||
visitor.visitAnnotationOnField((FieldDeclaration)up().get(), this, (Annotation)get());
|
||||
break;
|
||||
case METHOD:
|
||||
visitor.visitAnnotationOnMethod((AbstractMethodDeclaration)up().get(), this, (Annotation)get());
|
||||
break;
|
||||
case ARGUMENT:
|
||||
visitor.visitAnnotationOnMethodArgument(
|
||||
(Argument)parent.get(),
|
||||
(AbstractMethodDeclaration)parent.directUp().get(),
|
||||
this, (Annotation)get());
|
||||
break;
|
||||
case LOCAL:
|
||||
visitor.visitAnnotationOnLocal((LocalDeclaration)parent.get(), this, (Annotation)get());
|
||||
break;
|
||||
default:
|
||||
throw new AssertionError("Annotion not expected as child of a " + up().getKind());
|
||||
}
|
||||
break;
|
||||
case STATEMENT:
|
||||
visitor.visitStatement(this, (Statement)get());
|
||||
ast.traverseChildren(visitor, this);
|
||||
visitor.endVisitStatement(this, (Statement)get());
|
||||
break;
|
||||
default:
|
||||
throw new AssertionError("Unexpected kind during node traversal: " + getKind());
|
||||
}
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override public String getName() {
|
||||
final char[] n;
|
||||
if (node instanceof TypeDeclaration) n = ((TypeDeclaration)node).name;
|
||||
else if (node instanceof FieldDeclaration) n = ((FieldDeclaration)node).name;
|
||||
else if (node instanceof AbstractMethodDeclaration) n = ((AbstractMethodDeclaration)node).selector;
|
||||
else if (node instanceof LocalDeclaration) n = ((LocalDeclaration)node).name;
|
||||
else n = null;
|
||||
|
||||
return n == null ? null : new String(n);
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override public void addError(String message) {
|
||||
this.addError(message, this.get().sourceStart, this.get().sourceEnd);
|
||||
}
|
||||
|
||||
/** Generate a compiler error that shows the wavy underline from-to the stated character positions. */
|
||||
public void addError(String message, int sourceStart, int sourceEnd) {
|
||||
ast.addProblem(ast.new ParseProblem(false, message, sourceStart, sourceEnd));
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override public void addWarning(String message) {
|
||||
this.addWarning(message, this.get().sourceStart, this.get().sourceEnd);
|
||||
}
|
||||
|
||||
/** Generate a compiler warning that shows the wavy underline from-to the stated character positions. */
|
||||
public void addWarning(String message, int sourceStart, int sourceEnd) {
|
||||
ast.addProblem(ast.new ParseProblem(true, message, sourceStart, sourceEnd));
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override protected 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;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convenient shortcut to the owning EclipseAST object's isCompleteParse method.
|
||||
*
|
||||
* @see EclipseAST#isCompleteParse()
|
||||
*/
|
||||
public boolean isCompleteParse() {
|
||||
return ast.isCompleteParse();
|
||||
}
|
||||
}
|
||||
@@ -37,7 +37,6 @@ import lombok.core.SpiLoadUtil;
|
||||
import lombok.core.TypeLibrary;
|
||||
import lombok.core.TypeResolver;
|
||||
import lombok.core.AnnotationValues.AnnotationValueDecodeFail;
|
||||
import lombok.eclipse.EclipseAST.Node;
|
||||
|
||||
import org.eclipse.jdt.internal.compiler.ast.CompilationUnitDeclaration;
|
||||
import org.eclipse.jdt.internal.compiler.ast.TypeReference;
|
||||
@@ -67,7 +66,7 @@ public class HandlerLibrary {
|
||||
}
|
||||
|
||||
public boolean handle(org.eclipse.jdt.internal.compiler.ast.Annotation annotation,
|
||||
final Node annotationNode) {
|
||||
final EclipseNode annotationNode) {
|
||||
AnnotationValues<T> annValues = Eclipse.createAnnotation(annotationClass, annotationNode);
|
||||
return handler.handle(annValues, annotation, annotationNode);
|
||||
}
|
||||
@@ -110,7 +109,7 @@ public class HandlerLibrary {
|
||||
Eclipse.error(null, "Can't load Lombok annotation handler for Eclipse: ", t);
|
||||
}
|
||||
}
|
||||
} catch ( IOException e ) {
|
||||
} catch (IOException e) {
|
||||
Lombok.sneakyThrow(e);
|
||||
}
|
||||
}
|
||||
@@ -121,7 +120,7 @@ public class HandlerLibrary {
|
||||
for (EclipseASTVisitor visitor : SpiLoadUtil.findServices(EclipseASTVisitor.class)) {
|
||||
lib.visitorHandlers.add(visitor);
|
||||
}
|
||||
} catch ( Throwable t ) {
|
||||
} catch (Throwable t) {
|
||||
throw Lombok.sneakyThrow(t);
|
||||
}
|
||||
}
|
||||
@@ -143,27 +142,27 @@ public class HandlerLibrary {
|
||||
* @param annotationNode The Lombok AST Node representing the Annotation AST Node.
|
||||
* @param annotation 'node.get()' - convenience parameter.
|
||||
*/
|
||||
public boolean handle(CompilationUnitDeclaration ast, EclipseAST.Node annotationNode,
|
||||
public boolean handle(CompilationUnitDeclaration ast, EclipseNode annotationNode,
|
||||
org.eclipse.jdt.internal.compiler.ast.Annotation annotation) {
|
||||
String pkgName = annotationNode.getPackageDeclaration();
|
||||
Collection<String> imports = annotationNode.getImportStatements();
|
||||
|
||||
TypeResolver resolver = new TypeResolver(typeLibrary, pkgName, imports);
|
||||
TypeReference rawType = annotation.type;
|
||||
if ( rawType == null ) return false;
|
||||
if (rawType == null) return false;
|
||||
boolean handled = false;
|
||||
for ( String fqn : resolver.findTypeMatches(annotationNode, toQualifiedName(annotation.type.getTypeName())) ) {
|
||||
for (String fqn : resolver.findTypeMatches(annotationNode, toQualifiedName(annotation.type.getTypeName()))) {
|
||||
boolean isPrintAST = fqn.equals(PrintAST.class.getName());
|
||||
if ( isPrintAST == skipPrintAST ) continue;
|
||||
if (isPrintAST == skipPrintAST) continue;
|
||||
AnnotationHandlerContainer<?> container = annotationHandlers.get(fqn);
|
||||
|
||||
if ( container == null ) continue;
|
||||
if (container == null) continue;
|
||||
|
||||
try {
|
||||
handled |= container.handle(annotation, annotationNode);
|
||||
} catch ( AnnotationValueDecodeFail fail ) {
|
||||
} catch (AnnotationValueDecodeFail fail) {
|
||||
fail.owner.setError(fail.getMessage(), fail.idx);
|
||||
} catch ( Throwable t ) {
|
||||
} catch (Throwable t) {
|
||||
Eclipse.error(ast, String.format("Lombok annotation handler %s failed", container.handler.getClass()), t);
|
||||
}
|
||||
}
|
||||
@@ -175,9 +174,9 @@ public class HandlerLibrary {
|
||||
* Will call all registered {@link EclipseASTVisitor} instances.
|
||||
*/
|
||||
public void callASTVisitors(EclipseAST ast) {
|
||||
for ( EclipseASTVisitor visitor : visitorHandlers ) try {
|
||||
for (EclipseASTVisitor visitor : visitorHandlers) try {
|
||||
ast.traverse(visitor);
|
||||
} catch ( Throwable t ) {
|
||||
} catch (Throwable t) {
|
||||
Eclipse.error((CompilationUnitDeclaration) ast.top().get(),
|
||||
String.format("Lombok visitor handler %s failed", visitor.getClass()), t);
|
||||
}
|
||||
|
||||
@@ -23,7 +23,6 @@ package lombok.eclipse;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
|
||||
import lombok.eclipse.EclipseAST.Node;
|
||||
import lombok.patcher.Symbols;
|
||||
|
||||
import org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration;
|
||||
@@ -62,10 +61,10 @@ public class TransformEclipseAST {
|
||||
try {
|
||||
l = HandlerLibrary.load();
|
||||
f = CompilationUnitDeclaration.class.getDeclaredField("$lombokAST");
|
||||
} catch ( Throwable t ) {
|
||||
} catch (Throwable t) {
|
||||
try {
|
||||
Eclipse.error(null, "Problem initializing lombok", t);
|
||||
} catch ( Throwable t2) {
|
||||
} catch (Throwable t2) {
|
||||
System.err.println("Problem initializing lombok");
|
||||
t.printStackTrace();
|
||||
}
|
||||
@@ -125,19 +124,19 @@ public class TransformEclipseAST {
|
||||
}
|
||||
|
||||
private static EclipseAST getCache(CompilationUnitDeclaration ast) {
|
||||
if ( astCacheField == null ) return null;
|
||||
if (astCacheField == null) return null;
|
||||
try {
|
||||
return (EclipseAST)astCacheField.get(ast);
|
||||
} catch ( Exception e ) {
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private static void setCache(CompilationUnitDeclaration ast, EclipseAST cache) {
|
||||
if ( astCacheField != null ) try {
|
||||
if (astCacheField != null) try {
|
||||
astCacheField.set(ast, cache);
|
||||
} catch ( Exception ignore ) {
|
||||
} catch (Exception ignore) {
|
||||
ignore.printStackTrace();
|
||||
}
|
||||
}
|
||||
@@ -159,39 +158,39 @@ public class TransformEclipseAST {
|
||||
}
|
||||
|
||||
private static class AnnotationVisitor extends EclipseASTAdapter {
|
||||
@Override public void visitAnnotationOnField(FieldDeclaration field, Node annotationNode, Annotation annotation) {
|
||||
if ( annotationNode.isHandled() ) return;
|
||||
@Override public void visitAnnotationOnField(FieldDeclaration field, EclipseNode annotationNode, Annotation annotation) {
|
||||
if (annotationNode.isHandled()) return;
|
||||
CompilationUnitDeclaration top = (CompilationUnitDeclaration) annotationNode.top().get();
|
||||
boolean handled = handlers.handle(top, annotationNode, annotation);
|
||||
if ( handled ) annotationNode.setHandled();
|
||||
if (handled) annotationNode.setHandled();
|
||||
}
|
||||
|
||||
@Override public void visitAnnotationOnMethodArgument(Argument arg, AbstractMethodDeclaration method, Node annotationNode, Annotation annotation) {
|
||||
if ( annotationNode.isHandled() ) return;
|
||||
@Override public void visitAnnotationOnMethodArgument(Argument arg, AbstractMethodDeclaration method, EclipseNode annotationNode, Annotation annotation) {
|
||||
if (annotationNode.isHandled()) return;
|
||||
CompilationUnitDeclaration top = (CompilationUnitDeclaration) annotationNode.top().get();
|
||||
boolean handled = handlers.handle(top, annotationNode, annotation);
|
||||
if ( handled ) annotationNode.setHandled();
|
||||
if (handled) annotationNode.setHandled();
|
||||
}
|
||||
|
||||
@Override public void visitAnnotationOnLocal(LocalDeclaration local, Node annotationNode, Annotation annotation) {
|
||||
if ( annotationNode.isHandled() ) return;
|
||||
@Override public void visitAnnotationOnLocal(LocalDeclaration local, EclipseNode annotationNode, Annotation annotation) {
|
||||
if (annotationNode.isHandled()) return;
|
||||
CompilationUnitDeclaration top = (CompilationUnitDeclaration) annotationNode.top().get();
|
||||
boolean handled = handlers.handle(top, annotationNode, annotation);
|
||||
if ( handled ) annotationNode.setHandled();
|
||||
if (handled) annotationNode.setHandled();
|
||||
}
|
||||
|
||||
@Override public void visitAnnotationOnMethod(AbstractMethodDeclaration method, Node annotationNode, Annotation annotation) {
|
||||
if ( annotationNode.isHandled() ) return;
|
||||
@Override public void visitAnnotationOnMethod(AbstractMethodDeclaration method, EclipseNode annotationNode, Annotation annotation) {
|
||||
if (annotationNode.isHandled()) return;
|
||||
CompilationUnitDeclaration top = (CompilationUnitDeclaration) annotationNode.top().get();
|
||||
boolean handled = handlers.handle(top, annotationNode, annotation);
|
||||
if ( handled ) annotationNode.setHandled();
|
||||
if (handled) annotationNode.setHandled();
|
||||
}
|
||||
|
||||
@Override public void visitAnnotationOnType(TypeDeclaration type, Node annotationNode, Annotation annotation) {
|
||||
if ( annotationNode.isHandled() ) return;
|
||||
@Override public void visitAnnotationOnType(TypeDeclaration type, EclipseNode annotationNode, Annotation annotation) {
|
||||
if (annotationNode.isHandled()) return;
|
||||
CompilationUnitDeclaration top = (CompilationUnitDeclaration) annotationNode.top().get();
|
||||
boolean handled = handlers.handle(top, annotationNode, annotation);
|
||||
if ( handled ) annotationNode.setHandled();
|
||||
if (handled) annotationNode.setHandled();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -28,7 +28,7 @@ import lombok.core.AnnotationValues;
|
||||
import lombok.core.AST.Kind;
|
||||
import lombok.eclipse.Eclipse;
|
||||
import lombok.eclipse.EclipseAnnotationHandler;
|
||||
import lombok.eclipse.EclipseAST.Node;
|
||||
import lombok.eclipse.EclipseNode;
|
||||
|
||||
import org.eclipse.jdt.internal.compiler.ast.ASTNode;
|
||||
import org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration;
|
||||
@@ -51,37 +51,37 @@ import org.mangosdk.spi.ProviderFor;
|
||||
*/
|
||||
@ProviderFor(EclipseAnnotationHandler.class)
|
||||
public class HandleCleanup implements EclipseAnnotationHandler<Cleanup> {
|
||||
public boolean handle(AnnotationValues<Cleanup> annotation, Annotation ast, Node annotationNode) {
|
||||
public boolean handle(AnnotationValues<Cleanup> annotation, Annotation ast, EclipseNode annotationNode) {
|
||||
String cleanupName = annotation.getInstance().value();
|
||||
if ( cleanupName.length() == 0 ) {
|
||||
if (cleanupName.length() == 0) {
|
||||
annotationNode.addError("cleanupName cannot be the empty string.");
|
||||
return true;
|
||||
}
|
||||
|
||||
if ( annotationNode.up().getKind() != Kind.LOCAL ) {
|
||||
if (annotationNode.up().getKind() != Kind.LOCAL) {
|
||||
annotationNode.addError("@Cleanup is legal only on local variable declarations.");
|
||||
return true;
|
||||
}
|
||||
|
||||
LocalDeclaration decl = (LocalDeclaration)annotationNode.up().get();
|
||||
|
||||
if ( decl.initialization == null ) {
|
||||
if (decl.initialization == null) {
|
||||
annotationNode.addError("@Cleanup variable declarations need to be initialized.");
|
||||
return true;
|
||||
}
|
||||
|
||||
Node ancestor = annotationNode.up().directUp();
|
||||
EclipseNode ancestor = annotationNode.up().directUp();
|
||||
ASTNode blockNode = ancestor.get();
|
||||
|
||||
final boolean isSwitch;
|
||||
final Statement[] statements;
|
||||
if ( blockNode instanceof AbstractMethodDeclaration ) {
|
||||
if (blockNode instanceof AbstractMethodDeclaration) {
|
||||
isSwitch = false;
|
||||
statements = ((AbstractMethodDeclaration)blockNode).statements;
|
||||
} else if ( blockNode instanceof Block ) {
|
||||
} else if (blockNode instanceof Block) {
|
||||
isSwitch = false;
|
||||
statements = ((Block)blockNode).statements;
|
||||
} else if ( blockNode instanceof SwitchStatement ) {
|
||||
} else if (blockNode instanceof SwitchStatement) {
|
||||
isSwitch = true;
|
||||
statements = ((SwitchStatement)blockNode).statements;
|
||||
} else {
|
||||
@@ -89,17 +89,17 @@ public class HandleCleanup implements EclipseAnnotationHandler<Cleanup> {
|
||||
return true;
|
||||
}
|
||||
|
||||
if ( statements == null ) {
|
||||
if (statements == null) {
|
||||
annotationNode.addError("LOMBOK BUG: Parent block does not contain any statements.");
|
||||
return true;
|
||||
}
|
||||
|
||||
int start = 0;
|
||||
for ( ; start < statements.length ; start++ ) {
|
||||
if ( statements[start] == decl ) break;
|
||||
for (; start < statements.length ; start++) {
|
||||
if (statements[start] == decl) break;
|
||||
}
|
||||
|
||||
if ( start == statements.length ) {
|
||||
if (start == statements.length) {
|
||||
annotationNode.addError("LOMBOK BUG: Can't find this local variable declaration inside its parent.");
|
||||
return true;
|
||||
}
|
||||
@@ -107,10 +107,10 @@ public class HandleCleanup implements EclipseAnnotationHandler<Cleanup> {
|
||||
start++; //We start with try{} *AFTER* the var declaration.
|
||||
|
||||
int end;
|
||||
if ( isSwitch ) {
|
||||
if (isSwitch) {
|
||||
end = start + 1;
|
||||
for ( ; end < statements.length ; end++ ) {
|
||||
if ( statements[end] instanceof CaseStatement ) {
|
||||
for (; end < statements.length ; end++) {
|
||||
if (statements[end] instanceof CaseStatement) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -149,8 +149,8 @@ public class HandleCleanup implements EclipseAnnotationHandler<Cleanup> {
|
||||
Eclipse.setGeneratedBy(receiver, ast);
|
||||
unsafeClose.receiver = receiver;
|
||||
long nameSourcePosition = (long)ast.sourceStart << 32 | ast.sourceEnd;
|
||||
if ( ast.memberValuePairs() != null ) for ( MemberValuePair pair : ast.memberValuePairs() ) {
|
||||
if ( pair.name != null && new String(pair.name).equals("value") ) {
|
||||
if (ast.memberValuePairs() != null) for (MemberValuePair pair : ast.memberValuePairs()) {
|
||||
if (pair.name != null && new String(pair.name).equals("value")) {
|
||||
nameSourcePosition = (long)pair.value.sourceStart << 32 | pair.value.sourceEnd;
|
||||
break;
|
||||
}
|
||||
@@ -165,11 +165,11 @@ public class HandleCleanup implements EclipseAnnotationHandler<Cleanup> {
|
||||
tryStatement.catchArguments = null;
|
||||
tryStatement.catchBlocks = null;
|
||||
|
||||
if ( blockNode instanceof AbstractMethodDeclaration ) {
|
||||
if (blockNode instanceof AbstractMethodDeclaration) {
|
||||
((AbstractMethodDeclaration)blockNode).statements = newStatements;
|
||||
} else if ( blockNode instanceof Block ) {
|
||||
} else if (blockNode instanceof Block) {
|
||||
((Block)blockNode).statements = newStatements;
|
||||
} else if ( blockNode instanceof SwitchStatement ) {
|
||||
} else if (blockNode instanceof SwitchStatement) {
|
||||
((SwitchStatement)blockNode).statements = newStatements;
|
||||
}
|
||||
|
||||
@@ -178,21 +178,21 @@ public class HandleCleanup implements EclipseAnnotationHandler<Cleanup> {
|
||||
return true;
|
||||
}
|
||||
|
||||
private void doAssignmentCheck(Node node, Statement[] tryBlock, char[] varName) {
|
||||
for ( Statement statement : tryBlock ) doAssignmentCheck0(node, statement, varName);
|
||||
private void doAssignmentCheck(EclipseNode node, Statement[] tryBlock, char[] varName) {
|
||||
for (Statement statement : tryBlock) doAssignmentCheck0(node, statement, varName);
|
||||
}
|
||||
|
||||
private void doAssignmentCheck0(Node node, Statement statement, char[] varName) {
|
||||
if ( statement instanceof Assignment )
|
||||
private void doAssignmentCheck0(EclipseNode node, Statement statement, char[] varName) {
|
||||
if (statement instanceof Assignment)
|
||||
doAssignmentCheck0(node, ((Assignment)statement).expression, varName);
|
||||
else if ( statement instanceof LocalDeclaration )
|
||||
else if (statement instanceof LocalDeclaration)
|
||||
doAssignmentCheck0(node, ((LocalDeclaration)statement).initialization, varName);
|
||||
else if ( statement instanceof CastExpression )
|
||||
else if (statement instanceof CastExpression)
|
||||
doAssignmentCheck0(node, ((CastExpression)statement).expression, varName);
|
||||
else if ( statement instanceof SingleNameReference ) {
|
||||
if ( Arrays.equals(((SingleNameReference)statement).token, varName) ) {
|
||||
Node problemNode = node.getNodeFor(statement);
|
||||
if ( problemNode != null ) problemNode.addWarning(
|
||||
else if (statement instanceof SingleNameReference) {
|
||||
if (Arrays.equals(((SingleNameReference)statement).token, varName)) {
|
||||
EclipseNode problemNode = node.getNodeFor(statement);
|
||||
if (problemNode != null) problemNode.addWarning(
|
||||
"You're assigning an auto-cleanup variable to something else. This is a bad idea.");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -36,7 +36,7 @@ import lombok.core.TransformationsUtil;
|
||||
import lombok.core.AST.Kind;
|
||||
import lombok.eclipse.Eclipse;
|
||||
import lombok.eclipse.EclipseAnnotationHandler;
|
||||
import lombok.eclipse.EclipseAST.Node;
|
||||
import lombok.eclipse.EclipseNode;
|
||||
import lombok.eclipse.handlers.PKG.MemberExistsResult;
|
||||
|
||||
import org.eclipse.jdt.internal.compiler.ast.ASTNode;
|
||||
@@ -68,32 +68,32 @@ import org.mangosdk.spi.ProviderFor;
|
||||
*/
|
||||
@ProviderFor(EclipseAnnotationHandler.class)
|
||||
public class HandleData implements EclipseAnnotationHandler<Data> {
|
||||
public boolean handle(AnnotationValues<Data> annotation, Annotation ast, Node annotationNode) {
|
||||
public boolean handle(AnnotationValues<Data> annotation, Annotation ast, EclipseNode annotationNode) {
|
||||
Data ann = annotation.getInstance();
|
||||
Node typeNode = annotationNode.up();
|
||||
EclipseNode typeNode = annotationNode.up();
|
||||
|
||||
TypeDeclaration typeDecl = null;
|
||||
if ( typeNode.get() instanceof TypeDeclaration ) typeDecl = (TypeDeclaration) typeNode.get();
|
||||
if (typeNode.get() instanceof TypeDeclaration) typeDecl = (TypeDeclaration) typeNode.get();
|
||||
int modifiers = typeDecl == null ? 0 : typeDecl.modifiers;
|
||||
boolean notAClass = (modifiers &
|
||||
(ClassFileConstants.AccInterface | ClassFileConstants.AccAnnotation | ClassFileConstants.AccEnum)) != 0;
|
||||
|
||||
if ( typeDecl == null || notAClass ) {
|
||||
if (typeDecl == null || notAClass) {
|
||||
annotationNode.addError("@Data is only supported on a class.");
|
||||
return false;
|
||||
}
|
||||
|
||||
List<Node> nodesForConstructor = new ArrayList<Node>();
|
||||
for ( Node child : typeNode.down() ) {
|
||||
if ( child.getKind() != Kind.FIELD ) continue;
|
||||
List<EclipseNode> nodesForConstructor = new ArrayList<EclipseNode>();
|
||||
for (EclipseNode child : typeNode.down()) {
|
||||
if (child.getKind() != Kind.FIELD) continue;
|
||||
FieldDeclaration fieldDecl = (FieldDeclaration) child.get();
|
||||
//Skip static fields.
|
||||
if ( (fieldDecl.modifiers & ClassFileConstants.AccStatic) != 0 ) continue;
|
||||
if ((fieldDecl.modifiers & ClassFileConstants.AccStatic) != 0) continue;
|
||||
boolean isFinal = (fieldDecl.modifiers & ClassFileConstants.AccFinal) != 0;
|
||||
boolean isNonNull = findAnnotations(fieldDecl, TransformationsUtil.NON_NULL_PATTERN).length != 0;
|
||||
if ( (isFinal || isNonNull) && fieldDecl.initialization == null ) nodesForConstructor.add(child);
|
||||
if ((isFinal || isNonNull) && fieldDecl.initialization == null) nodesForConstructor.add(child);
|
||||
new HandleGetter().generateGetterForField(child, annotationNode.get());
|
||||
if ( !isFinal ) new HandleSetter().generateSetterForField(child, annotationNode.get());
|
||||
if (!isFinal) new HandleSetter().generateSetterForField(child, annotationNode.get());
|
||||
}
|
||||
|
||||
new HandleToString().generateToStringForType(typeNode, annotationNode);
|
||||
@@ -102,17 +102,17 @@ public class HandleData implements EclipseAnnotationHandler<Data> {
|
||||
//Careful: Generate the public static constructor (if there is one) LAST, so that any attempt to
|
||||
//'find callers' on the annotation node will find callers of the constructor, which is by far the
|
||||
//most useful of the many methods built by @Data. This trick won't work for the non-static constructor,
|
||||
//for whatever reason, though you can find callers of that one by focussing on the class name itself
|
||||
//for whatever reason, though you can find callers of that one by focusing on the class name itself
|
||||
//and hitting 'find callers'.
|
||||
|
||||
if ( constructorExists(typeNode) == MemberExistsResult.NOT_EXISTS ) {
|
||||
if (constructorExists(typeNode) == MemberExistsResult.NOT_EXISTS) {
|
||||
ConstructorDeclaration constructor = createConstructor(
|
||||
ann.staticConstructor().length() == 0, typeNode, nodesForConstructor, ast);
|
||||
injectMethod(typeNode, constructor);
|
||||
}
|
||||
|
||||
if ( ann.staticConstructor().length() > 0 ) {
|
||||
if ( methodExists("of", typeNode) == MemberExistsResult.NOT_EXISTS ) {
|
||||
if (ann.staticConstructor().length() > 0) {
|
||||
if (methodExists("of", typeNode) == MemberExistsResult.NOT_EXISTS) {
|
||||
MethodDeclaration staticConstructor = createStaticConstructor(
|
||||
ann.staticConstructor(), typeNode, nodesForConstructor, ast);
|
||||
injectMethod(typeNode, staticConstructor);
|
||||
@@ -122,7 +122,8 @@ public class HandleData implements EclipseAnnotationHandler<Data> {
|
||||
return false;
|
||||
}
|
||||
|
||||
private ConstructorDeclaration createConstructor(boolean isPublic, Node type, Collection<Node> fields, ASTNode source) {
|
||||
private ConstructorDeclaration createConstructor(boolean isPublic,
|
||||
EclipseNode type, Collection<EclipseNode> fields, ASTNode source) {
|
||||
long p = (long)source.sourceStart << 32 | source.sourceEnd;
|
||||
|
||||
ConstructorDeclaration constructor = new ConstructorDeclaration(
|
||||
@@ -145,7 +146,7 @@ public class HandleData implements EclipseAnnotationHandler<Data> {
|
||||
List<Statement> assigns = new ArrayList<Statement>();
|
||||
List<Statement> nullChecks = new ArrayList<Statement>();
|
||||
|
||||
for ( Node fieldNode : fields ) {
|
||||
for (EclipseNode fieldNode : fields) {
|
||||
FieldDeclaration field = (FieldDeclaration) fieldNode.get();
|
||||
FieldReference thisX = new FieldReference(("this." + new String(field.name)).toCharArray(), p);
|
||||
Eclipse.setGeneratedBy(thisX, source);
|
||||
@@ -178,7 +179,7 @@ public class HandleData implements EclipseAnnotationHandler<Data> {
|
||||
return constructor;
|
||||
}
|
||||
|
||||
private MethodDeclaration createStaticConstructor(String name, Node type, Collection<Node> fields, ASTNode source) {
|
||||
private MethodDeclaration createStaticConstructor(String name, EclipseNode type, Collection<EclipseNode> fields, ASTNode source) {
|
||||
int pS = source.sourceStart, pE = source.sourceEnd;
|
||||
long p = (long)pS << 32 | pE;
|
||||
|
||||
@@ -188,10 +189,10 @@ public class HandleData implements EclipseAnnotationHandler<Data> {
|
||||
|
||||
constructor.modifiers = PKG.toModifier(AccessLevel.PUBLIC) | Modifier.STATIC;
|
||||
TypeDeclaration typeDecl = (TypeDeclaration) type.get();
|
||||
if ( typeDecl.typeParameters != null && typeDecl.typeParameters.length > 0 ) {
|
||||
if (typeDecl.typeParameters != null && typeDecl.typeParameters.length > 0) {
|
||||
TypeReference[] refs = new TypeReference[typeDecl.typeParameters.length];
|
||||
int idx = 0;
|
||||
for ( TypeParameter param : typeDecl.typeParameters ) {
|
||||
for (TypeParameter param : typeDecl.typeParameters) {
|
||||
TypeReference typeRef = new SingleTypeReference(param.name, (long)param.sourceStart << 32 | param.sourceEnd);
|
||||
Eclipse.setGeneratedBy(typeRef, source);
|
||||
refs[idx++] = typeRef;
|
||||
@@ -214,7 +215,7 @@ public class HandleData implements EclipseAnnotationHandler<Data> {
|
||||
Eclipse.setGeneratedBy(statement, source);
|
||||
statement.type = copyType(constructor.returnType, source);
|
||||
|
||||
for ( Node fieldNode : fields ) {
|
||||
for (EclipseNode fieldNode : fields) {
|
||||
FieldDeclaration field = (FieldDeclaration) fieldNode.get();
|
||||
long fieldPos = (((long)field.sourceStart) << 32) | field.sourceEnd;
|
||||
SingleNameReference nameRef = new SingleNameReference(field.name, fieldPos);
|
||||
|
||||
@@ -81,7 +81,7 @@ import lombok.core.AnnotationValues;
|
||||
import lombok.core.AST.Kind;
|
||||
import lombok.eclipse.Eclipse;
|
||||
import lombok.eclipse.EclipseAnnotationHandler;
|
||||
import lombok.eclipse.EclipseAST.Node;
|
||||
import lombok.eclipse.EclipseNode;
|
||||
|
||||
/**
|
||||
* Handles the <code>EqualsAndHashCode</code> annotation for eclipse.
|
||||
@@ -91,23 +91,23 @@ public class HandleEqualsAndHashCode implements EclipseAnnotationHandler<EqualsA
|
||||
private static final Set<String> BUILT_IN_TYPES = Collections.unmodifiableSet(new HashSet<String>(Arrays.asList(
|
||||
"byte", "short", "int", "long", "char", "boolean", "double", "float")));
|
||||
|
||||
private void checkForBogusFieldNames(Node type, AnnotationValues<EqualsAndHashCode> annotation) {
|
||||
if ( annotation.isExplicit("exclude") ) {
|
||||
for ( int i : createListOfNonExistentFields(Arrays.asList(annotation.getInstance().exclude()), type, true, true) ) {
|
||||
private void checkForBogusFieldNames(EclipseNode type, AnnotationValues<EqualsAndHashCode> annotation) {
|
||||
if (annotation.isExplicit("exclude")) {
|
||||
for (int i : createListOfNonExistentFields(Arrays.asList(annotation.getInstance().exclude()), type, true, true)) {
|
||||
annotation.setWarning("exclude", "This field does not exist, or would have been excluded anyway.", i);
|
||||
}
|
||||
}
|
||||
if ( annotation.isExplicit("of") ) {
|
||||
for ( int i : createListOfNonExistentFields(Arrays.asList(annotation.getInstance().of()), type, false, false) ) {
|
||||
if (annotation.isExplicit("of")) {
|
||||
for (int i : createListOfNonExistentFields(Arrays.asList(annotation.getInstance().of()), type, false, false)) {
|
||||
annotation.setWarning("of", "This field does not exist.", i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void generateEqualsAndHashCodeForType(Node typeNode, Node errorNode) {
|
||||
for ( Node child : typeNode.down() ) {
|
||||
if ( child.getKind() == Kind.ANNOTATION ) {
|
||||
if ( Eclipse.annotationTypeMatches(EqualsAndHashCode.class, child) ) {
|
||||
public void generateEqualsAndHashCodeForType(EclipseNode typeNode, EclipseNode errorNode) {
|
||||
for (EclipseNode child : typeNode.down()) {
|
||||
if (child.getKind() == Kind.ANNOTATION) {
|
||||
if (Eclipse.annotationTypeMatches(EqualsAndHashCode.class, child)) {
|
||||
//The annotation will make it happen, so we can skip it.
|
||||
return;
|
||||
}
|
||||
@@ -117,20 +117,21 @@ public class HandleEqualsAndHashCode implements EclipseAnnotationHandler<EqualsA
|
||||
generateMethods(typeNode, errorNode, null, null, null, false);
|
||||
}
|
||||
|
||||
@Override public boolean handle(AnnotationValues<EqualsAndHashCode> annotation, Annotation ast, Node annotationNode) {
|
||||
@Override public boolean handle(AnnotationValues<EqualsAndHashCode> annotation,
|
||||
Annotation ast, EclipseNode annotationNode) {
|
||||
EqualsAndHashCode ann = annotation.getInstance();
|
||||
List<String> excludes = Arrays.asList(ann.exclude());
|
||||
List<String> includes = Arrays.asList(ann.of());
|
||||
Node typeNode = annotationNode.up();
|
||||
EclipseNode typeNode = annotationNode.up();
|
||||
|
||||
checkForBogusFieldNames(typeNode, annotation);
|
||||
|
||||
Boolean callSuper = ann.callSuper();
|
||||
if ( !annotation.isExplicit("callSuper") ) callSuper = null;
|
||||
if ( !annotation.isExplicit("exclude") ) excludes = null;
|
||||
if ( !annotation.isExplicit("of") ) includes = null;
|
||||
if (!annotation.isExplicit("callSuper")) callSuper = null;
|
||||
if (!annotation.isExplicit("exclude")) excludes = null;
|
||||
if (!annotation.isExplicit("of")) includes = null;
|
||||
|
||||
if ( excludes != null && includes != null ) {
|
||||
if (excludes != null && includes != null) {
|
||||
excludes = null;
|
||||
annotation.setWarning("exclude", "exclude and of are mutually exclusive; the 'exclude' parameter will be ignored.");
|
||||
}
|
||||
@@ -138,70 +139,70 @@ public class HandleEqualsAndHashCode implements EclipseAnnotationHandler<EqualsA
|
||||
return generateMethods(typeNode, annotationNode, excludes, includes, callSuper, true);
|
||||
}
|
||||
|
||||
public boolean generateMethods(Node typeNode, Node errorNode, List<String> excludes, List<String> includes,
|
||||
public boolean generateMethods(EclipseNode typeNode, EclipseNode errorNode, List<String> excludes, List<String> includes,
|
||||
Boolean callSuper, boolean whineIfExists) {
|
||||
assert excludes == null || includes == null;
|
||||
|
||||
TypeDeclaration typeDecl = null;
|
||||
|
||||
if ( typeNode.get() instanceof TypeDeclaration ) typeDecl = (TypeDeclaration) typeNode.get();
|
||||
if (typeNode.get() instanceof TypeDeclaration) typeDecl = (TypeDeclaration) typeNode.get();
|
||||
int modifiers = typeDecl == null ? 0 : typeDecl.modifiers;
|
||||
boolean notAClass = (modifiers &
|
||||
(ClassFileConstants.AccInterface | ClassFileConstants.AccAnnotation | ClassFileConstants.AccEnum)) != 0;
|
||||
|
||||
if ( typeDecl == null || notAClass ) {
|
||||
if (typeDecl == null || notAClass) {
|
||||
errorNode.addError("@EqualsAndHashCode is only supported on a class.");
|
||||
return false;
|
||||
}
|
||||
|
||||
boolean implicitCallSuper = callSuper == null;
|
||||
|
||||
if ( callSuper == null ) {
|
||||
if (callSuper == null) {
|
||||
try {
|
||||
callSuper = ((Boolean)EqualsAndHashCode.class.getMethod("callSuper").getDefaultValue()).booleanValue();
|
||||
} catch ( Exception ignore ) {}
|
||||
} catch (Exception ignore) {}
|
||||
}
|
||||
|
||||
boolean isDirectDescendantOfObject = true;
|
||||
|
||||
if ( typeDecl.superclass != null ) {
|
||||
if (typeDecl.superclass != null) {
|
||||
String p = typeDecl.superclass.toString();
|
||||
isDirectDescendantOfObject = p.equals("Object") || p.equals("java.lang.Object");
|
||||
}
|
||||
|
||||
if ( isDirectDescendantOfObject && callSuper ) {
|
||||
if (isDirectDescendantOfObject && callSuper) {
|
||||
errorNode.addError("Generating equals/hashCode with a supercall to java.lang.Object is pointless.");
|
||||
return true;
|
||||
}
|
||||
|
||||
if ( !isDirectDescendantOfObject && !callSuper && implicitCallSuper ) {
|
||||
if (!isDirectDescendantOfObject && !callSuper && implicitCallSuper) {
|
||||
errorNode.addWarning("Generating equals/hashCode implementation but without a call to superclass, even though this class does not extend java.lang.Object. If this is intentional, add '@EqualsAndHashCode(callSuper=false)' to your type.");
|
||||
}
|
||||
|
||||
List<Node> nodesForEquality = new ArrayList<Node>();
|
||||
if ( includes != null ) {
|
||||
for ( Node child : typeNode.down() ) {
|
||||
if ( child.getKind() != Kind.FIELD ) continue;
|
||||
List<EclipseNode> nodesForEquality = new ArrayList<EclipseNode>();
|
||||
if (includes != null) {
|
||||
for (EclipseNode child : typeNode.down()) {
|
||||
if (child.getKind() != Kind.FIELD) continue;
|
||||
FieldDeclaration fieldDecl = (FieldDeclaration) child.get();
|
||||
if ( includes.contains(new String(fieldDecl.name)) ) nodesForEquality.add(child);
|
||||
if (includes.contains(new String(fieldDecl.name))) nodesForEquality.add(child);
|
||||
}
|
||||
} else {
|
||||
for ( Node child : typeNode.down() ) {
|
||||
if ( child.getKind() != Kind.FIELD ) continue;
|
||||
for (EclipseNode child : typeNode.down()) {
|
||||
if (child.getKind() != Kind.FIELD) continue;
|
||||
FieldDeclaration fieldDecl = (FieldDeclaration) child.get();
|
||||
//Skip static fields.
|
||||
if ( (fieldDecl.modifiers & ClassFileConstants.AccStatic) != 0 ) continue;
|
||||
if ((fieldDecl.modifiers & ClassFileConstants.AccStatic) != 0) continue;
|
||||
//Skip transient fields.
|
||||
if ( (fieldDecl.modifiers & ClassFileConstants.AccTransient) != 0 ) continue;
|
||||
if ((fieldDecl.modifiers & ClassFileConstants.AccTransient) != 0) continue;
|
||||
//Skip excluded fields.
|
||||
if ( excludes != null && excludes.contains(new String(fieldDecl.name)) ) continue;
|
||||
if (excludes != null && excludes.contains(new String(fieldDecl.name))) continue;
|
||||
//Skip fields that start with $.
|
||||
if ( fieldDecl.name.length > 0 && fieldDecl.name[0] == '$' ) continue;
|
||||
if (fieldDecl.name.length > 0 && fieldDecl.name[0] == '$') continue;
|
||||
nodesForEquality.add(child);
|
||||
}
|
||||
}
|
||||
|
||||
switch ( methodExists("hashCode", typeNode) ) {
|
||||
switch (methodExists("hashCode", typeNode)) {
|
||||
case NOT_EXISTS:
|
||||
MethodDeclaration hashCode = createHashCode(typeNode, nodesForEquality, callSuper, errorNode.get());
|
||||
injectMethod(typeNode, hashCode);
|
||||
@@ -210,13 +211,13 @@ public class HandleEqualsAndHashCode implements EclipseAnnotationHandler<EqualsA
|
||||
break;
|
||||
default:
|
||||
case EXISTS_BY_USER:
|
||||
if ( whineIfExists ) {
|
||||
if (whineIfExists) {
|
||||
errorNode.addWarning("Not generating hashCode(): A method with that name already exists");
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
switch ( methodExists("equals", typeNode) ) {
|
||||
switch (methodExists("equals", typeNode)) {
|
||||
case NOT_EXISTS:
|
||||
MethodDeclaration equals = createEquals(typeNode, nodesForEquality, callSuper, errorNode.get());
|
||||
injectMethod(typeNode, equals);
|
||||
@@ -225,7 +226,7 @@ public class HandleEqualsAndHashCode implements EclipseAnnotationHandler<EqualsA
|
||||
break;
|
||||
default:
|
||||
case EXISTS_BY_USER:
|
||||
if ( whineIfExists ) {
|
||||
if (whineIfExists) {
|
||||
errorNode.addWarning("Not generating equals(Object other): A method with that name already exists");
|
||||
}
|
||||
break;
|
||||
@@ -234,7 +235,7 @@ public class HandleEqualsAndHashCode implements EclipseAnnotationHandler<EqualsA
|
||||
return true;
|
||||
}
|
||||
|
||||
private MethodDeclaration createHashCode(Node type, Collection<Node> fields, boolean callSuper, ASTNode source) {
|
||||
private MethodDeclaration createHashCode(EclipseNode type, Collection<EclipseNode> fields, boolean callSuper, ASTNode source) {
|
||||
int pS = source.sourceStart, pE = source.sourceEnd;
|
||||
long p = (long)pS << 32 | pE;
|
||||
|
||||
@@ -263,7 +264,7 @@ public class HandleEqualsAndHashCode implements EclipseAnnotationHandler<EqualsA
|
||||
|
||||
/* final int PRIME = 31; */ {
|
||||
/* Without fields, PRIME isn't used, and that would trigger a 'local variable not used' warning. */
|
||||
if ( !isEmpty || callSuper ) {
|
||||
if (!isEmpty || callSuper) {
|
||||
LocalDeclaration primeDecl = new LocalDeclaration(PRIME, pS, pE);
|
||||
Eclipse.setGeneratedBy(primeDecl, source);
|
||||
primeDecl.modifiers |= Modifier.FINAL;
|
||||
@@ -287,7 +288,7 @@ public class HandleEqualsAndHashCode implements EclipseAnnotationHandler<EqualsA
|
||||
statements.add(resultDecl);
|
||||
}
|
||||
|
||||
if ( callSuper ) {
|
||||
if (callSuper) {
|
||||
MessageSend callToSuper = new MessageSend();
|
||||
Eclipse.setGeneratedBy(callToSuper, source);
|
||||
callToSuper.sourceStart = pS; callToSuper.sourceEnd = pE;
|
||||
@@ -298,11 +299,11 @@ public class HandleEqualsAndHashCode implements EclipseAnnotationHandler<EqualsA
|
||||
}
|
||||
|
||||
int tempCounter = 0;
|
||||
for ( Node field : fields ) {
|
||||
for (EclipseNode field : fields) {
|
||||
FieldDeclaration f = (FieldDeclaration) field.get();
|
||||
char[] token = f.type.getLastToken();
|
||||
if ( f.type.dimensions() == 0 && token != null ) {
|
||||
if ( Arrays.equals(TypeConstants.FLOAT, token) ) {
|
||||
if (f.type.dimensions() == 0 && token != null) {
|
||||
if (Arrays.equals(TypeConstants.FLOAT, token)) {
|
||||
/* Float.floatToIntBits(fieldName) */
|
||||
MessageSend floatToIntBits = new MessageSend();
|
||||
floatToIntBits.sourceStart = pS; floatToIntBits.sourceEnd = pE;
|
||||
@@ -311,7 +312,7 @@ public class HandleEqualsAndHashCode implements EclipseAnnotationHandler<EqualsA
|
||||
floatToIntBits.selector = "floatToIntBits".toCharArray();
|
||||
floatToIntBits.arguments = new Expression[] { generateFieldReference(f.name, source) };
|
||||
intoResult.add(floatToIntBits);
|
||||
} else if ( Arrays.equals(TypeConstants.DOUBLE, token) ) {
|
||||
} else if (Arrays.equals(TypeConstants.DOUBLE, token)) {
|
||||
/* longToIntForHashCode(Double.doubleToLongBits(fieldName)) */
|
||||
MessageSend doubleToLongBits = new MessageSend();
|
||||
doubleToLongBits.sourceStart = pS; doubleToLongBits.sourceEnd = pE;
|
||||
@@ -333,7 +334,7 @@ public class HandleEqualsAndHashCode implements EclipseAnnotationHandler<EqualsA
|
||||
SingleNameReference copy2 = new SingleNameReference(tempName, p);
|
||||
Eclipse.setGeneratedBy(copy2, source);
|
||||
intoResult.add(longToIntForHashCode(copy1, copy2, source));
|
||||
} else if ( Arrays.equals(TypeConstants.BOOLEAN, token) ) {
|
||||
} else if (Arrays.equals(TypeConstants.BOOLEAN, token)) {
|
||||
/* booleanField ? 1231 : 1237 */
|
||||
IntLiteral int1231 = new IntLiteral("1231".toCharArray(), pS, pE);
|
||||
Eclipse.setGeneratedBy(int1231, source);
|
||||
@@ -343,9 +344,9 @@ public class HandleEqualsAndHashCode implements EclipseAnnotationHandler<EqualsA
|
||||
generateFieldReference(f.name, source), int1231, int1237);
|
||||
Eclipse.setGeneratedBy(int1231or1237, source);
|
||||
intoResult.add(int1231or1237);
|
||||
} else if ( Arrays.equals(TypeConstants.LONG, token) ) {
|
||||
} else if (Arrays.equals(TypeConstants.LONG, token)) {
|
||||
intoResult.add(longToIntForHashCode(generateFieldReference(f.name, source), generateFieldReference(f.name, source), source));
|
||||
} else if ( BUILT_IN_TYPES.contains(new String(token)) ) {
|
||||
} else if (BUILT_IN_TYPES.contains(new String(token))) {
|
||||
intoResult.add(generateFieldReference(f.name, source));
|
||||
} else /* objects */ {
|
||||
/* this.fieldName == null ? 0 : this.fieldName.hashCode() */
|
||||
@@ -366,13 +367,13 @@ public class HandleEqualsAndHashCode implements EclipseAnnotationHandler<EqualsA
|
||||
Eclipse.setGeneratedBy(nullOrHashCode, source);
|
||||
intoResult.add(nullOrHashCode);
|
||||
}
|
||||
} else if ( f.type.dimensions() > 0 && token != null ) {
|
||||
} else if (f.type.dimensions() > 0 && token != null) {
|
||||
/* Arrays.deepHashCode(array) //just hashCode for simple arrays */
|
||||
MessageSend arraysHashCodeCall = new MessageSend();
|
||||
arraysHashCodeCall.sourceStart = pS; arraysHashCodeCall.sourceEnd = pE;
|
||||
Eclipse.setGeneratedBy(arraysHashCodeCall, source);
|
||||
arraysHashCodeCall.receiver = generateQualifiedNameRef(source, TypeConstants.JAVA, TypeConstants.UTIL, "Arrays".toCharArray());
|
||||
if ( f.type.dimensions() > 1 || !BUILT_IN_TYPES.contains(new String(token)) ) {
|
||||
if (f.type.dimensions() > 1 || !BUILT_IN_TYPES.contains(new String(token))) {
|
||||
arraysHashCodeCall.selector = "deepHashCode".toCharArray();
|
||||
} else {
|
||||
arraysHashCodeCall.selector = "hashCode".toCharArray();
|
||||
@@ -384,7 +385,7 @@ public class HandleEqualsAndHashCode implements EclipseAnnotationHandler<EqualsA
|
||||
|
||||
/* fold each intoResult entry into:
|
||||
result = result * PRIME + (item); */ {
|
||||
for ( Expression ex : intoResult ) {
|
||||
for (Expression ex : intoResult) {
|
||||
SingleNameReference resultRef = new SingleNameReference(RESULT, p);
|
||||
Eclipse.setGeneratedBy(resultRef, source);
|
||||
SingleNameReference primeRef = new SingleNameReference(PRIME, p);
|
||||
@@ -415,7 +416,7 @@ public class HandleEqualsAndHashCode implements EclipseAnnotationHandler<EqualsA
|
||||
return method;
|
||||
}
|
||||
|
||||
private MethodDeclaration createEquals(Node type, Collection<Node> fields, boolean callSuper, ASTNode source) {
|
||||
private MethodDeclaration createEquals(EclipseNode type, Collection<EclipseNode> fields, boolean callSuper, ASTNode source) {
|
||||
int pS = source.sourceStart; int pE = source.sourceEnd;
|
||||
long p = (long)pS << 32 | pE;
|
||||
|
||||
@@ -441,7 +442,7 @@ public class HandleEqualsAndHashCode implements EclipseAnnotationHandler<EqualsA
|
||||
|
||||
List<Statement> statements = new ArrayList<Statement>();
|
||||
|
||||
/* if ( o == this ) return true; */ {
|
||||
/* if (o == this) return true; */ {
|
||||
SingleNameReference oRef = new SingleNameReference(new char[] { 'o' }, p);
|
||||
Eclipse.setGeneratedBy(oRef, source);
|
||||
ThisReference thisRef = new ThisReference(pS, pE);
|
||||
@@ -458,7 +459,7 @@ public class HandleEqualsAndHashCode implements EclipseAnnotationHandler<EqualsA
|
||||
statements.add(ifOtherEqualsThis);
|
||||
}
|
||||
|
||||
/* if ( o == null ) return false; */ {
|
||||
/* if (o == null) return false; */ {
|
||||
SingleNameReference oRef = new SingleNameReference(new char[] { 'o' }, p);
|
||||
Eclipse.setGeneratedBy(oRef, source);
|
||||
NullLiteral nullLiteral = new NullLiteral(pS, pE);
|
||||
@@ -475,7 +476,7 @@ public class HandleEqualsAndHashCode implements EclipseAnnotationHandler<EqualsA
|
||||
statements.add(ifOtherEqualsNull);
|
||||
}
|
||||
|
||||
/* if ( o.getClass() != getClass() ) return false; */ {
|
||||
/* if (o.getClass() != getClass()) return false; */ {
|
||||
MessageSend otherGetClass = new MessageSend();
|
||||
otherGetClass.sourceStart = pS; otherGetClass.sourceEnd = pE;
|
||||
Eclipse.setGeneratedBy(otherGetClass, source);
|
||||
@@ -501,8 +502,8 @@ public class HandleEqualsAndHashCode implements EclipseAnnotationHandler<EqualsA
|
||||
|
||||
char[] otherN = "other".toCharArray();
|
||||
|
||||
/* if ( !super.equals(o) ) return false; */
|
||||
if ( callSuper ) {
|
||||
/* if (!super.equals(o)) return false; */
|
||||
if (callSuper) {
|
||||
MessageSend callToSuper = new MessageSend();
|
||||
callToSuper.sourceStart = pS; callToSuper.sourceEnd = pE;
|
||||
Eclipse.setGeneratedBy(callToSuper, source);
|
||||
@@ -525,19 +526,19 @@ public class HandleEqualsAndHashCode implements EclipseAnnotationHandler<EqualsA
|
||||
|
||||
TypeDeclaration typeDecl = (TypeDeclaration)type.get();
|
||||
/* MyType<?> other = (MyType<?>) o; */ {
|
||||
if ( !fields.isEmpty() ) {
|
||||
if (!fields.isEmpty()) {
|
||||
LocalDeclaration other = new LocalDeclaration(otherN, pS, pE);
|
||||
Eclipse.setGeneratedBy(other, source);
|
||||
char[] typeName = typeDecl.name;
|
||||
Expression targetType;
|
||||
if ( typeDecl.typeParameters == null || typeDecl.typeParameters.length == 0 ) {
|
||||
if (typeDecl.typeParameters == null || typeDecl.typeParameters.length == 0) {
|
||||
targetType = new SingleNameReference(((TypeDeclaration)type.get()).name, p);
|
||||
Eclipse.setGeneratedBy(targetType, source);
|
||||
other.type = new SingleTypeReference(typeName, p);
|
||||
Eclipse.setGeneratedBy(other.type, source);
|
||||
} else {
|
||||
TypeReference[] typeArgs = new TypeReference[typeDecl.typeParameters.length];
|
||||
for ( int i = 0 ; i < typeArgs.length ; i++ ) {
|
||||
for (int i = 0; i < typeArgs.length; i++) {
|
||||
typeArgs[i] = new Wildcard(Wildcard.UNBOUND);
|
||||
typeArgs[i].sourceStart = pS; typeArgs[i].sourceEnd = pE;
|
||||
Eclipse.setGeneratedBy(typeArgs[i], source);
|
||||
@@ -555,15 +556,15 @@ public class HandleEqualsAndHashCode implements EclipseAnnotationHandler<EqualsA
|
||||
}
|
||||
}
|
||||
|
||||
for ( Node field : fields ) {
|
||||
for (EclipseNode field : fields) {
|
||||
FieldDeclaration f = (FieldDeclaration) field.get();
|
||||
char[] token = f.type.getLastToken();
|
||||
if ( f.type.dimensions() == 0 && token != null ) {
|
||||
if ( Arrays.equals(TypeConstants.FLOAT, token) ) {
|
||||
if (f.type.dimensions() == 0 && token != null) {
|
||||
if (Arrays.equals(TypeConstants.FLOAT, token)) {
|
||||
statements.add(generateCompareFloatOrDouble(otherN, "Float".toCharArray(), f.name, source));
|
||||
} else if ( Arrays.equals(TypeConstants.DOUBLE, token) ) {
|
||||
} else if (Arrays.equals(TypeConstants.DOUBLE, token)) {
|
||||
statements.add(generateCompareFloatOrDouble(otherN, "Double".toCharArray(), f.name, source));
|
||||
} else if ( BUILT_IN_TYPES.contains(new String(token)) ) {
|
||||
} else if (BUILT_IN_TYPES.contains(new String(token))) {
|
||||
NameReference fieldRef = new SingleNameReference(f.name, p);
|
||||
Eclipse.setGeneratedBy(fieldRef, source);
|
||||
EqualExpression fieldsNotEqual = new EqualExpression(fieldRef,
|
||||
@@ -608,12 +609,12 @@ public class HandleEqualsAndHashCode implements EclipseAnnotationHandler<EqualsA
|
||||
Eclipse.setGeneratedBy(ifStatement, source);
|
||||
statements.add(ifStatement);
|
||||
}
|
||||
} else if ( f.type.dimensions() > 0 && token != null ) {
|
||||
} else if (f.type.dimensions() > 0 && token != null) {
|
||||
MessageSend arraysEqualCall = new MessageSend();
|
||||
arraysEqualCall.sourceStart = pS; arraysEqualCall.sourceEnd = pE;
|
||||
Eclipse.setGeneratedBy(arraysEqualCall, source);
|
||||
arraysEqualCall.receiver = generateQualifiedNameRef(source, TypeConstants.JAVA, TypeConstants.UTIL, "Arrays".toCharArray());
|
||||
if ( f.type.dimensions() > 1 || !BUILT_IN_TYPES.contains(new String(token)) ) {
|
||||
if (f.type.dimensions() > 1 || !BUILT_IN_TYPES.contains(new String(token))) {
|
||||
arraysEqualCall.selector = "deepEquals".toCharArray();
|
||||
} else {
|
||||
arraysEqualCall.selector = "equals".toCharArray();
|
||||
@@ -648,7 +649,7 @@ public class HandleEqualsAndHashCode implements EclipseAnnotationHandler<EqualsA
|
||||
private IfStatement generateCompareFloatOrDouble(char[] otherN, char[] floatOrDouble, char[] fieldName, ASTNode source) {
|
||||
int pS = source.sourceStart, pE = source.sourceEnd;
|
||||
long p = (long)pS << 32 | pE;
|
||||
/* if ( Float.compare(fieldName, other.fieldName) != 0 ) return false */
|
||||
/* if (Float.compare(fieldName, other.fieldName) != 0) return false */
|
||||
MessageSend floatCompare = new MessageSend();
|
||||
floatCompare.sourceStart = pS; floatCompare.sourceEnd = pE;
|
||||
Eclipse.setGeneratedBy(floatCompare, source);
|
||||
@@ -707,7 +708,7 @@ public class HandleEqualsAndHashCode implements EclipseAnnotationHandler<EqualsA
|
||||
|
||||
NameReference ref;
|
||||
|
||||
if ( varNames.length > 1 ) ref = new QualifiedNameReference(varNames, new long[varNames.length], pS, pE);
|
||||
if (varNames.length > 1) ref = new QualifiedNameReference(varNames, new long[varNames.length], pS, pE);
|
||||
else ref = new SingleNameReference(varNames[0], p);
|
||||
Eclipse.setGeneratedBy(ref, source);
|
||||
return ref;
|
||||
|
||||
@@ -30,7 +30,7 @@ import lombok.core.TransformationsUtil;
|
||||
import lombok.core.AST.Kind;
|
||||
import lombok.eclipse.Eclipse;
|
||||
import lombok.eclipse.EclipseAnnotationHandler;
|
||||
import lombok.eclipse.EclipseAST.Node;
|
||||
import lombok.eclipse.EclipseNode;
|
||||
|
||||
import org.eclipse.jdt.internal.compiler.ast.ASTNode;
|
||||
import org.eclipse.jdt.internal.compiler.ast.Annotation;
|
||||
@@ -62,10 +62,10 @@ public class HandleGetter implements EclipseAnnotationHandler<Getter> {
|
||||
* If not, the getter is still generated if it isn't already there, though there will not
|
||||
* be a warning if its already there. The default access level is used.
|
||||
*/
|
||||
public void generateGetterForField(Node fieldNode, ASTNode pos) {
|
||||
for ( Node child : fieldNode.down() ) {
|
||||
if ( child.getKind() == Kind.ANNOTATION ) {
|
||||
if ( annotationTypeMatches(Getter.class, child) ) {
|
||||
public void generateGetterForField(EclipseNode fieldNode, ASTNode pos) {
|
||||
for (EclipseNode child : fieldNode.down()) {
|
||||
if (child.getKind() == Kind.ANNOTATION) {
|
||||
if (annotationTypeMatches(Getter.class, child)) {
|
||||
//The annotation will make it happen, so we can skip it.
|
||||
return;
|
||||
}
|
||||
@@ -75,16 +75,17 @@ public class HandleGetter implements EclipseAnnotationHandler<Getter> {
|
||||
createGetterForField(AccessLevel.PUBLIC, fieldNode, fieldNode, pos, false);
|
||||
}
|
||||
|
||||
public boolean handle(AnnotationValues<Getter> annotation, Annotation ast, Node annotationNode) {
|
||||
Node fieldNode = annotationNode.up();
|
||||
public boolean handle(AnnotationValues<Getter> annotation, Annotation ast, EclipseNode annotationNode) {
|
||||
EclipseNode fieldNode = annotationNode.up();
|
||||
AccessLevel level = annotation.getInstance().value();
|
||||
if ( level == AccessLevel.NONE ) return true;
|
||||
if (level == AccessLevel.NONE) return true;
|
||||
|
||||
return createGetterForField(level, fieldNode, annotationNode, annotationNode.get(), true);
|
||||
}
|
||||
|
||||
private boolean createGetterForField(AccessLevel level, Node fieldNode, Node errorNode, ASTNode source, boolean whineIfExists) {
|
||||
if ( fieldNode.getKind() != Kind.FIELD ) {
|
||||
private boolean createGetterForField(AccessLevel level,
|
||||
EclipseNode fieldNode, EclipseNode errorNode, ASTNode source, boolean whineIfExists) {
|
||||
if (fieldNode.getKind() != Kind.FIELD) {
|
||||
errorNode.addError("@Getter is only supported on a field.");
|
||||
return true;
|
||||
}
|
||||
@@ -97,14 +98,14 @@ public class HandleGetter implements EclipseAnnotationHandler<Getter> {
|
||||
|
||||
int modifier = toModifier(level) | (field.modifiers & ClassFileConstants.AccStatic);
|
||||
|
||||
for ( String altName : TransformationsUtil.toAllGetterNames(fieldName, isBoolean) ) {
|
||||
switch ( methodExists(altName, fieldNode) ) {
|
||||
for (String altName : TransformationsUtil.toAllGetterNames(fieldName, isBoolean)) {
|
||||
switch (methodExists(altName, fieldNode)) {
|
||||
case EXISTS_BY_LOMBOK:
|
||||
return true;
|
||||
case EXISTS_BY_USER:
|
||||
if ( whineIfExists ) {
|
||||
if (whineIfExists) {
|
||||
String altNameExpl = "";
|
||||
if ( !altName.equals(getterName) ) altNameExpl = String.format(" (%s)", altName);
|
||||
if (!altName.equals(getterName)) altNameExpl = String.format(" (%s)", altName);
|
||||
errorNode.addWarning(
|
||||
String.format("Not generating %s(): A method with that name already exists%s", getterName, altNameExpl));
|
||||
}
|
||||
|
||||
@@ -33,21 +33,21 @@ import lombok.core.AnnotationValues;
|
||||
import lombok.core.PrintAST;
|
||||
import lombok.eclipse.EclipseASTVisitor;
|
||||
import lombok.eclipse.EclipseAnnotationHandler;
|
||||
import lombok.eclipse.EclipseAST.Node;
|
||||
import lombok.eclipse.EclipseNode;
|
||||
|
||||
/**
|
||||
* Handles the <code>lombok.core.PrintAST</code> annotation for eclipse.
|
||||
*/
|
||||
@ProviderFor(EclipseAnnotationHandler.class)
|
||||
public class HandlePrintAST implements EclipseAnnotationHandler<PrintAST> {
|
||||
public boolean handle(AnnotationValues<PrintAST> annotation, Annotation ast, Node annotationNode) {
|
||||
if ( !annotationNode.isCompleteParse() ) return false;
|
||||
public boolean handle(AnnotationValues<PrintAST> annotation, Annotation ast, EclipseNode annotationNode) {
|
||||
if (!annotationNode.isCompleteParse()) return false;
|
||||
|
||||
PrintStream stream = System.out;
|
||||
String fileName = annotation.getInstance().outfile();
|
||||
if ( fileName.length() > 0 ) try {
|
||||
if (fileName.length() > 0) try {
|
||||
stream = new PrintStream(new File(fileName));
|
||||
} catch ( FileNotFoundException e ) {
|
||||
} catch (FileNotFoundException e) {
|
||||
Lombok.sneakyThrow(e);
|
||||
}
|
||||
|
||||
|
||||
@@ -33,7 +33,7 @@ import lombok.core.TransformationsUtil;
|
||||
import lombok.core.AST.Kind;
|
||||
import lombok.eclipse.Eclipse;
|
||||
import lombok.eclipse.EclipseAnnotationHandler;
|
||||
import lombok.eclipse.EclipseAST.Node;
|
||||
import lombok.eclipse.EclipseNode;
|
||||
|
||||
import org.eclipse.jdt.internal.compiler.ast.ASTNode;
|
||||
import org.eclipse.jdt.internal.compiler.ast.Annotation;
|
||||
@@ -69,10 +69,10 @@ public class HandleSetter implements EclipseAnnotationHandler<Setter> {
|
||||
* If not, the setter is still generated if it isn't already there, though there will not
|
||||
* be a warning if its already there. The default access level is used.
|
||||
*/
|
||||
public void generateSetterForField(Node fieldNode, ASTNode pos) {
|
||||
for ( Node child : fieldNode.down() ) {
|
||||
if ( child.getKind() == Kind.ANNOTATION ) {
|
||||
if ( annotationTypeMatches(Setter.class, child) ) {
|
||||
public void generateSetterForField(EclipseNode fieldNode, ASTNode pos) {
|
||||
for (EclipseNode child : fieldNode.down()) {
|
||||
if (child.getKind() == Kind.ANNOTATION) {
|
||||
if (annotationTypeMatches(Setter.class, child)) {
|
||||
//The annotation will make it happen, so we can skip it.
|
||||
return;
|
||||
}
|
||||
@@ -82,17 +82,18 @@ public class HandleSetter implements EclipseAnnotationHandler<Setter> {
|
||||
createSetterForField(AccessLevel.PUBLIC, fieldNode, fieldNode, pos, false);
|
||||
}
|
||||
|
||||
public boolean handle(AnnotationValues<Setter> annotation, Annotation ast, Node annotationNode) {
|
||||
Node fieldNode = annotationNode.up();
|
||||
if ( fieldNode.getKind() != Kind.FIELD ) return false;
|
||||
public boolean handle(AnnotationValues<Setter> annotation, Annotation ast, EclipseNode annotationNode) {
|
||||
EclipseNode fieldNode = annotationNode.up();
|
||||
if (fieldNode.getKind() != Kind.FIELD) return false;
|
||||
AccessLevel level = annotation.getInstance().value();
|
||||
if ( level == AccessLevel.NONE ) return true;
|
||||
if (level == AccessLevel.NONE) return true;
|
||||
|
||||
return createSetterForField(level, fieldNode, annotationNode, annotationNode.get(), true);
|
||||
}
|
||||
|
||||
private boolean createSetterForField(AccessLevel level, Node fieldNode, Node errorNode, ASTNode pos, boolean whineIfExists) {
|
||||
if ( fieldNode.getKind() != Kind.FIELD ) {
|
||||
private boolean createSetterForField(AccessLevel level,
|
||||
EclipseNode fieldNode, EclipseNode errorNode, ASTNode pos, boolean whineIfExists) {
|
||||
if (fieldNode.getKind() != Kind.FIELD) {
|
||||
errorNode.addError("@Setter is only supported on a field.");
|
||||
return true;
|
||||
}
|
||||
@@ -102,11 +103,11 @@ public class HandleSetter implements EclipseAnnotationHandler<Setter> {
|
||||
|
||||
int modifier = toModifier(level) | (field.modifiers & ClassFileConstants.AccStatic);
|
||||
|
||||
switch ( methodExists(setterName, fieldNode) ) {
|
||||
switch (methodExists(setterName, fieldNode)) {
|
||||
case EXISTS_BY_LOMBOK:
|
||||
return true;
|
||||
case EXISTS_BY_USER:
|
||||
if ( whineIfExists ) errorNode.addWarning(
|
||||
if (whineIfExists) errorNode.addWarning(
|
||||
String.format("Not generating %s(%s %s): A method with that name already exists",
|
||||
setterName, field.type, new String(field.name)));
|
||||
return true;
|
||||
@@ -115,7 +116,6 @@ public class HandleSetter implements EclipseAnnotationHandler<Setter> {
|
||||
//continue with creating the setter
|
||||
}
|
||||
|
||||
|
||||
MethodDeclaration method = generateSetter((TypeDeclaration) fieldNode.up().get(), field, setterName, modifier, pos);
|
||||
|
||||
injectMethod(fieldNode.up(), method);
|
||||
|
||||
@@ -29,7 +29,7 @@ import lombok.SneakyThrows;
|
||||
import lombok.core.AnnotationValues;
|
||||
import lombok.eclipse.Eclipse;
|
||||
import lombok.eclipse.EclipseAnnotationHandler;
|
||||
import lombok.eclipse.EclipseAST.Node;
|
||||
import lombok.eclipse.EclipseNode;
|
||||
|
||||
import org.eclipse.jdt.internal.compiler.ast.ASTNode;
|
||||
import org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration;
|
||||
@@ -69,35 +69,35 @@ public class HandleSneakyThrows implements EclipseAnnotationHandler<SneakyThrows
|
||||
}
|
||||
}
|
||||
|
||||
@Override public boolean handle(AnnotationValues<SneakyThrows> annotation, Annotation source, Node annotationNode) {
|
||||
@Override public boolean handle(AnnotationValues<SneakyThrows> annotation, Annotation source, EclipseNode annotationNode) {
|
||||
List<String> exceptionNames = annotation.getRawExpressions("value");
|
||||
List<DeclaredException> exceptions = new ArrayList<DeclaredException>();
|
||||
|
||||
MemberValuePair[] memberValuePairs = source.memberValuePairs();
|
||||
if ( memberValuePairs == null || memberValuePairs.length == 0 ) {
|
||||
if (memberValuePairs == null || memberValuePairs.length == 0) {
|
||||
exceptions.add(new DeclaredException("java.lang.Throwable", source));
|
||||
} else {
|
||||
Expression arrayOrSingle = memberValuePairs[0].value;
|
||||
final Expression[] exceptionNameNodes;
|
||||
if ( arrayOrSingle instanceof ArrayInitializer ) {
|
||||
if (arrayOrSingle instanceof ArrayInitializer) {
|
||||
exceptionNameNodes = ((ArrayInitializer)arrayOrSingle).expressions;
|
||||
} else exceptionNameNodes = new Expression[] { arrayOrSingle };
|
||||
|
||||
if ( exceptionNames.size() != exceptionNameNodes.length ) {
|
||||
if (exceptionNames.size() != exceptionNameNodes.length) {
|
||||
annotationNode.addError(
|
||||
"LOMBOK BUG: The number of exception classes in the annotation isn't the same pre- and post- guessing.");
|
||||
}
|
||||
|
||||
int idx = 0;
|
||||
for ( String exceptionName : exceptionNames ) {
|
||||
if ( exceptionName.endsWith(".class") ) exceptionName = exceptionName.substring(0, exceptionName.length() - 6);
|
||||
for (String exceptionName : exceptionNames) {
|
||||
if (exceptionName.endsWith(".class")) exceptionName = exceptionName.substring(0, exceptionName.length() - 6);
|
||||
exceptions.add(new DeclaredException(exceptionName, exceptionNameNodes[idx++]));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Node owner = annotationNode.up();
|
||||
switch ( owner.getKind() ) {
|
||||
EclipseNode owner = annotationNode.up();
|
||||
switch (owner.getKind()) {
|
||||
// case FIELD:
|
||||
// return handleField(annotationNode, (FieldDeclaration)owner.get(), exceptions);
|
||||
case METHOD:
|
||||
@@ -109,7 +109,7 @@ public class HandleSneakyThrows implements EclipseAnnotationHandler<SneakyThrows
|
||||
}
|
||||
|
||||
// private boolean handleField(Node annotation, FieldDeclaration field, List<DeclaredException> exceptions) {
|
||||
// if ( field.initialization == null ) {
|
||||
// if (field.initialization == null) {
|
||||
// annotation.addError("@SneakyThrows can only be used on fields with an initialization statement.");
|
||||
// return true;
|
||||
// }
|
||||
@@ -119,7 +119,7 @@ public class HandleSneakyThrows implements EclipseAnnotationHandler<SneakyThrows
|
||||
// new SingleNameReference(field.name, 0), expression, 0)};
|
||||
// field.initialization = null;
|
||||
//
|
||||
// for ( DeclaredException exception : exceptions ) {
|
||||
// for (DeclaredException exception : exceptions) {
|
||||
// content = new Statement[] { buildTryCatchBlock(content, exception) };
|
||||
// }
|
||||
//
|
||||
@@ -140,17 +140,17 @@ public class HandleSneakyThrows implements EclipseAnnotationHandler<SneakyThrows
|
||||
// return true;
|
||||
// }
|
||||
|
||||
private boolean handleMethod(Node annotation, AbstractMethodDeclaration method, List<DeclaredException> exceptions) {
|
||||
if ( method.isAbstract() ) {
|
||||
private boolean handleMethod(EclipseNode annotation, AbstractMethodDeclaration method, List<DeclaredException> exceptions) {
|
||||
if (method.isAbstract()) {
|
||||
annotation.addError("@SneakyThrows can only be used on concrete methods.");
|
||||
return true;
|
||||
}
|
||||
|
||||
if ( method.statements == null ) return false;
|
||||
if (method.statements == null) return false;
|
||||
|
||||
Statement[] contents = method.statements;
|
||||
|
||||
for ( DeclaredException exception : exceptions ) {
|
||||
for (DeclaredException exception : exceptions) {
|
||||
contents = new Statement[] { buildTryCatchBlock(contents, exception, exception.node) };
|
||||
}
|
||||
|
||||
@@ -171,7 +171,7 @@ public class HandleSneakyThrows implements EclipseAnnotationHandler<SneakyThrows
|
||||
Eclipse.setGeneratedBy(tryStatement.tryBlock, source);
|
||||
tryStatement.tryBlock.statements = contents;
|
||||
TypeReference typeReference;
|
||||
if ( exception.exceptionName.indexOf('.') == -1 ) {
|
||||
if (exception.exceptionName.indexOf('.') == -1) {
|
||||
typeReference = new SingleTypeReference(exception.exceptionName.toCharArray(), p);
|
||||
typeReference.statementEnd = pE;
|
||||
} else {
|
||||
@@ -179,7 +179,7 @@ public class HandleSneakyThrows implements EclipseAnnotationHandler<SneakyThrows
|
||||
char[][] elems = new char[x.length][];
|
||||
long[] poss = new long[x.length];
|
||||
int start = pS;
|
||||
for ( int i = 0 ; i < x.length ; i++ ) {
|
||||
for (int i = 0; i < x.length; i++) {
|
||||
elems[i] = x[i].trim().toCharArray();
|
||||
int end = start + x[i].length();
|
||||
poss[i] = (long)start << 32 | end;
|
||||
|
||||
@@ -30,7 +30,7 @@ import lombok.core.AnnotationValues;
|
||||
import lombok.core.AST.Kind;
|
||||
import lombok.eclipse.Eclipse;
|
||||
import lombok.eclipse.EclipseAnnotationHandler;
|
||||
import lombok.eclipse.EclipseAST.Node;
|
||||
import lombok.eclipse.EclipseNode;
|
||||
import lombok.eclipse.handlers.PKG.MemberExistsResult;
|
||||
|
||||
import org.eclipse.jdt.internal.compiler.ast.Annotation;
|
||||
@@ -57,31 +57,31 @@ public class HandleSynchronized implements EclipseAnnotationHandler<Synchronized
|
||||
private static final char[] INSTANCE_LOCK_NAME = "$lock".toCharArray();
|
||||
private static final char[] STATIC_LOCK_NAME = "$LOCK".toCharArray();
|
||||
|
||||
@Override public boolean handle(AnnotationValues<Synchronized> annotation, Annotation source, Node annotationNode) {
|
||||
@Override public boolean handle(AnnotationValues<Synchronized> annotation, Annotation source, EclipseNode annotationNode) {
|
||||
int p1 = source.sourceStart -1;
|
||||
int p2 = source.sourceStart -2;
|
||||
long pos = (((long)p1) << 32) | p2;
|
||||
Node methodNode = annotationNode.up();
|
||||
if ( methodNode == null || methodNode.getKind() != Kind.METHOD || !(methodNode.get() instanceof MethodDeclaration) ) {
|
||||
EclipseNode methodNode = annotationNode.up();
|
||||
if (methodNode == null || methodNode.getKind() != Kind.METHOD || !(methodNode.get() instanceof MethodDeclaration)) {
|
||||
annotationNode.addError("@Synchronized is legal only on methods.");
|
||||
return true;
|
||||
}
|
||||
|
||||
MethodDeclaration method = (MethodDeclaration)methodNode.get();
|
||||
if ( method.isAbstract() ) {
|
||||
if (method.isAbstract()) {
|
||||
annotationNode.addError("@Synchronized is legal only on concrete methods.");
|
||||
return true;
|
||||
}
|
||||
|
||||
char[] lockName = annotation.getInstance().value().toCharArray();
|
||||
boolean autoMake = false;
|
||||
if ( lockName.length == 0 ) {
|
||||
if (lockName.length == 0) {
|
||||
autoMake = true;
|
||||
lockName = method.isStatic() ? STATIC_LOCK_NAME : INSTANCE_LOCK_NAME;
|
||||
}
|
||||
|
||||
if ( fieldExists(new String(lockName), methodNode) == MemberExistsResult.NOT_EXISTS ) {
|
||||
if ( !autoMake ) {
|
||||
if (fieldExists(new String(lockName), methodNode) == MemberExistsResult.NOT_EXISTS) {
|
||||
if (!autoMake) {
|
||||
annotationNode.addError("The field " + new String(lockName) + " does not exist.");
|
||||
return true;
|
||||
}
|
||||
@@ -104,13 +104,13 @@ public class HandleSynchronized implements EclipseAnnotationHandler<Synchronized
|
||||
injectField(annotationNode.up().up(), fieldDecl);
|
||||
}
|
||||
|
||||
if ( method.statements == null ) return false;
|
||||
if (method.statements == null) return false;
|
||||
|
||||
Block block = new Block(0);
|
||||
Eclipse.setGeneratedBy(block, source);
|
||||
block.statements = method.statements;
|
||||
Expression lockVariable;
|
||||
if ( method.isStatic() ) lockVariable = new QualifiedNameReference(new char[][] {
|
||||
if (method.isStatic()) lockVariable = new QualifiedNameReference(new char[][] {
|
||||
methodNode.up().getName().toCharArray(), lockName }, new long[] { pos, pos }, p1, p2);
|
||||
else {
|
||||
lockVariable = new FieldReference(lockName, pos);
|
||||
|
||||
@@ -37,7 +37,7 @@ import lombok.core.AnnotationValues;
|
||||
import lombok.core.AST.Kind;
|
||||
import lombok.eclipse.Eclipse;
|
||||
import lombok.eclipse.EclipseAnnotationHandler;
|
||||
import lombok.eclipse.EclipseAST.Node;
|
||||
import lombok.eclipse.EclipseNode;
|
||||
|
||||
import org.eclipse.jdt.internal.compiler.ast.ASTNode;
|
||||
import org.eclipse.jdt.internal.compiler.ast.Annotation;
|
||||
@@ -68,24 +68,23 @@ import org.mangosdk.spi.ProviderFor;
|
||||
*/
|
||||
@ProviderFor(EclipseAnnotationHandler.class)
|
||||
public class HandleToString implements EclipseAnnotationHandler<ToString> {
|
||||
private void checkForBogusFieldNames(Node type, AnnotationValues<ToString> annotation) {
|
||||
if ( annotation.isExplicit("exclude") ) {
|
||||
for ( int i : createListOfNonExistentFields(Arrays.asList(annotation.getInstance().exclude()), type, true, false) ) {
|
||||
private void checkForBogusFieldNames(EclipseNode type, AnnotationValues<ToString> annotation) {
|
||||
if (annotation.isExplicit("exclude")) {
|
||||
for (int i : createListOfNonExistentFields(Arrays.asList(annotation.getInstance().exclude()), type, true, false)) {
|
||||
annotation.setWarning("exclude", "This field does not exist, or would have been excluded anyway.", i);
|
||||
}
|
||||
}
|
||||
if ( annotation.isExplicit("of") ) {
|
||||
for ( int i : createListOfNonExistentFields(Arrays.asList(annotation.getInstance().of()), type, false, false) ) {
|
||||
if (annotation.isExplicit("of")) {
|
||||
for (int i : createListOfNonExistentFields(Arrays.asList(annotation.getInstance().of()), type, false, false)) {
|
||||
annotation.setWarning("of", "This field does not exist.", i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void generateToStringForType(Node typeNode, Node errorNode) {
|
||||
for ( Node child : typeNode.down() ) {
|
||||
if ( child.getKind() == Kind.ANNOTATION ) {
|
||||
if ( Eclipse.annotationTypeMatches(ToString.class, child) ) {
|
||||
public void generateToStringForType(EclipseNode typeNode, EclipseNode errorNode) {
|
||||
for (EclipseNode child : typeNode.down()) {
|
||||
if (child.getKind() == Kind.ANNOTATION) {
|
||||
if (Eclipse.annotationTypeMatches(ToString.class, child)) {
|
||||
//The annotation will make it happen, so we can skip it.
|
||||
return;
|
||||
}
|
||||
@@ -95,22 +94,22 @@ public class HandleToString implements EclipseAnnotationHandler<ToString> {
|
||||
boolean includeFieldNames = true;
|
||||
try {
|
||||
includeFieldNames = ((Boolean)ToString.class.getMethod("includeFieldNames").getDefaultValue()).booleanValue();
|
||||
} catch ( Exception ignore ) {}
|
||||
} catch (Exception ignore) {}
|
||||
generateToString(typeNode, errorNode, null, null, includeFieldNames, null, false);
|
||||
}
|
||||
|
||||
public boolean handle(AnnotationValues<ToString> annotation, Annotation ast, Node annotationNode) {
|
||||
public boolean handle(AnnotationValues<ToString> annotation, Annotation ast, EclipseNode annotationNode) {
|
||||
ToString ann = annotation.getInstance();
|
||||
List<String> excludes = Arrays.asList(ann.exclude());
|
||||
List<String> includes = Arrays.asList(ann.of());
|
||||
Node typeNode = annotationNode.up();
|
||||
EclipseNode typeNode = annotationNode.up();
|
||||
Boolean callSuper = ann.callSuper();
|
||||
|
||||
if ( !annotation.isExplicit("callSuper") ) callSuper = null;
|
||||
if ( !annotation.isExplicit("exclude") ) excludes = null;
|
||||
if ( !annotation.isExplicit("of") ) includes = null;
|
||||
if (!annotation.isExplicit("callSuper")) callSuper = null;
|
||||
if (!annotation.isExplicit("exclude")) excludes = null;
|
||||
if (!annotation.isExplicit("of")) includes = null;
|
||||
|
||||
if ( excludes != null && includes != null ) {
|
||||
if (excludes != null && includes != null) {
|
||||
excludes = null;
|
||||
annotation.setWarning("exclude", "exclude and of are mutually exclusive; the 'exclude' parameter will be ignored.");
|
||||
}
|
||||
@@ -120,48 +119,48 @@ public class HandleToString implements EclipseAnnotationHandler<ToString> {
|
||||
return generateToString(typeNode, annotationNode, excludes, includes, ann.includeFieldNames(), callSuper, true);
|
||||
}
|
||||
|
||||
public boolean generateToString(Node typeNode, Node errorNode, List<String> excludes, List<String> includes,
|
||||
public boolean generateToString(EclipseNode typeNode, EclipseNode errorNode, List<String> excludes, List<String> includes,
|
||||
boolean includeFieldNames, Boolean callSuper, boolean whineIfExists) {
|
||||
TypeDeclaration typeDecl = null;
|
||||
|
||||
if ( typeNode.get() instanceof TypeDeclaration ) typeDecl = (TypeDeclaration) typeNode.get();
|
||||
if (typeNode.get() instanceof TypeDeclaration) typeDecl = (TypeDeclaration) typeNode.get();
|
||||
int modifiers = typeDecl == null ? 0 : typeDecl.modifiers;
|
||||
boolean notAClass = (modifiers &
|
||||
(ClassFileConstants.AccInterface | ClassFileConstants.AccAnnotation | ClassFileConstants.AccEnum)) != 0;
|
||||
|
||||
if ( typeDecl == null || notAClass ) {
|
||||
if (typeDecl == null || notAClass) {
|
||||
errorNode.addError("@ToString is only supported on a class.");
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( callSuper == null ) {
|
||||
if (callSuper == null) {
|
||||
try {
|
||||
callSuper = ((Boolean)ToString.class.getMethod("callSuper").getDefaultValue()).booleanValue();
|
||||
} catch ( Exception ignore ) {}
|
||||
} catch (Exception ignore) {}
|
||||
}
|
||||
|
||||
List<Node> nodesForToString = new ArrayList<Node>();
|
||||
if ( includes != null ) {
|
||||
for ( Node child : typeNode.down() ) {
|
||||
if ( child.getKind() != Kind.FIELD ) continue;
|
||||
List<EclipseNode> nodesForToString = new ArrayList<EclipseNode>();
|
||||
if (includes != null) {
|
||||
for (EclipseNode child : typeNode.down()) {
|
||||
if (child.getKind() != Kind.FIELD) continue;
|
||||
FieldDeclaration fieldDecl = (FieldDeclaration) child.get();
|
||||
if ( includes.contains(new String(fieldDecl.name)) ) nodesForToString.add(child);
|
||||
if (includes.contains(new String(fieldDecl.name))) nodesForToString.add(child);
|
||||
}
|
||||
} else {
|
||||
for ( Node child : typeNode.down() ) {
|
||||
if ( child.getKind() != Kind.FIELD ) continue;
|
||||
for (EclipseNode child : typeNode.down()) {
|
||||
if (child.getKind() != Kind.FIELD) continue;
|
||||
FieldDeclaration fieldDecl = (FieldDeclaration) child.get();
|
||||
//Skip static fields.
|
||||
if ( (fieldDecl.modifiers & ClassFileConstants.AccStatic) != 0 ) continue;
|
||||
if ((fieldDecl.modifiers & ClassFileConstants.AccStatic) != 0) continue;
|
||||
//Skip excluded fields.
|
||||
if ( excludes != null && excludes.contains(new String(fieldDecl.name)) ) continue;
|
||||
if (excludes != null && excludes.contains(new String(fieldDecl.name))) continue;
|
||||
//Skip fields that start with $
|
||||
if ( fieldDecl.name.length > 0 && fieldDecl.name[0] == '$' ) continue;
|
||||
if (fieldDecl.name.length > 0 && fieldDecl.name[0] == '$') continue;
|
||||
nodesForToString.add(child);
|
||||
}
|
||||
}
|
||||
|
||||
switch ( methodExists("toString", typeNode) ) {
|
||||
switch (methodExists("toString", typeNode)) {
|
||||
case NOT_EXISTS:
|
||||
MethodDeclaration toString = createToString(typeNode, nodesForToString, includeFieldNames, callSuper, errorNode.get());
|
||||
injectMethod(typeNode, toString);
|
||||
@@ -170,14 +169,15 @@ public class HandleToString implements EclipseAnnotationHandler<ToString> {
|
||||
return true;
|
||||
default:
|
||||
case EXISTS_BY_USER:
|
||||
if ( whineIfExists ) {
|
||||
if (whineIfExists) {
|
||||
errorNode.addWarning("Not generating toString(): A method with that name already exists");
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
private MethodDeclaration createToString(Node type, Collection<Node> fields, boolean includeFieldNames, boolean callSuper, ASTNode source) {
|
||||
private MethodDeclaration createToString(EclipseNode type, Collection<EclipseNode> fields,
|
||||
boolean includeFieldNames, boolean callSuper, ASTNode source) {
|
||||
TypeDeclaration typeDeclaration = (TypeDeclaration)type.get();
|
||||
char[] rawTypeName = typeDeclaration.name;
|
||||
String typeName = rawTypeName == null ? "" : new String(rawTypeName);
|
||||
@@ -190,11 +190,11 @@ public class HandleToString implements EclipseAnnotationHandler<ToString> {
|
||||
|
||||
char[] prefix;
|
||||
|
||||
if ( callSuper ) {
|
||||
if (callSuper) {
|
||||
prefix = (typeName + "(super=").toCharArray();
|
||||
} else if ( fields.isEmpty() ) {
|
||||
} else if (fields.isEmpty()) {
|
||||
prefix = (typeName + "()").toCharArray();
|
||||
} else if ( includeFieldNames ) {
|
||||
} else if (includeFieldNames) {
|
||||
prefix = (typeName + "(" + new String(((FieldDeclaration)fields.iterator().next().get()).name) + "=").toCharArray();
|
||||
} else {
|
||||
prefix = (typeName + "(").toCharArray();
|
||||
@@ -204,7 +204,7 @@ public class HandleToString implements EclipseAnnotationHandler<ToString> {
|
||||
Expression current = new StringLiteral(prefix, pS, pE, 0);
|
||||
Eclipse.setGeneratedBy(current, source);
|
||||
|
||||
if ( callSuper ) {
|
||||
if (callSuper) {
|
||||
MessageSend callToSuper = new MessageSend();
|
||||
callToSuper.sourceStart = pS; callToSuper.sourceEnd = pE;
|
||||
Eclipse.setGeneratedBy(callToSuper, source);
|
||||
@@ -216,18 +216,18 @@ public class HandleToString implements EclipseAnnotationHandler<ToString> {
|
||||
first = false;
|
||||
}
|
||||
|
||||
for ( Node field : fields ) {
|
||||
for (EclipseNode field : fields) {
|
||||
FieldDeclaration f = (FieldDeclaration)field.get();
|
||||
if ( f.name == null || f.type == null ) continue;
|
||||
if (f.name == null || f.type == null) continue;
|
||||
|
||||
Expression ex;
|
||||
if ( f.type.dimensions() > 0 ) {
|
||||
if (f.type.dimensions() > 0) {
|
||||
MessageSend arrayToString = new MessageSend();
|
||||
arrayToString.sourceStart = pS; arrayToString.sourceEnd = pE;
|
||||
arrayToString.receiver = generateQualifiedNameRef(source, TypeConstants.JAVA, TypeConstants.UTIL, "Arrays".toCharArray());
|
||||
arrayToString.arguments = new Expression[] { new SingleNameReference(f.name, p) };
|
||||
Eclipse.setGeneratedBy(arrayToString.arguments[0], source);
|
||||
if ( f.type.dimensions() > 1 || !BUILT_IN_TYPES.contains(new String(f.type.getLastToken())) ) {
|
||||
if (f.type.dimensions() > 1 || !BUILT_IN_TYPES.contains(new String(f.type.getLastToken()))) {
|
||||
arrayToString.selector = "deepToString".toCharArray();
|
||||
} else {
|
||||
arrayToString.selector = "toString".toCharArray();
|
||||
@@ -241,7 +241,7 @@ public class HandleToString implements EclipseAnnotationHandler<ToString> {
|
||||
}
|
||||
Eclipse.setGeneratedBy(ex, source);
|
||||
|
||||
if ( first ) {
|
||||
if (first) {
|
||||
current = new BinaryExpression(current, ex, PLUS);
|
||||
current.sourceStart = pS; current.sourceEnd = pE;
|
||||
Eclipse.setGeneratedBy(current, source);
|
||||
@@ -250,7 +250,7 @@ public class HandleToString implements EclipseAnnotationHandler<ToString> {
|
||||
}
|
||||
|
||||
StringLiteral fieldNameLiteral;
|
||||
if ( includeFieldNames ) {
|
||||
if (includeFieldNames) {
|
||||
char[] namePlusEqualsSign = (infixS + new String(f.name) + "=").toCharArray();
|
||||
fieldNameLiteral = new StringLiteral(namePlusEqualsSign, pS, pE, 0);
|
||||
} else {
|
||||
@@ -262,7 +262,7 @@ public class HandleToString implements EclipseAnnotationHandler<ToString> {
|
||||
current = new BinaryExpression(current, ex, PLUS);
|
||||
Eclipse.setGeneratedBy(current, source);
|
||||
}
|
||||
if ( !first ) {
|
||||
if (!first) {
|
||||
StringLiteral suffixLiteral = new StringLiteral(suffix, pS, pE, 0);
|
||||
Eclipse.setGeneratedBy(suffixLiteral, source);
|
||||
current = new BinaryExpression(current, suffixLiteral, PLUS);
|
||||
@@ -296,7 +296,7 @@ public class HandleToString implements EclipseAnnotationHandler<ToString> {
|
||||
int pS = source.sourceStart, pE = source.sourceEnd;
|
||||
long p = (long)pS << 32 | pE;
|
||||
NameReference ref;
|
||||
if ( varNames.length > 1 ) ref = new QualifiedNameReference(varNames, new long[varNames.length], pS, pE);
|
||||
if (varNames.length > 1) ref = new QualifiedNameReference(varNames, new long[varNames.length], pS, pE);
|
||||
else ref = new SingleNameReference(varNames[0], p);
|
||||
Eclipse.setGeneratedBy(ref, source);
|
||||
return ref;
|
||||
|
||||
@@ -32,8 +32,7 @@ import lombok.AccessLevel;
|
||||
import lombok.core.TransformationsUtil;
|
||||
import lombok.core.AST.Kind;
|
||||
import lombok.eclipse.Eclipse;
|
||||
import lombok.eclipse.EclipseAST;
|
||||
import lombok.eclipse.EclipseAST.Node;
|
||||
import lombok.eclipse.EclipseNode;
|
||||
|
||||
import org.eclipse.jdt.internal.compiler.ast.ASTNode;
|
||||
import org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration;
|
||||
@@ -66,7 +65,7 @@ class PKG {
|
||||
}
|
||||
|
||||
static int toModifier(AccessLevel value) {
|
||||
switch ( value ) {
|
||||
switch (value) {
|
||||
case MODULE:
|
||||
case PACKAGE:
|
||||
return 0;
|
||||
@@ -83,8 +82,8 @@ class PKG {
|
||||
static boolean nameEquals(char[][] typeName, String string) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
boolean first = true;
|
||||
for ( char[] elem : typeName ) {
|
||||
if ( first ) first = false;
|
||||
for (char[] elem : typeName) {
|
||||
if (first) first = false;
|
||||
else sb.append('.');
|
||||
sb.append(elem);
|
||||
}
|
||||
@@ -96,19 +95,19 @@ class PKG {
|
||||
NOT_EXISTS, EXISTS_BY_USER, EXISTS_BY_LOMBOK;
|
||||
}
|
||||
|
||||
static MemberExistsResult fieldExists(String fieldName, EclipseAST.Node node) {
|
||||
while ( node != null && !(node.get() instanceof TypeDeclaration) ) {
|
||||
static MemberExistsResult fieldExists(String fieldName, EclipseNode node) {
|
||||
while (node != null && !(node.get() instanceof TypeDeclaration)) {
|
||||
node = node.up();
|
||||
}
|
||||
|
||||
if ( node != null && node.get() instanceof TypeDeclaration ) {
|
||||
if (node != null && node.get() instanceof TypeDeclaration) {
|
||||
TypeDeclaration typeDecl = (TypeDeclaration)node.get();
|
||||
if ( typeDecl.fields != null ) for ( FieldDeclaration def : typeDecl.fields ) {
|
||||
if (typeDecl.fields != null) for (FieldDeclaration def : typeDecl.fields) {
|
||||
char[] fName = def.name;
|
||||
if ( fName == null ) continue;
|
||||
if ( fieldName.equals(new String(fName)) ) {
|
||||
EclipseAST.Node existing = node.getNodeFor(def);
|
||||
if ( existing == null || !existing.isHandled() ) return MemberExistsResult.EXISTS_BY_USER;
|
||||
if (fName == null) continue;
|
||||
if (fieldName.equals(new String(fName))) {
|
||||
EclipseNode existing = node.getNodeFor(def);
|
||||
if (existing == null || !existing.isHandled()) return MemberExistsResult.EXISTS_BY_USER;
|
||||
return MemberExistsResult.EXISTS_BY_LOMBOK;
|
||||
}
|
||||
}
|
||||
@@ -117,19 +116,19 @@ class PKG {
|
||||
return MemberExistsResult.NOT_EXISTS;
|
||||
}
|
||||
|
||||
static MemberExistsResult methodExists(String methodName, EclipseAST.Node node) {
|
||||
while ( node != null && !(node.get() instanceof TypeDeclaration) ) {
|
||||
static MemberExistsResult methodExists(String methodName, EclipseNode node) {
|
||||
while (node != null && !(node.get() instanceof TypeDeclaration)) {
|
||||
node = node.up();
|
||||
}
|
||||
|
||||
if ( node != null && node.get() instanceof TypeDeclaration ) {
|
||||
if (node != null && node.get() instanceof TypeDeclaration) {
|
||||
TypeDeclaration typeDecl = (TypeDeclaration)node.get();
|
||||
if ( typeDecl.methods != null ) for ( AbstractMethodDeclaration def : typeDecl.methods ) {
|
||||
if (typeDecl.methods != null) for (AbstractMethodDeclaration def : typeDecl.methods) {
|
||||
char[] mName = def.selector;
|
||||
if ( mName == null ) continue;
|
||||
if ( methodName.equals(new String(mName)) ) {
|
||||
EclipseAST.Node existing = node.getNodeFor(def);
|
||||
if ( existing == null || !existing.isHandled() ) return MemberExistsResult.EXISTS_BY_USER;
|
||||
if (mName == null) continue;
|
||||
if (methodName.equals(new String(mName))) {
|
||||
EclipseNode existing = node.getNodeFor(def);
|
||||
if (existing == null || !existing.isHandled()) return MemberExistsResult.EXISTS_BY_USER;
|
||||
return MemberExistsResult.EXISTS_BY_LOMBOK;
|
||||
}
|
||||
}
|
||||
@@ -138,18 +137,18 @@ class PKG {
|
||||
return MemberExistsResult.NOT_EXISTS;
|
||||
}
|
||||
|
||||
static MemberExistsResult constructorExists(EclipseAST.Node node) {
|
||||
while ( node != null && !(node.get() instanceof TypeDeclaration) ) {
|
||||
static MemberExistsResult constructorExists(EclipseNode node) {
|
||||
while (node != null && !(node.get() instanceof TypeDeclaration)) {
|
||||
node = node.up();
|
||||
}
|
||||
|
||||
if ( node != null && node.get() instanceof TypeDeclaration ) {
|
||||
if (node != null && node.get() instanceof TypeDeclaration) {
|
||||
TypeDeclaration typeDecl = (TypeDeclaration)node.get();
|
||||
if ( typeDecl.methods != null ) for ( AbstractMethodDeclaration def : typeDecl.methods ) {
|
||||
if ( def instanceof ConstructorDeclaration ) {
|
||||
if ( (def.bits & ASTNode.IsDefaultConstructor) != 0 ) continue;
|
||||
EclipseAST.Node existing = node.getNodeFor(def);
|
||||
if ( existing == null || !existing.isHandled() ) return MemberExistsResult.EXISTS_BY_USER;
|
||||
if (typeDecl.methods != null) for (AbstractMethodDeclaration def : typeDecl.methods) {
|
||||
if (def instanceof ConstructorDeclaration) {
|
||||
if ((def.bits & ASTNode.IsDefaultConstructor) != 0) continue;
|
||||
EclipseNode existing = node.getNodeFor(def);
|
||||
if (existing == null || !existing.isHandled()) return MemberExistsResult.EXISTS_BY_USER;
|
||||
return MemberExistsResult.EXISTS_BY_LOMBOK;
|
||||
}
|
||||
}
|
||||
@@ -158,17 +157,17 @@ class PKG {
|
||||
return MemberExistsResult.NOT_EXISTS;
|
||||
}
|
||||
|
||||
static EclipseAST.Node getExistingLombokConstructor(EclipseAST.Node node) {
|
||||
while ( node != null && !(node.get() instanceof TypeDeclaration) ) {
|
||||
static EclipseNode getExistingLombokConstructor(EclipseNode node) {
|
||||
while (node != null && !(node.get() instanceof TypeDeclaration)) {
|
||||
node = node.up();
|
||||
}
|
||||
|
||||
if ( node.get() instanceof TypeDeclaration ) {
|
||||
for ( AbstractMethodDeclaration def : ((TypeDeclaration)node.get()).methods ) {
|
||||
if ( def instanceof ConstructorDeclaration ) {
|
||||
if ( (def.bits & ASTNode.IsDefaultConstructor) != 0 ) continue;
|
||||
EclipseAST.Node existing = node.getNodeFor(def);
|
||||
if ( existing.isHandled() ) return existing;
|
||||
if (node.get() instanceof TypeDeclaration) {
|
||||
for (AbstractMethodDeclaration def : ((TypeDeclaration)node.get()).methods) {
|
||||
if (def instanceof ConstructorDeclaration) {
|
||||
if ((def.bits & ASTNode.IsDefaultConstructor) != 0) continue;
|
||||
EclipseNode existing = node.getNodeFor(def);
|
||||
if (existing.isHandled()) return existing;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -176,18 +175,18 @@ class PKG {
|
||||
return null;
|
||||
}
|
||||
|
||||
static EclipseAST.Node getExistingLombokMethod(String methodName, EclipseAST.Node node) {
|
||||
while ( node != null && !(node.get() instanceof TypeDeclaration) ) {
|
||||
static EclipseNode getExistingLombokMethod(String methodName, EclipseNode node) {
|
||||
while (node != null && !(node.get() instanceof TypeDeclaration)) {
|
||||
node = node.up();
|
||||
}
|
||||
|
||||
if ( node.get() instanceof TypeDeclaration ) {
|
||||
for ( AbstractMethodDeclaration def : ((TypeDeclaration)node.get()).methods ) {
|
||||
if (node.get() instanceof TypeDeclaration) {
|
||||
for (AbstractMethodDeclaration def : ((TypeDeclaration)node.get()).methods) {
|
||||
char[] mName = def.selector;
|
||||
if ( mName == null ) continue;
|
||||
if ( methodName.equals(new String(mName)) ) {
|
||||
EclipseAST.Node existing = node.getNodeFor(def);
|
||||
if ( existing.isHandled() ) return existing;
|
||||
if (mName == null) continue;
|
||||
if (methodName.equals(new String(mName))) {
|
||||
EclipseNode existing = node.getNodeFor(def);
|
||||
if (existing.isHandled()) return existing;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -195,10 +194,10 @@ class PKG {
|
||||
return null;
|
||||
}
|
||||
|
||||
static void injectField(EclipseAST.Node type, FieldDeclaration field) {
|
||||
static void injectField(EclipseNode type, FieldDeclaration field) {
|
||||
TypeDeclaration parent = (TypeDeclaration) type.get();
|
||||
|
||||
if ( parent.fields == null ) {
|
||||
if (parent.fields == null) {
|
||||
parent.fields = new FieldDeclaration[1];
|
||||
parent.fields[0] = field;
|
||||
} else {
|
||||
@@ -211,27 +210,27 @@ class PKG {
|
||||
type.add(field, Kind.FIELD).recursiveSetHandled();
|
||||
}
|
||||
|
||||
static void injectMethod(EclipseAST.Node type, AbstractMethodDeclaration method) {
|
||||
static void injectMethod(EclipseNode type, AbstractMethodDeclaration method) {
|
||||
TypeDeclaration parent = (TypeDeclaration) type.get();
|
||||
|
||||
if ( parent.methods == null ) {
|
||||
if (parent.methods == null) {
|
||||
parent.methods = new AbstractMethodDeclaration[1];
|
||||
parent.methods[0] = method;
|
||||
} else {
|
||||
boolean injectionComplete = false;
|
||||
if ( method instanceof ConstructorDeclaration ) {
|
||||
for ( int i = 0 ; i < parent.methods.length ; i++ ) {
|
||||
if ( parent.methods[i] instanceof ConstructorDeclaration &&
|
||||
(parent.methods[i].bits & ASTNode.IsDefaultConstructor) != 0 ) {
|
||||
EclipseAST.Node tossMe = type.getNodeFor(parent.methods[i]);
|
||||
if (method instanceof ConstructorDeclaration) {
|
||||
for (int i = 0 ; i < parent.methods.length ; i++) {
|
||||
if (parent.methods[i] instanceof ConstructorDeclaration &&
|
||||
(parent.methods[i].bits & ASTNode.IsDefaultConstructor) != 0) {
|
||||
EclipseNode tossMe = type.getNodeFor(parent.methods[i]);
|
||||
parent.methods[i] = method;
|
||||
if ( tossMe != null ) tossMe.up().removeChild(tossMe);
|
||||
if (tossMe != null) tossMe.up().removeChild(tossMe);
|
||||
injectionComplete = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if ( !injectionComplete ) {
|
||||
if (!injectionComplete) {
|
||||
AbstractMethodDeclaration[] newArray = new AbstractMethodDeclaration[parent.methods.length + 1];
|
||||
System.arraycopy(parent.methods, 0, newArray, 0, parent.methods.length);
|
||||
newArray[parent.methods.length] = method;
|
||||
@@ -244,13 +243,13 @@ class PKG {
|
||||
|
||||
static Annotation[] findAnnotations(FieldDeclaration field, Pattern namePattern) {
|
||||
List<Annotation> result = new ArrayList<Annotation>();
|
||||
if ( field.annotations == null ) return new Annotation[0];
|
||||
if (field.annotations == null) return new Annotation[0];
|
||||
for (Annotation annotation : field.annotations) {
|
||||
TypeReference typeRef = annotation.type;
|
||||
if ( typeRef != null && typeRef.getTypeName()!= null ) {
|
||||
if (typeRef != null && typeRef.getTypeName()!= null) {
|
||||
char[][] typeName = typeRef.getTypeName();
|
||||
String suspect = new String(typeName[typeName.length - 1]);
|
||||
if ( namePattern.matcher(suspect).matches() ) {
|
||||
if (namePattern.matcher(suspect).matches()) {
|
||||
result.add(annotation);
|
||||
}
|
||||
}
|
||||
@@ -294,24 +293,24 @@ class PKG {
|
||||
return ann;
|
||||
}
|
||||
|
||||
static List<Integer> createListOfNonExistentFields(List<String> list, Node type, boolean excludeStandard, boolean excludeTransient) {
|
||||
static List<Integer> createListOfNonExistentFields(List<String> list, EclipseNode type, boolean excludeStandard, boolean excludeTransient) {
|
||||
boolean[] matched = new boolean[list.size()];
|
||||
|
||||
for ( Node child : type.down() ) {
|
||||
if ( list.isEmpty() ) break;
|
||||
if ( child.getKind() != Kind.FIELD ) continue;
|
||||
if ( excludeStandard ) {
|
||||
if ( (((FieldDeclaration)child.get()).modifiers & ClassFileConstants.AccStatic) != 0 ) continue;
|
||||
if ( child.getName().startsWith("$") ) continue;
|
||||
for (EclipseNode child : type.down()) {
|
||||
if (list.isEmpty()) break;
|
||||
if (child.getKind() != Kind.FIELD) continue;
|
||||
if (excludeStandard) {
|
||||
if ((((FieldDeclaration)child.get()).modifiers & ClassFileConstants.AccStatic) != 0) continue;
|
||||
if (child.getName().startsWith("$")) continue;
|
||||
}
|
||||
if ( excludeTransient && (((FieldDeclaration)child.get()).modifiers & ClassFileConstants.AccTransient) != 0 ) continue;
|
||||
if (excludeTransient && (((FieldDeclaration)child.get()).modifiers & ClassFileConstants.AccTransient) != 0) continue;
|
||||
int idx = list.indexOf(child.getName());
|
||||
if ( idx > -1 ) matched[idx] = true;
|
||||
if (idx > -1) matched[idx] = true;
|
||||
}
|
||||
|
||||
List<Integer> problematic = new ArrayList<Integer>();
|
||||
for ( int i = 0 ; i < list.size() ; i++ ) {
|
||||
if ( !matched[i] ) problematic.add(i);
|
||||
for (int i = 0 ; i < list.size() ; i++) {
|
||||
if (!matched[i]) problematic.add(i);
|
||||
}
|
||||
|
||||
return problematic;
|
||||
|
||||
@@ -36,7 +36,7 @@ class AppleNativeLook {
|
||||
Object app = appClass.getMethod("getApplication").invoke(null);
|
||||
appClass.getMethod("removeAboutMenuItem").invoke(app);
|
||||
appClass.getMethod("removePreferencesMenuItem").invoke(app);
|
||||
|
||||
|
||||
BufferedImage image = ImageIO.read(AppleNativeLook.class.getResource("lombokIcon.png"));
|
||||
appClass.getMethod("setDockIconImage", Image.class).invoke(app, image);
|
||||
}
|
||||
|
||||
@@ -54,17 +54,17 @@ class EclipseFinder {
|
||||
URI uri = EclipseFinder.class.getResource("/" + EclipseFinder.class.getName().replace('.', '/') + ".class").toURI();
|
||||
Pattern p = Pattern.compile("^jar:file:([^\\!]+)\\!.*\\.class$");
|
||||
Matcher m = p.matcher(uri.toString());
|
||||
if ( !m.matches() ) return new File("lombok.jar");
|
||||
if (!m.matches()) return new File("lombok.jar");
|
||||
String rawUri = m.group(1);
|
||||
return new File(URLDecoder.decode(rawUri, Charset.defaultCharset().name()));
|
||||
} catch ( Exception e ) {
|
||||
} catch (Exception e) {
|
||||
throw Lombok.sneakyThrow(e);
|
||||
}
|
||||
}
|
||||
|
||||
private static final AtomicBoolean windowsDriveInfoLibLoaded = new AtomicBoolean(false);
|
||||
private static void loadWindowsDriveInfoLib() throws IOException {
|
||||
if ( !windowsDriveInfoLibLoaded.compareAndSet(false, true) ) return;
|
||||
if (!windowsDriveInfoLibLoaded.compareAndSet(false, true)) return;
|
||||
|
||||
final String prefix = "lombok-" + Version.getVersion() + "-";
|
||||
|
||||
@@ -75,17 +75,17 @@ class EclipseFinder {
|
||||
dll1.deleteOnExit();
|
||||
dll2.deleteOnExit();
|
||||
try {
|
||||
if ( unpackDLL("WindowsDriveInfo-i386.dll", dll1) ) {
|
||||
if (unpackDLL("WindowsDriveInfo-i386.dll", dll1)) {
|
||||
System.load(dll1.getAbsolutePath());
|
||||
return;
|
||||
}
|
||||
} catch ( Throwable ignore ) {}
|
||||
} catch (Throwable ignore) {}
|
||||
|
||||
try {
|
||||
if ( unpackDLL("WindowsDriveInfo-x86_64.dll", dll2) ) {
|
||||
if (unpackDLL("WindowsDriveInfo-x86_64.dll", dll2)) {
|
||||
System.load(dll2.getAbsolutePath());
|
||||
}
|
||||
} catch ( Throwable ignore ) {}
|
||||
} catch (Throwable ignore) {}
|
||||
}
|
||||
|
||||
private static boolean unpackDLL(String dllName, File target) throws IOException {
|
||||
@@ -95,15 +95,15 @@ class EclipseFinder {
|
||||
FileOutputStream out = new FileOutputStream(target);
|
||||
try {
|
||||
byte[] b = new byte[32000];
|
||||
while ( true ) {
|
||||
while (true) {
|
||||
int r = in.read(b);
|
||||
if ( r == -1 ) break;
|
||||
if (r == -1) break;
|
||||
out.write(b, 0, r);
|
||||
}
|
||||
} finally {
|
||||
out.close();
|
||||
}
|
||||
} catch ( IOException e ) {
|
||||
} catch (IOException e) {
|
||||
//Fall through - if there is a file named lombok-WindowsDriveInfo-arch.dll, we'll try it.
|
||||
return target.exists() && target.canRead();
|
||||
}
|
||||
@@ -125,8 +125,8 @@ class EclipseFinder {
|
||||
List<String> drives = new ArrayList<String>();
|
||||
|
||||
WindowsDriveInfo info = new WindowsDriveInfo();
|
||||
for ( String drive : info.getLogicalDrives() ) {
|
||||
if ( info.isFixedDisk(drive) ) drives.add(drive);
|
||||
for (String drive : info.getLogicalDrives()) {
|
||||
if (info.isFixedDisk(drive)) drives.add(drive);
|
||||
}
|
||||
|
||||
return drives;
|
||||
@@ -149,24 +149,24 @@ class EclipseFinder {
|
||||
List<String> driveLetters = asList("C");
|
||||
try {
|
||||
driveLetters = getDrivesOnWindows();
|
||||
} catch ( Throwable ignore ) {
|
||||
} catch (Throwable ignore) {
|
||||
ignore.printStackTrace();
|
||||
}
|
||||
|
||||
for ( String letter : driveLetters ) {
|
||||
for (String letter : driveLetters) {
|
||||
File f = new File(letter + ":\\");
|
||||
for ( File dir : f.listFiles() ) {
|
||||
if ( !dir.isDirectory() ) continue;
|
||||
if ( dir.getName().toLowerCase().contains("eclipse") ) {
|
||||
for (File dir : f.listFiles()) {
|
||||
if (!dir.isDirectory()) continue;
|
||||
if (dir.getName().toLowerCase().contains("eclipse")) {
|
||||
String eclipseLocation = findEclipseOnWindows1(dir);
|
||||
if ( eclipseLocation != null ) eclipses.add(eclipseLocation);
|
||||
if (eclipseLocation != null) eclipses.add(eclipseLocation);
|
||||
}
|
||||
if ( dir.getName().toLowerCase().contains("program files") ) {
|
||||
for ( File dir2 : dir.listFiles() ) {
|
||||
if ( !dir2.isDirectory() ) continue;
|
||||
if ( dir.getName().toLowerCase().contains("eclipse") ) {
|
||||
if (dir.getName().toLowerCase().contains("program files")) {
|
||||
for (File dir2 : dir.listFiles()) {
|
||||
if (!dir2.isDirectory()) continue;
|
||||
if (dir.getName().toLowerCase().contains("eclipse")) {
|
||||
String eclipseLocation = findEclipseOnWindows1(dir);
|
||||
if ( eclipseLocation != null ) eclipses.add(eclipseLocation);
|
||||
if (eclipseLocation != null) eclipses.add(eclipseLocation);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -178,7 +178,7 @@ class EclipseFinder {
|
||||
|
||||
/** Checks if the provided directory contains 'eclipse.exe', and if so, returns the directory, otherwise null. */
|
||||
private static String findEclipseOnWindows1(File dir) {
|
||||
if ( new File(dir, "eclipse.exe").isFile() ) return dir.getAbsolutePath();
|
||||
if (new File(dir, "eclipse.exe").isFile()) return dir.getAbsolutePath();
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -189,7 +189,7 @@ class EclipseFinder {
|
||||
* @return List of directories that contain the Eclipse executable.
|
||||
*/
|
||||
static List<String> findEclipses() {
|
||||
switch ( getOS() ) {
|
||||
switch (getOS()) {
|
||||
case WINDOWS:
|
||||
return findEclipseOnWindows();
|
||||
case MAC_OS_X:
|
||||
@@ -206,9 +206,9 @@ class EclipseFinder {
|
||||
|
||||
static OS getOS() {
|
||||
String prop = System.getProperty("os.name", "").toLowerCase();
|
||||
if ( prop.matches("^.*\\bmac\\b.*$") ) return OS.MAC_OS_X;
|
||||
if ( prop.matches("^.*\\bdarwin\\b.*$") ) return OS.MAC_OS_X;
|
||||
if ( prop.matches("^.*\\bwin(dows)\\b.*$") ) return OS.WINDOWS;
|
||||
if (prop.matches("^.*\\bmac\\b.*$")) return OS.MAC_OS_X;
|
||||
if (prop.matches("^.*\\bdarwin\\b.*$")) return OS.MAC_OS_X;
|
||||
if (prop.matches("^.*\\bwin(dows)\\b.*$")) return OS.WINDOWS;
|
||||
|
||||
return OS.UNIX;
|
||||
}
|
||||
@@ -219,7 +219,7 @@ class EclipseFinder {
|
||||
* @return 'Eclipse.app' on OS X, 'eclipse.exe' on Windows, and 'eclipse' on other OSes.
|
||||
*/
|
||||
static String getEclipseExecutableName() {
|
||||
switch ( getOS() ) {
|
||||
switch (getOS()) {
|
||||
case WINDOWS:
|
||||
return "eclipse.exe";
|
||||
case MAC_OS_X:
|
||||
@@ -235,15 +235,15 @@ class EclipseFinder {
|
||||
*/
|
||||
static List<String> findEclipseOnMac() {
|
||||
List<String> eclipses = new ArrayList<String>();
|
||||
for ( File dir : new File("/Applications").listFiles() ) {
|
||||
if ( !dir.isDirectory() ) continue;
|
||||
if ( dir.getName().toLowerCase().equals("eclipse.app") ) {
|
||||
for (File dir : new File("/Applications").listFiles()) {
|
||||
if (!dir.isDirectory()) continue;
|
||||
if (dir.getName().toLowerCase().equals("eclipse.app")) {
|
||||
//This would be kind of an unorthodox Eclipse installation, but if Eclipse ever
|
||||
//moves to this more maclike installation concept, our installer can still handle it.
|
||||
eclipses.add("/Applications");
|
||||
}
|
||||
if ( dir.getName().toLowerCase().contains("eclipse") ) {
|
||||
if ( new File(dir, "Eclipse.app").exists() ) eclipses.add(dir.toString());
|
||||
if (dir.getName().toLowerCase().contains("eclipse")) {
|
||||
if (new File(dir, "Eclipse.app").exists()) eclipses.add(dir.toString());
|
||||
}
|
||||
}
|
||||
return eclipses;
|
||||
|
||||
@@ -48,8 +48,8 @@ final class EclipseLocation {
|
||||
static {
|
||||
String os = System.getProperty("os.name", "");
|
||||
|
||||
if ( "Mac OS".equals(os) ) OS_NEWLINE = "\r";
|
||||
else if ( os.toLowerCase().contains("windows") ) OS_NEWLINE = "\r\n";
|
||||
if ("Mac OS".equals(os)) OS_NEWLINE = "\r";
|
||||
else if (os.toLowerCase().contains("windows")) OS_NEWLINE = "\r\n";
|
||||
else OS_NEWLINE = "\n";
|
||||
}
|
||||
|
||||
@@ -84,28 +84,28 @@ final class EclipseLocation {
|
||||
* @throws NotAnEclipseException If this isn't an Eclipse executable or a directory with an Eclipse executable.
|
||||
*/
|
||||
EclipseLocation(String path) throws NotAnEclipseException {
|
||||
if ( path == null ) throw new NullPointerException("path");
|
||||
if (path == null) throw new NullPointerException("path");
|
||||
File p = new File(path);
|
||||
if ( !p.exists() ) throw new NotAnEclipseException("File does not exist: " + path, null);
|
||||
if (!p.exists()) throw new NotAnEclipseException("File does not exist: " + path, null);
|
||||
|
||||
final String execName = EclipseFinder.getEclipseExecutableName();
|
||||
if ( p.isDirectory() ) {
|
||||
for ( File f : p.listFiles() ) {
|
||||
if ( f.getName().equalsIgnoreCase(execName) ) {
|
||||
if (p.isDirectory()) {
|
||||
for (File f : p.listFiles()) {
|
||||
if (f.getName().equalsIgnoreCase(execName)) {
|
||||
p = f;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ( !p.exists() || !p.getName().equalsIgnoreCase(execName) ) {
|
||||
if (!p.exists() || !p.getName().equalsIgnoreCase(execName)) {
|
||||
throw new NotAnEclipseException("This path does not appear to contain an Eclipse installation: " + p, null);
|
||||
}
|
||||
|
||||
this.path = p;
|
||||
try {
|
||||
this.hasLombok = checkForLombok();
|
||||
} catch ( IOException e ) {
|
||||
} catch (IOException e) {
|
||||
throw new NotAnEclipseException(
|
||||
"I can't read the configuration file of the Eclipse installed at " + this.path.getAbsolutePath() + "\n" +
|
||||
"You may need to run this installer with root privileges if you want to modify that Eclipse.", e);
|
||||
@@ -117,7 +117,7 @@ final class EclipseLocation {
|
||||
}
|
||||
|
||||
@Override public boolean equals(Object o) {
|
||||
if ( !(o instanceof EclipseLocation) ) return false;
|
||||
if (!(o instanceof EclipseLocation)) return false;
|
||||
return ((EclipseLocation)o).path.equals(path);
|
||||
}
|
||||
|
||||
@@ -146,8 +146,8 @@ final class EclipseLocation {
|
||||
}
|
||||
|
||||
private boolean checkForLombok() throws IOException {
|
||||
for ( File targetDir : getTargetDirs() ) {
|
||||
if ( checkForLombok0(targetDir) ) return true;
|
||||
for (File targetDir : getTargetDirs()) {
|
||||
if (checkForLombok0(targetDir)) return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
@@ -161,13 +161,13 @@ final class EclipseLocation {
|
||||
|
||||
private boolean checkForLombok0(File dir) throws IOException {
|
||||
File iniFile = new File(dir, "eclipse.ini");
|
||||
if ( !iniFile.exists() ) return false;
|
||||
if (!iniFile.exists()) return false;
|
||||
FileInputStream fis = new FileInputStream(iniFile);
|
||||
try {
|
||||
BufferedReader br = new BufferedReader(new InputStreamReader(fis));
|
||||
String line;
|
||||
while ( (line = br.readLine()) != null ) {
|
||||
if ( JAVA_AGENT_LINE_MATCHER.matcher(line.trim()).matches() ) return true;
|
||||
while ((line = br.readLine()) != null) {
|
||||
if (JAVA_AGENT_LINE_MATCHER.matcher(line.trim()).matches()) return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
@@ -194,10 +194,10 @@ final class EclipseLocation {
|
||||
* bugs in the uninstall code will probably throw other exceptions; this is intentional.
|
||||
*/
|
||||
void uninstall() throws UninstallException {
|
||||
for ( File dir : getTargetDirs() ) {
|
||||
for (File dir : getTargetDirs()) {
|
||||
File lombokJar = new File(dir, "lombok.jar");
|
||||
if ( lombokJar.exists() ) {
|
||||
if ( !lombokJar.delete() ) throw new UninstallException(
|
||||
if (lombokJar.exists()) {
|
||||
if (!lombokJar.delete()) throw new UninstallException(
|
||||
"Can't delete " + lombokJar.getAbsolutePath() +
|
||||
" - perhaps the installer does not have the access rights to do so.",
|
||||
null);
|
||||
@@ -206,8 +206,8 @@ final class EclipseLocation {
|
||||
/* legacy code - lombok at one point used to have a separate jar for the eclipse agent.
|
||||
* Leave this code in to delete it for those upgrading from an old version. */ {
|
||||
File agentJar = new File(dir, "lombok.eclipse.agent.jar");
|
||||
if ( agentJar.exists() ) {
|
||||
if ( !agentJar.delete() ) throw new UninstallException(
|
||||
if (agentJar.exists()) {
|
||||
if (!agentJar.delete()) throw new UninstallException(
|
||||
"Can't delete " + agentJar.getAbsolutePath() +
|
||||
" - perhaps the installer does not have the access rights to do so.",
|
||||
null);
|
||||
@@ -216,29 +216,29 @@ final class EclipseLocation {
|
||||
|
||||
File iniFile = new File(dir, "eclipse.ini");
|
||||
StringBuilder newContents = new StringBuilder();
|
||||
if ( iniFile.exists() ) {
|
||||
if (iniFile.exists()) {
|
||||
try {
|
||||
FileInputStream fis = new FileInputStream(iniFile);
|
||||
try {
|
||||
BufferedReader br = new BufferedReader(new InputStreamReader(fis));
|
||||
String line;
|
||||
while ( (line = br.readLine()) != null ) {
|
||||
if ( JAVA_AGENT_LINE_MATCHER.matcher(line).matches() ) continue;
|
||||
while ((line = br.readLine()) != null) {
|
||||
if (JAVA_AGENT_LINE_MATCHER.matcher(line).matches()) continue;
|
||||
Matcher m = BOOTCLASSPATH_LINE_MATCHER.matcher(line);
|
||||
if ( m.matches() ) {
|
||||
if (m.matches()) {
|
||||
StringBuilder elemBuilder = new StringBuilder();
|
||||
elemBuilder.append("-Xbootclasspath/a:");
|
||||
boolean first = true;
|
||||
for ( String elem : m.group(1).split(Pattern.quote(File.pathSeparator)) ) {
|
||||
if ( elem.toLowerCase().endsWith("lombok.jar") ) continue;
|
||||
for (String elem : m.group(1).split(Pattern.quote(File.pathSeparator))) {
|
||||
if (elem.toLowerCase().endsWith("lombok.jar")) continue;
|
||||
/* legacy code -see previous comment that starts with 'legacy' */ {
|
||||
if ( elem.toLowerCase().endsWith("lombok.eclipse.agent.jar") ) continue;
|
||||
if (elem.toLowerCase().endsWith("lombok.eclipse.agent.jar")) continue;
|
||||
}
|
||||
if ( first ) first = false;
|
||||
if (first) first = false;
|
||||
else elemBuilder.append(File.pathSeparator);
|
||||
elemBuilder.append(elem);
|
||||
}
|
||||
if ( !first ) newContents.append(elemBuilder.toString()).append(OS_NEWLINE);
|
||||
if (!first) newContents.append(elemBuilder.toString()).append(OS_NEWLINE);
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -255,7 +255,7 @@ final class EclipseLocation {
|
||||
} finally {
|
||||
fos.close();
|
||||
}
|
||||
} catch ( IOException e ) {
|
||||
} catch (IOException e) {
|
||||
throw new UninstallException("Cannot uninstall lombok from " + path.getAbsolutePath() +
|
||||
" probably because this installer does not have the access rights to do so.", e);
|
||||
}
|
||||
@@ -289,10 +289,10 @@ final class EclipseLocation {
|
||||
boolean fullPathRequired = EclipseFinder.getOS() == EclipseFinder.OS.UNIX;
|
||||
|
||||
boolean installSucceeded = false;
|
||||
for ( File dir : getTargetDirs() ) {
|
||||
for (File dir : getTargetDirs()) {
|
||||
File iniFile = new File(dir, "eclipse.ini");
|
||||
StringBuilder newContents = new StringBuilder();
|
||||
if ( !iniFile.exists() ) failedDirs.add(dir);
|
||||
if (!iniFile.exists()) failedDirs.add(dir);
|
||||
else {
|
||||
//If 'installSucceeded' is true here, something very weird is going on, but instrumenting all of them
|
||||
//is no less bad than aborting, and this situation should be rare to the point of non-existence.
|
||||
@@ -306,19 +306,19 @@ final class EclipseLocation {
|
||||
FileOutputStream out = new FileOutputStream(lombokJar);
|
||||
InputStream in = new FileInputStream(ourJar);
|
||||
try {
|
||||
while ( true ) {
|
||||
while (true) {
|
||||
int r = in.read(b);
|
||||
if ( r == -1 ) break;
|
||||
if (r == -1) break;
|
||||
out.write(b, 0, r);
|
||||
}
|
||||
} finally {
|
||||
out.close();
|
||||
}
|
||||
} catch ( IOException e ) {
|
||||
} catch (IOException e) {
|
||||
try {
|
||||
lombokJar.delete();
|
||||
} catch ( Throwable ignore ) {}
|
||||
if ( !readSucceeded ) throw new InstallException("I can't read my own jar file. I think you've found a bug in this installer! I suggest you restart it " +
|
||||
} catch (Throwable ignore) {}
|
||||
if (!readSucceeded) throw new InstallException("I can't read my own jar file. I think you've found a bug in this installer! I suggest you restart it " +
|
||||
"and use the 'what do I do' link, to manually install lombok. And tell us about this. Thanks!", e);
|
||||
throw new InstallException("I can't write to your Eclipse directory, probably because this installer does not have the access rights.", e);
|
||||
}
|
||||
@@ -332,23 +332,23 @@ final class EclipseLocation {
|
||||
try {
|
||||
BufferedReader br = new BufferedReader(new InputStreamReader(fis));
|
||||
String line;
|
||||
while ( (line = br.readLine()) != null ) {
|
||||
if ( JAVA_AGENT_LINE_MATCHER.matcher(line).matches() ) continue;
|
||||
while ((line = br.readLine()) != null) {
|
||||
if (JAVA_AGENT_LINE_MATCHER.matcher(line).matches()) continue;
|
||||
Matcher m = BOOTCLASSPATH_LINE_MATCHER.matcher(line);
|
||||
if ( m.matches() ) {
|
||||
if (m.matches()) {
|
||||
StringBuilder elemBuilder = new StringBuilder();
|
||||
elemBuilder.append("-Xbootclasspath/a:");
|
||||
boolean first = true;
|
||||
for ( String elem : m.group(1).split(Pattern.quote(File.pathSeparator)) ) {
|
||||
if ( elem.toLowerCase().endsWith("lombok.jar") ) continue;
|
||||
for (String elem : m.group(1).split(Pattern.quote(File.pathSeparator))) {
|
||||
if (elem.toLowerCase().endsWith("lombok.jar")) continue;
|
||||
/* legacy code -see previous comment that starts with 'legacy' */ {
|
||||
if ( elem.toLowerCase().endsWith("lombok.eclipse.agent.jar") ) continue;
|
||||
if (elem.toLowerCase().endsWith("lombok.eclipse.agent.jar")) continue;
|
||||
}
|
||||
if ( first ) first = false;
|
||||
if (first) first = false;
|
||||
else elemBuilder.append(File.pathSeparator);
|
||||
elemBuilder.append(elem);
|
||||
}
|
||||
if ( !first ) newContents.append(elemBuilder.toString()).append(OS_NEWLINE);
|
||||
if (!first) newContents.append(elemBuilder.toString()).append(OS_NEWLINE);
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -373,27 +373,27 @@ final class EclipseLocation {
|
||||
fos.close();
|
||||
}
|
||||
installSucceeded = true;
|
||||
} catch ( IOException e ) {
|
||||
} catch (IOException e) {
|
||||
throw new InstallException("Cannot install lombok at " + path.getAbsolutePath() +
|
||||
" probably because this installer does not have the access rights to do so.", e);
|
||||
} finally {
|
||||
if ( !installSucceeded ) try {
|
||||
if (!installSucceeded) try {
|
||||
lombokJar.delete();
|
||||
} catch ( Throwable ignore ) {}
|
||||
} catch (Throwable ignore) {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ( !installSucceeded ) {
|
||||
if (!installSucceeded) {
|
||||
throw new InstallException("I can't find the eclipse.ini file. Is this a real Eclipse installation?", null);
|
||||
}
|
||||
|
||||
for ( File dir : failedDirs ) {
|
||||
for (File dir : failedDirs) {
|
||||
/* Legacy code - lombok's installer used to install in other places. To keep the user's eclipse dir clean, we'll delete these. */ {
|
||||
try {
|
||||
new File(dir, "lombok.jar").delete();
|
||||
new File(dir, "lombok.eclipse.agent.jar").delete();
|
||||
} catch ( Throwable ignore ) {}
|
||||
} catch (Throwable ignore) {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -96,7 +96,7 @@ public class Installer {
|
||||
private JButton installButton;
|
||||
|
||||
public static void main(String[] args) {
|
||||
if ( EclipseFinder.getOS() == OS.MAC_OS_X ) {
|
||||
if (EclipseFinder.getOS() == OS.MAC_OS_X) {
|
||||
System.setProperty("com.apple.mrj.application.apple.menu.about.name", "Lombok Installer");
|
||||
System.setProperty("com.apple.macos.use-file-dialog-packages", "true");
|
||||
}
|
||||
@@ -107,15 +107,15 @@ public class Installer {
|
||||
try {
|
||||
try {
|
||||
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
|
||||
} catch ( Exception ignore ) {}
|
||||
} catch (Exception ignore) {}
|
||||
|
||||
new Installer().show();
|
||||
} catch ( HeadlessException e ) {
|
||||
} catch (HeadlessException e) {
|
||||
printHeadlessInfo();
|
||||
}
|
||||
}
|
||||
});
|
||||
} catch ( HeadlessException e ) {
|
||||
} catch (HeadlessException e) {
|
||||
printHeadlessInfo();
|
||||
}
|
||||
}
|
||||
@@ -156,7 +156,7 @@ public class Installer {
|
||||
howIWorkArea.setVisible(false);
|
||||
buildChrome(appWindow.getContentPane());
|
||||
appWindow.pack();
|
||||
} catch ( Throwable t ) {
|
||||
} catch (Throwable t) {
|
||||
handleException(t);
|
||||
}
|
||||
}
|
||||
@@ -312,31 +312,31 @@ public class Installer {
|
||||
final List<EclipseLocation> locations = new ArrayList<EclipseLocation>();
|
||||
final List<NotAnEclipseException> problems = new ArrayList<NotAnEclipseException>();
|
||||
|
||||
if ( eclipses != null ) {
|
||||
for ( String eclipse : eclipses ) try {
|
||||
if (eclipses != null) {
|
||||
for (String eclipse : eclipses) try {
|
||||
locations.add(new EclipseLocation(eclipse));
|
||||
} catch ( NotAnEclipseException e ) {
|
||||
} catch (NotAnEclipseException e) {
|
||||
problems.add(e);
|
||||
}
|
||||
}
|
||||
|
||||
SwingUtilities.invokeLater(new Runnable() {
|
||||
@Override public void run() {
|
||||
for ( EclipseLocation location : locations ) {
|
||||
for (EclipseLocation location : locations) {
|
||||
try {
|
||||
eclipsesList.addEclipse(location);
|
||||
} catch ( Throwable t ) {
|
||||
} catch (Throwable t) {
|
||||
handleException(t);
|
||||
}
|
||||
}
|
||||
|
||||
for ( NotAnEclipseException problem : problems ) {
|
||||
for (NotAnEclipseException problem : problems) {
|
||||
problem.showDialog(appWindow);
|
||||
}
|
||||
|
||||
loadingExpl.setVisible(false);
|
||||
|
||||
if ( eclipses == null ) {
|
||||
if (eclipses == null) {
|
||||
JOptionPane.showMessageDialog(appWindow,
|
||||
"I don't know how to automatically find Eclipse installations on this platform.\n" +
|
||||
"Please use the 'Specify Eclipse Location...' button to manually point out the\n" +
|
||||
@@ -344,7 +344,7 @@ public class Installer {
|
||||
}
|
||||
}
|
||||
});
|
||||
} catch ( Throwable t ) {
|
||||
} catch (Throwable t) {
|
||||
handleException(t);
|
||||
}
|
||||
}
|
||||
@@ -360,13 +360,13 @@ public class Installer {
|
||||
final String name = EclipseFinder.getEclipseExecutableName();
|
||||
String file = null;
|
||||
|
||||
if ( EclipseFinder.getOS() == OS.MAC_OS_X ) {
|
||||
if (EclipseFinder.getOS() == OS.MAC_OS_X) {
|
||||
FileDialog chooser = new FileDialog(appWindow);
|
||||
chooser.setMode(FileDialog.LOAD);
|
||||
chooser.setFilenameFilter(new FilenameFilter() {
|
||||
@Override public boolean accept(File dir, String name) {
|
||||
if ( name.equalsIgnoreCase(name) ) return true;
|
||||
if ( new File(dir, name).isDirectory() ) return true;
|
||||
if (name.equalsIgnoreCase(name)) return true;
|
||||
if (new File(dir, name).isDirectory()) return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
@@ -381,8 +381,8 @@ public class Installer {
|
||||
chooser.setFileSelectionMode(JFileChooser.FILES_ONLY);
|
||||
chooser.setFileFilter(new FileFilter() {
|
||||
@Override public boolean accept(File f) {
|
||||
if ( f.getName().equalsIgnoreCase(name) ) return true;
|
||||
if ( f.isDirectory() ) return true;
|
||||
if (f.getName().equalsIgnoreCase(name)) return true;
|
||||
if (f.isDirectory()) return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
@@ -392,18 +392,18 @@ public class Installer {
|
||||
}
|
||||
});
|
||||
|
||||
switch ( chooser.showDialog(appWindow, "Select") ) {
|
||||
switch (chooser.showDialog(appWindow, "Select")) {
|
||||
case JFileChooser.APPROVE_OPTION:
|
||||
file = chooser.getSelectedFile().getAbsolutePath();
|
||||
}
|
||||
}
|
||||
|
||||
if ( file != null ) {
|
||||
if (file != null) {
|
||||
try {
|
||||
eclipsesList.addEclipse(new EclipseLocation(file));
|
||||
} catch ( NotAnEclipseException e ) {
|
||||
} catch (NotAnEclipseException e) {
|
||||
e.showDialog(appWindow);
|
||||
} catch ( Throwable t ) {
|
||||
} catch (Throwable t) {
|
||||
handleException(t);
|
||||
}
|
||||
}
|
||||
@@ -417,7 +417,7 @@ public class Installer {
|
||||
installButton.addActionListener(new ActionListener() {
|
||||
@Override public void actionPerformed(ActionEvent e) {
|
||||
List<EclipseLocation> locationsToInstall = new ArrayList<EclipseLocation>(eclipsesList.getSelectedEclipses());
|
||||
if ( locationsToInstall.isEmpty() ) {
|
||||
if (locationsToInstall.isEmpty()) {
|
||||
JOptionPane.showMessageDialog(appWindow, "You haven't selected any Eclipse installations!.", "No Selection", JOptionPane.WARNING_MESSAGE);
|
||||
return;
|
||||
}
|
||||
@@ -446,11 +446,11 @@ public class Installer {
|
||||
uninstallButton.addActionListener(new ActionListener() {
|
||||
@Override public void actionPerformed(ActionEvent e) {
|
||||
List<EclipseLocation> locationsToUninstall = new ArrayList<EclipseLocation>();
|
||||
for ( EclipseLocation location : eclipsesList.getSelectedEclipses() ) {
|
||||
if ( location.hasLombok() ) locationsToUninstall.add(location);
|
||||
for (EclipseLocation location : eclipsesList.getSelectedEclipses()) {
|
||||
if (location.hasLombok()) locationsToUninstall.add(location);
|
||||
}
|
||||
|
||||
if ( locationsToUninstall.isEmpty() ) {
|
||||
if (locationsToUninstall.isEmpty()) {
|
||||
JOptionPane.showMessageDialog(appWindow, "You haven't selected any Eclipse installations that have been lombok-enabled.", "No Selection", JOptionPane.WARNING_MESSAGE);
|
||||
return;
|
||||
}
|
||||
@@ -480,7 +480,7 @@ public class Installer {
|
||||
|
||||
uninstallBox.removeAll();
|
||||
uninstallBox.add(Box.createRigidArea(new Dimension(1, 16)));
|
||||
for ( EclipseLocation location : locations ) {
|
||||
for (EclipseLocation location : locations) {
|
||||
JLabel label = new JLabel(location.getPath());
|
||||
label.setFont(label.getFont().deriveFont(Font.BOLD));
|
||||
uninstallBox.add(label);
|
||||
@@ -503,10 +503,10 @@ public class Installer {
|
||||
|
||||
new Thread() {
|
||||
@Override public void run() {
|
||||
for ( EclipseLocation loc : toInstall ) {
|
||||
for (EclipseLocation loc : toInstall) {
|
||||
try {
|
||||
loc.install();
|
||||
} catch ( final InstallException e ) {
|
||||
} catch (final InstallException e) {
|
||||
success.set(false);
|
||||
try {
|
||||
SwingUtilities.invokeAndWait(new Runnable() {
|
||||
@@ -515,14 +515,14 @@ public class Installer {
|
||||
e.getMessage(), "Install Problem", JOptionPane.ERROR_MESSAGE);
|
||||
}
|
||||
});
|
||||
} catch ( Exception e2 ) {
|
||||
} catch (Exception e2) {
|
||||
//Shouldn't happen.
|
||||
throw new RuntimeException(e2);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ( success.get() ) SwingUtilities.invokeLater(new Runnable() {
|
||||
if (success.get()) SwingUtilities.invokeLater(new Runnable() {
|
||||
@Override public void run() {
|
||||
JOptionPane.showMessageDialog(appWindow, "<html>Lombok has been installed on the selected Eclipse installations.<br>Don't forget to add <code>lombok.jar</code> to your projects, and restart your eclipse!</html>", "Install successful", JOptionPane.INFORMATION_MESSAGE);
|
||||
appWindow.setVisible(false);
|
||||
@@ -544,10 +544,10 @@ public class Installer {
|
||||
final AtomicReference<Boolean> success = new AtomicReference<Boolean>(true);
|
||||
new Thread() {
|
||||
@Override public void run() {
|
||||
for ( EclipseLocation loc : toUninstall ) {
|
||||
for (EclipseLocation loc : toUninstall) {
|
||||
try {
|
||||
loc.uninstall();
|
||||
} catch ( final UninstallException e ) {
|
||||
} catch (final UninstallException e) {
|
||||
success.set(false);
|
||||
try {
|
||||
SwingUtilities.invokeAndWait(new Runnable() {
|
||||
@@ -556,14 +556,14 @@ public class Installer {
|
||||
e.getMessage(), "Uninstall Problem", JOptionPane.ERROR_MESSAGE);
|
||||
}
|
||||
});
|
||||
} catch ( Exception e2 ) {
|
||||
} catch (Exception e2) {
|
||||
//Shouldn't happen.
|
||||
throw new RuntimeException(e2);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ( success.get() ) SwingUtilities.invokeLater(new Runnable() {
|
||||
if (success.get()) SwingUtilities.invokeLater(new Runnable() {
|
||||
@Override public void run() {
|
||||
JOptionPane.showMessageDialog(appWindow, "Lombok has been removed from the selected Eclipse installations.", "Uninstall successful", JOptionPane.INFORMATION_MESSAGE);
|
||||
appWindow.setVisible(false);
|
||||
@@ -594,8 +594,8 @@ public class Installer {
|
||||
void selectedLomboksChanged(List<EclipseLocation> selectedEclipses) {
|
||||
boolean uninstallAvailable = false;
|
||||
boolean installAvailable = false;
|
||||
for ( EclipseLocation loc : selectedEclipses ) {
|
||||
if ( loc.hasLombok() ) uninstallAvailable = true;
|
||||
for (EclipseLocation loc : selectedEclipses) {
|
||||
if (loc.hasLombok()) uninstallAvailable = true;
|
||||
installAvailable = true;
|
||||
}
|
||||
|
||||
@@ -616,7 +616,7 @@ public class Installer {
|
||||
|
||||
List<EclipseLocation> getSelectedEclipses() {
|
||||
List<EclipseLocation> list = new ArrayList<EclipseLocation>();
|
||||
for ( EclipseLocation loc : locations ) if ( loc.selected ) list.add(loc);
|
||||
for (EclipseLocation loc : locations) if (loc.selected) list.add(loc);
|
||||
return list;
|
||||
}
|
||||
|
||||
@@ -625,7 +625,7 @@ public class Installer {
|
||||
}
|
||||
|
||||
void addEclipse(final EclipseLocation location) {
|
||||
if ( locations.contains(location) ) return;
|
||||
if (locations.contains(location)) return;
|
||||
Box box = Box.createHorizontalBox();
|
||||
box.setBackground(Color.WHITE);
|
||||
final JCheckBox checkbox = new JCheckBox(location.getPath());
|
||||
@@ -639,7 +639,7 @@ public class Installer {
|
||||
}
|
||||
});
|
||||
|
||||
if ( location.hasLombok() ) {
|
||||
if (location.hasLombok()) {
|
||||
box.add(new JLabel(new ImageIcon(Installer.class.getResource("/lombok/installer/lombokIcon.png"))));
|
||||
}
|
||||
box.add(Box.createHorizontalGlue());
|
||||
@@ -726,10 +726,10 @@ public class Installer {
|
||||
//java.awt.Desktop doesn't exist in 1.5.
|
||||
Object desktop = Class.forName("java.awt.Desktop").getMethod("getDesktop").invoke(null);
|
||||
Class.forName("java.awt.Desktop").getMethod("browse", URI.class).invoke(desktop, ABOUT_LOMBOK_URL);
|
||||
} catch ( Exception e ) {
|
||||
} catch (Exception e) {
|
||||
Runtime rt = Runtime.getRuntime();
|
||||
try {
|
||||
switch ( EclipseFinder.getOS() ) {
|
||||
switch (EclipseFinder.getOS()) {
|
||||
case WINDOWS:
|
||||
String[] cmd = new String[4];
|
||||
cmd[0] = "cmd.exe";
|
||||
@@ -746,7 +746,7 @@ public class Installer {
|
||||
rt.exec("firefox " + ABOUT_LOMBOK_URL.toString());
|
||||
break;
|
||||
}
|
||||
} catch ( Exception e2 ) {
|
||||
} catch (Exception e2) {
|
||||
JOptionPane.showMessageDialog(appWindow,
|
||||
"Well, this is embarrassing. I don't know how to open a webbrowser.\n" +
|
||||
"I guess you'll have to open it. Browse to:\n" +
|
||||
@@ -770,10 +770,10 @@ public class Installer {
|
||||
*/
|
||||
public void show() {
|
||||
appWindow.setVisible(true);
|
||||
if ( EclipseFinder.getOS() == OS.MAC_OS_X ) {
|
||||
if (EclipseFinder.getOS() == OS.MAC_OS_X) {
|
||||
try {
|
||||
AppleNativeLook.go();
|
||||
} catch ( Throwable ignore ) {
|
||||
} catch (Throwable ignore) {
|
||||
//We're just prettying up the app. If it fails, meh.
|
||||
}
|
||||
}
|
||||
|
||||
@@ -77,8 +77,8 @@ public class WindowsDriveInfo {
|
||||
int flags = getLogicalDrives0();
|
||||
|
||||
List<String> letters = new ArrayList<String>();
|
||||
for ( int i = 0 ; i < 26 ; i++ ) {
|
||||
if ( (flags & (1 << i)) != 0 ) letters.add(Character.toString((char)('A' + i)));
|
||||
for (int i = 0; i < 26; i++) {
|
||||
if ((flags & (1 << i)) != 0) letters.add(Character.toString((char)('A' + i)));
|
||||
}
|
||||
|
||||
return letters;
|
||||
@@ -94,9 +94,9 @@ public class WindowsDriveInfo {
|
||||
* Feed it a drive letter (such as 'A') to see if it is a fixed disk.
|
||||
*/
|
||||
public boolean isFixedDisk(String letter) {
|
||||
if ( letter.length() != 1 ) throw new IllegalArgumentException("Supply 1 letter, not: " + letter);
|
||||
if (letter.length() != 1) throw new IllegalArgumentException("Supply 1 letter, not: " + letter);
|
||||
char drive = Character.toUpperCase(letter.charAt(0));
|
||||
if ( drive < 'A' || drive > 'Z' ) throw new IllegalArgumentException(
|
||||
if (drive < 'A' || drive > 'Z') throw new IllegalArgumentException(
|
||||
"A drive is indicated by a letter, so A-Z inclusive. Not " + drive);
|
||||
return getDriveType(drive + ":\\") == 3L;
|
||||
}
|
||||
@@ -119,7 +119,7 @@ public class WindowsDriveInfo {
|
||||
System.loadLibrary("WindowsDriveInfo");
|
||||
WindowsDriveInfo info = new WindowsDriveInfo();
|
||||
|
||||
for ( String letter : info.getLogicalDrives() ) {
|
||||
for (String letter : info.getLogicalDrives()) {
|
||||
System.out.printf("Drive %s: - %s\n", letter,
|
||||
info.isFixedDisk(letter) ? "Fixed Disk" : "Not Fixed Disk");
|
||||
}
|
||||
|
||||
@@ -72,7 +72,7 @@ public class HandlerLibrary {
|
||||
this.annotationClass = annotationClass;
|
||||
}
|
||||
|
||||
public boolean handle(final JavacAST.Node node) {
|
||||
public boolean handle(final JavacNode node) {
|
||||
return handler.handle(Javac.createAnnotation(annotationClass, node), (JCAnnotation)node.get(), node);
|
||||
}
|
||||
}
|
||||
@@ -97,17 +97,17 @@ public class HandlerLibrary {
|
||||
//No, that seemingly superfluous reference to JavacAnnotationHandler's classloader is not in fact superfluous!
|
||||
Iterator<JavacAnnotationHandler> it = ServiceLoader.load(JavacAnnotationHandler.class,
|
||||
JavacAnnotationHandler.class.getClassLoader()).iterator();
|
||||
while ( it.hasNext() ) {
|
||||
while (it.hasNext()) {
|
||||
try {
|
||||
JavacAnnotationHandler<?> handler = it.next();
|
||||
Class<? extends Annotation> annotationClass =
|
||||
SpiLoadUtil.findAnnotationClass(handler.getClass(), JavacAnnotationHandler.class);
|
||||
AnnotationHandlerContainer<?> container = new AnnotationHandlerContainer(handler, annotationClass);
|
||||
if ( lib.annotationHandlers.put(container.annotationClass.getName(), container) != null ) {
|
||||
if (lib.annotationHandlers.put(container.annotationClass.getName(), container) != null) {
|
||||
lib.javacWarning("Duplicate handlers for annotation type: " + container.annotationClass.getName());
|
||||
}
|
||||
lib.typeLibrary.addType(container.annotationClass.getName());
|
||||
} catch ( ServiceConfigurationError e ) {
|
||||
} catch (ServiceConfigurationError e) {
|
||||
lib.javacWarning("Can't load Lombok annotation handler for javac", e);
|
||||
}
|
||||
}
|
||||
@@ -118,11 +118,11 @@ public class HandlerLibrary {
|
||||
//No, that seemingly superfluous reference to JavacASTVisitor's classloader is not in fact superfluous!
|
||||
Iterator<JavacASTVisitor> it = ServiceLoader.load(JavacASTVisitor.class,
|
||||
JavacASTVisitor.class.getClassLoader()).iterator();
|
||||
while ( it.hasNext() ) {
|
||||
while (it.hasNext()) {
|
||||
try {
|
||||
JavacASTVisitor handler = it.next();
|
||||
lib.visitorHandlers.add(handler);
|
||||
} catch ( ServiceConfigurationError e ) {
|
||||
} catch (ServiceConfigurationError e) {
|
||||
lib.javacWarning("Can't load Lombok visitor handler for javac", e);
|
||||
}
|
||||
}
|
||||
@@ -146,7 +146,7 @@ public class HandlerLibrary {
|
||||
/** Generates an error in the Messager that was used to initialize this HandlerLibrary. */
|
||||
public void javacError(String message, Throwable t) {
|
||||
messager.printMessage(Diagnostic.Kind.ERROR, message + (t == null ? "" : (": " + t)));
|
||||
if ( t != null ) t.printStackTrace();
|
||||
if (t != null) t.printStackTrace();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -166,23 +166,23 @@ public class HandlerLibrary {
|
||||
* @param node The Lombok AST Node representing the Annotation AST Node.
|
||||
* @param annotation 'node.get()' - convenience parameter.
|
||||
*/
|
||||
public boolean handleAnnotation(JCCompilationUnit unit, JavacAST.Node node, JCAnnotation annotation) {
|
||||
public boolean handleAnnotation(JCCompilationUnit unit, JavacNode node, JCAnnotation annotation) {
|
||||
TypeResolver resolver = new TypeResolver(typeLibrary, node.getPackageDeclaration(), node.getImportStatements());
|
||||
String rawType = annotation.annotationType.toString();
|
||||
boolean handled = false;
|
||||
for ( String fqn : resolver.findTypeMatches(node, rawType) ) {
|
||||
for (String fqn : resolver.findTypeMatches(node, rawType)) {
|
||||
boolean isPrintAST = fqn.equals(PrintAST.class.getName());
|
||||
if ( isPrintAST == skipPrintAST ) continue;
|
||||
if (isPrintAST == skipPrintAST) continue;
|
||||
AnnotationHandlerContainer<?> container = annotationHandlers.get(fqn);
|
||||
if ( container == null ) continue;
|
||||
if (container == null) continue;
|
||||
|
||||
try {
|
||||
handled |= container.handle(node);
|
||||
} catch ( AnnotationValueDecodeFail fail ) {
|
||||
} catch (AnnotationValueDecodeFail fail) {
|
||||
fail.owner.setError(fail.getMessage(), fail.idx);
|
||||
} catch ( Throwable t ) {
|
||||
} catch (Throwable t) {
|
||||
String sourceName = "(unknown).java";
|
||||
if ( unit != null && unit.sourcefile != null ) sourceName = unit.sourcefile.getName();
|
||||
if (unit != null && unit.sourcefile != null) sourceName = unit.sourcefile.getName();
|
||||
javacError(String.format("Lombok annotation handler %s failed on " + sourceName, container.handler.getClass()), t);
|
||||
}
|
||||
}
|
||||
@@ -194,9 +194,9 @@ public class HandlerLibrary {
|
||||
* Will call all registered {@link JavacASTVisitor} instances.
|
||||
*/
|
||||
public void callASTVisitors(JavacAST ast) {
|
||||
for ( JavacASTVisitor visitor : visitorHandlers ) try {
|
||||
for (JavacASTVisitor visitor : visitorHandlers) try {
|
||||
ast.traverse(visitor);
|
||||
} catch ( Throwable t ) {
|
||||
} catch (Throwable t) {
|
||||
javacError(String.format("Lombok visitor handler %s failed", visitor.getClass()), t);
|
||||
}
|
||||
}
|
||||
|
||||
+19
-20
@@ -35,7 +35,6 @@ import lombok.core.TypeLibrary;
|
||||
import lombok.core.TypeResolver;
|
||||
import lombok.core.AST.Kind;
|
||||
import lombok.core.AnnotationValues.AnnotationValue;
|
||||
import lombok.javac.JavacAST.Node;
|
||||
|
||||
import com.sun.tools.javac.tree.JCTree.JCAnnotation;
|
||||
import com.sun.tools.javac.tree.JCTree.JCAssign;
|
||||
@@ -60,8 +59,8 @@ public class Javac {
|
||||
* @param type An actual annotation type, such as <code>lombok.Getter.class</code>.
|
||||
* @param node A Lombok AST node representing an annotation in source code.
|
||||
*/
|
||||
public static boolean annotationTypeMatches(Class<? extends Annotation> type, Node node) {
|
||||
if ( node.getKind() != Kind.ANNOTATION ) return false;
|
||||
public static boolean annotationTypeMatches(Class<? extends Annotation> type, JavacNode node) {
|
||||
if (node.getKind() != Kind.ANNOTATION) return false;
|
||||
String typeName = ((JCAnnotation)node.get()).annotationType.toString();
|
||||
|
||||
TypeLibrary library = new TypeLibrary();
|
||||
@@ -69,8 +68,8 @@ public class Javac {
|
||||
TypeResolver resolver = new TypeResolver(library, node.getPackageDeclaration(), node.getImportStatements());
|
||||
Collection<String> typeMatches = resolver.findTypeMatches(node, typeName);
|
||||
|
||||
for ( String match : typeMatches ) {
|
||||
if ( match.equals(type.getName()) ) return true;
|
||||
for (String match : typeMatches) {
|
||||
if (match.equals(type.getName())) return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
@@ -82,23 +81,23 @@ public class Javac {
|
||||
* @param type An annotation class type, such as <code>lombok.Getter.class</code>.
|
||||
* @param node A Lombok AST node representing an annotation in source code.
|
||||
*/
|
||||
public static <A extends Annotation> AnnotationValues<A> createAnnotation(Class<A> type, final Node node) {
|
||||
public static <A extends Annotation> AnnotationValues<A> createAnnotation(Class<A> type, final JavacNode node) {
|
||||
Map<String, AnnotationValue> values = new HashMap<String, AnnotationValue>();
|
||||
JCAnnotation anno = (JCAnnotation) node.get();
|
||||
List<JCExpression> arguments = anno.getArguments();
|
||||
for ( Method m : type.getDeclaredMethods() ) {
|
||||
if ( !Modifier.isPublic(m.getModifiers()) ) continue;
|
||||
for (Method m : type.getDeclaredMethods()) {
|
||||
if (!Modifier.isPublic(m.getModifiers())) continue;
|
||||
String name = m.getName();
|
||||
List<String> raws = new ArrayList<String>();
|
||||
List<Object> guesses = new ArrayList<Object>();
|
||||
final List<DiagnosticPosition> positions = new ArrayList<DiagnosticPosition>();
|
||||
boolean isExplicit = false;
|
||||
|
||||
for ( JCExpression arg : arguments ) {
|
||||
for (JCExpression arg : arguments) {
|
||||
String mName;
|
||||
JCExpression rhs;
|
||||
|
||||
if ( arg instanceof JCAssign ) {
|
||||
if (arg instanceof JCAssign) {
|
||||
JCAssign assign = (JCAssign) arg;
|
||||
mName = assign.lhs.toString();
|
||||
rhs = assign.rhs;
|
||||
@@ -107,11 +106,11 @@ public class Javac {
|
||||
mName = "value";
|
||||
}
|
||||
|
||||
if ( !mName.equals(name) ) continue;
|
||||
if (!mName.equals(name)) continue;
|
||||
isExplicit = true;
|
||||
if ( rhs instanceof JCNewArray ) {
|
||||
if (rhs instanceof JCNewArray) {
|
||||
List<JCExpression> elems = ((JCNewArray)rhs).elems;
|
||||
for ( JCExpression inner : elems ) {
|
||||
for (JCExpression inner : elems) {
|
||||
raws.add(inner.toString());
|
||||
guesses.add(calculateGuess(inner));
|
||||
positions.add(inner.pos());
|
||||
@@ -125,11 +124,11 @@ public class Javac {
|
||||
|
||||
values.put(name, new AnnotationValue(node, raws, guesses, isExplicit) {
|
||||
@Override public void setError(String message, int valueIdx) {
|
||||
if ( valueIdx < 0 ) node.addError(message);
|
||||
if (valueIdx < 0) node.addError(message);
|
||||
else node.addError(message, positions.get(valueIdx));
|
||||
}
|
||||
@Override public void setWarning(String message, int valueIdx) {
|
||||
if ( valueIdx < 0 ) node.addWarning(message);
|
||||
if (valueIdx < 0) node.addWarning(message);
|
||||
else node.addWarning(message, positions.get(valueIdx));
|
||||
}
|
||||
});
|
||||
@@ -144,18 +143,18 @@ public class Javac {
|
||||
* Will for example turn a TrueLiteral into 'Boolean.valueOf(true)'.
|
||||
*/
|
||||
private static Object calculateGuess(JCExpression expr) {
|
||||
if ( expr instanceof JCLiteral ) {
|
||||
if (expr instanceof JCLiteral) {
|
||||
JCLiteral lit = (JCLiteral)expr;
|
||||
if ( lit.getKind() == com.sun.source.tree.Tree.Kind.BOOLEAN_LITERAL ) {
|
||||
if (lit.getKind() == com.sun.source.tree.Tree.Kind.BOOLEAN_LITERAL) {
|
||||
return ((Number)lit.value).intValue() == 0 ? false : true;
|
||||
}
|
||||
return lit.value;
|
||||
} else if ( expr instanceof JCIdent || expr instanceof JCFieldAccess ) {
|
||||
} else if (expr instanceof JCIdent || expr instanceof JCFieldAccess) {
|
||||
String x = expr.toString();
|
||||
if ( x.endsWith(".class") ) x = x.substring(0, x.length() - 6);
|
||||
if (x.endsWith(".class")) x = x.substring(0, x.length() - 6);
|
||||
else {
|
||||
int idx = x.lastIndexOf('.');
|
||||
if ( idx > -1 ) x = x.substring(idx + 1);
|
||||
if (idx > -1) x = x.substring(idx + 1);
|
||||
}
|
||||
return x;
|
||||
} else return null;
|
||||
|
||||
+73
-272
@@ -55,7 +55,7 @@ import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition;
|
||||
* Wraps around javac's internal AST view to add useful features as well as the ability to visit parents from children,
|
||||
* something javac's own AST system does not offer.
|
||||
*/
|
||||
public class JavacAST extends AST<JCTree> {
|
||||
public class JavacAST extends AST<JavacAST, JavacNode, JCTree> {
|
||||
private final Messager messager;
|
||||
private final Name.Table nameTable;
|
||||
private final TreeMaker treeMaker;
|
||||
@@ -90,8 +90,8 @@ public class JavacAST extends AST<JCTree> {
|
||||
@Override public Collection<String> getImportStatements() {
|
||||
List<String> imports = new ArrayList<String>();
|
||||
JCCompilationUnit unit = (JCCompilationUnit)top().get();
|
||||
for ( JCTree def : unit.defs ) {
|
||||
if ( def instanceof JCImport ) {
|
||||
for (JCTree def : unit.defs) {
|
||||
if (def instanceof JCImport) {
|
||||
imports.add(((JCImport)def).qualid.toString());
|
||||
}
|
||||
}
|
||||
@@ -107,22 +107,12 @@ public class JavacAST extends AST<JCTree> {
|
||||
top().traverse(visitor);
|
||||
}
|
||||
|
||||
private void traverseChildren(JavacASTVisitor visitor, Node node) {
|
||||
for ( Node child : new ArrayList<Node>(node.down()) ) {
|
||||
void traverseChildren(JavacASTVisitor visitor, JavacNode node) {
|
||||
for (JavacNode child : new ArrayList<JavacNode>(node.down())) {
|
||||
child.traverse(visitor);
|
||||
}
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override public Node top() {
|
||||
return (Node) super.top();
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override public Node get(JCTree astNode) {
|
||||
return (Node) super.get(astNode);
|
||||
}
|
||||
|
||||
/** @return A Name object generated for the proper name table belonging to this AST. */
|
||||
public Name toName(String name) {
|
||||
return nameTable.fromString(name);
|
||||
@@ -139,8 +129,8 @@ public class JavacAST extends AST<JCTree> {
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override protected Node buildTree(JCTree node, Kind kind) {
|
||||
switch ( kind ) {
|
||||
@Override protected JavacNode buildTree(JCTree node, Kind kind) {
|
||||
switch (kind) {
|
||||
case COMPILATION_UNIT:
|
||||
return buildCompilationUnit((JCCompilationUnit) node);
|
||||
case TYPE:
|
||||
@@ -164,99 +154,100 @@ public class JavacAST extends AST<JCTree> {
|
||||
}
|
||||
}
|
||||
|
||||
private Node buildCompilationUnit(JCCompilationUnit top) {
|
||||
List<Node> childNodes = new ArrayList<Node>();
|
||||
for ( JCTree s : top.defs ) {
|
||||
if ( s instanceof JCClassDecl ) {
|
||||
private JavacNode buildCompilationUnit(JCCompilationUnit top) {
|
||||
List<JavacNode> childNodes = new ArrayList<JavacNode>();
|
||||
for (JCTree s : top.defs) {
|
||||
if (s instanceof JCClassDecl) {
|
||||
addIfNotNull(childNodes, buildType((JCClassDecl)s));
|
||||
} // else they are import statements, which we don't care about. Or Skip objects, whatever those are.
|
||||
}
|
||||
|
||||
return new Node(top, childNodes, Kind.COMPILATION_UNIT);
|
||||
return new JavacNode(this, top, childNodes, Kind.COMPILATION_UNIT);
|
||||
}
|
||||
|
||||
private Node buildType(JCClassDecl type) {
|
||||
if ( setAndGetAsHandled(type) ) return null;
|
||||
List<Node> childNodes = new ArrayList<Node>();
|
||||
private JavacNode buildType(JCClassDecl type) {
|
||||
if (setAndGetAsHandled(type)) return null;
|
||||
List<JavacNode> childNodes = new ArrayList<JavacNode>();
|
||||
|
||||
for ( JCTree def : type.defs ) {
|
||||
for ( JCAnnotation annotation : type.mods.annotations ) addIfNotNull(childNodes, buildAnnotation(annotation));
|
||||
for (JCTree def : type.defs) {
|
||||
for (JCAnnotation annotation : type.mods.annotations) addIfNotNull(childNodes, buildAnnotation(annotation));
|
||||
/* A def can be:
|
||||
* JCClassDecl for inner types
|
||||
* JCMethodDecl for constructors and methods
|
||||
* JCVariableDecl for fields
|
||||
* JCBlock for (static) initializers
|
||||
*/
|
||||
if ( def instanceof JCMethodDecl ) addIfNotNull(childNodes, buildMethod((JCMethodDecl)def));
|
||||
else if ( def instanceof JCClassDecl ) addIfNotNull(childNodes, buildType((JCClassDecl)def));
|
||||
else if ( def instanceof JCVariableDecl ) addIfNotNull(childNodes, buildField((JCVariableDecl)def));
|
||||
else if ( def instanceof JCBlock ) addIfNotNull(childNodes, buildInitializer((JCBlock)def));
|
||||
if (def instanceof JCMethodDecl) addIfNotNull(childNodes, buildMethod((JCMethodDecl)def));
|
||||
else if (def instanceof JCClassDecl) addIfNotNull(childNodes, buildType((JCClassDecl)def));
|
||||
else if (def instanceof JCVariableDecl) addIfNotNull(childNodes, buildField((JCVariableDecl)def));
|
||||
else if (def instanceof JCBlock) addIfNotNull(childNodes, buildInitializer((JCBlock)def));
|
||||
}
|
||||
|
||||
return putInMap(new Node(type, childNodes, Kind.TYPE));
|
||||
return putInMap(new JavacNode(this, type, childNodes, Kind.TYPE));
|
||||
}
|
||||
|
||||
private Node buildField(JCVariableDecl field) {
|
||||
if ( setAndGetAsHandled(field) ) return null;
|
||||
List<Node> childNodes = new ArrayList<Node>();
|
||||
for ( JCAnnotation annotation : field.mods.annotations ) addIfNotNull(childNodes, buildAnnotation(annotation));
|
||||
private JavacNode buildField(JCVariableDecl field) {
|
||||
if (setAndGetAsHandled(field)) return null;
|
||||
List<JavacNode> childNodes = new ArrayList<JavacNode>();
|
||||
for (JCAnnotation annotation : field.mods.annotations) addIfNotNull(childNodes, buildAnnotation(annotation));
|
||||
addIfNotNull(childNodes, buildExpression(field.init));
|
||||
return putInMap(new Node(field, childNodes, Kind.FIELD));
|
||||
return putInMap(new JavacNode(this, field, childNodes, Kind.FIELD));
|
||||
}
|
||||
|
||||
private Node buildLocalVar(JCVariableDecl local, Kind kind) {
|
||||
if ( setAndGetAsHandled(local) ) return null;
|
||||
List<Node> childNodes = new ArrayList<Node>();
|
||||
for ( JCAnnotation annotation : local.mods.annotations ) addIfNotNull(childNodes, buildAnnotation(annotation));
|
||||
private JavacNode buildLocalVar(JCVariableDecl local, Kind kind) {
|
||||
if (setAndGetAsHandled(local)) return null;
|
||||
List<JavacNode> childNodes = new ArrayList<JavacNode>();
|
||||
for (JCAnnotation annotation : local.mods.annotations) addIfNotNull(childNodes, buildAnnotation(annotation));
|
||||
addIfNotNull(childNodes, buildExpression(local.init));
|
||||
return putInMap(new Node(local, childNodes, kind));
|
||||
return putInMap(new JavacNode(this, local, childNodes, kind));
|
||||
}
|
||||
|
||||
private Node buildInitializer(JCBlock initializer) {
|
||||
if ( setAndGetAsHandled(initializer) ) return null;
|
||||
List<Node> childNodes = new ArrayList<Node>();
|
||||
for ( JCStatement statement: initializer.stats ) addIfNotNull(childNodes, buildStatement(statement));
|
||||
return putInMap(new Node(initializer, childNodes, Kind.INITIALIZER));
|
||||
private JavacNode buildInitializer(JCBlock initializer) {
|
||||
if (setAndGetAsHandled(initializer)) return null;
|
||||
List<JavacNode> childNodes = new ArrayList<JavacNode>();
|
||||
for (JCStatement statement: initializer.stats) addIfNotNull(childNodes, buildStatement(statement));
|
||||
return putInMap(new JavacNode(this, initializer, childNodes, Kind.INITIALIZER));
|
||||
}
|
||||
|
||||
private Node buildMethod(JCMethodDecl method) {
|
||||
if ( setAndGetAsHandled(method) ) return null;
|
||||
List<Node> childNodes = new ArrayList<Node>();
|
||||
for ( JCAnnotation annotation : method.mods.annotations ) addIfNotNull(childNodes, buildAnnotation(annotation));
|
||||
for ( JCVariableDecl param : method.params ) addIfNotNull(childNodes, buildLocalVar(param, Kind.ARGUMENT));
|
||||
if ( method.body != null && method.body.stats != null )
|
||||
for ( JCStatement statement : method.body.stats ) addIfNotNull(childNodes, buildStatement(statement));
|
||||
return putInMap(new Node(method, childNodes, Kind.METHOD));
|
||||
private JavacNode buildMethod(JCMethodDecl method) {
|
||||
if (setAndGetAsHandled(method)) return null;
|
||||
List<JavacNode> childNodes = new ArrayList<JavacNode>();
|
||||
for (JCAnnotation annotation : method.mods.annotations) addIfNotNull(childNodes, buildAnnotation(annotation));
|
||||
for (JCVariableDecl param : method.params) addIfNotNull(childNodes, buildLocalVar(param, Kind.ARGUMENT));
|
||||
if (method.body != null && method.body.stats != null) {
|
||||
for (JCStatement statement : method.body.stats) addIfNotNull(childNodes, buildStatement(statement));
|
||||
}
|
||||
return putInMap(new JavacNode(this, method, childNodes, Kind.METHOD));
|
||||
}
|
||||
|
||||
private Node buildAnnotation(JCAnnotation annotation) {
|
||||
if ( setAndGetAsHandled(annotation) ) return null;
|
||||
return putInMap(new Node(annotation, null, Kind.ANNOTATION));
|
||||
private JavacNode buildAnnotation(JCAnnotation annotation) {
|
||||
if (setAndGetAsHandled(annotation)) return null;
|
||||
return putInMap(new JavacNode(this, annotation, null, Kind.ANNOTATION));
|
||||
}
|
||||
|
||||
private Node buildExpression(JCExpression expression) {
|
||||
private JavacNode buildExpression(JCExpression expression) {
|
||||
return buildStatementOrExpression(expression);
|
||||
}
|
||||
|
||||
private Node buildStatement(JCStatement statement) {
|
||||
private JavacNode buildStatement(JCStatement statement) {
|
||||
return buildStatementOrExpression(statement);
|
||||
}
|
||||
|
||||
private Node buildStatementOrExpression(JCTree statement) {
|
||||
if ( statement == null ) return null;
|
||||
if ( statement instanceof JCAnnotation ) return null;
|
||||
if ( statement instanceof JCClassDecl ) return buildType((JCClassDecl)statement);
|
||||
if ( statement instanceof JCVariableDecl ) return buildLocalVar((JCVariableDecl)statement, Kind.LOCAL);
|
||||
private JavacNode buildStatementOrExpression(JCTree statement) {
|
||||
if (statement == null) return null;
|
||||
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 ( setAndGetAsHandled(statement) ) return null;
|
||||
if (setAndGetAsHandled(statement)) return null;
|
||||
|
||||
return drill(statement);
|
||||
}
|
||||
|
||||
private Node drill(JCTree statement) {
|
||||
List<Node> childNodes = new ArrayList<Node>();
|
||||
for ( FieldAccess fa : fieldsOf(statement.getClass()) ) childNodes.addAll(buildWithField(Node.class, statement, fa));
|
||||
return putInMap(new Node(statement, childNodes, Kind.STATEMENT));
|
||||
private JavacNode drill(JCTree statement) {
|
||||
List<JavacNode> childNodes = new ArrayList<JavacNode>();
|
||||
for (FieldAccess fa : fieldsOf(statement.getClass())) childNodes.addAll(buildWithField(JavacNode.class, statement, fa));
|
||||
return putInMap(new JavacNode(this, statement, childNodes, Kind.STATEMENT));
|
||||
}
|
||||
|
||||
/** For javac, both JCExpression and JCStatement are considered as valid children types. */
|
||||
@@ -267,200 +258,12 @@ public class JavacAST extends AST<JCTree> {
|
||||
return collection;
|
||||
}
|
||||
|
||||
private static void addIfNotNull(Collection<Node> nodes, Node node) {
|
||||
if ( node != null ) nodes.add(node);
|
||||
}
|
||||
|
||||
/**
|
||||
* Javac specific version of the AST.Node class.
|
||||
*/
|
||||
public class Node extends AST<JCTree>.Node {
|
||||
/**
|
||||
* See the {@link AST.Node} constructor for information.
|
||||
*/
|
||||
public Node(JCTree node, List<Node> children, Kind kind) {
|
||||
super(node, children, kind);
|
||||
}
|
||||
|
||||
/**
|
||||
* Visits this node and all child nodes depth-first, calling the provided visitor's visit methods.
|
||||
*/
|
||||
public void traverse(JavacASTVisitor visitor) {
|
||||
switch ( this.getKind() ) {
|
||||
case COMPILATION_UNIT:
|
||||
visitor.visitCompilationUnit(this, (JCCompilationUnit)get());
|
||||
traverseChildren(visitor, this);
|
||||
visitor.endVisitCompilationUnit(this, (JCCompilationUnit)get());
|
||||
break;
|
||||
case TYPE:
|
||||
visitor.visitType(this, (JCClassDecl)get());
|
||||
traverseChildren(visitor, this);
|
||||
visitor.endVisitType(this, (JCClassDecl)get());
|
||||
break;
|
||||
case FIELD:
|
||||
visitor.visitField(this, (JCVariableDecl)get());
|
||||
traverseChildren(visitor, this);
|
||||
visitor.endVisitField(this, (JCVariableDecl)get());
|
||||
break;
|
||||
case METHOD:
|
||||
visitor.visitMethod(this, (JCMethodDecl)get());
|
||||
traverseChildren(visitor, this);
|
||||
visitor.endVisitMethod(this, (JCMethodDecl)get());
|
||||
break;
|
||||
case INITIALIZER:
|
||||
visitor.visitInitializer(this, (JCBlock)get());
|
||||
traverseChildren(visitor, this);
|
||||
visitor.endVisitInitializer(this, (JCBlock)get());
|
||||
break;
|
||||
case ARGUMENT:
|
||||
JCMethodDecl parent = (JCMethodDecl) up().get();
|
||||
visitor.visitMethodArgument(this, (JCVariableDecl)get(), parent);
|
||||
traverseChildren(visitor, this);
|
||||
visitor.endVisitMethodArgument(this, (JCVariableDecl)get(), parent);
|
||||
break;
|
||||
case LOCAL:
|
||||
visitor.visitLocal(this, (JCVariableDecl)get());
|
||||
traverseChildren(visitor, this);
|
||||
visitor.endVisitLocal(this, (JCVariableDecl)get());
|
||||
break;
|
||||
case STATEMENT:
|
||||
visitor.visitStatement(this, get());
|
||||
traverseChildren(visitor, this);
|
||||
visitor.endVisitStatement(this, get());
|
||||
break;
|
||||
case ANNOTATION:
|
||||
switch ( up().getKind() ) {
|
||||
case TYPE:
|
||||
visitor.visitAnnotationOnType((JCClassDecl)up().get(), this, (JCAnnotation)get());
|
||||
break;
|
||||
case FIELD:
|
||||
visitor.visitAnnotationOnField((JCVariableDecl)up().get(), this, (JCAnnotation)get());
|
||||
break;
|
||||
case METHOD:
|
||||
visitor.visitAnnotationOnMethod((JCMethodDecl)up().get(), this, (JCAnnotation)get());
|
||||
break;
|
||||
case ARGUMENT:
|
||||
JCVariableDecl argument = (JCVariableDecl)up().get();
|
||||
JCMethodDecl method = (JCMethodDecl)up().up().get();
|
||||
visitor.visitAnnotationOnMethodArgument(argument, method, this, (JCAnnotation)get());
|
||||
break;
|
||||
case LOCAL:
|
||||
visitor.visitAnnotationOnLocal((JCVariableDecl)up().get(), this, (JCAnnotation)get());
|
||||
break;
|
||||
default:
|
||||
throw new AssertionError("Annotion not expected as child of a " + up().getKind());
|
||||
}
|
||||
break;
|
||||
default:
|
||||
throw new AssertionError("Unexpected kind during node traversal: " + getKind());
|
||||
}
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override public String getName() {
|
||||
final Name n;
|
||||
|
||||
if ( node instanceof JCClassDecl ) n = ((JCClassDecl)node).name;
|
||||
else if ( node instanceof JCMethodDecl ) n = ((JCMethodDecl)node).name;
|
||||
else if ( node instanceof JCVariableDecl ) n = ((JCVariableDecl)node).name;
|
||||
else n = null;
|
||||
|
||||
return n == null ? null : n.toString();
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override protected boolean calculateIsStructurallySignificant() {
|
||||
if ( node instanceof JCClassDecl ) return true;
|
||||
if ( node instanceof JCMethodDecl ) return true;
|
||||
if ( node instanceof JCVariableDecl ) return true;
|
||||
if ( node instanceof JCCompilationUnit ) return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convenient shortcut to the owning JavacAST object's getTreeMaker method.
|
||||
*
|
||||
* @see JavacAST#getTreeMaker()
|
||||
*/
|
||||
public TreeMaker getTreeMaker() {
|
||||
return treeMaker;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convenient shortcut to the owning JavacAST object's getSymbolTable method.
|
||||
*
|
||||
* @see JavacAST#getSymbolTable()
|
||||
*/
|
||||
public Symtab getSymbolTable() {
|
||||
return symtab;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convenient shortcut to the owning JavacAST object's toName method.
|
||||
*
|
||||
* @see JavacAST#toName(String)
|
||||
*/
|
||||
public Name toName(String name) {
|
||||
return JavacAST.this.toName(name);
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override public Node getNodeFor(JCTree obj) {
|
||||
return (Node) super.getNodeFor(obj);
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override public Node directUp() {
|
||||
return (Node) super.directUp();
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override public Node up() {
|
||||
return (Node) super.up();
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override public Node top() {
|
||||
return (Node) super.top();
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override public Collection<Node> down() {
|
||||
return (Collection<Node>) super.down();
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates an compiler error focused on the AST node represented by this node object.
|
||||
*/
|
||||
public void addError(String message) {
|
||||
printMessage(Diagnostic.Kind.ERROR, message, this, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates an compiler error focused on the AST node represented by this node object.
|
||||
*/
|
||||
public void addError(String message, DiagnosticPosition pos) {
|
||||
printMessage(Diagnostic.Kind.ERROR, message, null, pos);
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates a compiler warning focused on the AST node represented by this node object.
|
||||
*/
|
||||
public void addWarning(String message) {
|
||||
printMessage(Diagnostic.Kind.WARNING, message, this, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates a compiler warning focused on the AST node represented by this node object.
|
||||
*/
|
||||
public void addWarning(String message, DiagnosticPosition pos) {
|
||||
printMessage(Diagnostic.Kind.WARNING, message, null, pos);
|
||||
}
|
||||
private static void addIfNotNull(Collection<JavacNode> nodes, JavacNode node) {
|
||||
if (node != null) nodes.add(node);
|
||||
}
|
||||
|
||||
/** Supply either a position or a node (in that case, position of the node is used) */
|
||||
private void printMessage(Diagnostic.Kind kind, String message, Node node, DiagnosticPosition pos) {
|
||||
void printMessage(Diagnostic.Kind kind, String message, JavacNode node, DiagnosticPosition pos) {
|
||||
JavaFileObject oldSource = null;
|
||||
JavaFileObject newSource = null;
|
||||
JCTree astObject = node == null ? null : node.get();
|
||||
@@ -468,7 +271,7 @@ public class JavacAST extends AST<JCTree> {
|
||||
newSource = top.sourcefile;
|
||||
if (newSource != null) {
|
||||
oldSource = log.useSource(newSource);
|
||||
if ( pos == null ) pos = astObject.pos();
|
||||
if (pos == null) pos = astObject.pos();
|
||||
}
|
||||
try {
|
||||
switch (kind) {
|
||||
@@ -488,22 +291,20 @@ public class JavacAST extends AST<JCTree> {
|
||||
break;
|
||||
}
|
||||
} finally {
|
||||
if (oldSource != null)
|
||||
log.useSource(oldSource);
|
||||
if (oldSource != null) log.useSource(oldSource);
|
||||
}
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override protected void setElementInASTCollection(Field field, Object refField, List<Collection<?>> chain, Collection<?> collection, int idx, JCTree newN) throws IllegalAccessException {
|
||||
com.sun.tools.javac.util.List<?> list = setElementInConsList(chain, collection, ((List)collection).get(idx), newN);
|
||||
com.sun.tools.javac.util.List<?> list = setElementInConsList(chain, collection, ((List<?>)collection).get(idx), newN);
|
||||
field.set(refField, list);
|
||||
}
|
||||
|
||||
private com.sun.tools.javac.util.List<?> setElementInConsList(List<Collection<?>> chain, Collection<?> current, Object oldO, Object newO) {
|
||||
com.sun.tools.javac.util.List<?> oldL = (com.sun.tools.javac.util.List<?>) current;
|
||||
com.sun.tools.javac.util.List<?> newL = replaceInConsList(oldL, oldO, newO);
|
||||
if ( chain.isEmpty() ) return newL;
|
||||
if (chain.isEmpty()) return newL;
|
||||
else {
|
||||
List<Collection<?>> reducedChain = new ArrayList<Collection<?>>(chain);
|
||||
Collection<?> newCurrent = reducedChain.remove(reducedChain.size() -1);
|
||||
@@ -514,14 +315,14 @@ public class JavacAST extends AST<JCTree> {
|
||||
private com.sun.tools.javac.util.List<?> replaceInConsList(com.sun.tools.javac.util.List<?> oldL, Object oldO, Object newO) {
|
||||
boolean repl = false;
|
||||
Object[] a = oldL.toArray();
|
||||
for ( int i = 0 ; i < a.length ; i++ ) {
|
||||
if ( a[i] == oldO ) {
|
||||
for (int i = 0; i < a.length; i++) {
|
||||
if (a[i] == oldO) {
|
||||
a[i] = newO;
|
||||
repl = true;
|
||||
}
|
||||
}
|
||||
|
||||
if ( repl ) return com.sun.tools.javac.util.List.<Object>from(a);
|
||||
if (repl) return com.sun.tools.javac.util.List.<Object>from(a);
|
||||
else return oldL;
|
||||
}
|
||||
|
||||
@@ -529,11 +330,11 @@ public class JavacAST extends AST<JCTree> {
|
||||
try {
|
||||
Field f = messager.getClass().getDeclaredField("errorCount");
|
||||
f.setAccessible(true);
|
||||
if ( f.getType() == int.class ) {
|
||||
if (f.getType() == int.class) {
|
||||
int val = ((Number)f.get(messager)).intValue();
|
||||
f.set(messager, val +1);
|
||||
}
|
||||
} catch ( Throwable t ) {
|
||||
} catch (Throwable t) {
|
||||
//Very unfortunate, but in most cases it still works fine, so we'll silently swallow it.
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,8 +21,6 @@
|
||||
*/
|
||||
package lombok.javac;
|
||||
|
||||
import lombok.javac.JavacAST.Node;
|
||||
|
||||
import com.sun.tools.javac.tree.JCTree;
|
||||
import com.sun.tools.javac.tree.JCTree.JCAnnotation;
|
||||
import com.sun.tools.javac.tree.JCTree.JCBlock;
|
||||
@@ -37,64 +35,64 @@ import com.sun.tools.javac.tree.JCTree.JCVariableDecl;
|
||||
*/
|
||||
public class JavacASTAdapter implements JavacASTVisitor {
|
||||
/** {@inheritDoc} */
|
||||
@Override public void visitCompilationUnit(Node top, JCCompilationUnit unit) {}
|
||||
@Override public void visitCompilationUnit(JavacNode top, JCCompilationUnit unit) {}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override public void endVisitCompilationUnit(Node top, JCCompilationUnit unit) {}
|
||||
@Override public void endVisitCompilationUnit(JavacNode top, JCCompilationUnit unit) {}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override public void visitType(Node typeNode, JCClassDecl type) {}
|
||||
@Override public void visitType(JavacNode typeNode, JCClassDecl type) {}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override public void visitAnnotationOnType(JCClassDecl type, Node annotationNode, JCAnnotation annotation) {}
|
||||
@Override public void visitAnnotationOnType(JCClassDecl type, JavacNode annotationNode, JCAnnotation annotation) {}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override public void endVisitType(Node typeNode, JCClassDecl type) {}
|
||||
@Override public void endVisitType(JavacNode typeNode, JCClassDecl type) {}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override public void visitField(Node fieldNode, JCVariableDecl field) {}
|
||||
@Override public void visitField(JavacNode fieldNode, JCVariableDecl field) {}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override public void visitAnnotationOnField(JCVariableDecl field, Node annotationNode, JCAnnotation annotation) {}
|
||||
@Override public void visitAnnotationOnField(JCVariableDecl field, JavacNode annotationNode, JCAnnotation annotation) {}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override public void endVisitField(Node fieldNode, JCVariableDecl field) {}
|
||||
@Override public void endVisitField(JavacNode fieldNode, JCVariableDecl field) {}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override public void visitInitializer(Node initializerNode, JCBlock initializer) {}
|
||||
@Override public void visitInitializer(JavacNode initializerNode, JCBlock initializer) {}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override public void endVisitInitializer(Node initializerNode, JCBlock initializer) {}
|
||||
@Override public void endVisitInitializer(JavacNode initializerNode, JCBlock initializer) {}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override public void visitMethod(Node methodNode, JCMethodDecl method) {}
|
||||
@Override public void visitMethod(JavacNode methodNode, JCMethodDecl method) {}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override public void visitAnnotationOnMethod(JCMethodDecl method, Node annotationNode, JCAnnotation annotation) {}
|
||||
@Override public void visitAnnotationOnMethod(JCMethodDecl method, JavacNode annotationNode, JCAnnotation annotation) {}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override public void endVisitMethod(Node methodNode, JCMethodDecl method) {}
|
||||
@Override public void endVisitMethod(JavacNode methodNode, JCMethodDecl method) {}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override public void visitMethodArgument(Node argumentNode, JCVariableDecl argument, JCMethodDecl method) {}
|
||||
@Override public void visitMethodArgument(JavacNode argumentNode, JCVariableDecl argument, JCMethodDecl method) {}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override public void visitAnnotationOnMethodArgument(JCVariableDecl argument, JCMethodDecl method, Node annotationNode, JCAnnotation annotation) {}
|
||||
@Override public void visitAnnotationOnMethodArgument(JCVariableDecl argument, JCMethodDecl method, JavacNode annotationNode, JCAnnotation annotation) {}
|
||||
/** {@inheritDoc} */
|
||||
@Override public void endVisitMethodArgument(Node argumentNode, JCVariableDecl argument, JCMethodDecl method) {}
|
||||
@Override public void endVisitMethodArgument(JavacNode argumentNode, JCVariableDecl argument, JCMethodDecl method) {}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override public void visitLocal(Node localNode, JCVariableDecl local) {}
|
||||
@Override public void visitLocal(JavacNode localNode, JCVariableDecl local) {}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override public void visitAnnotationOnLocal(JCVariableDecl local, Node annotationNode, JCAnnotation annotation) {}
|
||||
@Override public void visitAnnotationOnLocal(JCVariableDecl local, JavacNode annotationNode, JCAnnotation annotation) {}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override public void endVisitLocal(Node localNode, JCVariableDecl local) {}
|
||||
@Override public void endVisitLocal(JavacNode localNode, JCVariableDecl local) {}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override public void visitStatement(Node statementNode, JCTree statement) {}
|
||||
@Override public void visitStatement(JavacNode statementNode, JCTree statement) {}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override public void endVisitStatement(Node statementNode, JCTree statement) {}
|
||||
@Override public void endVisitStatement(JavacNode statementNode, JCTree statement) {}
|
||||
}
|
||||
|
||||
@@ -23,8 +23,6 @@ package lombok.javac;
|
||||
|
||||
import java.io.PrintStream;
|
||||
|
||||
import lombok.javac.JavacAST.Node;
|
||||
|
||||
import com.sun.tools.javac.code.Flags;
|
||||
import com.sun.tools.javac.tree.JCTree;
|
||||
import com.sun.tools.javac.tree.JCTree.JCAnnotation;
|
||||
@@ -35,64 +33,64 @@ import com.sun.tools.javac.tree.JCTree.JCMethodDecl;
|
||||
import com.sun.tools.javac.tree.JCTree.JCVariableDecl;
|
||||
|
||||
/**
|
||||
* Implement so you can ask any JavacAST.Node to traverse depth-first through all children,
|
||||
* Implement so you can ask any JavacAST.LombokNode to traverse depth-first through all children,
|
||||
* calling the appropriate visit and endVisit methods.
|
||||
*/
|
||||
public interface JavacASTVisitor {
|
||||
/**
|
||||
* Called at the very beginning and end.
|
||||
*/
|
||||
void visitCompilationUnit(Node top, JCCompilationUnit unit);
|
||||
void endVisitCompilationUnit(Node top, JCCompilationUnit unit);
|
||||
void visitCompilationUnit(JavacNode top, JCCompilationUnit unit);
|
||||
void endVisitCompilationUnit(JavacNode top, JCCompilationUnit unit);
|
||||
|
||||
/**
|
||||
* Called when visiting a type (a class, interface, annotation, enum, etcetera).
|
||||
*/
|
||||
void visitType(Node typeNode, JCClassDecl type);
|
||||
void visitAnnotationOnType(JCClassDecl type, Node annotationNode, JCAnnotation annotation);
|
||||
void endVisitType(Node typeNode, JCClassDecl type);
|
||||
void visitType(JavacNode typeNode, JCClassDecl type);
|
||||
void visitAnnotationOnType(JCClassDecl type, JavacNode annotationNode, JCAnnotation annotation);
|
||||
void endVisitType(JavacNode typeNode, JCClassDecl type);
|
||||
|
||||
/**
|
||||
* Called when visiting a field of a class.
|
||||
*/
|
||||
void visitField(Node fieldNode, JCVariableDecl field);
|
||||
void visitAnnotationOnField(JCVariableDecl field, Node annotationNode, JCAnnotation annotation);
|
||||
void endVisitField(Node fieldNode, JCVariableDecl field);
|
||||
void visitField(JavacNode fieldNode, JCVariableDecl field);
|
||||
void visitAnnotationOnField(JCVariableDecl field, JavacNode annotationNode, JCAnnotation annotation);
|
||||
void endVisitField(JavacNode fieldNode, JCVariableDecl field);
|
||||
|
||||
/**
|
||||
* Called for static and instance initializers. You can tell the difference via the isStatic() method.
|
||||
*/
|
||||
void visitInitializer(Node initializerNode, JCBlock initializer);
|
||||
void endVisitInitializer(Node initializerNode, JCBlock initializer);
|
||||
void visitInitializer(JavacNode initializerNode, JCBlock initializer);
|
||||
void endVisitInitializer(JavacNode initializerNode, JCBlock initializer);
|
||||
|
||||
/**
|
||||
* Called for both methods and constructors.
|
||||
*/
|
||||
void visitMethod(Node methodNode, JCMethodDecl method);
|
||||
void visitAnnotationOnMethod(JCMethodDecl method, Node annotationNode, JCAnnotation annotation);
|
||||
void endVisitMethod(Node methodNode, JCMethodDecl method);
|
||||
void visitMethod(JavacNode methodNode, JCMethodDecl method);
|
||||
void visitAnnotationOnMethod(JCMethodDecl method, JavacNode annotationNode, JCAnnotation annotation);
|
||||
void endVisitMethod(JavacNode methodNode, JCMethodDecl method);
|
||||
|
||||
/**
|
||||
* Visits a method argument.
|
||||
*/
|
||||
void visitMethodArgument(Node argumentNode, JCVariableDecl argument, JCMethodDecl method);
|
||||
void visitAnnotationOnMethodArgument(JCVariableDecl argument, JCMethodDecl method, Node annotationNode, JCAnnotation annotation);
|
||||
void endVisitMethodArgument(Node argumentNode, JCVariableDecl argument, JCMethodDecl method);
|
||||
void visitMethodArgument(JavacNode argumentNode, JCVariableDecl argument, JCMethodDecl method);
|
||||
void visitAnnotationOnMethodArgument(JCVariableDecl argument, JCMethodDecl method, JavacNode annotationNode, JCAnnotation annotation);
|
||||
void endVisitMethodArgument(JavacNode argumentNode, JCVariableDecl argument, JCMethodDecl method);
|
||||
|
||||
/**
|
||||
* Visits a local declaration - that is, something like 'int x = 10;' on the method level. Also called
|
||||
* for method parameters.
|
||||
*/
|
||||
void visitLocal(Node localNode, JCVariableDecl local);
|
||||
void visitAnnotationOnLocal(JCVariableDecl local, Node annotationNode, JCAnnotation annotation);
|
||||
void endVisitLocal(Node localNode, JCVariableDecl local);
|
||||
void visitLocal(JavacNode localNode, JCVariableDecl local);
|
||||
void visitAnnotationOnLocal(JCVariableDecl local, JavacNode annotationNode, JCAnnotation annotation);
|
||||
void endVisitLocal(JavacNode localNode, JCVariableDecl local);
|
||||
|
||||
/**
|
||||
* Visits a statement that isn't any of the other visit methods (e.g. JCClassDecl).
|
||||
* The statement object is guaranteed to be either a JCStatement or a JCExpression.
|
||||
*/
|
||||
void visitStatement(Node statementNode, JCTree statement);
|
||||
void endVisitStatement(Node statementNode, JCTree statement);
|
||||
void visitStatement(JavacNode statementNode, JCTree statement);
|
||||
void endVisitStatement(JavacNode statementNode, JCTree statement);
|
||||
|
||||
/**
|
||||
* Prints the structure of an AST.
|
||||
@@ -125,142 +123,142 @@ public interface JavacASTVisitor {
|
||||
|
||||
private void forcePrint(String text, Object... params) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
for ( int i = 0 ; i < indent ; i++ ) sb.append(" ");
|
||||
for (int i = 0; i < indent; i++) sb.append(" ");
|
||||
out.printf(sb.append(text).append('\n').toString(), params);
|
||||
out.flush();
|
||||
}
|
||||
|
||||
private void print(String text, Object... params) {
|
||||
if ( disablePrinting == 0 ) forcePrint(text, params);
|
||||
if (disablePrinting == 0) forcePrint(text, params);
|
||||
}
|
||||
|
||||
@Override public void visitCompilationUnit(Node Node, JCCompilationUnit unit) {
|
||||
@Override public void visitCompilationUnit(JavacNode LombokNode, JCCompilationUnit unit) {
|
||||
out.println("---------------------------------------------------------");
|
||||
|
||||
print("<CU %s>", Node.getFileName());
|
||||
print("<CU %s>", LombokNode.getFileName());
|
||||
indent++;
|
||||
}
|
||||
|
||||
@Override public void endVisitCompilationUnit(Node node, JCCompilationUnit unit) {
|
||||
@Override public void endVisitCompilationUnit(JavacNode node, JCCompilationUnit unit) {
|
||||
indent--;
|
||||
print("</CUD>");
|
||||
}
|
||||
|
||||
@Override public void visitType(Node node, JCClassDecl type) {
|
||||
@Override public void visitType(JavacNode node, JCClassDecl type) {
|
||||
print("<TYPE %s>", type.name);
|
||||
indent++;
|
||||
if ( printContent ) {
|
||||
if (printContent) {
|
||||
print("%s", type);
|
||||
disablePrinting++;
|
||||
}
|
||||
}
|
||||
|
||||
@Override public void visitAnnotationOnType(JCClassDecl type, Node node, JCAnnotation annotation) {
|
||||
@Override public void visitAnnotationOnType(JCClassDecl type, JavacNode node, JCAnnotation annotation) {
|
||||
forcePrint("<ANNOTATION: %s />", annotation);
|
||||
}
|
||||
|
||||
@Override public void endVisitType(Node node, JCClassDecl type) {
|
||||
if ( printContent ) disablePrinting--;
|
||||
@Override public void endVisitType(JavacNode node, JCClassDecl type) {
|
||||
if (printContent) disablePrinting--;
|
||||
indent--;
|
||||
print("</TYPE %s>", type.name);
|
||||
}
|
||||
|
||||
@Override public void visitInitializer(Node node, JCBlock initializer) {
|
||||
@Override public void visitInitializer(JavacNode node, JCBlock initializer) {
|
||||
print("<%s INITIALIZER>",
|
||||
initializer.isStatic() ? "static" : "instance");
|
||||
indent++;
|
||||
if ( printContent ) {
|
||||
if (printContent) {
|
||||
print("%s", initializer);
|
||||
disablePrinting++;
|
||||
}
|
||||
}
|
||||
|
||||
@Override public void endVisitInitializer(Node node, JCBlock initializer) {
|
||||
if ( printContent ) disablePrinting--;
|
||||
@Override public void endVisitInitializer(JavacNode node, JCBlock initializer) {
|
||||
if (printContent) disablePrinting--;
|
||||
indent--;
|
||||
print("</%s INITIALIZER>", initializer.isStatic() ? "static" : "instance");
|
||||
}
|
||||
|
||||
@Override public void visitField(Node node, JCVariableDecl field) {
|
||||
@Override public void visitField(JavacNode node, JCVariableDecl field) {
|
||||
print("<FIELD %s %s>", field.vartype, field.name);
|
||||
indent++;
|
||||
if ( printContent ) {
|
||||
if ( field.init != null ) print("%s", field.init);
|
||||
if (printContent) {
|
||||
if (field.init != null) print("%s", field.init);
|
||||
disablePrinting++;
|
||||
}
|
||||
}
|
||||
|
||||
@Override public void visitAnnotationOnField(JCVariableDecl field, Node node, JCAnnotation annotation) {
|
||||
@Override public void visitAnnotationOnField(JCVariableDecl field, JavacNode node, JCAnnotation annotation) {
|
||||
forcePrint("<ANNOTATION: %s />", annotation);
|
||||
}
|
||||
|
||||
@Override public void endVisitField(Node node, JCVariableDecl field) {
|
||||
if ( printContent ) disablePrinting--;
|
||||
@Override public void endVisitField(JavacNode node, JCVariableDecl field) {
|
||||
if (printContent) disablePrinting--;
|
||||
indent--;
|
||||
print("</FIELD %s %s>", field.vartype, field.name);
|
||||
}
|
||||
|
||||
@Override public void visitMethod(Node node, JCMethodDecl method) {
|
||||
@Override public void visitMethod(JavacNode node, JCMethodDecl method) {
|
||||
final String type;
|
||||
if ( method.name.contentEquals("<init>") ) {
|
||||
if ( (method.mods.flags & Flags.GENERATEDCONSTR) != 0 ) {
|
||||
if (method.name.contentEquals("<init>")) {
|
||||
if ((method.mods.flags & Flags.GENERATEDCONSTR) != 0) {
|
||||
type = "DEFAULTCONSTRUCTOR";
|
||||
} else type = "CONSTRUCTOR";
|
||||
} else type = "METHOD";
|
||||
print("<%s %s> returns: %s", type, method.name, method.restype);
|
||||
indent++;
|
||||
if ( printContent ) {
|
||||
if ( method.body == null ) print("(ABSTRACT)");
|
||||
if (printContent) {
|
||||
if (method.body == null) print("(ABSTRACT)");
|
||||
else print("%s", method.body);
|
||||
disablePrinting++;
|
||||
}
|
||||
}
|
||||
|
||||
@Override public void visitAnnotationOnMethod(JCMethodDecl method, Node node, JCAnnotation annotation) {
|
||||
@Override public void visitAnnotationOnMethod(JCMethodDecl method, JavacNode node, JCAnnotation annotation) {
|
||||
forcePrint("<ANNOTATION: %s />", annotation);
|
||||
}
|
||||
|
||||
@Override public void endVisitMethod(Node node, JCMethodDecl method) {
|
||||
if ( printContent ) disablePrinting--;
|
||||
@Override public void endVisitMethod(JavacNode node, JCMethodDecl method) {
|
||||
if (printContent) disablePrinting--;
|
||||
indent--;
|
||||
print("</%s %s>", "XMETHOD", method.name);
|
||||
}
|
||||
|
||||
@Override public void visitMethodArgument(Node node, JCVariableDecl arg, JCMethodDecl method) {
|
||||
@Override public void visitMethodArgument(JavacNode node, JCVariableDecl arg, JCMethodDecl method) {
|
||||
print("<METHODARG %s %s>", arg.vartype, arg.name);
|
||||
indent++;
|
||||
}
|
||||
|
||||
@Override public void visitAnnotationOnMethodArgument(JCVariableDecl arg, JCMethodDecl method, Node nodeAnnotation, JCAnnotation annotation) {
|
||||
@Override public void visitAnnotationOnMethodArgument(JCVariableDecl arg, JCMethodDecl method, JavacNode nodeAnnotation, JCAnnotation annotation) {
|
||||
forcePrint("<ANNOTATION: %s />", annotation);
|
||||
}
|
||||
|
||||
@Override public void endVisitMethodArgument(Node node, JCVariableDecl arg, JCMethodDecl method) {
|
||||
@Override public void endVisitMethodArgument(JavacNode node, JCVariableDecl arg, JCMethodDecl method) {
|
||||
indent--;
|
||||
print("</METHODARG %s %s>", arg.vartype, arg.name);
|
||||
}
|
||||
|
||||
@Override public void visitLocal(Node node, JCVariableDecl local) {
|
||||
@Override public void visitLocal(JavacNode node, JCVariableDecl local) {
|
||||
print("<LOCAL %s %s>", local.vartype, local.name);
|
||||
indent++;
|
||||
}
|
||||
|
||||
@Override public void visitAnnotationOnLocal(JCVariableDecl local, Node node, JCAnnotation annotation) {
|
||||
@Override public void visitAnnotationOnLocal(JCVariableDecl local, JavacNode node, JCAnnotation annotation) {
|
||||
print("<ANNOTATION: %s />", annotation);
|
||||
}
|
||||
|
||||
@Override public void endVisitLocal(Node node, JCVariableDecl local) {
|
||||
@Override public void endVisitLocal(JavacNode node, JCVariableDecl local) {
|
||||
indent--;
|
||||
print("</LOCAL %s %s>", local.vartype, local.name);
|
||||
}
|
||||
|
||||
@Override public void visitStatement(Node node, JCTree statement) {
|
||||
@Override public void visitStatement(JavacNode node, JCTree statement) {
|
||||
print("<%s>", statement.getClass());
|
||||
indent++;
|
||||
print("%s", statement);
|
||||
}
|
||||
|
||||
@Override public void endVisitStatement(Node node, JCTree statement) {
|
||||
@Override public void endVisitStatement(JavacNode node, JCTree statement) {
|
||||
indent--;
|
||||
print("</%s>", statement.getClass());
|
||||
}
|
||||
|
||||
@@ -54,5 +54,5 @@ public interface JavacAnnotationHandler<T extends Annotation> {
|
||||
* @return <code>true</code> if you don't want to be called again about this annotation during this
|
||||
* compile session (you've handled it), or <code>false</code> to indicate you aren't done yet.
|
||||
*/
|
||||
boolean handle(AnnotationValues<T> annotation, JCAnnotation ast, JavacAST.Node annotationNode);
|
||||
boolean handle(AnnotationValues<T> annotation, JCAnnotation ast, JavacNode annotationNode);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,200 @@
|
||||
/*
|
||||
* Copyright © 2009 Reinier Zwitserloot and Roel Spilker.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
package lombok.javac;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import javax.tools.Diagnostic;
|
||||
|
||||
import lombok.core.AST.Kind;
|
||||
|
||||
import com.sun.tools.javac.code.Symtab;
|
||||
import com.sun.tools.javac.tree.JCTree;
|
||||
import com.sun.tools.javac.tree.TreeMaker;
|
||||
import com.sun.tools.javac.tree.JCTree.JCAnnotation;
|
||||
import com.sun.tools.javac.tree.JCTree.JCBlock;
|
||||
import com.sun.tools.javac.tree.JCTree.JCClassDecl;
|
||||
import com.sun.tools.javac.tree.JCTree.JCCompilationUnit;
|
||||
import com.sun.tools.javac.tree.JCTree.JCMethodDecl;
|
||||
import com.sun.tools.javac.tree.JCTree.JCVariableDecl;
|
||||
import com.sun.tools.javac.util.Name;
|
||||
import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition;
|
||||
|
||||
/**
|
||||
* Javac specific version of the LombokNode class.
|
||||
*/
|
||||
public class JavacNode extends lombok.core.LombokNode<JavacAST, JavacNode, JCTree> {
|
||||
/** {@inheritDoc} */
|
||||
public JavacNode(JavacAST ast, JCTree node, List<JavacNode> children, Kind kind) {
|
||||
super(ast, node, children, kind);
|
||||
}
|
||||
|
||||
/**
|
||||
* Visits this node and all child nodes depth-first, calling the provided visitor's visit methods.
|
||||
*/
|
||||
public void traverse(JavacASTVisitor visitor) {
|
||||
switch (this.getKind()) {
|
||||
case COMPILATION_UNIT:
|
||||
visitor.visitCompilationUnit(this, (JCCompilationUnit)get());
|
||||
ast.traverseChildren(visitor, this);
|
||||
visitor.endVisitCompilationUnit(this, (JCCompilationUnit)get());
|
||||
break;
|
||||
case TYPE:
|
||||
visitor.visitType(this, (JCClassDecl)get());
|
||||
ast.traverseChildren(visitor, this);
|
||||
visitor.endVisitType(this, (JCClassDecl)get());
|
||||
break;
|
||||
case FIELD:
|
||||
visitor.visitField(this, (JCVariableDecl)get());
|
||||
ast.traverseChildren(visitor, this);
|
||||
visitor.endVisitField(this, (JCVariableDecl)get());
|
||||
break;
|
||||
case METHOD:
|
||||
visitor.visitMethod(this, (JCMethodDecl)get());
|
||||
ast.traverseChildren(visitor, this);
|
||||
visitor.endVisitMethod(this, (JCMethodDecl)get());
|
||||
break;
|
||||
case INITIALIZER:
|
||||
visitor.visitInitializer(this, (JCBlock)get());
|
||||
ast.traverseChildren(visitor, this);
|
||||
visitor.endVisitInitializer(this, (JCBlock)get());
|
||||
break;
|
||||
case ARGUMENT:
|
||||
JCMethodDecl parent = (JCMethodDecl) up().get();
|
||||
visitor.visitMethodArgument(this, (JCVariableDecl)get(), parent);
|
||||
ast.traverseChildren(visitor, this);
|
||||
visitor.endVisitMethodArgument(this, (JCVariableDecl)get(), parent);
|
||||
break;
|
||||
case LOCAL:
|
||||
visitor.visitLocal(this, (JCVariableDecl)get());
|
||||
ast.traverseChildren(visitor, this);
|
||||
visitor.endVisitLocal(this, (JCVariableDecl)get());
|
||||
break;
|
||||
case STATEMENT:
|
||||
visitor.visitStatement(this, get());
|
||||
ast.traverseChildren(visitor, this);
|
||||
visitor.endVisitStatement(this, get());
|
||||
break;
|
||||
case ANNOTATION:
|
||||
switch (up().getKind()) {
|
||||
case TYPE:
|
||||
visitor.visitAnnotationOnType((JCClassDecl)up().get(), this, (JCAnnotation)get());
|
||||
break;
|
||||
case FIELD:
|
||||
visitor.visitAnnotationOnField((JCVariableDecl)up().get(), this, (JCAnnotation)get());
|
||||
break;
|
||||
case METHOD:
|
||||
visitor.visitAnnotationOnMethod((JCMethodDecl)up().get(), this, (JCAnnotation)get());
|
||||
break;
|
||||
case ARGUMENT:
|
||||
JCVariableDecl argument = (JCVariableDecl)up().get();
|
||||
JCMethodDecl method = (JCMethodDecl)up().up().get();
|
||||
visitor.visitAnnotationOnMethodArgument(argument, method, this, (JCAnnotation)get());
|
||||
break;
|
||||
case LOCAL:
|
||||
visitor.visitAnnotationOnLocal((JCVariableDecl)up().get(), this, (JCAnnotation)get());
|
||||
break;
|
||||
default:
|
||||
throw new AssertionError("Annotion not expected as child of a " + up().getKind());
|
||||
}
|
||||
break;
|
||||
default:
|
||||
throw new AssertionError("Unexpected kind during node traversal: " + getKind());
|
||||
}
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override public String getName() {
|
||||
final Name n;
|
||||
|
||||
if (node instanceof JCClassDecl) n = ((JCClassDecl)node).name;
|
||||
else if (node instanceof JCMethodDecl) n = ((JCMethodDecl)node).name;
|
||||
else if (node instanceof JCVariableDecl) n = ((JCVariableDecl)node).name;
|
||||
else n = null;
|
||||
|
||||
return n == null ? null : n.toString();
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override protected boolean calculateIsStructurallySignificant() {
|
||||
if (node instanceof JCClassDecl) return true;
|
||||
if (node instanceof JCMethodDecl) return true;
|
||||
if (node instanceof JCVariableDecl) return true;
|
||||
if (node instanceof JCCompilationUnit) return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convenient shortcut to the owning JavacAST object's getTreeMaker method.
|
||||
*
|
||||
* @see JavacAST#getTreeMaker()
|
||||
*/
|
||||
public TreeMaker getTreeMaker() {
|
||||
return ast.getTreeMaker();
|
||||
}
|
||||
|
||||
/**
|
||||
* Convenient shortcut to the owning JavacAST object's getSymbolTable method.
|
||||
*
|
||||
* @see JavacAST#getSymbolTable()
|
||||
*/
|
||||
public Symtab getSymbolTable() {
|
||||
return ast.getSymbolTable();
|
||||
}
|
||||
|
||||
/**
|
||||
* Convenient shortcut to the owning JavacAST object's toName method.
|
||||
*
|
||||
* @see JavacAST#toName(String)
|
||||
*/
|
||||
public Name toName(String name) {
|
||||
return ast.toName(name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates an compiler error focused on the AST node represented by this node object.
|
||||
*/
|
||||
public void addError(String message) {
|
||||
ast.printMessage(Diagnostic.Kind.ERROR, message, this, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates an compiler error focused on the AST node represented by this node object.
|
||||
*/
|
||||
public void addError(String message, DiagnosticPosition pos) {
|
||||
ast.printMessage(Diagnostic.Kind.ERROR, message, null, pos);
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates a compiler warning focused on the AST node represented by this node object.
|
||||
*/
|
||||
public void addWarning(String message) {
|
||||
ast.printMessage(Diagnostic.Kind.WARNING, message, this, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates a compiler warning focused on the AST node represented by this node object.
|
||||
*/
|
||||
public void addWarning(String message, DiagnosticPosition pos) {
|
||||
ast.printMessage(Diagnostic.Kind.WARNING, message, null, pos);
|
||||
}
|
||||
}
|
||||
@@ -39,7 +39,7 @@ import javax.tools.Diagnostic.Kind;
|
||||
import lombok.javac.HandlerLibrary;
|
||||
import lombok.javac.JavacAST;
|
||||
import lombok.javac.JavacASTAdapter;
|
||||
import lombok.javac.JavacAST.Node;
|
||||
import lombok.javac.JavacNode;
|
||||
|
||||
import com.sun.source.util.TreePath;
|
||||
import com.sun.source.util.Trees;
|
||||
@@ -71,7 +71,7 @@ public class Processor extends AbstractProcessor {
|
||||
/** {@inheritDoc} */
|
||||
@Override public void init(ProcessingEnvironment processingEnv) {
|
||||
super.init(processingEnv);
|
||||
if ( !(processingEnv instanceof JavacProcessingEnvironment) ) {
|
||||
if (!(processingEnv instanceof JavacProcessingEnvironment)) {
|
||||
processingEnv.getMessager().printMessage(Kind.WARNING, "You aren't using a compiler based around javac v1.6, so lombok will not work properly.");
|
||||
this.processingEnv = null;
|
||||
} else {
|
||||
@@ -83,72 +83,71 @@ public class Processor extends AbstractProcessor {
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
|
||||
if ( processingEnv == null ) return false;
|
||||
|
||||
if (processingEnv == null) return false;
|
||||
|
||||
IdentityHashMap<JCCompilationUnit, Void> units = new IdentityHashMap<JCCompilationUnit, Void>();
|
||||
for ( Element element : roundEnv.getRootElements() ) {
|
||||
for (Element element : roundEnv.getRootElements()) {
|
||||
JCCompilationUnit unit = toUnit(element);
|
||||
if ( unit != null ) units.put(unit, null);
|
||||
if (unit != null) units.put(unit, null);
|
||||
}
|
||||
|
||||
List<JavacAST> asts = new ArrayList<JavacAST>();
|
||||
|
||||
for ( JCCompilationUnit unit : units.keySet() ) asts.add(new JavacAST(trees, processingEnv, unit));
|
||||
for (JCCompilationUnit unit : units.keySet()) asts.add(new JavacAST(trees, processingEnv, unit));
|
||||
|
||||
handlers.skipPrintAST();
|
||||
for ( JavacAST ast : asts ) {
|
||||
for (JavacAST ast : asts) {
|
||||
ast.traverse(new AnnotationVisitor());
|
||||
handlers.callASTVisitors(ast);
|
||||
}
|
||||
|
||||
handlers.skipAllButPrintAST();
|
||||
for ( JavacAST ast : asts ) {
|
||||
for (JavacAST ast : asts) {
|
||||
ast.traverse(new AnnotationVisitor());
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private class AnnotationVisitor extends JavacASTAdapter {
|
||||
@Override public void visitAnnotationOnType(JCClassDecl type, Node annotationNode, JCAnnotation annotation) {
|
||||
if ( annotationNode.isHandled() ) return;
|
||||
@Override public void visitAnnotationOnType(JCClassDecl type, JavacNode annotationNode, JCAnnotation annotation) {
|
||||
if (annotationNode.isHandled()) return;
|
||||
JCCompilationUnit top = (JCCompilationUnit) annotationNode.top().get();
|
||||
boolean handled = handlers.handleAnnotation(top, annotationNode, annotation);
|
||||
if ( handled ) annotationNode.setHandled();
|
||||
if (handled) annotationNode.setHandled();
|
||||
}
|
||||
|
||||
@Override public void visitAnnotationOnField(JCVariableDecl field, Node annotationNode, JCAnnotation annotation) {
|
||||
if ( annotationNode.isHandled() ) return;
|
||||
@Override public void visitAnnotationOnField(JCVariableDecl field, JavacNode annotationNode, JCAnnotation annotation) {
|
||||
if (annotationNode.isHandled()) return;
|
||||
JCCompilationUnit top = (JCCompilationUnit) annotationNode.top().get();
|
||||
boolean handled = handlers.handleAnnotation(top, annotationNode, annotation);
|
||||
if ( handled ) annotationNode.setHandled();
|
||||
if (handled) annotationNode.setHandled();
|
||||
}
|
||||
|
||||
@Override public void visitAnnotationOnMethod(JCMethodDecl method, Node annotationNode, JCAnnotation annotation) {
|
||||
if ( annotationNode.isHandled() ) return;
|
||||
@Override public void visitAnnotationOnMethod(JCMethodDecl method, JavacNode annotationNode, JCAnnotation annotation) {
|
||||
if (annotationNode.isHandled()) return;
|
||||
JCCompilationUnit top = (JCCompilationUnit) annotationNode.top().get();
|
||||
boolean handled = handlers.handleAnnotation(top, annotationNode, annotation);
|
||||
if ( handled ) annotationNode.setHandled();
|
||||
if (handled) annotationNode.setHandled();
|
||||
}
|
||||
|
||||
@Override public void visitAnnotationOnMethodArgument(JCVariableDecl argument, JCMethodDecl method, Node annotationNode, JCAnnotation annotation) {
|
||||
if ( annotationNode.isHandled() ) return;
|
||||
@Override public void visitAnnotationOnMethodArgument(JCVariableDecl argument, JCMethodDecl method, JavacNode annotationNode, JCAnnotation annotation) {
|
||||
if (annotationNode.isHandled()) return;
|
||||
JCCompilationUnit top = (JCCompilationUnit) annotationNode.top().get();
|
||||
boolean handled = handlers.handleAnnotation(top, annotationNode, annotation);
|
||||
if ( handled ) annotationNode.setHandled();
|
||||
if (handled) annotationNode.setHandled();
|
||||
}
|
||||
|
||||
@Override public void visitAnnotationOnLocal(JCVariableDecl local, Node annotationNode, JCAnnotation annotation) {
|
||||
if ( annotationNode.isHandled() ) return;
|
||||
@Override public void visitAnnotationOnLocal(JCVariableDecl local, JavacNode annotationNode, JCAnnotation annotation) {
|
||||
if (annotationNode.isHandled()) return;
|
||||
JCCompilationUnit top = (JCCompilationUnit) annotationNode.top().get();
|
||||
boolean handled = handlers.handleAnnotation(top, annotationNode, annotation);
|
||||
if ( handled ) annotationNode.setHandled();
|
||||
if (handled) annotationNode.setHandled();
|
||||
}
|
||||
}
|
||||
|
||||
private JCCompilationUnit toUnit(Element element) {
|
||||
TreePath path = trees == null ? null : trees.getPath(element);
|
||||
if ( path == null ) return null;
|
||||
if (path == null) return null;
|
||||
|
||||
return (JCCompilationUnit) path.getCompilationUnit();
|
||||
}
|
||||
|
||||
@@ -25,7 +25,7 @@ import lombok.Cleanup;
|
||||
import lombok.core.AnnotationValues;
|
||||
import lombok.core.AST.Kind;
|
||||
import lombok.javac.JavacAnnotationHandler;
|
||||
import lombok.javac.JavacAST.Node;
|
||||
import lombok.javac.JavacNode;
|
||||
|
||||
import org.mangosdk.spi.ProviderFor;
|
||||
|
||||
@@ -52,34 +52,34 @@ import com.sun.tools.javac.util.Name;
|
||||
*/
|
||||
@ProviderFor(JavacAnnotationHandler.class)
|
||||
public class HandleCleanup implements JavacAnnotationHandler<Cleanup> {
|
||||
@Override public boolean handle(AnnotationValues<Cleanup> annotation, JCAnnotation ast, Node annotationNode) {
|
||||
@Override public boolean handle(AnnotationValues<Cleanup> annotation, JCAnnotation ast, JavacNode annotationNode) {
|
||||
String cleanupName = annotation.getInstance().value();
|
||||
if ( cleanupName.length() == 0 ) {
|
||||
if (cleanupName.length() == 0) {
|
||||
annotationNode.addError("cleanupName cannot be the empty string.");
|
||||
return true;
|
||||
}
|
||||
|
||||
if ( annotationNode.up().getKind() != Kind.LOCAL ) {
|
||||
if (annotationNode.up().getKind() != Kind.LOCAL) {
|
||||
annotationNode.addError("@Cleanup is legal only on local variable declarations.");
|
||||
return true;
|
||||
}
|
||||
|
||||
JCVariableDecl decl = (JCVariableDecl)annotationNode.up().get();
|
||||
|
||||
if ( decl.init == null ) {
|
||||
if (decl.init == null) {
|
||||
annotationNode.addError("@Cleanup variable declarations need to be initialized.");
|
||||
return true;
|
||||
}
|
||||
|
||||
Node ancestor = annotationNode.up().directUp();
|
||||
JavacNode ancestor = annotationNode.up().directUp();
|
||||
JCTree blockNode = ancestor.get();
|
||||
|
||||
final List<JCStatement> statements;
|
||||
if ( blockNode instanceof JCBlock ) {
|
||||
if (blockNode instanceof JCBlock) {
|
||||
statements = ((JCBlock)blockNode).stats;
|
||||
} else if ( blockNode instanceof JCCase ) {
|
||||
} else if (blockNode instanceof JCCase) {
|
||||
statements = ((JCCase)blockNode).stats;
|
||||
} else if ( blockNode instanceof JCMethodDecl ) {
|
||||
} else if (blockNode instanceof JCMethodDecl) {
|
||||
statements = ((JCMethodDecl)blockNode).body.stats;
|
||||
} else {
|
||||
annotationNode.addError("@Cleanup is legal only on a local variable declaration inside a block.");
|
||||
@@ -89,14 +89,16 @@ public class HandleCleanup implements JavacAnnotationHandler<Cleanup> {
|
||||
boolean seenDeclaration = false;
|
||||
List<JCStatement> tryBlock = List.nil();
|
||||
List<JCStatement> newStatements = List.nil();
|
||||
for ( JCStatement statement : statements ) {
|
||||
if ( !seenDeclaration ) {
|
||||
if ( statement == decl ) seenDeclaration = true;
|
||||
for (JCStatement statement : statements) {
|
||||
if (!seenDeclaration) {
|
||||
if (statement == decl) seenDeclaration = true;
|
||||
newStatements = newStatements.append(statement);
|
||||
} else tryBlock = tryBlock.append(statement);
|
||||
} else {
|
||||
tryBlock = tryBlock.append(statement);
|
||||
}
|
||||
}
|
||||
|
||||
if ( !seenDeclaration ) {
|
||||
if (!seenDeclaration) {
|
||||
annotationNode.addError("LOMBOK BUG: Can't find this local variable declaration inside its parent.");
|
||||
return true;
|
||||
}
|
||||
@@ -111,11 +113,11 @@ public class HandleCleanup implements JavacAnnotationHandler<Cleanup> {
|
||||
JCBlock finalizer = maker.Block(0, finalizerBlock);
|
||||
newStatements = newStatements.append(maker.Try(maker.Block(0, tryBlock), List.<JCCatch>nil(), finalizer));
|
||||
|
||||
if ( blockNode instanceof JCBlock ) {
|
||||
if (blockNode instanceof JCBlock) {
|
||||
((JCBlock)blockNode).stats = newStatements;
|
||||
} else if ( blockNode instanceof JCCase ) {
|
||||
} else if (blockNode instanceof JCCase) {
|
||||
((JCCase)blockNode).stats = newStatements;
|
||||
} else if ( blockNode instanceof JCMethodDecl ) {
|
||||
} else if (blockNode instanceof JCMethodDecl) {
|
||||
((JCMethodDecl)blockNode).body.stats = newStatements;
|
||||
} else throw new AssertionError("Should not get here");
|
||||
|
||||
@@ -124,20 +126,20 @@ public class HandleCleanup implements JavacAnnotationHandler<Cleanup> {
|
||||
return true;
|
||||
}
|
||||
|
||||
private void doAssignmentCheck(Node node, List<JCStatement> statements, Name name) {
|
||||
for ( JCStatement statement : statements ) doAssignmentCheck0(node, statement, name);
|
||||
private void doAssignmentCheck(JavacNode node, List<JCStatement> statements, Name name) {
|
||||
for (JCStatement statement : statements) doAssignmentCheck0(node, statement, name);
|
||||
}
|
||||
|
||||
private void doAssignmentCheck0(Node node, JCTree statement, Name name) {
|
||||
if ( statement instanceof JCAssign ) doAssignmentCheck0(node, ((JCAssign)statement).rhs, name);
|
||||
if ( statement instanceof JCExpressionStatement ) doAssignmentCheck0(node,
|
||||
private void doAssignmentCheck0(JavacNode node, JCTree statement, Name name) {
|
||||
if (statement instanceof JCAssign) doAssignmentCheck0(node, ((JCAssign)statement).rhs, name);
|
||||
if (statement instanceof JCExpressionStatement) doAssignmentCheck0(node,
|
||||
((JCExpressionStatement)statement).expr, name);
|
||||
if ( statement instanceof JCVariableDecl ) doAssignmentCheck0(node, ((JCVariableDecl)statement).init, name);
|
||||
if ( statement instanceof JCTypeCast ) doAssignmentCheck0(node, ((JCTypeCast)statement).expr, name);
|
||||
if ( statement instanceof JCIdent ) {
|
||||
if ( ((JCIdent)statement).name.contentEquals(name) ) {
|
||||
Node problemNode = node.getNodeFor(statement);
|
||||
if ( problemNode != null ) problemNode.addWarning(
|
||||
if (statement instanceof JCVariableDecl) doAssignmentCheck0(node, ((JCVariableDecl)statement).init, name);
|
||||
if (statement instanceof JCTypeCast) doAssignmentCheck0(node, ((JCTypeCast)statement).expr, name);
|
||||
if (statement instanceof JCIdent) {
|
||||
if (((JCIdent)statement).name.contentEquals(name)) {
|
||||
JavacNode problemNode = node.getNodeFor(statement);
|
||||
if (problemNode != null) problemNode.addWarning(
|
||||
"You're assigning an auto-cleanup variable to something else. This is a bad idea.");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -30,7 +30,7 @@ import lombok.core.AnnotationValues;
|
||||
import lombok.core.TransformationsUtil;
|
||||
import lombok.core.AST.Kind;
|
||||
import lombok.javac.JavacAnnotationHandler;
|
||||
import lombok.javac.JavacAST.Node;
|
||||
import lombok.javac.JavacNode;
|
||||
import lombok.javac.handlers.PKG.MemberExistsResult;
|
||||
|
||||
import org.mangosdk.spi.ProviderFor;
|
||||
@@ -58,32 +58,32 @@ import com.sun.tools.javac.util.List;
|
||||
*/
|
||||
@ProviderFor(JavacAnnotationHandler.class)
|
||||
public class HandleData implements JavacAnnotationHandler<Data> {
|
||||
@Override public boolean handle(AnnotationValues<Data> annotation, JCAnnotation ast, Node annotationNode) {
|
||||
Node typeNode = annotationNode.up();
|
||||
@Override public boolean handle(AnnotationValues<Data> annotation, JCAnnotation ast, JavacNode annotationNode) {
|
||||
JavacNode typeNode = annotationNode.up();
|
||||
JCClassDecl typeDecl = null;
|
||||
if ( typeNode.get() instanceof JCClassDecl ) typeDecl = (JCClassDecl)typeNode.get();
|
||||
if (typeNode.get() instanceof JCClassDecl) typeDecl = (JCClassDecl)typeNode.get();
|
||||
long flags = typeDecl == null ? 0 : typeDecl.mods.flags;
|
||||
boolean notAClass = (flags & (Flags.INTERFACE | Flags.ENUM | Flags.ANNOTATION)) != 0;
|
||||
|
||||
if ( typeDecl == null || notAClass ) {
|
||||
if (typeDecl == null || notAClass) {
|
||||
annotationNode.addError("@Data is only supported on a class.");
|
||||
return false;
|
||||
}
|
||||
|
||||
List<Node> nodesForEquality = List.nil();
|
||||
List<Node> nodesForConstructor = List.nil();
|
||||
for ( Node child : typeNode.down() ) {
|
||||
if ( child.getKind() != Kind.FIELD ) continue;
|
||||
List<JavacNode> nodesForEquality = List.nil();
|
||||
List<JavacNode> nodesForConstructor = List.nil();
|
||||
for (JavacNode child : typeNode.down()) {
|
||||
if (child.getKind() != Kind.FIELD) continue;
|
||||
JCVariableDecl fieldDecl = (JCVariableDecl) child.get();
|
||||
long fieldFlags = fieldDecl.mods.flags;
|
||||
//Skip static fields.
|
||||
if ( (fieldFlags & Flags.STATIC) != 0 ) continue;
|
||||
if ( (fieldFlags & Flags.TRANSIENT) == 0 ) nodesForEquality = nodesForEquality.append(child);
|
||||
if ((fieldFlags & Flags.STATIC) != 0) continue;
|
||||
if ((fieldFlags & Flags.TRANSIENT) == 0) nodesForEquality = nodesForEquality.append(child);
|
||||
boolean isFinal = (fieldFlags & Flags.FINAL) != 0;
|
||||
boolean isNonNull = !findAnnotations(child, TransformationsUtil.NON_NULL_PATTERN).isEmpty();
|
||||
if ( (isFinal || isNonNull) && fieldDecl.init == null ) nodesForConstructor = nodesForConstructor.append(child);
|
||||
if ((isFinal || isNonNull) && fieldDecl.init == null) nodesForConstructor = nodesForConstructor.append(child);
|
||||
new HandleGetter().generateGetterForField(child, annotationNode.get());
|
||||
if ( !isFinal ) new HandleSetter().generateSetterForField(child, annotationNode.get());
|
||||
if (!isFinal) new HandleSetter().generateSetterForField(child, annotationNode.get());
|
||||
}
|
||||
|
||||
new HandleToString().generateToStringForType(typeNode, annotationNode);
|
||||
@@ -91,12 +91,12 @@ public class HandleData implements JavacAnnotationHandler<Data> {
|
||||
|
||||
String staticConstructorName = annotation.getInstance().staticConstructor();
|
||||
|
||||
if ( constructorExists(typeNode) == MemberExistsResult.NOT_EXISTS ) {
|
||||
if (constructorExists(typeNode) == MemberExistsResult.NOT_EXISTS) {
|
||||
JCMethodDecl constructor = createConstructor(staticConstructorName.equals(""), typeNode, nodesForConstructor);
|
||||
injectMethod(typeNode, constructor);
|
||||
}
|
||||
|
||||
if ( !staticConstructorName.isEmpty() && methodExists("of", typeNode) == MemberExistsResult.NOT_EXISTS ) {
|
||||
if (!staticConstructorName.isEmpty() && methodExists("of", typeNode) == MemberExistsResult.NOT_EXISTS) {
|
||||
JCMethodDecl staticConstructor = createStaticConstructor(staticConstructorName, typeNode, nodesForConstructor);
|
||||
injectMethod(typeNode, staticConstructor);
|
||||
}
|
||||
@@ -104,7 +104,7 @@ public class HandleData implements JavacAnnotationHandler<Data> {
|
||||
return true;
|
||||
}
|
||||
|
||||
private JCMethodDecl createConstructor(boolean isPublic, Node typeNode, List<Node> fields) {
|
||||
private JCMethodDecl createConstructor(boolean isPublic, JavacNode typeNode, List<JavacNode> fields) {
|
||||
TreeMaker maker = typeNode.getTreeMaker();
|
||||
JCClassDecl type = (JCClassDecl) typeNode.get();
|
||||
|
||||
@@ -112,7 +112,7 @@ public class HandleData implements JavacAnnotationHandler<Data> {
|
||||
List<JCStatement> assigns = List.nil();
|
||||
List<JCVariableDecl> params = List.nil();
|
||||
|
||||
for ( Node fieldNode : fields ) {
|
||||
for (JavacNode fieldNode : fields) {
|
||||
JCVariableDecl field = (JCVariableDecl) fieldNode.get();
|
||||
List<JCAnnotation> nonNulls = findAnnotations(fieldNode, TransformationsUtil.NON_NULL_PATTERN);
|
||||
List<JCAnnotation> nullables = findAnnotations(fieldNode, TransformationsUtil.NULLABLE_PATTERN);
|
||||
@@ -133,7 +133,7 @@ public class HandleData implements JavacAnnotationHandler<Data> {
|
||||
null, type.typarams, params, List.<JCExpression>nil(), maker.Block(0L, nullChecks.appendList(assigns)), null);
|
||||
}
|
||||
|
||||
private JCMethodDecl createStaticConstructor(String name, Node typeNode, List<Node> fields) {
|
||||
private JCMethodDecl createStaticConstructor(String name, JavacNode typeNode, List<JavacNode> fields) {
|
||||
TreeMaker maker = typeNode.getTreeMaker();
|
||||
JCClassDecl type = (JCClassDecl) typeNode.get();
|
||||
|
||||
@@ -147,8 +147,8 @@ public class HandleData implements JavacAnnotationHandler<Data> {
|
||||
List<JCExpression> typeArgs2 = List.nil();
|
||||
List<JCExpression> args = List.nil();
|
||||
|
||||
if ( !type.typarams.isEmpty() ) {
|
||||
for ( JCTypeParameter param : type.typarams ) {
|
||||
if (!type.typarams.isEmpty()) {
|
||||
for (JCTypeParameter param : type.typarams) {
|
||||
typeArgs1 = typeArgs1.append(maker.Ident(param.name));
|
||||
typeArgs2 = typeArgs2.append(maker.Ident(param.name));
|
||||
typeParams = typeParams.append(maker.TypeParameter(param.name, param.bounds));
|
||||
@@ -160,16 +160,18 @@ public class HandleData implements JavacAnnotationHandler<Data> {
|
||||
constructorType = maker.Ident(type.name);
|
||||
}
|
||||
|
||||
for ( Node fieldNode : fields ) {
|
||||
for (JavacNode fieldNode : fields) {
|
||||
JCVariableDecl field = (JCVariableDecl) fieldNode.get();
|
||||
JCExpression pType;
|
||||
if ( field.vartype instanceof JCIdent ) pType = maker.Ident(((JCIdent)field.vartype).name);
|
||||
else if ( field.vartype instanceof JCTypeApply ) {
|
||||
if (field.vartype instanceof JCIdent) pType = maker.Ident(((JCIdent)field.vartype).name);
|
||||
else if (field.vartype instanceof JCTypeApply) {
|
||||
JCTypeApply typeApply = (JCTypeApply) field.vartype;
|
||||
List<JCExpression> tArgs = List.nil();
|
||||
for ( JCExpression arg : typeApply.arguments ) tArgs = tArgs.append(arg);
|
||||
for (JCExpression arg : typeApply.arguments) tArgs = tArgs.append(arg);
|
||||
pType = maker.TypeApply(typeApply.clazz, tArgs);
|
||||
} else pType = field.vartype;
|
||||
} else {
|
||||
pType = field.vartype;
|
||||
}
|
||||
List<JCAnnotation> nonNulls = findAnnotations(fieldNode, TransformationsUtil.NON_NULL_PATTERN);
|
||||
List<JCAnnotation> nullables = findAnnotations(fieldNode, TransformationsUtil.NULLABLE_PATTERN);
|
||||
JCVariableDecl param = maker.VarDef(maker.Modifiers(Flags.FINAL, nonNulls.appendList(nullables)), field.name, pType, null);
|
||||
|
||||
@@ -27,7 +27,7 @@ import lombok.core.AnnotationValues;
|
||||
import lombok.core.AST.Kind;
|
||||
import lombok.javac.Javac;
|
||||
import lombok.javac.JavacAnnotationHandler;
|
||||
import lombok.javac.JavacAST.Node;
|
||||
import lombok.javac.JavacNode;
|
||||
|
||||
import org.mangosdk.spi.ProviderFor;
|
||||
|
||||
@@ -58,33 +58,33 @@ import com.sun.tools.javac.util.Name;
|
||||
*/
|
||||
@ProviderFor(JavacAnnotationHandler.class)
|
||||
public class HandleEqualsAndHashCode implements JavacAnnotationHandler<EqualsAndHashCode> {
|
||||
private void checkForBogusFieldNames(Node type, AnnotationValues<EqualsAndHashCode> annotation) {
|
||||
if ( annotation.isExplicit("exclude") ) {
|
||||
for ( int i : createListOfNonExistentFields(List.from(annotation.getInstance().exclude()), type, true, true) ) {
|
||||
private void checkForBogusFieldNames(JavacNode type, AnnotationValues<EqualsAndHashCode> annotation) {
|
||||
if (annotation.isExplicit("exclude")) {
|
||||
for (int i : createListOfNonExistentFields(List.from(annotation.getInstance().exclude()), type, true, true)) {
|
||||
annotation.setWarning("exclude", "This field does not exist, or would have been excluded anyway.", i);
|
||||
}
|
||||
}
|
||||
if ( annotation.isExplicit("of") ) {
|
||||
for ( int i : createListOfNonExistentFields(List.from(annotation.getInstance().of()), type, false, false) ) {
|
||||
if (annotation.isExplicit("of")) {
|
||||
for (int i : createListOfNonExistentFields(List.from(annotation.getInstance().of()), type, false, false)) {
|
||||
annotation.setWarning("of", "This field does not exist.", i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override public boolean handle(AnnotationValues<EqualsAndHashCode> annotation, JCAnnotation ast, Node annotationNode) {
|
||||
@Override public boolean handle(AnnotationValues<EqualsAndHashCode> annotation, JCAnnotation ast, JavacNode annotationNode) {
|
||||
EqualsAndHashCode ann = annotation.getInstance();
|
||||
List<String> excludes = List.from(ann.exclude());
|
||||
List<String> includes = List.from(ann.of());
|
||||
Node typeNode = annotationNode.up();
|
||||
JavacNode typeNode = annotationNode.up();
|
||||
|
||||
checkForBogusFieldNames(typeNode, annotation);
|
||||
|
||||
Boolean callSuper = ann.callSuper();
|
||||
if ( !annotation.isExplicit("callSuper") ) callSuper = null;
|
||||
if ( !annotation.isExplicit("exclude") ) excludes = null;
|
||||
if ( !annotation.isExplicit("of") ) includes = null;
|
||||
if (!annotation.isExplicit("callSuper")) callSuper = null;
|
||||
if (!annotation.isExplicit("exclude")) excludes = null;
|
||||
if (!annotation.isExplicit("of")) includes = null;
|
||||
|
||||
if ( excludes != null && includes != null ) {
|
||||
if (excludes != null && includes != null) {
|
||||
excludes = null;
|
||||
annotation.setWarning("exclude", "exclude and of are mutually exclusive; the 'exclude' parameter will be ignored.");
|
||||
}
|
||||
@@ -92,10 +92,10 @@ public class HandleEqualsAndHashCode implements JavacAnnotationHandler<EqualsAnd
|
||||
return generateMethods(typeNode, annotationNode, excludes, includes, callSuper, true);
|
||||
}
|
||||
|
||||
public void generateEqualsAndHashCodeForType(Node typeNode, Node errorNode) {
|
||||
for ( Node child : typeNode.down() ) {
|
||||
if ( child.getKind() == Kind.ANNOTATION ) {
|
||||
if ( Javac.annotationTypeMatches(EqualsAndHashCode.class, child) ) {
|
||||
public void generateEqualsAndHashCodeForType(JavacNode typeNode, JavacNode errorNode) {
|
||||
for (JavacNode child : typeNode.down()) {
|
||||
if (child.getKind() == Kind.ANNOTATION) {
|
||||
if (Javac.annotationTypeMatches(EqualsAndHashCode.class, child)) {
|
||||
//The annotation will make it happen, so we can skip it.
|
||||
return;
|
||||
}
|
||||
@@ -105,66 +105,66 @@ public class HandleEqualsAndHashCode implements JavacAnnotationHandler<EqualsAnd
|
||||
generateMethods(typeNode, errorNode, null, null, null, false);
|
||||
}
|
||||
|
||||
private boolean generateMethods(Node typeNode, Node errorNode, List<String> excludes, List<String> includes,
|
||||
private boolean generateMethods(JavacNode typeNode, JavacNode errorNode, List<String> excludes, List<String> includes,
|
||||
Boolean callSuper, boolean whineIfExists) {
|
||||
boolean notAClass = true;
|
||||
if ( typeNode.get() instanceof JCClassDecl ) {
|
||||
if (typeNode.get() instanceof JCClassDecl) {
|
||||
long flags = ((JCClassDecl)typeNode.get()).mods.flags;
|
||||
notAClass = (flags & (Flags.INTERFACE | Flags.ANNOTATION | Flags.ENUM)) != 0;
|
||||
}
|
||||
|
||||
if ( notAClass ) {
|
||||
if (notAClass) {
|
||||
errorNode.addError("@EqualsAndHashCode is only supported on a class.");
|
||||
return false;
|
||||
}
|
||||
|
||||
boolean isDirectDescendantOfObject = true;
|
||||
boolean implicitCallSuper = callSuper == null;
|
||||
if ( callSuper == null ) {
|
||||
if (callSuper == null) {
|
||||
try {
|
||||
callSuper = ((Boolean)EqualsAndHashCode.class.getMethod("callSuper").getDefaultValue()).booleanValue();
|
||||
} catch ( Exception ignore ) {}
|
||||
} catch (Exception ignore) {}
|
||||
}
|
||||
|
||||
JCTree extending = ((JCClassDecl)typeNode.get()).extending;
|
||||
if ( extending != null ) {
|
||||
if (extending != null) {
|
||||
String p = extending.toString();
|
||||
isDirectDescendantOfObject = p.equals("Object") || p.equals("java.lang.Object");
|
||||
}
|
||||
|
||||
if ( isDirectDescendantOfObject && callSuper ) {
|
||||
if (isDirectDescendantOfObject && callSuper) {
|
||||
errorNode.addError("Generating equals/hashCode with a supercall to java.lang.Object is pointless.");
|
||||
return true;
|
||||
}
|
||||
|
||||
if ( !isDirectDescendantOfObject && !callSuper && implicitCallSuper ) {
|
||||
if (!isDirectDescendantOfObject && !callSuper && implicitCallSuper) {
|
||||
errorNode.addWarning("Generating equals/hashCode implementation but without a call to superclass, even though this class does not extend java.lang.Object. If this is intentional, add '@EqualsAndHashCode(callSuper=false)' to your type.");
|
||||
}
|
||||
|
||||
List<Node> nodesForEquality = List.nil();
|
||||
if ( includes != null ) {
|
||||
for ( Node child : typeNode.down() ) {
|
||||
if ( child.getKind() != Kind.FIELD ) continue;
|
||||
List<JavacNode> nodesForEquality = List.nil();
|
||||
if (includes != null) {
|
||||
for (JavacNode child : typeNode.down()) {
|
||||
if (child.getKind() != Kind.FIELD) continue;
|
||||
JCVariableDecl fieldDecl = (JCVariableDecl) child.get();
|
||||
if ( includes.contains(fieldDecl.name.toString()) ) nodesForEquality = nodesForEquality.append(child);
|
||||
if (includes.contains(fieldDecl.name.toString())) nodesForEquality = nodesForEquality.append(child);
|
||||
}
|
||||
} else {
|
||||
for ( Node child : typeNode.down() ) {
|
||||
if ( child.getKind() != Kind.FIELD ) continue;
|
||||
for (JavacNode child : typeNode.down()) {
|
||||
if (child.getKind() != Kind.FIELD) continue;
|
||||
JCVariableDecl fieldDecl = (JCVariableDecl) child.get();
|
||||
//Skip static fields.
|
||||
if ( (fieldDecl.mods.flags & Flags.STATIC) != 0 ) continue;
|
||||
if ((fieldDecl.mods.flags & Flags.STATIC) != 0) continue;
|
||||
//Skip transient fields.
|
||||
if ( (fieldDecl.mods.flags & Flags.TRANSIENT) != 0 ) continue;
|
||||
if ((fieldDecl.mods.flags & Flags.TRANSIENT) != 0) continue;
|
||||
//Skip excluded fields.
|
||||
if ( excludes != null && excludes.contains(fieldDecl.name.toString()) ) continue;
|
||||
if (excludes != null && excludes.contains(fieldDecl.name.toString())) continue;
|
||||
//Skip fields that start with $
|
||||
if ( fieldDecl.name.toString().startsWith("$") ) continue;
|
||||
if (fieldDecl.name.toString().startsWith("$")) continue;
|
||||
nodesForEquality = nodesForEquality.append(child);
|
||||
}
|
||||
}
|
||||
|
||||
switch ( methodExists("hashCode", typeNode) ) {
|
||||
switch (methodExists("hashCode", typeNode)) {
|
||||
case NOT_EXISTS:
|
||||
JCMethodDecl method = createHashCode(typeNode, nodesForEquality, callSuper);
|
||||
injectMethod(typeNode, method);
|
||||
@@ -173,13 +173,13 @@ public class HandleEqualsAndHashCode implements JavacAnnotationHandler<EqualsAnd
|
||||
break;
|
||||
default:
|
||||
case EXISTS_BY_USER:
|
||||
if ( whineIfExists ) {
|
||||
if (whineIfExists) {
|
||||
errorNode.addWarning("Not generating hashCode(): A method with that name already exists");
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
switch ( methodExists("equals", typeNode) ) {
|
||||
switch (methodExists("equals", typeNode)) {
|
||||
case NOT_EXISTS:
|
||||
JCMethodDecl method = createEquals(typeNode, nodesForEquality, callSuper);
|
||||
injectMethod(typeNode, method);
|
||||
@@ -188,7 +188,7 @@ public class HandleEqualsAndHashCode implements JavacAnnotationHandler<EqualsAnd
|
||||
break;
|
||||
default:
|
||||
case EXISTS_BY_USER:
|
||||
if ( whineIfExists ) {
|
||||
if (whineIfExists) {
|
||||
errorNode.addWarning("Not generating equals(Object other): A method with that name already exists");
|
||||
}
|
||||
break;
|
||||
@@ -197,7 +197,7 @@ public class HandleEqualsAndHashCode implements JavacAnnotationHandler<EqualsAnd
|
||||
return true;
|
||||
}
|
||||
|
||||
private JCMethodDecl createHashCode(Node typeNode, List<Node> fields, boolean callSuper) {
|
||||
private JCMethodDecl createHashCode(JavacNode typeNode, List<JavacNode> fields, boolean callSuper) {
|
||||
TreeMaker maker = typeNode.getTreeMaker();
|
||||
|
||||
JCAnnotation overrideAnnotation = maker.Annotation(chainDots(maker, typeNode, "java", "lang", "Override"), List.<JCExpression>nil());
|
||||
@@ -208,9 +208,9 @@ public class HandleEqualsAndHashCode implements JavacAnnotationHandler<EqualsAnd
|
||||
Name primeName = typeNode.toName("PRIME");
|
||||
Name resultName = typeNode.toName("result");
|
||||
/* final int PRIME = 31; */ {
|
||||
if ( !fields.isEmpty() || callSuper ) {
|
||||
statements = statements.append(
|
||||
maker.VarDef(maker.Modifiers(Flags.FINAL), primeName, maker.TypeIdent(TypeTags.INT), maker.Literal(31)));
|
||||
if (!fields.isEmpty() || callSuper) {
|
||||
statements = statements.append(maker.VarDef(maker.Modifiers(Flags.FINAL),
|
||||
primeName, maker.TypeIdent(TypeTags.INT), maker.Literal(31)));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -220,7 +220,7 @@ public class HandleEqualsAndHashCode implements JavacAnnotationHandler<EqualsAnd
|
||||
|
||||
List<JCExpression> intoResult = List.nil();
|
||||
|
||||
if ( callSuper ) {
|
||||
if (callSuper) {
|
||||
JCMethodInvocation callToSuper = maker.Apply(List.<JCExpression>nil(),
|
||||
maker.Select(maker.Ident(typeNode.toName("super")), typeNode.toName("hashCode")),
|
||||
List.<JCExpression>nil());
|
||||
@@ -228,13 +228,13 @@ public class HandleEqualsAndHashCode implements JavacAnnotationHandler<EqualsAnd
|
||||
}
|
||||
|
||||
int tempCounter = 0;
|
||||
for ( Node fieldNode : fields ) {
|
||||
for (JavacNode fieldNode : fields) {
|
||||
JCVariableDecl field = (JCVariableDecl) fieldNode.get();
|
||||
JCExpression fType = field.vartype;
|
||||
JCExpression thisDotField = maker.Select(maker.Ident(typeNode.toName("this")), field.name);
|
||||
JCExpression thisDotFieldClone = maker.Select(maker.Ident(typeNode.toName("this")), field.name);
|
||||
if ( fType instanceof JCPrimitiveTypeTree ) {
|
||||
switch ( ((JCPrimitiveTypeTree)fType).getPrimitiveTypeKind() ) {
|
||||
if (fType instanceof JCPrimitiveTypeTree) {
|
||||
switch (((JCPrimitiveTypeTree)fType).getPrimitiveTypeKind()) {
|
||||
case BOOLEAN:
|
||||
/* this.fieldName ? 1231 : 1237 */
|
||||
intoResult = intoResult.append(maker.Conditional(thisDotField, maker.Literal(1231), maker.Literal(1237)));
|
||||
@@ -269,7 +269,7 @@ public class HandleEqualsAndHashCode implements JavacAnnotationHandler<EqualsAnd
|
||||
intoResult = intoResult.append(thisDotField);
|
||||
break;
|
||||
}
|
||||
} else if ( fType instanceof JCArrayTypeTree ) {
|
||||
} else if (fType instanceof JCArrayTypeTree) {
|
||||
/* java.util.Arrays.deepHashCode(this.fieldName) //use just hashCode() for primitive arrays. */
|
||||
boolean multiDim = ((JCArrayTypeTree)fType).elemtype instanceof JCArrayTypeTree;
|
||||
boolean primitiveArray = ((JCArrayTypeTree)fType).elemtype instanceof JCPrimitiveTypeTree;
|
||||
@@ -290,7 +290,7 @@ public class HandleEqualsAndHashCode implements JavacAnnotationHandler<EqualsAnd
|
||||
|
||||
/* fold each intoResult entry into:
|
||||
result = result * PRIME + (item); */
|
||||
for ( JCExpression expr : intoResult ) {
|
||||
for (JCExpression expr : intoResult) {
|
||||
JCExpression mult = maker.Binary(JCTree.MUL, maker.Ident(resultName), maker.Ident(primeName));
|
||||
JCExpression add = maker.Binary(JCTree.PLUS, mult, expr);
|
||||
statements = statements.append(maker.Exec(maker.Assign(maker.Ident(resultName), add)));
|
||||
@@ -313,7 +313,7 @@ public class HandleEqualsAndHashCode implements JavacAnnotationHandler<EqualsAnd
|
||||
return maker.TypeCast(maker.TypeIdent(TypeTags.INT), xorBits);
|
||||
}
|
||||
|
||||
private JCMethodDecl createEquals(Node typeNode, List<Node> fields, boolean callSuper) {
|
||||
private JCMethodDecl createEquals(JavacNode typeNode, List<JavacNode> fields, boolean callSuper) {
|
||||
TreeMaker maker = typeNode.getTreeMaker();
|
||||
JCClassDecl type = (JCClassDecl) typeNode.get();
|
||||
|
||||
@@ -329,17 +329,17 @@ public class HandleEqualsAndHashCode implements JavacAnnotationHandler<EqualsAnd
|
||||
List<JCStatement> statements = List.nil();
|
||||
List<JCVariableDecl> params = List.of(maker.VarDef(maker.Modifiers(Flags.FINAL), oName, objectType, null));
|
||||
|
||||
/* if ( o == this ) return true; */ {
|
||||
statements = statements.append(
|
||||
maker.If(maker.Binary(JCTree.EQ, maker.Ident(oName), maker.Ident(thisName)), returnBool(maker, true), null));
|
||||
/* if (o == this) return true; */ {
|
||||
statements = statements.append(maker.If(maker.Binary(JCTree.EQ, maker.Ident(oName),
|
||||
maker.Ident(thisName)), returnBool(maker, true), null));
|
||||
}
|
||||
|
||||
/* if ( o == null ) return false; */ {
|
||||
statements = statements.append(
|
||||
maker.If(maker.Binary(JCTree.EQ, maker.Ident(oName), maker.Literal(TypeTags.BOT, null)), returnBool(maker, false), null));
|
||||
/* if (o == null) return false; */ {
|
||||
statements = statements.append(maker.If(maker.Binary(JCTree.EQ, maker.Ident(oName),
|
||||
maker.Literal(TypeTags.BOT, null)), returnBool(maker, false), null));
|
||||
}
|
||||
|
||||
/* if ( o.getClass() != this.getClass() ) return false; */ {
|
||||
/* if (o.getClass() != this.getClass()) return false; */ {
|
||||
Name getClass = typeNode.toName("getClass");
|
||||
List<JCExpression> exprNil = List.nil();
|
||||
JCExpression oGetClass = maker.Apply(exprNil, maker.Select(maker.Ident(oName), getClass), exprNil);
|
||||
@@ -348,8 +348,8 @@ public class HandleEqualsAndHashCode implements JavacAnnotationHandler<EqualsAnd
|
||||
maker.If(maker.Binary(JCTree.NE, oGetClass, thisGetClass), returnBool(maker, false), null));
|
||||
}
|
||||
|
||||
/* if ( !super.equals(o) ) return false; */
|
||||
if ( callSuper ) {
|
||||
/* if (!super.equals(o)) return false; */
|
||||
if (callSuper) {
|
||||
JCMethodInvocation callToSuper = maker.Apply(List.<JCExpression>nil(),
|
||||
maker.Select(maker.Ident(typeNode.toName("super")), typeNode.toName("equals")),
|
||||
List.<JCExpression>of(maker.Ident(oName)));
|
||||
@@ -361,12 +361,12 @@ public class HandleEqualsAndHashCode implements JavacAnnotationHandler<EqualsAnd
|
||||
final JCExpression selfType1, selfType2;
|
||||
List<JCExpression> wildcards1 = List.nil();
|
||||
List<JCExpression> wildcards2 = List.nil();
|
||||
for ( int i = 0 ; i < type.typarams.length() ; i++ ) {
|
||||
for (int i = 0 ; i < type.typarams.length() ; i++) {
|
||||
wildcards1 = wildcards1.append(maker.Wildcard(maker.TypeBoundKind(BoundKind.UNBOUND), null));
|
||||
wildcards2 = wildcards2.append(maker.Wildcard(maker.TypeBoundKind(BoundKind.UNBOUND), null));
|
||||
}
|
||||
|
||||
if ( type.typarams.isEmpty() ) {
|
||||
if (type.typarams.isEmpty()) {
|
||||
selfType1 = maker.Ident(type.name);
|
||||
selfType2 = maker.Ident(type.name);
|
||||
} else {
|
||||
@@ -378,29 +378,29 @@ public class HandleEqualsAndHashCode implements JavacAnnotationHandler<EqualsAnd
|
||||
maker.VarDef(maker.Modifiers(Flags.FINAL), otherName, selfType1, maker.TypeCast(selfType2, maker.Ident(oName))));
|
||||
}
|
||||
|
||||
for ( Node fieldNode : fields ) {
|
||||
for (JavacNode fieldNode : fields) {
|
||||
JCVariableDecl field = (JCVariableDecl) fieldNode.get();
|
||||
JCExpression fType = field.vartype;
|
||||
JCExpression thisDotField = maker.Select(maker.Ident(thisName), field.name);
|
||||
JCExpression otherDotField = maker.Select(maker.Ident(otherName), field.name);
|
||||
if ( fType instanceof JCPrimitiveTypeTree ) {
|
||||
switch ( ((JCPrimitiveTypeTree)fType).getPrimitiveTypeKind() ) {
|
||||
if (fType instanceof JCPrimitiveTypeTree) {
|
||||
switch (((JCPrimitiveTypeTree)fType).getPrimitiveTypeKind()) {
|
||||
case FLOAT:
|
||||
/* if ( Float.compare(this.fieldName, other.fieldName) != 0 ) return false; */
|
||||
/* if (Float.compare(this.fieldName, other.fieldName) != 0) return false; */
|
||||
statements = statements.append(generateCompareFloatOrDouble(thisDotField, otherDotField, maker, typeNode, false));
|
||||
break;
|
||||
case DOUBLE:
|
||||
/* if ( Double(this.fieldName, other.fieldName) != 0 ) return false; */
|
||||
/* if (Double(this.fieldName, other.fieldName) != 0) return false; */
|
||||
statements = statements.append(generateCompareFloatOrDouble(thisDotField, otherDotField, maker, typeNode, true));
|
||||
break;
|
||||
default:
|
||||
/* if ( this.fieldName != other.fieldName ) return false; */
|
||||
/* if (this.fieldName != other.fieldName) return false; */
|
||||
statements = statements.append(
|
||||
maker.If(maker.Binary(JCTree.NE, thisDotField, otherDotField), returnBool(maker, false), null));
|
||||
break;
|
||||
}
|
||||
} else if ( fType instanceof JCArrayTypeTree ) {
|
||||
/* if ( !java.util.Arrays.deepEquals(this.fieldName, other.fieldName) ) return false; //use equals for primitive arrays. */
|
||||
} else if (fType instanceof JCArrayTypeTree) {
|
||||
/* if (!java.util.Arrays.deepEquals(this.fieldName, other.fieldName)) return false; //use equals for primitive arrays. */
|
||||
boolean multiDim = ((JCArrayTypeTree)fType).elemtype instanceof JCArrayTypeTree;
|
||||
boolean primitiveArray = ((JCArrayTypeTree)fType).elemtype instanceof JCPrimitiveTypeTree;
|
||||
boolean useDeepEquals = multiDim || !primitiveArray;
|
||||
@@ -410,7 +410,7 @@ public class HandleEqualsAndHashCode implements JavacAnnotationHandler<EqualsAnd
|
||||
statements = statements.append(maker.If(maker.Unary(JCTree.NOT,
|
||||
maker.Apply(List.<JCExpression>nil(), eqMethod, args)), returnBool(maker, false), null));
|
||||
} else /* objects */ {
|
||||
/* if ( this.fieldName == null ? other.fieldName != null : !this.fieldName.equals(other.fieldName) ) return false; */
|
||||
/* if (this.fieldName == null ? other.fieldName != null : !this.fieldName.equals(other.fieldName)) return false; */
|
||||
JCExpression thisEqualsNull = maker.Binary(JCTree.EQ, thisDotField, maker.Literal(TypeTags.BOT, null));
|
||||
JCExpression otherNotEqualsNull = maker.Binary(JCTree.NE, otherDotField, maker.Literal(TypeTags.BOT, null));
|
||||
JCExpression thisEqualsThat = maker.Apply(
|
||||
@@ -428,8 +428,9 @@ public class HandleEqualsAndHashCode implements JavacAnnotationHandler<EqualsAnd
|
||||
return maker.MethodDef(mods, typeNode.toName("equals"), returnType, List.<JCTypeParameter>nil(), params, List.<JCExpression>nil(), body, null);
|
||||
}
|
||||
|
||||
private JCStatement generateCompareFloatOrDouble(JCExpression thisDotField, JCExpression otherDotField, TreeMaker maker, Node node, boolean isDouble) {
|
||||
/* if ( Float.compare(fieldName, other.fieldName) != 0 ) return false; */
|
||||
private JCStatement generateCompareFloatOrDouble(JCExpression thisDotField, JCExpression otherDotField,
|
||||
TreeMaker maker, JavacNode node, boolean isDouble) {
|
||||
/* if (Float.compare(fieldName, other.fieldName) != 0) return false; */
|
||||
JCExpression clazz = chainDots(maker, node, "java", "lang", isDouble ? "Double" : "Float");
|
||||
List<JCExpression> args = List.of(thisDotField, otherDotField);
|
||||
JCBinary compareCallEquals0 = maker.Binary(JCTree.NE, maker.Apply(
|
||||
|
||||
@@ -29,7 +29,7 @@ import lombok.core.TransformationsUtil;
|
||||
import lombok.core.AST.Kind;
|
||||
import lombok.javac.Javac;
|
||||
import lombok.javac.JavacAnnotationHandler;
|
||||
import lombok.javac.JavacAST.Node;
|
||||
import lombok.javac.JavacNode;
|
||||
|
||||
import org.mangosdk.spi.ProviderFor;
|
||||
|
||||
@@ -63,10 +63,10 @@ public class HandleGetter implements JavacAnnotationHandler<Getter> {
|
||||
* If not, the getter is still generated if it isn't already there, though there will not
|
||||
* be a warning if its already there. The default access level is used.
|
||||
*/
|
||||
public void generateGetterForField(Node fieldNode, DiagnosticPosition pos) {
|
||||
for ( Node child : fieldNode.down() ) {
|
||||
if ( child.getKind() == Kind.ANNOTATION ) {
|
||||
if ( Javac.annotationTypeMatches(Getter.class, child) ) {
|
||||
public void generateGetterForField(JavacNode fieldNode, DiagnosticPosition pos) {
|
||||
for (JavacNode child : fieldNode.down()) {
|
||||
if (child.getKind() == Kind.ANNOTATION) {
|
||||
if (Javac.annotationTypeMatches(Getter.class, child)) {
|
||||
//The annotation will make it happen, so we can skip it.
|
||||
return;
|
||||
}
|
||||
@@ -76,16 +76,17 @@ public class HandleGetter implements JavacAnnotationHandler<Getter> {
|
||||
createGetterForField(AccessLevel.PUBLIC, fieldNode, fieldNode, pos, false);
|
||||
}
|
||||
|
||||
@Override public boolean handle(AnnotationValues<Getter> annotation, JCAnnotation ast, Node annotationNode) {
|
||||
Node fieldNode = annotationNode.up();
|
||||
@Override public boolean handle(AnnotationValues<Getter> annotation, JCAnnotation ast, JavacNode annotationNode) {
|
||||
JavacNode fieldNode = annotationNode.up();
|
||||
AccessLevel level = annotation.getInstance().value();
|
||||
if ( level == AccessLevel.NONE ) return true;
|
||||
if (level == AccessLevel.NONE) return true;
|
||||
|
||||
return createGetterForField(level, fieldNode, annotationNode, annotationNode.get(), true);
|
||||
}
|
||||
|
||||
private boolean createGetterForField(AccessLevel level, Node fieldNode, Node errorNode, DiagnosticPosition pos, boolean whineIfExists) {
|
||||
if ( fieldNode.getKind() != Kind.FIELD ) {
|
||||
private boolean createGetterForField(AccessLevel level,
|
||||
JavacNode fieldNode, JavacNode errorNode, DiagnosticPosition pos, boolean whineIfExists) {
|
||||
if (fieldNode.getKind() != Kind.FIELD) {
|
||||
errorNode.addError("@Getter is only supported on a field.");
|
||||
return true;
|
||||
}
|
||||
@@ -93,14 +94,14 @@ public class HandleGetter implements JavacAnnotationHandler<Getter> {
|
||||
JCVariableDecl fieldDecl = (JCVariableDecl)fieldNode.get();
|
||||
String methodName = toGetterName(fieldDecl);
|
||||
|
||||
for ( String altName : toAllGetterNames(fieldDecl) ) {
|
||||
switch ( methodExists(altName, fieldNode) ) {
|
||||
for (String altName : toAllGetterNames(fieldDecl)) {
|
||||
switch (methodExists(altName, fieldNode)) {
|
||||
case EXISTS_BY_LOMBOK:
|
||||
return true;
|
||||
case EXISTS_BY_USER:
|
||||
if ( whineIfExists ) {
|
||||
if (whineIfExists) {
|
||||
String altNameExpl = "";
|
||||
if ( !altName.equals(methodName) ) altNameExpl = String.format(" (%s)", altName);
|
||||
if (!altName.equals(methodName)) altNameExpl = String.format(" (%s)", altName);
|
||||
errorNode.addWarning(
|
||||
String.format("Not generating %s(): A method with that name already exists%s", methodName, altNameExpl));
|
||||
}
|
||||
@@ -118,7 +119,7 @@ public class HandleGetter implements JavacAnnotationHandler<Getter> {
|
||||
return true;
|
||||
}
|
||||
|
||||
private JCMethodDecl createGetter(long access, Node field, TreeMaker treeMaker) {
|
||||
private JCMethodDecl createGetter(long access, JavacNode field, TreeMaker treeMaker) {
|
||||
JCVariableDecl fieldNode = (JCVariableDecl) field.get();
|
||||
JCStatement returnStatement = treeMaker.Return(treeMaker.Ident(fieldNode.getName()));
|
||||
|
||||
|
||||
@@ -34,19 +34,19 @@ import lombok.core.AnnotationValues;
|
||||
import lombok.core.PrintAST;
|
||||
import lombok.javac.JavacASTVisitor;
|
||||
import lombok.javac.JavacAnnotationHandler;
|
||||
import lombok.javac.JavacAST.Node;
|
||||
import lombok.javac.JavacNode;
|
||||
|
||||
/**
|
||||
* Handles the <code>lombok.core.PrintAST</code> annotation for javac.
|
||||
*/
|
||||
@ProviderFor(JavacAnnotationHandler.class)
|
||||
public class HandlePrintAST implements JavacAnnotationHandler<PrintAST> {
|
||||
@Override public boolean handle(AnnotationValues<PrintAST> annotation, JCAnnotation ast, Node annotationNode) {
|
||||
@Override public boolean handle(AnnotationValues<PrintAST> annotation, JCAnnotation ast, JavacNode annotationNode) {
|
||||
PrintStream stream = System.out;
|
||||
String fileName = annotation.getInstance().outfile();
|
||||
if ( fileName.length() > 0 ) try {
|
||||
if (fileName.length() > 0) try {
|
||||
stream = new PrintStream(new File(fileName));
|
||||
} catch ( FileNotFoundException e ) {
|
||||
} catch (FileNotFoundException e) {
|
||||
Lombok.sneakyThrow(e);
|
||||
}
|
||||
|
||||
|
||||
@@ -28,9 +28,8 @@ import lombok.core.AnnotationValues;
|
||||
import lombok.core.TransformationsUtil;
|
||||
import lombok.core.AST.Kind;
|
||||
import lombok.javac.Javac;
|
||||
import lombok.javac.JavacAST;
|
||||
import lombok.javac.JavacAnnotationHandler;
|
||||
import lombok.javac.JavacAST.Node;
|
||||
import lombok.javac.JavacNode;
|
||||
|
||||
import org.mangosdk.spi.ProviderFor;
|
||||
|
||||
@@ -66,10 +65,10 @@ public class HandleSetter implements JavacAnnotationHandler<Setter> {
|
||||
* If not, the setter is still generated if it isn't already there, though there will not
|
||||
* be a warning if its already there. The default access level is used.
|
||||
*/
|
||||
public void generateSetterForField(Node fieldNode, DiagnosticPosition pos) {
|
||||
for ( Node child : fieldNode.down() ) {
|
||||
if ( child.getKind() == Kind.ANNOTATION ) {
|
||||
if ( Javac.annotationTypeMatches(Setter.class, child) ) {
|
||||
public void generateSetterForField(JavacNode fieldNode, DiagnosticPosition pos) {
|
||||
for (JavacNode child : fieldNode.down()) {
|
||||
if (child.getKind() == Kind.ANNOTATION) {
|
||||
if (Javac.annotationTypeMatches(Setter.class, child)) {
|
||||
//The annotation will make it happen, so we can skip it.
|
||||
return;
|
||||
}
|
||||
@@ -79,16 +78,17 @@ public class HandleSetter implements JavacAnnotationHandler<Setter> {
|
||||
createSetterForField(AccessLevel.PUBLIC, fieldNode, fieldNode, pos, false);
|
||||
}
|
||||
|
||||
@Override public boolean handle(AnnotationValues<Setter> annotation, JCAnnotation ast, Node annotationNode) {
|
||||
Node fieldNode = annotationNode.up();
|
||||
@Override public boolean handle(AnnotationValues<Setter> annotation, JCAnnotation ast, JavacNode annotationNode) {
|
||||
JavacNode fieldNode = annotationNode.up();
|
||||
AccessLevel level = annotation.getInstance().value();
|
||||
if ( level == AccessLevel.NONE ) return true;
|
||||
if (level == AccessLevel.NONE) return true;
|
||||
|
||||
return createSetterForField(level, fieldNode, annotationNode, annotationNode.get(), true);
|
||||
}
|
||||
|
||||
private boolean createSetterForField(AccessLevel level, Node fieldNode, Node errorNode, DiagnosticPosition pos, boolean whineIfExists) {
|
||||
if ( fieldNode.getKind() != Kind.FIELD ) {
|
||||
private boolean createSetterForField(AccessLevel level,
|
||||
JavacNode fieldNode, JavacNode errorNode, DiagnosticPosition pos, boolean whineIfExists) {
|
||||
if (fieldNode.getKind() != Kind.FIELD) {
|
||||
fieldNode.addError("@Setter is only supported on a field.");
|
||||
return true;
|
||||
}
|
||||
@@ -96,11 +96,11 @@ public class HandleSetter implements JavacAnnotationHandler<Setter> {
|
||||
JCVariableDecl fieldDecl = (JCVariableDecl)fieldNode.get();
|
||||
String methodName = toSetterName(fieldDecl);
|
||||
|
||||
switch ( methodExists(methodName, fieldNode) ) {
|
||||
switch (methodExists(methodName, fieldNode)) {
|
||||
case EXISTS_BY_LOMBOK:
|
||||
return true;
|
||||
case EXISTS_BY_USER:
|
||||
if ( whineIfExists ) errorNode.addWarning(
|
||||
if (whineIfExists) errorNode.addWarning(
|
||||
String.format("Not generating %s(%s %s): A method with that name already exists",
|
||||
methodName, fieldDecl.vartype, fieldDecl.name));
|
||||
return true;
|
||||
@@ -116,7 +116,7 @@ public class HandleSetter implements JavacAnnotationHandler<Setter> {
|
||||
return true;
|
||||
}
|
||||
|
||||
private JCMethodDecl createSetter(long access, JavacAST.Node field, TreeMaker treeMaker) {
|
||||
private JCMethodDecl createSetter(long access, JavacNode field, TreeMaker treeMaker) {
|
||||
JCVariableDecl fieldDecl = (JCVariableDecl) field.get();
|
||||
|
||||
JCFieldAccess thisX = treeMaker.Select(treeMaker.Ident(field.toName("this")), fieldDecl.name);
|
||||
|
||||
@@ -29,7 +29,7 @@ import java.util.Collection;
|
||||
import lombok.SneakyThrows;
|
||||
import lombok.core.AnnotationValues;
|
||||
import lombok.javac.JavacAnnotationHandler;
|
||||
import lombok.javac.JavacAST.Node;
|
||||
import lombok.javac.JavacNode;
|
||||
|
||||
import org.mangosdk.spi.ProviderFor;
|
||||
|
||||
@@ -50,31 +50,31 @@ import com.sun.tools.javac.util.List;
|
||||
*/
|
||||
@ProviderFor(JavacAnnotationHandler.class)
|
||||
public class HandleSneakyThrows implements JavacAnnotationHandler<SneakyThrows> {
|
||||
@Override public boolean handle(AnnotationValues<SneakyThrows> annotation, JCAnnotation ast, Node annotationNode) {
|
||||
@Override public boolean handle(AnnotationValues<SneakyThrows> annotation, JCAnnotation ast, JavacNode annotationNode) {
|
||||
Collection<String> exceptionNames = annotation.getRawExpressions("value");
|
||||
|
||||
List<JCExpression> memberValuePairs = ast.getArguments();
|
||||
if ( memberValuePairs == null || memberValuePairs.size() == 0 ) return false;
|
||||
if (memberValuePairs == null || memberValuePairs.size() == 0) return false;
|
||||
|
||||
JCExpression arrayOrSingle = ((JCAssign)memberValuePairs.get(0)).rhs;
|
||||
final List<JCExpression> exceptionNameNodes;
|
||||
if ( arrayOrSingle instanceof JCNewArray ) {
|
||||
if (arrayOrSingle instanceof JCNewArray) {
|
||||
exceptionNameNodes = ((JCNewArray)arrayOrSingle).elems;
|
||||
} else exceptionNameNodes = List.of(arrayOrSingle);
|
||||
|
||||
if ( exceptionNames.size() != exceptionNameNodes.size() ) {
|
||||
if (exceptionNames.size() != exceptionNameNodes.size()) {
|
||||
annotationNode.addError(
|
||||
"LOMBOK BUG: The number of exception classes in the annotation isn't the same pre- and post- guessing.");
|
||||
}
|
||||
|
||||
java.util.List<String> exceptions = new ArrayList<String>();
|
||||
for ( String exception : exceptionNames ) {
|
||||
if ( exception.endsWith(".class") ) exception = exception.substring(0, exception.length() - 6);
|
||||
for (String exception : exceptionNames) {
|
||||
if (exception.endsWith(".class")) exception = exception.substring(0, exception.length() - 6);
|
||||
exceptions.add(exception);
|
||||
}
|
||||
|
||||
Node owner = annotationNode.up();
|
||||
switch ( owner.getKind() ) {
|
||||
JavacNode owner = annotationNode.up();
|
||||
switch (owner.getKind()) {
|
||||
case METHOD:
|
||||
return handleMethod(annotationNode, (JCMethodDecl)owner.get(), exceptions);
|
||||
default:
|
||||
@@ -83,19 +83,19 @@ public class HandleSneakyThrows implements JavacAnnotationHandler<SneakyThrows>
|
||||
}
|
||||
}
|
||||
|
||||
private boolean handleMethod(Node annotation, JCMethodDecl method, Collection<String> exceptions) {
|
||||
Node methodNode = annotation.up();
|
||||
private boolean handleMethod(JavacNode annotation, JCMethodDecl method, Collection<String> exceptions) {
|
||||
JavacNode methodNode = annotation.up();
|
||||
|
||||
if ( (method.mods.flags & Flags.ABSTRACT) != 0 ) {
|
||||
if ( (method.mods.flags & Flags.ABSTRACT) != 0) {
|
||||
annotation.addError("@SneakyThrows can only be used on concrete methods.");
|
||||
return true;
|
||||
}
|
||||
|
||||
if ( method.body == null ) return false;
|
||||
if (method.body == null) return false;
|
||||
|
||||
List<JCStatement> contents = method.body.stats;
|
||||
|
||||
for ( String exception : exceptions ) {
|
||||
for (String exception : exceptions) {
|
||||
contents = List.of(buildTryCatchBlock(methodNode, contents, exception));
|
||||
}
|
||||
|
||||
@@ -105,7 +105,7 @@ public class HandleSneakyThrows implements JavacAnnotationHandler<SneakyThrows>
|
||||
return true;
|
||||
}
|
||||
|
||||
private JCStatement buildTryCatchBlock(Node node, List<JCStatement> contents, String exception) {
|
||||
private JCStatement buildTryCatchBlock(JavacNode node, List<JCStatement> contents, String exception) {
|
||||
TreeMaker maker = node.getTreeMaker();
|
||||
|
||||
JCBlock tryBlock = maker.Block(0, contents);
|
||||
|
||||
@@ -40,7 +40,7 @@ import lombok.Synchronized;
|
||||
import lombok.core.AnnotationValues;
|
||||
import lombok.core.AST.Kind;
|
||||
import lombok.javac.JavacAnnotationHandler;
|
||||
import lombok.javac.JavacAST.Node;
|
||||
import lombok.javac.JavacNode;
|
||||
|
||||
/**
|
||||
* Handles the <code>lombok.Synchronized</code> annotation for javac.
|
||||
@@ -50,32 +50,32 @@ public class HandleSynchronized implements JavacAnnotationHandler<Synchronized>
|
||||
private static final String INSTANCE_LOCK_NAME = "$lock";
|
||||
private static final String STATIC_LOCK_NAME = "$LOCK";
|
||||
|
||||
@Override public boolean handle(AnnotationValues<Synchronized> annotation, JCAnnotation ast, Node annotationNode) {
|
||||
Node methodNode = annotationNode.up();
|
||||
@Override public boolean handle(AnnotationValues<Synchronized> annotation, JCAnnotation ast, JavacNode annotationNode) {
|
||||
JavacNode methodNode = annotationNode.up();
|
||||
|
||||
if ( methodNode == null || methodNode.getKind() != Kind.METHOD || !(methodNode.get() instanceof JCMethodDecl) ) {
|
||||
if (methodNode == null || methodNode.getKind() != Kind.METHOD || !(methodNode.get() instanceof JCMethodDecl)) {
|
||||
annotationNode.addError("@Synchronized is legal only on methods.");
|
||||
return true;
|
||||
}
|
||||
|
||||
JCMethodDecl method = (JCMethodDecl)methodNode.get();
|
||||
|
||||
if ( (method.mods.flags & Flags.ABSTRACT) != 0 ) {
|
||||
if ((method.mods.flags & Flags.ABSTRACT) != 0) {
|
||||
annotationNode.addError("@Synchronized is legal only on concrete methods.");
|
||||
return true;
|
||||
}
|
||||
boolean isStatic = (method.mods.flags & Flags.STATIC) != 0;
|
||||
String lockName = annotation.getInstance().value();
|
||||
boolean autoMake = false;
|
||||
if ( lockName.length() == 0 ) {
|
||||
if (lockName.length() == 0) {
|
||||
autoMake = true;
|
||||
lockName = isStatic ? STATIC_LOCK_NAME : INSTANCE_LOCK_NAME;
|
||||
}
|
||||
|
||||
TreeMaker maker = methodNode.getTreeMaker();
|
||||
|
||||
if ( fieldExists(lockName, methodNode) == MemberExistsResult.NOT_EXISTS ) {
|
||||
if ( !autoMake ) {
|
||||
if (fieldExists(lockName, methodNode) == MemberExistsResult.NOT_EXISTS) {
|
||||
if (!autoMake) {
|
||||
annotationNode.addError("The field " + new String(lockName) + " does not exist.");
|
||||
return true;
|
||||
}
|
||||
@@ -89,7 +89,7 @@ public class HandleSynchronized implements JavacAnnotationHandler<Synchronized>
|
||||
injectField(methodNode.up(), fieldDecl);
|
||||
}
|
||||
|
||||
if ( method.body == null ) return false;
|
||||
if (method.body == null) return false;
|
||||
|
||||
JCExpression lockNode = maker.Ident(methodNode.toName(lockName));
|
||||
|
||||
|
||||
@@ -28,7 +28,7 @@ import lombok.core.AnnotationValues;
|
||||
import lombok.core.AST.Kind;
|
||||
import lombok.javac.Javac;
|
||||
import lombok.javac.JavacAnnotationHandler;
|
||||
import lombok.javac.JavacAST.Node;
|
||||
import lombok.javac.JavacNode;
|
||||
|
||||
import org.mangosdk.spi.ProviderFor;
|
||||
|
||||
@@ -54,34 +54,34 @@ import com.sun.tools.javac.util.List;
|
||||
*/
|
||||
@ProviderFor(JavacAnnotationHandler.class)
|
||||
public class HandleToString implements JavacAnnotationHandler<ToString> {
|
||||
private void checkForBogusFieldNames(Node type, AnnotationValues<ToString> annotation) {
|
||||
if ( annotation.isExplicit("exclude") ) {
|
||||
for ( int i : createListOfNonExistentFields(List.from(annotation.getInstance().exclude()), type, true, false) ) {
|
||||
private void checkForBogusFieldNames(JavacNode type, AnnotationValues<ToString> annotation) {
|
||||
if (annotation.isExplicit("exclude")) {
|
||||
for (int i : createListOfNonExistentFields(List.from(annotation.getInstance().exclude()), type, true, false)) {
|
||||
annotation.setWarning("exclude", "This field does not exist, or would have been excluded anyway.", i);
|
||||
}
|
||||
}
|
||||
if ( annotation.isExplicit("of") ) {
|
||||
for ( int i : createListOfNonExistentFields(List.from(annotation.getInstance().of()), type, false, false) ) {
|
||||
if (annotation.isExplicit("of")) {
|
||||
for (int i : createListOfNonExistentFields(List.from(annotation.getInstance().of()), type, false, false)) {
|
||||
annotation.setWarning("of", "This field does not exist.", i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override public boolean handle(AnnotationValues<ToString> annotation, JCAnnotation ast, Node annotationNode) {
|
||||
@Override public boolean handle(AnnotationValues<ToString> annotation, JCAnnotation ast, JavacNode annotationNode) {
|
||||
ToString ann = annotation.getInstance();
|
||||
List<String> excludes = List.from(ann.exclude());
|
||||
List<String> includes = List.from(ann.of());
|
||||
Node typeNode = annotationNode.up();
|
||||
JavacNode typeNode = annotationNode.up();
|
||||
|
||||
checkForBogusFieldNames(typeNode, annotation);
|
||||
|
||||
Boolean callSuper = ann.callSuper();
|
||||
|
||||
if ( !annotation.isExplicit("callSuper") ) callSuper = null;
|
||||
if ( !annotation.isExplicit("exclude") ) excludes = null;
|
||||
if ( !annotation.isExplicit("of") ) includes = null;
|
||||
if (!annotation.isExplicit("callSuper")) callSuper = null;
|
||||
if (!annotation.isExplicit("exclude")) excludes = null;
|
||||
if (!annotation.isExplicit("of")) includes = null;
|
||||
|
||||
if ( excludes != null && includes != null ) {
|
||||
if (excludes != null && includes != null) {
|
||||
excludes = null;
|
||||
annotation.setWarning("exclude", "exclude and of are mutually exclusive; the 'exclude' parameter will be ignored.");
|
||||
}
|
||||
@@ -89,10 +89,10 @@ public class HandleToString implements JavacAnnotationHandler<ToString> {
|
||||
return generateToString(typeNode, annotationNode, excludes, includes, ann.includeFieldNames(), callSuper, true);
|
||||
}
|
||||
|
||||
public void generateToStringForType(Node typeNode, Node errorNode) {
|
||||
for ( Node child : typeNode.down() ) {
|
||||
if ( child.getKind() == Kind.ANNOTATION ) {
|
||||
if ( Javac.annotationTypeMatches(ToString.class, child) ) {
|
||||
public void generateToStringForType(JavacNode typeNode, JavacNode errorNode) {
|
||||
for (JavacNode child : typeNode.down()) {
|
||||
if (child.getKind() == Kind.ANNOTATION) {
|
||||
if (Javac.annotationTypeMatches(ToString.class, child)) {
|
||||
//The annotation will make it happen, so we can skip it.
|
||||
return;
|
||||
}
|
||||
@@ -102,51 +102,51 @@ public class HandleToString implements JavacAnnotationHandler<ToString> {
|
||||
boolean includeFieldNames = true;
|
||||
try {
|
||||
includeFieldNames = ((Boolean)ToString.class.getMethod("includeFieldNames").getDefaultValue()).booleanValue();
|
||||
} catch ( Exception ignore ) {}
|
||||
} catch (Exception ignore) {}
|
||||
generateToString(typeNode, errorNode, null, null, includeFieldNames, null, false);
|
||||
}
|
||||
|
||||
private boolean generateToString(Node typeNode, Node errorNode, List<String> excludes, List<String> includes,
|
||||
private boolean generateToString(JavacNode typeNode, JavacNode errorNode, List<String> excludes, List<String> includes,
|
||||
boolean includeFieldNames, Boolean callSuper, boolean whineIfExists) {
|
||||
boolean notAClass = true;
|
||||
if ( typeNode.get() instanceof JCClassDecl ) {
|
||||
if (typeNode.get() instanceof JCClassDecl) {
|
||||
long flags = ((JCClassDecl)typeNode.get()).mods.flags;
|
||||
notAClass = (flags & (Flags.INTERFACE | Flags.ANNOTATION | Flags.ENUM)) != 0;
|
||||
}
|
||||
|
||||
if ( callSuper == null ) {
|
||||
if (callSuper == null) {
|
||||
try {
|
||||
callSuper = ((Boolean)ToString.class.getMethod("callSuper").getDefaultValue()).booleanValue();
|
||||
} catch ( Exception ignore ) {}
|
||||
} catch (Exception ignore) {}
|
||||
}
|
||||
|
||||
if ( notAClass ) {
|
||||
if (notAClass) {
|
||||
errorNode.addError("@ToString is only supported on a class.");
|
||||
return false;
|
||||
}
|
||||
|
||||
List<Node> nodesForToString = List.nil();
|
||||
if ( includes != null ) {
|
||||
for ( Node child : typeNode.down() ) {
|
||||
if ( child.getKind() != Kind.FIELD ) continue;
|
||||
List<JavacNode> nodesForToString = List.nil();
|
||||
if (includes != null) {
|
||||
for (JavacNode child : typeNode.down()) {
|
||||
if (child.getKind() != Kind.FIELD) continue;
|
||||
JCVariableDecl fieldDecl = (JCVariableDecl) child.get();
|
||||
if ( includes.contains(fieldDecl.name.toString()) ) nodesForToString = nodesForToString.append(child);
|
||||
if (includes.contains(fieldDecl.name.toString())) nodesForToString = nodesForToString.append(child);
|
||||
}
|
||||
} else {
|
||||
for ( Node child : typeNode.down() ) {
|
||||
if ( child.getKind() != Kind.FIELD ) continue;
|
||||
for (JavacNode child : typeNode.down()) {
|
||||
if (child.getKind() != Kind.FIELD) continue;
|
||||
JCVariableDecl fieldDecl = (JCVariableDecl) child.get();
|
||||
//Skip static fields.
|
||||
if ( (fieldDecl.mods.flags & Flags.STATIC) != 0 ) continue;
|
||||
if ((fieldDecl.mods.flags & Flags.STATIC) != 0) continue;
|
||||
//Skip excluded fields.
|
||||
if ( excludes != null && excludes.contains(fieldDecl.name.toString()) ) continue;
|
||||
if (excludes != null && excludes.contains(fieldDecl.name.toString())) continue;
|
||||
//Skip fields that start with $.
|
||||
if ( fieldDecl.name.toString().startsWith("$") ) continue;
|
||||
if (fieldDecl.name.toString().startsWith("$")) continue;
|
||||
nodesForToString = nodesForToString.append(child);
|
||||
}
|
||||
}
|
||||
|
||||
switch ( methodExists("toString", typeNode) ) {
|
||||
switch (methodExists("toString", typeNode)) {
|
||||
case NOT_EXISTS:
|
||||
JCMethodDecl method = createToString(typeNode, nodesForToString, includeFieldNames, callSuper);
|
||||
injectMethod(typeNode, method);
|
||||
@@ -155,7 +155,7 @@ public class HandleToString implements JavacAnnotationHandler<ToString> {
|
||||
return true;
|
||||
default:
|
||||
case EXISTS_BY_USER:
|
||||
if ( whineIfExists ) {
|
||||
if (whineIfExists) {
|
||||
errorNode.addWarning("Not generating toString(): A method with that name already exists");
|
||||
}
|
||||
return true;
|
||||
@@ -163,7 +163,7 @@ public class HandleToString implements JavacAnnotationHandler<ToString> {
|
||||
|
||||
}
|
||||
|
||||
private JCMethodDecl createToString(Node typeNode, List<Node> fields, boolean includeFieldNames, boolean callSuper) {
|
||||
private JCMethodDecl createToString(JavacNode typeNode, List<JavacNode> fields, boolean includeFieldNames, boolean callSuper) {
|
||||
TreeMaker maker = typeNode.getTreeMaker();
|
||||
|
||||
JCAnnotation overrideAnnotation = maker.Annotation(chainDots(maker, typeNode, "java", "lang", "Override"), List.<JCExpression>nil());
|
||||
@@ -176,11 +176,11 @@ public class HandleToString implements JavacAnnotationHandler<ToString> {
|
||||
String infix = ", ";
|
||||
String suffix = ")";
|
||||
String prefix;
|
||||
if ( callSuper ) {
|
||||
if (callSuper) {
|
||||
prefix = typeName + "(super=";
|
||||
} else if ( fields.isEmpty() ) {
|
||||
} else if (fields.isEmpty()) {
|
||||
prefix = typeName + "()";
|
||||
} else if ( includeFieldNames ) {
|
||||
} else if (includeFieldNames) {
|
||||
prefix = typeName + "(" + ((JCVariableDecl)fields.iterator().next().get()).name.toString() + "=";
|
||||
} else {
|
||||
prefix = typeName + "(";
|
||||
@@ -188,7 +188,7 @@ public class HandleToString implements JavacAnnotationHandler<ToString> {
|
||||
|
||||
JCExpression current = maker.Literal(prefix);
|
||||
|
||||
if ( callSuper ) {
|
||||
if (callSuper) {
|
||||
JCMethodInvocation callToSuper = maker.Apply(List.<JCExpression>nil(),
|
||||
maker.Select(maker.Ident(typeNode.toName("super")), typeNode.toName("toString")),
|
||||
List.<JCExpression>nil());
|
||||
@@ -196,11 +196,11 @@ public class HandleToString implements JavacAnnotationHandler<ToString> {
|
||||
first = false;
|
||||
}
|
||||
|
||||
for ( Node fieldNode : fields ) {
|
||||
for (JavacNode fieldNode : fields) {
|
||||
JCVariableDecl field = (JCVariableDecl) fieldNode.get();
|
||||
JCExpression expr;
|
||||
|
||||
if ( field.vartype instanceof JCArrayTypeTree ) {
|
||||
if (field.vartype instanceof JCArrayTypeTree) {
|
||||
boolean multiDim = ((JCArrayTypeTree)field.vartype).elemtype instanceof JCArrayTypeTree;
|
||||
boolean primitiveArray = ((JCArrayTypeTree)field.vartype).elemtype instanceof JCPrimitiveTypeTree;
|
||||
boolean useDeepTS = multiDim || !primitiveArray;
|
||||
@@ -209,13 +209,13 @@ public class HandleToString implements JavacAnnotationHandler<ToString> {
|
||||
expr = maker.Apply(List.<JCExpression>nil(), hcMethod, List.<JCExpression>of(maker.Ident(field.name)));
|
||||
} else expr = maker.Ident(field.name);
|
||||
|
||||
if ( first ) {
|
||||
if (first) {
|
||||
current = maker.Binary(JCTree.PLUS, current, expr);
|
||||
first = false;
|
||||
continue;
|
||||
}
|
||||
|
||||
if ( includeFieldNames ) {
|
||||
if (includeFieldNames) {
|
||||
current = maker.Binary(JCTree.PLUS, current, maker.Literal(infix + fieldNode.getName() + "="));
|
||||
} else {
|
||||
current = maker.Binary(JCTree.PLUS, current, maker.Literal(infix));
|
||||
@@ -224,7 +224,7 @@ public class HandleToString implements JavacAnnotationHandler<ToString> {
|
||||
current = maker.Binary(JCTree.PLUS, current, expr);
|
||||
}
|
||||
|
||||
if ( !first ) current = maker.Binary(JCTree.PLUS, current, maker.Literal(suffix));
|
||||
if (!first) current = maker.Binary(JCTree.PLUS, current, maker.Literal(suffix));
|
||||
|
||||
JCStatement returnStatement = maker.Return(current);
|
||||
|
||||
|
||||
@@ -27,8 +27,7 @@ import java.util.regex.Pattern;
|
||||
import lombok.AccessLevel;
|
||||
import lombok.core.TransformationsUtil;
|
||||
import lombok.core.AST.Kind;
|
||||
import lombok.javac.JavacAST;
|
||||
import lombok.javac.JavacAST.Node;
|
||||
import lombok.javac.JavacNode;
|
||||
|
||||
import com.sun.tools.javac.code.Flags;
|
||||
import com.sun.tools.javac.code.TypeTags;
|
||||
@@ -95,17 +94,17 @@ class PKG {
|
||||
* @param fieldName the field name to check for.
|
||||
* @param node Any node that represents the Type (JCClassDecl) to check for, or any child node thereof.
|
||||
*/
|
||||
static MemberExistsResult fieldExists(String fieldName, JavacAST.Node node) {
|
||||
while ( node != null && !(node.get() instanceof JCClassDecl) ) {
|
||||
static MemberExistsResult fieldExists(String fieldName, JavacNode node) {
|
||||
while (node != null && !(node.get() instanceof JCClassDecl)) {
|
||||
node = node.up();
|
||||
}
|
||||
|
||||
if ( node != null && node.get() instanceof JCClassDecl ) {
|
||||
for ( JCTree def : ((JCClassDecl)node.get()).defs ) {
|
||||
if ( def instanceof JCVariableDecl ) {
|
||||
if ( ((JCVariableDecl)def).name.contentEquals(fieldName) ) {
|
||||
JavacAST.Node existing = node.getNodeFor(def);
|
||||
if ( existing == null || !existing.isHandled() ) return MemberExistsResult.EXISTS_BY_USER;
|
||||
if (node != null && node.get() instanceof JCClassDecl) {
|
||||
for (JCTree def : ((JCClassDecl)node.get()).defs) {
|
||||
if (def instanceof JCVariableDecl) {
|
||||
if (((JCVariableDecl)def).name.contentEquals(fieldName)) {
|
||||
JavacNode existing = node.getNodeFor(def);
|
||||
if (existing == null || !existing.isHandled()) return MemberExistsResult.EXISTS_BY_USER;
|
||||
return MemberExistsResult.EXISTS_BY_LOMBOK;
|
||||
}
|
||||
}
|
||||
@@ -122,17 +121,17 @@ class PKG {
|
||||
* @param methodName the method name to check for.
|
||||
* @param node Any node that represents the Type (JCClassDecl) to check for, or any child node thereof.
|
||||
*/
|
||||
static MemberExistsResult methodExists(String methodName, JavacAST.Node node) {
|
||||
while ( node != null && !(node.get() instanceof JCClassDecl) ) {
|
||||
static MemberExistsResult methodExists(String methodName, JavacNode node) {
|
||||
while (node != null && !(node.get() instanceof JCClassDecl)) {
|
||||
node = node.up();
|
||||
}
|
||||
|
||||
if ( node != null && node.get() instanceof JCClassDecl ) {
|
||||
for ( JCTree def : ((JCClassDecl)node.get()).defs ) {
|
||||
if ( def instanceof JCMethodDecl ) {
|
||||
if ( ((JCMethodDecl)def).name.contentEquals(methodName) ) {
|
||||
JavacAST.Node existing = node.getNodeFor(def);
|
||||
if ( existing == null || !existing.isHandled() ) return MemberExistsResult.EXISTS_BY_USER;
|
||||
if (node != null && node.get() instanceof JCClassDecl) {
|
||||
for (JCTree def : ((JCClassDecl)node.get()).defs) {
|
||||
if (def instanceof JCMethodDecl) {
|
||||
if (((JCMethodDecl)def).name.contentEquals(methodName)) {
|
||||
JavacNode existing = node.getNodeFor(def);
|
||||
if (existing == null || !existing.isHandled()) return MemberExistsResult.EXISTS_BY_USER;
|
||||
return MemberExistsResult.EXISTS_BY_LOMBOK;
|
||||
}
|
||||
}
|
||||
@@ -148,18 +147,18 @@ class PKG {
|
||||
*
|
||||
* @param node Any node that represents the Type (JCClassDecl) to check for, or any child node thereof.
|
||||
*/
|
||||
static MemberExistsResult constructorExists(JavacAST.Node node) {
|
||||
while ( node != null && !(node.get() instanceof JCClassDecl) ) {
|
||||
static MemberExistsResult constructorExists(JavacNode node) {
|
||||
while (node != null && !(node.get() instanceof JCClassDecl)) {
|
||||
node = node.up();
|
||||
}
|
||||
|
||||
if ( node != null && node.get() instanceof JCClassDecl ) {
|
||||
for ( JCTree def : ((JCClassDecl)node.get()).defs ) {
|
||||
if ( def instanceof JCMethodDecl ) {
|
||||
if ( ((JCMethodDecl)def).name.contentEquals("<init>") ) {
|
||||
if ( (((JCMethodDecl)def).mods.flags & Flags.GENERATEDCONSTR) != 0 ) continue;
|
||||
JavacAST.Node existing = node.getNodeFor(def);
|
||||
if ( existing == null || !existing.isHandled() ) return MemberExistsResult.EXISTS_BY_USER;
|
||||
if (node != null && node.get() instanceof JCClassDecl) {
|
||||
for (JCTree def : ((JCClassDecl)node.get()).defs) {
|
||||
if (def instanceof JCMethodDecl) {
|
||||
if (((JCMethodDecl)def).name.contentEquals("<init>")) {
|
||||
if ((((JCMethodDecl)def).mods.flags & Flags.GENERATEDCONSTR) != 0) continue;
|
||||
JavacNode existing = node.getNodeFor(def);
|
||||
if (existing == null || !existing.isHandled()) return MemberExistsResult.EXISTS_BY_USER;
|
||||
return MemberExistsResult.EXISTS_BY_LOMBOK;
|
||||
}
|
||||
}
|
||||
@@ -175,7 +174,7 @@ class PKG {
|
||||
* @see java.lang.Modifier
|
||||
*/
|
||||
static int toJavacModifier(AccessLevel accessLevel) {
|
||||
switch ( accessLevel ) {
|
||||
switch (accessLevel) {
|
||||
case MODULE:
|
||||
case PACKAGE:
|
||||
return 0;
|
||||
@@ -194,7 +193,7 @@ class PKG {
|
||||
*
|
||||
* Also takes care of updating the JavacAST.
|
||||
*/
|
||||
static void injectField(JavacAST.Node typeNode, JCVariableDecl field) {
|
||||
static void injectField(JavacNode typeNode, JCVariableDecl field) {
|
||||
JCClassDecl type = (JCClassDecl) typeNode.get();
|
||||
|
||||
type.defs = type.defs.append(field);
|
||||
@@ -208,17 +207,17 @@ class PKG {
|
||||
*
|
||||
* Also takes care of updating the JavacAST.
|
||||
*/
|
||||
static void injectMethod(JavacAST.Node typeNode, JCMethodDecl method) {
|
||||
static void injectMethod(JavacNode typeNode, JCMethodDecl method) {
|
||||
JCClassDecl type = (JCClassDecl) typeNode.get();
|
||||
|
||||
if ( method.getName().contentEquals("<init>") ) {
|
||||
if (method.getName().contentEquals("<init>")) {
|
||||
//Scan for default constructor, and remove it.
|
||||
int idx = 0;
|
||||
for ( JCTree def : type.defs ) {
|
||||
if ( def instanceof JCMethodDecl ) {
|
||||
if ( (((JCMethodDecl)def).mods.flags & Flags.GENERATEDCONSTR) != 0 ) {
|
||||
JavacAST.Node tossMe = typeNode.getNodeFor(def);
|
||||
if ( tossMe != null ) tossMe.up().removeChild(tossMe);
|
||||
for (JCTree def : type.defs) {
|
||||
if (def instanceof JCMethodDecl) {
|
||||
if ((((JCMethodDecl)def).mods.flags & Flags.GENERATEDCONSTR) != 0) {
|
||||
JavacNode tossMe = typeNode.getNodeFor(def);
|
||||
if (tossMe != null) tossMe.up().removeChild(tossMe);
|
||||
type.defs = addAllButOne(type.defs, idx);
|
||||
break;
|
||||
}
|
||||
@@ -235,8 +234,8 @@ class PKG {
|
||||
private static List<JCTree> addAllButOne(List<JCTree> defs, int idx) {
|
||||
List<JCTree> out = List.nil();
|
||||
int i = 0;
|
||||
for ( JCTree def : defs ) {
|
||||
if ( i++ != idx ) out = out.append(def);
|
||||
for (JCTree def : defs) {
|
||||
if (i++ != idx) out = out.append(def);
|
||||
}
|
||||
return out;
|
||||
}
|
||||
@@ -251,22 +250,22 @@ class PKG {
|
||||
* @see com.sun.tools.javac.tree.JCTree.JCIdent
|
||||
* @see com.sun.tools.javac.tree.JCTree.JCFieldAccess
|
||||
*/
|
||||
static JCExpression chainDots(TreeMaker maker, JavacAST.Node node, String... elems) {
|
||||
static JCExpression chainDots(TreeMaker maker, JavacNode node, String... elems) {
|
||||
assert elems != null;
|
||||
assert elems.length > 0;
|
||||
|
||||
JCExpression e = maker.Ident(node.toName(elems[0]));
|
||||
for ( int i = 1 ; i < elems.length ; i++ ) {
|
||||
for (int i = 1 ; i < elems.length ; i++) {
|
||||
e = maker.Select(e, node.toName(elems[i]));
|
||||
}
|
||||
|
||||
return e;
|
||||
}
|
||||
|
||||
static List<JCAnnotation> findAnnotations(Node fieldNode, Pattern namePattern) {
|
||||
static List<JCAnnotation> findAnnotations(JavacNode fieldNode, Pattern namePattern) {
|
||||
List<JCAnnotation> result = List.nil();
|
||||
for ( Node child : fieldNode.down() ) {
|
||||
if ( child.getKind() == Kind.ANNOTATION ) {
|
||||
for (JavacNode child : fieldNode.down()) {
|
||||
if (child.getKind() == Kind.ANNOTATION) {
|
||||
JCAnnotation annotation = (JCAnnotation) child.get();
|
||||
String name = annotation.annotationType.toString();
|
||||
int idx = name.lastIndexOf(".");
|
||||
@@ -279,7 +278,7 @@ class PKG {
|
||||
return result;
|
||||
}
|
||||
|
||||
static JCStatement generateNullCheck(TreeMaker treeMaker, JavacAST.Node variable) {
|
||||
static JCStatement generateNullCheck(TreeMaker treeMaker, JavacNode variable) {
|
||||
JCVariableDecl varDecl = (JCVariableDecl) variable.get();
|
||||
if (isPrimitive(varDecl.vartype)) return null;
|
||||
Name fieldName = varDecl.name;
|
||||
@@ -289,29 +288,28 @@ class PKG {
|
||||
return treeMaker.If(treeMaker.Binary(JCTree.EQ, treeMaker.Ident(fieldName), treeMaker.Literal(TypeTags.BOT, null)), throwStatement, null);
|
||||
}
|
||||
|
||||
static List<Integer> createListOfNonExistentFields(List<String> list, Node type, boolean excludeStandard, boolean excludeTransient) {
|
||||
static List<Integer> createListOfNonExistentFields(List<String> list, JavacNode type, boolean excludeStandard, boolean excludeTransient) {
|
||||
boolean[] matched = new boolean[list.size()];
|
||||
|
||||
for ( Node child : type.down() ) {
|
||||
if ( list.isEmpty() ) break;
|
||||
if ( child.getKind() != Kind.FIELD ) continue;
|
||||
for (JavacNode child : type.down()) {
|
||||
if (list.isEmpty()) break;
|
||||
if (child.getKind() != Kind.FIELD) continue;
|
||||
JCVariableDecl field = (JCVariableDecl)child.get();
|
||||
if ( excludeStandard ) {
|
||||
if ( (field.mods.flags & Flags.STATIC) != 0 ) continue;
|
||||
if ( field.name.toString().startsWith("$") ) continue;
|
||||
if (excludeStandard) {
|
||||
if ((field.mods.flags & Flags.STATIC) != 0) continue;
|
||||
if (field.name.toString().startsWith("$")) continue;
|
||||
}
|
||||
if ( excludeTransient && (field.mods.flags & Flags.TRANSIENT) != 0 ) continue;
|
||||
|
||||
if (excludeTransient && (field.mods.flags & Flags.TRANSIENT) != 0) continue;
|
||||
|
||||
int idx = list.indexOf(child.getName());
|
||||
if ( idx > -1 ) matched[idx] = true;
|
||||
if (idx > -1) matched[idx] = true;
|
||||
}
|
||||
|
||||
List<Integer> problematic = List.nil();
|
||||
for ( int i = 0 ; i < list.size() ; i++ ) {
|
||||
if ( !matched[i] ) problematic = problematic.append(i);
|
||||
for (int i = 0 ; i < list.size() ; i++) {
|
||||
if (!matched[i]) problematic = problematic.append(i);
|
||||
}
|
||||
|
||||
return problematic;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -54,13 +54,13 @@ public class PatchFixes {
|
||||
|
||||
int count = 0;
|
||||
for (int i = 0; i < in.length; i++) {
|
||||
if ( in[i] == null || !((Boolean)f.get(in[i])).booleanValue() ) count++;
|
||||
if (in[i] == null || !((Boolean)f.get(in[i])).booleanValue()) count++;
|
||||
}
|
||||
if (count == in.length) return in;
|
||||
SimpleName[] newSimpleNames = new SimpleName[count];
|
||||
count = 0;
|
||||
for (int i = 0; i < in.length; i++) {
|
||||
if ( in[i] == null || !((Boolean)f.get(in[i])).booleanValue() ) newSimpleNames[count++] = in[i];
|
||||
if (in[i] == null || !((Boolean)f.get(in[i])).booleanValue()) newSimpleNames[count++] = in[i];
|
||||
}
|
||||
return newSimpleNames;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user