Search in sources :

Example 6 with CtRole

use of spoon.reflect.path.CtRole in project spoon by INRIA.

the class SpoonMetaModel method addFieldsOfType.

/**
 * adds all {@link MetamodelProperty}s of `ctType`
 * @param mmConcept the owner of to be created fields
 * @param ctType to be scanned {@link CtType}
 */
private void addFieldsOfType(MetamodelConcept mmConcept, CtType<?> ctType) {
    ctType.getTypeMembers().forEach(typeMember -> {
        if (typeMember instanceof CtMethod<?>) {
            CtMethod<?> method = (CtMethod<?>) typeMember;
            CtRole role = getRoleOfMethod(method);
            if (role != null) {
                MetamodelProperty field = mmConcept.getOrCreateMMField(role);
                field.addMethod(method);
            } else {
                mmConcept.otherMethods.add(method);
            }
        }
    });
    addFieldsOfSuperType(mmConcept, ctType.getSuperclass());
    ctType.getSuperInterfaces().forEach(superIfaceRef -> addFieldsOfSuperType(mmConcept, superIfaceRef));
}
Also used : CtRole(spoon.reflect.path.CtRole) CtMethod(spoon.reflect.declaration.CtMethod)

Example 7 with CtRole

use of spoon.reflect.path.CtRole in project spoon by INRIA.

the class ReplaceParametrizedTest method testContract.

@Test
public void testContract() throws Throwable {
    List<String> problems = new ArrayList<>();
    // contract: all elements are replaceable wherever they are in the model
    // this test puts them at all possible locations
    CtType<?> toTest = typeToTest.getModelInterface();
    CtElement o = factory.Core().create((Class<? extends CtElement>) toTest.getActualClass());
    for (MetamodelProperty mmField : typeToTest.getRoleToProperty().values()) {
        Class<?> argType = mmField.getItemValueType().getActualClass();
        if (!CtElement.class.isAssignableFrom(argType)) {
            continue;
        }
        CtTypeReference<?> itemType = mmField.getItemValueType();
        // special cases...
        if (itemType.getQualifiedName().equals(CtStatement.class.getName())) {
            // the children of CtLoop wraps CtStatement into an implicit CtBlock. So make a block directly to test plain get/set and not wrapping.
            itemType = factory.createCtTypeReference(CtBlock.class);
        }
        if (o.getClass().getSimpleName().equals("CtAnnotationFieldAccessImpl") && mmField.getRole() == CtRole.VARIABLE) {
            itemType = factory.createCtTypeReference(CtFieldReference.class);
        } else if (CtFieldAccess.class.isAssignableFrom(o.getClass()) && mmField.getRole() == CtRole.VARIABLE) {
            itemType = factory.createCtTypeReference(CtFieldReference.class);
        }
        CtElement argument = (CtElement) createCompatibleObject(itemType);
        assertNotNull(argument);
        // we create a fresh object
        CtElement receiver = ((CtElement) o).clone();
        RoleHandler rh = RoleHandlerHelper.getRoleHandler(o.getClass(), mmField.getRole());
        if (mmField.isUnsettable()) {
            try {
                // we invoke the setter
                invokeSetter(rh, receiver, argument);
            } catch (SpoonException e) {
                // ok this unsettable property has no setter at all
                return;
            }
            // this unsettable property has setter, but it should do nothing
            CtRole argumentsRoleInParent = argument.getRoleInParent();
            if (argumentsRoleInParent == null) {
                // OK - unsettable property set no value
                continue;
            }
            if (argumentsRoleInParent == mmField.getRole()) {
                problems.add("UnsettableProperty " + mmField + " sets the value");
            } else {
                if (mmField.isDerived()) {
                // it is OK, that setting of value into derived unsettable field influences other field
                // Example 1: CtCatchVariable.setType(x) influences result of getMultitype()
                // Example 2: CtEnumValue.setAssignment(x) influences result of getDefaultExpression()
                } else {
                    problems.add("UnsettableProperty " + mmField + " sets the value into different role " + argumentsRoleInParent);
                }
            }
            continue;
        }
        // we invoke the setter
        invokeSetter(rh, receiver, argument);
        // contract: a property setter sets properties that are visitable by a scanner
        CtElement finalArgument = argument;
        class Scanner extends CtScanner {

            boolean found = false;

            @Override
            public void scan(CtRole role, CtElement e) {
                super.scan(role, e);
                if (e == finalArgument) {
                    if (rh.getRole() == role || rh.getRole().getSuperRole() == role) {
                        found = true;
                        return;
                    }
                    // if (rh.getRole()==CtRole.TYPE && role==CtRole.MULTI_TYPE) {
                    // //CtCatchVaraible#type sets CtCatchVaraible#multiType - OK
                    // found = true;
                    // return;
                    // }
                    problems.add("Argument was set into " + rh.getRole() + " but was found in " + role);
                }
            }
        }
        ;
        Scanner s = new Scanner();
        receiver.accept(s);
        assertTrue("Settable field " + mmField.toString() + " should set value.\n" + getReport(problems), s.found);
        // contract: a property getter on the same role can be used to get the value back
        assertSame(argument, invokeGetter(rh, receiver));
        final CtElement argument2 = argument.clone();
        assertNotSame(argument, argument2);
        // we do the replace
        argument.replace(argument2);
        // the new element is indeed now in this AST
        assertTrue(receiver.getClass().getSimpleName() + " failed for " + mmField, receiver.getElements(new Filter<CtElement>() {

            @Override
            public boolean matches(CtElement element) {
                return element == argument2;
            }
        }).size() == 1);
    }
    if (problems.size() > 0) {
        fail(getReport(problems));
    }
}
Also used : CtScanner(spoon.reflect.visitor.CtScanner) SpoonException(spoon.SpoonException) CtElement(spoon.reflect.declaration.CtElement) RoleHandler(spoon.reflect.meta.RoleHandler) ArrayList(java.util.ArrayList) CtFieldReference(spoon.reflect.reference.CtFieldReference) CtBlock(spoon.reflect.code.CtBlock) CtStatement(spoon.reflect.code.CtStatement) Filter(spoon.reflect.visitor.Filter) MetamodelProperty(spoon.test.metamodel.MetamodelProperty) CtRole(spoon.reflect.path.CtRole) CtScanner(spoon.reflect.visitor.CtScanner) Test(org.junit.Test)

Example 8 with CtRole

use of spoon.reflect.path.CtRole in project spoon by INRIA.

the class TestCtRole method testGetCtRoleByName.

@Test
public void testGetCtRoleByName() {
    // contract: one should be able to get CtRole based on its name (without '_' whatever the case is, or with '_' in uppercase)
    // exactly the same name: OK
    String name = "DECLARING_TYPE";
    assertEquals(CtRole.DECLARING_TYPE, CtRole.fromName(name));
    // camel case: OK
    name = "declaringType";
    assertEquals(CtRole.DECLARING_TYPE, CtRole.fromName(name));
    // lower case: OK
    name = "declaringtype";
    assertEquals(CtRole.DECLARING_TYPE, CtRole.fromName(name));
    // lower case with underscore: not accepted
    name = "declaring_type";
    assertNull(CtRole.fromName(name));
    for (CtRole role : CtRole.values()) {
        assertEquals(role, CtRole.fromName(role.name().replaceAll("_", "").toLowerCase()));
    }
}
Also used : CtRole(spoon.reflect.path.CtRole) Test(org.junit.Test)

Example 9 with CtRole

use of spoon.reflect.path.CtRole in project spoon by INRIA.

the class TestCtRole method testCtRoleSubRoleMatchesWithSuperRole.

@Test
public void testCtRoleSubRoleMatchesWithSuperRole() {
    // contract: CtRole#getSubRoles() and CtRole#getSuperRole() are empty or links to each other
    int countOfSubRoles = 0;
    for (CtRole role : CtRole.values()) {
        for (CtRole subRole : role.getSubRoles()) {
            countOfSubRoles++;
            assertSame(role, subRole.getSuperRole());
        }
        if (role.getSuperRole() != null) {
            assertTrue(role.getSuperRole().getSubRoles().contains(role));
        }
    }
    assertTrue(countOfSubRoles > 0);
}
Also used : CtRole(spoon.reflect.path.CtRole) Test(org.junit.Test)

Example 10 with CtRole

use of spoon.reflect.path.CtRole in project spoon by INRIA.

the class MetaModelTest method spoonMetaModelTest.

/*
	 * this test reports all spoon model elements which are not yet handled by meta model
	 * actually this is the result
	 */
@Test
public void spoonMetaModelTest() {
    SpoonMetaModel mm = new SpoonMetaModel(new File("./src/main/java"));
    List<String> problems = new ArrayList<>();
    // detect unused CtRoles
    Set<CtRole> unhandledRoles = new HashSet<>(Arrays.asList(CtRole.values()));
    mm.getConcepts().forEach(mmConcept -> {
        mmConcept.getRoleToProperty().forEach((role, mmField) -> {
            if (mmField.isUnsettable()) {
                // contract: all unsettable fields are derived too
                assertTrue("Unsettable field " + mmField + " must be derived too", mmField.isDerived());
            }
            unhandledRoles.remove(role);
            if (mmField.getMethod(MMMethodKind.GET) == null) {
                problems.add("Missing getter for " + mmField.getOwnerConcept().getName() + " and CtRole." + mmField.getRole());
            }
            if (mmField.getMethod(MMMethodKind.SET) == null) {
                if (mmConcept.getTypeContext().isSubtypeOf(mm.getFactory().Type().createReference(CtReference.class)) == false && mmConcept.getName().equals("CtTypeInformation") == false) {
                    // only NON references needs a setter
                    problems.add("Missing setter for " + mmField.getOwnerConcept().getName() + " and CtRole." + mmField.getRole());
                }
            }
            // contract: type of field value is never implicit
            assertFalse("Value type of Field " + mmField.toString() + " is implicit", mmField.getValueType().isImplicit());
            assertFalse("Item value type of Field " + mmField.toString() + " is implicit", mmField.getItemValueType().isImplicit());
            mmField.forEachUnhandledMethod(ctMethod -> problems.add("Unhandled method signature: " + ctMethod.getDeclaringType().getSimpleName() + "#" + ctMethod.getSignature()));
        });
    });
    unhandledRoles.forEach(it -> problems.add("Unused CtRole." + it.name()));
/*
		 * This assertion prints all the methods which are not covered by current implementation of SpoonMetaModel.
		 * It is not a bug. It is useful to see how much is SpoonMetaModel covering real Spoon model.
		 */
// assertTrue(String.join("\n", problems), problems.isEmpty());
}
Also used : SpoonMetaModel(spoon.test.metamodel.SpoonMetaModel) CtReference(spoon.reflect.reference.CtReference) ArrayList(java.util.ArrayList) CtRole(spoon.reflect.path.CtRole) File(java.io.File) HashSet(java.util.HashSet) Test(org.junit.Test)

Aggregations

CtRole (spoon.reflect.path.CtRole)15 ArrayList (java.util.ArrayList)7 Test (org.junit.Test)6 HashSet (java.util.HashSet)4 CtMethod (spoon.reflect.declaration.CtMethod)4 RoleHandler (spoon.reflect.meta.RoleHandler)4 CtElement (spoon.reflect.declaration.CtElement)3 CtLineElementComparator (spoon.support.comparator.CtLineElementComparator)3 SpoonMetaModel (spoon.test.metamodel.SpoonMetaModel)3 File (java.io.File)2 HashMap (java.util.HashMap)2 Launcher (spoon.Launcher)2 SpoonException (spoon.SpoonException)2 CtBlock (spoon.reflect.code.CtBlock)2 CtAnonymousExecutable (spoon.reflect.declaration.CtAnonymousExecutable)2 CtClass (spoon.reflect.declaration.CtClass)2 CtConstructor (spoon.reflect.declaration.CtConstructor)2 CtField (spoon.reflect.declaration.CtField)2 MMMethod (spoon.test.metamodel.MMMethod)2 MetamodelProperty (spoon.test.metamodel.MetamodelProperty)2