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.parser.UnitParser;
24 import net.sourceforge.phpdt.internal.compiler.problem.AbortCompilation;
25 import net.sourceforge.phpdt.internal.compiler.problem.ProblemReporter;
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.LocalTypeDeclaration;
35 import net.sourceforge.phpeclipse.internal.compiler.ast.MemberTypeDeclaration;
36 import net.sourceforge.phpeclipse.internal.compiler.ast.MethodDeclaration;
37 import net.sourceforge.phpeclipse.internal.compiler.ast.NameReference;
38 import net.sourceforge.phpeclipse.internal.compiler.ast.QualifiedAllocationExpression;
39 import net.sourceforge.phpeclipse.internal.compiler.ast.TypeDeclaration;
40 import net.sourceforge.phpeclipse.internal.compiler.ast.TypeReference;
45 * A source element parser extracts structural and reference information
46 * from a piece of source.
48 * also see @ISourceElementRequestor
50 * The structural investigation includes:
51 * - the package statement
53 * - top-level types: package member, member types (member types of member types...)
57 * If reference information is requested, then all source constructs are
58 * investigated and type, field & method references are provided as well.
60 * Any (parsing) problem encountered is also provided.
63 public class SourceElementParser extends UnitParser {
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 == null);
88 // return false; // don't visit members as this was done during notifySourceElementRequestor(...)
90 public boolean visit(LocalTypeDeclaration typeDeclaration, BlockScope scope) {
91 notifySourceElementRequestor(typeDeclaration, sourceType == null);
92 return false; // don't visit members as this was done during notifySourceElementRequestor(...)
94 public boolean visit(MemberTypeDeclaration typeDeclaration, ClassScope scope) {
95 notifySourceElementRequestor(typeDeclaration, sourceType == null);
96 return false; // don't visit members as this was done during notifySourceElementRequestor(...)
101 public SourceElementParser(
102 final ISourceElementRequestor requestor,
103 IProblemFactory problemFactory,
104 CompilerOptions options) {
105 // we want to notify all syntax error with the acceptProblem API
106 // To do so, we define the record method of the ProblemReporter
109 DefaultErrorHandlingPolicies.exitAfterAllProblems(),
112 public void record(IProblem problem, CompilationResult unitResult, ReferenceContext referenceContext) {
113 unitResult.record(problem, referenceContext);
114 requestor.acceptProblem(problem);
118 // options.sourceLevel >= CompilerOptions.JDK1_4);
119 this.requestor = requestor;
120 typeNames = new char[4][];
121 superTypeNames = new char[4][];
123 this.options = options;
126 /** @deprecated use SourceElementParser(ISourceElementRequestor, IProblemFactory, CompilerOptions) */
127 //public SourceElementParser(
128 // final ISourceElementRequestor requestor,
129 // IProblemFactory problemFactory) {
130 // this(requestor, problemFactory, new CompilerOptions());
133 //public SourceElementParser(
134 // final ISourceElementRequestor requestor,
135 // IProblemFactory problemFactory,
136 // CompilerOptions options,
137 // boolean reportLocalDeclarations) {
138 // this(requestor, problemFactory, options);
139 // if (reportLocalDeclarations) {
140 // this.localDeclarationVisitor = new LocalDeclarationVisitor();
144 //public void checkAnnotation() {
145 // int firstCommentIndex = scanner.commentPtr;
147 // super.checkAnnotation();
149 // // modify the modifier source start to point at the first comment
150 // if (firstCommentIndex >= 0) {
151 // modifiersSourceStart = scanner.commentStarts[0];
155 //protected void classInstanceCreation(boolean alwaysQualified) {
157 // boolean previousFlag = reportReferenceInfo;
158 // reportReferenceInfo = false; // not to see the type reference reported in super call to getTypeReference(...)
159 // super.classInstanceCreation(alwaysQualified);
160 // reportReferenceInfo = previousFlag;
161 // if (reportReferenceInfo){
162 // AllocationExpression alloc = (AllocationExpression)expressionStack[expressionPtr];
163 // TypeReference typeRef = alloc.type;
164 // requestor.acceptConstructorReference(
165 // typeRef instanceof SingleTypeReference
166 // ? ((SingleTypeReference) typeRef).token
167 // : CharOperation.concatWith(alloc.type.getTypeName(), '.'),
168 // alloc.arguments == null ? 0 : alloc.arguments.length,
169 // alloc.sourceStart);
172 //protected void consumeConstructorHeaderName() {
173 // // ConstructorHeaderName ::= Modifiersopt 'Identifier' '('
175 // /* recovering - might be an empty message send */
176 // if (currentElement != null){
177 // if (lastIgnoredToken == TokenNamenew){ // was an allocation expression
178 // lastCheckPoint = scanner.startPosition; // force to restart at this exact position
179 // restartRecovery = true;
183 // SourceConstructorDeclaration cd = new SourceConstructorDeclaration(this.compilationUnit.compilationResult);
185 // //name -- this is not really revelant but we do .....
186 // cd.selector = identifierStack[identifierPtr];
187 // long selectorSourcePositions = identifierPositionStack[identifierPtr--];
188 // identifierLengthPtr--;
191 // cd.declarationSourceStart = intStack[intPtr--];
192 // cd.modifiers = intStack[intPtr--];
194 // //highlight starts at the selector starts
195 // cd.sourceStart = (int) (selectorSourcePositions >>> 32);
196 // cd.selectorSourceEnd = (int) selectorSourcePositions;
197 // pushOnAstStack(cd);
199 // cd.sourceEnd = lParenPos;
200 // cd.bodyStart = lParenPos+1;
201 // listLength = 0; // initialize listLength before reading parameters/throws
204 // if (currentElement != null){
205 // lastCheckPoint = cd.bodyStart;
206 // if ((currentElement instanceof RecoveredType && lastIgnoredToken != TokenNameDOT)
207 // || cd.modifiers != 0){
208 // currentElement = currentElement.add(cd, 0);
209 // lastIgnoredToken = -1;
215 // * INTERNAL USE-ONLY
217 //protected void consumeExitVariableWithInitialization() {
218 // // ExitVariableWithInitialization ::= $empty
219 // // the scanner is located after the comma or the semi-colon.
220 // // we want to include the comma or the semi-colon
221 // super.consumeExitVariableWithInitialization();
222 // if (isLocalDeclaration() || ((currentToken != TokenNameCOMMA) && (currentToken != TokenNameSEMICOLON)))
224 // ((SourceFieldDeclaration) astStack[astPtr]).fieldEndPosition = scanner.currentPosition - 1;
226 //protected void consumeExitVariableWithoutInitialization() {
227 // // ExitVariableWithoutInitialization ::= $empty
228 // // do nothing by default
229 // super.consumeExitVariableWithoutInitialization();
230 // if (isLocalDeclaration() || ((currentToken != TokenNameCOMMA) && (currentToken != TokenNameSEMICOLON)))
232 // ((SourceFieldDeclaration) astStack[astPtr]).fieldEndPosition = scanner.currentPosition - 1;
236 // * INTERNAL USE-ONLY
238 //protected void consumeFieldAccess(boolean isSuperAccess) {
239 // // FieldAccess ::= Primary '.' 'Identifier'
240 // // FieldAccess ::= 'super' '.' 'Identifier'
241 // super.consumeFieldAccess(isSuperAccess);
242 // FieldReference fr = (FieldReference) expressionStack[expressionPtr];
243 // if (reportReferenceInfo) {
244 // requestor.acceptFieldReference(fr.token, fr.sourceStart);
247 //protected void consumeMethodHeaderName() {
248 // // MethodHeaderName ::= Modifiersopt Type 'Identifier' '('
249 // SourceMethodDeclaration md = new SourceMethodDeclaration(this.compilationUnit.compilationResult);
252 // md.selector = identifierStack[identifierPtr];
253 // long selectorSourcePositions = identifierPositionStack[identifierPtr--];
254 // identifierLengthPtr--;
256 // md.returnType = getTypeReference(intStack[intPtr--]);
258 // md.declarationSourceStart = intStack[intPtr--];
259 // md.modifiers = intStack[intPtr--];
261 // //highlight starts at selector start
262 // md.sourceStart = (int) (selectorSourcePositions >>> 32);
263 // md.selectorSourceEnd = (int) selectorSourcePositions;
264 // pushOnAstStack(md);
265 // md.sourceEnd = lParenPos;
266 // md.bodyStart = lParenPos+1;
267 // listLength = 0; // initialize listLength before reading parameters/throws
270 // if (currentElement != null){
271 // if (currentElement instanceof RecoveredType
272 // //|| md.modifiers != 0
273 // || (scanner.getLineNumber(md.returnType.sourceStart)
274 // == scanner.getLineNumber(md.sourceStart))){
275 // lastCheckPoint = md.bodyStart;
276 // currentElement = currentElement.add(md, 0);
277 // lastIgnoredToken = -1;
279 // lastCheckPoint = md.sourceStart;
280 // restartRecovery = true;
286 // * INTERNAL USE-ONLY
288 //protected void consumeMethodInvocationName() {
289 // // MethodInvocation ::= Name '(' ArgumentListopt ')'
291 // // when the name is only an identifier...we have a message send to "this" (implicit)
292 // super.consumeMethodInvocationName();
293 // MessageSend messageSend = (MessageSend) expressionStack[expressionPtr];
294 // Expression[] args = messageSend.arguments;
295 // if (reportReferenceInfo) {
296 // requestor.acceptMethodReference(
297 // messageSend.selector,
298 // args == null ? 0 : args.length,
299 // (int)(messageSend.nameSourcePosition >>> 32));
304 // * INTERNAL USE-ONLY
306 //protected void consumeMethodInvocationPrimary() {
307 // super.consumeMethodInvocationPrimary();
308 // MessageSend messageSend = (MessageSend) expressionStack[expressionPtr];
309 // Expression[] args = messageSend.arguments;
310 // if (reportReferenceInfo) {
311 // requestor.acceptMethodReference(
312 // messageSend.selector,
313 // args == null ? 0 : args.length,
314 // (int)(messageSend.nameSourcePosition >>> 32));
319 // * INTERNAL USE-ONLY
321 //protected void consumeMethodInvocationSuper() {
322 // // MethodInvocation ::= 'super' '.' 'Identifier' '(' ArgumentListopt ')'
323 // super.consumeMethodInvocationSuper();
324 // MessageSend messageSend = (MessageSend) expressionStack[expressionPtr];
325 // Expression[] args = messageSend.arguments;
326 // if (reportReferenceInfo) {
327 // requestor.acceptMethodReference(
328 // messageSend.selector,
329 // args == null ? 0 : args.length,
330 // (int)(messageSend.nameSourcePosition >>> 32));
333 //protected void consumeSingleTypeImportDeclarationName() {
334 // // SingleTypeImportDeclarationName ::= 'import' Name
335 // /* push an ImportRef build from the last name
336 // stored in the identifier stack. */
338 // super.consumeSingleTypeImportDeclarationName();
339 // ImportReference impt = (ImportReference)astStack[astPtr];
340 // if (reportReferenceInfo) {
341 // requestor.acceptTypeReference(impt.tokens, impt.sourceStart, impt.sourceEnd);
344 //protected void consumeTypeImportOnDemandDeclarationName() {
345 // // TypeImportOnDemandDeclarationName ::= 'import' Name '.' '*'
346 // /* push an ImportRef build from the last name
347 // stored in the identifier stack. */
349 // super.consumeTypeImportOnDemandDeclarationName();
350 // ImportReference impt = (ImportReference)astStack[astPtr];
351 // if (reportReferenceInfo) {
352 // requestor.acceptUnknownReference(impt.tokens, impt.sourceStart, impt.sourceEnd);
355 //protected FieldDeclaration createFieldDeclaration(Expression initialization, char[] name, int sourceStart, int sourceEnd) {
356 // return new SourceFieldDeclaration(null, name, sourceStart, sourceEnd);
358 //protected CompilationUnitDeclaration endParse(int act) {
359 // if (sourceType != null) {
360 // if (sourceType.isInterface()) {
361 // consumeInterfaceDeclaration();
363 // consumeClassDeclaration();
366 // if (compilationUnit != null) {
367 // CompilationUnitDeclaration result = super.endParse(act);
374 * Flush annotations defined prior to a given positions.
376 * Note: annotations are stacked in syntactical order
378 * Either answer given <position>, or the end position of a comment line
379 * immediately following the <position> (same line)
383 * } // end of method foo
386 //public int flushAnnotationsDefinedPriorTo(int position) {
388 // return lastFieldEndPosition = super.flushAnnotationsDefinedPriorTo(position);
390 //public TypeReference getTypeReference(int dim) {
391 // /* build a Reference on a variable that may be qualified or not
392 // * This variable is a type reference and dim will be its dimensions
395 // if ((length = identifierLengthStack[identifierLengthPtr--]) == 1) {
396 // // single variable reference
398 // SingleTypeReference ref =
399 // new SingleTypeReference(
400 // identifierStack[identifierPtr],
401 // identifierPositionStack[identifierPtr--]);
402 // if (reportReferenceInfo) {
403 // requestor.acceptTypeReference(ref.token, ref.sourceStart);
407 // ArrayTypeReference ref =
408 // new ArrayTypeReference(
409 // identifierStack[identifierPtr],
411 // identifierPositionStack[identifierPtr--]);
412 // ref.sourceEnd = endPosition;
413 // if (reportReferenceInfo) {
414 // requestor.acceptTypeReference(ref.token, ref.sourceStart);
419 // if (length < 0) { //flag for precompiled type reference on base types
420 // TypeReference ref = TypeReference.baseTypeReference(-length, dim);
421 // ref.sourceStart = intStack[intPtr--];
423 // ref.sourceEnd = intStack[intPtr--];
425 // intPtr--; // no need to use this position as it is an array
426 // ref.sourceEnd = endPosition;
428 // if (reportReferenceInfo){
429 // requestor.acceptTypeReference(ref.getTypeName(), ref.sourceStart, ref.sourceEnd);
432 // } else { //Qualified variable reference
433 // char[][] tokens = new char[length][];
434 // identifierPtr -= length;
435 // long[] positions = new long[length];
436 // System.arraycopy(identifierStack, identifierPtr + 1, tokens, 0, length);
438 // identifierPositionStack,
439 // identifierPtr + 1,
444 // QualifiedTypeReference ref = new QualifiedTypeReference(tokens, positions);
445 // if (reportReferenceInfo) {
446 // requestor.acceptTypeReference(ref.tokens, ref.sourceStart, ref.sourceEnd);
450 // ArrayQualifiedTypeReference ref =
451 // new ArrayQualifiedTypeReference(tokens, dim, positions);
452 // ref.sourceEnd = endPosition;
453 // if (reportReferenceInfo) {
454 // requestor.acceptTypeReference(ref.tokens, ref.sourceStart, ref.sourceEnd);
461 //public NameReference getUnspecifiedReference() {
462 // /* build a (unspecified) NameReference which may be qualified*/
465 // if ((length = identifierLengthStack[identifierLengthPtr--]) == 1) {
466 // // single variable reference
467 // SingleNameReference ref =
468 // new SingleNameReference(
469 // identifierStack[identifierPtr],
470 // identifierPositionStack[identifierPtr--]);
471 // if (reportReferenceInfo) {
472 // this.addUnknownRef(ref);
476 // //Qualified variable reference
477 // char[][] tokens = new char[length][];
478 // identifierPtr -= length;
479 // System.arraycopy(identifierStack, identifierPtr + 1, tokens, 0, length);
480 // QualifiedNameReference ref =
481 // new QualifiedNameReference(
483 // (int) (identifierPositionStack[identifierPtr + 1] >> 32), // sourceStart
484 // (int) identifierPositionStack[identifierPtr + length]); // sourceEnd
485 // if (reportReferenceInfo) {
486 // this.addUnknownRef(ref);
491 //public NameReference getUnspecifiedReferenceOptimized() {
492 // /* build a (unspecified) NameReference which may be qualified
493 // The optimization occurs for qualified reference while we are
494 // certain in this case the last item of the qualified name is
495 // a field access. This optimization is IMPORTANT while it results
496 // that when a NameReference is build, the type checker should always
497 // look for that it is not a type reference */
500 // if ((length = identifierLengthStack[identifierLengthPtr--]) == 1) {
501 // // single variable reference
502 // SingleNameReference ref =
503 // new SingleNameReference(
504 // identifierStack[identifierPtr],
505 // identifierPositionStack[identifierPtr--]);
506 // ref.bits &= ~AstNode.RestrictiveFlagMASK;
507 // ref.bits |= LOCAL | FIELD;
508 // if (reportReferenceInfo) {
509 // this.addUnknownRef(ref);
514 // //Qualified-variable-reference
515 // //In fact it is variable-reference DOT field-ref , but it would result in a type
516 // //conflict tha can be only reduce by making a superclass (or inetrface ) between
517 // //nameReference and FiledReference or putting FieldReference under NameReference
518 // //or else..........This optimisation is not really relevant so just leave as it is
520 // char[][] tokens = new char[length][];
521 // identifierPtr -= length;
522 // System.arraycopy(identifierStack, identifierPtr + 1, tokens, 0, length);
523 // QualifiedNameReference ref =
524 // new QualifiedNameReference(
526 // (int) (identifierPositionStack[identifierPtr + 1] >> 32),
528 // (int) identifierPositionStack[identifierPtr + length]); // sourceEnd
529 // ref.bits &= ~AstNode.RestrictiveFlagMASK;
530 // ref.bits |= LOCAL | FIELD;
531 // if (reportReferenceInfo) {
532 // this.addUnknownRef(ref);
538 // * INTERNAL USE-ONLY
540 //private boolean isLocalDeclaration() {
541 // int nestedDepth = nestedType;
542 // while (nestedDepth >= 0) {
543 // if (nestedMethod[nestedDepth] != 0) {
551 * Update the bodyStart of the corresponding parse node
553 public void notifySourceElementRequestor(CompilationUnitDeclaration parsedUnit) {
554 if (parsedUnit == null) {
555 // when we parse a single type member declaration the compilation unit is null, but we still
556 // want to be able to notify the requestor on the created ast node
557 if (astStack[0] instanceof AbstractMethodDeclaration) {
558 notifySourceElementRequestor((AbstractMethodDeclaration) astStack[0]);
565 scanner.initialPosition <= parsedUnit.sourceStart
566 && scanner.eofPosition >= parsedUnit.sourceEnd;
568 // if (reportReferenceInfo) {
569 // notifyAllUnknownReferences();
571 // collect the top level ast nodes
573 AstNode[] nodes = null;
574 if (sourceType == null){
576 requestor.enterCompilationUnit();
578 // ImportReference currentPackage = parsedUnit.currentPackage;
579 // ImportReference[] imports = parsedUnit.imports;
580 // TypeDeclaration[] types = parsedUnit.types;
581 ArrayList types = parsedUnit.types;
584 // (currentPackage == null ? 0 : 1)
585 // + (imports == null ? 0 : imports.length)
586 // + (types == null ? 0 : types.length);
587 // nodes = new AstNode[length];
588 length = types.size();
589 nodes = new AstNode[length];
591 // if (currentPackage != null) {
592 // nodes[index++] = currentPackage;
594 // if (imports != null) {
595 // for (int i = 0, max = imports.length; i < max; i++) {
596 // nodes[index++] = imports[i];
600 for (int i = 0, max = types.size(); i < max; i++) {
601 nodes[index++] = (AstNode)types.get(i);
605 // TypeDeclaration[] types = parsedUnit.types;
606 ArrayList types = parsedUnit.types;
608 length = types.size();
609 nodes = new AstNode[length];
610 for (int i = 0, max = types.size(); i < max; i++) {
611 nodes[i] = (AstNode)types.get(i);
616 // notify the nodes in the syntactical order
617 if (nodes != null && length > 0) {
618 quickSort(nodes, 0, length-1);
619 for (int i=0;i<length;i++) {
620 AstNode node = nodes[i];
621 // if (node instanceof ImportReference) {
622 // ImportReference importRef = (ImportReference)node;
623 // if (node == parsedUnit.currentPackage) {
624 // notifySourceElementRequestor(importRef, true);
626 // notifySourceElementRequestor(importRef, false);
628 // } else { // instanceof TypeDeclaration
629 if (node instanceof TypeDeclaration) {
630 notifySourceElementRequestor((TypeDeclaration)node, sourceType == null);
631 // notifySourceElementRequestor((CompilationUnitDeclaration)node, sourceType == null);
633 // jsurfer - INSERT start
634 if (node instanceof AbstractMethodDeclaration) {
635 notifySourceElementRequestor((AbstractMethodDeclaration)node);
637 // jsurfer - INSERT end
641 if (sourceType == null){
643 requestor.exitCompilationUnit(parsedUnit.sourceEnd);
648 //private void notifyAllUnknownReferences() {
649 // for (int i = 0, max = this.unknownRefsCounter; i < max; i++) {
650 // NameReference nameRef = this.unknownRefs[i];
651 // if ((nameRef.bits & BindingIds.VARIABLE) != 0) {
652 // if ((nameRef.bits & BindingIds.TYPE) == 0) {
653 // // variable but not type
654 // if (nameRef instanceof SingleNameReference) {
655 // // local var or field
656 // requestor.acceptUnknownReference(((SingleNameReference) nameRef).token, nameRef.sourceStart);
658 // // QualifiedNameReference
659 // // The last token is a field reference and the previous tokens are a type/variable references
660 // char[][] tokens = ((QualifiedNameReference) nameRef).tokens;
661 // int tokensLength = tokens.length;
662 // requestor.acceptFieldReference(tokens[tokensLength - 1], nameRef.sourceEnd - tokens[tokensLength - 1].length + 1);
663 // char[][] typeRef = new char[tokensLength - 1][];
664 // System.arraycopy(tokens, 0, typeRef, 0, tokensLength - 1);
665 // requestor.acceptUnknownReference(typeRef, nameRef.sourceStart, nameRef.sourceEnd - tokens[tokensLength - 1].length);
668 // // variable or type
669 // if (nameRef instanceof SingleNameReference) {
670 // requestor.acceptUnknownReference(((SingleNameReference) nameRef).token, nameRef.sourceStart);
672 // //QualifiedNameReference
673 // requestor.acceptUnknownReference(((QualifiedNameReference) nameRef).tokens, nameRef.sourceStart, nameRef.sourceEnd);
676 // } else if ((nameRef.bits & BindingIds.TYPE) != 0) {
677 // if (nameRef instanceof SingleNameReference) {
678 // requestor.acceptTypeReference(((SingleNameReference) nameRef).token, nameRef.sourceStart);
680 // // it is a QualifiedNameReference
681 // requestor.acceptTypeReference(((QualifiedNameReference) nameRef).tokens, nameRef.sourceStart, nameRef.sourceEnd);
687 * Update the bodyStart of the corresponding parse node
689 public void notifySourceElementRequestor(AbstractMethodDeclaration methodDeclaration) {
693 scanner.initialPosition <= methodDeclaration.declarationSourceStart
694 && scanner.eofPosition >= methodDeclaration.declarationSourceEnd;
696 if (methodDeclaration.isClinit()) {
697 this.visitIfNeeded(methodDeclaration);
701 if (methodDeclaration.isDefaultConstructor()) {
702 if (reportReferenceInfo) {
703 ConstructorDeclaration constructorDeclaration = (ConstructorDeclaration) methodDeclaration;
704 ExplicitConstructorCall constructorCall = constructorDeclaration.constructorCall;
705 if (constructorCall != null) {
706 switch(constructorCall.accessMode) {
707 case ExplicitConstructorCall.This :
708 requestor.acceptConstructorReference(
709 typeNames[nestedTypeIndex-1],
710 constructorCall.arguments == null ? 0 : constructorCall.arguments.length,
711 constructorCall.sourceStart);
713 case ExplicitConstructorCall.Super :
714 case ExplicitConstructorCall.ImplicitSuper :
715 requestor.acceptConstructorReference(
716 superTypeNames[nestedTypeIndex-1],
717 constructorCall.arguments == null ? 0 : constructorCall.arguments.length,
718 constructorCall.sourceStart);
725 char[][] argumentTypes = null;
726 char[][] argumentNames = null;
727 Argument[] arguments = methodDeclaration.arguments;
728 if (arguments != null) {
729 int argumentLength = arguments.length;
730 argumentTypes = new char[argumentLength][];
731 argumentNames = new char[argumentLength][];
732 for (int i = 0; i < argumentLength; i++) {
733 argumentTypes[i] = returnTypeName(arguments[i].type);
734 argumentNames[i] = arguments[i].name;
737 char[][] thrownExceptionTypes = null;
738 TypeReference[] thrownExceptions = methodDeclaration.thrownExceptions;
739 if (thrownExceptions != null) {
740 int thrownExceptionLength = thrownExceptions.length;
741 thrownExceptionTypes = new char[thrownExceptionLength][];
742 for (int i = 0; i < thrownExceptionLength; i++) {
743 thrownExceptionTypes[i] =
744 CharOperation.concatWith(thrownExceptions[i].getTypeName(), '.');
747 // by default no selector end position
748 int selectorSourceEnd = -1;
749 if (methodDeclaration.isConstructor()) {
750 // if (methodDeclaration instanceof SourceConstructorDeclaration) {
751 // selectorSourceEnd =
752 // ((SourceConstructorDeclaration) methodDeclaration).selectorSourceEnd;
755 requestor.enterConstructor(
756 methodDeclaration.declarationSourceStart,
757 methodDeclaration.modifiers,
758 methodDeclaration.selector,
759 methodDeclaration.sourceStart,
763 thrownExceptionTypes);
765 if (reportReferenceInfo) {
766 ConstructorDeclaration constructorDeclaration = (ConstructorDeclaration) methodDeclaration;
767 ExplicitConstructorCall constructorCall = constructorDeclaration.constructorCall;
768 if (constructorCall != null) {
769 switch(constructorCall.accessMode) {
770 case ExplicitConstructorCall.This :
771 requestor.acceptConstructorReference(
772 typeNames[nestedTypeIndex-1],
773 constructorCall.arguments == null ? 0 : constructorCall.arguments.length,
774 constructorCall.sourceStart);
776 case ExplicitConstructorCall.Super :
777 case ExplicitConstructorCall.ImplicitSuper :
778 requestor.acceptConstructorReference(
779 superTypeNames[nestedTypeIndex-1],
780 constructorCall.arguments == null ? 0 : constructorCall.arguments.length,
781 constructorCall.sourceStart);
786 this.visitIfNeeded(methodDeclaration);
788 requestor.exitConstructor(methodDeclaration.declarationSourceEnd);
792 // if (methodDeclaration instanceof SourceMethodDeclaration) {
793 // selectorSourceEnd =
794 // ((SourceMethodDeclaration) methodDeclaration).selectorSourceEnd;
797 int modifiers = methodDeclaration.modifiers;
798 // boolean deprecated = (modifiers & AccDeprecated) != 0; // remember deprecation so as to not lose it below
799 requestor.enterMethod(
800 methodDeclaration.declarationSourceStart,
801 modifiers, // deprecated ? (modifiers & AccJustFlag) | AccDeprecated : modifiers & AccJustFlag,
802 returnTypeName(((MethodDeclaration) methodDeclaration).returnType),
803 methodDeclaration.selector,
804 methodDeclaration.sourceStart,
808 thrownExceptionTypes);
810 this.visitIfNeeded(methodDeclaration);
813 requestor.exitMethod(methodDeclaration.declarationSourceEnd);
817 //* Update the bodyStart of the corresponding parse node
819 //public void notifySourceElementRequestor(FieldDeclaration fieldDeclaration) {
822 // boolean isInRange =
823 // scanner.initialPosition <= fieldDeclaration.declarationSourceStart
824 // && scanner.eofPosition >= fieldDeclaration.declarationSourceEnd;
826 // if (fieldDeclaration.isField()) {
827 // int fieldEndPosition = fieldDeclaration.declarationSourceEnd;
828 // if (fieldDeclaration instanceof SourceFieldDeclaration) {
829 // fieldEndPosition = ((SourceFieldDeclaration) fieldDeclaration).fieldEndPosition;
830 // if (fieldEndPosition == 0) {
831 // // use the declaration source end by default
832 // fieldEndPosition = fieldDeclaration.declarationSourceEnd;
836 // int modifiers = fieldDeclaration.modifiers;
837 // boolean deprecated = (modifiers & AccDeprecated) != 0; // remember deprecation so as to not lose it below
838 // requestor.enterField(
839 // fieldDeclaration.declarationSourceStart,
840 // deprecated ? (modifiers & AccJustFlag) | AccDeprecated : modifiers & AccJustFlag,
841 // returnTypeName(fieldDeclaration.type),
842 // fieldDeclaration.name,
843 // fieldDeclaration.sourceStart,
844 // fieldDeclaration.sourceEnd);
846 // this.visitIfNeeded(fieldDeclaration);
848 // requestor.exitField(
849 // // filter out initializations that are not a constant (simple check)
850 // (fieldDeclaration.initialization == null
851 // || fieldDeclaration.initialization instanceof ArrayInitializer
852 // || fieldDeclaration.initialization instanceof AllocationExpression
853 // || fieldDeclaration.initialization instanceof ArrayAllocationExpression
854 // || fieldDeclaration.initialization instanceof Assignment
855 // || fieldDeclaration.initialization instanceof ClassLiteralAccess
856 // || fieldDeclaration.initialization instanceof MessageSend
857 // || fieldDeclaration.initialization instanceof ArrayReference
858 // || fieldDeclaration.initialization instanceof ThisReference) ?
860 // fieldDeclaration.initialization.sourceStart,
862 // fieldDeclaration.declarationSourceEnd);
867 // requestor.enterInitializer(
868 // fieldDeclaration.declarationSourceStart,
869 // fieldDeclaration.modifiers);
871 // this.visitIfNeeded((Initializer)fieldDeclaration);
873 // requestor.exitInitializer(fieldDeclaration.declarationSourceEnd);
877 //public void notifySourceElementRequestor(
878 // ImportReference importReference,
879 // boolean isPackage) {
881 // requestor.acceptPackage(
882 // importReference.declarationSourceStart,
883 // importReference.declarationSourceEnd,
884 // CharOperation.concatWith(importReference.getImportName(), '.'));
886 // requestor.acceptImport(
887 // importReference.declarationSourceStart,
888 // importReference.declarationSourceEnd,
889 // CharOperation.concatWith(importReference.getImportName(), '.'),
890 // importReference.onDemand);
893 public void notifySourceElementRequestor(TypeDeclaration typeDeclaration, boolean notifyTypePresence) {
894 //// public void notifySourceElementRequestor(AstNode typeDeclaration, boolean notifyTypePresence) {
898 scanner.initialPosition <= typeDeclaration.declarationSourceStart
899 && scanner.eofPosition >= typeDeclaration.declarationSourceEnd;
901 FieldDeclaration[] fields = typeDeclaration.fields;
902 AbstractMethodDeclaration[] methods = typeDeclaration.methods;
903 MemberTypeDeclaration[] memberTypes = typeDeclaration.memberTypes;
904 int fieldCount = fields == null ? 0 : fields.length;
905 int methodCount = methods == null ? 0 : methods.length;
906 int memberTypeCount = memberTypes == null ? 0 : memberTypes.length;
909 int memberTypeIndex = 0;
910 boolean isInterface = typeDeclaration.isInterface();
912 if (notifyTypePresence){
913 char[][] interfaceNames = null;
914 int superInterfacesLength = 0;
915 TypeReference[] superInterfaces = typeDeclaration.superInterfaces;
916 if (superInterfaces != null) {
917 superInterfacesLength = superInterfaces.length;
918 interfaceNames = new char[superInterfacesLength][];
920 if (typeDeclaration instanceof AnonymousLocalTypeDeclaration) {
922 QualifiedAllocationExpression alloc = ((AnonymousLocalTypeDeclaration)typeDeclaration).allocation;
923 if (alloc != null && alloc.type != null) {
924 superInterfaces = new TypeReference[] { ((AnonymousLocalTypeDeclaration)typeDeclaration).allocation.type};
925 superInterfacesLength = 1;
926 interfaceNames = new char[1][];
930 if (superInterfaces != null) {
931 for (int i = 0; i < superInterfacesLength; i++) {
933 CharOperation.concatWith(superInterfaces[i].getTypeName(), '.');
938 int modifiers = typeDeclaration.modifiers;
939 boolean deprecated = false; //(modifiers & AccDeprecated) != 0; // remember deprecation so as to not lose it below
940 requestor.enterInterface(
941 typeDeclaration.declarationSourceStart,
942 modifiers, //deprecated ? (modifiers & AccJustFlag) | AccDeprecated : modifiers & AccJustFlag,
943 typeDeclaration.name,
944 typeDeclaration.sourceStart,
945 typeDeclaration.sourceEnd,
948 if (nestedTypeIndex == typeNames.length) {
950 System.arraycopy(typeNames, 0, (typeNames = new char[nestedTypeIndex * 2][]), 0, nestedTypeIndex);
951 System.arraycopy(superTypeNames, 0, (superTypeNames = new char[nestedTypeIndex * 2][]), 0, nestedTypeIndex);
953 typeNames[nestedTypeIndex] = typeDeclaration.name;
954 superTypeNames[nestedTypeIndex++] = JAVA_LANG_OBJECT;
956 TypeReference superclass = typeDeclaration.superclass;
957 if (superclass == null) {
959 requestor.enterClass(
960 typeDeclaration.declarationSourceStart,
961 typeDeclaration.modifiers,
962 typeDeclaration.name,
963 typeDeclaration.sourceStart,
964 typeDeclaration.sourceEnd,
970 requestor.enterClass(
971 typeDeclaration.declarationSourceStart,
972 typeDeclaration.modifiers,
973 typeDeclaration.name,
974 typeDeclaration.sourceStart,
975 typeDeclaration.sourceEnd,
976 CharOperation.concatWith(superclass.getTypeName(), '.'),
980 if (nestedTypeIndex == typeNames.length) {
982 System.arraycopy(typeNames, 0, (typeNames = new char[nestedTypeIndex * 2][]), 0, nestedTypeIndex);
983 System.arraycopy(superTypeNames, 0, (superTypeNames = new char[nestedTypeIndex * 2][]), 0, nestedTypeIndex);
985 typeNames[nestedTypeIndex] = typeDeclaration.name;
986 superTypeNames[nestedTypeIndex++] = superclass == null ? JAVA_LANG_OBJECT : CharOperation.concatWith(superclass.getTypeName(), '.');
989 while ((fieldIndex < fieldCount)
990 || (memberTypeIndex < memberTypeCount)
991 || (methodIndex < methodCount)) {
992 FieldDeclaration nextFieldDeclaration = null;
993 AbstractMethodDeclaration nextMethodDeclaration = null;
994 TypeDeclaration nextMemberDeclaration = null;
996 int position = Integer.MAX_VALUE;
997 int nextDeclarationType = -1;
998 if (fieldIndex < fieldCount) {
999 nextFieldDeclaration = fields[fieldIndex];
1000 if (nextFieldDeclaration.declarationSourceStart < position) {
1001 position = nextFieldDeclaration.declarationSourceStart;
1002 nextDeclarationType = 0; // FIELD
1005 if (methodIndex < methodCount) {
1006 nextMethodDeclaration = methods[methodIndex];
1007 if (nextMethodDeclaration.declarationSourceStart < position) {
1008 position = nextMethodDeclaration.declarationSourceStart;
1009 nextDeclarationType = 1; // METHOD
1012 if (memberTypeIndex < memberTypeCount) {
1013 nextMemberDeclaration = memberTypes[memberTypeIndex];
1014 if (nextMemberDeclaration.declarationSourceStart < position) {
1015 position = nextMemberDeclaration.declarationSourceStart;
1016 nextDeclarationType = 2; // MEMBER
1019 switch (nextDeclarationType) {
1022 // notifySourceElementRequestor(nextFieldDeclaration);
1026 notifySourceElementRequestor(nextMethodDeclaration);
1030 notifySourceElementRequestor(nextMemberDeclaration, true);
1033 if (notifyTypePresence){
1036 requestor.exitInterface(typeDeclaration.declarationSourceEnd);
1038 requestor.exitClass(typeDeclaration.declarationSourceEnd);
1044 public void parseCompilationUnit (
1045 ICompilationUnit unit,
1048 // boolean needReferenceInfo) {
1050 // reportReferenceInfo = needReferenceInfo;
1051 // boolean old = diet;
1052 // if (needReferenceInfo) {
1053 // unknownRefs = new NameReference[10];
1054 // unknownRefsCounter = 0;
1059 CompilationResult compilationUnitResult = new CompilationResult(unit, 0, 0, 10); //this.options.maxProblemsPerUnit);
1060 CompilationUnitDeclaration parsedUnit = parse(unit, compilationUnitResult, start, end);
1061 // if (scanner.recordLineSeparator) {
1062 // requestor.acceptLineSeparatorPositions(scanner.getLineEnds());
1064 // if (this.localDeclarationVisitor != null || needReferenceInfo){
1066 // this.getMethodBodies(parsedUnit);
1068 // this.scanner.resetTo(start, end);
1069 // notifySourceElementRequestor(parsedUnit);
1070 } catch (AbortCompilation e) {
1075 public void parseCompilationUnit(
1076 ICompilationUnit unit,
1077 boolean needReferenceInfo) {
1078 // boolean old = diet;
1079 // if (needReferenceInfo) {
1080 // unknownRefs = new NameReference[10];
1081 // unknownRefsCounter = 0;
1086 reportReferenceInfo = needReferenceInfo;
1087 CompilationResult compilationUnitResult = new CompilationResult(unit, 0, 0, 10); //this.options.maxProblemsPerUnit);
1088 CompilationUnitDeclaration parsedUnit = parse(unit, compilationUnitResult, false);
1089 if (scanner.recordLineSeparator) {
1090 requestor.acceptLineSeparatorPositions(scanner.getLineEnds());
1092 int initialStart = this.scanner.initialPosition;
1093 int initialEnd = this.scanner.eofPosition;
1094 // if (this.localDeclarationVisitor != null || needReferenceInfo){
1096 // this.getMethodBodies(parsedUnit);
1098 this.scanner.resetTo(initialStart, initialEnd);
1099 notifySourceElementRequestor(parsedUnit);
1100 } catch (AbortCompilation e) {
1105 //public void parseTypeMemberDeclarations(
1106 // ISourceType sourceType,
1107 // ICompilationUnit sourceUnit,
1110 // boolean needReferenceInfo) {
1111 // boolean old = diet;
1112 // if (needReferenceInfo) {
1113 // unknownRefs = new NameReference[10];
1114 // unknownRefsCounter = 0;
1118 // diet = !needReferenceInfo;
1119 // reportReferenceInfo = needReferenceInfo;
1120 // CompilationResult compilationUnitResult =
1121 // new CompilationResult(sourceUnit, 0, 0, this.options.maxProblemsPerUnit);
1122 // CompilationUnitDeclaration unit =
1123 // SourceTypeConverter.buildCompilationUnit(
1124 // new ISourceType[]{sourceType},
1125 // false, // no need for field and methods
1126 // false, // no need for member types
1127 // false, // no need for field initialization
1128 // problemReporter(),
1129 // compilationUnitResult);
1130 // if ((unit == null) || (unit.types == null) || (unit.types.length != 1))
1132 // this.sourceType = sourceType;
1134 // /* automaton initialization */
1136 // goForClassBodyDeclarations();
1137 // /* scanner initialization */
1138 // scanner.setSource(sourceUnit.getContents());
1139 // scanner.resetTo(start, end);
1140 // /* unit creation */
1141 // referenceContext = compilationUnit = unit;
1142 // /* initialize the astStacl */
1143 // // the compilationUnitDeclaration should contain exactly one type
1144 // pushOnAstStack(unit.types[0]);
1145 // /* run automaton */
1147 // notifySourceElementRequestor(unit);
1149 // unit = compilationUnit;
1150 // compilationUnit = null; // reset parser
1152 // } catch (AbortCompilation e) {
1154 // if (scanner.recordLineSeparator) {
1155 // requestor.acceptLineSeparatorPositions(scanner.getLineEnds());
1161 //public void parseTypeMemberDeclarations(
1166 // boolean old = diet;
1171 // /* automaton initialization */
1173 // goForClassBodyDeclarations();
1174 // /* scanner initialization */
1175 // scanner.setSource(contents);
1176 // scanner.recordLineSeparator = false;
1177 // scanner.taskTags = null;
1178 // scanner.taskPriorities = null;
1179 // scanner.resetTo(start, end);
1181 // /* unit creation */
1182 // referenceContext = null;
1184 // /* initialize the astStacl */
1185 // // the compilationUnitDeclaration should contain exactly one type
1186 // /* run automaton */
1188 // notifySourceElementRequestor((CompilationUnitDeclaration)null);
1189 // } catch (AbortCompilation e) {
1195 * Sort the given ast nodes by their positions.
1197 private static void quickSort(AstNode[] sortedCollection, int left, int right) {
1198 int original_left = left;
1199 int original_right = right;
1200 AstNode mid = sortedCollection[ (left + right) / 2];
1202 while (sortedCollection[left].sourceStart < mid.sourceStart) {
1205 while (mid.sourceStart < sortedCollection[right].sourceStart) {
1208 if (left <= right) {
1209 AstNode tmp = sortedCollection[left];
1210 sortedCollection[left] = sortedCollection[right];
1211 sortedCollection[right] = tmp;
1215 } while (left <= right);
1216 if (original_left < right) {
1217 quickSort(sortedCollection, original_left, right);
1219 if (left < original_right) {
1220 quickSort(sortedCollection, left, original_right);
1224 * Answer a char array representation of the type name formatted like:
1225 * - type name + dimensions
1227 * "A[][]".toCharArray()
1228 * "java.lang.String".toCharArray()
1230 private char[] returnTypeName(TypeReference type) {
1233 int dimension = type.dimensions();
1234 if (dimension != 0) {
1235 char[] dimensionsArray = new char[dimension * 2];
1236 for (int i = 0; i < dimension; i++) {
1237 dimensionsArray[i * 2] = '[';
1238 dimensionsArray[(i * 2) + 1] = ']';
1240 return CharOperation.concat(
1241 CharOperation.concatWith(type.getTypeName(), '.'),
1244 return CharOperation.concatWith(type.getTypeName(), '.');
1247 public void addUnknownRef(NameReference nameRef) {
1248 if (this.unknownRefs.length == this.unknownRefsCounter) {
1253 (this.unknownRefs = new NameReference[this.unknownRefsCounter * 2]),
1255 this.unknownRefsCounter);
1257 this.unknownRefs[this.unknownRefsCounter++] = nameRef;
1260 private void visitIfNeeded(AbstractMethodDeclaration method) {
1261 if (this.localDeclarationVisitor != null
1262 && (method.bits & AstNode.HasLocalTypeMASK) != 0) {
1263 if (method.statements != null) {
1264 int statementsLength = method.statements.length;
1265 for (int i = 0; i < statementsLength; i++)
1266 method.statements[i].traverse(this.localDeclarationVisitor, method.scope);
1271 //private void visitIfNeeded(FieldDeclaration field) {
1272 // if (this.localDeclarationVisitor != null
1273 // && (field.bits & AstNode.HasLocalTypeMASK) != 0) {
1274 // if (field.initialization != null) {
1275 // field.initialization.traverse(this.localDeclarationVisitor, null);
1280 //private void visitIfNeeded(Initializer initializer) {
1281 // if (this.localDeclarationVisitor != null
1282 // && (initializer.bits & AstNode.HasLocalTypeMASK) != 0) {
1283 // if (initializer.block != null) {
1284 // initializer.block.traverse(this.localDeclarationVisitor, null);
1289 //protected void reportSyntaxError(int act, int currentKind, int stateStackTop) {
1290 // if (compilationUnit == null) return;
1291 // super.reportSyntaxError(act, currentKind,stateStackTop);