aboutsummaryrefslogtreecommitdiff
path: root/src/eclipseAgent
diff options
context:
space:
mode:
Diffstat (limited to 'src/eclipseAgent')
-rw-r--r--src/eclipseAgent/lombok/eclipse/agent/EclipsePatcher.java71
-rw-r--r--src/eclipseAgent/lombok/eclipse/agent/PatchDelegate.java75
-rw-r--r--src/eclipseAgent/lombok/eclipse/agent/PatchVal.java130
-rw-r--r--src/eclipseAgent/lombok/eclipse/agent/PatchValEclipse.java22
-rw-r--r--src/eclipseAgent/lombok/launch/PatchFixesHider.java52
5 files changed, 273 insertions, 77 deletions
diff --git a/src/eclipseAgent/lombok/eclipse/agent/EclipsePatcher.java b/src/eclipseAgent/lombok/eclipse/agent/EclipsePatcher.java
index 7c538b6f..a6d745b6 100644
--- a/src/eclipseAgent/lombok/eclipse/agent/EclipsePatcher.java
+++ b/src/eclipseAgent/lombok/eclipse/agent/EclipsePatcher.java
@@ -23,12 +23,16 @@ package lombok.eclipse.agent;
import static lombok.patcher.scripts.ScriptBuilder.*;
+import java.io.File;
import java.lang.instrument.Instrumentation;
+import java.net.URLClassLoader;
+import java.security.ProtectionDomain;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import lombok.core.AgentLauncher;
+import lombok.patcher.Filter;
import lombok.patcher.Hook;
import lombok.patcher.MethodTarget;
import lombok.patcher.ScriptManager;
@@ -74,7 +78,16 @@ public class EclipsePatcher implements AgentLauncher.AgentLaunchable {
private static void registerPatchScripts(Instrumentation instrumentation, boolean reloadExistingClasses, boolean ecjOnly, Class<?> launchingContext) {
ScriptManager sm = new ScriptManager();
sm.registerTransformer(instrumentation);
- final boolean forceBaseResourceNames = !"".equals(System.getProperty("shadow.override.lombok", ""));
+ sm.setFilter(new Filter() {
+ @Override public boolean shouldTransform(ClassLoader loader, String className, Class<?> classBeingDefined, ProtectionDomain protectionDomain, byte[] classfileBuffer) {
+ if (!(loader instanceof URLClassLoader)) return true;
+ ClassLoader parent = loader.getParent();
+ if (parent == null) return true;
+ return !parent.getClass().getName().startsWith("org.eclipse.jdt.apt.core.internal.AnnotationProcessorFactoryLoader");
+ }
+ });
+
+ final boolean forceBaseResourceNames = shouldForceBaseResourceNames();
sm.setTransplantMapper(new TransplantMapper() {
public String mapResourceName(int classFileFormatVersion, String resourceName) {
if (classFileFormatVersion < 50 || forceBaseResourceNames) return resourceName;
@@ -93,7 +106,7 @@ public class EclipsePatcher implements AgentLauncher.AgentLaunchable {
patchHideGeneratedNodes(sm);
patchPostCompileHookEclipse(sm);
patchFixSourceTypeConverter(sm);
- patchDisableLombokForCodeFormatterAndCleanup(sm);
+ patchDisableLombokForCodeCleanup(sm);
patchListRewriteHandleGeneratedMethods(sm);
patchSyntaxAndOccurrencesHighlighting(sm);
patchSortMembersOperation(sm);
@@ -108,10 +121,37 @@ public class EclipsePatcher implements AgentLauncher.AgentLaunchable {
patchLombokizeAST(sm);
patchEcjTransformers(sm, ecjOnly);
patchExtensionMethod(sm, ecjOnly);
+ patchRenameField(sm);
if (reloadExistingClasses) sm.reloadClasses(instrumentation);
}
+ private static boolean shouldForceBaseResourceNames() {
+ String shadowOverride = System.getProperty("shadow.override.lombok", "");
+ if (shadowOverride == null || shadowOverride.length() == 0) return false;
+ for (String part : shadowOverride.split("\\s*" + (File.pathSeparatorChar == ';' ? ";" : ":") + "\\s*")) {
+ if (part.equalsIgnoreCase("lombok.jar")) return false;
+ }
+ return true;
+ }
+
+ private static void patchRenameField(ScriptManager sm) {
+ /* RefactoringSearchEngine.search will not return results when renaming field and Data Annotation is present. Return a fake Element to make checks pass */
+ sm.addScript(ScriptBuilder.wrapMethodCall()
+ .target(new MethodTarget("org.eclipse.jdt.internal.corext.refactoring.rename.RenameFieldProcessor", "checkAccessorDeclarations", "org.eclipse.ltk.core.refactoring.RefactoringStatus", "org.eclipse.core.runtime.IProgressMonitor", "org.eclipse.jdt.core.IMethod"))
+ .methodToWrap(new Hook("org.eclipse.jdt.internal.corext.refactoring.RefactoringSearchEngine", "search", "org.eclipse.jdt.internal.corext.refactoring.SearchResultGroup[]", "org.eclipse.jdt.core.search.SearchPattern","org.eclipse.jdt.core.search.IJavaSearchScope","org.eclipse.core.runtime.IProgressMonitor","org.eclipse.ltk.core.refactoring.RefactoringStatus"))
+ .wrapMethod(new Hook("lombok.launch.PatchFixesHider$PatchFixes", "createFakeSearchResult", "org.eclipse.jdt.internal.corext.refactoring.SearchResultGroup[]", "org.eclipse.jdt.internal.corext.refactoring.SearchResultGroup[]", "java.lang.Object"))
+ .requestExtra(StackRequest.THIS)
+ .transplant().build());
+
+ /* Filter search results which are Generated and based on Fields, e.g. Generated getters/setters */
+ sm.addScript(ScriptBuilder.wrapMethodCall()
+ .target(new MethodTarget("org.eclipse.jdt.internal.corext.refactoring.rename.RenameFieldProcessor", "addAccessorOccurrences", "void", "org.eclipse.core.runtime.IProgressMonitor", "org.eclipse.jdt.core.IMethod", "java.lang.String","java.lang.String","org.eclipse.ltk.core.refactoring.RefactoringStatus"))
+ .methodToWrap(new Hook("org.eclipse.jdt.internal.corext.refactoring.SearchResultGroup", "getSearchResults", "org.eclipse.jdt.core.search.SearchMatch[]"))
+ .wrapMethod(new Hook("lombok.launch.PatchFixesHider$PatchFixes", "removeGenerated", "org.eclipse.jdt.core.search.SearchMatch[]", "org.eclipse.jdt.core.search.SearchMatch[]"))
+ .transplant().build());
+ }
+
private static void patchExtractInterface(ScriptManager sm) {
/* Fix sourceEnding for generated nodes to avoid null pointer */
sm.addScript(ScriptBuilder.wrapMethodCall()
@@ -184,13 +224,7 @@ public class EclipsePatcher implements AgentLauncher.AgentLaunchable {
.build());
}
- private static void patchDisableLombokForCodeFormatterAndCleanup(ScriptManager sm) {
- sm.addScript(ScriptBuilder.setSymbolDuringMethodCall()
- .target(new MethodTarget("org.eclipse.jdt.internal.formatter.DefaultCodeFormatter", "formatCompilationUnit"))
- .callToWrap(new Hook("org.eclipse.jdt.internal.core.util.CodeSnippetParsingUtil", "parseCompilationUnit", "org.eclipse.jdt.internal.compiler.ast.CompilationUnitDeclaration", "char[]", "java.util.Map", "boolean"))
- .symbol("lombok.disable")
- .build());
-
+ private static void patchDisableLombokForCodeCleanup(ScriptManager sm) {
sm.addScript(ScriptBuilder.exitEarly()
.target(new MethodTarget("org.eclipse.jdt.internal.corext.fix.ControlStatementsFix$ControlStatementFinder", "visit", "boolean", "org.eclipse.jdt.core.dom.DoStatement"))
.target(new MethodTarget("org.eclipse.jdt.internal.corext.fix.ControlStatementsFix$ControlStatementFinder", "visit", "boolean", "org.eclipse.jdt.core.dom.EnhancedForStatement"))
@@ -309,18 +343,19 @@ public class EclipsePatcher implements AgentLauncher.AgentLaunchable {
}
private static void patchFormatters(ScriptManager sm) {
+ // before Eclipse Mars
sm.addScript(ScriptBuilder.setSymbolDuringMethodCall()
- .target(new MethodTarget("org.eclipse.jdt.internal.ui.text.java.JavaFormattingStrategy", "format", "void"))
- .callToWrap(new Hook("org.eclipse.jdt.internal.corext.util.CodeFormatterUtil", "reformat", "org.eclipse.text.edits.TextEdit",
- "int", "java.lang.String", "int", "int", "int", "java.lang.String", "java.util.Map"))
- .symbol("lombok.disable").build());
+ .target(new MethodTarget("org.eclipse.jdt.internal.formatter.DefaultCodeFormatter", "formatCompilationUnit"))
+ .callToWrap(new Hook("org.eclipse.jdt.internal.core.util.CodeSnippetParsingUtil", "parseCompilationUnit", "org.eclipse.jdt.internal.compiler.ast.CompilationUnitDeclaration", "char[]", "java.util.Map", "boolean"))
+ .symbol("lombok.disable")
+ .build());
+ // Eclipse Mars and beyond
sm.addScript(ScriptBuilder.setSymbolDuringMethodCall()
- .target(new MethodTarget("org.eclipse.jdt.internal.corext.fix.CodeFormatFix", "createCleanUp", "org.eclipse.jdt.ui.cleanup.ICleanUpFix",
- "org.eclipse.jdt.core.ICompilationUnit", "org.eclipse.jface.text.IRegion[]", "boolean", "boolean", "boolean", "boolean"))
- .callToWrap(new Hook("org.eclipse.jdt.internal.corext.util.CodeFormatterUtil", "reformat", "org.eclipse.text.edits.TextEdit",
- "int", "java.lang.String", "int", "java.lang.String", "java.util.Map"))
- .symbol("lombok.disable").build());
+ .target(new MethodTarget("org.eclipse.jdt.internal.formatter.DefaultCodeFormatter", "parseSourceCode"))
+ .callToWrap(new Hook("org.eclipse.jdt.core.dom.ASTParser", "createAST", "org.eclipse.jdt.core.dom.ASTNode", "org.eclipse.core.runtime.IProgressMonitor"))
+ .symbol("lombok.disable")
+ .build());
}
private static void patchRefactorScripts(ScriptManager sm) {
diff --git a/src/eclipseAgent/lombok/eclipse/agent/PatchDelegate.java b/src/eclipseAgent/lombok/eclipse/agent/PatchDelegate.java
index b1f5a43a..02760e35 100644
--- a/src/eclipseAgent/lombok/eclipse/agent/PatchDelegate.java
+++ b/src/eclipseAgent/lombok/eclipse/agent/PatchDelegate.java
@@ -699,7 +699,10 @@ public class PatchDelegate {
}
private static void addAllMethodBindings0(List<BindingTuple> list, TypeBinding binding, Set<String> banList, char[] fieldName, ASTNode responsible) throws DelegateRecursion {
- if (binding instanceof SourceTypeBinding) ((SourceTypeBinding) binding).scope.environment().globalOptions.storeAnnotations = true;
+ if (binding instanceof SourceTypeBinding) {
+ ClassScope scope = ((SourceTypeBinding) binding).scope;
+ if (scope != null) scope.environment().globalOptions.storeAnnotations = true;
+ }
if (binding == null) return;
TypeBinding inner;
@@ -721,42 +724,44 @@ public class PatchDelegate {
}
}
- if (binding instanceof ReferenceBinding) {
- ReferenceBinding rb = (ReferenceBinding) binding;
- MethodBinding[] availableMethods = rb.availableMethods();
- FieldBinding[] availableFields = rb.availableFields();
- failIfContainsAnnotation(binding, availableMethods);
- failIfContainsAnnotation(binding, availableFields);
-
- MethodBinding[] parameterizedSigs = availableMethods;
- MethodBinding[] baseSigs = parameterizedSigs;
- if (binding instanceof ParameterizedTypeBinding) {
- baseSigs = ((ParameterizedTypeBinding)binding).genericType().availableMethods();
- if (baseSigs.length != parameterizedSigs.length) {
- // The last known state of eclipse source says this can't happen, so we rely on it,
- // but if this invariant is broken, better to go with 'arg0' naming instead of crashing.
- baseSigs = parameterizedSigs;
- }
- }
- for (int i = 0; i < parameterizedSigs.length; i++) {
- MethodBinding mb = parameterizedSigs[i];
- String sig = printSig(mb);
- if (mb.isStatic()) continue;
- if (mb.isBridge()) continue;
- if (mb.isConstructor()) continue;
- if (mb.isDefaultAbstract()) continue;
- if (!mb.isPublic()) continue;
- if (mb.isSynthetic()) continue;
- if (!banList.add(sig)) continue; // If add returns false, it was already in there.
- BindingTuple pair = new BindingTuple(mb, baseSigs[i], fieldName, responsible);
- list.add(pair);
- }
- addAllMethodBindings0(list, rb.superclass(), banList, fieldName, responsible);
- ReferenceBinding[] interfaces = rb.superInterfaces();
- if (interfaces != null) {
- for (ReferenceBinding iface : interfaces) addAllMethodBindings0(list, iface, banList, fieldName, responsible);
+ if (!(binding instanceof ReferenceBinding)) {
+ return;
+ }
+
+ ReferenceBinding rb = (ReferenceBinding) binding;
+ MethodBinding[] availableMethods = rb.availableMethods();
+ FieldBinding[] availableFields = rb.availableFields();
+ failIfContainsAnnotation(binding, availableMethods);
+ failIfContainsAnnotation(binding, availableFields);
+
+ MethodBinding[] parameterizedSigs = availableMethods;
+ MethodBinding[] baseSigs = parameterizedSigs;
+ if (binding instanceof ParameterizedTypeBinding) {
+ baseSigs = ((ParameterizedTypeBinding)binding).genericType().availableMethods();
+ if (baseSigs.length != parameterizedSigs.length) {
+ // The last known state of eclipse source says this can't happen, so we rely on it,
+ // but if this invariant is broken, better to go with 'arg0' naming instead of crashing.
+ baseSigs = parameterizedSigs;
}
}
+ for (int i = 0; i < parameterizedSigs.length; i++) {
+ MethodBinding mb = parameterizedSigs[i];
+ String sig = printSig(mb);
+ if (mb.isStatic()) continue;
+ if (mb.isBridge()) continue;
+ if (mb.isConstructor()) continue;
+ if (mb.isDefaultAbstract()) continue;
+ if (!mb.isPublic()) continue;
+ if (mb.isSynthetic()) continue;
+ if (!banList.add(sig)) continue; // If add returns false, it was already in there.
+ BindingTuple pair = new BindingTuple(mb, baseSigs[i], fieldName, responsible);
+ list.add(pair);
+ }
+ addAllMethodBindings0(list, rb.superclass(), banList, fieldName, responsible);
+ ReferenceBinding[] interfaces = rb.superInterfaces();
+ if (interfaces != null) {
+ for (ReferenceBinding iface : interfaces) addAllMethodBindings0(list, iface, banList, fieldName, responsible);
+ }
}
private static final char[] STRING_LOMBOK = new char[] {'l', 'o', 'm', 'b', 'o', 'k'};
diff --git a/src/eclipseAgent/lombok/eclipse/agent/PatchVal.java b/src/eclipseAgent/lombok/eclipse/agent/PatchVal.java
index 2b8dfbaa..c2a362bd 100644
--- a/src/eclipseAgent/lombok/eclipse/agent/PatchVal.java
+++ b/src/eclipseAgent/lombok/eclipse/agent/PatchVal.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2010-2011 The Project Lombok Authors.
+ * Copyright (C) 2010-2018 The Project Lombok Authors.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -21,14 +21,11 @@
*/
package lombok.eclipse.agent;
-import static lombok.eclipse.handlers.EclipseHandlerUtil.*;
-import static lombok.eclipse.Eclipse.*;
-
-import java.lang.reflect.Field;
-
+import org.eclipse.jdt.internal.compiler.ast.ASTNode;
import org.eclipse.jdt.internal.compiler.ast.Annotation;
import org.eclipse.jdt.internal.compiler.ast.Expression;
import org.eclipse.jdt.internal.compiler.ast.ForeachStatement;
+import org.eclipse.jdt.internal.compiler.ast.ImportReference;
import org.eclipse.jdt.internal.compiler.ast.LocalDeclaration;
import org.eclipse.jdt.internal.compiler.ast.QualifiedTypeReference;
import org.eclipse.jdt.internal.compiler.ast.SingleTypeReference;
@@ -37,12 +34,20 @@ import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
import org.eclipse.jdt.internal.compiler.lookup.ArrayBinding;
import org.eclipse.jdt.internal.compiler.lookup.Binding;
import org.eclipse.jdt.internal.compiler.lookup.BlockScope;
+import org.eclipse.jdt.internal.compiler.lookup.CompilationUnitScope;
+import org.eclipse.jdt.internal.compiler.lookup.ImportBinding;
import org.eclipse.jdt.internal.compiler.lookup.ParameterizedTypeBinding;
import org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding;
+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 java.lang.reflect.Field;
+
+import static lombok.eclipse.Eclipse.poss;
+import static lombok.eclipse.handlers.EclipseHandlerUtil.makeType;
+
public class PatchVal {
// This is half of the work for 'val' support - the other half is in PatchValEclipse. This half is enough for ecj.
@@ -84,23 +89,89 @@ public class PatchVal {
return true;
}
- public static boolean couldBeVal(TypeReference ref) {
+ public static boolean couldBe(ImportBinding[] imports, String key, TypeReference ref) {
+ String[] keyParts = key.split("\\.");
if (ref instanceof SingleTypeReference) {
char[] token = ((SingleTypeReference)ref).token;
- return matches("val", token);
+ if (!matches(keyParts[keyParts.length - 1], token)) return false;
+ if (imports == null) return true;
+ top:
+ for (ImportBinding ib : imports) {
+ ImportReference ir = ib.reference;
+ if (ir == null) continue;
+ if (ir.isStatic()) continue;
+ boolean star = ((ir.bits & ASTNode.OnDemand) != 0);
+ int len = keyParts.length - (star ? 1 : 0);
+ char[][] t = ir.tokens;
+ if (len != t.length) continue;
+ for (int i = 0; i < len; i++) {
+ if (keyParts[i].length() != t[i].length) continue top;
+ for (int j = 0; j < t[i].length; j++) if (keyParts[i].charAt(j) != t[i][j]) continue top;
+ }
+ return true;
+ }
+ return false;
}
if (ref instanceof QualifiedTypeReference) {
char[][] tokens = ((QualifiedTypeReference)ref).tokens;
- if (tokens == null || tokens.length != 2) return false;
- return matches("lombok", tokens[0]) && matches("val", tokens[1]);
+ if (keyParts.length != tokens.length) return false;
+ for(int i = 0; i < tokens.length; ++i) {
+ String part = keyParts[i];
+ char[] token = tokens[i];
+ if (!matches(part, token)) return false;
+ }
+ return true;
}
return false;
}
- private static boolean isVal(TypeReference ref, BlockScope scope) {
- if (!couldBeVal(ref)) return false;
+ public static boolean couldBe(ImportReference[] imports, String key, TypeReference ref) {
+ String[] keyParts = key.split("\\.");
+ if (ref instanceof SingleTypeReference) {
+ char[] token = ((SingleTypeReference)ref).token;
+ if (!matches(keyParts[keyParts.length - 1], token)) return false;
+ if (imports == null) return true;
+ top:
+ for (ImportReference ir : imports) {
+ if (ir.isStatic()) continue;
+ boolean star = ((ir.bits & ASTNode.OnDemand) != 0);
+ int len = keyParts.length - (star ? 1 : 0);
+ char[][] t = ir.tokens;
+ if (len != t.length) continue;
+ for (int i = 0; i < len; i++) {
+ if (keyParts[i].length() != t[i].length) continue top;
+ for (int j = 0; j < t[i].length; j++) if (keyParts[i].charAt(j) != t[i][j]) continue top;
+ }
+ return true;
+ }
+ return false;
+ }
+
+ if (ref instanceof QualifiedTypeReference) {
+ char[][] tokens = ((QualifiedTypeReference)ref).tokens;
+ if (keyParts.length != tokens.length) return false;
+ for(int i = 0; i < tokens.length; ++i) {
+ String part = keyParts[i];
+ char[] token = tokens[i];
+ if (!matches(part, token)) return false;
+ }
+ return true;
+ }
+
+ return false;
+ }
+
+ private static boolean is(TypeReference ref, BlockScope scope, String key) {
+ Scope s = scope.parent;
+ while (s != null && !(s instanceof CompilationUnitScope)) {
+ Scope ns = s.parent;
+ s = ns == s ? null : ns;
+ }
+ ImportBinding[] imports = null;
+ if (s instanceof CompilationUnitScope) imports = ((CompilationUnitScope) s).imports;
+ if (!couldBe(imports, key, ref)) return false;
TypeBinding resolvedType = ref.resolvedType;
if (resolvedType == null) resolvedType = ref.resolveType(scope, false);
@@ -108,7 +179,14 @@ public class PatchVal {
char[] pkg = resolvedType.qualifiedPackageName();
char[] nm = resolvedType.qualifiedSourceName();
- return matches("lombok", pkg) && matches("val", nm);
+ int pkgFullLength = pkg.length > 0 ? pkg.length + 1: 0;
+ char[] fullName = new char[pkgFullLength + nm.length];
+ if(pkg.length > 0) {
+ System.arraycopy(pkg, 0, fullName, 0, pkg.length);
+ fullName[pkg.length] = '.';
+ }
+ System.arraycopy(nm, 0, fullName, pkgFullLength, nm.length);
+ return matches(key, fullName);
}
public static final class Reflection {
@@ -132,13 +210,17 @@ public class PatchVal {
if (local == null || !LocalDeclaration.class.equals(local.getClass())) return false;
boolean decomponent = false;
- if (!isVal(local.type, scope)) return false;
+ boolean val = isVal(local, scope);
+ boolean var = isVar(local, scope);
+ if (!(val || var)) return false;
StackTraceElement[] st = new Throwable().getStackTrace();
for (int i = 0; i < st.length - 2 && i < 10; i++) {
if (st[i].getClassName().equals("lombok.launch.PatchFixesHider$Val")) {
- if (st[i + 1].getClassName().equals("org.eclipse.jdt.internal.compiler.ast.LocalDeclaration") &&
- st[i + 2].getClassName().equals("org.eclipse.jdt.internal.compiler.ast.ForStatement")) return false;
+ boolean valInForStatement = val &&
+ st[i + 1].getClassName().equals("org.eclipse.jdt.internal.compiler.ast.LocalDeclaration") &&
+ st[i + 2].getClassName().equals("org.eclipse.jdt.internal.compiler.ast.ForStatement");
+ if (valInForStatement) return false;
break;
}
}
@@ -187,23 +269,33 @@ public class PatchVal {
}
}
- local.modifiers |= ClassFileConstants.AccFinal;
+ if(val) local.modifiers |= ClassFileConstants.AccFinal;
local.annotations = addValAnnotation(local.annotations, local.type, scope);
local.type = replacement != null ? replacement : new QualifiedTypeReference(TypeConstants.JAVA_LANG_OBJECT, poss(local.type, 3));
return false;
}
+ private static boolean isVar(LocalDeclaration local, BlockScope scope) {
+ return is(local.type, scope, "lombok.experimental.var") || is(local.type, scope, "lombok.var");
+ }
+
+ private static boolean isVal(LocalDeclaration local, BlockScope scope) {
+ return is(local.type, scope, "lombok.val");
+ }
+
public static boolean handleValForForEach(ForeachStatement forEach, BlockScope scope) {
if (forEach.elementVariable == null) return false;
- if (!isVal(forEach.elementVariable.type, scope)) return false;
+ boolean val = isVal(forEach.elementVariable, scope);
+ boolean var = isVar(forEach.elementVariable, scope);
+ if (!(val || var)) return false;
TypeBinding component = getForEachComponentType(forEach.collection, scope);
if (component == null) return false;
TypeReference replacement = makeType(component, forEach.elementVariable.type, false);
- forEach.elementVariable.modifiers |= ClassFileConstants.AccFinal;
+ if (val) forEach.elementVariable.modifiers |= ClassFileConstants.AccFinal;
forEach.elementVariable.annotations = addValAnnotation(forEach.elementVariable.annotations, forEach.elementVariable.type, scope);
forEach.elementVariable.type = replacement != null ? replacement :
new QualifiedTypeReference(TypeConstants.JAVA_LANG_OBJECT, poss(forEach.elementVariable.type, 3));
diff --git a/src/eclipseAgent/lombok/eclipse/agent/PatchValEclipse.java b/src/eclipseAgent/lombok/eclipse/agent/PatchValEclipse.java
index 7d5f36f4..d59b6a2e 100644
--- a/src/eclipseAgent/lombok/eclipse/agent/PatchValEclipse.java
+++ b/src/eclipseAgent/lombok/eclipse/agent/PatchValEclipse.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2010-2011 The Project Lombok Authors.
+ * Copyright (C) 2010-2018 The Project Lombok Authors.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -45,8 +45,10 @@ import org.eclipse.jdt.internal.compiler.ast.ASTNode;
import org.eclipse.jdt.internal.compiler.ast.AbstractVariableDeclaration;
import org.eclipse.jdt.internal.compiler.ast.Annotation;
import org.eclipse.jdt.internal.compiler.ast.ForeachStatement;
+import org.eclipse.jdt.internal.compiler.ast.ImportReference;
import org.eclipse.jdt.internal.compiler.ast.LocalDeclaration;
import org.eclipse.jdt.internal.compiler.ast.SingleTypeReference;
+import org.eclipse.jdt.internal.compiler.ast.TypeReference;
import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
import org.eclipse.jdt.internal.compiler.parser.Parser;
@@ -65,7 +67,9 @@ public class PatchValEclipse {
ForeachStatement foreachDecl = (ForeachStatement) astStack[astPtr];
ASTNode init = foreachDecl.collection;
if (init == null) return;
- if (foreachDecl.elementVariable == null || !PatchVal.couldBeVal(foreachDecl.elementVariable.type)) return;
+ boolean val = couldBeVal(parser == null ? null : parser.compilationUnit == null ? null : parser.compilationUnit.imports, foreachDecl.elementVariable.type);
+ boolean var = couldBeVar(parser == null ? null : parser.compilationUnit == null ? null : parser.compilationUnit.imports, foreachDecl.elementVariable.type);
+ if (foreachDecl.elementVariable == null || !(val || var)) return;
try {
if (Reflection.iterableCopyField != null) Reflection.iterableCopyField.set(foreachDecl.elementVariable, init);
@@ -88,7 +92,9 @@ public class PatchValEclipse {
if (!(variableDecl instanceof LocalDeclaration)) return;
ASTNode init = variableDecl.initialization;
if (init == null) return;
- if (!PatchVal.couldBeVal(variableDecl.type)) return;
+ boolean val = couldBeVal(parser == null ? null : parser.compilationUnit == null ? null : parser.compilationUnit.imports, variableDecl.type);
+ boolean var = couldBeVar(parser == null ? null : parser.compilationUnit == null ? null : parser.compilationUnit.imports, variableDecl.type);
+ if (!(val || var)) return;
try {
if (Reflection.initCopyField != null) Reflection.initCopyField.set(variableDecl, init);
@@ -97,6 +103,10 @@ public class PatchValEclipse {
}
}
+ private static boolean couldBeVar(ImportReference[] imports, TypeReference type) {
+ return PatchVal.couldBe(imports, "lombok.experimental.var", type) || PatchVal.couldBe(imports, "lombok.var", type);
+ }
+
public static void addFinalAndValAnnotationToSingleVariableDeclaration(Object converter, SingleVariableDeclaration out, LocalDeclaration in) {
@SuppressWarnings("unchecked") List<IExtendedModifier> modifiers = out.modifiers();
addFinalAndValAnnotationToModifierList(converter, modifiers, out.getAST(), in);
@@ -115,7 +125,7 @@ public class PatchValEclipse {
Annotation valAnnotation = null;
for (Annotation ann : in.annotations) {
- if (PatchVal.couldBeVal(ann.type)) {
+ if (couldBeVal(null, ann.type)) {
found = true;
valAnnotation = ann;
break;
@@ -167,6 +177,10 @@ public class PatchValEclipse {
}
}
+ private static boolean couldBeVal(ImportReference[] imports, TypeReference type) {
+ return PatchVal.couldBe(imports, "lombok.val", type);
+ }
+
public static Modifier createModifier(AST ast, ModifierKeyword keyword, int start, int end) {
Modifier modifier = null;
try {
diff --git a/src/eclipseAgent/lombok/launch/PatchFixesHider.java b/src/eclipseAgent/lombok/launch/PatchFixesHider.java
index fae06900..317b06a4 100644
--- a/src/eclipseAgent/lombok/launch/PatchFixesHider.java
+++ b/src/eclipseAgent/lombok/launch/PatchFixesHider.java
@@ -36,11 +36,13 @@ import lombok.eclipse.EclipseAugments;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.jdt.core.IAnnotatable;
import org.eclipse.jdt.core.IAnnotation;
+import org.eclipse.jdt.core.IField;
import org.eclipse.jdt.core.IMethod;
import org.eclipse.jdt.core.IType;
import org.eclipse.jdt.core.JavaModelException;
import org.eclipse.jdt.core.dom.MethodDeclaration;
import org.eclipse.jdt.core.dom.SimpleName;
+import org.eclipse.jdt.core.search.SearchMatch;
import org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration;
import org.eclipse.jdt.internal.compiler.ast.Annotation;
import org.eclipse.jdt.internal.compiler.ast.CompilationUnitDeclaration;
@@ -55,9 +57,11 @@ import org.eclipse.jdt.internal.compiler.lookup.Scope;
import org.eclipse.jdt.internal.compiler.lookup.TypeBinding;
import org.eclipse.jdt.internal.compiler.parser.Parser;
import org.eclipse.jdt.internal.compiler.problem.ProblemReporter;
+import org.eclipse.jdt.internal.core.SourceField;
import org.eclipse.jdt.internal.core.dom.rewrite.NodeRewriteEvent;
import org.eclipse.jdt.internal.core.dom.rewrite.RewriteEvent;
import org.eclipse.jdt.internal.core.dom.rewrite.TokenScanner;
+import org.eclipse.jdt.internal.corext.refactoring.SearchResultGroup;
import org.eclipse.jdt.internal.corext.refactoring.structure.ASTNodeSearchUtil;
/** These contain a mix of the following:
@@ -144,7 +148,11 @@ final class PatchFixesHider {
}
public static String addLombokNotesToEclipseAboutDialog(String origReturnValue, String key) {
- return (String) Util.invokeMethod(LombokDeps.ADD_LOMBOK_NOTES, origReturnValue, key);
+ try {
+ return (String) Util.invokeMethod(LombokDeps.ADD_LOMBOK_NOTES, origReturnValue, key);
+ } catch (Throwable t) {
+ return origReturnValue;
+ }
}
public static byte[] runPostCompiler(byte[] bytes, String fileName) {
@@ -565,6 +573,48 @@ final class PatchFixesHider {
return result.size() == methods.length ? methods : result.toArray(new IMethod[result.size()]);
}
+ public static SearchMatch[] removeGenerated(SearchMatch[] returnValue) {
+ List<SearchMatch> result = new ArrayList<SearchMatch>();
+ for (int j = 0; j < returnValue.length; j++) {
+ SearchMatch searchResult = returnValue[j];
+ if (searchResult.getElement() instanceof IField) {
+ IField field = (IField) searchResult.getElement();
+
+ // can not check for value=lombok because annotation is
+ // not fully resolved
+ IAnnotation annotation = field.getAnnotation("Generated");
+ if (annotation != null) {
+ // Method generated at field location, skip
+ continue;
+ }
+
+ }
+ result.add(searchResult);
+ }
+ return result.toArray(new SearchMatch[result.size()]);
+ }
+
+ public static SearchResultGroup[] createFakeSearchResult(SearchResultGroup[] returnValue,
+ Object/*
+ * org.eclipse.jdt.internal.corext.refactoring.rename.
+ * RenameFieldProcessor
+ */ processor) throws Exception {
+ if (returnValue == null || returnValue.length == 0) {
+ // if no matches were found, check if Data annotation is present on the class
+ Field declaredField = processor.getClass().getDeclaredField("fField");
+ if (declaredField != null) {
+ declaredField.setAccessible(true);
+ SourceField fField = (SourceField) declaredField.get(processor);
+ IAnnotation dataAnnotation = fField.getDeclaringType().getAnnotation("Data");
+ if (dataAnnotation != null) {
+ // add fake item, to make refactoring checks pass
+ return new SearchResultGroup[] {new SearchResultGroup(null, new SearchMatch[1])};
+ }
+ }
+ }
+ return returnValue;
+ }
+
public static SimpleName[] removeGeneratedSimpleNames(SimpleName[] in) throws Exception {
Field f = SimpleName.class.getField("$isGenerated");