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.java11
-rw-r--r--src/core/lombok/javac/JavacNode.java33
-rw-r--r--src/core/lombok/javac/JavacResolution.java66
-rw-r--r--src/core/lombok/javac/JavacTransformer.java29
-rw-r--r--src/core/lombok/javac/apt/Javac9BaseFileObjectWrapper.java111
-rw-r--r--src/core/lombok/javac/apt/LombokFileObjects.java154
-rw-r--r--src/core/lombok/javac/apt/LombokProcessor.java26
-rw-r--r--src/core/lombok/javac/handlers/HandleBuilder.java26
-rw-r--r--src/core/lombok/javac/handlers/HandleConstructor.java9
-rw-r--r--src/core/lombok/javac/handlers/HandleDelegate.java22
-rw-r--r--src/core/lombok/javac/handlers/HandleGetter.java20
-rw-r--r--src/core/lombok/javac/handlers/HandleJacksonized.java1
-rw-r--r--src/core/lombok/javac/handlers/HandleLog.java33
-rw-r--r--src/core/lombok/javac/handlers/HandleSuperBuilder.java41
-rw-r--r--src/core/lombok/javac/handlers/HandleUtilityClass.java2
-rw-r--r--src/core/lombok/javac/handlers/HandleWith.java3
-rw-r--r--src/core/lombok/javac/handlers/JavacHandlerUtil.java125
-rw-r--r--src/core/lombok/javac/handlers/JavacSingularsRecipes.java16
18 files changed, 373 insertions, 355 deletions
diff --git a/src/core/lombok/javac/JavacAST.java b/src/core/lombok/javac/JavacAST.java
index f6cd5571..86ff7646 100644
--- a/src/core/lombok/javac/JavacAST.java
+++ b/src/core/lombok/javac/JavacAST.java
@@ -79,6 +79,8 @@ public class JavacAST extends AST<JavacAST, JavacNode, JCTree> {
private final Log log;
private final ErrorLog errorLogger;
private final Context context;
+ private static final URI NOT_CALCULATED_MARKER = URI.create("https://projectlombok.org/not/calculated");
+ private URI memoizedAbsoluteFileLocation = NOT_CALCULATED_MARKER;
/**
* Creates a new JavacAST of the provided Compilation Unit.
@@ -102,7 +104,10 @@ public class JavacAST extends AST<JavacAST, JavacNode, JCTree> {
}
@Override public URI getAbsoluteFileLocation() {
- return getAbsoluteFileLocation((JCCompilationUnit) top().get());
+ if (memoizedAbsoluteFileLocation == NOT_CALCULATED_MARKER) {
+ memoizedAbsoluteFileLocation = getAbsoluteFileLocation((JCCompilationUnit) top().get());
+ }
+ return memoizedAbsoluteFileLocation;
}
public static URI getAbsoluteFileLocation(JCCompilationUnit cu) {
@@ -258,7 +263,7 @@ public class JavacAST extends AST<JavacAST, JavacNode, JCTree> {
if (typeUse == null) return null;
- if (typeUse.getClass().getSimpleName().equals("JCAnnotatedType")) {
+ if (typeUse.getClass().getName().equals("com.sun.tools.javac.tree.JCTree$JCAnnotatedType")) {
initJcAnnotatedType(typeUse.getClass());
Collection<?> anns = Permit.permissiveReadField(Collection.class, JCANNOTATEDTYPE_ANNOTATIONS, typeUse);
JCExpression underlying = Permit.permissiveReadField(JCExpression.class, JCANNOTATEDTYPE_UNDERLYINGTYPE, typeUse);
@@ -381,7 +386,7 @@ public class JavacAST extends AST<JavacAST, JavacNode, JCTree> {
if (statement instanceof JCClassDecl) return buildType((JCClassDecl) statement);
if (statement instanceof JCVariableDecl) return buildLocalVar((JCVariableDecl) statement, Kind.LOCAL);
if (statement instanceof JCTry) return buildTry((JCTry) statement);
- if (statement.getClass().getSimpleName().equals("JCLambda")) return buildLambda(statement);
+ if (statement.getClass().getName().equals("com.sun.tools.javac.tree.JCTree$JCLambda")) return buildLambda(statement);
if (setAndGetAsHandled(statement)) return null;
return drill(statement);
diff --git a/src/core/lombok/javac/JavacNode.java b/src/core/lombok/javac/JavacNode.java
index 19bbeae3..3de3f38b 100644
--- a/src/core/lombok/javac/JavacNode.java
+++ b/src/core/lombok/javac/JavacNode.java
@@ -27,10 +27,6 @@ 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;
@@ -43,8 +39,12 @@ 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;
import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition;
+import com.sun.tools.javac.util.Name;
+
+import lombok.core.AST.Kind;
+import lombok.core.AnnotationValues;
+import lombok.javac.handlers.JavacHandlerUtil;
/**
* Javac specific version of the LombokNode class.
@@ -345,6 +345,29 @@ public class JavacNode extends lombok.core.LombokNode<JavacAST, JavacNode, JCTre
return mods != null && (Flags.ENUM & mods.flags) != 0;
}
+ @Override public boolean isPrimitive() {
+ if (node instanceof JCVariableDecl && !isEnumMember()) {
+ return Javac.isPrimitive(((JCVariableDecl) node).vartype);
+ }
+ if (node instanceof JCMethodDecl) {
+ return Javac.isPrimitive(((JCMethodDecl) node).restype);
+ }
+ return false;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override public String fieldOrMethodBaseType() {
+ if (node instanceof JCVariableDecl && !isEnumMember()) {
+ return (((JCVariableDecl) node).vartype).toString();
+ }
+ if (node instanceof JCMethodDecl) {
+ return (((JCMethodDecl) node).restype).toString();
+ }
+ return null;
+ }
+
@Override public boolean isTransient() {
if (getKind() != Kind.FIELD) return false;
JCModifiers mods = getModifiers();
diff --git a/src/core/lombok/javac/JavacResolution.java b/src/core/lombok/javac/JavacResolution.java
index 9a0077a7..6b2f4637 100644
--- a/src/core/lombok/javac/JavacResolution.java
+++ b/src/core/lombok/javac/JavacResolution.java
@@ -28,7 +28,10 @@ import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayDeque;
+import java.util.Collection;
+import java.util.Iterator;
import java.util.Map;
+import java.util.NoSuchElementException;
import javax.lang.model.type.TypeKind;
import javax.tools.JavaFileObject;
@@ -40,6 +43,7 @@ import com.sun.tools.javac.code.Type;
import com.sun.tools.javac.code.Type.ArrayType;
import com.sun.tools.javac.code.Type.CapturedType;
import com.sun.tools.javac.code.Type.ClassType;
+import com.sun.tools.javac.code.Type.TypeVar;
import com.sun.tools.javac.code.Type.WildcardType;
import com.sun.tools.javac.code.Types;
import com.sun.tools.javac.comp.Attr;
@@ -59,6 +63,7 @@ import com.sun.tools.javac.util.Context;
import com.sun.tools.javac.util.List;
import com.sun.tools.javac.util.ListBuffer;
import com.sun.tools.javac.util.Log;
+import com.sun.tools.javac.util.Name;
import lombok.Lombok;
import lombok.core.debug.AssertionLogger;
@@ -314,6 +319,41 @@ public class JavacResolution {
return result;
}
+ private static Iterable<? extends Type> concat(final Type t, final Collection<? extends Type> ts) {
+ if (t == null) return ts;
+
+ return new Iterable<Type>() {
+ @Override public Iterator<Type> iterator() {
+ return new Iterator<Type>() {
+ private boolean first = true;
+ private Iterator<? extends Type> wrap = ts == null ? null : ts.iterator();
+ @Override public boolean hasNext() {
+ if (first) return true;
+ if (wrap == null) return false;
+ return wrap.hasNext();
+ }
+
+ @Override public Type next() {
+ if (first) {
+ first = false;
+ return t;
+ }
+ if (wrap == null) throw new NoSuchElementException();
+ return wrap.next();
+ }
+
+ @Override public void remove() {
+ throw new UnsupportedOperationException();
+ }
+ };
+ }
+ };
+ }
+
+ private static int compare(Name a, Name b) {
+ return a.compareTo(b);
+ }
+
private static JCExpression typeToJCTree0(Type type, JavacAST ast, boolean allowCompound, boolean allowVoid, boolean allowCapture) throws TypeNotConvertibleException {
// NB: There's such a thing as maker.Type(type), but this doesn't work very well; it screws up anonymous classes, captures, and adds an extra prefix dot for some reason too.
// -- so we write our own take on that here.
@@ -335,12 +375,30 @@ public class JavacResolution {
if (symbol.name.length() == 0) {
// Anonymous inner class
if (type instanceof ClassType) {
- List<Type> ifaces = ((ClassType) type).interfaces_field;
+ Type winner = null;
+ int winLevel = 0; // 100 = array, 50 = class, 20 = typevar, 15 = wildcard, 10 = interface, 1 = Object.
Type supertype = ((ClassType) type).supertype_field;
- if (isObject(supertype) && ifaces != null && ifaces.length() > 0) {
- return typeToJCTree(ifaces.get(0), ast, allowCompound, allowVoid, allowCapture);
+ List<Type> ifaces = ((ClassType) type).interfaces_field;
+ for (Type t : concat(supertype, ifaces)) {
+ int level = 0;
+ if (t instanceof ArrayType) level = 100;
+ else if (t instanceof TypeVar) level = 20;
+ else if (t instanceof WildcardType) level = 15;
+ else if (t.isInterface()) level = 10;
+ else if (isObject(t)) level = 1;
+ else if (t instanceof ClassType) level = 50;
+ else level = 5;
+
+ if (winLevel > level) continue;
+ if (winLevel < level) {
+ winner = t;
+ winLevel = level;
+ continue;
+ }
+ if (compare(winner.tsym.getQualifiedName(), t.tsym.getQualifiedName()) < 0) winner = t;
}
- if (supertype != null) return typeToJCTree(supertype, ast, allowCompound, allowVoid, allowCapture);
+ if (winner == null) return createJavaLangObject(ast);
+ return typeToJCTree(winner, ast, allowCompound, allowVoid, allowCapture);
}
throw new TypeNotConvertibleException("Anonymous inner class");
}
diff --git a/src/core/lombok/javac/JavacTransformer.java b/src/core/lombok/javac/JavacTransformer.java
index 625fb283..a2e00680 100644
--- a/src/core/lombok/javac/JavacTransformer.java
+++ b/src/core/lombok/javac/JavacTransformer.java
@@ -21,7 +21,7 @@
*/
package lombok.javac;
-import java.util.ArrayList;
+import java.util.List;
import java.util.SortedSet;
import javax.annotation.processing.Messager;
@@ -34,7 +34,6 @@ import com.sun.tools.javac.tree.JCTree.JCCompilationUnit;
import com.sun.tools.javac.tree.JCTree.JCMethodDecl;
import com.sun.tools.javac.tree.JCTree.JCVariableDecl;
import com.sun.tools.javac.util.Context;
-import com.sun.tools.javac.util.List;
import lombok.ConfigurationKeys;
import lombok.core.CleanupRegistry;
@@ -57,31 +56,15 @@ public class JavacTransformer {
return handlers.getPrioritiesRequiringResolutionReset();
}
- public void transform(long priority, Context context, java.util.List<JCCompilationUnit> compilationUnitsRaw, CleanupRegistry cleanup) {
- List<JCCompilationUnit> compilationUnits;
- if (compilationUnitsRaw instanceof List<?>) {
- compilationUnits = (List<JCCompilationUnit>) compilationUnitsRaw;
- } else {
- compilationUnits = List.nil();
- for (int i = compilationUnitsRaw.size() -1; i >= 0; i--) {
- compilationUnits = compilationUnits.prepend(compilationUnitsRaw.get(i));
- }
- }
-
- java.util.List<JavacAST> asts = new ArrayList<JavacAST>();
-
+ public void transform(long priority, Context context, List<JCCompilationUnit> compilationUnits, CleanupRegistry cleanup) {
for (JCCompilationUnit unit : compilationUnits) {
if (!Boolean.TRUE.equals(LombokConfiguration.read(ConfigurationKeys.LOMBOK_DISABLE, JavacAST.getAbsoluteFileLocation(unit)))) {
- asts.add(new JavacAST(messager, context, unit, cleanup));
+ JavacAST ast = new JavacAST(messager, context, unit, cleanup);
+ ast.traverse(new AnnotationVisitor(priority));
+ handlers.callASTVisitors(ast, priority);
+ if (ast.isChanged()) LombokOptions.markChanged(context, (JCCompilationUnit) ast.top().get());
}
}
-
- for (JavacAST ast : asts) {
- ast.traverse(new AnnotationVisitor(priority));
- handlers.callASTVisitors(ast, priority);
- }
-
- for (JavacAST ast : asts) if (ast.isChanged()) LombokOptions.markChanged(context, (JCCompilationUnit) ast.top().get());
}
private class AnnotationVisitor extends JavacASTAdapter {
diff --git a/src/core/lombok/javac/apt/Javac9BaseFileObjectWrapper.java b/src/core/lombok/javac/apt/Javac9BaseFileObjectWrapper.java
deleted file mode 100644
index f71be366..00000000
--- a/src/core/lombok/javac/apt/Javac9BaseFileObjectWrapper.java
+++ /dev/null
@@ -1,111 +0,0 @@
-/*
- * 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
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- * THE SOFTWARE.
- */
-
-package lombok.javac.apt;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.io.Reader;
-import java.io.Writer;
-import java.net.URI;
-import java.nio.file.Path;
-
-import javax.lang.model.element.Modifier;
-import javax.lang.model.element.NestingKind;
-
-import com.sun.tools.javac.file.BaseFileManager;
-
-class Javac9BaseFileObjectWrapper extends com.sun.tools.javac.file.PathFileObject {
- private final LombokFileObject delegate;
-
- public Javac9BaseFileObjectWrapper(BaseFileManager fileManager, Path path, LombokFileObject delegate) {
- super(fileManager, path);
- this.delegate = delegate;
- }
-
- @Override public boolean isNameCompatible(String simpleName, Kind kind) {
- return delegate.isNameCompatible(simpleName, kind);
- }
-
- @Override public URI toUri() {
- return delegate.toUri();
- }
-
- @SuppressWarnings("all")
- @Override public String getName() {
- return delegate.getName();
- }
-
- @Override public CharSequence getCharContent(boolean ignoreEncodingErrors) throws IOException {
- return delegate.getCharContent(ignoreEncodingErrors);
- }
-
- @Override public InputStream openInputStream() throws IOException {
- return delegate.openInputStream();
- }
-
- @Override public Reader openReader(boolean ignoreEncodingErrors) throws IOException {
- return delegate.openReader(ignoreEncodingErrors);
- }
-
- @Override public Writer openWriter() throws IOException {
- return delegate.openWriter();
- }
-
- @Override public OutputStream openOutputStream() throws IOException {
- return delegate.openOutputStream();
- }
-
- @Override public long getLastModified() {
- return delegate.getLastModified();
- }
-
- @Override public boolean delete() {
- return delegate.delete();
- }
-
- @Override public Kind getKind() {
- return delegate.getKind();
- }
-
- @Override public NestingKind getNestingKind() {
- return delegate.getNestingKind();
- }
-
- @Override public Modifier getAccessLevel() {
- return delegate.getAccessLevel();
- }
-
- @Override public boolean equals(Object obj) {
- if (!(obj instanceof Javac9BaseFileObjectWrapper)) return false;
- return delegate.equals(((Javac9BaseFileObjectWrapper)obj).delegate);
- }
-
- @Override public int hashCode() {
- return delegate.hashCode();
- }
-
- @Override public String toString() {
- return delegate.toString();
- }
-} \ No newline at end of file
diff --git a/src/core/lombok/javac/apt/LombokFileObjects.java b/src/core/lombok/javac/apt/LombokFileObjects.java
index f6643db3..880ef1fd 100644
--- a/src/core/lombok/javac/apt/LombokFileObjects.java
+++ b/src/core/lombok/javac/apt/LombokFileObjects.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2010-2019 The Project Lombok Authors.
+ * Copyright (C) 2010-2020 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,23 +22,15 @@
package lombok.javac.apt;
-import java.io.IOException;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
-import java.net.URI;
-import java.nio.file.Path;
-import java.nio.file.Paths;
import java.util.Arrays;
-import java.util.Iterator;
import java.util.List;
-import java.util.Set;
import java.util.concurrent.atomic.AtomicBoolean;
-import javax.tools.FileObject;
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 lombok.permit.Permit;
@@ -116,22 +108,20 @@ final class LombokFileObjects {
if (jfmClassName.equals("com.sun.tools.javac.file.JavacFileManager")) {
try {
Class<?> superType = Class.forName("com.sun.tools.javac.file.BaseFileManager");
- if (superType.isInstance(jfm)) {
- return new Java9Compiler(jfm);
- }
+ if (superType.isInstance(jfm)) return java9Compiler(jfm);
}
catch (Throwable e) {}
return Compiler.JAVAC7;
}
if (KNOWN_JAVA9_FILE_MANAGERS.contains(jfmClassName)) {
try {
- return new Java9Compiler(jfm);
+ return java9Compiler(jfm);
}
catch (Throwable e) {}
}
try {
if (Class.forName("com.sun.tools.javac.file.PathFileObject") == null) throw new NullPointerException();
- return new Java9Compiler(jfm);
+ return java9Compiler(jfm);
} catch (Throwable e) {}
try {
if (Class.forName("com.sun.tools.javac.file.BaseFileObject") == null) throw new NullPointerException();
@@ -156,122 +146,24 @@ final class LombokFileObjects {
return compiler.wrap(new InterceptingJavaFileObject(delegate, fileName, diagnostics, compiler.getDecoderMethod()));
}
- static class Java9Compiler implements Compiler {
- private final BaseFileManager fileManager;
-
- public Java9Compiler(JavaFileManager jfm) {
- fileManager = asBaseFileManager(jfm);
- }
-
- @Override public JavaFileObject wrap(LombokFileObject fileObject) {
- Path p; try {
- p = toPath(fileObject);
- } catch (Exception e) {
- p = null;
- }
-
- // J9BFOW extends javac's internal file base impl of javax.tools.JavaFileObject.
- // J9JFOW just straight implements it. Probably J9JFOW is fine, but we decided to extend java's internal impl possibly for a reason.
- // Some exotic build environments don't _have_ file objects and crash with FileNotFoundEx, so if that happens, let's try the alternative.
- if (p != null) return new Javac9BaseFileObjectWrapper(fileManager, p, fileObject);
- return new Javac9JavaFileObjectWrapper(fileObject);
- }
-
- @Override public Method getDecoderMethod() {
+ private static Constructor<?> j9CompilerConstructor = null;
+ private static Compiler java9Compiler(JavaFileManager jfm) {
+ try {
+ if (j9CompilerConstructor == null) j9CompilerConstructor = Class.forName("lombok.javac.apt.Java9Compiler").getConstructor(JavaFileManager.class);
+ return (Compiler) j9CompilerConstructor.newInstance(jfm);
+ } catch (ClassNotFoundException e) {
return null;
- }
-
- private static Path toPath(LombokFileObject fileObject) {
- URI uri = fileObject.toUri();
- if (uri.getScheme() == null) {
- uri = URI.create("file:///" + uri);
- }
- try {
- return Paths.get(uri);
- } catch (IllegalArgumentException e) {
- throw new IllegalArgumentException("Problems in URI '" + uri + "' (" + fileObject.toUri() + ")", e);
- }
- }
-
- private static BaseFileManager asBaseFileManager(JavaFileManager jfm) {
- if (jfm instanceof BaseFileManager) {
- return (BaseFileManager) jfm;
- }
- return new FileManagerWrapper(jfm);
- }
-
- static class FileManagerWrapper extends BaseFileManager {
- JavaFileManager manager;
-
- public FileManagerWrapper(JavaFileManager manager) {
- super(null);
- this.manager = manager;
- }
-
- @Override
- public int isSupportedOption(String option) {
- return manager.isSupportedOption(option);
- }
-
- @Override
- public ClassLoader getClassLoader(Location location) {
- return manager.getClassLoader(location);
- }
-
- @Override
- public Iterable<JavaFileObject> list(Location location, String packageName, Set<Kind> kinds, boolean recurse) throws IOException {
- return manager.list(location, packageName, kinds, recurse);
- }
-
- @Override
- public String inferBinaryName(Location location, JavaFileObject file) {
- return manager.inferBinaryName(location, file);
- }
-
- @Override
- public boolean isSameFile(FileObject a, FileObject b) {
- return manager.isSameFile(a, b);
- }
-
- @Override
- public boolean handleOption(String current, Iterator<String> remaining) {
- return manager.handleOption(current, remaining);
- }
-
- @Override
- public boolean hasLocation(Location location) {
- return manager.hasLocation(location);
- }
-
- @Override
- public JavaFileObject getJavaFileForInput(Location location, String className, Kind kind) throws IOException {
- return manager.getJavaFileForInput(location, className, kind);
- }
-
- @Override
- public JavaFileObject getJavaFileForOutput(Location location, String className, Kind kind, FileObject sibling) throws IOException {
- return manager.getJavaFileForOutput(location, className, kind, sibling);
- }
-
- @Override
- public FileObject getFileForInput(Location location, String packageName, String relativeName) throws IOException {
- return manager.getFileForInput(location, packageName, relativeName);
- }
-
- @Override
- public FileObject getFileForOutput(Location location, String packageName, String relativeName, FileObject sibling) throws IOException {
- return manager.getFileForOutput(location, packageName, relativeName, sibling);
- }
-
- @Override
- public void flush() throws IOException {
- manager.flush();
- }
-
- @Override
- public void close() throws IOException {
- manager.close();
- }
+ } catch (NoSuchMethodException e) {
+ return null;
+ } catch (InvocationTargetException e) {
+ Throwable t = e.getCause();
+ if (t instanceof RuntimeException) throw (RuntimeException) t;
+ if (t instanceof Error) throw (Error) t;
+ throw new RuntimeException(t);
+ } catch (IllegalAccessException e) {
+ throw new RuntimeException(e);
+ } catch (InstantiationException e) {
+ throw new RuntimeException(e);
}
}
}
diff --git a/src/core/lombok/javac/apt/LombokProcessor.java b/src/core/lombok/javac/apt/LombokProcessor.java
index c32e09d5..852e5de6 100644
--- a/src/core/lombok/javac/apt/LombokProcessor.java
+++ b/src/core/lombok/javac/apt/LombokProcessor.java
@@ -24,6 +24,7 @@ package lombok.javac.apt;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Field;
+import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.net.URL;
import java.util.ArrayList;
@@ -42,7 +43,6 @@ import javax.annotation.processing.RoundEnvironment;
import javax.annotation.processing.SupportedAnnotationTypes;
import javax.lang.model.SourceVersion;
import javax.lang.model.element.Element;
-import javax.lang.model.element.QualifiedNameable;
import javax.lang.model.element.TypeElement;
import javax.tools.Diagnostic.Kind;
import javax.tools.JavaFileManager;
@@ -371,7 +371,7 @@ public class LombokProcessor extends AbstractProcessor {
private String getModuleNameFor(Element element) {
while (element != null) {
- if (element.getKind().name().equals("MODULE")) return ModuleNameOracle.getModuleName(element);
+ if (element.getKind().name().equals("MODULE")) return getModuleName(element);
Element n = element.getEnclosingElement();
if (n == element) return null;
element = n;
@@ -379,12 +379,24 @@ public class LombokProcessor extends AbstractProcessor {
return null;
}
- // QualifiedNameable is a java7 thing, so to remain compatible with java6, shove this into an inner class to avoid the ClassNotFoundError.
- private static class ModuleNameOracle {
- static String getModuleName(Element element) {
- if (!(element instanceof QualifiedNameable)) return null;
- String name = ((QualifiedNameable) element).getQualifiedName().toString().trim();
+ private static Class<?> qualifiedNamableClass = null;
+ private static Method qualifiedNamableQualifiedNameMethod = null;
+ // QualifiedNameable isn't in java 6, so to remain compatible with java6, use reflection.
+ private static String getModuleName(Element element) {
+ try {
+ if (qualifiedNamableClass == null) qualifiedNamableClass = Class.forName("javax.lang.model.element.QualifiedNamable");
+ if (!qualifiedNamableClass.isInstance(element)) return null;
+ if (qualifiedNamableQualifiedNameMethod == null) qualifiedNamableQualifiedNameMethod = qualifiedNamableClass.getMethod("getQualifiedName");
+ String name = qualifiedNamableQualifiedNameMethod.invoke(element).toString().trim();
return name.isEmpty() ? null : name;
+ } catch (ClassNotFoundException e) {
+ return null;
+ } catch (NoSuchMethodException e) {
+ return null;
+ } catch (InvocationTargetException e) {
+ return null;
+ } catch (IllegalAccessException e) {
+ return null;
}
}
diff --git a/src/core/lombok/javac/handlers/HandleBuilder.java b/src/core/lombok/javac/handlers/HandleBuilder.java
index 91a74d62..7e87ce11 100644
--- a/src/core/lombok/javac/handlers/HandleBuilder.java
+++ b/src/core/lombok/javac/handlers/HandleBuilder.java
@@ -27,6 +27,8 @@ import static lombok.javac.JavacTreeMaker.TypeTag.typeTag;
import static lombok.javac.handlers.JavacHandlerUtil.*;
import java.util.ArrayList;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
import javax.lang.model.element.Modifier;
@@ -38,6 +40,7 @@ import com.sun.tools.javac.tree.JCTree.JCAnnotation;
import com.sun.tools.javac.tree.JCTree.JCArrayTypeTree;
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.JCExpression;
import com.sun.tools.javac.tree.JCTree.JCFieldAccess;
import com.sun.tools.javac.tree.JCTree.JCIdent;
@@ -432,7 +435,7 @@ public class HandleBuilder extends JavacAnnotationHandler<Builder> {
java.util.List<Included<JavacNode, ToString.Include>> fieldNodes = new ArrayList<Included<JavacNode, ToString.Include>>();
for (BuilderFieldData bfd : builderFields) {
for (JavacNode f : bfd.createdFields) {
- fieldNodes.add(new Included<JavacNode, ToString.Include>(f, null, true));
+ fieldNodes.add(new Included<JavacNode, ToString.Include>(f, null, true, false));
}
}
@@ -845,11 +848,30 @@ public class HandleBuilder extends JavacAnnotationHandler<Builder> {
newMethod.params = List.of(recv, newMethod.params.get(0));
}
recursiveSetGeneratedBy(newMethod, source.get(), builderType.getContext());
- copyJavadoc(originalFieldNode, newMethod, CopyJavadoc.SETTER, true);
+ if (source.up().getKind() == Kind.METHOD) {
+ copyJavadocFromParam(originalFieldNode.up(), newMethod, paramName.toString());
+ } else {
+ copyJavadoc(originalFieldNode, newMethod, CopyJavadoc.SETTER, true);
+ }
injectMethod(builderType, newMethod);
}
+ private void copyJavadocFromParam(JavacNode from, JCMethodDecl to, String param) {
+ try {
+ JCCompilationUnit cu = ((JCCompilationUnit) from.top().get());
+ String methodComment = Javac.getDocComment(cu, from.get());
+ if (methodComment == null) return;
+
+ Pattern pattern = Pattern.compile("@param " + param + " (\\S|\\s)+?(?=^ ?@)", Pattern.MULTILINE | Pattern.CASE_INSENSITIVE);
+ Matcher matcher = pattern.matcher(methodComment);
+ if (matcher.find()) {
+ String newJavadoc = addReturnsThisIfNeeded(matcher.group());
+ Javac.setDocComment(cu, to, newJavadoc);
+ }
+ } catch (Exception ignore) {}
+ }
+
public JavacNode makeBuilderClass(boolean isStatic, JavacNode source, JavacNode tdParent, String builderClassName, List<JCTypeParameter> typeParams, JCAnnotation ast, AccessLevel access) {
JavacTreeMaker maker = tdParent.getTreeMaker();
int modifiers = toJavacModifier(access);
diff --git a/src/core/lombok/javac/handlers/HandleConstructor.java b/src/core/lombok/javac/handlers/HandleConstructor.java
index e0abb53b..2a683767 100644
--- a/src/core/lombok/javac/handlers/HandleConstructor.java
+++ b/src/core/lombok/javac/handlers/HandleConstructor.java
@@ -68,6 +68,7 @@ import lombok.javac.handlers.JavacHandlerUtil.MemberExistsResult;
public class HandleConstructor {
@ProviderFor(JavacAnnotationHandler.class)
public static class HandleNoArgsConstructor extends JavacAnnotationHandler<NoArgsConstructor> {
+ private static final String NAME = NoArgsConstructor.class.getSimpleName();
private HandleConstructor handleConstructor = new HandleConstructor();
@Override public void handle(AnnotationValues<NoArgsConstructor> annotation, JCAnnotation ast, JavacNode annotationNode) {
@@ -76,7 +77,7 @@ public class HandleConstructor {
deleteAnnotationIfNeccessary(annotationNode, NoArgsConstructor.class);
deleteImportFromCompilationUnit(annotationNode, "lombok.AccessLevel");
JavacNode typeNode = annotationNode.up();
- if (!checkLegality(typeNode, annotationNode, NoArgsConstructor.class.getSimpleName())) return;
+ if (!checkLegality(typeNode, annotationNode, NAME)) return;
List<JCAnnotation> onConstructor = unboxAndRemoveAnnotationParameter(ast, "onConstructor", "@NoArgsConstructor(onConstructor", annotationNode);
NoArgsConstructor ann = annotation.getInstance();
AccessLevel level = ann.access();
@@ -89,6 +90,7 @@ public class HandleConstructor {
@ProviderFor(JavacAnnotationHandler.class)
public static class HandleRequiredArgsConstructor extends JavacAnnotationHandler<RequiredArgsConstructor> {
+ private static final String NAME = RequiredArgsConstructor.class.getSimpleName();
private HandleConstructor handleConstructor = new HandleConstructor();
@Override public void handle(AnnotationValues<RequiredArgsConstructor> annotation, JCAnnotation ast, JavacNode annotationNode) {
@@ -97,7 +99,7 @@ public class HandleConstructor {
deleteAnnotationIfNeccessary(annotationNode, RequiredArgsConstructor.class);
deleteImportFromCompilationUnit(annotationNode, "lombok.AccessLevel");
JavacNode typeNode = annotationNode.up();
- if (!checkLegality(typeNode, annotationNode, RequiredArgsConstructor.class.getSimpleName())) return;
+ if (!checkLegality(typeNode, annotationNode, NAME)) return;
List<JCAnnotation> onConstructor = unboxAndRemoveAnnotationParameter(ast, "onConstructor", "@RequiredArgsConstructor(onConstructor", annotationNode);
RequiredArgsConstructor ann = annotation.getInstance();
AccessLevel level = ann.access();
@@ -138,6 +140,7 @@ public class HandleConstructor {
@ProviderFor(JavacAnnotationHandler.class)
public static class HandleAllArgsConstructor extends JavacAnnotationHandler<AllArgsConstructor> {
+ private static final String NAME = AllArgsConstructor.class.getSimpleName();
private HandleConstructor handleConstructor = new HandleConstructor();
@Override public void handle(AnnotationValues<AllArgsConstructor> annotation, JCAnnotation ast, JavacNode annotationNode) {
@@ -146,7 +149,7 @@ public class HandleConstructor {
deleteAnnotationIfNeccessary(annotationNode, AllArgsConstructor.class);
deleteImportFromCompilationUnit(annotationNode, "lombok.AccessLevel");
JavacNode typeNode = annotationNode.up();
- if (!checkLegality(typeNode, annotationNode, AllArgsConstructor.class.getSimpleName())) return;
+ if (!checkLegality(typeNode, annotationNode, NAME)) return;
List<JCAnnotation> onConstructor = unboxAndRemoveAnnotationParameter(ast, "onConstructor", "@AllArgsConstructor(onConstructor", annotationNode);
AllArgsConstructor ann = annotation.getInstance();
AccessLevel level = ann.access();
diff --git a/src/core/lombok/javac/handlers/HandleDelegate.java b/src/core/lombok/javac/handlers/HandleDelegate.java
index 367b2cff..d6e76ab1 100644
--- a/src/core/lombok/javac/handlers/HandleDelegate.java
+++ b/src/core/lombok/javac/handlers/HandleDelegate.java
@@ -48,6 +48,7 @@ import org.mangosdk.spi.ProviderFor;
import com.sun.tools.javac.code.Attribute.Compound;
import com.sun.tools.javac.code.Flags;
import com.sun.tools.javac.code.Symbol;
+import com.sun.tools.javac.code.Symbol.MethodSymbol;
import com.sun.tools.javac.code.Symbol.TypeSymbol;
import com.sun.tools.javac.code.Type;
import com.sun.tools.javac.code.Type.ClassType;
@@ -175,14 +176,14 @@ public class HandleDelegate extends JavacAnnotationHandler<Delegate> {
List<MethodSig> signaturesToExclude = new ArrayList<MethodSig>();
Set<String> banList = new HashSet<String>();
banList.addAll(METHODS_IN_OBJECT);
- /* To exclude all methods in the class itself, try this:
- for (Symbol member : ((JCClassDecl)typeNode.get()).sym.getEnclosedElements()) {
- if (member instanceof MethodSymbol) {
- MethodSymbol method = (MethodSymbol) member;
- banList.add(printSig((ExecutableType) method.asType(), method.name, annotationNode.getTypesUtil()));
+
+ // Add already implemented methods to ban list
+ JavacNode typeNode = upToTypeNode(annotationNode);
+ for (Symbol m : ((JCClassDecl)typeNode.get()).sym.getEnclosedElements()) {
+ if (m instanceof MethodSymbol) {
+ banList.add(printSig((ExecutableType) m.asType(), m.name, annotationNode.getTypesUtil()));
}
}
- */
try {
for (Type t : toExclude) {
@@ -389,10 +390,11 @@ public class HandleDelegate extends JavacAnnotationHandler<Delegate> {
boolean isDeprecated = (member.flags() & DEPRECATED) != 0;
signatures.add(new MethodSig(member.name, methodType, isDeprecated, exElem));
}
-
- if (ct.supertype_field instanceof ClassType) addMethodBindings(signatures, (ClassType) ct.supertype_field, types, banList);
- if (ct.interfaces_field != null) for (Type iface : ct.interfaces_field) {
- if (iface instanceof ClassType) addMethodBindings(signatures, (ClassType) iface, types, banList);
+
+ for (Type type : types.directSupertypes(ct)) {
+ if (type instanceof ClassType) {
+ addMethodBindings(signatures, (ClassType) type, types, banList);
+ }
}
}
diff --git a/src/core/lombok/javac/handlers/HandleGetter.java b/src/core/lombok/javac/handlers/HandleGetter.java
index 985873c1..110941d6 100644
--- a/src/core/lombok/javac/handlers/HandleGetter.java
+++ b/src/core/lombok/javac/handlers/HandleGetter.java
@@ -232,9 +232,17 @@ public class HandleGetter extends JavacAnnotationHandler<Getter> {
List<JCStatement> statements;
JCTree toClearOfMarkers = null;
+ int[] methodArgPos = null;
boolean addSuppressWarningsUnchecked = false;
if (lazy && !inNetbeansEditor(field)) {
toClearOfMarkers = fieldNode.init;
+ if (toClearOfMarkers instanceof JCMethodInvocation) {
+ List<JCExpression> args = ((JCMethodInvocation) toClearOfMarkers).args;
+ methodArgPos = new int[args.length()];
+ for (int i = 0; i < methodArgPos.length; i++) {
+ methodArgPos[i] = args.get(i).pos;
+ }
+ }
statements = createLazyGetterBody(treeMaker, field, source);
addSuppressWarningsUnchecked = LombokOptionsFactory.getDelombokOptions(field.getContext()).getFormatPreferences().generateSuppressWarnings();
} else {
@@ -262,10 +270,20 @@ public class HandleGetter extends JavacAnnotationHandler<Getter> {
methodGenericParams, parameters, throwsClauses, methodBody, annotationMethodDefaultValue), source, field.getContext());
if (toClearOfMarkers != null) recursiveSetGeneratedBy(toClearOfMarkers, null, null);
+ if (methodArgPos != null) {
+ for (int i = 0; i < methodArgPos.length; i++) {
+ ((JCMethodInvocation) toClearOfMarkers).args.get(i).pos = methodArgPos[i];
+ }
+ }
decl.mods.annotations = decl.mods.annotations.appendList(delegates);
if (addSuppressWarningsUnchecked) {
- addAnnotation(decl.mods, field, source.pos, source, field.getContext(), "java.lang.SuppressWarnings", treeMaker.NewArray(null, List.<JCExpression>nil(), List.<JCExpression>of(treeMaker.Literal("all"), treeMaker.Literal("unchecked"))));
+ ListBuffer<JCExpression> suppressions = new ListBuffer<JCExpression>();
+ if (!Boolean.FALSE.equals(field.getAst().readConfiguration(ConfigurationKeys.ADD_SUPPRESSWARNINGS_ANNOTATIONS))) {
+ suppressions.add(treeMaker.Literal("all"));
+ }
+ suppressions.add(treeMaker.Literal("unchecked"));
+ addAnnotation(decl.mods, field, source.pos, source, field.getContext(), "java.lang.SuppressWarnings", treeMaker.NewArray(null, List.<JCExpression>nil(), suppressions.toList()));
}
copyJavadoc(field, decl, CopyJavadoc.GETTER);
diff --git a/src/core/lombok/javac/handlers/HandleJacksonized.java b/src/core/lombok/javac/handlers/HandleJacksonized.java
index aff0bf63..0aa02d1b 100644
--- a/src/core/lombok/javac/handlers/HandleJacksonized.java
+++ b/src/core/lombok/javac/handlers/HandleJacksonized.java
@@ -149,7 +149,6 @@ public class HandleJacksonized extends JavacAnnotationHandler<Jacksonized> {
// @SuperBuilder? Make it package-private!
if (superBuilderAnnotationNode != null)
builderClass.mods.flags = builderClass.mods.flags & ~Flags.PRIVATE;
-
}
private String getBuilderClassName(JCAnnotation ast, JavacNode annotationNode, JavacNode annotatedNode, JCClassDecl td, AnnotationValues<Builder> builderAnnotation, JavacTreeMaker maker) {
diff --git a/src/core/lombok/javac/handlers/HandleLog.java b/src/core/lombok/javac/handlers/HandleLog.java
index 522f8576..3173b3ba 100644
--- a/src/core/lombok/javac/handlers/HandleLog.java
+++ b/src/core/lombok/javac/handlers/HandleLog.java
@@ -56,7 +56,7 @@ public class HandleLog {
throw new UnsupportedOperationException();
}
- public static void processAnnotation(LoggingFramework framework, AnnotationValues<?> annotation, JavacNode annotationNode, String loggerTopic) {
+ public static void processAnnotation(LoggingFramework framework, AnnotationValues<?> annotation, JavacNode annotationNode) {
deleteAnnotationIfNeccessary(annotationNode, framework.getAnnotationClass());
JavacNode typeNode = annotationNode.up();
@@ -76,14 +76,17 @@ public class HandleLog {
return;
}
- if (loggerTopic != null && loggerTopic.trim().isEmpty()) loggerTopic = null;
+ Object valueGuess = annotation.getValueGuess("topic");
+ JCExpression loggerTopic = (JCExpression) annotation.getActualExpression("topic");
+
+ if (valueGuess instanceof String && ((String) valueGuess).trim().isEmpty()) loggerTopic = null;
if (framework.getDeclaration().getParametersWithTopic() == null && loggerTopic != null) {
annotationNode.addError(framework.getAnnotationAsString() + " does not allow a topic.");
loggerTopic = null;
}
if (framework.getDeclaration().getParametersWithoutTopic() == null && loggerTopic == null) {
annotationNode.addError(framework.getAnnotationAsString() + " requires a topic.");
- loggerTopic = "";
+ loggerTopic = typeNode.getTreeMaker().Literal("");
}
JCFieldAccess loggingType = selfType(typeNode);
@@ -101,7 +104,7 @@ public class HandleLog {
return maker.Select(maker.Ident(name), typeNode.toName("class"));
}
- private static boolean createField(LoggingFramework framework, JavacNode typeNode, JCFieldAccess loggingType, JCTree source, String logFieldName, boolean useStatic, String loggerTopic) {
+ private static boolean createField(LoggingFramework framework, JavacNode typeNode, JCFieldAccess loggingType, JCTree source, String logFieldName, boolean useStatic, JCExpression loggerTopic) {
JavacTreeMaker maker = typeNode.getTreeMaker();
LogDeclaration logDeclaration = framework.getDeclaration();
@@ -121,7 +124,7 @@ public class HandleLog {
return true;
}
- private static JCExpression[] createFactoryParameters(JavacNode typeNode, JCFieldAccess loggingType, java.util.List<LogFactoryParameter> parameters, String loggerTopic) {
+ private static JCExpression[] createFactoryParameters(JavacNode typeNode, JCFieldAccess loggingType, java.util.List<LogFactoryParameter> parameters, JCExpression loggerTopic) {
JCExpression[] expressions = new JCExpression[parameters.size()];
JavacTreeMaker maker = typeNode.getTreeMaker();
@@ -136,7 +139,7 @@ public class HandleLog {
expressions[i] = maker.Apply(List.<JCExpression>nil(), method, List.<JCExpression>nil());
break;
case TOPIC:
- expressions[i] = maker.Literal(loggerTopic);
+ expressions[i] = (JCExpression) loggerTopic.clone();
break;
case NULL:
expressions[i] = maker.Literal(CTC_BOT, null);
@@ -156,7 +159,7 @@ public class HandleLog {
public static class HandleCommonsLog extends JavacAnnotationHandler<lombok.extern.apachecommons.CommonsLog> {
@Override public void handle(AnnotationValues<lombok.extern.apachecommons.CommonsLog> annotation, JCAnnotation ast, JavacNode annotationNode) {
handleFlagUsage(annotationNode, ConfigurationKeys.LOG_COMMONS_FLAG_USAGE, "@apachecommons.CommonsLog", ConfigurationKeys.LOG_ANY_FLAG_USAGE, "any @Log");
- processAnnotation(LoggingFramework.COMMONS, annotation, annotationNode, annotation.getInstance().topic());
+ processAnnotation(LoggingFramework.COMMONS, annotation, annotationNode);
}
}
@@ -167,7 +170,7 @@ public class HandleLog {
public static class HandleJulLog extends JavacAnnotationHandler<lombok.extern.java.Log> {
@Override public void handle(AnnotationValues<lombok.extern.java.Log> annotation, JCAnnotation ast, JavacNode annotationNode) {
handleFlagUsage(annotationNode, ConfigurationKeys.LOG_JUL_FLAG_USAGE, "@java.Log", ConfigurationKeys.LOG_ANY_FLAG_USAGE, "any @Log");
- processAnnotation(LoggingFramework.JUL, annotation, annotationNode, annotation.getInstance().topic());
+ processAnnotation(LoggingFramework.JUL, annotation, annotationNode);
}
}
@@ -178,7 +181,7 @@ public class HandleLog {
public static class HandleLog4jLog extends JavacAnnotationHandler<lombok.extern.log4j.Log4j> {
@Override public void handle(AnnotationValues<lombok.extern.log4j.Log4j> annotation, JCAnnotation ast, JavacNode annotationNode) {
handleFlagUsage(annotationNode, ConfigurationKeys.LOG_LOG4J_FLAG_USAGE, "@Log4j", ConfigurationKeys.LOG_ANY_FLAG_USAGE, "any @Log");
- processAnnotation(LoggingFramework.LOG4J, annotation, annotationNode, annotation.getInstance().topic());
+ processAnnotation(LoggingFramework.LOG4J, annotation, annotationNode);
}
}
@@ -189,7 +192,7 @@ public class HandleLog {
public static class HandleLog4j2Log extends JavacAnnotationHandler<lombok.extern.log4j.Log4j2> {
@Override public void handle(AnnotationValues<lombok.extern.log4j.Log4j2> annotation, JCAnnotation ast, JavacNode annotationNode) {
handleFlagUsage(annotationNode, ConfigurationKeys.LOG_LOG4J2_FLAG_USAGE, "@Log4j2", ConfigurationKeys.LOG_ANY_FLAG_USAGE, "any @Log");
- processAnnotation(LoggingFramework.LOG4J2, annotation, annotationNode, annotation.getInstance().topic());
+ processAnnotation(LoggingFramework.LOG4J2, annotation, annotationNode);
}
}
@@ -200,7 +203,7 @@ public class HandleLog {
public static class HandleSlf4jLog extends JavacAnnotationHandler<lombok.extern.slf4j.Slf4j> {
@Override public void handle(AnnotationValues<lombok.extern.slf4j.Slf4j> annotation, JCAnnotation ast, JavacNode annotationNode) {
handleFlagUsage(annotationNode, ConfigurationKeys.LOG_SLF4J_FLAG_USAGE, "@Slf4j", ConfigurationKeys.LOG_ANY_FLAG_USAGE, "any @Log");
- processAnnotation(LoggingFramework.SLF4J, annotation, annotationNode, annotation.getInstance().topic());
+ processAnnotation(LoggingFramework.SLF4J, annotation, annotationNode);
}
}
@@ -211,7 +214,7 @@ public class HandleLog {
public static class HandleXSlf4jLog extends JavacAnnotationHandler<lombok.extern.slf4j.XSlf4j> {
@Override public void handle(AnnotationValues<lombok.extern.slf4j.XSlf4j> annotation, JCAnnotation ast, JavacNode annotationNode) {
handleFlagUsage(annotationNode, ConfigurationKeys.LOG_XSLF4J_FLAG_USAGE, "@XSlf4j", ConfigurationKeys.LOG_ANY_FLAG_USAGE, "any @Log");
- processAnnotation(LoggingFramework.XSLF4J, annotation, annotationNode, annotation.getInstance().topic());
+ processAnnotation(LoggingFramework.XSLF4J, annotation, annotationNode);
}
}
@@ -222,7 +225,7 @@ public class HandleLog {
public static class HandleJBossLog extends JavacAnnotationHandler<lombok.extern.jbosslog.JBossLog> {
@Override public void handle(AnnotationValues<lombok.extern.jbosslog.JBossLog> annotation, JCAnnotation ast, JavacNode annotationNode) {
handleFlagUsage(annotationNode, ConfigurationKeys.LOG_JBOSSLOG_FLAG_USAGE, "@JBossLog", ConfigurationKeys.LOG_ANY_FLAG_USAGE, "any @Log");
- processAnnotation(LoggingFramework.JBOSSLOG, annotation, annotationNode, annotation.getInstance().topic());
+ processAnnotation(LoggingFramework.JBOSSLOG, annotation, annotationNode);
}
}
@@ -233,7 +236,7 @@ public class HandleLog {
public static class HandleFloggerLog extends JavacAnnotationHandler<lombok.extern.flogger.Flogger> {
@Override public void handle(AnnotationValues<lombok.extern.flogger.Flogger> annotation, JCAnnotation ast, JavacNode annotationNode) {
handleFlagUsage(annotationNode, ConfigurationKeys.LOG_FLOGGER_FLAG_USAGE, "@Flogger", ConfigurationKeys.LOG_ANY_FLAG_USAGE, "any @Log");
- processAnnotation(LoggingFramework.FLOGGER, annotation, annotationNode, "");
+ processAnnotation(LoggingFramework.FLOGGER, annotation, annotationNode);
}
}
@@ -250,7 +253,7 @@ public class HandleLog {
return;
}
LoggingFramework framework = new LoggingFramework(lombok.CustomLog.class, logDeclaration);
- processAnnotation(framework, annotation, annotationNode, annotation.getInstance().topic());
+ processAnnotation(framework, annotation, annotationNode);
}
}
}
diff --git a/src/core/lombok/javac/handlers/HandleSuperBuilder.java b/src/core/lombok/javac/handlers/HandleSuperBuilder.java
index 2dc3247d..f6bf9e1f 100644
--- a/src/core/lombok/javac/handlers/HandleSuperBuilder.java
+++ b/src/core/lombok/javac/handlers/HandleSuperBuilder.java
@@ -304,7 +304,7 @@ public class HandleSuperBuilder extends JavacAnnotationHandler<SuperBuilder> {
java.util.List<Included<JavacNode, ToString.Include>> fieldNodes = new ArrayList<Included<JavacNode, ToString.Include>>();
for (BuilderFieldData bfd : builderFields) {
for (JavacNode f : bfd.createdFields) {
- fieldNodes.add(new Included<JavacNode, ToString.Include>(f, null, true));
+ fieldNodes.add(new Included<JavacNode, ToString.Include>(f, null, true, false));
}
}
@@ -354,8 +354,10 @@ public class HandleSuperBuilder extends JavacAnnotationHandler<SuperBuilder> {
}
// Generate a constructor in the annotated class that takes a builder as argument.
- generateBuilderBasedConstructor(cfv, tdParent, typeParams, builderFields, annotationNode, builderClassName,
- superclassBuilderClassExpression != null);
+ if (!constructorExists(tdParent, builderClassName)) {
+ generateBuilderBasedConstructor(cfv, tdParent, typeParams, builderFields, annotationNode, builderClassName,
+ superclassBuilderClassExpression != null);
+ }
if (isAbstract) {
// Only non-abstract classes get the builder() and toBuilder() methods.
@@ -375,14 +377,14 @@ public class HandleSuperBuilder extends JavacAnnotationHandler<SuperBuilder> {
if (toBuilder) {
switch (methodExists(TO_BUILDER_METHOD_NAME, tdParent, 0)) {
case EXISTS_BY_USER:
- annotationNode.addWarning("Not generating toBuilder() as it already exists.");
- return;
+ break;
case NOT_EXISTS:
JCMethodDecl md = generateToBuilderMethod(cfv, builderClassName, builderImplClassName, annotationNode, tdParent, typeParams);
if (md != null) {
recursiveSetGeneratedBy(md, ast, annotationNode.getContext());
injectMethod(tdParent, md);
}
+ break;
default:
// Should not happen.
}
@@ -1070,4 +1072,33 @@ public class HandleSuperBuilder extends JavacAnnotationHandler<SuperBuilder> {
}
return typeParameter;
}
+
+ /**
+ * Checks if there is a manual constructor in the given type with a single parameter (builder).
+ */
+ private boolean constructorExists(JavacNode type, String builderClassName) {
+ if (type != null && type.get() instanceof JCClassDecl) {
+ for (JCTree def : ((JCClassDecl)type.get()).defs) {
+ if (def instanceof JCMethodDecl) {
+ JCMethodDecl md = (JCMethodDecl) def;
+ String name = md.name.toString();
+ boolean matches = name.equals("<init>");
+ if (isTolerate(type, md))
+ continue;
+ if (matches && md.params != null && md.params.length() == 1) {
+ // Cannot use typeMatches() here, because the parameter could be fully-qualified, partially-qualified, or not qualified.
+ // A string-compare of the last part should work. If it's a false-positive, users could still @Tolerate it.
+ String typeName = md.params.get(0).getType().toString();
+ int lastIndexOfDot = typeName.lastIndexOf('.');
+ if (lastIndexOfDot >= 0) {
+ typeName = typeName.substring(lastIndexOfDot+1);
+ }
+ if ((builderClassName+"<?, ?>").equals(typeName))
+ return true;
+ }
+ }
+ }
+ }
+ return false;
+ }
}
diff --git a/src/core/lombok/javac/handlers/HandleUtilityClass.java b/src/core/lombok/javac/handlers/HandleUtilityClass.java
index 95de4c47..5d651689 100644
--- a/src/core/lombok/javac/handlers/HandleUtilityClass.java
+++ b/src/core/lombok/javac/handlers/HandleUtilityClass.java
@@ -110,7 +110,7 @@ public class HandleUtilityClass extends JavacAnnotationHandler<UtilityClass> {
if (typeNode.up().getKind() == Kind.COMPILATION_UNIT) markStatic = false;
if (markStatic && typeNode.up().getKind() == Kind.TYPE) {
JCClassDecl typeDecl = (JCClassDecl) typeNode.up().get();
- if ((typeDecl.mods.flags & (Flags.INTERFACE | Flags.ANNOTATION | Flags.ENUM)) != 0) markStatic = false;
+ if ((typeDecl.mods.flags & (Flags.INTERFACE | Flags.ANNOTATION)) != 0) markStatic = false;
}
if (markStatic) classDecl.mods.flags |= Flags.STATIC;
diff --git a/src/core/lombok/javac/handlers/HandleWith.java b/src/core/lombok/javac/handlers/HandleWith.java
index 6977b10e..4e35a574 100644
--- a/src/core/lombok/javac/handlers/HandleWith.java
+++ b/src/core/lombok/javac/handlers/HandleWith.java
@@ -234,7 +234,8 @@ public class HandleWith extends JavacAnnotationHandler<With> {
long flags = JavacHandlerUtil.addFinalIfNeeded(Flags.PARAMETER, field.getContext());
List<JCAnnotation> annsOnParam = copyAnnotations(onParam).appendList(copyableAnnotations);
- JCVariableDecl param = maker.VarDef(maker.Modifiers(flags, annsOnParam), fieldDecl.name, fieldDecl.vartype, null);
+ JCExpression pType = cloneType(maker, fieldDecl.vartype, source.get(), source.getContext());
+ JCVariableDecl param = maker.VarDef(maker.Modifiers(flags, annsOnParam), fieldDecl.name, pType, null);
if (!makeAbstract) {
ListBuffer<JCStatement> statements = new ListBuffer<JCStatement>();
diff --git a/src/core/lombok/javac/handlers/JavacHandlerUtil.java b/src/core/lombok/javac/handlers/JavacHandlerUtil.java
index a3e876c4..efc4bf61 100644
--- a/src/core/lombok/javac/handlers/JavacHandlerUtil.java
+++ b/src/core/lombok/javac/handlers/JavacHandlerUtil.java
@@ -40,6 +40,7 @@ import java.util.regex.Pattern;
import javax.lang.model.element.Element;
+import com.sun.tools.javac.code.Attribute;
import com.sun.tools.javac.code.BoundKind;
import com.sun.tools.javac.code.Flags;
import com.sun.tools.javac.code.Scope;
@@ -1127,7 +1128,25 @@ public class JavacHandlerUtil {
}
}
}
-
+
+ static class JCAnnotationReflect {
+ private static Field ATTRIBUTE;
+
+ static {
+ try {
+ ATTRIBUTE = Permit.getField(JCAnnotation.class, "attribute");
+ } catch (Exception ignore) {}
+ }
+
+ static Attribute.Compound getAttribute(JCAnnotation jcAnnotation) {
+ try {
+ return (Attribute.Compound) ATTRIBUTE.get(jcAnnotation);
+ } catch (Exception e) {
+ return null;
+ }
+ }
+ }
+
// jdk9 support, types have changed, names stay the same
static class ClassSymbolMembersField {
private static final Field membersField;
@@ -1178,8 +1197,10 @@ public class JavacHandlerUtil {
* Also takes care of updating the JavacAST.
*/
public static void injectMethod(JavacNode typeNode, JCMethodDecl method, List<Type> paramTypes, Type returnType) {
+ Context context = typeNode.getContext();
+ Symtab symtab = Symtab.instance(context);
JCClassDecl type = (JCClassDecl) typeNode.get();
-
+
if (method.getName().contentEquals("<init>")) {
//Scan for default constructor, and remove it.
int idx = 0;
@@ -1196,20 +1217,53 @@ public class JavacHandlerUtil {
idx++;
}
}
-
+
addSuppressWarningsAll(method.mods, typeNode, method.pos, getGeneratedBy(method), typeNode.getContext());
addGenerated(method.mods, typeNode, method.pos, getGeneratedBy(method), typeNode.getContext());
type.defs = type.defs.append(method);
-
- fixMethodMirror(typeNode.getContext(), typeNode.getElement(), method.getModifiers().flags, method.getName(), paramTypes, returnType);
-
+
+ List<Symbol.VarSymbol> params = null;
+ if (method.getParameters() != null && !method.getParameters().isEmpty()) {
+ ListBuffer<Symbol.VarSymbol> newParams = new ListBuffer<Symbol.VarSymbol>();
+ for (int i = 0; i < method.getParameters().size(); i++) {
+ JCTree.JCVariableDecl param = method.getParameters().get(i);
+ if (param.sym == null) {
+ Type paramType = paramTypes == null ? param.getType().type : paramTypes.get(i);
+ VarSymbol varSymbol = new VarSymbol(param.mods.flags, param.name, paramType, symtab.noSymbol);
+ List<JCAnnotation> annotations = param.getModifiers().getAnnotations();
+ if (annotations != null && !annotations.isEmpty()) {
+ ListBuffer<Attribute.Compound> newAnnotations = new ListBuffer<Attribute.Compound>();
+ for (JCAnnotation jcAnnotation : annotations) {
+ Attribute.Compound attribute = JCAnnotationReflect.getAttribute(jcAnnotation);
+ if (attribute != null) {
+ newAnnotations.append(attribute);
+ }
+ }
+ if (annotations.length() == newAnnotations.length()) {
+ varSymbol.appendAttributes(newAnnotations.toList());
+ }
+ }
+ newParams.append(varSymbol);
+ } else {
+ newParams.append(param.sym);
+ }
+ }
+ params = newParams.toList();
+ if (params.length() != method.getParameters().length()) params = null;
+ }
+
+ fixMethodMirror(typeNode.getContext(), typeNode.getElement(), method.getModifiers().flags, method.getName(), paramTypes, params, returnType);
+
typeNode.add(method, Kind.METHOD);
}
-
- private static void fixMethodMirror(Context context, Element typeMirror, long access, Name methodName, List<Type> paramTypes, Type returnType) {
+
+ private static void fixMethodMirror(Context context, Element typeMirror, long access, Name methodName, List<Type> paramTypes, List<Symbol.VarSymbol> params, Type returnType) {
if (typeMirror == null || paramTypes == null || returnType == null) return;
ClassSymbol cs = (ClassSymbol) typeMirror;
MethodSymbol methodSymbol = new MethodSymbol(access, methodName, new MethodType(paramTypes, returnType, List.<Type>nil(), Symtab.instance(context).methodClass), cs);
+ if (params != null && !params.isEmpty()) {
+ methodSymbol.params = params;
+ }
ClassSymbolMembersField.enter(cs, methodSymbol);
}
@@ -1265,15 +1319,17 @@ public class JavacHandlerUtil {
public static void addSuppressWarningsAll(JCModifiers mods, JavacNode node, int pos, JCTree source, Context context) {
if (!LombokOptionsFactory.getDelombokOptions(context).getFormatPreferences().generateSuppressWarnings()) return;
- boolean addJLSuppress = true;
+ boolean addJLSuppress = !Boolean.FALSE.equals(node.getAst().readConfiguration(ConfigurationKeys.ADD_SUPPRESSWARNINGS_ANNOTATIONS));
- for (JCAnnotation ann : mods.annotations) {
- JCTree type = ann.getAnnotationType();
- Name n = null;
- if (type instanceof JCIdent) n = ((JCIdent) type).name;
- else if (type instanceof JCFieldAccess) n = ((JCFieldAccess) type).name;
- if (n != null && n.contentEquals("SuppressWarnings")) {
- addJLSuppress = false;
+ if (addJLSuppress) {
+ for (JCAnnotation ann : mods.annotations) {
+ JCTree type = ann.getAnnotationType();
+ Name n = null;
+ if (type instanceof JCIdent) n = ((JCIdent) type).name;
+ else if (type instanceof JCFieldAccess) n = ((JCFieldAccess) type).name;
+ if (n != null && n.contentEquals("SuppressWarnings")) {
+ addJLSuppress = false;
+ }
}
}
if (addJLSuppress) addAnnotation(mods, node, pos, source, context, "java.lang.SuppressWarnings", node.getTreeMaker().Literal("all"));
@@ -1520,6 +1576,20 @@ public class JavacHandlerUtil {
* Searches the given field node for annotations that are specifically intentioned to be copied to the setter.
*/
public static List<JCAnnotation> findCopyableToSetterAnnotations(JavacNode node) {
+ return findAnnotationsInList(node, COPY_TO_SETTER_ANNOTATIONS);
+ }
+
+ /**
+ * Searches the given field node for annotations that are specifically intentioned to be copied to the builder's singular method.
+ */
+ public static List<JCAnnotation> findCopyableToBuilderSingularSetterAnnotations(JavacNode node) {
+ return findAnnotationsInList(node, COPY_TO_BUILDER_SINGULAR_SETTER_ANNOTATIONS);
+ }
+
+ /**
+ * Searches the given field node for annotations that are in the given list, and returns those.
+ */
+ private static List<JCAnnotation> findAnnotationsInList(JavacNode node, java.util.List<String> annotationsToFind) {
JCAnnotation anno = null;
String annoName = null;
for (JavacNode child : node.down()) {
@@ -1537,7 +1607,7 @@ public class JavacHandlerUtil {
if (annoName == null) return List.nil();
if (!annoName.isEmpty()) {
- for (String bn : COPY_TO_SETTER_ANNOTATIONS) if (typeMatches(bn, node, anno.annotationType)) return List.of(anno);
+ for (String bn : annotationsToFind) if (typeMatches(bn, node, anno.annotationType)) return List.of(anno);
}
ListBuffer<JCAnnotation> result = new ListBuffer<JCAnnotation>();
@@ -1545,7 +1615,7 @@ public class JavacHandlerUtil {
if (child.getKind() == Kind.ANNOTATION) {
JCAnnotation annotation = (JCAnnotation) child.get();
boolean match = false;
- if (!match) for (String bn : COPY_TO_SETTER_ANNOTATIONS) if (typeMatches(bn, node, annotation.annotationType)) {
+ if (!match) for (String bn : annotationsToFind) if (typeMatches(bn, node, annotation.annotationType)) {
result.append(annotation);
break;
}
@@ -1935,6 +2005,7 @@ public class JavacHandlerUtil {
}
private static final Pattern SECTION_FINDER = Pattern.compile("^\\s*\\**\\s*[-*][-*]+\\s*([GS]ETTER|WITH(?:ER)?)\\s*[-*][-*]+\\s*\\**\\s*$", Pattern.MULTILINE | Pattern.CASE_INSENSITIVE);
+ private static final Pattern LINE_BREAK_FINDER = Pattern.compile("(\\r?\\n)?");
public static String stripLinesWithTagFromJavadoc(String javadoc, String regexpFragment) {
Pattern p = Pattern.compile("^\\s*\\**\\s*" + regexpFragment + "\\s*\\**\\s*$", Pattern.MULTILINE | Pattern.CASE_INSENSITIVE);
@@ -1943,27 +2014,29 @@ public class JavacHandlerUtil {
}
public static String stripSectionsFromJavadoc(String javadoc) {
- Matcher m = SECTION_FINDER.matcher(javadoc);
- if (!m.find()) return javadoc;
+ Matcher sectionMatcher = SECTION_FINDER.matcher(javadoc);
+ if (!sectionMatcher.find()) return javadoc;
- return javadoc.substring(0, m.start());
+ return javadoc.substring(0, sectionMatcher.start());
}
public static String getJavadocSection(String javadoc, String sectionNameSpec) {
String[] sectionNames = sectionNameSpec.split("\\|");
- Matcher m = SECTION_FINDER.matcher(javadoc);
+ Matcher sectionMatcher = SECTION_FINDER.matcher(javadoc);
+ Matcher lineBreakMatcher = LINE_BREAK_FINDER.matcher(javadoc);
int sectionStart = -1;
int sectionEnd = -1;
- while (m.find()) {
+ while (sectionMatcher.find()) {
boolean found = false;
- for (String sectionName : sectionNames) if (m.group(1).equalsIgnoreCase(sectionName)) {
+ for (String sectionName : sectionNames) if (sectionMatcher.group(1).equalsIgnoreCase(sectionName)) {
found = true;
break;
}
if (found) {
- sectionStart = m.end() + 1;
+ lineBreakMatcher.find(sectionMatcher.end());
+ sectionStart = lineBreakMatcher.end();
} else if (sectionStart != -1) {
- sectionEnd = m.start();
+ sectionEnd = sectionMatcher.start();
}
}
diff --git a/src/core/lombok/javac/handlers/JavacSingularsRecipes.java b/src/core/lombok/javac/handlers/JavacSingularsRecipes.java
index ba052b5a..7cd52c8c 100644
--- a/src/core/lombok/javac/handlers/JavacSingularsRecipes.java
+++ b/src/core/lombok/javac/handlers/JavacSingularsRecipes.java
@@ -182,11 +182,12 @@ public class JavacSingularsRecipes {
return this;
}
- protected JCModifiers makeMods(JavacTreeMaker maker, CheckerFrameworkVersion cfv, JavacNode node, boolean deprecate, AccessLevel access) {
+ protected JCModifiers makeMods(JavacTreeMaker maker, CheckerFrameworkVersion cfv, JavacNode node, boolean deprecate, AccessLevel access, List<JCAnnotation> methodAnnotations) {
JCAnnotation deprecateAnn = deprecate ? maker.Annotation(genJavaLangTypeRef(node, "Deprecated"), List.<JCExpression>nil()) : null;
JCAnnotation rrAnn = cfv.generateReturnsReceiver() ? maker.Annotation(genTypeRef(node, CheckerFrameworkVersion.NAME__RETURNS_RECEIVER), List.<JCExpression>nil()) : null;
List<JCAnnotation> annsOnMethod = (deprecateAnn != null && rrAnn != null) ? List.of(deprecateAnn, rrAnn) : deprecateAnn != null ? List.of(deprecateAnn) : rrAnn != null ? List.of(rrAnn) : List.<JCAnnotation>nil();
+ annsOnMethod = mergeAnnotations(annsOnMethod,methodAnnotations);
return maker.Modifiers(toJavacModifier(access), annsOnMethod);
}
@@ -271,10 +272,10 @@ public class JavacSingularsRecipes {
generateClearMethod(cfv, deprecate, maker, returnTypeMaker.make(), returnStatementMaker.make(), data, builderType, source, access);
}
- private void finishAndInjectMethod(CheckerFrameworkVersion cfv, JavacTreeMaker maker, JCExpression returnType, JCStatement returnStatement, SingularData data, JavacNode builderType, JCTree source, boolean deprecate, ListBuffer<JCStatement> statements, Name methodName, List<JCVariableDecl> jcVariableDecls, AccessLevel access, Boolean ignoreNullCollections) {
+ private void finishAndInjectMethod(CheckerFrameworkVersion cfv, JavacTreeMaker maker, JCExpression returnType, JCStatement returnStatement, SingularData data, JavacNode builderType, JCTree source, boolean deprecate, ListBuffer<JCStatement> statements, Name methodName, List<JCVariableDecl> jcVariableDecls, List<JCAnnotation> methodAnnotations, AccessLevel access, Boolean ignoreNullCollections) {
if (returnStatement != null) statements.append(returnStatement);
JCBlock body = maker.Block(0, statements.toList());
- JCModifiers mods = makeMods(maker, cfv, builderType, deprecate, access);
+ JCModifiers mods = makeMods(maker, cfv, builderType, deprecate, access, methodAnnotations);
List<JCTypeParameter> typeParams = List.nil();
List<JCExpression> thrown = List.nil();
@@ -298,7 +299,7 @@ public class JavacSingularsRecipes {
statements.add(clearStatement);
Name methodName = builderType.toName(HandlerUtil.buildAccessorName("clear", data.getPluralName().toString()));
- finishAndInjectMethod(cfv, maker, returnType, returnStatement, data, builderType, source, deprecate, statements, methodName, List.<JCVariableDecl>nil(), access, null);
+ finishAndInjectMethod(cfv, maker, returnType, returnStatement, data, builderType, source, deprecate, statements, methodName, List.<JCVariableDecl>nil(), List.<JCAnnotation>nil(), access, null);
}
protected abstract JCStatement generateClearStatements(JavacTreeMaker maker, SingularData data, JavacNode builderType);
@@ -312,7 +313,8 @@ public class JavacSingularsRecipes {
if (!setterPrefix.isEmpty()) name = builderType.toName(HandlerUtil.buildAccessorName(setterPrefix, name.toString()));
statements.prepend(createConstructBuilderVarIfNeeded(maker, data, builderType, source));
- finishAndInjectMethod(cfv, maker, returnType, returnStatement, data, builderType, source, deprecate, statements, name, params, access, null);
+ List<JCAnnotation> methodAnnotations = copyAnnotations(findCopyableToBuilderSingularSetterAnnotations(data.annotation.up()));
+ finishAndInjectMethod(cfv, maker, returnType, returnStatement, data, builderType, source, deprecate, statements, name, params, methodAnnotations, access, null);
}
protected JCVariableDecl generateSingularMethodParameter(int typeIndex, JavacTreeMaker maker, SingularData data, JavacNode builderType, JCTree source, Name name) {
@@ -357,8 +359,10 @@ public class JavacSingularsRecipes {
} else {
statements.prepend(JavacHandlerUtil.generateNullCheck(maker, null, data.getPluralName(), builderType, "%s cannot be null"));
}
+
+ List<JCAnnotation> methodAnnotations = copyAnnotations(findCopyableToSetterAnnotations(data.annotation.up()));
- finishAndInjectMethod(cfv, maker, returnType, returnStatement, data, builderType, source, deprecate, statements, name, List.of(param), access, ignoreNullCollections);
+ finishAndInjectMethod(cfv, maker, returnType, returnStatement, data, builderType, source, deprecate, statements, name, List.of(param), methodAnnotations, access, ignoreNullCollections);
}
protected ListBuffer<JCStatement> generatePluralMethodStatements(JavacTreeMaker maker, SingularData data, JavacNode builderType, JCTree source) {