标签: annotation-processing

上一轮创建的类型为[生成的java文件的路径]的文件将不进行注释处理

我编写了一个AnnotationProcessor扫描代码中某个注释并从中生成 Java 类的程序。它基本上做了这样的事情:

  private Multimap<String, Element> elements;

 @Override
  public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {

    for (Element annotatedElement : roundEnv.getElementsAnnotatedWith(Factory.class)) {

        elements.put(annotatedElement.getSimpleName());
    }

   generateCode(elements);
}
Run Code Online (Sandbox Code Playgroud)

以防万一: generateCode()将迭代elements,这是一个多重映射,并为每个键创建一个类(键+后缀是我想要生成的文件的名称),并使用根据元素列表的信息创建的代码(与 key 关联的某个 key 的 multimap 的值。

显然我会调用generateCode()每一轮注释处理。因此,我会收到一个编译错误,表明在上一轮中已经生成了同名的文件。

处理这个问题的正确方法是什么?我认为收集所有注释并仅在最后一轮生成类是个好主意,如下所示:

  private Multimap<String, Element> elements;

 @Override
  public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {

    for (Element annotatedElement : roundEnv.getElementsAnnotatedWith(Factory.class)) {

        elements.put(annotatedElement.getSimpleName());
    }

   if (roundEnv.processingOver()){
      generateCode(elements);
   }
}
Run Code Online (Sandbox Code Playgroud)

这解决了多次生成相同文件的问题,但现在我收到以下警告:

警告:java:上一轮创建的类型为[生成的java文件的路径]的文件将不会受到注释处理。

javadoc 指出您不应该在上一轮中生成代码。我应该什么时候生成我的文件?

此外,如果我单击重建项目,我还会在 IntelliJ 14 中收到此警告:警告:输出路径 [生成的 …

java annotation-processing

6
推荐指数
1
解决办法
1112
查看次数

是否可以在注释处理环境中获取包中的所有 TypeElement?

我的库中有几个包含注释和基类的包。我在这个问题的上下文中扩展了 javax.annotation.processing.AbstractProcessor 。

有没有办法获取包中声明的所有类型的 java.lang.TypeElement 的列表/数组/集合?甚至元素?

目前,我有一个解决方法,通过使用类型上的注释将类标记为组,该类型仅存在于表示库中的相关对象组。是否有更简单的方法按包(即位置)而不是显式声明将类型分组在一起?

java metaprogramming javac annotation-processing

6
推荐指数
1
解决办法
1192
查看次数

Kotlin 多平台注释处理

kapt当一个人有一个 jvm 目标时,可以在 Kotlin Multiplatform 中完成注释处理。

但是,如果没有 jvm 目标,如何处理注释?

具体来说,我想在处理来自commonMain. 但我无法弄清楚如何处理这些。

我的注释处理器此刻只记录:

@SupportedSourceVersion(SourceVersion.RELEASE_8)
@SupportedAnnotationTypes("ch.hippmann.annotation.Register")
@SupportedOptions(RegisterAnnotationProcessor.KAPT_KOTLIN_GENERATED_OPTION_NAME)
class RegisterAnnotationProcessor : AbstractProcessor(){

    companion object {
        const val KAPT_KOTLIN_GENERATED_OPTION_NAME = "kapt.kotlin.generated"
    }

    override fun process(annotations: MutableSet<out TypeElement>?, roundEnv: RoundEnvironment?): Boolean {
        processingEnv.messager.printMessage(Diagnostic.Kind.WARNING, "Processing")
        return true
    }


}
Run Code Online (Sandbox Code Playgroud)

注释位于一个单独的多平台模块中,位于commonMain

@Target(AnnotationTarget.CLASS, AnnotationTarget.FUNCTION)
@Retention(AnnotationRetention.RUNTIME)
annotation class Register
Run Code Online (Sandbox Code Playgroud)

并在项目中使用commonMain
部分build.gradle

kotlin {
    jvm()
    // For ARM, should be changed to iosArm32 or iosArm64
    // For Linux, should be changed …
Run Code Online (Sandbox Code Playgroud)

annotations annotation-processing kotlin kapt kotlin-multiplatform

6
推荐指数
1
解决办法
616
查看次数

Android多模块注解处理

在多模块 Android 项目中,注释处理仍然作为第一个任务执行,然后再进行任何编译,然后触发完整的编译。当然,这是在进入模块之前按模块完成的app

想象一下,其中一些子模块依赖于他人的情况下,编译将失败作为因无法还没有找到该模块中生成的类定义,这取决于仅仅是因为他们还没有产生。

我想知道是否有一种方法可以使用gradle或其他任何方法来强制首先执行所有子模块注释处理,然后以自动方式编译整个项目。这意味着,如果我有3个模块,让我们为它们命名appservicesexecutors在那里services依赖executors

我所寻求的是构建树将按以下顺序进行:

  1. 对所有模块执行注解处理,无需编译
  2. 然后调用完整的项目编译

到目前为止,我发现使用该java compiler's选项的一些有希望的线索,-proc:{none;only}其中值only应该调用注释处理而无需任何进一步的编译。我试过将它传递option给我的编译器,但编译仍然按子模块顺序进行。

有任何想法吗?

java android annotation-processing

6
推荐指数
1
解决办法
347
查看次数

KSP:如何获取数据类属性的默认值?

我有以下数据类注释@MyAnnotation

@MyAnnotation
data class MyDataClass(
    val foo: Boolean = true,
    val bar: Int = 123,
    val buz: String? = "abc",
)
Run Code Online (Sandbox Code Playgroud)

ClassDeclaration我可以获取所有KSPropertyDeclaration,并且我能够获取simpleName并解析KSType,但我不知道如何获取每个属性的默认值。

annotation-processing kotlin kotlin-symbol-processing

6
推荐指数
1
解决办法
924
查看次数

带有版本目录的 kotlin-kapt 插件

我已将我的构建迁移到使用版本目录。我已从 build.gradle 中删除了以下内容

plugins {
id 'kotlin-android'
id 'kotlin-kapt'
}
Run Code Online (Sandbox Code Playgroud)

kapt "androidx.room:room-compiler:$room_version"
annotationProcessor "androidx.room:room-compiler:$room_version"

kapt "com.google.dagger:hilt-compiler:$hilt_version"
Run Code Online (Sandbox Code Playgroud)

现在我得到了

warning: The following options were not recognized by any processor: 
'[dagger.hilt.internal.useAggregatingRootProcessor, room.schemaLocation, 
dagger.fastInit, dagger.hilt.android.internal.disableAndroidSuperclassValidation, 
dagger.hilt.android.internal.projectType]'
Run Code Online (Sandbox Code Playgroud)

1 条警告

A failure occurred while executing 
com.android.build.gradle.internal.tasks.MergeJavaResWorkAction
 > 2 files found with path 'META-INF/gradle/incremental.annotation.processors' from 
 inputs:
  - /.gradle/caches/transforms- 
 3/5f588ae3973231906376832b3350f55d/transformed/jetified-hilt-android-compiler- 
 2.45.jar
   - /.gradle/caches/transforms- 
 3/f1c91d9e7fbd546100043f736678c477/transformed/jetified-dagger-compiler-2.45.jar
Run Code Online (Sandbox Code Playgroud)

现在我想知道如何kotlin-kapt作为插件添加到版本目录中。或者如何使用annotationProcessor版本目录?

annotation-processing android-studio android-gradle-plugin android-jetpack-compose

6
推荐指数
1
解决办法
5881
查看次数

如何从注释处理器中的AnnotationValue捕获枚举

我试图使用注释处理器和注释镜像读取注释中枚举的值,但我得到了返回null.我认为这与将Enum包装为VariableElement的AnnotationValue有关.VariableElement的文档#getConstantValue()表示"如果这是一个初始化为编译时常量的最终字段,则返回此变量的值." 好的,但是final不是注释成员的有效修饰符.另外值得注意的是,我可以轻松阅读其他注释值,只需阅读Enums.

我做了一些调查,看起来AnnotationValue在运行时被实例化为Symbol.VarSymbol,但是Symbol.VarSymbol #getConstantValue()看起来应该只返回对象.

最后,如果我在AnnotationValue上执行toString(),我会得到正确的值.

注释:

package annotation;
public @interface AnAnnotation
{
    String value();
    Behavior defaultBehavior() default Behavior.NEW;

    public static enum Behavior
    {
        NEW, NULL;
    }
}
Run Code Online (Sandbox Code Playgroud)

我的处理器的一部分并嵌套在过多的循环中以获得正确的AnnotaionMirror:

Map<? extends ExecutableElement, ? extends AnnotationValue> annotationValues = elemUtils.getElementValuesWithDefaults(annotationMirror);
for (ExecutableElement method : annotationValues.keySet())
{
    ...
    else if ("defaultBehavior".equals(method.getSimpleName().toString()))
    {

        defaultBehavior = (Behavior)( (VariableElement)annotationValues.get(method).getValue()).getConstantValue();

        // This prints "NEW" or "NULL" correctly
        processingEnv.getMessager().printMessage(Diagnostic.Kind.NOTE,annotationValues.get(method).toString());
        // This prints null incorrectly (expect "NEW" or "NULL")
        processingEnv.getMessager().printMessage(Diagnostic.Kind.NOTE, defaultBehavior + "");

    }
    ...
}
Run Code Online (Sandbox Code Playgroud)

编辑:处理器的更完整版本.

package annotation.processor;

import …
Run Code Online (Sandbox Code Playgroud)

java enums annotations mirror annotation-processing

5
推荐指数
1
解决办法
2229
查看次数

如何在Java注释处理中获取字段的类型注释?

例如,我有以下代码:

@Retention(RetentionPolicy.SOURCE)
public @interface ClassAnnotation {
}

@ClassAnnotation
public class AnnotatedClass {
}

@ClassAnnotation
public class AnotherAnnotatedClass {

    private AnnotatedClass someField;
    private int intIsNotAnnotated;
}
Run Code Online (Sandbox Code Playgroud)

并在编译时对该处理器进行预处理:

@SupportedAnnotationTypes({ "com.example.ClassAnnotation" })
@SupportedSourceVersion(SourceVersion.RELEASE_6)
public class AwesomeProcessor extends AbstractProcessor {

    public boolean process(Set<? extends TypeElement> annotations,
            RoundEnvironment roundEnv) {
        // Skipped for brevity...
        // For each annotated class
        for (Element e : roundEnv.getElementsAnnotatedWith(ClassAnnotation.class)) {
            // Skipped for brevity...
            // For each field
            for (Element ee : classElement.getEnclosedElements()) {
                // Skipped for brevity... (of course …
Run Code Online (Sandbox Code Playgroud)

java preprocessor annotations annotation-processing

5
推荐指数
1
解决办法
1416
查看次数

从Generic TypeParameterElement获取Java Annotation Processor的TypeElement?

使用Java Annotation Processors我有以下类型:

@NameToken(value={"startPage"})
public interface MyProxy extends Proxy<StartPagePresenter> {
}
Run Code Online (Sandbox Code Playgroud)

和:

public interface Proxy<T> { }
Run Code Online (Sandbox Code Playgroud)

我有TypeElementProxy为:

TypeElement pProxyTypeElement = // ...
Run Code Online (Sandbox Code Playgroud)

现在我想获得Type参数的TypeElement <StartPagePresenter>.

我试过了:

List<? extends TypeParameterElement> proxyTypeParamElems = 
                                         proxyTypeElement.getTypeParameters();
TypeParameterElement firstParameter = proxyTypeParamElems.get(0);
Run Code Online (Sandbox Code Playgroud)

当我打印时,firstParameter.getSimpleName()我得到T而不是StartPagePresenter.

如何TypeElement从TypeParameter 获取真正的StartPagePresenter?

java annotations annotation-processing

5
推荐指数
1
解决办法
1892
查看次数

如何使用注释基于在REST中创建这些资源的用户来授权特定资源

我不理解保留策略的Java注释作为RUNTIME.我要做的是创建一个名为@Authorize的注释,并将其用于需要用户授权的方法,以便执行某些操作(此时用户已经过身份验证).例如.我有一个带有getOrder()方法的订单服务.我只想创建此订单的用户访问它.`

public void getOrder(User user) {
   //current code does something like this
   if(order.getCreatedBy().equals(user)) {
     //then proceed. 
}
Run Code Online (Sandbox Code Playgroud)

}

我不想将这种逻辑与业务逻辑混合在一起.相反,我希望有这样的东西 - `

@Authorize
public void getOrder(User user) {
   //business logic
}
Run Code Online (Sandbox Code Playgroud)

`有几种方法,但并非所有方法都需要这种授权.有人可以解释一下我怎么能把这些碎片装在一起?在这一点上我不明白的是AnnotationProcessor如何在这里帮助我,因为它在编译时发挥了它的魔力.据我所知,它将帮助我在编译时生成一些代码,但我不知道如何使用生成的代码.我在AnnotationProcessors上经历了很多例子,但我仍然遗漏了一些东西.这些链接帮助我了解到目前为止的注释处理 -

http://hannesdorfmann.com/annotation-processing/annotationprocessing101 https://equaleyes.com/blog/2017/09/04/annotation-processing/

即使我使用反射,我应该在哪里放置反射逻辑?它与我想要实现的目标相反吗?

在这一点上,我对其他解决方案也持开放态度,这些解决方案不涉及注释,但会帮助我将业务逻辑与这种特定于资源的授权分离出来.

java spring authorization annotations annotation-processing

5
推荐指数
1
解决办法
689
查看次数