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.internal.compiler.CompilationResult;
17 import net.sourceforge.phpdt.core.compiler.CharOperation;
18 import net.sourceforge.phpdt.core.compiler.IProblem;
19 import net.sourceforge.phpdt.internal.compiler.env.ICompilationUnit;
20 import net.sourceforge.phpdt.internal.compiler.env.ISourceType;
21 import net.sourceforge.phpdt.internal.compiler.impl.CompilerOptions;
22 import net.sourceforge.phpdt.internal.compiler.impl.ReferenceContext;
23 import net.sourceforge.phpdt.internal.compiler.lookup.BlockScope;
24 import net.sourceforge.phpdt.internal.compiler.lookup.ClassScope;
25 import net.sourceforge.phpdt.internal.compiler.parser.UnitParser;
26 import net.sourceforge.phpdt.internal.compiler.problem.AbortCompilation;
27 import net.sourceforge.phpdt.internal.compiler.problem.ProblemReporter;
28 import net.sourceforge.phpeclipse.internal.compiler.ast.AbstractMethodDeclaration;
29 import net.sourceforge.phpeclipse.internal.compiler.ast.AnonymousLocalTypeDeclaration;
30 import net.sourceforge.phpeclipse.internal.compiler.ast.Argument;
31 import net.sourceforge.phpeclipse.internal.compiler.ast.AstNode;
32 import net.sourceforge.phpeclipse.internal.compiler.ast.CompilationUnitDeclaration;
33 import net.sourceforge.phpeclipse.internal.compiler.ast.ConstructorDeclaration;
34 import net.sourceforge.phpeclipse.internal.compiler.ast.ExplicitConstructorCall;
35 import net.sourceforge.phpeclipse.internal.compiler.ast.FieldDeclaration;
36 import net.sourceforge.phpeclipse.internal.compiler.ast.LocalTypeDeclaration;
37 import net.sourceforge.phpeclipse.internal.compiler.ast.MemberTypeDeclaration;
38 import net.sourceforge.phpeclipse.internal.compiler.ast.MethodDeclaration;
39 import net.sourceforge.phpeclipse.internal.compiler.ast.NameReference;
40 import net.sourceforge.phpeclipse.internal.compiler.ast.QualifiedAllocationExpression;
41 import net.sourceforge.phpeclipse.internal.compiler.ast.TypeDeclaration;
42 import net.sourceforge.phpeclipse.internal.compiler.ast.TypeReference;
47 * A source element parser extracts structural and reference information
48 * from a piece of source.
50 * also see @ISourceElementRequestor
52 * The structural investigation includes:
53 * - the package statement
55 * - top-level types: package member, member types (member types of member types...)
59 * If reference information is requested, then all source constructs are
60 * investigated and type, field & method references are provided as well.
62 * Any (parsing) problem encountered is also provided.
65 public class SourceElementParser extends UnitParser {
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 == null);
90 // return false; // don't visit members as this was done during 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 notifySourceElementRequestor(...)
96 public boolean visit(MemberTypeDeclaration typeDeclaration, ClassScope scope) {
97 notifySourceElementRequestor(typeDeclaration, sourceType == null);
98 return false; // don't visit members as this was done during notifySourceElementRequestor(...)
103 public SourceElementParser(
104 final ISourceElementRequestor requestor,
105 IProblemFactory problemFactory,
106 CompilerOptions options) {
107 // we want to notify all syntax error with the acceptProblem API
108 // To do so, we define the record method of the ProblemReporter
111 DefaultErrorHandlingPolicies.exitAfterAllProblems(),
114 public void record(IProblem problem, CompilationResult unitResult, ReferenceContext referenceContext) {
115 unitResult.record(problem, referenceContext);
116 requestor.acceptProblem(problem);
120 // options.sourceLevel >= CompilerOptions.JDK1_4);
121 this.requestor = requestor;
122 typeNames = new char[4][];
123 superTypeNames = new char[4][];
125 this.options = options;
128 /** @deprecated use SourceElementParser(ISourceElementRequestor, IProblemFactory, CompilerOptions) */
129 //public SourceElementParser(
130 // final ISourceElementRequestor requestor,
131 // IProblemFactory problemFactory) {
132 // this(requestor, problemFactory, new CompilerOptions());
135 //public SourceElementParser(
136 // final ISourceElementRequestor requestor,
137 // IProblemFactory problemFactory,
138 // CompilerOptions options,
139 // boolean reportLocalDeclarations) {
140 // this(requestor, problemFactory, options);
141 // if (reportLocalDeclarations) {
142 // 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];
157 //protected void classInstanceCreation(boolean alwaysQualified) {
159 // boolean previousFlag = reportReferenceInfo;
160 // reportReferenceInfo = false; // not to see the type reference reported in super call to getTypeReference(...)
161 // super.classInstanceCreation(alwaysQualified);
162 // reportReferenceInfo = previousFlag;
163 // if (reportReferenceInfo){
164 // AllocationExpression alloc = (AllocationExpression)expressionStack[expressionPtr];
165 // TypeReference typeRef = alloc.type;
166 // requestor.acceptConstructorReference(
167 // typeRef instanceof SingleTypeReference
168 // ? ((SingleTypeReference) typeRef).token
169 // : CharOperation.concatWith(alloc.type.getTypeName(), '.'),
170 // alloc.arguments == null ? 0 : alloc.arguments.length,
171 // alloc.sourceStart);
174 //protected void consumeConstructorHeaderName() {
175 // // ConstructorHeaderName ::= Modifiersopt 'Identifier' '('
177 // /* recovering - might be an empty message send */
178 // if (currentElement != null){
179 // if (lastIgnoredToken == TokenNamenew){ // was an allocation expression
180 // lastCheckPoint = scanner.startPosition; // force to restart at this exact position
181 // restartRecovery = true;
185 // SourceConstructorDeclaration cd = new SourceConstructorDeclaration(this.compilationUnit.compilationResult);
187 // //name -- this is not really revelant but we do .....
188 // cd.selector = identifierStack[identifierPtr];
189 // long selectorSourcePositions = identifierPositionStack[identifierPtr--];
190 // identifierLengthPtr--;
193 // cd.declarationSourceStart = intStack[intPtr--];
194 // cd.modifiers = intStack[intPtr--];
196 // //highlight starts at the selector starts
197 // cd.sourceStart = (int) (selectorSourcePositions >>> 32);
198 // cd.selectorSourceEnd = (int) selectorSourcePositions;
199 // pushOnAstStack(cd);
201 // cd.sourceEnd = lParenPos;
202 // cd.bodyStart = lParenPos+1;
203 // listLength = 0; // initialize listLength before reading parameters/throws
206 // if (currentElement != null){
207 // lastCheckPoint = cd.bodyStart;
208 // if ((currentElement instanceof RecoveredType && lastIgnoredToken != TokenNameDOT)
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) && (currentToken != TokenNameSEMICOLON)))
226 // ((SourceFieldDeclaration) astStack[astPtr]).fieldEndPosition = scanner.currentPosition - 1;
228 //protected void consumeExitVariableWithoutInitialization() {
229 // // ExitVariableWithoutInitialization ::= $empty
230 // // do nothing by default
231 // super.consumeExitVariableWithoutInitialization();
232 // if (isLocalDeclaration() || ((currentToken != TokenNameCOMMA) && (currentToken != TokenNameSEMICOLON)))
234 // ((SourceFieldDeclaration) astStack[astPtr]).fieldEndPosition = scanner.currentPosition - 1;
238 // * INTERNAL USE-ONLY
240 //protected void consumeFieldAccess(boolean isSuperAccess) {
241 // // FieldAccess ::= Primary '.' 'Identifier'
242 // // FieldAccess ::= 'super' '.' 'Identifier'
243 // super.consumeFieldAccess(isSuperAccess);
244 // FieldReference fr = (FieldReference) expressionStack[expressionPtr];
245 // if (reportReferenceInfo) {
246 // requestor.acceptFieldReference(fr.token, fr.sourceStart);
249 //protected void consumeMethodHeaderName() {
250 // // MethodHeaderName ::= Modifiersopt Type 'Identifier' '('
251 // SourceMethodDeclaration md = new SourceMethodDeclaration(this.compilationUnit.compilationResult);
254 // md.selector = identifierStack[identifierPtr];
255 // long selectorSourcePositions = identifierPositionStack[identifierPtr--];
256 // identifierLengthPtr--;
258 // md.returnType = getTypeReference(intStack[intPtr--]);
260 // md.declarationSourceStart = intStack[intPtr--];
261 // md.modifiers = intStack[intPtr--];
263 // //highlight starts at selector start
264 // md.sourceStart = (int) (selectorSourcePositions >>> 32);
265 // md.selectorSourceEnd = (int) selectorSourcePositions;
266 // pushOnAstStack(md);
267 // md.sourceEnd = lParenPos;
268 // md.bodyStart = lParenPos+1;
269 // listLength = 0; // initialize listLength before reading parameters/throws
272 // if (currentElement != null){
273 // if (currentElement instanceof RecoveredType
274 // //|| md.modifiers != 0
275 // || (scanner.getLineNumber(md.returnType.sourceStart)
276 // == scanner.getLineNumber(md.sourceStart))){
277 // lastCheckPoint = md.bodyStart;
278 // currentElement = currentElement.add(md, 0);
279 // lastIgnoredToken = -1;
281 // lastCheckPoint = md.sourceStart;
282 // restartRecovery = true;
288 // * INTERNAL USE-ONLY
290 //protected void consumeMethodInvocationName() {
291 // // MethodInvocation ::= Name '(' ArgumentListopt ')'
293 // // when the name is only an identifier...we have a message send to "this" (implicit)
294 // super.consumeMethodInvocationName();
295 // MessageSend messageSend = (MessageSend) expressionStack[expressionPtr];
296 // Expression[] args = messageSend.arguments;
297 // if (reportReferenceInfo) {
298 // requestor.acceptMethodReference(
299 // messageSend.selector,
300 // args == null ? 0 : args.length,
301 // (int)(messageSend.nameSourcePosition >>> 32));
306 // * INTERNAL USE-ONLY
308 //protected void consumeMethodInvocationPrimary() {
309 // super.consumeMethodInvocationPrimary();
310 // MessageSend messageSend = (MessageSend) expressionStack[expressionPtr];
311 // Expression[] args = messageSend.arguments;
312 // if (reportReferenceInfo) {
313 // requestor.acceptMethodReference(
314 // messageSend.selector,
315 // args == null ? 0 : args.length,
316 // (int)(messageSend.nameSourcePosition >>> 32));
321 // * INTERNAL USE-ONLY
323 //protected void consumeMethodInvocationSuper() {
324 // // MethodInvocation ::= 'super' '.' 'Identifier' '(' ArgumentListopt ')'
325 // super.consumeMethodInvocationSuper();
326 // MessageSend messageSend = (MessageSend) expressionStack[expressionPtr];
327 // Expression[] args = messageSend.arguments;
328 // if (reportReferenceInfo) {
329 // requestor.acceptMethodReference(
330 // messageSend.selector,
331 // args == null ? 0 : args.length,
332 // (int)(messageSend.nameSourcePosition >>> 32));
335 //protected void consumeSingleTypeImportDeclarationName() {
336 // // SingleTypeImportDeclarationName ::= 'import' Name
337 // /* push an ImportRef build from the last name
338 // stored in the identifier stack. */
340 // super.consumeSingleTypeImportDeclarationName();
341 // ImportReference impt = (ImportReference)astStack[astPtr];
342 // if (reportReferenceInfo) {
343 // requestor.acceptTypeReference(impt.tokens, impt.sourceStart, impt.sourceEnd);
346 //protected void consumeTypeImportOnDemandDeclarationName() {
347 // // TypeImportOnDemandDeclarationName ::= 'import' Name '.' '*'
348 // /* push an ImportRef build from the last name
349 // stored in the identifier stack. */
351 // super.consumeTypeImportOnDemandDeclarationName();
352 // ImportReference impt = (ImportReference)astStack[astPtr];
353 // if (reportReferenceInfo) {
354 // requestor.acceptUnknownReference(impt.tokens, impt.sourceStart, impt.sourceEnd);
357 //protected FieldDeclaration createFieldDeclaration(Expression initialization, char[] name, int sourceStart, int sourceEnd) {
358 // return new SourceFieldDeclaration(null, name, sourceStart, sourceEnd);
360 //protected CompilationUnitDeclaration endParse(int act) {
361 // if (sourceType != null) {
362 // if (sourceType.isInterface()) {
363 // consumeInterfaceDeclaration();
365 // consumeClassDeclaration();
368 // if (compilationUnit != null) {
369 // CompilationUnitDeclaration result = super.endParse(act);
376 * Flush annotations defined prior to a given positions.
378 * Note: annotations are stacked in syntactical order
380 * Either answer given <position>, or the end position of a comment line
381 * immediately following the <position> (same line)
385 * } // end of method foo
388 //public int flushAnnotationsDefinedPriorTo(int position) {
390 // return lastFieldEndPosition = super.flushAnnotationsDefinedPriorTo(position);
392 //public TypeReference getTypeReference(int dim) {
393 // /* build a Reference on a variable that may be qualified or not
394 // * This variable is a type reference and dim will be its dimensions
397 // if ((length = identifierLengthStack[identifierLengthPtr--]) == 1) {
398 // // single variable reference
400 // SingleTypeReference ref =
401 // new SingleTypeReference(
402 // identifierStack[identifierPtr],
403 // identifierPositionStack[identifierPtr--]);
404 // if (reportReferenceInfo) {
405 // requestor.acceptTypeReference(ref.token, ref.sourceStart);
409 // ArrayTypeReference ref =
410 // new ArrayTypeReference(
411 // identifierStack[identifierPtr],
413 // identifierPositionStack[identifierPtr--]);
414 // ref.sourceEnd = endPosition;
415 // if (reportReferenceInfo) {
416 // requestor.acceptTypeReference(ref.token, ref.sourceStart);
421 // if (length < 0) { //flag for precompiled type reference on base types
422 // TypeReference ref = TypeReference.baseTypeReference(-length, dim);
423 // ref.sourceStart = intStack[intPtr--];
425 // ref.sourceEnd = intStack[intPtr--];
427 // intPtr--; // no need to use this position as it is an array
428 // ref.sourceEnd = endPosition;
430 // if (reportReferenceInfo){
431 // requestor.acceptTypeReference(ref.getTypeName(), ref.sourceStart, ref.sourceEnd);
434 // } else { //Qualified variable reference
435 // char[][] tokens = new char[length][];
436 // identifierPtr -= length;
437 // long[] positions = new long[length];
438 // System.arraycopy(identifierStack, identifierPtr + 1, tokens, 0, length);
440 // identifierPositionStack,
441 // identifierPtr + 1,
446 // QualifiedTypeReference ref = new QualifiedTypeReference(tokens, positions);
447 // if (reportReferenceInfo) {
448 // requestor.acceptTypeReference(ref.tokens, ref.sourceStart, ref.sourceEnd);
452 // ArrayQualifiedTypeReference ref =
453 // new ArrayQualifiedTypeReference(tokens, dim, positions);
454 // ref.sourceEnd = endPosition;
455 // if (reportReferenceInfo) {
456 // requestor.acceptTypeReference(ref.tokens, ref.sourceStart, ref.sourceEnd);
463 //public NameReference getUnspecifiedReference() {
464 // /* build a (unspecified) NameReference which may be qualified*/
467 // if ((length = identifierLengthStack[identifierLengthPtr--]) == 1) {
468 // // single variable reference
469 // SingleNameReference ref =
470 // new SingleNameReference(
471 // identifierStack[identifierPtr],
472 // identifierPositionStack[identifierPtr--]);
473 // if (reportReferenceInfo) {
474 // this.addUnknownRef(ref);
478 // //Qualified variable reference
479 // char[][] tokens = new char[length][];
480 // identifierPtr -= length;
481 // System.arraycopy(identifierStack, identifierPtr + 1, tokens, 0, length);
482 // QualifiedNameReference ref =
483 // new QualifiedNameReference(
485 // (int) (identifierPositionStack[identifierPtr + 1] >> 32), // sourceStart
486 // (int) identifierPositionStack[identifierPtr + length]); // sourceEnd
487 // if (reportReferenceInfo) {
488 // this.addUnknownRef(ref);
493 //public NameReference getUnspecifiedReferenceOptimized() {
494 // /* build a (unspecified) NameReference which may be qualified
495 // The optimization occurs for qualified reference while we are
496 // certain in this case the last item of the qualified name is
497 // a field access. This optimization is IMPORTANT while it results
498 // that when a NameReference is build, the type checker should always
499 // look for that it is not a type reference */
502 // if ((length = identifierLengthStack[identifierLengthPtr--]) == 1) {
503 // // single variable reference
504 // SingleNameReference ref =
505 // new SingleNameReference(
506 // identifierStack[identifierPtr],
507 // identifierPositionStack[identifierPtr--]);
508 // ref.bits &= ~AstNode.RestrictiveFlagMASK;
509 // ref.bits |= LOCAL | FIELD;
510 // if (reportReferenceInfo) {
511 // this.addUnknownRef(ref);
516 // //Qualified-variable-reference
517 // //In fact it is variable-reference DOT field-ref , but it would result in a type
518 // //conflict tha can be only reduce by making a superclass (or inetrface ) between
519 // //nameReference and FiledReference or putting FieldReference under NameReference
520 // //or else..........This optimisation is not really relevant so just leave as it is
522 // char[][] tokens = new char[length][];
523 // identifierPtr -= length;
524 // System.arraycopy(identifierStack, identifierPtr + 1, tokens, 0, length);
525 // QualifiedNameReference ref =
526 // new QualifiedNameReference(
528 // (int) (identifierPositionStack[identifierPtr + 1] >> 32),
530 // (int) identifierPositionStack[identifierPtr + length]); // sourceEnd
531 // ref.bits &= ~AstNode.RestrictiveFlagMASK;
532 // ref.bits |= LOCAL | FIELD;
533 // if (reportReferenceInfo) {
534 // this.addUnknownRef(ref);
540 // * INTERNAL USE-ONLY
542 //private boolean isLocalDeclaration() {
543 // int nestedDepth = nestedType;
544 // while (nestedDepth >= 0) {
545 // if (nestedMethod[nestedDepth] != 0) {
553 * Update the bodyStart of the corresponding parse node
555 public void notifySourceElementRequestor(CompilationUnitDeclaration parsedUnit) {
556 if (parsedUnit == null) {
557 // when we parse a single type member declaration the compilation unit is null, but we still
558 // want to be able to notify the requestor on the created ast node
559 if (astStack[0] instanceof AbstractMethodDeclaration) {
560 notifySourceElementRequestor((AbstractMethodDeclaration) astStack[0]);
567 scanner.initialPosition <= parsedUnit.sourceStart
568 && scanner.eofPosition >= parsedUnit.sourceEnd;
570 // if (reportReferenceInfo) {
571 // notifyAllUnknownReferences();
573 // collect the top level ast nodes
575 AstNode[] nodes = null;
576 if (sourceType == null){
578 requestor.enterCompilationUnit();
580 // ImportReference currentPackage = parsedUnit.currentPackage;
581 // ImportReference[] imports = parsedUnit.imports;
582 // TypeDeclaration[] types = parsedUnit.types;
583 ArrayList types = parsedUnit.types;
586 // (currentPackage == null ? 0 : 1)
587 // + (imports == null ? 0 : imports.length)
588 // + (types == null ? 0 : types.length);
589 // nodes = new AstNode[length];
590 length = types.size();
591 nodes = new AstNode[length];
593 // if (currentPackage != null) {
594 // nodes[index++] = currentPackage;
596 // if (imports != null) {
597 // for (int i = 0, max = imports.length; i < max; i++) {
598 // nodes[index++] = imports[i];
602 for (int i = 0, max = types.size(); i < max; i++) {
603 nodes[index++] = (AstNode)types.get(i);
607 // TypeDeclaration[] types = parsedUnit.types;
608 ArrayList types = parsedUnit.types;
610 length = types.size();
611 nodes = new AstNode[length];
612 for (int i = 0, max = types.size(); i < max; i++) {
613 nodes[i] = (AstNode)types.get(i);
618 // notify the nodes in the syntactical order
619 if (nodes != null && length > 0) {
620 quickSort(nodes, 0, length-1);
621 for (int i=0;i<length;i++) {
622 AstNode node = nodes[i];
623 // if (node instanceof ImportReference) {
624 // ImportReference importRef = (ImportReference)node;
625 // if (node == parsedUnit.currentPackage) {
626 // notifySourceElementRequestor(importRef, true);
628 // notifySourceElementRequestor(importRef, false);
630 // } else { // instanceof TypeDeclaration
631 if (node instanceof TypeDeclaration) {
632 notifySourceElementRequestor((TypeDeclaration)node, sourceType == null);
633 // notifySourceElementRequestor((CompilationUnitDeclaration)node, sourceType == null);
635 // jsurfer - INSERT start
636 if (node instanceof AbstractMethodDeclaration) {
637 notifySourceElementRequestor((AbstractMethodDeclaration)node);
639 // jsurfer - INSERT end
643 if (sourceType == null){
645 requestor.exitCompilationUnit(parsedUnit.sourceEnd);
650 //private void notifyAllUnknownReferences() {
651 // for (int i = 0, max = this.unknownRefsCounter; i < max; i++) {
652 // NameReference nameRef = this.unknownRefs[i];
653 // if ((nameRef.bits & BindingIds.VARIABLE) != 0) {
654 // if ((nameRef.bits & BindingIds.TYPE) == 0) {
655 // // variable but not type
656 // if (nameRef instanceof SingleNameReference) {
657 // // local var or field
658 // requestor.acceptUnknownReference(((SingleNameReference) nameRef).token, nameRef.sourceStart);
660 // // QualifiedNameReference
661 // // The last token is a field reference and the previous tokens are a type/variable references
662 // char[][] tokens = ((QualifiedNameReference) nameRef).tokens;
663 // int tokensLength = tokens.length;
664 // requestor.acceptFieldReference(tokens[tokensLength - 1], nameRef.sourceEnd - tokens[tokensLength - 1].length + 1);
665 // char[][] typeRef = new char[tokensLength - 1][];
666 // System.arraycopy(tokens, 0, typeRef, 0, tokensLength - 1);
667 // requestor.acceptUnknownReference(typeRef, nameRef.sourceStart, nameRef.sourceEnd - tokens[tokensLength - 1].length);
670 // // variable or type
671 // if (nameRef instanceof SingleNameReference) {
672 // requestor.acceptUnknownReference(((SingleNameReference) nameRef).token, nameRef.sourceStart);
674 // //QualifiedNameReference
675 // requestor.acceptUnknownReference(((QualifiedNameReference) nameRef).tokens, nameRef.sourceStart, nameRef.sourceEnd);
678 // } else if ((nameRef.bits & BindingIds.TYPE) != 0) {
679 // if (nameRef instanceof SingleNameReference) {
680 // requestor.acceptTypeReference(((SingleNameReference) nameRef).token, nameRef.sourceStart);
682 // // it is a QualifiedNameReference
683 // requestor.acceptTypeReference(((QualifiedNameReference) nameRef).tokens, nameRef.sourceStart, nameRef.sourceEnd);
689 * Update the bodyStart of the corresponding parse node
691 public void notifySourceElementRequestor(AbstractMethodDeclaration methodDeclaration) {
695 scanner.initialPosition <= methodDeclaration.declarationSourceStart
696 && scanner.eofPosition >= methodDeclaration.declarationSourceEnd;
698 if (methodDeclaration.isClinit()) {
699 this.visitIfNeeded(methodDeclaration);
703 if (methodDeclaration.isDefaultConstructor()) {
704 if (reportReferenceInfo) {
705 ConstructorDeclaration constructorDeclaration = (ConstructorDeclaration) methodDeclaration;
706 ExplicitConstructorCall constructorCall = constructorDeclaration.constructorCall;
707 if (constructorCall != null) {
708 switch(constructorCall.accessMode) {
709 case ExplicitConstructorCall.This :
710 requestor.acceptConstructorReference(
711 typeNames[nestedTypeIndex-1],
712 constructorCall.arguments == null ? 0 : constructorCall.arguments.length,
713 constructorCall.sourceStart);
715 case ExplicitConstructorCall.Super :
716 case ExplicitConstructorCall.ImplicitSuper :
717 requestor.acceptConstructorReference(
718 superTypeNames[nestedTypeIndex-1],
719 constructorCall.arguments == null ? 0 : constructorCall.arguments.length,
720 constructorCall.sourceStart);
727 char[][] argumentTypes = null;
728 char[][] argumentNames = null;
729 Argument[] arguments = methodDeclaration.arguments;
730 if (arguments != null) {
731 int argumentLength = arguments.length;
732 argumentTypes = new char[argumentLength][];
733 argumentNames = new char[argumentLength][];
734 for (int i = 0; i < argumentLength; i++) {
735 argumentTypes[i] = returnTypeName(arguments[i].type);
736 argumentNames[i] = arguments[i].name;
739 char[][] thrownExceptionTypes = null;
740 TypeReference[] thrownExceptions = methodDeclaration.thrownExceptions;
741 if (thrownExceptions != null) {
742 int thrownExceptionLength = thrownExceptions.length;
743 thrownExceptionTypes = new char[thrownExceptionLength][];
744 for (int i = 0; i < thrownExceptionLength; i++) {
745 thrownExceptionTypes[i] =
746 CharOperation.concatWith(thrownExceptions[i].getTypeName(), '.');
749 // by default no selector end position
750 int selectorSourceEnd = -1;
751 if (methodDeclaration.isConstructor()) {
752 // if (methodDeclaration instanceof SourceConstructorDeclaration) {
753 // selectorSourceEnd =
754 // ((SourceConstructorDeclaration) methodDeclaration).selectorSourceEnd;
757 requestor.enterConstructor(
758 methodDeclaration.declarationSourceStart,
759 methodDeclaration.modifiers,
760 methodDeclaration.selector,
761 methodDeclaration.sourceStart,
765 thrownExceptionTypes);
767 if (reportReferenceInfo) {
768 ConstructorDeclaration constructorDeclaration = (ConstructorDeclaration) methodDeclaration;
769 ExplicitConstructorCall constructorCall = constructorDeclaration.constructorCall;
770 if (constructorCall != null) {
771 switch(constructorCall.accessMode) {
772 case ExplicitConstructorCall.This :
773 requestor.acceptConstructorReference(
774 typeNames[nestedTypeIndex-1],
775 constructorCall.arguments == null ? 0 : constructorCall.arguments.length,
776 constructorCall.sourceStart);
778 case ExplicitConstructorCall.Super :
779 case ExplicitConstructorCall.ImplicitSuper :
780 requestor.acceptConstructorReference(
781 superTypeNames[nestedTypeIndex-1],
782 constructorCall.arguments == null ? 0 : constructorCall.arguments.length,
783 constructorCall.sourceStart);
788 this.visitIfNeeded(methodDeclaration);
790 requestor.exitConstructor(methodDeclaration.declarationSourceEnd);
794 // if (methodDeclaration instanceof SourceMethodDeclaration) {
795 // selectorSourceEnd =
796 // ((SourceMethodDeclaration) methodDeclaration).selectorSourceEnd;
799 int modifiers = methodDeclaration.modifiers;
800 // boolean deprecated = (modifiers & AccDeprecated) != 0; // remember deprecation so as to not lose it below
801 requestor.enterMethod(
802 methodDeclaration.declarationSourceStart,
803 modifiers, // deprecated ? (modifiers & AccJustFlag) | AccDeprecated : modifiers & AccJustFlag,
804 returnTypeName(((MethodDeclaration) methodDeclaration).returnType),
805 methodDeclaration.selector,
806 methodDeclaration.sourceStart,
810 thrownExceptionTypes);
812 this.visitIfNeeded(methodDeclaration);
815 requestor.exitMethod(methodDeclaration.declarationSourceEnd);
819 //* Update the bodyStart of the corresponding parse node
821 //public void notifySourceElementRequestor(FieldDeclaration fieldDeclaration) {
824 // boolean isInRange =
825 // scanner.initialPosition <= fieldDeclaration.declarationSourceStart
826 // && scanner.eofPosition >= fieldDeclaration.declarationSourceEnd;
828 // if (fieldDeclaration.isField()) {
829 // int fieldEndPosition = fieldDeclaration.declarationSourceEnd;
830 // if (fieldDeclaration instanceof SourceFieldDeclaration) {
831 // fieldEndPosition = ((SourceFieldDeclaration) fieldDeclaration).fieldEndPosition;
832 // if (fieldEndPosition == 0) {
833 // // use the declaration source end by default
834 // fieldEndPosition = fieldDeclaration.declarationSourceEnd;
838 // int modifiers = fieldDeclaration.modifiers;
839 // boolean deprecated = (modifiers & AccDeprecated) != 0; // remember deprecation so as to not lose it below
840 // requestor.enterField(
841 // fieldDeclaration.declarationSourceStart,
842 // deprecated ? (modifiers & AccJustFlag) | AccDeprecated : modifiers & AccJustFlag,
843 // returnTypeName(fieldDeclaration.type),
844 // fieldDeclaration.name,
845 // fieldDeclaration.sourceStart,
846 // fieldDeclaration.sourceEnd);
848 // this.visitIfNeeded(fieldDeclaration);
850 // requestor.exitField(
851 // // filter out initializations that are not a constant (simple check)
852 // (fieldDeclaration.initialization == null
853 // || fieldDeclaration.initialization instanceof ArrayInitializer
854 // || fieldDeclaration.initialization instanceof AllocationExpression
855 // || fieldDeclaration.initialization instanceof ArrayAllocationExpression
856 // || fieldDeclaration.initialization instanceof Assignment
857 // || fieldDeclaration.initialization instanceof ClassLiteralAccess
858 // || fieldDeclaration.initialization instanceof MessageSend
859 // || fieldDeclaration.initialization instanceof ArrayReference
860 // || fieldDeclaration.initialization instanceof ThisReference) ?
862 // fieldDeclaration.initialization.sourceStart,
864 // fieldDeclaration.declarationSourceEnd);
869 // requestor.enterInitializer(
870 // fieldDeclaration.declarationSourceStart,
871 // fieldDeclaration.modifiers);
873 // this.visitIfNeeded((Initializer)fieldDeclaration);
875 // requestor.exitInitializer(fieldDeclaration.declarationSourceEnd);
879 //public void notifySourceElementRequestor(
880 // ImportReference importReference,
881 // boolean isPackage) {
883 // requestor.acceptPackage(
884 // importReference.declarationSourceStart,
885 // importReference.declarationSourceEnd,
886 // CharOperation.concatWith(importReference.getImportName(), '.'));
888 // requestor.acceptImport(
889 // importReference.declarationSourceStart,
890 // importReference.declarationSourceEnd,
891 // CharOperation.concatWith(importReference.getImportName(), '.'),
892 // importReference.onDemand);
895 public void notifySourceElementRequestor(TypeDeclaration typeDeclaration, boolean notifyTypePresence) {
896 //// public void notifySourceElementRequestor(AstNode typeDeclaration, boolean notifyTypePresence) {
900 scanner.initialPosition <= typeDeclaration.declarationSourceStart
901 && scanner.eofPosition >= typeDeclaration.declarationSourceEnd;
903 FieldDeclaration[] fields = typeDeclaration.fields;
904 AbstractMethodDeclaration[] methods = typeDeclaration.methods;
905 MemberTypeDeclaration[] memberTypes = typeDeclaration.memberTypes;
906 int fieldCount = fields == null ? 0 : fields.length;
907 int methodCount = methods == null ? 0 : methods.length;
908 int memberTypeCount = memberTypes == null ? 0 : memberTypes.length;
911 int memberTypeIndex = 0;
912 boolean isInterface = typeDeclaration.isInterface();
914 if (notifyTypePresence){
915 char[][] interfaceNames = null;
916 int superInterfacesLength = 0;
917 TypeReference[] superInterfaces = typeDeclaration.superInterfaces;
918 if (superInterfaces != null) {
919 superInterfacesLength = superInterfaces.length;
920 interfaceNames = new char[superInterfacesLength][];
922 if (typeDeclaration instanceof AnonymousLocalTypeDeclaration) {
924 QualifiedAllocationExpression alloc = ((AnonymousLocalTypeDeclaration)typeDeclaration).allocation;
925 if (alloc != null && alloc.type != null) {
926 superInterfaces = new TypeReference[] { ((AnonymousLocalTypeDeclaration)typeDeclaration).allocation.type};
927 superInterfacesLength = 1;
928 interfaceNames = new char[1][];
932 if (superInterfaces != null) {
933 for (int i = 0; i < superInterfacesLength; i++) {
935 CharOperation.concatWith(superInterfaces[i].getTypeName(), '.');
940 int modifiers = typeDeclaration.modifiers;
941 boolean deprecated = false; //(modifiers & AccDeprecated) != 0; // remember deprecation so as to not lose it below
942 requestor.enterInterface(
943 typeDeclaration.declarationSourceStart,
944 modifiers, //deprecated ? (modifiers & AccJustFlag) | AccDeprecated : modifiers & AccJustFlag,
945 typeDeclaration.name,
946 typeDeclaration.sourceStart,
947 typeDeclaration.sourceEnd,
950 if (nestedTypeIndex == typeNames.length) {
952 System.arraycopy(typeNames, 0, (typeNames = new char[nestedTypeIndex * 2][]), 0, nestedTypeIndex);
953 System.arraycopy(superTypeNames, 0, (superTypeNames = new char[nestedTypeIndex * 2][]), 0, nestedTypeIndex);
955 typeNames[nestedTypeIndex] = typeDeclaration.name;
956 superTypeNames[nestedTypeIndex++] = JAVA_LANG_OBJECT;
958 TypeReference superclass = typeDeclaration.superclass;
959 if (superclass == null) {
961 requestor.enterClass(
962 typeDeclaration.declarationSourceStart,
963 typeDeclaration.modifiers,
964 typeDeclaration.name,
965 typeDeclaration.sourceStart,
966 typeDeclaration.sourceEnd,
972 requestor.enterClass(
973 typeDeclaration.declarationSourceStart,
974 typeDeclaration.modifiers,
975 typeDeclaration.name,
976 typeDeclaration.sourceStart,
977 typeDeclaration.sourceEnd,
978 CharOperation.concatWith(superclass.getTypeName(), '.'),
982 if (nestedTypeIndex == typeNames.length) {
984 System.arraycopy(typeNames, 0, (typeNames = new char[nestedTypeIndex * 2][]), 0, nestedTypeIndex);
985 System.arraycopy(superTypeNames, 0, (superTypeNames = new char[nestedTypeIndex * 2][]), 0, nestedTypeIndex);
987 typeNames[nestedTypeIndex] = typeDeclaration.name;
988 superTypeNames[nestedTypeIndex++] = superclass == null ? JAVA_LANG_OBJECT : CharOperation.concatWith(superclass.getTypeName(), '.');
991 while ((fieldIndex < fieldCount)
992 || (memberTypeIndex < memberTypeCount)
993 || (methodIndex < methodCount)) {
994 FieldDeclaration nextFieldDeclaration = null;
995 AbstractMethodDeclaration nextMethodDeclaration = null;
996 TypeDeclaration nextMemberDeclaration = null;
998 int position = Integer.MAX_VALUE;
999 int nextDeclarationType = -1;
1000 if (fieldIndex < fieldCount) {
1001 nextFieldDeclaration = fields[fieldIndex];
1002 if (nextFieldDeclaration.declarationSourceStart < position) {
1003 position = nextFieldDeclaration.declarationSourceStart;
1004 nextDeclarationType = 0; // FIELD
1007 if (methodIndex < methodCount) {
1008 nextMethodDeclaration = methods[methodIndex];
1009 if (nextMethodDeclaration.declarationSourceStart < position) {
1010 position = nextMethodDeclaration.declarationSourceStart;
1011 nextDeclarationType = 1; // METHOD
1014 if (memberTypeIndex < memberTypeCount) {
1015 nextMemberDeclaration = memberTypes[memberTypeIndex];
1016 if (nextMemberDeclaration.declarationSourceStart < position) {
1017 position = nextMemberDeclaration.declarationSourceStart;
1018 nextDeclarationType = 2; // MEMBER
1021 switch (nextDeclarationType) {
1024 // notifySourceElementRequestor(nextFieldDeclaration);
1028 notifySourceElementRequestor(nextMethodDeclaration);
1032 notifySourceElementRequestor(nextMemberDeclaration, true);
1035 if (notifyTypePresence){
1038 requestor.exitInterface(typeDeclaration.declarationSourceEnd);
1040 requestor.exitClass(typeDeclaration.declarationSourceEnd);
1046 public void parseCompilationUnit (
1047 ICompilationUnit unit,
1050 // boolean needReferenceInfo) {
1052 // reportReferenceInfo = needReferenceInfo;
1053 // boolean old = diet;
1054 // if (needReferenceInfo) {
1055 // unknownRefs = new NameReference[10];
1056 // unknownRefsCounter = 0;
1061 CompilationResult compilationUnitResult = new CompilationResult(unit, 0, 0, 10); //this.options.maxProblemsPerUnit);
1062 CompilationUnitDeclaration parsedUnit = parse(unit, compilationUnitResult, start, end);
1063 // if (scanner.recordLineSeparator) {
1064 // requestor.acceptLineSeparatorPositions(scanner.getLineEnds());
1066 // if (this.localDeclarationVisitor != null || needReferenceInfo){
1068 // this.getMethodBodies(parsedUnit);
1070 // this.scanner.resetTo(start, end);
1071 // notifySourceElementRequestor(parsedUnit);
1072 } catch (AbortCompilation e) {
1077 public CompilationUnitDeclaration parseCompilationUnit(
1078 ICompilationUnit unit,
1079 boolean fullParse) {
1081 // boolean old = diet;
1083 // unknownRefs = new NameReference[10];
1084 // unknownRefsCounter = 0;
1089 this.reportReferenceInfo = fullParse;
1090 CompilationResult compilationUnitResult = new CompilationResult(unit, 0, 0, this.options.maxProblemsPerUnit);
1091 CompilationUnitDeclaration parsedUnit = parse(unit, compilationUnitResult, false);
1092 if (scanner.recordLineSeparator) {
1093 requestor.acceptLineSeparatorPositions(scanner.getLineEnds());
1095 int initialStart = this.scanner.initialPosition;
1096 int initialEnd = this.scanner.eofPosition;
1097 // if (this.localDeclarationVisitor != null || fullParse){
1099 // this.getMethodBodies(parsedUnit);
1101 this.scanner.resetTo(initialStart, initialEnd);
1102 notifySourceElementRequestor(parsedUnit);
1104 } catch (AbortCompilation e) {
1105 // ignore this exception
1112 //public void parseTypeMemberDeclarations(
1113 // ISourceType sourceType,
1114 // ICompilationUnit sourceUnit,
1117 // boolean needReferenceInfo) {
1118 // boolean old = diet;
1119 // if (needReferenceInfo) {
1120 // unknownRefs = new NameReference[10];
1121 // unknownRefsCounter = 0;
1125 // diet = !needReferenceInfo;
1126 // reportReferenceInfo = needReferenceInfo;
1127 // CompilationResult compilationUnitResult =
1128 // new CompilationResult(sourceUnit, 0, 0, this.options.maxProblemsPerUnit);
1129 // CompilationUnitDeclaration unit =
1130 // SourceTypeConverter.buildCompilationUnit(
1131 // new ISourceType[]{sourceType},
1132 // false, // no need for field and methods
1133 // false, // no need for member types
1134 // false, // no need for field initialization
1135 // problemReporter(),
1136 // compilationUnitResult);
1137 // if ((unit == null) || (unit.types == null) || (unit.types.length != 1))
1139 // this.sourceType = sourceType;
1141 // /* automaton initialization */
1143 // goForClassBodyDeclarations();
1144 // /* scanner initialization */
1145 // scanner.setSource(sourceUnit.getContents());
1146 // scanner.resetTo(start, end);
1147 // /* unit creation */
1148 // referenceContext = compilationUnit = unit;
1149 // /* initialize the astStacl */
1150 // // the compilationUnitDeclaration should contain exactly one type
1151 // pushOnAstStack(unit.types[0]);
1152 // /* run automaton */
1154 // notifySourceElementRequestor(unit);
1156 // unit = compilationUnit;
1157 // compilationUnit = null; // reset parser
1159 // } catch (AbortCompilation e) {
1161 // if (scanner.recordLineSeparator) {
1162 // requestor.acceptLineSeparatorPositions(scanner.getLineEnds());
1168 //public void parseTypeMemberDeclarations(
1173 // boolean old = diet;
1178 // /* automaton initialization */
1180 // goForClassBodyDeclarations();
1181 // /* scanner initialization */
1182 // scanner.setSource(contents);
1183 // scanner.recordLineSeparator = false;
1184 // scanner.taskTags = null;
1185 // scanner.taskPriorities = null;
1186 // scanner.resetTo(start, end);
1188 // /* unit creation */
1189 // referenceContext = null;
1191 // /* initialize the astStacl */
1192 // // the compilationUnitDeclaration should contain exactly one type
1193 // /* run automaton */
1195 // notifySourceElementRequestor((CompilationUnitDeclaration)null);
1196 // } catch (AbortCompilation e) {
1202 * Sort the given ast nodes by their positions.
1204 private static void quickSort(AstNode[] sortedCollection, int left, int right) {
1205 int original_left = left;
1206 int original_right = right;
1207 AstNode mid = sortedCollection[ (left + right) / 2];
1209 while (sortedCollection[left].sourceStart < mid.sourceStart) {
1212 while (mid.sourceStart < sortedCollection[right].sourceStart) {
1215 if (left <= right) {
1216 AstNode tmp = sortedCollection[left];
1217 sortedCollection[left] = sortedCollection[right];
1218 sortedCollection[right] = tmp;
1222 } while (left <= right);
1223 if (original_left < right) {
1224 quickSort(sortedCollection, original_left, right);
1226 if (left < original_right) {
1227 quickSort(sortedCollection, left, original_right);
1231 * Answer a char array representation of the type name formatted like:
1232 * - type name + dimensions
1234 * "A[][]".toCharArray()
1235 * "java.lang.String".toCharArray()
1237 private char[] returnTypeName(TypeReference type) {
1240 int dimension = type.dimensions();
1241 if (dimension != 0) {
1242 char[] dimensionsArray = new char[dimension * 2];
1243 for (int i = 0; i < dimension; i++) {
1244 dimensionsArray[i * 2] = '[';
1245 dimensionsArray[(i * 2) + 1] = ']';
1247 return CharOperation.concat(
1248 CharOperation.concatWith(type.getTypeName(), '.'),
1251 return CharOperation.concatWith(type.getTypeName(), '.');
1254 public void addUnknownRef(NameReference nameRef) {
1255 if (this.unknownRefs.length == this.unknownRefsCounter) {
1260 (this.unknownRefs = new NameReference[this.unknownRefsCounter * 2]),
1262 this.unknownRefsCounter);
1264 this.unknownRefs[this.unknownRefsCounter++] = nameRef;
1267 private void visitIfNeeded(AbstractMethodDeclaration method) {
1268 if (this.localDeclarationVisitor != null
1269 && (method.bits & AstNode.HasLocalTypeMASK) != 0) {
1270 if (method.statements != null) {
1271 int statementsLength = method.statements.length;
1272 for (int i = 0; i < statementsLength; i++)
1273 method.statements[i].traverse(this.localDeclarationVisitor, method.scope);
1278 //private void visitIfNeeded(FieldDeclaration field) {
1279 // if (this.localDeclarationVisitor != null
1280 // && (field.bits & AstNode.HasLocalTypeMASK) != 0) {
1281 // if (field.initialization != null) {
1282 // field.initialization.traverse(this.localDeclarationVisitor, null);
1287 //private void visitIfNeeded(Initializer initializer) {
1288 // if (this.localDeclarationVisitor != null
1289 // && (initializer.bits & AstNode.HasLocalTypeMASK) != 0) {
1290 // if (initializer.block != null) {
1291 // initializer.block.traverse(this.localDeclarationVisitor, null);
1296 //protected void reportSyntaxError(int act, int currentKind, int stateStackTop) {
1297 // if (compilationUnit == null) return;
1298 // super.reportSyntaxError(act, currentKind,stateStackTop);