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.core.compiler.IProblem;
29 import net.sourceforge.phpdt.internal.compiler.ast.AbstractVariableDeclaration;
30 import net.sourceforge.phpdt.internal.compiler.ast.Argument;
31 import net.sourceforge.phpdt.internal.compiler.ast.ArrayQualifiedTypeReference;
32 import net.sourceforge.phpdt.internal.compiler.ast.ArrayTypeReference;
33 import net.sourceforge.phpdt.internal.compiler.ast.CompilationUnitDeclaration;
34 import net.sourceforge.phpdt.internal.compiler.ast.ConstructorDeclaration;
35 import net.sourceforge.phpdt.internal.compiler.ast.FieldDeclaration;
36 import net.sourceforge.phpdt.internal.compiler.ast.ImportReference;
37 import net.sourceforge.phpdt.internal.compiler.ast.Initializer;
38 import net.sourceforge.phpdt.internal.compiler.ast.LocalDeclaration;
39 import net.sourceforge.phpdt.internal.compiler.ast.LocalTypeDeclaration;
40 import net.sourceforge.phpdt.internal.compiler.ast.MemberTypeDeclaration;
41 import net.sourceforge.phpdt.internal.compiler.ast.MethodDeclaration;
42 import net.sourceforge.phpdt.internal.compiler.ast.QualifiedTypeReference;
43 import net.sourceforge.phpdt.internal.compiler.ast.SingleTypeReference;
44 import net.sourceforge.phpdt.internal.compiler.ast.TypeDeclaration;
45 import net.sourceforge.phpdt.internal.compiler.ast.TypeReference;
46 import net.sourceforge.phpdt.internal.compiler.env.ICompilationUnit;
47 import net.sourceforge.phpdt.internal.compiler.impl.CompilerOptions;
48 import net.sourceforge.phpdt.internal.compiler.parser.Parser;
49 import net.sourceforge.phpdt.internal.compiler.problem.AbortCompilation;
50 import net.sourceforge.phpdt.internal.compiler.problem.ProblemReporter;
51 import net.sourceforge.phpdt.internal.compiler.util.CharOperation;
53 public class DocumentElementParser extends Parser {
54 IDocumentElementRequestor requestor;
55 private int localIntPtr;
56 private int lastFieldEndPosition;
57 private int lastFieldBodyEndPosition;
58 private int typeStartPosition;
59 private long selectorSourcePositions;
61 private int extendsDim;
62 private int declarationSourceStart;
64 /* int[] stack for storing javadoc positions */
65 int[][] intArrayStack;
68 CompilerOptions options;
70 public DocumentElementParser(
71 final IDocumentElementRequestor requestor,
72 IProblemFactory problemFactory,
73 CompilerOptions options) {
74 super(new ProblemReporter(
75 DefaultErrorHandlingPolicies.exitAfterAllProblems(),
78 public void record(IProblem problem, CompilationResult unitResult) {
79 requestor.acceptProblem(problem);
84 this.requestor = requestor;
85 intArrayStack = new int[30][];
86 this.options = options;
93 protected void adjustInterfaceModifiers() {
94 intStack[intPtr - 2] |= AccInterface;
97 * Will clear the comment stack when looking
98 * for a potential JavaDoc which might contain @deprecated.
100 * Additionally, before investigating for @deprecated, retrieve the positions
101 * of the JavaDoc comments so as to notify requestor with them.
103 public void checkAnnotation() {
105 /* persisting javadoc positions */
106 pushOnIntArrayStack(this.getJavaDocPositions());
107 boolean deprecated = false;
108 int lastAnnotationIndex = -1;
110 //since jdk1.2 look only in the last java doc comment...
112 if ((lastAnnotationIndex = scanner.commentPtr) >= 0) { //look for @deprecated
113 scanner.commentPtr = -1;
114 // reset the comment stack, since not necessary after having checked
115 int commentSourceStart = scanner.commentStarts[lastAnnotationIndex];
116 // javadoc only (non javadoc comment have negative end positions.)
117 int commentSourceEnd = scanner.commentStops[lastAnnotationIndex] - 1;
119 char[] comment = scanner.source;
121 for (int i = commentSourceStart + 3; i < commentSourceEnd - 10; i++) {
122 if ((comment[i] == '@')
123 && (comment[i + 1] == 'd')
124 && (comment[i + 2] == 'e')
125 && (comment[i + 3] == 'p')
126 && (comment[i + 4] == 'r')
127 && (comment[i + 5] == 'e')
128 && (comment[i + 6] == 'c')
129 && (comment[i + 7] == 'a')
130 && (comment[i + 8] == 't')
131 && (comment[i + 9] == 'e')
132 && (comment[i + 10] == 'd')) {
133 // ensure the tag is properly ended: either followed by a space, line end or asterisk.
134 int nextPos = i + 11;
136 (comment[nextPos] == ' ')
137 || (comment[nextPos] == '\n')
138 || (comment[nextPos] == '\r')
139 || (comment[nextPos] == '*');
146 checkAndSetModifiers(AccDeprecated);
148 // modify the modifier source start to point at the first comment
149 if (lastAnnotationIndex >= 0) {
150 declarationSourceStart = scanner.commentStarts[0];
157 protected void consumeClassBodyDeclaration() {
158 // ClassBodyDeclaration ::= Diet Block
159 //push an Initializer
160 //optimize the push/pop
162 super.consumeClassBodyDeclaration();
163 Initializer initializer = (Initializer) astStack[astPtr];
164 requestor.acceptInitializer(
165 initializer.declarationSourceStart,
166 initializer.declarationSourceEnd,
167 intArrayStack[intArrayPtr--],
169 modifiersSourceStart,
170 initializer.block.sourceStart,
171 initializer.block.sourceEnd);
177 protected void consumeClassDeclaration() {
178 super.consumeClassDeclaration();
179 // we know that we have a TypeDeclaration on the top of the astStack
180 if (isLocalDeclaration()) {
181 // we ignore the local variable declarations
184 requestor.exitClass(endStatementPosition, // '}' is the end of the body
185 ((TypeDeclaration) astStack[astPtr]).declarationSourceEnd);
191 protected void consumeClassHeader() {
192 //ClassHeader ::= $empty
193 super.consumeClassHeader();
194 if (isLocalDeclaration()) {
195 // we ignore the local variable declarations
199 TypeDeclaration typeDecl = (TypeDeclaration) astStack[astPtr];
200 TypeReference[] superInterfaces = typeDecl.superInterfaces;
201 char[][] interfaceNames = null;
202 int[] interfaceNameStarts = null;
203 int[] interfaceNameEnds = null;
204 if (superInterfaces != null) {
205 int superInterfacesLength = superInterfaces.length;
206 interfaceNames = new char[superInterfacesLength][];
207 interfaceNameStarts = new int[superInterfacesLength];
208 interfaceNameEnds = new int[superInterfacesLength];
209 for (int i = 0; i < superInterfacesLength; i++) {
210 TypeReference superInterface = superInterfaces[i];
211 interfaceNames[i] = CharOperation.concatWith(superInterface.getTypeName(), '.');
212 interfaceNameStarts[i] = superInterface.sourceStart;
213 interfaceNameEnds[i] = superInterface.sourceEnd;
216 // flush the comments related to the class header
217 scanner.commentPtr = -1;
218 TypeReference superclass = typeDecl.superclass;
219 if (superclass == null) {
220 requestor.enterClass(
221 typeDecl.declarationSourceStart,
222 intArrayStack[intArrayPtr--],
224 typeDecl.modifiersSourceStart,
227 typeDecl.sourceStart,
235 scanner.currentPosition - 1);
237 requestor.enterClass(
238 typeDecl.declarationSourceStart,
239 intArrayStack[intArrayPtr--],
241 typeDecl.modifiersSourceStart,
244 typeDecl.sourceStart,
246 CharOperation.concatWith(superclass.getTypeName(), '.'),
247 superclass.sourceStart,
248 superclass.sourceEnd,
252 scanner.currentPosition - 1);
256 protected void consumeClassHeaderName() {
257 // ClassHeaderName ::= Modifiersopt 'class' 'Identifier'
258 TypeDeclaration typeDecl;
259 if (nestedMethod[nestedType] == 0) {
260 if (nestedType != 0) {
261 typeDecl = new MemberTypeDeclaration(this.compilationUnit.compilationResult);
263 typeDecl = new TypeDeclaration(this.compilationUnit.compilationResult);
266 // Record that the block has a declaration for local types
267 typeDecl = new LocalTypeDeclaration(this.compilationUnit.compilationResult);
268 markCurrentMethodWithLocalType();
272 //highlight the name of the type
273 long pos = identifierPositionStack[identifierPtr];
274 typeDecl.sourceEnd = (int) pos;
275 typeDecl.sourceStart = (int) (pos >>> 32);
276 typeDecl.name = identifierStack[identifierPtr--];
277 identifierLengthPtr--;
279 //compute the declaration source too
280 // 'class' and 'interface' push an int position
281 typeStartPosition = typeDecl.declarationSourceStart = intStack[intPtr--];
283 int declarationSourceStart = intStack[intPtr--];
284 typeDecl.modifiersSourceStart = intStack[intPtr--];
285 typeDecl.modifiers = intStack[intPtr--];
286 if (typeDecl.declarationSourceStart > declarationSourceStart) {
287 typeDecl.declarationSourceStart = declarationSourceStart;
289 typeDecl.bodyStart = typeDecl.sourceEnd + 1;
290 pushOnAstStack(typeDecl);
296 protected void consumeCompilationUnit() {
297 // CompilationUnit ::= EnterCompilationUnit PackageDeclarationopt ImportDeclarationsopt
298 requestor.exitCompilationUnit(scanner.source.length - 1);
304 protected void consumeConstructorDeclaration() {
305 // ConstructorDeclaration ::= ConstructorHeader ConstructorBody
306 super.consumeConstructorDeclaration();
307 if (isLocalDeclaration()) {
308 // we ignore the local variable declarations
311 ConstructorDeclaration cd = (ConstructorDeclaration) astStack[astPtr];
312 requestor.exitConstructor(endStatementPosition, cd.declarationSourceEnd);
318 protected void consumeConstructorHeader() {
319 // ConstructorHeader ::= ConstructorHeaderName MethodHeaderParameters MethodHeaderThrowsClauseopt
320 super.consumeConstructorHeader();
321 if (isLocalDeclaration()) {
322 // we ignore the local variable declarations
326 ConstructorDeclaration cd = (ConstructorDeclaration) astStack[astPtr];
327 Argument[] arguments = cd.arguments;
328 char[][] argumentTypes = null;
329 char[][] argumentNames = null;
330 int[] argumentTypeStarts = null;
331 int[] argumentTypeEnds = null;
332 int[] argumentNameStarts = null;
333 int[] argumentNameEnds = null;
334 if (arguments != null) {
335 int argumentLength = arguments.length;
336 argumentTypes = new char[argumentLength][];
337 argumentNames = new char[argumentLength][];
338 argumentNameStarts = new int[argumentLength];
339 argumentNameEnds = new int[argumentLength];
340 argumentTypeStarts = new int[argumentLength];
341 argumentTypeEnds = new int[argumentLength];
342 for (int i = 0; i < argumentLength; i++) {
343 Argument argument = arguments[i];
344 TypeReference argumentType = argument.type;
345 argumentTypes[i] = returnTypeName(argumentType);
346 argumentNames[i] = argument.name;
347 argumentNameStarts[i] = argument.sourceStart;
348 argumentNameEnds[i] = argument.sourceEnd;
349 argumentTypeStarts[i] = argumentType.sourceStart;
350 argumentTypeEnds[i] = argumentType.sourceEnd;
353 TypeReference[] thrownExceptions = cd.thrownExceptions;
354 char[][] exceptionTypes = null;
355 int[] exceptionTypeStarts = null;
356 int[] exceptionTypeEnds = null;
357 if (thrownExceptions != null) {
358 int thrownExceptionLength = thrownExceptions.length;
359 exceptionTypes = new char[thrownExceptionLength][];
360 exceptionTypeStarts = new int[thrownExceptionLength];
361 exceptionTypeEnds = new int[thrownExceptionLength];
362 for (int i = 0; i < thrownExceptionLength; i++) {
363 TypeReference exception = thrownExceptions[i];
364 exceptionTypes[i] = CharOperation.concatWith(exception.getTypeName(), '.');
365 exceptionTypeStarts[i] = exception.sourceStart;
366 exceptionTypeEnds[i] = exception.sourceEnd;
371 cd.declarationSourceStart,
372 intArrayStack[intArrayPtr--],
374 cd.modifiersSourceStart,
377 (int) (selectorSourcePositions & 0xFFFFFFFFL),
378 // retrieve the source end of the name
390 scanner.currentPosition - 1);
392 protected void consumeConstructorHeaderName() {
393 // ConstructorHeaderName ::= Modifiersopt 'Identifier' '('
394 ConstructorDeclaration cd = new ConstructorDeclaration(this.compilationUnit.compilationResult);
396 //name -- this is not really revelant but we do .....
397 cd.selector = identifierStack[identifierPtr];
398 selectorSourcePositions = identifierPositionStack[identifierPtr--];
399 identifierLengthPtr--;
402 cd.declarationSourceStart = intStack[intPtr--];
403 cd.modifiersSourceStart = intStack[intPtr--];
404 cd.modifiers = intStack[intPtr--];
406 //highlight starts at the selector starts
407 cd.sourceStart = (int) (selectorSourcePositions >>> 32);
410 cd.sourceEnd = lParenPos;
411 cd.bodyStart = lParenPos + 1;
413 protected void consumeDefaultModifiers() {
414 checkAnnotation(); // might update modifiers with AccDeprecated
415 pushOnIntStack(modifiers); // modifiers
418 declarationSourceStart >= 0 ? declarationSourceStart : scanner.startPosition);
421 protected void consumeDiet() {
424 /* persisting javadoc positions
425 * Will be consume in consumeClassBodyDeclaration
427 pushOnIntArrayStack(this.getJavaDocPositions());
433 protected void consumeEnterCompilationUnit() {
434 // EnterCompilationUnit ::= $empty
435 requestor.enterCompilationUnit();
441 protected void consumeEnterVariable() {
442 // EnterVariable ::= $empty
443 boolean isLocalDeclaration = isLocalDeclaration();
444 if (!isLocalDeclaration && (variablesCounter[nestedType] != 0)) {
445 requestor.exitField(lastFieldBodyEndPosition, lastFieldEndPosition);
447 char[] name = identifierStack[identifierPtr];
448 long namePosition = identifierPositionStack[identifierPtr--];
449 int extendedTypeDimension = intStack[intPtr--];
451 AbstractVariableDeclaration declaration;
452 if (nestedMethod[nestedType] != 0) {
453 // create the local variable declarations
455 new LocalDeclaration(null, name, (int) (namePosition >>> 32), (int) namePosition);
457 // create the field declaration
459 new FieldDeclaration(null, name, (int) (namePosition >>> 32), (int) namePosition);
461 identifierLengthPtr--;
463 int variableIndex = variablesCounter[nestedType];
465 if (variableIndex == 0) {
466 // first variable of the declaration (FieldDeclaration or LocalDeclaration)
467 if (nestedMethod[nestedType] != 0) {
469 declaration.declarationSourceStart = intStack[intPtr--];
470 declaration.modifiersSourceStart = intStack[intPtr--];
471 declaration.modifiers = intStack[intPtr--];
472 type = getTypeReference(typeDim = intStack[intPtr--]); // type dimension
473 pushOnAstStack(type);
476 type = getTypeReference(typeDim = intStack[intPtr--]); // type dimension
477 pushOnAstStack(type);
478 declaration.declarationSourceStart = intStack[intPtr--];
479 declaration.modifiersSourceStart = intStack[intPtr--];
480 declaration.modifiers = intStack[intPtr--];
483 type = (TypeReference) astStack[astPtr - variableIndex];
484 typeDim = type.dimensions();
485 AbstractVariableDeclaration previousVariable =
486 (AbstractVariableDeclaration) astStack[astPtr];
487 declaration.declarationSourceStart = previousVariable.declarationSourceStart;
488 declaration.modifiers = previousVariable.modifiers;
489 declaration.modifiersSourceStart = previousVariable.modifiersSourceStart;
492 localIntPtr = intPtr;
494 if (extendedTypeDimension == 0) {
495 declaration.type = type;
497 int dimension = typeDim + extendedTypeDimension;
498 //on the identifierLengthStack there is the information about the type....
500 if ((baseType = identifierLengthStack[identifierLengthPtr + 1]) < 0) {
502 declaration.type = TypeReference.baseTypeReference(-baseType, dimension);
503 declaration.type.sourceStart = type.sourceStart;
504 declaration.type.sourceEnd = type.sourceEnd;
506 declaration.type = this.copyDims(type, dimension);
509 variablesCounter[nestedType]++;
510 nestedMethod[nestedType]++;
511 pushOnAstStack(declaration);
513 int[] javadocPositions = intArrayStack[intArrayPtr];
514 if (!isLocalDeclaration) {
517 declaration.declarationSourceStart,
519 declaration.modifiers,
520 declaration.modifiersSourceStart,
521 returnTypeName(declaration.type),
526 (int) (namePosition >>> 32),
528 extendedTypeDimension,
529 extendedTypeDimension == 0 ? -1 : endPosition);
536 protected void consumeExitVariableWithInitialization() {
537 // ExitVariableWithInitialization ::= $empty
538 // the scanner is located after the comma or the semi-colon.
539 // we want to include the comma or the semi-colon
540 super.consumeExitVariableWithInitialization();
541 nestedMethod[nestedType]--;
542 lastFieldEndPosition = scanner.currentPosition - 1;
543 lastFieldBodyEndPosition = ((AbstractVariableDeclaration) astStack[astPtr]).initialization.sourceEnd;
545 protected void consumeExitVariableWithoutInitialization() {
546 // ExitVariableWithoutInitialization ::= $empty
547 // do nothing by default
548 super.consumeExitVariableWithoutInitialization();
549 nestedMethod[nestedType]--;
550 lastFieldEndPosition = scanner.currentPosition - 1;
551 lastFieldBodyEndPosition = scanner.startPosition - 1;
557 protected void consumeFieldDeclaration() {
558 // See consumeLocalVariableDeclarationDefaultModifier() in case of change: duplicated code
559 // FieldDeclaration ::= Modifiersopt Type VariableDeclarators ';'
560 // the super.consumeFieldDeclaration will reinitialize the variableCounter[nestedType]
561 int variableIndex = variablesCounter[nestedType];
562 super.consumeFieldDeclaration();
564 if (isLocalDeclaration())
566 if (variableIndex != 0) {
567 requestor.exitField(lastFieldBodyEndPosition, lastFieldEndPosition);
570 protected void consumeFormalParameter() {
571 // FormalParameter ::= Type VariableDeclaratorId ==> false
572 // FormalParameter ::= Modifiers Type VariableDeclaratorId ==> true
575 identifierStack : type identifier
583 identifierLengthPtr--;
584 char[] name = identifierStack[identifierPtr];
585 long namePositions = identifierPositionStack[identifierPtr--];
586 TypeReference type = getTypeReference(intStack[intPtr--] + intStack[intPtr--]);
593 intStack[intPtr + 1]); // modifiers
601 protected void consumeInterfaceDeclaration() {
602 super.consumeInterfaceDeclaration();
603 // we know that we have a TypeDeclaration on the top of the astStack
604 if (isLocalDeclaration()) {
605 // we ignore the local variable declarations
608 requestor.exitInterface(endStatementPosition, // the '}' is the end of the body
609 ((TypeDeclaration) astStack[astPtr]).declarationSourceEnd);
615 protected void consumeInterfaceHeader() {
616 //InterfaceHeader ::= $empty
617 super.consumeInterfaceHeader();
618 if (isLocalDeclaration()) {
619 // we ignore the local variable declarations
623 TypeDeclaration typeDecl = (TypeDeclaration) astStack[astPtr];
624 TypeReference[] superInterfaces = typeDecl.superInterfaces;
625 char[][] interfaceNames = null;
626 int[] interfaceNameStarts = null;
627 int[] interfacenameEnds = null;
628 int superInterfacesLength = 0;
629 if (superInterfaces != null) {
630 superInterfacesLength = superInterfaces.length;
631 interfaceNames = new char[superInterfacesLength][];
632 interfaceNameStarts = new int[superInterfacesLength];
633 interfacenameEnds = new int[superInterfacesLength];
635 if (superInterfaces != null) {
636 for (int i = 0; i < superInterfacesLength; i++) {
637 TypeReference superInterface = superInterfaces[i];
638 interfaceNames[i] = CharOperation.concatWith(superInterface.getTypeName(), '.');
639 interfaceNameStarts[i] = superInterface.sourceStart;
640 interfacenameEnds[i] = superInterface.sourceEnd;
643 // flush the comments related to the interface header
644 scanner.commentPtr = -1;
645 requestor.enterInterface(
646 typeDecl.declarationSourceStart,
647 intArrayStack[intArrayPtr--],
649 typeDecl.modifiersSourceStart,
652 typeDecl.sourceStart,
657 scanner.currentPosition - 1);
659 protected void consumeInterfaceHeaderName() {
660 // InterfaceHeaderName ::= Modifiersopt 'interface' 'Identifier'
661 TypeDeclaration typeDecl;
662 if (nestedMethod[nestedType] == 0) {
663 if (nestedType != 0) {
664 typeDecl = new MemberTypeDeclaration(this.compilationUnit.compilationResult);
666 typeDecl = new TypeDeclaration(this.compilationUnit.compilationResult);
669 // Record that the block has a declaration for local types
670 typeDecl = new LocalTypeDeclaration(this.compilationUnit.compilationResult);
671 markCurrentMethodWithLocalType();
675 //highlight the name of the type
676 long pos = identifierPositionStack[identifierPtr];
677 typeDecl.sourceEnd = (int) pos;
678 typeDecl.sourceStart = (int) (pos >>> 32);
679 typeDecl.name = identifierStack[identifierPtr--];
680 identifierLengthPtr--;
682 //compute the declaration source too
683 // 'class' and 'interface' push an int position
684 typeStartPosition = typeDecl.declarationSourceStart = intStack[intPtr--];
686 int declarationSourceStart = intStack[intPtr--];
687 typeDecl.modifiersSourceStart = intStack[intPtr--];
688 typeDecl.modifiers = intStack[intPtr--];
689 if (typeDecl.declarationSourceStart > declarationSourceStart) {
690 typeDecl.declarationSourceStart = declarationSourceStart;
692 typeDecl.bodyStart = typeDecl.sourceEnd + 1;
693 pushOnAstStack(typeDecl);
699 protected void consumeLocalVariableDeclaration() {
700 // See consumeLocalVariableDeclarationDefaultModifier() in case of change: duplicated code
701 // FieldDeclaration ::= Modifiersopt Type VariableDeclarators ';'
703 super.consumeLocalVariableDeclaration();
710 protected void consumeMethodDeclaration(boolean isNotAbstract) {
711 // MethodDeclaration ::= MethodHeader MethodBody
712 // AbstractMethodDeclaration ::= MethodHeader ';'
713 super.consumeMethodDeclaration(isNotAbstract);
714 if (isLocalDeclaration()) {
715 // we ignore the local variable declarations
718 MethodDeclaration md = (MethodDeclaration) astStack[astPtr];
719 requestor.exitMethod(endStatementPosition, md.declarationSourceEnd);
725 protected void consumeMethodHeader() {
726 // MethodHeader ::= MethodHeaderName MethodHeaderParameters MethodHeaderExtendedDims ThrowsClauseopt
727 super.consumeMethodHeader();
728 if (isLocalDeclaration()) {
729 // we ignore the local variable declarations
733 MethodDeclaration md = (MethodDeclaration) astStack[astPtr];
735 TypeReference returnType = md.returnType;
736 char[] returnTypeName = returnTypeName(returnType);
737 Argument[] arguments = md.arguments;
738 char[][] argumentTypes = null;
739 char[][] argumentNames = null;
740 int[] argumentTypeStarts = null;
741 int[] argumentTypeEnds = null;
742 int[] argumentNameStarts = null;
743 int[] argumentNameEnds = null;
744 if (arguments != null) {
745 int argumentLength = arguments.length;
746 argumentTypes = new char[argumentLength][];
747 argumentNames = new char[argumentLength][];
748 argumentNameStarts = new int[argumentLength];
749 argumentNameEnds = new int[argumentLength];
750 argumentTypeStarts = new int[argumentLength];
751 argumentTypeEnds = new int[argumentLength];
752 for (int i = 0; i < argumentLength; i++) {
753 Argument argument = arguments[i];
754 TypeReference argumentType = argument.type;
755 argumentTypes[i] = returnTypeName(argumentType);
756 argumentNames[i] = argument.name;
757 argumentNameStarts[i] = argument.sourceStart;
758 argumentNameEnds[i] = argument.sourceEnd;
759 argumentTypeStarts[i] = argumentType.sourceStart;
760 argumentTypeEnds[i] = argumentType.sourceEnd;
763 TypeReference[] thrownExceptions = md.thrownExceptions;
764 char[][] exceptionTypes = null;
765 int[] exceptionTypeStarts = null;
766 int[] exceptionTypeEnds = null;
767 if (thrownExceptions != null) {
768 int thrownExceptionLength = thrownExceptions.length;
769 exceptionTypeStarts = new int[thrownExceptionLength];
770 exceptionTypeEnds = new int[thrownExceptionLength];
771 exceptionTypes = new char[thrownExceptionLength][];
772 for (int i = 0; i < thrownExceptionLength; i++) {
773 TypeReference exception = thrownExceptions[i];
774 exceptionTypes[i] = CharOperation.concatWith(exception.getTypeName(), '.');
775 exceptionTypeStarts[i] = exception.sourceStart;
776 exceptionTypeEnds[i] = exception.sourceEnd;
781 md.declarationSourceStart,
782 intArrayStack[intArrayPtr--],
784 md.modifiersSourceStart,
786 returnType.sourceStart,
787 returnType.sourceEnd,
791 (int) (selectorSourcePositions & 0xFFFFFFFFL),
800 extendsDim == 0 ? -1 : endPosition,
804 scanner.currentPosition - 1);
806 protected void consumeMethodHeaderExtendedDims() {
807 // MethodHeaderExtendedDims ::= Dimsopt
808 // now we update the returnType of the method
809 MethodDeclaration md = (MethodDeclaration) astStack[astPtr];
810 int extendedDims = intStack[intPtr--];
811 extendsDim = extendedDims;
812 if (extendedDims != 0) {
813 TypeReference returnType = md.returnType;
814 md.sourceEnd = endPosition;
815 int dims = returnType.dimensions() + extendedDims;
817 if ((baseType = identifierLengthStack[identifierLengthPtr + 1]) < 0) {
819 int sourceStart = returnType.sourceStart;
820 int sourceEnd = returnType.sourceEnd;
821 returnType = TypeReference.baseTypeReference(-baseType, dims);
822 returnType.sourceStart = sourceStart;
823 returnType.sourceEnd = sourceEnd;
824 md.returnType = returnType;
826 md.returnType = this.copyDims(md.returnType, dims);
828 if (currentToken == TokenNameLBRACE) {
829 md.bodyStart = endPosition + 1;
833 protected void consumeMethodHeaderName() {
834 // MethodHeaderName ::= Modifiersopt Type 'Identifier' '('
835 MethodDeclaration md = new MethodDeclaration(this.compilationUnit.compilationResult);
838 md.selector = identifierStack[identifierPtr];
839 selectorSourcePositions = identifierPositionStack[identifierPtr--];
840 identifierLengthPtr--;
842 md.returnType = getTypeReference(typeDims = intStack[intPtr--]);
844 md.declarationSourceStart = intStack[intPtr--];
845 md.modifiersSourceStart = intStack[intPtr--];
846 md.modifiers = intStack[intPtr--];
848 //highlight starts at selector start
849 md.sourceStart = (int) (selectorSourcePositions >>> 32);
851 md.bodyStart = scanner.currentPosition-1;
853 protected void consumeModifiers() {
854 checkAnnotation(); // might update modifiers with AccDeprecated
855 pushOnIntStack(modifiers); // modifiers
856 pushOnIntStack(modifiersSourceStart);
858 declarationSourceStart >= 0 ? declarationSourceStart : modifiersSourceStart);
865 protected void consumePackageDeclarationName() {
866 /* persisting javadoc positions */
867 pushOnIntArrayStack(this.getJavaDocPositions());
869 super.consumePackageDeclarationName();
870 ImportReference importReference = compilationUnit.currentPackage;
872 requestor.acceptPackage(
873 importReference.declarationSourceStart,
874 importReference.declarationSourceEnd,
875 intArrayStack[intArrayPtr--],
876 CharOperation.concatWith(importReference.getImportName(), '.'),
877 importReference.sourceStart);
879 protected void consumePushModifiers() {
880 checkAnnotation(); // might update modifiers with AccDeprecated
881 pushOnIntStack(modifiers); // modifiers
882 if (modifiersSourceStart < 0) {
885 declarationSourceStart >= 0 ? declarationSourceStart : scanner.startPosition);
887 pushOnIntStack(modifiersSourceStart);
889 declarationSourceStart >= 0 ? declarationSourceStart : modifiersSourceStart);
897 protected void consumeSingleTypeImportDeclarationName() {
898 // SingleTypeImportDeclarationName ::= 'import' Name
900 /* persisting javadoc positions */
901 pushOnIntArrayStack(this.getJavaDocPositions());
903 super.consumeSingleTypeImportDeclarationName();
904 ImportReference importReference = (ImportReference) astStack[astPtr];
905 requestor.acceptImport(
906 importReference.declarationSourceStart,
907 importReference.declarationSourceEnd,
908 intArrayStack[intArrayPtr--],
909 CharOperation.concatWith(importReference.getImportName(), '.'),
910 importReference.sourceStart,
917 protected void consumeStaticInitializer() {
918 // StaticInitializer ::= StaticOnly Block
919 //push an Initializer
920 //optimize the push/pop
921 super.consumeStaticInitializer();
922 Initializer initializer = (Initializer) astStack[astPtr];
923 requestor.acceptInitializer(
924 initializer.declarationSourceStart,
925 initializer.declarationSourceEnd,
926 intArrayStack[intArrayPtr--],
929 initializer.block.sourceStart,
930 initializer.declarationSourceEnd);
932 protected void consumeStaticOnly() {
933 // StaticOnly ::= 'static'
934 checkAnnotation(); // might update declaration source start
935 pushOnIntStack(modifiersSourceStart);
937 declarationSourceStart >= 0 ? declarationSourceStart : modifiersSourceStart);
938 jumpOverMethodBody();
939 nestedMethod[nestedType]++;
946 protected void consumeTypeImportOnDemandDeclarationName() {
947 // TypeImportOnDemandDeclarationName ::= 'import' Name '.' '*'
949 /* persisting javadoc positions */
950 pushOnIntArrayStack(this.getJavaDocPositions());
952 super.consumeTypeImportOnDemandDeclarationName();
953 ImportReference importReference = (ImportReference) astStack[astPtr];
954 requestor.acceptImport(
955 importReference.declarationSourceStart,
956 importReference.declarationSourceEnd,
957 intArrayStack[intArrayPtr--],
958 CharOperation.concatWith(importReference.getImportName(), '.'),
959 importReference.sourceStart,
962 public CompilationUnitDeclaration endParse(int act) {
963 if (scanner.recordLineSeparator) {
964 requestor.acceptLineSeparatorPositions(scanner.getLineEnds());
966 return super.endParse(act);
969 * Flush annotations defined prior to a given positions.
971 * Note: annotations are stacked in syntactical order
973 * Either answer given <position>, or the end position of a comment line
974 * immediately following the <position> (same line)
978 * } // end of method foo
981 public int flushAnnotationsDefinedPriorTo(int position) {
983 return lastFieldEndPosition = super.flushAnnotationsDefinedPriorTo(position);
985 protected TypeReference getTypeReference(int dim) { /* build a Reference on a variable that may be qualified or not
986 This variable is a type reference and dim will be its dimensions*/
990 if ((length = identifierLengthStack[identifierLengthPtr--]) == 1) {
991 // single variable reference
994 new SingleTypeReference(
995 identifierStack[identifierPtr],
996 identifierPositionStack[identifierPtr--]);
999 new ArrayTypeReference(
1000 identifierStack[identifierPtr],
1002 identifierPositionStack[identifierPtr--]);
1003 ref.sourceEnd = endPosition;
1006 if (length < 0) { //flag for precompiled type reference on base types
1007 ref = TypeReference.baseTypeReference(-length, dim);
1008 ref.sourceStart = intStack[intPtr--];
1010 ref.sourceEnd = intStack[intPtr--];
1013 ref.sourceEnd = endPosition;
1015 } else { //Qualified variable reference
1016 char[][] tokens = new char[length][];
1017 identifierPtr -= length;
1018 long[] positions = new long[length];
1019 System.arraycopy(identifierStack, identifierPtr + 1, tokens, 0, length);
1021 identifierPositionStack,
1027 ref = new QualifiedTypeReference(tokens, positions);
1029 ref = new ArrayQualifiedTypeReference(tokens, dim, positions);
1030 ref.sourceEnd = endPosition;
1036 public void initialize() {
1037 //positionning the parser for a new compilation unit
1038 //avoiding stack reallocation and all that....
1046 private boolean isLocalDeclaration() {
1047 int nestedDepth = nestedType;
1048 while (nestedDepth >= 0) {
1049 if (nestedMethod[nestedDepth] != 0) {
1057 * Investigate one entire unit.
1059 public void parseCompilationUnit(ICompilationUnit unit) {
1060 char[] regionSource = unit.getContents();
1063 goForCompilationUnit();
1067 new CompilationUnitDeclaration(
1069 new CompilationResult(unit, 0, 0, this.options.maxProblemsPerUnit),
1070 regionSource.length);
1071 scanner.resetTo(0, regionSource.length);
1072 scanner.setSource(regionSource);
1074 } catch (AbortCompilation ex) {
1078 * Investigate one constructor declaration.
1080 public void parseConstructor(char[] regionSource) {
1083 goForClassBodyDeclarations();
1087 new CompilationUnitDeclaration(
1089 new CompilationResult(regionSource, 0, 0, this.options.maxProblemsPerUnit),
1090 regionSource.length);
1091 scanner.resetTo(0, regionSource.length);
1092 scanner.setSource(regionSource);
1094 } catch (AbortCompilation ex) {
1098 * Investigate one field declaration statement (might have multiple declarations in it).
1100 public void parseField(char[] regionSource) {
1103 goForFieldDeclaration();
1107 new CompilationUnitDeclaration(
1109 new CompilationResult(regionSource, 0, 0, this.options.maxProblemsPerUnit),
1110 regionSource.length);
1111 scanner.resetTo(0, regionSource.length);
1112 scanner.setSource(regionSource);
1114 } catch (AbortCompilation ex) {
1119 * Investigate one import statement declaration.
1121 public void parseImport(char[] regionSource) {
1124 goForImportDeclaration();
1128 new CompilationUnitDeclaration(
1130 new CompilationResult(regionSource, 0, 0, this.options.maxProblemsPerUnit),
1131 regionSource.length);
1132 scanner.resetTo(0, regionSource.length);
1133 scanner.setSource(regionSource);
1135 } catch (AbortCompilation ex) {
1140 * Investigate one initializer declaration.
1141 * regionSource need to content exactly an initializer declaration.
1142 * e.g: static { i = 4; }
1143 * { name = "test"; }
1145 public void parseInitializer(char[] regionSource) {
1152 new CompilationUnitDeclaration(
1154 new CompilationResult(regionSource, 0, 0, this.options.maxProblemsPerUnit),
1155 regionSource.length);
1156 scanner.resetTo(0, regionSource.length);
1157 scanner.setSource(regionSource);
1159 } catch (AbortCompilation ex) {
1164 * Investigate one method declaration.
1166 public void parseMethod(char[] regionSource) {
1169 goForGenericMethodDeclaration();
1173 new CompilationUnitDeclaration(
1175 new CompilationResult(regionSource, 0, 0, this.options.maxProblemsPerUnit),
1176 regionSource.length);
1177 scanner.resetTo(0, regionSource.length);
1178 scanner.setSource(regionSource);
1180 } catch (AbortCompilation ex) {
1185 * Investigate one package statement declaration.
1187 public void parsePackage(char[] regionSource) {
1190 goForPackageDeclaration();
1194 new CompilationUnitDeclaration(
1196 new CompilationResult(regionSource, 0, 0, this.options.maxProblemsPerUnit),
1197 regionSource.length);
1198 scanner.resetTo(0, regionSource.length);
1199 scanner.setSource(regionSource);
1201 } catch (AbortCompilation ex) {
1206 * Investigate one type declaration, its fields, methods and member types.
1208 public void parseType(char[] regionSource) {
1211 goForTypeDeclaration();
1215 new CompilationUnitDeclaration(
1217 new CompilationResult(regionSource, 0, 0, this.options.maxProblemsPerUnit),
1218 regionSource.length);
1219 scanner.resetTo(0, regionSource.length);
1220 scanner.setSource(regionSource);
1222 } catch (AbortCompilation ex) {
1227 * Returns this parser's problem reporter initialized with its reference context.
1228 * Also it is assumed that a problem is going to be reported, so initializes
1229 * the compilation result's line positions.
1231 public ProblemReporter problemReporter() {
1232 problemReporter.referenceContext = referenceContext;
1233 return problemReporter;
1235 protected void pushOnIntArrayStack(int[] positions) {
1238 intArrayStack[++intArrayPtr] = positions;
1239 } catch (IndexOutOfBoundsException e) {
1241 int oldStackLength = intArrayStack.length;
1242 int oldStack[][] = intArrayStack;
1243 intArrayStack = new int[oldStackLength + StackIncrement][];
1244 System.arraycopy(oldStack, 0, intArrayStack, 0, oldStackLength);
1245 intArrayStack[intArrayPtr] = positions;
1248 protected void resetModifiers() {
1249 super.resetModifiers();
1250 declarationSourceStart = -1;
1253 * Syntax error was detected. Will attempt to perform some recovery action in order
1254 * to resume to the regular parse loop.
1256 protected boolean resumeOnSyntaxError() {
1260 * Answer a char array representation of the type name formatted like:
1261 * - type name + dimensions
1263 * "A[][]".toCharArray()
1264 * "java.lang.String".toCharArray()
1266 private char[] returnTypeName(TypeReference type) {
1267 int dimension = type.dimensions();
1268 if (dimension != 0) {
1269 char[] dimensionsArray = new char[dimension * 2];
1270 for (int i = 0; i < dimension; i++) {
1271 dimensionsArray[i*2] = '[';
1272 dimensionsArray[(i*2) + 1] = ']';
1274 return CharOperation.concat(
1275 CharOperation.concatWith(type.getTypeName(), '.'),
1278 return CharOperation.concatWith(type.getTypeName(), '.');
1280 public String toString() {
1281 StringBuffer buffer = new StringBuffer();
1282 buffer.append("intArrayPtr = " + intArrayPtr + "\n"); //$NON-NLS-1$ //$NON-NLS-2$
1283 buffer.append(super.toString());
1284 return buffer.toString();
1289 protected TypeReference typeReference(
1291 int localIdentifierPtr,
1292 int localIdentifierLengthPtr) {
1293 /* build a Reference on a variable that may be qualified or not
1294 * This variable is a type reference and dim will be its dimensions.
1295 * We don't have any side effect on the stacks' pointers.
1300 if ((length = identifierLengthStack[localIdentifierLengthPtr]) == 1) {
1301 // single variable reference
1304 new SingleTypeReference(
1305 identifierStack[localIdentifierPtr],
1306 identifierPositionStack[localIdentifierPtr--]);
1309 new ArrayTypeReference(
1310 identifierStack[localIdentifierPtr],
1312 identifierPositionStack[localIdentifierPtr--]);
1313 ref.sourceEnd = endPosition;
1316 if (length < 0) { //flag for precompiled type reference on base types
1317 ref = TypeReference.baseTypeReference(-length, dim);
1318 ref.sourceStart = intStack[localIntPtr--];
1320 ref.sourceEnd = intStack[localIntPtr--];
1323 ref.sourceEnd = endPosition;
1325 } else { //Qualified variable reference
1326 char[][] tokens = new char[length][];
1327 localIdentifierPtr -= length;
1328 long[] positions = new long[length];
1329 System.arraycopy(identifierStack, localIdentifierPtr + 1, tokens, 0, length);
1331 identifierPositionStack,
1332 localIdentifierPtr + 1,
1337 ref = new QualifiedTypeReference(tokens, positions);
1339 ref = new ArrayQualifiedTypeReference(tokens, dim, positions);