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

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

There is a newer version: 2.6.1
Show newest version
// Copyright (c) 2024. Tony Robalik.
// SPDX-License-Identifier: Apache-2.0
package com.autonomousapps.tasks

import com.autonomousapps.internal.externalArtifactsFor
import com.autonomousapps.internal.graph.GraphViewBuilder
import com.autonomousapps.internal.graph.GraphWriter
import com.autonomousapps.internal.utils.bufferWriteJson
import com.autonomousapps.internal.utils.getAndDelete
import com.autonomousapps.internal.utils.mapNotNullToSet
import com.autonomousapps.internal.utils.toCoordinates
import com.autonomousapps.model.Coordinates
import com.autonomousapps.model.CoordinatesContainer
import com.autonomousapps.model.internal.DependencyGraphView
import com.autonomousapps.model.declaration.SourceSetKind
import com.autonomousapps.model.declaration.Variant
import org.gradle.api.DefaultTask
import org.gradle.api.Project
import org.gradle.api.artifacts.Configuration
import org.gradle.api.artifacts.FileCollectionDependency
import org.gradle.api.artifacts.result.ResolvedComponentResult
import org.gradle.api.file.ConfigurableFileCollection
import org.gradle.api.file.RegularFileProperty
import org.gradle.api.provider.Property
import org.gradle.api.provider.SetProperty
import org.gradle.api.tasks.*

@CacheableTask
abstract class GraphViewTask : DefaultTask() {

  init {
    description = "Constructs a variant-specific view of this project's dependency graph"
  }

  @get:Internal
  abstract val compileClasspathName: Property

  @get:Internal
  abstract val compileClasspathResult: Property

  @get:Internal
  abstract val compileClasspathFileCoordinates: SetProperty

  @get:Internal
  abstract val runtimeClasspathName: Property

  @get:Internal
  abstract val runtimeClasspathResult: Property

  @get:Internal
  abstract val runtimeClasspathFileCoordinates: SetProperty

  @get:PathSensitive(PathSensitivity.NAME_ONLY)
  @get:InputFiles
  abstract val compileFiles: ConfigurableFileCollection

  @get:PathSensitive(PathSensitivity.NAME_ONLY)
  @get:InputFiles
  abstract val runtimeFiles: ConfigurableFileCollection

  /**
   * Unused, except to influence the up-to-date-ness of this task. Declaring a transitive dependency doesn't change the
   * compile classpath, but it must influence the output of this task.
   */
  @get:PathSensitive(PathSensitivity.NONE)
  @get:InputFile
  abstract val declarations: RegularFileProperty

  /** Needed to make sure task gives the same result if the build configuration in a composite changed between runs. */
  @get:Input
  abstract val buildPath: Property

  /** Needed to disambiguate other projects that might have otherwise identical inputs. */
  @get:Input
  abstract val projectPath: Property

  @get:Input
  abstract val variant: Property

  @get:Input
  abstract val kind: Property

  /** Output in json format for compile classpath graph. */
  @get:OutputFile
  abstract val output: RegularFileProperty

  /** Output in json format for compile classpath dependencies (the graph's nodes). */
  @get:OutputFile
  abstract val outputNodes: RegularFileProperty

  /** Output in graphviz format for compile classpath graph. */
  @get:OutputFile
  abstract val outputDot: RegularFileProperty

  /** Output in json format for runtime classpath graph. */
  @get:OutputFile
  abstract val outputRuntime: RegularFileProperty

  /** Output in graphviz format for runtime classpath graph. */
  @get:OutputFile
  abstract val outputRuntimeDot: RegularFileProperty

  internal fun configureTask(
    project: Project,
    compileClasspath: Configuration,
    runtimeClasspath: Configuration,
    jarAttr: String,
  ) {
    compileClasspathName.set(compileClasspath.name)
    compileClasspathResult.set(compileClasspath.incoming.resolutionResult.rootComponent)
    compileClasspathFileCoordinates.set(project.provider {
      compileClasspath.allDependencies
        .filterIsInstance()
        .mapNotNullToSet { it.toCoordinates() }
    })

    runtimeClasspathName.set(runtimeClasspath.name)
    runtimeClasspathResult.set(runtimeClasspath.incoming.resolutionResult.rootComponent)
    runtimeClasspathFileCoordinates.set(project.provider {
      runtimeClasspath.allDependencies
        .filterIsInstance()
        .mapNotNullToSet { it.toCoordinates() }
    })

    compileFiles.setFrom(project.provider { compileClasspath.externalArtifactsFor(jarAttr).artifactFiles })
    runtimeFiles.setFrom(project.provider { runtimeClasspath.externalArtifactsFor(jarAttr).artifactFiles })
  }

  @TaskAction fun action() {
    val output = output.getAndDelete()
    val outputDot = outputDot.getAndDelete()
    val outputNodes = outputNodes.getAndDelete()
    val outputRuntime = outputRuntime.getAndDelete()
    val outputRuntimeDot = outputRuntimeDot.getAndDelete()

    val variant = variant.get()
    val kind = kind.get()

    val compileGraph = GraphViewBuilder(compileClasspathResult.get(), compileClasspathFileCoordinates.get()).graph
    val compileGraphView = DependencyGraphView(
      variant = Variant(variant, kind),
      configurationName = compileClasspathName.get(),
      graph = compileGraph
    )

    val runtimeGraph = GraphViewBuilder(runtimeClasspathResult.get(), runtimeClasspathFileCoordinates.get()).graph
    val runtimeGraphView = DependencyGraphView(
      variant = Variant(variant, kind),
      configurationName = runtimeClasspathName.get(),
      graph = runtimeGraph
    )

    output.bufferWriteJson(compileGraphView)
    outputDot.writeText(GraphWriter.toDot(compileGraph))
    outputNodes.bufferWriteJson(CoordinatesContainer(compileGraphView.nodes))
    outputRuntime.bufferWriteJson(runtimeGraphView)
    outputRuntimeDot.writeText(GraphWriter.toDot(runtimeGraph))
  }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy