Skip to content

Commit

Permalink
Found another ECJ Annotation Processor Bug
Browse files Browse the repository at this point in the history
  • Loading branch information
guw committed Feb 29, 2024
1 parent 7e175dc commit 968fb8f
Show file tree
Hide file tree
Showing 10 changed files with 180 additions and 1 deletion.
3 changes: 2 additions & 1 deletion ecj-test/.gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,5 @@ remotejdk*
zulu*
*.jar
*.tar.gz
bin/
bin*/
src-gen/
11 changes: 11 additions & 0 deletions ecj-test/compile-proc.params
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
-d
bin-proc
-s
src-gen
-verbose
--release
11
src-proc/sample/processor/api/GeneratedResourceFamilyDefinition.java
src-proc/sample/processor/api/WrapperDefinition.java
src-proc/sample/processor/api/ResourceDefinition.java
src-proc/sample/processor/GeneratorAnnotationProcessor.java
16 changes: 16 additions & 0 deletions ecj-test/compile-procsample.params
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
-d
bin
-s
src-gen
-verbose
--release
11
-processorpath
bin-proc
-processor
sample.processor.GeneratorAnnotationProcessor
-classpath
bin-proc
src/sample/processor/usage/testing/ITestResource.java
src/sample/processor/usage/checks/ISomeChecks.java
src/sample/processor/usage/MyResources.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
package sample.processor;

import java.io.IOException;
import java.io.PrintWriter;
import java.util.Set;

import javax.annotation.processing.AbstractProcessor;
import javax.annotation.processing.RoundEnvironment;
import javax.annotation.processing.SupportedAnnotationTypes;
import javax.annotation.processing.SupportedSourceVersion;
import javax.lang.model.SourceVersion;
import javax.lang.model.element.Element;
import javax.lang.model.element.PackageElement;
import javax.lang.model.element.TypeElement;
import javax.tools.JavaFileObject;

import sample.processor.api.GeneratedResourceFamilyDefinition;

@SupportedAnnotationTypes({ "sample.processor.api.GeneratedResourceFamilyDefinition",
"sample.processor.api.WrapperDefinition", "sample.processor.api.ResourceDefinition" })
@SupportedSourceVersion(SourceVersion.RELEASE_8)
public class GeneratorAnnotationProcessor extends AbstractProcessor {

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

for (TypeElement annotation : annotations) {
Set<? extends Element> annotatedElements = roundEnv.getElementsAnnotatedWith(annotation);

for (Element element : annotatedElements) {
GeneratedResourceFamilyDefinition annotation2 = element
.getAnnotation(GeneratedResourceFamilyDefinition.class);
if (annotation2 != null) {
String wrapperClassName = annotation2.wrapper().className();
if (wrapperClassName == null || wrapperClassName.trim().isEmpty())
continue;

try {
writeWrapperFile(wrapperClassName, (TypeElement) element);
} catch (IOException e) {
throw new IllegalStateException("Unable to generate output. " + e.getMessage(), e);
}
}

}
}

return true;
}

private void writeWrapperFile(String simpleClassName, TypeElement annotatedElement) throws IOException {
String packageName = ((PackageElement) annotatedElement.getEnclosingElement()).getQualifiedName() + ".wrappers";

String wrapperClassName = packageName + "." + simpleClassName;
JavaFileObject builderFile = processingEnv.getFiler().createSourceFile(wrapperClassName, annotatedElement);

try (PrintWriter out = new PrintWriter(builderFile.openWriter())) {

out.print("package ");
out.print(packageName);
out.println(";");
out.println();

out.print("public class ");
out.print(simpleClassName);
out.println(" {");
out.println();

out.println("}");
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package sample.processor.api;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE})
public @interface GeneratedResourceFamilyDefinition {

Class<?> feature();

WrapperDefinition wrapper() default @WrapperDefinition(className="");

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package sample.processor.api;

public @interface ResourceDefinition {

Class<?> family();

String[] checks() default {};

}
16 changes: 16 additions & 0 deletions ecj-test/src-proc/sample/processor/api/WrapperDefinition.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package sample.processor.api;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface WrapperDefinition {

/**
* name of the wrapper class to generate.
*/
String className();
}
13 changes: 13 additions & 0 deletions ecj-test/src/sample/processor/usage/MyResources.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package sample.processor.usage;

import sample.processor.api.GeneratedResourceFamilyDefinition;
import sample.processor.api.WrapperDefinition;
import sample.processor.usage.testing.ITestResource;

@GeneratedResourceFamilyDefinition(wrapper = @WrapperDefinition(className = "MyResourceWrapperForTesting"), feature = ITestResource.class)
public class MyResources {

public void doSomething() {
// whatever
}
}
6 changes: 6 additions & 0 deletions ecj-test/src/sample/processor/usage/checks/ISomeChecks.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
package sample.processor.usage.checks;

public interface ISomeChecks {
public final static String CHECK_FOO = "Is Foo Present";
public final static String CHECK_BAR = "Is Bar Absent";
}
19 changes: 19 additions & 0 deletions ecj-test/src/sample/processor/usage/testing/ITestResource.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package sample.processor.usage.testing;

import sample.processor.api.ResourceDefinition;
import sample.processor.usage.MyResources;
import sample.processor.usage.checks.ISomeChecks;
import sample.processor.usage.wrappers.MyResourceWrapperForTesting;

/**
* A Test resource
*/
@ResourceDefinition(family = MyResources.class, checks = { ISomeChecks.CHECK_FOO })
public interface ITestResource {

/**
* For testing use the generated {@link MyResourceWrapperForTesting}
*/
String TEST_NAME = "foobar";

}

0 comments on commit 968fb8f

Please sign in to comment.