Search in sources :

Example 11 with CtLocalVariable

use of spoon.reflect.code.CtLocalVariable in project spoon by INRIA.

the class CtRenameLocalVariableRefactoringTest method testRenameAllLocalVariablesOfRenameTestSubject.

/**
 * The {@link CtRenameLocalVariableRefactoringTestSubject} class is loaded as spoon model. Then:
 * - It looks for each CtVariable and it's CtAnnotation and tries to rename that variable to the name defined by annotation.
 * - If the annotation name is prefixed with "-", then that refactoring should fail.
 * - If the annotation name is not prefixed, then that refactoring should pass.
 * If it behaves different then expected, then this test fails
 */
@Test
public void testRenameAllLocalVariablesOfRenameTestSubject() throws Exception {
    final Launcher launcher = new Launcher();
    final SpoonModelBuilder comp = launcher.createCompiler();
    comp.addInputSources(SpoonResourceHelper.resources("./src/test/java/" + CtRenameLocalVariableRefactoringTestSubject.class.getName().replace('.', '/') + ".java"));
    comp.build();
    final Factory factory = comp.getFactory();
    CtClass<?> varRenameClass = (CtClass<?>) factory.Type().get(CtRenameLocalVariableRefactoringTestSubject.class);
    CtTypeReference<TestTryRename> tryRename = varRenameClass.getFactory().createCtTypeReference(TestTryRename.class);
    varRenameClass.getMethods().forEach(method -> {
        // debugging support
        if (DEBUG.length == 3 && DEBUG[0].equals(method.getSimpleName()) == false)
            return;
        method.filterChildren((CtVariable var) -> true).map((CtVariable var) -> var.getAnnotation(tryRename)).forEach((CtAnnotation<TestTryRename> annotation) -> {
            String[] newNames = annotation.getActualAnnotation().value();
            CtVariable<?> targetVariable = (CtVariable<?>) annotation.getAnnotatedElement();
            for (String newName : newNames) {
                boolean renameShouldPass = newName.startsWith("-") == false;
                if (!renameShouldPass) {
                    newName = newName.substring(1);
                }
                if (targetVariable instanceof CtLocalVariable<?>) {
                    // debugging support
                    if (DEBUG.length == 3 && DEBUG[1].equals(targetVariable.getSimpleName()) && DEBUG[2].equals(newName)) {
                        // put breakpoint here and continue debugging of the buggy case
                        this.getClass();
                    }
                    checkLocalVariableRename(launcher, (CtLocalVariable<?>) targetVariable, newName, renameShouldPass);
                } else {
                // TODO test rename of other variables, e.g. parameters and catch... later
                }
            }
        });
    });
}
Also used : SpoonModelBuilder(spoon.SpoonModelBuilder) CtAnnotation(spoon.reflect.declaration.CtAnnotation) Factory(spoon.reflect.factory.Factory) CtLocalVariable(spoon.reflect.code.CtLocalVariable) CtClass(spoon.reflect.declaration.CtClass) TestTryRename(spoon.test.refactoring.testclasses.TestTryRename) CtVariable(spoon.reflect.declaration.CtVariable) Launcher(spoon.Launcher) CtRenameLocalVariableRefactoringTestSubject(spoon.test.refactoring.testclasses.CtRenameLocalVariableRefactoringTestSubject) Test(org.junit.Test)

Example 12 with CtLocalVariable

use of spoon.reflect.code.CtLocalVariable in project spoon by INRIA.

the class CtRenameLocalVariableRefactoring method detectNameConflicts.

@Override
protected void detectNameConflicts() {
    /*
		 * There can be these conflicts
		 * 1) target variable would shadow before declared variable (parameter, localVariable, catchVariable)
		 * --------------------------------------------------------------------------------------------------
		 */
    PotentialVariableDeclarationFunction potentialDeclarationFnc = new PotentialVariableDeclarationFunction(newName);
    CtVariable<?> var = getTarget().map(potentialDeclarationFnc).first();
    if (var != null) {
        if (var instanceof CtField) {
        /*
				 * we have found a field of same name.
				 * It is not problem, because variables can hide field declaration.
				 * Do nothing - OK
				 */
        } else if (potentialDeclarationFnc.isTypeOnTheWay()) {
            /*
				 * There is a local class declaration between future variable reference and variable declaration `var`.
				 * The found variable declaration `var` can be hidden by target variable with newName
				 * as long as there is no reference to `var` in visibility scope of the target variable.
				 * So search for such `var` reference now
				 */
            CtVariableReference<?> shadowedVar = target.map(new SiblingsFunction().includingSelf(true).mode(Mode.NEXT)).map(new VariableReferenceFunction(var)).first();
            if (shadowedVar != null) {
                // found variable reference, which would be shadowed by variable after rename.
                createNameConflictIssue(var, shadowedVar);
            } else {
            /*
					 * there is no local variable reference, which would be shadowed by variable after rename.
					 * OK
					 */
            }
        } else {
            /*
				 * the found variable is in conflict with target variable with newName
				 */
            createNameConflictIssue(var);
        }
    }
    /*
		 * 2) target variable is shadowed by later declared variable
		 * ---------------------------------------------------------
		 */
    final QueryDriver queryDriver = new QueryDriver();
    getTarget().map(new LocalVariableScopeFunction(queryDriver)).select(new Filter<CtElement>() {

        /**
         * return true for all CtVariables, which are in conflict
         */
        @Override
        public boolean matches(CtElement element) {
            if (element instanceof CtType<?>) {
                CtType<?> localClass = (CtType<?>) element;
                // TODO use faster hasField, implemented using map(new AllFieldsFunction()).select(new NameFilter(newName)).first()!=null
                Collection<CtFieldReference<?>> fields = localClass.getAllFields();
                for (CtFieldReference<?> fieldRef : fields) {
                    if (newName.equals(fieldRef.getSimpleName())) {
                        /*
							 * we have found a local class field, which will shadow input local variable if it's reference is in visibility scope of that field.
							 * Search for target variable reference in visibility scope of this field.
							 * If found than we cannot rename target variable to newName, because that reference would be shadowed
							 */
                        queryDriver.ignoreChildrenOf(element);
                        CtLocalVariableReference<?> shadowedVar = element.map(new LocalVariableReferenceFunction(target)).first();
                        if (shadowedVar != null) {
                            createNameConflictIssue(fieldRef.getFieldDeclaration(), shadowedVar);
                            return true;
                        }
                        return false;
                    }
                }
                return false;
            }
            if (element instanceof CtVariable<?>) {
                CtVariable<?> variable = (CtVariable<?>) element;
                if (newName.equals(variable.getSimpleName()) == false) {
                    // the variable with different name. Ignore it
                    return false;
                }
                // we have found a variable with new name
                if (variable instanceof CtField) {
                    throw new SpoonException("This should not happen. The children of local class which contains a field with new name should be skipped!");
                }
                if (variable instanceof CtCatchVariable || variable instanceof CtLocalVariable || variable instanceof CtParameter) {
                    /*
						 * we have found a catch variable or local variable or parameter with new name.
						 */
                    if (queryDriver.isInContextOfLocalClass()) {
                        /*
							 * We are in context of local class.
							 * This variable would shadow input local variable after rename
							 * so we cannot rename if there exist a local variable reference in variable visibility scope.
							 */
                        queryDriver.ignoreChildrenOf(variable.getParent());
                        CtQueryable searchScope;
                        if (variable instanceof CtLocalVariable) {
                            searchScope = variable.map(new SiblingsFunction().includingSelf(true).mode(Mode.NEXT));
                        } else {
                            searchScope = variable.getParent();
                        }
                        CtLocalVariableReference<?> shadowedVar = searchScope.map(new LocalVariableReferenceFunction(target)).first();
                        if (shadowedVar != null) {
                            // found local variable reference, which would be shadowed by variable after rename.
                            createNameConflictIssue(variable, shadowedVar);
                            return true;
                        }
                        // there is no local variable reference, which would be shadowed by variable after rename.
                        return false;
                    } else {
                        /*
							 * We are not in context of local class.
							 * So this variable is in conflict. Return it
							 */
                        createNameConflictIssue(variable);
                        return true;
                    }
                } else {
                    // Any new variable type???
                    throw new SpoonException("Unexpected variable " + variable.getClass().getName());
                }
            }
            return false;
        }
    }).first();
}
Also used : CtVariableReference(spoon.reflect.reference.CtVariableReference) SiblingsFunction(spoon.reflect.visitor.filter.SiblingsFunction) SpoonException(spoon.SpoonException) CtElement(spoon.reflect.declaration.CtElement) VariableReferenceFunction(spoon.reflect.visitor.filter.VariableReferenceFunction) LocalVariableReferenceFunction(spoon.reflect.visitor.filter.LocalVariableReferenceFunction) CtFieldReference(spoon.reflect.reference.CtFieldReference) CtParameter(spoon.reflect.declaration.CtParameter) CtLocalVariable(spoon.reflect.code.CtLocalVariable) CtType(spoon.reflect.declaration.CtType) Filter(spoon.reflect.visitor.Filter) CtField(spoon.reflect.declaration.CtField) CtQueryable(spoon.reflect.visitor.chain.CtQueryable) CtVariable(spoon.reflect.declaration.CtVariable) PotentialVariableDeclarationFunction(spoon.reflect.visitor.filter.PotentialVariableDeclarationFunction) CtCatchVariable(spoon.reflect.code.CtCatchVariable) LocalVariableScopeFunction(spoon.reflect.visitor.filter.LocalVariableScopeFunction) LocalVariableReferenceFunction(spoon.reflect.visitor.filter.LocalVariableReferenceFunction)

Example 13 with CtLocalVariable

use of spoon.reflect.code.CtLocalVariable in project spoon by INRIA.

the class AccessibleVariablesFinder method getVariable.

private List<CtVariable> getVariable(final CtElement parent) {
    final List<CtVariable> variables = new ArrayList<>();
    if (parent == null) {
        return variables;
    }
    class VariableScanner extends CtInheritanceScanner {

        @Override
        public void visitCtStatementList(CtStatementList e) {
            for (int i = 0; i < e.getStatements().size(); i++) {
                CtStatement ctStatement = e.getStatements().get(i);
                if (ctStatement.getPosition() == null) {
                }
                if (ctStatement.getPosition() != null && ctStatement.getPosition().getSourceStart() > expression.getPosition().getSourceEnd()) {
                    break;
                }
                if (ctStatement instanceof CtVariable) {
                    variables.add((CtVariable) ctStatement);
                }
            }
            super.visitCtStatementList(e);
        }

        @Override
        public <T> void scanCtType(CtType<T> type) {
            List<CtField<?>> fields = type.getFields();
            for (int i = 0; i < fields.size(); i++) {
                CtField<?> ctField = fields.get(i);
                if (ctField.hasModifier(ModifierKind.PUBLIC) || ctField.hasModifier(ModifierKind.PROTECTED)) {
                    variables.add(ctField);
                } else if (ctField.hasModifier(ModifierKind.PRIVATE)) {
                    if (expression.hasParent(type)) {
                        variables.add(ctField);
                    }
                } else if (expression.getParent(CtPackage.class).equals(type.getParent(CtPackage.class))) {
                    // default visibility
                    variables.add(ctField);
                }
            }
            CtTypeReference<?> superclass = type.getSuperclass();
            if (superclass != null) {
                variables.addAll(getVariable(superclass.getTypeDeclaration()));
            }
            Set<CtTypeReference<?>> superInterfaces = type.getSuperInterfaces();
            for (Iterator<CtTypeReference<?>> iterator = superInterfaces.iterator(); iterator.hasNext(); ) {
                CtTypeReference<?> typeReference = iterator.next();
                variables.addAll(getVariable(typeReference.getTypeDeclaration()));
            }
            super.scanCtType(type);
        }

        @Override
        public void visitCtTryWithResource(CtTryWithResource e) {
            variables.addAll(e.getResources());
            super.visitCtTryWithResource(e);
        }

        @Override
        public void scanCtExecutable(CtExecutable e) {
            variables.addAll(e.getParameters());
            super.scanCtExecutable(e);
        }

        @Override
        public void visitCtFor(CtFor e) {
            for (CtStatement ctStatement : e.getForInit()) {
                this.scan(ctStatement);
            }
            super.visitCtFor(e);
        }

        @Override
        public void visitCtForEach(CtForEach e) {
            variables.add(e.getVariable());
            super.visitCtForEach(e);
        }

        @Override
        public void visitCtMethod(CtMethod e) {
            this.scan(e.getBody());
            super.visitCtMethod(e);
        }

        @Override
        public void visitCtLocalVariable(CtLocalVariable e) {
            variables.add(e);
            super.visitCtLocalVariable(e);
        }

        @Override
        public void visitCtCatch(CtCatch e) {
            variables.add(e.getParameter());
            super.visitCtCatch(e);
        }
    }
    new VariableScanner().scan(parent);
    return variables;
}
Also used : ArrayList(java.util.ArrayList) CtLocalVariable(spoon.reflect.code.CtLocalVariable) CtExecutable(spoon.reflect.declaration.CtExecutable) CtForEach(spoon.reflect.code.CtForEach) CtType(spoon.reflect.declaration.CtType) CtStatement(spoon.reflect.code.CtStatement) CtField(spoon.reflect.declaration.CtField) CtTypeReference(spoon.reflect.reference.CtTypeReference) CtVariable(spoon.reflect.declaration.CtVariable) CtStatementList(spoon.reflect.code.CtStatementList) CtPackage(spoon.reflect.declaration.CtPackage) CtTryWithResource(spoon.reflect.code.CtTryWithResource) CtCatch(spoon.reflect.code.CtCatch) CtFor(spoon.reflect.code.CtFor) CtMethod(spoon.reflect.declaration.CtMethod)

Example 14 with CtLocalVariable

use of spoon.reflect.code.CtLocalVariable in project spoon by INRIA.

the class VariableAccessTest method testDeclarationArray.

@Test
public void testDeclarationArray() throws Exception {
    final CtType<Pozole> aPozole = ModelUtils.buildClass(Pozole.class);
    final CtMethod<Object> m2 = aPozole.getMethod("m2");
    final CtArrayWrite<?> ctArrayWrite = m2.getElements(new TypeFilter<CtArrayWrite<?>>(CtArrayWrite.class)).get(0);
    final CtLocalVariable expected = m2.getElements(new TypeFilter<CtLocalVariable>(CtLocalVariable.class)).get(0);
    assertEquals(expected, ((CtVariableAccess) ctArrayWrite.getTarget()).getVariable().getDeclaration());
}
Also used : CtVariableAccess(spoon.reflect.code.CtVariableAccess) Pozole(spoon.test.reference.testclasses.Pozole) TypeFilter(spoon.reflect.visitor.filter.TypeFilter) CtLocalVariable(spoon.reflect.code.CtLocalVariable) Test(org.junit.Test)

Example 15 with CtLocalVariable

use of spoon.reflect.code.CtLocalVariable in project spoon by INRIA.

the class VariableAccessTest method testGetDeclarationAfterClone.

@Test
public void testGetDeclarationAfterClone() throws Exception {
    final Launcher launcher = new Launcher();
    launcher.getEnvironment().setNoClasspath(true);
    launcher.addInputResource("./src/test/resources/noclasspath/A2.java");
    launcher.buildModel();
    final CtClass<Object> a2 = launcher.getFactory().Class().get("A2");
    final CtClass<Object> a2Cloned = a2.clone();
    assertEquals(a2, a2Cloned);
    final CtMethod<Object> methodA2 = getMethod(launcher, a2);
    final CtMethod<Object> methodA2Cloned = getMethod(launcher, a2Cloned);
    final CtLocalVariable declaration = methodA2.getBody().getStatement(0);
    final CtLocalVariable declarationCloned = methodA2Cloned.getBody().getStatement(0);
    final CtLocalVariableReference localVarRef = getLocalVariableRefF1(methodA2);
    final CtLocalVariableReference localVarRefCloned = getLocalVariableRefF1(methodA2Cloned);
    assertEquals(localVarRef.getDeclaration(), declaration);
    assertSame(localVarRef.getDeclaration(), declaration);
    assertEquals(localVarRefCloned.getDeclaration(), declarationCloned);
    assertSame(localVarRefCloned.getDeclaration(), declarationCloned);
}
Also used : CtLocalVariableReference(spoon.reflect.reference.CtLocalVariableReference) Launcher(spoon.Launcher) CtLocalVariable(spoon.reflect.code.CtLocalVariable) Test(org.junit.Test)

Aggregations

CtLocalVariable (spoon.reflect.code.CtLocalVariable)29 Test (org.junit.Test)21 Factory (spoon.reflect.factory.Factory)15 Launcher (spoon.Launcher)10 CtParameter (spoon.reflect.declaration.CtParameter)7 CtTypeReference (spoon.reflect.reference.CtTypeReference)7 TypeFilter (spoon.reflect.visitor.filter.TypeFilter)7 CtStatement (spoon.reflect.code.CtStatement)6 CtClass (spoon.reflect.declaration.CtClass)6 CtMethod (spoon.reflect.declaration.CtMethod)6 CtElement (spoon.reflect.declaration.CtElement)5 CtLocalVariableReference (spoon.reflect.reference.CtLocalVariableReference)5 List (java.util.List)4 CtComment (spoon.reflect.code.CtComment)4 CtTry (spoon.reflect.code.CtTry)4 CtField (spoon.reflect.declaration.CtField)4 CtType (spoon.reflect.declaration.CtType)4 CtAssignment (spoon.reflect.code.CtAssignment)3 CtCatchVariable (spoon.reflect.code.CtCatchVariable)3 CtExpression (spoon.reflect.code.CtExpression)3