diff --git a/.editorconfig b/.editorconfig index 186de61..e02e24e 100644 --- a/.editorconfig +++ b/.editorconfig @@ -1,4 +1,6 @@ # To learn more about .editorconfig see https://aka.ms/editorconfigdocs +root = true + ############################### # Core EditorConfig Options # ############################### @@ -8,11 +10,14 @@ indent_style = space [*.{csproj,xml,runsettings}] +indent_style = space indent_size = 2 +tab_size = 2 # Code files [*.{cs,csx,vb,vbx}] indent_size = 4 +tab_size = 4 insert_final_newline = true charset = utf-8 @@ -72,7 +77,7 @@ csharp_style_var_for_built_in_types = true csharp_style_var_when_type_is_apparent = true csharp_style_var_elsewhere = true # Expression-bodied members -csharp_style_expression_bodied_methods = false:suggestion +csharp_style_expression_bodied_methods = false:silent csharp_style_expression_bodied_constructors = false:suggestion csharp_style_expression_bodied_operators = false:suggestion csharp_style_expression_bodied_properties = true:suggestion @@ -122,3 +127,6 @@ csharp_space_between_method_call_empty_parameter_list_parentheses = false # Wrapping preferences csharp_preserve_single_line_statements = true csharp_preserve_single_line_blocks = true + +# IDE0022: Use block body for method +dotnet_diagnostic.IDE0022.severity = silent diff --git a/src/DendroDocs.Tool/Analyzers/SourceAnalyzer.cs b/src/DendroDocs.Tool/Analyzers/SourceAnalyzer.cs index a6d9f20..bee460f 100644 --- a/src/DendroDocs.Tool/Analyzers/SourceAnalyzer.cs +++ b/src/DendroDocs.Tool/Analyzers/SourceAnalyzer.cs @@ -221,7 +221,7 @@ private bool ProcessedEmbeddedType(SyntaxNode node) return true; } - private void ExtractAttributes(SyntaxList attributes, List attributeDescriptions) + private void ExtractAttributes(SyntaxList attributes, List attributeDescriptions) { foreach (var attribute in attributes.SelectMany(a => a.Attributes)) { diff --git a/src/DendroDocs.Tool/DendroDocs.Tool.csproj b/src/DendroDocs.Tool/DendroDocs.Tool.csproj index 6af8091..790b8c7 100644 --- a/src/DendroDocs.Tool/DendroDocs.Tool.csproj +++ b/src/DendroDocs.Tool/DendroDocs.Tool.csproj @@ -32,20 +32,19 @@ - - - - - - - - + + + + + + + + - - + diff --git a/src/DendroDocs.Tool/Program.cs b/src/DendroDocs.Tool/Program.cs index 03b5118..93ed339 100644 --- a/src/DendroDocs.Tool/Program.cs +++ b/src/DendroDocs.Tool/Program.cs @@ -1,5 +1,5 @@ -using Newtonsoft.Json; using System.Diagnostics; +using System.Text.Json; namespace DendroDocs.Tool; @@ -39,10 +39,10 @@ private static async Task RunApplicationAsync(Options options) stopwatch.Stop(); // Write analysis - var serializerSettings = JsonDefaults.SerializerSettings(); - serializerSettings.Formatting = options.PrettyPrint ? Formatting.Indented : Formatting.None; + var serializerSettings = JsonDefaults.SerializerOptions(); + serializerSettings.WriteIndented = options.PrettyPrint; - var result = JsonConvert.SerializeObject(types.OrderBy(t => t.FullName), serializerSettings); + var result = JsonSerializer.Serialize(types.OrderBy(t => t.FullName), serializerSettings); File.WriteAllText(options.OutputPath!, result); if (!options.Quiet) diff --git a/tests/DendroDocs.Tool.Tests/DeserializationTests.cs b/tests/DendroDocs.Tool.Tests/DeserializationTests.cs index 4d97e8f..f5dc0ed 100644 --- a/tests/DendroDocs.Tool.Tests/DeserializationTests.cs +++ b/tests/DendroDocs.Tool.Tests/DeserializationTests.cs @@ -1,5 +1,5 @@ using DendroDocs.Json; -using Newtonsoft.Json; +using System.Text.Json; namespace DendroDocs.Tool.Tests; @@ -13,7 +13,7 @@ public void NoTypes_Should_GiveEmptyArray() var json = @"[]"; // Act - var types = JsonConvert.DeserializeObject>(json, JsonDefaults.DeserializerSettings()); + var types = JsonSerializer.Deserialize>(json, JsonDefaults.DeserializerOptions())!; // Assert types.Should().BeEmpty(); @@ -26,7 +26,7 @@ public void AClassWithoutAModifierShouldBeInternalByDefault() var json = @"[{""FullName"":""Test""}]"; // Act - var types = JsonConvert.DeserializeObject>(json, JsonDefaults.DeserializerSettings()); + var types = JsonSerializer.Deserialize>(json, JsonDefaults.DeserializerOptions())!; // Assert types.Should().HaveCount(1); @@ -43,7 +43,7 @@ public void Collections_Should_NotBeNull() var json = @"[{""FullName"":""Test""}]"; // Act - var types = JsonConvert.DeserializeObject>(json, JsonDefaults.DeserializerSettings()); + var types = JsonSerializer.Deserialize>(json, JsonDefaults.DeserializerOptions())!; // Assert types[0].Fields.Should().BeEmpty(); @@ -78,7 +78,7 @@ public void ModifiersShouldBeDeserializedCorrectly(int value, Modifier modifier) var json = @$"[{{""Modifiers"":{value},""FullName"":""Test""}}]"; // Act - var types = JsonConvert.DeserializeObject>(json, JsonDefaults.DeserializerSettings()); + var types = JsonSerializer.Deserialize>(json, JsonDefaults.DeserializerOptions())!; // Assert types[0].Modifiers.Should().Be(modifier); @@ -91,7 +91,7 @@ public void MembersOfAClassWithoutAModifierShouldBePrivateByDefault() var json = @"[{""FullName"":""Test"",""Methods"":[{""Name"":""Method""}]}]"; // Act - var types = JsonConvert.DeserializeObject>(json, JsonDefaults.DeserializerSettings()); + var types = JsonSerializer.Deserialize>(json, JsonDefaults.DeserializerOptions())!; // Assert types[0].Methods.Should().HaveCount(1); @@ -107,7 +107,7 @@ public void AttributeCollection_Should_GiveAttributeWithNameAndType() var json = @"[{""FullName"":""Test"",""Attributes"":[{""Type"":""System.ObsoleteAttribute"",""Name"":""System.Obsolete""}]}]"; // Act - var types = JsonConvert.DeserializeObject>(json, JsonDefaults.DeserializerSettings()); + var types = JsonSerializer.Deserialize>(json, JsonDefaults.DeserializerOptions())!; // Assert types[0].Attributes.Should().HaveCount(1); @@ -123,7 +123,7 @@ public void AttributeArgumentCollection_Should_GiveAttributeArgumentWithName_Typ var json = @"[{""FullName"":""Test"",""Attributes"":[{""Type"":""System.ObsoleteAttribute"",""Name"":""System.Obsolete"",""Arguments"":[{""Name"":""\""Reason\"""",""Type"":""string"",""Value"":""Reason""}]}]}]"; // Act - var types = JsonConvert.DeserializeObject>(json, JsonDefaults.DeserializerSettings()); + var types = JsonSerializer.Deserialize>(json, JsonDefaults.DeserializerOptions())!; // Assert types[0].Attributes[0].Arguments.Should().HaveCount(1); @@ -150,7 +150,7 @@ public void AStatementInAMethodBodyShouldHaveTheMethodAsParent() }]"; // Act - var types = JsonConvert.DeserializeObject>(json, JsonDefaults.DeserializerSettings()); + var types = JsonSerializer.Deserialize>(json, JsonDefaults.DeserializerOptions())!; // Assert types[0].Methods[0].Statements[0].Parent.Should().Be(types[0].Methods[0]); @@ -173,7 +173,7 @@ public void AStatementInAConstructorBodyShouldHaveTheConstructorAsParent() }]"; // Act - var types = JsonConvert.DeserializeObject>(json, JsonDefaults.DeserializerSettings()); + var types = JsonSerializer.Deserialize>(json, JsonDefaults.DeserializerOptions())!; // Assert types[0].Constructors[0].Statements[0].Parent.Should().Be(types[0].Constructors[0]); @@ -195,7 +195,7 @@ public void AnIfElseSectionShouldHaveTheIfAsParent() }]"; // Act - var types = JsonConvert.DeserializeObject>(json, JsonDefaults.DeserializerSettings()); + var types = JsonSerializer.Deserialize>(json, JsonDefaults.DeserializerOptions())!; // Assert types[0].Methods[0].Statements[0].Should().BeOfType(); @@ -220,7 +220,7 @@ public void AnIfElseConditionShouldBeParsedCorrectly() }]"; // Act - var types = JsonConvert.DeserializeObject>(json, JsonDefaults.DeserializerSettings()); + var types = JsonSerializer.Deserialize>(json, JsonDefaults.DeserializerOptions())!; // Assert types[0].Methods[0].Statements[0].Should().BeOfType(); @@ -251,7 +251,7 @@ public void AStatementInAnIfElseSectionShouldHaveTheIfElseSectionAsParent() }]"; // Act - var types = JsonConvert.DeserializeObject>(json, JsonDefaults.DeserializerSettings()); + var types = JsonSerializer.Deserialize>(json, JsonDefaults.DeserializerOptions())!; // Assert types[0].Methods[0].Statements[0].Should().BeOfType(); @@ -276,7 +276,7 @@ public void ASwitchSectionShouldHaveTheSwitchAsParent() }]"; // Act - var types = JsonConvert.DeserializeObject>(json, JsonDefaults.DeserializerSettings()); + var types = JsonSerializer.Deserialize>(json, JsonDefaults.DeserializerOptions())!; // Assert types[0].Methods[0].Statements[0].Should().BeOfType(); @@ -301,7 +301,7 @@ public void ASwitchExpressionShouldBeParsedCorrectly() }]"; // Act - var types = JsonConvert.DeserializeObject>(json, JsonDefaults.DeserializerSettings()); + var types = JsonSerializer.Deserialize>(json, JsonDefaults.DeserializerOptions())!; // Assert types[0].Methods[0].Statements[0].Should().BeOfType(); @@ -328,7 +328,7 @@ public void SwitchLabelsShouldBeParsedCorrectly() }]"; // Act - var types = JsonConvert.DeserializeObject>(json, JsonDefaults.DeserializerSettings()); + var types = JsonSerializer.Deserialize>(json, JsonDefaults.DeserializerOptions())!; // Assert types[0].Methods[0].Statements[0].Should().BeOfType(); @@ -360,7 +360,7 @@ public void AStatementInASwitchSectionShouldHaveTheSwitchSectionAsParent() }]"; // Act - var types = JsonConvert.DeserializeObject>(json, JsonDefaults.DeserializerSettings()); + var types = JsonSerializer.Deserialize>(json, JsonDefaults.DeserializerOptions())!; // Assert types[0].Methods[0].Statements[0].Should().BeOfType(); diff --git a/tests/DendroDocs.Tool.Tests/DocumentationTagContentParsingTests.cs b/tests/DendroDocs.Tool.Tests/DocumentationTagContentParsingTests.cs index da31a10..d214d3b 100644 --- a/tests/DendroDocs.Tool.Tests/DocumentationTagContentParsingTests.cs +++ b/tests/DendroDocs.Tool.Tests/DocumentationTagContentParsingTests.cs @@ -7,70 +7,82 @@ public class DocumentationTagContentParsingTests public void Summary_Should_BeRead() { // Assign - var source = @" - /// - /// A summary. - /// - class Test - { - } - "; + var source = + """ + /// + /// A summary. + /// + class Test + { + } + """; // Act var types = TestHelper.VisitSyntaxTree(source); // Assert - types[0].DocumentationComments.Summary.Should().Be("A summary."); + types[0].DocumentationComments!.Summary.Should().Be("A summary."); } [TestMethod] public void Remarks_Should_BeRead() { // Assign - var source = @" - /// - /// A remark. - /// - class Test - { - } - "; + var source = """ + /// + /// A remark. + /// + class Test + { + } + """; // Act var types = TestHelper.VisitSyntaxTree(source); // Assert - types[0].DocumentationComments.Remarks.Should().Be("A remark."); + types[0].DocumentationComments!.Remarks.Should().Be("A remark."); } [TestMethod] public void Example_Should_BeRead() { // Assign - var source = @" - class Test - { - /// - /// The following example demonstrates the use of this method. - /// - /// - /// // Get a new random number - /// SampleClass sc = new SampleClass(10); - /// - /// int random = sc.GetRandomNumber(); - /// - /// Console.WriteLine(""Random value: {0}"", random); - /// - /// - void Method() {} - } - "; + var source = + """ + class Test + { + /// + /// The following example demonstrates the use of this method. + /// + /// + /// // Get a new random number + /// SampleClass sc = new SampleClass(10); + /// + /// int random = sc.GetRandomNumber(); + /// + /// Console.WriteLine("Random value: {0}", random); + /// + /// + void Method() {} + } + """; // Act var types = TestHelper.VisitSyntaxTree(source); // Assert - types[0].Methods[0].DocumentationComments.Example.Should().Be("The following example demonstrates the use of this method.\n\n// Get a new random number\nSampleClass sc = new SampleClass(10);\n\nint random = sc.GetRandomNumber();\n\nConsole.WriteLine(\"Random value: {0}\", random);"); + types[0].Methods[0].DocumentationComments!.Example.Should().Be( + """ + The following example demonstrates the use of this method. + + // Get a new random number + SampleClass sc = new SampleClass(10); + + int random = sc.GetRandomNumber(); + + Console.WriteLine("Random value: {0}", random); + """.UseUnixNewLine()); } @@ -78,13 +90,14 @@ void Method() {} public void Exception_Should_BeRead() { // Assign - var source = @" - class Test - { - /// An exception. - void Method() {} - } - "; + var source = + """ + class Test + { + /// An exception. + void Method() {} + } + """; // Act var types = TestHelper.VisitSyntaxTree(source); @@ -92,8 +105,8 @@ void Method() {} // Assert using (new AssertionScope()) { - types[0].Methods[0].DocumentationComments.Exceptions.Should().HaveCount(1); - types[0].Methods[0].DocumentationComments.Exceptions.Should().Contain("System.Exception", "An exception."); + types[0].Methods[0].DocumentationComments!.Exceptions.Should().HaveCount(1); + types[0].Methods[0].DocumentationComments!.Exceptions.Should().Contain("System.Exception", "An exception."); } } @@ -101,14 +114,15 @@ void Method() {} public void Exceptions_Should_BeRead() { // Assign - var source = @" - class Test - { - /// An exception. - /// Another exception. - void Method() {} - } - "; + var source = + """ + class Test + { + /// An exception. + /// Another exception. + void Method() {} + } + """; // Act var types = TestHelper.VisitSyntaxTree(source); @@ -116,9 +130,9 @@ void Method() {} // Assert using (new AssertionScope()) { - types[0].Methods[0].DocumentationComments.Exceptions.Should().HaveCount(2); - types[0].Methods[0].DocumentationComments.Exceptions.Should().Contain("System.Exception", "An exception."); - types[0].Methods[0].DocumentationComments.Exceptions.Should().Contain("System.StackOverflowException", "Another exception."); + types[0].Methods[0].DocumentationComments!.Exceptions.Should().HaveCount(2); + types[0].Methods[0].DocumentationComments!.Exceptions.Should().Contain("System.Exception", "An exception."); + types[0].Methods[0].DocumentationComments!.Exceptions.Should().Contain("System.StackOverflowException", "Another exception."); } } @@ -126,13 +140,14 @@ void Method() {} public void Param_Should_BeRead() { // Assign - var source = @" - class Test - { - /// This is a param. - void Method(string param) {} - } - "; + var source = + """ + class Test + { + /// This is a param. + void Method(string param) {} + } + """; // Act var types = TestHelper.VisitSyntaxTree(source); @@ -140,8 +155,8 @@ void Method(string param) {} // Assert using (new AssertionScope()) { - types[0].Methods[0].DocumentationComments.Params.Should().HaveCount(1); - types[0].Methods[0].DocumentationComments.Params.Should().Contain("param", "This is a param."); + types[0].Methods[0].DocumentationComments!.Params.Should().HaveCount(1); + types[0].Methods[0].DocumentationComments!.Params.Should().Contain("param", "This is a param."); } } @@ -149,14 +164,15 @@ void Method(string param) {} public void Params_Should_BeRead() { // Assign - var source = @" - class Test - { - /// This is the first parameter. - /// This is the second parameter. - void Method(string param1, string param2) {} - } - "; + var source = + """ + class Test + { + /// This is the first parameter. + /// This is the second parameter. + void Method(string param1, string param2) {} + } + """; // Act var types = TestHelper.VisitSyntaxTree(source); @@ -164,9 +180,9 @@ void Method(string param1, string param2) {} // Assert using (new AssertionScope()) { - types[0].Methods[0].DocumentationComments.Params.Should().HaveCount(2); - types[0].Methods[0].DocumentationComments.Params.Should().Contain("param1", "This is the first parameter."); - types[0].Methods[0].DocumentationComments.Params.Should().Contain("param2", "This is the second parameter."); + types[0].Methods[0].DocumentationComments!.Params.Should().HaveCount(2); + types[0].Methods[0].DocumentationComments!.Params.Should().Contain("param1", "This is the first parameter."); + types[0].Methods[0].DocumentationComments!.Params.Should().Contain("param2", "This is the second parameter."); } } @@ -174,13 +190,14 @@ void Method(string param1, string param2) {} public void Permission_Should_BeRead() { // Assign - var source = @" - class Test - { - /// A permission. - void Method() {} - } - "; + var source = + """ + class Test + { + /// A permission. + void Method() {} + } + """; // Act var types = TestHelper.VisitSyntaxTree(source); @@ -188,8 +205,8 @@ void Method() {} // Assert using (new AssertionScope()) { - types[0].Methods[0].DocumentationComments.Permissions.Should().HaveCount(1); - types[0].Methods[0].DocumentationComments.Permissions.Should().Contain("System.Security.PermissionSet", "A permission."); + types[0].Methods[0].DocumentationComments!.Permissions.Should().HaveCount(1); + types[0].Methods[0].DocumentationComments!.Permissions.Should().Contain("System.Security.PermissionSet", "A permission."); } } @@ -197,14 +214,15 @@ void Method() {} public void Permissions_Should_BeRead() { // Assign - var source = @" - class Test - { - /// A permission. - /// Another permission. - void Method() {} - } - "; + var source = + """ + class Test + { + /// A permission. + /// Another permission. + void Method() {} + } + """; // Act var types = TestHelper.VisitSyntaxTree(source); @@ -212,9 +230,9 @@ void Method() {} // Assert using (new AssertionScope()) { - types[0].Methods[0].DocumentationComments.Permissions.Should().HaveCount(2); - types[0].Methods[0].DocumentationComments.Permissions.Should().Contain("System.Security.Permissions.EnvironmentPermission", "A permission."); - types[0].Methods[0].DocumentationComments.Permissions.Should().Contain("System.Security.Permissions.FileIOPermission", "Another permission."); + types[0].Methods[0].DocumentationComments!.Permissions.Should().HaveCount(2); + types[0].Methods[0].DocumentationComments!.Permissions.Should().Contain("System.Security.Permissions.EnvironmentPermission", "A permission."); + types[0].Methods[0].DocumentationComments!.Permissions.Should().Contain("System.Security.Permissions.FileIOPermission", "Another permission."); } } @@ -222,13 +240,14 @@ void Method() {} public void SeeAlso_Should_BeRead() { // Assign - var source = @" - class Test - { - /// - void Method() {} - } - "; + var source = + """ + class Test + { + /// + void Method() {} + } + """; // Act var types = TestHelper.VisitSyntaxTree(source); @@ -236,8 +255,8 @@ void Method() {} // Assert using (new AssertionScope()) { - types[0].Methods[0].DocumentationComments.SeeAlsos.Should().HaveCount(1); - types[0].Methods[0].DocumentationComments.SeeAlsos.Should().Contain("System.String", "System.String"); + types[0].Methods[0].DocumentationComments!.SeeAlsos.Should().HaveCount(1); + types[0].Methods[0].DocumentationComments!.SeeAlsos.Should().Contain("System.String", "System.String"); } } @@ -245,14 +264,15 @@ void Method() {} public void SeeAlsos_Should_BeRead() { // Assign - var source = @" - class Test - { - /// - /// See also. - void Method() {} - } - "; + var source = + """ + class Test + { + /// + /// See also. + void Method() {} + } + """; // Act var types = TestHelper.VisitSyntaxTree(source); @@ -260,9 +280,9 @@ void Method() {} // Assert using (new AssertionScope()) { - types[0].Methods[0].DocumentationComments.SeeAlsos.Should().HaveCount(2); - types[0].Methods[0].DocumentationComments.SeeAlsos.Should().Contain("System.String", "System.String"); - types[0].Methods[0].DocumentationComments.SeeAlsos.Should().Contain("System.Object", "See also."); + types[0].Methods[0].DocumentationComments!.SeeAlsos.Should().HaveCount(2); + types[0].Methods[0].DocumentationComments!.SeeAlsos.Should().Contain("System.String", "System.String"); + types[0].Methods[0].DocumentationComments!.SeeAlsos.Should().Contain("System.Object", "See also."); } } @@ -270,13 +290,14 @@ void Method() {} public void TypeParam_Should_BeRead() { // Assign - var source = @" - class Test - { - /// This is a type param. - void Method() {} - } - "; + var source = + """ + class Test + { + /// This is a type param. + void Method() {} + } + """; // Act var types = TestHelper.VisitSyntaxTree(source); @@ -284,8 +305,8 @@ void Method() {} // Assert using (new AssertionScope()) { - types[0].Methods[0].DocumentationComments.TypeParams.Should().HaveCount(1); - types[0].Methods[0].DocumentationComments.TypeParams.Should().Contain("T", "This is a type param."); + types[0].Methods[0].DocumentationComments!.TypeParams.Should().HaveCount(1); + types[0].Methods[0].DocumentationComments!.TypeParams.Should().Contain("T", "This is a type param."); } } @@ -293,14 +314,15 @@ void Method() {} public void TypeParams_Should_BeRead() { // Assign - var source = @" - class Test - { - /// This is the first type parameter. - /// This is the second type parameter. - void Method() {} - } - "; + var source = + """ + class Test + { + /// This is the first type parameter. + /// This is the second type parameter. + void Method() {} + } + """; // Act var types = TestHelper.VisitSyntaxTree(source); @@ -308,9 +330,9 @@ void Method() {} // Assert using (new AssertionScope()) { - types[0].Methods[0].DocumentationComments.TypeParams.Should().HaveCount(2); - types[0].Methods[0].DocumentationComments.TypeParams.Should().Contain("T1", "This is the first type parameter."); - types[0].Methods[0].DocumentationComments.TypeParams.Should().Contain("T2", "This is the second type parameter."); + types[0].Methods[0].DocumentationComments!.TypeParams.Should().HaveCount(2); + types[0].Methods[0].DocumentationComments!.TypeParams.Should().Contain("T1", "This is the first type parameter."); + types[0].Methods[0].DocumentationComments!.TypeParams.Should().Contain("T2", "This is the second type parameter."); } } @@ -318,79 +340,87 @@ void Method() {} public void SummaryWithWhitespace_Should_BeTrimmed() { // Assign - var source = @" - /// - /// - /// A - /// - /// - class Test - { - } - "; + var source = + """ + /// + /// + /// A + /// + /// + class Test + { + } + """; // Act var types = TestHelper.VisitSyntaxTree(source); // Assert - types[0].DocumentationComments.Summary.Should().Be("A"); + types[0].DocumentationComments!.Summary.Should().Be("A"); } [TestMethod] public void NonSummaryWithWhitespace_Should_OnlyNonNewLinesBeTrimmed() { // Assign - var source = @" - /// - /// A - /// B - /// - class Test - { - } - "; + var source = + """ + /// + /// A + /// B + /// + class Test + { + } + """; // Act var types = TestHelper.VisitSyntaxTree(source); // Assert - types[0].DocumentationComments.Remarks.Should().Be("A\nB"); + types[0].DocumentationComments!.Remarks.Should().Be( + """ + A + B + """.UseUnixNewLine()); } [TestMethod] - public void TagWithSeeAlso_Should_IgnoreSeeAlso() + public void SummaryWithSeeAlso_Should_DisplaySeeAlso() { // Assign - var source = @" - class Test - { - /// - /// See also. - /// - public void Method() {} - } - "; + var source = + """ + class Test + { + /// + /// See also. + /// + public void Method() {} + } + """; // Act var types = TestHelper.VisitSyntaxTree(source); // Assert - types[0].Methods[0].DocumentationComments.Summary.Should().BeEmpty(); + types[0].Methods[0].DocumentationComments!.Summary.Should().Be("See also."); } [TestMethod] public void TagWithSeeAlso_Should_AddToSeeAlsos() { // Assign - var source = @" - class Test - { - /// - /// See also. - /// - public void Method() {} - } - "; + var source = + """ + class Test + { + /// + /// See also. + /// + public void Method() {} + } + """; // Act var types = TestHelper.VisitSyntaxTree(source); @@ -398,8 +428,8 @@ public void Method() {} // Assert using (new AssertionScope()) { - types[0].Methods[0].DocumentationComments.SeeAlsos.Should().HaveCount(1); - types[0].Methods[0].DocumentationComments.SeeAlsos.Should().Contain("System.Object", "See also."); + types[0].Methods[0].DocumentationComments!.SeeAlsos.Should().HaveCount(1); + types[0].Methods[0].DocumentationComments!.SeeAlsos.Should().Contain("System.Object", "See also."); } } @@ -407,42 +437,44 @@ public void Method() {} public void TagWithParamRefName_Should_HaveNameAsComment() { // Assign - var source = @" - class Test - { - /// - /// A c - /// - public void Method(string b) {} - } - "; + var source = + """ + class Test + { + /// + /// A c + /// + public void Method(string b) {} + } + """; // Act var types = TestHelper.VisitSyntaxTree(source); // Assert - types[0].Methods[0].DocumentationComments.Summary.Should().Be("A b c"); + types[0].Methods[0].DocumentationComments!.Summary.Should().Be("A b c"); } [TestMethod] public void TagWithTypeParamRefName_Should_HaveNameAsComment() { // Assign - var source = @" - class Test - { - /// - /// A c - /// - public void Method() {} - } - "; + var source = + """ + class Test + { + /// + /// A c + /// + public void Method() {} + } + """; // Act var types = TestHelper.VisitSyntaxTree(source); // Assert - types[0].Methods[0].DocumentationComments.Summary.Should().Be("A b c"); + types[0].Methods[0].DocumentationComments!.Summary.Should().Be("A b c"); } [TestMethod] @@ -464,7 +496,7 @@ class Test var types = TestHelper.VisitSyntaxTree(source); // Assert - types[0].DocumentationComments.Summary.Should().Be("a b"); + types[0].DocumentationComments!.Summary.Should().Be("a b"); } [TestMethod] @@ -485,352 +517,418 @@ class Test var types = TestHelper.VisitSyntaxTree(source); // Assert - types[0].DocumentationComments.Summary.Should().Be("a\nb"); + types[0].DocumentationComments!.Summary.Should().Be( + """ + a + b + """.UseUnixNewLine()); } [TestMethod] public void SummaryWithMultipleParas_Should_HaveLinebreakBetweenText() { // Assign - var source = @" - /// - /// a - /// b - /// c - /// - class Test - { - } - "; + var source = + """ + /// + /// a + /// b + /// c + /// + class Test + { + } + """; // Act var types = TestHelper.VisitSyntaxTree(source); // Assert - types[0].DocumentationComments.Summary.Should().Be("a\nb\nc"); + types[0].DocumentationComments!.Summary.Should().Be( + """ + a + b + c + """.UseUnixNewLine()); } [TestMethod] public void TagWithSeeWithInnertext_Should_HaveInnerTextAsComment() { // Assign - var source = @" - /// - /// A b c - /// - class Test - { - } - "; + var source = + """ + /// + /// A b c + /// + class Test + { + } + """; // Act var types = TestHelper.VisitSyntaxTree(source); // Assert - types[0].DocumentationComments.Summary.Should().Be("A b c"); + types[0].DocumentationComments!.Summary.Should().Be("A b c"); } [TestMethod] public void TagWithSee_Should_HaveCrefAsComment() { // Assign - var source = @" - /// - /// A c - /// - class Test - { - } - "; + var source = + """ + /// + /// A c + /// + class Test + { + } + """; // Act var types = TestHelper.VisitSyntaxTree(source); // Assert - types[0].DocumentationComments.Summary.Should().Be("A b c"); + types[0].DocumentationComments!.Summary.Should().Be("A b c"); } [TestMethod] public void TagWithCode_Should_HaveInnerTextAsComment() { // Assign - var source = @" - /// - /// A b c - /// - class Test - { - } - "; + var source = + """ + /// + /// A b c + /// + class Test + { + } + """; // Act var types = TestHelper.VisitSyntaxTree(source); // Assert - types[0].DocumentationComments.Summary.Should().Be("A b c"); + types[0].DocumentationComments!.Summary.Should().Be("A b c"); } [TestMethod] public void TagWithInvalidList_Should_HaveListItemsAsInlineTextInComment() { // Assign - var source = @" - /// - /// - /// First item - /// Second item - /// - /// - class Test - { - } - "; + var source = + """ + /// + /// + /// First item + /// Second item + /// + /// + class Test + { + } + """; // Act var types = TestHelper.VisitSyntaxTree(source); // Assert - types[0].DocumentationComments.Summary.Should().Be("First item Second item"); + types[0].DocumentationComments!.Summary.Should().Be( + """ + First item + Second item + """.UseUnixNewLine()); } [TestMethod] public void TagWithBulletList_Should_HaveListItemsAsLinesInComment() { // Assign - var source = @" - /// - /// - /// First item - /// Second item - /// - /// - class Test - { - } - "; + var source = + """ + /// + /// + /// First item + /// Second item + /// + /// + class Test + { + } + """; // Act var types = TestHelper.VisitSyntaxTree(source); // Assert - types[0].DocumentationComments.Summary.Should().Be("* First item\n* Second item"); + types[0].DocumentationComments!.Summary.Should().Be( + """ + * First item + * Second item + """.UseUnixNewLine()); } [TestMethod] public void TagWithBulletListWithDescriptions_Should_HaveListItemsAsLinesInComment() { // Assign - var source = @" - /// - /// - /// First item - /// Second item - /// - /// - class Test - { - } - "; + var source = + """ + /// + /// + /// First item + /// Second item + /// + /// + class Test + { + } + """; // Act var types = TestHelper.VisitSyntaxTree(source); // Assert - types[0].DocumentationComments.Summary.Should().Be("* First item\n* Second item"); + types[0].DocumentationComments!.Summary.Should().Be( + """ + * First item + * Second item + """.UseUnixNewLine()); } [TestMethod] public void TagWithBulletListWithTermsAndDescriptions_Should_HaveListItemsAsLinesInComment() { // Assign - var source = @" - /// - /// - /// - /// Term 1 - /// First item - /// - /// - /// Term 2 - /// Second item - /// - /// - /// - class Test - { - } - "; + var source = + """ + /// + /// + /// + /// Term 1 + /// First item + /// + /// + /// Term 2 + /// Second item + /// + /// + /// + class Test + { + } + """; // Act var types = TestHelper.VisitSyntaxTree(source); // Assert - types[0].DocumentationComments.Summary.Should().Be("* Term 1 - First item\n* Term 2 - Second item"); + types[0].DocumentationComments!.Summary.Should().Be( + """ + * Term 1 - First item + * Term 2 - Second item + """.UseUnixNewLine()); } - - [TestMethod] public void TagWithNumberedList_Should_HaveNumberedListItemsAsLinesInComment() { // Assign - var source = @" - /// - /// - /// First item - /// Second item - /// - /// - class Test - { - } - "; + var source = + """ + /// + /// + /// First item + /// Second item + /// + /// + class Test + { + } + """; // Act var types = TestHelper.VisitSyntaxTree(source); // Assert - types[0].DocumentationComments.Summary.Should().Be("1. First item\n2. Second item"); + types[0].DocumentationComments!.Summary.Should().Be( + """ + 1. First item + 2. Second item + """.UseUnixNewLine()); } [TestMethod] public void TagWithNumberedListWithStart_Should_HaveCorrectNumberedListItemsAsLinesInComment() { // Assign - var source = @" - /// - /// - /// First item - /// Second item - /// - /// - class Test - { - } - "; + var source = + """ + /// + /// + /// First item + /// Second item + /// + /// + class Test + { + } + """; // Act var types = TestHelper.VisitSyntaxTree(source); // Assert - types[0].DocumentationComments.Summary.Should().Be("3. First item\n4. Second item"); + types[0].DocumentationComments!.Summary.Should().Be( + """ + 3. First item + 4. Second item + """.UseUnixNewLine()); } [TestMethod] public void TagWithNumberedListWithDescriptions_Should_HaveNumberedListItemsAsLinesInComment() { // Assign - var source = @" - /// - /// - /// First item - /// Second item - /// - /// - class Test - { - } - "; + var source = + """ + /// + /// + /// First item + /// Second item + /// + /// + class Test + { + } + """; // Act var types = TestHelper.VisitSyntaxTree(source); // Assert - types[0].DocumentationComments.Summary.Should().Be("1. First item\n2. Second item"); + types[0].DocumentationComments!.Summary.Should().Be( + """ + 1. First item + 2. Second item + """.UseUnixNewLine()); } [TestMethod] public void TagWithNumberedListWithTermsAndDescriptions_Should_HaveNumberedListItemsAsLinesInComment() { // Assign - var source = @" - /// - /// - /// - /// Term 1 - /// First item - /// - /// - /// Term 2 - /// Second item - /// - /// - /// - class Test - { - } - "; + var source = + """ + /// + /// + /// + /// Term 1 + /// First item + /// + /// + /// Term 2 + /// Second item + /// + /// + /// + class Test + { + } + """; // Act var types = TestHelper.VisitSyntaxTree(source); // Assert - types[0].DocumentationComments.Summary.Should().Be("1. Term 1 - First item\n2. Term 2 - Second item"); + types[0].DocumentationComments!.Summary.Should().Be( + """ + 1. Term 1 - First item + 2. Term 2 - Second item + """.UseUnixNewLine()); } [TestMethod] public void TagWithDefinitionListWithTermsAndDescriptions_Should_HaveSeperateLinesWithTermAndDescriptionIndented() { // Assign - var source = @" - /// - /// - /// - /// Term 1 - /// First item - /// - /// - /// Term 2 - /// Second item - /// - /// - /// - class Test - { - } - "; + var source = + """ + /// + /// + /// + /// Term 1 + /// First item + /// + /// + /// Term 2 + /// Second item + /// + /// + /// + class Test + { + } + """; // Act var types = TestHelper.VisitSyntaxTree(source); // Assert - types[0].DocumentationComments.Summary.Should().Be("Term 1\n First item\nTerm 2\n Second item"); + types[0].DocumentationComments!.Summary.Should().Be( + """ + Term 1 — First item + Term 2 — Second item + """.UseUnixNewLine()); } [TestMethod] public void TagWithNestedContent_Should_RenderCorrectly() { // Assign - var source = @" - /// - /// This is a summary with mixed content. - /// A paragraph - /// Another - /// - /// - /// Term 1 - /// First - /// - /// - /// Term 2 - /// Second item - /// - /// - /// - /// class ACodeSample { } - /// - /// More text null and more text - /// - /// - class Test - { - } - "; + var source = + """ + /// + /// This is a summary with mixed content. + /// A paragraph + /// Another + /// + /// + /// Term 1 + /// First + /// + /// + /// Term 2 + /// Second item + /// + /// + /// + /// class ACodeSample { } + /// + /// More text null and more text + /// + /// + class Test + { + } + """; // Act var types = TestHelper.VisitSyntaxTree(source); // Assert - types[0].DocumentationComments.Summary.Should().Be("This is a summary with mixed content.\nA paragraph\nAnother paragraph\nTerm 1\n First item\nTerm 2\n Second item\nclass ACodeSample { }\nMore text null and more text"); + types[0].DocumentationComments!.Summary.Should().Be( + """ + This is a summary with mixed content. + A paragraph + Another paragraph + Term 1 — First item + Term 2 — Second item + class ACodeSample { } + More text null and more text System.Text.Action + """.UseUnixNewLine()); } } diff --git a/tests/DendroDocs.Tool.Tests/SerializationTests.cs b/tests/DendroDocs.Tool.Tests/SerializationTests.cs index 3974bb8..3a8fde0 100644 --- a/tests/DendroDocs.Tool.Tests/SerializationTests.cs +++ b/tests/DendroDocs.Tool.Tests/SerializationTests.cs @@ -1,5 +1,5 @@ using DendroDocs.Json; -using Newtonsoft.Json; +using System.Text.Json; namespace DendroDocs.Tool.Tests { @@ -15,7 +15,7 @@ public void NoTypes_Should_GiveEmptyArray() // Act var types = TestHelper.VisitSyntaxTree(source); - var result = JsonConvert.SerializeObject(types, JsonDefaults.SerializerSettings()); + var result = JsonSerializer.Serialize(types, JsonDefaults.SerializerOptions()); // Assert result.Should().Be("[]"); @@ -30,7 +30,7 @@ public void InternalClass_Should_GiveOnlyFullName() // Act var types = TestHelper.VisitSyntaxTree(source); - var result = JsonConvert.SerializeObject(types, JsonDefaults.SerializerSettings()); + var result = JsonSerializer.Serialize(types, JsonDefaults.SerializerOptions()); // Assert result.Should().Be(@"[{""FullName"":""Test""}]"); @@ -45,7 +45,7 @@ public void PublicClass_Should_GiveOnlyNonDefaultModifier() // Act var types = TestHelper.VisitSyntaxTree(source); - var result = JsonConvert.SerializeObject(types, JsonDefaults.SerializerSettings()); + var result = JsonSerializer.Serialize(types, JsonDefaults.SerializerOptions()); // Assert result.Should().Be(@"[{""FullName"":""Test"",""Modifiers"":2}]"); @@ -62,7 +62,7 @@ void Method() {} // Act var types = TestHelper.VisitSyntaxTree(source); - var result = JsonConvert.SerializeObject(types, JsonDefaults.SerializerSettings()); + var result = JsonSerializer.Serialize(types, JsonDefaults.SerializerOptions()); // Assert result.Should().Be(@"[{""FullName"":""Test"",""Methods"":[{""Name"":""Method""}]}]"); @@ -79,7 +79,7 @@ public void PrivateNonVoidMethod_Should_GiveNameAndReturnType() // Act var types = TestHelper.VisitSyntaxTree(source); - var result = JsonConvert.SerializeObject(types, JsonDefaults.SerializerSettings()); + var result = JsonSerializer.Serialize(types, JsonDefaults.SerializerOptions()); // Assert result.Should().Match(@"[{""FullName"":""Test"",""Methods"":[{""Name"":""Method"",""ReturnType"":""int"",*}]}]"); @@ -97,7 +97,7 @@ class Test { // Act var types = TestHelper.VisitSyntaxTree(source); - var result = JsonConvert.SerializeObject(types, JsonDefaults.SerializerSettings()); + var result = JsonSerializer.Serialize(types, JsonDefaults.SerializerOptions()); // Assert result.Should().Match(@"[{""FullName"":""Test"",""Attributes"":[{""Type"":""System.ObsoleteAttribute"",""Name"":""System.Obsolete""}]}]"); @@ -115,7 +115,7 @@ class Test { // Act var types = TestHelper.VisitSyntaxTree(source); - var result = JsonConvert.SerializeObject(types, JsonDefaults.SerializerSettings()); + var result = JsonSerializer.Serialize(types, JsonDefaults.SerializerOptions()); // Assert result.Should().Match(@"[{""FullName"":""Test"",""Attributes"":[{""Type"":""System.ObsoleteAttribute"",""Name"":""System.Obsolete"",""Arguments"":[{""Name"":""message"",""Type"":""string"",""Value"":""Reason""}]}]}]"); diff --git a/tests/DendroDocs.Tool.Tests/TestHelper.cs b/tests/DendroDocs.Tool.Tests/TestHelper.cs index e8fe147..4f559a0 100644 --- a/tests/DendroDocs.Tool.Tests/TestHelper.cs +++ b/tests/DendroDocs.Tool.Tests/TestHelper.cs @@ -1,11 +1,15 @@ using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.CSharp; using System.Runtime.CompilerServices; +using System.Text.RegularExpressions; namespace DendroDocs.Tool.Tests; -internal class TestHelper +internal static partial class TestHelper { + [GeneratedRegex(@"(\r\n|\r|\n)")] + private static partial Regex NewlineChars(); + public static IReadOnlyList VisitSyntaxTree(string source, params string[] ignoreErrorCodes) { source.Should().NotBeNullOrWhiteSpace("without source code there is nothing to test"); @@ -33,4 +37,9 @@ public static IReadOnlyList VisitSyntaxTree(string source, para return types; } + + public static string UseUnixNewLine(this string value) => value.UseSpecificNewLine("\n"); + public static string UseWindowsNewLine(this string value) => value.UseSpecificNewLine("\r\n"); + public static string UseEnvironmentNewLine(this string value) => value.UseSpecificNewLine(Environment.NewLine); + public static string UseSpecificNewLine(this string value, string specificNewline) => NewlineChars().Replace(value, specificNewline); }