Skip to content

Commit 4d92a69

Browse files
authored
Merge pull request #4059 from sharwell/function-pointers
Update for function pointers in C# 9
2 parents 313b1ea + dc28e2a commit 4d92a69

File tree

17 files changed

+267
-2
lines changed

17 files changed

+267
-2
lines changed

StyleCop.Analyzers/StyleCop.Analyzers.CodeFixes/SpacingRules/SA1018CodeFixProvider.cs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -88,8 +88,7 @@ private static async Task<Document> GetTransformedDocumentAsync(Document documen
8888
{
8989
var syntaxRoot = await document.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false);
9090

91-
var nullableType = (NullableTypeSyntax)syntaxRoot.FindNode(diagnostic.Location.SourceSpan);
92-
var questionToken = nullableType.QuestionToken;
91+
var questionToken = syntaxRoot.FindToken(diagnostic.Location.SourceSpan.Start);
9392
var precedingToken = questionToken.GetPreviousToken();
9493

9594
var triviaList = precedingToken.TrailingTrivia.AddRange(questionToken.LeadingTrivia);

StyleCop.Analyzers/StyleCop.Analyzers.Test.CSharp9/ReadabilityRules/SA1121CSharp9UnitTests.cs

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,5 +45,36 @@ class TestClass
4545

4646
await VerifyCSharpDiagnosticAsync(testCode, DiagnosticResult.EmptyDiagnosticResults, CancellationToken.None).ConfigureAwait(false);
4747
}
48+
49+
[Fact]
50+
[WorkItem(3970, "https://github.com/DotNetAnalyzers/StyleCopAnalyzers/issues/3970")]
51+
public async Task TestFunctionPointerParametersAsync()
52+
{
53+
var testCode = @"using System;
54+
public class TestClass
55+
{
56+
private unsafe delegate*<{|#0:System.Int64|}, {|#1:System.Int32|}> field1;
57+
private unsafe delegate*<{|#2:Int64|}, {|#3:Int32|}> field2;
58+
}
59+
";
60+
61+
var fixedCode = @"using System;
62+
public class TestClass
63+
{
64+
private unsafe delegate*<long, int> field1;
65+
private unsafe delegate*<long, int> field2;
66+
}
67+
";
68+
69+
var expected = new[]
70+
{
71+
Diagnostic().WithLocation(0),
72+
Diagnostic().WithLocation(1),
73+
Diagnostic().WithLocation(2),
74+
Diagnostic().WithLocation(3),
75+
};
76+
77+
await VerifyCSharpFixAsync(testCode, expected, fixedCode, CancellationToken.None).ConfigureAwait(false);
78+
}
4879
}
4980
}

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

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,33 @@ namespace StyleCop.Analyzers.Test.CSharp9.SpacingRules
1414

1515
public partial class SA1000CSharp9UnitTests : SA1000CSharp8UnitTests
1616
{
17+
[Fact]
18+
[WorkItem(3970, "https://github.com/DotNetAnalyzers/StyleCopAnalyzers/issues/3970")]
19+
public async Task TestFunctionPointerKeywordSpacingAsync()
20+
{
21+
var testCode = @"public class TestClass
22+
{
23+
private unsafe {|#0:delegate|} *<int, void> pointer1;
24+
private unsafe delegate* {|#1:unmanaged|} [Cdecl]<int, void> pointer2;
25+
}
26+
";
27+
28+
var fixedCode = @"public class TestClass
29+
{
30+
private unsafe delegate*<int, void> pointer1;
31+
private unsafe delegate* unmanaged[Cdecl]<int, void> pointer2;
32+
}
33+
";
34+
35+
var expected = new[]
36+
{
37+
Diagnostic().WithArguments("delegate", " not").WithLocation(0),
38+
Diagnostic().WithArguments("unmanaged", " not").WithLocation(1),
39+
};
40+
41+
await VerifyCSharpFixAsync(testCode, expected, fixedCode, CancellationToken.None).ConfigureAwait(false);
42+
}
43+
1744
[Fact]
1845
public async Task TestTargetTypedNewAsync()
1946
{

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

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

44
namespace StyleCop.Analyzers.Test.CSharp9.SpacingRules
55
{
6+
using System.Threading;
7+
using System.Threading.Tasks;
68
using StyleCop.Analyzers.Test.CSharp8.SpacingRules;
9+
using Xunit;
10+
11+
using static StyleCop.Analyzers.Test.Verifiers.StyleCopCodeFixVerifier<
12+
StyleCop.Analyzers.SpacingRules.SA1001CommasMustBeSpacedCorrectly,
13+
StyleCop.Analyzers.SpacingRules.TokenSpacingCodeFixProvider>;
714

815
public partial class SA1001CSharp9UnitTests : SA1001CSharp8UnitTests
916
{
17+
[Fact]
18+
[WorkItem(3970, "https://github.com/DotNetAnalyzers/StyleCopAnalyzers/issues/3970")]
19+
public async Task TestFunctionPointerParameterSpacingAsync()
20+
{
21+
var testCode = @"public class TestClass
22+
{
23+
private unsafe delegate*<int{|#0:,|}int, void> field1;
24+
private unsafe delegate*<int {|#1:,|}int, void> field2;
25+
}
26+
";
27+
28+
var fixedCode = @"public class TestClass
29+
{
30+
private unsafe delegate*<int, int, void> field1;
31+
private unsafe delegate*<int, int, void> field2;
32+
}
33+
";
34+
35+
var expected = new[]
36+
{
37+
Diagnostic().WithLocation(0).WithArguments(string.Empty, "followed"),
38+
Diagnostic().WithLocation(1).WithArguments(" not", "preceded"),
39+
Diagnostic().WithLocation(1).WithArguments(string.Empty, "followed"),
40+
};
41+
42+
await VerifyCSharpFixAsync(testCode, expected, fixedCode, CancellationToken.None).ConfigureAwait(false);
43+
}
1044
}
1145
}

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

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

44
namespace StyleCop.Analyzers.Test.CSharp9.SpacingRules
55
{
6+
using System.Threading;
7+
using System.Threading.Tasks;
68
using StyleCop.Analyzers.Test.CSharp8.SpacingRules;
9+
using Xunit;
10+
using static StyleCop.Analyzers.SpacingRules.SA1010OpeningSquareBracketsMustBeSpacedCorrectly;
11+
using static StyleCop.Analyzers.Test.Verifiers.StyleCopCodeFixVerifier<
12+
StyleCop.Analyzers.SpacingRules.SA1010OpeningSquareBracketsMustBeSpacedCorrectly,
13+
StyleCop.Analyzers.SpacingRules.TokenSpacingCodeFixProvider>;
714

815
public partial class SA1010CSharp9UnitTests : SA1010CSharp8UnitTests
916
{
17+
[Fact]
18+
[WorkItem(3970, "https://github.com/DotNetAnalyzers/StyleCopAnalyzers/issues/3970")]
19+
public async Task TestFunctionPointerCallingConventionBracketsAsync()
20+
{
21+
var testCode = @"public class TestClass
22+
{
23+
private unsafe delegate* unmanaged{|#0:[|} Cdecl]<void> field1;
24+
private unsafe delegate* unmanaged {|#1:[|}Cdecl]<void> field2;
25+
}
26+
";
27+
28+
var fixedCode = @"public class TestClass
29+
{
30+
private unsafe delegate* unmanaged[Cdecl]<void> field1;
31+
private unsafe delegate* unmanaged[Cdecl]<void> field2;
32+
}
33+
";
34+
35+
var expected = new[]
36+
{
37+
Diagnostic(DescriptorNotFollowed).WithLocation(0),
38+
Diagnostic(DescriptorNotPreceded).WithLocation(1),
39+
};
40+
41+
await VerifyCSharpFixAsync(testCode, expected, fixedCode, CancellationToken.None).ConfigureAwait(false);
42+
}
1043
}
1144
}

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

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

44
namespace StyleCop.Analyzers.Test.CSharp9.SpacingRules
55
{
6+
using System.Threading;
7+
using System.Threading.Tasks;
68
using StyleCop.Analyzers.Test.CSharp8.SpacingRules;
9+
using Xunit;
10+
using static StyleCop.Analyzers.Test.Verifiers.StyleCopCodeFixVerifier<
11+
StyleCop.Analyzers.SpacingRules.SA1014OpeningGenericBracketsMustBeSpacedCorrectly,
12+
StyleCop.Analyzers.SpacingRules.TokenSpacingCodeFixProvider>;
713

814
public partial class SA1014CSharp9UnitTests : SA1014CSharp8UnitTests
915
{
16+
[Fact]
17+
[WorkItem(3970, "https://github.com/DotNetAnalyzers/StyleCopAnalyzers/issues/3970")]
18+
public async Task TestFunctionPointerOpeningBracketSpacingAsync()
19+
{
20+
var testCode = @"public class TestClass
21+
{
22+
private unsafe delegate* {|#0:<|}int, void> field1;
23+
private unsafe delegate*{|#1:<|} int, void> field2;
24+
private unsafe delegate* unmanaged[Cdecl] {|#2:<|}int, void> field3;
25+
}
26+
";
27+
28+
var fixedCode = @"public class TestClass
29+
{
30+
private unsafe delegate*<int, void> field1;
31+
private unsafe delegate*<int, void> field2;
32+
private unsafe delegate* unmanaged[Cdecl]<int, void> field3;
33+
}
34+
";
35+
36+
var expected = new[]
37+
{
38+
Diagnostic().WithArguments("preceded").WithLocation(0),
39+
Diagnostic().WithArguments("followed").WithLocation(1),
40+
Diagnostic().WithArguments("preceded").WithLocation(2),
41+
};
42+
43+
await VerifyCSharpFixAsync(testCode, expected, fixedCode, CancellationToken.None).ConfigureAwait(false);
44+
}
1045
}
1146
}

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

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

44
namespace StyleCop.Analyzers.Test.CSharp9.SpacingRules
55
{
6+
using System.Threading;
7+
using System.Threading.Tasks;
68
using StyleCop.Analyzers.Test.CSharp8.SpacingRules;
9+
using Xunit;
10+
using static StyleCop.Analyzers.SpacingRules.SA1015ClosingGenericBracketsMustBeSpacedCorrectly;
11+
using static StyleCop.Analyzers.Test.Verifiers.StyleCopCodeFixVerifier<
12+
StyleCop.Analyzers.SpacingRules.SA1015ClosingGenericBracketsMustBeSpacedCorrectly,
13+
StyleCop.Analyzers.SpacingRules.TokenSpacingCodeFixProvider>;
714

815
public partial class SA1015CSharp9UnitTests : SA1015CSharp8UnitTests
916
{
17+
[Fact]
18+
[WorkItem(3970, "https://github.com/DotNetAnalyzers/StyleCopAnalyzers/issues/3970")]
19+
public async Task TestFunctionPointerClosingBracketSpacingAsync()
20+
{
21+
var testCode = @"public class TestClass
22+
{
23+
private unsafe delegate*<int, void {|#0:>|}field1;
24+
private unsafe delegate*<int, void {|#1:>|} field2;
25+
}
26+
";
27+
28+
var fixedCode = @"public class TestClass
29+
{
30+
private unsafe delegate*<int, void> field1;
31+
private unsafe delegate*<int, void> field2;
32+
}
33+
";
34+
35+
var expected = new[]
36+
{
37+
Diagnostic(DescriptorNotPreceded).WithLocation(0),
38+
Diagnostic(DescriptorFollowed).WithLocation(0),
39+
Diagnostic(DescriptorNotPreceded).WithLocation(1),
40+
};
41+
42+
await VerifyCSharpFixAsync(testCode, expected, fixedCode, CancellationToken.None).ConfigureAwait(false);
43+
}
1044
}
1145
}

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

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

44
namespace StyleCop.Analyzers.Test.CSharp9.SpacingRules
55
{
6+
using System.Threading;
7+
using System.Threading.Tasks;
68
using StyleCop.Analyzers.Test.CSharp8.SpacingRules;
9+
using Xunit;
10+
using static StyleCop.Analyzers.Test.Verifiers.StyleCopCodeFixVerifier<
11+
StyleCop.Analyzers.SpacingRules.SA1018NullableTypeSymbolsMustNotBePrecededBySpace,
12+
StyleCop.Analyzers.SpacingRules.SA1018CodeFixProvider>;
713

814
public partial class SA1018CSharp9UnitTests : SA1018CSharp8UnitTests
915
{
16+
[Fact]
17+
[WorkItem(3970, "https://github.com/DotNetAnalyzers/StyleCopAnalyzers/issues/3970")]
18+
public async Task TestFunctionPointerNullableTypeSpacingAsync()
19+
{
20+
var testCode = @"#nullable enable
21+
22+
public class TestClass
23+
{
24+
private unsafe delegate*<string {|#0:?|}, void> field1;
25+
private unsafe delegate*<string {|#1:?|}[], void> field2;
26+
}
27+
";
28+
29+
var fixedCode = @"#nullable enable
30+
31+
public class TestClass
32+
{
33+
private unsafe delegate*<string?, void> field1;
34+
private unsafe delegate*<string?[], void> field2;
35+
}
36+
";
37+
38+
var expected = new[]
39+
{
40+
Diagnostic().WithLocation(0),
41+
Diagnostic().WithLocation(1),
42+
};
43+
44+
await VerifyCSharpFixAsync(testCode, expected, fixedCode, CancellationToken.None).ConfigureAwait(false);
45+
}
1046
}
1147
}

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

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,8 @@ internal static class SyntaxKindEx
7070
public const SyntaxKind NullableDirectiveTrivia = (SyntaxKind)9055;
7171
public const SyntaxKind FunctionPointerType = (SyntaxKind)9056;
7272
public const SyntaxKind FunctionPointerParameter = (SyntaxKind)9057;
73+
public const SyntaxKind FunctionPointerParameterList = (SyntaxKind)9058;
74+
public const SyntaxKind FunctionPointerCallingConvention = (SyntaxKind)9059;
7375
public const SyntaxKind InitAccessorDeclaration = (SyntaxKind)9060;
7476
public const SyntaxKind WithExpression = (SyntaxKind)9061;
7577
public const SyntaxKind WithInitializerExpression = (SyntaxKind)9062;

StyleCop.Analyzers/StyleCop.Analyzers/SpacingRules/SA1000KeywordsMustBeSpacedCorrectly.cs

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,15 @@ private static void HandleSyntaxTree(SyntaxTreeAnalysisContext context)
8585
{
8686
switch (token.Kind())
8787
{
88+
case SyntaxKind.DelegateKeyword:
89+
if (token.Parent.IsKind(SyntaxKindEx.FunctionPointerType))
90+
{
91+
HandleDisallowedSpaceToken(ref context, token);
92+
break;
93+
}
94+
95+
goto default;
96+
8897
case SyntaxKindEx.AndKeyword:
8998
case SyntaxKind.AwaitKeyword:
9099
case SyntaxKind.CaseKeyword:
@@ -167,6 +176,14 @@ private static void HandleSyntaxTree(SyntaxTreeAnalysisContext context)
167176
HandleThrowKeywordToken(ref context, token);
168177
break;
169178

179+
case SyntaxKindEx.UnmanagedKeyword:
180+
if (token.Parent.IsKind(SyntaxKindEx.FunctionPointerCallingConvention))
181+
{
182+
HandleDisallowedSpaceToken(ref context, token);
183+
}
184+
185+
break;
186+
170187
default:
171188
break;
172189
}

0 commit comments

Comments
 (0)