X-Git-Url: http://secure.phpeclipse.com diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/compiler/DocumentElementParser.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/compiler/DocumentElementParser.java new file mode 100644 index 0000000..a94618b --- /dev/null +++ b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/compiler/DocumentElementParser.java @@ -0,0 +1,1328 @@ +/******************************************************************************* + * 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 , or the end position of a comment line + * immediately following the (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; +} +}