aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/core/lombok/Builder.java4
-rw-r--r--src/core/lombok/ConfigurationKeys.java7
-rw-r--r--src/core/lombok/eclipse/handlers/EclipseHandlerUtil.java12
-rwxr-xr-xsrc/core/lombok/eclipse/handlers/HandleBuilder.java16
-rwxr-xr-xsrc/core/lombok/eclipse/handlers/HandleSuperBuilder.java6
-rw-r--r--src/core/lombok/javac/JavacResolution.java6
-rw-r--r--src/core/lombok/javac/handlers/HandleBuilder.java34
-rw-r--r--src/core/lombok/javac/handlers/HandleEqualsAndHashCode.java41
-rw-r--r--src/core/lombok/javac/handlers/HandleSuperBuilder.java10
-rw-r--r--src/delombok/lombok/delombok/PrettyPrinter.java3
-rw-r--r--src/eclipseAgent/lombok/eclipse/agent/EclipsePatcher.java21
-rw-r--r--src/eclipseAgent/lombok/eclipse/agent/PatchVal.java126
-rwxr-xr-xsrc/eclipseAgent/lombok/launch/PatchFixesHider.java12
13 files changed, 251 insertions, 47 deletions
diff --git a/src/core/lombok/Builder.java b/src/core/lombok/Builder.java
index a60af9ee..dfa5ecb5 100644
--- a/src/core/lombok/Builder.java
+++ b/src/core/lombok/Builder.java
@@ -129,9 +129,9 @@ public @interface Builder {
/**
* Name of the builder class.
*
- * Default for {@code @Builder} on types and constructors: {@code (TypeName)Builder}.
+ * Default for {@code @Builder} on types and constructors: see the configkey {@code lombok.builder.className}, which if not set defaults to {@code (TypeName)Builder}.
* <p>
- * Default for {@code @Builder} on methods: {@code (ReturnTypeName)Builder}.
+ * Default for {@code @Builder} on methods: see the configkey {@code lombok.builder.className}, which if not set defaults to {@code (ReturnTypeName)Builder}.
*
* @return Name of the builder class that will be generated (or if it already exists, will be filled with builder elements).
*/
diff --git a/src/core/lombok/ConfigurationKeys.java b/src/core/lombok/ConfigurationKeys.java
index ecfddb2a..dda0b54b 100644
--- a/src/core/lombok/ConfigurationKeys.java
+++ b/src/core/lombok/ConfigurationKeys.java
@@ -258,6 +258,13 @@ public class ConfigurationKeys {
// ----- Builder -----
/**
+ * lombok configuration: {@code lombok.builder.classNames} = &lt;String: aJavaIdentifier (optionally with a star as placeholder for the type name)&gt; (Default: {@code *Builder}).
+ *
+ * For any usage of the {@code @Builder} annotation without an explicit {@code builderClassName} parameter, this value is used to determine the name of the builder class to generate (or to adapt if such an inner class already exists).
+ */
+ public static final ConfigurationKey<String> BUILDER_CLASS_NAME = new ConfigurationKey<String>("lombok.builder.className", "Default name of the generated builder class. A * is replaced with the name of the relevant type (default = *Builder).") {};
+
+ /**
* lombok configuration: {@code lombok.builder.flagUsage} = {@code WARNING} | {@code ERROR}.
*
* If set, <em>any</em> usage of {@code @Builder} results in a warning / error.
diff --git a/src/core/lombok/eclipse/handlers/EclipseHandlerUtil.java b/src/core/lombok/eclipse/handlers/EclipseHandlerUtil.java
index f04c541f..1a0633bf 100644
--- a/src/core/lombok/eclipse/handlers/EclipseHandlerUtil.java
+++ b/src/core/lombok/eclipse/handlers/EclipseHandlerUtil.java
@@ -114,6 +114,7 @@ import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
import org.eclipse.jdt.internal.compiler.lookup.Binding;
import org.eclipse.jdt.internal.compiler.lookup.CaptureBinding;
import org.eclipse.jdt.internal.compiler.lookup.ParameterizedTypeBinding;
+import org.eclipse.jdt.internal.compiler.lookup.RawTypeBinding;
import org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding;
import org.eclipse.jdt.internal.compiler.lookup.TypeBinding;
import org.eclipse.jdt.internal.compiler.lookup.TypeConstants;
@@ -844,7 +845,6 @@ public class EclipseHandlerUtil {
}
public static TypeReference makeType(TypeBinding binding, ASTNode pos, boolean allowCompound) {
-
if (binding.getClass() == EclipseReflectiveMembers.INTERSECTION_BINDING) {
Object[] arr = (Object[]) EclipseReflectiveMembers.reflect(EclipseReflectiveMembers.INTERSECTION_BINDING_TYPES, binding);
binding = (TypeBinding) arr[0];
@@ -933,7 +933,12 @@ public class EclipseHandlerUtil {
WildcardBinding wildcard = (WildcardBinding) binding;
if (wildcard.boundKind == Wildcard.EXTENDS) {
if (!allowCompound) {
- return makeType(wildcard.bound, pos, false);
+ TypeBinding bound = wildcard.bound;
+ boolean isObject = bound.id == TypeIds.T_JavaLangObject;
+ TypeBinding[] otherBounds = wildcard.otherBounds;
+ if (isObject && otherBounds != null && otherBounds.length > 0) {
+ return makeType(otherBounds[0], pos, false);
+ } else return makeType(bound, pos, false);
} else {
Wildcard out = new Wildcard(Wildcard.EXTENDS);
setGeneratedBy(out, pos);
@@ -960,7 +965,8 @@ public class EclipseHandlerUtil {
// Finally, add however many nullTypeArgument[] arrays as that are missing, inverse the list, toArray it, and use that as PTR's typeArgument argument.
List<TypeReference[]> params = new ArrayList<TypeReference[]>();
- /* Calculate generics */ {
+ /* Calculate generics */
+ if (!(binding instanceof RawTypeBinding)) {
TypeBinding b = binding;
while (true) {
boolean isFinalStop = b.isLocalType() || !b.isMemberType() || b.enclosingType() == null;
diff --git a/src/core/lombok/eclipse/handlers/HandleBuilder.java b/src/core/lombok/eclipse/handlers/HandleBuilder.java
index 96431a83..aa9d2147 100755
--- a/src/core/lombok/eclipse/handlers/HandleBuilder.java
+++ b/src/core/lombok/eclipse/handlers/HandleBuilder.java
@@ -209,6 +209,10 @@ public class HandleBuilder extends EclipseAnnotationHandler<Builder> {
List<EclipseNode> nonFinalNonDefaultedFields = null;
+ if (builderClassName.isEmpty()) builderClassName = annotationNode.getAst().readConfiguration(ConfigurationKeys.BUILDER_CLASS_NAME);
+ if (builderClassName == null || builderClassName.isEmpty()) builderClassName = "*Builder";
+ boolean replaceNameInBuilderClassName = builderClassName.contains("*");
+
if (parent.get() instanceof TypeDeclaration) {
tdParent = parent;
TypeDeclaration td = (TypeDeclaration) tdParent.get();
@@ -265,7 +269,8 @@ public class HandleBuilder extends EclipseAnnotationHandler<Builder> {
typeParams = td.typeParameters;
thrownExceptions = null;
nameOfStaticBuilderMethod = null;
- if (builderClassName.isEmpty()) builderClassName = new String(td.name) + "Builder";
+ if (replaceNameInBuilderClassName) builderClassName = builderClassName.replace("*", new String(td.name));
+ replaceNameInBuilderClassName = false;
} else if (parent.get() instanceof ConstructorDeclaration) {
ConstructorDeclaration cd = (ConstructorDeclaration) parent.get();
if (cd.typeParameters != null && cd.typeParameters.length > 0) {
@@ -279,12 +284,13 @@ public class HandleBuilder extends EclipseAnnotationHandler<Builder> {
typeParams = td.typeParameters;
thrownExceptions = cd.thrownExceptions;
nameOfStaticBuilderMethod = null;
- if (builderClassName.isEmpty()) builderClassName = new String(cd.selector) + "Builder";
+ if (replaceNameInBuilderClassName) builderClassName = builderClassName.replace("*", new String(cd.selector));
+ replaceNameInBuilderClassName = false;
} else if (parent.get() instanceof MethodDeclaration) {
MethodDeclaration md = (MethodDeclaration) parent.get();
tdParent = parent.up();
isStatic = md.isStatic();
-
+
if (toBuilder) {
final String TO_BUILDER_NOT_SUPPORTED = "@Builder(toBuilder=true) is only supported if you return your own type.";
char[] token;
@@ -360,7 +366,7 @@ public class HandleBuilder extends EclipseAnnotationHandler<Builder> {
typeParams = md.typeParameters;
thrownExceptions = md.thrownExceptions;
nameOfStaticBuilderMethod = md.selector;
- if (builderClassName.isEmpty()) {
+ if (replaceNameInBuilderClassName) {
char[] token;
if (md.returnType instanceof QualifiedTypeReference) {
char[][] tokens = ((QualifiedTypeReference) md.returnType).tokens;
@@ -387,7 +393,7 @@ public class HandleBuilder extends EclipseAnnotationHandler<Builder> {
token = newToken;
}
- builderClassName = new String(token) + "Builder";
+ builderClassName = builderClassName.replace("*", new String(token));
}
} else {
annotationNode.addError("@Builder is only supported on types, constructors, and methods.");
diff --git a/src/core/lombok/eclipse/handlers/HandleSuperBuilder.java b/src/core/lombok/eclipse/handlers/HandleSuperBuilder.java
index 9a86d372..f204bc24 100755
--- a/src/core/lombok/eclipse/handlers/HandleSuperBuilder.java
+++ b/src/core/lombok/eclipse/handlers/HandleSuperBuilder.java
@@ -203,7 +203,9 @@ public class HandleSuperBuilder extends EclipseAnnotationHandler<SuperBuilder> {
}
// Set the names of the builder classes.
- String builderClassName = String.valueOf(td.name) + "Builder";
+ String builderClassNameTemplate = annotationNode.getAst().readConfiguration(ConfigurationKeys.BUILDER_CLASS_NAME);
+ if (builderClassNameTemplate == null || builderClassNameTemplate.isEmpty()) builderClassNameTemplate = "*Builder";
+ String builderClassName = builderClassNameTemplate.replace("*", String.valueOf(td.name));
String builderImplClassName = builderClassName + "Impl";
typeParams = td.typeParameters != null ? td.typeParameters : new TypeParameter[0];
@@ -228,7 +230,7 @@ public class HandleSuperBuilder extends EclipseAnnotationHandler<SuperBuilder> {
if (extendsClause instanceof QualifiedTypeReference) {
QualifiedTypeReference qualifiedTypeReference = (QualifiedTypeReference)extendsClause;
String superclassClassName = String.valueOf(qualifiedTypeReference.getLastToken());
- String superclassBuilderClassName = superclassClassName + "Builder";
+ String superclassBuilderClassName = builderClassNameTemplate.replace("*", superclassClassName);
char[][] tokens = Arrays.copyOf(qualifiedTypeReference.tokens, qualifiedTypeReference.tokens.length + 1);
tokens[tokens.length] = superclassBuilderClassName.toCharArray();
diff --git a/src/core/lombok/javac/JavacResolution.java b/src/core/lombok/javac/JavacResolution.java
index abbf6726..7f940d2a 100644
--- a/src/core/lombok/javac/JavacResolution.java
+++ b/src/core/lombok/javac/JavacResolution.java
@@ -336,7 +336,7 @@ public class JavacResolution {
if (type instanceof ClassType) {
List<Type> ifaces = ((ClassType) type).interfaces_field;
Type supertype = ((ClassType) type).supertype_field;
- if (ifaces != null && ifaces.length() == 1) {
+ if (isObject(supertype) && ifaces != null && ifaces.length() > 0) {
return typeToJCTree(ifaces.get(0), ast, allowCompound, allowVoid);
}
if (supertype != null) return typeToJCTree(supertype, ast, allowCompound, allowVoid);
@@ -402,6 +402,10 @@ public class JavacResolution {
return genericsToJCTreeNodes(generics, ast, replacement);
}
+ private static boolean isObject(Type supertype) {
+ return supertype.tsym.toString().equals("java.lang.Object");
+ }
+
private static JCExpression genericsToJCTreeNodes(List<Type> generics, JavacAST ast, JCExpression rawTypeNode) throws TypeNotConvertibleException {
if (generics != null && !generics.isEmpty()) {
ListBuffer<JCExpression> args = new ListBuffer<JCExpression>();
diff --git a/src/core/lombok/javac/handlers/HandleBuilder.java b/src/core/lombok/javac/handlers/HandleBuilder.java
index d758f602..b339c2ca 100644
--- a/src/core/lombok/javac/handlers/HandleBuilder.java
+++ b/src/core/lombok/javac/handlers/HandleBuilder.java
@@ -157,6 +157,10 @@ public class HandleBuilder extends JavacAnnotationHandler<Builder> {
ArrayList<JavacNode> nonFinalNonDefaultedFields = null;
+ if (builderClassName.isEmpty()) builderClassName = annotationNode.getAst().readConfiguration(ConfigurationKeys.BUILDER_CLASS_NAME);
+ if (builderClassName == null || builderClassName.isEmpty()) builderClassName = "*Builder";
+ boolean replaceNameInBuilderClassName = builderClassName.contains("*");
+
if (parent.get() instanceof JCClassDecl) {
tdParent = parent;
JCClassDecl td = (JCClassDecl) tdParent.get();
@@ -211,7 +215,8 @@ public class HandleBuilder extends JavacAnnotationHandler<Builder> {
typeParams = td.typarams;
thrownExceptions = List.nil();
nameOfBuilderMethod = null;
- if (builderClassName.isEmpty()) builderClassName = td.name.toString() + "Builder";
+ if (replaceNameInBuilderClassName) builderClassName = builderClassName.replace("*", td.name.toString());
+ replaceNameInBuilderClassName = false;
} else if (fillParametersFrom != null && fillParametersFrom.getName().toString().equals("<init>")) {
JCMethodDecl jmd = (JCMethodDecl) fillParametersFrom.get();
if (!jmd.typarams.isEmpty()) {
@@ -225,7 +230,8 @@ public class HandleBuilder extends JavacAnnotationHandler<Builder> {
typeParams = td.typarams;
thrownExceptions = jmd.thrown;
nameOfBuilderMethod = null;
- if (builderClassName.isEmpty()) builderClassName = td.name.toString() + "Builder";
+ if (replaceNameInBuilderClassName) builderClassName = builderClassName.replace("*", td.name.toString());
+ replaceNameInBuilderClassName = false;
} else if (fillParametersFrom != null) {
tdParent = parent.up();
JCClassDecl td = (JCClassDecl) tdParent.get();
@@ -239,9 +245,10 @@ public class HandleBuilder extends JavacAnnotationHandler<Builder> {
if (returnType instanceof JCTypeApply) {
returnType = cloneType(tdParent.getTreeMaker(), returnType, ast, annotationNode.getContext());
}
- if (builderClassName.isEmpty()) {
+ if (replaceNameInBuilderClassName) {
+ String replStr = null;
if (returnType instanceof JCFieldAccess) {
- builderClassName = ((JCFieldAccess) returnType).name.toString() + "Builder";
+ replStr = ((JCFieldAccess) returnType).name.toString();
} else if (returnType instanceof JCIdent) {
Name n = ((JCIdent) returnType).name;
@@ -251,27 +258,30 @@ public class HandleBuilder extends JavacAnnotationHandler<Builder> {
return;
}
}
- builderClassName = n.toString() + "Builder";
+ replStr = n.toString();
} else if (returnType instanceof JCPrimitiveTypeTree) {
- builderClassName = returnType.toString() + "Builder";
- if (Character.isLowerCase(builderClassName.charAt(0))) {
- builderClassName = Character.toTitleCase(builderClassName.charAt(0)) + builderClassName.substring(1);
+ replStr = returnType.toString();
+ if (Character.isLowerCase(replStr.charAt(0))) {
+ replStr = Character.toTitleCase(replStr.charAt(0)) + replStr.substring(1);
}
} else if (returnType instanceof JCTypeApply) {
JCExpression clazz = ((JCTypeApply) returnType).clazz;
if (clazz instanceof JCFieldAccess) {
- builderClassName = ((JCFieldAccess) clazz).name + "Builder";
+ replStr = ((JCFieldAccess) clazz).name.toString();
} else if (clazz instanceof JCIdent) {
- builderClassName = ((JCIdent) clazz).name + "Builder";
+ replStr = ((JCIdent) clazz).name.toString();
}
}
- if (builderClassName.isEmpty()) {
+ if (replStr == null || replStr.isEmpty()) {
// This shouldn't happen.
System.err.println("Lombok bug ID#20140614-1651: javac HandleBuilder: return type to name conversion failed: " + returnType.getClass());
- builderClassName = td.name.toString() + "Builder";
+ replStr = td.name.toString();
}
+ builderClassName = builderClassName.replace("*", replStr);
+ replaceNameInBuilderClassName = false;
}
+ if (replaceNameInBuilderClassName) builderClassName = builderClassName.replace("*", td.name.toString());
if (toBuilder) {
final String TO_BUILDER_NOT_SUPPORTED = "@Builder(toBuilder=true) is only supported if you return your own type.";
if (returnType instanceof JCArrayTypeTree) {
diff --git a/src/core/lombok/javac/handlers/HandleEqualsAndHashCode.java b/src/core/lombok/javac/handlers/HandleEqualsAndHashCode.java
index cb12bd4e..e4d7fa7f 100644
--- a/src/core/lombok/javac/handlers/HandleEqualsAndHashCode.java
+++ b/src/core/lombok/javac/handlers/HandleEqualsAndHashCode.java
@@ -25,6 +25,7 @@ import static lombok.core.handlers.HandlerUtil.handleFlagUsage;
import static lombok.javac.Javac.*;
import static lombok.javac.handlers.JavacHandlerUtil.*;
+import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
@@ -234,7 +235,7 @@ public class HandleEqualsAndHashCode extends JavacAnnotationHandler<EqualsAndHas
for (Included<JavacNode, EqualsAndHashCode.Include> member : members) {
JavacNode memberNode = member.getNode();
- JCExpression fType = getFieldType(memberNode, fieldAccess);
+ JCExpression fType = unnotate(getFieldType(memberNode, fieldAccess));
boolean isMethod = memberNode.getKind() == Kind.METHOD;
JCExpression fieldAccessor = isMethod ? createMethodAccessor(maker, memberNode) : createFieldAccessor(maker, memberNode, fieldAccess);
@@ -279,9 +280,10 @@ public class HandleEqualsAndHashCode extends JavacAnnotationHandler<EqualsAndHas
break;
}
} else if (fType instanceof JCArrayTypeTree) {
+ JCArrayTypeTree array = (JCArrayTypeTree) fType;
/* java.util.Arrays.deepHashCode(this.fieldName) //use just hashCode() for primitive arrays. */
- boolean multiDim = ((JCArrayTypeTree) fType).elemtype instanceof JCArrayTypeTree;
- boolean primitiveArray = ((JCArrayTypeTree) fType).elemtype instanceof JCPrimitiveTypeTree;
+ boolean multiDim = unnotate(array.elemtype) instanceof JCArrayTypeTree;
+ boolean primitiveArray = unnotate(array.elemtype) instanceof JCPrimitiveTypeTree;
boolean useDeepHC = multiDim || !primitiveArray;
JCExpression hcMethod = chainDots(typeNode, "java", "util", "Arrays", useDeepHC ? "deepHashCode" : "hashCode");
@@ -430,7 +432,7 @@ public class HandleEqualsAndHashCode extends JavacAnnotationHandler<EqualsAndHas
JavacNode memberNode = member.getNode();
boolean isMethod = memberNode.getKind() == Kind.METHOD;
- JCExpression fType = getFieldType(memberNode, fieldAccess);
+ JCExpression fType = unnotate(getFieldType(memberNode, fieldAccess));
JCExpression thisFieldAccessor = isMethod ? createMethodAccessor(maker, memberNode) : createFieldAccessor(maker, memberNode, fieldAccess);
JCExpression otherFieldAccessor = isMethod ? createMethodAccessor(maker, memberNode, maker.Ident(otherName)) : createFieldAccessor(maker, memberNode, fieldAccess, maker.Ident(otherName));
if (fType instanceof JCPrimitiveTypeTree) {
@@ -450,9 +452,10 @@ public class HandleEqualsAndHashCode extends JavacAnnotationHandler<EqualsAndHas
break;
}
} else if (fType instanceof JCArrayTypeTree) {
+ JCArrayTypeTree array = (JCArrayTypeTree) fType;
/* if (!java.util.Arrays.deepEquals(this.fieldName, other.fieldName)) return false; //use equals for primitive arrays. */
- boolean multiDim = ((JCArrayTypeTree) fType).elemtype instanceof JCArrayTypeTree;
- boolean primitiveArray = ((JCArrayTypeTree) fType).elemtype instanceof JCPrimitiveTypeTree;
+ boolean multiDim = unnotate(array.elemtype) instanceof JCArrayTypeTree;
+ boolean primitiveArray = unnotate(array.elemtype) instanceof JCPrimitiveTypeTree;
boolean useDeepEquals = multiDim || !primitiveArray;
JCExpression eqMethod = chainDots(typeNode, "java", "util", "Arrays", useDeepEquals ? "deepEquals" : "equals");
@@ -522,4 +525,30 @@ public class HandleEqualsAndHashCode extends JavacAnnotationHandler<EqualsAndHas
public JCStatement returnBool(JavacTreeMaker maker, boolean bool) {
return maker.Return(maker.Literal(CTC_BOOLEAN, bool ? 1 : 0));
}
+
+ private boolean jcAnnotatedTypeInit;
+ private Class<?> jcAnnotatedTypeClass = null;
+ private Field jcAnnotatedTypeUnderlyingTypeField = null;
+
+ private JCExpression unnotate(JCExpression type) {
+ if (!isJcAnnotatedType(type)) return type;
+ if (jcAnnotatedTypeUnderlyingTypeField == null) return type;
+ try {
+ return (JCExpression) jcAnnotatedTypeUnderlyingTypeField.get(type);
+ } catch (Exception ignore) {}
+ return type;
+ }
+
+ private boolean isJcAnnotatedType(JCExpression o) {
+ if (o == null) return false;
+ if (!jcAnnotatedTypeInit) {
+ try {
+ jcAnnotatedTypeClass = Class.forName("com.sun.tools.javac.tree.JCTree$JCAnnotatedType", false, o.getClass().getClassLoader());
+ jcAnnotatedTypeUnderlyingTypeField = jcAnnotatedTypeClass.getDeclaredField("underlyingType");
+ }
+ catch (Exception ignore) {}
+ jcAnnotatedTypeInit = true;
+ }
+ return jcAnnotatedTypeClass == o.getClass();
+ }
}
diff --git a/src/core/lombok/javac/handlers/HandleSuperBuilder.java b/src/core/lombok/javac/handlers/HandleSuperBuilder.java
index 0fcaa5f8..9120fa07 100644
--- a/src/core/lombok/javac/handlers/HandleSuperBuilder.java
+++ b/src/core/lombok/javac/handlers/HandleSuperBuilder.java
@@ -177,7 +177,9 @@ public class HandleSuperBuilder extends JavacAnnotationHandler<SuperBuilder> {
}
// Set the names of the builder classes.
- String builderClassName = td.name.toString() + "Builder";
+ String builderClassNameTemplate = annotationNode.getAst().readConfiguration(ConfigurationKeys.BUILDER_CLASS_NAME);
+ if (builderClassNameTemplate == null || builderClassNameTemplate.isEmpty()) builderClassNameTemplate = "*Builder";
+ String builderClassName = builderClassNameTemplate.replace("*", td.name.toString());
String builderImplClassName = builderClassName + "Impl";
JCTree extendsClause = Javac.getExtendsClause(td);
JCExpression superclassBuilderClassExpression = null;
@@ -189,11 +191,11 @@ public class HandleSuperBuilder extends JavacAnnotationHandler<SuperBuilder> {
}
if (extendsClause instanceof JCFieldAccess) {
Name superclassClassName = ((JCFieldAccess)extendsClause).getIdentifier();
- String superclassBuilderClassName = superclassClassName + "Builder";
+ String superclassBuilderClassName = builderClassNameTemplate.replace("*", superclassClassName);
superclassBuilderClassExpression = tdParent.getTreeMaker().Select((JCFieldAccess) extendsClause,
- tdParent.toName(superclassBuilderClassName));
+ tdParent.toName(superclassBuilderClassName));
} else if (extendsClause != null) {
- String superclassBuilderClassName = extendsClause.toString() + "Builder";
+ String superclassBuilderClassName = builderClassNameTemplate.replace("*", extendsClause.toString());
superclassBuilderClassExpression = chainDots(tdParent, extendsClause.toString(), superclassBuilderClassName);
}
// If there is no superclass, superclassBuilderClassExpression is still == null at this point.
diff --git a/src/delombok/lombok/delombok/PrettyPrinter.java b/src/delombok/lombok/delombok/PrettyPrinter.java
index 3477c51c..1532319f 100644
--- a/src/delombok/lombok/delombok/PrettyPrinter.java
+++ b/src/delombok/lombok/delombok/PrettyPrinter.java
@@ -692,7 +692,10 @@ public class PrettyPrinter extends JCTree.Visitor {
@Override public void visitTypeApply(JCTypeApply tree) {
print(tree.clazz);
print("<");
+ boolean temp = innermostArrayBracketsAreVarargs;
+ innermostArrayBracketsAreVarargs = false;
print(tree.arguments, ", ");
+ innermostArrayBracketsAreVarargs = temp;
print(">");
}
diff --git a/src/eclipseAgent/lombok/eclipse/agent/EclipsePatcher.java b/src/eclipseAgent/lombok/eclipse/agent/EclipsePatcher.java
index 0e74dfaf..24c1216e 100644
--- a/src/eclipseAgent/lombok/eclipse/agent/EclipsePatcher.java
+++ b/src/eclipseAgent/lombok/eclipse/agent/EclipsePatcher.java
@@ -122,6 +122,7 @@ public class EclipsePatcher implements AgentLauncher.AgentLaunchable {
patchEcjTransformers(sm, ecjOnly);
patchExtensionMethod(sm, ecjOnly);
patchRenameField(sm);
+ patchNullCheck(sm);
if (reloadExistingClasses) sm.reloadClasses(instrumentation);
}
@@ -774,4 +775,24 @@ public class EclipsePatcher implements AgentLauncher.AgentLaunchable {
.build());
}
}
+
+ private static void patchNullCheck(ScriptManager sm) {
+ /* Avoid warnings caused by the null check generated for lombok.NonNull if NonNullByDefault is used. */
+
+ /* Avoid "Redundant null check: comparing '@NonNull String' against null" */
+ sm.addScript(ScriptBuilder.exitEarly()
+ .target(new MethodTarget("org.eclipse.jdt.internal.compiler.problem.ProblemReporter", "expressionNonNullComparison", "boolean", "org.eclipse.jdt.internal.compiler.ast.Expression", "boolean"))
+ .decisionMethod(new Hook("lombok.launch.PatchFixesHider$PatchFixes", "isGenerated", "boolean", "org.eclipse.jdt.internal.compiler.ast.ASTNode"))
+ .valueMethod(new Hook("lombok.launch.PatchFixesHider$PatchFixes", "returnTrue", "boolean", "java.lang.Object"))
+ .request(StackRequest.PARAM1)
+ .transplant().build());
+
+ /* Avoid "Dead code" */
+ sm.addScript(ScriptBuilder.exitEarly()
+ .target(new MethodTarget("org.eclipse.jdt.internal.compiler.problem.ProblemReporter", "fakeReachable", "void", "org.eclipse.jdt.internal.compiler.ast.ASTNode"))
+ .decisionMethod(new Hook("lombok.launch.PatchFixesHider$PatchFixes", "isGenerated", "boolean", "org.eclipse.jdt.internal.compiler.ast.ASTNode"))
+ .request(StackRequest.PARAM1)
+ .transplant().build());
+ }
+
}
diff --git a/src/eclipseAgent/lombok/eclipse/agent/PatchVal.java b/src/eclipseAgent/lombok/eclipse/agent/PatchVal.java
index b32c99cd..0c66bb31 100644
--- a/src/eclipseAgent/lombok/eclipse/agent/PatchVal.java
+++ b/src/eclipseAgent/lombok/eclipse/agent/PatchVal.java
@@ -21,16 +21,27 @@
*/
package lombok.eclipse.agent;
+import lombok.permit.Permit;
+import org.eclipse.jdt.core.compiler.CategorizedProblem;
+import org.eclipse.jdt.internal.compiler.CompilationResult;
+import org.eclipse.jdt.internal.compiler.DefaultErrorHandlingPolicies;
import org.eclipse.jdt.internal.compiler.ast.ASTNode;
+import org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration;
import org.eclipse.jdt.internal.compiler.ast.Annotation;
+import org.eclipse.jdt.internal.compiler.ast.CompilationUnitDeclaration;
+import org.eclipse.jdt.internal.compiler.ast.ConditionalExpression;
import org.eclipse.jdt.internal.compiler.ast.Expression;
import org.eclipse.jdt.internal.compiler.ast.ForeachStatement;
+import org.eclipse.jdt.internal.compiler.ast.FunctionalExpression;
import org.eclipse.jdt.internal.compiler.ast.ImportReference;
+import org.eclipse.jdt.internal.compiler.ast.LambdaExpression;
import org.eclipse.jdt.internal.compiler.ast.LocalDeclaration;
import org.eclipse.jdt.internal.compiler.ast.QualifiedTypeReference;
import org.eclipse.jdt.internal.compiler.ast.SingleTypeReference;
+import org.eclipse.jdt.internal.compiler.ast.TypeDeclaration;
import org.eclipse.jdt.internal.compiler.ast.TypeReference;
import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
+import org.eclipse.jdt.internal.compiler.impl.ReferenceContext;
import org.eclipse.jdt.internal.compiler.lookup.ArrayBinding;
import org.eclipse.jdt.internal.compiler.lookup.Binding;
import org.eclipse.jdt.internal.compiler.lookup.BlockScope;
@@ -42,13 +53,15 @@ import org.eclipse.jdt.internal.compiler.lookup.Scope;
import org.eclipse.jdt.internal.compiler.lookup.TypeBinding;
import org.eclipse.jdt.internal.compiler.lookup.TypeConstants;
import org.eclipse.jdt.internal.compiler.lookup.TypeIds;
-
-import lombok.permit.Permit;
+import org.eclipse.jdt.internal.compiler.problem.AbortCompilation;
+import org.eclipse.jdt.internal.compiler.problem.ProblemReporter;
import java.lang.reflect.Field;
+import static lombok.Lombok.sneakyThrow;
import static lombok.eclipse.Eclipse.poss;
import static lombok.eclipse.handlers.EclipseHandlerUtil.makeType;
+import static org.eclipse.jdt.core.compiler.CategorizedProblem.CAT_TYPE;
public class PatchVal {
@@ -263,15 +276,11 @@ public class PatchVal {
resolved = null;
}
if (resolved != null) {
- if (resolved.getClass().getSimpleName().startsWith("IntersectionTypeBinding")) {
- // We intentionally deconstruct these into simply 'Object', because picking an arbitrary type amongst the intersection feels worse.
- } else {
- try {
- replacement = makeType(resolved, local.type, false);
- if (!decomponent) init.resolvedType = replacement.resolveType(scope);
- } catch (Exception e) {
- // Some type thing failed.
- }
+ try {
+ replacement = makeType(resolved, local.type, false);
+ if (!decomponent) init.resolvedType = replacement.resolveType(scope);
+ } catch (Exception e) {
+ // Some type thing failed.
}
}
}
@@ -357,11 +366,106 @@ public class PatchVal {
}
private static TypeBinding resolveForExpression(Expression collection, BlockScope scope) {
+ CompilationUnitDeclaration referenceContext = scope.compilationUnitScope().referenceContext;
+ ProblemReporter oldProblemReporter = referenceContext.problemReporter;
+ referenceContext.problemReporter = new ProblemReporter(DefaultErrorHandlingPolicies.exitOnFirstError(),
+ oldProblemReporter.options, oldProblemReporter.problemFactory);
try {
return collection.resolveType(scope);
} catch (ArrayIndexOutOfBoundsException e) {
// Known cause of issues; for example: val e = mth("X"), where mth takes 2 arguments.
return null;
+ } catch (AbortCompilation e) {
+ if (collection instanceof ConditionalExpression) {
+ ConditionalExpression cexp = (ConditionalExpression) collection;
+ Expression ifTrue = cexp.valueIfTrue;
+ Expression ifFalse = cexp.valueIfFalse;
+ TypeBinding ifTrueResolvedType = ifTrue.resolvedType;
+ CategorizedProblem problem = e.problem;
+ if (ifTrueResolvedType != null && ifFalse.resolvedType == null && problem.getCategoryID() == CAT_TYPE) {
+ CompilationResult compilationResult = e.compilationResult;
+ CategorizedProblem[] problems = compilationResult.problems;
+ int problemCount = compilationResult.problemCount;
+ for (int i = 0; i < problemCount; ++i) {
+ if (problems[i] == problem) {
+ problems[i] = null;
+ if (i + 1 < problemCount) {
+ System.arraycopy(problems, i + 1, problems, i, problemCount - i + 1);
+ }
+ break;
+ }
+ }
+ compilationResult.removeProblem(problem);
+ if (!compilationResult.hasErrors()) {
+ clearIgnoreFurtherInvestigationField(scope.referenceContext());
+ setValue(getField(CompilationResult.class, "hasMandatoryErrors"), compilationResult, false);
+ }
+
+ if (ifFalse instanceof FunctionalExpression) {
+ FunctionalExpression functionalExpression = (FunctionalExpression) ifFalse;
+ functionalExpression.setExpectedType(ifTrueResolvedType);
+ }
+ if (ifFalse.resolvedType == null) {
+ ifFalse.resolve(scope);
+ }
+
+ return ifTrueResolvedType;
+ }
+ }
+ throw e;
+ } finally {
+ referenceContext.problemReporter = oldProblemReporter;
+ }
+ }
+
+ private static void clearIgnoreFurtherInvestigationField(ReferenceContext currentContext) {
+ if (currentContext instanceof AbstractMethodDeclaration) {
+ AbstractMethodDeclaration methodDeclaration = (AbstractMethodDeclaration) currentContext;
+ methodDeclaration.ignoreFurtherInvestigation = false;
+ } else if (currentContext instanceof LambdaExpression) {
+ LambdaExpression lambdaExpression = (LambdaExpression) currentContext;
+ setValue(getField(LambdaExpression.class, "ignoreFurtherInvestigation"), lambdaExpression, false);
+
+ Scope parent = lambdaExpression.enclosingScope.parent;
+ while (parent != null) {
+ switch(parent.kind) {
+ case Scope.CLASS_SCOPE:
+ case Scope.METHOD_SCOPE:
+ ReferenceContext parentAST = parent.referenceContext();
+ if (parentAST != lambdaExpression) {
+ clearIgnoreFurtherInvestigationField(parentAST);
+ return;
+ }
+ default:
+ parent = parent.parent;
+ break;
+ }
+ }
+
+ } else if (currentContext instanceof TypeDeclaration) {
+ TypeDeclaration typeDeclaration = (TypeDeclaration) currentContext;
+ typeDeclaration.ignoreFurtherInvestigation = false;
+ } else if (currentContext instanceof CompilationUnitDeclaration) {
+ CompilationUnitDeclaration typeDeclaration = (CompilationUnitDeclaration) currentContext;
+ typeDeclaration.ignoreFurtherInvestigation = false;
+ } else {
+ throw new UnsupportedOperationException("clearIgnoreFurtherInvestigationField for " + currentContext.getClass());
+ }
+ }
+
+ private static void setValue(Field field, Object object, Object value) {
+ try {
+ field.set(object, value);
+ } catch (IllegalAccessException e) {
+ throw sneakyThrow(e);
+ }
+ }
+
+ private static Field getField(Class clazz, String name) {
+ try {
+ return Permit.getField(clazz, name);
+ } catch (NoSuchFieldException e) {
+ throw sneakyThrow(e);
}
}
}
diff --git a/src/eclipseAgent/lombok/launch/PatchFixesHider.java b/src/eclipseAgent/lombok/launch/PatchFixesHider.java
index 3741aba8..563beab1 100755
--- a/src/eclipseAgent/lombok/launch/PatchFixesHider.java
+++ b/src/eclipseAgent/lombok/launch/PatchFixesHider.java
@@ -315,7 +315,17 @@ final class PatchFixesHider {
}
return result;
}
-
+
+ public static boolean isGenerated(org.eclipse.jdt.internal.compiler.ast.ASTNode node) {
+ boolean result = false;
+ try {
+ result = node.getClass().getField("$generatedBy").get(node) != null;
+ } catch (Exception e) {
+ // better to assume it isn't generated
+ }
+ return result;
+ }
+
public static boolean isListRewriteOnGeneratedNode(org.eclipse.jdt.core.dom.rewrite.ListRewrite rewrite) {
return isGenerated(rewrite.getParent());
}