diff options
Diffstat (limited to 'src/lombok')
| -rw-r--r-- | src/lombok/Getter.java | 2 | ||||
| -rw-r--r-- | src/lombok/Setter.java | 2 | ||||
| -rw-r--r-- | src/lombok/core/AST.java | 19 | ||||
| -rw-r--r-- | src/lombok/eclipse/Eclipse.java | 23 | ||||
| -rw-r--r-- | src/lombok/eclipse/EclipseAST.java | 70 | ||||
| -rw-r--r-- | src/lombok/eclipse/EclipseASTVisitor.java | 4 | ||||
| -rw-r--r-- | src/lombok/eclipse/HandlerLibrary.java | 12 | ||||
| -rw-r--r-- | src/lombok/eclipse/TransformEclipseAST.java | 11 | ||||
| -rw-r--r-- | src/lombok/eclipse/handlers/HandleData.java | 127 | ||||
| -rw-r--r-- | src/lombok/eclipse/handlers/HandleGetter.java | 66 | ||||
| -rw-r--r-- | src/lombok/eclipse/handlers/HandleSetter.java | 92 | ||||
| -rw-r--r-- | src/lombok/eclipse/handlers/PKG.java | 64 | ||||
| -rw-r--r-- | src/lombok/javac/JavacAST.java | 30 | ||||
| -rw-r--r-- | src/lombok/javac/handlers/HandleGetter.java | 23 | ||||
| -rw-r--r-- | src/lombok/javac/handlers/HandleSetter.java | 25 | ||||
| -rw-r--r-- | src/lombok/javac/handlers/PKG.java | 12 | 
16 files changed, 450 insertions, 132 deletions
| diff --git a/src/lombok/Getter.java b/src/lombok/Getter.java index 7510bf24..d59ea672 100644 --- a/src/lombok/Getter.java +++ b/src/lombok/Getter.java @@ -8,7 +8,5 @@ import java.lang.annotation.Target;  @Target(ElementType.FIELD)  @Retention(RetentionPolicy.SOURCE)  public @interface Getter { -	lombok.AccessLevel DEFAULT_ACCESS_LEVEL = lombok.AccessLevel.PUBLIC; -	  	lombok.AccessLevel value() default lombok.AccessLevel.PUBLIC;  } diff --git a/src/lombok/Setter.java b/src/lombok/Setter.java index acd1d180..b00d4158 100644 --- a/src/lombok/Setter.java +++ b/src/lombok/Setter.java @@ -8,7 +8,5 @@ import java.lang.annotation.Target;  @Target(ElementType.FIELD)  @Retention(RetentionPolicy.SOURCE)  public @interface Setter { -	lombok.AccessLevel DEFAULT_ACCESS_LEVEL = lombok.AccessLevel.PUBLIC; -	  	lombok.AccessLevel value() default lombok.AccessLevel.PUBLIC;  } diff --git a/src/lombok/core/AST.java b/src/lombok/core/AST.java index 2229f9ef..c1186d24 100644 --- a/src/lombok/core/AST.java +++ b/src/lombok/core/AST.java @@ -97,6 +97,10 @@ public abstract class AST<N> {  		protected abstract boolean calculateIsStructurallySignificant(); +		public Node getNodeFor(N obj) { +			return AST.this.get(obj); +		} +		  		public N get() {  			return node;  		} @@ -150,6 +154,19 @@ public abstract class AST<N> {  			return fileName;  		} +		public Node add(N newChild, Kind kind) { +			Node n = buildTree(newChild, kind); +			if ( n == null ) return null; +			n.parent = this; +			return n; +		} +		 +		public Node recursiveSetHandled() { +			this.handled = true; +			for ( Node child : children ) child.recursiveSetHandled(); +			return this; +		} +		  		public abstract void addError(String message);  		public abstract void addWarning(String message); @@ -164,6 +181,8 @@ public abstract class AST<N> {  		}  	} +	protected abstract Node buildTree(N item, Kind kind); +	  	protected static class FieldAccess {  		public final Field field;  		public final int dim; diff --git a/src/lombok/eclipse/Eclipse.java b/src/lombok/eclipse/Eclipse.java index baac26a9..a7286058 100644 --- a/src/lombok/eclipse/Eclipse.java +++ b/src/lombok/eclipse/Eclipse.java @@ -19,37 +19,45 @@ import org.eclipse.core.runtime.ILog;  import org.eclipse.core.runtime.IStatus;  import org.eclipse.core.runtime.Platform;  import org.eclipse.core.runtime.Status; +import org.eclipse.jdt.internal.compiler.ast.ASTNode;  import org.eclipse.jdt.internal.compiler.ast.Annotation;  import org.eclipse.jdt.internal.compiler.ast.ArrayInitializer;  import org.eclipse.jdt.internal.compiler.ast.ClassLiteralAccess; +import org.eclipse.jdt.internal.compiler.ast.CompilationUnitDeclaration;  import org.eclipse.jdt.internal.compiler.ast.Expression;  import org.eclipse.jdt.internal.compiler.ast.Literal;  import org.eclipse.jdt.internal.compiler.ast.MemberValuePair;  import org.eclipse.jdt.internal.compiler.ast.QualifiedNameReference; +import org.eclipse.jdt.internal.compiler.ast.QualifiedTypeReference;  import org.eclipse.jdt.internal.compiler.ast.SingleNameReference;  import org.eclipse.jdt.internal.compiler.ast.TypeReference; +import org.eclipse.jdt.internal.compiler.lookup.TypeConstants;  import org.eclipse.jdt.internal.compiler.lookup.TypeIds;  import org.osgi.framework.Bundle;  public class Eclipse { +	public static final int ECLIPSE_DO_NOT_TOUCH_FLAG = ASTNode.Bit24;  	private Eclipse() {  		//Prevent instantiation  	}  	private static final String DEFAULT_BUNDLE = "org.eclipse.jdt.core"; -	public static void error(String message) { -		error(message, DEFAULT_BUNDLE, null); +	public static final TypeReference TYPEREF_JAVA_LANG_STRING = new QualifiedTypeReference( +			TypeConstants.JAVA_LANG_STRING, new long[] {0, 0, 0}); +	 +	public static void error(CompilationUnitDeclaration cud, String message) { +		error(cud, message, DEFAULT_BUNDLE, null);  	} -	public static void error(String message, Throwable error) { -		error(message, DEFAULT_BUNDLE, error); +	public static void error(CompilationUnitDeclaration cud, String message, Throwable error) { +		error(cud, message, DEFAULT_BUNDLE, error);  	} -	public static void error(String message, String bundleName) { -		error(message, bundleName, null); +	public static void error(CompilationUnitDeclaration cud, String message, String bundleName) { +		error(cud, message, bundleName, null);  	} -	public static void error(String message, String bundleName, Throwable error) { +	public static void error(CompilationUnitDeclaration cud, String message, String bundleName, Throwable error) {  		Bundle bundle = Platform.getBundle(bundleName);  		if ( bundle == null ) {  			System.err.printf("Can't find bundle %s while trying to report error:\n%s\n", bundleName, message); @@ -59,6 +67,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);  	}  	static String toQualifiedName(char[][] typeName) { diff --git a/src/lombok/eclipse/EclipseAST.java b/src/lombok/eclipse/EclipseAST.java index 6c4ce211..850fb8dc 100644 --- a/src/lombok/eclipse/EclipseAST.java +++ b/src/lombok/eclipse/EclipseAST.java @@ -70,21 +70,19 @@ public class EclipseAST extends AST<ASTNode> {  	private class ParseProblem {  		final boolean isWarning;  		final String message; -		final Node node;  		final int sourceStart;  		final int sourceEnd; -		public ParseProblem(boolean isWarning, String message, Node node, int sourceStart, int sourceEnd) { +		public ParseProblem(boolean isWarning, String message, int sourceStart, int sourceEnd) {  			this.isWarning = isWarning;  			this.message = message; -			this.node = node;  			this.sourceStart = sourceStart;  			this.sourceEnd = sourceEnd;  		}  		void addToCompilationResult() { -			addProblemToCompilationResult(getFileName(), (CompilationUnitDeclaration) top().get(), -					isWarning, message, node.get(), sourceStart, sourceEnd); +			addProblemToCompilationResult((CompilationUnitDeclaration) top().get(), +					isWarning, message, sourceStart, sourceEnd);  		}  	} @@ -103,9 +101,11 @@ public class EclipseAST extends AST<ASTNode> {  		propagateProblems();  	} -	static void addProblemToCompilationResult(String fileName, CompilationUnitDeclaration ast, -			boolean isWarning, String message, ASTNode node, int sourceStart, int sourceEnd) { -		char[] fileNameArray = fileName.toCharArray(); +	static void addProblemToCompilationResult(CompilationUnitDeclaration ast, +			boolean isWarning, String message, int sourceStart, int sourceEnd) { +		if ( ast.compilationResult == null ) return; +		char[] fileNameArray = ast.getFileName(); +		if ( fileNameArray == null ) fileNameArray = "(unknown).java".toCharArray();  		int lineNumber = 0;  		int columnNumber = 1;  		CompilationResult result = ast.compilationResult; @@ -218,7 +218,7 @@ public class EclipseAST extends AST<ASTNode> {  		}  		public void addError(String message, int sourceStart, int sourceEnd) { -			addProblem(new ParseProblem(false, message, this, sourceStart, sourceEnd)); +			addProblem(new ParseProblem(false, message, sourceStart, sourceEnd));  		}  		@Override public void addWarning(String message) { @@ -226,7 +226,7 @@ public class EclipseAST extends AST<ASTNode> {  		}  		public void addWarning(String message, int sourceStart, int sourceEnd) { -			addProblem(new ParseProblem(true, message, this, sourceStart, sourceEnd)); +			addProblem(new ParseProblem(true, message, sourceStart, sourceEnd));  		}  		/** {@inheritDoc} */ @@ -244,6 +244,11 @@ public class EclipseAST extends AST<ASTNode> {  		}  		/** {@inheritDoc} */ +		@Override public Node getNodeFor(ASTNode obj) { +			return (Node) super.getNodeFor(obj); +		} +		 +		/** {@inheritDoc} */  		public Node directUp() {  			return (Node) super.directUp();  		} @@ -300,6 +305,31 @@ public class EclipseAST extends AST<ASTNode> {  		return (unit.bits & ASTNode.HasAllMethodBodies) > 0;  	} +	@Override protected Node buildTree(ASTNode node, Kind kind) { +		switch ( kind ) { +		case COMPILATION_UNIT: +			return buildCompilationUnit((CompilationUnitDeclaration) node); +		case TYPE: +			return buildType((TypeDeclaration) node); +		case FIELD: +			return buildField((FieldDeclaration) node); +		case INITIALIZER: +			return buildInitializer((Initializer) node); +		case METHOD: +			return buildMethod((AbstractMethodDeclaration) node); +		case ARGUMENT: +			return buildLocal((Argument) node, kind); +		case LOCAL: +			return buildLocal((LocalDeclaration) node, kind); +		case STATEMENT: +			return buildStatement((Statement) node); +		case ANNOTATION: +			return buildAnnotation((Annotation) node); +		default: +			throw new AssertionError("Did not expect to arrive here: " + kind); +		} +	} +	  	private Node buildCompilationUnit(CompilationUnitDeclaration top) {  		Collection<Node> children = buildTypes(top.types);  		return putInMap(new Node(top, children, Kind.COMPILATION_UNIT)); @@ -373,30 +403,32 @@ public class EclipseAST extends AST<ASTNode> {  		if ( children == null ) return Collections.emptyList();  		List<Node> childNodes = new ArrayList<Node>();  		for ( LocalDeclaration local : children ) { -			addIfNotNull(childNodes, buildLocal(local)); +			addIfNotNull(childNodes, buildLocal(local, Kind.ARGUMENT));  		}  		return childNodes;  	} -	private Node buildLocal(LocalDeclaration local) { +	private Node buildLocal(LocalDeclaration local, Kind kind) {  		if ( alreadyHandled(local) ) return null;  		List<Node> childNodes = new ArrayList<Node>();  		addIfNotNull(childNodes, buildStatement(local.initialization));  		childNodes.addAll(buildAnnotations(local.annotations)); -		return putInMap(new Node(local, childNodes, Kind.LOCAL)); +		return putInMap(new Node(local, childNodes, kind));  	}  	private Collection<Node> buildAnnotations(Annotation[] annotations) {  		if ( annotations == null ) return Collections.emptyList();  		List<Node> elements = new ArrayList<Node>(); -		for ( Annotation an : annotations ) { -			if ( an == null ) continue; -			if ( alreadyHandled(an) ) continue; -			elements.add(putInMap(new Node(an, null, Kind.ANNOTATION))); -		} +		for ( Annotation an : annotations ) addIfNotNull(elements, buildAnnotation(an));  		return elements;  	} +	private Node buildAnnotation(Annotation annotation) { +		if ( annotation == null ) return null; +		if ( alreadyHandled(annotation) ) return null; +		return putInMap(new Node(annotation, null, Kind.ANNOTATION)); +	} +	  	private Collection<Node> buildStatements(Statement[] children) {  		if ( children == null ) return Collections.emptyList();  		List<Node> childNodes = new ArrayList<Node>(); @@ -409,7 +441,7 @@ public class EclipseAST extends AST<ASTNode> {  		if ( child == null || alreadyHandled(child) ) return null;  		if ( child instanceof TypeDeclaration ) return buildType((TypeDeclaration)child); -		if ( child instanceof LocalDeclaration ) return buildLocal((LocalDeclaration)child); +		if ( child instanceof LocalDeclaration ) return buildLocal((LocalDeclaration)child, Kind.LOCAL);  		//We drill down because LocalDeclarations and TypeDeclarations can occur anywhere, even in, say,  		//an if block, or even the expression on an assert statement! diff --git a/src/lombok/eclipse/EclipseASTVisitor.java b/src/lombok/eclipse/EclipseASTVisitor.java index d5fece8f..aac0d8ed 100644 --- a/src/lombok/eclipse/EclipseASTVisitor.java +++ b/src/lombok/eclipse/EclipseASTVisitor.java @@ -122,8 +122,8 @@ public interface EclipseASTVisitor {  		}  		@Override public void visitCompilationUnit(Node node, CompilationUnitDeclaration unit) { -			System.out.println("---------------------------------------------------------"); -			System.out.println(node.isCompleteParse() ? "COMPLETE" : "incomplete"); +			out.println("---------------------------------------------------------"); +			out.println(node.isCompleteParse() ? "COMPLETE" : "incomplete");  			print("<CUD %s>", node.getFileName());  			indent++; diff --git a/src/lombok/eclipse/HandlerLibrary.java b/src/lombok/eclipse/HandlerLibrary.java index 39864e8e..10180963 100644 --- a/src/lombok/eclipse/HandlerLibrary.java +++ b/src/lombok/eclipse/HandlerLibrary.java @@ -63,11 +63,11 @@ public class HandlerLibrary {  					SpiLoadUtil.findAnnotationClass(handler.getClass(), EclipseAnnotationHandler.class);  				AnnotationHandlerContainer<?> container = new AnnotationHandlerContainer(handler, annotationClass);  				if ( lib.annotationHandlers.put(container.annotationClass.getName(), container) != null ) { -					Eclipse.error("Duplicate handlers for annotation type: " + container.annotationClass.getName()); +					Eclipse.error(null, "Duplicate handlers for annotation type: " + container.annotationClass.getName());  				}  				lib.typeLibrary.addType(container.annotationClass.getName());  			} catch ( ServiceConfigurationError e ) { -				Eclipse.error("Can't load Lombok annotation handler for eclipse: ", e); +				Eclipse.error(null, "Can't load Lombok annotation handler for eclipse: ", e);  			}  		}  	} @@ -78,7 +78,7 @@ public class HandlerLibrary {  			try {  				lib.visitorHandlers.add(it.next());  			} catch ( ServiceConfigurationError e ) { -				Eclipse.error("Can't load Lombok visitor handler for eclipse: ", e); +				Eclipse.error(null, "Can't load Lombok visitor handler for eclipse: ", e);  			}  		}  	} @@ -94,6 +94,7 @@ public class HandlerLibrary {  		boolean handled = false;  		for ( String fqn : resolver.findTypeMatches(annotationNode, toQualifiedName(annotation.type.getTypeName())) ) {  			AnnotationHandlerContainer<?> container = annotationHandlers.get(fqn); +			  			if ( container == null ) continue;  			try { @@ -101,7 +102,7 @@ public class HandlerLibrary {  			} catch ( AnnotationValueDecodeFail fail ) {  				fail.owner.setError(fail.getMessage(), fail.idx);  			} catch ( Throwable t ) { -				Eclipse.error(String.format("Lombok annotation handler %s failed", container.handler.getClass()), t); +				Eclipse.error(ast, String.format("Lombok annotation handler %s failed", container.handler.getClass()), t);  			}  		} @@ -112,7 +113,8 @@ public class HandlerLibrary {  		for ( EclipseASTVisitor visitor : visitorHandlers ) try {  			ast.traverse(visitor);  		} catch ( Throwable t ) { -			Eclipse.error(String.format("Lombok visitor handler %s failed", visitor.getClass()), t); +			Eclipse.error((CompilationUnitDeclaration) ast.top().get(), +					String.format("Lombok visitor handler %s failed", visitor.getClass()), t);  		}  	}  } diff --git a/src/lombok/eclipse/TransformEclipseAST.java b/src/lombok/eclipse/TransformEclipseAST.java index b56c594a..ccb29a8c 100644 --- a/src/lombok/eclipse/TransformEclipseAST.java +++ b/src/lombok/eclipse/TransformEclipseAST.java @@ -41,7 +41,7 @@ public class TransformEclipseAST {  			l = HandlerLibrary.load();  			f = CompilationUnitDeclaration.class.getDeclaredField("$lombokAST");  		} catch ( Throwable t ) { -			Eclipse.error("Problem initializing lombok", t); +			Eclipse.error(null, "Problem initializing lombok", t);  			disableLombok = true;  		}  		astCacheField = f; @@ -70,17 +70,12 @@ public class TransformEclipseAST {  			new TransformEclipseAST(existing).go();  		} catch ( Throwable t ) {  			try { -				String fileName = "(unknown)"; -				if ( ast.compilationResult != null && ast.compilationResult.fileName != null ) { -					fileName = new String(ast.compilationResult.fileName); -				} -				  				String message = "Lombok can't parse this source: " + t.toString(); -				EclipseAST.addProblemToCompilationResult(fileName, ast, false, message, ast, 0, 0); +				EclipseAST.addProblemToCompilationResult(ast, false, message, 0, 0);  				t.printStackTrace();  			} catch ( Throwable t2 ) { -				Eclipse.error("Can't create an error in the problems dialog while adding: " + t.toString(), t2); +				Eclipse.error(ast, "Can't create an error in the problems dialog while adding: " + t.toString(), t2);  			}  		}  	} diff --git a/src/lombok/eclipse/handlers/HandleData.java b/src/lombok/eclipse/handlers/HandleData.java index 64540e95..6c77644f 100644 --- a/src/lombok/eclipse/handlers/HandleData.java +++ b/src/lombok/eclipse/handlers/HandleData.java @@ -1,20 +1,38 @@  package lombok.eclipse.handlers; +import static lombok.eclipse.handlers.PKG.*; +  import java.util.ArrayList; +import java.util.Collection;  import java.util.List; -import org.eclipse.jdt.internal.compiler.ast.Annotation; -import org.eclipse.jdt.internal.compiler.ast.FieldDeclaration; -import org.eclipse.jdt.internal.compiler.ast.TypeDeclaration; -import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants; -import org.mangosdk.spi.ProviderFor; - +import lombok.AccessLevel;  import lombok.Data;  import lombok.core.AnnotationValues;  import lombok.core.AST.Kind; +import lombok.eclipse.Eclipse;  import lombok.eclipse.EclipseAnnotationHandler;  import lombok.eclipse.EclipseAST.Node; +import org.eclipse.jdt.internal.compiler.ast.ASTNode; +import org.eclipse.jdt.internal.compiler.ast.Annotation; +import org.eclipse.jdt.internal.compiler.ast.BinaryExpression; +import org.eclipse.jdt.internal.compiler.ast.CompilationUnitDeclaration; +import org.eclipse.jdt.internal.compiler.ast.ConstructorDeclaration; +import org.eclipse.jdt.internal.compiler.ast.Expression; +import org.eclipse.jdt.internal.compiler.ast.FieldDeclaration; +import org.eclipse.jdt.internal.compiler.ast.MethodDeclaration; +import org.eclipse.jdt.internal.compiler.ast.OperatorIds; +import org.eclipse.jdt.internal.compiler.ast.ReturnStatement; +import org.eclipse.jdt.internal.compiler.ast.SingleNameReference; +import org.eclipse.jdt.internal.compiler.ast.Statement; +import org.eclipse.jdt.internal.compiler.ast.StringLiteral; +import org.eclipse.jdt.internal.compiler.ast.TypeDeclaration; +import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants; +import org.eclipse.jdt.internal.compiler.lookup.MethodBinding; +import org.eclipse.jdt.internal.compiler.lookup.MethodScope; +import org.mangosdk.spi.ProviderFor; +  @ProviderFor(EclipseAnnotationHandler.class)  public class HandleData implements EclipseAnnotationHandler<Data> {  	@Override public boolean handle(AnnotationValues<Data> annotation, Annotation ast, Node annotationNode) { @@ -32,18 +50,111 @@ public class HandleData implements EclipseAnnotationHandler<Data> {  		}  		List<Node> nodesForEquality = new ArrayList<Node>(); +		List<Node> nodesForConstructorAndToString = new ArrayList<Node>();  		for ( Node 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.AccTransient) == 0 ) nodesForEquality.add(child); +			nodesForConstructorAndToString.add(child);  			new HandleGetter().generateGetterForField(child, annotationNode.get());  			if ( (fieldDecl.modifiers & ClassFileConstants.AccFinal) == 0 )  				new HandleSetter().generateSetterForField(child, annotationNode.get());  		} -		//TODO generate constructor, hashCode, equals, toString. -		return true; +		switch ( methodExists("toString", typeNode) ) { +		case NOT_EXISTS: +			MethodDeclaration toString = createToString(typeNode, nodesForConstructorAndToString, ast); +			injectMethod(typeNode, toString); +			break; +		case EXISTS_BY_LOMBOK: +			injectScopeIntoToString((MethodDeclaration) getExistingLombokMethod("toString", typeNode).get(), typeDecl); +		} +		 +		//TODO generate constructor, hashCode, equals. +		return false; +	} +	 +	private void injectScopeIntoToString(MethodDeclaration method, TypeDeclaration typeDecl) { +		if ( typeDecl.scope != null ) { +			method.scope = new MethodScope(typeDecl.scope, method, false); +			method.returnType.resolvedType = typeDecl.scope.getJavaLangString(); +			method.binding = new MethodBinding(method.modifiers, +					method.selector, typeDecl.scope.getJavaLangString(), null, null, typeDecl.binding); +		} +	} +	 +	private MethodDeclaration createToString(Node type, Collection<Node> fields, ASTNode pos) { +		char[] rawTypeName = ((TypeDeclaration)type.get()).name; +		String typeName = rawTypeName == null ? "" : new String(rawTypeName); +		char[] prefix = (typeName + "(").toCharArray(); +		char[] suffix = ")".toCharArray(); +		char[] infix = ", ".toCharArray(); +		long p = (long)pos.sourceStart << 32 | pos.sourceEnd; +		final int PLUS = OperatorIds.PLUS; +		 +		boolean first = true; +		Expression current = new StringLiteral(prefix, 0, 0, 0); +		for ( Node field : fields ) { +			char[] fName = ((FieldDeclaration)field.get()).name; +			if ( fName == null ) continue; +			if ( !first ) { +				current = new BinaryExpression(current, new StringLiteral(infix, 0, 0, 0), PLUS); +			} +			else first = false; +			current = new BinaryExpression(current, new SingleNameReference(fName, p), PLUS); +		} +		current = new BinaryExpression(current, new StringLiteral(suffix, 0, 0, 0), PLUS); +		 +		ReturnStatement returnStatement = new ReturnStatement(current, (int)(p >> 32), (int)p); +		 +		MethodDeclaration method = new MethodDeclaration(((CompilationUnitDeclaration) type.top().get()).compilationResult); +		method.modifiers = PKG.toModifier(AccessLevel.PUBLIC); +		method.returnType = Eclipse.TYPEREF_JAVA_LANG_STRING; +		method.annotations = null; +		method.arguments = null; +		method.selector = "toString".toCharArray(); +		method.binding = null; +		method.thrownExceptions = null; +		method.typeParameters = null; +		injectScopeIntoToString(method, (TypeDeclaration) type.get()); +		method.bits |= Eclipse.ECLIPSE_DO_NOT_TOUCH_FLAG; +		method.bodyStart = method.declarationSourceStart = method.sourceStart = pos.sourceStart; +		method.bodyEnd = method.declarationSourceEnd = method.sourceEnd = pos.sourceEnd; +		method.statements = new Statement[] { returnStatement }; +		return method; +	} +	 +	private MethodDeclaration createEquals(Collection<Node> fields) { +		return null; +	} +	 +	private ConstructorDeclaration createConstructor(Collection<Node> fields) { +		//If using an of() constructor, make private. +		//method params +		//on loop: Assignment(FieldReference(ThisReference, "x"), SingleNameReference("x")) +		return null; +	} +	 +	private MethodDeclaration createStaticConstructor(Collection<Node> fields) { +		//Return(AllocationExpression(SingleTypeReference("Bar"), namesOfFields); +		return null; +	} +	 +	private MethodDeclaration createHashCode(Collection<Node> fields) { +		//booleans: conditionalexpression that bounces between 1231 and 1237. +		//longs: (int) (lng ^ (lng >>> 32)); +		//doubles and floats: Double.doubleToLongBits, then as long. +		 +		//local final var PRIME = IntLiteral(primeNumber) +		//local final var RESULT = IntLiteral(1) +		 +		//    Assignment("RESULT", BinaryExpression("+", BinaryExpression("*", "PRIME", "RESULT"), "name") +		 +		//    add = ConditionalExpression(EqualExpression("name", NullLiteral), IntLiteral(0), MessageSend("name", "hashCode()")) +		//    Assignment("RESULT", BinaryExpression("+", BinaryExpression("*", "PRIME", "RESULT"), add); +		 +		return null;  	}  } diff --git a/src/lombok/eclipse/handlers/HandleGetter.java b/src/lombok/eclipse/handlers/HandleGetter.java index 798705da..5b3fbf90 100644 --- a/src/lombok/eclipse/handlers/HandleGetter.java +++ b/src/lombok/eclipse/handlers/HandleGetter.java @@ -1,18 +1,17 @@  package lombok.eclipse.handlers;  import static lombok.eclipse.handlers.PKG.*; -  import lombok.AccessLevel;  import lombok.Getter;  import lombok.core.AnnotationValues;  import lombok.core.TransformationsUtil;  import lombok.core.AST.Kind;  import lombok.eclipse.Eclipse; +import lombok.eclipse.EclipseASTVisitor;  import lombok.eclipse.EclipseAnnotationHandler;  import lombok.eclipse.EclipseAST.Node;  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.Expression;  import org.eclipse.jdt.internal.compiler.ast.FieldDeclaration; @@ -23,14 +22,16 @@ import org.eclipse.jdt.internal.compiler.ast.Statement;  import org.eclipse.jdt.internal.compiler.ast.TypeDeclaration;  import org.eclipse.jdt.internal.compiler.ast.TypeReference;  import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants; +import org.eclipse.jdt.internal.compiler.lookup.MethodBinding;  import org.eclipse.jdt.internal.compiler.lookup.MethodScope;  import org.mangosdk.spi.ProviderFor;  @ProviderFor(EclipseAnnotationHandler.class)  public class HandleGetter implements EclipseAnnotationHandler<Getter> {  	public void generateGetterForField(Node fieldNode, ASTNode pos) { -		AccessLevel level = Getter.DEFAULT_ACCESS_LEVEL; +		AccessLevel level = AccessLevel.PUBLIC;  		Node errorNode = fieldNode; +		boolean whineIfExists = false;  		for ( Node child : fieldNode.down() ) {  			if ( child.getKind() == Kind.ANNOTATION ) { @@ -38,21 +39,22 @@ public class HandleGetter implements EclipseAnnotationHandler<Getter> {  					level = Eclipse.createAnnotation(Getter.class, child).getInstance().value();  					errorNode = child;  					pos = child.get(); +					whineIfExists = true;  					break;  				}  			}  		} -		createGetterForField(level, fieldNode, errorNode, pos); +		createGetterForField(level, fieldNode, errorNode, pos, whineIfExists);  	}  	@Override public boolean handle(AnnotationValues<Getter> annotation, Annotation ast, Node annotationNode) {  		Node fieldNode = annotationNode.up();  		AccessLevel level = annotation.getInstance().value(); -		return createGetterForField(level, fieldNode, annotationNode, annotationNode.get()); +		return createGetterForField(level, fieldNode, annotationNode, annotationNode.get(), true);  	} -	private boolean createGetterForField(AccessLevel level, Node fieldNode, Node errorNode, ASTNode pos) { +	private boolean createGetterForField(AccessLevel level, Node fieldNode, Node errorNode, ASTNode pos, boolean whineIfExists) {  		if ( fieldNode.getKind() != Kind.FIELD ) {  			errorNode.addError("@Getter is only supported on a field.");  			return false; @@ -63,30 +65,40 @@ public class HandleGetter implements EclipseAnnotationHandler<Getter> {  		String getterName = TransformationsUtil.toGetterName(  				new String(field.name), nameEquals(fieldType.getTypeName(), "boolean")); -		TypeDeclaration parent = (TypeDeclaration) fieldNode.up().get(); -		if ( parent.methods != null ) for ( AbstractMethodDeclaration method : parent.methods ) { -			if ( method.selector != null && new String(method.selector).equals(getterName) ) { -				errorNode.addWarning(String.format( -						"Not generating %s(): A method with that name already exists",  getterName)); -				return false; -			} +		int modifier = toModifier(level) | (field.modifiers & ClassFileConstants.AccStatic); +		 +		switch ( methodExists(getterName, fieldNode) ) { +		case EXISTS_BY_LOMBOK: +			Node methodNode = getExistingLombokMethod(getterName, fieldNode); +			injectScopeIntoGetter(modifier, field, (MethodDeclaration)methodNode.get(), (TypeDeclaration) methodNode.up().get()); +			return false; +		case EXISTS_BY_USER: +			if ( whineIfExists ) errorNode.addWarning( +					String.format("Not generating %s(): A method with that name already exists",  getterName)); +			return false; +		default: +		case NOT_EXISTS: +			//continue with creating the getter  		} -		int modifier = toModifier(level) | (field.modifiers & ClassFileConstants.AccStatic); +		if ( new String(field.name).equals("a") ) fieldNode.up().traverse(new EclipseASTVisitor.Printer()); +		MethodDeclaration method = generateGetter((TypeDeclaration) fieldNode.up().get(), field, getterName, modifier, pos); -		MethodDeclaration method = generateGetter(parent, field, getterName, modifier, pos); +		injectMethod(fieldNode.up(), method); -		if ( parent.methods == null ) { -			parent.methods = new AbstractMethodDeclaration[1]; -			parent.methods[0] = method; -		} else { -			AbstractMethodDeclaration[] newArray = new AbstractMethodDeclaration[parent.methods.length + 1]; -			System.arraycopy(parent.methods, 0, newArray, 0, parent.methods.length); -			newArray[parent.methods.length] = method; -			parent.methods = newArray; +		return false; +	} +	 +	private void injectScopeIntoGetter(int modifier, FieldDeclaration field, MethodDeclaration method, TypeDeclaration parent) { +		if ( parent.scope != null ) { +			if ( method.binding != null ) { +				method.binding.returnType = field.type.resolvedType; +			} else { +				method.scope = new MethodScope(parent.scope, method, false); +				method.returnType.resolvedType = field.type.resolvedType; +				method.binding = new MethodBinding(modifier, method.selector, method.returnType.resolvedType, null, null, parent.binding); +			}  		} -		 -		return true;  	}  	private MethodDeclaration generateGetter(TypeDeclaration parent, FieldDeclaration field, String name, @@ -100,8 +112,8 @@ public class HandleGetter implements EclipseAnnotationHandler<Getter> {  		method.binding = null;  		method.thrownExceptions = null;  		method.typeParameters = null; -		method.scope = parent.scope == null ? null : new MethodScope(parent.scope, method, false); -		method.bits |= ASTNode.Bit24; +		injectScopeIntoGetter(modifier, field, method, parent); +		method.bits |= Eclipse.ECLIPSE_DO_NOT_TOUCH_FLAG;  		Expression fieldExpression = new SingleNameReference(field.name, (field.declarationSourceStart << 32) | field.declarationSourceEnd);  		Statement returnStatement = new ReturnStatement(fieldExpression, field.sourceStart, field.sourceEnd);  		method.bodyStart = method.declarationSourceStart = method.sourceStart = pos.sourceStart; diff --git a/src/lombok/eclipse/handlers/HandleSetter.java b/src/lombok/eclipse/handlers/HandleSetter.java index d0d0d902..c5f87a93 100644 --- a/src/lombok/eclipse/handlers/HandleSetter.java +++ b/src/lombok/eclipse/handlers/HandleSetter.java @@ -1,9 +1,16 @@  package lombok.eclipse.handlers;  import static lombok.eclipse.handlers.PKG.*; +import lombok.AccessLevel; +import lombok.Setter; +import lombok.core.AnnotationValues; +import lombok.core.TransformationsUtil; +import lombok.core.AST.Kind; +import lombok.eclipse.Eclipse; +import lombok.eclipse.EclipseAnnotationHandler; +import lombok.eclipse.EclipseAST.Node;  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.Assignment; @@ -16,24 +23,19 @@ import org.eclipse.jdt.internal.compiler.ast.ThisReference;  import org.eclipse.jdt.internal.compiler.ast.TypeDeclaration;  import org.eclipse.jdt.internal.compiler.ast.TypeReference;  import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants; +import org.eclipse.jdt.internal.compiler.lookup.BaseTypeBinding; +import org.eclipse.jdt.internal.compiler.lookup.MethodBinding;  import org.eclipse.jdt.internal.compiler.lookup.MethodScope; +import org.eclipse.jdt.internal.compiler.lookup.TypeBinding;  import org.eclipse.jdt.internal.compiler.lookup.TypeIds;  import org.mangosdk.spi.ProviderFor; -import lombok.AccessLevel; -import lombok.Setter; -import lombok.core.AnnotationValues; -import lombok.core.TransformationsUtil; -import lombok.core.AST.Kind; -import lombok.eclipse.Eclipse; -import lombok.eclipse.EclipseAnnotationHandler; -import lombok.eclipse.EclipseAST.Node; -  @ProviderFor(EclipseAnnotationHandler.class)  public class HandleSetter implements EclipseAnnotationHandler<Setter> {  	public void generateSetterForField(Node fieldNode, ASTNode pos) { -		AccessLevel level = Setter.DEFAULT_ACCESS_LEVEL; +		AccessLevel level = AccessLevel.PUBLIC;  		Node errorNode = fieldNode; +		boolean whineIfExists = false;  		for ( Node child : fieldNode.down() ) {  			if ( child.getKind() == Kind.ANNOTATION ) { @@ -41,51 +43,68 @@ public class HandleSetter implements EclipseAnnotationHandler<Setter> {  					level = Eclipse.createAnnotation(Setter.class, child).getInstance().value();  					errorNode = child;  					pos = child.get(); +					whineIfExists = true;  					break;  				}  			}  		} -		createSetterForField(level, fieldNode, errorNode, pos); +		createSetterForField(level, fieldNode, errorNode, pos, whineIfExists);  	}  	@Override public boolean handle(AnnotationValues<Setter> annotation, Annotation ast, Node annotationNode) {  		Node fieldNode = annotationNode.up();  		if ( fieldNode.getKind() != Kind.FIELD ) return false;  		AccessLevel level = annotation.getInstance().value(); -		return createSetterForField(level, fieldNode, annotationNode, annotationNode.get()); +		return createSetterForField(level, fieldNode, annotationNode, annotationNode.get(), true);  	} -	private boolean createSetterForField(AccessLevel level, Node fieldNode, Node errorNode, ASTNode pos) { -		if ( fieldNode.getKind() != Kind.FIELD ) return false; +	private boolean createSetterForField(AccessLevel level, Node fieldNode, Node errorNode, ASTNode pos, boolean whineIfExists) { +		if ( fieldNode.getKind() != Kind.FIELD ) { +			errorNode.addError("@Setter is only supported on a field."); +			return false; +		} +		  		FieldDeclaration field = (FieldDeclaration) fieldNode.get();  		String setterName = TransformationsUtil.toSetterName(new String(field.name)); -		TypeDeclaration parent = (TypeDeclaration) fieldNode.up().get(); -		if ( parent.methods != null ) for ( AbstractMethodDeclaration method : parent.methods ) { -			if ( method.selector != null && new String(method.selector).equals(setterName) ) { -				errorNode.addWarning(String.format( -						"Not generating %s(%s %s): A method with that name already exists", -						setterName, field.type, new String(field.name))); -				return false; -			} +		int modifier = toModifier(level) | (field.modifiers & ClassFileConstants.AccStatic); +		 +		switch ( methodExists(setterName, fieldNode) ) { +		case EXISTS_BY_LOMBOK: +			Node methodNode = getExistingLombokMethod(setterName, fieldNode); +			injectScopeIntoSetter(modifier, field, (MethodDeclaration)methodNode.get(), (TypeDeclaration) methodNode.up().get()); +			return false; +		case EXISTS_BY_USER: +			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 false; +		default: +		case NOT_EXISTS: +			//continue with creating the setter  		} -		int modifier = toModifier(level) | (field.modifiers & ClassFileConstants.AccStatic); -		MethodDeclaration method = generateSetter(parent, field, setterName, modifier, pos); +		MethodDeclaration method = generateSetter((TypeDeclaration) fieldNode.up().get(), field, setterName, modifier, pos); -		if ( parent.methods == null ) { -			parent.methods = new AbstractMethodDeclaration[1]; -			parent.methods[0] = method; -		} else { -			AbstractMethodDeclaration[] newArray = new AbstractMethodDeclaration[parent.methods.length + 1]; -			System.arraycopy(parent.methods, 0, newArray, 0, parent.methods.length); -			newArray[parent.methods.length] = method; -			parent.methods = newArray; -		} +		injectMethod(fieldNode.up(), method); -		return true; +		return false; +	} +	 +	private void injectScopeIntoSetter(int modifier, FieldDeclaration field, MethodDeclaration method, TypeDeclaration parent) { +		if ( parent.scope != null ) { +			TypeBinding[] params = new TypeBinding[] { field.type.resolvedType }; +			 +			if ( method.binding == null ) { +				method.scope = new MethodScope(parent.scope, method, false); +				method.binding = new MethodBinding(modifier, method.selector, BaseTypeBinding.VOID, params, null, parent.binding); +			} +			method.binding.parameters = params; +			method.binding.returnType = BaseTypeBinding.VOID; +			method.returnType.resolvedType = BaseTypeBinding.VOID; +		}  	}  	private MethodDeclaration generateSetter(TypeDeclaration parent, FieldDeclaration field, String name, @@ -102,7 +121,8 @@ public class HandleSetter implements EclipseAnnotationHandler<Setter> {  		method.thrownExceptions = null;  		method.typeParameters = null;  		method.scope = parent.scope == null ? null : new MethodScope(parent.scope, method, false); -		method.bits |= ASTNode.Bit24; +		method.bits |= Eclipse.ECLIPSE_DO_NOT_TOUCH_FLAG; +		injectScopeIntoSetter(modifier, field, method, parent);  		FieldReference thisX = new FieldReference(("this." + new String(field.name)).toCharArray(), pos);  		thisX.receiver = new ThisReference(ast.sourceStart, ast.sourceEnd);  		thisX.token = field.name; diff --git a/src/lombok/eclipse/handlers/PKG.java b/src/lombok/eclipse/handlers/PKG.java index 61f71140..d93807a7 100644 --- a/src/lombok/eclipse/handlers/PKG.java +++ b/src/lombok/eclipse/handlers/PKG.java @@ -3,6 +3,11 @@ package lombok.eclipse.handlers;  import java.lang.reflect.Modifier;  import lombok.AccessLevel; +import lombok.core.AST.Kind; +import lombok.eclipse.EclipseAST; + +import org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration; +import org.eclipse.jdt.internal.compiler.ast.TypeDeclaration;  class PKG {  	private PKG() {} @@ -33,4 +38,63 @@ class PKG {  		return string.contentEquals(sb);  	} +	 +	enum MethodExistsResult { +		NOT_EXISTS, EXISTS_BY_USER, EXISTS_BY_LOMBOK; +	} +	 +	static MethodExistsResult methodExists(String methodName, EclipseAST.Node node) { +		while ( node != null && !(node.get() instanceof TypeDeclaration) ) { +			node = node.up(); +		} +		 +		if ( node.get() instanceof TypeDeclaration ) { +			TypeDeclaration typeDecl = (TypeDeclaration)node.get(); +			if ( typeDecl.methods != null ) for ( AbstractMethodDeclaration def : typeDecl.methods ) { +				char[] mName = ((AbstractMethodDeclaration)def).selector; +				if ( mName == null ) continue; +				if ( methodName.equals(new String(mName)) ) { +					EclipseAST.Node existing = node.getNodeFor(def); +					if ( existing == null || !existing.isHandled() ) return MethodExistsResult.EXISTS_BY_USER; +					return MethodExistsResult.EXISTS_BY_LOMBOK; +				} +			} +		} +		 +		return MethodExistsResult.NOT_EXISTS; +	} +	 +	static EclipseAST.Node getExistingLombokMethod(String methodName, EclipseAST.Node node) { +		while ( node != null && !(node.get() instanceof TypeDeclaration) ) { +			node = node.up(); +		} +		 +		if ( node.get() instanceof TypeDeclaration ) { +			for ( AbstractMethodDeclaration def : ((TypeDeclaration)node.get()).methods ) { +				char[] mName = ((AbstractMethodDeclaration)def).selector; +				if ( mName == null ) continue; +				if ( methodName.equals(new String(mName)) ) { +					EclipseAST.Node existing = node.getNodeFor(def); +					if ( existing.isHandled() ) return existing; +				} +			} +		} +		 +		return null; +	} +	 +	static void injectMethod(EclipseAST.Node type, AbstractMethodDeclaration method) { +		TypeDeclaration parent = (TypeDeclaration) type.get(); +		if ( parent.methods == null ) { +			parent.methods = new AbstractMethodDeclaration[1]; +			parent.methods[0] = method; +		} else { +			AbstractMethodDeclaration[] newArray = new AbstractMethodDeclaration[parent.methods.length + 1]; +			System.arraycopy(parent.methods, 0, newArray, 0, parent.methods.length); +			newArray[parent.methods.length] = method; +			parent.methods = newArray; +		} +		 +		type.add(method, Kind.METHOD).recursiveSetHandled(); +	}  } diff --git a/src/lombok/javac/JavacAST.java b/src/lombok/javac/JavacAST.java index 7050df75..f0544256 100644 --- a/src/lombok/javac/JavacAST.java +++ b/src/lombok/javac/JavacAST.java @@ -94,6 +94,31 @@ public class JavacAST extends AST<JCTree> {  		return symtab;  	} +	@Override protected Node buildTree(JCTree node, Kind kind) { +		switch ( kind ) { +		case COMPILATION_UNIT: +			return buildCompilationUnit((JCCompilationUnit) node); +		case TYPE: +			return buildType((JCClassDecl) node); +		case FIELD: +			return buildField((JCVariableDecl) node); +		case INITIALIZER: +			return buildInitializer((JCBlock) node); +		case METHOD: +			return buildMethod((JCMethodDecl) node); +		case ARGUMENT: +			return buildLocalVar((JCVariableDecl) node, kind); +		case LOCAL: +			return buildLocalVar((JCVariableDecl) node, kind); +		case STATEMENT: +			return buildStatementOrExpression(node); +		case ANNOTATION: +			return buildAnnotation((JCAnnotation) node); +		default: +			throw new AssertionError("Did not expect: " + kind); +		} +	} +	  	private Node buildCompilationUnit(JCCompilationUnit top) {  		List<Node> childNodes = new ArrayList<Node>();  		for ( JCTree s : top.defs ) { @@ -310,6 +335,11 @@ public class JavacAST extends AST<JCTree> {  		}  		/** {@inheritDoc} */ +		@Override public Node getNodeFor(JCTree obj) { +			return (Node) super.getNodeFor(obj); +		} +		 +		/** {@inheritDoc} */  		@Override public Node directUp() {  			return (Node) super.directUp();  		} diff --git a/src/lombok/javac/handlers/HandleGetter.java b/src/lombok/javac/handlers/HandleGetter.java index 651bc018..3405810b 100644 --- a/src/lombok/javac/handlers/HandleGetter.java +++ b/src/lombok/javac/handlers/HandleGetter.java @@ -29,8 +29,9 @@ import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition;  @ProviderFor(JavacAnnotationHandler.class)  public class HandleGetter implements JavacAnnotationHandler<Getter> {  	public void generateGetterForField(Node fieldNode, DiagnosticPosition pos) { -		AccessLevel level = Getter.DEFAULT_ACCESS_LEVEL; +		AccessLevel level = AccessLevel.PUBLIC;  		Node errorNode = fieldNode; +		boolean whineIfExists = false;  		for ( Node child : fieldNode.down() ) {  			if ( child.getKind() == Kind.ANNOTATION ) { @@ -38,21 +39,22 @@ public class HandleGetter implements JavacAnnotationHandler<Getter> {  					level = Javac.createAnnotation(Getter.class, child).getInstance().value();  					errorNode = child;  					pos = child.get(); +					whineIfExists = true;  					break;  				}  			}  		} -		createGetterForField(level, fieldNode, errorNode, pos); +		createGetterForField(level, fieldNode, errorNode, pos, whineIfExists);  	}  	@Override public boolean handle(AnnotationValues<Getter> annotation, JCAnnotation ast, Node annotationNode) {  		Node fieldNode = annotationNode.up();  		AccessLevel level = annotation.getInstance().value(); -		return createGetterForField(level, fieldNode, annotationNode, annotationNode.get()); +		return createGetterForField(level, fieldNode, annotationNode, annotationNode.get(), true);  	} -	private boolean createGetterForField(AccessLevel level, Node fieldNode, Node errorNode, DiagnosticPosition pos) { +	private boolean createGetterForField(AccessLevel level, Node fieldNode, Node errorNode, DiagnosticPosition pos, boolean whineIfExists) {  		if ( fieldNode.getKind() != Kind.FIELD ) {  			errorNode.addError("@Getter is only supported on a field.");  			return false; @@ -61,10 +63,16 @@ public class HandleGetter implements JavacAnnotationHandler<Getter> {  		JCVariableDecl fieldDecl = (JCVariableDecl)fieldNode.get();  		String methodName = toGetterName(fieldDecl); -		if ( methodExists(methodName, fieldNode) ) { -			errorNode.addWarning( +		switch ( methodExists(methodName, fieldNode) ) { +		case EXISTS_BY_LOMBOK: +			return true; +		case EXISTS_BY_USER: +			if ( whineIfExists ) errorNode.addWarning(  					String.format("Not generating %s(): A method with that name already exists",  methodName));  			return false; +		default: +		case NOT_EXISTS: +			//continue with creating the getter  		}  		JCClassDecl javacClassTree = (JCClassDecl) fieldNode.up().get(); @@ -73,6 +81,9 @@ public class HandleGetter implements JavacAnnotationHandler<Getter> {  		JCMethodDecl getterMethod = createGetter(access, fieldNode, fieldNode.getTreeMaker());  		javacClassTree.defs = javacClassTree.defs.append(getterMethod); +		 +		fieldNode.up().add(getterMethod, Kind.METHOD).recursiveSetHandled(); +		  		return true;  	} diff --git a/src/lombok/javac/handlers/HandleSetter.java b/src/lombok/javac/handlers/HandleSetter.java index f1e73489..4999b5d8 100644 --- a/src/lombok/javac/handlers/HandleSetter.java +++ b/src/lombok/javac/handlers/HandleSetter.java @@ -31,8 +31,9 @@ import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition;  @ProviderFor(JavacAnnotationHandler.class)  public class HandleSetter implements JavacAnnotationHandler<Setter> {  	public void generateSetterForField(Node fieldNode, DiagnosticPosition pos) { -		AccessLevel level = Setter.DEFAULT_ACCESS_LEVEL; +		AccessLevel level = AccessLevel.PUBLIC;  		Node errorNode = fieldNode; +		boolean whineIfExists = false;  		for ( Node child : fieldNode.down() ) {  			if ( child.getKind() == Kind.ANNOTATION ) { @@ -40,21 +41,22 @@ public class HandleSetter implements JavacAnnotationHandler<Setter> {  					level = Javac.createAnnotation(Setter.class, child).getInstance().value();  					errorNode = child;  					pos = child.get(); +					whineIfExists = true;  					break;  				}  			}  		} -		createSetterForField(level, fieldNode, errorNode, pos); +		createSetterForField(level, fieldNode, errorNode, pos, whineIfExists);  	}  	@Override public boolean handle(AnnotationValues<Setter> annotation, JCAnnotation ast, Node annotationNode) {  		Node fieldNode = annotationNode.up();  		AccessLevel level = annotation.getInstance().value(); -		return createSetterForField(level, fieldNode, annotationNode, annotationNode.get()); +		return createSetterForField(level, fieldNode, annotationNode, annotationNode.get(), true);  	} -	private boolean createSetterForField(AccessLevel level, Node fieldNode, Node errorNode, DiagnosticPosition pos) { +	private boolean createSetterForField(AccessLevel level, Node fieldNode, Node errorNode, DiagnosticPosition pos, boolean whineIfExists) {  		if ( fieldNode.getKind() != Kind.FIELD ) {  			fieldNode.addError("@Setter is only supported on a field.");  			return false; @@ -63,11 +65,17 @@ public class HandleSetter implements JavacAnnotationHandler<Setter> {  		JCVariableDecl fieldDecl = (JCVariableDecl)fieldNode.get();  		String methodName = toSetterName(fieldDecl); -		if ( methodExists(methodName, fieldNode) ) { -			errorNode.addWarning( +		switch ( methodExists(methodName, fieldNode) ) { +		case EXISTS_BY_LOMBOK: +			return true; +		case EXISTS_BY_USER: +			if ( whineIfExists ) errorNode.addWarning(  					String.format("Not generating %s(%s %s): A method with that name already exists", -							methodName, fieldDecl.vartype, fieldDecl.name)); +					methodName, fieldDecl.vartype, fieldDecl.name));  			return false; +		default: +		case NOT_EXISTS: +			//continue with creating the setter  		}  		JCClassDecl javacClassTree = (JCClassDecl) fieldNode.up().get(); @@ -76,6 +84,9 @@ public class HandleSetter implements JavacAnnotationHandler<Setter> {  		JCMethodDecl setterMethod = createSetter(access, fieldNode, fieldNode.getTreeMaker());  		javacClassTree.defs = javacClassTree.defs.append(setterMethod); +		 +		fieldNode.up().add(setterMethod, Kind.METHOD).recursiveSetHandled(); +		  		return true;  	} diff --git a/src/lombok/javac/handlers/PKG.java b/src/lombok/javac/handlers/PKG.java index 2c038b2d..138559a9 100644 --- a/src/lombok/javac/handlers/PKG.java +++ b/src/lombok/javac/handlers/PKG.java @@ -28,7 +28,11 @@ class PKG {  		return TransformationsUtil.toSetterName(fieldName);  	} -	static boolean methodExists(String methodName, JavacAST.Node node) { +	enum MethodExistsResult { +		NOT_EXISTS, EXISTS_BY_USER, EXISTS_BY_LOMBOK; +	} +	 +	static MethodExistsResult methodExists(String methodName, JavacAST.Node node) {  		while ( node != null && !(node.get() instanceof JCClassDecl) ) {  			node = node.up();  		} @@ -37,13 +41,15 @@ class PKG {  			for ( JCTree def : ((JCClassDecl)node.get()).defs ) {  				if ( def instanceof JCMethodDecl ) {  					if ( ((JCMethodDecl)def).name.contentEquals(methodName) ) { -						return true; +						JavacAST.Node existing = node.getNodeFor(def); +						if ( existing == null || !existing.isHandled() ) return MethodExistsResult.EXISTS_BY_USER; +						return MethodExistsResult.EXISTS_BY_LOMBOK;  					}  				}  			}  		} -		return false; +		return MethodExistsResult.NOT_EXISTS;  	}  	static int toJavacModifier(AccessLevel accessLevel) { | 
