From 31fc0a31a02679edaccb2830ad98b0103800dafe Mon Sep 17 00:00:00 2001 From: Benjamin Douglas Date: Sun, 24 Sep 2017 20:37:41 -0700 Subject: [PATCH] Pre-calculate type aliases before processing models A type alias in this context is where a model is simply another name for a primitive type, such as `MyString` in the following model definitions: MyList: type: array items: $ref: '#/definitions/MyString' MyString: type: string It is valid to use a type alias as a property in another object or array model, even if the object/array is defined before the alias is, as in the example above. However, the current alias logic only looks "back" in list of previously defined models, meaning that `MyList` would not know that `MyString` is an alias. This change fixes the incorrect behavior by pre-calculating the list of aliases before any models are processed. It also changes the test endpoint to verify the correct behavior even when an object is defined before an alias it uses. --- .../io/swagger/codegen/DefaultCodegen.java | 36 ++++++++++++++++--- .../languages/AbstractJavaCodegen.java | 2 +- ...ith-fake-endpoints-models-for-testing.yaml | 12 +++---- 3 files changed, 38 insertions(+), 12 deletions(-) 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 61a4dc1ba61..3999ae6ac5e 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 @@ -119,7 +119,7 @@ public class DefaultCodegen { // Then translated back during JSON encoding and decoding protected Map specialCharReplacements = new HashMap(); // When a model is an alias for a simple type - protected Map typeAliases = new HashMap<>(); + protected Map typeAliases = null; protected String ignoreFilePathOverride; @@ -1312,6 +1312,10 @@ public CodegenModel fromModel(String name, Model model) { * @return Codegen Model object */ public CodegenModel fromModel(String name, Model model, Map allDefinitions) { + if (typeAliases == null) { + // Only do this once during first call + typeAliases = getAllAliases(allDefinitions); + } CodegenModel m = CodegenModelFactory.newInstance(CodegenModelType.MODEL); if (reservedWords.contains(name)) { m.name = escapeReservedWord(name); @@ -1327,6 +1331,7 @@ public CodegenModel fromModel(String name, Model model, Map allDe m.modelJson = Json.pretty(model); m.externalDocs = model.getExternalDocs(); m.vendorExtensions = model.getVendorExtensions(); + m.isAlias = typeAliases.containsKey(name); if (model instanceof ModelImpl) { ModelImpl modelImpl = (ModelImpl) model; @@ -1444,10 +1449,6 @@ public CodegenModel fromModel(String name, Model model, Map allDe ModelImpl impl = (ModelImpl) model; if (impl.getType() != null) { Property p = PropertyBuilder.build(impl.getType(), impl.getFormat(), null); - if (!impl.getType().equals("object") && impl.getEnum() == null) { - typeAliases.put(name, impl.getType()); - m.isAlias = true; - } m.dataType = getSwaggerType(p); } if(impl.getEnum() != null && impl.getEnum().size() > 0) { @@ -3166,6 +3167,31 @@ private void addVars(CodegenModel m, List vars, Map getAllAliases(Map allDefinitions) { + Map aliases = new HashMap<>(); + if (allDefinitions != null) { + for (Map.Entry entry : allDefinitions.entrySet()) { + String swaggerName = entry.getKey(); + Model m = entry.getValue(); + if (m instanceof ModelImpl) { + ModelImpl impl = (ModelImpl) m; + if (impl.getType() != null && + !impl.getType().equals("object") && + impl.getEnum() == null) { + aliases.put(swaggerName, impl.getType()); + } + } + } + } + return aliases; + } + /** * Remove characters not suitable for variable or method name from the input and camelize it * diff --git a/modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/AbstractJavaCodegen.java b/modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/AbstractJavaCodegen.java index 13310ecc5c3..2d471bf6207 100644 --- a/modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/AbstractJavaCodegen.java +++ b/modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/AbstractJavaCodegen.java @@ -619,7 +619,7 @@ public String getTypeDeclaration(Property p) { @Override public String getAlias(String name) { - if (typeAliases.containsKey(name)) { + if (typeAliases != null && typeAliases.containsKey(name)) { return typeAliases.get(name); } return name; diff --git a/modules/swagger-codegen/src/test/resources/2_0/petstore-with-fake-endpoints-models-for-testing.yaml b/modules/swagger-codegen/src/test/resources/2_0/petstore-with-fake-endpoints-models-for-testing.yaml index 19db9dcbf51..059a5ef4980 100644 --- a/modules/swagger-codegen/src/test/resources/2_0/petstore-with-fake-endpoints-models-for-testing.yaml +++ b/modules/swagger-codegen/src/test/resources/2_0/petstore-with-fake-endpoints-models-for-testing.yaml @@ -1402,12 +1402,6 @@ definitions: - "placed" - "approved" - "delivered" - OuterNumber: - type: number - OuterString: - type: string - OuterBoolean: - type: boolean OuterComposite: type: object properties: @@ -1417,6 +1411,12 @@ definitions: $ref: '#/definitions/OuterString' my_boolean: $ref: '#/definitions/OuterBoolean' + OuterNumber: + type: number + OuterString: + type: string + OuterBoolean: + type: boolean externalDocs: description: Find out more about Swagger url: 'http://swagger.io'