Skip to content

Commit

Permalink
feat(clients): delete unused models (#3445)
Browse files Browse the repository at this point in the history
  • Loading branch information
millotp committed Jul 30, 2024
1 parent 56b0b8e commit 41d86ce
Show file tree
Hide file tree
Showing 10 changed files with 146 additions and 13 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -142,6 +141,7 @@ public void processOpenAPI(OpenAPI openAPI) {
@Override
public OperationsMap postProcessOperationsWithModels(OperationsMap objs, List<ModelMap> models) {
OperationsMap operations = super.postProcessOperationsWithModels(objs, models);
ModelPruner.removeOrphans(this, operations, models);
Helpers.removeHelpers(operations);
GenericPropagator.propagateGenericsToOperations(operations, models);
return operations;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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();
Expand Down Expand Up @@ -132,6 +133,7 @@ public Map<String, ModelsMap> postProcessAllModels(Map<String, ModelsMap> objs)
@Override
public OperationsMap postProcessOperationsWithModels(OperationsMap objs, List<ModelMap> models) {
OperationsMap operations = super.postProcessOperationsWithModels(objs, models);
ModelPruner.removeOrphans(this, operations, models, true);
Helpers.removeHelpers(operations);
GenericPropagator.propagateGenericsToOperations(operations, models);
return operations;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -96,6 +95,7 @@ public Map<String, ModelsMap> postProcessAllModels(Map<String, ModelsMap> objs)
@Override
public OperationsMap postProcessOperationsWithModels(OperationsMap objs, List<ModelMap> models) {
OperationsMap operations = super.postProcessOperationsWithModels(objs, models);
ModelPruner.removeOrphans(this, operations, models);
Helpers.removeHelpers(operations);
GenericPropagator.propagateGenericsToOperations(operations, models);
return operations;
Expand Down
Original file line number Diff line number Diff line change
@@ -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;
Expand Down Expand Up @@ -188,6 +187,7 @@ private static void jsonParent(Map<String, ModelsMap> models) {
@Override
public OperationsMap postProcessOperationsWithModels(OperationsMap objs, List<ModelMap> models) {
OperationsMap operations = super.postProcessOperationsWithModels(objs, models);
ModelPruner.removeOrphans(this, operations, models);
Helpers.removeHelpers(operations);
GenericPropagator.propagateGenericsToOperations(operations, models);
return operations;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@ public CodegenOperation fromOperation(String path, String httpMethod, Operation
@Override
public OperationsMap postProcessOperationsWithModels(OperationsMap objs, List<ModelMap> models) {
OperationsMap operations = super.postProcessOperationsWithModels(objs, models);
ModelPruner.removeOrphans(this, operations, models);
Helpers.removeHelpers(operations);
return operations;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,7 @@ public CodegenOperation fromOperation(String path, String httpMethod, Operation
@Override
public OperationsMap postProcessOperationsWithModels(OperationsMap objs, List<ModelMap> models) {
OperationsMap operations = super.postProcessOperationsWithModels(objs, models);
ModelPruner.removeOrphans(this, operations, models);
Helpers.removeHelpers(operations);

List<Map<String, String>> imports = operations.getImports();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,7 @@ public CodegenOperation fromOperation(String path, String httpMethod, Operation
@Override
public OperationsMap postProcessOperationsWithModels(OperationsMap objs, List<ModelMap> models) {
OperationsMap operations = super.postProcessOperationsWithModels(objs, models);
ModelPruner.removeOrphans(this, operations, models);
Helpers.removeHelpers(operations);
return operations;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,6 @@

public class GenericPropagator {

public String language;

private static Set<String> primitiveModels = new HashSet<>(Arrays.asList("object", "array", "string", "boolean", "integer"));

// Only static use of this class
Expand Down Expand Up @@ -189,6 +187,10 @@ public static void propagateGenericsToModels(Map<String, ModelsMap> modelsMap, b
}
}

public static void propagateGenericsToModels(Map<String, ModelsMap> modelsMap) {
propagateGenericsToModels(modelsMap, false);
}

/** Mark operations with a generic return type with x-is-generic */
public static void propagateGenericsToOperations(OperationsMap operations, List<ModelMap> allModels) {
Map<String, CodegenModel> models = convertToMap(allModels);
Expand All @@ -207,8 +209,4 @@ public static void propagateGenericsToOperations(OperationsMap operations, List<
}
}
}

public static void propagateGenericsToModels(Map<String, ModelsMap> modelsMap) {
propagateGenericsToModels(modelsMap, false);
}
}
132 changes: 132 additions & 0 deletions generators/src/main/java/com/algolia/codegen/utils/ModelPruner.java
Original file line number Diff line number Diff line change
@@ -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<String> primitiveModels = new HashSet<>(Arrays.asList("object", "array", "string", "boolean", "integer"));

private Map<String, CodegenModel> models;
private Set<String> visitedModels;

private ModelPruner(Map<String, CodegenModel> 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<CodegenProperty> 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<String, CodegenModel> convertToMap(CodegenConfig config, List<ModelMap> models) {
Map<String, CodegenModel> 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<ModelMap> 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<String> 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<ModelMap> allModels) {
removeOrphans(config, operations, allModels, false);
}
}

0 comments on commit 41d86ce

Please sign in to comment.