private static void Handle(SyntaxNodeAnalysisContext context) { if (!context.IsExcludedFromAnalysis() && context.Node is DestructorDeclarationSyntax methodDeclaration) { if (DisposeMethod.TryFindDisposeBoolCall(methodDeclaration, context.SemanticModel, context.CancellationToken, out _, out var isDisposing) && isDisposing.Expression?.IsKind(SyntaxKind.FalseLiteralExpression) != true) { context.ReportDiagnostic(Diagnostic.Create(IDISP022DisposeFalse.Descriptor, isDisposing.GetLocation())); } using (var walker = FinalizerContextWalker.Borrow(methodDeclaration, context.SemanticModel, context.CancellationToken)) { foreach (var node in walker.UsedReferenceTypes) { context.ReportDiagnostic(Diagnostic.Create(IDISP023ReferenceTypeInFinalizerContext.Descriptor, node.GetLocation())); } } } }
private static void Handle(SyntaxNodeAnalysisContext context) { if (!context.IsExcludedFromAnalysis() && context.ContainingSymbol is IMethodSymbol method && context.Node is MethodDeclarationSyntax methodDeclaration && method.Name == "Dispose" && method.ReturnsVoid) { if (method.Parameters.Length == 0 && !method.IsStatic && method.DeclaredAccessibility == Accessibility.Public && method.ReturnsVoid && method.OverriddenMethod == null && method.GetAttributes().Length == 0) { if (!method.ExplicitInterfaceImplementations.Any() && !IsInterfaceImplementation(method)) { context.ReportDiagnostic(Diagnostic.Create(IDISP009IsIDisposable.Descriptor, methodDeclaration.Identifier.GetLocation())); } if (DisposeMethod.TryFindSuppressFinalizeCall(methodDeclaration, context.SemanticModel, context.CancellationToken, out var suppressFinalize)) { if (suppressFinalize.ArgumentList is ArgumentListSyntax argumentList && argumentList.Arguments.TrySingle(out var argument) && !argument.Expression.IsKind(SyntaxKind.ThisExpression)) { context.ReportDiagnostic(Diagnostic.Create(IDISP020SuppressFinalizeThis.Descriptor, argument.GetLocation())); } } else if (method.ContainingType.TryFindFirstMethod(x => x.MethodKind == MethodKind.Destructor, out _)) { context.ReportDiagnostic(Diagnostic.Create(IDISP018CallSuppressFinalizeWhenFinalizer.Descriptor, methodDeclaration.Identifier.GetLocation())); } else if (method.ContainingType.TryFindFirstMethod(x => DisposeMethod.IsVirtualDispose(x), out _)) { context.ReportDiagnostic(Diagnostic.Create(IDISP019CallSuppressFinalizeWhenVirtualDispose.Descriptor, methodDeclaration.Identifier.GetLocation())); } if (DisposeMethod.TryFindDisposeBoolCall(methodDeclaration, context.SemanticModel, context.CancellationToken, out _, out var isDisposing) && isDisposing.Expression?.IsKind(SyntaxKind.TrueLiteralExpression) != true) { context.ReportDiagnostic(Diagnostic.Create(IDISP021DisposeTrue.Descriptor, isDisposing.GetLocation())); } } if (method.Parameters.TrySingle(out var parameter) && parameter.Type == KnownSymbol.Boolean) { if (ShouldCallBase(method, methodDeclaration, context)) { context.ReportDiagnostic(Diagnostic.Create(IDISP010CallBaseDispose.Descriptor, methodDeclaration.Identifier.GetLocation(), parameter.Name)); } using (var walker = FinalizerContextWalker.Borrow(methodDeclaration, context.SemanticModel, context.CancellationToken)) { foreach (var node in walker.UsedReferenceTypes) { context.ReportDiagnostic(Diagnostic.Create(IDISP023ReferenceTypeInFinalizerContext.Descriptor, node.GetLocation())); } } } } }