use of spoon.reflect.declaration.CtField in project spoon by INRIA.
the class PotentialVariableDeclarationFunction method apply.
@Override
public void apply(CtElement input, CtConsumer<Object> outputConsumer) {
isTypeOnTheWay = false;
isInStaticScope = false;
// Search previous siblings for element which may represents the declaration of this local variable
CtQuery siblingsQuery = input.getFactory().createQuery().map(new SiblingsFunction().mode(SiblingsFunction.Mode.PREVIOUS)).select(new TypeFilter<>(CtVariable.class));
if (variableName != null) {
// variable name is defined so we have to search only for variables with that name
siblingsQuery = siblingsQuery.select(new NamedElementFilter<>(CtNamedElement.class, variableName));
}
CtElement scopeElement = input;
// Search input and then all parents until first CtPackage for element which may represents the declaration of this local variable
while (scopeElement != null && !(scopeElement instanceof CtPackage) && scopeElement.isParentInitialized()) {
CtElement parent = scopeElement.getParent();
if (parent instanceof CtType<?>) {
isTypeOnTheWay = true;
// visit each CtField of `parent` CtType
CtQuery q = parent.map(new AllTypeMembersFunction(CtField.class));
q.forEach((CtField<?> field) -> {
if (isInStaticScope && field.hasModifier(ModifierKind.STATIC) == false) {
/*
* the variable reference is used in static scope,
* but the field is not static - ignore it
*/
return;
}
// else send field as potential variable declaration
if (sendToOutput(field, outputConsumer)) {
// and terminate the internal query q if outer query is already terminated
q.terminate();
}
});
if (query.isTerminated()) {
return;
}
} else if (parent instanceof CtBodyHolder || parent instanceof CtStatementList) {
// visit all previous CtVariable siblings of scopeElement element in parent BodyHolder or Statement list
siblingsQuery.setInput(scopeElement).forEach(outputConsumer);
if (query.isTerminated()) {
return;
}
// visit parameters of CtCatch and CtExecutable (method, lambda)
if (parent instanceof CtCatch) {
CtCatch ctCatch = (CtCatch) parent;
if (sendToOutput(ctCatch.getParameter(), outputConsumer)) {
return;
}
} else if (parent instanceof CtExecutable) {
CtExecutable<?> exec = (CtExecutable<?>) parent;
for (CtParameter<?> param : exec.getParameters()) {
if (sendToOutput(param, outputConsumer)) {
return;
}
}
}
}
if (parent instanceof CtModifiable) {
isInStaticScope = isInStaticScope || ((CtModifiable) parent).hasModifier(ModifierKind.STATIC);
}
scopeElement = parent;
}
}
use of spoon.reflect.declaration.CtField in project spoon by INRIA.
the class CtTypeImpl method addTypeMemberAt.
@Override
public <C extends CtType<T>> C addTypeMemberAt(int position, CtTypeMember member) {
if (member == null) {
return (C) this;
}
if (this.typeMembers == CtElementImpl.<CtTypeMember>emptyList()) {
this.typeMembers = new ArrayList<>();
}
if (!this.typeMembers.stream().anyMatch(m -> m == member)) {
member.setParent(this);
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;
}
getFactory().getEnvironment().getModelChangeListener().onListAdd(this, role, this.typeMembers, position, member);
if (position < typeMembers.size()) {
this.typeMembers.add(position, member);
} else {
this.typeMembers.add(member);
}
}
return (C) this;
}
use of spoon.reflect.declaration.CtField in project spoon by INRIA.
the class AnnotationTest method testAnnotationTypeAndFieldOnField.
@Test
public void testAnnotationTypeAndFieldOnField() throws IOException {
// contract: annotation on field with an annotation type which supports type and field, should be attached both on type and field
// see: https://docs.oracle.com/javase/specs/jls/se9/html/jls-9.html#jls-9.7.3
// in this case, we want to print it only once before the type
final Launcher launcher = new Launcher();
launcher.addInputResource("./src/test/java/spoon/test/annotation/testclasses/typeandfield");
launcher.getEnvironment().setNoClasspath(true);
launcher.setSourceOutputDirectory("./target/spooned-typeandfield");
launcher.run();
CtType type = launcher.getFactory().Type().get(SimpleClass.class);
CtField field = type.getField("mandatoryField");
assertEquals(1, field.getAnnotations().size());
CtAnnotation annotation = field.getAnnotations().get(0);
assertEquals("spoon.test.annotation.testclasses.typeandfield.AnnotTypeAndField", annotation.getAnnotationType().getQualifiedName());
CtTypeReference fieldType = field.getType();
assertEquals(1, fieldType.getAnnotations().size());
CtAnnotation anotherAnnotation = fieldType.getAnnotations().get(0);
assertEquals(annotation, anotherAnnotation);
assertEquals("java.lang.String", field.getType().getQualifiedName());
assertEquals(1, field.getType().getAnnotations().size());
List<String> lines = Files.readAllLines(new File("./target/spooned-typeandfield/spoon/test/annotation/testclasses/typeandfield/SimpleClass.java").toPath());
String fileContent = StringUtils.join(lines, "\n");
assertTrue("Content :" + fileContent, fileContent.contains("@spoon.test.annotation.testclasses.typeandfield.AnnotTypeAndField"));
assertTrue("Content :" + fileContent, fileContent.contains("public java.lang.String mandatoryField;"));
}
use of spoon.reflect.declaration.CtField in project spoon by INRIA.
the class SpoonArchitectureEnforcerTest method statelessFactory.
@Test
public void statelessFactory() throws Exception {
// the factories must be stateless
SpoonAPI spoon = new Launcher();
spoon.addInputResource("src/main/java/spoon/reflect/factory");
spoon.buildModel();
for (CtType t : spoon.getFactory().Package().getRootPackage().getElements(new AbstractFilter<CtType>() {
@Override
public boolean matches(CtType element) {
return super.matches(element) && element.getSimpleName().contains("Factory");
}
})) {
for (Object o : t.getFields()) {
CtField f = (CtField) o;
if (f.getSimpleName().equals("factory")) {
continue;
}
if (f.hasModifier(ModifierKind.FINAL) || f.hasModifier(ModifierKind.TRANSIENT)) {
continue;
}
fail("architectural constraint: a factory must be stateless");
}
}
}
use of spoon.reflect.declaration.CtField in project spoon by INRIA.
the class ReplaceScanner method createInvocation.
private <T> CtInvocation<?> createInvocation(Factory factory, CtMethod<T> candidate, List<CtExpression<?>> invArgs, CtInvocation getter, Class getterTypeClass) {
CtInvocation<?> invocation;
Type type;
if (getterTypeClass.equals(Collection.class) || getterTypeClass.equals(List.class)) {
invocation = factory.Code().createInvocation(null, this.list, invArgs);
type = Type.LIST;
} else if (getterTypeClass.equals(Map.class)) {
invocation = factory.Code().createInvocation(null, this.map, invArgs);
type = Type.MAP;
} else if (getterTypeClass.equals(Set.class)) {
invocation = factory.Code().createInvocation(null, this.set, invArgs);
type = Type.SET;
} else {
invocation = factory.Code().createInvocation(null, this.element, invArgs);
type = Type.ELEMENT;
}
// Listener
final String name = getter.getExecutable().getSimpleName().substring(3);
final String listenerName = getter.getExecutable().getDeclaringType().getSimpleName() + name + "ReplaceListener";
CtClass listener;
if (listeners.containsKey(listenerName)) {
listener = listeners.get(listenerName);
} else {
final CtTypeReference getterType = getGetterType(factory, getter);
listener = createListenerClass(factory, listenerName, getterType, type);
final CtMethod setter = getSetter(name, getter.getTarget().getType().getDeclaration());
final CtField field = updateField(listener, setter.getDeclaringType().getReference());
updateConstructor(listener, setter.getDeclaringType().getReference());
updateSetter(factory, (CtMethod<?>) listener.getMethodsByName("set").get(0), getterType, field, setter);
// Add auto-generated comment.
final CtComment comment = factory.Core().createComment();
comment.setCommentType(CtComment.CommentType.INLINE);
comment.setContent("auto-generated, see " + ReplacementVisitorGenerator.class.getName());
listener.addComment(comment);
listeners.put(listenerName, listener);
}
invocation.addArgument(getConstructorCall(listener, factory.Code().createVariableRead(candidate.getParameters().get(0).getReference(), false)));
return invocation;
}
Aggregations