Skip to content

Commit

Permalink
jooby apt: more logging ref #2968
Browse files Browse the repository at this point in the history
  • Loading branch information
jknack committed Jun 9, 2024
1 parent 7d28303 commit 4ad95f1
Show file tree
Hide file tree
Showing 7 changed files with 78 additions and 65 deletions.
74 changes: 40 additions & 34 deletions modules/jooby-apt/src/main/java/io/jooby/apt/JoobyProcessor.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,64 +5,59 @@
*/
package io.jooby.apt;

import static io.jooby.apt.JoobyProcessor.Options.*;
import static java.util.Optional.ofNullable;

import java.io.IOException;
import java.io.PrintWriter;
import java.util.*;
import java.util.function.Consumer;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import javax.annotation.processing.*;
import javax.lang.model.SourceVersion;
import javax.lang.model.element.*;
import javax.lang.model.type.DeclaredType;
import javax.tools.Diagnostic;
import javax.tools.StandardLocation;

import com.squareup.javapoet.JavaFile;
import io.jooby.internal.apt.*;

@SupportedOptions({
JoobyProcessor.Options.OPT_DEBUG,
JoobyProcessor.Options.OPT_INCREMENTAL,
JoobyProcessor.Options.OPT_SERVICES,
JoobyProcessor.Options.OPT_SKIP_ATTRIBUTE_ANNOTATIONS
})
@SupportedOptions({DEBUG, INCREMENTAL, SERVICES, SKIP_ATTRIBUTE_ANNOTATIONS})
@SupportedSourceVersion(SourceVersion.RELEASE_17)
public class JoobyProcessor extends AbstractProcessor {
public interface Options {
String OPT_ROUTER_PREFIX = "jooby.routerPrefix";
String OPT_ROUTER_SUFFIX = "jooby.routerSuffix";
String OPT_DEBUG = "jooby.debug";
String OPT_INCREMENTAL = "jooby.incremental";
String OPT_SERVICES = "jooby.services";
String OPT_SKIP_ATTRIBUTE_ANNOTATIONS = "jooby.skipAttributeAnnotations";
String DEBUG = "jooby.debug";
String ROUTER_PREFIX = "jooby.routerPrefix";
String ROUTER_SUFFIX = "jooby.routerSuffix";
String INCREMENTAL = "jooby.incremental";
String SERVICES = "jooby.services";
String SKIP_ATTRIBUTE_ANNOTATIONS = "jooby.skipAttributeAnnotations";

static boolean boolOpt(
ProcessingEnvironment processingEnvironment, String option, boolean defaultValue) {
static boolean boolOpt(ProcessingEnvironment environment, String option, boolean defaultValue) {
return Boolean.parseBoolean(
processingEnvironment.getOptions().getOrDefault(option, String.valueOf(defaultValue)));
environment.getOptions().getOrDefault(option, String.valueOf(defaultValue)));
}

static String[] stringListOpt(
ProcessingEnvironment processingEnvironment, String option, String defaultValue) {
String value = processingEnvironment.getOptions().getOrDefault(option, defaultValue);
return value == null || value.isEmpty() ? new String[0] : value.split(",");
static List<String> stringListOpt(ProcessingEnvironment environment, String option) {
String value = string(environment, option, null);
return value == null || value.isEmpty() ? List.of() : List.of(value.split(","));
}

static String string(
ProcessingEnvironment processingEnvironment, String option, String defaultValue) {
String value = processingEnvironment.getOptions().getOrDefault(option, defaultValue);
static String string(ProcessingEnvironment environment, String option, String defaultValue) {
String value = environment.getOptions().getOrDefault(option, defaultValue);
return value == null || value.isEmpty() ? defaultValue : value;
}
}

private MvcContext context;
private Messager messager;
private Consumer<String> output;
private final Set<Object> processed = new HashSet<>();

public JoobyProcessor(Messager messager) {
this.messager = messager;
public JoobyProcessor(Consumer<String> output) {
this.output = output;
}

public JoobyProcessor() {}
Expand All @@ -72,15 +67,21 @@ public synchronized void init(ProcessingEnvironment processingEnvironment) {
this.context =
new MvcContext(
processingEnvironment,
ofNullable(messager).orElse(processingEnvironment.getMessager()));
ofNullable(output)
.orElseGet(
() ->
message ->
processingEnvironment
.getMessager()
.printMessage(Diagnostic.Kind.OTHER, message)));
super.init(processingEnvironment);
}

@Override
public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
context.debug("round #%s", context.nextRound());

if (roundEnv.processingOver()) {
context.debug("Output:");
context.getRouters().forEach(it -> context.debug(" %s.java", it.getGeneratedType()));
if (context.generateServices()) {
doServices(context.getProcessingEnvironment().getFiler(), context.getRouters());
}
Expand All @@ -92,7 +93,8 @@ public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment
try {
var javaFile = router.toSourceCode();
onGeneratedSource(javaFile);
context.debug("%s", router.getTargetType());
context.debug("router %s: %s", router.getTargetType(), router.getGeneratedType());
router.getRoutes().forEach(it -> context.debug(" %s", it));
javaFile.writeTo(filer);
context.add(router);
} catch (IOException cause) {
Expand All @@ -108,12 +110,12 @@ protected void onGeneratedSource(JavaFile source) {}
private void doServices(Filer filer, List<MvcRouter> routers) {
try {
var location = "META-INF/services/io.jooby.MvcFactory";
context.debug("%s", location);
context.debug(location);

var resource = filer.createResource(StandardLocation.CLASS_OUTPUT, "", location);
var content = new StringBuilder();
for (var router : routers) {
String classname = router.getGeneratedType();
var classname = router.getGeneratedType();
context.debug(" %s", classname);
content.append(classname).append(System.lineSeparator());
}
Expand All @@ -130,10 +132,12 @@ private Map<TypeElement, MvcRouter> buildRouteRegistry(
Map<TypeElement, MvcRouter> registry = new LinkedHashMap<>();

for (var annotation : annotations) {
context.debug("found annotation: %s", annotation);
var elements = roundEnv.getElementsAnnotatedWith(annotation);
// Element could be Class or Method, bc @Path can be applied to both of them
// Also we need to expand lookup to external jars see #2486
for (var element : elements) {
context.debug(" %s", element);
if (element instanceof TypeElement typeElement) {
buildRouteRegistry(registry, typeElement);
} else if (element instanceof ExecutableElement method) {
Expand Down Expand Up @@ -188,7 +192,7 @@ private void buildRouteRegistry(Map<TypeElement, MvcRouter> registry, TypeElemen
.forEach(
method -> {
if (method.getModifiers().contains(Modifier.ABSTRACT)) {
context.debug("ignoring abstract method %s", superType, method);
context.debug("ignoring abstract method: %s %s", superType, method);
} else {
method.getAnnotationMirrors().stream()
.map(AnnotationMirror::getAnnotationType)
Expand Down Expand Up @@ -220,8 +224,10 @@ private void buildRouteRegistry(Map<TypeElement, MvcRouter> registry, TypeElemen

@Override
public Set<String> getSupportedAnnotationTypes() {
return Stream.concat(HttpPath.PATH.getAnnotations().stream(), HttpMethod.annotations().stream())
.collect(Collectors.toSet());
var supportedTypes = new HashSet<String>();
supportedTypes.addAll(HttpPath.PATH.getAnnotations());
supportedTypes.addAll(HttpMethod.annotations());
return supportedTypes;
}

@Override
Expand Down
39 changes: 13 additions & 26 deletions modules/jooby-apt/src/main/java/io/jooby/apt/MvcContext.java
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,10 @@
package io.jooby.apt;

import java.util.*;
import java.util.function.Consumer;

import javax.annotation.processing.Messager;
import javax.annotation.processing.ProcessingEnvironment;
import javax.lang.model.element.*;
import javax.tools.Diagnostic;

import io.jooby.apt.JoobyProcessor.Options;
import io.jooby.internal.apt.HttpMethod;
Expand All @@ -28,18 +27,17 @@ public class MvcContext {
private final boolean services;
private final String routerPrefix;
private final String routerSuffix;
private int round;
private final Messager messager;
private final Consumer<String> output;
private final List<MvcRouter> routers = new ArrayList<>();

public MvcContext(ProcessingEnvironment processingEnvironment, Messager messager) {
public MvcContext(ProcessingEnvironment processingEnvironment, Consumer<String> output) {
this.processingEnvironment = processingEnvironment;
this.messager = messager;
this.debug = Options.boolOpt(processingEnvironment, Options.OPT_DEBUG, false);
this.incremental = Options.boolOpt(processingEnvironment, Options.OPT_INCREMENTAL, true);
this.services = Options.boolOpt(processingEnvironment, Options.OPT_SERVICES, true);
this.routerPrefix = Options.string(processingEnvironment, Options.OPT_ROUTER_PREFIX, "");
this.routerSuffix = Options.string(processingEnvironment, Options.OPT_ROUTER_SUFFIX, "_");
this.output = output;
this.debug = Options.boolOpt(processingEnvironment, Options.DEBUG, false);
this.incremental = Options.boolOpt(processingEnvironment, Options.INCREMENTAL, true);
this.services = Options.boolOpt(processingEnvironment, Options.SERVICES, true);
this.routerPrefix = Options.string(processingEnvironment, Options.ROUTER_PREFIX, "");
this.routerSuffix = Options.string(processingEnvironment, Options.ROUTER_SUFFIX, "_");

debug("Incremental annotation processing is turned %s.", incremental ? "ON" : "OFF");
debug("Generation of service provider configuration is turned %s.", services ? "ON" : "OFF");
Expand Down Expand Up @@ -132,25 +130,14 @@ public boolean isServices() {
return services;
}

public int nextRound() {
return ++round;
}

public void debug(String message, Object... args) {
if (debug) {
print(Diagnostic.Kind.NOTE, message, args);
info(message, args);
}
}

private void print(Diagnostic.Kind kind, String message, Object... args) {
Element originatingElement = null;
Object[] arguments = args;
if (args.length > 0 && args[args.length - 1] instanceof Element element) {
originatingElement = element;
arguments = new Object[args.length - 1];
System.arraycopy(arguments, 0, arguments, 0, arguments.length);
}
var msg = message.formatted(arguments);
messager.printMessage(kind, msg, originatingElement);
public void info(String message, Object... args) {
var msg = args.length == 0 ? message : message.formatted(args);
output.accept(msg);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -228,7 +228,12 @@ public String toString() {
}
buffer.append(") ");
}
buffer.append(method.getSimpleName()).append("()").append(" {}");
buffer
.append(method.getSimpleName())
.append("(")
.append(String.join(", ", getRawParameterTypes()))
.append("): ")
.append(getReturnType());
return buffer.toString();
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
*/
package io.jooby.internal.apt;

import static io.jooby.apt.JoobyProcessor.Options.SKIP_ATTRIBUTE_ANNOTATIONS;

import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.*;
Expand Down Expand Up @@ -49,8 +51,7 @@ public RouteAttributesGenerator(MvcContext context) {
var environment = context.getProcessingEnvironment();
this.elements = environment.getElementUtils();
this.types = environment.getTypeUtils();
this.skip =
List.of(Options.stringListOpt(environment, Options.OPT_SKIP_ATTRIBUTE_ANNOTATIONS, ""));
this.skip = Options.stringListOpt(environment, SKIP_ATTRIBUTE_ANNOTATIONS);
}

public Optional<String> toSourceCode(MvcRoute route, String indent) {
Expand Down
13 changes: 13 additions & 0 deletions modules/jooby-apt/src/test/java/io/jooby/apt/ProcessorRunner.java
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
import java.util.stream.Stream;

import javax.annotation.processing.Messager;
import javax.annotation.processing.ProcessingEnvironment;
import javax.lang.model.element.AnnotationMirror;
import javax.lang.model.element.AnnotationValue;
import javax.lang.model.element.Element;
Expand Down Expand Up @@ -68,6 +69,12 @@ public HookJoobyProcessor() {
super(new ConsoleMessager());
}

@Override
public synchronized void init(ProcessingEnvironment processingEnvironment) {
super.init(processingEnvironment);
((ConsoleMessager) messager).setProcessingEnvironment(processingEnvironment);
}

public GeneratedSourceClassLoader createClassLoader() {
Objects.requireNonNull(source);
return new GeneratedSourceClassLoader(getClass().getClassLoader(), source);
Expand All @@ -84,6 +91,8 @@ protected void onGeneratedSource(JavaFile source) {
}

private static class ConsoleMessager implements Messager {
private ProcessingEnvironment processingEnvironment;

@Override
public void printMessage(Diagnostic.Kind kind, CharSequence msg) {
println(kind, msg);
Expand Down Expand Up @@ -118,6 +127,10 @@ private void println(Diagnostic.Kind kind, CharSequence message, Object... args)
.map(Objects::toString)
.collect(Collectors.joining(" ")));
}

public void setProcessingEnvironment(ProcessingEnvironment processingEnvironment) {
this.processingEnvironment = processingEnvironment;
}
}

private final HookJoobyProcessor processor = new HookJoobyProcessor();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ public void generateCustomName() throws Exception {
+ suffix;
new ProcessorRunner(
new CustomRouterName(),
Map.of("jooby.routerPrefix", prefix, "jooby.routerSuffix", suffix))
Map.of("jooby.routerPrefix", prefix, "jooby.routerSuffix", suffix, "jooby.debug", true))
.withRouter(
(app, source) -> {
assertEquals(expectedClassName, source.packageName + "." + source.typeSpec.name);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
import java.lang.reflect.Type;
import java.util.function.BiFunction;

import edu.umd.cs.findbugs.annotations.NonNull;
import io.jooby.Context;
import io.jooby.Reified;
import io.jooby.ResultHandler;
Expand Down Expand Up @@ -41,7 +42,7 @@ public boolean isReactive() {
}

@Override
public Filter create() {
public @NonNull Filter create() {
return new JStachioHandler(jstachio, buffer, contextFunction);
}
}

0 comments on commit 4ad95f1

Please sign in to comment.