com.ybo.trackingplugin.extension.TraceConfigHandler.kt Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of traceplugin Show documentation
Show all versions of traceplugin Show documentation
gradle plugin allowing to add automatic logs (or other process) at the start of each traced method
package com.ybo.trackingplugin.extension
import com.ybo.trackingplugin.tracerlib.defaulttracer.DefTraceTest
import com.ybo.trackingplugin.tracerlib.defaulttracer.ReturnTrace
import com.ybo.trackingplugin.tracerlib.defaulttracer.tracers.TraceDefaultFactory
import org.gradle.api.GradleException
open class TraceProcessConfigHandler {
private val editableListOfConfigs: MutableList = mutableListOf()
internal val configs: List get() = editableListOfConfigs.toList()
/** adds a configuration, ie a set of annotation represening what method to trace,
* and a factory to create a tracer for these traced methods.*/
fun add(init: TraceConfig.() -> Unit) {
val config = TraceConfig()
config.init()
config.check()
config.checkInsertability(editableListOfConfigs)
editableListOfConfigs.add(config)
}
/** adds a configuration,
* but that is already prepopulated with default @DefTraceTest annotations*/
fun addDefaultConfig(init: DefaultTraceConfig.() -> Unit) {
val config = TraceConfig()
val defaultTraceConfig = DefaultTraceConfig()
defaultTraceConfig.init()
config.apply {
name = "DefaultEmbeddedConfig"
tracerFactory = TraceDefaultFactory::class.java.canonicalName
annotation = DefTraceTest::class.java.canonicalName
exclude = defaultTraceConfig.exclude
srcPath = defaultTraceConfig.srcPath
}
config.check()
config.checkInsertability(editableListOfConfigs)
editableListOfConfigs.add(config)
}
/** adds a configuration,
* but that is already prepopulated for return value feature*/
fun addReturnValueConfig(init: ReturnTraceConfig.() -> Unit) {
val config = TraceConfig()
val returnConfig = ReturnTraceConfig()
returnConfig.init()
config.apply {
name = "ReturnTraceConfig"
annotation = ReturnTrace::class.java.canonicalName
tracerFactory = returnConfig.tracerFactory
exclude = returnConfig.exclude
srcPath = returnConfig.srcPath
}
config.check()
config.checkInsertability(editableListOfConfigs)
editableListOfConfigs.add(config)
}
private fun TraceConfig.checkInsertability(configs: List) {
if (!configs.fold(true) { acc, candidate ->
acc && candidate.compatible(this)
}
) {
throw GradleException("cannot add config $name because it clashes with another config")
}
}
fun TraceConfig.compatible(anotherConfig: TraceConfig): Boolean {
val toProcessAnnotationDifferent = (
annotation?.lowercase()
?: ""
) != (anotherConfig.annotation?.lowercase() ?: "")
val nameDifferent = name.lowercase() != anotherConfig.name
return toProcessAnnotationDifferent && nameDifferent
}
private fun TraceConfig.check() {
if (name.isEmpty()) {
throw GradleException("in trace config, name must be defined")
}
if (annotation == null) {
throw GradleException("in trace config $name, toBeProcessedAnnotation must be defined")
}
if (tracerFactory.isEmpty()) {
throw GradleException("in trace config $name, tracerFactory must be defined")
}
if (srcPath == null) {
throw GradleException("in trace config $name, srcPath must be defined")
}
if (!annotation!!.contains('.') ) {
throw GradleException("in trace config $name, annotations must be defined in their full form (f.i. pretty.nice.package.TraceAnnotation)")
}
if (annotation.equals(alreadyProcessedAnnotation())) {
throw GradleException("in trace config $name, toBeProcessedAnnotation and alreadyProcessedAnnotation must be different")
}
}
}