Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Type-safe message bundles - handle nested bundle classes correctly #16583

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -58,12 +58,15 @@ public Set<ApplicationArchive> getAllApplicationArchives() {
* @return The application archive
*/
public ApplicationArchive containingArchive(String className) {
DotName name = DotName.createSimple(className);
if (root.getIndex().getClassByName(name) != null) {
return containingArchive(DotName.createSimple(className));
}

public ApplicationArchive containingArchive(DotName className) {
if (root.getIndex().getClassByName(className) != null) {
return root;
}
for (ApplicationArchive i : applicationArchives) {
if (i.getIndex().getClassByName(name) != null) {
if (i.getIndex().getClassByName(className) != null) {
return i;
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -480,16 +480,17 @@ private Map<String, String> generateImplementations(List<MessageBundleBuildItem>
}
String locale = entry.getKey();
ClassOutput localeAwareGizmoAdaptor = new GeneratedClassGizmoAdaptor(generatedClasses,
new AppClassPredicate(applicationArchivesBuildItem, new Function<String, String>() {
@Override
public String apply(String className) {
String localeSuffix = "_" + locale;
if (className.endsWith(localeSuffix)) {
return className.replace(localeSuffix, "");
}
return className;
}
}));
new AppClassPredicate(applicationArchivesBuildItem,
new Function<String, String>() {
@Override
public String apply(String className) {
String localeSuffix = "_" + locale;
if (className.endsWith(localeSuffix)) {
return className.replace(localeSuffix, "");
}
return className;
}
}));
generatedTypes.put(localizedFile.toString(),
generateImplementation(bundle.getDefaultBundleInterface(), bundleImpl, bundleInterface,
localeAwareGizmoAdaptor,
Expand Down Expand Up @@ -522,10 +523,10 @@ private String generateImplementation(ClassInfo defaultBundleInterface, String d

String baseName;
if (bundleInterface.enclosingClass() != null) {
baseName = DotNames.simpleName(bundleInterface.enclosingClass()) + "_"
+ DotNames.simpleName(bundleInterface.name());
baseName = DotNames.simpleName(bundleInterface.enclosingClass()) + ValueResolverGenerator.NESTED_SEPARATOR
+ DotNames.simpleName(bundleInterface);
} else {
baseName = DotNames.simpleName(bundleInterface.name());
baseName = DotNames.simpleName(bundleInterface);
}
if (locale != null) {
baseName = baseName + "_" + locale;
Expand Down Expand Up @@ -903,29 +904,31 @@ private Set<Path> findMessageFiles(ApplicationArchivesBuildItem applicationArchi
}

private static class AppClassPredicate implements Predicate<String> {
private final ApplicationArchivesBuildItem applicationArchivesBuildItem;

private final ApplicationArchivesBuildItem applicationArchives;
private final Function<String, String> additionalClassNameSanitizer;

public AppClassPredicate(ApplicationArchivesBuildItem applicationArchivesBuildItem) {
this(applicationArchivesBuildItem, Function.identity());
public AppClassPredicate(ApplicationArchivesBuildItem applicationArchives) {
this(applicationArchives, Function.identity());
}

public AppClassPredicate(ApplicationArchivesBuildItem applicationArchivesBuildItem,
public AppClassPredicate(ApplicationArchivesBuildItem applicationArchives,
Function<String, String> additionalClassNameSanitizer) {
this.applicationArchivesBuildItem = applicationArchivesBuildItem;
this.applicationArchives = applicationArchives;
this.additionalClassNameSanitizer = additionalClassNameSanitizer;
}

@Override
public boolean test(String name) {
int idx = name.lastIndexOf(SUFFIX);
// org/acme/Foo_Bundle -> org.acme.Foo
String className = name.substring(0, idx).replace("/", ".");
if (className.contains(ValueResolverGenerator.NESTED_SEPARATOR)) {
className = className.replace(ValueResolverGenerator.NESTED_SEPARATOR, "$");
}
// E.g. to match the bundle class generated for a localized file; org.acme.Foo_en -> org.acme.Foo
className = additionalClassNameSanitizer.apply(className);
return applicationArchivesBuildItem.getRootArchive().getIndex()
.getClassByName(DotName.createSimple(className)) != null;
return applicationArchives.containingArchive(className) != null;
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
package io.quarkus.qute.deployment.i18n;

import static org.junit.jupiter.api.Assertions.assertEquals;

import javax.enterprise.event.Observes;

import org.jboss.shrinkwrap.api.ShrinkWrap;
import org.jboss.shrinkwrap.api.spec.JavaArchive;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.RegisterExtension;

import io.quarkus.qute.i18n.Message;
import io.quarkus.qute.i18n.MessageBundle;
import io.quarkus.qute.i18n.MessageBundles;
import io.quarkus.test.QuarkusDevModeTest;
import io.restassured.RestAssured;
import io.vertx.ext.web.Router;

public class NestedMessageBundleDevModeTest {

@RegisterExtension
static final QuarkusDevModeTest testConfig = new QuarkusDevModeTest()
.setArchiveProducer(() -> ShrinkWrap.create(JavaArchive.class)
.addClasses(MyNestedMessages.class, TestRouteConfig.class));

@Test
public void testMessages() {
assertEquals("Hello Jachym!", RestAssured.get("test").then().statusCode(200).extract().body().asString());
testConfig.modifySourceFile(NestedMessageBundleDevModeTest.class, s -> s.replace("Hello {name}!", "Hi {name}!"));
assertEquals("Hi Jachym!", RestAssured.get("test").then().statusCode(200).extract().body().asString());
}

@MessageBundle
public interface MyNestedMessages {

@Message("Hello {name}!")
String hello_name(String name);

}

public static class TestRouteConfig {

void addTestRoute(@Observes Router router) {
router.route("/test")
.produces("text/plain")
.handler(rc -> rc.response().end(MessageBundles.get(MyNestedMessages.class).hello_name("Jachym")));
}

}

}