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/CompilerMessageSuppressor.java206
-rw-r--r--src/core/lombok/javac/JavacAST.java145
-rw-r--r--src/core/lombok/javac/apt/LombokFileObjects.java42
-rw-r--r--src/core/lombok/javac/handlers/HandleBuilder.java106
-rw-r--r--src/core/lombok/javac/handlers/HandleBuilderDefault.java29
-rw-r--r--src/core/lombok/javac/handlers/HandleConstructor.java54
-rw-r--r--src/core/lombok/javac/handlers/HandleEqualsAndHashCode.java7
-rw-r--r--src/core/lombok/javac/handlers/HandleGetter.java2
-rw-r--r--src/core/lombok/javac/handlers/HandleSetter.java15
-rw-r--r--src/core/lombok/javac/handlers/HandleToString.java6
-rw-r--r--src/core/lombok/javac/handlers/HandleWither.java4
-rw-r--r--src/core/lombok/javac/handlers/JavacHandlerUtil.java136
-rw-r--r--src/core/lombok/javac/handlers/JavacSingularsRecipes.java12
-rw-r--r--src/core/lombok/javac/handlers/singulars/JavacGuavaSingularizer.java23
-rw-r--r--src/core/lombok/javac/handlers/singulars/JavacJavaUtilListSetSingularizer.java26
-rw-r--r--src/core/lombok/javac/handlers/singulars/JavacJavaUtilMapSingularizer.java26
-rw-r--r--src/core/lombok/javac/handlers/singulars/JavacJavaUtilSingularizer.java3
17 files changed, 593 insertions, 249 deletions
diff --git a/src/core/lombok/javac/CompilerMessageSuppressor.java b/src/core/lombok/javac/CompilerMessageSuppressor.java
index a17e0c62..391ec64a 100644
--- a/src/core/lombok/javac/CompilerMessageSuppressor.java
+++ b/src/core/lombok/javac/CompilerMessageSuppressor.java
@@ -26,6 +26,7 @@ import java.io.OutputStream;
import java.io.PrintWriter;
import java.lang.reflect.Field;
import java.util.LinkedList;
+import java.util.Map;
import java.util.Queue;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
@@ -43,38 +44,40 @@ import com.sun.tools.javac.util.Log;
* then they will be generated AGAIN, this time with proper names and line numbers, at the end. Therefore, we want to suppress the logger.
*/
public final class CompilerMessageSuppressor {
+
private final Log log;
- private static final Field errWriterField, warnWriterField, noticeWriterField, dumpOnErrorField, promptOnErrorField, diagnosticListenerField;
+ private static final WriterField errWriterField, warnWriterField, noticeWriterField;
+ private static final Field dumpOnErrorField, promptOnErrorField, diagnosticListenerField;
private static final Field deferDiagnosticsField, deferredDiagnosticsField, diagnosticHandlerField;
private static final ConcurrentMap<Class<?>, Field> handlerDeferredFields = new ConcurrentHashMap<Class<?>, Field>();
private static final Field NULL_FIELD;
- private PrintWriter errWriter, warnWriter, noticeWriter;
private Boolean dumpOnError, promptOnError;
private DiagnosticListener<?> contextDiagnosticListener, logDiagnosticListener;
private final Context context;
- // If this is true, the fields changed. Better to print weird error messages than to fail outright.
- private static final boolean dontBother;
-
private static final ThreadLocal<Queue<?>> queueCache = new ThreadLocal<Queue<?>>();
+ enum Writers {
+ ERROR("errWriter", "ERROR"),
+ WARNING("warnWriter", "WARNING"),
+ NOTICE("noticeWriter", "NOTICE");
+
+ final String fieldName;
+ final String keyName;
+
+ Writers(String fieldName, String keyName) {
+ this.fieldName = fieldName;
+ this.keyName = keyName;
+ }
+ }
+
static {
- errWriterField = getDeclaredField(Log.class, "errWriter");
- warnWriterField = getDeclaredField(Log.class, "warnWriter");
- noticeWriterField = getDeclaredField(Log.class, "noticeWriter");
+ errWriterField = createWriterField(Writers.ERROR);
+ warnWriterField = createWriterField(Writers.WARNING);
+ noticeWriterField = createWriterField(Writers.NOTICE);
dumpOnErrorField = getDeclaredField(Log.class, "dumpOnError");
promptOnErrorField = getDeclaredField(Log.class, "promptOnError");
diagnosticListenerField = getDeclaredField(Log.class, "diagListener");
-
- dontBother =
- errWriterField == null ||
- warnWriterField == null ||
- noticeWriterField == null ||
- dumpOnErrorField == null ||
- promptOnErrorField == null ||
- diagnosticListenerField == null;
-
-
deferDiagnosticsField = getDeclaredField(Log.class, "deferDiagnostics");
deferredDiagnosticsField = getDeclaredField(Log.class, "deferredDiagnostics");
@@ -100,17 +103,13 @@ public final class CompilerMessageSuppressor {
this.context = context;
}
- public boolean disableLoggers() {
+ public void disableLoggers() {
contextDiagnosticListener = context.get(DiagnosticListener.class);
context.put(DiagnosticListener.class, (DiagnosticListener<?>) null);
- if (dontBother) return false;
- boolean dontBotherInstance = false;
-
- PrintWriter dummyWriter = new PrintWriter(new OutputStream() {
- @Override public void write(int b) throws IOException {
- // Do nothing on purpose
- }
- });
+
+ errWriterField.pauze(log);
+ warnWriterField.pauze(log);
+ noticeWriterField.pauze(log);
if (deferDiagnosticsField != null) try {
if (Boolean.TRUE.equals(deferDiagnosticsField.get(log))) {
@@ -130,50 +129,23 @@ public final class CompilerMessageSuppressor {
}
} catch (Exception e) {}
- if (!dontBotherInstance) try {
- errWriter = (PrintWriter) errWriterField.get(log);
- errWriterField.set(log, dummyWriter);
- } catch (Exception e) {
- dontBotherInstance = true;
- }
-
- if (!dontBotherInstance) try {
- warnWriter = (PrintWriter) warnWriterField.get(log);
- warnWriterField.set(log, dummyWriter);
- } catch (Exception e) {
- dontBotherInstance = true;
- }
-
- if (!dontBotherInstance) try {
- noticeWriter = (PrintWriter) noticeWriterField.get(log);
- noticeWriterField.set(log, dummyWriter);
- } catch (Exception e) {
- dontBotherInstance = true;
- }
-
- if (!dontBotherInstance) try {
+ if (dumpOnErrorField != null) try {
dumpOnError = (Boolean) dumpOnErrorField.get(log);
dumpOnErrorField.set(log, false);
} catch (Exception e) {
- dontBotherInstance = true;
}
- if (!dontBotherInstance) try {
+ if (promptOnErrorField != null) try {
promptOnError = (Boolean) promptOnErrorField.get(log);
promptOnErrorField.set(log, false);
} catch (Exception e) {
- dontBotherInstance = true;
}
- if (!dontBotherInstance) try {
+ if (diagnosticListenerField != null) try {
logDiagnosticListener = (DiagnosticListener<?>) diagnosticListenerField.get(log);
diagnosticListenerField.set(log, null);
} catch (Exception e) {
- dontBotherInstance = true;
}
-
- if (dontBotherInstance) enableLoggers();
- return !dontBotherInstance;
}
private static Field getDeferredField(Object handler) {
@@ -193,20 +165,9 @@ public final class CompilerMessageSuppressor {
contextDiagnosticListener = null;
}
- if (errWriter != null) try {
- errWriterField.set(log, errWriter);
- errWriter = null;
- } catch (Exception e) {}
-
- if (warnWriter != null) try {
- warnWriterField.set(log, warnWriter);
- warnWriter = null;
- } catch (Exception e) {}
-
- if (noticeWriter != null) try {
- noticeWriterField.set(log, noticeWriter);
- noticeWriter = null;
- } catch (Exception e) {}
+ errWriterField.resume(log);
+ warnWriterField.resume(log);
+ noticeWriterField.resume(log);
if (dumpOnError != null) try {
dumpOnErrorField.set(log, dumpOnError);
@@ -283,4 +244,107 @@ public final class CompilerMessageSuppressor {
// javac will contain rather a lot of messages, but this is a lot better than just crashing during compilation!
}
}
+
+ private static WriterField createWriterField(Writers w) {
+ // jdk9
+ try {
+ Field writers = getDeclaredField(Log.class, "writer");
+ if (writers != null) {
+ Class<?> kindsClass = Class.forName("com.sun.tools.javac.util.Log$WriterKind");
+ for (Object enumConstant : kindsClass.getEnumConstants()) {
+ if (enumConstant.toString().equals(w.keyName)) {
+ return new Java9WriterField(writers, enumConstant);
+ }
+ }
+ return WriterField.NONE;
+ }
+ } catch (Exception e) {
+ }
+
+ // jdk8
+ Field writerField = getDeclaredField(Log.class, w.fieldName);
+ if (writerField != null) return new Java8WriterField(writerField);
+
+ // other jdk
+ return WriterField.NONE;
+ }
+
+ interface WriterField {
+ final PrintWriter NO_WRITER = new PrintWriter(new OutputStream() {
+ @Override public void write(int b) throws IOException {
+ // Do nothing on purpose
+ }
+ });
+
+ final WriterField NONE = new WriterField() {
+ @Override public void pauze(Log log) {
+ // do nothing
+ }
+ @Override public void resume(Log log) {
+ // no nothing
+ }
+ };
+
+ void pauze(Log log);
+ void resume(Log log);
+ }
+
+ static class Java8WriterField implements WriterField {
+ private final Field field;
+ private PrintWriter writer;
+
+ public Java8WriterField(Field field) {
+ this.field = field;
+ }
+
+ @Override public void pauze(Log log) {
+ try {
+ writer = (PrintWriter) field.get(log);
+ field.set(log, NO_WRITER);
+ } catch (Exception e) {
+ }
+ }
+
+ @Override public void resume(Log log) {
+ if (writer != null) {
+ try {
+ field.set(log, writer);
+ } catch (Exception e) {
+ }
+ }
+ writer = null;
+ }
+ }
+
+
+ static class Java9WriterField implements WriterField {
+ private final Field field;
+ private final Object key;
+ private PrintWriter writer;
+
+ public Java9WriterField(Field field, Object key) {
+ this.field = field;
+ this.key = key;
+ }
+
+ @Override public void pauze(Log log) {
+ try {
+ @SuppressWarnings("unchecked") Map<Object,PrintWriter> map = (Map<Object,PrintWriter>)field.get(log);
+ writer = map.get(key);
+ map.put(key, NO_WRITER);
+ } catch (Exception e) {
+ }
+ }
+
+ @Override public void resume(Log log) {
+ if (writer != null) {
+ try {
+ @SuppressWarnings("unchecked") Map<Object,PrintWriter> map = (Map<Object,PrintWriter>)field.get(log);
+ map.put(key, writer);
+ } catch (Exception e) {
+ }
+ }
+ writer = null;
+ }
+ }
} \ No newline at end of file
diff --git a/src/core/lombok/javac/JavacAST.java b/src/core/lombok/javac/JavacAST.java
index c99ae5c9..91ed325f 100644
--- a/src/core/lombok/javac/JavacAST.java
+++ b/src/core/lombok/javac/JavacAST.java
@@ -65,12 +65,12 @@ import com.sun.tools.javac.util.Name;
* something javac's own AST system does not offer.
*/
public class JavacAST extends AST<JavacAST, JavacNode, JCTree> {
- private final Messager messager;
private final JavacElements elements;
private final JavacTreeMaker treeMaker;
private final Symtab symtab;
private final JavacTypes javacTypes;
private final Log log;
+ private final ErrorLog errorLogger;
private final Context context;
/**
@@ -84,8 +84,8 @@ public class JavacAST extends AST<JavacAST, JavacNode, JCTree> {
super(sourceName(top), PackageName.getPackageName(top), new JavacImportList(top), statementTypes());
setTop(buildCompilationUnit(top));
this.context = context;
- this.messager = messager;
this.log = Log.instance(context);
+ this.errorLogger = ErrorLog.create(messager, log);
this.elements = JavacElements.instance(context);
this.treeMaker = new JavacTreeMaker(TreeMaker.instance(context));
this.symtab = Symtab.instance(context);
@@ -422,22 +422,21 @@ public class JavacAST extends AST<JavacAST, JavacNode, JCTree> {
try {
switch (kind) {
case ERROR:
- increaseErrorCount(messager);
- boolean prev = log.multipleErrors;
- log.multipleErrors = true;
- try {
- log.error(pos, "proc.messager", message);
- } finally {
- log.multipleErrors = prev;
- }
+ errorLogger.error(pos, message);
+ break;
+ case MANDATORY_WARNING:
+ errorLogger.mandatoryWarning(pos, message);
break;
- default:
case WARNING:
- log.warning(pos, "proc.messager", message);
+ errorLogger.warning(pos, message);
+ break;
+ default:
+ case NOTE:
+ errorLogger.note(pos, message);
break;
}
} finally {
- if (oldSource != null) log.useSource(oldSource);
+ if (newSource != null) log.useSource(oldSource);
}
}
@@ -475,16 +474,118 @@ public class JavacAST extends AST<JavacAST, JavacNode, JCTree> {
return oldL;
}
- private void increaseErrorCount(Messager m) {
- try {
- Field f = m.getClass().getDeclaredField("errorCount");
- f.setAccessible(true);
- if (f.getType() == int.class) {
- int val = ((Number)f.get(m)).intValue();
- f.set(m, val +1);
+ abstract static class ErrorLog {
+ final Log log;
+ private final Messager messager;
+ private final Field errorCount;
+ private final Field warningCount;
+
+ private ErrorLog(Log log, Messager messager, Field errorCount, Field warningCount) {
+ this.log = log;
+ this.messager = messager;
+ this.errorCount = errorCount;
+ this.warningCount = warningCount;
+ }
+
+ final void error(DiagnosticPosition pos, String message) {
+ increment(errorCount);
+ error1(pos, message);
+ }
+
+ final void warning(DiagnosticPosition pos, String message) {
+ increment(warningCount);
+ log.warning(pos, "proc.messager", message);
+ }
+
+ final void mandatoryWarning(DiagnosticPosition pos, String message) {
+ increment(warningCount);
+ log.mandatoryWarning(pos, "proc.messager", message);
+ }
+
+ final void note(DiagnosticPosition pos, String message) {
+ log.note(pos, "proc.messager", message);
+ }
+
+ abstract void error1(DiagnosticPosition pos, String message);
+
+ private void increment(Field field) {
+ if (field == null) return;
+ try {
+ int val = ((Number)field.get(messager)).intValue();
+ field.set(messager, val +1);
+ } catch (Throwable t) {
+ //Very unfortunate, but in most cases it still works fine, so we'll silently swallow it.
}
- } catch (Throwable t) {
- //Very unfortunate, but in most cases it still works fine, so we'll silently swallow it.
+ }
+
+ static ErrorLog create(Messager messager, Log log) {
+ Field errorCount = null;
+ try {
+ Field f = messager.getClass().getDeclaredField("errorCount");
+ f.setAccessible(true);
+ errorCount = f;
+ } catch (Throwable t) {}
+ boolean hasMultipleErrors = false;
+ for (Field field : log.getClass().getFields()) {
+ if (field.getName().equals("multipleErrors")) {
+ hasMultipleErrors = true;
+ break;
+ }
+ }
+ if (hasMultipleErrors) return new JdkBefore9(log, messager, errorCount);
+
+ Field warningCount = null;
+ try {
+ Field f = messager.getClass().getDeclaredField("warningCount");
+ f.setAccessible(true);
+ 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);
+ }
+ }
+
+ static class JdkBefore9 extends ErrorLog {
+ private JdkBefore9(Log log, Messager messager, Field errorCount) {
+ super(log, messager, errorCount, null);
+ }
+
+ @Override void error1(DiagnosticPosition pos, String message) {
+ boolean prev = log.multipleErrors;
+ log.multipleErrors = true;
+ try {
+ log.error(pos, "proc.messager", message);
+ } finally {
+ log.multipleErrors = prev;
+ }
+ }
+ }
+
+ static class Jdk9Plus extends ErrorLog {
+ private final Object multiple;
+ private final Method logMethod;
+
+ private Jdk9Plus(Log log, Messager messager, Field errorCount, Field warningCount, Method logMethod, Object multiple) {
+ super(log, messager, errorCount, warningCount);
+ this.logMethod = logMethod;
+ this.multiple = multiple;
+ }
+
+ @Override void error1(DiagnosticPosition pos, String message) {
+ try {
+ logMethod.invoke(multiple, pos, "proc.messager", message);
+ } catch (Throwable t) {}
}
}
}
diff --git a/src/core/lombok/javac/apt/LombokFileObjects.java b/src/core/lombok/javac/apt/LombokFileObjects.java
index 7e818cab..cb2036e9 100644
--- a/src/core/lombok/javac/apt/LombokFileObjects.java
+++ b/src/core/lombok/javac/apt/LombokFileObjects.java
@@ -22,8 +22,10 @@
package lombok.javac.apt;
+import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.net.URI;
+import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.concurrent.atomic.AtomicBoolean;
@@ -31,10 +33,10 @@ import javax.tools.JavaFileManager;
import javax.tools.JavaFileObject;
import javax.tools.JavaFileObject.Kind;
-import com.sun.tools.javac.file.BaseFileManager;
-
import lombok.core.DiagnosticsReceiver;
+import com.sun.tools.javac.file.BaseFileManager;
+
//Can't use SimpleJavaFileObject so we copy/paste most of its content here, because javac doesn't follow the interface,
//and casts to its own BaseFileObject type. D'oh!
final class LombokFileObjects {
@@ -98,7 +100,9 @@ final class LombokFileObjects {
String jfmClassName = jfm != null ? jfm.getClass().getName() : "null";
if (jfmClassName.equals("com.sun.tools.javac.util.DefaultFileManager")) return Compiler.JAVAC6;
if (jfmClassName.equals("com.sun.tools.javac.util.JavacFileManager")) return Compiler.JAVAC6;
- if (jfmClassName.equals("com.sun.tools.javac.file.JavacFileManager")) {
+ if (jfmClassName.equals("com.sun.tools.javac.file.JavacFileManager") ||
+ jfmClassName.equals("com.google.errorprone.MaskedClassLoader$MaskedFileManager") ||
+ jfmClassName.equals("com.google.devtools.build.buildjar.javac.BlazeJavacMain$ClassloaderMaskingFileManager")) {
try {
Class<?> superType = Class.forName("com.sun.tools.javac.file.BaseFileManager");
if (superType.isInstance(jfm)) {
@@ -108,6 +112,18 @@ final class LombokFileObjects {
catch (Exception e) {}
return Compiler.JAVAC7;
}
+ if (jfmClassName.equals("com.sun.tools.javac.api.ClientCodeWrapper$WrappedStandardJavaFileManager")) {
+ try {
+ Field wrappedField = Class.forName("com.sun.tools.javac.api.ClientCodeWrapper$WrappedJavaFileManager").getDeclaredField("clientJavaFileManager");
+ wrappedField.setAccessible(true);
+ JavaFileManager wrappedManager = (JavaFileManager)wrappedField.get(jfm);
+ Class<?> superType = Class.forName("com.sun.tools.javac.file.BaseFileManager");
+ if (superType.isInstance(wrappedManager)) {
+ return new Java9Compiler(wrappedManager);
+ }
+ }
+ catch (Exception e) {}
+ }
try {
if (Class.forName("com.sun.tools.javac.file.BaseFileObject") == null) throw new NullPointerException();
return Compiler.JAVAC7;
@@ -116,7 +132,15 @@ final class LombokFileObjects {
if (Class.forName("com.sun.tools.javac.util.BaseFileObject") == null) throw new NullPointerException();
return Compiler.JAVAC6;
} catch (Exception e) {}
- return null;
+
+ StringBuilder sb = new StringBuilder(jfmClassName);
+ if (jfm != null) {
+ sb.append(" extends ").append(jfm.getClass().getSuperclass().getName());
+ for (Class<?> cls : jfm.getClass().getInterfaces()) {
+ sb.append(" implements ").append(cls.getName());
+ }
+ }
+ throw new IllegalArgumentException(sb.toString());
}
static JavaFileObject createEmpty(Compiler compiler, String name, Kind kind) {
@@ -137,9 +161,15 @@ final class LombokFileObjects {
@Override public JavaFileObject wrap(LombokFileObject fileObject) {
URI uri = fileObject.toUri();
if (uri.getScheme() == null) {
- uri = URI.create("file://" + uri);
+ uri = URI.create("file:///" + uri);
+ }
+ Path path;
+ try {
+ path = Paths.get(uri);
+ } catch (IllegalArgumentException e) {
+ throw new IllegalArgumentException("Problems in URI '" + uri + "' (" + fileObject.toUri() + ")", e);
}
- return new Javac9BaseFileObjectWrapper(fileManager, Paths.get(uri), fileObject);
+ return new Javac9BaseFileObjectWrapper(fileManager, path, fileObject);
}
@Override public Method getDecoderMethod() {
diff --git a/src/core/lombok/javac/handlers/HandleBuilder.java b/src/core/lombok/javac/handlers/HandleBuilder.java
index 2704981b..157828a0 100644
--- a/src/core/lombok/javac/handlers/HandleBuilder.java
+++ b/src/core/lombok/javac/handlers/HandleBuilder.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2013-2015 The Project Lombok Authors.
+ * Copyright (C) 2013-2017 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
@@ -85,9 +85,12 @@ public class HandleBuilder extends JavacAnnotationHandler<Builder> {
JCExpression type;
Name rawName;
Name name;
+ Name nameOfDefaultProvider;
+ Name nameOfSetFlag;
SingularData singularData;
ObtainVia obtainVia;
JavacNode obtainViaNode;
+ JavacNode originalFieldNode;
java.util.List<JavacNode> createdFields = new ArrayList<JavacNode>();
}
@@ -139,23 +142,45 @@ public class HandleBuilder extends JavacAnnotationHandler<Builder> {
ListBuffer<JavacNode> allFields = new ListBuffer<JavacNode>();
@SuppressWarnings("deprecation")
boolean valuePresent = (hasAnnotation(lombok.Value.class, parent) || hasAnnotation(lombok.experimental.Value.class, parent));
- for (JavacNode fieldNode : HandleConstructor.findAllFields(tdParent)) {
+ for (JavacNode fieldNode : HandleConstructor.findAllFields(tdParent, true)) {
JCVariableDecl fd = (JCVariableDecl) fieldNode.get();
- // final fields with an initializer cannot be written to, so they can't be 'builderized'. Unfortunately presence of @Value makes
- // non-final fields final, but @Value's handler hasn't done this yet, so we have to do this math ourselves.
- // Value will only skip making a field final if it has an explicit @NonFinal annotation, so we check for that.
- if (fd.init != null && valuePresent && !hasAnnotation(NonFinal.class, fieldNode)) continue;
+ JavacNode isDefault = findAnnotation(Builder.Default.class, fieldNode, true);
+ boolean isFinal = (fd.mods.flags & Flags.FINAL) != 0 || (valuePresent && !hasAnnotation(NonFinal.class, fieldNode));
BuilderFieldData bfd = new BuilderFieldData();
bfd.rawName = fd.name;
bfd.name = removePrefixFromField(fieldNode);
bfd.type = fd.vartype;
bfd.singularData = getSingularData(fieldNode);
+ bfd.originalFieldNode = fieldNode;
+
+ if (bfd.singularData != null && isDefault != null) {
+ isDefault.addError("@Builder.Default and @Singular cannot be mixed.");
+ isDefault = null;
+ }
+
+ if (fd.init == null && isDefault != null) {
+ isDefault.addWarning("@Builder.Default requires an initializing expression (' = something;').");
+ isDefault = null;
+ }
+
+ if (fd.init != null && isDefault == null) {
+ if (isFinal) continue;
+ fieldNode.addWarning("@Builder will ignore the initializing expression entirely. If you want the initializing expression to serve as default, add @Builder.Default. If it is not supposed to be settable during building, make the field final.");
+ }
+
+ if (isDefault != null) {
+ bfd.nameOfDefaultProvider = parent.toName("$default$" + bfd.name);
+ bfd.nameOfSetFlag = parent.toName(bfd.name + "$set");
+ JCMethodDecl md = generateDefaultProvider(bfd.nameOfDefaultProvider, fieldNode);
+ recursiveSetGeneratedBy(md, ast, annotationNode.getContext());
+ if (md != null) injectMethod(tdParent, md);
+ }
addObtainVia(bfd, fieldNode);
builderFields.add(bfd);
allFields.append(fieldNode);
}
- new HandleConstructor().generateConstructor(tdParent, AccessLevel.PACKAGE, List.<JCAnnotation>nil(), allFields.toList(), false, null, SkipIfConstructorExists.I_AM_BUILDER, null, annotationNode);
+ new HandleConstructor().generateConstructor(tdParent, AccessLevel.PACKAGE, List.<JCAnnotation>nil(), allFields.toList(), false, null, SkipIfConstructorExists.I_AM_BUILDER, annotationNode);
returnType = namePlusTypeParamsToTypeReference(tdParent.getTreeMaker(), td.name, td.typarams);
typeParams = td.typarams;
@@ -290,6 +315,7 @@ public class HandleBuilder extends JavacAnnotationHandler<Builder> {
bfd.rawName = raw.name;
bfd.type = raw.vartype;
bfd.singularData = getSingularData(param);
+ bfd.originalFieldNode = param;
addObtainVia(bfd, param);
builderFields.add(bfd);
}
@@ -348,7 +374,7 @@ public class HandleBuilder extends JavacAnnotationHandler<Builder> {
}
if (constructorExists(builderType) == MemberExistsResult.NOT_EXISTS) {
- JCMethodDecl cd = HandleConstructor.createConstructor(AccessLevel.PACKAGE, List.<JCAnnotation>nil(), builderType, List.<JavacNode>nil(), false, null, annotationNode);
+ JCMethodDecl cd = HandleConstructor.createConstructor(AccessLevel.PACKAGE, List.<JCAnnotation>nil(), builderType, List.<JavacNode>nil(), false, annotationNode);
if (cd != null) injectMethod(builderType, cd);
}
@@ -357,7 +383,7 @@ public class HandleBuilder extends JavacAnnotationHandler<Builder> {
}
if (methodExists(buildMethodName, builderType, -1) == MemberExistsResult.NOT_EXISTS) {
- JCMethodDecl md = generateBuildMethod(isStatic, buildMethodName, nameOfBuilderMethod, returnType, builderFields, builderType, thrownExceptions, ast, addCleaning);
+ JCMethodDecl md = generateBuildMethod(tdParent, isStatic, buildMethodName, nameOfBuilderMethod, returnType, builderFields, builderType, thrownExceptions, ast, addCleaning);
if (md != null) injectMethod(builderType, md);
}
@@ -477,7 +503,7 @@ public class HandleBuilder extends JavacAnnotationHandler<Builder> {
}
}
- statements.append(maker.Exec(maker.Assign(maker.Select(maker.Ident(type.toName("this")), type.toName("$lombokUnclean")), maker.Literal(CTC_BOOLEAN, false))));
+ statements.append(maker.Exec(maker.Assign(maker.Select(maker.Ident(type.toName("this")), type.toName("$lombokUnclean")), maker.Literal(CTC_BOOLEAN, 0))));
JCBlock body = maker.Block(0, statements.toList());
return maker.MethodDef(maker.Modifiers(Flags.PUBLIC), type.toName("$lombokClean"), maker.Type(Javac.createVoidType(type.getSymbolTable(), CTC_VOID)), List.<JCTypeParameter>nil(), List.<JCVariableDecl>nil(), List.<JCExpression>nil(), body, null);
/*
@@ -494,7 +520,7 @@ public class HandleBuilder extends JavacAnnotationHandler<Builder> {
*/
}
- private JCMethodDecl generateBuildMethod(boolean isStatic, String buildName, Name builderName, JCExpression returnType, java.util.List<BuilderFieldData> builderFields, JavacNode type, List<JCExpression> thrownExceptions, JCTree source, boolean addCleaning) {
+ private JCMethodDecl generateBuildMethod(JavacNode tdParent, boolean isStatic, String buildName, Name builderName, JCExpression returnType, java.util.List<BuilderFieldData> builderFields, JavacNode type, List<JCExpression> thrownExceptions, JCTree source, boolean addCleaning) {
JavacTreeMaker maker = type.getTreeMaker();
JCExpression call;
@@ -515,25 +541,28 @@ public class HandleBuilder extends JavacAnnotationHandler<Builder> {
ListBuffer<JCExpression> args = new ListBuffer<JCExpression>();
for (BuilderFieldData bfd : builderFields) {
- args.append(maker.Ident(bfd.name));
+ if (bfd.nameOfSetFlag != null) {
+ args.append(maker.Conditional(maker.Ident(bfd.nameOfSetFlag), maker.Ident(bfd.name),
+ maker.Apply(List.<JCExpression>nil(), maker.Select(maker.Ident(((JCClassDecl) tdParent.get()).name), bfd.nameOfDefaultProvider), List.<JCExpression>nil())));
+ } else {
+ args.append(maker.Ident(bfd.name));
+ }
}
if (addCleaning) {
- statements.append(maker.Exec(maker.Assign(maker.Select(maker.Ident(type.toName("this")), type.toName("$lombokUnclean")), maker.Literal(CTC_BOOLEAN, true))));
+ statements.append(maker.Exec(maker.Assign(maker.Select(maker.Ident(type.toName("this")), type.toName("$lombokUnclean")), maker.Literal(CTC_BOOLEAN, 1))));
}
if (builderName == null) {
call = maker.NewClass(null, List.<JCExpression>nil(), returnType, args.toList(), null);
statements.append(maker.Return(call));
} else {
-
ListBuffer<JCExpression> typeParams = new ListBuffer<JCExpression>();
for (JCTypeParameter tp : ((JCClassDecl) type.get()).typarams) {
typeParams.append(maker.Ident(tp.name));
}
JCExpression callee = maker.Ident(((JCClassDecl) type.up().get()).name);
- if (!isStatic)
- callee = maker.Select(callee, type.up().toName("this"));
+ if (!isStatic) callee = maker.Select(callee, type.up().toName("this"));
JCExpression fn = maker.Select(callee, builderName);
call = maker.Apply(typeParams.toList(), fn, args.toList());
if (returnType instanceof JCPrimitiveTypeTree && CTC_VOID.equals(typeTag(returnType))) {
@@ -548,6 +577,18 @@ public class HandleBuilder extends JavacAnnotationHandler<Builder> {
return maker.MethodDef(maker.Modifiers(Flags.PUBLIC), type.toName(buildName), returnType, List.<JCTypeParameter>nil(), List.<JCVariableDecl>nil(), thrownExceptions, body, null);
}
+ public JCMethodDecl generateDefaultProvider(Name methodName, JavacNode fieldNode) {
+ JavacTreeMaker maker = fieldNode.getTreeMaker();
+ JCVariableDecl field = (JCVariableDecl) fieldNode.get();
+
+ JCStatement statement = maker.Return(field.init);
+ field.init = null;
+
+ JCBlock body = maker.Block(0, List.<JCStatement>of(statement));
+ int modifiers = Flags.PRIVATE | Flags.STATIC;
+ return maker.MethodDef(maker.Modifiers(modifiers), methodName, cloneType(maker, field.vartype, field, fieldNode.getContext()), List.<JCTypeParameter>nil(), List.<JCVariableDecl>nil(), List.<JCExpression>nil(), body, null);
+ }
+
public JCMethodDecl generateBuilderMethod(boolean isStatic, String builderMethodName, String builderClassName, JavacNode source, JavacNode type, List<JCTypeParameter> typeParams) {
JavacTreeMaker maker = type.getTreeMaker();
@@ -572,36 +613,43 @@ public class HandleBuilder extends JavacAnnotationHandler<Builder> {
if (child.getKind() == Kind.FIELD) existing.add(child);
}
- top:
for (int i = len - 1; i >= 0; i--) {
BuilderFieldData bfd = builderFields.get(i);
if (bfd.singularData != null && bfd.singularData.getSingularizer() != null) {
bfd.createdFields.addAll(bfd.singularData.getSingularizer().generateFields(bfd.singularData, builderType, source));
} else {
+ JavacNode field = null, setFlag = null;
for (JavacNode exists : existing) {
Name n = ((JCVariableDecl) exists.get()).name;
- if (n.equals(bfd.name)) {
- bfd.createdFields.add(exists);
- continue top;
- }
+ if (n.equals(bfd.name)) field = exists;
+ if (n.equals(bfd.nameOfSetFlag)) setFlag = exists;
}
JavacTreeMaker maker = builderType.getTreeMaker();
- JCModifiers mods = maker.Modifiers(Flags.PRIVATE);
- JCVariableDecl newField = maker.VarDef(mods, bfd.name, cloneType(maker, bfd.type, source, builderType.getContext()), null);
- bfd.createdFields.add(injectFieldAndMarkGenerated(builderType, newField));
+ if (field == null) {
+ JCModifiers mods = maker.Modifiers(Flags.PRIVATE);
+ JCVariableDecl newField = maker.VarDef(mods, bfd.name, cloneType(maker, bfd.type, source, builderType.getContext()), null);
+ field = injectFieldAndMarkGenerated(builderType, newField);
+ }
+ if (setFlag == null && bfd.nameOfSetFlag != null) {
+ JCModifiers mods = maker.Modifiers(Flags.PRIVATE);
+ JCVariableDecl newField = maker.VarDef(mods, bfd.nameOfSetFlag, maker.TypeIdent(CTC_BOOLEAN), null);
+ injectFieldAndMarkGenerated(builderType, newField);
+ }
+ bfd.createdFields.add(field);
}
}
}
public void makeSetterMethodsForBuilder(JavacNode builderType, BuilderFieldData fieldNode, JavacNode source, boolean fluent, boolean chain) {
+ boolean deprecate = isFieldDeprecated(fieldNode.originalFieldNode);
if (fieldNode.singularData == null || fieldNode.singularData.getSingularizer() == null) {
- makeSimpleSetterMethodForBuilder(builderType, fieldNode.createdFields.get(0), source, fluent, chain);
+ makeSimpleSetterMethodForBuilder(builderType, deprecate, fieldNode.createdFields.get(0), fieldNode.nameOfSetFlag, source, fluent, chain);
} else {
- fieldNode.singularData.getSingularizer().generateMethods(fieldNode.singularData, builderType, source.get(), fluent, chain);
+ fieldNode.singularData.getSingularizer().generateMethods(fieldNode.singularData, deprecate, builderType, source.get(), fluent, chain);
}
}
- private void makeSimpleSetterMethodForBuilder(JavacNode builderType, JavacNode fieldNode, JavacNode source, boolean fluent, boolean chain) {
+ private void makeSimpleSetterMethodForBuilder(JavacNode builderType, boolean deprecate, JavacNode fieldNode, Name nameOfSetFlag, JavacNode source, boolean fluent, boolean chain) {
Name fieldName = ((JCVariableDecl) fieldNode.get()).name;
for (JavacNode child : builderType.down()) {
@@ -614,7 +662,9 @@ public class HandleBuilder extends JavacAnnotationHandler<Builder> {
String setterName = fluent ? fieldNode.getName() : HandlerUtil.buildAccessorName("set", fieldNode.getName());
JavacTreeMaker maker = fieldNode.getTreeMaker();
- JCMethodDecl newMethod = HandleSetter.createSetter(Flags.PUBLIC, fieldNode, maker, setterName, chain, source, List.<JCAnnotation>nil(), List.<JCAnnotation>nil());
+
+ JCMethodDecl newMethod = HandleSetter.createSetter(Flags.PUBLIC, deprecate, fieldNode, maker, setterName, nameOfSetFlag, chain, source, List.<JCAnnotation>nil(), List.<JCAnnotation>nil());
+
injectMethod(builderType, newMethod);
}
diff --git a/src/core/lombok/javac/handlers/HandleBuilderDefault.java b/src/core/lombok/javac/handlers/HandleBuilderDefault.java
new file mode 100644
index 00000000..733aea5a
--- /dev/null
+++ b/src/core/lombok/javac/handlers/HandleBuilderDefault.java
@@ -0,0 +1,29 @@
+package lombok.javac.handlers;
+
+import static lombok.javac.handlers.JavacHandlerUtil.*;
+
+import org.mangosdk.spi.ProviderFor;
+
+import com.sun.tools.javac.tree.JCTree.JCAnnotation;
+
+import lombok.Builder;
+import lombok.core.AST.Kind;
+import lombok.core.AnnotationValues;
+import lombok.core.HandlerPriority;
+import lombok.javac.JavacAnnotationHandler;
+import lombok.javac.JavacNode;
+
+@ProviderFor(JavacAnnotationHandler.class)
+@HandlerPriority(-1025) //HandleBuilder's level, minus one.
+public class HandleBuilderDefault extends JavacAnnotationHandler<Builder.Default> {
+ @SuppressWarnings("deprecation")
+ @Override public void handle(AnnotationValues<Builder.Default> annotation, JCAnnotation ast, JavacNode annotationNode) {
+ JavacNode annotatedField = annotationNode.up();
+ if (annotatedField.getKind() != Kind.FIELD) return;
+ JavacNode classWithAnnotatedField = annotatedField.up();
+ if (!hasAnnotation(Builder.class, classWithAnnotatedField) && !hasAnnotation(lombok.experimental.Builder.class, classWithAnnotatedField)) {
+ annotationNode.addWarning("@Builder.Default requires @Builder on the class for it to mean anything.");
+ deleteAnnotationIfNeccessary(annotationNode, Builder.Default.class);
+ }
+ }
+}
diff --git a/src/core/lombok/javac/handlers/HandleConstructor.java b/src/core/lombok/javac/handlers/HandleConstructor.java
index ef4ba088..929de3cd 100644
--- a/src/core/lombok/javac/handlers/HandleConstructor.java
+++ b/src/core/lombok/javac/handlers/HandleConstructor.java
@@ -71,14 +71,14 @@ public class HandleConstructor {
deleteImportFromCompilationUnit(annotationNode, "lombok.AccessLevel");
JavacNode typeNode = annotationNode.up();
if (!checkLegality(typeNode, annotationNode, NoArgsConstructor.class.getSimpleName())) return;
- List<JCAnnotation> onConstructor = unboxAndRemoveAnnotationParameter(ast, "onConstructor", "@NoArgsConstructor(onConstructor=", annotationNode);
+ List<JCAnnotation> onConstructor = unboxAndRemoveAnnotationParameter(ast, "onConstructor", "@NoArgsConstructor(onConstructor", annotationNode);
NoArgsConstructor ann = annotation.getInstance();
AccessLevel level = ann.access();
if (level == AccessLevel.NONE) return;
String staticName = ann.staticName();
boolean force = ann.force();
List<JavacNode> fields = force ? findFinalFields(typeNode) : List.<JavacNode>nil();
- new HandleConstructor().generateConstructor(typeNode, level, onConstructor, fields, force, staticName, SkipIfConstructorExists.NO, null, annotationNode);
+ new HandleConstructor().generateConstructor(typeNode, level, onConstructor, fields, force, staticName, SkipIfConstructorExists.NO, annotationNode);
}
}
@@ -91,19 +91,16 @@ public class HandleConstructor {
deleteImportFromCompilationUnit(annotationNode, "lombok.AccessLevel");
JavacNode typeNode = annotationNode.up();
if (!checkLegality(typeNode, annotationNode, RequiredArgsConstructor.class.getSimpleName())) return;
- List<JCAnnotation> onConstructor = unboxAndRemoveAnnotationParameter(ast, "onConstructor", "@RequiredArgsConstructor(onConstructor=", annotationNode);
+ List<JCAnnotation> onConstructor = unboxAndRemoveAnnotationParameter(ast, "onConstructor", "@RequiredArgsConstructor(onConstructor", annotationNode);
RequiredArgsConstructor ann = annotation.getInstance();
AccessLevel level = ann.access();
if (level == AccessLevel.NONE) return;
String staticName = ann.staticName();
- Boolean suppressConstructorProperties = null;
if (annotation.isExplicit("suppressConstructorProperties")) {
- @SuppressWarnings("deprecation")
- boolean suppress = ann.suppressConstructorProperties();
- suppressConstructorProperties = suppress;
+ annotationNode.addError("This deprecated feature is no longer supported. Remove it; you can create a lombok.config file with 'lombok.anyConstructor.suppressConstructorProperties = true'.");
}
- new HandleConstructor().generateConstructor(typeNode, level, onConstructor, findRequiredFields(typeNode), false, staticName, SkipIfConstructorExists.NO, suppressConstructorProperties, annotationNode);
+ new HandleConstructor().generateConstructor(typeNode, level, onConstructor, findRequiredFields(typeNode), false, staticName, SkipIfConstructorExists.NO, annotationNode);
}
}
@@ -141,22 +138,23 @@ public class HandleConstructor {
deleteImportFromCompilationUnit(annotationNode, "lombok.AccessLevel");
JavacNode typeNode = annotationNode.up();
if (!checkLegality(typeNode, annotationNode, AllArgsConstructor.class.getSimpleName())) return;
- List<JCAnnotation> onConstructor = unboxAndRemoveAnnotationParameter(ast, "onConstructor", "@AllArgsConstructor(onConstructor=", annotationNode);
+ List<JCAnnotation> onConstructor = unboxAndRemoveAnnotationParameter(ast, "onConstructor", "@AllArgsConstructor(onConstructor", annotationNode);
AllArgsConstructor ann = annotation.getInstance();
AccessLevel level = ann.access();
if (level == AccessLevel.NONE) return;
String staticName = ann.staticName();
- Boolean suppressConstructorProperties = null;
if (annotation.isExplicit("suppressConstructorProperties")) {
- @SuppressWarnings("deprecation")
- boolean suppress = ann.suppressConstructorProperties();
- suppressConstructorProperties = suppress;
+ annotationNode.addError("This deprecated feature is no longer supported. Remove it; you can create a lombok.config file with 'lombok.anyConstructor.suppressConstructorProperties = true'.");
}
- new HandleConstructor().generateConstructor(typeNode, level, onConstructor, findAllFields(typeNode), false, staticName, SkipIfConstructorExists.NO, suppressConstructorProperties, annotationNode);
+ new HandleConstructor().generateConstructor(typeNode, level, onConstructor, findAllFields(typeNode), false, staticName, SkipIfConstructorExists.NO, annotationNode);
}
}
public static List<JavacNode> findAllFields(JavacNode typeNode) {
+ return findAllFields(typeNode, false);
+ }
+
+ public static List<JavacNode> findAllFields(JavacNode typeNode, boolean evenFinalInitialized) {
ListBuffer<JavacNode> fields = new ListBuffer<JavacNode>();
for (JavacNode child : typeNode.down()) {
if (child.getKind() != Kind.FIELD) continue;
@@ -168,7 +166,7 @@ public class HandleConstructor {
if ((fieldFlags & Flags.STATIC) != 0) continue;
//Skip initialized final fields
boolean isFinal = (fieldFlags & Flags.FINAL) != 0;
- if (!isFinal || fieldDecl.init == null) fields.append(child);
+ if (evenFinalInitialized || !isFinal || fieldDecl.init == null) fields.append(child);
}
return fields.toList();
}
@@ -188,7 +186,7 @@ public class HandleConstructor {
}
public void generateRequiredArgsConstructor(JavacNode typeNode, AccessLevel level, String staticName, SkipIfConstructorExists skipIfConstructorExists, JavacNode source) {
- generateConstructor(typeNode, level, List.<JCAnnotation>nil(), findRequiredFields(typeNode), false, staticName, skipIfConstructorExists, null, source);
+ generateConstructor(typeNode, level, List.<JCAnnotation>nil(), findRequiredFields(typeNode), false, staticName, skipIfConstructorExists, source);
}
public enum SkipIfConstructorExists {
@@ -196,10 +194,10 @@ public class HandleConstructor {
}
public void generateAllArgsConstructor(JavacNode typeNode, AccessLevel level, String staticName, SkipIfConstructorExists skipIfConstructorExists, JavacNode source) {
- generateConstructor(typeNode, level, List.<JCAnnotation>nil(), findAllFields(typeNode), false, staticName, skipIfConstructorExists, null, 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, Boolean suppressConstructorProperties, JavacNode source) {
+ public void generateConstructor(JavacNode typeNode, AccessLevel level, List<JCAnnotation> onConstructor, List<JavacNode> fields, boolean allToDefault, String staticName, SkipIfConstructorExists skipIfConstructorExists, JavacNode source) {
boolean staticConstrRequired = staticName != null && !staticName.equals("");
if (skipIfConstructorExists != SkipIfConstructorExists.NO && constructorExists(typeNode) != MemberExistsResult.NOT_EXISTS) return;
@@ -228,7 +226,7 @@ public class HandleConstructor {
}
}
- JCMethodDecl constr = createConstructor(staticConstrRequired ? AccessLevel.PRIVATE : level, onConstructor, typeNode, fields, allToDefault, suppressConstructorProperties, source);
+ JCMethodDecl constr = createConstructor(staticConstrRequired ? AccessLevel.PRIVATE : level, onConstructor, typeNode, fields, allToDefault, source);
ListBuffer<Type> argTypes = new ListBuffer<Type>();
for (JavacNode fieldNode : fields) {
Type mirror = getMirrorForFieldType(fieldNode);
@@ -262,18 +260,18 @@ public class HandleConstructor {
mods.annotations = mods.annotations.append(annotation);
}
- public static JCMethodDecl createConstructor(AccessLevel level, List<JCAnnotation> onConstructor, JavacNode typeNode, List<JavacNode> fields, boolean allToDefault, Boolean suppressConstructorProperties, JavacNode source) {
+ public static JCMethodDecl createConstructor(AccessLevel level, List<JCAnnotation> onConstructor, JavacNode typeNode, List<JavacNode> fields, boolean allToDefault, JavacNode source) {
JavacTreeMaker maker = typeNode.getTreeMaker();
boolean isEnum = (((JCClassDecl) typeNode.get()).mods.flags & Flags.ENUM) != 0;
if (isEnum) level = AccessLevel.PRIVATE;
- if (suppressConstructorProperties == null) {
- if (fields.isEmpty()) {
- suppressConstructorProperties = false;
- } else {
- suppressConstructorProperties = Boolean.TRUE.equals(typeNode.getAst().readConfiguration(ConfigurationKeys.ANY_CONSTRUCTOR_SUPPRESS_CONSTRUCTOR_PROPERTIES));
- }
+ boolean suppressConstructorProperties;
+
+ if (fields.isEmpty()) {
+ suppressConstructorProperties = false;
+ } else {
+ suppressConstructorProperties = Boolean.TRUE.equals(typeNode.getAst().readConfiguration(ConfigurationKeys.ANY_CONSTRUCTOR_SUPPRESS_CONSTRUCTOR_PROPERTIES));
}
ListBuffer<JCStatement> nullChecks = new ListBuffer<JCStatement>();
@@ -291,7 +289,7 @@ public class HandleConstructor {
JCVariableDecl param = maker.VarDef(maker.Modifiers(flags, nonNulls.appendList(nullables)), fieldName, field.vartype, null);
params.append(param);
if (!nonNulls.isEmpty()) {
- JCStatement nullCheck = generateNullCheck(maker, fieldNode, source);
+ JCStatement nullCheck = generateNullCheck(maker, fieldNode, param, source);
if (nullCheck != null) nullChecks.append(nullCheck);
}
}
@@ -301,7 +299,7 @@ public class HandleConstructor {
}
JCModifiers mods = maker.Modifiers(toJavacModifier(level), List.<JCAnnotation>nil());
- if (!allToDefault && !suppressConstructorProperties && level != AccessLevel.PRIVATE && level != AccessLevel.PACKAGE && !isLocalType(typeNode) && LombokOptionsFactory.getDelombokOptions(typeNode.getContext()).getFormatPreferences().generateConstructorProperties()) {
+ if (!allToDefault && !suppressConstructorProperties && !isLocalType(typeNode) && LombokOptionsFactory.getDelombokOptions(typeNode.getContext()).getFormatPreferences().generateConstructorProperties()) {
addConstructorProperties(mods, typeNode, fields);
}
if (onConstructor != null) mods.annotations = mods.annotations.appendList(copyAnnotations(onConstructor));
diff --git a/src/core/lombok/javac/handlers/HandleEqualsAndHashCode.java b/src/core/lombok/javac/handlers/HandleEqualsAndHashCode.java
index 8e868bca..4bd1ce4b 100644
--- a/src/core/lombok/javac/handlers/HandleEqualsAndHashCode.java
+++ b/src/core/lombok/javac/handlers/HandleEqualsAndHashCode.java
@@ -95,7 +95,7 @@ public class HandleEqualsAndHashCode extends JavacAnnotationHandler<EqualsAndHas
List<String> excludes = List.from(ann.exclude());
List<String> includes = List.from(ann.of());
JavacNode typeNode = annotationNode.up();
- List<JCAnnotation> onParam = unboxAndRemoveAnnotationParameter(ast, "onParam", "@EqualsAndHashCode(onParam=", annotationNode);
+ List<JCAnnotation> onParam = unboxAndRemoveAnnotationParameter(ast, "onParam", "@EqualsAndHashCode(onParam", annotationNode);
checkForBogusFieldNames(typeNode, annotation);
Boolean callSuper = ann.callSuper();
@@ -121,7 +121,10 @@ public class HandleEqualsAndHashCode extends JavacAnnotationHandler<EqualsAndHas
return;
}
- generateMethods(typeNode, source, null, null, null, false, FieldAccess.GETTER, List.<JCAnnotation>nil());
+ Boolean doNotUseGettersConfiguration = typeNode.getAst().readConfiguration(ConfigurationKeys.EQUALS_AND_HASH_CODE_DO_NOT_USE_GETTERS);
+ FieldAccess access = doNotUseGettersConfiguration == null || !doNotUseGettersConfiguration ? FieldAccess.GETTER : FieldAccess.PREFER_FIELD;
+
+ generateMethods(typeNode, source, null, null, null, false, access, List.<JCAnnotation>nil());
}
public void generateMethods(JavacNode typeNode, JavacNode source, List<String> excludes, List<String> includes,
diff --git a/src/core/lombok/javac/handlers/HandleGetter.java b/src/core/lombok/javac/handlers/HandleGetter.java
index 60dbe8ee..5a2e1993 100644
--- a/src/core/lombok/javac/handlers/HandleGetter.java
+++ b/src/core/lombok/javac/handlers/HandleGetter.java
@@ -147,7 +147,7 @@ public class HandleGetter extends JavacAnnotationHandler<Getter> {
if (node == null) return;
- List<JCAnnotation> onMethod = unboxAndRemoveAnnotationParameter(ast, "onMethod", "@Getter(onMethod=", annotationNode);
+ List<JCAnnotation> onMethod = unboxAndRemoveAnnotationParameter(ast, "onMethod", "@Getter(onMethod", annotationNode);
switch (node.getKind()) {
case FIELD:
diff --git a/src/core/lombok/javac/handlers/HandleSetter.java b/src/core/lombok/javac/handlers/HandleSetter.java
index 02cc3775..1453aa27 100644
--- a/src/core/lombok/javac/handlers/HandleSetter.java
+++ b/src/core/lombok/javac/handlers/HandleSetter.java
@@ -129,8 +129,8 @@ public class HandleSetter extends JavacAnnotationHandler<Setter> {
if (level == AccessLevel.NONE || node == null) return;
- List<JCAnnotation> onMethod = unboxAndRemoveAnnotationParameter(ast, "onMethod", "@Setter(onMethod=", annotationNode);
- List<JCAnnotation> onParam = unboxAndRemoveAnnotationParameter(ast, "onParam", "@Setter(onParam=", annotationNode);
+ List<JCAnnotation> onMethod = unboxAndRemoveAnnotationParameter(ast, "onMethod", "@Setter(onMethod", annotationNode);
+ List<JCAnnotation> onParam = unboxAndRemoveAnnotationParameter(ast, "onParam", "@Setter(onParam", annotationNode);
switch (node.getKind()) {
case FIELD:
@@ -206,10 +206,10 @@ public class HandleSetter extends JavacAnnotationHandler<Setter> {
public static JCMethodDecl createSetter(long access, JavacNode field, JavacTreeMaker treeMaker, JavacNode source, List<JCAnnotation> onMethod, List<JCAnnotation> onParam) {
String setterName = toSetterName(field);
boolean returnThis = shouldReturnThis(field);
- return createSetter(access, field, treeMaker, setterName, returnThis, source, onMethod, onParam);
+ return createSetter(access, false, field, treeMaker, setterName, null, returnThis, source, onMethod, onParam);
}
- public static JCMethodDecl createSetter(long access, JavacNode field, JavacTreeMaker treeMaker, String setterName, boolean shouldReturnThis, JavacNode source, List<JCAnnotation> onMethod, List<JCAnnotation> onParam) {
+ public static JCMethodDecl createSetter(long access, boolean deprecate, JavacNode field, JavacTreeMaker treeMaker, String setterName, Name booleanFieldToSet, boolean shouldReturnThis, JavacNode source, List<JCAnnotation> onMethod, List<JCAnnotation> onParam) {
if (setterName == null) return null;
JCVariableDecl fieldDecl = (JCVariableDecl) field.get();
@@ -235,6 +235,11 @@ public class HandleSetter extends JavacAnnotationHandler<Setter> {
statements.append(treeMaker.Exec(assign));
}
+ if (booleanFieldToSet != null) {
+ JCAssign setBool = treeMaker.Assign(treeMaker.Ident(booleanFieldToSet), treeMaker.Literal(CTC_BOOLEAN, 1));
+ statements.append(treeMaker.Exec(setBool));
+ }
+
JCExpression methodType = null;
if (shouldReturnThis) {
methodType = cloneSelfType(field);
@@ -258,7 +263,7 @@ public class HandleSetter extends JavacAnnotationHandler<Setter> {
JCExpression annotationMethodDefaultValue = null;
List<JCAnnotation> annsOnMethod = copyAnnotations(onMethod);
- if (isFieldDeprecated(field)) {
+ if (isFieldDeprecated(field) || deprecate) {
annsOnMethod = annsOnMethod.prepend(treeMaker.Annotation(genJavaLangTypeRef(field, "Deprecated"), List.<JCExpression>nil()));
}
diff --git a/src/core/lombok/javac/handlers/HandleToString.java b/src/core/lombok/javac/handlers/HandleToString.java
index 743e7b26..897d5f2c 100644
--- a/src/core/lombok/javac/handlers/HandleToString.java
+++ b/src/core/lombok/javac/handlers/HandleToString.java
@@ -117,7 +117,11 @@ public class HandleToString extends JavacAnnotationHandler<ToString> {
Boolean configuration = typeNode.getAst().readConfiguration(ConfigurationKeys.TO_STRING_INCLUDE_FIELD_NAMES);
includeFieldNames = configuration != null ? configuration : ((Boolean)ToString.class.getMethod("includeFieldNames").getDefaultValue()).booleanValue();
} catch (Exception ignore) {}
- generateToString(typeNode, errorNode, null, null, includeFieldNames, null, false, FieldAccess.GETTER);
+
+ Boolean doNotUseGettersConfiguration = typeNode.getAst().readConfiguration(ConfigurationKeys.TO_STRING_DO_NOT_USE_GETTERS);
+ FieldAccess access = doNotUseGettersConfiguration == null || !doNotUseGettersConfiguration ? FieldAccess.GETTER : FieldAccess.PREFER_FIELD;
+
+ generateToString(typeNode, errorNode, null, null, includeFieldNames, null, false, access);
}
public void generateToString(JavacNode typeNode, JavacNode source, List<String> excludes, List<String> includes,
diff --git a/src/core/lombok/javac/handlers/HandleWither.java b/src/core/lombok/javac/handlers/HandleWither.java
index 8aec0240..987a3d34 100644
--- a/src/core/lombok/javac/handlers/HandleWither.java
+++ b/src/core/lombok/javac/handlers/HandleWither.java
@@ -131,8 +131,8 @@ public class HandleWither extends JavacAnnotationHandler<Wither> {
if (level == AccessLevel.NONE || node == null) return;
- List<JCAnnotation> onMethod = unboxAndRemoveAnnotationParameter(ast, "onMethod", "@Wither(onMethod=", annotationNode);
- List<JCAnnotation> onParam = unboxAndRemoveAnnotationParameter(ast, "onParam", "@Wither(onParam=", annotationNode);
+ List<JCAnnotation> onMethod = unboxAndRemoveAnnotationParameter(ast, "onMethod", "@Wither(onMethod", annotationNode);
+ List<JCAnnotation> onParam = unboxAndRemoveAnnotationParameter(ast, "onParam", "@Wither(onParam", annotationNode);
switch (node.getKind()) {
case FIELD:
diff --git a/src/core/lombok/javac/handlers/JavacHandlerUtil.java b/src/core/lombok/javac/handlers/JavacHandlerUtil.java
index 27289108..23206b43 100644
--- a/src/core/lombok/javac/handlers/JavacHandlerUtil.java
+++ b/src/core/lombok/javac/handlers/JavacHandlerUtil.java
@@ -191,6 +191,27 @@ public class JavacHandlerUtil {
}
}
+ static JavacNode findAnnotation(Class<? extends Annotation> type, JavacNode node, boolean delete) {
+ if (node == null) return null;
+ if (type == null) return null;
+ switch (node.getKind()) {
+ case ARGUMENT:
+ case FIELD:
+ case LOCAL:
+ case TYPE:
+ case METHOD:
+ for (JavacNode child : node.down()) {
+ if (annotationTypeMatches(type, child)) {
+ if (delete) deleteAnnotationIfNeccessary(child, type);
+ return child;
+ }
+ }
+ // intentional fallthrough
+ default:
+ return null;
+ }
+ }
+
/**
* Checks if the Annotation AST Node provided is likely to be an instance of the provided annotation type.
*
@@ -222,6 +243,7 @@ public class JavacHandlerUtil {
* @return {@code true} if a field is marked deprecated, either by {@code @Deprecated} or in javadoc, otherwise {@code false}
*/
public static boolean isFieldDeprecated(JavacNode field) {
+ if (!(field.get() instanceof JCVariableDecl)) return false;
JCVariableDecl fieldNode = (JCVariableDecl) field.get();
if ((fieldNode.mods.flags & Flags.DEPRECATED) != 0) {
return true;
@@ -1189,16 +1211,25 @@ public class JavacHandlerUtil {
}
/**
- * Generates a new statement that checks if the given variable is null, and if so, throws a specified exception with the
+ * Generates a new statement that checks if the given variable is null, and if so, throws a configured exception with the
* variable name as message.
- *
- * @param exName The name of the exception to throw; normally {@code java.lang.NullPointerException}.
*/
public static JCStatement generateNullCheck(JavacTreeMaker maker, JavacNode variable, JavacNode source) {
+ return generateNullCheck(maker, variable, (JCVariableDecl)variable.get(), source);
+ }
+
+ /**
+ * Generates a new statement that checks if the given variable is null, and if so, throws a configured exception with the
+ * variable name as message.
+ *
+ * This is a special case method reserved for use when the provided declaration differs from the
+ * variable's declaration, i.e. in a constructor or setter where the local parameter is named the same but with the prefix
+ * stripped as a result of @Accessors.prefix.
+ */
+ public static JCStatement generateNullCheck(JavacTreeMaker maker, JavacNode variable, JCVariableDecl varDecl, JavacNode source) {
NullCheckExceptionType exceptionType = source.getAst().readConfiguration(ConfigurationKeys.NON_NULL_EXCEPTION_TYPE);
if (exceptionType == null) exceptionType = NullCheckExceptionType.NULL_POINTER_EXCEPTION;
- JCVariableDecl varDecl = (JCVariableDecl) variable.get();
if (isPrimitive(varDecl.vartype)) return null;
Name fieldName = varDecl.name;
JCExpression exType = genTypeRef(variable, exceptionType.getExceptionType());
@@ -1240,19 +1271,9 @@ public class JavacHandlerUtil {
ListBuffer<JCExpression> params = new ListBuffer<JCExpression>();
ListBuffer<JCAnnotation> result = new ListBuffer<JCAnnotation>();
- try {
- for (JCExpression arg : ast.args) {
- String argName = "value";
- if (arg instanceof JCAssign) {
- JCAssign as = (JCAssign) arg;
- argName = as.lhs.toString();
- }
- if (!argName.equals(parameterName)) continue;
- }
- } catch (Exception ignore) {}
-
outer:
for (JCExpression param : ast.args) {
+ boolean allowRaw;
String nameOfParam = "value";
JCExpression valueOfParam = null;
if (param instanceof JCAssign) {
@@ -1264,6 +1285,15 @@ public class JavacHandlerUtil {
valueOfParam = assign.rhs;
}
+ /* strip trailing underscores */ {
+ int lastIdx;
+ for (lastIdx = nameOfParam.length() ; lastIdx > 0; lastIdx--) {
+ if (nameOfParam.charAt(lastIdx - 1) != '_') break;
+ }
+ allowRaw = lastIdx < nameOfParam.length();
+ nameOfParam = nameOfParam.substring(0, lastIdx);
+ }
+
if (!parameterName.equals(nameOfParam)) {
params.append(param);
continue outer;
@@ -1276,48 +1306,68 @@ public class JavacHandlerUtil {
String dummyAnnotationName = ((JCAnnotation) valueOfParam).annotationType.toString();
dummyAnnotationName = dummyAnnotationName.replace("_", "").replace("$", "").replace("x", "").replace("X", "");
if (dummyAnnotationName.length() > 0) {
- annotationNode.addError("The correct format is " + errorName + "@__({@SomeAnnotation, @SomeOtherAnnotation}))");
- continue outer;
- }
- for (JCExpression expr : ((JCAnnotation) valueOfParam).args) {
- if (expr instanceof JCAssign && ((JCAssign) expr).lhs instanceof JCIdent) {
- JCIdent id = (JCIdent) ((JCAssign) expr).lhs;
- if ("value".equals(id.name.toString())) {
- expr = ((JCAssign) expr).rhs;
- } else {
- annotationNode.addError("The correct format is " + errorName + "@__({@SomeAnnotation, @SomeOtherAnnotation}))");
- continue outer;
- }
+ if (allowRaw) {
+ result.append((JCAnnotation) valueOfParam);
+ } else {
+ addError(errorName, annotationNode);
+ continue outer;
}
-
- if (expr instanceof JCAnnotation) {
- result.append((JCAnnotation) expr);
- } else if (expr instanceof JCNewArray) {
- for (JCExpression expr2 : ((JCNewArray) expr).elems) {
- if (expr2 instanceof JCAnnotation) {
- result.append((JCAnnotation) expr2);
+ } else {
+ for (JCExpression expr : ((JCAnnotation) valueOfParam).args) {
+ if (expr instanceof JCAssign && ((JCAssign) expr).lhs instanceof JCIdent) {
+ JCIdent id = (JCIdent) ((JCAssign) expr).lhs;
+ if ("value".equals(id.name.toString())) {
+ expr = ((JCAssign) expr).rhs;
} else {
- annotationNode.addError("The correct format is " + errorName + "@__({@SomeAnnotation, @SomeOtherAnnotation}))");
- continue outer;
+ addError(errorName, annotationNode);
}
}
- } else {
- annotationNode.addError("The correct format is " + errorName + "@__({@SomeAnnotation, @SomeOtherAnnotation}))");
- continue outer;
+
+ if (expr instanceof JCAnnotation) {
+ result.append((JCAnnotation) expr);
+ } else if (expr instanceof JCNewArray) {
+ for (JCExpression expr2 : ((JCNewArray) expr).elems) {
+ if (expr2 instanceof JCAnnotation) {
+ result.append((JCAnnotation) expr2);
+ } else {
+ addError(errorName, annotationNode);
+ continue outer;
+ }
+ }
+ } else {
+ addError(errorName, annotationNode);
+ continue outer;
+ }
}
}
- } else {
- if (valueOfParam instanceof JCNewArray && ((JCNewArray) valueOfParam).elems.isEmpty()) {
- // Then we just remove it and move on (it's onMethod={} for example).
+ } else if (valueOfParam instanceof JCNewArray) {
+ JCNewArray arr = (JCNewArray) valueOfParam;
+ if (arr.elems.isEmpty()) {
+ // Just remove it, this is always fine.
+ } else if (allowRaw) {
+ for (JCExpression jce : arr.elems) {
+ if (jce instanceof JCAnnotation) result.append((JCAnnotation) jce);
+ else addError(errorName, annotationNode);
+ }
} else {
- annotationNode.addError("The correct format is " + errorName + "@__({@SomeAnnotation, @SomeOtherAnnotation}))");
+ addError(errorName, annotationNode);
}
+ } else {
+ addError(errorName, annotationNode);
}
}
ast.args = params.toList();
return result.toList();
}
+ private static void addError(String errorName, JavacNode node) {
+ if (node.getLatestJavaSpecSupported() < 8) {
+ node.addError("The correct format up to JDK7 is " + errorName + "=@__({@SomeAnnotation, @SomeOtherAnnotation}))");
+ } else {
+ node.addError("The correct format for JDK8+ is " + errorName + "_={@SomeAnnotation, @SomeOtherAnnotation})");
+ }
+ }
+
public static List<JCTypeParameter> copyTypeParams(JavacNode source, List<JCTypeParameter> params) {
if (params == null || params.isEmpty()) return params;
ListBuffer<JCTypeParameter> out = new ListBuffer<JCTypeParameter>();
diff --git a/src/core/lombok/javac/handlers/JavacSingularsRecipes.java b/src/core/lombok/javac/handlers/JavacSingularsRecipes.java
index c6d601bd..6a76e1dd 100644
--- a/src/core/lombok/javac/handlers/JavacSingularsRecipes.java
+++ b/src/core/lombok/javac/handlers/JavacSingularsRecipes.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2015 The Project Lombok Authors.
+ * Copyright (C) 2015-2017 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
@@ -38,9 +38,12 @@ import lombok.javac.JavacTreeMaker;
import com.sun.source.tree.Tree.Kind;
import com.sun.tools.javac.code.BoundKind;
+import com.sun.tools.javac.code.Flags;
import com.sun.tools.javac.tree.JCTree;
+import com.sun.tools.javac.tree.JCTree.JCAnnotation;
import com.sun.tools.javac.tree.JCTree.JCExpression;
import com.sun.tools.javac.tree.JCTree.JCMethodDecl;
+import com.sun.tools.javac.tree.JCTree.JCModifiers;
import com.sun.tools.javac.tree.JCTree.JCStatement;
import com.sun.tools.javac.tree.JCTree.JCVariableDecl;
import com.sun.tools.javac.tree.JCTree.JCWildcard;
@@ -141,6 +144,11 @@ public class JavacSingularsRecipes {
public static abstract class JavacSingularizer {
public abstract LombokImmutableList<String> getSupportedTypes();
+ protected JCModifiers makeMods(JavacTreeMaker maker, JavacNode node, boolean deprecate) {
+ if (deprecate) return maker.Modifiers(Flags.PUBLIC, List.<JCAnnotation>of(maker.Annotation(genJavaLangTypeRef(node, "Deprecated"), List.<JCExpression>nil())));
+ return maker.Modifiers(Flags.PUBLIC);
+ }
+
/** Checks if any of the to-be-generated nodes (fields, methods) already exist. If so, errors on these (singulars don't support manually writing some of it, and returns true). */
public boolean checkForAlreadyExistingNodesAndGenerateError(JavacNode builderType, SingularData data) {
for (JavacNode child : builderType.down()) {
@@ -186,7 +194,7 @@ public class JavacSingularsRecipes {
}
public abstract java.util.List<JavacNode> generateFields(SingularData data, JavacNode builderType, JCTree source);
- public abstract void generateMethods(SingularData data, JavacNode builderType, JCTree source, boolean fluent, boolean chain);
+ public abstract void generateMethods(SingularData data, boolean deprecate, JavacNode builderType, JCTree source, boolean fluent, boolean chain);
public abstract void appendBuildCode(SingularData data, JavacNode builderType, JCTree source, ListBuffer<JCStatement> statements, Name targetVariableName);
public boolean requiresCleaning() {
diff --git a/src/core/lombok/javac/handlers/singulars/JavacGuavaSingularizer.java b/src/core/lombok/javac/handlers/singulars/JavacGuavaSingularizer.java
index fba4c80e..0ab7da54 100644
--- a/src/core/lombok/javac/handlers/singulars/JavacGuavaSingularizer.java
+++ b/src/core/lombok/javac/handlers/singulars/JavacGuavaSingularizer.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2015 The Project Lombok Authors.
+ * Copyright (C) 2015-2017 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
@@ -70,24 +70,24 @@ abstract class JavacGuavaSingularizer extends JavacSingularizer {
return Collections.singletonList(injectFieldAndMarkGenerated(builderType, buildField));
}
- @Override public void generateMethods(SingularData data, JavacNode builderType, JCTree source, boolean fluent, boolean chain) {
+ @Override public void generateMethods(SingularData data, boolean deprecate, JavacNode builderType, JCTree source, boolean fluent, boolean chain) {
JavacTreeMaker maker = builderType.getTreeMaker();
Symtab symbolTable = builderType.getSymbolTable();
JCExpression returnType = chain ? cloneSelfType(builderType) : maker.Type(createVoidType(symbolTable, CTC_VOID));
JCStatement returnStatement = chain ? maker.Return(maker.Ident(builderType.toName("this"))) : null;
- generateSingularMethod(maker, returnType, returnStatement, data, builderType, source, fluent);
+ generateSingularMethod(deprecate, maker, returnType, returnStatement, data, builderType, source, fluent);
returnType = chain ? cloneSelfType(builderType) : maker.Type(createVoidType(symbolTable, CTC_VOID));
returnStatement = chain ? maker.Return(maker.Ident(builderType.toName("this"))) : null;
- generatePluralMethod(maker, returnType, returnStatement, data, builderType, source, fluent);
+ generatePluralMethod(deprecate, maker, returnType, returnStatement, data, builderType, source, fluent);
returnType = chain ? cloneSelfType(builderType) : maker.Type(createVoidType(symbolTable, CTC_VOID));
returnStatement = chain ? maker.Return(maker.Ident(builderType.toName("this"))) : null;
- generateClearMethod(maker, returnType, returnStatement, data, builderType, source);
+ generateClearMethod(deprecate, maker, returnType, returnStatement, data, builderType, source);
}
- private void generateClearMethod(JavacTreeMaker maker, JCExpression returnType, JCStatement returnStatement, SingularData data, JavacNode builderType, JCTree source) {
- JCModifiers mods = maker.Modifiers(Flags.PUBLIC);
+ private void generateClearMethod(boolean deprecate, JavacTreeMaker maker, JCExpression returnType, JCStatement returnStatement, SingularData data, JavacNode builderType, JCTree source) {
+ JCModifiers mods = makeMods(maker, builderType, deprecate);
List<JCTypeParameter> typeParams = List.nil();
List<JCExpression> thrown = List.nil();
List<JCVariableDecl> params = List.nil();
@@ -102,7 +102,7 @@ abstract class JavacGuavaSingularizer extends JavacSingularizer {
injectMethod(builderType, method);
}
- void generateSingularMethod(JavacTreeMaker maker, JCExpression returnType, JCStatement returnStatement, SingularData data, JavacNode builderType, JCTree source, boolean fluent) {
+ void generateSingularMethod(boolean deprecate, JavacTreeMaker maker, JCExpression returnType, JCStatement returnStatement, SingularData data, JavacNode builderType, JCTree source, boolean fluent) {
List<JCTypeParameter> typeParams = List.nil();
List<JCExpression> thrown = List.nil();
@@ -114,7 +114,7 @@ abstract class JavacGuavaSingularizer extends JavacSingularizer {
names[i] = s.isEmpty() ? n : builderType.toName(s);
}
- JCModifiers mods = maker.Modifiers(Flags.PUBLIC);
+ JCModifiers mods = makeMods(maker, builderType, deprecate);
ListBuffer<JCStatement> statements = new ListBuffer<JCStatement>();
statements.append(createConstructBuilderVarIfNeeded(maker, data, builderType, source));
JCExpression thisDotFieldDotAdd = chainDots(builderType, "this", data.getPluralName().toString(), getAddMethodName());
@@ -141,11 +141,10 @@ abstract class JavacGuavaSingularizer extends JavacSingularizer {
injectMethod(builderType, method);
}
- protected void generatePluralMethod(JavacTreeMaker maker, JCExpression returnType, JCStatement returnStatement, SingularData data, JavacNode builderType, JCTree source, boolean fluent) {
+ protected void generatePluralMethod(boolean deprecate, JavacTreeMaker maker, JCExpression returnType, JCStatement returnStatement, SingularData data, JavacNode builderType, JCTree source, boolean fluent) {
List<JCTypeParameter> typeParams = List.nil();
List<JCExpression> thrown = List.nil();
-
- JCModifiers mods = maker.Modifiers(Flags.PUBLIC);
+ JCModifiers mods = makeMods(maker, builderType, deprecate);
ListBuffer<JCStatement> statements = new ListBuffer<JCStatement>();
statements.append(createConstructBuilderVarIfNeeded(maker, data, builderType, source));
JCExpression thisDotFieldDotAddAll = chainDots(builderType, "this", data.getPluralName().toString(), getAddMethodName() + "All");
diff --git a/src/core/lombok/javac/handlers/singulars/JavacJavaUtilListSetSingularizer.java b/src/core/lombok/javac/handlers/singulars/JavacJavaUtilListSetSingularizer.java
index 7beb29cb..196ce45d 100644
--- a/src/core/lombok/javac/handlers/singulars/JavacJavaUtilListSetSingularizer.java
+++ b/src/core/lombok/javac/handlers/singulars/JavacJavaUtilListSetSingularizer.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2015 The Project Lombok Authors.
+ * Copyright (C) 2015-2017 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
@@ -76,9 +76,9 @@ abstract class JavacJavaUtilListSetSingularizer extends JavacJavaUtilSingularize
return Collections.singletonList(injectFieldAndMarkGenerated(builderType, buildField));
}
- @Override public void generateMethods(SingularData data, JavacNode builderType, JCTree source, boolean fluent, boolean chain) {
+ @Override public void generateMethods(SingularData data, boolean deprecate, JavacNode builderType, JCTree source, boolean fluent, boolean chain) {
if (useGuavaInstead(builderType)) {
- guavaListSetSingularizer.generateMethods(data, builderType, source, fluent, chain);
+ guavaListSetSingularizer.generateMethods(data, deprecate, builderType, source, fluent, chain);
return;
}
@@ -88,19 +88,19 @@ abstract class JavacJavaUtilListSetSingularizer extends JavacJavaUtilSingularize
JCExpression returnType = chain ? cloneSelfType(builderType) : maker.Type(createVoidType(symbolTable, CTC_VOID));
JCStatement returnStatement = chain ? maker.Return(maker.Ident(thisName)) : null;
- generateSingularMethod(maker, returnType, returnStatement, data, builderType, source, fluent);
+ generateSingularMethod(deprecate, maker, returnType, returnStatement, data, builderType, source, fluent);
returnType = chain ? cloneSelfType(builderType) : maker.Type(createVoidType(symbolTable, CTC_VOID));
returnStatement = chain ? maker.Return(maker.Ident(thisName)) : null;
- generatePluralMethod(maker, returnType, returnStatement, data, builderType, source, fluent);
+ generatePluralMethod(deprecate, maker, returnType, returnStatement, data, builderType, source, fluent);
returnType = chain ? cloneSelfType(builderType) : maker.Type(createVoidType(symbolTable, CTC_VOID));
returnStatement = chain ? maker.Return(maker.Ident(thisName)) : null;
- generateClearMethod(maker, returnType, returnStatement, data, builderType, source);
+ generateClearMethod(deprecate, maker, returnType, returnStatement, data, builderType, source);
}
- private void generateClearMethod(JavacTreeMaker maker, JCExpression returnType, JCStatement returnStatement, SingularData data, JavacNode builderType, JCTree source) {
- JCModifiers mods = maker.Modifiers(Flags.PUBLIC);
+ private void generateClearMethod(boolean deprecate, JavacTreeMaker maker, JCExpression returnType, JCStatement returnStatement, SingularData data, JavacNode builderType, JCTree source) {
+ JCModifiers mods = makeMods(maker, builderType, deprecate);
List<JCTypeParameter> typeParams = List.nil();
List<JCExpression> thrown = List.nil();
List<JCVariableDecl> params = List.nil();
@@ -119,11 +119,10 @@ abstract class JavacJavaUtilListSetSingularizer extends JavacJavaUtilSingularize
injectMethod(builderType, method);
}
- void generateSingularMethod(JavacTreeMaker maker, JCExpression returnType, JCStatement returnStatement, SingularData data, JavacNode builderType, JCTree source, boolean fluent) {
+ void generateSingularMethod(boolean deprecate, JavacTreeMaker maker, JCExpression returnType, JCStatement returnStatement, SingularData data, JavacNode builderType, JCTree source, boolean fluent) {
List<JCTypeParameter> typeParams = List.nil();
List<JCExpression> thrown = List.nil();
-
- JCModifiers mods = maker.Modifiers(Flags.PUBLIC);
+ JCModifiers mods = makeMods(maker, builderType, deprecate);
ListBuffer<JCStatement> statements = new ListBuffer<JCStatement>();
statements.append(createConstructBuilderVarIfNeeded(maker, data, builderType, false, source));
JCExpression thisDotFieldDotAdd = chainDots(builderType, "this", data.getPluralName().toString(), "add");
@@ -140,11 +139,10 @@ abstract class JavacJavaUtilListSetSingularizer extends JavacJavaUtilSingularize
injectMethod(builderType, method);
}
- void generatePluralMethod(JavacTreeMaker maker, JCExpression returnType, JCStatement returnStatement, SingularData data, JavacNode builderType, JCTree source, boolean fluent) {
+ void generatePluralMethod(boolean deprecate, JavacTreeMaker maker, JCExpression returnType, JCStatement returnStatement, SingularData data, JavacNode builderType, JCTree source, boolean fluent) {
List<JCTypeParameter> typeParams = List.nil();
List<JCExpression> thrown = List.nil();
-
- JCModifiers mods = maker.Modifiers(Flags.PUBLIC);
+ JCModifiers mods = makeMods(maker, builderType, deprecate);
ListBuffer<JCStatement> statements = new ListBuffer<JCStatement>();
statements.append(createConstructBuilderVarIfNeeded(maker, data, builderType, false, source));
JCExpression thisDotFieldDotAdd = chainDots(builderType, "this", data.getPluralName().toString(), "addAll");
diff --git a/src/core/lombok/javac/handlers/singulars/JavacJavaUtilMapSingularizer.java b/src/core/lombok/javac/handlers/singulars/JavacJavaUtilMapSingularizer.java
index 93b120e1..fd699275 100644
--- a/src/core/lombok/javac/handlers/singulars/JavacJavaUtilMapSingularizer.java
+++ b/src/core/lombok/javac/handlers/singulars/JavacJavaUtilMapSingularizer.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2015 The Project Lombok Authors.
+ * Copyright (C) 2015-2017 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
@@ -101,9 +101,9 @@ public class JavacJavaUtilMapSingularizer extends JavacJavaUtilSingularizer {
return Arrays.asList(keyFieldNode, valueFieldNode);
}
- @Override public void generateMethods(SingularData data, JavacNode builderType, JCTree source, boolean fluent, boolean chain) {
+ @Override public void generateMethods(SingularData data, boolean deprecate, JavacNode builderType, JCTree source, boolean fluent, boolean chain) {
if (useGuavaInstead(builderType)) {
- guavaMapSingularizer.generateMethods(data, builderType, source, fluent, chain);
+ guavaMapSingularizer.generateMethods(data, deprecate, builderType, source, fluent, chain);
return;
}
@@ -112,19 +112,20 @@ public class JavacJavaUtilMapSingularizer extends JavacJavaUtilSingularizer {
JCExpression returnType = chain ? cloneSelfType(builderType) : maker.Type(createVoidType(symbolTable, CTC_VOID));
JCStatement returnStatement = chain ? maker.Return(maker.Ident(builderType.toName("this"))) : null;
- generateSingularMethod(maker, returnType, returnStatement, data, builderType, source, fluent);
+ generateSingularMethod(deprecate, maker, returnType, returnStatement, data, builderType, source, fluent);
returnType = chain ? cloneSelfType(builderType) : maker.Type(createVoidType(symbolTable, CTC_VOID));
returnStatement = chain ? maker.Return(maker.Ident(builderType.toName("this"))) : null;
- generatePluralMethod(maker, returnType, returnStatement, data, builderType, source, fluent);
+ generatePluralMethod(deprecate, maker, returnType, returnStatement, data, builderType, source, fluent);
returnType = chain ? cloneSelfType(builderType) : maker.Type(createVoidType(symbolTable, CTC_VOID));
returnStatement = chain ? maker.Return(maker.Ident(builderType.toName("this"))) : null;
- generateClearMethod(maker, returnType, returnStatement, data, builderType, source);
+ generateClearMethod(deprecate, maker, returnType, returnStatement, data, builderType, source);
}
- private void generateClearMethod(JavacTreeMaker maker, JCExpression returnType, JCStatement returnStatement, SingularData data, JavacNode builderType, JCTree source) {
- JCModifiers mods = maker.Modifiers(Flags.PUBLIC);
+ private void generateClearMethod(boolean deprecate, JavacTreeMaker maker, JCExpression returnType, JCStatement returnStatement, SingularData data, JavacNode builderType, JCTree source) {
+ JCModifiers mods = makeMods(maker, builderType, deprecate);
+
List<JCTypeParameter> typeParams = List.nil();
List<JCExpression> thrown = List.nil();
List<JCVariableDecl> params = List.nil();
@@ -146,10 +147,11 @@ public class JavacJavaUtilMapSingularizer extends JavacJavaUtilSingularizer {
injectMethod(builderType, method);
}
- private void generateSingularMethod(JavacTreeMaker maker, JCExpression returnType, JCStatement returnStatement, SingularData data, JavacNode builderType, JCTree source, boolean fluent) {
+ private void generateSingularMethod(boolean deprecate, JavacTreeMaker maker, JCExpression returnType, JCStatement returnStatement, SingularData data, JavacNode builderType, JCTree source, boolean fluent) {
List<JCTypeParameter> typeParams = List.nil();
List<JCExpression> thrown = List.nil();
- JCModifiers mods = maker.Modifiers(Flags.PUBLIC);
+ JCModifiers mods = makeMods(maker, builderType, deprecate);
+
ListBuffer<JCStatement> statements = new ListBuffer<JCStatement>();
statements.append(createConstructBuilderVarIfNeeded(maker, data, builderType, true, source));
Name keyName = builderType.toName(data.getSingularName().toString() + "Key");
@@ -178,10 +180,10 @@ public class JavacJavaUtilMapSingularizer extends JavacJavaUtilSingularizer {
injectMethod(builderType, method);
}
- private void generatePluralMethod(JavacTreeMaker maker, JCExpression returnType, JCStatement returnStatement, SingularData data, JavacNode builderType, JCTree source, boolean fluent) {
+ private void generatePluralMethod(boolean deprecate, JavacTreeMaker maker, JCExpression returnType, JCStatement returnStatement, SingularData data, JavacNode builderType, JCTree source, boolean fluent) {
List<JCTypeParameter> typeParams = List.nil();
List<JCExpression> jceBlank = List.nil();
- JCModifiers mods = maker.Modifiers(Flags.PUBLIC);
+ JCModifiers mods = makeMods(maker, builderType, deprecate);
ListBuffer<JCStatement> statements = new ListBuffer<JCStatement>();
statements.append(createConstructBuilderVarIfNeeded(maker, data, builderType, true, source));
long paramFlags = JavacHandlerUtil.addFinalIfNeeded(Flags.PARAMETER, builderType.getContext());
diff --git a/src/core/lombok/javac/handlers/singulars/JavacJavaUtilSingularizer.java b/src/core/lombok/javac/handlers/singulars/JavacJavaUtilSingularizer.java
index 25669721..0589ac34 100644
--- a/src/core/lombok/javac/handlers/singulars/JavacJavaUtilSingularizer.java
+++ b/src/core/lombok/javac/handlers/singulars/JavacJavaUtilSingularizer.java
@@ -165,6 +165,9 @@ abstract class JavacJavaUtilSingularizer extends JavacSingularizer {
JCExpression pluralnameDotPut = maker.Select(maker.Ident(data.getPluralName()), builderType.toName("put"));
JCExpression arg1 = maker.Apply(jceBlank, chainDots(builderType, "this", data.getPluralName() + "$key", "get"), List.<JCExpression>of(maker.Ident(ivar)));
JCExpression arg2 = maker.Apply(jceBlank, chainDots(builderType, "this", data.getPluralName() + "$value", "get"), List.<JCExpression>of(maker.Ident(ivar)));
+ // [jdk9] We add an unneccessary (V) cast here. Not doing so gives an error in javac (build 9-ea+156-jigsaw-nightly-h6072-20170212):
+ // error: method put in interface Map<K#2,V#2> cannot be applied to given types;
+ arg2 = maker.TypeCast(createTypeArgs(2, false, builderType, data.getTypeArgs(), source).get(1), arg2);
JCStatement putStatement = maker.Exec(maker.Apply(jceBlank, pluralnameDotPut, List.of(arg1, arg2)));
JCStatement forInit = maker.VarDef(maker.Modifiers(0), ivar, maker.TypeIdent(CTC_INT), maker.Literal(CTC_INT, 0));
JCExpression checkExpr = maker.Binary(CTC_LESS_THAN, maker.Ident(ivar), getSize(maker, builderType, keyVarName, nullGuard, true));