@@ -22,37 +22,41 @@ public async Task Execute()
22
22
var compilation = await FluentAssertionAnalyzerDocsUtils . GetFluentAssertionAnalyzerDocsCompilation ( ) ;
23
23
var compilationWithAnalyzers = compilation . WithAnalyzers ( ImmutableArray . Create ( analyzer ) ) ;
24
24
25
- var docs = new StringBuilder ( ) ;
26
- var toc = new StringBuilder ( ) ;
27
- var scenarios = new StringBuilder ( ) ;
25
+ var testAssembly = typeof ( FluentAssertionAnalyzerDocs . FluentAssertionsAnalyzerTests ) . Assembly ;
28
26
29
- docs . AppendLine ( "<!--" ) ;
30
- docs . AppendLine ( "This is a generated file, please edit src\\ FluentAssertions.Analyzers.FluentAssertionAnalyzerDocsGenerator\\ DocsGenerator.cs to change the contents" ) ;
31
- docs . AppendLine ( "-->" ) ;
32
- docs . AppendLine ( ) ;
27
+ foreach ( var tree in compilationWithAnalyzers . Compilation . SyntaxTrees . Where ( t => t . FilePath . EndsWith ( "Tests.cs" ) ) )
28
+ {
29
+ Console . WriteLine ( $ "File: { Path . GetFileName ( tree . FilePath ) } ") ;
33
30
34
- docs . AppendLine ( "# FluentAssertions Analyzer Docs" ) ;
35
- docs . AppendLine ( ) ;
31
+ var docsName = Path . GetFileNameWithoutExtension ( tree . FilePath ) . Replace ( "Tests" , ".md" ) ;
36
32
37
- scenarios . AppendLine ( "## Scenarios" ) ;
38
- scenarios . AppendLine ( ) ;
33
+ var docs = new StringBuilder ( ) ;
34
+ var toc = new StringBuilder ( ) ;
35
+ var scenarios = new StringBuilder ( ) ;
39
36
40
- var testAssembly = typeof ( FluentAssertions . Analyzers . FluentAssertionAnalyzerDocs . FluentAssertionsAnalyzerTests ) . Assembly ;
37
+ docs . AppendLine ( "<!--" ) ;
38
+ docs . AppendLine ( "This is a generated file, please edit src\\ FluentAssertions.Analyzers.FluentAssertionAnalyzerDocsGenerator\\ DocsGenerator.cs to change the contents" ) ;
39
+ docs . AppendLine ( "-->" ) ;
40
+ docs . AppendLine ( ) ;
41
41
42
- foreach ( var tree in compilationWithAnalyzers . Compilation . SyntaxTrees . Where ( t => t . FilePath . EndsWith ( "Tests.cs" ) ) )
43
- {
44
- Console . WriteLine ( $ "File: { Path . GetFileName ( tree . FilePath ) } " ) ;
42
+ var subject = Path . GetFileNameWithoutExtension ( tree . FilePath ) . Replace ( "AnalyzerTests" , string . Empty ) ;
43
+ docs . AppendLine ( $ "# { subject } Analyzer Docs" ) ;
44
+ docs . AppendLine ( ) ;
45
45
46
+ scenarios . AppendLine ( "## Scenarios" ) ;
47
+ scenarios . AppendLine ( ) ;
46
48
47
49
var root = await tree . GetRootAsync ( ) ;
48
50
var classDef = root . DescendantNodes ( ) . OfType < ClassDeclarationSyntax > ( ) . First ( ) ;
49
51
var methods = root . DescendantNodes ( ) . OfType < MethodDeclarationSyntax > ( ) ;
52
+ var methodsMap = methods . ToDictionary ( m => m . Identifier . Text ) ;
50
53
51
54
var classType = testAssembly . GetType ( $ "FluentAssertions.Analyzers.FluentAssertionAnalyzerDocs.{ classDef . Identifier . Text } ") ;
52
55
var classInstance = Activator . CreateInstance ( classType ) ;
53
56
54
57
foreach ( var method in methods . Where ( m => m . AttributeLists . Any ( list => list . Attributes . Count is 1 && list . Attributes [ 0 ] . Name . ToString ( ) is "TestMethod" ) ) )
55
58
{
59
+ // success scenario:
56
60
{
57
61
scenarios . AppendLine ( $ "### scenario: { method . Identifier } ") ;
58
62
scenarios . AppendLine ( ) ;
@@ -67,8 +71,10 @@ public async Task Execute()
67
71
68
72
toc . AppendLine ( $ "- [{ method . Identifier } ](#scenario-{ method . Identifier . Text . ToLower ( ) } ) - `{ newAssertion } `") ;
69
73
}
74
+
75
+ // FluentAssertion failures scenario:
76
+ if ( methodsMap . TryGetValue ( $ "{ method . Identifier . Text } _Failure", out var testWithFailure ) )
70
77
{
71
- var testWithFailure = methods . FirstOrDefault ( m => m . Identifier . Text == $ "{ method . Identifier . Text } _Failure") ;
72
78
var testMethodWithFailure = classType . GetMethod ( testWithFailure . Identifier . Text ) ;
73
79
74
80
var exceptionMessageLines = GetMethodExceptionMessageLines ( classInstance , testMethodWithFailure ) ;
@@ -88,8 +94,6 @@ public async Task Execute()
88
94
var arrange = bodyLines . TakeWhile ( x => ! string . IsNullOrEmpty ( x ) )
89
95
. Select ( l => l . Length > paddingToRemove ? l . Substring ( paddingToRemove ) : l ) . Aggregate ( ( a , b ) => $ "{ a } { Environment . NewLine } { b } ") ;
90
96
91
- var methodBody = $ "```cs{ Environment . NewLine } { arrange } { Environment . NewLine } ```";
92
-
93
97
scenarios . AppendLine ( $ "#### Failure messages") ;
94
98
scenarios . AppendLine ( ) ;
95
99
scenarios . AppendLine ( "```cs" ) ;
@@ -106,6 +110,43 @@ public async Task Execute()
106
110
scenarios . AppendLine ( "```" ) ;
107
111
scenarios . AppendLine ( ) ;
108
112
}
113
+
114
+ // Testing Libraries failures scenarios:
115
+ if ( methodsMap . TryGetValue ( $ "{ method . Identifier . Text } _Failure_OldAssertion", out var testWithFailureOldAssertion )
116
+ && methodsMap . TryGetValue ( $ "{ method . Identifier . Text } _Failure_NewAssertion", out var testWithFailureNewAssertion ) )
117
+ {
118
+ var testMethodWithFailureOldAssertion = classType . GetMethod ( testWithFailureOldAssertion . Identifier . Text ) ;
119
+ var testMethodWithFailureNewAssertion = classType . GetMethod ( testWithFailureNewAssertion . Identifier . Text ) ;
120
+
121
+ var exceptionMessageLinesOldAssertion = GetMethodExceptionMessage ( classInstance , testMethodWithFailureOldAssertion ) ;
122
+ var exceptionMessageLinesNewAssertion = GetMethodExceptionMessage ( classInstance , testMethodWithFailureNewAssertion ) ;
123
+
124
+ var oldAssertionComment = testWithFailureOldAssertion . DescendantTrivia ( ) . First ( x => x . IsKind ( SyntaxKind . SingleLineCommentTrivia ) && x . ToString ( ) . Equals ( "// old assertion:" ) ) ;
125
+ var newAssertionComment = testWithFailureNewAssertion . DescendantTrivia ( ) . First ( x => x . IsKind ( SyntaxKind . SingleLineCommentTrivia ) && x . ToString ( ) . Equals ( "// new assertion:" ) ) ;
126
+
127
+ var bodyLines = testWithFailureNewAssertion . Body . ToFullString ( ) . Split ( Environment . NewLine ) [ 2 ..^ 2 ] ;
128
+ var paddingToRemove = bodyLines [ 0 ] . IndexOf ( bodyLines [ 0 ] . TrimStart ( ) ) ;
129
+
130
+ var oldAssertion = testWithFailureOldAssertion . Body . Statements . OfType < ExpressionStatementSyntax > ( ) . Single ( x => x . Span . CompareTo ( oldAssertionComment . Span ) > 0 ) . ToString ( ) . TrimStart ( ) + " \t // fail message: " + exceptionMessageLinesOldAssertion ;
131
+ var newAssertion = testWithFailureNewAssertion . Body . Statements . OfType < ExpressionStatementSyntax > ( ) . Single ( x => x . Span . CompareTo ( newAssertionComment . Span ) > 0 ) . ToString ( ) . TrimStart ( ) + " \t // fail message: " + exceptionMessageLinesNewAssertion ;
132
+
133
+ var arrange = bodyLines . TakeWhile ( x => ! string . IsNullOrEmpty ( x ) )
134
+ . Select ( l => l . Length > paddingToRemove ? l . Substring ( paddingToRemove ) : l ) . Aggregate ( ( a , b ) => $ "{ a } { Environment . NewLine } { b } ") ;
135
+
136
+ scenarios . AppendLine ( $ "#### Failure messages") ;
137
+ scenarios . AppendLine ( ) ;
138
+ scenarios . AppendLine ( "```cs" ) ;
139
+ scenarios . AppendLine ( arrange ) ;
140
+ scenarios . AppendLine ( ) ;
141
+ scenarios . AppendLine ( $ "// old assertion:") ;
142
+ scenarios . AppendLine ( oldAssertion ) ;
143
+ scenarios . AppendLine ( ) ;
144
+ scenarios . AppendLine ( $ "// new assertion:") ;
145
+ scenarios . AppendLine ( newAssertion ) ;
146
+ scenarios . AppendLine ( "```" ) ;
147
+ scenarios . AppendLine ( ) ;
148
+ }
149
+
109
150
}
110
151
111
152
var diagnostics = await compilationWithAnalyzers . GetAllDiagnosticsAsync ( ) ;
@@ -114,26 +155,28 @@ public async Task Execute()
114
155
Console . WriteLine ( $ "source: { root . FindNode ( diagnostic . Location . SourceSpan ) } ") ;
115
156
Console . WriteLine ( $ " diagnostic: { diagnostic } ") ;
116
157
}
117
- }
118
158
119
- docs . AppendLine ( toc . ToString ( ) ) ;
120
- docs . AppendLine ( ) ;
121
- docs . AppendLine ( scenarios . ToString ( ) ) ;
159
+ docs . AppendLine ( toc . ToString ( ) ) ;
160
+ docs . AppendLine ( ) ;
161
+ docs . AppendLine ( scenarios . ToString ( ) ) ;
122
162
123
- var docsPath = Path . Combine ( Environment . CurrentDirectory , ".." , ".." , "docs" , "FluentAssertionsAnalyzer.md" ) ;
124
- Directory . CreateDirectory ( Path . GetDirectoryName ( docsPath ) ) ;
125
- await File . WriteAllTextAsync ( docsPath , docs . ToString ( ) ) ;
163
+ var docsPath = Path . Combine ( Environment . CurrentDirectory , ".." , ".." , "docs" , docsName ) ;
164
+ Directory . CreateDirectory ( Path . GetDirectoryName ( docsPath ) ) ;
165
+ await File . WriteAllTextAsync ( docsPath , docs . ToString ( ) ) ;
166
+ }
126
167
}
127
168
128
- private string [ ] GetMethodExceptionMessageLines ( object instnace , MethodInfo method )
169
+ private string [ ] GetMethodExceptionMessageLines ( object instance , MethodInfo method )
170
+ => GetMethodExceptionMessage ( instance , method ) . Split ( Environment . NewLine , StringSplitOptions . RemoveEmptyEntries ) ;
171
+ private string GetMethodExceptionMessage ( object instance , MethodInfo method )
129
172
{
130
173
try
131
174
{
132
- method . Invoke ( instnace , null ) ;
175
+ method . Invoke ( instance , null ) ;
133
176
}
134
177
catch ( Exception ex ) when ( ex . InnerException is AssertFailedException exception )
135
178
{
136
- return exception . Message . Split ( Environment . NewLine , StringSplitOptions . RemoveEmptyEntries ) ;
179
+ return exception . Message ;
137
180
}
138
181
139
182
throw new InvalidOperationException ( "Method did not throw an exception" ) ;
0 commit comments