Skip to content

Commit

Permalink
Qute: fix template global class generation in the dev mode #2
Browse files Browse the repository at this point in the history
- follows-up on quarkusio#45771
- fixes quarkusio#46005

(cherry picked from commit d85129e)
  • Loading branch information
mkouba authored and gsmet committed Feb 11, 2025
1 parent e7ecbf6 commit 3e6805c
Show file tree
Hide file tree
Showing 3 changed files with 35 additions and 13 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ public boolean test(String t) {
return false;
}
});
try (ClassCreator classCreator = ClassCreator.builder().className("io.quarkus.qute.test.QuteDummyGlobals")
try (ClassCreator classCreator = ClassCreator.builder().className("org.acme.qute.test.QuteDummyGlobals")
.classOutput(gizmoAdaptor).build()) {
classCreator.addAnnotation(TemplateGlobal.class);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.ListIterator;
import java.util.Map;
Expand Down Expand Up @@ -2095,16 +2096,26 @@ public Function<FieldInfo, String> apply(ClassInfo clazz) {

if (!templateGlobals.isEmpty()) {
Set<String> generatedGlobals = new HashSet<>();
// The initial priority is increased during live reload so that priorities of non-application globals
// do not conflict with priorities of application globals
int initialPriority = -1000 + existingValueResolvers.globals.size();
// The classes for non-application globals are only generated during the first run because they can't be reloaded
// by the class loader during hot reload
// However, we need to make sure the priorities used by non-application globals do not conflict
// with priorities of application globals that are regenerated during each hot reload
// Therefore, the initial priority is increased by the number of all globals ever found
// For example, if there are three globals [A, B, C] (A and C are non-application classes)
// The intial priority during the first hot reload will be "-1000 + 3 = 997"
// If a global D is added afterwards, the initial priority during the subsequent hot reload will be "-1000 + 4 = 996"
// If the global D is removed, the initial priority will still remain "-1000 + 4 = 996"
// This way we can be sure that the priorities assigned to A and C will never conflict with priorities of B and D or any other application global class
int initialPriority = -1000 + existingValueResolvers.allGlobals.size();

TemplateGlobalGenerator globalGenerator = new TemplateGlobalGenerator(classOutput, GLOBAL_NAMESPACE,
initialPriority, index);

Map<DotName, Map<String, AnnotationTarget>> classToTargets = new HashMap<>();
Map<DotName, Map<String, AnnotationTarget>> classToTargets = new LinkedHashMap<>();
Map<DotName, List<TemplateGlobalBuildItem>> classToGlobals = templateGlobals.stream()
.collect(Collectors.groupingBy(TemplateGlobalBuildItem::getDeclaringClass));
.sorted(Comparator.comparing(g -> g.getDeclaringClass()))
.collect(Collectors.groupingBy(TemplateGlobalBuildItem::getDeclaringClass, LinkedHashMap::new,
Collectors.toList()));
for (Entry<DotName, List<TemplateGlobalBuildItem>> entry : classToGlobals.entrySet()) {
classToTargets.put(entry.getKey(), entry.getValue().stream().collect(
Collectors.toMap(TemplateGlobalBuildItem::getName, TemplateGlobalBuildItem::getTarget)));
Expand All @@ -2116,8 +2127,8 @@ public Function<FieldInfo, String> apply(ClassInfo clazz) {
generatedGlobals.add(generatedClass);
} else {
generatedClass = globalGenerator.generate(index.getClassByName(e.getKey()), e.getValue());
existingValueResolvers.addGlobal(e.getKey(), generatedClass, applicationClassPredicate);
}
existingValueResolvers.addGlobal(e.getKey(), generatedClass, applicationClassPredicate);
}
generatedGlobals.addAll(globalGenerator.getGeneratedTypes());

Expand All @@ -2135,9 +2146,12 @@ public Function<FieldInfo, String> apply(ClassInfo clazz) {
static class ExistingValueResolvers {

final Map<String, String> identifiersToGeneratedClass = new HashMap<>();
// class declaring globals -> generated type

// class declaring globals -> generated type; non-application globals only
final Map<String, String> globals = new HashMap<>();

final Set<String> allGlobals = new HashSet<>();

boolean contains(MethodInfo extensionMethod) {
return identifiersToGeneratedClass
.containsKey(toKey(extensionMethod));
Expand All @@ -2158,7 +2172,7 @@ void add(MethodInfo extensionMethod, String className, Predicate<DotName> applic
}

void addGlobal(DotName declaringClassName, String generatedClassName, Predicate<DotName> applicationClassPredicate) {
if (!applicationClassPredicate.test(declaringClassName)) {
if (allGlobals.add(generatedClassName.toString()) && !applicationClassPredicate.test(declaringClassName)) {
globals.put(declaringClassName.toString(), generatedClassName);
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.RegisterExtension;

import io.quarkus.qute.TemplateGlobal;
import io.quarkus.test.QuarkusDevModeTest;

/**
Expand All @@ -20,17 +21,17 @@ public class TemplateGlobalDevModeTest {
@RegisterExtension
static final QuarkusDevModeTest config = new QuarkusDevModeTest()
.withApplicationRoot(root -> root
.addClasses(TestRoute.class, QuteDummyTemplateGlobalMarker.class)
.addClasses(TestRoute.class, MyGlobals.class, QuteDummyTemplateGlobalMarker.class)
.addAsResource(new StringAsset(
"{quteDummyFoo}:{testFoo ?: 'NA'}"),
"{foo}:{quteDummyFoo}:{testFoo ?: 'NA'}"),
"templates/test.html"));

@Test
public void testTemplateGlobals() {
given().get("test")
.then()
.statusCode(200)
.body(Matchers.equalTo("bar:NA"));
.body(Matchers.equalTo("24:bar:NA"));

// Add application globals - the priority sequence should be automatically
// increased before it's used for TestGlobals
Expand All @@ -39,7 +40,14 @@ public void testTemplateGlobals() {
given().get("test")
.then()
.statusCode(200)
.body(Matchers.equalTo("bar:baz"));
.body(Matchers.equalTo("24:bar:baz"));
}

@TemplateGlobal
public static class MyGlobals {

public static int foo = 24;

}

}

0 comments on commit 3e6805c

Please sign in to comment.