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

Add support for using controllers' summary as tag description #2949

Merged
merged 4 commits into from
Jul 14, 2020
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 @@ -7,6 +7,7 @@
//-----------------------------------------------------------------------

using Microsoft.AspNetCore.Mvc.Controllers;
using Namotion.Reflection;
using NSwag.Generation.Processors;
using NSwag.Generation.Processors.Contexts;

Expand All @@ -23,10 +24,12 @@ protected override void AddControllerNameTag(OperationProcessorContext context)
if (aspNetCoreContext.ApiDescription.ActionDescriptor is ControllerActionDescriptor descriptor)
{
aspNetCoreContext.OperationDescription.Operation.Tags.Add(descriptor.ControllerName);
return;
SetDescription(context, descriptor.ControllerName, descriptor.ControllerTypeInfo.GetXmlDocsSummary());
}
else
{
base.AddControllerNameTag(context);
}

base.AddControllerNameTag(context);
}
}
}
5 changes: 5 additions & 0 deletions src/NSwag.Generation.Tests/NSwag.Generation.Tests.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,11 @@
<IsPackable>false</IsPackable>
</PropertyGroup>

<PropertyGroup>
<GenerateDocumentationFile>true</GenerateDocumentationFile>
<NoWarn>$(NoWarn);1591</NoWarn>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="15.9.0" />
<PackageReference Include="xunit" Version="2.4.0" />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,9 @@ public void TaggedMethod()
}
}

/// <summary>
/// Test summary
/// </summary>
public class UntaggedController
{
public void UntaggedMethod()
Expand Down Expand Up @@ -117,13 +120,18 @@ public void Process_AddsControllerNameWhenNoTagsArePresent()
{
Assert.Equal("Untagged", tag);
});

var docTag = context.Document.Tags[0];
Assert.Equal("Untagged", docTag.Name);
Assert.Equal("Test summary", docTag.Description);
}

private OperationProcessorContext GetContext(Type controllerType, MethodInfo methodInfo)
{
var document = new OpenApiDocument();
var operationDescription = new OpenApiOperationDescription { Operation = new OpenApiOperation() };
return new OperationProcessorContext(document, operationDescription, controllerType, methodInfo, null, null, null, null, null);
var settings = new OpenApiDocumentGeneratorSettings { UseControllerSummaryAsTagDescription = true };
return new OperationProcessorContext(document, operationDescription, controllerType, methodInfo, null, null, null, settings, null);
}
}
}
28 changes: 28 additions & 0 deletions src/NSwag.Generation/Collections/CollectionExtensions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
using System;
using System.Collections.Generic;
using System.Linq;

namespace NSwag.Generation.Collections
{
internal static class CollectionExtensions
{
/// <summary>Returns the only element of a sequence that satisfies a specified condition or a creates a new object and adds it to the collection if no such element exists; this method throws an exception if more than one element satisfies the condition.</summary>
/// <returns>The single element of the input sequence that satisfies the condition, or a new(<paramref name="TSource" />) if no such element is found.</returns>
/// <param name="source">An <see cref="T:System.Collections.Generic.IEnumerable`1" /> to return a single element from.</param>
/// <param name="predicate">A function to test an element for a condition.</param>
/// <typeparam name="TSource">The type of the elements of <paramref name="source" />.</typeparam>
/// <exception cref="T:System.ArgumentNullException">
/// <paramref name="source" /> or <paramref name="predicate" /> is null.</exception>
public static TSource SingleOrNew<TSource>(this ICollection<TSource> source, Func<TSource, bool> predicate) where TSource : new()
{
var item = source.SingleOrDefault(predicate);
if (item == null)
{
item = new TSource();
source.Add(item);
}

return item;
}
}
}
6 changes: 5 additions & 1 deletion src/NSwag.Generation/OpenApiDocumentGeneratorSettings.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@
using NSwag.Generation.Processors.Collections;
using NSwag.Generation.Processors.Contexts;
using System;
using System.Threading.Tasks;

namespace NSwag.Generation
{
Expand Down Expand Up @@ -67,6 +66,11 @@ public OpenApiDocumentGeneratorSettings()
/// <summary>Gets or sets the document template representing the initial Swagger specification (JSON data).</summary>
public string DocumentTemplate { get; set; }

/// <summary>
/// Gets or sets a value indicating whether controllers' XML documentation will be used as tag descriptions (but only when the controller name is used as a tag, default: false).
/// </summary>
public bool UseControllerSummaryAsTagDescription { get; set; }

/// <summary>Inserts a function based operation processor at the beginning of the pipeline to be used to filter operations.</summary>
/// <param name="filter">The processor filter.</param>
public void AddOperationFilter(Func<OperationProcessorContext, bool> filter)
Expand Down
14 changes: 2 additions & 12 deletions src/NSwag.Generation/Processors/DocumentTagsProcessor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
using System.Collections.Generic;
using System.Linq;
using Namotion.Reflection;
using NSwag.Generation.Collections;
using NSwag.Generation.Processors.Contexts;

namespace NSwag.Generation.Processors
Expand Down Expand Up @@ -76,18 +77,7 @@ private static void ProcessTagAttributes(OpenApiDocument document, Type controll

internal static void ProcessTagAttribute(OpenApiDocument document, dynamic tagAttribute)
{
if (document.Tags == null)
{
document.Tags = new List<OpenApiTag>();
}

var tag = document.Tags.SingleOrDefault(t => t.Name == tagAttribute.Name);
if (tag == null)
{
tag = new OpenApiTag();
document.Tags.Add(tag);
}

var tag = document.Tags.SingleOrNew(t => t.Name == tagAttribute.Name);
tag.Description = tagAttribute.Description;
tag.Name = tagAttribute.Name;

Expand Down
14 changes: 14 additions & 0 deletions src/NSwag.Generation/Processors/OperationTagsProcessor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
using System.Linq;
using System.Reflection;
using Namotion.Reflection;
using NSwag.Generation.Collections;
using NSwag.Generation.Processors.Contexts;

namespace NSwag.Generation.Processors
Expand Down Expand Up @@ -52,6 +53,19 @@ protected virtual void AddControllerNameTag(OperationProcessorContext context)
}

context.OperationDescription.Operation.Tags.Add(controllerName);
SetDescription(context, controllerName, context.ControllerType.GetXmlDocsSummary());
}

protected void SetDescription(OperationProcessorContext context, string controllerName, string description)
{
if (!context.Settings.UseControllerSummaryAsTagDescription || string.IsNullOrEmpty(description))
{
return;
}

var documentTag = context.Document.Tags.SingleOrNew(tag => tag.Name == controllerName);
documentTag.Name = controllerName;
documentTag.Description = description;
}

private void ProcessSwaggerTagAttributes(OpenApiDocument document, OpenApiOperationDescription operationDescription, MethodInfo methodInfo)
Expand Down