Search in sources :

Example 16 with CtElement

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

the class ImportScannerImpl method isTypeInCollision.

/**
 * Test if the reference can be imported, i.e. test if the importation could lead to a collision.
 * @param ref
 * @return true if the ref should be imported.
 */
protected boolean isTypeInCollision(CtReference ref, boolean fqnMode) {
    if (targetType != null && targetType.getSimpleName().equals(ref.getSimpleName()) && !targetType.equals(ref)) {
        return true;
    }
    try {
        CtElement parent;
        if (ref instanceof CtTypeReference) {
            parent = ref.getParent();
        } else {
            parent = ref;
        }
        // i.e. a string, an int, etc.
        if (parent instanceof CtLiteral) {
            return false;
        }
        Set<String> localVariablesOfBlock = new HashSet<>();
        if (parent instanceof CtField) {
            this.fieldAndMethodsNames.add(((CtField) parent).getSimpleName());
        } else if (parent instanceof CtMethod) {
            this.fieldAndMethodsNames.add(((CtMethod) parent).getSimpleName());
        } else {
            localVariablesOfBlock = this.lookForLocalVariables(parent);
        }
        while (!(parent instanceof CtPackage)) {
            if ((parent instanceof CtFieldReference) || (parent instanceof CtExecutableReference) || (parent instanceof CtInvocation)) {
                CtReference parentType;
                if (parent instanceof CtInvocation) {
                    parentType = ((CtInvocation) parent).getExecutable();
                } else {
                    parentType = (CtReference) parent;
                }
                LinkedList<String> qualifiedNameTokens = new LinkedList<>();
                // we don't want to test the current ref name, as we risk to create field import and make autoreference
                if (parentType != parent) {
                    qualifiedNameTokens.add(parentType.getSimpleName());
                }
                CtTypeReference typeReference;
                if (parent instanceof CtFieldReference) {
                    typeReference = ((CtFieldReference) parent).getDeclaringType();
                } else if (parent instanceof CtExecutableReference) {
                    typeReference = ((CtExecutableReference) parent).getDeclaringType();
                } else {
                    typeReference = ((CtInvocation) parent).getExecutable().getDeclaringType();
                }
                if (typeReference != null) {
                    qualifiedNameTokens.addFirst(typeReference.getSimpleName());
                    if (typeReference.getPackage() != null) {
                        StringTokenizer token = new StringTokenizer(typeReference.getPackage().getSimpleName(), CtPackage.PACKAGE_SEPARATOR);
                        int index = 0;
                        while (token.hasMoreElements()) {
                            qualifiedNameTokens.add(index, token.nextToken());
                            index++;
                        }
                    }
                }
                if (!qualifiedNameTokens.isEmpty()) {
                    // if the first package name is a variable name somewhere, it could lead to a collision
                    if (fieldAndMethodsNames.contains(qualifiedNameTokens.getFirst()) || localVariablesOfBlock.contains(qualifiedNameTokens.getFirst())) {
                        qualifiedNameTokens.removeFirst();
                        if (fqnMode) {
                            // for example: spoon.Launcher if a field spoon and another one Launcher exists
                            if (ref instanceof CtTypeReference) {
                                if (qualifiedNameTokens.isEmpty()) {
                                    return true;
                                }
                                // but if the other package names are not a variable name, it's ok to import
                                for (int i = 0; i < qualifiedNameTokens.size(); i++) {
                                    String testedToken = qualifiedNameTokens.get(i);
                                    if (!fieldAndMethodsNames.contains(testedToken) && !localVariablesOfBlock.contains(testedToken)) {
                                        return true;
                                    }
                                }
                                return false;
                            // However if it is a static method/field, we always accept to import them in this case
                            // It is the last possibility for managing import for us
                            } else {
                                return true;
                            }
                        } else {
                            // but if the other package names are not a variable name, it's ok to import
                            for (int i = 0; i < qualifiedNameTokens.size(); i++) {
                                String testedToken = qualifiedNameTokens.get(i);
                                if (!fieldAndMethodsNames.contains(testedToken) && !localVariablesOfBlock.contains(testedToken)) {
                                    return false;
                                }
                            }
                            return true;
                        }
                    }
                }
            }
            parent = parent.getParent();
        }
    } catch (ParentNotInitializedException e) {
        return false;
    }
    return false;
}
Also used : ParentNotInitializedException(spoon.reflect.declaration.ParentNotInitializedException) CtElement(spoon.reflect.declaration.CtElement) CtFieldReference(spoon.reflect.reference.CtFieldReference) LinkedList(java.util.LinkedList) CtInvocation(spoon.reflect.code.CtInvocation) StringTokenizer(java.util.StringTokenizer) CtLiteral(spoon.reflect.code.CtLiteral) CtReference(spoon.reflect.reference.CtReference) CtTypeReference(spoon.reflect.reference.CtTypeReference) CtField(spoon.reflect.declaration.CtField) CtExecutableReference(spoon.reflect.reference.CtExecutableReference) CtPackage(spoon.reflect.declaration.CtPackage) CtMethod(spoon.reflect.declaration.CtMethod) HashSet(java.util.HashSet)

Example 17 with CtElement

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

the class ImportScannerImpl method addClassImport.

/**
 * Adds a type to the classImports.
 */
protected boolean addClassImport(CtTypeReference<?> ref) {
    this.exploredReferences.add(ref);
    if (ref == null) {
        return false;
    }
    if (targetType != null && targetType.getSimpleName().equals(ref.getSimpleName()) && !targetType.equals(ref)) {
        return false;
    }
    if (classImports.containsKey(ref.getSimpleName())) {
        return isImportedInClassImports(ref);
    }
    // don't import unnamed package elements
    if (ref.getPackage() == null || ref.getPackage().isUnnamedPackage()) {
        return false;
    }
    if (targetType != null && targetType.canAccess(ref) == false) {
        // ref type is not visible in targetType we must not add import for it, java compiler would fail on that.
        return false;
    }
    if (this.isThereAnotherClassWithSameNameInAnotherPackage(ref)) {
        return false;
    }
    if (targetType != null) {
        try {
            CtElement parent = ref.getParent();
            if (parent != null) {
                parent = parent.getParent();
                if (parent != null) {
                    if ((parent instanceof CtFieldAccess) || (parent instanceof CtExecutable) || (parent instanceof CtInvocation)) {
                        CtTypeReference declaringType;
                        CtReference reference;
                        CtPackageReference pack = targetType.getPackage();
                        if (parent instanceof CtFieldAccess) {
                            CtFieldAccess field = (CtFieldAccess) parent;
                            CtFieldReference localReference = field.getVariable();
                            declaringType = localReference.getDeclaringType();
                            reference = localReference;
                        } else if (parent instanceof CtExecutable) {
                            CtExecutable exec = (CtExecutable) parent;
                            CtExecutableReference localReference = exec.getReference();
                            declaringType = localReference.getDeclaringType();
                            reference = localReference;
                        } else if (parent instanceof CtInvocation) {
                            CtInvocation invo = (CtInvocation) parent;
                            CtExecutableReference localReference = invo.getExecutable();
                            declaringType = localReference.getDeclaringType();
                            reference = localReference;
                        } else {
                            declaringType = null;
                            reference = null;
                        }
                        if (reference != null && isImported(reference)) {
                            // if we are in the **same** package we do the import for test with method isImported
                            if (declaringType != null) {
                                if (declaringType.getPackage() != null && !declaringType.getPackage().isUnnamedPackage()) {
                                    // ignore java.lang package
                                    if (!declaringType.getPackage().getSimpleName().equals("java.lang")) {
                                        // ignore type in same package
                                        if (declaringType.getPackage().getSimpleName().equals(pack.getSimpleName())) {
                                            classImports.put(ref.getSimpleName(), ref);
                                            return true;
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
        } catch (ParentNotInitializedException e) {
        }
        CtPackageReference pack = targetType.getPackage();
        if (pack != null && ref.getPackage() != null && !ref.getPackage().isUnnamedPackage()) {
            // ignore java.lang package
            if (!ref.getPackage().getSimpleName().equals("java.lang")) {
                // ignore type in same package
                if (ref.getPackage().getSimpleName().equals(pack.getSimpleName())) {
                    return false;
                }
            }
        }
    }
    classImports.put(ref.getSimpleName(), ref);
    return true;
}
Also used : CtFieldAccess(spoon.reflect.code.CtFieldAccess) CtInvocation(spoon.reflect.code.CtInvocation) ParentNotInitializedException(spoon.reflect.declaration.ParentNotInitializedException) CtPackageReference(spoon.reflect.reference.CtPackageReference) CtReference(spoon.reflect.reference.CtReference) CtElement(spoon.reflect.declaration.CtElement) CtTypeReference(spoon.reflect.reference.CtTypeReference) CtFieldReference(spoon.reflect.reference.CtFieldReference) CtExecutableReference(spoon.reflect.reference.CtExecutableReference) CtExecutable(spoon.reflect.declaration.CtExecutable)

Example 18 with CtElement

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

the class ParentFunction method apply.

@Override
public void apply(CtElement input, CtConsumer<Object> outputConsumer) {
    if (input == null) {
        return;
    }
    if (includingSelf) {
        outputConsumer.accept(input);
    }
    CtElement parent = input;
    CtModule topLevel = input.getFactory().getModel().getUnnamedModule();
    while (parent != null && parent != topLevel && query.isTerminated() == false && parent.isParentInitialized()) {
        parent = parent.getParent();
        outputConsumer.accept(parent);
    }
}
Also used : CtElement(spoon.reflect.declaration.CtElement) CtModule(spoon.reflect.declaration.CtModule)

Example 19 with CtElement

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

the class PotentialVariableDeclarationFunction method apply.

@Override
public void apply(CtElement input, CtConsumer<Object> outputConsumer) {
    isTypeOnTheWay = false;
    isInStaticScope = false;
    // Search previous siblings for element which may represents the declaration of this local variable
    CtQuery siblingsQuery = input.getFactory().createQuery().map(new SiblingsFunction().mode(SiblingsFunction.Mode.PREVIOUS)).select(new TypeFilter<>(CtVariable.class));
    if (variableName != null) {
        // variable name is defined so we have to search only for variables with that name
        siblingsQuery = siblingsQuery.select(new NamedElementFilter<>(CtNamedElement.class, variableName));
    }
    CtElement scopeElement = input;
    // Search input and then all parents until first CtPackage for element which may represents the declaration of this local variable
    while (scopeElement != null && !(scopeElement instanceof CtPackage) && scopeElement.isParentInitialized()) {
        CtElement parent = scopeElement.getParent();
        if (parent instanceof CtType<?>) {
            isTypeOnTheWay = true;
            // visit each CtField of `parent` CtType
            CtQuery q = parent.map(new AllTypeMembersFunction(CtField.class));
            q.forEach((CtField<?> field) -> {
                if (isInStaticScope && field.hasModifier(ModifierKind.STATIC) == false) {
                    /*
						 * the variable reference is used in static scope,
						 * but the field is not static - ignore it
						 */
                    return;
                }
                // else send field as potential variable declaration
                if (sendToOutput(field, outputConsumer)) {
                    // and terminate the internal query q if outer query is already terminated
                    q.terminate();
                }
            });
            if (query.isTerminated()) {
                return;
            }
        } else if (parent instanceof CtBodyHolder || parent instanceof CtStatementList) {
            // visit all previous CtVariable siblings of scopeElement element in parent BodyHolder or Statement list
            siblingsQuery.setInput(scopeElement).forEach(outputConsumer);
            if (query.isTerminated()) {
                return;
            }
            // visit parameters of CtCatch and CtExecutable (method, lambda)
            if (parent instanceof CtCatch) {
                CtCatch ctCatch = (CtCatch) parent;
                if (sendToOutput(ctCatch.getParameter(), outputConsumer)) {
                    return;
                }
            } else if (parent instanceof CtExecutable) {
                CtExecutable<?> exec = (CtExecutable<?>) parent;
                for (CtParameter<?> param : exec.getParameters()) {
                    if (sendToOutput(param, outputConsumer)) {
                        return;
                    }
                }
            }
        }
        if (parent instanceof CtModifiable) {
            isInStaticScope = isInStaticScope || ((CtModifiable) parent).hasModifier(ModifierKind.STATIC);
        }
        scopeElement = parent;
    }
}
Also used : CtElement(spoon.reflect.declaration.CtElement) CtQuery(spoon.reflect.visitor.chain.CtQuery) CtExecutable(spoon.reflect.declaration.CtExecutable) CtBodyHolder(spoon.reflect.code.CtBodyHolder) CtType(spoon.reflect.declaration.CtType) CtField(spoon.reflect.declaration.CtField) CtVariable(spoon.reflect.declaration.CtVariable) CtPackage(spoon.reflect.declaration.CtPackage) CtStatementList(spoon.reflect.code.CtStatementList) CtCatch(spoon.reflect.code.CtCatch) CtModifiable(spoon.reflect.declaration.CtModifiable)

Example 20 with CtElement

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

the class CtRolePathElement method getElements.

@Override
public Collection<CtElement> getElements(Collection<CtElement> roots) {
    Collection<CtElement> matchs = new LinkedList<>();
    for (CtElement root : roots) {
        RoleHandler roleHandler = RoleHandlerHelper.getOptionalRoleHandler(root.getClass(), getRole());
        if (roleHandler != null) {
            switch(roleHandler.getContainerKind()) {
                case SINGLE:
                    if (roleHandler.getValue(root) != null) {
                        matchs.add(roleHandler.getValue(root));
                    }
                    break;
                case LIST:
                    if (getArguments().containsKey("index")) {
                        int index = Integer.parseInt(getArguments().get("index"));
                        if (index < roleHandler.asList(root).size()) {
                            matchs.add((CtElement) roleHandler.asList(root).get(index));
                        }
                    } else {
                        matchs.addAll(roleHandler.asList(root));
                    }
                    break;
                case SET:
                    if (getArguments().containsKey("name")) {
                        String name = getArguments().get("name");
                        try {
                            CtElement match = getFromSet(roleHandler.asSet(root), name);
                            if (match != null) {
                                matchs.add(match);
                            }
                        } catch (CtPathException e) {
                        // System.err.println("[ERROR] Element not found for name: " + name);
                        // No element found for name.
                        }
                    } else {
                        matchs.addAll(roleHandler.asSet(root));
                    }
                    break;
                case MAP:
                    if (getArguments().containsKey("key")) {
                        String name = getArguments().get("key");
                        if (roleHandler.asMap(root).containsKey(name)) {
                            matchs.add((CtElement) roleHandler.asMap(root).get(name));
                        }
                    } else {
                        Map<String, CtElement> map = roleHandler.asMap(root);
                        matchs.addAll(map.values());
                    }
                    break;
            }
        }
    }
    return matchs;
}
Also used : CtElement(spoon.reflect.declaration.CtElement) RoleHandler(spoon.reflect.meta.RoleHandler) LinkedList(java.util.LinkedList) CtPathException(spoon.reflect.path.CtPathException)

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