From d6c25c5a4e3a449d6a4a2f25dc4fa9ca97dd3fff Mon Sep 17 00:00:00 2001 From: Jonathan Gerrish Date: Wed, 17 Feb 2021 05:02:25 -0800 Subject: [PATCH 1/7] * Support property annotations --- .../kotlin/plugin/jdeps/JdepsGenExtension.kt | 3 ++ .../tasks/jvm/KotlinBuilderJvmJdepsTest.kt | 44 +++++++++++++++++++ 2 files changed, 47 insertions(+) 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 d95064336..e742bac7f 100644 --- a/src/main/kotlin/io/bazel/kotlin/plugin/jdeps/JdepsGenExtension.kt +++ b/src/main/kotlin/io/bazel/kotlin/plugin/jdeps/JdepsGenExtension.kt @@ -181,6 +181,9 @@ class JdepsGenExtension( } is PropertyDescriptor -> { collectTypeReferences(descriptor.type) + descriptor.annotations.forEach { annotation -> + collectTypeReferences(annotation.type) + } } is LocalVariableDescriptor -> { collectTypeReferences(descriptor.type) 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 293d87ef4..6484436dd 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 @@ -280,6 +280,50 @@ class KotlinBuilderJvmJdepsTest { assertIncomplete(jdeps).isEmpty() } + @Test + fun `java annotation on property is an explict dep`() { + + val dependentTarget = ctx.runCompileTask(Consumer { c: KotlinJvmTestBuilder.TaskBuilder -> + c.addSource("JavaAnnotation.java", + """ + package something; + + import java.lang.annotation.Retention; + import java.lang.annotation.RetentionPolicy; + + @Retention(RetentionPolicy.RUNTIME) + public @interface JavaAnnotation { + } + """) + c.outputJar() + c.compileJava() + }) + + val dependingTarget = ctx.runCompileTask(Consumer { c: KotlinJvmTestBuilder.TaskBuilder -> + c.addSource("AnotherClass.kt", + """ + package something + + class AnotherClass { + @JavaAnnotation + val property = 42 + } + """) + c.outputJar() + c.compileKotlin() + c.outputJdeps() + c.addDirectDependencies(dependentTarget) + }) + val jdeps = depsProto(dependingTarget) + + assertThat(jdeps.ruleLabel).isEqualTo(dependingTarget.label()) + + assertExplicit(jdeps).contains(dependentTarget.singleCompileJar()) + assertImplicit(jdeps).isEmpty() + assertUnused(jdeps).isEmpty() + assertIncomplete(jdeps).isEmpty() + } + @Test fun `unused dependency listed`() { From 379b564ea22b9db059f5defbf9becedf3084c7d4 Mon Sep 17 00:00:00 2001 From: Jonathan Gerrish Date: Wed, 17 Feb 2021 05:25:36 -0800 Subject: [PATCH 2/7] * Property reference to class with super type should collect super references. --- .../kotlin/plugin/jdeps/JdepsGenExtension.kt | 2 +- .../tasks/jvm/KotlinBuilderJvmJdepsTest.kt | 50 +++++++++++++++++++ 2 files changed, 51 insertions(+), 1 deletion(-) 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 e742bac7f..eeaae94c2 100644 --- a/src/main/kotlin/io/bazel/kotlin/plugin/jdeps/JdepsGenExtension.kt +++ b/src/main/kotlin/io/bazel/kotlin/plugin/jdeps/JdepsGenExtension.kt @@ -143,7 +143,7 @@ class JdepsGenExtension( getClassCanonicalPath(resultingDescriptor)?.let { explicitClassesCanonicalPaths.add(it) } } is FakeCallableDescriptorForObject -> { - getClassCanonicalPath(resultingDescriptor)?.let { explicitClassesCanonicalPaths.add(it) } + collectTypeReferences(resultingDescriptor.type) } is JavaPropertyDescriptor -> { getClassCanonicalPath(resultingDescriptor)?.let { explicitClassesCanonicalPaths.add(it) } 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 6484436dd..4eb370422 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 @@ -883,6 +883,56 @@ class KotlinBuilderJvmJdepsTest { assertUnused(jdeps).isEmpty() assertIncomplete(jdeps).isEmpty() } + @Test + fun `property reference should collect indirect super class as implicit dependency`() { + val implicitSuperClassDep = ctx.runCompileTask(Consumer { c: KotlinJvmTestBuilder.TaskBuilder -> + c.addSource("Base.kt", + """ + package something + + open class Base(p: Int) + """) + c.outputJar() + c.compileKotlin() + }) + + val explicitSuperClassDep = ctx.runCompileTask(Consumer { c: KotlinJvmTestBuilder.TaskBuilder -> + c.addSource("Derived.kt", + """ + package something + + object Derived : Base(41) { + @JvmField + val SOME_CONST = 42 + } + """) + c.outputJar() + c.compileKotlin() + c.addDirectDependencies(implicitSuperClassDep) + }) + + val dependingTarget = ctx.runCompileTask(Consumer { c: KotlinJvmTestBuilder.TaskBuilder -> + c.addSource("ReferencesClassWithSuperClass.kt", + """ + package something + + val classRef = Derived.SOME_CONST + """) + c.outputJar() + c.compileKotlin() + c.addDirectDependencies(explicitSuperClassDep) + c.addTransitiveDependencies(implicitSuperClassDep) + c.outputJdeps() + }) + val jdeps = depsProto(dependingTarget) + + assertThat(jdeps.ruleLabel).isEqualTo(dependingTarget.label()) + + assertExplicit(jdeps).containsExactly(explicitSuperClassDep.singleCompileJar()) + assertImplicit(jdeps).containsExactly(implicitSuperClassDep.singleCompileJar()) + assertUnused(jdeps).isEmpty() + assertIncomplete(jdeps).isEmpty() + } @Test fun `class declaration all super class references should be an implicit dependency`() { From 92a8eb40f9837652a88caac651df0fdbc3bd78db Mon Sep 17 00:00:00 2001 From: Jonathan Gerrish Date: Wed, 17 Feb 2021 05:46:40 -0800 Subject: [PATCH 3/7] * Support functions imported from objects. --- .../kotlin/plugin/jdeps/JdepsGenExtension.kt | 10 +++-- .../tasks/jvm/KotlinBuilderJvmJdepsTest.kt | 40 +++++++++++++++++++ 2 files changed, 47 insertions(+), 3 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 eeaae94c2..8f8fcdea2 100644 --- a/src/main/kotlin/io/bazel/kotlin/plugin/jdeps/JdepsGenExtension.kt +++ b/src/main/kotlin/io/bazel/kotlin/plugin/jdeps/JdepsGenExtension.kt @@ -32,6 +32,7 @@ import org.jetbrains.kotlin.platform.TargetPlatform import org.jetbrains.kotlin.psi.KtDeclaration import org.jetbrains.kotlin.psi.KtFile import org.jetbrains.kotlin.resolve.BindingTrace +import org.jetbrains.kotlin.resolve.FunctionImportedFromObject import org.jetbrains.kotlin.resolve.PropertyImportedFromObject import org.jetbrains.kotlin.resolve.calls.checkers.CallChecker import org.jetbrains.kotlin.resolve.calls.checkers.CallCheckerContext @@ -127,6 +128,12 @@ class JdepsGenExtension( context: CallCheckerContext ) { when (val resultingDescriptor = resolvedCall.resultingDescriptor) { + is FunctionImportedFromObject -> { + collectTypeReferences((resolvedCall.resultingDescriptor as FunctionImportedFromObject).containingObject.defaultType) + } + is PropertyImportedFromObject -> { + collectTypeReferences((resolvedCall.resultingDescriptor as PropertyImportedFromObject).containingObject.defaultType) + } is JavaMethodDescriptor -> { getClassCanonicalPath((resultingDescriptor.containingDeclaration as ClassDescriptor).typeConstructor)?.let { explicitClassesCanonicalPaths.add(it) } } @@ -148,9 +155,6 @@ class JdepsGenExtension( is JavaPropertyDescriptor -> { getClassCanonicalPath(resultingDescriptor)?.let { explicitClassesCanonicalPaths.add(it) } } - is PropertyImportedFromObject -> { - collectTypeReferences((resolvedCall.resultingDescriptor as PropertyImportedFromObject).containingObject.defaultType) - } is PropertyDescriptor -> { val virtualFileClass = (resultingDescriptor).getContainingKotlinJvmBinaryClass() as? VirtualFileKotlinClass ?: return explicitClassesCanonicalPaths.add(virtualFileClass.file.path) 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 4eb370422..9c64992af 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 @@ -478,6 +478,46 @@ class KotlinBuilderJvmJdepsTest { assertIncomplete(jdeps).isEmpty() } + @Test + fun `kotlin extension property reference 2`() { + val dependentTarget = ctx.runCompileTask(Consumer { c: KotlinJvmTestBuilder.TaskBuilder -> + c.addSource("AClass.kt", + """ + package something + + object Extensions { + @JvmStatic + fun String.doubleLength() = length * 2 + } + """) + c.outputJar() + c.compileKotlin() + }) + + val dependingTarget = ctx.runCompileTask(Consumer { c: KotlinJvmTestBuilder.TaskBuilder -> + c.addSource("HasPropertyDependency.kt", + """ + package something + + import something.Extensions.doubleLength + + val property2 = "Hello".doubleLength() + """) + c.outputJar() + c.compileKotlin() + c.addDirectDependencies(dependentTarget) + c.outputJdeps() + }) + val jdeps = depsProto(dependingTarget) + + assertThat(jdeps.ruleLabel).isEqualTo(dependingTarget.label()) + + assertExplicit(jdeps).containsExactly(dependentTarget.singleCompileJar()) + assertImplicit(jdeps).isEmpty() + assertUnused(jdeps).isEmpty() + assertIncomplete(jdeps).isEmpty() + } + @Test fun `kotlin property definition`() { val dependentTarget = ctx.runCompileTask(Consumer { c: KotlinJvmTestBuilder.TaskBuilder -> From 014069234e1fb378ef75276f5d01905f60b5dcba Mon Sep 17 00:00:00 2001 From: Jonathan Gerrish Date: Wed, 17 Feb 2021 06:25:45 -0800 Subject: [PATCH 4/7] * Support enum property references --- .../kotlin/plugin/jdeps/JdepsGenExtension.kt | 9 ++++- .../tasks/jvm/KotlinBuilderJvmJdepsTest.kt | 40 +++++++++++++++++++ 2 files changed, 47 insertions(+), 2 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 8f8fcdea2..0f6a79b4e 100644 --- a/src/main/kotlin/io/bazel/kotlin/plugin/jdeps/JdepsGenExtension.kt +++ b/src/main/kotlin/io/bazel/kotlin/plugin/jdeps/JdepsGenExtension.kt @@ -156,8 +156,13 @@ class JdepsGenExtension( getClassCanonicalPath(resultingDescriptor)?.let { explicitClassesCanonicalPaths.add(it) } } is PropertyDescriptor -> { - val virtualFileClass = (resultingDescriptor).getContainingKotlinJvmBinaryClass() as? VirtualFileKotlinClass ?: return - explicitClassesCanonicalPaths.add(virtualFileClass.file.path) + when (resultingDescriptor.containingDeclaration) { + is ClassDescriptor -> collectTypeReferences((resultingDescriptor.containingDeclaration as ClassDescriptor).defaultType) + else -> { + val virtualFileClass = (resultingDescriptor).getContainingKotlinJvmBinaryClass() as? VirtualFileKotlinClass ?: return + explicitClassesCanonicalPaths.add(virtualFileClass.file.path) + } + } } else -> return } 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 9c64992af..a38dcbe11 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 @@ -561,6 +561,46 @@ class KotlinBuilderJvmJdepsTest { assertIncomplete(jdeps).isEmpty() } + @Test + fun `java enum reference`() { + val dependentTarget = ctx.runCompileTask(Consumer { c: KotlinJvmTestBuilder.TaskBuilder -> + c.addSource("InnerJavaEnum.java", + """ + package something; + + public enum InnerJavaEnum { + A_VALUE; + } + """) + c.outputJar() + c.compileJava() + }) + + val dependingTarget = ctx.runCompileTask(Consumer { c: KotlinJvmTestBuilder.TaskBuilder -> + c.addSource("HasPropertyDefinition.kt", + """ + package something + + class Foo { + + val result = InnerJavaEnum.A_VALUE.name + } + """) + c.outputJar() + c.compileKotlin() + c.addDirectDependencies(dependentTarget) + c.outputJdeps() + }) + val jdeps = depsProto(dependingTarget) + + assertThat(jdeps.ruleLabel).isEqualTo(dependingTarget.label()) + + assertExplicit(jdeps).containsExactly(dependentTarget.singleCompileJar()) + assertImplicit(jdeps).isEmpty() + assertUnused(jdeps).isEmpty() + assertIncomplete(jdeps).isEmpty() + } + @Test fun `kotlin method reference`() { val dependentTarget = ctx.runCompileTask(Consumer { c: KotlinJvmTestBuilder.TaskBuilder -> From 45398c5e00f2a2ee1ae80dd4dd3646a15c8e8521 Mon Sep 17 00:00:00 2001 From: Jonathan Gerrish Date: Wed, 17 Feb 2021 09:27:30 -0800 Subject: [PATCH 5/7] * Support annotations with target = FIELD are located on backing field. --- .../kotlin/plugin/jdeps/JdepsGenExtension.kt | 3 ++ .../tasks/jvm/KotlinBuilderJvmJdepsTest.kt | 47 +++++++++++++++++++ 2 files changed, 50 insertions(+) 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 0f6a79b4e..bf3902023 100644 --- a/src/main/kotlin/io/bazel/kotlin/plugin/jdeps/JdepsGenExtension.kt +++ b/src/main/kotlin/io/bazel/kotlin/plugin/jdeps/JdepsGenExtension.kt @@ -193,6 +193,9 @@ class JdepsGenExtension( descriptor.annotations.forEach { annotation -> collectTypeReferences(annotation.type) } + descriptor.backingField?.annotations?.forEach { annotation -> + collectTypeReferences(annotation.type) + } } is LocalVariableDescriptor -> { collectTypeReferences(descriptor.type) 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 a38dcbe11..8ea8022f7 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 @@ -324,6 +324,53 @@ class KotlinBuilderJvmJdepsTest { assertIncomplete(jdeps).isEmpty() } + @Test + fun `java annotation with field target on companion object property is an explict dep`() { + + val dependentTarget = ctx.runCompileTask(Consumer { c: KotlinJvmTestBuilder.TaskBuilder -> + c.addSource("LayoutRes.java", + """ + package androidx.annotation; + import static java.lang.annotation.ElementType.FIELD; + import java.lang.annotation.Target; + @Target({FIELD}) + public @interface LayoutRes { + } + """) + c.outputJar() + c.compileJava() + }) + + val dependingTarget = ctx.runCompileTask(Consumer { c: KotlinJvmTestBuilder.TaskBuilder -> + c.addSource("AnotherClass.kt", + """ + package something + + import androidx.annotation.LayoutRes + + class AnotherClass { + companion object { + + @JvmField @LayoutRes + val property = 42 + } + } + """) + c.outputJar() + c.compileKotlin() + c.outputJdeps() + c.addDirectDependencies(dependentTarget) + }) + val jdeps = depsProto(dependingTarget) + + assertThat(jdeps.ruleLabel).isEqualTo(dependingTarget.label()) + + assertExplicit(jdeps).contains(dependentTarget.singleCompileJar()) + assertImplicit(jdeps).isEmpty() + assertUnused(jdeps).isEmpty() + assertIncomplete(jdeps).isEmpty() + } + @Test fun `unused dependency listed`() { From fb1e432080d04086879d655bb3825cd52190eb78 Mon Sep 17 00:00:00 2001 From: Jonathan Gerrish Date: Wed, 17 Feb 2021 10:55:14 -0800 Subject: [PATCH 6/7] * Support indirect property references --- .../kotlin/plugin/jdeps/JdepsGenExtension.kt | 1 + .../tasks/jvm/KotlinBuilderJvmJdepsTest.kt | 55 +++++++++++++++++++ 2 files changed, 56 insertions(+) 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 bf3902023..20cca7221 100644 --- a/src/main/kotlin/io/bazel/kotlin/plugin/jdeps/JdepsGenExtension.kt +++ b/src/main/kotlin/io/bazel/kotlin/plugin/jdeps/JdepsGenExtension.kt @@ -163,6 +163,7 @@ class JdepsGenExtension( explicitClassesCanonicalPaths.add(virtualFileClass.file.path) } } + addImplicitDep(resultingDescriptor.type) } else -> return } 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 8ea8022f7..35aa71af9 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 @@ -489,6 +489,61 @@ class KotlinBuilderJvmJdepsTest { assertIncomplete(jdeps).isEmpty() } + @Test + fun `kotlin indirect property reference on object`() { + val transitivePropertyTarget = ctx.runCompileTask(Consumer { c: KotlinJvmTestBuilder.TaskBuilder -> + c.addSource("Bar.kt", + """ + package something + + class Bar { + fun helloWorld() {} + } + """) + c.outputJar() + c.compileKotlin() + }) + + val dependentTarget = ctx.runCompileTask(Consumer { c: KotlinJvmTestBuilder.TaskBuilder -> + c.addSource("Foo.kt", + """ + package something + + class Foo { + val bar = Bar() + } + """) + c.outputJar() + c.addDirectDependencies(transitivePropertyTarget) + c.compileKotlin() + }) + + val dependingTarget = ctx.runCompileTask(Consumer { c: KotlinJvmTestBuilder.TaskBuilder -> + c.addSource("HasPropertyDependency.kt", + """ + package something + + fun something(foo: Foo) { + val foo = Foo() + foo.bar.helloWorld() + } + """) + c.outputJar() + c.compileKotlin() + c.addDirectDependencies(dependentTarget) + c.addTransitiveDependencies(transitivePropertyTarget) + c.outputJdeps() + }) + val jdeps = depsProto(dependingTarget) + + assertThat(jdeps.ruleLabel).isEqualTo(dependingTarget.label()) + + assertExplicit(jdeps).contains(dependentTarget.singleCompileJar()) + assertExplicit(jdeps).contains(transitivePropertyTarget.singleCompileJar()) + assertUnused(jdeps).isEmpty() + assertIncomplete(jdeps).isEmpty() + } + @Test fun `kotlin extension property reference`() { val dependentTarget = ctx.runCompileTask(Consumer { c: KotlinJvmTestBuilder.TaskBuilder -> From 3fbd8b74dc006e9e23a2c60f46bfa0b890dd1737 Mon Sep 17 00:00:00 2001 From: Jonathan Gerrish Date: Thu, 18 Feb 2021 05:57:45 -0800 Subject: [PATCH 7/7] * Support nested type parameters --- .../kotlin/plugin/jdeps/JdepsGenExtension.kt | 5 ++ .../tasks/jvm/KotlinBuilderJvmJdepsTest.kt | 47 +++++++++++++++++++ 2 files changed, 52 insertions(+) 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 20cca7221..a7dabe8a0 100644 --- a/src/main/kotlin/io/bazel/kotlin/plugin/jdeps/JdepsGenExtension.kt +++ b/src/main/kotlin/io/bazel/kotlin/plugin/jdeps/JdepsGenExtension.kt @@ -227,9 +227,14 @@ class JdepsGenExtension( } } + collectTypeArguments(kotlinType) + } + + fun collectTypeArguments(kotlinType: KotlinType) { kotlinType.arguments.map { it.type }.forEach { typeArgument -> addExplicitDep(typeArgument) typeArgument.supertypes().forEach { addImplicitDep(it) } + collectTypeArguments(typeArgument) } } } 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 35aa71af9..e5429b637 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 @@ -1457,6 +1457,53 @@ class KotlinBuilderJvmJdepsTest { assertImplicit(jdeps).doesNotContain(depWithTypeParameter.singleCompileJar()) } + @Test + fun `function call parameter type nested type parameters should be an explicit dependency`() { + + val foo = ctx.runCompileTask(Consumer { c: KotlinJvmTestBuilder.TaskBuilder -> + c.addSource("Foo.kt", + """ + package something + + class Foo { } + """) + c.outputJar() + c.compileKotlin() + }) + + val bar = ctx.runCompileTask(Consumer { c: KotlinJvmTestBuilder.TaskBuilder -> + c.addSource("Bar.kt", + """ + package something + + class Bar { + val booleanValue = true + } + """) + c.outputJar() + c.compileKotlin() + }) + + val dependingTarget = ctx.runCompileTask(Consumer { c: KotlinJvmTestBuilder.TaskBuilder -> + c.addSource("FunctionWithTypeParams.kt", + """ + package something + + fun foo(param: Set>) { + + } + """) + c.outputJar() + c.compileKotlin() + c.addDirectDependencies(foo, bar) + c.outputJdeps() + }) + val jdeps = depsProto(dependingTarget) + + assertExplicit(jdeps).contains(bar.singleCompileJar()) + assertExplicit(jdeps).contains(foo.singleCompileJar()) + } + @Test fun `assignment from function call`() { val depWithReturnTypesSuperType = ctx.runCompileTask(Consumer { c: KotlinJvmTestBuilder.TaskBuilder ->