aboutsummaryrefslogtreecommitdiff
path: root/src/core/lombok/javac
diff options
context:
space:
mode:
authorReinier Zwitserloot <reinier@zwitserloot.com>2012-08-10 18:06:13 +0200
committerReinier Zwitserloot <reinier@zwitserloot.com>2012-08-10 18:06:13 +0200
commit1be7da76012b246af24d0515d192bca85d65c823 (patch)
tree21d9675c00d812c6bbbf76edb80d38b16777740d /src/core/lombok/javac
parent70317c73841d3e83b4b8008b68bea95753a5275f (diff)
downloadlombok-1be7da76012b246af24d0515d192bca85d65c823.tar.gz
lombok-1be7da76012b246af24d0515d192bca85d65c823.tar.bz2
lombok-1be7da76012b246af24d0515d192bca85d65c823.zip
* Added priorities to handlers, along with implementation of the priority system for javac and ecj.
* @Value now makes the class itself final by default.
Diffstat (limited to 'src/core/lombok/javac')
-rw-r--r--src/core/lombok/javac/HandlerLibrary.java94
-rw-r--r--src/core/lombok/javac/JavacTransformer.java46
-rw-r--r--src/core/lombok/javac/ResolutionBased.java36
-rw-r--r--src/core/lombok/javac/apt/Processor.java83
-rw-r--r--src/core/lombok/javac/handlers/HandleDelegate.java4
-rw-r--r--src/core/lombok/javac/handlers/HandleExtensionMethod.java7
-rw-r--r--src/core/lombok/javac/handlers/HandleFieldDefaults.java2
-rw-r--r--src/core/lombok/javac/handlers/HandleLog.java1
-rw-r--r--src/core/lombok/javac/handlers/HandlePrintAST.java2
-rw-r--r--src/core/lombok/javac/handlers/HandleVal.java4
-rw-r--r--src/core/lombok/javac/handlers/HandleValue.java11
11 files changed, 150 insertions, 140 deletions
diff --git a/src/core/lombok/javac/HandlerLibrary.java b/src/core/lombok/javac/HandlerLibrary.java
index 9666c9d5..1ce083f3 100644
--- a/src/core/lombok/javac/HandlerLibrary.java
+++ b/src/core/lombok/javac/HandlerLibrary.java
@@ -25,14 +25,17 @@ import java.io.IOException;
import java.lang.annotation.Annotation;
import java.util.ArrayList;
import java.util.Collection;
+import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
+import java.util.SortedSet;
+import java.util.TreeSet;
import java.util.WeakHashMap;
import javax.annotation.processing.Messager;
import javax.tools.Diagnostic;
-import lombok.core.PrintAST;
+import lombok.core.HandlerPriority;
import lombok.core.SpiLoadUtil;
import lombok.core.TypeLibrary;
import lombok.core.TypeResolver;
@@ -52,9 +55,8 @@ import com.sun.tools.javac.tree.JCTree.JCCompilationUnit;
public class HandlerLibrary {
private final TypeLibrary typeLibrary = new TypeLibrary();
private final Map<String, AnnotationHandlerContainer<?>> annotationHandlers = new HashMap<String, AnnotationHandlerContainer<?>>();
- private final Collection<JavacASTVisitor> visitorHandlers = new ArrayList<JavacASTVisitor>();
+ private final Collection<VisitorContainer> visitorHandlers = new ArrayList<VisitorContainer>();
private final Messager messager;
- private int phase = 0;
/**
* Creates a new HandlerLibrary that will report any problems or errors to the provided messager.
@@ -64,22 +66,53 @@ public class HandlerLibrary {
this.messager = messager;
}
+ private static class VisitorContainer {
+ private final JavacASTVisitor visitor;
+ private final long priority;
+
+ VisitorContainer(JavacASTVisitor visitor) {
+ this.visitor = visitor;
+ HandlerPriority hp = visitor.getClass().getAnnotation(HandlerPriority.class);
+ this.priority = hp == null ? 0L : (((long)hp.value()) << 32) + hp.subValue();
+ }
+
+ public long getPriority() {
+ return priority;
+ }
+ }
+
private static class AnnotationHandlerContainer<T extends Annotation> {
- private JavacAnnotationHandler<T> handler;
- private Class<T> annotationClass;
+ private final JavacAnnotationHandler<T> handler;
+ private final Class<T> annotationClass;
+ private final long priority;
AnnotationHandlerContainer(JavacAnnotationHandler<T> handler, Class<T> annotationClass) {
this.handler = handler;
this.annotationClass = annotationClass;
- }
-
- public boolean isResolutionBased() {
- return handler.getClass().isAnnotationPresent(ResolutionBased.class);
+ HandlerPriority hp = handler.getClass().getAnnotation(HandlerPriority.class);
+ this.priority = hp == null ? 0L : (((long)hp.value()) << 32) + hp.subValue();
}
public void handle(final JavacNode node) {
handler.handle(JavacHandlerUtil.createAnnotation(annotationClass, node), (JCAnnotation)node.get(), node);
}
+
+ public long getPriority() {
+ return priority;
+ }
+ }
+
+ private SortedSet<Long> priorities;
+
+ public SortedSet<Long> getPriorities() {
+ return priorities;
+ }
+
+ private void calculatePriorities() {
+ SortedSet<Long> set = new TreeSet<Long>();
+ for (AnnotationHandlerContainer<?> container : annotationHandlers.values()) set.add(container.getPriority());
+ for (VisitorContainer container : visitorHandlers) set.add(container.getPriority());
+ this.priorities = Collections.unmodifiableSortedSet(set);
}
/**
@@ -97,6 +130,8 @@ public class HandlerLibrary {
System.err.println("Lombok isn't running due to misconfigured SPI files: " + e);
}
+ library.calculatePriorities();
+
return library;
}
@@ -120,7 +155,7 @@ public class HandlerLibrary {
private static void loadVisitorHandlers(HandlerLibrary lib) throws IOException {
//No, that seemingly superfluous reference to JavacASTVisitor's classloader is not in fact superfluous!
for (JavacASTVisitor visitor : SpiLoadUtil.findServices(JavacASTVisitor.class, JavacASTVisitor.class.getClassLoader())) {
- lib.visitorHandlers.add(visitor);
+ lib.visitorHandlers.add(new VisitorContainer(visitor));
}
}
@@ -171,24 +206,15 @@ public class HandlerLibrary {
* @param node The Lombok AST Node representing the Annotation AST Node.
* @param annotation 'node.get()' - convenience parameter.
*/
- public void handleAnnotation(JCCompilationUnit unit, JavacNode node, JCAnnotation annotation) {
+ public void handleAnnotation(JCCompilationUnit unit, JavacNode node, JCAnnotation annotation, long priority) {
TypeResolver resolver = new TypeResolver(node.getPackageDeclaration(), node.getImportStatements());
String rawType = annotation.annotationType.toString();
for (String fqn : resolver.findTypeMatches(node, typeLibrary, rawType)) {
- boolean isPrintAST = fqn.equals(PrintAST.class.getName());
- if (isPrintAST && phase != 2) continue;
- if (!isPrintAST && phase == 2) continue;
AnnotationHandlerContainer<?> container = annotationHandlers.get(fqn);
if (container == null) continue;
try {
- if (container.isResolutionBased() && phase == 1) {
- if (checkAndSetHandled(annotation)) container.handle(node);
- }
- if (!container.isResolutionBased() && phase == 0) {
- if (checkAndSetHandled(annotation)) container.handle(node);
- }
- if (container.annotationClass == PrintAST.class && phase == 2) {
+ if (container.getPriority() == priority) {
if (checkAndSetHandled(annotation)) container.handle(node);
}
} catch (AnnotationValueDecodeFail fail) {
@@ -204,29 +230,11 @@ public class HandlerLibrary {
/**
* Will call all registered {@link JavacASTVisitor} instances.
*/
- public void callASTVisitors(JavacAST ast) {
- for (JavacASTVisitor visitor : visitorHandlers) try {
- boolean isResolutionBased = visitor.getClass().isAnnotationPresent(ResolutionBased.class);
- if (!isResolutionBased && phase == 0) ast.traverse(visitor);
- if (isResolutionBased && phase == 1) ast.traverse(visitor);
+ public void callASTVisitors(JavacAST ast, long priority) {
+ for (VisitorContainer container : visitorHandlers) try {
+ if (container.getPriority() == priority) ast.traverse(container.visitor);
} catch (Throwable t) {
- javacError(String.format("Lombok visitor handler %s failed", visitor.getClass()), t);
+ javacError(String.format("Lombok visitor handler %s failed", container.visitor.getClass()), t);
}
}
-
- /**
- * Lombok does not currently support triggering annotations in a specified order; the order is essentially
- * random right now. As a temporary hack we've identified 3 important phases.
- */
- public void setPreResolutionPhase() {
- phase = 0;
- }
-
- public void setPostResolutionPhase() {
- phase = 1;
- }
-
- public void setPrintASTPhase() {
- phase = 2;
- }
}
diff --git a/src/core/lombok/javac/JavacTransformer.java b/src/core/lombok/javac/JavacTransformer.java
index 3afdee0a..9cac787c 100644
--- a/src/core/lombok/javac/JavacTransformer.java
+++ b/src/core/lombok/javac/JavacTransformer.java
@@ -22,10 +22,10 @@
package lombok.javac;
import java.util.ArrayList;
+import java.util.SortedSet;
import javax.annotation.processing.Messager;
-
import com.sun.tools.javac.tree.JCTree.JCAnnotation;
import com.sun.tools.javac.tree.JCTree.JCClassDecl;
import com.sun.tools.javac.tree.JCTree.JCCompilationUnit;
@@ -43,7 +43,11 @@ public class JavacTransformer {
this.handlers = HandlerLibrary.load(messager);
}
- public void transform(boolean postResolution, Context context, java.util.List<JCCompilationUnit> compilationUnitsRaw) {
+ public SortedSet<Long> getPriorities() {
+ return handlers.getPriorities();
+ }
+
+ public void transform(long priority, Context context, java.util.List<JCCompilationUnit> compilationUnitsRaw) {
List<JCCompilationUnit> compilationUnits;
if (compilationUnitsRaw instanceof List<?>) {
compilationUnits = (List<JCCompilationUnit>)compilationUnitsRaw;
@@ -58,54 +62,44 @@ public class JavacTransformer {
for (JCCompilationUnit unit : compilationUnits) asts.add(new JavacAST(messager, context, unit));
- if (!postResolution) {
- handlers.setPreResolutionPhase();
- for (JavacAST ast : asts) {
- ast.traverse(new AnnotationVisitor());
- handlers.callASTVisitors(ast);
- }
- }
-
- if (postResolution) {
- handlers.setPostResolutionPhase();
- for (JavacAST ast : asts) {
- ast.traverse(new AnnotationVisitor());
- handlers.callASTVisitors(ast);
- }
-
- handlers.setPrintASTPhase();
- for (JavacAST ast : asts) {
- ast.traverse(new AnnotationVisitor());
- }
+ for (JavacAST ast : asts) {
+ ast.traverse(new AnnotationVisitor(priority));
+ handlers.callASTVisitors(ast, priority);
}
for (JavacAST ast : asts) if (ast.isChanged()) LombokOptions.markChanged(context, (JCCompilationUnit) ast.top().get());
}
private class AnnotationVisitor extends JavacASTAdapter {
+ private final long priority;
+
+ AnnotationVisitor(long priority) {
+ this.priority = priority;
+ }
+
@Override public void visitAnnotationOnType(JCClassDecl type, JavacNode annotationNode, JCAnnotation annotation) {
JCCompilationUnit top = (JCCompilationUnit) annotationNode.top().get();
- handlers.handleAnnotation(top, annotationNode, annotation);
+ handlers.handleAnnotation(top, annotationNode, annotation, priority);
}
@Override public void visitAnnotationOnField(JCVariableDecl field, JavacNode annotationNode, JCAnnotation annotation) {
JCCompilationUnit top = (JCCompilationUnit) annotationNode.top().get();
- handlers.handleAnnotation(top, annotationNode, annotation);
+ handlers.handleAnnotation(top, annotationNode, annotation, priority);
}
@Override public void visitAnnotationOnMethod(JCMethodDecl method, JavacNode annotationNode, JCAnnotation annotation) {
JCCompilationUnit top = (JCCompilationUnit) annotationNode.top().get();
- handlers.handleAnnotation(top, annotationNode, annotation);
+ handlers.handleAnnotation(top, annotationNode, annotation, priority);
}
@Override public void visitAnnotationOnMethodArgument(JCVariableDecl argument, JCMethodDecl method, JavacNode annotationNode, JCAnnotation annotation) {
JCCompilationUnit top = (JCCompilationUnit) annotationNode.top().get();
- handlers.handleAnnotation(top, annotationNode, annotation);
+ handlers.handleAnnotation(top, annotationNode, annotation, priority);
}
@Override public void visitAnnotationOnLocal(JCVariableDecl local, JavacNode annotationNode, JCAnnotation annotation) {
JCCompilationUnit top = (JCCompilationUnit) annotationNode.top().get();
- handlers.handleAnnotation(top, annotationNode, annotation);
+ handlers.handleAnnotation(top, annotationNode, annotation, priority);
}
}
}
diff --git a/src/core/lombok/javac/ResolutionBased.java b/src/core/lombok/javac/ResolutionBased.java
deleted file mode 100644
index 556e3736..00000000
--- a/src/core/lombok/javac/ResolutionBased.java
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * Copyright (C) 2012 The Project Lombok Authors.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- * THE SOFTWARE.
- */
-package lombok.javac;
-
-import java.lang.annotation.ElementType;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.lang.annotation.Target;
-
-/**
- * Marker to indicate a handler is to be called after all the non-resolution based visitors.
- * NB: Temporary solution - will be rewritten to a different style altogether in a future release.
- */
-@Target(ElementType.TYPE)
-@Retention(RetentionPolicy.RUNTIME)
-public @interface ResolutionBased {
-}
diff --git a/src/core/lombok/javac/apt/Processor.java b/src/core/lombok/javac/apt/Processor.java
index d05a3bdf..190a369b 100644
--- a/src/core/lombok/javac/apt/Processor.java
+++ b/src/core/lombok/javac/apt/Processor.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2009-2010 The Project Lombok Authors.
+ * Copyright (C) 2009-2012 The Project Lombok Authors.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -30,8 +30,10 @@ import java.net.URL;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.IdentityHashMap;
+import java.util.List;
import java.util.Map;
import java.util.Set;
+import java.util.SortedSet;
import javax.annotation.processing.AbstractProcessor;
import javax.annotation.processing.Messager;
@@ -80,6 +82,14 @@ public class Processor extends AbstractProcessor {
placePostCompileAndDontMakeForceRoundDummiesHook();
transformer = new JavacTransformer(procEnv.getMessager());
trees = Trees.instance(procEnv);
+ SortedSet<Long> p = transformer.getPriorities();
+ if (p.isEmpty()) {
+ this.priorityLevels = new long[] {0L};
+ } else {
+ this.priorityLevels = new long[p.size()];
+ int i = 0;
+ for (Long prio : p) this.priorityLevels[i++] = prio;
+ }
}
private void placePostCompileAndDontMakeForceRoundDummiesHook() {
@@ -204,47 +214,72 @@ public class Processor extends AbstractProcessor {
}
}
- private final IdentityHashMap<JCCompilationUnit, Void> rootsAtPhase0 = new IdentityHashMap<JCCompilationUnit, Void>();
- private final IdentityHashMap<JCCompilationUnit, Void> rootsAtPhase1 = new IdentityHashMap<JCCompilationUnit, Void>();
- private int dummyCount = 0;
+ private final IdentityHashMap<JCCompilationUnit, Long> roots = new IdentityHashMap<JCCompilationUnit, Long>();
+ private long[] priorityLevels;
/** {@inheritDoc} */
@Override public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
if (roundEnv.processingOver()) return false;
- if (!rootsAtPhase0.isEmpty()) {
- ArrayList<JCCompilationUnit> cus = new ArrayList<JCCompilationUnit>(rootsAtPhase0.keySet());
- transformer.transform(true, processingEnv.getContext(), cus);
- rootsAtPhase1.putAll(rootsAtPhase0);
- rootsAtPhase0.clear();
- }
+ // We have: A sorted set of all priority levels: 'priorityLevels'
+
+ // Step 1: Take all CUs which aren't already in the map. Give them the first priority level.
for (Element element : roundEnv.getRootElements()) {
JCCompilationUnit unit = toUnit(element);
- if (unit != null) {
- if (!rootsAtPhase1.containsKey(unit)) rootsAtPhase0.put(unit, null);
+ if (unit == null) continue;
+ if (roots.containsKey(unit)) continue;
+ roots.put(unit, priorityLevels[0]);
+ }
+
+ // Step 2: For all CUs (in the map, not the roundEnv!), run them across all handlers at their current prio level.
+
+ for (long prio : priorityLevels) {
+ List<JCCompilationUnit> cusForThisRound = new ArrayList<JCCompilationUnit>();
+ for (Map.Entry<JCCompilationUnit, Long> entry : roots.entrySet()) {
+ Long prioOfCu = entry.getValue();
+ if (prioOfCu == null || prioOfCu != prio) continue;
+ cusForThisRound.add(entry.getKey());
}
+ transformer.transform(prio, processingEnv.getContext(), cusForThisRound);
}
- if (!rootsAtPhase0.isEmpty()) {
- ArrayList<JCCompilationUnit> cus = new ArrayList<JCCompilationUnit>(rootsAtPhase0.keySet());
- transformer.transform(false, processingEnv.getContext(), cus);
- JavacFiler filer = (JavacFiler) processingEnv.getFiler();
- if (!filer.newFiles()) {
- try {
- JavaFileObject dummy = filer.createSourceFile("lombok.dummy.ForceNewRound" + (dummyCount++));
- Writer w = dummy.openWriter();
- w.close();
- } catch (Exception e) {
- processingEnv.getMessager().printMessage(Kind.WARNING,
- "Can't force a new processing round. Lombok features that require resolution won't work.");
+ // Step 3: Push up all CUs to the next level. Set level to null if there is no next level.
+
+ boolean nextRoundNeeded = false;
+ for (int i = priorityLevels.length - 1; i >= 0; i--) {
+ Long curLevel = priorityLevels[i];
+ Long nextLevel = (i == priorityLevels.length - 1) ? null : priorityLevels[i + 1];
+ for (Map.Entry<JCCompilationUnit, Long> entry : roots.entrySet()) {
+ if (curLevel.equals(entry.getValue())) {
+ entry.setValue(nextLevel);
+ if (nextLevel != null) nextRoundNeeded = true;
}
}
}
+ // Step 4: If ALL values are null, quit. Else, force new round.
+
+ if (nextRoundNeeded) forceNewRound((JavacFiler) processingEnv.getFiler());
+
return false;
}
+ private int dummyCount = 0;
+ private void forceNewRound(JavacFiler filer) {
+ if (!filer.newFiles()) {
+ try {
+ JavaFileObject dummy = filer.createSourceFile("lombok.dummy.ForceNewRound" + (dummyCount++));
+ Writer w = dummy.openWriter();
+ w.close();
+ } catch (Exception e) {
+ e.printStackTrace();
+ processingEnv.getMessager().printMessage(Kind.WARNING,
+ "Can't force a new processing round. Lombok won't work.");
+ }
+ }
+ }
+
private JCCompilationUnit toUnit(Element element) {
TreePath path = trees == null ? null : trees.getPath(element);
if (path == null) return null;
diff --git a/src/core/lombok/javac/handlers/HandleDelegate.java b/src/core/lombok/javac/handlers/HandleDelegate.java
index 50a2f1bb..b693a2a3 100644
--- a/src/core/lombok/javac/handlers/HandleDelegate.java
+++ b/src/core/lombok/javac/handlers/HandleDelegate.java
@@ -43,11 +43,11 @@ import javax.lang.model.type.TypeMirror;
import lombok.Delegate;
import lombok.core.AST.Kind;
import lombok.core.AnnotationValues;
+import lombok.core.HandlerPriority;
import lombok.javac.FindTypeVarScanner;
import lombok.javac.JavacAnnotationHandler;
import lombok.javac.JavacNode;
import lombok.javac.JavacResolution;
-import lombok.javac.ResolutionBased;
import lombok.javac.JavacResolution.TypeNotConvertibleException;
import org.mangosdk.spi.ProviderFor;
@@ -75,7 +75,7 @@ import com.sun.tools.javac.util.ListBuffer;
import com.sun.tools.javac.util.Name;
@ProviderFor(JavacAnnotationHandler.class)
-@ResolutionBased
+@HandlerPriority(65536) //2^16; to make sure that we also delegate generated methods.
public class HandleDelegate extends JavacAnnotationHandler<Delegate> {
private static final List<String> METHODS_IN_OBJECT = Collections.unmodifiableList(Arrays.asList(
"hashCode()",
diff --git a/src/core/lombok/javac/handlers/HandleExtensionMethod.java b/src/core/lombok/javac/handlers/HandleExtensionMethod.java
index 92d7c0e4..68df38ef 100644
--- a/src/core/lombok/javac/handlers/HandleExtensionMethod.java
+++ b/src/core/lombok/javac/handlers/HandleExtensionMethod.java
@@ -31,10 +31,10 @@ import java.util.List;
import javax.lang.model.element.ElementKind;
import lombok.core.AnnotationValues;
+import lombok.core.HandlerPriority;
import lombok.experimental.ExtensionMethod;
import lombok.javac.JavacAnnotationHandler;
import lombok.javac.JavacNode;
-import lombok.javac.ResolutionBased;
import org.mangosdk.spi.ProviderFor;
@@ -60,7 +60,7 @@ import com.sun.tools.javac.tree.JCTree.JCMethodInvocation;
* Handles the {@link ExtensionMethod} annotation for javac.
*/
@ProviderFor(JavacAnnotationHandler.class)
-@ResolutionBased
+@HandlerPriority(66560) // 2^16 + 2^10; we must run AFTER HandleVal which is at 2^16
public class HandleExtensionMethod extends JavacAnnotationHandler<ExtensionMethod> {
@Override
public void handle(final AnnotationValues<ExtensionMethod> annotation, final JCAnnotation source, final JavacNode annotationNode) {
@@ -83,9 +83,6 @@ public class HandleExtensionMethod extends JavacAnnotationHandler<ExtensionMetho
final List<Extension> extensions = getExtensions(annotationNode, extensionProviders);
if (extensions.isEmpty()) return;
- // call HandleVal explicitly to ensure val gets handled before @ExtensionMethdod gets handled.
- // TODO maybe we should prioritize lombok handler
- annotationNode.traverse(new HandleVal());
new ExtensionMethodReplaceVisitor(annotationNode, extensions, suppressBaseMethods).replace();
annotationNode.rebuild();
diff --git a/src/core/lombok/javac/handlers/HandleFieldDefaults.java b/src/core/lombok/javac/handlers/HandleFieldDefaults.java
index a2dfb7ce..c0829172 100644
--- a/src/core/lombok/javac/handlers/HandleFieldDefaults.java
+++ b/src/core/lombok/javac/handlers/HandleFieldDefaults.java
@@ -25,6 +25,7 @@ import static lombok.javac.handlers.JavacHandlerUtil.*;
import lombok.AccessLevel;
import lombok.core.AST.Kind;
import lombok.core.AnnotationValues;
+import lombok.core.HandlerPriority;
import lombok.experimental.FieldDefaults;
import lombok.experimental.NonFinal;
import lombok.experimental.PackagePrivate;
@@ -43,6 +44,7 @@ import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition;
* Handles the {@code lombok.FieldDefaults} annotation for eclipse.
*/
@ProviderFor(JavacAnnotationHandler.class)
+@HandlerPriority(-512) //-2^9; to ensure @Setter and such pick up on messing with the fields' 'final' state, run earlier.
public class HandleFieldDefaults extends JavacAnnotationHandler<FieldDefaults> {
public boolean generateFieldDefaultsForType(JavacNode typeNode, JavacNode errorNode, AccessLevel level, boolean makeFinal, boolean checkForTypeLevelFieldDefaults) {
if (checkForTypeLevelFieldDefaults) {
diff --git a/src/core/lombok/javac/handlers/HandleLog.java b/src/core/lombok/javac/handlers/HandleLog.java
index 4208f3c6..5ccc82d4 100644
--- a/src/core/lombok/javac/handlers/HandleLog.java
+++ b/src/core/lombok/javac/handlers/HandleLog.java
@@ -44,7 +44,6 @@ import com.sun.tools.javac.util.List;
import com.sun.tools.javac.util.Name;
public class HandleLog {
-
private HandleLog() {
throw new UnsupportedOperationException();
}
diff --git a/src/core/lombok/javac/handlers/HandlePrintAST.java b/src/core/lombok/javac/handlers/HandlePrintAST.java
index 27aa02ad..7b6d942c 100644
--- a/src/core/lombok/javac/handlers/HandlePrintAST.java
+++ b/src/core/lombok/javac/handlers/HandlePrintAST.java
@@ -31,6 +31,7 @@ import com.sun.tools.javac.tree.JCTree.JCAnnotation;
import lombok.Lombok;
import lombok.core.AnnotationValues;
+import lombok.core.HandlerPriority;
import lombok.core.PrintAST;
import lombok.javac.JavacASTVisitor;
import lombok.javac.JavacAnnotationHandler;
@@ -40,6 +41,7 @@ import lombok.javac.JavacNode;
* Handles the {@code lombok.core.PrintAST} annotation for javac.
*/
@ProviderFor(JavacAnnotationHandler.class)
+@HandlerPriority(536870912) // 2^29; this handler is customarily run at the very end.
public class HandlePrintAST extends JavacAnnotationHandler<PrintAST> {
@Override public void handle(AnnotationValues<PrintAST> annotation, JCAnnotation ast, JavacNode annotationNode) {
PrintStream stream = System.out;
diff --git a/src/core/lombok/javac/handlers/HandleVal.java b/src/core/lombok/javac/handlers/HandleVal.java
index 52d2ed13..0ab9d783 100644
--- a/src/core/lombok/javac/handlers/HandleVal.java
+++ b/src/core/lombok/javac/handlers/HandleVal.java
@@ -24,11 +24,11 @@ package lombok.javac.handlers;
import static lombok.javac.handlers.JavacHandlerUtil.*;
import lombok.val;
+import lombok.core.HandlerPriority;
import lombok.javac.JavacASTAdapter;
import lombok.javac.JavacASTVisitor;
import lombok.javac.JavacNode;
import lombok.javac.JavacResolution;
-import lombok.javac.ResolutionBased;
import org.mangosdk.spi.ProviderFor;
@@ -44,7 +44,7 @@ import com.sun.tools.javac.tree.JCTree.JCVariableDecl;
import com.sun.tools.javac.util.List;
@ProviderFor(JavacASTVisitor.class)
-@ResolutionBased
+@HandlerPriority(65536) // 2^16; resolution needs to work, so if the RHS expression is i.e. a call to a generated getter, we have to run after that getter has been generated.
public class HandleVal extends JavacASTAdapter {
@Override public void visitLocal(JavacNode localNode, JCVariableDecl local) {
if (local.vartype == null || (!local.vartype.toString().equals("val") && !local.vartype.toString().equals("lombok.val"))) return;
diff --git a/src/core/lombok/javac/handlers/HandleValue.java b/src/core/lombok/javac/handlers/HandleValue.java
index fac017a8..b52bad7c 100644
--- a/src/core/lombok/javac/handlers/HandleValue.java
+++ b/src/core/lombok/javac/handlers/HandleValue.java
@@ -24,18 +24,23 @@ package lombok.javac.handlers;
import static lombok.javac.handlers.JavacHandlerUtil.*;
import lombok.AccessLevel;
import lombok.core.AnnotationValues;
+import lombok.core.HandlerPriority;
+import lombok.experimental.NonFinal;
import lombok.experimental.Value;
import lombok.javac.JavacAnnotationHandler;
import lombok.javac.JavacNode;
import org.mangosdk.spi.ProviderFor;
+import com.sun.tools.javac.code.Flags;
import com.sun.tools.javac.tree.JCTree.JCAnnotation;
+import com.sun.tools.javac.tree.JCTree.JCClassDecl;
/**
* Handles the {@code lombok.Value} annotation for javac.
*/
@ProviderFor(JavacAnnotationHandler.class)
+@HandlerPriority(-512) //-2^9; to ensure @EqualsAndHashCode and such pick up on this handler making the class final and messing with the fields' access levels, run earlier.
public class HandleValue extends JavacAnnotationHandler<Value> {
@Override public void handle(AnnotationValues<Value> annotation, JCAnnotation ast, JavacNode annotationNode) {
deleteAnnotationIfNeccessary(annotationNode, Value.class);
@@ -49,12 +54,16 @@ public class HandleValue extends JavacAnnotationHandler<Value> {
String staticConstructorName = annotation.getInstance().staticConstructor();
+ if (!hasAnnotationAndDeleteIfNeccessary(NonFinal.class, typeNode)) {
+ ((JCClassDecl) typeNode.get()).mods.flags |= Flags.FINAL;
+ }
+ new HandleFieldDefaults().generateFieldDefaultsForType(typeNode, annotationNode, AccessLevel.PRIVATE, true, true);
+
// TODO move this to the end OR move it to the top in eclipse.
new HandleConstructor().generateAllArgsConstructor(typeNode, AccessLevel.PUBLIC, staticConstructorName, true, annotationNode);
new HandleGetter().generateGetterForType(typeNode, annotationNode, AccessLevel.PUBLIC, true);
new HandleWither().generateWitherForType(typeNode, annotationNode, AccessLevel.PUBLIC, true);
new HandleEqualsAndHashCode().generateEqualsAndHashCodeForType(typeNode, annotationNode);
new HandleToString().generateToStringForType(typeNode, annotationNode);
- new HandleFieldDefaults().generateFieldDefaultsForType(typeNode, annotationNode, AccessLevel.PRIVATE, true, true);
}
}