I'm trying to write an annotation processor to insert methods and fields on a class... and the documentation is so sparse. I'm not getting far and I don't know if I'm approaching it correctly.
The processing environment provides a Filer object which has handy methods for creating new source and class files. Those work fine but then I tried to figure out how read the existing source files, and all it provides is "getResource". So in my Processor implementation I've done this:
@Override public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) { try { for (TypeElement te : annotations) { for (Element element : roundEnv.getElementsAnnotatedWith(te)) { FileObject in_file = processingEnv.getFiler().getResource( StandardLocation.SOURCE_PATH, "", element.asType().toString().replace(".", "/") + ".java"); FileObject out_file = processingEnv.getFiler().getResource( StandardLocation.SOURCE_OUTPUT, "", element.asType().toString().replace(".", "/") + ".java"); //if (out_file.getLastModified() >= in_file.getLastModified()) continue; CharSequence data = in_file.getCharContent(false); data = transform(data); // run the macro processor JavaFileObject out_file2 = processingEnv.getFiler().createSourceFile( element.asType().toString(), element); Writer w = out_file2.openWriter(); w.append(data); w.close(); } } } catch (Exception e) { e.printStackTrace(); processingEnv.getMessager().printMessage(Diagnostic.Kind.ERROR, e.getMessage()); } return true; } My first quandary is I can't help feeling that element.asType().toString().replace(".", "/") + ".java" (to get the qualified type name and convert it into a package and source file path) is not a nice way to approach the problem. The rest of the API is so over-engineered but there doesn't seem to be a handy method for retrieving the original source code.
The real problem is that then the compiler gets spontaneously upset by the second source file in the output directory ("error: duplicate class") and now I'm stuck.
I've already written the rest of this -- a macro lexer and parser and whatnot for calculating some data and inserting the field values and methods -- but it operates as a initial step outside the compiler. Except for the fact that the original files cannot have a .java extension (to prevent the compiler seeing them), this works nicely. Then I heard that annotations can do code generation, which I assume will be more proper and convenient, but I can't find much guidance on it.