Skip to content

Commit

Permalink
Qute - fix validation of type-safe message expressions
Browse files Browse the repository at this point in the history
- NPE is currently thrown if a type-safe message expression references a
parent expression via hint
- resolves quarkusio#16590
  • Loading branch information
mkouba committed Apr 19, 2021
1 parent 0cd6553 commit cb2305f
Show file tree
Hide file tree
Showing 4 changed files with 47 additions and 4 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -315,6 +315,7 @@ void validateMessageBundleMethodsInTemplates(TemplatesAnalysisBuildItem analysis
List<TypeCheckExcludeBuildItem> excludes,
List<MessageBundleBuildItem> messageBundles,
List<MessageBundleMethodBuildItem> messageBundleMethods,
List<TemplateExpressionMatchesBuildItem> expressionMatches,
BuildProducer<IncorrectExpressionBuildItem> incorrectExpressions,
BuildProducer<ImplicitValueResolverBuildItem> implicitClasses) {

Expand Down Expand Up @@ -356,7 +357,13 @@ public String apply(String id) {

for (Entry<TemplateAnalysis, Set<Expression>> exprEntry : expressions.entrySet()) {

Map<Integer, Match> generatedIdsToMatches = new HashMap<>();
Map<Integer, Match> generatedIdsToMatches = Collections.emptyMap();
for (TemplateExpressionMatchesBuildItem templateExpressionMatchesBuildItem : expressionMatches) {
if (templateExpressionMatchesBuildItem.templateGeneratedId.equals(exprEntry.getKey().generatedId)) {
generatedIdsToMatches = templateExpressionMatchesBuildItem.getGeneratedIdsToMatches();
break;
}
}

for (Expression expression : exprEntry.getValue()) {
// msg:hello_world(foo.name)
Expand Down Expand Up @@ -407,7 +414,7 @@ public String apply(String id) {
incorrectExpressions, expression, index, implicitClassToMembersUsed,
templateIdToPathFun, generatedIdsToMatches);
Match match = results.get(param.toOriginalString());
if (match != null && !Types.isAssignableFrom(match.type(),
if (match != null && !match.isEmpty() && !Types.isAssignableFrom(match.type(),
methodParams.get(idx), index)) {
incorrectExpressions
.produce(new IncorrectExpressionBuildItem(expression.toOriginalString(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -484,6 +484,7 @@ void validateExpressions(TemplatesAnalysisBuildItem templatesAnalysis,
List<TypeCheckExcludeBuildItem> excludes,
BuildProducer<IncorrectExpressionBuildItem> incorrectExpressions,
BuildProducer<ImplicitValueResolverBuildItem> implicitClasses,
BuildProducer<TemplateExpressionMatchesBuildItem> expressionMatches,
BeanDiscoveryFinishedBuildItem beanDiscovery,
List<CheckedTemplateBuildItem> checkedTemplates,
QuteConfig config) {
Expand Down Expand Up @@ -559,6 +560,9 @@ public String apply(String id) {
generatedIdsToMatches));
}
}

expressionMatches
.produce(new TemplateExpressionMatchesBuildItem(templateAnalysis.generatedId, generatedIdsToMatches));
}

for (Entry<DotName, Set<String>> entry : implicitClassToMembersUsed.entrySet()) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package io.quarkus.qute.deployment;

import java.util.Map;

import io.quarkus.builder.item.MultiBuildItem;
import io.quarkus.qute.deployment.QuteProcessor.Match;

final class TemplateExpressionMatchesBuildItem extends MultiBuildItem {

final String templateGeneratedId;

private final Map<Integer, Match> generatedIdsToMatches;

public TemplateExpressionMatchesBuildItem(String templateGeneratedId, Map<Integer, Match> generatedIdsToMatches) {
this.templateGeneratedId = templateGeneratedId;
this.generatedIdsToMatches = generatedIdsToMatches;
}

Match getMatch(Integer generatedId) {
return generatedIdsToMatches.get(generatedId);
}

Map<Integer, Match> getGeneratedIdsToMatches() {
return generatedIdsToMatches;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,8 @@ public class MessageBundleTemplateExpressionValidationTest {
static final QuarkusUnitTest config = new QuarkusUnitTest()
.setArchiveProducer(() -> ShrinkWrap.create(JavaArchive.class)
.addClasses(MyBundle.class, Item.class)
.addAsResource(new StringAsset("{msg:hello('foo')} {msg:hello_and_bye} {msg:hello(1,2)}"),
.addAsResource(new StringAsset(
"{@java.util.List<java.lang.Integer> names} {msg:hello('foo')} {msg:hello_and_bye} {msg:hello(1,2)} {#each names}{msg:helloName(it)}{/each}"),
"templates/hello.html"))
.assertException(t -> {
Throwable e = t;
Expand All @@ -35,10 +36,11 @@ public class MessageBundleTemplateExpressionValidationTest {
if (te == null) {
fail("No template exception thrown: " + t);
}
assertTrue(te.getMessage().contains("Found template problems (3)"), te.getMessage());
assertTrue(te.getMessage().contains("Found template problems (4)"), te.getMessage());
assertTrue(te.getMessage().contains("msg:hello('foo')"), te.getMessage());
assertTrue(te.getMessage().contains("msg:hello_and_bye"), te.getMessage());
assertTrue(te.getMessage().contains("msg:hello(1,2)"), te.getMessage());
assertTrue(te.getMessage().contains("msg:helloName(it)"), te.getMessage());
});

@Test
Expand All @@ -52,6 +54,9 @@ public interface MyBundle {
@Message("Hello {item.name}")
String hello(Item item);

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

}

}

0 comments on commit cb2305f

Please sign in to comment.