Skip to content

Commit 2d42791

Browse files
Copilotcaptainsafia
andcommitted
Fix runtime lookup to use normalized documentation IDs
Co-authored-by: captainsafia <[email protected]>
1 parent 7215cca commit 2d42791

11 files changed

+240
-1584
lines changed

src/OpenApi/gen/XmlCommentGenerator.Emitter.cs

Lines changed: 30 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -302,6 +302,33 @@ private static string GetTypeDocId(Type type, bool includeGenericArguments, bool
302302
// For non-generic types, use FullName (if available) and replace nested type separators.
303303
return (type.FullName ?? type.Name).Replace('+', '.');
304304
}
305+
306+
/// <summary>
307+
/// Normalizes a documentation comment ID to match the compiler-style format.
308+
/// Strips the return type suffix for ordinary methods but retains it for conversion operators.
309+
/// </summary>
310+
/// <param name="docId">The documentation comment ID to normalize.</param>
311+
/// <returns>The normalized documentation comment ID.</returns>
312+
public static string NormalizeDocId(string docId)
313+
{
314+
// Find the tilde character that indicates the return type suffix
315+
var tildeIndex = docId.IndexOf('~');
316+
if (tildeIndex == -1)
317+
{
318+
// No return type suffix, return as-is
319+
return docId;
320+
}
321+
322+
// Check if this is a conversion operator (op_Implicit or op_Explicit)
323+
// For these operators, we need to keep the return type suffix
324+
if (docId.Contains("op_Implicit") || docId.Contains("op_Explicit"))
325+
{
326+
return docId;
327+
}
328+
329+
// For ordinary methods, strip the return type suffix
330+
return docId.Substring(0, tildeIndex);
331+
}
305332
}
306333
307334
{{GeneratedCodeAttribute}}
@@ -317,7 +344,7 @@ public Task TransformAsync(OpenApiOperation operation, OpenApiOperationTransform
317344
{
318345
return Task.CompletedTask;
319346
}
320-
if (XmlCommentCache.Cache.TryGetValue(methodInfo.CreateDocumentationId(), out var methodComment))
347+
if (XmlCommentCache.Cache.TryGetValue(DocumentationCommentIdHelper.NormalizeDocId(methodInfo.CreateDocumentationId()), out var methodComment))
321348
{
322349
if (methodComment.Summary is { } summary)
323350
{
@@ -423,7 +450,7 @@ public Task TransformAsync(OpenApiSchema schema, OpenApiSchemaTransformerContext
423450
{
424451
if (context.JsonPropertyInfo is { AttributeProvider: PropertyInfo propertyInfo })
425452
{
426-
if (XmlCommentCache.Cache.TryGetValue(propertyInfo.CreateDocumentationId(), out var propertyComment))
453+
if (XmlCommentCache.Cache.TryGetValue(DocumentationCommentIdHelper.NormalizeDocId(propertyInfo.CreateDocumentationId()), out var propertyComment))
427454
{
428455
schema.Description = propertyComment.Value ?? propertyComment.Returns ?? propertyComment.Summary;
429456
if (propertyComment.Examples?.FirstOrDefault() is { } jsonString)
@@ -432,7 +459,7 @@ public Task TransformAsync(OpenApiSchema schema, OpenApiSchemaTransformerContext
432459
}
433460
}
434461
}
435-
if (XmlCommentCache.Cache.TryGetValue(context.JsonTypeInfo.Type.CreateDocumentationId(), out var typeComment))
462+
if (XmlCommentCache.Cache.TryGetValue(DocumentationCommentIdHelper.NormalizeDocId(context.JsonTypeInfo.Type.CreateDocumentationId()), out var typeComment))
436463
{
437464
schema.Description = typeComment.Summary;
438465
if (typeComment.Examples?.FirstOrDefault() is { } jsonString)
Lines changed: 30 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -284,6 +284,33 @@ private static string GetTypeDocId(Type type, bool includeGenericArguments, bool
284284
// For non-generic types, use FullName (if available) and replace nested type separators.
285285
return (type.FullName ?? type.Name).Replace('+', '.');
286286
}
287+
288+
/// <summary>
289+
/// Normalizes a documentation comment ID to match the compiler-style format.
290+
/// Strips the return type suffix for ordinary methods but retains it for conversion operators.
291+
/// </summary>
292+
/// <param name="docId">The documentation comment ID to normalize.</param>
293+
/// <returns>The normalized documentation comment ID.</returns>
294+
public static string NormalizeDocId(string docId)
295+
{
296+
// Find the tilde character that indicates the return type suffix
297+
var tildeIndex = docId.IndexOf('~');
298+
if (tildeIndex == -1)
299+
{
300+
// No return type suffix, return as-is
301+
return docId;
302+
}
303+
304+
// Check if this is a conversion operator (op_Implicit or op_Explicit)
305+
// For these operators, we need to keep the return type suffix
306+
if (docId.Contains("op_Implicit") || docId.Contains("op_Explicit"))
307+
{
308+
return docId;
309+
}
310+
311+
// For ordinary methods, strip the return type suffix
312+
return docId.Substring(0, tildeIndex);
313+
}
287314
}
288315

289316
[System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.AspNetCore.OpenApi.SourceGenerators, Version=42.42.42.42, Culture=neutral, PublicKeyToken=adb9793829ddae60", "42.42.42.42")]
@@ -299,7 +326,7 @@ public Task TransformAsync(OpenApiOperation operation, OpenApiOperationTransform
299326
{
300327
return Task.CompletedTask;
301328
}
302-
if (XmlCommentCache.Cache.TryGetValue(methodInfo.CreateDocumentationId(), out var methodComment))
329+
if (XmlCommentCache.Cache.TryGetValue(DocumentationCommentIdHelper.NormalizeDocId(methodInfo.CreateDocumentationId()), out var methodComment))
303330
{
304331
if (methodComment.Summary is { } summary)
305332
{
@@ -405,7 +432,7 @@ public Task TransformAsync(OpenApiSchema schema, OpenApiSchemaTransformerContext
405432
{
406433
if (context.JsonPropertyInfo is { AttributeProvider: PropertyInfo propertyInfo })
407434
{
408-
if (XmlCommentCache.Cache.TryGetValue(propertyInfo.CreateDocumentationId(), out var propertyComment))
435+
if (XmlCommentCache.Cache.TryGetValue(DocumentationCommentIdHelper.NormalizeDocId(propertyInfo.CreateDocumentationId()), out var propertyComment))
409436
{
410437
schema.Description = propertyComment.Value ?? propertyComment.Returns ?? propertyComment.Summary;
411438
if (propertyComment.Examples?.FirstOrDefault() is { } jsonString)
@@ -414,7 +441,7 @@ public Task TransformAsync(OpenApiSchema schema, OpenApiSchemaTransformerContext
414441
}
415442
}
416443
}
417-
if (XmlCommentCache.Cache.TryGetValue(context.JsonTypeInfo.Type.CreateDocumentationId(), out var typeComment))
444+
if (XmlCommentCache.Cache.TryGetValue(DocumentationCommentIdHelper.NormalizeDocId(context.JsonTypeInfo.Type.CreateDocumentationId()), out var typeComment))
418445
{
419446
schema.Description = typeComment.Summary;
420447
if (typeComment.Examples?.FirstOrDefault() is { } jsonString)
Lines changed: 30 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -313,6 +313,33 @@ private static string GetTypeDocId(Type type, bool includeGenericArguments, bool
313313
// For non-generic types, use FullName (if available) and replace nested type separators.
314314
return (type.FullName ?? type.Name).Replace('+', '.');
315315
}
316+
317+
/// <summary>
318+
/// Normalizes a documentation comment ID to match the compiler-style format.
319+
/// Strips the return type suffix for ordinary methods but retains it for conversion operators.
320+
/// </summary>
321+
/// <param name="docId">The documentation comment ID to normalize.</param>
322+
/// <returns>The normalized documentation comment ID.</returns>
323+
public static string NormalizeDocId(string docId)
324+
{
325+
// Find the tilde character that indicates the return type suffix
326+
var tildeIndex = docId.IndexOf('~');
327+
if (tildeIndex == -1)
328+
{
329+
// No return type suffix, return as-is
330+
return docId;
331+
}
332+
333+
// Check if this is a conversion operator (op_Implicit or op_Explicit)
334+
// For these operators, we need to keep the return type suffix
335+
if (docId.Contains("op_Implicit") || docId.Contains("op_Explicit"))
336+
{
337+
return docId;
338+
}
339+
340+
// For ordinary methods, strip the return type suffix
341+
return docId.Substring(0, tildeIndex);
342+
}
316343
}
317344

318345
[System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.AspNetCore.OpenApi.SourceGenerators, Version=42.42.42.42, Culture=neutral, PublicKeyToken=adb9793829ddae60", "42.42.42.42")]
@@ -328,7 +355,7 @@ public Task TransformAsync(OpenApiOperation operation, OpenApiOperationTransform
328355
{
329356
return Task.CompletedTask;
330357
}
331-
if (XmlCommentCache.Cache.TryGetValue(methodInfo.CreateDocumentationId(), out var methodComment))
358+
if (XmlCommentCache.Cache.TryGetValue(DocumentationCommentIdHelper.NormalizeDocId(methodInfo.CreateDocumentationId()), out var methodComment))
332359
{
333360
if (methodComment.Summary is { } summary)
334361
{
@@ -434,7 +461,7 @@ public Task TransformAsync(OpenApiSchema schema, OpenApiSchemaTransformerContext
434461
{
435462
if (context.JsonPropertyInfo is { AttributeProvider: PropertyInfo propertyInfo })
436463
{
437-
if (XmlCommentCache.Cache.TryGetValue(propertyInfo.CreateDocumentationId(), out var propertyComment))
464+
if (XmlCommentCache.Cache.TryGetValue(DocumentationCommentIdHelper.NormalizeDocId(propertyInfo.CreateDocumentationId()), out var propertyComment))
438465
{
439466
schema.Description = propertyComment.Value ?? propertyComment.Returns ?? propertyComment.Summary;
440467
if (propertyComment.Examples?.FirstOrDefault() is { } jsonString)
@@ -443,7 +470,7 @@ public Task TransformAsync(OpenApiSchema schema, OpenApiSchemaTransformerContext
443470
}
444471
}
445472
}
446-
if (XmlCommentCache.Cache.TryGetValue(context.JsonTypeInfo.Type.CreateDocumentationId(), out var typeComment))
473+
if (XmlCommentCache.Cache.TryGetValue(DocumentationCommentIdHelper.NormalizeDocId(context.JsonTypeInfo.Type.CreateDocumentationId()), out var typeComment))
447474
{
448475
schema.Description = typeComment.Summary;
449476
if (typeComment.Examples?.FirstOrDefault() is { } jsonString)

src/OpenApi/test/Microsoft.AspNetCore.OpenApi.SourceGenerators.Tests/snapshots/CompletenessTests.SupportsAllXmlTagsOnSchemas#OpenApiXmlCommentSupport.generated.received.cs

Lines changed: 30 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -405,6 +405,33 @@ private static string GetTypeDocId(Type type, bool includeGenericArguments, bool
405405
// For non-generic types, use FullName (if available) and replace nested type separators.
406406
return (type.FullName ?? type.Name).Replace('+', '.');
407407
}
408+
409+
/// <summary>
410+
/// Normalizes a documentation comment ID to match the compiler-style format.
411+
/// Strips the return type suffix for ordinary methods but retains it for conversion operators.
412+
/// </summary>
413+
/// <param name="docId">The documentation comment ID to normalize.</param>
414+
/// <returns>The normalized documentation comment ID.</returns>
415+
public static string NormalizeDocId(string docId)
416+
{
417+
// Find the tilde character that indicates the return type suffix
418+
var tildeIndex = docId.IndexOf('~');
419+
if (tildeIndex == -1)
420+
{
421+
// No return type suffix, return as-is
422+
return docId;
423+
}
424+
425+
// Check if this is a conversion operator (op_Implicit or op_Explicit)
426+
// For these operators, we need to keep the return type suffix
427+
if (docId.Contains("op_Implicit") || docId.Contains("op_Explicit"))
428+
{
429+
return docId;
430+
}
431+
432+
// For ordinary methods, strip the return type suffix
433+
return docId.Substring(0, tildeIndex);
434+
}
408435
}
409436

410437
[System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.AspNetCore.OpenApi.SourceGenerators, Version=42.42.42.42, Culture=neutral, PublicKeyToken=adb9793829ddae60", "42.42.42.42")]
@@ -420,7 +447,7 @@ public Task TransformAsync(OpenApiOperation operation, OpenApiOperationTransform
420447
{
421448
return Task.CompletedTask;
422449
}
423-
if (XmlCommentCache.Cache.TryGetValue(methodInfo.CreateDocumentationId(), out var methodComment))
450+
if (XmlCommentCache.Cache.TryGetValue(DocumentationCommentIdHelper.NormalizeDocId(methodInfo.CreateDocumentationId()), out var methodComment))
424451
{
425452
if (methodComment.Summary is { } summary)
426453
{
@@ -526,7 +553,7 @@ public Task TransformAsync(OpenApiSchema schema, OpenApiSchemaTransformerContext
526553
{
527554
if (context.JsonPropertyInfo is { AttributeProvider: PropertyInfo propertyInfo })
528555
{
529-
if (XmlCommentCache.Cache.TryGetValue(propertyInfo.CreateDocumentationId(), out var propertyComment))
556+
if (XmlCommentCache.Cache.TryGetValue(DocumentationCommentIdHelper.NormalizeDocId(propertyInfo.CreateDocumentationId()), out var propertyComment))
530557
{
531558
schema.Description = propertyComment.Value ?? propertyComment.Returns ?? propertyComment.Summary;
532559
if (propertyComment.Examples?.FirstOrDefault() is { } jsonString)
@@ -535,7 +562,7 @@ public Task TransformAsync(OpenApiSchema schema, OpenApiSchemaTransformerContext
535562
}
536563
}
537564
}
538-
if (XmlCommentCache.Cache.TryGetValue(context.JsonTypeInfo.Type.CreateDocumentationId(), out var typeComment))
565+
if (XmlCommentCache.Cache.TryGetValue(DocumentationCommentIdHelper.NormalizeDocId(context.JsonTypeInfo.Type.CreateDocumentationId()), out var typeComment))
539566
{
540567
schema.Description = typeComment.Summary;
541568
if (typeComment.Examples?.FirstOrDefault() is { } jsonString)

0 commit comments

Comments
 (0)