Skip to content

Commit

Permalink
Qute type-safe validation - include all interface methods in hierarchy
Browse files Browse the repository at this point in the history
- resolves quarkusio#19564
  • Loading branch information
mkouba committed Aug 27, 2021
1 parent 3afc800 commit 55288bf
Show file tree
Hide file tree
Showing 3 changed files with 105 additions and 8 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -1738,14 +1738,13 @@ private static AnnotationTarget findProperty(String name, ClassInfo clazz, Index
clazz = index.getClassByName(clazz.superName());
}
}
// Try the default methods
// Try interface methods
for (DotName interfaceName : interfaceNames) {
ClassInfo interfaceClassInfo = index.getClassByName(interfaceName);
if (interfaceClassInfo != null) {
for (MethodInfo method : interfaceClassInfo.methods()) {
// A default method is a public non-abstract instance method
if (Modifier.isPublic(method.flags()) && !Modifier.isStatic(method.flags())
&& !ValueResolverGenerator.isSynthetic(method.flags()) && !Modifier.isAbstract(method.flags())
&& !ValueResolverGenerator.isSynthetic(method.flags())
&& (method.name().equals(name)
|| ValueResolverGenerator.getPropertyName(method.name()).equals(name))) {
return method;
Expand Down Expand Up @@ -1787,14 +1786,14 @@ && methodMatches(method, virtualMethod, expression, index, templateIdToPathFun,
clazz = index.getClassByName(clazz.superName());
}
}
// Try the default methods
// Try interface methods
for (DotName interfaceName : interfaceNames) {
ClassInfo interfaceClassInfo = index.getClassByName(interfaceName);
if (interfaceClassInfo != null) {
for (MethodInfo method : interfaceClassInfo.methods()) {
// A default method is a public non-abstract instance method
if (Modifier.isPublic(method.flags()) && !Modifier.isStatic(method.flags())
&& !ValueResolverGenerator.isSynthetic(method.flags()) && !Modifier.isAbstract(method.flags())
&& !ValueResolverGenerator.isSynthetic(method.flags())
&& methodMatches(method, virtualMethod, expression, index, templateIdToPathFun, results)) {
return method;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
package io.quarkus.qute.deployment.typesafe;

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 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.TemplateException;
import io.quarkus.test.QuarkusUnitTest;

public class InterfaceValidationFailureTest {

@RegisterExtension
static final QuarkusUnitTest config = new QuarkusUnitTest()
.setArchiveProducer(() -> ShrinkWrap.create(JavaArchive.class)
.addClasses(InterfaceValidationSuccessTest.Metrics.class, InterfaceValidationSuccessTest.Count.class,
InterfaceValidationSuccessTest.Wrapper.class)
.addAsResource(new StringAsset(
"{@io.quarkus.qute.deployment.typesafe.InterfaceValidationSuccessTest$Metrics metrics}"
+ "{metrics.responses.values}"),
"templates/metrics.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 template problems (1)"), te.getMessage());
assertTrue(te.getMessage().contains("{metrics.responses.values}"), te.getMessage());
});

@Test
public void test() {
fail();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -20,17 +20,69 @@ public class InterfaceValidationSuccessTest {
@RegisterExtension
static final QuarkusUnitTest config = new QuarkusUnitTest()
.setArchiveProducer(() -> ShrinkWrap.create(JavaArchive.class)
.addClasses(Movie.class, MovieExtensions.class)
.addClasses(Metrics.class, Count.class, Wrapper.class)
.addAsResource(new StringAsset("{@java.util.List list}"
+ "{list.empty}:{list.toString}"),
"templates/list.html"));
"templates/list.html")
.addAsResource(
new StringAsset(
"{@io.quarkus.qute.deployment.typesafe.InterfaceValidationSuccessTest$Metrics metrics}"
+ "{metrics.responses.value}:{metrics.responses.name(1)}:{metrics.requests.value??}"),
"templates/metrics.html"));

@Inject
Template list;

@Inject
Template metrics;

@Test
public void testResult() {
public void testInterfaceMethod() {
assertEquals("true:[]", list.data("list", Collections.emptyList()).render());
}

@Test
public void testInterfaceHierarchy() {
assertEquals("5:Andy:",
metrics.data("metrics", new Metrics() {

@Override
public Count responses() {
return new Count() {

@Override
public Integer value() {
return 5;
}

@Override
public String name(int age) {
return "Andy";
}
};
}

@Override
public Count requests() {
return null;
}
}).render());

}

public interface Wrapper<T> {
T value();

String name(int age);
}

public interface Count extends Wrapper<Integer> {
}

public interface Metrics {

Count requests();

Count responses();
}
}

0 comments on commit 55288bf

Please sign in to comment.