From 53f7e471c486fd445cad1a5ee7cc4a7c89efa883 Mon Sep 17 00:00:00 2001 From: Blake Lassiter Date: Sun, 9 Feb 2025 05:56:00 -0800 Subject: [PATCH] unity error message and code cleanup (#20595) --- .../languages/CSharpClientCodegen.java | 154 ++++++++++-------- 1 file changed, 86 insertions(+), 68 deletions(-) diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/CSharpClientCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/CSharpClientCodegen.java index 1fe2a272caf0..7b34c5b927fc 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/CSharpClientCodegen.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/CSharpClientCodegen.java @@ -698,6 +698,8 @@ public void processOpts() { super.processOpts(); + final String library = getLibrary(); + /* * NOTE: When supporting boolean additionalProperties, you should read the value and write it back as a boolean. * This avoids oddities where additionalProperties contains "false" rather than false, which will cause the @@ -753,27 +755,37 @@ public void processOpts() { setModelPackage("Model"); } - if (GENERICHOST.equals(getLibrary())) { - setLibrary(GENERICHOST); - additionalProperties.put("useGenericHost", true); - } else if (RESTSHARP.equals(getLibrary())) { - additionalProperties.put("useRestSharp", true); - needsCustomHttpMethod = true; - } else if (HTTPCLIENT.equals(getLibrary())) { - setLibrary(HTTPCLIENT); - additionalProperties.put("useHttpClient", true); - needsUriBuilder = true; - } else if (UNITY_WEB_REQUEST.equals(getLibrary())) { - setLibrary(UNITY_WEB_REQUEST); - additionalProperties.put("useUnityWebRequest", true); - needsUriBuilder = true; + final Map libraryActions = Map.of( + GENERICHOST, () -> { + setLibrary(GENERICHOST); + additionalProperties.put("useGenericHost", true); + }, + RESTSHARP, () -> { + additionalProperties.put("useRestSharp", true); + needsCustomHttpMethod = true; + }, + HTTPCLIENT, () -> { + setLibrary(HTTPCLIENT); + additionalProperties.put("useHttpClient", true); + needsUriBuilder = true; + }, + UNITY_WEB_REQUEST, () -> { + setLibrary(UNITY_WEB_REQUEST); + additionalProperties.put("useUnityWebRequest", true); + needsUriBuilder = true; + } + ); + final Runnable action = libraryActions.get(library); + if (action != null) { + action.run(); } else { - throw new RuntimeException("Invalid HTTP library " + getLibrary() + ". Only restsharp, httpclient, and generichost are supported."); + String supportedLibraries = String.join(", ", libraryActions.keySet()); + throw new RuntimeException("Invalid HTTP library " + library + ". Only " + supportedLibraries + " are supported."); } - String inputFramework = (String) additionalProperties.getOrDefault(CodegenConstants.DOTNET_FRAMEWORK, latestFramework.name); - String[] frameworks; - List strategies = new ArrayList<>(); + final String inputFramework = (String) additionalProperties.getOrDefault(CodegenConstants.DOTNET_FRAMEWORK, latestFramework.name); + final String[] frameworks; + final List strategies = new ArrayList<>(); if (inputFramework.contains(";")) { // multiple target framework @@ -792,7 +804,7 @@ public void processOpts() { strategyMatched = true; } - if (frameworkStrategy != FrameworkStrategy.NETSTANDARD_2_0 && "restsharp".equals(getLibrary())) { + if (frameworkStrategy != FrameworkStrategy.NETSTANDARD_2_0 && RESTSHARP.equals(library)) { LOGGER.warn("If using built-in templates, RestSharp only supports netstandard 2.0 or later."); } } @@ -876,39 +888,43 @@ public void processOpts() { apiTestTemplateFiles.put("api_test.mustache", ".cs"); } - if (HTTPCLIENT.equals(getLibrary())) { - supportingFiles.add(new SupportingFile("FileParameter.mustache", clientPackageDir, "FileParameter.cs")); - addSupportingFiles(clientPackageDir, packageFolder, excludeTests, testPackageFolder, testPackageName, modelPackageDir, authPackageDir); - additionalProperties.put("apiDocPath", apiDocPath); - additionalProperties.put("modelDocPath", modelDocPath); - } else if (GENERICHOST.equals(getLibrary())) { - addGenericHostSupportingFiles(clientPackageDir, packageFolder, excludeTests, testPackageFolder, testPackageName, modelPackageDir); - additionalProperties.put("apiDocPath", apiDocPath + File.separatorChar + "apis"); - additionalProperties.put("modelDocPath", modelDocPath + File.separatorChar + "models"); - } else if (UNITY_WEB_REQUEST.equals(getLibrary())) { - additionalProperties.put(CodegenConstants.VALIDATABLE, false); - setValidatable(false); - setSupportsRetry(false); - setSupportsAsync(true); - // Some consoles and tvOS do not support either Application.persistentDataPath or will refuse to - // compile/link if you even reference GetTempPath as well. - additionalProperties.put("supportsFileParameters", false); - setSupportsFileParameters(false); - - addSupportingFiles(clientPackageDir, packageFolder, excludeTests, testPackageFolder, testPackageName, modelPackageDir, authPackageDir); - - supportingFiles.add(new SupportingFile("ConnectionException.mustache", clientPackageDir, "ConnectionException.cs")); - supportingFiles.add(new SupportingFile("UnexpectedResponseException.mustache", clientPackageDir, "UnexpectedResponseException.cs")); - } else { //restsharp - addSupportingFiles(clientPackageDir, packageFolder, excludeTests, testPackageFolder, testPackageName, modelPackageDir, authPackageDir); - additionalProperties.put("apiDocPath", apiDocPath); - additionalProperties.put("modelDocPath", modelDocPath); - - if (ProcessUtils.hasOAuthMethods(openAPI)) { - supportingFiles.add(new SupportingFile("auth/OAuthAuthenticator.mustache", authPackageDir, "OAuthAuthenticator.cs")); - supportingFiles.add(new SupportingFile("auth/TokenResponse.mustache", authPackageDir, "TokenResponse.cs")); - supportingFiles.add(new SupportingFile("auth/OAuthFlow.mustache", authPackageDir, "OAuthFlow.cs")); - } + switch (library) { + case HTTPCLIENT: + supportingFiles.add(new SupportingFile("FileParameter.mustache", clientPackageDir, "FileParameter.cs")); + addSupportingFiles(clientPackageDir, packageFolder, excludeTests, testPackageFolder, testPackageName, modelPackageDir, authPackageDir); + additionalProperties.put("apiDocPath", apiDocPath); + additionalProperties.put("modelDocPath", modelDocPath); + break; + case GENERICHOST: + addGenericHostSupportingFiles(clientPackageDir, packageFolder, excludeTests, testPackageFolder, testPackageName, modelPackageDir); + additionalProperties.put("apiDocPath", apiDocPath + File.separatorChar + "apis"); + additionalProperties.put("modelDocPath", modelDocPath + File.separatorChar + "models"); + break; + case UNITY_WEB_REQUEST: + additionalProperties.put(CodegenConstants.VALIDATABLE, false); + setValidatable(false); + setSupportsRetry(false); + setSupportsAsync(true); + // Some consoles and tvOS do not support either Application.persistentDataPath or will refuse to + // compile/link if you even reference GetTempPath as well. + additionalProperties.put("supportsFileParameters", false); + setSupportsFileParameters(false); + + addSupportingFiles(clientPackageDir, packageFolder, excludeTests, testPackageFolder, testPackageName, modelPackageDir, authPackageDir); + supportingFiles.add(new SupportingFile("ConnectionException.mustache", clientPackageDir, "ConnectionException.cs")); + supportingFiles.add(new SupportingFile("UnexpectedResponseException.mustache", clientPackageDir, "UnexpectedResponseException.cs")); + break; + default: // restsharp + addSupportingFiles(clientPackageDir, packageFolder, excludeTests, testPackageFolder, testPackageName, modelPackageDir, authPackageDir); + additionalProperties.put("apiDocPath", apiDocPath); + additionalProperties.put("modelDocPath", modelDocPath); + + if (ProcessUtils.hasOAuthMethods(openAPI)) { + supportingFiles.add(new SupportingFile("auth/OAuthAuthenticator.mustache", authPackageDir, "OAuthAuthenticator.cs")); + supportingFiles.add(new SupportingFile("auth/TokenResponse.mustache", authPackageDir, "TokenResponse.cs")); + supportingFiles.add(new SupportingFile("auth/OAuthFlow.mustache", authPackageDir, "OAuthFlow.cs")); + } + break; } if (useDateOnly()) { @@ -998,7 +1014,9 @@ public CodegenOperation fromOperation(String path, public void addSupportingFiles(final String clientPackageDir, final String packageFolder, final AtomicReference excludeTests, final String testPackageFolder, final String testPackageName, final String modelPackageDir, final String authPackageDir) { - if (RESTSHARP.equals(getLibrary())) { // restsharp + final String library = getLibrary(); + + if (RESTSHARP.equals(library)) { // restsharp if (useIntForTimeout) { // option to fall back to int for Timeout using v7.9.0 template supportingFiles.add(new SupportingFile("ApiClient.v790.mustache", clientPackageDir, "ApiClient.cs")); supportingFiles.add(new SupportingFile("IReadableConfiguration.v790.mustache", clientPackageDir, "IReadableConfiguration.cs")); @@ -1046,7 +1064,7 @@ public void addSupportingFiles(final String clientPackageDir, final String packa supportingFiles.add(new SupportingFile("git_push.sh.mustache", "", "git_push.sh")); supportingFiles.add(new SupportingFile("gitignore.mustache", "", ".gitignore")); - if (UNITY_WEB_REQUEST.equals(getLibrary())) { + if (UNITY_WEB_REQUEST.equals(library)) { supportingFiles.add(new SupportingFile("asmdef.mustache", packageFolder, packageName + ".asmdef")); } else { supportingFiles.add(new SupportingFile("Solution.mustache", "", packageName + ".sln")); @@ -1054,14 +1072,14 @@ public void addSupportingFiles(final String clientPackageDir, final String packa } if (Boolean.FALSE.equals(excludeTests.get())) { - if (UNITY_WEB_REQUEST.equals(getLibrary())) { + if (UNITY_WEB_REQUEST.equals(library)) { supportingFiles.add(new SupportingFile("asmdef_test.mustache", testPackageFolder, testPackageName + ".asmdef")); } else { supportingFiles.add(new SupportingFile("netcore_testproject.mustache", testPackageFolder, testPackageName + ".csproj")); } } - if (!UNITY_WEB_REQUEST.equals(getLibrary())) { + if (!UNITY_WEB_REQUEST.equals(library)) { supportingFiles.add(new SupportingFile("appveyor.mustache", "", "appveyor.yml")); } supportingFiles.add(new SupportingFile("AbstractOpenAPISchema.mustache", modelPackageDir, "AbstractOpenAPISchema.cs")); @@ -1622,24 +1640,23 @@ public ModelsMap postProcessModels(ModelsMap objs) { for (ModelMap mo : objs.getModels()) { CodegenModel cm = mo.getModel(); - if (cm.oneOf != null && !cm.oneOf.isEmpty() && cm.oneOf.contains("Null")) { + if (cm.oneOf != null && !cm.oneOf.isEmpty() && cm.oneOf.remove("Null")) { // if oneOf contains "null" type cm.isNullable = true; - cm.oneOf.remove("Null"); } - if (cm.anyOf != null && !cm.anyOf.isEmpty() && cm.anyOf.contains("Null")) { + if (cm.anyOf != null && !cm.anyOf.isEmpty() && cm.anyOf.remove("Null")) { // if anyOf contains "null" type cm.isNullable = true; - cm.anyOf.remove("Null"); - } - - if (cm.getComposedSchemas() != null && cm.getComposedSchemas().getOneOf() != null && !cm.getComposedSchemas().getOneOf().isEmpty()) { - cm.getComposedSchemas().getOneOf().removeIf(o -> o.dataType.equals("Null")); } - if (cm.getComposedSchemas() != null && cm.getComposedSchemas().getAnyOf() != null && !cm.getComposedSchemas().getAnyOf().isEmpty()) { - cm.getComposedSchemas().getAnyOf().removeIf(o -> o.dataType.equals("Null")); + if (cm.getComposedSchemas() != null) { + if (cm.getComposedSchemas().getOneOf() != null) { + cm.getComposedSchemas().getOneOf().removeIf(o -> "Null".equals(o.dataType)); + } + if (cm.getComposedSchemas().getAnyOf() != null) { + cm.getComposedSchemas().getAnyOf().removeIf(o -> "Null".equals(o.dataType)); + } } for (CodegenProperty cp : cm.readWriteVars) { @@ -1648,7 +1665,7 @@ public ModelsMap postProcessModels(ModelsMap objs) { // see modules\openapi-generator\src\test\resources\3_0\allOf.yaml // property boosterSeat will be in readWriteVars but not allVars // the property is present in the model but gets removed at CodegenModel#removeDuplicatedProperty - if (Boolean.FALSE.equals(cm.allVars.stream().anyMatch(v -> v.baseName.equals(cp.baseName)))) { + if (cm.allVars.stream().noneMatch(v -> v.baseName.equals(cp.baseName))) { LOGGER.debug("Property " + cp.baseName + " was found in readWriteVars but not in allVars. Adding it back to allVars"); cm.allVars.add(cp); } @@ -1658,6 +1675,7 @@ public ModelsMap postProcessModels(ModelsMap objs) { return objs; } + // https://github.com/OpenAPITools/openapi-generator/issues/15867 @Override protected void removePropertiesDeclaredInComposedTypes(Map objs, CodegenModel model, List composedProperties) { @@ -1703,7 +1721,7 @@ protected void removePropertiesDeclaredInComposedTypes(Map ob @Override protected boolean isValueType(CodegenProperty var) { // this is temporary until x-csharp-value-type is removed - return this.getLibrary().equals("generichost") + return this.getLibrary().equals(GENERICHOST) ? super.isValueType(var) : this.getValueTypes().contains(var.dataType) || var.isEnum; }