Можно ли получить все функции верхнего уровня в файле сценария Kotlin (* .kts), которые украшены определенной аннотацией, с помощью API сценариев Java JSR 223 без необходимости изменять и оценивать сценарий (т.е. только путем компиляциисценарий с Java Scripting API)?
Требуется иметь возможность получать метаданные для функций в сценариях.Имена функций заранее неизвестны, и функции будут вызываться только позже.Он должен работать универсальным образом для сценария, написанного в любой реализации языка JVM с поддержкой JSR 223 (Kotlin, Groovy, JavaScript, JRuby и т. Д.).
Ниже показан тестовый проект.
Структура тестового проекта:
+---script-functions
| | pom.xml
| |
| +---src
| | +---main
| | | +---java
| | | | \---scriptfun
| | | | Main.java
| | | | MyAnnotation.java
| | | |
| | | \---resources
| | | \---META-INF
| | | \---services
| | | javax.script.ScriptEngineFactory
pom.xml:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>script-tests</groupId>
<artifactId>script-functions</artifactId>
<version>1.0-SNAPSHOT</version>
<properties>
<kotlin.version>1.3.21</kotlin.version>
</properties>
<dependencies>
<dependency>
<groupId>org.jetbrains.kotlin</groupId>
<artifactId>kotlin-script-util</artifactId>
<version>${kotlin.version}</version>
</dependency>
<dependency>
<groupId>org.jetbrains.kotlin</groupId>
<artifactId>kotlin-compiler-embeddable</artifactId>
<version>${kotlin.version}</version>
</dependency>
</dependencies>
</project>
MyAnnotation.java:
package scriptfun;
import java.lang.annotation.*;
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface MyAnnotation {
}
Main.java:
package scriptfun;
import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import javax.script.*;
public class Main {
private static final String SCRIPT
= "@scriptfun.MyAnnotation()\n"
+ "fun unknownFun(): Int {\n"
+ " return 0\n"
+ "}";
public static void main(String[] args) throws Exception {
boolean evalScript = false;
ScriptEngineManager factory = new ScriptEngineManager();
ScriptEngine engine = factory.getEngineByExtension("kts");
if (evalScript) {
// This works, but the script must be wrapped and evaluated and the code is specific to Kotlin
String script = "val obj = object {" + SCRIPT + "}\n"
+ "obj";
Object obj = engine.eval(script);
Method method = obj.getClass().getDeclaredMethods()[0];
Annotation annotation = method.getAnnotations()[0];
System.out.println("obj = " + obj); // obj = Line_1$obj$1@7fa255ee
System.out.println("method = " + method); // method = public final int Line_1$obj$1.unknownFun()
System.out.println("annotation = " + annotation); // annotation = @scriptfun.MyAnnotation()
} else {
if (engine instanceof Compilable) {
Compilable compilable = (Compilable) engine;
CompiledScript compiledScript = compilable.compile(SCRIPT);
// HELP How do I get the Method and Annotation here?
}
}
}
}