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.ReferenceContext;
20 import net.sourceforge.phpdt.internal.compiler.lookup.BlockScope;
21 import net.sourceforge.phpdt.internal.compiler.lookup.ClassScope;
22 import net.sourceforge.phpdt.internal.compiler.parser.UnitParser;
23 import net.sourceforge.phpdt.internal.compiler.problem.AbortCompilation;
24 import net.sourceforge.phpdt.internal.compiler.problem.ProblemReporter;
25 import net.sourceforge.phpeclipse.internal.compiler.ast.AbstractMethodDeclaration;
26 import net.sourceforge.phpeclipse.internal.compiler.ast.AnonymousLocalTypeDeclaration;
27 import net.sourceforge.phpeclipse.internal.compiler.ast.Argument;
28 import net.sourceforge.phpeclipse.internal.compiler.ast.AstNode;
29 import net.sourceforge.phpeclipse.internal.compiler.ast.CompilationUnitDeclaration;
30 import net.sourceforge.phpeclipse.internal.compiler.ast.ConstructorDeclaration;
31 import net.sourceforge.phpeclipse.internal.compiler.ast.ExplicitConstructorCall;
32 import net.sourceforge.phpeclipse.internal.compiler.ast.FieldDeclaration;
33 import net.sourceforge.phpeclipse.internal.compiler.ast.LocalTypeDeclaration;
34 import net.sourceforge.phpeclipse.internal.compiler.ast.MemberTypeDeclaration;
35 import net.sourceforge.phpeclipse.internal.compiler.ast.MethodDeclaration;
36 import net.sourceforge.phpeclipse.internal.compiler.ast.NameReference;
37 import net.sourceforge.phpeclipse.internal.compiler.ast.QualifiedAllocationExpression;
38 import net.sourceforge.phpeclipse.internal.compiler.ast.TypeDeclaration;
39 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 UnitParser {
64 ISourceElementRequestor requestor;
67 int lastFieldEndPosition;
68 ISourceType sourceType;
69 boolean reportReferenceInfo;
71 char[][] superTypeNames;
73 static final char[] JAVA_LANG_OBJECT = "java.lang.Object".toCharArray(); //$NON-NLS-1$
74 NameReference[] unknownRefs;
75 int unknownRefsCounter;
76 LocalDeclarationVisitor localDeclarationVisitor = null;
77 // CompilerOptions options;
80 * An ast visitor that visits local type declarations.
82 public class LocalDeclarationVisitor extends AbstractSyntaxTreeVisitorAdapter {
83 // public boolean visit(
84 // AnonymousLocalTypeDeclaration anonymousTypeDeclaration,
85 // BlockScope scope) {
86 // notifySourceElementRequestor(anonymousTypeDeclaration, sourceType == null);
87 // return false; // don't visit members as this was done during notifySourceElementRequestor(...)
89 public boolean visit(LocalTypeDeclaration typeDeclaration, BlockScope scope) {
90 notifySourceElementRequestor(typeDeclaration, sourceType == null);
91 return false; // don't visit members as this was done during notifySourceElementRequestor(...)
93 public boolean visit(MemberTypeDeclaration typeDeclaration, ClassScope scope) {
94 notifySourceElementRequestor(typeDeclaration, sourceType == null);
95 return false; // don't visit members as this was done during notifySourceElementRequestor(...)
100 public SourceElementParser(
101 final ISourceElementRequestor requestor,
102 IProblemFactory problemFactory) {
103 // CompilerOptions options) {
104 // we want to notify all syntax error with the acceptProblem API
105 // To do so, we define the record method of the ProblemReporter
108 DefaultErrorHandlingPolicies.exitAfterAllProblems(),
111 public void record(IProblem problem, CompilationResult unitResult, ReferenceContext referenceContext) {
112 unitResult.record(problem, referenceContext);
113 requestor.acceptProblem(problem);
117 // options.sourceLevel >= CompilerOptions.JDK1_4);
118 this.requestor = requestor;
119 typeNames = new char[4][];
120 superTypeNames = new char[4][];
122 // this.options = options;
125 /** @deprecated use SourceElementParser(ISourceElementRequestor, IProblemFactory, CompilerOptions) */
126 //public SourceElementParser(
127 // final ISourceElementRequestor requestor,
128 // IProblemFactory problemFactory) {
129 // 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();
143 //public void checkAnnotation() {
144 // int firstCommentIndex = scanner.commentPtr;
146 // super.checkAnnotation();
148 // // modify the modifier source start to point at the first comment
149 // if (firstCommentIndex >= 0) {
150 // modifiersSourceStart = scanner.commentStarts[0];
154 //protected void classInstanceCreation(boolean alwaysQualified) {
156 // boolean previousFlag = reportReferenceInfo;
157 // reportReferenceInfo = false; // not to see the type reference reported in super call to getTypeReference(...)
158 // super.classInstanceCreation(alwaysQualified);
159 // reportReferenceInfo = previousFlag;
160 // if (reportReferenceInfo){
161 // AllocationExpression alloc = (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 position
178 // restartRecovery = true;
182 // SourceConstructorDeclaration cd = new SourceConstructorDeclaration(this.compilationUnit.compilationResult);
184 // //name -- this is not really revelant but we do .....
185 // cd.selector = identifierStack[identifierPtr];
186 // long selectorSourcePositions = identifierPositionStack[identifierPtr--];
187 // identifierLengthPtr--;
190 // cd.declarationSourceStart = intStack[intPtr--];
191 // cd.modifiers = intStack[intPtr--];
193 // //highlight starts at the selector starts
194 // cd.sourceStart = (int) (selectorSourcePositions >>> 32);
195 // cd.selectorSourceEnd = (int) selectorSourcePositions;
196 // pushOnAstStack(cd);
198 // cd.sourceEnd = lParenPos;
199 // cd.bodyStart = lParenPos+1;
200 // listLength = 0; // initialize listLength before reading parameters/throws
203 // if (currentElement != null){
204 // lastCheckPoint = cd.bodyStart;
205 // if ((currentElement instanceof RecoveredType && lastIgnoredToken != TokenNameDOT)
206 // || cd.modifiers != 0){
207 // currentElement = currentElement.add(cd, 0);
208 // lastIgnoredToken = -1;
214 // * INTERNAL USE-ONLY
216 //protected void consumeExitVariableWithInitialization() {
217 // // ExitVariableWithInitialization ::= $empty
218 // // the scanner is located after the comma or the semi-colon.
219 // // we want to include the comma or the semi-colon
220 // super.consumeExitVariableWithInitialization();
221 // if (isLocalDeclaration() || ((currentToken != TokenNameCOMMA) && (currentToken != TokenNameSEMICOLON)))
223 // ((SourceFieldDeclaration) astStack[astPtr]).fieldEndPosition = scanner.currentPosition - 1;
225 //protected void consumeExitVariableWithoutInitialization() {
226 // // ExitVariableWithoutInitialization ::= $empty
227 // // do nothing by default
228 // super.consumeExitVariableWithoutInitialization();
229 // if (isLocalDeclaration() || ((currentToken != TokenNameCOMMA) && (currentToken != TokenNameSEMICOLON)))
231 // ((SourceFieldDeclaration) astStack[astPtr]).fieldEndPosition = scanner.currentPosition - 1;
235 // * INTERNAL USE-ONLY
237 //protected void consumeFieldAccess(boolean isSuperAccess) {
238 // // FieldAccess ::= Primary '.' 'Identifier'
239 // // FieldAccess ::= 'super' '.' 'Identifier'
240 // super.consumeFieldAccess(isSuperAccess);
241 // FieldReference fr = (FieldReference) expressionStack[expressionPtr];
242 // if (reportReferenceInfo) {
243 // requestor.acceptFieldReference(fr.token, fr.sourceStart);
246 //protected void consumeMethodHeaderName() {
247 // // MethodHeaderName ::= Modifiersopt Type 'Identifier' '('
248 // SourceMethodDeclaration md = new SourceMethodDeclaration(this.compilationUnit.compilationResult);
251 // md.selector = identifierStack[identifierPtr];
252 // long selectorSourcePositions = identifierPositionStack[identifierPtr--];
253 // identifierLengthPtr--;
255 // md.returnType = getTypeReference(intStack[intPtr--]);
257 // md.declarationSourceStart = intStack[intPtr--];
258 // md.modifiers = intStack[intPtr--];
260 // //highlight starts at selector start
261 // md.sourceStart = (int) (selectorSourcePositions >>> 32);
262 // md.selectorSourceEnd = (int) selectorSourcePositions;
263 // pushOnAstStack(md);
264 // md.sourceEnd = lParenPos;
265 // md.bodyStart = lParenPos+1;
266 // listLength = 0; // initialize listLength before reading parameters/throws
269 // if (currentElement != null){
270 // if (currentElement instanceof RecoveredType
271 // //|| md.modifiers != 0
272 // || (scanner.getLineNumber(md.returnType.sourceStart)
273 // == scanner.getLineNumber(md.sourceStart))){
274 // lastCheckPoint = md.bodyStart;
275 // currentElement = currentElement.add(md, 0);
276 // lastIgnoredToken = -1;
278 // lastCheckPoint = md.sourceStart;
279 // restartRecovery = true;
285 // * INTERNAL USE-ONLY
287 //protected void consumeMethodInvocationName() {
288 // // MethodInvocation ::= Name '(' ArgumentListopt ')'
290 // // when the name is only an identifier...we have a message send to "this" (implicit)
291 // super.consumeMethodInvocationName();
292 // MessageSend messageSend = (MessageSend) expressionStack[expressionPtr];
293 // Expression[] args = messageSend.arguments;
294 // if (reportReferenceInfo) {
295 // requestor.acceptMethodReference(
296 // messageSend.selector,
297 // args == null ? 0 : args.length,
298 // (int)(messageSend.nameSourcePosition >>> 32));
303 // * INTERNAL USE-ONLY
305 //protected void consumeMethodInvocationPrimary() {
306 // super.consumeMethodInvocationPrimary();
307 // MessageSend messageSend = (MessageSend) expressionStack[expressionPtr];
308 // Expression[] args = messageSend.arguments;
309 // if (reportReferenceInfo) {
310 // requestor.acceptMethodReference(
311 // messageSend.selector,
312 // args == null ? 0 : args.length,
313 // (int)(messageSend.nameSourcePosition >>> 32));
318 // * INTERNAL USE-ONLY
320 //protected void consumeMethodInvocationSuper() {
321 // // MethodInvocation ::= 'super' '.' 'Identifier' '(' ArgumentListopt ')'
322 // super.consumeMethodInvocationSuper();
323 // MessageSend messageSend = (MessageSend) expressionStack[expressionPtr];
324 // Expression[] args = messageSend.arguments;
325 // if (reportReferenceInfo) {
326 // requestor.acceptMethodReference(
327 // messageSend.selector,
328 // args == null ? 0 : args.length,
329 // (int)(messageSend.nameSourcePosition >>> 32));
332 //protected void consumeSingleTypeImportDeclarationName() {
333 // // SingleTypeImportDeclarationName ::= 'import' Name
334 // /* push an ImportRef build from the last name
335 // stored in the identifier stack. */
337 // super.consumeSingleTypeImportDeclarationName();
338 // ImportReference impt = (ImportReference)astStack[astPtr];
339 // if (reportReferenceInfo) {
340 // requestor.acceptTypeReference(impt.tokens, impt.sourceStart, impt.sourceEnd);
343 //protected void consumeTypeImportOnDemandDeclarationName() {
344 // // TypeImportOnDemandDeclarationName ::= 'import' Name '.' '*'
345 // /* push an ImportRef build from the last name
346 // stored in the identifier stack. */
348 // super.consumeTypeImportOnDemandDeclarationName();
349 // ImportReference impt = (ImportReference)astStack[astPtr];
350 // if (reportReferenceInfo) {
351 // requestor.acceptUnknownReference(impt.tokens, impt.sourceStart, impt.sourceEnd);
354 //protected FieldDeclaration createFieldDeclaration(Expression initialization, char[] name, int sourceStart, int sourceEnd) {
355 // return new SourceFieldDeclaration(null, name, sourceStart, sourceEnd);
357 //protected CompilationUnitDeclaration endParse(int act) {
358 // if (sourceType != null) {
359 // if (sourceType.isInterface()) {
360 // consumeInterfaceDeclaration();
362 // consumeClassDeclaration();
365 // if (compilationUnit != null) {
366 // CompilationUnitDeclaration result = super.endParse(act);
373 * Flush annotations defined prior to a given positions.
375 * Note: annotations are stacked in syntactical order
377 * Either answer given <position>, or the end position of a comment line
378 * immediately following the <position> (same line)
382 * } // end of method foo
385 //public int flushAnnotationsDefinedPriorTo(int position) {
387 // return lastFieldEndPosition = super.flushAnnotationsDefinedPriorTo(position);
389 //public TypeReference getTypeReference(int dim) {
390 // /* build a Reference on a variable that may be qualified or not
391 // * This variable is a type reference and dim will be its dimensions
394 // if ((length = identifierLengthStack[identifierLengthPtr--]) == 1) {
395 // // single variable reference
397 // SingleTypeReference ref =
398 // new SingleTypeReference(
399 // identifierStack[identifierPtr],
400 // identifierPositionStack[identifierPtr--]);
401 // if (reportReferenceInfo) {
402 // requestor.acceptTypeReference(ref.token, ref.sourceStart);
406 // ArrayTypeReference ref =
407 // new ArrayTypeReference(
408 // identifierStack[identifierPtr],
410 // identifierPositionStack[identifierPtr--]);
411 // ref.sourceEnd = endPosition;
412 // if (reportReferenceInfo) {
413 // requestor.acceptTypeReference(ref.token, ref.sourceStart);
418 // if (length < 0) { //flag for precompiled type reference on base types
419 // TypeReference ref = TypeReference.baseTypeReference(-length, dim);
420 // ref.sourceStart = intStack[intPtr--];
422 // ref.sourceEnd = intStack[intPtr--];
424 // intPtr--; // no need to use this position as it is an array
425 // ref.sourceEnd = endPosition;
427 // if (reportReferenceInfo){
428 // requestor.acceptTypeReference(ref.getTypeName(), ref.sourceStart, ref.sourceEnd);
431 // } else { //Qualified variable reference
432 // char[][] tokens = new char[length][];
433 // identifierPtr -= length;
434 // long[] positions = new long[length];
435 // System.arraycopy(identifierStack, identifierPtr + 1, tokens, 0, length);
437 // identifierPositionStack,
438 // identifierPtr + 1,
443 // QualifiedTypeReference ref = new QualifiedTypeReference(tokens, positions);
444 // if (reportReferenceInfo) {
445 // requestor.acceptTypeReference(ref.tokens, ref.sourceStart, ref.sourceEnd);
449 // ArrayQualifiedTypeReference ref =
450 // new ArrayQualifiedTypeReference(tokens, dim, positions);
451 // ref.sourceEnd = endPosition;
452 // if (reportReferenceInfo) {
453 // requestor.acceptTypeReference(ref.tokens, ref.sourceStart, ref.sourceEnd);
460 //public NameReference getUnspecifiedReference() {
461 // /* build a (unspecified) NameReference which may be qualified*/
464 // if ((length = identifierLengthStack[identifierLengthPtr--]) == 1) {
465 // // single variable reference
466 // SingleNameReference ref =
467 // new SingleNameReference(
468 // identifierStack[identifierPtr],
469 // identifierPositionStack[identifierPtr--]);
470 // if (reportReferenceInfo) {
471 // this.addUnknownRef(ref);
475 // //Qualified variable reference
476 // char[][] tokens = new char[length][];
477 // identifierPtr -= length;
478 // System.arraycopy(identifierStack, identifierPtr + 1, tokens, 0, length);
479 // QualifiedNameReference ref =
480 // new QualifiedNameReference(
482 // (int) (identifierPositionStack[identifierPtr + 1] >> 32), // sourceStart
483 // (int) identifierPositionStack[identifierPtr + length]); // sourceEnd
484 // if (reportReferenceInfo) {
485 // this.addUnknownRef(ref);
490 //public NameReference getUnspecifiedReferenceOptimized() {
491 // /* build a (unspecified) NameReference which may be qualified
492 // The optimization occurs for qualified reference while we are
493 // certain in this case the last item of the qualified name is
494 // a field access. This optimization is IMPORTANT while it results
495 // that when a NameReference is build, the type checker should always
496 // look for that it is not a type reference */
499 // if ((length = identifierLengthStack[identifierLengthPtr--]) == 1) {
500 // // single variable reference
501 // SingleNameReference ref =
502 // new SingleNameReference(
503 // identifierStack[identifierPtr],
504 // identifierPositionStack[identifierPtr--]);
505 // ref.bits &= ~AstNode.RestrictiveFlagMASK;
506 // ref.bits |= LOCAL | FIELD;
507 // if (reportReferenceInfo) {
508 // this.addUnknownRef(ref);
513 // //Qualified-variable-reference
514 // //In fact it is variable-reference DOT field-ref , but it would result in a type
515 // //conflict tha can be only reduce by making a superclass (or inetrface ) between
516 // //nameReference and FiledReference or putting FieldReference under NameReference
517 // //or else..........This optimisation is not really relevant so just leave as it is
519 // char[][] tokens = new char[length][];
520 // identifierPtr -= length;
521 // System.arraycopy(identifierStack, identifierPtr + 1, tokens, 0, length);
522 // QualifiedNameReference ref =
523 // new QualifiedNameReference(
525 // (int) (identifierPositionStack[identifierPtr + 1] >> 32),
527 // (int) identifierPositionStack[identifierPtr + length]); // sourceEnd
528 // ref.bits &= ~AstNode.RestrictiveFlagMASK;
529 // ref.bits |= LOCAL | FIELD;
530 // if (reportReferenceInfo) {
531 // this.addUnknownRef(ref);
537 // * INTERNAL USE-ONLY
539 //private boolean isLocalDeclaration() {
540 // int nestedDepth = nestedType;
541 // while (nestedDepth >= 0) {
542 // if (nestedMethod[nestedDepth] != 0) {
550 * Update the bodyStart of the corresponding parse node
552 public void notifySourceElementRequestor(CompilationUnitDeclaration parsedUnit) {
553 if (parsedUnit == null) {
554 // when we parse a single type member declaration the compilation unit is null, but we still
555 // want to be able to notify the requestor on the created ast node
556 if (astStack[0] instanceof AbstractMethodDeclaration) {
557 notifySourceElementRequestor((AbstractMethodDeclaration) astStack[0]);
564 scanner.initialPosition <= parsedUnit.sourceStart
565 && scanner.eofPosition >= parsedUnit.sourceEnd;
567 // if (reportReferenceInfo) {
568 // notifyAllUnknownReferences();
570 // collect the top level ast nodes
572 AstNode[] nodes = null;
573 if (sourceType == null){
575 requestor.enterCompilationUnit();
577 // ImportReference currentPackage = parsedUnit.currentPackage;
578 // ImportReference[] imports = parsedUnit.imports;
579 // TypeDeclaration[] types = parsedUnit.types;
580 ArrayList types = parsedUnit.types;
583 // (currentPackage == null ? 0 : 1)
584 // + (imports == null ? 0 : imports.length)
585 // + (types == null ? 0 : types.length);
586 // nodes = new AstNode[length];
587 length = types.size();
588 nodes = new AstNode[length];
590 // if (currentPackage != null) {
591 // nodes[index++] = currentPackage;
593 // if (imports != null) {
594 // for (int i = 0, max = imports.length; i < max; i++) {
595 // nodes[index++] = imports[i];
599 for (int i = 0, max = types.size(); i < max; i++) {
600 nodes[index++] = (AstNode)types.get(i);
604 // TypeDeclaration[] types = parsedUnit.types;
605 ArrayList types = parsedUnit.types;
607 length = types.size();
608 nodes = new AstNode[length];
609 for (int i = 0, max = types.size(); i < max; i++) {
610 nodes[i] = (AstNode)types.get(i);
615 // notify the nodes in the syntactical order
616 if (nodes != null && length > 0) {
617 quickSort(nodes, 0, length-1);
618 for (int i=0;i<length;i++) {
619 AstNode node = nodes[i];
620 // if (node instanceof ImportReference) {
621 // ImportReference importRef = (ImportReference)node;
622 // if (node == parsedUnit.currentPackage) {
623 // notifySourceElementRequestor(importRef, true);
625 // notifySourceElementRequestor(importRef, false);
627 // } else { // instanceof TypeDeclaration
628 if (node instanceof TypeDeclaration) {
629 notifySourceElementRequestor((TypeDeclaration)node, sourceType == null);
630 // notifySourceElementRequestor((CompilationUnitDeclaration)node, sourceType == null);
632 // jsurfer - INSERT start
633 if (node instanceof AbstractMethodDeclaration) {
634 notifySourceElementRequestor((AbstractMethodDeclaration)node);
636 // jsurfer - INSERT end
640 if (sourceType == null){
642 requestor.exitCompilationUnit(parsedUnit.sourceEnd);
647 //private void notifyAllUnknownReferences() {
648 // for (int i = 0, max = this.unknownRefsCounter; i < max; i++) {
649 // NameReference nameRef = this.unknownRefs[i];
650 // if ((nameRef.bits & BindingIds.VARIABLE) != 0) {
651 // if ((nameRef.bits & BindingIds.TYPE) == 0) {
652 // // variable but not type
653 // if (nameRef instanceof SingleNameReference) {
654 // // local var or field
655 // requestor.acceptUnknownReference(((SingleNameReference) nameRef).token, nameRef.sourceStart);
657 // // QualifiedNameReference
658 // // The last token is a field reference and the previous tokens are a type/variable references
659 // char[][] tokens = ((QualifiedNameReference) nameRef).tokens;
660 // int tokensLength = tokens.length;
661 // requestor.acceptFieldReference(tokens[tokensLength - 1], nameRef.sourceEnd - tokens[tokensLength - 1].length + 1);
662 // char[][] typeRef = new char[tokensLength - 1][];
663 // System.arraycopy(tokens, 0, typeRef, 0, tokensLength - 1);
664 // requestor.acceptUnknownReference(typeRef, nameRef.sourceStart, nameRef.sourceEnd - tokens[tokensLength - 1].length);
667 // // variable or type
668 // if (nameRef instanceof SingleNameReference) {
669 // requestor.acceptUnknownReference(((SingleNameReference) nameRef).token, nameRef.sourceStart);
671 // //QualifiedNameReference
672 // requestor.acceptUnknownReference(((QualifiedNameReference) nameRef).tokens, nameRef.sourceStart, nameRef.sourceEnd);
675 // } else if ((nameRef.bits & BindingIds.TYPE) != 0) {
676 // if (nameRef instanceof SingleNameReference) {
677 // requestor.acceptTypeReference(((SingleNameReference) nameRef).token, nameRef.sourceStart);
679 // // it is a QualifiedNameReference
680 // requestor.acceptTypeReference(((QualifiedNameReference) nameRef).tokens, nameRef.sourceStart, nameRef.sourceEnd);
686 * Update the bodyStart of the corresponding parse node
688 public void notifySourceElementRequestor(AbstractMethodDeclaration methodDeclaration) {
692 scanner.initialPosition <= methodDeclaration.declarationSourceStart
693 && scanner.eofPosition >= methodDeclaration.declarationSourceEnd;
695 if (methodDeclaration.isClinit()) {
696 this.visitIfNeeded(methodDeclaration);
700 if (methodDeclaration.isDefaultConstructor()) {
701 if (reportReferenceInfo) {
702 ConstructorDeclaration constructorDeclaration = (ConstructorDeclaration) methodDeclaration;
703 ExplicitConstructorCall constructorCall = constructorDeclaration.constructorCall;
704 if (constructorCall != null) {
705 switch(constructorCall.accessMode) {
706 case ExplicitConstructorCall.This :
707 requestor.acceptConstructorReference(
708 typeNames[nestedTypeIndex-1],
709 constructorCall.arguments == null ? 0 : constructorCall.arguments.length,
710 constructorCall.sourceStart);
712 case ExplicitConstructorCall.Super :
713 case ExplicitConstructorCall.ImplicitSuper :
714 requestor.acceptConstructorReference(
715 superTypeNames[nestedTypeIndex-1],
716 constructorCall.arguments == null ? 0 : constructorCall.arguments.length,
717 constructorCall.sourceStart);
724 char[][] argumentTypes = null;
725 char[][] argumentNames = null;
726 Argument[] arguments = methodDeclaration.arguments;
727 if (arguments != null) {
728 int argumentLength = arguments.length;
729 argumentTypes = new char[argumentLength][];
730 argumentNames = new char[argumentLength][];
731 for (int i = 0; i < argumentLength; i++) {
732 argumentTypes[i] = returnTypeName(arguments[i].type);
733 argumentNames[i] = arguments[i].name;
736 char[][] thrownExceptionTypes = null;
737 TypeReference[] thrownExceptions = methodDeclaration.thrownExceptions;
738 if (thrownExceptions != null) {
739 int thrownExceptionLength = thrownExceptions.length;
740 thrownExceptionTypes = new char[thrownExceptionLength][];
741 for (int i = 0; i < thrownExceptionLength; i++) {
742 thrownExceptionTypes[i] =
743 CharOperation.concatWith(thrownExceptions[i].getTypeName(), '.');
746 // by default no selector end position
747 int selectorSourceEnd = -1;
748 if (methodDeclaration.isConstructor()) {
749 // if (methodDeclaration instanceof SourceConstructorDeclaration) {
750 // selectorSourceEnd =
751 // ((SourceConstructorDeclaration) methodDeclaration).selectorSourceEnd;
754 requestor.enterConstructor(
755 methodDeclaration.declarationSourceStart,
756 methodDeclaration.modifiers,
757 methodDeclaration.selector,
758 methodDeclaration.sourceStart,
762 thrownExceptionTypes);
764 if (reportReferenceInfo) {
765 ConstructorDeclaration constructorDeclaration = (ConstructorDeclaration) methodDeclaration;
766 ExplicitConstructorCall constructorCall = constructorDeclaration.constructorCall;
767 if (constructorCall != null) {
768 switch(constructorCall.accessMode) {
769 case ExplicitConstructorCall.This :
770 requestor.acceptConstructorReference(
771 typeNames[nestedTypeIndex-1],
772 constructorCall.arguments == null ? 0 : constructorCall.arguments.length,
773 constructorCall.sourceStart);
775 case ExplicitConstructorCall.Super :
776 case ExplicitConstructorCall.ImplicitSuper :
777 requestor.acceptConstructorReference(
778 superTypeNames[nestedTypeIndex-1],
779 constructorCall.arguments == null ? 0 : constructorCall.arguments.length,
780 constructorCall.sourceStart);
785 this.visitIfNeeded(methodDeclaration);
787 requestor.exitConstructor(methodDeclaration.declarationSourceEnd);
791 // if (methodDeclaration instanceof SourceMethodDeclaration) {
792 // selectorSourceEnd =
793 // ((SourceMethodDeclaration) methodDeclaration).selectorSourceEnd;
796 int modifiers = methodDeclaration.modifiers;
797 // boolean deprecated = (modifiers & AccDeprecated) != 0; // remember deprecation so as to not lose it below
798 requestor.enterMethod(
799 methodDeclaration.declarationSourceStart,
800 modifiers, // deprecated ? (modifiers & AccJustFlag) | AccDeprecated : modifiers & AccJustFlag,
801 returnTypeName(((MethodDeclaration) methodDeclaration).returnType),
802 methodDeclaration.selector,
803 methodDeclaration.sourceStart,
807 thrownExceptionTypes);
809 this.visitIfNeeded(methodDeclaration);
812 requestor.exitMethod(methodDeclaration.declarationSourceEnd);
816 //* Update the bodyStart of the corresponding parse node
818 //public void notifySourceElementRequestor(FieldDeclaration fieldDeclaration) {
821 // boolean isInRange =
822 // scanner.initialPosition <= fieldDeclaration.declarationSourceStart
823 // && scanner.eofPosition >= fieldDeclaration.declarationSourceEnd;
825 // if (fieldDeclaration.isField()) {
826 // int fieldEndPosition = fieldDeclaration.declarationSourceEnd;
827 // if (fieldDeclaration instanceof SourceFieldDeclaration) {
828 // fieldEndPosition = ((SourceFieldDeclaration) fieldDeclaration).fieldEndPosition;
829 // if (fieldEndPosition == 0) {
830 // // use the declaration source end by default
831 // fieldEndPosition = fieldDeclaration.declarationSourceEnd;
835 // int modifiers = fieldDeclaration.modifiers;
836 // boolean deprecated = (modifiers & AccDeprecated) != 0; // remember deprecation so as to not lose it below
837 // requestor.enterField(
838 // fieldDeclaration.declarationSourceStart,
839 // deprecated ? (modifiers & AccJustFlag) | AccDeprecated : modifiers & AccJustFlag,
840 // returnTypeName(fieldDeclaration.type),
841 // fieldDeclaration.name,
842 // fieldDeclaration.sourceStart,
843 // fieldDeclaration.sourceEnd);
845 // this.visitIfNeeded(fieldDeclaration);
847 // requestor.exitField(
848 // // filter out initializations that are not a constant (simple check)
849 // (fieldDeclaration.initialization == null
850 // || fieldDeclaration.initialization instanceof ArrayInitializer
851 // || fieldDeclaration.initialization instanceof AllocationExpression
852 // || fieldDeclaration.initialization instanceof ArrayAllocationExpression
853 // || fieldDeclaration.initialization instanceof Assignment
854 // || fieldDeclaration.initialization instanceof ClassLiteralAccess
855 // || fieldDeclaration.initialization instanceof MessageSend
856 // || fieldDeclaration.initialization instanceof ArrayReference
857 // || fieldDeclaration.initialization instanceof ThisReference) ?
859 // fieldDeclaration.initialization.sourceStart,
861 // fieldDeclaration.declarationSourceEnd);
866 // requestor.enterInitializer(
867 // fieldDeclaration.declarationSourceStart,
868 // fieldDeclaration.modifiers);
870 // this.visitIfNeeded((Initializer)fieldDeclaration);
872 // requestor.exitInitializer(fieldDeclaration.declarationSourceEnd);
876 //public void notifySourceElementRequestor(
877 // ImportReference importReference,
878 // boolean isPackage) {
880 // requestor.acceptPackage(
881 // importReference.declarationSourceStart,
882 // importReference.declarationSourceEnd,
883 // CharOperation.concatWith(importReference.getImportName(), '.'));
885 // requestor.acceptImport(
886 // importReference.declarationSourceStart,
887 // importReference.declarationSourceEnd,
888 // CharOperation.concatWith(importReference.getImportName(), '.'),
889 // importReference.onDemand);
892 public void notifySourceElementRequestor(TypeDeclaration typeDeclaration, boolean notifyTypePresence) {
893 //// public void notifySourceElementRequestor(AstNode typeDeclaration, boolean notifyTypePresence) {
897 scanner.initialPosition <= typeDeclaration.declarationSourceStart
898 && scanner.eofPosition >= typeDeclaration.declarationSourceEnd;
900 FieldDeclaration[] fields = typeDeclaration.fields;
901 AbstractMethodDeclaration[] methods = typeDeclaration.methods;
902 MemberTypeDeclaration[] memberTypes = typeDeclaration.memberTypes;
903 int fieldCount = fields == null ? 0 : fields.length;
904 int methodCount = methods == null ? 0 : methods.length;
905 int memberTypeCount = memberTypes == null ? 0 : memberTypes.length;
908 int memberTypeIndex = 0;
909 boolean isInterface = typeDeclaration.isInterface();
911 if (notifyTypePresence){
912 char[][] interfaceNames = null;
913 int superInterfacesLength = 0;
914 TypeReference[] superInterfaces = typeDeclaration.superInterfaces;
915 if (superInterfaces != null) {
916 superInterfacesLength = superInterfaces.length;
917 interfaceNames = new char[superInterfacesLength][];
919 if (typeDeclaration instanceof AnonymousLocalTypeDeclaration) {
921 QualifiedAllocationExpression alloc = ((AnonymousLocalTypeDeclaration)typeDeclaration).allocation;
922 if (alloc != null && alloc.type != null) {
923 superInterfaces = new TypeReference[] { ((AnonymousLocalTypeDeclaration)typeDeclaration).allocation.type};
924 superInterfacesLength = 1;
925 interfaceNames = new char[1][];
929 if (superInterfaces != null) {
930 for (int i = 0; i < superInterfacesLength; i++) {
932 CharOperation.concatWith(superInterfaces[i].getTypeName(), '.');
937 int modifiers = typeDeclaration.modifiers;
938 boolean deprecated = false; //(modifiers & AccDeprecated) != 0; // remember deprecation so as to not lose it below
939 requestor.enterInterface(
940 typeDeclaration.declarationSourceStart,
941 modifiers, //deprecated ? (modifiers & AccJustFlag) | AccDeprecated : modifiers & AccJustFlag,
942 typeDeclaration.name,
943 typeDeclaration.sourceStart,
944 typeDeclaration.sourceEnd,
947 if (nestedTypeIndex == typeNames.length) {
949 System.arraycopy(typeNames, 0, (typeNames = new char[nestedTypeIndex * 2][]), 0, nestedTypeIndex);
950 System.arraycopy(superTypeNames, 0, (superTypeNames = new char[nestedTypeIndex * 2][]), 0, nestedTypeIndex);
952 typeNames[nestedTypeIndex] = typeDeclaration.name;
953 superTypeNames[nestedTypeIndex++] = JAVA_LANG_OBJECT;
955 TypeReference superclass = typeDeclaration.superclass;
956 if (superclass == null) {
958 requestor.enterClass(
959 typeDeclaration.declarationSourceStart,
960 typeDeclaration.modifiers,
961 typeDeclaration.name,
962 typeDeclaration.sourceStart,
963 typeDeclaration.sourceEnd,
969 requestor.enterClass(
970 typeDeclaration.declarationSourceStart,
971 typeDeclaration.modifiers,
972 typeDeclaration.name,
973 typeDeclaration.sourceStart,
974 typeDeclaration.sourceEnd,
975 CharOperation.concatWith(superclass.getTypeName(), '.'),
979 if (nestedTypeIndex == typeNames.length) {
981 System.arraycopy(typeNames, 0, (typeNames = new char[nestedTypeIndex * 2][]), 0, nestedTypeIndex);
982 System.arraycopy(superTypeNames, 0, (superTypeNames = new char[nestedTypeIndex * 2][]), 0, nestedTypeIndex);
984 typeNames[nestedTypeIndex] = typeDeclaration.name;
985 superTypeNames[nestedTypeIndex++] = superclass == null ? JAVA_LANG_OBJECT : CharOperation.concatWith(superclass.getTypeName(), '.');
988 while ((fieldIndex < fieldCount)
989 || (memberTypeIndex < memberTypeCount)
990 || (methodIndex < methodCount)) {
991 FieldDeclaration nextFieldDeclaration = null;
992 AbstractMethodDeclaration nextMethodDeclaration = null;
993 TypeDeclaration nextMemberDeclaration = null;
995 int position = Integer.MAX_VALUE;
996 int nextDeclarationType = -1;
997 if (fieldIndex < fieldCount) {
998 nextFieldDeclaration = fields[fieldIndex];
999 if (nextFieldDeclaration.declarationSourceStart < position) {
1000 position = nextFieldDeclaration.declarationSourceStart;
1001 nextDeclarationType = 0; // FIELD
1004 if (methodIndex < methodCount) {
1005 nextMethodDeclaration = methods[methodIndex];
1006 if (nextMethodDeclaration.declarationSourceStart < position) {
1007 position = nextMethodDeclaration.declarationSourceStart;
1008 nextDeclarationType = 1; // METHOD
1011 if (memberTypeIndex < memberTypeCount) {
1012 nextMemberDeclaration = memberTypes[memberTypeIndex];
1013 if (nextMemberDeclaration.declarationSourceStart < position) {
1014 position = nextMemberDeclaration.declarationSourceStart;
1015 nextDeclarationType = 2; // MEMBER
1018 switch (nextDeclarationType) {
1021 // notifySourceElementRequestor(nextFieldDeclaration);
1025 notifySourceElementRequestor(nextMethodDeclaration);
1029 notifySourceElementRequestor(nextMemberDeclaration, true);
1032 if (notifyTypePresence){
1035 requestor.exitInterface(typeDeclaration.declarationSourceEnd);
1037 requestor.exitClass(typeDeclaration.declarationSourceEnd);
1043 public void parseCompilationUnit (
1044 ICompilationUnit unit,
1047 // boolean needReferenceInfo) {
1049 // reportReferenceInfo = needReferenceInfo;
1050 // boolean old = diet;
1051 // if (needReferenceInfo) {
1052 // unknownRefs = new NameReference[10];
1053 // unknownRefsCounter = 0;
1058 CompilationResult compilationUnitResult = new CompilationResult(unit, 0, 0, 10); //this.options.maxProblemsPerUnit);
1059 CompilationUnitDeclaration parsedUnit = parse(unit, compilationUnitResult, start, end);
1060 // if (scanner.recordLineSeparator) {
1061 // requestor.acceptLineSeparatorPositions(scanner.getLineEnds());
1063 // if (this.localDeclarationVisitor != null || needReferenceInfo){
1065 // this.getMethodBodies(parsedUnit);
1067 // this.scanner.resetTo(start, end);
1068 // notifySourceElementRequestor(parsedUnit);
1069 } catch (AbortCompilation e) {
1074 public void parseCompilationUnit(
1075 ICompilationUnit unit,
1076 boolean needReferenceInfo) {
1077 // boolean old = diet;
1078 // if (needReferenceInfo) {
1079 // unknownRefs = new NameReference[10];
1080 // unknownRefsCounter = 0;
1085 reportReferenceInfo = needReferenceInfo;
1086 CompilationResult compilationUnitResult = new CompilationResult(unit, 0, 0, 10); //this.options.maxProblemsPerUnit);
1087 CompilationUnitDeclaration parsedUnit = parse(unit, compilationUnitResult, false);
1088 if (scanner.recordLineSeparator) {
1089 requestor.acceptLineSeparatorPositions(scanner.getLineEnds());
1091 int initialStart = this.scanner.initialPosition;
1092 int initialEnd = this.scanner.eofPosition;
1093 // if (this.localDeclarationVisitor != null || needReferenceInfo){
1095 // this.getMethodBodies(parsedUnit);
1097 this.scanner.resetTo(initialStart, initialEnd);
1098 notifySourceElementRequestor(parsedUnit);
1099 } catch (AbortCompilation e) {
1104 //public void parseTypeMemberDeclarations(
1105 // ISourceType sourceType,
1106 // ICompilationUnit sourceUnit,
1109 // boolean needReferenceInfo) {
1110 // boolean old = diet;
1111 // if (needReferenceInfo) {
1112 // unknownRefs = new NameReference[10];
1113 // unknownRefsCounter = 0;
1117 // diet = !needReferenceInfo;
1118 // reportReferenceInfo = needReferenceInfo;
1119 // CompilationResult compilationUnitResult =
1120 // new CompilationResult(sourceUnit, 0, 0, this.options.maxProblemsPerUnit);
1121 // CompilationUnitDeclaration unit =
1122 // SourceTypeConverter.buildCompilationUnit(
1123 // new ISourceType[]{sourceType},
1124 // false, // no need for field and methods
1125 // false, // no need for member types
1126 // false, // no need for field initialization
1127 // problemReporter(),
1128 // compilationUnitResult);
1129 // if ((unit == null) || (unit.types == null) || (unit.types.length != 1))
1131 // this.sourceType = sourceType;
1133 // /* automaton initialization */
1135 // goForClassBodyDeclarations();
1136 // /* scanner initialization */
1137 // scanner.setSource(sourceUnit.getContents());
1138 // scanner.resetTo(start, end);
1139 // /* unit creation */
1140 // referenceContext = compilationUnit = unit;
1141 // /* initialize the astStacl */
1142 // // the compilationUnitDeclaration should contain exactly one type
1143 // pushOnAstStack(unit.types[0]);
1144 // /* run automaton */
1146 // notifySourceElementRequestor(unit);
1148 // unit = compilationUnit;
1149 // compilationUnit = null; // reset parser
1151 // } catch (AbortCompilation e) {
1153 // if (scanner.recordLineSeparator) {
1154 // requestor.acceptLineSeparatorPositions(scanner.getLineEnds());
1160 //public void parseTypeMemberDeclarations(
1165 // boolean old = diet;
1170 // /* automaton initialization */
1172 // goForClassBodyDeclarations();
1173 // /* scanner initialization */
1174 // scanner.setSource(contents);
1175 // scanner.recordLineSeparator = false;
1176 // scanner.taskTags = null;
1177 // scanner.taskPriorities = null;
1178 // scanner.resetTo(start, end);
1180 // /* unit creation */
1181 // referenceContext = null;
1183 // /* initialize the astStacl */
1184 // // the compilationUnitDeclaration should contain exactly one type
1185 // /* run automaton */
1187 // notifySourceElementRequestor((CompilationUnitDeclaration)null);
1188 // } catch (AbortCompilation e) {
1194 * Sort the given ast nodes by their positions.
1196 private static void quickSort(AstNode[] sortedCollection, int left, int right) {
1197 int original_left = left;
1198 int original_right = right;
1199 AstNode mid = sortedCollection[ (left + right) / 2];
1201 while (sortedCollection[left].sourceStart < mid.sourceStart) {
1204 while (mid.sourceStart < sortedCollection[right].sourceStart) {
1207 if (left <= right) {
1208 AstNode tmp = sortedCollection[left];
1209 sortedCollection[left] = sortedCollection[right];
1210 sortedCollection[right] = tmp;
1214 } while (left <= right);
1215 if (original_left < right) {
1216 quickSort(sortedCollection, original_left, right);
1218 if (left < original_right) {
1219 quickSort(sortedCollection, left, original_right);
1223 * Answer a char array representation of the type name formatted like:
1224 * - type name + dimensions
1226 * "A[][]".toCharArray()
1227 * "java.lang.String".toCharArray()
1229 private char[] returnTypeName(TypeReference type) {
1232 int dimension = type.dimensions();
1233 if (dimension != 0) {
1234 char[] dimensionsArray = new char[dimension * 2];
1235 for (int i = 0; i < dimension; i++) {
1236 dimensionsArray[i * 2] = '[';
1237 dimensionsArray[(i * 2) + 1] = ']';
1239 return CharOperation.concat(
1240 CharOperation.concatWith(type.getTypeName(), '.'),
1243 return CharOperation.concatWith(type.getTypeName(), '.');
1246 public void addUnknownRef(NameReference nameRef) {
1247 if (this.unknownRefs.length == this.unknownRefsCounter) {
1252 (this.unknownRefs = new NameReference[this.unknownRefsCounter * 2]),
1254 this.unknownRefsCounter);
1256 this.unknownRefs[this.unknownRefsCounter++] = nameRef;
1259 private void visitIfNeeded(AbstractMethodDeclaration method) {
1260 if (this.localDeclarationVisitor != null
1261 && (method.bits & AstNode.HasLocalTypeMASK) != 0) {
1262 if (method.statements != null) {
1263 int statementsLength = method.statements.length;
1264 for (int i = 0; i < statementsLength; i++)
1265 method.statements[i].traverse(this.localDeclarationVisitor, method.scope);
1270 //private void visitIfNeeded(FieldDeclaration field) {
1271 // if (this.localDeclarationVisitor != null
1272 // && (field.bits & AstNode.HasLocalTypeMASK) != 0) {
1273 // if (field.initialization != null) {
1274 // field.initialization.traverse(this.localDeclarationVisitor, null);
1279 //private void visitIfNeeded(Initializer initializer) {
1280 // if (this.localDeclarationVisitor != null
1281 // && (initializer.bits & AstNode.HasLocalTypeMASK) != 0) {
1282 // if (initializer.block != null) {
1283 // initializer.block.traverse(this.localDeclarationVisitor, null);
1288 //protected void reportSyntaxError(int act, int currentKind, int stateStackTop) {
1289 // if (compilationUnit == null) return;
1290 // super.reportSyntaxError(act, currentKind,stateStackTop);