Skip to content

Fix check for Kotlin default properties #11813

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
May 23, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@ public static ExpressionDef invokeBeanConstructor(MethodElement constructor,
List<ParameterElement> constructorArguments = Arrays.asList(constructor.getParameters());
allowKotlinDefaults = allowKotlinDefaults && hasKotlinDefaultsParameters(constructorArguments);

List<ExpressionDef> constructorValues = constructorValues(constructor.getParameters(), values, allowKotlinDefaults);
List<ExpressionDef> constructorValues = constructorValues(constructor.getParameters(), values, hasValuesExpressions, allowKotlinDefaults);

if (requiresReflection && !isCompanion) { // Companion and reflection not implemented
return ClassTypeDef.of(InstantiationUtils.class).invokeStatic(
Expand Down Expand Up @@ -175,13 +175,22 @@ private static ExpressionDef invokeKotlinDefaultMethod(ClassElement declaringTyp
private static List<ExpressionDef> constructorValues(ParameterElement[] constructorArguments,
@Nullable
List<? extends ExpressionDef> values,
@Nullable
List<? extends ExpressionDef> hasValuesExpressions,
boolean addKotlinDefaults) {
List<ExpressionDef> expressions = new ArrayList<>(constructorArguments.length);
for (int i = 0; i < constructorArguments.length; i++) {
ParameterElement constructorArgument = constructorArguments[i];
ExpressionDef value = values == null ? null : values.get(i);
if (value != null) {
if (!addKotlinDefaults || value instanceof ExpressionDef.Constant constant && constant.value() != null || !constructorArgument.isPrimitive()) {
if (!addKotlinDefaults || value instanceof ExpressionDef.Constant constant && constant.value() != null) {
expressions.add(value);
} else if (hasValuesExpressions != null) {
// There should be a better way to check if the value exists only once
expressions.add(
hasValuesExpressions.get(i).isTrue().doIfElse(value, getDefaultValue(constructorArgument))
);
} else if (!constructorArgument.isPrimitive()) {
expressions.add(value);
} else {
expressions.add(
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package io.micronaut.validation.validator

import io.micronaut.context.annotation.ConfigurationProperties
import jakarta.validation.constraints.NotBlank

@ConfigurationProperties("app.controller")
data class ControllerCfg(
val enabled: Boolean = true,
@NotBlank val apiBase:String = "https://api.example.com/",
@NotBlank val something: String = "some-value"
)
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,24 @@ import jakarta.validation.ConstraintViolationException

class ValidatorSpec {

@Test
fun propertiesWithValidation() {
val context = ApplicationContext.run()
val conf = context.getBean(ControllerCfg::class.java)
assertEquals("https://api.example.com/", conf.apiBase)
assertEquals(true, conf.enabled)
assertEquals("some-value", conf.something)
context.close()
}

@Test
fun testValidateInstance() {
val context = ApplicationContext.run()
val validator = context.getBean(Validator::class.java)

val person = Person("", 10)
val violations = validator.validate(person)
// TODO: currently fails because bean introspection API does not handle data classes
// assertEquals(2, violations.size)
assertEquals(2, violations.size)
context.close()
}

Expand Down
Loading