diff options
author | Yigit Boyar <yboyar@google.com> | 2017-12-21 10:00:25 -0800 |
---|---|---|
committer | Yigit Boyar <yboyar@google.com> | 2018-05-18 22:25:47 +0000 |
commit | 744db5c5a111d68c30302deae8b4ba1ea9355603 (patch) | |
tree | d77df39f15fa9cfffb37ccdf8f1b3fc1471db120 /compiler/src/main/java/android/databinding/tool | |
parent | 24c7c961ba1eb09dccab240bcd18fd71df09a7dc (diff) | |
download | data-binding-744db5c5a111d68c30302deae8b4ba1ea9355603.tar.gz |
Fix kotlin.Unit method references in binding layouts.
When there is a binding adapter that receives a kotlin
function which does not return, Kotlin converts it to
Function0<kotlin.Unit>. But if there is a kotlin class
with a method that does not return value, kotlin converts
it to void.
This becomes a problem for data binding because it
cannot match the two when using function references.
We cannot simply convert kotlin.Unit to void because
we still generate code in java so we have to return
a value in the implementation.
Instead, this CL changes function matcher to accept
the two as equals and also changes the code generators
to handle the case manually.
Also added a kotlin test app (finally).
Bug: 70915745
Bug: 78662035
Test: KotlinTestApp
Change-Id: I019ee7eb1dd635b12efd7725ccc22f0c63dc2d72
Diffstat (limited to 'compiler/src/main/java/android/databinding/tool')
3 files changed, 19 insertions, 7 deletions
diff --git a/compiler/src/main/java/android/databinding/tool/expr/MethodBaseExpr.java b/compiler/src/main/java/android/databinding/tool/expr/MethodBaseExpr.java index 5f6e1783..3e51b517 100644 --- a/compiler/src/main/java/android/databinding/tool/expr/MethodBaseExpr.java +++ b/compiler/src/main/java/android/databinding/tool/expr/MethodBaseExpr.java @@ -83,9 +83,20 @@ public abstract class MethodBaseExpr extends Expr { final ModelClass[] listenerParameters = listenerMethod.getParameterTypes(); boolean isStatic = getTarget() instanceof StaticIdentifierExpr; List<ModelMethod> methods = childType.findMethods(mName, isStatic); + + final ModelClass listenerMethodReturnType = listenerMethod.getReturnType(null); + final boolean listenerIsKotlinUnit = listenerMethodReturnType.isKotlinUnit(); for (ModelMethod method : methods) { - if (acceptsParameters(method, listenerParameters) && - method.getReturnType(null).equals(listenerMethod.getReturnType(null))) { + final boolean parametersMatch = acceptsParameters(method, listenerParameters); + if (!parametersMatch) { + // no need to check return types. + continue; + } + final ModelClass methodReturnType = method.getReturnType(null); + // accept kotlin.Unit vs void. b/78662035 + final boolean returnTypesMatch = methodReturnType.equals(listenerMethodReturnType) + || (listenerIsKotlinUnit && methodReturnType.isVoid()); + if (returnTypesMatch) { target.getParents().remove(this); resetResolvedType(); // replace this with ListenerExpr in parent diff --git a/compiler/src/main/java/android/databinding/tool/reflection/ModelClass.java b/compiler/src/main/java/android/databinding/tool/reflection/ModelClass.java index 10218782..557ad25a 100644 --- a/compiler/src/main/java/android/databinding/tool/reflection/ModelClass.java +++ b/compiler/src/main/java/android/databinding/tool/reflection/ModelClass.java @@ -698,4 +698,8 @@ public abstract class ModelClass { } return false; } + + public boolean isKotlinUnit() { + return "kotlin.Unit".equals(getTypeName().toString()); + } } diff --git a/compiler/src/main/java/android/databinding/tool/store/SetterStore.java b/compiler/src/main/java/android/databinding/tool/store/SetterStore.java index 24ad9e76..239ca848 100644 --- a/compiler/src/main/java/android/databinding/tool/store/SetterStore.java +++ b/compiler/src/main/java/android/databinding/tool/store/SetterStore.java @@ -241,12 +241,9 @@ public class SetterStore { ExecutableElement bindingMethod, boolean takesComponent) { attribute = stripNamespace(attribute); L.d("STORE addBindingAdapter %s %s", attribute, bindingMethod); - HashMap<AccessorKey, MethodDescription> adapters = mStore.adapterMethods.get(attribute); + HashMap<AccessorKey, MethodDescription> adapters = mStore.adapterMethods + .computeIfAbsent(attribute, k -> new HashMap<>()); - if (adapters == null) { - adapters = new HashMap<AccessorKey, MethodDescription>(); - mStore.adapterMethods.put(attribute, adapters); - } List<? extends VariableElement> parameters = bindingMethod.getParameters(); final int viewIndex = takesComponent ? 1 : 0; TypeMirror viewType = eraseType(processingEnv, parameters.get(viewIndex).asType()); |