Support for multivariables MatcherUtilities.matches and in the declarative matches conditions
authorJan Lahoda <jlahoda@netbeans.org>
Thu, 28 Apr 2011 20:13:39 +0200
changeset 570f22a98c1c944
parent 569 e667b3883bb4
child 571 157bf9a34fa1
Support for multivariables MatcherUtilities.matches and in the declarative matches conditions
api/src/org/netbeans/modules/jackpot30/impl/Utilities.java
api/src/org/netbeans/modules/jackpot30/spi/JavaFix.java
api/src/org/netbeans/modules/jackpot30/spi/MatcherUtilities.java
api/test/unit/src/org/netbeans/modules/jackpot30/spi/MatcherUtilitiesTest.java
file/src/org/netbeans/modules/jackpot30/file/conditionapi/Matcher.java
     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  }