Skip to content

Commit 3e2dec8

Browse files
authored
Merge pull request #12 from delegateas/copilot/fix-11
Extend CT0002 to detect enum cast expressions with numeric literals
2 parents 465d210 + 9984e60 commit 3e2dec8

File tree

2 files changed

+133
-5
lines changed

2 files changed

+133
-5
lines changed

src/DataverseAnalyzer/EnumAssignmentAnalyzer.cs

Lines changed: 28 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -52,8 +52,20 @@ private static void AnalyzePropertyDeclaration(SyntaxNodeAnalysisContext context
5252

5353
private static void AnalyzeEnumAssignmentForProperty(SyntaxNodeAnalysisContext context, PropertyDeclarationSyntax property, ExpressionSyntax right)
5454
{
55-
// Check if the right side is a numeric literal
56-
if (right is not LiteralExpressionSyntax literal || !IsNumericLiteral(literal))
55+
LiteralExpressionSyntax literal;
56+
57+
// Check if the right side is a numeric literal or a cast expression with a numeric literal
58+
if (right is LiteralExpressionSyntax directLiteral && IsNumericLiteral(directLiteral))
59+
{
60+
literal = directLiteral;
61+
}
62+
else if (right is CastExpressionSyntax castExpr &&
63+
castExpr.Expression is LiteralExpressionSyntax castLiteral &&
64+
IsNumericLiteral(castLiteral))
65+
{
66+
literal = castLiteral;
67+
}
68+
else
5769
{
5870
return;
5971
}
@@ -88,8 +100,20 @@ private static void AnalyzeEnumAssignmentForProperty(SyntaxNodeAnalysisContext c
88100

89101
private static void AnalyzeEnumAssignment(SyntaxNodeAnalysisContext context, SyntaxNode left, ExpressionSyntax right)
90102
{
91-
// Check if the right side is a numeric literal
92-
if (right is not LiteralExpressionSyntax literal || !IsNumericLiteral(literal))
103+
LiteralExpressionSyntax literal;
104+
105+
// Check if the right side is a numeric literal or a cast expression with a numeric literal
106+
if (right is LiteralExpressionSyntax directLiteral && IsNumericLiteral(directLiteral))
107+
{
108+
literal = directLiteral;
109+
}
110+
else if (right is CastExpressionSyntax castExpr &&
111+
castExpr.Expression is LiteralExpressionSyntax castLiteral &&
112+
IsNumericLiteral(castLiteral))
113+
{
114+
literal = castLiteral;
115+
}
116+
else
93117
{
94118
return;
95119
}

tests/DataverseAnalyzer.Tests/EnumAssignmentAnalyzerTests.cs

Lines changed: 105 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -197,7 +197,7 @@ public void TestMethod()
197197
}
198198

199199
[Fact]
200-
public async Task EnumPropertyAssignedCastShouldNotTrigger()
200+
public async Task EnumPropertyAssignedCastShouldTrigger()
201201
{
202202
var source = """
203203
public enum Status
@@ -217,6 +217,110 @@ public void TestMethod()
217217
}
218218
""";
219219

220+
var diagnostics = await GetDiagnosticsAsync(source);
221+
Assert.Single(diagnostics);
222+
Assert.Equal("CT0002", diagnostics[0].Id);
223+
}
224+
225+
[Fact]
226+
public async Task EnumCastWithDataverseNamingPatternShouldTrigger()
227+
{
228+
var source = """
229+
public enum demo_Entity_statuscode
230+
{
231+
ValidStatus = 1,
232+
InvalidStatus = 2
233+
}
234+
235+
class TestClass
236+
{
237+
public demo_Entity_statuscode statuscode { get; set; }
238+
239+
public void TestMethod()
240+
{
241+
statuscode = (demo_Entity_statuscode)3;
242+
}
243+
}
244+
""";
245+
246+
var diagnostics = await GetDiagnosticsAsync(source);
247+
Assert.Single(diagnostics);
248+
Assert.Equal("CT0002", diagnostics[0].Id);
249+
}
250+
251+
[Fact]
252+
public async Task PropertyInitializerWithCastShouldTrigger()
253+
{
254+
var source = """
255+
public enum Priority
256+
{
257+
Low = 1,
258+
High = 2
259+
}
260+
261+
class TestClass
262+
{
263+
public Priority Priority { get; set; } = (Priority)1;
264+
}
265+
""";
266+
267+
var diagnostics = await GetDiagnosticsAsync(source);
268+
Assert.Single(diagnostics);
269+
Assert.Equal("CT0002", diagnostics[0].Id);
270+
}
271+
272+
[Fact]
273+
public async Task MemberAccessEnumAssignedCastShouldTrigger()
274+
{
275+
var source = """
276+
public enum AccountCategoryCode
277+
{
278+
Standard = 1,
279+
Preferred = 2
280+
}
281+
282+
class Account
283+
{
284+
public AccountCategoryCode? AccountCategoryCode { get; set; }
285+
}
286+
287+
class TestClass
288+
{
289+
public void TestMethod()
290+
{
291+
var account = new Account();
292+
account.AccountCategoryCode = (AccountCategoryCode)2;
293+
}
294+
}
295+
""";
296+
297+
var diagnostics = await GetDiagnosticsAsync(source);
298+
Assert.Single(diagnostics);
299+
Assert.Equal("CT0002", diagnostics[0].Id);
300+
}
301+
302+
[Fact]
303+
public async Task EnumCastFromVariableShouldNotTrigger()
304+
{
305+
var source = """
306+
public enum Status
307+
{
308+
Active = 1,
309+
Inactive = 2
310+
}
311+
312+
class TestClass
313+
{
314+
public Status Status { get; set; }
315+
316+
public void TestMethod()
317+
{
318+
var value = 1;
319+
Status = (Status)value;
320+
}
321+
}
322+
""";
323+
220324
var diagnostics = await GetDiagnosticsAsync(source);
221325
Assert.Empty(diagnostics);
222326
}

0 commit comments

Comments
 (0)