Search in sources :

Example 1 with CtExecutableReference

use of spoon.reflect.reference.CtExecutableReference in project spoon by INRIA.

the class ReferenceBuilder method getExecutableReference.

@SuppressWarnings("unchecked")
<T> CtExecutableReference<T> getExecutableReference(MethodBinding exec) {
    if (exec == null) {
        return null;
    }
    final CtExecutableReference ref = this.jdtTreeBuilder.getFactory().Core().createExecutableReference();
    if (exec.isConstructor()) {
        ref.setSimpleName(CtExecutableReference.CONSTRUCTOR_NAME);
        ref.setType(getTypeReference(exec.declaringClass));
    } else {
        ref.setSimpleName(new String(exec.selector));
        ref.setType(getTypeReference(exec.returnType));
    }
    if (exec instanceof ProblemMethodBinding) {
        if (exec.declaringClass != null && Arrays.asList(exec.declaringClass.methods()).contains(exec)) {
            ref.setDeclaringType(getTypeReference(exec.declaringClass));
        } else {
            final CtReference declaringType = getDeclaringReferenceFromImports(exec.constantPoolName());
            if (declaringType instanceof CtTypeReference) {
                ref.setDeclaringType((CtTypeReference<?>) declaringType);
            }
        }
        if (exec.isConstructor()) {
            // super() invocation have a good declaring class.
            ref.setDeclaringType(getTypeReference(exec.declaringClass));
        }
        ref.setStatic(true);
    } else {
        ref.setDeclaringType(getTypeReference(exec.declaringClass));
        ref.setStatic(exec.isStatic());
    }
    if (exec.declaringClass instanceof ParameterizedTypeBinding) {
        ref.setDeclaringType(getTypeReference(exec.declaringClass.actualType()));
    }
    // original() method returns a result not null when the current method is generic.
    if (exec.original() != null) {
        final List<CtTypeReference<?>> parameters = new ArrayList<>(exec.original().parameters.length);
        for (TypeBinding b : exec.original().parameters) {
            parameters.add(getTypeReference(b));
        }
        ref.setParameters(parameters);
    } else if (exec.parameters != null) {
        // This is a method without a generic argument.
        final List<CtTypeReference<?>> parameters = new ArrayList<>();
        for (TypeBinding b : exec.parameters) {
            parameters.add(getTypeReference(b));
        }
        ref.setParameters(parameters);
    }
    return ref;
}
Also used : ParameterizedTypeBinding(org.eclipse.jdt.internal.compiler.lookup.ParameterizedTypeBinding) ProblemMethodBinding(org.eclipse.jdt.internal.compiler.lookup.ProblemMethodBinding) CtReference(spoon.reflect.reference.CtReference) CtTypeReference(spoon.reflect.reference.CtTypeReference) BinaryTypeBinding(org.eclipse.jdt.internal.compiler.lookup.BinaryTypeBinding) ParameterizedTypeBinding(org.eclipse.jdt.internal.compiler.lookup.ParameterizedTypeBinding) TypeBinding(org.eclipse.jdt.internal.compiler.lookup.TypeBinding) MissingTypeBinding(org.eclipse.jdt.internal.compiler.lookup.MissingTypeBinding) SourceTypeBinding(org.eclipse.jdt.internal.compiler.lookup.SourceTypeBinding) JDTTreeBuilderQuery.searchTypeBinding(spoon.support.compiler.jdt.JDTTreeBuilderQuery.searchTypeBinding) PolyTypeBinding(org.eclipse.jdt.internal.compiler.lookup.PolyTypeBinding) LocalTypeBinding(org.eclipse.jdt.internal.compiler.lookup.LocalTypeBinding) BaseTypeBinding(org.eclipse.jdt.internal.compiler.lookup.BaseTypeBinding) RawTypeBinding(org.eclipse.jdt.internal.compiler.lookup.RawTypeBinding) ArrayList(java.util.ArrayList) CtExecutableReference(spoon.reflect.reference.CtExecutableReference) List(java.util.List) ArrayList(java.util.ArrayList)

Example 2 with CtExecutableReference

use of spoon.reflect.reference.CtExecutableReference in project spoon by INRIA.

the class SignatureTest method testArgumentNotNullForExecutableReference.

@Test
public void testArgumentNotNullForExecutableReference() throws Exception {
    final Launcher launcher = new Launcher();
    launcher.setArgs(new String[] { "--output-type", "nooutput" });
    launcher.addInputResource("./src/test/resources/variable/PropPanelUseCase_1.40.java");
    launcher.getEnvironment().setNoClasspath(true);
    launcher.run();
    final List<CtExecutableReference> references = Query.getElements(launcher.getFactory(), new ReferenceTypeFilter<CtExecutableReference>(CtExecutableReference.class) {

        @Override
        public boolean matches(CtExecutableReference reference) {
            return "addField".equals(reference.getSimpleName()) && super.matches(reference);
        }
    });
    assertEquals("addField(<unknown>,<unknown>)", references.get(0).getSignature());
    assertEquals("addField(<unknown>,org.argouml.uml.ui.UMLComboBoxNavigator)", references.get(1).getSignature());
    for (CtExecutableReference reference : references) {
        assertNotEquals("addField(null,null)", reference.getSignature());
    }
}
Also used : Launcher(spoon.Launcher) CtExecutableReference(spoon.reflect.reference.CtExecutableReference) Test(org.junit.Test)

Example 3 with CtExecutableReference

use of spoon.reflect.reference.CtExecutableReference 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 4 with CtExecutableReference

use of spoon.reflect.reference.CtExecutableReference 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 5 with CtExecutableReference

use of spoon.reflect.reference.CtExecutableReference in project spoon by INRIA.

the class CloneTest method testCopyMethod.

@Test
public void testCopyMethod() throws Exception {
    // contract: the copied method is well-formed, lookup of executable references is preserved after copying, esp for recursive methods
    Launcher l = new Launcher();
    l.getEnvironment().setNoClasspath(true);
    l.addInputResource("./src/test/resources/noclasspath/A2.java");
    l.buildModel();
    CtClass<Object> klass = l.getFactory().Class().get("A2");
    CtMethod<?> method = klass.getMethodsByName("c").get(0);
    List<CtExecutableReference> elements = method.getElements(new TypeFilter<>(CtExecutableReference.class));
    CtExecutableReference methodRef = elements.get(0);
    // the lookup is OK in the original node
    assertSame(method, methodRef.getDeclaration());
    assertEquals("A2", methodRef.getDeclaringType().toString());
    // we copy the method
    CtMethod<?> methodClone = method.copyMethod();
    assertEquals("cCopy", methodClone.getSimpleName());
    // useful for debug
    methodClone.getBody().insertBegin(l.getFactory().createCodeSnippetStatement("// debug info"));
    CtExecutableReference reference = methodClone.getElements(new TypeFilter<>(CtExecutableReference.class)).get(0);
    // all references have been updated
    assertEquals("cCopy", reference.getSimpleName());
    assertSame(methodClone, reference.getDeclaration());
    assertEquals("A2", methodClone.getDeclaringType().getQualifiedName());
    // now we may want to rename the copied method
    Refactoring.changeMethodName(methodClone, "foo");
    // the method has been changed
    assertEquals("foo", methodClone.getSimpleName());
    // the reference has been changed
    assertEquals("foo", reference.getSimpleName());
    // the lookup still works
    assertSame(methodClone, reference.getDeclaration());
    assertEquals("A2", methodClone.getDeclaringType().getQualifiedName());
    // one can even copy the method several times
    methodClone = Refactoring.copyMethod(method);
    assertEquals("cCopy", methodClone.getSimpleName());
    methodClone = Refactoring.copyMethod(method);
    assertEquals("cCopyX", methodClone.getSimpleName());
}
Also used : Launcher(spoon.Launcher) CtExecutableReference(spoon.reflect.reference.CtExecutableReference) TypeFilter(spoon.reflect.visitor.filter.TypeFilter) Test(org.junit.Test)

Aggregations

CtExecutableReference (spoon.reflect.reference.CtExecutableReference)27 Test (org.junit.Test)13 CtInvocation (spoon.reflect.code.CtInvocation)9 CtTypeReference (spoon.reflect.reference.CtTypeReference)9 Factory (spoon.reflect.factory.Factory)8 Launcher (spoon.Launcher)7 CtMethod (spoon.reflect.declaration.CtMethod)7 ArrayList (java.util.ArrayList)5 CtElement (spoon.reflect.declaration.CtElement)5 CtExecutable (spoon.reflect.declaration.CtExecutable)5 CtExpression (spoon.reflect.code.CtExpression)4 CtFieldReference (spoon.reflect.reference.CtFieldReference)4 List (java.util.List)3 CtType (spoon.reflect.declaration.CtType)3 CtReference (spoon.reflect.reference.CtReference)3 TypeFilter (spoon.reflect.visitor.filter.TypeFilter)3 HashSet (java.util.HashSet)2 CtFieldAccess (spoon.reflect.code.CtFieldAccess)2 CtLiteral (spoon.reflect.code.CtLiteral)2 CtStatement (spoon.reflect.code.CtStatement)2