Skip to content

Commit

Permalink
Qute: add possibility to ignore parts of expressions during validation
Browse files Browse the repository at this point in the history
- resolves quarkusio#12185
  • Loading branch information
mkouba committed Jan 20, 2021
1 parent 7f538c4 commit ecad79d
Show file tree
Hide file tree
Showing 3 changed files with 82 additions and 4 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -993,11 +993,9 @@ TemplateVariantsBuildItem collectTemplateVariants(List<TemplatePathBuildItem> te
}

@BuildStep
void excludeTypeChecks(BuildProducer<TypeCheckExcludeBuildItem> excludes) {
void excludeTypeChecks(QuteConfig config, BuildProducer<TypeCheckExcludeBuildItem> excludes) {
// Exclude all checks that involve built-in value resolvers
// TODO: We need a better way to exclude value resolvers that are not template extension methods
List<String> skipOperators = Arrays.asList("?:", "or", ":", "?", "&&", "||");

excludes.produce(new TypeCheckExcludeBuildItem(new Predicate<TypeCheck>() {
@Override
public boolean test(TypeCheck check) {
Expand All @@ -1016,6 +1014,31 @@ public boolean test(TypeCheck check) {
return false;
}
}));

if (config.typeCheckExcludes.isPresent()) {
for (String exclude : config.typeCheckExcludes.get()) {
//
String[] parts = exclude.split("\\.");
if (parts.length < 2) {
// A valida exclude must have at least two parts
continue;
}
String className = Arrays.stream(parts).limit(parts.length - 1).collect(Collectors.joining("."));
String propertyName = parts[parts.length - 1];
excludes.produce(new TypeCheckExcludeBuildItem(new Predicate<TypeCheck>() {
@Override
public boolean test(TypeCheck check) {
if (!className.equals("*") && !check.clazz.name().toString().equals(className)) {
return false;
}
if (!propertyName.equals("*") && !check.name.equals(propertyName)) {
return false;
}
return true;
}
}));
}
}
}

@BuildStep
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
package io.quarkus.qute.deployment.typesafe;

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

import javax.inject.Inject;

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

import io.quarkus.qute.Template;
import io.quarkus.test.QuarkusUnitTest;

public class TypeCheckExcludesTest {

@RegisterExtension
static final QuarkusUnitTest config = new QuarkusUnitTest()
.setArchiveProducer(() -> ShrinkWrap.create(JavaArchive.class)
.addClasses(Movie.class, Machine.class, MachineStatus.class)
.addAsResource(new StringAsset("{@io.quarkus.qute.deployment.typesafe.Movie movie}"
+ "{@io.quarkus.qute.deployment.typesafe.Machine machine}"
+ "{movie.name}::{movie.superior}::{machine.ping}::{machine.neverEver}"), "templates/movie.html")
.addAsResource(new StringAsset(
"quarkus.qute.type-check-excludes=io.quarkus.qute.deployment.typesafe.Movie.superior,io.quarkus.qute.deployment.typesafe.Machine.*"),
"application.properties"));

@Inject
Template movie;

@Test
public void testValidationSuccess() {
assertEquals("Jason::NOT_FOUND::1::NOT_FOUND",
movie.data("movie", new Movie(), "machine", new Machine()).render());
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import java.util.List;
import java.util.Map;
import java.util.Optional;

import io.quarkus.runtime.annotations.ConfigItem;
import io.quarkus.runtime.annotations.ConfigPhase;
Expand All @@ -11,7 +12,7 @@
public class QuteConfig {

/**
* The set of suffixes used when attempting to locate a template file.
* The list of suffixes used when attempting to locate a template file.
*
* By default, `engine.getTemplate("foo")` would result in several lookups: `foo`, `foo.html`, `foo.txt`, etc.
*
Expand All @@ -27,4 +28,20 @@ public class QuteConfig {
@ConfigItem
public Map<String, String> contentTypes;

/**
* The list of exclude rules used to intentionally ignore some parts of an expression when performing type-safe validation.
* <p>
* An element value must have at least two parts separated by dot. The last part is used to match the property/method name.
* The prepended parts are used to match the class name. The value {@code *} can be used to match any name.
* <p>
* Examples:
* <ul>
* <li>{@code org.acme.Foo.name} - exclude the property/method {@code name} on the {@code org.acme.Foo} class</li>
* <li>{@code org.acme.Foo.*} - exclude any property/method on the {@code org.acme.Foo} class</li>
* <li>{@code *.age} - exlude the property/method {@code age} on any class</li>
* </ul>
*/
@ConfigItem
public Optional<List<String>> typeCheckExcludes;

}

0 comments on commit ecad79d

Please sign in to comment.