1 /*******************************************************************************
2 * Copyright (c) 2000, 2003 IBM Corporation and others.
3 * All rights reserved. This program and the accompanying materials
4 * are made available under the terms of the Common Public License v1.0
5 * which accompanies this distribution, and is available at
6 * http://www.eclipse.org/legal/cpl-v10.html
9 * IBM Corporation - initial API and implementation
10 *******************************************************************************/
11 package net.sourceforge.phpdt.internal.core;
14 import java.util.Stack;
16 import net.sourceforge.phpdt.internal.core.JavaElement;
17 import net.sourceforge.phpdt.internal.core.SourceField;
18 import net.sourceforge.phpdt.internal.core.SourceFieldElementInfo;
19 import net.sourceforge.phpdt.internal.core.SourceMethod;
20 import net.sourceforge.phpdt.internal.core.SourceTypeElementInfo;
22 import net.sourceforge.phpdt.core.ICompilationUnit;
23 import net.sourceforge.phpdt.core.IField;
24 import net.sourceforge.phpdt.core.IJavaElement;
25 import net.sourceforge.phpdt.core.IMethod;
26 import net.sourceforge.phpdt.core.IType;
27 import net.sourceforge.phpdt.core.JavaModelException;
28 import net.sourceforge.phpdt.core.Signature;
29 import net.sourceforge.phpdt.core.compiler.IProblem;
30 import net.sourceforge.phpdt.internal.compiler.ISourceElementRequestor;
31 import net.sourceforge.phpdt.internal.compiler.parser.Parser;
32 import net.sourceforge.phpdt.internal.compiler.util.HashtableOfObject;
33 import net.sourceforge.phpdt.internal.core.util.ReferenceInfoAdapter;
34 import net.sourceforge.phpdt.internal.corext.Assert;
37 * A requestor for the fuzzy parser, used to compute the children of an ICompilationUnit.
39 public class CompilationUnitStructureRequestor extends ReferenceInfoAdapter implements ISourceElementRequestor {
42 * The handle to the compilation unit being parsed
44 protected ICompilationUnit fUnit;
47 * The info object for the compilation unit being parsed
49 protected CompilationUnitElementInfo fUnitInfo;
52 * The import container info - null until created
54 protected JavaElementInfo fImportContainerInfo = null;
57 * Hashtable of children elements of the compilation unit.
58 * Children are added to the table as they are found by
59 * the parser. Keys are handles, values are corresponding
62 protected Map fNewElements;
65 * Stack of parent scope info objects. The info on the
66 * top of the stack is the parent of the next element found.
67 * For example, when we locate a method, the parent info object
68 * will be the type the method is contained in.
70 protected Stack fInfoStack;
73 * Stack of parent handles, corresponding to the info stack. We
74 * keep both, since info objects do not have back pointers to
77 protected Stack fHandleStack;
80 * The name of the source file being parsed.
82 protected char[] fSourceFileName = null;
85 * The dot-separated name of the package the compilation unit
86 * is contained in - based on the package statement in the
87 * compilation unit, and initialized by #acceptPackage.
88 * Initialized to <code>null</code> for the default package.
90 protected char[] fPackageName = null;
93 * The number of references reported thus far. Used to
94 * expand the arrays of reference kinds and names.
96 protected int fRefCount = 0;
99 * The initial size of the reference kind and name
100 * arrays. If the arrays fill, they are doubled in
103 protected static int fgReferenceAllocation = 50;
106 * Problem requestor which will get notified of discovered problems
108 protected boolean hasSyntaxErrors = false;
111 * The parser this requestor is using.
113 // protected Parser parser;
114 protected Parser parser;
117 * Empty collections used for efficient initialization
119 protected static String[] fgEmptyStringArray = new String[0];
120 protected static byte[] fgEmptyByte = new byte[] {
122 protected static char[][] fgEmptyCharChar = new char[][] {
124 protected static char[] fgEmptyChar = new char[] {
127 protected HashtableOfObject fieldRefCache;
128 protected HashtableOfObject messageRefCache;
129 protected HashtableOfObject typeRefCache;
130 protected HashtableOfObject unknownRefCache;
132 protected CompilationUnitStructureRequestor(ICompilationUnit unit, CompilationUnitElementInfo unitInfo, Map newElements)
133 throws JavaModelException {
135 this.fUnitInfo = unitInfo;
136 this.fNewElements = newElements;
137 this.fSourceFileName = unit.getElementName().toCharArray();
140 * @see ISourceElementRequestor
142 //public void acceptImport(int declarationStart, int declarationEnd, char[] name, boolean onDemand) {
143 // JavaElementInfo parentInfo = (JavaElementInfo) fInfoStack.peek();
144 // JavaElement parentHandle= (JavaElement)fHandleStack.peek();
145 // if (!(parentHandle.getElementType() == IJavaElement.COMPILATION_UNIT)) {
146 // Assert.isTrue(false); // Should not happen
149 // ICompilationUnit parentCU= (ICompilationUnit)parentHandle;
150 // //create the import container and its info
151 // IImportContainer importContainer= parentCU.getImportContainer();
152 // if (fImportContainerInfo == null) {
153 // fImportContainerInfo= new JavaElementInfo();
154 // fImportContainerInfo.setIsStructureKnown(true);
155 // parentInfo.addChild(importContainer);
156 // fNewElements.put(importContainer, fImportContainerInfo);
159 // // tack on the '.*' if it is onDemand
160 // String importName;
162 // importName= new String(name) + ".*"; //$NON-NLS-1$
164 // importName= new String(name);
167 // ImportDeclaration handle = new ImportDeclaration(importContainer, importName);
168 // resolveDuplicates(handle);
170 // SourceRefElementInfo info = new SourceRefElementInfo();
171 // info.setSourceRangeStart(declarationStart);
172 // info.setSourceRangeEnd(declarationEnd);
174 // fImportContainerInfo.addChild(handle);
175 // fNewElements.put(handle, info);
178 * Table of line separator position. This table is passed once at the end
179 * of the parse action, so as to allow computation of normalized ranges.
181 * A line separator might corresponds to several characters in the source,
184 public void acceptLineSeparatorPositions(int[] positions) {
187 * @see ISourceElementRequestor
189 //public void acceptPackage(int declarationStart, int declarationEnd, char[] name) {
191 // JavaElementInfo parentInfo = (JavaElementInfo) fInfoStack.peek();
192 // JavaElement parentHandle= (JavaElement)fHandleStack.peek();
193 // IPackageDeclaration handle = null;
194 // fPackageName= name;
196 // if (parentHandle.getElementType() == IJavaElement.COMPILATION_UNIT) {
197 // handle = new PackageDeclaration((ICompilationUnit) parentHandle, new String(name));
200 // Assert.isTrue(false); // Should not happen
202 // resolveDuplicates(handle);
204 // SourceRefElementInfo info = new SourceRefElementInfo();
205 // info.setSourceRangeStart(declarationStart);
206 // info.setSourceRangeEnd(declarationEnd);
208 // parentInfo.addChild(handle);
209 // fNewElements.put(handle, info);
212 public void acceptProblem(IProblem problem) {
213 if ((problem.getID() & IProblem.Syntax) != 0) {
214 this.hasSyntaxErrors = true;
218 * Convert these type names to signatures.
222 static String[] convertTypeNamesToSigs(char[][] typeNames) {
223 if (typeNames == null)
224 return fgEmptyStringArray;
225 int n = typeNames.length;
227 return fgEmptyStringArray;
228 String[] typeSigs = new String[n];
229 for (int i = 0; i < n; ++i) {
230 typeSigs[i] = Signature.createTypeSignature(typeNames[i], false);
235 * @see ISourceElementRequestor
237 public void enterClass(
238 int declarationStart,
244 char[][] superinterfaces) {
246 enterType(declarationStart, modifiers, name, nameSourceStart, nameSourceEnd, superclass, superinterfaces);
250 * @see ISourceElementRequestor
252 public void enterCompilationUnit() {
253 fInfoStack = new Stack();
254 fHandleStack = new Stack();
255 fInfoStack.push(fUnitInfo);
256 fHandleStack.push(fUnit);
259 * @see ISourceElementRequestor
261 public void enterConstructor(
262 int declarationStart,
267 char[][] parameterTypes,
268 char[][] parameterNames,
269 char[][] exceptionTypes) {
285 * @see ISourceElementRequestor
287 public void enterField(int declarationStart, int modifiers, char[] type, char[] name, int nameSourceStart, int nameSourceEnd) {
289 SourceTypeElementInfo parentInfo = (SourceTypeElementInfo) fInfoStack.peek();
290 JavaElement parentHandle = (JavaElement) fHandleStack.peek();
291 IField handle = null;
293 if (parentHandle.getElementType() == IJavaElement.TYPE) {
294 handle = new SourceField(parentHandle, new String(name));
296 Assert.isTrue(false); // Should not happen
298 resolveDuplicates(handle);
300 SourceFieldElementInfo info = new SourceFieldElementInfo();
302 info.setNameSourceStart(nameSourceStart);
303 info.setNameSourceEnd(nameSourceEnd);
304 info.setSourceRangeStart(declarationStart);
305 info.setFlags(modifiers);
306 info.setTypeName(type);
308 parentInfo.addChild(handle);
309 fNewElements.put(handle, info);
311 fInfoStack.push(info);
312 fHandleStack.push(handle);
315 * @see ISourceElementRequestor
317 //public void enterInitializer(
318 // int declarationSourceStart,
320 // JavaElementInfo parentInfo = (JavaElementInfo) fInfoStack.peek();
321 // JavaElement parentHandle= (JavaElement)fHandleStack.peek();
322 // IInitializer handle = null;
324 // if (parentHandle.getElementType() == IJavaElement.TYPE) {
325 // handle = ((IType) parentHandle).getInitializer(1);
328 // Assert.isTrue(false); // Should not happen
330 // resolveDuplicates(handle);
332 // InitializerElementInfo info = new InitializerElementInfo();
333 // info.setSourceRangeStart(declarationSourceStart);
334 // info.setFlags(modifiers);
336 // parentInfo.addChild(handle);
337 // fNewElements.put(handle, info);
339 // fInfoStack.push(info);
340 // fHandleStack.push(handle);
343 * @see ISourceElementRequestor
345 public void enterInterface(
346 int declarationStart,
351 char[][] superinterfaces) {
353 enterType(declarationStart, modifiers, name, nameSourceStart, nameSourceEnd, null, superinterfaces);
357 * @see ISourceElementRequestor
359 public void enterMethod(
360 int declarationStart,
366 char[][] parameterTypes,
367 char[][] parameterNames,
368 char[][] exceptionTypes) {
383 * @see ISourceElementRequestor
385 protected void enterMethod(
386 int declarationStart,
392 char[][] parameterTypes,
393 char[][] parameterNames,
394 char[][] exceptionTypes,
395 boolean isConstructor) {
396 SourceTypeElementInfo parentInfo = null;
398 parentInfo = (SourceTypeElementInfo) fInfoStack.peek();
399 } catch (ClassCastException e) {
400 // parentInfo = null;
402 JavaElement parentHandle = (JavaElement) fHandleStack.peek();
403 IMethod handle = null;
405 // translate nulls to empty arrays
406 if (parameterTypes == null) {
407 parameterTypes = fgEmptyCharChar;
409 if (parameterNames == null) {
410 parameterNames = fgEmptyCharChar;
412 if (exceptionTypes == null) {
413 exceptionTypes = fgEmptyCharChar;
416 String[] parameterTypeSigs = convertTypeNamesToSigs(parameterTypes);
417 // TODO : jsurfer changed
418 // if (parentHandle.getElementType() == IJavaElement.TYPE) {
419 handle = new SourceMethod(parentHandle, new String(name), parameterTypeSigs);
422 // Assert.isTrue(false); // Should not happen
424 resolveDuplicates(handle);
426 SourceMethodElementInfo info = new SourceMethodElementInfo();
427 info.setSourceRangeStart(declarationStart);
428 int flags = modifiers;
430 info.setNameSourceStart(nameSourceStart);
431 info.setNameSourceEnd(nameSourceEnd);
432 info.setConstructor(isConstructor);
433 info.setFlags(flags);
434 info.setArgumentNames(parameterNames);
435 info.setArgumentTypeNames(parameterTypes);
436 info.setReturnType(returnType == null ? new char[] { 'v', 'o', 'i', 'd' }
438 info.setExceptionTypeNames(exceptionTypes);
440 if (parentInfo == null) {
441 fUnitInfo.addChild(handle);
443 parentInfo.addChild(handle);
445 fNewElements.put(handle, info);
446 fInfoStack.push(info);
447 fHandleStack.push(handle);
450 * Common processing for classes and interfaces.
452 protected void enterType(
453 int declarationStart,
459 char[][] superinterfaces) {
461 char[] enclosingTypeName = null;
462 char[] qualifiedName = null;
464 JavaElementInfo parentInfo = (JavaElementInfo) fInfoStack.peek();
465 JavaElement parentHandle = (JavaElement) fHandleStack.peek();
467 String nameString = new String(name);
469 if (parentHandle.getElementType() == IJavaElement.COMPILATION_UNIT) {
470 handle = ((ICompilationUnit) parentHandle).getType(nameString);
471 if (fPackageName == null) {
472 qualifiedName = nameString.toCharArray();
474 qualifiedName = (new String(fPackageName) + "." + nameString).toCharArray(); //$NON-NLS-1$
476 } else if (parentHandle.getElementType() == IJavaElement.TYPE) {
477 handle = ((IType) parentHandle).getType(nameString);
478 enclosingTypeName = ((SourceTypeElementInfo) parentInfo).getName();
479 qualifiedName = (new String(((SourceTypeElementInfo) parentInfo).getQualifiedName()) + "." + nameString).toCharArray(); //$NON-NLS-1$
481 Assert.isTrue(false); // Should not happen
483 resolveDuplicates(handle);
485 SourceTypeElementInfo info = new SourceTypeElementInfo();
486 info.setHandle(handle);
487 info.setSourceRangeStart(declarationStart);
488 info.setFlags(modifiers);
490 info.setNameSourceStart(nameSourceStart);
491 info.setNameSourceEnd(nameSourceEnd);
492 info.setSuperclassName(superclass);
493 info.setSuperInterfaceNames(superinterfaces);
494 info.setEnclosingTypeName(enclosingTypeName);
495 info.setSourceFileName(fSourceFileName);
496 info.setPackageName(fPackageName);
497 info.setQualifiedName(qualifiedName);
498 // for (Iterator iter = fNewElements.keySet().iterator(); iter.hasNext();){
499 // Object object = iter.next();
500 // if (object instanceof IImportDeclaration)
501 // info.addImport(((IImportDeclaration)object).getElementName().toCharArray());
504 parentInfo.addChild(handle);
505 fNewElements.put(handle, info);
507 fInfoStack.push(info);
508 fHandleStack.push(handle);
512 * @see ISourceElementRequestor
514 public void exitClass(int declarationEnd) {
516 exitMember(declarationEnd);
519 * @see ISourceElementRequestor
521 public void exitCompilationUnit(int declarationEnd) {
522 fUnitInfo.setSourceLength(declarationEnd + 1);
524 // determine if there were any parsing errors
525 fUnitInfo.setIsStructureKnown(!this.hasSyntaxErrors);
528 * @see ISourceElementRequestor
530 public void exitConstructor(int declarationEnd) {
531 exitMember(declarationEnd);
534 // * @see ISourceElementRequestor
536 //public void exitField(int initializationStart, int declarationEnd, int declarationSourceEnd) {
537 // SourceFieldElementInfo info = (SourceFieldElementInfo) fInfoStack.pop();
538 // info.setSourceRangeEnd(declarationSourceEnd);
540 // // remember initializer source if field is a constant
541 // if (initializationStart != -1) {
542 // int flags = info.flags;
544 // if (Flags.isStatic(flags) && Flags.isFinal(flags)
545 // || ((typeInfo = fInfoStack.peek()) instanceof SourceTypeElementInfo
546 // && (Flags.isInterface(((SourceTypeElementInfo)typeInfo).flags)))) {
547 // int length = declarationEnd - initializationStart;
549 // char[] initializer = new char[length];
550 // System.arraycopy(this.parser.scanner.source, initializationStart, initializer, 0, length);
551 // info.initializationSource = initializer;
555 // fHandleStack.pop();
558 * @see ISourceElementRequestor
560 public void exitInitializer(int declarationEnd) {
561 exitMember(declarationEnd);
564 * @see ISourceElementRequestor
566 public void exitInterface(int declarationEnd) {
567 exitMember(declarationEnd);
570 * common processing for classes and interfaces
572 protected void exitMember(int declarationEnd) {
573 SourceRefElementInfo info = (SourceRefElementInfo) fInfoStack.pop();
574 info.setSourceRangeEnd(declarationEnd);
578 * @see ISourceElementRequestor
580 public void exitMethod(int declarationEnd) {
581 exitMember(declarationEnd);
585 * Resolves duplicate handles by incrementing the occurrence count
586 * of the handle being created until there is no conflict.
588 protected void resolveDuplicates(IJavaElement handle) {
589 while (fNewElements.containsKey(handle)) {
590 JavaElement h = (JavaElement) handle;
591 h.setOccurrenceCount(h.getOccurrenceCount() + 1);