Skip to content

Commit 602b220

Browse files
committed
Fix SA1134 hard-coding of CRLF
1 parent 2633726 commit 602b220

File tree

2 files changed

+71
-13
lines changed

2 files changed

+71
-13
lines changed

StyleCop.Analyzers/StyleCop.Analyzers.CodeFixes/ReadabilityRules/SA1134CodeFixProvider.cs

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@ namespace StyleCop.Analyzers.ReadabilityRules
1515
using Microsoft.CodeAnalysis.CodeFixes;
1616
using Microsoft.CodeAnalysis.CSharp;
1717
using Microsoft.CodeAnalysis.CSharp.Syntax;
18+
using Microsoft.CodeAnalysis.Options;
19+
using Microsoft.CodeAnalysis.Text;
1820
using StyleCop.Analyzers.Helpers;
1921
using StyleCop.Analyzers.Settings.ObjectModel;
2022

@@ -58,18 +60,20 @@ public override async Task RegisterCodeFixesAsync(CodeFixContext context)
5860
private static async Task<Document> GetTransformedDocumentAsync(Document document, Diagnostic diagnostic, CancellationToken cancellationToken)
5961
{
6062
var syntaxRoot = await document.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false);
63+
var sourceText = await document.GetTextAsync(cancellationToken).ConfigureAwait(false);
64+
var options = document.Project.Solution.Workspace.Options;
6165
var settings = SettingsHelper.GetStyleCopSettingsInCodeFix(document.Project.AnalyzerOptions, syntaxRoot.SyntaxTree, cancellationToken);
6266
var tokensToReplace = new Dictionary<SyntaxToken, SyntaxToken>();
6367

64-
AddTokensToReplaceToMap(tokensToReplace, syntaxRoot, diagnostic, settings);
68+
AddTokensToReplaceToMap(tokensToReplace, syntaxRoot, sourceText, options, diagnostic, settings);
6569

6670
var newSyntaxRoot = syntaxRoot.ReplaceTokens(tokensToReplace.Keys, (original, rewritten) => tokensToReplace[original]);
6771
var newDocument = document.WithSyntaxRoot(newSyntaxRoot.WithoutFormatting());
6872

6973
return newDocument;
7074
}
7175

72-
private static void AddTokensToReplaceToMap(Dictionary<SyntaxToken, SyntaxToken> tokensToReplace, SyntaxNode syntaxRoot, Diagnostic diagnostic, StyleCopSettings settings)
76+
private static void AddTokensToReplaceToMap(Dictionary<SyntaxToken, SyntaxToken> tokensToReplace, SyntaxNode syntaxRoot, SourceText sourceText, OptionSet options, Diagnostic diagnostic, StyleCopSettings settings)
7377
{
7478
var attributeListSyntax = (AttributeListSyntax)syntaxRoot.FindNode(diagnostic.Location.SourceSpan);
7579

@@ -81,9 +85,10 @@ private static void AddTokensToReplaceToMap(Dictionary<SyntaxToken, SyntaxToken>
8185
if (diagnostic.Properties.ContainsKey(SA1134AttributesMustNotShareLine.FixWithNewLineBeforeKey))
8286
{
8387
var token = attributeListSyntax.OpenBracketToken;
88+
var endOfLineTrivia = FormattingHelper.GetEndOfLineForCodeFix(token, sourceText, options);
8489
var prevToken = token.GetPreviousToken();
8590

86-
tokensToReplace[prevToken] = prevToken.WithTrailingTrivia(prevToken.TrailingTrivia.WithoutTrailingWhitespace().Add(SyntaxFactory.CarriageReturnLineFeed));
91+
tokensToReplace[prevToken] = prevToken.WithTrailingTrivia(prevToken.TrailingTrivia.WithoutTrailingWhitespace().Add(endOfLineTrivia));
8792

8893
var newLeadingTrivia = token.LeadingTrivia.Insert(0, indentationTrivia);
8994
tokensToReplace[token] = token.WithLeadingTrivia(newLeadingTrivia);
@@ -92,9 +97,10 @@ private static void AddTokensToReplaceToMap(Dictionary<SyntaxToken, SyntaxToken>
9297
if (diagnostic.Properties.ContainsKey(SA1134AttributesMustNotShareLine.FixWithNewLineAfterKey))
9398
{
9499
var token = attributeListSyntax.CloseBracketToken;
100+
var endOfLineTrivia = FormattingHelper.GetEndOfLineForCodeFix(token, sourceText, options);
95101
var nextToken = token.GetNextToken();
96102

97-
tokensToReplace[token] = token.WithTrailingTrivia(token.TrailingTrivia.WithoutTrailingWhitespace().Add(SyntaxFactory.CarriageReturnLineFeed));
103+
tokensToReplace[token] = token.WithTrailingTrivia(token.TrailingTrivia.WithoutTrailingWhitespace().Add(endOfLineTrivia));
98104

99105
var newLeadingTrivia = nextToken.LeadingTrivia.Insert(0, indentationTrivia);
100106
tokensToReplace[nextToken] = nextToken.WithLeadingTrivia(newLeadingTrivia);
@@ -115,12 +121,14 @@ protected override async Task<SyntaxNode> FixAllInDocumentAsync(FixAllContext fi
115121
}
116122

117123
var syntaxRoot = await document.GetSyntaxRootAsync(fixAllContext.CancellationToken).ConfigureAwait(false);
124+
var sourceText = await document.GetTextAsync(fixAllContext.CancellationToken).ConfigureAwait(false);
125+
var options = document.Project.Solution.Workspace.Options;
118126
var settings = SettingsHelper.GetStyleCopSettingsInCodeFix(document.Project.AnalyzerOptions, syntaxRoot.SyntaxTree, fixAllContext.CancellationToken);
119127
var tokensToReplace = new Dictionary<SyntaxToken, SyntaxToken>();
120128

121129
foreach (var diagnostic in diagnostics)
122130
{
123-
AddTokensToReplaceToMap(tokensToReplace, syntaxRoot, diagnostic, settings);
131+
AddTokensToReplaceToMap(tokensToReplace, syntaxRoot, sourceText, options, diagnostic, settings);
124132
}
125133

126134
var newSyntaxRoot = syntaxRoot.ReplaceTokens(tokensToReplace.Keys, (original, rewritten) => tokensToReplace[original]);

StyleCop.Analyzers/StyleCop.Analyzers.Test/ReadabilityRules/SA1134UnitTests.cs

Lines changed: 58 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ namespace StyleCop.Analyzers.Test.ReadabilityRules
88
using System.Threading;
99
using System.Threading.Tasks;
1010
using Microsoft.CodeAnalysis.Testing;
11+
using StyleCop.Analyzers.Test.Helpers;
1112
using Xunit;
1213
using static StyleCop.Analyzers.Test.Verifiers.StyleCopCodeFixVerifier<
1314
StyleCop.Analyzers.ReadabilityRules.SA1134AttributesMustNotShareLine,
@@ -41,10 +42,7 @@ public class TestClass
4142
/// <param name="typeDeclaration">The type declaration to check.</param>
4243
/// <returns>A <see cref="Task"/> representing the asynchronous unit test.</returns>
4344
[Theory]
44-
[InlineData("class")]
45-
[InlineData("struct")]
46-
[InlineData("interface")]
47-
[InlineData("enum")]
45+
[MemberData(nameof(CommonMemberData.BaseTypeDeclarationKeywords), MemberType = typeof(CommonMemberData))]
4846
public async Task VerifyMultipleAttributesOnSameLineForTypeDeclarationsAsync(string typeDeclaration)
4947
{
5048
var testCode = $@"using System.ComponentModel;
@@ -54,12 +52,12 @@ namespace TestNamespace
5452
/// <summary>
5553
/// Test class.
5654
/// </summary>
57-
[EditorBrowsable(EditorBrowsableState.Never)][DesignOnly(true)]
55+
[EditorBrowsable(EditorBrowsableState.Never)]{{|#0:[|}}DesignOnly(true)]
5856
public {typeDeclaration} Test
5957
{{
6058
}}
6159
62-
[DesignOnly(true)] public {typeDeclaration} Test2
60+
{{|#1:[|}}DesignOnly(true)] public {typeDeclaration} Test2
6361
{{
6462
}}
6563
}}
@@ -87,8 +85,60 @@ namespace TestNamespace
8785

8886
DiagnosticResult[] expected =
8987
{
90-
Diagnostic().WithLocation(8, 50),
91-
Diagnostic().WithLocation(13, 5),
88+
Diagnostic().WithLocation(0),
89+
Diagnostic().WithLocation(1),
90+
};
91+
92+
await VerifyCSharpFixAsync(testCode, expected, fixedTestCode, CancellationToken.None).ConfigureAwait(false);
93+
}
94+
95+
[Theory]
96+
[InlineData("\n")]
97+
[InlineData("\r\n")]
98+
public async Task VerifyMultipleAttributesOnSameLineForTypeDeclarationsWithLineEndingsAsync(string lineEnding)
99+
{
100+
var testCode = @"using System.ComponentModel;
101+
102+
namespace TestNamespace
103+
{
104+
/// <summary>
105+
/// Test class.
106+
/// </summary>
107+
[EditorBrowsable(EditorBrowsableState.Never)]{|#0:[|}DesignOnly(true)]
108+
public class Test
109+
{
110+
}
111+
112+
{|#1:[|}DesignOnly(true)] public class Test2
113+
{
114+
}
115+
}
116+
".ReplaceLineEndings(lineEnding);
117+
118+
var fixedTestCode = @"using System.ComponentModel;
119+
120+
namespace TestNamespace
121+
{
122+
/// <summary>
123+
/// Test class.
124+
/// </summary>
125+
[EditorBrowsable(EditorBrowsableState.Never)]
126+
[DesignOnly(true)]
127+
public class Test
128+
{
129+
}
130+
131+
[DesignOnly(true)]
132+
public class Test2
133+
{
134+
}
135+
}
136+
".ReplaceLineEndings(lineEnding);
137+
138+
DiagnosticResult[] expected =
139+
{
140+
Diagnostic().WithLocation(0),
141+
Diagnostic().WithLocation(1),
92142
};
93143

94144
await VerifyCSharpFixAsync(testCode, expected, fixedTestCode, CancellationToken.None).ConfigureAwait(false);

0 commit comments

Comments
 (0)