diff --git a/eng/Versions.props b/eng/Versions.props index 1546badd1132137f782fd4ce7bd774f60609ec09..c08e4d5cbe73637bd129cc16b98d8e5e71652ae1 100644 --- a/eng/Versions.props +++ b/eng/Versions.props @@ -47,7 +47,7 @@ 2.0.17 $(MicrosoftCodeAnalysisTestingVersion) $(CodeStyleAnalyzerVersion) - 2.9.3-beta1.19271.2+23ca1e2d + 2.9.3-beta1.19301.2+4c8365b9 $(RoslynDiagnosticsNugetPackageVersion) 1.0.31 4.3.0 diff --git a/src/EditorFeatures/VisualBasicTest/DisposeAnalysis/DisposeObjectsBeforeLosingScopeTests.vb b/src/EditorFeatures/VisualBasicTest/DisposeAnalysis/DisposeObjectsBeforeLosingScopeTests.vb index 6f714a05ee5321a1b28e5b6f85a33c0cbaff52c2..625006b5ddb6ee6047e016b43c5daa3c4b14298a 100644 --- a/src/EditorFeatures/VisualBasicTest/DisposeAnalysis/DisposeObjectsBeforeLosingScopeTests.vb +++ b/src/EditorFeatures/VisualBasicTest/DisposeAnalysis/DisposeObjectsBeforeLosingScopeTests.vb @@ -1943,8 +1943,8 @@ End Module") End Function - Public Async Function DisposableCreationNotAssignedToAVariable_Diagnostic() As Task - Await TestDiagnosticsAsync( + Public Async Function DisposableCreationNotAssignedToAVariable_BailOut_NoDiagnostic() As Task + Await TestDiagnosticMissingAsync( "Imports System Class A @@ -1967,8 +1967,7 @@ Class Test New A(2).M() ' Error Dim x = New A(3).X End Sub|] -End Class", - Diagnostic(IDEDiagnosticIds.DisposeObjectsBeforeLosingScopeDiagnosticId, "New A(3)").WithLocation(21, 17)) +End Class") End Function diff --git a/src/Features/Core/Portable/DisposeAnalysis/DisposableFieldsShouldBeDisposedDiagnosticAnalyzer.cs b/src/Features/Core/Portable/DisposeAnalysis/DisposableFieldsShouldBeDisposedDiagnosticAnalyzer.cs index c780f3f50c6079e7829b8b79254a88a1948f0a59..c29948d0916de57c73cfee4585ad5fb9f9ef2a14 100644 --- a/src/Features/Core/Portable/DisposeAnalysis/DisposableFieldsShouldBeDisposedDiagnosticAnalyzer.cs +++ b/src/Features/Core/Portable/DisposeAnalysis/DisposableFieldsShouldBeDisposedDiagnosticAnalyzer.cs @@ -55,6 +55,7 @@ private sealed class SymbolAnalyzer private readonly ImmutableHashSet _disposableFields; private readonly ConcurrentDictionary _fieldDisposeValueMap; private readonly DisposeAnalysisHelper _disposeAnalysisHelper; + private bool _hasErrors; public SymbolAnalyzer(ImmutableHashSet disposableFields, DisposeAnalysisHelper disposeAnalysisHelper) { @@ -110,6 +111,11 @@ private void AddOrUpdateFieldDisposedValue(IFieldSymbol field, bool disposed) private void OnSymbolEnd(SymbolAnalysisContext symbolEndContext) { + if (_hasErrors) + { + return; + } + foreach (var kvp in _fieldDisposeValueMap) { IFieldSymbol field = kvp.Key; @@ -126,6 +132,13 @@ private void OnSymbolEnd(SymbolAnalysisContext symbolEndContext) [MethodImpl(MethodImplOptions.NoInlining)] private void OnOperationBlockStart(OperationBlockStartAnalysisContext operationBlockStartContext) { + if (_hasErrors) + { + return; + } + + operationBlockStartContext.RegisterOperationAction(_ => _hasErrors = true, OperationKind.Invalid); + switch (operationBlockStartContext.OwningSymbol) { case IFieldSymbol _: @@ -182,7 +195,8 @@ void AnalyzeFieldReference(OperationAnalysisContext operationContext) // Check if this is a Disposable field that is not currently being tracked. if (_fieldDisposeValueMap.ContainsKey(field) || - !_disposableFields.Contains(field)) + !_disposableFields.Contains(field) || + _hasErrors) { return; } @@ -209,6 +223,11 @@ void AnalyzeFieldReference(OperationAnalysisContext operationContext) { Interlocked.CompareExchange(ref lazyPointsToAnalysisResult, pointsToAnalysisResult, null); } + else + { + _hasErrors = true; + return; + } } PointsToAbstractValue assignedPointsToValue = lazyPointsToAnalysisResult[simpleAssignmentOperation.Value.Kind, simpleAssignmentOperation.Value.Syntax]; @@ -225,6 +244,11 @@ void AnalyzeFieldReference(OperationAnalysisContext operationContext) void AnalyzeDisposeMethod() { + if (_hasErrors) + { + return; + } + // Perform dataflow analysis to compute dispose value of disposable fields at the end of dispose method. if (_disposeAnalysisHelper.TryGetOrComputeResult(operationBlockStartContext, containingMethod, s_disposableFieldsShouldBeDisposedRule, trackInstanceFields: true, @@ -268,6 +292,10 @@ void AnalyzeDisposeMethod() } } } + else + { + _hasErrors = true; + } } } } diff --git a/src/Features/Core/Portable/DisposeAnalysis/DisposeAnalysisHelper.cs b/src/Features/Core/Portable/DisposeAnalysis/DisposeAnalysisHelper.cs index 92e4ab753599ce2d537945fadc9af3e58224e987..b01d9a7c74af8f4ad57d88c8d54d50d5b3521831 100644 --- a/src/Features/Core/Portable/DisposeAnalysis/DisposeAnalysisHelper.cs +++ b/src/Features/Core/Portable/DisposeAnalysis/DisposeAnalysisHelper.cs @@ -109,12 +109,15 @@ private void EnsureDisposableFieldsMap() if (cfg != null) { var wellKnownTypeProvider = WellKnownTypeProvider.GetOrCreate(context.Compilation); - disposeAnalysisResult = FlowAnalysis.DataFlow.DisposeAnalysis.DisposeAnalysis.GetOrComputeResult(cfg, containingMethod, wellKnownTypeProvider, + disposeAnalysisResult = FlowAnalysis.DataFlow.DisposeAnalysis.DisposeAnalysis.TryGetOrComputeResult(cfg, containingMethod, wellKnownTypeProvider, context.Options, rule, _disposeOwnershipTransferLikelyTypes, trackInstanceFields, exceptionPathsAnalysis: false, context.CancellationToken, out pointsToAnalysisResult, interproceduralAnalysisPredicateOpt: interproceduralAnalysisPredicateOpt, defaultDisposeOwnershipTransferAtConstructor: true); - return true; + if (disposeAnalysisResult != null) + { + return true; + } } } @@ -140,12 +143,15 @@ private void EnsureDisposableFieldsMap() if (cfg != null) { var wellKnownTypeProvider = WellKnownTypeProvider.GetOrCreate(context.Compilation); - disposeAnalysisResult = FlowAnalysis.DataFlow.DisposeAnalysis.DisposeAnalysis.GetOrComputeResult(cfg, containingMethod, wellKnownTypeProvider, + disposeAnalysisResult = FlowAnalysis.DataFlow.DisposeAnalysis.DisposeAnalysis.TryGetOrComputeResult(cfg, containingMethod, wellKnownTypeProvider, context.Options, rule, _disposeOwnershipTransferLikelyTypes, trackInstanceFields, exceptionPathsAnalysis: false, context.CancellationToken, out pointsToAnalysisResult, interproceduralAnalysisPredicateOpt: interproceduralAnalysisPredicateOpt, defaultDisposeOwnershipTransferAtConstructor: true); - return true; + if (disposeAnalysisResult != null) + { + return true; + } } } diff --git a/src/Features/Core/Portable/Microsoft.CodeAnalysis.Features.csproj b/src/Features/Core/Portable/Microsoft.CodeAnalysis.Features.csproj index baeafaa817c1237f3b05b82de8f31cb8f75b6506..b742add2a28cfc794f8b50b257b51ed2c733781d 100644 --- a/src/Features/Core/Portable/Microsoft.CodeAnalysis.Features.csproj +++ b/src/Features/Core/Portable/Microsoft.CodeAnalysis.Features.csproj @@ -125,7 +125,7 @@ - + diff --git a/src/Setup/DevDivInsertionFiles/DevDivInsertionFiles.csproj b/src/Setup/DevDivInsertionFiles/DevDivInsertionFiles.csproj index e4b990e07b2a2a9cdf42371ae69c5f6dedf71b08..63fa023b81887f05ec498f3e16ca5acf7db0d8b4 100644 --- a/src/Setup/DevDivInsertionFiles/DevDivInsertionFiles.csproj +++ b/src/Setup/DevDivInsertionFiles/DevDivInsertionFiles.csproj @@ -48,6 +48,7 @@ --> +