是否可以在运行时从 Java 到 运行 Xbase 脚本?

Is it possible to run Xbase script from Java in Runtime?

我想在运行时从我的 Java 应用程序调用一些脚本。但我想对用户隐藏内部模型。 所以我的想法是使用 Xtext 编写 DSL。并添加用户在此 DSL 中编写脚本然后在应用程序中执行它的能力。

可能吗?

没有通用教程。这在很大程度上取决于您的规则。关于您的环境等

这是一个过于简单化的例子

grammar org.xtext.example.mydsl.MyDsl with org.eclipse.xtext.xbase.Xbase

generate myDsl "http://www.xtext.org/example/mydsl/MyDsl"

Model:
    "model" name=ID "{"
        expressions+=NamedExpression*
    "}"
;

NamedExpression:
    name=ID "=" body=XExpression
;

推断者

/*
 * generated by Xtext 2.16.0-SNAPSHOT
 */
package org.xtext.example.mydsl.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.xtext.example.mydsl.myDsl.Model

/**
 * <p>Infers a JVM model from the source model.</p> 
 *
 * <p>The JVM model should contain all elements that would appear in the Java code 
 * which is generated from the source model. Other models link against the JVM model rather than the source model.</p>     
 */
class MyDslJvmModelInferrer extends AbstractModelInferrer {

    /**
     * convenience API to build and initialize JVM types and their members.
     */
    @Inject extension JvmTypesBuilder

    /**
     * The dispatch method {@code infer} is called for each instance of the
     * given element's type that is contained in a resource.
     * 
     * @param element
     *            the model to create one or more
     *            {@link org.eclipse.xtext.common.types.JvmDeclaredType declared
     *            types} from.
     * @param acceptor
     *            each created
     *            {@link org.eclipse.xtext.common.types.JvmDeclaredType type}
     *            without a container should be passed to the acceptor in order
     *            get attached to the current resource. The acceptor's
     *            {@link IJvmDeclaredTypeAcceptor#accept(org.eclipse.xtext.common.types.JvmDeclaredType)
     *            accept(..)} method takes the constructed empty type for the
     *            pre-indexing phase. This one is further initialized in the
     *            indexing phase using the lambda you pass as the last argument.
     * @param isPreIndexingPhase
     *            whether the method is called in a pre-indexing phase, i.e.
     *            when the global index is not yet fully updated. You must not
     *            rely on linking using the index if isPreIndexingPhase is
     *            <code>true</code>.
     */
    def dispatch void infer(Model element, IJvmDeclaredTypeAcceptor acceptor, boolean isPreIndexingPhase) {
        // Here you explain how your model is mapped to Java elements, by writing the actual translation code.

        // An implementation for the initial hello world example could look like this:
        acceptor.accept(element.toClass("my.company.greeting."+ element.name)) [
            for (x : element.expressions) {
                members += x.toMethod(x.name, inferredType) [
                    body = x.body
                ]
            }
        ]
    }
}

翻译电话

package org.xtext.example.mydsl

import org.eclipse.emf.common.util.URI
import org.eclipse.emf.ecore.resource.ResourceSet
import org.eclipse.xtext.util.CancelIndicator
import org.eclipse.xtext.util.StringInputStream
import org.eclipse.xtext.xbase.interpreter.impl.DefaultEvaluationContext
import org.eclipse.xtext.xbase.interpreter.impl.XbaseInterpreter
import org.xtext.example.mydsl.myDsl.Model

class Sample {

    def static void main(String[] args) {
        val userInput = '''
        model x {
            a = 1
            b = 1 + 2
            c = "Hello"
        }
        '''
        val injector = new MyDslStandaloneSetup().createInjectorAndDoEMFRegistration
        val resourceSet = injector.getInstance(ResourceSet)
        val resource = resourceSet.createResource(URI.createURI("dummy.mydsl"))
        resource.load(new StringInputStream(userInput), null)
        val model = resource.contents.head as Model
        val interpreter = injector.getInstance(XbaseInterpreter)
        for (g : model.expressions) {
            val ctx = new DefaultEvaluationContext
            val result = interpreter.evaluate(g.body, ctx, CancelIndicator.NullImpl)
            println(result.result)
        }
    }

}

您可能需要自定义解释器并另外将内容添加到上下文中以获取它运行您的代码。