Skip to content

Commit

Permalink
- #557 - discard unused union types/inheritance types via config
Browse files Browse the repository at this point in the history
  • Loading branch information
kirides committed Jan 17, 2025
1 parent b16636a commit 5491fa9
Show file tree
Hide file tree
Showing 5 changed files with 63 additions and 13 deletions.
10 changes: 7 additions & 3 deletions src/Refitter.Core/RefitGenerator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ public static async Task<RefitGenerator> CreateAsync(RefitGeneratorSettings sett

ProcessTagFilters(openApiDocument, settings.IncludeTags);
ProcessPathFilters(openApiDocument, settings.IncludePathMatches);
ProcessContractFilter(openApiDocument, settings.TrimUnusedSchema, settings.KeepSchemaPatterns);
ProcessContractFilter(openApiDocument, settings.TrimUnusedSchema, settings.KeepSchemaPatterns, settings.IncludeInheritanceHierarchy);

return new RefitGenerator(settings, openApiDocument);
}
Expand Down Expand Up @@ -55,13 +55,17 @@ private static OpenApiDocument SanitizePath(
return openApiDocument;
}

private static void ProcessContractFilter(OpenApiDocument openApiDocument, bool removeUnusedSchema, string[] includeSchemaMatches)
private static void ProcessContractFilter(OpenApiDocument openApiDocument, bool removeUnusedSchema, string[] includeSchemaMatches,
bool includeInheritanceHierarchy)
{
if (!removeUnusedSchema)
{
return;
}
var cleaner = new SchemaCleaner(openApiDocument, includeSchemaMatches);
var cleaner = new SchemaCleaner(openApiDocument, includeSchemaMatches)
{
IncludeInheritanceHierarchy = includeInheritanceHierarchy
};
cleaner.RemoveUnreferencedSchema();
}

Expand Down
51 changes: 42 additions & 9 deletions src/Refitter.Core/SchemaCleaner.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ public class SchemaCleaner
private readonly OpenApiDocument document;
private readonly string[] keepSchemaPatterns;

public bool IncludeInheritanceHierarchy { get; set; }

public SchemaCleaner(OpenApiDocument document, string[] keepSchemaPatterns)
{
this.document = document;
Expand All @@ -17,18 +19,39 @@ public SchemaCleaner(OpenApiDocument document, string[] keepSchemaPatterns)

public void RemoveUnreferencedSchema()
{
var usage = FindUsedSchema(document);

var (usedJsonSchema, usage) = FindUsedJsonSchema(document);
var unused = document.Components.Schemas.Where(s => !usage.Contains(s.Key))
.ToArray();

foreach (var unusedSchema in unused)
{
document.Components.Schemas.Remove(unusedSchema);
}

if (!IncludeInheritanceHierarchy)
{
foreach (var schema in usedJsonSchema)
{
// Fix any "abstract/sum" types so that the unused-types get removed
if (schema.DiscriminatorObject != null)
{
var mappings = schema.DiscriminatorObject.Mapping;
var keepMappings = mappings.Where(x =>
usage.Contains(x.Value.ActualSchema.Id ?? x.Value.Id ?? "_________SOME NON EXISTING VALUE")
)
.ToArray();

schema.DiscriminatorObject.Mapping.Clear();
foreach (var kvp in keepMappings)
{
schema.DiscriminatorObject.Mapping[kvp.Key] = kvp.Value;
}
}
}
}
}

private HashSet<string> FindUsedSchema(OpenApiDocument doc)
private (IReadOnlyCollection<JsonSchema>, HashSet<string>) FindUsedJsonSchema(OpenApiDocument doc)
{
var toProcess = new Stack<JsonSchema>();
var schemaIdLookup = document.Components.Schemas
Expand Down Expand Up @@ -82,7 +105,7 @@ private HashSet<string> FindUsedSchema(OpenApiDocument doc)
}
}

return seenIds;
return (seen, seenIds);
}

private IEnumerable<JsonSchema?> GetSchemaForPath(OpenApiPathItem pathItem)
Expand Down Expand Up @@ -144,10 +167,10 @@ private IEnumerable<JsonSchema> EnumerateSchema(JsonSchema? schema)
.Where(x => x != null)
.Select(x => x!);

static IEnumerable<JsonSchema?> EnumerateInternal(JsonSchema schema)
IEnumerable<JsonSchema?> EnumerateInternal(JsonSchema schema)
{
schema = schema.ActualSchema;

yield return schema.AdditionalItemsSchema;
yield return schema.AdditionalPropertiesSchema;
if (schema.AllInheritedSchemas != null)
Expand All @@ -157,12 +180,12 @@ private IEnumerable<JsonSchema> EnumerateSchema(JsonSchema? schema)
yield return s;
}
}

if (schema.Item != null)
{
yield return schema.Item;
}

if (schema.Items != null)
{
foreach (JsonSchema s in schema.Items)
Expand All @@ -179,6 +202,16 @@ private IEnumerable<JsonSchema> EnumerateSchema(JsonSchema? schema)
yield return subSchema;
}

if (schema.DiscriminatorObject != null && IncludeInheritanceHierarchy)
{
// abstract type
// if we let these out, we get a bunch of "AnonymousN"-classes
foreach (var subSchema in schema.DiscriminatorObject.Mapping)
{
yield return subSchema.Value;
}
}

foreach (var subSchema in schema.AnyOf)
{
yield return subSchema;
Expand All @@ -200,4 +233,4 @@ private IEnumerable<JsonSchema> EnumerateSchema(JsonSchema? schema)
}
}
}
}
}
9 changes: 8 additions & 1 deletion src/Refitter.Core/Settings/RefitGeneratorSettings.cs
Original file line number Diff line number Diff line change
Expand Up @@ -138,7 +138,7 @@ public class RefitGeneratorSettings
public bool GenerateDeprecatedOperations { get; set; } = true;

/// <summary>
/// Generate operation names using pattern.
/// Generate operation names using pattern.
/// When using <see cref="MultipleInterfaces"/> <see cref="Core.MultipleInterfaces.ByEndpoint"/>, this is name of the Execute() method in the interface.
/// </summary>
public string? OperationNameTemplate { get; set; }
Expand Down Expand Up @@ -187,6 +187,13 @@ public class RefitGeneratorSettings
/// </summary>
public string[] KeepSchemaPatterns { get; set; } = Array.Empty<string>();

/// <summary>
/// Set to <c>true</c> to keep all possible type-instances of inheritance/union types.
/// If this is <c>false</c> only directly referenced types will be kept.
/// This works in conjunction with <see cref="TrimUnusedSchema"/>.
/// </summary>
public bool IncludeInheritanceHierarchy { get; set; }

/// <summary>
/// The NSwag IOperationNameGenerator implementation to use
/// </summary>
Expand Down
1 change: 1 addition & 0 deletions src/Refitter/GenerateCommand.cs
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,7 @@ private static RefitGeneratorSettings CreateRefitGeneratorSettings(Settings sett
OptionalParameters = settings.OptionalNullableParameters,
TrimUnusedSchema = settings.TrimUnusedSchema,
KeepSchemaPatterns = settings.KeepSchemaPatterns ?? Array.Empty<string>(),
IncludeInheritanceHierarchy = settings.IncludeInheritanceHierarchy,
OperationNameGenerator = settings.OperationNameGenerator,
GenerateDefaultAdditionalProperties = !settings.SkipDefaultAdditionalProperties,
ImmutableRecords = settings.ImmutableRecords,
Expand Down
5 changes: 5 additions & 0 deletions src/Refitter/Settings.cs
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,11 @@ Generate multiple files instead of a single large file.
[DefaultValue(new string[0])]
public string[]? KeepSchemaPatterns { get; set; }

[Description("Keep all possible inherited types/union types even if they are not directly used.")]
[CommandOption("--include-inheritance-hierarchy")]
[DefaultValue(false)]
public bool IncludeInheritanceHierarchy { get; set; }

[Description("Don't show donation banner")]
[CommandOption("--no-banner")]
[DefaultValue(false)]
Expand Down

0 comments on commit 5491fa9

Please sign in to comment.