Skip to content

Commit 67dd320

Browse files
Update 'use compund expr' to support 'field keyword'
1 parent 3638dd9 commit 67dd320

File tree

9 files changed

+96
-22
lines changed

9 files changed

+96
-22
lines changed

src/Analyzers/CSharp/Analyzers/UseCompoundAssignment/CSharpUseCompoundAssignmentDiagnosticAnalyzer.cs

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -11,14 +11,10 @@
1111
namespace Microsoft.CodeAnalysis.CSharp.UseCompoundAssignment;
1212

1313
[DiagnosticAnalyzer(LanguageNames.CSharp)]
14-
internal class CSharpUseCompoundAssignmentDiagnosticAnalyzer
15-
: AbstractUseCompoundAssignmentDiagnosticAnalyzer<SyntaxKind, AssignmentExpressionSyntax, BinaryExpressionSyntax>
14+
internal sealed class CSharpUseCompoundAssignmentDiagnosticAnalyzer()
15+
: AbstractUseCompoundAssignmentDiagnosticAnalyzer<SyntaxKind, AssignmentExpressionSyntax, BinaryExpressionSyntax>(
16+
CSharpSyntaxFacts.Instance, Utilities.Kinds)
1617
{
17-
public CSharpUseCompoundAssignmentDiagnosticAnalyzer()
18-
: base(CSharpSyntaxFacts.Instance, Utilities.Kinds)
19-
{
20-
}
21-
2218
protected override SyntaxKind GetAnalysisKind()
2319
=> SyntaxKind.SimpleAssignmentExpression;
2420

src/Analyzers/CSharp/Analyzers/UseCompoundAssignment/CSharpUseCompoundCoalesceAssignmentDiagnosticAnalyzer.cs

Lines changed: 8 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -25,17 +25,13 @@ namespace Microsoft.CodeAnalysis.CSharp.UseCompoundAssignment;
2525
/// </list>
2626
/// </summary>
2727
[DiagnosticAnalyzer(LanguageNames.CSharp)]
28-
internal class CSharpUseCompoundCoalesceAssignmentDiagnosticAnalyzer
29-
: AbstractBuiltInCodeStyleDiagnosticAnalyzer
28+
internal sealed class CSharpUseCompoundCoalesceAssignmentDiagnosticAnalyzer()
29+
: AbstractBuiltInCodeStyleDiagnosticAnalyzer(
30+
IDEDiagnosticIds.UseCoalesceCompoundAssignmentDiagnosticId,
31+
EnforceOnBuildValues.UseCoalesceCompoundAssignment,
32+
CodeStyleOptions2.PreferCompoundAssignment,
33+
new LocalizableResourceString(nameof(AnalyzersResources.Use_compound_assignment), AnalyzersResources.ResourceManager, typeof(AnalyzersResources)))
3034
{
31-
public CSharpUseCompoundCoalesceAssignmentDiagnosticAnalyzer()
32-
: base(IDEDiagnosticIds.UseCoalesceCompoundAssignmentDiagnosticId,
33-
EnforceOnBuildValues.UseCoalesceCompoundAssignment,
34-
CodeStyleOptions2.PreferCompoundAssignment,
35-
new LocalizableResourceString(nameof(AnalyzersResources.Use_compound_assignment), AnalyzersResources.ResourceManager, typeof(AnalyzersResources)))
36-
{
37-
}
38-
3935
public override DiagnosticAnalyzerCategory GetAnalyzerCategory()
4036
=> DiagnosticAnalyzerCategory.SemanticSpanAnalysis;
4137

@@ -97,7 +93,7 @@ private void AnalyzeCoalesceExpression(SyntaxNodeAnalysisContext context)
9793
coalesceExpression.OperatorToken.GetLocation(),
9894
option.Notification,
9995
context.Options,
100-
additionalLocations: ImmutableArray.Create(coalesceExpression.GetLocation()),
96+
additionalLocations: [coalesceExpression.GetLocation()],
10197
properties: null));
10298
}
10399

@@ -170,7 +166,7 @@ private void AnalyzeIfStatement(SyntaxNodeAnalysisContext context)
170166
ifStatement.IfKeyword.GetLocation(),
171167
option.Notification,
172168
context.Options,
173-
additionalLocations: ImmutableArray.Create(ifStatement.GetLocation()),
169+
additionalLocations: [ifStatement.GetLocation()],
174170
properties: null));
175171
}
176172

src/Analyzers/CSharp/Tests/UseCompoundAssignment/UseCompoundAssignmentTests.cs

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1570,4 +1570,39 @@ void M()
15701570
}
15711571
""");
15721572
}
1573+
1574+
[Fact, WorkItem("https://github.com/dotnet/roslyn/issues/76633")]
1575+
public async Task TestFieldKeyword1()
1576+
{
1577+
await new VerifyCS.Test
1578+
{
1579+
TestCode = """
1580+
public class C
1581+
{
1582+
int M
1583+
{
1584+
get
1585+
{
1586+
field [|=|] field + 10;
1587+
return 0;
1588+
}
1589+
}
1590+
}
1591+
""",
1592+
FixedCode = """
1593+
public class C
1594+
{
1595+
int M
1596+
{
1597+
get
1598+
{
1599+
field += 10;
1600+
return 0;
1601+
}
1602+
}
1603+
}
1604+
""",
1605+
LanguageVersion = LanguageVersion.Preview,
1606+
}.RunAsync();
1607+
}
15731608
}

src/Analyzers/CSharp/Tests/UseCompoundAssignment/UseCompoundCoalesceAssignmentTests.cs

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -999,4 +999,46 @@ public unsafe class C {
999999
}
10001000
""", LanguageVersion.CSharp12);
10011001
}
1002+
1003+
[Fact, WorkItem("https://github.com/dotnet/roslyn/issues/76633")]
1004+
public async Task TestFieldKeyword1()
1005+
{
1006+
await new VerifyCS.Test
1007+
{
1008+
TestCode = """
1009+
using System;
1010+
class C
1011+
{
1012+
string Goo
1013+
{
1014+
get
1015+
{
1016+
[|if|] (field is null)
1017+
{
1018+
field = "";
1019+
}
1020+
1021+
return field;
1022+
}
1023+
}
1024+
}
1025+
""",
1026+
FixedCode = """
1027+
using System;
1028+
class C
1029+
{
1030+
string Goo
1031+
{
1032+
get
1033+
{
1034+
field ??= "";
1035+
1036+
return field;
1037+
}
1038+
}
1039+
}
1040+
""",
1041+
LanguageVersion = LanguageVersion.Preview,
1042+
}.RunAsync();
1043+
}
10021044
}

src/Analyzers/Core/Analyzers/UseCompoundAssignment/UseCompoundAssignmentUtilities.cs

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -48,16 +48,15 @@ private static bool IsSideEffectFreeRecurse(
4848
bool isTopLevel, CancellationToken cancellationToken)
4949
{
5050
if (expr == null)
51-
{
5251
return false;
53-
}
5452

5553
// it basically has to be of the form "a.b.c", where all components are locals,
5654
// parameters or fields. Basically, nothing that can cause arbitrary user code
5755
// execution when being evaluated by the compiler.
5856

5957
if (syntaxFacts.IsThisExpression(expr) ||
60-
syntaxFacts.IsBaseExpression(expr))
58+
syntaxFacts.IsBaseExpression(expr) ||
59+
syntaxFacts.IsFieldExpression(expr))
6160
{
6261
// Referencing this/base like this.a.b.c causes no side effects itself.
6362
return true;

src/Workspaces/SharedUtilitiesAndExtensions/Compiler/CSharp/Services/SyntaxFacts/CSharpSyntaxKinds.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,7 @@ public int Convert<TSyntaxKind>(TSyntaxKind kind) where TSyntaxKind : struct
9797
public int CollectionInitializerExpression => (int)SyntaxKind.CollectionInitializerExpression;
9898
public int ConditionalAccessExpression => (int)SyntaxKind.ConditionalAccessExpression;
9999
public int ConditionalExpression => (int)SyntaxKind.ConditionalExpression;
100+
public int? FieldExpression => (int)SyntaxKind.FieldExpression;
100101
public int? ImplicitArrayCreationExpression => (int)SyntaxKind.ImplicitArrayCreationExpression;
101102
public int? ImplicitObjectCreationExpression => (int)SyntaxKind.ImplicitObjectCreationExpression;
102103
public int? IndexExpression => (int)SyntaxKind.IndexExpression;

src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/Services/SyntaxFacts/ISyntaxFactsExtensions.cs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -805,6 +805,9 @@ public static bool IsConditionalExpression(this ISyntaxFacts syntaxFacts, [NotNu
805805
public static bool IsConditionalAccessExpression(this ISyntaxFacts syntaxFacts, [NotNullWhen(true)] SyntaxNode? node)
806806
=> node?.RawKind == syntaxFacts.SyntaxKinds.ConditionalAccessExpression;
807807

808+
public static bool IsFieldExpression(this ISyntaxFacts syntaxFacts, [NotNullWhen(true)] SyntaxNode? node)
809+
=> node?.RawKind == syntaxFacts.SyntaxKinds.FieldExpression;
810+
808811
public static bool IsImplicitArrayCreationExpression(this ISyntaxFacts syntaxFacts, [NotNullWhen(true)] SyntaxNode? node)
809812
=> node?.RawKind == syntaxFacts.SyntaxKinds.ImplicitArrayCreationExpression;
810813

src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/Services/SyntaxFacts/ISyntaxKinds.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,7 @@ internal interface ISyntaxKinds
139139
int CollectionInitializerExpression { get; }
140140
int ConditionalAccessExpression { get; }
141141
int ConditionalExpression { get; }
142+
int? FieldExpression { get; }
142143
int? ImplicitArrayCreationExpression { get; }
143144
int? ImplicitObjectCreationExpression { get; }
144145
int? IndexExpression { get; }

src/Workspaces/SharedUtilitiesAndExtensions/Compiler/VisualBasic/Services/SyntaxFacts/VisualBasicSyntaxKinds.vb

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.LanguageService
9999
Public ReadOnly Property CollectionInitializerExpression As Integer = SyntaxKind.CollectionInitializer Implements ISyntaxKinds.CollectionInitializerExpression
100100
Public ReadOnly Property ConditionalAccessExpression As Integer = SyntaxKind.ConditionalAccessExpression Implements ISyntaxKinds.ConditionalAccessExpression
101101
Public ReadOnly Property ConditionalExpression As Integer = SyntaxKind.TernaryConditionalExpression Implements ISyntaxKinds.ConditionalExpression
102+
Public ReadOnly Property FieldExpression As Integer? Implements ISyntaxKinds.FieldExpression
102103
Public ReadOnly Property ImplicitArrayCreationExpression As Integer? Implements ISyntaxKinds.ImplicitArrayCreationExpression
103104
Public ReadOnly Property ImplicitObjectCreationExpression As Integer? Implements ISyntaxKinds.ImplicitObjectCreationExpression
104105
Public ReadOnly Property IndexExpression As Integer? Implements ISyntaxKinds.IndexExpression

0 commit comments

Comments
 (0)