1 /*******************************************************************************
2 * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others.
3 * All rights reserved. This program and the accompanying materials
4 * are made available under the terms of the Common Public License v0.5
5 * which accompanies this distribution, and is available at
6 * http://www.eclipse.org/legal/cpl-v05.html
9 * IBM Corporation - initial API and implementation
10 ******************************************************************************/
11 package net.sourceforge.phpdt.internal.compiler;
14 * A document element parser extracts structural information
15 * from a piece of source, providing detailed source positions info.
17 * also see @IDocumentElementRequestor
19 * The structural investigation includes:
20 * - the package statement
22 * - top-level types: package member, member types (member types of member types...)
26 * Any (parsing) problem encountered is also provided.
28 import net.sourceforge.phpdt.internal.compiler.env.*;
30 import net.sourceforge.phpdt.internal.compiler.impl.*;
31 import net.sourceforge.phpdt.core.compiler.*;
32 import net.sourceforge.phpdt.internal.compiler.ast.*;
33 import net.sourceforge.phpdt.internal.compiler.parser.*;
34 import net.sourceforge.phpdt.internal.compiler.problem.*;
35 import net.sourceforge.phpdt.internal.compiler.util.*;
37 public class DocumentElementParser extends Parser {
38 IDocumentElementRequestor requestor;
39 private int localIntPtr;
40 private int lastFieldEndPosition;
41 private int lastFieldBodyEndPosition;
42 private int typeStartPosition;
43 private long selectorSourcePositions;
45 private int extendsDim;
46 private int declarationSourceStart;
48 /* int[] stack for storing javadoc positions */
49 int[][] intArrayStack;
52 CompilerOptions options;
54 public DocumentElementParser(
55 final IDocumentElementRequestor requestor,
56 IProblemFactory problemFactory,
57 CompilerOptions options) {
58 super(new ProblemReporter(
59 DefaultErrorHandlingPolicies.exitAfterAllProblems(),
62 public void record(IProblem problem, CompilationResult unitResult) {
63 requestor.acceptProblem(problem);
68 this.requestor = requestor;
69 intArrayStack = new int[30][];
70 this.options = options;
77 protected void adjustInterfaceModifiers() {
78 intStack[intPtr - 2] |= AccInterface;
81 * Will clear the comment stack when looking
82 * for a potential JavaDoc which might contain @deprecated.
84 * Additionally, before investigating for @deprecated, retrieve the positions
85 * of the JavaDoc comments so as to notify requestor with them.
87 public void checkAnnotation() {
89 /* persisting javadoc positions */
90 pushOnIntArrayStack(this.getJavaDocPositions());
91 boolean deprecated = false;
92 int lastAnnotationIndex = -1;
94 //since jdk1.2 look only in the last java doc comment...
96 if ((lastAnnotationIndex = scanner.commentPtr) >= 0) { //look for @deprecated
97 scanner.commentPtr = -1;
98 // reset the comment stack, since not necessary after having checked
99 int commentSourceStart = scanner.commentStarts[lastAnnotationIndex];
100 // javadoc only (non javadoc comment have negative end positions.)
101 int commentSourceEnd = scanner.commentStops[lastAnnotationIndex] - 1;
103 char[] comment = scanner.source;
105 for (int i = commentSourceStart + 3; i < commentSourceEnd - 10; i++) {
106 if ((comment[i] == '@')
107 && (comment[i + 1] == 'd')
108 && (comment[i + 2] == 'e')
109 && (comment[i + 3] == 'p')
110 && (comment[i + 4] == 'r')
111 && (comment[i + 5] == 'e')
112 && (comment[i + 6] == 'c')
113 && (comment[i + 7] == 'a')
114 && (comment[i + 8] == 't')
115 && (comment[i + 9] == 'e')
116 && (comment[i + 10] == 'd')) {
117 // ensure the tag is properly ended: either followed by a space, line end or asterisk.
118 int nextPos = i + 11;
120 (comment[nextPos] == ' ')
121 || (comment[nextPos] == '\n')
122 || (comment[nextPos] == '\r')
123 || (comment[nextPos] == '*');
130 checkAndSetModifiers(AccDeprecated);
132 // modify the modifier source start to point at the first comment
133 if (lastAnnotationIndex >= 0) {
134 declarationSourceStart = scanner.commentStarts[0];
141 protected void consumeClassBodyDeclaration() {
142 // ClassBodyDeclaration ::= Diet Block
143 //push an Initializer
144 //optimize the push/pop
146 super.consumeClassBodyDeclaration();
147 Initializer initializer = (Initializer) astStack[astPtr];
148 requestor.acceptInitializer(
149 initializer.declarationSourceStart,
150 initializer.declarationSourceEnd,
151 intArrayStack[intArrayPtr--],
153 modifiersSourceStart,
154 initializer.block.sourceStart,
155 initializer.block.sourceEnd);
161 protected void consumeClassDeclaration() {
162 super.consumeClassDeclaration();
163 // we know that we have a TypeDeclaration on the top of the astStack
164 if (isLocalDeclaration()) {
165 // we ignore the local variable declarations
168 requestor.exitClass(endStatementPosition, // '}' is the end of the body
169 ((TypeDeclaration) astStack[astPtr]).declarationSourceEnd);
175 protected void consumeClassHeader() {
176 //ClassHeader ::= $empty
177 super.consumeClassHeader();
178 if (isLocalDeclaration()) {
179 // we ignore the local variable declarations
183 TypeDeclaration typeDecl = (TypeDeclaration) astStack[astPtr];
184 TypeReference[] superInterfaces = typeDecl.superInterfaces;
185 char[][] interfaceNames = null;
186 int[] interfaceNameStarts = null;
187 int[] interfaceNameEnds = null;
188 if (superInterfaces != null) {
189 int superInterfacesLength = superInterfaces.length;
190 interfaceNames = new char[superInterfacesLength][];
191 interfaceNameStarts = new int[superInterfacesLength];
192 interfaceNameEnds = new int[superInterfacesLength];
193 for (int i = 0; i < superInterfacesLength; i++) {
194 TypeReference superInterface = superInterfaces[i];
195 interfaceNames[i] = CharOperation.concatWith(superInterface.getTypeName(), '.');
196 interfaceNameStarts[i] = superInterface.sourceStart;
197 interfaceNameEnds[i] = superInterface.sourceEnd;
200 // flush the comments related to the class header
201 scanner.commentPtr = -1;
202 TypeReference superclass = typeDecl.superclass;
203 if (superclass == null) {
204 requestor.enterClass(
205 typeDecl.declarationSourceStart,
206 intArrayStack[intArrayPtr--],
208 typeDecl.modifiersSourceStart,
211 typeDecl.sourceStart,
219 scanner.currentPosition - 1);
221 requestor.enterClass(
222 typeDecl.declarationSourceStart,
223 intArrayStack[intArrayPtr--],
225 typeDecl.modifiersSourceStart,
228 typeDecl.sourceStart,
230 CharOperation.concatWith(superclass.getTypeName(), '.'),
231 superclass.sourceStart,
232 superclass.sourceEnd,
236 scanner.currentPosition - 1);
240 protected void consumeClassHeaderName() {
241 // ClassHeaderName ::= Modifiersopt 'class' 'Identifier'
242 TypeDeclaration typeDecl;
243 if (nestedMethod[nestedType] == 0) {
244 if (nestedType != 0) {
245 typeDecl = new MemberTypeDeclaration(this.compilationUnit.compilationResult);
247 typeDecl = new TypeDeclaration(this.compilationUnit.compilationResult);
250 // Record that the block has a declaration for local types
251 typeDecl = new LocalTypeDeclaration(this.compilationUnit.compilationResult);
252 markCurrentMethodWithLocalType();
256 //highlight the name of the type
257 long pos = identifierPositionStack[identifierPtr];
258 typeDecl.sourceEnd = (int) pos;
259 typeDecl.sourceStart = (int) (pos >>> 32);
260 typeDecl.name = identifierStack[identifierPtr--];
261 identifierLengthPtr--;
263 //compute the declaration source too
264 // 'class' and 'interface' push an int position
265 typeStartPosition = typeDecl.declarationSourceStart = intStack[intPtr--];
267 int declarationSourceStart = intStack[intPtr--];
268 typeDecl.modifiersSourceStart = intStack[intPtr--];
269 typeDecl.modifiers = intStack[intPtr--];
270 if (typeDecl.declarationSourceStart > declarationSourceStart) {
271 typeDecl.declarationSourceStart = declarationSourceStart;
273 typeDecl.bodyStart = typeDecl.sourceEnd + 1;
274 pushOnAstStack(typeDecl);
280 protected void consumeCompilationUnit() {
281 // CompilationUnit ::= EnterCompilationUnit PackageDeclarationopt ImportDeclarationsopt
282 requestor.exitCompilationUnit(scanner.source.length - 1);
288 protected void consumeConstructorDeclaration() {
289 // ConstructorDeclaration ::= ConstructorHeader ConstructorBody
290 super.consumeConstructorDeclaration();
291 if (isLocalDeclaration()) {
292 // we ignore the local variable declarations
295 ConstructorDeclaration cd = (ConstructorDeclaration) astStack[astPtr];
296 requestor.exitConstructor(endStatementPosition, cd.declarationSourceEnd);
302 protected void consumeConstructorHeader() {
303 // ConstructorHeader ::= ConstructorHeaderName MethodHeaderParameters MethodHeaderThrowsClauseopt
304 super.consumeConstructorHeader();
305 if (isLocalDeclaration()) {
306 // we ignore the local variable declarations
310 ConstructorDeclaration cd = (ConstructorDeclaration) astStack[astPtr];
311 Argument[] arguments = cd.arguments;
312 char[][] argumentTypes = null;
313 char[][] argumentNames = null;
314 int[] argumentTypeStarts = null;
315 int[] argumentTypeEnds = null;
316 int[] argumentNameStarts = null;
317 int[] argumentNameEnds = null;
318 if (arguments != null) {
319 int argumentLength = arguments.length;
320 argumentTypes = new char[argumentLength][];
321 argumentNames = new char[argumentLength][];
322 argumentNameStarts = new int[argumentLength];
323 argumentNameEnds = new int[argumentLength];
324 argumentTypeStarts = new int[argumentLength];
325 argumentTypeEnds = new int[argumentLength];
326 for (int i = 0; i < argumentLength; i++) {
327 Argument argument = arguments[i];
328 TypeReference argumentType = argument.type;
329 argumentTypes[i] = returnTypeName(argumentType);
330 argumentNames[i] = argument.name;
331 argumentNameStarts[i] = argument.sourceStart;
332 argumentNameEnds[i] = argument.sourceEnd;
333 argumentTypeStarts[i] = argumentType.sourceStart;
334 argumentTypeEnds[i] = argumentType.sourceEnd;
337 TypeReference[] thrownExceptions = cd.thrownExceptions;
338 char[][] exceptionTypes = null;
339 int[] exceptionTypeStarts = null;
340 int[] exceptionTypeEnds = null;
341 if (thrownExceptions != null) {
342 int thrownExceptionLength = thrownExceptions.length;
343 exceptionTypes = new char[thrownExceptionLength][];
344 exceptionTypeStarts = new int[thrownExceptionLength];
345 exceptionTypeEnds = new int[thrownExceptionLength];
346 for (int i = 0; i < thrownExceptionLength; i++) {
347 TypeReference exception = thrownExceptions[i];
348 exceptionTypes[i] = CharOperation.concatWith(exception.getTypeName(), '.');
349 exceptionTypeStarts[i] = exception.sourceStart;
350 exceptionTypeEnds[i] = exception.sourceEnd;
355 cd.declarationSourceStart,
356 intArrayStack[intArrayPtr--],
358 cd.modifiersSourceStart,
361 (int) (selectorSourcePositions & 0xFFFFFFFFL),
362 // retrieve the source end of the name
374 scanner.currentPosition - 1);
376 protected void consumeConstructorHeaderName() {
377 // ConstructorHeaderName ::= Modifiersopt 'Identifier' '('
378 ConstructorDeclaration cd = new ConstructorDeclaration(this.compilationUnit.compilationResult);
380 //name -- this is not really revelant but we do .....
381 cd.selector = identifierStack[identifierPtr];
382 selectorSourcePositions = identifierPositionStack[identifierPtr--];
383 identifierLengthPtr--;
386 cd.declarationSourceStart = intStack[intPtr--];
387 cd.modifiersSourceStart = intStack[intPtr--];
388 cd.modifiers = intStack[intPtr--];
390 //highlight starts at the selector starts
391 cd.sourceStart = (int) (selectorSourcePositions >>> 32);
394 cd.sourceEnd = lParenPos;
395 cd.bodyStart = lParenPos + 1;
397 protected void consumeDefaultModifiers() {
398 checkAnnotation(); // might update modifiers with AccDeprecated
399 pushOnIntStack(modifiers); // modifiers
402 declarationSourceStart >= 0 ? declarationSourceStart : scanner.startPosition);
405 protected void consumeDiet() {
408 /* persisting javadoc positions
409 * Will be consume in consumeClassBodyDeclaration
411 pushOnIntArrayStack(this.getJavaDocPositions());
417 protected void consumeEnterCompilationUnit() {
418 // EnterCompilationUnit ::= $empty
419 requestor.enterCompilationUnit();
425 protected void consumeEnterVariable() {
426 // EnterVariable ::= $empty
427 boolean isLocalDeclaration = isLocalDeclaration();
428 if (!isLocalDeclaration && (variablesCounter[nestedType] != 0)) {
429 requestor.exitField(lastFieldBodyEndPosition, lastFieldEndPosition);
431 char[] name = identifierStack[identifierPtr];
432 long namePosition = identifierPositionStack[identifierPtr--];
433 int extendedTypeDimension = intStack[intPtr--];
435 AbstractVariableDeclaration declaration;
436 if (nestedMethod[nestedType] != 0) {
437 // create the local variable declarations
439 new LocalDeclaration(null, name, (int) (namePosition >>> 32), (int) namePosition);
441 // create the field declaration
443 new FieldDeclaration(null, name, (int) (namePosition >>> 32), (int) namePosition);
445 identifierLengthPtr--;
447 int variableIndex = variablesCounter[nestedType];
449 if (variableIndex == 0) {
450 // first variable of the declaration (FieldDeclaration or LocalDeclaration)
451 if (nestedMethod[nestedType] != 0) {
453 declaration.declarationSourceStart = intStack[intPtr--];
454 declaration.modifiersSourceStart = intStack[intPtr--];
455 declaration.modifiers = intStack[intPtr--];
456 type = getTypeReference(typeDim = intStack[intPtr--]); // type dimension
457 pushOnAstStack(type);
460 type = getTypeReference(typeDim = intStack[intPtr--]); // type dimension
461 pushOnAstStack(type);
462 declaration.declarationSourceStart = intStack[intPtr--];
463 declaration.modifiersSourceStart = intStack[intPtr--];
464 declaration.modifiers = intStack[intPtr--];
467 type = (TypeReference) astStack[astPtr - variableIndex];
468 typeDim = type.dimensions();
469 AbstractVariableDeclaration previousVariable =
470 (AbstractVariableDeclaration) astStack[astPtr];
471 declaration.declarationSourceStart = previousVariable.declarationSourceStart;
472 declaration.modifiers = previousVariable.modifiers;
473 declaration.modifiersSourceStart = previousVariable.modifiersSourceStart;
476 localIntPtr = intPtr;
478 if (extendedTypeDimension == 0) {
479 declaration.type = type;
481 int dimension = typeDim + extendedTypeDimension;
482 //on the identifierLengthStack there is the information about the type....
484 if ((baseType = identifierLengthStack[identifierLengthPtr + 1]) < 0) {
486 declaration.type = TypeReference.baseTypeReference(-baseType, dimension);
487 declaration.type.sourceStart = type.sourceStart;
488 declaration.type.sourceEnd = type.sourceEnd;
490 declaration.type = this.copyDims(type, dimension);
493 variablesCounter[nestedType]++;
494 nestedMethod[nestedType]++;
495 pushOnAstStack(declaration);
497 int[] javadocPositions = intArrayStack[intArrayPtr];
498 if (!isLocalDeclaration) {
501 declaration.declarationSourceStart,
503 declaration.modifiers,
504 declaration.modifiersSourceStart,
505 returnTypeName(declaration.type),
510 (int) (namePosition >>> 32),
512 extendedTypeDimension,
513 extendedTypeDimension == 0 ? -1 : endPosition);
520 protected void consumeExitVariableWithInitialization() {
521 // ExitVariableWithInitialization ::= $empty
522 // the scanner is located after the comma or the semi-colon.
523 // we want to include the comma or the semi-colon
524 super.consumeExitVariableWithInitialization();
525 nestedMethod[nestedType]--;
526 lastFieldEndPosition = scanner.currentPosition - 1;
527 lastFieldBodyEndPosition = ((AbstractVariableDeclaration) astStack[astPtr]).initialization.sourceEnd;
529 protected void consumeExitVariableWithoutInitialization() {
530 // ExitVariableWithoutInitialization ::= $empty
531 // do nothing by default
532 super.consumeExitVariableWithoutInitialization();
533 nestedMethod[nestedType]--;
534 lastFieldEndPosition = scanner.currentPosition - 1;
535 lastFieldBodyEndPosition = scanner.startPosition - 1;
541 protected void consumeFieldDeclaration() {
542 // See consumeLocalVariableDeclarationDefaultModifier() in case of change: duplicated code
543 // FieldDeclaration ::= Modifiersopt Type VariableDeclarators ';'
544 // the super.consumeFieldDeclaration will reinitialize the variableCounter[nestedType]
545 int variableIndex = variablesCounter[nestedType];
546 super.consumeFieldDeclaration();
548 if (isLocalDeclaration())
550 if (variableIndex != 0) {
551 requestor.exitField(lastFieldBodyEndPosition, lastFieldEndPosition);
554 protected void consumeFormalParameter() {
555 // FormalParameter ::= Type VariableDeclaratorId ==> false
556 // FormalParameter ::= Modifiers Type VariableDeclaratorId ==> true
559 identifierStack : type identifier
567 identifierLengthPtr--;
568 char[] name = identifierStack[identifierPtr];
569 long namePositions = identifierPositionStack[identifierPtr--];
570 TypeReference type = getTypeReference(intStack[intPtr--] + intStack[intPtr--]);
577 intStack[intPtr + 1]); // modifiers
585 protected void consumeInterfaceDeclaration() {
586 super.consumeInterfaceDeclaration();
587 // we know that we have a TypeDeclaration on the top of the astStack
588 if (isLocalDeclaration()) {
589 // we ignore the local variable declarations
592 requestor.exitInterface(endStatementPosition, // the '}' is the end of the body
593 ((TypeDeclaration) astStack[astPtr]).declarationSourceEnd);
599 protected void consumeInterfaceHeader() {
600 //InterfaceHeader ::= $empty
601 super.consumeInterfaceHeader();
602 if (isLocalDeclaration()) {
603 // we ignore the local variable declarations
607 TypeDeclaration typeDecl = (TypeDeclaration) astStack[astPtr];
608 TypeReference[] superInterfaces = typeDecl.superInterfaces;
609 char[][] interfaceNames = null;
610 int[] interfaceNameStarts = null;
611 int[] interfacenameEnds = null;
612 int superInterfacesLength = 0;
613 if (superInterfaces != null) {
614 superInterfacesLength = superInterfaces.length;
615 interfaceNames = new char[superInterfacesLength][];
616 interfaceNameStarts = new int[superInterfacesLength];
617 interfacenameEnds = new int[superInterfacesLength];
619 if (superInterfaces != null) {
620 for (int i = 0; i < superInterfacesLength; i++) {
621 TypeReference superInterface = superInterfaces[i];
622 interfaceNames[i] = CharOperation.concatWith(superInterface.getTypeName(), '.');
623 interfaceNameStarts[i] = superInterface.sourceStart;
624 interfacenameEnds[i] = superInterface.sourceEnd;
627 // flush the comments related to the interface header
628 scanner.commentPtr = -1;
629 requestor.enterInterface(
630 typeDecl.declarationSourceStart,
631 intArrayStack[intArrayPtr--],
633 typeDecl.modifiersSourceStart,
636 typeDecl.sourceStart,
641 scanner.currentPosition - 1);
643 protected void consumeInterfaceHeaderName() {
644 // InterfaceHeaderName ::= Modifiersopt 'interface' 'Identifier'
645 TypeDeclaration typeDecl;
646 if (nestedMethod[nestedType] == 0) {
647 if (nestedType != 0) {
648 typeDecl = new MemberTypeDeclaration(this.compilationUnit.compilationResult);
650 typeDecl = new TypeDeclaration(this.compilationUnit.compilationResult);
653 // Record that the block has a declaration for local types
654 typeDecl = new LocalTypeDeclaration(this.compilationUnit.compilationResult);
655 markCurrentMethodWithLocalType();
659 //highlight the name of the type
660 long pos = identifierPositionStack[identifierPtr];
661 typeDecl.sourceEnd = (int) pos;
662 typeDecl.sourceStart = (int) (pos >>> 32);
663 typeDecl.name = identifierStack[identifierPtr--];
664 identifierLengthPtr--;
666 //compute the declaration source too
667 // 'class' and 'interface' push an int position
668 typeStartPosition = typeDecl.declarationSourceStart = intStack[intPtr--];
670 int declarationSourceStart = intStack[intPtr--];
671 typeDecl.modifiersSourceStart = intStack[intPtr--];
672 typeDecl.modifiers = intStack[intPtr--];
673 if (typeDecl.declarationSourceStart > declarationSourceStart) {
674 typeDecl.declarationSourceStart = declarationSourceStart;
676 typeDecl.bodyStart = typeDecl.sourceEnd + 1;
677 pushOnAstStack(typeDecl);
683 protected void consumeLocalVariableDeclaration() {
684 // See consumeLocalVariableDeclarationDefaultModifier() in case of change: duplicated code
685 // FieldDeclaration ::= Modifiersopt Type VariableDeclarators ';'
687 super.consumeLocalVariableDeclaration();
694 protected void consumeMethodDeclaration(boolean isNotAbstract) {
695 // MethodDeclaration ::= MethodHeader MethodBody
696 // AbstractMethodDeclaration ::= MethodHeader ';'
697 super.consumeMethodDeclaration(isNotAbstract);
698 if (isLocalDeclaration()) {
699 // we ignore the local variable declarations
702 MethodDeclaration md = (MethodDeclaration) astStack[astPtr];
703 requestor.exitMethod(endStatementPosition, md.declarationSourceEnd);
709 protected void consumeMethodHeader() {
710 // MethodHeader ::= MethodHeaderName MethodHeaderParameters MethodHeaderExtendedDims ThrowsClauseopt
711 super.consumeMethodHeader();
712 if (isLocalDeclaration()) {
713 // we ignore the local variable declarations
717 MethodDeclaration md = (MethodDeclaration) astStack[astPtr];
719 TypeReference returnType = md.returnType;
720 char[] returnTypeName = returnTypeName(returnType);
721 Argument[] arguments = md.arguments;
722 char[][] argumentTypes = null;
723 char[][] argumentNames = null;
724 int[] argumentTypeStarts = null;
725 int[] argumentTypeEnds = null;
726 int[] argumentNameStarts = null;
727 int[] argumentNameEnds = null;
728 if (arguments != null) {
729 int argumentLength = arguments.length;
730 argumentTypes = new char[argumentLength][];
731 argumentNames = new char[argumentLength][];
732 argumentNameStarts = new int[argumentLength];
733 argumentNameEnds = new int[argumentLength];
734 argumentTypeStarts = new int[argumentLength];
735 argumentTypeEnds = new int[argumentLength];
736 for (int i = 0; i < argumentLength; i++) {
737 Argument argument = arguments[i];
738 TypeReference argumentType = argument.type;
739 argumentTypes[i] = returnTypeName(argumentType);
740 argumentNames[i] = argument.name;
741 argumentNameStarts[i] = argument.sourceStart;
742 argumentNameEnds[i] = argument.sourceEnd;
743 argumentTypeStarts[i] = argumentType.sourceStart;
744 argumentTypeEnds[i] = argumentType.sourceEnd;
747 TypeReference[] thrownExceptions = md.thrownExceptions;
748 char[][] exceptionTypes = null;
749 int[] exceptionTypeStarts = null;
750 int[] exceptionTypeEnds = null;
751 if (thrownExceptions != null) {
752 int thrownExceptionLength = thrownExceptions.length;
753 exceptionTypeStarts = new int[thrownExceptionLength];
754 exceptionTypeEnds = new int[thrownExceptionLength];
755 exceptionTypes = new char[thrownExceptionLength][];
756 for (int i = 0; i < thrownExceptionLength; i++) {
757 TypeReference exception = thrownExceptions[i];
758 exceptionTypes[i] = CharOperation.concatWith(exception.getTypeName(), '.');
759 exceptionTypeStarts[i] = exception.sourceStart;
760 exceptionTypeEnds[i] = exception.sourceEnd;
765 md.declarationSourceStart,
766 intArrayStack[intArrayPtr--],
768 md.modifiersSourceStart,
770 returnType.sourceStart,
771 returnType.sourceEnd,
775 (int) (selectorSourcePositions & 0xFFFFFFFFL),
784 extendsDim == 0 ? -1 : endPosition,
788 scanner.currentPosition - 1);
790 protected void consumeMethodHeaderExtendedDims() {
791 // MethodHeaderExtendedDims ::= Dimsopt
792 // now we update the returnType of the method
793 MethodDeclaration md = (MethodDeclaration) astStack[astPtr];
794 int extendedDims = intStack[intPtr--];
795 extendsDim = extendedDims;
796 if (extendedDims != 0) {
797 TypeReference returnType = md.returnType;
798 md.sourceEnd = endPosition;
799 int dims = returnType.dimensions() + extendedDims;
801 if ((baseType = identifierLengthStack[identifierLengthPtr + 1]) < 0) {
803 int sourceStart = returnType.sourceStart;
804 int sourceEnd = returnType.sourceEnd;
805 returnType = TypeReference.baseTypeReference(-baseType, dims);
806 returnType.sourceStart = sourceStart;
807 returnType.sourceEnd = sourceEnd;
808 md.returnType = returnType;
810 md.returnType = this.copyDims(md.returnType, dims);
812 if (currentToken == TokenNameLBRACE) {
813 md.bodyStart = endPosition + 1;
817 protected void consumeMethodHeaderName() {
818 // MethodHeaderName ::= Modifiersopt Type 'Identifier' '('
819 MethodDeclaration md = new MethodDeclaration(this.compilationUnit.compilationResult);
822 md.selector = identifierStack[identifierPtr];
823 selectorSourcePositions = identifierPositionStack[identifierPtr--];
824 identifierLengthPtr--;
826 md.returnType = getTypeReference(typeDims = intStack[intPtr--]);
828 md.declarationSourceStart = intStack[intPtr--];
829 md.modifiersSourceStart = intStack[intPtr--];
830 md.modifiers = intStack[intPtr--];
832 //highlight starts at selector start
833 md.sourceStart = (int) (selectorSourcePositions >>> 32);
835 md.bodyStart = scanner.currentPosition-1;
837 protected void consumeModifiers() {
838 checkAnnotation(); // might update modifiers with AccDeprecated
839 pushOnIntStack(modifiers); // modifiers
840 pushOnIntStack(modifiersSourceStart);
842 declarationSourceStart >= 0 ? declarationSourceStart : modifiersSourceStart);
849 protected void consumePackageDeclarationName() {
850 /* persisting javadoc positions */
851 pushOnIntArrayStack(this.getJavaDocPositions());
853 super.consumePackageDeclarationName();
854 ImportReference importReference = compilationUnit.currentPackage;
856 requestor.acceptPackage(
857 importReference.declarationSourceStart,
858 importReference.declarationSourceEnd,
859 intArrayStack[intArrayPtr--],
860 CharOperation.concatWith(importReference.getImportName(), '.'),
861 importReference.sourceStart);
863 protected void consumePushModifiers() {
864 checkAnnotation(); // might update modifiers with AccDeprecated
865 pushOnIntStack(modifiers); // modifiers
866 if (modifiersSourceStart < 0) {
869 declarationSourceStart >= 0 ? declarationSourceStart : scanner.startPosition);
871 pushOnIntStack(modifiersSourceStart);
873 declarationSourceStart >= 0 ? declarationSourceStart : modifiersSourceStart);
881 protected void consumeSingleTypeImportDeclarationName() {
882 // SingleTypeImportDeclarationName ::= 'import' Name
884 /* persisting javadoc positions */
885 pushOnIntArrayStack(this.getJavaDocPositions());
887 super.consumeSingleTypeImportDeclarationName();
888 ImportReference importReference = (ImportReference) astStack[astPtr];
889 requestor.acceptImport(
890 importReference.declarationSourceStart,
891 importReference.declarationSourceEnd,
892 intArrayStack[intArrayPtr--],
893 CharOperation.concatWith(importReference.getImportName(), '.'),
894 importReference.sourceStart,
901 protected void consumeStaticInitializer() {
902 // StaticInitializer ::= StaticOnly Block
903 //push an Initializer
904 //optimize the push/pop
905 super.consumeStaticInitializer();
906 Initializer initializer = (Initializer) astStack[astPtr];
907 requestor.acceptInitializer(
908 initializer.declarationSourceStart,
909 initializer.declarationSourceEnd,
910 intArrayStack[intArrayPtr--],
913 initializer.block.sourceStart,
914 initializer.declarationSourceEnd);
916 protected void consumeStaticOnly() {
917 // StaticOnly ::= 'static'
918 checkAnnotation(); // might update declaration source start
919 pushOnIntStack(modifiersSourceStart);
921 declarationSourceStart >= 0 ? declarationSourceStart : modifiersSourceStart);
922 jumpOverMethodBody();
923 nestedMethod[nestedType]++;
930 protected void consumeTypeImportOnDemandDeclarationName() {
931 // TypeImportOnDemandDeclarationName ::= 'import' Name '.' '*'
933 /* persisting javadoc positions */
934 pushOnIntArrayStack(this.getJavaDocPositions());
936 super.consumeTypeImportOnDemandDeclarationName();
937 ImportReference importReference = (ImportReference) astStack[astPtr];
938 requestor.acceptImport(
939 importReference.declarationSourceStart,
940 importReference.declarationSourceEnd,
941 intArrayStack[intArrayPtr--],
942 CharOperation.concatWith(importReference.getImportName(), '.'),
943 importReference.sourceStart,
946 public CompilationUnitDeclaration endParse(int act) {
947 if (scanner.recordLineSeparator) {
948 requestor.acceptLineSeparatorPositions(scanner.getLineEnds());
950 return super.endParse(act);
953 * Flush annotations defined prior to a given positions.
955 * Note: annotations are stacked in syntactical order
957 * Either answer given <position>, or the end position of a comment line
958 * immediately following the <position> (same line)
962 * } // end of method foo
965 public int flushAnnotationsDefinedPriorTo(int position) {
967 return lastFieldEndPosition = super.flushAnnotationsDefinedPriorTo(position);
969 protected TypeReference getTypeReference(int dim) { /* build a Reference on a variable that may be qualified or not
970 This variable is a type reference and dim will be its dimensions*/
974 if ((length = identifierLengthStack[identifierLengthPtr--]) == 1) {
975 // single variable reference
978 new SingleTypeReference(
979 identifierStack[identifierPtr],
980 identifierPositionStack[identifierPtr--]);
983 new ArrayTypeReference(
984 identifierStack[identifierPtr],
986 identifierPositionStack[identifierPtr--]);
987 ref.sourceEnd = endPosition;
990 if (length < 0) { //flag for precompiled type reference on base types
991 ref = TypeReference.baseTypeReference(-length, dim);
992 ref.sourceStart = intStack[intPtr--];
994 ref.sourceEnd = intStack[intPtr--];
997 ref.sourceEnd = endPosition;
999 } else { //Qualified variable reference
1000 char[][] tokens = new char[length][];
1001 identifierPtr -= length;
1002 long[] positions = new long[length];
1003 System.arraycopy(identifierStack, identifierPtr + 1, tokens, 0, length);
1005 identifierPositionStack,
1011 ref = new QualifiedTypeReference(tokens, positions);
1013 ref = new ArrayQualifiedTypeReference(tokens, dim, positions);
1014 ref.sourceEnd = endPosition;
1020 public void initialize() {
1021 //positionning the parser for a new compilation unit
1022 //avoiding stack reallocation and all that....
1030 private boolean isLocalDeclaration() {
1031 int nestedDepth = nestedType;
1032 while (nestedDepth >= 0) {
1033 if (nestedMethod[nestedDepth] != 0) {
1041 * Investigate one entire unit.
1043 public void parseCompilationUnit(ICompilationUnit unit) {
1044 char[] regionSource = unit.getContents();
1047 goForCompilationUnit();
1051 new CompilationUnitDeclaration(
1053 new CompilationResult(unit, 0, 0, this.options.maxProblemsPerUnit),
1054 regionSource.length);
1055 scanner.resetTo(0, regionSource.length);
1056 scanner.setSource(regionSource);
1058 } catch (AbortCompilation ex) {
1062 * Investigate one constructor declaration.
1064 public void parseConstructor(char[] regionSource) {
1067 goForClassBodyDeclarations();
1071 new CompilationUnitDeclaration(
1073 new CompilationResult(regionSource, 0, 0, this.options.maxProblemsPerUnit),
1074 regionSource.length);
1075 scanner.resetTo(0, regionSource.length);
1076 scanner.setSource(regionSource);
1078 } catch (AbortCompilation ex) {
1082 * Investigate one field declaration statement (might have multiple declarations in it).
1084 public void parseField(char[] regionSource) {
1087 goForFieldDeclaration();
1091 new CompilationUnitDeclaration(
1093 new CompilationResult(regionSource, 0, 0, this.options.maxProblemsPerUnit),
1094 regionSource.length);
1095 scanner.resetTo(0, regionSource.length);
1096 scanner.setSource(regionSource);
1098 } catch (AbortCompilation ex) {
1103 * Investigate one import statement declaration.
1105 public void parseImport(char[] regionSource) {
1108 goForImportDeclaration();
1112 new CompilationUnitDeclaration(
1114 new CompilationResult(regionSource, 0, 0, this.options.maxProblemsPerUnit),
1115 regionSource.length);
1116 scanner.resetTo(0, regionSource.length);
1117 scanner.setSource(regionSource);
1119 } catch (AbortCompilation ex) {
1124 * Investigate one initializer declaration.
1125 * regionSource need to content exactly an initializer declaration.
1126 * e.g: static { i = 4; }
1127 * { name = "test"; }
1129 public void parseInitializer(char[] regionSource) {
1136 new CompilationUnitDeclaration(
1138 new CompilationResult(regionSource, 0, 0, this.options.maxProblemsPerUnit),
1139 regionSource.length);
1140 scanner.resetTo(0, regionSource.length);
1141 scanner.setSource(regionSource);
1143 } catch (AbortCompilation ex) {
1148 * Investigate one method declaration.
1150 public void parseMethod(char[] regionSource) {
1153 goForGenericMethodDeclaration();
1157 new CompilationUnitDeclaration(
1159 new CompilationResult(regionSource, 0, 0, this.options.maxProblemsPerUnit),
1160 regionSource.length);
1161 scanner.resetTo(0, regionSource.length);
1162 scanner.setSource(regionSource);
1164 } catch (AbortCompilation ex) {
1169 * Investigate one package statement declaration.
1171 public void parsePackage(char[] regionSource) {
1174 goForPackageDeclaration();
1178 new CompilationUnitDeclaration(
1180 new CompilationResult(regionSource, 0, 0, this.options.maxProblemsPerUnit),
1181 regionSource.length);
1182 scanner.resetTo(0, regionSource.length);
1183 scanner.setSource(regionSource);
1185 } catch (AbortCompilation ex) {
1190 * Investigate one type declaration, its fields, methods and member types.
1192 public void parseType(char[] regionSource) {
1195 goForTypeDeclaration();
1199 new CompilationUnitDeclaration(
1201 new CompilationResult(regionSource, 0, 0, this.options.maxProblemsPerUnit),
1202 regionSource.length);
1203 scanner.resetTo(0, regionSource.length);
1204 scanner.setSource(regionSource);
1206 } catch (AbortCompilation ex) {
1211 * Returns this parser's problem reporter initialized with its reference context.
1212 * Also it is assumed that a problem is going to be reported, so initializes
1213 * the compilation result's line positions.
1215 public ProblemReporter problemReporter() {
1216 problemReporter.referenceContext = referenceContext;
1217 return problemReporter;
1219 protected void pushOnIntArrayStack(int[] positions) {
1222 intArrayStack[++intArrayPtr] = positions;
1223 } catch (IndexOutOfBoundsException e) {
1225 int oldStackLength = intArrayStack.length;
1226 int oldStack[][] = intArrayStack;
1227 intArrayStack = new int[oldStackLength + StackIncrement][];
1228 System.arraycopy(oldStack, 0, intArrayStack, 0, oldStackLength);
1229 intArrayStack[intArrayPtr] = positions;
1232 protected void resetModifiers() {
1233 super.resetModifiers();
1234 declarationSourceStart = -1;
1237 * Syntax error was detected. Will attempt to perform some recovery action in order
1238 * to resume to the regular parse loop.
1240 protected boolean resumeOnSyntaxError() {
1244 * Answer a char array representation of the type name formatted like:
1245 * - type name + dimensions
1247 * "A[][]".toCharArray()
1248 * "java.lang.String".toCharArray()
1250 private char[] returnTypeName(TypeReference type) {
1251 int dimension = type.dimensions();
1252 if (dimension != 0) {
1253 char[] dimensionsArray = new char[dimension * 2];
1254 for (int i = 0; i < dimension; i++) {
1255 dimensionsArray[i*2] = '[';
1256 dimensionsArray[(i*2) + 1] = ']';
1258 return CharOperation.concat(
1259 CharOperation.concatWith(type.getTypeName(), '.'),
1262 return CharOperation.concatWith(type.getTypeName(), '.');
1264 public String toString() {
1265 StringBuffer buffer = new StringBuffer();
1266 buffer.append("intArrayPtr = " + intArrayPtr + "\n"); //$NON-NLS-1$ //$NON-NLS-2$
1267 buffer.append(super.toString());
1268 return buffer.toString();
1273 protected TypeReference typeReference(
1275 int localIdentifierPtr,
1276 int localIdentifierLengthPtr) {
1277 /* build a Reference on a variable that may be qualified or not
1278 * This variable is a type reference and dim will be its dimensions.
1279 * We don't have any side effect on the stacks' pointers.
1284 if ((length = identifierLengthStack[localIdentifierLengthPtr]) == 1) {
1285 // single variable reference
1288 new SingleTypeReference(
1289 identifierStack[localIdentifierPtr],
1290 identifierPositionStack[localIdentifierPtr--]);
1293 new ArrayTypeReference(
1294 identifierStack[localIdentifierPtr],
1296 identifierPositionStack[localIdentifierPtr--]);
1297 ref.sourceEnd = endPosition;
1300 if (length < 0) { //flag for precompiled type reference on base types
1301 ref = TypeReference.baseTypeReference(-length, dim);
1302 ref.sourceStart = intStack[localIntPtr--];
1304 ref.sourceEnd = intStack[localIntPtr--];
1307 ref.sourceEnd = endPosition;
1309 } else { //Qualified variable reference
1310 char[][] tokens = new char[length][];
1311 localIdentifierPtr -= length;
1312 long[] positions = new long[length];
1313 System.arraycopy(identifierStack, localIdentifierPtr + 1, tokens, 0, length);
1315 identifierPositionStack,
1316 localIdentifierPtr + 1,
1321 ref = new QualifiedTypeReference(tokens, positions);
1323 ref = new ArrayQualifiedTypeReference(tokens, dim, positions);