--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v0.5
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v05.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ ******************************************************************************/
+package net.sourceforge.phpdt.internal.compiler;
+
+/*
+ * A document element parser extracts structural information
+ * from a piece of source, providing detailed source positions info.
+ *
+ * also see @IDocumentElementRequestor
+ *
+ * The structural investigation includes:
+ * - the package statement
+ * - import statements
+ * - top-level types: package member, member types (member types of member types...)
+ * - fields
+ * - methods
+ *
+ * Any (parsing) problem encountered is also provided.
+ */
+import net.sourceforge.phpdt.internal.compiler.env.*;
+
+import net.sourceforge.phpdt.internal.compiler.impl.*;
+import net.sourceforge.phpdt.core.compiler.*;
+import net.sourceforge.phpdt.internal.compiler.ast.*;
+import net.sourceforge.phpdt.internal.compiler.parser.*;
+import net.sourceforge.phpdt.internal.compiler.problem.*;
+import net.sourceforge.phpdt.internal.compiler.util.*;
+
+public class DocumentElementParser extends Parser {
+ IDocumentElementRequestor requestor;
+ private int localIntPtr;
+ private int lastFieldEndPosition;
+ private int lastFieldBodyEndPosition;
+ private int typeStartPosition;
+ private long selectorSourcePositions;
+ private int typeDims;
+ private int extendsDim;
+ private int declarationSourceStart;
+
+ /* int[] stack for storing javadoc positions */
+ int[][] intArrayStack;
+ int intArrayPtr;
+
+ CompilerOptions options;
+
+public DocumentElementParser(
+ final IDocumentElementRequestor requestor,
+ IProblemFactory problemFactory,
+ CompilerOptions options) {
+ super(new ProblemReporter(
+ DefaultErrorHandlingPolicies.exitAfterAllProblems(),
+ options,
+ problemFactory) {
+ public void record(IProblem problem, CompilationResult unitResult) {
+ requestor.acceptProblem(problem);
+ }
+ },
+ false,
+ options.assertMode);
+ this.requestor = requestor;
+ intArrayStack = new int[30][];
+ this.options = options;
+}
+
+/**
+ *
+ * INTERNAL USE-ONLY
+ */
+protected void adjustInterfaceModifiers() {
+ intStack[intPtr - 2] |= AccInterface;
+}
+/*
+ * Will clear the comment stack when looking
+ * for a potential JavaDoc which might contain @deprecated.
+ *
+ * Additionally, before investigating for @deprecated, retrieve the positions
+ * of the JavaDoc comments so as to notify requestor with them.
+ */
+public void checkAnnotation() {
+
+ /* persisting javadoc positions */
+ pushOnIntArrayStack(this.getJavaDocPositions());
+ boolean deprecated = false;
+ int lastAnnotationIndex = -1;
+
+ //since jdk1.2 look only in the last java doc comment...
+ found : {
+ if ((lastAnnotationIndex = scanner.commentPtr) >= 0) { //look for @deprecated
+ scanner.commentPtr = -1;
+ // reset the comment stack, since not necessary after having checked
+ int commentSourceStart = scanner.commentStarts[lastAnnotationIndex];
+ // javadoc only (non javadoc comment have negative end positions.)
+ int commentSourceEnd = scanner.commentStops[lastAnnotationIndex] - 1;
+ //stop is one over
+ char[] comment = scanner.source;
+
+ for (int i = commentSourceStart + 3; i < commentSourceEnd - 10; i++) {
+ if ((comment[i] == '@')
+ && (comment[i + 1] == 'd')
+ && (comment[i + 2] == 'e')
+ && (comment[i + 3] == 'p')
+ && (comment[i + 4] == 'r')
+ && (comment[i + 5] == 'e')
+ && (comment[i + 6] == 'c')
+ && (comment[i + 7] == 'a')
+ && (comment[i + 8] == 't')
+ && (comment[i + 9] == 'e')
+ && (comment[i + 10] == 'd')) {
+ // ensure the tag is properly ended: either followed by a space, line end or asterisk.
+ int nextPos = i + 11;
+ deprecated =
+ (comment[nextPos] == ' ')
+ || (comment[nextPos] == '\n')
+ || (comment[nextPos] == '\r')
+ || (comment[nextPos] == '*');
+ break found;
+ }
+ }
+ }
+ }
+ if (deprecated) {
+ checkAndSetModifiers(AccDeprecated);
+ }
+ // modify the modifier source start to point at the first comment
+ if (lastAnnotationIndex >= 0) {
+ declarationSourceStart = scanner.commentStarts[0];
+ }
+}
+/**
+ *
+ * INTERNAL USE-ONLY
+ */
+protected void consumeClassBodyDeclaration() {
+ // ClassBodyDeclaration ::= Diet Block
+ //push an Initializer
+ //optimize the push/pop
+
+ super.consumeClassBodyDeclaration();
+ Initializer initializer = (Initializer) astStack[astPtr];
+ requestor.acceptInitializer(
+ initializer.declarationSourceStart,
+ initializer.declarationSourceEnd,
+ intArrayStack[intArrayPtr--],
+ 0,
+ modifiersSourceStart,
+ initializer.block.sourceStart,
+ initializer.block.sourceEnd);
+}
+/**
+ *
+ * INTERNAL USE-ONLY
+ */
+protected void consumeClassDeclaration() {
+ super.consumeClassDeclaration();
+ // we know that we have a TypeDeclaration on the top of the astStack
+ if (isLocalDeclaration()) {
+ // we ignore the local variable declarations
+ return;
+ }
+ requestor.exitClass(endStatementPosition, // '}' is the end of the body
+ ((TypeDeclaration) astStack[astPtr]).declarationSourceEnd);
+}
+/**
+ *
+ * INTERNAL USE-ONLY
+ */
+protected void consumeClassHeader() {
+ //ClassHeader ::= $empty
+ super.consumeClassHeader();
+ if (isLocalDeclaration()) {
+ // we ignore the local variable declarations
+ intArrayPtr--;
+ return;
+ }
+ TypeDeclaration typeDecl = (TypeDeclaration) astStack[astPtr];
+ TypeReference[] superInterfaces = typeDecl.superInterfaces;
+ char[][] interfaceNames = null;
+ int[] interfaceNameStarts = null;
+ int[] interfaceNameEnds = null;
+ if (superInterfaces != null) {
+ int superInterfacesLength = superInterfaces.length;
+ interfaceNames = new char[superInterfacesLength][];
+ interfaceNameStarts = new int[superInterfacesLength];
+ interfaceNameEnds = new int[superInterfacesLength];
+ for (int i = 0; i < superInterfacesLength; i++) {
+ TypeReference superInterface = superInterfaces[i];
+ interfaceNames[i] = CharOperation.concatWith(superInterface.getTypeName(), '.');
+ interfaceNameStarts[i] = superInterface.sourceStart;
+ interfaceNameEnds[i] = superInterface.sourceEnd;
+ }
+ }
+ // flush the comments related to the class header
+ scanner.commentPtr = -1;
+ TypeReference superclass = typeDecl.superclass;
+ if (superclass == null) {
+ requestor.enterClass(
+ typeDecl.declarationSourceStart,
+ intArrayStack[intArrayPtr--],
+ typeDecl.modifiers,
+ typeDecl.modifiersSourceStart,
+ typeStartPosition,
+ typeDecl.name,
+ typeDecl.sourceStart,
+ typeDecl.sourceEnd,
+ null,
+ -1,
+ -1,
+ interfaceNames,
+ interfaceNameStarts,
+ interfaceNameEnds,
+ scanner.currentPosition - 1);
+ } else {
+ requestor.enterClass(
+ typeDecl.declarationSourceStart,
+ intArrayStack[intArrayPtr--],
+ typeDecl.modifiers,
+ typeDecl.modifiersSourceStart,
+ typeStartPosition,
+ typeDecl.name,
+ typeDecl.sourceStart,
+ typeDecl.sourceEnd,
+ CharOperation.concatWith(superclass.getTypeName(), '.'),
+ superclass.sourceStart,
+ superclass.sourceEnd,
+ interfaceNames,
+ interfaceNameStarts,
+ interfaceNameEnds,
+ scanner.currentPosition - 1);
+
+ }
+}
+protected void consumeClassHeaderName() {
+ // ClassHeaderName ::= Modifiersopt 'class' 'Identifier'
+ TypeDeclaration typeDecl;
+ if (nestedMethod[nestedType] == 0) {
+ if (nestedType != 0) {
+ typeDecl = new MemberTypeDeclaration(this.compilationUnit.compilationResult);
+ } else {
+ typeDecl = new TypeDeclaration(this.compilationUnit.compilationResult);
+ }
+ } else {
+ // Record that the block has a declaration for local types
+ typeDecl = new LocalTypeDeclaration(this.compilationUnit.compilationResult);
+ markCurrentMethodWithLocalType();
+ blockReal();
+ }
+
+ //highlight the name of the type
+ long pos = identifierPositionStack[identifierPtr];
+ typeDecl.sourceEnd = (int) pos;
+ typeDecl.sourceStart = (int) (pos >>> 32);
+ typeDecl.name = identifierStack[identifierPtr--];
+ identifierLengthPtr--;
+
+ //compute the declaration source too
+ // 'class' and 'interface' push an int position
+ typeStartPosition = typeDecl.declarationSourceStart = intStack[intPtr--];
+ intPtr--;
+ int declarationSourceStart = intStack[intPtr--];
+ typeDecl.modifiersSourceStart = intStack[intPtr--];
+ typeDecl.modifiers = intStack[intPtr--];
+ if (typeDecl.declarationSourceStart > declarationSourceStart) {
+ typeDecl.declarationSourceStart = declarationSourceStart;
+ }
+ typeDecl.bodyStart = typeDecl.sourceEnd + 1;
+ pushOnAstStack(typeDecl);
+}
+/**
+ *
+ * INTERNAL USE-ONLY
+ */
+protected void consumeCompilationUnit() {
+ // CompilationUnit ::= EnterCompilationUnit PackageDeclarationopt ImportDeclarationsopt
+ requestor.exitCompilationUnit(scanner.source.length - 1);
+}
+/**
+ *
+ * INTERNAL USE-ONLY
+ */
+protected void consumeConstructorDeclaration() {
+ // ConstructorDeclaration ::= ConstructorHeader ConstructorBody
+ super.consumeConstructorDeclaration();
+ if (isLocalDeclaration()) {
+ // we ignore the local variable declarations
+ return;
+ }
+ ConstructorDeclaration cd = (ConstructorDeclaration) astStack[astPtr];
+ requestor.exitConstructor(endStatementPosition, cd.declarationSourceEnd);
+}
+/**
+ *
+ * INTERNAL USE-ONLY
+ */
+protected void consumeConstructorHeader() {
+ // ConstructorHeader ::= ConstructorHeaderName MethodHeaderParameters MethodHeaderThrowsClauseopt
+ super.consumeConstructorHeader();
+ if (isLocalDeclaration()) {
+ // we ignore the local variable declarations
+ intArrayPtr--;
+ return;
+ }
+ ConstructorDeclaration cd = (ConstructorDeclaration) astStack[astPtr];
+ Argument[] arguments = cd.arguments;
+ char[][] argumentTypes = null;
+ char[][] argumentNames = null;
+ int[] argumentTypeStarts = null;
+ int[] argumentTypeEnds = null;
+ int[] argumentNameStarts = null;
+ int[] argumentNameEnds = null;
+ if (arguments != null) {
+ int argumentLength = arguments.length;
+ argumentTypes = new char[argumentLength][];
+ argumentNames = new char[argumentLength][];
+ argumentNameStarts = new int[argumentLength];
+ argumentNameEnds = new int[argumentLength];
+ argumentTypeStarts = new int[argumentLength];
+ argumentTypeEnds = new int[argumentLength];
+ for (int i = 0; i < argumentLength; i++) {
+ Argument argument = arguments[i];
+ TypeReference argumentType = argument.type;
+ argumentTypes[i] = returnTypeName(argumentType);
+ argumentNames[i] = argument.name;
+ argumentNameStarts[i] = argument.sourceStart;
+ argumentNameEnds[i] = argument.sourceEnd;
+ argumentTypeStarts[i] = argumentType.sourceStart;
+ argumentTypeEnds[i] = argumentType.sourceEnd;
+ }
+ }
+ TypeReference[] thrownExceptions = cd.thrownExceptions;
+ char[][] exceptionTypes = null;
+ int[] exceptionTypeStarts = null;
+ int[] exceptionTypeEnds = null;
+ if (thrownExceptions != null) {
+ int thrownExceptionLength = thrownExceptions.length;
+ exceptionTypes = new char[thrownExceptionLength][];
+ exceptionTypeStarts = new int[thrownExceptionLength];
+ exceptionTypeEnds = new int[thrownExceptionLength];
+ for (int i = 0; i < thrownExceptionLength; i++) {
+ TypeReference exception = thrownExceptions[i];
+ exceptionTypes[i] = CharOperation.concatWith(exception.getTypeName(), '.');
+ exceptionTypeStarts[i] = exception.sourceStart;
+ exceptionTypeEnds[i] = exception.sourceEnd;
+ }
+ }
+ requestor
+ .enterConstructor(
+ cd.declarationSourceStart,
+ intArrayStack[intArrayPtr--],
+ cd.modifiers,
+ cd.modifiersSourceStart,
+ cd.selector,
+ cd.sourceStart,
+ (int) (selectorSourcePositions & 0xFFFFFFFFL),
+ // retrieve the source end of the name
+ argumentTypes,
+ argumentTypeStarts,
+ argumentTypeEnds,
+ argumentNames,
+ argumentNameStarts,
+ argumentNameEnds,
+ rParenPos,
+ // right parenthesis
+ exceptionTypes,
+ exceptionTypeStarts,
+ exceptionTypeEnds,
+ scanner.currentPosition - 1);
+}
+protected void consumeConstructorHeaderName() {
+ // ConstructorHeaderName ::= Modifiersopt 'Identifier' '('
+ ConstructorDeclaration cd = new ConstructorDeclaration(this.compilationUnit.compilationResult);
+
+ //name -- this is not really revelant but we do .....
+ cd.selector = identifierStack[identifierPtr];
+ selectorSourcePositions = identifierPositionStack[identifierPtr--];
+ identifierLengthPtr--;
+
+ //modifiers
+ cd.declarationSourceStart = intStack[intPtr--];
+ cd.modifiersSourceStart = intStack[intPtr--];
+ cd.modifiers = intStack[intPtr--];
+
+ //highlight starts at the selector starts
+ cd.sourceStart = (int) (selectorSourcePositions >>> 32);
+ pushOnAstStack(cd);
+
+ cd.sourceEnd = lParenPos;
+ cd.bodyStart = lParenPos + 1;
+}
+protected void consumeDefaultModifiers() {
+ checkAnnotation(); // might update modifiers with AccDeprecated
+ pushOnIntStack(modifiers); // modifiers
+ pushOnIntStack(-1);
+ pushOnIntStack(
+ declarationSourceStart >= 0 ? declarationSourceStart : scanner.startPosition);
+ resetModifiers();
+}
+protected void consumeDiet() {
+ // Diet ::= $empty
+ super.consumeDiet();
+ /* persisting javadoc positions
+ * Will be consume in consumeClassBodyDeclaration
+ */
+ pushOnIntArrayStack(this.getJavaDocPositions());
+}
+/**
+ *
+ * INTERNAL USE-ONLY
+ */
+protected void consumeEnterCompilationUnit() {
+ // EnterCompilationUnit ::= $empty
+ requestor.enterCompilationUnit();
+}
+/**
+ *
+ * INTERNAL USE-ONLY
+ */
+protected void consumeEnterVariable() {
+ // EnterVariable ::= $empty
+ boolean isLocalDeclaration = isLocalDeclaration();
+ if (!isLocalDeclaration && (variablesCounter[nestedType] != 0)) {
+ requestor.exitField(lastFieldBodyEndPosition, lastFieldEndPosition);
+ }
+ char[] name = identifierStack[identifierPtr];
+ long namePosition = identifierPositionStack[identifierPtr--];
+ int extendedTypeDimension = intStack[intPtr--];
+
+ AbstractVariableDeclaration declaration;
+ if (nestedMethod[nestedType] != 0) {
+ // create the local variable declarations
+ declaration =
+ new LocalDeclaration(null, name, (int) (namePosition >>> 32), (int) namePosition);
+ } else {
+ // create the field declaration
+ declaration =
+ new FieldDeclaration(null, name, (int) (namePosition >>> 32), (int) namePosition);
+ }
+ identifierLengthPtr--;
+ TypeReference type;
+ int variableIndex = variablesCounter[nestedType];
+ int typeDim = 0;
+ if (variableIndex == 0) {
+ // first variable of the declaration (FieldDeclaration or LocalDeclaration)
+ if (nestedMethod[nestedType] != 0) {
+ // local declaration
+ declaration.declarationSourceStart = intStack[intPtr--];
+ declaration.modifiersSourceStart = intStack[intPtr--];
+ declaration.modifiers = intStack[intPtr--];
+ type = getTypeReference(typeDim = intStack[intPtr--]); // type dimension
+ pushOnAstStack(type);
+ } else {
+ // field declaration
+ type = getTypeReference(typeDim = intStack[intPtr--]); // type dimension
+ pushOnAstStack(type);
+ declaration.declarationSourceStart = intStack[intPtr--];
+ declaration.modifiersSourceStart = intStack[intPtr--];
+ declaration.modifiers = intStack[intPtr--];
+ }
+ } else {
+ type = (TypeReference) astStack[astPtr - variableIndex];
+ typeDim = type.dimensions();
+ AbstractVariableDeclaration previousVariable =
+ (AbstractVariableDeclaration) astStack[astPtr];
+ declaration.declarationSourceStart = previousVariable.declarationSourceStart;
+ declaration.modifiers = previousVariable.modifiers;
+ declaration.modifiersSourceStart = previousVariable.modifiersSourceStart;
+ }
+
+ localIntPtr = intPtr;
+
+ if (extendedTypeDimension == 0) {
+ declaration.type = type;
+ } else {
+ int dimension = typeDim + extendedTypeDimension;
+ //on the identifierLengthStack there is the information about the type....
+ int baseType;
+ if ((baseType = identifierLengthStack[identifierLengthPtr + 1]) < 0) {
+ //it was a baseType
+ declaration.type = TypeReference.baseTypeReference(-baseType, dimension);
+ declaration.type.sourceStart = type.sourceStart;
+ declaration.type.sourceEnd = type.sourceEnd;
+ } else {
+ declaration.type = this.copyDims(type, dimension);
+ }
+ }
+ variablesCounter[nestedType]++;
+ nestedMethod[nestedType]++;
+ pushOnAstStack(declaration);
+
+ int[] javadocPositions = intArrayStack[intArrayPtr];
+ if (!isLocalDeclaration) {
+ requestor
+ .enterField(
+ declaration.declarationSourceStart,
+ javadocPositions,
+ declaration.modifiers,
+ declaration.modifiersSourceStart,
+ returnTypeName(declaration.type),
+ type.sourceStart,
+ type.sourceEnd,
+ typeDims,
+ name,
+ (int) (namePosition >>> 32),
+ (int) namePosition,
+ extendedTypeDimension,
+ extendedTypeDimension == 0 ? -1 : endPosition);
+ }
+}
+/**
+ *
+ * INTERNAL USE-ONLY
+ */
+protected void consumeExitVariableWithInitialization() {
+ // ExitVariableWithInitialization ::= $empty
+ // the scanner is located after the comma or the semi-colon.
+ // we want to include the comma or the semi-colon
+ super.consumeExitVariableWithInitialization();
+ nestedMethod[nestedType]--;
+ lastFieldEndPosition = scanner.currentPosition - 1;
+ lastFieldBodyEndPosition = ((AbstractVariableDeclaration) astStack[astPtr]).initialization.sourceEnd;
+}
+protected void consumeExitVariableWithoutInitialization() {
+ // ExitVariableWithoutInitialization ::= $empty
+ // do nothing by default
+ super.consumeExitVariableWithoutInitialization();
+ nestedMethod[nestedType]--;
+ lastFieldEndPosition = scanner.currentPosition - 1;
+ lastFieldBodyEndPosition = scanner.startPosition - 1;
+}
+/**
+ *
+ * INTERNAL USE-ONLY
+ */
+protected void consumeFieldDeclaration() {
+ // See consumeLocalVariableDeclarationDefaultModifier() in case of change: duplicated code
+ // FieldDeclaration ::= Modifiersopt Type VariableDeclarators ';'
+ // the super.consumeFieldDeclaration will reinitialize the variableCounter[nestedType]
+ int variableIndex = variablesCounter[nestedType];
+ super.consumeFieldDeclaration();
+ intArrayPtr--;
+ if (isLocalDeclaration())
+ return;
+ if (variableIndex != 0) {
+ requestor.exitField(lastFieldBodyEndPosition, lastFieldEndPosition);
+ }
+}
+protected void consumeFormalParameter() {
+ // FormalParameter ::= Type VariableDeclaratorId ==> false
+ // FormalParameter ::= Modifiers Type VariableDeclaratorId ==> true
+ /*
+ astStack :
+ identifierStack : type identifier
+ intStack : dim dim
+ ==>
+ astStack : Argument
+ identifierStack :
+ intStack :
+ */
+
+ identifierLengthPtr--;
+ char[] name = identifierStack[identifierPtr];
+ long namePositions = identifierPositionStack[identifierPtr--];
+ TypeReference type = getTypeReference(intStack[intPtr--] + intStack[intPtr--]);
+ intPtr -= 3;
+ Argument arg =
+ new Argument(
+ name,
+ namePositions,
+ type,
+ intStack[intPtr + 1]); // modifiers
+ pushOnAstStack(arg);
+ intArrayPtr--;
+}
+/**
+ *
+ * INTERNAL USE-ONLY
+ */
+protected void consumeInterfaceDeclaration() {
+ super.consumeInterfaceDeclaration();
+ // we know that we have a TypeDeclaration on the top of the astStack
+ if (isLocalDeclaration()) {
+ // we ignore the local variable declarations
+ return;
+ }
+ requestor.exitInterface(endStatementPosition, // the '}' is the end of the body
+ ((TypeDeclaration) astStack[astPtr]).declarationSourceEnd);
+}
+/**
+ *
+ * INTERNAL USE-ONLY
+ */
+protected void consumeInterfaceHeader() {
+ //InterfaceHeader ::= $empty
+ super.consumeInterfaceHeader();
+ if (isLocalDeclaration()) {
+ // we ignore the local variable declarations
+ intArrayPtr--;
+ return;
+ }
+ TypeDeclaration typeDecl = (TypeDeclaration) astStack[astPtr];
+ TypeReference[] superInterfaces = typeDecl.superInterfaces;
+ char[][] interfaceNames = null;
+ int[] interfaceNameStarts = null;
+ int[] interfacenameEnds = null;
+ int superInterfacesLength = 0;
+ if (superInterfaces != null) {
+ superInterfacesLength = superInterfaces.length;
+ interfaceNames = new char[superInterfacesLength][];
+ interfaceNameStarts = new int[superInterfacesLength];
+ interfacenameEnds = new int[superInterfacesLength];
+ }
+ if (superInterfaces != null) {
+ for (int i = 0; i < superInterfacesLength; i++) {
+ TypeReference superInterface = superInterfaces[i];
+ interfaceNames[i] = CharOperation.concatWith(superInterface.getTypeName(), '.');
+ interfaceNameStarts[i] = superInterface.sourceStart;
+ interfacenameEnds[i] = superInterface.sourceEnd;
+ }
+ }
+ // flush the comments related to the interface header
+ scanner.commentPtr = -1;
+ requestor.enterInterface(
+ typeDecl.declarationSourceStart,
+ intArrayStack[intArrayPtr--],
+ typeDecl.modifiers,
+ typeDecl.modifiersSourceStart,
+ typeStartPosition,
+ typeDecl.name,
+ typeDecl.sourceStart,
+ typeDecl.sourceEnd,
+ interfaceNames,
+ interfaceNameStarts,
+ interfacenameEnds,
+ scanner.currentPosition - 1);
+}
+protected void consumeInterfaceHeaderName() {
+ // InterfaceHeaderName ::= Modifiersopt 'interface' 'Identifier'
+ TypeDeclaration typeDecl;
+ if (nestedMethod[nestedType] == 0) {
+ if (nestedType != 0) {
+ typeDecl = new MemberTypeDeclaration(this.compilationUnit.compilationResult);
+ } else {
+ typeDecl = new TypeDeclaration(this.compilationUnit.compilationResult);
+ }
+ } else {
+ // Record that the block has a declaration for local types
+ typeDecl = new LocalTypeDeclaration(this.compilationUnit.compilationResult);
+ markCurrentMethodWithLocalType();
+ blockReal();
+ }
+
+ //highlight the name of the type
+ long pos = identifierPositionStack[identifierPtr];
+ typeDecl.sourceEnd = (int) pos;
+ typeDecl.sourceStart = (int) (pos >>> 32);
+ typeDecl.name = identifierStack[identifierPtr--];
+ identifierLengthPtr--;
+
+ //compute the declaration source too
+ // 'class' and 'interface' push an int position
+ typeStartPosition = typeDecl.declarationSourceStart = intStack[intPtr--];
+ intPtr--;
+ int declarationSourceStart = intStack[intPtr--];
+ typeDecl.modifiersSourceStart = intStack[intPtr--];
+ typeDecl.modifiers = intStack[intPtr--];
+ if (typeDecl.declarationSourceStart > declarationSourceStart) {
+ typeDecl.declarationSourceStart = declarationSourceStart;
+ }
+ typeDecl.bodyStart = typeDecl.sourceEnd + 1;
+ pushOnAstStack(typeDecl);
+}
+/**
+ *
+ * INTERNAL USE-ONLY
+ */
+protected void consumeLocalVariableDeclaration() {
+ // See consumeLocalVariableDeclarationDefaultModifier() in case of change: duplicated code
+ // FieldDeclaration ::= Modifiersopt Type VariableDeclarators ';'
+
+ super.consumeLocalVariableDeclaration();
+ intArrayPtr--;
+}
+/**
+ *
+ * INTERNAL USE-ONLY
+ */
+protected void consumeMethodDeclaration(boolean isNotAbstract) {
+ // MethodDeclaration ::= MethodHeader MethodBody
+ // AbstractMethodDeclaration ::= MethodHeader ';'
+ super.consumeMethodDeclaration(isNotAbstract);
+ if (isLocalDeclaration()) {
+ // we ignore the local variable declarations
+ return;
+ }
+ MethodDeclaration md = (MethodDeclaration) astStack[astPtr];
+ requestor.exitMethod(endStatementPosition, md.declarationSourceEnd);
+}
+/**
+ *
+ * INTERNAL USE-ONLY
+ */
+protected void consumeMethodHeader() {
+ // MethodHeader ::= MethodHeaderName MethodHeaderParameters MethodHeaderExtendedDims ThrowsClauseopt
+ super.consumeMethodHeader();
+ if (isLocalDeclaration()) {
+ // we ignore the local variable declarations
+ intArrayPtr--;
+ return;
+ }
+ MethodDeclaration md = (MethodDeclaration) astStack[astPtr];
+
+ TypeReference returnType = md.returnType;
+ char[] returnTypeName = returnTypeName(returnType);
+ Argument[] arguments = md.arguments;
+ char[][] argumentTypes = null;
+ char[][] argumentNames = null;
+ int[] argumentTypeStarts = null;
+ int[] argumentTypeEnds = null;
+ int[] argumentNameStarts = null;
+ int[] argumentNameEnds = null;
+ if (arguments != null) {
+ int argumentLength = arguments.length;
+ argumentTypes = new char[argumentLength][];
+ argumentNames = new char[argumentLength][];
+ argumentNameStarts = new int[argumentLength];
+ argumentNameEnds = new int[argumentLength];
+ argumentTypeStarts = new int[argumentLength];
+ argumentTypeEnds = new int[argumentLength];
+ for (int i = 0; i < argumentLength; i++) {
+ Argument argument = arguments[i];
+ TypeReference argumentType = argument.type;
+ argumentTypes[i] = returnTypeName(argumentType);
+ argumentNames[i] = argument.name;
+ argumentNameStarts[i] = argument.sourceStart;
+ argumentNameEnds[i] = argument.sourceEnd;
+ argumentTypeStarts[i] = argumentType.sourceStart;
+ argumentTypeEnds[i] = argumentType.sourceEnd;
+ }
+ }
+ TypeReference[] thrownExceptions = md.thrownExceptions;
+ char[][] exceptionTypes = null;
+ int[] exceptionTypeStarts = null;
+ int[] exceptionTypeEnds = null;
+ if (thrownExceptions != null) {
+ int thrownExceptionLength = thrownExceptions.length;
+ exceptionTypeStarts = new int[thrownExceptionLength];
+ exceptionTypeEnds = new int[thrownExceptionLength];
+ exceptionTypes = new char[thrownExceptionLength][];
+ for (int i = 0; i < thrownExceptionLength; i++) {
+ TypeReference exception = thrownExceptions[i];
+ exceptionTypes[i] = CharOperation.concatWith(exception.getTypeName(), '.');
+ exceptionTypeStarts[i] = exception.sourceStart;
+ exceptionTypeEnds[i] = exception.sourceEnd;
+ }
+ }
+ requestor
+ .enterMethod(
+ md.declarationSourceStart,
+ intArrayStack[intArrayPtr--],
+ md.modifiers,
+ md.modifiersSourceStart,
+ returnTypeName,
+ returnType.sourceStart,
+ returnType.sourceEnd,
+ typeDims,
+ md.selector,
+ md.sourceStart,
+ (int) (selectorSourcePositions & 0xFFFFFFFFL),
+ argumentTypes,
+ argumentTypeStarts,
+ argumentTypeEnds,
+ argumentNames,
+ argumentNameStarts,
+ argumentNameEnds,
+ rParenPos,
+ extendsDim,
+ extendsDim == 0 ? -1 : endPosition,
+ exceptionTypes,
+ exceptionTypeStarts,
+ exceptionTypeEnds,
+ scanner.currentPosition - 1);
+}
+protected void consumeMethodHeaderExtendedDims() {
+ // MethodHeaderExtendedDims ::= Dimsopt
+ // now we update the returnType of the method
+ MethodDeclaration md = (MethodDeclaration) astStack[astPtr];
+ int extendedDims = intStack[intPtr--];
+ extendsDim = extendedDims;
+ if (extendedDims != 0) {
+ TypeReference returnType = md.returnType;
+ md.sourceEnd = endPosition;
+ int dims = returnType.dimensions() + extendedDims;
+ int baseType;
+ if ((baseType = identifierLengthStack[identifierLengthPtr + 1]) < 0) {
+ //it was a baseType
+ int sourceStart = returnType.sourceStart;
+ int sourceEnd = returnType.sourceEnd;
+ returnType = TypeReference.baseTypeReference(-baseType, dims);
+ returnType.sourceStart = sourceStart;
+ returnType.sourceEnd = sourceEnd;
+ md.returnType = returnType;
+ } else {
+ md.returnType = this.copyDims(md.returnType, dims);
+ }
+ if (currentToken == TokenNameLBRACE) {
+ md.bodyStart = endPosition + 1;
+ }
+ }
+}
+protected void consumeMethodHeaderName() {
+ // MethodHeaderName ::= Modifiersopt Type 'Identifier' '('
+ MethodDeclaration md = new MethodDeclaration(this.compilationUnit.compilationResult);
+
+ //name
+ md.selector = identifierStack[identifierPtr];
+ selectorSourcePositions = identifierPositionStack[identifierPtr--];
+ identifierLengthPtr--;
+ //type
+ md.returnType = getTypeReference(typeDims = intStack[intPtr--]);
+ //modifiers
+ md.declarationSourceStart = intStack[intPtr--];
+ md.modifiersSourceStart = intStack[intPtr--];
+ md.modifiers = intStack[intPtr--];
+
+ //highlight starts at selector start
+ md.sourceStart = (int) (selectorSourcePositions >>> 32);
+ pushOnAstStack(md);
+ md.bodyStart = scanner.currentPosition-1;
+}
+protected void consumeModifiers() {
+ checkAnnotation(); // might update modifiers with AccDeprecated
+ pushOnIntStack(modifiers); // modifiers
+ pushOnIntStack(modifiersSourceStart);
+ pushOnIntStack(
+ declarationSourceStart >= 0 ? declarationSourceStart : modifiersSourceStart);
+ resetModifiers();
+}
+/**
+ *
+ * INTERNAL USE-ONLY
+ */
+protected void consumePackageDeclarationName() {
+ /* persisting javadoc positions */
+ pushOnIntArrayStack(this.getJavaDocPositions());
+
+ super.consumePackageDeclarationName();
+ ImportReference importReference = compilationUnit.currentPackage;
+
+ requestor.acceptPackage(
+ importReference.declarationSourceStart,
+ importReference.declarationSourceEnd,
+ intArrayStack[intArrayPtr--],
+ CharOperation.concatWith(importReference.getImportName(), '.'),
+ importReference.sourceStart);
+}
+protected void consumePushModifiers() {
+ checkAnnotation(); // might update modifiers with AccDeprecated
+ pushOnIntStack(modifiers); // modifiers
+ if (modifiersSourceStart < 0) {
+ pushOnIntStack(-1);
+ pushOnIntStack(
+ declarationSourceStart >= 0 ? declarationSourceStart : scanner.startPosition);
+ } else {
+ pushOnIntStack(modifiersSourceStart);
+ pushOnIntStack(
+ declarationSourceStart >= 0 ? declarationSourceStart : modifiersSourceStart);
+ }
+ resetModifiers();
+}
+/**
+ *
+ * INTERNAL USE-ONLY
+ */
+protected void consumeSingleTypeImportDeclarationName() {
+ // SingleTypeImportDeclarationName ::= 'import' Name
+
+ /* persisting javadoc positions */
+ pushOnIntArrayStack(this.getJavaDocPositions());
+
+ super.consumeSingleTypeImportDeclarationName();
+ ImportReference importReference = (ImportReference) astStack[astPtr];
+ requestor.acceptImport(
+ importReference.declarationSourceStart,
+ importReference.declarationSourceEnd,
+ intArrayStack[intArrayPtr--],
+ CharOperation.concatWith(importReference.getImportName(), '.'),
+ importReference.sourceStart,
+ false);
+}
+/**
+ *
+ * INTERNAL USE-ONLY
+ */
+protected void consumeStaticInitializer() {
+ // StaticInitializer ::= StaticOnly Block
+ //push an Initializer
+ //optimize the push/pop
+ super.consumeStaticInitializer();
+ Initializer initializer = (Initializer) astStack[astPtr];
+ requestor.acceptInitializer(
+ initializer.declarationSourceStart,
+ initializer.declarationSourceEnd,
+ intArrayStack[intArrayPtr--],
+ AccStatic,
+ intStack[intPtr--],
+ initializer.block.sourceStart,
+ initializer.declarationSourceEnd);
+}
+protected void consumeStaticOnly() {
+ // StaticOnly ::= 'static'
+ checkAnnotation(); // might update declaration source start
+ pushOnIntStack(modifiersSourceStart);
+ pushOnIntStack(
+ declarationSourceStart >= 0 ? declarationSourceStart : modifiersSourceStart);
+ jumpOverMethodBody();
+ nestedMethod[nestedType]++;
+ resetModifiers();
+}
+/**
+ *
+ * INTERNAL USE-ONLY
+ */
+protected void consumeTypeImportOnDemandDeclarationName() {
+ // TypeImportOnDemandDeclarationName ::= 'import' Name '.' '*'
+
+ /* persisting javadoc positions */
+ pushOnIntArrayStack(this.getJavaDocPositions());
+
+ super.consumeTypeImportOnDemandDeclarationName();
+ ImportReference importReference = (ImportReference) astStack[astPtr];
+ requestor.acceptImport(
+ importReference.declarationSourceStart,
+ importReference.declarationSourceEnd,
+ intArrayStack[intArrayPtr--],
+ CharOperation.concatWith(importReference.getImportName(), '.'),
+ importReference.sourceStart,
+ true);
+}
+public CompilationUnitDeclaration endParse(int act) {
+ if (scanner.recordLineSeparator) {
+ requestor.acceptLineSeparatorPositions(scanner.getLineEnds());
+ }
+ return super.endParse(act);
+}
+/*
+ * Flush annotations defined prior to a given positions.
+ *
+ * Note: annotations are stacked in syntactical order
+ *
+ * Either answer given <position>, or the end position of a comment line
+ * immediately following the <position> (same line)
+ *
+ * e.g.
+ * void foo(){
+ * } // end of method foo
+ */
+
+public int flushAnnotationsDefinedPriorTo(int position) {
+
+ return lastFieldEndPosition = super.flushAnnotationsDefinedPriorTo(position);
+}
+protected TypeReference getTypeReference(int dim) { /* build a Reference on a variable that may be qualified or not
+This variable is a type reference and dim will be its dimensions*/
+
+ int length;
+ TypeReference ref;
+ if ((length = identifierLengthStack[identifierLengthPtr--]) == 1) {
+ // single variable reference
+ if (dim == 0) {
+ ref =
+ new SingleTypeReference(
+ identifierStack[identifierPtr],
+ identifierPositionStack[identifierPtr--]);
+ } else {
+ ref =
+ new ArrayTypeReference(
+ identifierStack[identifierPtr],
+ dim,
+ identifierPositionStack[identifierPtr--]);
+ ref.sourceEnd = endPosition;
+ }
+ } else {
+ if (length < 0) { //flag for precompiled type reference on base types
+ ref = TypeReference.baseTypeReference(-length, dim);
+ ref.sourceStart = intStack[intPtr--];
+ if (dim == 0) {
+ ref.sourceEnd = intStack[intPtr--];
+ } else {
+ intPtr--;
+ ref.sourceEnd = endPosition;
+ }
+ } else { //Qualified variable reference
+ char[][] tokens = new char[length][];
+ identifierPtr -= length;
+ long[] positions = new long[length];
+ System.arraycopy(identifierStack, identifierPtr + 1, tokens, 0, length);
+ System.arraycopy(
+ identifierPositionStack,
+ identifierPtr + 1,
+ positions,
+ 0,
+ length);
+ if (dim == 0) {
+ ref = new QualifiedTypeReference(tokens, positions);
+ } else {
+ ref = new ArrayQualifiedTypeReference(tokens, dim, positions);
+ ref.sourceEnd = endPosition;
+ }
+ }
+ };
+ return ref;
+}
+public void initialize() {
+ //positionning the parser for a new compilation unit
+ //avoiding stack reallocation and all that....
+ super.initialize();
+ intArrayPtr = -1;
+}
+/**
+ *
+ * INTERNAL USE-ONLY
+ */
+private boolean isLocalDeclaration() {
+ int nestedDepth = nestedType;
+ while (nestedDepth >= 0) {
+ if (nestedMethod[nestedDepth] != 0) {
+ return true;
+ }
+ nestedDepth--;
+ }
+ return false;
+}
+/*
+ * Investigate one entire unit.
+ */
+public void parseCompilationUnit(ICompilationUnit unit) {
+ char[] regionSource = unit.getContents();
+ try {
+ initialize();
+ goForCompilationUnit();
+ referenceContext =
+ compilationUnit =
+ compilationUnit =
+ new CompilationUnitDeclaration(
+ problemReporter(),
+ new CompilationResult(unit, 0, 0, this.options.maxProblemsPerUnit),
+ regionSource.length);
+ scanner.resetTo(0, regionSource.length);
+ scanner.setSource(regionSource);
+ parse();
+ } catch (AbortCompilation ex) {
+ }
+}
+/*
+ * Investigate one constructor declaration.
+ */
+public void parseConstructor(char[] regionSource) {
+ try {
+ initialize();
+ goForClassBodyDeclarations();
+ referenceContext =
+ compilationUnit =
+ compilationUnit =
+ new CompilationUnitDeclaration(
+ problemReporter(),
+ new CompilationResult(regionSource, 0, 0, this.options.maxProblemsPerUnit),
+ regionSource.length);
+ scanner.resetTo(0, regionSource.length);
+ scanner.setSource(regionSource);
+ parse();
+ } catch (AbortCompilation ex) {
+ }
+}
+/*
+ * Investigate one field declaration statement (might have multiple declarations in it).
+ */
+public void parseField(char[] regionSource) {
+ try {
+ initialize();
+ goForFieldDeclaration();
+ referenceContext =
+ compilationUnit =
+ compilationUnit =
+ new CompilationUnitDeclaration(
+ problemReporter(),
+ new CompilationResult(regionSource, 0, 0, this.options.maxProblemsPerUnit),
+ regionSource.length);
+ scanner.resetTo(0, regionSource.length);
+ scanner.setSource(regionSource);
+ parse();
+ } catch (AbortCompilation ex) {
+ }
+
+}
+/*
+ * Investigate one import statement declaration.
+ */
+public void parseImport(char[] regionSource) {
+ try {
+ initialize();
+ goForImportDeclaration();
+ referenceContext =
+ compilationUnit =
+ compilationUnit =
+ new CompilationUnitDeclaration(
+ problemReporter(),
+ new CompilationResult(regionSource, 0, 0, this.options.maxProblemsPerUnit),
+ regionSource.length);
+ scanner.resetTo(0, regionSource.length);
+ scanner.setSource(regionSource);
+ parse();
+ } catch (AbortCompilation ex) {
+ }
+
+}
+/*
+ * Investigate one initializer declaration.
+ * regionSource need to content exactly an initializer declaration.
+ * e.g: static { i = 4; }
+ * { name = "test"; }
+ */
+public void parseInitializer(char[] regionSource) {
+ try {
+ initialize();
+ goForInitializer();
+ referenceContext =
+ compilationUnit =
+ compilationUnit =
+ new CompilationUnitDeclaration(
+ problemReporter(),
+ new CompilationResult(regionSource, 0, 0, this.options.maxProblemsPerUnit),
+ regionSource.length);
+ scanner.resetTo(0, regionSource.length);
+ scanner.setSource(regionSource);
+ parse();
+ } catch (AbortCompilation ex) {
+ }
+
+}
+/*
+ * Investigate one method declaration.
+ */
+public void parseMethod(char[] regionSource) {
+ try {
+ initialize();
+ goForGenericMethodDeclaration();
+ referenceContext =
+ compilationUnit =
+ compilationUnit =
+ new CompilationUnitDeclaration(
+ problemReporter(),
+ new CompilationResult(regionSource, 0, 0, this.options.maxProblemsPerUnit),
+ regionSource.length);
+ scanner.resetTo(0, regionSource.length);
+ scanner.setSource(regionSource);
+ parse();
+ } catch (AbortCompilation ex) {
+ }
+
+}
+/*
+ * Investigate one package statement declaration.
+ */
+public void parsePackage(char[] regionSource) {
+ try {
+ initialize();
+ goForPackageDeclaration();
+ referenceContext =
+ compilationUnit =
+ compilationUnit =
+ new CompilationUnitDeclaration(
+ problemReporter(),
+ new CompilationResult(regionSource, 0, 0, this.options.maxProblemsPerUnit),
+ regionSource.length);
+ scanner.resetTo(0, regionSource.length);
+ scanner.setSource(regionSource);
+ parse();
+ } catch (AbortCompilation ex) {
+ }
+
+}
+/*
+ * Investigate one type declaration, its fields, methods and member types.
+ */
+public void parseType(char[] regionSource) {
+ try {
+ initialize();
+ goForTypeDeclaration();
+ referenceContext =
+ compilationUnit =
+ compilationUnit =
+ new CompilationUnitDeclaration(
+ problemReporter(),
+ new CompilationResult(regionSource, 0, 0, this.options.maxProblemsPerUnit),
+ regionSource.length);
+ scanner.resetTo(0, regionSource.length);
+ scanner.setSource(regionSource);
+ parse();
+ } catch (AbortCompilation ex) {
+ }
+
+}
+/**
+ * Returns this parser's problem reporter initialized with its reference context.
+ * Also it is assumed that a problem is going to be reported, so initializes
+ * the compilation result's line positions.
+ */
+public ProblemReporter problemReporter() {
+ problemReporter.referenceContext = referenceContext;
+ return problemReporter;
+}
+protected void pushOnIntArrayStack(int[] positions) {
+
+ try {
+ intArrayStack[++intArrayPtr] = positions;
+ } catch (IndexOutOfBoundsException e) {
+ //intPtr is correct
+ int oldStackLength = intArrayStack.length;
+ int oldStack[][] = intArrayStack;
+ intArrayStack = new int[oldStackLength + StackIncrement][];
+ System.arraycopy(oldStack, 0, intArrayStack, 0, oldStackLength);
+ intArrayStack[intArrayPtr] = positions;
+ }
+}
+protected void resetModifiers() {
+ super.resetModifiers();
+ declarationSourceStart = -1;
+}
+/*
+ * Syntax error was detected. Will attempt to perform some recovery action in order
+ * to resume to the regular parse loop.
+ */
+protected boolean resumeOnSyntaxError() {
+ return false;
+}
+/*
+ * Answer a char array representation of the type name formatted like:
+ * - type name + dimensions
+ * Example:
+ * "A[][]".toCharArray()
+ * "java.lang.String".toCharArray()
+ */
+private char[] returnTypeName(TypeReference type) {
+ int dimension = type.dimensions();
+ if (dimension != 0) {
+ char[] dimensionsArray = new char[dimension * 2];
+ for (int i = 0; i < dimension; i++) {
+ dimensionsArray[i*2] = '[';
+ dimensionsArray[(i*2) + 1] = ']';
+ }
+ return CharOperation.concat(
+ CharOperation.concatWith(type.getTypeName(), '.'),
+ dimensionsArray);
+ }
+ return CharOperation.concatWith(type.getTypeName(), '.');
+}
+public String toString() {
+ StringBuffer buffer = new StringBuffer();
+ buffer.append("intArrayPtr = " + intArrayPtr + "\n"); //$NON-NLS-1$ //$NON-NLS-2$
+ buffer.append(super.toString());
+ return buffer.toString();
+}
+/**
+ * INTERNAL USE ONLY
+ */
+protected TypeReference typeReference(
+ int dim,
+ int localIdentifierPtr,
+ int localIdentifierLengthPtr) {
+ /* build a Reference on a variable that may be qualified or not
+ * This variable is a type reference and dim will be its dimensions.
+ * We don't have any side effect on the stacks' pointers.
+ */
+
+ int length;
+ TypeReference ref;
+ if ((length = identifierLengthStack[localIdentifierLengthPtr]) == 1) {
+ // single variable reference
+ if (dim == 0) {
+ ref =
+ new SingleTypeReference(
+ identifierStack[localIdentifierPtr],
+ identifierPositionStack[localIdentifierPtr--]);
+ } else {
+ ref =
+ new ArrayTypeReference(
+ identifierStack[localIdentifierPtr],
+ dim,
+ identifierPositionStack[localIdentifierPtr--]);
+ ref.sourceEnd = endPosition;
+ }
+ } else {
+ if (length < 0) { //flag for precompiled type reference on base types
+ ref = TypeReference.baseTypeReference(-length, dim);
+ ref.sourceStart = intStack[localIntPtr--];
+ if (dim == 0) {
+ ref.sourceEnd = intStack[localIntPtr--];
+ } else {
+ localIntPtr--;
+ ref.sourceEnd = endPosition;
+ }
+ } else { //Qualified variable reference
+ char[][] tokens = new char[length][];
+ localIdentifierPtr -= length;
+ long[] positions = new long[length];
+ System.arraycopy(identifierStack, localIdentifierPtr + 1, tokens, 0, length);
+ System.arraycopy(
+ identifierPositionStack,
+ localIdentifierPtr + 1,
+ positions,
+ 0,
+ length);
+ if (dim == 0)
+ ref = new QualifiedTypeReference(tokens, positions);
+ else
+ ref = new ArrayQualifiedTypeReference(tokens, dim, positions);
+ }
+ };
+ return ref;
+}
+}