KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > armedbear > j > JavaContext


1 /*
2  * JavaContext.java
3  *
4  * Copyright (C) 2002 Peter Graves
5  * $Id: JavaContext.java,v 1.1.1.1 2002/09/24 16:09:21 piso Exp $
6  *
7  * This program is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License
9  * as published by the Free Software Foundation; either version 2
10  * of the License, or (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
20  */

21
22 package org.armedbear.j;
23
24 import gnu.regexp.RE;
25 import gnu.regexp.REMatch;
26 import gnu.regexp.UncheckedRE;
27 import java.util.ArrayList JavaDoc;
28 import java.util.List JavaDoc;
29 import java.util.Stack JavaDoc;
30
31 public final class JavaContext implements Constants
32 {
33     private static final boolean DEBUG = false;
34
35     private static final RE parameterRE =
36         new UncheckedRE("^(\\w+\\s+\\w+\\s*,?)");
37     private static final RE declarationRE =
38         new UncheckedRE("^(\\w+\\s+\\w+\\s*;|\\w+\\s+\\w+\\s*=[^=])");
39
40     // "return foo;"
41
private static final RE returnRE = new UncheckedRE("^return[ \t]");
42
43     private final Editor editor;
44     private final Stack JavaDoc stack = new Stack JavaDoc();
45
46     public JavaContext(Editor editor)
47     {
48         this.editor = editor;
49     }
50
51     public void parseContext(Position dot)
52     {
53         final List JavaDoc tags = editor.getBuffer().getTags();
54         if (tags != null) {
55             Scope scope = new Scope(new Position(editor.getBuffer().getFirstLine(), 0));
56             stack.push(scope);
57             // BUG! We should only consider the current top-level class (and
58
// its inner classes if any), not all the tags in the file.
59
final int size = tags.size();
60             for (int i = 0; i < size; i++) {
61                 JavaTag tag = (JavaTag) tags.get(i);
62                 if (tag.getType() == TAG_FIELD)
63                     scope.addField(tag.getSignature());
64             }
65         }
66         Position pos = findStartOfMethod(dot);
67         if (pos != null) {
68             while (pos.next() && pos.isBefore(dot)) {
69                 char c = pos.getChar();
70                 if (c == '(') {
71                     Scope scope = new Scope(pos);
72                     stack.push(scope);
73                     scope.parseParameters();
74                     continue;
75                 }
76                 if (c == '{') {
77                     Scope scope = new Scope(pos);
78                     stack.push(scope);
79                     scope.parse(dot);
80                     break;
81                 }
82             }
83         }
84     }
85
86     public JavaVariable findDeclaration(String JavaDoc name)
87     {
88         if (DEBUG)
89             Log.debug("findDeclaration name = |" + name + "|");
90         if (name == null)
91             return null;
92         int index = name.indexOf('.');
93         if (index >= 0) {
94             // It's a qualified name.
95
String JavaDoc prefix = name.substring(0, index);
96             // We only handle things like "this.foo".
97
if (!prefix.equals("this"))
98                 return null;
99             // It's a member of the current class.
100
name = name.substring(index+1);
101             if (stack.size() > 0) {
102                 Scope scope = (Scope) stack.get(0);
103                 for (int j = 0; j < scope.list.size(); j++) {
104                     JavaVariable var = scope.getVariable(j);
105                     if (name.equals(var.getName()))
106                         return var;
107                 }
108             }
109             return null;
110         }
111         // It's a simple name. A local variable hides a class member with the
112
// same name.
113
for (int i = stack.size()-1; i >= 0; i--) {
114             Scope scope = (Scope) stack.get(i);
115             for (int j = 0; j < scope.list.size(); j++) {
116                 JavaVariable var = scope.getVariable(j);
117                 if (name.equals(var.getName()))
118                     return var;
119             }
120         }
121         return null;
122     }
123
124     private Position findStartOfMethod(Position dot)
125     {
126         if (dot != null) {
127             final List JavaDoc tags = editor.getBuffer().getTags();
128             if (tags != null) {
129                 JavaTag tag = null;
130                 // Find the last tag before dot.
131
final int target = dot.lineNumber();
132                 final int limit = tags.size();
133                 for (int i = 0; i < limit; i++) {
134                     JavaTag nextTag = (JavaTag) tags.get(i);
135                     if (nextTag.lineNumber() > target)
136                         break;
137                     else
138                         tag = nextTag;
139                 }
140                 if (tag != null && tag.getType() == TAG_METHOD)
141                     return tag.getPosition().copy();
142             }
143         }
144         return null;
145     }
146
147     private final class Scope
148     {
149         final ArrayList JavaDoc list = new ArrayList JavaDoc();
150
151         final Position start;
152         final Position pos;
153
154         Scope(Position pos)
155         {
156             this.pos = pos;
157             start = pos.copy();
158         }
159
160         void parse(Position dot)
161         {
162             // Skip initial '{'.
163
if (pos.getChar() == '{') {
164                 if (!pos.next())
165                     return;
166             }
167             while (pos.isBefore(dot)) {
168                 char c = pos.getChar();
169                 if (c == '\'' || c == '"') {
170                     pos.skipQuote();
171                     continue;
172                 }
173                 if (c == '/' && pos.lookingAt("//")) {
174                     Line next = pos.getNextLine();
175                     if (next != null) {
176                         pos.moveTo(next, 0);
177                         continue;
178                     } else
179                         break;
180                 }
181                 if (c == '{') {
182                     Scope scope = new Scope(pos);
183                     stack.push(scope);
184                     scope.parse(dot);
185                 } else if (c == '}') {
186                     stack.pop();
187                     return;
188                 } else {
189                     final String JavaDoc text = pos.getLine().substring(pos.getOffset());
190                     final REMatch match = declarationRE.getMatch(text);
191                     if (match != null) {
192                         String JavaDoc s = match.toString();
193                         if (returnRE.getMatch(s) != null) {
194                             if (DEBUG)
195                                 Log.debug("skipping |" + s + "|");
196                         } else
197                             addLocalVariable(s);
198                         pos.skip(s.length());
199                         continue;
200                     }
201                 }
202                 if (!pos.next())
203                     return;
204             }
205         }
206
207         void parseParameters()
208         {
209             if (pos.getChar() == '(') {
210                 if (!pos.next())
211                     return;
212             }
213             FastStringBuffer sb = new FastStringBuffer();
214             while (!pos.atEnd()) {
215                 char c = pos.getChar();
216                 if (c == '\'' || c == '"') {
217                     pos.skipQuote();
218                     continue;
219                 }
220                 if (c == '/') {
221                     if (pos.lookingAt("//")) {
222                         Line next = pos.getNextLine();
223                         if (next != null) {
224                             pos.moveTo(next, 0);
225                             continue;
226                         } else
227                             break;
228                     }
229                     if (pos.lookingAt("/*")) {
230                         pos.skip(2);
231                         while (!pos.lookingAt("*/")) {
232                             if (!pos.next())
233                                 return;
234                         }
235                         pos.skip(2);
236                         continue;
237                     }
238                 }
239                 if (c == ')')
240                     break;
241                 // Default.
242
sb.append(c);
243                 if (!pos.next())
244                     break;
245             }
246             String JavaDoc parameters = sb.toString();
247             while (true) {
248                 if (DEBUG)
249                     Log.debug("parameters = |" + parameters + "|");
250                 REMatch match = parameterRE.getMatch(parameters);
251                 if (match != null) {
252                     String JavaDoc s = match.toString();
253                     addParameter(s);
254                     parameters = parameters.substring(s.length()).trim();
255                 } else
256                     break;
257             }
258         }
259
260         void addField(String JavaDoc signature)
261         {
262             int index = signature.indexOf('=');
263             if (index >= 0)
264                 signature = signature.substring(0, index);
265             list.add(new JavaVariable(signature, JavaVariable.FIELD));
266         }
267
268         void addParameter(String JavaDoc s)
269         {
270             list.add(new JavaVariable(s, JavaVariable.PARAMETER));
271         }
272
273         void addLocalVariable(String JavaDoc s)
274         {
275             list.add(new JavaVariable(s, JavaVariable.LOCAL));
276         }
277
278         JavaVariable getVariable(int index)
279         {
280             return (JavaVariable) list.get(index);
281         }
282
283         int getVariableCount()
284         {
285             return list.size();
286         }
287
288         // For debugging.
289
void dump()
290         {
291             Log.debug("scope at " + start);
292             for (int i = 0; i < list.size(); i++)
293                 Log.debug(((JavaVariable)list.get(i)).getName());
294         }
295     }
296
297     // For debugging.
298
public static void context()
299     {
300         final Editor editor = Editor.currentEditor();
301         JavaContext context = new JavaContext(editor);
302         context.parseContext(editor.getDot());
303         Log.debug("--- context at " + editor.getDot() + " ---");
304         context.dump();
305     }
306
307     // For debugging.
308
private void dump()
309     {
310         for (int i = 0; i < stack.size(); i++)
311             ((Scope)stack.get(i)).dump();
312     }
313 }
314
Popular Tags