From a684e1450aac2463138c78dda1805b5e54b1c58a Mon Sep 17 00:00:00 2001 From: kronic Date: Fri, 27 Oct 2023 15:40:21 +0300 Subject: [PATCH 1/6] - --- XmlSchemaClassGenerator.Console/Program.cs | 2 +- XmlSchemaClassGenerator.Tests/Compiler.cs | 2 +- .../DocumentationTests.cs | 193 ++++++++++++++++++ XmlSchemaClassGenerator.Tests/XmlTests.cs | 2 +- XmlSchemaClassGenerator/Generator.cs | 2 +- .../GeneratorConfiguration.cs | 2 +- XmlSchemaClassGenerator/ModelBuilder.cs | 2 +- XmlSchemaClassGenerator/TypeModel.cs | 49 +++-- 8 files changed, 234 insertions(+), 20 deletions(-) create mode 100644 XmlSchemaClassGenerator.Tests/DocumentationTests.cs diff --git a/XmlSchemaClassGenerator.Console/Program.cs b/XmlSchemaClassGenerator.Console/Program.cs index a9e4121c..36716143 100644 --- a/XmlSchemaClassGenerator.Console/Program.cs +++ b/XmlSchemaClassGenerator.Console/Program.cs @@ -246,7 +246,7 @@ A file name may be given by appending a pipe sign (|) followed by a file name (l generator.NamingProvider = new SubstituteNamingProvider(nameSubstituteMap); } - generator.CommentLanguages.AddRange(commentLanguages); + generator.CommentLanguages.UnionWith(commentLanguages); if (pclCompatible) { diff --git a/XmlSchemaClassGenerator.Tests/Compiler.cs b/XmlSchemaClassGenerator.Tests/Compiler.cs index 002c78f9..3d424797 100644 --- a/XmlSchemaClassGenerator.Tests/Compiler.cs +++ b/XmlSchemaClassGenerator.Tests/Compiler.cs @@ -122,7 +122,7 @@ public static Assembly GenerateFiles(string name, IEnumerable files, Gen }; gen.CommentLanguages.Clear(); - gen.CommentLanguages.AddRange(generatorPrototype.CommentLanguages); + gen.CommentLanguages.UnionWith(generatorPrototype.CommentLanguages); output.Configuration = gen.Configuration; diff --git a/XmlSchemaClassGenerator.Tests/DocumentationTests.cs b/XmlSchemaClassGenerator.Tests/DocumentationTests.cs new file mode 100644 index 00000000..9dab2b05 --- /dev/null +++ b/XmlSchemaClassGenerator.Tests/DocumentationTests.cs @@ -0,0 +1,193 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Xml.Schema; + +using Xunit; + +namespace XmlSchemaClassGenerator.Tests; + +public sealed class DocumentationTests +{ + private static IEnumerable ConvertXml(string xsd, Generator generatorPrototype) + { + var writer = new MemoryOutputWriter(); + + var gen = new Generator + { + OutputWriter = writer, + Version = new("Tests", "1.0.0.1"), + NamespaceProvider = generatorPrototype.NamespaceProvider, + //DataAnnotationMode = generatorPrototype.DataAnnotationMode, + GenerateDescriptionAttribute = generatorPrototype.GenerateDescriptionAttribute + }; + + var set = new XmlSchemaSet(); + + using (var stringReader = new StringReader(xsd)) + { + var schema = XmlSchema.Read + ( + stringReader, + (_, e) => throw new InvalidOperationException($"{e.Severity}: {e.Message}", e.Exception) + ); + + ArgumentNullException.ThrowIfNull(schema); + set.Add(schema); + } + + gen.Generate(set); + + return writer.Content; + } + + [Fact] + public void TestSummaryDoc() + { + const string xsd = """ + + + + + + Заголовок конверта. + Информация приложения + + + + + Тип программного обеспечения + + + + + Версия программного + обеспечения + + + + + Тип сообщения + + + + + + + """; + + var code = ConvertXml(xsd, new() {NamespacePrefix = "Test"}) + .Single(); + + Assert.Contains + ( + """ + /// + /// Заголовок конверта. + /// Информация приложения + /// + """, + code, + StringComparison.Ordinal + ); + + Assert.Contains + ( + """ + /// + /// Тип программного обеспечения + /// + """, + code, + StringComparison.Ordinal + ); + Assert.Contains + ( + """ + /// + /// Версия программного + /// обеспечения + /// + """, + code, + StringComparison.Ordinal + ); + + Assert.Contains + ( + """ + /// + /// Тип сообщения + /// + """, + code, + StringComparison.Ordinal + ); + } + + [Fact] + public void TestDescriptionAttributeValue() + { + const string xsd = """ + + + + + + Заголовок конверта. + Информация приложения + + + + + Тип программного обеспечения + + + + + Версия программного обеспечения + + + + + Тип сообщения + + + + + + + """; + + var code = ConvertXml(xsd, new() { NamespacePrefix = "Test", GenerateDescriptionAttribute = true }) + .Single(); + + Assert.Contains + ( + """[System.ComponentModel.DescriptionAttribute("Заголовок конверта. Информация приложения")]""", + code, + StringComparison.Ordinal + ); + + Assert.Contains + ( + """[System.ComponentModel.DescriptionAttribute("Тип программного обеспечения")]""", + code, + StringComparison.Ordinal + ); + Assert.Contains + ( + """[System.ComponentModel.DescriptionAttribute("Версия программного обеспечения")]""", + code, + StringComparison.Ordinal + ); + + Assert.Contains + ( + """[System.ComponentModel.DescriptionAttribute("Тип сообщения")]""", + code, + StringComparison.Ordinal + ); + } +} \ No newline at end of file diff --git a/XmlSchemaClassGenerator.Tests/XmlTests.cs b/XmlSchemaClassGenerator.Tests/XmlTests.cs index 4edee63a..f9f0c47c 100644 --- a/XmlSchemaClassGenerator.Tests/XmlTests.cs +++ b/XmlSchemaClassGenerator.Tests/XmlTests.cs @@ -69,7 +69,7 @@ private static IEnumerable ConvertXml(string name, IEnumerable x }; gen.CommentLanguages.Clear(); - gen.CommentLanguages.AddRange(generatorPrototype.CommentLanguages); + gen.CommentLanguages.UnionWith(generatorPrototype.CommentLanguages); var set = new XmlSchemaSet(); diff --git a/XmlSchemaClassGenerator/Generator.cs b/XmlSchemaClassGenerator/Generator.cs index 89cad4e8..527324a0 100644 --- a/XmlSchemaClassGenerator/Generator.cs +++ b/XmlSchemaClassGenerator/Generator.cs @@ -277,7 +277,7 @@ public bool CompactTypeNames set { _configuration.CompactTypeNames = value; } } - public List CommentLanguages + public HashSet CommentLanguages { get { return _configuration.CommentLanguages; } } diff --git a/XmlSchemaClassGenerator/GeneratorConfiguration.cs b/XmlSchemaClassGenerator/GeneratorConfiguration.cs index add6a8cf..ef322630 100644 --- a/XmlSchemaClassGenerator/GeneratorConfiguration.cs +++ b/XmlSchemaClassGenerator/GeneratorConfiguration.cs @@ -291,7 +291,7 @@ public void WriteLog(string message) /// /// The language identifiers comments will be generated for, e.g. "en", "de-DE". /// - public List CommentLanguages { get; } = new List(); + public HashSet CommentLanguages { get; } = new HashSet(StringComparer.OrdinalIgnoreCase); /// /// Create unique type names across all namespaces. See https://github.com/mganss/XmlSchemaClassGenerator/issues/240 diff --git a/XmlSchemaClassGenerator/ModelBuilder.cs b/XmlSchemaClassGenerator/ModelBuilder.cs index 0429ff1d..5eba9544 100644 --- a/XmlSchemaClassGenerator/ModelBuilder.cs +++ b/XmlSchemaClassGenerator/ModelBuilder.cs @@ -1078,7 +1078,7 @@ public static List GetDocumentation(XmlSchemaAnnotated annot return annotated.Annotation == null ? new List() : annotated.Annotation.Items.OfType() .Where(d => d.Markup?.Length > 0) - .Select(d => d.Markup.Select(m => new DocumentationModel { Language = d.Language, Text = new XText($"{m.Name}: {m.InnerText}").ToString() })) + .Select(d => d.Markup.Select(m => new DocumentationModel { Language = d.Language, Text = m.Value })) .SelectMany(d => d) .Where(d => !string.IsNullOrEmpty(d.Text)) .ToList(); diff --git a/XmlSchemaClassGenerator/TypeModel.cs b/XmlSchemaClassGenerator/TypeModel.cs index 7702d82d..933302dc 100644 --- a/XmlSchemaClassGenerator/TypeModel.cs +++ b/XmlSchemaClassGenerator/TypeModel.cs @@ -10,6 +10,7 @@ using System.Xml; using System.Xml.Schema; using System.Xml.Serialization; +using static System.Net.Mime.MediaTypeNames; namespace XmlSchemaClassGenerator { @@ -1383,7 +1384,7 @@ protected CodeTypeReference NullableTypeRef(CodeTypeReference typeReference) } public static bool DisableComments { get; set; } - protected IEnumerable GetComments(IList docs) + protected IEnumerable GetComments(IReadOnlyList docs) { if (DisableComments || docs.Count == 0) yield break; @@ -1391,8 +1392,15 @@ protected IEnumerable GetComments(IList", true); foreach (var doc in docs - .Where(d => string.IsNullOrEmpty(d.Language) || Configuration.CommentLanguages.Exists(l => d.Language.StartsWith(l, StringComparison.OrdinalIgnoreCase))) - .OrderBy(d => d.Language)) + .Where + ( + d => !string.IsNullOrWhiteSpace(d.Text) + && (string.IsNullOrEmpty(d.Language) + || Configuration.CommentLanguages.Count is 0 + || Configuration.CommentLanguages.Contains(d.Language) + || Configuration.CommentLanguages.Any(l => d.Language.StartsWith(l, StringComparison.OrdinalIgnoreCase))) + ) + .OrderBy(d => d.Language)) { var text = doc.Text; var comment = $"{CodeUtilities.NormalizeNewlines(text).Trim()}"; @@ -1402,24 +1410,37 @@ protected IEnumerable GetComments(IList", true); } - protected void AddDescription(CodeAttributeDeclarationCollection attributes, IEnumerable docs) + protected void AddDescription(CodeAttributeDeclarationCollection attributes, IReadOnlyList docs) { - if (!Configuration.GenerateDescriptionAttribute || DisableComments || !docs.Any()) return; + if (!Configuration.GenerateDescriptionAttribute || DisableComments || docs.Count is 0) return; - var doc = GetSingleDoc(docs.Where(d => string.IsNullOrEmpty(d.Language) || Configuration.CommentLanguages.Exists(l => d.Language.StartsWith(l, StringComparison.OrdinalIgnoreCase)))); + var docText = GetSingleDoc(docs); - if (doc != null) + if (string.IsNullOrWhiteSpace(docText) is false) { - var descriptionAttribute = AttributeDecl(new CodeAttributeArgument(new CodePrimitiveExpression(Regex.Replace(doc.Text, @"\s+", " ").Trim()))); + var descriptionAttribute = AttributeDecl(new CodeAttributeArgument(new CodePrimitiveExpression(Regex.Replace(docText, @"\s+", " ").Trim()))); attributes.Add(descriptionAttribute); } } - private static DocumentationModel GetSingleDoc(IEnumerable docs) - { - return docs.Count() == 1 ? docs.Single() - : docs.FirstOrDefault(d => string.IsNullOrEmpty(d.Language) || d.Language.StartsWith(English, StringComparison.OrdinalIgnoreCase)) - ?? docs.FirstOrDefault(); - } + private string GetSingleDoc(IReadOnlyList docs) + => string.Join + ( + " ", + docs.Where + ( + d => !string.IsNullOrWhiteSpace(d.Text) + && (string.IsNullOrEmpty(d.Language) + || Configuration.CommentLanguages.Count is 0 + || Configuration.CommentLanguages.Contains(d.Language) + || Configuration.CommentLanguages.Any(l => d.Language.StartsWith(l, StringComparison.OrdinalIgnoreCase))) + ) + .Where + ( + d => string.IsNullOrEmpty(d.Language) + || d.Language.StartsWith(English, StringComparison.OrdinalIgnoreCase) + ) + .Select(x => x.Text) + ); } } From 68f3ebdcadd89f6ef045d7b8613ad222a7c308be Mon Sep 17 00:00:00 2001 From: kronic Date: Fri, 27 Oct 2023 15:43:48 +0300 Subject: [PATCH 2/6] - --- XmlSchemaClassGenerator/TypeModel.cs | 51 ++++++++++++++-------------- 1 file changed, 26 insertions(+), 25 deletions(-) diff --git a/XmlSchemaClassGenerator/TypeModel.cs b/XmlSchemaClassGenerator/TypeModel.cs index 933302dc..04b9a586 100644 --- a/XmlSchemaClassGenerator/TypeModel.cs +++ b/XmlSchemaClassGenerator/TypeModel.cs @@ -1391,20 +1391,21 @@ protected IEnumerable GetComments(IReadOnlyList", true); - foreach (var doc in docs - .Where + foreach (var doc in docs.Where ( d => !string.IsNullOrWhiteSpace(d.Text) && (string.IsNullOrEmpty(d.Language) || Configuration.CommentLanguages.Count is 0 || Configuration.CommentLanguages.Contains(d.Language) - || Configuration.CommentLanguages.Any(l => d.Language.StartsWith(l, StringComparison.OrdinalIgnoreCase))) + || Configuration.CommentLanguages + .Any(l => d.Language.StartsWith(l, StringComparison.OrdinalIgnoreCase))) ) .OrderBy(d => d.Language)) { - var text = doc.Text; - var comment = $"{CodeUtilities.NormalizeNewlines(text).Trim()}"; - yield return new CodeCommentStatement(comment, true); + var text = doc.Text; + var comment = $"{CodeUtilities.NormalizeNewlines(text).Trim()}"; + + yield return new(comment, true); } yield return new CodeCommentStatement("", true); @@ -1423,24 +1424,24 @@ protected void AddDescription(CodeAttributeDeclarationCollection attributes, IRe } } - private string GetSingleDoc(IReadOnlyList docs) - => string.Join - ( - " ", - docs.Where - ( - d => !string.IsNullOrWhiteSpace(d.Text) - && (string.IsNullOrEmpty(d.Language) - || Configuration.CommentLanguages.Count is 0 - || Configuration.CommentLanguages.Contains(d.Language) - || Configuration.CommentLanguages.Any(l => d.Language.StartsWith(l, StringComparison.OrdinalIgnoreCase))) - ) - .Where - ( - d => string.IsNullOrEmpty(d.Language) - || d.Language.StartsWith(English, StringComparison.OrdinalIgnoreCase) - ) - .Select(x => x.Text) - ); + private string GetSingleDoc(IReadOnlyList docs) => string.Join + ( + " ", + docs.Where + ( + d => !string.IsNullOrWhiteSpace(d.Text) + && (string.IsNullOrEmpty(d.Language) + || Configuration.CommentLanguages.Count is 0 + || Configuration.CommentLanguages.Contains(d.Language) + || Configuration.CommentLanguages + .Any(l => d.Language.StartsWith(l, StringComparison.OrdinalIgnoreCase))) + ) + .Where + ( + d => string.IsNullOrEmpty(d.Language) + || d.Language.StartsWith(English, StringComparison.OrdinalIgnoreCase) + ) + .Select(x => x.Text) + ); } } From f48f65f93bad8ca4f06e3da98d5f7affe9c77a01 Mon Sep 17 00:00:00 2001 From: kronic Date: Fri, 27 Oct 2023 15:52:19 +0300 Subject: [PATCH 3/6] - --- .../DocumentationTests.cs | 45 +++++++++---------- 1 file changed, 22 insertions(+), 23 deletions(-) diff --git a/XmlSchemaClassGenerator.Tests/DocumentationTests.cs b/XmlSchemaClassGenerator.Tests/DocumentationTests.cs index 9dab2b05..199f9299 100644 --- a/XmlSchemaClassGenerator.Tests/DocumentationTests.cs +++ b/XmlSchemaClassGenerator.Tests/DocumentationTests.cs @@ -74,7 +74,6 @@ public void TestSummaryDoc() - """; var code = ConvertXml(xsd, new() {NamespacePrefix = "Test"}) @@ -134,30 +133,30 @@ public void TestDescriptionAttributeValue() - - Заголовок конверта. - Информация приложения - - - - - Тип программного обеспечения - - - - - Версия программного обеспечения - - - - - Тип сообщения - - - + + Заголовок конверта. + Информация приложения + + + + + Тип программного обеспечения + + + + + Версия программного + обеспечения + + + + + Тип сообщения + + + - """; var code = ConvertXml(xsd, new() { NamespacePrefix = "Test", GenerateDescriptionAttribute = true }) From 50a14d04ad175ca4a01e3c9fbde1a109cb74479a Mon Sep 17 00:00:00 2001 From: kronic Date: Mon, 30 Oct 2023 22:19:55 +0300 Subject: [PATCH 4/6] - --- XmlSchemaClassGenerator.Tests/DocumentationTests.cs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/XmlSchemaClassGenerator.Tests/DocumentationTests.cs b/XmlSchemaClassGenerator.Tests/DocumentationTests.cs index 199f9299..54eba92f 100644 --- a/XmlSchemaClassGenerator.Tests/DocumentationTests.cs +++ b/XmlSchemaClassGenerator.Tests/DocumentationTests.cs @@ -5,11 +5,16 @@ using System.Xml.Schema; using Xunit; +using Xunit.Abstractions; namespace XmlSchemaClassGenerator.Tests; public sealed class DocumentationTests { + private readonly ITestOutputHelper _testOutputHelper; + + public DocumentationTests(ITestOutputHelper testOutputHelper) => _testOutputHelper = testOutputHelper; + private static IEnumerable ConvertXml(string xsd, Generator generatorPrototype) { var writer = new MemoryOutputWriter(); @@ -78,7 +83,7 @@ public void TestSummaryDoc() var code = ConvertXml(xsd, new() {NamespacePrefix = "Test"}) .Single(); - + _testOutputHelper.WriteLine(code); Assert.Contains ( """ From a62fba616873502fb7b8a54b9cc5b86824633503 Mon Sep 17 00:00:00 2001 From: kronic Date: Mon, 30 Oct 2023 22:45:14 +0300 Subject: [PATCH 5/6] - --- .../DocumentationTests.cs | 48 ++++++++++--------- 1 file changed, 25 insertions(+), 23 deletions(-) diff --git a/XmlSchemaClassGenerator.Tests/DocumentationTests.cs b/XmlSchemaClassGenerator.Tests/DocumentationTests.cs index 54eba92f..47f9ace6 100644 --- a/XmlSchemaClassGenerator.Tests/DocumentationTests.cs +++ b/XmlSchemaClassGenerator.Tests/DocumentationTests.cs @@ -5,16 +5,11 @@ using System.Xml.Schema; using Xunit; -using Xunit.Abstractions; namespace XmlSchemaClassGenerator.Tests; public sealed class DocumentationTests { - private readonly ITestOutputHelper _testOutputHelper; - - public DocumentationTests(ITestOutputHelper testOutputHelper) => _testOutputHelper = testOutputHelper; - private static IEnumerable ConvertXml(string xsd, Generator generatorPrototype) { var writer = new MemoryOutputWriter(); @@ -81,16 +76,21 @@ public void TestSummaryDoc() """; - var code = ConvertXml(xsd, new() {NamespacePrefix = "Test"}) - .Single(); - _testOutputHelper.WriteLine(code); + var code = string.Join + ( + "\r\n", + ConvertXml(xsd, new() {NamespacePrefix = "Test"}) + .Single() + .Split(new[] {"\r\n", "\r", "\n"}, StringSplitOptions.TrimEntries) + ); + Assert.Contains ( """ - /// - /// Заголовок конверта. - /// Информация приложения - /// + /// + /// Заголовок конверта. + /// Информация приложения + /// """, code, StringComparison.Ordinal @@ -99,20 +99,21 @@ public void TestSummaryDoc() Assert.Contains ( """ - /// - /// Тип программного обеспечения - /// + /// + /// Тип программного обеспечения + /// """, code, StringComparison.Ordinal ); + Assert.Contains ( """ - /// - /// Версия программного - /// обеспечения - /// + /// + /// Версия программного + /// обеспечения + /// """, code, StringComparison.Ordinal @@ -121,9 +122,9 @@ public void TestSummaryDoc() Assert.Contains ( """ - /// - /// Тип сообщения - /// + /// + /// Тип сообщения + /// """, code, StringComparison.Ordinal @@ -164,7 +165,7 @@ public void TestDescriptionAttributeValue() """; - var code = ConvertXml(xsd, new() { NamespacePrefix = "Test", GenerateDescriptionAttribute = true }) + var code = ConvertXml(xsd, new() {NamespacePrefix = "Test", GenerateDescriptionAttribute = true}) .Single(); Assert.Contains @@ -180,6 +181,7 @@ public void TestDescriptionAttributeValue() code, StringComparison.Ordinal ); + Assert.Contains ( """[System.ComponentModel.DescriptionAttribute("Версия программного обеспечения")]""", From decb2d92e014305c06063a202feb7a8d9f0eae73 Mon Sep 17 00:00:00 2001 From: kronic Date: Mon, 30 Oct 2023 22:58:31 +0300 Subject: [PATCH 6/6] - --- .../DocumentationTests.cs | 29 +++++-------------- 1 file changed, 7 insertions(+), 22 deletions(-) diff --git a/XmlSchemaClassGenerator.Tests/DocumentationTests.cs b/XmlSchemaClassGenerator.Tests/DocumentationTests.cs index 47f9ace6..58269075 100644 --- a/XmlSchemaClassGenerator.Tests/DocumentationTests.cs +++ b/XmlSchemaClassGenerator.Tests/DocumentationTests.cs @@ -2,6 +2,7 @@ using System.Collections.Generic; using System.IO; using System.Linq; +using System.Text; using System.Xml.Schema; using Xunit; @@ -10,6 +11,8 @@ namespace XmlSchemaClassGenerator.Tests; public sealed class DocumentationTests { + static DocumentationTests() => Encoding.RegisterProvider(CodePagesEncodingProvider.Instance); + private static IEnumerable ConvertXml(string xsd, Generator generatorPrototype) { var writer = new MemoryOutputWriter(); @@ -86,46 +89,28 @@ public void TestSummaryDoc() Assert.Contains ( - """ - /// - /// Заголовок конверта. - /// Информация приложения - /// - """, + "/// \r\n/// Заголовок конверта.\r\n/// Информация приложения\r\n/// ", code, StringComparison.Ordinal ); Assert.Contains ( - """ - /// - /// Тип программного обеспечения - /// - """, + "/// \r\n/// Тип программного обеспечения\r\n/// ", code, StringComparison.Ordinal ); Assert.Contains ( - """ - /// - /// Версия программного - /// обеспечения - /// - """, + "/// \r\n/// Версия программного\r\n/// обеспечения\r\n/// ", code, StringComparison.Ordinal ); Assert.Contains ( - """ - /// - /// Тип сообщения - /// - """, + "/// \r\n/// Тип сообщения\r\n/// ", code, StringComparison.Ordinal );