You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@netbeans.apache.org by jl...@apache.org on 2017/10/22 19:36:41 UTC
[incubator-netbeans] 01/01: A very crude prototype of editor for
Java patterns.
This is an automated email from the ASF dual-hosted git repository.
jlahoda pushed a commit to branch jdk/amber/patterns
in repository https://gitbox.apache.org/repos/asf/incubator-netbeans.git
commit b062776b10e3cdad37c5eea2d8d87c757d8092d8
Author: Jan Lahoda <jl...@netbeans.org>
AuthorDate: Sun Oct 22 21:35:46 2017 +0200
A very crude prototype of editor for Java patterns.
---
.../java/completion/JavaCompletionTask.java | 143 +++++++++++++++++++--
.../modules/java/completion/Utilities.java | 20 +--
.../1.8/testBoundPatternVariable1.pass | 1 +
.../1.8/testBoundPatternVariable2.pass | 1 +
.../JavaCompletionTaskTest/1.8/testMatches1.pass | 2 +
.../1.8/testVariablePattern1.pass | 2 +
.../1.8/testVariablePattern2.pass | 1 +
.../1.8/testVariablePattern3.pass | 4 +
.../1.8/testVariablePattern4.pass | 2 +
.../1.8/testVariablePattern5.pass | 1 +
.../1.8/testVariablePatternInSwitch1.pass | 104 +++++++++++++++
.../1.8/testVariablePatternInSwitch2.pass | 2 +
.../JavaCompletionTaskTest/10/javaLangTypes.pass | 110 ++++++++++++++++
.../modules/java/completion/data/Patterns.java | 14 ++
.../JavaCompletionTaskAmberPatternsTest.java | 104 +++++++++++++++
java.editor.base/nbproject/project.xml | 4 +
.../editor/base/semantic/FindLocalUsagesQuery.java | 11 +-
.../base/semantic/SemanticHighlighterBase.java | 62 ++++++++-
.../java/editor/base/semantic/Utilities.java | 11 ++
.../base/semantic/DetectorTest/testPatterns.pass | 14 ++
.../base/semantic/MarkOccDetTest/testPatterns.pass | 2 +
.../java/editor/base/semantic/data/Patterns.java | 13 ++
.../java/editor/base/semantic/DetectorTest.java | 4 +
.../java/editor/base/semantic/MarkOccDetTest.java | 4 +
.../netbeans/modules/editor/java/GoToSupport.java | 14 +-
.../java/editor/codegen/LoggerGenerator.java | 2 +-
.../modules/editor/java/GoToSupportTest.java | 25 ++++
.../java/navigation/BreadCrumbsNodeImplTest.java | 10 +-
.../netbeans/api/java/source/TreeUtilities.java | 28 ++++
.../modules/java/source/builder/TreeFactory.java | 16 +++
.../modules/java/hints/spiimpl/JackpotTrees.java | 1 +
.../modules/java/hints/spiimpl/Utilities.java | 11 +-
32 files changed, 719 insertions(+), 24 deletions(-)
diff --git a/java.completion/src/org/netbeans/modules/java/completion/JavaCompletionTask.java b/java.completion/src/org/netbeans/modules/java/completion/JavaCompletionTask.java
index 234e0b3..564603b 100644
--- a/java.completion/src/org/netbeans/modules/java/completion/JavaCompletionTask.java
+++ b/java.completion/src/org/netbeans/modules/java/completion/JavaCompletionTask.java
@@ -163,6 +163,7 @@ public final class JavaCompletionTask<T> extends BaseTask {
private static final String INT_KEYWORD = "int"; //NOI18N
private static final String INTERFACE_KEYWORD = "interface"; //NOI18N
private static final String LONG_KEYWORD = "long"; //NOI18N
+ private static final String MATCHES_KEYWORD = "__matches"; //NOI18N
private static final String MODULE_KEYWORD = "module"; //NOI18N
private static final String NATIVE_KEYWORD = "native"; //NOI18N
private static final String NEW_KEYWORD = "new"; //NOI18N
@@ -467,6 +468,15 @@ public final class JavaCompletionTask<T> extends BaseTask {
case STRING_LITERAL:
insideStringLiteral(env);
break;
+ default:
+ switch (path.getLeaf().getKind().name()) {
+ case "VARIABLE_PATTERN":
+ insideVariablePattern(env);
+ break;
+ case "MATCHES":
+ insideMatches(env);
+ break;
+ }
}
}
@@ -909,6 +919,82 @@ public final class JavaCompletionTask<T> extends BaseTask {
}
}
+ private void insideVariablePattern(Env env) throws IOException {
+ int offset = env.getOffset();
+ TreePath path = env.getPath();
+ VariableTree var = (VariableTree) path.getLeaf();
+ SourcePositions sourcePositions = env.getSourcePositions();
+ CompilationUnitTree root = env.getRoot();
+ CompilationController controller = env.getController();
+ Tree type = var.getType();
+ int typePos = type.getKind() == Tree.Kind.ERRONEOUS && ((ErroneousTree) type).getErrorTrees().isEmpty()
+ ? (int) sourcePositions.getEndPosition(root, type) : (int) sourcePositions.getStartPosition(root, type);
+ if (offset <= typePos) {
+ Tree parent = path.getParentPath().getLeaf();
+ if (parent.getKind() == Tree.Kind.CATCH) {
+ if (!options.contains(Options.ALL_COMPLETION)) {
+ TreeUtilities tu = controller.getTreeUtilities();
+ TreePath tryPath = tu.getPathElementOfKind(Tree.Kind.TRY, path);
+ Set<TypeMirror> exs = tu.getUncaughtExceptions(tryPath);
+ Elements elements = controller.getElements();
+ for (TypeMirror ex : exs) {
+ if (ex.getKind() == TypeKind.DECLARED && startsWith(env, ((DeclaredType) ex).asElement().getSimpleName().toString())
+ && (Utilities.isShowDeprecatedMembers() || !elements.isDeprecated(((DeclaredType) ex).asElement()))
+ && !Utilities.isExcluded(((TypeElement)((DeclaredType) ex).asElement()).getQualifiedName())) {
+ env.addToExcludes(((DeclaredType) ex).asElement());
+ results.add(itemFactory.createTypeItem(controller, (TypeElement) ((DeclaredType) ex).asElement(), (DeclaredType) ex, anchorOffset, env.getReferencesCount(), elements.isDeprecated(((DeclaredType) ex).asElement()), false, false, false, true, false));
+ }
+ }
+ }
+ TypeElement te = controller.getElements().getTypeElement("java.lang.Throwable"); //NOI18N
+ if (te != null) {
+ addTypes(env, EnumSet.of(CLASS, INTERFACE, TYPE_PARAMETER), controller.getTypes().getDeclaredType(te));
+ }
+ } else if (parent.getKind() == Tree.Kind.TRY) {
+ TypeElement te = controller.getElements().getTypeElement("java.lang.AutoCloseable"); //NOI18N
+ if (te != null) {
+ addTypes(env, EnumSet.of(CLASS, INTERFACE, TYPE_PARAMETER), controller.getTypes().getDeclaredType(te));
+ }
+ } else {
+ boolean isLocal = !TreeUtilities.CLASS_TREE_KINDS.contains(parent.getKind());
+ addMemberModifiers(env, var.getModifiers().getFlags(), isLocal);
+ addTypes(env, EnumSet.of(CLASS, INTERFACE, ENUM, ANNOTATION_TYPE, TYPE_PARAMETER), null);
+ ModifiersTree mods = var.getModifiers();
+ if (mods.getFlags().isEmpty() && mods.getAnnotations().isEmpty()) {
+ addElementCreators(env);
+ }
+ }
+ return;
+ }
+ controller.toPhase(Phase.RESOLVED);
+ Tree init = unwrapErrTree(var.getInitializer());
+ if (init == null) {
+ TokenSequence<JavaTokenId> last = findLastNonWhitespaceToken(env, (int) sourcePositions.getEndPosition(root, type), offset);
+ if (last == null || last.token().id() == JavaTokenId.COMMA) {
+ insideExpression(env, new TreePath(path, type));
+ } else if (last.token().id() == JavaTokenId.EQ) {
+ localResult(env);
+ addValueKeywords(env);
+ }
+ } else {
+ int pos = (int) sourcePositions.getStartPosition(root, init);
+ if (pos < 0) {
+ return;
+ }
+ if (offset <= pos) {
+ TokenSequence<JavaTokenId> last = findLastNonWhitespaceToken(env, (int) sourcePositions.getEndPosition(root, type), offset);
+ if (last == null) {
+ insideExpression(env, new TreePath(path, type));
+ } else if (last.token().id() == JavaTokenId.EQ) {
+ localResult(env);
+ addValueKeywords(env);
+ }
+ } else {
+ insideExpression(env, new TreePath(path, init));
+ }
+ }
+ }
+
private void insideMethod(Env env) throws IOException {
int offset = env.getOffset();
TreePath path = env.getPath();
@@ -2292,7 +2378,7 @@ public final class JavaCompletionTask<T> extends BaseTask {
CaseTree cst = (CaseTree) path.getLeaf();
SourcePositions sourcePositions = env.getSourcePositions();
CompilationUnitTree root = env.getRoot();
- CompilationController controller = env.getController();
+ final CompilationController controller = env.getController();
if (cst.getExpression() != null && ((sourcePositions.getStartPosition(root, cst.getExpression()) >= offset)
|| (cst.getExpression().getKind() == Tree.Kind.ERRONEOUS && ((ErroneousTree) cst.getExpression()).getErrorTrees().isEmpty() && sourcePositions.getEndPosition(root, cst.getExpression()) >= offset))) {
TreePath path1 = path.getParentPath();
@@ -2307,8 +2393,27 @@ public final class JavaCompletionTask<T> extends BaseTask {
} else {
TokenSequence<JavaTokenId> ts = findLastNonWhitespaceToken(env, cst, offset);
if (ts != null && ts.token().id() != JavaTokenId.DEFAULT) {
- localResult(env);
- addKeywordsForBlock(env);
+ int exprEnd = (int) sourcePositions.getEndPosition(root, cst.getExpression());
+ if (ts.offset() + ts.token().length() == exprEnd) {
+ TypeMirror tm = controller.getTrees().getTypeMirror(new TreePath(env.getPath(), cst.getExpression()));
+ final Map<Name, ? extends Element> illegalForwardRefs = env.getForwardReferences();
+ Scope scope = env.getScope();
+ final ExecutableElement method = scope.getEnclosingMethod();
+ ElementUtilities.ElementAcceptor acceptor = new ElementUtilities.ElementAcceptor() {
+ @Override
+ public boolean accept(Element e, TypeMirror t) {
+ return (method == null || method == e.getEnclosingElement() || e.getModifiers().contains(FINAL)
+ || EnumSet.of(LOCAL_VARIABLE, PARAMETER, EXCEPTION_PARAMETER, RESOURCE_VARIABLE).contains(e.getKind()) && controller.getSourceVersion().compareTo(SourceVersion.RELEASE_8) >= 0 && controller.getElementUtilities().isEffectivelyFinal((VariableElement)e))
+ && !illegalForwardRefs.containsKey(e.getSimpleName());
+ }
+ };
+ for (String name : Utilities.varNamesSuggestions(tm, ElementKind.LOCAL_VARIABLE, EnumSet.noneOf(Modifier.class), null, env.getPrefix(), controller.getTypes(), controller.getElements(), controller.getTrees(), controller.getElementUtilities().getLocalMembersAndVars(scope, acceptor), CodeStyle.getDefault(controller.getDocument()))) {
+ results.add(itemFactory.createVariableItem(env.getController(), name, anchorOffset, true, false));
+ }
+ } else {
+ localResult(env);
+ addKeywordsForBlock(env);
+ }
}
}
}
@@ -2369,6 +2474,14 @@ public final class JavaCompletionTask<T> extends BaseTask {
}
}
+ private void insideMatches(Env env) throws IOException {
+ Tree iot = env.getPath().getLeaf();
+ TokenSequence<JavaTokenId> ts = findLastNonWhitespaceToken(env, iot, env.getOffset());
+ if (ts != null && ts.token().id() == JavaTokenId.IDENTIFIER && MATCHES_KEYWORD.contentEquals(ts.token().text())) {
+ addTypes(env, EnumSet.of(CLASS, INTERFACE, ENUM, ANNOTATION_TYPE, TYPE_PARAMETER), null);
+ }
+ }
+
private void insideArrayAccess(Env env) throws IOException {
int offset = env.getOffset();
ArrayAccessTree aat = (ArrayAccessTree) env.getPath().getLeaf();
@@ -2667,6 +2780,19 @@ public final class JavaCompletionTask<T> extends BaseTask {
et = ((AnnotatedTypeTree) et).getUnderlyingType();
exPath = new TreePath(exPath, et);
}
+ if (et.getKind().name().equals("MATCHES") && endPos < offset) {
+ List<Tree> children = env.getController().getTreeUtilities().getChildren(et);
+ parent = et = children.get(1); //((MatchesTree) et).getPattern()
+ exPath = new TreePath(exPath, et);
+ switch (et.getKind().name()) {
+ case "CONSTANT_PATTERN":
+ et = env.getController().getTreeUtilities().getChildren(et).get(0); //((ConstantPatternTree) et).getValue();
+ break;
+ default:
+ throw new IllegalStateException();
+ }
+ exPath = new TreePath(exPath, et);
+ }
if (parent.getKind() != Tree.Kind.PARENTHESIZED
&& (et.getKind() == Tree.Kind.PRIMITIVE_TYPE || et.getKind() == Tree.Kind.ARRAY_TYPE || et.getKind() == Tree.Kind.PARAMETERIZED_TYPE)) {
TypeMirror tm = controller.getTrees().getTypeMirror(exPath);
@@ -2681,7 +2807,7 @@ public final class JavaCompletionTask<T> extends BaseTask {
&& !illegalForwardRefs.containsKey(e.getSimpleName());
}
};
- for (String name : Utilities.varNamesSuggestions(tm, varKind, varMods, null, prefix, controller.getTypes(), controller.getElements(), controller.getElementUtilities().getLocalMembersAndVars(scope, acceptor), CodeStyle.getDefault(controller.getDocument()))) {
+ for (String name : Utilities.varNamesSuggestions(tm, varKind, varMods, null, prefix, controller.getTypes(), controller.getElements(), controller.getTrees(), controller.getElementUtilities().getLocalMembersAndVars(scope, acceptor), CodeStyle.getDefault(controller.getDocument()))) {
results.add(itemFactory.createVariableItem(env.getController(), name, anchorOffset, true, false));
}
return;
@@ -2718,7 +2844,7 @@ public final class JavaCompletionTask<T> extends BaseTask {
}
};
for (String name : Utilities.varNamesSuggestions(tm, varKind, varMods, null, prefix, controller.getTypes(), controller.getElements(),
- controller.getElementUtilities().getLocalMembersAndVars(scope, acceptor), CodeStyle.getDefault(controller.getDocument()))) {
+ controller.getTrees(), controller.getElementUtilities().getLocalMembersAndVars(scope, acceptor), CodeStyle.getDefault(controller.getDocument()))) {
results.add(itemFactory.createVariableItem(env.getController(), name, anchorOffset, true, false));
}
}
@@ -2735,6 +2861,7 @@ public final class JavaCompletionTask<T> extends BaseTask {
case PARAMETER:
if (tm != null && (tm.getKind() == TypeKind.DECLARED || tm.getKind() == TypeKind.ARRAY || tm.getKind() == TypeKind.ERROR)) {
addKeyword(env, INSTANCEOF_KEYWORD, SPACE, false);
+ addKeyword(env, MATCHES_KEYWORD, SPACE, false);
}
TypeElement te = getTypeElement(env, e.getSimpleName().toString());
if (te != null) {
@@ -2750,7 +2877,7 @@ public final class JavaCompletionTask<T> extends BaseTask {
}
};
for (String name : Utilities.varNamesSuggestions(controller.getTypes().getDeclaredType(te), varKind, varMods, null, prefix, controller.getTypes(),
- controller.getElements(), controller.getElementUtilities().getLocalMembersAndVars(scope, acceptor), CodeStyle.getDefault(controller.getDocument()))) {
+ controller.getElements(), controller.getTrees(), controller.getElementUtilities().getLocalMembersAndVars(scope, acceptor), CodeStyle.getDefault(controller.getDocument()))) {
results.add(itemFactory.createVariableItem(env.getController(), name, anchorOffset, true, false));
}
}
@@ -2859,7 +2986,7 @@ public final class JavaCompletionTask<T> extends BaseTask {
&& !illegalForwardRefs.containsKey(e.getSimpleName());
}
};
- for (String name : Utilities.varNamesSuggestions(tm, varKind, varMods, null, prefix, controller.getTypes(), controller.getElements(), controller.getElementUtilities().getLocalMembersAndVars(scope, acceptor), CodeStyle.getDefault(controller.getDocument()))) {
+ for (String name : Utilities.varNamesSuggestions(tm, varKind, varMods, null, prefix, controller.getTypes(), controller.getElements(), controller.getTrees(), controller.getElementUtilities().getLocalMembersAndVars(scope, acceptor), CodeStyle.getDefault(controller.getDocument()))) {
results.add(itemFactory.createVariableItem(env.getController(), name, anchorOffset, true, false));
}
break;
@@ -2876,7 +3003,7 @@ public final class JavaCompletionTask<T> extends BaseTask {
}
}
}
-
+
private void insideBreakOrContinue(Env env) throws IOException {
TreePath path = env.getPath();
TokenSequence<JavaTokenId> ts = findLastNonWhitespaceToken(env, path.getLeaf(), env.getOffset());
diff --git a/java.completion/src/org/netbeans/modules/java/completion/Utilities.java b/java.completion/src/org/netbeans/modules/java/completion/Utilities.java
index e1f97b2..b1a1a63 100644
--- a/java.completion/src/org/netbeans/modules/java/completion/Utilities.java
+++ b/java.completion/src/org/netbeans/modules/java/completion/Utilities.java
@@ -19,6 +19,7 @@
package org.netbeans.modules.java.completion;
+import com.sun.source.util.Trees;
import java.util.*;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicReference;
@@ -284,12 +285,12 @@ public final class Utilities {
}
}
- public static List<String> varNamesSuggestions(TypeMirror type, ElementKind kind, Set<Modifier> modifiers, String suggestedName, String prefix, Types types, Elements elements, Iterable<? extends Element> locals, CodeStyle codeStyle) {
+ public static List<String> varNamesSuggestions(TypeMirror type, ElementKind kind, Set<Modifier> modifiers, String suggestedName, String prefix, Types types, Elements elements, Trees trees, Iterable<? extends Element> locals, CodeStyle codeStyle) {
List<String> result = new ArrayList<>();
if (type == null && suggestedName == null) {
return result;
}
- List<String> vnct = suggestedName != null ? Collections.singletonList(suggestedName) : varNamesForType(type, types, elements, prefix);
+ List<String> vnct = suggestedName != null ? Collections.singletonList(suggestedName) : varNamesForType(type, types, elements, trees, prefix);
boolean isConst = false;
String namePrefix = null;
String nameSuffix = null;
@@ -379,17 +380,17 @@ public final class Utilities {
return result;
}
- private static List<String> varNamesForType(TypeMirror type, Types types, Elements elements, String prefix) {
+ private static List<String> varNamesForType(TypeMirror type, Types types, Elements elements, Trees trees, String prefix) {
switch (type.getKind()) {
case ARRAY:
TypeElement iterableTE = elements.getTypeElement("java.lang.Iterable"); //NOI18N
TypeMirror iterable = iterableTE != null ? types.getDeclaredType(iterableTE) : null;
TypeMirror ct = ((ArrayType) type).getComponentType();
if (ct.getKind() == TypeKind.ARRAY && iterable != null && types.isSubtype(ct, iterable)) {
- return varNamesForType(ct, types, elements, prefix);
+ return varNamesForType(ct, types, elements, trees, prefix);
}
List<String> vnct = new ArrayList<>();
- for (String name : varNamesForType(ct, types, elements, prefix)) {
+ for (String name : varNamesForType(ct, types, elements, trees, prefix)) {
vnct.add(name.endsWith("s") ? name + "es" : name + "s"); //NOI18N
}
return vnct;
@@ -408,6 +409,9 @@ public final class Utilities {
case TYPEVAR:
return Collections.<String>singletonList(type.toString().toLowerCase(Locale.ENGLISH));
case ERROR:
+ TypeMirror orig = trees.getOriginalType((ErrorType) type);
+ if (orig != null && orig.getKind() != TypeKind.ERROR)
+ return varNamesForType(orig, types, elements, trees, prefix);
String tn = ((ErrorType) type).asElement().getSimpleName().toString();
if (tn.toUpperCase(Locale.ENGLISH).contentEquals(tn)) {
return Collections.<String>singletonList(tn.toLowerCase(Locale.ENGLISH));
@@ -449,9 +453,9 @@ public final class Utilities {
if (tas.size() > 0) {
TypeMirror et = tas.get(0);
if (et.getKind() == TypeKind.ARRAY || (et.getKind() != TypeKind.WILDCARD && types.isSubtype(et, iterable))) {
- al.addAll(varNamesForType(et, types, elements, prefix));
+ al.addAll(varNamesForType(et, types, elements, trees, prefix));
} else {
- for (String name : varNamesForType(et, types, elements, prefix)) {
+ for (String name : varNamesForType(et, types, elements, trees, prefix)) {
al.add(name.endsWith("s") ? name + "es" : name + "s"); //NOI18N
}
}
@@ -470,7 +474,7 @@ public final class Utilities {
bound = ((WildcardType) type).getSuperBound();
}
if (bound != null) {
- return varNamesForType(bound, types, elements, prefix);
+ return varNamesForType(bound, types, elements, trees, prefix);
}
}
return Collections.<String>emptyList();
diff --git a/java.completion/test/unit/data/goldenfiles/org/netbeans/modules/java/completion/JavaCompletionTaskTest/1.8/testBoundPatternVariable1.pass b/java.completion/test/unit/data/goldenfiles/org/netbeans/modules/java/completion/JavaCompletionTaskTest/1.8/testBoundPatternVariable1.pass
new file mode 100644
index 0000000..7d77f8e
--- /dev/null
+++ b/java.completion/test/unit/data/goldenfiles/org/netbeans/modules/java/completion/JavaCompletionTaskTest/1.8/testBoundPatternVariable1.pass
@@ -0,0 +1 @@
+String str
diff --git a/java.completion/test/unit/data/goldenfiles/org/netbeans/modules/java/completion/JavaCompletionTaskTest/1.8/testBoundPatternVariable2.pass b/java.completion/test/unit/data/goldenfiles/org/netbeans/modules/java/completion/JavaCompletionTaskTest/1.8/testBoundPatternVariable2.pass
new file mode 100644
index 0000000..c441e8c
--- /dev/null
+++ b/java.completion/test/unit/data/goldenfiles/org/netbeans/modules/java/completion/JavaCompletionTaskTest/1.8/testBoundPatternVariable2.pass
@@ -0,0 +1 @@
+public int length()
diff --git a/java.completion/test/unit/data/goldenfiles/org/netbeans/modules/java/completion/JavaCompletionTaskTest/1.8/testMatches1.pass b/java.completion/test/unit/data/goldenfiles/org/netbeans/modules/java/completion/JavaCompletionTaskTest/1.8/testMatches1.pass
new file mode 100644
index 0000000..5174d10
--- /dev/null
+++ b/java.completion/test/unit/data/goldenfiles/org/netbeans/modules/java/completion/JavaCompletionTaskTest/1.8/testMatches1.pass
@@ -0,0 +1,2 @@
+__matches
+instanceof
diff --git a/java.completion/test/unit/data/goldenfiles/org/netbeans/modules/java/completion/JavaCompletionTaskTest/1.8/testVariablePattern1.pass b/java.completion/test/unit/data/goldenfiles/org/netbeans/modules/java/completion/JavaCompletionTaskTest/1.8/testVariablePattern1.pass
new file mode 100644
index 0000000..8f5cbed
--- /dev/null
+++ b/java.completion/test/unit/data/goldenfiles/org/netbeans/modules/java/completion/JavaCompletionTaskTest/1.8/testVariablePattern1.pass
@@ -0,0 +1,2 @@
+s
+string
diff --git a/java.completion/test/unit/data/goldenfiles/org/netbeans/modules/java/completion/JavaCompletionTaskTest/1.8/testVariablePattern2.pass b/java.completion/test/unit/data/goldenfiles/org/netbeans/modules/java/completion/JavaCompletionTaskTest/1.8/testVariablePattern2.pass
new file mode 100644
index 0000000..0ddf2ba
--- /dev/null
+++ b/java.completion/test/unit/data/goldenfiles/org/netbeans/modules/java/completion/JavaCompletionTaskTest/1.8/testVariablePattern2.pass
@@ -0,0 +1 @@
+i
diff --git a/java.completion/test/unit/data/goldenfiles/org/netbeans/modules/java/completion/JavaCompletionTaskTest/1.8/testVariablePattern3.pass b/java.completion/test/unit/data/goldenfiles/org/netbeans/modules/java/completion/JavaCompletionTaskTest/1.8/testVariablePattern3.pass
new file mode 100644
index 0000000..d753425
--- /dev/null
+++ b/java.completion/test/unit/data/goldenfiles/org/netbeans/modules/java/completion/JavaCompletionTaskTest/1.8/testVariablePattern3.pass
@@ -0,0 +1,4 @@
+l
+list
+ses
+strings
diff --git a/java.completion/test/unit/data/goldenfiles/org/netbeans/modules/java/completion/JavaCompletionTaskTest/1.8/testVariablePattern4.pass b/java.completion/test/unit/data/goldenfiles/org/netbeans/modules/java/completion/JavaCompletionTaskTest/1.8/testVariablePattern4.pass
new file mode 100644
index 0000000..7011bd4
--- /dev/null
+++ b/java.completion/test/unit/data/goldenfiles/org/netbeans/modules/java/completion/JavaCompletionTaskTest/1.8/testVariablePattern4.pass
@@ -0,0 +1,2 @@
+ses
+strings
diff --git a/java.completion/test/unit/data/goldenfiles/org/netbeans/modules/java/completion/JavaCompletionTaskTest/1.8/testVariablePattern5.pass b/java.completion/test/unit/data/goldenfiles/org/netbeans/modules/java/completion/JavaCompletionTaskTest/1.8/testVariablePattern5.pass
new file mode 100644
index 0000000..f5cb132
--- /dev/null
+++ b/java.completion/test/unit/data/goldenfiles/org/netbeans/modules/java/completion/JavaCompletionTaskTest/1.8/testVariablePattern5.pass
@@ -0,0 +1 @@
+is
diff --git a/java.completion/test/unit/data/goldenfiles/org/netbeans/modules/java/completion/JavaCompletionTaskTest/1.8/testVariablePatternInSwitch1.pass b/java.completion/test/unit/data/goldenfiles/org/netbeans/modules/java/completion/JavaCompletionTaskTest/1.8/testVariablePatternInSwitch1.pass
new file mode 100644
index 0000000..0418331
--- /dev/null
+++ b/java.completion/test/unit/data/goldenfiles/org/netbeans/modules/java/completion/JavaCompletionTaskTest/1.8/testVariablePatternInSwitch1.pass
@@ -0,0 +1,104 @@
+AbstractMethodError
+Appendable
+ArithmeticException
+ArrayIndexOutOfBoundsException
+ArrayStoreException
+AssertionError
+AutoCloseable
+Boolean
+BootstrapMethodError
+Byte
+CharSequence
+Character
+Class
+ClassCastException
+ClassCircularityError
+ClassFormatError
+ClassLoader
+ClassNotFoundException
+ClassValue
+CloneNotSupportedException
+Cloneable
+Comparable
+Compiler
+Deprecated
+Double
+Enum
+EnumConstantNotPresentException
+Error
+Exception
+ExceptionInInitializerError
+Float
+FunctionalInterface
+IllegalAccessError
+IllegalAccessException
+IllegalArgumentException
+IllegalMonitorStateException
+IllegalStateException
+IllegalThreadStateException
+IncompatibleClassChangeError
+IndexOutOfBoundsException
+InheritableThreadLocal
+InstantiationError
+InstantiationException
+Integer
+InternalError
+InterruptedException
+Iterable
+LinkageError
+Long
+Math
+NegativeArraySizeException
+NoClassDefFoundError
+NoSuchFieldError
+NoSuchFieldException
+NoSuchMethodError
+NoSuchMethodException
+NullPointerException
+Number
+NumberFormatException
+Object
+OutOfMemoryError
+Override
+Package
+Process
+ProcessBuilder
+Readable
+ReflectiveOperationException
+Runnable
+Runtime
+RuntimeException
+RuntimePermission
+SafeVarargs
+SecurityException
+SecurityManager
+Short
+StackOverflowError
+StackTraceElement
+StrictMath
+String
+StringBuffer
+StringBuilder
+StringIndexOutOfBoundsException
+SuppressWarnings
+System
+Test
+Thread
+ThreadDeath
+ThreadGroup
+ThreadLocal
+Throwable
+TypeNotPresentException
+UnknownError
+UnsatisfiedLinkError
+UnsupportedClassVersionError
+UnsupportedOperationException
+VerifyError
+VirtualMachineError
+Void
+com
+java
+javax
+oracle
+org
+sun
diff --git a/java.completion/test/unit/data/goldenfiles/org/netbeans/modules/java/completion/JavaCompletionTaskTest/1.8/testVariablePatternInSwitch2.pass b/java.completion/test/unit/data/goldenfiles/org/netbeans/modules/java/completion/JavaCompletionTaskTest/1.8/testVariablePatternInSwitch2.pass
new file mode 100644
index 0000000..8f5cbed
--- /dev/null
+++ b/java.completion/test/unit/data/goldenfiles/org/netbeans/modules/java/completion/JavaCompletionTaskTest/1.8/testVariablePatternInSwitch2.pass
@@ -0,0 +1,2 @@
+s
+string
diff --git a/java.completion/test/unit/data/goldenfiles/org/netbeans/modules/java/completion/JavaCompletionTaskTest/10/javaLangTypes.pass b/java.completion/test/unit/data/goldenfiles/org/netbeans/modules/java/completion/JavaCompletionTaskTest/10/javaLangTypes.pass
new file mode 100644
index 0000000..be3ce7c
--- /dev/null
+++ b/java.completion/test/unit/data/goldenfiles/org/netbeans/modules/java/completion/JavaCompletionTaskTest/10/javaLangTypes.pass
@@ -0,0 +1,110 @@
+AbstractMethodError
+Appendable
+ArithmeticException
+ArrayIndexOutOfBoundsException
+ArrayStoreException
+AssertionError
+AutoCloseable
+Boolean
+BootstrapMethodError
+Byte
+CharSequence
+Character
+Class
+ClassCastException
+ClassCircularityError
+ClassFormatError
+ClassLoader
+ClassNotFoundException
+ClassValue
+CloneNotSupportedException
+Cloneable
+Comparable
+Compiler
+Deprecated
+Double
+Enum
+EnumConstantNotPresentException
+Error
+Exception
+ExceptionInInitializerError
+Float
+FunctionalInterface
+IllegalAccessError
+IllegalAccessException
+IllegalArgumentException
+IllegalCallerException
+IllegalMonitorStateException
+IllegalStateException
+IllegalThreadStateException
+IncompatibleClassChangeError
+IndexOutOfBoundsException
+InheritableThreadLocal
+InstantiationError
+InstantiationException
+Integer
+InternalError
+InterruptedException
+Iterable
+LayerInstantiationException
+LinkageError
+Long
+Math
+Module
+ModuleLayer
+NegativeArraySizeException
+NoClassDefFoundError
+NoSuchFieldError
+NoSuchFieldException
+NoSuchMethodError
+NoSuchMethodException
+NullPointerException
+Number
+NumberFormatException
+Object
+OutOfMemoryError
+Override
+Package
+Process
+ProcessBuilder
+ProcessHandle
+Readable
+ReflectiveOperationException
+Runnable
+Runtime
+RuntimeException
+RuntimePermission
+SafeVarargs
+SecurityException
+SecurityManager
+Short
+StackOverflowError
+StackTraceElement
+StackWalker
+StrictMath
+String
+StringBuffer
+StringBuilder
+StringIndexOutOfBoundsException
+SuppressWarnings
+System
+Test
+Thread
+ThreadDeath
+ThreadGroup
+ThreadLocal
+Throwable
+TypeNotPresentException
+UnknownError
+UnsatisfiedLinkError
+UnsupportedClassVersionError
+UnsupportedOperationException
+VerifyError
+VirtualMachineError
+Void
+com
+java
+javax
+netscape
+org
+sun
diff --git a/java.completion/test/unit/data/org/netbeans/modules/java/completion/data/Patterns.java b/java.completion/test/unit/data/org/netbeans/modules/java/completion/data/Patterns.java
new file mode 100644
index 0000000..ad1a8f8
--- /dev/null
+++ b/java.completion/test/unit/data/org/netbeans/modules/java/completion/data/Patterns.java
@@ -0,0 +1,14 @@
+package test;
+
+public class Test {
+
+ public void op(Object o) {
+ if (o __matches String str) {
+ System.err.println("len: ");
+ }
+ if (o) { }
+ switch (o) {
+ case null: System.err.println("null"); break;
+ }
+ }
+}
diff --git a/java.completion/test/unit/src/org/netbeans/modules/java/completion/JavaCompletionTaskAmberPatternsTest.java b/java.completion/test/unit/src/org/netbeans/modules/java/completion/JavaCompletionTaskAmberPatternsTest.java
new file mode 100644
index 0000000..d71884d
--- /dev/null
+++ b/java.completion/test/unit/src/org/netbeans/modules/java/completion/JavaCompletionTaskAmberPatternsTest.java
@@ -0,0 +1,104 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved.
+ *
+ * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
+ * Other names may be trademarks of their respective owners.
+ *
+ * The contents of this file are subject to the terms of either the GNU
+ * General Public License Version 2 only ("GPL") or the Common
+ * Development and Distribution License("CDDL") (collectively, the
+ * "License"). You may not use this file except in compliance with the
+ * License. You can obtain a copy of the License at
+ * http://www.netbeans.org/cddl-gplv2.html
+ * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
+ * specific language governing permissions and limitations under the
+ * License. When distributing the software, include this License Header
+ * Notice in each file and include the License file at
+ * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the GPL Version 2 section of the License file that
+ * accompanied this code. If applicable, add the following below the
+ * License Header, with the fields enclosed by brackets [] replaced by
+ * your own identifying information:
+ * "Portions Copyrighted [year] [name of copyright owner]"
+ *
+ * Contributor(s):
+ *
+ * The Original Software is NetBeans. The Initial Developer of the Original
+ * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
+ * Microsystems, Inc. All Rights Reserved.
+ *
+ * If you wish your version of this file to be governed by only the CDDL
+ * or only the GPL Version 2, indicate your decision by adding
+ * "[Contributor] elects to include this software in this distribution
+ * under the [CDDL or GPL Version 2] license." If you do not indicate a
+ * single choice of license, a recipient has the option to distribute
+ * your version of this file under either the CDDL, the GPL Version 2 or
+ * to extend the choice of license to its licensees as provided above.
+ * However, if you add GPL Version 2 code and therefore, elected the GPL
+ * Version 2 license, then the option applies only if the new code is
+ * made subject to such option by the copyright holder.
+ */
+package org.netbeans.modules.java.completion;
+
+import org.netbeans.modules.java.source.parsing.JavacParser;
+
+/**
+ *
+ * @author Dusan Balek
+ */
+//TODO: smart types
+public class JavaCompletionTaskAmberPatternsTest extends CompletionTestBase {
+
+ public JavaCompletionTaskAmberPatternsTest(String testName) {
+ super(testName);
+ }
+
+ public void testBoundPatternVariable1() throws Exception {
+ performTest("Patterns", 143, "+ st", "testBoundPatternVariable1.pass", "1.9");
+ }
+
+ public void testBoundPatternVariable2() throws Exception {
+ performTest("Patterns", 143, "+ str.len", "testBoundPatternVariable2.pass", "1.9");
+ }
+
+ public void testMatches1() throws Exception {
+ //TODO: fix the remaining instances of addKeyword(env, INSTANCEOF_KEYWORD, SPACE, false);
+ performTest("Patterns", 169, " ", "testMatches1.pass", "1.9");
+ }
+
+ public void testTypeAfterMatches() throws Exception {
+ performTest("Patterns", 169, " __matches ", "javaLangTypes.pass", "1.9");
+ }
+
+ public void testVariablePatternName() throws Exception {
+ performTest("Patterns", 169, " __matches String ", "testVariablePattern1.pass", "1.9");
+ performTest("Patterns", 169, " __matches int ", "testVariablePattern2.pass", "1.9");
+ performTest("Patterns", 169, " __matches java.util.List<String> ", "testVariablePattern3.pass", "1.9");
+ performTest("Patterns", 169, " __matches String[] ", "testVariablePattern4.pass", "1.9");
+ performTest("Patterns", 169, " __matches int[] ", "testVariablePattern5.pass", "1.9");
+ }
+
+ public void testVariablePatternInSwitch() throws Exception {
+ performTest("Patterns", 213, " ", "javaLangTypes.pass", "1.9");
+ performTest("Patterns", 213, "String ", "testVariablePatternInSwitch2.pass", "1.9");
+ }
+
+ @Override
+ protected void runTest() throws Throwable {
+ try {
+ Class.forName("com.sun.source.tree.MatchesTree");
+ } catch (ClassNotFoundException ex) {
+ //skip
+ return ;
+ }
+ super.runTest();
+ }
+
+
+ static {
+ JavacParser.DISABLE_SOURCE_LEVEL_DOWNGRADE = true;
+ }
+}
diff --git a/java.editor.base/nbproject/project.xml b/java.editor.base/nbproject/project.xml
index 3e05345..51c0824 100644
--- a/java.editor.base/nbproject/project.xml
+++ b/java.editor.base/nbproject/project.xml
@@ -202,6 +202,10 @@
<compile-dependency/>
</test-dependency>
<test-dependency>
+ <code-name-base>org.netbeans.modules.java.j2seplatform</code-name-base>
+ <compile-dependency/>
+ </test-dependency>
+ <test-dependency>
<code-name-base>org.netbeans.modules.java.source.base</code-name-base>
<recursive/>
<compile-dependency/>
diff --git a/java.editor.base/src/org/netbeans/modules/java/editor/base/semantic/FindLocalUsagesQuery.java b/java.editor.base/src/org/netbeans/modules/java/editor/base/semantic/FindLocalUsagesQuery.java
index a4d7f9a..bbce89f 100644
--- a/java.editor.base/src/org/netbeans/modules/java/editor/base/semantic/FindLocalUsagesQuery.java
+++ b/java.editor.base/src/org/netbeans/modules/java/editor/base/semantic/FindLocalUsagesQuery.java
@@ -133,7 +133,7 @@ public class FindLocalUsagesQuery extends CancellableTreePathScanner<Void, Stack
super.visitVariable(tree, d);
return null;
}
-
+
@Override
public Void visitClass(ClassTree tree, Stack<Tree> d) {
handlePotentialVariable(getCurrentPath());
@@ -191,4 +191,13 @@ public class FindLocalUsagesQuery extends CancellableTreePathScanner<Void, Stack
}
return super.visitImport(node, p);
}
+
+ @Override
+ public Void scan(Tree tree, Stack<Tree> p) {
+ if (tree != null && tree.getKind().name().equals("VARIABLE_PATTERN")) {
+ handlePotentialVariable(new TreePath(getCurrentPath(), tree));
+ }
+ return super.scan(tree, p);
+ }
+
}
diff --git a/java.editor.base/src/org/netbeans/modules/java/editor/base/semantic/SemanticHighlighterBase.java b/java.editor.base/src/org/netbeans/modules/java/editor/base/semantic/SemanticHighlighterBase.java
index 8a72f45..887620c 100644
--- a/java.editor.base/src/org/netbeans/modules/java/editor/base/semantic/SemanticHighlighterBase.java
+++ b/java.editor.base/src/org/netbeans/modules/java/editor/base/semantic/SemanticHighlighterBase.java
@@ -41,6 +41,7 @@ import com.sun.source.tree.IfTree;
import com.sun.source.tree.ImportTree;
import com.sun.source.tree.InstanceOfTree;
import com.sun.source.tree.LambdaExpressionTree;
+//import com.sun.source.tree.MatchesTree;
import com.sun.source.tree.MemberReferenceTree;
import com.sun.source.tree.MemberSelectTree;
import com.sun.source.tree.MethodInvocationTree;
@@ -63,12 +64,14 @@ import com.sun.source.tree.TypeParameterTree;
import com.sun.source.tree.UnaryTree;
import com.sun.source.tree.UnionTypeTree;
import com.sun.source.tree.UsesTree;
+//import com.sun.source.tree.VariablePatternTree;
import com.sun.source.tree.VariableTree;
import com.sun.source.tree.WhileLoopTree;
import com.sun.source.tree.WildcardTree;
import com.sun.source.util.SourcePositions;
import com.sun.source.util.TreePath;
import java.lang.reflect.Field;
+import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
@@ -105,7 +108,6 @@ import org.netbeans.modules.parsing.spi.Scheduler;
import org.netbeans.modules.parsing.spi.SchedulerEvent;
import org.netbeans.modules.parsing.spi.TaskIndexingMode;
import org.openide.filesystems.FileUtil;
-import org.openide.util.Exceptions;
/**
@@ -1540,6 +1542,64 @@ public abstract class SemanticHighlighterBase extends JavaParserResultTask {
return null;
}
+ private TreePath currentPath;
+
+ public TreePath getCurrentPath() {
+ return currentPath;
+ }
+
+ @Override
+ public Void scan(Tree tree, EnumSet<UseTypes> p) {
+ if (tree == null) {
+ return null;
+ }
+ TreePath oldPath = currentPath;
+ try {
+ currentPath = new TreePath(currentPath, tree);
+ switch (tree.getKind().name()) {
+ case "MATCHES": return visitMatches(tree, p);
+ case "VARIABLE_PATTERN": return visitVariablePattern(tree, p);
+ }
+ return super.scan(tree, p);
+ } finally {
+ currentPath = oldPath;
+ }
+ }
+
+ public Void visitMatches(Tree node, EnumSet<UseTypes> p) {
+ List<Tree> children = info.getTreeUtilities().getChildren(node);
+ scan(children.get(0) /*node.getExpression()*/, p);
+ tl.moveToEnd(children.get(0) /*node.getExpression()*/);
+ Token t = firstIdentifierToken("__matches", "matches");
+ if (t != null) {
+ contextKeywords.add(t);
+ }
+ scan(children.get(1) /*node.getPattern()*/, p);
+ return null;
+ }
+
+ public Void visitVariablePattern(Tree node, EnumSet<UseTypes> p) {
+ List<Tree> children = info.getTreeUtilities().getChildren(node);
+ handlePossibleIdentifier(getCurrentPath(), EnumSet.of(UseTypes.DECLARATION, UseTypes.WRITE));
+
+ scan(children.get(0) /*tree.getType()*/, null);
+
+ tl.moveToEnd(children.get(0) /*tree.getType()*/);
+
+// int[] span = info.getTreeUtilities().findNameSpan(tree);
+// if (span != null)
+// tl.moveToOffset(span[0]);
+
+ try {
+ Method getBinding = node.getClass().getMethod("getBinding");
+ firstIdentifier(String.valueOf(getBinding.invoke(node)));
+ } catch (Exception ex) {
+ ex.printStackTrace(); //XXX
+ }
+
+ return null;
+ }
+
}
public static interface ErrorDescriptionSetter {
diff --git a/java.editor.base/src/org/netbeans/modules/java/editor/base/semantic/Utilities.java b/java.editor.base/src/org/netbeans/modules/java/editor/base/semantic/Utilities.java
index e127369..faf248e 100644
--- a/java.editor.base/src/org/netbeans/modules/java/editor/base/semantic/Utilities.java
+++ b/java.editor.base/src/org/netbeans/modules/java/editor/base/semantic/Utilities.java
@@ -578,6 +578,17 @@ public class Utilities {
TokenHierarchy<?> th = info.getTokenHierarchy();
TokenSequence<JavaTokenId> ts = th.tokenSequence(JavaTokenId.language());
+ if ("VARIABLE_PATTERN".equals(leaf.getKind().name())) {
+ ts.move(end);
+ if (ts.movePrevious()) {
+ Token<JavaTokenId> token = ts.token();
+ JavaTokenId id = token.id();
+ if (id == JavaTokenId.IDENTIFIER) {
+ return token;
+ }
+ }
+ }
+
if (ts.move(start) == Integer.MAX_VALUE) {
return null;
}
diff --git a/java.editor.base/test/unit/data/goldenfiles/org/netbeans/modules/java/editor/base/semantic/DetectorTest/testPatterns.pass b/java.editor.base/test/unit/data/goldenfiles/org/netbeans/modules/java/editor/base/semantic/DetectorTest/testPatterns.pass
new file mode 100644
index 0000000..b8fd5fb
--- /dev/null
+++ b/java.editor.base/test/unit/data/goldenfiles/org/netbeans/modules/java/editor/base/semantic/DetectorTest/testPatterns.pass
@@ -0,0 +1,14 @@
+[PUBLIC, CLASS, DECLARATION], 2:13-2:21
+[STATIC, PUBLIC, METHOD, DECLARATION], 4:23-4:27
+[PUBLIC, CLASS], 4:28-4:34
+[PARAMETER, DECLARATION], 4:35-4:36
+[PARAMETER], 5:12-5:13
+[], 5:14-5:23
+[LOCAL_VARIABLE, DECLARATION], 5:31-5:35
+[PUBLIC, CLASS], 6:12-6:18
+[STATIC, PUBLIC, FIELD], 6:19-6:22
+[PUBLIC, METHOD], 6:23-6:30
+[LOCAL_VARIABLE], 6:41-6:45
+[PARAMETER], 8:12-8:13
+[], 8:14-8:23
+[LOCAL_VARIABLE, UNUSED, DECLARATION], 8:31-8:35
diff --git a/java.editor.base/test/unit/data/goldenfiles/org/netbeans/modules/java/editor/base/semantic/MarkOccDetTest/testPatterns.pass b/java.editor.base/test/unit/data/goldenfiles/org/netbeans/modules/java/editor/base/semantic/MarkOccDetTest/testPatterns.pass
new file mode 100644
index 0000000..28bdae1
--- /dev/null
+++ b/java.editor.base/test/unit/data/goldenfiles/org/netbeans/modules/java/editor/base/semantic/MarkOccDetTest/testPatterns.pass
@@ -0,0 +1,2 @@
+[MARK_OCCURRENCES], 5:31-5:35
+[MARK_OCCURRENCES], 6:41-6:45
diff --git a/java.editor.base/test/unit/data/org/netbeans/modules/java/editor/base/semantic/data/Patterns.java b/java.editor.base/test/unit/data/org/netbeans/modules/java/editor/base/semantic/data/Patterns.java
new file mode 100644
index 0000000..48d6664
--- /dev/null
+++ b/java.editor.base/test/unit/data/org/netbeans/modules/java/editor/base/semantic/data/Patterns.java
@@ -0,0 +1,13 @@
+package org.netbeans.modules.java.editor.semantic.data;
+
+public class Patterns {
+
+ public static void main(Object o) {
+ if (o __matches String str1) {
+ System.err.println("str1=" + str1);
+ }
+ if (o __matches String str2) {
+ }
+ }
+
+}
diff --git a/java.editor.base/test/unit/src/org/netbeans/modules/java/editor/base/semantic/DetectorTest.java b/java.editor.base/test/unit/src/org/netbeans/modules/java/editor/base/semantic/DetectorTest.java
index 1995fad..4b591ef 100644
--- a/java.editor.base/test/unit/src/org/netbeans/modules/java/editor/base/semantic/DetectorTest.java
+++ b/java.editor.base/test/unit/src/org/netbeans/modules/java/editor/base/semantic/DetectorTest.java
@@ -398,6 +398,10 @@ public class DetectorTest extends TestBase {
performTest("IncDecReading230408");
}
+ public void testPatterns() throws Exception {
+ performTest("Patterns");
+ }
+
private void performTest(String fileName) throws Exception {
performTest(fileName, new Performer() {
public void compute(CompilationController parameter, Document doc, final ErrorDescriptionSetter setter) {
diff --git a/java.editor.base/test/unit/src/org/netbeans/modules/java/editor/base/semantic/MarkOccDetTest.java b/java.editor.base/test/unit/src/org/netbeans/modules/java/editor/base/semantic/MarkOccDetTest.java
index 125dd42..fe81fcb 100644
--- a/java.editor.base/test/unit/src/org/netbeans/modules/java/editor/base/semantic/MarkOccDetTest.java
+++ b/java.editor.base/test/unit/src/org/netbeans/modules/java/editor/base/semantic/MarkOccDetTest.java
@@ -316,6 +316,10 @@ public class MarkOccDetTest extends TestBase {
performTest("ExitPoints", 115, 22);
}
+ public void testPatterns() throws Exception {
+ performTest("Patterns", 6, 42);
+ }
+
//Support for exotic identifiers has been removed 6999438
public void REMOVEDtestExoticIdentifiers1() throws Exception {
performTest("ExoticIdentifier", 3, 43);
diff --git a/java.editor/src/org/netbeans/modules/editor/java/GoToSupport.java b/java.editor/src/org/netbeans/modules/editor/java/GoToSupport.java
index b5e8915..ed6c030 100644
--- a/java.editor/src/org/netbeans/modules/editor/java/GoToSupport.java
+++ b/java.editor/src/org/netbeans/modules/editor/java/GoToSupport.java
@@ -36,6 +36,7 @@ import com.sun.source.tree.Scope;
import com.sun.source.tree.Tree;
import com.sun.source.tree.Tree.Kind;
import com.sun.source.tree.TypeParameterTree;
+//import com.sun.source.tree.VariablePatternTree;
import com.sun.source.tree.VariableTree;
import com.sun.source.util.TreePath;
import org.netbeans.api.java.source.support.ErrorAwareTreePathScanner;
@@ -713,12 +714,21 @@ public class GoToSupport {
if (found != null) {
return null;
}
+ if (tree != null && tree.getKind().name().equals("VARIABLE_PATTERN")) {
+ if (!process(new TreePath(getCurrentPath(), tree))) {
+ return super.scan(tree, p);
+ }
+ return null;
+ }
return super.scan(tree, p);
}
private boolean process() {
- Element resolved = info.getTrees().getElement(getCurrentPath());
+ return process(getCurrentPath());
+ }
+ private boolean process(TreePath path) {
+ Element resolved = info.getTrees().getElement(path);
if (toFind.equals(resolved)) {
- found = getCurrentPath();
+ found = path;
return true;
}
return false;
diff --git a/java.editor/src/org/netbeans/modules/java/editor/codegen/LoggerGenerator.java b/java.editor/src/org/netbeans/modules/java/editor/codegen/LoggerGenerator.java
index fbcc66f..69f0376 100644
--- a/java.editor/src/org/netbeans/modules/java/editor/codegen/LoggerGenerator.java
+++ b/java.editor/src/org/netbeans/modules/java/editor/codegen/LoggerGenerator.java
@@ -139,7 +139,7 @@ public class LoggerGenerator implements CodeGenerator {
ClassTree cls = (ClassTree) path.getLeaf();
CodeStyle cs = CodeStyle.getDefault(component.getDocument());
Set<Modifier> mods = EnumSet.of(Modifier.PRIVATE, Modifier.STATIC, Modifier.FINAL);
- List<String> names = Utilities.varNamesSuggestions(null, ElementKind.FIELD, mods, "LOG", null, copy.getTypes(), copy.getElements(), e.getEnclosedElements(), cs);
+ List<String> names = Utilities.varNamesSuggestions(null, ElementKind.FIELD, mods, "LOG", null, copy.getTypes(), copy.getElements(), copy.getTrees(), e.getEnclosedElements(), cs);
VariableTree var = createLoggerField(copy.getTreeMaker(), cls, names.size() > 0 ? names.get(0) : "LOG", mods); //NOI18N
copy.rewrite(cls, GeneratorUtils.insertClassMembers(copy, cls, Collections.singletonList(var), caretOffset));
}
diff --git a/java.editor/test/unit/src/org/netbeans/modules/editor/java/GoToSupportTest.java b/java.editor/test/unit/src/org/netbeans/modules/editor/java/GoToSupportTest.java
index bf44269..0d5991c 100644
--- a/java.editor/test/unit/src/org/netbeans/modules/editor/java/GoToSupportTest.java
+++ b/java.editor/test/unit/src/org/netbeans/modules/editor/java/GoToSupportTest.java
@@ -929,6 +929,31 @@ public class GoToSupportTest extends NbTestCase {
assertTrue(wasCalled[0]);
}
+ public void testPatterns1() throws Exception {
+ final boolean[] wasCalled = new boolean[1];
+
+ performTest("package test; public class Test { t(Object o) { if (o __matches String str) { String s = str; } }", 91, new UiUtilsCaller() {
+ public boolean open(FileObject fo, int pos) {
+ assertTrue(source == fo);
+ assertEquals(64, pos);
+ wasCalled[0] = true;
+ return true;
+ }
+ public void beep(boolean goToSource, boolean goToJavadoc) {
+ fail("Should not be called.");
+ }
+ public boolean open(ClasspathInfo info, ElementHandle<?> el) {
+ fail("Should not be called.");
+ return false;
+ }
+ public void warnCannotOpen(String displayName) {
+ fail("Should not be called.");
+ }
+ }, false);
+
+ assertTrue(wasCalled[0]);
+ }
+
public void testDeadlock135736() throws Exception {
final CountDownLatch l1 = new CountDownLatch(1);
final CountDownLatch l2 = new CountDownLatch(1);
diff --git a/java.navigation/test/unit/src/org/netbeans/modules/java/navigation/BreadCrumbsNodeImplTest.java b/java.navigation/test/unit/src/org/netbeans/modules/java/navigation/BreadCrumbsNodeImplTest.java
index d0fe02b..70480e5 100644
--- a/java.navigation/test/unit/src/org/netbeans/modules/java/navigation/BreadCrumbsNodeImplTest.java
+++ b/java.navigation/test/unit/src/org/netbeans/modules/java/navigation/BreadCrumbsNodeImplTest.java
@@ -24,7 +24,6 @@ import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.atomic.AtomicBoolean;
-import static org.junit.Assert.*;
import org.netbeans.api.java.source.CompilationInfo;
import org.netbeans.api.java.source.JavaSource;
import org.netbeans.api.java.source.SourceUtilsTestUtil;
@@ -34,7 +33,6 @@ import org.netbeans.modules.editor.breadcrumbs.spi.BreadcrumbsElement;
import org.netbeans.spi.queries.FileEncodingQueryImplementation;
import org.openide.filesystems.FileObject;
import org.openide.filesystems.FileUtil;
-import org.openide.nodes.Node;
import org.openide.util.lookup.ServiceProvider;
/**
@@ -99,6 +97,14 @@ public class BreadCrumbsNodeImplTest extends NbTestCase {
performBreadcrumbsSelectionTest("package test; public class Test { t(String str) { if (str.equals(\"čcč|\")) { | } }", "test.Test>>>>t>>>>if <font color=#707070>(str.equals("čcč"))</font>>>>>");
}
+ public void testPatterns1() throws Exception {
+ performBreadcrumbsSelectionTest("package test; public class Test { t(Object o) { if (o __matches String str) { String s = st|r; } }", "test.Test>>>>t>>>>if <font color=#707070>(o matches String str)</font>>>>>s>>>>");
+ }
+
+ public void testPatterns2() throws Exception {
+ performBreadcrumbsSelectionTest("package test; public class Test { t(Object o) { if (o __matches String s|tr) { String s = str; } }", "test.Test>>>>t>>>>if <font color=#707070>(o matches String str)</font>>>>>");
+ }
+
private void performBreadcrumbsSelectionTest(String code, String golden) throws Exception {
int caret = code.indexOf('|');
diff --git a/java.source.base/src/org/netbeans/api/java/source/TreeUtilities.java b/java.source.base/src/org/netbeans/api/java/source/TreeUtilities.java
index aac8cee..6d705b9 100644
--- a/java.source.base/src/org/netbeans/api/java/source/TreeUtilities.java
+++ b/java.source.base/src/org/netbeans/api/java/source/TreeUtilities.java
@@ -71,6 +71,7 @@ import javax.tools.JavaFileObject;
import javax.tools.SimpleJavaFileObject;
import com.sun.source.util.DocTrees;
+import com.sun.source.util.TreeScanner;
import com.sun.tools.javac.api.JavacTaskImpl;
import com.sun.tools.javac.comp.ArgumentAttr;
import com.sun.tools.javac.comp.Attr;
@@ -106,6 +107,8 @@ import org.openide.util.Exceptions;
*
* @author Jan Lahoda, Dusan Balek, Tomas Zezula
*/
+
+
public final class TreeUtilities {
/**{@link Kind}s that are represented by {@link ClassTree}.
@@ -1117,6 +1120,19 @@ public final class TreeUtilities {
return findNameSpan(cont.getLabel().toString(), cont);
}
+// /**Find span of the {@link VariablePatternTree#getBinding()} identifier in the source.
+// * Returns starting and ending offset of the name in the source code that was parsed
+// * (ie. {@link CompilationInfo.getText()}, which may differ from the positions in the source
+// * document if it has been already altered.
+// *
+// * @param var variable pattern which name should be searched for
+// * @return the span of the name, or null if cannot be found
+// * @since 0.999
+// */
+// public int[] findNameSpan(VariablePatternTree var) {
+// return findNameSpan(var.getBinding().toString(), var);
+// }
+
/**Find span of the {@link MethodTree#getParameters()} parameter list in the source.
* Returns the position of the opening and closing parentheses of the parameter list
* in the source code that was parsed (ie. {@link CompilationInfo.getText()}, which
@@ -1842,6 +1858,18 @@ public final class TreeUtilities {
return ref.paramTypes;
}
+ public List<Tree> getChildren(Tree t) {
+ final List<Tree> result = new ArrayList<>();
+ t.accept(new TreeScanner<Void, Void>() {
+ @Override
+ public Void scan(Tree tree, Void p) {
+ result.add(tree);
+ return null;
+ }
+ }, null);
+ return result;
+ }
+
private static final class NBScope implements Scope {
private final JavacScope delegate;
diff --git a/java.source.base/src/org/netbeans/modules/java/source/builder/TreeFactory.java b/java.source.base/src/org/netbeans/modules/java/source/builder/TreeFactory.java
index 360e5a1..5598c1b 100644
--- a/java.source.base/src/org/netbeans/modules/java/source/builder/TreeFactory.java
+++ b/java.source.base/src/org/netbeans/modules/java/source/builder/TreeFactory.java
@@ -68,10 +68,13 @@ import com.sun.tools.javac.util.ListBuffer;
import com.sun.tools.javac.util.Name;
import com.sun.tools.javac.util.Names;
import com.sun.tools.javac.util.Context;
+import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Set;
+import java.util.logging.Level;
+import java.util.logging.Logger;
import javax.lang.model.element.*;
import javax.lang.model.type.ArrayType;
import javax.lang.model.type.TypeKind;
@@ -1845,4 +1848,17 @@ public class TreeFactory {
}
return docMake.at(NOPOS).newReferenceTree("", (JCExpression) qualExpr, member != null ? (Name) names.fromString(member.toString()) : null, paramTypesList);
}
+
+ public <R extends Tree> R createReflective(String factoryName, Class<R> apiType, Object... params) {
+ for (java.lang.reflect.Method m : make.getClass().getMethods()) {
+ if (m.getName().equals(factoryName) && m.isAccessible() && m.getParameterTypes().length == params.length) {
+ try {
+ return apiType.cast(m.invoke(make.at(NOPOS), params));
+ } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException ex) {
+ Logger.getLogger(TreeFactory.class.getName()).log(Level.FINE, null, ex);
+ }
+ }
+ }
+ throw new UnsupportedOperationException("Cannot find factory: " + factoryName);
+ }
}
diff --git a/spi.java.hints/src/org/netbeans/modules/java/hints/spiimpl/JackpotTrees.java b/spi.java.hints/src/org/netbeans/modules/java/hints/spiimpl/JackpotTrees.java
index 453f390..d215544 100644
--- a/spi.java.hints/src/org/netbeans/modules/java/hints/spiimpl/JackpotTrees.java
+++ b/spi.java.hints/src/org/netbeans/modules/java/hints/spiimpl/JackpotTrees.java
@@ -182,6 +182,7 @@ public class JackpotTrees {
private final JCIdent jcIdent;
public CaseWildcard(Context ctx, Name ident, JCIdent jcIdent) {
+// super(new JCConstantPattern(jcIdent) {}, List.<JCStatement>nil());
super(jcIdent, List.<JCStatement>nil());
this.ident = ident;
this.jcIdent = jcIdent;
diff --git a/spi.java.hints/src/org/netbeans/modules/java/hints/spiimpl/Utilities.java b/spi.java.hints/src/org/netbeans/modules/java/hints/spiimpl/Utilities.java
index 5962f8c..0f0f031 100644
--- a/spi.java.hints/src/org/netbeans/modules/java/hints/spiimpl/Utilities.java
+++ b/spi.java.hints/src/org/netbeans/modules/java/hints/spiimpl/Utilities.java
@@ -162,6 +162,7 @@ import org.netbeans.spi.editor.hints.Severity;
import org.netbeans.spi.java.classpath.support.ClassPathSupport;
import org.openide.filesystems.FileObject;
import org.openide.filesystems.FileUtil;
+import org.openide.util.Exceptions;
import org.openide.util.Lookup;
import org.openide.util.NbCollections;
import org.openide.util.WeakListeners;
@@ -1394,7 +1395,7 @@ public class Utilities {
@Override
protected JCCase switchBlockStatementGroup() {
- if (token.kind == TokenKind.CASE) {
+ if (token.kind == TokenKind.CASE && /*XXX: patterns*/!hasPatterns()) {
Token peeked = S.token(1);
if (peeked.kind == TokenKind.IDENTIFIER) {
@@ -1420,6 +1421,14 @@ public class Utilities {
return super.switchBlockStatementGroup();
}
+ private boolean hasPatterns() {
+ try {
+ Class.forName("com.sun.source.tree.ConstantPatternTree");
+ return true;
+ } catch (ClassNotFoundException ex) {
+ return false;
+ }
+ }
@Override
protected JCTree resource() {
--
To stop receiving notification emails like this one, please contact
"commits@netbeans.apache.org" <co...@netbeans.apache.org>.