|
|
@ -25,6 +25,7 @@ import javax.annotation.processing.RoundEnvironment; |
|
|
|
import javax.lang.model.SourceVersion; |
|
|
|
import javax.lang.model.SourceVersion; |
|
|
|
import javax.lang.model.element.AnnotationValue; |
|
|
|
import javax.lang.model.element.AnnotationValue; |
|
|
|
import javax.lang.model.element.Element; |
|
|
|
import javax.lang.model.element.Element; |
|
|
|
|
|
|
|
import javax.lang.model.element.ElementKind; |
|
|
|
import javax.lang.model.element.TypeElement; |
|
|
|
import javax.lang.model.element.TypeElement; |
|
|
|
import javax.lang.model.type.DeclaredType; |
|
|
|
import javax.lang.model.type.DeclaredType; |
|
|
|
import javax.lang.model.type.TypeKind; |
|
|
|
import javax.lang.model.type.TypeKind; |
|
|
@ -32,6 +33,7 @@ import javax.lang.model.type.TypeMirror; |
|
|
|
import javax.tools.Diagnostic; |
|
|
|
import javax.tools.Diagnostic; |
|
|
|
import java.lang.reflect.Constructor; |
|
|
|
import java.lang.reflect.Constructor; |
|
|
|
import java.util.ArrayList; |
|
|
|
import java.util.ArrayList; |
|
|
|
|
|
|
|
import java.util.Collections; |
|
|
|
import java.util.HashMap; |
|
|
|
import java.util.HashMap; |
|
|
|
import java.util.HashSet; |
|
|
|
import java.util.HashSet; |
|
|
|
import java.util.List; |
|
|
|
import java.util.List; |
|
|
@ -60,7 +62,7 @@ public class ExtensionAnnotationProcessor extends AbstractProcessor { |
|
|
|
public synchronized void init(ProcessingEnvironment processingEnv) { |
|
|
|
public synchronized void init(ProcessingEnvironment processingEnv) { |
|
|
|
super.init(processingEnv); |
|
|
|
super.init(processingEnv); |
|
|
|
|
|
|
|
|
|
|
|
info("%s init", ExtensionAnnotationProcessor.class); |
|
|
|
info("%s init", ExtensionAnnotationProcessor.class.getName()); |
|
|
|
|
|
|
|
|
|
|
|
initStorage(); |
|
|
|
initStorage(); |
|
|
|
} |
|
|
|
} |
|
|
@ -72,10 +74,7 @@ public class ExtensionAnnotationProcessor extends AbstractProcessor { |
|
|
|
|
|
|
|
|
|
|
|
@Override |
|
|
|
@Override |
|
|
|
public Set<String> getSupportedAnnotationTypes() { |
|
|
|
public Set<String> getSupportedAnnotationTypes() { |
|
|
|
Set<String> annotationTypes = new HashSet<>(); |
|
|
|
return Collections.singleton("*"); |
|
|
|
annotationTypes.add(Extension.class.getName()); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return annotationTypes; |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
@Override |
|
|
|
@Override |
|
|
@ -92,33 +91,26 @@ public class ExtensionAnnotationProcessor extends AbstractProcessor { |
|
|
|
return false; |
|
|
|
return false; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
info("Processing @%s", Extension.class); |
|
|
|
info("Processing @%s", Extension.class.getName()); |
|
|
|
for (Element element : roundEnv.getElementsAnnotatedWith(Extension.class)) { |
|
|
|
for (Element element : roundEnv.getElementsAnnotatedWith(Extension.class)) { |
|
|
|
// check if @Extension is put on class and not on method or constructor
|
|
|
|
if (element.getKind() != ElementKind.ANNOTATION_TYPE) { |
|
|
|
if (!(element instanceof TypeElement)) { |
|
|
|
processExtensionElement(element); |
|
|
|
error(element, "Put annotation only on classes (no methods, no fields)"); |
|
|
|
|
|
|
|
continue; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// check if class extends/implements an extension point
|
|
|
|
|
|
|
|
if (!isExtension(element.asType())) { |
|
|
|
|
|
|
|
error(element, "%s is not an extension (it doesn't implement ExtensionPoint)", element); |
|
|
|
|
|
|
|
continue; |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
TypeElement extensionElement = (TypeElement) element; |
|
|
|
// collect nested extension annotations
|
|
|
|
// Extension annotation = element.getAnnotation(Extension.class);
|
|
|
|
List<TypeElement> extensionAnnotations = new ArrayList<>(); |
|
|
|
List<TypeElement> extensionPointElements = findExtensionPoints(extensionElement); |
|
|
|
for (TypeElement annotation : annotations) { |
|
|
|
if (extensionPointElements.isEmpty()) { |
|
|
|
if (ClassUtils.getAnnotationMirror(annotation, Extension.class) != null) { |
|
|
|
// TODO throw error ?
|
|
|
|
extensionAnnotations.add(annotation); |
|
|
|
continue; |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
String extension = getBinaryName(extensionElement); |
|
|
|
// process nested extension annotations
|
|
|
|
for (TypeElement extensionPointElement : extensionPointElements) { |
|
|
|
for (TypeElement te : extensionAnnotations) { |
|
|
|
String extensionPoint = getBinaryName(extensionPointElement); |
|
|
|
info("Processing @%s", te); |
|
|
|
Set<String> extensionPoints = extensions.computeIfAbsent(extensionPoint, k -> new TreeSet<>()); |
|
|
|
for (Element element : roundEnv.getElementsAnnotatedWith(te)) { |
|
|
|
extensionPoints.add(extension); |
|
|
|
processExtensionElement(element); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
@ -250,4 +242,32 @@ public class ExtensionAnnotationProcessor extends AbstractProcessor { |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private void processExtensionElement(Element element) { |
|
|
|
|
|
|
|
// check if @Extension is put on class and not on method or constructor
|
|
|
|
|
|
|
|
if (!(element instanceof TypeElement)) { |
|
|
|
|
|
|
|
error(element, "Put annotation only on classes (no methods, no fields)"); |
|
|
|
|
|
|
|
return; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// check if class extends/implements an extension point
|
|
|
|
|
|
|
|
if (!isExtension(element.asType())) { |
|
|
|
|
|
|
|
error(element, "%s is not an extension (it doesn't implement ExtensionPoint)", element); |
|
|
|
|
|
|
|
return; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
TypeElement extensionElement = (TypeElement) element; |
|
|
|
|
|
|
|
List<TypeElement> extensionPointElements = findExtensionPoints(extensionElement); |
|
|
|
|
|
|
|
if (extensionPointElements.isEmpty()) { |
|
|
|
|
|
|
|
error(element, "No extension points found for extension %s", extensionElement); |
|
|
|
|
|
|
|
return; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
String extension = getBinaryName(extensionElement); |
|
|
|
|
|
|
|
for (TypeElement extensionPointElement : extensionPointElements) { |
|
|
|
|
|
|
|
String extensionPoint = getBinaryName(extensionPointElement); |
|
|
|
|
|
|
|
Set<String> extensionPoints = extensions.computeIfAbsent(extensionPoint, k -> new TreeSet<>()); |
|
|
|
|
|
|
|
extensionPoints.add(extension); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|