Ballerina 注释处理未按预期工作

Ballerina annotation processing doesn't work as expected

我正在尝试使用 ballerina(MacOS Catalina 上的 jBallerina-1.0.5)实现一个简单的注释处理器。在这个例子中,我需要:

  1. 遍历给定 service
  2. 的可用 resource 函数
  3. 对于每次迭代,获取给定 @annotation 的值,如 resource
  4. 中所注释

举个例子:

...
service my_service on new http:Listener(8080) {
    @my_annonatation {
        value: "my-value-for-resource-1"
    }
    resource function my_resource_1() {}

    @my_annonatation {
        value: "my-value-for-resource-2"
    }
    resource function my_resource_2() {}
}

根据上面的 service 代码片段,我需要得到 resource names as ["my_resource_1", "my_resource_2"] and @annotation value as my-value-for-resource-1,my-value-for-resource-2 对应 my_resource_1my_resource_2

我的问题是:

  1. 如何使用芭蕾舞演员
  2. 获得给定service中定义的resources
  3. 我已经尝试使用 ballerina/reflect 模块的 function getServiceAnnotations(service serviceType, string annotName, string? moduleName = ()) returns any 来获取 @annotation 值。但它在 return 中没有给出任何内容(显然它 return 是一个空字符串或可能为空)。

我没有看到任何关于芭蕾舞演员注释处理的好文章,除了老芭蕾舞演员 0.x 预发布 1. I found that the ballerina/reflect module is now updated 2 3 since 0.x pre-releases as I compared with the ballerina source code (but it has not mentioned in ballerina release notes 4)。

文章 "Extending Ballerina" 5 也提到了另一种通过编译器扩展进行注释处理的方法,它将操作委托给 Java。然而,我们有限制将 Java 依赖项推入 ballerina central

请建议我一个解决方法以获得预期的结果,非常感谢纯芭蕾舞语言的代码。

参考资料

  1. Ballerina Annotation Processing example for 0.9.x releases
  2. ballerina/reflect of 0.x
  3. ballerina/reflect of 1.0.5
  4. Ballerina release notes
  5. Extending Ballerina

注释处理可以在编译时或运行时完成。现在(使用 Ballerina 1.0.5 和更早版本),编译时注释处理只能通过 "Extending Ballerina" 文档中描述的编译器扩展来完成,而运行时注释访问可以使用 annotation access expression 或通过 ballerina/reflect 模块(只有那些不能通过注解访问表达式实现的现在可以在 ballerina/reflect 模块中使用——虽然发行说明 "A binary operator .@ has been introduced to access annotation values at runtime." 中提到了这一添加,事实上,这似乎已经遗漏了 ballerina/reflect 模块中的一些功能。

https://github.com/ballerina-platform/ballerina-lang/issues/19325 描述了提议的 Ballerina 编译器插件架构,这将允许在 Ballerina 中编写扩展。

运行时:

  1. 检索服务中定义的资源的名称 - IINM 目前如果不编写外部方法(使用 Java 互操作)是不可能的。资源名称在编译时是否未知?您可以根据要求创建一个 issue in the ballerina-lang repository 吗?

  2. 访问资源注释 - 这可以使用 reflect:getResourceAnnotations 方法完成

import ballerina/http;
import ballerina/io;
import ballerina/reflect;

type AnnotRecord record {| 
    string value; 
|};

annotation AnnotRecord my_annonatation on resource function;

string[] resourceNames = ["my_resource_1", "my_resource_2"];

service my_service on new http:Listener(8080) {
    @my_annonatation {
        value: "my-value-for-resource-1"
    }
    resource function my_resource_1(http:Caller caller, http:Request request) {}

    @my_annonatation {
        value: "my-value-for-resource-2"
    }
    resource function my_resource_2(http:Caller caller, http:Request request) {}
}

public function main() {
    foreach var resourceName in resourceNames {
        any annot = reflect:getResourceAnnotations(my_service, resourceName, "my_annonatation");
        if annot is AnnotRecord {
            io:println(annot.value);
        }
    }
}

更新:

@MaryamZis 的解决方案适用于单个芭蕾舞女演员文件,但不适用于芭蕾舞女演员项目。正如她所建议的,我已将 <org-name>/<module>:<version> 传递给 reflect:getResourceAnnotations 函数的 module 参数以使其正常工作。

...
any annot = reflect:getResourceAnnotations(
    my_service, 
    resourceName, 
    "my_annonatation", 
    "my_org/my_module:0.1.0"
);
...

//NOTE: org-name and version are defined in Ballerina.toml of the project

但是,希望在不指定模块的情况下通过reflect函数检测当前项目的注解。此 issue 由@MaryamZi 记录在芭蕾舞女演员 git 存储库中。