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.ast.ASTNode;
18 import net.sourceforge.phpdt.internal.compiler.ast.AbstractMethodDeclaration;
19 import net.sourceforge.phpdt.internal.compiler.ast.AnonymousLocalTypeDeclaration;
20 import net.sourceforge.phpdt.internal.compiler.ast.Argument;
21 import net.sourceforge.phpdt.internal.compiler.ast.CompilationUnitDeclaration;
22 import net.sourceforge.phpdt.internal.compiler.ast.ConstructorDeclaration;
23 import net.sourceforge.phpdt.internal.compiler.ast.ExplicitConstructorCall;
24 import net.sourceforge.phpdt.internal.compiler.ast.FieldDeclaration;
25 import net.sourceforge.phpdt.internal.compiler.ast.ImportReference;
26 import net.sourceforge.phpdt.internal.compiler.ast.MethodDeclaration;
27 import net.sourceforge.phpdt.internal.compiler.ast.NameReference;
28 import net.sourceforge.phpdt.internal.compiler.ast.QualifiedAllocationExpression;
29 import net.sourceforge.phpdt.internal.compiler.ast.TypeDeclaration;
30 import net.sourceforge.phpdt.internal.compiler.ast.TypeReference;
31 import net.sourceforge.phpdt.internal.compiler.env.ICompilationUnit;
32 import net.sourceforge.phpdt.internal.compiler.env.ISourceType;
33 import net.sourceforge.phpdt.internal.compiler.impl.CompilerOptions;
34 import net.sourceforge.phpdt.internal.compiler.impl.ReferenceContext;
35 import net.sourceforge.phpdt.internal.compiler.lookup.BlockScope;
36 import net.sourceforge.phpdt.internal.compiler.lookup.ClassScope;
37 import net.sourceforge.phpdt.internal.compiler.problem.AbortCompilation;
38 import net.sourceforge.phpdt.internal.compiler.problem.ProblemReporter;
39 import net.sourceforge.phpdt.internal.core.util.CommentRecorderParser;
42 * A source element parser extracts structural and reference information from a
47 * @ISourceElementRequestor
49 * The structural investigation includes: - the package statement - import
50 * statements - top-level types: package member, member types (member types of
51 * member types...) - fields - methods
53 * If reference information is requested, then all source constructs are
54 * investigated and type, field & method references are provided as well.
56 * Any (parsing) problem encountered is also provided.
59 public class SourceElementParser extends CommentRecorderParser {// extends
62 ISourceElementRequestor requestor;
68 int lastFieldEndPosition;
70 ISourceType sourceType;
72 boolean reportReferenceInfo;
76 char[][] superTypeNames;
80 static final char[] JAVA_LANG_OBJECT = "java.lang.Object".toCharArray(); //$NON-NLS-1$
82 NameReference[] unknownRefs;
84 int unknownRefsCounter;
86 LocalDeclarationVisitor localDeclarationVisitor = null;
88 // CompilerOptions options;
91 * An ast visitor that visits local type declarations.
93 public class LocalDeclarationVisitor extends ASTVisitor {
94 public boolean visit(TypeDeclaration typeDeclaration, BlockScope scope) {
95 notifySourceElementRequestor(typeDeclaration, sourceType == null);
96 return false; // don't visit members as this was done during
97 // notifySourceElementRequestor(...)
100 public boolean visit(TypeDeclaration typeDeclaration, ClassScope scope) {
101 notifySourceElementRequestor(typeDeclaration, sourceType == null);
102 return false; // don't visit members as this was done during
103 // notifySourceElementRequestor(...)
108 public SourceElementParser(final ISourceElementRequestor requestor,
109 IProblemFactory problemFactory, CompilerOptions options) {
110 // we want to notify all syntax error with the acceptProblem API
111 // To do so, we define the record method of the ProblemReporter
112 super(new ProblemReporter(DefaultErrorHandlingPolicies
113 .exitAfterAllProblems(), options, problemFactory) {
114 public void record(IProblem problem, CompilationResult unitResult,
115 ReferenceContext referenceContext) {
116 unitResult.record(problem, referenceContext);
117 if (requestor != null) {
118 requestor.acceptProblem(problem);
123 // options.sourceLevel >= CompilerOptions.JDK1_4);
124 this.requestor = requestor;
125 typeNames = new char[4][];
126 superTypeNames = new char[4][];
128 this.options = options;
132 * @deprecated use SourceElementParser(ISourceElementRequestor,
133 * IProblemFactory, CompilerOptions)
135 public SourceElementParser(final ISourceElementRequestor requestor,
136 IProblemFactory problemFactory) {
137 this(requestor, problemFactory, new CompilerOptions());
140 public SourceElementParser(final ISourceElementRequestor requestor,
141 IProblemFactory problemFactory, CompilerOptions options,
142 boolean reportLocalDeclarations) {
143 this(requestor, problemFactory, options);
144 if (reportLocalDeclarations) {
145 this.localDeclarationVisitor = new LocalDeclarationVisitor();
149 // public void checkAnnotation() {
150 // int firstCommentIndex = scanner.commentPtr;
152 // super.checkAnnotation();
154 // // modify the modifier source start to point at the first comment
155 // if (firstCommentIndex >= 0) {
156 // modifiersSourceStart = scanner.commentStarts[0];
159 // protected void classInstanceCreation(boolean alwaysQualified) {
161 // boolean previousFlag = reportReferenceInfo;
162 // reportReferenceInfo = false; // not to see the type reference reported in
163 // super call to getTypeReference(...)
164 // super.classInstanceCreation(alwaysQualified);
165 // reportReferenceInfo = previousFlag;
166 // if (reportReferenceInfo){
167 // AllocationExpression alloc =
168 // (AllocationExpression)expressionStack[expressionPtr];
169 // TypeReference typeRef = alloc.type;
170 // requestor.acceptConstructorReference(
171 // typeRef instanceof SingleTypeReference
172 // ? ((SingleTypeReference) typeRef).token
173 // : CharOperation.concatWith(alloc.type.getTypeName(), '.'),
174 // alloc.arguments == null ? 0 : alloc.arguments.length,
175 // alloc.sourceStart);
178 // protected void consumeConstructorHeaderName() {
179 // // ConstructorHeaderName ::= Modifiersopt 'Identifier' '('
181 // /* recovering - might be an empty message send */
182 // if (currentElement != null){
183 // if (lastIgnoredToken == TokenNamenew){ // was an allocation expression
184 // lastCheckPoint = scanner.startPosition; // force to restart at this exact
186 // restartRecovery = true;
190 // SourceConstructorDeclaration cd = new
191 // SourceConstructorDeclaration(this.compilationUnit.compilationResult);
193 // //name -- this is not really revelant but we do .....
194 // cd.selector = identifierStack[identifierPtr];
195 // long selectorSourcePositions = identifierPositionStack[identifierPtr--];
196 // identifierLengthPtr--;
199 // cd.declarationSourceStart = intStack[intPtr--];
200 // cd.modifiers = intStack[intPtr--];
202 // //highlight starts at the selector starts
203 // cd.sourceStart = (int) (selectorSourcePositions >>> 32);
204 // cd.selectorSourceEnd = (int) selectorSourcePositions;
205 // pushOnAstStack(cd);
207 // cd.sourceEnd = lParenPos;
208 // cd.bodyStart = lParenPos+1;
209 // listLength = 0; // initialize listLength before reading parameters/throws
212 // if (currentElement != null){
213 // lastCheckPoint = cd.bodyStart;
214 // if ((currentElement instanceof RecoveredType && lastIgnoredToken !=
216 // || cd.modifiers != 0){
217 // currentElement = currentElement.add(cd, 0);
218 // lastIgnoredToken = -1;
224 // * INTERNAL USE-ONLY
226 // protected void consumeExitVariableWithInitialization() {
227 // // ExitVariableWithInitialization ::= $empty
228 // // the scanner is located after the comma or the semi-colon.
229 // // we want to include the comma or the semi-colon
230 // super.consumeExitVariableWithInitialization();
231 // if (isLocalDeclaration() || ((currentToken != TokenNameCOMMA) &&
232 // (currentToken != TokenNameSEMICOLON)))
234 // ((SourceFieldDeclaration) astStack[astPtr]).fieldEndPosition =
235 // scanner.currentPosition - 1;
237 // protected void consumeExitVariableWithoutInitialization() {
238 // // ExitVariableWithoutInitialization ::= $empty
239 // // do nothing by default
240 // super.consumeExitVariableWithoutInitialization();
241 // if (isLocalDeclaration() || ((currentToken != TokenNameCOMMA) &&
242 // (currentToken != TokenNameSEMICOLON)))
244 // ((SourceFieldDeclaration) astStack[astPtr]).fieldEndPosition =
245 // scanner.currentPosition - 1;
249 // * INTERNAL USE-ONLY
251 // protected void consumeFieldAccess(boolean isSuperAccess) {
252 // // FieldAccess ::= Primary '.' 'Identifier'
253 // // FieldAccess ::= 'super' '.' 'Identifier'
254 // super.consumeFieldAccess(isSuperAccess);
255 // FieldReference fr = (FieldReference) expressionStack[expressionPtr];
256 // if (reportReferenceInfo) {
257 // requestor.acceptFieldReference(fr.token, fr.sourceStart);
260 // protected void consumeMethodHeaderName() {
261 // // MethodHeaderName ::= Modifiersopt Type 'Identifier' '('
262 // SourceMethodDeclaration md = new
263 // SourceMethodDeclaration(this.compilationUnit.compilationResult);
266 // md.selector = identifierStack[identifierPtr];
267 // long selectorSourcePositions = identifierPositionStack[identifierPtr--];
268 // identifierLengthPtr--;
270 // md.returnType = getTypeReference(intStack[intPtr--]);
272 // md.declarationSourceStart = intStack[intPtr--];
273 // md.modifiers = intStack[intPtr--];
275 // //highlight starts at selector start
276 // md.sourceStart = (int) (selectorSourcePositions >>> 32);
277 // md.selectorSourceEnd = (int) selectorSourcePositions;
278 // pushOnAstStack(md);
279 // md.sourceEnd = lParenPos;
280 // md.bodyStart = lParenPos+1;
281 // listLength = 0; // initialize listLength before reading parameters/throws
284 // if (currentElement != null){
285 // if (currentElement instanceof RecoveredType
286 // //|| md.modifiers != 0
287 // || (scanner.getLineNumber(md.returnType.sourceStart)
288 // == scanner.getLineNumber(md.sourceStart))){
289 // lastCheckPoint = md.bodyStart;
290 // currentElement = currentElement.add(md, 0);
291 // lastIgnoredToken = -1;
293 // lastCheckPoint = md.sourceStart;
294 // restartRecovery = true;
300 // * INTERNAL USE-ONLY
302 // protected void consumeMethodInvocationName() {
303 // // MethodInvocation ::= Name '(' ArgumentListopt ')'
305 // // when the name is only an identifier...we have a message send to "this"
307 // super.consumeMethodInvocationName();
308 // MessageSend messageSend = (MessageSend) expressionStack[expressionPtr];
309 // Expression[] args = messageSend.arguments;
310 // if (reportReferenceInfo) {
311 // requestor.acceptMethodReference(
312 // messageSend.selector,
313 // args == null ? 0 : args.length,
314 // (int)(messageSend.nameSourcePosition >>> 32));
319 // * INTERNAL USE-ONLY
321 // protected void consumeMethodInvocationPrimary() {
322 // super.consumeMethodInvocationPrimary();
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));
334 // * INTERNAL USE-ONLY
336 // protected void consumeMethodInvocationSuper() {
337 // // MethodInvocation ::= 'super' '.' 'Identifier' '(' ArgumentListopt ')'
338 // super.consumeMethodInvocationSuper();
339 // MessageSend messageSend = (MessageSend) expressionStack[expressionPtr];
340 // Expression[] args = messageSend.arguments;
341 // if (reportReferenceInfo) {
342 // requestor.acceptMethodReference(
343 // messageSend.selector,
344 // args == null ? 0 : args.length,
345 // (int)(messageSend.nameSourcePosition >>> 32));
348 // protected void consumeSingleTypeImportDeclarationName() {
349 // // SingleTypeImportDeclarationName ::= 'import' Name
350 // /* push an ImportRef build from the last name
351 // stored in the identifier stack. */
353 // super.consumeSingleTypeImportDeclarationName();
354 // ImportReference impt = (ImportReference)astStack[astPtr];
355 // if (reportReferenceInfo) {
356 // requestor.acceptTypeReference(impt.tokens, impt.sourceStart,
360 // protected void consumeTypeImportOnDemandDeclarationName() {
361 // // TypeImportOnDemandDeclarationName ::= 'import' Name '.' '*'
362 // /* push an ImportRef build from the last name
363 // stored in the identifier stack. */
365 // super.consumeTypeImportOnDemandDeclarationName();
366 // ImportReference impt = (ImportReference)astStack[astPtr];
367 // if (reportReferenceInfo) {
368 // requestor.acceptUnknownReference(impt.tokens, impt.sourceStart,
372 // protected FieldDeclaration createFieldDeclaration(Expression
373 // initialization, char[] name, int sourceStart, int sourceEnd) {
374 // return new SourceFieldDeclaration(null, name, sourceStart, sourceEnd);
376 // protected CompilationUnitDeclaration endParse(int act) {
377 // if (sourceType != null) {
378 // if (sourceType.isInterface()) {
379 // consumeInterfaceDeclaration();
381 // consumeClassDeclaration();
384 // if (compilationUnit != null) {
385 // CompilationUnitDeclaration result = super.endParse(act);
392 * Flush annotations defined prior to a given positions.
394 * Note: annotations are stacked in syntactical order
396 * Either answer given <position>, or the end position of a comment line
397 * immediately following the <position> (same line)
399 * e.g. void foo(){ } // end of method foo
402 // public int flushAnnotationsDefinedPriorTo(int position) {
404 // return lastFieldEndPosition =
405 // super.flushAnnotationsDefinedPriorTo(position);
407 // public TypeReference getTypeReference(int dim) {
408 // /* build a Reference on a variable that may be qualified or not
409 // * This variable is a type reference and dim will be its dimensions
412 // if ((length = identifierLengthStack[identifierLengthPtr--]) == 1) {
413 // // single variable reference
415 // SingleTypeReference ref =
416 // new SingleTypeReference(
417 // identifierStack[identifierPtr],
418 // identifierPositionStack[identifierPtr--]);
419 // if (reportReferenceInfo) {
420 // requestor.acceptTypeReference(ref.token, ref.sourceStart);
424 // ArrayTypeReference ref =
425 // new ArrayTypeReference(
426 // identifierStack[identifierPtr],
428 // identifierPositionStack[identifierPtr--]);
429 // ref.sourceEnd = endPosition;
430 // if (reportReferenceInfo) {
431 // requestor.acceptTypeReference(ref.token, ref.sourceStart);
436 // if (length < 0) { //flag for precompiled type reference on base types
437 // TypeReference ref = TypeReference.baseTypeReference(-length, dim);
438 // ref.sourceStart = intStack[intPtr--];
440 // ref.sourceEnd = intStack[intPtr--];
442 // intPtr--; // no need to use this position as it is an array
443 // ref.sourceEnd = endPosition;
445 // if (reportReferenceInfo){
446 // requestor.acceptTypeReference(ref.getTypeName(), ref.sourceStart,
450 // } else { //Qualified variable reference
451 // char[][] tokens = new char[length][];
452 // identifierPtr -= length;
453 // long[] positions = new long[length];
454 // System.arraycopy(identifierStack, identifierPtr + 1, tokens, 0, length);
456 // identifierPositionStack,
457 // identifierPtr + 1,
462 // QualifiedTypeReference ref = new QualifiedTypeReference(tokens,
464 // if (reportReferenceInfo) {
465 // requestor.acceptTypeReference(ref.tokens, ref.sourceStart,
470 // ArrayQualifiedTypeReference ref =
471 // new ArrayQualifiedTypeReference(tokens, dim, positions);
472 // ref.sourceEnd = endPosition;
473 // if (reportReferenceInfo) {
474 // requestor.acceptTypeReference(ref.tokens, ref.sourceStart,
482 // public NameReference getUnspecifiedReference() {
483 // /* build a (unspecified) NameReference which may be qualified*/
486 // if ((length = identifierLengthStack[identifierLengthPtr--]) == 1) {
487 // // single variable reference
488 // SingleNameReference ref =
489 // new SingleNameReference(
490 // identifierStack[identifierPtr],
491 // identifierPositionStack[identifierPtr--]);
492 // if (reportReferenceInfo) {
493 // this.addUnknownRef(ref);
497 // //Qualified variable reference
498 // char[][] tokens = new char[length][];
499 // identifierPtr -= length;
500 // System.arraycopy(identifierStack, identifierPtr + 1, tokens, 0, length);
501 // QualifiedNameReference ref =
502 // new QualifiedNameReference(
504 // (int) (identifierPositionStack[identifierPtr + 1] >> 32), // sourceStart
505 // (int) identifierPositionStack[identifierPtr + length]); // sourceEnd
506 // if (reportReferenceInfo) {
507 // this.addUnknownRef(ref);
512 // public NameReference getUnspecifiedReferenceOptimized() {
513 // /* build a (unspecified) NameReference which may be qualified
514 // The optimization occurs for qualified reference while we are
515 // certain in this case the last item of the qualified name is
516 // a field access. This optimization is IMPORTANT while it results
517 // that when a NameReference is build, the type checker should always
518 // look for that it is not a type reference */
521 // if ((length = identifierLengthStack[identifierLengthPtr--]) == 1) {
522 // // single variable reference
523 // SingleNameReference ref =
524 // new SingleNameReference(
525 // identifierStack[identifierPtr],
526 // identifierPositionStack[identifierPtr--]);
527 // ref.bits &= ~ASTNode.RestrictiveFlagMASK;
528 // ref.bits |= LOCAL | FIELD;
529 // if (reportReferenceInfo) {
530 // this.addUnknownRef(ref);
535 // //Qualified-variable-reference
536 // //In fact it is variable-reference DOT field-ref , but it would result in
539 // //conflict tha can be only reduce by making a superclass (or inetrface )
541 // //nameReference and FiledReference or putting FieldReference under
543 // //or else..........This optimisation is not really relevant so just leave
546 // char[][] tokens = new char[length][];
547 // identifierPtr -= length;
548 // System.arraycopy(identifierStack, identifierPtr + 1, tokens, 0, length);
549 // QualifiedNameReference ref =
550 // new QualifiedNameReference(
552 // (int) (identifierPositionStack[identifierPtr + 1] >> 32),
554 // (int) identifierPositionStack[identifierPtr + length]); // sourceEnd
555 // ref.bits &= ~ASTNode.RestrictiveFlagMASK;
556 // ref.bits |= LOCAL | FIELD;
557 // if (reportReferenceInfo) {
558 // this.addUnknownRef(ref);
564 // * INTERNAL USE-ONLY
566 // private boolean isLocalDeclaration() {
567 // int nestedDepth = nestedType;
568 // while (nestedDepth >= 0) {
569 // if (nestedMethod[nestedDepth] != 0) {
577 * Update the bodyStart of the corresponding parse node
579 public void notifySourceElementRequestor(
580 CompilationUnitDeclaration parsedUnit) {
581 if (parsedUnit == null) {
582 // when we parse a single type member declaration the compilation
584 // null, but we still
585 // want to be able to notify the requestor on the created ast node
586 if (astStack[0] instanceof AbstractMethodDeclaration) {
587 notifySourceElementRequestor((AbstractMethodDeclaration) astStack[0]);
593 boolean isInRange = scanner.initialPosition <= parsedUnit.sourceStart
594 && scanner.eofPosition >= parsedUnit.sourceEnd;
596 // if (reportReferenceInfo) {
597 // notifyAllUnknownReferences();
599 // collect the top level ast nodes
601 ASTNode[] nodes = null;
602 if (sourceType == null) {
604 requestor.enterCompilationUnit();
606 // ImportReference currentPackage = parsedUnit.currentPackage;
607 ImportReference[] imports = parsedUnit.imports;
608 // TypeDeclaration[] types = parsedUnit.types;
609 ArrayList types = parsedUnit.types;
612 // (currentPackage == null ? 0 : 1)
613 // + (imports == null ? 0 : imports.length)
614 // + (types == null ? 0 : types.length);
615 // nodes = new ASTNode[length];
616 length = (imports == null ? 0 : imports.length) + types.size();
617 nodes = new ASTNode[length];
619 // if (currentPackage != null) {
620 // nodes[index++] = currentPackage;
622 if (imports != null) {
623 for (int i = 0, max = imports.length; i < max; i++) {
624 nodes[index++] = imports[i];
628 for (int i = 0, max = types.size(); i < max; i++) {
629 nodes[index++] = (ASTNode) types.get(i);
633 // TypeDeclaration[] types = parsedUnit.types;
634 ArrayList types = parsedUnit.types;
636 length = types.size();
637 nodes = new ASTNode[length];
638 for (int i = 0, max = types.size(); i < max; i++) {
639 nodes[i] = (ASTNode) types.get(i);
644 // notify the nodes in the syntactical order
645 if (nodes != null && length > 0) {
646 quickSort(nodes, 0, length - 1);
647 for (int i = 0; i < length; i++) {
648 ASTNode node = nodes[i];
649 if (node instanceof ImportReference) {
650 ImportReference importRef = (ImportReference) node;
651 // if (node == parsedUnit.currentPackage) {
652 // notifySourceElementRequestor(importRef, true);
654 notifySourceElementRequestor(importRef, false);
656 } // else { instanceof TypeDeclaration
657 if (node instanceof TypeDeclaration) {
658 notifySourceElementRequestor((TypeDeclaration) node,
660 // notifySourceElementRequestor((CompilationUnitDeclaration)node,
661 // sourceType == null);
663 // jsurfer - INSERT start
664 if (node instanceof AbstractMethodDeclaration) {
665 notifySourceElementRequestor((AbstractMethodDeclaration) node);
667 // jsurfer - INSERT end
671 if (sourceType == null) {
673 requestor.exitCompilationUnit(parsedUnit.sourceEnd);
678 // private void notifyAllUnknownReferences() {
679 // for (int i = 0, max = this.unknownRefsCounter; i < max; i++) {
680 // NameReference nameRef = this.unknownRefs[i];
681 // if ((nameRef.bits & BindingIds.VARIABLE) != 0) {
682 // if ((nameRef.bits & BindingIds.TYPE) == 0) {
683 // // variable but not type
684 // if (nameRef instanceof SingleNameReference) {
685 // // local var or field
686 // requestor.acceptUnknownReference(((SingleNameReference) nameRef).token,
687 // nameRef.sourceStart);
689 // // QualifiedNameReference
690 // // The last token is a field reference and the previous tokens are a
691 // type/variable references
692 // char[][] tokens = ((QualifiedNameReference) nameRef).tokens;
693 // int tokensLength = tokens.length;
694 // requestor.acceptFieldReference(tokens[tokensLength - 1],
696 // - tokens[tokensLength - 1].length + 1);
697 // char[][] typeRef = new char[tokensLength - 1][];
698 // System.arraycopy(tokens, 0, typeRef, 0, tokensLength - 1);
699 // requestor.acceptUnknownReference(typeRef, nameRef.sourceStart,
700 // nameRef.sourceEnd - tokens[tokensLength - 1].length);
703 // // variable or type
704 // if (nameRef instanceof SingleNameReference) {
705 // requestor.acceptUnknownReference(((SingleNameReference) nameRef).token,
706 // nameRef.sourceStart);
708 // //QualifiedNameReference
709 // requestor.acceptUnknownReference(((QualifiedNameReference)
711 // nameRef.sourceStart, nameRef.sourceEnd);
714 // } else if ((nameRef.bits & BindingIds.TYPE) != 0) {
715 // if (nameRef instanceof SingleNameReference) {
716 // requestor.acceptTypeReference(((SingleNameReference) nameRef).token,
717 // nameRef.sourceStart);
719 // // it is a QualifiedNameReference
720 // requestor.acceptTypeReference(((QualifiedNameReference) nameRef).tokens,
721 // nameRef.sourceStart, nameRef.sourceEnd);
727 * Update the bodyStart of the corresponding parse node
729 public void notifySourceElementRequestor(
730 AbstractMethodDeclaration methodDeclaration) {
733 boolean isInRange = scanner.initialPosition <= methodDeclaration.declarationSourceStart
734 && scanner.eofPosition >= methodDeclaration.declarationSourceEnd;
736 if (methodDeclaration.isClinit()) {
737 this.visitIfNeeded(methodDeclaration);
741 if (methodDeclaration.isDefaultConstructor()) {
742 if (reportReferenceInfo) {
743 ConstructorDeclaration constructorDeclaration = (ConstructorDeclaration) methodDeclaration;
744 ExplicitConstructorCall constructorCall = constructorDeclaration.constructorCall;
745 if (constructorCall != null) {
746 switch (constructorCall.accessMode) {
747 case ExplicitConstructorCall.This:
748 requestor.acceptConstructorReference(
749 typeNames[nestedTypeIndex - 1],
750 constructorCall.arguments == null ? 0
751 : constructorCall.arguments.length,
752 constructorCall.sourceStart);
754 case ExplicitConstructorCall.Super:
755 case ExplicitConstructorCall.ImplicitSuper:
756 requestor.acceptConstructorReference(
757 superTypeNames[nestedTypeIndex - 1],
758 constructorCall.arguments == null ? 0
759 : constructorCall.arguments.length,
760 constructorCall.sourceStart);
767 char[][] argumentTypes = null;
768 char[][] argumentNames = null;
769 Argument[] arguments = methodDeclaration.arguments;
770 if (arguments != null) {
771 int argumentLength = arguments.length;
772 argumentTypes = new char[argumentLength][];
773 argumentNames = new char[argumentLength][];
774 for (int i = 0; i < argumentLength; i++) {
775 argumentTypes[i] = returnTypeName(arguments[i].type);
776 argumentNames[i] = arguments[i].name;
779 char[][] thrownExceptionTypes = null;
780 TypeReference[] thrownExceptions = methodDeclaration.thrownExceptions;
781 if (thrownExceptions != null) {
782 int thrownExceptionLength = thrownExceptions.length;
783 thrownExceptionTypes = new char[thrownExceptionLength][];
784 for (int i = 0; i < thrownExceptionLength; i++) {
785 thrownExceptionTypes[i] = CharOperation.concatWith(
786 thrownExceptions[i].getTypeName(), '.');
789 // by default no selector end position
790 int selectorSourceEnd = -1;
791 if (methodDeclaration.isConstructor()) {
792 // if (methodDeclaration instanceof SourceConstructorDeclaration) {
793 // selectorSourceEnd =
794 // ((SourceConstructorDeclaration)
795 // methodDeclaration).selectorSourceEnd;
798 requestor.enterConstructor(
799 methodDeclaration.declarationSourceStart,
800 methodDeclaration.modifiers,
801 methodDeclaration.selector,
802 methodDeclaration.sourceStart, selectorSourceEnd,
803 argumentTypes, argumentNames, thrownExceptionTypes);
805 if (reportReferenceInfo) {
806 ConstructorDeclaration constructorDeclaration = (ConstructorDeclaration) methodDeclaration;
807 ExplicitConstructorCall constructorCall = constructorDeclaration.constructorCall;
808 if (constructorCall != null) {
809 switch (constructorCall.accessMode) {
810 case ExplicitConstructorCall.This:
811 requestor.acceptConstructorReference(
812 typeNames[nestedTypeIndex - 1],
813 constructorCall.arguments == null ? 0
814 : constructorCall.arguments.length,
815 constructorCall.sourceStart);
817 case ExplicitConstructorCall.Super:
818 case ExplicitConstructorCall.ImplicitSuper:
819 requestor.acceptConstructorReference(
820 superTypeNames[nestedTypeIndex - 1],
821 constructorCall.arguments == null ? 0
822 : constructorCall.arguments.length,
823 constructorCall.sourceStart);
828 this.visitIfNeeded(methodDeclaration);
831 .exitConstructor(methodDeclaration.declarationSourceEnd);
835 // if (methodDeclaration instanceof SourceMethodDeclaration) {
836 // selectorSourceEnd =
837 // ((SourceMethodDeclaration) methodDeclaration).selectorSourceEnd;
840 int modifiers = methodDeclaration.modifiers;
841 // boolean deprecated = (modifiers & AccDeprecated) != 0; //
843 // deprecation so as to not lose it below
846 methodDeclaration.declarationSourceStart,
847 modifiers, // deprecated
858 returnTypeName(((MethodDeclaration) methodDeclaration).returnType),
859 methodDeclaration.selector,
860 methodDeclaration.sourceStart, selectorSourceEnd,
861 argumentTypes, argumentNames, thrownExceptionTypes);
863 this.visitIfNeeded(methodDeclaration);
866 requestor.exitMethod(methodDeclaration.declarationSourceEnd);
871 * Update the bodyStart of the corresponding parse node
873 public void notifySourceElementRequestor(FieldDeclaration fieldDeclaration) {
876 boolean isInRange = scanner.initialPosition <= fieldDeclaration.declarationSourceStart
877 && scanner.eofPosition >= fieldDeclaration.declarationSourceEnd;
879 if (fieldDeclaration.isField()) {
880 int fieldEndPosition = fieldDeclaration.declarationSourceEnd;
881 // if (fieldDeclaration instanceof SourceFieldDeclaration) {
882 // fieldEndPosition = ((SourceFieldDeclaration)
883 // fieldDeclaration).fieldEndPosition;
884 // if (fieldEndPosition == 0) {
885 // // use the declaration source end by default
886 // fieldEndPosition = fieldDeclaration.declarationSourceEnd;
890 int modifiers = fieldDeclaration.modifiers;
891 boolean deprecated = (modifiers & AccDeprecated) != 0; // remember
895 requestor.enterField(fieldDeclaration.declarationSourceStart,
896 deprecated ? (modifiers & AccJustFlag) | AccDeprecated
897 : modifiers & AccJustFlag,
898 returnTypeName(fieldDeclaration.type),
899 fieldDeclaration.name, fieldDeclaration.sourceStart,
900 fieldDeclaration.sourceEnd);
902 // this.visitIfNeeded(fieldDeclaration);
904 // requestor.exitField(
905 // // filter out initializations that are not a constant (simple
907 // (fieldDeclaration.initialization == null
908 // || fieldDeclaration.initialization instanceof
910 // || fieldDeclaration.initialization instanceof
911 // AllocationExpression
912 // || fieldDeclaration.initialization instanceof
913 // ArrayAllocationExpression
914 // || fieldDeclaration.initialization instanceof Assignment
915 // || fieldDeclaration.initialization instanceof
916 // ClassLiteralAccess
917 // || fieldDeclaration.initialization instanceof MessageSend
918 // || fieldDeclaration.initialization instanceof ArrayReference
919 // || fieldDeclaration.initialization instanceof ThisReference)
922 // fieldDeclaration.initialization.sourceStart,
924 // fieldDeclaration.declarationSourceEnd);
926 // filter out initializations that are not a constant
928 -1, fieldEndPosition,
929 fieldDeclaration.declarationSourceEnd);
934 // requestor.enterInitializer(
935 // fieldDeclaration.declarationSourceStart,
936 // fieldDeclaration.modifiers);
938 // this.visitIfNeeded((Initializer)fieldDeclaration);
940 // requestor.exitInitializer(fieldDeclaration.declarationSourceEnd);
945 public void notifySourceElementRequestor(ImportReference importReference,
948 // requestor.acceptPackage(
949 // importReference.declarationSourceStart,
950 // importReference.declarationSourceEnd,
951 // CharOperation.concatWith(importReference.getImportName(), '.'));
953 requestor.acceptImport(importReference.declarationSourceStart,
954 importReference.declarationSourceEnd, importReference
955 .getIncludeName(), // CharOperation.concatWith(importReference.getImportName(),
957 importReference.onDemand);
961 public void notifySourceElementRequestor(TypeDeclaration typeDeclaration,
962 boolean notifyTypePresence) {
963 // // public void notifySourceElementRequestor(ASTNode typeDeclaration,
964 // boolean notifyTypePresence) {
967 boolean isInRange = scanner.initialPosition <= typeDeclaration.declarationSourceStart
968 && scanner.eofPosition >= typeDeclaration.declarationSourceEnd;
970 FieldDeclaration[] fields = typeDeclaration.fields;
971 AbstractMethodDeclaration[] methods = typeDeclaration.methods;
972 TypeDeclaration[] memberTypes = typeDeclaration.memberTypes;
973 int fieldCount = fields == null ? 0 : fields.length;
974 int methodCount = methods == null ? 0 : methods.length;
975 int memberTypeCount = memberTypes == null ? 0 : memberTypes.length;
978 int memberTypeIndex = 0;
979 boolean isInterface = typeDeclaration.isInterface();
981 if (notifyTypePresence) {
982 char[][] interfaceNames = null;
983 int superInterfacesLength = 0;
984 TypeReference[] superInterfaces = typeDeclaration.superInterfaces;
985 if (superInterfaces != null) {
986 superInterfacesLength = superInterfaces.length;
987 interfaceNames = new char[superInterfacesLength][];
989 if (typeDeclaration instanceof AnonymousLocalTypeDeclaration) {
991 QualifiedAllocationExpression alloc = ((AnonymousLocalTypeDeclaration) typeDeclaration).allocation;
992 if (alloc != null && alloc.type != null) {
993 superInterfaces = new TypeReference[] { ((AnonymousLocalTypeDeclaration) typeDeclaration).allocation.type };
994 superInterfacesLength = 1;
995 interfaceNames = new char[1][];
999 if (superInterfaces != null) {
1000 for (int i = 0; i < superInterfacesLength; i++) {
1001 interfaceNames[i] = CharOperation.concatWith(
1002 superInterfaces[i].getTypeName(), '.');
1007 int modifiers = typeDeclaration.modifiers;
1008 boolean deprecated = false; // (modifiers & AccDeprecated)
1010 // remember deprecation so as to not lose
1012 requestor.enterInterface(
1013 typeDeclaration.declarationSourceStart,
1014 modifiers, // deprecated
1025 typeDeclaration.name, typeDeclaration.sourceStart,
1026 typeDeclaration.sourceEnd, interfaceNames);
1028 if (nestedTypeIndex == typeNames.length) {
1030 System.arraycopy(typeNames, 0,
1031 (typeNames = new char[nestedTypeIndex * 2][]), 0,
1033 System.arraycopy(superTypeNames, 0,
1034 (superTypeNames = new char[nestedTypeIndex * 2][]),
1035 0, nestedTypeIndex);
1037 typeNames[nestedTypeIndex] = typeDeclaration.name;
1038 superTypeNames[nestedTypeIndex++] = JAVA_LANG_OBJECT;
1040 TypeReference superclass = typeDeclaration.superclass;
1041 if (superclass == null) {
1045 typeDeclaration.declarationSourceStart,
1046 typeDeclaration.modifiers,
1047 typeDeclaration.name,
1048 typeDeclaration.sourceStart,
1049 typeDeclaration.sourceEnd, null,
1054 requestor.enterClass(
1055 typeDeclaration.declarationSourceStart,
1056 typeDeclaration.modifiers,
1057 typeDeclaration.name,
1058 typeDeclaration.sourceStart,
1059 typeDeclaration.sourceEnd, CharOperation
1060 .concatWith(superclass.getTypeName(),
1061 '.'), interfaceNames);
1064 if (nestedTypeIndex == typeNames.length) {
1066 System.arraycopy(typeNames, 0,
1067 (typeNames = new char[nestedTypeIndex * 2][]), 0,
1069 System.arraycopy(superTypeNames, 0,
1070 (superTypeNames = new char[nestedTypeIndex * 2][]),
1071 0, nestedTypeIndex);
1073 typeNames[nestedTypeIndex] = typeDeclaration.name;
1074 superTypeNames[nestedTypeIndex++] = superclass == null ? JAVA_LANG_OBJECT
1075 : CharOperation.concatWith(superclass.getTypeName(),
1079 while ((fieldIndex < fieldCount) || (memberTypeIndex < memberTypeCount)
1080 || (methodIndex < methodCount)) {
1081 FieldDeclaration nextFieldDeclaration = null;
1082 AbstractMethodDeclaration nextMethodDeclaration = null;
1083 TypeDeclaration nextMemberDeclaration = null;
1085 int position = Integer.MAX_VALUE;
1086 int nextDeclarationType = -1;
1087 if (fieldIndex < fieldCount) {
1088 nextFieldDeclaration = fields[fieldIndex];
1089 if (nextFieldDeclaration.declarationSourceStart < position) {
1090 position = nextFieldDeclaration.declarationSourceStart;
1091 nextDeclarationType = 0; // FIELD
1094 if (methodIndex < methodCount) {
1095 nextMethodDeclaration = methods[methodIndex];
1096 if (nextMethodDeclaration.declarationSourceStart < position) {
1097 position = nextMethodDeclaration.declarationSourceStart;
1098 nextDeclarationType = 1; // METHOD
1101 if (memberTypeIndex < memberTypeCount) {
1102 nextMemberDeclaration = memberTypes[memberTypeIndex];
1103 if (nextMemberDeclaration.declarationSourceStart < position) {
1104 position = nextMemberDeclaration.declarationSourceStart;
1105 nextDeclarationType = 2; // MEMBER
1108 switch (nextDeclarationType) {
1111 notifySourceElementRequestor(nextFieldDeclaration);
1115 notifySourceElementRequestor(nextMethodDeclaration);
1119 notifySourceElementRequestor(nextMemberDeclaration, true);
1122 if (notifyTypePresence) {
1126 .exitInterface(typeDeclaration.declarationSourceEnd);
1128 requestor.exitClass(typeDeclaration.declarationSourceEnd);
1135 public void parseCompilationUnit(ICompilationUnit unit, int start, int end) {
1136 // boolean needReferenceInfo) {
1138 // reportReferenceInfo = needReferenceInfo;
1139 // boolean old = diet;
1140 // if (needReferenceInfo) {
1141 // unknownRefs = new NameReference[10];
1142 // unknownRefsCounter = 0;
1147 CompilationResult compilationUnitResult = new CompilationResult(
1148 unit, 0, 0, 10); // this.options.maxProblemsPerUnit);
1149 CompilationUnitDeclaration parsedUnit = parse(unit,
1150 compilationUnitResult, start, end);
1151 // if (scanner.recordLineSeparator) {
1152 // requestor.acceptLineSeparatorPositions(scanner.getLineEnds());
1154 // if (this.localDeclarationVisitor != null || needReferenceInfo){
1156 // this.getMethodBodies(parsedUnit);
1158 // this.scanner.resetTo(start, end);
1159 // notifySourceElementRequestor(parsedUnit);
1160 } catch (AbortCompilation e) {
1166 public CompilationUnitDeclaration parseCompilationUnit(
1167 ICompilationUnit unit, boolean fullParse) {
1169 // boolean old = diet;
1171 // unknownRefs = new NameReference[10];
1172 // unknownRefsCounter = 0;
1177 this.reportReferenceInfo = fullParse;
1178 CompilationResult compilationUnitResult = new CompilationResult(
1179 unit, 0, 0, this.options.maxProblemsPerUnit);
1180 CompilationUnitDeclaration parsedUnit = parse(unit,
1181 compilationUnitResult, false);
1182 if (scanner.recordLineSeparator) {
1183 requestor.acceptLineSeparatorPositions(scanner.getLineEnds());
1185 int initialStart = this.scanner.initialPosition;
1186 int initialEnd = this.scanner.eofPosition;
1187 // if (this.localDeclarationVisitor != null || fullParse){
1189 // this.getMethodBodies(parsedUnit);
1191 this.scanner.resetTo(initialStart, initialEnd);
1192 notifySourceElementRequestor(parsedUnit);
1194 } catch (AbortCompilation e) {
1195 // ignore this exception
1202 public CompilationUnitDeclaration parseCompletionUnit(
1203 ICompilationUnit unit, boolean fullParse) {
1205 // boolean old = diet;
1207 // unknownRefs = new NameReference[10];
1208 // unknownRefsCounter = 0;
1213 this.reportReferenceInfo = fullParse;
1214 CompilationResult compilationUnitResult = new CompilationResult(
1215 unit, 0, 0, this.options.maxProblemsPerUnit);
1216 CompilationUnitDeclaration parsedUnit = parse(unit,
1217 compilationUnitResult, false);
1218 // if (scanner.recordLineSeparator) {
1219 // requestor.acceptLineSeparatorPositions(scanner.getLineEnds());
1221 // int initialStart = this.scanner.initialPosition;
1222 // int initialEnd = this.scanner.eofPosition;
1223 // // if (this.localDeclarationVisitor != null || fullParse){
1225 // // this.getMethodBodies(parsedUnit);
1227 // this.scanner.resetTo(initialStart, initialEnd);
1228 // notifySourceElementRequestor(parsedUnit);
1230 } catch (AbortCompilation e) {
1231 // ignore this exception
1238 // public void parseTypeMemberDeclarations(
1239 // ISourceType sourceType,
1240 // ICompilationUnit sourceUnit,
1243 // boolean needReferenceInfo) {
1244 // boolean old = diet;
1245 // if (needReferenceInfo) {
1246 // unknownRefs = new NameReference[10];
1247 // unknownRefsCounter = 0;
1251 // diet = !needReferenceInfo;
1252 // reportReferenceInfo = needReferenceInfo;
1253 // CompilationResult compilationUnitResult =
1254 // new CompilationResult(sourceUnit, 0, 0, this.options.maxProblemsPerUnit);
1255 // CompilationUnitDeclaration unit =
1256 // SourceTypeConverter.buildCompilationUnit(
1257 // new ISourceType[]{sourceType},
1258 // false, // no need for field and methods
1259 // false, // no need for member types
1260 // false, // no need for field initialization
1261 // problemReporter(),
1262 // compilationUnitResult);
1263 // if ((unit == null) || (unit.types == null) || (unit.types.length != 1))
1265 // this.sourceType = sourceType;
1267 // /* automaton initialization */
1269 // goForClassBodyDeclarations();
1270 // /* scanner initialization */
1271 // scanner.setSource(sourceUnit.getContents());
1272 // scanner.resetTo(start, end);
1273 // /* unit creation */
1274 // referenceContext = compilationUnit = unit;
1275 // /* initialize the astStacl */
1276 // // the compilationUnitDeclaration should contain exactly one type
1277 // pushOnAstStack(unit.types[0]);
1278 // /* run automaton */
1280 // notifySourceElementRequestor(unit);
1282 // unit = compilationUnit;
1283 // compilationUnit = null; // reset parser
1285 // } catch (AbortCompilation e) {
1287 // if (scanner.recordLineSeparator) {
1288 // requestor.acceptLineSeparatorPositions(scanner.getLineEnds());
1294 // public void parseTypeMemberDeclarations(
1299 // boolean old = diet;
1304 // /* automaton initialization */
1306 // goForClassBodyDeclarations();
1307 // /* scanner initialization */
1308 // scanner.setSource(contents);
1309 // scanner.recordLineSeparator = false;
1310 // scanner.taskTags = null;
1311 // scanner.taskPriorities = null;
1312 // scanner.resetTo(start, end);
1314 // /* unit creation */
1315 // referenceContext = null;
1317 // /* initialize the astStacl */
1318 // // the compilationUnitDeclaration should contain exactly one type
1319 // /* run automaton */
1321 // notifySourceElementRequestor((CompilationUnitDeclaration)null);
1322 // } catch (AbortCompilation e) {
1328 * Sort the given ast nodes by their positions.
1330 private static void quickSort(ASTNode[] sortedCollection, int left,
1332 int original_left = left;
1333 int original_right = right;
1334 ASTNode mid = sortedCollection[(left + right) / 2];
1336 while (sortedCollection[left].sourceStart < mid.sourceStart) {
1339 while (mid.sourceStart < sortedCollection[right].sourceStart) {
1342 if (left <= right) {
1343 ASTNode tmp = sortedCollection[left];
1344 sortedCollection[left] = sortedCollection[right];
1345 sortedCollection[right] = tmp;
1349 } while (left <= right);
1350 if (original_left < right) {
1351 quickSort(sortedCollection, original_left, right);
1353 if (left < original_right) {
1354 quickSort(sortedCollection, left, original_right);
1359 * Answer a char array representation of the type name formatted like: -
1360 * type name + dimensions Example: "A[][]".toCharArray()
1361 * "java.lang.String".toCharArray()
1363 private char[] returnTypeName(TypeReference type) {
1366 int dimension = type.dimensions();
1367 if (dimension != 0) {
1368 char[] dimensionsArray = new char[dimension * 2];
1369 for (int i = 0; i < dimension; i++) {
1370 dimensionsArray[i * 2] = '[';
1371 dimensionsArray[(i * 2) + 1] = ']';
1373 return CharOperation.concat(CharOperation.concatWith(type
1374 .getTypeName(), '.'), dimensionsArray);
1376 return CharOperation.concatWith(type.getTypeName(), '.');
1379 public void addUnknownRef(NameReference nameRef) {
1380 if (this.unknownRefs.length == this.unknownRefsCounter) {
1386 (this.unknownRefs = new NameReference[this.unknownRefsCounter * 2]),
1387 0, this.unknownRefsCounter);
1389 this.unknownRefs[this.unknownRefsCounter++] = nameRef;
1392 private void visitIfNeeded(AbstractMethodDeclaration method) {
1393 if (this.localDeclarationVisitor != null
1394 && (method.bits & ASTNode.HasLocalTypeMASK) != 0) {
1395 if (method.statements != null) {
1396 int statementsLength = method.statements.length;
1397 for (int i = 0; i < statementsLength; i++)
1398 method.statements[i].traverse(this.localDeclarationVisitor,
1404 // private void visitIfNeeded(FieldDeclaration field) {
1405 // if (this.localDeclarationVisitor != null
1406 // && (field.bits & ASTNode.HasLocalTypeMASK) != 0) {
1407 // if (field.initialization != null) {
1408 // field.initialization.traverse(this.localDeclarationVisitor, null);
1413 // private void visitIfNeeded(Initializer initializer) {
1414 // if (this.localDeclarationVisitor != null
1415 // && (initializer.bits & ASTNode.HasLocalTypeMASK) != 0) {
1416 // if (initializer.block != null) {
1417 // initializer.block.traverse(this.localDeclarationVisitor, null);
1422 // protected void reportSyntaxError(int act, int currentKind, int
1424 // if (compilationUnit == null) return;
1425 // super.reportSyntaxError(act, currentKind,stateStackTop);
1427 protected CompilationUnitDeclaration endParse(int act) {
1428 // if (sourceType != null) {
1429 // if (sourceType.isInterface()) {
1430 // consumeInterfaceDeclaration();
1432 // consumeClassDeclaration();
1435 if (compilationUnit != null) {
1436 CompilationUnitDeclaration result = super.endParse(act);