All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.autonomousapps.internal.analyzer.JvmProjectAnalyzer.kt Maven / Gradle / Ivy

There is a newer version: 2.0.2
Show newest version
@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)
  }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy