aboutsummaryrefslogtreecommitdiff
path: root/src/eclipseAgent/lombok/eclipse
diff options
context:
space:
mode:
Diffstat (limited to 'src/eclipseAgent/lombok/eclipse')
-rw-r--r--src/eclipseAgent/lombok/eclipse/agent/EclipseLoaderPatcher.java6
-rw-r--r--src/eclipseAgent/lombok/eclipse/agent/EclipsePatcher.java366
-rw-r--r--src/eclipseAgent/lombok/eclipse/agent/ExtensionMethodCompletionProposal.java76
-rw-r--r--src/eclipseAgent/lombok/eclipse/agent/PatchDelegate.java226
-rw-r--r--src/eclipseAgent/lombok/eclipse/agent/PatchDelegatePortal.java58
-rw-r--r--src/eclipseAgent/lombok/eclipse/agent/PatchExtensionMethod.java148
-rwxr-xr-xsrc/eclipseAgent/lombok/eclipse/agent/PatchExtensionMethodCompletionProposal.java41
-rw-r--r--src/eclipseAgent/lombok/eclipse/agent/PatchExtensionMethodPortal.java103
-rw-r--r--src/eclipseAgent/lombok/eclipse/agent/PatchJavadoc.java138
-rw-r--r--src/eclipseAgent/lombok/eclipse/agent/PatchVal.java29
10 files changed, 837 insertions, 354 deletions
diff --git a/src/eclipseAgent/lombok/eclipse/agent/EclipseLoaderPatcher.java b/src/eclipseAgent/lombok/eclipse/agent/EclipseLoaderPatcher.java
index aa01c13d..25906c6b 100644
--- a/src/eclipseAgent/lombok/eclipse/agent/EclipseLoaderPatcher.java
+++ b/src/eclipseAgent/lombok/eclipse/agent/EclipseLoaderPatcher.java
@@ -31,6 +31,12 @@ import lombok.patcher.scripts.ScriptBuilder;
public class EclipseLoaderPatcher {
private static final String TRANSPLANTS_CLASS_NAME = "lombok.eclipse.agent.EclipseLoaderPatcherTransplants";
+ static final String[] OSGI_TYPES = {
+ "org/eclipse/osgi/internal/baseadaptor/DefaultClassLoader",
+ "org/eclipse/osgi/framework/adapter/core/AbstractClassLoader",
+ "org/eclipse/osgi/internal/loader/ModuleClassLoader"
+ };
+
public static void patchEquinoxLoaders(ScriptManager sm, Class<?> launchingContext) {
sm.addScript(ScriptBuilder.exitEarly()
.target(new MethodTarget("org.eclipse.osgi.internal.baseadaptor.DefaultClassLoader", "loadClass",
diff --git a/src/eclipseAgent/lombok/eclipse/agent/EclipsePatcher.java b/src/eclipseAgent/lombok/eclipse/agent/EclipsePatcher.java
index c560f002..ce26c892 100644
--- a/src/eclipseAgent/lombok/eclipse/agent/EclipsePatcher.java
+++ b/src/eclipseAgent/lombok/eclipse/agent/EclipsePatcher.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2009-2020 The Project Lombok Authors.
+ * Copyright (C) 2009-2021 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,6 +22,7 @@
package lombok.eclipse.agent;
import static lombok.patcher.scripts.ScriptBuilder.*;
+import static lombok.eclipse.agent.EclipseLoaderPatcher.OSGI_TYPES;
import java.io.File;
import java.lang.instrument.Instrumentation;
@@ -49,34 +50,11 @@ import lombok.patcher.scripts.ScriptBuilder;
* transformed.
*/
public class EclipsePatcher implements AgentLauncher.AgentLaunchable {
- // At some point I'd like the agent to be capable of auto-detecting if its on eclipse or on ecj. This class is a sure sign we're not in ecj but in eclipse. -ReinierZ
- @SuppressWarnings("unused")
- private static final String ECLIPSE_SIGNATURE_CLASS = "org/eclipse/core/runtime/adaptor/EclipseStarter";
-
@Override public void runAgent(String agentArgs, Instrumentation instrumentation, boolean injected, Class<?> launchingContext) throws Exception {
- String[] args = agentArgs == null ? new String[0] : agentArgs.split(":");
- boolean forceEcj = false;
- boolean forceEclipse = false;
-
- for (String arg : args) {
- if (arg.trim().equalsIgnoreCase("ECJ")) forceEcj = true;
- if (arg.trim().equalsIgnoreCase("ECLIPSE")) forceEclipse = true;
- }
- if (forceEcj && forceEclipse) {
- forceEcj = false;
- forceEclipse = false;
- }
-
- boolean ecj;
-
- if (forceEcj) ecj = true;
- else if (forceEclipse) ecj = false;
- else ecj = injected;
-
- registerPatchScripts(instrumentation, injected, ecj, launchingContext);
+ registerPatchScripts(instrumentation, injected, launchingContext);
}
- private static void registerPatchScripts(Instrumentation instrumentation, boolean reloadExistingClasses, boolean ecjOnly, Class<?> launchingContext) {
+ private static void registerPatchScripts(Instrumentation instrumentation, boolean reloadExistingClasses, Class<?> launchingContext) {
ScriptManager sm = new ScriptManager();
sm.registerTransformer(instrumentation);
sm.setFilter(new Filter() {
@@ -97,33 +75,33 @@ public class EclipsePatcher implements AgentLauncher.AgentLaunchable {
}
});
- if (!ecjOnly) {
- EclipseLoaderPatcher.patchEquinoxLoaders(sm, launchingContext);
- patchCatchReparse(sm);
- patchIdentifierEndReparse(sm);
- patchRetrieveEllipsisStartPosition(sm);
- patchRetrieveRightBraceOrSemiColonPosition(sm);
- patchRetrieveProperRightBracketPosition(sm);
- patchSetGeneratedFlag(sm);
- patchDomAstReparseIssues(sm);
- patchHideGeneratedNodes(sm);
- patchPostCompileHookEclipse(sm);
- patchFixSourceTypeConverter(sm);
- patchDisableLombokForCodeCleanup(sm);
- patchListRewriteHandleGeneratedMethods(sm);
- patchSyntaxAndOccurrencesHighlighting(sm);
- patchSortMembersOperation(sm);
- patchExtractInterface(sm);
- patchAboutDialog(sm);
- patchEclipseDebugPatches(sm);
- } else {
- patchPostCompileHookEcj(sm);
- }
+ EclipseLoaderPatcher.patchEquinoxLoaders(sm, launchingContext);
+ patchCatchReparse(sm);
+ patchIdentifierEndReparse(sm);
+ patchRetrieveEllipsisStartPosition(sm);
+ patchRetrieveRightBraceOrSemiColonPosition(sm);
+ patchRetrieveProperRightBracketPosition(sm);
+ patchRetrieveStartBlockPosition(sm);
+ patchSetGeneratedFlag(sm);
+ patchDomAstReparseIssues(sm);
+ patchHideGeneratedNodes(sm);
+ patchPostCompileHookEclipse(sm);
+ patchFixSourceTypeConverter(sm);
+ patchDisableLombokForCodeCleanup(sm);
+ patchListRewriteHandleGeneratedMethods(sm);
+ patchSyntaxAndOccurrencesHighlighting(sm);
+ patchSortMembersOperation(sm);
+ patchExtractInterface(sm);
+ patchAboutDialog(sm);
+ patchEclipseDebugPatches(sm);
+ patchJavadoc(sm);
+
+ patchPostCompileHookEcj(sm);
patchAvoidReparsingGeneratedCode(sm);
patchLombokizeAST(sm);
- patchEcjTransformers(sm, ecjOnly);
- patchExtensionMethod(sm, ecjOnly);
+ patchEcjTransformers(sm);
+ patchExtensionMethod(sm);
patchRenameField(sm);
patchNullCheck(sm);
@@ -158,7 +136,7 @@ public class EclipsePatcher implements AgentLauncher.AgentLaunchable {
private static void patchExtractInterface(ScriptManager sm) {
/* Fix sourceEnding for generated nodes to avoid null pointer */
- sm.addScript(ScriptBuilder.wrapMethodCall()
+ sm.addScriptIfWitness(OSGI_TYPES, ScriptBuilder.wrapMethodCall()
.target(new MethodTarget("org.eclipse.jdt.internal.compiler.SourceElementNotifier", "notifySourceElementRequestor", "void", "org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration", "org.eclipse.jdt.internal.compiler.ast.TypeDeclaration", "org.eclipse.jdt.internal.compiler.ast.ImportReference"))
.methodToWrap(new Hook("org.eclipse.jdt.internal.compiler.util.HashtableOfObjectToInt", "get", "int", "java.lang.Object"))
.wrapMethod(new Hook("lombok.launch.PatchFixesHider$PatchFixes", "getSourceEndFixed", "int", "int", "org.eclipse.jdt.internal.compiler.ast.ASTNode"))
@@ -166,7 +144,7 @@ public class EclipsePatcher implements AgentLauncher.AgentLaunchable {
.transplant().build());
/* Make sure the generated source element is found instead of the annotation */
- sm.addScript(ScriptBuilder.wrapMethodCall()
+ sm.addScriptIfWitness(OSGI_TYPES, ScriptBuilder.wrapMethodCall()
.target(new MethodTarget("org.eclipse.jdt.internal.corext.refactoring.structure.ExtractInterfaceProcessor", "createMethodDeclaration", "void",
"org.eclipse.jdt.internal.corext.refactoring.structure.CompilationUnitRewrite",
"org.eclipse.jdt.core.dom.rewrite.ASTRewrite",
@@ -179,7 +157,7 @@ public class EclipsePatcher implements AgentLauncher.AgentLaunchable {
.transplant().build());
/* get real generated node in stead of a random one generated by the annotation */
- sm.addScript(ScriptBuilder.replaceMethodCall()
+ sm.addScriptIfWitness(OSGI_TYPES, ScriptBuilder.replaceMethodCall()
.target(new MethodTarget("org.eclipse.jdt.internal.corext.refactoring.structure.ExtractInterfaceProcessor", "createMemberDeclarations"))
.target(new MethodTarget("org.eclipse.jdt.internal.corext.refactoring.structure.ExtractInterfaceProcessor", "createMethodComments"))
.methodToReplace(new Hook("org.eclipse.jdt.internal.corext.refactoring.structure.ASTNodeSearchUtil", "getMethodDeclarationNode", "org.eclipse.jdt.core.dom.MethodDeclaration", "org.eclipse.jdt.core.IMethod", "org.eclipse.jdt.core.dom.CompilationUnit"))
@@ -187,14 +165,14 @@ public class EclipsePatcher implements AgentLauncher.AgentLaunchable {
.transplant().build());
/* Do not add @Override's for generated methods */
- sm.addScript(ScriptBuilder.exitEarly()
+ sm.addScriptIfWitness(OSGI_TYPES, ScriptBuilder.exitEarly()
.target(new MethodTarget("org.eclipse.jdt.core.dom.rewrite.ListRewrite", "insertFirst"))
.decisionMethod(new Hook("lombok.launch.PatchFixesHider$PatchFixes", "isListRewriteOnGeneratedNode", "boolean", "org.eclipse.jdt.core.dom.rewrite.ListRewrite"))
.request(StackRequest.THIS)
.transplant().build());
/* Do not add comments for generated methods */
- sm.addScript(ScriptBuilder.exitEarly()
+ sm.addScriptIfWitness(OSGI_TYPES, ScriptBuilder.exitEarly()
.target(new MethodTarget("org.eclipse.jdt.internal.corext.refactoring.structure.ExtractInterfaceProcessor", "createMethodComment"))
.decisionMethod(new Hook("lombok.launch.PatchFixesHider$PatchFixes", "isGenerated", "boolean", "org.eclipse.jdt.core.dom.ASTNode"))
.request(StackRequest.PARAM2)
@@ -207,7 +185,7 @@ public class EclipsePatcher implements AgentLauncher.AgentLaunchable {
* This is doable without patching, but we intentionally patch it so that presence of the lombok info
* in the about dialog can be used to ascertain that patching in general is doing something.
*/
- sm.addScript(ScriptBuilder.wrapReturnValue()
+ sm.addScriptIfWitness(OSGI_TYPES, ScriptBuilder.wrapReturnValue()
.target(new MethodTarget("org.eclipse.core.internal.runtime.Product", "getProperty", "java.lang.String", "java.lang.String"))
.wrapMethod(new Hook("lombok.launch.PatchFixesHider$LombokDeps", "addLombokNotesToEclipseAboutDialog", "java.lang.String", "java.lang.String", "java.lang.String"))
.request(StackRequest.RETURN_VALUE, StackRequest.PARAM1)
@@ -218,7 +196,7 @@ public class EclipsePatcher implements AgentLauncher.AgentLaunchable {
/*
* Skip generated nodes for "visual effects" (syntax highlighting && highlight occurrences)
*/
- sm.addScript(ScriptBuilder.exitEarly()
+ sm.addScriptIfWitness(OSGI_TYPES, ScriptBuilder.exitEarly()
.target(new MethodTarget("org.eclipse.jdt.internal.ui.search.OccurrencesFinder", "addUsage"))
.target(new MethodTarget("org.eclipse.jdt.internal.ui.search.OccurrencesFinder", "addWrite"))
.target(new MethodTarget("org.eclipse.jdt.internal.ui.javaeditor.SemanticHighlightingReconciler$PositionCollector", "visit", "boolean", "org.eclipse.jdt.core.dom.SimpleName"))
@@ -229,7 +207,7 @@ public class EclipsePatcher implements AgentLauncher.AgentLaunchable {
}
private static void patchDisableLombokForCodeCleanup(ScriptManager sm) {
- sm.addScript(ScriptBuilder.exitEarly()
+ sm.addScriptIfWitness(OSGI_TYPES, 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"))
.target(new MethodTarget("org.eclipse.jdt.internal.corext.fix.ControlStatementsFix$ControlStatementFinder", "visit", "boolean", "org.eclipse.jdt.core.dom.ForStatement"))
@@ -256,7 +234,7 @@ public class EclipsePatcher implements AgentLauncher.AgentLaunchable {
}
private static void patchListRewriteHandleGeneratedMethods(ScriptManager sm) {
- sm.addScript(ScriptBuilder.replaceMethodCall()
+ sm.addScriptIfWitness(OSGI_TYPES, ScriptBuilder.replaceMethodCall()
.target(new MethodTarget("org.eclipse.jdt.internal.core.dom.rewrite.ASTRewriteAnalyzer$ListRewriter", "rewriteList"))
.methodToReplace(new Hook("org.eclipse.jdt.internal.core.dom.rewrite.RewriteEvent", "getChildren", "org.eclipse.jdt.internal.core.dom.rewrite.RewriteEvent[]"))
.replacementMethod(new Hook("lombok.launch.PatchFixesHider$PatchFixes", "listRewriteHandleGeneratedMethods", "org.eclipse.jdt.internal.core.dom.rewrite.RewriteEvent[]", "org.eclipse.jdt.internal.core.dom.rewrite.RewriteEvent"))
@@ -268,37 +246,37 @@ public class EclipsePatcher implements AgentLauncher.AgentLaunchable {
* I would have liked to patch sortMembers, but kept getting a VerifyError: Illegal type in constant pool
* So now I just patch all calling methods
*/
- sm.addScript(ScriptBuilder.wrapMethodCall()
+ sm.addScriptIfWitness(OSGI_TYPES, ScriptBuilder.wrapMethodCall()
.target(new MethodTarget("org.eclipse.jdt.internal.core.SortElementsOperation$2", "visit", "boolean", "org.eclipse.jdt.core.dom.CompilationUnit"))
.methodToWrap(new Hook("org.eclipse.jdt.core.dom.CompilationUnit", "types", "java.util.List"))
.wrapMethod(new Hook("lombok.launch.PatchFixesHider$PatchFixes", "removeGeneratedNodes", "java.util.List", "java.util.List"))
.transplant().build());
- sm.addScript(ScriptBuilder.wrapMethodCall()
+ sm.addScriptIfWitness(OSGI_TYPES, ScriptBuilder.wrapMethodCall()
.target(new MethodTarget("org.eclipse.jdt.internal.core.SortElementsOperation$2", "visit", "boolean", "org.eclipse.jdt.core.dom.AnnotationTypeDeclaration"))
.methodToWrap(new Hook("org.eclipse.jdt.core.dom.AnnotationTypeDeclaration", "bodyDeclarations", "java.util.List"))
.wrapMethod(new Hook("lombok.launch.PatchFixesHider$PatchFixes", "removeGeneratedNodes", "java.util.List", "java.util.List"))
.transplant().build());
- sm.addScript(ScriptBuilder.wrapMethodCall()
+ sm.addScriptIfWitness(OSGI_TYPES, ScriptBuilder.wrapMethodCall()
.target(new MethodTarget("org.eclipse.jdt.internal.core.SortElementsOperation$2", "visit", "boolean", "org.eclipse.jdt.core.dom.AnonymousClassDeclaration"))
.methodToWrap(new Hook("org.eclipse.jdt.core.dom.AnonymousClassDeclaration", "bodyDeclarations", "java.util.List"))
.wrapMethod(new Hook("lombok.launch.PatchFixesHider$PatchFixes", "removeGeneratedNodes", "java.util.List", "java.util.List"))
.transplant().build());
- sm.addScript(ScriptBuilder.wrapMethodCall()
+ sm.addScriptIfWitness(OSGI_TYPES, ScriptBuilder.wrapMethodCall()
.target(new MethodTarget("org.eclipse.jdt.internal.core.SortElementsOperation$2", "visit", "boolean", "org.eclipse.jdt.core.dom.TypeDeclaration"))
.methodToWrap(new Hook("org.eclipse.jdt.core.dom.TypeDeclaration", "bodyDeclarations", "java.util.List"))
.wrapMethod(new Hook("lombok.launch.PatchFixesHider$PatchFixes", "removeGeneratedNodes", "java.util.List", "java.util.List"))
.transplant().build());
- sm.addScript(ScriptBuilder.wrapMethodCall()
+ sm.addScriptIfWitness(OSGI_TYPES, ScriptBuilder.wrapMethodCall()
.target(new MethodTarget("org.eclipse.jdt.internal.core.SortElementsOperation$2", "visit", "boolean", "org.eclipse.jdt.core.dom.EnumDeclaration"))
.methodToWrap(new Hook("org.eclipse.jdt.core.dom.EnumDeclaration", "bodyDeclarations", "java.util.List"))
.wrapMethod(new Hook("lombok.launch.PatchFixesHider$PatchFixes", "removeGeneratedNodes", "java.util.List", "java.util.List"))
.transplant().build());
- sm.addScript(ScriptBuilder.wrapMethodCall()
+ sm.addScriptIfWitness(OSGI_TYPES, ScriptBuilder.wrapMethodCall()
.target(new MethodTarget("org.eclipse.jdt.internal.core.SortElementsOperation$2", "visit", "boolean", "org.eclipse.jdt.core.dom.EnumDeclaration"))
.methodToWrap(new Hook("org.eclipse.jdt.core.dom.EnumDeclaration", "enumConstants", "java.util.List"))
.wrapMethod(new Hook("lombok.launch.PatchFixesHider$PatchFixes", "removeGeneratedNodes", "java.util.List", "java.util.List"))
@@ -306,7 +284,7 @@ public class EclipsePatcher implements AgentLauncher.AgentLaunchable {
}
private static void patchDomAstReparseIssues(ScriptManager sm) {
- sm.addScript(ScriptBuilder.replaceMethodCall()
+ sm.addScriptIfWitness(OSGI_TYPES, ScriptBuilder.replaceMethodCall()
.target(new MethodTarget("org.eclipse.jdt.internal.core.dom.rewrite.ASTRewriteAnalyzer", "visit"))
.methodToReplace(new Hook("org.eclipse.jdt.internal.core.dom.rewrite.TokenScanner", "getTokenEndOffset", "int", "int", "int"))
.replacementMethod(new Hook("lombok.launch.PatchFixesHider$PatchFixes", "getTokenEndOffsetFixed", "int", "org.eclipse.jdt.internal.core.dom.rewrite.TokenScanner", "int", "int", "java.lang.Object"))
@@ -317,7 +295,7 @@ public class EclipsePatcher implements AgentLauncher.AgentLaunchable {
}
private static void patchPostCompileHookEclipse(ScriptManager sm) {
- sm.addScript(ScriptBuilder.wrapMethodCall()
+ sm.addScriptIfWitness(OSGI_TYPES, ScriptBuilder.wrapMethodCall()
.target(new MethodTarget("org.eclipse.jdt.internal.core.builder.IncrementalImageBuilder", "writeClassFileContents"))
.target(new MethodTarget("org.eclipse.jdt.internal.core.builder.AbstractImageBuilder", "writeClassFileContents"))
.methodToWrap(new Hook("org.eclipse.jdt.internal.compiler.ClassFile", "getBytes", "byte[]"))
@@ -327,13 +305,13 @@ public class EclipsePatcher implements AgentLauncher.AgentLaunchable {
}
private static void patchPostCompileHookEcj(ScriptManager sm) {
- sm.addScript(ScriptBuilder.wrapMethodCall()
+ sm.addScriptIfNotWitness(OSGI_TYPES, ScriptBuilder.wrapMethodCall()
.target(new MethodTarget("org.eclipse.jdt.internal.compiler.tool.EclipseCompilerImpl", "outputClassFiles"))
.methodToWrap(new Hook("javax.tools.JavaFileObject", "openOutputStream", "java.io.OutputStream"))
.wrapMethod(new Hook("lombok.launch.PatchFixesHider$LombokDeps", "runPostCompiler", "java.io.OutputStream", "java.io.OutputStream"))
.transplant().build());
- sm.addScript(ScriptBuilder.wrapMethodCall()
+ sm.addScriptIfNotWitness(OSGI_TYPES, ScriptBuilder.wrapMethodCall()
.target(new MethodTarget("org.eclipse.jdt.internal.compiler.util.Util", "writeToDisk"))
.methodToWrap(new Hook("java.io.BufferedOutputStream", "<init>", "void", "java.io.OutputStream", "int"))
.wrapMethod(new Hook("lombok.launch.PatchFixesHider$LombokDeps", "runPostCompiler", "java.io.BufferedOutputStream", "java.io.BufferedOutputStream", "java.lang.String", "java.lang.String"))
@@ -342,7 +320,7 @@ public class EclipsePatcher implements AgentLauncher.AgentLaunchable {
}
private static void patchHideGeneratedNodes(ScriptManager sm) {
- sm.addScript(ScriptBuilder.wrapReturnValue()
+ sm.addScriptIfWitness(OSGI_TYPES, ScriptBuilder.wrapReturnValue()
.target(new MethodTarget("org.eclipse.jdt.internal.corext.dom.LinkedNodeFinder", "findByNode"))
.target(new MethodTarget("org.eclipse.jdt.internal.corext.dom.LinkedNodeFinder", "findByBinding"))
.wrapMethod(new Hook("lombok.launch.PatchFixesHider$PatchFixes", "removeGeneratedSimpleNames", "org.eclipse.jdt.core.dom.SimpleName[]",
@@ -354,37 +332,37 @@ 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.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());
+ // before Eclipse Mars
+ sm.addScriptIfWitness(OSGI_TYPES, 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());
// Eclipse Mars and beyond
- sm.addScript(ScriptBuilder.setSymbolDuringMethodCall()
- .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());
+ sm.addScriptIfWitness(OSGI_TYPES, ScriptBuilder.setSymbolDuringMethodCall()
+ .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) {
- sm.addScript(ScriptBuilder.exitEarly()
+ sm.addScriptIfWitness(OSGI_TYPES, ScriptBuilder.exitEarly()
.target(new MethodTarget("org.eclipse.jdt.core.dom.rewrite.ASTRewrite", "replace"))
.target(new MethodTarget("org.eclipse.jdt.core.dom.rewrite.ASTRewrite", "remove"))
.decisionMethod(new Hook("lombok.launch.PatchFixesHider$PatchFixes", "skipRewritingGeneratedNodes", "boolean",
"org.eclipse.jdt.core.dom.ASTNode"))
.transplant().request(StackRequest.PARAM1).build());
- sm.addScript(ScriptBuilder.wrapMethodCall()
+ sm.addScriptIfWitness(OSGI_TYPES, ScriptBuilder.wrapMethodCall()
.target(new MethodTarget("org.eclipse.jdt.internal.corext.refactoring.rename.RenameTypeProcessor", "addConstructorRenames"))
.methodToWrap(new Hook("org.eclipse.jdt.core.IType", "getMethods", "org.eclipse.jdt.core.IMethod[]"))
.wrapMethod(new Hook("lombok.launch.PatchFixesHider$PatchFixes", "removeGeneratedMethods", "org.eclipse.jdt.core.IMethod[]",
"org.eclipse.jdt.core.IMethod[]"))
.transplant().build());
- sm.addScript(ScriptBuilder.exitEarly()
+ sm.addScriptIfWitness(OSGI_TYPES, ScriptBuilder.exitEarly()
.target(new MethodTarget("org.eclipse.jdt.internal.corext.refactoring.rename.TempOccurrenceAnalyzer", "visit", "boolean", "org.eclipse.jdt.core.dom.SimpleName"))
.target(new MethodTarget("org.eclipse.jdt.internal.corext.refactoring.rename.RenameAnalyzeUtil$ProblemNodeFinder$NameNodeVisitor", "visit", "boolean", "org.eclipse.jdt.core.dom.SimpleName"))
.decisionMethod(new Hook("lombok.launch.PatchFixesHider$PatchFixes", "isGenerated", "boolean", "org.eclipse.jdt.core.dom.ASTNode"))
@@ -401,21 +379,28 @@ public class EclipsePatcher implements AgentLauncher.AgentLaunchable {
}
private static void patchIdentifierEndReparse(ScriptManager sm) {
- sm.addScript(ScriptBuilder.wrapReturnValue()
+ sm.addScriptIfWitness(OSGI_TYPES, ScriptBuilder.wrapReturnValue()
.target(new MethodTarget("org.eclipse.jdt.core.dom.ASTConverter", "retrieveIdentifierEndPosition"))
.wrapMethod(new Hook("lombok.launch.PatchFixesHider$PatchFixes", "fixRetrieveIdentifierEndPosition", "int", "int", "int", "int"))
.transplant().request(StackRequest.RETURN_VALUE, StackRequest.PARAM1, StackRequest.PARAM2).build());
}
private static void patchRetrieveEllipsisStartPosition(ScriptManager sm) {
- sm.addScript(ScriptBuilder.wrapReturnValue()
+ sm.addScriptIfWitness(OSGI_TYPES, ScriptBuilder.wrapReturnValue()
.target(new MethodTarget("org.eclipse.jdt.core.dom.ASTConverter", "retrieveEllipsisStartPosition"))
.wrapMethod(new Hook("lombok.launch.PatchFixesHider$PatchFixes", "fixRetrieveEllipsisStartPosition", "int", "int", "int"))
.transplant().request(StackRequest.RETURN_VALUE, StackRequest.PARAM2).build());
}
+ private static void patchRetrieveStartBlockPosition(ScriptManager sm) {
+ sm.addScriptIfWitness(OSGI_TYPES, ScriptBuilder.wrapReturnValue()
+ .target(new MethodTarget("org.eclipse.jdt.core.dom.ASTConverter", "retrieveStartBlockPosition"))
+ .wrapMethod(new Hook("lombok.launch.PatchFixesHider$PatchFixes", "fixRetrieveStartBlockPosition", "int", "int", "int"))
+ .transplant().request(StackRequest.RETURN_VALUE, StackRequest.PARAM2).build());
+ }
+
private static void patchRetrieveRightBraceOrSemiColonPosition(ScriptManager sm) {
- sm.addScript(ScriptBuilder.wrapMethodCall()
+ sm.addScriptIfWitness(OSGI_TYPES, ScriptBuilder.wrapMethodCall()
.target(new MethodTarget("org.eclipse.jdt.core.dom.ASTConverter", "convert", "org.eclipse.jdt.core.dom.ASTNode", "boolean", "org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration"))
.methodToWrap(new Hook("org.eclipse.jdt.core.dom.ASTConverter", "retrieveRightBraceOrSemiColonPosition", "int", "int", "int"))
.wrapMethod(new Hook("lombok.launch.PatchFixesHider$PatchFixes", "fixRetrieveRightBraceOrSemiColonPosition", "int", "int", "org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration"))
@@ -447,28 +432,36 @@ public class EclipsePatcher implements AgentLauncher.AgentLaunchable {
}
private static void patchRetrieveProperRightBracketPosition(ScriptManager sm) {
- sm.addScript(ScriptBuilder.wrapMethodCall()
+ sm.addScriptIfWitness(OSGI_TYPES, ScriptBuilder.wrapMethodCall()
.target(new MethodTarget("org.eclipse.jdt.core.dom.ASTConverter", "extractSubArrayType", "org.eclipse.jdt.core.dom.ArrayType", "org.eclipse.jdt.core.dom.ArrayType", "int", "int"))
.methodToWrap(new Hook("org.eclipse.jdt.core.dom.ASTConverter", "retrieveProperRightBracketPosition", "int", "int", "int"))
- .wrapMethod(new Hook("lombok.launch.PatchFixesHider$PatchFixes", "fixRetrieveProperRightBracketPosition", "int", "int", "org.eclipse.jdt.core.dom.ArrayType"))
+ .wrapMethod(new Hook("lombok.launch.PatchFixesHider$PatchFixes", "fixRetrieveProperRightBracketPosition", "int", "int", "org.eclipse.jdt.core.dom.Type"))
+ .requestExtra(StackRequest.PARAM1)
+ .transplant()
+ .build());
+
+ sm.addScriptIfWitness(OSGI_TYPES, ScriptBuilder.wrapMethodCall()
+ .target(new MethodTarget("org.eclipse.jdt.core.dom.ASTConverter", "convertToArray", "org.eclipse.jdt.core.dom.ArrayType", "org.eclipse.jdt.core.dom.Type", "int", "int", "int", "org.eclipse.jdt.internal.compiler.ast.Annotation[][]"))
+ .methodToWrap(new Hook("org.eclipse.jdt.core.dom.ASTConverter", "retrieveProperRightBracketPosition", "int", "int", "int"))
+ .wrapMethod(new Hook("lombok.launch.PatchFixesHider$PatchFixes", "fixRetrieveProperRightBracketPosition", "int", "int", "org.eclipse.jdt.core.dom.Type"))
.requestExtra(StackRequest.PARAM1)
.transplant()
.build());
}
private static void patchSetGeneratedFlag(ScriptManager sm) {
- sm.addScript(ScriptBuilder.addField()
+ sm.addScriptIfWitness(OSGI_TYPES, ScriptBuilder.addField()
.targetClass("org.eclipse.jdt.internal.compiler.ast.ASTNode")
.fieldName("$generatedBy")
.fieldType("Lorg/eclipse/jdt/internal/compiler/ast/ASTNode;")
.setPublic().setTransient().build());
- sm.addScript(ScriptBuilder.addField()
+ sm.addScriptIfWitness(OSGI_TYPES, ScriptBuilder.addField()
.targetClass("org.eclipse.jdt.core.dom.ASTNode")
.fieldName("$isGenerated").fieldType("Z")
.setPublic().setTransient().build());
- sm.addScript(ScriptBuilder.wrapReturnValue()
+ sm.addScriptIfWitness(OSGI_TYPES, ScriptBuilder.wrapReturnValue()
.target(new TargetMatcher() {
@Override public boolean matches(String classSpec, String methodName, String descriptor) {
if (!"convert".equals(methodName)) return false;
@@ -480,6 +473,10 @@ public class EclipsePatcher implements AgentLauncher.AgentLaunchable {
return true;
}
+ @Override public String describe() {
+ return "ASTConverter:[all relevant]";
+ }
+
@Override public Collection<String> getAffectedClasses() {
return Collections.singleton("org.eclipse.jdt.core.dom.ASTConverter");
}
@@ -488,14 +485,14 @@ public class EclipsePatcher implements AgentLauncher.AgentLaunchable {
"org.eclipse.jdt.core.dom.ASTNode", "org.eclipse.jdt.internal.compiler.ast.ASTNode"))
.transplant().build());
- sm.addScript(ScriptBuilder.wrapReturnValue()
+ sm.addScriptIfWitness(OSGI_TYPES, ScriptBuilder.wrapReturnValue()
.target(new MethodTarget("org.eclipse.jdt.core.dom.ASTConverter", "convert", "org.eclipse.jdt.core.dom.ASTNode", "boolean", "org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration"))
.request(StackRequest.PARAM2, StackRequest.RETURN_VALUE)
.wrapMethod(new Hook("lombok.launch.PatchFixesHider$PatchFixes", "setIsGeneratedFlag", "void",
"org.eclipse.jdt.core.dom.ASTNode", "org.eclipse.jdt.internal.compiler.ast.ASTNode"))
.transplant().build());
- sm.addScript(ScriptBuilder.wrapReturnValue()
+ sm.addScriptIfWitness(OSGI_TYPES, ScriptBuilder.wrapReturnValue()
.target(new MethodTarget("org.eclipse.jdt.core.dom.ASTConverter", "convertToFieldDeclaration", "org.eclipse.jdt.core.dom.FieldDeclaration", "org.eclipse.jdt.internal.compiler.ast.FieldDeclaration"))
/* Targets beneath are only patched because the resulting dom nodes should be marked if generated.
* However I couldn't find a usecase where these were actually used
@@ -507,6 +504,8 @@ public class EclipsePatcher implements AgentLauncher.AgentLaunchable {
.target(new MethodTarget("org.eclipse.jdt.core.dom.ASTConverter", "convertToVariableDeclarationFragment", "org.eclipse.jdt.core.dom.VariableDeclarationFragment", "org.eclipse.jdt.internal.compiler.ast.FieldDeclaration"))
.target(new MethodTarget("org.eclipse.jdt.core.dom.ASTConverter", "convertToVariableDeclarationFragment", "org.eclipse.jdt.core.dom.VariableDeclarationFragment", "org.eclipse.jdt.internal.compiler.ast.LocalDeclaration"))
.target(new MethodTarget("org.eclipse.jdt.core.dom.ASTConverter", "convertToVariableDeclarationStatement", "org.eclipse.jdt.core.dom.VariableDeclarationStatement", "org.eclipse.jdt.internal.compiler.ast.LocalDeclaration"))
+ .target(new MethodTarget("org.eclipse.jdt.core.dom.ASTConverter", "createBaseType", "org.eclipse.jdt.core.dom.Type", "org.eclipse.jdt.internal.compiler.ast.TypeReference", "long[]", "org.eclipse.jdt.internal.compiler.ast.Annotation[][]", "char[][]", "int", "int", "boolean"))
+ .target(new MethodTarget("org.eclipse.jdt.core.dom.ASTConverter", "createQualifiedType", "org.eclipse.jdt.core.dom.QualifiedType", "org.eclipse.jdt.internal.compiler.ast.TypeReference", "long[]", "org.eclipse.jdt.internal.compiler.ast.Annotation[][]", "char[][]", "int", "org.eclipse.jdt.core.dom.Type"))
/* Targets above are only patched because the resulting dom nodes should be marked if generated. */
.request(StackRequest.PARAM1, StackRequest.RETURN_VALUE)
.wrapMethod(new Hook("lombok.launch.PatchFixesHider$PatchFixes", "setIsGeneratedFlag", "void",
@@ -514,7 +513,7 @@ public class EclipsePatcher implements AgentLauncher.AgentLaunchable {
.transplant().build());
/* Set generated flag for SimpleNames */
- sm.addScript(ScriptBuilder.wrapMethodCall()
+ sm.addScriptIfWitness(OSGI_TYPES, ScriptBuilder.wrapMethodCall()
.target(new TargetMatcher() {
@Override public boolean matches(String classSpec, String methodName, String descriptor) {
if (!methodName.startsWith("convert")) return false;
@@ -526,6 +525,10 @@ public class EclipsePatcher implements AgentLauncher.AgentLaunchable {
return true;
}
+ @Override public String describe() {
+ return "ASTConverter::(all relevant)";
+ }
+
@Override public Collection<String> getAffectedClasses() {
return Collections.singleton("org.eclipse.jdt.core.dom.ASTConverter");
}
@@ -535,16 +538,53 @@ public class EclipsePatcher implements AgentLauncher.AgentLaunchable {
"org.eclipse.jdt.core.dom.Name", "java.lang.Object"))
.transplant().build());
- sm.addScript(ScriptBuilder.wrapMethodCall()
+ sm.addScriptIfWitness(OSGI_TYPES, ScriptBuilder.wrapMethodCall()
.target(new MethodTarget("org.eclipse.jdt.core.dom.ASTConverter", "convert", "org.eclipse.jdt.core.dom.ASTNode", "boolean", "org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration"))
.methodToWrap(new Hook("org.eclipse.jdt.core.dom.SimpleName", "<init>", "void", "org.eclipse.jdt.core.dom.AST"))
.requestExtra(StackRequest.PARAM2)
.wrapMethod(new Hook("lombok.launch.PatchFixesHider$PatchFixes", "setIsGeneratedFlagForName", "void",
"org.eclipse.jdt.core.dom.Name", "java.lang.Object"))
.transplant().build());
+
+
+ sm.addScriptIfWitness(OSGI_TYPES, ScriptBuilder.wrapMethodCall()
+ .target(new MethodTarget("org.eclipse.jdt.core.dom.ASTConverter", "convertType", "org.eclipse.jdt.core.dom.Type", "org.eclipse.jdt.internal.compiler.ast.TypeReference"))
+ .methodToWrap(new Hook("org.eclipse.jdt.core.dom.PrimitiveType", "<init>", "void", "org.eclipse.jdt.core.dom.AST"))
+ .requestExtra(StackRequest.PARAM1)
+ .wrapMethod(new Hook("lombok.launch.PatchFixesHider$PatchFixes", "setIsGeneratedFlag", "void",
+ "org.eclipse.jdt.core.dom.ASTNode", "org.eclipse.jdt.internal.compiler.ast.ASTNode"))
+ .transplant()
+ .build());
+
+ sm.addScriptIfWitness(OSGI_TYPES, ScriptBuilder.wrapMethodCall()
+ .target(new MethodTarget("org.eclipse.jdt.core.dom.ASTConverter", "convertType", "org.eclipse.jdt.core.dom.Type", "org.eclipse.jdt.internal.compiler.ast.TypeReference"))
+ .methodToWrap(new Hook("org.eclipse.jdt.core.dom.SimpleType", "<init>", "void", "org.eclipse.jdt.core.dom.AST"))
+ .requestExtra(StackRequest.PARAM1)
+ .wrapMethod(new Hook("lombok.launch.PatchFixesHider$PatchFixes", "setIsGeneratedFlag", "void",
+ "org.eclipse.jdt.core.dom.ASTNode", "org.eclipse.jdt.internal.compiler.ast.ASTNode"))
+ .transplant()
+ .build());
+
+ sm.addScriptIfWitness(OSGI_TYPES, ScriptBuilder.wrapMethodCall()
+ .target(new MethodTarget("org.eclipse.jdt.core.dom.ASTConverter", "convertType", "org.eclipse.jdt.core.dom.Type", "org.eclipse.jdt.internal.compiler.ast.TypeReference"))
+ .methodToWrap(new Hook("org.eclipse.jdt.core.dom.ParameterizedType", "<init>", "void", "org.eclipse.jdt.core.dom.AST"))
+ .requestExtra(StackRequest.PARAM1)
+ .wrapMethod(new Hook("lombok.launch.PatchFixesHider$PatchFixes", "setIsGeneratedFlag", "void",
+ "org.eclipse.jdt.core.dom.ASTNode", "org.eclipse.jdt.internal.compiler.ast.ASTNode"))
+ .transplant()
+ .build());
+
+ sm.addScriptIfWitness(OSGI_TYPES, ScriptBuilder.wrapMethodCall()
+ .target(new MethodTarget("org.eclipse.jdt.core.dom.ASTConverter", "convertType", "org.eclipse.jdt.core.dom.Type", "org.eclipse.jdt.internal.compiler.ast.TypeReference"))
+ .methodToWrap(new Hook("org.eclipse.jdt.core.dom.QualifiedType", "<init>", "void", "org.eclipse.jdt.core.dom.AST"))
+ .requestExtra(StackRequest.PARAM1)
+ .wrapMethod(new Hook("lombok.launch.PatchFixesHider$PatchFixes", "setIsGeneratedFlag", "void",
+ "org.eclipse.jdt.core.dom.ASTNode", "org.eclipse.jdt.internal.compiler.ast.ASTNode"))
+ .transplant()
+ .build());
/* Set generated flag for QualifiedNames */
- sm.addScript(ScriptBuilder.wrapMethodCall()
+ sm.addScriptIfWitness(OSGI_TYPES, ScriptBuilder.wrapMethodCall()
.target(new MethodTarget("org.eclipse.jdt.core.dom.ASTConverter", "setQualifiedNameNameAndSourceRanges", "org.eclipse.jdt.core.dom.QualifiedName", "char[][]", "long[]", "int", "org.eclipse.jdt.internal.compiler.ast.ASTNode"))
.methodToWrap(new Hook("org.eclipse.jdt.core.dom.SimpleName", "<init>", "void", "org.eclipse.jdt.core.dom.AST"))
.requestExtra(StackRequest.PARAM4)
@@ -552,7 +592,7 @@ public class EclipsePatcher implements AgentLauncher.AgentLaunchable {
"org.eclipse.jdt.core.dom.Name", "java.lang.Object"))
.transplant().build());
- sm.addScript(ScriptBuilder.wrapMethodCall()
+ sm.addScriptIfWitness(OSGI_TYPES, ScriptBuilder.wrapMethodCall()
.target(new MethodTarget("org.eclipse.jdt.core.dom.ASTConverter", "setQualifiedNameNameAndSourceRanges", "org.eclipse.jdt.core.dom.QualifiedName", "char[][]", "long[]", "int", "org.eclipse.jdt.internal.compiler.ast.ASTNode"))
.methodToWrap(new Hook("org.eclipse.jdt.core.dom.QualifiedName", "<init>", "void", "org.eclipse.jdt.core.dom.AST"))
.requestExtra(StackRequest.PARAM4)
@@ -560,7 +600,7 @@ public class EclipsePatcher implements AgentLauncher.AgentLaunchable {
"org.eclipse.jdt.core.dom.Name", "java.lang.Object"))
.transplant().build());
- sm.addScript(ScriptBuilder.wrapMethodCall()
+ sm.addScriptIfWitness(OSGI_TYPES, ScriptBuilder.wrapMethodCall()
.target(new MethodTarget("org.eclipse.jdt.core.dom.ASTConverter", "setQualifiedNameNameAndSourceRanges", "org.eclipse.jdt.core.dom.QualifiedName", "char[][]", "long[]", "org.eclipse.jdt.internal.compiler.ast.ASTNode"))
.methodToWrap(new Hook("org.eclipse.jdt.core.dom.SimpleName", "<init>", "void", "org.eclipse.jdt.core.dom.AST"))
.requestExtra(StackRequest.PARAM3)
@@ -568,7 +608,7 @@ public class EclipsePatcher implements AgentLauncher.AgentLaunchable {
"org.eclipse.jdt.core.dom.Name", "java.lang.Object"))
.transplant().build());
- sm.addScript(ScriptBuilder.wrapMethodCall()
+ sm.addScriptIfWitness(OSGI_TYPES, ScriptBuilder.wrapMethodCall()
.target(new MethodTarget("org.eclipse.jdt.core.dom.ASTConverter", "setQualifiedNameNameAndSourceRanges", "org.eclipse.jdt.core.dom.QualifiedName", "char[][]", "long[]", "org.eclipse.jdt.internal.compiler.ast.ASTNode"))
.methodToWrap(new Hook("org.eclipse.jdt.core.dom.QualifiedName", "<init>", "void", "org.eclipse.jdt.core.dom.AST"))
.requestExtra(StackRequest.PARAM3)
@@ -576,7 +616,7 @@ public class EclipsePatcher implements AgentLauncher.AgentLaunchable {
"org.eclipse.jdt.core.dom.Name", "java.lang.Object"))
.transplant().build());
- sm.addScript(ScriptBuilder.wrapMethodCall()
+ sm.addScriptIfWitness(OSGI_TYPES, ScriptBuilder.wrapMethodCall()
.target(new MethodTarget("org.eclipse.jdt.core.dom.ASTConverter", "setTypeNameForAnnotation", "void", "org.eclipse.jdt.internal.compiler.ast.Annotation", "org.eclipse.jdt.core.dom.Annotation"))
.methodToWrap(new Hook("org.eclipse.jdt.core.dom.SimpleName", "<init>", "void", "org.eclipse.jdt.core.dom.AST"))
.requestExtra(StackRequest.PARAM1)
@@ -584,7 +624,7 @@ public class EclipsePatcher implements AgentLauncher.AgentLaunchable {
"org.eclipse.jdt.core.dom.Name", "java.lang.Object"))
.transplant().build());
- sm.addScript(ScriptBuilder.wrapMethodCall()
+ sm.addScriptIfWitness(OSGI_TYPES, ScriptBuilder.wrapMethodCall()
.target(new MethodTarget("org.eclipse.jdt.core.dom.ASTConverter", "setTypeNameForAnnotation", "void", "org.eclipse.jdt.internal.compiler.ast.Annotation", "org.eclipse.jdt.core.dom.Annotation"))
.methodToWrap(new Hook("org.eclipse.jdt.core.dom.QualifiedName", "<init>", "void", "org.eclipse.jdt.core.dom.AST"))
.requestExtra(StackRequest.PARAM1)
@@ -629,25 +669,26 @@ public class EclipsePatcher implements AgentLauncher.AgentLaunchable {
final String PARSER_SIG = "org.eclipse.jdt.internal.compiler.parser.Parser";
final String CUD_SIG = "org.eclipse.jdt.internal.compiler.ast.CompilationUnitDeclaration";
+ final String OBJECT_SIG = "java.lang.Object";
sm.addScript(ScriptBuilder.wrapReturnValue()
.target(new MethodTarget(PARSER_SIG, "getMethodBodies", "void", CUD_SIG))
- .wrapMethod(new Hook("lombok.launch.PatchFixesHider$Transform", "transform", "void", PARSER_SIG, CUD_SIG))
+ .wrapMethod(new Hook("lombok.launch.PatchFixesHider$Transform", "transform", "void", OBJECT_SIG, OBJECT_SIG))
.request(StackRequest.THIS, StackRequest.PARAM1).build());
sm.addScript(ScriptBuilder.wrapReturnValue()
.target(new MethodTarget(PARSER_SIG, "endParse", CUD_SIG, "int"))
- .wrapMethod(new Hook("lombok.launch.PatchFixesHider$Transform", "transform_swapped", "void", CUD_SIG, PARSER_SIG))
+ .wrapMethod(new Hook("lombok.launch.PatchFixesHider$Transform", "transform_swapped", "void", OBJECT_SIG, OBJECT_SIG))
.request(StackRequest.THIS, StackRequest.RETURN_VALUE).build());
}
- private static void patchEcjTransformers(ScriptManager sm, boolean ecj) {
- addPatchesForDelegate(sm, ecj);
+ private static void patchEcjTransformers(ScriptManager sm) {
+ addPatchesForDelegate(sm);
addPatchesForVal(sm);
- if (!ecj) addPatchesForValEclipse(sm);
+ addPatchesForValEclipse(sm);
}
- private static void addPatchesForDelegate(ScriptManager sm, boolean ecj) {
+ private static void addPatchesForDelegate(ScriptManager sm) {
final String CLASSSCOPE_SIG = "org.eclipse.jdt.internal.compiler.lookup.ClassScope";
sm.addScript(ScriptBuilder.exitEarly()
@@ -655,6 +696,26 @@ public class EclipsePatcher implements AgentLauncher.AgentLaunchable {
.request(StackRequest.THIS)
.decisionMethod(new Hook("lombok.launch.PatchFixesHider$Delegate", "handleDelegateForType", "boolean", "java.lang.Object"))
.build());
+
+ sm.addScriptIfWitness(OSGI_TYPES, ScriptBuilder.setSymbolDuringMethodCall()
+ .target(new MethodTarget("org.eclipse.jdt.internal.core.SelectionRequestor", "acceptSourceMethod"))
+ .callToWrap(new Hook("org.eclipse.jdt.core.IType", "getMethods", "org.eclipse.jdt.core.IMethod[]"))
+ .symbol("lombok.skipdelegates")
+ .build());
+
+ sm.addScriptIfWitness(OSGI_TYPES, ScriptBuilder.addField()
+ .fieldName("$delegateMethods")
+ .fieldType("Ljava/util/Map;")
+ .setPublic()
+ .setTransient()
+ .targetClass("org.eclipse.jdt.internal.core.CompilationUnit")
+ .build());
+
+ sm.addScriptIfWitness(OSGI_TYPES, ScriptBuilder.wrapReturnValue()
+ .target(new MethodTarget("org.eclipse.jdt.internal.core.SourceTypeElementInfo", "getChildren", "org.eclipse.jdt.core.IJavaElement[]"))
+ .request(StackRequest.RETURN_VALUE, StackRequest.THIS)
+ .wrapMethod(new Hook("lombok.launch.PatchFixesHider$Delegate", "addGeneratedDelegateMethods", "java.lang.Object[]", "java.lang.Object", "java.lang.Object"))
+ .build());
}
private static void addPatchesForValEclipse(ScriptManager sm) {
@@ -664,7 +725,7 @@ public class EclipsePatcher implements AgentLauncher.AgentLaunchable {
final String SINGLEVARIABLEDECLARATION_SIG = "org.eclipse.jdt.core.dom.SingleVariableDeclaration";
final String ASTCONVERTER_SIG = "org.eclipse.jdt.core.dom.ASTConverter";
- sm.addScript(ScriptBuilder.addField()
+ sm.addScriptIfWitness(OSGI_TYPES, ScriptBuilder.addField()
.fieldName("$initCopy")
.fieldType("Lorg/eclipse/jdt/internal/compiler/ast/ASTNode;")
.setPublic()
@@ -672,7 +733,7 @@ public class EclipsePatcher implements AgentLauncher.AgentLaunchable {
.targetClass("org.eclipse.jdt.internal.compiler.ast.LocalDeclaration")
.build());
- sm.addScript(ScriptBuilder.addField()
+ sm.addScriptIfWitness(OSGI_TYPES, ScriptBuilder.addField()
.fieldName("$iterableCopy")
.fieldType("Lorg/eclipse/jdt/internal/compiler/ast/ASTNode;")
.setPublic()
@@ -680,25 +741,25 @@ public class EclipsePatcher implements AgentLauncher.AgentLaunchable {
.targetClass("org.eclipse.jdt.internal.compiler.ast.LocalDeclaration")
.build());
- sm.addScript(ScriptBuilder.wrapReturnValue()
+ sm.addScriptIfWitness(OSGI_TYPES, ScriptBuilder.wrapReturnValue()
.target(new MethodTarget(PARSER_SIG, "consumeExitVariableWithInitialization", "void"))
.request(StackRequest.THIS)
.wrapMethod(new Hook("lombok.launch.PatchFixesHider$ValPortal", "copyInitializationOfLocalDeclaration", "void", "java.lang.Object"))
.build());
- sm.addScript(ScriptBuilder.wrapReturnValue()
+ sm.addScriptIfWitness(OSGI_TYPES, ScriptBuilder.wrapReturnValue()
.target(new MethodTarget(PARSER_SIG, "consumeEnhancedForStatementHeader", "void"))
.request(StackRequest.THIS)
.wrapMethod(new Hook("lombok.launch.PatchFixesHider$ValPortal", "copyInitializationOfForEachIterable", "void", "java.lang.Object"))
.build());
- sm.addScript(ScriptBuilder.wrapReturnValue()
+ sm.addScriptIfWitness(OSGI_TYPES, ScriptBuilder.wrapReturnValue()
.target(new MethodTarget(ASTCONVERTER_SIG, "setModifiers", "void", VARIABLEDECLARATIONSTATEMENT_SIG, LOCALDECLARATION_SIG))
.wrapMethod(new Hook("lombok.launch.PatchFixesHider$ValPortal", "addFinalAndValAnnotationToVariableDeclarationStatement",
"void", "java.lang.Object", "java.lang.Object", "java.lang.Object"))
.request(StackRequest.THIS, StackRequest.PARAM1, StackRequest.PARAM2).build());
- sm.addScript(ScriptBuilder.wrapReturnValue()
+ sm.addScriptIfWitness(OSGI_TYPES, ScriptBuilder.wrapReturnValue()
.target(new MethodTarget(ASTCONVERTER_SIG, "setModifiers", "void", SINGLEVARIABLEDECLARATION_SIG, LOCALDECLARATION_SIG))
.wrapMethod(new Hook("lombok.launch.PatchFixesHider$ValPortal", "addFinalAndValAnnotationToSingleVariableDeclaration",
"void", "java.lang.Object", "java.lang.Object", "java.lang.Object"))
@@ -711,11 +772,12 @@ public class EclipsePatcher implements AgentLauncher.AgentLaunchable {
final String EXPRESSION_SIG = "org.eclipse.jdt.internal.compiler.ast.Expression";
final String BLOCKSCOPE_SIG = "org.eclipse.jdt.internal.compiler.lookup.BlockScope";
final String TYPEBINDING_SIG = "org.eclipse.jdt.internal.compiler.lookup.TypeBinding";
+ final String OBJECT_SIG = "java.lang.Object";
sm.addScript(ScriptBuilder.exitEarly()
.target(new MethodTarget(LOCALDECLARATION_SIG, "resolve", "void", BLOCKSCOPE_SIG))
.request(StackRequest.THIS, StackRequest.PARAM1)
- .decisionMethod(new Hook("lombok.launch.PatchFixesHider$Val", "handleValForLocalDeclaration", "boolean", LOCALDECLARATION_SIG, BLOCKSCOPE_SIG))
+ .decisionMethod(new Hook("lombok.launch.PatchFixesHider$Val", "handleValForLocalDeclaration", "boolean", OBJECT_SIG, OBJECT_SIG))
.build());
sm.addScript(ScriptBuilder.replaceMethodCall()
@@ -723,18 +785,20 @@ public class EclipsePatcher implements AgentLauncher.AgentLaunchable {
.methodToReplace(new Hook(EXPRESSION_SIG, "resolveType", TYPEBINDING_SIG, BLOCKSCOPE_SIG))
.requestExtra(StackRequest.THIS)
.replacementMethod(new Hook("lombok.launch.PatchFixesHider$Val", "skipResolveInitializerIfAlreadyCalled2", TYPEBINDING_SIG, EXPRESSION_SIG, BLOCKSCOPE_SIG, LOCALDECLARATION_SIG))
+ .transplant()
.build());
sm.addScript(ScriptBuilder.replaceMethodCall()
.target(new MethodTarget(FOREACHSTATEMENT_SIG, "resolve", "void", BLOCKSCOPE_SIG))
.methodToReplace(new Hook(EXPRESSION_SIG, "resolveType", TYPEBINDING_SIG, BLOCKSCOPE_SIG))
.replacementMethod(new Hook("lombok.launch.PatchFixesHider$Val", "skipResolveInitializerIfAlreadyCalled", TYPEBINDING_SIG, EXPRESSION_SIG, BLOCKSCOPE_SIG))
+ .transplant()
.build());
sm.addScript(ScriptBuilder.exitEarly()
.target(new MethodTarget(FOREACHSTATEMENT_SIG, "resolve", "void", BLOCKSCOPE_SIG))
.request(StackRequest.THIS, StackRequest.PARAM1)
- .decisionMethod(new Hook("lombok.launch.PatchFixesHider$Val", "handleValForForEach", "boolean", FOREACHSTATEMENT_SIG, BLOCKSCOPE_SIG))
+ .decisionMethod(new Hook("lombok.launch.PatchFixesHider$Val", "handleValForForEach", "boolean", OBJECT_SIG, OBJECT_SIG))
.build());
}
@@ -743,7 +807,7 @@ public class EclipsePatcher implements AgentLauncher.AgentLaunchable {
final String I_ANNOTATABLE_SIG = "org.eclipse.jdt.core.IAnnotatable";
final String ANNOTATION_SIG = "org.eclipse.jdt.internal.compiler.ast.Annotation";
- sm.addScript(ScriptBuilder.wrapReturnValue()
+ sm.addScriptIfWitness(OSGI_TYPES, ScriptBuilder.wrapReturnValue()
.target(new MethodTarget(SOURCE_TYPE_CONVERTER_SIG, "convertAnnotations", ANNOTATION_SIG + "[]", I_ANNOTATABLE_SIG))
.wrapMethod(new Hook("lombok.launch.PatchFixesHider$PatchFixes", "convertAnnotations", ANNOTATION_SIG + "[]", ANNOTATION_SIG + "[]", I_ANNOTATABLE_SIG))
.request(StackRequest.PARAM1, StackRequest.RETURN_VALUE).build());
@@ -753,7 +817,7 @@ public class EclipsePatcher implements AgentLauncher.AgentLaunchable {
final String ASTNODE_SIG = "org.eclipse.jdt.core.dom.ASTNode";
final String PATCH_DEBUG = "lombok.eclipse.agent.PatchDiagnostics";
- sm.addScript(exitEarly()
+ sm.addScriptIfWitness(OSGI_TYPES, exitEarly()
.target(new MethodTarget(ASTNODE_SIG, "setSourceRange", "void", "int", "int"))
.request(StackRequest.THIS)
.request(StackRequest.PARAM1)
@@ -762,7 +826,7 @@ public class EclipsePatcher implements AgentLauncher.AgentLaunchable {
.build());
}
- private static void patchExtensionMethod(ScriptManager sm, boolean ecj) {
+ private static void patchExtensionMethod(ScriptManager sm) {
final String PATCH_EXTENSIONMETHOD = "lombok.launch.PatchFixesHider$ExtensionMethod";
final String PATCH_EXTENSIONMETHOD_COMPLETIONPROPOSAL_PORTAL = "lombok.eclipse.agent.PatchExtensionMethodCompletionProposalPortal";
final String MESSAGE_SEND_SIG = "org.eclipse.jdt.internal.compiler.ast.MessageSend";
@@ -774,42 +838,50 @@ public class EclipsePatcher implements AgentLauncher.AgentLaunchable {
final String METHOD_BINDING_SIG = "org.eclipse.jdt.internal.compiler.lookup.MethodBinding";
final String COMPLETION_PROPOSAL_COLLECTOR_SIG = "org.eclipse.jdt.ui.text.java.CompletionProposalCollector";
final String I_JAVA_COMPLETION_PROPOSAL_SIG = "org.eclipse.jdt.ui.text.java.IJavaCompletionProposal[]";
+ final String AST_NODE = "org.eclipse.jdt.internal.compiler.ast.ASTNode";
+ final String OBJECT_SIG = "java.lang.Object";
sm.addScript(wrapReturnValue()
.target(new MethodTarget(MESSAGE_SEND_SIG, "resolveType", TYPE_BINDING_SIG, BLOCK_SCOPE_SIG))
.request(StackRequest.RETURN_VALUE)
.request(StackRequest.THIS)
.request(StackRequest.PARAM1)
- .wrapMethod(new Hook(PATCH_EXTENSIONMETHOD, "resolveType", TYPE_BINDING_SIG, TYPE_BINDING_SIG, MESSAGE_SEND_SIG, BLOCK_SCOPE_SIG))
+ .wrapMethod(new Hook(PATCH_EXTENSIONMETHOD, "resolveType", OBJECT_SIG, OBJECT_SIG, OBJECT_SIG, OBJECT_SIG))
+ .cast()
.build());
sm.addScript(replaceMethodCall()
.target(new MethodTarget(MESSAGE_SEND_SIG, "resolveType", TYPE_BINDING_SIG, BLOCK_SCOPE_SIG))
.methodToReplace(new Hook(PROBLEM_REPORTER_SIG, "errorNoMethodFor", "void", MESSAGE_SEND_SIG, TYPE_BINDING_SIG, TYPE_BINDINGS_SIG))
- .replacementMethod(new Hook(PATCH_EXTENSIONMETHOD, "errorNoMethodFor", "void", PROBLEM_REPORTER_SIG, MESSAGE_SEND_SIG, TYPE_BINDING_SIG, TYPE_BINDINGS_SIG))
+ .replacementMethod(new Hook(PATCH_EXTENSIONMETHOD, "errorNoMethodFor", "void", OBJECT_SIG, OBJECT_SIG, OBJECT_SIG, OBJECT_SIG))
.build());
sm.addScript(replaceMethodCall()
.target(new MethodTarget(MESSAGE_SEND_SIG, "resolveType", TYPE_BINDING_SIG, BLOCK_SCOPE_SIG))
.methodToReplace(new Hook(PROBLEM_REPORTER_SIG, "invalidMethod", "void", MESSAGE_SEND_SIG, METHOD_BINDING_SIG))
- .replacementMethod(new Hook(PATCH_EXTENSIONMETHOD, "invalidMethod", "void", PROBLEM_REPORTER_SIG, MESSAGE_SEND_SIG, METHOD_BINDING_SIG))
+ .replacementMethod(new Hook(PATCH_EXTENSIONMETHOD, "invalidMethod", "void", OBJECT_SIG, OBJECT_SIG, OBJECT_SIG))
.build());
// Since eclipse mars; they added a param.
sm.addScript(replaceMethodCall()
.target(new MethodTarget(MESSAGE_SEND_SIG, "resolveType", TYPE_BINDING_SIG, BLOCK_SCOPE_SIG))
.methodToReplace(new Hook(PROBLEM_REPORTER_SIG, "invalidMethod", "void", MESSAGE_SEND_SIG, METHOD_BINDING_SIG, SCOPE_SIG))
- .replacementMethod(new Hook(PATCH_EXTENSIONMETHOD, "invalidMethod", "void", PROBLEM_REPORTER_SIG, MESSAGE_SEND_SIG, METHOD_BINDING_SIG, SCOPE_SIG))
+ .replacementMethod(new Hook(PATCH_EXTENSIONMETHOD, "invalidMethod", "void", OBJECT_SIG, OBJECT_SIG, OBJECT_SIG, OBJECT_SIG))
.build());
- if (!ecj) {
- sm.addScript(wrapReturnValue()
- .target(new MethodTarget(COMPLETION_PROPOSAL_COLLECTOR_SIG, "getJavaCompletionProposals", I_JAVA_COMPLETION_PROPOSAL_SIG))
- .request(StackRequest.RETURN_VALUE)
- .request(StackRequest.THIS)
- .wrapMethod(new Hook(PATCH_EXTENSIONMETHOD_COMPLETIONPROPOSAL_PORTAL, "getJavaCompletionProposals", I_JAVA_COMPLETION_PROPOSAL_SIG, "java.lang.Object[]", "java.lang.Object"))
- .build());
- }
+ sm.addScript(replaceMethodCall()
+ .target(new MethodTarget(MESSAGE_SEND_SIG, "resolveType", TYPE_BINDING_SIG, BLOCK_SCOPE_SIG))
+ .methodToReplace(new Hook(PROBLEM_REPORTER_SIG, "nonStaticAccessToStaticMethod", "void", AST_NODE, METHOD_BINDING_SIG))
+ .replacementMethod(new Hook(PATCH_EXTENSIONMETHOD, "nonStaticAccessToStaticMethod", "void", OBJECT_SIG, OBJECT_SIG, OBJECT_SIG, OBJECT_SIG))
+ .requestExtra(StackRequest.THIS)
+ .build());
+
+ sm.addScriptIfWitness(OSGI_TYPES, wrapReturnValue()
+ .target(new MethodTarget(COMPLETION_PROPOSAL_COLLECTOR_SIG, "getJavaCompletionProposals", I_JAVA_COMPLETION_PROPOSAL_SIG))
+ .request(StackRequest.RETURN_VALUE)
+ .request(StackRequest.THIS)
+ .wrapMethod(new Hook(PATCH_EXTENSIONMETHOD_COMPLETIONPROPOSAL_PORTAL, "getJavaCompletionProposals", I_JAVA_COMPLETION_PROPOSAL_SIG, "java.lang.Object[]", "java.lang.Object"))
+ .build());
}
private static void patchNullCheck(ScriptManager sm) {
@@ -830,5 +902,37 @@ public class EclipsePatcher implements AgentLauncher.AgentLaunchable {
.request(StackRequest.PARAM1)
.transplant().build());
}
+
+ private static void patchJavadoc(ScriptManager sm) {
+ sm.addScriptIfWitness(OSGI_TYPES, ScriptBuilder.wrapMethodCall()
+ .target(new MethodTarget("org.eclipse.jdt.internal.ui.text.javadoc.JavadocContentAccess2", "getHTMLContent", "java.lang.String", "org.eclipse.jdt.core.IJavaElement", "boolean"))
+ .methodToWrap(new Hook("org.eclipse.jdt.internal.ui.text.javadoc.JavadocContentAccess2", "getHTMLContentFromSource", "java.lang.String", "org.eclipse.jdt.core.IJavaElement"))
+ .wrapMethod(new Hook("lombok.launch.PatchFixesHider$Javadoc", "getHTMLContentFromSource", "java.lang.String", "java.lang.String", "org.eclipse.jdt.core.IJavaElement"))
+ .requestExtra(StackRequest.PARAM1)
+ .build());
+
+ /* This is an older version that uses IMember instead of IJavaElement */
+ sm.addScriptIfWitness(OSGI_TYPES, ScriptBuilder.wrapMethodCall()
+ .target(new MethodTarget("org.eclipse.jdt.internal.ui.text.javadoc.JavadocContentAccess2", "getHTMLContent", "java.lang.String", "org.eclipse.jdt.core.IMember", "boolean"))
+ .methodToWrap(new Hook("org.eclipse.jdt.internal.ui.text.javadoc.JavadocContentAccess2", "getHTMLContentFromSource", "java.lang.String", "org.eclipse.jdt.core.IMember"))
+ .wrapMethod(new Hook("lombok.launch.PatchFixesHider$Javadoc", "getHTMLContentFromSource", "java.lang.String", "java.lang.String", "org.eclipse.jdt.core.IJavaElement"))
+ .requestExtra(StackRequest.PARAM1)
+ .build());
+
+ sm.addScript(ScriptBuilder.replaceMethodCall()
+ .target(new MethodTarget("org.eclipse.jdt.internal.compiler.ast.TypeDeclaration", "printBody", "java.lang.StringBuffer", "int", "java.lang.StringBuffer"))
+ .methodToReplace(new Hook("org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration", "print", "java.lang.StringBuffer", "int", "java.lang.StringBuffer"))
+ .replacementMethod(new Hook("lombok.launch.PatchFixesHider$Javadoc", "printMethod", "java.lang.StringBuffer", "org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration", "int", "java.lang.StringBuffer", "org.eclipse.jdt.internal.compiler.ast.TypeDeclaration"))
+ .requestExtra(StackRequest.THIS)
+ .build());
+
+ sm.addScriptIfWitness(OSGI_TYPES, ScriptBuilder.addField()
+ .fieldName("$javadoc")
+ .fieldType("Ljava/util/Map;")
+ .setPublic()
+ .setTransient()
+ .targetClass("org.eclipse.jdt.internal.core.CompilationUnit")
+ .build());
+ }
}
diff --git a/src/eclipseAgent/lombok/eclipse/agent/ExtensionMethodCompletionProposal.java b/src/eclipseAgent/lombok/eclipse/agent/ExtensionMethodCompletionProposal.java
index 46ce63f9..833a8226 100644
--- a/src/eclipseAgent/lombok/eclipse/agent/ExtensionMethodCompletionProposal.java
+++ b/src/eclipseAgent/lombok/eclipse/agent/ExtensionMethodCompletionProposal.java
@@ -22,10 +22,15 @@
package lombok.eclipse.agent;
import static org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants.AccStatic;
+import static org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants.AccVarargs;
import java.util.Arrays;
+import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.jdt.core.CompletionProposal;
+import org.eclipse.jdt.core.IMethod;
+import org.eclipse.jdt.core.JavaModelException;
+import org.eclipse.jdt.core.Signature;
import org.eclipse.jdt.core.compiler.CharOperation;
import org.eclipse.jdt.internal.codeassist.CompletionEngine;
import org.eclipse.jdt.internal.codeassist.InternalCompletionProposal;
@@ -35,16 +40,29 @@ import org.eclipse.jdt.internal.codeassist.complete.CompletionOnSingleNameRefere
import org.eclipse.jdt.internal.compiler.ast.ASTNode;
import org.eclipse.jdt.internal.compiler.lookup.MethodBinding;
import org.eclipse.jdt.internal.compiler.lookup.TypeBinding;
+import org.eclipse.jdt.internal.core.NameLookup;
public class ExtensionMethodCompletionProposal extends InternalCompletionProposal {
+ private char[] fullSignature;
+ private char[][] parameterNames;
+
public ExtensionMethodCompletionProposal(final int replacementOffset) {
super(CompletionProposal.METHOD_REF, replacementOffset - 1);
}
public void setMethodBinding(final MethodBinding method, final ASTNode node) {
+ // Add proposal parameter names, sometimes its empty...
+ if (method.parameterNames != null && method.parameterNames.length > 0) {
+ setParameterNames(Arrays.copyOfRange(method.parameterNames, 1, method.parameterNames.length));
+ } else {
+ // Copy signature for parameter name resolution, this is more reliable but slower
+ fullSignature = CompletionEngine.getSignature(method);
+ }
+
MethodBinding original = method.original();
TypeBinding[] parameters = Arrays.copyOf(method.parameters, method.parameters.length);
method.parameters = Arrays.copyOfRange(method.parameters, 1, method.parameters.length);
+
TypeBinding[] originalParameters = null;
if (original != method) {
originalParameters = Arrays.copyOf(method.original().parameters, method.original().parameters.length);
@@ -76,6 +94,10 @@ public class ExtensionMethodCompletionProposal extends InternalCompletionProposa
setName(method.selector);
setCompletion(completion);
setFlags(method.modifiers & (~AccStatic));
+ // Remove varargs flag if it is the only parameter
+ if (method.isVarargs() && length == 0) {
+ setFlags(getFlags() & (~AccVarargs));
+ }
int index = node.sourceEnd + 1;
if (node instanceof CompletionOnQualifiedNameReference) {
index -= ((CompletionOnQualifiedNameReference) node).completionIdentifier.length;
@@ -96,4 +118,58 @@ public class ExtensionMethodCompletionProposal extends InternalCompletionProposa
method.original().parameters = originalParameters;
}
}
+
+ @Override
+ public char[][] findParameterNames(IProgressMonitor monitor) {
+ if (parameterNames != null) {
+ return parameterNames;
+ }
+
+ NameLookup.Answer answer = this.nameLookup.findType(
+ new String(this.declarationTypeName),
+ new String(this.declarationPackageName),
+ false,
+ NameLookup.ACCEPT_CLASSES & NameLookup.ACCEPT_INTERFACES,
+ true/* consider secondary types */,
+ false/* do NOT wait for indexes */,
+ false/*don't check restrictions*/,
+ null);
+
+ if (answer != null && answer.type != null) {
+ char[][] parameterTypes = Signature.getParameterTypes(fullSignature);
+
+ String[] args = new String[parameterTypes.length];
+ for (int i = 0; i < parameterTypes.length; i++) {
+ args[i] = new String(parameterTypes[i]);
+ }
+ IMethod method = answer.type.getMethod(new String(this.getName()), args);
+ IMethod[] methods = answer.type.findMethods(method);
+ if (methods != null && methods.length > 0) {
+ method = methods[0];
+ }
+ if (method != null) {
+ try {
+ String[] parameterNames = method.getParameterNames();
+ char[][] parameterNamesAsChar = new char[parameterNames.length - 1][];
+ for (int i = 0; i < parameterNamesAsChar.length; i++) {
+ parameterNamesAsChar[i] = parameterNames[i + 1].toCharArray();
+ }
+ setParameterNames(parameterNamesAsChar);
+ } catch (JavaModelException e) {
+ // Nope
+ }
+ }
+ }
+ // Seems like we failed, fallback
+ if (parameterNames == null) {
+ parameterNames = super.findParameterNames(monitor);
+ }
+ return parameterNames;
+ }
+
+ @Override
+ public void setParameterNames(char[][] parameterNames) {
+ this.parameterNames = parameterNames;
+ super.setParameterNames(parameterNames);
+ }
}
diff --git a/src/eclipseAgent/lombok/eclipse/agent/PatchDelegate.java b/src/eclipseAgent/lombok/eclipse/agent/PatchDelegate.java
index 1a287d93..d7b17598 100644
--- a/src/eclipseAgent/lombok/eclipse/agent/PatchDelegate.java
+++ b/src/eclipseAgent/lombok/eclipse/agent/PatchDelegate.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2010-2014 The Project Lombok Authors.
+ * Copyright (C) 2010-2021 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,8 +22,8 @@
package lombok.eclipse.agent;
import static lombok.eclipse.Eclipse.*;
+import static lombok.eclipse.EcjAugments.*;
import static lombok.eclipse.handlers.EclipseHandlerUtil.*;
-import static lombok.eclipse.EclipseAugments.Annotation_applied;
import java.lang.reflect.Method;
import java.util.ArrayList;
@@ -34,14 +34,16 @@ import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
-import lombok.core.AST.Kind;
-import lombok.eclipse.Eclipse;
-import lombok.eclipse.EclipseAST;
-import lombok.eclipse.EclipseNode;
-import lombok.eclipse.TransformEclipseAST;
-import lombok.eclipse.handlers.SetGeneratedByVisitor;
-
+import org.eclipse.jdt.core.ElementChangedEvent;
+import org.eclipse.jdt.core.IJavaElement;
+import org.eclipse.jdt.core.ILocalVariable;
+import org.eclipse.jdt.core.IType;
+import org.eclipse.jdt.core.JavaModelException;
+import org.eclipse.jdt.core.Signature;
+import org.eclipse.jdt.core.compiler.CharOperation;
import org.eclipse.jdt.internal.compiler.CompilationResult;
import org.eclipse.jdt.internal.compiler.ast.ASTNode;
import org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration;
@@ -81,8 +83,28 @@ import org.eclipse.jdt.internal.compiler.lookup.TypeConstants;
import org.eclipse.jdt.internal.compiler.lookup.TypeVariableBinding;
import org.eclipse.jdt.internal.compiler.lookup.UnresolvedReferenceBinding;
import org.eclipse.jdt.internal.compiler.lookup.WildcardBinding;
+import org.eclipse.jdt.internal.core.CompilationUnit;
+import org.eclipse.jdt.internal.core.DeltaProcessor;
+import org.eclipse.jdt.internal.core.JavaElement;
+import org.eclipse.jdt.internal.core.JavaElementDelta;
+import org.eclipse.jdt.internal.core.JavaModelManager;
+import org.eclipse.jdt.internal.core.LocalVariable;
+import org.eclipse.jdt.internal.core.SourceMethod;
+import org.eclipse.jdt.internal.core.SourceMethodInfo;
+import org.eclipse.jdt.internal.core.SourceType;
+import org.eclipse.jdt.internal.core.SourceTypeElementInfo;
+
+import lombok.core.AST.Kind;
+import lombok.eclipse.Eclipse;
+import lombok.eclipse.EclipseAST;
+import lombok.eclipse.EclipseNode;
+import lombok.eclipse.TransformEclipseAST;
+import lombok.eclipse.handlers.SetGeneratedByVisitor;
+import lombok.patcher.Symbols;
+import lombok.permit.Permit;
public class PatchDelegate {
+
private static class ClassScopeEntry {
ClassScopeEntry(ClassScope scope) {
this.scope = scope;
@@ -123,6 +145,14 @@ public class PatchDelegate {
public static boolean handleDelegateForType(ClassScope scope) {
if (TransformEclipseAST.disableLombok) return false;
+
+ CompilationUnitDeclaration cud = scope.compilationUnitScope().referenceContext;
+ if (scope == scope.compilationUnitScope().topLevelTypes[0].scope) {
+ if (eclipseAvailable) {
+ EclipseOnlyMethods.cleanupDelegateMethods(cud);
+ }
+ }
+
if (!hasDelegateMarkedFieldsOrMethods(scope.referenceContext)) return false;
List<ClassScopeEntry> stack = visited.get();
@@ -149,7 +179,6 @@ public class PatchDelegate {
try {
TypeDeclaration decl = scope.referenceContext;
if (decl != null) {
- CompilationUnitDeclaration cud = scope.compilationUnitScope().referenceContext;
EclipseAST eclipseAst = TransformEclipseAST.getAST(cud, true);
List<BindingTuple> methodsToDelegate = new ArrayList<BindingTuple>();
fillMethodBindingsForFields(cud, scope, methodsToDelegate);
@@ -168,6 +197,9 @@ public class PatchDelegate {
}
} finally {
stack.remove(stack.size() - 1);
+ if (stack.isEmpty() && eclipseAvailable) {
+ EclipseOnlyMethods.notifyDelegateMethodsAdded(cud);
+ }
}
}
@@ -419,6 +451,7 @@ public class PatchDelegate {
private static void generateDelegateMethods(EclipseNode typeNode, List<BindingTuple> methods, DelegateReceiver delegateReceiver) {
CompilationUnitDeclaration top = (CompilationUnitDeclaration) typeNode.top().get();
+ List<MethodDeclaration> addedMethods = new ArrayList<MethodDeclaration>();
for (BindingTuple pair : methods) {
EclipseNode annNode = typeNode.getAst().get(pair.responsible);
MethodDeclaration method = createDelegateMethod(pair.fieldName, typeNode, pair, top.compilationResult, annNode, delegateReceiver);
@@ -426,8 +459,12 @@ public class PatchDelegate {
SetGeneratedByVisitor visitor = new SetGeneratedByVisitor(annNode.get());
method.traverse(visitor, ((TypeDeclaration)typeNode.get()).scope);
injectMethod(typeNode, method);
+ addedMethods.add(method);
}
}
+ if (eclipseAvailable) {
+ EclipseOnlyMethods.collectGeneratedDelegateMethods(top, typeNode, addedMethods);
+ }
}
public static void checkConflictOfTypeVarNames(BindingTuple binding, EclipseNode typeNode) throws CantMakeDelegates {
@@ -673,20 +710,177 @@ public class PatchDelegate {
return method;
}
+ private static boolean eclipseAvailable = true;
+ static {
+ try {
+ CompilationUnit.class.getName();
+ } catch (Throwable t) {
+ eclipseAvailable = false;
+ }
+ }
+
+ public static Object[] addGeneratedDelegateMethods(Object[] returnValue, Object javaElement) {
+ if (Symbols.hasSymbol("lombok.skipdelegates")) return returnValue;
+ if (!eclipseAvailable) return returnValue;
+
+ return EclipseOnlyMethods.addGeneratedDelegateMethodsToChildren(returnValue, javaElement);
+ }
+
+ public static class EclipseOnlyMethods {
+ private static void cleanupDelegateMethods(CompilationUnitDeclaration cud) {
+ CompilationUnit compilationUnit = getCompilationUnit(cud);
+ if (compilationUnit != null) {
+ EclipseAugments.CompilationUnit_delegateMethods.clear(compilationUnit);
+ }
+ }
+
+ public static void collectGeneratedDelegateMethods(CompilationUnitDeclaration top, EclipseNode typeNode, List<MethodDeclaration> addedMethods) {
+ String qualifiedName = new String(CharOperation.concatWith(getQualifiedInnerName(typeNode.up(), typeNode.getName().toCharArray()), '$'));
+ SourceType sourceType = getSourceType(top, qualifiedName);
+ List<SourceMethod> generatedMethods = getGeneratedMethods(sourceType);
+ if (generatedMethods == null) return;
+
+ for (MethodDeclaration md : addedMethods) {
+ generatedMethods.add(DelegateSourceMethod.forMethodDeclaration(sourceType, md));
+ }
+ }
+
+ public static Object[] addGeneratedDelegateMethodsToChildren(Object[] returnValue, Object javaElement) {
+ List<SourceMethod> delegateMethods = getGeneratedMethods((SourceType) ((SourceTypeElementInfo) javaElement).getHandle());
+ if (delegateMethods != null) {
+ return concat((IJavaElement[]) returnValue, delegateMethods.toArray(new IJavaElement[0]), IJavaElement.class);
+ }
+ return returnValue;
+ }
+
+ private static void notifyDelegateMethodsAdded(CompilationUnitDeclaration cud) {
+ CompilationUnit compilationUnit = getCompilationUnit(cud);
+ if (compilationUnit != null) {
+ DeltaProcessor deltaProcessor = JavaModelManager.getJavaModelManager().getDeltaProcessor();
+ deltaProcessor.fire(new JavaElementDelta(compilationUnit), ElementChangedEvent.POST_CHANGE);
+ }
+ }
+
+ private static CompilationUnit getCompilationUnit(Object iCompilationUnit) {
+ if (iCompilationUnit instanceof CompilationUnit) {
+ CompilationUnit compilationUnit = (CompilationUnit) iCompilationUnit;
+ return compilationUnit.originalFromClone();
+ }
+ return null;
+ }
+
+ private static CompilationUnit getCompilationUnit(CompilationUnitDeclaration cud) {
+ return getCompilationUnit(cud.compilationResult.compilationUnit);
+ }
+
+ private static final class DelegateSourceMethod extends SourceMethod {
+ private DelegateSourceMethodInfo sourceMethodInfo;
+
+ private static DelegateSourceMethod forMethodDeclaration(JavaElement parent, MethodDeclaration method) {
+ Argument[] arguments = method.arguments != null ? method.arguments : new Argument[0];
+ String[] parameterTypes = new String[arguments.length];
+ for (int i = 0; i < arguments.length; i++) {
+ parameterTypes[i] = Signature.createTypeSignature(CharOperation.concatWith(arguments[i].type.getParameterizedTypeName(), '.'), false);
+ }
+ return new DelegateSourceMethod(parent, new String(method.selector), parameterTypes, method);
+ }
+
+ private DelegateSourceMethod(JavaElement parent, String name, String[] parameterTypes, MethodDeclaration md) {
+ super(parent, name, parameterTypes);
+ sourceMethodInfo = new DelegateSourceMethodInfo(this, md);
+ }
+
+ @Override public Object getElementInfo() throws JavaModelException {
+ return sourceMethodInfo;
+ }
+
+ /**
+ * Disable refactoring for delegate methods
+ */
+ @Override public boolean isReadOnly() {
+ return true;
+ }
+
+ /**
+ * This is required to prevent duplicate entries in the outline
+ */
+ @Override public boolean equals(Object o) {
+ return this == o;
+ }
+
+ public static final class DelegateSourceMethodInfo extends SourceMethodInfo {
+ DelegateSourceMethodInfo(DelegateSourceMethod delegateSourceMethod, MethodDeclaration md) {
+ int pS = md.sourceStart;
+ int pE = md.sourceEnd;
+
+ Argument[] methodArguments = md.arguments != null ? md.arguments : new Argument[0];
+ char[][] argumentNames = new char[methodArguments.length][];
+ arguments = new ILocalVariable[methodArguments.length];
+ for (int i = 0; i < methodArguments.length; i++) {
+ Argument argument = methodArguments[i];
+ argumentNames[i] = argument.name;
+ arguments[i] = new LocalVariable(delegateSourceMethod, new String(argument.name), pS, pE, pS, pS, delegateSourceMethod.getParameterTypes()[i], argument.annotations, argument.modifiers, true);
+ }
+ setArgumentNames(argumentNames);
+
+ setSourceRangeStart(pS);
+ setSourceRangeEnd(pE);
+ setNameSourceStart(pS);
+ setNameSourceEnd(pE);
+
+ setExceptionTypeNames(CharOperation.NO_CHAR_CHAR);
+ setReturnType(md.returnType == null ? new char[]{'v', 'o','i', 'd'} : CharOperation.concatWith(md.returnType.getParameterizedTypeName(), '.'));
+ setFlags(md.modifiers);
+ }
+ }
+ }
+
+ private static List<SourceMethod> getGeneratedMethods(SourceType sourceType) {
+ if (sourceType != null) {
+ CompilationUnit compilationUnit = getCompilationUnit(sourceType.getCompilationUnit());
+ if (compilationUnit != null) {
+ ConcurrentMap<String, List<SourceMethod>> map = EclipseAugments.CompilationUnit_delegateMethods.setIfAbsent(compilationUnit, new ConcurrentHashMap<String, List<SourceMethod>>());
+ List<SourceMethod> newList = new ArrayList<SourceMethod>();
+ List<SourceMethod> oldList = map.putIfAbsent(sourceType.getTypeQualifiedName(), newList);
+ return oldList != null ? oldList : newList;
+ }
+ }
+ return null;
+ }
+
+ private static SourceType getSourceType(CompilationUnitDeclaration cud, String typeName) {
+ CompilationUnit compilationUnit = getCompilationUnit(cud);
+ if (compilationUnit != null) {
+ try {
+ for (IType type : compilationUnit.getAllTypes()) {
+ if (type instanceof SourceType && type.getTypeQualifiedName().equals(typeName)) {
+ return (SourceType) type;
+ }
+ }
+ } catch (JavaModelException e) {
+ // Ignore
+ }
+ }
+ return null;
+ }
+ }
+
private static final class Reflection {
public static final Method classScopeBuildFieldsAndMethodsMethod;
-
+ public static final Throwable initCause;
static {
Method m = null;
+ Throwable c = null;
try {
- m = ClassScope.class.getDeclaredMethod("buildFieldsAndMethods");
- m.setAccessible(true);
+ m = Permit.getMethod(ClassScope.class, "buildFieldsAndMethods");
} catch (Throwable t) {
+ c = t;
// That's problematic, but as long as no local classes are used we don't actually need it.
// Better fail on local classes than crash altogether.
}
classScopeBuildFieldsAndMethodsMethod = m;
+ initCause = c;
}
}
@@ -723,16 +917,14 @@ public class PatchDelegate {
ClassScope cs = ((SourceTypeBinding)inner).scope;
if (cs != null) {
try {
- Reflection.classScopeBuildFieldsAndMethodsMethod.invoke(cs);
+ Permit.invoke(Reflection.initCause, Reflection.classScopeBuildFieldsAndMethodsMethod, cs);
} catch (Exception e) {
// See 'Reflection' class for why we ignore this exception.
}
}
}
- if (!(binding instanceof ReferenceBinding)) {
- return;
- }
+ if (!(binding instanceof ReferenceBinding)) return;
ReferenceBinding rb = (ReferenceBinding) binding;
MethodBinding[] availableMethods = rb.availableMethods();
diff --git a/src/eclipseAgent/lombok/eclipse/agent/PatchDelegatePortal.java b/src/eclipseAgent/lombok/eclipse/agent/PatchDelegatePortal.java
index 49083df0..01e4bb18 100644
--- a/src/eclipseAgent/lombok/eclipse/agent/PatchDelegatePortal.java
+++ b/src/eclipseAgent/lombok/eclipse/agent/PatchDelegatePortal.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2012 The Project Lombok Authors.
+ * Copyright (C) 2012-2021 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,52 +21,54 @@
*/
package lombok.eclipse.agent;
-import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
-import lombok.Lombok;
+import lombok.permit.Permit;
public class PatchDelegatePortal {
static final String CLASS_SCOPE = "org.eclipse.jdt.internal.compiler.lookup.ClassScope";
+ static final String I_JAVA_ELEMENT_ARRAY = "[Lorg.eclipse.jdt.core.IJavaElement;";
+ static final String SOURCE_TYPE_ELEMENT_INFO = "org.eclipse.jdt.internal.core.SourceTypeElementInfo";
public static boolean handleDelegateForType(Object classScope) {
- try {
- return (Boolean) Reflection.handleDelegateForType.invoke(null, classScope);
- } catch (NoClassDefFoundError e) {
- //ignore, we don't have access to the correct ECJ classes, so lombok can't possibly
- //do anything useful here.
- return false;
- } catch (IllegalAccessException e) {
- throw Lombok.sneakyThrow(e);
- } catch (InvocationTargetException e) {
- throw Lombok.sneakyThrow(e.getCause());
- } catch (NullPointerException e) {
- if (!"false".equals(System.getProperty("lombok.debug.reflection", "false"))) {
- e.initCause(Reflection.problem);
- throw e;
- }
- //ignore, we don't have access to the correct ECJ classes, so lombok can't possibly
- //do anything useful here.
- return false;
- }
+ Boolean v = (Boolean) Permit.invokeSneaky(Reflection.problemHandleDelegate, Reflection.handleDelegateForType, null, classScope);
+ if (v == null) return false;
+ return v.booleanValue();
+ }
+
+ public static Object[] addGeneratedDelegateMethods(Object returnValue, Object javaElement) {
+ return (Object[]) Permit.invokeSneaky(Reflection.problemAddGeneratedDelegateMethods, Reflection.addGeneratedDelegateMethods, null, returnValue, javaElement);
}
private static final class Reflection {
public static final Method handleDelegateForType;
- public static final Throwable problem;
+ public static final Method addGeneratedDelegateMethods;
+ public static final Throwable problemHandleDelegate;
+ public static final Throwable problemAddGeneratedDelegateMethods;
static {
- Method m = null;
- Throwable problem_ = null;
+ Method m = null, n = null;
+ Throwable problemHandleDelegate_ = null;
+ Throwable problemAddGeneratedDelegateMethods_ = null;
try {
- m = PatchDelegate.class.getMethod("handleDelegateForType", Class.forName(CLASS_SCOPE));
+ m = Permit.getMethod(PatchDelegate.class, "handleDelegateForType", Class.forName(CLASS_SCOPE));
} catch (Throwable t) {
// That's problematic, but as long as no local classes are used we don't actually need it.
// Better fail on local classes than crash altogether.
- problem_ = t;
+ problemHandleDelegate_ = t;
}
handleDelegateForType = m;
- problem = problem_;
+ problemHandleDelegate = problemHandleDelegate_;
+
+ try {
+ n = Permit.getMethod(PatchDelegate.class, "addGeneratedDelegateMethods", Object[].class, Object.class);
+ } catch (Throwable t) {
+ // That's problematic, but as long as no local classes are used we don't actually need it.
+ // Better fail on local classes than crash altogether.
+ problemAddGeneratedDelegateMethods_ = t;
+ }
+ addGeneratedDelegateMethods = n;
+ problemAddGeneratedDelegateMethods = problemAddGeneratedDelegateMethods_;
}
}
}
diff --git a/src/eclipseAgent/lombok/eclipse/agent/PatchExtensionMethod.java b/src/eclipseAgent/lombok/eclipse/agent/PatchExtensionMethod.java
index fcc76059..2e540b5e 100644
--- a/src/eclipseAgent/lombok/eclipse/agent/PatchExtensionMethod.java
+++ b/src/eclipseAgent/lombok/eclipse/agent/PatchExtensionMethod.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2012-2014 The Project Lombok Authors.
+ * Copyright (C) 2012-2021 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
@@ -24,6 +24,7 @@ package lombok.eclipse.agent;
import static lombok.eclipse.handlers.EclipseHandlerUtil.createAnnotation;
import java.lang.ref.WeakReference;
+import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
@@ -54,9 +55,9 @@ import org.eclipse.jdt.internal.compiler.ast.SingleNameReference;
import org.eclipse.jdt.internal.compiler.ast.SuperReference;
import org.eclipse.jdt.internal.compiler.ast.ThisReference;
import org.eclipse.jdt.internal.compiler.ast.TypeDeclaration;
+import org.eclipse.jdt.internal.compiler.impl.ReferenceContext;
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.MethodBinding;
import org.eclipse.jdt.internal.compiler.lookup.ProblemMethodBinding;
import org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding;
@@ -98,13 +99,13 @@ public class PatchExtensionMethod {
private static final Method shortMethod = getMethod("invalidMethod", MessageSend.class, MethodBinding.class);
private static final Method longMethod = getMethod("invalidMethod", MessageSend.class, MethodBinding.class, Scope.class);
+ private static Throwable initProblem;
private static Method getMethod(String name, Class<?>... types) {
try {
- Method m = ProblemReporter.class.getMethod(name, types);
- m.setAccessible(true);
- return m;
+ return Permit.getMethod(ProblemReporter.class, name, types);
} catch (Exception e) {
+ initProblem = e;
return null;
}
}
@@ -119,8 +120,9 @@ public class PatchExtensionMethod {
static void invoke(ProblemReporter problemReporter, MessageSend messageSend, MethodBinding method, Scope scope) {
if (messageSend != null) {
try {
- if (shortMethod != null) shortMethod.invoke(problemReporter, messageSend, method);
- else if (longMethod != null) longMethod.invoke(problemReporter, messageSend, method, scope);
+ if (shortMethod != null) Permit.invoke(initProblem, shortMethod, problemReporter, messageSend, method);
+ else if (longMethod != null) Permit.invoke(initProblem, longMethod, problemReporter, messageSend, method, scope);
+ else Permit.reportReflectionProblem(initProblem, "method named 'invalidMethod' not found in ProblemReporter.class");
} catch (IllegalAccessException e) {
throw new RuntimeException(e);
} catch (InvocationTargetException e) {
@@ -138,6 +140,25 @@ public class PatchExtensionMethod {
}
}
+ private static class PostponedNonStaticAccessToStaticMethodError implements PostponedError {
+ private final ProblemReporter problemReporter;
+ private ASTNode location;
+ private MethodBinding method;
+ private ReferenceContext referenceContext;
+
+ PostponedNonStaticAccessToStaticMethodError(ProblemReporter problemReporter, ASTNode location, MethodBinding method) {
+ this.problemReporter = problemReporter;
+ this.location = location;
+ this.method = method;
+ this.referenceContext = problemReporter.referenceContext;
+ }
+
+ public void fire() {
+ problemReporter.referenceContext = this.referenceContext;
+ problemReporter.nonStaticAccessToStaticMethod(location, method);
+ }
+ }
+
private static interface PostponedError {
public void fire();
}
@@ -200,15 +221,12 @@ public class PatchExtensionMethod {
TypeBinding receiverType) {
List<MethodBinding> extensionMethods = new ArrayList<MethodBinding>();
- CompilationUnitScope cuScope = ((CompilationUnitDeclaration) typeNode.top().get()).scope;
for (MethodBinding method : extensionMethodProviderBinding.methods()) {
if (!method.isStatic()) continue;
if (!method.isPublic()) continue;
if (method.parameters == null || method.parameters.length == 0) continue;
TypeBinding firstArgType = method.parameters[0];
if (receiverType.isProvablyDistinct(firstArgType) && !receiverType.isCompatibleWith(firstArgType.erasure())) continue;
- TypeBinding[] argumentTypes = Arrays.copyOfRange(method.parameters, 1, method.parameters.length);
- if ((receiverType instanceof ReferenceBinding) && ((ReferenceBinding) receiverType).getExactMethod(method.selector, argumentTypes, cuScope) != null) continue;
extensionMethods.add(method);
}
return extensionMethods;
@@ -228,6 +246,10 @@ public class PatchExtensionMethod {
MessageSend_postponedErrors.set(messageSend, new PostponedInvalidMethodError(problemReporter, messageSend, method, scope));
}
+ public static void nonStaticAccessToStaticMethod(ProblemReporter problemReporter, ASTNode location, MethodBinding method, MessageSend messageSend) {
+ MessageSend_postponedErrors.set(messageSend, new PostponedNonStaticAccessToStaticMethodError(problemReporter, location, method));
+ }
+
public static TypeBinding resolveType(TypeBinding resolvedType, MessageSend methodCall, BlockScope scope) {
List<Extension> extensions = new ArrayList<Extension>();
TypeDeclaration decl = scope.classScope().referenceContext;
@@ -250,6 +272,14 @@ public class PatchExtensionMethod {
Binding binding = ((NameReference)methodCall.receiver).binding;
if (binding instanceof TypeBinding) skip = true;
}
+ // It's impossible to resolve the right method without types
+ if (Reflection.argumentsHaveErrors != null) {
+ try {
+ if ((Boolean) Reflection.argumentsHaveErrors.get(methodCall)) skip = true;
+ } catch (IllegalAccessException ignore) {
+ // ignore
+ }
+ }
if (!skip) for (Extension extension : extensions) {
if (!extension.suppressBaseMethods && !(methodCall.binding instanceof ProblemMethodBinding)) continue;
@@ -262,13 +292,31 @@ public class PatchExtensionMethod {
List<Expression> arguments = new ArrayList<Expression>();
arguments.add(methodCall.receiver);
if (methodCall.arguments != null) arguments.addAll(Arrays.asList(methodCall.arguments));
+ Expression[] originalArgs = methodCall.arguments;
+ methodCall.arguments = arguments.toArray(new Expression[0]);
+
List<TypeBinding> argumentTypes = new ArrayList<TypeBinding>();
for (Expression argument : arguments) {
- if (argument.resolvedType != null) argumentTypes.add(argument.resolvedType);
- // TODO: Instead of just skipping nulls entirely, there is probably a 'unresolved type' placeholder. THAT is what we ought to be adding here!
+ TypeBinding argumentType = argument.resolvedType;
+ if (argumentType == null && Reflection.isFunctionalExpression(argument)) {
+ argumentType = Reflection.getPolyTypeBinding(argument);
+ }
+ if (argumentType == null) {
+ argumentType = TypeBinding.NULL;
+ }
+ argumentTypes.add(argumentType);
}
- Expression[] originalArgs = methodCall.arguments;
- methodCall.arguments = arguments.toArray(new Expression[0]);
+
+ if (methodCall.receiver instanceof MessageSend) {
+ if (Reflection.inferenceContexts != null) {
+ try {
+ Permit.set(Reflection.inferenceContexts, methodCall.receiver, null);
+ } catch (IllegalAccessException ignore) {
+ // ignore
+ }
+ }
+ }
+
MethodBinding fixedBinding = scope.getMethod(extensionMethod.declaringClass, methodCall.selector, argumentTypes.toArray(new TypeBinding[0]), methodCall);
if (fixedBinding instanceof ProblemMethodBinding) {
methodCall.arguments = originalArgs;
@@ -276,18 +324,33 @@ public class PatchExtensionMethod {
PostponedInvalidMethodError.invoke(scope.problemReporter(), methodCall, fixedBinding, scope);
}
} else {
+ // If the extension method uses varargs, the last fixed binding parameter is an array but
+ // the method arguments are not. Even thought we already know that the method is fine we still
+ // have to compare each parameter with the type of the array to support autoboxing/unboxing.
+ boolean isVarargs = fixedBinding.isVarargs();
for (int i = 0, iend = arguments.size(); i < iend; i++) {
Expression arg = arguments.get(i);
- if (fixedBinding.parameters[i].isArrayType() != arg.resolvedType.isArrayType()) break;
- if (arg instanceof MessageSend) {
- ((MessageSend) arg).valueCast = arg.resolvedType;
+ TypeBinding[] parameters = fixedBinding.parameters;
+ TypeBinding param;
+ if (isVarargs && i >= parameters.length - 1) {
+ // Extract the array element type for all vararg arguments
+ param = parameters[parameters.length - 1].leafComponentType();
+ } else {
+ param = parameters[i];
+ }
+ // Resolve types for lambdas
+ if (Reflection.isFunctionalExpression(arg)) {
+ arg.setExpectedType(param);
+ arg.resolveType(scope);
}
- if (!fixedBinding.parameters[i].isBaseType() && arg.resolvedType.isBaseType()) {
- int id = arg.resolvedType.id;
- arg.implicitConversion = TypeIds.BOXING | (id + (id << 4)); // magic see TypeIds
- } else if (fixedBinding.parameters[i].isBaseType() && !arg.resolvedType.isBaseType()) {
- int id = fixedBinding.parameters[i].id;
- arg.implicitConversion = TypeIds.UNBOXING | (id + (id << 4)); // magic see TypeIds
+ if (arg.resolvedType != null) {
+ if (!param.isBaseType() && arg.resolvedType.isBaseType()) {
+ int id = arg.resolvedType.id;
+ arg.implicitConversion = TypeIds.BOXING | (id + (id << 4)); // magic see TypeIds
+ } else if (param.isBaseType() && !arg.resolvedType.isBaseType()) {
+ int id = parameters[i].id;
+ arg.implicitConversion = TypeIds.UNBOXING | (id + (id << 4)); // magic see TypeIds
+ }
}
}
@@ -295,6 +358,7 @@ public class PatchExtensionMethod {
methodCall.actualReceiverType = extensionMethod.declaringClass;
methodCall.binding = fixedBinding;
methodCall.resolvedType = methodCall.binding.returnType;
+ methodCall.statementEnd = methodCall.sourceEnd;
if (Reflection.argumentTypes != null) {
try {
Reflection.argumentTypes.set(methodCall, argumentTypes.toArray(new TypeBinding[0]));
@@ -340,16 +404,42 @@ public class PatchExtensionMethod {
}
private static final class Reflection {
- public static final Field argumentTypes;
+ public static final Field argumentTypes = Permit.permissiveGetField(MessageSend.class, "argumentTypes");
+ public static final Field argumentsHaveErrors = Permit.permissiveGetField(MessageSend.class, "argumentsHaveErrors");
+ public static final Field inferenceContexts = Permit.permissiveGetField(MessageSend.class, "inferenceContexts");
+ private static final Class<?> functionalExpression;
+ private static final Constructor<?> polyTypeBindingConstructor;
static {
- Field a = null;
+ Class<?> a = null;
+ Constructor<?> b = null;
try {
- a = Permit.getField(MessageSend.class, "argumentTypes");
- } catch (Throwable t) {
- //ignore - old eclipse versions don't know this one
+ a = Class.forName("org.eclipse.jdt.internal.compiler.ast.FunctionalExpression");
+ } catch (Exception e) {
+ // Ignore
+ }
+ try {
+ b = Permit.getConstructor(Class.forName("org.eclipse.jdt.internal.compiler.lookup.PolyTypeBinding"), Expression.class);
+ } catch (Exception e) {
+ // Ignore
+ }
+ functionalExpression = a;
+ polyTypeBindingConstructor = b;
+ }
+
+ public static boolean isFunctionalExpression(Expression expression) {
+ if (functionalExpression == null) return false;
+ return functionalExpression.isInstance(expression);
+ }
+
+ public static TypeBinding getPolyTypeBinding(Expression expression) {
+ if (polyTypeBindingConstructor == null) return null;
+ try {
+ return (TypeBinding) polyTypeBindingConstructor.newInstance(expression);
+ } catch (Exception e) {
+ // Ignore
}
- argumentTypes = a;
+ return null;
}
}
}
diff --git a/src/eclipseAgent/lombok/eclipse/agent/PatchExtensionMethodCompletionProposal.java b/src/eclipseAgent/lombok/eclipse/agent/PatchExtensionMethodCompletionProposal.java
index 085c903f..1b94d1b9 100755
--- a/src/eclipseAgent/lombok/eclipse/agent/PatchExtensionMethodCompletionProposal.java
+++ b/src/eclipseAgent/lombok/eclipse/agent/PatchExtensionMethodCompletionProposal.java
@@ -65,13 +65,14 @@ public class PatchExtensionMethodCompletionProposal {
CompletionProposalCollector completionProposalCollector) {
List<IJavaCompletionProposal> proposals = new ArrayList<IJavaCompletionProposal>(Arrays.asList(javaCompletionProposals));
- if (canExtendCodeAssist(proposals)) {
- IJavaCompletionProposal firstProposal = proposals.get(0);
- int replacementOffset = getReplacementOffset(firstProposal);
+ if (canExtendCodeAssist()) {
for (Extension extension : getExtensionMethods(completionProposalCollector)) {
for (MethodBinding method : extension.extensionMethods) {
- ExtensionMethodCompletionProposal newProposal = new ExtensionMethodCompletionProposal(replacementOffset);
- copyNameLookupAndCompletionEngine(completionProposalCollector, firstProposal, newProposal);
+ if (!isMatchingProposal(method, completionProposalCollector)) {
+ continue;
+ }
+ ExtensionMethodCompletionProposal newProposal = new ExtensionMethodCompletionProposal(0);
+ copyNameLookupAndCompletionEngine(completionProposalCollector, newProposal);
ASTNode node = getAssistNode(completionProposalCollector);
newProposal.setMethodBinding(method, node);
createAndAddJavaCompletionProposal(completionProposalCollector, newProposal, proposals);
@@ -81,7 +82,6 @@ public class PatchExtensionMethodCompletionProposal {
return proposals.toArray(new IJavaCompletionProposal[0]);
}
-
private static List<Extension> getExtensionMethods(CompletionProposalCollector completionProposalCollector) {
List<Extension> extensions = new ArrayList<Extension>();
ClassScope classScope = getClassScope(completionProposalCollector);
@@ -96,6 +96,17 @@ public class PatchExtensionMethodCompletionProposal {
return extensions;
}
+ private static boolean isMatchingProposal(MethodBinding method, CompletionProposalCollector completionProposalCollector) {
+ try {
+ InternalCompletionContext context = (InternalCompletionContext) Reflection.contextField.get(completionProposalCollector);
+ String searchToken = new String(context.getToken());
+ String extensionMethodName = new String(method.selector);
+ return extensionMethodName.contains(searchToken);
+ } catch (IllegalAccessException e) {
+ return true;
+ }
+ }
+
static TypeBinding getFirstParameterType(TypeDeclaration decl, CompletionProposalCollector completionProposalCollector) {
TypeBinding firstParameterType = null;
ASTNode node = getAssistNode(completionProposalCollector);
@@ -149,8 +160,7 @@ public class PatchExtensionMethodCompletionProposal {
return scope;
}
- private static void copyNameLookupAndCompletionEngine(CompletionProposalCollector completionProposalCollector, IJavaCompletionProposal proposal,
- InternalCompletionProposal newProposal) {
+ private static void copyNameLookupAndCompletionEngine(CompletionProposalCollector completionProposalCollector, InternalCompletionProposal newProposal) {
try {
InternalCompletionContext context = (InternalCompletionContext) Reflection.contextField.get(completionProposalCollector);
@@ -173,17 +183,10 @@ public class PatchExtensionMethodCompletionProposal {
}
}
- private static boolean canExtendCodeAssist(List<IJavaCompletionProposal> proposals) {
- return !proposals.isEmpty() && Reflection.isComplete();
- }
-
- private static int getReplacementOffset(Object proposal) {
- try {
- return Reflection.replacementOffsetField.getInt(proposal);
- } catch (Exception ignore) {
- return 0;
- }
+ private static boolean canExtendCodeAssist() {
+ return Reflection.isComplete();
}
+
static class Reflection {
public static final Field replacementOffsetField;
@@ -195,7 +198,7 @@ public class PatchExtensionMethodCompletionProposal {
public static final Field completionEngineField;
public static final Field nameLookupField;
public static final Method createJavaCompletionProposalMethod;
-
+
static {
replacementOffsetField = accessField(AbstractJavaCompletionProposal.class, "fReplacementOffset");
contextField = accessField(CompletionProposalCollector.class, "fContext");
diff --git a/src/eclipseAgent/lombok/eclipse/agent/PatchExtensionMethodPortal.java b/src/eclipseAgent/lombok/eclipse/agent/PatchExtensionMethodPortal.java
deleted file mode 100644
index b66bafbb..00000000
--- a/src/eclipseAgent/lombok/eclipse/agent/PatchExtensionMethodPortal.java
+++ /dev/null
@@ -1,103 +0,0 @@
-package lombok.eclipse.agent;
-
-import java.lang.reflect.InvocationTargetException;
-import java.lang.reflect.Method;
-
-import lombok.Lombok;
-
-import org.eclipse.jdt.internal.compiler.lookup.TypeBinding;
-
-public class PatchExtensionMethodPortal {
- private static final String TYPE_BINDING = "org.eclipse.jdt.internal.compiler.lookup.TypeBinding";
- private static final String TYPE_BINDING_ARRAY = "[Lorg.eclipse.jdt.internal.compiler.lookup.TypeBinding;";
- private static final String MESSAGE_SEND = "org.eclipse.jdt.internal.compiler.ast.MessageSend";
- private static final String BLOCK_SCOPE = "org.eclipse.jdt.internal.compiler.lookup.BlockScope";
- private static final String METHOD_BINDING = "org.eclipse.jdt.internal.compiler.lookup.MethodBinding";
- private static final String PROBLEM_REPORTER = "org.eclipse.jdt.internal.compiler.problem.ProblemReporter";
-
- public static TypeBinding resolveType(Object resolvedType, Object methodCall, Object scope) {
- try {
- return (TypeBinding) Reflection.resolveType.invoke(null, resolvedType, methodCall, scope);
- } catch (NoClassDefFoundError e) {
- //ignore, we don't have access to the correct ECJ classes, so lombok can't possibly
- //do anything useful here.
- return (TypeBinding) resolvedType;
- } catch (IllegalAccessException e) {
- throw Lombok.sneakyThrow(e);
- } catch (InvocationTargetException e) {
- throw Lombok.sneakyThrow(e);
- } catch (NullPointerException e) {
- if (!"false".equals(System.getProperty("lombok.debug.reflection", "false"))) {
- e.initCause(Reflection.problem);
- throw e;
- }
- //ignore, we don't have access to the correct ECJ classes, so lombok can't possibly
- //do anything useful here.
- return (TypeBinding)resolvedType;
- }
- }
-
- public static void errorNoMethodFor(Object problemReporter, Object messageSend, Object recType, Object params) {
- try {
- Reflection.errorNoMethodFor.invoke(null, problemReporter, messageSend, recType, params);
- } catch (NoClassDefFoundError e) {
- //ignore, we don't have access to the correct ECJ classes, so lombok can't possibly
- //do anything useful here.
- } catch (IllegalAccessException e) {
- throw Lombok.sneakyThrow(e);
- } catch (InvocationTargetException e) {
- throw Lombok.sneakyThrow(e.getCause());
- } catch (NullPointerException e) {
- if (!"false".equals(System.getProperty("lombok.debug.reflection", "false"))) {
- e.initCause(Reflection.problem);
- throw e;
- }
- //ignore, we don't have access to the correct ECJ classes, so lombok can't possibly
- //do anything useful here.
- }
- }
-
- public static void invalidMethod(Object problemReporter, Object messageSend, Object method) {
- try {
- Reflection.invalidMethod.invoke(null, problemReporter, messageSend, method);
- } catch (NoClassDefFoundError e) {
- //ignore, we don't have access to the correct ECJ classes, so lombok can't possibly
- //do anything useful here.
- } catch (IllegalAccessException e) {
- throw Lombok.sneakyThrow(e);
- } catch (InvocationTargetException e) {
- throw Lombok.sneakyThrow(e.getCause());
- } catch (NullPointerException e) {
- if (!"false".equals(System.getProperty("lombok.debug.reflection", "false"))) {
- e.initCause(Reflection.problem);
- throw e;
- }
- //ignore, we don't have access to the correct ECJ classes, so lombok can't possibly
- //do anything useful here.
- }
- }
-
- private static final class Reflection {
- public static final Method resolveType, errorNoMethodFor, invalidMethod;
- public static final Throwable problem;
-
- static {
- Method m = null, n = null, o = null;
- Throwable problem_ = null;
- try {
- m = PatchExtensionMethod.class.getMethod("resolveType", Class.forName(TYPE_BINDING), Class.forName(MESSAGE_SEND), Class.forName(BLOCK_SCOPE));
- n = PatchExtensionMethod.class.getMethod("errorNoMethodFor", Class.forName(PROBLEM_REPORTER),
- Class.forName(MESSAGE_SEND), Class.forName(TYPE_BINDING), Class.forName(TYPE_BINDING_ARRAY));
- o = PatchExtensionMethod.class.getMethod("invalidMethod", Class.forName(PROBLEM_REPORTER), Class.forName(MESSAGE_SEND), Class.forName(METHOD_BINDING));
- } catch (Throwable t) {
- // That's problematic, but as long as no local classes are used we don't actually need it.
- // Better fail on local classes than crash altogether.
- problem_ = t;
- }
- resolveType = m;
- errorNoMethodFor = n;
- invalidMethod = o;
- problem = problem_;
- }
- }
-}
diff --git a/src/eclipseAgent/lombok/eclipse/agent/PatchJavadoc.java b/src/eclipseAgent/lombok/eclipse/agent/PatchJavadoc.java
new file mode 100644
index 00000000..5b34917e
--- /dev/null
+++ b/src/eclipseAgent/lombok/eclipse/agent/PatchJavadoc.java
@@ -0,0 +1,138 @@
+/*
+ * Copyright (C) 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
+ * 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.eclipse.agent;
+
+import static lombok.eclipse.EcjAugments.CompilationUnit_javadoc;
+
+import java.lang.reflect.Method;
+import java.util.Map;
+
+import org.eclipse.jdt.core.ICompilationUnit;
+import org.eclipse.jdt.core.IJavaElement;
+import org.eclipse.jdt.core.IMember;
+import org.eclipse.jdt.internal.compiler.ast.ASTNode;
+import org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration;
+import org.eclipse.jdt.internal.compiler.ast.TypeDeclaration;
+import org.eclipse.jdt.internal.core.CompilationUnit;
+import org.eclipse.jdt.internal.core.SourceMethod;
+import org.eclipse.jdt.internal.ui.text.javadoc.JavadocContentAccess2;
+
+import lombok.eclipse.handlers.EclipseHandlerUtil;
+import lombok.permit.Permit;
+
+public class PatchJavadoc {
+
+ public static String getHTMLContentFromSource(String original, Object member) {
+ if (original != null) {
+ return original;
+ }
+
+ if (member instanceof SourceMethod) {
+ SourceMethod sourceMethod = (SourceMethod) member;
+ ICompilationUnit iCompilationUnit = sourceMethod.getCompilationUnit();
+ if (iCompilationUnit instanceof CompilationUnit) {
+ CompilationUnit compilationUnit = (CompilationUnit) iCompilationUnit;
+ Map<String, String> docs = CompilationUnit_javadoc.get(compilationUnit);
+ if (docs == null) return null;
+
+ String signature = Signature.getSignature(sourceMethod);
+ String rawJavadoc = docs.get(signature);
+ if (rawJavadoc == null) return null;
+
+ return Reflection.javadoc2HTML((IMember) member, (IJavaElement) member, rawJavadoc);
+ }
+ }
+
+ return null;
+ }
+
+ public static StringBuffer printMethod(AbstractMethodDeclaration methodDeclaration, Integer tab, StringBuffer output, TypeDeclaration type) {
+ Map<String, String> docs = CompilationUnit_javadoc.get(methodDeclaration.compilationResult.compilationUnit);
+ if (docs != null) {
+ String signature = EclipseHandlerUtil.getSignature(type, methodDeclaration);
+ String rawJavadoc = docs.get(signature);
+ if (rawJavadoc != null) {
+ for (String line : rawJavadoc.split("\r?\n")) {
+ ASTNode.printIndent(tab, output).append(line).append("\n");
+ }
+ }
+ }
+ return methodDeclaration.print(tab, output);
+ }
+
+ private static class Signature {
+ static final String getSignature(SourceMethod sourceMethod) {
+ StringBuilder sb = new StringBuilder();
+ sb.append(sourceMethod.getParent().getElementName());
+ sb.append(".");
+ sb.append(sourceMethod.getElementName());
+ sb.append("(");
+ for (String type : sourceMethod.getParameterTypes()) {
+ sb.append(org.eclipse.jdt.core.Signature.toString(type));
+ }
+ sb.append(")");
+
+ return sb.toString();
+ }
+ }
+
+ /**
+ * The method <code>javadoc2HTML</code> changed 2014-12 to accept an
+ * additional IJavaElement parameter. To support older versions, try to
+ * find that one too.
+ */
+ private static class Reflection {
+ private static final Method javadoc2HTML;
+ private static final Method oldJavadoc2HTML;
+ static {
+ Method a = null, b = null;
+
+ try {
+ a = Permit.getMethod(JavadocContentAccess2.class, "javadoc2HTML", IMember.class, IJavaElement.class, String.class);
+ } catch (Throwable t) {}
+ try {
+ b = Permit.getMethod(JavadocContentAccess2.class, "javadoc2HTML", IMember.class, String.class);
+ } catch (Throwable t) {}
+
+ javadoc2HTML = a;
+ oldJavadoc2HTML = b;
+ }
+
+ private static String javadoc2HTML(IMember member, IJavaElement element, String rawJavadoc) {
+ if (javadoc2HTML != null) {
+ try {
+ return (String) javadoc2HTML.invoke(null, member, element, rawJavadoc);
+ } catch (Throwable t) {
+ return null;
+ }
+ }
+ if (oldJavadoc2HTML != null) {
+ try {
+ return (String) oldJavadoc2HTML.invoke(null, member, rawJavadoc);
+ } catch (Throwable t) {
+ return null;
+ }
+ }
+ return null;
+ }
+ }
+}
diff --git a/src/eclipseAgent/lombok/eclipse/agent/PatchVal.java b/src/eclipseAgent/lombok/eclipse/agent/PatchVal.java
index f22e78a8..9663f364 100644
--- a/src/eclipseAgent/lombok/eclipse/agent/PatchVal.java
+++ b/src/eclipseAgent/lombok/eclipse/agent/PatchVal.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2010-2019 The Project Lombok Authors.
+ * Copyright (C) 2010-2021 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
@@ -68,32 +68,7 @@ public class PatchVal {
// This is half of the work for 'val' support - the other half is in PatchValEclipse. This half is enough for ecj.
// Creates a copy of the 'initialization' field on a LocalDeclaration if the type of the LocalDeclaration is 'val', because the completion parser will null this out,
// which in turn stops us from inferring the intended type for 'val x = 5;'. We look at the copy.
- // Also patches local declaration to not call .resolveType() on the initializer expression if we've already done so (calling it twice causes weird errors),
- // and patches .resolve() on LocalDeclaration itself to just-in-time replace the 'val' vartype with the right one.
-
- public static TypeBinding skipResolveInitializerIfAlreadyCalled(Expression expr, BlockScope scope) {
- if (expr.resolvedType != null) return expr.resolvedType;
- try {
- return expr.resolveType(scope);
- } catch (NullPointerException e) {
- return null;
- } catch (ArrayIndexOutOfBoundsException e) {
- // This will occur internally due to for example 'val x = mth("X");', where mth takes 2 arguments.
- return null;
- }
- }
-
- public static TypeBinding skipResolveInitializerIfAlreadyCalled2(Expression expr, BlockScope scope, LocalDeclaration decl) {
- if (decl != null && LocalDeclaration.class.equals(decl.getClass()) && expr.resolvedType != null) return expr.resolvedType;
- try {
- return expr.resolveType(scope);
- } catch (NullPointerException e) {
- return null;
- } catch (ArrayIndexOutOfBoundsException e) {
- // This will occur internally due to for example 'val x = mth("X");', where mth takes 2 arguments.
- return null;
- }
- }
+ // Also patches .resolve() on LocalDeclaration itself to just-in-time replace the 'val' vartype with the right one.
public static boolean matches(String key, char[] array) {
if (array == null || key.length() != array.length) return false;