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.MemberTypeDeclaration;
36 import net.sourceforge.phpeclipse.internal.compiler.ast.MethodDeclaration;
37 import net.sourceforge.phpeclipse.internal.compiler.ast.NameReference;
38 import net.sourceforge.phpeclipse.internal.compiler.ast.QualifiedAllocationExpression;
39 import net.sourceforge.phpeclipse.internal.compiler.ast.TypeDeclaration;
40 import net.sourceforge.phpeclipse.internal.compiler.ast.TypeReference;
43 * A source element parser extracts structural and reference information
44 * from a piece of source.
46 * also see @ISourceElementRequestor
48 * The structural investigation includes:
49 * - the package statement
51 * - top-level types: package member, member types (member types of member types...)
55 * If reference information is requested, then all source constructs are
56 * investigated and type, field & method references are provided as well.
58 * Any (parsing) problem encountered is also provided.
61 public class SourceElementParser extends CommentRecorderParser {//extends
64 ISourceElementRequestor requestor;
67 int lastFieldEndPosition;
68 ISourceType sourceType;
69 boolean reportReferenceInfo;
71 char[][] superTypeNames;
73 static final char[] JAVA_LANG_OBJECT = "java.lang.Object".toCharArray(); //$NON-NLS-1$
74 NameReference[] unknownRefs;
75 int unknownRefsCounter;
76 LocalDeclarationVisitor localDeclarationVisitor = null;
77 // CompilerOptions options;
80 * An ast visitor that visits local type declarations.
82 public class LocalDeclarationVisitor extends ASTVisitor {
83 public boolean visit(TypeDeclaration typeDeclaration, BlockScope scope) {
84 notifySourceElementRequestor(typeDeclaration, sourceType == null);
85 return false; // don't visit members as this was done during notifySourceElementRequestor(...)
87 public boolean visit(TypeDeclaration typeDeclaration, ClassScope scope) {
88 notifySourceElementRequestor(typeDeclaration, sourceType == null);
89 return false; // don't visit members as this was done during notifySourceElementRequestor(...)
94 public SourceElementParser(final ISourceElementRequestor requestor, IProblemFactory problemFactory, CompilerOptions options) {
95 // we want to notify all syntax error with the acceptProblem API
96 // To do so, we define the record method of the ProblemReporter
97 super( new ProblemReporter(DefaultErrorHandlingPolicies.exitAfterAllProblems(), options, problemFactory) {
98 public void record(IProblem problem, CompilationResult unitResult, ReferenceContext referenceContext) {
99 unitResult.record(problem, referenceContext);
100 if (requestor!=null) {
101 requestor.acceptProblem(problem);
106 // options.sourceLevel >= CompilerOptions.JDK1_4);
107 this.requestor = requestor;
108 typeNames = new char[4][];
109 superTypeNames = new char[4][];
111 this.options = options;
115 * @deprecated use SourceElementParser(ISourceElementRequestor,
116 * IProblemFactory, CompilerOptions)
118 public SourceElementParser(
119 final ISourceElementRequestor requestor,
120 IProblemFactory problemFactory) {
121 this(requestor, problemFactory, new CompilerOptions());
123 public SourceElementParser(
124 final ISourceElementRequestor requestor,
125 IProblemFactory problemFactory,
126 CompilerOptions options,
127 boolean reportLocalDeclarations) {
128 this(requestor, problemFactory, options);
129 if (reportLocalDeclarations) {
130 this.localDeclarationVisitor = new LocalDeclarationVisitor();
133 //public void checkAnnotation() {
134 // int firstCommentIndex = scanner.commentPtr;
136 // super.checkAnnotation();
138 // // modify the modifier source start to point at the first comment
139 // if (firstCommentIndex >= 0) {
140 // modifiersSourceStart = scanner.commentStarts[0];
143 //protected void classInstanceCreation(boolean alwaysQualified) {
145 // boolean previousFlag = reportReferenceInfo;
146 // reportReferenceInfo = false; // not to see the type reference reported in
147 // super call to getTypeReference(...)
148 // super.classInstanceCreation(alwaysQualified);
149 // reportReferenceInfo = previousFlag;
150 // if (reportReferenceInfo){
151 // AllocationExpression alloc =
152 // (AllocationExpression)expressionStack[expressionPtr];
153 // TypeReference typeRef = alloc.type;
154 // requestor.acceptConstructorReference(
155 // typeRef instanceof SingleTypeReference
156 // ? ((SingleTypeReference) typeRef).token
157 // : CharOperation.concatWith(alloc.type.getTypeName(), '.'),
158 // alloc.arguments == null ? 0 : alloc.arguments.length,
159 // alloc.sourceStart);
162 //protected void consumeConstructorHeaderName() {
163 // // ConstructorHeaderName ::= Modifiersopt 'Identifier' '('
165 // /* recovering - might be an empty message send */
166 // if (currentElement != null){
167 // if (lastIgnoredToken == TokenNamenew){ // was an allocation expression
168 // lastCheckPoint = scanner.startPosition; // force to restart at this exact
170 // restartRecovery = true;
174 // SourceConstructorDeclaration cd = new
175 // SourceConstructorDeclaration(this.compilationUnit.compilationResult);
177 // //name -- this is not really revelant but we do .....
178 // cd.selector = identifierStack[identifierPtr];
179 // long selectorSourcePositions = identifierPositionStack[identifierPtr--];
180 // identifierLengthPtr--;
183 // cd.declarationSourceStart = intStack[intPtr--];
184 // cd.modifiers = intStack[intPtr--];
186 // //highlight starts at the selector starts
187 // cd.sourceStart = (int) (selectorSourcePositions >>> 32);
188 // cd.selectorSourceEnd = (int) selectorSourcePositions;
189 // pushOnAstStack(cd);
191 // cd.sourceEnd = lParenPos;
192 // cd.bodyStart = lParenPos+1;
193 // listLength = 0; // initialize listLength before reading parameters/throws
196 // if (currentElement != null){
197 // lastCheckPoint = cd.bodyStart;
198 // if ((currentElement instanceof RecoveredType && lastIgnoredToken !=
200 // || cd.modifiers != 0){
201 // currentElement = currentElement.add(cd, 0);
202 // lastIgnoredToken = -1;
208 // * INTERNAL USE-ONLY
210 //protected void consumeExitVariableWithInitialization() {
211 // // ExitVariableWithInitialization ::= $empty
212 // // the scanner is located after the comma or the semi-colon.
213 // // we want to include the comma or the semi-colon
214 // super.consumeExitVariableWithInitialization();
215 // if (isLocalDeclaration() || ((currentToken != TokenNameCOMMA) &&
216 // (currentToken != TokenNameSEMICOLON)))
218 // ((SourceFieldDeclaration) astStack[astPtr]).fieldEndPosition =
219 // scanner.currentPosition - 1;
221 //protected void consumeExitVariableWithoutInitialization() {
222 // // ExitVariableWithoutInitialization ::= $empty
223 // // do nothing by default
224 // super.consumeExitVariableWithoutInitialization();
225 // if (isLocalDeclaration() || ((currentToken != TokenNameCOMMA) &&
226 // (currentToken != TokenNameSEMICOLON)))
228 // ((SourceFieldDeclaration) astStack[astPtr]).fieldEndPosition =
229 // scanner.currentPosition - 1;
233 // * INTERNAL USE-ONLY
235 //protected void consumeFieldAccess(boolean isSuperAccess) {
236 // // FieldAccess ::= Primary '.' 'Identifier'
237 // // FieldAccess ::= 'super' '.' 'Identifier'
238 // super.consumeFieldAccess(isSuperAccess);
239 // FieldReference fr = (FieldReference) expressionStack[expressionPtr];
240 // if (reportReferenceInfo) {
241 // requestor.acceptFieldReference(fr.token, fr.sourceStart);
244 //protected void consumeMethodHeaderName() {
245 // // MethodHeaderName ::= Modifiersopt Type 'Identifier' '('
246 // SourceMethodDeclaration md = new
247 // SourceMethodDeclaration(this.compilationUnit.compilationResult);
250 // md.selector = identifierStack[identifierPtr];
251 // long selectorSourcePositions = identifierPositionStack[identifierPtr--];
252 // identifierLengthPtr--;
254 // md.returnType = getTypeReference(intStack[intPtr--]);
256 // md.declarationSourceStart = intStack[intPtr--];
257 // md.modifiers = intStack[intPtr--];
259 // //highlight starts at selector start
260 // md.sourceStart = (int) (selectorSourcePositions >>> 32);
261 // md.selectorSourceEnd = (int) selectorSourcePositions;
262 // pushOnAstStack(md);
263 // md.sourceEnd = lParenPos;
264 // md.bodyStart = lParenPos+1;
265 // listLength = 0; // initialize listLength before reading parameters/throws
268 // if (currentElement != null){
269 // if (currentElement instanceof RecoveredType
270 // //|| md.modifiers != 0
271 // || (scanner.getLineNumber(md.returnType.sourceStart)
272 // == scanner.getLineNumber(md.sourceStart))){
273 // lastCheckPoint = md.bodyStart;
274 // currentElement = currentElement.add(md, 0);
275 // lastIgnoredToken = -1;
277 // lastCheckPoint = md.sourceStart;
278 // restartRecovery = true;
284 // * INTERNAL USE-ONLY
286 //protected void consumeMethodInvocationName() {
287 // // MethodInvocation ::= Name '(' ArgumentListopt ')'
289 // // when the name is only an identifier...we have a message send to "this"
291 // super.consumeMethodInvocationName();
292 // MessageSend messageSend = (MessageSend) expressionStack[expressionPtr];
293 // Expression[] args = messageSend.arguments;
294 // if (reportReferenceInfo) {
295 // requestor.acceptMethodReference(
296 // messageSend.selector,
297 // args == null ? 0 : args.length,
298 // (int)(messageSend.nameSourcePosition >>> 32));
303 // * INTERNAL USE-ONLY
305 //protected void consumeMethodInvocationPrimary() {
306 // super.consumeMethodInvocationPrimary();
307 // MessageSend messageSend = (MessageSend) expressionStack[expressionPtr];
308 // Expression[] args = messageSend.arguments;
309 // if (reportReferenceInfo) {
310 // requestor.acceptMethodReference(
311 // messageSend.selector,
312 // args == null ? 0 : args.length,
313 // (int)(messageSend.nameSourcePosition >>> 32));
318 // * INTERNAL USE-ONLY
320 //protected void consumeMethodInvocationSuper() {
321 // // MethodInvocation ::= 'super' '.' 'Identifier' '(' ArgumentListopt ')'
322 // super.consumeMethodInvocationSuper();
323 // MessageSend messageSend = (MessageSend) expressionStack[expressionPtr];
324 // Expression[] args = messageSend.arguments;
325 // if (reportReferenceInfo) {
326 // requestor.acceptMethodReference(
327 // messageSend.selector,
328 // args == null ? 0 : args.length,
329 // (int)(messageSend.nameSourcePosition >>> 32));
332 //protected void consumeSingleTypeImportDeclarationName() {
333 // // SingleTypeImportDeclarationName ::= 'import' Name
334 // /* push an ImportRef build from the last name
335 // stored in the identifier stack. */
337 // super.consumeSingleTypeImportDeclarationName();
338 // ImportReference impt = (ImportReference)astStack[astPtr];
339 // if (reportReferenceInfo) {
340 // requestor.acceptTypeReference(impt.tokens, impt.sourceStart,
344 //protected void consumeTypeImportOnDemandDeclarationName() {
345 // // TypeImportOnDemandDeclarationName ::= 'import' Name '.' '*'
346 // /* push an ImportRef build from the last name
347 // stored in the identifier stack. */
349 // super.consumeTypeImportOnDemandDeclarationName();
350 // ImportReference impt = (ImportReference)astStack[astPtr];
351 // if (reportReferenceInfo) {
352 // requestor.acceptUnknownReference(impt.tokens, impt.sourceStart,
356 //protected FieldDeclaration createFieldDeclaration(Expression
357 // initialization, char[] name, int sourceStart, int sourceEnd) {
358 // return new SourceFieldDeclaration(null, name, sourceStart, sourceEnd);
360 //protected CompilationUnitDeclaration endParse(int act) {
361 // if (sourceType != null) {
362 // if (sourceType.isInterface()) {
363 // consumeInterfaceDeclaration();
365 // consumeClassDeclaration();
368 // if (compilationUnit != null) {
369 // CompilationUnitDeclaration result = super.endParse(act);
376 * Flush annotations defined prior to a given positions.
378 * Note: annotations are stacked in syntactical order
380 * Either answer given <position>, or the end position of a comment line
381 * immediately following the <position> (same line)
383 * e.g. void foo(){ } // end of method foo
386 //public int flushAnnotationsDefinedPriorTo(int position) {
388 // return lastFieldEndPosition =
389 // super.flushAnnotationsDefinedPriorTo(position);
391 //public TypeReference getTypeReference(int dim) {
392 // /* build a Reference on a variable that may be qualified or not
393 // * This variable is a type reference and dim will be its dimensions
396 // if ((length = identifierLengthStack[identifierLengthPtr--]) == 1) {
397 // // single variable reference
399 // SingleTypeReference ref =
400 // new SingleTypeReference(
401 // identifierStack[identifierPtr],
402 // identifierPositionStack[identifierPtr--]);
403 // if (reportReferenceInfo) {
404 // requestor.acceptTypeReference(ref.token, ref.sourceStart);
408 // ArrayTypeReference ref =
409 // new ArrayTypeReference(
410 // identifierStack[identifierPtr],
412 // identifierPositionStack[identifierPtr--]);
413 // ref.sourceEnd = endPosition;
414 // if (reportReferenceInfo) {
415 // requestor.acceptTypeReference(ref.token, ref.sourceStart);
420 // if (length < 0) { //flag for precompiled type reference on base types
421 // TypeReference ref = TypeReference.baseTypeReference(-length, dim);
422 // ref.sourceStart = intStack[intPtr--];
424 // ref.sourceEnd = intStack[intPtr--];
426 // intPtr--; // no need to use this position as it is an array
427 // ref.sourceEnd = endPosition;
429 // if (reportReferenceInfo){
430 // requestor.acceptTypeReference(ref.getTypeName(), ref.sourceStart,
434 // } else { //Qualified variable reference
435 // char[][] tokens = new char[length][];
436 // identifierPtr -= length;
437 // long[] positions = new long[length];
438 // System.arraycopy(identifierStack, identifierPtr + 1, tokens, 0, length);
440 // identifierPositionStack,
441 // identifierPtr + 1,
446 // QualifiedTypeReference ref = new QualifiedTypeReference(tokens, positions);
447 // if (reportReferenceInfo) {
448 // requestor.acceptTypeReference(ref.tokens, ref.sourceStart, ref.sourceEnd);
452 // ArrayQualifiedTypeReference ref =
453 // new ArrayQualifiedTypeReference(tokens, dim, positions);
454 // ref.sourceEnd = endPosition;
455 // if (reportReferenceInfo) {
456 // requestor.acceptTypeReference(ref.tokens, ref.sourceStart, ref.sourceEnd);
463 //public NameReference getUnspecifiedReference() {
464 // /* build a (unspecified) NameReference which may be qualified*/
467 // if ((length = identifierLengthStack[identifierLengthPtr--]) == 1) {
468 // // single variable reference
469 // SingleNameReference ref =
470 // new SingleNameReference(
471 // identifierStack[identifierPtr],
472 // identifierPositionStack[identifierPtr--]);
473 // if (reportReferenceInfo) {
474 // this.addUnknownRef(ref);
478 // //Qualified variable reference
479 // char[][] tokens = new char[length][];
480 // identifierPtr -= length;
481 // System.arraycopy(identifierStack, identifierPtr + 1, tokens, 0, length);
482 // QualifiedNameReference ref =
483 // new QualifiedNameReference(
485 // (int) (identifierPositionStack[identifierPtr + 1] >> 32), // sourceStart
486 // (int) identifierPositionStack[identifierPtr + length]); // sourceEnd
487 // if (reportReferenceInfo) {
488 // this.addUnknownRef(ref);
493 //public NameReference getUnspecifiedReferenceOptimized() {
494 // /* build a (unspecified) NameReference which may be qualified
495 // The optimization occurs for qualified reference while we are
496 // certain in this case the last item of the qualified name is
497 // a field access. This optimization is IMPORTANT while it results
498 // that when a NameReference is build, the type checker should always
499 // look for that it is not a type reference */
502 // if ((length = identifierLengthStack[identifierLengthPtr--]) == 1) {
503 // // single variable reference
504 // SingleNameReference ref =
505 // new SingleNameReference(
506 // identifierStack[identifierPtr],
507 // identifierPositionStack[identifierPtr--]);
508 // ref.bits &= ~ASTNode.RestrictiveFlagMASK;
509 // ref.bits |= LOCAL | FIELD;
510 // if (reportReferenceInfo) {
511 // this.addUnknownRef(ref);
516 // //Qualified-variable-reference
517 // //In fact it is variable-reference DOT field-ref , but it would result in a
519 // //conflict tha can be only reduce by making a superclass (or inetrface )
521 // //nameReference and FiledReference or putting FieldReference under
523 // //or else..........This optimisation is not really relevant so just leave
526 // char[][] tokens = new char[length][];
527 // identifierPtr -= length;
528 // System.arraycopy(identifierStack, identifierPtr + 1, tokens, 0, length);
529 // QualifiedNameReference ref =
530 // new QualifiedNameReference(
532 // (int) (identifierPositionStack[identifierPtr + 1] >> 32),
534 // (int) identifierPositionStack[identifierPtr + length]); // sourceEnd
535 // ref.bits &= ~ASTNode.RestrictiveFlagMASK;
536 // ref.bits |= LOCAL | FIELD;
537 // if (reportReferenceInfo) {
538 // this.addUnknownRef(ref);
544 // * INTERNAL USE-ONLY
546 //private boolean isLocalDeclaration() {
547 // int nestedDepth = nestedType;
548 // while (nestedDepth >= 0) {
549 // if (nestedMethod[nestedDepth] != 0) {
557 * Update the bodyStart of the corresponding parse node
559 public void notifySourceElementRequestor(CompilationUnitDeclaration parsedUnit) {
560 if (parsedUnit == null) {
561 // when we parse a single type member declaration the compilation unit is
562 // null, but we still
563 // want to be able to notify the requestor on the created ast node
564 if (astStack[0] instanceof AbstractMethodDeclaration) {
565 notifySourceElementRequestor((AbstractMethodDeclaration) astStack[0]);
571 boolean isInRange = scanner.initialPosition <= parsedUnit.sourceStart && scanner.eofPosition >= parsedUnit.sourceEnd;
573 // if (reportReferenceInfo) {
574 // notifyAllUnknownReferences();
576 // collect the top level ast nodes
578 ASTNode[] nodes = null;
579 if (sourceType == null) {
581 requestor.enterCompilationUnit();
583 // ImportReference currentPackage = parsedUnit.currentPackage;
584 ImportReference[] imports = parsedUnit.imports;
585 // TypeDeclaration[] types = parsedUnit.types;
586 ArrayList types = parsedUnit.types;
589 // (currentPackage == null ? 0 : 1)
590 // + (imports == null ? 0 : imports.length)
591 // + (types == null ? 0 : types.length);
592 // nodes = new ASTNode[length];
593 length = (imports == null ? 0 : imports.length) + types.size();
594 nodes = new ASTNode[length];
596 // if (currentPackage != null) {
597 // nodes[index++] = currentPackage;
599 if (imports != null) {
600 for (int i = 0, max = imports.length; i < max; i++) {
601 nodes[index++] = imports[i];
605 for (int i = 0, max = types.size(); i < max; i++) {
606 nodes[index++] = (ASTNode) types.get(i);
610 // TypeDeclaration[] types = parsedUnit.types;
611 ArrayList types = parsedUnit.types;
613 length = types.size();
614 nodes = new ASTNode[length];
615 for (int i = 0, max = types.size(); i < max; i++) {
616 nodes[i] = (ASTNode) types.get(i);
621 // notify the nodes in the syntactical order
622 if (nodes != null && length > 0) {
623 quickSort(nodes, 0, length - 1);
624 for (int i = 0; i < length; i++) {
625 ASTNode node = nodes[i];
626 if (node instanceof ImportReference) {
627 ImportReference importRef = (ImportReference)node;
628 // if (node == parsedUnit.currentPackage) {
629 // notifySourceElementRequestor(importRef, true);
631 notifySourceElementRequestor(importRef, false);
633 } //else { instanceof TypeDeclaration
634 if (node instanceof TypeDeclaration) {
635 notifySourceElementRequestor((TypeDeclaration) node, sourceType == null);
636 // notifySourceElementRequestor((CompilationUnitDeclaration)node,
637 // sourceType == null);
639 // jsurfer - INSERT start
640 if (node instanceof AbstractMethodDeclaration) {
641 notifySourceElementRequestor((AbstractMethodDeclaration) node);
643 // jsurfer - INSERT end
647 if (sourceType == null) {
649 requestor.exitCompilationUnit(parsedUnit.sourceEnd);
654 //private void notifyAllUnknownReferences() {
655 // for (int i = 0, max = this.unknownRefsCounter; i < max; i++) {
656 // NameReference nameRef = this.unknownRefs[i];
657 // if ((nameRef.bits & BindingIds.VARIABLE) != 0) {
658 // if ((nameRef.bits & BindingIds.TYPE) == 0) {
659 // // variable but not type
660 // if (nameRef instanceof SingleNameReference) {
661 // // local var or field
662 // requestor.acceptUnknownReference(((SingleNameReference) nameRef).token,
663 // nameRef.sourceStart);
665 // // QualifiedNameReference
666 // // The last token is a field reference and the previous tokens are a
667 // type/variable references
668 // char[][] tokens = ((QualifiedNameReference) nameRef).tokens;
669 // int tokensLength = tokens.length;
670 // requestor.acceptFieldReference(tokens[tokensLength - 1], nameRef.sourceEnd
671 // - tokens[tokensLength - 1].length + 1);
672 // char[][] typeRef = new char[tokensLength - 1][];
673 // System.arraycopy(tokens, 0, typeRef, 0, tokensLength - 1);
674 // requestor.acceptUnknownReference(typeRef, nameRef.sourceStart,
675 // nameRef.sourceEnd - tokens[tokensLength - 1].length);
678 // // variable or type
679 // if (nameRef instanceof SingleNameReference) {
680 // requestor.acceptUnknownReference(((SingleNameReference) nameRef).token,
681 // nameRef.sourceStart);
683 // //QualifiedNameReference
684 // requestor.acceptUnknownReference(((QualifiedNameReference) nameRef).tokens,
685 // nameRef.sourceStart, nameRef.sourceEnd);
688 // } else if ((nameRef.bits & BindingIds.TYPE) != 0) {
689 // if (nameRef instanceof SingleNameReference) {
690 // requestor.acceptTypeReference(((SingleNameReference) nameRef).token,
691 // nameRef.sourceStart);
693 // // it is a QualifiedNameReference
694 // requestor.acceptTypeReference(((QualifiedNameReference) nameRef).tokens,
695 // nameRef.sourceStart, nameRef.sourceEnd);
701 * Update the bodyStart of the corresponding parse node
703 public void notifySourceElementRequestor(AbstractMethodDeclaration methodDeclaration) {
706 boolean isInRange = scanner.initialPosition <= methodDeclaration.declarationSourceStart
707 && scanner.eofPosition >= methodDeclaration.declarationSourceEnd;
709 if (methodDeclaration.isClinit()) {
710 this.visitIfNeeded(methodDeclaration);
714 if (methodDeclaration.isDefaultConstructor()) {
715 if (reportReferenceInfo) {
716 ConstructorDeclaration constructorDeclaration = (ConstructorDeclaration) methodDeclaration;
717 ExplicitConstructorCall constructorCall = constructorDeclaration.constructorCall;
718 if (constructorCall != null) {
719 switch (constructorCall.accessMode) {
720 case ExplicitConstructorCall.This :
721 requestor.acceptConstructorReference(typeNames[nestedTypeIndex - 1], constructorCall.arguments == null
723 : constructorCall.arguments.length, constructorCall.sourceStart);
725 case ExplicitConstructorCall.Super :
726 case ExplicitConstructorCall.ImplicitSuper :
727 requestor.acceptConstructorReference(superTypeNames[nestedTypeIndex - 1], constructorCall.arguments == null
729 : constructorCall.arguments.length, constructorCall.sourceStart);
736 char[][] argumentTypes = null;
737 char[][] argumentNames = null;
738 Argument[] arguments = methodDeclaration.arguments;
739 if (arguments != null) {
740 int argumentLength = arguments.length;
741 argumentTypes = new char[argumentLength][];
742 argumentNames = new char[argumentLength][];
743 for (int i = 0; i < argumentLength; i++) {
744 argumentTypes[i] = returnTypeName(arguments[i].type);
745 argumentNames[i] = arguments[i].name;
748 char[][] thrownExceptionTypes = null;
749 TypeReference[] thrownExceptions = methodDeclaration.thrownExceptions;
750 if (thrownExceptions != null) {
751 int thrownExceptionLength = thrownExceptions.length;
752 thrownExceptionTypes = new char[thrownExceptionLength][];
753 for (int i = 0; i < thrownExceptionLength; i++) {
754 thrownExceptionTypes[i] = CharOperation.concatWith(thrownExceptions[i].getTypeName(), '.');
757 // by default no selector end position
758 int selectorSourceEnd = -1;
759 if (methodDeclaration.isConstructor()) {
760 // if (methodDeclaration instanceof SourceConstructorDeclaration) {
761 // selectorSourceEnd =
762 // ((SourceConstructorDeclaration) methodDeclaration).selectorSourceEnd;
765 requestor.enterConstructor(methodDeclaration.declarationSourceStart, methodDeclaration.modifiers,
766 methodDeclaration.selector, methodDeclaration.sourceStart, selectorSourceEnd, argumentTypes, argumentNames,
767 thrownExceptionTypes);
769 if (reportReferenceInfo) {
770 ConstructorDeclaration constructorDeclaration = (ConstructorDeclaration) methodDeclaration;
771 ExplicitConstructorCall constructorCall = constructorDeclaration.constructorCall;
772 if (constructorCall != null) {
773 switch (constructorCall.accessMode) {
774 case ExplicitConstructorCall.This :
775 requestor.acceptConstructorReference(typeNames[nestedTypeIndex - 1], constructorCall.arguments == null
777 : constructorCall.arguments.length, constructorCall.sourceStart);
779 case ExplicitConstructorCall.Super :
780 case ExplicitConstructorCall.ImplicitSuper :
781 requestor.acceptConstructorReference(superTypeNames[nestedTypeIndex - 1], constructorCall.arguments == null
783 : constructorCall.arguments.length, constructorCall.sourceStart);
788 this.visitIfNeeded(methodDeclaration);
790 requestor.exitConstructor(methodDeclaration.declarationSourceEnd);
794 // if (methodDeclaration instanceof SourceMethodDeclaration) {
795 // selectorSourceEnd =
796 // ((SourceMethodDeclaration) methodDeclaration).selectorSourceEnd;
799 int modifiers = methodDeclaration.modifiers;
800 // boolean deprecated = (modifiers & AccDeprecated) != 0; // remember
801 // deprecation so as to not lose it below
802 requestor.enterMethod(methodDeclaration.declarationSourceStart, modifiers, // deprecated
813 returnTypeName(((MethodDeclaration) methodDeclaration).returnType), methodDeclaration.selector,
814 methodDeclaration.sourceStart, selectorSourceEnd, argumentTypes, argumentNames, thrownExceptionTypes);
816 this.visitIfNeeded(methodDeclaration);
819 requestor.exitMethod(methodDeclaration.declarationSourceEnd);
823 * Update the bodyStart of the corresponding parse node
825 public void notifySourceElementRequestor(FieldDeclaration fieldDeclaration) {
828 boolean isInRange = scanner.initialPosition <= fieldDeclaration.declarationSourceStart
829 && scanner.eofPosition >= fieldDeclaration.declarationSourceEnd;
831 if (fieldDeclaration.isField()) {
832 int fieldEndPosition = fieldDeclaration.declarationSourceEnd;
833 // if (fieldDeclaration instanceof SourceFieldDeclaration) {
834 // fieldEndPosition = ((SourceFieldDeclaration)
835 // fieldDeclaration).fieldEndPosition;
836 // if (fieldEndPosition == 0) {
837 // // use the declaration source end by default
838 // fieldEndPosition = fieldDeclaration.declarationSourceEnd;
842 int modifiers = fieldDeclaration.modifiers;
843 boolean deprecated = (modifiers & AccDeprecated) != 0; // remember
847 requestor.enterField(fieldDeclaration.declarationSourceStart, deprecated
848 ? (modifiers & AccJustFlag) | AccDeprecated
849 : modifiers & AccJustFlag, returnTypeName(fieldDeclaration.type), fieldDeclaration.name, fieldDeclaration.sourceStart,
850 fieldDeclaration.sourceEnd);
852 // this.visitIfNeeded(fieldDeclaration);
854 // requestor.exitField(
855 // // filter out initializations that are not a constant (simple check)
856 // (fieldDeclaration.initialization == null
857 // || fieldDeclaration.initialization instanceof ArrayInitializer
858 // || fieldDeclaration.initialization instanceof AllocationExpression
859 // || fieldDeclaration.initialization instanceof
860 // ArrayAllocationExpression
861 // || fieldDeclaration.initialization instanceof Assignment
862 // || fieldDeclaration.initialization instanceof ClassLiteralAccess
863 // || fieldDeclaration.initialization instanceof MessageSend
864 // || fieldDeclaration.initialization instanceof ArrayReference
865 // || fieldDeclaration.initialization instanceof ThisReference) ?
867 // fieldDeclaration.initialization.sourceStart,
869 // fieldDeclaration.declarationSourceEnd);
871 // filter out initializations that are not a constant (simple check)
872 -1, fieldEndPosition, fieldDeclaration.declarationSourceEnd);
877 // requestor.enterInitializer(
878 // fieldDeclaration.declarationSourceStart,
879 // fieldDeclaration.modifiers);
881 // this.visitIfNeeded((Initializer)fieldDeclaration);
883 // requestor.exitInitializer(fieldDeclaration.declarationSourceEnd);
887 public void notifySourceElementRequestor(
888 ImportReference importReference,
891 // requestor.acceptPackage(
892 // importReference.declarationSourceStart,
893 // importReference.declarationSourceEnd,
894 // CharOperation.concatWith(importReference.getImportName(), '.'));
896 requestor.acceptImport(
897 importReference.declarationSourceStart,
898 importReference.declarationSourceEnd,
899 importReference.getIncludeName(), //CharOperation.concatWith(importReference.getImportName(), '.'),
900 importReference.onDemand);
903 public void notifySourceElementRequestor(TypeDeclaration typeDeclaration, boolean notifyTypePresence) {
904 //// public void notifySourceElementRequestor(ASTNode typeDeclaration,
905 // boolean notifyTypePresence) {
908 boolean isInRange = scanner.initialPosition <= typeDeclaration.declarationSourceStart
909 && scanner.eofPosition >= typeDeclaration.declarationSourceEnd;
911 FieldDeclaration[] fields = typeDeclaration.fields;
912 AbstractMethodDeclaration[] methods = typeDeclaration.methods;
913 TypeDeclaration[] memberTypes = typeDeclaration.memberTypes;
914 int fieldCount = fields == null ? 0 : fields.length;
915 int methodCount = methods == null ? 0 : methods.length;
916 int memberTypeCount = memberTypes == null ? 0 : memberTypes.length;
919 int memberTypeIndex = 0;
920 boolean isInterface = typeDeclaration.isInterface();
922 if (notifyTypePresence) {
923 char[][] interfaceNames = null;
924 int superInterfacesLength = 0;
925 TypeReference[] superInterfaces = typeDeclaration.superInterfaces;
926 if (superInterfaces != null) {
927 superInterfacesLength = superInterfaces.length;
928 interfaceNames = new char[superInterfacesLength][];
930 if (typeDeclaration instanceof AnonymousLocalTypeDeclaration) {
932 QualifiedAllocationExpression alloc = ((AnonymousLocalTypeDeclaration) typeDeclaration).allocation;
933 if (alloc != null && alloc.type != null) {
934 superInterfaces = new TypeReference[]{((AnonymousLocalTypeDeclaration) typeDeclaration).allocation.type};
935 superInterfacesLength = 1;
936 interfaceNames = new char[1][];
940 if (superInterfaces != null) {
941 for (int i = 0; i < superInterfacesLength; i++) {
942 interfaceNames[i] = CharOperation.concatWith(superInterfaces[i].getTypeName(), '.');
947 int modifiers = typeDeclaration.modifiers;
948 boolean deprecated = false; //(modifiers & AccDeprecated) != 0; //
949 // remember deprecation so as to not lose
951 requestor.enterInterface(typeDeclaration.declarationSourceStart, modifiers, //deprecated
962 typeDeclaration.name, typeDeclaration.sourceStart, typeDeclaration.sourceEnd, interfaceNames);
964 if (nestedTypeIndex == typeNames.length) {
966 System.arraycopy(typeNames, 0, (typeNames = new char[nestedTypeIndex * 2][]), 0, nestedTypeIndex);
967 System.arraycopy(superTypeNames, 0, (superTypeNames = new char[nestedTypeIndex * 2][]), 0, nestedTypeIndex);
969 typeNames[nestedTypeIndex] = typeDeclaration.name;
970 superTypeNames[nestedTypeIndex++] = JAVA_LANG_OBJECT;
972 TypeReference superclass = typeDeclaration.superclass;
973 if (superclass == null) {
975 requestor.enterClass(typeDeclaration.declarationSourceStart, typeDeclaration.modifiers, typeDeclaration.name,
976 typeDeclaration.sourceStart, typeDeclaration.sourceEnd, null, interfaceNames);
980 requestor.enterClass(typeDeclaration.declarationSourceStart, typeDeclaration.modifiers, typeDeclaration.name,
981 typeDeclaration.sourceStart, typeDeclaration.sourceEnd, CharOperation.concatWith(superclass.getTypeName(), '.'),
985 if (nestedTypeIndex == typeNames.length) {
987 System.arraycopy(typeNames, 0, (typeNames = new char[nestedTypeIndex * 2][]), 0, nestedTypeIndex);
988 System.arraycopy(superTypeNames, 0, (superTypeNames = new char[nestedTypeIndex * 2][]), 0, nestedTypeIndex);
990 typeNames[nestedTypeIndex] = typeDeclaration.name;
991 superTypeNames[nestedTypeIndex++] = superclass == null ? JAVA_LANG_OBJECT : CharOperation.concatWith(superclass
992 .getTypeName(), '.');
995 while ((fieldIndex < fieldCount) || (memberTypeIndex < memberTypeCount) || (methodIndex < methodCount)) {
996 FieldDeclaration nextFieldDeclaration = null;
997 AbstractMethodDeclaration nextMethodDeclaration = null;
998 TypeDeclaration nextMemberDeclaration = null;
1000 int position = Integer.MAX_VALUE;
1001 int nextDeclarationType = -1;
1002 if (fieldIndex < fieldCount) {
1003 nextFieldDeclaration = fields[fieldIndex];
1004 if (nextFieldDeclaration.declarationSourceStart < position) {
1005 position = nextFieldDeclaration.declarationSourceStart;
1006 nextDeclarationType = 0; // FIELD
1009 if (methodIndex < methodCount) {
1010 nextMethodDeclaration = methods[methodIndex];
1011 if (nextMethodDeclaration.declarationSourceStart < position) {
1012 position = nextMethodDeclaration.declarationSourceStart;
1013 nextDeclarationType = 1; // METHOD
1016 if (memberTypeIndex < memberTypeCount) {
1017 nextMemberDeclaration = memberTypes[memberTypeIndex];
1018 if (nextMemberDeclaration.declarationSourceStart < position) {
1019 position = nextMemberDeclaration.declarationSourceStart;
1020 nextDeclarationType = 2; // MEMBER
1023 switch (nextDeclarationType) {
1026 notifySourceElementRequestor(nextFieldDeclaration);
1030 notifySourceElementRequestor(nextMethodDeclaration);
1034 notifySourceElementRequestor(nextMemberDeclaration, true);
1037 if (notifyTypePresence) {
1040 requestor.exitInterface(typeDeclaration.declarationSourceEnd);
1042 requestor.exitClass(typeDeclaration.declarationSourceEnd);
1048 public void parseCompilationUnit(ICompilationUnit unit, int start, int end) {
1049 // boolean needReferenceInfo) {
1051 // reportReferenceInfo = needReferenceInfo;
1052 // boolean old = diet;
1053 // if (needReferenceInfo) {
1054 // unknownRefs = new NameReference[10];
1055 // unknownRefsCounter = 0;
1060 CompilationResult compilationUnitResult = new CompilationResult(unit, 0, 0, 10); //this.options.maxProblemsPerUnit);
1061 CompilationUnitDeclaration parsedUnit = parse(unit, compilationUnitResult, start, end);
1062 // if (scanner.recordLineSeparator) {
1063 // requestor.acceptLineSeparatorPositions(scanner.getLineEnds());
1065 // if (this.localDeclarationVisitor != null || needReferenceInfo){
1067 // this.getMethodBodies(parsedUnit);
1069 // this.scanner.resetTo(start, end);
1070 // notifySourceElementRequestor(parsedUnit);
1071 } catch (AbortCompilation e) {
1076 public CompilationUnitDeclaration parseCompilationUnit(ICompilationUnit unit, boolean fullParse) {
1078 // boolean old = diet;
1080 // unknownRefs = new NameReference[10];
1081 // unknownRefsCounter = 0;
1086 this.reportReferenceInfo = fullParse;
1087 CompilationResult compilationUnitResult = new CompilationResult(unit, 0, 0, this.options.maxProblemsPerUnit);
1088 CompilationUnitDeclaration parsedUnit = parse(unit, compilationUnitResult, false);
1089 if (scanner.recordLineSeparator) {
1090 requestor.acceptLineSeparatorPositions(scanner.getLineEnds());
1092 int initialStart = this.scanner.initialPosition;
1093 int initialEnd = this.scanner.eofPosition;
1094 // if (this.localDeclarationVisitor != null || fullParse){
1096 // this.getMethodBodies(parsedUnit);
1098 this.scanner.resetTo(initialStart, initialEnd);
1099 notifySourceElementRequestor(parsedUnit);
1101 } catch (AbortCompilation e) {
1102 // ignore this exception
1109 public CompilationUnitDeclaration parseCompletionUnit(ICompilationUnit unit, boolean fullParse) {
1111 // boolean old = diet;
1113 // unknownRefs = new NameReference[10];
1114 // unknownRefsCounter = 0;
1119 this.reportReferenceInfo = fullParse;
1120 CompilationResult compilationUnitResult = new CompilationResult(unit, 0, 0, this.options.maxProblemsPerUnit);
1121 CompilationUnitDeclaration parsedUnit = parse(unit, compilationUnitResult, false);
1122 // if (scanner.recordLineSeparator) {
1123 // requestor.acceptLineSeparatorPositions(scanner.getLineEnds());
1125 // int initialStart = this.scanner.initialPosition;
1126 // int initialEnd = this.scanner.eofPosition;
1127 // // if (this.localDeclarationVisitor != null || fullParse){
1129 // // this.getMethodBodies(parsedUnit);
1131 // this.scanner.resetTo(initialStart, initialEnd);
1132 // notifySourceElementRequestor(parsedUnit);
1134 } catch (AbortCompilation e) {
1135 // ignore this exception
1141 //public void parseTypeMemberDeclarations(
1142 // ISourceType sourceType,
1143 // ICompilationUnit sourceUnit,
1146 // boolean needReferenceInfo) {
1147 // boolean old = diet;
1148 // if (needReferenceInfo) {
1149 // unknownRefs = new NameReference[10];
1150 // unknownRefsCounter = 0;
1154 // diet = !needReferenceInfo;
1155 // reportReferenceInfo = needReferenceInfo;
1156 // CompilationResult compilationUnitResult =
1157 // new CompilationResult(sourceUnit, 0, 0, this.options.maxProblemsPerUnit);
1158 // CompilationUnitDeclaration unit =
1159 // SourceTypeConverter.buildCompilationUnit(
1160 // new ISourceType[]{sourceType},
1161 // false, // no need for field and methods
1162 // false, // no need for member types
1163 // false, // no need for field initialization
1164 // problemReporter(),
1165 // compilationUnitResult);
1166 // if ((unit == null) || (unit.types == null) || (unit.types.length != 1))
1168 // this.sourceType = sourceType;
1170 // /* automaton initialization */
1172 // goForClassBodyDeclarations();
1173 // /* scanner initialization */
1174 // scanner.setSource(sourceUnit.getContents());
1175 // scanner.resetTo(start, end);
1176 // /* unit creation */
1177 // referenceContext = compilationUnit = unit;
1178 // /* initialize the astStacl */
1179 // // the compilationUnitDeclaration should contain exactly one type
1180 // pushOnAstStack(unit.types[0]);
1181 // /* run automaton */
1183 // notifySourceElementRequestor(unit);
1185 // unit = compilationUnit;
1186 // compilationUnit = null; // reset parser
1188 // } catch (AbortCompilation e) {
1190 // if (scanner.recordLineSeparator) {
1191 // requestor.acceptLineSeparatorPositions(scanner.getLineEnds());
1197 //public void parseTypeMemberDeclarations(
1202 // boolean old = diet;
1207 // /* automaton initialization */
1209 // goForClassBodyDeclarations();
1210 // /* scanner initialization */
1211 // scanner.setSource(contents);
1212 // scanner.recordLineSeparator = false;
1213 // scanner.taskTags = null;
1214 // scanner.taskPriorities = null;
1215 // scanner.resetTo(start, end);
1217 // /* unit creation */
1218 // referenceContext = null;
1220 // /* initialize the astStacl */
1221 // // the compilationUnitDeclaration should contain exactly one type
1222 // /* run automaton */
1224 // notifySourceElementRequestor((CompilationUnitDeclaration)null);
1225 // } catch (AbortCompilation e) {
1231 * Sort the given ast nodes by their positions.
1233 private static void quickSort(ASTNode[] sortedCollection, int left, int right) {
1234 int original_left = left;
1235 int original_right = right;
1236 ASTNode mid = sortedCollection[(left + right) / 2];
1238 while (sortedCollection[left].sourceStart < mid.sourceStart) {
1241 while (mid.sourceStart < sortedCollection[right].sourceStart) {
1244 if (left <= right) {
1245 ASTNode tmp = sortedCollection[left];
1246 sortedCollection[left] = sortedCollection[right];
1247 sortedCollection[right] = tmp;
1251 } while (left <= right);
1252 if (original_left < right) {
1253 quickSort(sortedCollection, original_left, right);
1255 if (left < original_right) {
1256 quickSort(sortedCollection, left, original_right);
1260 * Answer a char array representation of the type name formatted like: - type
1261 * name + dimensions Example: "A[][]".toCharArray()
1262 * "java.lang.String".toCharArray()
1264 private char[] returnTypeName(TypeReference type) {
1267 int dimension = type.dimensions();
1268 if (dimension != 0) {
1269 char[] dimensionsArray = new char[dimension * 2];
1270 for (int i = 0; i < dimension; i++) {
1271 dimensionsArray[i * 2] = '[';
1272 dimensionsArray[(i * 2) + 1] = ']';
1274 return CharOperation.concat(CharOperation.concatWith(type.getTypeName(), '.'), dimensionsArray);
1276 return CharOperation.concatWith(type.getTypeName(), '.');
1279 public void addUnknownRef(NameReference nameRef) {
1280 if (this.unknownRefs.length == this.unknownRefsCounter) {
1282 System.arraycopy(this.unknownRefs, 0, (this.unknownRefs = new NameReference[this.unknownRefsCounter * 2]), 0,
1283 this.unknownRefsCounter);
1285 this.unknownRefs[this.unknownRefsCounter++] = nameRef;
1288 private void visitIfNeeded(AbstractMethodDeclaration method) {
1289 if (this.localDeclarationVisitor != null && (method.bits & ASTNode.HasLocalTypeMASK) != 0) {
1290 if (method.statements != null) {
1291 int statementsLength = method.statements.length;
1292 for (int i = 0; i < statementsLength; i++)
1293 method.statements[i].traverse(this.localDeclarationVisitor, method.scope);
1298 //private void visitIfNeeded(FieldDeclaration field) {
1299 // if (this.localDeclarationVisitor != null
1300 // && (field.bits & ASTNode.HasLocalTypeMASK) != 0) {
1301 // if (field.initialization != null) {
1302 // field.initialization.traverse(this.localDeclarationVisitor, null);
1307 //private void visitIfNeeded(Initializer initializer) {
1308 // if (this.localDeclarationVisitor != null
1309 // && (initializer.bits & ASTNode.HasLocalTypeMASK) != 0) {
1310 // if (initializer.block != null) {
1311 // initializer.block.traverse(this.localDeclarationVisitor, null);
1316 //protected void reportSyntaxError(int act, int currentKind, int
1318 // if (compilationUnit == null) return;
1319 // super.reportSyntaxError(act, currentKind,stateStackTop);
1321 protected CompilationUnitDeclaration endParse(int act) {
1322 // if (sourceType != null) {
1323 // if (sourceType.isInterface()) {
1324 // consumeInterfaceDeclaration();
1326 // consumeClassDeclaration();
1329 if (compilationUnit != null) {
1330 CompilationUnitDeclaration result = super.endParse(act);