From e0d5e3c6bbe1cf20c6ce5c5249db429ec46289a7 Mon Sep 17 00:00:00 2001 From: Walter Oggioni Date: Sun, 5 Apr 2020 19:25:51 +0100 Subject: [PATCH] added renderDependencies task --- .../build.gradle} | 4 + .../settings.gradle} | 0 sample/{ => kotlin}/build.gradle.kts | 9 +- sample/{ => kotlin}/settings.gradle.kts | 0 .../plugins/DependencyExportPlugin.kt | 122 ++++++++++++++---- 5 files changed, 106 insertions(+), 29 deletions(-) rename sample/{build.gradle.backup => groovy/build.gradle} (91%) rename sample/{settings.gradle.backup => groovy/settings.gradle} (100%) rename sample/{ => kotlin}/build.gradle.kts (65%) rename sample/{ => kotlin}/settings.gradle.kts (100%) diff --git a/sample/build.gradle.backup b/sample/groovy/build.gradle similarity index 91% rename from sample/build.gradle.backup rename to sample/groovy/build.gradle index e844592..b3a9d89 100644 --- a/sample/build.gradle.backup +++ b/sample/groovy/build.gradle @@ -23,6 +23,10 @@ exportDependencies { configurationName = 'runtime' } +renderDependencies { + format = "svg" +} + dependencies { runtime("org.hibernate:hibernate-core:5.4.13.Final") } diff --git a/sample/settings.gradle.backup b/sample/groovy/settings.gradle similarity index 100% rename from sample/settings.gradle.backup rename to sample/groovy/settings.gradle diff --git a/sample/build.gradle.kts b/sample/kotlin/build.gradle.kts similarity index 65% rename from sample/build.gradle.kts rename to sample/kotlin/build.gradle.kts index 376b70a..64f3c71 100644 --- a/sample/build.gradle.kts +++ b/sample/kotlin/build.gradle.kts @@ -9,7 +9,8 @@ buildscript { } } -import net.woggioni.plugins.DependencyExportPluginExtension +import net.woggioni.plugins.ExportDependenciesPluginExtension +import net.woggioni.plugins.RenderDependenciesPluginExtension plugins { kotlin("jvm") version "1.3.71" @@ -25,6 +26,10 @@ dependencies { runtime("org.hibernate:hibernate-core:5.4.13.Final") } -configure { +configure { configurationName = "runtime" } + +configure { + format = "svg" +} diff --git a/sample/settings.gradle.kts b/sample/kotlin/settings.gradle.kts similarity index 100% rename from sample/settings.gradle.kts rename to sample/kotlin/settings.gradle.kts diff --git a/src/main/kotlin/net/woggioni/plugins/DependencyExportPlugin.kt b/src/main/kotlin/net/woggioni/plugins/DependencyExportPlugin.kt index 4e08b95..b80327b 100644 --- a/src/main/kotlin/net/woggioni/plugins/DependencyExportPlugin.kt +++ b/src/main/kotlin/net/woggioni/plugins/DependencyExportPlugin.kt @@ -3,6 +3,7 @@ */ package net.woggioni.plugins +import org.gradle.api.GradleException import org.gradle.api.Plugin import org.gradle.api.Project import org.gradle.api.artifacts.component.ModuleComponentIdentifier @@ -13,26 +14,63 @@ import org.gradle.api.artifacts.result.UnresolvedDependencyResult import java.io.BufferedWriter import java.io.OutputStreamWriter import java.nio.file.Files +import java.nio.file.Path +import java.nio.file.Paths +import kotlin.reflect.KMutableProperty0 -open class DependencyExportPluginExtension { + +open class ExportDependenciesPluginExtension(project: Project) { var configurationName: String = "default" + var outputFile = project.buildDir.toPath().resolve("dependencies.dot") +} + +open class RenderDependenciesPluginExtension(project: Project) { + var format: String = "xlib" + var outputFile = project.buildDir.toPath().resolve("renderedDependencies") + var graphvizExecutable: String = "dot" +} + +private class Overrider(private val properties : Map, private val prefix: String) { + inline fun identity(arg: T): T { + return arg + } + + fun overrideProperty( + property: KMutableProperty0) { + overrideProperty(property, ::identity) + } + + inline fun overrideProperty( + property: KMutableProperty0, + valueFactory: (String) -> V) { + val propertyKey = prefix + "." + property.name + val propertyValue = properties[propertyKey] as String? + if (propertyValue != null) { + property.set(valueFactory(propertyValue)) + } + } } object DependencyExporter { - fun graphviz(project: Project, configurationName : String) { + fun exportDot(project: Project, ext: ExportDependenciesPluginExtension) { + val overrider = Overrider(project.properties, "exportDependencies") + overrider.overrideProperty(ext::configurationName) + overrider.overrideProperty(ext::outputFile) { value -> Paths.get(value) } + var sequence = 0 val map = HashMap() + val resolutionResult = project.configurations.single { - it.name == configurationName + it.name == ext.configurationName }.incoming.resolutionResult - project.buildDir.toPath().let { - Files.createDirectories(it) - }.let { - BufferedWriter( - OutputStreamWriter( - Files.newOutputStream(project.buildDir.toPath().resolve("dependencies.dot")))) - }.use { writer -> + if(!ext.outputFile.isAbsolute) { + ext.outputFile = project.buildDir.toPath().resolve(ext.outputFile) + } + Files.createDirectories(ext.outputFile.parent) + BufferedWriter( + OutputStreamWriter( + Files.newOutputStream(ext.outputFile))).use { writer -> writer.write("digraph G {") writer.newLine() writer.write(" #rankdir=\"LR\";") @@ -47,15 +85,15 @@ object DependencyExporter { else -> throw NotImplementedError("${component.id::class}") } val attrs = mapOf( - "label" to component.id.displayName, - "shape" to shape, - "style" to "filled", - "fillcolor" to color + "label" to component.id.displayName, + "shape" to shape, + "style" to "filled", + "fillcolor" to color ) writer.write(" node_${map[component]} [" + attrs.entries - .asSequence() - .map { "${it.key}=\"${it.value}\"" }.joinToString(", ") + + .asSequence() + .map { "${it.key}=\"${it.value}\"" }.joinToString(", ") + "];") writer.newLine() } @@ -83,17 +121,47 @@ object DependencyExporter { } } -class DependencyExportPlugin : Plugin { - override fun apply(project: Project) { - val extension = DependencyExportPluginExtension() - project.extensions.add(DependencyExportPluginExtension::class.java, "exportDependencies", extension) - project.tasks.register("exportDependencies") { - it.doLast { - val propertyKey = "exportDependencies.configurationName" - val properties = project.properties - val configurationName = properties.getOrDefault(propertyKey, extension.configurationName) as String - DependencyExporter.graphviz(project, configurationName = configurationName) - } +object DependencyRenderer { + fun render(project: Project, ext: RenderDependenciesPluginExtension, sourceFile : Path) { + val overrider = Overrider(project.properties, "renderDependencies") + overrider.overrideProperty(ext::format) + overrider.overrideProperty(ext::graphvizExecutable) + overrider.overrideProperty(ext::outputFile) { value -> Paths.get(value) } + + if(!ext.outputFile.isAbsolute) { + ext.outputFile = project.buildDir.toPath().resolve(ext.outputFile) + } + val cmd: List = listOf( + ext.graphvizExecutable, + "-T${ext.format}", + "-o${ext.outputFile}", + sourceFile.toString() + + ) + val returnCode = ProcessBuilder(cmd).inheritIO().start().waitFor() + if (returnCode != 0) { + throw GradleException("Error invoking graphviz") } } +} + +class DependencyExportPlugin : Plugin { + override fun apply(project: Project) { + val dependencyExportExtension = ExportDependenciesPluginExtension(project) + project.extensions.add(ExportDependenciesPluginExtension::class.java, "exportDependencies", dependencyExportExtension) + val exportDependenciesTask = project.tasks.register("exportDependencies") { + it.doLast { + DependencyExporter.exportDot(project, dependencyExportExtension) + } + }.get() + + val renderDependenciesPluginExtension = RenderDependenciesPluginExtension(project) + project.extensions.add(RenderDependenciesPluginExtension::class.java, "renderDependencies", renderDependenciesPluginExtension) + val renderDependenciesTask = project.tasks.register("renderDependencies") { + it.dependsOn(exportDependenciesTask) + it.doLast { + DependencyRenderer.render(project, renderDependenciesPluginExtension, dependencyExportExtension.outputFile) + } + }.get() + } } \ No newline at end of file