![JAR search and dependency download from the Maven repository](/logo.png)
schwarz.it.lightsaber.checkers.UnusedModules.kt Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of lightsaber Show documentation
Show all versions of lightsaber Show documentation
A Dagger 2 plugin to find unused dependencies declared in your Modules and Components.
package schwarz.it.lightsaber.checkers
import dagger.spi.model.BindingGraph
import dagger.spi.model.DaggerProcessingEnv
import schwarz.it.lightsaber.CodePosition
import schwarz.it.lightsaber.Finding
import schwarz.it.lightsaber.domain.Module
import schwarz.it.lightsaber.domain.hasSuppress
import schwarz.it.lightsaber.utils.TreeNode
import schwarz.it.lightsaber.utils.getDeclaredModules
import schwarz.it.lightsaber.utils.getModulesCodePosition
import schwarz.it.lightsaber.utils.getUsedModules
internal fun checkUnusedModules(
bindingGraph: BindingGraph,
daggerProcessingEnv: DaggerProcessingEnv,
): List {
val used = bindingGraph.getUsedModules()
return bindingGraph.componentNodes()
.flatMap { component ->
component.getDeclaredModules(bindingGraph, daggerProcessingEnv)
.flatMap {
getErrorMessages(
used = used,
node = it,
daggerProcessingEnv = daggerProcessingEnv,
codePosition = { component.getModulesCodePosition(daggerProcessingEnv) },
)
}
.filterNot { it.module.toString().startsWith("anvil.module.") }
.map {
Finding(
it.message,
it.codePosition,
component.componentPath().currentComponent()::hasSuppress,
)
}
}
}
private fun getErrorMessages(
used: Set,
node: TreeNode,
daggerProcessingEnv: DaggerProcessingEnv,
codePosition: () -> CodePosition,
path: List = emptyList(),
): List {
return buildList {
if (!used.contains(node.value)) {
val usedChildren = findUsedChildren(used, node)
add(
UnusedModuleFinding(
generateMessage(usedChildren.map { it.value }, node.value, path),
codePosition.invoke(),
node.value,
),
)
val newPath = path.plus(node.value.toString())
addAll(
usedChildren.flatMap { child ->
getErrorMessages(
used = used,
node = child,
daggerProcessingEnv = daggerProcessingEnv,
codePosition = { node.value.getIncludesCodePosition(daggerProcessingEnv) },
path = newPath,
)
},
)
} else {
val newPath = path.plus(node.value.toString())
addAll(
node.children.flatMap { child ->
getErrorMessages(
used = used,
node = child,
daggerProcessingEnv,
codePosition = { node.value.getIncludesCodePosition(daggerProcessingEnv) },
path = newPath,
)
},
)
}
}
}
data class UnusedModuleFinding(val message: String, val codePosition: CodePosition, val module: Module)
private fun generateMessage(
usedChildren: List,
node: Module,
path: List = emptyList(),
): String {
val prefix = if (path.isEmpty()) {
"The @Module `$node`"
} else {
"The @Module `$node` included by `${path.joinToString(" → ")}`"
}
return when (usedChildren.size) {
0 -> "$prefix is not used."
1 -> "$prefix is not used but its child `${usedChildren.single()}` is used."
else -> "$prefix is not used but its children ${usedChildren.joinToString { "`$it`" }} are used."
}
}
private fun findUsedChildren(
used: Set,
node: TreeNode,
): List> {
return node.children.flatMap {
if (used.contains(it.value)) {
listOf(it)
} else {
findUsedChildren(used, it)
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy