Skip to content
18 changes: 14 additions & 4 deletions src/Refitter.Core/RefitInterfaceGenerator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,11 @@ private string GenerateInterfaceBody(out string? dynamicQuerystringParameters)
var parametersString = string.Join(", ", parameters);
var hasApizrRequestOptionsParameter = settings.ApizrSettings?.WithRequestOptions == true;

this.docGenerator.AppendMethodDocumentation(operationModel, IsApiResponseType(returnType), hasDynamicQuerystringParameter, hasApizrRequestOptionsParameter, code);
if (settings.GenerateXmlDocCodeComments)
{
this.docGenerator.AppendMethodDocumentation(operationModel, IsApiResponseType(returnType), hasDynamicQuerystringParameter, hasApizrRequestOptionsParameter, code);
}

GenerateObsoleteAttribute(operation, code);
GenerateForMultipartFormData(operationModel, code);
GenerateHeaders(operations, operation, operationModel, code);
Expand All @@ -82,7 +86,10 @@ private string GenerateInterfaceBody(out string? dynamicQuerystringParameters)

if (parametersString.Contains("?") && settings is {OptionalParameters: true, ApizrSettings: not null})
{
this.docGenerator.AppendMethodDocumentation(operationModel, IsApiResponseType(returnType), false, hasApizrRequestOptionsParameter, code);
if (settings.GenerateXmlDocCodeComments)
{
this.docGenerator.AppendMethodDocumentation(operationModel, IsApiResponseType(returnType), false, hasApizrRequestOptionsParameter, code);
}
GenerateObsoleteAttribute(operation, code);
GenerateForMultipartFormData(operationModel, code);
GenerateHeaders(operations, operation, operationModel, code);
Expand Down Expand Up @@ -290,10 +297,13 @@ private string GenerateInterfaceDeclaration(out string interfaceName)
: null;

var modifier = settings.TypeAccessibility.ToString().ToLowerInvariant();
return $"""
var code = new StringBuilder();
docGenerator.AppendInterfaceDocumentation(document, code);
code.Append($"""
{Separator}{GetGeneratedCodeAttribute()}
{Separator}{modifier} partial interface {interfaceName}{inheritance}
""";
""");
return code.ToString();
Comment thread
christianhelle marked this conversation as resolved.
}

protected string GetGeneratedCodeAttribute() =>
Expand Down
73 changes: 63 additions & 10 deletions src/Refitter.Core/XmlDocumentationGenerator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -30,15 +30,38 @@ internal XmlDocumentationGenerator(RefitGeneratorSettings settings)

/// <summary>
/// Appends XML docs for the given interface definition to the given code builder.
/// This uses the OpenAPI operation info to generate the summary and remarks.
/// </summary>
/// <param name="group">The OpenAPI definition of the interface.</param>
/// <param name="code">The builder to append the documentation to.</param>
public void AppendInterfaceDocumentation(OpenApiOperation group, StringBuilder code)
{
if (!_settings.GenerateXmlDocCodeComments || string.IsNullOrWhiteSpace(group.Summary))
if (!_settings.GenerateXmlDocCodeComments)
{
return;
}

this.AppendXmlCommentBlock("summary", group.Summary, code, indent: Separator);
this.AppendXmlCommentBlock("summary", group?.Summary ?? "No summary available", code, indent: Separator);
}

/// <summary>
/// Appends XML docs for the given interface definition to the given code builder.
/// This uses the OpenAPI document's info description as the summary.
/// </summary>
/// <param name="document">The OpenAPI definition of the interface.</param>
/// <param name="code">The builder to append the documentation to.</param>
public void AppendInterfaceDocumentation(OpenApiDocument document, StringBuilder code)
{
if (!_settings.GenerateXmlDocCodeComments)
{
return;
}

this.AppendXmlCommentBlock(
"summary",
document.Info?.Title ?? "Refit interface - no description available",
code,
indent: Separator);
}

/// <summary>
Expand All @@ -49,7 +72,12 @@ public void AppendInterfaceDocumentation(OpenApiOperation group, StringBuilder c
/// <param name="hasDynamicQuerystringParameter">Indicates whether the method gets a dynamic querystring parameter</param>
/// <param name="hasApizrRequestOptionsParameter">Indicates whether the method gets an IApizrRequestOptions options final parameter</param>
/// <param name="code">The builder to append the documentation to.</param>
public void AppendMethodDocumentation(CSharpOperationModel method, bool hasApiResponse, bool hasDynamicQuerystringParameter, bool hasApizrRequestOptionsParameter, StringBuilder code)
public void AppendMethodDocumentation(
CSharpOperationModel method,
bool hasApiResponse,
bool hasDynamicQuerystringParameter,
bool hasApizrRequestOptionsParameter,
StringBuilder code)
{
if (!_settings.GenerateXmlDocCodeComments)
return;
Expand All @@ -65,8 +93,14 @@ public void AppendMethodDocumentation(CSharpOperationModel method, bool hasApiRe
if (parameter == null || string.IsNullOrWhiteSpace(parameter.Description))
continue;

this.AppendXmlCommentBlock("param", parameter.Description, code, new Dictionary<string, string>
{ ["name"] = parameter.VariableName });
this.AppendXmlCommentBlock(
"param",
parameter.Description,
code,
new Dictionary<string, string>
{
["name"] = parameter.VariableName
});
}

if (hasDynamicQuerystringParameter)
Expand All @@ -75,7 +109,10 @@ public void AppendMethodDocumentation(CSharpOperationModel method, bool hasApiRe
"param",
"The dynamic querystring parameter wrapping all others.",
code,
new Dictionary<string, string> { ["name"] = "queryParams" });
new Dictionary<string, string>
{
["name"] = "queryParams"
});
}

if (hasApizrRequestOptionsParameter)
Expand All @@ -84,7 +121,10 @@ public void AppendMethodDocumentation(CSharpOperationModel method, bool hasApiRe
"param",
"The <see cref=\"IApizrRequestOptions\"/> instance to pass through the request.",
code,
new Dictionary<string, string> { ["name"] = "options" });
new Dictionary<string, string>
{
["name"] = "options"
});
}

if (hasApiResponse)
Expand Down Expand Up @@ -114,7 +154,10 @@ public void AppendMethodDocumentation(CSharpOperationModel method, bool hasApiRe
"exception",
this.BuildErrorDescription(method.Responses),
code,
new Dictionary<string, string> { ["cref"] = "ApiException" });
new Dictionary<string, string>
{
["cref"] = "ApiException"
});
}
}

Expand Down Expand Up @@ -142,12 +185,22 @@ private void AppendXmlCommentBlock(

code.Append(">");

var lines = content.Split(new[] { "\r\n", "\r", "\n" }, StringSplitOptions.None);
var lines = content.Split(
new[]
{
"\r\n", "\r", "\n"
},
StringSplitOptions.None);
if (lines.Length > 1)
{
// When working with multiple lines, place the content on a separate line with normalized linebreaks.
code.AppendLine();
foreach (var line in content.Split(new[] { "\r\n", "\r", "\n" }, StringSplitOptions.None))
foreach (var line in content.Split(
new[]
{
"\r\n", "\r", "\n"
},
StringSplitOptions.None))
code.AppendLine($"{indent}/// {line.Trim()}");

code.AppendLine($"{indent}/// </{tagName}>");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@

namespace Refitter.Tests.AdditionalFiles.NoFilename
{
/// <summary>Swagger Petstore - OpenAPI 3.0</summary>
[System.CodeDom.Compiler.GeneratedCode("Refitter", "1.0.0.0")]
public partial interface ISwaggerPetstore
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@

namespace Refitter.Tests.AdditionalFiles.OptionalParameters
{
/// <summary>Swagger Petstore - OpenAPI 3.0</summary>
[System.CodeDom.Compiler.GeneratedCode("Refitter", "1.0.0.0")]
public partial interface ISwaggerPetstoreWithOptionalParameters
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@

namespace Refitter.Tests.AdditionalFiles.SingeInterfaceWithHttpResilience
{
/// <summary>Swagger Petstore - OpenAPI 3.0</summary>
[System.CodeDom.Compiler.GeneratedCode("Refitter", "1.0.0.0")]
public partial interface ISwaggerPetstoreInterfaceWithHttpResilience
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@

namespace Refitter.Tests.AdditionalFiles.SingeInterface
{
/// <summary>Swagger Petstore - OpenAPI 3.0</summary>
[System.CodeDom.Compiler.GeneratedCode("Refitter", "1.0.0.0")]
public partial interface ISwaggerPetstoreInterface
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@

namespace Refitter.Tests.UseJsonInheritanceConverter
{
/// <summary>Refit interface - no description available</summary>
[System.CodeDom.Compiler.GeneratedCode("Refitter", "1.0.0.0")]
public partial interface IApiClient
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@

namespace Refitter.Tests.UsePolymorphicSerialization
{
/// <summary>Refit interface - no description available</summary>
[System.CodeDom.Compiler.GeneratedCode("Refitter", "1.0.0.0")]
public partial interface IApiClient
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@

namespace Refitter.Tests.CustomGenerated
{
/// <summary>Swagger Petstore - OpenAPI 3.0</summary>
[System.CodeDom.Compiler.GeneratedCode("Refitter", "1.0.0.0")]
public partial interface IApiInCustomGeneratedFolder
{
Expand Down
12 changes: 12 additions & 0 deletions src/Refitter.Tests/SwaggerPetstoreTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -823,4 +823,16 @@ public async Task Can_Build_Generated_Code_With_IDisposable(SampleOpenSpecificat
.Should()
.BeTrue();
}

[Theory]
[InlineData(SampleOpenSpecifications.SwaggerPetstoreJsonV3, "SwaggerPetstore.json")]
[InlineData(SampleOpenSpecifications.SwaggerPetstoreYamlV3, "SwaggerPetstore.yaml")]
[InlineData(SampleOpenSpecifications.SwaggerPetstoreJsonV2, "SwaggerPetstore.json")]
[InlineData(SampleOpenSpecifications.SwaggerPetstoreYamlV2, "SwaggerPetstore.yaml")]
public async Task Can_Generate_Interface_With_Summary(SampleOpenSpecifications version, string filename)
{
var settings = new RefitGeneratorSettings { GenerateXmlDocCodeComments = true };
var generateCode = await GenerateCode(version, filename, settings);
generateCode.Should().Contain("<summary>Swagger Petstore");
}
}
3 changes: 2 additions & 1 deletion src/Refitter/GenerateCommand.cs
Original file line number Diff line number Diff line change
Expand Up @@ -193,7 +193,8 @@ private static RefitGeneratorSettings CreateRefitGeneratorSettings(Settings sett
ContractsNamespace = settings.ContractsNamespace,
UsePolymorphicSerialization = settings.UsePolymorphicSerialization,
GenerateDisposableClients = settings.GenerateDisposableClients,
CollectionFormat = settings.CollectionFormat
CollectionFormat = settings.CollectionFormat,
GenerateXmlDocCodeComments = !settings.NoXmlDocCodeComments
};
}
private static async Task WriteSingleFile(
Expand Down
7 changes: 6 additions & 1 deletion src/Refitter/Settings.cs
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,12 @@ public sealed class Settings : CommandSettings
[Description("Don't add <auto-generated> header to output file")]
[CommandOption("--no-auto-generated-header")]
[DefaultValue(false)]
public bool NoAutoGeneratedHeader { get; set; }
public bool NoAutoGeneratedHeader { get; set; }

[Description("Don't generate XML doc comments for interfaces and operations")]
[CommandOption("--no-xml-doc-comments")]
[DefaultValue(false)]
public bool NoXmlDocCodeComments { get; set; }

[Description("Don't add <Accept> header to output file")]
[CommandOption("--no-accept-headers")]
Expand Down
Loading