总览

我正在尝试构建我的第一个注释处理器,并且进展顺利。我正在创建一个代码生成处理器,该处理器基本上为定义的接口(interface)生成SharedPreferences。我当前的注释是SharedPrefsDefault@SharedPrefs通知处理器该文件是接口(interface),需要生成的prefs文件。 @Default是我在接口(interface)中注释的一些属性,以便让处理器知道将默认值设置为什么。可以有多个定义为@SharedPrefs的文件。

实作

我目前使用以下代码来获取带有@SharedPrefs@Default注释的文件的列表:

roundEnv.getElementsAnnotatedWith(SharedPrefs::class.java)?.forEach { element ->
  ...
  roundEnv.getElementsAnnotatedWith(Default::class.java)?.forEach {
    ...
  }
}
@SharedPrefs:

@Retention(AnnotationRetention.SOURCE)
@Target(AnnotationTarget.CLASS)
annotation class SharedPrefs(val showTraces: Boolean = false)
@Default:

@Retention(AnnotationRetention.SOURCE)
@Target(AnnotationTarget.PROPERTY)
annotation class Default(val defaultValue: String = "[null]")

正在使用:

@SharedPrefs
interface InstanceSettings {
    var wifiPassword: String
    @Default("20")
    var count: Int
}

问题

照原样,内部forEach从所有带有@Default注释的文件中返回所有属性。代码生成工作正常,但是这似乎不是最好的方法。有没有办法只获取我正在处理的当前@SharedPrefs类中的属性?例如,类似:

roundEnv.getElementsAnnotatedWith(SharedPrefs::class.java)?.forEach { element ->
  ...
  element.methodToGetAnnotatedProperties(Default::class.java)?.forEach {
    ...
  }
}

*编辑*

我发现,对于我注释的方法

@SomeAnnotation
fun someMethod()

我可以遍历element.enclosingElements并使用enclosingElement.getAnnotation(<SomeAnnotation::class.java>)查找它是否具有注释。不幸的是,如果在这里我错了,请纠正我,我无法使用AnnotationTarget.FIELD注释注释接口(interface)变量,因为它们是接口(interface)并且没有实现,因此它们没有后备字段。因此,我正在使用AnnotationTarget.PROPERTY。当遍历封闭的元素时,所有变量都显示为getter和setter。对于上面InstanceSettings的示例,我得到getWifiPasswordsetWifiPasswordgetCountsetCount。我不只是wifiPasswordcount的元素。由于生成它们,因此调用getAnnotation(Default::class.java)将始终对它们返回null。

另外,任何人都知道的有关注释处理的任何其他资源都将成为注释中的重要补充。谢谢!

最佳答案

有人问过Java中类似的问题here

这是创建扩展功能的方法,它将为您效劳!

roundEnv.getElementsAnnotatedWith(SharedPrefs::class.java)?.forEach { element ->
    ...
    roundEnv.findNestedElements(SharedPrefs::class, Default::class)?.forEach {
        ...
    }
}

fun <T> RoundEnvironment.findNestedElements(parent: KClass<*>, child: KClass<T>): List<Element>? {
    val childs = this.getElementsAnnotatedWith(child.java)
    val list = ArrayList<Element>()
    for (element in childs)
    {
        if (element.getEnclosingElement().getAnnotation(parent.java) != null)
        {
            list.add(element)
        }
    }
    return if(list.isEmpty()) null else list
}

09-04 22:42