【问题标题】:Referencing Grammar in Xtext Validator在 Xtext Validator 中引用语法
【发布时间】:2018-12-19 18:33:44
【问题描述】:

在 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)
        }
    }
}

我在这里添加推断器:

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")
    }
}

【问题讨论】:

  • 我不确定这是否有意义。你似乎使用 xbase。但您可以按照参考并使用 IJvmModelAssociations 找出 jvmType 是从什么推断出来的
  • var simpleName= f.type.type.simpleName,这会给我java类型,但我不知道它是聚合类型还是值类型。我可以通过 IJvmModelAssociations 获得相同的信息,但同样,我只获得目标 Java 对象。我知道这是一个地址,但不是一个聚合
  • 我的意思是 f.type.type
  • org.eclipse.xtext.xbase.jvmmodel.IJvmModelAssociations.getPrimarySourceElement(EObject)
  • 不幸的是,org.eclipse.xtext.xbase.jvmmodel.IJvmModelAssociations.getSourceElements() 返回一个空列表。因此 getPrimarySourceElement() 为 null :(

标签: xtext


【解决方案1】:

我无法重现这个

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)

如预期的那样

【讨论】:

  • 我从头开始重新创建了一个新的 Xtext 项目。源仍为空:\norg.fb.simple.impl.PropertyImpl@43af351a(名称:a)和 []。我的测试设置错了吗?
  • 能否提供完整的样品和测试
  • 我刚刚添加了测试
  • 我刚刚从 github 下载了这些示例 (github.com/xtext/seven-languages-xtext)。当我从脚本示例运行 CompilationTest 时,我仍然得到一个空源。可能与我使用的 Eclipse 版本有关吗?有什么改变吗?这是我的 Eclipse 版本 Eclipse DSL 工具版本:2018-09 (4.9.0) 构建 ID:20180917-1800
  • 你测试的模型是什么?
猜你喜欢
  • 2012-11-01
  • 2015-08-14
  • 2015-09-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-05-20
  • 2021-12-12
  • 2012-05-13
相关资源
最近更新 更多