Skip to content

Commit 913dd2b

Browse files
authored
Merge pull request #10 from d1820/full-class-support
Full class support
2 parents b7a6dbc + 31ebd47 commit 913dd2b

37 files changed

Lines changed: 1540 additions & 231 deletions
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
using System;
2+
using System.Diagnostics.CodeAnalysis;
3+
using System.Linq;
4+
using CodeDocumentor.Helper;
5+
using CodeDocumentor.Vsix2022;
6+
using FluentAssertions;
7+
using Xunit;
8+
9+
namespace CodeDocumentor.Test.Helper
10+
{
11+
[SuppressMessage("XMLDocumentation", "")]
12+
public class CommentHelperTests
13+
{
14+
public CommentHelperTests()
15+
{
16+
TestFixture.BuildOptionsPageGrid();
17+
18+
CodeDocumentorPackage.Options.ExcludeAsyncSuffix = true;
19+
}
20+
21+
//SpilitNameAndToLower
22+
[Fact]
23+
public void SpilitNameAndToLower_KeepsAllUpperCaseWordsInProperCasing()
24+
{
25+
var result = CommentHelper.SpilitNameAndToLower("ExecuteOCRActionAsync".AsSpan(), true);
26+
result.Count.Should().Be(3);
27+
result[0].All(a => char.IsLower(a)).Should().BeTrue();
28+
result[1].All(a => char.IsUpper(a)).Should().BeTrue();
29+
result[2].All(a => char.IsLower(a)).Should().BeTrue();
30+
}
31+
32+
[Fact]
33+
public void SpilitNameAndToLower_KeepsAllUpperCaseWordsInProperCasingAddsAsyncToListWhenOptionTrue()
34+
{
35+
CodeDocumentorPackage.Options.ExcludeAsyncSuffix =false;
36+
var result = CommentHelper.SpilitNameAndToLower("ExecuteOCRActionAsync".AsSpan(), true);
37+
result.Count.Should().Be(4);
38+
result[0].All(a => char.IsLower(a)).Should().BeTrue();
39+
result[1].All(a => char.IsUpper(a)).Should().BeTrue();
40+
result[2].All(a => char.IsLower(a)).Should().BeTrue();
41+
result[3].All(a => char.IsLower(a)).Should().BeTrue();
42+
}
43+
}
44+
}
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
using System;
2+
using System.Diagnostics.CodeAnalysis;
3+
using System.Linq;
4+
using CodeDocumentor.Helper;
5+
using FluentAssertions;
6+
using Xunit;
7+
8+
namespace CodeDocumentor.Test.Helper
9+
{
10+
[SuppressMessage("XMLDocumentation", "")]
11+
public class NameSplitterTests
12+
{
13+
[Fact]
14+
public void Split_ReturnsWordsSplitByUpperCaseLetter()
15+
{
16+
var result = NameSplitter.Split("ExecuteNewActionAsync".AsSpan());
17+
result.Count.Should().Be(4);
18+
}
19+
20+
[Fact]
21+
public void Split_ReturnsWordsHandlingGroupsOfUppercaseLetters()
22+
{
23+
var result = NameSplitter.Split("ExecuteOCRActionAsync".AsSpan());
24+
result.Count.Should().Be(4);
25+
result.Any(a => a.Contains("OCR")).Should().BeTrue();
26+
}
27+
28+
[Fact]
29+
public void Split_ReturnsWordsHandlingMultipleGroupsOfUppercaseLetters()
30+
{
31+
var result = NameSplitter.Split("ExecuteOCRActionFMRAsync".AsSpan());
32+
result.Count.Should().Be(5);
33+
result.Any(a => a.Contains("OCR")).Should().BeTrue();
34+
result.Any(a => a.Contains("FMR")).Should().BeTrue();
35+
}
36+
37+
//NullIntPROP
38+
39+
[Fact]
40+
public void Split_ReturnsWordsHandlingGroupsOfUppercaseLettersAtEnd()
41+
{
42+
var result = NameSplitter.Split("ExecuteOCRActionPROP".AsSpan());
43+
result.Count.Should().Be(4);
44+
result.Any(a => a.Contains("OCR")).Should().BeTrue();
45+
result.Any(a => a.Contains("PROP")).Should().BeTrue();
46+
}
47+
48+
[Fact]
49+
public void Split_ReturnsWordsHandlingGroupsOfUppercaseLettersAtBegining()
50+
{
51+
var result = NameSplitter.Split("PROPExecuteOCRAction".AsSpan());
52+
result.Count.Should().Be(4);
53+
result.Any(a => a.Contains("OCR")).Should().BeTrue();
54+
result.Any(a => a.Contains("PROP")).Should().BeTrue();
55+
}
56+
57+
[Fact]
58+
public void Split_ReturnsWordsHandlingUnderscoresAsSpaces()
59+
{
60+
var result = NameSplitter.Split("Execute_Action".AsSpan());
61+
result.Count.Should().Be(2);
62+
result.Any(a => a.Contains("Execute")).Should().BeTrue();
63+
result.Any(a => a.Contains("Action")).Should().BeTrue();
64+
}
65+
}
66+
}

CodeDocumentor.Test/Helper/ReturnCommentConstructionTests.cs

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ public void GenerateGenericTypeComment_CreatesValidStringFromIReadOnlyCollection
3636
var roc = TestFixture.BuildGenericNameSyntax("IReadOnlyCollection", list);
3737

3838
var comment = _returnCommentBuilder.BuildComment(roc, false);
39-
comment.Should().Be("A read only collection of lists of strings.");
39+
comment.Should().Be("A read only collection of list of strings.");
4040
}
4141

4242
[Fact]
@@ -71,7 +71,7 @@ public void GenerateGenericTypeComment_CreatesValidStringFromListOfList()
7171
var roc = TestFixture.BuildGenericNameSyntax("List", list);
7272

7373
var comment = _returnCommentBuilder.BuildComment(roc, false);
74-
comment.Should().Be("A list of lists of strings.");
74+
comment.Should().Be("A list of list of strings.");
7575
}
7676

7777
[Fact]
@@ -84,7 +84,7 @@ public void GenerateGenericTypeComment_CreatesValidStringFromListOfListOfList()
8484
var roc = TestFixture.BuildGenericNameSyntax("List", list2);
8585

8686
var comment = _returnCommentBuilder.BuildComment(roc, false);
87-
comment.Should().Be("A list of lists of lists of strings.");
87+
comment.Should().Be("A list of list of list of strings.");
8888
}
8989

9090

@@ -105,7 +105,7 @@ public void GenerateGenericTypeComment_CreatesValidStringFromIListOfIList()
105105
var roc = TestFixture.BuildGenericNameSyntax("IList", list);
106106

107107
var comment = _returnCommentBuilder.BuildComment(roc, false);
108-
comment.Should().Be("A list of lists of strings.");
108+
comment.Should().Be("A list of list of strings.");
109109
}
110110

111111

@@ -124,7 +124,7 @@ public void GenerateGenericTypeComment_CreatesValidStringFromListOfListOfInt()
124124
var list = TestFixture.BuildGenericNameSyntax("List", SyntaxKind.IntKeyword);
125125
var roc = TestFixture.BuildGenericNameSyntax("IList", list);
126126
var comment = _returnCommentBuilder.BuildComment(roc, false);
127-
comment.Should().Be("A list of lists of integers.");
127+
comment.Should().Be("A list of list of integers.");
128128
}
129129
#endregion
130130

@@ -145,7 +145,7 @@ public void GenerateGenericTypeComment_CreatesValidStringFromIEnumerableOfIEnume
145145
var roc = TestFixture.BuildGenericNameSyntax("IEnumerable", list);
146146

147147
var comment = _returnCommentBuilder.BuildComment(roc, false);
148-
comment.Should().Be("A list of lists of strings.");
148+
comment.Should().Be("A list of list of strings.");
149149
}
150150
#endregion
151151

@@ -218,7 +218,7 @@ public void GenerateGenericTypeComment_CreatesValidStringFromDictionaryWithListO
218218
var roc = TestFixture.BuildGenericNameSyntax("Dictionary", SyntaxKind.StringKeyword, list2);
219219

220220
var comment = _returnCommentBuilder.BuildComment(roc, false);
221-
comment.Should().Be("A dictionary with a key of type string and a value of type list of lists of strings.");
221+
comment.Should().Be("A dictionary with a key of type string and a value of type list of list of strings.");
222222
}
223223
#endregion
224224

CodeDocumentor/Analyzers/Classes/ClassAnalyzer.cs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,9 +41,13 @@ public override void Initialize(AnalysisContext context)
4141
/// Analyzes node.
4242
/// </summary>
4343
/// <param name="context"> The context. </param>
44-
private static void AnalyzeNode(SyntaxNodeAnalysisContext context)
44+
internal static void AnalyzeNode(SyntaxNodeAnalysisContext context)
4545
{
4646
ClassDeclarationSyntax node = context.Node as ClassDeclarationSyntax;
47+
if(node == null)
48+
{
49+
return;
50+
}
4751
if (PrivateMemberVerifier.IsPrivateMember(node))
4852
{
4953
return;

CodeDocumentor/Analyzers/Classes/ClassAnalyzerSettings.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ internal class ClassAnalyzerSettings
1919
/// <summary>
2020
/// The diagnostic id.
2121
/// </summary>
22-
internal const string DiagnosticId = "CD1600";
22+
internal const string DiagnosticId = Constants.DiagnosticIds.CLASS_DIAGNOSTIC_ID;
2323

2424
/// <summary>
2525
/// The message format.

CodeDocumentor/Analyzers/Classes/ClassCodeFixProvider.cs

Lines changed: 42 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
using System;
2+
using System.Collections.Generic;
23
using System.Collections.Immutable;
34
using System.Composition;
45
using System.Linq;
6+
using System.Runtime.Remoting.Contexts;
57
using System.Threading;
68
using System.Threading.Tasks;
79
using CodeDocumentor.Helper;
@@ -11,9 +13,11 @@
1113
using Microsoft.CodeAnalysis.CodeFixes;
1214
using Microsoft.CodeAnalysis.CSharp;
1315
using Microsoft.CodeAnalysis.CSharp.Syntax;
16+
using Microsoft.VisualStudio.Package;
1417

1518
namespace CodeDocumentor
1619
{
20+
1721
/// <summary>
1822
/// The class code fix provider.
1923
/// </summary>
@@ -23,7 +27,7 @@ public class ClassCodeFixProvider : CodeFixProvider
2327
/// <summary>
2428
/// The title.
2529
/// </summary>
26-
private const string title = "Add documentation header to this class";
30+
private const string title = "Code Documentor this class";
2731

2832
/// <summary>
2933
/// Gets the fixable diagnostic ids.
@@ -66,6 +70,33 @@ public override sealed async Task RegisterCodeFixesAsync(CodeFixContext context)
6670
diagnostic);
6771
}
6872

73+
74+
/// <summary>
75+
/// Builds the headers.
76+
/// </summary>
77+
/// <param name="root">The root.</param>
78+
/// <param name="nodesToReplace">The nodes to replace.</param>
79+
internal static void BuildComments(SyntaxNode root, Dictionary<CSharpSyntaxNode, CSharpSyntaxNode> nodesToReplace)
80+
{
81+
var declarations = root.DescendantNodes().Where(w => w.IsKind(SyntaxKind.ClassDeclaration)).OfType<ClassDeclarationSyntax>().ToArray();
82+
83+
foreach (var declarationSyntax in declarations)
84+
{
85+
if (CodeDocumentorPackage.Options?.IsEnabledForPublishMembersOnly == true
86+
&& PrivateMemberVerifier.IsPrivateMember(declarationSyntax))
87+
{
88+
continue;
89+
}
90+
91+
if (declarationSyntax.HasSummary())
92+
{
93+
continue;
94+
}
95+
var newDeclaration = BuildNewDeclaration(declarationSyntax);
96+
nodesToReplace.TryAdd(declarationSyntax, newDeclaration);
97+
}
98+
}
99+
69100
/// <summary>
70101
/// Adds documentation header async.
71102
/// </summary>
@@ -74,7 +105,15 @@ public override sealed async Task RegisterCodeFixesAsync(CodeFixContext context)
74105
/// <param name="declarationSyntax"> The declaration syntax. </param>
75106
/// <param name="cancellationToken"> The cancellation token. </param>
76107
/// <returns> A Document. </returns>
77-
private async Task<Document> AddDocumentationHeaderAsync(Document document, SyntaxNode root, ClassDeclarationSyntax declarationSyntax, CancellationToken cancellationToken)
108+
internal static async Task<Document> AddDocumentationHeaderAsync(Document document, SyntaxNode root, ClassDeclarationSyntax declarationSyntax, CancellationToken cancellationToken)
109+
{
110+
var newDeclaration = BuildNewDeclaration(declarationSyntax);
111+
SyntaxNode newRoot = root.ReplaceNode(declarationSyntax, newDeclaration);
112+
113+
return document.WithSyntaxRoot(newRoot);
114+
}
115+
116+
private static ClassDeclarationSyntax BuildNewDeclaration(ClassDeclarationSyntax declarationSyntax)
78117
{
79118
SyntaxList<SyntaxNode> list = SyntaxFactory.List<SyntaxNode>();
80119

@@ -96,9 +135,7 @@ private async Task<Document> AddDocumentationHeaderAsync(Document document, Synt
96135

97136
var newLeadingTrivia = DocumentationHeaderHelper.BuildLeadingTrivia(leadingTrivia, commentTrivia);
98137
ClassDeclarationSyntax newDeclaration = declarationSyntax.WithLeadingTrivia(newLeadingTrivia);
99-
SyntaxNode newRoot = root.ReplaceNode(declarationSyntax, newDeclaration);
100-
101-
return document.WithSyntaxRoot(newRoot);
138+
return newDeclaration;
102139
}
103140
}
104141
}

CodeDocumentor/Analyzers/Constructors/ConstructorAnalyzer.cs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,9 +41,13 @@ public override void Initialize(AnalysisContext context)
4141
/// Analyzes node.
4242
/// </summary>
4343
/// <param name="context"> The context. </param>
44-
private static void AnalyzeNode(SyntaxNodeAnalysisContext context)
44+
internal static void AnalyzeNode(SyntaxNodeAnalysisContext context)
4545
{
4646
ConstructorDeclarationSyntax node = context.Node as ConstructorDeclarationSyntax;
47+
if (node == null)
48+
{
49+
return;
50+
}
4751
if (PrivateMemberVerifier.IsPrivateMember(node))
4852
{
4953
return;

CodeDocumentor/Analyzers/Constructors/ConstructorAnalyzerSettings.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ internal class ConstructorAnalyzerSettings
1919
/// <summary>
2020
/// The diagnostic id.
2121
/// </summary>
22-
internal const string DiagnosticId = "CD1601";
22+
internal const string DiagnosticId = Constants.DiagnosticIds.CONSTRUCTOR_DIAGNOSTIC_ID;
2323

2424
/// <summary>
2525
/// The message format.

CodeDocumentor/Analyzers/Constructors/ConstructorCodeFixProvider.cs

Lines changed: 34 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
using System.Collections.Immutable;
1+
using System.Collections.Generic;
2+
using System.Collections.Immutable;
23
using System.Composition;
34
using System.Linq;
45
using System.Threading;
@@ -22,7 +23,7 @@ public class ConstructorCodeFixProvider : CodeFixProvider
2223
/// <summary>
2324
/// The title.
2425
/// </summary>
25-
private const string title = "Add documentation header to this constructor";
26+
private const string title = "Code Documentor this constructor";
2627

2728
/// <summary>
2829
/// Gets the fixable diagnostic ids.
@@ -64,6 +65,36 @@ public override sealed async Task RegisterCodeFixesAsync(CodeFixContext context)
6465
diagnostic);
6566
}
6667

68+
internal static void BuildComments(SyntaxNode root, Dictionary<CSharpSyntaxNode, CSharpSyntaxNode> nodesToReplace)
69+
{
70+
var declarations = root.DescendantNodes().Where(w => w.IsKind(SyntaxKind.ConstructorDeclaration)).OfType<ConstructorDeclarationSyntax>().ToArray();
71+
72+
foreach (var declarationSyntax in declarations)
73+
{
74+
if (CodeDocumentorPackage.Options?.IsEnabledForPublishMembersOnly == true && PrivateMemberVerifier.IsPrivateMember(declarationSyntax))
75+
{
76+
continue;
77+
}
78+
if (declarationSyntax.HasSummary())
79+
{
80+
continue;
81+
}
82+
var newDeclaration = BuildNewDeclaration(declarationSyntax);
83+
nodesToReplace.TryAdd(declarationSyntax, newDeclaration);
84+
}
85+
}
86+
87+
private static ConstructorDeclarationSyntax BuildNewDeclaration(ConstructorDeclarationSyntax declarationSyntax)
88+
{
89+
SyntaxTriviaList leadingTrivia = declarationSyntax.GetLeadingTrivia();
90+
DocumentationCommentTriviaSyntax commentTrivia = CreateDocumentationCommentTriviaSyntax(declarationSyntax);
91+
92+
var newLeadingTrivia = DocumentationHeaderHelper.BuildLeadingTrivia(leadingTrivia, commentTrivia);
93+
ConstructorDeclarationSyntax newDeclaration = declarationSyntax.WithLeadingTrivia(newLeadingTrivia);
94+
return newDeclaration;
95+
96+
}
97+
6798
/// <summary>
6899
/// Adds documentation header async.
69100
/// </summary>
@@ -74,12 +105,7 @@ public override sealed async Task RegisterCodeFixesAsync(CodeFixContext context)
74105
/// <returns> A Document. </returns>
75106
private async Task<Document> AddDocumentationHeaderAsync(Document document, SyntaxNode root, ConstructorDeclarationSyntax declarationSyntax, CancellationToken cancellationToken)
76107
{
77-
SyntaxTriviaList leadingTrivia = declarationSyntax.GetLeadingTrivia();
78-
DocumentationCommentTriviaSyntax commentTrivia = await Task.Run(() => CreateDocumentationCommentTriviaSyntax(declarationSyntax), cancellationToken);
79-
80-
var newLeadingTrivia = DocumentationHeaderHelper.BuildLeadingTrivia(leadingTrivia, commentTrivia);
81-
ConstructorDeclarationSyntax newDeclaration = declarationSyntax.WithLeadingTrivia(newLeadingTrivia);
82-
108+
var newDeclaration = BuildNewDeclaration(declarationSyntax);
83109
SyntaxNode newRoot = root.ReplaceNode(declarationSyntax, newDeclaration);
84110
return document.WithSyntaxRoot(newRoot);
85111
}

0 commit comments

Comments
 (0)