diff --git a/src/Docfx.Dotnet/Parsers/XmlComment.Extensions.cs b/src/Docfx.Dotnet/Parsers/XmlComment.Extensions.cs new file mode 100644 index 00000000000..c34fb0defd5 --- /dev/null +++ b/src/Docfx.Dotnet/Parsers/XmlComment.Extensions.cs @@ -0,0 +1,296 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.Diagnostics; +using System.Xml; +using System.Xml.Linq; +using System.Xml.XPath; + +namespace Docfx.Dotnet; + +internal partial class XmlComment +{ + // List of block tags that are defined by CommonMark + // https://spec.commonmark.org/0.31.2/#html-blocks + private static readonly string[] BlockTags = + { + "ol", + "p", + "table", + "ul", + + // Recommended XML tags for C# documentation comments + "example", + + // Other tags + "pre", + }; + + private static readonly Lazy BlockTagsXPath = new(string.Join(" | ", BlockTags.Select(tagName => $".//{tagName}"))); + + /// + /// Gets markdown text from XElement. + /// + private static string GetMarkdownText(XElement elem) + { + // Gets HTML block tags by XPath. + var nodes = elem.XPathSelectElements(BlockTagsXPath.Value).ToArray(); + + // Insert HTML/Markdown separator lines. + foreach (var node in nodes) + { + if (node.NeedEmptyLineBefore()) + node.InsertEmptyLineBefore(); + + if (node.NeedEmptyLineAfter()) + node.AddAfterSelf(new XText("\n")); + } + + return elem.GetInnerXml(); + } + + private static string GetInnerXml(XElement elem) + => elem.GetInnerXml(); +} + +// Define file scoped extension methods. +static file class XElementExtensions +{ + /// + /// Gets inner XML text of XElement. + /// + public static string GetInnerXml(this XElement elem) + { + using var sw = new StringWriter(); + using var writer = XmlWriter.Create(sw, new XmlWriterSettings + { + OmitXmlDeclaration = true, + ConformanceLevel = ConformanceLevel.Fragment, // Required to write XML partial fragment + Indent = false, // Preserve original indents + NewLineChars = "\n", // Use LF + }); + + var nodes = elem.Nodes().ToArray(); + foreach (var node in nodes) + { + node.WriteTo(writer); + } + writer.Flush(); + + var xml = sw.ToString(); + + // Remove shared indents. + xml = RemoveCommonIndent(xml); + + // Trim beginning spaces/lines if text starts with HTML tag. + var firstNode = nodes.FirstOrDefault(x => !x.IsWhitespaceNode()); + if (firstNode != null && firstNode.NodeType == XmlNodeType.Element) + xml = xml.TrimStart(); + + // Trim ending spaces/lines if text ends with HTML tag. + var lastNode = nodes.LastOrDefault(x => !x.IsWhitespaceNode()); + if (lastNode != null && lastNode.NodeType == XmlNodeType.Element) + xml = xml.TrimEnd(); + + return xml; + } + + public static bool NeedEmptyLineBefore(this XElement node) + { + if (!node.TryGetNonWhitespacePrevNode(out var prevNode)) + return false; + + switch (prevNode.NodeType) + { + // If prev node is HTML element. No need to insert empty line. + case XmlNodeType.Element: + return false; + + // Ensure empty lines exists before text node. + case XmlNodeType.Text: + var prevTextNode = (XText)prevNode; + + // No need to insert line if prev node ends with empty line. + if (prevTextNode.Value.EndsWithEmptyLine()) + return false; + + return true; + + default: + return false; + } + } + + public static void InsertEmptyLineBefore(this XElement elem) + { + if (!elem.TryGetNonWhitespacePrevNode(out var prevNode)) + return; + + Debug.Assert(prevNode.NodeType == XmlNodeType.Text); + + var prevTextNode = (XText)prevNode; + var span = prevTextNode.Value.AsSpan(); + int index = span.LastIndexOf('\n'); + + ReadOnlySpan lastLine = index == -1 + ? span + : span.Slice(index + 1); + + if (lastLine.Length > 0 && lastLine.IsWhiteSpace()) + { + // Insert new line before indent of last line. + prevTextNode.Value = prevTextNode.Value.Insert(index, "\n"); + } + else + { + elem.AddBeforeSelf(new XText("\n")); + } + } + + private static bool EndsWithEmptyLine(this ReadOnlySpan span) + { + var index = span.LastIndexOfAnyExcept([' ', '\t']); + if (index >= 0 && span[index] == '\n') + { + span = span.Slice(0, index); + index = span.LastIndexOfAnyExcept([' ', '\t']); + if (index >= 0 && span[index] == '\n') + return true; + } + + return false; + } + + private static bool TryGetNonWhitespacePrevNode(this XElement elem, out XNode result) + { + var prev = elem.PreviousNode; + while (prev != null && prev.IsWhitespaceNode()) + prev = prev.PreviousNode; + + if (prev == null) + { + result = null; + return false; + } + + result = prev; + return true; + } + + public static bool NeedEmptyLineAfter(this XElement node) + { + if (!node.TryGetNonWhitespaceNextNode(out var nextNode)) + return false; + + switch (nextNode.NodeType) + { + // If next node is HTML element. No need to insert new line. + case XmlNodeType.Element: + return false; + + // Ensure empty lines exists after node. + case XmlNodeType.Text: + var nextTextNode = (XText)nextNode; + var textSpan = nextTextNode.Value.AsSpan(); + + // No need to insert line if prev node ends with empty line. + if (textSpan.StartsWithEmptyLine()) + return false; + + return true; + + default: + return false; + } + } + private static bool StartsWithEmptyLine(this ReadOnlySpan span) + { + var index = span.IndexOfAnyExcept([' ', '\t']); + if (index >= 0 && span[index] == '\n') + { + ++index; + if (index > span.Length) + return false; + + span = span.Slice(index); + index = span.IndexOfAnyExcept([' ', '\t']); + + if (index < 0 || span[index] == '\n') + return true; // There is no content or empty line is already exists. + } + return false; + } + + private static bool TryGetNonWhitespaceNextNode(this XElement elem, out XNode result) + { + var next = elem.NextNode; + while (next != null && next.IsWhitespaceNode()) + next = next.NextNode; + + if (next == null) + { + result = null; + return false; + } + + result = next; + return true; + } + + private static string RemoveCommonIndent(string text) + { + var lines = text.Split('\n').ToArray(); + + var inPre = false; + var indentCounts = new List(); + + // Caluculate line's indent chars (
 tag region is excluded)
+        foreach (var line in lines)
+        {
+            if (!inPre && !string.IsNullOrWhiteSpace(line))
+            {
+                int indent = line.TakeWhile(c => c == ' ' || c == '\t').Count();
+                indentCounts.Add(indent);
+            }
+
+            var trimmed = line.Trim();
+            if (trimmed.StartsWith("", StringComparison.OrdinalIgnoreCase))
+                inPre = false;
+        }
+
+        int minIndent = indentCounts.DefaultIfEmpty(0).Min();
+
+        inPre = false;
+        var resultLines = new List();
+        foreach (var line in lines)
+        {
+            if (!inPre && line.Length >= minIndent)
+                resultLines.Add(line.Substring(minIndent));
+            else
+                resultLines.Add(line);
+
+            // Update inPre flag.
+            var trimmed = line.Trim();
+            if (trimmed.StartsWith("
", StringComparison.OrdinalIgnoreCase))
+                inPre = true;
+            if (trimmed.EndsWith("
", StringComparison.OrdinalIgnoreCase)) + inPre = false; + } + + // Insert empty line to append `\n`. + resultLines.Add(""); + + return string.Join("\n", resultLines); + } + + private static bool IsWhitespaceNode(this XNode node) + { + if (node is not XText textNode) + return false; + + return textNode.Value.All(char.IsWhiteSpace); + } +} diff --git a/src/Docfx.Dotnet/Parsers/XmlComment.cs b/src/Docfx.Dotnet/Parsers/XmlComment.cs index 5e736979005..f6c5ed60a56 100644 --- a/src/Docfx.Dotnet/Parsers/XmlComment.cs +++ b/src/Docfx.Dotnet/Parsers/XmlComment.cs @@ -93,15 +93,15 @@ private XmlComment(string xml, XmlCommentParserContext context) ResolveCode(doc, context); var nav = doc.CreateNavigator(); - Summary = GetSingleNodeValue(nav, "/member/summary"); - Remarks = GetSingleNodeValue(nav, "/member/remarks"); - Returns = GetSingleNodeValue(nav, "/member/returns"); + Summary = GetSingleNodeValue(doc, "/member/summary"); + Remarks = GetSingleNodeValue(doc, "/member/remarks"); + Returns = GetSingleNodeValue(doc, "/member/returns"); - Exceptions = ToListNullOnEmpty(GetMultipleCrefInfo(nav, "/member/exception")); - SeeAlsos = ToListNullOnEmpty(GetMultipleLinkInfo(nav, "/member/seealso")); - Examples = GetMultipleExampleNodes(nav, "/member/example").ToList(); - Parameters = GetListContent(nav, "/member/param", "parameter", context); - TypeParameters = GetListContent(nav, "/member/typeparam", "type parameter", context); + Exceptions = ToListNullOnEmpty(GetMultipleCrefInfo(doc, "/member/exception")); + SeeAlsos = ToListNullOnEmpty(GetMultipleLinkInfo(doc, "/member/seealso")); + Examples = GetMultipleExampleNodes(doc, "/member/example").ToList(); + Parameters = GetListContent(doc, "/member/param", "parameter", context); + TypeParameters = GetListContent(doc, "/member/typeparam", "type parameter", context); // Nulls and empty list are treated differently in overwrite files: // null values can be replaced, but empty list are merged by merge key @@ -142,17 +142,22 @@ public string GetTypeParameter(string name) return TypeParameters.GetValueOrDefault(name); } - private void ResolveCode(XDocument doc, XmlCommentParserContext context) + private static void ResolveCode(XDocument doc, XmlCommentParserContext context) { - foreach (var node in doc.XPathSelectElements("//code").ToList()) + var nodes = doc.XPathSelectElements("//code").ToArray(); + foreach (var node in nodes) { + // Remove `data-inline` attribute if it exists. if (node.Attribute("data-inline") is { } inlineAttribute) { inlineAttribute.Remove(); continue; } + // Gets indents placed before `` tag var indent = new string(' ', ((IXmlLineInfo)node).LinePosition - 2); + + // Try to resolve `source` attribute var (lang, value) = ResolveCodeSource(node, context); value = TrimEachLine(value ?? node.Value, indent); var code = new XElement("code", value); @@ -169,18 +174,7 @@ private void ResolveCode(XDocument doc, XmlCommentParserContext context) code.SetAttributeValue("class", $"lang-{lang}"); - if (node.PreviousNode is null - || node.PreviousNode is XText xText && xText.Value == $"\n{indent}") - { - // Xml writer formats
 with unintended identation
-                // when there is no preceeding text node.
-                // Prepend a text node with the same indentation to force 
.
-                node.ReplaceWith($"\n{indent}", new XElement("pre", code));
-            }
-            else
-            {
-                node.ReplaceWith(new XElement("pre", code));
-            }
+            node.ReplaceWith(new XElement("pre", code));
         }
     }
 
@@ -256,25 +250,23 @@ private static IEnumerable ReadLines(string text)
         }
     }
 
-    private Dictionary GetListContent(XPathNavigator navigator, string xpath, string contentType, XmlCommentParserContext context)
+    private Dictionary GetListContent(XDocument doc, string xpath, string contentType, XmlCommentParserContext context)
     {
-        var iterator = navigator.Select(xpath);
         var result = new Dictionary();
-        if (iterator == null)
-        {
-            return result;
-        }
-        foreach (XPathNavigator nav in iterator)
+        var nodes = doc.XPathSelectElements(xpath).ToArray();
+
+        foreach (var node in nodes)
         {
-            string name = nav.GetAttribute("name", string.Empty);
-            string description = GetXmlValue(nav);
-            if (!string.IsNullOrEmpty(name))
+            var name = node.Attribute("name")?.Value;
+            if (name == null)
+                continue;
+
+            string description = GetXmlValue(node);
+
+            if (!result.TryAdd(name, description))
             {
-                if (!result.TryAdd(name, description))
-                {
-                    string path = context.Source?.Remote != null ? Path.Combine(EnvironmentContext.BaseDirectory, context.Source.Remote.Path) : context.Source?.Path;
-                    Logger.LogWarning($"Duplicate {contentType} '{name}' found in comments, the latter one is ignored.", file: StringExtension.ToDisplayPath(path), line: context.Source?.StartLine.ToString());
-                }
+                string path = context.Source?.Remote != null ? Path.Combine(EnvironmentContext.BaseDirectory, context.Source.Remote.Path) : context.Source?.Path;
+                Logger.LogWarning($"Duplicate {contentType} '{name}' found in comments, the latter one is ignored.", file: StringExtension.ToDisplayPath(path), line: context.Source?.StartLine.ToString());
             }
         }
 
@@ -402,81 +394,75 @@ private void ResolveCrefLink(XNode node, string nodeSelector, Action GetMultipleExampleNodes(XPathNavigator navigator, string selector)
+    private IEnumerable GetMultipleExampleNodes(XDocument doc, string selector)
     {
-        var iterator = navigator.Select(selector);
-        if (iterator == null)
-        {
-            yield break;
-        }
-        foreach (XPathNavigator nav in iterator)
+        // Gets nodes with XPath selector
+        var nodes = doc.XPathSelectElements(selector).ToArray();
+        foreach (var node in nodes)
         {
-            yield return GetXmlValue(nav);
+            var xml = GetXmlValue(node);
+            yield return xml;
         }
     }
 
-    private IEnumerable GetMultipleCrefInfo(XPathNavigator navigator, string selector)
+    private IEnumerable GetMultipleCrefInfo(XDocument doc, string selector)
     {
-        var iterator = navigator.Clone().Select(selector);
-        if (iterator == null)
+        var nodes = doc.XPathSelectElements(selector).ToArray();
+        foreach (var node in nodes)
         {
-            yield break;
-        }
-        foreach (XPathNavigator nav in iterator)
-        {
-            string description = GetXmlValue(nav);
-            string commentId = nav.GetAttribute("cref", string.Empty);
-            string refId = nav.GetAttribute("refId", string.Empty);
-            if (!string.IsNullOrEmpty(refId))
+            string description = GetXmlValue(node);
+            string commentId = node.Attribute("cref")?.Value ?? "";
+            string refId = node.Attribute("refId")?.Value ?? "";
+
+            if (refId != "")
             {
                 yield return new ExceptionInfo
                 {
                     Description = description,
                     Type = refId,
-                    CommentId = commentId
+                    CommentId = commentId,
                 };
+                continue;
             }
-            else if (!string.IsNullOrEmpty(commentId))
+
+            if (commentId == "")
+                continue;
+
+            // Check if exception type is valid and trim prefix
+            var match = CommentIdRegex().Match(commentId);
+            if (match.Success)
             {
-                // Check if exception type is valid and trim prefix
-                var match = CommentIdRegex().Match(commentId);
-                if (match.Success)
+                var id = match.Groups["id"].Value;
+                var type = match.Groups["type"].Value;
+                if (type == "T")
                 {
-                    var id = match.Groups["id"].Value;
-                    var type = match.Groups["type"].Value;
-                    if (type == "T")
+                    yield return new ExceptionInfo
                     {
-                        yield return new ExceptionInfo
-                        {
-                            Description = description,
-                            Type = id,
-                            CommentId = commentId
-                        };
-                    }
+                        Description = description,
+                        Type = id,
+                        CommentId = commentId,
+                    };
                 }
             }
         }
     }
 
-    private static IEnumerable GetMultipleLinkInfo(XPathNavigator navigator, string selector)
+    private static IEnumerable GetMultipleLinkInfo(XDocument doc, string selector)
     {
-        var iterator = navigator.Clone().Select(selector);
-        if (iterator == null)
-        {
-            yield break;
-        }
-        foreach (XPathNavigator nav in iterator)
+        var nodes = doc.XPathSelectElements(selector).ToArray();
+
+        foreach (var node in nodes)
         {
-            string altText = nav.InnerXml.Trim();
+            string altText = GetInnerXml(node).Trim();
             if (string.IsNullOrEmpty(altText))
             {
                 altText = null;
             }
 
-            string commentId = nav.GetAttribute("cref", string.Empty);
-            string url = nav.GetAttribute("href", string.Empty);
-            string refId = nav.GetAttribute("refId", string.Empty);
-            if (!string.IsNullOrEmpty(refId))
+            string commentId = node.Attribute("cref")?.Value ?? "";
+            string refId = node.Attribute("refId")?.Value ?? "";
+
+            if (refId != "")
             {
                 yield return new LinkInfo
                 {
@@ -485,8 +471,10 @@ private static IEnumerable GetMultipleLinkInfo(XPathNavigator navigato
                     CommentId = commentId,
                     LinkType = LinkType.CRef
                 };
+                continue;
             }
-            else if (!string.IsNullOrEmpty(commentId))
+
+            if (commentId != "")
             {
                 // Check if cref type is valid and trim prefix
                 var match = CommentIdRegex().Match(commentId);
@@ -507,8 +495,11 @@ private static IEnumerable GetMultipleLinkInfo(XPathNavigator navigato
                         LinkType = LinkType.CRef
                     };
                 }
+                continue;
             }
-            else if (!string.IsNullOrEmpty(url))
+
+            string url = node.Attribute("href")?.Value ?? "";
+            if (!string.IsNullOrEmpty(url))
             {
                 yield return new LinkInfo
                 {
@@ -520,20 +511,29 @@ private static IEnumerable GetMultipleLinkInfo(XPathNavigator navigato
         }
     }
 
-    private string GetSingleNodeValue(XPathNavigator nav, string selector)
+    private string GetSingleNodeValue(XDocument doc, string selector)
     {
-        return GetXmlValue(nav.Clone().SelectSingleNode(selector));
+        var elem = doc.XPathSelectElement(selector);
+
+        return GetXmlValue(elem);
     }
 
-    private string GetXmlValue(XPathNavigator node)
+    private string GetXmlValue(XElement node)
     {
         if (node is null)
             return null;
 
         if (_context.SkipMarkup)
-            return TrimEachLine(node.InnerXml);
+            return TrimEachLine(GetInnerXml(node));
+
+        // Gets markdown text from XElement. (Insert empty line between Markdown/HTML tags)
+        var xml = GetMarkdownText(node);
 
-        return GetInnerXmlAsMarkdown(TrimEachLine(node.InnerXml));
+        // Trim extra indents.
+        xml = TrimEachLine(xml);
+
+        // Decode XML Entity References to markdown
+        return GetInnerXmlAsMarkdown(xml);
     }
 
     private static string TrimEachLine(string text, string indent = "")
@@ -557,20 +557,11 @@ private static string TrimEachLine(string text, string indent = "")
         // Trim leading empty lines
         var trimStart = true;
 
-        // Apply indentation to all lines except the first,
-        // since the first new line in 
 is significant
-        var firstLine = true;
-
         foreach (var line in lines)
         {
             if (trimStart && string.IsNullOrWhiteSpace(line))
                 continue;
 
-            if (firstLine)
-                firstLine = false;
-            else
-                builder.Append(indent);
-
             if (string.IsNullOrWhiteSpace(line))
             {
                 builder.AppendLine();
@@ -584,13 +575,15 @@ private static string TrimEachLine(string text, string indent = "")
         return builder.ToString().TrimEnd();
     }
 
+    private static readonly MarkdownPipeline pipeline = new MarkdownPipelineBuilder().UseMathematics().EnableTrackTrivia().Build();
+
     private static string GetInnerXmlAsMarkdown(string xml)
     {
         if (!xml.Contains('&'))
             return xml;
 
         xml = HandleBlockQuote(xml);
-        var pipeline = new MarkdownPipelineBuilder().UseMathematics().EnableTrackTrivia().Build();
+
         var markdown = Markdown.Parse(xml, pipeline);
         MarkdownXmlDecode(markdown);
         var sw = new StringWriter();
diff --git a/test/Docfx.Dotnet.Tests/XmlCommentTests/XmlCommentExamplesTest.cs b/test/Docfx.Dotnet.Tests/XmlCommentTests/XmlCommentExamplesTest.cs
new file mode 100644
index 00000000000..f91f062017d
--- /dev/null
+++ b/test/Docfx.Dotnet.Tests/XmlCommentTests/XmlCommentExamplesTest.cs
@@ -0,0 +1,199 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+using AwesomeAssertions;
+using Xunit;
+
+namespace Docfx.Dotnet.Tests;
+
+public class XmlCommentExamplesTest
+{
+    [Fact]
+    public void Examples()
+    {
+        // Indent of first line should be preserved
+        ValidateExamples(
+            // Input XML
+            """
+            
+            This sample shows how to call the  method.
+            
+            class TestClass
+            {
+                static int Main()
+                {
+                    return GetExceptions(null, null).Count();
+                }
+            } 
+            
+            
+
+            
+            This is another example
+            
+
+            
+            Check empty code.
+            
+            
+
+            
+            This is an example using source reference.
+            
+            
+            """,
+            // Expected Markdown
+            [
+               // Example #1
+               """
+               This sample shows how to call the  method.
+
+               
class TestClass
+               {
+                   static int Main()
+                   {
+                       return GetExceptions(null, null).Count();
+                   }
+               }
+ """, + + // Example #2 + """ + This is another example + """, + + // Example #3 + """ + Check empty code. + +
+ """, + + // Example #4 + """ + This is an example using source reference. + +
+ """, + ]); + } + + [Fact] + public void Examples_WithIndent() + { + ValidateExamples( + // Input XML + """ + + + Paragraph1 + + class TestClass + { + static int Main() + { + return 0; + } + } + + + + """, + // Expected Markdown + [ + """ + Paragraph1 + +
class TestClass
+               {
+                   static int Main()
+                   {
+                       return 0;
+                   }
+               }
+ """, + ]); + } + + + [Fact] + public void Examples_WithIndent2() + { + ValidateExamples( + // Input XML + """ + + + + + + + """, + // Expected Markdown + [ + """ +
options.UseRelativeLinks = true;
+
{
+                 "type": "articles",
+                 "id": "4309",
+                 "relationships": {
+                   "author": {
+                     "links": {
+                       "self": "/api/shopping/articles/4309/relationships/author",
+                       "related": "/api/shopping/articles/4309/author"
+                     }
+                   }
+                 }
+               }
+ """, + ]); + } + + [Fact] + public void Examples_WithIndentedCodes() + { + ValidateExamples( + // Input XML + """ + + + aaa + bbb + + + """, + // Expected Markdown + [ + """ +
aaa
+
bbb
+ """, + ]); + } + + private static void ValidateExamples(string input, string[] expected) + { + // Act + var results = XmlComment.Parse(input).Examples; + + // Assert + results.Should().NotBeNull(); // Failed to get summary from XML input. + + results.Should() + .BeEquivalentTo(expected, x => x.IgnoringNewlineStyle().WithStrictOrdering()); + } +} diff --git a/test/Docfx.Dotnet.Tests/XmlCommentTests/XmlCommentExceptionsTest.cs b/test/Docfx.Dotnet.Tests/XmlCommentTests/XmlCommentExceptionsTest.cs new file mode 100644 index 00000000000..f319486eb39 --- /dev/null +++ b/test/Docfx.Dotnet.Tests/XmlCommentTests/XmlCommentExceptionsTest.cs @@ -0,0 +1,61 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using AwesomeAssertions; +using Docfx.DataContracts.ManagedReference; +using Xunit; + +namespace Docfx.Dotnet.Tests; + +public class XmlCommentExceptionsTest +{ + [Fact] + public void Exceptions() + { + ValidateException( + // Input XML + """ + This is a sample of exception node. Ref Exception + DocfxException + + This is a sample of exception node with invalid cref + This is a sample of invalid exception node + This is a sample of another invalid exception node + """, + // Expected results + [ + new ExceptionInfo + { + Type = "System.Xml.XmlException", + CommentId = "T:System.Xml.XmlException", + Description = + """ + This is a sample of exception node. Ref Exception + """, + }, + new ExceptionInfo + { + Type = "Docfx.Exceptions.DocfxException", + CommentId = "T:Docfx.Exceptions.DocfxException", + Description = "DocfxException", + }, + // Other exception tags are ignored. Because it's invalid. + ]); + } + + private static void ValidateException(string input, ExceptionInfo[] expected) + { + // Act + var results = XmlComment.Parse(input).Exceptions; + + // Assert + results.Should().NotBeNull(); // Failed to get summary from XML input. + + results.Should() + .BeEquivalentTo(expected, x => x.IgnoringNewlineStyle().WithStrictOrdering()); + } +} + + + + diff --git a/test/Docfx.Dotnet.Tests/XmlCommentTests/XmlCommentParametersTest.cs b/test/Docfx.Dotnet.Tests/XmlCommentTests/XmlCommentParametersTest.cs new file mode 100644 index 00000000000..155b2f75f02 --- /dev/null +++ b/test/Docfx.Dotnet.Tests/XmlCommentTests/XmlCommentParametersTest.cs @@ -0,0 +1,50 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using AwesomeAssertions; +using Xunit; + +namespace Docfx.Dotnet.Tests; + +public class XmlCommentParametersTest +{ + [Fact] + public void Parameters() + { + ValidateParameters( + // Input XML + """ + This is the input + This is the output + """, + // Expected results + new Dictionary + { + ["input"] = + """ + This is the input + """, + + ["output"] = + """ + This is the output + """, + }); + } + + private static void ValidateParameters(string input, Dictionary expected) + { + // Act + var results = XmlComment.Parse(input).Parameters; + + // Assert + results.Should().NotBeNull(); // Failed to get summary from XML input. + + results.Should() + .BeEquivalentTo(expected, x => x.IgnoringNewlineStyle().WithStrictOrdering()); + } +} + + + + diff --git a/test/Docfx.Dotnet.Tests/XmlCommentTests/XmlCommentRemarksTest.cs b/test/Docfx.Dotnet.Tests/XmlCommentTests/XmlCommentRemarksTest.cs new file mode 100644 index 00000000000..04da4d4184d --- /dev/null +++ b/test/Docfx.Dotnet.Tests/XmlCommentTests/XmlCommentRemarksTest.cs @@ -0,0 +1,82 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using AwesomeAssertions; +using Xunit; + +namespace Docfx.Dotnet.Tests; + +public class XmlCommentRemarksTest +{ + [Fact] + public void Remarks() + { + ValidateRemarks( + // Input XML + """ + + + + + + public class XmlElement + : XmlLinkedNode + + + + + + """, + // Expected Markdown + """ +
  • +
    public class XmlElement
    +                : XmlLinkedNode
    +
+ """ + ); + } + + [Fact] + public void Remarks_WithCodeBlocks() + { + ValidateRemarks( + // Input XML + """ + + ```csharp + CSharpCode1 + ``` + + + CSharpCode2 + + + """, + // Expected Markdown + """ + ```csharp + CSharpCode1 + ``` + +
CSharpCode2
+ """ + ); + } + + private static void ValidateRemarks(string input, string expected) + { + // Act + var results = XmlComment.Parse(input).Remarks; + + // Assert + results.Should().NotBeNull(); // Failed to get summary from XML input. + + results.Should() + .BeEquivalentTo(expected, x => x.IgnoringNewlineStyle()); + } +} + + + + diff --git a/test/Docfx.Dotnet.Tests/XmlCommentTests/XmlCommentSeeAlsosTest.cs b/test/Docfx.Dotnet.Tests/XmlCommentTests/XmlCommentSeeAlsosTest.cs new file mode 100644 index 00000000000..c75d948757a --- /dev/null +++ b/test/Docfx.Dotnet.Tests/XmlCommentTests/XmlCommentSeeAlsosTest.cs @@ -0,0 +1,60 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using AwesomeAssertions; +using Docfx.DataContracts.ManagedReference; +using Xunit; + +namespace Docfx.Dotnet.Tests; + +public class XmlCommentSeeAlsosTest +{ + [Fact] + public void SeeAlsos() + { + ValidateSeeAlsos( + // Input XML + """ + + ABCS + Hello Bing + + """, + // Expected results + [ + new LinkInfo + { + LinkType = LinkType.CRef, + LinkId = "System.IO.WaitForChangedResult", + CommentId = "T:System.IO.WaitForChangedResult", + AltText = null, + }, + new LinkInfo + { + LinkType = LinkType.HRef, + LinkId = "http://www.bing.com", + CommentId = null, + AltText = "Hello Bing", + }, + new LinkInfo + { + LinkType = LinkType.HRef, + LinkId = "http://www.bing.com", + CommentId = null, + AltText = "http://www.bing.com", + }, + ]); + } + + private static void ValidateSeeAlsos(string input, LinkInfo[] expected) + { + // Act + var results = XmlComment.Parse(input).SeeAlsos; + + // Assert + results.Should().NotBeNull(); // Failed to get summary from XML input. + + results.Should() + .BeEquivalentTo(expected, x => x.IgnoringNewlineStyle().WithStrictOrdering()); + } +} diff --git a/test/Docfx.Dotnet.Tests/XmlCommentTests/XmlCommentSummaryTest.Basic.cs b/test/Docfx.Dotnet.Tests/XmlCommentTests/XmlCommentSummaryTest.Basic.cs new file mode 100644 index 00000000000..d8d9f7854d7 --- /dev/null +++ b/test/Docfx.Dotnet.Tests/XmlCommentTests/XmlCommentSummaryTest.Basic.cs @@ -0,0 +1,39 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using Xunit; + +namespace Docfx.Dotnet.Tests; + +public partial class XmlCommentSummaryTest +{ + [Fact] + public void Summary_Basic() + { + ValidateSummary( + // Input XML + """ + + This is a simple summary. + + """, + // Expected Markdown + """ + This is a simple summary. + """); + } + + [Fact] + public void Summary_WithMarkdown() + { + ValidateSummary( + // Input XML + """ + + This is a summary with **markdown**. + + """, + // Expected Markdown + "This is a summary with **markdown**."); + } +} diff --git a/test/Docfx.Dotnet.Tests/XmlCommentTests/XmlCommentSummaryTest.Code.cs b/test/Docfx.Dotnet.Tests/XmlCommentTests/XmlCommentSummaryTest.Code.cs new file mode 100644 index 00000000000..51844bbe682 --- /dev/null +++ b/test/Docfx.Dotnet.Tests/XmlCommentTests/XmlCommentSummaryTest.Code.cs @@ -0,0 +1,50 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using Xunit; + +namespace Docfx.Dotnet.Tests; + +public partial class XmlCommentSummaryTest +{ + [Fact] + public void Code_Block() + { + ValidateSummary( + // Input XML + """ + + This is a summary with a code block: + + var x = 1; + + + """, + // Expected Markdown + """ + This is a summary with a code block: + +
var x = 1;
+ """); + } + + [Fact] + public void Code_Inline() + { + ValidateSummary( + // Input XML + """ + + Paragraph1 + text InlineCode text. + Paragraph2 + + """, + // Expected Markdown + """ + Paragraph1 + text InlineCode text. + Paragraph2 + """); + } +} diff --git a/test/Docfx.Dotnet.Tests/XmlCommentTests/XmlCommentSummaryTest.Indent.cs b/test/Docfx.Dotnet.Tests/XmlCommentTests/XmlCommentSummaryTest.Indent.cs new file mode 100644 index 00000000000..c5256d8e4f7 --- /dev/null +++ b/test/Docfx.Dotnet.Tests/XmlCommentTests/XmlCommentSummaryTest.Indent.cs @@ -0,0 +1,166 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using Xunit; + +namespace Docfx.Dotnet.Tests; + +public partial class XmlCommentSummaryTest +{ + [Fact] + public void Indent_NoIndent() + { + // Basic sumamry content + ValidateSummary( + // Input XML + """ + + First line + Second line + + """, + // Expected Markdown + """ + First line + Second line + """); + } + + [Fact] + public void Indent_SharedIndent_Removed() + { + // Shared indent should be removed. + ValidateSummary( + // Input XML + """ + + First line + Second line + + """, + // Expected Markdown + """ + First line + Second line + """); + } + + [Fact] + public void Indent_FirstLine() + { + // Indent of first line should be preserved + ValidateSummary( + // Input XML + """ + + First line + Second line + + """, + // Expected Markdown + """ + First line + Second line + """); + } + + [Fact] + public void Indent_SecondLine() + { + // Indent of second line should be preserved + ValidateSummary( + // Input XML + """ + + First line + Second line + + """, + // Expected Markdown + """ + First line + Second line + """); + } + + + [Fact] + public void Indent_BetweenInlineTags() + { + ValidateSummary( + // Input XML + """ + +

Paragraph1

Paragraph2

+
+ """, + // Expected Markdown + """ +

Paragraph1

Paragraph2

+ """); + } + + + [Fact] + public void Indent_MarkdownLineBreak1() + { + // Indent of before new line is preserved. + ValidateSummary( + // Input XML + """ + + First line + Second line + + """, + // Expected Markdown + """ + First line + Second line + """); + } + + [Fact] + public void Indent_MarkdownLineBreak2() + { + ValidateSummary( + // Input XML + """ + + First line\ + Second line + + """, + // Expected Markdown + """ + First line\ + Second line + """); + } + + /// + /// Tests for XML that are returned by roslyn. + /// + [Fact] + public void Indent_Code() + { + ValidateSummary( + // Input XML + """ + + + Summary + + 1ListItem + + + + """, + // Expected Markdown + """ + Summary + +
  • 1ListItem
+ """); + } +} diff --git a/test/Docfx.Dotnet.Tests/XmlCommentTests/XmlCommentSummaryTest.List.cs b/test/Docfx.Dotnet.Tests/XmlCommentTests/XmlCommentSummaryTest.List.cs new file mode 100644 index 00000000000..e7ec9dd3ae8 --- /dev/null +++ b/test/Docfx.Dotnet.Tests/XmlCommentTests/XmlCommentSummaryTest.List.cs @@ -0,0 +1,186 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using Xunit; + +namespace Docfx.Dotnet.Tests; + +public partial class XmlCommentSummaryTest +{ + [Fact] + public void ListTypeTable() + { + ValidateSummary( + // Input XML + """ + + Paragraph1 + + + Summary + Description + + + Paragraph2 + + """, + // Expected Markdown + """" + Paragraph1 + +
SummaryDescription
+ + Paragraph2 + """"); + } + + [Fact] + public void ListTypeBullet() + { + ValidateSummary( + // Input XML + """ + + Paragraph1 + + + Summary + Description + + + Paragraph2 + + """, + // Expected Markdown + """ + Paragraph1 + +
  • SummaryDescription
+ + Paragraph2 + """); + } + + [Fact] + public void ListTypeNumber() + { + ValidateSummary( + // Input XML + """ + + Paragraph1 + + + Summary + Description + + + Paragraph2 + + """, + // Expected Markdown + """ + Paragraph1 + +
  1. SummaryDescription
+ + Paragraph2 + """); + } + + [Fact] + public void ListWithCode() + { + ValidateSummary( + // Input XML + """ + + Paragraph1 + + + + + public class XmlElement + : XmlLinkedNode + + + + + Paragraph2 + + """, + // Expected Markdown + """ + Paragraph1 + +
  • +
    public class XmlElement
    +                : XmlLinkedNode
    +
+ + Paragraph2 + """); + } + + [Fact] + public void ListComplex() + { + ValidateSummary( + // Input XML + """ + + + example + This is a sample of exception node + + + + + public class XmlElement + : XmlLinkedNode + + + + + word inside list->listItem->list->listItem->para.> + the second line. + + + + item2 in numbered list + + + + + + item2 in bullet list + + + loose text not wrapped in description + + + + } + """, + // Expected Markdown + """ + https://example.org + example +

This is ref a sample of exception node

+
  • +
    public class XmlElement
    +              : XmlLinkedNode
    +
    1. + word inside list->listItem->list->listItem->para.> + the second line. +
    2. item2 in numbered list
    +
  • item2 in bullet list
  • + loose text not wrapped in description +
+ """); + } +} + + + + diff --git a/test/Docfx.Dotnet.Tests/XmlCommentTests/XmlCommentSummaryTest.Others.cs b/test/Docfx.Dotnet.Tests/XmlCommentTests/XmlCommentSummaryTest.Others.cs new file mode 100644 index 00000000000..58bc835d583 --- /dev/null +++ b/test/Docfx.Dotnet.Tests/XmlCommentTests/XmlCommentSummaryTest.Others.cs @@ -0,0 +1,129 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using Xunit; + +namespace Docfx.Dotnet.Tests; + +public partial class XmlCommentSummaryTest +{ + [Fact] + public void Example() + { + ValidateSummary( + // Input XML + """ + + Paragraph1 + + code content + + Paragraph2 + + """, + // Expected Markdown + """ + Paragraph1 + + +
code content
+
+ + Paragraph2 + """); + } + + [Fact] + public void ContainsXmlEscapeChars() + { + // ['<' '>' '%'] chars are not unescaped. These chars need to be escaped before converting markdown. + ValidateSummary( + // Input XML + """ + + "'<>& + + """, + // Expected Markdown + """ + "'<>& + """); + } + + [Fact] + public void ContainsBr() + { + ValidateSummary( + // Input XML + """ + + Used to provide asynchronous lifetime functionality.Currently supported:
+ - Test classes
+ - Classes used in
+ - Classes used in .
+ - Classes used in [assembly: ()]. +
+ """, + // Expected Markdown + """ + Used to provide asynchronous lifetime functionality.Currently supported:
+ - Test classes
+ - Classes used in
+ - Classes used in .
+ - Classes used in [assembly: ()]. + """); + } + + [Fact] + public void ContainsEmptyLine_BeforeMarkdownBlock() + { + ValidateSummary( + // Input XML + """ + + + CodeBlock1 + + + ```csharp + CodeBlock2 + ``` + + ``` + """, + // Expected Markdown + """ +
CodeBlock1
+ + ```csharp + CodeBlock2 + ``` + """); + } + + [Fact] + public void ContainsEmptyLine_AfterMarkdownBlock() + { + ValidateSummary( + // Input XML + """ + + ```csharp + CodeBlock1 + ``` + + + CodeBlock2 + + + """, + // Expected Markdown + """ + ```csharp + CodeBlock1 + ``` + +
CodeBlock2
+ """); + } +} diff --git a/test/Docfx.Dotnet.Tests/XmlCommentTests/XmlCommentSummaryTest.cs b/test/Docfx.Dotnet.Tests/XmlCommentTests/XmlCommentSummaryTest.cs new file mode 100644 index 00000000000..f3ada011b85 --- /dev/null +++ b/test/Docfx.Dotnet.Tests/XmlCommentTests/XmlCommentSummaryTest.cs @@ -0,0 +1,31 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using AwesomeAssertions; +using Xunit.Abstractions; + +namespace Docfx.Dotnet.Tests; + +public partial class XmlCommentSummaryTest(ITestOutputHelper Output) +{ + private void ValidateSummary(string input, string expected) + { + // Act + var result = XmlComment.Parse(input).Summary; + + // Assert + result.Should().NotBeNull(); // Failed to get summary from XML input. + try + { + result.Should() + .BeEquivalentTo(expected, x => x.IgnoringNewlineStyle()); + } + catch + { + Output.WriteLine("Actual HTML:"); + Output.WriteLine("--------------------------------------------------------------------------------"); + Output.WriteLine(result); + throw; + } + } +} diff --git a/test/Docfx.Dotnet.Tests/XmlCommentTests/XmlCommentTypeParametersTest.cs b/test/Docfx.Dotnet.Tests/XmlCommentTests/XmlCommentTypeParametersTest.cs new file mode 100644 index 00000000000..2b35b7bc9a6 --- /dev/null +++ b/test/Docfx.Dotnet.Tests/XmlCommentTests/XmlCommentTypeParametersTest.cs @@ -0,0 +1,55 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using AwesomeAssertions; +using Xunit; + +namespace Docfx.Dotnet.Tests; + +public class XmlCommentTypeParametersTest +{ + [Fact] + public void TypeParameters() + { + ValidateTypeParameters( + // Input XML + """ + + The base item type. Must implement IComparable. + + + + Exception: . + + """, + // Expected results + new Dictionary + { + ["T"] = + """ + The base item type. Must implement IComparable. + """, + + ["T2"] = + """ + Exception: . + """ + }); + } + + private static void ValidateTypeParameters(string input, Dictionary expected) + { + // Act + var results = XmlComment.Parse(input).TypeParameters; + + // Assert + results.Should().NotBeNull(); // Failed to get summary from XML input. + + results.Should() + .BeEquivalentTo(expected, x => x.IgnoringNewlineStyle()); + } +} + + + + diff --git a/test/Docfx.Dotnet.Tests/XmlCommentUnitTest.Issue10553.cs b/test/Docfx.Dotnet.Tests/XmlCommentUnitTest.Issue10553.cs new file mode 100644 index 00000000000..132d0972577 --- /dev/null +++ b/test/Docfx.Dotnet.Tests/XmlCommentUnitTest.Issue10553.cs @@ -0,0 +1,43 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using AwesomeAssertions; +using Xunit; + +namespace Docfx.Dotnet.Tests; + +public partial class XmlCommentUnitTest +{ + [Fact] + public void Issue10553() + { + var result = XmlComment.Parse( + """ + + Converts action result without parameters into action result with null parameter. + + return NotFound(null) + return NotFound() -> return NotFound(null) + ]]> + + This ensures our formatter is invoked, where we'll build a JSON:API compliant response. For details, see: + https://github.com/dotnet/aspnetcore/issues/16969 + + """); + + var expected = """ + Converts action result without parameters into action result with null parameter. + +
return NotFound() -> return NotFound(null)
+                return NotFound() -> return NotFound(null)
+
+ + This ensures our formatter is invoked, where we'll build a JSON:API compliant response. For details, see: + https://github.com/dotnet/aspnetcore/issues/16969 + """.ReplaceLineEndings(); + + // Verify empty line is inserted before/after `` tags. + result.Summary.Should().BeEquivalentTo(expected); + } +} diff --git a/test/Docfx.Dotnet.Tests/XmlCommentUnitTest.Issue8360.cs b/test/Docfx.Dotnet.Tests/XmlCommentUnitTest.Issue8360.cs new file mode 100644 index 00000000000..1e6f557c61b --- /dev/null +++ b/test/Docfx.Dotnet.Tests/XmlCommentUnitTest.Issue8360.cs @@ -0,0 +1,50 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using AwesomeAssertions; +using Docfx.DataContracts.ManagedReference; +using Xunit; + +namespace Docfx.Dotnet.Tests; + +public partial class XmlCommentUnitTest +{ + [Fact] + public void Issue8360() + { + // Act + var result = XmlComment.Parse( + """ + + Test . + + InvalidOperationException + ArgumentNullException + """); + + // Assert + var summary = result.Summary; + summary.Should().Be( + """ + Test . + """); + + var exceptions = result.Exceptions; + exceptions.Should().BeEquivalentTo( + [ + new ExceptionInfo + { + Type ="InvalidOperationException", + CommentId ="T:InvalidOperationException", + Description="InvalidOperationException", + }, + new ExceptionInfo + { + Type ="ArgumentNullException", + CommentId ="T:ArgumentNullException", + Description="ArgumentNullException", + }, + ], + options => options.WithStrictOrdering()); + } +} diff --git a/test/Docfx.Dotnet.Tests/XmlCommentUnitTest.cs b/test/Docfx.Dotnet.Tests/XmlCommentUnitTest.cs index 9906c514222..e0c3d69cb92 100644 --- a/test/Docfx.Dotnet.Tests/XmlCommentUnitTest.cs +++ b/test/Docfx.Dotnet.Tests/XmlCommentUnitTest.cs @@ -5,7 +5,7 @@ namespace Docfx.Dotnet.Tests; -public class XmlCommentUnitTest +public partial class XmlCommentUnitTest { private static void Verify(string comment, string summary) { @@ -28,6 +28,7 @@ public static void ParaNewLine() Assert.Equal( """ a +

b

c

""", @@ -64,8 +65,22 @@ public static void Issue4165() [Fact] public static void Issue8965() { - Verify("See also on MDN", "\n See also on MDN\n"); - Verify("See also on MDN", "\n See also on MDN\n"); + // + Verify( + """ + See also on MDN + """, + """ + See also on MDN + """); + // + Verify( + """ + See also on MDN + """, + """ + See also on MDN + """); } [Fact] @@ -165,6 +180,7 @@ public void ExternalCodeBlockXaml() Assert.Equal( """ This is an example using source reference in a xaml file. +
<Grid>
               <TextBlock Text="Hello World" />
             </Grid>
@@ -324,18 +340,18 @@ loose text not wrapped in description Task returns - This is the input + This is the input - This is the output - This is a sample of exception node. Ref Exception - This is a sample of exception node with invalid cref - This is a sample of invalid exception node - This is a sample of another invalid exception node + This is the output + This is a sample of exception node. Ref Exception + This is a sample of exception node with invalid cref + This is a sample of invalid exception node + This is a sample of another invalid exception node This sample shows how to call the method. - class TestClass + class TestClass { static int Main() { @@ -386,16 +402,16 @@ Classes in assemblies are by definition complete. Assert.Equal("This is the input", paramInput); var remarks = commentModel.Remarks; - Assert.Equal(""" + Assert.Equal( + """ https://example.org example

This is ref a sample of exception node

  • -
    public class XmlElement
    -                            : XmlLinkedNode
    + : XmlLinkedNode
  1. - word inside list->listItem->list->listItem->para.> + word inside list->listItem->list->listItem->para.> the second line.
  2. item2 in numbered list
  • item2 in bullet list
  • @@ -413,13 +429,14 @@ loose text not wrapped in description e => Assert.Equal( """ This sample shows how to call the method. +
    class TestClass
    -                 {
    -                     static int Main()
    -                     {
    -                         return GetExceptions(null, null).Count();
    -                     }
    -                 }
    + { + static int Main() + { + return GetExceptions(null, null).Count(); + } + }
  • """, e, ignoreLineEndingDifferences: true), e => Assert.Equal( """ @@ -428,11 +445,13 @@ This is another example e => Assert.Equal( """ Check empty code. +
    """, e, ignoreLineEndingDifferences: true), e => Assert.Equal( """ This is an example using source reference. +
    """, e, ignoreLineEndingDifferences: true) ); @@ -521,7 +540,6 @@ public void Issue9495() Assert.Equal( """
    options.UseRelativeLinks = true;
    -
    {
                   "type": "articles",
                   "id": "4309",
    @@ -563,7 +581,6 @@ public sealed class Issue10385
                 

    Paragraph.

    -
    public sealed class Issue10385
                 {
                     public int AAA {get;set;}
    @@ -574,7 +591,4 @@ public sealed class Issue10385
                 }
    """, comment.Remarks, ignoreLineEndingDifferences: true); } - - - } diff --git a/test/docfx.Snapshot.Tests/SamplesTest.Seed/apipage/CatLibrary.ICatExtension.html.view.verified.json b/test/docfx.Snapshot.Tests/SamplesTest.Seed/apipage/CatLibrary.ICatExtension.html.view.verified.json index 9df7f45bb92..30680d9eddb 100644 --- a/test/docfx.Snapshot.Tests/SamplesTest.Seed/apipage/CatLibrary.ICatExtension.html.view.verified.json +++ b/test/docfx.Snapshot.Tests/SamplesTest.Seed/apipage/CatLibrary.ICatExtension.html.view.verified.json @@ -4,7 +4,7 @@ "_enableSearch": true, "pdf": true, "pdfTocPage": true, - "description": "It's the class that contains ICat interface's extension method.\nThis class must be public and static.\nAlso it shouldn't be a geneic class", + "description": "It's the class that contains ICat interface's extension method.\n\nThis class must be public and static.\nAlso it shouldn't be a geneic class", "title": "Class ICatExtension", "content": "

    Class ICatExtension

    \r\n
    \r\n
    Namespace
    CatLibrary
    Assembly
    CatLibrary.dll
    \r\n

    It's the class that contains ICat interface's extension method.

    \n

    This class must be public and static.

    \n

    Also it shouldn't be a geneic class

    \n
    public static class ICatExtension

    Inheritance

    \r\n
    \nobject\n
    \n\n\r\n

    Inherited Members

    \r\n\n\n\n\n\n\n\n\r\n

    Methods

    Play(ICat, ColorType)

    \r\n

    Extension method to let cat play

    \n
    public static void Play(this ICat icat, ContainersRefType.ColorType toy)

    Parameters

    icat ICat
    \r\n
    \r\n\r\n\r\n

    Cat

    \n\r\n
    toy ContainersRefType.ColorType
    \r\n
    \r\n\r\n\r\n

    Something to play

    \n\r\n

    Sleep(ICat, long)

    \r\n

    Extension method hint that how long the cat can sleep.

    \n
    public static void Sleep(this ICat icat, long hours)

    Parameters

    icat ICat
    \r\n
    \r\n\r\n\r\n

    The type will be extended.

    \n\r\n
    hours long
    \r\n
    \r\n\r\n\r\n

    The length of sleep.

    \n\r\n
    ", "yamlmime": "ApiPage", diff --git a/test/docfx.Snapshot.Tests/SamplesTest.Seed/md/BuildFromProject.Class1.html.view.verified.json b/test/docfx.Snapshot.Tests/SamplesTest.Seed/md/BuildFromProject.Class1.html.view.verified.json index 8d95803b5dc..a5b7cfb21a9 100644 --- a/test/docfx.Snapshot.Tests/SamplesTest.Seed/md/BuildFromProject.Class1.html.view.verified.json +++ b/test/docfx.Snapshot.Tests/SamplesTest.Seed/md/BuildFromProject.Class1.html.view.verified.json @@ -1,5 +1,5 @@ { - "conceptual": "\n

    Namespace: BuildFromProject
    \nAssembly: BuildFromProject.dll

    \n
    public class Class1 : IClass1\n
    \n

    Inheritance

    \n

    object ←\nClass1

    \n

    Implements

    \n

    IClass1

    \n

    Inherited Members

    \n

    object.Equals(object?),\nobject.Equals(object?, object?),\nobject.GetHashCode(),\nobject.GetType(),\nobject.MemberwiseClone(),\nobject.ReferenceEquals(object?, object?),\nobject.ToString()

    \n

    Methods

    \n

    Issue1651()

    \n

    Pricing models are used to calculate theoretical option values

    \n
    • 1Black Scholes
    • 2Black76
    • 3Black76Fut
    • 4Equity Tree
    • 5Variance Swap
    • 6Dividend Forecast
    \n
    public void Issue1651()\n
    \n

    Issue1887()

    \n

    IConfiguration related helper and extension routines.

    \n
    public void Issue1887()\n
    \n

    Issue2623()

    \n
    public void Issue2623()\n
    \n

    Examples

    \n
    MyClass myClass = new MyClass();\n\nvoid Update()\n{\n    myClass.Execute();\n}\n
    \n

    Remarks

    \n

    For example:

    \n
    MyClass myClass = new MyClass();\n\nvoid Update()\n{\n    myClass.Execute();\n}\n
    \n

    Issue2723()

    \n
    public void Issue2723()\n
    \n

    Remarks

    \n
    \n
    Note
    \n

    This is a <note>. & " '

    \n
    \n

    Inline <angle brackets>.

    \n

    link

    \n
    for (var i = 0; i > 10; i++) // & " '\nvar range = new Range<int> { Min = 0, Max = 10 };\n
    \n
    var range = new Range<int> { Min = 0, Max = 10 };
    \n

    Issue4017()

    \n
    public void Issue4017()\n
    \n

    Examples

    \n
    public void HookMessageDeleted(BaseSocketClient client)\n{\n    client.MessageDeleted += HandleMessageDelete;\n}\n\npublic Task HandleMessageDelete(Cacheable<IMessage, ulong> cachedMessage, ISocketMessageChannel channel)\n{\n    // check if the message exists in cache; if not, we cannot report what was removed\n    if (!cachedMessage.HasValue) return;\n    var message = cachedMessage.Value;\n    Console.WriteLine($\"A message ({message.Id}) from {message.Author} was removed from the channel {channel.Name} ({channel.Id}):\"\n        + Environment.NewLine\n        + message.Content);\n    return Task.CompletedTask;\n}
    \n

    Remarks

    \n
    void Update()\n{\n    myClass.Execute();\n}
    \n

    Issue4392()

    \n
    public void Issue4392()\n
    \n

    Remarks

    \n

    @"\\\\?\\"

    \n

    Issue7484()

    \n
    public void Issue7484()\n
    \n

    Remarks

    \n

    There's really no reason to not believe that this class can test things.

    \n
    TermDescription
    A TermA Description
    Bee TermBee Description
    \n

    Issue8764<T>()

    \n
    public void Issue8764<T>() where T : unmanaged\n
    \n

    Type Parameters

    \n

    T

    \n

    Issue896()

    \n

    Test

    \n
    public void Issue896()\n
    \n

    See Also

    \n

    Class1.Test<T>,\nClass1

    \n

    Issue9216()

    \n

    Calculates the determinant of a 3-dimensional matrix:

    \n

    \\(A = \\begin{vmatrix} a_{11} & a_{12} & a_{13} \\\\ a_{21} & a_{22} & a_{23} \\\\ a_{31} & a_{32} & a_{33} \\end{vmatrix}\\)

    \n

    Returns the smallest value:

    \n

    \\(\\left\\{\\begin{matrix}a, a<b \\\\ b, b>a\\\\ \\end{matrix} \\right.\\)

    \n
    public static double Issue9216()\n
    \n

    Returns

    \n

    double

    \n

    XmlCommentIncludeTag()

    \n

    This method should do something...

    \n
    public void XmlCommentIncludeTag()\n
    \n

    Remarks

    \n

    This is remarks.

    \n", + "conceptual": "\n

    Namespace: BuildFromProject
    \nAssembly: BuildFromProject.dll

    \n
    public class Class1 : IClass1\n
    \n

    Inheritance

    \n

    object ←\nClass1

    \n

    Implements

    \n

    IClass1

    \n

    Inherited Members

    \n

    object.Equals(object?),\nobject.Equals(object?, object?),\nobject.GetHashCode(),\nobject.GetType(),\nobject.MemberwiseClone(),\nobject.ReferenceEquals(object?, object?),\nobject.ToString()

    \n

    Methods

    \n

    Issue1651()

    \n

    Pricing models are used to calculate theoretical option values

    \n
    • 1Black Scholes
    • 2Black76
    • 3Black76Fut
    • 4Equity Tree
    • 5Variance Swap
    • 6Dividend Forecast
    \n
    public void Issue1651()\n
    \n

    Issue1887()

    \n

    IConfiguration related helper and extension routines.

    \n
    public void Issue1887()\n
    \n

    Issue2623()

    \n
    public void Issue2623()\n
    \n

    Examples

    \n
    MyClass myClass = new MyClass();\n\nvoid Update()\n{\n    myClass.Execute();\n}\n
    \n

    Remarks

    \n

    For example:

    \n
    MyClass myClass = new MyClass();\n\nvoid Update()\n{\n    myClass.Execute();\n}\n
    \n

    Issue2723()

    \n
    public void Issue2723()\n
    \n

    Remarks

    \n
    \n
    Note
    \n

    This is a <note>. & " '

    \n
    \n

    Inline <angle brackets>.

    \n

    link

    \n
    for (var i = 0; i > 10; i++) // & " '\nvar range = new Range<int> { Min = 0, Max = 10 };\n
    \n
    var range = new Range<int> { Min = 0, Max = 10 };
    \n

    Issue4017()

    \n
    public void Issue4017()\n
    \n

    Examples

    \n
    public void HookMessageDeleted(BaseSocketClient client)\n{\n    client.MessageDeleted += HandleMessageDelete;\n}\n\npublic Task HandleMessageDelete(Cacheable<IMessage, ulong> cachedMessage, ISocketMessageChannel channel)\n{\n    // check if the message exists in cache; if not, we cannot report what was removed\n    if (!cachedMessage.HasValue) return;\n    var message = cachedMessage.Value;\n    Console.WriteLine($\"A message ({message.Id}) from {message.Author} was removed from the channel {channel.Name} ({channel.Id}):\"\n        + Environment.NewLine\n        + message.Content);\n    return Task.CompletedTask;\n}
    \n

    Remarks

    \n
    void Update()\n{\n    myClass.Execute();\n}
    \n

    Issue4392()

    \n
    public void Issue4392()\n
    \n

    Remarks

    \n

    @"\\\\?\\"

    \n

    Issue7484()

    \n
    public void Issue7484()\n
    \n

    Remarks

    \n

    There's really no reason to not believe that this class can test things.

    \n
    TermDescription
    A TermA Description
    Bee TermBee Description
    \n

    Issue8764<T>()

    \n
    public void Issue8764<T>() where T : unmanaged\n
    \n

    Type Parameters

    \n

    T

    \n

    Issue896()

    \n

    Test

    \n
    public void Issue896()\n
    \n

    See Also

    \n

    Class1.Test<T>,\nClass1

    \n

    Issue9216()

    \n

    Calculates the determinant of a 3-dimensional matrix:

    \n

    \\(A = \\begin{vmatrix} a_{11} & a_{12} & a_{13} \\\\ a_{21} & a_{22} & a_{23} \\\\ a_{31} & a_{32} & a_{33} \\end{vmatrix}\\)

    \n

    Returns the smallest value:

    \n

    \\(\\left\\{\\begin{matrix}a, a<b \\\\ b, b>a\\\\ \\end{matrix} \\right.\\)

    \n
    public static double Issue9216()\n
    \n

    Returns

    \n

    double

    \n

    XmlCommentIncludeTag()

    \n

    This method should do something...

    \n
    public void XmlCommentIncludeTag()\n
    \n

    Remarks

    \n

    This is remarks.

    \n", "type": "Conceptual", "source": { "remote": { diff --git a/test/docfx.Snapshot.Tests/SamplesTest.Seed/md/BuildFromProject.Inheritdoc.Issue7484.html.view.verified.json b/test/docfx.Snapshot.Tests/SamplesTest.Seed/md/BuildFromProject.Inheritdoc.Issue7484.html.view.verified.json index 369e0170da5..02965cd1e32 100644 --- a/test/docfx.Snapshot.Tests/SamplesTest.Seed/md/BuildFromProject.Inheritdoc.Issue7484.html.view.verified.json +++ b/test/docfx.Snapshot.Tests/SamplesTest.Seed/md/BuildFromProject.Inheritdoc.Issue7484.html.view.verified.json @@ -1,5 +1,5 @@ { - "conceptual": "\n

    Namespace: BuildFromProject
    \nAssembly: BuildFromProject.dll

    \n

    This is a test class to have something for DocFX to document.

    \n
    public class Inheritdoc.Issue7484\n
    \n

    Inheritance

    \n

    object ←\nInheritdoc.Issue7484

    \n

    Inherited Members

    \n

    object.Equals(object?),\nobject.Equals(object?, object?),\nobject.GetHashCode(),\nobject.GetType(),\nobject.MemberwiseClone(),\nobject.ReferenceEquals(object?, object?),\nobject.ToString()

    \n

    Remarks

    \n

    We're going to talk about things now.

    \n
    \nSimple method to generate docs for.\n
    \nA string that could have something.\n
    \n

    Constructors

    \n

    Issue7484()

    \n

    This is a constructor to document.

    \n
    public Issue7484()\n
    \n

    Properties

    \n

    DoDad

    \n

    A string that could have something.

    \n
    public string DoDad { get; }\n
    \n

    Property Value

    \n

    string

    \n

    Methods

    \n

    BoolReturningMethod(bool)

    \n

    Simple method to generate docs for.

    \n
    public bool BoolReturningMethod(bool source)\n
    \n

    Parameters

    \n

    source bool

    \n

    A meaningless boolean value, much like most questions in the world.

    \n

    Returns

    \n

    bool

    \n

    An exactly equivalently meaningless boolean value, much like most answers in the world.

    \n

    Remarks

    \n

    I'd like to take a moment to thank all of those who helped me get to\na place where I can write documentation like this.

    \n", + "conceptual": "\n

    Namespace: BuildFromProject
    \nAssembly: BuildFromProject.dll

    \n

    This is a test class to have something for DocFX to document.

    \n
    public class Inheritdoc.Issue7484\n
    \n

    Inheritance

    \n

    object ←\nInheritdoc.Issue7484

    \n

    Inherited Members

    \n

    object.Equals(object?),\nobject.Equals(object?, object?),\nobject.GetHashCode(),\nobject.GetType(),\nobject.MemberwiseClone(),\nobject.ReferenceEquals(object?, object?),\nobject.ToString()

    \n

    Remarks

    \n

    We're going to talk about things now.

    \n
    \nSimple method to generate docs for.\n
    \nA string that could have something.\n
    \n

    Constructors

    \n

    Issue7484()

    \n

    This is a constructor to document.

    \n
    public Issue7484()\n
    \n

    Properties

    \n

    DoDad

    \n

    A string that could have something.

    \n
    public string DoDad { get; }\n
    \n

    Property Value

    \n

    string

    \n

    Methods

    \n

    BoolReturningMethod(bool)

    \n

    Simple method to generate docs for.

    \n
    public bool BoolReturningMethod(bool source)\n
    \n

    Parameters

    \n

    source bool

    \n

    A meaningless boolean value, much like most questions in the world.

    \n

    Returns

    \n

    bool

    \n

    An exactly equivalently meaningless boolean value, much like most answers in the world.

    \n

    Remarks

    \n

    I'd like to take a moment to thank all of those who helped me get to\na place where I can write documentation like this.

    \n", "type": "Conceptual", "source": { "remote": { diff --git a/test/docfx.Snapshot.Tests/SamplesTest.Seed/md/CatLibrary.Cat-2.html.view.verified.json b/test/docfx.Snapshot.Tests/SamplesTest.Seed/md/CatLibrary.Cat-2.html.view.verified.json index fc358188bf6..e5641108203 100644 --- a/test/docfx.Snapshot.Tests/SamplesTest.Seed/md/CatLibrary.Cat-2.html.view.verified.json +++ b/test/docfx.Snapshot.Tests/SamplesTest.Seed/md/CatLibrary.Cat-2.html.view.verified.json @@ -1,5 +1,5 @@ { - "conceptual": "\n

    Namespace: CatLibrary
    \nAssembly: CatLibrary.dll

    \n

    Here's main class of this Demo.

    \n

    You can see mostly type of article within this class and you for more detail, please see the remarks.

    \n

    \n

    this class is a template class. It has two Generic parameter. they are: T and K.

    \n

    The extension method of this class can refer to class

    \n
    [Serializable]\n[Obsolete]\npublic class Cat<T, K> : ICat, IAnimal where T : class, new() where K : struct\n
    \n

    Type Parameters

    \n

    T

    \n

    This type should be class and can new instance.

    \n

    K

    \n

    This type is a struct type, class type can't be used for this parameter.

    \n

    Inheritance

    \n

    object ←\nCat<T, K>

    \n

    Implements

    \n

    ICat,\nIAnimal

    \n

    Inherited Members

    \n

    object.Equals(object?),\nobject.Equals(object?, object?),\nobject.GetHashCode(),\nobject.GetType(),\nobject.MemberwiseClone(),\nobject.ReferenceEquals(object?, object?),\nobject.ToString()

    \n

    Extension Methods

    \n

    ICatExtension.Play(ICat, ContainersRefType.ColorType),\nICatExtension.Sleep(ICat, long)

    \n

    Examples

    \n

    Here's example of how to create an instance of this class. As T is limited with class and K is limited with struct.

    \n
    var a = new Cat(object, int)();\nint catNumber = new int();\nunsafe\n{\n    a.GetFeetLength(catNumber);\n}
    \n

    As you see, here we bring in pointer so we need to add unsafe keyword.

    \n

    Remarks

    \n

    Here's all the content you can see in this class.

    \n

    Constructors

    \n

    Cat()

    \n

    Default constructor.

    \n
    public Cat()\n
    \n

    Cat(T)

    \n

    Constructor with one generic parameter.

    \n
    public Cat(T ownType)\n
    \n

    Parameters

    \n

    ownType T

    \n

    This parameter type defined by class.

    \n

    Cat(string, out int, string, bool)

    \n

    It's a complex constructor. The parameter will have some attributes.

    \n
    public Cat(string nickName, out int age, string realName, bool isHealthy)\n
    \n

    Parameters

    \n

    nickName string

    \n

    it's string type.

    \n

    age int

    \n

    It's an out and ref parameter.

    \n

    realName string

    \n

    It's an out paramter.

    \n

    isHealthy bool

    \n

    It's an in parameter.

    \n

    Fields

    \n

    isHealthy

    \n

    Field with attribute.

    \n
    [ContextStatic]\n[NonSerialized]\n[Obsolete]\npublic bool isHealthy\n
    \n

    Field Value

    \n

    bool

    \n

    Properties

    \n

    Age

    \n

    Hint cat's age.

    \n
    [Obsolete]\nprotected int Age { get; set; }\n
    \n

    Property Value

    \n

    int

    \n

    Name

    \n

    EII property.

    \n
    public string Name { get; }\n
    \n

    Property Value

    \n

    string

    \n

    this[string]

    \n

    This is index property of Cat. You can see that the visibility is different between get and set method.

    \n
    public int this[string a] { protected get; set; }\n
    \n

    Property Value

    \n

    int

    \n

    Methods

    \n

    CalculateFood(DateTime)

    \n

    It's a method with complex return type.

    \n
    public Dictionary<string, List<int>> CalculateFood(DateTime date)\n
    \n

    Parameters

    \n

    date DateTime

    \n

    Date time to now.

    \n

    Returns

    \n

    Dictionary<string, List<int>>

    \n

    It's a relationship map of different kind food.

    \n

    Equals(object)

    \n

    Override the method of Object.Equals(object obj).

    \n
    public override bool Equals(object obj)\n
    \n

    Parameters

    \n

    obj object

    \n

    Can pass any class type.

    \n

    Returns

    \n

    bool

    \n

    The return value tell you whehter the compare operation is successful.

    \n

    GetTailLength(int*, params object[])

    \n

    It's an unsafe method.\nAs you see, catName is a pointer, so we need to add unsafe keyword.

    \n
    public long GetTailLength(int* catName, params object[] parameters)\n
    \n

    Parameters

    \n

    catName int*

    \n

    Thie represent for cat name length.

    \n

    parameters object[]

    \n

    Optional parameters.

    \n

    Returns

    \n

    long

    \n

    Return cat tail's length.

    \n

    Jump(T, K, ref bool)

    \n

    This method have attribute above it.

    \n
    [Conditional("Debug")]\npublic void Jump(T ownType, K anotherOwnType, ref bool cheat)\n
    \n

    Parameters

    \n

    ownType T

    \n

    Type come from class define.

    \n

    anotherOwnType K

    \n

    Type come from class define.

    \n

    cheat bool

    \n

    Hint whether this cat has cheat mode.

    \n

    Exceptions

    \n

    ArgumentException

    \n

    This is an argument exception

    \n

    ownEat

    \n

    Eat event of this cat

    \n
    [Obsolete("This _event handler_ is deprecated.")]\npublic event EventHandler ownEat\n
    \n

    Event Type

    \n

    EventHandler

    \n

    Operators

    \n

    operator +(Cat<T, K>, int)

    \n

    Addition operator of this class.

    \n
    public static int operator +(Cat<T, K> lsr, int rsr)\n
    \n

    Parameters

    \n

    lsr Cat<T, K>

    \n

    ..

    \n

    rsr int

    \n

    ~~

    \n

    Returns

    \n

    int

    \n

    Result with int type.

    \n

    explicit operator Tom(Cat<T, K>)

    \n

    Expilicit operator of this class.

    \n

    It means this cat can evolve to change to Tom. Tom and Jerry.

    \n
    public static explicit operator Tom(Cat<T, K> src)\n
    \n

    Parameters

    \n

    src Cat<T, K>

    \n

    Instance of this class.

    \n

    Returns

    \n

    Tom

    \n

    Advanced class type of cat.

    \n

    operator -(Cat<T, K>, int)

    \n

    Similar with operaotr +, refer to that topic.

    \n
    public static int operator -(Cat<T, K> lsr, int rsr)\n
    \n

    Parameters

    \n

    lsr Cat<T, K>

    \n

    rsr int

    \n

    Returns

    \n

    int

    \n", + "conceptual": "\n

    Namespace: CatLibrary
    \nAssembly: CatLibrary.dll

    \n

    Here's main class of this Demo.

    \n

    You can see mostly type of article within this class and you for more detail, please see the remarks.

    \n

    \n

    this class is a template class. It has two Generic parameter. they are: T and K.

    \n

    The extension method of this class can refer to class

    \n
    [Serializable]\n[Obsolete]\npublic class Cat<T, K> : ICat, IAnimal where T : class, new() where K : struct\n
    \n

    Type Parameters

    \n

    T

    \n

    This type should be class and can new instance.

    \n

    K

    \n

    This type is a struct type, class type can't be used for this parameter.

    \n

    Inheritance

    \n

    object ←\nCat<T, K>

    \n

    Implements

    \n

    ICat,\nIAnimal

    \n

    Inherited Members

    \n

    object.Equals(object?),\nobject.Equals(object?, object?),\nobject.GetHashCode(),\nobject.GetType(),\nobject.MemberwiseClone(),\nobject.ReferenceEquals(object?, object?),\nobject.ToString()

    \n

    Extension Methods

    \n

    ICatExtension.Play(ICat, ContainersRefType.ColorType),\nICatExtension.Sleep(ICat, long)

    \n

    Examples

    \n

    Here's example of how to create an instance of this class. As T is limited with class and K is limited with struct.

    \n
    var a = new Cat(object, int)();\nint catNumber = new int();\nunsafe\n{\n    a.GetFeetLength(catNumber);\n}
    \n

    As you see, here we bring in pointer so we need to add unsafe keyword.

    \n

    Remarks

    \n

    Here's all the content you can see in this class.

    \n

    Constructors

    \n

    Cat()

    \n

    Default constructor.

    \n
    public Cat()\n
    \n

    Cat(T)

    \n

    Constructor with one generic parameter.

    \n
    public Cat(T ownType)\n
    \n

    Parameters

    \n

    ownType T

    \n

    This parameter type defined by class.

    \n

    Cat(string, out int, string, bool)

    \n

    It's a complex constructor. The parameter will have some attributes.

    \n
    public Cat(string nickName, out int age, string realName, bool isHealthy)\n
    \n

    Parameters

    \n

    nickName string

    \n

    it's string type.

    \n

    age int

    \n

    It's an out and ref parameter.

    \n

    realName string

    \n

    It's an out paramter.

    \n

    isHealthy bool

    \n

    It's an in parameter.

    \n

    Fields

    \n

    isHealthy

    \n

    Field with attribute.

    \n
    [ContextStatic]\n[NonSerialized]\n[Obsolete]\npublic bool isHealthy\n
    \n

    Field Value

    \n

    bool

    \n

    Properties

    \n

    Age

    \n

    Hint cat's age.

    \n
    [Obsolete]\nprotected int Age { get; set; }\n
    \n

    Property Value

    \n

    int

    \n

    Name

    \n

    EII property.

    \n
    public string Name { get; }\n
    \n

    Property Value

    \n

    string

    \n

    this[string]

    \n

    This is index property of Cat. You can see that the visibility is different between get and set method.

    \n
    public int this[string a] { protected get; set; }\n
    \n

    Property Value

    \n

    int

    \n

    Methods

    \n

    CalculateFood(DateTime)

    \n

    It's a method with complex return type.

    \n
    public Dictionary<string, List<int>> CalculateFood(DateTime date)\n
    \n

    Parameters

    \n

    date DateTime

    \n

    Date time to now.

    \n

    Returns

    \n

    Dictionary<string, List<int>>

    \n

    It's a relationship map of different kind food.

    \n

    Equals(object)

    \n

    Override the method of Object.Equals(object obj).

    \n
    public override bool Equals(object obj)\n
    \n

    Parameters

    \n

    obj object

    \n

    Can pass any class type.

    \n

    Returns

    \n

    bool

    \n

    The return value tell you whehter the compare operation is successful.

    \n

    GetTailLength(int*, params object[])

    \n

    It's an unsafe method.\nAs you see, catName is a pointer, so we need to add unsafe keyword.

    \n
    public long GetTailLength(int* catName, params object[] parameters)\n
    \n

    Parameters

    \n

    catName int*

    \n

    Thie represent for cat name length.

    \n

    parameters object[]

    \n

    Optional parameters.

    \n

    Returns

    \n

    long

    \n

    Return cat tail's length.

    \n

    Jump(T, K, ref bool)

    \n

    This method have attribute above it.

    \n
    [Conditional("Debug")]\npublic void Jump(T ownType, K anotherOwnType, ref bool cheat)\n
    \n

    Parameters

    \n

    ownType T

    \n

    Type come from class define.

    \n

    anotherOwnType K

    \n

    Type come from class define.

    \n

    cheat bool

    \n

    Hint whether this cat has cheat mode.

    \n

    Exceptions

    \n

    ArgumentException

    \n

    This is an argument exception

    \n

    ownEat

    \n

    Eat event of this cat

    \n
    [Obsolete("This _event handler_ is deprecated.")]\npublic event EventHandler ownEat\n
    \n

    Event Type

    \n

    EventHandler

    \n

    Operators

    \n

    operator +(Cat<T, K>, int)

    \n

    Addition operator of this class.

    \n
    public static int operator +(Cat<T, K> lsr, int rsr)\n
    \n

    Parameters

    \n

    lsr Cat<T, K>

    \n

    ..

    \n

    rsr int

    \n

    ~~

    \n

    Returns

    \n

    int

    \n

    Result with int type.

    \n

    explicit operator Tom(Cat<T, K>)

    \n

    Expilicit operator of this class.

    \n

    It means this cat can evolve to change to Tom. Tom and Jerry.

    \n
    public static explicit operator Tom(Cat<T, K> src)\n
    \n

    Parameters

    \n

    src Cat<T, K>

    \n

    Instance of this class.

    \n

    Returns

    \n

    Tom

    \n

    Advanced class type of cat.

    \n

    operator -(Cat<T, K>, int)

    \n

    Similar with operaotr +, refer to that topic.

    \n
    public static int operator -(Cat<T, K> lsr, int rsr)\n
    \n

    Parameters

    \n

    lsr Cat<T, K>

    \n

    rsr int

    \n

    Returns

    \n

    int

    \n", "type": "Conceptual", "source": { "remote": { diff --git a/test/docfx.Snapshot.Tests/SamplesTest.Seed/md/CatLibrary.ICatExtension.html.view.verified.json b/test/docfx.Snapshot.Tests/SamplesTest.Seed/md/CatLibrary.ICatExtension.html.view.verified.json index 384c39aa5b8..da608de3e5c 100644 --- a/test/docfx.Snapshot.Tests/SamplesTest.Seed/md/CatLibrary.ICatExtension.html.view.verified.json +++ b/test/docfx.Snapshot.Tests/SamplesTest.Seed/md/CatLibrary.ICatExtension.html.view.verified.json @@ -1,5 +1,5 @@ { - "conceptual": "\n

    Namespace: CatLibrary
    \nAssembly: CatLibrary.dll

    \n

    It's the class that contains ICat interface's extension method.

    \n

    This class must be public and static.

    \n

    Also it shouldn't be a geneic class

    \n
    public static class ICatExtension\n
    \n

    Inheritance

    \n

    object ←\nICatExtension

    \n

    Inherited Members

    \n

    object.Equals(object?),\nobject.Equals(object?, object?),\nobject.GetHashCode(),\nobject.GetType(),\nobject.MemberwiseClone(),\nobject.ReferenceEquals(object?, object?),\nobject.ToString()

    \n

    Methods

    \n

    Play(ICat, ColorType)

    \n

    Extension method to let cat play

    \n
    public static void Play(this ICat icat, ContainersRefType.ColorType toy)\n
    \n

    Parameters

    \n

    icat ICat

    \n

    Cat

    \n

    toy ContainersRefType.ColorType

    \n

    Something to play

    \n

    Sleep(ICat, long)

    \n

    Extension method hint that how long the cat can sleep.

    \n
    public static void Sleep(this ICat icat, long hours)\n
    \n

    Parameters

    \n

    icat ICat

    \n

    The type will be extended.

    \n

    hours long

    \n

    The length of sleep.

    \n", + "conceptual": "\n

    Namespace: CatLibrary
    \nAssembly: CatLibrary.dll

    \n

    It's the class that contains ICat interface's extension method.

    \n

    This class must be public and static.

    \n

    Also it shouldn't be a geneic class

    \n
    public static class ICatExtension\n
    \n

    Inheritance

    \n

    object ←\nICatExtension

    \n

    Inherited Members

    \n

    object.Equals(object?),\nobject.Equals(object?, object?),\nobject.GetHashCode(),\nobject.GetType(),\nobject.MemberwiseClone(),\nobject.ReferenceEquals(object?, object?),\nobject.ToString()

    \n

    Methods

    \n

    Play(ICat, ColorType)

    \n

    Extension method to let cat play

    \n
    public static void Play(this ICat icat, ContainersRefType.ColorType toy)\n
    \n

    Parameters

    \n

    icat ICat

    \n

    Cat

    \n

    toy ContainersRefType.ColorType

    \n

    Something to play

    \n

    Sleep(ICat, long)

    \n

    Extension method hint that how long the cat can sleep.

    \n
    public static void Sleep(this ICat icat, long hours)\n
    \n

    Parameters

    \n

    icat ICat

    \n

    The type will be extended.

    \n

    hours long

    \n

    The length of sleep.

    \n", "type": "Conceptual", "source": { "remote": { diff --git a/test/docfx.Snapshot.Tests/SamplesTest.Seed/md/CatLibrary.html.view.verified.json b/test/docfx.Snapshot.Tests/SamplesTest.Seed/md/CatLibrary.html.view.verified.json index eec926a8103..6956bfe2afc 100644 --- a/test/docfx.Snapshot.Tests/SamplesTest.Seed/md/CatLibrary.html.view.verified.json +++ b/test/docfx.Snapshot.Tests/SamplesTest.Seed/md/CatLibrary.html.view.verified.json @@ -1,5 +1,5 @@ { - "conceptual": "\n

    Namespaces

    \n

    CatLibrary.Core

    \n

    Classes

    \n

    Cat<T, K>

    \n

    Here's main class of this Demo.

    \n

    You can see mostly type of article within this class and you for more detail, please see the remarks.

    \n

    \n

    this class is a template class. It has two Generic parameter. they are: T and K.

    \n

    The extension method of this class can refer to class

    \n

    CatException<T>

    \n

    Complex<T, J>

    \n

    ICatExtension

    \n

    It's the class that contains ICat interface's extension method.

    \n

    This class must be public and static.

    \n

    Also it shouldn't be a geneic class

    \n

    Tom

    \n

    Tom class is only inherit from Object. Not any member inside itself.

    \n

    TomFromBaseClass

    \n

    TomFromBaseClass inherits from @

    \n

    Interfaces

    \n

    IAnimal

    \n

    This is basic interface of all animal.

    \n

    ICat

    \n

    Cat's interface

    \n

    Delegates

    \n

    FakeDelegate<T>

    \n

    Fake delegate

    \n

    MRefDelegate<K, T, L>

    \n

    Generic delegate with many constrains.

    \n

    MRefNormalDelegate

    \n

    Delegate in the namespace

    \n", + "conceptual": "\n

    Namespaces

    \n

    CatLibrary.Core

    \n

    Classes

    \n

    Cat<T, K>

    \n

    Here's main class of this Demo.

    \n

    You can see mostly type of article within this class and you for more detail, please see the remarks.

    \n

    \n

    this class is a template class. It has two Generic parameter. they are: T and K.

    \n

    The extension method of this class can refer to class

    \n

    CatException<T>

    \n

    Complex<T, J>

    \n

    ICatExtension

    \n

    It's the class that contains ICat interface's extension method.

    \n

    This class must be public and static.

    \n

    Also it shouldn't be a geneic class

    \n

    Tom

    \n

    Tom class is only inherit from Object. Not any member inside itself.

    \n

    TomFromBaseClass

    \n

    TomFromBaseClass inherits from @

    \n

    Interfaces

    \n

    IAnimal

    \n

    This is basic interface of all animal.

    \n

    ICat

    \n

    Cat's interface

    \n

    Delegates

    \n

    FakeDelegate<T>

    \n

    Fake delegate

    \n

    MRefDelegate<K, T, L>

    \n

    Generic delegate with many constrains.

    \n

    MRefNormalDelegate

    \n

    Delegate in the namespace

    \n", "type": "Conceptual", "source": { "remote": { diff --git a/test/docfx.Snapshot.Tests/SamplesTest.SeedMarkdown/BuildFromProject.Class1.verified.md b/test/docfx.Snapshot.Tests/SamplesTest.SeedMarkdown/BuildFromProject.Class1.verified.md index 80a08dca133..2462d345985 100644 --- a/test/docfx.Snapshot.Tests/SamplesTest.SeedMarkdown/BuildFromProject.Class1.verified.md +++ b/test/docfx.Snapshot.Tests/SamplesTest.SeedMarkdown/BuildFromProject.Class1.verified.md @@ -31,6 +31,7 @@ IClass1 ### Issue1651\(\) Pricing models are used to calculate theoretical option values +
    • 1Black Scholes
    • 2Black76
    • 3Black76Fut
    • 4Equity Tree
    • 5Variance Swap
    • 6Dividend Forecast
    ```csharp @@ -145,6 +146,7 @@ public void Issue7484() #### Remarks There's really no reason to not believe that this class can test things. +
    TermDescription
    A TermA Description
    Bee TermBee Description
    ### Issue8764\(\) diff --git a/test/docfx.Snapshot.Tests/SamplesTest.SeedMarkdown/BuildFromProject.Inheritdoc.Issue7484.verified.md b/test/docfx.Snapshot.Tests/SamplesTest.SeedMarkdown/BuildFromProject.Inheritdoc.Issue7484.verified.md index f5c3bde8213..32b67629abd 100644 --- a/test/docfx.Snapshot.Tests/SamplesTest.SeedMarkdown/BuildFromProject.Inheritdoc.Issue7484.verified.md +++ b/test/docfx.Snapshot.Tests/SamplesTest.SeedMarkdown/BuildFromProject.Inheritdoc.Issue7484.verified.md @@ -27,6 +27,7 @@ public class Inheritdoc.Issue7484 ## Remarks We're going to talk about things now. +
    Simple method to generate docs for.
    diff --git a/test/docfx.Snapshot.Tests/SamplesTest.SeedMarkdown/BuildFromProject.Inheritdoc.Issue9736.IJsonApiOptions.verified.md b/test/docfx.Snapshot.Tests/SamplesTest.SeedMarkdown/BuildFromProject.Inheritdoc.Issue9736.IJsonApiOptions.verified.md index 77e0eb7cee2..58b580028b5 100644 --- a/test/docfx.Snapshot.Tests/SamplesTest.SeedMarkdown/BuildFromProject.Inheritdoc.Issue9736.IJsonApiOptions.verified.md +++ b/test/docfx.Snapshot.Tests/SamplesTest.SeedMarkdown/BuildFromProject.Inheritdoc.Issue9736.IJsonApiOptions.verified.md @@ -24,7 +24,6 @@ bool UseRelativeLinks { get; } #### Examples
    options.UseRelativeLinks = true;
    -
    {
       "type": "articles",
       "id": "4309",
    diff --git a/test/docfx.Snapshot.Tests/SamplesTest.SeedMarkdown/BuildFromProject.Inheritdoc.Issue9736.JsonApiOptions.verified.md b/test/docfx.Snapshot.Tests/SamplesTest.SeedMarkdown/BuildFromProject.Inheritdoc.Issue9736.JsonApiOptions.verified.md
    index f0b10502450..42d409f8ec9 100644
    --- a/test/docfx.Snapshot.Tests/SamplesTest.SeedMarkdown/BuildFromProject.Inheritdoc.Issue9736.JsonApiOptions.verified.md
    +++ b/test/docfx.Snapshot.Tests/SamplesTest.SeedMarkdown/BuildFromProject.Inheritdoc.Issue9736.JsonApiOptions.verified.md
    @@ -42,7 +42,6 @@ public bool UseRelativeLinks { get; set; }
     #### Examples
     
     
    options.UseRelativeLinks = true;
    -
    {
       "type": "articles",
       "id": "4309",
    diff --git a/test/docfx.Snapshot.Tests/SamplesTest.SeedMarkdown/CatLibrary.Cat-2.verified.md b/test/docfx.Snapshot.Tests/SamplesTest.SeedMarkdown/CatLibrary.Cat-2.verified.md
    index e4d4b1532ae..655c1c89678 100644
    --- a/test/docfx.Snapshot.Tests/SamplesTest.SeedMarkdown/CatLibrary.Cat-2.verified.md
    +++ b/test/docfx.Snapshot.Tests/SamplesTest.SeedMarkdown/CatLibrary.Cat-2.verified.md
    @@ -53,7 +53,6 @@ This type is a struct type, class type can't be used for this parameter.
     ## Examples
     
     

    Here's example of how to create an instance of this class. As T is limited with class and K is limited with struct.

    -
    var a = new Cat(object, int)();
     int catNumber = new int();
     unsafe
    @@ -310,6 +309,7 @@ Result with int type.
     ###  explicit operator Tom\(Cat\)
     
     Expilicit operator of this class.
    +
     

    It means this cat can evolve to change to Tom. Tom and Jerry.

    ```csharp diff --git a/test/docfx.Snapshot.Tests/SamplesTest.SeedMarkdown/CatLibrary.ICatExtension.verified.md b/test/docfx.Snapshot.Tests/SamplesTest.SeedMarkdown/CatLibrary.ICatExtension.verified.md index f0ba1fb6128..8b7ad2bf92a 100644 --- a/test/docfx.Snapshot.Tests/SamplesTest.SeedMarkdown/CatLibrary.ICatExtension.verified.md +++ b/test/docfx.Snapshot.Tests/SamplesTest.SeedMarkdown/CatLibrary.ICatExtension.verified.md @@ -4,6 +4,7 @@ Namespace: [CatLibrary](CatLibrary.md) Assembly: CatLibrary.dll It's the class that contains ICat interface's extension method. +

    This class must be public and static.

    Also it shouldn't be a geneic class

    diff --git a/test/docfx.Snapshot.Tests/SamplesTest.SeedMarkdown/CatLibrary.verified.md b/test/docfx.Snapshot.Tests/SamplesTest.SeedMarkdown/CatLibrary.verified.md index 9701b5ef723..a2cb9c7e722 100644 --- a/test/docfx.Snapshot.Tests/SamplesTest.SeedMarkdown/CatLibrary.verified.md +++ b/test/docfx.Snapshot.Tests/SamplesTest.SeedMarkdown/CatLibrary.verified.md @@ -21,6 +21,7 @@ [ICatExtension](CatLibrary.ICatExtension.md) It's the class that contains ICat interface's extension method. +

    This class must be public and static.

    Also it shouldn't be a geneic class