Too much stuff in one commit. Rename blocks now follows language semantics. Removal of more ASTPath consumers
authorenebo@netbeans.org
Sun, 08 Dec 2013 11:39:16 -0600
changeset 455407958c1ff402
parent 4553 32cac83e9ae7
child 4555 3773928e70d0
Too much stuff in one commit. Rename blocks now follows language semantics. Removal of more ASTPath consumers
ruby/src/org/netbeans/modules/ruby/AstUtilities.java
ruby/src/org/netbeans/modules/ruby/RubyDeclarationFinder.java
ruby/src/org/netbeans/modules/ruby/RubyParseResult.java
ruby/src/org/netbeans/modules/ruby/RubyParser.java
ruby/src/org/netbeans/modules/ruby/RubyRenameHandler.java
ruby/test/unit/data/testfiles/nestedblocks.rb.testRename7.rename
ruby/test/unit/src/org/netbeans/modules/ruby/AstUtilitiesTest.java
ruby/test/unit/src/org/netbeans/modules/ruby/RubyParserTest.java
ruby/test/unit/src/org/netbeans/modules/ruby/RubyTypeAnalyzerTest.java
     1.1 --- a/ruby/src/org/netbeans/modules/ruby/AstUtilities.java	Sun Nov 24 15:46:13 2013 -0600
     1.2 +++ b/ruby/src/org/netbeans/modules/ruby/AstUtilities.java	Sun Dec 08 11:39:16 2013 -0600
     1.3 @@ -1707,19 +1707,33 @@
     1.4          }
     1.5      }
     1.6      
     1.7 +    public static List<Node> getOutermostToInnerMostBlocks(Node leaf) {
     1.8 +        Node scope = leaf.getInnermostIter();
     1.9 +        
    1.10 +        if (scope == null) return Collections.emptyList();
    1.11 +        
    1.12 +        List<Node> result = new ArrayList<Node>();
    1.13 +        while (scope != null) {
    1.14 +            result.add(scope);
    1.15 +            
    1.16 +            scope = scope.getInnermostIter();
    1.17 +        }
    1.18 +        
    1.19 +        Collections.reverse(result);
    1.20 +        
    1.21 +        return result;
    1.22 +    }
    1.23 +    
    1.24      /** Return all the blocknodes that apply to the given node. The outermost block
    1.25       * is returned first.
    1.26       */
    1.27      public static List<Node> getApplicableBlocks(AstPath path, boolean includeNested) {
    1.28          Node block = AstUtilities.findBlock(path);
    1.29  
    1.30 -        if (block == null) {
    1.31 -            // Use parent
    1.32 +        if (block == null) { // Use parent
    1.33              block = path.leafParent();
    1.34  
    1.35 -            if (block == null) {
    1.36 -                return Collections.emptyList();
    1.37 -            }
    1.38 +            if (block == null) return Collections.emptyList();
    1.39          }
    1.40          
    1.41          List<Node> result = new ArrayList<Node>();
    1.42 @@ -1727,37 +1741,34 @@
    1.43          
    1.44          // Skip the leaf node, we're going to add it unconditionally afterwards
    1.45          if (includeNested) {
    1.46 -            if (it.hasNext()) {
    1.47 -                it.next();
    1.48 -            }
    1.49 +            if (it.hasNext()) it.next();
    1.50          }
    1.51  
    1.52          Node leaf = path.root();
    1.53  
    1.54 -      while_loop:
    1.55 +        while_loop:
    1.56          while (it.hasNext()) {
    1.57              Node n = it.next();
    1.58              switch (n.getNodeType()) {
    1.59 -            //case BLOCKNODE:
    1.60 -            case ITERNODE:
    1.61 -                leaf = n;
    1.62 -                result.add(n);
    1.63 -                break;
    1.64 -            case DEFNNODE:
    1.65 -            case DEFSNODE:
    1.66 -            case CLASSNODE:
    1.67 -            case SCLASSNODE:
    1.68 -            case MODULENODE:
    1.69 -                leaf = n;
    1.70 -                break while_loop;
    1.71 +                case ITERNODE:
    1.72 +                    leaf = n;
    1.73 +                    result.add(n);
    1.74 +                    break;
    1.75 +                case DEFNNODE:
    1.76 +                case DEFSNODE:
    1.77 +                case CLASSNODE:
    1.78 +                case SCLASSNODE:
    1.79 +                case MODULENODE:
    1.80 +                    leaf = n;
    1.81 +                    break while_loop;
    1.82              }
    1.83          }
    1.84  
    1.85          if (includeNested) {
    1.86 -            addNodesByType(leaf, new NodeType[] { /*NodeType.BLOCKNODE,*/ NodeType.ITERNODE }, result);
    1.87 +            addNodesByType(leaf, new NodeType[] { NodeType.ITERNODE }, result);
    1.88          }
    1.89          
    1.90 -        return result;
    1.91 +      return result;
    1.92      }
    1.93      
    1.94      public static String guessName(Parser.Result result, OffsetRange lexRange, OffsetRange astRange) {
     2.1 --- a/ruby/src/org/netbeans/modules/ruby/RubyDeclarationFinder.java	Sun Nov 24 15:46:13 2013 -0600
     2.2 +++ b/ruby/src/org/netbeans/modules/ruby/RubyDeclarationFinder.java	Sun Dec 08 11:39:16 2013 -0600
     2.3 @@ -82,6 +82,8 @@
     2.4  import org.jrubyparser.ast.SymbolNode;
     2.5  import org.jrubyparser.ast.VCallNode;
     2.6  import org.jrubyparser.ast.INameNode;
     2.7 +import org.jrubyparser.ast.IParameterScope;
     2.8 +import org.jrubyparser.ast.IterNode;
     2.9  import org.jrubyparser.ast.NodeType;
    2.10  import org.jrubyparser.ast.SuperNode;
    2.11  import org.jrubyparser.ast.ZSuperNode;
    2.12 @@ -378,7 +380,7 @@
    2.13                          }
    2.14  
    2.15                          AstPath path = new AstPath(root, astOffset);
    2.16 -                        Node closest = path.leaf();
    2.17 +                        Node closest = AstUtilities.findNodeAtOffset(root, astOffset);
    2.18                          if (closest == null) return;
    2.19  
    2.20                          // See if the hyperlink is over a method reference in an rdoc comment
    2.21 @@ -404,23 +406,18 @@
    2.22                                  closest instanceof CallNode) {
    2.23                              // A method call
    2.24                              String name = ((INameNode)closest).getName();
    2.25 -
    2.26                              Call call = Call.getCallType(doc, th, lexOffset);
    2.27 -
    2.28                              RubyType type = call.getType();
    2.29                              String lhs = call.getLhs();
    2.30  
    2.31                              if (!type.isKnown() && lhs != null && call.isSimpleIdentifier()) {
    2.32                                  Node method = AstUtilities.findLocalScope(closest, path);
    2.33  
    2.34 -                                if (method != null) {
    2.35 -                                    // TODO - if the lhs is "foo.bar." I need to split this
    2.36 -                                    // up and do it a bit more cleverly
    2.37 -                                    ContextKnowledge knowledge = new ContextKnowledge(
    2.38 -                                            index, root, method, astOffset, lexOffset, parserResult);
    2.39 -                                    RubyTypeInferencer inferencer = RubyTypeInferencer.create(knowledge);
    2.40 -                                    type = inferencer.inferType(lhs);
    2.41 -                                }
    2.42 +                                // TODO - if the lhs is "foo.bar." I need to split this
    2.43 +                                // up and do it a bit more cleverly
    2.44 +                                ContextKnowledge knowledge = new ContextKnowledge(
    2.45 +                                        index, root, method, astOffset, lexOffset, parserResult);
    2.46 +                                type = RubyTypeInferencer.create(knowledge).inferType(lhs);
    2.47                              }
    2.48  
    2.49                              // Constructors: "new" ends up calling "initialize".
    2.50 @@ -1346,37 +1343,28 @@
    2.51      @SuppressWarnings("empty-statement")
    2.52      private DeclarationLocation findRDocMethod(ParserResult info, Document doc, int astOffset, int lexOffset,
    2.53              Node root, AstPath path, Node closest, RubyIndex index) {
    2.54 -        TokenHierarchy<Document> th = TokenHierarchy.get(doc);
    2.55 +//        TokenHierarchy<Document> th = TokenHierarchy.get(doc);
    2.56 +
    2.57          TokenSequence<?> ts = LexUtilities.getRubyTokenSequence((BaseDocument)doc, lexOffset);
    2.58 -
    2.59 -        if (ts == null) {
    2.60 -            return DeclarationLocation.NONE;
    2.61 -        }
    2.62 +        if (ts == null) return DeclarationLocation.NONE;
    2.63  
    2.64          ts.move(lexOffset);
    2.65  
    2.66 -        if (!ts.moveNext() && !ts.movePrevious()) {
    2.67 -            return DeclarationLocation.NONE;
    2.68 -        }
    2.69 +        if (!ts.moveNext() && !ts.movePrevious()) return DeclarationLocation.NONE;
    2.70  
    2.71          Token<?> token = ts.token();
    2.72 -
    2.73          TokenSequence<?> embedded = ts.embedded();
    2.74  
    2.75          if (embedded != null) {
    2.76 -            ts = embedded;
    2.77 -
    2.78              embedded.move(lexOffset);
    2.79  
    2.80 -            if (!embedded.moveNext() && !embedded.movePrevious()) {
    2.81 -                return DeclarationLocation.NONE;
    2.82 -            }
    2.83 +            if (!embedded.moveNext() && !embedded.movePrevious()) return DeclarationLocation.NONE;
    2.84  
    2.85              token = embedded.token();
    2.86          }
    2.87  
    2.88          // Is this a comment? If so, possibly do rdoc-method reference jump
    2.89 -        if ((token != null) && (token.id() == RubyCommentTokenId.COMMENT_LINK)) {
    2.90 +        if (token != null && token.id() == RubyCommentTokenId.COMMENT_LINK) {
    2.91              // TODO - use findLinkedMethod
    2.92              String method = token.text().toString();
    2.93  
    2.94 @@ -1385,20 +1373,13 @@
    2.95  
    2.96                  DeclarationLocation loc = findMethod(info, root, method, Arity.UNKNOWN);
    2.97  
    2.98 -                // It looks like "#foo" can refer not just to methods (as rdoc suggested)
    2.99 -                // but to attributes as well - in Rails' initializer.rb this is used
   2.100 -                // in a number of places.
   2.101 -                if (loc == DeclarationLocation.NONE) {
   2.102 -                    loc = findInstance(info, root, "@" + method, index);
   2.103 -                }
   2.104 -
   2.105 -                return loc;
   2.106 +                // It looks like "#foo" can refer not just to methods (as rdoc suggested) but to 
   2.107 +                // attributes as well - in Rails' initializer.rb this is used in a number of places.
   2.108 +                return loc != DeclarationLocation.NONE ? loc : findInstance(info, root, "@" + method, index);
   2.109              } else {
   2.110                  // A URL such as http://netbeans.org - try to open it in a browser!
   2.111                  try {
   2.112 -                    URL url = new URL(method);
   2.113 -
   2.114 -                    return new DeclarationLocation(url);
   2.115 +                    return new DeclarationLocation(new URL(method));
   2.116                  } catch (MalformedURLException mue) {
   2.117                      // URL is from user source... don't complain with exception dialogs etc.
   2.118                      ;
   2.119 @@ -1794,56 +1775,15 @@
   2.120  
   2.121      private DeclarationLocation findLocal(ParserResult info, Node node, String name) {
   2.122          if (node instanceof LocalAsgnNode) {
   2.123 -            if (((INameNode)node).getName().equals(name)) {
   2.124 -                return getLocation(info, node);
   2.125 -            }
   2.126 +            if (((INameNode)node).getName().equals(name)) return getLocation(info, node);
   2.127          } else if (!ignoreAlias && node instanceof AliasNode) {
   2.128              String newName = AstUtilities.getNameOrValue(((AliasNode)node).getNewName());
   2.129 -            if (name.equals(newName)) {
   2.130 -                return getLocation(info, node);
   2.131 -            }
   2.132 -        } else if (node instanceof ArgsNode) {
   2.133 -            ArgsNode an = (ArgsNode)node;
   2.134  
   2.135 -            if (an.getRequiredCount() > 0) {
   2.136 -                List<Node> args = an.childNodes();
   2.137 -
   2.138 -                for (Node arg : args) {
   2.139 -                    if (arg instanceof ListNode) {
   2.140 -                        List<Node> args2 = arg.childNodes();
   2.141 -
   2.142 -                        for (Node arg2 : args2) {
   2.143 -                            if (arg2 instanceof ArgumentNode) {
   2.144 -                                if (((ArgumentNode)arg2).getName().equals(name)) {
   2.145 -                                    return getLocation(info, arg2);
   2.146 -                                }
   2.147 -                            } else if (arg2 instanceof LocalAsgnNode) {
   2.148 -                                if (((LocalAsgnNode)arg2).getName().equals(name)) {
   2.149 -                                    return getLocation(info, arg2);
   2.150 -                                }
   2.151 -                            }
   2.152 -                        }
   2.153 -                    }
   2.154 -                }
   2.155 -            }
   2.156 -
   2.157 -            // Rest args
   2.158 -            if (an.getRest() != null) {
   2.159 -                ArgumentNode bn = an.getRest();
   2.160 -
   2.161 -                if (bn.getName().equals(name)) {
   2.162 -                    return getLocation(info, bn);
   2.163 -                }
   2.164 -            }
   2.165 -
   2.166 -            // Block args
   2.167 -            if (an.getBlock() != null) {
   2.168 -                BlockArgNode bn = an.getBlock();
   2.169 -
   2.170 -                if (bn.getName().equals(name)) {
   2.171 -                    return getLocation(info, bn);
   2.172 -                }
   2.173 -            }
   2.174 +            if (name.equals(newName)) return getLocation(info, node);
   2.175 +        } else if (node instanceof IParameterScope) {
   2.176 +            ILocalVariable parameter = ((IParameterScope) node).getParameterNamed(name);
   2.177 +            
   2.178 +            return parameter != null ? getLocation(info, (Node) parameter) : DeclarationLocation.NONE;
   2.179          }
   2.180  
   2.181          List<Node> list = node.childNodes();
     3.1 --- a/ruby/src/org/netbeans/modules/ruby/RubyParseResult.java	Sun Nov 24 15:46:13 2013 -0600
     3.2 +++ b/ruby/src/org/netbeans/modules/ruby/RubyParseResult.java	Sun Dec 08 11:39:16 2013 -0600
     3.3 @@ -57,7 +57,6 @@
     3.4   */
     3.5  public class RubyParseResult extends org.netbeans.modules.csl.spi.ParserResult {
     3.6      
     3.7 -    private final RubyParser parser;
     3.8      private final Node rootNode;
     3.9      
    3.10      private String source;
    3.11 @@ -69,9 +68,8 @@
    3.12      private boolean commentsAdded;
    3.13      private List<Error> errors;
    3.14  
    3.15 -    public RubyParseResult(RubyParser parser, Snapshot snapshot, Node rootNode) {
    3.16 +    public RubyParseResult(Snapshot snapshot, Node rootNode) {
    3.17          super(snapshot);
    3.18 -        this.parser = parser;
    3.19          this.rootNode = rootNode;
    3.20          this.errors = new ArrayList<Error>();
    3.21      }
    3.22 @@ -90,15 +88,6 @@
    3.23          this.errors = new ArrayList<Error>(errors);
    3.24      }
    3.25  
    3.26 -    // XXX: CSL rewrite
    3.27 -//    public ParserResult.AstTreeNode getAst() {
    3.28 -//        return ast;
    3.29 -//    }
    3.30 -//
    3.31 -//    public void setAst(AstTreeNode ast) {
    3.32 -//        this.ast = ast;
    3.33 -//    }
    3.34 -
    3.35      /** The root node of the AST produced by the parser.
    3.36       * Later, rip out the getAst part etc.
    3.37       */
     4.1 --- a/ruby/src/org/netbeans/modules/ruby/RubyParser.java	Sun Nov 24 15:46:13 2013 -0600
     4.2 +++ b/ruby/src/org/netbeans/modules/ruby/RubyParser.java	Sun Dec 08 11:39:16 2013 -0600
     4.3 @@ -663,7 +663,7 @@
     4.4      }
     4.5  
     4.6      protected RubyParseResult createParseResult(Snapshot snapshots, Node rootNode) {
     4.7 -        return new RubyParseResult(this, snapshots, rootNode);
     4.8 +        return new RubyParseResult(snapshots, rootNode);
     4.9      }
    4.10      
    4.11      public static RubyElement resolveHandle(org.netbeans.modules.csl.spi.ParserResult info, ElementHandle handle) {
     5.1 --- a/ruby/src/org/netbeans/modules/ruby/RubyRenameHandler.java	Sun Nov 24 15:46:13 2013 -0600
     5.2 +++ b/ruby/src/org/netbeans/modules/ruby/RubyRenameHandler.java	Sun Dec 08 11:39:16 2013 -0600
     5.3 @@ -147,11 +147,14 @@
     5.4          if (closest == null) return Collections.emptySet();
     5.5  
     5.6          if (closest.isBlockParameter()) {
     5.7 -            String name = ((INameNode) closest).getName();
     5.8 +            ILocalVariable blockParameter = (ILocalVariable) closest;
     5.9              
    5.10 -            for (Node block : AstUtilities.getApplicableBlocks(path, true)) {
    5.11 -                addDynamicVars(info, block, name, regions);
    5.12 -            }            
    5.13 +            for (ILocalVariable occurrence: blockParameter.getOccurrences()) {
    5.14 +                OffsetRange range = LexUtilities.getLexerOffsets(info, 
    5.15 +                        AstUtilities.offsetRangeFor(occurrence.getLexicalNamePosition()));
    5.16 +                
    5.17 +                if (range != OffsetRange.NONE) regions.add(range);
    5.18 +            }         
    5.19          } else if (closest instanceof LocalVarNode || closest instanceof LocalAsgnNode) {
    5.20              // A local variable read or a parameter read, or an assignment to one of these
    5.21              String name = ((INameNode)closest).getName();
     6.1 --- a/ruby/test/unit/data/testfiles/nestedblocks.rb.testRename7.rename	Sun Nov 24 15:46:13 2013 -0600
     6.2 +++ b/ruby/test/unit/data/testfiles/nestedblocks.rb.testRename7.rename	Sun Dec 08 11:39:16 2013 -0600
     6.3 @@ -1,4 +1,2 @@
     6.4 -1: [1,2,3].each { ||>outer<||
     6.5 -2:   puts |>outer<|
     6.6  3:   [4,5,6].each { ||>outer<||
     6.7  4:      puts |>outer<|
     7.1 --- a/ruby/test/unit/src/org/netbeans/modules/ruby/AstUtilitiesTest.java	Sun Nov 24 15:46:13 2013 -0600
     7.2 +++ b/ruby/test/unit/src/org/netbeans/modules/ruby/AstUtilitiesTest.java	Sun Dec 08 11:39:16 2013 -0600
     7.3 @@ -524,9 +524,7 @@
     7.4          Parser.Result parserResult = getParserResult("testfiles/ape.rb");
     7.5          String text = getText(parserResult);
     7.6          int caretOffset = getCaretOffset(text, "might_^fail(uri, requested_e_coll, requested_m_coll)");
     7.7 -        Node root = AstUtilities.getRoot(parserResult);
     7.8 -        AstPath path = new AstPath(root, caretOffset);
     7.9 -        Node call = path.leaf();
    7.10 +        Node call = AstUtilities.getRoot(parserResult).getNodeAt(caretOffset);
    7.11          assertTrue(AstUtilities.isCall(call));
    7.12  
    7.13          caretOffset = getCaretOffset(text, "might_fail(^uri, requested_e_coll, requested_m_coll)");
    7.14 @@ -557,9 +555,7 @@
    7.15          //int caretOffset = 2755; // "new" call from failed earlier test
    7.16          int caretOffset = getCaretOffset(text, "MUTEX = Mutex.^new");
    7.17  
    7.18 -        Node root = AstUtilities.getRoot(parserResult);
    7.19 -        AstPath path = new AstPath(root, caretOffset);
    7.20 -        Node call = path.leaf();
    7.21 +        Node call = AstUtilities.getRoot(parserResult).getNodeAt(caretOffset);
    7.22          assertTrue(AstUtilities.isCall(call));
    7.23  
    7.24          assertEquals(-1, AstUtilities.findArgumentIndex(call, caretOffset));
    7.25 @@ -571,10 +567,7 @@
    7.26          String text = getText(parserResult);
    7.27          //int caretOffset = 2755; // "new" call from failed earlier test
    7.28          int caretOffset = getCaretOffset(text, "Gem.ac^tivate(gem_name, *version_requirements)");
    7.29 -
    7.30 -        Node root = AstUtilities.getRoot(parserResult);
    7.31 -        AstPath path = new AstPath(root, caretOffset);
    7.32 -        Node call = path.leaf();
    7.33 +        Node call = AstUtilities.getRoot(parserResult).getNodeAt(caretOffset);        
    7.34          assertTrue(AstUtilities.isCall(call));
    7.35  
    7.36          caretOffset = getCaretOffset(text, "Gem.^activate(gem_name, *version_requirements)");
     8.1 --- a/ruby/test/unit/src/org/netbeans/modules/ruby/RubyParserTest.java	Sun Nov 24 15:46:13 2013 -0600
     8.2 +++ b/ruby/test/unit/src/org/netbeans/modules/ruby/RubyParserTest.java	Sun Dec 08 11:39:16 2013 -0600
     8.3 @@ -103,8 +103,7 @@
     8.4                      } else {
     8.5                          adjustedOffset = caretOffset;
     8.6                      }
     8.7 -                    AstPath path = new AstPath(root, adjustedOffset);
     8.8 -                    Node closest = path.leaf();
     8.9 +                    Node closest = root.getNodeAt(adjustedOffset);
    8.10                      assertNotNull(closest);
    8.11                      String leafName = closest.getClass().getName();
    8.12                      leafName = leafName.substring(leafName.lastIndexOf('.') + 1);
     9.1 --- a/ruby/test/unit/src/org/netbeans/modules/ruby/RubyTypeAnalyzerTest.java	Sun Nov 24 15:46:13 2013 -0600
     9.2 +++ b/ruby/test/unit/src/org/netbeans/modules/ruby/RubyTypeAnalyzerTest.java	Sun Dec 08 11:39:16 2013 -0600
     9.3 @@ -82,13 +82,11 @@
     9.4              enforceCaretOffset(source, caretOffset);
     9.5          }
     9.6  
     9.7 -        BaseDocument doc = getDocument(fo);
     9.8          ParserResult parserResult = getParserResult(fo);
     9.9          Node root = AstUtilities.getRoot(parserResult);
    9.10          initializeRegistry();
    9.11          RubyIndex index = RubyIndex.get(parserResult);
    9.12 -        AstPath path = new AstPath(root, caretOffset);
    9.13 -        Node node = path.leaf();
    9.14 +        Node node = root.getNodeAt(caretOffset);
    9.15  
    9.16          if (findMethod) {
    9.17              MethodDefNode method = AstUtilities.findMethodAtOffset(root, caretOffset);