Gradle plugin with multi-spec support - #5
Conversation
There was a problem hiding this comment.
Pull request overview
Adds a dedicated Gradle plugin module to generate Kotlin clients/models from multiple OpenAPI specs, and extends the core parser/generators with polymorphism, inline-schema handling, and shared response types.
Changes:
- Introduces
pluginsubproject withjustworks { specs { ... } }multi-spec DSL and generation tasks (including shared types). - Expands core OpenAPI parsing/validation and codegen (oneOf/anyOf/allOf, inline schema dedup, serializers module, response wrappers).
- Adds extensive unit + functional test coverage and test resources for parser/codegen.
Reviewed changes
Copilot reviewed 8 out of 9 changed files in this pull request and generated 9 comments.
Show a summary per file
| File | Description |
|---|---|
| settings.gradle.kts | Adds plugin subproject to the build. |
| .gitignore | Ignores Gradle/Kotlin/IDE build artifacts. |
| core/build.gradle.kts | Adds Arrow + compiler args; ktlint pin workaround. |
| core/src/main/kotlin/com/avsystem/justworks/core/Generator.kt | Adds placeholder generator entry point. |
| core/src/main/kotlin/com/avsystem/justworks/core/gen/ApiResponseGenerator.kt | Generates shared HttpError/HttpSuccess types. |
| core/src/main/kotlin/com/avsystem/justworks/core/gen/ClientGenerator.kt | Generates Ktor client code per tag + error handling. |
| core/src/main/kotlin/com/avsystem/justworks/core/gen/InlineSchemaDeduplicator.kt | Adds inline schema structural dedup + naming collision handling. |
| core/src/main/kotlin/com/avsystem/justworks/core/gen/ModelGenerator.kt | Adds polymorphic + inline schema generation features and defaults. |
| core/src/main/kotlin/com/avsystem/justworks/core/gen/NameUtils.kt | Adds name transformations for identifiers/enum constants/ops. |
| core/src/main/kotlin/com/avsystem/justworks/core/gen/Names.kt | Centralizes KotlinPoet references for generator output. |
| core/src/main/kotlin/com/avsystem/justworks/core/gen/SerializersModuleGenerator.kt | Emits generatedSerializersModule for polymorphic types. |
| core/src/main/kotlin/com/avsystem/justworks/core/gen/TypeMapping.kt | Maps TypeRef to KotlinPoet TypeNames. |
| core/src/main/kotlin/com/avsystem/justworks/core/model/ApiSpec.kt | Introduces parsed model layer (ApiSpec, SchemaModel, etc.). |
| core/src/main/kotlin/com/avsystem/justworks/core/model/TypeRef.kt | Adds TypeRef IR including inline schemas. |
| core/src/main/kotlin/com/avsystem/justworks/core/parser/SpecParser.kt | Implements parsing + validation + $ref + combinator handling. |
| core/src/main/kotlin/com/avsystem/justworks/core/parser/SpecValidator.kt | Adds spec validation issues (errors + warnings). |
| core/src/test/kotlin/com/avsystem/justworks/core/gen/ApiResponseGeneratorTest.kt | Tests shared response type generation. |
| core/src/test/kotlin/com/avsystem/justworks/core/gen/ClientGeneratorTest.kt | Tests generated client structure and request wiring. |
| core/src/test/kotlin/com/avsystem/justworks/core/gen/InlineSchemaDedupTest.kt | Tests inline schema dedup + naming collision behavior. |
| core/src/test/kotlin/com/avsystem/justworks/core/gen/ModelGeneratorPolymorphicTest.kt | Tests polymorphic model generation behaviors. |
| core/src/test/kotlin/com/avsystem/justworks/core/gen/ModelGeneratorTest.kt | Tests model generation incl defaults + keywords + aliases. |
| core/src/test/kotlin/com/avsystem/justworks/core/gen/NameUtilsTest.kt | Tests name/identifier conversion utilities. |
| core/src/test/kotlin/com/avsystem/justworks/core/gen/SerializersModuleGeneratorTest.kt | Tests serializers module generation output. |
| core/src/test/kotlin/com/avsystem/justworks/core/gen/TypeMappingTest.kt | Tests TypeRef -> Kotlin type mapping. |
| core/src/test/kotlin/com/avsystem/justworks/core/parser/SpecParserPolymorphicTest.kt | Tests oneOf/allOf/discriminator parsing outcomes. |
| core/src/test/kotlin/com/avsystem/justworks/core/parser/SpecParserTest.kt | Tests parser correctness across refs/v2/anyOf errors. |
| core/src/test/kotlin/com/avsystem/justworks/core/parser/SpecValidatorTest.kt | Tests validation issue detection. |
| core/src/test/resources/anyof-spec.yaml | Adds anyOf test fixture. |
| core/src/test/resources/anyof-valid-spec.yaml | Adds discriminator + anyOf test fixture. |
| core/src/test/resources/invalid-spec.yaml | Adds invalid spec fixture for error tests. |
| core/src/test/resources/mixed-combinator-spec.yaml | Adds mixed combinator fixture for failure tests. |
| core/src/test/resources/petstore-v2.json | Adds Swagger v2 conversion fixture. |
| core/src/test/resources/petstore.yaml | Adds OpenAPI v3 petstore fixture. |
| core/src/test/resources/polymorphic-spec.yaml | Adds oneOf/allOf polymorphism fixture. |
| core/src/test/resources/refs-spec.yaml | Adds $ref resolution fixture. |
| plugin/build.gradle.kts | Defines Gradle plugin + functionalTest source set. |
| plugin/src/functionalTest/kotlin/com/avsystem/justworks/gradle/JustworksPluginFunctionalTest.kt | End-to-end TestKit coverage for multi-spec plugin. |
| plugin/src/main/kotlin/com/avsystem/justworks/gradle/JustworksExtension.kt | Adds multi-spec DSL extension container. |
| plugin/src/main/kotlin/com/avsystem/justworks/gradle/JustworksGenerateTask.kt | Cacheable generation task wiring parser + generators. |
| plugin/src/main/kotlin/com/avsystem/justworks/gradle/JustworksPlugin.kt | Registers tasks per spec + source-set wiring. |
| plugin/src/main/kotlin/com/avsystem/justworks/gradle/JustworksSharedTypesTask.kt | Cacheable task to generate shared response types. |
| plugin/src/main/kotlin/com/avsystem/justworks/gradle/JustworksSpecConfiguration.kt | Adds per-spec configuration object. |
Comments suppressed due to low confidence (2)
plugin/src/main/kotlin/com/avsystem/justworks/gradle/JustworksSpecConfiguration.kt:1
- The KDoc DSL example uses
specFile = .../packageName = ..., but these arevalGradlePropertytypes; assignment won’t compile in Kotlin DSL. Update the docs to usespecFile.set(file(...))andpackageName.set("...")(and similarly forapiPackage/modelPackage), or change the API to expose Kotlin-DSL-friendly setters (e.g.,var specFile: Filedelegating to the underlyingRegularFileProperty).
plugin/src/functionalTest/kotlin/com/avsystem/justworks/gradle/JustworksPluginFunctionalTest.kt:1 - The functional test project’s build script configures
specFile/packageNamevia assignment, butJustworksSpecConfigurationexposes these asRegularFileProperty/Property<String>vals, so the script should use.set(...)(or the plugin should provide DSL-friendly setters). As written, the TestKit build should fail during Kotlin script compilation.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
You can also share your feedback on Copilot code review. Take the survey.
JustworksPlugin, JustworksExtension, JustworksGenerateTask, JustworksSharedTypesTask, JustworksSpecConfiguration for multi-spec DSL. Functional tests included. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
72d5acd to
1c4647e
Compare
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 8 out of 9 changed files in this pull request and generated 11 comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
You can also share your feedback on Copilot code review. Take the survey.
| specs { | ||
| register("pet-store") { | ||
| specFile = file("api/petstore.yaml") | ||
| packageName = "com.example" | ||
| } | ||
| } |
| // Functional test source set | ||
| val functionalTest by sourceSets.creating { | ||
| compileClasspath += sourceSets["main"].output | ||
| runtimeClasspath += sourceSets["main"].output | ||
| } | ||
|
|
||
| val functionalTestImplementation by configurations.getting { | ||
| extendsFrom(configurations["testImplementation"]) | ||
| } | ||
|
|
||
| val functionalTestRuntimeOnly by configurations.getting { | ||
| extendsFrom(configurations["testRuntimeOnly"]) | ||
| } | ||
|
|
||
| dependencies { | ||
| functionalTestImplementation(gradleTestKit()) | ||
| } | ||
|
|
||
| val functionalTestTask = | ||
| tasks.register<Test>("functionalTest") { | ||
| testClassesDirs = functionalTest.output.classesDirs | ||
| classpath = functionalTest.runtimeClasspath | ||
| useJUnitPlatform() | ||
| } |
| * specFile = file("api/petstore.yaml") | ||
| * packageName = "com.example.petstore" |
| /** Path to the OpenAPI spec file (.yaml or .json). */ | ||
| abstract val specFile: RegularFileProperty | ||
|
|
||
| /** Base package name for generated code (e.g., "com.example.api"). */ | ||
| abstract val packageName: Property<String> | ||
|
|
||
| /** | ||
| * Package for generated API client classes. | ||
| * Defaults to `"$packageName.api"` if not set. | ||
| */ | ||
| abstract val apiPackage: Property<String> | ||
|
|
||
| /** | ||
| * Package for generated model/data classes. | ||
| * Defaults to `"$packageName.model"` if not set. | ||
| */ | ||
| abstract val modelPackage: Property<String> |
| justworks { | ||
| specs { | ||
| register("main") { | ||
| specFile = file("api/petstore.yaml") | ||
| packageName = "com.example" | ||
| $extraDsl | ||
| } | ||
| } | ||
| } |
| implementation("io.ktor:ktor-client-core:3.1.1") | ||
| implementation("io.ktor:ktor-client-content-negotiation:3.1.1") | ||
| implementation("io.ktor:ktor-serialization-kotlinx-json:3.1.1") | ||
| implementation("io.arrow-kt:arrow-core:2.1.2") |
| specFile = file("api/petstore.yaml") | ||
| packageName = "com.example.petstore" | ||
| } | ||
| register("payments") { | ||
| specFile = file("api/payments.yaml") | ||
| packageName = "com.example.payments" |
| specFile = file("api/petstore.yaml") | ||
| packageName = "com.example.petstore" | ||
| } | ||
| register("payments") { | ||
| specFile = file("api/payments.yaml") | ||
| packageName = "com.example.payments" |
- Introduced `generateTo` methods in `ApiResponseGenerator`, `ModelGenerator`, and `ClientGenerator` to streamline file generation and output directory management. - Updated `JustworksGenerateTask` to use the new methods with enhanced polymorphic type handling.
…teTo methods - Unified `ApiResponseGenerator`, `ModelGenerator`, and `ClientGenerator` under `CodeGenerator` to streamline generation logic. - Removed redundant `generateTo` methods, simplifying file generation and output handling. - Updated Gradle tasks to leverage the new `CodeGenerator` structure.
Summary
JustworksPlugin— registers tasks per spec configurationJustworksExtensionwithNamedDomainObjectContainerfor multi-spec DSLJustworksGenerateTask— wires parser + generators into Gradle taskJustworksSharedTypesTask— generates shared API response typesJustworksSpecConfiguration— per-spec configuration (specFile, packages, outputDir)Test plan
./gradlew plugin:testpasses./gradlew core:testpassesDepends on #4
🤖 Generated with Claude Code