/** * Copyright (C) 2006-2017 INRIA and contributors * Spoon - http://spoon.gforge.inria.fr/ * * This software is governed by the CeCILL-C License under French law and * abiding by the rules of distribution of free software. You can use, modify * and/or redistribute the software under the terms of the CeCILL-C license as * circulated by CEA, CNRS and INRIA at http://www.cecill.info. * * This program is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the CeCILL-C License for more details. * * The fact that you are presently reading this means that you have had * knowledge of the CeCILL-C license and that you accept its terms. */ package spoon.support.compiler.jdt; import org.eclipse.jdt.internal.compiler.ast.ASTNode; import org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration; import org.eclipse.jdt.internal.compiler.ast.AbstractVariableDeclaration; import org.eclipse.jdt.internal.compiler.ast.Annotation; import org.eclipse.jdt.internal.compiler.ast.Expression; import org.eclipse.jdt.internal.compiler.ast.Javadoc; import org.eclipse.jdt.internal.compiler.ast.MethodDeclaration; import org.eclipse.jdt.internal.compiler.ast.TypeDeclaration; import org.eclipse.jdt.internal.compiler.ast.TypeParameter; import spoon.reflect.code.CtStatementList; import spoon.reflect.cu.CompilationUnit; import spoon.reflect.cu.SourcePosition; import spoon.reflect.declaration.CtElement; import spoon.reflect.factory.CoreFactory; import static spoon.support.compiler.jdt.JDTTreeBuilderQuery.getModifiers; /** * Created by bdanglot on 07/07/16. */ public class PositionBuilder { private final JDTTreeBuilder jdtTreeBuilder; public PositionBuilder(JDTTreeBuilder jdtTreeBuilder) { this.jdtTreeBuilder = jdtTreeBuilder; } SourcePosition buildPosition(int sourceStart, int sourceEnd) { CompilationUnit cu = this.jdtTreeBuilder.getContextBuilder().compilationUnitSpoon; final int[] lineSeparatorPositions = this.jdtTreeBuilder.getContextBuilder().compilationunitdeclaration.compilationResult.lineSeparatorPositions; return this.jdtTreeBuilder.getFactory().Core().createSourcePosition(cu, sourceStart, sourceEnd, lineSeparatorPositions); } SourcePosition buildPositionCtElement(CtElement e, ASTNode node) { CoreFactory cf = this.jdtTreeBuilder.getFactory().Core(); CompilationUnit cu = this.jdtTreeBuilder.getFactory().CompilationUnit().create(new String(this.jdtTreeBuilder.getContextBuilder().compilationunitdeclaration.getFileName())); int[] lineSeparatorPositions = this.jdtTreeBuilder.getContextBuilder().compilationunitdeclaration.compilationResult.lineSeparatorPositions; int sourceStart = node.sourceStart; int sourceEnd = node.sourceEnd; if ((node instanceof Expression)) { if (((Expression) node).statementEnd > 0) { sourceEnd = ((Expression) node).statementEnd; } } if (node instanceof AbstractVariableDeclaration) { AbstractVariableDeclaration variableDeclaration = (AbstractVariableDeclaration) node; int modifiersSourceStart = variableDeclaration.modifiersSourceStart; int declarationSourceStart = variableDeclaration.declarationSourceStart; int declarationSourceEnd = variableDeclaration.declarationSourceEnd; int declarationEnd = variableDeclaration.declarationEnd; Annotation[] annotations = variableDeclaration.annotations; if (annotations != null && annotations.length > 0) { if (annotations[0].sourceStart() == sourceStart) { modifiersSourceStart = annotations[annotations.length - 1].sourceEnd() + 2; } } if (modifiersSourceStart == 0) { modifiersSourceStart = declarationSourceStart; } int modifiersSourceEnd; if (variableDeclaration.type != null) { modifiersSourceEnd = variableDeclaration.type.sourceStart() - 2; } else { // variable that has no type such as TypeParameter modifiersSourceEnd = declarationSourceStart - 1; } // when no modifier if (modifiersSourceStart > modifiersSourceEnd) { modifiersSourceEnd = modifiersSourceStart - 1; } return cf.createDeclarationSourcePosition(cu, sourceStart, sourceEnd, modifiersSourceStart, modifiersSourceEnd, declarationSourceStart, declarationSourceEnd, 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; Annotation[] annotations = typeDeclaration.annotations; if (annotations != null && annotations.length > 0) { if (annotations[0].sourceStart() == declarationSourceStart) { modifiersSourceStart = annotations[annotations.length - 1].sourceEnd() + 2; } } if (modifiersSourceStart == 0) { modifiersSourceStart = declarationSourceStart; } // the position the name minus the size of "class" minus at least 2 spaces int modifiersSourceEnd = sourceStart - 8; 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; } Javadoc javadoc = methodDeclaration.javadoc; if (javadoc != null && javadoc.sourceEnd() > declarationSourceStart) { modifiersSourceStart = javadoc.sourceEnd() + 1; } Annotation[] annotations = methodDeclaration.annotations; if (annotations != null && annotations.length > 0) { if (annotations[0].sourceStart() == declarationSourceStart) { modifiersSourceStart = annotations[annotations.length - 1].sourceEnd() + 2; } } int modifiersSourceEnd = sourceStart - 1; 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).isEmpty()) { modifiersSourceStart = modifiersSourceEnd + 1; } sourceEnd = sourceStart + methodDeclaration.selector.length - 1; if (e instanceof CtStatementList) { return cf.createSourcePosition(cu, bodyStart - 1, bodyEnd + 1, lineSeparatorPositions); } else { if (bodyStart == 0) { return SourcePosition.NOPOSITION; } else { return cf.createBodyHolderSourcePosition(cu, sourceStart, sourceEnd, modifiersSourceStart, modifiersSourceEnd, declarationSourceStart, declarationSourceEnd, bodyStart - 1, bodyEnd + 1, lineSeparatorPositions); } } } if ((node instanceof Expression)) { Expression expression = (Expression) node; int statementEnd = expression.statementEnd; if (statementEnd > 0) { sourceEnd = statementEnd; } } return cf.createSourcePosition(cu, sourceStart, sourceEnd, lineSeparatorPositions); } }