Search in sources :

Example 41 with CtElement

use of spoon.reflect.declaration.CtElement in project spoon by INRIA.

the class ElementPrinterHelper method writeAnnotationElement.

/**
 * Writes an annotation element.
 */
public void writeAnnotationElement(Factory factory, Object value) {
    if (value instanceof CtTypeAccess) {
        prettyPrinter.scan((CtTypeAccess) value);
        printer.writeSeparator(".").writeKeyword("class");
    } else if (value instanceof CtFieldReference) {
        prettyPrinter.scan(((CtFieldReference<?>) value).getDeclaringType());
        printer.writeSeparator(".").writeIdentifier(((CtFieldReference<?>) value).getSimpleName());
    } else if (value instanceof CtElement) {
        prettyPrinter.scan((CtElement) value);
    } else if (value instanceof String) {
        printer.writeLiteral("\"" + LiteralHelper.getStringLiteral((String) value, true) + "\"");
    } else if (value instanceof Collection) {
        try (ListPrinter lp = createListPrinter(false, "{", false, true, ",", false, false, "}")) {
            for (Object obj : (Collection<?>) value) {
                lp.printSeparatorIfAppropriate();
                writeAnnotationElement(factory, obj);
            }
        }
    } else if (value instanceof Object[]) {
        try (ListPrinter lp = createListPrinter(false, "{", false, true, ",", false, false, "}")) {
            for (Object obj : (Object[]) value) {
                lp.printSeparatorIfAppropriate();
                writeAnnotationElement(factory, obj);
            }
        }
    } else if (value instanceof Enum) {
        try (Writable c = prettyPrinter.getContext().modify().ignoreGenerics(true)) {
            prettyPrinter.scan(factory.Type().createReference(((Enum<?>) value).getDeclaringClass()));
        }
        printer.writeSeparator(".");
        printer.writeIdentifier(value.toString());
    } else {
        // it probably prints, boolean, number, ...
        printer.writeLiteral(value.toString());
    }
}
Also used : CtElement(spoon.reflect.declaration.CtElement) CtTypeAccess(spoon.reflect.code.CtTypeAccess) CtFieldReference(spoon.reflect.reference.CtFieldReference) Collection(java.util.Collection) Writable(spoon.reflect.visitor.PrintingContext.Writable)

Example 42 with CtElement

use of spoon.reflect.declaration.CtElement in project spoon by INRIA.

the class CtParameterRemoveRefactoring method computeAllInvocations.

/**
 * search for all methods and lambdas which has to be refactored together with target method
 */
private void computeAllInvocations() {
    ExecutableReferenceFilter execRefFilter = new ExecutableReferenceFilter();
    for (CtExecutable<?> exec : getTargetExecutables()) {
        execRefFilter.addExecutable(exec);
    }
    // all the invocations, which belongs to same inheritance tree
    final List<CtInvocation<?>> invocations = new ArrayList<>();
    target.getFactory().getModel().filterChildren(execRefFilter).forEach(new CtConsumer<CtExecutableReference<?>>() {

        @Override
        public void accept(CtExecutableReference<?> t) {
            CtElement parent = t.getParent();
            if (parent instanceof CtInvocation<?>) {
                invocations.add((CtInvocation<?>) parent);
            }
        // else ignore other hits, which are not in context of invocation
        }
    });
    targetInvocations = Collections.unmodifiableList(invocations);
}
Also used : CtInvocation(spoon.reflect.code.CtInvocation) CtElement(spoon.reflect.declaration.CtElement) ArrayList(java.util.ArrayList) CtExecutableReference(spoon.reflect.reference.CtExecutableReference) ExecutableReferenceFilter(spoon.reflect.visitor.filter.ExecutableReferenceFilter)

Example 43 with CtElement

use of spoon.reflect.declaration.CtElement 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 44 with CtElement

use of spoon.reflect.declaration.CtElement in project spoon by INRIA.

the class TypeFactory method createTypeAdapter.

/**
 * Create a {@link GenericTypeAdapter} for adapting of formal type parameters from any compatible context to the context of provided `formalTypeDeclarer`
 *
 * @param formalTypeDeclarer
 * 		the target scope of the returned {@link GenericTypeAdapter}
 */
public GenericTypeAdapter createTypeAdapter(CtFormalTypeDeclarer formalTypeDeclarer) {
    class Visitor extends CtAbstractVisitor {

        GenericTypeAdapter adapter;

        @Override
        public <T> void visitCtClass(CtClass<T> ctClass) {
            adapter = new ClassTypingContext(ctClass);
        }

        @Override
        public <T> void visitCtInterface(CtInterface<T> intrface) {
            adapter = new ClassTypingContext(intrface);
        }

        @Override
        public <T> void visitCtMethod(CtMethod<T> m) {
            adapter = new MethodTypingContext().setMethod(m);
        }

        @Override
        public <T> void visitCtConstructor(CtConstructor<T> c) {
            adapter = new MethodTypingContext().setConstructor(c);
        }
    }
    Visitor visitor = new Visitor();
    ((CtElement) formalTypeDeclarer).accept(visitor);
    return visitor.adapter;
}
Also used : CtAbstractVisitor(spoon.reflect.visitor.CtAbstractVisitor) CtClass(spoon.reflect.declaration.CtClass) CtInterface(spoon.reflect.declaration.CtInterface) ClassTypingContext(spoon.support.visitor.ClassTypingContext) GenericTypeAdapter(spoon.support.visitor.GenericTypeAdapter) CtAbstractVisitor(spoon.reflect.visitor.CtAbstractVisitor) MethodTypingContext(spoon.support.visitor.MethodTypingContext) CtElement(spoon.reflect.declaration.CtElement) CtMethod(spoon.reflect.declaration.CtMethod) CtConstructor(spoon.reflect.declaration.CtConstructor)

Example 45 with CtElement

use of spoon.reflect.declaration.CtElement in project spoon by INRIA.

the class CtElementPathBuilder method fromElement.

/**
 * Build path to a CtElement el, from one of its parent.
 *
 * @throws CtPathException is thrown when root is not a parent of el.
 *
 * @param el : the element to which the CtPath leads to
 * @param root : Starting point of the CtPath
 * @return CtPath from root to el
 */
public CtPath fromElement(CtElement el, CtElement root) throws CtPathException {
    CtPathImpl path = new CtPathImpl();
    CtElement cur = el;
    while (cur != root) {
        CtElement parent = cur.getParent();
        CtRole role = cur.getRoleInParent();
        if (role == null) {
            throw new CtPathException();
        }
        RoleHandler roleHandler = RoleHandlerHelper.getOptionalRoleHandler(parent.getClass(), role);
        if (roleHandler == null) {
            throw new CtPathException();
        }
        CtPathElement pathElement = new CtRolePathElement(role);
        switch(roleHandler.getContainerKind()) {
            case SINGLE:
                break;
            case LIST:
                // Element needs to be differentiated from its brothers
                List list = roleHandler.asList(parent);
                // Assumes that List's order is deterministic.
                // Can't be replaced by list.indexOf(cur)
                // Because objects must be the same (and not just equals)
                int index = 0;
                for (Object o : list) {
                    if (o == cur) {
                        break;
                    }
                    index++;
                }
                pathElement.addArgument("index", index + "");
                break;
            case SET:
                String name;
                if (cur instanceof CtNamedElement) {
                    name = ((CtNamedElement) cur).getSimpleName();
                } else if (cur instanceof CtReference) {
                    name = ((CtReference) cur).getSimpleName();
                } else {
                    throw new CtPathException();
                }
                pathElement.addArgument("name", name);
                break;
            case MAP:
                Map map = roleHandler.asMap(parent);
                String key = null;
                for (Object o : map.keySet()) {
                    if (map.get(o) == cur) {
                        key = (String) o;
                        break;
                    }
                }
                if (key == null) {
                    throw new CtPathException();
                } else {
                    pathElement.addArgument("key", key);
                }
                break;
        }
        cur = parent;
        path.addFirst(pathElement);
    }
    return path;
}
Also used : CtElement(spoon.reflect.declaration.CtElement) RoleHandler(spoon.reflect.meta.RoleHandler) CtPathElement(spoon.reflect.path.impl.CtPathElement) CtRolePathElement(spoon.reflect.path.impl.CtRolePathElement) CtPathImpl(spoon.reflect.path.impl.CtPathImpl) CtReference(spoon.reflect.reference.CtReference) List(java.util.List) CtNamedElement(spoon.reflect.declaration.CtNamedElement) Map(java.util.Map)

Aggregations

CtElement (spoon.reflect.declaration.CtElement)86 Test (org.junit.Test)39 Launcher (spoon.Launcher)23 Factory (spoon.reflect.factory.Factory)18 ArrayList (java.util.ArrayList)17 CtMethod (spoon.reflect.declaration.CtMethod)17 CtType (spoon.reflect.declaration.CtType)15 CtStatement (spoon.reflect.code.CtStatement)14 CtTypeReference (spoon.reflect.reference.CtTypeReference)14 List (java.util.List)12 CtClass (spoon.reflect.declaration.CtClass)12 CtField (spoon.reflect.declaration.CtField)12 CtIf (spoon.reflect.code.CtIf)11 CtInvocation (spoon.reflect.code.CtInvocation)11 TypeFilter (spoon.reflect.visitor.filter.TypeFilter)11 CtLocalVariable (spoon.reflect.code.CtLocalVariable)10 CtExecutableReference (spoon.reflect.reference.CtExecutableReference)9 CtScanner (spoon.reflect.visitor.CtScanner)9 NamedElementFilter (spoon.reflect.visitor.filter.NamedElementFilter)9 Collection (java.util.Collection)8