com.autonomousapps.internal.analyzer.JvmProjectAnalyzer.kt Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of dependency-analysis-gradle-plugin Show documentation
Show all versions of dependency-analysis-gradle-plugin Show documentation
Analyzes dependency usage in Android and JVM projects
@file:Suppress("UnstableApiUsage")
package com.autonomousapps.internal.analyzer
import com.autonomousapps.internal.OutputPaths
import com.autonomousapps.internal.utils.capitalizeSafely
import com.autonomousapps.internal.utils.namedOrNull
import com.autonomousapps.services.InMemoryCache
import com.autonomousapps.tasks.*
import org.gradle.api.Project
import org.gradle.api.UnknownDomainObjectException
import org.gradle.api.artifacts.Configuration
import org.gradle.api.attributes.Attribute
import org.gradle.api.file.FileTree
import org.gradle.api.provider.Provider
import org.gradle.api.tasks.SourceSet
import org.gradle.api.tasks.TaskProvider
import org.gradle.api.tasks.bundling.Jar
import org.gradle.kotlin.dsl.get
import org.gradle.kotlin.dsl.register
import org.jetbrains.kotlin.gradle.plugin.KotlinSourceSet as JbKotlinSourceSet
internal abstract class JvmAnalyzer(
project: Project,
private val mainSourceSet: JvmSourceSet,
private val testSourceSet: JvmSourceSet?
) : AbstractDependencyAnalyzer(project) {
final override val flavorName: String? = null
final override val variantName: String = mainSourceSet.name
final override val variantNameCapitalized = variantName.capitalizeSafely()
// Yes, these two are the same for this case
final override val compileConfigurationName = "compileClasspath"
final override val runtimeConfigurationName = compileConfigurationName
// Do NOT replace this with AndroidArtifacts.ARTIFACT_TYPE, as this will not be available in a
// java lib project
final override val attribute: Attribute = Attribute.of("artifactType", String::class.java)
final override val attributeValue = "jar"
final override val attributeValueRes: String? = null
final override val kotlinSourceFiles: FileTree = getKotlinSources()
override val javaSourceFiles: FileTree? = getJavaSources()
final override val javaAndKotlinSourceFiles: FileTree? = null
final override val isDataBindingEnabled: Boolean = false
final override val isViewBindingEnabled: Boolean = false
protected val outputPaths = OutputPaths(project, variantName)
override fun registerCreateVariantFilesTask(): TaskProvider {
return project.tasks.register("createVariantFiles$variantNameCapitalized") {
val mainFiles = project.files(mainSourceSet.sourceCode.sourceDirectories)
val testFiles = testSourceSet?.let { project.files(it.sourceCode.sourceDirectories) }
this.mainFiles.setFrom(mainFiles)
testFiles?.let { this.testFiles.setFrom(it) }
output.set(outputPaths.variantFilesPath)
}
}
final override val testJavaCompileName: String = "compileTestJava"
final override val testKotlinCompileName: String = "compileTestKotlin"
final override fun registerClassAnalysisTask(createVariantFiles: TaskProvider): TaskProvider =
project.tasks.register("analyzeClassUsage$variantNameCapitalized") {
javaCompileTask()?.let { javaClasses.from(it.get().outputs.files.asFileTree) }
kotlinCompileTask()?.let { kotlinClasses.from(it.get().outputs.files.asFileTree) }
variantFiles.set(createVariantFiles.flatMap { it.output })
testJavaCompile?.let { javaCompile ->
testJavaClassesDir.set(javaCompile.flatMap { it.destinationDirectory })
}
testKotlinCompile?.let { kotlinCompile ->
testKotlinClassesDir.set(kotlinCompile.flatMap { it.destinationDirectory })
}
output.set(outputPaths.allUsedClassesPath)
outputPretty.set(outputPaths.allUsedClassesPrettyPath)
}
final override fun registerFindDeclaredProcsTask(
inMemoryCacheProvider: Provider,
locateDependenciesTask: TaskProvider
): TaskProvider {
return project.tasks.register(
"findDeclaredProcs$variantNameCapitalized"
) {
kaptConf()?.let {
setKaptArtifacts(it.incoming.artifacts)
}
annotationProcessorConf()?.let {
setAnnotationProcessorArtifacts(it.incoming.artifacts)
}
dependencyConfigurations.set(locateDependenciesTask.flatMap { it.output })
output.set(outputPaths.declaredProcPath)
outputPretty.set(outputPaths.declaredProcPrettyPath)
this.inMemoryCacheProvider.set(inMemoryCacheProvider)
}
}
final override fun registerFindUnusedProcsTask(
findDeclaredProcs: TaskProvider,
importFinder: TaskProvider
): TaskProvider {
return project.tasks.register(
"findUnusedProcs${variantNameCapitalized}"
) {
javaCompileTask()?.let { javaClasses.from(it.get().outputs.files.asFileTree) }
kotlinCompileTask()?.let { kotlinClasses.from(it.get().outputs.files.asFileTree) }
imports.set(importFinder.flatMap { it.importsReport })
annotationProcessorsProperty.set(findDeclaredProcs.flatMap { it.output })
output.set(outputPaths.unusedProcPath)
}
}
private fun kaptConf(): Configuration? = try {
project.configurations["kapt"]
} catch (_: UnknownDomainObjectException) {
null
}
private fun annotationProcessorConf(): Configuration? = try {
project.configurations["annotationProcessor"]
} catch (_: UnknownDomainObjectException) {
null
}
protected fun javaCompileTask() = project.tasks.namedOrNull("compileJava")
protected fun kotlinCompileTask() = project.tasks.namedOrNull("compileKotlin")
?: project.tasks.namedOrNull("compileKotlinJvm") // for multiplatform projects
protected fun getJarTask(): TaskProvider = project.tasks.named(mainSourceSet.jarTaskName, Jar::class.java)
private fun getKotlinSources(): FileTree = getSourceDirectories().matching {
include("**/*.kt")
exclude("**/*.java")
}
private fun getJavaSources(): FileTree = getSourceDirectories().matching {
include("**/*.java")
exclude("**/*.kt")
}
private fun getSourceDirectories(): FileTree {
val javaAndKotlinSource = mainSourceSet.sourceCode.sourceDirectories
return project.files(javaAndKotlinSource).asFileTree
}
}
internal class JavaAppAnalyzer(project: Project, sourceSet: SourceSet, testSourceSet: SourceSet?)
: JvmAnalyzer(project, JavaSourceSet(sourceSet), testSourceSet?.let { JavaSourceSet(it) })
internal class JavaLibAnalyzer(project: Project, sourceSet: SourceSet, testSourceSet: SourceSet?)
: JvmAnalyzer(project, JavaSourceSet(sourceSet), testSourceSet?.let { JavaSourceSet(it) }) {
override fun registerAbiAnalysisTask(
findClassesTask: TaskProvider,
abiExclusions: Provider
): TaskProvider? =
project.tasks.register("abiAnalysis$variantNameCapitalized") {
javaCompileTask()?.let { javaClasses.from(it.get().outputs.files.asFileTree) }
kotlinCompileTask()?.let { kotlinClasses.from(it.get().outputs.files.asFileTree) }
dependencies.set(findClassesTask.flatMap { it.allComponentsReport })
exclusions.set(abiExclusions)
output.set(outputPaths.abiAnalysisPath)
abiDump.set(outputPaths.abiDumpPath)
}
}
internal abstract class KotlinJvmAnalyzer(
project: Project,
mainSourceSet: JbKotlinSourceSet,
testSourceSet: JbKotlinSourceSet?
) : JvmAnalyzer(
project = project,
mainSourceSet = KotlinSourceSet(mainSourceSet),
testSourceSet = testSourceSet?.let { KotlinSourceSet(it) }
) {
final override val javaSourceFiles: FileTree? = null
}
internal class KotlinJvmAppAnalyzer(
project: Project,
sourceSet: JbKotlinSourceSet,
testSourceSet: JbKotlinSourceSet?
) : KotlinJvmAnalyzer(
project = project,
mainSourceSet = sourceSet,
testSourceSet = testSourceSet
)
internal class KotlinJvmLibAnalyzer(
project: Project,
mainSourceSet: JbKotlinSourceSet,
testSourceSet: JbKotlinSourceSet?
) : KotlinJvmAnalyzer(
project = project,
mainSourceSet = mainSourceSet,
testSourceSet = testSourceSet
) {
override fun registerAbiAnalysisTask(
findClassesTask: TaskProvider,
abiExclusions: Provider
) = project.tasks.register("abiAnalysis$variantNameCapitalized") {
javaCompileTask()?.let { javaClasses.from(it.get().outputs.files.asFileTree) }
kotlinCompileTask()?.let { kotlinClasses.from(it.get().outputs.files.asFileTree) }
dependencies.set(findClassesTask.flatMap { it.allComponentsReport })
output.set(outputPaths.abiAnalysisPath)
abiDump.set(outputPaths.abiDumpPath)
}
}