1 /*******************************************************************************
2 * Copyright (c) 2000, 2003 IBM Corporation and others.
3 * All rights reserved. This program and the accompanying materials
4 * are made available under the terms of the Common Public License v1.0
5 * which accompanies this distribution, and is available at
6 * http://www.eclipse.org/legal/cpl-v10.html
9 * IBM Corporation - initial API and implementation
10 *******************************************************************************/
11 package net.sourceforge.phpdt.internal.compiler;
13 import java.util.ArrayList;
15 import net.sourceforge.phpdt.core.compiler.CharOperation;
16 import net.sourceforge.phpdt.core.compiler.IProblem;
17 import net.sourceforge.phpdt.internal.compiler.env.ICompilationUnit;
18 import net.sourceforge.phpdt.internal.compiler.env.ISourceType;
19 import net.sourceforge.phpdt.internal.compiler.impl.CompilerOptions;
20 import net.sourceforge.phpdt.internal.compiler.impl.ReferenceContext;
21 import net.sourceforge.phpdt.internal.compiler.lookup.BlockScope;
22 import net.sourceforge.phpdt.internal.compiler.lookup.ClassScope;
23 import net.sourceforge.phpdt.internal.compiler.problem.AbortCompilation;
24 import net.sourceforge.phpdt.internal.compiler.problem.ProblemReporter;
25 import net.sourceforge.phpdt.internal.core.util.CommentRecorderParser;
26 import net.sourceforge.phpeclipse.internal.compiler.ast.ASTNode;
27 import net.sourceforge.phpeclipse.internal.compiler.ast.AbstractMethodDeclaration;
28 import net.sourceforge.phpeclipse.internal.compiler.ast.AnonymousLocalTypeDeclaration;
29 import net.sourceforge.phpeclipse.internal.compiler.ast.Argument;
30 import net.sourceforge.phpeclipse.internal.compiler.ast.CompilationUnitDeclaration;
31 import net.sourceforge.phpeclipse.internal.compiler.ast.ConstructorDeclaration;
32 import net.sourceforge.phpeclipse.internal.compiler.ast.ExplicitConstructorCall;
33 import net.sourceforge.phpeclipse.internal.compiler.ast.FieldDeclaration;
34 import net.sourceforge.phpeclipse.internal.compiler.ast.ImportReference;
35 import net.sourceforge.phpeclipse.internal.compiler.ast.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;
43 import org.eclipse.core.resources.IResource;
46 * A source element parser extracts structural and reference information
47 * from a piece of source.
49 * also see @ISourceElementRequestor
51 * The structural investigation includes:
52 * - the package statement
54 * - top-level types: package member, member types (member types of member types...)
58 * If reference information is requested, then all source constructs are
59 * investigated and type, field & method references are provided as well.
61 * Any (parsing) problem encountered is also provided.
64 public class SourceElementParser extends CommentRecorderParser {//extends
67 ISourceElementRequestor requestor;
70 int lastFieldEndPosition;
71 ISourceType sourceType;
72 boolean reportReferenceInfo;
74 char[][] superTypeNames;
76 static final char[] JAVA_LANG_OBJECT = "java.lang.Object".toCharArray(); //$NON-NLS-1$
77 NameReference[] unknownRefs;
78 int unknownRefsCounter;
79 LocalDeclarationVisitor localDeclarationVisitor = null;
80 // CompilerOptions options;
83 * An ast visitor that visits local type declarations.
85 public class LocalDeclarationVisitor extends AbstractSyntaxTreeVisitorAdapter {
86 // public boolean visit(
87 // AnonymousLocalTypeDeclaration anonymousTypeDeclaration,
88 // BlockScope scope) {
89 // notifySourceElementRequestor(anonymousTypeDeclaration, sourceType ==
91 // return false; // don't visit members as this was done during
92 // notifySourceElementRequestor(...)
94 public boolean visit(LocalTypeDeclaration typeDeclaration, BlockScope scope) {
95 notifySourceElementRequestor(typeDeclaration, sourceType == null);
96 return false; // don't visit members as this was done during
97 // notifySourceElementRequestor(...)
99 public boolean visit(MemberTypeDeclaration typeDeclaration, ClassScope scope) {
100 notifySourceElementRequestor(typeDeclaration, sourceType == null);
101 return false; // don't visit members as this was done during
102 // notifySourceElementRequestor(...)
107 public SourceElementParser(final ISourceElementRequestor requestor, IProblemFactory problemFactory, CompilerOptions options) {
108 // we want to notify all syntax error with the acceptProblem API
109 // To do so, we define the record method of the ProblemReporter
110 super( new ProblemReporter(DefaultErrorHandlingPolicies.exitAfterAllProblems(), options, problemFactory) {
111 public void record(IProblem problem, CompilationResult unitResult, ReferenceContext referenceContext) {
112 unitResult.record(problem, referenceContext);
113 if (requestor!=null) {
114 requestor.acceptProblem(problem);
119 // options.sourceLevel >= CompilerOptions.JDK1_4);
120 this.requestor = requestor;
121 typeNames = new char[4][];
122 superTypeNames = new char[4][];
124 this.options = options;
128 * @deprecated use SourceElementParser(ISourceElementRequestor,
129 * IProblemFactory, CompilerOptions)
131 //public SourceElementParser(
132 // final ISourceElementRequestor requestor,
133 // IProblemFactory problemFactory) {
134 // this(requestor, problemFactory, new CompilerOptions());
136 //public SourceElementParser(
137 // final ISourceElementRequestor requestor,
138 // IProblemFactory problemFactory,
139 // CompilerOptions options,
140 // boolean reportLocalDeclarations) {
141 // this(requestor, problemFactory, options);
142 // if (reportLocalDeclarations) {
143 // this.localDeclarationVisitor = new LocalDeclarationVisitor();
146 //public void checkAnnotation() {
147 // int firstCommentIndex = scanner.commentPtr;
149 // super.checkAnnotation();
151 // // modify the modifier source start to point at the first comment
152 // if (firstCommentIndex >= 0) {
153 // modifiersSourceStart = scanner.commentStarts[0];
156 //protected void classInstanceCreation(boolean alwaysQualified) {
158 // boolean previousFlag = reportReferenceInfo;
159 // reportReferenceInfo = false; // not to see the type reference reported in
160 // super call to getTypeReference(...)
161 // super.classInstanceCreation(alwaysQualified);
162 // reportReferenceInfo = previousFlag;
163 // if (reportReferenceInfo){
164 // AllocationExpression alloc =
165 // (AllocationExpression)expressionStack[expressionPtr];
166 // TypeReference typeRef = alloc.type;
167 // requestor.acceptConstructorReference(
168 // typeRef instanceof SingleTypeReference
169 // ? ((SingleTypeReference) typeRef).token
170 // : CharOperation.concatWith(alloc.type.getTypeName(), '.'),
171 // alloc.arguments == null ? 0 : alloc.arguments.length,
172 // alloc.sourceStart);
175 //protected void consumeConstructorHeaderName() {
176 // // ConstructorHeaderName ::= Modifiersopt 'Identifier' '('
178 // /* recovering - might be an empty message send */
179 // if (currentElement != null){
180 // if (lastIgnoredToken == TokenNamenew){ // was an allocation expression
181 // lastCheckPoint = scanner.startPosition; // force to restart at this exact
183 // restartRecovery = true;
187 // SourceConstructorDeclaration cd = new
188 // SourceConstructorDeclaration(this.compilationUnit.compilationResult);
190 // //name -- this is not really revelant but we do .....
191 // cd.selector = identifierStack[identifierPtr];
192 // long selectorSourcePositions = identifierPositionStack[identifierPtr--];
193 // identifierLengthPtr--;
196 // cd.declarationSourceStart = intStack[intPtr--];
197 // cd.modifiers = intStack[intPtr--];
199 // //highlight starts at the selector starts
200 // cd.sourceStart = (int) (selectorSourcePositions >>> 32);
201 // cd.selectorSourceEnd = (int) selectorSourcePositions;
202 // pushOnAstStack(cd);
204 // cd.sourceEnd = lParenPos;
205 // cd.bodyStart = lParenPos+1;
206 // listLength = 0; // initialize listLength before reading parameters/throws
209 // if (currentElement != null){
210 // lastCheckPoint = cd.bodyStart;
211 // if ((currentElement instanceof RecoveredType && lastIgnoredToken !=
213 // || cd.modifiers != 0){
214 // currentElement = currentElement.add(cd, 0);
215 // lastIgnoredToken = -1;
221 // * INTERNAL USE-ONLY
223 //protected void consumeExitVariableWithInitialization() {
224 // // ExitVariableWithInitialization ::= $empty
225 // // the scanner is located after the comma or the semi-colon.
226 // // we want to include the comma or the semi-colon
227 // super.consumeExitVariableWithInitialization();
228 // if (isLocalDeclaration() || ((currentToken != TokenNameCOMMA) &&
229 // (currentToken != TokenNameSEMICOLON)))
231 // ((SourceFieldDeclaration) astStack[astPtr]).fieldEndPosition =
232 // scanner.currentPosition - 1;
234 //protected void consumeExitVariableWithoutInitialization() {
235 // // ExitVariableWithoutInitialization ::= $empty
236 // // do nothing by default
237 // super.consumeExitVariableWithoutInitialization();
238 // if (isLocalDeclaration() || ((currentToken != TokenNameCOMMA) &&
239 // (currentToken != TokenNameSEMICOLON)))
241 // ((SourceFieldDeclaration) astStack[astPtr]).fieldEndPosition =
242 // scanner.currentPosition - 1;
246 // * INTERNAL USE-ONLY
248 //protected void consumeFieldAccess(boolean isSuperAccess) {
249 // // FieldAccess ::= Primary '.' 'Identifier'
250 // // FieldAccess ::= 'super' '.' 'Identifier'
251 // super.consumeFieldAccess(isSuperAccess);
252 // FieldReference fr = (FieldReference) expressionStack[expressionPtr];
253 // if (reportReferenceInfo) {
254 // requestor.acceptFieldReference(fr.token, fr.sourceStart);
257 //protected void consumeMethodHeaderName() {
258 // // MethodHeaderName ::= Modifiersopt Type 'Identifier' '('
259 // SourceMethodDeclaration md = new
260 // SourceMethodDeclaration(this.compilationUnit.compilationResult);
263 // md.selector = identifierStack[identifierPtr];
264 // long selectorSourcePositions = identifierPositionStack[identifierPtr--];
265 // identifierLengthPtr--;
267 // md.returnType = getTypeReference(intStack[intPtr--]);
269 // md.declarationSourceStart = intStack[intPtr--];
270 // md.modifiers = intStack[intPtr--];
272 // //highlight starts at selector start
273 // md.sourceStart = (int) (selectorSourcePositions >>> 32);
274 // md.selectorSourceEnd = (int) selectorSourcePositions;
275 // pushOnAstStack(md);
276 // md.sourceEnd = lParenPos;
277 // md.bodyStart = lParenPos+1;
278 // listLength = 0; // initialize listLength before reading parameters/throws
281 // if (currentElement != null){
282 // if (currentElement instanceof RecoveredType
283 // //|| md.modifiers != 0
284 // || (scanner.getLineNumber(md.returnType.sourceStart)
285 // == scanner.getLineNumber(md.sourceStart))){
286 // lastCheckPoint = md.bodyStart;
287 // currentElement = currentElement.add(md, 0);
288 // lastIgnoredToken = -1;
290 // lastCheckPoint = md.sourceStart;
291 // restartRecovery = true;
297 // * INTERNAL USE-ONLY
299 //protected void consumeMethodInvocationName() {
300 // // MethodInvocation ::= Name '(' ArgumentListopt ')'
302 // // when the name is only an identifier...we have a message send to "this"
304 // super.consumeMethodInvocationName();
305 // MessageSend messageSend = (MessageSend) expressionStack[expressionPtr];
306 // Expression[] args = messageSend.arguments;
307 // if (reportReferenceInfo) {
308 // requestor.acceptMethodReference(
309 // messageSend.selector,
310 // args == null ? 0 : args.length,
311 // (int)(messageSend.nameSourcePosition >>> 32));
316 // * INTERNAL USE-ONLY
318 //protected void consumeMethodInvocationPrimary() {
319 // super.consumeMethodInvocationPrimary();
320 // MessageSend messageSend = (MessageSend) expressionStack[expressionPtr];
321 // Expression[] args = messageSend.arguments;
322 // if (reportReferenceInfo) {
323 // requestor.acceptMethodReference(
324 // messageSend.selector,
325 // args == null ? 0 : args.length,
326 // (int)(messageSend.nameSourcePosition >>> 32));
331 // * INTERNAL USE-ONLY
333 //protected void consumeMethodInvocationSuper() {
334 // // MethodInvocation ::= 'super' '.' 'Identifier' '(' ArgumentListopt ')'
335 // super.consumeMethodInvocationSuper();
336 // MessageSend messageSend = (MessageSend) expressionStack[expressionPtr];
337 // Expression[] args = messageSend.arguments;
338 // if (reportReferenceInfo) {
339 // requestor.acceptMethodReference(
340 // messageSend.selector,
341 // args == null ? 0 : args.length,
342 // (int)(messageSend.nameSourcePosition >>> 32));
345 //protected void consumeSingleTypeImportDeclarationName() {
346 // // SingleTypeImportDeclarationName ::= 'import' Name
347 // /* push an ImportRef build from the last name
348 // stored in the identifier stack. */
350 // super.consumeSingleTypeImportDeclarationName();
351 // ImportReference impt = (ImportReference)astStack[astPtr];
352 // if (reportReferenceInfo) {
353 // requestor.acceptTypeReference(impt.tokens, impt.sourceStart,
357 //protected void consumeTypeImportOnDemandDeclarationName() {
358 // // TypeImportOnDemandDeclarationName ::= 'import' Name '.' '*'
359 // /* push an ImportRef build from the last name
360 // stored in the identifier stack. */
362 // super.consumeTypeImportOnDemandDeclarationName();
363 // ImportReference impt = (ImportReference)astStack[astPtr];
364 // if (reportReferenceInfo) {
365 // requestor.acceptUnknownReference(impt.tokens, impt.sourceStart,
369 //protected FieldDeclaration createFieldDeclaration(Expression
370 // initialization, char[] name, int sourceStart, int sourceEnd) {
371 // return new SourceFieldDeclaration(null, name, sourceStart, sourceEnd);
373 //protected CompilationUnitDeclaration endParse(int act) {
374 // if (sourceType != null) {
375 // if (sourceType.isInterface()) {
376 // consumeInterfaceDeclaration();
378 // consumeClassDeclaration();
381 // if (compilationUnit != null) {
382 // CompilationUnitDeclaration result = super.endParse(act);
389 * Flush annotations defined prior to a given positions.
391 * Note: annotations are stacked in syntactical order
393 * Either answer given <position>, or the end position of a comment line
394 * immediately following the <position> (same line)
396 * e.g. void foo(){ } // end of method foo
399 //public int flushAnnotationsDefinedPriorTo(int position) {
401 // return lastFieldEndPosition =
402 // super.flushAnnotationsDefinedPriorTo(position);
404 //public TypeReference getTypeReference(int dim) {
405 // /* build a Reference on a variable that may be qualified or not
406 // * This variable is a type reference and dim will be its dimensions
409 // if ((length = identifierLengthStack[identifierLengthPtr--]) == 1) {
410 // // single variable reference
412 // SingleTypeReference ref =
413 // new SingleTypeReference(
414 // identifierStack[identifierPtr],
415 // identifierPositionStack[identifierPtr--]);
416 // if (reportReferenceInfo) {
417 // requestor.acceptTypeReference(ref.token, ref.sourceStart);
421 // ArrayTypeReference ref =
422 // new ArrayTypeReference(
423 // identifierStack[identifierPtr],
425 // identifierPositionStack[identifierPtr--]);
426 // ref.sourceEnd = endPosition;
427 // if (reportReferenceInfo) {
428 // requestor.acceptTypeReference(ref.token, ref.sourceStart);
433 // if (length < 0) { //flag for precompiled type reference on base types
434 // TypeReference ref = TypeReference.baseTypeReference(-length, dim);
435 // ref.sourceStart = intStack[intPtr--];
437 // ref.sourceEnd = intStack[intPtr--];
439 // intPtr--; // no need to use this position as it is an array
440 // ref.sourceEnd = endPosition;
442 // if (reportReferenceInfo){
443 // requestor.acceptTypeReference(ref.getTypeName(), ref.sourceStart,
447 // } else { //Qualified variable reference
448 // char[][] tokens = new char[length][];
449 // identifierPtr -= length;
450 // long[] positions = new long[length];
451 // System.arraycopy(identifierStack, identifierPtr + 1, tokens, 0, length);
453 // identifierPositionStack,
454 // identifierPtr + 1,
459 // QualifiedTypeReference ref = new QualifiedTypeReference(tokens, positions);
460 // if (reportReferenceInfo) {
461 // requestor.acceptTypeReference(ref.tokens, ref.sourceStart, ref.sourceEnd);
465 // ArrayQualifiedTypeReference ref =
466 // new ArrayQualifiedTypeReference(tokens, dim, positions);
467 // ref.sourceEnd = endPosition;
468 // if (reportReferenceInfo) {
469 // requestor.acceptTypeReference(ref.tokens, ref.sourceStart, ref.sourceEnd);
476 //public NameReference getUnspecifiedReference() {
477 // /* build a (unspecified) NameReference which may be qualified*/
480 // if ((length = identifierLengthStack[identifierLengthPtr--]) == 1) {
481 // // single variable reference
482 // SingleNameReference ref =
483 // new SingleNameReference(
484 // identifierStack[identifierPtr],
485 // identifierPositionStack[identifierPtr--]);
486 // if (reportReferenceInfo) {
487 // this.addUnknownRef(ref);
491 // //Qualified variable reference
492 // char[][] tokens = new char[length][];
493 // identifierPtr -= length;
494 // System.arraycopy(identifierStack, identifierPtr + 1, tokens, 0, length);
495 // QualifiedNameReference ref =
496 // new QualifiedNameReference(
498 // (int) (identifierPositionStack[identifierPtr + 1] >> 32), // sourceStart
499 // (int) identifierPositionStack[identifierPtr + length]); // sourceEnd
500 // if (reportReferenceInfo) {
501 // this.addUnknownRef(ref);
506 //public NameReference getUnspecifiedReferenceOptimized() {
507 // /* build a (unspecified) NameReference which may be qualified
508 // The optimization occurs for qualified reference while we are
509 // certain in this case the last item of the qualified name is
510 // a field access. This optimization is IMPORTANT while it results
511 // that when a NameReference is build, the type checker should always
512 // look for that it is not a type reference */
515 // if ((length = identifierLengthStack[identifierLengthPtr--]) == 1) {
516 // // single variable reference
517 // SingleNameReference ref =
518 // new SingleNameReference(
519 // identifierStack[identifierPtr],
520 // identifierPositionStack[identifierPtr--]);
521 // ref.bits &= ~ASTNode.RestrictiveFlagMASK;
522 // ref.bits |= LOCAL | FIELD;
523 // if (reportReferenceInfo) {
524 // this.addUnknownRef(ref);
529 // //Qualified-variable-reference
530 // //In fact it is variable-reference DOT field-ref , but it would result in a
532 // //conflict tha can be only reduce by making a superclass (or inetrface )
534 // //nameReference and FiledReference or putting FieldReference under
536 // //or else..........This optimisation is not really relevant so just leave
539 // char[][] tokens = new char[length][];
540 // identifierPtr -= length;
541 // System.arraycopy(identifierStack, identifierPtr + 1, tokens, 0, length);
542 // QualifiedNameReference ref =
543 // new QualifiedNameReference(
545 // (int) (identifierPositionStack[identifierPtr + 1] >> 32),
547 // (int) identifierPositionStack[identifierPtr + length]); // sourceEnd
548 // ref.bits &= ~ASTNode.RestrictiveFlagMASK;
549 // ref.bits |= LOCAL | FIELD;
550 // if (reportReferenceInfo) {
551 // this.addUnknownRef(ref);
557 // * INTERNAL USE-ONLY
559 //private boolean isLocalDeclaration() {
560 // int nestedDepth = nestedType;
561 // while (nestedDepth >= 0) {
562 // if (nestedMethod[nestedDepth] != 0) {
570 * Update the bodyStart of the corresponding parse node
572 public void notifySourceElementRequestor(CompilationUnitDeclaration parsedUnit) {
573 if (parsedUnit == null) {
574 // when we parse a single type member declaration the compilation unit is
575 // null, but we still
576 // want to be able to notify the requestor on the created ast node
577 if (astStack[0] instanceof AbstractMethodDeclaration) {
578 notifySourceElementRequestor((AbstractMethodDeclaration) astStack[0]);
584 boolean isInRange = scanner.initialPosition <= parsedUnit.sourceStart && scanner.eofPosition >= parsedUnit.sourceEnd;
586 // if (reportReferenceInfo) {
587 // notifyAllUnknownReferences();
589 // collect the top level ast nodes
591 ASTNode[] nodes = null;
592 if (sourceType == null) {
594 requestor.enterCompilationUnit();
596 // ImportReference currentPackage = parsedUnit.currentPackage;
597 ImportReference[] imports = parsedUnit.imports;
598 // TypeDeclaration[] types = parsedUnit.types;
599 ArrayList types = parsedUnit.types;
602 // (currentPackage == null ? 0 : 1)
603 // + (imports == null ? 0 : imports.length)
604 // + (types == null ? 0 : types.length);
605 // nodes = new ASTNode[length];
606 length = (imports == null ? 0 : imports.length) + types.size();
607 nodes = new ASTNode[length];
609 // if (currentPackage != null) {
610 // nodes[index++] = currentPackage;
612 if (imports != null) {
613 for (int i = 0, max = imports.length; i < max; i++) {
614 nodes[index++] = imports[i];
618 for (int i = 0, max = types.size(); i < max; i++) {
619 nodes[index++] = (ASTNode) types.get(i);
623 // TypeDeclaration[] types = parsedUnit.types;
624 ArrayList types = parsedUnit.types;
626 length = types.size();
627 nodes = new ASTNode[length];
628 for (int i = 0, max = types.size(); i < max; i++) {
629 nodes[i] = (ASTNode) types.get(i);
634 // notify the nodes in the syntactical order
635 if (nodes != null && length > 0) {
636 quickSort(nodes, 0, length - 1);
637 for (int i = 0; i < length; i++) {
638 ASTNode node = nodes[i];
639 if (node instanceof ImportReference) {
640 ImportReference importRef = (ImportReference)node;
641 // if (node == parsedUnit.currentPackage) {
642 // notifySourceElementRequestor(importRef, true);
644 notifySourceElementRequestor(importRef, false);
646 } //else { instanceof TypeDeclaration
647 if (node instanceof TypeDeclaration) {
648 notifySourceElementRequestor((TypeDeclaration) node, sourceType == null);
649 // notifySourceElementRequestor((CompilationUnitDeclaration)node,
650 // sourceType == null);
652 // jsurfer - INSERT start
653 if (node instanceof AbstractMethodDeclaration) {
654 notifySourceElementRequestor((AbstractMethodDeclaration) node);
656 // jsurfer - INSERT end
660 if (sourceType == null) {
662 requestor.exitCompilationUnit(parsedUnit.sourceEnd);
667 //private void notifyAllUnknownReferences() {
668 // for (int i = 0, max = this.unknownRefsCounter; i < max; i++) {
669 // NameReference nameRef = this.unknownRefs[i];
670 // if ((nameRef.bits & BindingIds.VARIABLE) != 0) {
671 // if ((nameRef.bits & BindingIds.TYPE) == 0) {
672 // // variable but not type
673 // if (nameRef instanceof SingleNameReference) {
674 // // local var or field
675 // requestor.acceptUnknownReference(((SingleNameReference) nameRef).token,
676 // nameRef.sourceStart);
678 // // QualifiedNameReference
679 // // The last token is a field reference and the previous tokens are a
680 // type/variable references
681 // char[][] tokens = ((QualifiedNameReference) nameRef).tokens;
682 // int tokensLength = tokens.length;
683 // requestor.acceptFieldReference(tokens[tokensLength - 1], nameRef.sourceEnd
684 // - tokens[tokensLength - 1].length + 1);
685 // char[][] typeRef = new char[tokensLength - 1][];
686 // System.arraycopy(tokens, 0, typeRef, 0, tokensLength - 1);
687 // requestor.acceptUnknownReference(typeRef, nameRef.sourceStart,
688 // nameRef.sourceEnd - tokens[tokensLength - 1].length);
691 // // variable or type
692 // if (nameRef instanceof SingleNameReference) {
693 // requestor.acceptUnknownReference(((SingleNameReference) nameRef).token,
694 // nameRef.sourceStart);
696 // //QualifiedNameReference
697 // requestor.acceptUnknownReference(((QualifiedNameReference) nameRef).tokens,
698 // nameRef.sourceStart, nameRef.sourceEnd);
701 // } else if ((nameRef.bits & BindingIds.TYPE) != 0) {
702 // if (nameRef instanceof SingleNameReference) {
703 // requestor.acceptTypeReference(((SingleNameReference) nameRef).token,
704 // nameRef.sourceStart);
706 // // it is a QualifiedNameReference
707 // requestor.acceptTypeReference(((QualifiedNameReference) nameRef).tokens,
708 // nameRef.sourceStart, nameRef.sourceEnd);
714 * Update the bodyStart of the corresponding parse node
716 public void notifySourceElementRequestor(AbstractMethodDeclaration methodDeclaration) {
719 boolean isInRange = scanner.initialPosition <= methodDeclaration.declarationSourceStart
720 && scanner.eofPosition >= methodDeclaration.declarationSourceEnd;
722 if (methodDeclaration.isClinit()) {
723 this.visitIfNeeded(methodDeclaration);
727 if (methodDeclaration.isDefaultConstructor()) {
728 if (reportReferenceInfo) {
729 ConstructorDeclaration constructorDeclaration = (ConstructorDeclaration) methodDeclaration;
730 ExplicitConstructorCall constructorCall = constructorDeclaration.constructorCall;
731 if (constructorCall != null) {
732 switch (constructorCall.accessMode) {
733 case ExplicitConstructorCall.This :
734 requestor.acceptConstructorReference(typeNames[nestedTypeIndex - 1], constructorCall.arguments == null
736 : constructorCall.arguments.length, constructorCall.sourceStart);
738 case ExplicitConstructorCall.Super :
739 case ExplicitConstructorCall.ImplicitSuper :
740 requestor.acceptConstructorReference(superTypeNames[nestedTypeIndex - 1], constructorCall.arguments == null
742 : constructorCall.arguments.length, constructorCall.sourceStart);
749 char[][] argumentTypes = null;
750 char[][] argumentNames = null;
751 Argument[] arguments = methodDeclaration.arguments;
752 if (arguments != null) {
753 int argumentLength = arguments.length;
754 argumentTypes = new char[argumentLength][];
755 argumentNames = new char[argumentLength][];
756 for (int i = 0; i < argumentLength; i++) {
757 argumentTypes[i] = returnTypeName(arguments[i].type);
758 argumentNames[i] = arguments[i].name;
761 char[][] thrownExceptionTypes = null;
762 TypeReference[] thrownExceptions = methodDeclaration.thrownExceptions;
763 if (thrownExceptions != null) {
764 int thrownExceptionLength = thrownExceptions.length;
765 thrownExceptionTypes = new char[thrownExceptionLength][];
766 for (int i = 0; i < thrownExceptionLength; i++) {
767 thrownExceptionTypes[i] = CharOperation.concatWith(thrownExceptions[i].getTypeName(), '.');
770 // by default no selector end position
771 int selectorSourceEnd = -1;
772 if (methodDeclaration.isConstructor()) {
773 // if (methodDeclaration instanceof SourceConstructorDeclaration) {
774 // selectorSourceEnd =
775 // ((SourceConstructorDeclaration) methodDeclaration).selectorSourceEnd;
778 requestor.enterConstructor(methodDeclaration.declarationSourceStart, methodDeclaration.modifiers,
779 methodDeclaration.selector, methodDeclaration.sourceStart, selectorSourceEnd, argumentTypes, argumentNames,
780 thrownExceptionTypes);
782 if (reportReferenceInfo) {
783 ConstructorDeclaration constructorDeclaration = (ConstructorDeclaration) methodDeclaration;
784 ExplicitConstructorCall constructorCall = constructorDeclaration.constructorCall;
785 if (constructorCall != null) {
786 switch (constructorCall.accessMode) {
787 case ExplicitConstructorCall.This :
788 requestor.acceptConstructorReference(typeNames[nestedTypeIndex - 1], constructorCall.arguments == null
790 : constructorCall.arguments.length, constructorCall.sourceStart);
792 case ExplicitConstructorCall.Super :
793 case ExplicitConstructorCall.ImplicitSuper :
794 requestor.acceptConstructorReference(superTypeNames[nestedTypeIndex - 1], constructorCall.arguments == null
796 : constructorCall.arguments.length, constructorCall.sourceStart);
801 this.visitIfNeeded(methodDeclaration);
803 requestor.exitConstructor(methodDeclaration.declarationSourceEnd);
807 // if (methodDeclaration instanceof SourceMethodDeclaration) {
808 // selectorSourceEnd =
809 // ((SourceMethodDeclaration) methodDeclaration).selectorSourceEnd;
812 int modifiers = methodDeclaration.modifiers;
813 // boolean deprecated = (modifiers & AccDeprecated) != 0; // remember
814 // deprecation so as to not lose it below
815 requestor.enterMethod(methodDeclaration.declarationSourceStart, modifiers, // deprecated
826 returnTypeName(((MethodDeclaration) methodDeclaration).returnType), methodDeclaration.selector,
827 methodDeclaration.sourceStart, selectorSourceEnd, argumentTypes, argumentNames, thrownExceptionTypes);
829 this.visitIfNeeded(methodDeclaration);
832 requestor.exitMethod(methodDeclaration.declarationSourceEnd);
836 * Update the bodyStart of the corresponding parse node
838 public void notifySourceElementRequestor(FieldDeclaration fieldDeclaration) {
841 boolean isInRange = scanner.initialPosition <= fieldDeclaration.declarationSourceStart
842 && scanner.eofPosition >= fieldDeclaration.declarationSourceEnd;
844 if (fieldDeclaration.isField()) {
845 int fieldEndPosition = fieldDeclaration.declarationSourceEnd;
846 // if (fieldDeclaration instanceof SourceFieldDeclaration) {
847 // fieldEndPosition = ((SourceFieldDeclaration)
848 // fieldDeclaration).fieldEndPosition;
849 // if (fieldEndPosition == 0) {
850 // // use the declaration source end by default
851 // fieldEndPosition = fieldDeclaration.declarationSourceEnd;
855 int modifiers = fieldDeclaration.modifiers;
856 boolean deprecated = (modifiers & AccDeprecated) != 0; // remember
860 requestor.enterField(fieldDeclaration.declarationSourceStart, deprecated
861 ? (modifiers & AccJustFlag) | AccDeprecated
862 : modifiers & AccJustFlag, returnTypeName(fieldDeclaration.type), fieldDeclaration.name, fieldDeclaration.sourceStart,
863 fieldDeclaration.sourceEnd);
865 // this.visitIfNeeded(fieldDeclaration);
867 // requestor.exitField(
868 // // filter out initializations that are not a constant (simple check)
869 // (fieldDeclaration.initialization == null
870 // || fieldDeclaration.initialization instanceof ArrayInitializer
871 // || fieldDeclaration.initialization instanceof AllocationExpression
872 // || fieldDeclaration.initialization instanceof
873 // ArrayAllocationExpression
874 // || fieldDeclaration.initialization instanceof Assignment
875 // || fieldDeclaration.initialization instanceof ClassLiteralAccess
876 // || fieldDeclaration.initialization instanceof MessageSend
877 // || fieldDeclaration.initialization instanceof ArrayReference
878 // || fieldDeclaration.initialization instanceof ThisReference) ?
880 // fieldDeclaration.initialization.sourceStart,
882 // fieldDeclaration.declarationSourceEnd);
884 // filter out initializations that are not a constant (simple check)
885 -1, fieldEndPosition, fieldDeclaration.declarationSourceEnd);
890 // requestor.enterInitializer(
891 // fieldDeclaration.declarationSourceStart,
892 // fieldDeclaration.modifiers);
894 // this.visitIfNeeded((Initializer)fieldDeclaration);
896 // requestor.exitInitializer(fieldDeclaration.declarationSourceEnd);
900 public void notifySourceElementRequestor(
901 ImportReference importReference,
904 // requestor.acceptPackage(
905 // importReference.declarationSourceStart,
906 // importReference.declarationSourceEnd,
907 // CharOperation.concatWith(importReference.getImportName(), '.'));
909 requestor.acceptImport(
910 importReference.declarationSourceStart,
911 importReference.declarationSourceEnd,
912 importReference.getIncludeName(), //CharOperation.concatWith(importReference.getImportName(), '.'),
913 importReference.onDemand);
916 public void notifySourceElementRequestor(TypeDeclaration typeDeclaration, boolean notifyTypePresence) {
917 //// public void notifySourceElementRequestor(ASTNode typeDeclaration,
918 // boolean notifyTypePresence) {
921 boolean isInRange = scanner.initialPosition <= typeDeclaration.declarationSourceStart
922 && scanner.eofPosition >= typeDeclaration.declarationSourceEnd;
924 FieldDeclaration[] fields = typeDeclaration.fields;
925 AbstractMethodDeclaration[] methods = typeDeclaration.methods;
926 MemberTypeDeclaration[] memberTypes = typeDeclaration.memberTypes;
927 int fieldCount = fields == null ? 0 : fields.length;
928 int methodCount = methods == null ? 0 : methods.length;
929 int memberTypeCount = memberTypes == null ? 0 : memberTypes.length;
932 int memberTypeIndex = 0;
933 boolean isInterface = typeDeclaration.isInterface();
935 if (notifyTypePresence) {
936 char[][] interfaceNames = null;
937 int superInterfacesLength = 0;
938 TypeReference[] superInterfaces = typeDeclaration.superInterfaces;
939 if (superInterfaces != null) {
940 superInterfacesLength = superInterfaces.length;
941 interfaceNames = new char[superInterfacesLength][];
943 if (typeDeclaration instanceof AnonymousLocalTypeDeclaration) {
945 QualifiedAllocationExpression alloc = ((AnonymousLocalTypeDeclaration) typeDeclaration).allocation;
946 if (alloc != null && alloc.type != null) {
947 superInterfaces = new TypeReference[]{((AnonymousLocalTypeDeclaration) typeDeclaration).allocation.type};
948 superInterfacesLength = 1;
949 interfaceNames = new char[1][];
953 if (superInterfaces != null) {
954 for (int i = 0; i < superInterfacesLength; i++) {
955 interfaceNames[i] = CharOperation.concatWith(superInterfaces[i].getTypeName(), '.');
960 int modifiers = typeDeclaration.modifiers;
961 boolean deprecated = false; //(modifiers & AccDeprecated) != 0; //
962 // remember deprecation so as to not lose
964 requestor.enterInterface(typeDeclaration.declarationSourceStart, modifiers, //deprecated
975 typeDeclaration.name, typeDeclaration.sourceStart, typeDeclaration.sourceEnd, interfaceNames);
977 if (nestedTypeIndex == typeNames.length) {
979 System.arraycopy(typeNames, 0, (typeNames = new char[nestedTypeIndex * 2][]), 0, nestedTypeIndex);
980 System.arraycopy(superTypeNames, 0, (superTypeNames = new char[nestedTypeIndex * 2][]), 0, nestedTypeIndex);
982 typeNames[nestedTypeIndex] = typeDeclaration.name;
983 superTypeNames[nestedTypeIndex++] = JAVA_LANG_OBJECT;
985 TypeReference superclass = typeDeclaration.superclass;
986 if (superclass == null) {
988 requestor.enterClass(typeDeclaration.declarationSourceStart, typeDeclaration.modifiers, typeDeclaration.name,
989 typeDeclaration.sourceStart, typeDeclaration.sourceEnd, null, interfaceNames);
993 requestor.enterClass(typeDeclaration.declarationSourceStart, typeDeclaration.modifiers, typeDeclaration.name,
994 typeDeclaration.sourceStart, typeDeclaration.sourceEnd, CharOperation.concatWith(superclass.getTypeName(), '.'),
998 if (nestedTypeIndex == typeNames.length) {
1000 System.arraycopy(typeNames, 0, (typeNames = new char[nestedTypeIndex * 2][]), 0, nestedTypeIndex);
1001 System.arraycopy(superTypeNames, 0, (superTypeNames = new char[nestedTypeIndex * 2][]), 0, nestedTypeIndex);
1003 typeNames[nestedTypeIndex] = typeDeclaration.name;
1004 superTypeNames[nestedTypeIndex++] = superclass == null ? JAVA_LANG_OBJECT : CharOperation.concatWith(superclass
1005 .getTypeName(), '.');
1008 while ((fieldIndex < fieldCount) || (memberTypeIndex < memberTypeCount) || (methodIndex < methodCount)) {
1009 FieldDeclaration nextFieldDeclaration = null;
1010 AbstractMethodDeclaration nextMethodDeclaration = null;
1011 TypeDeclaration nextMemberDeclaration = null;
1013 int position = Integer.MAX_VALUE;
1014 int nextDeclarationType = -1;
1015 if (fieldIndex < fieldCount) {
1016 nextFieldDeclaration = fields[fieldIndex];
1017 if (nextFieldDeclaration.declarationSourceStart < position) {
1018 position = nextFieldDeclaration.declarationSourceStart;
1019 nextDeclarationType = 0; // FIELD
1022 if (methodIndex < methodCount) {
1023 nextMethodDeclaration = methods[methodIndex];
1024 if (nextMethodDeclaration.declarationSourceStart < position) {
1025 position = nextMethodDeclaration.declarationSourceStart;
1026 nextDeclarationType = 1; // METHOD
1029 if (memberTypeIndex < memberTypeCount) {
1030 nextMemberDeclaration = memberTypes[memberTypeIndex];
1031 if (nextMemberDeclaration.declarationSourceStart < position) {
1032 position = nextMemberDeclaration.declarationSourceStart;
1033 nextDeclarationType = 2; // MEMBER
1036 switch (nextDeclarationType) {
1039 notifySourceElementRequestor(nextFieldDeclaration);
1043 notifySourceElementRequestor(nextMethodDeclaration);
1047 notifySourceElementRequestor(nextMemberDeclaration, true);
1050 if (notifyTypePresence) {
1053 requestor.exitInterface(typeDeclaration.declarationSourceEnd);
1055 requestor.exitClass(typeDeclaration.declarationSourceEnd);
1061 public void parseCompilationUnit(ICompilationUnit unit, int start, int end) {
1062 // boolean needReferenceInfo) {
1064 // reportReferenceInfo = needReferenceInfo;
1065 // boolean old = diet;
1066 // if (needReferenceInfo) {
1067 // unknownRefs = new NameReference[10];
1068 // unknownRefsCounter = 0;
1073 CompilationResult compilationUnitResult = new CompilationResult(unit, 0, 0, 10); //this.options.maxProblemsPerUnit);
1074 CompilationUnitDeclaration parsedUnit = parse(unit, compilationUnitResult, start, end);
1075 // if (scanner.recordLineSeparator) {
1076 // requestor.acceptLineSeparatorPositions(scanner.getLineEnds());
1078 // if (this.localDeclarationVisitor != null || needReferenceInfo){
1080 // this.getMethodBodies(parsedUnit);
1082 // this.scanner.resetTo(start, end);
1083 // notifySourceElementRequestor(parsedUnit);
1084 } catch (AbortCompilation e) {
1089 public CompilationUnitDeclaration parseCompilationUnit(ICompilationUnit unit, boolean fullParse) {
1091 // boolean old = diet;
1093 // unknownRefs = new NameReference[10];
1094 // unknownRefsCounter = 0;
1099 this.reportReferenceInfo = fullParse;
1100 CompilationResult compilationUnitResult = new CompilationResult(unit, 0, 0, this.options.maxProblemsPerUnit);
1101 CompilationUnitDeclaration parsedUnit = parse(unit, compilationUnitResult, false);
1102 if (scanner.recordLineSeparator) {
1103 requestor.acceptLineSeparatorPositions(scanner.getLineEnds());
1105 int initialStart = this.scanner.initialPosition;
1106 int initialEnd = this.scanner.eofPosition;
1107 // if (this.localDeclarationVisitor != null || fullParse){
1109 // this.getMethodBodies(parsedUnit);
1111 this.scanner.resetTo(initialStart, initialEnd);
1112 notifySourceElementRequestor(parsedUnit);
1114 } catch (AbortCompilation e) {
1115 // ignore this exception
1122 public CompilationUnitDeclaration parseCompletionUnit(ICompilationUnit unit, boolean fullParse) {
1124 // boolean old = diet;
1126 // unknownRefs = new NameReference[10];
1127 // unknownRefsCounter = 0;
1132 this.reportReferenceInfo = fullParse;
1133 CompilationResult compilationUnitResult = new CompilationResult(unit, 0, 0, this.options.maxProblemsPerUnit);
1134 CompilationUnitDeclaration parsedUnit = parse(unit, compilationUnitResult, false);
1135 // if (scanner.recordLineSeparator) {
1136 // requestor.acceptLineSeparatorPositions(scanner.getLineEnds());
1138 // int initialStart = this.scanner.initialPosition;
1139 // int initialEnd = this.scanner.eofPosition;
1140 // // if (this.localDeclarationVisitor != null || fullParse){
1142 // // this.getMethodBodies(parsedUnit);
1144 // this.scanner.resetTo(initialStart, initialEnd);
1145 // notifySourceElementRequestor(parsedUnit);
1147 } catch (AbortCompilation e) {
1148 // ignore this exception
1154 //public void parseTypeMemberDeclarations(
1155 // ISourceType sourceType,
1156 // ICompilationUnit sourceUnit,
1159 // boolean needReferenceInfo) {
1160 // boolean old = diet;
1161 // if (needReferenceInfo) {
1162 // unknownRefs = new NameReference[10];
1163 // unknownRefsCounter = 0;
1167 // diet = !needReferenceInfo;
1168 // reportReferenceInfo = needReferenceInfo;
1169 // CompilationResult compilationUnitResult =
1170 // new CompilationResult(sourceUnit, 0, 0, this.options.maxProblemsPerUnit);
1171 // CompilationUnitDeclaration unit =
1172 // SourceTypeConverter.buildCompilationUnit(
1173 // new ISourceType[]{sourceType},
1174 // false, // no need for field and methods
1175 // false, // no need for member types
1176 // false, // no need for field initialization
1177 // problemReporter(),
1178 // compilationUnitResult);
1179 // if ((unit == null) || (unit.types == null) || (unit.types.length != 1))
1181 // this.sourceType = sourceType;
1183 // /* automaton initialization */
1185 // goForClassBodyDeclarations();
1186 // /* scanner initialization */
1187 // scanner.setSource(sourceUnit.getContents());
1188 // scanner.resetTo(start, end);
1189 // /* unit creation */
1190 // referenceContext = compilationUnit = unit;
1191 // /* initialize the astStacl */
1192 // // the compilationUnitDeclaration should contain exactly one type
1193 // pushOnAstStack(unit.types[0]);
1194 // /* run automaton */
1196 // notifySourceElementRequestor(unit);
1198 // unit = compilationUnit;
1199 // compilationUnit = null; // reset parser
1201 // } catch (AbortCompilation e) {
1203 // if (scanner.recordLineSeparator) {
1204 // requestor.acceptLineSeparatorPositions(scanner.getLineEnds());
1210 //public void parseTypeMemberDeclarations(
1215 // boolean old = diet;
1220 // /* automaton initialization */
1222 // goForClassBodyDeclarations();
1223 // /* scanner initialization */
1224 // scanner.setSource(contents);
1225 // scanner.recordLineSeparator = false;
1226 // scanner.taskTags = null;
1227 // scanner.taskPriorities = null;
1228 // scanner.resetTo(start, end);
1230 // /* unit creation */
1231 // referenceContext = null;
1233 // /* initialize the astStacl */
1234 // // the compilationUnitDeclaration should contain exactly one type
1235 // /* run automaton */
1237 // notifySourceElementRequestor((CompilationUnitDeclaration)null);
1238 // } catch (AbortCompilation e) {
1244 * Sort the given ast nodes by their positions.
1246 private static void quickSort(ASTNode[] sortedCollection, int left, int right) {
1247 int original_left = left;
1248 int original_right = right;
1249 ASTNode mid = sortedCollection[(left + right) / 2];
1251 while (sortedCollection[left].sourceStart < mid.sourceStart) {
1254 while (mid.sourceStart < sortedCollection[right].sourceStart) {
1257 if (left <= right) {
1258 ASTNode tmp = sortedCollection[left];
1259 sortedCollection[left] = sortedCollection[right];
1260 sortedCollection[right] = tmp;
1264 } while (left <= right);
1265 if (original_left < right) {
1266 quickSort(sortedCollection, original_left, right);
1268 if (left < original_right) {
1269 quickSort(sortedCollection, left, original_right);
1273 * Answer a char array representation of the type name formatted like: - type
1274 * name + dimensions Example: "A[][]".toCharArray()
1275 * "java.lang.String".toCharArray()
1277 private char[] returnTypeName(TypeReference type) {
1280 int dimension = type.dimensions();
1281 if (dimension != 0) {
1282 char[] dimensionsArray = new char[dimension * 2];
1283 for (int i = 0; i < dimension; i++) {
1284 dimensionsArray[i * 2] = '[';
1285 dimensionsArray[(i * 2) + 1] = ']';
1287 return CharOperation.concat(CharOperation.concatWith(type.getTypeName(), '.'), dimensionsArray);
1289 return CharOperation.concatWith(type.getTypeName(), '.');
1292 public void addUnknownRef(NameReference nameRef) {
1293 if (this.unknownRefs.length == this.unknownRefsCounter) {
1295 System.arraycopy(this.unknownRefs, 0, (this.unknownRefs = new NameReference[this.unknownRefsCounter * 2]), 0,
1296 this.unknownRefsCounter);
1298 this.unknownRefs[this.unknownRefsCounter++] = nameRef;
1301 private void visitIfNeeded(AbstractMethodDeclaration method) {
1302 if (this.localDeclarationVisitor != null && (method.bits & ASTNode.HasLocalTypeMASK) != 0) {
1303 if (method.statements != null) {
1304 int statementsLength = method.statements.length;
1305 for (int i = 0; i < statementsLength; i++)
1306 method.statements[i].traverse(this.localDeclarationVisitor, method.scope);
1311 //private void visitIfNeeded(FieldDeclaration field) {
1312 // if (this.localDeclarationVisitor != null
1313 // && (field.bits & ASTNode.HasLocalTypeMASK) != 0) {
1314 // if (field.initialization != null) {
1315 // field.initialization.traverse(this.localDeclarationVisitor, null);
1320 //private void visitIfNeeded(Initializer initializer) {
1321 // if (this.localDeclarationVisitor != null
1322 // && (initializer.bits & ASTNode.HasLocalTypeMASK) != 0) {
1323 // if (initializer.block != null) {
1324 // initializer.block.traverse(this.localDeclarationVisitor, null);
1329 //protected void reportSyntaxError(int act, int currentKind, int
1331 // if (compilationUnit == null) return;
1332 // super.reportSyntaxError(act, currentKind,stateStackTop);
1334 protected CompilationUnitDeclaration endParse(int act) {
1335 // if (sourceType != null) {
1336 // if (sourceType.isInterface()) {
1337 // consumeInterfaceDeclaration();
1339 // consumeClassDeclaration();
1342 if (compilationUnit != null) {
1343 CompilationUnitDeclaration result = super.endParse(act);