在Xtext验证器中,我想断言一个Aggregate没有引用另一个Aggregate
通过这种简化的语法
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")
}
}
答案 0 :(得分:0)
我无法复制
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)
符合预期