blob: ca700ef79dabcf1bd25116a5a68768aeb7d187d2 [file] [log] [blame]
package org.eclipse.jdt.internal.compiler;
/*
* (c) Copyright IBM Corp. 2000, 2001.
* All Rights Reserved.
*/
/**
* A source element parser extracts structural and reference information
* from a piece of source.
*
* also see @ISourceElementRequestor
*
* The structural investigation includes:
* - the package statement
* - import statements
* - top-level types: package member, member types (member types of member types...)
* - fields
* - methods
*
* If reference information is requested, then all source constructs are
* investigated and type, field & method references are provided as well.
*
* Any (parsing) problem encountered is also provided.
*/
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.*;
public class SourceElementParser extends Parser {
ISourceElementRequestor requestor;
private int lastFieldEndPosition;
private ISourceType sourceType;
private boolean reportReferenceInfo;
private char[][] typeNames;
private char[][] superTypeNames;
private int nestedTypeIndex;
private static final char[] JAVA_LANG_OBJECT = "java.lang.Object"/*nonNLS*/.toCharArray();
public SourceElementParser(
final ISourceElementRequestor requestor,
IProblemFactory problemFactory) {
// we want to notify all syntax error with the acceptProblem API
// To do so, we define the record method of the ProblemReporter
super(new ProblemReporter(
DefaultErrorHandlingPolicies.exitAfterAllProblems(),
new CompilerOptions(),
problemFactory) {
public void record(IProblem problem, CompilationResult unitResult) {
unitResult.record(problem);
requestor.acceptProblem(problem);
}
}, false);
this.requestor = requestor;
typeNames = new char[4][];
superTypeNames = new char[4][];
nestedTypeIndex = 0;
}
protected void classInstanceCreation(boolean alwaysQualified) {
boolean previousFlag = reportReferenceInfo;
reportReferenceInfo = false; // not to see the type reference reported in super call to getTypeReference(...)
super.classInstanceCreation(alwaysQualified);
reportReferenceInfo = previousFlag;
if (reportReferenceInfo){
AllocationExpression alloc = (AllocationExpression)expressionStack[expressionPtr];
TypeReference typeRef = alloc.type;
requestor.acceptConstructorReference(
typeRef instanceof SingleTypeReference
? ((SingleTypeReference) typeRef).token
: CharOperation.concatWith(alloc.type.getTypeName(), '.'),
alloc.arguments == null ? 0 : alloc.arguments.length,
alloc.sourceStart);
}
}
protected void consumeConstructorHeaderName() {
// ConstructorHeaderName ::= Modifiersopt 'Identifier' '('
/* recovering - might be an empty message send */
if (currentElement != null){
if (lastIgnoredToken == TokenNamenew){ // was an allocation expression
lastCheckPoint = scanner.startPosition; // force to restart at this exact position
restartRecovery = true;
return;
}
}
SourceConstructorDeclaration cd = new SourceConstructorDeclaration();
//name -- this is not really revelant but we do .....
cd.selector = identifierStack[identifierPtr];
long selectorSourcePositions = identifierPositionStack[identifierPtr--];
identifierLengthPtr--;
//modifiers
cd.declarationSourceStart = intStack[intPtr--];
cd.modifiers = intStack[intPtr--];
//highlight starts at the selector starts
cd.sourceStart = (int) (selectorSourcePositions >>> 32);
cd.selectorSourceEnd = (int) selectorSourcePositions;
pushOnAstStack(cd);
cd.sourceEnd = lParenPos;
cd.bodyStart = lParenPos+1;
listLength = 0; // initialize listLength before reading parameters/throws
// recovery
if (currentElement != null){
lastCheckPoint = cd.bodyStart;
if ((currentElement instanceof RecoveredType && lastIgnoredToken != TokenNameDOT)
|| cd.modifiers != 0){
currentElement = currentElement.add(cd, 0);
lastIgnoredToken = -1;
}
}
}
/**
*
* 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();
if (isLocalDeclaration() || ((currentToken != TokenNameCOMMA) && (currentToken != TokenNameSEMICOLON)))
return;
((SourceFieldDeclaration) astStack[astPtr]).fieldEndPosition = scanner.currentPosition - 1;
}
protected void consumeExitVariableWithoutInitialization() {
// ExitVariableWithoutInitialization ::= $empty
// do nothing by default
if (isLocalDeclaration() || ((currentToken != TokenNameCOMMA) && (currentToken != TokenNameSEMICOLON)))
return;
((SourceFieldDeclaration) astStack[astPtr]).fieldEndPosition = scanner.currentPosition - 1;
}
/**
*
* INTERNAL USE-ONLY
*/
protected void consumeFieldAccess(boolean isSuperAccess) {
// FieldAccess ::= Primary '.' 'Identifier'
// FieldAccess ::= 'super' '.' 'Identifier'
super.consumeFieldAccess(isSuperAccess);
FieldReference fr = (FieldReference) expressionStack[expressionPtr];
if (reportReferenceInfo) {
requestor.acceptFieldReference(fr.token, fr.sourceStart);
}
}
protected void consumeMethodHeaderName() {
// MethodHeaderName ::= Modifiersopt Type 'Identifier' '('
int length;
SourceMethodDeclaration md = new SourceMethodDeclaration();
//name
md.selector = identifierStack[identifierPtr];
long selectorSourcePositions = identifierPositionStack[identifierPtr--];
identifierLengthPtr--;
//type
md.returnType = getTypeReference(intStack[intPtr--]);
//modifiers
md.declarationSourceStart = intStack[intPtr--];
md.modifiers = intStack[intPtr--];
//highlight starts at selector start
md.sourceStart = (int) (selectorSourcePositions >>> 32);
md.selectorSourceEnd = (int) selectorSourcePositions;
pushOnAstStack(md);
md.sourceEnd = lParenPos;
md.bodyStart = lParenPos+1;
listLength = 0; // initialize listLength before reading parameters/throws
// recovery
if (currentElement != null){
if (currentElement instanceof RecoveredType
//|| md.modifiers != 0
|| (scanner.searchLineNumber(md.returnType.sourceStart)
== scanner.searchLineNumber(md.sourceStart))){
lastCheckPoint = md.bodyStart;
currentElement = currentElement.add(md, 0);
lastIgnoredToken = -1;
} else {
lastCheckPoint = md.sourceStart;
restartRecovery = true;
}
}
}
/**
*
* INTERNAL USE-ONLY
*/
protected void consumeMethodInvocationName() {
// MethodInvocation ::= Name '(' ArgumentListopt ')'
// when the name is only an identifier...we have a message send to "this" (implicit)
super.consumeMethodInvocationName();
MessageSend messageSend = (MessageSend) expressionStack[expressionPtr];
Expression[] args = messageSend.arguments;
if (reportReferenceInfo) {
requestor.acceptMethodReference(
messageSend.selector,
args == null ? 0 : args.length,
(int)(messageSend.nameSourcePosition >>> 32));
}
}
/**
*
* INTERNAL USE-ONLY
*/
protected void consumeMethodInvocationPrimary() {
super.consumeMethodInvocationPrimary();
MessageSend messageSend = (MessageSend) expressionStack[expressionPtr];
Expression[] args = messageSend.arguments;
if (reportReferenceInfo) {
requestor.acceptMethodReference(
messageSend.selector,
args == null ? 0 : args.length,
(int)(messageSend.nameSourcePosition >>> 32));
}
}
/**
*
* INTERNAL USE-ONLY
*/
protected void consumeMethodInvocationSuper() {
// MethodInvocation ::= 'super' '.' 'Identifier' '(' ArgumentListopt ')'
super.consumeMethodInvocationSuper();
MessageSend messageSend = (MessageSend) expressionStack[expressionPtr];
Expression[] args = messageSend.arguments;
if (reportReferenceInfo) {
requestor.acceptMethodReference(
messageSend.selector,
args == null ? 0 : args.length,
(int)(messageSend.nameSourcePosition >>> 32));
}
}
protected void consumeSingleTypeImportDeclarationName() {
// SingleTypeImportDeclarationName ::= 'import' Name
/* push an ImportRef build from the last name
stored in the identifier stack. */
super.consumeSingleTypeImportDeclarationName();
ImportReference impt = (ImportReference)astStack[astPtr];
if (reportReferenceInfo) {
requestor.acceptTypeReference(impt.tokens, impt.sourceStart(), impt.sourceEnd());
}
}
protected void consumeTypeImportOnDemandDeclarationName() {
// TypeImportOnDemandDeclarationName ::= 'import' Name '.' '*'
/* push an ImportRef build from the last name
stored in the identifier stack. */
super.consumeTypeImportOnDemandDeclarationName();
ImportReference impt = (ImportReference)astStack[astPtr];
if (reportReferenceInfo) {
requestor.acceptUnknownReference(impt.tokens, impt.sourceStart(), impt.sourceEnd());
}
}
protected FieldDeclaration createFieldDeclaration(Expression initialization, char[] name, int sourceStart, int sourceEnd) {
return new SourceFieldDeclaration(null, name, sourceStart, sourceEnd);
}
protected CompilationUnitDeclaration endParse(int act) {
if (sourceType != null) {
if (sourceType.isInterface()) {
consumeInterfaceDeclaration();
} else {
consumeClassDeclaration();
}
}
CompilationUnitDeclaration result = super.endParse(act);
notifySourceElementRequestor();
return result;
}
/*
* 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);
}
public 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;
if ((length = identifierLengthStack[identifierLengthPtr--]) == 1) {
// single variable reference
if (dim == 0) {
SingleTypeReference ref =
new SingleTypeReference(
identifierStack[identifierPtr],
identifierPositionStack[identifierPtr--]);
if (reportReferenceInfo) {
requestor.acceptTypeReference(ref.token, ref.sourceStart);
}
return ref;
} else {
ArrayTypeReference ref =
new ArrayTypeReference(
identifierStack[identifierPtr],
dim,
identifierPositionStack[identifierPtr--]);
if (reportReferenceInfo) {
requestor.acceptTypeReference(ref.token, ref.sourceStart);
}
return ref;
}
} else {
if (length < 0) { //flag for precompiled type reference on base types
TypeReference ref = TypeReference.baseTypeReference(-length, dim);
ref.sourceStart = intStack[intPtr--];
return ref;
} 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) {
QualifiedTypeReference ref = new QualifiedTypeReference(tokens, positions);
if (reportReferenceInfo) {
requestor.acceptTypeReference(ref.tokens, ref.sourceStart(), ref.sourceEnd());
}
return ref;
} else {
ArrayQualifiedTypeReference ref =
new ArrayQualifiedTypeReference(tokens, dim, positions);
if (reportReferenceInfo) {
requestor.acceptTypeReference(ref.tokens, ref.sourceStart(), ref.sourceEnd());
}
return ref;
}
}
}
}
public NameReference getUnspecifiedReference() {
/* build a (unspecified) NameReference which may be qualified*/
int length;
if ((length = identifierLengthStack[identifierLengthPtr--]) == 1) {
// single variable reference
SingleNameReference ref =
new SingleNameReference(
identifierStack[identifierPtr],
identifierPositionStack[identifierPtr--]);
if (reportReferenceInfo) {
requestor.acceptUnknownReference(ref.token, ref.sourceStart());
}
return ref;
} else {
//Qualified variable reference
char[][] tokens = new char[length][];
identifierPtr -= length;
System.arraycopy(identifierStack, identifierPtr + 1, tokens, 0, length);
QualifiedNameReference ref =
new QualifiedNameReference(
tokens,
(int) (identifierPositionStack[identifierPtr + 1] >> 32),
// sourceStart
(int) identifierPositionStack[identifierPtr + length]); // sourceEnd
if (reportReferenceInfo) {
requestor.acceptUnknownReference(
ref.tokens,
ref.sourceStart(),
ref.sourceEnd());
}
return ref;
}
}
public NameReference getUnspecifiedReferenceOptimized() {
/* build a (unspecified) NameReference which may be qualified
The optimization occurs for qualified reference while we are
certain in this case the last item of the qualified name is
a field access. This optimization is IMPORTANT while it results
that when a NameReference is build, the type checker should always
look for that it is not a type reference */
int length;
if ((length = identifierLengthStack[identifierLengthPtr--]) == 1) {
// single variable reference
SingleNameReference ref =
new SingleNameReference(
identifierStack[identifierPtr],
identifierPositionStack[identifierPtr--]);
ref.bits &= ~NameReference.RestrictiveFlagMASK;
ref.bits |= LOCAL | FIELD;
if (reportReferenceInfo) {
requestor.acceptUnknownReference(ref.token, ref.sourceStart());
}
return ref;
}
//Qualified-variable-reference
//In fact it is variable-reference DOT field-ref , but it would result in a type
//conflict tha can be only reduce by making a superclass (or inetrface ) between
//nameReference and FiledReference or putting FieldReference under NameReference
//or else..........This optimisation is not really relevant so just leave as it is
char[][] tokens = new char[length][];
identifierPtr -= length;
System.arraycopy(identifierStack, identifierPtr + 1, tokens, 0, length);
QualifiedNameReference ref =
new QualifiedNameReference(
tokens,
(int) (identifierPositionStack[identifierPtr + 1] >> 32),
// sourceStart
(int) identifierPositionStack[identifierPtr + length]); // sourceEnd
ref.bits &= ~NameReference.RestrictiveFlagMASK;
ref.bits |= LOCAL | FIELD;
if (reportReferenceInfo) {
requestor.acceptUnknownReference(
ref.tokens,
ref.sourceStart(),
ref.sourceEnd());
}
return ref;
}
/**
*
* INTERNAL USE-ONLY
*/
private boolean isLocalDeclaration() {
int nestedDepth = nestedType;
while (nestedDepth >= 0) {
if (nestedMethod[nestedDepth] != 0) {
return true;
}
nestedDepth--;
}
return false;
}
/*
* Update the bodyStart of the corresponding parse node
*/
public void notifySourceElementRequestor() {
if (sourceType == null){
if (scanner.initialPosition == 0) {
requestor.enterCompilationUnit();
}
// first we notify the package declaration
ImportReference currentPackage = compilationUnit.currentPackage;
if (currentPackage != null) {
notifySourceElementRequestor(currentPackage, true);
}
// then the imports
ImportReference[] imports = compilationUnit.imports;
if (imports != null) {
for (int i = 0, max = imports.length; i < max; i++) {
notifySourceElementRequestor(imports[i], false);
}
}
}
// then the types contained by this compilation unit
TypeDeclaration[] types = compilationUnit.types;
if (types != null) {
for (int i = 0, max = types.length; i < max; i++) {
notifySourceElementRequestor(types[i], sourceType == null);
}
}
if (sourceType == null){
if (scanner.eofPosition >= compilationUnit.sourceEnd) {
requestor.exitCompilationUnit(compilationUnit.sourceEnd);
}
}
}
/*
* Update the bodyStart of the corresponding parse node
*/
public void notifySourceElementRequestor(AbstractMethodDeclaration methodDeclaration) {
if (methodDeclaration.isClinit())
return;
if (methodDeclaration.isDefaultConstructor()) {
if (reportReferenceInfo) {
ConstructorDeclaration constructorDeclaration = (ConstructorDeclaration) methodDeclaration;
ExplicitConstructorCall constructorCall = constructorDeclaration.constructorCall;
if (constructorCall != null) {
switch(constructorCall.accessMode) {
case ExplicitConstructorCall.This :
requestor.acceptConstructorReference(
typeNames[nestedTypeIndex-1],
constructorCall.arguments == null ? 0 : constructorCall.arguments.length,
constructorCall.sourceStart);
break;
case ExplicitConstructorCall.Super :
case ExplicitConstructorCall.ImplicitSuper :
requestor.acceptConstructorReference(
superTypeNames[nestedTypeIndex-1],
constructorCall.arguments == null ? 0 : constructorCall.arguments.length,
constructorCall.sourceStart);
break;
}
}
}
return;
}
char[][] argumentTypes = null;
char[][] argumentNames = null;
Argument[] arguments = methodDeclaration.arguments;
if (arguments != null) {
int argumentLength = arguments.length;
argumentTypes = new char[argumentLength][];
argumentNames = new char[argumentLength][];
for (int i = 0; i < argumentLength; i++) {
argumentTypes[i] = returnTypeName(arguments[i].type);
argumentNames[i] = arguments[i].name;
}
}
char[][] thrownExceptionTypes = null;
TypeReference[] thrownExceptions = methodDeclaration.thrownExceptions;
if (thrownExceptions != null) {
int thrownExceptionLength = thrownExceptions.length;
thrownExceptionTypes = new char[thrownExceptionLength][];
for (int i = 0; i < thrownExceptionLength; i++) {
thrownExceptionTypes[i] =
CharOperation.concatWith(thrownExceptions[i].getTypeName(), '.');
}
}
// by default no selector end position
int selectorSourceEnd = -1;
if (methodDeclaration.isConstructor()) {
if (methodDeclaration instanceof SourceConstructorDeclaration) {
selectorSourceEnd =
((SourceConstructorDeclaration) methodDeclaration).selectorSourceEnd;
}
if (scanner.initialPosition <= methodDeclaration.declarationSourceStart) {
requestor.enterConstructor(
methodDeclaration.declarationSourceStart,
methodDeclaration.modifiers,
methodDeclaration.selector,
methodDeclaration.sourceStart,
selectorSourceEnd,
argumentTypes,
argumentNames,
thrownExceptionTypes);
if (reportReferenceInfo) {
ConstructorDeclaration constructorDeclaration = (ConstructorDeclaration) methodDeclaration;
ExplicitConstructorCall constructorCall = constructorDeclaration.constructorCall;
if (constructorCall != null) {
switch(constructorCall.accessMode) {
case ExplicitConstructorCall.This :
requestor.acceptConstructorReference(
typeNames[nestedTypeIndex-1],
constructorCall.arguments == null ? 0 : constructorCall.arguments.length,
constructorCall.sourceStart);
break;
case ExplicitConstructorCall.Super :
case ExplicitConstructorCall.ImplicitSuper :
requestor.acceptConstructorReference(
superTypeNames[nestedTypeIndex-1],
constructorCall.arguments == null ? 0 : constructorCall.arguments.length,
constructorCall.sourceStart);
break;
}
}
}
}
if (scanner.eofPosition >= methodDeclaration.declarationSourceEnd) {
requestor.exitConstructor(methodDeclaration.declarationSourceEnd);
}
return;
}
if (methodDeclaration instanceof SourceMethodDeclaration) {
selectorSourceEnd =
((SourceMethodDeclaration) methodDeclaration).selectorSourceEnd;
}
requestor.enterMethod(
methodDeclaration.declarationSourceStart,
methodDeclaration.modifiers,
returnTypeName(((MethodDeclaration) methodDeclaration).returnType),
methodDeclaration.selector,
methodDeclaration.sourceStart,
selectorSourceEnd,
argumentTypes,
argumentNames,
thrownExceptionTypes);
requestor.exitMethod(methodDeclaration.declarationSourceEnd);
}
/*
* Update the bodyStart of the corresponding parse node
*/
public void notifySourceElementRequestor(FieldDeclaration fieldDeclaration) {
if (fieldDeclaration.isField()) {
int fieldEndPosition = fieldDeclaration.declarationSourceEnd;
if (fieldDeclaration instanceof SourceFieldDeclaration) {
fieldEndPosition = ((SourceFieldDeclaration) fieldDeclaration).fieldEndPosition;
if (fieldEndPosition == 0) {
// use the declaration source end by default
fieldEndPosition = fieldDeclaration.declarationSourceEnd;
}
}
requestor.enterField(
fieldDeclaration.declarationSourceStart,
fieldDeclaration.modifiers,
returnTypeName(fieldDeclaration.type),
fieldDeclaration.name,
fieldDeclaration.sourceStart,
fieldDeclaration.sourceEnd);
requestor.exitField(fieldEndPosition);
} else {
requestor.acceptInitializer(
fieldDeclaration.modifiers,
fieldDeclaration.declarationSourceStart,
fieldDeclaration.declarationSourceEnd);
}
}
public void notifySourceElementRequestor(
ImportReference importReference,
boolean isPackage) {
if (isPackage) {
requestor.acceptPackage(
importReference.declarationSourceStart,
importReference.declarationSourceEnd,
CharOperation.concatWith(importReference.getImportName(), '.'));
} else {
requestor.acceptImport(
importReference.declarationSourceStart,
importReference.declarationSourceEnd,
CharOperation.concatWith(importReference.getImportName(), '.'),
importReference.onDemand);
}
}
public void notifySourceElementRequestor(TypeDeclaration typeDeclaration, boolean notifyTypePresence) {
FieldDeclaration[] fields = typeDeclaration.fields;
AbstractMethodDeclaration[] methods = typeDeclaration.methods;
MemberTypeDeclaration[] memberTypes = typeDeclaration.memberTypes;
int fieldCount = fields == null ? 0 : fields.length;
int methodCount = methods == null ? 0 : methods.length;
int memberTypeCount = memberTypes == null ? 0 : memberTypes.length;
int fieldIndex = 0;
int methodIndex = 0;
int memberTypeIndex = 0;
boolean isInterface = typeDeclaration.isInterface();
if (notifyTypePresence){
char[][] interfaceNames = null;
int superInterfacesLength = 0;
TypeReference[] superInterfaces = typeDeclaration.superInterfaces;
if (superInterfaces != null) {
superInterfacesLength = superInterfaces.length;
interfaceNames = new char[superInterfacesLength][];
}
if (superInterfaces != null) {
for (int i = 0; i < superInterfacesLength; i++) {
interfaceNames[i] =
CharOperation.concatWith(superInterfaces[i].getTypeName(), '.');
}
}
if (isInterface) {
requestor.enterInterface(
typeDeclaration.declarationSourceStart,
typeDeclaration.modifiers,
typeDeclaration.name,
typeDeclaration.sourceStart,
typeDeclaration.sourceEnd,
interfaceNames);
if (nestedTypeIndex == typeNames.length) {
// need a resize
System.arraycopy(typeNames, 0, (typeNames = new char[nestedTypeIndex * 2][]), 0, nestedTypeIndex);
System.arraycopy(superTypeNames, 0, (superTypeNames = new char[nestedTypeIndex * 2][]), 0, nestedTypeIndex);
}
typeNames[nestedTypeIndex] = typeDeclaration.name;
superTypeNames[nestedTypeIndex++] = JAVA_LANG_OBJECT;
} else {
TypeReference superclass = typeDeclaration.superclass;
if (superclass == null) {
requestor.enterClass(
typeDeclaration.declarationSourceStart,
typeDeclaration.modifiers,
typeDeclaration.name,
typeDeclaration.sourceStart,
typeDeclaration.sourceEnd,
null,
interfaceNames);
} else {
requestor.enterClass(
typeDeclaration.declarationSourceStart,
typeDeclaration.modifiers,
typeDeclaration.name,
typeDeclaration.sourceStart,
typeDeclaration.sourceEnd,
CharOperation.concatWith(superclass.getTypeName(), '.'),
interfaceNames);
}
if (nestedTypeIndex == typeNames.length) {
// need a resize
System.arraycopy(typeNames, 0, (typeNames = new char[nestedTypeIndex * 2][]), 0, nestedTypeIndex);
System.arraycopy(superTypeNames, 0, (superTypeNames = new char[nestedTypeIndex * 2][]), 0, nestedTypeIndex);
}
typeNames[nestedTypeIndex] = typeDeclaration.name;
superTypeNames[nestedTypeIndex++] = superclass == null ? JAVA_LANG_OBJECT : CharOperation.concatWith(superclass.getTypeName(), '.');
}
}
while ((fieldIndex < fieldCount)
|| (memberTypeIndex < memberTypeCount)
|| (methodIndex < methodCount)) {
FieldDeclaration nextFieldDeclaration = null;
AbstractMethodDeclaration nextMethodDeclaration = null;
TypeDeclaration nextMemberDeclaration = null;
int position = Integer.MAX_VALUE;
int nextDeclarationType = -1;
if (fieldIndex < fieldCount) {
nextFieldDeclaration = fields[fieldIndex];
if (nextFieldDeclaration.declarationSourceStart < position) {
position = nextFieldDeclaration.declarationSourceStart;
nextDeclarationType = 0; // FIELD
}
}
if (methodIndex < methodCount) {
nextMethodDeclaration = methods[methodIndex];
if (nextMethodDeclaration.declarationSourceStart < position) {
position = nextMethodDeclaration.declarationSourceStart;
nextDeclarationType = 1; // METHOD
}
}
if (memberTypeIndex < memberTypeCount) {
nextMemberDeclaration = memberTypes[memberTypeIndex];
if (nextMemberDeclaration.declarationSourceStart < position) {
position = nextMemberDeclaration.declarationSourceStart;
nextDeclarationType = 2; // MEMBER
}
}
switch (nextDeclarationType) {
case 0 :
fieldIndex++;
notifySourceElementRequestor(nextFieldDeclaration);
break;
case 1 :
methodIndex++;
notifySourceElementRequestor(nextMethodDeclaration);
break;
case 2 :
memberTypeIndex++;
notifySourceElementRequestor(nextMemberDeclaration, true);
}
}
if (notifyTypePresence){
if (isInterface) {
requestor.exitInterface(typeDeclaration.declarationSourceEnd);
} else {
requestor.exitClass(typeDeclaration.declarationSourceEnd);
}
nestedTypeIndex--;
}
}
public void parseCompilationUnit(
ICompilationUnit unit,
int start,
int end,
boolean needReferenceInfo) {
CompilationUnitDeclaration result;
reportReferenceInfo = needReferenceInfo;
boolean old = diet;
try {
diet = !needReferenceInfo;
CompilationResult compilationUnitResult = new CompilationResult(unit, 0, 0);
result = parse(unit, compilationUnitResult, start, end);
} catch (AbortCompilation e) {
} finally {
if (scanner.recordLineSeparator) {
requestor.acceptLineSeparatorPositions(scanner.lineEnds());
}
diet = old;
}
}
public void parseCompilationUnit(
ICompilationUnit unit,
boolean needReferenceInfo) {
CompilationUnitDeclaration result;
boolean old = diet;
try {
diet = !needReferenceInfo;
reportReferenceInfo = needReferenceInfo;
CompilationResult compilationUnitResult = new CompilationResult(unit, 0, 0);
result = parse(unit, compilationUnitResult);
} catch (AbortCompilation e) {
} finally {
if (scanner.recordLineSeparator) {
requestor.acceptLineSeparatorPositions(scanner.lineEnds());
}
diet = old;
}
}
public void parseTypeMemberDeclarations(
ISourceType sourceType,
ICompilationUnit sourceUnit,
int start,
int end,
boolean needReferenceInfo) {
boolean old = diet;
try {
diet = !needReferenceInfo;
reportReferenceInfo = needReferenceInfo;
CompilationResult compilationUnitResult =
new CompilationResult(sourceUnit, 0, 0);
CompilationUnitDeclaration unit =
SourceTypeConverter.buildCompilationUnit(
sourceType,
false,
false,
problemReporter(),
compilationUnitResult);
if ((unit == null) || (unit.types == null) || (unit.types.length != 1))
return;
this.sourceType = sourceType;
try {
/* automaton initialization */
initialize();
goForClassBodyDeclarations();
/* scanner initialization */
scanner.setSourceBuffer(sourceUnit.getContents());
int sourceLength = scanner.source.length;
scanner.resetTo(start, end);
/* unit creation */
referenceContext = compilationUnit = unit;
/* initialize the astStacl */
// the compilationUnitDeclaration should contain exactly one type
pushOnAstStack(unit.types[0]);
/* run automaton */
parse();
} finally {
unit = compilationUnit;
compilationUnit = null; // reset parser
}
} catch (AbortCompilation e) {
} finally {
if (scanner.recordLineSeparator) {
requestor.acceptLineSeparatorPositions(scanner.lineEnds());
}
diet = old;
}
}
/*
* 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) {
if (type == null)
return null;
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(), '.');
}
}