aboutsummaryrefslogtreecommitdiff
path: root/src/core/lombok/javac
diff options
context:
space:
mode:
Diffstat (limited to 'src/core/lombok/javac')
-rw-r--r--src/core/lombok/javac/JavacAST.java124
-rw-r--r--src/core/lombok/javac/JavacNode.java71
-rw-r--r--src/core/lombok/javac/apt/EmptyLombokFileObject.java2
-rw-r--r--src/core/lombok/javac/apt/LombokProcessor.java94
-rw-r--r--src/core/lombok/javac/handlers/HandleBuilder.java9
-rw-r--r--src/core/lombok/javac/handlers/HandleConstructor.java78
-rw-r--r--src/core/lombok/javac/handlers/HandleData.java9
-rw-r--r--src/core/lombok/javac/handlers/HandleEqualsAndHashCode.java145
-rw-r--r--src/core/lombok/javac/handlers/HandleFieldNameConstants.java137
-rw-r--r--src/core/lombok/javac/handlers/HandleGetter.java14
-rw-r--r--src/core/lombok/javac/handlers/HandleLog.java37
-rw-r--r--src/core/lombok/javac/handlers/HandleSetter.java13
-rw-r--r--src/core/lombok/javac/handlers/HandleSuperBuilder.java11
-rw-r--r--src/core/lombok/javac/handlers/HandleToString.java120
-rw-r--r--src/core/lombok/javac/handlers/HandleValue.java4
-rw-r--r--src/core/lombok/javac/handlers/HandleWither.java1
-rw-r--r--src/core/lombok/javac/handlers/JavacHandlerUtil.java87
17 files changed, 674 insertions, 282 deletions
diff --git a/src/core/lombok/javac/JavacAST.java b/src/core/lombok/javac/JavacAST.java
index 45679fd3..4ca2c050 100644
--- a/src/core/lombok/javac/JavacAST.java
+++ b/src/core/lombok/javac/JavacAST.java
@@ -35,6 +35,7 @@ import javax.annotation.processing.Messager;
import javax.tools.Diagnostic;
import javax.tools.JavaFileObject;
+import com.sun.tools.javac.util.JCDiagnostic;
import lombok.core.AST;
import com.sun.tools.javac.code.Source;
@@ -395,7 +396,7 @@ public class JavacAST extends AST<JavacAST, JavacNode, JCTree> {
oldSource = log.useSource(newSource);
if (pos == null) pos = astObject.pos();
}
- if (pos != null && attemptToRemoveErrorsInRange) {
+ if (pos != null && node != null && attemptToRemoveErrorsInRange) {
removeFromDeferredDiagnostics(pos.getStartPosition(), node.getEndPosition(pos));
}
try {
@@ -470,22 +471,21 @@ public class JavacAST extends AST<JavacAST, JavacNode, JCTree> {
increment(errorCount);
error1(pos, message);
}
-
+
final void warning(DiagnosticPosition pos, String message) {
increment(warningCount);
- log.warning(pos, "proc.messager", message);
+ warning1(pos, message);
}
-
+
final void mandatoryWarning(DiagnosticPosition pos, String message) {
increment(warningCount);
- log.mandatoryWarning(pos, "proc.messager", message);
+ mandatoryWarning1(pos, message);
}
-
- final void note(DiagnosticPosition pos, String message) {
- log.note(pos, "proc.messager", message);
- }
-
+
abstract void error1(DiagnosticPosition pos, String message);
+ abstract void warning1(DiagnosticPosition pos, String message);
+ abstract void mandatoryWarning1(DiagnosticPosition pos, String message);
+ abstract void note(DiagnosticPosition pos, String message);
private void increment(Field field) {
if (field == null) return;
@@ -520,18 +520,7 @@ public class JavacAST extends AST<JavacAST, JavacNode, JCTree> {
warningCount = f;
} catch (Throwable t) {}
-
- Method logMethod = null;
- Object multiple = null;
- try {
- Class<?> df = Class.forName("com.sun.tools.javac.util.JCDiagnostic$DiagnosticFlag");
- for (Object constant : df.getEnumConstants()) {
- if (constant.toString().equals("MULTIPLE")) multiple = constant;
- }
- logMethod = log.getClass().getMethod("error", new Class<?>[] {df, DiagnosticPosition.class, String.class, Object[].class});
- } catch (Throwable t) {}
-
- return new Jdk9Plus(log, messager, errorCount, warningCount, logMethod, multiple);
+ return new Jdk9Plus(log, messager, errorCount, warningCount);
}
}
@@ -549,22 +538,99 @@ public class JavacAST extends AST<JavacAST, JavacNode, JCTree> {
log.multipleErrors = prev;
}
}
+
+ @Override void warning1(DiagnosticPosition pos, String message) {
+ log.warning(pos, "proc.messager", message);
+ }
+
+ @Override void mandatoryWarning1(DiagnosticPosition pos, String message) {
+ log.mandatoryWarning(pos, "proc.messager", message);
+ }
+
+ @Override void note(DiagnosticPosition pos, String message) {
+ log.note(pos, "proc.messager", message);
+ }
}
static class Jdk9Plus extends ErrorLog {
- private final Object multiple;
- private final Method logMethod;
+ private static final String PROC_MESSAGER = "proc.messager";
+ private Object multiple;
+ private Method errorMethod, warningMethod, mandatoryWarningMethod, noteMethod;
+ private Method errorKey, warningKey, noteKey;
+ private JCDiagnostic.Factory diags;
- private Jdk9Plus(Log log, Messager messager, Field errorCount, Field warningCount, Method logMethod, Object multiple) {
+ private Jdk9Plus(Log log, Messager messager, Field errorCount, Field warningCount) {
super(log, messager, errorCount, warningCount);
- this.logMethod = logMethod;
- this.multiple = multiple;
+
+ try {
+ final String jcd = "com.sun.tools.javac.util.JCDiagnostic";
+ Class<?> df = Class.forName(jcd + "$DiagnosticFlag");
+ for (Object constant : df.getEnumConstants()) {
+ if (constant.toString().equals("MULTIPLE")) this.multiple = constant;
+ }
+
+ Class<?> errorCls = Class.forName(jcd + "$Error");
+ Class<?> warningCls = Class.forName(jcd + "$Warning");
+ Class<?> noteCls = Class.forName(jcd + "$Note");
+
+ Class<?> lc = log.getClass();
+ this.errorMethod = lc.getMethod("error", df, DiagnosticPosition.class, errorCls);
+ this.warningMethod = lc.getMethod("warning", DiagnosticPosition.class, warningCls);
+ this.mandatoryWarningMethod = lc.getMethod("mandatoryWarning", DiagnosticPosition.class, warningCls);
+ this.noteMethod = lc.getMethod("note", DiagnosticPosition.class, noteCls);
+
+ Field diagsField = lc.getSuperclass().getDeclaredField("diags");
+ diagsField.setAccessible(true);
+ this.diags = (JCDiagnostic.Factory)diagsField.get(log);
+
+ Class<?> dc = this.diags.getClass();
+ this.errorKey = dc.getMethod("errorKey", String.class, Object[].class);
+ this.warningKey = dc.getDeclaredMethod("warningKey", String.class, Object[].class);
+ this.warningKey.setAccessible(true);
+ this.noteKey = dc.getDeclaredMethod("noteKey", String.class, Object[].class);
+ this.noteKey.setAccessible(true);
+ } catch (Throwable t) {
+ //t.printStackTrace();
+ }
}
@Override void error1(DiagnosticPosition pos, String message) {
try {
- logMethod.invoke(log, multiple, pos, "proc.messager", new Object[] { message });
- } catch (Throwable t) {}
+ Object error = this.errorKey.invoke(diags, PROC_MESSAGER, new Object[] { message });
+ errorMethod.invoke(log, multiple, pos, error);
+ } catch (Throwable t) {
+ //t.printStackTrace();
+ }
+ }
+
+ @Override
+ void warning1(DiagnosticPosition pos, String message) {
+ try {
+ Object warning = this.warningKey.invoke(diags, PROC_MESSAGER, new Object[] { message });
+ warningMethod.invoke(log, pos, warning);
+ } catch (Throwable t) {
+ //t.printStackTrace();
+ }
+ }
+
+ @Override
+ void mandatoryWarning1(DiagnosticPosition pos, String message) {
+ try {
+ Object warning = this.warningKey.invoke(diags, PROC_MESSAGER, new Object[] { message });
+ mandatoryWarningMethod.invoke(log, pos, warning);
+ } catch (Throwable t) {
+ //t.printStackTrace();
+ }
+ }
+
+ @Override
+ void note(DiagnosticPosition pos, String message) {
+ try {
+ Object note = this.noteKey.invoke(diags, PROC_MESSAGER, new Object[] { message });
+ noteMethod.invoke(log, pos, note);
+ } catch (Throwable t) {
+ //t.printStackTrace();
+ }
}
}
}
diff --git a/src/core/lombok/javac/JavacNode.java b/src/core/lombok/javac/JavacNode.java
index fa24c2f9..2bce6e3a 100644
--- a/src/core/lombok/javac/JavacNode.java
+++ b/src/core/lombok/javac/JavacNode.java
@@ -21,13 +21,17 @@
*/
package lombok.javac;
+import java.lang.annotation.Annotation;
import java.util.List;
import javax.lang.model.element.Element;
import javax.tools.Diagnostic;
+import lombok.core.AnnotationValues;
import lombok.core.AST.Kind;
+import lombok.javac.handlers.JavacHandlerUtil;
+import com.sun.tools.javac.code.Flags;
import com.sun.tools.javac.code.Symtab;
import com.sun.tools.javac.model.JavacTypes;
import com.sun.tools.javac.tree.JCTree;
@@ -36,6 +40,7 @@ import com.sun.tools.javac.tree.JCTree.JCBlock;
import com.sun.tools.javac.tree.JCTree.JCClassDecl;
import com.sun.tools.javac.tree.JCTree.JCCompilationUnit;
import com.sun.tools.javac.tree.JCTree.JCMethodDecl;
+import com.sun.tools.javac.tree.JCTree.JCModifiers;
import com.sun.tools.javac.tree.JCTree.JCVariableDecl;
import com.sun.tools.javac.util.Context;
import com.sun.tools.javac.util.Name;
@@ -256,4 +261,70 @@ public class JavacNode extends lombok.core.LombokNode<JavacAST, JavacNode, JCTre
public void addWarning(String message, DiagnosticPosition pos) {
ast.printMessage(Diagnostic.Kind.WARNING, message, null, pos, false);
}
+
+ @Override public boolean hasAnnotation(Class<? extends Annotation> type) {
+ return JavacHandlerUtil.hasAnnotationAndDeleteIfNeccessary(type, this);
+ }
+
+ @Override public <Z extends Annotation> AnnotationValues<Z> findAnnotation(Class<Z> type) {
+ JavacNode annotation = JavacHandlerUtil.findAnnotation(type, this, true);
+ if (annotation == null) return null;
+ return JavacHandlerUtil.createAnnotation(type, annotation);
+ }
+
+ private JCModifiers getModifiers() {
+ if (node instanceof JCClassDecl) return ((JCClassDecl) node).getModifiers();
+ if (node instanceof JCMethodDecl) return ((JCMethodDecl) node).getModifiers();
+ if (node instanceof JCVariableDecl) return ((JCVariableDecl) node).getModifiers();
+ return null;
+ }
+
+ @Override public boolean isStatic() {
+ if (node instanceof JCClassDecl) {
+ JavacNode directUp = directUp();
+ if (directUp == null || directUp.getKind() == Kind.COMPILATION_UNIT) return true;
+ if (!(directUp.get() instanceof JCClassDecl)) return false;
+ JCClassDecl p = (JCClassDecl) directUp.get();
+ long f = p.mods.flags;
+ if ((Flags.INTERFACE & f) != 0) return true;
+ if ((Flags.ENUM & f) != 0) return true;
+ }
+
+ if (node instanceof JCVariableDecl) {
+ JavacNode directUp = directUp();
+ if (directUp != null && directUp.get() instanceof JCClassDecl) {
+ JCClassDecl p = (JCClassDecl) directUp.get();
+ long f = p.mods.flags;
+ if ((Flags.INTERFACE & f) != 0) return true;
+ }
+ }
+
+ JCModifiers mods = getModifiers();
+ if (mods == null) return false;
+ return (mods.flags & Flags.STATIC) != 0;
+ }
+
+ @Override public boolean isEnumMember() {
+ if (getKind() != Kind.FIELD) return false;
+ JCModifiers mods = getModifiers();
+ return mods != null && (Flags.ENUM & mods.flags) != 0;
+ }
+
+ @Override public boolean isTransient() {
+ if (getKind() != Kind.FIELD) return false;
+ JCModifiers mods = getModifiers();
+ return mods != null && (Flags.TRANSIENT & mods.flags) != 0;
+ }
+
+ @Override public int countMethodParameters() {
+ if (getKind() != Kind.METHOD) return 0;
+
+ com.sun.tools.javac.util.List<JCVariableDecl> params = ((JCMethodDecl) node).params;
+ if (params == null) return 0;
+ return params.size();
+ }
+
+ @Override public int getStartPos() {
+ return node.getPreferredPosition();
+ }
}
diff --git a/src/core/lombok/javac/apt/EmptyLombokFileObject.java b/src/core/lombok/javac/apt/EmptyLombokFileObject.java
index 5a3a7def..84bb00e4 100644
--- a/src/core/lombok/javac/apt/EmptyLombokFileObject.java
+++ b/src/core/lombok/javac/apt/EmptyLombokFileObject.java
@@ -57,7 +57,7 @@ class EmptyLombokFileObject implements LombokFileObject {
}
@Override public URI toUri() {
- return URI.create(name);
+ return URI.create("file:///" + (name.startsWith("/") ? name.substring(1) : name));
}
@Override public CharSequence getCharContent(boolean ignoreEncodingErrors) throws IOException {
diff --git a/src/core/lombok/javac/apt/LombokProcessor.java b/src/core/lombok/javac/apt/LombokProcessor.java
index 9c0a2dfa..04b494bf 100644
--- a/src/core/lombok/javac/apt/LombokProcessor.java
+++ b/src/core/lombok/javac/apt/LombokProcessor.java
@@ -69,7 +69,10 @@ import com.sun.tools.javac.util.Context;
*/
@SupportedAnnotationTypes("*")
public class LombokProcessor extends AbstractProcessor {
- private JavacProcessingEnvironment processingEnv;
+
+ private ProcessingEnvironment processingEnv;
+ private JavacProcessingEnvironment javacProcessingEnv;
+ private JavacFiler javacFiler;
private JavacTransformer transformer;
private Trees trees;
private boolean lombokDisabled = false;
@@ -81,11 +84,13 @@ public class LombokProcessor extends AbstractProcessor {
lombokDisabled = true;
return;
}
-
- this.processingEnv = (JavacProcessingEnvironment) procEnv;
-
+
+ this.processingEnv = procEnv;
+ this.javacProcessingEnv = getJavacProcessingEnvironment(procEnv);
+ this.javacFiler = getJavacFiler(procEnv.getFiler());
+
placePostCompileAndDontMakeForceRoundDummiesHook();
- trees = Trees.instance(procEnv);
+ trees = Trees.instance(javacProcessingEnv);
transformer = new JavacTransformer(procEnv.getMessager(), trees);
SortedSet<Long> p = transformer.getPriorities();
if (p.isEmpty()) {
@@ -124,7 +129,7 @@ public class LombokProcessor extends AbstractProcessor {
@SuppressWarnings("unused")
private String listAnnotationProcessorsBeforeOurs() {
try {
- Object discoveredProcessors = javacProcessingEnvironment_discoveredProcs.get(this.processingEnv);
+ Object discoveredProcessors = javacProcessingEnvironment_discoveredProcs.get(this.javacProcessingEnv);
ArrayList<?> states = (ArrayList<?>) discoveredProcessors_procStateList.get(discoveredProcessors);
if (states == null || states.isEmpty()) return null;
if (states.size() == 1) return processorState_processor.get(states.get(0)).getClass().getName();
@@ -147,7 +152,7 @@ public class LombokProcessor extends AbstractProcessor {
stopJavacProcessingEnvironmentFromClosingOurClassloader();
forceMultipleRoundsInNetBeansEditor();
- Context context = processingEnv.getContext();
+ Context context = javacProcessingEnv.getContext();
disablePartialReparseInNetBeansEditor(context);
try {
Method keyMethod = Context.class.getDeclaredMethod("key", Class.class);
@@ -161,14 +166,14 @@ public class LombokProcessor extends AbstractProcessor {
if (!(originalFiler instanceof InterceptingJavaFileManager)) {
final Messager messager = processingEnv.getMessager();
DiagnosticsReceiver receiver = new MessagerDiagnosticsReceiver(messager);
-
- JavaFileManager newFiler = new InterceptingJavaFileManager(originalFiler, receiver);
- ht.put(key, newFiler);
+
+ JavaFileManager newFilerManager = new InterceptingJavaFileManager(originalFiler, receiver);
+ ht.put(key, newFilerManager);
Field filerFileManagerField = JavacFiler.class.getDeclaredField("fileManager");
filerFileManagerField.setAccessible(true);
- filerFileManagerField.set(processingEnv.getFiler(), newFiler);
-
- replaceFileManagerJdk9(context, newFiler);
+ filerFileManagerField.set(javacFiler, newFilerManager);
+
+ replaceFileManagerJdk9(context, newFilerManager);
}
} catch (Exception e) {
throw Lombok.sneakyThrow(e);
@@ -203,7 +208,7 @@ public class LombokProcessor extends AbstractProcessor {
try {
Field f = JavacProcessingEnvironment.class.getDeclaredField("isBackgroundCompilation");
f.setAccessible(true);
- f.set(processingEnv, true);
+ f.set(javacProcessingEnv, true);
} catch (NoSuchFieldException e) {
// only NetBeans has it
} catch (Throwable t) {
@@ -277,10 +282,10 @@ public class LombokProcessor extends AbstractProcessor {
try {
Field f = JavacProcessingEnvironment.class.getDeclaredField("processorClassLoader");
f.setAccessible(true);
- ClassLoader unwrapped = (ClassLoader) f.get(processingEnv);
+ ClassLoader unwrapped = (ClassLoader) f.get(javacProcessingEnv);
if (unwrapped == null) return;
ClassLoader wrapped = wrapClassLoader(unwrapped);
- f.set(processingEnv, wrapped);
+ f.set(javacProcessingEnv, wrapped);
} catch (NoSuchFieldException e) {
// Some versions of javac have this (and call close on it), some don't. I guess this one doesn't have it.
} catch (Throwable t) {
@@ -321,7 +326,7 @@ public class LombokProcessor extends AbstractProcessor {
if (prioOfCu == null || prioOfCu != prio) continue;
cusForThisRound.add(entry.getKey());
}
- transformer.transform(prio, processingEnv.getContext(), cusForThisRound);
+ transformer.transform(prio, javacProcessingEnv.getContext(), cusForThisRound);
}
// Step 3: Push up all CUs to the next level. Set level to null if there is no next level.
@@ -349,7 +354,7 @@ public class LombokProcessor extends AbstractProcessor {
newLevels.retainAll(priorityLevelsRequiringResolutionReset);
if (!newLevels.isEmpty()) {
// Force a new round to reset resolution. The next round will cause this method (process) to be called again.
- forceNewRound(randomModuleName, (JavacFiler) processingEnv.getFiler());
+ forceNewRound(randomModuleName, javacFiler);
return false;
}
// None of the new levels need resolution, so just keep going.
@@ -399,4 +404,57 @@ public class LombokProcessor extends AbstractProcessor {
@Override public SourceVersion getSupportedSourceVersion() {
return SourceVersion.latest();
}
+
+ /**
+ * This class casts the given processing environment to a JavacProcessingEnvironment. In case of
+ * gradle incremental compilation, the delegate ProcessingEnvironment of the gradle wrapper is returned.
+ */
+ public JavacProcessingEnvironment getJavacProcessingEnvironment(Object procEnv) {
+ if (procEnv instanceof JavacProcessingEnvironment) {
+ return (JavacProcessingEnvironment) procEnv;
+ }
+
+ // try to find a "delegate" field in the object, and use this to try to obtain a JavacProcessingEnvironment
+ for (Class<?> procEnvClass = procEnv.getClass(); procEnvClass != null; procEnvClass = procEnvClass.getSuperclass()) {
+ try {
+ return getJavacProcessingEnvironment(tryGetDelegateField(procEnvClass, procEnv));
+ } catch (final Exception e) {
+ // delegate field was not found, try on superclass
+ }
+ }
+
+ processingEnv.getMessager().printMessage(Kind.WARNING,
+ "Can't get the delegate of the gradle IncrementalProcessingEnvironment. Lombok won't work.");
+ return null;
+ }
+
+ /**
+ * This class returns the given filer as a JavacFiler. In case the case that the filer is no
+ * JavacFiler (e.g. the Gradle IncrementalFiler), its "delegate" field is used to get the JavacFiler
+ * (directly or through a delegate field again)
+ */
+ public JavacFiler getJavacFiler(Object filer) {
+ if (filer instanceof JavacFiler) {
+ return (JavacFiler) filer;
+ }
+
+ // try to find a "delegate" field in the object, and use this to check for a JavacFiler
+ for (Class<?> filerClass = filer.getClass(); filerClass != null; filerClass = filerClass.getSuperclass()) {
+ try {
+ return getJavacFiler(tryGetDelegateField(filerClass, filer));
+ } catch (final Exception e) {
+ // delegate field was not found, try on superclass
+ }
+ }
+
+ processingEnv.getMessager().printMessage(Kind.WARNING,
+ "Can't get a JavacFiler from " + filer.getClass().getName() + ". Lombok won't work.");
+ return null;
+ }
+
+ private Object tryGetDelegateField(Class<?> delegateClass, Object instance) throws Exception {
+ Field field = delegateClass.getDeclaredField("delegate");
+ field.setAccessible(true);
+ return field.get(instance);
+ }
}
diff --git a/src/core/lombok/javac/handlers/HandleBuilder.java b/src/core/lombok/javac/handlers/HandleBuilder.java
index fec999ba..d56d6ac2 100644
--- a/src/core/lombok/javac/handlers/HandleBuilder.java
+++ b/src/core/lombok/javac/handlers/HandleBuilder.java
@@ -54,10 +54,12 @@ import lombok.Builder;
import lombok.Builder.ObtainVia;
import lombok.ConfigurationKeys;
import lombok.Singular;
+import lombok.ToString;
import lombok.core.AST.Kind;
import lombok.core.AnnotationValues;
import lombok.core.HandlerPriority;
import lombok.core.handlers.HandlerUtil;
+import lombok.core.handlers.InclusionExclusionUtils.Included;
import lombok.experimental.NonFinal;
import lombok.javac.Javac;
import lombok.javac.JavacAnnotationHandler;
@@ -398,10 +400,13 @@ public class HandleBuilder extends JavacAnnotationHandler<Builder> {
}
if (methodExists("toString", builderType, 0) == MemberExistsResult.NOT_EXISTS) {
- java.util.List<JavacNode> fieldNodes = new ArrayList<JavacNode>();
+ java.util.List<Included<JavacNode, ToString.Include>> fieldNodes = new ArrayList<Included<JavacNode, ToString.Include>>();
for (BuilderFieldData bfd : builderFields) {
- fieldNodes.addAll(bfd.createdFields);
+ for (JavacNode f : bfd.createdFields) {
+ fieldNodes.add(new Included<JavacNode, ToString.Include>(f, null, true));
+ }
}
+
JCMethodDecl md = HandleToString.createToString(builderType, fieldNodes, true, false, FieldAccess.ALWAYS_FIELD, ast);
if (md != null) injectMethod(builderType, md);
}
diff --git a/src/core/lombok/javac/handlers/HandleConstructor.java b/src/core/lombok/javac/handlers/HandleConstructor.java
index dca25ee7..32eb43b2 100644
--- a/src/core/lombok/javac/handlers/HandleConstructor.java
+++ b/src/core/lombok/javac/handlers/HandleConstructor.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2010-2014 The Project Lombok Authors.
+ * Copyright (C) 2010-2018 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
@@ -22,22 +22,8 @@
package lombok.javac.handlers;
import static lombok.core.handlers.HandlerUtil.*;
-import static lombok.javac.handlers.JavacHandlerUtil.*;
import static lombok.javac.Javac.*;
-
-import lombok.AccessLevel;
-import lombok.AllArgsConstructor;
-import lombok.Builder;
-import lombok.ConfigurationKeys;
-import lombok.NoArgsConstructor;
-import lombok.RequiredArgsConstructor;
-import lombok.core.AnnotationValues;
-import lombok.core.AST.Kind;
-import lombok.delombok.LombokOptionsFactory;
-import lombok.javac.Javac;
-import lombok.javac.JavacAnnotationHandler;
-import lombok.javac.JavacNode;
-import lombok.javac.JavacTreeMaker;
+import static lombok.javac.handlers.JavacHandlerUtil.*;
import org.mangosdk.spi.ProviderFor;
@@ -61,6 +47,21 @@ import com.sun.tools.javac.util.List;
import com.sun.tools.javac.util.ListBuffer;
import com.sun.tools.javac.util.Name;
+import lombok.AccessLevel;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.ConfigurationKeys;
+import lombok.NoArgsConstructor;
+import lombok.RequiredArgsConstructor;
+import lombok.core.AST.Kind;
+import lombok.core.AnnotationValues;
+import lombok.delombok.LombokOptionsFactory;
+import lombok.javac.Javac;
+import lombok.javac.JavacAnnotationHandler;
+import lombok.javac.JavacNode;
+import lombok.javac.JavacTreeMaker;
+import lombok.javac.handlers.JavacHandlerUtil.MemberExistsResult;
+
public class HandleConstructor {
@ProviderFor(JavacAnnotationHandler.class)
public static class HandleNoArgsConstructor extends JavacAnnotationHandler<NoArgsConstructor> {
@@ -191,19 +192,33 @@ public class HandleConstructor {
return true;
}
- public void generateRequiredArgsConstructor(JavacNode typeNode, AccessLevel level, String staticName, SkipIfConstructorExists skipIfConstructorExists, JavacNode source) {
- generateConstructor(typeNode, level, List.<JCAnnotation>nil(), findRequiredFields(typeNode), false, staticName, skipIfConstructorExists, source);
- }
-
public enum SkipIfConstructorExists {
YES, NO, I_AM_BUILDER;
}
+ public void generateExtraNoArgsConstructor(JavacNode typeNode, JavacNode source) {
+ if (!isDirectDescendantOfObject(typeNode)) return;
+
+ Boolean v = typeNode.getAst().readConfiguration(ConfigurationKeys.NO_ARGS_CONSTRUCTOR_EXTRA_PRIVATE);
+ if (v == null || !v) return;
+
+ List<JavacNode> fields = findFinalFields(typeNode);
+ generate(typeNode, AccessLevel.PRIVATE, List.<JCAnnotation>nil(), fields, true, null, SkipIfConstructorExists.NO, source, true);
+ }
+
+ public void generateRequiredArgsConstructor(JavacNode typeNode, AccessLevel level, String staticName, SkipIfConstructorExists skipIfConstructorExists, JavacNode source) {
+ generateConstructor(typeNode, level, List.<JCAnnotation>nil(), findRequiredFields(typeNode), false, staticName, skipIfConstructorExists, source);
+ }
+
public void generateAllArgsConstructor(JavacNode typeNode, AccessLevel level, String staticName, SkipIfConstructorExists skipIfConstructorExists, JavacNode source) {
generateConstructor(typeNode, level, List.<JCAnnotation>nil(), findAllFields(typeNode), false, staticName, skipIfConstructorExists, source);
}
public void generateConstructor(JavacNode typeNode, AccessLevel level, List<JCAnnotation> onConstructor, List<JavacNode> fields, boolean allToDefault, String staticName, SkipIfConstructorExists skipIfConstructorExists, JavacNode source) {
+ generate(typeNode, level, onConstructor, fields, allToDefault, staticName, skipIfConstructorExists, source, false);
+ }
+
+ private void generate(JavacNode typeNode, AccessLevel level, List<JCAnnotation> onConstructor, List<JavacNode> fields, boolean allToDefault, String staticName, SkipIfConstructorExists skipIfConstructorExists, JavacNode source, boolean noArgs) {
boolean staticConstrRequired = staticName != null && !staticName.equals("");
if (skipIfConstructorExists != SkipIfConstructorExists.NO && constructorExists(typeNode) != MemberExistsResult.NOT_EXISTS) return;
@@ -232,6 +247,8 @@ public class HandleConstructor {
}
}
+ if (noArgs && noArgsConstructorExists(typeNode)) return;
+
JCMethodDecl constr = createConstructor(staticConstrRequired ? AccessLevel.PRIVATE : level, onConstructor, typeNode, fields, allToDefault, source);
ListBuffer<Type> argTypes = new ListBuffer<Type>();
for (JavacNode fieldNode : fields) {
@@ -252,6 +269,27 @@ public class HandleConstructor {
}
}
+ private static boolean noArgsConstructorExists(JavacNode node) {
+ node = upToTypeNode(node);
+
+ if (node != null && node.get() instanceof JCClassDecl) {
+ for (JCTree def : ((JCClassDecl) node.get()).defs) {
+ if (def instanceof JCMethodDecl) {
+ JCMethodDecl md = (JCMethodDecl) def;
+ if (md.name.contentEquals("<init>") && md.params.size() == 0) return true;
+ }
+ }
+ }
+
+ for (JavacNode child : node.down()) {
+ if (annotationTypeMatches(NoArgsConstructor.class, child)) return true;
+ if (annotationTypeMatches(RequiredArgsConstructor.class, child) && findRequiredFields(node).isEmpty()) return true;
+ if (annotationTypeMatches(AllArgsConstructor.class, child) && findAllFields(node).isEmpty()) return true;
+ }
+
+ return false;
+ }
+
public static void addConstructorProperties(JCModifiers mods, JavacNode node, List<JavacNode> fields) {
if (fields.isEmpty()) return;
JavacTreeMaker maker = node.getTreeMaker();
diff --git a/src/core/lombok/javac/handlers/HandleData.java b/src/core/lombok/javac/handlers/HandleData.java
index 15f1fd83..15c9c9e7 100644
--- a/src/core/lombok/javac/handlers/HandleData.java
+++ b/src/core/lombok/javac/handlers/HandleData.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2009-2014 The Project Lombok Authors.
+ * Copyright (C) 2009-2018 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
@@ -34,6 +34,7 @@ import lombok.javac.handlers.HandleConstructor.SkipIfConstructorExists;
import org.mangosdk.spi.ProviderFor;
import com.sun.tools.javac.tree.JCTree.JCAnnotation;
+import com.sun.tools.javac.util.List;
/**
* Handles the {@code lombok.Data} annotation for javac.
@@ -60,9 +61,11 @@ public class HandleData extends JavacAnnotationHandler<Data> {
String staticConstructorName = annotation.getInstance().staticConstructor();
+ // TODO move this to the end OR move it to the top in eclipse.
handleConstructor.generateRequiredArgsConstructor(typeNode, AccessLevel.PUBLIC, staticConstructorName, SkipIfConstructorExists.YES, annotationNode);
- handleGetter.generateGetterForType(typeNode, annotationNode, AccessLevel.PUBLIC, true);
- handleSetter.generateSetterForType(typeNode, annotationNode, AccessLevel.PUBLIC, true);
+ handleConstructor.generateExtraNoArgsConstructor(typeNode, annotationNode);
+ handleGetter.generateGetterForType(typeNode, annotationNode, AccessLevel.PUBLIC, true, List.<JCAnnotation>nil());
+ handleSetter.generateSetterForType(typeNode, annotationNode, AccessLevel.PUBLIC, true, List.<JCAnnotation>nil(), List.<JCAnnotation>nil());
handleEqualsAndHashCode.generateEqualsAndHashCodeForType(typeNode, annotationNode);
handleToString.generateToStringForType(typeNode, annotationNode);
}
diff --git a/src/core/lombok/javac/handlers/HandleEqualsAndHashCode.java b/src/core/lombok/javac/handlers/HandleEqualsAndHashCode.java
index d8bfd154..aa0fe633 100644
--- a/src/core/lombok/javac/handlers/HandleEqualsAndHashCode.java
+++ b/src/core/lombok/javac/handlers/HandleEqualsAndHashCode.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2009-2014 The Project Lombok Authors.
+ * Copyright (C) 2009-2018 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
@@ -21,7 +21,7 @@
*/
package lombok.javac.handlers;
-import static lombok.core.handlers.HandlerUtil.*;
+import static lombok.core.handlers.HandlerUtil.handleFlagUsage;
import static lombok.javac.Javac.*;
import static lombok.javac.handlers.JavacHandlerUtil.*;
@@ -29,19 +29,6 @@ import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
-import lombok.ConfigurationKeys;
-import lombok.EqualsAndHashCode;
-import lombok.core.AST.Kind;
-import lombok.core.configuration.CallSuperType;
-import lombok.core.AnnotationValues;
-import lombok.core.handlers.HandlerUtil;
-import lombok.javac.Javac;
-import lombok.javac.JavacAnnotationHandler;
-import lombok.javac.JavacNode;
-import lombok.javac.JavacTreeMaker;
-import lombok.javac.handlers.JavacHandlerUtil.FieldAccess;
-import lombok.javac.handlers.JavacHandlerUtil.MemberExistsResult;
-
import org.mangosdk.spi.ProviderFor;
import com.sun.tools.javac.code.BoundKind;
@@ -66,6 +53,20 @@ import com.sun.tools.javac.util.List;
import com.sun.tools.javac.util.ListBuffer;
import com.sun.tools.javac.util.Name;
+import lombok.ConfigurationKeys;
+import lombok.EqualsAndHashCode;
+import lombok.core.AST.Kind;
+import lombok.core.AnnotationValues;
+import lombok.core.configuration.CallSuperType;
+import lombok.core.handlers.HandlerUtil;
+import lombok.core.handlers.HandlerUtil.FieldAccess;
+import lombok.core.handlers.InclusionExclusionUtils;
+import lombok.core.handlers.InclusionExclusionUtils.Included;
+import lombok.javac.JavacAnnotationHandler;
+import lombok.javac.JavacNode;
+import lombok.javac.JavacTreeMaker;
+import lombok.javac.handlers.JavacHandlerUtil.MemberExistsResult;
+
/**
* Handles the {@code lombok.EqualsAndHashCode} annotation for javac.
*/
@@ -74,45 +75,23 @@ public class HandleEqualsAndHashCode extends JavacAnnotationHandler<EqualsAndHas
private static final String RESULT_NAME = "result";
private static final String PRIME_NAME = "PRIME";
- public void checkForBogusFieldNames(JavacNode type, AnnotationValues<EqualsAndHashCode> annotation) {
- if (annotation.isExplicit("exclude")) {
- for (int i : createListOfNonExistentFields(List.from(annotation.getInstance().exclude()), type, true, true)) {
- annotation.setWarning("exclude", "This field does not exist, or would have been excluded anyway.", i);
- }
- }
- if (annotation.isExplicit("of")) {
- for (int i : createListOfNonExistentFields(List.from(annotation.getInstance().of()), type, false, false)) {
- annotation.setWarning("of", "This field does not exist.", i);
- }
- }
- }
-
@Override public void handle(AnnotationValues<EqualsAndHashCode> annotation, JCAnnotation ast, JavacNode annotationNode) {
handleFlagUsage(annotationNode, ConfigurationKeys.EQUALS_AND_HASH_CODE_FLAG_USAGE, "@EqualsAndHashCode");
deleteAnnotationIfNeccessary(annotationNode, EqualsAndHashCode.class);
EqualsAndHashCode ann = annotation.getInstance();
- List<String> excludes = List.from(ann.exclude());
- List<String> includes = List.from(ann.of());
+ java.util.List<Included<JavacNode, EqualsAndHashCode.Include>> members = InclusionExclusionUtils.handleEqualsAndHashCodeMarking(annotationNode.up(), annotation, annotationNode);
JavacNode typeNode = annotationNode.up();
List<JCAnnotation> onParam = unboxAndRemoveAnnotationParameter(ast, "onParam", "@EqualsAndHashCode(onParam", annotationNode);
- checkForBogusFieldNames(typeNode, annotation);
Boolean callSuper = ann.callSuper();
if (!annotation.isExplicit("callSuper")) callSuper = null;
- if (!annotation.isExplicit("exclude")) excludes = null;
- if (!annotation.isExplicit("of")) includes = null;
-
- if (excludes != null && includes != null) {