diff --git a/modules/swagger-codegen/src/main/java/io/swagger/codegen/DefaultCodegen.java b/modules/swagger-codegen/src/main/java/io/swagger/codegen/DefaultCodegen.java index 2188af33b7f2..51bcf53177c2 100644 --- a/modules/swagger-codegen/src/main/java/io/swagger/codegen/DefaultCodegen.java +++ b/modules/swagger-codegen/src/main/java/io/swagger/codegen/DefaultCodegen.java @@ -1458,4 +1458,42 @@ public class DefaultCodegen { } return new CliOption("library", sb.toString()); } + + /** + * sanitize name (parameter, property, method, etc) + * + * @param name string to be sanitize + * @return sanitized string + */ + public String sanitizeName(String name) { + // NOTE: performance wise, we should have written with 2 replaceAll to replace desired + // character with _ or empty character. Below aims to spell out different cases we've + // encountered so far and hopefully make it easier for others to add more special + // cases in the future. + + // input[] => input + name = name.replaceAll("\\[\\]", ""); + + // input[a][b] => input_a_b + name = name.replaceAll("\\[", "_"); + name = name.replaceAll("\\]", ""); + + // input(a)(b) => input_a_b + name = name.replaceAll("\\(", "_"); + name = name.replaceAll("\\)", ""); + + // input.name => input_name + name = name.replaceAll("\\.", "_"); + + // input-name => input_name + name = name.replaceAll("-", "_"); + + // input name and age => input_name_and_age + name = name.replaceAll(" ", "_"); + + // remove everything else other than word, number and _ + // $php_variable => php_variable + return name.replaceAll("[^a-zA-Z0-9_]", ""); + + } } diff --git a/modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/CSharpClientCodegen.java b/modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/CSharpClientCodegen.java index 1d7accd3b274..09ec05b078bf 100644 --- a/modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/CSharpClientCodegen.java +++ b/modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/CSharpClientCodegen.java @@ -146,8 +146,8 @@ public class CSharpClientCodegen extends DefaultCodegen implements CodegenConfig @Override public String toVarName(String name) { - // replace - with _ e.g. created-at => created_at - name = name.replaceAll("-", "_"); + // sanitize name + name = sanitizeName(name); // if it's all uppper case, do nothing if (name.matches("^[A-Z_]*$")) { @@ -249,7 +249,7 @@ public class CSharpClientCodegen extends DefaultCodegen implements CodegenConfig throw new RuntimeException(operationId + " (reserved word) cannot be used as method name"); } - return camelize(operationId); + return camelize(sanitizeName(operationId)); } } diff --git a/modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/JavaClientCodegen.java b/modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/JavaClientCodegen.java index 00b5c99cf4fc..aad744dd1ce4 100644 --- a/modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/JavaClientCodegen.java +++ b/modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/JavaClientCodegen.java @@ -205,8 +205,8 @@ public class JavaClientCodegen extends DefaultCodegen implements CodegenConfig { @Override public String toVarName(String name) { - // replace - with _ e.g. created-at => created_at - name = name.replaceAll("-", "_"); + // sanitize name + name = sanitizeName(name); if("_".equals(name)) { name = "_u"; @@ -310,7 +310,7 @@ public class JavaClientCodegen extends DefaultCodegen implements CodegenConfig { throw new RuntimeException(operationId + " (reserved word) cannot be used as method name"); } - return camelize(operationId, true); + return camelize(sanitizeName(operationId), true); } @Override diff --git a/modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/ObjcClientCodegen.java b/modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/ObjcClientCodegen.java index cb6ec79a9848..dfb4094f2b65 100644 --- a/modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/ObjcClientCodegen.java +++ b/modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/ObjcClientCodegen.java @@ -328,9 +328,8 @@ public class ObjcClientCodegen extends DefaultCodegen implements CodegenConfig { @Override public String toVarName(String name) { - // replace non-word characters to `_` - // e.g. `created-at` to `created_at` - name = name.replaceAll("[^a-zA-Z0-9_]", "_"); + // sanitize name + name = sanitizeName(name); // if it's all upper case, do noting if (name.matches("^[A-Z_]$")) { @@ -371,7 +370,7 @@ public class ObjcClientCodegen extends DefaultCodegen implements CodegenConfig { throw new RuntimeException(operationId + " (reserved word) cannot be used as method name"); } - return camelize(operationId, true); + return camelize(sanitizeName(operationId), true); } public void setClassPrefix(String classPrefix) { diff --git a/modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/PhpClientCodegen.java b/modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/PhpClientCodegen.java index fbb798f68026..ac2cddfefa98 100644 --- a/modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/PhpClientCodegen.java +++ b/modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/PhpClientCodegen.java @@ -300,6 +300,9 @@ public class PhpClientCodegen extends DefaultCodegen implements CodegenConfig { this.setParameterNamingConvention((String) additionalProperties.get("variableNamingConvention")); } + // sanitize name + name = sanitizeName(name); + if ("camelCase".equals(variableNamingConvention)) { // return the name in camelCase style // phone_number => phoneNumber @@ -342,4 +345,20 @@ public class PhpClientCodegen extends DefaultCodegen implements CodegenConfig { // should be the same as the model name return toModelName(name); } + + @Override + public String toOperationId(String operationId) { + // throw exception if method name is empty + if (StringUtils.isEmpty(operationId)) { + throw new RuntimeException("Empty method name (operationId) not allowed"); + } + + // method name cannot use reserved keyword, e.g. return + if (reservedWords.contains(operationId)) { + throw new RuntimeException(operationId + " (reserved word) cannot be used as method name"); + } + + return camelize(sanitizeName(operationId), true); + } + } diff --git a/modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/PythonClientCodegen.java b/modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/PythonClientCodegen.java index 9b685d1e2070..8926a79343a5 100755 --- a/modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/PythonClientCodegen.java +++ b/modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/PythonClientCodegen.java @@ -167,8 +167,8 @@ public class PythonClientCodegen extends DefaultCodegen implements CodegenConfig @Override public String toVarName(String name) { - // replace - with _ e.g. created-at => created_at - name = name.replaceAll("-", "_"); + // sanitize name + name = sanitizeName(name); // if it's all uppper case, convert to lower case if (name.matches("^[A-Z_]*$")) { @@ -177,7 +177,7 @@ public class PythonClientCodegen extends DefaultCodegen implements CodegenConfig // underscore the variable name // petId => pet_id - name = underscore(dropDots(name)); + name = underscore(name); // remove leading underscore name = name.replaceAll("^_*", ""); @@ -258,7 +258,7 @@ public class PythonClientCodegen extends DefaultCodegen implements CodegenConfig throw new RuntimeException(operationId + " (reserved word) cannot be used as method name"); } - return underscore(operationId); + return underscore(sanitizeName(operationId)); } public void setPackageName(String packageName) { diff --git a/modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/RubyClientCodegen.java b/modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/RubyClientCodegen.java index 36a3f31aa486..4368fc3cef4b 100644 --- a/modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/RubyClientCodegen.java +++ b/modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/RubyClientCodegen.java @@ -199,8 +199,8 @@ public class RubyClientCodegen extends DefaultCodegen implements CodegenConfig { @Override public String toVarName(String name) { - // replace - with _ e.g. created-at => created_at - name = name.replaceAll("-", "_"); + // sanitize name + name = sanitizeName(name); // if it's all uppper case, convert to lower case if (name.matches("^[A-Z_]*$")) { @@ -279,7 +279,7 @@ public class RubyClientCodegen extends DefaultCodegen implements CodegenConfig { throw new RuntimeException(operationId + " (reserved word) cannot be used as method name"); } - return underscore(operationId); + return underscore(sanitizeName(operationId)); } @Override diff --git a/modules/swagger-codegen/src/test/scala/Java/JavaModelTest.scala b/modules/swagger-codegen/src/test/scala/Java/JavaModelTest.scala index 2df8db477de4..1d044fbfdbec 100644 --- a/modules/swagger-codegen/src/test/scala/Java/JavaModelTest.scala +++ b/modules/swagger-codegen/src/test/scala/Java/JavaModelTest.scala @@ -355,6 +355,20 @@ class JavaModelTest extends FlatSpec with Matchers { vars.get(0).name should be("createdAt") } + it should "convert query[password] to queryPassword" in { + val model = new ModelImpl() + .description("a sample model") + .property("query[password]", new StringProperty()) + + val codegen = new JavaClientCodegen() + val cm = codegen.fromModel("sample", model) + val vars = cm.vars + vars.get(0).baseName should be("query[password]") + vars.get(0).getter should be("getQueryPassword") + vars.get(0).setter should be("setQueryPassword") + vars.get(0).name should be("queryPassword") + } + it should "properly escape names per 567" in { val model = new ModelImpl() .description("a sample model") diff --git a/samples/client/petstore/python/swagger_client/__init__.py b/samples/client/petstore/python/swagger_client/__init__.py index 6e7b59f36fde..f61c5d55262a 100644 --- a/samples/client/petstore/python/swagger_client/__init__.py +++ b/samples/client/petstore/python/swagger_client/__init__.py @@ -9,8 +9,8 @@ from .models.order import Order # import apis into sdk package from .apis.user_api import UserApi -from .apis.store_api import StoreApi from .apis.pet_api import PetApi +from .apis.store_api import StoreApi # import ApiClient from .api_client import ApiClient diff --git a/samples/client/petstore/python/swagger_client/apis/__init__.py b/samples/client/petstore/python/swagger_client/apis/__init__.py index c0e09458f950..592a56e282d2 100644 --- a/samples/client/petstore/python/swagger_client/apis/__init__.py +++ b/samples/client/petstore/python/swagger_client/apis/__init__.py @@ -2,5 +2,5 @@ from __future__ import absolute_import # import apis into api package from .user_api import UserApi -from .store_api import StoreApi from .pet_api import PetApi +from .store_api import StoreApi diff --git a/samples/client/petstore/python/swagger_client/apis/pet_api.py b/samples/client/petstore/python/swagger_client/apis/pet_api.py index b162cc534c38..ad053a7d72d9 100644 --- a/samples/client/petstore/python/swagger_client/apis/pet_api.py +++ b/samples/client/petstore/python/swagger_client/apis/pet_api.py @@ -409,7 +409,7 @@ class PetApi(object): select_header_content_type([]) # Authentication setting - auth_settings = ['petstore_auth', 'api_key'] + auth_settings = ['api_key', 'petstore_auth'] response = self.api_client.call_api(resource_path, method, path_params,