diff --git a/bin/configs/crystal.yaml b/bin/configs/crystal.yaml index c578838173a..db88d8bfd9b 100644 --- a/bin/configs/crystal.yaml +++ b/bin/configs/crystal.yaml @@ -7,3 +7,12 @@ additionalProperties: moduleName: Petstore shardName: petstore strictSpecBehavior: false +modelNameMappings: + PropertyNameMapping: AnotherPropertyNameMapping +nameMappings: + _type: underscore_type + type_: type_with_underscore + type-: type_with_dash +parameterNameMappings: + _type: underscore_type + type_: type_with_underscore diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/CrystalClientCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/CrystalClientCodegen.java index 5afccae337b..818d14939a4 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/CrystalClientCodegen.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/CrystalClientCodegen.java @@ -368,6 +368,11 @@ public class CrystalClientCodegen extends DefaultCodegen { @Override public String toModelName(final String name) { + // obtain the name from modelNameMapping directly if provided + if (modelNameMapping.containsKey(name)) { + return modelNameMapping.get(name); + } + String modelName; modelName = sanitizeModelName(name); @@ -409,6 +414,11 @@ public class CrystalClientCodegen extends DefaultCodegen { @Override public String toModelFilename(String name) { + // obtain the name from modelNameMapping directly if provided + if (modelNameMapping.containsKey(name)) { + return underscore(modelNameMapping.get(name)); + } + return underscore(toModelName(name)); } @@ -867,6 +877,11 @@ public class CrystalClientCodegen extends DefaultCodegen { @Override public String toVarName(final String name) { + // obtain the name from nameMapping directly if provided + if (nameMapping.containsKey(name)) { + return nameMapping.get(name); + } + String varName; // sanitize name varName = sanitizeName(name); @@ -894,6 +909,11 @@ public class CrystalClientCodegen extends DefaultCodegen { @Override public String toParamName(String name) { + // obtain the name from parameterNameMapping directly if provided + if (parameterNameMapping.containsKey(name)) { + return parameterNameMapping.get(name); + } + // should be the same as variable name return toVarName(name); } diff --git a/modules/openapi-generator/src/test/resources/3_0/crystal/petstore.yaml b/modules/openapi-generator/src/test/resources/3_0/crystal/petstore.yaml index 385b3e0e5e7..21cb43dc5fc 100644 --- a/modules/openapi-generator/src/test/resources/3_0/crystal/petstore.yaml +++ b/modules/openapi-generator/src/test/resources/3_0/crystal/petstore.yaml @@ -566,6 +566,47 @@ paths: description: User not found security: - api_key: [] + /fake/parameter-name-mapping: + get: + tags: + - fake + summary: parameter name mapping test + operationId: getParameterNameMapping + parameters: + - name: _type + in: header + description: _type + required: true + schema: + type: integer + format: int64 + - name: type + in: query + description: type + required: true + schema: + type: string + - name: type_ + in: header + description: type_ + required: true + schema: + type: string + - name: type- + in: header + description: type- + required: true + schema: + type: string + - name: http_debug_option + in: query + description: http debug option (to test parameter naming option) + required: true + schema: + type: string + responses: + 200: + description: OK externalDocs: description: Find out more about Swagger url: 'http://swagger.io' @@ -809,3 +850,13 @@ components: description: A string starting with 'image_' (case insensitive) and one to three digits following i.e. Image_01. type: string pattern: '/^image_\d{1,3}$/i' + PropertyNameMapping: + properties: + http_debug_operation: + type: string + _type: + type: string + type: + type: string + type_: + type: string diff --git a/samples/client/petstore/crystal/.openapi-generator/FILES b/samples/client/petstore/crystal/.openapi-generator/FILES index ab944b040a0..46d1bf5974e 100644 --- a/samples/client/petstore/crystal/.openapi-generator/FILES +++ b/samples/client/petstore/crystal/.openapi-generator/FILES @@ -5,12 +5,14 @@ git_push.sh shard.yml spec/spec_helper.cr src/petstore.cr +src/petstore/api/fake_api.cr src/petstore/api/pet_api.cr src/petstore/api/store_api.cr src/petstore/api/user_api.cr src/petstore/api_client.cr src/petstore/api_error.cr src/petstore/configuration.cr +src/petstore/models/another_property_name_mapping.cr src/petstore/models/api_response.cr src/petstore/models/category.cr src/petstore/models/format_test.cr diff --git a/samples/client/petstore/crystal/spec/api/fake_api_spec.cr b/samples/client/petstore/crystal/spec/api/fake_api_spec.cr new file mode 100644 index 00000000000..b8b9922be4c --- /dev/null +++ b/samples/client/petstore/crystal/spec/api/fake_api_spec.cr @@ -0,0 +1,41 @@ +# #OpenAPI Petstore +# +##This is a sample server Petstore server. For this sample, you can use the api key `special-key` to test the authorization filters. +# +#The version of the OpenAPI document: 1.0.0 +# +#Generated by: https://openapi-generator.tech +#OpenAPI Generator version: 7.0.0-SNAPSHOT +# + +require "../spec_helper" +require "json" +require "time" + +# Unit tests for Petstore::FakeApi +# Automatically generated by openapi-generator (https://openapi-generator.tech) +# Please update as you see appropriate +describe "FakeApi" do + describe "test an instance of FakeApi" do + it "should create an instance of FakeApi" do + api_instance = Petstore::FakeApi.new + # TODO expect(api_instance).to be_instance_of(Petstore::FakeApi) + end + end + + # unit tests for get_parameter_name_mapping + # parameter name mapping test + # @param _type _type + # @param _type2 type + # @param type_ type_ + # @param type_2 type- + # @param http_debug_option http debug option (to test parameter naming option) + # @param [Hash] opts the optional parameters + # @return [nil] + describe "get_parameter_name_mapping test" do + it "should work" do + # assertion here. ref: https://crystal-lang.org/reference/guides/testing.html + end + end + +end diff --git a/samples/client/petstore/crystal/spec/models/another_property_name_mapping_spec.cr b/samples/client/petstore/crystal/spec/models/another_property_name_mapping_spec.cr new file mode 100644 index 00000000000..c7491f69c04 --- /dev/null +++ b/samples/client/petstore/crystal/spec/models/another_property_name_mapping_spec.cr @@ -0,0 +1,50 @@ +# #OpenAPI Petstore +# +##This is a sample server Petstore server. For this sample, you can use the api key `special-key` to test the authorization filters. +# +#The version of the OpenAPI document: 1.0.0 +# +#Generated by: https://openapi-generator.tech +#OpenAPI Generator version: 7.0.0-SNAPSHOT +# + +require "../spec_helper" +require "json" +require "time" + +# Unit tests for Petstore::AnotherPropertyNameMapping +# Automatically generated by openapi-generator (https://openapi-generator.tech) +# Please update as you see appropriate +describe Petstore::AnotherPropertyNameMapping do + + describe "test an instance of AnotherPropertyNameMapping" do + it "should create an instance of AnotherPropertyNameMapping" do + #instance = Petstore::AnotherPropertyNameMapping.new + #expect(instance).to be_instance_of(Petstore::AnotherPropertyNameMapping) + end + end + describe "test attribute 'http_debug_operation'" do + it "should work" do + # assertion here. ref: https://crystal-lang.org/reference/guides/testing.html + end + end + + describe "test attribute 'underscore_type'" do + it "should work" do + # assertion here. ref: https://crystal-lang.org/reference/guides/testing.html + end + end + + describe "test attribute '_type'" do + it "should work" do + # assertion here. ref: https://crystal-lang.org/reference/guides/testing.html + end + end + + describe "test attribute 'type_with_underscore'" do + it "should work" do + # assertion here. ref: https://crystal-lang.org/reference/guides/testing.html + end + end + +end diff --git a/samples/client/petstore/crystal/src/petstore/api/fake_api.cr b/samples/client/petstore/crystal/src/petstore/api/fake_api.cr new file mode 100644 index 00000000000..c5703bcd257 --- /dev/null +++ b/samples/client/petstore/crystal/src/petstore/api/fake_api.cr @@ -0,0 +1,104 @@ +# #OpenAPI Petstore +# +##This is a sample server Petstore server. For this sample, you can use the api key `special-key` to test the authorization filters. +# +#The version of the OpenAPI document: 1.0.0 +# +#Generated by: https://openapi-generator.tech +#OpenAPI Generator version: 7.0.0-SNAPSHOT +# + +require "uri" + +module Petstore + class FakeApi + property api_client : ApiClient + + def initialize(api_client = ApiClient.default) + @api_client = api_client + end + # parameter name mapping test + # @param underscore_type [Int64] _type + # @param _type [String] type + # @param type_with_underscore [String] type_ + # @param type_with_dash [String] type- + # @param http_debug_option [String] http debug option (to test parameter naming option) + # @return [nil] + def get_parameter_name_mapping(underscore_type : Int64, _type : String, type_with_underscore : String, type_with_dash : String, http_debug_option : String) + get_parameter_name_mapping_with_http_info(underscore_type, _type, type_with_underscore, type_with_dash, http_debug_option) + nil + end + + # parameter name mapping test + # @param underscore_type [Int64] _type + # @param _type [String] type + # @param type_with_underscore [String] type_ + # @param type_with_dash [String] type- + # @param http_debug_option [String] http debug option (to test parameter naming option) + # @return [Array<(nil, Integer, Hash)>] nil, response status code and response headers + def get_parameter_name_mapping_with_http_info(underscore_type : Int64, _type : String, type_with_underscore : String, type_with_dash : String, http_debug_option : String) + if @api_client.config.debugging + Log.debug {"Calling API: FakeApi.get_parameter_name_mapping ..."} + end + # verify the required parameter "underscore_type" is set + if @api_client.config.client_side_validation && underscore_type.nil? + raise ArgumentError.new("Missing the required parameter 'underscore_type' when calling FakeApi.get_parameter_name_mapping") + end + # verify the required parameter "_type" is set + if @api_client.config.client_side_validation && _type.nil? + raise ArgumentError.new("Missing the required parameter '_type' when calling FakeApi.get_parameter_name_mapping") + end + # verify the required parameter "type_with_underscore" is set + if @api_client.config.client_side_validation && type_with_underscore.nil? + raise ArgumentError.new("Missing the required parameter 'type_with_underscore' when calling FakeApi.get_parameter_name_mapping") + end + # verify the required parameter "type_with_dash" is set + if @api_client.config.client_side_validation && type_with_dash.nil? + raise ArgumentError.new("Missing the required parameter 'type_with_dash' when calling FakeApi.get_parameter_name_mapping") + end + # verify the required parameter "http_debug_option" is set + if @api_client.config.client_side_validation && http_debug_option.nil? + raise ArgumentError.new("Missing the required parameter 'http_debug_option' when calling FakeApi.get_parameter_name_mapping") + end + # resource path + local_var_path = "/fake/parameter-name-mapping" + + # query parameters + query_params = Hash(String, String).new + query_params["type"] = _type.to_s unless _type.nil? + query_params["http_debug_option"] = http_debug_option.to_s unless http_debug_option.nil? + + # header parameters + header_params = Hash(String, String).new + header_params["_type"] = underscore_type + header_params["type_"] = type_with_underscore + header_params["type-"] = type_with_dash + + # form parameters + form_params = Hash(Symbol, (String | ::File)).new + + # http body (model) + post_body = nil + + # return_type + return_type = nil + + # auth_names + auth_names = [] of String + + data, status_code, headers = @api_client.call_api(:GET, + local_var_path, + :"FakeApi.get_parameter_name_mapping", + return_type, + post_body, + auth_names, + header_params, + query_params, + form_params) + if @api_client.config.debugging + Log.debug {"API called: FakeApi#get_parameter_name_mapping\nData: #{data.inspect}\nStatus code: #{status_code}\nHeaders: #{headers}"} + end + return nil, status_code, headers + end + end +end diff --git a/samples/client/petstore/crystal/src/petstore/models/another_property_name_mapping.cr b/samples/client/petstore/crystal/src/petstore/models/another_property_name_mapping.cr new file mode 100644 index 00000000000..19361be3efc --- /dev/null +++ b/samples/client/petstore/crystal/src/petstore/models/another_property_name_mapping.cr @@ -0,0 +1,193 @@ +# #OpenAPI Petstore +# +##This is a sample server Petstore server. For this sample, you can use the api key `special-key` to test the authorization filters. +# +#The version of the OpenAPI document: 1.0.0 +# +#Generated by: https://openapi-generator.tech +#OpenAPI Generator version: 7.0.0-SNAPSHOT +# + +require "big" +require "json" +require "time" + +module Petstore + class AnotherPropertyNameMapping + include JSON::Serializable + + # Optional properties + @[JSON::Field(key: "http_debug_operation", type: String?, nillable: true, emit_null: false)] + property http_debug_operation : String? + + @[JSON::Field(key: "_type", type: String?, nillable: true, emit_null: false)] + property underscore_type : String? + + @[JSON::Field(key: "type", type: String?, nillable: true, emit_null: false)] + property _type : String? + + @[JSON::Field(key: "type_", type: String?, nillable: true, emit_null: false)] + property type_with_underscore : String? + + # Initializes the object + # @param [Hash] attributes Model attributes in the form of hash + def initialize(@http_debug_operation : String?, @underscore_type : String?, @_type : String?, @type_with_underscore : String?) + end + + # Show invalid properties with the reasons. Usually used together with valid? + # @return Array for valid properties with the reasons + def list_invalid_properties + invalid_properties = Array(String).new + invalid_properties + end + + # Check to see if the all the properties in the model are valid + # @return true if the model is valid + def valid? + true + end + + # Checks equality by comparing each attribute. + # @param [Object] Object to be compared + def ==(o) + return true if self.same?(o) + self.class == o.class && + http_debug_operation == o.http_debug_operation && + underscore_type == o.underscore_type && + _type == o._type && + type_with_underscore == o.type_with_underscore + end + + # @see the `==` method + # @param [Object] Object to be compared + def eql?(o) + self == o + end + + # Calculates hash code according to all attributes. + # @return [Integer] Hash code + def hash + [http_debug_operation, underscore_type, _type, type_with_underscore].hash + end + + # Builds the object from hash + # @param [Hash] attributes Model attributes in the form of hash + # @return [Object] Returns the model itself + def self.build_from_hash(attributes) + new.build_from_hash(attributes) + end + + # Builds the object from hash + # @param [Hash] attributes Model attributes in the form of hash + # @return [Object] Returns the model itself + def build_from_hash(attributes) + return nil unless attributes.is_a?(Hash) + self.class.openapi_types.each_pair do |key, type| + if !attributes[self.class.attribute_map[key]]? && self.class.openapi_nullable.includes?(key) + self.send("#{key}=", nil) + elsif type =~ /\AArray<(.*)>/i + # check to ensure the input is an array given that the attribute + # is documented as an array but the input is not + if attributes[self.class.attribute_map[key]].is_a?(Array) + self.send("#{key}=", attributes[self.class.attribute_map[key]].map { |v| _deserialize($1, v) }) + end + elsif !attributes[self.class.attribute_map[key]].nil? + self.send("#{key}=", _deserialize(type, attributes[self.class.attribute_map[key]])) + end + end + + self + end + + # Deserializes the data based on type + # @param string type Data type + # @param string value Value to be deserialized + # @return [Object] Deserialized data + def _deserialize(type, value) + case type.to_sym + when :Time + Time.parse(value) + when :Date + Date.parse(value) + when :String + value.to_s + when :Integer + value.to_i + when :Float + value.to_f + when :Boolean + if value.to_s =~ /\A(true|t|yes|y|1)\z/i + true + else + false + end + when :Object + # generic object (usually a Hash), return directly + value + when /\AArray<(?.+)>\z/ + inner_type = Regexp.last_match[:inner_type] + value.map { |v| _deserialize(inner_type, v) } + when /\AHash<(?.+?), (?.+)>\z/ + k_type = Regexp.last_match[:k_type] + v_type = Regexp.last_match[:v_type] + ({} of Symbol => String).tap do |hash| + value.each do |k, v| + hash[_deserialize(k_type, k)] = _deserialize(v_type, v) + end + end + else # model + # models (e.g. Pet) or oneOf + klass = Petstore.const_get(type) + klass.respond_to?(:openapi_one_of) ? klass.build(value) : klass.build_from_hash(value) + end + end + + # Returns the string representation of the object + # @return [String] String presentation of the object + def to_s + to_hash.to_s + end + + # to_body is an alias to to_hash (backward compatibility) + # @return [Hash] Returns the object in the form of hash + def to_body + to_hash + end + + # Returns the object in the form of hash + # @return [Hash] Returns the object in the form of hash + def to_hash + hash = {} of Symbol => String + self.class.attribute_map.each_pair do |attr, param| + value = self.send(attr) + if value.nil? + is_nullable = self.class.openapi_nullable.includes?(attr) + next if !is_nullable || (is_nullable && !instance_variable_defined?(:"@#{attr}")) + end + + hash[param] = _to_hash(value) + end + hash + end + + # Outputs non-array value in the form of hash + # For object, use to_hash. Otherwise, just return the value + # @param [Object] value Any valid value + # @return [Hash] Returns the value in the form of hash + def _to_hash(value) + if value.is_a?(Array) + value.compact.map { |v| _to_hash(v) } + elsif value.is_a?(Hash) + ({} of Symbol => String).tap do |hash| + value.each { |k, v| hash[k] = _to_hash(v) } + end + elsif value.respond_to? :to_hash + value.to_hash + else + value + end + end + + end + +end