diff --git a/generators/src/main/java/com/algolia/codegen/AlgoliaCSharpGenerator.java b/generators/src/main/java/com/algolia/codegen/AlgoliaCSharpGenerator.java index 2fed33ae9b..06cfdb53e6 100644 --- a/generators/src/main/java/com/algolia/codegen/AlgoliaCSharpGenerator.java +++ b/generators/src/main/java/com/algolia/codegen/AlgoliaCSharpGenerator.java @@ -2,7 +2,6 @@ import com.algolia.codegen.exceptions.*; import com.algolia.codegen.utils.*; -import com.algolia.codegen.utils.OneOf; import com.samskivert.mustache.Mustache; import io.swagger.v3.oas.models.OpenAPI; import io.swagger.v3.oas.models.Operation; @@ -142,6 +141,7 @@ public void processOpenAPI(OpenAPI openAPI) { @Override public OperationsMap postProcessOperationsWithModels(OperationsMap objs, List models) { OperationsMap operations = super.postProcessOperationsWithModels(objs, models); + ModelPruner.removeOrphans(this, operations, models); Helpers.removeHelpers(operations); GenericPropagator.propagateGenericsToOperations(operations, models); return operations; diff --git a/generators/src/main/java/com/algolia/codegen/AlgoliaGoGenerator.java b/generators/src/main/java/com/algolia/codegen/AlgoliaGoGenerator.java index 6673768ca0..aad528b487 100644 --- a/generators/src/main/java/com/algolia/codegen/AlgoliaGoGenerator.java +++ b/generators/src/main/java/com/algolia/codegen/AlgoliaGoGenerator.java @@ -3,7 +3,6 @@ import com.algolia.codegen.exceptions.*; import com.algolia.codegen.lambda.ScreamingSnakeCaseLambda; import com.algolia.codegen.utils.*; -import com.algolia.codegen.utils.OneOf; import com.google.common.collect.ImmutableMap; import com.google.common.collect.Iterables; import com.samskivert.mustache.Mustache; @@ -44,6 +43,8 @@ public void processOpts() { typeMapping.put("object", "map[string]any"); typeMapping.put("AnyType", "any"); + modelNameMapping.put("range", "modelRange"); + apiTestTemplateFiles.clear(); modelTestTemplateFiles.clear(); apiDocTemplateFiles.clear(); @@ -132,6 +133,7 @@ public Map postProcessAllModels(Map objs) @Override public OperationsMap postProcessOperationsWithModels(OperationsMap objs, List models) { OperationsMap operations = super.postProcessOperationsWithModels(objs, models); + ModelPruner.removeOrphans(this, operations, models, true); Helpers.removeHelpers(operations); GenericPropagator.propagateGenericsToOperations(operations, models); return operations; diff --git a/generators/src/main/java/com/algolia/codegen/AlgoliaJavaGenerator.java b/generators/src/main/java/com/algolia/codegen/AlgoliaJavaGenerator.java index becdb89dd5..17cdd32fa4 100644 --- a/generators/src/main/java/com/algolia/codegen/AlgoliaJavaGenerator.java +++ b/generators/src/main/java/com/algolia/codegen/AlgoliaJavaGenerator.java @@ -2,7 +2,6 @@ import com.algolia.codegen.exceptions.*; import com.algolia.codegen.utils.*; -import com.algolia.codegen.utils.OneOf; import com.google.common.collect.ImmutableMap.Builder; import com.samskivert.mustache.Mustache; import com.samskivert.mustache.Mustache.Lambda; @@ -96,6 +95,7 @@ public Map postProcessAllModels(Map objs) @Override public OperationsMap postProcessOperationsWithModels(OperationsMap objs, List models) { OperationsMap operations = super.postProcessOperationsWithModels(objs, models); + ModelPruner.removeOrphans(this, operations, models); Helpers.removeHelpers(operations); GenericPropagator.propagateGenericsToOperations(operations, models); return operations; diff --git a/generators/src/main/java/com/algolia/codegen/AlgoliaKotlinGenerator.java b/generators/src/main/java/com/algolia/codegen/AlgoliaKotlinGenerator.java index 17547ef08c..74fd6e90c0 100644 --- a/generators/src/main/java/com/algolia/codegen/AlgoliaKotlinGenerator.java +++ b/generators/src/main/java/com/algolia/codegen/AlgoliaKotlinGenerator.java @@ -1,7 +1,6 @@ package com.algolia.codegen; import com.algolia.codegen.utils.*; -import com.algolia.codegen.utils.OneOf; import com.samskivert.mustache.Mustache; import io.swagger.v3.oas.models.OpenAPI; import io.swagger.v3.oas.models.Operation; @@ -188,6 +187,7 @@ private static void jsonParent(Map models) { @Override public OperationsMap postProcessOperationsWithModels(OperationsMap objs, List models) { OperationsMap operations = super.postProcessOperationsWithModels(objs, models); + ModelPruner.removeOrphans(this, operations, models); Helpers.removeHelpers(operations); GenericPropagator.propagateGenericsToOperations(operations, models); return operations; diff --git a/generators/src/main/java/com/algolia/codegen/AlgoliaPhpGenerator.java b/generators/src/main/java/com/algolia/codegen/AlgoliaPhpGenerator.java index 8646d66496..5acde700d5 100644 --- a/generators/src/main/java/com/algolia/codegen/AlgoliaPhpGenerator.java +++ b/generators/src/main/java/com/algolia/codegen/AlgoliaPhpGenerator.java @@ -77,6 +77,7 @@ public CodegenOperation fromOperation(String path, String httpMethod, Operation @Override public OperationsMap postProcessOperationsWithModels(OperationsMap objs, List models) { OperationsMap operations = super.postProcessOperationsWithModels(objs, models); + ModelPruner.removeOrphans(this, operations, models); Helpers.removeHelpers(operations); return operations; } diff --git a/generators/src/main/java/com/algolia/codegen/AlgoliaPythonGenerator.java b/generators/src/main/java/com/algolia/codegen/AlgoliaPythonGenerator.java index b5b8794331..1cdae97116 100644 --- a/generators/src/main/java/com/algolia/codegen/AlgoliaPythonGenerator.java +++ b/generators/src/main/java/com/algolia/codegen/AlgoliaPythonGenerator.java @@ -120,6 +120,7 @@ public CodegenOperation fromOperation(String path, String httpMethod, Operation @Override public OperationsMap postProcessOperationsWithModels(OperationsMap objs, List models) { OperationsMap operations = super.postProcessOperationsWithModels(objs, models); + ModelPruner.removeOrphans(this, operations, models); Helpers.removeHelpers(operations); List> imports = operations.getImports(); diff --git a/generators/src/main/java/com/algolia/codegen/AlgoliaRubyGenerator.java b/generators/src/main/java/com/algolia/codegen/AlgoliaRubyGenerator.java index a154828b5e..f8fa44178c 100644 --- a/generators/src/main/java/com/algolia/codegen/AlgoliaRubyGenerator.java +++ b/generators/src/main/java/com/algolia/codegen/AlgoliaRubyGenerator.java @@ -82,6 +82,7 @@ public CodegenOperation fromOperation(String path, String httpMethod, Operation @Override public OperationsMap postProcessOperationsWithModels(OperationsMap objs, List models) { OperationsMap operations = super.postProcessOperationsWithModels(objs, models); + ModelPruner.removeOrphans(this, operations, models); Helpers.removeHelpers(operations); return operations; } diff --git a/generators/src/main/java/com/algolia/codegen/AlgoliaSwiftGenerator.java b/generators/src/main/java/com/algolia/codegen/AlgoliaSwiftGenerator.java index dc9203af2f..fe2dd01b3f 100644 --- a/generators/src/main/java/com/algolia/codegen/AlgoliaSwiftGenerator.java +++ b/generators/src/main/java/com/algolia/codegen/AlgoliaSwiftGenerator.java @@ -4,9 +4,7 @@ import static org.openapitools.codegen.utils.StringUtils.camelize; import com.algolia.codegen.exceptions.*; -import com.algolia.codegen.utils.GenericPropagator; -import com.algolia.codegen.utils.Helpers; -import com.algolia.codegen.utils.OneOf; +import com.algolia.codegen.utils.*; import com.samskivert.mustache.Mustache; import io.swagger.v3.oas.models.OpenAPI; import io.swagger.v3.oas.models.Operation; diff --git a/generators/src/main/java/com/algolia/codegen/utils/GenericPropagator.java b/generators/src/main/java/com/algolia/codegen/utils/GenericPropagator.java index fa2ca74f1c..b2cfa40302 100644 --- a/generators/src/main/java/com/algolia/codegen/utils/GenericPropagator.java +++ b/generators/src/main/java/com/algolia/codegen/utils/GenericPropagator.java @@ -9,8 +9,6 @@ public class GenericPropagator { - public String language; - private static Set primitiveModels = new HashSet<>(Arrays.asList("object", "array", "string", "boolean", "integer")); // Only static use of this class @@ -189,6 +187,10 @@ public static void propagateGenericsToModels(Map modelsMap, b } } + public static void propagateGenericsToModels(Map modelsMap) { + propagateGenericsToModels(modelsMap, false); + } + /** Mark operations with a generic return type with x-is-generic */ public static void propagateGenericsToOperations(OperationsMap operations, List allModels) { Map models = convertToMap(allModels); @@ -207,8 +209,4 @@ public static void propagateGenericsToOperations(OperationsMap operations, List< } } } - - public static void propagateGenericsToModels(Map modelsMap) { - propagateGenericsToModels(modelsMap, false); - } } diff --git a/generators/src/main/java/com/algolia/codegen/utils/ModelPruner.java b/generators/src/main/java/com/algolia/codegen/utils/ModelPruner.java new file mode 100644 index 0000000000..4317bfc1f2 --- /dev/null +++ b/generators/src/main/java/com/algolia/codegen/utils/ModelPruner.java @@ -0,0 +1,132 @@ +package com.algolia.codegen.utils; + +import java.io.File; +import java.util.*; +import org.openapitools.codegen.*; +import org.openapitools.codegen.model.ModelMap; +import org.openapitools.codegen.model.OperationsMap; + +public class ModelPruner { + + private static Set primitiveModels = new HashSet<>(Arrays.asList("object", "array", "string", "boolean", "integer")); + + private Map models; + private Set visitedModels; + + private ModelPruner(Map models) { + this.visitedModels = new TreeSet<>(String.CASE_INSENSITIVE_ORDER); + this.models = models; + } + + private CodegenModel getModel(String name) { + name = name.replace("?", ""); + // openapi generator returns some weird error when looking for primitive type, so we filter them + // by hand + if (primitiveModels.contains(name)) { + return null; + } + + return models.get(name); + } + + private CodegenModel propertyToModel(CodegenProperty prop) { + return prop == null ? null : getModel(prop.openApiType); + } + + private void exploreProperties(CodegenModel model, List properties) { + for (CodegenProperty property : properties) { + CodegenModel propModel = propertyToModel(property); + if (propModel != null && !visitedModels.contains(propModel.name)) { + visitedModels.add(property.openApiType); + visitedModels.add(propModel.name); + visitModelRecursive(propModel); + } + CodegenModel itemsModel = propertyToModel(property.mostInnerItems); + if (itemsModel != null && !visitedModels.contains(itemsModel.name)) { + // In csharp the real model name varies if its part of the modelMapping so we have to add + // both + visitedModels.add(property.mostInnerItems.openApiType); + visitedModels.add(itemsModel.name); + visitModelRecursive(itemsModel); + } + } + } + + private void visitModelRecursive(CodegenModel model) { + exploreProperties(model, model.getVars()); + if (model.getComposedSchemas() != null && model.getComposedSchemas().getOneOf() != null) { + exploreProperties(model, model.getComposedSchemas().getOneOf()); + } + } + + private static Map convertToMap(CodegenConfig config, List models) { + Map modelsMap = new TreeMap<>(String.CASE_INSENSITIVE_ORDER); + for (ModelMap modelMap : models) { + CodegenModel model = modelMap.getModel(); + + modelsMap.put(config.toModelName(model.name), model); + } + return modelsMap; + } + + private void exploreGraph(OperationsMap operations) { + for (CodegenModel model : models.values()) { + visitModelRecursive(model); + } + + for (CodegenOperation ope : operations.getOperations().getOperation()) { + if (ope.returnType != null) { + CodegenModel returnType = getModel(ope.returnBaseType); + if (returnType != null) { + visitedModels.add(returnType.name); + } + } + for (CodegenParameter param : ope.allParams) { + CodegenModel paramType = getModel(param.baseType != null ? param.baseType : param.dataType); + if (paramType != null) { + visitedModels.add(paramType.name); + } + CodegenModel itemsModel = propertyToModel(param.mostInnerItems); + if (itemsModel != null) { + visitedModels.add(itemsModel.name); + } + } + } + } + + /** remove all the unused models, most likely the sub models of allOf */ + public static void removeOrphans(CodegenConfig config, OperationsMap operations, List allModels, boolean keepError) { + // visit all the models that are accessible from: + // - the properties of a model (needs recursive search) + // - the return type of an operation + // - the parameters of an operation + + ModelPruner modelPruner = new ModelPruner(convertToMap(config, allModels)); + Helpers.prettyPrint(modelPruner.models.keySet()); + modelPruner.exploreGraph(operations); + + List toRemove = new ArrayList<>(); + for (String modelName : modelPruner.models.keySet()) { + if (keepError && modelName.equals("ErrorBase")) { + continue; + } + if (!modelPruner.visitedModels.contains(modelName)) { + toRemove.add(modelName); + } + } + + String templateName = config.modelTemplateFiles().keySet().iterator().next(); + + for (String modelName : toRemove) { + String filename = config.modelFilename(templateName, modelName); + File file = new File(filename); + if (file.exists()) { + file.delete(); + } + } + } + + public static void removeOrphans(CodegenConfig config, OperationsMap operations, List allModels) { + removeOrphans(config, operations, allModels, false); + } +}