KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > netbeans > modules > languages > javascript > Semantic


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
20 package org.netbeans.modules.languages.javascript;
21
22 import java.util.HashMap JavaDoc;
23 import java.util.LinkedList JavaDoc;
24 import java.util.WeakHashMap JavaDoc;
25 import javax.swing.text.Document JavaDoc;
26 import org.netbeans.api.languages.ASTItem;
27 import org.netbeans.api.languages.ASTNode;
28 import org.netbeans.api.languages.SyntaxContext;
29 import org.netbeans.api.languages.ASTToken;
30 import java.util.ArrayList JavaDoc;
31 import java.util.Iterator JavaDoc;
32 import java.util.List JavaDoc;
33 import java.util.Map JavaDoc;
34 import org.netbeans.modules.editor.NbEditorUtilities;
35 import org.openide.filesystems.FileObject;
36 import org.openide.loaders.DataObject;
37
38
39 /**
40  *
41  * @author Daniel Prusa
42  */

43 public class Semantic {
44     
45     // [PENDING] change array to hashmap
46
private static String JavaDoc[] BLOCK_NAMES = {"Block", "IfStatement", "SwitchStatement", // NOI18N
47
"DoStatement", "WhileStatement", "ForStatement", "TryStatement"}; // NOI18N
48

49     private static Map JavaDoc docsToInfos = new WeakHashMap JavaDoc(); // Document -> Semantic.Info
50

51     public static synchronized void storeInfo(Document JavaDoc doc, Info info) {
52         docsToInfos.put(doc, info);
53     }
54     
55     public static synchronized Info getInfo(Document JavaDoc doc) {
56         return (Info)docsToInfos.get(doc);
57     }
58     
59     public static ASTNode process (SyntaxContext cookie) {
60         ASTNode node = (ASTNode) cookie.getASTPath ().getRoot ();
61         ASTContext context = new ASTContext(cookie.getDocument());
62         Info info = new Info();
63         
64         preprocessTree(node, context, info);
65         processTree(node, context, info);
66         storeInfo(cookie.getDocument(), info);
67         
68         return node;
69     }
70     
71     private static void preprocessTree(ASTNode node, ASTContext context, Info info) {
72         for (Iterator JavaDoc iter = node.getChildren().iterator(); iter.hasNext();) {
73             Object JavaDoc obj = iter.next();
74             if (!(obj instanceof ASTNode)) {
75                 continue;
76             }
77             ASTNode n = (ASTNode)obj;
78             String JavaDoc nt = n.getNT();
79             if ("FunctionDeclaration".equals(nt)) { // NOI18N
80
ASTNode fnode = findNode(n, "FunctionName", 0);
81                 if (fnode == null) {
82                     continue;
83                 }
84                 ASTItem item = fnode.getChildren().get(0);
85                 if (item instanceof ASTToken) {
86                     String JavaDoc name = ((ASTToken)item).getIdentifier();
87                     Declaration decl = new Declaration(context.getFileObject(), context.getDocument(), item,
88                         Declaration.METHOD);
89                     context.addMethod(name, decl);
90                     info.putItem(item, decl);
91                 }
92             } else {
93                 preprocessTree(n, context, info);
94             }
95         } // for
96
}
97     
98     private static void processTree(ASTNode node, ASTContext context, Info info) {
99         context.startBlock();
100         for (Iterator JavaDoc iter = node.getChildren().iterator(); iter.hasNext();) {
101             Object JavaDoc obj = iter.next();
102             if (!(obj instanceof ASTNode)) {
103                 continue;
104             }
105             ASTNode n = (ASTNode)obj;
106             String JavaDoc nt = n.getNT();
107             if ("FunctionDeclaration".equals(nt)) { // NOI18N
108
processFunction(n, node, context, info);
109             } else {
110                 processTree(n, context, info);
111             }
112         } // for
113
context.endBlock();
114     }
115     
116     private static void processFunction(ASTNode node, ASTNode parent, ASTContext context, Info info) {
117         context.startBlock();
118         ASTNode paramsNode = findNode(node, "FormalParameterList", 2); // NOI18N
119
if (paramsNode != null) {
120             Iterator JavaDoc iter = paramsNode.getChildren().iterator();
121             while (iter.hasNext()) {
122                 ASTToken token = (ASTToken)iter.next();
123                 if ("js_identifier".equals(token.getType())) {
124                     String JavaDoc paramName = token.getIdentifier();
125                     Declaration decl = new Declaration(context.getFileObject(), context.getDocument(), token,
126                             Declaration.PARAMETER);
127                     context.addParameter(paramName, decl);
128                     info.putItem(token, decl);
129                 }
130             } // while
131
}
132         ASTNode body = findNode(node, "FunctionBody", 4); // NOI18N
133
processStatements(body, node, context, info, false);
134         context.clearParameters();
135         context.endBlock();
136     }
137     
138     private static void processStatements(ASTNode node, ASTNode parent, ASTContext context, Info info, boolean newBlock) {
139         if (newBlock) {
140             context.startBlock();
141         }
142         for (Iterator JavaDoc iter = node.getChildren().iterator(); iter.hasNext();) {
143             Object JavaDoc obj = iter.next();
144             if (obj instanceof ASTNode) {
145                 ASTNode n = (ASTNode)obj;
146                 String JavaDoc nt = n.getNT();
147                 if ("VariableDeclaration".equals(nt)) { // NOI18N
148
Object JavaDoc child = n.getChildren().get(0);
149                     if (child instanceof ASTToken) {
150                         ASTToken id = (ASTToken)child;
151                         Declaration localVarDecl = new Declaration(context.getFileObject(), context.getDocument(), id,
152                                 Declaration.LOCAL_VARIABLE);
153                         info.putItem(id, localVarDecl);
154                         context.putLocalVar(id.getIdentifier(), localVarDecl);
155                         ASTNode initializer = findNode(n, "Initializer", 1);
156                         if (initializer != null) {
157                             processStatements(initializer, node, context, info, false);
158                         }
159                     }
160                 } else {
161                     boolean isBlock = false;
162                     for (int x = 0; x < BLOCK_NAMES.length; x++) {
163                         if (BLOCK_NAMES[x].equals(nt)) {
164                             isBlock = true;
165                             break;
166                         }
167                     }
168                     processStatements(n, node, context, info, isBlock);
169                 }
170             } else {
171                 ASTToken token = (ASTToken)obj;
172                 if ("js_identifier".equals(token.getType())) { // NOI18N
173
if (!"MemberOperator".equals(parent.getNT())) { // NOI18N
174
String JavaDoc id = token.getIdentifier();
175                         ASTItem brother = findBrother(parent, node);
176                         Declaration decl = null;
177                         if ((brother instanceof ASTNode) && "Arguments".equals(((ASTNode)brother).getNT())) { // NOI18N
178
decl = context.getMethod(id);
179                         } else {
180                             decl = context.getDeclaration(id);
181                         }
182                         if (decl != null) {
183                             Usage usage = new Usage(context.getFileObject(), context.getDocument(), token, decl);
184                             decl.addUsage(usage);
185                             info.putItem(token, decl);
186                         }
187                     } // if
188
} // if
189
} // else
190
} // for
191
if (newBlock) {
192             context.endBlock();
193         }
194     }
195     
196     private static ASTNode findNode(ASTNode node, String JavaDoc nt, int index) {
197         List JavaDoc children = node.getChildren();
198         if (index > children.size()) {
199             return null;
200         }
201         for (Iterator JavaDoc iter = children.listIterator(index); iter.hasNext();) {
202             Object JavaDoc obj = iter.next();
203             if ((obj instanceof ASTNode) && nt.equals(((ASTNode)obj).getNT())) {
204                 return (ASTNode)obj;
205             }
206         }
207         return null;
208     }
209     
210     private static ASTItem findBrother(ASTNode node, ASTItem item) {
211         List JavaDoc children = node.getChildren();
212         for (Iterator JavaDoc iter = children.iterator(); iter.hasNext();) {
213             Object JavaDoc obj = iter.next();
214             if (obj == item) {
215                 return iter.hasNext() ? (ASTItem) iter.next() : null;
216             }
217         }
218         return null;
219     }
220     
221     public static class Declaration {
222         
223         public static final int PARAMETER = 0;
224         public static final int LOCAL_VARIABLE = 1;
225         public static final int METHOD = 2;
226         
227         private ASTItem item;
228         private FileObject fileObject;
229         private Document JavaDoc doc;
230         private int kind;
231         private List JavaDoc usages = new ArrayList JavaDoc();
232         
233         Declaration(FileObject fileObj, Document JavaDoc doc, ASTItem item, int kind) {
234             this.fileObject = fileObj;
235             this.doc = doc;
236             this.item = item;
237             this.kind = kind;
238         }
239         
240         public void addUsage(Usage usage) {
241             usages.add(usage);
242         }
243         
244         public List JavaDoc getUsages() {
245             return usages;
246         }
247         
248         public ASTItem getASTItem() {
249             return item;
250         }
251      
252         public FileObject getFileObject() {
253             return fileObject;
254         }
255         
256         public Document JavaDoc getDocument() {
257             return doc;
258         }
259         
260         public int getKind() {
261             return kind;
262         }
263         
264     }
265     
266     public static class Usage {
267         private ASTItem item;
268         private FileObject fileObject;
269         private Document JavaDoc doc;
270         private Declaration declaration;
271         
272         Usage(FileObject fileObj, Document JavaDoc doc, ASTItem item, Declaration decl) {
273             this.fileObject = fileObj;
274             this.item = item;
275             this.declaration = decl;
276         }
277         
278         public Declaration getDeclaration() {
279             return declaration;
280         }
281         
282         public ASTItem getASTItem() {
283             return item;
284         }
285         
286         public FileObject getFileObject() {
287             return fileObject;
288         }
289         
290     }
291     
292     public static class Info {
293         private Map JavaDoc items = new HashMap JavaDoc(); // ASTNode -> Declaration
294

295         public void putItem(ASTItem item, Declaration decl) {
296             items.put(item, decl);
297         }
298         
299         public Declaration getItem(ASTItem item) {
300             return (Declaration)items.get(item);
301         }
302     }
303     
304     private static class ASTContext {
305         
306         private FileObject fileObject;
307         private Document JavaDoc doc;
308         
309         private Map JavaDoc parameters = new HashMap JavaDoc();
310         private Map JavaDoc methods = new HashMap JavaDoc();
311         private LinkedList JavaDoc localVarsStack = new LinkedList JavaDoc();
312         private Map JavaDoc localVarsDecl;
313         
314         public ASTContext(Document JavaDoc doc) {
315             this.doc = doc;
316             DataObject dobj = NbEditorUtilities.getDataObject(doc);
317             fileObject = dobj.getPrimaryFile();
318         }
319         
320         public void addParameter(String JavaDoc paramName, Declaration decl) {
321             parameters.put(paramName, decl);
322         }
323         
324         public void addMethod(String JavaDoc methodName, Declaration decl) {
325             methods.put(methodName, decl);
326         }
327         
328 // public Declaration getParameter(String paramName) {
329
// return (Declaration)parameters.get(paramName);
330
// }
331

332         public void clearParameters() {
333             parameters.clear();
334         }
335         
336         public void startBlock() {
337             localVarsDecl = new HashMap JavaDoc();
338             localVarsStack.addFirst(localVarsDecl);
339         }
340         
341         public void endBlock() {
342             localVarsStack.removeFirst();
343             localVarsDecl = localVarsStack.isEmpty() ? null : (Map JavaDoc)localVarsStack.getFirst();
344         }
345         
346         public void putLocalVar(String JavaDoc varName, Declaration localVarDecl) {
347             localVarsDecl.put(varName, localVarDecl);
348         }
349         
350         public Declaration getDeclaration(String JavaDoc name) {
351             for (Iterator JavaDoc iter = localVarsStack.iterator(); iter.hasNext(); ) {
352                 Map JavaDoc map = (Map JavaDoc)iter.next();
353                 Declaration decl = (Declaration)map.get(name);
354                 if (decl != null) {
355                     return decl;
356                 }
357             }
358             return (Declaration)parameters.get(name);
359         }
360         
361         public Declaration getMethod(String JavaDoc name) {
362             return (Declaration)methods.get(name);
363         }
364         
365         public FileObject getFileObject() {
366             return fileObject;
367         }
368         
369         public Document JavaDoc getDocument() {
370             return doc;
371         }
372     }
373     
374 }
375
Popular Tags