Xtext内容/模板提案

时间:2014-11-17 20:00:24

标签: xtext

另一个Xtext问题!我的目标是为类似注释的结构创建模板/内容提案,如下所示:

Model:
    elements+=Element*;

Element:
    AnnotationDecl | ClassDecl;

AnnotationDecl:
    'annotation' name=ID '{' fields+=AnnotationDeclField* '}';

AnnotationDeclField:
    name=ID;

Annotation:
    '@' declaration=[AnnotationDecl] '(' members+=AnnotationField* ')';

AnnotationField:
    declaration=[AnnotationDeclField] '=' value=STRING;

ClassDecl:
    annotations+=Annotation* 'class' name=ID '{' /* ... */ '}';

这种语言的示例用法是这样的:

annotation Foo { 
    foo 
    bar
} 

@Foo(foo = 'foo' bar = 'bar')
class A { 
}

问题

现在处于当前状态,如果我编写必要的范围提供程序,Xtext为用户完成此结构提供了相当好的基础,但如果他/她不熟悉该语言的结构,则可能会令人困惑输入以下内容:

@ ctrl + space 选择Foo ctrl + space select { {1}} ctrl + space ...

所以我的想法是提供一个预先填充的基础,这在语法上是正确的,并且他/她只需要在模板中使用 tab 导航填充重要部分:

(

尝试解决此问题:

我做了2次尝试,没有一次是我正在寻找的。

1。内容提案

首先是通过以下内容提案来解决这个问题:

@Foo(foo = '${foo}' bar = '${bar}')

这使得上下文正确,因为它在我键入class MyDslProposalProvider extends AbstractMyDslProposalProvider { override complete_Annotation(EObject model, RuleCall rc, ContentAssistContext ctx, ICompletionProposalAcceptor acceptor) { super.complete_Annotation(model, rc, ctx, acceptor) if (model == null || model.eContainer == null) { return } val rootModel = model.eContainer as Model val annotationDecls = rootModel.elements.filter(AnnotationDecl) annotationDecls.forEach [ annDecl | val fieldsProposals = annDecl.fields.map[name].map[field|'''«field» = ${«field»}'''] val fullProposalText = '''@«annDecl.name»(«fieldsProposals.join(' ')»)''' val proposal = createCompletionProposal(fullProposalText, annDecl.name, null, ctx) acceptor.accept(proposal) ] } } 字符后立即显示提案,但由于它不是模板,因此它将按原样使用并显示原始字符串创建的内容: / p>

@

2。模板提案

我的第二次尝试是创建模板提议提供程序,如下所示:

@Foo(foo = '${foo}' bar = '${bar}')

在内容方面创建了我想要的内容,但我无法对其进行微调,因此只有在我输入class MyDslTemplateProposalProvider extends DefaultTemplateProposalProvider { @Inject new(TemplateStore templateStore, ContextTypeRegistry registry, ContextTypeIdHelper helper) { super(templateStore, registry, helper) } override protected createTemplates(TemplateContext tplCtx, ContentAssistContext ctx, ITemplateAcceptor acceptor) { super.createTemplates(tplCtx, ctx, acceptor) val rootModel = ctx.rootModel as Model if (rootModel == null) { return } val annotationDecls = rootModel.elements.filter(AnnotationDecl) annotationDecls.forEach [ annDecl | val fieldsProposals = annDecl.fields.map[name].map[field|'''«field» = '${«field»}' '''.toString.trim] val fullProposalText = '''@«annDecl.name»(«fieldsProposals.join(' ')»)''' val template = new Template(annDecl.name, '', annDecl.name, fullProposalText, true) val proposal = createProposal(template, tplCtx, ctx, null, getRelevance(template)) acceptor.accept(proposal) ] } } 字符并按 ctrl 后才能显示+ space (就像内容提案一样),因为看起来它不会显示我是否处于未完成的规则​​中。

所以我的问题是:

哪个是正确的解决方案?

  • 常规内容提案是否可以某种方式配置,所以它是 解释为模板?
  • 或者我可以以某种方式微调模板 建议只在我希望它显示的上下文中显示('@'按下)?

提前致谢,对于大量代码感到抱歉,我真的试图将其缩小到相关部分!

1 个答案:

答案 0 :(得分:0)

createTemplates方法允许您访问ContentAssistContext,从而访问getCurrentNode,您可以从中确定是否已有@