From 3d554b6284836ff81c788c3f174aa5cf471027bc Mon Sep 17 00:00:00 2001 From: Tomas Langer Date: Tue, 22 Aug 2023 14:51:17 +0200 Subject: [PATCH 1/2] Interceptor creator now uses TypeName (and related changes) --- .../CircuitBreakerMethodCreator.java | 4 +- .../processor/FallbackMethodCreator.java | 4 +- .../processor/RetryMethodCreator.java | 4 +- .../http/processor/HttpEndpointCreator.java | 4 +- .../http/processor/HttpMethodCreator.java | 14 +- .../processor/CustomAnnotationProcessor.java | 8 +- .../InjectionAnnotationProcessor.java | 4 +- .../ExtensibleGetTemplateProducer.java | 4 +- .../interceptor/InterceptorRuntimeTest.java | 4 +- .../expected/ximpl-interceptor._java_ | 12 +- .../expected/yimpl-interceptor._java_ | 128 +++++++----- .../tools/InterceptedElementBlueprint.java | 3 +- .../tools/InterceptionPlanBlueprint.java | 2 +- .../tools/InterceptorCreatorDefault.java | 196 +++++++++--------- .../spi/CustomAnnotationTemplateCreator.java | 3 +- .../inject/tools/spi/InterceptorCreator.java | 33 ++- .../default/interface-based-interceptor.hbs | 2 - .../default/no-arg-based-interceptor.hbs | 2 - .../tools/InterceptorCreatorDefaultTest.java | 13 +- 19 files changed, 231 insertions(+), 213 deletions(-) diff --git a/fault-tolerance/processor/src/main/java/io/helidon/faulttolerance/processor/CircuitBreakerMethodCreator.java b/fault-tolerance/processor/src/main/java/io/helidon/faulttolerance/processor/CircuitBreakerMethodCreator.java index c5730a5b0c6..bf168822176 100644 --- a/fault-tolerance/processor/src/main/java/io/helidon/faulttolerance/processor/CircuitBreakerMethodCreator.java +++ b/fault-tolerance/processor/src/main/java/io/helidon/faulttolerance/processor/CircuitBreakerMethodCreator.java @@ -52,8 +52,8 @@ public CircuitBreakerMethodCreator() { } @Override - public Set annoTypes() { - return Set.of(FT_ANNOTATION); + public Set annoTypes() { + return Set.of(FT_ANNOTATION_TYPE); } @Override diff --git a/fault-tolerance/processor/src/main/java/io/helidon/faulttolerance/processor/FallbackMethodCreator.java b/fault-tolerance/processor/src/main/java/io/helidon/faulttolerance/processor/FallbackMethodCreator.java index 2211ed5c798..9d03e7fca87 100644 --- a/fault-tolerance/processor/src/main/java/io/helidon/faulttolerance/processor/FallbackMethodCreator.java +++ b/fault-tolerance/processor/src/main/java/io/helidon/faulttolerance/processor/FallbackMethodCreator.java @@ -53,8 +53,8 @@ public FallbackMethodCreator() { } @Override - public Set annoTypes() { - return Set.of(FALLBACK_ANNOTATION); + public Set annoTypes() { + return Set.of(FALLBACK_ANNOTATION_TYPE); } @Override diff --git a/fault-tolerance/processor/src/main/java/io/helidon/faulttolerance/processor/RetryMethodCreator.java b/fault-tolerance/processor/src/main/java/io/helidon/faulttolerance/processor/RetryMethodCreator.java index 4492e9565a7..2336f3b86e8 100644 --- a/fault-tolerance/processor/src/main/java/io/helidon/faulttolerance/processor/RetryMethodCreator.java +++ b/fault-tolerance/processor/src/main/java/io/helidon/faulttolerance/processor/RetryMethodCreator.java @@ -52,8 +52,8 @@ public RetryMethodCreator() { } @Override - public Set annoTypes() { - return Set.of(RETRY_ANNOTATION); + public Set annoTypes() { + return Set.of(RETRY_ANNOTATION_TYPE); } @Override diff --git a/http/processor/src/main/java/io/helidon/http/processor/HttpEndpointCreator.java b/http/processor/src/main/java/io/helidon/http/processor/HttpEndpointCreator.java index 99a51902419..22ebe9c12e7 100644 --- a/http/processor/src/main/java/io/helidon/http/processor/HttpEndpointCreator.java +++ b/http/processor/src/main/java/io/helidon/http/processor/HttpEndpointCreator.java @@ -45,8 +45,8 @@ public HttpEndpointCreator() { } @Override - public Set annoTypes() { - return Set.of(PATH_ANNOTATION); + public Set annoTypes() { + return Set.of(TypeName.create(PATH_ANNOTATION)); } @Override diff --git a/http/processor/src/main/java/io/helidon/http/processor/HttpMethodCreator.java b/http/processor/src/main/java/io/helidon/http/processor/HttpMethodCreator.java index 0eebb944882..42f8060e53b 100644 --- a/http/processor/src/main/java/io/helidon/http/processor/HttpMethodCreator.java +++ b/http/processor/src/main/java/io/helidon/http/processor/HttpMethodCreator.java @@ -66,13 +66,13 @@ public HttpMethodCreator() { } @Override - public Set annoTypes() { - return Set.of(GET_ANNOTATION, - HEADER_PARAM_ANNOTATION, - HTTP_METHOD_ANNOTATION, - POST_ANNOTATION, - PATH_ANNOTATION, - QUERY_PARAM_ANNOTATION); + public Set annoTypes() { + return Set.of(TypeName.create(GET_ANNOTATION), + TypeName.create(HEADER_PARAM_ANNOTATION), + TypeName.create(HTTP_METHOD_ANNOTATION), + TypeName.create(POST_ANNOTATION), + TypeName.create(PATH_ANNOTATION), + TypeName.create(QUERY_PARAM_ANNOTATION)); } @Override diff --git a/inject/processor/src/main/java/io/helidon/inject/processor/CustomAnnotationProcessor.java b/inject/processor/src/main/java/io/helidon/inject/processor/CustomAnnotationProcessor.java index e9db98c704c..e1193194750 100644 --- a/inject/processor/src/main/java/io/helidon/inject/processor/CustomAnnotationProcessor.java +++ b/inject/processor/src/main/java/io/helidon/inject/processor/CustomAnnotationProcessor.java @@ -78,9 +78,9 @@ static List initialize() { List creators = HelidonServiceLoader.create(loader()).asList(); creators.forEach(creator -> { try { - Set annoTypes = creator.annoTypes(); + Set annoTypes = creator.annoTypes(); annoTypes.forEach(annoType -> { - PRODUCERS_BY_ANNOTATION.compute(TypeName.create(annoType), (k, v) -> { + PRODUCERS_BY_ANNOTATION.compute(annoType, (k, v) -> { if (v == null) { v = new LinkedHashSet<>(); } @@ -88,7 +88,9 @@ static List initialize() { return v; }); }); - ALL_ANNO_TYPES_HANDLED.addAll(annoTypes); + ALL_ANNO_TYPES_HANDLED.addAll(annoTypes.stream() + .map(TypeName::fqName) + .toList()); } catch (Throwable t) { System.Logger logger = System.getLogger(CustomAnnotationProcessor.class.getName()); ToolsException te = new ToolsException("Failed to initialize: " + creator, t); diff --git a/inject/processor/src/main/java/io/helidon/inject/processor/InjectionAnnotationProcessor.java b/inject/processor/src/main/java/io/helidon/inject/processor/InjectionAnnotationProcessor.java index e88299125ce..7d70ca433f4 100644 --- a/inject/processor/src/main/java/io/helidon/inject/processor/InjectionAnnotationProcessor.java +++ b/inject/processor/src/main/java/io/helidon/inject/processor/InjectionAnnotationProcessor.java @@ -644,8 +644,8 @@ private void processInterceptors(ServicesToProcess services, InterceptorCreator.InterceptorProcessor processor = interceptorCreator.createInterceptorProcessor( interceptedServiceInfo, interceptorCreator, - Optional.of(processingEnv)); - Set annotationTypeTriggers = processor.allAnnotationTypeTriggers(); + processingEnv); + Set annotationTypeTriggers = processor.allAnnotationTypeTriggers(); if (annotationTypeTriggers.isEmpty()) { services.addInterceptorPlanFor(serviceTypeName, Optional.empty()); return; diff --git a/inject/processor/src/test/java/io/helidon/inject/processor/ExtensibleGetTemplateProducer.java b/inject/processor/src/test/java/io/helidon/inject/processor/ExtensibleGetTemplateProducer.java index 6feddbb3ccf..a31259e7324 100644 --- a/inject/processor/src/test/java/io/helidon/inject/processor/ExtensibleGetTemplateProducer.java +++ b/inject/processor/src/test/java/io/helidon/inject/processor/ExtensibleGetTemplateProducer.java @@ -44,8 +44,8 @@ public ExtensibleGetTemplateProducer() { } @Override - public Set annoTypes() { - return Set.of("io.helidon.inject.processor.testsubjects.ExtensibleGET"); + public Set annoTypes() { + return Set.of(TypeName.create("io.helidon.inject.processor.testsubjects.ExtensibleGET")); } @Override diff --git a/inject/tests/resources-inject/src/test/java/io/helidon/inject/tests/inject/interceptor/InterceptorRuntimeTest.java b/inject/tests/resources-inject/src/test/java/io/helidon/inject/tests/inject/interceptor/InterceptorRuntimeTest.java index d162a666af7..2112c26ca63 100644 --- a/inject/tests/resources-inject/src/test/java/io/helidon/inject/tests/inject/interceptor/InterceptorRuntimeTest.java +++ b/inject/tests/resources-inject/src/test/java/io/helidon/inject/tests/inject/interceptor/InterceptorRuntimeTest.java @@ -28,8 +28,8 @@ import io.helidon.config.Config; import io.helidon.config.ConfigSources; import io.helidon.inject.api.InjectionException; -import io.helidon.inject.api.Interceptor; import io.helidon.inject.api.InjectionServices; +import io.helidon.inject.api.Interceptor; import io.helidon.inject.api.ServiceInfo; import io.helidon.inject.api.ServiceInfoCriteria; import io.helidon.inject.api.ServiceProvider; @@ -43,7 +43,6 @@ import jakarta.inject.Named; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; import static io.helidon.inject.api.Qualifier.create; @@ -97,7 +96,6 @@ void createNoArgBasedInterceptorSource() throws Exception { java); } - @Disabled // will be handled in https://github.com/helidon-io/helidon/issues/6542 @Test void createInterfaceBasedInterceptorSource() throws Exception { TypeName interceptorTypeName = TypeName.create(YImpl$$Injection$$Interceptor.class); diff --git a/inject/tests/resources-inject/src/test/resources/expected/ximpl-interceptor._java_ b/inject/tests/resources-inject/src/test/resources/expected/ximpl-interceptor._java_ index 376c319fc4d..45ed09ad116 100644 --- a/inject/tests/resources-inject/src/test/resources/expected/ximpl-interceptor._java_ +++ b/inject/tests/resources-inject/src/test/resources/expected/ximpl-interceptor._java_ @@ -25,8 +25,6 @@ import java.util.function.Function; import io.helidon.common.types.Annotation; import io.helidon.common.types.TypeName; import io.helidon.common.types.TypedElementInfo; -import io.helidon.common.types.TypeName; -import io.helidon.common.types.TypedElementInfo; import io.helidon.common.types.TypeValues; import io.helidon.inject.api.ClassNamed; import io.helidon.inject.api.InvocationContext; @@ -228,17 +226,17 @@ public class XImpl$$Injection$$Interceptor extends io.helidon.inject.tests.injec @Inject @SuppressWarnings("unchecked") XImpl$$Injection$$Interceptor( - @ClassNamed(io.helidon.inject.tests.plain.interceptor.InterceptorBasedAnno.class) List> io_helidon_inject_tests_plain_interceptor_InterceptorBasedAnno, @ClassNamed(io.helidon.inject.tests.inject.interceptor.TestNamed.class) List> io_helidon_inject_tests_inject_interceptor_TestNamed, + @ClassNamed(io.helidon.inject.tests.plain.interceptor.InterceptorBasedAnno.class) List> io_helidon_inject_tests_plain_interceptor_InterceptorBasedAnno, Provider provider) { this.__provider = Objects.requireNonNull(provider); this.__sp = (provider instanceof ServiceProvider) ? (ServiceProvider) __provider : null; List> __ctor__interceptors = mergeAndCollapse(io_helidon_inject_tests_inject_interceptor_TestNamed); this.__methodIA1__interceptors = mergeAndCollapse(io_helidon_inject_tests_inject_interceptor_TestNamed); - this.__methodIA2__interceptors = mergeAndCollapse(io_helidon_inject_tests_plain_interceptor_InterceptorBasedAnno, io_helidon_inject_tests_inject_interceptor_TestNamed); - this.__methodIB__interceptors = mergeAndCollapse(io_helidon_inject_tests_plain_interceptor_InterceptorBasedAnno, io_helidon_inject_tests_inject_interceptor_TestNamed); - this.__methodIB2__interceptors = mergeAndCollapse(io_helidon_inject_tests_plain_interceptor_InterceptorBasedAnno, io_helidon_inject_tests_inject_interceptor_TestNamed); - this.__close__interceptors = mergeAndCollapse(io_helidon_inject_tests_plain_interceptor_InterceptorBasedAnno, io_helidon_inject_tests_inject_interceptor_TestNamed); + this.__methodIA2__interceptors = mergeAndCollapse(io_helidon_inject_tests_inject_interceptor_TestNamed, io_helidon_inject_tests_plain_interceptor_InterceptorBasedAnno); + this.__methodIB__interceptors = mergeAndCollapse(io_helidon_inject_tests_inject_interceptor_TestNamed, io_helidon_inject_tests_plain_interceptor_InterceptorBasedAnno); + this.__methodIB2__interceptors = mergeAndCollapse(io_helidon_inject_tests_inject_interceptor_TestNamed, io_helidon_inject_tests_plain_interceptor_InterceptorBasedAnno); + this.__close__interceptors = mergeAndCollapse(io_helidon_inject_tests_inject_interceptor_TestNamed, io_helidon_inject_tests_plain_interceptor_InterceptorBasedAnno); this.__methodX__interceptors = mergeAndCollapse(io_helidon_inject_tests_inject_interceptor_TestNamed); this.__methodY__interceptors = mergeAndCollapse(io_helidon_inject_tests_inject_interceptor_TestNamed); this.__methodZ__interceptors = mergeAndCollapse(io_helidon_inject_tests_inject_interceptor_TestNamed); diff --git a/inject/tests/resources-inject/src/test/resources/expected/yimpl-interceptor._java_ b/inject/tests/resources-inject/src/test/resources/expected/yimpl-interceptor._java_ index bfefb11300c..9426ff90c33 100644 --- a/inject/tests/resources-inject/src/test/resources/expected/yimpl-interceptor._java_ +++ b/inject/tests/resources-inject/src/test/resources/expected/yimpl-interceptor._java_ @@ -1,6 +1,21 @@ -// This is a generated file (powered by Helidon). Do not edit or extend from this artifact as it is subject to change at any time! +/* + * Copyright (c) 2023 Oracle and/or its affiliates. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + -package io.helidon.pico.tests.pico.interceptor; +package io.helidon.inject.tests.inject.interceptor; import java.util.List; import java.util.Map; @@ -8,14 +23,15 @@ import java.util.Objects; import java.util.function.Function; import io.helidon.common.types.Annotation; -import io.helidon.common.types.AnnotationDefault; import io.helidon.common.types.TypeName; import io.helidon.common.types.TypedElementInfo; -import io.helidon.pico.api.InvocationContextDefault; -import io.helidon.pico.api.Interceptor; -import io.helidon.pico.api.InvocationException; -import io.helidon.pico.api.ServiceProvider; -import io.helidon.pico.runtime.InterceptedMethod; +import io.helidon.common.types.TypeValues; +import io.helidon.inject.api.ClassNamed; +import io.helidon.inject.api.InvocationContext; +import io.helidon.inject.api.Interceptor; +import io.helidon.inject.api.InvocationException; +import io.helidon.inject.api.ServiceProvider; +import io.helidon.inject.runtime.InterceptedMethod; import jakarta.inject.Inject; import jakarta.inject.Named; @@ -23,103 +39,109 @@ import jakarta.inject.Provider; import jakarta.inject.Singleton; import static io.helidon.common.types.TypeName.create; -import static io.helidon.pico.runtime.Invocation.createInvokeAndSupply; -import static io.helidon.pico.runtime.Invocation.mergeAndCollapse; +import static io.helidon.inject.runtime.Invocation.createInvokeAndSupply; +import static io.helidon.inject.runtime.Invocation.mergeAndCollapse; /** - * Pico {@link Interceptor} for {@link io.helidon.pico.tests.pico.interceptor.YImpl }. + * Injection {@link Interceptor} for {@link io.helidon.inject.tests.inject.interceptor.YImpl }. */ // using the interfaces approach @io.helidon.common.Weight(100.001) -@io.helidon.pico.api.Intercepted(io.helidon.pico.tests.pico.interceptor.YImpl.class) +@io.helidon.inject.api.Intercepted(io.helidon.inject.tests.inject.interceptor.YImpl.class) @Singleton @SuppressWarnings("ALL") -@io.helidon.common.Generated(value = "io.helidon.pico.tools.InterceptorCreatorDefault", trigger = "io.helidon.pico.tests.pico.interceptor.YImpl") -public class YImpl$$Pico$$Interceptor /* extends io.helidon.pico.tests.pico.interceptor.YImpl */ implements io.helidon.pico.tests.plain.interceptor.IB, java.io.Closeable, java.lang.AutoCloseable { +@io.helidon.common.Generated(value = "io.helidon.inject.tools.InterceptorCreatorDefault", trigger = "io.helidon.inject.tests.inject.interceptor.YImpl") +public class YImpl$$Injection$$Interceptor /* extends io.helidon.inject.tests.inject.interceptor.YImpl */ implements io.helidon.inject.tests.plain.interceptor.IB, java.io.Closeable, java.lang.AutoCloseable { private static final List __serviceLevelAnnotations = List.of( Annotation.create(jakarta.inject.Singleton.class), - Annotation.create(jakarta.inject.Named.class, Map.of("value", "ClassY")), - Annotation.create(io.helidon.pico.api.ExternalContracts.class, Map.of("moduleNames", "test1, test2", "value", "java.io.Closeable")), - Annotation.create(java.lang.SuppressWarnings.class, Map.of("value", "unused"))); + Annotation.create(io.helidon.inject.api.ClassNamed.class, Map.of("value", "io.helidon.inject.tests.inject.ClassNamedY")), + Annotation.create(io.helidon.inject.api.ExternalContracts.class, Map.of("moduleNames", java.util.List.of("test1", "test2"), "value", java.util.List.of("java.io.Closeable"))), + Annotation.create(java.lang.SuppressWarnings.class, Map.of("value", java.util.List.of("unused")))); private static final TypedElementInfo __ctor = TypedElementInfo.builder() .typeName(create(void.class)) - .elementTypeKind(TypeValues.KIND_CONSTRUCTOR) - .elementName(io.helidon.pico.api.ElementInfo.CONSTRUCTOR) - .addAnnotation(Annotation.create(io.helidon.pico.api.ExternalContracts.class, Map.of("moduleNames", "test1, test2", "value", "java.io.Closeable"))) + .elementTypeKind(TypeValues.KIND_CONSTRUCTOR) + .elementName(io.helidon.inject.api.ElementInfo.CONSTRUCTOR) + .addAnnotation(Annotation.create(io.helidon.inject.api.ClassNamed.class, Map.of("value", "io.helidon.inject.tests.inject.ClassNamedY"))) + .addAnnotation(Annotation.create(io.helidon.inject.api.ExternalContracts.class, Map.of("moduleNames", java.util.List.of("test1", "test2"), "value", java.util.List.of("java.io.Closeable")))) .addAnnotation(Annotation.create(jakarta.inject.Inject.class)) - .addAnnotation(Annotation.create(jakarta.inject.Named.class, Map.of("value", "ClassY"))) .addAnnotation(Annotation.create(jakarta.inject.Singleton.class)) - .addAnnotation(Annotation.create(java.lang.SuppressWarnings.class, Map.of("value", "unused"))) + .addAnnotation(Annotation.create(java.lang.SuppressWarnings.class, Map.of("value", java.util.List.of("unused")))) .build(); private static final TypedElementInfo __methodIB = TypedElementInfo.builder() .typeName(create(void.class)) - .elementTypeKind(TypeValues.KIND_METHOD) + .elementTypeKind(TypeValues.KIND_METHOD) .elementName("methodIB") - .addAnnotation(Annotation.create(io.helidon.pico.api.ExternalContracts.class, Map.of("moduleNames", "test1, test2", "value", "java.io.Closeable"))) - .addAnnotation(Annotation.create(io.helidon.pico.tests.plain.interceptor.InterceptorBasedAnno.class, Map.of("value", "IBSubAnno"))) + .addAnnotation(Annotation.create(io.helidon.inject.api.ClassNamed.class, Map.of("value", "io.helidon.inject.tests.inject.ClassNamedY"))) + .addAnnotation(Annotation.create(io.helidon.inject.api.ExternalContracts.class, Map.of("moduleNames", java.util.List.of("test1", "test2"), "value", java.util.List.of("java.io.Closeable")))) + .addAnnotation(Annotation.create(io.helidon.inject.tests.plain.interceptor.InterceptorBasedAnno.class, Map.of("value", "IBSubAnno"))) .addAnnotation(Annotation.create(jakarta.inject.Named.class, Map.of("value", "methodIB"))) .addAnnotation(Annotation.create(jakarta.inject.Singleton.class)) .addAnnotation(Annotation.create(java.lang.Override.class)) - .addAnnotation(Annotation.create(java.lang.SuppressWarnings.class, Map.of("value", "unused"))) + .addAnnotation(Annotation.create(java.lang.SuppressWarnings.class, Map.of("value", java.util.List.of("unused")))) .build(); private static final TypedElementInfo __methodIB__p1 = TypedElementInfo.builder() .typeName(create(java.lang.String.class)) + .elementTypeKind(TypeValues.KIND_METHOD) .elementName("p1") .addAnnotation(Annotation.create(jakarta.inject.Named.class, Map.of("value", "arg1"))) .build(); private static final TypedElementInfo __methodIB2 = TypedElementInfo.builder() .typeName(create(java.lang.String.class)) + .elementTypeKind(TypeValues.KIND_METHOD) .elementName("methodIB2") - .addAnnotation(Annotation.create(io.helidon.pico.api.ExternalContracts.class, Map.of("moduleNames", "test1, test2", "value", "java.io.Closeable"))) - .addAnnotation(Annotation.create(io.helidon.pico.tests.plain.interceptor.InterceptorBasedAnno.class, Map.of("value", "IBSubAnno"))) + .addAnnotation(Annotation.create(io.helidon.inject.api.ClassNamed.class, Map.of("value", "io.helidon.inject.tests.inject.ClassNamedY"))) + .addAnnotation(Annotation.create(io.helidon.inject.api.ExternalContracts.class, Map.of("moduleNames", java.util.List.of("test1", "test2"), "value", java.util.List.of("java.io.Closeable")))) + .addAnnotation(Annotation.create(io.helidon.inject.tests.plain.interceptor.InterceptorBasedAnno.class, Map.of("value", "IBSubAnno"))) .addAnnotation(Annotation.create(jakarta.inject.Named.class, Map.of("value", "methodIB2"))) .addAnnotation(Annotation.create(jakarta.inject.Singleton.class)) .addAnnotation(Annotation.create(java.lang.Override.class)) - .addAnnotation(Annotation.create(java.lang.SuppressWarnings.class, Map.of("value", "unused"))) + .addAnnotation(Annotation.create(java.lang.SuppressWarnings.class, Map.of("value", java.util.List.of("unused")))) .build(); private static final TypedElementInfo __methodIB2__p1 = TypedElementInfo.builder() - .typeName(create(java.lang.String.class) ) + .typeName(create(java.lang.String.class)) + .elementTypeKind(TypeValues.KIND_METHOD) .elementName("p1") .addAnnotation(Annotation.create(jakarta.inject.Named.class, Map.of("value", "arg1"))) .build(); private static final TypedElementInfo __close = TypedElementInfo.builder() .typeName(create(void.class)) + .elementTypeKind(TypeValues.KIND_METHOD) .elementName("close") - .addAnnotation(Annotation.create(io.helidon.pico.api.ExternalContracts.class, Map.of("moduleNames", "test1, test2", "value", "java.io.Closeable"))) - .addAnnotation(Annotation.create(io.helidon.pico.tests.plain.interceptor.InterceptorBasedAnno.class)) - .addAnnotation(Annotation.create(jakarta.inject.Named.class, Map.of("value", "ClassY"))) + .addAnnotation(Annotation.create(io.helidon.inject.api.ClassNamed.class, Map.of("value", "io.helidon.inject.tests.inject.ClassNamedY"))) + .addAnnotation(Annotation.create(io.helidon.inject.api.ExternalContracts.class, Map.of("moduleNames", java.util.List.of("test1", "test2"), "value", java.util.List.of("java.io.Closeable")))) + .addAnnotation(Annotation.create(io.helidon.inject.tests.plain.interceptor.InterceptorBasedAnno.class, Map.of("value", ""))) .addAnnotation(Annotation.create(jakarta.inject.Singleton.class)) .addAnnotation(Annotation.create(java.lang.Override.class)) - .addAnnotation(Annotation.create(java.lang.SuppressWarnings.class, Map.of("value", "unused"))) + .addAnnotation(Annotation.create(java.lang.SuppressWarnings.class, Map.of("value", java.util.List.of("unused")))) .build(); - private static final TypeName __serviceTypeName = TypeName.create(io.helidon.pico.tests.pico.interceptor.YImpl.class); + private static final TypeName __serviceTypeName = TypeName.create(io.helidon.inject.tests.inject.interceptor.YImpl.class); - private final Provider __provider; - private final ServiceProvider __sp; - private final io.helidon.pico.tests.pico.interceptor.YImpl __impl; + private final Provider __provider; + private final ServiceProvider __sp; + private final io.helidon.inject.tests.inject.interceptor.YImpl __impl; private final List> __methodIB__interceptors; private final List> __methodIB2__interceptors; private final List> __close__interceptors; - private final InterceptedMethod __methodIB__call; - private final InterceptedMethod __methodIB2__call; - private final InterceptedMethod __close__call; + private final InterceptedMethod __methodIB__call; + private final InterceptedMethod __methodIB2__call; + private final InterceptedMethod __close__call; @Inject @SuppressWarnings("unchecked") - YImpl$$Pico$$Interceptor( - @Named("io.helidon.pico.tests.plain.interceptor.InterceptorBasedAnno") List> io_helidon_pico_tests_plain_interceptor_InterceptorBasedAnno, - Provider provider) { + YImpl$$Injection$$Interceptor( + @ClassNamed(io.helidon.inject.tests.plain.interceptor.InterceptorBasedAnno.class) List> io_helidon_inject_tests_plain_interceptor_InterceptorBasedAnno, + Provider provider) { this.__provider = Objects.requireNonNull(provider); - this.__sp = (provider instanceof ServiceProvider) ? (ServiceProvider) __provider : null; + this.__sp = (provider instanceof ServiceProvider) ? (ServiceProvider) __provider : null; List> __ctor__interceptors = mergeAndCollapse(); - this.__methodIB__interceptors = mergeAndCollapse(io_helidon_pico_tests_plain_interceptor_InterceptorBasedAnno); - this.__methodIB2__interceptors = mergeAndCollapse(io_helidon_pico_tests_plain_interceptor_InterceptorBasedAnno); - this.__close__interceptors = mergeAndCollapse(io_helidon_pico_tests_plain_interceptor_InterceptorBasedAnno); + this.__methodIB__interceptors = mergeAndCollapse(io_helidon_inject_tests_plain_interceptor_InterceptorBasedAnno); + this.__methodIB2__interceptors = mergeAndCollapse(io_helidon_inject_tests_plain_interceptor_InterceptorBasedAnno); + this.__close__interceptors = mergeAndCollapse(io_helidon_inject_tests_plain_interceptor_InterceptorBasedAnno); - Function call = args -> __provider.get(); - io.helidon.pico.tests.pico.interceptor.YImpl result = createInvokeAndSupply( + Function call = args -> __provider.get(); + io.helidon.inject.tests.inject.interceptor.YImpl result = createInvokeAndSupply( InvocationContext.builder() .serviceProvider(__sp) .serviceTypeName(__serviceTypeName) @@ -131,7 +153,7 @@ public class YImpl$$Pico$$Interceptor /* extends io.helidon.pico.tests.pico.inte new Object[0]); this.__impl = Objects.requireNonNull(result); - this.__methodIB__call = new InterceptedMethod( + this.__methodIB__call = new InterceptedMethod( __impl, __sp, __serviceTypeName, __serviceLevelAnnotations, __methodIB__interceptors, __methodIB, List.of(__methodIB__p1)) { @Override @@ -141,7 +163,7 @@ public class YImpl$$Pico$$Interceptor /* extends io.helidon.pico.tests.pico.inte } }; - this.__methodIB2__call = new InterceptedMethod( + this.__methodIB2__call = new InterceptedMethod( __impl, __sp, __serviceTypeName, __serviceLevelAnnotations, __methodIB2__interceptors, __methodIB2, List.of(__methodIB2__p1)) { @Override @@ -150,7 +172,7 @@ public class YImpl$$Pico$$Interceptor /* extends io.helidon.pico.tests.pico.inte } }; - this.__close__call = new InterceptedMethod( + this.__close__call = new InterceptedMethod( __impl, __sp, __serviceTypeName, __serviceLevelAnnotations, __close__interceptors, __close) { @Override public java.lang.Void invoke(Object... args) throws Throwable { diff --git a/inject/tools/src/main/java/io/helidon/inject/tools/InterceptedElementBlueprint.java b/inject/tools/src/main/java/io/helidon/inject/tools/InterceptedElementBlueprint.java index ddc72e1fcef..7faacde2b34 100644 --- a/inject/tools/src/main/java/io/helidon/inject/tools/InterceptedElementBlueprint.java +++ b/inject/tools/src/main/java/io/helidon/inject/tools/InterceptedElementBlueprint.java @@ -19,6 +19,7 @@ import java.util.Set; import io.helidon.builder.api.Prototype; +import io.helidon.common.types.TypeName; /** * Used in the interception model described by {@link InterceptionPlan}. An intercepted @@ -35,7 +36,7 @@ interface InterceptedElementBlueprint { * * @return the set of intercepted trigger types that apply to this method/element */ - Set interceptedTriggerTypeNames(); + Set interceptedTriggerTypeNames(); /** * The method element info for this intercepted method. diff --git a/inject/tools/src/main/java/io/helidon/inject/tools/InterceptionPlanBlueprint.java b/inject/tools/src/main/java/io/helidon/inject/tools/InterceptionPlanBlueprint.java index a2fa169e5ab..276be25b9d8 100644 --- a/inject/tools/src/main/java/io/helidon/inject/tools/InterceptionPlanBlueprint.java +++ b/inject/tools/src/main/java/io/helidon/inject/tools/InterceptionPlanBlueprint.java @@ -64,7 +64,7 @@ interface InterceptionPlanBlueprint { * * @return all the annotation names that contributed to triggering this interceptor plan */ - Set annotationTriggerTypeNames(); + Set annotationTriggerTypeNames(); /** * The list of elements that should be intercepted. diff --git a/inject/tools/src/main/java/io/helidon/inject/tools/InterceptorCreatorDefault.java b/inject/tools/src/main/java/io/helidon/inject/tools/InterceptorCreatorDefault.java index 7dab6ee0bb0..6d965527f6e 100644 --- a/inject/tools/src/main/java/io/helidon/inject/tools/InterceptorCreatorDefault.java +++ b/inject/tools/src/main/java/io/helidon/inject/tools/InterceptorCreatorDefault.java @@ -20,7 +20,6 @@ import java.lang.annotation.RetentionPolicy; import java.util.ArrayList; import java.util.Collection; -import java.util.Collections; import java.util.HashMap; import java.util.LinkedHashSet; import java.util.List; @@ -31,6 +30,7 @@ import java.util.TreeMap; import java.util.TreeSet; import java.util.concurrent.atomic.AtomicInteger; +import java.util.function.Predicate; import java.util.stream.Collectors; import javax.annotation.processing.ProcessingEnvironment; @@ -83,9 +83,14 @@ public class InterceptorCreatorDefault extends AbstractCreator implements Interc private static final String INTERFACES_INTERCEPTOR_HBS = "interface-based-interceptor.hbs"; private static final double INTERCEPTOR_PRIORITY_DELTA = 0.001; private static final String CTOR_ALIAS = "ctor"; - private static final Set ALLOW_LIST = new LinkedHashSet<>(); + /** + * the interceptor meta-annotation. + */ + private static final Annotation TRIGGER = Annotation.create(InterceptedTrigger.class); + private static final TypeName TRIGGER_TYPE = TRIGGER.typeName(); + private static final Set ALLOW_LIST = new LinkedHashSet<>(); - private Set allowListedAnnoTypeNames; + private final Set allowListedAnnoTypeNames = new LinkedHashSet<>(); /** * Service loader based constructor. @@ -99,7 +104,7 @@ public InterceptorCreatorDefault() { @Override public boolean reset(boolean deep) { - allowListedAnnoTypeNames = null; + allowListedAnnoTypeNames.clear(); return true; } @@ -109,14 +114,14 @@ public boolean reset(boolean deep) { * @param allowListedAnnotationTypes the allow-listed annotation types * @return this instance */ - public InterceptorCreatorDefault allowListedAnnotationTypes(Set allowListedAnnotationTypes) { - this.allowListedAnnoTypeNames = allowListedAnnotationTypes; + public InterceptorCreatorDefault allowListedAnnotationTypes(Set allowListedAnnotationTypes) { + this.allowListedAnnoTypeNames.addAll(allowListedAnnotationTypes); return this; } @Override - public Set allowListedAnnotationTypes() { - return (allowListedAnnoTypeNames != null) ? allowListedAnnoTypeNames : Collections.emptySet(); + public Set allowListedAnnotationTypes() { + return allowListedAnnoTypeNames; } /** @@ -129,7 +134,7 @@ abstract static class AnnotationTypeNameResolver { * @param annoTypeName the annotation type name * @return the list of (meta) annotations for the given annotation */ - abstract Collection resolve(String annoTypeName); + abstract Collection resolve(TypeName annoTypeName); } static class ProcessorResolver extends AnnotationTypeNameResolver { @@ -140,21 +145,17 @@ static class ProcessorResolver extends AnnotationTypeNameResolver { } @Override - public Collection resolve(String annoTypeName) { - TypeElement typeElement = elements.getTypeElement(annoTypeName); + public Collection resolve(TypeName annoTypeName) { + TypeElement typeElement = elements.getTypeElement(annoTypeName.fqName()); + if (typeElement == null) { - // maybe an inner class, let's do a bit of a brute force - typeElement = elements.getTypeElement(annoTypeName.replace('$', '.')); - if (typeElement == null) { - throw new ToolsException("Unable to resolve: " + annoTypeName); - } + throw new ToolsException("Unable to resolve: " + annoTypeName); } List annotations = typeElement.getAnnotationMirrors(); - Set result = annotations.stream() + return annotations.stream() .map(it -> AnnotationFactory.createAnnotation(it, elements)) .collect(Collectors.toSet()); - return result; } } @@ -166,11 +167,12 @@ static class ReflectionResolver extends AnnotationTypeNameResolver { } @Override - public Collection resolve(String annoTypeName) { - ClassInfo classInfo = scan.getClassInfo(annoTypeName); + public Collection resolve(TypeName annoTypeName) { + ClassInfo classInfo = scan.getClassInfo(annoTypeName.fqName()); if (classInfo == null) { try { - Class annotationType = (Class) Class.forName(annoTypeName); + Class annotationType = + (Class) Class.forName(annoTypeName.fqName()); return createAnnotationListFromAnnotations(annotationType.getAnnotations()); } catch (ClassNotFoundException e) { throw new ToolsException(e.getMessage(), e); @@ -183,7 +185,6 @@ public Collection resolve(String annoTypeName) { /** * Filter will apply the appropriate strategy determine which annotation types qualify as triggers for interception. */ - @SuppressWarnings("checkstyle:VisibilityModifier") abstract static class TriggerFilter { /** * The creator. @@ -195,11 +196,6 @@ abstract static class TriggerFilter { */ protected final AnnotationTypeNameResolver resolver; - /** - * the interceptor meta-annotation. - */ - public static final Annotation TRIGGER = Annotation.create(InterceptedTrigger.class); - protected TriggerFilter() { this.creator = null; this.resolver = null; @@ -222,7 +218,7 @@ protected TriggerFilter(InterceptorCreator creator, * @param annotationTypeName the annotation type name * @return true if the annotation qualifies/triggers interceptor creation */ - public boolean isQualifyingTrigger(String annotationTypeName) { + public boolean isQualifyingTrigger(TypeName annotationTypeName) { return (creator != null) && creator.isAllowListed(annotationTypeName); } } @@ -237,9 +233,9 @@ protected ExplicitStrategy(InterceptorCreator creator, } @Override - public boolean isQualifyingTrigger(String annotationTypeName) { + public boolean isQualifyingTrigger(TypeName annotationTypeName) { return resolver.resolve(annotationTypeName).contains(TRIGGER) - || TRIGGER.typeName().name().equals(annotationTypeName); + || TRIGGER_TYPE.equals(annotationTypeName); } } @@ -256,7 +252,7 @@ protected AllRuntimeStrategy(InterceptorCreator creator, } @Override - public boolean isQualifyingTrigger(String annotationTypeName) { + public boolean isQualifyingTrigger(TypeName annotationTypeName) { Objects.requireNonNull(resolver); Objects.requireNonNull(annotationTypeName); return (resolver.resolve(annotationTypeName).contains(RUNTIME) @@ -269,7 +265,7 @@ public boolean isQualifyingTrigger(String annotationTypeName) { * Enforces {@link Strategy#ALLOW_LISTED}. */ private static class AllowListedStrategy extends TriggerFilter { - private final Set allowListed; + private final Set allowListed; protected AllowListedStrategy(InterceptorCreator creator) { super(creator); @@ -277,7 +273,7 @@ protected AllowListedStrategy(InterceptorCreator creator) { } @Override - public boolean isQualifyingTrigger(String annotationTypeName) { + public boolean isQualifyingTrigger(TypeName annotationTypeName) { Objects.requireNonNull(annotationTypeName); return allowListed.contains(annotationTypeName) || ALLOW_LIST.contains(annotationTypeName); } @@ -292,7 +288,7 @@ protected CustomStrategy(InterceptorCreator creator) { } @Override - public boolean isQualifyingTrigger(String annotationTypeName) { + public boolean isQualifyingTrigger(TypeName annotationTypeName) { Objects.requireNonNull(creator); Objects.requireNonNull(annotationTypeName); return (creator.isAllowListed(annotationTypeName) || ALLOW_LIST.contains(annotationTypeName)); @@ -318,7 +314,7 @@ protected BlendedStrategy(InterceptorCreator creator, } @Override - public boolean isQualifyingTrigger(String annotationTypeName) { + public boolean isQualifyingTrigger(TypeName annotationTypeName) { if (super.isQualifyingTrigger(annotationTypeName)) { return true; } @@ -400,22 +396,23 @@ TriggerFilter triggerFilter() { * @return the set of annotation types that are trigger interception */ @Override - public Set allAnnotationTypeTriggers() { - Set allAnnotations = getAllAnnotations(); + public Set allAnnotationTypeTriggers() { + Set allAnnotations = getAllAnnotations(); if (allAnnotations.isEmpty()) { return Set.of(); } TriggerFilter triggerFilter = triggerFilter(); - Set annotationTypeTriggers = allAnnotations.stream() + // the below section uses a linked has set to make sure the order is preserved + // so we can run tests that depend on that order (such as actual generated code) + return allAnnotations.stream() .filter(triggerFilter::isQualifyingTrigger) - .filter(anno -> !TriggerFilter.TRIGGER.typeName().name().equals(anno)) - .collect(Collectors.toSet()); - return annotationTypeTriggers; + .filter(Predicate.not(TRIGGER_TYPE::equals)) + .collect(Collectors.toCollection(LinkedHashSet::new)); } @Override - public Optional createInterceptorPlan(Set interceptorAnnotationTriggers) { + public Optional createInterceptorPlan(Set interceptorAnnotationTriggers) { boolean hasNoArgConstructor = hasNoArgConstructor(); Set interfaces = interfaces(); @@ -462,7 +459,7 @@ public String toString() { /** * @return the cumulative annotations referenced by this type */ - abstract Set getAllAnnotations(); + abstract Set getAllAnnotations(); /** * @return only the service level annotations referenced by this type @@ -482,18 +479,18 @@ public String toString() { /** * @return all public methods */ - abstract List getInterceptedElements(Set interceptorAnnotationTriggers); + abstract List getInterceptedElements(Set interceptorAnnotationTriggers); /** * @return all public methods for only the given interfaces */ - abstract List getInterceptedElements(Set interceptorAnnotationTriggers, + abstract List getInterceptedElements(Set interceptorAnnotationTriggers, Set interfaces); boolean containsAny(Set annotations, - Set annotationTypeNames) { + Set annotationTypeNames) { for (Annotation annotation : annotations) { - if (annotationTypeNames.contains(annotation.typeName().name())) { + if (annotationTypeNames.contains(annotation.typeName())) { return true; } } @@ -550,9 +547,11 @@ private static class ProcessorBased extends AbstractInterceptorProcessor { } @Override - Set getAllAnnotations() { + Set getAllAnnotations() { Set set = gatherAllAnnotationsUsedOnPublicNonStaticMethods(serviceTypeElement, processEnv); - return set.stream().map(a -> a.typeName().name()).collect(Collectors.toCollection(LinkedHashSet::new)); + return set.stream() + .map(a -> a.typeName()) + .collect(Collectors.toCollection(LinkedHashSet::new)); } @Override @@ -590,7 +589,7 @@ Set gatherInterfaces(Set result, } @Override - List getInterceptedElements(Set interceptorAnnotationTriggers) { + List getInterceptedElements(Set interceptorAnnotationTriggers) { List result = new ArrayList<>(); Set serviceLevelAnnos = getServiceLevelAnnotations(); @@ -608,7 +607,7 @@ List getInterceptedElements(Set interceptorAnnotatio } @Override - List getInterceptedElements(Set interceptorAnnotationTriggers, + List getInterceptedElements(Set interceptorAnnotationTriggers, Set interfaces) { assert (!interfaces.isEmpty()); List result = new ArrayList<>(); @@ -630,7 +629,7 @@ List getInterceptedElements(Set interceptorAnnotatio void gatherInjectableConstructor(List result, Set serviceLevelAnnos, - Set interceptorAnnotationTriggers) { + Set interceptorAnnotationTriggers) { serviceTypeElement.getEnclosedElements().stream() .filter(e -> e.getKind() == ElementKind.CONSTRUCTOR) .map(ExecutableElement.class::cast) @@ -688,11 +687,13 @@ boolean mapsToAnInterface(ExecutableElement ee, private InterceptedElement create(ProcessingEnvironment processingEnv, ExecutableElement ee, Set serviceLevelAnnos, - Set interceptorAnnotationTriggers) { + Set interceptorAnnotationTriggers) { MethodElementInfo elementInfo = createMethodElementInfo(processingEnv, serviceTypeElement, ee, serviceLevelAnnos); - Set applicableTriggers = new LinkedHashSet<>(interceptorAnnotationTriggers); - applicableTriggers.retainAll(elementInfo.annotations().stream() - .map(a -> a.typeName().name()).collect(Collectors.toSet())); + Set applicableTriggers = new LinkedHashSet<>(interceptorAnnotationTriggers); + applicableTriggers.retainAll(elementInfo.annotations() + .stream() + .map(a -> a.typeName()) + .collect(Collectors.toSet())); return InterceptedElement.builder() .interceptedTriggerTypeNames(applicableTriggers) .elementInfo(elementInfo) @@ -713,9 +714,11 @@ private static class ReflectionBased extends AbstractInterceptorProcessor { } @Override - Set getAllAnnotations() { + Set getAllAnnotations() { Set set = gatherAllAnnotationsUsedOnPublicNonStaticMethods(classInfo); - return set.stream().map(a -> a.typeName().name()).collect(Collectors.toCollection(LinkedHashSet::new)); + return set.stream() + .map(a -> a.typeName()) + .collect(Collectors.toCollection(LinkedHashSet::new)); } @Override @@ -750,7 +753,7 @@ Set gatherInterfaces(Set result, } @Override - List getInterceptedElements(Set interceptorAnnotationTriggers) { + List getInterceptedElements(Set interceptorAnnotationTriggers) { List result = new ArrayList<>(); Set serviceLevelAnnos = getServiceLevelAnnotations(); classInfo.getMethodAndConstructorInfo() @@ -763,7 +766,7 @@ List getInterceptedElements(Set interceptorAnnotatio } @Override - List getInterceptedElements(Set interceptorAnnotationTriggers, + List getInterceptedElements(Set interceptorAnnotationTriggers, Set interfaces) { List result = new ArrayList<>(); Set serviceLevelAnnos = getServiceLevelAnnotations(); @@ -812,11 +815,13 @@ ClassInfo toClassInfo(TypeName typeName, private InterceptedElement create(MethodInfo mi, Set serviceLevelAnnos, - Set interceptorAnnotationTriggers) { + Set interceptorAnnotationTriggers) { MethodElementInfo elementInfo = createMethodElementInfo(mi, serviceLevelAnnos); - Set applicableTriggers = new LinkedHashSet<>(interceptorAnnotationTriggers); - applicableTriggers.retainAll(elementInfo.annotations().stream() - .map(a -> a.typeName().name()).collect(Collectors.toSet())); + Set applicableTriggers = new LinkedHashSet<>(interceptorAnnotationTriggers); + applicableTriggers.retainAll(elementInfo.annotations() + .stream() + .map(a -> a.typeName()) + .collect(Collectors.toSet())); return InterceptedElement.builder() .interceptedTriggerTypeNames(applicableTriggers) .elementInfo(elementInfo) @@ -846,50 +851,33 @@ static AnnotationTypeNameResolver createResolverFromReflection() { @Override public AbstractInterceptorProcessor createInterceptorProcessor(ServiceInfoBasics interceptedService, InterceptorCreator delegateCreator, - Optional processEnv) { + ProcessingEnvironment processEnv) { Objects.requireNonNull(interceptedService); Objects.requireNonNull(delegateCreator); - if (processEnv.isPresent()) { - return createInterceptorProcessorFromProcessor(interceptedService, delegateCreator, processEnv); - } - return createInterceptorProcessorFromReflection(interceptedService, delegateCreator); + Objects.requireNonNull(processEnv); + + Options.init(processEnv); + ALLOW_LIST.addAll(Options.getOptionStringList(Options.TAG_ALLOW_LISTED_INTERCEPTOR_ANNOTATIONS) + .stream() + .map(TypeName::create) + .toList()); + + return new ProcessorBased(interceptedService, + delegateCreator, + processEnv, + logger()); } - /** - * Create an interceptor processor based on annotation processing. - * - * @param interceptedService the service being processed - * @param delegateCreator the real/delegate creator - * @param processEnv the processing env, if available - * @return the {@link InterceptorCreatorDefault.AbstractInterceptorProcessor} to use - */ - AbstractInterceptorProcessor createInterceptorProcessorFromProcessor(ServiceInfoBasics interceptedService, - InterceptorCreator delegateCreator, - Optional processEnv) { - processEnv.ifPresent(Options::init); - ALLOW_LIST.addAll(Options.getOptionStringList(Options.TAG_ALLOW_LISTED_INTERCEPTOR_ANNOTATIONS)); - if (processEnv.isPresent()) { - return new ProcessorBased(interceptedService, - delegateCreator, - processEnv.get(), - logger()); - } - return createInterceptorProcessorFromReflection(interceptedService, delegateCreator); - } + @Override + public InterceptorProcessor createInterceptorProcessor(ServiceInfoBasics interceptedService, + InterceptorCreator delegateCreator) { + Objects.requireNonNull(interceptedService); + Objects.requireNonNull(delegateCreator); - /** - * Create an interceptor processor based on reflection processing. - * - * @param interceptedService the service being processed - * @param realCreator the real/delegate creator - * @return the {@link InterceptorCreatorDefault.AbstractInterceptorProcessor} to use - */ - AbstractInterceptorProcessor createInterceptorProcessorFromReflection(ServiceInfoBasics interceptedService, - InterceptorCreator realCreator) { String resolvedType = interceptedService.serviceTypeName().resolvedName(); return new ReflectionBased(Objects.requireNonNull(interceptedService), - Objects.requireNonNull(realCreator), + Objects.requireNonNull(delegateCreator), Objects.requireNonNull(SCAN.get().getClassInfo(resolvedType)), logger()); } @@ -940,7 +928,8 @@ String createInterceptorSourceBody(InterceptionPlan plan) { .toList()); subst.put("annotationtriggertypenames", IdAndToString .toList(plan.annotationTriggerTypeNames(), - str -> new IdAndToString(str.replace(".", "_"), str.replace('$', '.')))); + typeName -> new IdAndToString(typeName.fqName().replace(".", "_"), + typeName.fqName().replace('$', '.')))); subst.put("servicelevelannotations", IdAndToString .toList(plan.serviceLevelAnnotations(), InterceptorCreatorDefault::toDecl)); String template = templateHelper().safeLoadTemplate( @@ -1150,7 +1139,7 @@ static class InterceptedMethodCodeGen extends IdAndToString { String args, String objArrayArgs, String untypedElementArgs, - Collection interceptedTriggerTypeNames, + Collection interceptedTriggerTypeNames, Object toString) { super(id, toString); this.methodDecl = methodDecl; @@ -1162,7 +1151,8 @@ static class InterceptedMethodCodeGen extends IdAndToString { this.objArrayArgs = objArrayArgs; this.untypedElementArgs = untypedElementArgs; this.interceptedTriggerTypeNames = CommonUtils.toString(interceptedTriggerTypeNames, - (str) -> str.replace(".", "_"), null); + typeName -> typeName.fqName().replace(".", "_"), + null); } // note: this needs to stay as a public getXXX() method to support Mustache diff --git a/inject/tools/src/main/java/io/helidon/inject/tools/spi/CustomAnnotationTemplateCreator.java b/inject/tools/src/main/java/io/helidon/inject/tools/spi/CustomAnnotationTemplateCreator.java index acb37303137..a16deb385d8 100644 --- a/inject/tools/src/main/java/io/helidon/inject/tools/spi/CustomAnnotationTemplateCreator.java +++ b/inject/tools/src/main/java/io/helidon/inject/tools/spi/CustomAnnotationTemplateCreator.java @@ -19,6 +19,7 @@ import java.util.Optional; import java.util.Set; +import io.helidon.common.types.TypeName; import io.helidon.inject.tools.CustomAnnotationTemplateRequest; import io.helidon.inject.tools.CustomAnnotationTemplateResponse; @@ -34,7 +35,7 @@ public interface CustomAnnotationTemplateCreator { * * @return the supported annotation types for this producer */ - Set annoTypes(); + Set annoTypes(); /** * The implementor should return empty if the request should not be handled. diff --git a/inject/tools/src/main/java/io/helidon/inject/tools/spi/InterceptorCreator.java b/inject/tools/src/main/java/io/helidon/inject/tools/spi/InterceptorCreator.java index 856d27d12df..b7516aeb789 100644 --- a/inject/tools/src/main/java/io/helidon/inject/tools/spi/InterceptorCreator.java +++ b/inject/tools/src/main/java/io/helidon/inject/tools/spi/InterceptorCreator.java @@ -22,6 +22,7 @@ import javax.annotation.processing.ProcessingEnvironment; +import io.helidon.common.types.TypeName; import io.helidon.inject.api.Contract; import io.helidon.inject.api.InterceptedTrigger; import io.helidon.inject.api.ServiceInfoBasics; @@ -51,7 +52,7 @@ default Strategy strategy() { * * @return the set of type names that should trigger creation */ - default Set allowListedAnnotationTypes() { + default Set allowListedAnnotationTypes() { return Set.of(); } @@ -61,23 +62,32 @@ default Set allowListedAnnotationTypes() { * @param annotationType the annotation type name * @return true if the annotation type should trigger interceptor creation */ - default boolean isAllowListed(String annotationType) { + default boolean isAllowListed(TypeName annotationType) { Objects.requireNonNull(annotationType); return allowListedAnnotationTypes().contains(annotationType); } /** - * Returns the processor appropriate for the context revealed in the calling arguments, favoring reflection if - * the serviceTypeElement is provided. + * Returns the reflection based interceptor processor. * * @param interceptedService the service being intercepted * @param delegateCreator the "real" creator - * @param processEnv optionally, the processing environment (should be passed if in annotation processor) + * @return the processor to use for the given arguments + */ + InterceptorProcessor createInterceptorProcessor(ServiceInfoBasics interceptedService, + InterceptorCreator delegateCreator); + + /** + * Returns the annotation based interceptor processor. + * + * @param interceptedService the service being intercepted + * @param delegateCreator the "real" creator + * @param processEnv the processing environment (should be passed if in annotation processor) * @return the processor to use for the given arguments */ InterceptorProcessor createInterceptorProcessor(ServiceInfoBasics interceptedService, InterceptorCreator delegateCreator, - Optional processEnv); + ProcessingEnvironment processEnv); /** * The strategy applied for resolving annotations that trigger interception. @@ -103,8 +113,8 @@ enum Strategy { ALLOW_LISTED, /** - * A call to {@link #isAllowListed(String)} will be used on a case-by-case basis to check which annotation - * types qualify. + * A call to {@link #isAllowListed(io.helidon.common.types.TypeName)} will be used on a case-by-case basis to check + * which annotation types qualify. */ CUSTOM, @@ -115,7 +125,8 @@ enum Strategy { /** * Applies a blend of {@link #EXPLICIT} and {@link #CUSTOM} to determine which annotations qualify (i.e., if - * the annotation is not explicitly marked, then a call is still issued to {@link #isAllowListed(String)}. This + * the annotation is not explicitly marked, then a call is still issued to + * {@link #isAllowListed(io.helidon.common.types.TypeName)}. This * strategy is typically the default strategy type in use. */ BLENDED @@ -132,7 +143,7 @@ interface InterceptorProcessor { * * @return the set of annotation types that are trigger interception */ - Set allAnnotationTypeTriggers(); + Set allAnnotationTypeTriggers(); /** * Creates the interception plan. @@ -140,7 +151,7 @@ interface InterceptorProcessor { * @param interceptorAnnotationTriggers the annotation type triggering the interception creation. * @return the plan, or empty if there is no interception needed */ - Optional createInterceptorPlan(Set interceptorAnnotationTriggers); + Optional createInterceptorPlan(Set interceptorAnnotationTriggers); } diff --git a/inject/tools/src/main/resources/templates/inject/default/interface-based-interceptor.hbs b/inject/tools/src/main/resources/templates/inject/default/interface-based-interceptor.hbs index 4a78f9d1ae2..a2035d1dad5 100644 --- a/inject/tools/src/main/resources/templates/inject/default/interface-based-interceptor.hbs +++ b/inject/tools/src/main/resources/templates/inject/default/interface-based-interceptor.hbs @@ -24,8 +24,6 @@ import java.util.function.Function; import io.helidon.common.types.Annotation; import io.helidon.common.types.TypeName; import io.helidon.common.types.TypedElementInfo; -import io.helidon.common.types.TypeName; -import io.helidon.common.types.TypedElementInfo; import io.helidon.common.types.TypeValues; import io.helidon.inject.api.ClassNamed; import io.helidon.inject.api.InvocationContext; diff --git a/inject/tools/src/main/resources/templates/inject/default/no-arg-based-interceptor.hbs b/inject/tools/src/main/resources/templates/inject/default/no-arg-based-interceptor.hbs index c7b09279ef1..b9b82f1d995 100644 --- a/inject/tools/src/main/resources/templates/inject/default/no-arg-based-interceptor.hbs +++ b/inject/tools/src/main/resources/templates/inject/default/no-arg-based-interceptor.hbs @@ -24,8 +24,6 @@ import java.util.function.Function; import io.helidon.common.types.Annotation; import io.helidon.common.types.TypeName; import io.helidon.common.types.TypedElementInfo; -import io.helidon.common.types.TypeName; -import io.helidon.common.types.TypedElementInfo; import io.helidon.common.types.TypeValues; import io.helidon.inject.api.ClassNamed; import io.helidon.inject.api.InvocationContext; diff --git a/inject/tools/src/test/java/io/helidon/inject/tools/InterceptorCreatorDefaultTest.java b/inject/tools/src/test/java/io/helidon/inject/tools/InterceptorCreatorDefaultTest.java index b89ebbaa0a6..ba1039df3d3 100644 --- a/inject/tools/src/test/java/io/helidon/inject/tools/InterceptorCreatorDefaultTest.java +++ b/inject/tools/src/test/java/io/helidon/inject/tools/InterceptorCreatorDefaultTest.java @@ -19,7 +19,6 @@ import java.lang.annotation.Documented; import java.lang.annotation.Retention; import java.lang.annotation.Target; -import java.util.Optional; import java.util.Set; import io.helidon.common.types.Annotation; @@ -49,13 +48,13 @@ void sanity() { assertThat(interceptorCreator.getClass(), equalTo(InterceptorCreatorDefault.class)); assertThat(interceptorCreator.strategy(), is(InterceptorCreator.Strategy.BLENDED)); assertThat(interceptorCreator.allowListedAnnotationTypes().size(), is(0)); - assertThat(interceptorCreator.isAllowListed(Named.class.getName()), is(false)); + assertThat(interceptorCreator.isAllowListed(TypeName.create(Named.class)), is(false)); } @Test void resolverByReflection() { InterceptorCreatorDefault.AnnotationTypeNameResolver resolver = InterceptorCreatorDefault.createResolverFromReflection(); - assertThat(resolver.resolve(InterceptedTrigger.class.getName()), + assertThat(resolver.resolve(TypeName.create(InterceptedTrigger.class)), containsInAnyOrder( Annotation.create(Documented.class), Annotation.create(Retention.class, "java.lang.annotation.RetentionPolicy.CLASS"), @@ -69,10 +68,10 @@ void interceptorPlanByReflection() { .serviceTypeName(HelloInjectionWorldImpl.class) .build(); InterceptorCreatorDefault.AbstractInterceptorProcessor processor = - ((InterceptorCreatorDefault) interceptorCreator).createInterceptorProcessor(serviceInfoBasics, - interceptorCreator, - Optional.empty()); - InterceptionPlan plan = processor.createInterceptorPlan(Set.of(Singleton.class.getName())).orElseThrow(); + (InterceptorCreatorDefault.AbstractInterceptorProcessor) + interceptorCreator.createInterceptorProcessor(serviceInfoBasics, interceptorCreator); + InterceptionPlan plan = processor.createInterceptorPlan(Set.of(TypeName.create(Singleton.class.getName()))) + .orElseThrow(); assertThat(plan.hasNoArgConstructor(), is(false)); assertThat(plan.interfaces(), From 55bec1e4b5fb0ea1bda115ff2a0b33d41d98ab28 Mon Sep 17 00:00:00 2001 From: Tomas Langer Date: Tue, 22 Aug 2023 16:43:26 +0200 Subject: [PATCH 2/2] Checkstyle fix. --- .../tools/InterceptorCreatorDefault.java | 35 +++++++++++++------ 1 file changed, 25 insertions(+), 10 deletions(-) diff --git a/inject/tools/src/main/java/io/helidon/inject/tools/InterceptorCreatorDefault.java b/inject/tools/src/main/java/io/helidon/inject/tools/InterceptorCreatorDefault.java index 6d965527f6e..fbaea772198 100644 --- a/inject/tools/src/main/java/io/helidon/inject/tools/InterceptorCreatorDefault.java +++ b/inject/tools/src/main/java/io/helidon/inject/tools/InterceptorCreatorDefault.java @@ -189,12 +189,12 @@ abstract static class TriggerFilter { /** * The creator. */ - protected final InterceptorCreator creator; + private final InterceptorCreator creator; /** * The way to convert a string to the annotation type. */ - protected final AnnotationTypeNameResolver resolver; + private final AnnotationTypeNameResolver resolver; protected TriggerFilter() { this.creator = null; @@ -212,13 +212,21 @@ protected TriggerFilter(InterceptorCreator creator, this.resolver = Objects.requireNonNull(resolver); } + Optional creator() { + return Optional.ofNullable(creator); + } + + Optional resolver() { + return Optional.ofNullable(resolver); + } + /** * Returns true if the annotation qualifies/triggers interceptor creation. * * @param annotationTypeName the annotation type name * @return true if the annotation qualifies/triggers interceptor creation */ - public boolean isQualifyingTrigger(TypeName annotationTypeName) { + boolean isQualifyingTrigger(TypeName annotationTypeName) { return (creator != null) && creator.isAllowListed(annotationTypeName); } } @@ -234,7 +242,8 @@ protected ExplicitStrategy(InterceptorCreator creator, @Override public boolean isQualifyingTrigger(TypeName annotationTypeName) { - return resolver.resolve(annotationTypeName).contains(TRIGGER) + return resolver().map(it -> it.resolve(annotationTypeName).contains(TRIGGER)) + .orElse(false) || TRIGGER_TYPE.equals(annotationTypeName); } } @@ -253,11 +262,13 @@ protected AllRuntimeStrategy(InterceptorCreator creator, @Override public boolean isQualifyingTrigger(TypeName annotationTypeName) { - Objects.requireNonNull(resolver); Objects.requireNonNull(annotationTypeName); - return (resolver.resolve(annotationTypeName).contains(RUNTIME) - || resolver.resolve(annotationTypeName).contains(CLASS) - || ALLOW_LIST.contains(annotationTypeName)); + if (ALLOW_LIST.contains(annotationTypeName)) { + return true; + } + return resolver().map(resolver -> resolver.resolve(annotationTypeName).contains(RUNTIME) + || resolver.resolve(annotationTypeName).contains(CLASS)) + .orElse(false); } } @@ -289,9 +300,13 @@ protected CustomStrategy(InterceptorCreator creator) { @Override public boolean isQualifyingTrigger(TypeName annotationTypeName) { - Objects.requireNonNull(creator); Objects.requireNonNull(annotationTypeName); - return (creator.isAllowListed(annotationTypeName) || ALLOW_LIST.contains(annotationTypeName)); + if (ALLOW_LIST.contains(annotationTypeName)) { + return true; + } + + return creator().map(it -> it.isAllowListed(annotationTypeName)) + .orElse(false); } }