Skip to content
This repository has been archived by the owner on Apr 13, 2023. It is now read-only.

Latest commit

 

History

History
152 lines (123 loc) · 6.6 KB

Better Annotation Processing Supporting Stubs in kapt.md

File metadata and controls

152 lines (123 loc) · 6.6 KB
title date author tags keywords categories reward reward_title reward_wechat reward_alipay source_url translator translator_url
[译]Better Annotation Processing: Supporting Stubs in kapt
2015-06-22 08:28:00 -0700
Andrey Breslav
官方动态
false
Have a nice Kotlin!

我们宣布 kapt 之前,Kotlin 的注释处理工具,并讨论了其局限性。现在,大部分**限制正在消失,可以使用0.1-SNAPSHOT预览版本的kapt`更新版本。<span id =“ more-2385“>

回顾:kapt 如何工作

通过截取注解处理器(例如 Dagger 2)和javac之间的通信,初始版本的kapt工作,并在 Java 类之上添加了已经编译的 Kotlin 类,代码> javac`在源中看到自己。这种方法的问题是,由于 Kotlin 类必须已经被编译,所以没有办法引用处理器生成的任何代码(例如 Dagger 的模块类)。因此,我们必须在 Java 中编写 Dagger 应用程序类。

它现在如何工作

在上一篇博文中讨论过 可以通过在运行javac之前生成 Kotlin 类的**来克服该问题,然后在javac完成后运行真正的编译。存根只包含声明,没有方法体。 Kotlin 编译器用于在内存中创建这样的存根(它们用于 Java 互操作,当 Java 代码回溯到 Kotlin 时),所以我们只需要将它们序列化到磁盘上的文件。

示例:DBFlow

Stubs 支持依赖于注释处理器生成的代码的框架。例如,您现在可以使用 DBFlow 在 Kotlin:

{% raw %}

{% endraw %}
public object ItemRepository {
 
    public fun getAll(): MutableList<Item> {
        return Select()
                .from(javaClass<Item>())
                .where()
                .orderBy(false, Item_Table.UPDATED_AT)
                .queryList()
    }
 
}

{% raw %}

{% endraw %}

由 DBFLow 库提供类似 DSL 的功能Select(),()等,DBFlow 的注释处理器生成Item_Table,上面的 Kotlin 代码可以高兴地参考它! 完整的例子是可用的 [这里](https://github.com/yanex/kotlin-poc) (谢谢 [Mickele Moriconi](https://github.com/mickele) 对于初始代码)。 请注意,生成存根需要相对较多的工作,因为所有声明必须解决,有时候知道返回类型需要分析表达式(函数或属性初始化程序的主体在=符号之后)。因此,在kapt`中使用存根减慢了你的构建。这就是为什么存根默认情况下关闭,为了使它们能够在您的 build.gradle 文件

{% raw %}

{% endraw %}
kapt {
    generateStubs = true
}

{% raw %}

{% endraw %}

此外,kapt现在可以处理传递参数到注释处理器。这是一个例子 AndroidAnnotations 图书馆:

{% raw %}

{% endraw %}
kapt {
    generateStubs = true
    arguments {
        arg("androidManifestFile", variant.outputs[0].processResourcesTask.manifestFile)
    }
}

{% raw %}

{% endraw %}

源保留注释

正如您可能已经注意到的那样,我们生成二进制代码.class -files,而不是作为.java源。这更加方便,原因有很多:

  • 我们已经为不同的目的生成了必要的字节,
  • 在一个类文件中,我们可以简单地跳过一个方法的主体,不需要生成一个将使 javac 快乐的存根体,
  • javac 将编译存根源并生成稍后需要删除的类文件,
  • 这种方式,旧的(快速)和新(较慢)的 kapt 模式使用相同的基本机制。

但是二进制存根有自己的缺点:

  • 如果注释由 @Retention(RetentionPolicy.SOURCE)标记,则它不在二进制文件中,
  • javac 不会在类层次结构下传播 @Inherited 注释。

到目前为止,我们还没有解决后一个问题,但前者的源保留注释是绝对关键的,因为许多流行的框架(如 DBFlow )他们的注释源保留。幸运的是,当javac读取二进制文件时,它不会仔细检查注释,如果我们将类保留的注释写入类文件,尽管声明了保留,它会高兴地看到它。这是我们现在所做的<img alt =“:)”class =“wp-smiley”data-recalc-dims =“1”src =“https://i2.wp.com/blog.jetbrains.com/kotlin /wp-includes/images/smilies/simple-smile.png?w=640&ssl=1“style =”height:1em; max-height:1em“

剩余限制

kapt上还有一些工作尚待处理。 注释处理本身最大的问题是支持 @ 继承注释 。我们需要解决javac,不会将它们传播到二进制类的层次结构中。 但是真正的问题在于外部的kapt:许多框架,如 AndroidAnnotation 并且上述 DBFlow 想要直接将值注入到字段中,而 Kotlin 则是关于安全的,并且使这些字段private正在阻碍。这就是为什么现在我们必须在 Java 中编写 DBFlow“表类” Item.java 在我们的例子中 所以,我们正在考虑一个选择性功能,使得 Kotlin 生成的类中的非私有字段。

反馈

新的kapt尚未发布,但欢迎您尝试并告诉我们您的想法。以下是您如何做的例子:

{% raw %}

{% endraw %}
repositories {
    maven { url 'https://raw.github.com/Raizlabs/maven-releases/master/releases' }
    maven { url 'http://oss.sonatype.org/content/repositories/snapshots' }
    jcenter()
}
 
dependencies {
    ...
 
    // DBFlow
    kapt 'com.raizlabs.android:DBFlow-Compiler:2.0.0'
    compile 'com.raizlabs.android:DBFlow-Core:2.0.0'
    compile 'com.raizlabs.android:DBFlow:2.0.0'
 
    // Kotlin
    compile 'org.jetbrains.kotlin:kotlin-stdlib:0.1-SNAPSHOT'
}
 
kapt {
    generateStubs = true
}

{% raw %}

{% endraw %}

再次参见完整的 DBFlow 示例 这里 。 请告诉我们:

  • 有什么对你有用
  • 什么没有?
  • 你喜欢还是不喜欢什么?
  • 任何我们忽视的用例?

谢谢!