Skip to content

Commit

Permalink
fix: disambiguate parameter class names for swashbuckle
Browse files Browse the repository at this point in the history
  • Loading branch information
ascott18 committed Oct 14, 2024
1 parent 718a979 commit 1948a7c
Show file tree
Hide file tree
Showing 8 changed files with 142 additions and 3 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ private static void WriteControllerActionJsonPreamble(CSharpCodeBuilder b, Metho
if (!method.ApiParameters.Any()) return;

b.Line();
using (b.Block($"public class {method.NameWithoutAsync}Parameters"))
using (b.Block($"public class {method.ParameterClassName}"))
{
foreach (var param in method.ApiParameters.OrderBy(p => p.HasDefaultValue))
{
Expand Down Expand Up @@ -282,7 +282,7 @@ protected IDisposable WriteControllerActionJsonSignature(CSharpCodeBuilder b, Me

if (method.ApiParameters.Any())
{
b.Line($"[FromBody] {method.NameWithoutAsync}Parameters _params");
b.Line($"[FromBody] {method.ParameterClassName} _params");
}

indent.Dispose();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -316,6 +316,9 @@ public static ItemResult<IFile> DownloadAttachmentStatic()
[Coalesce]
public CaseDtoStandalone CustomDto(CaseDtoStandalone input) => input;

[Coalesce]
public CaseDtoStandalone SameMethodNameAsMethodOnDifferentType(CaseDtoStandalone input) => input;

[Coalesce]
[ControllerAction(Method = HttpMethod.Post)]
public static ItemResult HasTopLevelParamWithSameNameAsObjectProp(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,5 +8,8 @@ public class ComplexModelDependent
public int ParentId { get; set; }

public string Name { get; set; }

[Coalesce]
public CaseDtoStandalone SameMethodNameAsMethodOnDifferentType(CaseDtoStandalone input) => input;
}
}
22 changes: 22 additions & 0 deletions src/IntelliTect.Coalesce/TypeDefinition/MethodViewModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -170,6 +170,28 @@ ApiActionHttpMethod is not HttpMethod.Get and not HttpMethod.Delete &&
public IEnumerable<ParameterViewModel> ClientParameters => Parameters
.Where(f => !f.IsDI);

/// <summary>
/// The generated class that wraps the method parameters for JSON-accepting API endpoints
/// </summary>
public string ParameterClassName
{
get
{
var parameterClassName = $"{NameWithoutAsync}Parameters";

// Disambiguate the parameter class name using the owning type's name
// if there are mutliple same-name methods in the application.
// This prevents Swashbuckle from throwing errors when it uses
// only the class name as the OpenAPI schema name.
if (Parent.ReflectionRepository?.ClientMethodsLookup[Name].Count() > 1)
{
parameterClassName = Parent.Name + parameterClassName;
}

return parameterClassName;
}
}

/// <summary>
/// List of parameters that are part of the endpoint's API surface.
/// Includes implicit parameters that are not defined on the underlying implementation.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,6 @@ public class ReflectionRepository

private readonly ConcurrentHashSet<DbContextTypeUsage> _contexts = new();
private readonly ConcurrentHashSet<ClassViewModel> _entities = new();
private ILookup<ClassViewModel, EntityTypeUsage>? _entityUsages = null;

private readonly ConcurrentHashSet<CrudStrategyTypeUsage> _behaviors = new();
private readonly ConcurrentHashSet<CrudStrategyTypeUsage> _dataSources = new();
Expand All @@ -43,10 +42,17 @@ private readonly ConcurrentDictionary<object, TypeViewModel> _allTypeViewModels
private readonly object _discoverLock = new();

public ReadOnlyHashSet<DbContextTypeUsage> DbContexts => new(_contexts);

private ILookup<ClassViewModel, EntityTypeUsage>? _entityUsages = null;
public ILookup<ClassViewModel, EntityTypeUsage> EntityUsages => _entityUsages ??= DbContexts
.SelectMany(contextUsage => contextUsage.Entities)
.ToLookup(entityUsage => entityUsage.ClassViewModel);

private ILookup<string, MethodViewModel>? _clientMethods = null;
public ILookup<string, MethodViewModel> ClientMethodsLookup => _clientMethods ??= ControllerBackedClasses
.SelectMany(c => c.ClientMethods)
.ToLookup(m => m.Name);

private ReadOnlyDictionary<string, ClassViewModel>? _clientTypes;
public ReadOnlyDictionary<string, ClassViewModel> ClientTypesLookup
=> _clientTypes ??= new(ClientClasses.Union(Services).ToDictionary(c => c.ClientTypeName, StringComparer.OrdinalIgnoreCase));
Expand Down Expand Up @@ -175,6 +181,7 @@ private void ProcessAddedType(TypeViewModel type)

// Null this out so it gets recomputed on next access.
_clientTypes = null;
_clientMethods = null;

if (type.IsA<DbContext>())
{
Expand Down
18 changes: 18 additions & 0 deletions src/test-targets/api-clients.g.ts

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

64 changes: 64 additions & 0 deletions src/test-targets/metadata.g.ts

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

22 changes: 22 additions & 0 deletions src/test-targets/viewmodels.g.ts

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit 1948a7c

Please sign in to comment.