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); }