Search in sources :

Example 1 with MetamodelProperty

use of spoon.test.metamodel.MetamodelProperty 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 2 with MetamodelProperty

use of spoon.test.metamodel.MetamodelProperty in project spoon by INRIA.

the class RoleHandlersGenerator method process.

@Override
public void process() {
    SpoonMetaModel metaModel = new SpoonMetaModel(getFactory());
    // all root super MMFields
    List<MetamodelProperty> superFields = new ArrayList<>();
    metaModel.getConcepts().forEach(mmConcept -> {
        mmConcept.getRoleToProperty().forEach((role, rim) -> {
            addUniqueObject(superFields, rim.getRootSuperField());
        });
    });
    superFields.sort((a, b) -> {
        int d = a.getRole().name().compareTo(b.getRole().name());
        if (d != 0) {
            return d;
        }
        return a.getOwnerConcept().getName().compareTo(b.getOwnerConcept().getName());
    });
    PrinterHelper concept = new PrinterHelper(getFactory().getEnvironment());
    superFields.forEach(mmField -> {
        concept.write(mmField.getOwnerConcept().getName() + " CtRole." + mmField.getRole().name()).writeln().incTab().write("ItemType: ").write(mmField.getValueType().toString()).writeln();
        for (MMMethodKind mk : MMMethodKind.values()) {
            MMMethod mmMethod = mmField.getMethod(mk);
            if (mmMethod != null) {
                concept.write(mk.name()).write(": ").write(mmMethod.getSignature()).write(" : ").write(mmMethod.getReturnType().toString()).writeln();
            }
        }
        concept.decTab();
        concept.write("----------------------------------------------------------").writeln();
    });
    try (Writer w = new OutputStreamWriter(new FileOutputStream(file("target/report/concept.txt")))) {
        w.write(concept.toString());
    } catch (IOException e) {
        throw new RuntimeException(e);
    }
    CtType<?> template = getTemplate("spoon.generating.meta.ModelRoleHandlerTemplate");
    CtClass<?> modelRoleHandlersClass = Substitution.createTypeFromTemplate(TARGET_PACKAGE + ".ModelRoleHandlers", template, new HashMap<>());
    CtNewArray<?> roleHandlersFieldExpr = (CtNewArray<?>) modelRoleHandlersClass.getField("roleHandlers").getDefaultExpression();
    superFields.forEach(rim -> {
        Map<String, Object> params = new HashMap<>();
        params.put("$getterName$", rim.getMethod(MMMethodKind.GET).getName());
        if (rim.getMethod(MMMethodKind.SET) != null) {
            params.put("$setterName$", rim.getMethod(MMMethodKind.SET).getName());
        }
        params.put("$Role$", getFactory().Type().createReference(CtRole.class));
        params.put("ROLE", rim.getRole().name());
        params.put("$TargetType$", rim.getOwnerConcept().getModelInterface().getReference());
        // params.put("AbstractHandler", getFactory().Type().createReference("spoon.reflect.meta.impl.AbstractRoleHandler"));
        params.put("AbstractHandler", getRoleHandlerSuperTypeQName(rim));
        params.put("Node", rim.getOwnerConcept().getModelInterface().getReference());
        params.put("ValueType", fixMainValueType(getRoleHandlerSuperTypeQName(rim).endsWith("SingleHandler") ? rim.getValueType() : rim.getItemValueType()));
        CtClass<?> modelRoleHandlerClass = Substitution.createTypeFromTemplate(getHandlerName(rim), getTemplate("spoon.generating.meta.RoleHandlerTemplate"), params);
        if (rim.getMethod(MMMethodKind.SET) == null) {
            modelRoleHandlerClass.getMethodsByName("setValue").forEach(m -> m.delete());
        }
        modelRoleHandlerClass.addModifier(ModifierKind.STATIC);
        modelRoleHandlersClass.addNestedType(modelRoleHandlerClass);
        roleHandlersFieldExpr.addElement(getFactory().createCodeSnippetExpression("new " + modelRoleHandlerClass.getSimpleName() + "()"));
    });
}
Also used : SpoonMetaModel(spoon.test.metamodel.SpoonMetaModel) MMMethod(spoon.test.metamodel.MMMethod) HashMap(java.util.HashMap) ArrayList(java.util.ArrayList) IOException(java.io.IOException) CtNewArray(spoon.reflect.code.CtNewArray) PrinterHelper(spoon.reflect.visitor.PrinterHelper) FileOutputStream(java.io.FileOutputStream) MetamodelProperty(spoon.test.metamodel.MetamodelProperty) CtRole(spoon.reflect.path.CtRole) OutputStreamWriter(java.io.OutputStreamWriter) MMMethodKind(spoon.test.metamodel.MMMethodKind) OutputStreamWriter(java.io.OutputStreamWriter) Writer(java.io.Writer)

Aggregations

ArrayList (java.util.ArrayList)2 CtRole (spoon.reflect.path.CtRole)2 MetamodelProperty (spoon.test.metamodel.MetamodelProperty)2 FileOutputStream (java.io.FileOutputStream)1 IOException (java.io.IOException)1 OutputStreamWriter (java.io.OutputStreamWriter)1 Writer (java.io.Writer)1 HashMap (java.util.HashMap)1 Test (org.junit.Test)1 SpoonException (spoon.SpoonException)1 CtBlock (spoon.reflect.code.CtBlock)1 CtNewArray (spoon.reflect.code.CtNewArray)1 CtStatement (spoon.reflect.code.CtStatement)1 CtElement (spoon.reflect.declaration.CtElement)1 RoleHandler (spoon.reflect.meta.RoleHandler)1 CtFieldReference (spoon.reflect.reference.CtFieldReference)1 CtScanner (spoon.reflect.visitor.CtScanner)1 Filter (spoon.reflect.visitor.Filter)1 PrinterHelper (spoon.reflect.visitor.PrinterHelper)1 MMMethod (spoon.test.metamodel.MMMethod)1