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

com.autonomousapps.tasks.GeneralUsageDetectionTask.kt Maven / Gradle / Ivy

There is a newer version: 2.0.2
Show newest version
@file:Suppress("UnstableApiUsage")

package com.autonomousapps.tasks

import com.autonomousapps.TASK_GROUP_DEP
import com.autonomousapps.advice.Dependency
import com.autonomousapps.internal.Component
import com.autonomousapps.internal.Imports
import com.autonomousapps.internal.utils.*
import com.autonomousapps.internal.utils.getLogger
import org.gradle.api.DefaultTask
import org.gradle.api.file.RegularFileProperty
import org.gradle.api.tasks.*
import org.gradle.workers.WorkAction
import org.gradle.workers.WorkParameters
import org.gradle.workers.WorkerExecutor
import javax.inject.Inject

/**
 * This detects _any_ usage, based on presence of imports that can be associated with dependencies.
 * It is sort of a catch-all / edge-case detector.
 */
abstract class GeneralUsageDetectionTask @Inject constructor(
  private val workerExecutor: WorkerExecutor
) : DefaultTask() {

  init {
    group = TASK_GROUP_DEP
    description = "Produces a report of dependencies that are used based on the heuristic that " +
      "import statements appear in project source"
  }

  /**
   * Class usages, as `List`.
   */
  @get:PathSensitive(PathSensitivity.RELATIVE)
  @get:InputFile
  abstract val components: RegularFileProperty

  /**
   * All the imports in the Java and Kotlin source in this project.
   */
  @get:PathSensitive(PathSensitivity.NONE)
  @get:InputFile
  abstract val imports: RegularFileProperty

  /**
   * A [`Set`][Dependency] of dependencies that provide types that the current project
   * is using.
   */
  @get:OutputFile
  abstract val output: RegularFileProperty

  @TaskAction fun action() {
    workerExecutor.noIsolation().submit(GeneralUsageDetectionWorkAction::class.java) {
      components.set([email protected])
      importsFile.set([email protected])
      output.set([email protected])
    }
  }
}

interface GeneralUsageDetectionParameters : WorkParameters {
  val components: RegularFileProperty
  val importsFile: RegularFileProperty
  val output: RegularFileProperty
}

abstract class GeneralUsageDetectionWorkAction : WorkAction {

  private val logger = getLogger()

  override fun execute() {
    // Output
    val constantUsageReportFile = parameters.output.getAndDelete()

    // Inputs
    val components = parameters.components.get().asFile.readText().fromJsonList()
    val imports = parameters.importsFile.get().asFile.readText().fromJsonList().flatten()

    val usedDependencies = findUsedDependencies(components, imports)

    logger.debug("Constants usage:\n${usedDependencies.toPrettyString()}")
    constantUsageReportFile.writeText(usedDependencies.toJson())
  }

  /**
   * Given components:
   * ```
   * [{"dependency":{"identifier":":proj-2","configurationName":"implementation"},"isTransitive":false,"isCompileOnlyAnnotations":false,"classes":["com.example.lib.Library"]}]
   * ```
   * and imports:
   * ```
   * ["com.example.lib.Library"]
   * ```
   * return `Dependency(':proj-2')`
   */
  private fun findUsedDependencies(
    components: List, imports: Set
  ): Set {
    return imports.mapNotNull { import ->
      components.find { component ->
        component.classes.contains(import)
      }
    }.mapToSet { it.dependency }
  }

  // The detector doesn't care about source type
  private fun List.flatten(): Set = flatMapToOrderedSet { it.imports }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy