From e084c3ffd6da347bb0cf1e4bdbf28b7dc4d54a3d Mon Sep 17 00:00:00 2001 From: Tom Monck Date: Sun, 23 Jan 2022 11:40:56 -0500 Subject: [PATCH 01/12] Exclude private members and methods if told to in configuration --- .../Configuration/DocumentationOptions.cs | 5 +++++ .../Strategies/DefaultDocumentationStrategy.cs | 13 +++++++++++++ .../Strategies/MethodDocumentationStrategy.cs | 14 ++++++++++++++ 3 files changed, 32 insertions(+) diff --git a/src/DotnetDocument/Configuration/DocumentationOptions.cs b/src/DotnetDocument/Configuration/DocumentationOptions.cs index 67a3f02..4e281e0 100644 --- a/src/DotnetDocument/Configuration/DocumentationOptions.cs +++ b/src/DotnetDocument/Configuration/DocumentationOptions.cs @@ -18,6 +18,11 @@ public abstract class MemberDocumentationOptionsBase /// public bool Required { get; init; } = true; + /// + /// Gets or inits the value of the exclude private + /// + public bool ExcludePrivate { get; init; } = false; + /// /// Gets the syntax kind /// diff --git a/src/DotnetDocument/Strategies/DefaultDocumentationStrategy.cs b/src/DotnetDocument/Strategies/DefaultDocumentationStrategy.cs index 0099176..c0f07de 100644 --- a/src/DotnetDocument/Strategies/DefaultDocumentationStrategy.cs +++ b/src/DotnetDocument/Strategies/DefaultDocumentationStrategy.cs @@ -1,4 +1,5 @@ using System.Collections.Generic; +using System.Linq; using DotnetDocument.Configuration; using DotnetDocument.Format; using DotnetDocument.Strategies.Abstractions; @@ -70,6 +71,18 @@ public override MemberDeclarationSyntax Apply(MemberDeclarationSyntax node) // Retrieve member name var name = SyntaxUtils.FindMemberIdentifier(node); + // Check if we want to exclude private member + if (_options.ExcludePrivate) + { + _logger.LogInformation($"Configured to not generate documentation for private members. Skipping {name}"); + + if (node.Modifiers.ToFullString().Contains("private")) + { + // Just return the node as is to prevent us from adding docs. + return node; + } + } + // Declare the summary by using the template from configuration var summary = new List { diff --git a/src/DotnetDocument/Strategies/MethodDocumentationStrategy.cs b/src/DotnetDocument/Strategies/MethodDocumentationStrategy.cs index d57b7b7..378b193 100644 --- a/src/DotnetDocument/Strategies/MethodDocumentationStrategy.cs +++ b/src/DotnetDocument/Strategies/MethodDocumentationStrategy.cs @@ -59,6 +59,7 @@ public override IEnumerable GetSupportedKinds() => new[] /// The method declaration syntax public override MethodDeclarationSyntax Apply(MethodDeclarationSyntax node) { + // Get the doc builder for this node var builder = GetDocumentationBuilder() .For(node); @@ -66,6 +67,19 @@ public override MethodDeclarationSyntax Apply(MethodDeclarationSyntax node) // Extract method name var methodName = node.Identifier.Text; + // Check if we want to exclude private methods + if (_options.ExcludePrivate) + { + _logger.LogInformation( + $"Configured to not generate documentation for private methods. Skipping {methodName}"); + + if (node.Modifiers.Any(m => m.Text.Contains("private"))) + { + // Just return the node as is to prevent us from adding docs. + return node; + } + } + // Extract return type var returnType = node.ReturnType.ToString(); From c830203ca927b7c52dde60725d25d99fd1a62ee0 Mon Sep 17 00:00:00 2001 From: Tom Monck Date: Sun, 23 Jan 2022 12:07:45 -0500 Subject: [PATCH 02/12] Exclude private properties. --- .../Strategies/PropertyDocumentationStrategy.cs | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/DotnetDocument/Strategies/PropertyDocumentationStrategy.cs b/src/DotnetDocument/Strategies/PropertyDocumentationStrategy.cs index 7f7dd44..d10582d 100644 --- a/src/DotnetDocument/Strategies/PropertyDocumentationStrategy.cs +++ b/src/DotnetDocument/Strategies/PropertyDocumentationStrategy.cs @@ -61,6 +61,18 @@ public override PropertyDeclarationSyntax Apply(PropertyDeclarationSyntax node) // Retrieve constructor name var propertyName = node.Identifier.Text; + // Check if we want to exclude private property + if (_options.ExcludePrivate) + { + _logger.LogInformation($"Configured to not generate documentation for private properties. Skipping {propertyName}"); + + if (node.Modifiers.ToFullString().Contains("private")) + { + // Just return the node as is to prevent us from adding docs. + return node; + } + } + // Humanize the constructor name var humanizedPropertyName = propertyName.Humanize().ToLower(); From 6da72f23429ebc4ca6515ef7de190b6a050068ed Mon Sep 17 00:00:00 2001 From: Tom Monck Date: Sun, 23 Jan 2022 12:26:56 -0500 Subject: [PATCH 03/12] Add documentation in readme on how to configure. --- README.md | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/README.md b/README.md index 8b789dd..eb3bc38 100644 --- a/README.md +++ b/README.md @@ -87,6 +87,23 @@ To double check which configuration is being used, invoke dotnet document config ``` +If you wish to exclude private members, properties, or methods modify your configuration file like: + +```yaml +... +method: + ... + exclude_private: true +property: + ... + exclude_private: true +default_member: + ... + exclude_private: true + +``` + +` > 👉 Folder based configuration discovery is not yet supported ## Acknowledgments From 70a4a7ff8391d08507515cbc6c2cb42c154540da Mon Sep 17 00:00:00 2001 From: Tom Monck Date: Sun, 23 Jan 2022 12:29:35 -0500 Subject: [PATCH 04/12] Clean up extra line --- src/DotnetDocument/Strategies/MethodDocumentationStrategy.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/DotnetDocument/Strategies/MethodDocumentationStrategy.cs b/src/DotnetDocument/Strategies/MethodDocumentationStrategy.cs index 378b193..fe8e418 100644 --- a/src/DotnetDocument/Strategies/MethodDocumentationStrategy.cs +++ b/src/DotnetDocument/Strategies/MethodDocumentationStrategy.cs @@ -59,7 +59,6 @@ public override IEnumerable GetSupportedKinds() => new[] /// The method declaration syntax public override MethodDeclarationSyntax Apply(MethodDeclarationSyntax node) { - // Get the doc builder for this node var builder = GetDocumentationBuilder() .For(node); From a16f4738b79c68e7b1911941be8b438f7714ed61 Mon Sep 17 00:00:00 2001 From: Tom Monck Date: Sun, 23 Jan 2022 12:56:49 -0500 Subject: [PATCH 05/12] Add Exclude Private check to Class Documentation Strategy. --- .../Strategies/ClassDocumentationStrategy.cs | 12 ++++++++++++ .../Strategies/PropertyDocumentationStrategy.cs | 2 +- 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/src/DotnetDocument/Strategies/ClassDocumentationStrategy.cs b/src/DotnetDocument/Strategies/ClassDocumentationStrategy.cs index 2a37d1a..161b43b 100644 --- a/src/DotnetDocument/Strategies/ClassDocumentationStrategy.cs +++ b/src/DotnetDocument/Strategies/ClassDocumentationStrategy.cs @@ -61,6 +61,18 @@ public override ClassDeclarationSyntax Apply(ClassDeclarationSyntax node) // Retrieve class name var className = node.Identifier.Text; + // Check if we want to exclude private classess + if (_options.ExcludePrivate) + { + _logger.LogInformation($"Configured to not generate documentation for private classes. Skipping {className}"); + + if (node.Modifiers.Any((m) => m.Text.Contains("private"))) + { + // Just return the node as is to prevent us from adding docs. + return node; + } + } + // Declare the summary by using the template from configuration var summary = _formatter.FormatName(_options.Summary.Template, (TemplateKeys.Name, className)); diff --git a/src/DotnetDocument/Strategies/PropertyDocumentationStrategy.cs b/src/DotnetDocument/Strategies/PropertyDocumentationStrategy.cs index d10582d..bed4f00 100644 --- a/src/DotnetDocument/Strategies/PropertyDocumentationStrategy.cs +++ b/src/DotnetDocument/Strategies/PropertyDocumentationStrategy.cs @@ -66,7 +66,7 @@ public override PropertyDeclarationSyntax Apply(PropertyDeclarationSyntax node) { _logger.LogInformation($"Configured to not generate documentation for private properties. Skipping {propertyName}"); - if (node.Modifiers.ToFullString().Contains("private")) + if (node.Modifiers.Any((m) => m.Text.Contains("private"))) { // Just return the node as is to prevent us from adding docs. return node; From 8807ca319e795fdb9451aabc5289f66defc2749e Mon Sep 17 00:00:00 2001 From: Tom Monck Date: Sun, 23 Jan 2022 13:23:10 -0500 Subject: [PATCH 06/12] Add class configuration to README --- README.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index eb3bc38..96f47fc 100644 --- a/README.md +++ b/README.md @@ -90,7 +90,9 @@ dotnet document config If you wish to exclude private members, properties, or methods modify your configuration file like: ```yaml -... +class: + ... + exclude_private: true method: ... exclude_private: true From 6813be9237f954ebbde85ef7c784d5f5d19da053 Mon Sep 17 00:00:00 2001 From: Tom Monck Date: Sun, 23 Jan 2022 13:27:12 -0500 Subject: [PATCH 07/12] Remove extra character --- README.md | 1 - 1 file changed, 1 deletion(-) diff --git a/README.md b/README.md index 96f47fc..9f11c9d 100644 --- a/README.md +++ b/README.md @@ -105,7 +105,6 @@ default_member: ``` -` > 👉 Folder based configuration discovery is not yet supported ## Acknowledgments From 932e6b73340ad64feb2b8c787be1abc3be55157a Mon Sep 17 00:00:00 2001 From: Tom Monck Date: Sun, 23 Jan 2022 14:31:33 -0500 Subject: [PATCH 08/12] Fix to log only if we are actually skipping the node --- .../Strategies/ClassDocumentationStrategy.cs | 12 +++++------- .../Strategies/DefaultDocumentationStrategy.cs | 12 +++++------- .../Strategies/MethodDocumentationStrategy.cs | 9 +++------ .../Strategies/PropertyDocumentationStrategy.cs | 12 +++++------- 4 files changed, 18 insertions(+), 27 deletions(-) diff --git a/src/DotnetDocument/Strategies/ClassDocumentationStrategy.cs b/src/DotnetDocument/Strategies/ClassDocumentationStrategy.cs index 161b43b..54f24d4 100644 --- a/src/DotnetDocument/Strategies/ClassDocumentationStrategy.cs +++ b/src/DotnetDocument/Strategies/ClassDocumentationStrategy.cs @@ -62,15 +62,13 @@ public override ClassDeclarationSyntax Apply(ClassDeclarationSyntax node) var className = node.Identifier.Text; // Check if we want to exclude private classess - if (_options.ExcludePrivate) + if (_options.ExcludePrivate && node.Modifiers.Any((m) => m.Text.Contains("private"))) { - _logger.LogInformation($"Configured to not generate documentation for private classes. Skipping {className}"); + _logger.LogInformation( + $"Configured to not generate documentation for private classes. Skipping {className}"); - if (node.Modifiers.Any((m) => m.Text.Contains("private"))) - { - // Just return the node as is to prevent us from adding docs. - return node; - } + // Just return the node as is to prevent us from adding docs. + return node; } // Declare the summary by using the template from configuration diff --git a/src/DotnetDocument/Strategies/DefaultDocumentationStrategy.cs b/src/DotnetDocument/Strategies/DefaultDocumentationStrategy.cs index c0f07de..0b9e23b 100644 --- a/src/DotnetDocument/Strategies/DefaultDocumentationStrategy.cs +++ b/src/DotnetDocument/Strategies/DefaultDocumentationStrategy.cs @@ -72,15 +72,13 @@ public override MemberDeclarationSyntax Apply(MemberDeclarationSyntax node) var name = SyntaxUtils.FindMemberIdentifier(node); // Check if we want to exclude private member - if (_options.ExcludePrivate) + if (_options.ExcludePrivate && node.Modifiers.ToFullString().Contains("private")) { - _logger.LogInformation($"Configured to not generate documentation for private members. Skipping {name}"); + _logger.LogInformation( + $"Configured to not generate documentation for private members. Skipping {name}"); - if (node.Modifiers.ToFullString().Contains("private")) - { - // Just return the node as is to prevent us from adding docs. - return node; - } + // Just return the node as is to prevent us from adding docs. + return node; } // Declare the summary by using the template from configuration diff --git a/src/DotnetDocument/Strategies/MethodDocumentationStrategy.cs b/src/DotnetDocument/Strategies/MethodDocumentationStrategy.cs index fe8e418..561ebb5 100644 --- a/src/DotnetDocument/Strategies/MethodDocumentationStrategy.cs +++ b/src/DotnetDocument/Strategies/MethodDocumentationStrategy.cs @@ -67,16 +67,13 @@ public override MethodDeclarationSyntax Apply(MethodDeclarationSyntax node) var methodName = node.Identifier.Text; // Check if we want to exclude private methods - if (_options.ExcludePrivate) + if (_options.ExcludePrivate && node.Modifiers.Any(m => m.Text.Contains("private"))) { _logger.LogInformation( $"Configured to not generate documentation for private methods. Skipping {methodName}"); - if (node.Modifiers.Any(m => m.Text.Contains("private"))) - { - // Just return the node as is to prevent us from adding docs. - return node; - } + // Just return the node as is to prevent us from adding docs. + return node; } // Extract return type diff --git a/src/DotnetDocument/Strategies/PropertyDocumentationStrategy.cs b/src/DotnetDocument/Strategies/PropertyDocumentationStrategy.cs index bed4f00..f2862e5 100644 --- a/src/DotnetDocument/Strategies/PropertyDocumentationStrategy.cs +++ b/src/DotnetDocument/Strategies/PropertyDocumentationStrategy.cs @@ -62,15 +62,13 @@ public override PropertyDeclarationSyntax Apply(PropertyDeclarationSyntax node) var propertyName = node.Identifier.Text; // Check if we want to exclude private property - if (_options.ExcludePrivate) + if (_options.ExcludePrivate && node.Modifiers.Any((m) => m.Text.Contains("private"))) { - _logger.LogInformation($"Configured to not generate documentation for private properties. Skipping {propertyName}"); + _logger.LogInformation( + $"Configured to not generate documentation for private properties. Skipping {propertyName}"); - if (node.Modifiers.Any((m) => m.Text.Contains("private"))) - { - // Just return the node as is to prevent us from adding docs. - return node; - } + // Just return the node as is to prevent us from adding docs. + return node; } // Humanize the constructor name From 1f378813d42403a40761828eba1a0ce4e7a33606 Mon Sep 17 00:00:00 2001 From: Tom Monck Date: Sun, 6 Feb 2022 19:29:35 -0500 Subject: [PATCH 09/12] Refactor things to have a bit more flexibility. --- .../Handlers/ApplyDocumentHandler.cs | 65 +++++++++++++++---- .../Configuration/DocumentationOptions.cs | 2 +- .../MemberDeclarationSyntaxExtensions.cs | 26 ++++++++ .../Abstractions/DocumentationStrategyBase.cs | 6 ++ .../Abstractions/IDocumentationStrategy.cs | 1 + .../Strategies/ClassDocumentationStrategy.cs | 12 +--- .../ConstructorDocumentationStrategy.cs | 2 + .../DefaultDocumentationStrategy.cs | 12 +--- .../Strategies/EnumDocumentationStrategy.cs | 2 + .../EnumMemberDocumentationStrategy.cs | 8 +++ .../InterfaceDocumentationStrategy.cs | 3 + .../Strategies/MethodDocumentationStrategy.cs | 13 +--- .../PropertyDocumentationStrategy.cs | 18 +++-- .../Syntax/DocumentationSyntaxWalker.cs | 10 +-- 14 files changed, 121 insertions(+), 59 deletions(-) create mode 100644 src/DotnetDocument/Extensions/MemberDeclarationSyntaxExtensions.cs diff --git a/src/DotnetDocument.Tools/Handlers/ApplyDocumentHandler.cs b/src/DotnetDocument.Tools/Handlers/ApplyDocumentHandler.cs index a4fd5b3..085870c 100644 --- a/src/DotnetDocument.Tools/Handlers/ApplyDocumentHandler.cs +++ b/src/DotnetDocument.Tools/Handlers/ApplyDocumentHandler.cs @@ -92,7 +92,39 @@ public Result Apply(string? path, bool isDryRun) : Result.Success; } + foreach (var member in undocumentedMembers) + { + + var fileContent = File.ReadAllText(member.FilePath); + + // Declare a new CSharp syntax tree + var tree = CSharpSyntaxTree.ParseText(fileContent, + new CSharpParseOptions(documentationMode: DocumentationMode.Parse)); + + // Get the compilation unit root + var root = tree.GetCompilationUnitRoot(); + + _walker.Clean(); + _walker.Visit(root); + + // Replace the + var changedSyntaxTree = root.ReplaceNodes(_walker.AllNodes, (node, syntaxNode) => + { + var docStrategy = _serviceResolver.Resolve(syntaxNode.Kind().ToString()); + + if (docStrategy != null) + { + return docStrategy.ShouldDocument(syntaxNode) ? docStrategy.Apply(syntaxNode) : syntaxNode; + } + + return syntaxNode; + }); + _logger.LogTrace(" Writing changes of {File} to disk", member.FilePath); + + File.WriteAllText(member.FilePath, changedSyntaxTree.ToFullString()); + } // Check and apply changes + /* foreach (var file in files) { // Read the file content @@ -121,6 +153,7 @@ public Result Apply(string? path, bool isDryRun) File.WriteAllText(file, changedSyntaxTree.ToFullString()); } + */ // Return success return Result.Success; @@ -157,21 +190,25 @@ private IEnumerable GetFileDocumentationStatus(string _walker.Clean(); _walker.Visit(root); - foreach (var node in _walker.NodesWithXmlDoc) - yield return new MemberDocumentationStatus(filePath, SyntaxUtils.FindMemberIdentifier(node), - node.Kind(), true, null, node, - node.GetLocation().GetLineSpan().StartLinePosition.ToString()); - - foreach (var node in _walker.NodesWithoutXmlDoc) + foreach (var node in _walker.AllNodes) { - var nodeWithDoc = _serviceResolver - .Resolve(node.Kind().ToString()) - ? - .Apply(node); - - yield return new MemberDocumentationStatus(filePath, SyntaxUtils.FindMemberIdentifier(node), - node.Kind(), false, node, nodeWithDoc, - node.GetLocation().GetLineSpan().StartLinePosition.ToString()); + var docStrategy = _serviceResolver.Resolve(node.Kind().ToString()); + var shouldDocument = docStrategy?.ShouldDocument(node); + + if (shouldDocument.HasValue && shouldDocument.Value) + { + var nodeWithDoc = docStrategy?.Apply(node); + + yield return new MemberDocumentationStatus(filePath, SyntaxUtils.FindMemberIdentifier(node), + node.Kind(), false, node, nodeWithDoc, + node.GetLocation().GetLineSpan().StartLinePosition.ToString()); + } + else + { + yield return new MemberDocumentationStatus(filePath, SyntaxUtils.FindMemberIdentifier(node), + node.Kind(), true, null, node, + node.GetLocation().GetLineSpan().StartLinePosition.ToString()); + } } } diff --git a/src/DotnetDocument/Configuration/DocumentationOptions.cs b/src/DotnetDocument/Configuration/DocumentationOptions.cs index 4e281e0..2584519 100644 --- a/src/DotnetDocument/Configuration/DocumentationOptions.cs +++ b/src/DotnetDocument/Configuration/DocumentationOptions.cs @@ -21,7 +21,7 @@ public abstract class MemberDocumentationOptionsBase /// /// Gets or inits the value of the exclude private /// - public bool ExcludePrivate { get; init; } = false; + public IEnumerable AccessModifiers { get; init; } = new List(); /// /// Gets the syntax kind diff --git a/src/DotnetDocument/Extensions/MemberDeclarationSyntaxExtensions.cs b/src/DotnetDocument/Extensions/MemberDeclarationSyntaxExtensions.cs new file mode 100644 index 0000000..7d5e928 --- /dev/null +++ b/src/DotnetDocument/Extensions/MemberDeclarationSyntaxExtensions.cs @@ -0,0 +1,26 @@ +using System.Linq; +using DotnetDocument.Configuration; +using DotnetDocument.Syntax; +using Microsoft.CodeAnalysis.CSharp.Syntax; + +namespace DotnetDocument.Extensions +{ + public static class MemberDeclarationSyntaxExtensions + { + public static bool ShouldDocument(this MemberDeclarationSyntax node, MemberDocumentationOptionsBase options) + { + var shouldDocument = false; + + foreach (var modifier in options.AccessModifiers) + { + if (node.Modifiers.ToFullString().Contains(modifier) && !SyntaxUtils.IsDocumented(node)) + { + shouldDocument = true; + break; + } + } + + return shouldDocument; + } + } +} diff --git a/src/DotnetDocument/Strategies/Abstractions/DocumentationStrategyBase.cs b/src/DotnetDocument/Strategies/Abstractions/DocumentationStrategyBase.cs index be37679..02aac7c 100644 --- a/src/DotnetDocument/Strategies/Abstractions/DocumentationStrategyBase.cs +++ b/src/DotnetDocument/Strategies/Abstractions/DocumentationStrategyBase.cs @@ -3,6 +3,7 @@ using DotnetDocument.Syntax; using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.CSharp; +using Microsoft.CodeAnalysis.CSharp.Syntax; namespace DotnetDocument.Strategies.Abstractions { @@ -18,6 +19,11 @@ public abstract class DocumentationStrategyBase : IDocumentationStrategy wher /// An enumerable of syntax kind public abstract IEnumerable GetSupportedKinds(); + public bool ShouldDocument(SyntaxNode node) => + ShouldDocument(node as T ?? throw new InvalidOperationException()); + + public abstract bool ShouldDocument(T node); + /// /// Applies the node /// diff --git a/src/DotnetDocument/Strategies/Abstractions/IDocumentationStrategy.cs b/src/DotnetDocument/Strategies/Abstractions/IDocumentationStrategy.cs index 64ca384..d0ed84e 100644 --- a/src/DotnetDocument/Strategies/Abstractions/IDocumentationStrategy.cs +++ b/src/DotnetDocument/Strategies/Abstractions/IDocumentationStrategy.cs @@ -9,6 +9,7 @@ namespace DotnetDocument.Strategies.Abstractions /// public interface IDocumentationStrategy { + bool ShouldDocument(SyntaxNode node); /// /// Gets the supported kinds /// diff --git a/src/DotnetDocument/Strategies/ClassDocumentationStrategy.cs b/src/DotnetDocument/Strategies/ClassDocumentationStrategy.cs index 54f24d4..b7463ed 100644 --- a/src/DotnetDocument/Strategies/ClassDocumentationStrategy.cs +++ b/src/DotnetDocument/Strategies/ClassDocumentationStrategy.cs @@ -1,6 +1,7 @@ using System.Collections.Generic; using System.Linq; using DotnetDocument.Configuration; +using DotnetDocument.Extensions; using DotnetDocument.Format; using DotnetDocument.Strategies.Abstractions; using DotnetDocument.Syntax; @@ -32,6 +33,7 @@ public class ClassDocumentationStrategy : DocumentationStrategyBase private readonly ClassDocumentationOptions _options; + public override bool ShouldDocument(ClassDeclarationSyntax node) => node.ShouldDocument(_options); /// /// Initializes a new instance of the class /// @@ -61,16 +63,6 @@ public override ClassDeclarationSyntax Apply(ClassDeclarationSyntax node) // Retrieve class name var className = node.Identifier.Text; - // Check if we want to exclude private classess - if (_options.ExcludePrivate && node.Modifiers.Any((m) => m.Text.Contains("private"))) - { - _logger.LogInformation( - $"Configured to not generate documentation for private classes. Skipping {className}"); - - // Just return the node as is to prevent us from adding docs. - return node; - } - // Declare the summary by using the template from configuration var summary = _formatter.FormatName(_options.Summary.Template, (TemplateKeys.Name, className)); diff --git a/src/DotnetDocument/Strategies/ConstructorDocumentationStrategy.cs b/src/DotnetDocument/Strategies/ConstructorDocumentationStrategy.cs index 0c763e6..45499af 100644 --- a/src/DotnetDocument/Strategies/ConstructorDocumentationStrategy.cs +++ b/src/DotnetDocument/Strategies/ConstructorDocumentationStrategy.cs @@ -1,6 +1,7 @@ using System.Collections.Generic; using System.Linq; using DotnetDocument.Configuration; +using DotnetDocument.Extensions; using DotnetDocument.Format; using DotnetDocument.Strategies.Abstractions; using DotnetDocument.Syntax; @@ -32,6 +33,7 @@ public class ConstructorDocumentationStrategy : DocumentationStrategyBase private readonly CtorDocumentationOptions _options; + public override bool ShouldDocument(ConstructorDeclarationSyntax node) => node.ShouldDocument(_options); /// /// Initializes a new instance of the class /// diff --git a/src/DotnetDocument/Strategies/DefaultDocumentationStrategy.cs b/src/DotnetDocument/Strategies/DefaultDocumentationStrategy.cs index 0b9e23b..f0ccefa 100644 --- a/src/DotnetDocument/Strategies/DefaultDocumentationStrategy.cs +++ b/src/DotnetDocument/Strategies/DefaultDocumentationStrategy.cs @@ -1,6 +1,7 @@ using System.Collections.Generic; using System.Linq; using DotnetDocument.Configuration; +using DotnetDocument.Extensions; using DotnetDocument.Format; using DotnetDocument.Strategies.Abstractions; using DotnetDocument.Syntax; @@ -37,6 +38,7 @@ public class DefaultDocumentationStrategy : DocumentationStrategyBase private readonly DefaultMemberDocumentationOptions _options; + public override bool ShouldDocument(MemberDeclarationSyntax node) => node.ShouldDocument(_options); /// /// Initializes a new instance of the class /// @@ -71,16 +73,6 @@ public override MemberDeclarationSyntax Apply(MemberDeclarationSyntax node) // Retrieve member name var name = SyntaxUtils.FindMemberIdentifier(node); - // Check if we want to exclude private member - if (_options.ExcludePrivate && node.Modifiers.ToFullString().Contains("private")) - { - _logger.LogInformation( - $"Configured to not generate documentation for private members. Skipping {name}"); - - // Just return the node as is to prevent us from adding docs. - return node; - } - // Declare the summary by using the template from configuration var summary = new List { diff --git a/src/DotnetDocument/Strategies/EnumDocumentationStrategy.cs b/src/DotnetDocument/Strategies/EnumDocumentationStrategy.cs index 08cd3f3..905cb22 100644 --- a/src/DotnetDocument/Strategies/EnumDocumentationStrategy.cs +++ b/src/DotnetDocument/Strategies/EnumDocumentationStrategy.cs @@ -1,5 +1,6 @@ using System.Collections.Generic; using DotnetDocument.Configuration; +using DotnetDocument.Extensions; using DotnetDocument.Format; using DotnetDocument.Strategies.Abstractions; using Microsoft.CodeAnalysis.CSharp; @@ -30,6 +31,7 @@ public class EnumDocumentationStrategy : DocumentationStrategyBase private readonly EnumDocumentationOptions _options; + public override bool ShouldDocument(EnumDeclarationSyntax node) => node.ShouldDocument(_options); /// /// Initializes a new instance of the class /// diff --git a/src/DotnetDocument/Strategies/EnumMemberDocumentationStrategy.cs b/src/DotnetDocument/Strategies/EnumMemberDocumentationStrategy.cs index 1b41999..563b830 100644 --- a/src/DotnetDocument/Strategies/EnumMemberDocumentationStrategy.cs +++ b/src/DotnetDocument/Strategies/EnumMemberDocumentationStrategy.cs @@ -1,5 +1,6 @@ using System.Collections.Generic; using DotnetDocument.Configuration; +using DotnetDocument.Extensions; using DotnetDocument.Format; using DotnetDocument.Strategies.Abstractions; using Microsoft.CodeAnalysis.CSharp; @@ -30,6 +31,13 @@ public class EnumMemberDocumentationStrategy : DocumentationStrategyBase private readonly EnumMemberDocumentationOptions _options; + /// + /// + /// + /// + /// + public override bool ShouldDocument(EnumMemberDeclarationSyntax node) => node.ShouldDocument(_options); + /// /// Initializes a new instance of the class /// diff --git a/src/DotnetDocument/Strategies/InterfaceDocumentationStrategy.cs b/src/DotnetDocument/Strategies/InterfaceDocumentationStrategy.cs index 85bf8b2..95cc3f6 100644 --- a/src/DotnetDocument/Strategies/InterfaceDocumentationStrategy.cs +++ b/src/DotnetDocument/Strategies/InterfaceDocumentationStrategy.cs @@ -1,6 +1,7 @@ using System.Collections.Generic; using System.Linq; using DotnetDocument.Configuration; +using DotnetDocument.Extensions; using DotnetDocument.Format; using DotnetDocument.Strategies.Abstractions; using DotnetDocument.Syntax; @@ -32,6 +33,7 @@ public class InterfaceDocumentationStrategy : DocumentationStrategyBase private readonly InterfaceDocumentationOptions _options; + public override bool ShouldDocument(InterfaceDeclarationSyntax node) => node.ShouldDocument(_options); /// /// Initializes a new instance of the class /// @@ -51,6 +53,7 @@ public override IEnumerable GetSupportedKinds() => new[] SyntaxKind.InterfaceDeclaration }; + /// /// Applies the node /// diff --git a/src/DotnetDocument/Strategies/MethodDocumentationStrategy.cs b/src/DotnetDocument/Strategies/MethodDocumentationStrategy.cs index 561ebb5..7b3279a 100644 --- a/src/DotnetDocument/Strategies/MethodDocumentationStrategy.cs +++ b/src/DotnetDocument/Strategies/MethodDocumentationStrategy.cs @@ -1,6 +1,7 @@ using System.Collections.Generic; using System.Linq; using DotnetDocument.Configuration; +using DotnetDocument.Extensions; using DotnetDocument.Format; using DotnetDocument.Strategies.Abstractions; using DotnetDocument.Syntax; @@ -52,6 +53,8 @@ public override IEnumerable GetSupportedKinds() => new[] SyntaxKind.MethodDeclaration }; + public override bool ShouldDocument(MethodDeclarationSyntax node) => node.ShouldDocument(_options); + /// /// Applies the node /// @@ -66,16 +69,6 @@ public override MethodDeclarationSyntax Apply(MethodDeclarationSyntax node) // Extract method name var methodName = node.Identifier.Text; - // Check if we want to exclude private methods - if (_options.ExcludePrivate && node.Modifiers.Any(m => m.Text.Contains("private"))) - { - _logger.LogInformation( - $"Configured to not generate documentation for private methods. Skipping {methodName}"); - - // Just return the node as is to prevent us from adding docs. - return node; - } - // Extract return type var returnType = node.ReturnType.ToString(); diff --git a/src/DotnetDocument/Strategies/PropertyDocumentationStrategy.cs b/src/DotnetDocument/Strategies/PropertyDocumentationStrategy.cs index f2862e5..9f7833e 100644 --- a/src/DotnetDocument/Strategies/PropertyDocumentationStrategy.cs +++ b/src/DotnetDocument/Strategies/PropertyDocumentationStrategy.cs @@ -1,6 +1,7 @@ using System.Collections.Generic; using System.Linq; using DotnetDocument.Configuration; +using DotnetDocument.Extensions; using DotnetDocument.Format; using DotnetDocument.Strategies.Abstractions; using Humanizer; @@ -32,6 +33,13 @@ public class PropertyDocumentationStrategy : DocumentationStrategyBase private readonly PropertyDocumentationOptions _options; + /// + /// + /// + /// + /// + public override bool ShouldDocument(PropertyDeclarationSyntax node) => node.ShouldDocument(_options); + /// /// Initializes a new instance of the class /// @@ -61,16 +69,6 @@ public override PropertyDeclarationSyntax Apply(PropertyDeclarationSyntax node) // Retrieve constructor name var propertyName = node.Identifier.Text; - // Check if we want to exclude private property - if (_options.ExcludePrivate && node.Modifiers.Any((m) => m.Text.Contains("private"))) - { - _logger.LogInformation( - $"Configured to not generate documentation for private properties. Skipping {propertyName}"); - - // Just return the node as is to prevent us from adding docs. - return node; - } - // Humanize the constructor name var humanizedPropertyName = propertyName.Humanize().ToLower(); diff --git a/src/DotnetDocument/Syntax/DocumentationSyntaxWalker.cs b/src/DotnetDocument/Syntax/DocumentationSyntaxWalker.cs index 85aa0c3..f8dafdd 100644 --- a/src/DotnetDocument/Syntax/DocumentationSyntaxWalker.cs +++ b/src/DotnetDocument/Syntax/DocumentationSyntaxWalker.cs @@ -26,6 +26,11 @@ public class DocumentationSyntaxWalker : CSharpSyntaxWalker /// Gets the value of the nodes with xml doc /// public IList NodesWithXmlDoc { get; } = new List(); + + /// + /// Gets the value of all nodes + /// + public IList AllNodes { get; } = new List(); /// /// Gets the value of the nodes without xml doc @@ -56,10 +61,7 @@ private void VisitCore(SyntaxNode node) { if (IsDocumentable(node.Kind())) { - if (SyntaxUtils.IsDocumented(node)) - NodesWithXmlDoc.Add(node); - else - NodesWithoutXmlDoc.Add(node); + AllNodes.Add(node); } base.DefaultVisit(node); From 38559bb1ed52651dfa11ab9202accf7eb89c1d19 Mon Sep 17 00:00:00 2001 From: Tom Monck Date: Sat, 12 Feb 2022 18:59:37 -0500 Subject: [PATCH 10/12] Use strategy to determine if it should be documented --- .../Handlers/ApplyDocumentHandler.cs | 48 +++++-------------- .../Syntax/DocumentationSyntaxWalker.cs | 5 +- 2 files changed, 15 insertions(+), 38 deletions(-) diff --git a/src/DotnetDocument.Tools/Handlers/ApplyDocumentHandler.cs b/src/DotnetDocument.Tools/Handlers/ApplyDocumentHandler.cs index 085870c..bb76acc 100644 --- a/src/DotnetDocument.Tools/Handlers/ApplyDocumentHandler.cs +++ b/src/DotnetDocument.Tools/Handlers/ApplyDocumentHandler.cs @@ -92,39 +92,7 @@ public Result Apply(string? path, bool isDryRun) : Result.Success; } - foreach (var member in undocumentedMembers) - { - - var fileContent = File.ReadAllText(member.FilePath); - - // Declare a new CSharp syntax tree - var tree = CSharpSyntaxTree.ParseText(fileContent, - new CSharpParseOptions(documentationMode: DocumentationMode.Parse)); - - // Get the compilation unit root - var root = tree.GetCompilationUnitRoot(); - - _walker.Clean(); - _walker.Visit(root); - - // Replace the - var changedSyntaxTree = root.ReplaceNodes(_walker.AllNodes, (node, syntaxNode) => - { - var docStrategy = _serviceResolver.Resolve(syntaxNode.Kind().ToString()); - - if (docStrategy != null) - { - return docStrategy.ShouldDocument(syntaxNode) ? docStrategy.Apply(syntaxNode) : syntaxNode; - } - - return syntaxNode; - }); - _logger.LogTrace(" Writing changes of {File} to disk", member.FilePath); - - File.WriteAllText(member.FilePath, changedSyntaxTree.ToFullString()); - } // Check and apply changes - /* foreach (var file in files) { // Read the file content @@ -142,10 +110,17 @@ public Result Apply(string? path, bool isDryRun) // Replace the var changedSyntaxTree = root.ReplaceNodes(_walker.NodesWithoutXmlDoc, - (node, syntaxNode) => _serviceResolver - .Resolve(syntaxNode.Kind().ToString()) - ? - .Apply(syntaxNode) ?? syntaxNode); + (node, syntaxNode) => + { + var strategy = _serviceResolver.Resolve(syntaxNode.Kind().ToString()); + + if (strategy != null && strategy.ShouldDocument(syntaxNode)) + { + return strategy.Apply(syntaxNode); + } + + return syntaxNode; + }); // TODO: Don't write if no changes @@ -153,7 +128,6 @@ public Result Apply(string? path, bool isDryRun) File.WriteAllText(file, changedSyntaxTree.ToFullString()); } - */ // Return success return Result.Success; diff --git a/src/DotnetDocument/Syntax/DocumentationSyntaxWalker.cs b/src/DotnetDocument/Syntax/DocumentationSyntaxWalker.cs index f8dafdd..3b1564a 100644 --- a/src/DotnetDocument/Syntax/DocumentationSyntaxWalker.cs +++ b/src/DotnetDocument/Syntax/DocumentationSyntaxWalker.cs @@ -61,7 +61,10 @@ private void VisitCore(SyntaxNode node) { if (IsDocumentable(node.Kind())) { - AllNodes.Add(node); + if (SyntaxUtils.IsDocumented(node)) + NodesWithXmlDoc.Add(node); + else + NodesWithoutXmlDoc.Add(node); } base.DefaultVisit(node); From cd411ab74d61a4244eeeb17a5067be2bc08b95f1 Mon Sep 17 00:00:00 2001 From: Tom Monck Date: Sat, 12 Feb 2022 19:30:50 -0500 Subject: [PATCH 11/12] Make sure the accessor matches exactly --- .../Handlers/ApplyDocumentHandler.cs | 8 +++++- .../Configuration/DocumentationOptions.cs | 10 ++++++- .../MemberDeclarationSyntaxExtensions.cs | 26 ++++++++++++++++--- 3 files changed, 39 insertions(+), 5 deletions(-) diff --git a/src/DotnetDocument.Tools/Handlers/ApplyDocumentHandler.cs b/src/DotnetDocument.Tools/Handlers/ApplyDocumentHandler.cs index bb76acc..3537174 100644 --- a/src/DotnetDocument.Tools/Handlers/ApplyDocumentHandler.cs +++ b/src/DotnetDocument.Tools/Handlers/ApplyDocumentHandler.cs @@ -164,11 +164,17 @@ private IEnumerable GetFileDocumentationStatus(string _walker.Clean(); _walker.Visit(root); - foreach (var node in _walker.AllNodes) + foreach (var node in _walker.NodesWithXmlDoc) + yield return new MemberDocumentationStatus(filePath, SyntaxUtils.FindMemberIdentifier(node), + node.Kind(), true, null, node, + node.GetLocation().GetLineSpan().StartLinePosition.ToString()); + + foreach (var node in _walker.NodesWithoutXmlDoc) { var docStrategy = _serviceResolver.Resolve(node.Kind().ToString()); var shouldDocument = docStrategy?.ShouldDocument(node); + // Check if we should document the node if (shouldDocument.HasValue && shouldDocument.Value) { var nodeWithDoc = docStrategy?.Apply(node); diff --git a/src/DotnetDocument/Configuration/DocumentationOptions.cs b/src/DotnetDocument/Configuration/DocumentationOptions.cs index 2584519..4574037 100644 --- a/src/DotnetDocument/Configuration/DocumentationOptions.cs +++ b/src/DotnetDocument/Configuration/DocumentationOptions.cs @@ -21,7 +21,15 @@ public abstract class MemberDocumentationOptionsBase /// /// Gets or inits the value of the exclude private /// - public IEnumerable AccessModifiers { get; init; } = new List(); + public IEnumerable AccessModifiers { get; init; } = new List + { + "public", + "internal", + "private", + "protected", + "protected private", + "protected internal", + }; /// /// Gets the syntax kind diff --git a/src/DotnetDocument/Extensions/MemberDeclarationSyntaxExtensions.cs b/src/DotnetDocument/Extensions/MemberDeclarationSyntaxExtensions.cs index 7d5e928..44a3985 100644 --- a/src/DotnetDocument/Extensions/MemberDeclarationSyntaxExtensions.cs +++ b/src/DotnetDocument/Extensions/MemberDeclarationSyntaxExtensions.cs @@ -1,3 +1,4 @@ +using System; using System.Linq; using DotnetDocument.Configuration; using DotnetDocument.Syntax; @@ -13,10 +14,29 @@ public static bool ShouldDocument(this MemberDeclarationSyntax node, MemberDocum foreach (var modifier in options.AccessModifiers) { - if (node.Modifiers.ToFullString().Contains(modifier) && !SyntaxUtils.IsDocumented(node)) + var modifierArray = modifier.Split(" "); + + if (node != null) { - shouldDocument = true; - break; + if (modifierArray.Length > 1) + { + if (node.Modifiers.Any(m => m.Text.Equals(modifierArray[0], StringComparison.Ordinal)) && + node.Modifiers.Any(m => m.Text.Equals(modifierArray[1], StringComparison.Ordinal)) && + !SyntaxUtils.IsDocumented(node)) + { + shouldDocument = true; + + break; + } + + if (node.Modifiers.All(m => m.Text.Equals(modifier, StringComparison.Ordinal)) && + !SyntaxUtils.IsDocumented(node)) + { + shouldDocument = true; + + break; + } + } } } From c938071a2dee60b1b4907f906c1e0df08eace3e0 Mon Sep 17 00:00:00 2001 From: tom Date: Tue, 7 Jan 2025 20:59:08 -0500 Subject: [PATCH 12/12] Fix it so that single word accessors (public) work properly --- .../Extensions/MemberDeclarationSyntaxExtensions.cs | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/DotnetDocument/Extensions/MemberDeclarationSyntaxExtensions.cs b/src/DotnetDocument/Extensions/MemberDeclarationSyntaxExtensions.cs index 44a3985..5dae0c4 100644 --- a/src/DotnetDocument/Extensions/MemberDeclarationSyntaxExtensions.cs +++ b/src/DotnetDocument/Extensions/MemberDeclarationSyntaxExtensions.cs @@ -29,6 +29,9 @@ public static bool ShouldDocument(this MemberDeclarationSyntax node, MemberDocum break; } + } + else + { if (node.Modifiers.All(m => m.Text.Equals(modifier, StringComparison.Ordinal)) && !SyntaxUtils.IsDocumented(node)) { @@ -36,6 +39,14 @@ public static bool ShouldDocument(this MemberDeclarationSyntax node, MemberDocum break; } + + if (node.Modifiers.Any() && node.Modifiers[0].Text.Equals(modifier, StringComparison.Ordinal) && + !SyntaxUtils.IsDocumented(node)) + { + shouldDocument = true; + + break; + } } } }