Skip to content

Commit bf8ed75

Browse files
committed
ArC: simplify generating names of generated classes
- the generated class names are binary names now, instead of internal names (that is, they use `.` as a separator, not `/`) - the attempt to replace `$` as a nested type separator with `_` is removed (it has never been necessary and it has always been imprecise, because it did the replacement for only _one_ level of class nesting) - deprecated (for removal) many unnecessary methods from `DotNames`; the only retained method is `packageName()`, now called `packagePrefix()`, - the special type function passed to `ResourceClassOutput` is now explicitly documented to accept a binary name of the class
1 parent 9420e67 commit bf8ed75

File tree

15 files changed

+118
-213
lines changed

15 files changed

+118
-213
lines changed

independent-projects/arc/processor/src/main/java/io/quarkus/arc/processor/AbstractGenerator.java

Lines changed: 31 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -47,70 +47,59 @@ static Gizmo gizmo(ClassOutput classOutput) {
4747
}
4848

4949
/**
50-
* Create a generated bean name from a bean package. When bean is located
51-
* in a default package (i.e. a classpath root), the target package name
52-
* is empty string. This need to be taken into account when creating
53-
* generated bean name because it is later used to build class file path
54-
* and we do not want it to start from a slash because it will point root
55-
* directory instead of a relative one. This method will address this
56-
* problem.<br>
57-
* <br>
58-
* Example generated bean names (without quotes):
59-
* <ol>
60-
* <li>a <i>"io/quarcus/foo/FooService_Bean"</i>, when in io.quarcus.foo package,</li>
61-
* <li>a <i>"BarService_Bean"</i>, when in default package.</li>
62-
* </ol>
50+
* Generates a class name from a target package, base name and suffix. When the class
51+
* is located in a default package, the target package name is an empty string.
6352
*
64-
* @param baseName a bean name (class name)
65-
* @param targetPackage a package where bean is located
66-
* @return Generated name
53+
* @param targetPackage name of the target package
54+
* @param baseName simple class name
55+
* @param suffix suffix to append to the generated name
56+
* @return generated name
6757
*/
6858
static String generatedNameFromTarget(String targetPackage, String baseName, String suffix) {
6959
if (targetPackage == null || targetPackage.isEmpty()) {
7060
return baseName + suffix;
7161
} else {
72-
return targetPackage.replace('.', '/') + "/" + baseName + suffix;
62+
return targetPackage + "." + baseName + suffix;
7363
}
7464
}
7565

76-
protected String getBaseName(String beanClassName) {
77-
String name = Types.getSimpleName(beanClassName);
78-
return name.substring(0, name.lastIndexOf(BeanGenerator.BEAN_SUFFIX));
66+
/**
67+
* {@return a simple name of the given {@code beanClassName}, stripped of the {@link BeanGenerator#BEAN_SUFFIX}}
68+
*/
69+
protected final String getBeanBaseName(String beanClassName) {
70+
String simpleName = beanClassName.contains(".")
71+
? beanClassName.substring(beanClassName.lastIndexOf(".") + 1)
72+
: beanClassName;
73+
return simpleName.substring(0, simpleName.lastIndexOf(BeanGenerator.BEAN_SUFFIX));
7974
}
8075

81-
protected boolean isReflectionFallbackNeeded(MethodInfo method, String targetPackage) {
82-
// Reflection fallback is needed for private methods and non-public methods declared on superclasses located in a different package
76+
protected final boolean isReflectionFallbackNeeded(MethodInfo method, String targetPackage) {
77+
if (Modifier.isPublic(method.flags())) {
78+
return false;
79+
}
80+
// Reflection fallback is needed for:
81+
// 1. private methods
8382
if (Modifier.isPrivate(method.flags())) {
8483
return true;
8584
}
86-
if (Modifier.isProtected(method.flags()) || isPackagePrivate(method.flags())) {
87-
return !DotNames.packageName(method.declaringClass().name()).equals(targetPackage);
88-
}
89-
return false;
85+
// 2. non-public methods declared on superclasses located in a different package
86+
return !DotNames.packagePrefix(method.declaringClass().name()).equals(targetPackage);
9087
}
9188

92-
protected boolean isReflectionFallbackNeeded(FieldInfo field, String targetPackage, BeanInfo bean) {
93-
// Reflection fallback is needed for private fields if the transformation config is set to false
94-
// and for non-public fields declared on superclasses located in a different package
89+
protected final boolean isReflectionFallbackNeeded(FieldInfo field, String targetPackage, BeanInfo bean) {
90+
if (Modifier.isPublic(field.flags())) {
91+
return false;
92+
}
93+
// Reflection fallback is needed for:
94+
// 1. private fields if the transformation is turned off OR if the field's declaring class != bean class
9595
if (Modifier.isPrivate(field.flags())) {
96-
// if the transformation is turned off OR if the field's declaring class != bean class, we need reflection
9796
if (!bean.getDeployment().transformPrivateInjectedFields
9897
|| !field.declaringClass().name().equals(bean.getBeanClass())) {
9998
return true;
100-
} else {
101-
// this is for cases when we want to perform transformation but the class with private field is also
102-
// extended by another bean in completely different package - we'll still need reflection there
103-
return !DotNames.packageName(field.declaringClass().name()).equals(targetPackage);
10499
}
105100
}
106-
if (Modifier.isProtected(field.flags()) || isPackagePrivate(field.flags())) {
107-
return !DotNames.packageName(field.declaringClass().name()).equals(targetPackage);
108-
}
109-
return false;
110-
}
111-
112-
protected boolean isPackagePrivate(int mod) {
113-
return !(Modifier.isPrivate(mod) || Modifier.isProtected(mod) || Modifier.isPublic(mod));
101+
// 2. for non-public fields declared on superclasses located in a different package
102+
return !DotNames.packagePrefix(field.declaringClass().name()).equals(targetPackage);
114103
}
115104

116105
}

independent-projects/arc/processor/src/main/java/io/quarkus/arc/processor/BeanGenerator.java

Lines changed: 13 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,6 @@
2929
import jakarta.enterprise.context.spi.CreationalContext;
3030
import jakarta.enterprise.inject.CreationException;
3131
import jakarta.enterprise.inject.IllegalProductException;
32-
import jakarta.enterprise.inject.TransientReference;
3332
import jakarta.enterprise.inject.UnproxyableResolutionException;
3433
import jakarta.enterprise.inject.literal.InjectLiteral;
3534
import jakarta.enterprise.inject.spi.InterceptionType;
@@ -144,28 +143,17 @@ void precomputeGeneratedName(BeanInfo bean) {
144143

145144
private void generateClassBeanName(BeanInfo bean) {
146145
ClassInfo beanClass = bean.getTarget().get().asClass();
147-
String baseName;
148-
if (beanClass.enclosingClass() != null) {
149-
baseName = DotNames.simpleName(beanClass.enclosingClass()) + UNDERSCORE + DotNames.simpleName(beanClass);
150-
} else {
151-
baseName = DotNames.simpleName(beanClass);
152-
}
146+
String baseName = beanClass.name().withoutPackagePrefix();
153147
this.beanToGeneratedBaseName.put(bean, baseName);
154-
String targetPackage = DotNames.packageName(bean.getProviderType().name());
148+
String targetPackage = DotNames.packagePrefix(bean.getProviderType().name());
155149
String generatedName = generatedNameFromTarget(targetPackage, baseName, BEAN_SUFFIX);
156150
this.beanToGeneratedName.put(bean, generatedName);
157151
}
158152

159153
private void generateProducerMethodBeanName(BeanInfo bean) {
160154
MethodInfo producerMethod = bean.getTarget().get().asMethod();
161155
ClassInfo declaringClass = producerMethod.declaringClass();
162-
String declaringClassBase;
163-
if (declaringClass.enclosingClass() != null) {
164-
declaringClassBase = DotNames.simpleName(declaringClass.enclosingClass()) + UNDERSCORE
165-
+ DotNames.simpleName(declaringClass);
166-
} else {
167-
declaringClassBase = DotNames.simpleName(declaringClass);
168-
}
156+
String declaringClassBase = declaringClass.name().withoutPackagePrefix();
169157

170158
StringBuilder sigBuilder = new StringBuilder();
171159
sigBuilder.append(producerMethod.name())
@@ -178,42 +166,26 @@ private void generateProducerMethodBeanName(BeanInfo bean) {
178166
String baseName = declaringClassBase + PRODUCER_METHOD_SUFFIX + UNDERSCORE + producerMethod.name() + UNDERSCORE
179167
+ Hashes.sha1_base64(sigBuilder.toString());
180168
this.beanToGeneratedBaseName.put(bean, baseName);
181-
String targetPackage = DotNames.packageName(declaringClass.name());
169+
String targetPackage = DotNames.packagePrefix(declaringClass.name());
182170
String generatedName = generatedNameFromTarget(targetPackage, baseName, BEAN_SUFFIX);
183171
this.beanToGeneratedName.put(bean, generatedName);
184172
}
185173

186174
private void generateProducerFieldBeanName(BeanInfo bean) {
187175
FieldInfo producerField = bean.getTarget().get().asField();
188176
ClassInfo declaringClass = producerField.declaringClass();
189-
String declaringClassBase;
190-
if (declaringClass.enclosingClass() != null) {
191-
declaringClassBase = DotNames.simpleName(declaringClass.enclosingClass()) + UNDERSCORE
192-
+ DotNames.simpleName(declaringClass);
193-
} else {
194-
declaringClassBase = DotNames.simpleName(declaringClass);
195-
}
177+
String declaringClassBase = declaringClass.name().withoutPackagePrefix();
196178

197179
String baseName = declaringClassBase + PRODUCER_FIELD_SUFFIX + UNDERSCORE + producerField.name();
198180
this.beanToGeneratedBaseName.put(bean, baseName);
199-
String targetPackage = DotNames.packageName(declaringClass.name());
181+
String targetPackage = DotNames.packagePrefix(declaringClass.name());
200182
String generatedName = generatedNameFromTarget(targetPackage, baseName, BEAN_SUFFIX);
201183
this.beanToGeneratedName.put(bean, generatedName);
202184
}
203185

204186
private void generateSyntheticBeanName(BeanInfo bean) {
205-
StringBuilder baseNameBuilder = new StringBuilder();
206-
if (bean.getImplClazz().enclosingClass() != null) {
207-
baseNameBuilder.append(DotNames.simpleName(bean.getImplClazz().enclosingClass())).append(UNDERSCORE)
208-
.append(DotNames.simpleName(bean.getImplClazz()));
209-
} else {
210-
baseNameBuilder.append(DotNames.simpleName(bean.getImplClazz()));
211-
}
212-
baseNameBuilder.append(UNDERSCORE);
213-
baseNameBuilder.append(bean.getIdentifier());
214-
baseNameBuilder.append(UNDERSCORE);
215-
baseNameBuilder.append(SYNTHETIC_SUFFIX);
216-
String baseName = baseNameBuilder.toString();
187+
String baseName = bean.getImplClazz().name().withoutPackagePrefix() + UNDERSCORE + bean.getIdentifier()
188+
+ UNDERSCORE + SYNTHETIC_SUFFIX;
217189
this.beanToGeneratedBaseName.put(bean, baseName);
218190
String targetPackage = bean.getTargetPackageName();
219191
this.beanToGeneratedName.put(bean, generatedNameFromTarget(targetPackage, baseName, BEAN_SUFFIX));
@@ -242,7 +214,7 @@ Collection<Resource> generate(BeanInfo bean) {
242214
String baseName = beanToGeneratedBaseName.get(bean);
243215
String targetPackage = bean.isSynthetic()
244216
? bean.getTargetPackageName()
245-
: DotNames.packageName(bean.isProducer() ? clazz.name() : providerType.name());
217+
: DotNames.packagePrefix(bean.isProducer() ? clazz.name() : providerType.name());
246218
String generatedName = beanToGeneratedName.get(bean);
247219
if (existingClasses.contains(generatedName)) {
248220
return Collections.emptyList();
@@ -263,8 +235,7 @@ Collection<Resource> generate(BeanInfo bean) {
263235

264236
private void generateBean(Gizmo gizmo, BeanInfo bean, String generatedName, String baseName,
265237
String targetPackage, boolean isApplicationClass, ProviderType providerType) {
266-
// TODO generated name includes `/` instead of `.`
267-
gizmo.class_(generatedName.replace('/', '.'), cc -> {
238+
gizmo.class_(generatedName, cc -> {
268239
cc.implements_(InjectableBean.class);
269240
cc.implements_(Supplier.class);
270241

@@ -880,9 +851,7 @@ private void generateCreateForClassBean(ClassCreator cc, BeanInfo bean,
880851
// and also the CDI specification:
881852
//
882853
// > Invocations of initializer methods by the container are not business method invocations.
883-
// TODO generated name includes `/` instead of `.`
884-
ClassDesc subclass = ClassDesc.of(SubclassGenerator.generatedName(bean.getProviderType().name(), baseName)
885-
.replace('/', '.'));
854+
ClassDesc subclass = ClassDesc.of(SubclassGenerator.generatedName(bean.getProviderType().name(), baseName));
886855
bc.invokeVirtual(ClassMethodDesc.of(subclass, SubclassGenerator.MARK_CONSTRUCTED_METHOD_NAME, void.class),
887856
bc.cast(instance, subclass));
888857
}
@@ -1015,9 +984,7 @@ private Expr newBeanInstance(BeanInfo bean, BlockCreator bc, ProviderType provid
1015984
args.add(providers.get(injectionPoints.size() + interceptors.size() + i));
1016985
}
1017986

1018-
// TODO generated name includes `/` instead of `.`
1019-
ClassDesc subclass = ClassDesc.of(SubclassGenerator.generatedName(bean.getProviderType().name(), baseName)
1020-
.replace('/', '.'));
987+
ClassDesc subclass = ClassDesc.of(SubclassGenerator.generatedName(bean.getProviderType().name(), baseName));
1021988
return bc.new_(ConstructorDesc.of(subclass, paramTypes), args);
1022989
} else if (constructorInjection.isPresent()) {
1023990
if (Modifier.isPrivate(constructor.flags())) {
@@ -1561,9 +1528,8 @@ void generate(BlockCreator bc, Var instance) {
15611528
// }
15621529
new PreDestroyGenerator().generate(b1, instance);
15631530
} else {
1564-
// TODO generated name includes `/` instead of `.`
15651531
ClassDesc subclass = ClassDesc.of(SubclassGenerator.generatedName(
1566-
bean.getProviderType().name(), baseName).replace('/', '.'));
1532+
bean.getProviderType().name(), baseName));
15671533

15681534
// if there _is_ some `@PreDestroy` interceptor, however, we'll reify the chain of `@PreDestroy`
15691535
// callbacks into a `Runnable` that we pass into the interceptor chain to be called

independent-projects/arc/processor/src/main/java/io/quarkus/arc/processor/BeanInfo.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -636,7 +636,7 @@ public String getTargetPackageName() {
636636
providerTypeName = providerType.name();
637637
}
638638
}
639-
String packageName = DotNames.packageName(providerTypeName);
639+
String packageName = DotNames.packagePrefix(providerTypeName);
640640
if (packageName.startsWith("java.")) {
641641
// It is not possible to place a class in a JDK package
642642
packageName = AbstractGenerator.DEFAULT_PACKAGE;
@@ -649,7 +649,7 @@ public String getClientProxyPackageName() {
649649
AnnotationTarget target = getTarget().get();
650650
DotName typeName = target.kind() == Kind.FIELD ? target.asField().type().name()
651651
: target.asMethod().returnType().name();
652-
String packageName = DotNames.packageName(typeName);
652+
String packageName = DotNames.packagePrefix(typeName);
653653
if (packageName.startsWith("java.")) {
654654
// It is not possible to place a class in a JDK package
655655
packageName = AbstractGenerator.DEFAULT_PACKAGE;

independent-projects/arc/processor/src/main/java/io/quarkus/arc/processor/Beans.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1165,7 +1165,7 @@ private static String decapitalize(String name) {
11651165

11661166
private static String getDefaultName(ClassInfo beanClass) {
11671167
StringBuilder defaultName = new StringBuilder();
1168-
defaultName.append(DotNames.simpleName(beanClass));
1168+
defaultName.append(beanClass.simpleName());
11691169
// URLMatcher becomes uRLMatcher
11701170
defaultName.setCharAt(0, Character.toLowerCase(defaultName.charAt(0)));
11711171
return defaultName.toString();

independent-projects/arc/processor/src/main/java/io/quarkus/arc/processor/ClientProxyGenerator.java

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,7 @@ Collection<Resource> generate(BeanInfo bean, String beanClassName,
9898
return Collections.emptySet();
9999
}
100100

101-
String baseName = getBaseName(beanClassName);
101+
String baseName = getBeanBaseName(beanClassName);
102102
String targetPackage = bean.getClientProxyPackageName();
103103
String generatedName = generatedNameFromTarget(targetPackage, baseName, CLIENT_PROXY_SUFFIX);
104104
if (existingClasses.contains(generatedName)) {
@@ -129,8 +129,7 @@ private void createClientProxy(Gizmo gizmo, BeanInfo bean, Consumer<BytecodeTran
129129
ClassDesc superClass = isInterface ? CD_Object : providerClassDesc;
130130

131131
// Foo_ClientProxy extends Foo implements ClientProxy
132-
// TODO generated name includes `/` instead of `.`
133-
gizmo.class_(generatedName.replace('/', '.'), cc -> {
132+
gizmo.class_(generatedName, cc -> {
134133
copyTypeParameters(providerClass, cc);
135134

136135
GenericType.OfClass providerGenericType = genericTypeOfClass(providerType);

independent-projects/arc/processor/src/main/java/io/quarkus/arc/processor/ComponentsProviderGenerator.java

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -259,9 +259,8 @@ private void generateAddBeans(ClassCreator cc, CodeGenInfo info, Map<BeanInfo, S
259259
ParamVar beanIdToBean = mc.parameter("beanIdToBean", Map.class);
260260
mc.body(bc -> {
261261
for (BeanInfo bean : group.beans()) {
262-
// TODO generated name includes `/` instead of `.`
263262
ClassDesc beanType = beanToGeneratedName.containsKey(bean)
264-
? ClassDesc.of(beanToGeneratedName.get(bean).replace('/', '.'))
263+
? ClassDesc.of(beanToGeneratedName.get(bean))
265264
: null;
266265
if (beanType == null) {
267266
throw new IllegalStateException("No bean type found for: " + bean);
@@ -350,9 +349,8 @@ private void generateAddObservers(ClassCreator cc, CodeGenInfo info, Map<Observe
350349
ParamVar observers = mc.parameter("observers", List.class);
351350
mc.body(bc -> {
352351
for (ObserverInfo observer : group.observers()) {
353-
// TODO generated name includes `/` instead of `.`
354352
ClassDesc observerType = observerToGeneratedName.containsKey(observer)
355-
? ClassDesc.of(observerToGeneratedName.get(observer).replace('/', '.'))
353+
? ClassDesc.of(observerToGeneratedName.get(observer))
356354
: null;
357355
if (observerType == null) {
358356
throw new IllegalStateException("No observer type found for: " + observerType);

0 commit comments

Comments
 (0)