mirror of https://github.com/apache/maven.git
Enhance DiIndexProcessor
Sort and *update* the file (in case of a partial build)
This commit is contained in:
parent
0c7e73335d
commit
bb99857f34
|
@ -29,67 +29,122 @@ import javax.tools.Diagnostic;
|
||||||
import javax.tools.FileObject;
|
import javax.tools.FileObject;
|
||||||
import javax.tools.StandardLocation;
|
import javax.tools.StandardLocation;
|
||||||
|
|
||||||
|
import java.io.BufferedReader;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.io.InputStreamReader;
|
||||||
|
import java.io.PrintWriter;
|
||||||
|
import java.io.StringWriter;
|
||||||
import java.io.Writer;
|
import java.io.Writer;
|
||||||
|
import java.util.HashSet;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
import java.util.TreeSet;
|
||||||
|
|
||||||
import org.apache.maven.api.di.Named;
|
import org.apache.maven.api.di.Named;
|
||||||
|
|
||||||
// Auto-register the annotation processor
|
|
||||||
@SupportedAnnotationTypes("org.apache.maven.api.di.Named")
|
@SupportedAnnotationTypes("org.apache.maven.api.di.Named")
|
||||||
@SupportedSourceVersion(SourceVersion.RELEASE_17)
|
@SupportedSourceVersion(SourceVersion.RELEASE_17)
|
||||||
public class DiIndexProcessor extends AbstractProcessor {
|
public class DiIndexProcessor extends AbstractProcessor {
|
||||||
|
|
||||||
|
private final Set<String> processedClasses = new HashSet<>();
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
|
public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
|
||||||
// Collect the fully qualified names of classes annotated with @Named
|
logMessage(
|
||||||
StringBuilder builder = new StringBuilder();
|
Diagnostic.Kind.NOTE, "Processing " + roundEnv.getRootElements().size() + " classes");
|
||||||
|
|
||||||
processingEnv
|
|
||||||
.getMessager()
|
|
||||||
.printMessage(
|
|
||||||
Diagnostic.Kind.NOTE,
|
|
||||||
"Processing " + roundEnv.getRootElements().size() + " classes");
|
|
||||||
|
|
||||||
for (Element element : roundEnv.getElementsAnnotatedWith(Named.class)) {
|
for (Element element : roundEnv.getElementsAnnotatedWith(Named.class)) {
|
||||||
if (element instanceof TypeElement typeElement) {
|
if (element instanceof TypeElement typeElement) {
|
||||||
// Get the fully qualified class name
|
String className = getFullClassName(typeElement);
|
||||||
String className = typeElement.getQualifiedName().toString();
|
processedClasses.add(className);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Handle inner classes by checking if the enclosing element is a class or interface
|
if (roundEnv.processingOver()) {
|
||||||
|
try {
|
||||||
|
updateFileIfChanged();
|
||||||
|
} catch (Exception e) {
|
||||||
|
logError("Error updating file", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private String getFullClassName(TypeElement typeElement) {
|
||||||
|
String className = typeElement.getQualifiedName().toString();
|
||||||
Element enclosingElement = typeElement.getEnclosingElement();
|
Element enclosingElement = typeElement.getEnclosingElement();
|
||||||
if (enclosingElement instanceof TypeElement) {
|
if (enclosingElement instanceof TypeElement) {
|
||||||
// It's an inner class, replace the last dot with a '$'
|
|
||||||
String enclosingClassName =
|
String enclosingClassName =
|
||||||
((TypeElement) enclosingElement).getQualifiedName().toString();
|
((TypeElement) enclosingElement).getQualifiedName().toString();
|
||||||
className = enclosingClassName + "$" + typeElement.getSimpleName();
|
className = enclosingClassName + "$" + typeElement.getSimpleName();
|
||||||
}
|
}
|
||||||
|
return className;
|
||||||
builder.append(className).append("\n");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!builder.isEmpty()) { // Check if the StringBuilder is non-empty
|
private void updateFileIfChanged() throws IOException {
|
||||||
|
String path = "META-INF/maven/org.apache.maven.api.di.Inject";
|
||||||
|
Set<String> existingClasses = new TreeSet<>(); // Using TreeSet for natural ordering
|
||||||
|
String existingContent = "";
|
||||||
|
|
||||||
|
// Try to read existing content
|
||||||
try {
|
try {
|
||||||
writeFile(builder.toString());
|
FileObject inputFile = processingEnv.getFiler().getResource(StandardLocation.CLASS_OUTPUT, "", path);
|
||||||
|
try (BufferedReader reader = new BufferedReader(new InputStreamReader(inputFile.openInputStream()))) {
|
||||||
|
String line;
|
||||||
|
StringBuilder contentBuilder = new StringBuilder();
|
||||||
|
while ((line = reader.readLine()) != null) {
|
||||||
|
if (!line.trim().startsWith("#")) {
|
||||||
|
existingClasses.add(line.trim());
|
||||||
|
}
|
||||||
|
contentBuilder.append(line).append("\n");
|
||||||
|
}
|
||||||
|
existingContent = contentBuilder.toString();
|
||||||
|
}
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
processingEnv
|
logMessage(Diagnostic.Kind.NOTE, "Unable to read existing file. Proceeding with empty content.");
|
||||||
.getMessager()
|
}
|
||||||
.printMessage(Diagnostic.Kind.ERROR, "Error writing file: " + e.getMessage());
|
|
||||||
|
Set<String> allClasses = new TreeSet<>(existingClasses); // Using TreeSet for natural ordering
|
||||||
|
allClasses.addAll(processedClasses);
|
||||||
|
|
||||||
|
StringBuilder newContentBuilder = new StringBuilder();
|
||||||
|
for (String className : allClasses) {
|
||||||
|
newContentBuilder.append(className).append("\n");
|
||||||
|
}
|
||||||
|
String newContent = newContentBuilder.toString();
|
||||||
|
|
||||||
|
if (!newContent.equals(existingContent)) {
|
||||||
|
logMessage(Diagnostic.Kind.NOTE, "Content has changed. Updating file.");
|
||||||
|
try {
|
||||||
|
FileObject outputFile =
|
||||||
|
processingEnv.getFiler().createResource(StandardLocation.CLASS_OUTPUT, "", path);
|
||||||
|
try (Writer writer = outputFile.openWriter()) {
|
||||||
|
writer.write(newContent);
|
||||||
|
}
|
||||||
|
} catch (IOException e) {
|
||||||
|
logError("Failed to write to file", e);
|
||||||
|
throw e; // Re-throw to ensure the compilation fails
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
logMessage(Diagnostic.Kind.NOTE, "Content unchanged. Skipping file update.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return true; // Indicate that annotations are claimed by this processor
|
private void logMessage(Diagnostic.Kind kind, String message) {
|
||||||
|
processingEnv.getMessager().printMessage(kind, message);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void writeFile(String content) throws IOException {
|
private void logError(String message, Exception e) {
|
||||||
// Create the file META-INF/maven/org.apache.maven.api.di.Inject
|
StringWriter sw = new StringWriter();
|
||||||
FileObject fileObject = processingEnv
|
PrintWriter pw = new PrintWriter(sw);
|
||||||
.getFiler()
|
e.printStackTrace(pw);
|
||||||
.createResource(StandardLocation.CLASS_OUTPUT, "", "META-INF/maven/org.apache.maven.api.di.Inject");
|
String stackTrace = sw.toString();
|
||||||
|
|
||||||
try (Writer writer = fileObject.openWriter()) {
|
String fullMessage = message + "\n" + "Exception: "
|
||||||
writer.write(content);
|
+ e.getClass().getName() + "\n" + "Message: "
|
||||||
}
|
+ e.getMessage() + "\n" + "Stack trace:\n"
|
||||||
|
+ stackTrace;
|
||||||
|
|
||||||
|
processingEnv.getMessager().printMessage(Diagnostic.Kind.ERROR, fullMessage);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue