Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 18 additions & 11 deletions src/StaticCs/EnumClosedConversionAnalyzer.cs
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@

using System.Collections.Immutable;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.CodeAnalysis.Diagnostics;
using Microsoft.CodeAnalysis.Operations;

namespace StaticCs;

Expand All @@ -24,22 +23,30 @@ public override void Initialize(AnalysisContext ctx)
{
ctx.EnableConcurrentExecution();
ctx.ConfigureGeneratedCodeAnalysis(GeneratedCodeAnalysisFlags.ReportDiagnostics);
ctx.RegisterSyntaxNodeAction(ctx =>
ctx.RegisterOperationAction(ctx =>
{
var castSyntax = (CastExpressionSyntax)ctx.Node;
var model = ctx.SemanticModel;
var targetTypeInfo = model.GetTypeInfo(castSyntax.Type);

if (targetTypeInfo.Type is { TypeKind: TypeKind.Enum } type)
var conversion = (IConversionOperation)ctx.Operation;

// Check if the conversion is from an integer type to an enum type
if (conversion.Type is { TypeKind: TypeKind.Enum } targetType &&
conversion.Operand.Type?.SpecialType is
SpecialType.System_SByte or
SpecialType.System_Byte or
SpecialType.System_Int16 or
SpecialType.System_UInt16 or
SpecialType.System_Int32 or
SpecialType.System_UInt32 or
SpecialType.System_Int64 or
SpecialType.System_UInt64)
{
foreach (var attr in type.GetAttributes())
foreach (var attr in targetType.GetAttributes())
{
if (attr.AttributeClass?.ToDisplayString() == "StaticCs.ClosedAttribute")
{
ctx.ReportDiagnostic(Diagnostic.Create(s_descriptor, castSyntax.GetLocation(), type));
ctx.ReportDiagnostic(Diagnostic.Create(s_descriptor, conversion.Syntax.GetLocation(), targetType));
}
}
}
}, SyntaxKind.CastExpression);
}, OperationKind.Conversion);
}
}
6 changes: 4 additions & 2 deletions test/test/ClosedTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ await VerifyDiagnostics<EnumClosedConversionAnalyzer>(src,
}

[Fact]
public async Task ImplicitConversionToClosedLoophole()
public async Task ImplicitConversionToClosedError()
{
var src = """
using System;
Expand All @@ -96,7 +96,9 @@ void M()
}
}
""";
await VerifyDiagnostics<EnumClosedConversionAnalyzer>(src);
await VerifyDiagnostics<EnumClosedConversionAnalyzer>(src,
// /0/Test0.cs(9,19): error STATICCS002: Integer conversions to [Closed] enum Rgb are disallowed
ClosedEnumConversion.WithSpan(9, 19, 9, 20).WithArguments("Rgb"));
}

[Fact]
Expand Down