Skip to content

Commit 0147ecb

Browse files
authored
Use strings for provides/requires (#835)
* use strings for provides/requires this prevents issues where auto provided/required types not available during compilation or plugin activation fail builds * allow generics in `@InjectModule` * gradle * separate generics in generated annotation
1 parent 64f5293 commit 0147ecb

File tree

10 files changed

+257
-133
lines changed

10 files changed

+257
-133
lines changed

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

Lines changed: 12 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,10 @@
66

77
import java.io.FileWriter;
88
import java.io.IOException;
9-
import java.lang.reflect.Type;
109
import java.util.ArrayList;
1110
import java.util.Arrays;
1211
import java.util.Collection;
12+
import java.util.Collections;
1313
import java.util.HashMap;
1414
import java.util.HashSet;
1515
import java.util.List;
@@ -84,24 +84,22 @@ static void registerModuleProvidedTypes(Set<String> providedTypes) {
8484
for (final var module : modules) {
8585
final var name = module.getClass().getTypeName();
8686
final var provides = new TreeSet<String>();
87-
for (final var provide : module.provides()) {
88-
provides.add(provide.getTypeName());
89-
}
90-
for (final var provide : module.autoProvides()) {
91-
provides.add(provide.getTypeName());
92-
}
93-
for (final var provide : module.autoProvidesAspects()) {
94-
final var aspectType = Util.wrapAspect(provide.getTypeName());
87+
Collections.addAll(provides, module.providesBeans());
88+
Collections.addAll(provides, module.autoProvidesBeans());
89+
for (final var provide : module.autoProvidesAspectBeans()) {
90+
final var aspectType = Util.wrapAspect(provide);
9591
provides.add(aspectType);
9692
}
9793
registerExternalMetaData(name);
9894
readMetaDataProvides(provides);
9995
providedTypes.addAll(provides);
100-
final var requires = Arrays.stream(module.requires()).map(Type::getTypeName).collect(toList());
101-
102-
Arrays.stream(module.autoRequires()).map(Type::getTypeName).forEach(requires::add);
103-
Arrays.stream(module.requiresPackages()).map(Type::getTypeName).forEach(requires::add);
104-
Arrays.stream(module.autoRequiresAspects()).map(Type::getTypeName).map(Util::wrapAspect).forEach(requires::add);
96+
final List<String> requires = new ArrayList<>();
97+
Collections.addAll(requires, module.requiresBeans());
98+
Collections.addAll(requires, module.autoRequiresBeans());
99+
Collections.addAll(requires, module.requiresPackagesFromType());
100+
Arrays.stream(module.autoRequiresAspectBeans())
101+
.map(Util::wrapAspect)
102+
.forEach(requires::add);
105103

106104
ProcessingContext.addModule(new ModuleData(name, List.copyOf(provides), requires));
107105
}

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

Lines changed: 62 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,8 @@ private void read(Element element) {
130130
ignoreSingleton = injectModule.ignoreSingleton();
131131
injectModule.requires().stream().map(Object::toString).forEach(requires::add);
132132
injectModule.provides().stream().map(Object::toString).forEach(provides::add);
133+
requires.addAll(injectModule.requiresString());
134+
provides.addAll(injectModule.providesString());
133135
injectModule.requiresPackages().stream()
134136
.map(Object::toString)
135137
.forEach(
@@ -391,12 +393,42 @@ void buildAtInjectModule(Append writer) {
391393
writer.append(Constants.AT_GENERATED).eol();
392394
writer.append("@InjectModule(");
393395
boolean leadingComma = false;
394-
if (!provides.isEmpty()) {
395-
attributeClasses(false, writer, "provides", provides);
396+
List<String> regularProvides = new ArrayList<>();
397+
List<String> genericProvides = new ArrayList<>();
398+
399+
for (var type : provides) {
400+
if (type.contains("<")) {
401+
genericProvides.add(type);
402+
} else {
403+
regularProvides.add(type);
404+
}
405+
}
406+
407+
if (!regularProvides.isEmpty()) {
408+
attributeClasses(false, writer, "provides", regularProvides);
396409
leadingComma = true;
397410
}
398-
if (!requires.isEmpty()) {
399-
attributeClasses(leadingComma, writer, "requires", requires);
411+
if (!genericProvides.isEmpty()) {
412+
attributeString(false, writer, "providesString", provides);
413+
leadingComma = true;
414+
}
415+
416+
List<String> regularRequires = new ArrayList<>();
417+
List<String> genericRequires = new ArrayList<>();
418+
419+
for (var type : requires) {
420+
if (type.contains("<")) {
421+
genericRequires.add(type);
422+
} else {
423+
regularRequires.add(type);
424+
}
425+
}
426+
if (!regularRequires.isEmpty()) {
427+
attributeClasses(leadingComma, writer, "requires", regularRequires);
428+
leadingComma = true;
429+
}
430+
if (!genericRequires.isEmpty()) {
431+
attributeString(leadingComma, writer, "requiresString", requires);
400432
leadingComma = true;
401433
}
402434
if (!requiresPackages.isEmpty()) {
@@ -412,7 +444,22 @@ void buildAtInjectModule(Append writer) {
412444
writer.append(")").eol();
413445
}
414446

415-
private void attributeClasses(boolean leadingComma, Append writer, String prefix, Set<String> classNames) {
447+
private void attributeString(boolean leadingComma, Append writer, String prefix, Set<String> classNames) {
448+
if (leadingComma) {
449+
writer.append(", ");
450+
}
451+
writer.append("%s = {", prefix);
452+
int c = 0;
453+
for (final String value : classNames) {
454+
if (c++ > 0) {
455+
writer.append(",");
456+
}
457+
writer.append("\"%s\"", value);
458+
}
459+
writer.append("}");
460+
}
461+
462+
private void attributeClasses(boolean leadingComma, Append writer, String prefix, Collection<String> classNames) {
416463
if (leadingComma) {
417464
writer.append(", ");
418465
}
@@ -429,32 +476,26 @@ private void attributeClasses(boolean leadingComma, Append writer, String prefix
429476

430477
void buildProvides(Append writer) {
431478
if (!provides.isEmpty()) {
432-
buildProvidesMethod(writer, "provides", provides);
479+
buildProvidesMethod(writer, "providesBeans", provides);
433480
}
434481
if (!requires.isEmpty()) {
435-
buildProvidesMethod(writer, "requires", requires);
482+
buildProvidesMethod(writer, "requiresBeans", requires);
436483
}
437484
if (!requiresPackages.isEmpty()) {
438-
buildProvidesMethod(writer, "requiresPackages", requiresPackages);
485+
buildProvidesMethod(writer, "requiresPackagesFromType", requiresPackages);
439486
}
440487
}
441488

442489
private void buildProvidesMethod(Append writer, String fieldName, Set<String> types) {
443490
writer.append(" @Override").eol();
444-
final var arrayType = fieldName.contains("Aspects") ? "Class<?>" : "Type";
445-
writer.append(" public %s[] %s() {", arrayType, fieldName).eol();
446-
writer.append(" return new %s[] {", arrayType).eol();
491+
writer.append(" public String[] %s() {", fieldName).eol();
492+
writer.append(" return new String[] {").eol();
447493
for (final String rawType : types) {
448494

449495
if (rawType.contains(":")) {
450496
continue;
451497
}
452-
453-
if (rawType.contains("<")) {
454-
writer.append(" new GenericType<%s>(){},", rawType).eol();
455-
} else {
456-
writer.append(" %s.class,", rawType).eol();
457-
}
498+
writer.append(" \"%s\",", rawType).eol();
458499
}
459500
writer.append(" };").eol();
460501
writer.append(" }").eol().eol();
@@ -463,28 +504,28 @@ private void buildProvidesMethod(Append writer, String fieldName, Set<String> ty
463504
void buildAutoProvides(Append writer, Set<String> autoProvides) {
464505
autoProvides.removeAll(provides);
465506
if (!autoProvides.isEmpty()) {
466-
buildProvidesMethod(writer, "autoProvides", autoProvides);
507+
buildProvidesMethod(writer, "autoProvidesBeans", autoProvides);
467508
}
468509
}
469510

470511
void buildAutoProvidesAspects(Append writer, Set<String> autoProvidesAspects) {
471512
autoProvidesAspects.removeAll(provides);
472513
if (!autoProvidesAspects.isEmpty()) {
473-
buildProvidesMethod(writer, "autoProvidesAspects", autoProvidesAspects);
514+
buildProvidesMethod(writer, "autoProvidesAspectBeans", autoProvidesAspects);
474515
}
475516
}
476517

477518
void buildAutoRequires(Append writer, Set<String> autoRequires) {
478519
autoRequires.removeAll(requires);
479520
if (!autoRequires.isEmpty()) {
480-
buildProvidesMethod(writer, "autoRequires", autoRequires);
521+
buildProvidesMethod(writer, "autoRequiresBeans", autoRequires);
481522
}
482523
}
483524

484525
void buildAutoRequiresAspects(Append writer, Set<String> autoRequires) {
485526
autoRequires.removeAll(requires);
486527
if (!autoRequires.isEmpty()) {
487-
buildProvidesMethod(writer, "autoRequiresAspects", autoRequires);
528+
buildProvidesMethod(writer, "autoRequiresAspectBeans", autoRequires);
488529
}
489530
}
490531

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

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,23 @@
11
package io.avaje.inject.generator;
22

3-
import static io.avaje.inject.generator.APContext.*;
4-
import static io.avaje.inject.generator.ProcessingContext.*;
3+
import static io.avaje.inject.generator.APContext.logError;
4+
import static io.avaje.inject.generator.APContext.typeElement;
5+
import static io.avaje.inject.generator.ProcessingContext.allScopes;
6+
import static io.avaje.inject.generator.ProcessingContext.createMetaInfWriterFor;
57
import static java.util.stream.Collectors.toList;
68
import static java.util.stream.Collectors.toSet;
79

810
import java.io.IOException;
911
import java.io.Writer;
10-
import java.util.*;
12+
import java.util.ArrayList;
13+
import java.util.HashSet;
14+
import java.util.LinkedHashMap;
15+
import java.util.LinkedHashSet;
16+
import java.util.List;
17+
import java.util.Map;
18+
import java.util.Objects;
19+
import java.util.Set;
20+
import java.util.TreeSet;
1121
import java.util.function.Predicate;
1222
import java.util.stream.Stream;
1323

inject-generator/src/test/java/io/avaje/inject/generator/models/valid/_Wiring.java

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

33
import io.avaje.inject.Factory;
44
import io.avaje.inject.InjectModule;
5-
@InjectModule(strictWiring = true)
5+
6+
@InjectModule(strictWiring = true, providesString = "java.util.Queue<java.util.String>")
67
@Factory
7-
public class _Wiring {
8-
}
8+
public class _Wiring {}

inject-gradle-plugin/build.gradle

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,15 +6,15 @@ plugins {
66
}
77

88
group 'io.avaje.inject'
9-
version '11.1'
9+
version '11.6-RC4'
1010

1111
repositories {
1212
mavenLocal()
1313
mavenCentral()
1414
}
1515

1616
dependencies {
17-
implementation 'io.avaje:avaje-inject:11.1'
17+
implementation 'io.avaje:avaje-inject:11.6-RC4'
1818
implementation gradleApi()
1919

2020
testImplementation 'org.junit.jupiter:junit-jupiter-api:5.8.1'

inject-gradle-plugin/src/main/java/io/avaje/inject/plugin/AvajeInjectPlugin.java

Lines changed: 10 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -49,8 +49,8 @@ private void writeProvides(Project project) {
4949
try (var classLoader = classLoader(project);
5050
var pluginWriter = createFileWriter(outputDir.getPath(), "avaje-plugins.csv");
5151
var moduleCSV = createFileWriter(outputDir.getPath(), "avaje-module-dependencies.csv")) {
52-
writeProvidedPlugins(classLoader, pluginWriter);
53-
writeModuleCSV(classLoader, moduleCSV);
52+
writeProvidedPlugins(classLoader, pluginWriter);
53+
writeModuleCSV(classLoader, moduleCSV);
5454
} catch (IOException e) {
5555
throw new GradleException("Failed to write avaje-module-provides", e);
5656
}
@@ -115,7 +115,8 @@ private URLClassLoader classLoader(Project project) {
115115

116116
private static URL[] createClassPath(Project project) {
117117
try {
118-
Set<File> compileClasspath = project.getConfigurations().getByName("compileClasspath").resolve();
118+
Set<File> compileClasspath =
119+
project.getConfigurations().getByName("compileClasspath").resolve();
119120
final List<URL> urls = new ArrayList<>(compileClasspath.size());
120121
for (File file : compileClasspath) {
121122
urls.add(file.toURI().toURL());
@@ -140,25 +141,15 @@ private void writeModuleCSV(ClassLoader classLoader, FileWriter moduleWriter) th
140141
System.out.println("Detected External Module: " + name);
141142

142143
final var provides = new ArrayList<String>();
143-
for (final var provide : module.provides()) {
144-
var type = provide.getTypeName();
144+
for (final var provide : module.providesBeans()) {
145+
var type = provide;
145146
provides.add(type);
146147
}
147-
for (final var provide : module.autoProvides()) {
148-
var type = provide.getTypeName();
149-
provides.add(type);
150-
}
151-
for (final var provide : module.autoProvidesAspects()) {
152-
var type = wrapAspect(provide.getTypeName());
153-
provides.add(type);
154-
}
155-
156-
final var requires = Arrays.<Type>stream(module.requires()).map(Type::getTypeName).collect(toList());
157148

158-
Arrays.<Type>stream(module.autoRequires()).map(Type::getTypeName).forEach(requires::add);
159-
Arrays.<Type>stream(module.requiresPackages()).map(Type::getTypeName).forEach(requires::add);
160-
Arrays.<Type>stream(module.autoRequiresAspects())
161-
.map(Type::getTypeName)
149+
final var requires = Arrays.stream(module.requiresBeans()).collect(toList());
150+
Collections.addAll(requires, module.requiresPackagesFromType());
151+
Arrays.stream(module.autoRequiresAspects())
152+
.map(Class::getTypeName)
162153
.map(AvajeInjectPlugin::wrapAspect)
163154
.forEach(requires::add);
164155
modules.add(new ModuleData(name, provides, requires));

inject-maven-plugin/src/main/java/io/avaje/inject/mojo/AutoProvidesMojo.java

Lines changed: 16 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@
55
import java.io.File;
66
import java.io.FileWriter;
77
import java.io.IOException;
8-
import java.lang.reflect.Type;
98
import java.net.MalformedURLException;
109
import java.net.URL;
1110
import java.net.URLClassLoader;
@@ -108,14 +107,15 @@ private void writeProvidedPlugins(URLClassLoader newClassLoader, FileWriter plug
108107
final Map<String, List<String>> pluginEntries = new HashMap<>();
109108
for (final var plugin : plugins) {
110109
final List<String> provides = new ArrayList<>();
111-
final var typeName = plugin.getClass().getTypeName();
110+
final var typeName = plugin.getClass();
112111
log.info("Loaded Plugin: " + typeName);
113112
for (final var provide : plugin.provides()) {
114113
provides.add(provide.getTypeName());
115114
}
116115
for (final var provide : plugin.providesAspects()) {
117116
provides.add(wrapAspect(provide.getCanonicalName()));
118117
}
118+
pluginEntries.put(typeName.getTypeName(), provides);
119119
Optional.ofNullable(plugin.getClass().getAnnotation(PluginProvides.class))
120120
.ifPresent(p -> {
121121
for (final var provide : p.value()) {
@@ -127,7 +127,6 @@ private void writeProvidedPlugins(URLClassLoader newClassLoader, FileWriter plug
127127
}
128128
p.providesStrings();
129129
});
130-
pluginEntries.put(typeName, provides);
131130
}
132131

133132
pluginWriter.write("External Plugin Type|Provides");
@@ -151,35 +150,33 @@ private void writeModuleCSV(ClassLoader newClassLoader, FileWriter moduleWriter)
151150

152151
List<ModuleData> modules = new ArrayList<>();
153152
for (final var module : avajeModules) {
154-
final var name = module.getClass().getTypeName();
153+
final var name = module.getClass();
155154
log.info("Detected External Module: " + name);
156155

157156
final var provides = new ArrayList<String>();
158-
for (final var provide : module.provides()) {
159-
var type = provide.getTypeName();
157+
for (final var provide : module.providesBeans()) {
158+
var type = provide;
160159
provides.add(type);
161160
}
162161

163-
for (final var provide : module.autoProvides()) {
164-
var type = provide.getTypeName();
162+
for (final var provide : module.autoProvidesBeans()) {
163+
var type = provide;
165164
provides.add(type);
166165
}
167166

168-
for (final var provide : module.autoProvidesAspects()) {
169-
var type = wrapAspect(provide.getTypeName());
167+
for (final var provide : module.autoProvidesAspectBeans()) {
168+
var type = wrapAspect(provide);
170169
provides.add(type);
171170
}
172171

173-
final var requires =
174-
Arrays.<Type>stream(module.requires()).map(Type::getTypeName).collect(toList());
172+
final var requires = Arrays.stream(module.requiresBeans()).collect(toList());
175173

176-
Arrays.<Type>stream(module.autoRequires()).map(Type::getTypeName).forEach(requires::add);
177-
Arrays.<Type>stream(module.requiresPackages()).map(Type::getTypeName).forEach(requires::add);
178-
Arrays.<Type>stream(module.autoRequiresAspects())
179-
.map(Type::getTypeName)
180-
.map(AutoProvidesMojo::wrapAspect)
181-
.forEach(requires::add);
182-
modules.add(new ModuleData(name, provides, requires));
174+
Collections.addAll(requires, module.autoRequiresBeans());
175+
Collections.addAll(requires, module.requiresPackagesFromType());
176+
Arrays.stream(module.autoRequiresAspectBeans())
177+
.map(AutoProvidesMojo::wrapAspect)
178+
.forEach(requires::add);
179+
modules.add(new ModuleData(name.getTypeName(), provides, requires));
183180
}
184181

185182
moduleWriter.write("External Module Type|Provides|Requires");

0 commit comments

Comments
 (0)