mirror of
https://github.com/tiennm99/lombok.git
synced 2026-10-03 07:13:15 +00:00
Massive performance improvements, and a few potentially breaking changes for other lombok plugin developers.
This commit is contained in:
1 parent
7a50b9a634
commit
9630fc96e8
16 files changed
+599
-253
No files matched your search
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2009 The Project Lombok Authors.
|
||||
* Copyright (C) 2009-2013 The Project Lombok Authors.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
@@ -30,7 +30,6 @@ import java.lang.reflect.ParameterizedType;
|
||||
import java.lang.reflect.Type;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.IdentityHashMap;
|
||||
import java.util.List;
|
||||
@@ -54,15 +53,15 @@ public abstract class AST<A extends AST<A, L, N>, L extends LombokNode<A, L, N>,
|
||||
private L top;
|
||||
private final String fileName;
|
||||
private final String packageDeclaration;
|
||||
private final Collection<String> imports;
|
||||
private final ImportList imports;
|
||||
Map<N, Void> identityDetector = new IdentityHashMap<N, Void>();
|
||||
private Map<N, L> nodeMap = new IdentityHashMap<N, L>();
|
||||
private boolean changed = false;
|
||||
|
||||
protected AST(String fileName, String packageDeclaration, Collection<String> imports) {
|
||||
protected AST(String fileName, String packageDeclaration, ImportList imports) {
|
||||
this.fileName = fileName == null ? "(unknown).java" : fileName;
|
||||
this.packageDeclaration = packageDeclaration;
|
||||
this.imports = Collections.unmodifiableCollection(new ArrayList<String>(imports));
|
||||
this.imports = imports;
|
||||
}
|
||||
|
||||
public void setChanged() {
|
||||
@@ -96,7 +95,7 @@ public abstract class AST<A extends AST<A, L, N>, L extends LombokNode<A, L, N>,
|
||||
*
|
||||
* Example: "java.util.IOException".
|
||||
*/
|
||||
public final Collection<String> getImportStatements() {
|
||||
public final ImportList getImportList() {
|
||||
return imports;
|
||||
}
|
||||
|
||||
@@ -159,8 +158,8 @@ public abstract class AST<A extends AST<A, L, N>, L extends LombokNode<A, L, N>,
|
||||
oldChild.parent = targetNode;
|
||||
}
|
||||
|
||||
targetNode.children.clear();
|
||||
((List)targetNode.children).addAll(children);
|
||||
targetNode.children = ImmutableList.copyOf(children);
|
||||
|
||||
return targetNode;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2009-2012 The Project Lombok Authors.
|
||||
* Copyright (C) 2009-2013 The Project Lombok Authors.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
@@ -435,23 +435,16 @@ public class AnnotationValues<A extends Annotation> {
|
||||
}
|
||||
|
||||
/* 2. Walk through non-star imports and search for a match. */ {
|
||||
for (String im : ast == null ? Collections.<String>emptyList() : ast.getImportStatements()) {
|
||||
if (im.endsWith(".*")) continue;
|
||||
int idx = im.lastIndexOf('.');
|
||||
String simple = idx == -1 ? im : im.substring(idx+1);
|
||||
if (simple.equals(prefix)) {
|
||||
return im + typeName.substring(prefix.length());
|
||||
}
|
||||
if (prefix.equals(typeName)) {
|
||||
String fqn = ast.getImportList().getFullyQualifiedNameForSimpleName(typeName);
|
||||
if (fqn != null) return fqn;
|
||||
}
|
||||
}
|
||||
|
||||
/* 3. Walk through star imports and, if they start with "java.", use Class.forName based resolution. */ {
|
||||
List<String> imports = ast == null ? Collections.<String>emptyList() : new ArrayList<String>(ast.getImportStatements());
|
||||
imports.add("java.lang.*");
|
||||
for (String im : imports) {
|
||||
if (!im.endsWith(".*") || !im.startsWith("java.")) continue;
|
||||
for (String potential : ast.getImportList().applyNameToStarImports("java", typeName)) {
|
||||
try {
|
||||
Class<?> c = Class.forName(im.substring(0, im.length()-1) + typeName);
|
||||
Class<?> c = Class.forName(potential);
|
||||
if (c != null) return c.getName();
|
||||
} catch (Throwable t) {
|
||||
//Class.forName failed for whatever reason - it most likely does not exist, continue.
|
||||
|
||||
@@ -0,0 +1,43 @@
|
||||
/*
|
||||
* Copyright (C) 2013 The Project Lombok Authors.
|
||||
*
|
||||
* 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.Collection;
|
||||
|
||||
public interface ImportList {
|
||||
/**
|
||||
* If there is an explicit import of the stated unqualified type name, return that. Otherwise, return null.
|
||||
*/
|
||||
String getFullyQualifiedNameForSimpleName(String unqualified);
|
||||
|
||||
/**
|
||||
* Returns true if the package name is explicitly star-imported, OR the packageName refers to this source file's own package name, OR packageName is 'java.lang'.
|
||||
*/
|
||||
boolean hasStarImport(String packageName);
|
||||
|
||||
/**
|
||||
* Takes all explicit non-static star imports whose first element is equal to {@code startsWith}, replaces the star with {@code unqualified}, and returns these.
|
||||
*/
|
||||
Collection<String> applyNameToStarImports(String startsWith, String unqualified);
|
||||
|
||||
String applyUnqualifiedNameToPackage(String unqualified);
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2009-2011 The Project Lombok Authors.
|
||||
* Copyright (C) 2009-2013 The Project Lombok Authors.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
@@ -42,7 +42,7 @@ public abstract class LombokNode<A extends AST<A, L, N>, L extends LombokNode<A,
|
||||
protected final A ast;
|
||||
protected final Kind kind;
|
||||
protected final N node;
|
||||
protected final List<L> children;
|
||||
protected ImmutableList<L> children;
|
||||
protected L parent;
|
||||
|
||||
/** structurally significant are those nodes that can be annotated in java 1.6 or are method-like toplevels,
|
||||
@@ -62,7 +62,7 @@ public abstract class LombokNode<A extends AST<A, L, N>, L extends LombokNode<A,
|
||||
this.ast = ast;
|
||||
this.kind = kind;
|
||||
this.node = node;
|
||||
this.children = children == null ? new ArrayList<L>() : children;
|
||||
this.children = children != null ? ImmutableList.copyOf(children) : ImmutableList.<L>of();
|
||||
for (L child : this.children) {
|
||||
child.parent = (L) this;
|
||||
if (!child.isStructurallySignificant)
|
||||
@@ -91,12 +91,12 @@ public abstract class LombokNode<A extends AST<A, L, N>, L extends LombokNode<A,
|
||||
}
|
||||
|
||||
/**
|
||||
* Convenient shortcut to the owning ast object's {@code getImportStatements} method.
|
||||
* Convenient shortcut to the owning ast object's {@code getImportList} method.
|
||||
*
|
||||
* @see AST#getImportStatements()
|
||||
* @see AST#getImportList()
|
||||
*/
|
||||
public Collection<String> getImportStatements() {
|
||||
return ast.getImportStatements();
|
||||
public ImportList getImportList() {
|
||||
return ast.getImportList();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -120,35 +120,6 @@ public abstract class LombokNode<A extends AST<A, L, N>, L extends LombokNode<A,
|
||||
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({"rawtypes", "unchecked"})
|
||||
public L replaceWith(N newN, Kind newNodeKind) {
|
||||
ast.setChanged();
|
||||
L newNode = ast.buildTree(newN, newNodeKind);
|
||||
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.setChanged();
|
||||
ast.replaceStatementInNode(get(), oldN, newN);
|
||||
}
|
||||
|
||||
public Kind getKind() {
|
||||
return kind;
|
||||
}
|
||||
@@ -204,12 +175,9 @@ public abstract class LombokNode<A extends AST<A, L, N>, L extends LombokNode<A,
|
||||
|
||||
/**
|
||||
* 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);
|
||||
public ImmutableList<L> down() {
|
||||
return children;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -235,13 +203,13 @@ public abstract class LombokNode<A extends AST<A, L, N>, L extends LombokNode<A,
|
||||
*
|
||||
* Does not change the underlying (javac/Eclipse) AST, only the wrapped view.
|
||||
*/
|
||||
@SuppressWarnings({"rawtypes", "unchecked"})
|
||||
@SuppressWarnings({"unchecked"})
|
||||
public L add(N newChild, Kind newChildKind) {
|
||||
ast.setChanged();
|
||||
L n = ast.buildTree(newChild, newChildKind);
|
||||
if (n == null) return null;
|
||||
n.parent = (L) this;
|
||||
((List)children).add(n);
|
||||
children = children.append(n);
|
||||
return n;
|
||||
}
|
||||
|
||||
@@ -267,7 +235,7 @@ public abstract class LombokNode<A extends AST<A, L, N>, L extends LombokNode<A,
|
||||
for (LombokNode child : children) child.gatherAndRemoveChildren(map);
|
||||
ast.identityDetector.remove(get());
|
||||
map.put(get(), (L) this);
|
||||
children.clear();
|
||||
children = ImmutableList.of();
|
||||
ast.getNodeMap().remove(get());
|
||||
}
|
||||
|
||||
@@ -278,7 +246,7 @@ public abstract class LombokNode<A extends AST<A, L, N>, L extends LombokNode<A,
|
||||
*/
|
||||
public void removeChild(L child) {
|
||||
ast.setChanged();
|
||||
children.remove(child);
|
||||
children = children.removeElement(child);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2009-2012 The Project Lombok Authors.
|
||||
* Copyright (C) 2009-2013 The Project Lombok Authors.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
@@ -21,12 +21,7 @@
|
||||
*/
|
||||
package lombok.core;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
@@ -40,24 +35,23 @@ import java.util.Map;
|
||||
* <ul><li>foo.Spork</li><li>Spork</li><li>foo.*</li></ul>
|
||||
*/
|
||||
public class TypeLibrary {
|
||||
private final Map<String, List<String>> keyToFqnMap;
|
||||
private final String singletonValue;
|
||||
private final List<String> singletonKeys;
|
||||
private final Map<String, String> unqualifiedToQualifiedMap;
|
||||
private final String unqualified, qualified;
|
||||
|
||||
public TypeLibrary() {
|
||||
keyToFqnMap = new HashMap<String, List<String>>();
|
||||
singletonKeys = null;
|
||||
singletonValue = null;
|
||||
unqualifiedToQualifiedMap = new HashMap<String, String>();
|
||||
unqualified = null;
|
||||
qualified = null;
|
||||
}
|
||||
|
||||
private TypeLibrary(String fqnSingleton) {
|
||||
keyToFqnMap = null;
|
||||
singletonValue = fqnSingleton;
|
||||
unqualifiedToQualifiedMap = null;
|
||||
qualified = fqnSingleton;
|
||||
int idx = fqnSingleton.lastIndexOf('.');
|
||||
if (idx == -1) {
|
||||
singletonKeys = Collections.singletonList(fqnSingleton);
|
||||
unqualified = fqnSingleton;
|
||||
} else {
|
||||
singletonKeys = Arrays.asList(fqnSingleton, fqnSingleton.substring(idx + 1), fqnSingleton.substring(0, idx) + ".*");
|
||||
unqualified = fqnSingleton.substring(idx + 1);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -71,42 +65,28 @@ public class TypeLibrary {
|
||||
* @param fullyQualifiedTypeName the FQN type name, such as 'java.lang.String'.
|
||||
*/
|
||||
public void addType(String fullyQualifiedTypeName) {
|
||||
if (keyToFqnMap == null) throw new IllegalStateException("SingleType library");
|
||||
fullyQualifiedTypeName = fullyQualifiedTypeName.replace("$", ".");
|
||||
int idx = fullyQualifiedTypeName.lastIndexOf('.');
|
||||
if (idx == -1) throw new IllegalArgumentException(
|
||||
"Only fully qualified types are allowed (and stuff in the default package is not palatable to us either!)");
|
||||
String unqualified = fullyQualifiedTypeName.substring(idx + 1);
|
||||
if (unqualifiedToQualifiedMap == null) throw new IllegalStateException("SingleType library");
|
||||
|
||||
fullyQualifiedTypeName = fullyQualifiedTypeName.replace("$", ".");
|
||||
final String simpleName = fullyQualifiedTypeName.substring(idx +1);
|
||||
final String packageName = fullyQualifiedTypeName.substring(0, idx);
|
||||
|
||||
if (keyToFqnMap.put(fullyQualifiedTypeName, Collections.singletonList(fullyQualifiedTypeName)) != null) return;
|
||||
|
||||
addToMap(simpleName, fullyQualifiedTypeName);
|
||||
addToMap(packageName + ".*", fullyQualifiedTypeName);
|
||||
}
|
||||
|
||||
private TypeLibrary addToMap(String keyName, String fullyQualifiedTypeName) {
|
||||
List<String> list = keyToFqnMap.get(keyName);
|
||||
if (list == null) {
|
||||
list = new ArrayList<String>();
|
||||
keyToFqnMap.put(keyName, list);
|
||||
}
|
||||
|
||||
list.add(fullyQualifiedTypeName);
|
||||
return this;
|
||||
unqualifiedToQualifiedMap.put(unqualified, fullyQualifiedTypeName);
|
||||
unqualifiedToQualifiedMap.put(fullyQualifiedTypeName, fullyQualifiedTypeName);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns all items in the type library that may be a match to the provided type.
|
||||
* Translates an unqualified name such as 'String' to 'java.lang.String', _if_ you added 'java.lang.String' to the library via the {@code addType} method.
|
||||
* Also returns the input if it is equal to a fully qualified name added to this type library.
|
||||
*
|
||||
* @param typeReference something like 'String', 'java.lang.String', or 'java.lang.*'.
|
||||
* @return A list of Fully Qualified Names for all types in the library that fit the reference.
|
||||
* Returns null if it does not match any type in this type library.
|
||||
*/
|
||||
public Collection<String> findCompatible(String typeReference) {
|
||||
if (singletonKeys != null) return singletonKeys.contains(typeReference) ? Collections.singletonList(singletonValue) : Collections.<String>emptyList();
|
||||
|
||||
List<String> result = keyToFqnMap.get(typeReference);
|
||||
return result == null ? Collections.<String>emptyList() : Collections.unmodifiableList(result);
|
||||
public String toQualified(String typeReference) {
|
||||
if (unqualifiedToQualifiedMap == null) {
|
||||
if (typeReference.equals(unqualified) || typeReference.equals(qualified)) return qualified;
|
||||
return null;
|
||||
}
|
||||
return unqualifiedToQualifiedMap.get(typeReference);
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2009-2011 The Project Lombok Authors.
|
||||
* Copyright (C) 2009-2013 The Project Lombok Authors.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
@@ -21,11 +21,6 @@
|
||||
*/
|
||||
package lombok.core;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
import lombok.core.AST.Kind;
|
||||
|
||||
/**
|
||||
@@ -35,60 +30,54 @@ import lombok.core.AST.Kind;
|
||||
* and this importer also can't find inner types from superclasses/interfaces.
|
||||
*/
|
||||
public class TypeResolver {
|
||||
private Collection<String> imports;
|
||||
private ImportList imports;
|
||||
|
||||
/**
|
||||
* Creates a new TypeResolver that can be used to resolve types in a source file with the given package and import statements.
|
||||
*/
|
||||
public TypeResolver(String packageString, Collection<String> importStrings) {
|
||||
this.imports = makeImportList(packageString, importStrings);
|
||||
}
|
||||
|
||||
private static Collection<String> makeImportList(String packageString, Collection<String> importStrings) {
|
||||
Set<String> imports = new HashSet<String>();
|
||||
if (packageString != null) imports.add(packageString + ".*");
|
||||
imports.addAll(importStrings == null ? Collections.<String>emptySet() : importStrings);
|
||||
imports.add("java.lang.*");
|
||||
return imports;
|
||||
public TypeResolver(ImportList importList) {
|
||||
this.imports = importList;
|
||||
}
|
||||
|
||||
// private static ImportList makeImportList(String packageString, Collection<String> importStrings) {
|
||||
// Set<String> imports = new HashSet<String>();
|
||||
// if (packageString != null) imports.add(packageString + ".*");
|
||||
// imports.addAll(importStrings == null ? Collections.<String>emptySet() : importStrings);
|
||||
// imports.add("java.lang.*");
|
||||
// return imports;
|
||||
// }
|
||||
//
|
||||
public boolean typeMatches(LombokNode<?, ?, ?> context, String fqn, String typeRef) {
|
||||
return !findTypeMatches(context, TypeLibrary.createLibraryForSingleType(fqn), typeRef).isEmpty();
|
||||
return typeRefToFullyQualifiedName(context, TypeLibrary.createLibraryForSingleType(fqn), typeRef) != null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds type matches for the stated type reference. The provided context is scanned for local type names
|
||||
* 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(LombokNode<?, ?, ?> context, TypeLibrary library, String typeRef) {
|
||||
public String typeRefToFullyQualifiedName(LombokNode<?, ?, ?> context, TypeLibrary library, String typeRef) {
|
||||
// When asking if 'Foo' could possibly be referring to 'bar.Baz', the answer is obviously no.
|
||||
Collection<String> potentialMatches = library.findCompatible(typeRef);
|
||||
if (potentialMatches.isEmpty()) return Collections.emptyList();
|
||||
String qualified = library.toQualified(typeRef);
|
||||
if (qualified == null) return null;
|
||||
|
||||
// If input type appears to be fully qualified, we found a winner.
|
||||
int idx = typeRef.indexOf('.');
|
||||
if (idx > -1) return potentialMatches;
|
||||
// When asking if 'lombok.Getter' could possibly be referring to 'lombok.Getter', the answer is obviously yes.
|
||||
if (typeRef.equals(qualified)) return typeRef;
|
||||
|
||||
// If there's an import statement that explicitly imports a 'Getter' that isn't any of our potentials, return no matches,
|
||||
// because if you want to know if 'Foo' could refer to 'bar.Foo' when 'baz.Foo' is explicitly imported, the answer is no.
|
||||
if (nameConflictInImportList(typeRef, potentialMatches)) return Collections.emptyList();
|
||||
// When asking if 'Getter' could possibly be referring to 'lombok.Getter' if 'import lombok.Getter;' is in the source file, the answer is yes.
|
||||
String fromExplicitImport = imports.getFullyQualifiedNameForSimpleName(typeRef);
|
||||
if (fromExplicitImport != null) {
|
||||
// ... and if 'import foobar.Getter;' is in the source file, the answer is no.
|
||||
return fromExplicitImport.equals(qualified) ? qualified : null;
|
||||
}
|
||||
|
||||
// Check if any of our potentials are even imported in the first place. If not: no matches.
|
||||
// Note that (ourPackage.*) is added to the imports.
|
||||
potentialMatches = eliminateImpossibleMatches(potentialMatches, library);
|
||||
if (potentialMatches.isEmpty()) return Collections.emptyList();
|
||||
// When asking if 'Getter' could possibly be referring to 'lombok.Getter' and 'import lombok.*; / package lombok;' isn't in the source file. the answer is no.
|
||||
String pkgName = qualified.substring(0, qualified.length() - typeRef.length() - 1);
|
||||
if (!imports.hasStarImport(pkgName)) return null;
|
||||
|
||||
// Now the hard part - inner classes or method local classes in our own scope.
|
||||
// For method locals, this refers to any statements that are 'above' the type reference with the same name.
|
||||
// For inners, this refers to siblings of us or any parent node that are type declarations.
|
||||
// Now the hard part: Given that there is a star import, 'Getter' most likely refers to 'lombok.Getter', but type shadowing may occur in which case it doesn't.
|
||||
LombokNode<?, ?, ?> n = context;
|
||||
|
||||
mainLoop:
|
||||
while (n != null) {
|
||||
if (n.getKind() == Kind.TYPE && typeRef.equals(n.getName())) {
|
||||
// Our own class or one of our outer classes is named 'typeRef' so that's what 'typeRef' is referring to, not one of our type library classes.
|
||||
return Collections.emptyList();
|
||||
return null;
|
||||
}
|
||||
|
||||
if (n.getKind() == Kind.STATEMENT || n.getKind() == Kind.LOCAL) {
|
||||
@@ -99,7 +88,7 @@ public class TypeResolver {
|
||||
for (LombokNode<?, ?, ?> child : newN.down()) {
|
||||
// We found a method local with the same name above our code. That's the one 'typeRef' is referring to, not
|
||||
// anything in the type library we're trying to find, so, no matches.
|
||||
if (child.getKind() == Kind.TYPE && typeRef.equals(child.getName())) return Collections.emptyList();
|
||||
if (child.getKind() == Kind.TYPE && typeRef.equals(child.getName())) return null;
|
||||
if (child == n) break;
|
||||
}
|
||||
}
|
||||
@@ -110,41 +99,14 @@ public class TypeResolver {
|
||||
if (n.getKind() == Kind.TYPE || n.getKind() == Kind.COMPILATION_UNIT) {
|
||||
for (LombokNode<?, ?, ?> child : n.down()) {
|
||||
// Inner class that's visible to us has 'typeRef' as name, so that's the one being referred to, not one of our type library classes.
|
||||
if (child.getKind() == Kind.TYPE && typeRef.equals(child.getName())) return Collections.emptyList();
|
||||
if (child.getKind() == Kind.TYPE && typeRef.equals(child.getName())) return null;
|
||||
}
|
||||
}
|
||||
|
||||
n = n.directUp();
|
||||
}
|
||||
|
||||
// No class in this source file is a match, therefore the potential matches found via the import statements must be it. Return those.
|
||||
return potentialMatches;
|
||||
}
|
||||
|
||||
private Collection<String> eliminateImpossibleMatches(Collection<String> potentialMatches, TypeLibrary library) {
|
||||
Set<String> results = new HashSet<String>();
|
||||
|
||||
for (String importedType : imports) {
|
||||
Collection<String> reduced = new HashSet<String>(library.findCompatible(importedType));
|
||||
reduced.retainAll(potentialMatches);
|
||||
results.addAll(reduced);
|
||||
}
|
||||
|
||||
return results;
|
||||
}
|
||||
|
||||
private boolean nameConflictInImportList(String simpleName, Collection<String> potentialMatches) {
|
||||
for (String importedType : imports) {
|
||||
if (!toSimpleName(importedType).equals(simpleName)) continue;
|
||||
if (potentialMatches.contains(importedType)) continue;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private static String toSimpleName(String typeName) {
|
||||
int idx = typeName.lastIndexOf('.');
|
||||
return idx == -1 ? typeName : typeName.substring(idx+1);
|
||||
return qualified;
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2009-2010 The Project Lombok Authors.
|
||||
* Copyright (C) 2009-2013 The Project Lombok Authors.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
@@ -30,6 +30,7 @@ import java.util.List;
|
||||
|
||||
import lombok.Lombok;
|
||||
import lombok.core.AST;
|
||||
import lombok.core.ImmutableList;
|
||||
|
||||
import org.eclipse.jdt.internal.compiler.ast.ASTNode;
|
||||
import org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration;
|
||||
@@ -55,7 +56,7 @@ public class EclipseAST extends AST<EclipseAST, EclipseNode, ASTNode> {
|
||||
* @param ast The compilation unit, which serves as the top level node in the tree to be built.
|
||||
*/
|
||||
public EclipseAST(CompilationUnitDeclaration ast) {
|
||||
super(toFileName(ast), packageDeclaration(ast), imports(ast));
|
||||
super(toFileName(ast), packageDeclaration(ast), new EclipseImportList(ast));
|
||||
this.compilationUnitDeclaration = ast;
|
||||
setTop(buildCompilationUnit(ast));
|
||||
this.completeParse = isComplete(ast);
|
||||
@@ -67,18 +68,6 @@ public class EclipseAST extends AST<EclipseAST, EclipseNode, ASTNode> {
|
||||
return pkg == null ? null : Eclipse.toQualifiedName(pkg.getImportName());
|
||||
}
|
||||
|
||||
private static Collection<String> imports(CompilationUnitDeclaration cud) {
|
||||
List<String> imports = new ArrayList<String>();
|
||||
if (cud.imports == null) return imports;
|
||||
for (ImportReference imp : cud.imports) {
|
||||
if (imp == null) continue;
|
||||
String qualifiedName = Eclipse.toQualifiedName(imp.getImportName());
|
||||
if ((imp.bits & ASTNode.OnDemand) != 0) qualifiedName += ".*";
|
||||
imports.add(qualifiedName);
|
||||
}
|
||||
return imports;
|
||||
}
|
||||
|
||||
/**
|
||||
* Runs through the entire AST, starting at the compilation unit, calling the provided visitor's visit methods
|
||||
* for each node, depth first.
|
||||
@@ -88,8 +77,10 @@ public class EclipseAST extends AST<EclipseAST, EclipseNode, ASTNode> {
|
||||
}
|
||||
|
||||
void traverseChildren(EclipseASTVisitor visitor, EclipseNode node) {
|
||||
for (EclipseNode child : node.down()) {
|
||||
child.traverse(visitor);
|
||||
ImmutableList<EclipseNode> children = node.down();
|
||||
int len = children.size();
|
||||
for (int i = 0; i < len; i++) {
|
||||
children.get(i).traverse(visitor);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,131 @@
|
||||
/*
|
||||
* Copyright (C) 2013 The Project Lombok Authors.
|
||||
*
|
||||
* 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 static lombok.eclipse.Eclipse.*;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import org.eclipse.jdt.internal.compiler.ast.ASTNode;
|
||||
import org.eclipse.jdt.internal.compiler.ast.CompilationUnitDeclaration;
|
||||
import org.eclipse.jdt.internal.compiler.ast.ImportReference;
|
||||
|
||||
import lombok.core.ImportList;
|
||||
|
||||
public class EclipseImportList implements ImportList {
|
||||
private ImportReference[] imports;
|
||||
private ImportReference pkg;
|
||||
|
||||
public EclipseImportList(CompilationUnitDeclaration cud) {
|
||||
this.pkg = cud.currentPackage;
|
||||
this.imports = cud.imports;
|
||||
}
|
||||
|
||||
@Override public String getFullyQualifiedNameForSimpleName(String unqualified) {
|
||||
if (imports != null) {
|
||||
outer:
|
||||
for (ImportReference imp : imports) {
|
||||
if ((imp.bits & ASTNode.OnDemand) != 0) continue;
|
||||
char[][] tokens = imp.tokens;
|
||||
char[] token = tokens.length == 0 ? new char[0] : tokens[tokens.length - 1];
|
||||
int len = token.length;
|
||||
if (len != unqualified.length()) continue;
|
||||
for (int i = 0; i < len; i++) if (token[i] != unqualified.charAt(i)) continue outer;
|
||||
return toQualifiedName(tokens);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override public boolean hasStarImport(String packageName) {
|
||||
if (isEqual(packageName, pkg)) return true;
|
||||
if ("java.lang".equals(packageName)) return true;
|
||||
if (imports != null) for (ImportReference imp : imports) {
|
||||
if ((imp.bits & ASTNode.OnDemand) == 0) continue;
|
||||
if (imp.isStatic()) continue;
|
||||
if (isEqual(packageName, imp)) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private static boolean isEqual(String packageName, ImportReference pkgOrStarImport) {
|
||||
if (pkgOrStarImport == null || pkgOrStarImport.tokens == null || pkgOrStarImport.tokens.length == 0) return packageName.isEmpty();
|
||||
int pos = 0;
|
||||
int len = packageName.length();
|
||||
for (int i = 0; i < pkgOrStarImport.tokens.length; i++) {
|
||||
if (i != 0) {
|
||||
if (pos >= len) return false;
|
||||
if (packageName.charAt(pos++) != '.') return false;
|
||||
}
|
||||
for (int j = 0; j < pkgOrStarImport.tokens[i].length; j++) {
|
||||
if (pos >= len) return false;
|
||||
if (packageName.charAt(pos++) != pkgOrStarImport.tokens[i][j]) return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override public Collection<String> applyNameToStarImports(String startsWith, String name) {
|
||||
List<String> out = Collections.emptyList();
|
||||
|
||||
if (pkg != null && pkg.tokens != null && pkg.tokens.length != 0) {
|
||||
char[] first = pkg.tokens[0];
|
||||
int len = first.length;
|
||||
boolean match = true;
|
||||
if (startsWith.length() == len) {
|
||||
for (int i = 0; match && i < len; i++) {
|
||||
if (startsWith.charAt(i) != first[i]) match = false;
|
||||
}
|
||||
if (match) out.add(toQualifiedName(pkg.tokens) + "." + name);
|
||||
}
|
||||
}
|
||||
|
||||
if (imports != null) {
|
||||
outer:
|
||||
for (ImportReference imp : imports) {
|
||||
if ((imp.bits & ASTNode.OnDemand) == 0) continue;
|
||||
if (imp.isStatic()) continue;
|
||||
if (imp.tokens == null || imp.tokens.length == 0) continue;
|
||||
char[] firstToken = imp.tokens[0];
|
||||
if (firstToken.length != startsWith.length()) continue;
|
||||
for (int i = 0; i < firstToken.length; i++) if (startsWith.charAt(i) != firstToken[i]) continue outer;
|
||||
String fqn = toQualifiedName(imp.tokens) + "." + name;
|
||||
if (out.isEmpty()) out = Collections.singletonList(fqn);
|
||||
else if (out.size() == 1) {
|
||||
out = new ArrayList<String>(out);
|
||||
out.add(fqn);
|
||||
} else {
|
||||
out.add(fqn);
|
||||
}
|
||||
}
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
@Override public String applyUnqualifiedNameToPackage(String unqualified) {
|
||||
if (pkg == null || pkg.tokens == null || pkg.tokens.length == 0) return unqualified;
|
||||
return toQualifiedName(pkg.tokens) + "." + unqualified;
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2009-2012 The Project Lombok Authors.
|
||||
* Copyright (C) 2009-2013 The Project Lombok Authors.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
@@ -218,30 +218,27 @@ public class HandlerLibrary {
|
||||
* @param annotation 'node.get()' - convenience parameter.
|
||||
*/
|
||||
public void handleAnnotation(CompilationUnitDeclaration ast, EclipseNode annotationNode, org.eclipse.jdt.internal.compiler.ast.Annotation annotation, long priority) {
|
||||
String pkgName = annotationNode.getPackageDeclaration();
|
||||
Collection<String> imports = annotationNode.getImportStatements();
|
||||
|
||||
TypeResolver resolver = new TypeResolver(pkgName, imports);
|
||||
TypeResolver resolver = new TypeResolver(annotationNode.getImportList());
|
||||
TypeReference rawType = annotation.type;
|
||||
if (rawType == null) return;
|
||||
|
||||
for (String fqn : resolver.findTypeMatches(annotationNode, typeLibrary, toQualifiedName(annotation.type.getTypeName()))) {
|
||||
AnnotationHandlerContainer<?> container = annotationHandlers.get(fqn);
|
||||
if (container == null) continue;
|
||||
if (priority != container.getPriority()) continue;
|
||||
|
||||
if (!annotationNode.isCompleteParse() && container.deferUntilPostDiet()) {
|
||||
if (needsHandling(annotation)) container.preHandle(annotation, annotationNode);
|
||||
continue;
|
||||
}
|
||||
|
||||
try {
|
||||
if (checkAndSetHandled(annotation)) container.handle(annotation, annotationNode);
|
||||
} catch (AnnotationValueDecodeFail fail) {
|
||||
fail.owner.setError(fail.getMessage(), fail.idx);
|
||||
} catch (Throwable t) {
|
||||
error(ast, String.format("Lombok annotation handler %s failed", container.handler.getClass()), t);
|
||||
}
|
||||
String fqn = resolver.typeRefToFullyQualifiedName(annotationNode, typeLibrary, toQualifiedName(annotation.type.getTypeName()));
|
||||
if (fqn == null) return;
|
||||
AnnotationHandlerContainer<?> container = annotationHandlers.get(fqn);
|
||||
if (container == null) return;
|
||||
if (priority != container.getPriority()) return;
|
||||
|
||||
if (!annotationNode.isCompleteParse() && container.deferUntilPostDiet()) {
|
||||
if (needsHandling(annotation)) container.preHandle(annotation, annotationNode);
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
if (checkAndSetHandled(annotation)) container.handle(annotation, annotationNode);
|
||||
} catch (AnnotationValueDecodeFail fail) {
|
||||
fail.owner.setError(fail.getMessage(), fail.idx);
|
||||
} catch (Throwable t) {
|
||||
error(ast, String.format("Lombok annotation handler %s failed", container.handler.getClass()), t);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -290,7 +290,7 @@ public class EclipseHandlerUtil {
|
||||
if (!lastPartA.equals(lastPartB)) return false;
|
||||
String typeName = toQualifiedName(typeRef.getTypeName());
|
||||
|
||||
TypeResolver resolver = new TypeResolver(node.getPackageDeclaration(), node.getImportStatements());
|
||||
TypeResolver resolver = new TypeResolver(node.getImportList());
|
||||
return resolver.typeMatches(node, type.getName(), typeName);
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2009-2012 The Project Lombok Authors.
|
||||
* Copyright (C) 2009-2013 The Project Lombok Authors.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
@@ -231,23 +231,23 @@ public class HandlerLibrary {
|
||||
* @param annotation 'node.get()' - convenience parameter.
|
||||
*/
|
||||
public void handleAnnotation(JCCompilationUnit unit, JavacNode node, JCAnnotation annotation, long priority) {
|
||||
TypeResolver resolver = new TypeResolver(node.getPackageDeclaration(), node.getImportStatements());
|
||||
TypeResolver resolver = new TypeResolver(node.getImportList());
|
||||
String rawType = annotation.annotationType.toString();
|
||||
for (String fqn : resolver.findTypeMatches(node, typeLibrary, rawType)) {
|
||||
AnnotationHandlerContainer<?> container = annotationHandlers.get(fqn);
|
||||
if (container == null) continue;
|
||||
|
||||
try {
|
||||
if (container.getPriority() == priority) {
|
||||
if (checkAndSetHandled(annotation)) container.handle(node);
|
||||
}
|
||||
} catch (AnnotationValueDecodeFail fail) {
|
||||
fail.owner.setError(fail.getMessage(), fail.idx);
|
||||
} catch (Throwable t) {
|
||||
String sourceName = "(unknown).java";
|
||||
if (unit != null && unit.sourcefile != null) sourceName = unit.sourcefile.getName();
|
||||
javacError(String.format("Lombok annotation handler %s failed on " + sourceName, container.handler.getClass()), t);
|
||||
String fqn = resolver.typeRefToFullyQualifiedName(node, typeLibrary, rawType);
|
||||
if (fqn == null) return;
|
||||
AnnotationHandlerContainer<?> container = annotationHandlers.get(fqn);
|
||||
if (container == null) return;
|
||||
|
||||
try {
|
||||
if (container.getPriority() == priority) {
|
||||
if (checkAndSetHandled(annotation)) container.handle(node);
|
||||
}
|
||||
} catch (AnnotationValueDecodeFail fail) {
|
||||
fail.owner.setError(fail.getMessage(), fail.idx);
|
||||
} catch (Throwable t) {
|
||||
String sourceName = "(unknown).java";
|
||||
if (unit != null && unit.sourcefile != null) sourceName = unit.sourcefile.getName();
|
||||
javacError(String.format("Lombok annotation handler %s failed on " + sourceName, container.handler.getClass()), t);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -46,7 +46,6 @@ import com.sun.tools.javac.tree.JCTree.JCCompilationUnit;
|
||||
import com.sun.tools.javac.tree.JCTree.JCExpression;
|
||||
import com.sun.tools.javac.tree.JCTree.JCFieldAccess;
|
||||
import com.sun.tools.javac.tree.JCTree.JCIdent;
|
||||
import com.sun.tools.javac.tree.JCTree.JCImport;
|
||||
import com.sun.tools.javac.tree.JCTree.JCMethodDecl;
|
||||
import com.sun.tools.javac.tree.JCTree.JCStatement;
|
||||
import com.sun.tools.javac.tree.JCTree.JCVariableDecl;
|
||||
@@ -78,7 +77,7 @@ public class JavacAST extends AST<JavacAST, JavacNode, JCTree> {
|
||||
* @param top The compilation unit, which serves as the top level node in the tree to be built.
|
||||
*/
|
||||
public JavacAST(Messager messager, Context context, JCCompilationUnit top) {
|
||||
super(sourceName(top), packageDeclaration(top), imports(top));
|
||||
super(sourceName(top), packageDeclaration(top), new JavacImportList(top));
|
||||
setTop(buildCompilationUnit(top));
|
||||
this.context = context;
|
||||
this.messager = messager;
|
||||
@@ -98,16 +97,6 @@ public class JavacAST extends AST<JavacAST, JavacNode, JCTree> {
|
||||
return (cu.pid instanceof JCFieldAccess || cu.pid instanceof JCIdent) ? cu.pid.toString() : null;
|
||||
}
|
||||
|
||||
private static Collection<String> imports(JCCompilationUnit cu) {
|
||||
List<String> imports = new ArrayList<String>();
|
||||
for (JCTree def : cu.defs) {
|
||||
if (def instanceof JCImport) {
|
||||
imports.add(((JCImport)def).qualid.toString());
|
||||
}
|
||||
}
|
||||
return imports;
|
||||
}
|
||||
|
||||
public Context getContext() {
|
||||
return context;
|
||||
}
|
||||
@@ -121,9 +110,7 @@ public class JavacAST extends AST<JavacAST, JavacNode, JCTree> {
|
||||
}
|
||||
|
||||
void traverseChildren(JavacASTVisitor visitor, JavacNode node) {
|
||||
for (JavacNode child : new ArrayList<JavacNode>(node.down())) {
|
||||
child.traverse(visitor);
|
||||
}
|
||||
for (JavacNode child : node.down()) child.traverse(visitor);
|
||||
}
|
||||
|
||||
/** @return A Name object generated for the proper name table belonging to this AST. */
|
||||
|
||||
@@ -0,0 +1,105 @@
|
||||
/*
|
||||
* Copyright (C) 2013 The Project Lombok Authors.
|
||||
*
|
||||
* 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.ArrayList;
|
||||
import java.util.Collection;
|
||||
|
||||
import com.sun.tools.javac.tree.JCTree;
|
||||
import com.sun.tools.javac.tree.JCTree.JCCompilationUnit;
|
||||
import com.sun.tools.javac.tree.JCTree.JCExpression;
|
||||
import com.sun.tools.javac.tree.JCTree.JCFieldAccess;
|
||||
import com.sun.tools.javac.tree.JCTree.JCImport;
|
||||
import com.sun.tools.javac.util.List;
|
||||
|
||||
import lombok.core.ImportList;
|
||||
|
||||
public class JavacImportList implements ImportList {
|
||||
private final JCExpression pkg;
|
||||
private final List<JCTree> defs;
|
||||
|
||||
public JavacImportList(JCCompilationUnit cud) {
|
||||
this.pkg = cud.pid;
|
||||
this.defs = cud.defs;
|
||||
}
|
||||
|
||||
@Override public String getFullyQualifiedNameForSimpleName(String unqualified) {
|
||||
for (JCTree def : defs) {
|
||||
if (!(def instanceof JCImport)) continue;
|
||||
JCTree qual = ((JCImport) def).qualid;
|
||||
if (!(qual instanceof JCFieldAccess)) continue;
|
||||
String simpleName = ((JCFieldAccess) qual).name.toString();
|
||||
if (simpleName.equals(unqualified)) return qual.toString();
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override public boolean hasStarImport(String packageName) {
|
||||
if (pkg != null && pkg.toString().equals(packageName)) return true;
|
||||
if ("java.lang".equals(packageName)) return true;
|
||||
|
||||
for (JCTree def : defs) {
|
||||
if (!(def instanceof JCImport)) continue;
|
||||
if (((JCImport) def).staticImport) continue;
|
||||
JCTree qual = ((JCImport) def).qualid;
|
||||
if (!(qual instanceof JCFieldAccess)) continue;
|
||||
String simpleName = ((JCFieldAccess) qual).name.toString();
|
||||
if (!"*".equals(simpleName)) continue;
|
||||
if (packageName.equals(((JCFieldAccess) qual).selected.toString())) return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override public Collection<String> applyNameToStarImports(String startsWith, String name) {
|
||||
ArrayList<String> out = new ArrayList<String>();
|
||||
|
||||
if (pkg != null && topLevelName(pkg).equals(startsWith)) out.add(pkg.toString() + "." + name);
|
||||
|
||||
for (JCTree def : defs) {
|
||||
if (!(def instanceof JCImport)) continue;
|
||||
if (((JCImport) def).staticImport) continue;
|
||||
JCTree qual = ((JCImport) def).qualid;
|
||||
if (!(qual instanceof JCFieldAccess)) continue;
|
||||
String simpleName = ((JCFieldAccess) qual).name.toString();
|
||||
if (!"*".equals(simpleName)) continue;
|
||||
|
||||
String topLevelName = topLevelName(qual);
|
||||
if (topLevelName.equals(startsWith)) {
|
||||
out.add(((JCFieldAccess) qual).selected.toString() + "." + name);
|
||||
}
|
||||
}
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
private String topLevelName(JCTree tree) {
|
||||
while (tree instanceof JCFieldAccess) tree = ((JCFieldAccess) tree).selected;
|
||||
return tree.toString();
|
||||
}
|
||||
|
||||
@Override public String applyUnqualifiedNameToPackage(String unqualified) {
|
||||
if (pkg == null) return unqualified;
|
||||
return pkg.toString() + "." + unqualified;
|
||||
}
|
||||
}
|
||||
@@ -185,7 +185,7 @@ public class JavacHandlerUtil {
|
||||
public static boolean typeMatches(Class<?> type, JavacNode node, JCTree typeNode) {
|
||||
String typeName = typeNode.toString();
|
||||
|
||||
TypeResolver resolver = new TypeResolver(node.getPackageDeclaration(), node.getImportStatements());
|
||||
TypeResolver resolver = new TypeResolver(node.getImportList());
|
||||
return resolver.typeMatches(node, type.getName(), typeName);
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,188 @@
|
||||
/*
|
||||
* Copyright (C) 2013 The Project Lombok Authors.
|
||||
*
|
||||
* 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.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.NoSuchElementException;
|
||||
|
||||
public final class ImmutableList<T> implements Iterable<T> {
|
||||
private Object[] content;
|
||||
private static final ImmutableList<?> EMPTY = new ImmutableList<Object>(new Object[0]);
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public static <T> ImmutableList<T> of() {
|
||||
return (ImmutableList<T>) EMPTY;
|
||||
}
|
||||
|
||||
public static <T> ImmutableList<T> of(T a) {
|
||||
return new ImmutableList<T>(new Object[] {a});
|
||||
}
|
||||
|
||||
public static <T> ImmutableList<T> of(T a, T b) {
|
||||
return new ImmutableList<T>(new Object[] {a, b});
|
||||
}
|
||||
|
||||
public static <T> ImmutableList<T> of(T a, T b, T c) {
|
||||
return new ImmutableList<T>(new Object[] {a, b, c});
|
||||
}
|
||||
|
||||
public static <T> ImmutableList<T> of(T a, T b, T c, T d) {
|
||||
return new ImmutableList<T>(new Object[] {a, b, c, d});
|
||||
}
|
||||
|
||||
public static <T> ImmutableList<T> of(T a, T b, T c, T d, T e) {
|
||||
return new ImmutableList<T>(new Object[] {a, b, c, d, e});
|
||||
}
|
||||
|
||||
public static <T> ImmutableList<T> of(T a, T b, T c, T d, T e, T f, @SuppressWarnings("unchecked") T... g) {
|
||||
Object[] rest = g == null ? new Object[] {null} : g;
|
||||
Object[] val = new Object[rest.length + 6];
|
||||
System.arraycopy(rest, 0, val, 6, rest.length);
|
||||
val[0] = a;
|
||||
val[1] = b;
|
||||
val[2] = c;
|
||||
val[3] = d;
|
||||
val[4] = e;
|
||||
val[5] = f;
|
||||
return new ImmutableList<T>(val);
|
||||
}
|
||||
|
||||
public static <T> ImmutableList<T> copyOf(Collection<? extends T> list) {
|
||||
return new ImmutableList<T>(list.toArray());
|
||||
}
|
||||
|
||||
public static <T> ImmutableList<T> copyOf(Iterable<? extends T> iterable) {
|
||||
List<T> list = new ArrayList<T>();
|
||||
for (T o : iterable) list.add(o);
|
||||
return copyOf(list);
|
||||
}
|
||||
|
||||
private ImmutableList(Object[] content) {
|
||||
this.content = content;
|
||||
}
|
||||
|
||||
public ImmutableList<T> replaceElementAt(int idx, T newValue) {
|
||||
Object[] newContent = content.clone();
|
||||
newContent[idx] = newValue;
|
||||
return new ImmutableList<T>(newContent);
|
||||
}
|
||||
|
||||
public ImmutableList<T> append(T newValue) {
|
||||
int len = content.length;
|
||||
Object[] newContent = new Object[len + 1];
|
||||
System.arraycopy(content, 0, newContent, 0, len);
|
||||
newContent[len] = newValue;
|
||||
return new ImmutableList<T>(newContent);
|
||||
}
|
||||
|
||||
public ImmutableList<T> prepend(T newValue) {
|
||||
int len = content.length;
|
||||
Object[] newContent = new Object[len + 1];
|
||||
System.arraycopy(content, 0, newContent, 1, len);
|
||||
newContent[0] = newValue;
|
||||
return new ImmutableList<T>(newContent);
|
||||
}
|
||||
|
||||
public int indexOf(T val) {
|
||||
int len = content.length;
|
||||
if (val == null) {
|
||||
for (int i = 0; i < len; i++) if (content[i] == null) return i;
|
||||
return -1;
|
||||
}
|
||||
|
||||
for (int i = 0; i < len; i++) if (val.equals(content[i])) return i;
|
||||
return -1;
|
||||
}
|
||||
|
||||
public ImmutableList<T> removeElement(T val) {
|
||||
int idx = indexOf(val);
|
||||
return idx == -1 ? this : removeElementAt(idx);
|
||||
}
|
||||
|
||||
public ImmutableList<T> removeElementAt(int idx) {
|
||||
int len = content.length;
|
||||
Object[] newContent = new Object[len - 1];
|
||||
if (idx > 0) System.arraycopy(content, 0, newContent, 0, idx);
|
||||
if (idx < len - 1) System.arraycopy(content, idx + 1, newContent, idx, len - idx - 1);
|
||||
return new ImmutableList<T>(newContent);
|
||||
}
|
||||
|
||||
public boolean isEmpty() {
|
||||
return content.length == 0;
|
||||
}
|
||||
|
||||
public int size() {
|
||||
return content.length;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public T get(int idx) {
|
||||
return (T) content[idx];
|
||||
}
|
||||
|
||||
public boolean contains(T in) {
|
||||
if (in == null) {
|
||||
for (Object e : content) if (e == null) return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
for (Object e : content) if (in.equals(e)) return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
public Iterator<T> iterator() {
|
||||
return new Iterator<T>() {
|
||||
private int idx = 0;
|
||||
@Override public boolean hasNext() {
|
||||
return idx < content.length;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override public T next() {
|
||||
if (idx < content.length) return (T) content[idx++];
|
||||
throw new NoSuchElementException();
|
||||
}
|
||||
|
||||
@Override public void remove() {
|
||||
throw new UnsupportedOperationException("List is immutable");
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@Override public String toString() {
|
||||
return Arrays.toString(content);
|
||||
}
|
||||
|
||||
@Override public boolean equals(Object obj) {
|
||||
if (!(obj instanceof ImmutableList)) return false;
|
||||
if (obj == this) return true;
|
||||
return Arrays.equals(content, ((ImmutableList<?>) obj).content);
|
||||
}
|
||||
|
||||
@Override public int hashCode() {
|
||||
return Arrays.hashCode(content);
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2009-2011 The Project Lombok Authors.
|
||||
* Copyright (C) 2009-2013 The Project Lombok Authors.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
@@ -58,7 +58,9 @@ public class Eclipse {
|
||||
* but we need to deal with it. This turns [[java][lang][String]] into "java.lang.String".
|
||||
*/
|
||||
public static String toQualifiedName(char[][] typeName) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
int len = typeName.length - 1;
|
||||
for (char[] c : typeName) len += c.length;
|
||||
StringBuilder sb = new StringBuilder(len);
|
||||
boolean first = true;
|
||||
for (char[] c : typeName) {
|
||||
sb.append(first ? "" : ".").append(c);
|
||||
|
||||
Reference in new issue
Block a user