diff --git a/kotlin/codegen/pom.xml b/kotlin/codegen/pom.xml
index 566b578..21bda8e 100644
--- a/kotlin/codegen/pom.xml
+++ b/kotlin/codegen/pom.xml
@@ -25,7 +25,7 @@
com.squareup
kotlinpoet
- 1.3.0
+ ${kotlinpoet.version}
net.ltgt.gradle.incap
@@ -37,12 +37,12 @@
com.google.auto
auto-common
- 0.10
+ ${auto-common.version}
com.google.auto.service
auto-service-annotations
- ${autoservice.version}
+ ${auto-service.version}
provided
true
@@ -56,32 +56,31 @@
assertj-core
test
+
+ com.google.truth
+ truth
+ ${truth.version}
+ test
+
-
- org.jetbrains.kotlin
- kotlin-compiler-embeddable
- test
-
-
- org.jetbrains.kotlin
- kotlin-annotation-processing-embeddable
- test
-
me.eugeniomarletti.kotlin.metadata
kotlin-metadata
-
- com.google.testing.compile
- compile-testing
+ com.github.tschuchortdev
+ kotlin-compile-testing
+ ${kotlin-compile-testing.version}
+ test
+
+
+ com.squareup.okio
+ okio
+ ${okio2.version}
test
@@ -111,7 +110,7 @@
com.google.auto.service
auto-service
- ${autoservice.version}
+ ${auto-service.version}
net.ltgt.gradle.incap
diff --git a/kotlin/codegen/src/test/java/com/squareup/moshi/kotlin/codegen/JsonClassCodegenProcessorTest.kt b/kotlin/codegen/src/test/java/com/squareup/moshi/kotlin/codegen/JsonClassCodegenProcessorTest.kt
index 99896ea..f60200c 100644
--- a/kotlin/codegen/src/test/java/com/squareup/moshi/kotlin/codegen/JsonClassCodegenProcessorTest.kt
+++ b/kotlin/codegen/src/test/java/com/squareup/moshi/kotlin/codegen/JsonClassCodegenProcessorTest.kt
@@ -15,384 +15,352 @@
*/
package com.squareup.moshi.kotlin.codegen
+import com.tschuchort.compiletesting.KotlinCompilation
+import com.tschuchort.compiletesting.SourceFile
+import com.tschuchort.compiletesting.SourceFile.Companion.kotlin
import org.assertj.core.api.Assertions.assertThat
-import org.jetbrains.kotlin.cli.common.ExitCode
import org.junit.Ignore
import org.junit.Rule
import org.junit.Test
import org.junit.rules.TemporaryFolder
-import javax.annotation.processing.Processor
/** Execute kotlinc to confirm that either files are generated or errors are printed. */
class JsonClassCodegenProcessorTest {
@Rule @JvmField var temporaryFolder: TemporaryFolder = TemporaryFolder()
@Test fun privateConstructor() {
- val call = KotlinCompilerCall(temporaryFolder.root)
- call.inheritClasspath = true
- call.addService(Processor::class, JsonClassCodegenProcessor::class)
- call.addKt("source.kt", """
- |import com.squareup.moshi.JsonClass
- |
- |@JsonClass(generateAdapter = true)
- |class PrivateConstructor private constructor(var a: Int, var b: Int) {
- | fun a() = a
- | fun b() = b
- | companion object {
- | fun newInstance(a: Int, b: Int) = PrivateConstructor(a, b)
- | }
- |}
- |""".trimMargin())
-
- val result = call.execute()
- assertThat(result.exitCode).isEqualTo(ExitCode.COMPILATION_ERROR)
- assertThat(result.systemErr).contains("constructor is not internal or public")
+ val result = compile(kotlin("source.kt",
+ """
+ import com.squareup.moshi.JsonClass
+
+ @JsonClass(generateAdapter = true)
+ class PrivateConstructor private constructor(var a: Int, var b: Int) {
+ fun a() = a
+ fun b() = b
+ companion object {
+ fun newInstance(a: Int, b: Int) = PrivateConstructor(a, b)
+ }
+ }
+ """
+ ))
+ assertThat(result.exitCode).isEqualTo(KotlinCompilation.ExitCode.COMPILATION_ERROR)
+ assertThat(result.messages).contains("constructor is not internal or public")
}
@Test fun privateConstructorParameter() {
- val call = KotlinCompilerCall(temporaryFolder.root)
- call.inheritClasspath = true
- call.addService(Processor::class, JsonClassCodegenProcessor::class)
- call.addKt("source.kt", """
- |import com.squareup.moshi.JsonClass
- |
- |@JsonClass(generateAdapter = true)
- |class PrivateConstructorParameter(private var a: Int)
- |""".trimMargin())
+ val result = compile(kotlin("source.kt",
+ """
+ import com.squareup.moshi.JsonClass
- val result = call.execute()
- assertThat(result.exitCode).isEqualTo(ExitCode.COMPILATION_ERROR)
- assertThat(result.systemErr).contains("property a is not visible")
+ @JsonClass(generateAdapter = true)
+ class PrivateConstructorParameter(private var a: Int)
+ """
+ ))
+ assertThat(result.exitCode).isEqualTo(KotlinCompilation.ExitCode.COMPILATION_ERROR)
+ assertThat(result.messages).contains("property a is not visible")
}
@Test fun privateProperties() {
- val call = KotlinCompilerCall(temporaryFolder.root)
- call.inheritClasspath = true
- call.addService(Processor::class, JsonClassCodegenProcessor::class)
- call.addKt("source.kt", """
- |import com.squareup.moshi.JsonClass
- |
- |@JsonClass(generateAdapter = true)
- |class PrivateProperties {
- | private var a: Int = -1
- | private var b: Int = -1
- |}
- |""".trimMargin())
+ val result = compile(kotlin("source.kt",
+ """
+ import com.squareup.moshi.JsonClass
- val result = call.execute()
- assertThat(result.exitCode).isEqualTo(ExitCode.COMPILATION_ERROR)
- assertThat(result.systemErr).contains("property a is not visible")
+ @JsonClass(generateAdapter = true)
+ class PrivateProperties {
+ private var a: Int = -1
+ private var b: Int = -1
+ }
+ """
+ ))
+ assertThat(result.exitCode).isEqualTo(KotlinCompilation.ExitCode.COMPILATION_ERROR)
+ assertThat(result.messages).contains("property a is not visible")
}
@Test fun interfacesNotSupported() {
- val call = KotlinCompilerCall(temporaryFolder.root)
- call.inheritClasspath = true
- call.addService(Processor::class, JsonClassCodegenProcessor::class)
- call.addKt("source.kt", """
- |import com.squareup.moshi.JsonClass
- |
- |@JsonClass(generateAdapter = true)
- |interface Interface
- |""".trimMargin())
+ val result = compile(kotlin("source.kt",
+ """
+ import com.squareup.moshi.JsonClass
- val result = call.execute()
- assertThat(result.exitCode).isEqualTo(ExitCode.COMPILATION_ERROR)
- assertThat(result.systemErr).contains(
+ @JsonClass(generateAdapter = true)
+ interface Interface
+ """
+ ))
+ assertThat(result.exitCode).isEqualTo(KotlinCompilation.ExitCode.COMPILATION_ERROR)
+ assertThat(result.messages).contains(
"error: @JsonClass can't be applied to Interface: must be a Kotlin class")
}
- @Test fun abstractClassesNotSupported() {
- val call = KotlinCompilerCall(temporaryFolder.root)
- call.inheritClasspath = true
- call.addService(Processor::class, JsonClassCodegenProcessor::class)
- call.addKt("source.kt", """
- |import com.squareup.moshi.JsonClass
- |
- |@JsonClass(generateAdapter = true)
- |abstract class AbstractClass(val a: Int)
- |""".trimMargin())
+ @Test fun interfacesDoNotErrorWhenGeneratorNotSet() {
+ val result = compile(kotlin("source.kt",
+ """
+ import com.squareup.moshi.JsonClass
- val result = call.execute()
- assertThat(result.exitCode).isEqualTo(ExitCode.COMPILATION_ERROR)
- assertThat(result.systemErr).contains(
+ @JsonClass(generateAdapter = true, generator="customGenerator")
+ interface Interface
+ """
+ ))
+ assertThat(result.exitCode).isEqualTo(KotlinCompilation.ExitCode.OK)
+ }
+
+ @Test fun abstractClassesNotSupported() {
+ val result = compile(kotlin("source.kt",
+ """
+ import com.squareup.moshi.JsonClass
+
+ @JsonClass(generateAdapter = true)
+ abstract class AbstractClass(val a: Int)
+ """
+ ))
+ assertThat(result.exitCode).isEqualTo(KotlinCompilation.ExitCode.COMPILATION_ERROR)
+ assertThat(result.messages).contains(
"error: @JsonClass can't be applied to AbstractClass: must not be abstract")
}
@Test fun sealedClassesNotSupported() {
- val call = KotlinCompilerCall(temporaryFolder.root)
- call.inheritClasspath = true
- call.addService(Processor::class, JsonClassCodegenProcessor::class)
- call.addKt("source.kt", """
- |import com.squareup.moshi.JsonClass
- |
- |@JsonClass(generateAdapter = true)
- |sealed class SealedClass(val a: Int)
- |""".trimMargin())
-
- val result = call.execute()
- assertThat(result.exitCode).isEqualTo(ExitCode.COMPILATION_ERROR)
- assertThat(result.systemErr).contains(
+ val result = compile(kotlin("source.kt",
+ """
+ import com.squareup.moshi.JsonClass
+
+ @JsonClass(generateAdapter = true)
+ sealed class SealedClass(val a: Int)
+ """
+ ))
+ assertThat(result.exitCode).isEqualTo(KotlinCompilation.ExitCode.COMPILATION_ERROR)
+ assertThat(result.messages).contains(
"error: @JsonClass can't be applied to SealedClass: must not be sealed")
}
@Test fun innerClassesNotSupported() {
- val call = KotlinCompilerCall(temporaryFolder.root)
- call.inheritClasspath = true
- call.addService(Processor::class, JsonClassCodegenProcessor::class)
- call.addKt("source.kt", """
- |import com.squareup.moshi.JsonClass
- |
- |class Outer {
- | @JsonClass(generateAdapter = true)
- | inner class InnerClass(val a: Int)
- |}
- |""".trimMargin())
-
- val result = call.execute()
- assertThat(result.exitCode).isEqualTo(ExitCode.COMPILATION_ERROR)
- assertThat(result.systemErr).contains(
+ val result = compile(kotlin("source.kt",
+ """
+ import com.squareup.moshi.JsonClass
+
+ class Outer {
+ @JsonClass(generateAdapter = true)
+ inner class InnerClass(val a: Int)
+ }
+ """
+ ))
+ assertThat(result.exitCode).isEqualTo(KotlinCompilation.ExitCode.COMPILATION_ERROR)
+ assertThat(result.messages).contains(
"error: @JsonClass can't be applied to Outer.InnerClass: must not be an inner class")
}
@Test fun enumClassesNotSupported() {
- val call = KotlinCompilerCall(temporaryFolder.root)
- call.inheritClasspath = true
- call.addService(Processor::class, JsonClassCodegenProcessor::class)
- call.addKt("source.kt", """
- |import com.squareup.moshi.JsonClass
- |
- |@JsonClass(generateAdapter = true)
- |enum class KotlinEnum {
- | A, B
- |}
- |""".trimMargin())
-
- val result = call.execute()
- assertThat(result.exitCode).isEqualTo(ExitCode.COMPILATION_ERROR)
- assertThat(result.systemErr).contains(
+ val result = compile(kotlin("source.kt",
+ """
+ import com.squareup.moshi.JsonClass
+
+ @JsonClass(generateAdapter = true)
+ enum class KotlinEnum {
+ A, B
+ }
+ """
+ ))
+ assertThat(result.exitCode).isEqualTo(KotlinCompilation.ExitCode.COMPILATION_ERROR)
+ assertThat(result.messages).contains(
"error: @JsonClass with 'generateAdapter = \"true\"' can't be applied to KotlinEnum: code gen for enums is not supported or necessary")
}
// Annotation processors don't get called for local classes, so we don't have the opportunity to
// print an error message. Instead local classes will fail at runtime.
- @Ignore
- @Test fun localClassesNotSupported() {
- val call = KotlinCompilerCall(temporaryFolder.root)
- call.inheritClasspath = true
- call.addService(Processor::class, JsonClassCodegenProcessor::class)
- call.addKt("source.kt", """
- |import com.squareup.moshi.JsonClass
- |
- |fun outer() {
- | @JsonClass(generateAdapter = true)
- | class LocalClass(val a: Int)
- |}
- |""".trimMargin())
-
- val result = call.execute()
- assertThat(result.exitCode).isEqualTo(ExitCode.COMPILATION_ERROR)
- assertThat(result.systemErr).contains(
+ @Ignore @Test fun localClassesNotSupported() {
+ val result = compile(kotlin("source.kt",
+ """
+ import com.squareup.moshi.JsonClass
+
+ fun outer() {
+ @JsonClass(generateAdapter = true)
+ class LocalClass(val a: Int)
+ }
+ """
+ ))
+ assertThat(result.exitCode).isEqualTo(KotlinCompilation.ExitCode.COMPILATION_ERROR)
+ assertThat(result.messages).contains(
"error: @JsonClass can't be applied to LocalClass: must not be local")
}
@Test fun objectDeclarationsNotSupported() {
- val call = KotlinCompilerCall(temporaryFolder.root)
- call.inheritClasspath = true
- call.addService(Processor::class, JsonClassCodegenProcessor::class)
- call.addKt("source.kt", """
- |import com.squareup.moshi.JsonClass
- |
- |@JsonClass(generateAdapter = true)
- |object ObjectDeclaration {
- | var a = 5
- |}
- |""".trimMargin())
- val result = call.execute()
- assertThat(result.exitCode).isEqualTo(ExitCode.COMPILATION_ERROR)
- assertThat(result.systemErr).contains(
+ val result = compile(kotlin("source.kt",
+ """
+ import com.squareup.moshi.JsonClass
+
+ @JsonClass(generateAdapter = true)
+ object ObjectDeclaration {
+ var a = 5
+ }
+ """
+ ))
+ assertThat(result.exitCode).isEqualTo(KotlinCompilation.ExitCode.COMPILATION_ERROR)
+ assertThat(result.messages).contains(
"error: @JsonClass can't be applied to ObjectDeclaration: must be a Kotlin class")
}
@Test fun objectExpressionsNotSupported() {
- val call = KotlinCompilerCall(temporaryFolder.root)
- call.inheritClasspath = true
- call.addService(Processor::class, JsonClassCodegenProcessor::class)
- call.addKt("source.kt", """
- |import com.squareup.moshi.JsonClass
- |
- |@JsonClass(generateAdapter = true)
- |val expression = object : Any() {
- | var a = 5
- |}
- |""".trimMargin())
-
- val result = call.execute()
- assertThat(result.exitCode).isEqualTo(ExitCode.COMPILATION_ERROR)
- assertThat(result.systemErr).contains(
+ val result = compile(kotlin("source.kt",
+ """
+ import com.squareup.moshi.JsonClass
+
+ @JsonClass(generateAdapter = true)
+ val expression = object : Any() {
+ var a = 5
+ }
+ """
+ ))
+ assertThat(result.exitCode).isEqualTo(KotlinCompilation.ExitCode.COMPILATION_ERROR)
+ assertThat(result.messages).contains(
"error: @JsonClass can't be applied to expression\$annotations(): must be a Kotlin class")
}
@Test fun requiredTransientConstructorParameterFails() {
- val call = KotlinCompilerCall(temporaryFolder.root)
- call.inheritClasspath = true
- call.addService(Processor::class, JsonClassCodegenProcessor::class)
- call.addKt("source.kt", """
- |import com.squareup.moshi.JsonClass
- |
- |@JsonClass(generateAdapter = true)
- |class RequiredTransientConstructorParameter(@Transient var a: Int)
- |""".trimMargin())
-
- val result = call.execute()
- assertThat(result.exitCode).isEqualTo(ExitCode.COMPILATION_ERROR)
- assertThat(result.systemErr).contains(
+ val result = compile(kotlin("source.kt",
+ """
+ import com.squareup.moshi.JsonClass
+
+ @JsonClass(generateAdapter = true)
+ class RequiredTransientConstructorParameter(@Transient var a: Int)
+ """
+ ))
+ assertThat(result.exitCode).isEqualTo(KotlinCompilation.ExitCode.COMPILATION_ERROR)
+ assertThat(result.messages).contains(
"error: No default value for transient property a")
}
@Test fun nonPropertyConstructorParameter() {
- val call = KotlinCompilerCall(temporaryFolder.root)
- call.inheritClasspath = true
- call.addService(Processor::class, JsonClassCodegenProcessor::class)
- call.addKt("source.kt", """
- |import com.squareup.moshi.JsonClass
- |
- |@JsonClass(generateAdapter = true)
- |class NonPropertyConstructorParameter(a: Int, val b: Int)
- |""".trimMargin())
-
- val result = call.execute()
- assertThat(result.exitCode).isEqualTo(ExitCode.COMPILATION_ERROR)
- assertThat(result.systemErr).contains(
+ val result = compile(kotlin("source.kt",
+ """
+ import com.squareup.moshi.JsonClass
+
+ import com.squareup.moshi.JsonClass
+ @JsonClass(generateAdapter = true)
+ class NonPropertyConstructorParameter(a: Int, val b: Int)
+ """
+ ))
+ assertThat(result.exitCode).isEqualTo(KotlinCompilation.ExitCode.COMPILATION_ERROR)
+ assertThat(result.messages).contains(
"error: No property for required constructor parameter a")
}
@Test fun badGeneratedAnnotation() {
- val call = KotlinCompilerCall(temporaryFolder.root)
- call.inheritClasspath = true
- call.addService(Processor::class, JsonClassCodegenProcessor::class)
- call.kaptArgs[JsonClassCodegenProcessor.OPTION_GENERATED] = "javax.annotation.GeneratedBlerg"
- call.addKt("source.kt", """
- |import com.squareup.moshi.JsonClass
- |
- |@JsonClass(generateAdapter = true)
- |data class Foo(val a: Int)
- |""".trimMargin())
-
- val result = call.execute()
- assertThat(result.exitCode).isEqualTo(ExitCode.COMPILATION_ERROR)
- assertThat(result.systemErr).contains(
+ val result = prepareCompilation(kotlin("source.kt",
+ """
+ import com.squareup.moshi.JsonClass
+
+ @JsonClass(generateAdapter = true)
+ data class Foo(val a: Int)
+ """
+ )).apply {
+ kaptArgs[JsonClassCodegenProcessor.OPTION_GENERATED] = "javax.annotation.GeneratedBlerg"
+ }.compile()
+ assertThat(result.messages).contains(
"Invalid option value for ${JsonClassCodegenProcessor.OPTION_GENERATED}")
}
@Test fun multipleErrors() {
- val call = KotlinCompilerCall(temporaryFolder.root)
- call.inheritClasspath = true
- call.addService(Processor::class, JsonClassCodegenProcessor::class)
- call.addKt("source.kt", """
- |import com.squareup.moshi.JsonClass
- |
- |@JsonClass(generateAdapter = true)
- |class Class1(private var a: Int, private var b: Int)
- |
- |@JsonClass(generateAdapter = true)
- |class Class2(private var c: Int)
- |""".trimMargin())
+ val result = compile(kotlin("source.kt",
+ """
+ import com.squareup.moshi.JsonClass
- val result = call.execute()
- assertThat(result.exitCode).isEqualTo(ExitCode.COMPILATION_ERROR)
- assertThat(result.systemErr).contains("property a is not visible")
- assertThat(result.systemErr).contains("property b is not visible")
- assertThat(result.systemErr).contains("property c is not visible")
+ @JsonClass(generateAdapter = true)
+ class Class1(private var a: Int, private var b: Int)
+
+ @JsonClass(generateAdapter = true)
+ class Class2(private var c: Int)
+ """
+ ))
+ assertThat(result.exitCode).isEqualTo(KotlinCompilation.ExitCode.COMPILATION_ERROR)
+ assertThat(result.messages).contains("property a is not visible")
+ assertThat(result.messages).contains("property c is not visible")
}
@Test fun extendPlatformType() {
- val call = KotlinCompilerCall(temporaryFolder.root)
- call.inheritClasspath = true
- call.addService(Processor::class, JsonClassCodegenProcessor::class)
- call.addKt("source.kt", """
- |import com.squareup.moshi.JsonClass
- |import java.util.Date
- |
- |@JsonClass(generateAdapter = true)
- |class ExtendsPlatformClass(var a: Int) : Date()
- |""".trimMargin())
+ val result = compile(kotlin("source.kt",
+ """
+ import com.squareup.moshi.JsonClass
+ import java.util.Date
- val result = call.execute()
- assertThat(result.exitCode).isEqualTo(ExitCode.COMPILATION_ERROR)
- assertThat(result.systemErr).contains("supertype java.util.Date is not a Kotlin type")
+ @JsonClass(generateAdapter = true)
+ class ExtendsPlatformClass(var a: Int) : Date()
+ """
+ ))
+ assertThat(result.messages).contains("supertype java.util.Date is not a Kotlin type")
}
@Test fun extendJavaType() {
- val call = KotlinCompilerCall(temporaryFolder.root)
- call.inheritClasspath = true
- call.addService(Processor::class, JsonClassCodegenProcessor::class)
- call.addKt("source.kt", """
- |import com.squareup.moshi.JsonClass
- |import com.squareup.moshi.kotlin.codegen.JavaSuperclass
- |
- |@JsonClass(generateAdapter = true)
- |class ExtendsJavaType(var b: Int) : JavaSuperclass()
- |""".trimMargin())
-
- val result = call.execute()
- assertThat(result.exitCode).isEqualTo(ExitCode.COMPILATION_ERROR)
- assertThat(result.systemErr)
+ val result = compile(kotlin("source.kt",
+ """
+ import com.squareup.moshi.JsonClass
+ import com.squareup.moshi.kotlin.codegen.JavaSuperclass
+
+ @JsonClass(generateAdapter = true)
+ class ExtendsJavaType(var b: Int) : JavaSuperclass()
+ """
+ ))
+ assertThat(result.exitCode).isEqualTo(KotlinCompilation.ExitCode.COMPILATION_ERROR)
+ assertThat(result.messages)
.contains("supertype com.squareup.moshi.kotlin.codegen.JavaSuperclass is not a Kotlin type")
}
- @Test
- fun nonFieldApplicableQualifier() {
- val call = KotlinCompilerCall(temporaryFolder.root)
- call.inheritClasspath = true
- call.addService(Processor::class, JsonClassCodegenProcessor::class)
- call.addKt("source.kt", """
- |import com.squareup.moshi.JsonClass
- |import com.squareup.moshi.JsonQualifier
- |import kotlin.annotation.AnnotationRetention.RUNTIME
- |import kotlin.annotation.AnnotationTarget.PROPERTY
- |import kotlin.annotation.Retention
- |import kotlin.annotation.Target
- |
- |@Retention(RUNTIME)
- |@Target(PROPERTY)
- |@JsonQualifier
- |annotation class UpperCase
- |
- |@JsonClass(generateAdapter = true)
- |class ClassWithQualifier(@UpperCase val a: Int)
- |""".trimMargin())
+ @Test fun nonFieldApplicableQualifier() {
+ val result = compile(kotlin("source.kt",
+ """
+ import com.squareup.moshi.JsonClass
+ import com.squareup.moshi.JsonQualifier
+ import kotlin.annotation.AnnotationRetention.RUNTIME
+ import kotlin.annotation.AnnotationTarget.PROPERTY
+ import kotlin.annotation.Retention
+ import kotlin.annotation.Target
- val result = call.execute()
- println(result.systemErr)
- assertThat(result.exitCode).isEqualTo(ExitCode.COMPILATION_ERROR)
- assertThat(result.systemErr).contains("JsonQualifier @UpperCase must support FIELD target")
+ @Retention(RUNTIME)
+ @Target(PROPERTY)
+ @JsonQualifier
+ annotation class UpperCase
+
+ @JsonClass(generateAdapter = true)
+ class ClassWithQualifier(@UpperCase val a: Int)
+ """
+ ))
+ assertThat(result.exitCode).isEqualTo(KotlinCompilation.ExitCode.COMPILATION_ERROR)
+ assertThat(result.messages).contains("JsonQualifier @UpperCase must support FIELD target")
}
- @Test
- fun nonRuntimeQualifier() {
- val call = KotlinCompilerCall(temporaryFolder.root)
- call.inheritClasspath = true
- call.addService(Processor::class, JsonClassCodegenProcessor::class)
- call.addKt("source.kt", """
- |import com.squareup.moshi.JsonClass
- |import com.squareup.moshi.JsonQualifier
- |import kotlin.annotation.AnnotationRetention.BINARY
- |import kotlin.annotation.AnnotationTarget.FIELD
- |import kotlin.annotation.AnnotationTarget.PROPERTY
- |import kotlin.annotation.Retention
- |import kotlin.annotation.Target
- |
- |@Retention(BINARY)
- |@Target(PROPERTY, FIELD)
- |@JsonQualifier
- |annotation class UpperCase
- |
- |@JsonClass(generateAdapter = true)
- |class ClassWithQualifier(@UpperCase val a: Int)
- |""".trimMargin())
+ @Test fun nonRuntimeQualifier() {
+ val result = compile(kotlin("source.kt",
+ """
+ import com.squareup.moshi.JsonClass
+ import com.squareup.moshi.JsonQualifier
+ import kotlin.annotation.AnnotationRetention.BINARY
+ import kotlin.annotation.AnnotationTarget.FIELD
+ import kotlin.annotation.AnnotationTarget.PROPERTY
+ import kotlin.annotation.Retention
+ import kotlin.annotation.Target
- val result = call.execute()
- assertThat(result.exitCode).isEqualTo(ExitCode.COMPILATION_ERROR)
- assertThat(result.systemErr).contains("JsonQualifier @UpperCase must have RUNTIME retention")
+ @Retention(BINARY)
+ @Target(PROPERTY, FIELD)
+ @JsonQualifier
+ annotation class UpperCase
+
+ @JsonClass(generateAdapter = true)
+ class ClassWithQualifier(@UpperCase val a: Int)
+ """
+ ))
+ assertThat(result.exitCode).isEqualTo(KotlinCompilation.ExitCode.COMPILATION_ERROR)
+ assertThat(result.messages).contains("JsonQualifier @UpperCase must have RUNTIME retention")
}
+
+ private fun prepareCompilation(vararg sourceFiles: SourceFile): KotlinCompilation {
+ return KotlinCompilation()
+ .apply {
+ workingDir = temporaryFolder.root
+ annotationProcessors = listOf(JsonClassCodegenProcessor())
+ inheritClassPath = true
+ sources = sourceFiles.asList()
+ verbose = false
+ }
+ }
+
+ private fun compile(vararg sourceFiles: SourceFile): KotlinCompilation.Result {
+ return prepareCompilation(*sourceFiles).compile()
+ }
+
}
diff --git a/kotlin/codegen/src/test/java/com/squareup/moshi/kotlin/codegen/KotlinCompilerCall.kt b/kotlin/codegen/src/test/java/com/squareup/moshi/kotlin/codegen/KotlinCompilerCall.kt
deleted file mode 100644
index 90a9567..0000000
--- a/kotlin/codegen/src/test/java/com/squareup/moshi/kotlin/codegen/KotlinCompilerCall.kt
+++ /dev/null
@@ -1,193 +0,0 @@
-/*
- * Copyright (C) 2018 Square, Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.squareup.moshi.kotlin.codegen
-
-import com.google.common.collect.LinkedHashMultimap
-import okio.Buffer
-import okio.Okio
-import org.jetbrains.kotlin.cli.common.CLITool
-import org.jetbrains.kotlin.cli.jvm.K2JVMCompiler
-import java.io.File
-import java.io.FileOutputStream
-import java.io.ObjectOutputStream
-import java.io.PrintStream
-import java.net.URLClassLoader
-import java.net.URLDecoder
-import java.util.zip.ZipEntry
-import java.util.zip.ZipOutputStream
-import kotlin.reflect.KClass
-
-/** Prepares an invocation of the Kotlin compiler. */
-class KotlinCompilerCall(var scratchDir: File) {
- val sourcesDir = File(scratchDir, "sources")
- val classesDir = File(scratchDir, "classes")
- val servicesJar = File(scratchDir, "services.jar")
-
- var inheritClasspath = false
-
- val args = mutableListOf()
- val kaptArgs = mutableMapOf()
- val classpath = mutableListOf()
- val services = LinkedHashMultimap.create, KClass<*>>()
-
- /** Adds a source file to be compiled. */
- fun addKt(path: String, source: String) {
- val sourceFile = File(sourcesDir, path)
- sourceFile.parentFile.mkdirs()
- Okio.buffer(Okio.sink(sourceFile)).use {
- it.writeUtf8(source)
- }
- }
-
- /** Adds a service like an annotation processor to make available to the compiler. */
- fun addService(serviceClass: KClass<*>, implementation: KClass<*>) {
- services.put(serviceClass, implementation)
- }
-
- fun execute(): KotlinCompilerResult {
- val fullArgs = mutableListOf()
- fullArgs.addAll(args)
-
- fullArgs.add("-d")
- fullArgs.add(classesDir.toString())
-
- val fullClasspath = fullClasspath()
- if (fullClasspath.isNotEmpty()) {
- fullArgs.add("-classpath")
- fullArgs.add(fullClasspath.joinToString(separator = ":"))
- }
-
- for (source in sourcesDir.listFiles()) {
- fullArgs.add(source.toString())
- }
-
- fullArgs.addAll(annotationProcessorArgs())
- if (kaptArgs.isNotEmpty()) {
- fullArgs.apply {
- add("-P")
- add("plugin:org.jetbrains.kotlin.kapt3:apoptions=${encodeOptions(kaptArgs)}")
- }
- }
-
- val systemErrBuffer = Buffer()
- val oldSystemErr = System.err
- System.setErr(PrintStream(systemErrBuffer.outputStream()))
- try {
- val exitCode = CLITool.doMainNoExit(K2JVMCompiler(), fullArgs.toTypedArray())
- val systemErr = systemErrBuffer.readUtf8()
- return KotlinCompilerResult(systemErr, exitCode)
- } finally {
- System.setErr(oldSystemErr)
- }
- }
-
- /** Returns arguments necessary to enable and configure kapt3. */
- private fun annotationProcessorArgs(): List {
- val kaptSourceDir = File(scratchDir, "kapt/sources")
- val kaptStubsDir = File(scratchDir, "kapt/stubs")
-
- return listOf(
- "-Xplugin=${kapt3Jar()}",
- "-P", "plugin:org.jetbrains.kotlin.kapt3:sources=$kaptSourceDir",
- "-P", "plugin:org.jetbrains.kotlin.kapt3:classes=$classesDir",
- "-P", "plugin:org.jetbrains.kotlin.kapt3:stubs=$kaptStubsDir",
- "-P", "plugin:org.jetbrains.kotlin.kapt3:apclasspath=$servicesJar",
- "-P", "plugin:org.jetbrains.kotlin.kapt3:correctErrorTypes=true"
- )
- }
-
- /** Returns the classpath to use when compiling code. */
- private fun fullClasspath(): List {
- val result = mutableListOf()
- result.addAll(classpath)
-
- // Copy over the classpath of the running application.
- if (inheritClasspath) {
- for (classpathFile in classpathFiles()) {
- result.add(classpathFile.toString())
- }
- }
-
- if (!services.isEmpty) {
- writeServicesJar()
- result.add(servicesJar.toString())
- }
-
- return result.toList()
- }
-
- /**
- * Generate a .jar file that holds ServiceManager registrations. Necessary because AutoService's
- * results might not be visible to this test.
- */
- private fun writeServicesJar() {
- ZipOutputStream(FileOutputStream(servicesJar)).use { zipOutputStream ->
- for (entry in services.asMap()) {
- zipOutputStream.putNextEntry(
- ZipEntry("META-INF/services/${entry.key.qualifiedName}"))
- val serviceFile = Okio.buffer(Okio.sink(zipOutputStream))
- for (implementation in entry.value) {
- serviceFile.writeUtf8(implementation.qualifiedName!!)
- serviceFile.writeUtf8("\n")
- }
- serviceFile.emit() // Don't close the entry; that closes the file.
- zipOutputStream.closeEntry()
- }
- }
- }
-
- /** Returns the files on the host process' classpath. */
- private fun classpathFiles(): List {
- val classLoader = JsonClassCodegenProcessorTest::class.java.classLoader
- if (classLoader !is URLClassLoader) {
- throw UnsupportedOperationException("unable to extract classpath from $classLoader")
- }
-
- val result = mutableListOf()
- for (url in classLoader.urLs) {
- if (url.protocol != "file") {
- throw UnsupportedOperationException("unable to handle classpath element $url")
- }
- result.add(File(URLDecoder.decode(url.path, "UTF-8")))
- }
- return result.toList()
- }
-
- /** Returns the path to the kotlin-annotation-processing .jar file. */
- private fun kapt3Jar(): File {
- for (file in classpathFiles()) {
- if (file.name.startsWith("kotlin-annotation-processing-embeddable")) return file
- }
- throw IllegalStateException("no kotlin-annotation-processing-embeddable jar on classpath:\n " +
- "${classpathFiles().joinToString(separator = "\n ")}}")
- }
-
- /**
- * Base64 encodes a mapping of annotation processor args for kapt, as specified by
- * https://kotlinlang.org/docs/reference/kapt.html#apjavac-options-encoding
- */
- private fun encodeOptions(options: Map): String {
- val buffer = Buffer()
- ObjectOutputStream(buffer.outputStream()).use { oos ->
- oos.writeInt(options.size)
- for ((key, value) in options.entries) {
- oos.writeUTF(key)
- oos.writeUTF(value)
- }
- }
- return buffer.readByteString().base64()
- }
-}
diff --git a/kotlin/codegen/src/test/java/com/squareup/moshi/kotlin/codegen/KotlinCompilerResult.kt b/kotlin/codegen/src/test/java/com/squareup/moshi/kotlin/codegen/KotlinCompilerResult.kt
deleted file mode 100644
index cb4dba0..0000000
--- a/kotlin/codegen/src/test/java/com/squareup/moshi/kotlin/codegen/KotlinCompilerResult.kt
+++ /dev/null
@@ -1,23 +0,0 @@
-/*
- * Copyright (C) 2018 Square, Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.squareup.moshi.kotlin.codegen
-
-import org.jetbrains.kotlin.cli.common.ExitCode
-
-class KotlinCompilerResult(
- val systemErr: String,
- var exitCode: ExitCode
-)
\ No newline at end of file
diff --git a/pom.xml b/pom.xml
index 62d5113..501a2e9 100644
--- a/pom.xml
+++ b/pom.xml
@@ -29,20 +29,25 @@
UTF-8
1.7
- 1.3.40
- 1.4.0
- 0.9.17
- 3.1.0
- 0.2
- 1.0-rc5
+ 0.10
+ 1.0-rc5
+ 0.9.17
+ 0.2
1.16.0
+ 2.1.0
+ 1.3.40
+ 1.3.0
+ 1.4.0
+ 3.1.0
+ 3.11.1
0.15
4.12
- 3.11.1
+ 1.2.2
+ 1.0