另一个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次尝试,没有一次是我正在寻找的。 p>
首先是通过以下内容提案来解决这个问题:
@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>
@
我的第二次尝试是创建模板提议提供程序,如下所示:
@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 (就像内容提案一样),因为看起来它不会显示我是否处于未完成的规则中。
哪个是正确的解决方案?
'@'
按下)?提前致谢,对于大量代码感到抱歉,我真的试图将其缩小到相关部分!
答案 0 :(得分:0)
createTemplates方法允许您访问ContentAssistContext,从而访问getCurrentNode,您可以从中确定是否已有@