1 /*******************************************************************************
2 * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others.
3 * All rights reserved. This program and the accompanying materials
4 * are made available under the terms of the Common Public License v0.5
5 * which accompanies this distribution, and is available at
6 * http://www.eclipse.org/legal/cpl-v05.html
9 * IBM Corporation - initial API and implementation
10 ******************************************************************************/
11 package net.sourceforge.phpdt.internal.compiler;
14 * A source element parser extracts structural and reference information
15 * from a piece of source.
17 * also see @ISourceElementRequestor
19 * The structural investigation includes:
20 * - the package statement
22 * - top-level types: package member, member types (member types of member types...)
26 * If reference information is requested, then all source constructs are
27 * investigated and type, field & method references are provided as well.
29 * Any (parsing) problem encountered is also provided.
32 import net.sourceforge.phpdt.internal.compiler.env.*;
33 import net.sourceforge.phpdt.internal.compiler.impl.*;
34 import net.sourceforge.phpdt.core.compiler.*;
35 import net.sourceforge.phpdt.internal.compiler.ast.*;
36 import net.sourceforge.phpdt.internal.compiler.lookup.*;
37 import net.sourceforge.phpdt.internal.compiler.parser.*;
38 import net.sourceforge.phpdt.internal.compiler.problem.*;
39 import net.sourceforge.phpdt.internal.compiler.util.*;
41 public class SourceElementParser extends Parser {
43 ISourceElementRequestor requestor;
44 private int fieldCount;
45 private int localIntPtr;
46 private int lastFieldEndPosition;
47 private ISourceType sourceType;
48 private boolean reportReferenceInfo;
49 private char[][] typeNames;
50 private char[][] superTypeNames;
51 private int nestedTypeIndex;
52 private static final char[] JAVA_LANG_OBJECT = "java.lang.Object".toCharArray(); //$NON-NLS-1$
53 private NameReference[] unknownRefs;
54 private int unknownRefsCounter;
55 private LocalDeclarationVisitor localDeclarationVisitor = null;
56 private CompilerOptions options;
59 * An ast visitor that visits local type declarations.
61 public class LocalDeclarationVisitor extends AbstractSyntaxTreeVisitorAdapter {
63 AnonymousLocalTypeDeclaration anonymousTypeDeclaration,
65 notifySourceElementRequestor(anonymousTypeDeclaration, sourceType == null);
66 return false; // don't visit members as this was done during notifySourceElementRequestor(...)
68 public boolean visit(LocalTypeDeclaration typeDeclaration, BlockScope scope) {
69 notifySourceElementRequestor(typeDeclaration, sourceType == null);
70 return false; // don't visit members as this was done during notifySourceElementRequestor(...)
72 public boolean visit(MemberTypeDeclaration typeDeclaration, ClassScope scope) {
73 notifySourceElementRequestor(typeDeclaration, sourceType == null);
74 return false; // don't visit members as this was done during notifySourceElementRequestor(...)
79 public SourceElementParser(
80 final ISourceElementRequestor requestor,
81 IProblemFactory problemFactory,
82 CompilerOptions options) {
83 // we want to notify all syntax error with the acceptProblem API
84 // To do so, we define the record method of the ProblemReporter
85 super(new ProblemReporter(
86 DefaultErrorHandlingPolicies.exitAfterAllProblems(),
89 public void record(IProblem problem, CompilationResult unitResult, ReferenceContext referenceContext) {
90 unitResult.record(problem, referenceContext);
91 requestor.acceptProblem(problem);
96 this.requestor = requestor;
97 typeNames = new char[4][];
98 superTypeNames = new char[4][];
100 this.options = options;
103 /** @deprecated use SourceElementParser(ISourceElementRequestor, IProblemFactory, CompilerOptions) */
104 public SourceElementParser(
105 final ISourceElementRequestor requestor,
106 IProblemFactory problemFactory) {
107 this(requestor, problemFactory, new CompilerOptions());
110 public SourceElementParser(
111 final ISourceElementRequestor requestor,
112 IProblemFactory problemFactory,
113 CompilerOptions options,
114 boolean reportLocalDeclarations) {
115 this(requestor, problemFactory, options);
116 if (reportLocalDeclarations) {
117 this.localDeclarationVisitor = new LocalDeclarationVisitor();
121 public void checkAnnotation() {
122 int firstCommentIndex = scanner.commentPtr;
124 super.checkAnnotation();
126 // modify the modifier source start to point at the first comment
127 if (firstCommentIndex >= 0) {
128 modifiersSourceStart = scanner.commentStarts[0];
132 protected void classInstanceCreation(boolean alwaysQualified) {
134 boolean previousFlag = reportReferenceInfo;
135 reportReferenceInfo = false; // not to see the type reference reported in super call to getTypeReference(...)
136 super.classInstanceCreation(alwaysQualified);
137 reportReferenceInfo = previousFlag;
138 if (reportReferenceInfo){
139 AllocationExpression alloc = (AllocationExpression)expressionStack[expressionPtr];
140 TypeReference typeRef = alloc.type;
141 requestor.acceptConstructorReference(
142 typeRef instanceof SingleTypeReference
143 ? ((SingleTypeReference) typeRef).token
144 : CharOperation.concatWith(alloc.type.getTypeName(), '.'),
145 alloc.arguments == null ? 0 : alloc.arguments.length,
149 protected void consumeConstructorHeaderName() {
150 // ConstructorHeaderName ::= Modifiersopt 'Identifier' '('
152 /* recovering - might be an empty message send */
153 if (currentElement != null){
154 if (lastIgnoredToken == TokenNamenew){ // was an allocation expression
155 lastCheckPoint = scanner.startPosition; // force to restart at this exact position
156 restartRecovery = true;
160 SourceConstructorDeclaration cd = new SourceConstructorDeclaration(this.compilationUnit.compilationResult);
162 //name -- this is not really revelant but we do .....
163 cd.selector = identifierStack[identifierPtr];
164 long selectorSourcePositions = identifierPositionStack[identifierPtr--];
165 identifierLengthPtr--;
168 cd.declarationSourceStart = intStack[intPtr--];
169 cd.modifiers = intStack[intPtr--];
171 //highlight starts at the selector starts
172 cd.sourceStart = (int) (selectorSourcePositions >>> 32);
173 cd.selectorSourceEnd = (int) selectorSourcePositions;
176 cd.sourceEnd = lParenPos;
177 cd.bodyStart = lParenPos+1;
178 listLength = 0; // initialize listLength before reading parameters/throws
181 if (currentElement != null){
182 lastCheckPoint = cd.bodyStart;
183 if ((currentElement instanceof RecoveredType && lastIgnoredToken != TokenNameDOT)
184 || cd.modifiers != 0){
185 currentElement = currentElement.add(cd, 0);
186 lastIgnoredToken = -1;
194 protected void consumeExitVariableWithInitialization() {
195 // ExitVariableWithInitialization ::= $empty
196 // the scanner is located after the comma or the semi-colon.
197 // we want to include the comma or the semi-colon
198 super.consumeExitVariableWithInitialization();
199 if (isLocalDeclaration() || ((currentToken != TokenNameCOMMA) && (currentToken != TokenNameSEMICOLON)))
201 ((SourceFieldDeclaration) astStack[astPtr]).fieldEndPosition = scanner.currentPosition - 1;
203 protected void consumeExitVariableWithoutInitialization() {
204 // ExitVariableWithoutInitialization ::= $empty
205 // do nothing by default
206 if (isLocalDeclaration() || ((currentToken != TokenNameCOMMA) && (currentToken != TokenNameSEMICOLON)))
208 ((SourceFieldDeclaration) astStack[astPtr]).fieldEndPosition = scanner.currentPosition - 1;
214 protected void consumeFieldAccess(boolean isSuperAccess) {
215 // FieldAccess ::= Primary '.' 'Identifier'
216 // FieldAccess ::= 'super' '.' 'Identifier'
217 super.consumeFieldAccess(isSuperAccess);
218 FieldReference fr = (FieldReference) expressionStack[expressionPtr];
219 if (reportReferenceInfo) {
220 requestor.acceptFieldReference(fr.token, fr.sourceStart);
223 protected void consumeMethodHeaderName() {
224 // MethodHeaderName ::= Modifiersopt Type 'Identifier' '('
225 SourceMethodDeclaration md = new SourceMethodDeclaration(this.compilationUnit.compilationResult);
228 md.selector = identifierStack[identifierPtr];
229 long selectorSourcePositions = identifierPositionStack[identifierPtr--];
230 identifierLengthPtr--;
232 md.returnType = getTypeReference(intStack[intPtr--]);
234 md.declarationSourceStart = intStack[intPtr--];
235 md.modifiers = intStack[intPtr--];
237 //highlight starts at selector start
238 md.sourceStart = (int) (selectorSourcePositions >>> 32);
239 md.selectorSourceEnd = (int) selectorSourcePositions;
241 md.sourceEnd = lParenPos;
242 md.bodyStart = lParenPos+1;
243 listLength = 0; // initialize listLength before reading parameters/throws
246 if (currentElement != null){
247 if (currentElement instanceof RecoveredType
248 //|| md.modifiers != 0
249 || (scanner.getLineNumber(md.returnType.sourceStart)
250 == scanner.getLineNumber(md.sourceStart))){
251 lastCheckPoint = md.bodyStart;
252 currentElement = currentElement.add(md, 0);
253 lastIgnoredToken = -1;
255 lastCheckPoint = md.sourceStart;
256 restartRecovery = true;
264 protected void consumeMethodInvocationName() {
265 // MethodInvocation ::= Name '(' ArgumentListopt ')'
267 // when the name is only an identifier...we have a message send to "this" (implicit)
268 super.consumeMethodInvocationName();
269 MessageSend messageSend = (MessageSend) expressionStack[expressionPtr];
270 Expression[] args = messageSend.arguments;
271 if (reportReferenceInfo) {
272 requestor.acceptMethodReference(
273 messageSend.selector,
274 args == null ? 0 : args.length,
275 (int)(messageSend.nameSourcePosition >>> 32));
282 protected void consumeMethodInvocationPrimary() {
283 super.consumeMethodInvocationPrimary();
284 MessageSend messageSend = (MessageSend) expressionStack[expressionPtr];
285 Expression[] args = messageSend.arguments;
286 if (reportReferenceInfo) {
287 requestor.acceptMethodReference(
288 messageSend.selector,
289 args == null ? 0 : args.length,
290 (int)(messageSend.nameSourcePosition >>> 32));
297 protected void consumeMethodInvocationSuper() {
298 // MethodInvocation ::= 'super' '.' 'Identifier' '(' ArgumentListopt ')'
299 super.consumeMethodInvocationSuper();
300 MessageSend messageSend = (MessageSend) expressionStack[expressionPtr];
301 Expression[] args = messageSend.arguments;
302 if (reportReferenceInfo) {
303 requestor.acceptMethodReference(
304 messageSend.selector,
305 args == null ? 0 : args.length,
306 (int)(messageSend.nameSourcePosition >>> 32));
309 protected void consumeSingleTypeImportDeclarationName() {
310 // SingleTypeImportDeclarationName ::= 'import' Name
311 /* push an ImportRef build from the last name
312 stored in the identifier stack. */
314 super.consumeSingleTypeImportDeclarationName();
315 ImportReference impt = (ImportReference)astStack[astPtr];
316 if (reportReferenceInfo) {
317 requestor.acceptTypeReference(impt.tokens, impt.sourceStart, impt.sourceEnd);
320 protected void consumeTypeImportOnDemandDeclarationName() {
321 // TypeImportOnDemandDeclarationName ::= 'import' Name '.' '*'
322 /* push an ImportRef build from the last name
323 stored in the identifier stack. */
325 super.consumeTypeImportOnDemandDeclarationName();
326 ImportReference impt = (ImportReference)astStack[astPtr];
327 if (reportReferenceInfo) {
328 requestor.acceptUnknownReference(impt.tokens, impt.sourceStart, impt.sourceEnd);
331 protected FieldDeclaration createFieldDeclaration(Expression initialization, char[] name, int sourceStart, int sourceEnd) {
332 return new SourceFieldDeclaration(null, name, sourceStart, sourceEnd);
334 protected CompilationUnitDeclaration endParse(int act) {
335 if (sourceType != null) {
336 if (sourceType.isInterface()) {
337 consumeInterfaceDeclaration();
339 consumeClassDeclaration();
342 if (compilationUnit != null) {
343 CompilationUnitDeclaration result = super.endParse(act);
350 * Flush annotations defined prior to a given positions.
352 * Note: annotations are stacked in syntactical order
354 * Either answer given <position>, or the end position of a comment line
355 * immediately following the <position> (same line)
359 * } // end of method foo
362 public int flushAnnotationsDefinedPriorTo(int position) {
364 return lastFieldEndPosition = super.flushAnnotationsDefinedPriorTo(position);
366 public TypeReference getTypeReference(int dim) {
367 /* build a Reference on a variable that may be qualified or not
368 * This variable is a type reference and dim will be its dimensions
371 if ((length = identifierLengthStack[identifierLengthPtr--]) == 1) {
372 // single variable reference
374 SingleTypeReference ref =
375 new SingleTypeReference(
376 identifierStack[identifierPtr],
377 identifierPositionStack[identifierPtr--]);
378 if (reportReferenceInfo) {
379 requestor.acceptTypeReference(ref.token, ref.sourceStart);
383 ArrayTypeReference ref =
384 new ArrayTypeReference(
385 identifierStack[identifierPtr],
387 identifierPositionStack[identifierPtr--]);
388 ref.sourceEnd = endPosition;
389 if (reportReferenceInfo) {
390 requestor.acceptTypeReference(ref.token, ref.sourceStart);
395 if (length < 0) { //flag for precompiled type reference on base types
396 TypeReference ref = TypeReference.baseTypeReference(-length, dim);
397 ref.sourceStart = intStack[intPtr--];
399 ref.sourceEnd = intStack[intPtr--];
401 intPtr--; // no need to use this position as it is an array
402 ref.sourceEnd = endPosition;
404 if (reportReferenceInfo){
405 requestor.acceptTypeReference(ref.getTypeName(), ref.sourceStart, ref.sourceEnd);
408 } else { //Qualified variable reference
409 char[][] tokens = new char[length][];
410 identifierPtr -= length;
411 long[] positions = new long[length];
412 System.arraycopy(identifierStack, identifierPtr + 1, tokens, 0, length);
414 identifierPositionStack,
420 QualifiedTypeReference ref = new QualifiedTypeReference(tokens, positions);
421 if (reportReferenceInfo) {
422 requestor.acceptTypeReference(ref.tokens, ref.sourceStart, ref.sourceEnd);
426 ArrayQualifiedTypeReference ref =
427 new ArrayQualifiedTypeReference(tokens, dim, positions);
428 ref.sourceEnd = endPosition;
429 if (reportReferenceInfo) {
430 requestor.acceptTypeReference(ref.tokens, ref.sourceStart, ref.sourceEnd);
437 public NameReference getUnspecifiedReference() {
438 /* build a (unspecified) NameReference which may be qualified*/
441 if ((length = identifierLengthStack[identifierLengthPtr--]) == 1) {
442 // single variable reference
443 SingleNameReference ref =
444 new SingleNameReference(
445 identifierStack[identifierPtr],
446 identifierPositionStack[identifierPtr--]);
447 if (reportReferenceInfo) {
448 this.addUnknownRef(ref);
452 //Qualified variable reference
453 char[][] tokens = new char[length][];
454 identifierPtr -= length;
455 System.arraycopy(identifierStack, identifierPtr + 1, tokens, 0, length);
456 QualifiedNameReference ref =
457 new QualifiedNameReference(
459 (int) (identifierPositionStack[identifierPtr + 1] >> 32), // sourceStart
460 (int) identifierPositionStack[identifierPtr + length]); // sourceEnd
461 if (reportReferenceInfo) {
462 this.addUnknownRef(ref);
467 public NameReference getUnspecifiedReferenceOptimized() {
468 /* build a (unspecified) NameReference which may be qualified
469 The optimization occurs for qualified reference while we are
470 certain in this case the last item of the qualified name is
471 a field access. This optimization is IMPORTANT while it results
472 that when a NameReference is build, the type checker should always
473 look for that it is not a type reference */
476 if ((length = identifierLengthStack[identifierLengthPtr--]) == 1) {
477 // single variable reference
478 SingleNameReference ref =
479 new SingleNameReference(
480 identifierStack[identifierPtr],
481 identifierPositionStack[identifierPtr--]);
482 ref.bits &= ~AstNode.RestrictiveFlagMASK;
483 ref.bits |= LOCAL | FIELD;
484 if (reportReferenceInfo) {
485 this.addUnknownRef(ref);
490 //Qualified-variable-reference
491 //In fact it is variable-reference DOT field-ref , but it would result in a type
492 //conflict tha can be only reduce by making a superclass (or inetrface ) between
493 //nameReference and FiledReference or putting FieldReference under NameReference
494 //or else..........This optimisation is not really relevant so just leave as it is
496 char[][] tokens = new char[length][];
497 identifierPtr -= length;
498 System.arraycopy(identifierStack, identifierPtr + 1, tokens, 0, length);
499 QualifiedNameReference ref =
500 new QualifiedNameReference(
502 (int) (identifierPositionStack[identifierPtr + 1] >> 32),
504 (int) identifierPositionStack[identifierPtr + length]); // sourceEnd
505 ref.bits &= ~AstNode.RestrictiveFlagMASK;
506 ref.bits |= LOCAL | FIELD;
507 if (reportReferenceInfo) {
508 this.addUnknownRef(ref);
516 private boolean isLocalDeclaration() {
517 int nestedDepth = nestedType;
518 while (nestedDepth >= 0) {
519 if (nestedMethod[nestedDepth] != 0) {
527 * Update the bodyStart of the corresponding parse node
529 public void notifySourceElementRequestor(CompilationUnitDeclaration parsedUnit) {
530 if (parsedUnit == null) {
531 // when we parse a single type member declaration the compilation unit is null, but we still
532 // want to be able to notify the requestor on the created ast node
533 if (astStack[0] instanceof AbstractMethodDeclaration) {
534 notifySourceElementRequestor((AbstractMethodDeclaration) astStack[0]);
541 scanner.initialPosition <= parsedUnit.sourceStart
542 && scanner.eofPosition >= parsedUnit.sourceEnd;
544 if (reportReferenceInfo) {
545 notifyAllUnknownReferences();
547 // collect the top level ast nodes
549 AstNode[] nodes = null;
550 if (sourceType == null){
552 requestor.enterCompilationUnit();
554 ImportReference currentPackage = parsedUnit.currentPackage;
555 ImportReference[] imports = parsedUnit.imports;
556 TypeDeclaration[] types = parsedUnit.types;
558 (currentPackage == null ? 0 : 1)
559 + (imports == null ? 0 : imports.length)
560 + (types == null ? 0 : types.length);
561 nodes = new AstNode[length];
563 if (currentPackage != null) {
564 nodes[index++] = currentPackage;
566 if (imports != null) {
567 for (int i = 0, max = imports.length; i < max; i++) {
568 nodes[index++] = imports[i];
572 for (int i = 0, max = types.length; i < max; i++) {
573 nodes[index++] = types[i];
577 TypeDeclaration[] types = parsedUnit.types;
579 length = types.length;
580 nodes = new AstNode[length];
581 for (int i = 0, max = types.length; i < max; i++) {
587 // notify the nodes in the syntactical order
588 if (nodes != null && length > 0) {
589 quickSort(nodes, 0, length-1);
590 for (int i=0;i<length;i++) {
591 AstNode node = nodes[i];
592 if (node instanceof ImportReference) {
593 ImportReference importRef = (ImportReference)node;
594 if (node == parsedUnit.currentPackage) {
595 notifySourceElementRequestor(importRef, true);
597 notifySourceElementRequestor(importRef, false);
599 } else { // instanceof TypeDeclaration
600 notifySourceElementRequestor((TypeDeclaration)node, sourceType == null);
605 if (sourceType == null){
607 requestor.exitCompilationUnit(parsedUnit.sourceEnd);
612 private void notifyAllUnknownReferences() {
613 for (int i = 0, max = this.unknownRefsCounter; i < max; i++) {
614 NameReference nameRef = this.unknownRefs[i];
615 if ((nameRef.bits & BindingIds.VARIABLE) != 0) {
616 if ((nameRef.bits & BindingIds.TYPE) == 0) {
617 // variable but not type
618 if (nameRef instanceof SingleNameReference) {
619 // local var or field
620 requestor.acceptUnknownReference(((SingleNameReference) nameRef).token, nameRef.sourceStart);
622 // QualifiedNameReference
623 // The last token is a field reference and the previous tokens are a type/variable references
624 char[][] tokens = ((QualifiedNameReference) nameRef).tokens;
625 int tokensLength = tokens.length;
626 requestor.acceptFieldReference(tokens[tokensLength - 1], nameRef.sourceEnd - tokens[tokensLength - 1].length + 1);
627 char[][] typeRef = new char[tokensLength - 1][];
628 System.arraycopy(tokens, 0, typeRef, 0, tokensLength - 1);
629 requestor.acceptUnknownReference(typeRef, nameRef.sourceStart, nameRef.sourceEnd - tokens[tokensLength - 1].length);
633 if (nameRef instanceof SingleNameReference) {
634 requestor.acceptUnknownReference(((SingleNameReference) nameRef).token, nameRef.sourceStart);
636 //QualifiedNameReference
637 requestor.acceptUnknownReference(((QualifiedNameReference) nameRef).tokens, nameRef.sourceStart, nameRef.sourceEnd);
640 } else if ((nameRef.bits & BindingIds.TYPE) != 0) {
641 if (nameRef instanceof SingleNameReference) {
642 requestor.acceptTypeReference(((SingleNameReference) nameRef).token, nameRef.sourceStart);
644 // it is a QualifiedNameReference
645 requestor.acceptTypeReference(((QualifiedNameReference) nameRef).tokens, nameRef.sourceStart, nameRef.sourceEnd);
651 * Update the bodyStart of the corresponding parse node
653 public void notifySourceElementRequestor(AbstractMethodDeclaration methodDeclaration) {
657 scanner.initialPosition <= methodDeclaration.declarationSourceStart
658 && scanner.eofPosition >= methodDeclaration.declarationSourceEnd;
660 if (methodDeclaration.isClinit()) {
661 this.visitIfNeeded(methodDeclaration);
665 if (methodDeclaration.isDefaultConstructor()) {
666 if (reportReferenceInfo) {
667 ConstructorDeclaration constructorDeclaration = (ConstructorDeclaration) methodDeclaration;
668 ExplicitConstructorCall constructorCall = constructorDeclaration.constructorCall;
669 if (constructorCall != null) {
670 switch(constructorCall.accessMode) {
671 case ExplicitConstructorCall.This :
672 requestor.acceptConstructorReference(
673 typeNames[nestedTypeIndex-1],
674 constructorCall.arguments == null ? 0 : constructorCall.arguments.length,
675 constructorCall.sourceStart);
677 case ExplicitConstructorCall.Super :
678 case ExplicitConstructorCall.ImplicitSuper :
679 requestor.acceptConstructorReference(
680 superTypeNames[nestedTypeIndex-1],
681 constructorCall.arguments == null ? 0 : constructorCall.arguments.length,
682 constructorCall.sourceStart);
689 char[][] argumentTypes = null;
690 char[][] argumentNames = null;
691 Argument[] arguments = methodDeclaration.arguments;
692 if (arguments != null) {
693 int argumentLength = arguments.length;
694 argumentTypes = new char[argumentLength][];
695 argumentNames = new char[argumentLength][];
696 for (int i = 0; i < argumentLength; i++) {
697 argumentTypes[i] = returnTypeName(arguments[i].type);
698 argumentNames[i] = arguments[i].name;
701 char[][] thrownExceptionTypes = null;
702 TypeReference[] thrownExceptions = methodDeclaration.thrownExceptions;
703 if (thrownExceptions != null) {
704 int thrownExceptionLength = thrownExceptions.length;
705 thrownExceptionTypes = new char[thrownExceptionLength][];
706 for (int i = 0; i < thrownExceptionLength; i++) {
707 thrownExceptionTypes[i] =
708 CharOperation.concatWith(thrownExceptions[i].getTypeName(), '.');
711 // by default no selector end position
712 int selectorSourceEnd = -1;
713 if (methodDeclaration.isConstructor()) {
714 if (methodDeclaration instanceof SourceConstructorDeclaration) {
716 ((SourceConstructorDeclaration) methodDeclaration).selectorSourceEnd;
719 requestor.enterConstructor(
720 methodDeclaration.declarationSourceStart,
721 methodDeclaration.modifiers,
722 methodDeclaration.selector,
723 methodDeclaration.sourceStart,
727 thrownExceptionTypes);
729 if (reportReferenceInfo) {
730 ConstructorDeclaration constructorDeclaration = (ConstructorDeclaration) methodDeclaration;
731 ExplicitConstructorCall constructorCall = constructorDeclaration.constructorCall;
732 if (constructorCall != null) {
733 switch(constructorCall.accessMode) {
734 case ExplicitConstructorCall.This :
735 requestor.acceptConstructorReference(
736 typeNames[nestedTypeIndex-1],
737 constructorCall.arguments == null ? 0 : constructorCall.arguments.length,
738 constructorCall.sourceStart);
740 case ExplicitConstructorCall.Super :
741 case ExplicitConstructorCall.ImplicitSuper :
742 requestor.acceptConstructorReference(
743 superTypeNames[nestedTypeIndex-1],
744 constructorCall.arguments == null ? 0 : constructorCall.arguments.length,
745 constructorCall.sourceStart);
750 this.visitIfNeeded(methodDeclaration);
752 requestor.exitConstructor(methodDeclaration.declarationSourceEnd);
756 if (methodDeclaration instanceof SourceMethodDeclaration) {
758 ((SourceMethodDeclaration) methodDeclaration).selectorSourceEnd;
761 requestor.enterMethod(
762 methodDeclaration.declarationSourceStart,
763 methodDeclaration.modifiers & AccJustFlag,
764 returnTypeName(((MethodDeclaration) methodDeclaration).returnType),
765 methodDeclaration.selector,
766 methodDeclaration.sourceStart,
770 thrownExceptionTypes);
772 this.visitIfNeeded(methodDeclaration);
775 requestor.exitMethod(methodDeclaration.declarationSourceEnd);
779 * Update the bodyStart of the corresponding parse node
781 public void notifySourceElementRequestor(FieldDeclaration fieldDeclaration) {
785 scanner.initialPosition <= fieldDeclaration.declarationSourceStart
786 && scanner.eofPosition >= fieldDeclaration.declarationSourceEnd;
788 if (fieldDeclaration.isField()) {
789 int fieldEndPosition = fieldDeclaration.declarationSourceEnd;
790 if (fieldDeclaration instanceof SourceFieldDeclaration) {
791 fieldEndPosition = ((SourceFieldDeclaration) fieldDeclaration).fieldEndPosition;
792 if (fieldEndPosition == 0) {
793 // use the declaration source end by default
794 fieldEndPosition = fieldDeclaration.declarationSourceEnd;
798 requestor.enterField(
799 fieldDeclaration.declarationSourceStart,
800 fieldDeclaration.modifiers & AccJustFlag,
801 returnTypeName(fieldDeclaration.type),
802 fieldDeclaration.name,
803 fieldDeclaration.sourceStart,
804 fieldDeclaration.sourceEnd);
806 this.visitIfNeeded(fieldDeclaration);
808 requestor.exitField(fieldEndPosition);
813 requestor.enterInitializer(
814 fieldDeclaration.declarationSourceStart,
815 fieldDeclaration.modifiers);
817 this.visitIfNeeded((Initializer)fieldDeclaration);
819 requestor.exitInitializer(fieldDeclaration.declarationSourceEnd);
823 public void notifySourceElementRequestor(
824 ImportReference importReference,
827 requestor.acceptPackage(
828 importReference.declarationSourceStart,
829 importReference.declarationSourceEnd,
830 CharOperation.concatWith(importReference.getImportName(), '.'));
832 requestor.acceptImport(
833 importReference.declarationSourceStart,
834 importReference.declarationSourceEnd,
835 CharOperation.concatWith(importReference.getImportName(), '.'),
836 importReference.onDemand);
839 public void notifySourceElementRequestor(TypeDeclaration typeDeclaration, boolean notifyTypePresence) {
843 scanner.initialPosition <= typeDeclaration.declarationSourceStart
844 && scanner.eofPosition >= typeDeclaration.declarationSourceEnd;
846 FieldDeclaration[] fields = typeDeclaration.fields;
847 AbstractMethodDeclaration[] methods = typeDeclaration.methods;
848 MemberTypeDeclaration[] memberTypes = typeDeclaration.memberTypes;
849 int fieldCount = fields == null ? 0 : fields.length;
850 int methodCount = methods == null ? 0 : methods.length;
851 int memberTypeCount = memberTypes == null ? 0 : memberTypes.length;
854 int memberTypeIndex = 0;
855 boolean isInterface = typeDeclaration.isInterface();
857 if (notifyTypePresence){
858 char[][] interfaceNames = null;
859 int superInterfacesLength = 0;
860 TypeReference[] superInterfaces = typeDeclaration.superInterfaces;
861 if (superInterfaces != null) {
862 superInterfacesLength = superInterfaces.length;
863 interfaceNames = new char[superInterfacesLength][];
865 if (typeDeclaration instanceof AnonymousLocalTypeDeclaration) {
867 QualifiedAllocationExpression alloc = ((AnonymousLocalTypeDeclaration)typeDeclaration).allocation;
868 if (alloc != null && alloc.type != null) {
869 superInterfaces = new TypeReference[] { ((AnonymousLocalTypeDeclaration)typeDeclaration).allocation.type};
870 superInterfacesLength = 1;
871 interfaceNames = new char[1][];
875 if (superInterfaces != null) {
876 for (int i = 0; i < superInterfacesLength; i++) {
878 CharOperation.concatWith(superInterfaces[i].getTypeName(), '.');
883 requestor.enterInterface(
884 typeDeclaration.declarationSourceStart,
885 typeDeclaration.modifiers & AccJustFlag,
886 typeDeclaration.name,
887 typeDeclaration.sourceStart,
888 typeDeclaration.sourceEnd,
891 if (nestedTypeIndex == typeNames.length) {
893 System.arraycopy(typeNames, 0, (typeNames = new char[nestedTypeIndex * 2][]), 0, nestedTypeIndex);
894 System.arraycopy(superTypeNames, 0, (superTypeNames = new char[nestedTypeIndex * 2][]), 0, nestedTypeIndex);
896 typeNames[nestedTypeIndex] = typeDeclaration.name;
897 superTypeNames[nestedTypeIndex++] = JAVA_LANG_OBJECT;
899 TypeReference superclass = typeDeclaration.superclass;
900 if (superclass == null) {
902 requestor.enterClass(
903 typeDeclaration.declarationSourceStart,
904 typeDeclaration.modifiers,
905 typeDeclaration.name,
906 typeDeclaration.sourceStart,
907 typeDeclaration.sourceEnd,
913 requestor.enterClass(
914 typeDeclaration.declarationSourceStart,
915 typeDeclaration.modifiers,
916 typeDeclaration.name,
917 typeDeclaration.sourceStart,
918 typeDeclaration.sourceEnd,
919 CharOperation.concatWith(superclass.getTypeName(), '.'),
923 if (nestedTypeIndex == typeNames.length) {
925 System.arraycopy(typeNames, 0, (typeNames = new char[nestedTypeIndex * 2][]), 0, nestedTypeIndex);
926 System.arraycopy(superTypeNames, 0, (superTypeNames = new char[nestedTypeIndex * 2][]), 0, nestedTypeIndex);
928 typeNames[nestedTypeIndex] = typeDeclaration.name;
929 superTypeNames[nestedTypeIndex++] = superclass == null ? JAVA_LANG_OBJECT : CharOperation.concatWith(superclass.getTypeName(), '.');
932 while ((fieldIndex < fieldCount)
933 || (memberTypeIndex < memberTypeCount)
934 || (methodIndex < methodCount)) {
935 FieldDeclaration nextFieldDeclaration = null;
936 AbstractMethodDeclaration nextMethodDeclaration = null;
937 TypeDeclaration nextMemberDeclaration = null;
939 int position = Integer.MAX_VALUE;
940 int nextDeclarationType = -1;
941 if (fieldIndex < fieldCount) {
942 nextFieldDeclaration = fields[fieldIndex];
943 if (nextFieldDeclaration.declarationSourceStart < position) {
944 position = nextFieldDeclaration.declarationSourceStart;
945 nextDeclarationType = 0; // FIELD
948 if (methodIndex < methodCount) {
949 nextMethodDeclaration = methods[methodIndex];
950 if (nextMethodDeclaration.declarationSourceStart < position) {
951 position = nextMethodDeclaration.declarationSourceStart;
952 nextDeclarationType = 1; // METHOD
955 if (memberTypeIndex < memberTypeCount) {
956 nextMemberDeclaration = memberTypes[memberTypeIndex];
957 if (nextMemberDeclaration.declarationSourceStart < position) {
958 position = nextMemberDeclaration.declarationSourceStart;
959 nextDeclarationType = 2; // MEMBER
962 switch (nextDeclarationType) {
965 notifySourceElementRequestor(nextFieldDeclaration);
969 notifySourceElementRequestor(nextMethodDeclaration);
973 notifySourceElementRequestor(nextMemberDeclaration, true);
976 if (notifyTypePresence){
979 requestor.exitInterface(typeDeclaration.declarationSourceEnd);
981 requestor.exitClass(typeDeclaration.declarationSourceEnd);
987 public void parseCompilationUnit(
988 ICompilationUnit unit,
991 boolean needReferenceInfo) {
993 reportReferenceInfo = needReferenceInfo;
995 if (needReferenceInfo) {
996 unknownRefs = new NameReference[10];
997 unknownRefsCounter = 0;
1001 CompilationResult compilationUnitResult = new CompilationResult(unit, 0, 0, this.options.maxProblemsPerUnit);
1002 CompilationUnitDeclaration parsedUnit = parse(unit, compilationUnitResult, start, end);
1003 if (needReferenceInfo){
1005 this.getMethodBodies(parsedUnit);
1007 this.scanner.resetTo(start, end);
1008 notifySourceElementRequestor(parsedUnit);
1009 } catch (AbortCompilation e) {
1011 if (scanner.recordLineSeparator) {
1012 requestor.acceptLineSeparatorPositions(scanner.getLineEnds());
1017 public void parseCompilationUnit(
1018 ICompilationUnit unit,
1019 boolean needReferenceInfo) {
1021 if (needReferenceInfo) {
1022 unknownRefs = new NameReference[10];
1023 unknownRefsCounter = 0;
1027 /* diet = !needReferenceInfo;
1028 reportReferenceInfo = needReferenceInfo;
1029 CompilationResult compilationUnitResult = new CompilationResult(unit, 0, 0);
1030 parse(unit, compilationUnitResult);
1032 reportReferenceInfo = needReferenceInfo;
1033 CompilationResult compilationUnitResult = new CompilationResult(unit, 0, 0, this.options.maxProblemsPerUnit);
1034 CompilationUnitDeclaration parsedUnit = parse(unit, compilationUnitResult);
1035 int initialStart = this.scanner.initialPosition;
1036 int initialEnd = this.scanner.eofPosition;
1037 if (needReferenceInfo){
1039 this.getMethodBodies(parsedUnit);
1041 this.scanner.resetTo(initialStart, initialEnd);
1042 notifySourceElementRequestor(parsedUnit);
1043 } catch (AbortCompilation e) {
1045 if (scanner.recordLineSeparator) {
1046 requestor.acceptLineSeparatorPositions(scanner.getLineEnds());
1051 public void parseTypeMemberDeclarations(
1052 ISourceType sourceType,
1053 ICompilationUnit sourceUnit,
1056 boolean needReferenceInfo) {
1058 if (needReferenceInfo) {
1059 unknownRefs = new NameReference[10];
1060 unknownRefsCounter = 0;
1064 diet = !needReferenceInfo;
1065 reportReferenceInfo = needReferenceInfo;
1066 CompilationResult compilationUnitResult =
1067 new CompilationResult(sourceUnit, 0, 0, this.options.maxProblemsPerUnit);
1068 CompilationUnitDeclaration unit =
1069 SourceTypeConverter.buildCompilationUnit(
1070 new ISourceType[]{sourceType},
1074 compilationUnitResult);
1075 if ((unit == null) || (unit.types == null) || (unit.types.length != 1))
1077 this.sourceType = sourceType;
1079 /* automaton initialization */
1081 goForClassBodyDeclarations();
1082 /* scanner initialization */
1083 scanner.setSource(sourceUnit.getContents());
1084 scanner.resetTo(start, end);
1086 referenceContext = compilationUnit = unit;
1087 /* initialize the astStacl */
1088 // the compilationUnitDeclaration should contain exactly one type
1089 pushOnAstStack(unit.types[0]);
1092 notifySourceElementRequestor(unit);
1094 unit = compilationUnit;
1095 compilationUnit = null; // reset parser
1097 } catch (AbortCompilation e) {
1099 if (scanner.recordLineSeparator) {
1100 requestor.acceptLineSeparatorPositions(scanner.getLineEnds());
1106 public void parseTypeMemberDeclarations(
1116 /* automaton initialization */
1118 goForClassBodyDeclarations();
1119 /* scanner initialization */
1120 scanner.setSource(contents);
1121 scanner.recordLineSeparator = false;
1122 scanner.resetTo(start, end);
1125 referenceContext = null;
1127 /* initialize the astStacl */
1128 // the compilationUnitDeclaration should contain exactly one type
1131 notifySourceElementRequestor((CompilationUnitDeclaration)null);
1132 } catch (AbortCompilation e) {
1138 * Sort the given ast nodes by their positions.
1140 private static void quickSort(AstNode[] sortedCollection, int left, int right) {
1141 int original_left = left;
1142 int original_right = right;
1143 AstNode mid = sortedCollection[ (left + right) / 2];
1145 while (sortedCollection[left].sourceStart < mid.sourceStart) {
1148 while (mid.sourceStart < sortedCollection[right].sourceStart) {
1151 if (left <= right) {
1152 AstNode tmp = sortedCollection[left];
1153 sortedCollection[left] = sortedCollection[right];
1154 sortedCollection[right] = tmp;
1158 } while (left <= right);
1159 if (original_left < right) {
1160 quickSort(sortedCollection, original_left, right);
1162 if (left < original_right) {
1163 quickSort(sortedCollection, left, original_right);
1167 * Answer a char array representation of the type name formatted like:
1168 * - type name + dimensions
1170 * "A[][]".toCharArray()
1171 * "java.lang.String".toCharArray()
1173 private char[] returnTypeName(TypeReference type) {
1176 int dimension = type.dimensions();
1177 if (dimension != 0) {
1178 char[] dimensionsArray = new char[dimension * 2];
1179 for (int i = 0; i < dimension; i++) {
1180 dimensionsArray[i * 2] = '[';
1181 dimensionsArray[(i * 2) + 1] = ']';
1183 return CharOperation.concat(
1184 CharOperation.concatWith(type.getTypeName(), '.'),
1187 return CharOperation.concatWith(type.getTypeName(), '.');
1190 public void addUnknownRef(NameReference nameRef) {
1191 if (this.unknownRefs.length == this.unknownRefsCounter) {
1196 (this.unknownRefs = new NameReference[this.unknownRefsCounter * 2]),
1198 this.unknownRefsCounter);
1200 this.unknownRefs[this.unknownRefsCounter++] = nameRef;
1202 private TypeReference typeReference(
1204 int localIdentifierPtr,
1205 int localIdentifierLengthPtr) {
1206 /* build a Reference on a variable that may be qualified or not
1207 * This variable is a type reference and dim will be its dimensions.
1208 * We don't have any side effect on the stacks' pointers.
1213 if ((length = identifierLengthStack[localIdentifierLengthPtr]) == 1) {
1214 // single variable reference
1217 new SingleTypeReference(
1218 identifierStack[localIdentifierPtr],
1219 identifierPositionStack[localIdentifierPtr--]);
1222 new ArrayTypeReference(
1223 identifierStack[localIdentifierPtr],
1225 identifierPositionStack[localIdentifierPtr--]);
1226 ref.sourceEnd = endPosition;
1229 if (length < 0) { //flag for precompiled type reference on base types
1230 ref = TypeReference.baseTypeReference(-length, dim);
1231 ref.sourceStart = intStack[localIntPtr--];
1233 ref.sourceEnd = intStack[localIntPtr--];
1236 ref.sourceEnd = endPosition;
1238 } else { //Qualified variable reference
1239 char[][] tokens = new char[length][];
1240 localIdentifierPtr -= length;
1241 long[] positions = new long[length];
1242 System.arraycopy(identifierStack, localIdentifierPtr + 1, tokens, 0, length);
1244 identifierPositionStack,
1245 localIdentifierPtr + 1,
1250 ref = new QualifiedTypeReference(tokens, positions);
1252 ref = new ArrayQualifiedTypeReference(tokens, dim, positions);
1253 ref.sourceEnd = endPosition;
1260 private void visitIfNeeded(AbstractMethodDeclaration method) {
1261 if (this.localDeclarationVisitor != null
1262 && (method.bits & AstNode.HasLocalTypeMASK) != 0) {
1263 if (method.statements != null) {
1264 int statementsLength = method.statements.length;
1265 for (int i = 0; i < statementsLength; i++)
1266 method.statements[i].traverse(this.localDeclarationVisitor, method.scope);
1271 private void visitIfNeeded(FieldDeclaration field) {
1272 if (this.localDeclarationVisitor != null
1273 && (field.bits & AstNode.HasLocalTypeMASK) != 0) {
1274 if (field.initialization != null) {
1275 field.initialization.traverse(this.localDeclarationVisitor, null);
1280 private void visitIfNeeded(Initializer initializer) {
1281 if (this.localDeclarationVisitor != null
1282 && (initializer.bits & AstNode.HasLocalTypeMASK) != 0) {
1283 if (initializer.block != null) {
1284 initializer.block.traverse(this.localDeclarationVisitor, null);
1289 protected void reportSyntaxError(int act, int currentKind, int stateStackTop) {
1290 if (compilationUnit == null) return;
1291 super.reportSyntaxError(act, currentKind,stateStackTop);