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.compiler;
13 import java.util.ArrayList;
15 import net.sourceforge.phpdt.core.compiler.CharOperation;
16 import net.sourceforge.phpdt.core.compiler.IProblem;
17 import net.sourceforge.phpdt.internal.compiler.env.ICompilationUnit;
18 import net.sourceforge.phpdt.internal.compiler.env.ISourceType;
19 import net.sourceforge.phpdt.internal.compiler.impl.CompilerOptions;
20 import net.sourceforge.phpdt.internal.compiler.impl.ReferenceContext;
21 import net.sourceforge.phpdt.internal.compiler.lookup.BlockScope;
22 import net.sourceforge.phpdt.internal.compiler.lookup.ClassScope;
23 import net.sourceforge.phpdt.internal.compiler.problem.AbortCompilation;
24 import net.sourceforge.phpdt.internal.compiler.problem.ProblemReporter;
25 import net.sourceforge.phpdt.internal.core.util.CommentRecorderParser;
26 import net.sourceforge.phpeclipse.internal.compiler.ast.ASTNode;
27 import net.sourceforge.phpeclipse.internal.compiler.ast.AbstractMethodDeclaration;
28 import net.sourceforge.phpeclipse.internal.compiler.ast.AnonymousLocalTypeDeclaration;
29 import net.sourceforge.phpeclipse.internal.compiler.ast.Argument;
30 import net.sourceforge.phpeclipse.internal.compiler.ast.CompilationUnitDeclaration;
31 import net.sourceforge.phpeclipse.internal.compiler.ast.ConstructorDeclaration;
32 import net.sourceforge.phpeclipse.internal.compiler.ast.ExplicitConstructorCall;
33 import net.sourceforge.phpeclipse.internal.compiler.ast.FieldDeclaration;
34 import net.sourceforge.phpeclipse.internal.compiler.ast.ImportReference;
35 import net.sourceforge.phpeclipse.internal.compiler.ast.MethodDeclaration;
36 import net.sourceforge.phpeclipse.internal.compiler.ast.NameReference;
37 import net.sourceforge.phpeclipse.internal.compiler.ast.QualifiedAllocationExpression;
38 import net.sourceforge.phpeclipse.internal.compiler.ast.TypeDeclaration;
39 import net.sourceforge.phpeclipse.internal.compiler.ast.TypeReference;
42 * A source element parser extracts structural and reference information
43 * from a piece of source.
45 * also see @ISourceElementRequestor
47 * The structural investigation includes:
48 * - the package statement
50 * - top-level types: package member, member types (member types of member types...)
54 * If reference information is requested, then all source constructs are
55 * investigated and type, field & method references are provided as well.
57 * Any (parsing) problem encountered is also provided.
60 public class SourceElementParser extends CommentRecorderParser {//extends
63 ISourceElementRequestor requestor;
66 int lastFieldEndPosition;
67 ISourceType sourceType;
68 boolean reportReferenceInfo;
70 char[][] superTypeNames;
72 static final char[] JAVA_LANG_OBJECT = "java.lang.Object".toCharArray(); //$NON-NLS-1$
73 NameReference[] unknownRefs;
74 int unknownRefsCounter;
75 LocalDeclarationVisitor localDeclarationVisitor = null;
76 // CompilerOptions options;
79 * An ast visitor that visits local type declarations.
81 public class LocalDeclarationVisitor extends ASTVisitor {
82 public boolean visit(TypeDeclaration typeDeclaration, BlockScope scope) {
83 notifySourceElementRequestor(typeDeclaration, sourceType == null);
84 return false; // don't visit members as this was done during notifySourceElementRequestor(...)
86 public boolean visit(TypeDeclaration typeDeclaration, ClassScope scope) {
87 notifySourceElementRequestor(typeDeclaration, sourceType == null);
88 return false; // don't visit members as this was done during notifySourceElementRequestor(...)
93 public SourceElementParser(final ISourceElementRequestor requestor, IProblemFactory problemFactory, CompilerOptions options) {
94 // we want to notify all syntax error with the acceptProblem API
95 // To do so, we define the record method of the ProblemReporter
96 super( new ProblemReporter(DefaultErrorHandlingPolicies.exitAfterAllProblems(), options, problemFactory) {
97 public void record(IProblem problem, CompilationResult unitResult, ReferenceContext referenceContext) {
98 unitResult.record(problem, referenceContext);
99 if (requestor!=null) {
100 requestor.acceptProblem(problem);
105 // options.sourceLevel >= CompilerOptions.JDK1_4);
106 this.requestor = requestor;
107 typeNames = new char[4][];
108 superTypeNames = new char[4][];
110 this.options = options;
114 * @deprecated use SourceElementParser(ISourceElementRequestor,
115 * IProblemFactory, CompilerOptions)
117 public SourceElementParser(
118 final ISourceElementRequestor requestor,
119 IProblemFactory problemFactory) {
120 this(requestor, problemFactory, new CompilerOptions());
122 public SourceElementParser(
123 final ISourceElementRequestor requestor,
124 IProblemFactory problemFactory,
125 CompilerOptions options,
126 boolean reportLocalDeclarations) {
127 this(requestor, problemFactory, options);
128 if (reportLocalDeclarations) {
129 this.localDeclarationVisitor = new LocalDeclarationVisitor();
132 //public void checkAnnotation() {
133 // int firstCommentIndex = scanner.commentPtr;
135 // super.checkAnnotation();
137 // // modify the modifier source start to point at the first comment
138 // if (firstCommentIndex >= 0) {
139 // modifiersSourceStart = scanner.commentStarts[0];
142 //protected void classInstanceCreation(boolean alwaysQualified) {
144 // boolean previousFlag = reportReferenceInfo;
145 // reportReferenceInfo = false; // not to see the type reference reported in
146 // super call to getTypeReference(...)
147 // super.classInstanceCreation(alwaysQualified);
148 // reportReferenceInfo = previousFlag;
149 // if (reportReferenceInfo){
150 // AllocationExpression alloc =
151 // (AllocationExpression)expressionStack[expressionPtr];
152 // TypeReference typeRef = alloc.type;
153 // requestor.acceptConstructorReference(
154 // typeRef instanceof SingleTypeReference
155 // ? ((SingleTypeReference) typeRef).token
156 // : CharOperation.concatWith(alloc.type.getTypeName(), '.'),
157 // alloc.arguments == null ? 0 : alloc.arguments.length,
158 // alloc.sourceStart);
161 //protected void consumeConstructorHeaderName() {
162 // // ConstructorHeaderName ::= Modifiersopt 'Identifier' '('
164 // /* recovering - might be an empty message send */
165 // if (currentElement != null){
166 // if (lastIgnoredToken == TokenNamenew){ // was an allocation expression
167 // lastCheckPoint = scanner.startPosition; // force to restart at this exact
169 // restartRecovery = true;
173 // SourceConstructorDeclaration cd = new
174 // SourceConstructorDeclaration(this.compilationUnit.compilationResult);
176 // //name -- this is not really revelant but we do .....
177 // cd.selector = identifierStack[identifierPtr];
178 // long selectorSourcePositions = identifierPositionStack[identifierPtr--];
179 // identifierLengthPtr--;
182 // cd.declarationSourceStart = intStack[intPtr--];
183 // cd.modifiers = intStack[intPtr--];
185 // //highlight starts at the selector starts
186 // cd.sourceStart = (int) (selectorSourcePositions >>> 32);
187 // cd.selectorSourceEnd = (int) selectorSourcePositions;
188 // pushOnAstStack(cd);
190 // cd.sourceEnd = lParenPos;
191 // cd.bodyStart = lParenPos+1;
192 // listLength = 0; // initialize listLength before reading parameters/throws
195 // if (currentElement != null){
196 // lastCheckPoint = cd.bodyStart;
197 // if ((currentElement instanceof RecoveredType && lastIgnoredToken !=
199 // || cd.modifiers != 0){
200 // currentElement = currentElement.add(cd, 0);
201 // lastIgnoredToken = -1;
207 // * INTERNAL USE-ONLY
209 //protected void consumeExitVariableWithInitialization() {
210 // // ExitVariableWithInitialization ::= $empty
211 // // the scanner is located after the comma or the semi-colon.
212 // // we want to include the comma or the semi-colon
213 // super.consumeExitVariableWithInitialization();
214 // if (isLocalDeclaration() || ((currentToken != TokenNameCOMMA) &&
215 // (currentToken != TokenNameSEMICOLON)))
217 // ((SourceFieldDeclaration) astStack[astPtr]).fieldEndPosition =
218 // scanner.currentPosition - 1;
220 //protected void consumeExitVariableWithoutInitialization() {
221 // // ExitVariableWithoutInitialization ::= $empty
222 // // do nothing by default
223 // super.consumeExitVariableWithoutInitialization();
224 // if (isLocalDeclaration() || ((currentToken != TokenNameCOMMA) &&
225 // (currentToken != TokenNameSEMICOLON)))
227 // ((SourceFieldDeclaration) astStack[astPtr]).fieldEndPosition =
228 // scanner.currentPosition - 1;
232 // * INTERNAL USE-ONLY
234 //protected void consumeFieldAccess(boolean isSuperAccess) {
235 // // FieldAccess ::= Primary '.' 'Identifier'
236 // // FieldAccess ::= 'super' '.' 'Identifier'
237 // super.consumeFieldAccess(isSuperAccess);
238 // FieldReference fr = (FieldReference) expressionStack[expressionPtr];
239 // if (reportReferenceInfo) {
240 // requestor.acceptFieldReference(fr.token, fr.sourceStart);
243 //protected void consumeMethodHeaderName() {
244 // // MethodHeaderName ::= Modifiersopt Type 'Identifier' '('
245 // SourceMethodDeclaration md = new
246 // SourceMethodDeclaration(this.compilationUnit.compilationResult);
249 // md.selector = identifierStack[identifierPtr];
250 // long selectorSourcePositions = identifierPositionStack[identifierPtr--];
251 // identifierLengthPtr--;
253 // md.returnType = getTypeReference(intStack[intPtr--]);
255 // md.declarationSourceStart = intStack[intPtr--];
256 // md.modifiers = intStack[intPtr--];
258 // //highlight starts at selector start
259 // md.sourceStart = (int) (selectorSourcePositions >>> 32);
260 // md.selectorSourceEnd = (int) selectorSourcePositions;
261 // pushOnAstStack(md);
262 // md.sourceEnd = lParenPos;
263 // md.bodyStart = lParenPos+1;
264 // listLength = 0; // initialize listLength before reading parameters/throws
267 // if (currentElement != null){
268 // if (currentElement instanceof RecoveredType
269 // //|| md.modifiers != 0
270 // || (scanner.getLineNumber(md.returnType.sourceStart)
271 // == scanner.getLineNumber(md.sourceStart))){
272 // lastCheckPoint = md.bodyStart;
273 // currentElement = currentElement.add(md, 0);
274 // lastIgnoredToken = -1;
276 // lastCheckPoint = md.sourceStart;
277 // restartRecovery = true;
283 // * INTERNAL USE-ONLY
285 //protected void consumeMethodInvocationName() {
286 // // MethodInvocation ::= Name '(' ArgumentListopt ')'
288 // // when the name is only an identifier...we have a message send to "this"
290 // super.consumeMethodInvocationName();
291 // MessageSend messageSend = (MessageSend) expressionStack[expressionPtr];
292 // Expression[] args = messageSend.arguments;
293 // if (reportReferenceInfo) {
294 // requestor.acceptMethodReference(
295 // messageSend.selector,
296 // args == null ? 0 : args.length,
297 // (int)(messageSend.nameSourcePosition >>> 32));
302 // * INTERNAL USE-ONLY
304 //protected void consumeMethodInvocationPrimary() {
305 // super.consumeMethodInvocationPrimary();
306 // MessageSend messageSend = (MessageSend) expressionStack[expressionPtr];
307 // Expression[] args = messageSend.arguments;
308 // if (reportReferenceInfo) {
309 // requestor.acceptMethodReference(
310 // messageSend.selector,
311 // args == null ? 0 : args.length,
312 // (int)(messageSend.nameSourcePosition >>> 32));
317 // * INTERNAL USE-ONLY
319 //protected void consumeMethodInvocationSuper() {
320 // // MethodInvocation ::= 'super' '.' 'Identifier' '(' ArgumentListopt ')'
321 // super.consumeMethodInvocationSuper();
322 // MessageSend messageSend = (MessageSend) expressionStack[expressionPtr];
323 // Expression[] args = messageSend.arguments;
324 // if (reportReferenceInfo) {
325 // requestor.acceptMethodReference(
326 // messageSend.selector,
327 // args == null ? 0 : args.length,
328 // (int)(messageSend.nameSourcePosition >>> 32));
331 //protected void consumeSingleTypeImportDeclarationName() {
332 // // SingleTypeImportDeclarationName ::= 'import' Name
333 // /* push an ImportRef build from the last name
334 // stored in the identifier stack. */
336 // super.consumeSingleTypeImportDeclarationName();
337 // ImportReference impt = (ImportReference)astStack[astPtr];
338 // if (reportReferenceInfo) {
339 // requestor.acceptTypeReference(impt.tokens, impt.sourceStart,
343 //protected void consumeTypeImportOnDemandDeclarationName() {
344 // // TypeImportOnDemandDeclarationName ::= 'import' Name '.' '*'
345 // /* push an ImportRef build from the last name
346 // stored in the identifier stack. */
348 // super.consumeTypeImportOnDemandDeclarationName();
349 // ImportReference impt = (ImportReference)astStack[astPtr];
350 // if (reportReferenceInfo) {
351 // requestor.acceptUnknownReference(impt.tokens, impt.sourceStart,
355 //protected FieldDeclaration createFieldDeclaration(Expression
356 // initialization, char[] name, int sourceStart, int sourceEnd) {
357 // return new SourceFieldDeclaration(null, name, sourceStart, sourceEnd);
359 //protected CompilationUnitDeclaration endParse(int act) {
360 // if (sourceType != null) {
361 // if (sourceType.isInterface()) {
362 // consumeInterfaceDeclaration();
364 // consumeClassDeclaration();
367 // if (compilationUnit != null) {
368 // CompilationUnitDeclaration result = super.endParse(act);
375 * Flush annotations defined prior to a given positions.
377 * Note: annotations are stacked in syntactical order
379 * Either answer given <position>, or the end position of a comment line
380 * immediately following the <position> (same line)
382 * e.g. void foo(){ } // end of method foo
385 //public int flushAnnotationsDefinedPriorTo(int position) {
387 // return lastFieldEndPosition =
388 // super.flushAnnotationsDefinedPriorTo(position);
390 //public TypeReference getTypeReference(int dim) {
391 // /* build a Reference on a variable that may be qualified or not
392 // * This variable is a type reference and dim will be its dimensions
395 // if ((length = identifierLengthStack[identifierLengthPtr--]) == 1) {
396 // // single variable reference
398 // SingleTypeReference ref =
399 // new SingleTypeReference(
400 // identifierStack[identifierPtr],
401 // identifierPositionStack[identifierPtr--]);
402 // if (reportReferenceInfo) {
403 // requestor.acceptTypeReference(ref.token, ref.sourceStart);
407 // ArrayTypeReference ref =
408 // new ArrayTypeReference(
409 // identifierStack[identifierPtr],
411 // identifierPositionStack[identifierPtr--]);
412 // ref.sourceEnd = endPosition;
413 // if (reportReferenceInfo) {
414 // requestor.acceptTypeReference(ref.token, ref.sourceStart);
419 // if (length < 0) { //flag for precompiled type reference on base types
420 // TypeReference ref = TypeReference.baseTypeReference(-length, dim);
421 // ref.sourceStart = intStack[intPtr--];
423 // ref.sourceEnd = intStack[intPtr--];
425 // intPtr--; // no need to use this position as it is an array
426 // ref.sourceEnd = endPosition;
428 // if (reportReferenceInfo){
429 // requestor.acceptTypeReference(ref.getTypeName(), ref.sourceStart,
433 // } else { //Qualified variable reference
434 // char[][] tokens = new char[length][];
435 // identifierPtr -= length;
436 // long[] positions = new long[length];
437 // System.arraycopy(identifierStack, identifierPtr + 1, tokens, 0, length);
439 // identifierPositionStack,
440 // identifierPtr + 1,
445 // QualifiedTypeReference ref = new QualifiedTypeReference(tokens, positions);
446 // if (reportReferenceInfo) {
447 // requestor.acceptTypeReference(ref.tokens, ref.sourceStart, ref.sourceEnd);
451 // ArrayQualifiedTypeReference ref =
452 // new ArrayQualifiedTypeReference(tokens, dim, positions);
453 // ref.sourceEnd = endPosition;
454 // if (reportReferenceInfo) {
455 // requestor.acceptTypeReference(ref.tokens, ref.sourceStart, ref.sourceEnd);
462 //public NameReference getUnspecifiedReference() {
463 // /* build a (unspecified) NameReference which may be qualified*/
466 // if ((length = identifierLengthStack[identifierLengthPtr--]) == 1) {
467 // // single variable reference
468 // SingleNameReference ref =
469 // new SingleNameReference(
470 // identifierStack[identifierPtr],
471 // identifierPositionStack[identifierPtr--]);
472 // if (reportReferenceInfo) {
473 // this.addUnknownRef(ref);
477 // //Qualified variable reference
478 // char[][] tokens = new char[length][];
479 // identifierPtr -= length;
480 // System.arraycopy(identifierStack, identifierPtr + 1, tokens, 0, length);
481 // QualifiedNameReference ref =
482 // new QualifiedNameReference(
484 // (int) (identifierPositionStack[identifierPtr + 1] >> 32), // sourceStart
485 // (int) identifierPositionStack[identifierPtr + length]); // sourceEnd
486 // if (reportReferenceInfo) {
487 // this.addUnknownRef(ref);
492 //public NameReference getUnspecifiedReferenceOptimized() {
493 // /* build a (unspecified) NameReference which may be qualified
494 // The optimization occurs for qualified reference while we are
495 // certain in this case the last item of the qualified name is
496 // a field access. This optimization is IMPORTANT while it results
497 // that when a NameReference is build, the type checker should always
498 // look for that it is not a type reference */
501 // if ((length = identifierLengthStack[identifierLengthPtr--]) == 1) {
502 // // single variable reference
503 // SingleNameReference ref =
504 // new SingleNameReference(
505 // identifierStack[identifierPtr],
506 // identifierPositionStack[identifierPtr--]);
507 // ref.bits &= ~ASTNode.RestrictiveFlagMASK;
508 // ref.bits |= LOCAL | FIELD;
509 // if (reportReferenceInfo) {
510 // this.addUnknownRef(ref);
515 // //Qualified-variable-reference
516 // //In fact it is variable-reference DOT field-ref , but it would result in a
518 // //conflict tha can be only reduce by making a superclass (or inetrface )
520 // //nameReference and FiledReference or putting FieldReference under
522 // //or else..........This optimisation is not really relevant so just leave
525 // char[][] tokens = new char[length][];
526 // identifierPtr -= length;
527 // System.arraycopy(identifierStack, identifierPtr + 1, tokens, 0, length);
528 // QualifiedNameReference ref =
529 // new QualifiedNameReference(
531 // (int) (identifierPositionStack[identifierPtr + 1] >> 32),
533 // (int) identifierPositionStack[identifierPtr + length]); // sourceEnd
534 // ref.bits &= ~ASTNode.RestrictiveFlagMASK;
535 // ref.bits |= LOCAL | FIELD;
536 // if (reportReferenceInfo) {
537 // this.addUnknownRef(ref);
543 // * INTERNAL USE-ONLY
545 //private boolean isLocalDeclaration() {
546 // int nestedDepth = nestedType;
547 // while (nestedDepth >= 0) {
548 // if (nestedMethod[nestedDepth] != 0) {
556 * Update the bodyStart of the corresponding parse node
558 public void notifySourceElementRequestor(CompilationUnitDeclaration parsedUnit) {
559 if (parsedUnit == null) {
560 // when we parse a single type member declaration the compilation unit is
561 // null, but we still
562 // want to be able to notify the requestor on the created ast node
563 if (astStack[0] instanceof AbstractMethodDeclaration) {
564 notifySourceElementRequestor((AbstractMethodDeclaration) astStack[0]);
570 boolean isInRange = scanner.initialPosition <= parsedUnit.sourceStart && scanner.eofPosition >= parsedUnit.sourceEnd;
572 // if (reportReferenceInfo) {
573 // notifyAllUnknownReferences();
575 // collect the top level ast nodes
577 ASTNode[] nodes = null;
578 if (sourceType == null) {
580 requestor.enterCompilationUnit();
582 // ImportReference currentPackage = parsedUnit.currentPackage;
583 ImportReference[] imports = parsedUnit.imports;
584 // TypeDeclaration[] types = parsedUnit.types;
585 ArrayList types = parsedUnit.types;
588 // (currentPackage == null ? 0 : 1)
589 // + (imports == null ? 0 : imports.length)
590 // + (types == null ? 0 : types.length);
591 // nodes = new ASTNode[length];
592 length = (imports == null ? 0 : imports.length) + types.size();
593 nodes = new ASTNode[length];
595 // if (currentPackage != null) {
596 // nodes[index++] = currentPackage;
598 if (imports != null) {
599 for (int i = 0, max = imports.length; i < max; i++) {
600 nodes[index++] = imports[i];
604 for (int i = 0, max = types.size(); i < max; i++) {
605 nodes[index++] = (ASTNode) types.get(i);
609 // TypeDeclaration[] types = parsedUnit.types;
610 ArrayList types = parsedUnit.types;
612 length = types.size();
613 nodes = new ASTNode[length];
614 for (int i = 0, max = types.size(); i < max; i++) {
615 nodes[i] = (ASTNode) types.get(i);
620 // notify the nodes in the syntactical order
621 if (nodes != null && length > 0) {
622 quickSort(nodes, 0, length - 1);
623 for (int i = 0; i < length; i++) {
624 ASTNode node = nodes[i];
625 if (node instanceof ImportReference) {
626 ImportReference importRef = (ImportReference)node;
627 // if (node == parsedUnit.currentPackage) {
628 // notifySourceElementRequestor(importRef, true);
630 notifySourceElementRequestor(importRef, false);
632 } //else { instanceof TypeDeclaration
633 if (node instanceof TypeDeclaration) {
634 notifySourceElementRequestor((TypeDeclaration) node, sourceType == null);
635 // notifySourceElementRequestor((CompilationUnitDeclaration)node,
636 // sourceType == null);
638 // jsurfer - INSERT start
639 if (node instanceof AbstractMethodDeclaration) {
640 notifySourceElementRequestor((AbstractMethodDeclaration) node);
642 // jsurfer - INSERT end
646 if (sourceType == null) {
648 requestor.exitCompilationUnit(parsedUnit.sourceEnd);
653 //private void notifyAllUnknownReferences() {
654 // for (int i = 0, max = this.unknownRefsCounter; i < max; i++) {
655 // NameReference nameRef = this.unknownRefs[i];
656 // if ((nameRef.bits & BindingIds.VARIABLE) != 0) {
657 // if ((nameRef.bits & BindingIds.TYPE) == 0) {
658 // // variable but not type
659 // if (nameRef instanceof SingleNameReference) {
660 // // local var or field
661 // requestor.acceptUnknownReference(((SingleNameReference) nameRef).token,
662 // nameRef.sourceStart);
664 // // QualifiedNameReference
665 // // The last token is a field reference and the previous tokens are a
666 // type/variable references
667 // char[][] tokens = ((QualifiedNameReference) nameRef).tokens;
668 // int tokensLength = tokens.length;
669 // requestor.acceptFieldReference(tokens[tokensLength - 1], nameRef.sourceEnd
670 // - tokens[tokensLength - 1].length + 1);
671 // char[][] typeRef = new char[tokensLength - 1][];
672 // System.arraycopy(tokens, 0, typeRef, 0, tokensLength - 1);
673 // requestor.acceptUnknownReference(typeRef, nameRef.sourceStart,
674 // nameRef.sourceEnd - tokens[tokensLength - 1].length);
677 // // variable or type
678 // if (nameRef instanceof SingleNameReference) {
679 // requestor.acceptUnknownReference(((SingleNameReference) nameRef).token,
680 // nameRef.sourceStart);
682 // //QualifiedNameReference
683 // requestor.acceptUnknownReference(((QualifiedNameReference) nameRef).tokens,
684 // nameRef.sourceStart, nameRef.sourceEnd);
687 // } else if ((nameRef.bits & BindingIds.TYPE) != 0) {
688 // if (nameRef instanceof SingleNameReference) {
689 // requestor.acceptTypeReference(((SingleNameReference) nameRef).token,
690 // nameRef.sourceStart);
692 // // it is a QualifiedNameReference
693 // requestor.acceptTypeReference(((QualifiedNameReference) nameRef).tokens,
694 // nameRef.sourceStart, nameRef.sourceEnd);
700 * Update the bodyStart of the corresponding parse node
702 public void notifySourceElementRequestor(AbstractMethodDeclaration methodDeclaration) {
705 boolean isInRange = scanner.initialPosition <= methodDeclaration.declarationSourceStart
706 && scanner.eofPosition >= methodDeclaration.declarationSourceEnd;
708 if (methodDeclaration.isClinit()) {
709 this.visitIfNeeded(methodDeclaration);
713 if (methodDeclaration.isDefaultConstructor()) {
714 if (reportReferenceInfo) {
715 ConstructorDeclaration constructorDeclaration = (ConstructorDeclaration) methodDeclaration;
716 ExplicitConstructorCall constructorCall = constructorDeclaration.constructorCall;
717 if (constructorCall != null) {
718 switch (constructorCall.accessMode) {
719 case ExplicitConstructorCall.This :
720 requestor.acceptConstructorReference(typeNames[nestedTypeIndex - 1], constructorCall.arguments == null
722 : constructorCall.arguments.length, constructorCall.sourceStart);
724 case ExplicitConstructorCall.Super :
725 case ExplicitConstructorCall.ImplicitSuper :
726 requestor.acceptConstructorReference(superTypeNames[nestedTypeIndex - 1], constructorCall.arguments == null
728 : constructorCall.arguments.length, constructorCall.sourceStart);
735 char[][] argumentTypes = null;
736 char[][] argumentNames = null;
737 Argument[] arguments = methodDeclaration.arguments;
738 if (arguments != null) {
739 int argumentLength = arguments.length;
740 argumentTypes = new char[argumentLength][];
741 argumentNames = new char[argumentLength][];
742 for (int i = 0; i < argumentLength; i++) {
743 argumentTypes[i] = returnTypeName(arguments[i].type);
744 argumentNames[i] = arguments[i].name;
747 char[][] thrownExceptionTypes = null;
748 TypeReference[] thrownExceptions = methodDeclaration.thrownExceptions;
749 if (thrownExceptions != null) {
750 int thrownExceptionLength = thrownExceptions.length;
751 thrownExceptionTypes = new char[thrownExceptionLength][];
752 for (int i = 0; i < thrownExceptionLength; i++) {
753 thrownExceptionTypes[i] = CharOperation.concatWith(thrownExceptions[i].getTypeName(), '.');
756 // by default no selector end position
757 int selectorSourceEnd = -1;
758 if (methodDeclaration.isConstructor()) {
759 // if (methodDeclaration instanceof SourceConstructorDeclaration) {
760 // selectorSourceEnd =
761 // ((SourceConstructorDeclaration) methodDeclaration).selectorSourceEnd;
764 requestor.enterConstructor(methodDeclaration.declarationSourceStart, methodDeclaration.modifiers,
765 methodDeclaration.selector, methodDeclaration.sourceStart, selectorSourceEnd, argumentTypes, argumentNames,
766 thrownExceptionTypes);
768 if (reportReferenceInfo) {
769 ConstructorDeclaration constructorDeclaration = (ConstructorDeclaration) methodDeclaration;
770 ExplicitConstructorCall constructorCall = constructorDeclaration.constructorCall;
771 if (constructorCall != null) {
772 switch (constructorCall.accessMode) {
773 case ExplicitConstructorCall.This :
774 requestor.acceptConstructorReference(typeNames[nestedTypeIndex - 1], constructorCall.arguments == null
776 : constructorCall.arguments.length, constructorCall.sourceStart);
778 case ExplicitConstructorCall.Super :
779 case ExplicitConstructorCall.ImplicitSuper :
780 requestor.acceptConstructorReference(superTypeNames[nestedTypeIndex - 1], constructorCall.arguments == null
782 : constructorCall.arguments.length, constructorCall.sourceStart);
787 this.visitIfNeeded(methodDeclaration);
789 requestor.exitConstructor(methodDeclaration.declarationSourceEnd);
793 // if (methodDeclaration instanceof SourceMethodDeclaration) {
794 // selectorSourceEnd =
795 // ((SourceMethodDeclaration) methodDeclaration).selectorSourceEnd;
798 int modifiers = methodDeclaration.modifiers;
799 // boolean deprecated = (modifiers & AccDeprecated) != 0; // remember
800 // deprecation so as to not lose it below
801 requestor.enterMethod(methodDeclaration.declarationSourceStart, modifiers, // deprecated
812 returnTypeName(((MethodDeclaration) methodDeclaration).returnType), methodDeclaration.selector,
813 methodDeclaration.sourceStart, selectorSourceEnd, argumentTypes, argumentNames, thrownExceptionTypes);
815 this.visitIfNeeded(methodDeclaration);
818 requestor.exitMethod(methodDeclaration.declarationSourceEnd);
822 * Update the bodyStart of the corresponding parse node
824 public void notifySourceElementRequestor(FieldDeclaration fieldDeclaration) {
827 boolean isInRange = scanner.initialPosition <= fieldDeclaration.declarationSourceStart
828 && scanner.eofPosition >= fieldDeclaration.declarationSourceEnd;
830 if (fieldDeclaration.isField()) {
831 int fieldEndPosition = fieldDeclaration.declarationSourceEnd;
832 // if (fieldDeclaration instanceof SourceFieldDeclaration) {
833 // fieldEndPosition = ((SourceFieldDeclaration)
834 // fieldDeclaration).fieldEndPosition;
835 // if (fieldEndPosition == 0) {
836 // // use the declaration source end by default
837 // fieldEndPosition = fieldDeclaration.declarationSourceEnd;
841 int modifiers = fieldDeclaration.modifiers;
842 boolean deprecated = (modifiers & AccDeprecated) != 0; // remember
846 requestor.enterField(fieldDeclaration.declarationSourceStart, deprecated
847 ? (modifiers & AccJustFlag) | AccDeprecated
848 : modifiers & AccJustFlag, returnTypeName(fieldDeclaration.type), fieldDeclaration.name, fieldDeclaration.sourceStart,
849 fieldDeclaration.sourceEnd);
851 // this.visitIfNeeded(fieldDeclaration);
853 // requestor.exitField(
854 // // filter out initializations that are not a constant (simple check)
855 // (fieldDeclaration.initialization == null
856 // || fieldDeclaration.initialization instanceof ArrayInitializer
857 // || fieldDeclaration.initialization instanceof AllocationExpression
858 // || fieldDeclaration.initialization instanceof
859 // ArrayAllocationExpression
860 // || fieldDeclaration.initialization instanceof Assignment
861 // || fieldDeclaration.initialization instanceof ClassLiteralAccess
862 // || fieldDeclaration.initialization instanceof MessageSend
863 // || fieldDeclaration.initialization instanceof ArrayReference
864 // || fieldDeclaration.initialization instanceof ThisReference) ?
866 // fieldDeclaration.initialization.sourceStart,
868 // fieldDeclaration.declarationSourceEnd);
870 // filter out initializations that are not a constant (simple check)
871 -1, fieldEndPosition, fieldDeclaration.declarationSourceEnd);
876 // requestor.enterInitializer(
877 // fieldDeclaration.declarationSourceStart,
878 // fieldDeclaration.modifiers);
880 // this.visitIfNeeded((Initializer)fieldDeclaration);
882 // requestor.exitInitializer(fieldDeclaration.declarationSourceEnd);
886 public void notifySourceElementRequestor(
887 ImportReference importReference,
890 // requestor.acceptPackage(
891 // importReference.declarationSourceStart,
892 // importReference.declarationSourceEnd,
893 // CharOperation.concatWith(importReference.getImportName(), '.'));
895 requestor.acceptImport(
896 importReference.declarationSourceStart,
897 importReference.declarationSourceEnd,
898 importReference.getIncludeName(), //CharOperation.concatWith(importReference.getImportName(), '.'),
899 importReference.onDemand);
902 public void notifySourceElementRequestor(TypeDeclaration typeDeclaration, boolean notifyTypePresence) {
903 //// public void notifySourceElementRequestor(ASTNode typeDeclaration,
904 // boolean notifyTypePresence) {
907 boolean isInRange = scanner.initialPosition <= typeDeclaration.declarationSourceStart
908 && scanner.eofPosition >= typeDeclaration.declarationSourceEnd;
910 FieldDeclaration[] fields = typeDeclaration.fields;
911 AbstractMethodDeclaration[] methods = typeDeclaration.methods;
912 TypeDeclaration[] memberTypes = typeDeclaration.memberTypes;
913 int fieldCount = fields == null ? 0 : fields.length;
914 int methodCount = methods == null ? 0 : methods.length;
915 int memberTypeCount = memberTypes == null ? 0 : memberTypes.length;
918 int memberTypeIndex = 0;
919 boolean isInterface = typeDeclaration.isInterface();
921 if (notifyTypePresence) {
922 char[][] interfaceNames = null;
923 int superInterfacesLength = 0;
924 TypeReference[] superInterfaces = typeDeclaration.superInterfaces;
925 if (superInterfaces != null) {
926 superInterfacesLength = superInterfaces.length;
927 interfaceNames = new char[superInterfacesLength][];
929 if (typeDeclaration instanceof AnonymousLocalTypeDeclaration) {
931 QualifiedAllocationExpression alloc = ((AnonymousLocalTypeDeclaration) typeDeclaration).allocation;
932 if (alloc != null && alloc.type != null) {
933 superInterfaces = new TypeReference[]{((AnonymousLocalTypeDeclaration) typeDeclaration).allocation.type};
934 superInterfacesLength = 1;
935 interfaceNames = new char[1][];
939 if (superInterfaces != null) {
940 for (int i = 0; i < superInterfacesLength; i++) {
941 interfaceNames[i] = CharOperation.concatWith(superInterfaces[i].getTypeName(), '.');
946 int modifiers = typeDeclaration.modifiers;
947 boolean deprecated = false; //(modifiers & AccDeprecated) != 0; //
948 // remember deprecation so as to not lose
950 requestor.enterInterface(typeDeclaration.declarationSourceStart, modifiers, //deprecated
961 typeDeclaration.name, typeDeclaration.sourceStart, typeDeclaration.sourceEnd, interfaceNames);
963 if (nestedTypeIndex == typeNames.length) {
965 System.arraycopy(typeNames, 0, (typeNames = new char[nestedTypeIndex * 2][]), 0, nestedTypeIndex);
966 System.arraycopy(superTypeNames, 0, (superTypeNames = new char[nestedTypeIndex * 2][]), 0, nestedTypeIndex);
968 typeNames[nestedTypeIndex] = typeDeclaration.name;
969 superTypeNames[nestedTypeIndex++] = JAVA_LANG_OBJECT;
971 TypeReference superclass = typeDeclaration.superclass;
972 if (superclass == null) {
974 requestor.enterClass(typeDeclaration.declarationSourceStart, typeDeclaration.modifiers, typeDeclaration.name,
975 typeDeclaration.sourceStart, typeDeclaration.sourceEnd, null, interfaceNames);
979 requestor.enterClass(typeDeclaration.declarationSourceStart, typeDeclaration.modifiers, typeDeclaration.name,
980 typeDeclaration.sourceStart, typeDeclaration.sourceEnd, CharOperation.concatWith(superclass.getTypeName(), '.'),
984 if (nestedTypeIndex == typeNames.length) {
986 System.arraycopy(typeNames, 0, (typeNames = new char[nestedTypeIndex * 2][]), 0, nestedTypeIndex);
987 System.arraycopy(superTypeNames, 0, (superTypeNames = new char[nestedTypeIndex * 2][]), 0, nestedTypeIndex);
989 typeNames[nestedTypeIndex] = typeDeclaration.name;
990 superTypeNames[nestedTypeIndex++] = superclass == null ? JAVA_LANG_OBJECT : CharOperation.concatWith(superclass
991 .getTypeName(), '.');
994 while ((fieldIndex < fieldCount) || (memberTypeIndex < memberTypeCount) || (methodIndex < methodCount)) {
995 FieldDeclaration nextFieldDeclaration = null;
996 AbstractMethodDeclaration nextMethodDeclaration = null;
997 TypeDeclaration nextMemberDeclaration = null;
999 int position = Integer.MAX_VALUE;
1000 int nextDeclarationType = -1;
1001 if (fieldIndex < fieldCount) {
1002 nextFieldDeclaration = fields[fieldIndex];
1003 if (nextFieldDeclaration.declarationSourceStart < position) {
1004 position = nextFieldDeclaration.declarationSourceStart;
1005 nextDeclarationType = 0; // FIELD
1008 if (methodIndex < methodCount) {
1009 nextMethodDeclaration = methods[methodIndex];
1010 if (nextMethodDeclaration.declarationSourceStart < position) {
1011 position = nextMethodDeclaration.declarationSourceStart;
1012 nextDeclarationType = 1; // METHOD
1015 if (memberTypeIndex < memberTypeCount) {
1016 nextMemberDeclaration = memberTypes[memberTypeIndex];
1017 if (nextMemberDeclaration.declarationSourceStart < position) {
1018 position = nextMemberDeclaration.declarationSourceStart;
1019 nextDeclarationType = 2; // MEMBER
1022 switch (nextDeclarationType) {
1025 notifySourceElementRequestor(nextFieldDeclaration);
1029 notifySourceElementRequestor(nextMethodDeclaration);
1033 notifySourceElementRequestor(nextMemberDeclaration, true);
1036 if (notifyTypePresence) {
1039 requestor.exitInterface(typeDeclaration.declarationSourceEnd);
1041 requestor.exitClass(typeDeclaration.declarationSourceEnd);
1047 public void parseCompilationUnit(ICompilationUnit unit, int start, int end) {
1048 // boolean needReferenceInfo) {
1050 // reportReferenceInfo = needReferenceInfo;
1051 // boolean old = diet;
1052 // if (needReferenceInfo) {
1053 // unknownRefs = new NameReference[10];
1054 // unknownRefsCounter = 0;
1059 CompilationResult compilationUnitResult = new CompilationResult(unit, 0, 0, 10); //this.options.maxProblemsPerUnit);
1060 CompilationUnitDeclaration parsedUnit = parse(unit, compilationUnitResult, start, end);
1061 // if (scanner.recordLineSeparator) {
1062 // requestor.acceptLineSeparatorPositions(scanner.getLineEnds());
1064 // if (this.localDeclarationVisitor != null || needReferenceInfo){
1066 // this.getMethodBodies(parsedUnit);
1068 // this.scanner.resetTo(start, end);
1069 // notifySourceElementRequestor(parsedUnit);
1070 } catch (AbortCompilation e) {
1075 public CompilationUnitDeclaration parseCompilationUnit(ICompilationUnit unit, boolean fullParse) {
1077 // boolean old = diet;
1079 // unknownRefs = new NameReference[10];
1080 // unknownRefsCounter = 0;
1085 this.reportReferenceInfo = fullParse;
1086 CompilationResult compilationUnitResult = new CompilationResult(unit, 0, 0, this.options.maxProblemsPerUnit);
1087 CompilationUnitDeclaration parsedUnit = parse(unit, compilationUnitResult, false);
1088 if (scanner.recordLineSeparator) {
1089 requestor.acceptLineSeparatorPositions(scanner.getLineEnds());
1091 int initialStart = this.scanner.initialPosition;
1092 int initialEnd = this.scanner.eofPosition;
1093 // if (this.localDeclarationVisitor != null || fullParse){
1095 // this.getMethodBodies(parsedUnit);
1097 this.scanner.resetTo(initialStart, initialEnd);
1098 notifySourceElementRequestor(parsedUnit);
1100 } catch (AbortCompilation e) {
1101 // ignore this exception
1108 public CompilationUnitDeclaration parseCompletionUnit(ICompilationUnit unit, boolean fullParse) {
1110 // boolean old = diet;
1112 // unknownRefs = new NameReference[10];
1113 // unknownRefsCounter = 0;
1118 this.reportReferenceInfo = fullParse;
1119 CompilationResult compilationUnitResult = new CompilationResult(unit, 0, 0, this.options.maxProblemsPerUnit);
1120 CompilationUnitDeclaration parsedUnit = parse(unit, compilationUnitResult, false);
1121 // if (scanner.recordLineSeparator) {
1122 // requestor.acceptLineSeparatorPositions(scanner.getLineEnds());
1124 // int initialStart = this.scanner.initialPosition;
1125 // int initialEnd = this.scanner.eofPosition;
1126 // // if (this.localDeclarationVisitor != null || fullParse){
1128 // // this.getMethodBodies(parsedUnit);
1130 // this.scanner.resetTo(initialStart, initialEnd);
1131 // notifySourceElementRequestor(parsedUnit);
1133 } catch (AbortCompilation e) {
1134 // ignore this exception
1140 //public void parseTypeMemberDeclarations(
1141 // ISourceType sourceType,
1142 // ICompilationUnit sourceUnit,
1145 // boolean needReferenceInfo) {
1146 // boolean old = diet;
1147 // if (needReferenceInfo) {
1148 // unknownRefs = new NameReference[10];
1149 // unknownRefsCounter = 0;
1153 // diet = !needReferenceInfo;
1154 // reportReferenceInfo = needReferenceInfo;
1155 // CompilationResult compilationUnitResult =
1156 // new CompilationResult(sourceUnit, 0, 0, this.options.maxProblemsPerUnit);
1157 // CompilationUnitDeclaration unit =
1158 // SourceTypeConverter.buildCompilationUnit(
1159 // new ISourceType[]{sourceType},
1160 // false, // no need for field and methods
1161 // false, // no need for member types
1162 // false, // no need for field initialization
1163 // problemReporter(),
1164 // compilationUnitResult);
1165 // if ((unit == null) || (unit.types == null) || (unit.types.length != 1))
1167 // this.sourceType = sourceType;
1169 // /* automaton initialization */
1171 // goForClassBodyDeclarations();
1172 // /* scanner initialization */
1173 // scanner.setSource(sourceUnit.getContents());
1174 // scanner.resetTo(start, end);
1175 // /* unit creation */
1176 // referenceContext = compilationUnit = unit;
1177 // /* initialize the astStacl */
1178 // // the compilationUnitDeclaration should contain exactly one type
1179 // pushOnAstStack(unit.types[0]);
1180 // /* run automaton */
1182 // notifySourceElementRequestor(unit);
1184 // unit = compilationUnit;
1185 // compilationUnit = null; // reset parser
1187 // } catch (AbortCompilation e) {
1189 // if (scanner.recordLineSeparator) {
1190 // requestor.acceptLineSeparatorPositions(scanner.getLineEnds());
1196 //public void parseTypeMemberDeclarations(
1201 // boolean old = diet;
1206 // /* automaton initialization */
1208 // goForClassBodyDeclarations();
1209 // /* scanner initialization */
1210 // scanner.setSource(contents);
1211 // scanner.recordLineSeparator = false;
1212 // scanner.taskTags = null;
1213 // scanner.taskPriorities = null;
1214 // scanner.resetTo(start, end);
1216 // /* unit creation */
1217 // referenceContext = null;
1219 // /* initialize the astStacl */
1220 // // the compilationUnitDeclaration should contain exactly one type
1221 // /* run automaton */
1223 // notifySourceElementRequestor((CompilationUnitDeclaration)null);
1224 // } catch (AbortCompilation e) {
1230 * Sort the given ast nodes by their positions.
1232 private static void quickSort(ASTNode[] sortedCollection, int left, int right) {
1233 int original_left = left;
1234 int original_right = right;
1235 ASTNode mid = sortedCollection[(left + right) / 2];
1237 while (sortedCollection[left].sourceStart < mid.sourceStart) {
1240 while (mid.sourceStart < sortedCollection[right].sourceStart) {
1243 if (left <= right) {
1244 ASTNode tmp = sortedCollection[left];
1245 sortedCollection[left] = sortedCollection[right];
1246 sortedCollection[right] = tmp;
1250 } while (left <= right);
1251 if (original_left < right) {
1252 quickSort(sortedCollection, original_left, right);
1254 if (left < original_right) {
1255 quickSort(sortedCollection, left, original_right);
1259 * Answer a char array representation of the type name formatted like: - type
1260 * name + dimensions Example: "A[][]".toCharArray()
1261 * "java.lang.String".toCharArray()
1263 private char[] returnTypeName(TypeReference type) {
1266 int dimension = type.dimensions();
1267 if (dimension != 0) {
1268 char[] dimensionsArray = new char[dimension * 2];
1269 for (int i = 0; i < dimension; i++) {
1270 dimensionsArray[i * 2] = '[';
1271 dimensionsArray[(i * 2) + 1] = ']';
1273 return CharOperation.concat(CharOperation.concatWith(type.getTypeName(), '.'), dimensionsArray);
1275 return CharOperation.concatWith(type.getTypeName(), '.');
1278 public void addUnknownRef(NameReference nameRef) {
1279 if (this.unknownRefs.length == this.unknownRefsCounter) {
1281 System.arraycopy(this.unknownRefs, 0, (this.unknownRefs = new NameReference[this.unknownRefsCounter * 2]), 0,
1282 this.unknownRefsCounter);
1284 this.unknownRefs[this.unknownRefsCounter++] = nameRef;
1287 private void visitIfNeeded(AbstractMethodDeclaration method) {
1288 if (this.localDeclarationVisitor != null && (method.bits & ASTNode.HasLocalTypeMASK) != 0) {
1289 if (method.statements != null) {
1290 int statementsLength = method.statements.length;
1291 for (int i = 0; i < statementsLength; i++)
1292 method.statements[i].traverse(this.localDeclarationVisitor, method.scope);
1297 //private void visitIfNeeded(FieldDeclaration field) {
1298 // if (this.localDeclarationVisitor != null
1299 // && (field.bits & ASTNode.HasLocalTypeMASK) != 0) {
1300 // if (field.initialization != null) {
1301 // field.initialization.traverse(this.localDeclarationVisitor, null);
1306 //private void visitIfNeeded(Initializer initializer) {
1307 // if (this.localDeclarationVisitor != null
1308 // && (initializer.bits & ASTNode.HasLocalTypeMASK) != 0) {
1309 // if (initializer.block != null) {
1310 // initializer.block.traverse(this.localDeclarationVisitor, null);
1315 //protected void reportSyntaxError(int act, int currentKind, int
1317 // if (compilationUnit == null) return;
1318 // super.reportSyntaxError(act, currentKind,stateStackTop);
1320 protected CompilationUnitDeclaration endParse(int act) {
1321 // if (sourceType != null) {
1322 // if (sourceType.isInterface()) {
1323 // consumeInterfaceDeclaration();
1325 // consumeClassDeclaration();
1328 if (compilationUnit != null) {
1329 CompilationUnitDeclaration result = super.endParse(act);