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 requestor.acceptProblem(problem);
115 // options.sourceLevel >= CompilerOptions.JDK1_4);
116 this.requestor = requestor;
117 typeNames = new char[4][];
118 superTypeNames = new char[4][];
120 this.options = options;
124 * @deprecated use SourceElementParser(ISourceElementRequestor,
125 * IProblemFactory, CompilerOptions)
127 //public SourceElementParser(
128 // final ISourceElementRequestor requestor,
129 // IProblemFactory problemFactory) {
130 // this(requestor, problemFactory, new CompilerOptions());
132 //public SourceElementParser(
133 // final ISourceElementRequestor requestor,
134 // IProblemFactory problemFactory,
135 // CompilerOptions options,
136 // boolean reportLocalDeclarations) {
137 // this(requestor, problemFactory, options);
138 // if (reportLocalDeclarations) {
139 // this.localDeclarationVisitor = new LocalDeclarationVisitor();
142 //public void checkAnnotation() {
143 // int firstCommentIndex = scanner.commentPtr;
145 // super.checkAnnotation();
147 // // modify the modifier source start to point at the first comment
148 // if (firstCommentIndex >= 0) {
149 // modifiersSourceStart = scanner.commentStarts[0];
152 //protected void classInstanceCreation(boolean alwaysQualified) {
154 // boolean previousFlag = reportReferenceInfo;
155 // reportReferenceInfo = false; // not to see the type reference reported in
156 // super call to getTypeReference(...)
157 // super.classInstanceCreation(alwaysQualified);
158 // reportReferenceInfo = previousFlag;
159 // if (reportReferenceInfo){
160 // AllocationExpression alloc =
161 // (AllocationExpression)expressionStack[expressionPtr];
162 // TypeReference typeRef = alloc.type;
163 // requestor.acceptConstructorReference(
164 // typeRef instanceof SingleTypeReference
165 // ? ((SingleTypeReference) typeRef).token
166 // : CharOperation.concatWith(alloc.type.getTypeName(), '.'),
167 // alloc.arguments == null ? 0 : alloc.arguments.length,
168 // alloc.sourceStart);
171 //protected void consumeConstructorHeaderName() {
172 // // ConstructorHeaderName ::= Modifiersopt 'Identifier' '('
174 // /* recovering - might be an empty message send */
175 // if (currentElement != null){
176 // if (lastIgnoredToken == TokenNamenew){ // was an allocation expression
177 // lastCheckPoint = scanner.startPosition; // force to restart at this exact
179 // restartRecovery = true;
183 // SourceConstructorDeclaration cd = new
184 // SourceConstructorDeclaration(this.compilationUnit.compilationResult);
186 // //name -- this is not really revelant but we do .....
187 // cd.selector = identifierStack[identifierPtr];
188 // long selectorSourcePositions = identifierPositionStack[identifierPtr--];
189 // identifierLengthPtr--;
192 // cd.declarationSourceStart = intStack[intPtr--];
193 // cd.modifiers = intStack[intPtr--];
195 // //highlight starts at the selector starts
196 // cd.sourceStart = (int) (selectorSourcePositions >>> 32);
197 // cd.selectorSourceEnd = (int) selectorSourcePositions;
198 // pushOnAstStack(cd);
200 // cd.sourceEnd = lParenPos;
201 // cd.bodyStart = lParenPos+1;
202 // listLength = 0; // initialize listLength before reading parameters/throws
205 // if (currentElement != null){
206 // lastCheckPoint = cd.bodyStart;
207 // if ((currentElement instanceof RecoveredType && lastIgnoredToken !=
209 // || cd.modifiers != 0){
210 // currentElement = currentElement.add(cd, 0);
211 // lastIgnoredToken = -1;
217 // * INTERNAL USE-ONLY
219 //protected void consumeExitVariableWithInitialization() {
220 // // ExitVariableWithInitialization ::= $empty
221 // // the scanner is located after the comma or the semi-colon.
222 // // we want to include the comma or the semi-colon
223 // super.consumeExitVariableWithInitialization();
224 // if (isLocalDeclaration() || ((currentToken != TokenNameCOMMA) &&
225 // (currentToken != TokenNameSEMICOLON)))
227 // ((SourceFieldDeclaration) astStack[astPtr]).fieldEndPosition =
228 // scanner.currentPosition - 1;
230 //protected void consumeExitVariableWithoutInitialization() {
231 // // ExitVariableWithoutInitialization ::= $empty
232 // // do nothing by default
233 // super.consumeExitVariableWithoutInitialization();
234 // if (isLocalDeclaration() || ((currentToken != TokenNameCOMMA) &&
235 // (currentToken != TokenNameSEMICOLON)))
237 // ((SourceFieldDeclaration) astStack[astPtr]).fieldEndPosition =
238 // scanner.currentPosition - 1;
242 // * INTERNAL USE-ONLY
244 //protected void consumeFieldAccess(boolean isSuperAccess) {
245 // // FieldAccess ::= Primary '.' 'Identifier'
246 // // FieldAccess ::= 'super' '.' 'Identifier'
247 // super.consumeFieldAccess(isSuperAccess);
248 // FieldReference fr = (FieldReference) expressionStack[expressionPtr];
249 // if (reportReferenceInfo) {
250 // requestor.acceptFieldReference(fr.token, fr.sourceStart);
253 //protected void consumeMethodHeaderName() {
254 // // MethodHeaderName ::= Modifiersopt Type 'Identifier' '('
255 // SourceMethodDeclaration md = new
256 // SourceMethodDeclaration(this.compilationUnit.compilationResult);
259 // md.selector = identifierStack[identifierPtr];
260 // long selectorSourcePositions = identifierPositionStack[identifierPtr--];
261 // identifierLengthPtr--;
263 // md.returnType = getTypeReference(intStack[intPtr--]);
265 // md.declarationSourceStart = intStack[intPtr--];
266 // md.modifiers = intStack[intPtr--];
268 // //highlight starts at selector start
269 // md.sourceStart = (int) (selectorSourcePositions >>> 32);
270 // md.selectorSourceEnd = (int) selectorSourcePositions;
271 // pushOnAstStack(md);
272 // md.sourceEnd = lParenPos;
273 // md.bodyStart = lParenPos+1;
274 // listLength = 0; // initialize listLength before reading parameters/throws
277 // if (currentElement != null){
278 // if (currentElement instanceof RecoveredType
279 // //|| md.modifiers != 0
280 // || (scanner.getLineNumber(md.returnType.sourceStart)
281 // == scanner.getLineNumber(md.sourceStart))){
282 // lastCheckPoint = md.bodyStart;
283 // currentElement = currentElement.add(md, 0);
284 // lastIgnoredToken = -1;
286 // lastCheckPoint = md.sourceStart;
287 // restartRecovery = true;
293 // * INTERNAL USE-ONLY
295 //protected void consumeMethodInvocationName() {
296 // // MethodInvocation ::= Name '(' ArgumentListopt ')'
298 // // when the name is only an identifier...we have a message send to "this"
300 // super.consumeMethodInvocationName();
301 // MessageSend messageSend = (MessageSend) expressionStack[expressionPtr];
302 // Expression[] args = messageSend.arguments;
303 // if (reportReferenceInfo) {
304 // requestor.acceptMethodReference(
305 // messageSend.selector,
306 // args == null ? 0 : args.length,
307 // (int)(messageSend.nameSourcePosition >>> 32));
312 // * INTERNAL USE-ONLY
314 //protected void consumeMethodInvocationPrimary() {
315 // super.consumeMethodInvocationPrimary();
316 // MessageSend messageSend = (MessageSend) expressionStack[expressionPtr];
317 // Expression[] args = messageSend.arguments;
318 // if (reportReferenceInfo) {
319 // requestor.acceptMethodReference(
320 // messageSend.selector,
321 // args == null ? 0 : args.length,
322 // (int)(messageSend.nameSourcePosition >>> 32));
327 // * INTERNAL USE-ONLY
329 //protected void consumeMethodInvocationSuper() {
330 // // MethodInvocation ::= 'super' '.' 'Identifier' '(' ArgumentListopt ')'
331 // super.consumeMethodInvocationSuper();
332 // MessageSend messageSend = (MessageSend) expressionStack[expressionPtr];
333 // Expression[] args = messageSend.arguments;
334 // if (reportReferenceInfo) {
335 // requestor.acceptMethodReference(
336 // messageSend.selector,
337 // args == null ? 0 : args.length,
338 // (int)(messageSend.nameSourcePosition >>> 32));
341 //protected void consumeSingleTypeImportDeclarationName() {
342 // // SingleTypeImportDeclarationName ::= 'import' Name
343 // /* push an ImportRef build from the last name
344 // stored in the identifier stack. */
346 // super.consumeSingleTypeImportDeclarationName();
347 // ImportReference impt = (ImportReference)astStack[astPtr];
348 // if (reportReferenceInfo) {
349 // requestor.acceptTypeReference(impt.tokens, impt.sourceStart,
353 //protected void consumeTypeImportOnDemandDeclarationName() {
354 // // TypeImportOnDemandDeclarationName ::= 'import' Name '.' '*'
355 // /* push an ImportRef build from the last name
356 // stored in the identifier stack. */
358 // super.consumeTypeImportOnDemandDeclarationName();
359 // ImportReference impt = (ImportReference)astStack[astPtr];
360 // if (reportReferenceInfo) {
361 // requestor.acceptUnknownReference(impt.tokens, impt.sourceStart,
365 //protected FieldDeclaration createFieldDeclaration(Expression
366 // initialization, char[] name, int sourceStart, int sourceEnd) {
367 // return new SourceFieldDeclaration(null, name, sourceStart, sourceEnd);
369 //protected CompilationUnitDeclaration endParse(int act) {
370 // if (sourceType != null) {
371 // if (sourceType.isInterface()) {
372 // consumeInterfaceDeclaration();
374 // consumeClassDeclaration();
377 // if (compilationUnit != null) {
378 // CompilationUnitDeclaration result = super.endParse(act);
385 * Flush annotations defined prior to a given positions.
387 * Note: annotations are stacked in syntactical order
389 * Either answer given <position>, or the end position of a comment line
390 * immediately following the <position> (same line)
392 * e.g. void foo(){ } // end of method foo
395 //public int flushAnnotationsDefinedPriorTo(int position) {
397 // return lastFieldEndPosition =
398 // super.flushAnnotationsDefinedPriorTo(position);
400 //public TypeReference getTypeReference(int dim) {
401 // /* build a Reference on a variable that may be qualified or not
402 // * This variable is a type reference and dim will be its dimensions
405 // if ((length = identifierLengthStack[identifierLengthPtr--]) == 1) {
406 // // single variable reference
408 // SingleTypeReference ref =
409 // new SingleTypeReference(
410 // identifierStack[identifierPtr],
411 // identifierPositionStack[identifierPtr--]);
412 // if (reportReferenceInfo) {
413 // requestor.acceptTypeReference(ref.token, ref.sourceStart);
417 // ArrayTypeReference ref =
418 // new ArrayTypeReference(
419 // identifierStack[identifierPtr],
421 // identifierPositionStack[identifierPtr--]);
422 // ref.sourceEnd = endPosition;
423 // if (reportReferenceInfo) {
424 // requestor.acceptTypeReference(ref.token, ref.sourceStart);
429 // if (length < 0) { //flag for precompiled type reference on base types
430 // TypeReference ref = TypeReference.baseTypeReference(-length, dim);
431 // ref.sourceStart = intStack[intPtr--];
433 // ref.sourceEnd = intStack[intPtr--];
435 // intPtr--; // no need to use this position as it is an array
436 // ref.sourceEnd = endPosition;
438 // if (reportReferenceInfo){
439 // requestor.acceptTypeReference(ref.getTypeName(), ref.sourceStart,
443 // } else { //Qualified variable reference
444 // char[][] tokens = new char[length][];
445 // identifierPtr -= length;
446 // long[] positions = new long[length];
447 // System.arraycopy(identifierStack, identifierPtr + 1, tokens, 0, length);
449 // identifierPositionStack,
450 // identifierPtr + 1,
455 // QualifiedTypeReference ref = new QualifiedTypeReference(tokens, positions);
456 // if (reportReferenceInfo) {
457 // requestor.acceptTypeReference(ref.tokens, ref.sourceStart, ref.sourceEnd);
461 // ArrayQualifiedTypeReference ref =
462 // new ArrayQualifiedTypeReference(tokens, dim, positions);
463 // ref.sourceEnd = endPosition;
464 // if (reportReferenceInfo) {
465 // requestor.acceptTypeReference(ref.tokens, ref.sourceStart, ref.sourceEnd);
472 //public NameReference getUnspecifiedReference() {
473 // /* build a (unspecified) NameReference which may be qualified*/
476 // if ((length = identifierLengthStack[identifierLengthPtr--]) == 1) {
477 // // single variable reference
478 // SingleNameReference ref =
479 // new SingleNameReference(
480 // identifierStack[identifierPtr],
481 // identifierPositionStack[identifierPtr--]);
482 // if (reportReferenceInfo) {
483 // this.addUnknownRef(ref);
487 // //Qualified variable reference
488 // char[][] tokens = new char[length][];
489 // identifierPtr -= length;
490 // System.arraycopy(identifierStack, identifierPtr + 1, tokens, 0, length);
491 // QualifiedNameReference ref =
492 // new QualifiedNameReference(
494 // (int) (identifierPositionStack[identifierPtr + 1] >> 32), // sourceStart
495 // (int) identifierPositionStack[identifierPtr + length]); // sourceEnd
496 // if (reportReferenceInfo) {
497 // this.addUnknownRef(ref);
502 //public NameReference getUnspecifiedReferenceOptimized() {
503 // /* build a (unspecified) NameReference which may be qualified
504 // The optimization occurs for qualified reference while we are
505 // certain in this case the last item of the qualified name is
506 // a field access. This optimization is IMPORTANT while it results
507 // that when a NameReference is build, the type checker should always
508 // look for that it is not a type reference */
511 // if ((length = identifierLengthStack[identifierLengthPtr--]) == 1) {
512 // // single variable reference
513 // SingleNameReference ref =
514 // new SingleNameReference(
515 // identifierStack[identifierPtr],
516 // identifierPositionStack[identifierPtr--]);
517 // ref.bits &= ~AstNode.RestrictiveFlagMASK;
518 // ref.bits |= LOCAL | FIELD;
519 // if (reportReferenceInfo) {
520 // this.addUnknownRef(ref);
525 // //Qualified-variable-reference
526 // //In fact it is variable-reference DOT field-ref , but it would result in a
528 // //conflict tha can be only reduce by making a superclass (or inetrface )
530 // //nameReference and FiledReference or putting FieldReference under
532 // //or else..........This optimisation is not really relevant so just leave
535 // char[][] tokens = new char[length][];
536 // identifierPtr -= length;
537 // System.arraycopy(identifierStack, identifierPtr + 1, tokens, 0, length);
538 // QualifiedNameReference ref =
539 // new QualifiedNameReference(
541 // (int) (identifierPositionStack[identifierPtr + 1] >> 32),
543 // (int) identifierPositionStack[identifierPtr + length]); // sourceEnd
544 // ref.bits &= ~AstNode.RestrictiveFlagMASK;
545 // ref.bits |= LOCAL | FIELD;
546 // if (reportReferenceInfo) {
547 // this.addUnknownRef(ref);
553 // * INTERNAL USE-ONLY
555 //private boolean isLocalDeclaration() {
556 // int nestedDepth = nestedType;
557 // while (nestedDepth >= 0) {
558 // if (nestedMethod[nestedDepth] != 0) {
566 * Update the bodyStart of the corresponding parse node
568 public void notifySourceElementRequestor(CompilationUnitDeclaration parsedUnit) {
569 if (parsedUnit == null) {
570 // when we parse a single type member declaration the compilation unit is
571 // null, but we still
572 // want to be able to notify the requestor on the created ast node
573 if (astStack[0] instanceof AbstractMethodDeclaration) {
574 notifySourceElementRequestor((AbstractMethodDeclaration) astStack[0]);
580 boolean isInRange = scanner.initialPosition <= parsedUnit.sourceStart && scanner.eofPosition >= parsedUnit.sourceEnd;
582 // if (reportReferenceInfo) {
583 // notifyAllUnknownReferences();
585 // collect the top level ast nodes
587 AstNode[] nodes = null;
588 if (sourceType == null) {
590 requestor.enterCompilationUnit();
592 // ImportReference currentPackage = parsedUnit.currentPackage;
593 ImportReference[] imports = parsedUnit.imports;
594 // TypeDeclaration[] types = parsedUnit.types;
595 ArrayList types = parsedUnit.types;
598 // (currentPackage == null ? 0 : 1)
599 // + (imports == null ? 0 : imports.length)
600 // + (types == null ? 0 : types.length);
601 // nodes = new AstNode[length];
602 length = (imports == null ? 0 : imports.length) + types.size();
603 nodes = new AstNode[length];
605 // if (currentPackage != null) {
606 // nodes[index++] = currentPackage;
608 if (imports != null) {
609 for (int i = 0, max = imports.length; i < max; i++) {
610 nodes[index++] = imports[i];
614 for (int i = 0, max = types.size(); i < max; i++) {
615 nodes[index++] = (AstNode) types.get(i);
619 // TypeDeclaration[] types = parsedUnit.types;
620 ArrayList types = parsedUnit.types;
622 length = types.size();
623 nodes = new AstNode[length];
624 for (int i = 0, max = types.size(); i < max; i++) {
625 nodes[i] = (AstNode) types.get(i);
630 // notify the nodes in the syntactical order
631 if (nodes != null && length > 0) {
632 quickSort(nodes, 0, length - 1);
633 for (int i = 0; i < length; i++) {
634 AstNode node = nodes[i];
635 if (node instanceof ImportReference) {
636 ImportReference importRef = (ImportReference)node;
637 // if (node == parsedUnit.currentPackage) {
638 // notifySourceElementRequestor(importRef, true);
640 notifySourceElementRequestor(importRef, false);
642 } //else { instanceof TypeDeclaration
643 if (node instanceof TypeDeclaration) {
644 notifySourceElementRequestor((TypeDeclaration) node, sourceType == null);
645 // notifySourceElementRequestor((CompilationUnitDeclaration)node,
646 // sourceType == null);
648 // jsurfer - INSERT start
649 if (node instanceof AbstractMethodDeclaration) {
650 notifySourceElementRequestor((AbstractMethodDeclaration) node);
652 // jsurfer - INSERT end
656 if (sourceType == null) {
658 requestor.exitCompilationUnit(parsedUnit.sourceEnd);
663 //private void notifyAllUnknownReferences() {
664 // for (int i = 0, max = this.unknownRefsCounter; i < max; i++) {
665 // NameReference nameRef = this.unknownRefs[i];
666 // if ((nameRef.bits & BindingIds.VARIABLE) != 0) {
667 // if ((nameRef.bits & BindingIds.TYPE) == 0) {
668 // // variable but not type
669 // if (nameRef instanceof SingleNameReference) {
670 // // local var or field
671 // requestor.acceptUnknownReference(((SingleNameReference) nameRef).token,
672 // nameRef.sourceStart);
674 // // QualifiedNameReference
675 // // The last token is a field reference and the previous tokens are a
676 // type/variable references
677 // char[][] tokens = ((QualifiedNameReference) nameRef).tokens;
678 // int tokensLength = tokens.length;
679 // requestor.acceptFieldReference(tokens[tokensLength - 1], nameRef.sourceEnd
680 // - tokens[tokensLength - 1].length + 1);
681 // char[][] typeRef = new char[tokensLength - 1][];
682 // System.arraycopy(tokens, 0, typeRef, 0, tokensLength - 1);
683 // requestor.acceptUnknownReference(typeRef, nameRef.sourceStart,
684 // nameRef.sourceEnd - tokens[tokensLength - 1].length);
687 // // variable or type
688 // if (nameRef instanceof SingleNameReference) {
689 // requestor.acceptUnknownReference(((SingleNameReference) nameRef).token,
690 // nameRef.sourceStart);
692 // //QualifiedNameReference
693 // requestor.acceptUnknownReference(((QualifiedNameReference) nameRef).tokens,
694 // nameRef.sourceStart, nameRef.sourceEnd);
697 // } else if ((nameRef.bits & BindingIds.TYPE) != 0) {
698 // if (nameRef instanceof SingleNameReference) {
699 // requestor.acceptTypeReference(((SingleNameReference) nameRef).token,
700 // nameRef.sourceStart);
702 // // it is a QualifiedNameReference
703 // requestor.acceptTypeReference(((QualifiedNameReference) nameRef).tokens,
704 // nameRef.sourceStart, nameRef.sourceEnd);
710 * Update the bodyStart of the corresponding parse node
712 public void notifySourceElementRequestor(AbstractMethodDeclaration methodDeclaration) {
715 boolean isInRange = scanner.initialPosition <= methodDeclaration.declarationSourceStart
716 && scanner.eofPosition >= methodDeclaration.declarationSourceEnd;
718 if (methodDeclaration.isClinit()) {
719 this.visitIfNeeded(methodDeclaration);
723 if (methodDeclaration.isDefaultConstructor()) {
724 if (reportReferenceInfo) {
725 ConstructorDeclaration constructorDeclaration = (ConstructorDeclaration) methodDeclaration;
726 ExplicitConstructorCall constructorCall = constructorDeclaration.constructorCall;
727 if (constructorCall != null) {
728 switch (constructorCall.accessMode) {
729 case ExplicitConstructorCall.This :
730 requestor.acceptConstructorReference(typeNames[nestedTypeIndex - 1], constructorCall.arguments == null
732 : constructorCall.arguments.length, constructorCall.sourceStart);
734 case ExplicitConstructorCall.Super :
735 case ExplicitConstructorCall.ImplicitSuper :
736 requestor.acceptConstructorReference(superTypeNames[nestedTypeIndex - 1], constructorCall.arguments == null
738 : constructorCall.arguments.length, constructorCall.sourceStart);
745 char[][] argumentTypes = null;
746 char[][] argumentNames = null;
747 Argument[] arguments = methodDeclaration.arguments;
748 if (arguments != null) {
749 int argumentLength = arguments.length;
750 argumentTypes = new char[argumentLength][];
751 argumentNames = new char[argumentLength][];
752 for (int i = 0; i < argumentLength; i++) {
753 argumentTypes[i] = returnTypeName(arguments[i].type);
754 argumentNames[i] = arguments[i].name;
757 char[][] thrownExceptionTypes = null;
758 TypeReference[] thrownExceptions = methodDeclaration.thrownExceptions;
759 if (thrownExceptions != null) {
760 int thrownExceptionLength = thrownExceptions.length;
761 thrownExceptionTypes = new char[thrownExceptionLength][];
762 for (int i = 0; i < thrownExceptionLength; i++) {
763 thrownExceptionTypes[i] = CharOperation.concatWith(thrownExceptions[i].getTypeName(), '.');
766 // by default no selector end position
767 int selectorSourceEnd = -1;
768 if (methodDeclaration.isConstructor()) {
769 // if (methodDeclaration instanceof SourceConstructorDeclaration) {
770 // selectorSourceEnd =
771 // ((SourceConstructorDeclaration) methodDeclaration).selectorSourceEnd;
774 requestor.enterConstructor(methodDeclaration.declarationSourceStart, methodDeclaration.modifiers,
775 methodDeclaration.selector, methodDeclaration.sourceStart, selectorSourceEnd, argumentTypes, argumentNames,
776 thrownExceptionTypes);
778 if (reportReferenceInfo) {
779 ConstructorDeclaration constructorDeclaration = (ConstructorDeclaration) methodDeclaration;
780 ExplicitConstructorCall constructorCall = constructorDeclaration.constructorCall;
781 if (constructorCall != null) {
782 switch (constructorCall.accessMode) {
783 case ExplicitConstructorCall.This :
784 requestor.acceptConstructorReference(typeNames[nestedTypeIndex - 1], constructorCall.arguments == null
786 : constructorCall.arguments.length, constructorCall.sourceStart);
788 case ExplicitConstructorCall.Super :
789 case ExplicitConstructorCall.ImplicitSuper :
790 requestor.acceptConstructorReference(superTypeNames[nestedTypeIndex - 1], constructorCall.arguments == null
792 : constructorCall.arguments.length, constructorCall.sourceStart);
797 this.visitIfNeeded(methodDeclaration);
799 requestor.exitConstructor(methodDeclaration.declarationSourceEnd);
803 // if (methodDeclaration instanceof SourceMethodDeclaration) {
804 // selectorSourceEnd =
805 // ((SourceMethodDeclaration) methodDeclaration).selectorSourceEnd;
808 int modifiers = methodDeclaration.modifiers;
809 // boolean deprecated = (modifiers & AccDeprecated) != 0; // remember
810 // deprecation so as to not lose it below
811 requestor.enterMethod(methodDeclaration.declarationSourceStart, modifiers, // deprecated
822 returnTypeName(((MethodDeclaration) methodDeclaration).returnType), methodDeclaration.selector,
823 methodDeclaration.sourceStart, selectorSourceEnd, argumentTypes, argumentNames, thrownExceptionTypes);
825 this.visitIfNeeded(methodDeclaration);
828 requestor.exitMethod(methodDeclaration.declarationSourceEnd);
832 * Update the bodyStart of the corresponding parse node
834 public void notifySourceElementRequestor(FieldDeclaration fieldDeclaration) {
837 boolean isInRange = scanner.initialPosition <= fieldDeclaration.declarationSourceStart
838 && scanner.eofPosition >= fieldDeclaration.declarationSourceEnd;
840 if (fieldDeclaration.isField()) {
841 int fieldEndPosition = fieldDeclaration.declarationSourceEnd;
842 // if (fieldDeclaration instanceof SourceFieldDeclaration) {
843 // fieldEndPosition = ((SourceFieldDeclaration)
844 // fieldDeclaration).fieldEndPosition;
845 // if (fieldEndPosition == 0) {
846 // // use the declaration source end by default
847 // fieldEndPosition = fieldDeclaration.declarationSourceEnd;
851 int modifiers = fieldDeclaration.modifiers;
852 boolean deprecated = (modifiers & AccDeprecated) != 0; // remember
856 requestor.enterField(fieldDeclaration.declarationSourceStart, deprecated
857 ? (modifiers & AccJustFlag) | AccDeprecated
858 : modifiers & AccJustFlag, returnTypeName(fieldDeclaration.type), fieldDeclaration.name, fieldDeclaration.sourceStart,
859 fieldDeclaration.sourceEnd);
861 // this.visitIfNeeded(fieldDeclaration);
863 // requestor.exitField(
864 // // filter out initializations that are not a constant (simple check)
865 // (fieldDeclaration.initialization == null
866 // || fieldDeclaration.initialization instanceof ArrayInitializer
867 // || fieldDeclaration.initialization instanceof AllocationExpression
868 // || fieldDeclaration.initialization instanceof
869 // ArrayAllocationExpression
870 // || fieldDeclaration.initialization instanceof Assignment
871 // || fieldDeclaration.initialization instanceof ClassLiteralAccess
872 // || fieldDeclaration.initialization instanceof MessageSend
873 // || fieldDeclaration.initialization instanceof ArrayReference
874 // || fieldDeclaration.initialization instanceof ThisReference) ?
876 // fieldDeclaration.initialization.sourceStart,
878 // fieldDeclaration.declarationSourceEnd);
880 // filter out initializations that are not a constant (simple check)
881 -1, fieldEndPosition, fieldDeclaration.declarationSourceEnd);
886 // requestor.enterInitializer(
887 // fieldDeclaration.declarationSourceStart,
888 // fieldDeclaration.modifiers);
890 // this.visitIfNeeded((Initializer)fieldDeclaration);
892 // requestor.exitInitializer(fieldDeclaration.declarationSourceEnd);
896 public void notifySourceElementRequestor(
897 ImportReference importReference,
900 // requestor.acceptPackage(
901 // importReference.declarationSourceStart,
902 // importReference.declarationSourceEnd,
903 // CharOperation.concatWith(importReference.getImportName(), '.'));
905 requestor.acceptImport(
906 importReference.declarationSourceStart,
907 importReference.declarationSourceEnd,
908 importReference.getIncludeName(), //CharOperation.concatWith(importReference.getImportName(), '.'),
909 importReference.onDemand);
912 public void notifySourceElementRequestor(TypeDeclaration typeDeclaration, boolean notifyTypePresence) {
913 //// public void notifySourceElementRequestor(AstNode typeDeclaration,
914 // boolean notifyTypePresence) {
917 boolean isInRange = scanner.initialPosition <= typeDeclaration.declarationSourceStart
918 && scanner.eofPosition >= typeDeclaration.declarationSourceEnd;
920 FieldDeclaration[] fields = typeDeclaration.fields;
921 AbstractMethodDeclaration[] methods = typeDeclaration.methods;
922 MemberTypeDeclaration[] memberTypes = typeDeclaration.memberTypes;
923 int fieldCount = fields == null ? 0 : fields.length;
924 int methodCount = methods == null ? 0 : methods.length;
925 int memberTypeCount = memberTypes == null ? 0 : memberTypes.length;
928 int memberTypeIndex = 0;
929 boolean isInterface = typeDeclaration.isInterface();
931 if (notifyTypePresence) {
932 char[][] interfaceNames = null;
933 int superInterfacesLength = 0;
934 TypeReference[] superInterfaces = typeDeclaration.superInterfaces;
935 if (superInterfaces != null) {
936 superInterfacesLength = superInterfaces.length;
937 interfaceNames = new char[superInterfacesLength][];
939 if (typeDeclaration instanceof AnonymousLocalTypeDeclaration) {
941 QualifiedAllocationExpression alloc = ((AnonymousLocalTypeDeclaration) typeDeclaration).allocation;
942 if (alloc != null && alloc.type != null) {
943 superInterfaces = new TypeReference[]{((AnonymousLocalTypeDeclaration) typeDeclaration).allocation.type};
944 superInterfacesLength = 1;
945 interfaceNames = new char[1][];
949 if (superInterfaces != null) {
950 for (int i = 0; i < superInterfacesLength; i++) {
951 interfaceNames[i] = CharOperation.concatWith(superInterfaces[i].getTypeName(), '.');
956 int modifiers = typeDeclaration.modifiers;
957 boolean deprecated = false; //(modifiers & AccDeprecated) != 0; //
958 // remember deprecation so as to not lose
960 requestor.enterInterface(typeDeclaration.declarationSourceStart, modifiers, //deprecated
971 typeDeclaration.name, typeDeclaration.sourceStart, typeDeclaration.sourceEnd, interfaceNames);
973 if (nestedTypeIndex == typeNames.length) {
975 System.arraycopy(typeNames, 0, (typeNames = new char[nestedTypeIndex * 2][]), 0, nestedTypeIndex);
976 System.arraycopy(superTypeNames, 0, (superTypeNames = new char[nestedTypeIndex * 2][]), 0, nestedTypeIndex);
978 typeNames[nestedTypeIndex] = typeDeclaration.name;
979 superTypeNames[nestedTypeIndex++] = JAVA_LANG_OBJECT;
981 TypeReference superclass = typeDeclaration.superclass;
982 if (superclass == null) {
984 requestor.enterClass(typeDeclaration.declarationSourceStart, typeDeclaration.modifiers, typeDeclaration.name,
985 typeDeclaration.sourceStart, typeDeclaration.sourceEnd, null, interfaceNames);
989 requestor.enterClass(typeDeclaration.declarationSourceStart, typeDeclaration.modifiers, typeDeclaration.name,
990 typeDeclaration.sourceStart, typeDeclaration.sourceEnd, CharOperation.concatWith(superclass.getTypeName(), '.'),
994 if (nestedTypeIndex == typeNames.length) {
996 System.arraycopy(typeNames, 0, (typeNames = new char[nestedTypeIndex * 2][]), 0, nestedTypeIndex);
997 System.arraycopy(superTypeNames, 0, (superTypeNames = new char[nestedTypeIndex * 2][]), 0, nestedTypeIndex);
999 typeNames[nestedTypeIndex] = typeDeclaration.name;
1000 superTypeNames[nestedTypeIndex++] = superclass == null ? JAVA_LANG_OBJECT : CharOperation.concatWith(superclass
1001 .getTypeName(), '.');
1004 while ((fieldIndex < fieldCount) || (memberTypeIndex < memberTypeCount) || (methodIndex < methodCount)) {
1005 FieldDeclaration nextFieldDeclaration = null;
1006 AbstractMethodDeclaration nextMethodDeclaration = null;
1007 TypeDeclaration nextMemberDeclaration = null;
1009 int position = Integer.MAX_VALUE;
1010 int nextDeclarationType = -1;
1011 if (fieldIndex < fieldCount) {
1012 nextFieldDeclaration = fields[fieldIndex];
1013 if (nextFieldDeclaration.declarationSourceStart < position) {
1014 position = nextFieldDeclaration.declarationSourceStart;
1015 nextDeclarationType = 0; // FIELD
1018 if (methodIndex < methodCount) {
1019 nextMethodDeclaration = methods[methodIndex];
1020 if (nextMethodDeclaration.declarationSourceStart < position) {
1021 position = nextMethodDeclaration.declarationSourceStart;
1022 nextDeclarationType = 1; // METHOD
1025 if (memberTypeIndex < memberTypeCount) {
1026 nextMemberDeclaration = memberTypes[memberTypeIndex];
1027 if (nextMemberDeclaration.declarationSourceStart < position) {
1028 position = nextMemberDeclaration.declarationSourceStart;
1029 nextDeclarationType = 2; // MEMBER
1032 switch (nextDeclarationType) {
1035 notifySourceElementRequestor(nextFieldDeclaration);
1039 notifySourceElementRequestor(nextMethodDeclaration);
1043 notifySourceElementRequestor(nextMemberDeclaration, true);
1046 if (notifyTypePresence) {
1049 requestor.exitInterface(typeDeclaration.declarationSourceEnd);
1051 requestor.exitClass(typeDeclaration.declarationSourceEnd);
1057 public void parseCompilationUnit(ICompilationUnit unit, int start, int end) {
1058 // boolean needReferenceInfo) {
1060 // reportReferenceInfo = needReferenceInfo;
1061 // boolean old = diet;
1062 // if (needReferenceInfo) {
1063 // unknownRefs = new NameReference[10];
1064 // unknownRefsCounter = 0;
1069 CompilationResult compilationUnitResult = new CompilationResult(unit, 0, 0, 10); //this.options.maxProblemsPerUnit);
1070 CompilationUnitDeclaration parsedUnit = parse(unit, compilationUnitResult, start, end);
1071 // if (scanner.recordLineSeparator) {
1072 // requestor.acceptLineSeparatorPositions(scanner.getLineEnds());
1074 // if (this.localDeclarationVisitor != null || needReferenceInfo){
1076 // this.getMethodBodies(parsedUnit);
1078 // this.scanner.resetTo(start, end);
1079 // notifySourceElementRequestor(parsedUnit);
1080 } catch (AbortCompilation e) {
1085 public CompilationUnitDeclaration parseCompilationUnit(ICompilationUnit unit, boolean fullParse) {
1087 // boolean old = diet;
1089 // unknownRefs = new NameReference[10];
1090 // unknownRefsCounter = 0;
1095 this.reportReferenceInfo = fullParse;
1096 CompilationResult compilationUnitResult = new CompilationResult(unit, 0, 0, this.options.maxProblemsPerUnit);
1097 CompilationUnitDeclaration parsedUnit = parse(unit, compilationUnitResult, false);
1098 if (scanner.recordLineSeparator) {
1099 requestor.acceptLineSeparatorPositions(scanner.getLineEnds());
1101 int initialStart = this.scanner.initialPosition;
1102 int initialEnd = this.scanner.eofPosition;
1103 // if (this.localDeclarationVisitor != null || fullParse){
1105 // this.getMethodBodies(parsedUnit);
1107 this.scanner.resetTo(initialStart, initialEnd);
1108 notifySourceElementRequestor(parsedUnit);
1110 } catch (AbortCompilation e) {
1111 // ignore this exception
1118 //public void parseTypeMemberDeclarations(
1119 // ISourceType sourceType,
1120 // ICompilationUnit sourceUnit,
1123 // boolean needReferenceInfo) {
1124 // boolean old = diet;
1125 // if (needReferenceInfo) {
1126 // unknownRefs = new NameReference[10];
1127 // unknownRefsCounter = 0;
1131 // diet = !needReferenceInfo;
1132 // reportReferenceInfo = needReferenceInfo;
1133 // CompilationResult compilationUnitResult =
1134 // new CompilationResult(sourceUnit, 0, 0, this.options.maxProblemsPerUnit);
1135 // CompilationUnitDeclaration unit =
1136 // SourceTypeConverter.buildCompilationUnit(
1137 // new ISourceType[]{sourceType},
1138 // false, // no need for field and methods
1139 // false, // no need for member types
1140 // false, // no need for field initialization
1141 // problemReporter(),
1142 // compilationUnitResult);
1143 // if ((unit == null) || (unit.types == null) || (unit.types.length != 1))
1145 // this.sourceType = sourceType;
1147 // /* automaton initialization */
1149 // goForClassBodyDeclarations();
1150 // /* scanner initialization */
1151 // scanner.setSource(sourceUnit.getContents());
1152 // scanner.resetTo(start, end);
1153 // /* unit creation */
1154 // referenceContext = compilationUnit = unit;
1155 // /* initialize the astStacl */
1156 // // the compilationUnitDeclaration should contain exactly one type
1157 // pushOnAstStack(unit.types[0]);
1158 // /* run automaton */
1160 // notifySourceElementRequestor(unit);
1162 // unit = compilationUnit;
1163 // compilationUnit = null; // reset parser
1165 // } catch (AbortCompilation e) {
1167 // if (scanner.recordLineSeparator) {
1168 // requestor.acceptLineSeparatorPositions(scanner.getLineEnds());
1174 //public void parseTypeMemberDeclarations(
1179 // boolean old = diet;
1184 // /* automaton initialization */
1186 // goForClassBodyDeclarations();
1187 // /* scanner initialization */
1188 // scanner.setSource(contents);
1189 // scanner.recordLineSeparator = false;
1190 // scanner.taskTags = null;
1191 // scanner.taskPriorities = null;
1192 // scanner.resetTo(start, end);
1194 // /* unit creation */
1195 // referenceContext = null;
1197 // /* initialize the astStacl */
1198 // // the compilationUnitDeclaration should contain exactly one type
1199 // /* run automaton */
1201 // notifySourceElementRequestor((CompilationUnitDeclaration)null);
1202 // } catch (AbortCompilation e) {
1208 * Sort the given ast nodes by their positions.
1210 private static void quickSort(AstNode[] sortedCollection, int left, int right) {
1211 int original_left = left;
1212 int original_right = right;
1213 AstNode mid = sortedCollection[(left + right) / 2];
1215 while (sortedCollection[left].sourceStart < mid.sourceStart) {
1218 while (mid.sourceStart < sortedCollection[right].sourceStart) {
1221 if (left <= right) {
1222 AstNode tmp = sortedCollection[left];
1223 sortedCollection[left] = sortedCollection[right];
1224 sortedCollection[right] = tmp;
1228 } while (left <= right);
1229 if (original_left < right) {
1230 quickSort(sortedCollection, original_left, right);
1232 if (left < original_right) {
1233 quickSort(sortedCollection, left, original_right);
1237 * Answer a char array representation of the type name formatted like: - type
1238 * name + dimensions Example: "A[][]".toCharArray()
1239 * "java.lang.String".toCharArray()
1241 private char[] returnTypeName(TypeReference type) {
1244 int dimension = type.dimensions();
1245 if (dimension != 0) {
1246 char[] dimensionsArray = new char[dimension * 2];
1247 for (int i = 0; i < dimension; i++) {
1248 dimensionsArray[i * 2] = '[';
1249 dimensionsArray[(i * 2) + 1] = ']';
1251 return CharOperation.concat(CharOperation.concatWith(type.getTypeName(), '.'), dimensionsArray);
1253 return CharOperation.concatWith(type.getTypeName(), '.');
1256 public void addUnknownRef(NameReference nameRef) {
1257 if (this.unknownRefs.length == this.unknownRefsCounter) {
1259 System.arraycopy(this.unknownRefs, 0, (this.unknownRefs = new NameReference[this.unknownRefsCounter * 2]), 0,
1260 this.unknownRefsCounter);
1262 this.unknownRefs[this.unknownRefsCounter++] = nameRef;
1265 private void visitIfNeeded(AbstractMethodDeclaration method) {
1266 if (this.localDeclarationVisitor != null && (method.bits & AstNode.HasLocalTypeMASK) != 0) {
1267 if (method.statements != null) {
1268 int statementsLength = method.statements.length;
1269 for (int i = 0; i < statementsLength; i++)
1270 method.statements[i].traverse(this.localDeclarationVisitor, method.scope);
1275 //private void visitIfNeeded(FieldDeclaration field) {
1276 // if (this.localDeclarationVisitor != null
1277 // && (field.bits & AstNode.HasLocalTypeMASK) != 0) {
1278 // if (field.initialization != null) {
1279 // field.initialization.traverse(this.localDeclarationVisitor, null);
1284 //private void visitIfNeeded(Initializer initializer) {
1285 // if (this.localDeclarationVisitor != null
1286 // && (initializer.bits & AstNode.HasLocalTypeMASK) != 0) {
1287 // if (initializer.block != null) {
1288 // initializer.block.traverse(this.localDeclarationVisitor, null);
1293 //protected void reportSyntaxError(int act, int currentKind, int
1295 // if (compilationUnit == null) return;
1296 // super.reportSyntaxError(act, currentKind,stateStackTop);
1298 protected CompilationUnitDeclaration endParse(int act) {
1299 // if (sourceType != null) {
1300 // if (sourceType.isInterface()) {
1301 // consumeInterfaceDeclaration();
1303 // consumeClassDeclaration();
1306 if (compilationUnit != null) {
1307 CompilationUnitDeclaration result = super.endParse(act);