Skip to content

Commit ce28c3c

Browse files
committed
Update SA1121 for native-sized integers
1 parent da11cbc commit ce28c3c

File tree

5 files changed

+108
-5
lines changed

5 files changed

+108
-5
lines changed

StyleCop.Analyzers/StyleCop.Analyzers.CodeFixes/ReadabilityRules/SA1121CodeFixProvider.cs

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -66,8 +66,16 @@ private static SyntaxNode ComputeReplacement(SemanticModel semanticModel, Syntax
6666

6767
var type = semanticModel.GetSymbolInfo(node, cancellationToken).Symbol as INamedTypeSymbol;
6868

69-
PredefinedTypeSyntax typeSyntax;
70-
if (!SpecialTypeHelper.TryGetPredefinedType(type.SpecialType, out typeSyntax))
69+
TypeSyntax typeSyntax;
70+
if (SpecialTypeHelper.TryGetPredefinedType(type.SpecialType, out var predefinedType))
71+
{
72+
typeSyntax = predefinedType;
73+
}
74+
else if (type.SpecialType is SpecialType.System_IntPtr or SpecialType.System_UIntPtr)
75+
{
76+
typeSyntax = SyntaxFactory.IdentifierName(type.SpecialType == SpecialType.System_IntPtr ? "nint" : "nuint");
77+
}
78+
else
7179
{
7280
return node;
7381
}

StyleCop.Analyzers/StyleCop.Analyzers.Test.CSharp11/ReadabilityRules/SA1121CSharp11UnitTests.cs

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ namespace StyleCop.Analyzers.Test.CSharp11.ReadabilityRules
55
{
66
using System.Threading;
77
using System.Threading.Tasks;
8+
using Microsoft.CodeAnalysis.Testing;
89
using StyleCop.Analyzers.Test.CSharp10.ReadabilityRules;
910
using Xunit;
1011

@@ -64,5 +65,54 @@ class TestClass
6465
FixedSources = { newSource },
6566
}.RunAsync(CancellationToken.None).ConfigureAwait(false);
6667
}
68+
69+
[Fact]
70+
[WorkItem(3969, "https://github.com/DotNetAnalyzers/StyleCopAnalyzers/issues/3969")]
71+
public async Task TestNativeSizedIntegersReportWithNet70Async()
72+
{
73+
var testCode = @"
74+
using System;
75+
76+
class TestClass
77+
{
78+
[|IntPtr|] field1;
79+
[|System.UIntPtr|] field2;
80+
}";
81+
82+
var fixedCode = @"
83+
using System;
84+
85+
class TestClass
86+
{
87+
nint field1;
88+
nuint field2;
89+
}";
90+
91+
await new CSharpTest
92+
{
93+
TestCode = testCode,
94+
FixedCode = fixedCode,
95+
}.RunAsync(CancellationToken.None).ConfigureAwait(false);
96+
}
97+
98+
[Fact]
99+
[WorkItem(3969, "https://github.com/DotNetAnalyzers/StyleCopAnalyzers/issues/3969")]
100+
public async Task TestNativeSizedIntegersDoNotReportWithNet60Async()
101+
{
102+
var testCode = @"
103+
using System;
104+
105+
class TestClass
106+
{
107+
IntPtr field1;
108+
System.UIntPtr field2;
109+
}";
110+
111+
await new CSharpTest
112+
{
113+
ReferenceAssemblies = ReferenceAssemblies.Net.Net60,
114+
TestCode = testCode,
115+
}.RunAsync(CancellationToken.None).ConfigureAwait(false);
116+
}
67117
}
68118
}

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

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

44
namespace StyleCop.Analyzers.Test.CSharp9.ReadabilityRules
55
{
6+
using System.Threading;
7+
using System.Threading.Tasks;
8+
using Microsoft.CodeAnalysis.Testing;
9+
using StyleCop.Analyzers.Lightup;
610
using StyleCop.Analyzers.Test.CSharp8.ReadabilityRules;
11+
using Xunit;
12+
using static StyleCop.Analyzers.Test.Verifiers.StyleCopCodeFixVerifier<
13+
StyleCop.Analyzers.ReadabilityRules.SA1121UseBuiltInTypeAlias,
14+
StyleCop.Analyzers.ReadabilityRules.SA1121CodeFixProvider>;
715

816
public partial class SA1121CSharp9UnitTests : SA1121CSharp8UnitTests
917
{
18+
[Fact]
19+
[WorkItem(3969, "https://github.com/DotNetAnalyzers/StyleCopAnalyzers/issues/3969")]
20+
public async Task TestNativeSizedIntegersDoNotReportAsync()
21+
{
22+
// Explicitly test with C# 9 since C# 11 and later include separate coverage where these cases do report.
23+
var testCode = @"
24+
using System;
25+
26+
class TestClass
27+
{
28+
IntPtr field1;
29+
System.UIntPtr field2;
30+
}";
31+
32+
await VerifyCSharpDiagnosticAsync(LanguageVersionEx.CSharp9, testCode, DiagnosticResult.EmptyDiagnosticResults, CancellationToken.None).ConfigureAwait(false);
33+
}
34+
35+
[Fact]
36+
[WorkItem(3969, "https://github.com/DotNetAnalyzers/StyleCopAnalyzers/issues/3969")]
37+
public async Task TestNativeSizedIntegerAliasesDoNotReportAsync()
38+
{
39+
var testCode = @"
40+
class TestClass
41+
{
42+
nint field1;
43+
nuint field2;
44+
}";
45+
46+
await VerifyCSharpDiagnosticAsync(testCode, DiagnosticResult.EmptyDiagnosticResults, CancellationToken.None).ConfigureAwait(false);
47+
}
1048
}
1149
}

StyleCop.Analyzers/StyleCop.Analyzers/ReadabilityRules/SA1121UseBuiltInTypeAlias.cs

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@
66
namespace StyleCop.Analyzers.ReadabilityRules
77
{
88
using System;
9-
using System.Collections.Concurrent;
109
using System.Collections.Immutable;
1110
using Microsoft.CodeAnalysis;
1211
using Microsoft.CodeAnalysis.CSharp;
@@ -153,17 +152,19 @@ public override void Initialize(AnalysisContext context)
153152

154153
private static void HandleCompilationStart(CompilationStartAnalysisContext context)
155154
{
156-
Analyzer analyzer = new Analyzer(context.Compilation.GetOrCreateUsingAliasCache());
155+
Analyzer analyzer = new Analyzer(context.Compilation.GetOrCreateUsingAliasCache(), context.Compilation.SupportsNativeSizedIntegers());
157156
context.RegisterSyntaxNodeAction(analyzer.HandleIdentifierNameSyntax, SyntaxKind.IdentifierName);
158157
}
159158

160159
private sealed class Analyzer
161160
{
162161
private readonly UsingAliasCache usingAliasCache;
162+
private readonly bool supportsNativeSizedIntegers;
163163

164-
public Analyzer(UsingAliasCache usingAliasCache)
164+
public Analyzer(UsingAliasCache usingAliasCache, bool supportsNativeSizedIntegers)
165165
{
166166
this.usingAliasCache = usingAliasCache;
167+
this.supportsNativeSizedIntegers = supportsNativeSizedIntegers;
167168
}
168169

169170
public void HandleIdentifierNameSyntax(SyntaxNodeAnalysisContext context, StyleCopSettings settings)
@@ -230,6 +231,7 @@ public void HandleIdentifierNameSyntax(SyntaxNodeAnalysisContext context, StyleC
230231
case nameof(UInt16):
231232
case nameof(UInt32):
232233
case nameof(UInt64):
234+
case nameof(IntPtr) or nameof(UIntPtr) when this.supportsNativeSizedIntegers:
233235
break;
234236

235237
default:
@@ -266,6 +268,7 @@ public void HandleIdentifierNameSyntax(SyntaxNodeAnalysisContext context, StyleC
266268
case SpecialType.System_UInt16:
267269
case SpecialType.System_UInt32:
268270
case SpecialType.System_UInt64:
271+
case SpecialType.System_IntPtr or SpecialType.System_UIntPtr when this.supportsNativeSizedIntegers:
269272
break;
270273

271274
default:

documentation/SA1121.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,10 @@ The following table lists each of these types in all three formats:
4747
| uint | UInt32 | System.UInt32 |
4848
| ulong | UInt64 | System.UInt64 |
4949

50+
### Native-sized integers (C# 11 and .NET 7 or later)
51+
52+
The native-sized integer aliases *nint* and *nuint* were introduced in C# 9. SA1121 considers `IntPtr`/`UIntPtr` and their aliases starting in C# 11 when targeting .NET 7 or later (detected via `System.Runtime.CompilerServices.RuntimeFeature.NumericIntPtr`). In earlier language versions or runtimes, including C# 9, these types do not trigger SA1121 diagnostics.
53+
5054
## How to fix violations
5155

5256
To fix a violation of this rule, replace the type with the built-in alias for the type.

0 commit comments

Comments
 (0)