Merge changes Ic3a572e4,I56e090c2,I0463b1bd into androidx-master-dev
* changes:
Run TypeAdapterStore tests with KSP
Enable as many tests as possible with KSP
New processing test APIs
diff --git a/room/compiler-processing-testing/build.gradle b/room/compiler-processing-testing/build.gradle
index 0edce59..0ffb5fd 100644
--- a/room/compiler-processing-testing/build.gradle
+++ b/room/compiler-processing-testing/build.gradle
@@ -26,10 +26,10 @@
dependencies {
implementation("androidx.annotation:annotation:1.1.0")
- implementation(project(":room:room-compiler-processing"))
+ api(project(":room:room-compiler-processing"))
implementation(KOTLIN_STDLIB)
implementation(KOTLIN_KSP_API)
- testImplementation(KOTLIN_KSP)
+ implementation(KOTLIN_KSP)
implementation(GOOGLE_COMPILE_TESTING)
implementation(KOTLIN_COMPILE_TESTING_KSP)
}
diff --git a/room/compiler-processing-testing/src/main/java/androidx/room/compiler/processing/SyntheticJavacProcessor.kt b/room/compiler-processing-testing/src/main/java/androidx/room/compiler/processing/SyntheticJavacProcessor.kt
index 0ac5928..54fc124 100644
--- a/room/compiler-processing-testing/src/main/java/androidx/room/compiler/processing/SyntheticJavacProcessor.kt
+++ b/room/compiler-processing-testing/src/main/java/androidx/room/compiler/processing/SyntheticJavacProcessor.kt
@@ -16,21 +16,27 @@
package androidx.room.compiler.processing
+import androidx.room.compiler.processing.util.RecordingXMessager
import androidx.room.compiler.processing.util.XTestInvocation
-import java.lang.AssertionError
import javax.lang.model.SourceVersion
class SyntheticJavacProcessor(
- val handler: (XTestInvocation) -> Unit
-) : JavacTestProcessor() {
+ val handler: (XTestInvocation) -> Unit,
+) : JavacTestProcessor(), SyntheticProcessor {
+ override val invocationInstances = mutableListOf<XTestInvocation>()
private var result: Result<Unit>? = null
+ override val messageWatcher = RecordingXMessager()
override fun doProcess(annotations: Set<XTypeElement>, roundEnv: XRoundEnv): Boolean {
+ val xEnv = XProcessingEnv.create(processingEnv)
+ xEnv.messager.addMessageWatcher(messageWatcher)
result = kotlin.runCatching {
handler(
XTestInvocation(
- processingEnv = XProcessingEnv.create(processingEnv)
- )
+ processingEnv = xEnv
+ ).also {
+ invocationInstances.add(it)
+ }
)
}
return true
@@ -42,7 +48,7 @@
override fun getSupportedAnnotationTypes() = setOf("*")
- fun throwIfFailed() {
+ override fun throwIfFailed() {
val result = checkNotNull(result) {
"did not compile"
}
diff --git a/room/compiler-processing-testing/src/main/java/androidx/room/compiler/processing/SyntheticKspProcessor.kt b/room/compiler-processing-testing/src/main/java/androidx/room/compiler/processing/SyntheticKspProcessor.kt
index 106d6b1..68ec813 100644
--- a/room/compiler-processing-testing/src/main/java/androidx/room/compiler/processing/SyntheticKspProcessor.kt
+++ b/room/compiler-processing-testing/src/main/java/androidx/room/compiler/processing/SyntheticKspProcessor.kt
@@ -16,6 +16,7 @@
package androidx.room.compiler.processing
+import androidx.room.compiler.processing.util.RecordingXMessager
import androidx.room.compiler.processing.util.XTestInvocation
import com.google.devtools.ksp.processing.CodeGenerator
import com.google.devtools.ksp.processing.KSPLogger
@@ -24,11 +25,14 @@
class SyntheticKspProcessor(
private val handler: (XTestInvocation) -> Unit
-) : SymbolProcessor {
+) : SymbolProcessor, SyntheticProcessor {
+ override val invocationInstances = mutableListOf<XTestInvocation>()
private var result: Result<Unit>? = null
private lateinit var options: Map<String, String>
private lateinit var codeGenerator: CodeGenerator
private lateinit var logger: KSPLogger
+ override val messageWatcher = RecordingXMessager()
+
override fun finish() {
}
@@ -44,21 +48,25 @@
}
override fun process(resolver: Resolver) {
+ val xEnv = XProcessingEnv.create(
+ options,
+ resolver,
+ codeGenerator,
+ logger
+ )
+ xEnv.messager.addMessageWatcher(messageWatcher)
result = kotlin.runCatching {
handler(
XTestInvocation(
- processingEnv = XProcessingEnv.create(
- options,
- resolver,
- codeGenerator,
- logger
- )
- )
+ processingEnv = xEnv
+ ).also {
+ invocationInstances.add(it)
+ }
)
}
}
- fun throwIfFailed() {
+ override fun throwIfFailed() {
val result = checkNotNull(result) {
"did not compile"
}
diff --git a/room/compiler-processing-testing/src/main/java/androidx/room/compiler/processing/SyntheticProcessor.kt b/room/compiler-processing-testing/src/main/java/androidx/room/compiler/processing/SyntheticProcessor.kt
new file mode 100644
index 0000000..05cc826
--- /dev/null
+++ b/room/compiler-processing-testing/src/main/java/androidx/room/compiler/processing/SyntheticProcessor.kt
@@ -0,0 +1,45 @@
+/*
+ * Copyright 2020 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
+
+import androidx.room.compiler.processing.util.RecordingXMessager
+import androidx.room.compiler.processing.util.XTestInvocation
+
+/**
+ * Common interface for SyntheticProcessors that we create for testing.
+ */
+internal interface SyntheticProcessor {
+ /**
+ * List of invocations that was sent to the test code.
+ *
+ * The test code can register assertions on the compilation result, which is why we need this
+ * list (to run assertions after compilation).
+ */
+ val invocationInstances: List<XTestInvocation>
+
+ /**
+ * The recorder for messages where we'll grab the diagnostics.
+ */
+ val messageWatcher: RecordingXMessager
+
+ /**
+ * Should throw if processor did throw an exception.
+ * When assertions fail, we don't fail the compilation to keep the stack trace, instead,
+ * dispatch them afterwards.
+ */
+ fun throwIfFailed()
+}
diff --git a/room/compiler-processing-testing/src/main/java/androidx/room/compiler/processing/util/CompilationResultSubject.kt b/room/compiler-processing-testing/src/main/java/androidx/room/compiler/processing/util/CompilationResultSubject.kt
new file mode 100644
index 0000000..3dbbff7
--- /dev/null
+++ b/room/compiler-processing-testing/src/main/java/androidx/room/compiler/processing/util/CompilationResultSubject.kt
@@ -0,0 +1,210 @@
+/*
+ * Copyright 2020 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 androidx.room.compiler.processing.SyntheticJavacProcessor
+import androidx.room.compiler.processing.SyntheticProcessor
+import androidx.room.compiler.processing.util.runner.CompilationTestRunner
+import com.google.common.truth.Fact.simpleFact
+import com.google.common.truth.FailureMetadata
+import com.google.common.truth.Subject
+import com.google.common.truth.Subject.Factory
+import com.google.common.truth.Truth
+import com.google.testing.compile.Compilation
+import com.google.testing.compile.CompileTester
+import com.tschuchort.compiletesting.KotlinCompilation
+import javax.tools.Diagnostic
+
+/**
+ * Holds the information about a test compilation result.
+ */
+abstract class CompilationResult internal constructor(
+ /**
+ * The test infra which run this test
+ */
+ internal val testRunnerName: String,
+ /**
+ * The [SyntheticProcessor] used in this compilation.
+ */
+ internal val processor: SyntheticProcessor,
+ /**
+ * True if compilation result was success.
+ */
+ internal val successfulCompilation: Boolean,
+) {
+ private val diagnostics = processor.messageWatcher.diagnostics()
+
+ fun diagnosticsOfKind(kind: Diagnostic.Kind) = diagnostics[kind].orEmpty()
+
+ override fun toString(): String {
+ return buildString {
+ appendLine("CompilationResult (with $testRunnerName)")
+ Diagnostic.Kind.values().forEach { kind ->
+ val messages = diagnosticsOfKind(kind)
+ appendLine("${kind.name}: ${messages.size}")
+ messages.forEach {
+ appendLine(it)
+ }
+ appendLine()
+ }
+ }
+ }
+}
+
+/**
+ * Truth subject that can run assertions on the [CompilationResult].
+ * see: [XTestInvocation.assertCompilationResult]
+ */
+class CompilationResultSubject(
+ failureMetadata: FailureMetadata,
+ val compilationResult: CompilationResult,
+) : Subject<CompilationResultSubject, CompilationResult>(
+ failureMetadata, compilationResult
+) {
+ /**
+ * set to true if any assertion on the subject requires it to fail (e.g. looking for errors)
+ */
+ internal var shouldSucceed: Boolean = true
+
+ /**
+ * Asserts that compilation did fail. This covers the cases where the processor won't print
+ * any diagnostics but compilation will still fail (e.g. bad generated code).
+ *
+ * @see hasError
+ */
+ fun compilationDidFail() = chain {
+ shouldSucceed = false
+ }
+
+ /**
+ * Asserts that compilation has a warning with the given text.
+ *
+ * @see hasError
+ */
+ fun hasWarning(expected: String) = chain {
+ hasDiagnosticWithMessage(
+ kind = Diagnostic.Kind.WARNING,
+ expected = expected
+ ) {
+ "expected warning: $expected"
+ }
+ }
+
+ /**
+ * Asserts that compilation has an error with the given text.
+ *
+ * @see hasWarning
+ */
+ fun hasError(expected: String) = chain {
+ shouldSucceed = false
+ hasDiagnosticWithMessage(
+ kind = Diagnostic.Kind.ERROR,
+ expected = expected
+ ) {
+ "expected error: $expected"
+ }
+ }
+
+ /**
+ * Asserts that compilation has at least one diagnostics message with kind error.
+ *
+ * @see compilationDidFail
+ * @see hasWarning
+ */
+ fun hasError() = chain {
+ shouldSucceed = false
+ if (actual().diagnosticsOfKind(Diagnostic.Kind.ERROR).isEmpty()) {
+ failWithActual(
+ simpleFact("expected at least one failure message")
+ )
+ }
+ }
+
+ /**
+ * Called after handler is invoked to check its compilation failure assertion against the
+ * compilation result.
+ */
+ internal fun assertCompilationResult() {
+ if (compilationResult.successfulCompilation != shouldSucceed) {
+ failWithActual(
+ simpleFact(
+ "expected compilation result to be: $shouldSucceed but was " +
+ "${compilationResult.successfulCompilation}"
+ )
+ )
+ }
+ }
+
+ private fun hasDiagnosticWithMessage(
+ kind: Diagnostic.Kind,
+ expected: String,
+ buildErrorMessage: () -> String
+ ) {
+ val diagnostics = compilationResult.diagnosticsOfKind(kind)
+ if (diagnostics.any { it.msg == expected }) {
+ return
+ }
+ failWithActual(simpleFact(buildErrorMessage()))
+ }
+
+ private fun chain(
+ block: () -> Unit
+ ): CompileTester.ChainingClause<CompilationResultSubject> {
+ block()
+ return CompileTester.ChainingClause<CompilationResultSubject> {
+ this
+ }
+ }
+
+ companion object {
+ private val FACTORY =
+ Factory<CompilationResultSubject, CompilationResult> { metadata, actual ->
+ CompilationResultSubject(metadata, actual)
+ }
+
+ fun assertThat(
+ compilationResult: CompilationResult
+ ): CompilationResultSubject {
+ return Truth.assertAbout(FACTORY).that(
+ compilationResult
+ )
+ }
+ }
+}
+
+internal class JavaCompileTestingCompilationResult(
+ testRunner: CompilationTestRunner,
+ @Suppress("unused")
+ private val delegate: Compilation,
+ processor: SyntheticJavacProcessor
+) : CompilationResult(
+ testRunnerName = testRunner.name,
+ processor = processor,
+ successfulCompilation = delegate.status() == Compilation.Status.SUCCESS
+)
+
+internal class KotlinCompileTestingCompilationResult(
+ testRunner: CompilationTestRunner,
+ @Suppress("unused")
+ private val delegate: KotlinCompilation.Result,
+ processor: SyntheticProcessor,
+ successfulCompilation: Boolean
+) : CompilationResult(
+ testRunnerName = testRunner.name,
+ processor = processor,
+ successfulCompilation = successfulCompilation
+)
\ No newline at end of file
diff --git a/room/compiler-processing-testing/src/main/java/androidx/room/compiler/processing/util/DiagnosticMessage.kt b/room/compiler-processing-testing/src/main/java/androidx/room/compiler/processing/util/DiagnosticMessage.kt
new file mode 100644
index 0000000..34ef8e3
--- /dev/null
+++ b/room/compiler-processing-testing/src/main/java/androidx/room/compiler/processing/util/DiagnosticMessage.kt
@@ -0,0 +1,27 @@
+/*
+ * Copyright 2020 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 androidx.room.compiler.processing.XElement
+
+/**
+ * Holder for diagnostics messages
+ */
+data class DiagnosticMessage(
+ val msg: String,
+ val element: XElement?
+)
\ 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 076b531..bbf2888 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
@@ -16,275 +16,147 @@
package androidx.room.compiler.processing.util
-import androidx.room.compiler.processing.SyntheticJavacProcessor
-import androidx.room.compiler.processing.SyntheticKspProcessor
-import com.google.common.truth.Truth
+import androidx.room.compiler.processing.util.runner.CompilationTestRunner
+import androidx.room.compiler.processing.util.runner.JavacCompilationTestRunner
+import androidx.room.compiler.processing.util.runner.KaptCompilationTestRunner
+import androidx.room.compiler.processing.util.runner.KspCompilationTestRunner
+import androidx.room.compiler.processing.util.runner.TestCompilationParameters
import com.google.common.truth.Truth.assertThat
-import com.google.testing.compile.CompileTester
-import com.google.testing.compile.JavaSourcesSubjectFactory
+import com.google.common.truth.Truth.assertWithMessage
import com.tschuchort.compiletesting.KotlinCompilation
-import com.tschuchort.compiletesting.SourceFile
-import com.tschuchort.compiletesting.kspSourcesDir
-import com.tschuchort.compiletesting.symbolProcessors
import java.io.File
-// TODO get rid of these once kotlin compile testing supports two step compilation for KSP.
-// https://github.com/tschuchortdev/kotlin-compile-testing/issues/72
-private val KotlinCompilation.kspJavaSourceDir: File
- get() = kspSourcesDir.resolve("java")
+private fun runTests(
+ params: TestCompilationParameters,
+ vararg runners: CompilationTestRunner
+) {
+ val runCount = runners.count { runner ->
+ if (runner.canRun(params)) {
+ val compilationResult = runner.compile(params)
+ val subject = CompilationResultSubject.assertThat(compilationResult)
+ // if any assertion failed, throw first those.
+ compilationResult.processor.throwIfFailed()
-private val KotlinCompilation.kspKotlinSourceDir: File
- get() = kspSourcesDir.resolve("kotlin")
+ compilationResult.processor.invocationInstances.forEach {
+ it.runPostCompilationChecks(subject)
+ }
+ assertWithMessage(
+ "compilation should've run the processor callback at least once"
+ ).that(
+ compilationResult.processor.invocationInstances
+ ).isNotEmpty()
-private fun compileSources(
- sources: List<Source>,
- classpath: List<File>,
+ subject.assertCompilationResult()
+ true
+ } else {
+ false
+ }
+ }
+ // make sure some tests did run
+ assertThat(runCount).isGreaterThan(0)
+}
+
+fun runProcessorTestWithoutKsp(
+ sources: List<Source> = emptyList(),
+ classpath: List<File> = emptyList(),
handler: (XTestInvocation) -> Unit
-): Pair<SyntheticJavacProcessor, CompileTester> {
- val syntheticJavacProcessor = SyntheticJavacProcessor(handler)
- return syntheticJavacProcessor to Truth.assertAbout(
- JavaSourcesSubjectFactory.javaSources()
- ).that(
- sources.map {
- it.toJFO()
- }
- ).apply {
- if (classpath.isNotEmpty()) {
- withClasspath(classpath)
- }
- }.processedWith(
- syntheticJavacProcessor
+) {
+ runTests(
+ params = TestCompilationParameters(
+ sources = sources,
+ classpath = classpath,
+ handler = handler
+ ),
+ JavacCompilationTestRunner,
+ KaptCompilationTestRunner
)
}
-private fun compileWithKapt(
- sources: List<Source>,
- classpath: List<File>,
- handler: (XTestInvocation) -> Unit
-): Pair<SyntheticJavacProcessor, KotlinCompilation> {
- val syntheticJavacProcessor = SyntheticJavacProcessor(handler)
- val compilation = KotlinCompilation()
- sources.forEach {
- compilation.workingDir.resolve("sources")
- .resolve(it.relativePath())
- .parentFile
- .mkdirs()
- }
- compilation.sources = sources.map {
- it.toKotlinSourceFile()
- }
- compilation.annotationProcessors = listOf(syntheticJavacProcessor)
- compilation.inheritClassPath = true
- compilation.verbose = false
- compilation.classpaths += classpath
-
- return syntheticJavacProcessor to compilation
-}
-
-private fun compileWithKsp(
- sources: List<Source>,
- classpath: List<File>,
- handler: (XTestInvocation) -> Unit
-): Pair<SyntheticKspProcessor, KotlinCompilation.Result> {
- @Suppress("NAME_SHADOWING")
- val sources = if (sources.none { it is Source.KotlinSource }) {
- // looks like this requires a kotlin source file
- // see: https://github.com/tschuchortdev/kotlin-compile-testing/issues/57
- sources + Source.kotlin("placeholder.kt", "")
- } else {
- sources
- }
- val syntheticKspProcessor = SyntheticKspProcessor(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 += classpath
- return compilation
- }
-
- val kspCompilation = prepareCompilation()
- kspCompilation.symbolProcessors = listOf(syntheticKspProcessor)
- kspCompilation.compile()
- // ignore KSP result for now because KSP stops compilation, which might create false negatives
- // when java code accesses kotlin code.
- // TODO: fix once https://github.com/tschuchortdev/kotlin-compile-testing/issues/72 is fixed
-
- // after ksp, compile without ksp with KSP's output as input
- val finalCompilation = prepareCompilation()
- // build source files from generated code
- finalCompilation.sources += kspCompilation.kspJavaSourceDir.collectSourceFiles() +
- kspCompilation.kspKotlinSourceDir.collectSourceFiles()
- return syntheticKspProcessor to finalCompilation.compile()
-}
-
-private fun File.collectSourceFiles(): List<SourceFile> {
- return walkTopDown().filter {
- it.isFile
- }.map { file ->
- SourceFile.fromPath(file)
- }.toList()
-}
-
+/**
+ * Runs the compilation test with all 3 backends (javac, kapt, ksp) if possible (e.g. javac
+ * cannot test kotlin sources).
+ *
+ * The [handler] will be invoked for each compilation hence it should be repeatable.
+ *
+ * To assert on the compilation results, [handler] can call
+ * [XTestInvocation.assertCompilationResult] where it will receive a subject for post compilation
+ * assertions.
+ *
+ * By default, the compilation is expected to succeed. If it should fail, there must be an
+ * assertion on [XTestInvocation.assertCompilationResult] which expects a failure (e.g. checking
+ * errors).
+ */
fun runProcessorTest(
sources: List<Source> = emptyList(),
classpath: List<File> = emptyList(),
handler: (XTestInvocation) -> Unit
) {
- @Suppress("NAME_SHADOWING")
- val sources = if (sources.isEmpty()) {
- // synthesize a source to trigger compilation
- listOf(
- Source.java(
- "foo.bar.SyntheticSource",
- """
- package foo.bar;
- public class SyntheticSource {}
- """.trimIndent()
- )
- )
- } else {
- sources
- }
- // we can compile w/ javac only if all code is in java
- if (sources.canCompileWithJava()) {
- runJavaProcessorTest(
+ runTests(
+ params = TestCompilationParameters(
sources = sources,
classpath = classpath,
- handler = handler,
- succeed = true
- )
- }
- runKaptTest(
- sources = sources,
- classpath = classpath,
- handler = handler,
- succeed = true
+ handler = handler
+ ),
+ JavacCompilationTestRunner,
+ KaptCompilationTestRunner,
+ KspCompilationTestRunner
)
}
/**
- * This method is oddly named instead of being an overload on runProcessorTest to easily track
- * which tests started to support KSP.
+ * Runs the test only with javac compilation backend.
*
- * Eventually, it will be merged with runProcessorTest when all tests pass with KSP.
+ * @see runProcessorTest
*/
-fun runProcessorTestIncludingKsp(
- sources: List<Source> = emptyList(),
- classpath: List<File> = emptyList(),
- handler: (XTestInvocation) -> Unit
-) {
- runProcessorTest(
- sources = sources,
- classpath = classpath,
- handler = handler
- )
- runKspTest(
- sources = sources,
- classpath = classpath,
- succeed = true,
- handler = handler
- )
-}
-
-fun runProcessorTestForFailedCompilation(
- sources: List<Source>,
- classpath: List<File> = emptyList(),
- handler: (XTestInvocation) -> Unit
-) {
- if (sources.canCompileWithJava()) {
- // run with java processor
- runJavaProcessorTest(
- sources = sources,
- classpath = classpath,
- handler = handler,
- succeed = false
- )
- }
- // now run with kapt
- runKaptTest(
- sources = sources,
- classpath = classpath,
- handler = handler,
- succeed = false
- )
-}
-
-fun runProcessorTestForFailedCompilationIncludingKsp(
- sources: List<Source>,
- classpath: List<File>,
- handler: (XTestInvocation) -> Unit
-) {
- runProcessorTestForFailedCompilation(
- sources = sources,
- classpath = classpath,
- handler = handler
- )
- // now run with ksp
- runKspTest(
- sources = sources,
- classpath = classpath,
- handler = handler,
- succeed = false
- )
-}
-
fun runJavaProcessorTest(
sources: List<Source>,
classpath: List<File>,
- succeed: Boolean,
handler: (XTestInvocation) -> Unit
) {
- val (syntheticJavacProcessor, compileTester) = compileSources(sources, classpath, handler)
- if (succeed) {
- compileTester.compilesWithoutError()
- } else {
- compileTester.failsToCompile()
- }
- syntheticJavacProcessor.throwIfFailed()
+ runTests(
+ params = TestCompilationParameters(
+ sources = sources,
+ classpath = classpath,
+ handler = handler
+ ),
+ JavacCompilationTestRunner
+ )
}
+/**
+ * Runs the test only with kapt compilation backend
+ */
fun runKaptTest(
sources: List<Source>,
classpath: List<File> = emptyList(),
- succeed: Boolean = true,
handler: (XTestInvocation) -> Unit
) {
- // now run with kapt
- val (kaptProcessor, kotlinCompilation) = compileWithKapt(sources, classpath, handler)
- val compilationResult = kotlinCompilation.compile()
- if (succeed) {
- assertThat(compilationResult.exitCode).isEqualTo(KotlinCompilation.ExitCode.OK)
- } else {
- assertThat(compilationResult.exitCode).isNotEqualTo(KotlinCompilation.ExitCode.OK)
- }
- kaptProcessor.throwIfFailed()
+ runTests(
+ params = TestCompilationParameters(
+ sources = sources,
+ classpath = classpath,
+ handler = handler
+ ),
+ KaptCompilationTestRunner
+ )
}
+/**
+ * Runs the test only with ksp compilation backend
+ */
fun runKspTest(
sources: List<Source>,
classpath: List<File> = emptyList(),
- succeed: Boolean = true,
handler: (XTestInvocation) -> Unit
) {
- val (kspProcessor, compilationResult) = compileWithKsp(sources, classpath, handler)
- if (succeed) {
- assertThat(compilationResult.exitCode).isEqualTo(KotlinCompilation.ExitCode.OK)
- } else {
- assertThat(compilationResult.exitCode).isNotEqualTo(KotlinCompilation.ExitCode.OK)
- }
- kspProcessor.throwIfFailed()
+ runTests(
+ params = TestCompilationParameters(
+ sources = sources,
+ classpath = classpath,
+ handler = handler
+ ),
+ KspCompilationTestRunner
+ )
}
/**
@@ -314,5 +186,3 @@
}
return compilation.classesDir
}
-
-private fun List<Source>.canCompileWithJava() = all { it is Source.JavaSource }
diff --git a/room/compiler-processing-testing/src/main/java/androidx/room/compiler/processing/util/RecordingXMessager.kt b/room/compiler-processing-testing/src/main/java/androidx/room/compiler/processing/util/RecordingXMessager.kt
new file mode 100644
index 0000000..c2aa5dc
--- /dev/null
+++ b/room/compiler-processing-testing/src/main/java/androidx/room/compiler/processing/util/RecordingXMessager.kt
@@ -0,0 +1,43 @@
+/*
+ * Copyright 2020 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 androidx.room.compiler.processing.XElement
+import androidx.room.compiler.processing.XMessager
+import javax.tools.Diagnostic
+
+/**
+ * An XMessager implementation that holds onto dispatched diagnostics.
+ */
+class RecordingXMessager : XMessager() {
+ private val diagnostics = mutableMapOf<Diagnostic.Kind, MutableList<DiagnosticMessage>>()
+
+ fun diagnostics(): Map<Diagnostic.Kind, List<DiagnosticMessage>> = diagnostics
+
+ override fun onPrintMessage(kind: Diagnostic.Kind, msg: String, element: XElement?) {
+ diagnostics.getOrPut(
+ kind
+ ) {
+ mutableListOf()
+ }.add(
+ DiagnosticMessage(
+ msg = msg,
+ element = element
+ )
+ )
+ }
+}
\ No newline at end of file
diff --git a/room/compiler-processing-testing/src/main/java/androidx/room/compiler/processing/util/XTestInvocation.kt b/room/compiler-processing-testing/src/main/java/androidx/room/compiler/processing/util/XTestInvocation.kt
index 267c140..d7d0e75 100644
--- a/room/compiler-processing-testing/src/main/java/androidx/room/compiler/processing/util/XTestInvocation.kt
+++ b/room/compiler-processing-testing/src/main/java/androidx/room/compiler/processing/util/XTestInvocation.kt
@@ -17,6 +17,7 @@
package androidx.room.compiler.processing.util
import androidx.room.compiler.processing.XProcessingEnv
+import kotlin.reflect.KClass
/**
* Data holder for XProcessing tests to access the processing environment.
@@ -24,6 +25,48 @@
class XTestInvocation(
val processingEnv: XProcessingEnv,
) {
+ /**
+ * Extension mechanism to allow putting objects into invocation that can be retrieved later.
+ */
+ private val userData = mutableMapOf<KClass<*>, Any>()
+
+ private val postCompilationAssertions = mutableListOf<CompilationResultSubject.() -> Unit>()
val isKsp: Boolean
get() = processingEnv.backend == XProcessingEnv.Backend.KSP
+
+ /**
+ * Registers a block that will be called with a [CompilationResultSubject] when compilation
+ * finishes.
+ *
+ * Note that it is not safe to access the environment in this block.
+ */
+ fun assertCompilationResult(block: CompilationResultSubject.() -> Unit) {
+ postCompilationAssertions.add(block)
+ }
+
+ internal fun runPostCompilationChecks(
+ compilationResultSubject: CompilationResultSubject
+ ) {
+ postCompilationAssertions.forEach {
+ it(compilationResultSubject)
+ }
+ }
+
+ fun <T : Any> getUserData(key: KClass<T>): T? {
+ @Suppress("UNCHECKED_CAST")
+ return userData[key] as T?
+ }
+
+ fun <T : Any> putUserData(key: KClass<T>, value: T) {
+ userData[key] = value
+ }
+
+ fun <T : Any> getOrPutUserData(key: KClass<T>, create: () -> T): T {
+ getUserData(key)?.let {
+ return it
+ }
+ return create().also {
+ putUserData(key, it)
+ }
+ }
}
\ No newline at end of file
diff --git a/room/compiler-processing-testing/src/main/java/androidx/room/compiler/processing/util/runner/CompilationTestRunner.kt b/room/compiler-processing-testing/src/main/java/androidx/room/compiler/processing/util/runner/CompilationTestRunner.kt
new file mode 100644
index 0000000..257e58a
--- /dev/null
+++ b/room/compiler-processing-testing/src/main/java/androidx/room/compiler/processing/util/runner/CompilationTestRunner.kt
@@ -0,0 +1,40 @@
+/*
+ * Copyright 2020 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.runner
+
+import androidx.room.compiler.processing.util.CompilationResult
+import androidx.room.compiler.processing.util.Source
+import androidx.room.compiler.processing.util.XTestInvocation
+import java.io.File
+
+/**
+ * Common interface for compilation tests
+ */
+internal interface CompilationTestRunner {
+ // user visible name that we can print in assertions
+ val name: String
+
+ fun canRun(params: TestCompilationParameters): Boolean
+
+ fun compile(params: TestCompilationParameters): CompilationResult
+}
+
+internal data class TestCompilationParameters(
+ val sources: List<Source> = emptyList(),
+ val classpath: List<File> = emptyList(),
+ val handler: (XTestInvocation) -> Unit
+)
diff --git a/room/compiler-processing-testing/src/main/java/androidx/room/compiler/processing/util/runner/JavacCompilationTestRunner.kt b/room/compiler-processing-testing/src/main/java/androidx/room/compiler/processing/util/runner/JavacCompilationTestRunner.kt
new file mode 100644
index 0000000..5fdba61
--- /dev/null
+++ b/room/compiler-processing-testing/src/main/java/androidx/room/compiler/processing/util/runner/JavacCompilationTestRunner.kt
@@ -0,0 +1,70 @@
+/*
+ * Copyright 2020 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.runner
+
+import androidx.room.compiler.processing.SyntheticJavacProcessor
+import androidx.room.compiler.processing.util.CompilationResult
+import androidx.room.compiler.processing.util.JavaCompileTestingCompilationResult
+import androidx.room.compiler.processing.util.Source
+import com.google.testing.compile.Compiler
+
+internal object JavacCompilationTestRunner : CompilationTestRunner {
+
+ override val name: String = "javac"
+
+ override fun canRun(params: TestCompilationParameters): Boolean {
+ return params.sources.all { it is Source.JavaSource }
+ }
+
+ override fun compile(params: TestCompilationParameters): CompilationResult {
+ val syntheticJavacProcessor = SyntheticJavacProcessor(params.handler)
+ val sources = if (params.sources.isEmpty()) {
+ // synthesize a source to trigger compilation
+ listOf(
+ Source.java(
+ qName = "foo.bar.SyntheticSource",
+ code = """
+ package foo.bar;
+ public class SyntheticSource {}
+ """.trimIndent()
+ )
+ )
+ } else {
+ params.sources
+ }
+ val compiler = Compiler
+ .javac()
+ .withProcessors(syntheticJavacProcessor)
+ .withOptions("-Xlint")
+ .let {
+ if (params.classpath.isNotEmpty()) {
+ it.withClasspath(params.classpath)
+ } else {
+ it
+ }
+ }
+ val javaFileObjects = sources.map {
+ it.toJFO()
+ }
+ val compilation = compiler.compile(javaFileObjects)
+ return JavaCompileTestingCompilationResult(
+ testRunner = this,
+ delegate = compilation,
+ processor = syntheticJavacProcessor
+ )
+ }
+}
\ No newline at end of file
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
new file mode 100644
index 0000000..e6cb5ee
--- /dev/null
+++ b/room/compiler-processing-testing/src/main/java/androidx/room/compiler/processing/util/runner/KaptCompilationTestRunner.kt
@@ -0,0 +1,57 @@
+/*
+ * Copyright 2020 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.runner
+
+import androidx.room.compiler.processing.SyntheticJavacProcessor
+import androidx.room.compiler.processing.util.CompilationResult
+import androidx.room.compiler.processing.util.KotlinCompileTestingCompilationResult
+import com.tschuchort.compiletesting.KotlinCompilation
+
+internal object KaptCompilationTestRunner : CompilationTestRunner {
+
+ override val name: String = "kapt"
+
+ override fun canRun(params: TestCompilationParameters): Boolean {
+ return true
+ }
+
+ 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.annotationProcessors = listOf(syntheticJavacProcessor)
+ compilation.inheritClassPath = true
+ compilation.verbose = false
+ compilation.classpaths += params.classpath
+
+ val result = compilation.compile()
+ return KotlinCompileTestingCompilationResult(
+ testRunner = this,
+ delegate = result,
+ processor = syntheticJavacProcessor,
+ successfulCompilation = result.exitCode == KotlinCompilation.ExitCode.OK
+ )
+ }
+}
\ No newline at end of file
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
new file mode 100644
index 0000000..8ac5ed3
--- /dev/null
+++ b/room/compiler-processing-testing/src/main/java/androidx/room/compiler/processing/util/runner/KspCompilationTestRunner.kt
@@ -0,0 +1,110 @@
+/*
+ * Copyright 2020 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.runner
+
+import androidx.room.compiler.processing.SyntheticKspProcessor
+import androidx.room.compiler.processing.util.CompilationResult
+import androidx.room.compiler.processing.util.KotlinCompileTestingCompilationResult
+import androidx.room.compiler.processing.util.Source
+import com.tschuchort.compiletesting.KotlinCompilation
+import com.tschuchort.compiletesting.SourceFile
+import com.tschuchort.compiletesting.kspSourcesDir
+import com.tschuchort.compiletesting.symbolProcessors
+import java.io.File
+import javax.tools.Diagnostic
+
+internal object KspCompilationTestRunner : CompilationTestRunner {
+
+ override val name: String = "ksp"
+
+ override fun canRun(params: TestCompilationParameters): Boolean {
+ return true
+ }
+
+ override fun compile(params: TestCompilationParameters): CompilationResult {
+ @Suppress("NAME_SHADOWING")
+ val sources = if (params.sources.none { it is Source.KotlinSource }) {
+ // looks like this requires a kotlin source file
+ // see: https://github.com/tschuchortdev/kotlin-compile-testing/issues/57
+ params.sources + Source.kotlin("placeholder.kt", "")
+ } else {
+ 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()
+ kspCompilation.symbolProcessors = listOf(syntheticKspProcessor)
+ kspCompilation.compile()
+ // ignore KSP result for now because KSP stops compilation, which might create false
+ // negatives when java code accesses kotlin code.
+ // TODO: fix once https://github.com/tschuchortdev/kotlin-compile-testing/issues/72 is
+ // fixed
+
+ // after ksp, compile without ksp with KSP's output as input
+ val finalCompilation = prepareCompilation()
+ // build source files from generated code
+ finalCompilation.sources += kspCompilation.kspJavaSourceDir.collectSourceFiles() +
+ kspCompilation.kspKotlinSourceDir.collectSourceFiles()
+ val result = finalCompilation.compile()
+ // workaround for: https://github.com/google/ksp/issues/122
+ // KSP does not fail compilation for error diagnostics hence we do it here.
+ val hasErrorDiagnostics = syntheticKspProcessor.messageWatcher
+ .diagnostics()[Diagnostic.Kind.ERROR].orEmpty().isNotEmpty()
+ return KotlinCompileTestingCompilationResult(
+ testRunner = this,
+ delegate = result,
+ processor = syntheticKspProcessor,
+ successfulCompilation = result.exitCode == KotlinCompilation.ExitCode.OK &&
+ !hasErrorDiagnostics
+
+ )
+ }
+
+ // TODO get rid of these once kotlin compile testing supports two step compilation for KSP.
+ // https://github.com/tschuchortdev/kotlin-compile-testing/issues/72
+ private val KotlinCompilation.kspJavaSourceDir: File
+ get() = kspSourcesDir.resolve("java")
+
+ private val KotlinCompilation.kspKotlinSourceDir: File
+ get() = kspSourcesDir.resolve("kotlin")
+
+ private fun File.collectSourceFiles(): List<SourceFile> {
+ return walkTopDown().filter {
+ it.isFile
+ }.map { file ->
+ SourceFile.fromPath(file)
+ }.toList()
+ }
+}
\ No newline at end of file
diff --git a/room/compiler-processing-testing/src/test/java/androidx/room/compiler/processing/util/TestRunnerTest.kt b/room/compiler-processing-testing/src/test/java/androidx/room/compiler/processing/util/TestRunnerTest.kt
new file mode 100644
index 0000000..59dd47f7
--- /dev/null
+++ b/room/compiler-processing-testing/src/test/java/androidx/room/compiler/processing/util/TestRunnerTest.kt
@@ -0,0 +1,72 @@
+/*
+ * Copyright 2020 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.squareup.javapoet.CodeBlock
+import com.squareup.javapoet.JavaFile
+import com.squareup.javapoet.TypeSpec
+import org.junit.Test
+import javax.tools.Diagnostic
+
+class TestRunnerTest {
+ @Test
+ fun generatedBadCode_expected() = generatedBadCode(assertFailure = true)
+
+ @Test(expected = AssertionError::class)
+ fun generatedBadCode_unexpected() = generatedBadCode(assertFailure = false)
+
+ private fun generatedBadCode(assertFailure: Boolean) {
+ runProcessorTest {
+ if (it.processingEnv.findTypeElement("foo.Foo") == null) {
+ val badCode = TypeSpec.classBuilder("Foo").apply {
+ addStaticBlock(
+ CodeBlock.of("bad code")
+ )
+ }.build()
+ val badGeneratedFile = JavaFile.builder("foo", badCode).build()
+ it.processingEnv.filer.write(
+ badGeneratedFile
+ )
+ }
+ if (assertFailure) {
+ it.assertCompilationResult {
+ compilationDidFail()
+ }
+ }
+ }
+ }
+
+ @Test
+ fun reportedError_expected() = reportedError(assertFailure = true)
+
+ @Test(expected = AssertionError::class)
+ fun reportedError_unexpected() = reportedError(assertFailure = false)
+
+ fun reportedError(assertFailure: Boolean) {
+ runProcessorTest {
+ it.processingEnv.messager.printMessage(
+ kind = Diagnostic.Kind.ERROR,
+ msg = "reported error"
+ )
+ if (assertFailure) {
+ it.assertCompilationResult {
+ hasError("reported error")
+ }
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/room/compiler-processing/build.gradle b/room/compiler-processing/build.gradle
index 795a691..b15e171 100644
--- a/room/compiler-processing/build.gradle
+++ b/room/compiler-processing/build.gradle
@@ -26,12 +26,13 @@
}
dependencies {
+ api(KOTLIN_STDLIB)
+ api(JAVAPOET)
implementation("androidx.annotation:annotation:1.1.0")
implementation(GUAVA)
- implementation(KOTLIN_STDLIB)
implementation(AUTO_COMMON)
implementation(AUTO_VALUE_ANNOTATIONS)
- implementation(JAVAPOET)
+
implementation(KOTLIN_METADATA_JVM)
implementation(INTELLIJ_ANNOTATIONS)
implementation(KOTLIN_KSP_API) {
diff --git a/room/compiler-processing/src/main/java/androidx/room/compiler/processing/XMessager.kt b/room/compiler-processing/src/main/java/androidx/room/compiler/processing/XMessager.kt
index 0701c52..29ff818 100644
--- a/room/compiler-processing/src/main/java/androidx/room/compiler/processing/XMessager.kt
+++ b/room/compiler-processing/src/main/java/androidx/room/compiler/processing/XMessager.kt
@@ -21,7 +21,8 @@
/**
* Logging interface for the processor
*/
-interface XMessager {
+abstract class XMessager {
+ private val watchers = mutableListOf<XMessager>()
/**
* Prints the given [msg] to the logs while also associating it with the given [element].
*
@@ -29,5 +30,20 @@
* @param msg The actual message to report to the compiler
* @param element The element with whom the message should be associated with
*/
- fun printMessage(kind: Diagnostic.Kind, msg: String, element: XElement? = null)
+ final fun printMessage(kind: Diagnostic.Kind, msg: String, element: XElement? = null) {
+ watchers.forEach {
+ it.printMessage(kind, msg, element)
+ }
+ onPrintMessage(kind, msg, element)
+ }
+
+ abstract fun onPrintMessage(kind: Diagnostic.Kind, msg: String, element: XElement? = null)
+
+ fun addMessageWatcher(watcher: XMessager) {
+ watchers.add(watcher)
+ }
+
+ fun removeMessageWatcher(watcher: XMessager) {
+ watchers.remove(watcher)
+ }
}
diff --git a/room/compiler-processing/src/main/java/androidx/room/compiler/processing/javac/JavacProcessingEnvMessager.kt b/room/compiler-processing/src/main/java/androidx/room/compiler/processing/javac/JavacProcessingEnvMessager.kt
index f5120fa..e49a5f7 100644
--- a/room/compiler-processing/src/main/java/androidx/room/compiler/processing/javac/JavacProcessingEnvMessager.kt
+++ b/room/compiler-processing/src/main/java/androidx/room/compiler/processing/javac/JavacProcessingEnvMessager.kt
@@ -27,8 +27,8 @@
internal class JavacProcessingEnvMessager(
private val processingEnv: ProcessingEnvironment
-) : XMessager {
- override fun printMessage(kind: Diagnostic.Kind, msg: String, element: XElement?) {
+) : XMessager() {
+ override fun onPrintMessage(kind: Diagnostic.Kind, msg: String, element: XElement?) {
val javacElement = (element as? JavacElement)?.element
processingEnv.messager.printMessage(
kind,
diff --git a/room/compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/KspMessager.kt b/room/compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/KspMessager.kt
index 557cfa3..1497d90 100644
--- a/room/compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/KspMessager.kt
+++ b/room/compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/KspMessager.kt
@@ -23,8 +23,8 @@
internal class KspMessager(
private val logger: KSPLogger
-) : XMessager {
- override fun printMessage(kind: Diagnostic.Kind, msg: String, element: XElement?) {
+) : XMessager() {
+ override fun onPrintMessage(kind: Diagnostic.Kind, msg: String, element: XElement?) {
val ksNode = (element as? KspElement)?.declaration
when (kind) {
Diagnostic.Kind.ERROR -> logger.error(msg, ksNode)
diff --git a/room/compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/KspTypeElement.kt b/room/compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/KspTypeElement.kt
index 60339a5..22993b2 100644
--- a/room/compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/KspTypeElement.kt
+++ b/room/compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/KspTypeElement.kt
@@ -317,4 +317,8 @@
.filter {
it.simpleName == this.simpleName
}
+
+ override fun toString(): String {
+ return declaration.toString()
+ }
}
diff --git a/room/compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/KspTypeMapper.kt b/room/compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/KspTypeMapper.kt
index 734f3b1..06a1983 100644
--- a/room/compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/KspTypeMapper.kt
+++ b/room/compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/KspTypeMapper.kt
@@ -75,7 +75,7 @@
mapping["java.lang.Boolean"] = "kotlin.Boolean"
// collections. default to mutable ones since java types are always mutable
mapping["java.util.Iterator"] = "kotlin.collections.MutableIterator"
- mapping["java.util.Iterable"] = "kotlin.collections.Iterable"
+ mapping["java.lang.Iterable"] = "kotlin.collections.Iterable"
mapping["java.util.Collection"] = "kotlin.collections.MutableCollection"
mapping["java.util.Set"] = "kotlin.collections.MutableSet"
mapping["java.util.List"] = "kotlin.collections.MutableList"
diff --git a/room/compiler-processing/src/test/java/androidx/room/compiler/processing/MethodSpecHelperTest.kt b/room/compiler-processing/src/test/java/androidx/room/compiler/processing/MethodSpecHelperTest.kt
index 49ad742..b31aa76 100644
--- a/room/compiler-processing/src/test/java/androidx/room/compiler/processing/MethodSpecHelperTest.kt
+++ b/room/compiler-processing/src/test/java/androidx/room/compiler/processing/MethodSpecHelperTest.kt
@@ -22,7 +22,7 @@
import androidx.room.compiler.processing.util.XTestInvocation
import androidx.room.compiler.processing.util.javaTypeUtils
import androidx.room.compiler.processing.util.runKaptTest
-import androidx.room.compiler.processing.util.runProcessorTestIncludingKsp
+import androidx.room.compiler.processing.util.runProcessorTest
import com.google.auto.common.MoreTypes
import com.google.common.truth.Truth.assertThat
import com.squareup.javapoet.MethodSpec
@@ -291,7 +291,7 @@
private fun overridesCheck(source: Source, ignoreInheritedMethods: Boolean = false) {
// first build golden image with Java processor so we can use JavaPoet's API
val golden = buildMethodsViaJavaPoet(source, ignoreInheritedMethods)
- runProcessorTestIncludingKsp(
+ runProcessorTest(
sources = listOf(source)
) { invocation ->
val (target, methods) = invocation.getOverrideTestTargets(ignoreInheritedMethods)
@@ -316,8 +316,7 @@
): List<String> {
lateinit var result: List<String>
runKaptTest(
- sources = listOf(source),
- succeed = true
+ sources = listOf(source)
) { invocation ->
val (target, methods) = invocation.getOverrideTestTargets(
ignoreInheritedMethods
diff --git a/room/compiler-processing/src/test/java/androidx/room/compiler/processing/XAnnotationBoxTest.kt b/room/compiler-processing/src/test/java/androidx/room/compiler/processing/XAnnotationBoxTest.kt
index 45f8aad..40cab24 100644
--- a/room/compiler-processing/src/test/java/androidx/room/compiler/processing/XAnnotationBoxTest.kt
+++ b/room/compiler-processing/src/test/java/androidx/room/compiler/processing/XAnnotationBoxTest.kt
@@ -25,7 +25,7 @@
import androidx.room.compiler.processing.util.getMethod
import androidx.room.compiler.processing.util.getParameter
import androidx.room.compiler.processing.util.runProcessorTest
-import androidx.room.compiler.processing.util.runProcessorTestIncludingKsp
+import androidx.room.compiler.processing.util.runProcessorTestWithoutKsp
import androidx.room.compiler.processing.util.typeName
import com.google.common.truth.Truth.assertThat
import com.google.common.truth.Truth.assertWithMessage
@@ -48,7 +48,6 @@
}
""".trimIndent()
)
- // TODO add KSP once https://github.com/google/ksp/issues/96 is fixed.
runProcessorTest(
sources = listOf(source)
) {
@@ -87,7 +86,8 @@
}
""".trimIndent()
)
- runProcessorTest(
+ // re-enable after fixing b/175144186
+ runProcessorTestWithoutKsp(
listOf(mySource)
) {
val element = it.processingEnv.requireTypeElement("foo.bar.Baz")
@@ -129,7 +129,7 @@
}
""".trimIndent()
)
- runProcessorTestIncludingKsp(
+ runProcessorTest(
sources = listOf(source)
) {
val element = it.processingEnv.requireTypeElement("Subject")
@@ -169,7 +169,7 @@
}
""".trimIndent()
)
- runProcessorTestIncludingKsp(
+ runProcessorTest(
listOf(mySource)
) { invocation ->
val element = invocation.processingEnv.requireTypeElement("Subject")
@@ -229,7 +229,7 @@
}
""".trimIndent()
)
- runProcessorTestIncludingKsp(sources = listOf(src)) { invocation ->
+ runProcessorTest(sources = listOf(src)) { invocation ->
val subject = invocation.processingEnv.requireTypeElement("Subject")
subject.getField("prop1").assertHasSuppressWithValue("onProp1")
@@ -280,7 +280,7 @@
}
""".trimIndent()
)
- runProcessorTestIncludingKsp(sources = listOf(src)) { invocation ->
+ runProcessorTest(sources = listOf(src)) { invocation ->
val subject = invocation.processingEnv.requireTypeElement("Subject")
subject.getMethod("noAnnotations").let { method ->
method.assertDoesNotHaveAnnotation()
@@ -309,7 +309,7 @@
)
""".trimIndent()
)
- runProcessorTestIncludingKsp(sources = listOf(src)) { invocation ->
+ runProcessorTest(sources = listOf(src)) { invocation ->
val subject = invocation.processingEnv.requireTypeElement("Subject")
subject.assertHasSuppressWithValue("onClass")
val constructor = subject.getConstructors().single()
@@ -338,7 +338,7 @@
class JavaClass {}
""".trimIndent()
)
- runProcessorTestIncludingKsp(sources = listOf(kotlinSrc, javaSrc)) { invocation ->
+ runProcessorTest(sources = listOf(kotlinSrc, javaSrc)) { invocation ->
listOf("KotlinClass", "JavaClass")
.map {
invocation.processingEnv.requireTypeElement(it)
diff --git a/room/compiler-processing/src/test/java/androidx/room/compiler/processing/XArrayTypeTest.kt b/room/compiler-processing/src/test/java/androidx/room/compiler/processing/XArrayTypeTest.kt
index 1f3260d..66b4de0 100644
--- a/room/compiler-processing/src/test/java/androidx/room/compiler/processing/XArrayTypeTest.kt
+++ b/room/compiler-processing/src/test/java/androidx/room/compiler/processing/XArrayTypeTest.kt
@@ -23,7 +23,6 @@
import androidx.room.compiler.processing.util.kspResolver
import androidx.room.compiler.processing.util.runKspTest
import androidx.room.compiler.processing.util.runProcessorTest
-import androidx.room.compiler.processing.util.runProcessorTestIncludingKsp
import androidx.room.compiler.processing.util.typeName
import com.google.common.truth.Truth.assertThat
import com.google.common.truth.Truth.assertWithMessage
@@ -43,7 +42,7 @@
}
""".trimIndent()
)
- runProcessorTestIncludingKsp(
+ runProcessorTest(
sources = listOf(source)
) { invocation ->
val type = invocation.processingEnv
@@ -63,7 +62,7 @@
@Test
fun synthetic() {
- runProcessorTestIncludingKsp {
+ runProcessorTest {
val objArray = it.processingEnv.getArrayType(
TypeName.OBJECT
)
@@ -89,7 +88,7 @@
}
""".trimIndent()
)
- runProcessorTestIncludingKsp(
+ runProcessorTest(
sources = listOf(source)
) { invocation ->
val element = invocation.processingEnv.requireTypeElement("foo.bar.Baz")
@@ -140,7 +139,7 @@
}
""".trimIndent()
)
- runProcessorTestIncludingKsp(listOf(src)) {
+ runProcessorTest(listOf(src)) {
val subject = it.processingEnv.requireTypeElement("Subject")
val types = subject.getAllFieldsIncludingPrivateSupers().map {
assertWithMessage(it.name).that(it.type.isArray()).isTrue()
@@ -170,8 +169,7 @@
@Test
fun createArray() {
runKspTest(
- sources = emptyList(),
- succeed = true
+ sources = emptyList()
) { invocation ->
val intType = invocation.processingEnv.requireType("kotlin.Int")
invocation.processingEnv.getArrayType(intType).let {
diff --git a/room/compiler-processing/src/test/java/androidx/room/compiler/processing/XElementTest.kt b/room/compiler-processing/src/test/java/androidx/room/compiler/processing/XElementTest.kt
index d84af6e..84623ee 100644
--- a/room/compiler-processing/src/test/java/androidx/room/compiler/processing/XElementTest.kt
+++ b/room/compiler-processing/src/test/java/androidx/room/compiler/processing/XElementTest.kt
@@ -22,8 +22,8 @@
import androidx.room.compiler.processing.util.getField
import androidx.room.compiler.processing.util.getMethod
import androidx.room.compiler.processing.util.getParameter
+import androidx.room.compiler.processing.util.runProcessorTestWithoutKsp
import androidx.room.compiler.processing.util.runProcessorTest
-import androidx.room.compiler.processing.util.runProcessorTestIncludingKsp
import com.google.common.truth.Truth.assertThat
import com.squareup.javapoet.ClassName
import com.squareup.javapoet.TypeName
@@ -36,7 +36,7 @@
class XElementTest {
@Test
fun modifiers() {
- runProcessorTestIncludingKsp(
+ runProcessorTest(
listOf(
Source.java(
"foo.bar.Baz",
@@ -146,7 +146,7 @@
}
""".trimIndent()
)
- runProcessorTestIncludingKsp(
+ runProcessorTest(
listOf(genericBase, boundedChild)
) {
fun validateElement(element: XTypeElement, tTypeName: TypeName, rTypeName: TypeName) {
@@ -210,7 +210,7 @@
}
""".trimIndent()
)
- runProcessorTestIncludingKsp(
+ runProcessorTest(
listOf(source)
) {
val element = it.processingEnv.requireTypeElement("foo.bar.Baz")
@@ -257,7 +257,7 @@
}
""".trimIndent()
)
- runProcessorTestIncludingKsp(
+ runProcessorTest(
listOf(source)
) {
val element = it.processingEnv.requireTypeElement("java.lang.Object")
@@ -280,7 +280,7 @@
}
""".trimIndent()
)
- runProcessorTestIncludingKsp(
+ runProcessorTest(
sources = listOf(subject)
) {
val inner = ClassName.get("foo.bar", "Baz.Inner")
@@ -317,7 +317,7 @@
}
""".trimIndent()
)
- runProcessorTestIncludingKsp(
+ runProcessorTest(
listOf(source)
) {
val element = it.processingEnv.requireTypeElement("foo.bar.Baz")
@@ -350,7 +350,8 @@
}
""".trimIndent()
)
- runProcessorTest(
+ // enable once https://github.com/google/ksp/issues/167 is fixed
+ runProcessorTestWithoutKsp(
sources = listOf(source)
) {
val element = it.processingEnv.requireTypeElement("foo.bar.Baz")
@@ -371,9 +372,14 @@
@Test
fun toStringMatchesUnderlyingElement() {
- runProcessorTest {
- it.processingEnv.findTypeElement("java.util.List").let { list ->
- assertThat(list.toString()).isEqualTo("java.util.List")
+ runProcessorTest { invocation ->
+ invocation.processingEnv.findTypeElement("java.util.List").let { list ->
+ val expected = if (invocation.isKsp) {
+ "MutableList"
+ } else {
+ "java.util.List"
+ }
+ assertThat(list.toString()).isEqualTo(expected)
}
}
}
diff --git a/room/compiler-processing/src/test/java/androidx/room/compiler/processing/XExecutableElementTest.kt b/room/compiler-processing/src/test/java/androidx/room/compiler/processing/XExecutableElementTest.kt
index a270b74..d4c82e9 100644
--- a/room/compiler-processing/src/test/java/androidx/room/compiler/processing/XExecutableElementTest.kt
+++ b/room/compiler-processing/src/test/java/androidx/room/compiler/processing/XExecutableElementTest.kt
@@ -23,7 +23,7 @@
import androidx.room.compiler.processing.util.getDeclaredMethod
import androidx.room.compiler.processing.util.getMethod
import androidx.room.compiler.processing.util.getParameter
-import androidx.room.compiler.processing.util.runProcessorTestIncludingKsp
+import androidx.room.compiler.processing.util.runProcessorTest
import androidx.room.compiler.processing.util.typeName
import com.google.common.truth.Truth
import com.google.common.truth.Truth.assertThat
@@ -38,7 +38,7 @@
class XExecutableElementTest {
@Test
fun basic() {
- runProcessorTestIncludingKsp(
+ runProcessorTest(
sources = listOf(
Source.java(
"foo.bar.Baz",
@@ -89,7 +89,7 @@
}
""".trimIndent()
)
- runProcessorTestIncludingKsp(
+ runProcessorTest(
sources = listOf(subject)
) {
val element = it.processingEnv.requireTypeElement("foo.bar.Baz")
@@ -108,7 +108,7 @@
}
""".trimIndent()
)
- runProcessorTestIncludingKsp(
+ runProcessorTest(
sources = listOf(subject)
) {
val element = it.processingEnv.requireTypeElement("Subject")
@@ -138,7 +138,7 @@
}
""".trimIndent()
)
- runProcessorTestIncludingKsp(
+ runProcessorTest(
sources = listOf(subject)
) {
val element = it.processingEnv.requireTypeElement("foo.bar.Baz")
@@ -182,7 +182,7 @@
}
""".trimIndent()
)
- runProcessorTestIncludingKsp(
+ runProcessorTest(
sources = listOf(src)
) { invocation ->
val subject = invocation.processingEnv.requireTypeElement("Subject")
@@ -269,7 +269,7 @@
}
""".trimIndent()
)
- runProcessorTestIncludingKsp(sources = listOf(src)) { invocation ->
+ runProcessorTest(sources = listOf(src)) { invocation ->
val klass = invocation.processingEnv.requireTypeElement("MyDataClass")
val methodNames = klass.getAllMethods().map {
it.name
@@ -323,7 +323,7 @@
class NullableSubject: Base<String?>()
""".trimIndent()
)
- runProcessorTestIncludingKsp(sources = listOf(source)) { invocation ->
+ runProcessorTest(sources = listOf(source)) { invocation ->
val base = invocation.processingEnv.requireTypeElement("Base")
val subject = invocation.processingEnv.requireType("Subject")
.asDeclaredType()
@@ -386,7 +386,7 @@
}
""".trimIndent()
)
- runProcessorTestIncludingKsp(sources = listOf(src, javaSrc)) { invocation ->
+ runProcessorTest(sources = listOf(src, javaSrc)) { invocation ->
val base = invocation.processingEnv.requireTypeElement("MyInterface")
val impl = invocation.processingEnv.requireTypeElement("MyImpl")
val javaImpl = invocation.processingEnv.requireTypeElement("JavaImpl")
diff --git a/room/compiler-processing/src/test/java/androidx/room/compiler/processing/XExecutableTypeTest.kt b/room/compiler-processing/src/test/java/androidx/room/compiler/processing/XExecutableTypeTest.kt
index b2a03e5..38b007d 100644
--- a/room/compiler-processing/src/test/java/androidx/room/compiler/processing/XExecutableTypeTest.kt
+++ b/room/compiler-processing/src/test/java/androidx/room/compiler/processing/XExecutableTypeTest.kt
@@ -20,7 +20,7 @@
import androidx.room.compiler.processing.util.Source
import androidx.room.compiler.processing.util.UNIT_CLASS_NAME
import androidx.room.compiler.processing.util.getMethod
-import androidx.room.compiler.processing.util.runProcessorTestIncludingKsp
+import androidx.room.compiler.processing.util.runProcessorTest
import androidx.room.compiler.processing.util.typeName
import com.google.common.truth.Truth.assertThat
import com.squareup.javapoet.ParameterizedTypeName
@@ -43,7 +43,7 @@
abstract class Subject : MyInterface<String>
""".trimIndent()
)
- runProcessorTestIncludingKsp(
+ runProcessorTest(
sources = listOf(src)
) { invocation ->
val myInterface = invocation.processingEnv.requireTypeElement("MyInterface")
@@ -112,7 +112,7 @@
abstract class NullableSubject: MyInterface<String?>
""".trimIndent()
)
- runProcessorTestIncludingKsp(sources = listOf(src)) { invocation ->
+ runProcessorTest(sources = listOf(src)) { invocation ->
val myInterface = invocation.processingEnv.requireTypeElement("MyInterface")
// helper method to get executable types both from sub class and also as direct child of
diff --git a/room/compiler-processing/src/test/java/androidx/room/compiler/processing/XNullabilityTest.kt b/room/compiler-processing/src/test/java/androidx/room/compiler/processing/XNullabilityTest.kt
index 859e553..b808f2c 100644
--- a/room/compiler-processing/src/test/java/androidx/room/compiler/processing/XNullabilityTest.kt
+++ b/room/compiler-processing/src/test/java/androidx/room/compiler/processing/XNullabilityTest.kt
@@ -23,8 +23,8 @@
import androidx.room.compiler.processing.util.getField
import androidx.room.compiler.processing.util.getMethod
import androidx.room.compiler.processing.util.getParameter
+import androidx.room.compiler.processing.util.runProcessorTestWithoutKsp
import androidx.room.compiler.processing.util.runProcessorTest
-import androidx.room.compiler.processing.util.runProcessorTestIncludingKsp
import com.google.common.truth.Truth.assertThat
import com.squareup.javapoet.TypeName
import org.junit.Test
@@ -69,7 +69,7 @@
""".trimIndent()
)
// TODO run with KSP once https://github.com/google/ksp/issues/167 is fixed
- runProcessorTest(
+ runProcessorTestWithoutKsp(
sources = listOf(source)
) {
val element = it.processingEnv.requireTypeElement("foo.bar.Baz")
@@ -164,7 +164,7 @@
}
""".trimIndent()
)
- runProcessorTestIncludingKsp(
+ runProcessorTest(
sources = listOf(source)
) {
val element = it.processingEnv.requireTypeElement("foo.bar.Baz")
@@ -257,7 +257,7 @@
@Test
fun changeNullability_primitives() {
- runProcessorTestIncludingKsp { invocation ->
+ runProcessorTest { invocation ->
PRIMITIVE_TYPES.forEach { primitiveTypeName ->
val primitive = invocation.processingEnv.requireType(primitiveTypeName)
assertThat(primitive.nullability).isEqualTo(NONNULL)
@@ -295,7 +295,7 @@
}
""".trimIndent()
)
- runProcessorTestIncludingKsp(sources = listOf(javaSrc, kotlinSrc)) { invocation ->
+ runProcessorTest(sources = listOf(javaSrc, kotlinSrc)) { invocation ->
listOf("KotlinClass", "JavaClass").forEach {
val subject = invocation.processingEnv.requireTypeElement(it)
.getField("subject").type
@@ -316,7 +316,7 @@
@Test
fun changeNullability_declared() {
- runProcessorTestIncludingKsp { invocation ->
+ runProcessorTest { invocation ->
val subject = invocation.processingEnv.requireType("java.util.List")
subject.makeNullable().let {
assertThat(it.nullability).isEqualTo(NULLABLE)
@@ -337,7 +337,7 @@
@Test
fun changeNullability_arrayTypes() {
- runProcessorTestIncludingKsp { invocation ->
+ runProcessorTest { invocation ->
val subject = invocation.processingEnv.getArrayType(
invocation.processingEnv.requireType("java.util.List")
)
@@ -368,7 +368,7 @@
}
""".trimIndent()
)
- runProcessorTestIncludingKsp(sources = listOf(src)) { invocation ->
+ runProcessorTest(sources = listOf(src)) { invocation ->
val voidType = invocation.processingEnv.requireTypeElement("Foo")
.getMethod("subject").returnType
assertThat(voidType.typeName).isEqualTo(TypeName.VOID)
diff --git a/room/compiler-processing/src/test/java/androidx/room/compiler/processing/XProcessingEnvTest.kt b/room/compiler-processing/src/test/java/androidx/room/compiler/processing/XProcessingEnvTest.kt
index 4ae8c01..2f92301 100644
--- a/room/compiler-processing/src/test/java/androidx/room/compiler/processing/XProcessingEnvTest.kt
+++ b/room/compiler-processing/src/test/java/androidx/room/compiler/processing/XProcessingEnvTest.kt
@@ -17,8 +17,7 @@
package androidx.room.compiler.processing
import androidx.room.compiler.processing.util.Source
-import androidx.room.compiler.processing.util.runProcessorTestForFailedCompilation
-import androidx.room.compiler.processing.util.runProcessorTestIncludingKsp
+import androidx.room.compiler.processing.util.runProcessorTest
import com.google.common.truth.Truth.assertThat
import com.squareup.javapoet.ClassName
import com.squareup.javapoet.JavaFile
@@ -34,7 +33,7 @@
class XProcessingEnvTest {
@Test
fun getElement() {
- runProcessorTestIncludingKsp(
+ runProcessorTest(
listOf(
Source.java(
"foo.bar.Baz",
@@ -98,7 +97,7 @@
@Test
fun basic() {
- runProcessorTestIncludingKsp(
+ runProcessorTest(
listOf(
Source.java(
"foo.bar.Baz",
@@ -138,7 +137,7 @@
}
""".trimIndent()
)
- runProcessorTestIncludingKsp(
+ runProcessorTest(
listOf(source)
) { invocation ->
PRIMITIVE_TYPES.flatMap {
@@ -163,7 +162,7 @@
}
""".trimIndent()
)
- runProcessorTestIncludingKsp(sources = listOf(src)) {
+ runProcessorTest(sources = listOf(src)) {
it.processingEnv.requireTypeElement("foo.bar.Outer.Inner").let {
val className = it.className
assertThat(className.packageName()).isEqualTo("foo.bar")
@@ -175,7 +174,7 @@
@Test
fun findGeneratedAnnotation() {
- runProcessorTestIncludingKsp { invocation ->
+ runProcessorTest { invocation ->
val generatedAnnotation = invocation.processingEnv.findGeneratedAnnotation()
assertThat(generatedAnnotation?.name).isEqualTo("Generated")
}
@@ -200,7 +199,7 @@
""".trimIndent()
)
listOf(javaSrc, kotlinSrc).forEach { src ->
- runProcessorTestIncludingKsp(sources = listOf(src)) { invocation ->
+ runProcessorTest(sources = listOf(src)) { invocation ->
val className = ClassName.get("foo.bar", "ToBeGenerated")
if (invocation.processingEnv.findTypeElement(className) == null) {
// generate only if it doesn't exist to handle multi-round
@@ -223,14 +222,18 @@
class Foo {}
""".trimIndent()
)
- // TODO include KSP when https://github.com/google/ksp/issues/122 is fixed.
- runProcessorTestForFailedCompilation(
+ runProcessorTest(
sources = listOf(src)
) {
it.processingEnv.messager.printMessage(
Diagnostic.Kind.ERROR,
"intentional failure"
)
+ it.assertCompilationResult {
+ compilationDidFail()
+ .and()
+ .hasError("intentional failure")
+ }
}
}
diff --git a/room/compiler-processing/src/test/java/androidx/room/compiler/processing/XTypeTest.kt b/room/compiler-processing/src/test/java/androidx/room/compiler/processing/XTypeTest.kt
index 2cd2588..4aa8ac9 100644
--- a/room/compiler-processing/src/test/java/androidx/room/compiler/processing/XTypeTest.kt
+++ b/room/compiler-processing/src/test/java/androidx/room/compiler/processing/XTypeTest.kt
@@ -24,9 +24,8 @@
import androidx.room.compiler.processing.util.javaElementUtils
import androidx.room.compiler.processing.util.kspResolver
import androidx.room.compiler.processing.util.runKspTest
+import androidx.room.compiler.processing.util.runProcessorTestWithoutKsp
import androidx.room.compiler.processing.util.runProcessorTest
-import androidx.room.compiler.processing.util.runProcessorTestForFailedCompilation
-import androidx.room.compiler.processing.util.runProcessorTestIncludingKsp
import androidx.room.compiler.processing.util.typeName
import com.google.common.truth.Truth
import com.google.common.truth.Truth.assertThat
@@ -53,7 +52,7 @@
}
""".trimIndent()
)
- runProcessorTestIncludingKsp(
+ runProcessorTest(
sources = listOf(parent)
) {
val type = it.processingEnv.requireType("foo.bar.Parent") as XDeclaredType
@@ -110,8 +109,9 @@
}
""".trimIndent()
)
- // TODO run with KSP as well once https://github.com/google/ksp/issues/107 is resolved
- runProcessorTestForFailedCompilation(
+
+ // enable KSP once https://github.com/google/ksp/issues/107 is fixed.
+ runProcessorTestWithoutKsp(
sources = listOf(missingTypeRef)
) {
val element = it.processingEnv.requireTypeElement("foo.bar.Baz")
@@ -127,6 +127,9 @@
ClassName.get("", "NotExistingType")
)
}
+ it.assertCompilationResult {
+ compilationDidFail()
+ }
}
}
@@ -141,7 +144,7 @@
}
""".trimIndent()
)
- runProcessorTestIncludingKsp(
+ runProcessorTest(
sources = listOf(subject)
) {
val type = it.processingEnv.requireType("foo.bar.Baz")
@@ -174,7 +177,7 @@
@Test
fun isCollection_kotlin() {
- runKspTest(sources = emptyList(), succeed = true) { invocation ->
+ runKspTest(sources = emptyList()) { invocation ->
val subjects = listOf("Map" to false, "List" to true, "Set" to true)
subjects.forEach { (subject, expected) ->
invocation.processingEnv.requireType("kotlin.collections.$subject").let { type ->
@@ -187,7 +190,7 @@
@Test
fun toStringMatchesUnderlyingElement() {
- runProcessorTestIncludingKsp {
+ runProcessorTest {
val subject = "java.lang.String"
val expected = if (it.isKsp) {
it.kspResolver.getClassDeclarationByName(subject)?.toString()
@@ -212,12 +215,14 @@
}
""".trimIndent()
)
- // TODO run with KSP as well once https://github.com/google/ksp/issues/107 is resolved
- runProcessorTestForFailedCompilation(
+ runProcessorTest(
sources = listOf(missingTypeRef)
) {
val element = it.processingEnv.requireTypeElement("foo.bar.Baz")
assertThat(element.superType?.isError()).isTrue()
+ it.assertCompilationResult {
+ compilationDidFail()
+ }
}
}
@@ -256,7 +261,7 @@
@Test
fun rawType() {
- runProcessorTestIncludingKsp {
+ runProcessorTest {
val subject = it.processingEnv.getDeclaredType(
it.processingEnv.requireTypeElement(List::class),
it.processingEnv.requireType(String::class)
diff --git a/room/compiler-processing/src/test/java/androidx/room/compiler/processing/javac/kotlin/KotlinMetadataElementTest.kt b/room/compiler-processing/src/test/java/androidx/room/compiler/processing/javac/kotlin/KotlinMetadataElementTest.kt
index 679af1c..7251136 100644
--- a/room/compiler-processing/src/test/java/androidx/room/compiler/processing/javac/kotlin/KotlinMetadataElementTest.kt
+++ b/room/compiler-processing/src/test/java/androidx/room/compiler/processing/javac/kotlin/KotlinMetadataElementTest.kt
@@ -18,7 +18,7 @@
import androidx.room.compiler.processing.javac.JavacProcessingEnv
import androidx.room.compiler.processing.util.Source
-import androidx.room.compiler.processing.util.runProcessorTest
+import androidx.room.compiler.processing.util.runKaptTest
import com.google.common.truth.Truth.assertThat
import org.junit.AssumptionViolatedException
import org.junit.Test
@@ -478,7 +478,7 @@
sources: List<Source> = emptyList(),
handler: (ProcessingEnvironment) -> Unit
) {
- runProcessorTest(sources) {
+ runKaptTest(sources) {
val processingEnv = it.processingEnv
if (processingEnv !is JavacProcessingEnv) {
throw AssumptionViolatedException("This test only works for java/kapt compilation")
diff --git a/room/compiler-processing/src/test/java/androidx/room/compiler/processing/ksp/KSAsMemberOfTest.kt b/room/compiler-processing/src/test/java/androidx/room/compiler/processing/ksp/KSAsMemberOfTest.kt
index 1bc7787..5cfa2d6 100644
--- a/room/compiler-processing/src/test/java/androidx/room/compiler/processing/ksp/KSAsMemberOfTest.kt
+++ b/room/compiler-processing/src/test/java/androidx/room/compiler/processing/ksp/KSAsMemberOfTest.kt
@@ -48,7 +48,7 @@
""".trimIndent()
)
- runKspTest(sources = listOf(src), succeed = true) { invocation ->
+ runKspTest(sources = listOf(src)) { invocation ->
val base = invocation.processingEnv.requireTypeElement("BaseClass")
val sub = invocation.processingEnv.requireType("SubClass").asDeclaredType()
base.getField("normalInt").let { prop ->
@@ -121,7 +121,7 @@
abstract class NullableSubject: MyInterface<String?>()
""".trimIndent()
)
- runKspTest(sources = listOf(src), succeed = true) { invocation ->
+ runKspTest(sources = listOf(src)) { invocation ->
val myInterface = invocation.processingEnv.requireTypeElement("MyInterface")
val nonNullSubject = invocation.processingEnv.requireType("NonNullSubject")
.asDeclaredType()
diff --git a/room/compiler-processing/src/test/java/androidx/room/compiler/processing/ksp/KSTypeExtTest.kt b/room/compiler-processing/src/test/java/androidx/room/compiler/processing/ksp/KSTypeExtTest.kt
index c185f47..2865715 100644
--- a/room/compiler-processing/src/test/java/androidx/room/compiler/processing/ksp/KSTypeExtTest.kt
+++ b/room/compiler-processing/src/test/java/androidx/room/compiler/processing/ksp/KSTypeExtTest.kt
@@ -26,7 +26,6 @@
import com.google.common.truth.Truth.assertThat
import com.google.devtools.ksp.getDeclaredFunctions
import com.google.devtools.ksp.getDeclaredProperties
-import com.google.devtools.ksp.processing.Resolver
import com.google.devtools.ksp.symbol.KSClassDeclaration
import com.squareup.javapoet.ClassName
import com.squareup.javapoet.ParameterizedTypeName
@@ -55,18 +54,18 @@
}
""".trimIndent()
)
- runTest(subjectSrc) { resolver ->
- val subject = resolver.requireClass("foo.bar.Baz")
- assertThat(subject.propertyType("intField").typeName(resolver))
+ runKspTest(sources = listOf(subjectSrc)) { invocation ->
+ val subject = invocation.kspResolver.requireClass("foo.bar.Baz")
+ assertThat(subject.propertyType("intField").typeName(invocation.kspResolver))
.isEqualTo(TypeName.INT)
- assertThat(subject.propertyType("listOfInts").typeName(resolver))
+ assertThat(subject.propertyType("listOfInts").typeName(invocation.kspResolver))
.isEqualTo(
ParameterizedTypeName.get(
List::class.className(),
TypeName.INT.box()
)
)
- assertThat(subject.propertyType("mutableMapOfAny").typeName(resolver))
+ assertThat(subject.propertyType("mutableMapOfAny").typeName(invocation.kspResolver))
.isEqualTo(
ParameterizedTypeName.get(
Map::class.className(),
@@ -74,7 +73,7 @@
TypeName.OBJECT,
)
)
- val typeName = subject.propertyType("nested").typeName(resolver)
+ val typeName = subject.propertyType("nested").typeName(invocation.kspResolver)
check(typeName is ClassName)
assertThat(typeName.packageName()).isEqualTo("foo.bar")
assertThat(typeName.simpleNames()).containsExactly("Baz", "Nested")
@@ -97,22 +96,25 @@
}
""".trimIndent()
)
- runTest(subjectSrc) { resolver ->
- val subject = resolver.requireClass("Baz")
- assertThat(subject.propertyType("intField").typeName(resolver))
- .isEqualTo(TypeName.INT)
- assertThat(subject.propertyType("listOfInts").typeName(resolver))
- .isEqualTo(
- ParameterizedTypeName.get(
- List::class.className(),
- TypeName.INT.box()
- )
+ runKspTest(sources = listOf(subjectSrc)) { invocation ->
+ val subject = invocation.kspResolver.requireClass("Baz")
+ assertThat(
+ subject.propertyType("intField").typeName(invocation.kspResolver)
+ ).isEqualTo(TypeName.INT)
+ assertThat(
+ subject.propertyType("listOfInts").typeName(invocation.kspResolver)
+ ).isEqualTo(
+ ParameterizedTypeName.get(
+ List::class.className(),
+ TypeName.INT.box()
)
- assertThat(subject.propertyType("incompleteGeneric").typeName(resolver))
- .isEqualTo(
- List::class.className()
- )
- assertThat(subject.propertyType("nested").typeName(resolver))
+ )
+ assertThat(
+ subject.propertyType("incompleteGeneric").typeName(invocation.kspResolver)
+ ).isEqualTo(
+ List::class.className()
+ )
+ assertThat(subject.propertyType("nested").typeName(invocation.kspResolver))
.isEqualTo(
ClassName.get("", "Baz", "Nested")
)
@@ -132,25 +134,31 @@
}
""".trimIndent()
)
- runTest(subjectSrc, succeed = false) { resolver ->
- val subject = resolver.requireClass("Foo")
- assertThat(subject.propertyType("errorField").typeName(resolver))
- .isEqualTo(ERROR_TYPE_NAME)
- assertThat(subject.propertyType("listOfError").typeName(resolver))
- .isEqualTo(
- ParameterizedTypeName.get(
- List::class.className(),
- ERROR_TYPE_NAME
- )
+ runKspTest(sources = listOf(subjectSrc)) { invocation ->
+ val subject = invocation.kspResolver.requireClass("Foo")
+ assertThat(
+ subject.propertyType("errorField").typeName(invocation.kspResolver)
+ ).isEqualTo(ERROR_TYPE_NAME)
+ assertThat(
+ subject.propertyType("listOfError").typeName(invocation.kspResolver)
+ ).isEqualTo(
+ ParameterizedTypeName.get(
+ List::class.className(),
+ ERROR_TYPE_NAME
)
- assertThat(subject.propertyType("mutableMapOfDontExist").typeName(resolver))
- .isEqualTo(
- ParameterizedTypeName.get(
- Map::class.className(),
- String::class.className(),
- ERROR_TYPE_NAME
- )
+ )
+ assertThat(
+ subject.propertyType("mutableMapOfDontExist").typeName(invocation.kspResolver)
+ ).isEqualTo(
+ ParameterizedTypeName.get(
+ Map::class.className(),
+ String::class.className(),
+ ERROR_TYPE_NAME
)
+ )
+ invocation.assertCompilationResult {
+ compilationDidFail()
+ }
}
}
@@ -181,8 +189,7 @@
// methodName -> returnType, ...paramTypes
val golden = mutableMapOf<String, List<TypeName>>()
runKaptTest(
- sources = listOf(src),
- succeed = true
+ sources = listOf(src)
) { invocation ->
val env = (invocation.processingEnv as JavacProcessingEnv)
val subject = env.delegate.elementUtils.getTypeElement("Subject")
@@ -196,8 +203,7 @@
}
val kspResults = mutableMapOf<String, List<TypeName>>()
runKspTest(
- sources = listOf(src),
- succeed = true
+ sources = listOf(src)
) { invocation ->
val env = (invocation.processingEnv as KspProcessingEnv)
val subject = env.resolver.requireClass("Subject")
@@ -220,21 +226,6 @@
assertThat(kspResults).containsExactlyEntriesIn(golden)
}
- private fun runTest(
- vararg sources: Source,
- succeed: Boolean = true,
- handler: (Resolver) -> Unit
- ) {
- runKspTest(
- sources = sources.toList(),
- succeed = succeed
- ) {
- handler(
- (it.processingEnv as KspProcessingEnv).resolver
- )
- }
- }
-
private fun KSClassDeclaration.requireProperty(name: String) = getDeclaredProperties().first {
it.simpleName.asString() == name
}
diff --git a/room/compiler-processing/src/test/java/androidx/room/compiler/processing/ksp/KspFieldElementTest.kt b/room/compiler-processing/src/test/java/androidx/room/compiler/processing/ksp/KspFieldElementTest.kt
index 1e8a5a2..f6666c4 100644
--- a/room/compiler-processing/src/test/java/androidx/room/compiler/processing/ksp/KspFieldElementTest.kt
+++ b/room/compiler-processing/src/test/java/androidx/room/compiler/processing/ksp/KspFieldElementTest.kt
@@ -25,7 +25,7 @@
import androidx.room.compiler.processing.util.className
import androidx.room.compiler.processing.util.compileFiles
import androidx.room.compiler.processing.util.getField
-import androidx.room.compiler.processing.util.runProcessorTestIncludingKsp
+import androidx.room.compiler.processing.util.runProcessorTest
import androidx.room.compiler.processing.util.typeName
import com.google.common.truth.Truth.assertThat
import com.google.common.truth.Truth.assertWithMessage
@@ -152,7 +152,7 @@
class Sub1 : Base<Int, String>()
""".trimIndent()
)
- runProcessorTestIncludingKsp(sources = listOf(src)) { invocation ->
+ runProcessorTest(sources = listOf(src)) { invocation ->
val sub = invocation.processingEnv.requireTypeElement("Sub1")
val base = invocation.processingEnv.requireTypeElement("Base")
val t = base.getField("t")
@@ -197,13 +197,13 @@
private fun runModifierTest(vararg inputs: ModifierTestInput) {
// we'll run the test twice. once it is in source and once it is coming from a dependency.
val sources = inputs.map(ModifierTestInput::source)
- runProcessorTestIncludingKsp(
+ runProcessorTest(
sources = sources
) { invocation ->
assertModifiers(invocation, inputs)
}
val classpath = compileFiles(sources)
- runProcessorTestIncludingKsp(
+ runProcessorTest(
sources = emptyList(),
classpath = listOf(classpath)
) { invocation ->
diff --git a/room/compiler-processing/src/test/java/androidx/room/compiler/processing/ksp/KspTypeElementTest.kt b/room/compiler-processing/src/test/java/androidx/room/compiler/processing/ksp/KspTypeElementTest.kt
index 437bdc3..804df7b 100644
--- a/room/compiler-processing/src/test/java/androidx/room/compiler/processing/ksp/KspTypeElementTest.kt
+++ b/room/compiler-processing/src/test/java/androidx/room/compiler/processing/ksp/KspTypeElementTest.kt
@@ -23,7 +23,7 @@
import androidx.room.compiler.processing.util.getField
import androidx.room.compiler.processing.util.getMethod
import androidx.room.compiler.processing.util.runKspTest
-import androidx.room.compiler.processing.util.runProcessorTestIncludingKsp
+import androidx.room.compiler.processing.util.runProcessorTest
import com.google.common.truth.Truth
import com.google.common.truth.Truth.assertThat
import com.squareup.javapoet.ClassName
@@ -52,8 +52,7 @@
""".trimIndent()
)
runKspTest(
- sources = listOf(src1, src2),
- succeed = true
+ sources = listOf(src1, src2)
) { invocation ->
invocation.processingEnv.requireTypeElement("TopLevel").let {
assertThat(it.packageName).isEqualTo("")
@@ -93,7 +92,7 @@
interface MyInterface {}
""".trimIndent()
)
- runKspTest(sources = listOf(src), succeed = true) { invocation ->
+ runKspTest(sources = listOf(src)) { invocation ->
invocation.processingEnv.requireTypeElement("foo.bar.Baz").let {
assertThat(it.superType).isEqualTo(
invocation.processingEnv.requireType("foo.bar.AbstractClass")
@@ -134,7 +133,7 @@
}
""".trimIndent()
)
- runKspTest(sources = listOf(src), succeed = true) { invocation ->
+ runKspTest(sources = listOf(src)) { invocation ->
invocation.processingEnv.requireTypeElement("foo.bar.Outer").let {
assertThat(it.className).isEqualTo(ClassName.get("foo.bar", "Outer"))
assertThat(it.enclosingTypeElement).isNull()
@@ -163,7 +162,7 @@
private class PrivateClass
""".trimIndent()
)
- runKspTest(sources = listOf(src), succeed = true) { invocation ->
+ runKspTest(sources = listOf(src)) { invocation ->
fun getModifiers(element: XTypeElement): Set<String> {
val result = mutableSetOf<String>()
if (element.isAbstract()) result.add("abstract")
@@ -205,7 +204,7 @@
interface MyInterface
""".trimIndent()
)
- runKspTest(sources = listOf(src), succeed = true) { invocation ->
+ runKspTest(sources = listOf(src)) { invocation ->
invocation.processingEnv.requireTypeElement("MyClass").let {
assertThat(it.kindName()).isEqualTo("class")
}
@@ -228,7 +227,7 @@
}
""".trimIndent()
)
- runProcessorTestIncludingKsp(sources = listOf(src)) { invocation ->
+ runProcessorTest(sources = listOf(src)) { invocation ->
val baseClass = invocation.processingEnv.requireTypeElement("BaseClass")
assertThat(baseClass.getAllFieldNames()).containsExactly("genericProp")
val subClass = invocation.processingEnv.requireTypeElement("SubClass")
@@ -269,7 +268,7 @@
) : BaseClass(value)
""".trimIndent()
)
- runKspTest(sources = listOf(src), succeed = true) { invocation ->
+ runKspTest(sources = listOf(src)) { invocation ->
val baseClass = invocation.processingEnv.requireTypeElement("BaseClass")
assertThat(baseClass.getAllFieldNames()).containsExactly("value")
val subClass = invocation.processingEnv.requireTypeElement("SubClass")
@@ -317,7 +316,7 @@
}
""".trimIndent()
)
- runKspTest(sources = listOf(src), succeed = true) { invocation ->
+ runKspTest(sources = listOf(src)) { invocation ->
val base = invocation.processingEnv.requireTypeElement("Base")
assertThat(base.getDeclaredMethods().names()).containsExactly(
"baseFun", "suspendFun", "privateBaseFun", "staticBaseFun"
@@ -371,7 +370,7 @@
}
""".trimIndent()
)
- runKspTest(sources = listOf(src), succeed = true) { invocation ->
+ runKspTest(sources = listOf(src)) { invocation ->
val klass = invocation.processingEnv.requireTypeElement("SubClass")
assertThat(klass.getAllMethods().names()).containsExactly(
"baseMethod", "overriddenMethod", "baseCompanionMethod",
@@ -395,7 +394,7 @@
}
""".trimIndent()
)
- runKspTest(sources = listOf(src), succeed = true) { invocation ->
+ runKspTest(sources = listOf(src)) { invocation ->
invocation.processingEnv.requireTypeElement("JustGetter").let { base ->
assertThat(base.getDeclaredMethods().names()).containsExactly(
"getX"
@@ -438,7 +437,7 @@
class SubClass : CompanionSubject()
""".trimIndent()
)
- runKspTest(sources = listOf(src), succeed = true) { invocation ->
+ runKspTest(sources = listOf(src)) { invocation ->
val subject = invocation.processingEnv.requireTypeElement("CompanionSubject")
assertThat(subject.getAllFieldNames()).containsExactly(
"mutableStatic", "immutableStatic"
@@ -471,7 +470,7 @@
}
""".trimIndent()
)
- runKspTest(sources = listOf(src), succeed = true) { invocation ->
+ runKspTest(sources = listOf(src)) { invocation ->
invocation.processingEnv.requireTypeElement("JustGetter").let { base ->
assertThat(base.getDeclaredMethods().names()).containsExactly(
"getX"
@@ -520,7 +519,7 @@
abstract class AbstractExplicit(x:Int)
""".trimIndent()
)
- runProcessorTestIncludingKsp(sources = listOf(src)) { invocation ->
+ runProcessorTest(sources = listOf(src)) { invocation ->
val subjects = listOf(
"MyInterface", "NoExplicitConstructor", "Base", "ExplicitConstructor",
"BaseWithSecondary", "Sub", "SubWith3Constructors",
@@ -576,7 +575,7 @@
}
""".trimIndent()
)
- runKspTest(sources = listOf(src), succeed = true) { invocation ->
+ runKspTest(sources = listOf(src)) { invocation ->
val subject = invocation.processingEnv.requireTypeElement("MyInterface")
assertThat(subject.getMethod("notJvmDefault").isJavaDefault()).isFalse()
assertThat(subject.getMethod("jvmDefault").isJavaDefault()).isTrue()
@@ -623,7 +622,7 @@
}
""".trimIndent()
)
- runProcessorTestIncludingKsp(sources = listOf(src)) { invocation ->
+ runProcessorTest(sources = listOf(src)) { invocation ->
val subjects = listOf(
"MyInterface", "NoExplicitConstructor", "Base", "ExplicitConstructor",
"BaseWithSecondary", "Sub", "SubWith3Constructors",
diff --git a/room/compiler-processing/src/test/java/androidx/room/compiler/processing/ksp/KspTypeTest.kt b/room/compiler-processing/src/test/java/androidx/room/compiler/processing/ksp/KspTypeTest.kt
index db0fc7dc..7643b04 100644
--- a/room/compiler-processing/src/test/java/androidx/room/compiler/processing/ksp/KspTypeTest.kt
+++ b/room/compiler-processing/src/test/java/androidx/room/compiler/processing/ksp/KspTypeTest.kt
@@ -50,7 +50,7 @@
interface MyInterface {}
""".trimIndent()
)
- runKspTest(listOf(src), succeed = true) {
+ runKspTest(listOf(src)) {
val subject = it.processingEnv.requireType("foo.bar.Baz")
assertThat(subject.typeName).isEqualTo(
ClassName.get("foo.bar", "Baz")
@@ -89,8 +89,7 @@
""".trimIndent()
)
runKspTest(
- listOf(src),
- succeed = false
+ listOf(src)
) { invocation ->
invocation.requireDeclaredPropertyType("errorType").let { type ->
assertThat(type.isError()).isTrue()
@@ -107,6 +106,9 @@
assertThat(typeArg.typeName).isEqualTo(ERROR_TYPE_NAME)
}
}
+ invocation.assertCompilationResult {
+ compilationDidFail()
+ }
}
}
@@ -121,8 +123,7 @@
""".trimIndent()
)
runKspTest(
- listOf(src),
- succeed = true
+ listOf(src)
) { invocation ->
invocation.requireDeclaredPropertyType("listOfNullableStrings").let { type ->
assertThat(type.nullability).isEqualTo(NONNULL)
@@ -173,8 +174,7 @@
""".trimIndent()
)
runKspTest(
- listOf(src),
- succeed = true
+ listOf(src)
) { invocation ->
val nullableStringList = invocation
.requireDeclaredPropertyType("listOfNullableStrings")
@@ -220,8 +220,7 @@
""".trimIndent()
)
runKspTest(
- listOf(src),
- succeed = true
+ listOf(src)
) { invocation ->
invocation.requirePropertyType("simple").let {
assertThat(it.rawType.typeName).isEqualTo(TypeName.INT)
@@ -257,7 +256,7 @@
}
""".trimIndent()
)
- runKspTest(sources = listOf(src), succeed = true) { invocation ->
+ runKspTest(sources = listOf(src)) { invocation ->
val resolver = (invocation.processingEnv as KspProcessingEnv).resolver
val voidMethod = resolver.getClassDeclarationByName("foo.bar.Baz")!!
.getDeclaredFunctions()
@@ -289,8 +288,7 @@
""".trimIndent()
)
runKspTest(
- listOf(src),
- succeed = false
+ listOf(src)
) { invocation ->
fun mapProp(name: String) = invocation.requirePropertyType(name).let {
listOf(
@@ -313,6 +311,9 @@
assertThat(mapProp("nullableByteProp")).containsExactly("isByte")
assertThat(mapProp("errorProp")).containsExactly("isError")
assertThat(mapProp("nullableErrorProp")).containsExactly("isError")
+ invocation.assertCompilationResult {
+ compilationDidFail()
+ }
}
}
@@ -334,8 +335,7 @@
""".trimIndent()
)
runKspTest(
- listOf(src),
- succeed = false
+ listOf(src)
) { invocation ->
fun getDefaultValue(name: String) = invocation.requirePropertyType(name).defaultValue()
// javac types do not check nullability but checking it is more correct
@@ -351,6 +351,9 @@
assertThat(getDefaultValue("errorProp")).isEqualTo("null")
assertThat(getDefaultValue("nullableErrorProp")).isEqualTo("null")
assertThat(getDefaultValue("stringProp")).isEqualTo("null")
+ invocation.assertCompilationResult {
+ compilationDidFail()
+ }
}
}
@@ -366,8 +369,7 @@
""".trimIndent()
)
runKspTest(
- listOf(src),
- succeed = true
+ listOf(src)
) { invocation ->
assertThat(
invocation.requirePropertyType("stringProp").isTypeOf(
@@ -418,8 +420,7 @@
""".trimIndent()
)
runKspTest(
- listOf(src),
- succeed = true
+ listOf(src)
) { invocation ->
fun check(prop1: String, prop2: String): Boolean {
return invocation.requirePropertyType(prop1).isSameType(
@@ -450,8 +451,7 @@
""".trimIndent()
)
runKspTest(
- listOf(src),
- succeed = true
+ listOf(src)
) { invocation ->
val env = (invocation.processingEnv as KspProcessingEnv)
val classNames = listOf("Bar", "Bar_NullableFoo")
@@ -491,8 +491,7 @@
""".trimIndent()
)
runKspTest(
- listOf(src),
- succeed = true
+ listOf(src)
) { invocation ->
val env = (invocation.processingEnv as KspProcessingEnv)
val method = env.resolver
diff --git a/room/compiler/build.gradle b/room/compiler/build.gradle
index fc529d1..6cca78d 100644
--- a/room/compiler/build.gradle
+++ b/room/compiler/build.gradle
@@ -114,6 +114,7 @@
implementation(INTELLIJ_ANNOTATIONS)
testImplementation(GOOGLE_COMPILE_TESTING)
testImplementation projectOrArtifact(":paging:paging-common")
+ testImplementation(project(":room:room-compiler-processing-testing"))
testImplementation(JUNIT)
testImplementation(JSR250)
testImplementation(MOCKITO_CORE)
diff --git a/room/compiler/src/main/kotlin/androidx/room/log/RLog.kt b/room/compiler/src/main/kotlin/androidx/room/log/RLog.kt
index d18778e..0ce7b73 100644
--- a/room/compiler/src/main/kotlin/androidx/room/log/RLog.kt
+++ b/room/compiler/src/main/kotlin/androidx/room/log/RLog.kt
@@ -75,9 +75,9 @@
messager.printMessage(WARNING, msg.safeFormat(args), defaultElement)
}
- class CollectingMessager : XMessager {
+ class CollectingMessager : XMessager() {
private val messages = mutableMapOf<Diagnostic.Kind, MutableList<Pair<String, XElement?>>>()
- override fun printMessage(kind: Diagnostic.Kind, msg: String, element: XElement?) {
+ override fun onPrintMessage(kind: Diagnostic.Kind, msg: String, element: XElement?) {
messages.getOrPut(
kind,
{
diff --git a/room/compiler/src/main/kotlin/androidx/room/solver/types/BoxedBooleanToBoxedIntConverter.kt b/room/compiler/src/main/kotlin/androidx/room/solver/types/BoxedBooleanToBoxedIntConverter.kt
index 7a3664c..2e53e25 100644
--- a/room/compiler/src/main/kotlin/androidx/room/solver/types/BoxedBooleanToBoxedIntConverter.kt
+++ b/room/compiler/src/main/kotlin/androidx/room/solver/types/BoxedBooleanToBoxedIntConverter.kt
@@ -25,8 +25,8 @@
*/
object BoxedBooleanToBoxedIntConverter {
fun create(processingEnvironment: XProcessingEnv): List<TypeConverter> {
- val tBoolean = processingEnvironment.requireType("java.lang.Boolean")
- val tInt = processingEnvironment.requireType("java.lang.Integer")
+ val tBoolean = processingEnvironment.requireType("java.lang.Boolean").makeNullable()
+ val tInt = processingEnvironment.requireType("java.lang.Integer").makeNullable()
return listOf(
object : TypeConverter(tBoolean, tInt) {
override fun convert(
diff --git a/room/compiler/src/main/kotlin/androidx/room/solver/types/BoxedPrimitiveColumnTypeAdapter.kt b/room/compiler/src/main/kotlin/androidx/room/solver/types/BoxedPrimitiveColumnTypeAdapter.kt
index 6fc5cc5..e47d917 100644
--- a/room/compiler/src/main/kotlin/androidx/room/solver/types/BoxedPrimitiveColumnTypeAdapter.kt
+++ b/room/compiler/src/main/kotlin/androidx/room/solver/types/BoxedPrimitiveColumnTypeAdapter.kt
@@ -34,7 +34,7 @@
return primitiveAdapters.map {
BoxedPrimitiveColumnTypeAdapter(
- it.out.boxed(),
+ it.out.boxed().makeNullable(),
it
)
}
diff --git a/room/compiler/src/test/kotlin/androidx/room/log/RLogTest.kt b/room/compiler/src/test/kotlin/androidx/room/log/RLogTest.kt
index b87099d..71a4ce0 100644
--- a/room/compiler/src/test/kotlin/androidx/room/log/RLogTest.kt
+++ b/room/compiler/src/test/kotlin/androidx/room/log/RLogTest.kt
@@ -16,20 +16,22 @@
package androidx.room.log
+import androidx.room.compiler.processing.XElement
import androidx.room.compiler.processing.XMessager
import androidx.room.vo.Warning
import org.junit.Test
import org.junit.runner.RunWith
import org.junit.runners.JUnit4
-import org.mockito.Mockito.mock
+import javax.tools.Diagnostic
@RunWith(JUnit4::class)
class RLogTest {
-
- val messager = mock(XMessager::class.java)
-
@Test
fun testSafeFormat() {
+ val messager = object : XMessager() {
+ override fun onPrintMessage(kind: Diagnostic.Kind, msg: String, element: XElement?) {
+ }
+ }
val logger = RLog(messager, emptySet(), null)
// UnknownFormatConversionException
diff --git a/room/compiler/src/test/kotlin/androidx/room/solver/TypeAdapterStoreTest.kt b/room/compiler/src/test/kotlin/androidx/room/solver/TypeAdapterStoreTest.kt
index f7ad69b..ab48fa7a 100644
--- a/room/compiler/src/test/kotlin/androidx/room/solver/TypeAdapterStoreTest.kt
+++ b/room/compiler/src/test/kotlin/androidx/room/solver/TypeAdapterStoreTest.kt
@@ -19,9 +19,11 @@
import COMMON
import androidx.paging.DataSource
import androidx.paging.PagingSource
-import androidx.room.Entity
import androidx.room.compiler.processing.XProcessingEnv
import androidx.room.compiler.processing.asDeclaredType
+import androidx.room.compiler.processing.util.Source
+import androidx.room.compiler.processing.util.XTestInvocation
+import androidx.room.compiler.processing.util.runProcessorTest
import androidx.room.ext.GuavaUtilConcurrentTypeNames
import androidx.room.ext.L
import androidx.room.ext.LifecyclesTypeNames
@@ -46,12 +48,7 @@
import androidx.room.solver.types.CompositeAdapter
import androidx.room.solver.types.EnumColumnTypeAdapter
import androidx.room.solver.types.TypeConverter
-import androidx.room.testing.TestInvocation
-import androidx.room.testing.TestProcessor
-import com.google.common.truth.Truth
-import com.google.testing.compile.CompileTester
-import com.google.testing.compile.JavaFileObjects
-import com.google.testing.compile.JavaSourcesSubjectFactory
+import androidx.room.testing.context
import com.squareup.javapoet.TypeName
import org.hamcrest.CoreMatchers.`is`
import org.hamcrest.CoreMatchers.instanceOf
@@ -61,8 +58,8 @@
import org.junit.Test
import org.junit.runner.RunWith
import org.junit.runners.JUnit4
-import simpleRun
import testCodeGenScope
+import toSources
@Suppress("PLATFORM_CLASS_MAPPED_TO_KOTLIN")
@RunWith(JUnit4::class)
@@ -73,21 +70,24 @@
@Test
fun testDirect() {
- singleRun { invocation ->
+ runProcessorTest { invocation ->
val store = TypeAdapterStore.create(Context(invocation.processingEnv))
val primitiveType = invocation.processingEnv.requireType(TypeName.INT)
val adapter = store.findColumnTypeAdapter(primitiveType, null)
assertThat(adapter, notNullValue())
- }.compilesWithoutError()
+ }
}
@Test
fun testJavaLangBoolean() {
- singleRun { invocation ->
- val store = TypeAdapterStore.create(Context(invocation.processingEnv))
+ runProcessorTest { invocation ->
+ val store = TypeAdapterStore.create(
+ Context(invocation.processingEnv)
+ )
val boolean = invocation
.processingEnv
.requireType("java.lang.Boolean")
+ .makeNullable()
val adapter = store.findColumnTypeAdapter(boolean, null)
assertThat(adapter, notNullValue())
assertThat(adapter, instanceOf(CompositeAdapter::class.java))
@@ -100,22 +100,23 @@
composite.columnTypeAdapter.out.typeName,
`is`(TypeName.INT.box())
)
- }.compilesWithoutError()
+ }
}
@Test
fun testJavaLangEnumCompilesWithoutError() {
- simpleRun(
- JavaFileObjects.forSourceString(
- "foo.bar.Fruit",
- """ package foo.bar;
+ val enumSrc = Source.java(
+ "foo.bar.Fruit",
+ """ package foo.bar;
import androidx.room.*;
enum Fruit {
APPLE,
BANANA,
STRAWBERRY}
""".trimMargin()
- )
+ )
+ runProcessorTest(
+ sources = listOf(enumSrc)
) { invocation ->
val store = TypeAdapterStore.create(Context(invocation.processingEnv))
val enum = invocation
@@ -124,12 +125,12 @@
val adapter = store.findColumnTypeAdapter(enum, null)
assertThat(adapter, notNullValue())
assertThat(adapter, instanceOf(EnumColumnTypeAdapter::class.java))
- }.compilesWithoutError()
+ }
}
@Test
fun testVia1TypeAdapter() {
- singleRun { invocation ->
+ runProcessorTest { invocation ->
val store = TypeAdapterStore.create(Context(invocation.processingEnv))
val booleanType = invocation.processingEnv.requireType(TypeName.BOOLEAN)
val adapter = store.findColumnTypeAdapter(booleanType, null)
@@ -160,12 +161,35 @@
""".trimIndent()
)
)
- }.compilesWithoutError()
+ }
}
@Test
fun testVia2TypeAdapters() {
- singleRun { invocation ->
+ val point = Source.java(
+ "foo.bar.Point",
+ """
+ package foo.bar;
+ import androidx.room.*;
+ @Entity
+ public class Point {
+ public int x, y;
+ public Point(int x, int y) {
+ this.x = x;
+ this.y = y;
+ }
+ public static Point fromBoolean(boolean val) {
+ return val ? new Point(1, 1) : new Point(0, 0);
+ }
+ public static boolean toBoolean(Point point) {
+ return point.x > 0;
+ }
+ }
+ """
+ )
+ runProcessorTest(
+ sources = listOf(point)
+ ) { invocation ->
val store = TypeAdapterStore.create(
Context(invocation.processingEnv),
pointTypeConverters(invocation.processingEnv)
@@ -204,17 +228,17 @@
""".trimIndent()
)
)
- }.compilesWithoutError()
+ }
}
@Test
fun testDate() {
- singleRun { (processingEnv) ->
+ runProcessorTest { invocation ->
val store = TypeAdapterStore.create(
- Context(processingEnv),
- dateTypeConverters(processingEnv)
+ invocation.context,
+ dateTypeConverters(invocation.processingEnv)
)
- val tDate = processingEnv.requireType("java.util.Date")
+ val tDate = invocation.processingEnv.requireType("java.util.Date")
val adapter = store.findCursorValueReader(tDate, SQLTypeAffinity.INTEGER)
assertThat(adapter, notNullValue())
assertThat(adapter?.typeMirror(), `is`(tDate))
@@ -234,12 +258,12 @@
""".trimIndent()
)
)
- }.compilesWithoutError()
+ }
}
@Test
fun testIntList() {
- singleRun { invocation ->
+ runProcessorTest { invocation ->
val binders = createIntListToStringBinders(invocation)
val store = TypeAdapterStore.create(
Context(invocation.processingEnv), binders[0],
@@ -272,12 +296,12 @@
)
assertThat(converter, notNullValue())
assertThat(store.reverse(converter!!), `is`(binders[1]))
- }.compilesWithoutError()
+ }
}
@Test
fun testOneWayConversion() {
- singleRun { invocation ->
+ runProcessorTest { invocation ->
val binders = createIntListToStringBinders(invocation)
val store = TypeAdapterStore.create(Context(invocation.processingEnv), binders[0])
val adapter = store.findColumnTypeAdapter(binders[0].from, null)
@@ -298,7 +322,9 @@
@Test
fun testMissingRx2Room() {
@Suppress("CHANGING_ARGUMENTS_EXECUTION_ORDER_FOR_NAMED_VARARGS")
- simpleRun(jfos = arrayOf(COMMON.PUBLISHER, COMMON.RX2_FLOWABLE)) { invocation ->
+ runProcessorTest(
+ sources = listOf(COMMON.PUBLISHER, COMMON.RX2_FLOWABLE).toSources()
+ ) { invocation ->
val publisherElement = invocation.processingEnv
.requireTypeElement(ReactiveStreamsTypeNames.PUBLISHER)
assertThat(publisherElement, notNullValue())
@@ -308,13 +334,18 @@
},
`is`(true)
)
- }.failsToCompile().withErrorContaining(ProcessorErrors.MISSING_ROOM_RXJAVA2_ARTIFACT)
+ invocation.assertCompilationResult {
+ hasError(ProcessorErrors.MISSING_ROOM_RXJAVA2_ARTIFACT)
+ }
+ }
}
@Test
fun testMissingRx3Room() {
@Suppress("CHANGING_ARGUMENTS_EXECUTION_ORDER_FOR_NAMED_VARARGS")
- simpleRun(jfos = arrayOf(COMMON.PUBLISHER, COMMON.RX3_FLOWABLE)) { invocation ->
+ runProcessorTest(
+ sources = listOf(COMMON.PUBLISHER, COMMON.RX3_FLOWABLE).toSources()
+ ) { invocation ->
val publisherElement = invocation.processingEnv
.requireTypeElement(ReactiveStreamsTypeNames.PUBLISHER)
assertThat(publisherElement, notNullValue())
@@ -324,7 +355,10 @@
},
`is`(true)
)
- }.failsToCompile().withErrorContaining(ProcessorErrors.MISSING_ROOM_RXJAVA3_ARTIFACT)
+ invocation.assertCompilationResult {
+ hasError(ProcessorErrors.MISSING_ROOM_RXJAVA3_ARTIFACT)
+ }
+ }
}
@Test
@@ -334,8 +368,9 @@
COMMON.RX3_FLOWABLE to COMMON.RX3_ROOM
).forEach { (rxTypeSrc, rxRoomSrc) ->
@Suppress("CHANGING_ARGUMENTS_EXECUTION_ORDER_FOR_NAMED_VARARGS")
- simpleRun(jfos = arrayOf(COMMON.PUBLISHER, rxTypeSrc, rxRoomSrc)) {
- invocation ->
+ runProcessorTest(
+ sources = listOf(COMMON.PUBLISHER, rxTypeSrc, rxRoomSrc).toSources()
+ ) { invocation ->
val publisher = invocation.processingEnv
.requireTypeElement(ReactiveStreamsTypeNames.PUBLISHER)
assertThat(publisher, notNullValue())
@@ -345,7 +380,7 @@
},
`is`(true)
)
- }.compilesWithoutError()
+ }
}
}
@@ -356,8 +391,9 @@
Triple(COMMON.RX3_FLOWABLE, COMMON.RX3_ROOM, RxJava3TypeNames.FLOWABLE)
).forEach { (rxTypeSrc, rxRoomSrc, rxTypeClassName) ->
@Suppress("CHANGING_ARGUMENTS_EXECUTION_ORDER_FOR_NAMED_VARARGS")
- simpleRun(jfos = arrayOf(COMMON.PUBLISHER, rxTypeSrc, rxRoomSrc)) {
- invocation ->
+ runProcessorTest(
+ sources = listOf(COMMON.PUBLISHER, rxTypeSrc, rxRoomSrc).toSources()
+ ) { invocation ->
val flowable = invocation.processingEnv.requireTypeElement(rxTypeClassName)
assertThat(
RxQueryResultBinderProvider.getAll(invocation.context).any {
@@ -365,7 +401,7 @@
},
`is`(true)
)
- }.compilesWithoutError()
+ }
}
}
@@ -376,8 +412,9 @@
Triple(COMMON.RX3_OBSERVABLE, COMMON.RX3_ROOM, RxJava3TypeNames.OBSERVABLE)
).forEach { (rxTypeSrc, rxRoomSrc, rxTypeClassName) ->
@Suppress("CHANGING_ARGUMENTS_EXECUTION_ORDER_FOR_NAMED_VARARGS")
- simpleRun(jfos = arrayOf(rxTypeSrc, rxRoomSrc)) {
- invocation ->
+ runProcessorTest(
+ sources = listOf(rxTypeSrc, rxRoomSrc).toSources()
+ ) { invocation ->
val observable = invocation.processingEnv.requireTypeElement(rxTypeClassName)
assertThat(observable, notNullValue())
assertThat(
@@ -386,7 +423,7 @@
},
`is`(true)
)
- }.compilesWithoutError()
+ }
}
}
@@ -397,8 +434,7 @@
Triple(COMMON.RX3_SINGLE, COMMON.RX3_ROOM, RxJava3TypeNames.SINGLE)
).forEach { (rxTypeSrc, _, rxTypeClassName) ->
@Suppress("CHANGING_ARGUMENTS_EXECUTION_ORDER_FOR_NAMED_VARARGS")
- simpleRun(jfos = arrayOf(rxTypeSrc)) {
- invocation ->
+ runProcessorTest(sources = listOf(rxTypeSrc).toSources()) { invocation ->
val single = invocation.processingEnv.requireTypeElement(rxTypeClassName)
assertThat(single, notNullValue())
assertThat(
@@ -407,7 +443,7 @@
},
`is`(true)
)
- }.compilesWithoutError()
+ }
}
}
@@ -417,9 +453,7 @@
Triple(COMMON.RX2_MAYBE, COMMON.RX2_ROOM, RxJava2TypeNames.MAYBE),
Triple(COMMON.RX3_MAYBE, COMMON.RX3_ROOM, RxJava3TypeNames.MAYBE)
).forEach { (rxTypeSrc, _, rxTypeClassName) ->
- @Suppress("CHANGING_ARGUMENTS_EXECUTION_ORDER_FOR_NAMED_VARARGS")
- simpleRun(jfos = arrayOf(rxTypeSrc)) {
- invocation ->
+ runProcessorTest(sources = listOf(rxTypeSrc).toSources()) { invocation ->
val maybe = invocation.processingEnv.requireTypeElement(rxTypeClassName)
assertThat(
RxCallableInsertMethodBinderProvider.getAll(invocation.context).any {
@@ -427,7 +461,7 @@
},
`is`(true)
)
- }.compilesWithoutError()
+ }
}
}
@@ -437,9 +471,7 @@
Triple(COMMON.RX2_COMPLETABLE, COMMON.RX2_ROOM, RxJava2TypeNames.COMPLETABLE),
Triple(COMMON.RX3_COMPLETABLE, COMMON.RX3_ROOM, RxJava3TypeNames.COMPLETABLE)
).forEach { (rxTypeSrc, _, rxTypeClassName) ->
- @Suppress("CHANGING_ARGUMENTS_EXECUTION_ORDER_FOR_NAMED_VARARGS")
- simpleRun(jfos = arrayOf(rxTypeSrc)) {
- invocation ->
+ runProcessorTest(sources = listOf(rxTypeSrc).toSources()) { invocation ->
val completable = invocation.processingEnv.requireTypeElement(rxTypeClassName)
assertThat(
RxCallableInsertMethodBinderProvider.getAll(invocation.context).any {
@@ -447,14 +479,13 @@
},
`is`(true)
)
- }.compilesWithoutError()
+ }
}
}
@Test
fun testFindInsertListenableFuture() {
- @Suppress("CHANGING_ARGUMENTS_EXECUTION_ORDER_FOR_NAMED_VARARGS")
- simpleRun(jfos = arrayOf(COMMON.LISTENABLE_FUTURE)) {
+ runProcessorTest(sources = listOf(COMMON.LISTENABLE_FUTURE).toSources()) {
invocation ->
val future = invocation.processingEnv
.requireTypeElement(GuavaUtilConcurrentTypeNames.LISTENABLE_FUTURE)
@@ -464,14 +495,12 @@
),
`is`(true)
)
- }.compilesWithoutError()
+ }
}
@Test
fun testFindDeleteOrUpdateSingle() {
- @Suppress("CHANGING_ARGUMENTS_EXECUTION_ORDER_FOR_NAMED_VARARGS")
- simpleRun(jfos = arrayOf(COMMON.RX2_SINGLE)) {
- invocation ->
+ runProcessorTest(sources = listOf(COMMON.RX2_SINGLE).toSources()) { invocation ->
val single = invocation.processingEnv.requireTypeElement(RxJava2TypeNames.SINGLE)
assertThat(single, notNullValue())
assertThat(
@@ -480,13 +509,12 @@
},
`is`(true)
)
- }.compilesWithoutError()
+ }
}
@Test
fun testFindDeleteOrUpdateMaybe() {
- @Suppress("CHANGING_ARGUMENTS_EXECUTION_ORDER_FOR_NAMED_VARARGS")
- simpleRun(jfos = arrayOf(COMMON.RX2_MAYBE)) {
+ runProcessorTest(sources = listOf(COMMON.RX2_MAYBE).toSources()) {
invocation ->
val maybe = invocation.processingEnv.requireTypeElement(RxJava2TypeNames.MAYBE)
assertThat(maybe, notNullValue())
@@ -496,13 +524,12 @@
},
`is`(true)
)
- }.compilesWithoutError()
+ }
}
@Test
fun testFindDeleteOrUpdateCompletable() {
- @Suppress("CHANGING_ARGUMENTS_EXECUTION_ORDER_FOR_NAMED_VARARGS")
- simpleRun(jfos = arrayOf(COMMON.RX2_COMPLETABLE)) {
+ runProcessorTest(sources = listOf(COMMON.RX2_COMPLETABLE).toSources()) {
invocation ->
val completable = invocation.processingEnv
.requireTypeElement(RxJava2TypeNames.COMPLETABLE)
@@ -513,14 +540,14 @@
},
`is`(true)
)
- }.compilesWithoutError()
+ }
}
@Test
fun testFindDeleteOrUpdateListenableFuture() {
- @Suppress("CHANGING_ARGUMENTS_EXECUTION_ORDER_FOR_NAMED_VARARGS")
- simpleRun(jfos = arrayOf(COMMON.LISTENABLE_FUTURE)) {
- invocation ->
+ runProcessorTest(
+ sources = listOf(COMMON.LISTENABLE_FUTURE).toSources()
+ ) { invocation ->
val future = invocation.processingEnv
.requireTypeElement(GuavaUtilConcurrentTypeNames.LISTENABLE_FUTURE)
assertThat(future, notNullValue())
@@ -529,14 +556,14 @@
.matches(future.asDeclaredType()),
`is`(true)
)
- }.compilesWithoutError()
+ }
}
@Test
fun testFindLiveData() {
- @Suppress("CHANGING_ARGUMENTS_EXECUTION_ORDER_FOR_NAMED_VARARGS")
- simpleRun(jfos = arrayOf(COMMON.COMPUTABLE_LIVE_DATA, COMMON.LIVE_DATA)) {
- invocation ->
+ runProcessorTest(
+ sources = listOf(COMMON.COMPUTABLE_LIVE_DATA, COMMON.LIVE_DATA).toSources()
+ ) { invocation ->
val liveData = invocation.processingEnv
.requireTypeElement(LifecyclesTypeNames.LIVE_DATA)
assertThat(liveData, notNullValue())
@@ -546,12 +573,12 @@
),
`is`(true)
)
- }.compilesWithoutError()
+ }
}
@Test
fun findPagingSourceIntKey() {
- simpleRun { invocation ->
+ runProcessorTest { invocation ->
val pagingSourceElement = invocation.processingEnv
.requireTypeElement(PagingSource::class)
val intType = invocation.processingEnv.requireType(Integer::class)
@@ -569,7 +596,7 @@
@Test
fun findPagingSourceStringKey() {
- simpleRun { invocation ->
+ runProcessorTest { invocation ->
val pagingSourceElement = invocation.processingEnv
.requireTypeElement(PagingSource::class)
val stringType = invocation.processingEnv.requireType(String::class)
@@ -582,12 +609,15 @@
.matches(pagingSourceIntIntType.asDeclaredType()),
`is`(true)
)
- }.failsToCompile().withErrorContaining(ProcessorErrors.PAGING_SPECIFY_PAGING_SOURCE_TYPE)
+ invocation.assertCompilationResult {
+ hasError(ProcessorErrors.PAGING_SPECIFY_PAGING_SOURCE_TYPE)
+ }
+ }
}
@Test
fun findDataSource() {
- simpleRun {
+ runProcessorTest {
invocation ->
val dataSource = invocation.processingEnv.requireTypeElement(DataSource::class)
assertThat(dataSource, notNullValue())
@@ -597,12 +627,15 @@
),
`is`(true)
)
- }.failsToCompile().withErrorContaining(ProcessorErrors.PAGING_SPECIFY_DATA_SOURCE_TYPE)
+ invocation.assertCompilationResult {
+ hasError(ProcessorErrors.PAGING_SPECIFY_DATA_SOURCE_TYPE)
+ }
+ }
}
@Test
fun findPositionalDataSource() {
- simpleRun {
+ runProcessorTest {
invocation ->
@Suppress("DEPRECATION")
val dataSource = invocation.processingEnv
@@ -614,13 +647,12 @@
),
`is`(true)
)
- }.compilesWithoutError()
+ }
}
@Test
fun findDataSourceFactory() {
- @Suppress("CHANGING_ARGUMENTS_EXECUTION_ORDER_FOR_NAMED_VARARGS")
- simpleRun(jfos = arrayOf(COMMON.DATA_SOURCE_FACTORY)) {
+ runProcessorTest(sources = listOf(COMMON.DATA_SOURCE_FACTORY).toSources()) {
invocation ->
val pagedListProvider = invocation.processingEnv
.requireTypeElement(PagingTypeNames.DATA_SOURCE_FACTORY)
@@ -631,14 +663,13 @@
),
`is`(true)
)
- }.compilesWithoutError()
+ }
}
- private fun createIntListToStringBinders(invocation: TestInvocation): List<TypeConverter> {
+ private fun createIntListToStringBinders(invocation: XTestInvocation): List<TypeConverter> {
val intType = invocation.processingEnv.requireType(Integer::class)
val listElement = invocation.processingEnv.requireTypeElement(java.util.List::class)
val listOfInts = invocation.processingEnv.getDeclaredType(listElement, intType)
-
val intListConverter = object : TypeConverter(
listOfInts,
invocation.context.COMMON_TYPES.STRING
@@ -676,53 +707,6 @@
return listOf(intListConverter, stringToIntListConverter)
}
- fun singleRun(handler: (TestInvocation) -> Unit): CompileTester {
- return Truth.assertAbout(JavaSourcesSubjectFactory.javaSources())
- .that(
- listOf(
- JavaFileObjects.forSourceString(
- "foo.bar.DummyClass",
- """
- package foo.bar;
- import androidx.room.*;
- @Entity
- public class DummyClass {}
- """
- ),
- JavaFileObjects.forSourceString(
- "foo.bar.Point",
- """
- package foo.bar;
- import androidx.room.*;
- @Entity
- public class Point {
- public int x, y;
- public Point(int x, int y) {
- this.x = x;
- this.y = y;
- }
- public static Point fromBoolean(boolean val) {
- return val ? new Point(1, 1) : new Point(0, 0);
- }
- public static boolean toBoolean(Point point) {
- return point.x > 0;
- }
- }
- """
- )
- )
- )
- .processedWith(
- TestProcessor.builder()
- .forAnnotations(Entity::class)
- .nextRunHandler { invocation ->
- handler(invocation)
- true
- }
- .build()
- )
- }
-
fun pointTypeConverters(env: XProcessingEnv): List<TypeConverter> {
val tPoint = env.requireType("foo.bar.Point")
val tBoolean = env.requireType(TypeName.BOOLEAN)
@@ -759,8 +743,8 @@
}
fun dateTypeConverters(env: XProcessingEnv): List<TypeConverter> {
- val tDate = env.requireType("java.util.Date")
- val tLong = env.requireType("java.lang.Long")
+ val tDate = env.requireType("java.util.Date").makeNullable()
+ val tLong = env.requireType("java.lang.Long").makeNullable()
return listOf(
object : TypeConverter(tDate, tLong) {
override fun convert(
diff --git a/room/compiler/src/test/kotlin/androidx/room/testing/InProcessorTest.kt b/room/compiler/src/test/kotlin/androidx/room/testing/InProcessorTest.kt
index 2d00be6..25c629a 100644
--- a/room/compiler/src/test/kotlin/androidx/room/testing/InProcessorTest.kt
+++ b/room/compiler/src/test/kotlin/androidx/room/testing/InProcessorTest.kt
@@ -16,46 +16,37 @@
package androidx.room.testing
-import androidx.room.Query
-import com.google.common.truth.Truth
-import com.google.testing.compile.JavaFileObjects
-import com.google.testing.compile.JavaSourceSubjectFactory
-import org.hamcrest.CoreMatchers.`is`
-import org.hamcrest.MatcherAssert.assertThat
+import androidx.room.compiler.processing.util.Source
+import androidx.room.compiler.processing.util.runProcessorTest
+import com.google.common.truth.Truth.assertThat
import org.junit.Test
import org.junit.runner.RunWith
import org.junit.runners.JUnit4
-import java.util.concurrent.atomic.AtomicBoolean
@RunWith(JUnit4::class)
class InProcessorTest {
@Test
fun testInProcessorTestRuns() {
- val didRun = AtomicBoolean(false)
- Truth.assertAbout(JavaSourceSubjectFactory.javaSource())
- .that(
- JavaFileObjects.forSourceString(
- "foo.bar.MyClass",
- """
- package foo.bar;
- abstract public class MyClass {
- @androidx.room.Query("foo")
- abstract public void setFoo(String foo);
- }
- """
- )
- )
- .processedWith(
- TestProcessor.builder()
- .nextRunHandler { invocation ->
- didRun.set(true)
- assertThat(invocation.annotations.size, `is`(1))
- true
- }
- .forAnnotations(Query::class)
- .build()
- )
- .compilesWithoutError()
- assertThat(didRun.get(), `is`(true))
+ val source = Source.java(
+ qName = "foo.bar.MyClass",
+ code = """
+ package foo.bar;
+ abstract public class MyClass {
+ @androidx.room.Query("foo")
+ abstract public void setFoo(String foo);
+ }
+ """.trimIndent()
+ )
+ var runCount = 0
+ runProcessorTest(sources = listOf(source)) {
+ assertThat(
+ it.processingEnv.findTypeElement("foo.bar.MyClass")
+ ).isNotNull()
+ runCount++
+ }
+ // run 3 times: javac, kapt, ksp
+ assertThat(
+ runCount
+ ).isEqualTo(3)
}
}
diff --git a/room/compiler/src/test/kotlin/androidx/room/testing/XTestInvocationExt.kt b/room/compiler/src/test/kotlin/androidx/room/testing/XTestInvocationExt.kt
new file mode 100644
index 0000000..62e386a
--- /dev/null
+++ b/room/compiler/src/test/kotlin/androidx/room/testing/XTestInvocationExt.kt
@@ -0,0 +1,25 @@
+/*
+ * Copyright 2020 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.testing
+
+import androidx.room.compiler.processing.util.XTestInvocation
+import androidx.room.processor.Context
+
+val XTestInvocation.context
+ get() = getOrPutUserData(Context::class) {
+ Context(processingEnv)
+ }
\ No newline at end of file
diff --git a/room/compiler/src/test/kotlin/androidx/room/testing/test_util.kt b/room/compiler/src/test/kotlin/androidx/room/testing/test_util.kt
index b186bff..febe6e2 100644
--- a/room/compiler/src/test/kotlin/androidx/room/testing/test_util.kt
+++ b/room/compiler/src/test/kotlin/androidx/room/testing/test_util.kt
@@ -19,6 +19,7 @@
import androidx.room.compiler.processing.XElement
import androidx.room.compiler.processing.XFieldElement
import androidx.room.compiler.processing.XType
+import androidx.room.compiler.processing.util.Source
import androidx.room.ext.GuavaUtilConcurrentTypeNames
import androidx.room.ext.KotlinTypeNames
import androidx.room.ext.LifecyclesTypeNames
@@ -314,4 +315,25 @@
return System.getProperty("java.class.path")!!.split(pathSeparator).map { File(it) }.toSet()
}
-fun String.toJFO(qName: String): JavaFileObject = JavaFileObjects.forSourceLines(qName, this)
\ No newline at end of file
+fun String.toJFO(qName: String): JavaFileObject = JavaFileObjects.forSourceLines(qName, this)
+
+/**
+ * Convenience method to convert JFO's to the Source objects in XProcessing so that we can
+ * convert room tests to the common API w/o major code refactor
+ */
+fun JavaFileObject.toSource(): Source {
+ val uri = this.toUri()
+ // parse name from uri
+ val contents = this.openReader(true).use {
+ it.readText()
+ }
+ val qName = uri.path.replace('/', '.')
+ val javaExt = ".java"
+ check(qName.endsWith(javaExt)) {
+ "expected a java source file, $qName does not seem like one"
+ }
+
+ return Source.java(qName.dropLast(javaExt.length), contents)
+}
+
+fun Collection<JavaFileObject>.toSources() = map { it.toSource() }