mirror of
https://github.com/tiennm99/lombok.git
synced 2026-10-13 16:15:16 +00:00
More work on the HandleData annotation. Constructor seems to work fine, static constructor not so much.
This commit is contained in:
1 parent
a27c48dd5c
commit
fdde039d23
2 files changed
+172
-13
No files matched your search
@@ -15,27 +15,36 @@ import lombok.eclipse.EclipseAnnotationHandler;
|
||||
import lombok.eclipse.EclipseAST.Node;
|
||||
|
||||
import org.eclipse.jdt.internal.compiler.ast.ASTNode;
|
||||
import org.eclipse.jdt.internal.compiler.ast.AllocationExpression;
|
||||
import org.eclipse.jdt.internal.compiler.ast.Annotation;
|
||||
import org.eclipse.jdt.internal.compiler.ast.Argument;
|
||||
import org.eclipse.jdt.internal.compiler.ast.Assignment;
|
||||
import org.eclipse.jdt.internal.compiler.ast.BinaryExpression;
|
||||
import org.eclipse.jdt.internal.compiler.ast.CompilationUnitDeclaration;
|
||||
import org.eclipse.jdt.internal.compiler.ast.ConstructorDeclaration;
|
||||
import org.eclipse.jdt.internal.compiler.ast.ExplicitConstructorCall;
|
||||
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.MethodDeclaration;
|
||||
import org.eclipse.jdt.internal.compiler.ast.OperatorIds;
|
||||
import org.eclipse.jdt.internal.compiler.ast.ReturnStatement;
|
||||
import org.eclipse.jdt.internal.compiler.ast.SingleNameReference;
|
||||
import org.eclipse.jdt.internal.compiler.ast.SingleTypeReference;
|
||||
import org.eclipse.jdt.internal.compiler.ast.Statement;
|
||||
import org.eclipse.jdt.internal.compiler.ast.StringLiteral;
|
||||
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.MethodBinding;
|
||||
import org.eclipse.jdt.internal.compiler.lookup.MethodScope;
|
||||
import org.eclipse.jdt.internal.compiler.lookup.TypeBinding;
|
||||
import org.mangosdk.spi.ProviderFor;
|
||||
|
||||
@ProviderFor(EclipseAnnotationHandler.class)
|
||||
public class HandleData implements EclipseAnnotationHandler<Data> {
|
||||
@Override public boolean handle(AnnotationValues<Data> annotation, Annotation ast, Node annotationNode) {
|
||||
Data ann = annotation.getInstance();
|
||||
Node typeNode = annotationNode.up();
|
||||
|
||||
TypeDeclaration typeDecl = null;
|
||||
@@ -72,7 +81,29 @@ public class HandleData implements EclipseAnnotationHandler<Data> {
|
||||
injectScopeIntoToString((MethodDeclaration) getExistingLombokMethod("toString", typeNode).get(), typeDecl);
|
||||
}
|
||||
|
||||
//TODO generate constructor, hashCode, equals.
|
||||
switch ( constructorExists(typeNode) ) {
|
||||
case NOT_EXISTS:
|
||||
ConstructorDeclaration constructor = createConstructor(
|
||||
ann.staticConstructor().isEmpty(), typeNode, nodesForConstructorAndToString, ast);
|
||||
injectMethod(typeNode, constructor);
|
||||
break;
|
||||
}
|
||||
|
||||
if ( !ann.staticConstructor().isEmpty() ) {
|
||||
switch ( methodExists("of", typeNode) ) {
|
||||
case NOT_EXISTS:
|
||||
MethodDeclaration staticConstructor = createStaticConstructor(
|
||||
ann.staticConstructor(), typeNode, nodesForConstructorAndToString, ast);
|
||||
injectMethod(typeNode, staticConstructor);
|
||||
break;
|
||||
case EXISTS_BY_LOMBOK:
|
||||
injectScopeIntoStaticConstructor((MethodDeclaration) getExistingLombokMethod(
|
||||
ann.staticConstructor(), typeNode).get(),
|
||||
nodesForConstructorAndToString, typeDecl);
|
||||
}
|
||||
}
|
||||
|
||||
//TODO generate hashCode, equals.
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -126,22 +157,96 @@ public class HandleData implements EclipseAnnotationHandler<Data> {
|
||||
return method;
|
||||
}
|
||||
|
||||
private MethodDeclaration createEquals(Collection<Node> fields) {
|
||||
return null;
|
||||
private ConstructorDeclaration createConstructor(boolean isPublic, Node type, Collection<Node> fields, ASTNode pos) {
|
||||
long p = (long)pos.sourceStart << 32 | pos.sourceEnd;
|
||||
|
||||
ConstructorDeclaration constructor = new ConstructorDeclaration(
|
||||
((CompilationUnitDeclaration) type.top().get()).compilationResult);
|
||||
|
||||
constructor.modifiers = PKG.toModifier(isPublic ? AccessLevel.PUBLIC : AccessLevel.PRIVATE);
|
||||
constructor.annotations = null;
|
||||
constructor.selector = ((TypeDeclaration)type.get()).name;
|
||||
constructor.constructorCall = new ExplicitConstructorCall(ExplicitConstructorCall.ImplicitSuper);
|
||||
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.arguments = null;
|
||||
|
||||
List<Argument> args = new ArrayList<Argument>();
|
||||
List<Statement> assigns = new ArrayList<Statement>();
|
||||
|
||||
for ( Node fieldNode : fields ) {
|
||||
FieldDeclaration field = (FieldDeclaration) fieldNode.get();
|
||||
FieldReference thisX = new FieldReference(("this." + new String(field.name)).toCharArray(), p);
|
||||
thisX.receiver = new ThisReference((int)(p >> 32), (int)p);
|
||||
thisX.token = field.name;
|
||||
assigns.add(new Assignment(thisX, new SingleNameReference(field.name, p), (int)p));
|
||||
long fieldPos = (((long)field.sourceStart) << 32) | field.sourceEnd;
|
||||
args.add(new Argument(field.name, fieldPos, field.type, 0));
|
||||
}
|
||||
|
||||
constructor.statements = assigns.toArray(new Statement[assigns.size()]);
|
||||
constructor.arguments = args.toArray(new Argument[args.size()]);
|
||||
return constructor;
|
||||
}
|
||||
|
||||
private ConstructorDeclaration createConstructor(Collection<Node> fields) {
|
||||
private void injectScopeIntoStaticConstructor(MethodDeclaration constructor, Collection<Node> fields, TypeDeclaration typeDecl) {
|
||||
if ( typeDecl.scope != null ) {
|
||||
constructor.scope = new MethodScope(typeDecl.scope, constructor, false);
|
||||
// constructor.binding = new MethodBinding(constructor.modifiers,
|
||||
// constructor.selector, null, null, null, typeDecl.binding);
|
||||
constructor.returnType.resolvedType = typeDecl.binding;
|
||||
// TypeBinding[] bindings = new TypeBinding[fields.size()];
|
||||
// int idx = 0;
|
||||
// for ( Node field : fields ) bindings[idx++] = ((FieldDeclaration)field.get()).type.resolvedType;
|
||||
// constructor.binding.parameters = bindings;
|
||||
}
|
||||
}
|
||||
|
||||
private MethodDeclaration createStaticConstructor(String name, Node type, Collection<Node> fields, ASTNode pos) {
|
||||
long p = (long)pos.sourceStart << 32 | pos.sourceEnd;
|
||||
|
||||
MethodDeclaration constructor = new MethodDeclaration(
|
||||
((CompilationUnitDeclaration) type.top().get()).compilationResult);
|
||||
|
||||
constructor.modifiers = PKG.toModifier(AccessLevel.PUBLIC);
|
||||
constructor.returnType = new SingleTypeReference(((TypeDeclaration)type.get()).name, p);
|
||||
constructor.annotations = null;
|
||||
constructor.selector = name.toCharArray();
|
||||
constructor.thrownExceptions = null;
|
||||
constructor.typeParameters = null;
|
||||
injectScopeIntoStaticConstructor(constructor, fields, (TypeDeclaration) type.get());
|
||||
constructor.bits |= Eclipse.ECLIPSE_DO_NOT_TOUCH_FLAG;
|
||||
constructor.bodyStart = constructor.declarationSourceStart = constructor.sourceStart = pos.sourceStart;
|
||||
constructor.bodyEnd = constructor.declarationSourceEnd = constructor.sourceEnd = pos.sourceEnd;
|
||||
|
||||
List<Argument> args = new ArrayList<Argument>();
|
||||
List<Expression> assigns = new ArrayList<Expression>();
|
||||
AllocationExpression statement = new AllocationExpression();
|
||||
statement.type = constructor.returnType;
|
||||
|
||||
for ( Node fieldNode : fields ) {
|
||||
FieldDeclaration field = (FieldDeclaration) fieldNode.get();
|
||||
long fieldPos = (((long)field.sourceStart) << 32) | field.sourceEnd;
|
||||
assigns.add(new SingleNameReference(field.name, fieldPos));
|
||||
args.add(new Argument(field.name, fieldPos, field.type, 0));
|
||||
}
|
||||
|
||||
statement.arguments = assigns.toArray(new Expression[assigns.size()]);
|
||||
constructor.arguments = args.toArray(new Argument[args.size()]);
|
||||
constructor.statements = new Statement[] { statement };
|
||||
return constructor;
|
||||
}
|
||||
|
||||
private MethodDeclaration createEquals(Collection<Node> fields) {
|
||||
//If using an of() constructor, make private.
|
||||
//method params
|
||||
//on loop: Assignment(FieldReference(ThisReference, "x"), SingleNameReference("x"))
|
||||
return null;
|
||||
}
|
||||
|
||||
private MethodDeclaration createStaticConstructor(Collection<Node> fields) {
|
||||
//Return(AllocationExpression(SingleTypeReference("Bar"), namesOfFields);
|
||||
return null;
|
||||
}
|
||||
|
||||
private MethodDeclaration createHashCode(Collection<Node> fields) {
|
||||
//booleans: conditionalexpression that bounces between 1231 and 1237.
|
||||
//longs: (int) (lng ^ (lng >>> 32));
|
||||
|
||||
@@ -6,7 +6,9 @@ import lombok.AccessLevel;
|
||||
import lombok.core.AST.Kind;
|
||||
import lombok.eclipse.EclipseAST;
|
||||
|
||||
import org.eclipse.jdt.internal.compiler.ast.ASTNode;
|
||||
import org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration;
|
||||
import org.eclipse.jdt.internal.compiler.ast.ConstructorDeclaration;
|
||||
import org.eclipse.jdt.internal.compiler.ast.TypeDeclaration;
|
||||
|
||||
class PKG {
|
||||
@@ -64,6 +66,44 @@ class PKG {
|
||||
return MethodExistsResult.NOT_EXISTS;
|
||||
}
|
||||
|
||||
static MethodExistsResult constructorExists(EclipseAST.Node node) {
|
||||
while ( node != null && !(node.get() instanceof TypeDeclaration) ) {
|
||||
node = node.up();
|
||||
}
|
||||
|
||||
if ( node.get() instanceof TypeDeclaration ) {
|
||||
TypeDeclaration typeDecl = (TypeDeclaration)node.get();
|
||||
if ( typeDecl.methods != null ) for ( AbstractMethodDeclaration def : typeDecl.methods ) {
|
||||
if ( def instanceof ConstructorDeclaration ) {
|
||||
if ( (def.bits & ASTNode.IsDefaultConstructor) != 0 ) continue;
|
||||
EclipseAST.Node existing = node.getNodeFor(def);
|
||||
if ( existing == null || !existing.isHandled() ) return MethodExistsResult.EXISTS_BY_USER;
|
||||
return MethodExistsResult.EXISTS_BY_LOMBOK;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return MethodExistsResult.NOT_EXISTS;
|
||||
}
|
||||
|
||||
static EclipseAST.Node getExistingLombokConstructor(EclipseAST.Node node) {
|
||||
while ( node != null && !(node.get() instanceof TypeDeclaration) ) {
|
||||
node = node.up();
|
||||
}
|
||||
|
||||
if ( node.get() instanceof TypeDeclaration ) {
|
||||
for ( AbstractMethodDeclaration def : ((TypeDeclaration)node.get()).methods ) {
|
||||
if ( def instanceof ConstructorDeclaration ) {
|
||||
if ( (def.bits & ASTNode.IsDefaultConstructor) != 0 ) continue;
|
||||
EclipseAST.Node existing = node.getNodeFor(def);
|
||||
if ( existing.isHandled() ) return existing;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
static EclipseAST.Node getExistingLombokMethod(String methodName, EclipseAST.Node node) {
|
||||
while ( node != null && !(node.get() instanceof TypeDeclaration) ) {
|
||||
node = node.up();
|
||||
@@ -85,14 +125,28 @@ class PKG {
|
||||
|
||||
static void injectMethod(EclipseAST.Node type, AbstractMethodDeclaration method) {
|
||||
TypeDeclaration parent = (TypeDeclaration) type.get();
|
||||
|
||||
if ( parent.methods == null ) {
|
||||
parent.methods = new AbstractMethodDeclaration[1];
|
||||
parent.methods[0] = method;
|
||||
} else {
|
||||
AbstractMethodDeclaration[] newArray = new AbstractMethodDeclaration[parent.methods.length + 1];
|
||||
System.arraycopy(parent.methods, 0, newArray, 0, parent.methods.length);
|
||||
newArray[parent.methods.length] = method;
|
||||
parent.methods = newArray;
|
||||
boolean injectionComplete = false;
|
||||
if ( method instanceof ConstructorDeclaration ) {
|
||||
for ( int i = 0 ; i < parent.methods.length ; i++ ) {
|
||||
if ( parent.methods[i] instanceof ConstructorDeclaration &&
|
||||
(parent.methods[i].bits & ASTNode.IsDefaultConstructor) != 0 ) {
|
||||
parent.methods[i] = method;
|
||||
injectionComplete = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if ( !injectionComplete ) {
|
||||
AbstractMethodDeclaration[] newArray = new AbstractMethodDeclaration[parent.methods.length + 1];
|
||||
System.arraycopy(parent.methods, 0, newArray, 0, parent.methods.length);
|
||||
newArray[parent.methods.length] = method;
|
||||
parent.methods = newArray;
|
||||
}
|
||||
}
|
||||
|
||||
type.add(method, Kind.METHOD).recursiveSetHandled();
|
||||
|
||||
Reference in new issue
Block a user