11// Licensed to the .NET Foundation under one or more agreements.
22// The .NET Foundation licenses this file to you under the MIT license.
33
4- using System ;
54using System . Collections . Generic ;
65using System . Collections . Immutable ;
76using System . IO ;
@@ -44,6 +43,7 @@ namespace Microsoft.AspNetCore.OpenApi.Generated
4443{
4544 using System;
4645 using System.Collections.Generic;
46+ using System.Diagnostics.CodeAnalysis;
4747 using System.Linq;
4848 using System.Reflection;
4949 using System.Text.Json;
@@ -87,6 +87,16 @@ file static class XmlCommentCache
8787{{ commentsFromCompilation }}
8888 return _cache;
8989 }
90+
91+ internal static bool TryGetXmlComment(Type? type, string? memberName, [NotNullWhen(true)] out XmlComment? xmlComment)
92+ {
93+ if (type is not null && type.IsGenericType)
94+ {
95+ type = type.GetGenericTypeDefinition();
96+ }
97+
98+ return XmlCommentCache.Cache.TryGetValue((type, memberName), out xmlComment);
99+ }
90100 }
91101
92102 {{ GeneratedCodeAttribute }}
@@ -102,7 +112,7 @@ public Task TransformAsync(OpenApiOperation operation, OpenApiOperationTransform
102112 {
103113 return Task.CompletedTask;
104114 }
105- if (XmlCommentCache.Cache.TryGetValue(( methodInfo.DeclaringType, methodInfo.Name) , out var methodComment))
115+ if (XmlCommentCache.TryGetXmlComment( methodInfo.DeclaringType, methodInfo.Name, out var methodComment))
106116 {
107117 if (methodComment.Summary is { } summary)
108118 {
@@ -173,7 +183,7 @@ public Task TransformAsync(OpenApiSchema schema, OpenApiSchemaTransformerContext
173183 {
174184 if (context.JsonPropertyInfo is { AttributeProvider: PropertyInfo propertyInfo })
175185 {
176- if (XmlCommentCache.Cache.TryGetValue(( propertyInfo.DeclaringType, propertyInfo.Name) , out var propertyComment))
186+ if (XmlCommentCache.TryGetXmlComment( propertyInfo.DeclaringType, propertyInfo.Name, out var propertyComment))
177187 {
178188 schema.Description = propertyComment.Value ?? propertyComment.Returns ?? propertyComment.Summary;
179189 if (propertyComment.Examples?.FirstOrDefault() is { } jsonString)
@@ -182,7 +192,8 @@ public Task TransformAsync(OpenApiSchema schema, OpenApiSchemaTransformerContext
182192 }
183193 }
184194 }
185- if (XmlCommentCache.Cache.TryGetValue((context.JsonTypeInfo.Type, null), out var typeComment))
195+ System.Diagnostics.Debugger.Break();
196+ if (XmlCommentCache.TryGetXmlComment(context.JsonTypeInfo.Type, null, out var typeComment))
186197 {
187198 schema.Description = typeComment.Summary;
188199 if (typeComment.Examples?.FirstOrDefault() is { } jsonString)
@@ -312,61 +323,88 @@ internal static string EmitCommentsCache(IEnumerable<(string, string?, XmlCommen
312323 return writer . ToString ( ) ;
313324 }
314325
326+ private static string FormatStringForCode ( string ? input )
327+ {
328+ if ( input == null )
329+ {
330+ return "null" ;
331+ }
332+
333+ var formatted = input
334+ . Replace ( "\" " , "\" \" " ) ; // Escape double quotes
335+
336+ return $ "@\" { formatted } \" ";
337+ }
338+
315339 internal static string EmitSourceGeneratedXmlComment ( XmlComment comment )
316340 {
317341 var writer = new StringWriter ( ) ;
318342 var codeWriter = new CodeWriter ( writer , baseIndent : 0 ) ;
319343 codeWriter . Write ( $ "new XmlComment(") ;
320- codeWriter . Write ( comment . Summary is null ? "null," : $ " \" \" { SymbolDisplay . FormatLiteral ( comment . Summary , true ) } \" \ " , ") ;
321- codeWriter . Write ( comment . Description is null ? "null," : $ " \" \" { SymbolDisplay . FormatLiteral ( comment . Description , true ) } \" \ " , ") ;
322- codeWriter . Write ( comment . Remarks is null ? "null," : $ " \" \" { SymbolDisplay . FormatLiteral ( comment . Remarks , true ) } \" \ " , ") ;
323- codeWriter . Write ( comment . Returns is null ? "null," : $ " \" \" { SymbolDisplay . FormatLiteral ( comment . Returns , true ) } \" \ " , ") ;
324- codeWriter . Write ( comment . Value is null ? "null," : $ " \" \" { SymbolDisplay . FormatLiteral ( comment . Value , true ) } \" \ " , ") ;
325- codeWriter . Write ( comment . Deprecated is null ? "false," : $ " { SymbolDisplay . FormatPrimitive ( comment . Deprecated == true ? "true" : "false" , false , false ) } , ") ;
326- if ( comment . Examples is null )
344+ codeWriter . Write ( FormatStringForCode ( comment . Summary ) + ", " ) ;
345+ codeWriter . Write ( FormatStringForCode ( comment . Description ) + ", " ) ;
346+ codeWriter . Write ( FormatStringForCode ( comment . Remarks ) + ", " ) ;
347+ codeWriter . Write ( FormatStringForCode ( comment . Returns ) + ", " ) ;
348+ codeWriter . Write ( FormatStringForCode ( comment . Value ) + ", " ) ;
349+ codeWriter . Write ( comment . Deprecated == true ? "true" : "false" + " , ") ;
350+ if ( comment . Examples is null || comment . Examples . Count == 0 )
327351 {
328352 codeWriter . Write ( "null, " ) ;
329353 }
330354 else
331355 {
332- codeWriter . Write ( "new List<string>" ) ;
333- codeWriter . Write ( "{" ) ;
334- foreach ( var example in comment . Examples )
356+ codeWriter . Write ( "[" ) ;
357+ for ( int i = 0 ; i < comment . Examples . Count ; i ++ )
335358 {
336- codeWriter . Write ( $ "@\" { example } \" , ") ;
359+ var example = comment . Examples [ i ] ;
360+ codeWriter . Write ( FormatStringForCode ( example ) ) ;
361+ if ( i < comment . Examples . Count - 1 )
362+ {
363+ codeWriter . Write ( ", " ) ;
364+ }
337365 }
338- codeWriter . Write ( "} , " ) ;
366+ codeWriter . Write ( "] , " ) ;
339367 }
340- if ( comment . Parameters is null )
368+
369+ if ( comment . Parameters is null || comment . Parameters . Count == 0 )
341370 {
342371 codeWriter . Write ( "null, " ) ;
343372 }
344373 else
345374 {
346- codeWriter . Write ( "new List<XmlParameterComment>" ) ;
347- codeWriter . Write ( "{" ) ;
348- foreach ( var parameter in comment . Parameters )
375+ codeWriter . Write ( "[" ) ;
376+ for ( int i = 0 ; i < comment . Parameters . Count ; i ++ )
349377 {
378+ var parameter = comment . Parameters [ i ] ;
350379 var exampleLiteral = string . IsNullOrEmpty ( parameter . Example )
351380 ? "null"
352- : $ "\" \" \" { parameter . Example ! } \" \" \" ";
353- codeWriter . Write ( $ "new XmlParameterComment(@\" { parameter . Name } \" , @\" { parameter . Description } \" , { exampleLiteral } , { ( parameter . Deprecated == true ? "true" : "false" ) } ), ") ;
381+ : FormatStringForCode ( parameter . Example ! ) ;
382+ codeWriter . Write ( $ "new XmlParameterComment(@\" { parameter . Name } \" , @\" { parameter . Description } \" , { exampleLiteral } , { ( parameter . Deprecated == true ? "true" : "false" ) } )") ;
383+ if ( i < comment . Parameters . Count - 1 )
384+ {
385+ codeWriter . Write ( ", " ) ;
386+ }
354387 }
355- codeWriter . Write ( "} , " ) ;
388+ codeWriter . Write ( "], " ) ;
356389 }
357- if ( comment . Responses is null )
390+
391+ if ( comment . Responses is null || comment . Responses . Count == 0 )
358392 {
359393 codeWriter . Write ( "null" ) ;
360394 }
361395 else
362396 {
363- codeWriter . Write ( "new List<XmlResponseComment>" ) ;
364- codeWriter . Write ( "{" ) ;
365- foreach ( var response in comment . Responses )
397+ codeWriter . Write ( "[" ) ;
398+ for ( int i = 0 ; i < comment . Responses . Count ; i ++ )
366399 {
367- codeWriter . Write ( $ "new XmlResponseComment(@\" { response . Code } \" , @\" { response . Description } \" , @\" { response . Example } \" ), ") ;
400+ var response = comment . Responses [ i ] ;
401+ codeWriter . Write ( $ "new XmlResponseComment(@\" { response . Code } \" , @\" { response . Description } \" , { ( response . Example is null ? "null" : FormatStringForCode ( response . Example ) ) } )") ;
402+ if ( i < comment . Responses . Count - 1 )
403+ {
404+ codeWriter . Write ( ", " ) ;
405+ }
368406 }
369- codeWriter . Write ( "} " ) ;
407+ codeWriter . Write ( "] " ) ;
370408 }
371409 codeWriter . Write ( ")" ) ;
372410 return writer . ToString ( ) ;
0 commit comments