KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > netbeans > modules > ruby > RenameHandler


1 /*
2  * The contents of this file are subject to the terms of the Common Development
3  * and Distribution License (the License). You may not use this file except in
4  * compliance with the License.
5  *
6  * You can obtain a copy of the License at http://www.netbeans.org/cddl.html
7  * or http://www.netbeans.org/cddl.txt.
8  *
9  * When distributing Covered Code, include this CDDL Header Notice in each file
10  * and include the License file at http://www.netbeans.org/cddl.txt.
11  * If applicable, add the following below the CDDL Header, with the fields
12  * enclosed by brackets [] replaced by your own identifying information:
13  * "Portions Copyrighted [year] [name of copyright owner]"
14  *
15  * The Original Software is NetBeans. The Initial Developer of the Original
16  * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
17  * Microsystems, Inc. All Rights Reserved.
18  */

19 package org.netbeans.modules.ruby;
20
21 import java.util.Collections JavaDoc;
22 import java.util.HashSet JavaDoc;
23 import java.util.List JavaDoc;
24 import java.util.Set JavaDoc;
25
26 import org.jruby.ast.ArgsNode;
27 import org.jruby.ast.ArgumentNode;
28 import org.jruby.ast.DAsgnNode;
29 import org.jruby.ast.DVarNode;
30 import org.jruby.ast.DefnNode;
31 import org.jruby.ast.DefsNode;
32 import org.jruby.ast.ListNode;
33 import org.jruby.ast.LocalAsgnNode;
34 import org.jruby.ast.LocalVarNode;
35 import org.jruby.ast.NewlineNode;
36 import org.jruby.ast.Node;
37 import org.jruby.ast.types.INameNode;
38 import org.netbeans.api.gsf.InstantRenamer;
39 import org.netbeans.api.gsf.OffsetRange;
40 import org.netbeans.api.gsf.CompilationInfo;
41
42
43 /**
44  * Handle renaming of local elements
45  * @todo I should be able to rename top-level methods as well since they
46  * are private
47  *
48  * @author Tor Norbye
49  */

50 public class RenameHandler implements InstantRenamer {
51     public RenameHandler() {
52     }
53
54     public boolean isRenameAllowed(CompilationInfo info, int caretOffset) {
55         Node root = AstUtilities.getRoot(info);
56
57         if (root == null) {
58             return false;
59         }
60
61         AstPath path = new AstPath(root, caretOffset);
62         Node closest = path.leaf();
63
64         if (closest instanceof LocalVarNode || closest instanceof LocalAsgnNode ||
65                 closest instanceof DVarNode || closest instanceof DAsgnNode) {
66             return true;
67         }
68
69           if (closest instanceof ArgumentNode) {
70             Node parent = path.leafParent();
71             if (parent != null) {
72                 // Make sure it's not a method name
73
if (!(parent instanceof DefnNode || parent instanceof DefsNode)) {
74                     return true;
75                 }
76             }
77         }
78
79         return false;
80     }
81
82     public Set JavaDoc<OffsetRange> getRenameRegions(CompilationInfo info, int caretOffset) {
83         Node root = AstUtilities.getRoot(info);
84
85         if (root == null) {
86             return Collections.emptySet();
87         }
88
89         Set JavaDoc<OffsetRange> regions = new HashSet JavaDoc<OffsetRange>();
90
91         AstPath path = new AstPath(root, caretOffset);
92         Node closest = path.leaf();
93
94         if (closest instanceof LocalVarNode || closest instanceof LocalAsgnNode) {
95             // A local variable read or a parameter read, or an assignment to one of these
96
String JavaDoc name = ((INameNode)closest).getName();
97             Node method = AstUtilities.findMethod(path);
98
99             if (method == null) {
100                 method = AstUtilities.findBlock(path);
101             }
102
103             if (method == null) {
104                 // Use parent, possibly Grand Parent if we have a newline node in the way
105
method = path.leafParent();
106                 if (method instanceof NewlineNode) {
107                     method = path.leafGrandParent();
108                 }
109                 if (method == null) {
110                     method = closest;
111                 }
112             }
113
114             addLocals(method, name, regions);
115         } else if (closest instanceof DVarNode || closest instanceof DAsgnNode) {
116             // A dynamic variable read or assignment
117
String JavaDoc name = ((INameNode)closest).getName();
118             Node block = AstUtilities.findBlock(path);
119
120             if (block == null) {
121                 // Use parent
122
block = path.leafParent();
123                 if (block == null) {
124                     block = closest;
125                 }
126             }
127
128             addDynamicVars(block, name, regions);
129         } else if (closest instanceof ArgumentNode) {
130             // A method name (if under a DefnNode or DefsNode) or a parameter (if indirectly under an ArgsNode)
131
String JavaDoc name = ((ArgumentNode)closest).getName(); // ArgumentNode doesn't implement INameNode
132

133             Node parent = path.leafParent();
134             if (parent != null) {
135                 // Make sure it's a parameter, not a method
136
if (!(parent instanceof DefnNode || parent instanceof DefsNode)) {
137                     // Parameter (check to see if its under ArgumentNode)
138
Node method = AstUtilities.findMethod(path);
139
140                     if (method == null) {
141                         method = AstUtilities.findBlock(path);
142                     }
143
144                     if (method == null) {
145                         // Use parent, possibly Grand Parent if we have a newline node in the way
146
method = path.leafParent();
147                         if (method instanceof NewlineNode) {
148                             method = path.leafGrandParent();
149                         }
150                         if (method == null) {
151                             method = closest;
152                         }
153                     }
154
155                     addLocals(method, name, regions);
156                 }
157             }
158         }
159
160         return regions;
161     }
162
163     @SuppressWarnings JavaDoc("unchecked")
164     private void addLocals(Node node, String JavaDoc name, Set JavaDoc<OffsetRange> ranges) {
165         if (node instanceof LocalVarNode) {
166             if (((INameNode)node).getName().equals(name)) {
167                 OffsetRange range = AstUtilities.getRange(node);
168                 ranges.add(range);
169             }
170         } else if (node instanceof LocalAsgnNode) {
171             if (((INameNode)node).getName().equals(name)) {
172                 OffsetRange range = AstUtilities.getRange(node);
173                 // Adjust end offset to only include the left hand size
174
range = new OffsetRange(range.getStart(), range.getStart() + name.length());
175                 ranges.add(range);
176             }
177         } else if (node instanceof ArgsNode) {
178             ArgsNode an = (ArgsNode)node;
179
180             if (an.getArgsCount() > 0) {
181                 List JavaDoc<Node> args = (List JavaDoc<Node>)an.childNodes();
182
183                 for (Node arg : args) {
184                     if (arg instanceof ListNode) {
185                         List JavaDoc<Node> args2 = (List JavaDoc<Node>)arg.childNodes();
186
187                         for (Node arg2 : args2) {
188                             if (arg2 instanceof ArgumentNode) {
189                                 if (((ArgumentNode)arg2).getName().equals(name)) {
190                                     OffsetRange range = AstUtilities.getRange(arg2);
191                                     ranges.add(range);
192                                 }
193                             } else if (arg2 instanceof LocalAsgnNode) {
194                                 if (((LocalAsgnNode)arg2).getName().equals(name)) {
195                                     OffsetRange range = AstUtilities.getRange(arg2);
196                                     ranges.add(range);
197                                 }
198                             }
199                         }
200                     }
201                 }
202             }
203         }
204
205         List JavaDoc<Node> list = node.childNodes();
206
207         for (Node child : list) {
208             addLocals(child, name, ranges);
209         }
210     }
211
212     @SuppressWarnings JavaDoc("unchecked")
213     private void addDynamicVars(Node node, String JavaDoc name, Set JavaDoc<OffsetRange> ranges) {
214         if (node instanceof DVarNode) {
215             if (((INameNode)node).getName().equals(name)) {
216                 OffsetRange range = AstUtilities.getRange(node);
217                 ranges.add(range);
218             }
219         } else if (node instanceof DAsgnNode) {
220             if (((INameNode)node).getName().equals(name)) {
221                 OffsetRange range = AstUtilities.getRange(node);
222                 // TODO - AstUtility for this
223
// Adjust end offset to only include the left hand size
224
range = new OffsetRange(range.getStart(), range.getStart() + name.length());
225                 ranges.add(range);
226             }
227         }
228
229         List JavaDoc<Node> list = node.childNodes();
230
231         for (Node child : list) {
232             addDynamicVars(child, name, ranges);
233         }
234     }
235 }
236
Popular Tags