KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > eclipse > jdt > internal > core > CompilationUnitStructureRequestor


1 /*******************************************************************************
2  * Copyright (c) 2000, 2006 IBM Corporation and others.
3  * All rights reserved. This program and the accompanying materials
4  * are made available under the terms of the Eclipse Public License v1.0
5  * which accompanies this distribution, and is available at
6  * http://www.eclipse.org/legal/epl-v10.html
7  *
8  * Contributors:
9  * IBM Corporation - initial API and implementation
10  *******************************************************************************/

11 package org.eclipse.jdt.internal.core;
12
13 import java.util.ArrayList JavaDoc;
14 import java.util.HashMap JavaDoc;
15 import java.util.Map JavaDoc;
16 import java.util.Stack JavaDoc;
17
18 import org.eclipse.core.runtime.Assert;
19 import org.eclipse.jdt.core.*;
20 import org.eclipse.jdt.core.compiler.CategorizedProblem;
21 import org.eclipse.jdt.core.compiler.CharOperation;
22 import org.eclipse.jdt.core.compiler.IProblem;
23 import org.eclipse.jdt.internal.compiler.ISourceElementRequestor;
24 import org.eclipse.jdt.internal.compiler.parser.Parser;
25 import org.eclipse.jdt.internal.compiler.util.HashtableOfObject;
26 import org.eclipse.jdt.internal.core.util.ReferenceInfoAdapter;
27
28 /**
29  * A requestor for the fuzzy parser, used to compute the children of an ICompilationUnit.
30  */

31 public class CompilationUnitStructureRequestor extends ReferenceInfoAdapter implements ISourceElementRequestor {
32
33     /**
34      * The handle to the compilation unit being parsed
35      */

36     protected ICompilationUnit unit;
37
38     /**
39      * The info object for the compilation unit being parsed
40      */

41     protected CompilationUnitElementInfo unitInfo;
42
43     /**
44      * The import container info - null until created
45      */

46     protected JavaElementInfo importContainerInfo = null;
47
48     /**
49      * Hashtable of children elements of the compilation unit.
50      * Children are added to the table as they are found by
51      * the parser. Keys are handles, values are corresponding
52      * info objects.
53      */

54     protected Map JavaDoc newElements;
55
56     /**
57      * Stack of parent scope info objects. The info on the
58      * top of the stack is the parent of the next element found.
59      * For example, when we locate a method, the parent info object
60      * will be the type the method is contained in.
61      */

62     protected Stack JavaDoc infoStack;
63     
64     /*
65      * Map from JavaElementInfo to of ArrayList of IJavaElement representing the children
66      * of the given info.
67      */

68     protected HashMap JavaDoc children;
69
70     /**
71      * Stack of parent handles, corresponding to the info stack. We
72      * keep both, since info objects do not have back pointers to
73      * handles.
74      */

75     protected Stack JavaDoc handleStack;
76
77     /**
78      * The number of references reported thus far. Used to
79      * expand the arrays of reference kinds and names.
80      */

81     protected int referenceCount= 0;
82
83     /**
84      * Problem requestor which will get notified of discovered problems
85      */

86     protected boolean hasSyntaxErrors = false;
87     
88     /*
89      * The parser this requestor is using.
90      */

91     protected Parser parser;
92     
93     /**
94      * Empty collections used for efficient initialization
95      */

96     protected static byte[] NO_BYTES= new byte[]{};
97
98     protected HashtableOfObject fieldRefCache;
99     protected HashtableOfObject messageRefCache;
100     protected HashtableOfObject typeRefCache;
101     protected HashtableOfObject unknownRefCache;
102
103 protected CompilationUnitStructureRequestor(ICompilationUnit unit, CompilationUnitElementInfo unitInfo, Map JavaDoc newElements) {
104     this.unit = unit;
105     this.unitInfo = unitInfo;
106     this.newElements = newElements;
107 }
108 /**
109  * @see ISourceElementRequestor
110  */

111 public void acceptImport(int declarationStart, int declarationEnd, char[][] tokens, boolean onDemand, int modifiers) {
112     JavaElement parentHandle= (JavaElement) this.handleStack.peek();
113     if (!(parentHandle.getElementType() == IJavaElement.COMPILATION_UNIT)) {
114         Assert.isTrue(false); // Should not happen
115
}
116
117     ICompilationUnit parentCU= (ICompilationUnit)parentHandle;
118     //create the import container and its info
119
ImportContainer importContainer= (ImportContainer)parentCU.getImportContainer();
120     if (this.importContainerInfo == null) {
121         this.importContainerInfo = new JavaElementInfo();
122         JavaElementInfo parentInfo = (JavaElementInfo) this.infoStack.peek();
123         addToChildren(parentInfo, importContainer);
124         this.newElements.put(importContainer, this.importContainerInfo);
125     }
126     
127     String JavaDoc elementName = JavaModelManager.getJavaModelManager().intern(new String JavaDoc(CharOperation.concatWith(tokens, '.')));
128     ImportDeclaration handle = new ImportDeclaration(importContainer, elementName, onDemand);
129     resolveDuplicates(handle);
130     
131     ImportDeclarationElementInfo info = new ImportDeclarationElementInfo();
132     info.setSourceRangeStart(declarationStart);
133     info.setSourceRangeEnd(declarationEnd);
134     info.setFlags(modifiers);
135
136     addToChildren(this.importContainerInfo, handle);
137     this.newElements.put(handle, info);
138 }
139 /*
140  * Table of line separator position. This table is passed once at the end
141  * of the parse action, so as to allow computation of normalized ranges.
142  *
143  * A line separator might corresponds to several characters in the source,
144  *
145  */

146 public void acceptLineSeparatorPositions(int[] positions) {
147     // ignore line separator positions
148
}
149 /**
150  * @see ISourceElementRequestor
151  */

152 public void acceptPackage(int declarationStart, int declarationEnd, char[] name) {
153
154         JavaElementInfo parentInfo = (JavaElementInfo) this.infoStack.peek();
155         JavaElement parentHandle= (JavaElement) this.handleStack.peek();
156         PackageDeclaration handle = null;
157         
158         if (parentHandle.getElementType() == IJavaElement.COMPILATION_UNIT) {
159             handle = new PackageDeclaration((CompilationUnit) parentHandle, new String JavaDoc(name));
160         }
161         else {
162             Assert.isTrue(false); // Should not happen
163
}
164         resolveDuplicates(handle);
165         
166         SourceRefElementInfo info = new SourceRefElementInfo();
167         info.setSourceRangeStart(declarationStart);
168         info.setSourceRangeEnd(declarationEnd);
169
170         addToChildren(parentInfo, handle);
171         this.newElements.put(handle, info);
172
173 }
174 public void acceptProblem(CategorizedProblem problem) {
175     if ((problem.getID() & IProblem.Syntax) != 0){
176         this.hasSyntaxErrors = true;
177     }
178 }
179 private void addToChildren(JavaElementInfo parentInfo, JavaElement handle) {
180     ArrayList JavaDoc childrenList = (ArrayList JavaDoc) this.children.get(parentInfo);
181     if (childrenList == null)
182         this.children.put(parentInfo, childrenList = new ArrayList JavaDoc());
183     childrenList.add(handle);
184 }
185 /**
186  * Convert these type names to signatures.
187  * @see Signature
188  */

189 /* default */ static String JavaDoc[] convertTypeNamesToSigs(char[][] typeNames) {
190     if (typeNames == null)
191         return CharOperation.NO_STRINGS;
192     int n = typeNames.length;
193     if (n == 0)
194         return CharOperation.NO_STRINGS;
195     JavaModelManager manager = JavaModelManager.getJavaModelManager();
196     String JavaDoc[] typeSigs = new String JavaDoc[n];
197     for (int i = 0; i < n; ++i) {
198         typeSigs[i] = manager.intern(Signature.createTypeSignature(typeNames[i], false));
199     }
200     return typeSigs;
201 }
202 /**
203  * @see ISourceElementRequestor
204  */

205 public void enterCompilationUnit() {
206     this.infoStack = new Stack JavaDoc();
207     this.children = new HashMap JavaDoc();
208     this.handleStack= new Stack JavaDoc();
209     this.infoStack.push(this.unitInfo);
210     this.handleStack.push(this.unit);
211 }
212 /**
213  * @see ISourceElementRequestor
214  */

215 public void enterConstructor(MethodInfo methodInfo) {
216     enterMethod(methodInfo);
217 }
218 /**
219  * @see ISourceElementRequestor
220  */

221 public void enterField(FieldInfo fieldInfo) {
222
223     SourceTypeElementInfo parentInfo = (SourceTypeElementInfo) this.infoStack.peek();
224     JavaElement parentHandle= (JavaElement) this.handleStack.peek();
225     SourceField handle = null;
226     if (parentHandle.getElementType() == IJavaElement.TYPE) {
227         String JavaDoc fieldName = JavaModelManager.getJavaModelManager().intern(new String JavaDoc(fieldInfo.name));
228         handle = new SourceField(parentHandle, fieldName);
229     }
230     else {
231         Assert.isTrue(false); // Should not happen
232
}
233     resolveDuplicates(handle);
234     
235     SourceFieldElementInfo info = new SourceFieldElementInfo();
236     info.setNameSourceStart(fieldInfo.nameSourceStart);
237     info.setNameSourceEnd(fieldInfo.nameSourceEnd);
238     info.setSourceRangeStart(fieldInfo.declarationStart);
239     info.setFlags(fieldInfo.modifiers);
240     char[] typeName = JavaModelManager.getJavaModelManager().intern(fieldInfo.type);
241     info.setTypeName(typeName);
242     
243     this.unitInfo.addAnnotationPositions(handle, fieldInfo.annotationPositions);
244
245     addToChildren(parentInfo, handle);
246     parentInfo.addCategories(handle, fieldInfo.categories);
247     this.newElements.put(handle, info);
248
249     this.infoStack.push(info);
250     this.handleStack.push(handle);
251 }
252 /**
253  * @see ISourceElementRequestor
254  */

255 public void enterInitializer(
256     int declarationSourceStart,
257     int modifiers) {
258         JavaElementInfo parentInfo = (JavaElementInfo) this.infoStack.peek();
259         JavaElement parentHandle= (JavaElement) this.handleStack.peek();
260         Initializer handle = null;
261         
262         if (parentHandle.getElementType() == IJavaElement.TYPE) {
263             handle = new Initializer(parentHandle, 1);
264         }
265         else {
266             Assert.isTrue(false); // Should not happen
267
}
268         resolveDuplicates(handle);
269         
270         InitializerElementInfo info = new InitializerElementInfo();
271         info.setSourceRangeStart(declarationSourceStart);
272         info.setFlags(modifiers);
273
274         addToChildren(parentInfo, handle);
275         this.newElements.put(handle, info);
276
277         this.infoStack.push(info);
278         this.handleStack.push(handle);
279 }
280 /**
281  * @see ISourceElementRequestor
282  */

283 public void enterMethod(MethodInfo methodInfo) {
284
285     SourceTypeElementInfo parentInfo = (SourceTypeElementInfo) this.infoStack.peek();
286     JavaElement parentHandle= (JavaElement) this.handleStack.peek();
287     SourceMethod handle = null;
288
289     // translate nulls to empty arrays
290
if (methodInfo.parameterTypes == null) {
291         methodInfo.parameterTypes= CharOperation.NO_CHAR_CHAR;
292     }
293     if (methodInfo.parameterNames == null) {
294         methodInfo.parameterNames= CharOperation.NO_CHAR_CHAR;
295     }
296     if (methodInfo.exceptionTypes == null) {
297         methodInfo.exceptionTypes= CharOperation.NO_CHAR_CHAR;
298     }
299     
300     String JavaDoc[] parameterTypeSigs = convertTypeNamesToSigs(methodInfo.parameterTypes);
301     if (parentHandle.getElementType() == IJavaElement.TYPE) {
302         String JavaDoc selector = JavaModelManager.getJavaModelManager().intern(new String JavaDoc(methodInfo.name));
303         handle = new SourceMethod(parentHandle, selector, parameterTypeSigs);
304     }
305     else {
306         Assert.isTrue(false); // Should not happen
307
}
308     resolveDuplicates(handle);
309     
310     SourceMethodElementInfo info;
311     if (methodInfo.isConstructor)
312         info = new SourceConstructorInfo();
313     else if (methodInfo.isAnnotation)
314         info = new SourceAnnotationMethodInfo();
315     else
316         info = new SourceMethodInfo();
317     info.setSourceRangeStart(methodInfo.declarationStart);
318     int flags = methodInfo.modifiers;
319     info.setNameSourceStart(methodInfo.nameSourceStart);
320     info.setNameSourceEnd(methodInfo.nameSourceEnd);
321     info.setFlags(flags);
322     JavaModelManager manager = JavaModelManager.getJavaModelManager();
323     char[][] parameterNames = methodInfo.parameterNames;
324     for (int i = 0, length = parameterNames.length; i < length; i++)
325         parameterNames[i] = manager.intern(parameterNames[i]);
326     info.setArgumentNames(parameterNames);
327     char[] returnType = methodInfo.returnType == null ? new char[]{'v', 'o','i', 'd'} : methodInfo.returnType;
328     info.setReturnType(manager.intern(returnType));
329     char[][] exceptionTypes = methodInfo.exceptionTypes;
330     info.setExceptionTypeNames(exceptionTypes);
331     for (int i = 0, length = exceptionTypes.length; i < length; i++)
332         exceptionTypes[i] = manager.intern(exceptionTypes[i]);
333     this.unitInfo.addAnnotationPositions(handle, methodInfo.annotationPositions);
334     addToChildren(parentInfo, handle);
335     parentInfo.addCategories(handle, methodInfo.categories);
336     this.newElements.put(handle, info);
337     this.infoStack.push(info);
338     this.handleStack.push(handle);
339
340     if (methodInfo.typeParameters != null) {
341         for (int i = 0, length = methodInfo.typeParameters.length; i < length; i++) {
342             TypeParameterInfo typeParameterInfo = methodInfo.typeParameters[i];
343             enterTypeParameter(typeParameterInfo);
344             exitMember(typeParameterInfo.declarationEnd);
345         }
346     }
347 }
348 /**
349  * @see ISourceElementRequestor
350  */

351 public void enterType(TypeInfo typeInfo) {
352
353     JavaElementInfo parentInfo = (JavaElementInfo) this.infoStack.peek();
354     JavaElement parentHandle= (JavaElement) this.handleStack.peek();
355     String JavaDoc nameString= new String JavaDoc(typeInfo.name);
356     SourceType handle = new SourceType(parentHandle, nameString); //NB: occurenceCount is computed in resolveDuplicates
357
resolveDuplicates(handle);
358     
359     SourceTypeElementInfo info =
360         typeInfo.anonymousMember ?
361             new SourceTypeElementInfo() {
362                 public boolean isAnonymousMember() {
363                     return true;
364                 }
365             } :
366         new SourceTypeElementInfo();
367     info.setHandle(handle);
368     info.setSourceRangeStart(typeInfo.declarationStart);
369     info.setFlags(typeInfo.modifiers);
370     info.setNameSourceStart(typeInfo.nameSourceStart);
371     info.setNameSourceEnd(typeInfo.nameSourceEnd);
372     JavaModelManager manager = JavaModelManager.getJavaModelManager();
373     char[] superclass = typeInfo.superclass;
374     info.setSuperclassName(superclass == null ? null : manager.intern(superclass));
375     char[][] superinterfaces = typeInfo.superinterfaces;
376     for (int i = 0, length = superinterfaces == null ? 0 : superinterfaces.length; i < length; i++)
377         superinterfaces[i] = manager.intern(superinterfaces[i]);
378     info.setSuperInterfaceNames(superinterfaces);
379     info.addCategories(handle, typeInfo.categories);
380     if (parentHandle.getElementType() == IJavaElement.TYPE)
381         ((SourceTypeElementInfo) parentInfo).addCategories(handle, typeInfo.categories);
382     addToChildren(parentInfo, handle);
383     this.unitInfo.addAnnotationPositions(handle, typeInfo.annotationPositions);
384     this.newElements.put(handle, info);
385     this.infoStack.push(info);
386     this.handleStack.push(handle);
387     
388     if (typeInfo.typeParameters != null) {
389         for (int i = 0, length = typeInfo.typeParameters.length; i < length; i++) {
390             TypeParameterInfo typeParameterInfo = typeInfo.typeParameters[i];
391             enterTypeParameter(typeParameterInfo);
392             exitMember(typeParameterInfo.declarationEnd);
393         }
394     }
395 }
396 protected void enterTypeParameter(TypeParameterInfo typeParameterInfo) {
397     JavaElementInfo parentInfo = (JavaElementInfo) this.infoStack.peek();
398     JavaElement parentHandle = (JavaElement) this.handleStack.peek();
399     String JavaDoc nameString = new String JavaDoc(typeParameterInfo.name);
400     TypeParameter handle = new TypeParameter(parentHandle, nameString); //NB: occurenceCount is computed in resolveDuplicates
401
resolveDuplicates(handle);
402     
403     TypeParameterElementInfo info = new TypeParameterElementInfo();
404     info.setSourceRangeStart(typeParameterInfo.declarationStart);
405     info.nameStart = typeParameterInfo.nameSourceStart;
406     info.nameEnd = typeParameterInfo.nameSourceEnd;
407     info.bounds = typeParameterInfo.bounds;
408     if (parentInfo instanceof SourceTypeElementInfo) {
409         SourceTypeElementInfo elementInfo = (SourceTypeElementInfo) parentInfo;
410         ITypeParameter[] typeParameters = elementInfo.typeParameters;
411         int length = typeParameters.length;
412         System.arraycopy(typeParameters, 0, typeParameters = new ITypeParameter[length+1], 0, length);
413         typeParameters[length] = handle;
414         elementInfo.typeParameters = typeParameters;
415     } else {
416         SourceMethodElementInfo elementInfo = (SourceMethodElementInfo) parentInfo;
417         ITypeParameter[] typeParameters = elementInfo.typeParameters;
418         int length = typeParameters.length;
419         System.arraycopy(typeParameters, 0, typeParameters = new ITypeParameter[length+1], 0, length);
420         typeParameters[length] = handle;
421         elementInfo.typeParameters = typeParameters;
422     }
423     this.unitInfo.addAnnotationPositions(handle, typeParameterInfo.annotationPositions);
424     this.newElements.put(handle, info);
425     this.infoStack.push(info);
426     this.handleStack.push(handle);
427 }
428 /**
429  * @see ISourceElementRequestor
430  */

431 public void exitCompilationUnit(int declarationEnd) {
432     // set import container children
433
if (this.importContainerInfo != null) {
434         setChildren(this.importContainerInfo);
435     }
436     
437     // set children
438
setChildren(this.unitInfo);
439     
440     this.unitInfo.setSourceLength(declarationEnd + 1);
441
442     // determine if there were any parsing errors
443
this.unitInfo.setIsStructureKnown(!this.hasSyntaxErrors);
444 }
445 /**
446  * @see ISourceElementRequestor
447  */

448 public void exitConstructor(int declarationEnd) {
449     exitMember(declarationEnd);
450 }
451 /**
452  * @see ISourceElementRequestor
453  */

454 public void exitField(int initializationStart, int declarationEnd, int declarationSourceEnd) {
455     SourceFieldElementInfo info = (SourceFieldElementInfo) this.infoStack.pop();
456     info.setSourceRangeEnd(declarationSourceEnd);
457     setChildren(info);
458     
459     // remember initializer source if field is a constant
460
if (initializationStart != -1) {
461         int flags = info.flags;
462         Object JavaDoc typeInfo;
463         if (Flags.isStatic(flags) && Flags.isFinal(flags)
464                 || ((typeInfo = this.infoStack.peek()) instanceof SourceTypeElementInfo
465                      && (Flags.isInterface(((SourceTypeElementInfo)typeInfo).flags)))) {
466             int length = declarationEnd - initializationStart;
467             if (length > 0) {
468                 char[] initializer = new char[length];
469                 System.arraycopy(this.parser.scanner.source, initializationStart, initializer, 0, length);
470                 info.initializationSource = initializer;
471             }
472         }
473     }
474     this.handleStack.pop();
475 }
476 /**
477  * @see ISourceElementRequestor
478  */

479 public void exitInitializer(int declarationEnd) {
480     exitMember(declarationEnd);
481 }
482 /**
483  * common processing for classes and interfaces
484  */

485 protected void exitMember(int declarationEnd) {
486     SourceRefElementInfo info = (SourceRefElementInfo) this.infoStack.pop();
487     info.setSourceRangeEnd(declarationEnd);
488     setChildren(info);
489     this.handleStack.pop();
490 }
491 /**
492  * @see ISourceElementRequestor
493  */

494 public void exitMethod(int declarationEnd, int defaultValueStart, int defaultValueEnd) {
495     SourceMethodElementInfo info = (SourceMethodElementInfo) this.infoStack.pop();
496     info.setSourceRangeEnd(declarationEnd);
497     setChildren(info);
498     
499     // remember default value of annotation method
500
if (info.isAnnotationMethod()) {
501         SourceAnnotationMethodInfo annotationMethodInfo = (SourceAnnotationMethodInfo) info;
502         annotationMethodInfo.defaultValueStart = defaultValueStart;
503         annotationMethodInfo.defaultValueEnd = defaultValueEnd;
504     }
505     this.handleStack.pop();
506 }
507 /**
508  * @see ISourceElementRequestor
509  */

510 public void exitType(int declarationEnd) {
511
512     exitMember(declarationEnd);
513 }
514 /**
515  * Resolves duplicate handles by incrementing the occurrence count
516  * of the handle being created until there is no conflict.
517  */

518 protected void resolveDuplicates(SourceRefElement handle) {
519     while (this.newElements.containsKey(handle)) {
520         handle.occurrenceCount++;
521     }
522 }
523 private void setChildren(JavaElementInfo info) {
524     ArrayList JavaDoc childrenList = (ArrayList JavaDoc) this.children.get(info);
525     if (childrenList != null) {
526         int length = childrenList.size();
527         IJavaElement[] elements = new IJavaElement[length];
528         childrenList.toArray(elements);
529         info.children = elements;
530     }
531 }
532 }
533
Popular Tags