Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(clients): delete unused models #3445

Merged
merged 9 commits into from
Jul 30, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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);
}
}
Loading