Skip to content

Commit

Permalink
Qute: introduce ValidationParserHookBuildItem
Browse files Browse the repository at this point in the history
- that can be used to hook into the parser logic during validation at
build time
  • Loading branch information
mkouba committed Jul 4, 2024
1 parent a2ef151 commit 811534a
Show file tree
Hide file tree
Showing 4 changed files with 115 additions and 8 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -591,8 +591,11 @@ private boolean isNotLocatedByCustomTemplateLocator(

@BuildStep
TemplatesAnalysisBuildItem analyzeTemplates(List<TemplatePathBuildItem> templatePaths,
TemplateFilePathsBuildItem filePaths, List<CheckedTemplateBuildItem> checkedTemplates,
List<MessageBundleMethodBuildItem> messageBundleMethods, List<TemplateGlobalBuildItem> globals, QuteConfig config,
TemplateFilePathsBuildItem filePaths,
List<CheckedTemplateBuildItem> checkedTemplates,
List<MessageBundleMethodBuildItem> messageBundleMethods,
List<TemplateGlobalBuildItem> globals, QuteConfig config,
List<ValidationParserHookBuildItem> validationParserHooks,
Optional<EngineConfigurationsBuildItem> engineConfigurations,
BeanArchiveIndexBuildItem beanArchiveIndex,
BuildProducer<CheckedFragmentValidationBuildItem> checkedFragmentValidations) {
Expand Down Expand Up @@ -724,6 +727,10 @@ public void beforeParsing(ParserHelper parserHelper) {
parserHelper.addParameter(UserTagSectionHelper.Factory.ARGS,
UserTagSectionHelper.Arguments.class.getName());
}

for (ValidationParserHookBuildItem hook : validationParserHooks) {
hook.accept(parserHelper);
}
}

// If needed add params to message bundle templates
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package io.quarkus.qute.deployment;

import java.util.Objects;
import java.util.function.Consumer;

import io.quarkus.builder.item.MultiBuildItem;
import io.quarkus.qute.ParserHelper;

/**
* This build item can be used to hook into the parser logic during validation at build time.
* <p>
* Validation parser hooks are never used at runtime.
*/
public final class ValidationParserHookBuildItem extends MultiBuildItem {

private final Consumer<ParserHelper> hook;

public ValidationParserHookBuildItem(Consumer<ParserHelper> hook) {
this.hook = Objects.requireNonNull(hook);
}

public Consumer<ParserHelper> getHook() {
return hook;
}

public void accept(ParserHelper helper) {
hook.accept(helper);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,10 @@
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.junit.jupiter.api.Assertions.fail;

import jakarta.inject.Inject;

import org.jboss.shrinkwrap.api.asset.StringAsset;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.RegisterExtension;

import io.quarkus.qute.Engine;
import io.quarkus.qute.EngineConfiguration;
import io.quarkus.qute.ParserHelper;
import io.quarkus.qute.ParserHook;
Expand Down Expand Up @@ -39,9 +36,6 @@ public class CustomParserHookBuildTest {
assertTrue(te.getMessage().contains("{foo.bar}"), te.getMessage());
});;

@Inject
Engine engine;

@Test
public void test() {
fail();
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
package io.quarkus.qute.deployment.engineconfigurations.parserhook;

import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.junit.jupiter.api.Assertions.fail;

import java.util.function.Consumer;

import org.jboss.shrinkwrap.api.asset.StringAsset;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.RegisterExtension;

import io.quarkus.builder.BuildChainBuilder;
import io.quarkus.builder.BuildContext;
import io.quarkus.builder.BuildStep;
import io.quarkus.qute.TemplateException;
import io.quarkus.qute.deployment.ValidationParserHookBuildItem;
import io.quarkus.test.QuarkusUnitTest;

public class ValidationHookTest {

@RegisterExtension
static final QuarkusUnitTest config = new QuarkusUnitTest()
.withApplicationRoot(
root -> root.addClasses(Foo.class)
.addAsResource(new StringAsset("{foo.bar}"), "templates/foo.html"))
.assertException(t -> {
Throwable e = t;
TemplateException te = null;
while (e != null) {
if (e instanceof TemplateException) {
te = (TemplateException) e;
break;
}
e = e.getCause();
}
assertNotNull(te);
assertTrue(te.getMessage().contains("Found incorrect expressions (1)"), te.getMessage());
assertTrue(te.getMessage().contains("{foo.bar}"), te.getMessage());
}).addBuildChainCustomizer(buildCustomizer());

static Consumer<BuildChainBuilder> buildCustomizer() {
return new Consumer<BuildChainBuilder>() {
@Override
public void accept(BuildChainBuilder builder) {
builder.addBuildStep(new BuildStep() {
@Override
public void execute(BuildContext context) {
context.produce(new ValidationParserHookBuildItem(helper -> {
if (helper.getTemplateId().contains("foo")) {
helper.addParameter("foo", Foo.class.getName());
}
}));
}
}).produces(ValidationParserHookBuildItem.class)
.build();

}
};
}

@Test
public void test() {
fail();
}

public static class Foo {

// package-private method is ignored
String bar() {
return null;
}

}

}

0 comments on commit 811534a

Please sign in to comment.