DocumentationHelper.cs 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125
  1. using System;
  2. using System.Linq;
  3. using System.Text;
  4. using System.Xml.Linq;
  5. namespace QuestPDF.InteropGenerators;
  6. /// <summary>
  7. /// Helper class for extracting and processing XML documentation comments
  8. /// </summary>
  9. public static class DocumentationHelper
  10. {
  11. /// <summary>
  12. /// Extracts documentation from XML documentation comments.
  13. /// Processes summary and remarks sections, stripping XML tags and formatting.
  14. /// </summary>
  15. /// <param name="xmlDocumentation">Raw XML documentation string from Roslyn symbol</param>
  16. /// <returns>Cleaned documentation text, or empty string if no documentation exists</returns>
  17. public static string ExtractDocumentation(string? xmlDocumentation)
  18. {
  19. if (string.IsNullOrWhiteSpace(xmlDocumentation))
  20. return string.Empty;
  21. var doc = new StringBuilder();
  22. try
  23. {
  24. var xml = XDocument.Parse(xmlDocumentation);
  25. // Extract summary
  26. var summary = xml.Descendants("summary").FirstOrDefault();
  27. if (summary != null)
  28. {
  29. var summaryText = CleanXmlContent(summary);
  30. if (!string.IsNullOrWhiteSpace(summaryText))
  31. doc.AppendLine(summaryText);
  32. }
  33. // Extract remarks
  34. var remarks = xml.Descendants("remarks").FirstOrDefault();
  35. if (remarks != null)
  36. {
  37. var remarksText = CleanXmlContent(remarks);
  38. if (!string.IsNullOrWhiteSpace(remarksText))
  39. {
  40. if (doc.Length > 0)
  41. doc.AppendLine();
  42. doc.Append(remarksText);
  43. }
  44. }
  45. }
  46. catch
  47. {
  48. // If XML parsing fails, return empty string
  49. return string.Empty;
  50. }
  51. return doc.ToString().Trim();
  52. }
  53. /// <summary>
  54. /// Cleans XML content by removing tags like &lt;see cref="..." /&gt; and normalizing whitespace
  55. /// </summary>
  56. /// <param name="element">XML element to clean</param>
  57. /// <returns>Cleaned text content</returns>
  58. private static string CleanXmlContent(XElement element)
  59. {
  60. var text = new StringBuilder();
  61. foreach (var node in element.Nodes())
  62. {
  63. if (node is XText textNode)
  64. {
  65. text.Append(textNode.Value);
  66. }
  67. else if (node is XElement childElement)
  68. {
  69. // Handle specific XML elements
  70. switch (childElement.Name.LocalName)
  71. {
  72. case "see":
  73. case "seealso":
  74. // Extract the referenced name from cref attribute
  75. var cref = childElement.Attribute("cref")?.Value;
  76. if (!string.IsNullOrEmpty(cref))
  77. {
  78. // Extract just the member name (e.g., "Height" from "ConstrainedExtensions.Height")
  79. var parts = cref.Split('.');
  80. var memberName = parts.Length > 0 ? parts[parts.Length - 1] : cref;
  81. text.Append(memberName);
  82. }
  83. else
  84. {
  85. // Fallback to inner text if no cref
  86. text.Append(childElement.Value);
  87. }
  88. break;
  89. case "paramref":
  90. case "typeparamref":
  91. // Extract parameter name
  92. var name = childElement.Attribute("name")?.Value ?? childElement.Value;
  93. text.Append(name);
  94. break;
  95. case "c":
  96. case "code":
  97. // Inline code or code blocks
  98. text.Append(childElement.Value);
  99. break;
  100. default:
  101. // For other elements, just get the text content
  102. text.Append(childElement.Value);
  103. break;
  104. }
  105. }
  106. }
  107. // Normalize whitespace: collapse multiple spaces/newlines into single spaces
  108. var result = text.ToString();
  109. result = System.Text.RegularExpressions.Regex.Replace(result, @"\s+", " ");
  110. return result.Trim();
  111. }
  112. }