private static void ComputeDiagnostics( ImmutableDictionary <AbstractLocation, DisposeAbstractValue> disposeData, ArrayBuilder <Diagnostic> notDisposedDiagnostics, ArrayBuilder <Diagnostic> mayBeNotDisposedDiagnostics, DisposeAnalysisResult disposeAnalysisResult, PointsToAnalysisResult pointsToAnalysisResult, DisposeAnalysisKind disposeAnalysisKind, bool isDisposeDataForExceptionPaths) { foreach (var kvp in disposeData) { AbstractLocation location = kvp.Key; DisposeAbstractValue disposeValue = kvp.Value; if (disposeValue.Kind == DisposeAbstractValueKind.NotDisposable || location.CreationOpt == null) { continue; } var isNotDisposed = disposeValue.Kind == DisposeAbstractValueKind.NotDisposed || (disposeValue.DisposingOrEscapingOperations.Count > 0 && disposeValue.DisposingOrEscapingOperations.All(d => d.IsInsideCatchRegion(disposeAnalysisResult.ControlFlowGraph))); var isMayBeNotDisposed = !isNotDisposed && (disposeValue.Kind == DisposeAbstractValueKind.MaybeDisposed || disposeValue.Kind == DisposeAbstractValueKind.NotDisposedOrEscaped); if (isNotDisposed || (isMayBeNotDisposed && disposeAnalysisKind.AreMayBeNotDisposedViolationsEnabled())) { var syntax = location.TryGetNodeToReportDiagnostic(pointsToAnalysisResult); if (syntax == null) { continue; } // CA2000: Call System.IDisposable.Dispose on object created by '{0}' before all references to it are out of scope. var rule = GetRule(isNotDisposed); var argument = syntax.ToString(); var diagnostic = syntax.CreateDiagnostic(rule, argument); if (isNotDisposed) { notDisposedDiagnostics.Add(diagnostic); } else { mayBeNotDisposedDiagnostics.Add(diagnostic); } } } DiagnosticDescriptor GetRule(bool isNotDisposed) { if (isNotDisposed) { return(isDisposeDataForExceptionPaths ? NotDisposedOnExceptionPathsRule : NotDisposedRule); } else { return(isDisposeDataForExceptionPaths ? MayBeDisposedOnExceptionPathsRule : MayBeDisposedRule); } } }
private static void ComputeDiagnostics( ImmutableDictionary <AbstractLocation, DisposeAbstractValue> disposeData, ArrayBuilder <Diagnostic> notDisposedDiagnostics, ArrayBuilder <Diagnostic> mayBeNotDisposedDiagnostics, DisposeAnalysisResult disposeAnalysisResult, PointsToAnalysisResult pointsToAnalysisResult, DisposeAnalysisKind disposeAnalysisKind, bool isDisposeDataForExceptionPaths) { foreach (var kvp in disposeData) { AbstractLocation location = kvp.Key; DisposeAbstractValue disposeValue = kvp.Value; if (disposeValue.Kind == DisposeAbstractValueKind.NotDisposable || location.Creation == null) { continue; } var isNotDisposed = disposeValue.Kind == DisposeAbstractValueKind.NotDisposed || (!disposeValue.DisposingOrEscapingOperations.IsEmpty && disposeValue.DisposingOrEscapingOperations.All(d => d.IsInsideCatchRegion(disposeAnalysisResult.ControlFlowGraph) && !location.GetTopOfCreationCallStackOrCreation().IsInsideCatchRegion(disposeAnalysisResult.ControlFlowGraph))); var isMayBeNotDisposed = !isNotDisposed && (disposeValue.Kind == DisposeAbstractValueKind.MaybeDisposed || disposeValue.Kind == DisposeAbstractValueKind.NotDisposedOrEscaped); if (isNotDisposed || (isMayBeNotDisposed && disposeAnalysisKind.AreMayBeNotDisposedViolationsEnabled())) { var syntax = location.TryGetNodeToReportDiagnostic(pointsToAnalysisResult); if (syntax == null) { continue; } // CA2000: Call System.IDisposable.Dispose on object created by '{0}' before all references to it are out of scope. var rule = GetRule(isNotDisposed); // Ensure that we do not include multiple lines for the object creation expression in the diagnostic message. var argument = syntax.ToString(); var indexOfNewLine = argument.IndexOf(Environment.NewLine, StringComparison.Ordinal); if (indexOfNewLine > 0) { argument = argument.Substring(0, indexOfNewLine); } var diagnostic = syntax.CreateDiagnostic(rule, argument); if (isNotDisposed) { notDisposedDiagnostics.Add(diagnostic); } else { mayBeNotDisposedDiagnostics.Add(diagnostic); } } } DiagnosticDescriptor GetRule(bool isNotDisposed) { if (isNotDisposed) { return(isDisposeDataForExceptionPaths ? NotDisposedOnExceptionPathsRule : NotDisposedRule); } else { return(isDisposeDataForExceptionPaths ? MayBeDisposedOnExceptionPathsRule : MayBeDisposedRule); } } }
public static bool AreExceptionPathsAndMayBeNotDisposedViolationsEnabled(this DisposeAnalysisKind disposeAnalysisKind) => disposeAnalysisKind.AreExceptionPathsEnabled() && disposeAnalysisKind.AreMayBeNotDisposedViolationsEnabled();