Skip to content

Commit edf811d

Browse files
authored
Merge pull request #3252 from NextTurn/sa1023
Fix SA1023 for C# 9 function pointer parameters
2 parents 8ee2404 + 56fa929 commit edf811d

File tree

3 files changed

+109
-1
lines changed

3 files changed

+109
-1
lines changed

StyleCop.Analyzers/StyleCop.Analyzers.Test.CSharp9/SpacingRules/SA1023CSharp9UnitTests.cs

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,86 @@
33

44
namespace StyleCop.Analyzers.Test.CSharp9.SpacingRules
55
{
6+
using System.Threading;
7+
using System.Threading.Tasks;
8+
using Microsoft.CodeAnalysis.CSharp;
9+
using Microsoft.CodeAnalysis.Testing;
610
using StyleCop.Analyzers.Test.CSharp8.SpacingRules;
11+
using StyleCop.Analyzers.Test.Verifiers;
12+
using Xunit;
13+
using static StyleCop.Analyzers.SpacingRules.SA1023DereferenceAndAccessOfSymbolsMustBeSpacedCorrectly;
14+
using static StyleCop.Analyzers.Test.Verifiers.StyleCopCodeFixVerifier<
15+
StyleCop.Analyzers.SpacingRules.SA1023DereferenceAndAccessOfSymbolsMustBeSpacedCorrectly,
16+
StyleCop.Analyzers.SpacingRules.TokenSpacingCodeFixProvider>;
717

818
public class SA1023CSharp9UnitTests : SA1023CSharp8UnitTests
919
{
20+
[Fact]
21+
public async Task TestFunctionPointerParameterInvalidSpacingAsync()
22+
{
23+
var testCode = @"public class TestClass
24+
{
25+
unsafe delegate*<int {|#0:*|}> FuncPtr1;
26+
unsafe delegate*<int{|#1:*|} > FuncPtr2;
27+
}
28+
";
29+
30+
var fixedCode = @"public class TestClass
31+
{
32+
unsafe delegate*<int*> FuncPtr1;
33+
unsafe delegate*<int*> FuncPtr2;
34+
}
35+
";
36+
37+
var expected = new[]
38+
{
39+
Diagnostic(DescriptorNotPreceded).WithLocation(0),
40+
Diagnostic(DescriptorNotFollowed).WithLocation(1),
41+
};
42+
43+
await VerifyCSharpFixAsync(LanguageVersion.CSharp9, testCode, expected, fixedCode, CancellationToken.None).ConfigureAwait(false);
44+
}
45+
46+
[Fact]
47+
public async Task TestFunctionPointerTypeInvalidSpacingAsync()
48+
{
49+
var testCode = @"public class TestClass
50+
{
51+
unsafe delegate {|#0:*|}<int*> FuncPtr1;
52+
unsafe delegate{|#1:*|} <int*> FuncPtr2;
53+
unsafe delegate {|#2:*|} managed<int*> FuncPtr3;
54+
unsafe delegate{|#3:*|}managed<int*> FuncPtr4;
55+
unsafe delegate {|#4:*|} unmanaged<int*> FuncPtr5;
56+
unsafe delegate{|#5:*|}unmanaged<int*> FuncPtr6;
57+
}
58+
";
59+
60+
var fixedCode = @"public class TestClass
61+
{
62+
unsafe delegate*<int*> FuncPtr1;
63+
unsafe delegate*<int*> FuncPtr2;
64+
unsafe delegate* managed<int*> FuncPtr3;
65+
unsafe delegate* managed<int*> FuncPtr4;
66+
unsafe delegate* unmanaged<int*> FuncPtr5;
67+
unsafe delegate* unmanaged<int*> FuncPtr6;
68+
}
69+
";
70+
71+
await new CSharpTest(LanguageVersion.CSharp9)
72+
{
73+
ReferenceAssemblies = GenericAnalyzerTest.ReferenceAssembliesNet50,
74+
TestCode = testCode,
75+
FixedCode = fixedCode,
76+
ExpectedDiagnostics =
77+
{
78+
Diagnostic(DescriptorNotPreceded).WithLocation(0),
79+
Diagnostic(DescriptorNotFollowed).WithLocation(1),
80+
Diagnostic(DescriptorNotPreceded).WithLocation(2),
81+
Diagnostic(DescriptorFollowed).WithLocation(3),
82+
Diagnostic(DescriptorNotPreceded).WithLocation(4),
83+
Diagnostic(DescriptorFollowed).WithLocation(5),
84+
},
85+
}.RunAsync().ConfigureAwait(false);
86+
}
1087
}
1188
}

StyleCop.Analyzers/StyleCop.Analyzers/Lightup/SyntaxKindEx.cs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@ internal static class SyntaxKindEx
99
{
1010
public const SyntaxKind DotDotToken = (SyntaxKind)8222;
1111
public const SyntaxKind QuestionQuestionEqualsToken = (SyntaxKind)8284;
12+
public const SyntaxKind ManagedKeyword = (SyntaxKind)8445;
13+
public const SyntaxKind UnmanagedKeyword = (SyntaxKind)8446;
1214
public const SyntaxKind NullableKeyword = (SyntaxKind)8486;
1315
public const SyntaxKind EnableKeyword = (SyntaxKind)8487;
1416
public const SyntaxKind WarningsKeyword = (SyntaxKind)8488;
@@ -49,6 +51,8 @@ internal static class SyntaxKindEx
4951
public const SyntaxKind ImplicitStackAllocArrayCreationExpression = (SyntaxKind)9053;
5052
public const SyntaxKind SuppressNullableWarningExpression = (SyntaxKind)9054;
5153
public const SyntaxKind NullableDirectiveTrivia = (SyntaxKind)9055;
54+
public const SyntaxKind FunctionPointerType = (SyntaxKind)9056;
55+
public const SyntaxKind FunctionPointerParameter = (SyntaxKind)9057;
5256
public const SyntaxKind WithInitializerExpression = (SyntaxKind)9062;
5357
public const SyntaxKind RecordDeclaration = (SyntaxKind)9063;
5458
public const SyntaxKind FunctionPointerUnmanagedCallingConventionList = (SyntaxKind)9066;

StyleCop.Analyzers/StyleCop.Analyzers/SpacingRules/SA1023DereferenceAndAccessOfSymbolsMustBeSpacedCorrectly.cs

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ namespace StyleCop.Analyzers.SpacingRules
99
using Microsoft.CodeAnalysis.CSharp;
1010
using Microsoft.CodeAnalysis.Diagnostics;
1111
using StyleCop.Analyzers.Helpers;
12+
using StyleCop.Analyzers.Lightup;
1213

1314
/// <summary>
1415
/// A dereference symbol or an access-of symbol within a C# element is not spaced correctly.
@@ -112,11 +113,37 @@ private static void HandleAsteriskToken(SyntaxTreeAnalysisContext context, Synta
112113
bool allowTrailingSpace;
113114
switch (token.Parent.Kind())
114115
{
116+
case SyntaxKindEx.FunctionPointerType:
117+
allowAtLineStart = true;
118+
allowAtLineEnd = true;
119+
allowPrecedingSpace = false;
120+
var nextToken = token.GetNextToken();
121+
switch (nextToken.Kind())
122+
{
123+
case SyntaxKindEx.ManagedKeyword:
124+
case SyntaxKindEx.UnmanagedKeyword:
125+
allowTrailingSpace = true;
126+
break;
127+
128+
default:
129+
allowTrailingSpace = false;
130+
break;
131+
}
132+
133+
break;
134+
135+
case SyntaxKind.PointerType when token.Parent.Parent.IsKind(SyntaxKindEx.FunctionPointerParameter):
136+
allowAtLineStart = true;
137+
allowAtLineEnd = true;
138+
allowPrecedingSpace = false;
139+
allowTrailingSpace = false;
140+
break;
141+
115142
case SyntaxKind.PointerType:
116143
allowAtLineStart = false;
117144
allowAtLineEnd = true;
118145
allowPrecedingSpace = false;
119-
var nextToken = token.GetNextToken();
146+
nextToken = token.GetNextToken();
120147
switch (nextToken.Kind())
121148
{
122149
case SyntaxKind.OpenBracketToken:

0 commit comments

Comments
 (0)