@@ -480,8 +480,7 @@ private static void DisposedIn(Parameters parameters, HashSet<string> disposals,
480
480
// disposable.Dispose();
481
481
if ( ifStatement . Condition is IsPatternExpressionSyntax isPatternExpression &&
482
482
isPatternExpression . Pattern is DeclarationPatternSyntax declarationPattern &&
483
- declarationPattern . Type is IdentifierNameSyntax identifierName &&
484
- identifierName . Identifier . Text . EndsWith ( "Disposable" , StringComparison . Ordinal ) &&
483
+ IsDisposable ( declarationPattern . Type ) &&
485
484
declarationPattern . Designation is SingleVariableDesignationSyntax singleVariableDesignation )
486
485
{
487
486
string ? member = GetIdentifier ( isPatternExpression . Expression ) ;
@@ -555,19 +554,59 @@ private static void DisposedIn(Parameters parameters, HashSet<string> disposals,
555
554
return memberAccessExpression . Name . Identifier . Text ;
556
555
}
557
556
558
- // considering cast to IDisposable, e.g. in case of explicit interface implementation of IDisposable.Dispose()
559
- else if ( expression is ParenthesizedExpressionSyntax parenthesizedExpression &&
560
- parenthesizedExpression . Expression is CastExpressionSyntax castExpression &&
561
- castExpression . Expression is IdentifierNameSyntax castIdentifierName &&
562
- castExpression . Type is IdentifierNameSyntax typeIdentifierName &&
563
- typeIdentifierName . Identifier . Text . Equals ( "IDisposable" , StringComparison . Ordinal ) )
557
+ // considering cast to I(Async)Disposable, e.g. in case of explicit interface implementation of IDisposable.Dispose()
558
+ // or in case of 'as IDisposable' or 'as IAsyncDisposable'
559
+ else if ( expression is ParenthesizedExpressionSyntax parenthesizedExpression )
564
560
{
565
- return castIdentifierName . Identifier . Text ;
561
+ IdentifierNameSyntax ? memberIdentifierName = null ;
562
+ ExpressionSyntax ? typeExpression = null ;
563
+
564
+ if ( parenthesizedExpression . Expression is CastExpressionSyntax castExpression )
565
+ {
566
+ memberIdentifierName = castExpression . Expression as IdentifierNameSyntax ;
567
+ typeExpression = castExpression . Type ;
568
+ }
569
+ else if ( parenthesizedExpression . Expression is BinaryExpressionSyntax binaryExpression &&
570
+ binaryExpression . IsKind ( SyntaxKind . AsExpression ) )
571
+ {
572
+ memberIdentifierName = binaryExpression . Left as IdentifierNameSyntax ;
573
+ typeExpression = binaryExpression . Right ;
574
+ }
575
+
576
+ if ( memberIdentifierName is not null &&
577
+ typeExpression is not null && IsDisposable ( typeExpression ) )
578
+ {
579
+ return memberIdentifierName . Identifier . Text ;
580
+ }
566
581
}
567
582
568
583
return null ;
569
584
}
570
585
586
+ private static bool IsDisposable ( ExpressionSyntax typeExpression )
587
+ {
588
+ IdentifierNameSyntax ? typeIdentifierName = null ;
589
+
590
+ if ( typeExpression is QualifiedNameSyntax qualifiedNameSyntax &&
591
+ qualifiedNameSyntax . Left is IdentifierNameSyntax systemName &&
592
+ systemName . Identifier . Text is "System" )
593
+ {
594
+ typeIdentifierName = qualifiedNameSyntax . Right as IdentifierNameSyntax ;
595
+ }
596
+ else if ( typeExpression is IdentifierNameSyntax identifierNameSyntax )
597
+ {
598
+ typeIdentifierName = identifierNameSyntax ;
599
+ }
600
+
601
+ if ( typeIdentifierName is not null &&
602
+ typeIdentifierName . Identifier . Text is "IDisposable" or "IAsyncDisposable" )
603
+ {
604
+ return true ;
605
+ }
606
+
607
+ return false ;
608
+ }
609
+
571
610
private sealed class Parameters
572
611
{
573
612
private readonly INamedTypeSymbol type ;
0 commit comments