mirror of
https://github.com/OpenAPITools/openapi-generator.git
synced 2026-03-18 16:39:21 +00:00
Merge remote-tracking branch 'origin/3.4.x' into 4.0.x
This commit is contained in:
@@ -221,6 +221,10 @@ public class CodegenConstants {
|
||||
public static final String SOURCECODEONLY_GENERATION = "generateSourceCodeOnly";
|
||||
public static final String SOURCECODEONLY_GENERATION_DESC = "Specifies that only a library source code is to be generated.";
|
||||
|
||||
public static final String PARCELIZE_MODELS = "parcelizeModels";
|
||||
public static final String PARCELIZE_MODELS_DESC = "toggle \"@Parcelize\" for generated models";
|
||||
|
||||
|
||||
// Not user-configurable. System provided for use in templates.
|
||||
|
||||
public static final String GENERATE_APIS = "generateApis";
|
||||
|
||||
@@ -2985,6 +2985,12 @@ public class DefaultCodegen implements CodegenConfig {
|
||||
LOGGER.warn("Unknown parameter type: " + parameter.getName());
|
||||
}
|
||||
|
||||
// default to UNKNOWN_PARAMETER_NAME if paramName is null
|
||||
if (codegenParameter.paramName == null) {
|
||||
LOGGER.warn("Parameter name not defined properly. Default to UNKNOWN_PARAMETER_NAME");
|
||||
codegenParameter.paramName = "UNKNOWN_PARAMETER_NAME";
|
||||
}
|
||||
|
||||
// set the parameter excample value
|
||||
// should be overridden by lang codegen
|
||||
setParameterExampleValue(codegenParameter, parameter);
|
||||
|
||||
@@ -170,7 +170,6 @@ public class DefaultGenerator extends AbstractGenerator implements Generator {
|
||||
config.additionalProperties().put(CodegenConstants.EXCLUDE_TESTS, true);
|
||||
}
|
||||
|
||||
|
||||
if (System.getProperty("debugOpenAPI") != null) {
|
||||
Json.prettyPrint(openAPI);
|
||||
} else if (System.getProperty("debugSwagger") != null) {
|
||||
@@ -524,10 +523,31 @@ public class DefaultGenerator extends AbstractGenerator implements Generator {
|
||||
operation.put("importPath", config.toApiImport(tag));
|
||||
operation.put("classFilename", config.toApiFilename(tag));
|
||||
|
||||
if (allModels == null || allModels.isEmpty()) {
|
||||
operation.put("hasModel", false);
|
||||
} else {
|
||||
operation.put("hasModel", true);
|
||||
}
|
||||
|
||||
if (!config.vendorExtensions().isEmpty()) {
|
||||
operation.put("vendorExtensions", config.vendorExtensions());
|
||||
}
|
||||
|
||||
// process top-level x-group-parameters
|
||||
if (config.vendorExtensions().containsKey("x-group-parameters")) {
|
||||
Boolean isGroupParameters = Boolean.valueOf(config.vendorExtensions().get("x-group-parameters").toString());
|
||||
|
||||
Map<String, Object> objectMap = (Map<String, Object>) operation.get("operations");
|
||||
@SuppressWarnings("unchecked")
|
||||
List<CodegenOperation> operations = (List<CodegenOperation>) objectMap.get("operation");
|
||||
for (CodegenOperation op : operations) {
|
||||
op.httpMethod = op.httpMethod.toLowerCase(Locale.ROOT);
|
||||
if (!op.vendorExtensions.containsKey("x-group-parameters")) {
|
||||
op.vendorExtensions.put("x-group-parameters", Boolean.TRUE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Pass sortParamsByRequiredFlag through to the Mustache template...
|
||||
boolean sortParamsByRequiredFlag = true;
|
||||
if (this.config.additionalProperties().containsKey(CodegenConstants.SORT_PARAMS_BY_REQUIRED_FLAG)) {
|
||||
@@ -1032,13 +1052,16 @@ public class DefaultGenerator extends AbstractGenerator implements Generator {
|
||||
}
|
||||
|
||||
List<Map<String, String>> imports = new ArrayList<Map<String, String>>();
|
||||
Set<String> mappingSet = new TreeSet<>();
|
||||
for (String nextImport : allImports) {
|
||||
Map<String, String> im = new LinkedHashMap<String, String>();
|
||||
String mapping = config.importMapping().get(nextImport);
|
||||
if (mapping == null) {
|
||||
mapping = config.toModelImport(nextImport);
|
||||
}
|
||||
if (mapping != null) {
|
||||
|
||||
if (mapping != null && !mappingSet.contains(mapping)) { // ensure import (mapping) is unique
|
||||
mappingSet.add(mapping);
|
||||
im.put("import", mapping);
|
||||
im.put("classname", nextImport);
|
||||
if (!imports.contains(im)) { // avoid duplicates
|
||||
@@ -1053,6 +1076,7 @@ public class DefaultGenerator extends AbstractGenerator implements Generator {
|
||||
if (imports.size() > 0) {
|
||||
operations.put("hasImport", true);
|
||||
}
|
||||
|
||||
config.postProcessOperations(operations);
|
||||
config.postProcessOperationsWithModels(operations, allModels);
|
||||
if (objs.size() > 0) {
|
||||
|
||||
@@ -160,21 +160,21 @@ public abstract class AbstractCSharpCodegen extends DefaultCodegen implements Co
|
||||
typeMapping = new HashMap<String, String>();
|
||||
typeMapping.put("string", "string");
|
||||
typeMapping.put("binary", "byte[]");
|
||||
typeMapping.put("bytearray", "byte[]");
|
||||
typeMapping.put("ByteArray", "byte[]");
|
||||
typeMapping.put("boolean", "bool?");
|
||||
typeMapping.put("integer", "int?");
|
||||
typeMapping.put("float", "float?");
|
||||
typeMapping.put("long", "long?");
|
||||
typeMapping.put("double", "double?");
|
||||
typeMapping.put("number", "decimal?");
|
||||
typeMapping.put("datetime", "DateTime?");
|
||||
typeMapping.put("DateTime", "DateTime?");
|
||||
typeMapping.put("date", "DateTime?");
|
||||
typeMapping.put("file", "System.IO.Stream");
|
||||
typeMapping.put("array", "List");
|
||||
typeMapping.put("list", "List");
|
||||
typeMapping.put("map", "Dictionary");
|
||||
typeMapping.put("object", "Object");
|
||||
typeMapping.put("uuid", "Guid?");
|
||||
typeMapping.put("UUID", "Guid?");
|
||||
}
|
||||
|
||||
public void setReturnICollection(boolean returnICollection) {
|
||||
@@ -216,6 +216,7 @@ public abstract class AbstractCSharpCodegen extends DefaultCodegen implements Co
|
||||
|
||||
if (StringUtils.isEmpty(System.getenv("CSHARP_POST_PROCESS_FILE"))) {
|
||||
LOGGER.info("Environment variable CSHARP_POST_PROCESS_FILE not defined so the C# code may not be properly formatted by uncrustify (0.66 or later) or other code formatter. To define it, try `export CSHARP_POST_PROCESS_FILE=\"/usr/local/bin/uncrustify --no-backup\" && export UNCRUSTIFY_CONFIG=/path/to/uncrustify-rules.cfg` (Linux/Mac). Note: replace /path/to with the location of uncrustify-rules.cfg");
|
||||
LOGGER.info("NOTE: To enable file post-processing, 'enablePostProcessFile' must be set to `true` (--enable-post-process-file for CLI).");
|
||||
}
|
||||
|
||||
// {{packageVersion}}
|
||||
@@ -766,20 +767,19 @@ public abstract class AbstractCSharpCodegen extends DefaultCodegen implements Co
|
||||
String type;
|
||||
|
||||
if (openAPIType == null) {
|
||||
openAPIType = ""; // set swagger type to empty string if null
|
||||
LOGGER.error("OpenAPI Type for {} is null. Default to UNKNOWN_OPENAPI_TYPE instead.", p.getName());
|
||||
openAPIType = "UNKNOWN_OPENAPI_TYPE";
|
||||
}
|
||||
|
||||
// NOTE: typeMapping here supports things like string/String, long/Long, datetime/DateTime as lowercase keys.
|
||||
// Should we require explicit casing here (values are not insensitive).
|
||||
// TODO avoid using toLowerCase as typeMapping should be case-sensitive
|
||||
if (typeMapping.containsKey(openAPIType.toLowerCase(Locale.ROOT))) {
|
||||
type = typeMapping.get(openAPIType.toLowerCase(Locale.ROOT));
|
||||
if (typeMapping.containsKey(openAPIType)) {
|
||||
type = typeMapping.get(openAPIType);
|
||||
if (languageSpecificPrimitives.contains(type)) {
|
||||
return type;
|
||||
}
|
||||
} else {
|
||||
type = openAPIType;
|
||||
}
|
||||
|
||||
return toModelName(type);
|
||||
}
|
||||
|
||||
|
||||
@@ -19,6 +19,8 @@ package org.openapitools.codegen.languages;
|
||||
|
||||
import io.swagger.v3.oas.models.media.Schema;
|
||||
|
||||
import org.apache.commons.io.FilenameUtils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import com.samskivert.mustache.Mustache;
|
||||
import org.openapitools.codegen.CodegenConfig;
|
||||
@@ -28,6 +30,7 @@ import org.openapitools.codegen.mustache.IndentedLambda;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.Arrays;
|
||||
import java.util.Map;
|
||||
|
||||
@@ -226,8 +229,8 @@ abstract public class AbstractCppCodegen extends DefaultCodegen implements Codeg
|
||||
nameInCamelCase = sanitizeName(nameInCamelCase);
|
||||
}
|
||||
if (isReservedWord(nameInCamelCase) || nameInCamelCase.matches("^\\d.*")) {
|
||||
nameInCamelCase = escapeReservedWord(nameInCamelCase);
|
||||
}
|
||||
nameInCamelCase = escapeReservedWord(nameInCamelCase);
|
||||
}
|
||||
property.nameInCamelCase = nameInCamelCase;
|
||||
return property;
|
||||
}
|
||||
@@ -249,6 +252,12 @@ abstract public class AbstractCppCodegen extends DefaultCodegen implements Codeg
|
||||
|
||||
public void processOpts() {
|
||||
super.processOpts();
|
||||
|
||||
if (StringUtils.isEmpty(System.getenv("CPP_POST_PROCESS_FILE"))) {
|
||||
LOGGER.info("Environment variable CPP_POST_PROCESS_FILE not defined so the C++ code may not be properly formatted. To define it, try 'export CPP_POST_PROCESS_FILE=\"/usr/local/bin/clang-format -i\"' (Linux/Mac)");
|
||||
LOGGER.info("NOTE: To enable file post-processing, 'enablePostProcessFile' must be set to `true` (--enable-post-process-file for CLI).");
|
||||
}
|
||||
|
||||
addMustacheLambdas(additionalProperties);
|
||||
}
|
||||
|
||||
@@ -265,4 +274,31 @@ abstract public class AbstractCppCodegen extends DefaultCodegen implements Codeg
|
||||
objs.put("lambda", lambdas);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void postProcessFile(File file, String fileType) {
|
||||
if (file == null) {
|
||||
return;
|
||||
}
|
||||
String cppPostProcessFile = System.getenv("CPP_POST_PROCESS_FILE");
|
||||
if (StringUtils.isEmpty(cppPostProcessFile)) {
|
||||
return; // skip if CPP_POST_PROCESS_FILE env variable is not defined
|
||||
}
|
||||
// only process files with cpp extension
|
||||
if ("cpp".equals(FilenameUtils.getExtension(file.toString())) || "h".equals(FilenameUtils.getExtension(file.toString()))) {
|
||||
String command = cppPostProcessFile + " " + file.toString();
|
||||
try {
|
||||
Process p = Runtime.getRuntime().exec(command);
|
||||
p.waitFor();
|
||||
int exitValue = p.exitValue();
|
||||
if (exitValue != 0) {
|
||||
LOGGER.error("Error running the command ({}). Exit value: {}", command, exitValue);
|
||||
} else {
|
||||
LOGGER.info("Successfully executed: " + command);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
LOGGER.error("Error running the command ({}). Exception: {}", command, e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -121,6 +121,7 @@ public abstract class AbstractGoCodegen extends DefaultCodegen implements Codege
|
||||
|
||||
if (StringUtils.isEmpty(System.getenv("GO_POST_PROCESS_FILE"))) {
|
||||
LOGGER.info("Environment variable GO_POST_PROCESS_FILE not defined so Go code may not be properly formatted. To define it, try `export GO_POST_PROCESS_FILE=\"/usr/local/bin/gofmt -w\"` (Linux/Mac)");
|
||||
LOGGER.info("NOTE: To enable file post-processing, 'enablePostProcessFile' must be set to `true` (--enable-post-process-file for CLI).");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -215,6 +215,7 @@ public abstract class AbstractJavaCodegen extends DefaultCodegen implements Code
|
||||
|
||||
if (StringUtils.isEmpty(System.getenv("JAVA_POST_PROCESS_FILE"))) {
|
||||
LOGGER.info("Environment variable JAVA_POST_PROCESS_FILE not defined so the Java code may not be properly formatted. To define it, try 'export JAVA_POST_PROCESS_FILE=\"/usr/local/bin/clang-format -i\"' (Linux/Mac)");
|
||||
LOGGER.info("NOTE: To enable file post-processing, 'enablePostProcessFile' must be set to `true` (--enable-post-process-file for CLI).");
|
||||
}
|
||||
|
||||
if (additionalProperties.containsKey(SUPPORT_JAVA6)) {
|
||||
|
||||
@@ -45,6 +45,7 @@ public abstract class AbstractKotlinCodegen extends DefaultCodegen implements Co
|
||||
|
||||
protected String apiDocPath = "docs/";
|
||||
protected String modelDocPath = "docs/";
|
||||
protected boolean parcelizeModels = false;
|
||||
|
||||
protected CodegenConstants.ENUM_PROPERTY_NAMING_TYPE enumPropertyNaming = CodegenConstants.ENUM_PROPERTY_NAMING_TYPE.camelCase;
|
||||
|
||||
@@ -199,6 +200,7 @@ public abstract class AbstractKotlinCodegen extends DefaultCodegen implements Co
|
||||
|
||||
CliOption enumPropertyNamingOpt = new CliOption(CodegenConstants.ENUM_PROPERTY_NAMING, CodegenConstants.ENUM_PROPERTY_NAMING_DESC);
|
||||
cliOptions.add(enumPropertyNamingOpt.defaultValue(enumPropertyNaming.name()));
|
||||
cliOptions.add(new CliOption(CodegenConstants.PARCELIZE_MODELS, CodegenConstants.PARCELIZE_MODELS_DESC));
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -356,6 +358,20 @@ public abstract class AbstractKotlinCodegen extends DefaultCodegen implements Co
|
||||
LOGGER.warn(CodegenConstants.INVOKER_PACKAGE + " with " + this.getName() + " generator is ignored. Use " + CodegenConstants.PACKAGE_NAME + ".");
|
||||
}
|
||||
|
||||
if (additionalProperties.containsKey(CodegenConstants.PARCELIZE_MODELS)) {
|
||||
this.setParcelizeModels(Boolean.valueOf((String)additionalProperties.get(CodegenConstants.PARCELIZE_MODELS)));
|
||||
LOGGER.info(CodegenConstants.PARCELIZE_MODELS + " depends on the android framework and " +
|
||||
"experimental parcelize feature. Make sure your build applies the android plugin:\n" +
|
||||
"apply plugin: 'com.android.library' OR apply plugin: 'com.android.application'.\n" +
|
||||
"and enables the experimental features:\n" +
|
||||
"androidExtensions {\n" +
|
||||
" experimental = true\n" +
|
||||
"}"
|
||||
);
|
||||
} else {
|
||||
additionalProperties.put(CodegenConstants.PARCELIZE_MODELS, parcelizeModels);
|
||||
}
|
||||
|
||||
additionalProperties.put(CodegenConstants.API_PACKAGE, apiPackage());
|
||||
additionalProperties.put(CodegenConstants.MODEL_PACKAGE, modelPackage());
|
||||
|
||||
@@ -383,6 +399,14 @@ public abstract class AbstractKotlinCodegen extends DefaultCodegen implements Co
|
||||
this.sourceFolder = sourceFolder;
|
||||
}
|
||||
|
||||
public Boolean getParcelizeModels() {
|
||||
return parcelizeModels;
|
||||
}
|
||||
|
||||
public void setParcelizeModels(Boolean parcelizeModels) {
|
||||
this.parcelizeModels = parcelizeModels;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the sanitized variable name for enum
|
||||
*
|
||||
|
||||
@@ -18,6 +18,7 @@ package org.openapitools.codegen.languages;
|
||||
|
||||
import io.swagger.v3.oas.models.media.ArraySchema;
|
||||
import io.swagger.v3.oas.models.media.Schema;
|
||||
import org.apache.commons.io.FilenameUtils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.openapitools.codegen.CliOption;
|
||||
import org.openapitools.codegen.CodegenConfig;
|
||||
@@ -40,12 +41,6 @@ import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.regex.Matcher;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
|
||||
public abstract class AbstractPhpCodegen extends DefaultCodegen implements CodegenConfig {
|
||||
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(AbstractPhpCodegen.class);
|
||||
@@ -161,6 +156,11 @@ public abstract class AbstractPhpCodegen extends DefaultCodegen implements Codeg
|
||||
public void processOpts() {
|
||||
super.processOpts();
|
||||
|
||||
if (StringUtils.isEmpty(System.getenv("PHP_POST_PROCESS_FILE"))) {
|
||||
LOGGER.info("Environment variable PHP_POST_PROCESS_FILE not defined so the PHP code may not be properly formatted. To define it, try 'export PHP_POST_PROCESS_FILE=\"/usr/local/bin/prettier --write\"' (Linux/Mac)");
|
||||
LOGGER.info("NOTE: To enable file post-processing, 'enablePostProcessFile' must be set to `true` (--enable-post-process-file for CLI).");
|
||||
}
|
||||
|
||||
if (additionalProperties.containsKey(PACKAGE_NAME)) {
|
||||
this.setPackageName((String) additionalProperties.get(PACKAGE_NAME));
|
||||
} else {
|
||||
@@ -773,4 +773,31 @@ public abstract class AbstractPhpCodegen extends DefaultCodegen implements Codeg
|
||||
final int lastBackslashIndex = phpClassName.lastIndexOf('\\');
|
||||
return phpClassName.substring(lastBackslashIndex + 1);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void postProcessFile(File file, String fileType) {
|
||||
if (file == null) {
|
||||
return;
|
||||
}
|
||||
String phpPostProcessFile = System.getenv("PHP_POST_PROCESS_FILE");
|
||||
if (StringUtils.isEmpty(phpPostProcessFile)) {
|
||||
return; // skip if PHP_POST_PROCESS_FILE env variable is not defined
|
||||
}
|
||||
// only process files with php extension
|
||||
if ("php".equals(FilenameUtils.getExtension(file.toString()))) {
|
||||
String command = phpPostProcessFile + " " + file.toString();
|
||||
try {
|
||||
Process p = Runtime.getRuntime().exec(command);
|
||||
p.waitFor();
|
||||
int exitValue = p.exitValue();
|
||||
if (exitValue != 0) {
|
||||
LOGGER.error("Error running the command ({}). Exit value: {}", command, exitValue);
|
||||
} else {
|
||||
LOGGER.info("Successfully executed: " + command);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
LOGGER.error("Error running the command ({}). Exception: {}", command, e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -116,6 +116,7 @@ public abstract class AbstractScalaCodegen extends DefaultCodegen {
|
||||
|
||||
if (StringUtils.isEmpty(System.getenv("SCALA_POST_PROCESS_FILE"))) {
|
||||
LOGGER.info("Environment variable SCALA_POST_PROCESS_FILE not defined so the Scala code may not be properly formatted. To define it, try 'export SCALA_POST_PROCESS_FILE=/usr/local/bin/scalafmt' (Linux/Mac)");
|
||||
LOGGER.info("NOTE: To enable file post-processing, 'enablePostProcessFile' must be set to `true` (--enable-post-process-file for CLI).");
|
||||
}
|
||||
|
||||
if (additionalProperties.containsKey(CodegenConstants.SOURCE_FOLDER)) {
|
||||
|
||||
@@ -0,0 +1,850 @@
|
||||
/*
|
||||
* Copyright 2018 OpenAPI-Generator Contributors (https://openapi-generator.tech)
|
||||
* Copyright 2018 SmartBear Software
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.openapitools.codegen.languages;
|
||||
|
||||
import static org.apache.commons.lang3.StringUtils.isEmpty;
|
||||
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import com.samskivert.mustache.Mustache;
|
||||
|
||||
import io.swagger.v3.oas.models.media.Schema;
|
||||
|
||||
import org.openapitools.codegen.CliOption;
|
||||
import org.openapitools.codegen.CodegenConstants;
|
||||
import org.openapitools.codegen.CodegenModel;
|
||||
import org.openapitools.codegen.CodegenOperation;
|
||||
import org.openapitools.codegen.CodegenParameter;
|
||||
import org.openapitools.codegen.CodegenProperty;
|
||||
import org.openapitools.codegen.CodegenType;
|
||||
import org.openapitools.codegen.SupportingFile;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
|
||||
public class CSharpRefactorClientCodegen extends AbstractCSharpCodegen {
|
||||
@SuppressWarnings({"hiding"})
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(CSharpClientCodegen.class);
|
||||
private static final String NET45 = "v4.5";
|
||||
private static final String NET40 = "v4.0";
|
||||
private static final String NET35 = "v3.5";
|
||||
// TODO: v5.0 is PCL, not netstandard version 1.3, and not a specific .NET Framework. This needs to be updated,
|
||||
// especially because it will conflict with .NET Framework 5.0 when released, and PCL 5 refers to Framework 4.0.
|
||||
// We should support either NETSTANDARD, PCL, or Both… but the concepts shouldn't be mixed.
|
||||
private static final String NETSTANDARD = "v5.0";
|
||||
private static final String UWP = "uwp";
|
||||
|
||||
// Defines the sdk option for targeted frameworks, which differs from targetFramework and targetFrameworkNuget
|
||||
private static final String MCS_NET_VERSION_KEY = "x-mcs-sdk";
|
||||
|
||||
protected String packageGuid = "{" + java.util.UUID.randomUUID().toString().toUpperCase(Locale.ROOT) + "}";
|
||||
protected String clientPackage = "Org.OpenAPITools.Client";
|
||||
protected String localVariablePrefix = "";
|
||||
protected String apiDocPath = "docs/";
|
||||
protected String modelDocPath = "docs/";
|
||||
|
||||
// Defines TargetFrameworkVersion in csproj files
|
||||
protected String targetFramework = NET45;
|
||||
|
||||
// Defines nuget identifiers for target framework
|
||||
protected String targetFrameworkNuget = "net45";
|
||||
protected boolean supportsAsync = Boolean.TRUE;
|
||||
protected boolean supportsUWP = Boolean.FALSE;
|
||||
protected boolean netStandard = Boolean.FALSE;
|
||||
protected boolean generatePropertyChanged = Boolean.FALSE;
|
||||
|
||||
protected boolean validatable = Boolean.TRUE;
|
||||
protected Map<Character, String> regexModifiers;
|
||||
protected final Map<String, String> frameworks;
|
||||
|
||||
// By default, generated code is considered public
|
||||
protected boolean nonPublicApi = Boolean.FALSE;
|
||||
|
||||
public CSharpRefactorClientCodegen() {
|
||||
super();
|
||||
supportsInheritance = true;
|
||||
modelTemplateFiles.put("model.mustache", ".cs");
|
||||
apiTemplateFiles.put("api.mustache", ".cs");
|
||||
|
||||
modelDocTemplateFiles.put("model_doc.mustache", ".md");
|
||||
apiDocTemplateFiles.put("api_doc.mustache", ".md");
|
||||
|
||||
embeddedTemplateDir = templateDir = "csharp-refactor";
|
||||
|
||||
hideGenerationTimestamp = Boolean.TRUE;
|
||||
|
||||
cliOptions.clear();
|
||||
|
||||
// CLI options
|
||||
addOption(CodegenConstants.PACKAGE_NAME,
|
||||
"C# package name (convention: Title.Case).",
|
||||
this.packageName);
|
||||
|
||||
addOption(CodegenConstants.PACKAGE_VERSION,
|
||||
"C# package version.",
|
||||
this.packageVersion);
|
||||
|
||||
addOption(CodegenConstants.SOURCE_FOLDER,
|
||||
CodegenConstants.SOURCE_FOLDER_DESC,
|
||||
sourceFolder);
|
||||
|
||||
addOption(CodegenConstants.OPTIONAL_PROJECT_GUID,
|
||||
CodegenConstants.OPTIONAL_PROJECT_GUID_DESC,
|
||||
null);
|
||||
|
||||
addOption(CodegenConstants.INTERFACE_PREFIX,
|
||||
CodegenConstants.INTERFACE_PREFIX_DESC,
|
||||
interfacePrefix);
|
||||
|
||||
CliOption framework = new CliOption(
|
||||
CodegenConstants.DOTNET_FRAMEWORK,
|
||||
CodegenConstants.DOTNET_FRAMEWORK_DESC
|
||||
);
|
||||
frameworks = new ImmutableMap.Builder<String, String>()
|
||||
.put(NET35, ".NET Framework 3.5 compatible")
|
||||
.put(NET40, ".NET Framework 4.0 compatible")
|
||||
.put(NET45, ".NET Framework 4.5+ compatible")
|
||||
.put(NETSTANDARD, ".NET Standard 1.3 compatible")
|
||||
.put(UWP, "Universal Windows Platform (IMPORTANT: this will be decommissioned and replaced by v5.0)")
|
||||
.build();
|
||||
framework.defaultValue(this.targetFramework);
|
||||
framework.setEnum(frameworks);
|
||||
cliOptions.add(framework);
|
||||
|
||||
CliOption modelPropertyNaming = new CliOption(CodegenConstants.MODEL_PROPERTY_NAMING, CodegenConstants.MODEL_PROPERTY_NAMING_DESC);
|
||||
cliOptions.add(modelPropertyNaming.defaultValue("PascalCase"));
|
||||
|
||||
// CLI Switches
|
||||
addSwitch(CodegenConstants.HIDE_GENERATION_TIMESTAMP,
|
||||
CodegenConstants.HIDE_GENERATION_TIMESTAMP_DESC,
|
||||
this.hideGenerationTimestamp);
|
||||
|
||||
addSwitch(CodegenConstants.SORT_PARAMS_BY_REQUIRED_FLAG,
|
||||
CodegenConstants.SORT_PARAMS_BY_REQUIRED_FLAG_DESC,
|
||||
this.sortParamsByRequiredFlag);
|
||||
|
||||
addSwitch(CodegenConstants.USE_DATETIME_OFFSET,
|
||||
CodegenConstants.USE_DATETIME_OFFSET_DESC,
|
||||
this.useDateTimeOffsetFlag);
|
||||
|
||||
addSwitch(CodegenConstants.USE_COLLECTION,
|
||||
CodegenConstants.USE_COLLECTION_DESC,
|
||||
this.useCollection);
|
||||
|
||||
addSwitch(CodegenConstants.RETURN_ICOLLECTION,
|
||||
CodegenConstants.RETURN_ICOLLECTION_DESC,
|
||||
this.returnICollection);
|
||||
|
||||
addSwitch(CodegenConstants.OPTIONAL_METHOD_ARGUMENT,
|
||||
"C# Optional method argument, e.g. void square(int x=10) (.net 4.0+ only).",
|
||||
this.optionalMethodArgumentFlag);
|
||||
|
||||
addSwitch(CodegenConstants.OPTIONAL_ASSEMBLY_INFO,
|
||||
CodegenConstants.OPTIONAL_ASSEMBLY_INFO_DESC,
|
||||
this.optionalAssemblyInfoFlag);
|
||||
|
||||
addSwitch(CodegenConstants.OPTIONAL_PROJECT_FILE,
|
||||
CodegenConstants.OPTIONAL_PROJECT_FILE_DESC,
|
||||
this.optionalProjectFileFlag);
|
||||
|
||||
addSwitch(CodegenConstants.OPTIONAL_EMIT_DEFAULT_VALUES,
|
||||
CodegenConstants.OPTIONAL_EMIT_DEFAULT_VALUES_DESC,
|
||||
this.optionalEmitDefaultValue);
|
||||
|
||||
addSwitch(CodegenConstants.GENERATE_PROPERTY_CHANGED,
|
||||
CodegenConstants.PACKAGE_DESCRIPTION_DESC,
|
||||
this.generatePropertyChanged);
|
||||
|
||||
// NOTE: This will reduce visibility of all public members in templates. Users can use InternalsVisibleTo
|
||||
// https://msdn.microsoft.com/en-us/library/system.runtime.compilerservices.internalsvisibletoattribute(v=vs.110).aspx
|
||||
// to expose to shared code if the generated code is not embedded into another project. Otherwise, users of codegen
|
||||
// should rely on default public visibility.
|
||||
addSwitch(CodegenConstants.NON_PUBLIC_API,
|
||||
CodegenConstants.NON_PUBLIC_API_DESC,
|
||||
this.nonPublicApi);
|
||||
|
||||
addSwitch(CodegenConstants.ALLOW_UNICODE_IDENTIFIERS,
|
||||
CodegenConstants.ALLOW_UNICODE_IDENTIFIERS_DESC,
|
||||
this.allowUnicodeIdentifiers);
|
||||
|
||||
addSwitch(CodegenConstants.NETCORE_PROJECT_FILE,
|
||||
CodegenConstants.NETCORE_PROJECT_FILE_DESC,
|
||||
this.netCoreProjectFileFlag);
|
||||
|
||||
addSwitch(CodegenConstants.VALIDATABLE,
|
||||
CodegenConstants.VALIDATABLE_DESC,
|
||||
this.validatable);
|
||||
|
||||
regexModifiers = new HashMap<Character, String>();
|
||||
regexModifiers.put('i', "IgnoreCase");
|
||||
regexModifiers.put('m', "Multiline");
|
||||
regexModifiers.put('s', "Singleline");
|
||||
regexModifiers.put('x', "IgnorePatternWhitespace");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void processOpts() {
|
||||
super.processOpts();
|
||||
|
||||
/*
|
||||
* 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
|
||||
* templating engine to behave unexpectedly.
|
||||
*
|
||||
* Use the pattern:
|
||||
* if (additionalProperties.containsKey(prop)) convertPropertyToBooleanAndWriteBack(prop);
|
||||
*/
|
||||
|
||||
if (additionalProperties.containsKey(CodegenConstants.MODEL_PROPERTY_NAMING)) {
|
||||
setModelPropertyNaming((String) additionalProperties.get(CodegenConstants.MODEL_PROPERTY_NAMING));
|
||||
}
|
||||
|
||||
|
||||
if (isEmpty(apiPackage)) {
|
||||
setApiPackage("Api");
|
||||
}
|
||||
if (isEmpty(modelPackage)) {
|
||||
setModelPackage("Model");
|
||||
}
|
||||
clientPackage = "Client";
|
||||
|
||||
Boolean excludeTests = false;
|
||||
if (additionalProperties.containsKey(CodegenConstants.EXCLUDE_TESTS)) {
|
||||
excludeTests = convertPropertyToBooleanAndWriteBack(CodegenConstants.EXCLUDE_TESTS);
|
||||
}
|
||||
|
||||
if (additionalProperties.containsKey(CodegenConstants.VALIDATABLE)) {
|
||||
setValidatable(convertPropertyToBooleanAndWriteBack(CodegenConstants.VALIDATABLE));
|
||||
} else {
|
||||
additionalProperties.put(CodegenConstants.VALIDATABLE, validatable);
|
||||
}
|
||||
|
||||
if (additionalProperties.containsKey(CodegenConstants.DOTNET_FRAMEWORK)) {
|
||||
setTargetFramework((String) additionalProperties.get(CodegenConstants.DOTNET_FRAMEWORK));
|
||||
} else {
|
||||
// Ensure default is set.
|
||||
setTargetFramework(NET45);
|
||||
additionalProperties.put(CodegenConstants.DOTNET_FRAMEWORK, this.targetFramework);
|
||||
}
|
||||
|
||||
if (NET35.equals(this.targetFramework)) {
|
||||
// This is correct, mono will require you build .NET 3.5 sources using 4.0 SDK
|
||||
additionalProperties.put(MCS_NET_VERSION_KEY, "4");
|
||||
additionalProperties.put("net35", true);
|
||||
if (additionalProperties.containsKey(CodegenConstants.SUPPORTS_ASYNC)) {
|
||||
LOGGER.warn(".NET 3.5 generator does not support async.");
|
||||
additionalProperties.remove(CodegenConstants.SUPPORTS_ASYNC);
|
||||
}
|
||||
|
||||
setTargetFrameworkNuget("net35");
|
||||
setValidatable(Boolean.FALSE);
|
||||
setSupportsAsync(Boolean.FALSE);
|
||||
} else if (NETSTANDARD.equals(this.targetFramework)) {
|
||||
// TODO: NETSTANDARD here is misrepresenting a PCL v5.0 which supports .NET Framework 4.6+, .NET Core 1.0, and Windows Universal 10.0
|
||||
additionalProperties.put(MCS_NET_VERSION_KEY, "4.6-api");
|
||||
if (additionalProperties.containsKey("supportsUWP")) {
|
||||
LOGGER.warn(".NET " + NETSTANDARD + " generator does not support UWP.");
|
||||
additionalProperties.remove("supportsUWP");
|
||||
}
|
||||
|
||||
// TODO: NETSTANDARD=v5.0 and targetFrameworkNuget=netstandard1.3. These need to sync.
|
||||
setTargetFrameworkNuget("netstandard1.3");
|
||||
setSupportsAsync(Boolean.TRUE);
|
||||
setSupportsUWP(Boolean.FALSE);
|
||||
setNetStandard(Boolean.TRUE);
|
||||
|
||||
//Tests not yet implemented for .NET Standard codegen
|
||||
//Todo implement it
|
||||
excludeTests = true;
|
||||
} else if (UWP.equals(this.targetFramework)) {
|
||||
setTargetFrameworkNuget("uwp");
|
||||
setSupportsAsync(Boolean.TRUE);
|
||||
setSupportsUWP(Boolean.TRUE);
|
||||
} else if (NET40.equals(this.targetFramework)) {
|
||||
additionalProperties.put(MCS_NET_VERSION_KEY, "4");
|
||||
additionalProperties.put("isNet40", true);
|
||||
|
||||
if (additionalProperties.containsKey(CodegenConstants.SUPPORTS_ASYNC)) {
|
||||
LOGGER.warn(".NET " + NET40 + " generator does not support async.");
|
||||
additionalProperties.remove(CodegenConstants.SUPPORTS_ASYNC);
|
||||
}
|
||||
|
||||
setTargetFrameworkNuget("net40");
|
||||
setSupportsAsync(Boolean.FALSE);
|
||||
} else {
|
||||
additionalProperties.put(MCS_NET_VERSION_KEY, "4.5.2-api");
|
||||
setTargetFrameworkNuget("net45");
|
||||
setSupportsAsync(Boolean.TRUE);
|
||||
}
|
||||
|
||||
if (additionalProperties.containsKey(CodegenConstants.GENERATE_PROPERTY_CHANGED)) {
|
||||
if (NET35.equals(targetFramework)) {
|
||||
LOGGER.warn(CodegenConstants.GENERATE_PROPERTY_CHANGED + " is only supported by generated code for .NET 4+.");
|
||||
additionalProperties.remove(CodegenConstants.GENERATE_PROPERTY_CHANGED);
|
||||
} else if (NETSTANDARD.equals(targetFramework)) {
|
||||
LOGGER.warn(CodegenConstants.GENERATE_PROPERTY_CHANGED + " is not supported in .NET Standard generated code.");
|
||||
additionalProperties.remove(CodegenConstants.GENERATE_PROPERTY_CHANGED);
|
||||
} else if (Boolean.TRUE.equals(netCoreProjectFileFlag)) {
|
||||
LOGGER.warn(CodegenConstants.GENERATE_PROPERTY_CHANGED + " is not supported in .NET Core csproj project format.");
|
||||
additionalProperties.remove(CodegenConstants.GENERATE_PROPERTY_CHANGED);
|
||||
} else {
|
||||
setGeneratePropertyChanged(convertPropertyToBooleanAndWriteBack(CodegenConstants.GENERATE_PROPERTY_CHANGED));
|
||||
}
|
||||
}
|
||||
|
||||
additionalProperties.put(CodegenConstants.API_PACKAGE, apiPackage);
|
||||
additionalProperties.put(CodegenConstants.MODEL_PACKAGE, modelPackage);
|
||||
additionalProperties.put("clientPackage", clientPackage);
|
||||
|
||||
additionalProperties.put(CodegenConstants.EXCLUDE_TESTS, excludeTests);
|
||||
additionalProperties.put(CodegenConstants.VALIDATABLE, this.validatable);
|
||||
additionalProperties.put(CodegenConstants.SUPPORTS_ASYNC, this.supportsAsync);
|
||||
additionalProperties.put("supportsUWP", this.supportsUWP);
|
||||
additionalProperties.put("netStandard", this.netStandard);
|
||||
additionalProperties.put("targetFrameworkNuget", this.targetFrameworkNuget);
|
||||
|
||||
// TODO: either remove this and update templates to match the "optionalEmitDefaultValues" property, or rename that property.
|
||||
additionalProperties.put("emitDefaultValue", optionalEmitDefaultValue);
|
||||
|
||||
if (additionalProperties.containsKey(CodegenConstants.OPTIONAL_PROJECT_FILE)) {
|
||||
setOptionalProjectFileFlag(convertPropertyToBooleanAndWriteBack(CodegenConstants.OPTIONAL_PROJECT_FILE));
|
||||
} else {
|
||||
additionalProperties.put(CodegenConstants.OPTIONAL_PROJECT_FILE, optionalProjectFileFlag);
|
||||
}
|
||||
|
||||
if (additionalProperties.containsKey(CodegenConstants.OPTIONAL_PROJECT_GUID)) {
|
||||
setPackageGuid((String) additionalProperties.get(CodegenConstants.OPTIONAL_PROJECT_GUID));
|
||||
} else {
|
||||
additionalProperties.put(CodegenConstants.OPTIONAL_PROJECT_GUID, packageGuid);
|
||||
}
|
||||
|
||||
if (additionalProperties.containsKey(CodegenConstants.OPTIONAL_METHOD_ARGUMENT)) {
|
||||
setOptionalMethodArgumentFlag(convertPropertyToBooleanAndWriteBack(CodegenConstants.OPTIONAL_METHOD_ARGUMENT));
|
||||
} else {
|
||||
additionalProperties.put(CodegenConstants.OPTIONAL_METHOD_ARGUMENT, optionalMethodArgumentFlag);
|
||||
}
|
||||
|
||||
if (additionalProperties.containsKey(CodegenConstants.OPTIONAL_ASSEMBLY_INFO)) {
|
||||
setOptionalAssemblyInfoFlag(convertPropertyToBooleanAndWriteBack(CodegenConstants.OPTIONAL_ASSEMBLY_INFO));
|
||||
} else {
|
||||
additionalProperties.put(CodegenConstants.OPTIONAL_ASSEMBLY_INFO, optionalAssemblyInfoFlag);
|
||||
}
|
||||
|
||||
if (additionalProperties.containsKey(CodegenConstants.NON_PUBLIC_API)) {
|
||||
setNonPublicApi(convertPropertyToBooleanAndWriteBack(CodegenConstants.NON_PUBLIC_API));
|
||||
} else {
|
||||
additionalProperties.put(CodegenConstants.NON_PUBLIC_API, isNonPublicApi());
|
||||
}
|
||||
|
||||
final String testPackageName = testPackageName();
|
||||
String packageFolder = sourceFolder + File.separator + packageName;
|
||||
String clientPackageDir = packageFolder + File.separator + clientPackage;
|
||||
String testPackageFolder = testFolder + File.separator + testPackageName;
|
||||
|
||||
additionalProperties.put("testPackageName", testPackageName);
|
||||
|
||||
//Compute the relative path to the bin directory where the external assemblies live
|
||||
//This is necessary to properly generate the project file
|
||||
int packageDepth = packageFolder.length() - packageFolder.replace(java.io.File.separator, "").length();
|
||||
String binRelativePath = "..\\";
|
||||
for (int i = 0; i < packageDepth; i = i + 1)
|
||||
binRelativePath += "..\\";
|
||||
binRelativePath += "vendor";
|
||||
additionalProperties.put("binRelativePath", binRelativePath);
|
||||
|
||||
supportingFiles.add(new SupportingFile("IApiAccessor.mustache",
|
||||
clientPackageDir, "IApiAccessor.cs"));
|
||||
supportingFiles.add(new SupportingFile("Configuration.mustache",
|
||||
clientPackageDir, "Configuration.cs"));
|
||||
supportingFiles.add(new SupportingFile("ApiClient.mustache",
|
||||
clientPackageDir, "ApiClient.cs"));
|
||||
supportingFiles.add(new SupportingFile("ApiException.mustache",
|
||||
clientPackageDir, "ApiException.cs"));
|
||||
supportingFiles.add(new SupportingFile("ApiResponse.mustache",
|
||||
clientPackageDir, "ApiResponse.cs"));
|
||||
supportingFiles.add(new SupportingFile("ExceptionFactory.mustache",
|
||||
clientPackageDir, "ExceptionFactory.cs"));
|
||||
supportingFiles.add(new SupportingFile("OpenAPIDateConverter.mustache",
|
||||
clientPackageDir, "OpenAPIDateConverter.cs"));
|
||||
|
||||
supportingFiles.add(new SupportingFile("ClientUtils.mustache",
|
||||
clientPackageDir, "ClientUtils.cs"));
|
||||
supportingFiles.add(new SupportingFile("HttpMethod.mustache",
|
||||
clientPackageDir, "HttpMethod.cs"));
|
||||
supportingFiles.add(new SupportingFile("IAsynchronousClient.mustache",
|
||||
clientPackageDir, "IAsynchronousClient.cs"));
|
||||
supportingFiles.add(new SupportingFile("ISynchronousClient.mustache",
|
||||
clientPackageDir, "ISynchronousClient.cs"));
|
||||
supportingFiles.add(new SupportingFile("RequestOptions.mustache",
|
||||
clientPackageDir, "RequestOptions.cs"));
|
||||
supportingFiles.add(new SupportingFile("Multimap.mustache",
|
||||
clientPackageDir, "Multimap.cs"));
|
||||
|
||||
if (Boolean.FALSE.equals(this.netStandard) && Boolean.FALSE.equals(this.netCoreProjectFileFlag)) {
|
||||
supportingFiles.add(new SupportingFile("compile.mustache", "", "build.bat"));
|
||||
supportingFiles.add(new SupportingFile("compile-mono.sh.mustache", "", "build.sh"));
|
||||
|
||||
// copy package.config to nuget's standard location for project-level installs
|
||||
supportingFiles.add(new SupportingFile("packages.config.mustache", packageFolder + File.separator, "packages.config"));
|
||||
// .travis.yml for travis-ci.org CI
|
||||
supportingFiles.add(new SupportingFile("travis.mustache", "", ".travis.yml"));
|
||||
} else if (Boolean.FALSE.equals(this.netCoreProjectFileFlag)) {
|
||||
supportingFiles.add(new SupportingFile("project.json.mustache", packageFolder + File.separator, "project.json"));
|
||||
}
|
||||
|
||||
supportingFiles.add(new SupportingFile("IReadableConfiguration.mustache",
|
||||
clientPackageDir, "IReadableConfiguration.cs"));
|
||||
supportingFiles.add(new SupportingFile("GlobalConfiguration.mustache",
|
||||
clientPackageDir, "GlobalConfiguration.cs"));
|
||||
|
||||
// Only write out test related files if excludeTests is unset or explicitly set to false (see start of this method)
|
||||
if (Boolean.FALSE.equals(excludeTests)) {
|
||||
// shell script to run the nunit test
|
||||
supportingFiles.add(new SupportingFile("mono_nunit_test.mustache", "", "mono_nunit_test.sh"));
|
||||
|
||||
modelTestTemplateFiles.put("model_test.mustache", ".cs");
|
||||
apiTestTemplateFiles.put("api_test.mustache", ".cs");
|
||||
|
||||
if (Boolean.FALSE.equals(this.netCoreProjectFileFlag)) {
|
||||
supportingFiles.add(new SupportingFile("packages_test.config.mustache", testPackageFolder + File.separator, "packages.config"));
|
||||
}
|
||||
|
||||
if (NET40.equals(this.targetFramework)) {
|
||||
// Include minimal tests for modifications made to JsonSubTypes, since code is quite different for .net 4.0 from original implementation
|
||||
supportingFiles.add(new SupportingFile("JsonSubTypesTests.mustache",
|
||||
testPackageFolder + File.separator + "Client",
|
||||
"JsonSubTypesTests.cs"));
|
||||
}
|
||||
}
|
||||
|
||||
if (Boolean.TRUE.equals(generatePropertyChanged)) {
|
||||
supportingFiles.add(new SupportingFile("FodyWeavers.xml", packageFolder, "FodyWeavers.xml"));
|
||||
}
|
||||
|
||||
supportingFiles.add(new SupportingFile("README.mustache", "", "README.md"));
|
||||
supportingFiles.add(new SupportingFile("git_push.sh.mustache", "", "git_push.sh"));
|
||||
supportingFiles.add(new SupportingFile("gitignore.mustache", "", ".gitignore"));
|
||||
|
||||
if (optionalAssemblyInfoFlag && Boolean.FALSE.equals(this.netCoreProjectFileFlag)) {
|
||||
supportingFiles.add(new SupportingFile("AssemblyInfo.mustache", packageFolder + File.separator + "Properties", "AssemblyInfo.cs"));
|
||||
}
|
||||
if (optionalProjectFileFlag) {
|
||||
supportingFiles.add(new SupportingFile("Solution.mustache", "", packageName + ".sln"));
|
||||
|
||||
if (Boolean.TRUE.equals(this.netCoreProjectFileFlag)) {
|
||||
supportingFiles.add(new SupportingFile("netcore_project.mustache", packageFolder, packageName + ".csproj"));
|
||||
} else {
|
||||
supportingFiles.add(new SupportingFile("Project.mustache", packageFolder, packageName + ".csproj"));
|
||||
if (Boolean.FALSE.equals(this.netStandard)) {
|
||||
supportingFiles.add(new SupportingFile("nuspec.mustache", packageFolder, packageName + ".nuspec"));
|
||||
}
|
||||
}
|
||||
|
||||
if (Boolean.FALSE.equals(excludeTests)) {
|
||||
// NOTE: This exists here rather than previous excludeTests block because the test project is considered an optional project file.
|
||||
if (Boolean.TRUE.equals(this.netCoreProjectFileFlag)) {
|
||||
supportingFiles.add(new SupportingFile("netcore_testproject.mustache", testPackageFolder, testPackageName + ".csproj"));
|
||||
} else {
|
||||
supportingFiles.add(new SupportingFile("TestProject.mustache", testPackageFolder, testPackageName + ".csproj"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
additionalProperties.put("apiDocPath", apiDocPath);
|
||||
additionalProperties.put("modelDocPath", modelDocPath);
|
||||
}
|
||||
|
||||
public void setModelPropertyNaming(String naming) {
|
||||
if ("original".equals(naming) || "camelCase".equals(naming) ||
|
||||
"PascalCase".equals(naming) || "snake_case".equals(naming)) {
|
||||
this.modelPropertyNaming = naming;
|
||||
} else {
|
||||
throw new IllegalArgumentException("Invalid model property naming '" +
|
||||
naming + "'. Must be 'original', 'camelCase', " +
|
||||
"'PascalCase' or 'snake_case'");
|
||||
}
|
||||
}
|
||||
|
||||
public String getModelPropertyNaming() {
|
||||
return this.modelPropertyNaming;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Object> postProcessOperationsWithModels(Map<String, Object> objs, List<Object> allModels) {
|
||||
super.postProcessOperationsWithModels(objs, allModels);
|
||||
if (objs != null) {
|
||||
Map<String, Object> operations = (Map<String, Object>) objs.get("operations");
|
||||
if (operations != null) {
|
||||
List<CodegenOperation> ops = (List<CodegenOperation>) operations.get("operation");
|
||||
for (CodegenOperation operation : ops) {
|
||||
if (operation.returnType != null) {
|
||||
operation.returnContainer = operation.returnType;
|
||||
if (this.returnICollection && (
|
||||
operation.returnType.startsWith("List") ||
|
||||
operation.returnType.startsWith("Collection"))) {
|
||||
// NOTE: ICollection works for both List<T> and Collection<T>
|
||||
int genericStart = operation.returnType.indexOf("<");
|
||||
if (genericStart > 0) {
|
||||
operation.returnType = "ICollection" + operation.returnType.substring(genericStart);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return objs;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CodegenType getTag() {
|
||||
return CodegenType.CLIENT;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return "csharp-refactor";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getHelp() {
|
||||
return "Generates a CSharp client library.";
|
||||
}
|
||||
|
||||
public void setOptionalAssemblyInfoFlag(boolean flag) {
|
||||
this.optionalAssemblyInfoFlag = flag;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CodegenModel fromModel(String name, Schema model, Map<String, Schema> allDefinitions) {
|
||||
CodegenModel codegenModel = super.fromModel(name, model, allDefinitions);
|
||||
if (allDefinitions != null && codegenModel != null && codegenModel.parent != null) {
|
||||
final Schema parentModel = allDefinitions.get(toModelName(codegenModel.parent));
|
||||
if (parentModel != null) {
|
||||
final CodegenModel parentCodegenModel = super.fromModel(codegenModel.parent, parentModel, allDefinitions);
|
||||
if (codegenModel.hasEnums) {
|
||||
codegenModel = this.reconcileInlineEnums(codegenModel, parentCodegenModel);
|
||||
}
|
||||
|
||||
Map<String, CodegenProperty> propertyHash = new HashMap<>(codegenModel.vars.size());
|
||||
for (final CodegenProperty property : codegenModel.vars) {
|
||||
propertyHash.put(property.name, property);
|
||||
}
|
||||
|
||||
for (final CodegenProperty property : codegenModel.readWriteVars) {
|
||||
if (property.defaultValue == null && property.baseName.equals(parentCodegenModel.discriminator)) {
|
||||
property.defaultValue = "\"" + name + "\"";
|
||||
}
|
||||
}
|
||||
|
||||
CodegenProperty last = null;
|
||||
for (final CodegenProperty property : parentCodegenModel.vars) {
|
||||
// helper list of parentVars simplifies templating
|
||||
if (!propertyHash.containsKey(property.name)) {
|
||||
final CodegenProperty parentVar = property.clone();
|
||||
parentVar.isInherited = true;
|
||||
parentVar.hasMore = true;
|
||||
last = parentVar;
|
||||
LOGGER.info("adding parent variable {}", property.name);
|
||||
codegenModel.parentVars.add(parentVar);
|
||||
}
|
||||
}
|
||||
|
||||
if (last != null) {
|
||||
last.hasMore = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Cleanup possible duplicates. Currently, readWriteVars can contain the same property twice. May or may not be isolated to C#.
|
||||
if (codegenModel != null && codegenModel.readWriteVars != null && codegenModel.readWriteVars.size() > 1) {
|
||||
int length = codegenModel.readWriteVars.size() - 1;
|
||||
for (int i = length; i > (length / 2); i--) {
|
||||
final CodegenProperty codegenProperty = codegenModel.readWriteVars.get(i);
|
||||
// If the property at current index is found earlier in the list, remove this last instance.
|
||||
if (codegenModel.readWriteVars.indexOf(codegenProperty) < i) {
|
||||
codegenModel.readWriteVars.remove(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return codegenModel;
|
||||
}
|
||||
|
||||
public void setOptionalProjectFileFlag(boolean flag) {
|
||||
this.optionalProjectFileFlag = flag;
|
||||
}
|
||||
|
||||
public void setPackageGuid(String packageGuid) {
|
||||
this.packageGuid = packageGuid;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void postProcessParameter(CodegenParameter parameter) {
|
||||
postProcessPattern(parameter.pattern, parameter.vendorExtensions);
|
||||
super.postProcessParameter(parameter);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void postProcessModelProperty(CodegenModel model, CodegenProperty property) {
|
||||
postProcessPattern(property.pattern, property.vendorExtensions);
|
||||
super.postProcessModelProperty(model, property);
|
||||
}
|
||||
|
||||
/*
|
||||
* The pattern spec follows the Perl convention and style of modifiers. .NET
|
||||
* does not support this syntax directly so we need to convert the pattern to a .NET compatible
|
||||
* format and apply modifiers in a compatible way.
|
||||
* See https://msdn.microsoft.com/en-us/library/yd1hzczs(v=vs.110).aspx for .NET options.
|
||||
*/
|
||||
public void postProcessPattern(String pattern, Map<String, Object> vendorExtensions) {
|
||||
if (pattern != null) {
|
||||
int i = pattern.lastIndexOf('/');
|
||||
|
||||
//Must follow Perl /pattern/modifiers convention
|
||||
if (pattern.charAt(0) != '/' || i < 2) {
|
||||
throw new IllegalArgumentException("Pattern must follow the Perl "
|
||||
+ "/pattern/modifiers convention. " + pattern + " is not valid.");
|
||||
}
|
||||
|
||||
String regex = pattern.substring(1, i).replace("'", "\'");
|
||||
List<String> modifiers = new ArrayList<String>();
|
||||
|
||||
// perl requires an explicit modifier to be culture specific and .NET is the reverse.
|
||||
modifiers.add("CultureInvariant");
|
||||
|
||||
for (char c : pattern.substring(i).toCharArray()) {
|
||||
if (regexModifiers.containsKey(c)) {
|
||||
String modifier = regexModifiers.get(c);
|
||||
modifiers.add(modifier);
|
||||
} else if (c == 'l') {
|
||||
modifiers.remove("CultureInvariant");
|
||||
}
|
||||
}
|
||||
|
||||
vendorExtensions.put("x-regex", regex);
|
||||
vendorExtensions.put("x-modifiers", modifiers);
|
||||
}
|
||||
}
|
||||
|
||||
public void setTargetFramework(String dotnetFramework) {
|
||||
if (!frameworks.containsKey(dotnetFramework)) {
|
||||
LOGGER.warn("Invalid .NET framework version, defaulting to " + this.targetFramework);
|
||||
} else {
|
||||
this.targetFramework = dotnetFramework;
|
||||
}
|
||||
LOGGER.info("Generating code for .NET Framework " + this.targetFramework);
|
||||
}
|
||||
|
||||
private CodegenModel reconcileInlineEnums(CodegenModel codegenModel, CodegenModel parentCodegenModel) {
|
||||
// This generator uses inline classes to define enums, which breaks when
|
||||
// dealing with models that have subTypes. To clean this up, we will analyze
|
||||
// the parent and child models, look for enums that match, and remove
|
||||
// them from the child models and leave them in the parent.
|
||||
// Because the child models extend the parents, the enums will be available via the parent.
|
||||
|
||||
// Only bother with reconciliation if the parent model has enums.
|
||||
if (parentCodegenModel.hasEnums) {
|
||||
|
||||
// Get the properties for the parent and child models
|
||||
final List<CodegenProperty> parentModelCodegenProperties = parentCodegenModel.vars;
|
||||
List<CodegenProperty> codegenProperties = codegenModel.vars;
|
||||
|
||||
// Iterate over all of the parent model properties
|
||||
boolean removedChildEnum = false;
|
||||
for (CodegenProperty parentModelCodegenPropery : parentModelCodegenProperties) {
|
||||
// Look for enums
|
||||
if (parentModelCodegenPropery.isEnum) {
|
||||
// Now that we have found an enum in the parent class,
|
||||
// and search the child class for the same enum.
|
||||
Iterator<CodegenProperty> iterator = codegenProperties.iterator();
|
||||
while (iterator.hasNext()) {
|
||||
CodegenProperty codegenProperty = iterator.next();
|
||||
if (codegenProperty.isEnum && codegenProperty.equals(parentModelCodegenPropery)) {
|
||||
// We found an enum in the child class that is
|
||||
// a duplicate of the one in the parent, so remove it.
|
||||
iterator.remove();
|
||||
removedChildEnum = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (removedChildEnum) {
|
||||
// If we removed an entry from this model's vars, we need to ensure hasMore is updated
|
||||
int count = 0, numVars = codegenProperties.size();
|
||||
for (CodegenProperty codegenProperty : codegenProperties) {
|
||||
count += 1;
|
||||
codegenProperty.hasMore = count < numVars;
|
||||
}
|
||||
codegenModel.vars = codegenProperties;
|
||||
}
|
||||
}
|
||||
|
||||
return codegenModel;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toEnumVarName(String value, String datatype) {
|
||||
if (value.length() == 0) {
|
||||
return "Empty";
|
||||
}
|
||||
|
||||
// for symbol, e.g. $, #
|
||||
if (getSymbolName(value) != null) {
|
||||
return camelize(getSymbolName(value));
|
||||
}
|
||||
|
||||
// number
|
||||
if (datatype.startsWith("int") || datatype.startsWith("long") ||
|
||||
datatype.startsWith("double") || datatype.startsWith("float")) {
|
||||
String varName = "NUMBER_" + value;
|
||||
varName = varName.replaceAll("-", "MINUS_");
|
||||
varName = varName.replaceAll("\\+", "PLUS_");
|
||||
varName = varName.replaceAll("\\.", "_DOT_");
|
||||
return varName;
|
||||
}
|
||||
|
||||
// string
|
||||
String var = value.replaceAll("_", " ");
|
||||
//var = WordUtils.capitalizeFully(var);
|
||||
var = camelize(var);
|
||||
var = var.replaceAll("\\W+", "");
|
||||
|
||||
if (var.matches("\\d.*")) {
|
||||
return "_" + var;
|
||||
} else {
|
||||
return var;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toVarName(String name) {
|
||||
// sanitize name
|
||||
name = sanitizeName(name);
|
||||
|
||||
// if it's all uppper case, do nothing
|
||||
if (name.matches("^[A-Z_]*$")) {
|
||||
return name;
|
||||
}
|
||||
|
||||
name = getNameUsingModelPropertyNaming(name);
|
||||
|
||||
// for reserved word or word starting with number, append _
|
||||
if (isReservedWord(name) || name.matches("^\\d.*")) {
|
||||
name = escapeReservedWord(name);
|
||||
}
|
||||
|
||||
return name;
|
||||
}
|
||||
|
||||
public String getNameUsingModelPropertyNaming(String name) {
|
||||
switch (CodegenConstants.MODEL_PROPERTY_NAMING_TYPE.valueOf(getModelPropertyNaming())) {
|
||||
case original:
|
||||
return name;
|
||||
case camelCase:
|
||||
return camelize(name, true);
|
||||
case PascalCase:
|
||||
return camelize(name);
|
||||
case snake_case:
|
||||
return underscore(name);
|
||||
default:
|
||||
throw new IllegalArgumentException("Invalid model property naming '" +
|
||||
name + "'. Must be 'original', 'camelCase', " +
|
||||
"'PascalCase' or 'snake_case'");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void setPackageName(String packageName) {
|
||||
this.packageName = packageName;
|
||||
}
|
||||
|
||||
public void setPackageVersion(String packageVersion) {
|
||||
this.packageVersion = packageVersion;
|
||||
}
|
||||
|
||||
public void setTargetFrameworkNuget(String targetFrameworkNuget) {
|
||||
this.targetFrameworkNuget = targetFrameworkNuget;
|
||||
}
|
||||
|
||||
public void setSupportsAsync(Boolean supportsAsync) {
|
||||
this.supportsAsync = supportsAsync;
|
||||
}
|
||||
|
||||
public void setSupportsUWP(Boolean supportsUWP) {
|
||||
this.supportsUWP = supportsUWP;
|
||||
}
|
||||
|
||||
public void setNetStandard(Boolean netStandard) {
|
||||
this.netStandard = netStandard;
|
||||
}
|
||||
|
||||
public void setGeneratePropertyChanged(final Boolean generatePropertyChanged) {
|
||||
this.generatePropertyChanged = generatePropertyChanged;
|
||||
}
|
||||
|
||||
public boolean isNonPublicApi() {
|
||||
return nonPublicApi;
|
||||
}
|
||||
|
||||
public void setNonPublicApi(final boolean nonPublicApi) {
|
||||
this.nonPublicApi = nonPublicApi;
|
||||
}
|
||||
|
||||
public void setValidatable(boolean validatable) {
|
||||
this.validatable = validatable;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toModelDocFilename(String name) {
|
||||
return toModelFilename(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String apiDocFileFolder() {
|
||||
return (outputFolder + "/" + apiDocPath).replace('/', File.separatorChar);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String modelDocFileFolder() {
|
||||
return (outputFolder + "/" + modelDocPath).replace('/', File.separatorChar);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String apiTestFileFolder() {
|
||||
return outputFolder + File.separator + testFolder + File.separator + testPackageName() + File.separator + apiPackage();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String modelTestFileFolder() {
|
||||
return outputFolder + File.separator + testFolder + File.separator + testPackageName() + File.separator + modelPackage();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Mustache.Compiler processCompiler(Mustache.Compiler compiler) {
|
||||
// To avoid unexpected behaviors when options are passed programmatically such as { "supportsAsync": "" }
|
||||
return super.processCompiler(compiler).emptyStringIsFalse(true);
|
||||
}
|
||||
}
|
||||
@@ -160,7 +160,7 @@ public class CppQt5ClientCodegen extends CppQt5AbstractCodegen implements Codege
|
||||
|
||||
@Override
|
||||
public String toApiFilename(String name) {
|
||||
return modelNamePrefix + initialCaps(name) + "Api";
|
||||
return modelNamePrefix + sanitizeName(initialCaps(name)) + "Api";
|
||||
}
|
||||
|
||||
public void setOptionalProjectFileFlag(boolean flag) {
|
||||
|
||||
@@ -152,6 +152,7 @@ public class DartClientCodegen extends DefaultCodegen implements CodegenConfig {
|
||||
|
||||
if (StringUtils.isEmpty(System.getenv("DART_POST_PROCESS_FILE"))) {
|
||||
LOGGER.info("Environment variable DART_POST_PROCESS_FILE not defined so the Dart code may not be properly formatted. To define it, try `export DART_POST_PROCESS_FILE=\"/usr/local/bin/dartfmt -w\"` (Linux/Mac)");
|
||||
LOGGER.info("NOTE: To enable file post-processing, 'enablePostProcessFile' must be set to `true` (--enable-post-process-file for CLI).");
|
||||
}
|
||||
|
||||
if (additionalProperties.containsKey(BROWSER_CLIENT)) {
|
||||
|
||||
@@ -191,6 +191,7 @@ public class ElmClientCodegen extends DefaultCodegen implements CodegenConfig {
|
||||
} else { // 0.19
|
||||
LOGGER.info("Environment variable ELM_POST_PROCESS_FILE not defined so the Elm code may not be properly formatted. To define it, try `export ELM_POST_PROCESS_FILE=\"/usr/local/bin/elm-format --elm-version={} --yes\"` (Linux/Mac)", "0.19");
|
||||
}
|
||||
LOGGER.info("NOTE: To enable file post-processing, 'enablePostProcessFile' must be set to `true` (--enable-post-process-file for CLI).");
|
||||
}
|
||||
|
||||
switch (elmVersion) {
|
||||
@@ -261,7 +262,13 @@ public class ElmClientCodegen extends DefaultCodegen implements CodegenConfig {
|
||||
|
||||
@Override
|
||||
public String toEnumVarName(String value, String datatype) {
|
||||
final String camelized = org.openapitools.codegen.utils.StringUtils.camelize(value.replace(" ", "_").replace("(", "_").replace(")", "")); // TODO FIXME escape properly
|
||||
String camelized = org.openapitools.codegen.utils.StringUtils.camelize(value.replace(" ", "_").replace("(", "_").replace(")", "")); // TODO FIXME escape properly
|
||||
|
||||
if (camelized.length() == 0) {
|
||||
LOGGER.error("Unable to determine enum variable name (name: {}, datatype: {}) from empty string. Default to UnknownEnumVariableName", value, datatype);
|
||||
camelized = "UnknownEnumVariableName";
|
||||
}
|
||||
|
||||
if (!Character.isUpperCase(camelized.charAt(0))) {
|
||||
return "N" + camelized;
|
||||
}
|
||||
@@ -495,9 +502,8 @@ public class ElmClientCodegen extends DefaultCodegen implements CodegenConfig {
|
||||
} else if (ModelUtils.isDateTimeSchema(p)) {
|
||||
return toOptionalValue(null);
|
||||
} else if (ModelUtils.isNumberSchema(p)) {
|
||||
NumberSchema dp = (NumberSchema) p;
|
||||
if (dp.getDefault() != null) {
|
||||
return toOptionalValue(dp.getDefault().toString());
|
||||
if (p.getDefault() != null) {
|
||||
return toOptionalValue(p.getDefault().toString());
|
||||
}
|
||||
return toOptionalValue(null);
|
||||
} else if (ModelUtils.isIntegerSchema(p)) {
|
||||
|
||||
@@ -152,6 +152,7 @@ public class JavaResteasyServerCodegen extends AbstractJavaJAXRSServerCodegen im
|
||||
|
||||
@Override
|
||||
public void postProcessModelProperty(CodegenModel model, CodegenProperty property) {
|
||||
super.postProcessModelProperty(model, property);
|
||||
//Add imports for Jackson
|
||||
if (!BooleanUtils.toBoolean(model.isEnum)) {
|
||||
model.imports.add("JsonProperty");
|
||||
|
||||
@@ -234,6 +234,7 @@ public class JavascriptClientCodegen extends DefaultCodegen implements CodegenCo
|
||||
|
||||
if (StringUtils.isEmpty(System.getenv("JS_POST_PROCESS_FILE"))) {
|
||||
LOGGER.info("Environment variable JS_POST_PROCESS_FILE not defined so the JS code may not be properly formatted. To define it, try 'export JS_POST_PROCESS_FILE=\"/usr/local/bin/js-beautify -r -f\"' (Linux/Mac)");
|
||||
LOGGER.info("NOTE: To enable file post-processing, 'enablePostProcessFile' must be set to `true` (--enable-post-process-file for CLI).");
|
||||
}
|
||||
|
||||
if (additionalProperties.containsKey(PROJECT_NAME)) {
|
||||
|
||||
@@ -135,6 +135,7 @@ public class PerlClientCodegen extends DefaultCodegen implements CodegenConfig {
|
||||
|
||||
if (StringUtils.isEmpty(System.getenv("PERL_POST_PROCESS_FILE"))) {
|
||||
LOGGER.info("Environment variable PERL_POST_PROCESS_FILE not defined so the Perl code may not be properly formatted. To define it, try 'export PERL_POST_PROCESS_FILE=/usr/local/bin/perltidy -b -bext=\"/\"' (Linux/Mac)");
|
||||
LOGGER.info("NOTE: To enable file post-processing, 'enablePostProcessFile' must be set to `true` (--enable-post-process-file for CLI).");
|
||||
}
|
||||
|
||||
if (additionalProperties.containsKey(MODULE_VERSION)) {
|
||||
|
||||
@@ -174,6 +174,7 @@ public class PythonClientCodegen extends DefaultCodegen implements CodegenConfig
|
||||
|
||||
if (StringUtils.isEmpty(System.getenv("PYTHON_POST_PROCESS_FILE"))) {
|
||||
LOGGER.info("Environment variable PYTHON_POST_PROCESS_FILE not defined so the Python code may not be properly formatted. To define it, try 'export PYTHON_POST_PROCESS_FILE=\"/usr/local/bin/yapf -i\"' (Linux/Mac)");
|
||||
LOGGER.info("NOTE: To enable file post-processing, 'enablePostProcessFile' must be set to `true` (--enable-post-process-file for CLI).");
|
||||
}
|
||||
|
||||
Boolean excludeTests = false;
|
||||
|
||||
@@ -157,6 +157,7 @@ public class PythonFlaskConnexionServerCodegen extends DefaultCodegen implements
|
||||
|
||||
if (StringUtils.isEmpty(System.getenv("PYTHON_POST_PROCESS_FILE"))) {
|
||||
LOGGER.info("Environment variable PYTHON_POST_PROCESS_FILE not defined so the Python code may not be properly formatted. To define it, try 'export PYTHON_POST_PROCESS_FILE=\"/usr/local/bin/yapf -i\"' (Linux/Mac)");
|
||||
LOGGER.info("NOTE: To enable file post-processing, 'enablePostProcessFile' must be set to `true` (--enable-post-process-file for CLI).");
|
||||
}
|
||||
|
||||
//apiTemplateFiles.clear();
|
||||
|
||||
@@ -245,6 +245,7 @@ public class Swift3Codegen extends DefaultCodegen implements CodegenConfig {
|
||||
|
||||
if (StringUtils.isEmpty(System.getenv("SWIFT_POST_PROCESS_FILE"))) {
|
||||
LOGGER.info("Environment variable SWIFT_POST_PROCESS_FILE not defined so the Swift code may not be properly formatted. To define it, try 'export SWIFT_POST_PROCESS_FILE=/usr/local/bin/swiftformat' (Linux/Mac)");
|
||||
LOGGER.info("NOTE: To enable file post-processing, 'enablePostProcessFile' must be set to `true` (--enable-post-process-file for CLI).");
|
||||
}
|
||||
|
||||
// Setup project name
|
||||
|
||||
@@ -300,6 +300,7 @@ public class Swift4Codegen extends DefaultCodegen implements CodegenConfig {
|
||||
|
||||
if (StringUtils.isEmpty(System.getenv("SWIFT_POST_PROCESS_FILE"))) {
|
||||
LOGGER.info("Environment variable SWIFT_POST_PROCESS_FILE not defined so the Swift code may not be properly formatted. To define it, try 'export SWIFT_POST_PROCESS_FILE=/usr/local/bin/swiftformat' (Linux/Mac)");
|
||||
LOGGER.info("NOTE: To enable file post-processing, 'enablePostProcessFile' must be set to `true` (--enable-post-process-file for CLI).");
|
||||
}
|
||||
|
||||
// Setup project name
|
||||
|
||||
Reference in New Issue
Block a user