标签: annotation-processing

以编程方式调用注释处理器

这是我第一次编写Annotation Processor,我想以编程方式调用它.可能吗?

我为处理器编写了小代码:

@SupportedAnnotationTypes({"app.dev.ems.support.annotation.HBMModel"})
public class HBMModelProcessor extends AbstractProcessor {

    @Override
    public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
        Set<? extends Element> elements = roundEnv.getElementsAnnotatedWith(HBMModel.class);
        System.out.println(elements);
        return true;
    }

}
Run Code Online (Sandbox Code Playgroud)

现在如果我想调用流程方法,那我该怎么做呢?我可以通过以下方式完成:

HBMModelProcessor modelProcessor = new HBMModelProcessor();
modelProcessor.process(annotations, roundEnv)
Run Code Online (Sandbox Code Playgroud)

任何信息对我都非常有帮助.

谢谢.

java annotations annotation-processing

7
推荐指数
1
解决办法
2004
查看次数

如何使用@Target(ElementType.TYPE_USE)处理注释?

我正在实现一个注释处理器,以确保标记有注释的元素是实现某个接口的类的实例,或者是实现某个接口的类型的使用:

@Documented
@Target(value = { ElementType.PARAMETER, ElementType.TYPE_USE })
@Retention(value = RetentionPolicy.RUNTIME)
public @interface AuditSubject {

}

public interface Auditable {
    // methods that provide data for writing a log entry...
}

public class Report implements Auditable {

}
Run Code Online (Sandbox Code Playgroud)

对于带注释的元素,必须在方法执行后(使用AOP)创建日志条目.例子:

@CreateLogEntry
public Result persist(@AuditSubject Report newReport) {
    // A log entry must be created based on the incoming 'newReport' instance.    
}

@CreateLogEntry
public UpdateResult<@AuditSubject Report> update(Report update) {
    // A log entry must be created based on the updated report, which …
Run Code Online (Sandbox Code Playgroud)

java annotations annotation-processing java-8 annotation-processor

7
推荐指数
2
解决办法
581
查看次数

使用注释处理器时,IntelliJ 中的 Maven 项目构建失败(google/auto-value)

我使用google/auto-value在 maven 项目中创建不可变的值类。

<?xml version="1.0" encoding="UTF-8"?>
<project 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"
         xmlns="http://maven.apache.org/POM/4.0.0">
    <modelVersion>4.0.0</modelVersion>
    [...]
    <packaging>war</packaging>

    <properties>
        <auto-value.version>1.7</auto-value.version>
    </properties>

    <build>
        <plugins>
            <plugin>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.8.1</version>
                <configuration>
                    <annotationProcessorPaths>
                        <path>
                            <groupId>com.google.auto.value</groupId>
                            <artifactId>auto-value</artifactId>
                            <version>${auto-value.version}</version>
                        </path>
                    </annotationProcessorPaths>
                </configuration>
            </plugin>
        </plugins>
    </build>

    <dependencies>
        <dependency>
            <groupId>com.google.auto.value</groupId>
            <artifactId>auto-value-annotations</artifactId>
            <version>${auto-value.version}</version>
        </dependency>

        [...]

        <dependency>
            <groupId>org.junit.jupiter</groupId>
            <artifactId>junit-jupiter</artifactId>
            <version>5.5.2</version>
            <scope>test</scope>
        </dependency>
    </dependencies>
</project>
Run Code Online (Sandbox Code Playgroud)

这就像使用 CLI(例如mvn clean test)的魅力一样,但在 IntelliJ 项目构建期间会产生错误:

Error:java: java.lang.NoClassDefFoundError: com/google/auto/service/AutoService
com.google.auto.service.AutoService
Run Code Online (Sandbox Code Playgroud)

值得注意的是:正确的源代码生成到generated-sources/annotations/...但在这一步之后 IntelliJ 构建失败并且不会创建生成的测试源目录generated-test-sources/...

虽然可以通过将另一个注释处理器路径添加到 maven-compiler-plugin

<path>
    <groupId>com.google.auto.service</groupId>
    <artifactId>auto-service</artifactId>
    <version>1.0-rc6</version>
</path>
Run Code Online (Sandbox Code Playgroud)

此修复程序的缺点是auto-service在 …

intellij-idea maven annotation-processing auto-value

7
推荐指数
2
解决办法
1871
查看次数

正常处理TypeMirror和Class

我刚刚进入这里的javax AnnotationProcessing,并遇到了一个丑陋的案例.我将在一系列描述我学习过程的伪代码行中进行说明:

MyAnnotation ann = elementIfound.getAnnotation(MyAnnotation.class);
// Class<?> clazz = ann.getCustomClass();  // Can throw MirroredTypeException!
// Classes within the compilation unit don't exist in this form at compile time!

// Search web and find this alternative...

// Inspect all AnnotationMirrors
for (AnnotationMirror mirror : element.getAnnotationMirrors()) {
  if (mirror.getAnnotationType().toString().equals(annotationType.getName())) {
    // Inspect all methods on the Annotation class
    for (Entry<? extends ExecutableElement,? extends AnnotationValue> entry : mirror.getElementValues().entrySet()) {
      if (entry.getKey().getSimpleName().toString().equals(paramName)) {
        return (TypeMirror) entry.getValue();
      }
    }
    return null;
  }
}
return …
Run Code Online (Sandbox Code Playgroud)

java reflection annotation-processing

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

任何处理器都无法识别 AnnotationProcessor 选项

我写了一个注释处理器。用户可以传递一个选项作为处理器的参数。我也可以在我的注释处理器中读取这个参数。到目前为止一切顺利,一切都按预期进行!

但是,我从编译器收到警告,传递给注释处理器的选项尚未被任何注释处理器识别:

警告:以下选项未被任何处理器识别:'[fragmentArgsLib]'

实际上,我的处理器已成功识别并读取此选项:

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

    String fragementArgsLib = processingEnv.getOptions().get("fragmentArgsLib");
    ... 
}
Run Code Online (Sandbox Code Playgroud)

我想我必须手动说我已经使用这个选项来使这个编译器警告消失。你们中有人知道怎么做吗?

java annotation-processing

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

上一轮创建的类型为[生成的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
查看次数

Java 11 模块信息和注释处理器

我们如何提供带有 Java 11 模块的注释处理器?

要注册注释提供程序,我们需要以下模块信息条目:

import javax.annotation.processing.Processor;
import com.mycompany.mylib.impl.MyAnnotationProcessor;

module com.mycompany.mylib {

    provides Processor with MyAnnotationProcessor;

}
Run Code Online (Sandbox Code Playgroud)

现在,不幸的是,这是不是因为包装不够javax.annotation.processingjavax.lang.model.*javax.tools不是在java.base模块,但在java.compiler模块。

在 Java SE 8 中,一切都只在 JRE 中可用,但在 Java 11 中,我们可以选择只使用一个子集。随着jlink我们再可以创建更小的运行时间图像。

现在,当然,我可以将以下内容添加到模块信息中:

requires java.compiler;
Run Code Online (Sandbox Code Playgroud)

但这也会导致java.compiler成为自定义运行时映像的一部分。

但是注解处理有些特殊:它是在编译时运行的代码,而不是在运行时运行。因此它不应该是运行时映像的一部分。它应该只是编译时要求/依赖项。

有没有办法用 Java 11 模块系统解决这个问题?

java annotation-processing module-info

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

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
查看次数