eclipse-vertx / vertx-codegen

Vert.x code generator for asynchronous polyglot APIs
Apache License 2.0
103 stars 91 forks source link

Annotation processor custom generator-loader issue #280

Closed mustafakibar closed 5 years ago

mustafakibar commented 5 years ago

I have a project with vert.x(3.8.1), kotlin(1.3.50) and gradle(5.6). I have many classes marked as @DataObject(generateConverter = true).

Also I want to use snake_case format on generated files so I'm using @eutkin sample https://github.com/eutkin/vertx-gen-snake-case .

Response class:

@DataObject(generateConverter = true)
class Response() {

    var statusId: Int = -1

    constructor(json: JsonObject) : this() {
        ResponseConverter.fromJson(json, this)
    }

    fun toJson() = JsonObject().also { ResponseConverter.toJson(this, it) }

}

When I was build my project then I look at the ResponseConverter class, but as you see below keys not the snake_case format. After a few attempts, I saw that the codegen processor does not use the DataObjectHelperGeneratorLoader but I already defined under resources. What's wrong?

public class ResponseConverter {

  public static void fromJson(Iterable<java.util.Map.Entry<String, Object>> json, Response obj) {
    for (java.util.Map.Entry<String, Object> member : json) {
      switch (member.getKey()) {
        case "statusId": // expected:  status_id
          if (member.getValue() instanceof Number) {
            obj.setStatusId(((Number)member.getValue()).intValue());
          }
          break;
      }
    }
  }

  public static void toJson(Response obj, JsonObject json) {
    toJson(obj, json.getMap());
  }

  public static void toJson(Response obj, java.util.Map<String, Object> json) {
    json.put("statusId" // expected status_id, obj.getStatusId());
  }
}

Project structure:

- src
     - main
          - kotlin
          - resources
               - META-INF
                    - services
                         - io.vertx.codegen.GeneratorLoader
- build.gradle.kts

build.gradle.kts:

import org.jetbrains.kotlin.gradle.tasks.KotlinCompile

plugins {
    idea
    java
    application
    kotlin("jvm").version(Config.Versions.kotlin)
    kotlin("kapt").version(Config.Versions.kotlin)
}

buildscript {
    dependencies {
        classpath(Config.Plugins.kotlin_gradle)
    }
}

application {
    mainClassName = "App"
}

java {
    sourceCompatibility = JavaVersion.VERSION_1_8
    targetCompatibility = JavaVersion.VERSION_1_8
}

idea {
    module {
        isDownloadJavadoc = true
        isDownloadSources = true
    }
}

task<JavaCompile>("annotationProcessing") {
    source = fileTree("${project.projectDir}/src/main/kotlin")
    classpath = configurations.compile.get() + configurations.compileOnly.get()
    destinationDir = project.file("build/generated")
    options.annotationProcessorPath = classpath
    options.compilerArgs = listOf(
        "-proc:only",
        "-processor", "io.vertx.codegen.CodeGenProcessor",
        "-Acodegen.output=${project.projectDir}/src/main/"
    )
}

tasks.withType<KotlinCompile> {
    kotlinOptions {
        jvmTarget = "1.8"
    }
}

tasks.getByName("compileJava").dependsOn("annotationProcessing")

sourceSets {
    getByName("main").resources.srcDirs("src/main/resources")
    getByName("main").java.srcDirs("src/main/kotlin", "src/main/java")
    getByName("test").java.srcDirs("src/test/kotlin", "src/main/java")
}

dependencies {
    compile(kotlin("stdlib"))
    compile(kotlin("reflect"))
    compile(Config.Libs.kotlin_coroutine)
    compile(Config.Libs.jackson)
    compile(Config.Libs.vertx_web)
    compile(Config.Libs.vertx_core)
    compile(Config.Libs.vertx_kotlin)
    compile(Config.Libs.vertx_kotlin_coroutines)
    compile(Config.Libs.vertx_config)
    compile(Config.Libs.vertx_service_proxy)
    compile(Config.Libs.vertx_service_discovery)
    compile(Config.Libs.vertx_hazelcast)
    compileOnly(Config.Libs.vertx_codegen)
    kapt(Config.Libs.vertx_codegen_kapt)
}

io.vertx.codegen.GeneratorLoader: io.github.eutkin.snakecase.DataObjectHelperGeneratorLoader

okou19900722 commented 5 years ago

you need to add -Acodegen.generators=sc_data_object_converters to you annotation processor compiler args. it's should be like that

task<JavaCompile>("annotationProcessing") {
    source = fileTree("${project.projectDir}/src/main/kotlin")
    classpath = configurations.compile.get() + configurations.compileOnly.get()
    destinationDir = project.file("build/generated")
    options.annotationProcessorPath = classpath
    options.compilerArgs = listOf(
        "-proc:only",
        "-processor", "io.vertx.codegen.CodeGenProcessor",
        "-Acodegen.output=${project.projectDir}/src/main/",
        "-Acodegen.generators=sc_data_object_converters"
    )
}

without that argument, it will load all the generator, so you must config all the generator which you required.

mustafakibar commented 5 years ago
tasks {
    register<JavaCompile>("annotationProcessing") {
        source("src/main/kotlin")
        classpath = configurations["annotationProcessor"] + configurations["compile"] + configurations["compileOnly"]
        destinationDir = project.file("build/generated")
        options.annotationProcessorPath = classpath
        options.annotationProcessorGeneratedSourcesDirectory = file("build/generated")

        options.compilerArgs = listOf(
            "-proc:only",
            "-processor", "io.vertx.codegen.CodeGenProcessor",
            "-Acodegen.output=${project.projectDir}/src/main/",
            "-Acodegen.generators=sc_data_object_converters"
        )
    }

    getByName("compileJava").dependsOn("annotationProcessing")
}

sourceSets {
    getByName("main").resources.srcDirs("conf", "src/main/resources")
    getByName("main").java.srcDirs("src/main/kotlin", "src/main/java", "build/generated")
    getByName("test").java.srcDirs("src/test/kotlin", "src/test/java")
}

Thank you for interest I tried it unfortunately did not work 😞 I have tried different combinations as follows but nothing changed;

  1. kapt(Config.Libs.vertx_codegen_kapt) > annotationProcessor(Config.Libs.vertx_codegen_kapt)
  2. options.annotationProcessorPath = classpath > options.annotationProcessorPath = configurations.annotationProcessor.get()

Config.Libs.vertx_codegen_kapt = io.vertx:vertx-codegen:3.8.1:processor

okou19900722 commented 5 years ago

sorry, I missed a very important configuration. For gradle 5 and above, you need to configure the dependency of annotation processor separately.

dependencies {
    annotationProcessor("io.vertx:vertx-codegen:$version")
    //other dependencies which annotation processor depends on
}
mustafakibar commented 5 years ago

Yes I tried but it didnt work. If I change kapt to annotationProcessor of the previous comment this time I got an error like that 'Annotation Processor io.vertx.codegen.CodeGenProcessor not found' .

okou19900722 commented 5 years ago

Can you provide the simplest code to reproduce on github?

mustafakibar commented 5 years ago

here is the reproduce: repo-link

okou19900722 commented 5 years ago

Sorry, I saw that you are using the JavaCompile task, I mistakenly think that your DataObject is a Java class. If you use the kotlin class, it seems that you can only use kapt to execute codegen I submitted a pr so that I can delete my repository and the links discussed in this issue will not return 404. https://github.com/mustafakibar/vertx-codegen.snake-case/pull/1

mustafakibar commented 5 years ago

Working smoothly thanks!