public static DisposeAnalysisKind GetDisposeAnalysisKindOption( this AnalyzerOptions options, DiagnosticDescriptor rule, SyntaxTree tree, Compilation compilation, DisposeAnalysisKind defaultValue) => options.GetNonFlagsEnumOptionValue(EditorConfigOptionNames.DisposeAnalysisKind, rule, tree, compilation, defaultValue);
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); } } }
public static bool AreExceptionPathsEnabled(this DisposeAnalysisKind disposeAnalysisKind) { return(disposeAnalysisKind switch { DisposeAnalysisKind.NonExceptionPaths or DisposeAnalysisKind.NonExceptionPathsOnlyNotDisposed => false, _ => true, });
public static DisposeAnalysisKind GetDisposeAnalysisKindOption( this AnalyzerOptions options, DiagnosticDescriptor rule, ISymbol symbol, Compilation compilation, DisposeAnalysisKind defaultValue, CancellationToken cancellationToken) => options.GetDisposeAnalysisKindOption(rule, symbol.Locations[0].SourceTree, compilation, defaultValue, cancellationToken);
public static DisposeAnalysisKind GetDisposeAnalysisKindOption( this AnalyzerOptions options, DiagnosticDescriptor rule, ISymbol symbol, Compilation compilation, DisposeAnalysisKind defaultValue) => TryGetSyntaxTreeForOption(symbol, out var tree) ? options.GetDisposeAnalysisKindOption(rule, tree, compilation, defaultValue) : defaultValue;
public static bool AreMayBeNotDisposedViolationsEnabled(this DisposeAnalysisKind disposeAnalysisKind) { switch (disposeAnalysisKind) { case DisposeAnalysisKind.AllPathsOnlyNotDisposed: case DisposeAnalysisKind.NonExceptionPathsOnlyNotDisposed: return(false); default: return(true); } }
public static DisposeAnalysisKind GetDisposeAnalysisKindOption( this AnalyzerOptions options, DiagnosticDescriptor rule, DisposeAnalysisKind defaultValue, CancellationToken cancellationToken) => options.GetNonFlagsEnumOptionValue(EditorConfigOptionNames.DisposeAnalysisKind, rule, defaultValue, cancellationToken);
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();