Too much stuff in one commit. Rename blocks now follows language semantics. Removal of more ASTPath consumers
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);