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.AbstractMethodDeclaration;
27 import net.sourceforge.phpeclipse.internal.compiler.ast.AnonymousLocalTypeDeclaration;
28 import net.sourceforge.phpeclipse.internal.compiler.ast.Argument;
29 import net.sourceforge.phpeclipse.internal.compiler.ast.ASTNode;
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.LocalTypeDeclaration;
36 import net.sourceforge.phpeclipse.internal.compiler.ast.MemberTypeDeclaration;
37 import net.sourceforge.phpeclipse.internal.compiler.ast.MethodDeclaration;
38 import net.sourceforge.phpeclipse.internal.compiler.ast.NameReference;
39 import net.sourceforge.phpeclipse.internal.compiler.ast.QualifiedAllocationExpression;
40 import net.sourceforge.phpeclipse.internal.compiler.ast.TypeDeclaration;
41 import net.sourceforge.phpeclipse.internal.compiler.ast.TypeReference;
44 * A source element parser extracts structural and reference information
45 * from a piece of source.
47 * also see @ISourceElementRequestor
49 * The structural investigation includes:
50 * - the package statement
52 * - top-level types: package member, member types (member types of member types...)
56 * If reference information is requested, then all source constructs are
57 * investigated and type, field & method references are provided as well.
59 * Any (parsing) problem encountered is also provided.
62 public class SourceElementParser extends CommentRecorderParser {//extends
65 ISourceElementRequestor requestor;
68 int lastFieldEndPosition;
69 ISourceType sourceType;
70 boolean reportReferenceInfo;
72 char[][] superTypeNames;
74 static final char[] JAVA_LANG_OBJECT = "java.lang.Object".toCharArray(); //$NON-NLS-1$
75 NameReference[] unknownRefs;
76 int unknownRefsCounter;
77 LocalDeclarationVisitor localDeclarationVisitor = null;
78 // CompilerOptions options;
81 * An ast visitor that visits local type declarations.
83 public class LocalDeclarationVisitor extends AbstractSyntaxTreeVisitorAdapter {
84 // public boolean visit(
85 // AnonymousLocalTypeDeclaration anonymousTypeDeclaration,
86 // BlockScope scope) {
87 // notifySourceElementRequestor(anonymousTypeDeclaration, sourceType ==
89 // return false; // don't visit members as this was done during
90 // notifySourceElementRequestor(...)
92 public boolean visit(LocalTypeDeclaration typeDeclaration, BlockScope scope) {
93 notifySourceElementRequestor(typeDeclaration, sourceType == null);
94 return false; // don't visit members as this was done during
95 // notifySourceElementRequestor(...)
97 public boolean visit(MemberTypeDeclaration typeDeclaration, ClassScope scope) {
98 notifySourceElementRequestor(typeDeclaration, sourceType == null);
99 return false; // don't visit members as this was done during
100 // notifySourceElementRequestor(...)
105 public SourceElementParser(final ISourceElementRequestor requestor, IProblemFactory problemFactory, CompilerOptions options) {
106 // we want to notify all syntax error with the acceptProblem API
107 // To do so, we define the record method of the ProblemReporter
108 super(new ProblemReporter(DefaultErrorHandlingPolicies.exitAfterAllProblems(), options, problemFactory) {
109 public void record(IProblem problem, CompilationResult unitResult, ReferenceContext referenceContext) {
110 unitResult.record(problem, referenceContext);
111 if (requestor!=null) {
112 requestor.acceptProblem(problem);
117 // options.sourceLevel >= CompilerOptions.JDK1_4);
118 this.requestor = requestor;
119 typeNames = new char[4][];
120 superTypeNames = new char[4][];
122 this.options = options;
126 * @deprecated use SourceElementParser(ISourceElementRequestor,
127 * IProblemFactory, CompilerOptions)
129 //public SourceElementParser(
130 // final ISourceElementRequestor requestor,
131 // IProblemFactory problemFactory) {
132 // this(requestor, problemFactory, new CompilerOptions());
134 //public SourceElementParser(
135 // final ISourceElementRequestor requestor,
136 // IProblemFactory problemFactory,
137 // CompilerOptions options,
138 // boolean reportLocalDeclarations) {
139 // this(requestor, problemFactory, options);
140 // if (reportLocalDeclarations) {
141 // this.localDeclarationVisitor = new LocalDeclarationVisitor();
144 //public void checkAnnotation() {
145 // int firstCommentIndex = scanner.commentPtr;
147 // super.checkAnnotation();
149 // // modify the modifier source start to point at the first comment
150 // if (firstCommentIndex >= 0) {
151 // modifiersSourceStart = scanner.commentStarts[0];
154 //protected void classInstanceCreation(boolean alwaysQualified) {
156 // boolean previousFlag = reportReferenceInfo;
157 // reportReferenceInfo = false; // not to see the type reference reported in
158 // super call to getTypeReference(...)
159 // super.classInstanceCreation(alwaysQualified);
160 // reportReferenceInfo = previousFlag;
161 // if (reportReferenceInfo){
162 // AllocationExpression alloc =
163 // (AllocationExpression)expressionStack[expressionPtr];
164 // TypeReference typeRef = alloc.type;
165 // requestor.acceptConstructorReference(
166 // typeRef instanceof SingleTypeReference
167 // ? ((SingleTypeReference) typeRef).token
168 // : CharOperation.concatWith(alloc.type.getTypeName(), '.'),
169 // alloc.arguments == null ? 0 : alloc.arguments.length,
170 // alloc.sourceStart);
173 //protected void consumeConstructorHeaderName() {
174 // // ConstructorHeaderName ::= Modifiersopt 'Identifier' '('
176 // /* recovering - might be an empty message send */
177 // if (currentElement != null){
178 // if (lastIgnoredToken == TokenNamenew){ // was an allocation expression
179 // lastCheckPoint = scanner.startPosition; // force to restart at this exact
181 // restartRecovery = true;
185 // SourceConstructorDeclaration cd = new
186 // SourceConstructorDeclaration(this.compilationUnit.compilationResult);
188 // //name -- this is not really revelant but we do .....
189 // cd.selector = identifierStack[identifierPtr];
190 // long selectorSourcePositions = identifierPositionStack[identifierPtr--];
191 // identifierLengthPtr--;
194 // cd.declarationSourceStart = intStack[intPtr--];
195 // cd.modifiers = intStack[intPtr--];
197 // //highlight starts at the selector starts
198 // cd.sourceStart = (int) (selectorSourcePositions >>> 32);
199 // cd.selectorSourceEnd = (int) selectorSourcePositions;
200 // pushOnAstStack(cd);
202 // cd.sourceEnd = lParenPos;
203 // cd.bodyStart = lParenPos+1;
204 // listLength = 0; // initialize listLength before reading parameters/throws
207 // if (currentElement != null){
208 // lastCheckPoint = cd.bodyStart;
209 // if ((currentElement instanceof RecoveredType && lastIgnoredToken !=
211 // || cd.modifiers != 0){
212 // currentElement = currentElement.add(cd, 0);
213 // lastIgnoredToken = -1;
219 // * INTERNAL USE-ONLY
221 //protected void consumeExitVariableWithInitialization() {
222 // // ExitVariableWithInitialization ::= $empty
223 // // the scanner is located after the comma or the semi-colon.
224 // // we want to include the comma or the semi-colon
225 // super.consumeExitVariableWithInitialization();
226 // if (isLocalDeclaration() || ((currentToken != TokenNameCOMMA) &&
227 // (currentToken != TokenNameSEMICOLON)))
229 // ((SourceFieldDeclaration) astStack[astPtr]).fieldEndPosition =
230 // scanner.currentPosition - 1;
232 //protected void consumeExitVariableWithoutInitialization() {
233 // // ExitVariableWithoutInitialization ::= $empty
234 // // do nothing by default
235 // super.consumeExitVariableWithoutInitialization();
236 // if (isLocalDeclaration() || ((currentToken != TokenNameCOMMA) &&
237 // (currentToken != TokenNameSEMICOLON)))
239 // ((SourceFieldDeclaration) astStack[astPtr]).fieldEndPosition =
240 // scanner.currentPosition - 1;
244 // * INTERNAL USE-ONLY
246 //protected void consumeFieldAccess(boolean isSuperAccess) {
247 // // FieldAccess ::= Primary '.' 'Identifier'
248 // // FieldAccess ::= 'super' '.' 'Identifier'
249 // super.consumeFieldAccess(isSuperAccess);
250 // FieldReference fr = (FieldReference) expressionStack[expressionPtr];
251 // if (reportReferenceInfo) {
252 // requestor.acceptFieldReference(fr.token, fr.sourceStart);
255 //protected void consumeMethodHeaderName() {
256 // // MethodHeaderName ::= Modifiersopt Type 'Identifier' '('
257 // SourceMethodDeclaration md = new
258 // SourceMethodDeclaration(this.compilationUnit.compilationResult);
261 // md.selector = identifierStack[identifierPtr];
262 // long selectorSourcePositions = identifierPositionStack[identifierPtr--];
263 // identifierLengthPtr--;
265 // md.returnType = getTypeReference(intStack[intPtr--]);
267 // md.declarationSourceStart = intStack[intPtr--];
268 // md.modifiers = intStack[intPtr--];
270 // //highlight starts at selector start
271 // md.sourceStart = (int) (selectorSourcePositions >>> 32);
272 // md.selectorSourceEnd = (int) selectorSourcePositions;
273 // pushOnAstStack(md);
274 // md.sourceEnd = lParenPos;
275 // md.bodyStart = lParenPos+1;
276 // listLength = 0; // initialize listLength before reading parameters/throws
279 // if (currentElement != null){
280 // if (currentElement instanceof RecoveredType
281 // //|| md.modifiers != 0
282 // || (scanner.getLineNumber(md.returnType.sourceStart)
283 // == scanner.getLineNumber(md.sourceStart))){
284 // lastCheckPoint = md.bodyStart;
285 // currentElement = currentElement.add(md, 0);
286 // lastIgnoredToken = -1;
288 // lastCheckPoint = md.sourceStart;
289 // restartRecovery = true;
295 // * INTERNAL USE-ONLY
297 //protected void consumeMethodInvocationName() {
298 // // MethodInvocation ::= Name '(' ArgumentListopt ')'
300 // // when the name is only an identifier...we have a message send to "this"
302 // super.consumeMethodInvocationName();
303 // MessageSend messageSend = (MessageSend) expressionStack[expressionPtr];
304 // Expression[] args = messageSend.arguments;
305 // if (reportReferenceInfo) {
306 // requestor.acceptMethodReference(
307 // messageSend.selector,
308 // args == null ? 0 : args.length,
309 // (int)(messageSend.nameSourcePosition >>> 32));
314 // * INTERNAL USE-ONLY
316 //protected void consumeMethodInvocationPrimary() {
317 // super.consumeMethodInvocationPrimary();
318 // MessageSend messageSend = (MessageSend) expressionStack[expressionPtr];
319 // Expression[] args = messageSend.arguments;
320 // if (reportReferenceInfo) {
321 // requestor.acceptMethodReference(
322 // messageSend.selector,
323 // args == null ? 0 : args.length,
324 // (int)(messageSend.nameSourcePosition >>> 32));
329 // * INTERNAL USE-ONLY
331 //protected void consumeMethodInvocationSuper() {
332 // // MethodInvocation ::= 'super' '.' 'Identifier' '(' ArgumentListopt ')'
333 // super.consumeMethodInvocationSuper();
334 // MessageSend messageSend = (MessageSend) expressionStack[expressionPtr];
335 // Expression[] args = messageSend.arguments;
336 // if (reportReferenceInfo) {
337 // requestor.acceptMethodReference(
338 // messageSend.selector,
339 // args == null ? 0 : args.length,
340 // (int)(messageSend.nameSourcePosition >>> 32));
343 //protected void consumeSingleTypeImportDeclarationName() {
344 // // SingleTypeImportDeclarationName ::= 'import' Name
345 // /* push an ImportRef build from the last name
346 // stored in the identifier stack. */
348 // super.consumeSingleTypeImportDeclarationName();
349 // ImportReference impt = (ImportReference)astStack[astPtr];
350 // if (reportReferenceInfo) {
351 // requestor.acceptTypeReference(impt.tokens, impt.sourceStart,
355 //protected void consumeTypeImportOnDemandDeclarationName() {
356 // // TypeImportOnDemandDeclarationName ::= 'import' Name '.' '*'
357 // /* push an ImportRef build from the last name
358 // stored in the identifier stack. */
360 // super.consumeTypeImportOnDemandDeclarationName();
361 // ImportReference impt = (ImportReference)astStack[astPtr];
362 // if (reportReferenceInfo) {
363 // requestor.acceptUnknownReference(impt.tokens, impt.sourceStart,
367 //protected FieldDeclaration createFieldDeclaration(Expression
368 // initialization, char[] name, int sourceStart, int sourceEnd) {
369 // return new SourceFieldDeclaration(null, name, sourceStart, sourceEnd);
371 //protected CompilationUnitDeclaration endParse(int act) {
372 // if (sourceType != null) {
373 // if (sourceType.isInterface()) {
374 // consumeInterfaceDeclaration();
376 // consumeClassDeclaration();
379 // if (compilationUnit != null) {
380 // CompilationUnitDeclaration result = super.endParse(act);
387 * Flush annotations defined prior to a given positions.
389 * Note: annotations are stacked in syntactical order
391 * Either answer given <position>, or the end position of a comment line
392 * immediately following the <position> (same line)
394 * e.g. void foo(){ } // end of method foo
397 //public int flushAnnotationsDefinedPriorTo(int position) {
399 // return lastFieldEndPosition =
400 // super.flushAnnotationsDefinedPriorTo(position);
402 //public TypeReference getTypeReference(int dim) {
403 // /* build a Reference on a variable that may be qualified or not
404 // * This variable is a type reference and dim will be its dimensions
407 // if ((length = identifierLengthStack[identifierLengthPtr--]) == 1) {
408 // // single variable reference
410 // SingleTypeReference ref =
411 // new SingleTypeReference(
412 // identifierStack[identifierPtr],
413 // identifierPositionStack[identifierPtr--]);
414 // if (reportReferenceInfo) {
415 // requestor.acceptTypeReference(ref.token, ref.sourceStart);
419 // ArrayTypeReference ref =
420 // new ArrayTypeReference(
421 // identifierStack[identifierPtr],
423 // identifierPositionStack[identifierPtr--]);
424 // ref.sourceEnd = endPosition;
425 // if (reportReferenceInfo) {
426 // requestor.acceptTypeReference(ref.token, ref.sourceStart);
431 // if (length < 0) { //flag for precompiled type reference on base types
432 // TypeReference ref = TypeReference.baseTypeReference(-length, dim);
433 // ref.sourceStart = intStack[intPtr--];
435 // ref.sourceEnd = intStack[intPtr--];
437 // intPtr--; // no need to use this position as it is an array
438 // ref.sourceEnd = endPosition;
440 // if (reportReferenceInfo){
441 // requestor.acceptTypeReference(ref.getTypeName(), ref.sourceStart,
445 // } else { //Qualified variable reference
446 // char[][] tokens = new char[length][];
447 // identifierPtr -= length;
448 // long[] positions = new long[length];
449 // System.arraycopy(identifierStack, identifierPtr + 1, tokens, 0, length);
451 // identifierPositionStack,
452 // identifierPtr + 1,
457 // QualifiedTypeReference ref = new QualifiedTypeReference(tokens, positions);
458 // if (reportReferenceInfo) {
459 // requestor.acceptTypeReference(ref.tokens, ref.sourceStart, ref.sourceEnd);
463 // ArrayQualifiedTypeReference ref =
464 // new ArrayQualifiedTypeReference(tokens, dim, positions);
465 // ref.sourceEnd = endPosition;
466 // if (reportReferenceInfo) {
467 // requestor.acceptTypeReference(ref.tokens, ref.sourceStart, ref.sourceEnd);
474 //public NameReference getUnspecifiedReference() {
475 // /* build a (unspecified) NameReference which may be qualified*/
478 // if ((length = identifierLengthStack[identifierLengthPtr--]) == 1) {
479 // // single variable reference
480 // SingleNameReference ref =
481 // new SingleNameReference(
482 // identifierStack[identifierPtr],
483 // identifierPositionStack[identifierPtr--]);
484 // if (reportReferenceInfo) {
485 // this.addUnknownRef(ref);
489 // //Qualified variable reference
490 // char[][] tokens = new char[length][];
491 // identifierPtr -= length;
492 // System.arraycopy(identifierStack, identifierPtr + 1, tokens, 0, length);
493 // QualifiedNameReference ref =
494 // new QualifiedNameReference(
496 // (int) (identifierPositionStack[identifierPtr + 1] >> 32), // sourceStart
497 // (int) identifierPositionStack[identifierPtr + length]); // sourceEnd
498 // if (reportReferenceInfo) {
499 // this.addUnknownRef(ref);
504 //public NameReference getUnspecifiedReferenceOptimized() {
505 // /* build a (unspecified) NameReference which may be qualified
506 // The optimization occurs for qualified reference while we are
507 // certain in this case the last item of the qualified name is
508 // a field access. This optimization is IMPORTANT while it results
509 // that when a NameReference is build, the type checker should always
510 // look for that it is not a type reference */
513 // if ((length = identifierLengthStack[identifierLengthPtr--]) == 1) {
514 // // single variable reference
515 // SingleNameReference ref =
516 // new SingleNameReference(
517 // identifierStack[identifierPtr],
518 // identifierPositionStack[identifierPtr--]);
519 // ref.bits &= ~ASTNode.RestrictiveFlagMASK;
520 // ref.bits |= LOCAL | FIELD;
521 // if (reportReferenceInfo) {
522 // this.addUnknownRef(ref);
527 // //Qualified-variable-reference
528 // //In fact it is variable-reference DOT field-ref , but it would result in a
530 // //conflict tha can be only reduce by making a superclass (or inetrface )
532 // //nameReference and FiledReference or putting FieldReference under
534 // //or else..........This optimisation is not really relevant so just leave
537 // char[][] tokens = new char[length][];
538 // identifierPtr -= length;
539 // System.arraycopy(identifierStack, identifierPtr + 1, tokens, 0, length);
540 // QualifiedNameReference ref =
541 // new QualifiedNameReference(
543 // (int) (identifierPositionStack[identifierPtr + 1] >> 32),
545 // (int) identifierPositionStack[identifierPtr + length]); // sourceEnd
546 // ref.bits &= ~ASTNode.RestrictiveFlagMASK;
547 // ref.bits |= LOCAL | FIELD;
548 // if (reportReferenceInfo) {
549 // this.addUnknownRef(ref);
555 // * INTERNAL USE-ONLY
557 //private boolean isLocalDeclaration() {
558 // int nestedDepth = nestedType;
559 // while (nestedDepth >= 0) {
560 // if (nestedMethod[nestedDepth] != 0) {
568 * Update the bodyStart of the corresponding parse node
570 public void notifySourceElementRequestor(CompilationUnitDeclaration parsedUnit) {
571 if (parsedUnit == null) {
572 // when we parse a single type member declaration the compilation unit is
573 // null, but we still
574 // want to be able to notify the requestor on the created ast node
575 if (astStack[0] instanceof AbstractMethodDeclaration) {
576 notifySourceElementRequestor((AbstractMethodDeclaration) astStack[0]);
582 boolean isInRange = scanner.initialPosition <= parsedUnit.sourceStart && scanner.eofPosition >= parsedUnit.sourceEnd;
584 // if (reportReferenceInfo) {
585 // notifyAllUnknownReferences();
587 // collect the top level ast nodes
589 ASTNode[] nodes = null;
590 if (sourceType == null) {
592 requestor.enterCompilationUnit();
594 // ImportReference currentPackage = parsedUnit.currentPackage;
595 ImportReference[] imports = parsedUnit.imports;
596 // TypeDeclaration[] types = parsedUnit.types;
597 ArrayList types = parsedUnit.types;
600 // (currentPackage == null ? 0 : 1)
601 // + (imports == null ? 0 : imports.length)
602 // + (types == null ? 0 : types.length);
603 // nodes = new ASTNode[length];
604 length = (imports == null ? 0 : imports.length) + types.size();
605 nodes = new ASTNode[length];
607 // if (currentPackage != null) {
608 // nodes[index++] = currentPackage;
610 if (imports != null) {
611 for (int i = 0, max = imports.length; i < max; i++) {
612 nodes[index++] = imports[i];
616 for (int i = 0, max = types.size(); i < max; i++) {
617 nodes[index++] = (ASTNode) types.get(i);
621 // TypeDeclaration[] types = parsedUnit.types;
622 ArrayList types = parsedUnit.types;
624 length = types.size();
625 nodes = new ASTNode[length];
626 for (int i = 0, max = types.size(); i < max; i++) {
627 nodes[i] = (ASTNode) types.get(i);
632 // notify the nodes in the syntactical order
633 if (nodes != null && length > 0) {
634 quickSort(nodes, 0, length - 1);
635 for (int i = 0; i < length; i++) {
636 ASTNode node = nodes[i];
637 if (node instanceof ImportReference) {
638 ImportReference importRef = (ImportReference)node;
639 // if (node == parsedUnit.currentPackage) {
640 // notifySourceElementRequestor(importRef, true);
642 notifySourceElementRequestor(importRef, false);
644 } //else { instanceof TypeDeclaration
645 if (node instanceof TypeDeclaration) {
646 notifySourceElementRequestor((TypeDeclaration) node, sourceType == null);
647 // notifySourceElementRequestor((CompilationUnitDeclaration)node,
648 // sourceType == null);
650 // jsurfer - INSERT start
651 if (node instanceof AbstractMethodDeclaration) {
652 notifySourceElementRequestor((AbstractMethodDeclaration) node);
654 // jsurfer - INSERT end
658 if (sourceType == null) {
660 requestor.exitCompilationUnit(parsedUnit.sourceEnd);
665 //private void notifyAllUnknownReferences() {
666 // for (int i = 0, max = this.unknownRefsCounter; i < max; i++) {
667 // NameReference nameRef = this.unknownRefs[i];
668 // if ((nameRef.bits & BindingIds.VARIABLE) != 0) {
669 // if ((nameRef.bits & BindingIds.TYPE) == 0) {
670 // // variable but not type
671 // if (nameRef instanceof SingleNameReference) {
672 // // local var or field
673 // requestor.acceptUnknownReference(((SingleNameReference) nameRef).token,
674 // nameRef.sourceStart);
676 // // QualifiedNameReference
677 // // The last token is a field reference and the previous tokens are a
678 // type/variable references
679 // char[][] tokens = ((QualifiedNameReference) nameRef).tokens;
680 // int tokensLength = tokens.length;
681 // requestor.acceptFieldReference(tokens[tokensLength - 1], nameRef.sourceEnd
682 // - tokens[tokensLength - 1].length + 1);
683 // char[][] typeRef = new char[tokensLength - 1][];
684 // System.arraycopy(tokens, 0, typeRef, 0, tokensLength - 1);
685 // requestor.acceptUnknownReference(typeRef, nameRef.sourceStart,
686 // nameRef.sourceEnd - tokens[tokensLength - 1].length);
689 // // variable or type
690 // if (nameRef instanceof SingleNameReference) {
691 // requestor.acceptUnknownReference(((SingleNameReference) nameRef).token,
692 // nameRef.sourceStart);
694 // //QualifiedNameReference
695 // requestor.acceptUnknownReference(((QualifiedNameReference) nameRef).tokens,
696 // nameRef.sourceStart, nameRef.sourceEnd);
699 // } else if ((nameRef.bits & BindingIds.TYPE) != 0) {
700 // if (nameRef instanceof SingleNameReference) {
701 // requestor.acceptTypeReference(((SingleNameReference) nameRef).token,
702 // nameRef.sourceStart);
704 // // it is a QualifiedNameReference
705 // requestor.acceptTypeReference(((QualifiedNameReference) nameRef).tokens,
706 // nameRef.sourceStart, nameRef.sourceEnd);
712 * Update the bodyStart of the corresponding parse node
714 public void notifySourceElementRequestor(AbstractMethodDeclaration methodDeclaration) {
717 boolean isInRange = scanner.initialPosition <= methodDeclaration.declarationSourceStart
718 && scanner.eofPosition >= methodDeclaration.declarationSourceEnd;
720 if (methodDeclaration.isClinit()) {
721 this.visitIfNeeded(methodDeclaration);
725 if (methodDeclaration.isDefaultConstructor()) {
726 if (reportReferenceInfo) {
727 ConstructorDeclaration constructorDeclaration = (ConstructorDeclaration) methodDeclaration;
728 ExplicitConstructorCall constructorCall = constructorDeclaration.constructorCall;
729 if (constructorCall != null) {
730 switch (constructorCall.accessMode) {
731 case ExplicitConstructorCall.This :
732 requestor.acceptConstructorReference(typeNames[nestedTypeIndex - 1], constructorCall.arguments == null
734 : constructorCall.arguments.length, constructorCall.sourceStart);
736 case ExplicitConstructorCall.Super :
737 case ExplicitConstructorCall.ImplicitSuper :
738 requestor.acceptConstructorReference(superTypeNames[nestedTypeIndex - 1], constructorCall.arguments == null
740 : constructorCall.arguments.length, constructorCall.sourceStart);
747 char[][] argumentTypes = null;
748 char[][] argumentNames = null;
749 Argument[] arguments = methodDeclaration.arguments;
750 if (arguments != null) {
751 int argumentLength = arguments.length;
752 argumentTypes = new char[argumentLength][];
753 argumentNames = new char[argumentLength][];
754 for (int i = 0; i < argumentLength; i++) {
755 argumentTypes[i] = returnTypeName(arguments[i].type);
756 argumentNames[i] = arguments[i].name;
759 char[][] thrownExceptionTypes = null;
760 TypeReference[] thrownExceptions = methodDeclaration.thrownExceptions;
761 if (thrownExceptions != null) {
762 int thrownExceptionLength = thrownExceptions.length;
763 thrownExceptionTypes = new char[thrownExceptionLength][];
764 for (int i = 0; i < thrownExceptionLength; i++) {
765 thrownExceptionTypes[i] = CharOperation.concatWith(thrownExceptions[i].getTypeName(), '.');
768 // by default no selector end position
769 int selectorSourceEnd = -1;
770 if (methodDeclaration.isConstructor()) {
771 // if (methodDeclaration instanceof SourceConstructorDeclaration) {
772 // selectorSourceEnd =
773 // ((SourceConstructorDeclaration) methodDeclaration).selectorSourceEnd;
776 requestor.enterConstructor(methodDeclaration.declarationSourceStart, methodDeclaration.modifiers,
777 methodDeclaration.selector, methodDeclaration.sourceStart, selectorSourceEnd, argumentTypes, argumentNames,
778 thrownExceptionTypes);
780 if (reportReferenceInfo) {
781 ConstructorDeclaration constructorDeclaration = (ConstructorDeclaration) methodDeclaration;
782 ExplicitConstructorCall constructorCall = constructorDeclaration.constructorCall;
783 if (constructorCall != null) {
784 switch (constructorCall.accessMode) {
785 case ExplicitConstructorCall.This :
786 requestor.acceptConstructorReference(typeNames[nestedTypeIndex - 1], constructorCall.arguments == null
788 : constructorCall.arguments.length, constructorCall.sourceStart);
790 case ExplicitConstructorCall.Super :
791 case ExplicitConstructorCall.ImplicitSuper :
792 requestor.acceptConstructorReference(superTypeNames[nestedTypeIndex - 1], constructorCall.arguments == null
794 : constructorCall.arguments.length, constructorCall.sourceStart);
799 this.visitIfNeeded(methodDeclaration);
801 requestor.exitConstructor(methodDeclaration.declarationSourceEnd);
805 // if (methodDeclaration instanceof SourceMethodDeclaration) {
806 // selectorSourceEnd =
807 // ((SourceMethodDeclaration) methodDeclaration).selectorSourceEnd;
810 int modifiers = methodDeclaration.modifiers;
811 // boolean deprecated = (modifiers & AccDeprecated) != 0; // remember
812 // deprecation so as to not lose it below
813 requestor.enterMethod(methodDeclaration.declarationSourceStart, modifiers, // deprecated
824 returnTypeName(((MethodDeclaration) methodDeclaration).returnType), methodDeclaration.selector,
825 methodDeclaration.sourceStart, selectorSourceEnd, argumentTypes, argumentNames, thrownExceptionTypes);
827 this.visitIfNeeded(methodDeclaration);
830 requestor.exitMethod(methodDeclaration.declarationSourceEnd);
834 * Update the bodyStart of the corresponding parse node
836 public void notifySourceElementRequestor(FieldDeclaration fieldDeclaration) {
839 boolean isInRange = scanner.initialPosition <= fieldDeclaration.declarationSourceStart
840 && scanner.eofPosition >= fieldDeclaration.declarationSourceEnd;
842 if (fieldDeclaration.isField()) {
843 int fieldEndPosition = fieldDeclaration.declarationSourceEnd;
844 // if (fieldDeclaration instanceof SourceFieldDeclaration) {
845 // fieldEndPosition = ((SourceFieldDeclaration)
846 // fieldDeclaration).fieldEndPosition;
847 // if (fieldEndPosition == 0) {
848 // // use the declaration source end by default
849 // fieldEndPosition = fieldDeclaration.declarationSourceEnd;
853 int modifiers = fieldDeclaration.modifiers;
854 boolean deprecated = (modifiers & AccDeprecated) != 0; // remember
858 requestor.enterField(fieldDeclaration.declarationSourceStart, deprecated
859 ? (modifiers & AccJustFlag) | AccDeprecated
860 : modifiers & AccJustFlag, returnTypeName(fieldDeclaration.type), fieldDeclaration.name, fieldDeclaration.sourceStart,
861 fieldDeclaration.sourceEnd);
863 // this.visitIfNeeded(fieldDeclaration);
865 // requestor.exitField(
866 // // filter out initializations that are not a constant (simple check)
867 // (fieldDeclaration.initialization == null
868 // || fieldDeclaration.initialization instanceof ArrayInitializer
869 // || fieldDeclaration.initialization instanceof AllocationExpression
870 // || fieldDeclaration.initialization instanceof
871 // ArrayAllocationExpression
872 // || fieldDeclaration.initialization instanceof Assignment
873 // || fieldDeclaration.initialization instanceof ClassLiteralAccess
874 // || fieldDeclaration.initialization instanceof MessageSend
875 // || fieldDeclaration.initialization instanceof ArrayReference
876 // || fieldDeclaration.initialization instanceof ThisReference) ?
878 // fieldDeclaration.initialization.sourceStart,
880 // fieldDeclaration.declarationSourceEnd);
882 // filter out initializations that are not a constant (simple check)
883 -1, fieldEndPosition, fieldDeclaration.declarationSourceEnd);
888 // requestor.enterInitializer(
889 // fieldDeclaration.declarationSourceStart,
890 // fieldDeclaration.modifiers);
892 // this.visitIfNeeded((Initializer)fieldDeclaration);
894 // requestor.exitInitializer(fieldDeclaration.declarationSourceEnd);
898 public void notifySourceElementRequestor(
899 ImportReference importReference,
902 // requestor.acceptPackage(
903 // importReference.declarationSourceStart,
904 // importReference.declarationSourceEnd,
905 // CharOperation.concatWith(importReference.getImportName(), '.'));
907 requestor.acceptImport(
908 importReference.declarationSourceStart,
909 importReference.declarationSourceEnd,
910 importReference.getIncludeName(), //CharOperation.concatWith(importReference.getImportName(), '.'),
911 importReference.onDemand);
914 public void notifySourceElementRequestor(TypeDeclaration typeDeclaration, boolean notifyTypePresence) {
915 //// public void notifySourceElementRequestor(ASTNode typeDeclaration,
916 // boolean notifyTypePresence) {
919 boolean isInRange = scanner.initialPosition <= typeDeclaration.declarationSourceStart
920 && scanner.eofPosition >= typeDeclaration.declarationSourceEnd;
922 FieldDeclaration[] fields = typeDeclaration.fields;
923 AbstractMethodDeclaration[] methods = typeDeclaration.methods;
924 MemberTypeDeclaration[] memberTypes = typeDeclaration.memberTypes;
925 int fieldCount = fields == null ? 0 : fields.length;
926 int methodCount = methods == null ? 0 : methods.length;
927 int memberTypeCount = memberTypes == null ? 0 : memberTypes.length;
930 int memberTypeIndex = 0;
931 boolean isInterface = typeDeclaration.isInterface();
933 if (notifyTypePresence) {
934 char[][] interfaceNames = null;
935 int superInterfacesLength = 0;
936 TypeReference[] superInterfaces = typeDeclaration.superInterfaces;
937 if (superInterfaces != null) {
938 superInterfacesLength = superInterfaces.length;
939 interfaceNames = new char[superInterfacesLength][];
941 if (typeDeclaration instanceof AnonymousLocalTypeDeclaration) {
943 QualifiedAllocationExpression alloc = ((AnonymousLocalTypeDeclaration) typeDeclaration).allocation;
944 if (alloc != null && alloc.type != null) {
945 superInterfaces = new TypeReference[]{((AnonymousLocalTypeDeclaration) typeDeclaration).allocation.type};
946 superInterfacesLength = 1;
947 interfaceNames = new char[1][];
951 if (superInterfaces != null) {
952 for (int i = 0; i < superInterfacesLength; i++) {
953 interfaceNames[i] = CharOperation.concatWith(superInterfaces[i].getTypeName(), '.');
958 int modifiers = typeDeclaration.modifiers;
959 boolean deprecated = false; //(modifiers & AccDeprecated) != 0; //
960 // remember deprecation so as to not lose
962 requestor.enterInterface(typeDeclaration.declarationSourceStart, modifiers, //deprecated
973 typeDeclaration.name, typeDeclaration.sourceStart, typeDeclaration.sourceEnd, interfaceNames);
975 if (nestedTypeIndex == typeNames.length) {
977 System.arraycopy(typeNames, 0, (typeNames = new char[nestedTypeIndex * 2][]), 0, nestedTypeIndex);
978 System.arraycopy(superTypeNames, 0, (superTypeNames = new char[nestedTypeIndex * 2][]), 0, nestedTypeIndex);
980 typeNames[nestedTypeIndex] = typeDeclaration.name;
981 superTypeNames[nestedTypeIndex++] = JAVA_LANG_OBJECT;
983 TypeReference superclass = typeDeclaration.superclass;
984 if (superclass == null) {
986 requestor.enterClass(typeDeclaration.declarationSourceStart, typeDeclaration.modifiers, typeDeclaration.name,
987 typeDeclaration.sourceStart, typeDeclaration.sourceEnd, null, interfaceNames);
991 requestor.enterClass(typeDeclaration.declarationSourceStart, typeDeclaration.modifiers, typeDeclaration.name,
992 typeDeclaration.sourceStart, typeDeclaration.sourceEnd, CharOperation.concatWith(superclass.getTypeName(), '.'),
996 if (nestedTypeIndex == typeNames.length) {
998 System.arraycopy(typeNames, 0, (typeNames = new char[nestedTypeIndex * 2][]), 0, nestedTypeIndex);
999 System.arraycopy(superTypeNames, 0, (superTypeNames = new char[nestedTypeIndex * 2][]), 0, nestedTypeIndex);
1001 typeNames[nestedTypeIndex] = typeDeclaration.name;
1002 superTypeNames[nestedTypeIndex++] = superclass == null ? JAVA_LANG_OBJECT : CharOperation.concatWith(superclass
1003 .getTypeName(), '.');
1006 while ((fieldIndex < fieldCount) || (memberTypeIndex < memberTypeCount) || (methodIndex < methodCount)) {
1007 FieldDeclaration nextFieldDeclaration = null;
1008 AbstractMethodDeclaration nextMethodDeclaration = null;
1009 TypeDeclaration nextMemberDeclaration = null;
1011 int position = Integer.MAX_VALUE;
1012 int nextDeclarationType = -1;
1013 if (fieldIndex < fieldCount) {
1014 nextFieldDeclaration = fields[fieldIndex];
1015 if (nextFieldDeclaration.declarationSourceStart < position) {
1016 position = nextFieldDeclaration.declarationSourceStart;
1017 nextDeclarationType = 0; // FIELD
1020 if (methodIndex < methodCount) {
1021 nextMethodDeclaration = methods[methodIndex];
1022 if (nextMethodDeclaration.declarationSourceStart < position) {
1023 position = nextMethodDeclaration.declarationSourceStart;
1024 nextDeclarationType = 1; // METHOD
1027 if (memberTypeIndex < memberTypeCount) {
1028 nextMemberDeclaration = memberTypes[memberTypeIndex];
1029 if (nextMemberDeclaration.declarationSourceStart < position) {
1030 position = nextMemberDeclaration.declarationSourceStart;
1031 nextDeclarationType = 2; // MEMBER
1034 switch (nextDeclarationType) {
1037 notifySourceElementRequestor(nextFieldDeclaration);
1041 notifySourceElementRequestor(nextMethodDeclaration);
1045 notifySourceElementRequestor(nextMemberDeclaration, true);
1048 if (notifyTypePresence) {
1051 requestor.exitInterface(typeDeclaration.declarationSourceEnd);
1053 requestor.exitClass(typeDeclaration.declarationSourceEnd);
1059 public void parseCompilationUnit(ICompilationUnit unit, int start, int end) {
1060 // boolean needReferenceInfo) {
1062 // reportReferenceInfo = needReferenceInfo;
1063 // boolean old = diet;
1064 // if (needReferenceInfo) {
1065 // unknownRefs = new NameReference[10];
1066 // unknownRefsCounter = 0;
1071 CompilationResult compilationUnitResult = new CompilationResult(unit, 0, 0, 10); //this.options.maxProblemsPerUnit);
1072 CompilationUnitDeclaration parsedUnit = parse(unit, compilationUnitResult, start, end);
1073 // if (scanner.recordLineSeparator) {
1074 // requestor.acceptLineSeparatorPositions(scanner.getLineEnds());
1076 // if (this.localDeclarationVisitor != null || needReferenceInfo){
1078 // this.getMethodBodies(parsedUnit);
1080 // this.scanner.resetTo(start, end);
1081 // notifySourceElementRequestor(parsedUnit);
1082 } catch (AbortCompilation e) {
1087 public CompilationUnitDeclaration parseCompilationUnit(ICompilationUnit unit, boolean fullParse) {
1089 // boolean old = diet;
1091 // unknownRefs = new NameReference[10];
1092 // unknownRefsCounter = 0;
1097 this.reportReferenceInfo = fullParse;
1098 CompilationResult compilationUnitResult = new CompilationResult(unit, 0, 0, this.options.maxProblemsPerUnit);
1099 CompilationUnitDeclaration parsedUnit = parse(unit, compilationUnitResult, false);
1100 if (scanner.recordLineSeparator) {
1101 requestor.acceptLineSeparatorPositions(scanner.getLineEnds());
1103 int initialStart = this.scanner.initialPosition;
1104 int initialEnd = this.scanner.eofPosition;
1105 // if (this.localDeclarationVisitor != null || fullParse){
1107 // this.getMethodBodies(parsedUnit);
1109 this.scanner.resetTo(initialStart, initialEnd);
1110 notifySourceElementRequestor(parsedUnit);
1112 } catch (AbortCompilation e) {
1113 // ignore this exception
1120 public CompilationUnitDeclaration parseCompletionUnit(ICompilationUnit unit, boolean fullParse) {
1122 // boolean old = diet;
1124 // unknownRefs = new NameReference[10];
1125 // unknownRefsCounter = 0;
1130 this.reportReferenceInfo = fullParse;
1131 CompilationResult compilationUnitResult = new CompilationResult(unit, 0, 0, this.options.maxProblemsPerUnit);
1132 CompilationUnitDeclaration parsedUnit = parse(unit, compilationUnitResult, false);
1133 // if (scanner.recordLineSeparator) {
1134 // requestor.acceptLineSeparatorPositions(scanner.getLineEnds());
1136 // int initialStart = this.scanner.initialPosition;
1137 // int initialEnd = this.scanner.eofPosition;
1138 // // if (this.localDeclarationVisitor != null || fullParse){
1140 // // this.getMethodBodies(parsedUnit);
1142 // this.scanner.resetTo(initialStart, initialEnd);
1143 // notifySourceElementRequestor(parsedUnit);
1145 } catch (AbortCompilation e) {
1146 // ignore this exception
1152 //public void parseTypeMemberDeclarations(
1153 // ISourceType sourceType,
1154 // ICompilationUnit sourceUnit,
1157 // boolean needReferenceInfo) {
1158 // boolean old = diet;
1159 // if (needReferenceInfo) {
1160 // unknownRefs = new NameReference[10];
1161 // unknownRefsCounter = 0;
1165 // diet = !needReferenceInfo;
1166 // reportReferenceInfo = needReferenceInfo;
1167 // CompilationResult compilationUnitResult =
1168 // new CompilationResult(sourceUnit, 0, 0, this.options.maxProblemsPerUnit);
1169 // CompilationUnitDeclaration unit =
1170 // SourceTypeConverter.buildCompilationUnit(
1171 // new ISourceType[]{sourceType},
1172 // false, // no need for field and methods
1173 // false, // no need for member types
1174 // false, // no need for field initialization
1175 // problemReporter(),
1176 // compilationUnitResult);
1177 // if ((unit == null) || (unit.types == null) || (unit.types.length != 1))
1179 // this.sourceType = sourceType;
1181 // /* automaton initialization */
1183 // goForClassBodyDeclarations();
1184 // /* scanner initialization */
1185 // scanner.setSource(sourceUnit.getContents());
1186 // scanner.resetTo(start, end);
1187 // /* unit creation */
1188 // referenceContext = compilationUnit = unit;
1189 // /* initialize the astStacl */
1190 // // the compilationUnitDeclaration should contain exactly one type
1191 // pushOnAstStack(unit.types[0]);
1192 // /* run automaton */
1194 // notifySourceElementRequestor(unit);
1196 // unit = compilationUnit;
1197 // compilationUnit = null; // reset parser
1199 // } catch (AbortCompilation e) {
1201 // if (scanner.recordLineSeparator) {
1202 // requestor.acceptLineSeparatorPositions(scanner.getLineEnds());
1208 //public void parseTypeMemberDeclarations(
1213 // boolean old = diet;
1218 // /* automaton initialization */
1220 // goForClassBodyDeclarations();
1221 // /* scanner initialization */
1222 // scanner.setSource(contents);
1223 // scanner.recordLineSeparator = false;
1224 // scanner.taskTags = null;
1225 // scanner.taskPriorities = null;
1226 // scanner.resetTo(start, end);
1228 // /* unit creation */
1229 // referenceContext = null;
1231 // /* initialize the astStacl */
1232 // // the compilationUnitDeclaration should contain exactly one type
1233 // /* run automaton */
1235 // notifySourceElementRequestor((CompilationUnitDeclaration)null);
1236 // } catch (AbortCompilation e) {
1242 * Sort the given ast nodes by their positions.
1244 private static void quickSort(ASTNode[] sortedCollection, int left, int right) {
1245 int original_left = left;
1246 int original_right = right;
1247 ASTNode mid = sortedCollection[(left + right) / 2];
1249 while (sortedCollection[left].sourceStart < mid.sourceStart) {
1252 while (mid.sourceStart < sortedCollection[right].sourceStart) {
1255 if (left <= right) {
1256 ASTNode tmp = sortedCollection[left];
1257 sortedCollection[left] = sortedCollection[right];
1258 sortedCollection[right] = tmp;
1262 } while (left <= right);
1263 if (original_left < right) {
1264 quickSort(sortedCollection, original_left, right);
1266 if (left < original_right) {
1267 quickSort(sortedCollection, left, original_right);
1271 * Answer a char array representation of the type name formatted like: - type
1272 * name + dimensions Example: "A[][]".toCharArray()
1273 * "java.lang.String".toCharArray()
1275 private char[] returnTypeName(TypeReference type) {
1278 int dimension = type.dimensions();
1279 if (dimension != 0) {
1280 char[] dimensionsArray = new char[dimension * 2];
1281 for (int i = 0; i < dimension; i++) {
1282 dimensionsArray[i * 2] = '[';
1283 dimensionsArray[(i * 2) + 1] = ']';
1285 return CharOperation.concat(CharOperation.concatWith(type.getTypeName(), '.'), dimensionsArray);
1287 return CharOperation.concatWith(type.getTypeName(), '.');
1290 public void addUnknownRef(NameReference nameRef) {
1291 if (this.unknownRefs.length == this.unknownRefsCounter) {
1293 System.arraycopy(this.unknownRefs, 0, (this.unknownRefs = new NameReference[this.unknownRefsCounter * 2]), 0,
1294 this.unknownRefsCounter);
1296 this.unknownRefs[this.unknownRefsCounter++] = nameRef;
1299 private void visitIfNeeded(AbstractMethodDeclaration method) {
1300 if (this.localDeclarationVisitor != null && (method.bits & ASTNode.HasLocalTypeMASK) != 0) {
1301 if (method.statements != null) {
1302 int statementsLength = method.statements.length;
1303 for (int i = 0; i < statementsLength; i++)
1304 method.statements[i].traverse(this.localDeclarationVisitor, method.scope);
1309 //private void visitIfNeeded(FieldDeclaration field) {
1310 // if (this.localDeclarationVisitor != null
1311 // && (field.bits & ASTNode.HasLocalTypeMASK) != 0) {
1312 // if (field.initialization != null) {
1313 // field.initialization.traverse(this.localDeclarationVisitor, null);
1318 //private void visitIfNeeded(Initializer initializer) {
1319 // if (this.localDeclarationVisitor != null
1320 // && (initializer.bits & ASTNode.HasLocalTypeMASK) != 0) {
1321 // if (initializer.block != null) {
1322 // initializer.block.traverse(this.localDeclarationVisitor, null);
1327 //protected void reportSyntaxError(int act, int currentKind, int
1329 // if (compilationUnit == null) return;
1330 // super.reportSyntaxError(act, currentKind,stateStackTop);
1332 protected CompilationUnitDeclaration endParse(int act) {
1333 // if (sourceType != null) {
1334 // if (sourceType.isInterface()) {
1335 // consumeInterfaceDeclaration();
1337 // consumeClassDeclaration();
1340 if (compilationUnit != null) {
1341 CompilationUnitDeclaration result = super.endParse(act);