1
1
package io .avaje .http .generator .core ;
2
2
3
- import java .io .BufferedReader ;
4
3
import java .io .IOException ;
5
- import java .io .InputStreamReader ;
6
4
import java .net .URI ;
7
5
import java .nio .file .Paths ;
8
- import java .util .Collection ;
9
6
import java .util .List ;
10
7
import java .util .Objects ;
11
8
import java .util .Optional ;
12
- import java .util .Set ;
13
9
import java .util .stream .Collectors ;
14
10
import java .util .stream .Stream ;
15
11
16
12
import javax .annotation .processing .Filer ;
17
13
import javax .annotation .processing .Messager ;
18
14
import javax .annotation .processing .ProcessingEnvironment ;
19
- import javax .annotation .processing .RoundEnvironment ;
20
15
import javax .lang .model .element .Element ;
21
16
import javax .lang .model .element .ExecutableElement ;
22
17
import javax .lang .model .element .ModuleElement ;
31
26
import javax .tools .JavaFileObject ;
32
27
import javax .tools .StandardLocation ;
33
28
29
+ import io .avaje .http .generator .core .ModuleInfoReader .Provides ;
34
30
import io .avaje .http .generator .core .openapi .DocContext ;
35
31
36
32
public final class ProcessingContext {
@@ -53,8 +49,9 @@ private static final class Ctx {
53
49
private final boolean instrumentAllMethods ;
54
50
private final boolean disableDirectWrites ;
55
51
private final boolean javalin6 ;
56
- private ModuleElement module ;
52
+ private final boolean spiPresent = APContext . typeElement ( "io.avaje.spi.internal.ServiceProcessor" ) != null ;
57
53
private boolean validated ;
54
+ private String clientFQN ;
58
55
59
56
Ctx (ProcessingEnvironment env , PlatformAdapter adapter , boolean generateOpenAPI ) {
60
57
readAdapter = adapter ;
@@ -146,7 +143,12 @@ public static JavaFileObject createWriter(String cls, Element origin) throws IOE
146
143
147
144
/** Create a file writer for the META-INF services file. */
148
145
public static FileObject createMetaInfWriter (String target ) throws IOException {
149
- return CTX .get ().filer .createResource (StandardLocation .CLASS_OUTPUT , "" , target );
146
+ var serviceFile =
147
+ CTX .get ().spiPresent
148
+ ? target .replace ("META-INF/services/" , "META-INF/generated-services/" )
149
+ : target ;
150
+
151
+ return filer ().createResource (StandardLocation .CLASS_OUTPUT , "" , serviceFile );
150
152
}
151
153
152
154
public static JavaFileObject createWriter (String cls ) throws IOException {
@@ -175,7 +177,7 @@ public static List<ExecutableElement> superMethods(Element element, String metho
175
177
.filter (type -> !type .toString ().contains ("java.lang.Object" ))
176
178
.map (superType -> {
177
179
final var superClass = (TypeElement ) types .asElement (superType );
178
- for (final ExecutableElement method : ElementFilter .methodsIn (CTX .get ().elementUtils .getAllMembers (superClass ))) {
180
+ for (final var method : ElementFilter .methodsIn (CTX .get ().elementUtils .getAllMembers (superClass ))) {
179
181
if (method .getSimpleName ().contentEquals (methodName )) {
180
182
return method ;
181
183
}
@@ -231,45 +233,33 @@ public static boolean isAssignable2Interface(String type, String superType) {
231
233
static Stream <String > superTypes (Element element ) {
232
234
final Types types = CTX .get ().typeUtils ;
233
235
return types .directSupertypes (element .asType ()).stream ()
234
- .filter (type -> !type .toString ().contains ("java.lang.Object" ))
235
- .map (superType -> (TypeElement ) types .asElement (superType ))
236
- .flatMap (e -> Stream .concat (superTypes (e ), Stream .of (e )))
237
- .map (Object ::toString );
238
- }
239
-
240
- public static void findModule (Set <? extends TypeElement > annotations , RoundEnvironment roundEnv ) {
241
- if (CTX .get ().module == null ) {
242
- CTX .get ().module =
243
- annotations .stream ()
244
- .map (roundEnv ::getElementsAnnotatedWith )
245
- .flatMap (Collection ::stream )
246
- .findAny ()
247
- .map (ProcessingContext ::getModuleElement )
248
- .orElse (null );
249
- }
236
+ .filter (type -> !type .toString ().contains ("java.lang.Object" ))
237
+ .map (superType -> (TypeElement ) types .asElement (superType ))
238
+ .flatMap (e -> Stream .concat (superTypes (e ), Stream .of (e )))
239
+ .map (Object ::toString );
250
240
}
251
241
252
- public static void validateModule (String fqn ) {
253
- var module = CTX . get (). module ;
242
+ public static void validateModule () {
243
+ var module = APContext . getProjectModuleElement () ;
254
244
if (module != null && !CTX .get ().validated && !module .isUnnamed ()) {
255
-
256
245
CTX .get ().validated = true ;
257
- try (var inputStream =
258
- CTX . get ()
259
- . filer
260
- . getResource ( StandardLocation . SOURCE_PATH , "" , "module-info.java" )
261
- . toUri ()
262
- . toURL ()
263
- . openStream ( );
264
- var reader = new BufferedReader ( new InputStreamReader ( inputStream ))) {
265
-
266
- var noProvides = reader . lines (). map ( s -> {
267
- if ( s . contains ( "io.avaje.http.api.javalin" ) && ! s . contains ( "static" )) {
268
- logWarn ( "io.avaje.http.api.javalin only contains SOURCE retention annotations. It should added as `requires static`" );
269
- }
270
- return s ;
271
- } )
246
+ try (var bufferedReader = APContext . getModuleInfoReader ()) {
247
+ var reader = new ModuleInfoReader ( module , bufferedReader );
248
+ reader . requires (). forEach ( r -> {
249
+ if (! r . isStatic () && r . getDependency (). getQualifiedName (). contentEquals ( "io.avaje.http.api.javalin" )) {
250
+ logWarn ( module , "io.avaje.http.api.javalin only contains SOURCE retention annotations. It should added as `requires static`" );
251
+ }
252
+ } );
253
+ var fqn = CTX . get (). clientFQN ;
254
+ if ( CTX . get (). spiPresent || fqn == null ) {
255
+ return ;
256
+ }
257
+ var noProvides = reader . provides (). stream ()
258
+ . filter ( p -> "io.avaje.http.client.HttpClient.GeneratedComponent" . equals ( p . service ()))
259
+ . map ( Provides :: implementations )
260
+ . flatMap ( List :: stream )
272
261
.noneMatch (s -> s .contains (fqn ));
262
+
273
263
if (noProvides && !buildPluginAvailable ()) {
274
264
logError (module , "Missing `provides io.avaje.http.client.HttpClient.GeneratedComponent with %s;`" , fqn );
275
265
}
@@ -309,4 +299,8 @@ private static boolean resourceExists(String relativeName) {
309
299
return false ;
310
300
}
311
301
}
302
+
303
+ public static void addClientComponent (String clientFQN ) {
304
+ CTX .get ().clientFQN = clientFQN ;
305
+ }
312
306
}
0 commit comments