Search in sources :

Example 1 with CtFieldReference

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

the class FilterTest method testFieldAccessFilter.

@Test
public void testFieldAccessFilter() throws Exception {
    // also specifies VariableAccessFilter since FieldAccessFilter is only a VariableAccessFilter with additional static typing
    CtClass<?> foo = factory.Package().get("spoon.test.filters").getType("Foo");
    assertEquals("Foo", foo.getSimpleName());
    List<CtNamedElement> elements = foo.getElements(new NamedElementFilter<>(CtNamedElement.class, "i"));
    assertEquals(1, elements.size());
    CtFieldReference<?> ref = (CtFieldReference<?>) (elements.get(0)).getReference();
    List<CtFieldAccess<?>> expressions = foo.getElements(new FieldAccessFilter(ref));
    assertEquals(2, expressions.size());
    final Factory build = build(FieldAccessFilterTacos.class);
    final CtType<FieldAccessFilterTacos> fieldAccessFilterTacos = build.Type().get(FieldAccessFilterTacos.class);
    try {
        List<CtField> fields = fieldAccessFilterTacos.getElements(new TypeFilter<CtField>(CtField.class));
        for (CtField ctField : fields) {
            fieldAccessFilterTacos.getElements(new FieldAccessFilter(ctField.getReference()));
        }
    } catch (NullPointerException e) {
        fail("FieldAccessFilter must not throw a NPE.");
    }
}
Also used : CtFieldAccess(spoon.reflect.code.CtFieldAccess) CtFieldReference(spoon.reflect.reference.CtFieldReference) Factory(spoon.reflect.factory.Factory) FieldAccessFilterTacos(spoon.test.filters.testclasses.FieldAccessFilterTacos) CtField(spoon.reflect.declaration.CtField) CtNamedElement(spoon.reflect.declaration.CtNamedElement) FieldAccessFilter(spoon.reflect.visitor.filter.FieldAccessFilter) Test(org.junit.Test)

Example 2 with CtFieldReference

use of spoon.reflect.reference.CtFieldReference 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 3 with CtFieldReference

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

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

the class CtAnnotationImpl method convertValueToExpression.

private CtExpression convertValueToExpression(Object value) {
    CtExpression res;
    if (value.getClass().isArray()) {
        // Value should be converted to a CtNewArray.
        res = getFactory().Core().createNewArray();
        Object[] values = (Object[]) value;
        res.setType(getFactory().Type().createArrayReference(getFactory().Type().createReference(value.getClass().getComponentType())));
        for (Object o : values) {
            ((CtNewArray) res).addElement(convertValueToExpression(o));
        }
    } else if (value instanceof Collection) {
        // Value should be converted to a CtNewArray.
        res = getFactory().Core().createNewArray();
        Collection values = (Collection) value;
        res.setType(getFactory().Type().createArrayReference(getFactory().Type().createReference(values.toArray()[0].getClass())));
        for (Object o : values) {
            ((CtNewArray) res).addElement(convertValueToExpression(o));
        }
    } else if (value instanceof Class) {
        // Value should be a field access to a .class.
        res = getFactory().Code().createClassAccess(getFactory().Type().createReference((Class) value));
    } else if (value instanceof Field) {
        // Value should be a field access to a field.
        CtFieldReference<Object> variable = getFactory().Field().createReference((Field) value);
        variable.setStatic(true);
        CtTypeAccess target = getFactory().Code().createTypeAccess(getFactory().Type().createReference(((Field) value).getDeclaringClass()));
        CtFieldRead fieldRead = getFactory().Core().createFieldRead();
        fieldRead.setVariable(variable);
        fieldRead.setTarget(target);
        fieldRead.setType(target.getAccessedType());
        res = fieldRead;
    } else if (isPrimitive(value.getClass()) || value instanceof String) {
        // Value should be a literal.
        res = getFactory().Code().createLiteral(value);
    } else if (value.getClass().isEnum()) {
        final CtTypeReference declaringClass = getFactory().Type().createReference(((Enum) value).getDeclaringClass());
        final CtFieldReference variableRef = getFactory().Field().createReference(declaringClass, declaringClass, ((Enum) value).name());
        CtTypeAccess target = getFactory().Code().createTypeAccess(declaringClass);
        CtFieldRead fieldRead = getFactory().Core().createFieldRead();
        fieldRead.setVariable(variableRef);
        fieldRead.setTarget(target);
        fieldRead.setType(declaringClass);
        res = fieldRead;
    } else {
        throw new SpoonException("Please, submit a valid value.");
    }
    return res;
}
Also used : CtFieldRead(spoon.reflect.code.CtFieldRead) CtExpression(spoon.reflect.code.CtExpression) SpoonException(spoon.SpoonException) CtFieldReference(spoon.reflect.reference.CtFieldReference) CtNewArray(spoon.reflect.code.CtNewArray) CtField(spoon.reflect.declaration.CtField) MetamodelPropertyField(spoon.reflect.annotations.MetamodelPropertyField) Field(java.lang.reflect.Field) CtTypeReference(spoon.reflect.reference.CtTypeReference) Collection(java.util.Collection) CtTypeAccess(spoon.reflect.code.CtTypeAccess)

Example 5 with CtFieldReference

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

the class TypeReferenceTest method doNotCloseLoader.

@SuppressWarnings({ "rawtypes", "unchecked" })
@Test
public void doNotCloseLoader() throws Exception {
    /* Given the following scenario:
		 * 	- ClassA has a field of ClassB.
		 *	- ClassB has a field of ClassC.
		 * 	- Spoon only models ClassA.
		 *
		 * We want to get the field of ClassB, which should be accessible because
		 * the definitions of ClassB and ClassC were provided in the class path.
		 */
    SpoonModelBuilder comp = new Launcher().createCompiler();
    Factory factory = comp.getFactory();
    String qualifiedName = "spoontest.a.ClassA";
    String referenceQualifiedName = "spoontest.b.ClassB";
    // we only create the model for ClassA
    List<SpoonResource> fileToBeSpooned = SpoonResourceHelper.resources("./src/test/resources/reference-test-2/" + qualifiedName.replace('.', '/') + ".java");
    comp.addInputSources(fileToBeSpooned);
    // for ClassA
    assertEquals(1, fileToBeSpooned.size());
    // Spoon requires the binary version of dependencies
    List<SpoonResource> classpath = SpoonResourceHelper.resources("./src/test/resources/reference-test-2/ReferenceTest2.jar");
    String[] dependencyClasspath = new String[] { classpath.get(0).getPath() };
    factory.getEnvironment().setSourceClasspath(dependencyClasspath);
    assertEquals(1, classpath.size());
    // now we can build the model
    comp.build();
    // we can get the model of ClassA
    CtType<?> theClass = factory.Type().get(qualifiedName);
    // we get ClassA's field of type ClassB
    List<CtField<?>> fields = theClass.getFields();
    assertEquals(1, fields.size());
    CtField<?> bField = fields.get(0);
    CtTypeReference referencedType = bField.getType();
    assertEquals(referenceQualifiedName, referencedType.getQualifiedName());
    // we get ClassB's field of type ClassC
    Collection<CtFieldReference<?>> fieldsOfB = referencedType.getAllFields();
    if (fieldsOfB.size() == 2) {
        // Jacoco instruments all dependencies with an agent.
        // So, when we use reflection on ClassB, we don't have one field but two fields.
        // First, it is the field of ClassB. Second, it is the field of Jacoco.
        final CtFieldReference<?> potentialJacoco = (CtFieldReference<?>) fieldsOfB.toArray()[1];
        if ("$jacocoData".equals(potentialJacoco.getSimpleName())) {
            fieldsOfB.remove(potentialJacoco);
        }
    }
    assertEquals(1, fieldsOfB.size());
    CtFieldReference<?> cField = fieldsOfB.iterator().next();
    assertEquals("spoontest.c.ClassC", cField.getType().getQualifiedName());
}
Also used : SpoonModelBuilder(spoon.SpoonModelBuilder) ModelUtils.createFactory(spoon.testing.utils.ModelUtils.createFactory) Factory(spoon.reflect.factory.Factory) CtFieldReference(spoon.reflect.reference.CtFieldReference) CtField(spoon.reflect.declaration.CtField) CtTypeReference(spoon.reflect.reference.CtTypeReference) Launcher(spoon.Launcher) SpoonResource(spoon.compiler.SpoonResource) Test(org.junit.Test)

Aggregations

CtFieldReference (spoon.reflect.reference.CtFieldReference)18 Test (org.junit.Test)9 CtTypeReference (spoon.reflect.reference.CtTypeReference)6 Launcher (spoon.Launcher)5 CtField (spoon.reflect.declaration.CtField)5 CtFieldAccess (spoon.reflect.code.CtFieldAccess)4 CtClass (spoon.reflect.declaration.CtClass)4 CtElement (spoon.reflect.declaration.CtElement)4 CtMethod (spoon.reflect.declaration.CtMethod)4 CtExecutableReference (spoon.reflect.reference.CtExecutableReference)4 CtInvocation (spoon.reflect.code.CtInvocation)3 CtImport (spoon.reflect.declaration.CtImport)3 ParentNotInitializedException (spoon.reflect.declaration.ParentNotInitializedException)3 Factory (spoon.reflect.factory.Factory)3 Field (java.lang.reflect.Field)2 ArrayList (java.util.ArrayList)2 Collection (java.util.Collection)2 HashSet (java.util.HashSet)2 SpoonException (spoon.SpoonException)2 MetamodelPropertyField (spoon.reflect.annotations.MetamodelPropertyField)2