forked from loafle/openapi-generator-original
Add additional cli option and properties to swift3 for Objective-C compatibility. (#6129)
Currently, in the swift3 language, if you have an optional integer, number, or boolean property in a model, then the generated swift3 model class might look like: class SomeModel { var someInt: Int? var someFloat: Float? var someDouble: Double? var someBool: Bool? } This works fine if you are accessing this model only from Swift code. However, it is very common for iOS codebases to contain both Swift AND Objective-C. If you need to access this model from Objective-C, then those 4 properties are not accessible, since Optional scalars do not translate to Objective-C. Therefore, in the swift3 language, we want to add some code for Objective-C compatibility: 1. We add a "objCompatible" boolean command-line option. If objCompatible=true, then this enables some additional code generation to make these types of properties accessible from Objective-C. If objCompatible=false, then the generated code is exactly as it currently is. The default is objcCopmatible=false. 2. If objCompatible=true, then for these types of Objective-C-inaccessible properties (Optional scalars), then we add a "x-swift-optional-scalar=true" vendor extension in the CodegenProperty. 3. Then, in the model.mustache template, if we see x-swift-optional-scalar=true, then we add an additional computed property which returns an optional NSNumber. So, for example, when objcCompatible=false (the default case), then the generated code for the "declawed" property of the Cat model looks like: open class Cat: Animal { public var declawed: Bool? ... But when objcCompatible=true, then it looks like: open class Cat: Animal { public var declawed: Bool? public var declawedNum: NSNumber? { get { return declawed.map({ return NSNumber(value: $0) }) } } ...
This commit is contained in:
parent
218273e9a8
commit
dd46ba9ef6
7
bin/swift3-petstore-objcCompatible.json
Normal file
7
bin/swift3-petstore-objcCompatible.json
Normal file
@ -0,0 +1,7 @@
|
||||
{
|
||||
"podSummary": "PetstoreClient",
|
||||
"podHomepage": "https://github.com/swagger-api/swagger-codegen",
|
||||
"podAuthors": "",
|
||||
"projectName": "PetstoreClient",
|
||||
"objcCompatible": true
|
||||
}
|
31
bin/swift3-petstore-objcCompatible.sh
Executable file
31
bin/swift3-petstore-objcCompatible.sh
Executable file
@ -0,0 +1,31 @@
|
||||
#!/bin/sh
|
||||
|
||||
SCRIPT="$0"
|
||||
|
||||
while [ -h "$SCRIPT" ] ; do
|
||||
ls=`ls -ld "$SCRIPT"`
|
||||
link=`expr "$ls" : '.*-> \(.*\)$'`
|
||||
if expr "$link" : '/.*' > /dev/null; then
|
||||
SCRIPT="$link"
|
||||
else
|
||||
SCRIPT=`dirname "$SCRIPT"`/"$link"
|
||||
fi
|
||||
done
|
||||
|
||||
if [ ! -d "${APP_DIR}" ]; then
|
||||
APP_DIR=`dirname "$SCRIPT"`/..
|
||||
APP_DIR=`cd "${APP_DIR}"; pwd`
|
||||
fi
|
||||
|
||||
executable="./modules/swagger-codegen-cli/target/swagger-codegen-cli.jar"
|
||||
|
||||
if [ ! -f "$executable" ]
|
||||
then
|
||||
mvn clean package
|
||||
fi
|
||||
|
||||
# if you've executed sbt assembly previously it will use that instead.
|
||||
export JAVA_OPTS="${JAVA_OPTS} -XX:MaxPermSize=256M -Xmx1024M -DloggerPath=conf/log4j.properties"
|
||||
ags="generate -v -t modules/swagger-codegen/src/main/resources/swift3 -i modules/swagger-codegen/src/test/resources/2_0/petstore-with-fake-endpoints-models-for-testing.yaml -l swift3 -c ./bin/swift3-petstore-objcCompatible.json -o samples/client/petstore/swift3/objcCompatible $@"
|
||||
|
||||
java $JAVA_OPTS -jar $executable $ags
|
@ -27,6 +27,7 @@ public class Swift3Codegen extends DefaultCodegen implements CodegenConfig {
|
||||
public static final String PROJECT_NAME = "projectName";
|
||||
public static final String RESPONSE_AS = "responseAs";
|
||||
public static final String UNWRAP_REQUIRED = "unwrapRequired";
|
||||
public static final String OBJC_COMPATIBLE = "objcCompatible";
|
||||
public static final String POD_SOURCE = "podSource";
|
||||
public static final String POD_AUTHORS = "podAuthors";
|
||||
public static final String POD_SOCIAL_MEDIA_URL = "podSocialMediaURL";
|
||||
@ -45,6 +46,7 @@ public class Swift3Codegen extends DefaultCodegen implements CodegenConfig {
|
||||
protected static final String[] RESPONSE_LIBRARIES = {LIBRARY_PROMISE_KIT, LIBRARY_RX_SWIFT};
|
||||
protected String projectName = "SwaggerClient";
|
||||
protected boolean unwrapRequired;
|
||||
protected boolean objcCompatible = false;
|
||||
protected boolean lenientTypeCast = false;
|
||||
protected boolean swiftUseApiNamespace;
|
||||
protected String[] responseAs = new String[0];
|
||||
@ -158,6 +160,7 @@ public class Swift3Codegen extends DefaultCodegen implements CodegenConfig {
|
||||
StringUtils.join(RESPONSE_LIBRARIES, ", ") + " are available."));
|
||||
cliOptions.add(new CliOption(UNWRAP_REQUIRED, "Treat 'required' properties in response as non-optional " +
|
||||
"(which would crash the app if api returns null as opposed to required option specified in json schema"));
|
||||
cliOptions.add(new CliOption(OBJC_COMPATIBLE, "Add additional properties and methods for Objective-C compatibility (default: false)"));
|
||||
cliOptions.add(new CliOption(POD_SOURCE, "Source information used for Podspec"));
|
||||
cliOptions.add(new CliOption(CodegenConstants.POD_VERSION, "Version used for Podspec"));
|
||||
cliOptions.add(new CliOption(POD_AUTHORS, "Authors used for Podspec"));
|
||||
@ -202,6 +205,12 @@ public class Swift3Codegen extends DefaultCodegen implements CodegenConfig {
|
||||
}
|
||||
additionalProperties.put(UNWRAP_REQUIRED, unwrapRequired);
|
||||
|
||||
// Setup objcCompatible option, which adds additional properties and methods for Objective-C compatibility
|
||||
if (additionalProperties.containsKey(OBJC_COMPATIBLE)) {
|
||||
setObjcCompatible(convertPropertyToBooleanAndWriteBack(OBJC_COMPATIBLE));
|
||||
}
|
||||
additionalProperties.put(OBJC_COMPATIBLE, objcCompatible);
|
||||
|
||||
// Setup unwrapRequired option, which makes all the properties with "required" non-optional
|
||||
if (additionalProperties.containsKey(RESPONSE_AS)) {
|
||||
Object responseAsObject = additionalProperties.get(RESPONSE_AS);
|
||||
@ -479,6 +488,10 @@ public class Swift3Codegen extends DefaultCodegen implements CodegenConfig {
|
||||
this.unwrapRequired = unwrapRequired;
|
||||
}
|
||||
|
||||
public void setObjcCompatible(boolean objcCompatible) {
|
||||
this.objcCompatible = objcCompatible;
|
||||
}
|
||||
|
||||
public void setLenientTypeCast(boolean lenientTypeCast) {
|
||||
this.lenientTypeCast = lenientTypeCast;
|
||||
}
|
||||
@ -579,6 +592,31 @@ public class Swift3Codegen extends DefaultCodegen implements CodegenConfig {
|
||||
return postProcessModelsEnum(objs);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void postProcessModelProperty(CodegenModel model, CodegenProperty property) {
|
||||
super.postProcessModelProperty(model, property);
|
||||
|
||||
// The default template code has the following logic for assigning a type as Swift Optional:
|
||||
//
|
||||
// {{^unwrapRequired}}?{{/unwrapRequired}}{{#unwrapRequired}}{{^required}}?{{/required}}{{/unwrapRequired}}
|
||||
//
|
||||
// which means:
|
||||
//
|
||||
// boolean isSwiftOptional = !unwrapRequired || (unwrapRequired && !property.required);
|
||||
//
|
||||
// We can drop the check for unwrapRequired in (unwrapRequired && !property.required)
|
||||
// due to short-circuit evaluation of the || operator.
|
||||
boolean isSwiftOptional = !unwrapRequired || !property.required;
|
||||
boolean isSwiftScalarType = property.isInteger || property.isLong || property.isFloat || property.isDouble || property.isBoolean;
|
||||
if (isSwiftOptional && isSwiftScalarType) {
|
||||
// Optional scalar types like Int?, Int64?, Float?, Double?, and Bool?
|
||||
// do not translate to Objective-C. So we want to flag those
|
||||
// properties in case we want to put special code in the templates
|
||||
// which provide Objective-C compatibility.
|
||||
property.vendorExtensions.put("x-swift-optional-scalar", true);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String escapeQuotationMark(String input) {
|
||||
// remove " to avoid code injection
|
||||
|
@ -44,7 +44,12 @@ open class {{classname}}: {{#parent}}{{{parent}}}{{/parent}}{{^parent}}JSONEncod
|
||||
{{/isEnum}}
|
||||
{{^isEnum}}
|
||||
{{#description}}/** {{description}} */
|
||||
{{/description}}public var {{name}}: {{{datatype}}}{{^unwrapRequired}}?{{/unwrapRequired}}{{#unwrapRequired}}{{^required}}?{{/required}}{{/unwrapRequired}}{{#defaultValue}} = {{{defaultValue}}}{{/defaultValue}}
|
||||
{{/description}}public var {{name}}: {{{datatype}}}{{^unwrapRequired}}?{{/unwrapRequired}}{{#unwrapRequired}}{{^required}}?{{/required}}{{/unwrapRequired}}{{#defaultValue}} = {{{defaultValue}}}{{/defaultValue}}{{#objcCompatible}}{{#vendorExtensions.x-swift-optional-scalar}}
|
||||
public var {{name}}Num: NSNumber? {
|
||||
get {
|
||||
return {{name}}.map({ return NSNumber(value: $0) })
|
||||
}
|
||||
}{{/vendorExtensions.x-swift-optional-scalar}}{{/objcCompatible}}
|
||||
{{/isEnum}}
|
||||
{{/vars}}
|
||||
|
||||
|
@ -13,6 +13,7 @@ public class Swift3OptionsProvider implements OptionsProvider {
|
||||
public static final String PROJECT_NAME_VALUE = "Swagger";
|
||||
public static final String RESPONSE_AS_VALUE = "test";
|
||||
public static final String UNWRAP_REQUIRED_VALUE = "true";
|
||||
public static final String OBJC_COMPATIBLE_VALUE = "false";
|
||||
public static final String LENIENT_TYPE_CAST_VALUE = "false";
|
||||
public static final String POD_SOURCE_VALUE = "{ :git => 'git@github.com:swagger-api/swagger-mustache.git'," +
|
||||
" :tag => 'v1.0.0-SNAPSHOT' }";
|
||||
@ -42,6 +43,7 @@ public class Swift3OptionsProvider implements OptionsProvider {
|
||||
.put(Swift3Codegen.PROJECT_NAME, PROJECT_NAME_VALUE)
|
||||
.put(Swift3Codegen.RESPONSE_AS, RESPONSE_AS_VALUE)
|
||||
.put(Swift3Codegen.UNWRAP_REQUIRED, UNWRAP_REQUIRED_VALUE)
|
||||
.put(Swift3Codegen.OBJC_COMPATIBLE, OBJC_COMPATIBLE_VALUE)
|
||||
.put(Swift3Codegen.LENIENT_TYPE_CAST, LENIENT_TYPE_CAST_VALUE)
|
||||
.put(Swift3Codegen.POD_SOURCE, POD_SOURCE_VALUE)
|
||||
.put(CodegenConstants.POD_VERSION, POD_VERSION_VALUE)
|
||||
|
@ -33,6 +33,8 @@ public class Swift3OptionsTest extends AbstractOptionsTest {
|
||||
times = 1;
|
||||
clientCodegen.setUnwrapRequired(Boolean.valueOf(Swift3OptionsProvider.UNWRAP_REQUIRED_VALUE));
|
||||
times = 1;
|
||||
clientCodegen.setObjcCompatible(Boolean.valueOf(Swift3OptionsProvider.OBJC_COMPATIBLE_VALUE));
|
||||
times = 1;
|
||||
clientCodegen.setLenientTypeCast(Boolean.valueOf(Swift3OptionsProvider.LENIENT_TYPE_CAST_VALUE));
|
||||
times = 1;
|
||||
}};
|
||||
|
Loading…
x
Reference in New Issue
Block a user