【问题标题】:Grammatically restricted JVMModelInferrer inheritence with Xtext and XBaseXtext 和 XBase 的语法限制 JVMModelInferrer 继承
【发布时间】:2018-10-17 19:04:38
【问题描述】:

以下规范的 XBase 实体语法(来自“使用 Xtext 和 Xtend 实现领域特定语言”Bettini)允许实体扩展 任何 Java 类。正如注释行所示,我想在语法上强制实体从实体继承。

grammar org.example.xbase.entities.Entities with org.eclipse.xtext.xbase.Xbase

generate entities "http://www.example.org/xbase/entities/Entities"

Model:
    importSection=XImportSection?
    entities+=Entity*;

Entity:
    'entity' name=ID ('extends' superType=JvmParameterizedTypeReference)? '{'
//  'entity' name=ID ('extends' superType=[Entity|QualifiedName])? '{'
        attributes += Attribute*
        constructors+=Constructor*
        operations += Operation*
    '}';

Attribute:
    'attr' (type=JvmTypeReference)? name=ID ('=' initexpression=XExpression)? ';';

Operation:
    'op' (type=JvmTypeReference)? name=ID 
    '(' (params+=FullJvmFormalParameter (',' params+=FullJvmFormalParameter)*)? ')' 
        body=XBlockExpression;

Constructor:    'new'  
    '(' (params+=FullJvmFormalParameter (',' params+=FullJvmFormalParameter)*)? ')' 
        body=XBlockExpression;

这是上面模型的工作 JVMModelInferrer,其中注释行(和额外方法)再次反映了我的意图。

package org.example.xbase.entities.jvmmodel

import com.google.inject.Inject
import org.eclipse.xtext.common.types.JvmTypeReference
import org.eclipse.xtext.naming.IQualifiedNameProvider
import org.eclipse.xtext.xbase.jvmmodel.AbstractModelInferrer
import org.eclipse.xtext.xbase.jvmmodel.IJvmDeclaredTypeAcceptor
import org.eclipse.xtext.xbase.jvmmodel.JvmTypesBuilder
import org.example.xbase.entities.entities.Entity

class EntitiesJvmModelInferrer extends AbstractModelInferrer {

    @Inject extension JvmTypesBuilder
    @Inject extension IQualifiedNameProvider

    def dispatch void infer(Entity entity, IJvmDeclaredTypeAcceptor acceptor, boolean isPreIndexingPhase) {
        acceptor.accept(entity.toClass("entities." + entity.name)) [
            documentation = entity.documentation
            if (entity.superType !== null) {
                superTypes += entity.superType.cloneWithProxies
                //superTypes += entity.superType.jvmTypeReference.cloneWithProxies
            }

            entity.attributes.forEach [ a |
                val type = a.type ?: a.initexpression?.inferredType
                members += a.toField(a.name, type) [
                    documentation = a.documentation
                    if (a.initexpression != null)
                        initializer = a.initexpression
                ]
                members += a.toGetter(a.name, type)
                members += a.toSetter(a.name, type)
            ]
            entity.operations.forEach [ op |
                members += op.toMethod(op.name, op.type ?: inferredType) [
                    documentation = op.documentation
                    for (p : op.params) {
                        parameters += p.toParameter(p.name, p.parameterType)
                    }
                    body = op.body
                ]
            ]
            entity.constructors.forEach [ con |
                members += entity.toConstructor [
                    for (p : con.params) {
                        parameters += p.toParameter(p.name, p.parameterType)
                    }
                    body = con.body
                ]
            ]
        ]
    }

    def JvmTypeReference getJvmTypeReference(Entity e) {
        e.toClass(e.fullyQualifiedName).typeRef
    }

}

以下简单实例完美解析和推断(使用 cmets)。

entity A {
    attr String y;

    new(String y) {
        this.y=y        
    }

}    

entity B extends A {
    new() {
        super("Hello World!")
    }
} 

但是,如果我取消注释(并在上面的相应行中注释)语法和推断器(并重新生成),则上述实例不再解析。消息是“方法 super(String) 未定义”。

我了解如何让继承“松散”并限制使用验证器等,但我更愿意将其强烈键入到模型中。

考虑到 XBase 和 JvmModelInferrer 的作用,我不知道如何解决这个问题,因为我不确定哪里出了问题。一个指针(或引用)就足够了。

[...我能够为这个语法的 non-xbase 版本实现所有范围问题...]

【问题讨论】:

  • 这行不通。我宁愿保留语法并过滤提案并引入验证
  • 或者,如果您可以猜出引用的名称(例如,从节点模型中),那么您可以使用 "qualified.Name.Of.Entity".typeRef 作为超类型
  • 这不正是我使用我的帮助方法 getJvmTypeReference(Entity e) 所做的吗?生成的qualifiedName 是正确的,但从B 中看不到super(String)。
  • 不在您上面发布的内容中
  • 非常感谢。我明白你的意思,它有效。所需的行(在这种情况下)是“superTypes += ("entities."+entity.superType.name).typeRef()”。请回答。

标签: xtext xbase


【解决方案1】:

这行不通。您要么必须保留语法并自定义提案提供者和验证。或者你必须使用"f.q.n.o.y.Entity".typeRef。您可以使用 NodeModelUtils 来阅读 FQN 或尝试类似 ("entities."+entity.superType.name).typeRef

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多