From 6d6fcb0dfc6f83df186a9ea93396efd2cdf527c3 Mon Sep 17 00:00:00 2001 From: Alexey Eremin Date: Mon, 1 Aug 2022 22:55:18 +0200 Subject: [PATCH] Mark receiver parameter type as referenced. --- .../kotlin/plugin/jdeps/JdepsGenExtension.kt | 26 +++++-- .../tasks/jvm/KotlinBuilderJvmJdepsTest.kt | 68 +++++++++++++++++++ 2 files changed, 87 insertions(+), 7 deletions(-) diff --git a/src/main/kotlin/io/bazel/kotlin/plugin/jdeps/JdepsGenExtension.kt b/src/main/kotlin/io/bazel/kotlin/plugin/jdeps/JdepsGenExtension.kt index c5a3665e7..643483859 100644 --- a/src/main/kotlin/io/bazel/kotlin/plugin/jdeps/JdepsGenExtension.kt +++ b/src/main/kotlin/io/bazel/kotlin/plugin/jdeps/JdepsGenExtension.kt @@ -139,7 +139,7 @@ class JdepsGenExtension( is FunctionDescriptor -> { resultingDescriptor.returnType?.let { addImplicitDep(it) } resultingDescriptor.valueParameters.forEach { valueParameter -> - addImplicitDep(valueParameter.type) + collectTypeReferences(valueParameter.type, isExplicit = false) } val virtualFileClass = resultingDescriptor.getContainingKotlinJvmBinaryClass() as? VirtualFileKotlinClass ?: return @@ -217,8 +217,14 @@ class JdepsGenExtension( * are other types required for compilation such as supertypes and interfaces of those explicit * types. */ - private fun collectTypeReferences(kotlinType: KotlinType, collectSuperTypes: Boolean = true) { - addExplicitDep(kotlinType) + private fun collectTypeReferences(kotlinType: KotlinType, + isExplicit: Boolean = true, + collectSuperTypes: Boolean = true) { + if (isExplicit) { + addExplicitDep(kotlinType) + } else { + addImplicitDep(kotlinType) + } if (collectSuperTypes) { kotlinType.supertypes().forEach { @@ -226,16 +232,22 @@ class JdepsGenExtension( } } - collectTypeArguments(kotlinType) + collectTypeArguments(kotlinType, isExplicit) } - fun collectTypeArguments(kotlinType: KotlinType, visitedKotlinTypes: MutableSet = mutableSetOf()) { + fun collectTypeArguments(kotlinType: KotlinType, + isExplicit: Boolean, + visitedKotlinTypes: MutableSet = mutableSetOf()) { visitedKotlinTypes.add(kotlinType) kotlinType.arguments.map { it.type }.forEach { typeArgument -> - addExplicitDep(typeArgument) + if (isExplicit) { + addExplicitDep(typeArgument) + } else { + addImplicitDep(typeArgument) + } typeArgument.supertypes().forEach { addImplicitDep(it) } if (!visitedKotlinTypes.contains(typeArgument)) { - collectTypeArguments(typeArgument, visitedKotlinTypes) + collectTypeArguments(typeArgument, isExplicit, visitedKotlinTypes) } } } diff --git a/src/test/kotlin/io/bazel/kotlin/builder/tasks/jvm/KotlinBuilderJvmJdepsTest.kt b/src/test/kotlin/io/bazel/kotlin/builder/tasks/jvm/KotlinBuilderJvmJdepsTest.kt index a01d4ce54..b12d65dc3 100644 --- a/src/test/kotlin/io/bazel/kotlin/builder/tasks/jvm/KotlinBuilderJvmJdepsTest.kt +++ b/src/test/kotlin/io/bazel/kotlin/builder/tasks/jvm/KotlinBuilderJvmJdepsTest.kt @@ -1222,6 +1222,74 @@ class KotlinBuilderJvmJdepsTest { assertImplicit(jdeps).doesNotContain(depWithReturnTypesSuperType) } + @Test + fun `function call receiver type`() { + val depWithReceiverTypeSuperType = ctx.runCompileTask(Consumer { c: KotlinJvmTestBuilder.TaskBuilder -> + c.addSource("SomeSuperType.kt", + """ + package something + + open class SomeSuperType {} + """) + c.outputJar() + c.outputJdeps() + c.compileKotlin() + c.setLabel("depWithSuperType") + }) + val depWithReceiverType = ctx.runCompileTask(Consumer { c: KotlinJvmTestBuilder.TaskBuilder -> + c.addSource("SomeType.kt", + """ + package something + + class SomeType : SomeSuperType() {} + """) + c.outputJar() + c.outputJdeps() + c.compileKotlin() + c.setLabel("depWithReceiverType") + c.addDirectDependencies(depWithReceiverTypeSuperType) + }) + + val depWithFunction = ctx.runCompileTask(Consumer { c: KotlinJvmTestBuilder.TaskBuilder -> + c.addSource("ContainsFunction.kt", + """ + package something + + fun receiverSomeType(arg: SomeType.() -> Unit) {} + """) + c.outputJar() + c.compileKotlin() + c.addDirectDependencies(depWithReceiverType) + c.addTransitiveDependencies(depWithReceiverTypeSuperType) + c.setLabel("depWithFunction") + }) + + val dependingTarget = ctx.runCompileTask(Consumer { c: KotlinJvmTestBuilder.TaskBuilder -> + c.addSource("CallsFunctionWithReceiver.kt", + """ + package something + + fun foo() { + receiverSomeType { + } + } + """) + c.outputJar() + c.compileKotlin() + c.addDirectDependencies(depWithFunction) + c.addTransitiveDependencies(depWithReceiverType, depWithReceiverTypeSuperType) + c.outputJdeps() + c.setLabel("dependingTarget") + }) + val jdeps = depsProto(dependingTarget) + + assertThat(jdeps.ruleLabel).isEqualTo(dependingTarget.label()) + + assertExplicit(jdeps).contains(depWithFunction.singleCompileJar()) + assertImplicit(jdeps).contains(depWithReceiverType.singleCompileJar()) + assertImplicit(jdeps).contains(depWithReceiverTypeSuperType.singleCompileJar()) + } + @Test fun `constructor parameters are required implicit dependencies`() { val fooDep = ctx.runCompileTask(Consumer { c: KotlinJvmTestBuilder.TaskBuilder ->