Skip to content
Permalink
Browse files

Use OpenApiTagAttribute of class to set tags for those methods where …

…such attribute is not set explicitly (#2381)

* OperationTagsProcessor processes OpenApiTagsAttribute and OpenApiTagAttribute  set for the class if they were not specified for method.

* Added OperationTagsProcessor tests

* Set VS version back to 16 in solution files
  • Loading branch information...
korneyev authored and RicoSuter committed Oct 8, 2019
1 parent 872c129 commit 9d77bc4d823b2981bd5b8573f2c34669562a9a58
@@ -0,0 +1,20 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFramework>netcoreapp2.2</TargetFramework>

<IsPackable>false</IsPackable>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="15.9.0" />
<PackageReference Include="xunit" Version="2.4.0" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.0" />
</ItemGroup>

<ItemGroup>
<ProjectReference Include="..\NSwag.Annotations\NSwag.Annotations.csproj" />
<ProjectReference Include="..\NSwag.Generation\NSwag.Generation.csproj" />
</ItemGroup>

</Project>
@@ -0,0 +1,129 @@
using System;
using System.Reflection;
using NSwag.Annotations;
using NSwag.Generation.Processors;
using NSwag.Generation.Processors.Contexts;
using Xunit;

namespace NSwag.Generation.Tests.Processors
{
public class OperationTagsProcessorTests
{
[OpenApiTag("Controller tag 1")]
[OpenApiTags("Controller tag 2", "Controller tag 3")]
public class TaggedController
{
public void UntaggedMethod()
{
}

[OpenApiTag("Method tag 1")]
[OpenApiTags("Method tag 2", "Method tag 3")]
public void TaggedMethod()
{
}
}

public class UntaggedController
{
public void UntaggedMethod()
{
}
}

[Fact]
public void Process_AddsTagsFromTaggedControllerForUntaggedMethod()
{
//// Arrange
var controllerType = typeof(TaggedController);
var methodInfo = controllerType.GetMethod("UntaggedMethod");

var context = GetContext(controllerType, methodInfo);
var processor = new OperationTagsProcessor();

//// Act
processor.Process(context);

//// Assert
var tags = context.OperationDescription.Operation.Tags;

Assert.Collection(
tags,
tag =>
{
Assert.Contains("Controller tag 1", tags);
},
tag =>
{
Assert.Contains("Controller tag 2", tags);
},
tag =>
{
Assert.Contains("Controller tag 3", tags);
});
}

[Fact]
public void Process_AddsTagsFromTaggedMethod()
{
//// Arrange
var controllerType = typeof(TaggedController);
var methodInfo = controllerType.GetMethod("TaggedMethod");

var context = GetContext(controllerType, methodInfo);
var processor = new OperationTagsProcessor();

//// Act
processor.Process(context);

//// Assert
var tags = context.OperationDescription.Operation.Tags;

Assert.Collection(
tags,
tag =>
{
Assert.Contains("Method tag 1", tags);
},
tag =>
{
Assert.Contains("Method tag 2", tags);
},
tag =>
{
Assert.Contains("Method tag 3", tags);
});
}

[Fact]
public void Process_AddsControllerNameWhenNoTagsArePresent()
{
//// Arrange
var controllerType = typeof(UntaggedController);
var methodInfo = controllerType.GetMethod("UntaggedMethod");

var context = GetContext(controllerType, methodInfo);
var processor = new OperationTagsProcessor();

//// Act
processor.Process(context);

//// Assert
var tags = context.OperationDescription.Operation.Tags;

Assert.Collection(
tags,
tag =>
{
Assert.Equal("Untagged", tag);
});
}

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);
}
}
}
@@ -25,6 +25,14 @@ public bool Process(OperationProcessorContext context)
ProcessSwaggerTagsAttribute(context.Document, context.OperationDescription, context.MethodInfo);
ProcessSwaggerTagAttributes(context.Document, context.OperationDescription, context.MethodInfo);

if (!context.OperationDescription.Operation.Tags.Any())
{
var typeInfo = context.ControllerType.GetTypeInfo();

ProcessControllerSwaggerTagsAttribute(context.OperationDescription, typeInfo);
ProcessControllerSwaggerTagAttributes(context.OperationDescription, typeInfo);
}

if (!context.OperationDescription.Operation.Tags.Any())
{
AddControllerNameTag(context);
@@ -95,5 +103,37 @@ private void ProcessSwaggerTagsAttribute(OpenApiDocument document, OpenApiOperat
}
}
}

private void ProcessControllerSwaggerTagsAttribute(OpenApiOperationDescription operationDescription, TypeInfo typeInfo)
{
dynamic tagsAttribute = typeInfo
.GetCustomAttributes()
.FirstAssignableToTypeNameOrDefault("OpenApiTagsAttribute", TypeNameStyle.Name);

if (tagsAttribute != null)
{
var tags = ((string[])tagsAttribute.Tags).ToList();
foreach (var tag in tags)
{
if (operationDescription.Operation.Tags.All(t => t != tag))
{
operationDescription.Operation.Tags.Add(tag);
}
}
}
}

private void ProcessControllerSwaggerTagAttributes(OpenApiOperationDescription operationDescription, TypeInfo typeInfo)
{
foreach (var tagAttribute in typeInfo.GetCustomAttributes()
.GetAssignableToTypeName("OpenApiTagAttribute", TypeNameStyle.Name)
.Select(a => (dynamic)a))
{
if (operationDescription.Operation.Tags.All(t => t != tagAttribute.Name))
{
operationDescription.Operation.Tags.Add(tagAttribute.Name);
}
}
}
}
}
@@ -1,7 +1,7 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 16
VisualStudioVersion = 16.0.28721.148
VisualStudioVersion = 16.0.28803.156
MinimumVisualStudioVersion = 10.0.40219.1
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "NSwag.CodeGeneration", "NSwag.CodeGeneration\NSwag.CodeGeneration.csproj", "{75B3F91D-687E-4FB3-AD45-CCFA3C406DB4}"
EndProject
@@ -75,6 +75,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "NSwag.AssemblyLoader.Tests"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "NSwag.Sample.NETCore22", "NSwag.Sample.NETCore22\NSwag.Sample.NETCore22.csproj", "{BBEBEC80-1E20-4C96-9A9F-2F50092E8FFC}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "NSwag.Generation.Tests", "NSwag.Generation.Tests\NSwag.Generation.Tests.csproj", "{3A6CA187-AD6F-438C-9E5B-B2771F75AF41}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "NSwag.Sample.NETCore30", "NSwag.Sample.NETCore30\NSwag.Sample.NETCore30.csproj", "{A3A38972-E431-4EB2-92CA-F422791E2F74}"
EndProject
Global
@@ -610,6 +612,24 @@ Global
{BBEBEC80-1E20-4C96-9A9F-2F50092E8FFC}.ReleaseTypeScriptStrict|x64.Build.0 = Release|Any CPU
{BBEBEC80-1E20-4C96-9A9F-2F50092E8FFC}.ReleaseTypeScriptStrict|x86.ActiveCfg = Release|Any CPU
{BBEBEC80-1E20-4C96-9A9F-2F50092E8FFC}.ReleaseTypeScriptStrict|x86.Build.0 = Release|Any CPU
{3A6CA187-AD6F-438C-9E5B-B2771F75AF41}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{3A6CA187-AD6F-438C-9E5B-B2771F75AF41}.Debug|Any CPU.Build.0 = Debug|Any CPU
{3A6CA187-AD6F-438C-9E5B-B2771F75AF41}.Debug|x64.ActiveCfg = Debug|Any CPU
{3A6CA187-AD6F-438C-9E5B-B2771F75AF41}.Debug|x64.Build.0 = Debug|Any CPU
{3A6CA187-AD6F-438C-9E5B-B2771F75AF41}.Debug|x86.ActiveCfg = Debug|Any CPU
{3A6CA187-AD6F-438C-9E5B-B2771F75AF41}.Debug|x86.Build.0 = Debug|Any CPU
{3A6CA187-AD6F-438C-9E5B-B2771F75AF41}.Release|Any CPU.ActiveCfg = Release|Any CPU
{3A6CA187-AD6F-438C-9E5B-B2771F75AF41}.Release|Any CPU.Build.0 = Release|Any CPU
{3A6CA187-AD6F-438C-9E5B-B2771F75AF41}.Release|x64.ActiveCfg = Release|Any CPU
{3A6CA187-AD6F-438C-9E5B-B2771F75AF41}.Release|x64.Build.0 = Release|Any CPU
{3A6CA187-AD6F-438C-9E5B-B2771F75AF41}.Release|x86.ActiveCfg = Release|Any CPU
{3A6CA187-AD6F-438C-9E5B-B2771F75AF41}.Release|x86.Build.0 = Release|Any CPU
{3A6CA187-AD6F-438C-9E5B-B2771F75AF41}.ReleaseTypeScriptStrict|Any CPU.ActiveCfg = Release|Any CPU
{3A6CA187-AD6F-438C-9E5B-B2771F75AF41}.ReleaseTypeScriptStrict|Any CPU.Build.0 = Release|Any CPU
{3A6CA187-AD6F-438C-9E5B-B2771F75AF41}.ReleaseTypeScriptStrict|x64.ActiveCfg = Release|Any CPU
{3A6CA187-AD6F-438C-9E5B-B2771F75AF41}.ReleaseTypeScriptStrict|x64.Build.0 = Release|Any CPU
{3A6CA187-AD6F-438C-9E5B-B2771F75AF41}.ReleaseTypeScriptStrict|x86.ActiveCfg = Release|Any CPU
{3A6CA187-AD6F-438C-9E5B-B2771F75AF41}.ReleaseTypeScriptStrict|x86.Build.0 = Release|Any CPU
{A3A38972-E431-4EB2-92CA-F422791E2F74}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{A3A38972-E431-4EB2-92CA-F422791E2F74}.Debug|Any CPU.Build.0 = Debug|Any CPU
{A3A38972-E431-4EB2-92CA-F422791E2F74}.Debug|x64.ActiveCfg = Debug|Any CPU
@@ -662,6 +682,7 @@ Global
{DCAF8B88-E36F-48F8-AD0E-0F9B42E9FEB6} = {49A70E20-FF73-451D-BBE8-7680EDCF007B}
{06B5C478-0ACC-4088-97B6-891C4F35EBBC} = {D8CC0D1C-8DAC-49FE-AA78-C028DC124DD5}
{BBEBEC80-1E20-4C96-9A9F-2F50092E8FFC} = {A0338E8D-A4A3-4380-9FF7-1D0BDC260E31}
{3A6CA187-AD6F-438C-9E5B-B2771F75AF41} = {D8CC0D1C-8DAC-49FE-AA78-C028DC124DD5}
{A3A38972-E431-4EB2-92CA-F422791E2F74} = {A0338E8D-A4A3-4380-9FF7-1D0BDC260E31}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
@@ -159,6 +159,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "NSwag.Sample.NETCore22", "N
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "NSwag.Core.Yaml.Tests", "NSwag.Core.Yaml.Tests\NSwag.Core.Yaml.Tests.csproj", "{B6467D5A-7B13-4B06-89BE-2BC7B6615956}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NSwag.Generation.Tests", "NSwag.Generation.Tests\NSwag.Generation.Tests.csproj", "{F237A592-2D74-4C38-B222-2C91029B87F8}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "NSwag.Sample.NETCore30", "NSwag.Sample.NETCore30\NSwag.Sample.NETCore30.csproj", "{2A50783A-1FF9-4DCE-A67E-508A654587D5}"
EndProject
Global
@@ -995,6 +997,24 @@ Global
{B6467D5A-7B13-4B06-89BE-2BC7B6615956}.ReleaseTypeScriptStrict|x64.Build.0 = Release|Any CPU
{B6467D5A-7B13-4B06-89BE-2BC7B6615956}.ReleaseTypeScriptStrict|x86.ActiveCfg = Release|Any CPU
{B6467D5A-7B13-4B06-89BE-2BC7B6615956}.ReleaseTypeScriptStrict|x86.Build.0 = Release|Any CPU
{F237A592-2D74-4C38-B222-2C91029B87F8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{F237A592-2D74-4C38-B222-2C91029B87F8}.Debug|Any CPU.Build.0 = Debug|Any CPU
{F237A592-2D74-4C38-B222-2C91029B87F8}.Debug|x64.ActiveCfg = Debug|Any CPU
{F237A592-2D74-4C38-B222-2C91029B87F8}.Debug|x64.Build.0 = Debug|Any CPU
{F237A592-2D74-4C38-B222-2C91029B87F8}.Debug|x86.ActiveCfg = Debug|Any CPU
{F237A592-2D74-4C38-B222-2C91029B87F8}.Debug|x86.Build.0 = Debug|Any CPU
{F237A592-2D74-4C38-B222-2C91029B87F8}.Release|Any CPU.ActiveCfg = Release|Any CPU
{F237A592-2D74-4C38-B222-2C91029B87F8}.Release|Any CPU.Build.0 = Release|Any CPU
{F237A592-2D74-4C38-B222-2C91029B87F8}.Release|x64.ActiveCfg = Release|Any CPU
{F237A592-2D74-4C38-B222-2C91029B87F8}.Release|x64.Build.0 = Release|Any CPU
{F237A592-2D74-4C38-B222-2C91029B87F8}.Release|x86.ActiveCfg = Release|Any CPU
{F237A592-2D74-4C38-B222-2C91029B87F8}.Release|x86.Build.0 = Release|Any CPU
{F237A592-2D74-4C38-B222-2C91029B87F8}.ReleaseTypeScriptStrict|Any CPU.ActiveCfg = Release|Any CPU
{F237A592-2D74-4C38-B222-2C91029B87F8}.ReleaseTypeScriptStrict|Any CPU.Build.0 = Release|Any CPU
{F237A592-2D74-4C38-B222-2C91029B87F8}.ReleaseTypeScriptStrict|x64.ActiveCfg = Release|Any CPU
{F237A592-2D74-4C38-B222-2C91029B87F8}.ReleaseTypeScriptStrict|x64.Build.0 = Release|Any CPU
{F237A592-2D74-4C38-B222-2C91029B87F8}.ReleaseTypeScriptStrict|x86.ActiveCfg = Release|Any CPU
{F237A592-2D74-4C38-B222-2C91029B87F8}.ReleaseTypeScriptStrict|x86.Build.0 = Release|Any CPU
{2A50783A-1FF9-4DCE-A67E-508A654587D5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{2A50783A-1FF9-4DCE-A67E-508A654587D5}.Debug|Any CPU.Build.0 = Debug|Any CPU
{2A50783A-1FF9-4DCE-A67E-508A654587D5}.Debug|x64.ActiveCfg = Debug|Any CPU
@@ -1069,6 +1089,7 @@ Global
{E6E40935-0C79-480B-BF29-8C493AC7E518} = {DDBB05AC-B066-48C4-933C-034F401EBB6A}
{AC8C4C44-C9AA-4894-AF21-868B53A96429} = {D8CC0D1C-8DAC-49FE-AA78-C028DC124DD5}
{B6467D5A-7B13-4B06-89BE-2BC7B6615956} = {634E4ABD-29EC-4EB2-81EF-7E41D6D6F6E0}
{F237A592-2D74-4C38-B222-2C91029B87F8} = {634E4ABD-29EC-4EB2-81EF-7E41D6D6F6E0}
{2A50783A-1FF9-4DCE-A67E-508A654587D5} = {D8CC0D1C-8DAC-49FE-AA78-C028DC124DD5}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution

0 comments on commit 9d77bc4

Please sign in to comment.
You can’t perform that action at this time.