如何从 XExpression 获取 JvmModelInferrer 方法主体并附加样板代码
How to JvmModelInferrer method body from XExpression and append boilerplate code
在 JvmModelInferrer 中,构造方法或构造函数的主体时,如何从语法中插入 both XExpression
body = op.body
和额外的"boilerplate"代码,例如
body = [
append(
'''
System.out.println("BOILERPLATE");
'''
)
]
我可以做到其中一个,但不能同时做到。
对于最小的工作示例,请考虑以下规范的 Xbase 语法,
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)? '{'
attributes += Attribute*
operations += Operation*
'}';
Attribute:
'attr' (type=JvmTypeReference)? name=ID ('=' initexpression=XExpression)? ';';
Operation:
'op' (type=JvmTypeReference)? name=ID
'(' (params+=FullJvmFormalParameter (',' params+=FullJvmFormalParameter)*)? ')'
body=XBlockExpression;
和 JvmModelInferrer,
package org.example.xbase.entities.jvmmodel
import com.google.inject.Inject
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
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
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 = [
// append(
// '''
// System.out.println("BOILERPLATE");
// '''
// )
// ]
body = op.body
]
]
]
}
}
正如评论所建议的那样,我想将 "boilerplate" 代码插入到方法主体中,在 XExpression 本身之前。虽然我可以插入样板文件或表达式,但我不知道如何同时执行这两项操作。
这行不通。你唯一能做的就是推断两种方法
methodWithBoilerplate() {
//pre
methodwithoutboilerplate
//post
}
methodwithoutboilerplate() {
usercode goes here
}
- 首次使用
body = '''code here'''
- 第二次使用
body = exp.body
在 JvmModelInferrer 中,构造方法或构造函数的主体时,如何从语法中插入 both XExpression
body = op.body
和额外的"boilerplate"代码,例如
body = [
append(
'''
System.out.println("BOILERPLATE");
'''
)
]
我可以做到其中一个,但不能同时做到。
对于最小的工作示例,请考虑以下规范的 Xbase 语法,
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)? '{'
attributes += Attribute*
operations += Operation*
'}';
Attribute:
'attr' (type=JvmTypeReference)? name=ID ('=' initexpression=XExpression)? ';';
Operation:
'op' (type=JvmTypeReference)? name=ID
'(' (params+=FullJvmFormalParameter (',' params+=FullJvmFormalParameter)*)? ')'
body=XBlockExpression;
和 JvmModelInferrer,
package org.example.xbase.entities.jvmmodel
import com.google.inject.Inject
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
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
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 = [
// append(
// '''
// System.out.println("BOILERPLATE");
// '''
// )
// ]
body = op.body
]
]
]
}
}
正如评论所建议的那样,我想将 "boilerplate" 代码插入到方法主体中,在 XExpression 本身之前。虽然我可以插入样板文件或表达式,但我不知道如何同时执行这两项操作。
这行不通。你唯一能做的就是推断两种方法
methodWithBoilerplate() {
//pre
methodwithoutboilerplate
//post
}
methodwithoutboilerplate() {
usercode goes here
}
- 首次使用
body = '''code here'''
- 第二次使用
body = exp.body