This is an automated email from the ASF dual-hosted git repository.
jlahoda pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-netbeans.git
The following commit(s) were added to refs/heads/master by this push:
new e3df660 [NETBEANS-1945]: Fixing handling of implicit trees produced
by matching (when hints refer to implicit this).
e3df660 is described below
commit e3df6600d9780ff84cc6e4b0665e6a420a5b65d5
Author: Jan Lahoda <[email protected]>
AuthorDate: Mon Jan 28 22:49:44 2019 +0100
[NETBEANS-1945]: Fixing handling of implicit trees produced by matching
(when hints refer to implicit this).
---
.travis.yml | 2 +-
.../modules/java/hints/threading/Tiny.java | 2 +-
java/spi.java.hints/nbproject/project.properties | 2 +-
.../netbeans/modules/java/hints/spiimpl/Hacks.java | 2 +-
.../modules/java/hints/spiimpl/Utilities.java | 6 +-
.../netbeans/spi/java/hints/JavaFixUtilities.java | 116 +++++++++++++++++--
.../spi/java/hints/JavaFixUtilitiesTest.java | 128 +++++++++++++++++++++
7 files changed, 243 insertions(+), 15 deletions(-)
diff --git a/.travis.yml b/.travis.yml
index f01b4c9..721d5c4 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -44,7 +44,7 @@ matrix:
- env: OPTS="-quiet" TARGET="build-platform"
jdk: oraclejdk11
- - env: SIGTEST=false COMPILETEST=false RAT=false EOL=false
LICENSE=false CV=false RUN_TESTS_JDK9PLUS=false RUN_TESTS_JDK8=true
TEST_MODULES="java/java.completion" OPTS="-Dcluster.config=java -quiet build
-Djavac.compilerargs=-nowarn -Dbuild.compiler.deprecation=false"
+ - env: SIGTEST=false COMPILETEST=false RAT=false EOL=false
LICENSE=false CV=false RUN_TESTS_JDK9PLUS=false RUN_TESTS_JDK8=true
TEST_MODULES="java/java.completion java/spi.java.hints
java/java.hints.declarative" OPTS="-Dcluster.config=java -quiet build
-Djavac.compilerargs=-nowarn -Dbuild.compiler.deprecation=false
-Dtest-unit-sys-prop.ignore.random.failures=true"
jdk: oraclejdk8
- env: SIGTEST=false COMPILETEST=false RAT=false EOL=false
LICENSE=false CV=false RUN_TESTS_JDK8=false RUN_TESTS_JDK9PLUS=true
TEST_JDK_VERSION="--feature 11 --license GPL"
TEST_RUN_OPTIONS='-Dtest.run.args=--limit-modules=java.base,java.logging,java.xml,java.prefs,java.desktop,java.management,java.instrument
-Dtest.use.jdk.javac=true' TEST_MODULES="java/java.completion"
OPTS="-Dcluster.config=java -quiet build -Djavac.compilerargs=-nowarn
-Dbuild.compiler.deprecation=false"
diff --git
a/java/java.hints/src/org/netbeans/modules/java/hints/threading/Tiny.java
b/java/java.hints/src/org/netbeans/modules/java/hints/threading/Tiny.java
index 477dcd0..d3c0255 100644
--- a/java/java.hints/src/org/netbeans/modules/java/hints/threading/Tiny.java
+++ b/java/java.hints/src/org/netbeans/modules/java/hints/threading/Tiny.java
@@ -352,7 +352,7 @@ public class Tiny {
private static boolean equals(VariableElement var1, VariableElement var2) {
if ( var1.getSimpleName() == var2.getSimpleName()
- && var1.getSimpleName().contentEquals("class")) {
+ && (var1.getSimpleName().contentEquals("class") ||
var1.getSimpleName().contentEquals("this"))) {
return
var1.getEnclosingElement().equals(var2.getEnclosingElement());
} else {
return var1.equals(var2);
diff --git a/java/spi.java.hints/nbproject/project.properties
b/java/spi.java.hints/nbproject/project.properties
index fc8b5f2..537a869 100644
--- a/java/spi.java.hints/nbproject/project.properties
+++ b/java/spi.java.hints/nbproject/project.properties
@@ -15,7 +15,7 @@
# specific language governing permissions and limitations
# under the License.
is.autoload=true
-javac.source=1.7
+javac.source=1.8
javac.compilerargs=-Xlint -Xlint:-serial
spec.version.base=1.34.0
requires.nb.javac=true
diff --git
a/java/spi.java.hints/src/org/netbeans/modules/java/hints/spiimpl/Hacks.java
b/java/spi.java.hints/src/org/netbeans/modules/java/hints/spiimpl/Hacks.java
index bf8ccf9..8c713ed 100644
--- a/java/spi.java.hints/src/org/netbeans/modules/java/hints/spiimpl/Hacks.java
+++ b/java/spi.java.hints/src/org/netbeans/modules/java/hints/spiimpl/Hacks.java
@@ -75,7 +75,7 @@ public class Hacks {
clazz.append("import ").append(i).append(";\n");
}
- clazz.append("public class $").append(inc++).append("{");
+ clazz.append("public class $$scopeclass$").append(inc++).append("{");
clazz.append("private void test() {\n");
clazz.append("}\n");
diff --git
a/java/spi.java.hints/src/org/netbeans/modules/java/hints/spiimpl/Utilities.java
b/java/spi.java.hints/src/org/netbeans/modules/java/hints/spiimpl/Utilities.java
index b8d6ce6..d43b123 100644
---
a/java/spi.java.hints/src/org/netbeans/modules/java/hints/spiimpl/Utilities.java
+++
b/java/spi.java.hints/src/org/netbeans/modules/java/hints/spiimpl/Utilities.java
@@ -709,7 +709,7 @@ public class Utilities {
StringBuilder clazz = new StringBuilder();
- clazz.append("package $;");
+ clazz.append("package $$;");
for (String i : auxiliaryImports) {
clazz.append(i);
@@ -717,7 +717,7 @@ public class Utilities {
long count = inc++;
- clazz.append("public class $" + count + "{");
+ clazz.append("public class $$scopeclass$constraints$" + count + "{");
for (Entry<String, TypeMirror> e : constraints.entrySet()) {
if (e.getValue() != null) {
@@ -742,7 +742,7 @@ public class Utilities {
Annotate annotate = Annotate.instance(context);
Log.DiagnosticHandler discardHandler = new
Log.DiscardDiagnosticHandler(compiler.log);
- JavaFileObject jfo = FileObjects.memoryFileObject("$", "$", new
File("/tmp/$" + count + ".java").toURI(), System.currentTimeMillis(),
clazz.toString());
+ JavaFileObject jfo = FileObjects.memoryFileObject("$", "$", new
File("/tmp/$$scopeclass$constraints$" + count + ".java").toURI(),
System.currentTimeMillis(), clazz.toString());
try {
resolve.disableAccessibilityChecks();
diff --git
a/java/spi.java.hints/src/org/netbeans/spi/java/hints/JavaFixUtilities.java
b/java/spi.java.hints/src/org/netbeans/spi/java/hints/JavaFixUtilities.java
index 6f5ccd2..bcaee17 100644
--- a/java/spi.java.hints/src/org/netbeans/spi/java/hints/JavaFixUtilities.java
+++ b/java/spi.java.hints/src/org/netbeans/spi/java/hints/JavaFixUtilities.java
@@ -57,6 +57,7 @@ import com.sun.source.tree.VariableTree;
import com.sun.source.tree.WhileLoopTree;
import com.sun.source.util.SourcePositions;
import com.sun.source.util.TreePath;
+import com.sun.source.util.TreeScanner;
import org.netbeans.api.java.source.support.ErrorAwareTreePathScanner;
import org.netbeans.api.java.source.support.ErrorAwareTreeScanner;
import java.io.IOException;
@@ -67,6 +68,7 @@ import java.util.Collections;
import java.util.EnumMap;
import java.util.EnumSet;
import java.util.HashMap;
+import java.util.HashSet;
import java.util.IdentityHashMap;
import java.util.Iterator;
import java.util.LinkedList;
@@ -91,10 +93,12 @@ import org.netbeans.api.java.queries.SourceForBinaryQuery;
import org.netbeans.api.java.source.ClasspathInfo;
import org.netbeans.api.java.source.ClasspathInfo.PathKind;
import org.netbeans.api.java.source.CompilationInfo;
+import org.netbeans.api.java.source.ElementHandle;
import org.netbeans.api.java.source.GeneratorUtilities;
import org.netbeans.api.java.source.SourceUtils;
import org.netbeans.api.java.source.TreeMaker;
import org.netbeans.api.java.source.TreePathHandle;
+import org.netbeans.api.java.source.TreeUtilities;
import org.netbeans.api.java.source.TypeMirrorHandle;
import org.netbeans.api.java.source.WorkingCopy;
import org.netbeans.api.java.source.matching.Occurrence;
@@ -144,8 +148,17 @@ public class JavaFixUtilities {
static Fix rewriteFix(CompilationInfo info, String displayName, TreePath
what, final String to, Map<String, TreePath> parameters, Map<String,
Collection<? extends TreePath>> parametersMulti, final Map<String, String>
parameterNames, Map<String, TypeMirror> constraints, Map<String, String>
options, String... imports) {
final Map<String, TreePathHandle> params = new HashMap<String,
TreePathHandle>();
final Map<String, Object> extraParamsData = new HashMap<String,
Object>();
+ final Map<String, ElementHandle<?>> implicitThis = new HashMap<>();
for (Entry<String, TreePath> e : parameters.entrySet()) {
+ TreePath tp = e.getValue();
+ if (tp.getParentPath() != null &&
!immediateChildren(tp.getParentPath().getLeaf()).contains(tp.getLeaf())) {
+ Element el = info.getTrees().getElement(tp);
+ if (el != null && el.getSimpleName().contentEquals("this")) {
+ implicitThis.put(e.getKey(),
ElementHandle.create(el.getEnclosingElement()));
+ continue;
+ }
+ }
params.put(e.getKey(), TreePathHandle.create(e.getValue(), info));
if (e.getValue() instanceof Callable) {
try {
@@ -183,7 +196,22 @@ public class JavaFixUtilities {
displayName = defaultFixDisplayName(info, parameters, to);
}
- return new JavaFixRealImpl(info, what, options, displayName, to,
params, extraParamsData, paramsMulti, parameterNames, constraintsHandles,
Arrays.asList(imports)).toEditorFix();
+ return new JavaFixRealImpl(info, what, options, displayName, to,
params, extraParamsData, implicitThis, paramsMulti, parameterNames,
constraintsHandles, Arrays.asList(imports)).toEditorFix();
+ }
+
+ private static Set<Tree> immediateChildren(Tree t) {
+ Set<Tree> children = new HashSet<>();
+
+ t.accept(new TreeScanner<Void, Void>() {
+ @Override
+ public Void scan(Tree tree, Void p) {
+ if (tree != null)
+ children.add(tree);
+ return null;
+ }
+ }, null);
+
+ return children;
}
/**Creates a fix that removes the given code corresponding to the given
tree
@@ -357,19 +385,21 @@ public class JavaFixUtilities {
private final String displayName;
private final Map<String, TreePathHandle> params;
private final Map<String, Object> extraParamsData;
+ private final Map<String, ElementHandle<?>> implicitThis;
private final Map<String, Collection<TreePathHandle>> paramsMulti;
private final Map<String, String> parameterNames;
private final Map<String, TypeMirrorHandle<?>> constraintsHandles;
private final Iterable<? extends String> imports;
private final String to;
- public JavaFixRealImpl(CompilationInfo info, TreePath what,
Map<String, String> options, String displayName, String to, Map<String,
TreePathHandle> params, Map<String, Object> extraParamsData, Map<String,
Collection<TreePathHandle>> paramsMulti, final Map<String, String>
parameterNames, Map<String, TypeMirrorHandle<?>> constraintsHandles, Iterable<?
extends String> imports) {
+ public JavaFixRealImpl(CompilationInfo info, TreePath what,
Map<String, String> options, String displayName, String to, Map<String,
TreePathHandle> params, Map<String, Object> extraParamsData, Map<String,
ElementHandle<?>> implicitThis, Map<String, Collection<TreePathHandle>>
paramsMulti, final Map<String, String> parameterNames, Map<String,
TypeMirrorHandle<?>> constraintsHandles, Iterable<? extends String> imports) {
super(info, what, options);
this.displayName = displayName;
this.to = to;
this.params = params;
this.extraParamsData = extraParamsData;
+ this.implicitThis = implicitThis;
this.paramsMulti = paramsMulti;
this.parameterNames = parameterNames;
this.constraintsHandles = constraintsHandles;
@@ -400,6 +430,19 @@ public class JavaFixUtilities {
parameters.put(e.getKey(), p);
}
+ Map<String, Element> implicitThis = new HashMap<>();
+
+ for (Entry<String, ElementHandle<?>> e :
this.implicitThis.entrySet()) {
+ Element clazz = e.getValue().resolve(wc);
+
+ if (clazz == null) {
+
Logger.getLogger(JavaFix.class.getName()).log(Level.SEVERE, "Cannot resolve
handle={0}", e.getValue());
+ continue;
+ }
+
+ implicitThis.put(e.getKey(), clazz);
+ }
+
final Map<String, Collection<TreePath>> parametersMulti = new
HashMap<String, Collection<TreePath>>();
for (Entry<String, Collection<TreePathHandle>> e :
paramsMulti.entrySet()) {
@@ -528,7 +571,7 @@ public class JavaFixUtilities {
}
}.scan(original, null);
- new ReplaceParameters(wc, ctx.isCanShowUI(), inImport, parameters,
extraParamsData, parametersMulti, parameterNames, rewriteFromTo, order,
originalTrees).scan(new TreePath(tp.getParentPath(),
rewriteFromTo.get(original)), null);
+ new ReplaceParameters(wc, ctx.isCanShowUI(), inImport, parameters,
extraParamsData, implicitThis, parametersMulti, parameterNames, rewriteFromTo,
order, originalTrees).scan(new TreePath(tp.getParentPath(),
rewriteFromTo.get(original)), null);
if (inPackage) {
String newPackage =
wc.getTreeUtilities().translate(wc.getCompilationUnit().getPackageName(), new
IdentityHashMap<Tree, Tree>(rewriteFromTo))./*XXX: not correct*/toString();
@@ -587,19 +630,22 @@ public class JavaFixUtilities {
private final boolean inImport;
private final Map<String, TreePath> parameters;
private final Map<String, Object> extraParamsData;
+ private final Map<String, Element> implicitThis;
private final Map<String, Collection<TreePath>> parametersMulti;
private final Map<String, String> parameterNames;
private final Map<Tree, Tree> rewriteFromTo;
private final Set<Tree> originalTrees;
private final List<Tree> order;
+ private final List<Element> nestedTypes = new ArrayList<>();
- public ReplaceParameters(WorkingCopy wc, boolean canShowUI, boolean
inImport, Map<String, TreePath> parameters, Map<String, Object>
extraParamsData, Map<String, Collection<TreePath>> parametersMulti, Map<String,
String> parameterNames, Map<Tree, Tree> rewriteFromTo, List<Tree> order,
Set<Tree> originalTrees) {
+ public ReplaceParameters(WorkingCopy wc, boolean canShowUI, boolean
inImport, Map<String, TreePath> parameters, Map<String, Object>
extraParamsData, Map<String, Element> implicitThis, Map<String,
Collection<TreePath>> parametersMulti, Map<String, String> parameterNames,
Map<Tree, Tree> rewriteFromTo, List<Tree> order, Set<Tree> originalTrees) {
this.parameters = parameters;
this.info = wc;
this.make = wc.getTreeMaker();
this.canShowUI = canShowUI;
this.inImport = inImport;
this.extraParamsData = extraParamsData;
+ this.implicitThis = implicitThis;
this.parametersMulti = parametersMulti;
this.parameterNames = parameterNames;
this.rewriteFromTo = rewriteFromTo;
@@ -617,6 +663,17 @@ public class JavaFixUtilities {
if (NUMBER_LITERAL_KINDS.contains(newNode.getKind())) {
return (Number) ((LiteralTree) newNode).getValue();
}
+ } else {
+ Element implicitThisClass = implicitThis.get(name);
+ if (implicitThisClass != null) {
+ Element enclClass = findEnclosingClass();
+ if (enclClass == implicitThisClass) {
+ rewrite(node, make.Identifier("this"));
+ } else {
+ rewrite(node,
make.MemberSelect(make.QualIdent(implicitThisClass), "this"));
+ }
+ return null;
+ }
}
Element e = info.getTrees().getElement(getCurrentPath());
@@ -628,6 +685,14 @@ public class JavaFixUtilities {
return super.visitIdentifier(node, p);
}
+ private Element findEnclosingClass() {
+ TreePath findClass = getCurrentPath();
+ while (findClass != null &&
!TreeUtilities.CLASS_TREE_KINDS.contains(findClass.getLeaf().getKind())) {
+ findClass = findClass.getParentPath();
+ }
+ return findClass != null ? info.getTrees().getElement(findClass) :
null;
+ }
+
@Override
public Number visitTypeParameter(TypeParameterTree node, Void p) {
String name = node.getName().toString();
@@ -732,9 +797,36 @@ public class JavaFixUtilities {
String name = ((IdentifierTree)
nue.getExpression()).getName().toString();
if (name.startsWith("$") && parameters.get(name) == null) {
- //XXX: unbound variable, use identifier instead of member
select - may cause problems?
- rewrite(node, make.Identifier(nue.getIdentifier()));
- return null;
+ Element implicitThisClass = implicitThis.get(name);
+ if (implicitThisClass != null) {
+ TreePath findClass = getCurrentPath();
+ OUTER: while (findClass != null) {
+ if
(TreeUtilities.CLASS_TREE_KINDS.contains(findClass.getLeaf().getKind())) {
+ Element clazz =
info.getTrees().getElement(findClass);
+ if (implicitThisClass.equals(clazz)) {
+ //this.<...>, the this may be implicit:
+ rewrite(node,
make.Identifier(nue.getIdentifier()));
+ return null;
+ }
+ if (clazz.getKind().isClass() ||
clazz.getKind().isInterface()) {
+ for (Element currentClassElement :
info.getElements().getAllMembers((TypeElement) clazz)) {
+ if
(currentClassElement.getSimpleName().equals(node.getIdentifier())) {
+ //there may be a resolution
conflict, let the member select be qualified
+ //TODO: no conflicts between
fields and methods of the same name
+ //but we current still qualify the
name
+ break OUTER;
+ }
+ }
+ }
+ }
+ findClass = findClass.getParentPath();
+ }
+ //let visitIdent handle this
+ } else {
+ //XXX: unbound variable, use identifier instead of
member select - may cause problems?
+ rewrite(node, make.Identifier(nue.getIdentifier()));
+ return null;
+ }
}
}
@@ -814,7 +906,15 @@ public class JavaFixUtilities {
rewrite(node, nue);
- return super.visitClass(nue, p);
+ Element el = info.getTrees().getElement(getCurrentPath());
+
+ nestedTypes.add(el);
+
+ try {
+ return super.visitClass(nue, p);
+ } finally {
+ nestedTypes.remove(nestedTypes.size() - 1);
+ }
}
@Override
diff --git
a/java/spi.java.hints/test/unit/src/org/netbeans/spi/java/hints/JavaFixUtilitiesTest.java
b/java/spi.java.hints/test/unit/src/org/netbeans/spi/java/hints/JavaFixUtilitiesTest.java
index 2f2af83..f85c63a 100644
---
a/java/spi.java.hints/test/unit/src/org/netbeans/spi/java/hints/JavaFixUtilitiesTest.java
+++
b/java/spi.java.hints/test/unit/src/org/netbeans/spi/java/hints/JavaFixUtilitiesTest.java
@@ -1195,6 +1195,134 @@ public class JavaFixUtilitiesTest extends TestBase {
"}\n");
}
+ public void testImplicitThis1() throws Exception {
+ performRewriteTest("package test;\n" +
+ "public class Test {\n" +
+ " public void z(Test t) {\n" +
+ " this.z(new Test());\n" +
+ " }\n" +
+ "}\n",
+ "$0{test.Test}.z($1) => $1.z($0)",
+ "package test;\n" +
+ "public class Test {\n" +
+ " public void z(Test t) {\n" +
+ " new Test().z(this);\n" +
+ " }\n" +
+ "}\n");
+ }
+
+ public void testImplicitThis2() throws Exception {
+ performRewriteTest("package test;\n" +
+ "public class Test {\n" +
+ " public void z(Test t) {\n" +
+ " z(new Test());\n" +
+ " }\n" +
+ "}\n",
+ "$0{test.Test}.z($1) => $1.z($0)",
+ "package test;\n" +
+ "public class Test {\n" +
+ " public void z(Test t) {\n" +
+ " new Test().z(this);\n" +
+ " }\n" +
+ "}\n");
+ }
+
+ public void testImplicitThis3() throws Exception {
+ performRewriteTest("package test;\n" +
+ "public class Test {\n" +
+ " public void z(Test t) {\n" +
+ " }\n" +
+ " private class T {\n" +
+ " void t() {\n" +
+ " z(new Test());\n" +
+ " }\n" +
+ " }\n" +
+ "}\n",
+ "$0{test.Test}.z($1) => $1.z($0)",
+ "package test;\n" +
+ "public class Test {\n" +
+ " public void z(Test t) {\n" +
+ " }\n" +
+ " private class T {\n" +
+ " void t() {\n" +
+ " new Test().z(Test.this);\n" +
+ " }\n" +
+ " }\n" +
+ "}\n");
+ }
+
+ public void testImplicitThis4() throws Exception {
+ performRewriteTest("package test;\n" +
+ "public class Test {\n" +
+ " public void z() {}\n" +
+ " public void a() {}\n" +
+ " private class T {\n" +
+ " void t() {\n" +
+ " z();\n" +
+ " }\n" +
+ " }\n" +
+ "}\n",
+ "$0{test.Test}.z() => $0.a()",
+ "package test;\n" +
+ "public class Test {\n" +
+ " public void z() {}\n" +
+ " public void a() {}\n" +
+ " private class T {\n" +
+ " void t() {\n" +
+ " a();\n" +
+ " }\n" +
+ " }\n" +
+ "}\n");
+ }
+
+ public void testImplicitThis5() throws Exception {
+ performRewriteTest("package test;\n" +
+ "public class Test {\n" +
+ " public void z() {}\n" +
+ " public void a() {}\n" +
+ " private class T {\n" +
+ " public void a() {}\n" +
+ " void t() {\n" +
+ " z();\n" +
+ " }\n" +
+ " }\n" +
+ "}\n",
+ "$0{test.Test}.z() => $0.a()",
+ "package test;\n" +
+ "public class Test {\n" +
+ " public void z() {}\n" +
+ " public void a() {}\n" +
+ " private class T {\n" +
+ " public void a() {}\n" +
+ " void t() {\n" +
+ " Test.this.a();\n" +
+ " }\n" +
+ " }\n" +
+ "}\n");
+ }
+
+ public void testImplicitThis6() throws Exception {
+ performRewriteTest("package test;\n" +
+ "public class Test {\n" +
+ " public void z() {}\n" +
+ " private class T {\n" +
+ " void t() {\n" +
+ " z();\n" +
+ " }\n" +
+ " }\n" +
+ "}\n",
+ "$0{test.Test}.z() => $0.toString()",
+ "package test;\n" +
+ "public class Test {\n" +
+ " public void z() {}\n" +
+ " private class T {\n" +
+ " void t() {\n" +
+ " Test.this.toString();\n" +
+ " }\n" +
+ " }\n" +
+ "}\n");
+ }
+
public void performRewriteTest(String code, String rule, String golden)
throws Exception {
performRewriteTest(code, rule, golden, null);
}
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]
For further information about the NetBeans mailing lists, visit:
https://cwiki.apache.org/confluence/display/NETBEANS/Mailing+lists