Merge pull request #1965 from wing328/ts_option_property_naming

[TypeScript] add an option to determine property naming convention
This commit is contained in:
wing328 2016-01-26 16:54:20 +08:00
commit f2ab4db419
15 changed files with 239 additions and 20 deletions

View File

@ -74,4 +74,9 @@ public class CodegenConstants {
public static final String OPTIONAL_PROJECT_GUID = "packageGuid";
public static final String OPTIONAL_PROJECT_GUID_DESC = "The GUID that will be associated with the C# project";
public static final String MODEL_PROPERTY_NAMING = "modelPropertyNaming";
public static final String MODEL_PROPERTY_NAMING_DESC = "Naming convention for the property: 'camelCase', 'PascalCase', 'snake_case' and 'original', which keeps the original name";
public static enum MODEL_PROPERTY_NAMING_TYPE {camelCase, PascalCase, snake_case, original}
}

View File

@ -10,6 +10,8 @@ import org.apache.commons.lang.StringUtils;
public abstract class AbstractTypeScriptClientCodegen extends DefaultCodegen implements CodegenConfig {
protected String modelPropertyNaming= "camelCase";
public AbstractTypeScriptClientCodegen() {
super();
supportsInheritance = true;
@ -50,8 +52,21 @@ public abstract class AbstractTypeScriptClientCodegen extends DefaultCodegen imp
typeMapping.put("DateTime", "Date");
//TODO binary should be mapped to byte array
// mapped to String as a workaround
typeMapping.put("binary", "string");
typeMapping.put("binary", "string");
cliOptions.add(new CliOption(CodegenConstants.MODEL_PROPERTY_NAMING, CodegenConstants.MODEL_PROPERTY_NAMING_DESC).defaultValue("camelCase"));
}
@Override
public void processOpts() {
super.processOpts();
if (additionalProperties.containsKey(CodegenConstants.MODEL_PROPERTY_NAMING)) {
setModelPropertyNaming((String) additionalProperties.get(CodegenConstants.MODEL_PROPERTY_NAMING));
}
}
@Override
public CodegenType getTag() {
@ -74,7 +89,7 @@ public abstract class AbstractTypeScriptClientCodegen extends DefaultCodegen imp
}
@Override
public String toVarName(String name) {
public String toParamName(String name) {
// replace - with _ e.g. created-at => created_at
name = name.replaceAll("-", "_"); // FIXME: a parameter should not be assigned. Also declare the methods parameters as 'final'.
@ -94,9 +109,9 @@ public abstract class AbstractTypeScriptClientCodegen extends DefaultCodegen imp
}
@Override
public String toParamName(String name) {
public String toVarName(String name) {
// should be the same as variable name
return toVarName(name);
return getNameUsingModelPropertyNaming(name);
}
@Override
@ -146,19 +161,47 @@ public abstract class AbstractTypeScriptClientCodegen extends DefaultCodegen imp
return type;
}
@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
// append _ at the beginning, e.g. _return
if (reservedWords.contains(operationId)) {
return escapeReservedWord(camelize(sanitizeName(operationId), true));
}
return camelize(sanitizeName(operationId), true);
@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
// append _ at the beginning, e.g. _return
if (reservedWords.contains(operationId)) {
return escapeReservedWord(camelize(sanitizeName(operationId), true));
}
return camelize(sanitizeName(operationId), true);
}
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;
}
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'");
}
}
}

View File

@ -9,6 +9,7 @@ import java.util.Map;
public class TypeScriptAngularClientOptionsProvider implements OptionsProvider {
public static final String SORT_PARAMS_VALUE = "false";
public static final String ENSURE_UNIQUE_PARAMS_VALUE = "true";
public static final String MODEL_PROPERTY_NAMING_VALUE = "camelCase";
@Override
public String getLanguage() {
@ -20,6 +21,7 @@ public class TypeScriptAngularClientOptionsProvider implements OptionsProvider {
ImmutableMap.Builder<String, String> builder = new ImmutableMap.Builder<String, String>();
return builder.put(CodegenConstants.SORT_PARAMS_BY_REQUIRED_FLAG, SORT_PARAMS_VALUE)
.put(CodegenConstants.ENSURE_UNIQUE_PARAMS, ENSURE_UNIQUE_PARAMS_VALUE)
.put(CodegenConstants.MODEL_PROPERTY_NAMING, MODEL_PROPERTY_NAMING_VALUE)
.build();
}

View File

@ -9,6 +9,7 @@ import java.util.Map;
public class TypeScriptNodeClientOptionsProvider implements OptionsProvider {
public static final String SORT_PARAMS_VALUE = "false";
public static final String ENSURE_UNIQUE_PARAMS_VALUE = "true";
public static final String MODEL_PROPERTY_NAMING_VALUE = "camelCase";
@Override
public String getLanguage() {
@ -20,6 +21,7 @@ public class TypeScriptNodeClientOptionsProvider implements OptionsProvider {
ImmutableMap.Builder<String, String> builder = new ImmutableMap.Builder<String, String>();
return builder.put(CodegenConstants.SORT_PARAMS_BY_REQUIRED_FLAG, SORT_PARAMS_VALUE)
.put(CodegenConstants.ENSURE_UNIQUE_PARAMS, ENSURE_UNIQUE_PARAMS_VALUE)
.put(CodegenConstants.MODEL_PROPERTY_NAMING, MODEL_PROPERTY_NAMING_VALUE)
.build();
}

View File

@ -28,6 +28,8 @@ public class TypeScriptAngularClientOptionsTest extends AbstractOptionsTest {
new Expectations(clientCodegen) {{
clientCodegen.setSortParamsByRequiredFlag(Boolean.valueOf(TypeScriptAngularClientOptionsProvider.SORT_PARAMS_VALUE));
times = 1;
clientCodegen.setModelPropertyNaming(TypeScriptAngularClientOptionsProvider.MODEL_PROPERTY_NAMING_VALUE);
times = 1;
}};
}
}

View File

@ -28,6 +28,8 @@ public class TypeScriptNodeClientOptionsTest extends AbstractOptionsTest {
new Expectations(clientCodegen) {{
clientCodegen.setSortParamsByRequiredFlag(Boolean.valueOf(TypeScriptNodeClientOptionsProvider.SORT_PARAMS_VALUE));
times = 1;
clientCodegen.setModelPropertyNaming(TypeScriptNodeClientOptionsProvider.MODEL_PROPERTY_NAMING_VALUE);
times = 1;
}};
}
}

View File

@ -1,2 +0,0 @@
// <autogenerated />
[assembly: global::System.Runtime.Versioning.TargetFrameworkAttribute(".NETFramework,Version=v4.5", FrameworkDisplayName = "")]

View File

@ -287,6 +287,64 @@ namespace API.Client {
httpRequestParams = this.extendObj(httpRequestParams, extraHttpRequestParams);
}
return this.$http(httpRequestParams);
}
/**
* Fake endpoint to test byte array return by &#39;Find pet by ID&#39;
* Returns a pet when ID &lt; 10. ID &gt; 10 or nonintegers will simulate API error conditions
* @param petId ID of pet that needs to be fetched
*/
public getPetByIdWithByteArray (petId: number, extraHttpRequestParams?: any ) : ng.IHttpPromise<string> {
const path = this.basePath + '/pet/{petId}?testing_byte_array=true'
.replace('{' + 'petId' + '}', String(petId));
let queryParameters: any = {};
let headerParams: any = this.extendObj({}, this.defaultHeaders);
// verify required parameter 'petId' is set
if (!petId) {
throw new Error('Missing required parameter petId when calling getPetByIdWithByteArray');
}
let httpRequestParams: any = {
method: 'GET',
url: path,
json: true,
params: queryParameters,
headers: headerParams
};
if (extraHttpRequestParams) {
httpRequestParams = this.extendObj(httpRequestParams, extraHttpRequestParams);
}
return this.$http(httpRequestParams);
}
/**
* Fake endpoint to test byte array in body parameter for adding a new pet to the store
*
* @param body Pet object in the form of byte array
*/
public addPetUsingByteArray (body?: string, extraHttpRequestParams?: any ) : ng.IHttpPromise<{}> {
const path = this.basePath + '/pet?testing_byte_array=true';
let queryParameters: any = {};
let headerParams: any = this.extendObj({}, this.defaultHeaders);
let httpRequestParams: any = {
method: 'POST',
url: path,
json: true,
data: body,
params: queryParameters,
headers: headerParams
};
if (extraHttpRequestParams) {
httpRequestParams = this.extendObj(httpRequestParams, extraHttpRequestParams);
}
return this.$http(httpRequestParams);
}
}

View File

@ -1071,6 +1071,113 @@ export class PetApi {
}
});
return deferred.promise;
}
/**
* Fake endpoint to test byte array return by &#39;Find pet by ID&#39;
* Returns a pet when ID &lt; 10. ID &gt; 10 or nonintegers will simulate API error conditions
* @param petId ID of pet that needs to be fetched
*/
public getPetByIdWithByteArray (petId: number) : Promise<{ response: http.ClientResponse; body: string; }> {
const path = this.basePath + '/pet/{petId}?testing_byte_array=true'
.replace('{' + 'petId' + '}', String(petId));
let queryParameters: any = {};
let headerParams: any = this.extendObj({}, this.defaultHeaders);
let formParams: any = {};
// verify required parameter 'petId' is set
if (!petId) {
throw new Error('Missing required parameter petId when calling getPetByIdWithByteArray');
}
let useFormData = false;
let deferred = promise.defer<{ response: http.ClientResponse; body: string; }>();
let requestOptions: request.Options = {
method: 'GET',
qs: queryParameters,
headers: headerParams,
uri: path,
json: true,
}
this.authentications.api_key.applyToRequest(requestOptions);
this.authentications.default.applyToRequest(requestOptions);
if (Object.keys(formParams).length) {
if (useFormData) {
(<any>requestOptions).formData = formParams;
} else {
requestOptions.form = formParams;
}
}
request(requestOptions, (error, response, body) => {
if (error) {
deferred.reject(error);
} else {
if (response.statusCode >= 200 && response.statusCode <= 299) {
deferred.resolve({ response: response, body: body });
} else {
deferred.reject({ response: response, body: body });
}
}
});
return deferred.promise;
}
/**
* Fake endpoint to test byte array in body parameter for adding a new pet to the store
*
* @param body Pet object in the form of byte array
*/
public addPetUsingByteArray (body?: string) : Promise<{ response: http.ClientResponse; body?: any; }> {
const path = this.basePath + '/pet?testing_byte_array=true';
let queryParameters: any = {};
let headerParams: any = this.extendObj({}, this.defaultHeaders);
let formParams: any = {};
let useFormData = false;
let deferred = promise.defer<{ response: http.ClientResponse; body?: any; }>();
let requestOptions: request.Options = {
method: 'POST',
qs: queryParameters,
headers: headerParams,
uri: path,
json: true,
body: body,
}
this.authentications.petstore_auth.applyToRequest(requestOptions);
this.authentications.default.applyToRequest(requestOptions);
if (Object.keys(formParams).length) {
if (useFormData) {
(<any>requestOptions).formData = formParams;
} else {
requestOptions.form = formParams;
}
}
request(requestOptions, (error, response, body) => {
if (error) {
deferred.reject(error);
} else {
if (response.statusCode >= 200 && response.statusCode <= 299) {
deferred.resolve({ response: response, body: body });
} else {
deferred.reject({ response: response, body: body });
}
}
});
return deferred.promise;
}
}