Support for multivariables MatcherUtilities.matches and in the declarative matches conditions
1.1 --- a/api/src/org/netbeans/modules/jackpot30/impl/Utilities.java Thu Apr 28 20:13:39 2011 +0200
1.2 +++ b/api/src/org/netbeans/modules/jackpot30/impl/Utilities.java Thu Apr 28 20:13:39 2011 +0200
1.3 @@ -1447,6 +1447,46 @@
1.4 return false;
1.5 }
1.6
1.7 + public static boolean isFakeBlock(Tree t) {
1.8 + if (!(t instanceof BlockTree)) {
1.9 + return false;
1.10 + }
1.11 +
1.12 + BlockTree bt = (BlockTree) t;
1.13 +
1.14 + if (bt.getStatements().isEmpty()) {
1.15 + return false;
1.16 + }
1.17 +
1.18 + CharSequence wildcardTreeName = Utilities.getWildcardTreeName(bt.getStatements().get(0));
1.19 +
1.20 + if (wildcardTreeName == null) {
1.21 + return false;
1.22 + }
1.23 +
1.24 + return wildcardTreeName.toString().startsWith("$$");
1.25 + }
1.26 +
1.27 + public static boolean isFakeClass(Tree t) {
1.28 + if (!(t instanceof ClassTree)) {
1.29 + return false;
1.30 + }
1.31 +
1.32 + ClassTree ct = (ClassTree) t;
1.33 +
1.34 + if (ct.getMembers().isEmpty()) {
1.35 + return false;
1.36 + }
1.37 +
1.38 + CharSequence wildcardTreeName = Utilities.getWildcardTreeName(ct.getMembers().get(0));
1.39 +
1.40 + if (wildcardTreeName == null) {
1.41 + return false;
1.42 + }
1.43 +
1.44 + return wildcardTreeName.toString().startsWith("$$");
1.45 + }
1.46 +
1.47 private static final class DiagnosticListenerImpl implements DiagnosticListener<JavaFileObject> {
1.48 private final Collection<Diagnostic<? extends JavaFileObject>> errors;
1.49
2.1 --- a/api/src/org/netbeans/modules/jackpot30/spi/JavaFix.java Thu Apr 28 20:13:39 2011 +0200
2.2 +++ b/api/src/org/netbeans/modules/jackpot30/spi/JavaFix.java Thu Apr 28 20:13:39 2011 +0200
2.3 @@ -208,46 +208,6 @@
2.4 return toEditorFix(new JavaFixRealImpl(info, what, options, displayName, to, params, paramsMulti, parameterNames, constraintsHandles, Arrays.asList(imports)));
2.5 }
2.6
2.7 - private static boolean isFakeBlock(Tree t) {
2.8 - if (!(t instanceof BlockTree)) {
2.9 - return false;
2.10 - }
2.11 -
2.12 - BlockTree bt = (BlockTree) t;
2.13 -
2.14 - if (bt.getStatements().isEmpty()) {
2.15 - return false;
2.16 - }
2.17 -
2.18 - CharSequence wildcardTreeName = Utilities.getWildcardTreeName(bt.getStatements().get(0));
2.19 -
2.20 - if (wildcardTreeName == null) {
2.21 - return false;
2.22 - }
2.23 -
2.24 - return wildcardTreeName.toString().startsWith("$$");
2.25 - }
2.26 -
2.27 - private static boolean isFakeClass(Tree t) {
2.28 - if (!(t instanceof ClassTree)) {
2.29 - return false;
2.30 - }
2.31 -
2.32 - ClassTree ct = (ClassTree) t;
2.33 -
2.34 - if (ct.getMembers().isEmpty()) {
2.35 - return false;
2.36 - }
2.37 -
2.38 - CharSequence wildcardTreeName = Utilities.getWildcardTreeName(ct.getMembers().get(0));
2.39 -
2.40 - if (wildcardTreeName == null) {
2.41 - return false;
2.42 - }
2.43 -
2.44 - return wildcardTreeName.toString().startsWith("$$");
2.45 - }
2.46 -
2.47 private static String defaultFixDisplayName(CompilationInfo info, Map<String, TreePath> variables, String replaceTarget) {
2.48 Map<String, String> stringsForVariables = new HashMap<String, String>();
2.49
2.50 @@ -473,7 +433,7 @@
2.51
2.52 Tree parsed = Pattern.parseAndAttribute(wc, to, constraints, new Scope[1], imports);
2.53
2.54 - if (isFakeBlock(parsed)) {
2.55 + if (Utilities.isFakeBlock(parsed)) {
2.56 TreePath parent = tp.getParentPath();
2.57 List<? extends StatementTree> statements = ((BlockTree) parsed).getStatements();
2.58
2.59 @@ -494,7 +454,7 @@
2.60 } else {
2.61 wc.rewrite(tp.getLeaf(), wc.getTreeMaker().Block(statements, false));
2.62 }
2.63 - } else if (isFakeClass(parsed)) {
2.64 + } else if (Utilities.isFakeClass(parsed)) {
2.65 TreePath parent = tp.getParentPath();
2.66 List<? extends Tree> members = ((ClassTree) parsed).getMembers();
2.67
3.1 --- a/api/src/org/netbeans/modules/jackpot30/spi/MatcherUtilities.java Thu Apr 28 20:13:39 2011 +0200
3.2 +++ b/api/src/org/netbeans/modules/jackpot30/spi/MatcherUtilities.java Thu Apr 28 20:13:39 2011 +0200
3.3 @@ -39,12 +39,16 @@
3.4
3.5 package org.netbeans.modules.jackpot30.spi;
3.6
3.7 +import com.sun.source.tree.BlockTree;
3.8 import com.sun.source.tree.Scope;
3.9 +import com.sun.source.tree.StatementTree;
3.10 import com.sun.source.tree.Tree;
3.11 import com.sun.source.util.TreePath;
3.12 import java.util.Collection;
3.13 import java.util.Collections;
3.14 import java.util.HashMap;
3.15 +import java.util.Iterator;
3.16 +import java.util.List;
3.17 import java.util.Map;
3.18 import java.util.concurrent.atomic.AtomicBoolean;
3.19 import javax.lang.model.type.TypeMirror;
3.20 @@ -62,7 +66,6 @@
3.21 return matches(ctx, variable, pattern, null, null, null);
3.22 }
3.23
3.24 - //fillInVariables is a hack to allow declarative hint debugging
3.25 public static boolean matches(@NonNull HintContext ctx, @NonNull TreePath variable, @NonNull String pattern, Map<String, TreePath> outVariables, Map<String, Collection<? extends TreePath>> outMultiVariables, Map<String, String> outVariables2Names) {
3.26 Scope s = Utilities.constructScope(ctx.getInfo(), Collections.<String, TypeMirror>emptyMap());
3.27 Tree patternTree = Utilities.parseAndAttribute(ctx.getInfo(), pattern, s);
3.28 @@ -82,6 +85,46 @@
3.29 return false;
3.30 }
3.31
3.32 + public static boolean matches(@NonNull HintContext ctx, @NonNull Collection<? extends TreePath> variable, @NonNull String pattern, Map<String, TreePath> outVariables, Map<String, Collection<? extends TreePath>> outMultiVariables, Map<String, String> outVariables2Names) {
3.33 + Scope s = Utilities.constructScope(ctx.getInfo(), Collections.<String, TypeMirror>emptyMap());
3.34 + Tree patternTree = Utilities.parseAndAttribute(ctx.getInfo(), pattern, s);
3.35 + List<? extends Tree> patternTrees;
3.36 +
3.37 + if (Utilities.isFakeBlock(patternTree)) {
3.38 + List<? extends StatementTree> statements = ((BlockTree) patternTree).getStatements();
3.39 +
3.40 + patternTrees = statements.subList(1, statements.size() - 1);
3.41 + } else {
3.42 + patternTrees = Collections.singletonList(patternTree);
3.43 + }
3.44 +
3.45 + if (variable.size() != patternTrees.size()) return false;
3.46 +
3.47 + Map<String, TreePath> variables = new HashMap<String, TreePath>(ctx.getVariables());
3.48 + Map<String, Collection<? extends TreePath>> multiVariables = new HashMap<String, Collection<? extends TreePath>>(ctx.getMultiVariables());
3.49 + Map<String, String> variables2Names = new HashMap<String, String>(ctx.getVariableNames());
3.50 + Iterator<? extends TreePath> variableIt = variable.iterator();
3.51 + Iterator<? extends Tree> patternTreesIt = patternTrees.iterator();
3.52 +
3.53 + while (variableIt.hasNext() && patternTreesIt.hasNext()) {
3.54 + TreePath patternTreePath = new TreePath(new TreePath(ctx.getInfo().getCompilationUnit()), patternTreesIt.next());
3.55 +
3.56 + if (!CopyFinder.isDuplicate(ctx.getInfo(), patternTreePath, variableIt.next(), true, variables, multiVariables, variables2Names, new AtomicBoolean()/*XXX*/)) {
3.57 + return false;
3.58 + }
3.59 + }
3.60 +
3.61 + if (variableIt.hasNext() == patternTreesIt.hasNext()) {
3.62 + outVariables(outVariables, variables, ctx.getVariables());
3.63 + outVariables(outMultiVariables, multiVariables, ctx.getMultiVariables());
3.64 + outVariables(outVariables2Names, variables2Names, ctx.getVariableNames());
3.65 +
3.66 + return true;
3.67 + }
3.68 +
3.69 + return false;
3.70 + }
3.71 +
3.72 private static <T> void outVariables(Map<String, T> outMap, Map<String, T> currentValues, Map<String, T> origValues) {
3.73 if (outMap == null) return;
3.74
4.1 --- a/api/test/unit/src/org/netbeans/modules/jackpot30/spi/MatcherUtilitiesTest.java Thu Apr 28 20:13:39 2011 +0200
4.2 +++ b/api/test/unit/src/org/netbeans/modules/jackpot30/spi/MatcherUtilitiesTest.java Thu Apr 28 20:13:39 2011 +0200
4.3 @@ -39,10 +39,13 @@
4.4
4.5 package org.netbeans.modules.jackpot30.spi;
4.6
4.7 +import com.sun.source.tree.BlockTree;
4.8 +import com.sun.source.tree.StatementTree;
4.9 import com.sun.source.tree.Tree.Kind;
4.10 import com.sun.source.util.TreePath;
4.11 import java.util.Collection;
4.12 import java.util.Collections;
4.13 +import java.util.LinkedList;
4.14 import java.util.regex.Pattern;
4.15 import org.netbeans.modules.jackpot30.impl.TestBase;
4.16
4.17 @@ -98,4 +101,24 @@
4.18 assertTrue(MatcherUtilities.matches(ctx, ctx.getPath(), "java.io.File"));
4.19 }
4.20
4.21 + public void testMatchMultivar() throws Exception {
4.22 + String code = "package test; import java.io.File; public class Test { { | int $i = 0; $i += 2; } }";
4.23 + int pos = code.indexOf("|");
4.24 +
4.25 + code = code.replaceAll(Pattern.quote("|"), "");
4.26 +
4.27 + prepareTest("test/Test.java", code);
4.28 +
4.29 + TreePath tp = info.getTreeUtilities().pathFor(pos);
4.30 + HintContext ctx = HintContext.create(info, null, tp, Collections.<String, TreePath>emptyMap(), Collections.<String, Collection<? extends TreePath>>emptyMap(), Collections.<String, String>emptyMap());
4.31 + Collection<TreePath> originals = new LinkedList<TreePath>();
4.32 +
4.33 + for (StatementTree st : ((BlockTree) tp.getLeaf()).getStatements()) {
4.34 + originals.add(new TreePath(tp, st));
4.35 + }
4.36 +
4.37 + assertTrue(MatcherUtilities.matches(ctx, originals, "int $i = 0; $i += 2;", null, null, null));
4.38 + assertFalse(MatcherUtilities.matches(ctx, originals, "int $i = 0; $i += 3;", null, null, null));
4.39 + }
4.40 +
4.41 }
4.42 \ No newline at end of file
5.1 --- a/file/src/org/netbeans/modules/jackpot30/file/conditionapi/Matcher.java Thu Apr 28 20:13:39 2011 +0200
5.2 +++ b/file/src/org/netbeans/modules/jackpot30/file/conditionapi/Matcher.java Thu Apr 28 20:13:39 2011 +0200
5.3 @@ -42,6 +42,8 @@
5.4 import com.sun.source.tree.Tree;
5.5 import com.sun.source.util.TreePath;
5.6 import com.sun.source.util.TreePathScanner;
5.7 +import java.util.Collection;
5.8 +import java.util.LinkedList;
5.9 import javax.lang.model.element.Element;
5.10 import org.netbeans.api.annotations.common.NonNull;
5.11 import org.netbeans.modules.jackpot30.spi.MatcherUtilities;
5.12 @@ -159,15 +161,18 @@
5.13 public boolean matchesWithBind(Variable var, String pattern) {
5.14 TreePath path = ctx.getSingleVariable(var);
5.15
5.16 - if (path == null) {
5.17 - return false;
5.18 + if (path != null) {
5.19 + return MatcherUtilities.matches(ctx.ctx, path, pattern, ctx.variables.get(0), ctx.multiVariables.get(0), ctx.variableNames.get(0));
5.20 }
5.21
5.22 - if (MatcherUtilities.matches(ctx.ctx, path, pattern, ctx.variables.get(0), ctx.multiVariables.get(0), ctx.variableNames.get(0))) {
5.23 - return true;
5.24 + Iterable<? extends Variable> multiVar = ctx.getIndexedVariables(var);
5.25 + Collection<TreePath> multi = new LinkedList<TreePath>();
5.26 +
5.27 + for (Variable v : multiVar) {
5.28 + multi.add(ctx.getSingleVariable(v));
5.29 }
5.30
5.31 - return false;
5.32 + return MatcherUtilities.matches(ctx.ctx, multi, pattern, ctx.variables.get(0), ctx.multiVariables.get(0), ctx.variableNames.get(0));
5.33 }
5.34
5.35 }