diff options
Diffstat (limited to 'src/lombok/eclipse')
-rw-r--r-- | src/lombok/eclipse/Eclipse.java | 100 | ||||
-rw-r--r-- | src/lombok/eclipse/EclipseASTVisitor.java | 31 | ||||
-rw-r--r-- | src/lombok/eclipse/handlers/HandleCleanup.java | 6 | ||||
-rw-r--r-- | src/lombok/eclipse/handlers/HandleData.java | 60 | ||||
-rw-r--r-- | src/lombok/eclipse/handlers/HandleEqualsAndHashCode.java | 365 | ||||
-rw-r--r-- | src/lombok/eclipse/handlers/HandleGetter.java | 23 | ||||
-rw-r--r-- | src/lombok/eclipse/handlers/HandleSetter.java | 36 | ||||
-rw-r--r-- | src/lombok/eclipse/handlers/HandleSneakyThrows.java | 58 | ||||
-rw-r--r-- | src/lombok/eclipse/handlers/HandleSynchronized.java | 19 | ||||
-rw-r--r-- | src/lombok/eclipse/handlers/HandleToString.java | 72 | ||||
-rw-r--r-- | src/lombok/eclipse/handlers/PKG.java | 36 |
11 files changed, 570 insertions, 236 deletions
diff --git a/src/lombok/eclipse/Eclipse.java b/src/lombok/eclipse/Eclipse.java index 6122d6bc..c96c9ce6 100644 --- a/src/lombok/eclipse/Eclipse.java +++ b/src/lombok/eclipse/Eclipse.java @@ -21,6 +21,7 @@ */ package lombok.eclipse; +import java.lang.reflect.Field; import java.lang.reflect.Method; import java.lang.reflect.Modifier; import java.util.ArrayList; @@ -29,6 +30,7 @@ import java.util.HashMap; import java.util.List; import java.util.Map; +import lombok.Lombok; import lombok.core.AnnotationValues; import lombok.core.TypeLibrary; import lombok.core.TypeResolver; @@ -145,17 +147,18 @@ public class Eclipse { * from another 'T', even for the same T in a single class file. Unfortunately the TypeParameter type hierarchy * is complicated and there's no clone method on TypeParameter itself. This method can clone them. */ - public static TypeParameter[] copyTypeParams(TypeParameter[] params) { + public static TypeParameter[] copyTypeParams(TypeParameter[] params, ASTNode source) { if ( params == null ) return null; TypeParameter[] out = new TypeParameter[params.length]; int idx = 0; for ( TypeParameter param : params ) { TypeParameter o = new TypeParameter(); + setGeneratedBy(o, source); o.annotations = param.annotations; o.bits = param.bits; o.modifiers = param.modifiers; o.name = param.name; - o.type = copyType(param.type); + o.type = copyType(param.type, source); o.sourceStart = param.sourceStart; o.sourceEnd = param.sourceEnd; o.declarationEnd = param.declarationEnd; @@ -164,7 +167,7 @@ public class Eclipse { if ( param.bounds != null ) { TypeReference[] b = new TypeReference[param.bounds.length]; int idx2 = 0; - for ( TypeReference ref : param.bounds ) b[idx2++] = copyType(ref); + for ( TypeReference ref : param.bounds ) b[idx2++] = copyType(ref, source); o.bounds = b; } out[idx++] = o; @@ -176,12 +179,12 @@ public class Eclipse { * Convenience method that creates a new array and copies each TypeReference in the source array via * {@link #copyType(TypeReference)}. */ - public static TypeReference[] copyTypes(TypeReference[] refs) { + public static TypeReference[] copyTypes(TypeReference[] refs, ASTNode source) { if ( refs == null ) return null; TypeReference[] outs = new TypeReference[refs.length]; int idx = 0; for ( TypeReference ref : refs ) { - outs[idx++] = copyType(ref); + outs[idx++] = copyType(ref, source); } return outs; } @@ -191,7 +194,7 @@ public class Eclipse { * Unfortunately the TypeReference type hierarchy is complicated and there's no clone * method on TypeReference itself. This method can clone them. */ - public static TypeReference copyType(TypeReference ref) { + public static TypeReference copyType(TypeReference ref, ASTNode source) { if ( ref instanceof ParameterizedQualifiedTypeReference ) { ParameterizedQualifiedTypeReference iRef = (ParameterizedQualifiedTypeReference) ref; TypeReference[][] args = null; @@ -204,23 +207,29 @@ public class Eclipse { TypeReference[] outRefArray = new TypeReference[inRefArray.length]; int idx2 = 0; for ( TypeReference inRef : inRefArray ) { - outRefArray[idx2++] = copyType(inRef); + outRefArray[idx2++] = copyType(inRef, source); } args[idx++] = outRefArray; } } } - return new ParameterizedQualifiedTypeReference(iRef.tokens, args, iRef.dimensions(), iRef.sourcePositions); + TypeReference typeRef = new ParameterizedQualifiedTypeReference(iRef.tokens, args, iRef.dimensions(), iRef.sourcePositions); + setGeneratedBy(typeRef, source); + return typeRef; } if ( ref instanceof ArrayQualifiedTypeReference ) { ArrayQualifiedTypeReference iRef = (ArrayQualifiedTypeReference) ref; - return new ArrayQualifiedTypeReference(iRef.tokens, iRef.dimensions(), iRef.sourcePositions); + TypeReference typeRef = new ArrayQualifiedTypeReference(iRef.tokens, iRef.dimensions(), iRef.sourcePositions); + setGeneratedBy(typeRef, source); + return typeRef; } if ( ref instanceof QualifiedTypeReference ) { QualifiedTypeReference iRef = (QualifiedTypeReference) ref; - return new QualifiedTypeReference(iRef.tokens, iRef.sourcePositions); + TypeReference typeRef = new QualifiedTypeReference(iRef.tokens, iRef.sourcePositions); + setGeneratedBy(typeRef, source); + return typeRef; } if ( ref instanceof ParameterizedSingleTypeReference ) { @@ -231,62 +240,72 @@ public class Eclipse { int idx = 0; for ( TypeReference inRef : iRef.typeArguments ) { if ( inRef == null ) args[idx++] = null; - else args[idx++] = copyType(inRef); + else args[idx++] = copyType(inRef, source); } } - return new ParameterizedSingleTypeReference(iRef.token, args, iRef.dimensions(), (long)iRef.sourceStart << 32 | iRef.sourceEnd); + + TypeReference typeRef = new ParameterizedSingleTypeReference(iRef.token, args, iRef.dimensions(), (long)iRef.sourceStart << 32 | iRef.sourceEnd); + setGeneratedBy(typeRef, source); + return typeRef; } if ( ref instanceof ArrayTypeReference ) { ArrayTypeReference iRef = (ArrayTypeReference) ref; - return new ArrayTypeReference(iRef.token, iRef.dimensions(), (long)iRef.sourceStart << 32 | iRef.sourceEnd); + TypeReference typeRef = new ArrayTypeReference(iRef.token, iRef.dimensions(), (long)iRef.sourceStart << 32 | iRef.sourceEnd); + setGeneratedBy(typeRef, source); + return typeRef; } if ( ref instanceof Wildcard ) { Wildcard wildcard = new Wildcard(((Wildcard)ref).kind); wildcard.sourceStart = ref.sourceStart; wildcard.sourceEnd = ref.sourceEnd; + setGeneratedBy(wildcard, source); return wildcard; } if ( ref instanceof SingleTypeReference ) { SingleTypeReference iRef = (SingleTypeReference) ref; - return new SingleTypeReference(iRef.token, (long)iRef.sourceStart << 32 | iRef.sourceEnd); + TypeReference typeRef = new SingleTypeReference(iRef.token, (long)iRef.sourceStart << 32 | iRef.sourceEnd); + setGeneratedBy(typeRef, source); + return typeRef; } return ref; } - public static Annotation[] copyAnnotations(Annotation[] annotations, long p) { - return copyAnnotations(annotations, null, p); + public static Annotation[] copyAnnotations(Annotation[] annotations, ASTNode source) { + return copyAnnotations(annotations, null, source); } - public static Annotation[] copyAnnotations(Annotation[] annotations1, Annotation[] annotations2, long p) { + public static Annotation[] copyAnnotations(Annotation[] annotations1, Annotation[] annotations2, ASTNode source) { if (annotations1 == null && annotations2 == null) return null; if (annotations1 == null) annotations1 = new Annotation[0]; if (annotations2 == null) annotations2 = new Annotation[0]; Annotation[] outs = new Annotation[annotations1.length + annotations2.length]; int idx = 0; for ( Annotation annotation : annotations1 ) { - outs[idx++] = copyAnnotation(annotation, p); + outs[idx++] = copyAnnotation(annotation, source); } for ( Annotation annotation : annotations2 ) { - outs[idx++] = copyAnnotation(annotation, p); + outs[idx++] = copyAnnotation(annotation, source); } return outs; } - public static Annotation copyAnnotation(Annotation annotation, long p) { - int pS = (int)(p >> 32), pE = (int)p; + public static Annotation copyAnnotation(Annotation annotation, ASTNode source) { + int pS = source.sourceStart, pE = source.sourceEnd; if (annotation instanceof MarkerAnnotation) { - MarkerAnnotation ann = new MarkerAnnotation(copyType(annotation.type), pS); + MarkerAnnotation ann = new MarkerAnnotation(copyType(annotation.type, source), pS); + setGeneratedBy(ann, source); ann.declarationSourceEnd = ann.sourceEnd = ann.statementEnd = pE; return ann; } if (annotation instanceof SingleMemberAnnotation) { - SingleMemberAnnotation ann = new SingleMemberAnnotation(copyType(annotation.type), pS); + SingleMemberAnnotation ann = new SingleMemberAnnotation(copyType(annotation.type, source), pS); + setGeneratedBy(ann, source); ann.declarationSourceEnd = ann.sourceEnd = ann.statementEnd = pE; //TODO memberValue(s) need to be copied as well (same for copying a NormalAnnotation as below). ann.memberValue = ((SingleMemberAnnotation)annotation).memberValue; @@ -294,7 +313,8 @@ public class Eclipse { } if (annotation instanceof NormalAnnotation) { - NormalAnnotation ann = new NormalAnnotation(copyType(annotation.type), pS); + NormalAnnotation ann = new NormalAnnotation(copyType(annotation.type, source), pS); + setGeneratedBy(ann, source); ann.declarationSourceEnd = ann.statementEnd = ann.sourceEnd = pE; ann.memberValuePairs = ((NormalAnnotation)annotation).memberValuePairs; return ann; @@ -425,4 +445,36 @@ public class Eclipse { return null; } + + private static Field generatedByField; + + static { + try { + generatedByField = ASTNode.class.getDeclaredField("$generatedBy"); + } catch ( Throwable t ) { + throw Lombok.sneakyThrow(t); + } + } + + public static ASTNode getGeneratedBy(ASTNode node) { + try { + return (ASTNode) generatedByField.get(node); + } catch ( Exception t ) { + throw Lombok.sneakyThrow(t); + } + } + + public static boolean isGenerated(ASTNode node) { + return getGeneratedBy(node) != null; + } + + public static ASTNode setGeneratedBy(ASTNode node, ASTNode source) { + try { + generatedByField.set(node, source); + } catch ( Exception t ) { + throw Lombok.sneakyThrow(t); + } + + return node; + } } diff --git a/src/lombok/eclipse/EclipseASTVisitor.java b/src/lombok/eclipse/EclipseASTVisitor.java index 6cc4130f..39c785d1 100644 --- a/src/lombok/eclipse/EclipseASTVisitor.java +++ b/src/lombok/eclipse/EclipseASTVisitor.java @@ -165,7 +165,7 @@ public interface EclipseASTVisitor { out.println("---------------------------------------------------------"); out.println(node.isCompleteParse() ? "COMPLETE" : "incomplete"); - print("<CUD %s>", node.getFileName()); + print("<CUD %s%s>", node.getFileName(), Eclipse.isGenerated(unit) ? " (GENERATED)" : ""); indent++; } @@ -175,7 +175,7 @@ public interface EclipseASTVisitor { } public void visitType(Node node, TypeDeclaration type) { - print("<TYPE %s>", str(type.name)); + print("<TYPE %s%s>", str(type.name), Eclipse.isGenerated(type) ? " (GENERATED)" : ""); indent++; if ( printContent ) { print("%s", type); @@ -184,7 +184,7 @@ public interface EclipseASTVisitor { } public void visitAnnotationOnType(TypeDeclaration type, Node node, Annotation annotation) { - forcePrint("<ANNOTATION: %s />", annotation); + forcePrint("<ANNOTATION%s: %s />", Eclipse.isGenerated(annotation) ? " (GENERATED)" : "", annotation); } public void endVisitType(Node node, TypeDeclaration type) { @@ -196,9 +196,10 @@ public interface EclipseASTVisitor { public void visitInitializer(Node node, Initializer initializer) { Block block = initializer.block; boolean s = (block != null && block.statements != null); - print("<%s INITIALIZER: %s>", + print("<%s INITIALIZER: %s%s>", (initializer.modifiers & Modifier.STATIC) != 0 ? "static" : "instance", - s ? "filled" : "blank"); + s ? "filled" : "blank", + Eclipse.isGenerated(initializer) ? " (GENERATED)" : ""); indent++; if ( printContent ) { if ( initializer.block != null ) print("%s", initializer.block); @@ -213,7 +214,8 @@ public interface EclipseASTVisitor { } public void visitField(Node node, FieldDeclaration field) { - print("<FIELD %s %s = %s>", str(field.type), str(field.name), field.initialization); + print("<FIELD%s %s %s = %s>", Eclipse.isGenerated(field) ? " (GENERATED)" : "", + str(field.type), str(field.name), field.initialization); indent++; if ( printContent ) { if ( field.initialization != null ) print("%s", field.initialization); @@ -222,7 +224,7 @@ public interface EclipseASTVisitor { } public void visitAnnotationOnField(FieldDeclaration field, Node node, Annotation annotation) { - forcePrint("<ANNOTATION: %s />", annotation); + forcePrint("<ANNOTATION%s: %s />", Eclipse.isGenerated(annotation) ? " (GENERATED)" : "", annotation); } public void endVisitField(Node node, FieldDeclaration field) { @@ -233,7 +235,8 @@ public interface EclipseASTVisitor { public void visitMethod(Node node, AbstractMethodDeclaration method) { String type = method instanceof ConstructorDeclaration ? "CONSTRUCTOR" : "METHOD"; - print("<%s %s: %s>", type, str(method.selector), method.statements != null ? "filled" : "blank"); + print("<%s %s: %s%s>", type, str(method.selector), method.statements != null ? "filled" : "blank", + Eclipse.isGenerated(method) ? " (GENERATED)" : ""); indent++; if ( printContent ) { if ( method.statements != null ) print("%s", method); @@ -242,7 +245,7 @@ public interface EclipseASTVisitor { } public void visitAnnotationOnMethod(AbstractMethodDeclaration method, Node node, Annotation annotation) { - forcePrint("<ANNOTATION: %s />", annotation); + forcePrint("<ANNOTATION%s: %s />", Eclipse.isGenerated(method) ? " (GENERATED)" : "", annotation); } public void endVisitMethod(Node node, AbstractMethodDeclaration method) { @@ -253,12 +256,12 @@ public interface EclipseASTVisitor { } public void visitMethodArgument(Node node, Argument arg, AbstractMethodDeclaration method) { - print("<METHODARG %s %s = %s>", str(arg.type), str(arg.name), arg.initialization); + print("<METHODARG%s %s %s = %s>", Eclipse.isGenerated(arg) ? " (GENERATED)" : "", str(arg.type), str(arg.name), arg.initialization); indent++; } public void visitAnnotationOnMethodArgument(Argument arg, AbstractMethodDeclaration method, Node node, Annotation annotation) { - print("<ANNOTATION: %s />", annotation); + print("<ANNOTATION%s: %s />", Eclipse.isGenerated(annotation) ? " (GENERATED)" : "", annotation); } public void endVisitMethodArgument(Node node, Argument arg, AbstractMethodDeclaration method) { @@ -267,12 +270,12 @@ public interface EclipseASTVisitor { } public void visitLocal(Node node, LocalDeclaration local) { - print("<LOCAL %s %s = %s>", str(local.type), str(local.name), local.initialization); + print("<LOCAL%s %s %s = %s>", Eclipse.isGenerated(local) ? " (GENERATED)" : "", str(local.type), str(local.name), local.initialization); indent++; } public void visitAnnotationOnLocal(LocalDeclaration local, Node node, Annotation annotation) { - print("<ANNOTATION: %s />", annotation); + print("<ANNOTATION%s: %s />", Eclipse.isGenerated(annotation) ? " (GENERATED)" : "", annotation); } public void endVisitLocal(Node node, LocalDeclaration local) { @@ -281,7 +284,7 @@ public interface EclipseASTVisitor { } public void visitStatement(Node node, Statement statement) { - print("<%s>", statement.getClass()); + print("<%s%s>", statement.getClass(), Eclipse.isGenerated(statement) ? " (GENERATED)" : ""); indent++; print("%s", statement); } diff --git a/src/lombok/eclipse/handlers/HandleCleanup.java b/src/lombok/eclipse/handlers/HandleCleanup.java index 9621e81c..07c921ab 100644 --- a/src/lombok/eclipse/handlers/HandleCleanup.java +++ b/src/lombok/eclipse/handlers/HandleCleanup.java @@ -26,6 +26,7 @@ import java.util.Arrays; import lombok.Cleanup; import lombok.core.AnnotationValues; import lombok.core.AST.Kind; +import lombok.eclipse.Eclipse; import lombok.eclipse.EclipseAnnotationHandler; import lombok.eclipse.EclipseAST.Node; @@ -134,15 +135,18 @@ public class HandleCleanup implements EclipseAnnotationHandler<Cleanup> { doAssignmentCheck(annotationNode, tryBlock, decl.name); TryStatement tryStatement = new TryStatement(); + Eclipse.setGeneratedBy(tryStatement, ast); tryStatement.tryBlock = new Block(0); tryStatement.tryBlock.statements = tryBlock; newStatements[start] = tryStatement; Statement[] finallyBlock = new Statement[1]; MessageSend unsafeClose = new MessageSend(); + Eclipse.setGeneratedBy(unsafeClose, ast); unsafeClose.sourceStart = ast.sourceStart; unsafeClose.sourceEnd = ast.sourceEnd; SingleNameReference receiver = new SingleNameReference(decl.name, 0); + Eclipse.setGeneratedBy(receiver, ast); unsafeClose.receiver = receiver; long nameSourcePosition = (long)ast.sourceStart << 32 | ast.sourceEnd; if ( ast.memberValuePairs() != null ) for ( MemberValuePair pair : ast.memberValuePairs() ) { @@ -155,6 +159,7 @@ public class HandleCleanup implements EclipseAnnotationHandler<Cleanup> { unsafeClose.selector = cleanupName.toCharArray(); finallyBlock[0] = unsafeClose; tryStatement.finallyBlock = new Block(0); + Eclipse.setGeneratedBy(tryStatement.finallyBlock, ast); tryStatement.finallyBlock.statements = finallyBlock; tryStatement.catchArguments = null; @@ -170,7 +175,6 @@ public class HandleCleanup implements EclipseAnnotationHandler<Cleanup> { ancestor.rebuild(); - return true; } diff --git a/src/lombok/eclipse/handlers/HandleData.java b/src/lombok/eclipse/handlers/HandleData.java index 385f56d4..2761c20b 100644 --- a/src/lombok/eclipse/handlers/HandleData.java +++ b/src/lombok/eclipse/handlers/HandleData.java @@ -122,21 +122,23 @@ public class HandleData implements EclipseAnnotationHandler<Data> { return false; } - private ConstructorDeclaration createConstructor(boolean isPublic, Node type, Collection<Node> fields, ASTNode pos) { - long p = (long)pos.sourceStart << 32 | pos.sourceEnd; + private ConstructorDeclaration createConstructor(boolean isPublic, Node type, Collection<Node> fields, ASTNode source) { + long p = (long)source.sourceStart << 32 | source.sourceEnd; ConstructorDeclaration constructor = new ConstructorDeclaration( ((CompilationUnitDeclaration) type.top().get()).compilationResult); + Eclipse.setGeneratedBy(constructor, source); constructor.modifiers = PKG.toModifier(isPublic ? AccessLevel.PUBLIC : AccessLevel.PRIVATE); constructor.annotations = null; constructor.selector = ((TypeDeclaration)type.get()).name; constructor.constructorCall = new ExplicitConstructorCall(ExplicitConstructorCall.ImplicitSuper); + Eclipse.setGeneratedBy(constructor.constructorCall, source); constructor.thrownExceptions = null; constructor.typeParameters = null; constructor.bits |= Eclipse.ECLIPSE_DO_NOT_TOUCH_FLAG; - constructor.bodyStart = constructor.declarationSourceStart = constructor.sourceStart = pos.sourceStart; - constructor.bodyEnd = constructor.declarationSourceEnd = constructor.sourceEnd = pos.sourceEnd; + constructor.bodyStart = constructor.declarationSourceStart = constructor.sourceStart = source.sourceStart; + constructor.bodyEnd = constructor.declarationSourceEnd = constructor.sourceEnd = source.sourceEnd; constructor.arguments = null; List<Argument> args = new ArrayList<Argument>(); @@ -146,19 +148,26 @@ public class HandleData implements EclipseAnnotationHandler<Data> { for ( Node fieldNode : fields ) { FieldDeclaration field = (FieldDeclaration) fieldNode.get(); FieldReference thisX = new FieldReference(("this." + new String(field.name)).toCharArray(), p); + Eclipse.setGeneratedBy(thisX, source); thisX.receiver = new ThisReference((int)(p >> 32), (int)p); + Eclipse.setGeneratedBy(thisX.receiver, source); thisX.token = field.name; - assigns.add(new Assignment(thisX, new SingleNameReference(field.name, p), (int)p)); + SingleNameReference assignmentNameRef = new SingleNameReference(field.name, p); + Eclipse.setGeneratedBy(assignmentNameRef, source); + Assignment assignment = new Assignment(thisX, assignmentNameRef, (int)p); + Eclipse.setGeneratedBy(assignment, source); + assigns.add(assignment); long fieldPos = (((long)field.sourceStart) << 32) | field.sourceEnd; - Argument argument = new Argument(field.name, fieldPos, copyType(field.type), Modifier.FINAL); + Argument argument = new Argument(field.name, fieldPos, copyType(field.type, source), Modifier.FINAL); + Eclipse.setGeneratedBy(argument, source); Annotation[] nonNulls = findAnnotations(field, TransformationsUtil.NON_NULL_PATTERN); Annotation[] nullables = findAnnotations(field, TransformationsUtil.NULLABLE_PATTERN); if (nonNulls.length != 0) { - Statement nullCheck = generateNullCheck(field); + Statement nullCheck = generateNullCheck(field, source); if (nullCheck != null) nullChecks.add(nullCheck); } - Annotation[] copiedAnnotations = copyAnnotations(nonNulls, nullables, p); + Annotation[] copiedAnnotations = copyAnnotations(nonNulls, nullables, source); if (copiedAnnotations.length != 0) argument.annotations = copiedAnnotations; args.add(argument); } @@ -169,11 +178,13 @@ public class HandleData implements EclipseAnnotationHandler<Data> { return constructor; } - private MethodDeclaration createStaticConstructor(String name, Node type, Collection<Node> fields, ASTNode pos) { - long p = (long)pos.sourceStart << 32 | pos.sourceEnd; + private MethodDeclaration createStaticConstructor(String name, Node type, Collection<Node> fields, ASTNode source) { + int pS = source.sourceStart, pE = source.sourceEnd; + long p = (long)pS << 32 | pE; MethodDeclaration constructor = new MethodDeclaration( ((CompilationUnitDeclaration) type.top().get()).compilationResult); + Eclipse.setGeneratedBy(constructor, source); constructor.modifiers = PKG.toModifier(AccessLevel.PUBLIC) | Modifier.STATIC; TypeDeclaration typeDecl = (TypeDeclaration) type.get(); @@ -181,38 +192,49 @@ public class HandleData implements EclipseAnnotationHandler<Data> { TypeReference[] refs = new TypeReference[typeDecl.typeParameters.length]; int idx = 0; for ( TypeParameter param : typeDecl.typeParameters ) { - refs[idx++] = new SingleTypeReference(param.name, (long)param.sourceStart << 32 | param.sourceEnd); + TypeReference typeRef = new SingleTypeReference(param.name, (long)param.sourceStart << 32 | param.sourceEnd); + Eclipse.setGeneratedBy(typeRef, source); + refs[idx++] = typeRef; } constructor.returnType = new ParameterizedSingleTypeReference(typeDecl.name, refs, 0, p); } else constructor.returnType = new SingleTypeReference(((TypeDeclaration)type.get()).name, p); + Eclipse.setGeneratedBy(constructor.returnType, source); constructor.annotations = null; constructor.selector = name.toCharArray(); constructor.thrownExceptions = null; - constructor.typeParameters = copyTypeParams(((TypeDeclaration)type.get()).typeParameters); + constructor.typeParameters = copyTypeParams(((TypeDeclaration)type.get()).typeParameters, source); constructor.bits |= Eclipse.ECLIPSE_DO_NOT_TOUCH_FLAG; - constructor.bodyStart = constructor.declarationSourceStart = constructor.sourceStart = pos.sourceStart; - constructor.bodyEnd = constructor.declarationSourceEnd = constructor.sourceEnd = pos.sourceEnd; + constructor.bodyStart = constructor.declarationSourceStart = constructor.sourceStart = source.sourceStart; + constructor.bodyEnd = constructor.declarationSourceEnd = constructor.sourceEnd = source.sourceEnd; List<Argument> args = new ArrayList<Argument>(); List<Expression> assigns = new ArrayList<Expression>(); AllocationExpression statement = new AllocationExpression(); - statement.type = copyType(constructor.returnType); + statement.sourceStart = pS; statement.sourceEnd = pE; + Eclipse.setGeneratedBy(statement, source); + statement.type = copyType(constructor.returnType, source); for ( Node fieldNode : fields ) { FieldDeclaration field = (FieldDeclaration) fieldNode.get(); long fieldPos = (((long)field.sourceStart) << 32) | field.sourceEnd; - assigns.add(new SingleNameReference(field.name, fieldPos)); + SingleNameReference nameRef = new SingleNameReference(field.name, fieldPos); + Eclipse.setGeneratedBy(nameRef, source); + assigns.add(nameRef); - Argument argument = new Argument(field.name, fieldPos, copyType(field.type), 0); + Argument argument = new Argument(field.name, fieldPos, copyType(field.type, source), 0); + Eclipse.setGeneratedBy(argument, source); + Annotation[] copiedAnnotations = copyAnnotations( - findAnnotations(field, TransformationsUtil.NON_NULL_PATTERN), findAnnotations(field, TransformationsUtil.NULLABLE_PATTERN), p); + findAnnotations(field, TransformationsUtil.NON_NULL_PATTERN), + findAnnotations(field, TransformationsUtil.NULLABLE_PATTERN), source); if (copiedAnnotations.length != 0) argument.annotations = copiedAnnotations; - args.add(new Argument(field.name, fieldPos, copyType(field.type), Modifier.FINAL)); + args.add(new Argument(field.name, fieldPos, copyType(field.type, source), Modifier.FINAL)); } statement.arguments = assigns.isEmpty() ? null : assigns.toArray(new Expression[assigns.size()]); constructor.arguments = args.isEmpty() ? null : args.toArray(new Argument[args.size()]); constructor.statements = new Statement[] { new ReturnStatement(statement, (int)(p >> 32), (int)p) }; + Eclipse.setGeneratedBy(constructor.statements[0], source); return constructor; } } diff --git a/src/lombok/eclipse/handlers/HandleEqualsAndHashCode.java b/src/lombok/eclipse/handlers/HandleEqualsAndHashCode.java index 46792236..209c095c 100644 --- a/src/lombok/eclipse/handlers/HandleEqualsAndHashCode.java +++ b/src/lombok/eclipse/handlers/HandleEqualsAndHashCode.java @@ -234,22 +234,24 @@ public class HandleEqualsAndHashCode implements EclipseAnnotationHandler<EqualsA return true; } - private MethodDeclaration createHashCode(Node type, Collection<Node> fields, boolean callSuper, ASTNode pos) { - int pS = pos.sourceStart, pE = pos.sourceEnd; + private MethodDeclaration createHashCode(Node type, Collection<Node> fields, boolean callSuper, ASTNode source) { + int pS = source.sourceStart, pE = source.sourceEnd; long p = (long)pS << 32 | pE; MethodDeclaration method = new MethodDeclaration( ((CompilationUnitDeclaration) type.top().get()).compilationResult); + Eclipse.setGeneratedBy(method, source); method.modifiers = PKG.toModifier(AccessLevel.PUBLIC); method.returnType = TypeReference.baseTypeReference(TypeIds.T_int, 0); - method.annotations = new Annotation[] {makeMarkerAnnotation(TypeConstants.JAVA_LANG_OVERRIDE, p)}; + Eclipse.setGeneratedBy(method.returnType, source); + method.annotations = new Annotation[] {makeMarkerAnnotation(TypeConstants.JAVA_LANG_OVERRIDE, source)}; method.selector = "hashCode".toCharArray(); method.thrownExceptions = null; method.typeParameters = null; 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.bodyStart = method.declarationSourceStart = method.sourceStart = source.sourceStart; + method.bodyEnd = method.declarationSourceEnd = method.sourceEnd = source.sourceEnd; method.arguments = null; List<Statement> statements = new ArrayList<Statement>(); @@ -263,23 +265,34 @@ public class HandleEqualsAndHashCode implements EclipseAnnotationHandler<EqualsA /* Without fields, PRIME isn't used, and that would trigger a 'local variable not used' warning. */ if ( !isEmpty || callSuper ) { LocalDeclaration primeDecl = new LocalDeclaration(PRIME, pS, pE); + Eclipse.setGeneratedBy(primeDecl, source); primeDecl.modifiers |= Modifier.FINAL; primeDecl.type = TypeReference.baseTypeReference(TypeIds.T_int, 0); + primeDecl.type.sourceStart = pS; primeDecl.type.sourceEnd = pE; + Eclipse.setGeneratedBy(primeDecl.type, source); primeDecl.initialization = new IntLiteral("31".toCharArray(), pS, pE); + Eclipse.setGeneratedBy(primeDecl.initialization, source); statements.add(primeDecl); } } /* int result = 1; */ { LocalDeclaration resultDecl = new LocalDeclaration(RESULT, pS, pE); + Eclipse.setGeneratedBy(resultDecl, source); resultDecl.initialization = new IntLiteral("1".toCharArray(), pS, pE); + Eclipse.setGeneratedBy(resultDecl.initialization, source); resultDecl.type = TypeReference.baseTypeReference(TypeIds.T_int, 0); + resultDecl.type.sourceStart = pS; resultDecl.type.sourceEnd = pE; + Eclipse.setGeneratedBy(resultDecl.type, source); statements.add(resultDecl); } if ( callSuper ) { MessageSend callToSuper = new MessageSend(); + Eclipse.setGeneratedBy(callToSuper, source); + callToSuper.sourceStart = pS; callToSuper.sourceEnd = pE; callToSuper.receiver = new SuperReference(pS, pE); + Eclipse.setGeneratedBy(callToSuper.receiver, source); callToSuper.selector = "hashCode".toCharArray(); intoResult.add(callToSuper); } @@ -292,59 +305,79 @@ public class HandleEqualsAndHashCode implements EclipseAnnotationHandler<EqualsA if ( Arrays.equals(TypeConstants.FLOAT, token) ) { /* Float.floatToIntBits(fieldName) */ MessageSend floatToIntBits = new MessageSend(); - floatToIntBits.receiver = generateQualifiedNameRef(p, TypeConstants.JAVA_LANG_FLOAT); + floatToIntBits.sourceStart = pS; floatToIntBits.sourceEnd = pE; + Eclipse.setGeneratedBy(floatToIntBits, source); + floatToIntBits.receiver = generateQualifiedNameRef(source, TypeConstants.JAVA_LANG_FLOAT); floatToIntBits.selector = "floatToIntBits".toCharArray(); - floatToIntBits.arguments = new Expression[] { generateFieldReference(f.name, p) }; + floatToIntBits.arguments = new Expression[] { generateFieldReference(f.name, source) }; intoResult.add(floatToIntBits); } else if ( Arrays.equals(TypeConstants.DOUBLE, token) ) { /* longToIntForHashCode(Double.doubleToLongBits(fieldName)) */ MessageSend doubleToLongBits = new MessageSend(); - doubleToLongBits.receiver = generateQualifiedNameRef(p, TypeConstants.JAVA_LANG_DOUBLE); + doubleToLongBits.sourceStart = pS; doubleToLongBits.sourceEnd = pE; + Eclipse.setGeneratedBy(doubleToLongBits, source); + doubleToLongBits.receiver = generateQualifiedNameRef(source, TypeConstants.JAVA_LANG_DOUBLE); doubleToLongBits.selector = "doubleToLongBits".toCharArray(); - doubleToLongBits.arguments = new Expression[] { generateFieldReference(f.name, p) }; + doubleToLongBits.arguments = new Expression[] { generateFieldReference(f.name, source) }; final char[] tempName = ("temp" + ++tempCounter).toCharArray(); LocalDeclaration tempVar = new LocalDeclaration(tempName, pS, pE); + Eclipse.setGeneratedBy(tempVar, source); tempVar.initialization = doubleToLongBits; tempVar.type = TypeReference.baseTypeReference(TypeIds.T_long, 0); + tempVar.type.sourceStart = pS; tempVar.type.sourceEnd = pE; + Eclipse.setGeneratedBy(tempVar.type, source); tempVar.modifiers = Modifier.FINAL; statements.add(tempVar); - intoResult.add(longToIntForHashCode( - new SingleNameReference(tempName, p), new SingleNameReference(tempName, p), p)); + SingleNameReference copy1 = new SingleNameReference(tempName, p); + Eclipse.setGeneratedBy(copy1, source); + SingleNameReference copy2 = new SingleNameReference(tempName, p); + Eclipse.setGeneratedBy(copy2, source); + intoResult.add(longToIntForHashCode(copy1, copy2, source)); } else if ( Arrays.equals(TypeConstants.BOOLEAN, token) ) { /* booleanField ? 1231 : 1237 */ - intoResult.add(new ConditionalExpression( - generateFieldReference(f.name, p), - new IntLiteral("1231".toCharArray(), pS, pE), - new IntLiteral("1237".toCharArray(), pS, pE))); + IntLiteral int1231 = new IntLiteral("1231".toCharArray(), pS, pE); + Eclipse.setGeneratedBy(int1231, source); + IntLiteral int1237 = new IntLiteral("1237".toCharArray(), pS, pE); + Eclipse.setGeneratedBy(int1237, source); + ConditionalExpression int1231or1237 = new ConditionalExpression( + generateFieldReference(f.name, source), int1231, int1237); + Eclipse.setGeneratedBy(int1231or1237, source); + intoResult.add(int1231or1237); } else if ( Arrays.equals(TypeConstants.LONG, token) ) { - intoResult.add(longToIntForHashCode(generateFieldReference(f.name, p), generateFieldReference(f.name, p), p)); + intoResult.add(longToIntForHashCode(generateFieldReference(f.name, source), generateFieldReference(f.name, source), source)); } else if ( BUILT_IN_TYPES.contains(new String(token)) ) { - intoResult.add(generateFieldReference(f.name, p)); + intoResult.add(generateFieldReference(f.name, source)); } else /* objects */ { /* this.fieldName == null ? 0 : this.fieldName.hashCode() */ MessageSend hashCodeCall = new MessageSend(); - hashCodeCall.receiver = generateFieldReference(f.name, p); + hashCodeCall.sourceStart = pS; hashCodeCall.sourceEnd = pE; + Eclipse.setGeneratedBy(hashCodeCall, source); + hashCodeCall.receiver = generateFieldReference(f.name, source); hashCodeCall.selector = "hashCode".toCharArray(); + NullLiteral nullLiteral = new NullLiteral(pS, pE); + Eclipse.setGeneratedBy(nullLiteral, source); EqualExpression objIsNull = new EqualExpression( - generateFieldReference(f.name, p), - new NullLiteral(pS, pE), - OperatorIds.EQUAL_EQUAL); - ConditionalExpression nullOrHashCode = new ConditionalExpression( - objIsNull, - new IntLiteral("0".toCharArray(), pS, pE), - hashCodeCall); + generateFieldReference(f.name, source), nullLiteral, OperatorIds.EQUAL_EQUAL); + Eclipse.setGeneratedBy(objIsNull, source); + IntLiteral int0 = new IntLiteral("0".toCharArray(), pS, pE); + Eclipse.setGeneratedBy(int0, source); + ConditionalExpression nullOrHashCode = new ConditionalExpression(objIsNull, int0, hashCodeCall); + nullOrHashCode.sourceStart = pS; nullOrHashCode.sourceEnd = pE; + Eclipse.setGeneratedBy(nullOrHashCode, source); intoResult.add(nullOrHashCode); } } else if ( f.type.dimensions() > 0 && token != null ) { /* Arrays.deepHashCode(array) //just hashCode for simple arrays */ MessageSend arraysHashCodeCall = new MessageSend(); - arraysHashCodeCall.receiver = generateQualifiedNameRef(p, TypeConstants.JAVA, TypeConstants.UTIL, "Arrays".toCharArray()); + arraysHashCodeCall.sourceStart = pS; arraysHashCodeCall.sourceEnd = pE; + Eclipse.setGeneratedBy(arraysHashCodeCall, source); + arraysHashCodeCall.receiver = generateQualifiedNameRef(source, TypeConstants.JAVA, TypeConstants.UTIL, "Arrays".toCharArray()); if ( f.type.dimensions() > 1 || !BUILT_IN_TYPES.contains(new String(token)) ) { arraysHashCodeCall.selector = "deepHashCode".toCharArray(); } else { arraysHashCodeCall.selector = "hashCode".toCharArray(); } - arraysHashCodeCall.arguments = new Expression[] { generateFieldReference(f.name, p) }; + arraysHashCodeCall.arguments = new Expression[] { generateFieldReference(f.name, source) }; intoResult.add(arraysHashCodeCall); } } @@ -352,73 +385,117 @@ public class HandleEqualsAndHashCode implements EclipseAnnotationHandler<EqualsA /* fold each intoResult entry into: result = result * PRIME + (item); */ { for ( Expression ex : intoResult ) { - BinaryExpression multiplyByPrime = new BinaryExpression(new SingleNameReference(RESULT, p), - new SingleNameReference(PRIME, 0), OperatorIds.MULTIPLY); + SingleNameReference resultRef = new SingleNameReference(RESULT, p); + Eclipse.setGeneratedBy(resultRef, source); + SingleNameReference primeRef = new SingleNameReference(PRIME, p); + Eclipse.setGeneratedBy(primeRef, source); + BinaryExpression multiplyByPrime = new BinaryExpression(resultRef, primeRef, OperatorIds.MULTIPLY); + multiplyByPrime.sourceStart = pS; multiplyByPrime.sourceEnd = pE; + Eclipse.setGeneratedBy(multiplyByPrime, source); BinaryExpression addItem = new BinaryExpression(multiplyByPrime, ex, OperatorIds.PLUS); - statements.add(new Assignment(new SingleNameReference(RESULT, p), addItem, pE)); + addItem.sourceStart = pS; addItem.sourceEnd = pE; + Eclipse.setGeneratedBy(addItem, source); + resultRef = new SingleNameReference(RESULT, p); + Eclipse.setGeneratedBy(resultRef, source); + Assignment assignment = new Assignment(resultRef, addItem, pE); + assignment.sourceStart = pS; assignment.sourceEnd = pE; + Eclipse.setGeneratedBy(assignment, source); + statements.add(assignment); } } /* return result; */ { - statements.add(new ReturnStatement(new SingleNameReference(RESULT, p), pS, pE)); + SingleNameReference resultRef = new SingleNameReference(RESULT, p); + Eclipse.setGeneratedBy(resultRef, source); + ReturnStatement returnStatement = new ReturnStatement(resultRef, pS, pE); + Eclipse.setGeneratedBy(returnStatement, source); + statements.add(returnStatement); } method.statements = statements.toArray(new Statement[statements.size()]); return method; } - private MethodDeclaration createEquals(Node type, Collection<Node> fields, boolean callSuper, ASTNode pos) { - int pS = pos.sourceStart; int pE = pos.sourceEnd; + private MethodDeclaration createEquals(Node type, Collection<Node> fields, boolean callSuper, ASTNode source) { + int pS = source.sourceStart; int pE = source.sourceEnd; long p = (long)pS << 32 | pE; MethodDeclaration method = new MethodDeclaration( ((CompilationUnitDeclaration) type.top().get()).compilationResult); - + Eclipse.setGeneratedBy(method, source); method.modifiers = PKG.toModifier(AccessLevel.PUBLIC); method.returnType = TypeReference.baseTypeReference(TypeIds.T_boolean, 0); - method.annotations = new Annotation[] {makeMarkerAnnotation(TypeConstants.JAVA_LANG_OVERRIDE, p)}; + method.returnType.sourceStart = pS; method.returnType.sourceEnd = pE; + Eclipse.setGeneratedBy(method.returnType, source); + method.annotations = new Annotation[] {makeMarkerAnnotation(TypeConstants.JAVA_LANG_OVERRIDE, source)}; method.selector = "equals".toCharArray(); method.thrownExceptions = null; method.typeParameters = null; 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.arguments = new Argument[] { - new Argument(new char[] { 'o' }, 0, - new QualifiedTypeReference(TypeConstants.JAVA_LANG_OBJECT, new long[] { p, p, p }), Modifier.FINAL) - }; + method.bodyStart = method.declarationSourceStart = method.sourceStart = source.sourceStart; + method.bodyEnd = method.declarationSourceEnd = method.sourceEnd = source.sourceEnd; + TypeReference objectRef = new QualifiedTypeReference(TypeConstants.JAVA_LANG_OBJECT, new long[] { p, p, p }); + Eclipse.setGeneratedBy(objectRef, source); + method.arguments = new Argument[] {new Argument(new char[] { 'o' }, 0, objectRef, Modifier.FINAL)}; + method.arguments[0].sourceStart = pS; method.arguments[0].sourceEnd = pE; + Eclipse.setGeneratedBy(method.arguments[0], source); List<Statement> statements = new ArrayList<Statement>(); /* if ( o == this ) return true; */ { - EqualExpression otherEqualsThis = new EqualExpression( - new SingleNameReference(new char[] { 'o' }, p), - new ThisReference(pS, pE), OperatorIds.EQUAL_EQUAL); + SingleNameReference oRef = new SingleNameReference(new char[] { 'o' }, p); + Eclipse.setGeneratedBy(oRef, source); + ThisReference thisRef = new ThisReference(pS, pE); + Eclipse.setGeneratedBy(thisRef, source); + EqualExpression otherEqualsThis = new EqualExpression(oRef, thisRef, OperatorIds.EQUAL_EQUAL); + Eclipse.setGeneratedBy(otherEqualsThis, source); - ReturnStatement returnTrue = new ReturnStatement(new TrueLiteral(pS, pE), pS, pE); + TrueLiteral trueLiteral = new TrueLiteral(pS, pE); + Eclipse.setGeneratedBy(trueLiteral, source); + ReturnStatement returnTrue = new ReturnStatement(trueLiteral, pS, pE); + Eclipse.setGeneratedBy(returnTrue, source); IfStatement ifOtherEqualsThis = new IfStatement(otherEqualsThis, returnTrue, pS, pE); + Eclipse.setGeneratedBy(ifOtherEqualsThis, source); statements.add(ifOtherEqualsThis); } /* if ( o == null ) return false; */ { - EqualExpression otherEqualsNull = new EqualExpression( - new SingleNameReference(new char[] { 'o' }, p), - new NullLiteral(pS, pE), OperatorIds.EQUAL_EQUAL); + SingleNameReference oRef = new SingleNameReference(new char[] { 'o' }, p); + Eclipse.setGeneratedBy(oRef, source); + NullLiteral nullLiteral = new NullLiteral(pS, pE); + Eclipse.setGeneratedBy(nullLiteral, source); + EqualExpression otherEqualsNull = new EqualExpression(oRef, nullLiteral, OperatorIds.EQUAL_EQUAL); + Eclipse.setGeneratedBy(otherEqualsNull, source); - ReturnStatement returnFalse = new ReturnStatement(new FalseLiteral(pS, pE), pS, pE); + FalseLiteral falseLiteral = new FalseLiteral(pS, pE); + Eclipse.setGeneratedBy(falseLiteral, source); + ReturnStatement returnFalse = new ReturnStatement(falseLiteral, pS, pE); + Eclipse.setGeneratedBy(returnFalse, source); IfStatement ifOtherEqualsNull = new IfStatement(otherEqualsNull, returnFalse, pS, pE); + Eclipse.setGeneratedBy(ifOtherEqualsNull, source); statements.add(ifOtherEqualsNull); } /* if ( o.getClass() != getClass() ) return false; */ { MessageSend otherGetClass = new MessageSend(); + otherGetClass.sourceStart = pS; otherGetClass.sourceEnd = pE; + Eclipse.setGeneratedBy(otherGetClass, source); otherGetClass.receiver = new SingleNameReference(new char[] { 'o' }, p); + Eclipse.setGeneratedBy(otherGetClass.receiver, source); otherGetClass.selector = "getClass".toCharArray(); MessageSend thisGetClass = new MessageSend(); + thisGetClass.sourceStart = pS; thisGetClass.sourceEnd = pE; + Eclipse.setGeneratedBy(thisGetClass, source); thisGetClass.receiver = new ThisReference(pS, pE); + Eclipse.setGeneratedBy(thisGetClass.receiver, source); thisGetClass.selector = "getClass".toCharArray(); EqualExpression classesNotEqual = new EqualExpression(otherGetClass, thisGetClass, OperatorIds.NOT_EQUAL); - ReturnStatement returnFalse = new ReturnStatement(new FalseLiteral(pS, pE), pS, pE); + Eclipse.setGeneratedBy(classesNotEqual, source); + FalseLiteral falseLiteral = new FalseLiteral(pS, pE); + Eclipse.setGeneratedBy(falseLiteral, source); + ReturnStatement returnFalse = new ReturnStatement(falseLiteral, pS, pE); + Eclipse.setGeneratedBy(returnFalse, source); IfStatement ifClassesNotEqual = new IfStatement(classesNotEqual, returnFalse, pS, pE); + Eclipse.setGeneratedBy(ifClassesNotEqual, source); statements.add(ifClassesNotEqual); } @@ -427,12 +504,22 @@ public class HandleEqualsAndHashCode implements EclipseAnnotationHandler<EqualsA /* if ( !super.equals(o) ) return false; */ if ( callSuper ) { MessageSend callToSuper = new MessageSend(); + callToSuper.sourceStart = pS; callToSuper.sourceEnd = pE; + Eclipse.setGeneratedBy(callToSuper, source); callToSuper.receiver = new SuperReference(pS, pE); + Eclipse.setGeneratedBy(callToSuper.receiver, source); callToSuper.selector = "equals".toCharArray(); - callToSuper.arguments = new Expression[] {new SingleNameReference(new char[] { 'o' }, p) }; + SingleNameReference oRef = new SingleNameReference(new char[] { 'o' }, p); + Eclipse.setGeneratedBy(oRef, source); + callToSuper.arguments = new Expression[] {oRef}; Expression superNotEqual = new UnaryExpression(callToSuper, OperatorIds.NOT); - ReturnStatement returnFalse = new ReturnStatement(new FalseLiteral(pS, pE), pS, pE); + Eclipse.setGeneratedBy(superNotEqual, source); + FalseLiteral falseLiteral = new FalseLiteral(pS, pE); + Eclipse.setGeneratedBy(falseLiteral, source); + ReturnStatement returnFalse = new ReturnStatement(falseLiteral, pS, pE); + Eclipse.setGeneratedBy(returnFalse, source); IfStatement ifSuperEquals = new IfStatement(superNotEqual, returnFalse, pS, pE); + Eclipse.setGeneratedBy(ifSuperEquals, source); statements.add(ifSuperEquals); } @@ -440,20 +527,30 @@ public class HandleEqualsAndHashCode implements EclipseAnnotationHandler<EqualsA /* MyType<?> other = (MyType<?>) o; */ { if ( !fields.isEmpty() ) { LocalDeclaration other = new LocalDeclaration(otherN, pS, pE); + Eclipse.setGeneratedBy(other, source); char[] typeName = typeDecl.name; Expression targetType; if ( typeDecl.typeParameters == null || typeDecl.typeParameters.length == 0 ) { targetType = new SingleNameReference(((TypeDeclaration)type.get()).name, p); + Eclipse.setGeneratedBy(targetType, source); other.type = new SingleTypeReference(typeName, p); + Eclipse.setGeneratedBy(other.type, source); } else { TypeReference[] typeArgs = new TypeReference[typeDecl.typeParameters.length]; - for ( int i = 0 ; i < typeArgs.length ; i++ ) typeArgs[i] = new Wildcard(Wildcard.UNBOUND); + for ( int i = 0 ; i < typeArgs.length ; i++ ) { + typeArgs[i] = new Wildcard(Wildcard.UNBOUND); + typeArgs[i].sourceStart = pS; typeArgs[i].sourceEnd = pE; + Eclipse.setGeneratedBy(typeArgs[i], source); + } targetType = new ParameterizedSingleTypeReference(typeName, typeArgs, 0, p); - other.type = new ParameterizedSingleTypeReference(typeName, copyTypes(typeArgs), 0, p); + Eclipse.setGeneratedBy(targetType, source); + other.type = new ParameterizedSingleTypeReference(typeName, copyTypes(typeArgs, source), 0, p); + Eclipse.setGeneratedBy(other.type, source); } - other.initialization = new CastExpression( - new SingleNameReference(new char[] { 'o' }, p), - targetType); + NameReference oRef = new SingleNameReference(new char[] { 'o' }, p); + Eclipse.setGeneratedBy(oRef, source); + other.initialization = new CastExpression(oRef, targetType); + Eclipse.setGeneratedBy(other.initialization, source); statements.add(other); } } @@ -463,92 +560,156 @@ public class HandleEqualsAndHashCode implements EclipseAnnotationHandler<EqualsA char[] token = f.type.getLastToken(); if ( f.type.dimensions() == 0 && token != null ) { if ( Arrays.equals(TypeConstants.FLOAT, token) ) { - statements.add(generateCompareFloatOrDouble(otherN, "Float".toCharArray(), f.name, p)); + statements.add(generateCompareFloatOrDouble(otherN, "Float".toCharArray(), f.name, source)); } else if ( Arrays.equals(TypeConstants.DOUBLE, token) ) { - statements.add(generateCompareFloatOrDouble(otherN, "Double".toCharArray(), f.name, p)); + statements.add(generateCompareFloatOrDouble(otherN, "Double".toCharArray(), f.name, source)); } else if ( BUILT_IN_TYPES.contains(new String(token)) ) { - EqualExpression fieldsNotEqual = new EqualExpression( - new SingleNameReference(f.name, p), - generateQualifiedNameRef(p, otherN, f.name), - OperatorIds.NOT_EQUAL); - ReturnStatement returnStatement = new ReturnStatement(new FalseLiteral(pS, pE), pS, pE); - statements.add(new IfStatement(fieldsNotEqual, returnStatement, pS, pE)); + NameReference fieldRef = new SingleNameReference(f.name, p); + Eclipse.setGeneratedBy(fieldRef, source); + EqualExpression fieldsNotEqual = new EqualExpression(fieldRef, + generateQualifiedNameRef(source, otherN, f.name), OperatorIds.NOT_EQUAL); + Eclipse.setGeneratedBy(fieldsNotEqual, source); + FalseLiteral falseLiteral = new FalseLiteral(pS, pE); + Eclipse.setGeneratedBy(falseLiteral, source); + ReturnStatement returnStatement = new ReturnStatement(falseLiteral, pS, pE); + Eclipse.setGeneratedBy(returnStatement, source); + IfStatement ifStatement = new IfStatement(fieldsNotEqual, returnStatement, pS, pE); + Eclipse.setGeneratedBy(ifStatement, source); + statements.add(ifStatement); } else /* objects */ { - EqualExpression fieldIsNull = new EqualExpression( - new SingleNameReference(f.name, p), - new NullLiteral(pS, pE), OperatorIds.EQUAL_EQUAL); + NameReference fieldNameRef = new SingleNameReference(f.name, p); + Eclipse.setGeneratedBy(fieldNameRef, source); + NullLiteral nullLiteral = new NullLiteral(pS, pE); + Eclipse.setGeneratedBy(nullLiteral, source); + EqualExpression fieldIsNull = new EqualExpression(fieldNameRef, nullLiteral, OperatorIds.EQUAL_EQUAL); + nullLiteral = new NullLiteral(pS, pE); + Eclipse.setGeneratedBy(nullLiteral, source); EqualExpression otherFieldIsntNull = new EqualExpression( - generateQualifiedNameRef(p, otherN, f.name), - new NullLiteral(pS, pE), OperatorIds.NOT_EQUAL); + generateQualifiedNameRef(source, otherN, f.name), + nullLiteral, OperatorIds.NOT_EQUAL); MessageSend equalsCall = new MessageSend(); + equalsCall.sourceStart = pS; equalsCall.sourceEnd = pE; + Eclipse.setGeneratedBy(equalsCall, source); equalsCall.receiver = new SingleNameReference(f.name, p); + Eclipse.setGeneratedBy(equalsCall.receiver, source); equalsCall.selector = "equals".toCharArray(); - equalsCall.arguments = new Expression[] { generateQualifiedNameRef(p, otherN, f.name) }; + equalsCall.arguments = new Expression[] { generateQualifiedNameRef(source, otherN, f.name) }; UnaryExpression fieldsNotEqual = new UnaryExpression(equalsCall, OperatorIds.NOT); + fieldsNotEqual.sourceStart = pS; fieldsNotEqual.sourceEnd = pE; + Eclipse.setGeneratedBy(fieldsNotEqual, source); ConditionalExpression fullEquals = new ConditionalExpression(fieldIsNull, otherFieldIsntNull, fieldsNotEqual); - ReturnStatement returnStatement = new ReturnStatement(new FalseLiteral(pS, pE), pS, pE); - statements.add(new IfStatement(fullEquals, returnStatement, pS, pE)); + fullEquals.sourceStart = pS; fullEquals.sourceEnd = pE; + Eclipse.setGeneratedBy(fullEquals, source); + FalseLiteral falseLiteral = new FalseLiteral(pS, pE); + Eclipse.setGeneratedBy(falseLiteral, source); + ReturnStatement returnStatement = new ReturnStatement(falseLiteral, pS, pE); + Eclipse.setGeneratedBy(returnStatement, source); + IfStatement ifStatement = new IfStatement(fullEquals, returnStatement, pS, pE); + Eclipse.setGeneratedBy(ifStatement, source); + statements.add(ifStatement); } } else if ( f.type.dimensions() > 0 && token != null ) { MessageSend arraysEqualCall = new MessageSend(); - arraysEqualCall.receiver = generateQualifiedNameRef(p, TypeConstants.JAVA, TypeConstants.UTIL, "Arrays".toCharArray()); + arraysEqualCall.sourceStart = pS; arraysEqualCall.sourceEnd = pE; + Eclipse.setGeneratedBy(arraysEqualCall, source); + arraysEqualCall.receiver = generateQualifiedNameRef(source, TypeConstants.JAVA, TypeConstants.UTIL, "Arrays".toCharArray()); if ( f.type.dimensions() > 1 || !BUILT_IN_TYPES.contains(new String(token)) ) { arraysEqualCall.selector = "deepEquals".toCharArray(); } else { arraysEqualCall.selector = "equals".toCharArray(); } - arraysEqualCall.arguments = new Expression[] { - new SingleNameReference(f.name, p), - generateQualifiedNameRef(p, otherN, f.name) }; + NameReference fieldNameRef = new SingleNameReference(f.name, p); + Eclipse.setGeneratedBy(fieldNameRef, source); + arraysEqualCall.arguments = new Expression[] { fieldNameRef, generateQualifiedNameRef(source, otherN, f.name) }; UnaryExpression arraysNotEqual = new UnaryExpression(arraysEqualCall, OperatorIds.NOT); - ReturnStatement returnStatement = new ReturnStatement(new FalseLiteral(pS, pE), pS, pE); - statements.add(new IfStatement(arraysNotEqual, returnStatement, pS, pE)); + arraysNotEqual.sourceStart = pS; arraysNotEqual.sourceEnd = pE; + Eclipse.setGeneratedBy(arraysNotEqual, source); + FalseLiteral falseLiteral = new FalseLiteral(pS, pE); + Eclipse.setGeneratedBy(falseLiteral, source); + ReturnStatement returnStatement = new ReturnStatement(falseLiteral, pS, pE); + Eclipse.setGeneratedBy(returnStatement, source); + IfStatement ifStatement = new IfStatement(arraysNotEqual, returnStatement, pS, pE); + Eclipse.setGeneratedBy(ifStatement, source); + statements.add(ifStatement); } } /* return true; */ { - statements.add(new ReturnStatement(new TrueLiteral(pS, pE), pS, pE)); + TrueLiteral trueLiteral = new TrueLiteral(pS, pE); + Eclipse.setGeneratedBy(trueLiteral, source); + ReturnStatement returnStatement = new ReturnStatement(trueLiteral, pS, pE); + Eclipse.setGeneratedBy(returnStatement, source); + statements.add(returnStatement); } method.statements = statements.toArray(new Statement[statements.size()]); return method; } - private IfStatement generateCompareFloatOrDouble(char[] otherN, char[] floatOrDouble, char[] fieldName, long p) { - int pS = (int)(p >> 32), pE = (int)p; + private IfStatement generateCompareFloatOrDouble(char[] otherN, char[] floatOrDouble, char[] fieldName, ASTNode source) { + int pS = source.sourceStart, pE = source.sourceEnd; + long p = (long)pS << 32 | pE; /* if ( Float.compare(fieldName, other.fieldName) != 0 ) return false */ MessageSend floatCompare = new MessageSend(); - floatCompare.receiver = generateQualifiedNameRef(p, TypeConstants.JAVA, TypeConstants.LANG, floatOrDouble); + floatCompare.sourceStart = pS; floatCompare.sourceEnd = pE; + Eclipse.setGeneratedBy(floatCompare, source); + floatCompare.receiver = generateQualifiedNameRef(source, TypeConstants.JAVA, TypeConstants.LANG, floatOrDouble); floatCompare.selector = "compare".toCharArray(); - floatCompare.arguments = new Expression[] { - new SingleNameReference(fieldName, p), - generateQualifiedNameRef(p, otherN, fieldName) - }; - EqualExpression ifFloatCompareIsNot0 = new EqualExpression(floatCompare, new IntLiteral(new char[] {'0'}, pS, pE), OperatorIds.NOT_EQUAL); - ReturnStatement returnFalse = new ReturnStatement(new FalseLiteral(pS, pE), pS, pE); - return new IfStatement(ifFloatCompareIsNot0, returnFalse, pS, pE); + NameReference fieldNameRef = new SingleNameReference(fieldName, p); + Eclipse.setGeneratedBy(fieldNameRef, source); + floatCompare.arguments = new Expression[] {fieldNameRef, generateQualifiedNameRef(source, otherN, fieldName)}; + IntLiteral int0 = new IntLiteral(new char[] {'0'}, pS, pE); + Eclipse.setGeneratedBy(int0, source); + EqualExpression ifFloatCompareIsNot0 = new EqualExpression(floatCompare, int0, OperatorIds.NOT_EQUAL); + ifFloatCompareIsNot0.sourceStart = pS; ifFloatCompareIsNot0.sourceEnd = pE; + Eclipse.setGeneratedBy(ifFloatCompareIsNot0, source); + FalseLiteral falseLiteral = new FalseLiteral(pS, pE); + Eclipse.setGeneratedBy(falseLiteral, source); + ReturnStatement returnFalse = new ReturnStatement(falseLiteral, pS, pE); + Eclipse.setGeneratedBy(returnFalse, source); + IfStatement ifStatement = new IfStatement(ifFloatCompareIsNot0, returnFalse, pS, pE); + Eclipse.setGeneratedBy(ifStatement, source); + return ifStatement; } /** Give 2 clones! */ - private Expression longToIntForHashCode(Reference ref1, Reference ref2, long p) { - int pS = (int)(p >> 32), pE = (int)p; + private Expression longToIntForHashCode(Reference ref1, Reference ref2, ASTNode source) { + int pS = source.sourceStart, pE = source.sourceEnd; /* (int)(ref >>> 32 ^ ref) */ - BinaryExpression higherBits = new BinaryExpression( - ref1, new IntLiteral("32".toCharArray(), pS, pE), - OperatorIds.UNSIGNED_RIGHT_SHIFT); + IntLiteral int32 = new IntLiteral("32".toCharArray(), pS, pE); + Eclipse.setGeneratedBy(int32, source); + BinaryExpression higherBits = new BinaryExpression(ref1, int32, OperatorIds.UNSIGNED_RIGHT_SHIFT); + Eclipse.setGeneratedBy(higherBits, source); BinaryExpression xorParts = new BinaryExpression(ref2, higherBits, OperatorIds.XOR); - return new CastExpression(xorParts, TypeReference.baseTypeReference(TypeIds.T_int, 0)); + Eclipse.setGeneratedBy(xorParts, source); + TypeReference intRef = TypeReference.baseTypeReference(TypeIds.T_int, 0); + intRef.sourceStart = pS; intRef.sourceEnd = pE; + Eclipse.setGeneratedBy(intRef, source); + CastExpression expr = new CastExpression(xorParts, intRef); + expr.sourceStart = pS; expr.sourceEnd = pE; + Eclipse.setGeneratedBy(expr, source); + return expr; } - private Reference generateFieldReference(char[] fieldName, long p) { + private Reference generateFieldReference(char[] fieldName, ASTNode source) { + int pS = source.sourceStart, pE = source.sourceEnd; + long p = (long)pS << 32 | pE; FieldReference thisX = new FieldReference(("this." + new String(fieldName)).toCharArray(), p); - thisX.receiver = new ThisReference((int)(p >> 32), (int)p); + Eclipse.setGeneratedBy(thisX, source); + thisX.receiver = new ThisReference(pS, pE); + Eclipse.setGeneratedBy(thisX.receiver, source); thisX.token = fieldName; return thisX; } - private NameReference generateQualifiedNameRef(long p, char[]... varNames) { - if ( varNames.length > 1 ) - return new QualifiedNameReference(varNames, new long[varNames.length], (int)(p >> 32), (int)p); - else return new SingleNameReference(varNames[0], p); + private NameReference generateQualifiedNameRef(ASTNode source, char[]... varNames) { + int pS = source.sourceStart, pE = source.sourceEnd; + long p = (long)pS << 32 | pE; + + NameReference ref; + + if ( varNames.length > 1 ) ref = new QualifiedNameReference(varNames, new long[varNames.length], pS, pE); + else ref = new SingleNameReference(varNames[0], p); + Eclipse.setGeneratedBy(ref, source); + return ref; } } diff --git a/src/lombok/eclipse/handlers/HandleGetter.java b/src/lombok/eclipse/handlers/HandleGetter.java index e83b2cc5..9760fe01 100644 --- a/src/lombok/eclipse/handlers/HandleGetter.java +++ b/src/lombok/eclipse/handlers/HandleGetter.java @@ -28,6 +28,7 @@ import lombok.Getter; 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; @@ -82,16 +83,14 @@ public class HandleGetter implements EclipseAnnotationHandler<Getter> { return createGetterForField(level, fieldNode, annotationNode, annotationNode.get(), true); } - private boolean createGetterForField(AccessLevel level, Node fieldNode, Node errorNode, ASTNode pos, boolean whineIfExists) { - int pS = pos.sourceStart(), pE = pos.sourceEnd(); - long p = (long)pS << 32 | pE; + private boolean createGetterForField(AccessLevel level, Node fieldNode, Node errorNode, ASTNode source, boolean whineIfExists) { if ( fieldNode.getKind() != Kind.FIELD ) { errorNode.addError("@Getter is only supported on a field."); return true; } FieldDeclaration field = (FieldDeclaration) fieldNode.get(); - TypeReference fieldType = copyType(field.type); + TypeReference fieldType = copyType(field.type, source); String fieldName = new String(field.name); boolean isBoolean = nameEquals(fieldType.getTypeName(), "boolean") && fieldType.dimensions() == 0; String getterName = TransformationsUtil.toGetterName(fieldName, isBoolean); @@ -116,9 +115,10 @@ public class HandleGetter implements EclipseAnnotationHandler<Getter> { } } - MethodDeclaration method = generateGetter((TypeDeclaration) fieldNode.up().get(), field, getterName, modifier, pos); + MethodDeclaration method = generateGetter((TypeDeclaration) fieldNode.up().get(), field, getterName, modifier, source); Annotation[] copiedAnnotations = copyAnnotations( - findAnnotations(field, TransformationsUtil.NON_NULL_PATTERN), findAnnotations(field, TransformationsUtil.NULLABLE_PATTERN), p); + findAnnotations(field, TransformationsUtil.NON_NULL_PATTERN), + findAnnotations(field, TransformationsUtil.NULLABLE_PATTERN), source); if (copiedAnnotations.length != 0) { method.annotations = copiedAnnotations; } @@ -129,10 +129,11 @@ public class HandleGetter implements EclipseAnnotationHandler<Getter> { } private MethodDeclaration generateGetter(TypeDeclaration parent, FieldDeclaration field, String name, - int modifier, ASTNode pos) { + int modifier, ASTNode source) { MethodDeclaration method = new MethodDeclaration(parent.compilationResult); + Eclipse.setGeneratedBy(method, source); method.modifiers = modifier; - method.returnType = copyType(field.type); + method.returnType = copyType(field.type, source); method.annotations = null; method.arguments = null; method.selector = name.toCharArray(); @@ -141,9 +142,11 @@ public class HandleGetter implements EclipseAnnotationHandler<Getter> { method.typeParameters = null; method.bits |= ECLIPSE_DO_NOT_TOUCH_FLAG; Expression fieldExpression = new SingleNameReference(field.name, (field.declarationSourceStart << 32) | field.declarationSourceEnd); + Eclipse.setGeneratedBy(fieldExpression, source); Statement returnStatement = new ReturnStatement(fieldExpression, field.sourceStart, field.sourceEnd); - method.bodyStart = method.declarationSourceStart = method.sourceStart = pos.sourceStart; - method.bodyEnd = method.declarationSourceEnd = method.sourceEnd = pos.sourceEnd; + Eclipse.setGeneratedBy(returnStatement, source); + method.bodyStart = method.declarationSourceStart = method.sourceStart = source.sourceStart; + method.bodyEnd = method.declarationSourceEnd = method.sourceEnd = source.sourceEnd; method.statements = new Statement[] { returnStatement }; return method; } diff --git a/src/lombok/eclipse/handlers/HandleSetter.java b/src/lombok/eclipse/handlers/HandleSetter.java index 636226bd..f804eefc 100644 --- a/src/lombok/eclipse/handlers/HandleSetter.java +++ b/src/lombok/eclipse/handlers/HandleSetter.java @@ -31,6 +31,7 @@ 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; @@ -41,13 +42,13 @@ import org.eclipse.jdt.internal.compiler.ast.Assignment; import org.eclipse.jdt.internal.compiler.ast.FieldDeclaration; import org.eclipse.jdt.internal.compiler.ast.FieldReference; import org.eclipse.jdt.internal.compiler.ast.MethodDeclaration; +import org.eclipse.jdt.internal.compiler.ast.NameReference; import org.eclipse.jdt.internal.compiler.ast.SingleNameReference; import org.eclipse.jdt.internal.compiler.ast.Statement; 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.MethodScope; import org.eclipse.jdt.internal.compiler.lookup.TypeIds; import org.mangosdk.spi.ProviderFor; @@ -123,37 +124,48 @@ public class HandleSetter implements EclipseAnnotationHandler<Setter> { } private MethodDeclaration generateSetter(TypeDeclaration parent, FieldDeclaration field, String name, - int modifier, ASTNode ast) { + int modifier, ASTNode source) { - long pos = (((long)ast.sourceStart) << 32) | ast.sourceEnd; + int pS = source.sourceStart, pE = source.sourceEnd; + long p = (long)pS << 32 | pE; MethodDeclaration method = new MethodDeclaration(parent.compilationResult); + Eclipse.setGeneratedBy(method, source); method.modifiers = modifier; method.returnType = TypeReference.baseTypeReference(TypeIds.T_void, 0); + method.returnType.sourceStart = pS; method.returnType.sourceEnd = pE; + Eclipse.setGeneratedBy(method.returnType, source); method.annotations = null; - Argument param = new Argument(field.name, pos, copyType(field.type), Modifier.FINAL); + Argument param = new Argument(field.name, p, copyType(field.type, source), Modifier.FINAL); + param.sourceStart = pS; param.sourceEnd = pE; + Eclipse.setGeneratedBy(param, source); method.arguments = new Argument[] { param }; method.selector = name.toCharArray(); method.binding = null; method.thrownExceptions = null; method.typeParameters = null; - method.scope = parent.scope == null ? null : new MethodScope(parent.scope, method, false); method.bits |= ECLIPSE_DO_NOT_TOUCH_FLAG; - FieldReference thisX = new FieldReference(field.name, pos); - thisX.receiver = new ThisReference(ast.sourceStart, ast.sourceEnd); - Assignment assignment = new Assignment(thisX, new SingleNameReference(field.name, pos), (int)pos); - method.bodyStart = method.declarationSourceStart = method.sourceStart = ast.sourceStart; - method.bodyEnd = method.declarationSourceEnd = method.sourceEnd = ast.sourceEnd; + FieldReference thisX = new FieldReference(field.name, p); + Eclipse.setGeneratedBy(thisX, source); + thisX.receiver = new ThisReference(source.sourceStart, source.sourceEnd); + Eclipse.setGeneratedBy(thisX.receiver, source); + NameReference fieldNameRef = new SingleNameReference(field.name, p); + Eclipse.setGeneratedBy(fieldNameRef, source); + Assignment assignment = new Assignment(thisX, fieldNameRef, (int)p); + assignment.sourceStart = pS; assignment.sourceEnd = pE; + Eclipse.setGeneratedBy(assignment, source); + method.bodyStart = method.declarationSourceStart = method.sourceStart = source.sourceStart; + method.bodyEnd = method.declarationSourceEnd = method.sourceEnd = source.sourceEnd; Annotation[] nonNulls = findAnnotations(field, TransformationsUtil.NON_NULL_PATTERN); Annotation[] nullables = findAnnotations(field, TransformationsUtil.NULLABLE_PATTERN); if (nonNulls.length == 0) { method.statements = new Statement[] { assignment }; } else { - Statement nullCheck = generateNullCheck(field); + Statement nullCheck = generateNullCheck(field, source); if (nullCheck != null) method.statements = new Statement[] { nullCheck, assignment }; else method.statements = new Statement[] { assignment }; } - Annotation[] copiedAnnotations = copyAnnotations(nonNulls, nullables, pos); + Annotation[] copiedAnnotations = copyAnnotations(nonNulls, nullables, source); if (copiedAnnotations.length != 0) param.annotations = copiedAnnotations; return method; } diff --git a/src/lombok/eclipse/handlers/HandleSneakyThrows.java b/src/lombok/eclipse/handlers/HandleSneakyThrows.java index f0ff53db..75dad780 100644 --- a/src/lombok/eclipse/handlers/HandleSneakyThrows.java +++ b/src/lombok/eclipse/handlers/HandleSneakyThrows.java @@ -27,6 +27,7 @@ import java.util.List; import lombok.SneakyThrows; import lombok.core.AnnotationValues; +import lombok.eclipse.Eclipse; import lombok.eclipse.EclipseAnnotationHandler; import lombok.eclipse.EclipseAST.Node; @@ -68,29 +69,32 @@ public class HandleSneakyThrows implements EclipseAnnotationHandler<SneakyThrows } } - @Override public boolean handle(AnnotationValues<SneakyThrows> annotation, Annotation ast, Node annotationNode) { + @Override public boolean handle(AnnotationValues<SneakyThrows> annotation, Annotation source, Node annotationNode) { List<String> exceptionNames = annotation.getRawExpressions("value"); + List<DeclaredException> exceptions = new ArrayList<DeclaredException>(); - MemberValuePair[] memberValuePairs = ast.memberValuePairs(); - if ( memberValuePairs == null || memberValuePairs.length == 0 ) return false; - - Expression arrayOrSingle = memberValuePairs[0].value; - final Expression[] exceptionNameNodes; - if ( arrayOrSingle instanceof ArrayInitializer ) { - exceptionNameNodes = ((ArrayInitializer)arrayOrSingle).expressions; - } else exceptionNameNodes = new Expression[] { arrayOrSingle }; - - if ( exceptionNames.size() != exceptionNameNodes.length ) { - annotationNode.addError( - "LOMBOK BUG: The number of exception classes in the annotation isn't the same pre- and post- guessing."); + MemberValuePair[] memberValuePairs = source.memberValuePairs(); + if ( memberValuePairs == null || memberValuePairs.length == 0 ) { + exceptions.add(new DeclaredException("java.lang.Throwable", source)); + } else { + Expression arrayOrSingle = memberValuePairs[0].value; + final Expression[] exceptionNameNodes; + if ( arrayOrSingle instanceof ArrayInitializer ) { + exceptionNameNodes = ((ArrayInitializer)arrayOrSingle).expressions; + } else exceptionNameNodes = new Expression[] { arrayOrSingle }; + + if ( exceptionNames.size() != exceptionNameNodes.length ) { + annotationNode.addError( + "LOMBOK BUG: The number of exception classes in the annotation isn't the same pre- and post- guessing."); + } + + int idx = 0; + for ( String exceptionName : exceptionNames ) { + if ( exceptionName.endsWith(".class") ) exceptionName = exceptionName.substring(0, exceptionName.length() - 6); + exceptions.add(new DeclaredException(exceptionName, exceptionNameNodes[idx++])); + } } - List<DeclaredException> exceptions = new ArrayList<DeclaredException>(); - int idx = 0; - for ( String exceptionName : exceptionNames ) { - if ( exceptionName.endsWith(".class") ) exceptionName = exceptionName.substring(0, exceptionName.length() - 6); - exceptions.add(new DeclaredException(exceptionName, exceptionNameNodes[idx++])); - } Node owner = annotationNode.up(); switch ( owner.getKind() ) { @@ -147,7 +151,7 @@ public class HandleSneakyThrows implements EclipseAnnotationHandler<SneakyThrows Statement[] contents = method.statements; for ( DeclaredException exception : exceptions ) { - contents = new Statement[] { buildTryCatchBlock(contents, exception) }; + contents = new Statement[] { buildTryCatchBlock(contents, exception, exception.node) }; } method.statements = contents; @@ -156,14 +160,15 @@ public class HandleSneakyThrows implements EclipseAnnotationHandler<SneakyThrows return true; } - private Statement buildTryCatchBlock(Statement[] contents, DeclaredException exception) { + private Statement buildTryCatchBlock(Statement[] contents, DeclaredException exception, ASTNode source) { long p = exception.getPos(); int pS = (int)(p >> 32), pE = (int)p; TryStatement tryStatement = new TryStatement(); + Eclipse.setGeneratedBy(tryStatement, source); tryStatement.tryBlock = new Block(0); - tryStatement.tryBlock.sourceStart = pS; - tryStatement.tryBlock.sourceEnd = pE; + tryStatement.tryBlock.sourceStart = pS; tryStatement.tryBlock.sourceEnd = pE; + Eclipse.setGeneratedBy(tryStatement.tryBlock, source); tryStatement.tryBlock.statements = contents; TypeReference typeReference; if ( exception.exceptionName.indexOf('.') == -1 ) { @@ -182,27 +187,34 @@ public class HandleSneakyThrows implements EclipseAnnotationHandler<SneakyThrows } typeReference = new QualifiedTypeReference(elems, poss); } + Eclipse.setGeneratedBy(typeReference, source); Argument catchArg = new Argument("$ex".toCharArray(), p, typeReference, Modifier.FINAL); + Eclipse.setGeneratedBy(catchArg, source); catchArg.declarationSourceEnd = catchArg.declarationEnd = catchArg.sourceEnd = pE; catchArg.declarationSourceStart = catchArg.modifiersSourceStart = catchArg.sourceStart = pS; tryStatement.catchArguments = new Argument[] { catchArg }; MessageSend sneakyThrowStatement = new MessageSend(); + Eclipse.setGeneratedBy(sneakyThrowStatement, source); sneakyThrowStatement.receiver = new QualifiedNameReference(new char[][] { "lombok".toCharArray(), "Lombok".toCharArray() }, new long[] { p, p }, pS, pE); + Eclipse.setGeneratedBy(sneakyThrowStatement.receiver, source); sneakyThrowStatement.receiver.statementEnd = pE; sneakyThrowStatement.selector = "sneakyThrow".toCharArray(); SingleNameReference exRef = new SingleNameReference("$ex".toCharArray(), p); + Eclipse.setGeneratedBy(exRef, source); exRef.statementEnd = pE; sneakyThrowStatement.arguments = new Expression[] { exRef }; sneakyThrowStatement.nameSourcePosition = p; sneakyThrowStatement.sourceStart = pS; sneakyThrowStatement.sourceEnd = sneakyThrowStatement.statementEnd = pE; Statement rethrowStatement = new ThrowStatement(sneakyThrowStatement, pS, pE); + Eclipse.setGeneratedBy(rethrowStatement, source); Block block = new Block(0); block.sourceStart = pS; block.sourceEnd = pE; + Eclipse.setGeneratedBy(block, source); block.statements = new Statement[] { rethrowStatement }; tryStatement.catchBlocks = new Block[] { block }; tryStatement.sourceStart = pS; diff --git a/src/lombok/eclipse/handlers/HandleSynchronized.java b/src/lombok/eclipse/handlers/HandleSynchronized.java index d0233b50..7a573198 100644 --- a/src/lombok/eclipse/handlers/HandleSynchronized.java +++ b/src/lombok/eclipse/handlers/HandleSynchronized.java @@ -28,6 +28,7 @@ import java.lang.reflect.Modifier; import lombok.Synchronized; import lombok.core.AnnotationValues; import lombok.core.AST.Kind; +import lombok.eclipse.Eclipse; import lombok.eclipse.EclipseAnnotationHandler; import lombok.eclipse.EclipseAST.Node; import lombok.eclipse.handlers.PKG.MemberExistsResult; @@ -56,9 +57,9 @@ public class HandleSynchronized implements EclipseAnnotationHandler<Synchronized private static final char[] INSTANCE_LOCK_NAME = "$lock".toCharArray(); private static final char[] STATIC_LOCK_NAME = "$LOCK".toCharArray(); - @Override public boolean handle(AnnotationValues<Synchronized> annotation, Annotation ast, Node annotationNode) { - int p1 = ast.sourceStart -1; - int p2 = ast.sourceStart -2; + @Override public boolean handle(AnnotationValues<Synchronized> annotation, Annotation source, Node annotationNode) { + int p1 = source.sourceStart -1; + int p2 = source.sourceStart -2; long pos = (((long)p1) << 32) | p2; Node methodNode = annotationNode.up(); if ( methodNode == null || methodNode.getKind() != Kind.METHOD || !(methodNode.get() instanceof MethodDeclaration) ) { @@ -85,15 +86,20 @@ public class HandleSynchronized implements EclipseAnnotationHandler<Synchronized return true; } FieldDeclaration fieldDecl = new FieldDeclaration(lockName, 0, -1); + Eclipse.setGeneratedBy(fieldDecl, source); fieldDecl.declarationSourceEnd = -1; fieldDecl.modifiers = (method.isStatic() ? Modifier.STATIC : 0) | Modifier.FINAL | Modifier.PRIVATE; //We use 'new Object[0];' because quite unlike 'new Object();', empty arrays *ARE* serializable! ArrayAllocationExpression arrayAlloc = new ArrayAllocationExpression(); + Eclipse.setGeneratedBy(arrayAlloc, source); arrayAlloc.dimensions = new Expression[] { new IntLiteral(new char[] { '0' }, 0, 0) }; + Eclipse.setGeneratedBy(arrayAlloc.dimensions[0], source); arrayAlloc.type = new QualifiedTypeReference(TypeConstants.JAVA_LANG_OBJECT, new long[] { 0, 0, 0 }); + Eclipse.setGeneratedBy(arrayAlloc.type, source); fieldDecl.type = new QualifiedTypeReference(TypeConstants.JAVA_LANG_OBJECT, new long[] { 0, 0, 0 }); + Eclipse.setGeneratedBy(fieldDecl.type, source); fieldDecl.initialization = arrayAlloc; injectField(annotationNode.up().up(), fieldDecl); } @@ -101,18 +107,23 @@ public class HandleSynchronized implements EclipseAnnotationHandler<Synchronized if ( method.statements == null ) return false; Block block = new Block(0); + Eclipse.setGeneratedBy(block, source); block.statements = method.statements; Expression lockVariable; if ( method.isStatic() ) lockVariable = new QualifiedNameReference(new char[][] { methodNode.up().getName().toCharArray(), lockName }, new long[] { pos, pos }, p1, p2); else { lockVariable = new FieldReference(lockName, pos); - ((FieldReference)lockVariable).receiver = new ThisReference(p1, p2); + ThisReference thisReference = new ThisReference(p1, p2); + Eclipse.setGeneratedBy(thisReference, source); + ((FieldReference)lockVariable).receiver = thisReference; } + Eclipse.setGeneratedBy(lockVariable, source); method.statements = new Statement[] { new SynchronizedStatement(lockVariable, block, 0, 0) }; + Eclipse.setGeneratedBy(method.statements[0], source); methodNode.rebuild(); diff --git a/src/lombok/eclipse/handlers/HandleToString.java b/src/lombok/eclipse/handlers/HandleToString.java index 5b88b568..5a840e1f 100644 --- a/src/lombok/eclipse/handlers/HandleToString.java +++ b/src/lombok/eclipse/handlers/HandleToString.java @@ -45,6 +45,7 @@ import org.eclipse.jdt.internal.compiler.ast.BinaryExpression; import org.eclipse.jdt.internal.compiler.ast.CompilationUnitDeclaration; import org.eclipse.jdt.internal.compiler.ast.Expression; import org.eclipse.jdt.internal.compiler.ast.FieldDeclaration; +import org.eclipse.jdt.internal.compiler.ast.FieldReference; import org.eclipse.jdt.internal.compiler.ast.MessageSend; import org.eclipse.jdt.internal.compiler.ast.MethodDeclaration; import org.eclipse.jdt.internal.compiler.ast.NameReference; @@ -56,6 +57,7 @@ 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.SuperReference; +import org.eclipse.jdt.internal.compiler.ast.ThisReference; import org.eclipse.jdt.internal.compiler.ast.TypeDeclaration; import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants; import org.eclipse.jdt.internal.compiler.lookup.TypeConstants; @@ -175,14 +177,15 @@ public class HandleToString implements EclipseAnnotationHandler<ToString> { } } - private MethodDeclaration createToString(Node type, Collection<Node> fields, boolean includeFieldNames, boolean callSuper, ASTNode pos) { + private MethodDeclaration createToString(Node type, Collection<Node> fields, boolean includeFieldNames, boolean callSuper, ASTNode source) { TypeDeclaration typeDeclaration = (TypeDeclaration)type.get(); char[] rawTypeName = typeDeclaration.name; String typeName = rawTypeName == null ? "" : new String(rawTypeName); char[] suffix = ")".toCharArray(); String infixS = ", "; char[] infix = infixS.toCharArray(); - long p = (long)pos.sourceStart << 32 | pos.sourceEnd; + int pS = source.sourceStart, pE = source.sourceEnd; + long p = (long)pS << 32 | pE; final int PLUS = OperatorIds.PLUS; char[] prefix; @@ -198,12 +201,18 @@ public class HandleToString implements EclipseAnnotationHandler<ToString> { } boolean first = true; - Expression current = new StringLiteral(prefix, 0, 0, 0); + Expression current = new StringLiteral(prefix, pS, pE, 0); + Eclipse.setGeneratedBy(current, source); + if ( callSuper ) { MessageSend callToSuper = new MessageSend(); - callToSuper.receiver = new SuperReference(0, 0); + callToSuper.sourceStart = pS; callToSuper.sourceEnd = pE; + Eclipse.setGeneratedBy(callToSuper, source); + callToSuper.receiver = new SuperReference(pS, pE); + Eclipse.setGeneratedBy(callToSuper, source); callToSuper.selector = "toString".toCharArray(); current = new BinaryExpression(current, callToSuper, PLUS); + Eclipse.setGeneratedBy(current, source); first = false; } @@ -214,45 +223,68 @@ public class HandleToString implements EclipseAnnotationHandler<ToString> { Expression ex; if ( f.type.dimensions() > 0 ) { MessageSend arrayToString = new MessageSend(); - arrayToString.receiver = generateQualifiedNameRef(TypeConstants.JAVA, TypeConstants.UTIL, "Arrays".toCharArray()); + arrayToString.sourceStart = pS; arrayToString.sourceEnd = pE; + arrayToString.receiver = generateQualifiedNameRef(source, TypeConstants.JAVA, TypeConstants.UTIL, "Arrays".toCharArray()); arrayToString.arguments = new Expression[] { new SingleNameReference(f.name, p) }; + Eclipse.setGeneratedBy(arrayToString.arguments[0], source); if ( f.type.dimensions() > 1 || !BUILT_IN_TYPES.contains(new String(f.type.getLastToken())) ) { arrayToString.selector = "deepToString".toCharArray(); } else { arrayToString.selector = "toString".toCharArray(); } ex = arrayToString; - } else ex = new SingleNameReference(f.name, p); + } else { + FieldReference thisX = new FieldReference(f.name, p); + thisX.receiver = new ThisReference(source.sourceStart, source.sourceEnd); + Eclipse.setGeneratedBy(thisX.receiver, source); + ex = thisX; + } + Eclipse.setGeneratedBy(ex, source); if ( first ) { current = new BinaryExpression(current, ex, PLUS); + current.sourceStart = pS; current.sourceEnd = pE; + Eclipse.setGeneratedBy(current, source); first = false; continue; } + StringLiteral fieldNameLiteral; if ( includeFieldNames ) { char[] namePlusEqualsSign = (infixS + new String(f.name) + "=").toCharArray(); - current = new BinaryExpression(current, new StringLiteral(namePlusEqualsSign, 0, 0, 0), PLUS); + fieldNameLiteral = new StringLiteral(namePlusEqualsSign, pS, pE, 0); } else { - current = new BinaryExpression(current, new StringLiteral(infix, 0, 0, 0), PLUS); + fieldNameLiteral = new StringLiteral(infix, pS, pE, 0); } + Eclipse.setGeneratedBy(fieldNameLiteral, source); + current = new BinaryExpression(current, fieldNameLiteral, PLUS); + Eclipse.setGeneratedBy(current, source); current = new BinaryExpression(current, ex, PLUS); + Eclipse.setGeneratedBy(current, source); + } + if ( !first ) { + StringLiteral suffixLiteral = new StringLiteral(suffix, pS, pE, 0); + Eclipse.setGeneratedBy(suffixLiteral, source); + current = new BinaryExpression(current, suffixLiteral, PLUS); + Eclipse.setGeneratedBy(current, source); } - if ( !first ) current = new BinaryExpression(current, new StringLiteral(suffix, 0, 0, 0), PLUS); - ReturnStatement returnStatement = new ReturnStatement(current, (int)(p >> 32), (int)p); + ReturnStatement returnStatement = new ReturnStatement(current, pS, pE); + Eclipse.setGeneratedBy(returnStatement, source); MethodDeclaration method = new MethodDeclaration(((CompilationUnitDeclaration) type.top().get()).compilationResult); + Eclipse.setGeneratedBy(method, source); method.modifiers = toModifier(AccessLevel.PUBLIC); - method.returnType = new QualifiedTypeReference(TypeConstants.JAVA_LANG_STRING, new long[] {0, 0, 0}); - method.annotations = new Annotation[] {makeMarkerAnnotation(TypeConstants.JAVA_LANG_OVERRIDE, p)}; + method.returnType = new QualifiedTypeReference(TypeConstants.JAVA_LANG_STRING, new long[] {p, p, p}); + Eclipse.setGeneratedBy(method.returnType, source); + method.annotations = new Annotation[] {makeMarkerAnnotation(TypeConstants.JAVA_LANG_OVERRIDE, source)}; method.arguments = null; method.selector = "toString".toCharArray(); method.thrownExceptions = null; method.typeParameters = null; 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.bodyStart = method.declarationSourceStart = method.sourceStart = source.sourceStart; + method.bodyEnd = method.declarationSourceEnd = method.sourceEnd = source.sourceEnd; method.statements = new Statement[] { returnStatement }; return method; } @@ -260,9 +292,13 @@ public class HandleToString implements EclipseAnnotationHandler<ToString> { private static final Set<String> BUILT_IN_TYPES = Collections.unmodifiableSet(new HashSet<String>(Arrays.asList( "byte", "short", "int", "long", "char", "boolean", "double", "float"))); - private NameReference generateQualifiedNameRef(char[]... varNames) { - if ( varNames.length > 1 ) - return new QualifiedNameReference(varNames, new long[varNames.length], 0, 0); - else return new SingleNameReference(varNames[0], 0); + private NameReference generateQualifiedNameRef(ASTNode source, char[]... varNames) { + int pS = source.sourceStart, pE = source.sourceEnd; + long p = (long)pS << 32 | pE; + NameReference ref; + if ( varNames.length > 1 ) ref = new QualifiedNameReference(varNames, new long[varNames.length], pS, pE); + else ref = new SingleNameReference(varNames[0], p); + Eclipse.setGeneratedBy(ref, source); + return ref; } } diff --git a/src/lombok/eclipse/handlers/PKG.java b/src/lombok/eclipse/handlers/PKG.java index 58fac4a1..6bc4499d 100644 --- a/src/lombok/eclipse/handlers/PKG.java +++ b/src/lombok/eclipse/handlers/PKG.java @@ -258,21 +258,39 @@ class PKG { return result.toArray(new Annotation[0]); } - static Statement generateNullCheck(AbstractVariableDeclaration variable) { + static Statement generateNullCheck(AbstractVariableDeclaration variable, ASTNode source) { + int pS = source.sourceStart, pE = source.sourceEnd; + long p = (long)pS << 32 | pE; + if (isPrimitive(variable.type)) return null; AllocationExpression exception = new AllocationExpression(); - exception.type = new QualifiedTypeReference(fromQualifiedName("java.lang.NullPointerException"), new long[]{0, 0, 0}); - exception.arguments = new Expression[] { new StringLiteral(variable.name, 0, variable.name.length - 1, 0)}; - ThrowStatement throwStatement = new ThrowStatement(exception, 0, 0); + Eclipse.setGeneratedBy(exception, source); + exception.type = new QualifiedTypeReference(fromQualifiedName("java.lang.NullPointerException"), new long[]{p, p, p}); + Eclipse.setGeneratedBy(exception.type, source); + exception.arguments = new Expression[] { new StringLiteral(variable.name, pS, pE, 0)}; + Eclipse.setGeneratedBy(exception.arguments[0], source); + ThrowStatement throwStatement = new ThrowStatement(exception, pS, pE); + Eclipse.setGeneratedBy(throwStatement, source); - return new IfStatement(new EqualExpression(new SingleNameReference(variable.name, 0), - new NullLiteral(0, 0), OperatorIds.EQUAL_EQUAL), throwStatement, 0, 0); + SingleNameReference varName = new SingleNameReference(variable.name, p); + Eclipse.setGeneratedBy(varName, source); + NullLiteral nullLiteral = new NullLiteral(pS, pE); + Eclipse.setGeneratedBy(nullLiteral, source); + EqualExpression equalExpression = new EqualExpression(varName, nullLiteral, OperatorIds.EQUAL_EQUAL); + equalExpression.sourceStart = pS; equalExpression.sourceEnd = pE; + Eclipse.setGeneratedBy(equalExpression, source); + IfStatement ifStatement = new IfStatement(equalExpression, throwStatement, 0, 0); + Eclipse.setGeneratedBy(ifStatement, source); + return ifStatement; } - static MarkerAnnotation makeMarkerAnnotation(char[][] name, long pos) { - MarkerAnnotation ann = new MarkerAnnotation(new QualifiedTypeReference(name, new long[] {pos, pos, pos}), (int)(pos >> 32)); + static MarkerAnnotation makeMarkerAnnotation(char[][] name, ASTNode source) { + long pos = source.sourceStart << 32 | source.sourceEnd; + TypeReference typeRef = new QualifiedTypeReference(name, new long[] {pos, pos, pos}); + Eclipse.setGeneratedBy(typeRef, source); + MarkerAnnotation ann = new MarkerAnnotation(typeRef, (int)(pos >> 32)); ann.declarationSourceEnd = ann.sourceEnd = ann.statementEnd = (int)pos; - ann.bits |= ASTNode.HasBeenGenerated; + Eclipse.setGeneratedBy(ann, source); return ann; } |