Skip to content

Commit e3281dd

Browse files
committed
Format and extract helper methods
1 parent 5a1204d commit e3281dd

File tree

4 files changed

+129
-134
lines changed

4 files changed

+129
-134
lines changed

blackbox-aspect/src/main/java/org/example/external/aspect/spi/AspectPlugin.java

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@ public class AspectPlugin implements InjectPlugin {
1111

1212
@Override
1313
public Class<?>[] provides() {
14-
1514
return new Class<?>[] {PluginProvidedClass.class};
1615
}
1716

inject-generator/src/main/java/io/avaje/inject/generator/ExternalProvider.java

Lines changed: 102 additions & 111 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22

33
import static java.util.List.of;
44
import static java.util.Map.entry;
5-
import static java.util.stream.Collectors.joining;
65
import static java.util.stream.Collectors.toList;
76

87
import java.io.FileWriter;
@@ -113,8 +112,7 @@ static void registerModuleProvidedTypes(Set<String> providedTypes) {
113112
static void registerPluginProvidedTypes(ScopeInfo defaultScope) {
114113
if (!INJECT_AVAILABLE) {
115114
if (!pluginExists("avaje-module-dependencies.csv")) {
116-
APContext.logNote(
117-
"Unable to detect Avaje Inject Maven/Gradle plugin, use the Avaje Inject Maven/Gradle plugin for auto detecting External Inject Plugins/Modules from dependencies");
115+
APContext.logNote("Unable to detect Avaje Inject Maven/Gradle plugin, use the Avaje Inject Maven/Gradle plugin for auto detecting External Inject Plugins/Modules from dependencies");
118116
}
119117
return;
120118
}
@@ -165,162 +163,155 @@ static void readMetaDataProvides(Collection<String> providedTypes) {
165163
}
166164

167165
static void scanAllInjectPlugins(ScopeInfo defaultScope) {
168-
final var noPlugins = !defaultScope.pluginProvided().isEmpty();
169-
170-
avajePlugins.forEach(
171-
(k, v) -> {
172-
if (APContext.typeElement(k) != null) {
173-
APContext.logNote("Loaded Plugin: %s", k);
174-
v.forEach(defaultScope::pluginProvided);
175-
}
176-
});
166+
final var hasPlugins = !defaultScope.pluginProvided().isEmpty();
167+
avajePlugins.forEach((k, v) -> {
168+
if (APContext.typeElement(k) != null) {
169+
APContext.logNote("Loaded Plugin: %s", k);
170+
v.forEach(defaultScope::pluginProvided);
171+
}
172+
});
177173
defaultScope.pluginProvided("io.avaje.inject.event.ObserverManager");
178-
179-
if (noPlugins) {
174+
if (hasPlugins) {
180175
return;
181176
}
182177

183-
var stream = getInjectExtensions();
184-
stream
185-
.filter(PluginProvidesPrism::isPresent)
186-
.distinct()
187-
.forEach(
188-
t -> {
189-
final var name = t.getQualifiedName().toString();
190-
if (avajePlugins.containsKey(name)) {
191-
return;
192-
}
193-
194-
var prism = PluginProvidesPrism.getInstanceOn(t);
195-
196-
for (final var provide : prism.provides()) {
197-
defaultScope.pluginProvided(provide.toString());
198-
}
199-
for (final var provide : prism.providesStrings()) {
200-
defaultScope.pluginProvided(provide);
201-
}
202-
for (final var provide : prism.providesAspects()) {
203-
defaultScope.pluginProvided(Util.wrapAspect(provide.toString()));
204-
}
205-
206-
APContext.logNote("Loaded Plugin: %s", name);
207-
});
178+
injectExtensions()
179+
.filter(PluginProvidesPrism::isPresent)
180+
.distinct()
181+
.forEach(pluginType -> addPluginToScope(defaultScope, pluginType));
182+
208183
if (defaultScope.pluginProvided().isEmpty()) {
209184
APContext.logNote("No external plugins detected");
210185
}
186+
writePluginProvides(defaultScope);
187+
}
211188

189+
private static void writePluginProvides(ScopeInfo defaultScope) {
212190
// write detected plugins to a text file for test compilation
213-
try (var pluginWriter =
214-
new FileWriter(APContext.getBuildResource("avaje-plugin-provides.txt").toFile())) {
215-
191+
try (final var pluginWriter = new FileWriter(APContext.getBuildResource("avaje-plugin-provides.txt").toFile())) {
216192
for (var providedType : defaultScope.pluginProvided()) {
217-
218193
pluginWriter.write(providedType);
219194
pluginWriter.write("\n");
220195
}
221-
222196
} catch (IOException e) {
223-
e.printStackTrace();
197+
APContext.logWarn("Failed to write avaje-plugin-provides.txt due to %s", e.getMessage());
224198
}
225199
}
226200

201+
private static void addPluginToScope(ScopeInfo defaultScope, TypeElement pluginType) {
202+
final var name = pluginType.getQualifiedName().toString();
203+
if (avajePlugins.containsKey(name)) {
204+
return;
205+
}
206+
var prism = PluginProvidesPrism.getInstanceOn(pluginType);
207+
for (final var provide : prism.provides()) {
208+
defaultScope.pluginProvided(provide.toString());
209+
}
210+
for (final var provide : prism.providesStrings()) {
211+
defaultScope.pluginProvided(provide);
212+
}
213+
for (final var provide : prism.providesAspects()) {
214+
defaultScope.pluginProvided(Util.wrapAspect(provide.toString()));
215+
}
216+
APContext.logNote("Loaded Plugin: %s", name);
217+
}
218+
227219
static void scanAllAvajeModules(Collection<String> providedTypes) {
228220
if (!externalMeta.isEmpty()) {
229221
return;
230222
}
231-
var stream = getInjectExtensions();
232-
233-
var types = APContext.types();
234-
var spi = APContext.typeElement("io.avaje.inject.spi.AvajeModule").asType();
235-
stream
236-
.filter(t -> t.getInterfaces().stream().anyMatch(i -> types.isAssignable(i, spi)))
237-
.distinct()
238-
.forEach(
239-
t -> {
240-
final var provides = new HashSet<String>();
241-
final var requires = new HashSet<String>();
242-
243-
ElementFilter.methodsIn(t.getEnclosedElements()).stream()
244-
.map(DependencyMetaPrism::getInstanceOn)
245-
.filter(Objects::nonNull)
246-
.map(MetaData::new)
247-
.forEach(
248-
m -> {
249-
externalMeta.add(m);
250-
provides.addAll(m.autoProvides());
251-
provides.addAll(m.provides());
252-
m.dependsOn().stream()
253-
.filter(d -> !d.isSoftDependency())
254-
.map(Dependency::name)
255-
.forEach(requires::add);
256-
257-
providedTypes.add(m.key());
258-
providedTypes.add(m.type());
259-
providedTypes.addAll(Util.addQualifierSuffix(m.provides(), m.name()));
260-
providedTypes.addAll(Util.addQualifierSuffix(m.autoProvides(), m.name()));
261-
});
262-
263-
final var name = t.getQualifiedName().toString();
264-
APContext.logNote("Detected Module: %s", name);
265-
ProcessingContext.addModule(
266-
new ModuleData(name, List.copyOf(provides), List.copyOf(requires)));
267-
});
223+
final var types = APContext.types();
224+
final var avajeModuleType = APContext.typeElement("io.avaje.inject.spi.AvajeModule").asType();
225+
injectExtensions()
226+
.filter(t -> t.getInterfaces().stream().anyMatch(i -> types.isAssignable(i, avajeModuleType)))
227+
.distinct()
228+
.forEach(otherModule -> addOtherModuleProvides(providedTypes, otherModule));
229+
268230
if (externalMeta.isEmpty()) {
269231
APContext.logNote("No external modules detected");
270232
}
233+
writeModuleDependencies();
234+
}
271235

236+
private static void writeModuleDependencies() {
272237
// write detected modules to a csv for test compilation
273-
try (var moduleWriter =
274-
new FileWriter(APContext.getBuildResource("avaje-module-dependencies.csv").toFile())) {
275-
238+
try (final var moduleWriter = new FileWriter(APContext.getBuildResource("avaje-module-dependencies.csv").toFile())) {
276239
moduleWriter.write("External Module Type|Provides|Requires");
277240
for (ModuleData avajeModule : ProcessingContext.modules()) {
278241
moduleWriter.write("\n");
279242
moduleWriter.write(avajeModule.name());
280243
moduleWriter.write("|");
281-
var provides = avajeModule.provides().stream().collect(joining(","));
244+
var provides = String.join(",", avajeModule.provides());
282245
moduleWriter.write(provides.isEmpty() ? " " : provides);
283246
moduleWriter.write("|");
284-
var requires = avajeModule.requires().stream().collect(joining(","));
247+
var requires = String.join(",", avajeModule.requires());
285248
moduleWriter.write(requires.isEmpty() ? " " : requires);
286249
}
287250

288251
} catch (IOException e) {
289-
e.printStackTrace();
252+
APContext.logWarn("Failed to write avaje-module-dependencies.csv due to %s", e.getMessage());
290253
}
291254
}
292255

293-
private static Stream<TypeElement> getInjectExtensions() {
294-
var allModules =
295-
APContext.elements().getAllModuleElements().stream()
296-
.filter(m -> !m.getQualifiedName().toString().startsWith("java"))
297-
.filter(m -> !m.getQualifiedName().toString().startsWith("jdk"))
298-
// for whatever reason, compilation breaks if we don't filter out the current module
299-
.filter(m -> !m.equals(APContext.getProjectModuleElement()))
300-
.collect(toList());
256+
private static void addOtherModuleProvides(Collection<String> providedTypes, TypeElement otherModule) {
257+
final var provides = new HashSet<String>();
258+
final var requires = new HashSet<String>();
259+
260+
ElementFilter.methodsIn(otherModule.getEnclosedElements()).stream()
261+
.map(DependencyMetaPrism::getInstanceOn)
262+
.filter(Objects::nonNull)
263+
.map(MetaData::new)
264+
.forEach(m -> {
265+
externalMeta.add(m);
266+
provides.addAll(m.autoProvides());
267+
provides.addAll(m.provides());
268+
m.dependsOn().stream()
269+
.filter(d -> !d.isSoftDependency())
270+
.map(Dependency::name)
271+
.forEach(requires::add);
272+
273+
providedTypes.add(m.key());
274+
providedTypes.add(m.type());
275+
providedTypes.addAll(Util.addQualifierSuffix(m.provides(), m.name()));
276+
providedTypes.addAll(Util.addQualifierSuffix(m.autoProvides(), m.name()));
277+
});
278+
279+
final var name = otherModule.getQualifiedName().toString();
280+
APContext.logNote("Detected Module: %s", name);
281+
ProcessingContext.addModule(new ModuleData(name, List.copyOf(provides), List.copyOf(requires)));
282+
}
283+
284+
private static Stream<TypeElement> injectExtensions() {
285+
final var allModules =
286+
APContext.elements().getAllModuleElements().stream()
287+
.filter(m -> !m.getQualifiedName().toString().startsWith("java"))
288+
.filter(m -> !m.getQualifiedName().toString().startsWith("jdk"))
289+
// for whatever reason, compilation breaks if we don't filter out the current module
290+
.filter(m -> !m.equals(APContext.getProjectModuleElement()))
291+
.collect(toList());
301292

302-
var types = APContext.types();
303-
var spi = APContext.typeElement("io.avaje.inject.spi.InjectExtension").asType();
293+
final var types = APContext.types();
294+
final var extensionType = APContext.typeElement("io.avaje.inject.spi.InjectExtension").asType();
304295

305296
final var checkEnclosing =
306-
allModules.stream()
307-
.flatMap(m -> m.getEnclosedElements().stream())
308-
.flatMap(p -> p.getEnclosedElements().stream())
309-
.map(TypeElement.class::cast)
310-
.filter(t -> t.getKind() == ElementKind.CLASS)
311-
.filter(t -> t.getModifiers().contains(Modifier.PUBLIC))
312-
.filter(t -> types.isAssignable(t.asType(), spi));
297+
allModules.stream()
298+
.flatMap(m -> m.getEnclosedElements().stream())
299+
.flatMap(p -> p.getEnclosedElements().stream())
300+
.map(TypeElement.class::cast)
301+
.filter(t -> t.getKind() == ElementKind.CLASS)
302+
.filter(t -> t.getModifiers().contains(Modifier.PUBLIC))
303+
.filter(t -> types.isAssignable(t.asType(), extensionType));
313304

314305
final var checkDirectives =
315-
allModules.stream()
316-
.flatMap(m -> ElementFilter.providesIn(m.getDirectives()).stream())
317-
.filter(ExternalProvider::isInjectExtension)
318-
.flatMap(p -> p.getImplementations().stream());
306+
allModules.stream()
307+
.flatMap(m -> ElementFilter.providesIn(m.getDirectives()).stream())
308+
.filter(ExternalProvider::isInjectExtension)
309+
.flatMap(p -> p.getImplementations().stream());
310+
319311
return Stream.concat(checkEnclosing, checkDirectives);
320312
}
321313

322314
private static boolean isInjectExtension(ModuleElement.ProvidesDirective p) {
323-
return "io.avaje.inject.spi.InjectExtension"
324-
.equals(p.getService().getQualifiedName().toString());
315+
return "io.avaje.inject.spi.InjectExtension".equals(p.getService().getQualifiedName().toString());
325316
}
326317
}

inject-generator/src/main/java/io/avaje/inject/generator/InjectProcessor.java

Lines changed: 10 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -350,24 +350,16 @@ private void registerSPI(Set<? extends Element> beans) {
350350
}
351351

352352
private boolean isExtension(TypeElement te) {
353-
354-
PluginProvidesPrism.getOptionalOn(te)
355-
.ifPresent(
356-
t -> {
357-
if (!APContext.isAssignable(te, "io.avaje.inject.spi.InjectPlugin")) {
358-
APContext.logError(
359-
te, "PluginProvides can only be placed on io.avaje.inject.spi.InjectPlugin");
360-
}
361-
});
362-
363-
ServiceProviderPrism.getOptionalOn(te)
364-
.ifPresent(
365-
t -> {
366-
if (APContext.isAssignable(te, "io.avaje.inject.spi.InjectPlugin")) {
367-
APContext.logWarn(
368-
te, "PluginProvides should be used to auto register InjectPlugins");
369-
}
370-
});
353+
PluginProvidesPrism.getOptionalOn(te).ifPresent(t -> {
354+
if (!APContext.isAssignable(te, "io.avaje.inject.spi.InjectPlugin")) {
355+
APContext.logError(te, "PluginProvides can only be placed on io.avaje.inject.spi.InjectPlugin");
356+
}
357+
});
358+
ServiceProviderPrism.getOptionalOn(te).ifPresent(t -> {
359+
if (APContext.isAssignable(te, "io.avaje.inject.spi.InjectPlugin")) {
360+
APContext.logWarn(te, "PluginProvides should be used to auto register InjectPlugins");
361+
}
362+
});
371363

372364
return APContext.isAssignable(te, "io.avaje.inject.spi.InjectExtension");
373365
}

inject/src/main/java/io/avaje/inject/spi/PluginProvides.java

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,17 +5,30 @@
55
import java.lang.annotation.RetentionPolicy;
66
import java.lang.annotation.Target;
77

8-
/** Registers {@link InjectPlugin} classes for auto detection */
8+
/**
9+
* Registers {@link InjectPlugin} classes for auto-detection.
10+
* <p>
11+
* Plugins can be registered traditionally via service loading etc but
12+
* if we use this {@code @PluginProvides} annotation, then avaje inject
13+
* can ALSO auto-detect the plugin and the types that it provides.
14+
* Otherwise, we need to use Maven/Gradle plugins to perform this detection.
15+
*/
916
@Target(ElementType.TYPE)
1017
@Retention(RetentionPolicy.CLASS)
1118
public @interface PluginProvides {
1219

13-
/** The types this plugin provides. */
20+
/**
21+
* The types this plugin provides.
22+
*/
1423
Class<?>[] provides() default {};
1524

16-
/** Fully Qualified Strings of the classes provided. Use when providing generic types */
25+
/**
26+
* Fully Qualified Strings of the classes provided. Use when providing generic types
27+
*/
1728
String[] providesStrings() default {};
1829

19-
/** The aspects this component provides. */
30+
/**
31+
* The aspects this component provides.
32+
*/
2033
Class<?>[] providesAspects() default {};
2134
}

0 commit comments

Comments
 (0)