So we are using Vaadin. Vaadin comes with a Key interface. I copied it and deleted all entries except the CONTROL key (for demonstration purposes here, we don't copy the classes in our actual code):
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;
import java.util.stream.Stream;
@FunctionalInterface
public interface VaadinKey extends Serializable {
VaadinKey CONTROL = VaadinKey.of("Control", "ControlLeft", "ControlRight");
//...
static VaadinKey of(String key, String... additionalKeys) {
Objects.requireNonNull(key);
if ("".equals(key)) {
throw new IllegalArgumentException("'key' cannot be empty");
}
List<String> keys = new ArrayList<>();
keys.add(key);
keys.addAll(Arrays.asList(additionalKeys));
return () -> keys;
}
List<String> getKeys();
default boolean matches(String key) {
return getKeys().contains(key);
}
static boolean isModifier(com.vaadin.flow.component.Key key) {
return Stream.of(VaadinKeyModifier.values())
.anyMatch(k -> k.matches(key.getKeys().get(0)));
}
}
The interface is implemented by a KeyModifier class, that I've also copied out and stripped down:
import java.util.List;
import java.util.stream.Stream;
public enum VaadinKeyModifier implements VaadinKey {
/**
* KeyModifier for "{@code Control}" key.
*/
CONTROL(VaadinKey.CONTROL)
//...
;
private final VaadinKey key;
VaadinKeyModifier(VaadinKey key) {
this.key = key;
}
@Override
public List<String> getKeys() {
return key.getKeys();
}
public static VaadinKeyModifier of(String key) {
return Stream.of(values()).filter(k -> k.matches(key)).findFirst()
.orElseThrow(IllegalArgumentException::new);
}
}
Now let's try to use it from Kotlin:
fun foo() {
val ctrl: VaadinKeyModifier = VaadinKeyModifier.CONTROL
}
This will fail to compile because
Type mismatch: inferred type is VaadinKey! but VaadinKeyModifier was expected
(And if I ctrl+click it in IntelliJ, it will also take me to the VaadinKey interface.)
I also tried
import com.[...].VaadinKeyModifier.CONTROL as CONTROL_MODIFIER
fun foo() {
val ctrl: VaadinKeyModifier = CONTROL_MODIFIER
}
With the same result.
Now interestingly, the direct use of VaadinKeyModifier.CONTROL will not register any usage of VaadinKeyModifier::CONTROL, whereas the import variant registers one usage in the import (which however does not prevent the compilation error).
What gives?
Why does this happen?
And how do I get this to work?