mirror of
https://github.com/tiennm99/lombok.git
synced 2026-10-12 22:14:53 +00:00
Massive change to the eclipse handlers: They now set the 'generatedBy' flag which we can use to patch eclipse in specific places to ignore generated nodes.
This commit is contained in:
1 parent
21717cec11
commit
35691e83ed
11 files changed
+571
-237
No files matched your search
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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,30 +69,33 @@ 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");
|
||||
|
||||
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.");
|
||||
}
|
||||
|
||||
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++]));
|
||||
|
||||
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++]));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Node owner = annotationNode.up();
|
||||
switch ( owner.getKind() ) {
|
||||
// case FIELD:
|
||||
@@ -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;
|
||||
|
||||
@@ -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();
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
Reference in new issue
Block a user