Skip to content

Commit 8124d85

Browse files
authored
Kotlin ktor delegate pattern support (#23756)
* Generating All Apis class and delegate interfaces for ktor library * Working delegates * Working delegates * Working delegates for ktor * Generate updated doc for delegate pattern option * Fix tests after conflicts resolved * Fix delegates unsafe casting by using as? * Use fromValue() method for enum parsing * Use to<dataType>() to extract numerical values * Fix multipleOf validation to support floating-point
1 parent 6e2c8ce commit 8124d85

82 files changed

Lines changed: 4331 additions & 86 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -312,3 +312,6 @@ samples/client/jetbrains/adyen/checkout71/http/client/Apis/http-client.private.e
312312

313313
# Generated by the run-in-docker.sh
314314
\?/
315+
316+
# AI agent caches
317+
.junie
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
generatorName: kotlin-server
2+
outputDir: samples/server/petstore/kotlin-server/ktor-delegate-pattern/generated
3+
library: ktor
4+
inputSpec: modules/openapi-generator/src/test/resources/3_1/petstore.yaml
5+
templateDir: modules/openapi-generator/src/main/resources/kotlin-server
6+
additionalProperties:
7+
hideGenerationTimestamp: "true"
8+
serializableModel: "true"
9+
delegatePattern: "true"

docs/generators/kotlin-server.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ These options may be applied as additional-properties (cli) or configOptions (pl
2222
|apiSuffix|suffix for api classes| |Api|
2323
|artifactId|Generated artifact id (name of jar).| |kotlin-server|
2424
|artifactVersion|Generated artifact's package version.| |1.0.0|
25+
|delegatePattern|Whether to generate the server files using the delegate pattern. This option is currently supported only when using ktor library.| |false|
2526
|enumPropertyNaming|Naming convention for enum properties: 'camelCase', 'PascalCase', 'snake_case', 'UPPERCASE', 'original', and 'bestEffortBacktick' (like 'original' but tries to wrap values in backticks before falling back to sanitizing, e.g. `name,asc` stays `name,asc` rather than becoming nameCommaAsc; useful for sort/order enums)| |original|
2627
|featureAutoHead|Automatically provide responses to HEAD requests for existing routes that have the GET verb defined.| |true|
2728
|featureCORS|Ktor by default provides an interceptor for implementing proper support for Cross-Origin Resource Sharing (CORS). See enable-cors.org.| |false|

modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/KotlinServerCodegen.java

Lines changed: 31 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,9 @@ public class KotlinServerCodegen extends AbstractKotlinCodegen implements BeanVa
100100
@Getter
101101
@Setter
102102
private boolean fixJacksonJsonTypeInfoInheritance = true;
103+
@Getter
104+
@Setter
105+
private Boolean delegatePatternEnabled = false;
103106

104107
/**
105108
* Constructs an instance of `KotlinServerCodegen`.
@@ -174,6 +177,7 @@ public KotlinServerCodegen() {
174177
addSwitch(Constants.OMIT_GRADLE_WRAPPER, Constants.OMIT_GRADLE_WRAPPER_DESC, omitGradleWrapper);
175178
addSwitch(USE_JAKARTA_EE, Constants.USE_JAKARTA_EE_DESC, useJakartaEe);
176179
addSwitch(Constants.FIX_JACKSON_JSON_TYPE_INFO_INHERITANCE, Constants.FIX_JACKSON_JSON_TYPE_INFO_INHERITANCE_DESC, fixJacksonJsonTypeInfoInheritance);
180+
addSwitch(Constants.DELEGATE_PATTERN, Constants.DELEGATE_PATTERN_DESC, getDelegatePatternEnabled());
177181
}
178182

179183
@Override
@@ -307,6 +311,17 @@ public void processOpts() {
307311
} else {
308312
additionalProperties.put(Constants.METRICS, getMetricsFeatureEnabled());
309313
}
314+
if(isKtor()){
315+
if (additionalProperties.containsKey(Constants.DELEGATE_PATTERN)) {
316+
setDelegatePatternEnabled(convertPropertyToBooleanAndWriteBack(Constants.DELEGATE_PATTERN));
317+
} else {
318+
additionalProperties.put(Constants.DELEGATE_PATTERN, getDelegatePatternEnabled());
319+
}
320+
if (delegatePatternEnabled) {
321+
typeMapping.put("file", "io.ktor.http.content.PartData.FileItem");
322+
importMapping.put("io.ktor.http.content.PartData.FileItem", "io.ktor.http.content.PartData.FileItem");
323+
}
324+
}
310325

311326
boolean generateApis = additionalProperties.containsKey(CodegenConstants.GENERATE_APIS) && (Boolean) additionalProperties.get(CodegenConstants.GENERATE_APIS);
312327
String packageFolder = (sourceFolder + File.separator + packageName).replace(".", File.separator);
@@ -330,9 +345,10 @@ public void processOpts() {
330345
if (isKtor2Or3()) {
331346
additionalProperties.put(Constants.IS_KTOR, true);
332347

333-
supportingFiles.add(new SupportingFile("AppMain.kt.mustache", packageFolder, "AppMain.kt"));
334-
supportingFiles.add(new SupportingFile("Configuration.kt.mustache", packageFolder, "Configuration.kt"));
335-
348+
if(!delegatePatternEnabled) {
349+
supportingFiles.add(new SupportingFile("AppMain.kt.mustache", packageFolder, "AppMain.kt"));
350+
supportingFiles.add(new SupportingFile("Configuration.kt.mustache", packageFolder, "Configuration.kt"));
351+
}
336352
if (generateApis && resourcesFeatureEnabled) {
337353
supportingFiles.add(new SupportingFile("Paths.kt.mustache", packageFolder, "Paths.kt"));
338354
}
@@ -347,6 +363,16 @@ public void processOpts() {
347363
if (!getOmitGradleWrapper()) {
348364
supportingFiles.add(new SupportingFile("gradle-wrapper.properties", "gradle" + File.separator + "wrapper", "gradle-wrapper.properties"));
349365
}
366+
if(isKtor()){
367+
supportingFiles.add(new SupportingFile("AllApis.kt.mustache", packageFolder, "AllApis.kt"));
368+
if(delegatePatternEnabled){
369+
apiTemplateFiles.put("apiDelegate.mustache", "Delegate.kt");
370+
supportingFiles.add(new SupportingFile("Delegates.kt.mustache", infrastructureFolder, "Delegates.kt"));
371+
supportingFiles.add(new SupportingFile("AppDelegates.kt.mustache", infrastructureFolder, "AppDelegates.kt"));
372+
supportingFiles.add(new SupportingFile("BadParameterException.kt.mustache", infrastructureFolder, "BadParameterException.kt"));
373+
supportingFiles.add(new SupportingFile("APINotImplementedException.kt.mustache", infrastructureFolder, "APINotImplementedException.kt"));
374+
}
375+
}
350376

351377
} else if (isJavalin()) {
352378
supportingFiles.add(new SupportingFile("Main.kt.mustache", packageFolder, "Main.kt"));
@@ -402,6 +428,8 @@ public static class Constants {
402428
public static final String FIX_JACKSON_JSON_TYPE_INFO_INHERITANCE_DESC = "When true (default), ensures Jackson polymorphism works correctly by: (1) always setting visible=true on @JsonTypeInfo, and (2) adding the discriminator property to child models with appropriate default values. When false, visible is only set to true if all children already define the discriminator property.";
403429
public static final String USE_TAGS = "useTags";
404430
public static final String USE_TAGS_DESC = "use tags for creating interface and controller classnames.";
431+
public static final String DELEGATE_PATTERN = "delegatePattern";
432+
public static final String DELEGATE_PATTERN_DESC = "Whether to generate the server files using the delegate pattern. This option is currently supported only when using ktor library.";
405433
}
406434

407435
@Override

0 commit comments

Comments
 (0)