Configure kotlin kapt for data binding

This CL changes task manager to detect the existence of kotlin
plugin and configure data binding dependencies for both the
kapt configuration and kapt tasks (kotlin compilation).

This is a bit hacky, normally such thing should happen in an
API between AGP and kotlin plugin but this quickly fixes the
current issue and we can iterate over it.

Bug: 70915745
Test: DataBindingKotlinAppTest
Change-Id: I73f0b619bffed71feced91dc637313a1d48b13d5
diff --git a/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/TaskManager.java b/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/TaskManager.java
index 8b778f3..839b7c2 100644
--- a/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/TaskManager.java
+++ b/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/TaskManager.java
@@ -39,6 +39,7 @@
 import static com.android.build.gradle.internal.scope.TaskOutputHolder.TaskOutputType.APK_MAPPING;
 import static com.android.build.gradle.internal.scope.TaskOutputHolder.TaskOutputType.DATA_BINDING_BASE_CLASS_LOGS_DEPENDENCY_ARTIFACTS;
 import static com.android.build.gradle.internal.scope.TaskOutputHolder.TaskOutputType.DATA_BINDING_BASE_CLASS_SOURCE_OUT;
+import static com.android.build.gradle.internal.scope.TaskOutputHolder.TaskOutputType.DATA_BINDING_DEPENDENCY_ARTIFACTS;
 import static com.android.build.gradle.internal.scope.TaskOutputHolder.TaskOutputType.INSTANT_RUN_MAIN_APK_RESOURCES;
 import static com.android.build.gradle.internal.scope.TaskOutputHolder.TaskOutputType.INSTANT_RUN_MERGED_MANIFESTS;
 import static com.android.build.gradle.internal.scope.TaskOutputHolder.TaskOutputType.JAVAC;
@@ -230,11 +231,13 @@
 import java.util.Collections;
 import java.util.List;
 import java.util.Locale;
+import java.util.Map;
 import java.util.Optional;
 import java.util.Set;
 import java.util.function.Consumer;
 import java.util.function.Supplier;
 import java.util.stream.Collectors;
+import org.gradle.api.Action;
 import org.gradle.api.DefaultTask;
 import org.gradle.api.GradleException;
 import org.gradle.api.Project;
@@ -251,6 +254,7 @@
 import org.gradle.api.plugins.BasePlugin;
 import org.gradle.api.plugins.JavaBasePlugin;
 import org.gradle.api.plugins.JavaPlugin;
+import org.gradle.api.tasks.PathSensitivity;
 import org.gradle.api.tasks.Sync;
 import org.gradle.api.tasks.TaskAction;
 import org.gradle.api.tasks.compile.JavaCompile;
@@ -3549,7 +3553,8 @@
         return logger;
     }
 
-    public void addDataBindingDependenciesIfNecessary(DataBindingOptions options) {
+    public void addDataBindingDependenciesIfNecessary(
+            DataBindingOptions options, List<VariantScope> variantScopes) {
         if (!options.isEnabled()) {
             return;
         }
@@ -3587,6 +3592,92 @@
                                     + ":"
                                     + dataBindingBuilder.getBaseAdaptersVersion(version));
         }
+        project.getPluginManager()
+                .withPlugin(
+                        "org.jetbrains.kotlin.kapt",
+                        appliedPlugin -> {
+                            configureKotlinKaptTasksForDataBinding(project, variantScopes, version);
+                        });
+    }
+
+    private void configureKotlinKaptTasksForDataBinding(
+            Project project, List<VariantScope> variantScopes, String version) {
+        project.getDependencies()
+                .add(
+                        "kapt",
+                        SdkConstants.DATA_BINDING_ANNOTATION_PROCESSOR_ARTIFACT + ":" + version);
+        Class<? extends Task> kaptTaskClass = null;
+        try {
+            //noinspection unchecked
+            kaptTaskClass =
+                    (Class<? extends Task>)
+                            Class.forName("org.jetbrains.kotlin.gradle.internal.KaptTask");
+        } catch (ClassNotFoundException e) {
+            logger.error(
+                    "Kotlin plugin is applied to the project "
+                            + project.getPath()
+                            + " but we cannot find the KaptTask. Make sure you apply the"
+                            + " kotlin-kapt plugin because it is necessary to use kotlin"
+                            + " with data binding.");
+        }
+        if (kaptTaskClass == null) {
+            return;
+        }
+        // create a map from kapt task name to variant scope
+        Map<String, VariantScope> kaptTaskLookup =
+                variantScopes
+                        .stream()
+                        .collect(
+                                Collectors.toMap(
+                                        variantScope ->
+                                                variantScope
+                                                        .getVariantData()
+                                                        .getTaskName("kapt", "Kotlin"),
+                                        variantScope -> variantScope));
+        project.getTasks()
+                .withType(
+                        kaptTaskClass,
+                        (Action<Task>)
+                                kaptTask -> {
+                                    // find matching scope.
+                                    VariantScope matchingScope =
+                                            kaptTaskLookup.get(kaptTask.getName());
+                                    if (matchingScope != null) {
+                                        configureKaptTaskInScope(matchingScope, kaptTask);
+                                    }
+                                });
+    }
+
+    private static void configureKaptTaskInScope(VariantScope scope, Task kaptTask) {
+        if (scope.hasOutput(DATA_BINDING_DEPENDENCY_ARTIFACTS)) {
+            // if data binding is enabled and this variant has merged dependency artifacts, then
+            // make the compilation task depend on them. (test variants don't do the merge so they
+            // could not have the artifacts)
+            kaptTask.getInputs()
+                    .files(scope.getOutput(DATA_BINDING_DEPENDENCY_ARTIFACTS))
+                    .withPathSensitivity(PathSensitivity.RELATIVE)
+                    .withPropertyName("dataBindingDependencyArtifacts");
+        }
+        if (scope.hasOutput(TaskOutputHolder.TaskOutputType.DATA_BINDING_BASE_CLASS_LOG_ARTIFACT)) {
+            kaptTask.getInputs()
+                    .files(
+                            scope.getOutput(
+                                    TaskOutputHolder.TaskOutputType
+                                            .DATA_BINDING_BASE_CLASS_LOG_ARTIFACT))
+                    .withPathSensitivity(PathSensitivity.RELATIVE)
+                    .withPropertyName("dataBindingClassLogDir");
+        }
+        // the data binding artifact is created by the annotation processor, so we register this
+        // task output (which also publishes it) with javac as the generating task.
+        kaptTask.getOutputs()
+                .files(scope.getBundleArtifactFolderForDataBinding())
+                .withPropertyName("dataBindingArtifactOutputDir");
+        if (!scope.hasOutput(TaskOutputHolder.TaskOutputType.DATA_BINDING_ARTIFACT)) {
+            scope.addTaskOutput(
+                    TaskOutputHolder.TaskOutputType.DATA_BINDING_ARTIFACT,
+                    scope.getBundleArtifactFolderForDataBinding(),
+                    kaptTask.getName());
+        }
     }
 
     protected void configureTestData(AbstractTestDataImpl testData) {
diff --git a/build-system/gradle/src/main/java/com/android/build/gradle/BasePlugin.java b/build-system/gradle/src/main/java/com/android/build/gradle/BasePlugin.java
index 57aaafd..ef77a19 100644
--- a/build-system/gradle/src/main/java/com/android/build/gradle/BasePlugin.java
+++ b/build-system/gradle/src/main/java/com/android/build/gradle/BasePlugin.java
@@ -720,7 +720,6 @@
         // setup SDK repositories.
         sdkHandler.addLocalRepositories(project);
 
-        taskManager.addDataBindingDependenciesIfNecessary(extension.getDataBinding());
         threadRecorder.record(
                 ExecutionType.VARIANT_MANAGER_CREATE_ANDROID_TASKS,
                 project.getPath(),
@@ -737,6 +736,10 @@
                         BaseVariantData variantData = variantScope.getVariantData();
                         apiObjectFactory.create(variantData);
                     }
+                    // must run this after scopes are created so that we can configure kotlin
+                    // kapt tasks
+                    taskManager.addDataBindingDependenciesIfNecessary(
+                            extension.getDataBinding(), variantManager.getVariantScopes());
                 });
 
         // create the global lint task that depends on all the variants
diff --git a/build-system/integration-test/application/src/test/java/com/android/build/gradle/integration/automatic/CheckAll.java b/build-system/integration-test/application/src/test/java/com/android/build/gradle/integration/automatic/CheckAll.java
index d78f19c..4fbd094 100755
--- a/build-system/integration-test/application/src/test/java/com/android/build/gradle/integration/automatic/CheckAll.java
+++ b/build-system/integration-test/application/src/test/java/com/android/build/gradle/integration/automatic/CheckAll.java
@@ -108,6 +108,7 @@
                     "databindingIncremental",
                     "databindingAndDagger",
                     "databinding",
+                    "databindingAndKotlin",
 
                     // These are all right:
                     "genFolderApi", // Has a required injectable property
diff --git a/build-system/integration-test/databinding/src/test/java/com/android/build/gradle/integration/databinding/DataBindingKotlinAppTest.java b/build-system/integration-test/databinding/src/test/java/com/android/build/gradle/integration/databinding/DataBindingKotlinAppTest.java
deleted file mode 100644
index ef0d0c1..0000000
--- a/build-system/integration-test/databinding/src/test/java/com/android/build/gradle/integration/databinding/DataBindingKotlinAppTest.java
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.build.gradle.integration.databinding;
-
-import com.android.build.gradle.integration.common.category.SmokeTests;
-import com.android.build.gradle.integration.common.fixture.GradleTestProject;
-import com.android.build.gradle.integration.common.utils.TestFileUtils;
-import java.io.IOException;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.experimental.categories.Category;
-
-/** Assemble tests for kotlin. */
-@Category(SmokeTests.class)
-public class DataBindingKotlinAppTest {
-    @Rule
-    public GradleTestProject project =
-            GradleTestProject.builder().fromTestProject("kotlinApp").create();
-
-    @Test
-    public void dataBindingEnabled() throws IOException, InterruptedException {
-        TestFileUtils.appendToFile(
-                project.getSubproject(":app").getBuildFile(),
-                "\n"
-                        + "android.dataBinding.enabled = true\n"
-                        + "\n"
-                        + "dependencies {\n"
-                        + "    compile \"com.android.support:support-v4:${rootProject.supportLibVersion}\"\n"
-                        + "}\n");
-
-        project.executor().run("clean", "app:assembleDebug");
-    }
-}
diff --git a/build-system/integration-test/databinding/src/test/java/com/android/build/gradle/integration/databinding/DataBindingKotlinAppTest.kt b/build-system/integration-test/databinding/src/test/java/com/android/build/gradle/integration/databinding/DataBindingKotlinAppTest.kt
new file mode 100644
index 0000000..dc9fa2b
--- /dev/null
+++ b/build-system/integration-test/databinding/src/test/java/com/android/build/gradle/integration/databinding/DataBindingKotlinAppTest.kt
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.build.gradle.integration.databinding;
+
+import com.android.build.gradle.integration.common.fixture.GradleTestProject
+import com.android.build.gradle.integration.common.runner.FilterableParameterized
+import com.android.build.gradle.integration.common.truth.TruthHelper.assertThat
+import com.android.build.gradle.options.BooleanOption
+import org.junit.Rule
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.junit.runners.Parameterized
+
+/** Assemble tests for kotlin. */
+@RunWith(FilterableParameterized::class)
+class DataBindingKotlinAppTest(private val useV2 : Boolean) {
+    @Rule @JvmField
+    val project =
+            GradleTestProject.builder()
+                    .fromTestProject("databindingAndKotlin")
+                    .withDependencyChecker(false) // breaks w/ kapt
+                    .addGradleProperties(
+                            BooleanOption.ENABLE_DATA_BINDING_V2.propertyName
+                                    + "="
+                                    + useV2)
+                    .create()
+
+    companion object {
+        @Parameterized.Parameters(name = "useV2_{0}")
+        @JvmStatic
+        fun params() = listOf(true, false)
+    }
+
+    @Test
+    fun compile() {
+        project.executor().run("app:assembleDebug");
+        val appBindingClass = "Lcom/example/android/kotlin/databinding/ActivityLayoutBinding;"
+        val libBindingClass = "Lcom/example/android/kotlin/lib/databinding/LibActivityLayoutBinding;"
+        //val apk = project.getApk("app", GradleTestProject.ApkType.DEBUG)
+        val apk = project.getSubproject("app").getApk(GradleTestProject.ApkType.DEBUG)
+        assertThat(apk).containsClass(appBindingClass)
+        assertThat(apk).containsClass(libBindingClass)
+        if (useV2) {
+            // implementations should be in as well.
+            assertThat(apk).containsClass(
+                    appBindingClass.replace(";", "Impl;")
+            )
+            assertThat(apk).containsClass(
+                    libBindingClass.replace(";", "Impl;")
+            )
+        }
+    }
+}
diff --git a/build-system/integration-test/test-projects/databindingAndKotlin/app/build.gradle b/build-system/integration-test/test-projects/databindingAndKotlin/app/build.gradle
new file mode 100644
index 0000000..fd65ebd
--- /dev/null
+++ b/build-system/integration-test/test-projects/databindingAndKotlin/app/build.gradle
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+apply plugin: 'com.android.application'
+apply plugin: 'kotlin-android'
+apply plugin: 'kotlin-kapt'
+apply from: "../../commonLocalRepo.gradle"
+
+android {
+    compileSdkVersion rootProject.latestCompileSdk
+    buildToolsVersion = rootProject.buildToolsVersion
+
+    defaultConfig {
+        minSdkVersion 14
+        targetSdkVersion rootProject.latestCompileSdk
+    }
+
+    sourceSets {
+        main.java.srcDirs += 'src/main/kotlin'
+    }
+    dataBinding {
+        enabled = true
+    }
+}
+
+dependencies {
+    api project(':library')
+    implementation "org.jetbrains.kotlin:kotlin-stdlib:$rootProject.kotlinVersion"
+}
diff --git a/build-system/integration-test/test-projects/databindingAndKotlin/app/src/main/AndroidManifest.xml b/build-system/integration-test/test-projects/databindingAndKotlin/app/src/main/AndroidManifest.xml
new file mode 100644
index 0000000..9407273
--- /dev/null
+++ b/build-system/integration-test/test-projects/databindingAndKotlin/app/src/main/AndroidManifest.xml
@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="utf-8"?>
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+    package="com.example.android.kotlin">
+
+    <application android:label="Kotlin app test">
+        <activity android:name=".MainActivity" >
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.LAUNCHER" />
+            </intent-filter>
+        </activity>
+    </application>
+
+</manifest>
diff --git a/build-system/integration-test/test-projects/databindingAndKotlin/app/src/main/kotlin/com/example/android/kotlin/MainActivity.kt b/build-system/integration-test/test-projects/databindingAndKotlin/app/src/main/kotlin/com/example/android/kotlin/MainActivity.kt
new file mode 100644
index 0000000..4d43ab4
--- /dev/null
+++ b/build-system/integration-test/test-projects/databindingAndKotlin/app/src/main/kotlin/com/example/android/kotlin/MainActivity.kt
@@ -0,0 +1,18 @@
+package com.example.android.kotlin
+
+import android.app.Activity
+import android.databinding.DataBindingUtil
+import android.os.Bundle
+import android.view.View
+import android.widget.Button
+import android.widget.TextView
+import com.example.android.kotlin.databinding.ActivityLayoutBinding
+
+class MainActivity : Activity() {
+
+    override fun onCreate(savedInstanceState: Bundle?) {
+        super.onCreate(savedInstanceState)
+        val binding : ActivityLayoutBinding = DataBindingUtil.setContentView(this, R.layout.activity_layout)
+        binding.model = ViewModel("foo", "bar")
+    }
+}
diff --git a/build-system/integration-test/test-projects/databindingAndKotlin/app/src/main/res/layout/activity_incl_library.xml b/build-system/integration-test/test-projects/databindingAndKotlin/app/src/main/res/layout/activity_incl_library.xml
new file mode 100644
index 0000000..da20520
--- /dev/null
+++ b/build-system/integration-test/test-projects/databindingAndKotlin/app/src/main/res/layout/activity_incl_library.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2017 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  -->
+
+<layout>
+    <data>
+        <variable name="model" type="com.example.android.kotlin.ViewModel"/>
+    </data>
+    <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+                    xmlns:tools="http://schemas.android.com/tools"
+                    android:layout_width="match_parent"
+                    android:layout_height="match_parent"
+                    tools:context="com.example.android.kotlin.MainActivity"
+                    tools:showIn="@layout/activity_">
+
+        <include layout="@layout/lib_activity_layout" app:model="@{model}"/>
+    </RelativeLayout>
+
+</layout>
diff --git a/build-system/integration-test/test-projects/databindingAndKotlin/app/src/main/res/layout/activity_layout.xml b/build-system/integration-test/test-projects/databindingAndKotlin/app/src/main/res/layout/activity_layout.xml
new file mode 100644
index 0000000..3b17ea9
--- /dev/null
+++ b/build-system/integration-test/test-projects/databindingAndKotlin/app/src/main/res/layout/activity_layout.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="utf-8"?>
+<layout>
+    <data>
+        <variable name="model" type="com.example.android.kotlin.ViewModel"/>
+    </data>
+    <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+                    xmlns:tools="http://schemas.android.com/tools"
+                    android:layout_width="match_parent"
+                    android:layout_height="match_parent"
+                    tools:context="com.example.android.kotlin.MainActivity"
+                    tools:showIn="@layout/activity_">
+
+        <TextView
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:textAppearance="?android:attr/textAppearanceMedium"
+                android:text="@{model.name}"
+                android:id="@+id/someText"
+                android:layout_alignParentTop="true"
+                android:layout_centerHorizontal="true" />
+
+        <Button
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:text="Click"
+                android:id="@+id/click"
+                android:onClick="viewModel::handleClick"
+                android:layout_below="@+id/someText"
+                android:layout_centerHorizontal="true" />
+    </RelativeLayout>
+
+</layout>
\ No newline at end of file
diff --git a/build-system/integration-test/test-projects/databindingAndKotlin/build.gradle b/build-system/integration-test/test-projects/databindingAndKotlin/build.gradle
new file mode 100644
index 0000000..fbd330e
--- /dev/null
+++ b/build-system/integration-test/test-projects/databindingAndKotlin/build.gradle
@@ -0,0 +1,10 @@
+apply from: "../commonHeader.gradle"
+
+buildscript {
+    apply from: "../commonHeader.gradle"  // for $kotlinVersion
+    apply from: "../commonBuildScript.gradle"
+
+    dependencies {
+        classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$rootProject.kotlinVersion"
+    }
+}
diff --git a/build-system/integration-test/test-projects/databindingAndKotlin/library/build.gradle b/build-system/integration-test/test-projects/databindingAndKotlin/library/build.gradle
new file mode 100644
index 0000000..9fea2cb
--- /dev/null
+++ b/build-system/integration-test/test-projects/databindingAndKotlin/library/build.gradle
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+apply plugin: 'com.android.library'
+apply plugin: 'kotlin-android'
+apply plugin: 'kotlin-kapt'
+apply from: "../../commonLocalRepo.gradle"
+
+android {
+    compileSdkVersion rootProject.latestCompileSdk
+    buildToolsVersion = rootProject.buildToolsVersion
+
+    defaultConfig {
+        minSdkVersion 14
+        targetSdkVersion rootProject.latestCompileSdk
+    }
+
+    sourceSets {
+        main.java.srcDirs += 'src/main/kotlin'
+    }
+    dataBinding {
+        enabled = true
+    }
+}
+
+dependencies {
+    compile "org.jetbrains.kotlin:kotlin-stdlib:$rootProject.kotlinVersion"
+}
diff --git a/build-system/integration-test/test-projects/databindingAndKotlin/library/src/main/AndroidManifest.xml b/build-system/integration-test/test-projects/databindingAndKotlin/library/src/main/AndroidManifest.xml
new file mode 100644
index 0000000..6a56c31
--- /dev/null
+++ b/build-system/integration-test/test-projects/databindingAndKotlin/library/src/main/AndroidManifest.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="utf-8"?>
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+    package="com.example.android.kotlin.lib">
+
+    <application android:label="Kotlin app test">
+    </application>
+
+</manifest>
diff --git a/build-system/integration-test/test-projects/databindingAndKotlin/library/src/main/kotlin/com/example/android/kotlin/LibActivity.kt b/build-system/integration-test/test-projects/databindingAndKotlin/library/src/main/kotlin/com/example/android/kotlin/LibActivity.kt
new file mode 100644
index 0000000..f42130a
--- /dev/null
+++ b/build-system/integration-test/test-projects/databindingAndKotlin/library/src/main/kotlin/com/example/android/kotlin/LibActivity.kt
@@ -0,0 +1,19 @@
+package com.example.android.kotlin
+
+import android.app.Activity
+import android.databinding.DataBindingUtil
+import android.os.Bundle
+import android.view.View
+import android.widget.Button
+import android.widget.TextView
+import com.example.android.kotlin.lib.R
+import com.example.android.kotlin.lib.databinding.LibActivityLayoutBinding
+
+class LibActivity : Activity() {
+
+    override fun onCreate(savedInstanceState: Bundle?) {
+        super.onCreate(savedInstanceState)
+        val binding : LibActivityLayoutBinding = DataBindingUtil.setContentView(this, R.layout.lib_activity_layout)
+        binding.model = ViewModel("foo", "bar")
+    }
+}
diff --git a/build-system/integration-test/test-projects/databindingAndKotlin/library/src/main/kotlin/com/example/android/kotlin/ViewModel.kt b/build-system/integration-test/test-projects/databindingAndKotlin/library/src/main/kotlin/com/example/android/kotlin/ViewModel.kt
new file mode 100644
index 0000000..079ecc1
--- /dev/null
+++ b/build-system/integration-test/test-projects/databindingAndKotlin/library/src/main/kotlin/com/example/android/kotlin/ViewModel.kt
@@ -0,0 +1,22 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.example.android.kotlin
+data class ViewModel(val name : String, val lastName : String) {
+    fun handleClick() {
+
+    }
+}
\ No newline at end of file
diff --git a/build-system/integration-test/test-projects/databindingAndKotlin/library/src/main/res/layout/lib_activity_layout.xml b/build-system/integration-test/test-projects/databindingAndKotlin/library/src/main/res/layout/lib_activity_layout.xml
new file mode 100644
index 0000000..3b17ea9
--- /dev/null
+++ b/build-system/integration-test/test-projects/databindingAndKotlin/library/src/main/res/layout/lib_activity_layout.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="utf-8"?>
+<layout>
+    <data>
+        <variable name="model" type="com.example.android.kotlin.ViewModel"/>
+    </data>
+    <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+                    xmlns:tools="http://schemas.android.com/tools"
+                    android:layout_width="match_parent"
+                    android:layout_height="match_parent"
+                    tools:context="com.example.android.kotlin.MainActivity"
+                    tools:showIn="@layout/activity_">
+
+        <TextView
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:textAppearance="?android:attr/textAppearanceMedium"
+                android:text="@{model.name}"
+                android:id="@+id/someText"
+                android:layout_alignParentTop="true"
+                android:layout_centerHorizontal="true" />
+
+        <Button
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:text="Click"
+                android:id="@+id/click"
+                android:onClick="viewModel::handleClick"
+                android:layout_below="@+id/someText"
+                android:layout_centerHorizontal="true" />
+    </RelativeLayout>
+
+</layout>
\ No newline at end of file
diff --git a/build-system/integration-test/test-projects/databindingAndKotlin/settings.gradle b/build-system/integration-test/test-projects/databindingAndKotlin/settings.gradle
new file mode 100644
index 0000000..3c8defd
--- /dev/null
+++ b/build-system/integration-test/test-projects/databindingAndKotlin/settings.gradle
@@ -0,0 +1 @@
+include 'app', 'library'
\ No newline at end of file