diff --git a/compiler-plugin/src/main/kotlin/com/google/devtools/ksp/processing/impl/ResolverImpl.kt b/compiler-plugin/src/main/kotlin/com/google/devtools/ksp/processing/impl/ResolverImpl.kt index 7c1fade23d..70bbf5f947 100644 --- a/compiler-plugin/src/main/kotlin/com/google/devtools/ksp/processing/impl/ResolverImpl.kt +++ b/compiler-plugin/src/main/kotlin/com/google/devtools/ksp/processing/impl/ResolverImpl.kt @@ -1054,7 +1054,7 @@ class ResolverImpl( val typeSubstitutor = containing.kotlinType.createTypeSubstitutor() val substituted = declaration.substitute(typeSubstitutor) as? ValueDescriptor substituted?.let { - return getKSTypeCached(substituted.type) + return getKSTypeCached(substituted.type, annotations = property.type.resolve().annotations) } } // if substitution fails, fallback to the type from the property diff --git a/compiler-plugin/src/main/kotlin/com/google/devtools/ksp/symbol/impl/kotlin/KSTypeImpl.kt b/compiler-plugin/src/main/kotlin/com/google/devtools/ksp/symbol/impl/kotlin/KSTypeImpl.kt index 9e8929a877..e6ca7235e9 100644 --- a/compiler-plugin/src/main/kotlin/com/google/devtools/ksp/symbol/impl/kotlin/KSTypeImpl.kt +++ b/compiler-plugin/src/main/kotlin/com/google/devtools/ksp/symbol/impl/kotlin/KSTypeImpl.kt @@ -97,12 +97,12 @@ class KSTypeImpl private constructor( override fun replace(arguments: List): KSType { return kotlinType.replaceTypeArguments(arguments)?.let { - getKSTypeCached(it, arguments) + getKSTypeCached(it, arguments, annotations) } ?: KSErrorType } override fun starProjection(): KSType { - return getKSTypeCached(kotlinType.replaceArgumentsWithStarProjections()) + return getKSTypeCached(kotlinType.replaceArgumentsWithStarProjections(), annotations = annotations) } private val meNullable: KSType by lazy { getKSTypeCached(kotlinType.makeNullable()) } diff --git a/compiler-plugin/src/test/kotlin/com/google/devtools/ksp/test/KSPCompilerPluginTest.kt b/compiler-plugin/src/test/kotlin/com/google/devtools/ksp/test/KSPCompilerPluginTest.kt index e970b5d731..40f68197c5 100644 --- a/compiler-plugin/src/test/kotlin/com/google/devtools/ksp/test/KSPCompilerPluginTest.kt +++ b/compiler-plugin/src/test/kotlin/com/google/devtools/ksp/test/KSPCompilerPluginTest.kt @@ -507,6 +507,12 @@ class KSPCompilerPluginTest : AbstractKSPCompilerPluginTest() { runTest("../test-utils/testData/api/typeAliasComparison.kt") } + @TestMetadata("typeAnnotation.kt") + @Test + fun testTypeAnnotation() { + runTest("../test-utils/testData/api/typeAnnotation.kt") + } + @TestMetadata("typeComposure.kt") @Test fun testTypeComposure() { diff --git a/gradle-plugin/src/main/kotlin/com/google/devtools/ksp/gradle/KotlinFactories.kt b/gradle-plugin/src/main/kotlin/com/google/devtools/ksp/gradle/KotlinFactories.kt index b112a2adf4..6be9ee3ab6 100644 --- a/gradle-plugin/src/main/kotlin/com/google/devtools/ksp/gradle/KotlinFactories.kt +++ b/gradle-plugin/src/main/kotlin/com/google/devtools/ksp/gradle/KotlinFactories.kt @@ -84,6 +84,12 @@ class KotlinFactories { // See [KotlinCompileConfig] in for details. // FIXME: make it configurable in upstream or support useClasspathSnapshot == true, if possible. kspTaskProvider.configure { + val compilerOptions = kotlinCompilation.compilerOptions.options as KotlinJvmCompilerOptions + KotlinJvmCompilerOptionsHelper.syncOptionsAsConvention( + from = compilerOptions, + into = it.compilerOptions + ) + if (it.classpathSnapshotProperties.useClasspathSnapshot.get()) { it.classpathSnapshotProperties.classpath.from(project.provider { it.libraries }) } @@ -100,6 +106,12 @@ class KotlinFactories { BaseKotlin2JsCompileConfig(KotlinCompilationInfo(kotlinCompilation)) .execute(kspTaskProvider as TaskProvider) kspTaskProvider.configure { + val compilerOptions = kotlinCompilation.compilerOptions.options as KotlinJsCompilerOptions + KotlinJsCompilerOptionsHelper.syncOptionsAsConvention( + from = compilerOptions, + into = it.compilerOptions + ) + it.incrementalJsKlib = false } } @@ -113,6 +125,15 @@ class KotlinFactories { return project.tasks.register(taskName, KspTaskMetadata::class.java).also { kspTaskProvider -> KotlinCompileCommonConfig(KotlinCompilationInfo(kotlinCompilation)) .execute(kspTaskProvider as TaskProvider) + + kspTaskProvider.configure { + val compilerOptions = + kotlinCompilation.compilerOptions.options as KotlinMultiplatformCommonCompilerOptions + KotlinMultiplatformCommonCompilerOptionsHelper.syncOptionsAsConvention( + from = compilerOptions, + into = it.compilerOptions + ) + } } } @@ -127,6 +148,12 @@ class KotlinFactories { KotlinCompilationInfo(kotlinCompilation) ).apply { configure { kspTask -> + val compilerOptions = kotlinCompilation.compilerOptions.options as KotlinNativeCompilerOptions + KotlinNativeCompilerOptionsHelper.syncOptionsAsConvention( + from = compilerOptions, + into = kspTask.compilerOptions + ) + kspTask.onlyIf { kspTask.konanTarget.enabledOnCurrentHost } diff --git a/gradle-plugin/src/main/kotlin/com/google/devtools/ksp/gradle/KspSubplugin.kt b/gradle-plugin/src/main/kotlin/com/google/devtools/ksp/gradle/KspSubplugin.kt index 5ff4598b5a..5ef3d1b5f7 100644 --- a/gradle-plugin/src/main/kotlin/com/google/devtools/ksp/gradle/KspSubplugin.kt +++ b/gradle-plugin/src/main/kotlin/com/google/devtools/ksp/gradle/KspSubplugin.kt @@ -400,7 +400,7 @@ class KspGradleSubplugin @Inject internal constructor(private val registry: Tool fun configureLanguageVersion(kspTask: KotlinCompilationTask<*>) { kspTask.compilerOptions.useK2.value(false) - kspTask.compilerOptions.languageVersion.orNull?.let { version -> + kotlinCompilation.compilerOptions.options.languageVersion.orNull?.let { version -> if (version >= KotlinVersion.KOTLIN_2_0) { kspTask.compilerOptions.languageVersion.value(LANGUAGE_VERSION) } @@ -419,15 +419,11 @@ class KspGradleSubplugin @Inject internal constructor(private val registry: Tool configureAsKspTask(kspTask, isIncremental) configureAsAbstractKotlinCompileTool(kspTask as AbstractKotlinCompileTool<*>) configurePluginOptions(kspTask) - kspTask.compilerOptions.noJdk.value(kotlinCompileTask.compilerOptions.noJdk) - kspTask.compilerOptions.verbose.convention(kotlinCompilation.compilerOptions.options.verbose) configureLanguageVersion(kspTask) if (kspTask.classpathSnapshotProperties.useClasspathSnapshot.get() == false) { kspTask.compilerOptions.moduleName.convention( kotlinCompileTask.compilerOptions.moduleName.map { "$it-ksp" } ) - } else { - kspTask.compilerOptions.moduleName.convention(kotlinCompileTask.compilerOptions.moduleName) } kspTask.destination.value(kspOutputDir) @@ -460,11 +456,7 @@ class KspGradleSubplugin @Inject internal constructor(private val registry: Tool configureAsKspTask(kspTask, isIncremental) configureAsAbstractKotlinCompileTool(kspTask as AbstractKotlinCompileTool<*>) configurePluginOptions(kspTask) - kspTask.compilerOptions.verbose.convention(kotlinCompilation.compilerOptions.options.verbose) - kspTask.compilerOptions.freeCompilerArgs - .value(kotlinCompileTask.compilerOptions.freeCompilerArgs) configureLanguageVersion(kspTask) - kspTask.compilerOptions.moduleName.convention(kotlinCompileTask.moduleName) kspTask.incrementalChangesTransformers.add( createIncrementalChangesTransformer( @@ -524,12 +516,9 @@ class KspGradleSubplugin @Inject internal constructor(private val registry: Tool classpathCfg + kotlinCompileTask.compilerPluginClasspath!! kspTask.compilerPluginOptions.addPluginArgument(kotlinCompileTask.compilerPluginOptions) } - kspTask.compilerOptions.moduleName - .convention(kotlinCompileTask.compilerOptions.moduleName.map { "$it-ksp" }) kspTask.commonSources.from(kotlinCompileTask.commonSources) kspTask.options.add(FilesSubpluginOption("apclasspath", processorClasspath.files.toList())) val kspOptions = kspTask.options.get().flatMap { listOf("-P", it.toArg()) } - kspTask.compilerOptions.verbose.convention(kotlinCompilation.compilerOptions.options.verbose) kspTask.compilerOptions.freeCompilerArgs.value( kspOptions + kotlinCompileTask.compilerOptions.freeCompilerArgs.get() ) diff --git a/gradle.properties b/gradle.properties index 1df74d8eac..ff00835c2d 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,7 +1,7 @@ # Copied from kotlinc org.gradle.jvmargs=-Duser.country=US -Dkotlin.daemon.jvm.options=-Xmx2200m -Dfile.encoding=UTF-8 -kotlinBaseVersion=1.9.0-dev-6976 +kotlinBaseVersion=1.9.0-RC agpBaseVersion=7.0.0 intellijVersion=213.7172.25 junitVersion=4.12 diff --git a/integration-tests/src/test/kotlin/com/google/devtools/ksp/test/PlaygroundIT.kt b/integration-tests/src/test/kotlin/com/google/devtools/ksp/test/PlaygroundIT.kt index c08b084d97..4928046588 100644 --- a/integration-tests/src/test/kotlin/com/google/devtools/ksp/test/PlaygroundIT.kt +++ b/integration-tests/src/test/kotlin/com/google/devtools/ksp/test/PlaygroundIT.kt @@ -298,4 +298,36 @@ class PlaygroundIT { } project.restore(buildFile.path) } + + @Test + fun testProjectExtensionCompilerOptions() { + val properties = File(project.root, "gradle.properties") + properties.writeText( + properties.readText().replace( + "kotlin.jvm.target.validation.mode=warning", + "kotlin.jvm.target.validation.mode=error" + ) + ) + val buildFile = File(project.root, "workload/build.gradle.kts") + buildFile.appendText( + """ + kotlin { + compilerOptions { + jvmTarget.set(org.jetbrains.kotlin.gradle.dsl.JvmTarget.JVM_17) + } + } + """.trimIndent() + ) + val gradleRunner = GradleRunner.create().withProjectDir(project.root).withGradleVersion("8.0") + gradleRunner.withArguments("clean", "build").buildAndFail().let { result -> + Assert.assertTrue( + result.output.contains( + "'compileJava' task (current target is 11) and 'kspKotlin' " + + "task (current target is 17) jvm target compatibility should be set to the same Java version." + ) + ) + } + project.restore(buildFile.path) + project.restore(properties.path) + } } diff --git a/test-utils/src/main/kotlin/com/google/devtools/ksp/processor/TypeAnnotationProcessor.kt b/test-utils/src/main/kotlin/com/google/devtools/ksp/processor/TypeAnnotationProcessor.kt new file mode 100644 index 0000000000..fa974f7d57 --- /dev/null +++ b/test-utils/src/main/kotlin/com/google/devtools/ksp/processor/TypeAnnotationProcessor.kt @@ -0,0 +1,24 @@ +package com.google.devtools.ksp.processor + +import com.google.devtools.ksp.getClassDeclarationByName +import com.google.devtools.ksp.getDeclaredProperties +import com.google.devtools.ksp.processing.Resolver +import com.google.devtools.ksp.symbol.KSAnnotated + +class TypeAnnotationProcessor : AbstractTestProcessor() { + val result = mutableListOf() + + override fun toResult(): List { + return result + } + + override fun process(resolver: Resolver): List { + val myList = resolver.getClassDeclarationByName("MyClass")!!.getDeclaredProperties().single() + val myStringClass = resolver.getClassDeclarationByName("MyStringClass")!!.asStarProjectedType() + result.add(myList.type.resolve().annotations.joinToString()) + result.add(myList.asMemberOf(myStringClass).annotations.joinToString()) + result.add(myList.type.resolve().let { it.replace(it.arguments) }.annotations.joinToString()) + result.add(myList.type.resolve().starProjection().annotations.joinToString()) + return emptyList() + } +} diff --git a/test-utils/testData/api/typeAnnotation.kt b/test-utils/testData/api/typeAnnotation.kt new file mode 100644 index 0000000000..1bd76e40d0 --- /dev/null +++ b/test-utils/testData/api/typeAnnotation.kt @@ -0,0 +1,32 @@ +/* + * Copyright 2023 Google LLC + * Copyright 2010-2023 JetBrains s.r.o. and Kotlin Programming Language contributors. + * + * 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. + * + */ + +// WITH_RUNTIME +// TEST PROCESSOR: TypeAnnotationProcessor +// EXPECTED: +// @JvmSuppressWildcards +// @JvmSuppressWildcards +// @JvmSuppressWildcards +// @JvmSuppressWildcards +// END + +class MyClass { + var myList: @JvmSuppressWildcards List = TODO() +} + +class MyStringClass: MyClass {}