Type Inference Failed When Registering Multiple ControlsFX Validators


#1

When registering a single validator (using ControlsFX library) per JavaFX control the JavaFX program compiles fine. However when registering multiple validators compilation fails with a type inference failed message. Below is the code snippet:


class MainWindowController {
    @FXML
    private lateinit var inputVoltageTxt: TextField
    @FXML
    private lateinit var outputVoltageTxt: TextField
    @FXML
    private lateinit var resistance1Txt: TextField
    @FXML
    private lateinit var resistance2Txt: TextField
    @FXML
    private lateinit var calculateBtn: Button

    @FXML
    private fun initialize() {
        val MAX_LENGTH = 6
        val NUM_MSG = "A valid number must be entered"
        val MAX_LENGTH_MSG = "Field exceeds the maximum length ($MAX_LENGTH) allowed"
        val validation = ValidationSupport()
        val maxLengthValidator = { control: Control, newVal: String ->
            ValidationResult.fromErrorIf(
                    control, MAX_LENGTH_MSG, if (control is TextField) control.length > MAX_LENGTH else false
            )
        }
        val doubleValidator = { control: Control, newVal: String ->
            ValidationResult.fromErrorIf(
                    control, NUM_MSG, if (control is TextField) !control.text.isDouble() else false
            )
        }

        validation.registerValidator(inputVoltageTxt, false, Validator.combine(doubleValidator, maxLengthValidator))
        validation.registerValidator(outputVoltageTxt, false, Validator.combine(doubleValidator, maxLengthValidator))
        validation.registerValidator(resistance1Txt, false, Validator.combine(doubleValidator, maxLengthValidator))
        validation.registerValidator(resistance2Txt, false, Validator.combine(doubleValidator, maxLengthValidator))
        validation.validationResultProperty().addListener { o, oldVal, newVal ->
            calculateBtn.isDisable = newVal.errors.isNotEmpty() }
    }

    // ...
}

Using Kotlin 1.0.4, ControlsFX 8.40.12, and JavaFX 8 Update 66.

Is there a way to get around this?


#2

Short answer is: you should add Validator before lambda definition. Like this:

val maxLengthValidator = Validator { control: Control, newVal: String ->
            ValidationResult.fromErrorIf(
                    control, MAX_LENGTH_MSG, if (control is TextField) control.length > MAX_LENGTH else false
            )
        }

Right now SAM conversion is not working for functions with vararg parameter(correponding bug: https://youtrack.jetbrains.com/issue/KT-14233).
Because of this in your snippet we have the following situation: maxLengthValidator has type (Control, String) -> ValidationResult. But function Validator.combine expect Validator as argument.

So, when we add Validator before lambda then type of maxLengthValidator transformed to Validator<String> and code start working.


#3

Where is the Type Inference getting String, in Validator?


#4

Discovered an issue with Discourse where it can’t handle ‘<’ & ‘>’ characters in formatting. Validator should have been displayed as Validator[left_arrow_char]String[right_arrow_char].