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

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

There is a newer version: 2.0.2
Show newest version
package com.autonomousapps.tasks

import com.autonomousapps.TASK_GROUP_DEP_INTERNAL
import com.autonomousapps.internal.parse.SourceListener
import com.autonomousapps.internal.utils.bufferWriteJsonSet
import com.autonomousapps.internal.utils.getAndDelete
import com.autonomousapps.model.CodeSource.Kind
import com.autonomousapps.model.intermediates.ExplodingSourceCode
import org.gradle.api.DefaultTask
import org.gradle.api.file.ConfigurableFileCollection
import org.gradle.api.file.DirectoryProperty
import org.gradle.api.file.ProjectLayout
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 java.io.File
import java.nio.file.Paths
import javax.inject.Inject

@CacheableTask
abstract class CodeSourceExploderTask @Inject constructor(
  private val workerExecutor: WorkerExecutor,
  private val layout: ProjectLayout
) : DefaultTask() {

  init {
    group = TASK_GROUP_DEP_INTERNAL
    description = "Parses Java and Kotlin source to detect source-only usages"
  }

  /** The Groovy source of the current project. */
  @get:PathSensitive(PathSensitivity.RELATIVE)
  @get:InputFiles
  abstract val groovySourceFiles: ConfigurableFileCollection

  /** The Java source of the current project. */
  @get:PathSensitive(PathSensitivity.RELATIVE)
  @get:InputFiles
  abstract val javaSourceFiles: ConfigurableFileCollection

  /** The Kotlin source of the current project. */
  @get:PathSensitive(PathSensitivity.RELATIVE)
  @get:InputFiles
  abstract val kotlinSourceFiles: ConfigurableFileCollection

  /** The Scala source of the current project. */
  @get:PathSensitive(PathSensitivity.RELATIVE)
  @get:InputFiles
  abstract val scalaSourceFiles: ConfigurableFileCollection

  @get:OutputFile
  abstract val output: RegularFileProperty

  @TaskAction fun action() {
    workerExecutor.noIsolation().submit(CodeSourceExploderWorkAction::class.java) {
      projectDir.set(layout.projectDirectory)
      groovySourceFiles.from([email protected])
      javaSourceFiles.from([email protected])
      kotlinSourceFiles.from([email protected])
      scalaSourceFiles.from([email protected])
      output.set([email protected])
    }
  }

  interface CodeSourceExploderParameters : WorkParameters {
    val projectDir: DirectoryProperty
    val groovySourceFiles: ConfigurableFileCollection
    val javaSourceFiles: ConfigurableFileCollection
    val kotlinSourceFiles: ConfigurableFileCollection
    val scalaSourceFiles: ConfigurableFileCollection
    val output: RegularFileProperty
  }

  abstract class CodeSourceExploderWorkAction : WorkAction {

    override fun execute() {
      val reportFile = parameters.output.getAndDelete()

      val explodedSource = SourceExploder(
        projectDir = parameters.projectDir.get().asFile,
        groovySourceFiles = parameters.groovySourceFiles,
        javaSourceFiles = parameters.javaSourceFiles,
        kotlinSourceFiles = parameters.kotlinSourceFiles,
        scalaSourceFiles = parameters.scalaSourceFiles,
      ).explode()

      reportFile.bufferWriteJsonSet(explodedSource)
    }
  }
}

private class SourceExploder(
  private val projectDir: File,
  private val groovySourceFiles: ConfigurableFileCollection,
  private val javaSourceFiles: ConfigurableFileCollection,
  private val kotlinSourceFiles: ConfigurableFileCollection,
  private val scalaSourceFiles: ConfigurableFileCollection,
) {

  fun explode(): Set {
    val destination = sortedSetOf()
    javaSourceFiles.mapTo(destination) {
      val rel = relativize(it)
      ExplodingSourceCode(
        relativePath = rel,
        className = canonicalClassName(rel),
        kind = Kind.JAVA,
        imports = SourceListener.parseSourceFileForImports(it)
      )
    }
    kotlinSourceFiles.mapTo(destination) {
      val rel = relativize(it)
      ExplodingSourceCode(
        relativePath = rel,
        className = canonicalClassName(rel),
        kind = Kind.KOTLIN,
        imports = SourceListener.parseSourceFileForImports(it)
      )
    }
    groovySourceFiles.mapTo(destination) {
      val rel = relativize(it)
      ExplodingSourceCode(
        relativePath = rel,
        className = canonicalClassName(rel),
        kind = Kind.GROOVY,
        imports = SourceListener.parseSourceFileForImports(it)
      )
    }
    scalaSourceFiles.mapTo(destination) {
      val rel = relativize(it)
      ExplodingSourceCode(
        relativePath = rel,
        className = canonicalClassName(rel),
        kind = Kind.SCALA,
        imports = SourceListener.parseSourceFileForImports(it)
      )
    }
    return destination
  }

  private fun relativize(file: File) = file.toRelativeString(projectDir)

  private fun canonicalClassName(relativePath: String): String {
    return Paths.get(relativePath)
      // Hack to drop e.g. `src/main/java`. Would be better if a FileTree exposed that info.
      .drop(3)
      // com/example/Foo.java -> com.example.Foo.java
      .joinToString(separator = ".")
      // Drop file extension (.java, .kt, etc.) as well.
      .substringBeforeLast('.')
  }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy