Skip to content

Commit

Permalink
initial prototype for kroto config gradle dsl
Browse files Browse the repository at this point in the history
  • Loading branch information
marcoferrer committed Dec 3, 2018
1 parent 8c4af77 commit 89ef739
Show file tree
Hide file tree
Showing 5 changed files with 197 additions and 0 deletions.
40 changes: 40 additions & 0 deletions example-project/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -13,15 +13,55 @@ buildscript {
jcenter()
mavenCentral()
maven { url 'http://dl.bintray.com/kotlin/kotlin-eap' }
flatDir dirs: "${rootDir}/../kroto-plus-gradle-plugin/build/libs/"
// flatDir dirs: "${rootDir}/../kroto-plus-coroutines/build/libs/"
// flatDir dirs: "${rootDir}/../kroto-plus-test/build/libs/"
// flatDir dirs: "${rootDir}/../protoc-gen-kroto-plus/build/libs/"
}

dependencies{
classpath "com.github.marcoferrer.krotoplus:kroto-plus-gradle-plugin:${versions.krotoplus}"
classpath "com.google.protobuf:protobuf-java:${versions.protobuf}"
}

}


plugins{
id 'idea'
id 'com.google.protobuf' version '0.8.6'
id "org.jetbrains.kotlin.jvm" version "1.3.0"
}

apply plugin: "com.github.marcoferrer.kroto-plus"

krotoPlus {
createConfig("testing"){
protoBuilders {
filter {
addAllIncludePath(["test","asdasd"])
}
unwrapBuilders = true
}
generatorScripts {
addAllScriptPath("varArgExtensionGenerator.kts")
scriptBundle = "kp-scripts/build/libs/kp-scripts.jar"
}
}

//add overloads for file path
//add logic to check if filepath exists
//add logic to check if script exists if no bundle exists
//add logic to check it script exists inside bundle??
//add logic to make sure there is no file set for script is bundle is set
//add function to generate bytestring for plugin option
//setup seperate subproject for mpproto
//set project dir path to perserve relative paths


println(configs["testing"])
}

group = 'com.github.marcoferrer.krotoplus'
version = versions.krotoplus

Expand Down
13 changes: 13 additions & 0 deletions kroto-plus-gradle-plugin/gen-config-dsl/build.gradle
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@

dependencies{
implementation project(":protoc-gen-kroto-plus")
implementation "com.google.protobuf:protobuf-java:3.6.1"
implementation "org.jetbrains.kotlin:kotlin-script-util"
implementation ("com.squareup:kotlinpoet:0.7.0") {
exclude group: 'org.jetbrains.kotlin'
}
}

jar {
archiveName = 'bundle.jar'
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
import com.github.marcoferrer.krotoplus.proto.ProtoMessage
import com.github.marcoferrer.krotoplus.utils.memoize
import com.google.protobuf.DescriptorProtos

// language=java
fun builderScope(message: ProtoMessage): String? = buildString {
val schema = message.protoFile.schema

message.descriptorProto.fieldList.asSequence()
.filter { it.type == DescriptorProtos.FieldDescriptorProto.Type.TYPE_MESSAGE }
.map {
it to requireNotNull(schema.protoTypes[it.typeName] as? ProtoMessage) {
"${it.typeName} was not found in schema type map."
}
}
.filterNot { it.second.isMapEntry }
.forEach { (fieldDescriptorProto, protoMessageForField) ->

val fieldNameCamelCase = camelCaseFieldName(fieldDescriptorProto.name)

val addStatement= if (fieldDescriptorProto.label == DescriptorProtos.FieldDescriptorProto.Label.LABEL_REPEATED)
"add$fieldNameCamelCase(builder)" else "set$fieldNameCamelCase(builder)"

append("""
public void ${fieldNameCamelCase.decapitalize()}( org.gradle.api.Action<${protoMessageForField.builderClassName.canonicalName}> action){
${protoMessageForField.builderClassName.canonicalName} builder = ${protoMessageForField.className.canonicalName}.newBuilder();
action.execute(builder);
$addStatement;
}
public void ${fieldNameCamelCase.decapitalize()}( groovy.lang.Closure<${protoMessageForField.builderClassName.canonicalName}> closure){
${protoMessageForField.builderClassName.canonicalName} builder = ${protoMessageForField.className.canonicalName}.newBuilder();
org.gradle.util.ConfigureUtil.configure(closure,builder);
$addStatement;
}
""".trimIndent()
)
appendln()
}
}


val camelCaseFieldName = { it: String ->
// We cant use CaseFormat.UPPER_CAMEL since
// protoc is lenient with malformed field names
if (it.contains("_"))
it.split("_").joinToString(separator = "") { it.capitalize() } else
it.capitalize()

}.memoize()
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
import com.github.marcoferrer.krotoplus.config.CompilerConfig
import com.github.marcoferrer.krotoplus.generators.Generator
import com.github.marcoferrer.krotoplus.generators.ProtoBuildersGenerator
import com.github.marcoferrer.krotoplus.proto.ProtoEnum
import com.github.marcoferrer.krotoplus.proto.ProtoMessage
import com.github.marcoferrer.krotoplus.utils.addFile
import com.github.marcoferrer.krotoplus.utils.addFunctions
import com.github.marcoferrer.krotoplus.utils.memoize
import com.google.protobuf.ByteString
import com.google.protobuf.DescriptorProtos
import com.google.protobuf.DescriptorProtos.FieldDescriptorProto.Label.LABEL_REPEATED
import com.google.protobuf.compiler.PluginProtos
import com.squareup.kotlinpoet.*

object VarArgExtensionGenerator : Generator {

private val gradleActionClassName = ClassName("org.gradle.api", "Action")

override val isEnabled: Boolean
get() = true

override fun invoke(): PluginProtos.CodeGeneratorResponse {
val configMessage = context.schema.protoTypes.values
.find { it.name == "CompilerConfig" } as ProtoMessage

val funSpecs = configMessage.descriptorProto.fieldList.asSequence()
.filter { it.type == DescriptorProtos.FieldDescriptorProto.Type.TYPE_MESSAGE }
.map {
it to requireNotNull(context.schema.protoTypes[it.typeName] as? ProtoMessage) {
"${it.typeName} was not found in schema type map."
}
}
.filterNot { it.second.isMapEntry }
.map { (fieldDescriptorProto, protoMessageForField) ->

val fieldNameCamelCase = camelCaseFieldName(fieldDescriptorProto.name)
val statementTemplate = "builder.add%N(%T.newBuilder().also{ block.execute(it) }.build())"

val funSpecBuilder = FunSpec.builder(fieldNameCamelCase.decapitalize())
.addStatement(statementTemplate, fieldNameCamelCase, protoMessageForField.className)

funSpecBuilder
.addParameter(
"block", ParameterizedTypeName
.get(gradleActionClassName, protoMessageForField.builderClassName)

)
.returns(UNIT)
.build()
}.toList()

val fileSpec = FileSpec.builder(configMessage.javaPackage.orEmpty(), "CompilerConfigDsl")
.addType(
TypeSpec.classBuilder("KrotoPlusConfigurator")
.addProperty(
PropertySpec.builder("builder", configMessage.builderClassName)
.addModifiers(KModifier.PRIVATE)
.initializer("%T.newBuilder()", configMessage.className)
.build()
)
.addFunctions(funSpecs)
.build()
)

// val typeSpec =

return PluginProtos.CodeGeneratorResponse.newBuilder()
.addFile(fileSpec.build().toResponseFileProto())
.build()
}

val camelCaseFieldName = { it: String ->
// We cant use CaseFormat.UPPER_CAMEL since
// protoc is lenient with malformed field names
if (it.contains("_"))
it.split("_").joinToString(separator = "") { it.capitalize() } else
it.capitalize()

}.memoize()
}

13 changes: 13 additions & 0 deletions kroto-plus-gradle-plugin/krotoPlusConfig.asciipb
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
generator_scripts {
script_path: "varArgExtensionGenerator.kts"
script_bundle: "gen-config-dsl/build/libs/bundle.jar"
}
insertions {
filter {
include_path: "krotoplus/*"
}
entry { point: BUILDER_SCOPE
script_path: "builderInsertion.kts"
script_bundle: "gen-config-dsl/build/libs/bundle.jar"
}
}

0 comments on commit 89ef739

Please sign in to comment.