Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Capture more jdeps cases #475

Merged
merged 1 commit into from
Feb 5, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -63,13 +63,15 @@ class KotlinJvmTaskExecutor @Inject internal constructor(
context,
compiler,
args = baseArgs()
.plugin(plugins.jdeps) {
flag("output", outputs.jdeps)
flag("target_label", info.label)
inputs.directDependenciesList.forEach {
flag("direct_dependencies", it)
.given(outputs.jdeps).notEmpty {
plugin(plugins.jdeps) {
flag("output", outputs.jdeps)
flag("target_label", info.label)
inputs.directDependenciesList.forEach {
flag("direct_dependencies", it)
}
flag("strict_kotlin_deps", info.strictKotlinDeps)
}
flag("strict_kotlin_deps", info.strictKotlinDeps)
}
.given(outputs.jar).notEmpty {
append(codeGenArgs())
Expand Down
52 changes: 38 additions & 14 deletions src/main/kotlin/io/bazel/kotlin/plugin/jdeps/JdepsGenExtension.kt
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,15 @@ import org.jetbrains.kotlin.analyzer.AnalysisResult
import org.jetbrains.kotlin.config.CompilerConfiguration
import org.jetbrains.kotlin.container.StorageComponentContainer
import org.jetbrains.kotlin.container.useInstance
import org.jetbrains.kotlin.descriptors.ClassDescriptor
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
import org.jetbrains.kotlin.descriptors.DeclarationDescriptorWithSource
import org.jetbrains.kotlin.descriptors.ModuleDescriptor
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
import org.jetbrains.kotlin.descriptors.ParameterDescriptor
import org.jetbrains.kotlin.descriptors.PropertyDescriptor
import org.jetbrains.kotlin.descriptors.SourceElement
import org.jetbrains.kotlin.descriptors.impl.LocalVariableDescriptor
import org.jetbrains.kotlin.extensions.StorageComponentContainerContributor
import org.jetbrains.kotlin.load.java.descriptors.JavaPropertyDescriptor
import org.jetbrains.kotlin.load.java.sources.JavaSourceElement
Expand All @@ -36,6 +39,8 @@ import org.jetbrains.kotlin.resolve.checkers.DeclarationChecker
import org.jetbrains.kotlin.resolve.checkers.DeclarationCheckerContext
import org.jetbrains.kotlin.resolve.jvm.extensions.AnalysisHandlerExtension
import org.jetbrains.kotlin.types.KotlinType
import org.jetbrains.kotlin.types.TypeConstructor
import org.jetbrains.kotlin.types.typeUtil.supertypes
import java.io.BufferedOutputStream
import java.io.File
import java.nio.file.Paths
Expand Down Expand Up @@ -92,6 +97,10 @@ class JdepsGenExtension(
else -> null
}
}

fun getClassCanonicalPath(typeConstructor: TypeConstructor): String? {
return (typeConstructor.declarationDescriptor as? DeclarationDescriptorWithSource)?.let { getClassCanonicalPath(it) }
}
}

private val explicitClassesCanonicalPaths = mutableSetOf<String>()
Expand All @@ -117,10 +126,14 @@ class JdepsGenExtension(
) {
when (val resultingDescriptor = resolvedCall.resultingDescriptor) {
is FunctionDescriptor -> {
resultingDescriptor.returnType?.let { addImplicitDep(it) }
val virtualFileClass = resultingDescriptor.getContainingKotlinJvmBinaryClass() as? VirtualFileKotlinClass
?: return
explicitClassesCanonicalPaths.add(virtualFileClass.file.path)
}
is ParameterDescriptor -> {
getClassCanonicalPath(resultingDescriptor)?.let { explicitClassesCanonicalPaths.add(it) }
}
is FakeCallableDescriptorForObject -> {
getClassCanonicalPath(resultingDescriptor)?.let { explicitClassesCanonicalPaths.add(it) }
}
Expand All @@ -140,6 +153,11 @@ class JdepsGenExtension(
context: DeclarationCheckerContext
) {
when (descriptor) {
is ClassDescriptor -> {
descriptor.typeConstructor.supertypes.forEach {
collectTypeReferences(it)
}
}
is FunctionDescriptor -> {
descriptor.returnType?.let { collectTypeReferences(it) }
descriptor.valueParameters.forEach { valueParameter ->
Expand All @@ -152,32 +170,38 @@ class JdepsGenExtension(
is PropertyDescriptor -> {
collectTypeReferences(descriptor.type)
}
is LocalVariableDescriptor -> {
collectTypeReferences(descriptor.type)
}
}
}

private fun addImplicitDep(it: KotlinType) {
getClassCanonicalPath(it.constructor)?.let { implicitClassesCanonicalPaths.add(it) }
}

private fun addExplicitDep(it: KotlinType) {
getClassCanonicalPath(it.constructor)?.let { explicitClassesCanonicalPaths.add(it) }
}

/**
* Records direct and indirect references for a given type. Direct references are explicitly
* used in the code, e.g: a type declaration or a generic type declaration. Indirect references
* are other types required for compilation such as supertypes and interfaces of those explicit
* types.
*/
private fun collectTypeReferences(kotlinType: KotlinType) {
val constructor = kotlinType.constructor
getClassCanonicalPath(constructor.declarationDescriptor as DeclarationDescriptorWithSource)?.let { explicitClassesCanonicalPaths.add(it) }
private fun collectTypeReferences(kotlinType: KotlinType, collectSuperTypes: Boolean = true) {
addExplicitDep(kotlinType)

constructor.supertypes.forEach {
val classCanonicalPath = getClassCanonicalPath(it.constructor.declarationDescriptor as DeclarationDescriptorWithSource)
classCanonicalPath?.let { implicitClassesCanonicalPaths.add(classCanonicalPath) }
if (collectSuperTypes) {
kotlinType.constructor.supertypes.forEach {
addImplicitDep(it)
}
}

kotlinType.arguments
.map { it.type.constructor }
.forEach { typeArgument ->
getClassCanonicalPath(typeArgument.declarationDescriptor as DeclarationDescriptorWithSource)?.let { explicitClassesCanonicalPaths.add(it) }
typeArgument.supertypes.forEach {
val classCanonicalPath = getClassCanonicalPath(it.constructor.declarationDescriptor as DeclarationDescriptorWithSource)
classCanonicalPath?.let { implicitClassesCanonicalPaths.add(classCanonicalPath) }
}
kotlinType.arguments.map { it.type }.forEach { typeArgument ->
addExplicitDep(typeArgument)
typeArgument.supertypes().forEach { addImplicitDep(it) }
}
}
}
Expand Down
Loading