first functional version

This commit is contained in:
2020-04-01 22:37:51 +01:00
parent 94e2807919
commit 10afa523fd
11 changed files with 245 additions and 100 deletions

View File

@@ -1,39 +0,0 @@
/*
* This Kotlin source file was generated by the Gradle 'init' task.
*/
package my.first.plugin
import org.gradle.api.Project
import org.gradle.api.Plugin
///**
// * A simple 'hello world' plugin.
// */
//class MyFirstPluginPlugin: Plugin<Project> {
// override fun apply(project: Project) {
// // Register a task
// project.tasks.register("greeting") { task ->
// task.doLast {
// println("Hello from plugin 'my.first.plugin.greeting'")
// }
// }
// }
//}
open class MyFirstPluginPluginExtension {
var message: String? = null
var greeter: String? = null
}
class MyFirstPluginPlugin : Plugin<Project> {
override fun apply(project: Project) {
val extension = MyFirstPluginPluginExtension()
project.extensions.add(MyFirstPluginPluginExtension::class.java, "my_first_plugin", MyFirstPluginPluginExtension())
project.tasks.register("hello") {
it.doLast {
println("${extension.message} from ${extension.greeter}")
}
}
}
}

View File

@@ -0,0 +1,173 @@
/*
* This Kotlin source file was generated by the Gradle 'init' task.
*/
package net.woggioni.plugins
import net.woggioni.jwo.JWO
import net.woggioni.jwo.tree.StackContext
import net.woggioni.jwo.tree.TreeNode
import net.woggioni.jwo.tree.TreeNodeVisitor
import net.woggioni.jwo.tree.TreeWalker
import net.woggioni.worth.serialization.json.JSONDumper
import net.woggioni.worth.value.ObjectValue
import net.woggioni.worth.xface.Value
import org.gradle.api.Plugin
import org.gradle.api.Project
import org.gradle.api.artifacts.component.ModuleComponentIdentifier
import org.gradle.api.artifacts.component.ProjectComponentIdentifier
import org.gradle.api.artifacts.result.ResolvedComponentResult
import org.gradle.api.artifacts.result.ResolvedDependencyResult
import org.gradle.api.artifacts.result.UnresolvedDependencyResult
import java.io.BufferedWriter
import java.io.OutputStreamWriter
import java.nio.file.Files
import java.nio.file.Paths
open class DependencyExportPluginExtension {
var configurationName: String = "default"
}
object DependencyExporter {
fun graphviz(project: Project, configurationName : String) {
var sequence = 0
val map = HashMap<ResolvedComponentResult, Int>()
val resolutionResult = project.configurations.single {
it.name == configurationName
}.incoming.resolutionResult
project.buildDir.toPath().let {
Files.createDirectories(it)
}.let {
BufferedWriter(
OutputStreamWriter(
Files.newOutputStream(project.buildDir.toPath().resolve("dependencies.dot"))))
}.use { writer ->
writer.write("digraph G {")
writer.newLine()
writer.write(" #rankdir=\"LR\";")
writer.newLine()
for (component in resolutionResult.allComponents) {
map.computeIfAbsent(component) {
sequence++
}
val (shape, color) = when (component.id) {
is ProjectComponentIdentifier -> "box" to "#88ff88"
is ModuleComponentIdentifier -> "oval" to "#ffff88"
else -> throw NotImplementedError("${component.id::class}")
}
val attrs = mapOf(
"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(", ") +
"];")
writer.newLine()
}
for (component in resolutionResult.allComponents) {
component.dependencies.map { dependency ->
when (dependency) {
is ResolvedDependencyResult -> dependency
is UnresolvedDependencyResult -> {
throw dependency.failure
}
else -> {
throw NotImplementedError("${dependency::class}")
}
}
}.map(ResolvedDependencyResult::getSelected).forEach { child ->
writer.write(" node_${map[component]} -> node_${map[child]};")
writer.newLine()
}
}
writer.write("}")
writer.newLine()
}
}
}
class DependencyTreeNode(val component: ResolvedComponentResult) : TreeNode<DependencyTreeNode> {
override fun children(): Iterator<DependencyTreeNode> {
return object : Iterator<DependencyTreeNode> {
val it = component.dependencies.iterator()
override fun hasNext(): Boolean {
return it.hasNext()
}
override fun next(): DependencyTreeNode {
val dependency = it.next()
return when (dependency) {
is ResolvedDependencyResult -> {
DependencyTreeNode(dependency.selected)
}
is UnresolvedDependencyResult -> {
throw dependency.failure
}
else -> {
throw NotImplementedError("${dependency::class}")
}
}
}
}
}
}
fun export(project: Project) {
val cfg = Value.Configuration.builder()
.serializeReferences(true)
.objectValueImplementation(ObjectValue.Implementation.ArrayList)
.build()
val result = ObjectValue.newInstance(cfg)
project.configurations.all { configuration ->
if (configuration.isCanBeResolved) {
val configDeps = ObjectValue.newInstance(cfg)
val visitor = object : TreeNodeVisitor<DependencyTreeNode, ObjectValue> {
override fun visitPre(stack: MutableList<StackContext<DependencyTreeNode, ObjectValue>>): TreeNodeVisitor.VisitOutcome {
val stackElement = JWO.tail(stack)
stackElement.context = ObjectValue.newInstance(cfg)
val id = stackElement.node.component.id
if (stack.size == 1) {
configDeps.put(id.displayName, stackElement.context)
} else if (stack.size > 1) {
val parentStackElement = JWO.tail(stack, -2)
parentStackElement.context.put(id.displayName, stackElement.context)
}
return TreeNodeVisitor.VisitOutcome.CONTINUE
}
// override fun visitPost(stack: MutableList<StackContext<DependencyTreeNode, ObjectValue>>?) {
// val stackElement = JWO.tail(stack)
// if(stack.size > 1) {
// val parentStackElement = JWO.tail(stack, -2)
// parentStackElement.context.add(StringValue(stackElement.node.component.toString()))
// }
// }
}
TreeWalker(visitor).walk(DependencyTreeNode(configuration.incoming.resolutionResult.root))
result.put(configuration.name, configDeps)
}
}
BufferedWriter(OutputStreamWriter(Files.newOutputStream(Paths.get("/tmp/dependencies.json")))).use {
JSONDumper.newInstance(cfg).dump(result, it)
}
}
class DependencyExportPlugin : Plugin<Project> {
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)
}
}
}
}

View File

@@ -1,4 +1,4 @@
package my.first.plugin
package net.woggioni.plugins
import java.io.FileNotFoundException
import java.io.IOException

View File

@@ -1,23 +1,17 @@
/*
* This Kotlin source file was generated by the Gradle 'init' task.
*/
package my.first.plugin.test
package net.woggioni.plugins
import my.first.plugin.installResource
import org.gradle.testfixtures.ProjectBuilder
import net.woggioni.plugins.installResource
import org.gradle.testkit.runner.GradleRunner
import org.junit.jupiter.api.BeforeEach
import org.junit.jupiter.api.Test
import org.junit.jupiter.api.io.TempDir
import java.io.File
import java.net.URLClassLoader
import java.nio.file.Path
/**
* A simple unit test for the 'my.first.plugin.greeting' plugin.
*/
class MyFirstPluginPluginTest {
class DependencyExportPluginTest {
@TempDir
lateinit var testProjectDir : Path
@@ -37,33 +31,20 @@ class MyFirstPluginPluginTest {
}
@Test
fun fooKotlin() {
fun testKotlin() {
installResource("build.gradle.kts", testProjectDir)
installResource("settings.gradle.kts", testProjectDir)
installResource("gradle.properties", testProjectDir)
val runner = getStandardGradleRunnerFor("hello")
val runner = getStandardGradleRunnerFor("exportDependencies")
val result = runner.build()
println(result.output)
}
@Test
fun fooGroovy() {
fun testGroovy() {
installResource("build.gradle", testProjectDir)
installResource("settings.gradle.kts", testProjectDir)
installResource("gradle.properties", testProjectDir)
val runner = getStandardGradleRunnerFor("hello")
val runner = getStandardGradleRunnerFor("exportDependencies")
val result = runner.build()
println(result.output)
}
// @Test
// fun `plugin registers task`() {
// // Create a test project and apply the plugin
// val project = ProjectBuilder.builder().build()
// project.plugins.apply("my.first.plugin.MyFirstPlugin")
//
// // Verify the result
// val task = project.tasks.findByName("hello")!!
// println(task.outputs.hasOutput)
// }
}

View File

@@ -1,8 +0,0 @@
plugins {
id "net.corda.my-first-plugin"
}
my_first_plugin {
message = 'Hi'
greeter = 'Gradle'
}

View File

@@ -1,21 +0,0 @@
//buildscript {
// repositories {
// mavenLocal()
// jcenter()
// mavenCentral()
// }
// dependencies {
// classpath("net.corda:my-first-plugin:0.1")
// }
//}
plugins {
id("net.corda.my-first-plugin")
}
//apply(plugin = "net.corda.my-first-plugin")
import my.first.plugin.MyFirstPluginPluginExtension
configure<my.first.plugin.MyFirstPluginPluginExtension> {
message = "Hi"
greeter = "Gradle"
}

View File

@@ -0,0 +1,17 @@
plugins {
id "org.jetbrains.kotlin.jvm" version "1.3.61"
id "net.woggioni.plugins.dependency-export"
}
exportDependencies {
configurationName = 'runtime'
}
repositories {
jcenter()
mavenLocal()
}
dependencies {
runtime("org.hibernate:hibernate-core:5.4.13.Final")
}

View File

@@ -0,0 +1,14 @@
plugins {
kotlin("jvm") version "1.3.71"
id("net.woggioni.plugins.dependency-export")
}
repositories {
jcenter()
mavenLocal()
}
dependencies {
runtime("org.hibernate:hibernate-core:5.4.13.Final")
}