Search in sources :

Example 1 with PotentialVariableDeclarationFunction

use of spoon.reflect.visitor.filter.PotentialVariableDeclarationFunction in project spoon by INRIA.

the class DefaultJavaPrettyPrinter method printCtFieldAccess.

private <T> void printCtFieldAccess(CtFieldAccess<T> f) {
    enterCtExpression(f);
    try (Writable _context = context.modify()) {
        if ((f.getVariable().isStatic() || "class".equals(f.getVariable().getSimpleName())) && f.getTarget() instanceof CtTypeAccess) {
            _context.ignoreGenerics(true);
        }
        CtExpression<?> target = f.getTarget();
        if (target != null) {
            boolean isInitializeStaticFinalField = isInitializeStaticFinalField(f.getTarget());
            boolean isStaticField = f.getVariable().isStatic();
            boolean isImportedField = this.isImported(f.getVariable());
            if (!isInitializeStaticFinalField && !(isStaticField && isImportedField)) {
                if (target.isImplicit() && !(f.getVariable().getFieldDeclaration() == null && this.env.getNoClasspath())) {
                    /*
						 * target is implicit, check whether there is no conflict with an local variable, catch variable or parameter
						 * in case of conflict make it explicit, otherwise the field access is shadowed by that variable.
						 * Search for potential variable declaration until we found a class which declares or inherits this field
						 */
                    final CtField<?> field = f.getVariable().getFieldDeclaration();
                    if (field != null) {
                        final String fieldName = field.getSimpleName();
                        CtVariable<?> var = f.getVariable().map(new PotentialVariableDeclarationFunction(fieldName)).first();
                        if (var != field) {
                            // another variable declaration was found which is hiding the field declaration for this field access. Make the field access expicit
                            target.setImplicit(false);
                        }
                    } else {
                        // There is a model inconsistency
                        printer.writeComment(f.getFactory().createComment("ERROR: Missing field \"" + f.getVariable().getSimpleName() + "\", please check your model. The code may not compile.", CommentType.BLOCK)).writeSpace();
                    }
                }
                // the implicit drives the separator
                if (!target.isImplicit()) {
                    scan(target);
                    printer.writeSeparator(".");
                }
            }
            _context.ignoreStaticAccess(true);
        }
        scan(f.getVariable());
    }
    exitCtExpression(f);
}
Also used : PotentialVariableDeclarationFunction(spoon.reflect.visitor.filter.PotentialVariableDeclarationFunction) Writable(spoon.reflect.visitor.PrintingContext.Writable) CtTypeAccess(spoon.reflect.code.CtTypeAccess)

Example 2 with PotentialVariableDeclarationFunction

use of spoon.reflect.visitor.filter.PotentialVariableDeclarationFunction 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 3 with PotentialVariableDeclarationFunction

use of spoon.reflect.visitor.filter.PotentialVariableDeclarationFunction in project spoon by INRIA.

the class VariableReferencesTest method testPotentialVariableAccessFromStaticMethod.

@Test
public void testPotentialVariableAccessFromStaticMethod() throws Exception {
    Factory factory = ModelUtils.build(VariableReferencesFromStaticMethod.class);
    CtClass<?> clazz = factory.Class().get(VariableReferencesFromStaticMethod.class);
    CtMethod staticMethod = clazz.getMethodsByName("staticMethod").get(0);
    CtStatement stmt = staticMethod.getBody().getStatements().get(1);
    assertEquals("org.junit.Assert.assertTrue((field == 2))", stmt.toString());
    CtLocalVariableReference varRef = stmt.filterChildren(new TypeFilter<>(CtLocalVariableReference.class)).first();
    List<CtVariable> vars = varRef.map(new PotentialVariableDeclarationFunction()).list();
    assertEquals("Found unexpected variable declaration.", 1, vars.size());
}
Also used : CtStatement(spoon.reflect.code.CtStatement) CtLocalVariableReference(spoon.reflect.reference.CtLocalVariableReference) CtVariable(spoon.reflect.declaration.CtVariable) PotentialVariableDeclarationFunction(spoon.reflect.visitor.filter.PotentialVariableDeclarationFunction) Factory(spoon.reflect.factory.Factory) TypeFilter(spoon.reflect.visitor.filter.TypeFilter) CtMethod(spoon.reflect.declaration.CtMethod) VariableReferencesModelTest(spoon.test.query_function.testclasses.VariableReferencesModelTest) Test(org.junit.Test)

Example 4 with PotentialVariableDeclarationFunction

use of spoon.reflect.visitor.filter.PotentialVariableDeclarationFunction in project spoon by INRIA.

the class CtLocalVariableReferenceImpl method getDeclaration.

@SuppressWarnings("unchecked")
@Override
public CtLocalVariable<T> getDeclaration() {
    // without a factory, we are not able to filter for local variables
    final Factory factory = getFactory();
    if (factory == null) {
        return null;
    }
    final String simpleName = getSimpleName();
    // handle the CtLocalVariableReference which were created by CtLocalVariable#getReference() and which are not yet part of model, so we cannot found them using standard rules
    if (parent instanceof CtLocalVariable) {
        CtLocalVariable<T> var = (CtLocalVariable<T>) parent;
        if (simpleName.equals(var.getSimpleName())) {
            return var;
        }
    }
    try {
        // successively iterate through all parents of this reference and
        // return first result (which must be the closest declaration
        // respecting visible scope)
        CtVariable<?> var = map(new PotentialVariableDeclarationFunction(simpleName)).first();
        if (var instanceof CtLocalVariable) {
            return (CtLocalVariable<T>) var;
        }
        if (var != null) {
            // handle it as not found
            return null;
        }
    } catch (ParentNotInitializedException e) {
    // handle this case as 'not found'
    }
    return null;
}
Also used : ParentNotInitializedException(spoon.reflect.declaration.ParentNotInitializedException) PotentialVariableDeclarationFunction(spoon.reflect.visitor.filter.PotentialVariableDeclarationFunction) Factory(spoon.reflect.factory.Factory) CtLocalVariable(spoon.reflect.code.CtLocalVariable)

Aggregations

PotentialVariableDeclarationFunction (spoon.reflect.visitor.filter.PotentialVariableDeclarationFunction)4 CtLocalVariable (spoon.reflect.code.CtLocalVariable)2 CtVariable (spoon.reflect.declaration.CtVariable)2 Factory (spoon.reflect.factory.Factory)2 Test (org.junit.Test)1 SpoonException (spoon.SpoonException)1 CtCatchVariable (spoon.reflect.code.CtCatchVariable)1 CtStatement (spoon.reflect.code.CtStatement)1 CtTypeAccess (spoon.reflect.code.CtTypeAccess)1 CtElement (spoon.reflect.declaration.CtElement)1 CtField (spoon.reflect.declaration.CtField)1 CtMethod (spoon.reflect.declaration.CtMethod)1 CtParameter (spoon.reflect.declaration.CtParameter)1 CtType (spoon.reflect.declaration.CtType)1 ParentNotInitializedException (spoon.reflect.declaration.ParentNotInitializedException)1 CtFieldReference (spoon.reflect.reference.CtFieldReference)1 CtLocalVariableReference (spoon.reflect.reference.CtLocalVariableReference)1 CtVariableReference (spoon.reflect.reference.CtVariableReference)1 Filter (spoon.reflect.visitor.Filter)1 Writable (spoon.reflect.visitor.PrintingContext.Writable)1