Skip to content

Commit 540b88a

Browse files
Exclude stmts with contracts from Roslyn ctrl flow analysis #221
1 parent 6c303ea commit 540b88a

File tree

1 file changed

+35
-34
lines changed

1 file changed

+35
-34
lines changed

CheckedExceptions/CheckedExceptionsAnalyzer.ControlFlow.cs

Lines changed: 35 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,4 @@
11
using System.Collections.Immutable;
2-
using System.Linq.Expressions;
3-
using System.Net.NetworkInformation;
42

53
using Microsoft.CodeAnalysis;
64
using Microsoft.CodeAnalysis.CSharp.Syntax;
@@ -345,7 +343,6 @@ private FlowWithExceptionsResult AnalyzeBlockWithExceptions(
345343
break;
346344
}
347345

348-
349346
// Delegate analysis to the per‑statement helper
350347
var stmtResult = AnalyzeStatementWithExceptions(context, statement, settings, caughtExceptions);
351348

@@ -422,9 +419,7 @@ private FlowWithExceptionsResult AnalyzeStatementWithExceptions(
422419
if (isCatchRedundant)
423420
{
424421
// 🚩 Redundant catch-all
425-
context.ReportDiagnostic(Diagnostic.Create(
426-
RuleRedundantCatchAllClause,
427-
catchClause.CatchKeyword.GetLocation()));
422+
ReportRedundantCatchAll(context, catchClause);
428423
}
429424

430425
// The exceptions caught in this block
@@ -466,10 +461,7 @@ private FlowWithExceptionsResult AnalyzeStatementWithExceptions(
466461
if (!handlesAny)
467462
{
468463
// 🚩 Redundant typed catch
469-
context.ReportDiagnostic(Diagnostic.Create(
470-
RuleRedundantTypedCatchClause,
471-
catchClause.Declaration.Type.GetLocation(),
472-
caught.Name));
464+
ReportRedundantTypedCatchClause(context, catchClause, caught);
473465

474466
if (catchClause.Block != null)
475467
{
@@ -735,6 +727,24 @@ private FlowWithExceptionsResult AnalyzeStatementWithExceptions(
735727
return new FlowWithExceptionsResult(false,
736728
unhandled.ToImmutableHashSet());
737729

730+
case LocalDeclarationStatementSyntax localDecl
731+
when localDecl.Declaration.Variables
732+
.Any(v => v.Initializer?.Value is InvocationExpressionSyntax
733+
or ElementAccessExpressionSyntax
734+
or ObjectCreationExpressionSyntax
735+
or ImplicitObjectCreationExpressionSyntax):
736+
unhandled.UnionWith(CollectExceptionsFromStatement(context, statement, settings));
737+
return new FlowWithExceptionsResult(true, unhandled.ToImmutableHashSet());
738+
739+
case ExpressionStatementSyntax exprStmt
740+
when exprStmt.Expression.DescendantNodesAndSelf()
741+
.Any(n => n is InvocationExpressionSyntax
742+
or ElementAccessExpressionSyntax
743+
or ObjectCreationExpressionSyntax
744+
or ImplicitObjectCreationExpressionSyntax):
745+
unhandled.UnionWith(CollectExceptionsFromStatement(context, statement, settings));
746+
return new FlowWithExceptionsResult(true, unhandled.ToImmutableHashSet());
747+
738748
default:
739749
unhandled.UnionWith(CollectExceptionsFromStatement(context, statement, settings));
740750
// Fallback: assume it falls through
@@ -743,6 +753,21 @@ private FlowWithExceptionsResult AnalyzeStatementWithExceptions(
743753
}
744754
}
745755

756+
private static void ReportRedundantTypedCatchClause(SyntaxNodeAnalysisContext context, CatchClauseSyntax catchClause, INamedTypeSymbol caughtType)
757+
{
758+
context.ReportDiagnostic(Diagnostic.Create(
759+
RuleRedundantTypedCatchClause,
760+
catchClause.Declaration.Type.GetLocation(),
761+
caughtType.Name));
762+
}
763+
764+
private static void ReportRedundantCatchAll(SyntaxNodeAnalysisContext context, CatchClauseSyntax catchClause)
765+
{
766+
context.ReportDiagnostic(Diagnostic.Create(
767+
RuleRedundantCatchAllClause,
768+
catchClause.CatchKeyword.GetLocation()));
769+
}
770+
746771
private static void ReportUnreachableThrow(SyntaxNodeAnalysisContext context, SyntaxNode node)
747772
{
748773
context.ReportDiagnostic(Diagnostic.Create(
@@ -762,30 +787,6 @@ private static void ReportUnreachableCode(SyntaxNodeAnalysisContext context, Loc
762787
location));
763788
}
764789

765-
private INamedTypeSymbol? GetExceptionTypeFromNode(SyntaxNode throwNode, SemanticModel semanticModel)
766-
{
767-
switch (throwNode)
768-
{
769-
case ThrowStatementSyntax throwStmt
770-
when throwStmt.Expression is ObjectCreationExpressionSyntax obj:
771-
{
772-
var type = semanticModel.GetTypeInfo(obj.Type).Type as INamedTypeSymbol;
773-
return type;
774-
}
775-
776-
case ThrowExpressionSyntax throwExpr
777-
when throwExpr.Expression is ObjectCreationExpressionSyntax obj:
778-
{
779-
var type = semanticModel.GetTypeInfo(obj.Type).Type as INamedTypeSymbol;
780-
return type;
781-
}
782-
783-
// TODO: handle invocation and rethrow cases if needed
784-
}
785-
786-
return null;
787-
}
788-
789790
private Location? GetThrowsAttributeLocation(
790791
ISymbol symbol,
791792
INamedTypeSymbol declaredType,

0 commit comments

Comments
 (0)