blob: 340864ca713be49c4f6e1bf3cd3e90ea65d85ffb [file] [log] [blame]
package org.eclipse.jdt.internal.compiler;
/*
* (c) Copyright IBM Corp. 2000, 2001.
* All Rights Reserved.
*/
/*
* 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 org.eclipse.jdt.internal.compiler.Compiler;
import org.eclipse.jdt.internal.compiler.env.*;
import org.eclipse.jdt.internal.compiler.impl.*;
import org.eclipse.jdt.internal.compiler.ast.*;
import org.eclipse.jdt.internal.compiler.parser.*;
import org.eclipse.jdt.internal.compiler.problem.*;
import org.eclipse.jdt.internal.compiler.util.*;
import java.util.Locale;
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;
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.getAssertMode());
this.requestor = requestor;
intArrayStack = new int[30][];
}
public DocumentElementParser(
final IDocumentElementRequestor requestor,
IProblemFactory problemFactory) {
this(requestor, problemFactory, new CompilerOptions());
}
/**
*
* 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;
int length;
if (nestedMethod[nestedType] == 0) {
if (nestedType != 0) {
typeDecl = new MemberTypeDeclaration();
} else {
typeDecl = new TypeDeclaration();
}
} else {
// Record that the block has a declaration for local types
typeDecl = new LocalTypeDeclaration();
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--];
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);
length = 0; // will be updated when reading super-interfaces
}
/**
*
* 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();
//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);
} else {
declaration.type = type.copyDims(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;
int length;
if (nestedMethod[nestedType] == 0) {
if (nestedType != 0) {
typeDecl = new MemberTypeDeclaration();
} else {
typeDecl = new TypeDeclaration();
}
} else {
// Record that the block has a declaration for local types
typeDecl = new LocalTypeDeclaration();
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--];
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;
}
int length;
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 = md.returnType.copyDims(dims);
}
if (currentToken == TokenNameLBRACE) {
md.bodyStart = endPosition + 1;
}
}
}
protected void consumeMethodHeaderName() {
// MethodHeaderName ::= Modifiersopt Type 'Identifier' '('
int length;
MethodDeclaration md = new MethodDeclaration();
//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();
}
protected void consumeToken(int type) {
super.consumeToken(type);
switch (type) {
case TokenNamevoid :
case TokenNameboolean :
case TokenNamebyte :
case TokenNamechar :
case TokenNamedouble :
case TokenNamefloat :
case TokenNameint :
case TokenNamelong :
case TokenNameshort :
// we need this position to know where the base type name ends.
pushOnIntStack(scanner.currentPosition - 1);
break;
}
}
/**
*
* 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.lineEnds());
}
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--]);
}
} else {
if (length < 0) { //flag for precompiled type reference on base types
ref = TypeReference.baseTypeReference(-length, dim);
ref.sourceEnd = intStack[intPtr--];
ref.sourceStart = intStack[intPtr--];
} 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);
}
};
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),
regionSource.length);
scanner.resetTo(0, regionSource.length);
scanner.setSourceBuffer(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),
regionSource.length);
scanner.resetTo(0, regionSource.length);
scanner.setSourceBuffer(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),
regionSource.length);
scanner.resetTo(0, regionSource.length);
scanner.setSourceBuffer(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),
regionSource.length);
scanner.resetTo(0, regionSource.length);
scanner.setSourceBuffer(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),
regionSource.length);
scanner.resetTo(0, regionSource.length);
scanner.setSourceBuffer(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),
regionSource.length);
scanner.resetTo(0, regionSource.length);
scanner.setSourceBuffer(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),
regionSource.length);
scanner.resetTo(0, regionSource.length);
scanner.setSourceBuffer(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),
regionSource.length);
scanner.resetTo(0, regionSource.length);
scanner.setSourceBuffer(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--]);
}
} else {
if (length < 0) { //flag for precompiled type reference on base types
ref = TypeReference.baseTypeReference(-length, dim);
ref.sourceEnd = intStack[localIntPtr--];
ref.sourceStart = intStack[localIntPtr--];
} 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;
}
}