/** * Copyright (C) 2006-2017 INRIA and contributors * Spoon - http://spoon.gforge.inria.fr/ * * This software is governed by the CeCILL-C License under French law and * abiding by the rules of distribution of free software. You can use, modify * and/or redistribute the software under the terms of the CeCILL-C license as * circulated by CEA, CNRS and INRIA at http://www.cecill.info. * * This program is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the CeCILL-C License for more details. * * The fact that you are presently reading this means that you have had * knowledge of the CeCILL-C license and that you accept its terms. */ package spoon.reflect.visitor.filter; import spoon.SpoonException; import spoon.reflect.code.CtCatchVariable; import spoon.reflect.code.CtLocalVariable; import spoon.reflect.declaration.CtElement; import spoon.reflect.declaration.CtField; import spoon.reflect.declaration.CtParameter; import spoon.reflect.declaration.CtVariable; import spoon.reflect.reference.CtVariableReference; import spoon.reflect.visitor.CtScanner; import spoon.reflect.visitor.chain.CtConsumableFunction; import spoon.reflect.visitor.chain.CtConsumer; /** * The mapping function, accepting {@link CtVariable} * <ul> * <li>CtLocalVariable - local variable declared in body * <li>CtField - member field of an type * <li>CtParameter - method parameter * <li>CtCatchVariable - try - catch variable * </ul> * and returning all the {@link CtVariableReference}, which refers this variable */ public class VariableReferenceFunction implements CtConsumableFunction<CtElement> { protected final Visitor visitor = new Visitor(); private final CtVariable<?> variable; protected CtConsumer<Object> outputConsumer; protected CtElement scope; public VariableReferenceFunction() { this.variable = null; } public VariableReferenceFunction(CtVariable<?> variable) { this.variable = variable; } @Override public void apply(CtElement variableOrScope, CtConsumer<Object> outputConsumer) { scope = variableOrScope; CtVariable<?> var = this.variable; if (var == null) { if (variableOrScope instanceof CtVariable<?>) { var = (CtVariable<?>) variableOrScope; } else { throw new SpoonException("The input of VariableReferenceFunction must be a CtVariable but is a " + variableOrScope.getClass().getSimpleName()); } } this.outputConsumer = outputConsumer; var.accept(visitor); } protected class Visitor extends CtScanner { @Override protected void enter(CtElement e) { throw new SpoonException("Unsupported variable of type " + e.getClass().getName()); } /** * calls outputConsumer for each reference of the field */ @Override public <T> void visitCtField(CtField<T> field) { new FieldReferenceFunction((CtField<?>) variable).apply(scope, outputConsumer); } /** * calls outputConsumer for each reference of the local variable */ @Override public <T> void visitCtLocalVariable(CtLocalVariable<T> localVariable) { new LocalVariableReferenceFunction((CtLocalVariable<?>) variable).apply(scope, outputConsumer); } /** * calls outputConsumer for each reference of the parameter */ @Override public <T> void visitCtParameter(CtParameter<T> parameter) { new ParameterReferenceFunction((CtParameter<?>) variable).apply(scope, outputConsumer); } /** * calls outputConsumer for each reference of the catch variable */ @Override public <T> void visitCtCatchVariable(CtCatchVariable<T> catchVariable) { new CatchVariableReferenceFunction((CtCatchVariable<?>) variable).apply(scope, outputConsumer); } } }