Update kotlin compile testing to 1.3.5

This version includes a fix where java sources were not
provided to KSP, which means getSymbolsAnnotatedWith didn't
work.

Unfortunately, this update hit a bug in KSP/KCT (not sure yet) where KSP
cannot find java sources. After a long investigation (see github
issues), I figured it is the lack of javaSourceRoots argument being
passed into KotlinCompilation that confuses KSP (but regular kotlin
compilation works fine). KCT does not set it and cannot easily set it
since its public API receives any file as an argument (so it cannot
calculate a root). For this reason, now Room's abstraction passes that
argument directly.

As part of that change, I also changed how SourceFile's are converted.
Now we always build a "proper" folder structure before calling KCT. I've
refactored all 3 places where we use KCT to use this common path.

https://github.com/tschuchortdev/kotlin-compile-testing/issues/105
https://github.com/google/ksp/issues/263

Test: existing tests
Change-Id: Ibd0d6fc46849c2a0489b2bb632a2c19862e31c9e
diff --git a/buildSrc/src/main/kotlin/androidx/build/dependencies/Dependencies.kt b/buildSrc/src/main/kotlin/androidx/build/dependencies/Dependencies.kt
index 384cd9a..58a9c20 100644
--- a/buildSrc/src/main/kotlin/androidx/build/dependencies/Dependencies.kt
+++ b/buildSrc/src/main/kotlin/androidx/build/dependencies/Dependencies.kt
@@ -76,8 +76,8 @@
 const val KOTLINPOET_METADATA_SPECS = "com.squareup:kotlinpoet-metadata-specs:1.4.0"
 const val KOTLINPOET_CLASSINSPECTOR_ELEMENTS =
     "com.squareup:kotlinpoet-classinspector-elements:1.4.0"
-const val KOTLIN_COMPILE_TESTING = "com.github.tschuchortdev:kotlin-compile-testing:1.3.4"
-const val KOTLIN_COMPILE_TESTING_KSP = "com.github.tschuchortdev:kotlin-compile-testing-ksp:1.3.4"
+const val KOTLIN_COMPILE_TESTING = "com.github.tschuchortdev:kotlin-compile-testing:1.3.5"
+const val KOTLIN_COMPILE_TESTING_KSP = "com.github.tschuchortdev:kotlin-compile-testing-ksp:1.3.5"
 
 /**
  * KSP is used both as a plugin and runtime dependency, hence its version is declared in the
diff --git a/room/compiler-processing-testing/src/main/java/androidx/room/compiler/processing/util/KotlinCompilationUtil.kt b/room/compiler-processing-testing/src/main/java/androidx/room/compiler/processing/util/KotlinCompilationUtil.kt
new file mode 100644
index 0000000..5554597
--- /dev/null
+++ b/room/compiler-processing-testing/src/main/java/androidx/room/compiler/processing/util/KotlinCompilationUtil.kt
@@ -0,0 +1,49 @@
+/*
+ * Copyright 2021 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 androidx.room.compiler.processing.util
+
+import com.tschuchort.compiletesting.KotlinCompilation
+import java.io.File
+
+/**
+ * Helper class for Kotlin Compile Testing library to have common setup for room.
+ */
+internal object KotlinCompilationUtil {
+    fun prepareCompilation(
+        sources: List<Source>,
+        classpaths: List<File> = emptyList()
+    ): KotlinCompilation {
+        val compilation = KotlinCompilation()
+        val srcRoot = compilation.workingDir.resolve("ksp/srcInput")
+        val javaSrcRoot = srcRoot.resolve("java")
+        val kotlinSrcRoot = srcRoot.resolve("kotlin")
+        compilation.sources = sources.map {
+            when (it) {
+                is Source.JavaSource -> it.toKotlinSourceFile(javaSrcRoot)
+                is Source.KotlinSource -> it.toKotlinSourceFile(kotlinSrcRoot)
+            }
+        }
+        // workaround for https://github.com/tschuchortdev/kotlin-compile-testing/issues/105
+        compilation.kotlincArguments += "-Xjava-source-roots=${javaSrcRoot.absolutePath}"
+        compilation.jvmDefault = "enable"
+        compilation.jvmTarget = "1.8"
+        compilation.inheritClassPath = true
+        compilation.verbose = false
+        compilation.classpaths += classpaths
+        return compilation
+    }
+}
\ No newline at end of file
diff --git a/room/compiler-processing-testing/src/main/java/androidx/room/compiler/processing/util/ProcessorTestExt.kt b/room/compiler-processing-testing/src/main/java/androidx/room/compiler/processing/util/ProcessorTestExt.kt
index b4beb39..7b806e2 100644
--- a/room/compiler-processing-testing/src/main/java/androidx/room/compiler/processing/util/ProcessorTestExt.kt
+++ b/room/compiler-processing-testing/src/main/java/androidx/room/compiler/processing/util/ProcessorTestExt.kt
@@ -165,20 +165,7 @@
 fun compileFiles(
     sources: List<Source>
 ): File {
-    val compilation = KotlinCompilation()
-    sources.forEach {
-        compilation.workingDir.resolve("sources")
-            .resolve(it.relativePath())
-            .parentFile
-            .mkdirs()
-    }
-    compilation.sources = sources.map {
-        it.toKotlinSourceFile()
-    }
-    compilation.jvmDefault = "enable"
-    compilation.jvmTarget = "1.8"
-    compilation.inheritClassPath = true
-    compilation.verbose = false
+    val compilation = KotlinCompilationUtil.prepareCompilation(sources = sources)
     val result = compilation.compile()
     check(result.exitCode == KotlinCompilation.ExitCode.OK) {
         "compilation failed: ${result.messages}"
diff --git a/room/compiler-processing-testing/src/main/java/androidx/room/compiler/processing/util/Source.kt b/room/compiler-processing-testing/src/main/java/androidx/room/compiler/processing/util/Source.kt
index 778b6b8..68df609 100644
--- a/room/compiler-processing-testing/src/main/java/androidx/room/compiler/processing/util/Source.kt
+++ b/room/compiler-processing-testing/src/main/java/androidx/room/compiler/processing/util/Source.kt
@@ -19,6 +19,7 @@
 import com.google.testing.compile.JavaFileObjects
 import com.tschuchort.compiletesting.SourceFile
 import org.intellij.lang.annotations.Language
+import java.io.File
 import javax.tools.JavaFileObject
 
 /**
@@ -26,11 +27,7 @@
  */
 sealed class Source {
     abstract fun toJFO(): JavaFileObject
-    abstract fun toKotlinSourceFile(): SourceFile
-
-    // we need this for kotlin compile testing as it doesn't create directories
-    abstract fun relativePath(): String
-
+    abstract fun toKotlinSourceFile(srcRoot: File): SourceFile
     class JavaSource(
         val qName: String,
         val contents: String
@@ -42,14 +39,16 @@
             )
         }
 
-        override fun toKotlinSourceFile(): SourceFile {
-            return SourceFile.java(
-                relativePath(),
-                contents
-            )
+        override fun toKotlinSourceFile(srcRoot: File): SourceFile {
+            val outFile = srcRoot.resolve(relativePath())
+                .also {
+                    it.parentFile.mkdirs()
+                    it.writeText(contents)
+                }
+            return SourceFile.fromPath(outFile)
         }
 
-        override fun relativePath(): String {
+        private fun relativePath(): String {
             return qName.replace(".", "/") + ".java"
         }
     }
@@ -62,14 +61,15 @@
             throw IllegalStateException("cannot include kotlin code in javac compilation")
         }
 
-        override fun toKotlinSourceFile(): SourceFile {
-            return SourceFile.kotlin(
-                filePath,
-                contents
+        override fun toKotlinSourceFile(srcRoot: File): SourceFile {
+            val outFile = srcRoot.resolve(filePath).also {
+                it.parentFile.mkdirs()
+                it.writeText(contents)
+            }
+            return SourceFile.fromPath(
+                outFile
             )
         }
-
-        override fun relativePath(): String = filePath
     }
 
     companion object {
diff --git a/room/compiler-processing-testing/src/main/java/androidx/room/compiler/processing/util/runner/KaptCompilationTestRunner.kt b/room/compiler-processing-testing/src/main/java/androidx/room/compiler/processing/util/runner/KaptCompilationTestRunner.kt
index 9534163..6a98998 100644
--- a/room/compiler-processing-testing/src/main/java/androidx/room/compiler/processing/util/runner/KaptCompilationTestRunner.kt
+++ b/room/compiler-processing-testing/src/main/java/androidx/room/compiler/processing/util/runner/KaptCompilationTestRunner.kt
@@ -18,6 +18,7 @@
 
 import androidx.room.compiler.processing.SyntheticJavacProcessor
 import androidx.room.compiler.processing.util.CompilationResult
+import androidx.room.compiler.processing.util.KotlinCompilationUtil
 import androidx.room.compiler.processing.util.KotlinCompileTestingCompilationResult
 import com.tschuchort.compiletesting.KotlinCompilation
 
@@ -31,23 +32,11 @@
 
     override fun compile(params: TestCompilationParameters): CompilationResult {
         val syntheticJavacProcessor = SyntheticJavacProcessor(params.handler)
-        val compilation = KotlinCompilation()
-        params.sources.forEach {
-            compilation.workingDir.resolve("sources")
-                .resolve(it.relativePath())
-                .parentFile
-                .mkdirs()
-        }
-        compilation.sources = params.sources.map {
-            it.toKotlinSourceFile()
-        }
-        compilation.jvmDefault = "enable"
-        compilation.jvmTarget = "1.8"
+        val compilation = KotlinCompilationUtil.prepareCompilation(
+            sources = params.sources,
+            classpaths = params.classpath
+        )
         compilation.annotationProcessors = listOf(syntheticJavacProcessor)
-        compilation.inheritClassPath = true
-        compilation.verbose = false
-        compilation.classpaths += params.classpath
-
         val result = compilation.compile()
         return KotlinCompileTestingCompilationResult(
             testRunner = this,
diff --git a/room/compiler-processing-testing/src/main/java/androidx/room/compiler/processing/util/runner/KspCompilationTestRunner.kt b/room/compiler-processing-testing/src/main/java/androidx/room/compiler/processing/util/runner/KspCompilationTestRunner.kt
index 8ac5ed3..91a2b21 100644
--- a/room/compiler-processing-testing/src/main/java/androidx/room/compiler/processing/util/runner/KspCompilationTestRunner.kt
+++ b/room/compiler-processing-testing/src/main/java/androidx/room/compiler/processing/util/runner/KspCompilationTestRunner.kt
@@ -18,6 +18,7 @@
 
 import androidx.room.compiler.processing.SyntheticKspProcessor
 import androidx.room.compiler.processing.util.CompilationResult
+import androidx.room.compiler.processing.util.KotlinCompilationUtil
 import androidx.room.compiler.processing.util.KotlinCompileTestingCompilationResult
 import androidx.room.compiler.processing.util.Source
 import com.tschuchort.compiletesting.KotlinCompilation
@@ -45,26 +46,11 @@
             params.sources
         }
         val syntheticKspProcessor = SyntheticKspProcessor(params.handler)
-        fun prepareCompilation(): KotlinCompilation {
-            val compilation = KotlinCompilation()
-            sources.forEach {
-                compilation.workingDir.resolve("sources")
-                    .resolve(it.relativePath())
-                    .parentFile
-                    .mkdirs()
-            }
-            compilation.sources = sources.map {
-                it.toKotlinSourceFile()
-            }
-            compilation.jvmDefault = "enable"
-            compilation.jvmTarget = "1.8"
-            compilation.inheritClassPath = true
-            compilation.verbose = false
-            compilation.classpaths += params.classpath
-            return compilation
-        }
 
-        val kspCompilation = prepareCompilation()
+        val kspCompilation = KotlinCompilationUtil.prepareCompilation(
+            sources,
+            params.classpath
+        )
         kspCompilation.symbolProcessors = listOf(syntheticKspProcessor)
         kspCompilation.compile()
         // ignore KSP result for now because KSP stops compilation, which might create false
@@ -73,7 +59,10 @@
         //  fixed
 
         // after ksp, compile without ksp with KSP's output as input
-        val finalCompilation = prepareCompilation()
+        val finalCompilation = KotlinCompilationUtil.prepareCompilation(
+            sources,
+            params.classpath
+        )
         // build source files from generated code
         finalCompilation.sources += kspCompilation.kspJavaSourceDir.collectSourceFiles() +
             kspCompilation.kspKotlinSourceDir.collectSourceFiles()
@@ -88,7 +77,6 @@
             processor = syntheticKspProcessor,
             successfulCompilation = result.exitCode == KotlinCompilation.ExitCode.OK &&
                 !hasErrorDiagnostics
-
         )
     }
 
diff --git a/room/compiler/src/test/data/common/input/guava/ListenableFuture.java b/room/compiler/src/test/data/common/input/guava/ListenableFuture.java
index 2c25b8a..9c1d64e 100644
--- a/room/compiler/src/test/data/common/input/guava/ListenableFuture.java
+++ b/room/compiler/src/test/data/common/input/guava/ListenableFuture.java
@@ -13,7 +13,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-
+package com.google.common.util.concurrent;
 // fake ListenableFuture
 import java.util.concurrent.Executor;
 import java.util.concurrent.Future;