Skip to content

Commit 4a59836

Browse files
committed
Update SA1023 for function pointer types
1 parent d403d78 commit 4a59836

File tree

3 files changed

+127
-5
lines changed

3 files changed

+127
-5
lines changed

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

Lines changed: 104 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ public async Task TestFunctionPointerParameterInvalidPrecedingSpaceAsync()
3232
{
3333
var testCode = @"public class TestClass
3434
{
35-
unsafe delegate*<int *> FuncPtr;
35+
unsafe delegate*<int {|#0:*|}> FuncPtr;
3636
}
3737
";
3838

@@ -42,7 +42,7 @@ public async Task TestFunctionPointerParameterInvalidPrecedingSpaceAsync()
4242
}
4343
";
4444

45-
var expected = Diagnostic(DescriptorNotPreceded).WithLocation(3, 26);
45+
var expected = Diagnostic(DescriptorNotPreceded).WithLocation(0);
4646
await VerifyCSharpFixAsync(testCode, expected, fixedCode, CancellationToken.None).ConfigureAwait(false);
4747
}
4848

@@ -51,7 +51,7 @@ public async Task TestFunctionPointerParameterInvalidTrailingSpaceAsync()
5151
{
5252
var testCode = @"public class TestClass
5353
{
54-
unsafe delegate*<int* > FuncPtr;
54+
unsafe delegate*<int{|#0:*|} > FuncPtr;
5555
}
5656
";
5757

@@ -61,7 +61,107 @@ public async Task TestFunctionPointerParameterInvalidTrailingSpaceAsync()
6161
}
6262
";
6363

64-
var expected = Diagnostic(DescriptorNotFollowed).WithLocation(3, 25);
64+
var expected = Diagnostic(DescriptorNotFollowed).WithLocation(0);
65+
await VerifyCSharpFixAsync(testCode, expected, fixedCode, CancellationToken.None).ConfigureAwait(false);
66+
}
67+
68+
[Fact]
69+
public async Task TestFunctionPointerTypeValidSpacingAsync()
70+
{
71+
var testCode = @"public class TestClass
72+
{
73+
unsafe delegate*<int*> FuncPtr;
74+
}
75+
";
76+
77+
await VerifyCSharpDiagnosticAsync(testCode, DiagnosticResult.EmptyDiagnosticResults, CancellationToken.None).ConfigureAwait(false);
78+
}
79+
80+
[Fact]
81+
public async Task TestFunctionPointerTypeInvalidPrecedingSpaceAsync()
82+
{
83+
var testCode = @"public class TestClass
84+
{
85+
unsafe delegate {|#0:*|}<int*> FuncPtr;
86+
}
87+
";
88+
89+
var fixedCode = @"public class TestClass
90+
{
91+
unsafe delegate*<int*> FuncPtr;
92+
}
93+
";
94+
95+
var expected = Diagnostic(DescriptorNotPreceded).WithLocation(0);
96+
await VerifyCSharpFixAsync(testCode, expected, fixedCode, CancellationToken.None).ConfigureAwait(false);
97+
}
98+
99+
[Fact]
100+
public async Task TestFunctionPointerTypeInvalidTrailingSpaceAsync()
101+
{
102+
var testCode = @"public class TestClass
103+
{
104+
unsafe delegate{|#0:*|} <int*> FuncPtr;
105+
}
106+
";
107+
108+
var fixedCode = @"public class TestClass
109+
{
110+
unsafe delegate*<int*> FuncPtr;
111+
}
112+
";
113+
114+
var expected = Diagnostic(DescriptorNotFollowed).WithLocation(0);
115+
await VerifyCSharpFixAsync(testCode, expected, fixedCode, CancellationToken.None).ConfigureAwait(false);
116+
}
117+
118+
[Fact]
119+
public async Task TestFunctionPointerTypeWithCallingConventionValidSpacingAsync()
120+
{
121+
var testCode = @"public class TestClass
122+
{
123+
unsafe delegate* managed<int*> FuncPtr;
124+
}
125+
";
126+
127+
await VerifyCSharpDiagnosticAsync(testCode, DiagnosticResult.EmptyDiagnosticResults, CancellationToken.None).ConfigureAwait(false);
128+
}
129+
130+
[Fact]
131+
public async Task TestFunctionPointerTypeWithCallingConventionInvalidPrecedingSpaceAsync()
132+
{
133+
var testCode = @"public class TestClass
134+
{
135+
unsafe delegate {|#0:*|} managed<int*> FuncPtr;
136+
}
137+
";
138+
139+
var fixedCode = @"public class TestClass
140+
{
141+
unsafe delegate* managed<int*> FuncPtr;
142+
}
143+
";
144+
145+
var expected = Diagnostic(DescriptorNotPreceded).WithLocation(0);
146+
await VerifyCSharpFixAsync(testCode, expected, fixedCode, CancellationToken.None).ConfigureAwait(false);
147+
}
148+
149+
[Fact]
150+
public async Task TestFunctionPointerTypeWithCallingConventionMissingTrailingSpaceAsync()
151+
{
152+
var testCode = @"public class TestClass
153+
{
154+
unsafe delegate{|#0:*|}managed<int*> FuncPtr;
155+
}
156+
";
157+
158+
var fixedCode = @"public class TestClass
159+
{
160+
unsafe delegate* managed<int*> FuncPtr;
161+
}
162+
";
163+
164+
var expected = Diagnostic(DescriptorFollowed).WithLocation(0);
65165
await VerifyCSharpFixAsync(testCode, expected, fixedCode, CancellationToken.None).ConfigureAwait(false);
66166
}
67167
}

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

Lines changed: 3 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,7 @@ 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;
5255
public const SyntaxKind FunctionPointerParameter = (SyntaxKind)9057;
5356
public const SyntaxKind WithInitializerExpression = (SyntaxKind)9062;
5457
public const SyntaxKind RecordDeclaration = (SyntaxKind)9063;

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

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,25 @@ private static void HandleAsteriskToken(SyntaxTreeAnalysisContext context, Synta
114114
bool allowTrailingSpace;
115115
switch (token.Parent.Kind())
116116
{
117+
case SyntaxKindEx.FunctionPointerType:
118+
allowAtLineStart = true;
119+
allowAtLineEnd = true;
120+
allowPrecedingSpace = false;
121+
var nextToken = token.GetNextToken();
122+
switch (nextToken.Kind())
123+
{
124+
case SyntaxKindEx.ManagedKeyword:
125+
case SyntaxKindEx.UnmanagedKeyword:
126+
allowTrailingSpace = true;
127+
break;
128+
129+
default:
130+
allowTrailingSpace = false;
131+
break;
132+
}
133+
134+
break;
135+
117136
case SyntaxKind.PointerType when token.Parent.Parent.IsKind(SyntaxKindEx.FunctionPointerParameter):
118137
allowAtLineStart = true;
119138
allowAtLineEnd = true;
@@ -125,7 +144,7 @@ private static void HandleAsteriskToken(SyntaxTreeAnalysisContext context, Synta
125144
allowAtLineStart = false;
126145
allowAtLineEnd = true;
127146
allowPrecedingSpace = false;
128-
var nextToken = token.GetNextToken();
147+
nextToken = token.GetNextToken();
129148
switch (nextToken.Kind())
130149
{
131150
case SyntaxKind.OpenBracketToken:

0 commit comments

Comments
 (0)