use of spoon.reflect.visitor.CtScanner in project spoon by INRIA.
the class TypeFactory method get.
/**
* Gets a type from its runtime Java class. If the class isn't in the spoon path,
* the class will be build from the Java reflection and will be marked as
* shadow (see {@link spoon.reflect.declaration.CtShadowable}).
*
* @param <T>
* actual type of the class
* @param cl
* the java class: note that this class should be Class<T> but it
* then poses problem when T is a generic type itself
*/
@SuppressWarnings("unchecked")
public <T> CtType<T> get(Class<?> cl) {
final CtType<T> aType = get(cl.getName());
if (aType == null) {
final CtType<T> shadowClass = (CtType<T>) this.shadowCache.get(cl);
if (shadowClass == null) {
CtType<T> newShadowClass;
try {
newShadowClass = new JavaReflectionTreeBuilder(createFactory()).scan((Class<T>) cl);
} catch (Throwable e) {
throw new SpoonClassNotFoundException("cannot create shadow class: " + cl.getName(), e);
}
newShadowClass.setFactory(factory);
newShadowClass.accept(new CtScanner() {
@Override
public void scan(CtElement element) {
if (element != null) {
element.setFactory(factory);
}
}
});
this.shadowCache.put(cl, newShadowClass);
return newShadowClass;
} else {
return shadowClass;
}
}
return aType;
}
use of spoon.reflect.visitor.CtScanner in project spoon by INRIA.
the class Refactoring method copyType.
/**
* See doc in {@link CtType#copyType()}
*/
public static CtType<?> copyType(final CtType<?> type) {
CtType<?> clone = type.clone();
String tentativeTypeName = type.getSimpleName() + "Copy";
while (type.getFactory().Type().get(type.getPackage().getQualifiedName() + "." + tentativeTypeName) != null) {
tentativeTypeName += "X";
}
final String cloneTypeName = tentativeTypeName;
clone.setSimpleName(cloneTypeName);
type.getPackage().addType(clone);
new CtScanner() {
@Override
public <T> void visitCtTypeReference(CtTypeReference<T> reference) {
if (reference.getDeclaration() == null) {
return;
}
if (reference.getDeclaration() == type) {
reference.setSimpleName(cloneTypeName);
}
if (reference.getDeclaration() != clone) {
throw new SpoonException("post condition broken " + reference);
}
super.visitCtTypeReference(reference);
}
@Override
public <T> void visitCtExecutableReference(CtExecutableReference<T> reference) {
CtExecutable<T> declaration = reference.getDeclaration();
if (declaration == null) {
return;
}
if (declaration.hasParent(type)) {
reference.getDeclaringType().setSimpleName(cloneTypeName);
}
if (!reference.getDeclaration().hasParent(clone)) {
throw new SpoonException("post condition broken " + reference);
}
super.visitCtExecutableReference(reference);
}
@Override
public <T> void visitCtFieldReference(CtFieldReference<T> reference) {
CtField<T> declaration = reference.getDeclaration();
if (declaration == null) {
return;
}
if (declaration.hasParent(type)) {
reference.getDeclaringType().setSimpleName(cloneTypeName);
}
if (reference.getDeclaration() == null || !reference.getDeclaration().hasParent(clone)) {
throw new SpoonException("post condition broken " + reference);
}
super.visitCtFieldReference(reference);
}
}.scan(clone);
return clone;
}
use of spoon.reflect.visitor.CtScanner in project spoon by INRIA.
the class SiblingsFunction method apply.
@Override
public void apply(final CtElement input, final CtConsumer<Object> outputConsumer) {
final CtElement parent = input.getParent();
parent.accept(new CtScanner() {
boolean hasVisitedInput = false;
boolean visitPrev = mode == Mode.ALL || mode == Mode.PREVIOUS;
boolean visitNext = mode == Mode.ALL || mode == Mode.NEXT;
@Override
public void scan(CtElement element) {
if (element != null && element.isParentInitialized() && element.getParent() == parent) {
// visit only elements whose parent is same
boolean canVisit = hasVisitedInput ? visitNext : visitPrev;
if (input == element) {
hasVisitedInput = true;
canVisit = includingSelf;
}
if (canVisit) {
outputConsumer.accept(element);
}
}
}
});
}
use of spoon.reflect.visitor.CtScanner in project spoon by INRIA.
the class SubstitutionVisitor method substitute.
/**
* Substitutes all template parameters of element and returns substituted element.
*
* @param element to be substituted model
* @return substituted model
*/
public <E extends CtElement> List<E> substitute(E element) {
final Map<CtElement, String> elementToGeneratedByComment = addGeneratedBy ? new IdentityHashMap<CtElement, String>() : null;
if (addGeneratedBy) {
/*
* collect 'generated by' comments for each type member of the substituted element, before the substitution is done,
* so we know the origin names of the members.
*/
final CtInheritanceScanner internalScanner = new CtInheritanceScanner() {
public void scanCtTypeMember(CtTypeMember typeMeber) {
elementToGeneratedByComment.put(typeMeber, getGeneratedByComment(typeMeber));
}
};
new CtScanner() {
@Override
public void scan(CtElement p_element) {
internalScanner.scan(p_element);
super.scan(p_element);
}
}.scan(element);
}
List<E> result = createContext().substitute(element);
if (addGeneratedBy) {
// add generated by comments after substitution, otherwise they would be substituted in comments too.
applyGeneratedByComments(elementToGeneratedByComment);
}
return result;
}
use of spoon.reflect.visitor.CtScanner in project spoon by INRIA.
the class MainTest method checkParentConsistency.
public static void checkParentConsistency(CtElement ele) {
final Set<CtElement> inconsistentParents = new HashSet<>();
new CtScanner() {
private Deque<CtElement> previous = new ArrayDeque();
@Override
protected void enter(CtElement e) {
if (e != null) {
if (!previous.isEmpty()) {
try {
if (e.getParent() != previous.getLast()) {
inconsistentParents.add(e);
}
} catch (ParentNotInitializedException ignore) {
inconsistentParents.add(e);
}
}
previous.add(e);
}
super.enter(e);
}
@Override
protected void exit(CtElement e) {
if (e == null) {
return;
}
if (e.equals(previous.getLast())) {
previous.removeLast();
} else {
throw new RuntimeException("Inconsistent stack");
}
super.exit(e);
}
}.scan(ele);
assertEquals("All parents have to be consistent", 0, inconsistentParents.size());
}
Aggregations