use of spoon.reflect.declaration.CtField in project spoon by INRIA.
the class JDTCommentBuilder method insertCommentInAST.
/**
* Inserts the comment into the AST.
* @param comment the comment to insert
*/
private void insertCommentInAST(final CtComment comment) {
CtElement commentParent = findCommentParent(comment);
if (commentParent == null) {
File file = spoonUnit.getFile();
if (file != null && file.getName().equals(DefaultJavaPrettyPrinter.JAVA_PACKAGE_DECLARATION)) {
spoonUnit.getDeclaredPackage().addComment(comment);
} else if (file != null && file.getName().equals(DefaultJavaPrettyPrinter.JAVA_MODULE_DECLARATION)) {
spoonUnit.getDeclaredModule().addComment(comment);
} else {
comment.setCommentType(CtComment.CommentType.FILE);
addCommentToNear(comment, new ArrayList<CtElement>(spoonUnit.getDeclaredTypes()));
}
return;
}
// visitor that inserts the comment in the element
CtInheritanceScanner insertionVisitor = new CtInheritanceScanner() {
private boolean isScanned = false;
@Override
public void scan(CtElement e) {
if (e == null) {
return;
}
// Do not visit the AST, only the first element
if (!isScanned) {
isScanned = true;
if (e.getPosition().getSourceStart() == comment.getPosition().getSourceStart()) {
e.addComment(comment);
return;
}
super.scan(e);
}
}
@Override
public <R> void visitCtStatementList(CtStatementList e) {
addCommentToNear(comment, new ArrayList<CtElement>(e.getStatements()));
try {
comment.getParent();
} catch (ParentNotInitializedException ex) {
e.addStatement(comment);
}
}
@Override
public <T> void visitCtMethod(CtMethod<T> e) {
e.addComment(comment);
}
@Override
public <T> void visitCtConstructor(CtConstructor<T> e) {
e.addComment(comment);
}
@Override
public <T> void visitCtConditional(CtConditional<T> e) {
List<CtElement> elements = new ArrayList<>();
elements.add(e.getElseExpression());
elements.add(e.getThenExpression());
elements.add(e.getCondition());
addCommentToNear(comment, elements);
}
@Override
public <T> void visitCtBinaryOperator(CtBinaryOperator<T> e) {
List<CtElement> elements = new ArrayList<>();
elements.add(e.getLeftHandOperand());
elements.add(e.getRightHandOperand());
addCommentToNear(comment, elements);
}
@Override
public <T> void visitCtClass(CtClass<T> e) {
if (comment.getPosition().getLine() <= e.getPosition().getLine()) {
e.addComment(comment);
return;
}
final List<CtElement> elements = new ArrayList<>();
for (CtTypeMember typeMember : e.getTypeMembers()) {
if (typeMember instanceof CtField || typeMember instanceof CtMethod || typeMember instanceof CtConstructor) {
elements.add(typeMember);
}
}
addCommentToNear(comment, elements);
try {
comment.getParent();
} catch (ParentNotInitializedException ex) {
e.addComment(comment);
}
}
@Override
public <T> void visitCtInterface(CtInterface<T> e) {
final List<CtElement> elements = new ArrayList<>();
for (CtTypeMember typeMember : e.getTypeMembers()) {
if (typeMember instanceof CtField || typeMember instanceof CtMethod) {
elements.add(typeMember);
}
}
addCommentToNear(comment, elements);
try {
comment.getParent();
} catch (ParentNotInitializedException ex) {
e.addComment(comment);
}
}
@Override
public <T> void visitCtField(CtField<T> e) {
e.addComment(comment);
}
@Override
public <E> void visitCtSwitch(CtSwitch<E> e) {
List<CtCase<? super E>> cases = e.getCases();
CtCase previous = null;
for (int i = 0; i < cases.size(); i++) {
CtCase<? super E> ctCase = cases.get(i);
if (previous == null) {
if (comment.getPosition().getSourceStart() < ctCase.getPosition().getSourceStart() && e.getPosition().getSourceStart() < comment.getPosition().getSourceStart()) {
ctCase.addComment(comment);
return;
}
} else {
if (previous.getPosition().getSourceEnd() < comment.getPosition().getSourceStart() && ctCase.getPosition().getSourceStart() > comment.getPosition().getSourceStart()) {
addCommentToNear(comment, new ArrayList<CtElement>(previous.getStatements()));
try {
comment.getParent();
} catch (ParentNotInitializedException ex) {
previous.addStatement(comment);
}
return;
}
}
previous = ctCase;
}
if (previous.getPosition().getSourceEnd() < comment.getPosition().getSourceStart()) {
addCommentToNear(comment, new ArrayList<CtElement>(previous.getStatements()));
try {
comment.getParent();
} catch (ParentNotInitializedException ex) {
previous.addStatement(comment);
}
return;
}
try {
comment.getParent();
} catch (ParentNotInitializedException ex) {
e.addComment(comment);
}
}
@Override
public void visitCtIf(CtIf e) {
if (!(e.getThenStatement() instanceof CtBlock)) {
if (comment.getPosition().getSourceEnd() <= e.getThenStatement().getPosition().getSourceStart()) {
e.getThenStatement().addComment(comment);
return;
}
}
if (e.getElseStatement() != null) {
SourcePosition thenPosition = e.getThenStatement().getPosition() == null ? ((CtBlock) e.getThenStatement()).getStatement(0).getPosition() : e.getThenStatement().getPosition();
SourcePosition elsePosition = e.getElseStatement().getPosition() == null ? ((CtBlock) e.getElseStatement()).getStatement(0).getPosition() : e.getElseStatement().getPosition();
if (comment.getPosition().getSourceStart() > thenPosition.getSourceEnd() && comment.getPosition().getSourceEnd() < elsePosition.getSourceStart()) {
e.getElseStatement().addComment(comment);
}
}
try {
comment.getParent();
} catch (ParentNotInitializedException ex) {
e.addComment(comment);
}
}
@Override
public void scanCtStatement(CtStatement s) {
if (!(s instanceof CtStatementList || s instanceof CtSwitch)) {
s.addComment(comment);
}
}
@Override
public void visitCtAnonymousExecutable(CtAnonymousExecutable e) {
e.addComment(comment);
}
@Override
public <T> void visitCtNewArray(CtNewArray<T> e) {
addCommentToNear(comment, new ArrayList<CtElement>(e.getElements()));
try {
comment.getParent();
} catch (ParentNotInitializedException ex) {
e.addComment(comment);
}
}
@Override
public <T> void visitCtParameter(CtParameter<T> e) {
e.addComment(comment);
}
@Override
public void visitCtCatch(CtCatch e) {
if (comment.getPosition().getLine() <= e.getPosition().getLine()) {
e.addComment(comment);
return;
}
}
@Override
public void visitCtModule(CtModule module) {
addCommentToNear(comment, new ArrayList<>(module.getModuleDirectives()));
}
};
insertionVisitor.scan(commentParent);
try {
comment.getParent();
} catch (ParentNotInitializedException e) {
LOGGER.error(comment + " is not added into the AST", e);
}
}
use of spoon.reflect.declaration.CtField in project spoon by INRIA.
the class JDTTreeBuilderHelper method createVariableAccessNoClasspath.
/**
* Analyzes if {@code singleNameReference} points to a {@link CtVariable} visible in current
* scope and, if existent, returns its corresponding {@link CtVariableAccess}. Returns
* {@code null} if {@code singleNameReference} could not be resolved as variable access. Since
* we are in noclasspath mode this function may also returns {@code null} if
* {@code singleNameReference} points to a variable declared by an unknown class.
*
* @param singleNameReference
* The potential variable access.
* @return A {@link CtVariableAccess} if {@code singleNameReference} points to a variable
* visible in current scope, {@code null} otherwise.
*/
<T> CtVariableAccess<T> createVariableAccessNoClasspath(SingleNameReference singleNameReference) {
final TypeFactory typeFactory = jdtTreeBuilder.getFactory().Type();
final CoreFactory coreFactory = jdtTreeBuilder.getFactory().Core();
final ExecutableFactory executableFactory = jdtTreeBuilder.getFactory().Executable();
final ContextBuilder contextBuilder = jdtTreeBuilder.getContextBuilder();
final ReferenceBuilder referenceBuilder = jdtTreeBuilder.getReferencesBuilder();
final PositionBuilder positionBuilder = jdtTreeBuilder.getPositionBuilder();
final String name = CharOperation.charToString(singleNameReference.token);
final CtVariable<T> variable = contextBuilder.getVariableDeclaration(name);
if (variable == null) {
return null;
}
final CtVariableReference<T> variableReference;
final CtVariableAccess<T> variableAccess;
if (variable instanceof CtParameter) {
// create variable of concrete type to avoid type casting while calling methods
final CtParameterReference<T> parameterReference = coreFactory.createParameterReference();
if (variable.getParent() instanceof CtLambda) {
// nothing
} else {
// Unfortunately, we can not use `variable.getReference()` here as some parent
// references (in terms of Java objects) have not been set up yet. Thus, we need to
// create the required parameter reference by our own.
// Since the given parameter has not been declared in a lambda expression it must
// have been declared by a method/constructor.
final CtExecutable executable = (CtExecutable) variable.getParent();
// create list of executable's parameter types
final List<CtTypeReference<?>> parameterTypesOfExecutable = new ArrayList<>();
@SuppressWarnings("unchecked") final List<CtParameter<?>> parametersOfExecutable = executable.getParameters();
for (CtParameter<?> parameter : parametersOfExecutable) {
parameterTypesOfExecutable.add(parameter.getType() != null ? parameter.getType().clone() : // it's the best match :(
typeFactory.OBJECT.clone());
}
// find executable's corresponding jdt element
AbstractMethodDeclaration executableJDT = null;
for (final ASTPair astPair : contextBuilder.stack) {
if (astPair.element == executable) {
executableJDT = (AbstractMethodDeclaration) astPair.node;
}
}
assert executableJDT != null;
// create a reference to executable's declaring class
final CtTypeReference declaringReferenceOfExecutable = // available
executableJDT.binding == null ? coreFactory.createTypeReference() : referenceBuilder.getTypeReference(executableJDT.binding.declaringClass);
// If executable is a constructor, `executable.getType()` returns null since the
// parent is not available yet. Fortunately, however, the return type of a
// constructor is its declaring class which, in our case, is already available with
// declaringReferenceOfExecutable.
CtTypeReference executableTypeReference = executable instanceof CtConstructor ? // indirectly sets the parent of `rt` and, thus, may break the AST!
declaringReferenceOfExecutable.clone() : executable.getType().clone();
}
variableReference = parameterReference;
variableAccess = isLhsAssignment(contextBuilder, singleNameReference) ? coreFactory.<T>createVariableWrite() : coreFactory.<T>createVariableRead();
} else if (variable instanceof CtField) {
variableReference = variable.getReference();
variableAccess = isLhsAssignment(contextBuilder, singleNameReference) ? coreFactory.<T>createFieldWrite() : coreFactory.<T>createFieldRead();
} else {
// CtLocalVariable, CtCatchVariable, ...
variableReference = variable.getReference();
variableAccess = isLhsAssignment(contextBuilder, singleNameReference) ? coreFactory.<T>createVariableWrite() : coreFactory.<T>createVariableRead();
}
variableReference.setSimpleName(name);
variableReference.setPosition(positionBuilder.buildPosition(singleNameReference.sourceStart(), singleNameReference.sourceEnd()));
variableAccess.setVariable(variableReference);
return variableAccess;
}
use of spoon.reflect.declaration.CtField in project spoon by INRIA.
the class CloneVisitorGenerator method process.
@Override
public void process() {
final CtClass<Object> target = createCloneVisitor();
final CtClass<Object> targetBuilder = createCloneBuilder();
final Factory factory = target.getFactory();
final CtTypeReference<Object> cloneBuilder = factory.Type().createReference("spoon.support.visitor.clone.CloneBuilder");
final CtTypeAccess<Object> cloneBuilderType = factory.Code().createTypeAccess(cloneBuilder);
final CtVariableAccess<Object> builderFieldAccess = factory.Code().createVariableRead(factory.Field().createReference(target.getReference(), cloneBuilder, "builder"), false);
final CtVariableAccess<Object> tailorerFieldAccess = factory.Code().createVariableRead(factory.Field().createReference(target.getReference(), cloneBuilder, "tailorer"), false);
final CtVariableAccess<Object> cloneHelperFieldAccess = factory.Code().createVariableRead(factory.Field().createReference(target.getReference(), cloneBuilder, "cloneHelper"), false);
final CtFieldReference<Object> other = factory.Field().createReference((CtField) target.getField("other"));
final CtVariableAccess otherRead = factory.Code().createVariableRead(other, true);
new CtScanner() {
private final List<String> internals = Collections.singletonList("CtCircularTypeReference");
@Override
public <T> void visitCtMethod(CtMethod<T> element) {
if (!element.getSimpleName().startsWith("visitCt")) {
return;
}
CtMethod<T> clone = element.clone();
// Variables used by the visit method.
final CtParameter<CtElement> ctParameter = (CtParameter<CtElement>) element.getParameters().get(0);
final CtVariableAccess<CtElement> elementVarRead = factory.Code().createVariableRead(ctParameter.getReference(), false);
final CtInvocation cloneBuilderInvocation = createCloneBuilderBuildInvocation(elementVarRead);
final CtLocalVariable localCloningElement = createLocalCloningElement(ctParameter.getType(), createFactoryInvocation(elementVarRead));
final CtVariableAccess localVarRead = factory.Code().createVariableRead(localCloningElement.getReference(), false);
// Changes body of the cloned method.
for (int i = 1; i < clone.getBody().getStatements().size() - 1; i++) {
List<CtExpression> invArgs = ((CtInvocation) clone.getBody().getStatement(i)).getArguments();
if (invArgs.size() <= 1) {
throw new RuntimeException("You forget the role argument in line " + i + " of method " + element.getSimpleName() + " from " + element.getDeclaringType().getQualifiedName());
}
final CtInvocation targetInvocation = (CtInvocation) invArgs.get(1);
if ("getValue".equals(targetInvocation.getExecutable().getSimpleName()) && "CtLiteral".equals(targetInvocation.getExecutable().getDeclaringType().getSimpleName())) {
clone.getBody().getStatement(i--).delete();
continue;
}
//
clone.getBody().getStatement(i).replace(createSetter((CtInvocation) clone.getBody().getStatement(i), localVarRead));
}
// Delete enter and exit methods.
clone.getBody().getStatement(0).delete();
clone.getBody().getStatement(clone.getBody().getStatements().size() - 1).delete();
// declaration of local variable
clone.getBody().insertBegin(localCloningElement);
// call to copy
clone.getBody().insertEnd(createCloneBuilderCopyInvocation(elementVarRead, localVarRead));
// call to tailor
clone.getBody().insertEnd(createTailorerScanInvocation(elementVarRead, localVarRead));
// final assignment
clone.getBody().insertEnd(factory.Code().createVariableAssignment(other, false, localVarRead));
// Add auto-generated comment.
final CtComment comment = factory.Core().createComment();
comment.setCommentType(CtComment.CommentType.INLINE);
comment.setContent("auto-generated, see " + CloneVisitorGenerator.class.getName());
clone.addComment(comment);
target.addMethod(clone);
}
/**
* Creates <code>anElement.setX(clone(anElement.getX()))</code>.
*
* @param scanInvocation <code>scan(anElement.getX())</code>.
* @param elementVarRead <code>anElement</code>.
*/
private CtInvocation<?> createSetter(CtInvocation scanInvocation, CtVariableAccess<CtElement> elementVarRead) {
final CtInvocation<?> getter = (CtInvocation<?>) scanInvocation.getArguments().get(1);
final String getterName = getter.getExecutable().getSimpleName();
final CtExecutableReference<Object> setterRef = factory.Executable().createReference("void CtElement#set" + getterName.substring(3, getterName.length()) + "()");
final CtExecutableReference<Object> cloneRef = factory.Executable().createReference("CtElement spoon.support.visitor.equals.CloneHelper#clone()");
final CtInvocation<Object> cloneInv = factory.Code().createInvocation(null, cloneRef, getter);
cloneInv.setTarget(cloneHelperFieldAccess);
return factory.Code().createInvocation(elementVarRead, setterRef, cloneInv);
}
/**
* Creates <code>CtElement anElement = CloneBuilder.build(builder, element, element.getFactory().Core().createElement())</code>.
*
* @param typeReference <code>CtElement</code>.
* @param ctInvocation <code>CloneBuilder.build(builder, element, element.getFactory().Core().createElement())</code>.
*/
private <T> CtLocalVariable<T> createLocalCloningElement(CtTypeReference<T> typeReference, CtInvocation<T> ctInvocation) {
return factory.Code().createLocalVariable(typeReference, "a" + typeReference.getSimpleName(), ctInvocation);
}
/**
* Creates <code>CloneBuilder.build(builder, element, element.getFactory().Core().createElement())</code>.
*
* @param elementAccess <code>element</code>.
*/
private CtInvocation<CloneBuilder> createCloneBuilderBuildInvocation(CtVariableAccess<CtElement> elementAccess) {
final CtExecutableReference<CloneBuilder> buildExecRef = factory.Executable().createReference("CloneBuilder CtElement#build()");
return factory.Code().createInvocation(cloneBuilderType, buildExecRef, builderFieldAccess, elementAccess, createFactoryInvocation(elementAccess.clone()));
}
private CtInvocation<CloneBuilder> createCloneBuilderCopyInvocation(CtVariableAccess<CtElement> elementVarRead, CtVariableAccess<CtElement> elementVarRead2) {
final CtExecutableReference<CloneBuilder> buildExecRef = factory.Executable().createReference("CloneBuilder #copy()");
return factory.Code().createInvocation(builderFieldAccess, buildExecRef, elementVarRead, elementVarRead2);
}
private CtInvocation<CloneBuilder> createTailorerScanInvocation(CtVariableAccess elementVarRead, CtVariableAccess localVarRead) {
final CtExecutableReference<CloneBuilder> buildExecRef = factory.Executable().createReference("CloneHelper #tailor()");
return factory.Code().createInvocation(cloneHelperFieldAccess, buildExecRef, elementVarRead, localVarRead);
}
/**
* Creates <code>element.getFactory().Core().createElement()</code>.
*
* @param elementAccess <code>element</code>.
*/
private CtInvocation createFactoryInvocation(CtVariableAccess<CtElement> elementAccess) {
final String typeName = elementAccess.getType().getSimpleName();
// #getFactory()
final CtInvocation<Object> getFactory = factory.Code().createInvocation(null, factory.Executable().createReference("Factory CtElement#getFactory()"));
getFactory.setTarget(elementAccess);
// Factory#Core() or Factory#Internal()
final String factoryName = internals.contains(typeName) ? "Internal" : "Core";
final CtInvocation<Object> coreFactory = factory.Code().createInvocation(getFactory, factory.Executable().createReference("CoreFactory Factory#" + factoryName + "()"));
// CoreFactory#createElement()
return factory.Code().createInvocation(coreFactory, factory.Executable().createReference("CoreFactory CtElement#create" + typeName.substring(2, typeName.length()) + "()"));
}
}.scan(getFactory().Class().get(CtScanner.class));
new CtScanner() {
private final List<String> excludesAST = //
Arrays.asList(//
"spoon.support.reflect.declaration.CtTypeInformationImpl", //
"spoon.support.reflect.code.CtAbstractInvocationImpl", //
"spoon.support.reflect.declaration.CtTypedElementImpl", //
"spoon.support.reflect.declaration.CtVariableImpl", //
"spoon.support.reflect.reference.CtActualTypeContainerImpl", //
"spoon.support.reflect.code.CtCFlowBreakImpl", //
"spoon.support.reflect.code.CtLabelledFlowBreakImpl", //
"spoon.support.reflect.declaration.CtCodeSnippetImpl", //
"spoon.support.reflect.declaration.CtFormalTypeDeclarerImpl", //
"spoon.support.reflect.declaration.CtGenericElementImpl", //
"spoon.support.reflect.reference.CtGenericElementReferenceImpl", //
"spoon.support.reflect.declaration.CtModifiableImpl", //
"spoon.support.reflect.declaration.CtMultiTypedElementImpl", "spoon.support.reflect.declaration.CtTypeMemberImpl", "spoon.support.reflect.code.CtRHSReceiverImpl", "spoon.support.reflect.declaration.CtShadowableImpl", "spoon.support.reflect.code.CtBodyHolderImpl", "spoon.support.reflect.declaration.CtModuleDirectiveImpl");
private final List<String> excludesFields = Arrays.asList("factory", "elementValues", "target", "metadata");
private final CtTypeReference<List> LIST_REFERENCE = factory.Type().createReference(List.class);
private final CtTypeReference<Collection> COLLECTION_REFERENCE = factory.Type().createReference(Collection.class);
private final CtTypeReference<Set> SET_REFERENCE = factory.Type().createReference(Set.class);
private final CtTypeReference<CtElement> CTELEMENT_REFERENCE = factory.Type().createReference(CtElement.class);
private final CtClass<?> GETTER_TEMPLATE_MATCHER_CLASS = factory.Class().get(GENERATING_CLONE_PACKAGE + ".GetterTemplateMatcher");
private final CtClass<?> SETTER_TEMPLATE_MATCHER_CLASS = factory.Class().get(GENERATING_CLONE_PACKAGE + ".SetterTemplateMatcher");
@Override
public <T> void visitCtMethod(CtMethod<T> element) {
if (!element.getSimpleName().startsWith("visitCt") && !element.getSimpleName().startsWith("scanCt")) {
return;
}
if ("scanCtVisitable".equals(element.getSimpleName())) {
return;
}
final String qualifiedNameOfImplClass = "spoon.support" + element.getParameters().get(0).getType().getQualifiedName().substring(5) + "Impl";
if (excludesAST.contains(qualifiedNameOfImplClass)) {
return;
}
final CtType<?> declaration = factory.Class().get(qualifiedNameOfImplClass);
if (declaration == null) {
throw new SpoonException(qualifiedNameOfImplClass + " doesn't have declaration in the source path for " + element.getSignature());
}
CtMethod<T> clone = element.clone();
clone.getBody().getStatements().clear();
for (CtField<?> ctField : declaration.getFields()) {
if (excludesFields.contains(ctField.getSimpleName())) {
continue;
}
if (isConstantOrStatic(ctField)) {
continue;
}
if (isSubTypeOfCtElement(ctField.getType())) {
continue;
}
final CtMethod<?> setterOfField = getSetterOf(ctField);
final CtInvocation<?> setterInvocation = createSetterInvocation(//
element.getParameters().get(0).getType(), //
setterOfField, createGetterInvocation(element.getParameters().get(0), getGetterOf(ctField)));
final List<CtMethod<?>> methodsToAvoid = getCtMethodThrowUnsupportedOperation(setterOfField);
if (methodsToAvoid.size() > 0) {
clone.getBody().addStatement(createProtectionToException(setterInvocation, methodsToAvoid));
} else {
clone.getBody().addStatement(setterInvocation);
}
}
if (clone.getBody().getStatements().size() > 0) {
clone.getBody().insertEnd(createSuperInvocation(element));
// Add auto-generated comment.
final CtComment comment = factory.Core().createComment();
comment.setCommentType(CtComment.CommentType.INLINE);
comment.setContent("auto-generated, see " + CloneVisitorGenerator.class.getName());
clone.addComment(comment);
targetBuilder.addMethod(clone);
}
}
/**
* Creates <code>if (!(other instanceof CtX && other instanceof CtY && ..)) {}</code>.
*/
private CtIf createProtectionToException(CtInvocation<?> setterInvocation, List<CtMethod<?>> methodsAvoid) {
final CtIf anIf = factory.Core().createIf();
anIf.setCondition(factory.Core().createUnaryOperator().setOperand(createBinaryConditions(methodsAvoid)).setKind(UnaryOperatorKind.NOT));
anIf.setThenStatement(factory.Code().createCtBlock(setterInvocation));
return anIf;
}
/**
* Creates <code>condition && condition && ...</code>.
*
* @param methodsAvoid Methods to avoid.
*/
private CtExpression<Object> createBinaryConditions(List<CtMethod<?>> methodsAvoid) {
CtExpression<Object> left = null;
CtExpression<Object> right;
for (int i = 0; i < methodsAvoid.size(); i++) {
final CtInterface<?> ctInterface = getInterfaceOf(methodsAvoid.get(i).getDeclaringType());
if (i == 0) {
left = //
factory.Code().createBinaryOperator(//
otherRead, //
factory.Code().createTypeAccess(ctInterface.getReference()), BinaryOperatorKind.INSTANCEOF);
} else {
right = //
factory.Code().createBinaryOperator(//
otherRead, //
factory.Code().createTypeAccess(ctInterface.getReference()), BinaryOperatorKind.INSTANCEOF);
left = factory.Code().createBinaryOperator(left, right, BinaryOperatorKind.OR);
}
}
return left;
}
/**
* Query to get all methods which throw an UnsupportedOperationException. We must avoid to call these methods during a clone process.
*/
private List<CtMethod<?>> getCtMethodThrowUnsupportedOperation(CtMethod<?> method) {
final List<CtMethod<?>> avoid = new ArrayList<>();
final CtInterface<?> ctInterface = getInterfaceOf(method.getDeclaringType());
if (ctInterface == null) {
return avoid;
}
final CtMethod<?> declarationMethod = getMethodByCtMethod(ctInterface, method);
for (CtMethod<?> ctMethod : Query.getElements(factory, new OverridingMethodFilter(declarationMethod))) {
if (!avoidThrowUnsupportedOperationException(ctMethod)) {
avoid.add(ctMethod);
}
}
return avoid;
}
/**
* Check if the candidate method throw an UnsupportedOperationException.
*/
private boolean avoidThrowUnsupportedOperationException(CtMethod<?> candidate) {
if (candidate.getBody().getStatements().size() != 1) {
return true;
}
if (!(candidate.getBody().getStatement(0) instanceof CtThrow)) {
return true;
}
CtThrow ctThrow = candidate.getBody().getStatement(0);
if (!(ctThrow.getThrownExpression() instanceof CtConstructorCall)) {
return true;
}
final CtConstructorCall<? extends Throwable> thrownExpression = (CtConstructorCall<? extends Throwable>) ctThrow.getThrownExpression();
if (!thrownExpression.getType().equals(factory.Type().createReference(UnsupportedOperationException.class))) {
return true;
}
return false;
}
/**
* Query to get a method from a CtMethod.
*/
private CtMethod<?> getMethodByCtMethod(CtType<?> ctType, CtMethod<?> method) {
for (CtMethod<?> ctMethod : ctType.getAllMethods()) {
if (!method.getSimpleName().equals(ctMethod.getSimpleName())) {
continue;
}
boolean cont = method.getParameters().size() == ctMethod.getParameters().size();
for (int i = 0; cont && i < method.getParameters().size(); i++) {
if (!method.getParameters().get(i).getType().equals(ctMethod.getParameters().get(i).getType())) {
cont = false;
}
}
if (cont) {
return ctMethod;
}
}
throw new AssertionError("Can't find method " + method.getSignature() + " in the given interface " + ctType.getQualifiedName());
}
/**
* Query to get the interface of the class.
*/
private CtInterface<?> getInterfaceOf(CtType<?> declaringType) {
final CtTypeReference<?>[] interfaces = declaringType.getSuperInterfaces().toArray(new CtTypeReference[declaringType.getSuperInterfaces().size()]);
for (CtTypeReference<?> anInterface : interfaces) {
if (anInterface.getSimpleName().equals(declaringType.getSimpleName().substring(0, declaringType.getSimpleName().length() - 4))) {
return (CtInterface<?>) anInterface.getDeclaration();
}
}
throw new AssertionError("You should have the interface for the implementation " + declaringType.getQualifiedName());
}
/**
* Creates <code>super.visitMethod(element)</code>.
*
* @param element <code>visitMethod</code>.
*/
private <T> CtInvocation<T> createSuperInvocation(CtMethod<T> element) {
return factory.Code().createInvocation(factory.Core().createSuperAccess(), element.getReference(), factory.Code().createVariableRead(element.getParameters().get(0).getReference(), false));
}
/**
* Creates <code>((CtElement) other).setX(element.getX())</code>
* or <code>((CtElement) other).setX(new Collection(element.getX()))</code>
* if the field is a collection.
*
* @param type <code>CtElement</code>
* @param setter <code>setX</code>.
* @param getter <code>getX</code>.
*/
private CtInvocation<?> createSetterInvocation(CtTypeReference<?> type, CtMethod<?> setter, CtInvocation<?> getter) {
return factory.Code().createInvocation(otherRead.clone().addTypeCast(type), setter.getReference(), getter);
}
/**
* Creates <code>element.getX()</code>.
*
* @param element <code>element</code>.
* @param getter <code>getX</code>.
*/
private CtInvocation<?> createGetterInvocation(CtParameter<?> element, CtMethod<?> getter) {
return factory.Code().createInvocation(factory.Code().createVariableRead(element.getReference(), false), getter.getReference());
}
/**
* Query to get the setter of given field.
*/
private <T> CtMethod<?> getSetterOf(final CtField<T> ctField) {
if (ctField.getType().equals(getFactory().createCtTypeReference(CtModifierHandler.class))) {
return ctField.getDeclaringType().getMethodsByName("setModifiers").get(0);
}
// Search by name convention.
for (CtMethod<?> ctMethod : ctField.getDeclaringType().getMethods()) {
if (ctMethod.getSimpleName().startsWith("set") && ctMethod.getSimpleName().toLowerCase().contains(ctField.getSimpleName().toLowerCase())) {
if (ctMethod.getParameters().size() != 1) {
continue;
}
if (!ctMethod.getParameters().get(0).getType().equals(ctField.getType())) {
continue;
}
return ctMethod;
}
}
SETTER_TEMPLATE_MATCHER_CLASS.getMethod("setElement", factory.Type().BOOLEAN_PRIMITIVE).getBody();
final List<CtMethod> matchers = ctField.getDeclaringType().getElements(new TypeFilter<CtMethod>(CtMethod.class) {
@Override
public boolean matches(CtMethod element) {
final CtBlock body = element.getBody();
if (body.getStatements().size() != 3) {
return false;
}
if (body.getStatement(1) instanceof CtAssignment) {
final CtExpression assigned = ((CtAssignment) body.getStatement(1)).getAssigned();
if (!(assigned instanceof CtFieldAccess)) {
return false;
}
if (!((CtFieldAccess) assigned).getVariable().getSimpleName().equals(ctField.getSimpleName())) {
return false;
}
} else {
return false;
}
return true;
}
});
if (matchers.size() != 1) {
throw new SpoonException("Get more than one setter. Please make an more ingenious method to get setter method. " + matchers.size() + " " + ctField);
}
return matchers.get(0);
}
/**
* Query to get the getter of the given field.
*/
private <T> CtMethod<?> getGetterOf(CtField<T> ctField) {
if (ctField.getType().equals(getFactory().createCtTypeReference(CtModifierHandler.class))) {
return ctField.getDeclaringType().getMethod("getModifiers");
}
// Search by name convention.
for (CtMethod<?> ctMethod : ctField.getDeclaringType().getMethods()) {
if (//
(ctMethod.getSimpleName().startsWith("get") || ctMethod.getSimpleName().startsWith("is")) && ctMethod.getSimpleName().toLowerCase().contains(ctField.getSimpleName().toLowerCase())) {
if (!ctMethod.getType().equals(ctField.getType())) {
continue;
}
if (ctMethod.getParameters().size() != 0) {
continue;
}
return ctMethod;
}
}
// Search with template.
final CtBlock<?> templateRoot = GETTER_TEMPLATE_MATCHER_CLASS.getMethod("getElement").getBody();
((CtReturn) templateRoot.getStatement(0)).setReturnedExpression(factory.Code().createVariableRead(ctField.getReference(), true));
List<CtMethod> matchers = ctField.getDeclaringType().getElements(new TypeFilter<CtMethod>(CtMethod.class) {
@Override
public boolean matches(CtMethod element) {
return element.getBody().toString().equals(templateRoot.toString());
}
});
if (matchers.isEmpty()) {
throw new SpoonException("No getter found for field " + ctField);
}
if (matchers.size() > 1) {
throw new SpoonException("Get more than one getter (" + StringUtils.join(matchers, ";") + "). Please make an more ingenious method to get getter method.");
}
return matchers.get(0);
}
/**
* Check if the type is a subtype of CtElement.
*/
private boolean isSubTypeOfCtElement(CtTypeReference<?> type) {
if (!type.isPrimitive() && !type.equals(factory.Type().STRING)) {
if (type.isSubtypeOf(factory.Type().createReference(CtElement.class))) {
return true;
}
if (type.getQualifiedName().equals(LIST_REFERENCE.getQualifiedName()) || type.getQualifiedName().equals(COLLECTION_REFERENCE.getQualifiedName()) || type.getQualifiedName().equals(SET_REFERENCE.getQualifiedName())) {
if (type.getActualTypeArguments().get(0).isSubtypeOf(CTELEMENT_REFERENCE)) {
return true;
}
}
}
return false;
}
private boolean isConstantOrStatic(CtField<?> ctField) {
return ctField.getModifiers().contains(ModifierKind.FINAL) || ctField.getModifiers().contains(ModifierKind.STATIC);
}
}.scan(getFactory().Class().get(CtInheritanceScanner.class));
}
use of spoon.reflect.declaration.CtField in project spoon by INRIA.
the class JavaReflectionTreeBuilder method visitAnnotationClass.
@Override
public <T extends Annotation> void visitAnnotationClass(Class<T> clazz) {
final CtAnnotationType<?> ctAnnotationType = factory.Core().createAnnotationType();
ctAnnotationType.setSimpleName(clazz.getSimpleName());
setModifier(ctAnnotationType, clazz.getModifiers());
enter(new TypeRuntimeBuilderContext(ctAnnotationType) {
@Override
public void addMethod(CtMethod ctMethod) {
final CtField<Object> field = factory.Core().createField();
field.setSimpleName(ctMethod.getSimpleName());
field.setModifiers(ctMethod.getModifiers());
field.setType(ctMethod.getType());
ctAnnotationType.addField(field);
}
});
super.visitAnnotationClass(clazz);
exit();
contexts.peek().addType(ctAnnotationType);
}
use of spoon.reflect.declaration.CtField in project spoon by INRIA.
the class CtTypeImpl method removeTypeMember.
@Override
public boolean removeTypeMember(CtTypeMember member) {
CtRole role;
if (member instanceof CtMethod) {
role = METHOD;
} else if (member instanceof CtConstructor) {
role = CONSTRUCTOR;
} else if (member instanceof CtField) {
role = FIELD;
} else if (member instanceof CtAnonymousExecutable) {
role = ANNONYMOUS_EXECUTABLE;
} else {
role = NESTED_TYPE;
}
if (typeMembers.size() == 1) {
if (typeMembers.contains(member)) {
getFactory().getEnvironment().getModelChangeListener().onListDelete(this, role, this.typeMembers, this.typeMembers.indexOf(member), member);
typeMembers = emptyList();
return true;
} else {
return false;
}
}
if (typeMembers.contains(member)) {
getFactory().getEnvironment().getModelChangeListener().onListDelete(this, role, this.typeMembers, this.typeMembers.indexOf(member), member);
return typeMembers.remove(member);
}
return false;
}
Aggregations