use of spoon.reflect.declaration.CtType in project spoon by INRIA.
the class SubInheritanceHierarchyFunction method apply.
@Override
public void apply(CtTypeInformation input, final CtConsumer<Object> outputConsumer) {
final SubInheritanceHierarchyResolver fnc = new SubInheritanceHierarchyResolver(((CtElement) input).getFactory().getModel().getRootPackage()).failOnClassNotFound(failOnClassNotFound).includingInterfaces(includingInterfaces);
if (includingSelf) {
if (input instanceof CtTypeReference) {
outputConsumer.accept(((CtTypeReference<?>) input).getTypeDeclaration());
} else {
outputConsumer.accept(((CtType<?>) input));
}
}
fnc.addSuperType(input);
fnc.forEachSubTypeInPackage(new CtConsumer<CtType>() {
@Override
public void accept(CtType typeInfo) {
outputConsumer.accept(typeInfo);
if (query.isTerminated()) {
// Cannot terminate, because it's support was removed.
// I think there are cases where it might be useful.
// fnc.terminate();
}
}
});
}
use of spoon.reflect.declaration.CtType 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.CtType in project spoon by INRIA.
the class CtTypeImpl method getNestedType.
@Override
@SuppressWarnings("unchecked")
public <N extends CtType<?>> N getNestedType(final String name) {
class NestedTypeScanner extends EarlyTerminatingScanner<CtType<?>> {
private boolean checkType(CtType<?> type) {
if (type.getSimpleName().equals(name) && CtTypeImpl.this.equals(type.getDeclaringType())) {
setResult(type);
terminate();
return true;
}
return false;
}
@Override
public <U> void visitCtClass(spoon.reflect.declaration.CtClass<U> ctClass) {
if (!checkType(ctClass)) {
final List<CtTypeMember> typeMembers = new ArrayList<>();
for (CtTypeMember typeMember : ctClass.getTypeMembers()) {
if (typeMember instanceof CtType || typeMember instanceof CtConstructor || typeMember instanceof CtMethod) {
typeMembers.add(typeMember);
}
}
scan(typeMembers);
}
}
@Override
public <U> void visitCtInterface(spoon.reflect.declaration.CtInterface<U> intrface) {
if (!checkType(intrface)) {
final List<CtTypeMember> typeMembers = new ArrayList<>();
for (CtTypeMember typeMember : intrface.getTypeMembers()) {
if (typeMember instanceof CtType || typeMember instanceof CtMethod) {
typeMembers.add(typeMember);
}
}
scan(typeMembers);
}
}
@Override
public <U extends java.lang.Enum<?>> void visitCtEnum(spoon.reflect.declaration.CtEnum<U> ctEnum) {
if (!checkType(ctEnum)) {
final List<CtTypeMember> typeMembers = new ArrayList<>();
for (CtTypeMember typeMember : ctEnum.getTypeMembers()) {
if (typeMember instanceof CtType || typeMember instanceof CtConstructor || typeMember instanceof CtMethod) {
typeMembers.add(typeMember);
}
}
scan(typeMembers);
}
}
@Override
public <A extends Annotation> void visitCtAnnotationType(CtAnnotationType<A> annotationType) {
if (!checkType(annotationType)) {
scan(annotationType.getNestedTypes());
}
}
}
NestedTypeScanner scanner = new NestedTypeScanner();
scanner.scan(this);
return (N) scanner.getResult();
}
use of spoon.reflect.declaration.CtType in project spoon by INRIA.
the class SubInheritanceHierarchyResolver method forEachSubTypeInPackage.
/**
* Calls `outputConsumer.apply(subType)` for each sub type of the targetSuperTypes that are found in `inputPackage`.
* Each sub type is returned only once.
* It makes sense to call this method again for example after new super types are added
* by {@link #addSuperType(CtTypeInformation)}.
*
* If this method is called again with same input and configuration, nothing in sent to outputConsumer
* @param outputConsumer the consumer for found sub types
*/
public <T extends CtType<?>> void forEachSubTypeInPackage(final CtConsumer<T> outputConsumer) {
/*
* Set of qualified names of all visited types, independent on whether they are sub types or not.
*/
final Set<String> allVisitedTypeNames = new HashSet<>();
/*
* the queue of types whose super inheritance hierarchy we are just visiting.
* They are potential sub types of an `targetSuperTypes`
*/
final Deque<CtTypeReference<?>> currentSubTypes = new ArrayDeque<>();
// algorithm
// 1) query step: scan input package for sub classes and sub interfaces
final CtQuery q = inputPackage.map(new CtScannerFunction());
// 2) query step: visit only required CtTypes
if (includingInterfaces) {
// the client is interested in sub inheritance hierarchy of interfaces too. Check interfaces, classes, enums, Annotations, but not CtTypeParameters.
q.select(typeFilter);
} else {
// the client is not interested in sub inheritance hierarchy of interfaces. Check only classes and enums.
q.select(classFilter);
}
/*
* 3) query step: for each found CtType, visit it's super inheritance hierarchy and search there for a type which is equal to one of targetSuperTypes.
* If found then all sub types in hierarchy (variable `currentSubTypes`) are sub types of targetSuperTypes. So return them
*/
q.map(new SuperInheritanceHierarchyFunction().includingInterfaces(hasSuperInterface).failOnClassNotFound(failOnClassNotFound).setListener(new CtScannerListener() {
@Override
public ScanningMode enter(CtElement element) {
final CtTypeReference<?> typeRef = (CtTypeReference<?>) element;
String qName = typeRef.getQualifiedName();
if (targetSuperTypes.contains(qName)) {
/*
* FOUND! we are in super inheritance hierarchy, which extends from an searched super type(s).
* All `currentSubTypes` are sub types of searched super type
*/
while (currentSubTypes.size() > 0) {
final CtTypeReference<?> currentTypeRef = currentSubTypes.pop();
String currentQName = currentTypeRef.getQualifiedName();
/*
* Send them to outputConsumer and add then as targetSuperTypes too, to perform faster with detection of next sub types.
*/
if (!targetSuperTypes.contains(currentQName)) {
targetSuperTypes.add(currentQName);
outputConsumer.accept((T) currentTypeRef.getTypeDeclaration());
}
}
// but continue visiting of siblings (do not terminate query)
return SKIP_ALL;
}
if (allVisitedTypeNames.add(qName) == false) {
/*
* this type was already visited, by another way. So it is not sub type of `targetSuperTypes`.
* Stop visiting it's inheritance hierarchy.
*/
return SKIP_ALL;
}
/*
* This type was not visited yet.
* We still do not know whether this type is a sub type of any target super type(s)
* continue searching in super inheritance hierarchy
*/
currentSubTypes.push(typeRef);
return NORMAL;
}
@Override
public void exit(CtElement element) {
CtTypeInformation type = (CtTypeInformation) element;
if (currentSubTypes.isEmpty() == false) {
// remove current type, which is not a sub type of targetSuperTypes from the currentSubTypes
CtTypeInformation stackType = currentSubTypes.pop();
if (stackType != type) {
// the enter/exit was not called consistently. There is a bug in SuperInheritanceHierarchyFunction
throw new SpoonException("CtScannerListener#exit was not called after enter.");
}
}
}
})).forEach(new CtConsumer<CtType<?>>() {
@Override
public void accept(CtType<?> type) {
// we do not care about types visited by query `q`.
// the result of whole mapping function was already produced by `sendResult` call
// but we have to consume all these results to let query running
}
});
}
use of spoon.reflect.declaration.CtType in project spoon by INRIA.
the class TypeReferenceScanner method visitCtInterface.
@Override
public <T> void visitCtInterface(CtInterface<T> intrface) {
addReference(intrface.getReference());
for (CtTypeMember typeMember : intrface.getTypeMembers()) {
if (typeMember instanceof CtType) {
addReference(((CtType) typeMember).getReference());
}
}
super.visitCtInterface(intrface);
}
Aggregations