Skip to content

Commit d7b033d

Browse files
committed
Merge remote-tracking branch 'refs/remotes/DotNetAnalyzers/master'
2 parents e7e9760 + 172bc26 commit d7b033d

7 files changed

Lines changed: 276 additions & 6 deletions

File tree

StyleCop.Analyzers/StyleCop.Analyzers.CodeFixes/OrderingRules/UsingCodeFixProvider.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -154,7 +154,8 @@ private static SyntaxNode ReAddFileHeader(SyntaxNode syntaxRoot, SyntaxNode newS
154154
}
155155

156156
var newFirstToken = newSyntaxRoot.GetFirstToken();
157-
return newSyntaxRoot.ReplaceToken(newFirstToken, newFirstToken.WithLeadingTrivia(fileHeader));
157+
var newLeadingTrivia = newFirstToken.LeadingTrivia.InsertRange(0, fileHeader);
158+
return newSyntaxRoot.ReplaceToken(newFirstToken, newFirstToken.WithLeadingTrivia(newLeadingTrivia));
158159
}
159160

160161
private static int CountNamespaces(SyntaxList<MemberDeclarationSyntax> members)
Lines changed: 135 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,135 @@
1+
// Copyright (c) Tunnel Vision Laboratories, LLC. All Rights Reserved.
2+
// Licensed under the Apache License, Version 2.0. See LICENSE in the project root for license information.
3+
4+
namespace StyleCop.Analyzers.Test.LayoutRules
5+
{
6+
using System.Threading;
7+
using System.Threading.Tasks;
8+
using StyleCop.Analyzers.LayoutRules;
9+
using TestHelper;
10+
using Xunit;
11+
12+
/// <summary>
13+
/// Unit tests for the operators part of <see cref="SA1502ElementMustNotBeOnASingleLine"/>.
14+
/// </summary>
15+
public partial class SA1502UnitTests : CodeFixVerifier
16+
{
17+
/// <summary>
18+
/// Verifies that valid operators will pass without diagnostic.
19+
/// </summary>
20+
/// <returns>A <see cref="Task"/> representing the asynchronous unit test.</returns>
21+
[Fact]
22+
public async Task TestValidOperatorsAsync()
23+
{
24+
var testCode = @"public class TestClass
25+
{
26+
public static TestClass operator +(TestClass value)
27+
{
28+
return value;
29+
}
30+
31+
public static explicit operator TestClass(int value)
32+
{
33+
return new TestClass();
34+
}
35+
}";
36+
37+
await this.VerifyCSharpDiagnosticAsync(testCode, EmptyDiagnosticResults, CancellationToken.None).ConfigureAwait(false);
38+
}
39+
40+
/// <summary>
41+
/// Verifies that operators with their blocks on the same line will trigger a diagnostic.
42+
/// </summary>
43+
/// <returns>A <see cref="Task"/> representing the asynchronous unit test.</returns>
44+
[Fact]
45+
public async Task TestOperatorsOnSingleLineAsync()
46+
{
47+
var testCode = @"public class TestClass
48+
{
49+
public static TestClass operator +(TestClass value) { return value; }
50+
51+
public static explicit operator TestClass(int value) { return new TestClass(); }
52+
}";
53+
54+
var fixedCode = @"public class TestClass
55+
{
56+
public static TestClass operator +(TestClass value)
57+
{
58+
return value;
59+
}
60+
61+
public static explicit operator TestClass(int value)
62+
{
63+
return new TestClass();
64+
}
65+
}";
66+
67+
DiagnosticResult[] expected =
68+
{
69+
this.CSharpDiagnostic().WithLocation(3, 57),
70+
this.CSharpDiagnostic().WithLocation(5, 58)
71+
};
72+
73+
await this.VerifyCSharpDiagnosticAsync(testCode, expected, CancellationToken.None).ConfigureAwait(false);
74+
await this.VerifyCSharpDiagnosticAsync(fixedCode, EmptyDiagnosticResults, CancellationToken.None).ConfigureAwait(false);
75+
await this.VerifyCSharpFixAsync(testCode, fixedCode).ConfigureAwait(false);
76+
}
77+
78+
/// <summary>
79+
/// Verifies that operators with their blocks on the next line will trigger a diagnostic.
80+
/// </summary>
81+
/// <returns>A <see cref="Task"/> representing the asynchronous unit test.</returns>
82+
[Fact]
83+
public async Task TestOperatorsWithBlockOnNextLineAsync()
84+
{
85+
var testCode = @"public class TestClass
86+
{
87+
public static TestClass operator +(TestClass value)
88+
{ return value; }
89+
90+
public static explicit operator TestClass(int value)
91+
{ return new TestClass(); }
92+
}";
93+
94+
var fixedCode = @"public class TestClass
95+
{
96+
public static TestClass operator +(TestClass value)
97+
{
98+
return value;
99+
}
100+
101+
public static explicit operator TestClass(int value)
102+
{
103+
return new TestClass();
104+
}
105+
}";
106+
107+
DiagnosticResult[] expected =
108+
{
109+
this.CSharpDiagnostic().WithLocation(4, 9),
110+
this.CSharpDiagnostic().WithLocation(7, 9)
111+
};
112+
113+
await this.VerifyCSharpDiagnosticAsync(testCode, expected, CancellationToken.None).ConfigureAwait(false);
114+
await this.VerifyCSharpDiagnosticAsync(fixedCode, EmptyDiagnosticResults, CancellationToken.None).ConfigureAwait(false);
115+
await this.VerifyCSharpFixAsync(testCode, fixedCode).ConfigureAwait(false);
116+
}
117+
118+
/// <summary>
119+
/// Verifies that operators with an expression body will pass without diagnostic.
120+
/// </summary>
121+
/// <returns>A <see cref="Task"/> representing the asynchronous unit test.</returns>
122+
[Fact]
123+
public async Task TestOperatorsWithExpressionBodyAsync()
124+
{
125+
var testCode = @"public class TestClass
126+
{
127+
public static TestClass operator +(TestClass value) => value;
128+
129+
public static explicit operator TestClass(int value) => new TestClass();
130+
}";
131+
132+
await this.VerifyCSharpDiagnosticAsync(testCode, EmptyDiagnosticResults, CancellationToken.None).ConfigureAwait(false);
133+
}
134+
}
135+
}

StyleCop.Analyzers/StyleCop.Analyzers.Test/OrderingRules/UsingCodeFixProviderUnitTests.cs

Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -477,6 +477,98 @@ public async Task VerifyCodefixForElsePartOfDirectiveTriviaAsync()
477477
await this.VerifyCSharpFixAsync(testCode, fixedTestCode).ConfigureAwait(false);
478478
}
479479

480+
/// <summary>
481+
/// Verifies that the code fix will handle using statements with directive trivia outside of namespaces
482+
/// This is a regression test for #1733
483+
/// </summary>
484+
/// <returns>A <see cref="Task"/> representing the asynchronous unit test.</returns>
485+
[Fact]
486+
public async Task VerifyCodefixForDirectiveTriviaOutsideOfNamespacesAsync()
487+
{
488+
var testCode = @"// <copyright file=""Program.cs"" company=""PlaceholderCompany"" >
489+
// Copyright (c) PlaceholderCompany. All rights reserved.
490+
// </copyright>
491+
492+
#if DEBUG
493+
using Fish;
494+
#else
495+
using Fish.Face;
496+
#endif
497+
using System.Text;
498+
using System;
499+
500+
namespace StyleCopBugRepro
501+
{
502+
class Program
503+
{
504+
static void Main(string[] args)
505+
{
506+
Int32 q;
507+
Haddock h;
508+
StringBuilder sb;
509+
}
510+
}
511+
}
512+
513+
namespace Fish
514+
{
515+
public class Haddock { }
516+
517+
namespace Face
518+
{
519+
public class Haddock { }
520+
}
521+
}
522+
";
523+
524+
var fixedTestCode = @"// <copyright file=""Program.cs"" company=""PlaceholderCompany"" >
525+
// Copyright (c) PlaceholderCompany. All rights reserved.
526+
// </copyright>
527+
528+
#if DEBUG
529+
using Fish;
530+
#else
531+
using Fish.Face;
532+
#endif
533+
using System;
534+
using System.Text;
535+
536+
namespace StyleCopBugRepro
537+
{
538+
class Program
539+
{
540+
static void Main(string[] args)
541+
{
542+
Int32 q;
543+
Haddock h;
544+
StringBuilder sb;
545+
}
546+
}
547+
}
548+
549+
namespace Fish
550+
{
551+
public class Haddock { }
552+
553+
namespace Face
554+
{
555+
public class Haddock { }
556+
}
557+
}
558+
";
559+
560+
DiagnosticResult[] expected =
561+
{
562+
this.CSharpDiagnostic(SA1200UsingDirectivesMustBePlacedWithinNamespace.DiagnosticId).WithLocation(8, 1),
563+
this.CSharpDiagnostic(SA1200UsingDirectivesMustBePlacedWithinNamespace.DiagnosticId).WithLocation(10, 1),
564+
this.CSharpDiagnostic(SA1210UsingDirectivesMustBeOrderedAlphabeticallyByNamespace.DiagnosticId).WithLocation(10, 1),
565+
this.CSharpDiagnostic(SA1200UsingDirectivesMustBePlacedWithinNamespace.DiagnosticId).WithLocation(11, 1)
566+
};
567+
568+
await this.VerifyCSharpDiagnosticAsync(testCode, expected, CancellationToken.None).ConfigureAwait(false);
569+
await this.VerifyCSharpFixAsync(testCode, fixedTestCode).ConfigureAwait(false);
570+
}
571+
480572
/// <inheritdoc/>
481573
protected override IEnumerable<string> GetDisabledDiagnostics()
482574
{

StyleCop.Analyzers/StyleCop.Analyzers.Test/StyleCop.Analyzers.Test.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -208,6 +208,7 @@
208208
<Compile Include="LayoutRules\SA1502\SA1502UnitTests.Interfaces.cs" />
209209
<Compile Include="LayoutRules\SA1502\SA1502UnitTests.Methods.cs" />
210210
<Compile Include="LayoutRules\SA1502\SA1502UnitTests.Namespaces.cs" />
211+
<Compile Include="LayoutRules\SA1502\SA1502UnitTests.Operators.cs" />
211212
<Compile Include="LayoutRules\SA1502\SA1502UnitTests.Properties.cs" />
212213
<Compile Include="LayoutRules\SA1502\SA1502UnitTests.TypeDeclarations.cs" />
213214
<Compile Include="LayoutRules\SA1503UnitTests.cs" />

StyleCop.Analyzers/StyleCop.Analyzers/LayoutRules/LayoutResources.Designer.cs

Lines changed: 27 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

StyleCop.Analyzers/StyleCop.Analyzers/LayoutRules/LayoutResources.resx

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,15 @@
126126
<data name="SA1502CodeFix" xml:space="preserve">
127127
<value>Expand element</value>
128128
</data>
129+
<data name="SA1502Description" xml:space="preserve">
130+
<value>A C# element containing opening and closing curly brackets is written completely on a single line.</value>
131+
</data>
132+
<data name="SA1502MessageFormat" xml:space="preserve">
133+
<value>Element must not be on a single line</value>
134+
</data>
135+
<data name="SA1502Title" xml:space="preserve">
136+
<value>Element must not be on a single line</value>
137+
</data>
129138
<data name="SA1503CodeFix" xml:space="preserve">
130139
<value>Wrap with curly brackets</value>
131140
</data>

StyleCop.Analyzers/StyleCop.Analyzers/LayoutRules/SA1502ElementMustNotBeOnASingleLine.cs

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -43,10 +43,10 @@ internal class SA1502ElementMustNotBeOnASingleLine : DiagnosticAnalyzer
4343
/// The ID for diagnostics produced by the <see cref="SA1502ElementMustNotBeOnASingleLine"/> analyzer.
4444
/// </summary>
4545
public const string DiagnosticId = "SA1502";
46-
private const string Title = "Element must not be on a single line";
47-
private const string MessageFormat = "Element must not be on a single line";
48-
private const string Description = "A C# element containing opening and closing curly brackets is written completely on a single line.";
49-
private const string HelpLink = "https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/SA1502.md";
46+
private static readonly LocalizableString Title = new LocalizableResourceString(nameof(LayoutResources.SA1502Title), LayoutResources.ResourceManager, typeof(LayoutResources));
47+
private static readonly LocalizableString MessageFormat = new LocalizableResourceString(nameof(LayoutResources.SA1502MessageFormat), LayoutResources.ResourceManager, typeof(LayoutResources));
48+
private static readonly LocalizableString Description = new LocalizableResourceString(nameof(LayoutResources.SA1502Description), LayoutResources.ResourceManager, typeof(LayoutResources));
49+
private static readonly string HelpLink = "https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/SA1502.md";
5050

5151
private static readonly DiagnosticDescriptor Descriptor =
5252
new DiagnosticDescriptor(DiagnosticId, Title, MessageFormat, AnalyzerCategory.LayoutRules, DiagnosticSeverity.Warning, AnalyzerConstants.EnabledByDefault, Description, HelpLink);
@@ -58,7 +58,12 @@ internal class SA1502ElementMustNotBeOnASingleLine : DiagnosticAnalyzer
5858
ImmutableArray.Create(SyntaxKind.PropertyDeclaration, SyntaxKind.EventDeclaration, SyntaxKind.IndexerDeclaration);
5959

6060
private static readonly ImmutableArray<SyntaxKind> BaseMethodDeclarationKinds =
61-
ImmutableArray.Create(SyntaxKind.MethodDeclaration, SyntaxKind.ConstructorDeclaration, SyntaxKind.DestructorDeclaration);
61+
ImmutableArray.Create(
62+
SyntaxKind.MethodDeclaration,
63+
SyntaxKind.ConstructorDeclaration,
64+
SyntaxKind.DestructorDeclaration,
65+
SyntaxKind.OperatorDeclaration,
66+
SyntaxKind.ConversionOperatorDeclaration);
6267

6368
private static readonly Action<CompilationStartAnalysisContext> CompilationStartAction = HandleCompilationStart;
6469
private static readonly Action<SyntaxNodeAnalysisContext> BaseTypeDeclarationAction = HandleBaseTypeDeclaration;

0 commit comments

Comments
 (0)