Skip to content

Commit db7a4d4

Browse files
committed
Merge remote-tracking branch 'DotNetAnalyzers/master' into fix-2023
2 parents 990b6bd + 4da56fd commit db7a4d4

362 files changed

Lines changed: 16067 additions & 4143 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

CONTRIBUTING.md

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,6 @@ If you want to contribute code you can get started by looking for issues marked
55
We also have the [easy](https://github.com/DotNetAnalyzers/StyleCopAnalyzers/labels/easy) tag
66
for issues suitable if you are unfamiliar with roslyn.
77

8-
Also see the [contributing guide](CONTRIBUTING.md).
9-
108
You can also help by filing issues, participating in discussions and doing code review.
119

1210
## Implementing a diagnostic
@@ -30,4 +28,4 @@ You can also help by filing issues, participating in discussions and doing code
3028

3129
Visual Studio 2015 RC is required for building this repository.
3230
The Visual Studio 2015 RC SDK is required for building the vsix extension project and for
33-
debugging in an experimental visual studio hive.
31+
debugging in an experimental visual studio hive.

DOCUMENTATION.md

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
StyleCop.Analyzers provides warnings that indicate style and consistency rule violations in C# code. The warnings are organized into rule areas such as documentation, layout, naming, ordering, readability, spacing, and so forth. Each warning signifies a violation of a style or consistency rule. This section provides an explanation of each of the default StyleCop.Analyzers rules.
2+
3+
### Rule areas
4+
**[Special Rules (SA0000-)](documentation/SpecialRules.md)**
5+
6+
Rules which provide special functionality like workarounds, configuration errors, etc.
7+
8+
**[Spacing Rules (SA1000-)](documentation/SpacingRules.md)**
9+
10+
Rules which enforce spacing requirements around keywords and symbols in the code.
11+
12+
**[Readability Rules (SA1100-)](documentation/ReadabilityRules.md)**
13+
14+
Rules which ensure that the code is well-formatted and readable.
15+
16+
**[Ordering Rules (SA1200-)](documentation/OrderingRules.md)**
17+
18+
Rules which enforce a standard ordering scheme for code contents.
19+
20+
**[Naming Rules (SA1300-)](documentation/NamingRules.md)**
21+
22+
Rules which enforce naming requirements for members, types, and variables.
23+
24+
**[Maintainability Rules (SA1400-)](documentation/MaintainabilityRules.md)**
25+
26+
Rules which improve code maintainability.
27+
28+
**[Layout Rules (SA1500-)](documentation/LayoutRules.md)**
29+
30+
Rules which enforce code layout and line spacing.
31+
32+
**[Documentation Rules (SA1600-)](documentation/DocumentationRules.md)**
33+
34+
Rules which verify the content and formatting of code documentation.
35+
36+
**[Alternative Rules (SX0000-)](documentation/AlternativeRules.md)**
37+
38+
Rules which offer a non-standard extension to the default StyleCop behavior.
39+
40+
### Additional documentation
41+
**[Configuration](documentation/Configuration.md)**
42+
43+
Describes the configuration options for StyleCop.Analyzers
44+
45+
**[How to enable the configuration](documentation/EnableConfiguration.md)**
46+
47+
Describes how to enable the **stylecop.json** file for usage.
48+
49+
**[Known changes](documentation/KnownChanges.md)**
50+
51+
Describes the known differences between StyleCop Analyzers and StyleCop Classic.

README.md

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,14 @@ for information about known differences which you may notice when switching to S
2222

2323
## Installation
2424

25-
StyleCopAnalyzers can be installed using the NuGet Package Manager in Visual Studio 2015.
25+
StyleCopAnalyzers can be installed using the NuGet command line or the NuGet Package Manager in Visual Studio 2015.
2626

27+
**Install using the command line:**
28+
```bash
29+
Install-Package StyleCop.Analyzers
30+
```
31+
32+
**Install using the package manager:**
2733
![Install via nuget](https://cloud.githubusercontent.com/assets/1408396/8233513/491f301a-159c-11e5-8b7a-1e16a0695da6.png)
2834

2935
## Team Considerations

StyleCop.Analyzers/StyleCop.Analyzers.CodeFixes/DocumentationRules/FileHeaderCodeFixProvider.cs

Lines changed: 53 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
namespace StyleCop.Analyzers.DocumentationRules
55
{
66
using System;
7+
using System.Collections.Generic;
78
using System.Collections.Immutable;
89
using System.Composition;
910
using System.Text;
@@ -18,6 +19,7 @@ namespace StyleCop.Analyzers.DocumentationRules
1819
using Microsoft.CodeAnalysis.Formatting;
1920
using StyleCop.Analyzers.Helpers;
2021
using StyleCop.Analyzers.Settings.ObjectModel;
22+
using Path = System.IO.Path;
2123

2224
/// <summary>
2325
/// Implements a code fix for file header diagnostics.
@@ -136,8 +138,9 @@ private static SyntaxNode ReplaceWellFormedMultiLineCommentHeader(Document docum
136138
// Pad line that used to be next to a /*
137139
triviaStringParts[0] = commentIndentation + interlinePadding + " " + triviaStringParts[0];
138140
StringBuilder sb = StringBuilderPool.Allocate();
141+
string fileName = Path.GetFileName(document.FilePath);
139142
var copyrightText = commentIndentation + interlinePadding + " " +
140-
GetCopyrightText(commentIndentation + interlinePadding, settings.DocumentationRules.CopyrightText, newLineText);
143+
GetCopyrightText(commentIndentation + interlinePadding, settings.DocumentationRules.GetCopyrightText(fileName), newLineText);
141144
var newHeader = WrapInXmlComment(commentIndentation + interlinePadding, copyrightText, document.Name, settings, newLineText);
142145

143146
sb.Append(commentIndentation);
@@ -212,6 +215,9 @@ private static SyntaxNode ReplaceHeader(Document document, SyntaxNode root, Styl
212215
var leadingSpaces = string.Empty;
213216
string possibleLeadingSpaces = string.Empty;
214217

218+
// remove header decoration lines, they will be re-generated
219+
trivia = RemoveHeaderDecorationLines(trivia, settings);
220+
215221
// Need to do this with index so we get the line endings correct.
216222
for (int i = 0; i < trivia.Count; i++)
217223
{
@@ -350,31 +356,71 @@ private static SyntaxNode AddHeader(Document document, SyntaxNode root, string n
350356
return root.WithLeadingTrivia(newTrivia);
351357
}
352358

353-
private static SyntaxTriviaList CreateNewHeader(string prefixWithLeadingSpaces, string filename, StyleCopSettings settings, string newLineText)
359+
private static SyntaxTriviaList CreateNewHeader(string prefixWithLeadingSpaces, string fileName, StyleCopSettings settings, string newLineText)
354360
{
355-
var copyrightText = prefixWithLeadingSpaces + " " + GetCopyrightText(prefixWithLeadingSpaces, settings.DocumentationRules.CopyrightText, newLineText);
361+
var copyrightText = prefixWithLeadingSpaces + " " + GetCopyrightText(prefixWithLeadingSpaces, settings.DocumentationRules.GetCopyrightText(fileName), newLineText);
356362
var newHeader = settings.DocumentationRules.XmlHeader
357-
? WrapInXmlComment(prefixWithLeadingSpaces, copyrightText, filename, settings, newLineText)
363+
? WrapInXmlComment(prefixWithLeadingSpaces, copyrightText, fileName, settings, newLineText)
358364
: copyrightText;
359365
return SyntaxFactory.ParseLeadingTrivia(newHeader);
360366
}
361367

362-
private static string WrapInXmlComment(string prefixWithLeadingSpaces, string copyrightText, string filename, StyleCopSettings settings, string newLineText)
368+
private static string WrapInXmlComment(string prefixWithLeadingSpaces, string copyrightText, string fileName, StyleCopSettings settings, string newLineText)
363369
{
364-
string encodedFilename = new XAttribute("t", filename).ToString().Substring(2).Trim('"');
370+
string encodedFilename = new XAttribute("t", fileName).ToString().Substring(2).Trim('"');
365371
string encodedCompanyName = new XAttribute("t", settings.DocumentationRules.CompanyName).ToString().Substring(2).Trim('"');
366372
string encodedCopyrightText = new XText(copyrightText).ToString();
367373

368-
return
374+
string copyrightString =
369375
$"{prefixWithLeadingSpaces} <copyright file=\"{encodedFilename}\" company=\"{encodedCompanyName}\">" + newLineText
370376
+ encodedCopyrightText + newLineText
371377
+ prefixWithLeadingSpaces + " </copyright>";
378+
379+
if (!string.IsNullOrEmpty(settings.DocumentationRules.HeaderDecoration))
380+
{
381+
return
382+
$"{prefixWithLeadingSpaces} {settings.DocumentationRules.HeaderDecoration}" + newLineText
383+
+ copyrightString + newLineText
384+
+ $"{prefixWithLeadingSpaces} {settings.DocumentationRules.HeaderDecoration}";
385+
}
386+
387+
return copyrightString;
372388
}
373389

374390
private static string GetCopyrightText(string prefixWithLeadingSpaces, string copyrightText, string newLineText)
375391
{
376392
copyrightText = copyrightText.Replace("\r\n", "\n");
377393
return string.Join(newLineText + prefixWithLeadingSpaces + " ", copyrightText.Split('\n')).Replace(prefixWithLeadingSpaces + " " + newLineText, prefixWithLeadingSpaces + newLineText);
378394
}
395+
396+
private static SyntaxTriviaList RemoveHeaderDecorationLines(SyntaxTriviaList trivia, StyleCopSettings settings)
397+
{
398+
if (!string.IsNullOrEmpty(settings.DocumentationRules.HeaderDecoration))
399+
{
400+
var decorationRemovalList = new List<int>();
401+
for (int i = 0; i < trivia.Count; i++)
402+
{
403+
var triviaLine = trivia[i];
404+
if (triviaLine.Kind() == SyntaxKind.SingleLineCommentTrivia && triviaLine.ToFullString().Contains(settings.DocumentationRules.HeaderDecoration))
405+
{
406+
decorationRemovalList.Add(i);
407+
408+
// also remove the line break
409+
if (i + 1 < trivia.Count && trivia[i + 1].Kind() == SyntaxKind.EndOfLineTrivia)
410+
{
411+
decorationRemovalList.Add(i + 1);
412+
}
413+
}
414+
}
415+
416+
// Remove decoration lines in reverse order.
417+
for (int i = decorationRemovalList.Count - 1; i >= 0; i--)
418+
{
419+
trivia = trivia.RemoveAt(decorationRemovalList[i]);
420+
}
421+
}
422+
423+
return trivia;
424+
}
379425
}
380426
}

StyleCop.Analyzers/StyleCop.Analyzers.CodeFixes/DocumentationRules/SA1609SA1610CodeFixProvider.cs

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -44,12 +44,15 @@ public override Task RegisterCodeFixesAsync(CodeFixContext context)
4444
{
4545
foreach (var diagnostic in context.Diagnostics)
4646
{
47-
context.RegisterCodeFix(
48-
CodeAction.Create(
49-
DocumentationResources.SA1609SA1610CodeFix,
50-
cancellationToken => this.GetTransformedDocumentAsync(context.Document, diagnostic, cancellationToken),
51-
nameof(SA1609SA1610CodeFixProvider)),
52-
diagnostic);
47+
if (!diagnostic.Properties.ContainsKey(PropertyDocumentationBase.NoCodeFixKey))
48+
{
49+
context.RegisterCodeFix(
50+
CodeAction.Create(
51+
DocumentationResources.SA1609SA1610CodeFix,
52+
cancellationToken => this.GetTransformedDocumentAsync(context.Document, diagnostic, cancellationToken),
53+
nameof(SA1609SA1610CodeFixProvider)),
54+
diagnostic);
55+
}
5356
}
5457

5558
return SpecializedTasks.CompletedTask;

StyleCop.Analyzers/StyleCop.Analyzers.CodeFixes/DocumentationRules/SA1615SA1616CodeFixProvider.cs

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,13 @@ private static async Task<Document> GetTransformedDocumentAsync(Document documen
7575
DocumentationCommentTriviaSyntax documentationComment =
7676
methodDeclarationSyntax?.GetDocumentationCommentTriviaSyntax()
7777
?? delegateDeclarationSyntax?.GetDocumentationCommentTriviaSyntax();
78-
if (documentationComment == null)
78+
bool canIgnoreDocumentation =
79+
documentationComment == null
80+
|| documentationComment.Content
81+
.Where(x => x is XmlElementSyntax || x is XmlEmptyElementSyntax)
82+
.All(x => string.Equals(x.GetName()?.ToString(), XmlCommentHelper.IncludeXmlTag));
83+
84+
if (canIgnoreDocumentation)
7985
{
8086
return document;
8187
}

StyleCop.Analyzers/StyleCop.Analyzers.CodeFixes/DocumentationRules/SA1617CodeFixProvider.cs

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -39,12 +39,15 @@ public override Task RegisterCodeFixesAsync(CodeFixContext context)
3939
{
4040
foreach (Diagnostic diagnostic in context.Diagnostics)
4141
{
42-
context.RegisterCodeFix(
43-
CodeAction.Create(
44-
DocumentationResources.SA1617CodeFix,
45-
cancellationToken => GetTransformedDocumentAsync(context.Document, diagnostic, cancellationToken),
46-
nameof(SA1617CodeFixProvider)),
47-
diagnostic);
42+
if (!diagnostic.Properties.ContainsKey(SA1617VoidReturnValueMustNotBeDocumented.NoCodeFixKey))
43+
{
44+
context.RegisterCodeFix(
45+
CodeAction.Create(
46+
DocumentationResources.SA1617CodeFix,
47+
cancellationToken => GetTransformedDocumentAsync(context.Document, diagnostic, cancellationToken),
48+
nameof(SA1617CodeFixProvider)),
49+
diagnostic);
50+
}
4851
}
4952

5053
return SpecializedTasks.CompletedTask;

StyleCop.Analyzers/StyleCop.Analyzers.CodeFixes/DocumentationRules/SA1642SA1643CodeFixProvider.cs

Lines changed: 23 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,10 @@ namespace StyleCop.Analyzers.DocumentationRules
66
using System;
77
using System.Collections.Immutable;
88
using System.Composition;
9+
using System.Globalization;
910
using System.Linq;
1011
using System.Text.RegularExpressions;
12+
using System.Threading;
1113
using System.Threading.Tasks;
1214
using Helpers;
1315
using Microsoft.CodeAnalysis;
@@ -48,16 +50,20 @@ public override async Task RegisterCodeFixesAsync(CodeFixContext context)
4850

4951
foreach (var diagnostic in context.Diagnostics)
5052
{
51-
var node = root.FindNode(diagnostic.Location.SourceSpan, findInsideTrivia: true, getInnermostNodeForTie: true);
53+
if (diagnostic.Properties.ContainsKey(StandardTextDiagnosticBase.NoCodeFixKey))
54+
{
55+
continue;
56+
}
5257

58+
var node = root.FindNode(diagnostic.Location.SourceSpan, findInsideTrivia: true, getInnermostNodeForTie: true);
5359
var xmlElementSyntax = node as XmlElementSyntax;
5460

5561
if (xmlElementSyntax != null)
5662
{
5763
context.RegisterCodeFix(
5864
CodeAction.Create(
5965
DocumentationResources.SA1642SA1643CodeFix,
60-
cancellationToken => GetTransformedDocumentAsync(context.Document, root, xmlElementSyntax),
66+
cancellationToken => GetTransformedDocumentAsync(context.Document, root, xmlElementSyntax, cancellationToken),
6167
nameof(SA1642SA1643CodeFixProvider)),
6268
diagnostic);
6369
}
@@ -74,11 +80,14 @@ public override async Task RegisterCodeFixesAsync(CodeFixContext context)
7480
}
7581
}
7682

77-
private static Task<Document> GetTransformedDocumentAsync(Document document, SyntaxNode root, XmlElementSyntax node)
83+
private static Task<Document> GetTransformedDocumentAsync(Document document, SyntaxNode root, XmlElementSyntax node, CancellationToken cancellationToken)
7884
{
7985
var typeDeclaration = node.FirstAncestorOrSelf<BaseTypeDeclarationSyntax>();
8086
var declarationSyntax = node.FirstAncestorOrSelf<BaseMethodDeclarationSyntax>();
8187
bool isStruct = typeDeclaration.IsKind(SyntaxKind.StructDeclaration);
88+
var settings = document.Project.AnalyzerOptions.GetStyleCopSettings(cancellationToken);
89+
var culture = new CultureInfo(settings.DocumentationRules.DocumentationCulture);
90+
var resourceManager = DocumentationResources.ResourceManager;
8291

8392
TypeParameterListSyntax typeParameterList;
8493
ClassDeclarationSyntax classDeclaration = typeDeclaration as ClassDeclarationSyntax;
@@ -94,35 +103,29 @@ private static Task<Document> GetTransformedDocumentAsync(Document document, Syn
94103
ImmutableArray<string> standardText;
95104
if (declarationSyntax is ConstructorDeclarationSyntax)
96105
{
106+
var typeKindText = resourceManager.GetString(isStruct ? nameof(DocumentationResources.TypeTextStruct) : nameof(DocumentationResources.TypeTextClass), culture);
97107
if (declarationSyntax.Modifiers.Any(SyntaxKind.StaticKeyword))
98108
{
99-
if (isStruct)
100-
{
101-
standardText = ImmutableArray.Create(SA1642ConstructorSummaryDocumentationMustBeginWithStandardText.StaticConstructorStandardText, " struct.");
102-
}
103-
else
104-
{
105-
standardText = ImmutableArray.Create(SA1642ConstructorSummaryDocumentationMustBeginWithStandardText.StaticConstructorStandardText, " class.");
106-
}
109+
standardText = ImmutableArray.Create(
110+
string.Format(resourceManager.GetString(nameof(DocumentationResources.StaticConstructorStandardTextFirstPart), culture), typeKindText),
111+
string.Format(resourceManager.GetString(nameof(DocumentationResources.StaticConstructorStandardTextSecondPart), culture), typeKindText));
107112
}
108113
else
109114
{
110115
// Prefer to insert the "non-private" wording for all constructors, even though both are considered
111116
// acceptable for private constructors by the diagnostic.
112117
// https://github.com/DotNetAnalyzers/StyleCopAnalyzers/issues/413
113-
if (isStruct)
114-
{
115-
standardText = ImmutableArray.Create(SA1642ConstructorSummaryDocumentationMustBeginWithStandardText.NonPrivateConstructorStandardText, " struct.");
116-
}
117-
else
118-
{
119-
standardText = ImmutableArray.Create(SA1642ConstructorSummaryDocumentationMustBeginWithStandardText.NonPrivateConstructorStandardText, " class.");
120-
}
118+
standardText = ImmutableArray.Create(
119+
string.Format(resourceManager.GetString(nameof(DocumentationResources.NonPrivateConstructorStandardTextFirstPart), culture), typeKindText),
120+
string.Format(resourceManager.GetString(nameof(DocumentationResources.NonPrivateConstructorStandardTextSecondPart), culture), typeKindText));
121121
}
122122
}
123123
else if (declarationSyntax is DestructorDeclarationSyntax)
124124
{
125-
standardText = SA1643DestructorSummaryDocumentationMustBeginWithStandardText.DestructorStandardText;
125+
standardText =
126+
ImmutableArray.Create(
127+
resourceManager.GetString(nameof(DocumentationResources.DestructorStandardTextFirstPart), culture),
128+
resourceManager.GetString(nameof(DocumentationResources.DestructorStandardTextSecondPart), culture));
126129
}
127130
else
128131
{

0 commit comments

Comments
 (0)