From e32cff3b38cebcf25e39cde7089290972eb8af7d Mon Sep 17 00:00:00 2001 From: Sebastian Sellmair Date: Thu, 15 Dec 2022 15:13:12 +0100 Subject: [PATCH] [Gradle] Implement IdeMultiplatformImport using new IdeaKotlinClasspath ^KT-55492 Verification Pending --- ...linDependencyBackwardsCompatibilityTest.kt | 26 ++----- .../api/kotlin-gradle-plugin-idea.api | 1 + .../gradle/idea/tcs/IdeaKotlinClasspath.kt | 4 ++ .../tcs/IdeaKotlinDependencyCoordinates.kt | 1 - .../gradle/MppIdeDependencyResolutionIT.kt | 4 +- .../gradle/android/androidBootClasspath.kt | 12 ++-- .../ide/IdeAdditionalArtifactResolver.kt | 70 +++++++++++++++++++ .../plugin/ide/IdeDependencyResolver.kt | 3 + .../plugin/ide/IdeMultiplatformImport.kt | 22 +++++- .../ide/IdeMultiplatformImportFactory.kt | 26 ++----- .../plugin/ide/IdeMultiplatformImportImpl.kt | 57 ++++++++++++++- ...ionQuerySourcesAndDocumentationResolver.kt | 55 +++++++++------ .../IdeBinaryDependencyResolver.kt | 16 ++--- ...JvmAndAndroidPlatformDependencyResolver.kt | 4 +- .../IdeMetadataSourcesResolver.kt | 10 +-- .../IdeNativeStdlibDependencyResolver.kt | 19 +++-- .../IdeNativeStdlibSourcesResolver.kt | 35 ---------- .../IdeOriginalMetadataDependencyResolver.kt | 6 +- .../IdePlatformSourcesResolver.kt | 4 +- ...deTransformedMetadataDependencyResolver.kt | 8 +-- .../resolveNativeDistributionDependency.kt | 7 +- .../UnusedSourcesAndDocumentationFilter.kt | 48 ------------- .../plugin/ide/kotlinExtrasSerialization.kt | 4 ++ ...deSourcesAndDocumentationResolutionTest.kt | 45 +++++++----- 24 files changed, 273 insertions(+), 214 deletions(-) create mode 100644 libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/ide/IdeAdditionalArtifactResolver.kt delete mode 100644 libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/ide/dependencyResolvers/IdeNativeStdlibSourcesResolver.kt delete mode 100644 libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/ide/dependencyTransformers/UnusedSourcesAndDocumentationFilter.kt diff --git a/libraries/tools/kotlin-gradle-plugin-idea-proto/src/test/kotlin/org/jetbrains/kotlin/gradle/idea/proto/tcs/IdeaKotlinDependencyBackwardsCompatibilityTest.kt b/libraries/tools/kotlin-gradle-plugin-idea-proto/src/test/kotlin/org/jetbrains/kotlin/gradle/idea/proto/tcs/IdeaKotlinDependencyBackwardsCompatibilityTest.kt index eae5be9decc..09eb952b829 100644 --- a/libraries/tools/kotlin-gradle-plugin-idea-proto/src/test/kotlin/org/jetbrains/kotlin/gradle/idea/proto/tcs/IdeaKotlinDependencyBackwardsCompatibilityTest.kt +++ b/libraries/tools/kotlin-gradle-plugin-idea-proto/src/test/kotlin/org/jetbrains/kotlin/gradle/idea/proto/tcs/IdeaKotlinDependencyBackwardsCompatibilityTest.kt @@ -7,7 +7,10 @@ package org.jetbrains.kotlin.gradle.idea.proto.tcs import org.jetbrains.kotlin.gradle.idea.proto.classLoaderForBackwardsCompatibleClasses import org.jetbrains.kotlin.gradle.idea.serialize.IdeaKotlinSerializationLogger -import org.jetbrains.kotlin.gradle.idea.tcs.* +import org.jetbrains.kotlin.gradle.idea.tcs.IdeaKotlinProjectArtifactDependency +import org.jetbrains.kotlin.gradle.idea.tcs.IdeaKotlinResolvedBinaryDependency +import org.jetbrains.kotlin.gradle.idea.tcs.IdeaKotlinSourceDependency +import org.jetbrains.kotlin.gradle.idea.tcs.IdeaKotlinUnresolvedBinaryDependency import org.jetbrains.kotlin.gradle.idea.testFixtures.tcs.TestIdeaKotlinDependencySerializer import org.jetbrains.kotlin.gradle.idea.testFixtures.tcs.TestIdeaKotlinInstances import org.jetbrains.kotlin.gradle.idea.testFixtures.utils.copy @@ -66,27 +69,6 @@ class IdeaKotlinDependencyBackwardsCompatibilityTest { assertEquals(dependency.coordinates, deserializedCopied.coordinates) assertEquals(dependency.extras, deserializedCopied.extras) } - - @Test - fun `test - empty classpath`() { - val classpath = TestIdeaKotlinInstances.emptyClasspath - val binary = TestIdeaKotlinDependencySerializer().serialize(classpath) - val deserialized = deserializeIdeaKotlinDependencyWithBackwardsCompatibleClasses(binary) - val copied = deserialized.copy() - - assertEquals(classpath.toSet(), copied.toSet()) - } - - @Test - fun `test - simple classpath`() { - val classpath = TestIdeaKotlinInstances.simpleClasspath - val binary = TestIdeaKotlinDependencySerializer().serialize(classpath) - val deserialized = deserializeIdeaKotlinDependencyWithBackwardsCompatibleClasses(binary) - val copied = deserialized.copy() - - assertEquals(classpath.toSet(), copied.toSet()) - } - } private fun deserializeIdeaKotlinDependencyWithBackwardsCompatibleClasses(project: ByteArray): Any { diff --git a/libraries/tools/kotlin-gradle-plugin-idea/api/kotlin-gradle-plugin-idea.api b/libraries/tools/kotlin-gradle-plugin-idea/api/kotlin-gradle-plugin-idea.api index c1318f71afb..7d8666b5fc1 100644 --- a/libraries/tools/kotlin-gradle-plugin-idea/api/kotlin-gradle-plugin-idea.api +++ b/libraries/tools/kotlin-gradle-plugin-idea/api/kotlin-gradle-plugin-idea.api @@ -335,6 +335,7 @@ public final class org/jetbrains/kotlin/gradle/idea/tcs/IdeaKotlinClasspath : ja public fun add (Ljava/io/File;)Z public synthetic fun add (Ljava/lang/Object;)Z public fun addAll (Ljava/util/Collection;)Z + public final fun addAll (Lorg/jetbrains/kotlin/gradle/idea/tcs/IdeaKotlinClasspath;)Z public fun clear ()V public fun contains (Ljava/io/File;)Z public final fun contains (Ljava/lang/Object;)Z diff --git a/libraries/tools/kotlin-gradle-plugin-idea/src/main/kotlin/org/jetbrains/kotlin/gradle/idea/tcs/IdeaKotlinClasspath.kt b/libraries/tools/kotlin-gradle-plugin-idea/src/main/kotlin/org/jetbrains/kotlin/gradle/idea/tcs/IdeaKotlinClasspath.kt index 5dbf66899d2..5866d811aab 100644 --- a/libraries/tools/kotlin-gradle-plugin-idea/src/main/kotlin/org/jetbrains/kotlin/gradle/idea/tcs/IdeaKotlinClasspath.kt +++ b/libraries/tools/kotlin-gradle-plugin-idea/src/main/kotlin/org/jetbrains/kotlin/gradle/idea/tcs/IdeaKotlinClasspath.kt @@ -23,6 +23,10 @@ class IdeaKotlinClasspath private constructor(private val files: MutableSet): Boolean { return files.addAll(elements.map(::normalise)) } diff --git a/libraries/tools/kotlin-gradle-plugin-idea/src/main/kotlin/org/jetbrains/kotlin/gradle/idea/tcs/IdeaKotlinDependencyCoordinates.kt b/libraries/tools/kotlin-gradle-plugin-idea/src/main/kotlin/org/jetbrains/kotlin/gradle/idea/tcs/IdeaKotlinDependencyCoordinates.kt index 6045aa63cd2..59baa538c27 100644 --- a/libraries/tools/kotlin-gradle-plugin-idea/src/main/kotlin/org/jetbrains/kotlin/gradle/idea/tcs/IdeaKotlinDependencyCoordinates.kt +++ b/libraries/tools/kotlin-gradle-plugin-idea/src/main/kotlin/org/jetbrains/kotlin/gradle/idea/tcs/IdeaKotlinDependencyCoordinates.kt @@ -25,7 +25,6 @@ data class IdeaKotlinBinaryCoordinates( } } -@IdeaKotlinModel data class IdeaKotlinProjectCoordinates( val buildId: String, val projectPath: String, diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/MppIdeDependencyResolutionIT.kt b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/MppIdeDependencyResolutionIT.kt index e5960dd4e8d..dd43fb47e36 100644 --- a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/MppIdeDependencyResolutionIT.kt +++ b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/MppIdeDependencyResolutionIT.kt @@ -8,8 +8,8 @@ package org.jetbrains.kotlin.gradle import org.gradle.util.GradleVersion import org.jetbrains.kotlin.commonizer.CommonizerTarget import org.jetbrains.kotlin.commonizer.identityString +import org.jetbrains.kotlin.gradle.idea.tcs.IdeaKotlinBinaryDependency import org.jetbrains.kotlin.gradle.idea.tcs.IdeaKotlinDependency -import org.jetbrains.kotlin.gradle.idea.tcs.IdeaKotlinDependency.Companion.CLASSPATH_BINARY_TYPE import org.jetbrains.kotlin.gradle.idea.tcs.IdeaKotlinResolvedBinaryDependency import org.jetbrains.kotlin.gradle.idea.tcs.extras.isCommonized import org.jetbrains.kotlin.gradle.idea.tcs.extras.isNativeDistribution @@ -37,7 +37,7 @@ class MppIdeDependencyResolutionIT : KGPBaseTest() { filterIsInstance() .filter { !it.isNativeStdlib } .filter { it.isNativeDistribution } - .filter { it.binaryType == CLASSPATH_BINARY_TYPE } + .filter { it.binaryType == IdeaKotlinBinaryDependency.KOTLIN_COMPILE_BINARY_TYPE } val nativeMainDependencies = dependencies["nativeMain"].filterNativePlatformDependencies() val nativeTestDependencies = dependencies["nativeTest"].filterNativePlatformDependencies() diff --git a/libraries/tools/kotlin-gradle-plugin-tcs-android/src/main/kotlin/org/jetbrains/kotlin/gradle/android/androidBootClasspath.kt b/libraries/tools/kotlin-gradle-plugin-tcs-android/src/main/kotlin/org/jetbrains/kotlin/gradle/android/androidBootClasspath.kt index b3cf3c7c49f..62fb7e4e34f 100644 --- a/libraries/tools/kotlin-gradle-plugin-tcs-android/src/main/kotlin/org/jetbrains/kotlin/gradle/android/androidBootClasspath.kt +++ b/libraries/tools/kotlin-gradle-plugin-tcs-android/src/main/kotlin/org/jetbrains/kotlin/gradle/android/androidBootClasspath.kt @@ -10,9 +10,7 @@ import org.gradle.api.Project import org.gradle.api.file.FileCollection import org.gradle.kotlin.dsl.getByType import org.jetbrains.kotlin.gradle.android.AndroidKotlinSourceSet.Companion.android -import org.jetbrains.kotlin.gradle.idea.tcs.IdeaKotlinBinaryCoordinates -import org.jetbrains.kotlin.gradle.idea.tcs.IdeaKotlinDependency -import org.jetbrains.kotlin.gradle.idea.tcs.IdeaKotlinResolvedBinaryDependency +import org.jetbrains.kotlin.gradle.idea.tcs.* import org.jetbrains.kotlin.gradle.plugin.KotlinSourceSet import org.jetbrains.kotlin.gradle.plugin.ide.IdeDependencyResolver import org.jetbrains.kotlin.tooling.core.mutableExtrasOf @@ -25,13 +23,13 @@ internal fun Project.androidBootClasspath(): FileCollection { internal class AndroidBootClasspathIdeDependencyResolver(private val project: Project) : IdeDependencyResolver { override fun resolve(sourceSet: KotlinSourceSet): Set { if (sourceSet.android == null) return emptySet() - return project.androidBootClasspath().files.map { file -> + return setOf( IdeaKotlinResolvedBinaryDependency( - binaryType = IdeaKotlinDependency.CLASSPATH_BINARY_TYPE, - binaryFile = file, + binaryType = IdeaKotlinBinaryDependency.KOTLIN_COMPILE_BINARY_TYPE, + classpath = IdeaKotlinClasspath(project.androidBootClasspath().files), extras = mutableExtrasOf(), coordinates = IdeaKotlinBinaryCoordinates("com.android", "sdk", "7.4") ) - }.toSet() + ) } } diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/ide/IdeAdditionalArtifactResolver.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/ide/IdeAdditionalArtifactResolver.kt new file mode 100644 index 00000000000..3c889c7b1a9 --- /dev/null +++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/ide/IdeAdditionalArtifactResolver.kt @@ -0,0 +1,70 @@ +/* + * Copyright 2010-2022 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package org.jetbrains.kotlin.gradle.plugin.ide + +import org.jetbrains.kotlin.gradle.idea.tcs.IdeaKotlinBinaryDependency +import org.jetbrains.kotlin.gradle.idea.tcs.IdeaKotlinDependency +import org.jetbrains.kotlin.gradle.idea.tcs.IdeaKotlinResolvedBinaryDependency +import org.jetbrains.kotlin.gradle.idea.tcs.extras.documentationClasspath +import org.jetbrains.kotlin.gradle.idea.tcs.extras.sourcesClasspath +import org.jetbrains.kotlin.gradle.plugin.KotlinSourceSet +import org.jetbrains.kotlin.gradle.plugin.ide.IdeDependencyResolver.Companion.DOCUMENTATION_BINARY_TYPE +import org.jetbrains.kotlin.gradle.plugin.ide.IdeDependencyResolver.Companion.SOURCES_BINARY_TYPE + + +fun interface IdeAdditionalArtifactResolver { + fun resolve(sourceSet: KotlinSourceSet, dependencies: Set) +} + +internal fun IdeDependencyResolver.withAdditionalArtifactResolver(resolver: IdeAdditionalArtifactResolver) = + IdeDependencyResolver { sourceSet -> + this@withAdditionalArtifactResolver.resolve(sourceSet).also { result -> + resolver.resolve(sourceSet, result) + } + } + +internal fun IdeAdditionalArtifactResolver(resolvers: Iterable) = + IdeAdditionalArtifactResolver { sourceSet, dependencies -> + resolvers.forEach { resolver -> resolver?.resolve(sourceSet, dependencies) } + } + + +/** + * Creates an [IdeAdditionalArtifactResolver] from a given [IdeDependencyResolver]: + * Dependencies from the [IdeDependencyResolver] need to resolve sources and javadoc using + * the [SOURCES_BINARY_TYPE] or [DOCUMENTATION_BINARY_TYPE] + */ +fun IdeAdditionalArtifactResolver(resolver: IdeDependencyResolver) = IdeAdditionalArtifactResolver { sourceSet, dependencies -> + /* + Group already resolved dependencies by their coordinates (ignoring sourceSetName, since -sources.jar are not published + on a "per source set" level.) + */ + val dependenciesByCoordinates = dependencies.filterIsInstance() + .filter { it.binaryType == IdeaKotlinBinaryDependency.KOTLIN_COMPILE_BINARY_TYPE } + .groupBy { it.coordinates?.copy(sourceSetName = null) } + + /* + Use the passed resolver to resolve the -sources.jar and -javadoc jar dependencies as idea dependencies. + For each dependency, we will find the dependencies to add this artifacts by matching the coordinates. + */ + resolver.resolve(sourceSet).filterIsInstance() + .filter { it.binaryType == SOURCES_BINARY_TYPE || it.binaryType == DOCUMENTATION_BINARY_TYPE } + .forEach forEachSourceOrDocumentationDependency@{ sourceOrDocumentationDependency -> + /* Find dependencies that match by coordinates and add the artifacts */ + dependenciesByCoordinates[sourceOrDocumentationDependency.coordinates ?: return@forEachSourceOrDocumentationDependency] + .orEmpty().forEach forEachMatchedDependency@{ dependency -> + val classpath = when (sourceOrDocumentationDependency.binaryType) { + SOURCES_BINARY_TYPE -> dependency.sourcesClasspath + DOCUMENTATION_BINARY_TYPE -> dependency.documentationClasspath + else -> return@forEachMatchedDependency + } + classpath.addAll(dependency.classpath) + } + } +} + + +fun IdeDependencyResolver.asAdditionalArtifactResolver() = IdeAdditionalArtifactResolver(this) \ No newline at end of file diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/ide/IdeDependencyResolver.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/ide/IdeDependencyResolver.kt index ac5442c09b3..ef2fe29b16b 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/ide/IdeDependencyResolver.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/ide/IdeDependencyResolver.kt @@ -26,6 +26,9 @@ fun interface IdeDependencyResolver { } companion object { + const val SOURCES_BINARY_TYPE = "SOURCES" + const val DOCUMENTATION_BINARY_TYPE = "DOCUMENTATION" + var IdeaKotlinDependency.resolvedBy: IdeDependencyResolver? by extrasReadWriteProperty("resolvedBy") var IdeaKotlinDependency.gradleArtifact: ResolvedArtifactResult? by extrasReadWriteProperty("gradleArtifact") } diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/ide/IdeMultiplatformImport.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/ide/IdeMultiplatformImport.kt index c9a99be6bd3..787a6acea1f 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/ide/IdeMultiplatformImport.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/ide/IdeMultiplatformImport.kt @@ -15,9 +15,7 @@ import org.jetbrains.kotlin.gradle.dsl.multiplatformExtensionOrNull import org.jetbrains.kotlin.gradle.idea.serialize.IdeaKotlinExtrasSerializationExtension import org.jetbrains.kotlin.gradle.idea.serialize.IdeaKotlinExtrasSerializationExtensionBuilder import org.jetbrains.kotlin.gradle.idea.tcs.IdeaKotlinDependency -import org.jetbrains.kotlin.gradle.plugin.KotlinPlatformType.androidJvm -import org.jetbrains.kotlin.gradle.plugin.KotlinPlatformType.jvm -import org.jetbrains.kotlin.gradle.plugin.KotlinPlatformType.common +import org.jetbrains.kotlin.gradle.plugin.KotlinPlatformType.* import org.jetbrains.kotlin.gradle.plugin.KotlinSourceSet import org.jetbrains.kotlin.gradle.plugin.extraProperties import org.jetbrains.kotlin.gradle.plugin.ide.IdeMultiplatformImport.DependencyResolutionLevel.Default @@ -50,6 +48,14 @@ interface IdeMultiplatformImport { level: DependencyResolutionLevel = Default, ) + @ExternalKotlinTargetApi + fun registerAdditionalArtifactResolver( + resolver: IdeAdditionalArtifactResolver, + constraint: SourceSetConstraint, + phase: AdditionalArtifactResolutionPhase, + level: AdditionalArtifactResolutionLevel = AdditionalArtifactResolutionLevel.Default + ) + @ExternalKotlinTargetApi fun registerDependencyTransformer( transformer: IdeDependencyTransformer, @@ -112,6 +118,16 @@ interface IdeMultiplatformImport { Default, Overwrite } + enum class AdditionalArtifactResolutionPhase { + PreAdditionalArtifactResolution, + SourcesAndJavadocArtifactResolution, + PostAdditionalArtifactResolution + } + + enum class AdditionalArtifactResolutionLevel { + Default, Overwrite + } + /** * Any [IdeDependencyResolver] has to be registered for a given transformation phase. * The phases will be executed in the order of this enums ordinal. diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/ide/IdeMultiplatformImportFactory.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/ide/IdeMultiplatformImportFactory.kt index 97726d891da..a153a8c75cd 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/ide/IdeMultiplatformImportFactory.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/ide/IdeMultiplatformImportFactory.kt @@ -10,7 +10,6 @@ import org.jetbrains.kotlin.gradle.plugin.PropertiesProvider.Companion.kotlinPro import org.jetbrains.kotlin.gradle.plugin.ide.IdeMultiplatformImport.SourceSetConstraint import org.jetbrains.kotlin.gradle.plugin.ide.dependencyResolvers.* import org.jetbrains.kotlin.gradle.plugin.ide.dependencyTransformers.IdePlatformStdlibCommonDependencyFilter -import org.jetbrains.kotlin.gradle.plugin.ide.dependencyTransformers.UnusedSourcesAndDocumentationFilter internal fun IdeMultiplatformImport(extension: KotlinProjectExtension): IdeMultiplatformImport { return IdeMultiplatformImportImpl(extension).apply { @@ -96,13 +95,6 @@ internal fun IdeMultiplatformImport(extension: KotlinProjectExtension): IdeMulti level = IdeMultiplatformImport.DependencyResolutionLevel.Default ) - registerDependencyResolver( - resolver = IdeNativeStdlibSourcesResolver, - constraint = SourceSetConstraint.isNative, - phase = IdeMultiplatformImport.DependencyResolutionPhase.SourcesAndDocumentationResolution, - level = IdeMultiplatformImport.DependencyResolutionLevel.Default - ) - registerDependencyResolver( resolver = IdePlatformSourcesResolver(), constraint = SourceSetConstraint.isSinglePlatformType, @@ -110,19 +102,19 @@ internal fun IdeMultiplatformImport(extension: KotlinProjectExtension): IdeMulti level = IdeMultiplatformImport.DependencyResolutionLevel.Default ) - registerDependencyResolver( + registerAdditionalArtifactResolver( resolver = IdeMetadataSourcesResolver(), constraint = !SourceSetConstraint.isSinglePlatformType, - phase = IdeMultiplatformImport.DependencyResolutionPhase.SourcesAndDocumentationResolution, - level = IdeMultiplatformImport.DependencyResolutionLevel.Default + phase = IdeMultiplatformImport.AdditionalArtifactResolutionPhase.SourcesAndJavadocArtifactResolution, + level = IdeMultiplatformImport.AdditionalArtifactResolutionLevel.Default ) if (extension.project.kotlinPropertiesProvider.enableSlowIdeSourcesJarResolver) { - registerDependencyResolver( + registerAdditionalArtifactResolver( resolver = IdeArtifactResolutionQuerySourcesAndDocumentationResolver, constraint = SourceSetConstraint.unconstrained, - phase = IdeMultiplatformImport.DependencyResolutionPhase.SourcesAndDocumentationResolution, - level = IdeMultiplatformImport.DependencyResolutionLevel.Default + phase = IdeMultiplatformImport.AdditionalArtifactResolutionPhase.SourcesAndJavadocArtifactResolution, + level = IdeMultiplatformImport.AdditionalArtifactResolutionLevel.Default ) } @@ -132,12 +124,6 @@ internal fun IdeMultiplatformImport(extension: KotlinProjectExtension): IdeMulti phase = IdeMultiplatformImport.DependencyTransformationPhase.DependencyFilteringPhase, ) - registerDependencyTransformer( - transformer = UnusedSourcesAndDocumentationFilter, - constraint = SourceSetConstraint.unconstrained, - phase = IdeMultiplatformImport.DependencyTransformationPhase.DependencyFilteringPhase - ) - registerDependencyEffect( effect = IdeDependencyLogger, constraint = SourceSetConstraint.unconstrained diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/ide/IdeMultiplatformImportImpl.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/ide/IdeMultiplatformImportImpl.kt index 3d202d4038c..d0636f80963 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/ide/IdeMultiplatformImportImpl.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/ide/IdeMultiplatformImportImpl.kt @@ -18,6 +18,7 @@ import org.jetbrains.kotlin.gradle.plugin.ide.IdeMultiplatformImport.* import org.jetbrains.kotlin.gradle.plugin.ide.IdeMultiplatformImport.Companion.logger import org.jetbrains.kotlin.tooling.core.Extras import org.jetbrains.kotlin.utils.addToStdlib.measureTimeMillisWithResult +import kotlin.system.measureTimeMillis internal class IdeMultiplatformImportImpl( @@ -47,6 +48,7 @@ internal class IdeMultiplatformImportImpl( } private val registeredDependencyResolvers = mutableListOf() + private val registeredAdditionalArtifactResolvers = mutableListOf() private val registeredDependencyTransformers = mutableListOf() private val registeredDependencyEffects = mutableListOf() private val registeredExtrasSerializationExtensions = mutableListOf() @@ -82,6 +84,20 @@ internal class IdeMultiplatformImportImpl( ) } + @ExternalKotlinTargetApi + override fun registerAdditionalArtifactResolver( + resolver: IdeAdditionalArtifactResolver, + constraint: SourceSetConstraint, + phase: AdditionalArtifactResolutionPhase, + level: AdditionalArtifactResolutionLevel + ) { + registeredAdditionalArtifactResolvers.add( + RegisteredAdditionalArtifactResolver( + extension.project.kotlinIdeMultiplatformImportStatistics, resolver, constraint, phase, level + ) + ) + } + @ExternalKotlinTargetApi override fun registerDependencyEffect(effect: IdeDependencyEffect, constraint: SourceSetConstraint) { registeredDependencyEffects.add( @@ -95,9 +111,11 @@ internal class IdeMultiplatformImportImpl( } private fun createDependencyResolver(): IdeDependencyResolver { - return IdeDependencyResolver(DependencyResolutionPhase.values().map { phase -> - createDependencyResolver(phase) - }).withTransformer(createDependencyTransformer()) + return IdeDependencyResolver( + DependencyResolutionPhase.values().map { phase -> createDependencyResolver(phase) } + ) + .withAdditionalArtifactResolver(createAdditionalArtifactsResolver()) + .withTransformer(createDependencyTransformer()) .withEffect(createDependencyEffect()) } @@ -119,6 +137,25 @@ internal class IdeMultiplatformImportImpl( emptySet() } + private fun createAdditionalArtifactsResolver() = IdeAdditionalArtifactResolver( + AdditionalArtifactResolutionPhase.values().map { phase -> createAdditionalArtifactsResolver(phase) }) + + private fun createAdditionalArtifactsResolver(phase: AdditionalArtifactResolutionPhase) = + IdeAdditionalArtifactResolver resolve@{ sourceSet, dependencies -> + val applicableResolvers = registeredAdditionalArtifactResolvers + .filter { it.phase == phase } + .filter { it.constraint(sourceSet) } + .groupBy { it.level } + + AdditionalArtifactResolutionLevel.values().reversed().forEach { level -> + val resolvers = applicableResolvers[level].orEmpty() + if (resolvers.isNotEmpty()) { + resolvers.forEach { resolver -> resolver.resolve(sourceSet, dependencies) } + return@resolve + } + } + } + private fun createDependencyTransformer(): IdeDependencyTransformer { return IdeDependencyTransformer(DependencyTransformationPhase.values().map { phase -> createDependencyTransformer(phase) @@ -202,4 +239,18 @@ internal class IdeMultiplatformImportImpl( } } } + + private class RegisteredAdditionalArtifactResolver( + private val statistics: IdeMultiplatformImportStatistics, + private val resolver: IdeAdditionalArtifactResolver, + val constraint: SourceSetConstraint, + val phase: AdditionalArtifactResolutionPhase, + val level: AdditionalArtifactResolutionLevel + ) : IdeAdditionalArtifactResolver { + override fun resolve(sourceSet: KotlinSourceSet, dependencies: Set) { + runCatching { measureTimeMillis { resolver.resolve(sourceSet, dependencies) } } + .onFailure { logger.error("e: ${resolver::class.java.name} failed on ${IdeaKotlinSourceCoordinates(sourceSet)}", it) } + .onSuccess { statistics.addExecutionTime(resolver::class.java, it) } + } + } } diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/ide/dependencyResolvers/IdeArtifactResolutionQuerySourcesAndDocumentationResolver.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/ide/dependencyResolvers/IdeArtifactResolutionQuerySourcesAndDocumentationResolver.kt index 89e2a614e54..b0bbcb87e0f 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/ide/dependencyResolvers/IdeArtifactResolutionQuerySourcesAndDocumentationResolver.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/ide/dependencyResolvers/IdeArtifactResolutionQuerySourcesAndDocumentationResolver.kt @@ -7,17 +7,18 @@ package org.jetbrains.kotlin.gradle.plugin.ide.dependencyResolvers import org.gradle.api.artifacts.Configuration import org.gradle.api.artifacts.component.ModuleComponentIdentifier -import org.gradle.api.artifacts.result.ArtifactResolutionResult import org.gradle.api.artifacts.result.ResolvedArtifactResult -import org.gradle.api.component.Artifact import org.gradle.jvm.JvmLibrary import org.gradle.language.base.artifact.SourcesArtifact import org.gradle.language.java.artifact.JavadocArtifact import org.jetbrains.kotlin.gradle.idea.tcs.IdeaKotlinDependency import org.jetbrains.kotlin.gradle.idea.tcs.IdeaKotlinResolvedBinaryDependency +import org.jetbrains.kotlin.gradle.idea.tcs.extras.documentationClasspath +import org.jetbrains.kotlin.gradle.idea.tcs.extras.sourcesClasspath +import org.jetbrains.kotlin.gradle.idea.tcs.isKotlinCompileBinaryType import org.jetbrains.kotlin.gradle.plugin.KotlinPlatformType import org.jetbrains.kotlin.gradle.plugin.KotlinSourceSet -import org.jetbrains.kotlin.gradle.plugin.ide.IdeDependencyResolver +import org.jetbrains.kotlin.gradle.plugin.ide.IdeAdditionalArtifactResolver import org.jetbrains.kotlin.gradle.plugin.ide.IdeaKotlinBinaryCoordinates import org.jetbrains.kotlin.gradle.plugin.mpp.internal import org.jetbrains.kotlin.gradle.plugin.mpp.resolvableMetadataConfiguration @@ -32,8 +33,12 @@ import org.jetbrains.kotlin.gradle.plugin.sources.project * * cc Anton Lakotka, Sebastian Sellmair */ -internal object IdeArtifactResolutionQuerySourcesAndDocumentationResolver : IdeDependencyResolver { - override fun resolve(sourceSet: KotlinSourceSet): Set { +internal object IdeArtifactResolutionQuerySourcesAndDocumentationResolver : IdeAdditionalArtifactResolver { + override fun resolve(sourceSet: KotlinSourceSet, dependencies: Set) { + val binaryDependencies = dependencies.filterIsInstance() + .filter { dependency -> dependency.isKotlinCompileBinaryType } + .groupBy { dependency -> dependency.coordinates?.copy(sourceSetName = null) } + val project = sourceSet.project val configuration = selectConfiguration(sourceSet) val resolutionResult = project.dependencies.createArtifactResolutionQuery() @@ -41,25 +46,29 @@ internal object IdeArtifactResolutionQuerySourcesAndDocumentationResolver : IdeD .withArtifacts(JvmLibrary::class.java, SourcesArtifact::class.java, JavadocArtifact::class.java) .execute() - return resolve(resolutionResult, SourcesArtifact::class.java, IdeaKotlinDependency.SOURCES_BINARY_TYPE) + - resolve(resolutionResult, JavadocArtifact::class.java, IdeaKotlinDependency.DOCUMENTATION_BINARY_TYPE) - } + val sourcesArtifacts = resolutionResult.resolvedComponents.flatMap { resolved -> + resolved.getArtifacts(SourcesArtifact::class.java).filterIsInstance() + } - fun resolve( - resolutionResult: ArtifactResolutionResult, artifactType: Class, binaryType: String - ): Set { - return resolutionResult.resolvedComponents.flatMap { resolved -> - resolved.getArtifacts(artifactType) - .filterIsInstance() - .mapNotNull { artifact -> - val id = artifact.id.componentIdentifier as? ModuleComponentIdentifier ?: return@mapNotNull null - IdeaKotlinResolvedBinaryDependency( - coordinates = IdeaKotlinBinaryCoordinates(id), - binaryType = binaryType, - binaryFile = artifact.file - ) - } - }.toSet() + sourcesArtifacts.forEach { artifact -> + val artifactId = artifact.id.componentIdentifier as? ModuleComponentIdentifier ?: return@forEach + val artifactCoordinates = IdeaKotlinBinaryCoordinates(artifactId) + binaryDependencies[artifactCoordinates]?.forEach { dependency -> + dependency.sourcesClasspath.add(artifact.file) + } + } + + val javadocArtifacts = resolutionResult.resolvedComponents.flatMap { resolved -> + resolved.getArtifacts(JavadocArtifact::class.java).filterIsInstance() + } + + javadocArtifacts.forEach { artifact -> + val artifactId = artifact.id.componentIdentifier as? ModuleComponentIdentifier ?: return@forEach + val artifactCoordinates = IdeaKotlinBinaryCoordinates(artifactId) + binaryDependencies[artifactCoordinates]?.forEach { dependency -> + dependency.documentationClasspath.add(artifact.file) + } + } } private fun selectConfiguration(sourceSet: KotlinSourceSet): Configuration { diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/ide/dependencyResolvers/IdeBinaryDependencyResolver.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/ide/dependencyResolvers/IdeBinaryDependencyResolver.kt index 3fd42f6a94e..dea7247291b 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/ide/dependencyResolvers/IdeBinaryDependencyResolver.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/ide/dependencyResolvers/IdeBinaryDependencyResolver.kt @@ -15,6 +15,7 @@ import org.gradle.internal.component.local.model.OpaqueComponentArtifactIdentifi import org.gradle.internal.resolve.ModuleVersionResolveException import org.jetbrains.kotlin.gradle.ExternalKotlinTargetApi import org.jetbrains.kotlin.gradle.idea.tcs.* +import org.jetbrains.kotlin.gradle.idea.tcs.extras.artifactsClasspath import org.jetbrains.kotlin.gradle.plugin.KotlinCompilation import org.jetbrains.kotlin.gradle.plugin.KotlinPlatformType import org.jetbrains.kotlin.gradle.plugin.KotlinSourceSet @@ -36,7 +37,7 @@ import org.jetbrains.kotlin.tooling.core.mutableExtrasOf @ExternalKotlinTargetApi class IdeBinaryDependencyResolver( - private val binaryType: String = IdeaKotlinDependency.CLASSPATH_BINARY_TYPE, + private val binaryType: String = IdeaKotlinBinaryDependency.KOTLIN_COMPILE_BINARY_TYPE, private val artifactResolutionStrategy: ArtifactResolutionStrategy = ArtifactResolutionStrategy.Compilation() ) : IdeDependencyResolver { @@ -100,18 +101,17 @@ class IdeBinaryDependencyResolver( is ProjectComponentIdentifier -> { IdeaKotlinProjectArtifactDependency( type = IdeaKotlinSourceDependency.Type.Regular, - coordinates = IdeaKotlinProjectArtifactCoordinates( - project = IdeaKotlinProjectCoordinates(componentId), - artifactFile = artifact.file - ) - ) + coordinates = IdeaKotlinProjectCoordinates(componentId) + ).apply { + artifactsClasspath.add(artifact.file) + } } is ModuleComponentIdentifier -> { IdeaKotlinResolvedBinaryDependency( coordinates = IdeaKotlinBinaryCoordinates(componentId), binaryType = binaryType, - binaryFile = artifact.file, + classpath = IdeaKotlinClasspath(artifact.file), ) } @@ -123,7 +123,7 @@ class IdeBinaryDependencyResolver( module = componentId.libraryName, version = null, sourceSetName = null ), - binaryFile = artifact.file + classpath = IdeaKotlinClasspath(artifact.file) ) } diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/ide/dependencyResolvers/IdeJvmAndAndroidPlatformDependencyResolver.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/ide/dependencyResolvers/IdeJvmAndAndroidPlatformDependencyResolver.kt index f0c42556bee..9a2996a9177 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/ide/dependencyResolvers/IdeJvmAndAndroidPlatformDependencyResolver.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/ide/dependencyResolvers/IdeJvmAndAndroidPlatformDependencyResolver.kt @@ -12,7 +12,7 @@ import org.gradle.api.artifacts.component.ProjectComponentIdentifier import org.gradle.api.attributes.Category import org.gradle.api.attributes.Usage import org.gradle.api.attributes.java.TargetJvmEnvironment -import org.jetbrains.kotlin.gradle.idea.tcs.IdeaKotlinDependency +import org.jetbrains.kotlin.gradle.idea.tcs.IdeaKotlinBinaryDependency import org.jetbrains.kotlin.gradle.plugin.KotlinPlatformType import org.jetbrains.kotlin.gradle.plugin.ide.IdeDependencyResolver import org.jetbrains.kotlin.gradle.plugin.usageByName @@ -23,7 +23,7 @@ import org.jetbrains.kotlin.gradle.utils.named */ internal fun IdeJvmAndAndroidPlatformBinaryDependencyResolver(project: Project): IdeDependencyResolver = IdeBinaryDependencyResolver( - binaryType = IdeaKotlinDependency.CLASSPATH_BINARY_TYPE, + binaryType = IdeaKotlinBinaryDependency.KOTLIN_COMPILE_BINARY_TYPE, artifactResolutionStrategy = IdeBinaryDependencyResolver.ArtifactResolutionStrategy.PlatformLikeSourceSet( setupPlatformResolutionAttributes = { attributes.attribute(Usage.USAGE_ATTRIBUTE, project.usageByName(Usage.JAVA_API)) diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/ide/dependencyResolvers/IdeMetadataSourcesResolver.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/ide/dependencyResolvers/IdeMetadataSourcesResolver.kt index 0f0019e0716..a635108f744 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/ide/dependencyResolvers/IdeMetadataSourcesResolver.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/ide/dependencyResolvers/IdeMetadataSourcesResolver.kt @@ -9,14 +9,16 @@ package org.jetbrains.kotlin.gradle.plugin.ide.dependencyResolvers import org.gradle.api.attributes.Category import org.gradle.api.attributes.DocsType -import org.jetbrains.kotlin.gradle.idea.tcs.IdeaKotlinDependency +import org.jetbrains.kotlin.gradle.plugin.ide.IdeAdditionalArtifactResolver +import org.jetbrains.kotlin.gradle.plugin.ide.IdeDependencyResolver +import org.jetbrains.kotlin.gradle.plugin.ide.asAdditionalArtifactResolver import org.jetbrains.kotlin.gradle.plugin.mpp.resolvableMetadataConfiguration import org.jetbrains.kotlin.gradle.plugin.sources.internal import org.jetbrains.kotlin.gradle.plugin.sources.project import org.jetbrains.kotlin.gradle.utils.named -internal fun IdeMetadataSourcesResolver(): IdeBinaryDependencyResolver = IdeBinaryDependencyResolver( - binaryType = IdeaKotlinDependency.SOURCES_BINARY_TYPE, +internal fun IdeMetadataSourcesResolver(): IdeAdditionalArtifactResolver = IdeBinaryDependencyResolver( + binaryType = IdeDependencyResolver.SOURCES_BINARY_TYPE, artifactResolutionStrategy = IdeBinaryDependencyResolver.ArtifactResolutionStrategy.ResolvableConfiguration( configurationSelector = { it.internal.resolvableMetadataConfiguration }, setupArtifactViewAttributes = { @@ -24,4 +26,4 @@ internal fun IdeMetadataSourcesResolver(): IdeBinaryDependencyResolver = IdeBina attribute(DocsType.DOCS_TYPE_ATTRIBUTE, it.project.objects.named(DocsType.SOURCES)) } ) -) +).asAdditionalArtifactResolver() diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/ide/dependencyResolvers/IdeNativeStdlibDependencyResolver.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/ide/dependencyResolvers/IdeNativeStdlibDependencyResolver.kt index 37e5e32ae44..412cbdaec64 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/ide/dependencyResolvers/IdeNativeStdlibDependencyResolver.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/ide/dependencyResolvers/IdeNativeStdlibDependencyResolver.kt @@ -9,15 +9,15 @@ import org.gradle.api.Project import org.gradle.api.logging.Logger import org.gradle.api.logging.Logging import org.jetbrains.kotlin.commonizer.KonanDistribution +import org.jetbrains.kotlin.commonizer.sourcesDir import org.jetbrains.kotlin.commonizer.stdlib import org.jetbrains.kotlin.compilerRunner.konanHome import org.jetbrains.kotlin.compilerRunner.konanVersion -import org.jetbrains.kotlin.gradle.idea.tcs.IdeaKotlinBinaryCoordinates -import org.jetbrains.kotlin.gradle.idea.tcs.IdeaKotlinDependency -import org.jetbrains.kotlin.gradle.idea.tcs.IdeaKotlinResolvedBinaryDependency +import org.jetbrains.kotlin.gradle.idea.tcs.* import org.jetbrains.kotlin.gradle.idea.tcs.extras.isNativeDistribution import org.jetbrains.kotlin.gradle.idea.tcs.extras.isNativeStdlib import org.jetbrains.kotlin.gradle.idea.tcs.extras.klibExtra +import org.jetbrains.kotlin.gradle.idea.tcs.extras.sourcesClasspath import org.jetbrains.kotlin.gradle.plugin.KotlinSourceSet import org.jetbrains.kotlin.gradle.plugin.ide.IdeDependencyResolver import org.jetbrains.kotlin.gradle.plugin.ide.KlibExtra @@ -30,11 +30,12 @@ internal object IdeNativeStdlibDependencyResolver : IdeDependencyResolver { private val logger: Logger = Logging.getLogger(IdeNativePlatformDependencyResolver::class.java) override fun resolve(sourceSet: KotlinSourceSet): Set { - val binaryFile = KonanDistribution(sourceSet.project.konanHome).stdlib + val konanDistribution = KonanDistribution(sourceSet.project.konanHome) + val stdlibFile = KonanDistribution(sourceSet.project.konanHome).stdlib val klibExtra = try { val kotlinLibrary = resolveSingleFileKlib( - libraryFile = File(binaryFile.absolutePath), + libraryFile = File(stdlibFile.absolutePath), strategy = ToolingSingleFileKlibResolveStrategy ) @@ -46,13 +47,17 @@ internal object IdeNativeStdlibDependencyResolver : IdeDependencyResolver { return setOf( IdeaKotlinResolvedBinaryDependency( - binaryType = IdeaKotlinDependency.CLASSPATH_BINARY_TYPE, - binaryFile = binaryFile, + binaryType = IdeaKotlinBinaryDependency.KOTLIN_COMPILE_BINARY_TYPE, + classpath = IdeaKotlinClasspath(stdlibFile), coordinates = nativeStdlibCoordinates(sourceSet.project) ).apply { this.isNativeDistribution = true this.isNativeStdlib = true this.klibExtra = klibExtra + this.sourcesClasspath += konanDistribution.sourcesDir.listFiles().orEmpty() + /* Ignore org.jetbrains.kotlinx. in this case */ + .filter { file -> file.name.startsWith("kotlin") } + .ifEmpty { return emptySet() } } ) } diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/ide/dependencyResolvers/IdeNativeStdlibSourcesResolver.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/ide/dependencyResolvers/IdeNativeStdlibSourcesResolver.kt deleted file mode 100644 index 9a1a3a8d1ea..00000000000 --- a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/ide/dependencyResolvers/IdeNativeStdlibSourcesResolver.kt +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright 2010-2022 JetBrains s.r.o. and Kotlin Programming Language contributors. - * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. - */ - -package org.jetbrains.kotlin.gradle.plugin.ide.dependencyResolvers - -import org.jetbrains.kotlin.commonizer.KonanDistribution -import org.jetbrains.kotlin.commonizer.sourcesDir -import org.jetbrains.kotlin.compilerRunner.konanHome -import org.jetbrains.kotlin.gradle.idea.tcs.IdeaKotlinDependency -import org.jetbrains.kotlin.gradle.idea.tcs.IdeaKotlinResolvedBinaryDependency -import org.jetbrains.kotlin.gradle.idea.tcs.extras.isNativeDistribution -import org.jetbrains.kotlin.gradle.idea.tcs.extras.isNativeStdlib -import org.jetbrains.kotlin.gradle.plugin.KotlinSourceSet -import org.jetbrains.kotlin.gradle.plugin.ide.IdeDependencyResolver -import org.jetbrains.kotlin.gradle.plugin.sources.project - -internal object IdeNativeStdlibSourcesResolver : IdeDependencyResolver { - override fun resolve(sourceSet: KotlinSourceSet): Set { - return KonanDistribution(sourceSet.project.konanHome).sourcesDir.listFiles().orEmpty() - /* Ignore org.jetbrains.kotlinx. in this case */ - .filter { file -> file.name.startsWith("kotlin") } - .map { file -> - IdeaKotlinResolvedBinaryDependency( - binaryType = IdeaKotlinDependency.SOURCES_BINARY_TYPE, - binaryFile = file, - coordinates = IdeNativeStdlibDependencyResolver.nativeStdlibCoordinates(sourceSet.project) - ).apply { - isNativeStdlib = true - isNativeDistribution = true - } - }.toSet() - } -} diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/ide/dependencyResolvers/IdeOriginalMetadataDependencyResolver.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/ide/dependencyResolvers/IdeOriginalMetadataDependencyResolver.kt index 5ad5ef2a612..f1eb0533c89 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/ide/dependencyResolvers/IdeOriginalMetadataDependencyResolver.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/ide/dependencyResolvers/IdeOriginalMetadataDependencyResolver.kt @@ -6,6 +6,8 @@ package org.jetbrains.kotlin.gradle.plugin.ide.dependencyResolvers import org.gradle.api.artifacts.component.ModuleComponentIdentifier +import org.jetbrains.kotlin.gradle.idea.tcs.IdeaKotlinBinaryDependency +import org.jetbrains.kotlin.gradle.idea.tcs.IdeaKotlinClasspath import org.jetbrains.kotlin.gradle.idea.tcs.IdeaKotlinDependency import org.jetbrains.kotlin.gradle.idea.tcs.IdeaKotlinResolvedBinaryDependency import org.jetbrains.kotlin.gradle.plugin.KotlinSourceSet @@ -30,8 +32,8 @@ internal object IdeOriginalMetadataDependencyResolver : IdeDependencyResolver { return artifactsView.artifacts.mapNotNull { artifact -> val moduleId = artifact.id.componentIdentifier as? ModuleComponentIdentifier ?: return@mapNotNull null IdeaKotlinResolvedBinaryDependency( - binaryType = IdeaKotlinDependency.CLASSPATH_BINARY_TYPE, - binaryFile = artifact.file, + binaryType = IdeaKotlinBinaryDependency.KOTLIN_COMPILE_BINARY_TYPE, + classpath = IdeaKotlinClasspath(artifact.file), coordinates = IdeaKotlinBinaryCoordinates(moduleId) ) }.toSet() diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/ide/dependencyResolvers/IdePlatformSourcesResolver.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/ide/dependencyResolvers/IdePlatformSourcesResolver.kt index db5ca8275a6..01f3de0287b 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/ide/dependencyResolvers/IdePlatformSourcesResolver.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/ide/dependencyResolvers/IdePlatformSourcesResolver.kt @@ -9,12 +9,12 @@ package org.jetbrains.kotlin.gradle.plugin.ide.dependencyResolvers import org.gradle.api.attributes.Category import org.gradle.api.attributes.DocsType -import org.jetbrains.kotlin.gradle.idea.tcs.IdeaKotlinDependency +import org.jetbrains.kotlin.gradle.plugin.ide.IdeDependencyResolver import org.jetbrains.kotlin.gradle.plugin.sources.project import org.jetbrains.kotlin.gradle.utils.named internal fun IdePlatformSourcesResolver(): IdeBinaryDependencyResolver = IdeBinaryDependencyResolver( - binaryType = IdeaKotlinDependency.SOURCES_BINARY_TYPE, + binaryType = IdeDependencyResolver.SOURCES_BINARY_TYPE, artifactResolutionStrategy = IdeBinaryDependencyResolver.ArtifactResolutionStrategy.Compilation( setupArtifactViewAttributes = { attribute(Category.CATEGORY_ATTRIBUTE, it.project.objects.named(Category.DOCUMENTATION)) diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/ide/dependencyResolvers/IdeTransformedMetadataDependencyResolver.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/ide/dependencyResolvers/IdeTransformedMetadataDependencyResolver.kt index d606a2e5aeb..0ad00f3c199 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/ide/dependencyResolvers/IdeTransformedMetadataDependencyResolver.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/ide/dependencyResolvers/IdeTransformedMetadataDependencyResolver.kt @@ -6,9 +6,7 @@ package org.jetbrains.kotlin.gradle.plugin.ide.dependencyResolvers import org.gradle.api.artifacts.component.ProjectComponentIdentifier -import org.jetbrains.kotlin.gradle.idea.tcs.IdeaKotlinBinaryCoordinates -import org.jetbrains.kotlin.gradle.idea.tcs.IdeaKotlinDependency -import org.jetbrains.kotlin.gradle.idea.tcs.IdeaKotlinResolvedBinaryDependency +import org.jetbrains.kotlin.gradle.idea.tcs.* import org.jetbrains.kotlin.gradle.plugin.KotlinSourceSet import org.jetbrains.kotlin.gradle.plugin.ide.IdeDependencyResolver import org.jetbrains.kotlin.gradle.plugin.mpp.MetadataDependencyResolution.ChooseVisibleSourceSets @@ -42,8 +40,8 @@ internal object IdeTransformedMetadataDependencyResolver : IdeDependencyResolver } IdeaKotlinResolvedBinaryDependency( - binaryType = IdeaKotlinDependency.CLASSPATH_BINARY_TYPE, - binaryFile = metadataLibraryOutputFile, + binaryType = IdeaKotlinBinaryDependency.KOTLIN_COMPILE_BINARY_TYPE, + classpath = IdeaKotlinClasspath(metadataLibraryOutputFile), extras = mutableExtrasOf(), coordinates = IdeaKotlinBinaryCoordinates( group = metadataProvider.moduleDependencyIdentifier.groupId ?: "", diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/ide/dependencyResolvers/resolveNativeDistributionDependency.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/ide/dependencyResolvers/resolveNativeDistributionDependency.kt index 0cd4e629d1d..143ed596701 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/ide/dependencyResolvers/resolveNativeDistributionDependency.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/ide/dependencyResolvers/resolveNativeDistributionDependency.kt @@ -11,7 +11,8 @@ import org.jetbrains.kotlin.commonizer.CommonizerTarget import org.jetbrains.kotlin.commonizer.identityString import org.jetbrains.kotlin.compilerRunner.konanVersion import org.jetbrains.kotlin.gradle.idea.tcs.IdeaKotlinBinaryCoordinates -import org.jetbrains.kotlin.gradle.idea.tcs.IdeaKotlinDependency +import org.jetbrains.kotlin.gradle.idea.tcs.IdeaKotlinBinaryDependency +import org.jetbrains.kotlin.gradle.idea.tcs.IdeaKotlinClasspath import org.jetbrains.kotlin.gradle.idea.tcs.IdeaKotlinResolvedBinaryDependency import org.jetbrains.kotlin.gradle.idea.tcs.extras.isNativeDistribution import org.jetbrains.kotlin.gradle.idea.tcs.extras.klibExtra @@ -35,8 +36,8 @@ internal fun Project.resolveNativeDistributionLibraryForIde( } return IdeaKotlinResolvedBinaryDependency( - binaryType = IdeaKotlinDependency.CLASSPATH_BINARY_TYPE, - binaryFile = library, + binaryType = IdeaKotlinBinaryDependency.KOTLIN_COMPILE_BINARY_TYPE, + classpath = IdeaKotlinClasspath(library), coordinates = IdeaKotlinBinaryCoordinates( group = "org.jetbrains.kotlin.native", module = resolvedLibrary.packageFqName ?: resolvedLibrary.shortName ?: resolvedLibrary.uniqueName, diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/ide/dependencyTransformers/UnusedSourcesAndDocumentationFilter.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/ide/dependencyTransformers/UnusedSourcesAndDocumentationFilter.kt deleted file mode 100644 index b7d575d2fae..00000000000 --- a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/ide/dependencyTransformers/UnusedSourcesAndDocumentationFilter.kt +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Copyright 2010-2022 JetBrains s.r.o. and Kotlin Programming Language contributors. - * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. - */ - -package org.jetbrains.kotlin.gradle.plugin.ide.dependencyTransformers - -import org.jetbrains.kotlin.gradle.idea.tcs.IdeaKotlinBinaryCoordinates -import org.jetbrains.kotlin.gradle.idea.tcs.IdeaKotlinDependency -import org.jetbrains.kotlin.gradle.idea.tcs.IdeaKotlinDependency.Companion.CLASSPATH_BINARY_TYPE -import org.jetbrains.kotlin.gradle.idea.tcs.IdeaKotlinDependency.Companion.DOCUMENTATION_BINARY_TYPE -import org.jetbrains.kotlin.gradle.idea.tcs.IdeaKotlinDependency.Companion.SOURCES_BINARY_TYPE -import org.jetbrains.kotlin.gradle.idea.tcs.IdeaKotlinResolvedBinaryDependency -import org.jetbrains.kotlin.gradle.plugin.KotlinSourceSet -import org.jetbrains.kotlin.gradle.plugin.ide.IdeDependencyTransformer -import org.jetbrains.kotlin.gradle.plugin.ide.dependencyResolvers.IdeArtifactResolutionQuerySourcesAndDocumentationResolver - -/** - * Filters out -sources.jar and -javadoc.jar dependencies that are actually not necessary for the KotlinSourceSet: - * This counter-acts the fact that the [IdeArtifactResolutionQuerySourcesAndDocumentationResolver] is potentially "over-resolving" sources - * for multiplatform libraries. - */ -internal object UnusedSourcesAndDocumentationFilter : IdeDependencyTransformer { - - override fun transform(sourceSet: KotlinSourceSet, dependencies: Set): Set { - val binaryDependencies = dependencies.filterIsInstance() - - val classpathBinaryCoordinates = binaryDependencies.filter { it.binaryType == CLASSPATH_BINARY_TYPE } - .mapNotNull { it.coordinates?.relevantString() } - .toSet() - - val unusedDependencies = binaryDependencies.filter { it.binaryType in sourcesAndDocumentationBinaryTypes } - .filter { it.coordinates?.relevantString() !in classpathBinaryCoordinates } - .toSet() - - return dependencies - unusedDependencies - } - - - private val sourcesAndDocumentationBinaryTypes = setOf(SOURCES_BINARY_TYPE, DOCUMENTATION_BINARY_TYPE) - - /** - * This filter only works based upon group, module and version. - * We can consider the sourceSetName to be irrelevant, since we do not have -sources.jar published on a 'per source set' level. - */ - private fun IdeaKotlinBinaryCoordinates.relevantString(): String = "$group:$module:$version" -} - diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/ide/kotlinExtrasSerialization.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/ide/kotlinExtrasSerialization.kt index 9eecef1d8f6..3e5e1cb9541 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/ide/kotlinExtrasSerialization.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/ide/kotlinExtrasSerialization.kt @@ -6,6 +6,7 @@ package org.jetbrains.kotlin.gradle.plugin.ide import org.jetbrains.kotlin.gradle.InternalKotlinGradlePluginApi +import org.jetbrains.kotlin.gradle.idea.proto.tcs.IdeaKotlinClasspathSerializer import org.jetbrains.kotlin.gradle.idea.serialize.IdeaKotlinBooleanExtrasSerializer import org.jetbrains.kotlin.gradle.idea.serialize.IdeaKotlinExtrasSerializationExtension import org.jetbrains.kotlin.gradle.idea.serialize.IdeaKotlinExtrasSerializer.Companion.javaIoSerializable @@ -20,4 +21,7 @@ val kotlinExtrasSerialization = IdeaKotlinExtrasSerializationExtension { register(isNativeDistributionKey, IdeaKotlinBooleanExtrasSerializer) register(isNativeStdlibKey, IdeaKotlinBooleanExtrasSerializer) register(isCommonizedKey, IdeaKotlinBooleanExtrasSerializer) + register(sourcesClasspathKey, IdeaKotlinClasspathSerializer) + register(documentationClasspathKey, IdeaKotlinClasspathSerializer) + register(projectArtifactsClasspathKey, IdeaKotlinClasspathSerializer) } diff --git a/libraries/tools/kotlin-gradle-plugin/src/functionalTest/kotlin/org/jetbrains/kotlin/gradle/ide/IdeSourcesAndDocumentationResolutionTest.kt b/libraries/tools/kotlin-gradle-plugin/src/functionalTest/kotlin/org/jetbrains/kotlin/gradle/ide/IdeSourcesAndDocumentationResolutionTest.kt index 17f680a58e1..5e9c927bc93 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/functionalTest/kotlin/org/jetbrains/kotlin/gradle/ide/IdeSourcesAndDocumentationResolutionTest.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/functionalTest/kotlin/org/jetbrains/kotlin/gradle/ide/IdeSourcesAndDocumentationResolutionTest.kt @@ -13,7 +13,9 @@ import org.jetbrains.kotlin.gradle.dsl.multiplatformExtension import org.jetbrains.kotlin.gradle.enableDefaultStdlibDependency import org.jetbrains.kotlin.gradle.enableDependencyVerification import org.jetbrains.kotlin.gradle.idea.tcs.IdeaKotlinResolvedBinaryDependency -import org.jetbrains.kotlin.gradle.idea.tcs.isSourcesBinaryType +import org.jetbrains.kotlin.gradle.idea.tcs.extras.documentationClasspathKey +import org.jetbrains.kotlin.gradle.idea.tcs.extras.sourcesClasspath +import org.jetbrains.kotlin.gradle.idea.tcs.extras.sourcesClasspathKey import org.jetbrains.kotlin.gradle.idea.testFixtures.tcs.assertMatches import org.jetbrains.kotlin.gradle.idea.testFixtures.tcs.binaryCoordinates import org.jetbrains.kotlin.gradle.kpm.idea.mavenCentralCacheRedirector @@ -57,36 +59,36 @@ class IdeSourcesAndDocumentationResolutionTest { fun resolveDependencySources(sourceSet: KotlinSourceSet): List = project.kotlinIdeMultiplatformImport.resolveDependencies(sourceSet) .filterIsInstance() - .filter { it.isSourcesBinaryType } - + .filter { it.sourcesClasspath.isNotEmpty() } /* Check commonMain&commonTest */ run { val expectedDependencies = listOf( - binaryCoordinates("com.arkivanov.mvikotlin:mvikotlin:3.0.2"), - binaryCoordinates("com.arkivanov.essenty:lifecycle:0.4.2"), - binaryCoordinates("com.arkivanov.essenty:instance-keeper:0.4.2"), + binaryCoordinates("com.arkivanov.mvikotlin:mvikotlin:3.0.2:commonMain"), + binaryCoordinates("com.arkivanov.essenty:lifecycle:0.4.2:commonMain"), + binaryCoordinates("com.arkivanov.essenty:instance-keeper:0.4.2:commonMain"), ) val resolvedDependencies = resolveDependencySources(commonMain) resolvedDependencies.assertMatches(expectedDependencies) resolveDependencySources(commonTest).assertMatches(resolvedDependencies) - resolvedDependencies.assertFilesEndWith("-sources.jar") + resolvedDependencies.assertSourcesFilesEndWith("-sources.jar") } /* Check nativeMain&nativeTest */ run { val expectedDependencies = listOf( - binaryCoordinates("com.arkivanov.mvikotlin:mvikotlin:3.0.2"), - binaryCoordinates("com.arkivanov.essenty:lifecycle:0.4.2"), - binaryCoordinates("com.arkivanov.essenty:instance-keeper:0.4.2"), + binaryCoordinates("com.arkivanov.mvikotlin:mvikotlin:3.0.2:commonMain"), + binaryCoordinates("com.arkivanov.mvikotlin:mvikotlin:3.0.2:jsNativeMain"), + binaryCoordinates("com.arkivanov.essenty:lifecycle:0.4.2:commonMain"), + binaryCoordinates("com.arkivanov.essenty:instance-keeper:0.4.2:commonMain"), IdeNativeStdlibDependencyResolver.nativeStdlibCoordinates(project) ) val resolvedDependencies = resolveDependencySources(nativeMain) resolvedDependencies.assertMatches(expectedDependencies) resolveDependencySources(nativeTest).assertMatches(resolvedDependencies) - resolvedDependencies.assertFilesEndWith("-sources.jar", "-sources.zip") + resolvedDependencies.assertSourcesFilesEndWith("-sources.jar", "-sources.zip") } /* Check linuxX64Main and linuxX64Test */ @@ -114,16 +116,25 @@ class IdeSourcesAndDocumentationResolutionTest { val resolvedDependencies = resolveDependencySources(linuxX64Main) resolvedDependencies.assertMatches(expectedDependencies) - resolveDependencySources(linuxX64Test).assertMatches(resolvedDependencies) - resolvedDependencies.assertFilesEndWith("-sources.jar", "-sources.zip") + resolveDependencySources(linuxX64Test).withSanitisedExtras().assertMatches(resolvedDependencies.withSanitisedExtras()) + resolvedDependencies.assertSourcesFilesEndWith("-sources.jar", "-sources.zip") } } } -private fun Iterable.assertFilesEndWith(vararg suffixes: String) { +private fun Iterable.withSanitisedExtras() = onEach { dependency -> + val keysToKeep = setOf(sourcesClasspathKey, documentationClasspathKey) + (dependency.extras.keys - keysToKeep).forEach { keyToRemove -> + dependency.extras.remove(keyToRemove) + } +} + +private fun Iterable.assertSourcesFilesEndWith(vararg suffixes: String) { forEach { dependency -> - if (suffixes.none { suffix -> dependency.binaryFile.path.endsWith(suffix) }) { - fail("Expected binaryFile to end with one of ${suffixes.toList()}. Found: ${dependency.binaryFile}") + dependency.sourcesClasspath.forEach { sourcesFile -> + if (suffixes.none { suffix -> sourcesFile.path.endsWith(suffix) }) { + fail("Expected binaryFile to end with one of ${suffixes.toList()}. Found: ${sourcesFile}") + } } } -} \ No newline at end of file +}