List of usage examples for org.eclipse.jdt.internal.compiler.ast Javadoc sourceEnd
public int sourceEnd()
From source file:spoon.support.compiler.jdt.PositionBuilder.java
License:Open Source License
SourcePosition buildPositionCtElement(CtElement e, ASTNode node) {
if (e instanceof CtCatch) {
//we cannot compute position of CtCatch, because we do not know position of it's body yet
//it is computed later by #buildPosition(CtCatch)
return SourcePosition.NOPOSITION;
}/*w w w . j ava2 s. c om*/
CoreFactory cf = this.jdtTreeBuilder.getFactory().Core();
CompilationUnit cu = this.jdtTreeBuilder.getContextBuilder().compilationUnitSpoon;
int[] lineSeparatorPositions = jdtTreeBuilder.getContextBuilder()
.getCompilationUnitLineSeparatorPositions();
char[] contents = jdtTreeBuilder.getContextBuilder().getCompilationUnitContents();
int sourceStart = node.sourceStart;
int sourceEnd = node.sourceEnd;
if ((node instanceof Annotation)) {
Annotation ann = (Annotation) node;
int declEnd = ann.declarationSourceEnd;
if (declEnd > 0) {
sourceEnd = declEnd;
}
} else if ((node instanceof Expression)) {
Expression expression = (Expression) node;
int statementEnd = expression.statementEnd;
if (statementEnd > 0) {
sourceEnd = statementEnd;
}
if (this.jdtTreeBuilder.getContextBuilder().isBuildTypeCast && e instanceof CtTypeReference) {
//the type cast reference must be enclosed with brackets
int declarationSourceStart = sourceStart;
int declarationSourceEnd = sourceEnd;
declarationSourceStart = findPrevNonWhitespace(contents, getParentsSourceStart(),
declarationSourceStart - 1);
if (contents[declarationSourceStart] != '(') {
return handlePositionProblem("Unexpected character \'" + contents[declarationSourceStart]
+ "\' at start of cast expression on offset: " + declarationSourceStart);
}
declarationSourceEnd = findNextNonWhitespace(contents, contents.length - 1,
declarationSourceEnd + 1);
if (contents[declarationSourceEnd] != ')') {
return handlePositionProblem("Unexpected character \'" + contents[declarationSourceStart]
+ "\' at end of cast expression on offset: " + declarationSourceEnd);
}
return cf.createCompoundSourcePosition(cu, sourceStart, sourceEnd, declarationSourceStart,
declarationSourceEnd, lineSeparatorPositions);
}
List<CastInfo> casts = this.jdtTreeBuilder.getContextBuilder().casts;
if (!casts.isEmpty() && e instanceof CtExpression) {
int declarationSourceStart = sourceStart;
int declarationSourceEnd = sourceEnd;
SourcePosition pos = casts.get(0).typeRef.getPosition();
if (pos.isValidPosition()) {
declarationSourceStart = pos.getSourceStart();
int nrOfBrackets = getNrOfFirstCastExpressionBrackets();
while (nrOfBrackets > 0) {
declarationSourceStart = findPrevNonWhitespace(contents, getParentsSourceStart(),
declarationSourceStart - 1);
if (declarationSourceStart < 0) {
return handlePositionProblem("Cannot found beginning of cast expression until offset: "
+ getParentsSourceStart());
}
if (contents[declarationSourceStart] != '(') {
return handlePositionProblem(
"Unexpected character \'" + contents[declarationSourceStart]
+ "\' at start of expression on offset: " + declarationSourceStart);
}
nrOfBrackets--;
}
nrOfBrackets = getNrOfCastExpressionBrackets();
while (nrOfBrackets > 0) {
declarationSourceEnd = findNextNonWhitespace(contents, contents.length - 1,
declarationSourceEnd + 1);
if (contents[declarationSourceEnd] != ')') {
return handlePositionProblem(
"Unexpected character \'" + contents[declarationSourceStart]
+ "\' at end of expression on offset: " + declarationSourceEnd);
}
nrOfBrackets--;
}
}
return cf.createCompoundSourcePosition(cu, sourceStart, sourceEnd, declarationSourceStart,
declarationSourceEnd, lineSeparatorPositions);
}
}
if (node instanceof TypeParameter) {
TypeParameter typeParameter = (TypeParameter) node;
sourceStart = typeParameter.declarationSourceStart;
sourceEnd = typeParameter.declarationSourceEnd;
if (typeParameter.type != null) {
sourceEnd = getSourceEndOfTypeReference(contents, typeParameter.type, sourceEnd);
}
} else if (node instanceof AbstractVariableDeclaration) {
AbstractVariableDeclaration variableDeclaration = (AbstractVariableDeclaration) node;
int modifiersSourceStart = variableDeclaration.modifiersSourceStart;
int declarationSourceStart = variableDeclaration.declarationSourceStart;
int declarationSourceEnd = variableDeclaration.declarationSourceEnd;
if (declarationSourceStart == 0 && declarationSourceEnd == 0) {
return SourcePosition.NOPOSITION;
}
if (e instanceof CtCatchVariable) {
/* compiler delivers wrong declarationSourceStart in case like: */
//... catch/*2*/ ( /*3*/ final @Deprecated /*4*/ ClassCastException /*5*/ e /*6*/) /*7*/ {
/*
* the declarationSourceStart should be after the '(', but sometime it is before
* So we have to compute correct offset here
*/
CtTry tryStatement = this.jdtTreeBuilder.getContextBuilder().getParentElementOfType(CtTry.class);
int endOfTry = tryStatement.getPosition().getSourceEnd();
//offset of the bracket before catch
int lastBracket = getEndOfLastTryBlock(tryStatement, 0);
int catchStart = findNextNonWhitespace(contents, endOfTry, lastBracket + 1);
if (CATCH.equals(new String(contents, catchStart, CATCH.length())) == false) {
return handlePositionProblem(
"Unexpected beginning of catch statement on offset: " + catchStart);
}
int bracketStart = findNextNonWhitespace(contents, endOfTry, catchStart + CATCH.length());
if (bracketStart < 0) {
return handlePositionProblem(
"Unexpected end of file instead of \'(\' after catch statement on offset: "
+ catchStart);
}
if (contents[bracketStart] != '(') {
return handlePositionProblem("Unexpected character " + contents[bracketStart]
+ " instead of \'(\' after catch statement on offset: " + bracketStart);
}
declarationSourceStart = bracketStart + 1;
}
CtElement parent = this.jdtTreeBuilder.getContextBuilder().getContextElementOnLevel(1);
if (parent instanceof CtForEach) {
CtForEach forEach = (CtForEach) parent;
//compiler deliver wrong local variable position when for(...:...) starts with line comment
int parentStart = parent.getPosition().getSourceStart();
if (contents[parentStart] != 'f' || contents[parentStart + 1] != 'o'
|| contents[parentStart + 2] != 'r') {
return handlePositionProblem("Expected keyword for at offset: " + parentStart);
}
int bracketOff = findNextNonWhitespace(contents, forEach.getPosition().getSourceEnd(),
parentStart + 3);
if (bracketOff < 0 || contents[bracketOff] != '(') {
return handlePositionProblem(
"Expected character after \'for\' instead of \'(\' at offset: " + (parentStart + 3));
}
declarationSourceStart = bracketOff + 1;
declarationSourceEnd = sourceEnd;
}
if (variableDeclaration instanceof Argument && variableDeclaration.type instanceof ArrayTypeReference) {
//handle type declarations like `String[] arg` `String arg[]` and `String []arg[]`
ArrayTypeReference arrTypeRef = (ArrayTypeReference) variableDeclaration.type;
int dimensions = arrTypeRef.dimensions();
if (dimensions > 0) {
//count number of brackets between type and variable name
int foundDimensions = getNrOfDimensions(contents, declarationSourceStart, declarationSourceEnd);
while (dimensions > foundDimensions) {
//some brackets are after the variable name
declarationSourceEnd = findNextChar(contents, contents.length, declarationSourceEnd + 1,
']');
if (declarationSourceEnd < 0) {
return handlePositionProblem(
"Unexpected array type declaration on offset: " + declarationSourceStart);
}
foundDimensions++;
}
}
}
// Handle lambda parameters without explicit type
if (variableDeclaration instanceof Argument && variableDeclaration.type == null) {
declarationSourceStart = findPrevNonWhitespace(contents, 0, declarationSourceStart - 1);
declarationSourceEnd = findNextNonWhitespace(contents, contents.length - 1,
declarationSourceEnd + 1);
}
if (modifiersSourceStart <= 0) {
modifiersSourceStart = findNextNonWhitespace(contents, contents.length - 1, declarationSourceStart);
}
int modifiersSourceEnd;
if (variableDeclaration.type != null) {
modifiersSourceEnd = findPrevNonWhitespace(contents, declarationSourceStart,
variableDeclaration.type.sourceStart() - 1);
} else if (variableDeclaration instanceof Initializer) {
modifiersSourceEnd = ((Initializer) variableDeclaration).block.sourceStart - 1;
} else {
// variable that has no type such as TypeParameter
modifiersSourceEnd = declarationSourceStart - 1;
}
// when no modifier
if (modifiersSourceStart > modifiersSourceEnd) {
modifiersSourceEnd = modifiersSourceStart - 1;
} else if (e instanceof CtModifiable) {
setModifiersPosition((CtModifiable) e, modifiersSourceStart, modifiersSourceEnd);
}
return cf.createDeclarationSourcePosition(cu, sourceStart, sourceEnd, modifiersSourceStart,
modifiersSourceEnd, declarationSourceStart, declarationSourceEnd, lineSeparatorPositions);
} else if (node instanceof TypeDeclaration && e instanceof CtPackage) {
// the position returned by JTD is equals to 0
return cf.createSourcePosition(cu, 0, contents.length - 1, lineSeparatorPositions);
} else if (node instanceof TypeDeclaration) {
TypeDeclaration typeDeclaration = (TypeDeclaration) node;
int declarationSourceStart = typeDeclaration.declarationSourceStart;
int declarationSourceEnd = typeDeclaration.declarationSourceEnd;
int modifiersSourceStart = typeDeclaration.modifiersSourceStart;
int bodyStart = typeDeclaration.bodyStart;
int bodyEnd = typeDeclaration.bodyEnd;
int modifiersSourceEnd;
if (typeDeclaration.name.length == 0) {
//it is anonymous type
if (contents[bodyStart] != '{') {
//adjust bodyStart of annonymous type in definition of enum value
if (bodyStart < 1 || contents[bodyStart - 1] != '{') {
throw new SpoonException("Cannot found body start at offset " + bodyStart
+ " of annonymous class with sources:\n" + new String(contents));
}
bodyStart--;
}
declarationSourceStart = modifiersSourceStart = sourceStart = bodyStart;
if (contents[bodyEnd] != '}') {
//adjust bodyEnd of annonymous type in definition of enum value
if (contents[bodyEnd + 1] != '}') {
throw new SpoonException("Cannot found body end at offset " + bodyEnd
+ " of annonymous class with sources:\n" + new String(contents));
}
bodyEnd++;
}
declarationSourceEnd = bodyEnd;
//there is no name of annonymous class
sourceEnd = sourceStart - 1;
//there are no modifiers of annonymous class
modifiersSourceEnd = modifiersSourceStart - 1;
bodyStart++;
} else {
if (modifiersSourceStart <= 0) {
modifiersSourceStart = declarationSourceStart;
}
//look for start of first keyword before the type keyword e.g. "class". `sourceStart` points at first char of type name
modifiersSourceEnd = findPrevNonWhitespace(contents, modifiersSourceStart - 1,
findPrevWhitespace(contents, modifiersSourceStart - 1,
findPrevNonWhitespace(contents, modifiersSourceStart - 1, sourceStart - 1)));
if (e instanceof CtModifiable) {
setModifiersPosition((CtModifiable) e, modifiersSourceStart, modifiersSourceEnd);
}
if (modifiersSourceEnd < modifiersSourceStart) {
//there is no modifier
modifiersSourceEnd = modifiersSourceStart - 1;
}
}
return cf.createBodyHolderSourcePosition(cu, sourceStart, sourceEnd, modifiersSourceStart,
modifiersSourceEnd, declarationSourceStart, declarationSourceEnd, bodyStart - 1, bodyEnd,
lineSeparatorPositions);
} else if (node instanceof AbstractMethodDeclaration) {
AbstractMethodDeclaration methodDeclaration = (AbstractMethodDeclaration) node;
int bodyStart = methodDeclaration.bodyStart;
int bodyEnd = methodDeclaration.bodyEnd;
int declarationSourceStart = methodDeclaration.declarationSourceStart;
int declarationSourceEnd = methodDeclaration.declarationSourceEnd;
int modifiersSourceStart = methodDeclaration.modifiersSourceStart;
if (modifiersSourceStart <= 0) {
modifiersSourceStart = declarationSourceStart;
}
if (node instanceof AnnotationMethodDeclaration && bodyStart == bodyEnd) {
//The ";" at the end of annotation method declaration is not part of body
//let it behave same like in abstract MethodDeclaration
bodyEnd--;
}
Javadoc javadoc = methodDeclaration.javadoc;
if (javadoc != null && javadoc.sourceEnd() > declarationSourceStart) {
modifiersSourceStart = javadoc.sourceEnd() + 1;
}
int modifiersSourceEnd = sourceStart - 1;
if (e instanceof CtModifiable) {
setModifiersPosition((CtModifiable) e, modifiersSourceStart, declarationSourceEnd);
}
if (methodDeclaration instanceof MethodDeclaration
&& ((MethodDeclaration) methodDeclaration).returnType != null) {
modifiersSourceEnd = ((MethodDeclaration) methodDeclaration).returnType.sourceStart() - 2;
}
TypeParameter[] typeParameters = methodDeclaration.typeParameters();
if (typeParameters != null && typeParameters.length > 0) {
modifiersSourceEnd = typeParameters[0].declarationSourceStart - 3;
}
if (getModifiers(methodDeclaration.modifiers, false, true).isEmpty()) {
modifiersSourceEnd = modifiersSourceStart - 1;
}
sourceEnd = sourceStart + methodDeclaration.selector.length - 1;
if (bodyStart == 0) {
return cf.createPartialSourcePosition(cu);
}
if (e instanceof CtStatementList) {
return cf.createSourcePosition(cu, bodyStart - 1, bodyEnd + 1, lineSeparatorPositions);
} else {
//include brackets if they are there
if (contents[bodyStart - 1] == '{') {
bodyStart--;
if (contents[bodyEnd + 1] == '}') {
bodyEnd++;
} else {
if (bodyStart < bodyEnd) {
return handlePositionProblem("Missing body end in\n"
+ new String(contents, sourceStart, sourceEnd - sourceStart));
}
}
}
return cf.createBodyHolderSourcePosition(cu, sourceStart, sourceEnd, modifiersSourceStart,
modifiersSourceEnd, declarationSourceStart, declarationSourceEnd, bodyStart, bodyEnd,
lineSeparatorPositions);
}
} else if (e instanceof CtCatchVariable) {
ASTPair pair = this.jdtTreeBuilder.getContextBuilder().getParentContextOfType(CtCatch.class);
if (pair == null) {
return handlePositionProblem("There is no CtCatch parent for CtCatchVariable");
}
//build position with appropriate context
return buildPositionCtElement(e, (Argument) pair.node);
} else if (node instanceof TypeReference) {
sourceEnd = getSourceEndOfTypeReference(contents, (TypeReference) node, sourceEnd);
} else if (node instanceof AllocationExpression) {
AllocationExpression allocationExpression = (AllocationExpression) node;
if (allocationExpression.enumConstant != null) {
FieldDeclaration fieldDeclaration = allocationExpression.enumConstant;
//1) skip comments
sourceStart = findNextNonWhitespace(contents, sourceEnd, sourceStart);
//2) move to beginning of enum construction
sourceStart += fieldDeclaration.name.length;
}
} else if (node instanceof CaseStatement) {
sourceEnd = findNextNonWhitespace(contents, contents.length - 1, sourceEnd + 1);
if (sourceEnd < 0) {
return handlePositionProblem("Unexpected end of file in CtCase on: " + sourceStart);
}
if (contents[sourceEnd] != ':') {
return handlePositionProblem("Unexpected character " + contents[sourceEnd]
+ " instead of \':\' in CtCase on: " + sourceEnd);
}
}
if (e instanceof CtModifiable) {
setModifiersPosition((CtModifiable) e, sourceStart, sourceEnd);
}
if (sourceStart == 0 && sourceEnd == 0) {
return SourcePosition.NOPOSITION;
}
return cf.createSourcePosition(cu, sourceStart, sourceEnd, lineSeparatorPositions);
}