use of spoon.reflect.reference.CtVariableReference in project spoon by INRIA.
the class LocalVariableReferenceFunction method apply.
@Override
public void apply(final CtElement scope, CtConsumer<Object> outputConsumer) {
CtVariable<?> var = targetVariable;
if (var == null) {
if (variableClass.isInstance(scope)) {
var = (CtVariable<?>) scope;
} else {
throw new SpoonException("The input of " + getClass().getSimpleName() + " must be a " + variableClass.getSimpleName() + " but is " + scope.getClass().getSimpleName());
}
}
final CtVariable<?> variable = var;
final String simpleName = variable.getSimpleName();
// the context which knows whether we are scanning in scope of local type or not
final Context context = new Context();
CtQuery scopeQuery;
if (scope == variable) {
// we are starting search from local variable declaration
scopeQuery = createScopeQuery(variable, scope, context);
} else {
// we are starting search later, somewhere deep in scope of variable declaration
final CtElement variableParent = variable.getParent();
/*
* search in parents of searching scope for the variableParent
* 1) to check that scope is a child of variableParent
* 2) to detect if there is an local class between variable declaration and scope
*/
if (scope.map(new ParentFunction()).select(new Filter<CtElement>() {
@Override
public boolean matches(CtElement element) {
if (element instanceof CtType) {
// detected that the search scope is in local class declared in visibility scope of variable
context.nrTypes++;
}
return variableParent == element;
}
}).first() == null) {
// the scope is not under children of localVariable
throw new SpoonException("Cannot search for references of variable in wrong scope.");
}
// search in all children of the scope element
scopeQuery = scope.map(new CtScannerFunction().setListener(context));
}
scopeQuery.select(new Filter<CtElement>() {
@Override
public boolean matches(CtElement element) {
if (variableReferenceClass.isInstance(element)) {
CtVariableReference<?> varRef = (CtVariableReference<?>) element;
if (simpleName.equals(varRef.getSimpleName())) {
// we have found a variable reference of required type in visibility scope of targetVariable
if (context.hasLocalType()) {
// so finally check that found variable reference is really a reference to target variable
return variable == varRef.getDeclaration();
}
// else we can be sure that found reference is reference to variable
return true;
}
}
return false;
}
}).forEach(outputConsumer);
}
Aggregations