1.1 --- a/ruby/src/org/netbeans/modules/ruby/AstUtilities.java Sun Dec 08 11:39:16 2013 -0600
1.2 +++ b/ruby/src/org/netbeans/modules/ruby/AstUtilities.java Sun Dec 08 12:20:16 2013 -0600
1.3 @@ -519,6 +519,19 @@
1.4
1.5 return child == null ? null : child.getMethodFor();
1.6 }
1.7 +
1.8 + public static Node findNodeAtOffset(ParserResult info, int caretOffset) {
1.9 + Node root = AstUtilities.getRoot(info);
1.10 + if (root == null) return null;
1.11 +
1.12 + int astOffset = AstUtilities.getAstOffset(info, caretOffset);
1.13 + if (astOffset == -1) return null;
1.14 +
1.15 + Node closest = root.getNodeAt(astOffset);
1.16 + if (closest == null) return null;
1.17 +
1.18 + return closest;
1.19 + }
1.20
1.21 // FIXME: Replace this with something which returns nearest module...Do we really specifically need class?
1.22 public static ClassNode findClassAtOffset(Node root, int offset) {
2.1 --- a/ruby/src/org/netbeans/modules/ruby/RubyRenameHandler.java Sun Dec 08 11:39:16 2013 -0600
2.2 +++ b/ruby/src/org/netbeans/modules/ruby/RubyRenameHandler.java Sun Dec 08 12:20:16 2013 -0600
2.3 @@ -47,19 +47,7 @@
2.4 import java.util.HashSet;
2.5 import java.util.Set;
2.6
2.7 -import org.jrubyparser.ast.ArgsNode;
2.8 -import org.jrubyparser.ast.ArgumentNode;
2.9 -import org.jrubyparser.ast.BlockArgNode;
2.10 -import org.jrubyparser.ast.ListNode;
2.11 -import org.jrubyparser.ast.LocalAsgnNode;
2.12 -import org.jrubyparser.ast.LocalVarNode;
2.13 -import org.jrubyparser.ast.MethodDefNode;
2.14 import org.jrubyparser.ast.Node;
2.15 -import org.jrubyparser.ast.NodeType;
2.16 -import org.jrubyparser.ast.INameNode;
2.17 -import org.jrubyparser.SourcePosition;
2.18 -import org.jrubyparser.ast.AssignableNode;
2.19 -import org.jrubyparser.ast.ILocalScope;
2.20 import org.jrubyparser.ast.ILocalVariable;
2.21 import org.netbeans.modules.csl.api.InstantRenamer;
2.22 import org.netbeans.modules.csl.api.OffsetRange;
2.23 @@ -134,102 +122,22 @@
2.24
2.25 @Override
2.26 public Set<OffsetRange> getRenameRegions(ParserResult info, int caretOffset) {
2.27 - Node root = AstUtilities.getRoot(info);
2.28 - if (root == null) return Collections.emptySet();
2.29 + Node closest = AstUtilities.findNodeAtOffset(info, caretOffset);
2.30 + if (closest == null || !(closest instanceof ILocalVariable)) return Collections.emptySet();
2.31
2.32 + ILocalVariable variable = (ILocalVariable) closest;
2.33 Set<OffsetRange> regions = new HashSet<OffsetRange>();
2.34
2.35 - int astOffset = AstUtilities.getAstOffset(info, caretOffset);
2.36 - if (astOffset == -1) return Collections.emptySet();
2.37 + for (ILocalVariable occurrence: variable.getOccurrences()) {
2.38 + OffsetRange range = LexUtilities.getLexerOffsets(info,
2.39 + AstUtilities.offsetRangeFor(occurrence.getNamePosition()));
2.40
2.41 - AstPath path = new AstPath(root, astOffset);
2.42 - Node closest = path.leaf();
2.43 - if (closest == null) return Collections.emptySet();
2.44 -
2.45 - if (closest.isBlockParameter()) {
2.46 - ILocalVariable blockParameter = (ILocalVariable) closest;
2.47 -
2.48 - for (ILocalVariable occurrence: blockParameter.getOccurrences()) {
2.49 - OffsetRange range = LexUtilities.getLexerOffsets(info,
2.50 - AstUtilities.offsetRangeFor(occurrence.getLexicalNamePosition()));
2.51 -
2.52 - if (range != OffsetRange.NONE) regions.add(range);
2.53 - }
2.54 - } else if (closest instanceof LocalVarNode || closest instanceof LocalAsgnNode) {
2.55 - // A local variable read or a parameter read, or an assignment to one of these
2.56 - String name = ((INameNode)closest).getName();
2.57 - Node localScope = AstUtilities.findLocalScope(closest, path);
2.58 -
2.59 - if (localScope == null) {
2.60 - // Use parent, possibly Grand Parent if we have a newline node in the way
2.61 - localScope = path.leafParent();
2.62 -
2.63 - if (localScope.getNodeType() == NodeType.NEWLINENODE) localScope = path.leafGrandParent();
2.64 - if (localScope == null) localScope = closest;
2.65 - }
2.66 -
2.67 - addLocals(info, localScope, name, regions);
2.68 - } else if (closest.getNodeType() == NodeType.DVARNODE || closest.getNodeType() == NodeType.DASGNNODE) {
2.69 - // 1.8-style block declaration: iter { dasgn }
2.70 - String name = ((INameNode)closest).getName();
2.71 -
2.72 - for (Node block : AstUtilities.getApplicableBlocks(path, true)) {
2.73 - addDynamicVars(info, block, name, regions);
2.74 - }
2.75 - } else if (closest.getNodeType() == NodeType.ARGUMENTNODE || closest.getNodeType() == NodeType.BLOCKARGNODE) {
2.76 - // A method name (if under a DefnNode or DefsNode) or a parameter (if indirectly under an ArgsNode)
2.77 - String name = ((INameNode)closest).getName();
2.78 -
2.79 - Node parent = path.leafParent();
2.80 -
2.81 - if (parent != null) {
2.82 - // Make sure it's a parameter, not a method
2.83 - if (!(parent instanceof MethodDefNode)) {
2.84 - // Parameter (check to see if its under ArgumentNode)
2.85 - Node method = AstUtilities.findMethodAtOffset(root, astOffset);
2.86 -
2.87 - if (method == null) method = AstUtilities.findBlock(path);
2.88 -
2.89 - if (method == null) {
2.90 - // Use parent, possibly Grand Parent if we have a newline node in the way
2.91 - method = path.leafParent();
2.92 -
2.93 - if (method.getNodeType() == NodeType.NEWLINENODE) method = path.leafGrandParent();
2.94 - if (method == null) method = closest;
2.95 - }
2.96 -
2.97 - addLocals(info, method, name, regions);
2.98 - }
2.99 - }
2.100 + if (range != OffsetRange.NONE) regions.add(range);
2.101 }
2.102
2.103 return regions;
2.104 }
2.105
2.106 - private void addLocals(ParserResult info, Node node, String name, Set<OffsetRange> ranges) {
2.107 - if (node.getNodeType() == NodeType.LOCALVARNODE) {
2.108 - if (((INameNode)node).getName().equals(name)) {
2.109 - OffsetRange range = AstUtilities.getRange(node);
2.110 - range = LexUtilities.getLexerOffsets(info, range);
2.111 - if (range != OffsetRange.NONE) ranges.add(range);
2.112 - }
2.113 - } else if (node.getNodeType() == NodeType.LOCALASGNNODE) {
2.114 - if (((INameNode)node).getName().equals(name)) {
2.115 - OffsetRange range = AstUtilities.getRange(node);
2.116 - // Adjust end offset to only include the left hand size
2.117 - range = new OffsetRange(range.getStart(), range.getStart() + name.length());
2.118 - range = LexUtilities.getLexerOffsets(info, range);
2.119 - if (range != OffsetRange.NONE) ranges.add(range);
2.120 - }
2.121 - } else if (node.getNodeType() == NodeType.ARGSNODE) {
2.122 - addArgsNode(node, name, info, ranges);
2.123 - }
2.124 -
2.125 - for (Node child : node.childNodes()) {
2.126 - addLocals(info, child, name, ranges);
2.127 - }
2.128 - }
2.129 -
2.130 // TODO: Check
2.131 // quick tip renaming
2.132 // unused detection
2.133 @@ -240,84 +148,4 @@
2.134 //
2.135 // Test both parent blocks, sibling blocks and descendant blocks
2.136 // Make sure the "isUsed" detection is smarter too.
2.137 -
2.138 - private void addDynamicVars(ParserResult info, Node node, String name, Set<OffsetRange> ranges) {
2.139 - switch (node.getNodeType()) {
2.140 - case DVARNODE:
2.141 - if (((INameNode)node).getName().equals(name)) {
2.142 - OffsetRange range = LexUtilities.getLexerOffsets(info, AstUtilities.getRange(node));
2.143 - if (range != OffsetRange.NONE) ranges.add(range);
2.144 - }
2.145 - break;
2.146 - case DASGNNODE:
2.147 - if (((INameNode)node).getName().equals(name)) {
2.148 - OffsetRange range = AstUtilities.offsetRangeFor(((AssignableNode) node).getLeftHandSidePosition());
2.149 - range = LexUtilities.getLexerOffsets(info, range);
2.150 - if (range != OffsetRange.NONE) ranges.add(range);
2.151 - }
2.152 - break;
2.153 - case ARGSNODE:
2.154 - addArgsNode(node, name, info, ranges);
2.155 - }
2.156 -
2.157 - for (Node child : node.childNodes()) {
2.158 - if (child instanceof ILocalScope || child.getNodeType() == NodeType.ITERNODE) continue;
2.159 -
2.160 - addDynamicVars(info, child, name, ranges);
2.161 - }
2.162 - }
2.163 -
2.164 - private void addArgsNode(Node node, String name, ParserResult info, Set<OffsetRange> ranges) {
2.165 - ArgsNode an = (ArgsNode)node;
2.166 -
2.167 - if (an.getRequiredCount() > 0) {
2.168 - for (Node arg : an.childNodes()) {
2.169 - if (!(arg instanceof ListNode)) continue;
2.170 - for (Node arg2 : arg.childNodes()) {
2.171 - if (arg2.getNodeType() == NodeType.ARGUMENTNODE) {
2.172 - if (((ArgumentNode)arg2).getName().equals(name)) {
2.173 - OffsetRange range = AstUtilities.getRange(arg2);
2.174 - range = LexUtilities.getLexerOffsets(info, range);
2.175 - if (range != OffsetRange.NONE) ranges.add(range);
2.176 - }
2.177 - } else if (arg2.getNodeType() == NodeType.LOCALASGNNODE) {
2.178 - if (((LocalAsgnNode)arg2).getName().equals(name)) {
2.179 - OffsetRange range = AstUtilities.getRange(arg2);
2.180 - // Adjust end offset to only include the left hand size
2.181 - range = new OffsetRange(range.getStart(), range.getStart() + name.length());
2.182 - range = LexUtilities.getLexerOffsets(info, range);
2.183 - if (range != OffsetRange.NONE) ranges.add(range);
2.184 - }
2.185 - }
2.186 - }
2.187 - }
2.188 - }
2.189 -
2.190 - // Rest args
2.191 - if (an.getRest() != null) {
2.192 - ArgumentNode bn = an.getRest();
2.193 -
2.194 - if (bn.getName().equals(name)) {
2.195 - SourcePosition pos = bn.getPosition();
2.196 -
2.197 - // +1: Skip "*" and "&" prefix
2.198 - OffsetRange range = new OffsetRange(pos.getStartOffset() + 1, pos.getEndOffset());
2.199 - range = LexUtilities.getLexerOffsets(info, range);
2.200 - if (range != OffsetRange.NONE) ranges.add(range);
2.201 - }
2.202 - }
2.203 -
2.204 - if (an.getBlock() != null) {
2.205 - BlockArgNode bn = an.getBlock();
2.206 -
2.207 - if (bn.getName().equals(name)) {
2.208 - SourcePosition pos = bn.getPosition();
2.209 -
2.210 - // +1: Skip "*" and "&" prefix
2.211 - OffsetRange range = new OffsetRange(pos.getStartOffset() + 1, pos.getEndOffset());
2.212 - range = LexUtilities.getLexerOffsets(info, range);
2.213 - if (range != OffsetRange.NONE) ranges.add(range);
2.214 - }
2.215 - }
2.216 - }
2.217 }