Skip to content

Commit

Permalink
Qute - fix validation of primitives
Browse files Browse the repository at this point in the history
- fix a regression caused by
2b01ca7
  • Loading branch information
mkouba committed Feb 18, 2021
1 parent 40b89fd commit de57c4d
Show file tree
Hide file tree
Showing 7 changed files with 91 additions and 35 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -642,26 +642,28 @@ static Match validateNestedExpressions(TemplateAnalysis templateAnalysis, ClassI
}
}
}
if (member == null) {
// Then try to find an etension method
member = findTemplateExtensionMethod(info, match.type(), templateExtensionMethods, expression,
index,
templateIdToPathFun, results);
}
if (member == null) {
// Test whether the validation should be skipped
TypeCheck check = new TypeCheck(
info.isProperty() ? info.asProperty().name : info.asVirtualMethod().name,
match.clazz(),
info.part.isVirtualMethod() ? info.part.asVirtualMethod().getParameters().size() : -1);
if (isExcluded(check, excludes)) {
LOGGER.debugf(
"Expression part [%s] excluded from validation of [%s] against type [%s]",
info.value,
expression.toOriginalString(), match.type());
match.clearValues();
break;
}
}

if (member == null) {
// Then try to find an etension method
member = findTemplateExtensionMethod(info, match.type(), templateExtensionMethods, expression,
index,
templateIdToPathFun, results);
}

if (member == null) {
// Test whether the validation should be skipped
TypeCheck check = new TypeCheck(
info.isProperty() ? info.asProperty().name : info.asVirtualMethod().name,
match.clazz(),
info.part.isVirtualMethod() ? info.part.asVirtualMethod().getParameters().size() : -1);
if (isExcluded(check, excludes)) {
LOGGER.debugf(
"Expression part [%s] excluded from validation of [%s] against type [%s]",
info.value,
expression.toOriginalString(), match.type());
match.clearValues();
break;
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ public class Movie {

public final Boolean alwaysTrue;

public final boolean alwaysFalsePrimitive = false;

public final List<String> mainCharacters;

public Movie(String... mainCharacters) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,4 +17,8 @@ static Long toLong(Movie movie, long... values) {
return ret;
}

static boolean negate(boolean val) {
return !val;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@ public class ValidationSuccessTest {
// Built-in value resolvers
+ "{movie.name ?: 'Mono'} "
+ "{movie.alwaysTrue ? 'Mono' : 'Stereo'} "
+ "{movie.alwaysFalsePrimitive ? 'Mono' : 'Stereo'} "
+ "{movie.alwaysFalsePrimitive.negate} "
+ "{movie.mainCharacters.size} "
// Name and number of params ok and param type ignored
+ "{movie.findService('foo')} "
Expand All @@ -53,7 +55,7 @@ public class ValidationSuccessTest {
@Test
public void testResult() {
// Validation succeeded! Yay!
assertEquals("Jason Jason Mono 1 10 11 ok 43 3 ohn bar",
assertEquals("Jason Jason Mono Stereo true 1 10 11 ok 43 3 ohn bar",
movie.data("movie", new Movie("John"), "name", "Vasik", "surname", "Hu", "age", 10l, "map",
Collections.singletonMap("foo", "bar")).render());
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package io.quarkus.qute.generator;

import java.util.concurrent.CompletionStage;
import org.jboss.jandex.DotName;

final class DotNames {

static final DotName BOOLEAN = DotName.createSimple(Boolean.class.getName());
static final DotName BYTE = DotName.createSimple(Byte.class.getName());
static final DotName CHARACTER = DotName.createSimple(Character.class.getName());
static final DotName DOUBLE = DotName.createSimple(Double.class.getName());
static final DotName FLOAT = DotName.createSimple(Float.class.getName());
static final DotName INTEGER = DotName.createSimple(Integer.class.getName());
static final DotName LONG = DotName.createSimple(Long.class.getName());
static final DotName SHORT = DotName.createSimple(Short.class.getName());
static final DotName STRING = DotName.createSimple(String.class.getName());
static final DotName COMPLETION_STAGE = DotName.createSimple(CompletionStage.class.getName());
static final DotName OBJECT = DotName.createSimple(Object.class.getName());

}
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@
import org.jboss.jandex.DotName;
import org.jboss.jandex.IndexView;
import org.jboss.jandex.MethodInfo;
import org.jboss.jandex.PrimitiveType.Primitive;
import org.jboss.jandex.Type;
import org.jboss.jandex.Type.Kind;

Expand All @@ -55,8 +56,6 @@
public class ExtensionMethodGenerator {

public static final DotName TEMPLATE_EXTENSION = DotName.createSimple(TemplateExtension.class.getName());
static final DotName STRING = DotName.createSimple(String.class.getName());

public static final String SUFFIX = "_Extension" + ValueResolverGenerator.SUFFIX;
public static final String NAMESPACE_SUFFIX = "_Namespace" + SUFFIX;

Expand Down Expand Up @@ -132,7 +131,7 @@ public void generate(MethodInfo method, String matchName, String matchRegex, Int

if (matchRegex != null || matchName.equals(TemplateExtension.ANY)) {
// The second parameter must be a string
if (parameters.size() < 2 || !parameters.get(1).name().equals(STRING)) {
if (parameters.size() < 2 || !parameters.get(1).name().equals(io.quarkus.qute.generator.DotNames.STRING)) {
throw new TemplateException(
"A template extension method matching multiple names or a regular expression must declare at least two parameters and the second parameter must be string: "
+ method);
Expand Down Expand Up @@ -352,7 +351,8 @@ private void implementAppliesTo(ClassCreator valueResolver, MethodInfo method, S

// Test base object class
ResultHandle baseClass = appliesTo.invokeVirtualMethod(Descriptors.GET_CLASS, base);
ResultHandle testClass = appliesTo.loadClass(parameters.get(0).name().toString());
// Perform autoboxing for primitives
ResultHandle testClass = appliesTo.loadClass(box(parameters.get(0)).name().toString());
ResultHandle baseClassTest = appliesTo.invokeVirtualMethod(Descriptors.IS_ASSIGNABLE_FROM, testClass,
baseClass);
BytecodeCreator baseNotAssignable = appliesTo.ifTrue(baseClassTest).falseBranch();
Expand Down Expand Up @@ -633,4 +633,34 @@ static String sha1(String value) {
}
}

static Type box(Type type) {
if (type.kind() == Kind.PRIMITIVE) {
return box(type.asPrimitiveType().primitive());
}
return type;
}

static Type box(Primitive primitive) {
switch (primitive) {
case BOOLEAN:
return Type.create(DotNames.BOOLEAN, Kind.CLASS);
case DOUBLE:
return Type.create(DotNames.DOUBLE, Kind.CLASS);
case FLOAT:
return Type.create(DotNames.FLOAT, Kind.CLASS);
case LONG:
return Type.create(DotNames.LONG, Kind.CLASS);
case INT:
return Type.create(DotNames.INTEGER, Kind.CLASS);
case BYTE:
return Type.create(DotNames.BYTE, Kind.CLASS);
case CHAR:
return Type.create(DotNames.CHARACTER, Kind.CLASS);
case SHORT:
return Type.create(DotNames.SHORT, Kind.CLASS);
default:
throw new IllegalArgumentException("Unsupported primitive: " + primitive);
}
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -64,10 +64,6 @@ public static Builder builder() {
public static final DotName TEMPLATE_DATA = DotName.createSimple(TemplateData.class.getName());
public static final DotName TEMPLATE_DATA_CONTAINER = DotName.createSimple(TemplateData.Container.class.getName());

private static final DotName COMPLETION_STAGE = DotName.createSimple(CompletionStage.class.getName());
private static final DotName OBJECT = DotName.createSimple(Object.class.getName());
private static final DotName BOOLEAN = DotName.createSimple(Boolean.class.getName());

public static final String SUFFIX = "_ValueResolver";
public static final String NESTED_SEPARATOR = "$_";

Expand Down Expand Up @@ -115,7 +111,7 @@ public void generate() {
Map<DotName, Set<DotName>> superToSub = new HashMap<>();
for (Entry<DotName, ClassInfo> entry : nameToClass.entrySet()) {
DotName superName = entry.getValue().superName();
if (superName != null && !OBJECT.equals(superName)) {
if (superName != null && !DotNames.OBJECT.equals(superName)) {
superToSub.computeIfAbsent(superName, name -> new HashSet<>()).add(entry.getKey());
}
}
Expand All @@ -135,7 +131,7 @@ public void generate() {
generate(entry.getKey(), priority);
// Queue a class removal
DotName superName = entry.getValue().superName();
if (superName != null && !OBJECT.equals(superName)) {
if (superName != null && !DotNames.OBJECT.equals(superName)) {
superToSubRemovals.computeIfAbsent(superName, name -> new HashSet<>()).add(entry.getKey());
}
// Remove the processed binding
Expand Down Expand Up @@ -229,7 +225,7 @@ private void implementResolve(ClassCreator valueResolver, String clazzName, Clas
.collect(Collectors.toList());
if (!ignoreSuperclasses) {
DotName superName = clazz.superName();
while (superName != null && !superName.equals(OBJECT)) {
while (superName != null && !superName.equals(DotNames.OBJECT)) {
ClassInfo superClass = index.getClassByName(superName);
if (superClass != null) {
methods.addAll(
Expand All @@ -250,7 +246,7 @@ private void implementResolve(ClassCreator valueResolver, String clazzName, Clas
if ((field.type().kind() == org.jboss.jandex.Type.Kind.PRIMITIVE
&& field.type().asPrimitiveType().equals(PrimitiveType.BOOLEAN))
|| (field.type().kind() == org.jboss.jandex.Type.Kind.CLASS
&& field.type().name().equals(BOOLEAN))) {
&& field.type().name().equals(DotNames.BOOLEAN))) {
getterName = IS_PREFIX + capitalize(field.name());
} else {
getterName = GET_PREFIX + capitalize(field.name());
Expand Down Expand Up @@ -837,7 +833,7 @@ static boolean isGetterName(String name, Type returnType) {
return true;
}
if (returnType == null
|| (returnType.name().equals(PrimitiveType.BOOLEAN.name()) || returnType.name().equals(BOOLEAN))) {
|| (returnType.name().equals(PrimitiveType.BOOLEAN.name()) || returnType.name().equals(DotNames.BOOLEAN))) {
return name.startsWith(IS_PREFIX) || name.startsWith(HAS_PREFIX);
}
return false;
Expand Down Expand Up @@ -939,7 +935,7 @@ static String generatedNameFromTarget(String targetPackage, String baseName, Str

public static boolean hasCompletionStageInTypeClosure(ClassInfo classInfo,
IndexView index) {
return hasClassInTypeClosure(classInfo, COMPLETION_STAGE, index);
return hasClassInTypeClosure(classInfo, DotNames.COMPLETION_STAGE, index);
}

public static boolean hasClassInTypeClosure(ClassInfo classInfo, DotName className,
Expand Down

0 comments on commit de57c4d

Please sign in to comment.