Ссылка на грамматику в Xtext Validator - PullRequest
0 голосов
/ 14 декабря 2018

В валидаторе Xtext я хотел бы утверждать, что Агрегат не ссылается на другой Агрегат

С этой упрощенной грамматикой

grammar com.mimacom.mdd.ddd.MdDsl with org.eclipse.xtext.xbase.Xbase

generate mdDsl "http://www.mimacom.com/mdd/ddd/MdDsl"  

Domainmodel:
    elements+=Element*;

Element:
    Aggregate | ValueObject;

Aggregate:
    'aggregate' name=ValidID ('extends' superType=JvmTypeReference)? '{'
        properties+=Property*
    '}';

ValueObject:
    'valueObject' name=ValidID ('extends' superType=JvmTypeReference)? '{'
        properties+=Property*
    '}';

Property:
    name=ValidID ':' type=JvmTypeReference;

Когда я анализирую следующее, я ожидаю, чтосмог выяснить, является ли свойство valueObject или агрегатом

aggregate Address{
}
aggregate Person{
    p : Address
}

Проверка выглядит следующим образом: я не смог извлечь информацию из свойства, чтобы выяснить, является ли тип свойстваагрегат

@Inject
IJvmModelAssociations assoc;

@Check
def aggregateDoesNotReferenceOtherAggregates(Aggregate aggregate) {
    var features = aggregate.features

    for(Feature f : features){
        println(f)
        var s = assoc.getSourceElements(f.type.type)
        var first = s.get(0)
        if(first instanceof Aggregate   ){
            warning('An aggregate is not allowed to reference another aggregate'
                , null
                , aggregate.eContainingFeature)
        }
    }
}

Я добавляю Inferrer здесь:

class MdDslJvmModelInferrer extends AbstractModelInferrer {

@Inject extension JvmTypesBuilder
@Inject extension IQualifiedNameProvider

def dispatch void infer(Aggregate aggregate, IJvmDeclaredTypeAcceptor acceptor, boolean isPrelinkingPhase) {
    acceptor.accept(aggregate.toClass(aggregate.fullyQualifiedName)) [
        processAggregate(aggregate, it)
    ]
}

def dispatch void infer(ValueObject element, IJvmDeclaredTypeAcceptor acceptor, boolean isPrelinkingPhase) {
    acceptor.accept(element.toClass(element.fullyQualifiedName)) [
        processValueObject(element, it)
    ]
}

protected def void processAggregate(Aggregate aggregate, JvmGenericType it) {
    documentation = aggregate.documentation
    if (aggregate.superType !== null)
            superTypes += aggregate.superType.cloneWithProxies

    for (feature : aggregate.features) {
        switch feature {
            Property: {
                members += feature.toField(feature.name, feature.type)
                members += feature.toGetter(feature.name, feature.type)
                members += feature.toSetter(feature.name, feature.type)
            }
            Operation: {
                processOperation(it, feature)
            }
        }
    }
}

protected def void processValueObject(ValueObject element, JvmGenericType it) {
    documentation = element.documentation
    if (element.superType !== null)
            superTypes += element.superType.cloneWithProxies
    for (feature : element.features) {
        switch feature {
            Property: {
                members += feature.toField(feature.name, feature.type)
                members += feature.toGetter(feature.name, feature.type)
            }
            Operation: {
                processOperation(it, feature)
            }
        }
    }
}

protected def boolean processOperation(JvmGenericType it, Operation feature) {
    members += feature.toMethod(feature.name, feature.type) [
        documentation = feature.documentation
        for (p : feature.params) {
            parameters += p.toParameter(p.name, p.parameterType)
        }
        body = feature.body
    ]
}
}

тест, который я выполняю, который дает мне пустой источник, выглядит так

@ExtendWith(InjectionExtension)
@InjectWith(MdDslInjectorProvider)
class MdDslParsingTest {
    @Inject 
    extension CompilationTestHelper

    @Test
    def void aggregateDoesNotReferenceOtherAggregate() {
        val result = parseHelper.parse('''
            aggregate Address{
            }
            aggregate Person{
                a : Address
            }
        ''')

    validationHelper.assertWarning(result,result.eClass,"failed to find the problem")
    }
}

1 Ответ

0 голосов
/ 18 декабря 2018

я не могу воспроизвести это

class MyDslValidator extends AbstractMyDslValidator {

    @Inject
    private IJvmModelAssociations assoc

    @Check
    def checkAggregateReference(Aggregate aggregate) {
        var properties = aggregate.properties

        for (f : properties) {
            System.err.println(f)
            System.err.println(assoc.getSourceElements(f.type.type))
        }
    }

}

дает мне

org.xtext.example.mydsl.myDsl.impl.PropertyImpl@15c4ae78 (name: p)
[org.xtext.example.mydsl.myDsl.impl.AggregateImpl@6952cae7 (name: Address)

, как и ожидалось

...