diff options
author | Reinier Zwitserloot <reinier@zwitserloot.com> | 2011-05-30 22:04:46 +0200 |
---|---|---|
committer | Reinier Zwitserloot <reinier@zwitserloot.com> | 2011-05-30 22:08:12 +0200 |
commit | aa8a627349bb68f376b98847b6f73c2c89e989fd (patch) | |
tree | 70df1fa6ba0f8e3c34a45d868d7f763e5b7ccbf9 /src/core/lombok/javac/handlers/HandleGetter.java | |
parent | daf84dd00ed5059710acf9f40b4663ba7fed06e0 (diff) | |
download | lombok-aa8a627349bb68f376b98847b6f73c2c89e989fd.tar.gz lombok-aa8a627349bb68f376b98847b6f73c2c89e989fd.tar.bz2 lombok-aa8a627349bb68f376b98847b6f73c2c89e989fd.zip |
tracking if an annotation has been handled or not is now no longer done
via the LombokAST object. Instead its tracked more directly in an attempt
to avoid having to write all handlers as idempotent, and just in case
issue #164 is a race condition (the handled-or-not is a synchronized CAS check).
This does break API for other plugins, but the fix is trivial: Just make your
'handle' method return void. That 'we won't call you again' business in the decks
never quite worked right anyway.
Also, you might want to call Javac.(recursive)setHandledBy when you generate nodes, now.
Diffstat (limited to 'src/core/lombok/javac/handlers/HandleGetter.java')
-rw-r--r-- | src/core/lombok/javac/handlers/HandleGetter.java | 86 |
1 files changed, 44 insertions, 42 deletions
diff --git a/src/core/lombok/javac/handlers/HandleGetter.java b/src/core/lombok/javac/handlers/HandleGetter.java index 8a1f7eed..83b6a898 100644 --- a/src/core/lombok/javac/handlers/HandleGetter.java +++ b/src/core/lombok/javac/handlers/HandleGetter.java @@ -1,5 +1,5 @@ /* - * Copyright © 2009-2010 Reinier Zwitserloot and Roel Spilker. + * Copyright © 2009-2011 Reinier Zwitserloot and Roel Spilker. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -70,13 +70,13 @@ import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition; */ @ProviderFor(JavacAnnotationHandler.class) public class HandleGetter implements JavacAnnotationHandler<Getter> { - public boolean generateGetterForType(JavacNode typeNode, JavacNode errorNode, AccessLevel level, boolean checkForTypeLevelGetter) { + public void generateGetterForType(JavacNode typeNode, JavacNode errorNode, AccessLevel level, boolean checkForTypeLevelGetter) { if (checkForTypeLevelGetter) { if (typeNode != null) for (JavacNode child : typeNode.down()) { if (child.getKind() == Kind.ANNOTATION) { if (Javac.annotationTypeMatches(Getter.class, child)) { //The annotation will make it happen, so we can skip it. - return true; + return; } } } @@ -89,14 +89,12 @@ public class HandleGetter implements JavacAnnotationHandler<Getter> { if (typeDecl == null || notAClass) { errorNode.addError("@Getter is only supported on a class, an enum, or a field."); - return false; + return; } for (JavacNode field : typeNode.down()) { if (fieldQualifiesForGetterGeneration(field)) generateGetterForField(field, errorNode.get(), level, List.<JCExpression>nil(), false); } - - return true; } public boolean fieldQualifiesForGetterGeneration(JavacNode field) { @@ -123,7 +121,6 @@ public class HandleGetter implements JavacAnnotationHandler<Getter> { * * @param fieldNode The node representing the field you want a getter for. * @param pos The node responsible for generating the getter (the {@code @Data} or {@code @Getter} annotation). - * @param lazy */ public void generateGetterForField(JavacNode fieldNode, DiagnosticPosition pos, AccessLevel level, List<JCExpression> onMethod, boolean lazy) { for (JavacNode child : fieldNode.down()) { @@ -138,9 +135,9 @@ public class HandleGetter implements JavacAnnotationHandler<Getter> { createGetterForField(level, fieldNode, fieldNode, false, onMethod, lazy); } - @Override public boolean handle(AnnotationValues<Getter> annotation, JCAnnotation ast, JavacNode annotationNode) { + @Override public void handle(AnnotationValues<Getter> annotation, JCAnnotation ast, JavacNode annotationNode) { Collection<JavacNode> fields = annotationNode.upFromAnnotationToFields(); - markAnnotationAsProcessed(annotationNode, Getter.class); + deleteAnnotationIfNeccessary(annotationNode, Getter.class); deleteImportFromCompilationUnit(annotationNode, "lombok.AccessLevel"); JavacNode node = annotationNode.up(); Getter annotationInstance = annotation.getInstance(); @@ -150,48 +147,47 @@ public class HandleGetter implements JavacAnnotationHandler<Getter> { if (lazy) { annotationNode.addWarning("'lazy' does not work with AccessLevel.NONE."); } - return true; + return; } - if (node == null) return false; + if (node == null) return; List<JCExpression> onMethod = getAndRemoveAnnotationParameter(ast, "onMethod"); - if (node.getKind() == Kind.FIELD) { - return createGetterForFields(level, fields, annotationNode, true, onMethod, lazy); - } - if (node.getKind() == Kind.TYPE) { + switch (node.getKind()) { + case FIELD: + createGetterForFields(level, fields, annotationNode, true, onMethod, lazy); + break; + case TYPE: if (!onMethod.isEmpty()) annotationNode.addError("'onMethod' is not supported for @Getter on a type."); if (lazy) annotationNode.addError("'lazy' is not supported for @Getter on a type."); - return generateGetterForType(node, annotationNode, level, false); + generateGetterForType(node, annotationNode, level, false); + break; } - return false; } - private boolean createGetterForFields(AccessLevel level, Collection<JavacNode> fieldNodes, JavacNode errorNode, boolean whineIfExists, List<JCExpression> onMethod, boolean lazy) { + private void createGetterForFields(AccessLevel level, Collection<JavacNode> fieldNodes, JavacNode errorNode, boolean whineIfExists, List<JCExpression> onMethod, boolean lazy) { for (JavacNode fieldNode : fieldNodes) { createGetterForField(level, fieldNode, errorNode, whineIfExists, onMethod, lazy); } - - return true; } - private boolean createGetterForField(AccessLevel level, - JavacNode fieldNode, JavacNode errorNode, boolean whineIfExists, List<JCExpression> onMethod, boolean lazy) { + private void createGetterForField(AccessLevel level, + JavacNode fieldNode, JavacNode source, boolean whineIfExists, List<JCExpression> onMethod, boolean lazy) { if (fieldNode.getKind() != Kind.FIELD) { - errorNode.addError("@Getter is only supported on a class or a field."); - return true; + source.addError("@Getter is only supported on a class or a field."); + return; } JCVariableDecl fieldDecl = (JCVariableDecl)fieldNode.get(); if (lazy) { if ((fieldDecl.mods.flags & Flags.PRIVATE) == 0 || (fieldDecl.mods.flags & Flags.FINAL) == 0) { - errorNode.addError("'lazy' requires the field to be private and final."); - return true; + source.addError("'lazy' requires the field to be private and final."); + return; } if (fieldDecl.init == null) { - errorNode.addError("'lazy' requires field initialization."); - return true; + source.addError("'lazy' requires field initialization."); + return; } } @@ -200,15 +196,15 @@ public class HandleGetter implements JavacAnnotationHandler<Getter> { for (String altName : toAllGetterNames(fieldDecl)) { switch (methodExists(altName, fieldNode, false)) { case EXISTS_BY_LOMBOK: - return true; + return; case EXISTS_BY_USER: if (whineIfExists) { String altNameExpl = ""; if (!altName.equals(methodName)) altNameExpl = String.format(" (%s)", altName); - errorNode.addWarning( + source.addWarning( String.format("Not generating %s(): A method with that name already exists%s", methodName, altNameExpl)); } - return true; + return; default: case NOT_EXISTS: //continue scanning the other alt names. @@ -217,20 +213,20 @@ public class HandleGetter implements JavacAnnotationHandler<Getter> { long access = toJavacModifier(level) | (fieldDecl.mods.flags & Flags.STATIC); - injectMethod(fieldNode.up(), createGetter(access, fieldNode, fieldNode.getTreeMaker(), onMethod, lazy)); - - return true; + injectMethod(fieldNode.up(), createGetter(access, fieldNode, fieldNode.getTreeMaker(), onMethod, lazy, source.get())); } - private JCMethodDecl createGetter(long access, JavacNode field, TreeMaker treeMaker, List<JCExpression> onMethod, boolean lazy) { + private JCMethodDecl createGetter(long access, JavacNode field, TreeMaker treeMaker, List<JCExpression> onMethod, boolean lazy, JCTree source) { JCVariableDecl fieldNode = (JCVariableDecl) field.get(); // Remember the type; lazy will change it; JCExpression methodType = copyType(treeMaker, fieldNode); List<JCStatement> statements; + JCTree toClearOfMarkers = null; if (lazy) { - statements = createLazyGetterBody(treeMaker, field); + toClearOfMarkers = fieldNode.init; + statements = createLazyGetterBody(treeMaker, field, source); } else { statements = createSimpleGetterBody(treeMaker, field); } @@ -248,8 +244,12 @@ public class HandleGetter implements JavacAnnotationHandler<Getter> { List<JCAnnotation> annsOnMethod = copyAnnotations(onMethod).appendList(nonNulls).appendList(nullables); - return treeMaker.MethodDef(treeMaker.Modifiers(access, annsOnMethod), methodName, methodType, - methodGenericParams, parameters, throwsClauses, methodBody, annotationMethodDefaultValue); + JCMethodDecl decl = Javac.recursiveSetGeneratedBy(treeMaker.MethodDef(treeMaker.Modifiers(access, annsOnMethod), methodName, methodType, + methodGenericParams, parameters, throwsClauses, methodBody, annotationMethodDefaultValue), source); + + if (toClearOfMarkers != null) Javac.recursiveSetGeneratedBy(toClearOfMarkers, null); + + return decl; } private List<JCStatement> createSimpleGetterBody(TreeMaker treeMaker, JavacNode field) { @@ -273,7 +273,7 @@ public class HandleGetter implements JavacAnnotationHandler<Getter> { TYPE_MAP = Collections.unmodifiableMap(m); } - private List<JCStatement> createLazyGetterBody(TreeMaker maker, JavacNode fieldNode) { + private List<JCStatement> createLazyGetterBody(TreeMaker maker, JavacNode fieldNode, JCTree source) { /* java.util.concurrent.atomic.AtomicReference<ValueType> value = this.fieldName.get(); if (value == null) { @@ -318,7 +318,7 @@ public class HandleGetter implements JavacAnnotationHandler<Getter> { /* if (value == null) { */ { ListBuffer<JCStatement> innerIfStatements = ListBuffer.lb(); /* value = new java.util.concurrent.atomic.AtomicReference<ValueType>(new ValueType());*/ { - JCTypeApply valueVarType = maker.TypeApply(chainDotsString(maker, fieldNode, AR), List.of(copyType(maker, field))); + JCTypeApply valueVarType = maker.TypeApply(chainDotsString(maker, fieldNode, AR), List.of(copyType(maker, field))); JCNewClass newInstance = maker.NewClass(null, NIL_EXPRESSION, valueVarType, List.<JCExpression>of(field.init), null); JCStatement statement = maker.Exec(maker.Assign(maker.Ident(valueName), newInstance)); @@ -347,8 +347,10 @@ public class HandleGetter implements JavacAnnotationHandler<Getter> { // update the field type and init last /* private final java.util.concurrent.atomic.AtomicReference<java.util.concurrent.atomic.AtomicReference<ValueType> fieldName = new java.util.concurrent.atomic.AtomicReference<java.util.concurrent.atomic.AtomicReference<ValueType>>(); */ { - field.vartype = maker.TypeApply(chainDotsString(maker, fieldNode, AR), List.<JCExpression>of(maker.TypeApply(chainDotsString(maker, fieldNode, AR), List.of(copyType(maker, field))))); - field.init = maker.NewClass(null, NIL_EXPRESSION, copyType(maker, field), NIL_EXPRESSION, null); + field.vartype = Javac.recursiveSetGeneratedBy( + maker.TypeApply(chainDotsString(maker, fieldNode, AR), List.<JCExpression>of(maker.TypeApply(chainDotsString(maker, fieldNode, AR), List.of(copyType(maker, field))))), + source); + field.init = Javac.recursiveSetGeneratedBy(maker.NewClass(null, NIL_EXPRESSION, copyType(maker, field), NIL_EXPRESSION, null), source); } return statements.toList(); |