From e29e3a1fe3454515f2a0e132775e6f6b207ae4a4 Mon Sep 17 00:00:00 2001 From: Manish Vasani Date: Thu, 7 Nov 2019 09:42:20 -0800 Subject: [PATCH 01/28] Enable nullable on repo --- Directory.Build.props | 1 + 1 file changed, 1 insertion(+) diff --git a/Directory.Build.props b/Directory.Build.props index c1635c1e19..9eb903b60a 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -11,6 +11,7 @@ 8 16 + enable From a5b448aad5a98a78df3e917129b1f01ede7956f5 Mon Sep 17 00:00:00 2001 From: Manish Vasani Date: Thu, 7 Nov 2019 09:43:07 -0800 Subject: [PATCH 02/28] Annotate Utilities with nullable annotation --- .../DisposeObjectsBeforeLosingScope.cs | 2 +- .../Compiler/Analyzer.Utilities.projitems | 2 +- .../Compiler/BoundedCacheWithFactory.cs | 14 +- ...deAnalysisMetricData.AssemblyMetricData.cs | 2 +- ...eAnalysisMetricData.NamedTypeMetricData.cs | 2 +- ...eAnalysisMetricData.NamespaceMetricData.cs | 2 +- .../CodeMetrics/CodeAnalysisMetricData.cs | 1 - .../ComputationalComplexityMetrics.cs | 14 +- src/Utilities/Compiler/DiagnosticHelpers.cs | 9 +- .../DoNotCatchGeneralUnlessRethrown.cs | 14 +- .../Extensions/CompilationExtensions.cs | 7 +- .../Extensions/DiagnosticExtensions.cs | 6 +- .../Extensions/IEnumerableExtensions.cs | 10 +- .../IEnumerableOfIMethodSymbolExtensions.cs | 2 +- .../Extensions/IMethodSymbolExtensions.cs | 54 ++-- .../Extensions/INamedTypeSymbolExtensions.cs | 2 +- .../Extensions/IOperationExtensions.cs | 50 ++-- .../Compiler/Extensions/ISymbolExtensions.cs | 42 +-- .../Extensions/ITypeSymbolExtensions.cs | 6 +- .../Compiler/Extensions/ObjectExtensions.cs | 31 -- .../OperationBlockAnalysisContextExtension.cs | 2 +- .../Extensions/SemanticModelExtensions.cs | 2 +- .../Compiler/Extensions/UriExtensions.cs | 2 +- src/Utilities/Compiler/HashUtilities.cs | 10 +- src/Utilities/Compiler/NullableAttributes.cs | 86 ++++++ .../Options/AnalyzerOptionsExtensions.cs | 2 +- .../CategorizedAnalyzerConfigOptions.cs | 2 +- .../Compiler/Options/EditorConfigParser.cs | 4 +- .../Compiler/Options/SymbolNamesOption.cs | 4 +- .../PooledObjects/ArrayBuilder.Enumerator.cs | 2 +- .../Compiler/PooledObjects/ArrayBuilder.cs | 37 +-- .../Compiler/PooledObjects/ObjectPool.cs | 12 +- .../PooledObjects/PooledDictionary.cs | 12 +- .../Compiler/PooledObjects/PooledHashSet.cs | 10 +- .../Compiler/WellKnownTypeProvider.cs | 14 +- src/Utilities/Compiler/WordParser.cs | 14 +- src/Utilities/FlowAnalysis/BranchWithInfo.cs | 6 +- .../Extensions/BasicBlockExtensions.cs | 21 +- .../Extensions/ControlFlowGraphExtensions.cs | 3 - .../Extensions/OperationBlocksExtensions.cs | 4 +- .../CopyAnalysis.CopyAbstractValueDomain.cs | 3 - ...pyAnalysis.CopyDataFlowOperationVisitor.cs | 37 ++- ...CopyAnalysis.CoreCopyAnalysisDataDomain.cs | 2 - .../Analysis/CopyAnalysis/CopyAnalysis.cs | 6 +- .../CopyAnalysis/CopyAnalysisContext.cs | 24 +- .../Analysis/CopyAnalysis/CopyAnalysisData.cs | 7 +- .../DisposeAnalysis/DisposeAbstractValue.cs | 2 - ...poseAnalysis.DisposeAbstractValueDomain.cs | 3 - ...nalysis.DisposeDataFlowOperationVisitor.cs | 17 +- .../DisposeAnalysis/DisposeAnalysis.cs | 15 +- .../DisposeAnalysis/DisposeAnalysisContext.cs | 24 +- .../DisposeAnalysis/DisposeAnalysisHelper.cs | 25 +- .../DisposeAnalysis/DisposeAnalysisResult.cs | 4 +- ...meterValidationDataFlowOperationVisitor.cs | 2 +- .../ParameterValidationAnalysis.cs | 29 +- .../ParameterValidationAnalysisContext.cs | 20 +- .../PointsToAnalysis/PointsToAbstractValue.cs | 3 +- ...Analysis.CorePointsToAnalysisDataDomain.cs | 5 - ...sToAnalysis.PointsToAbstractValueDomain.cs | 6 - ...alysis.PointsToDataFlowOperationVisitor.cs | 47 ++-- .../PointsToAnalysis/PointsToAnalysis.cs | 12 +- .../PointsToAnalysisContext.cs | 24 +- ...sis.PropertySetDataFlowOperationVisitor.cs | 4 +- .../PropertySetAnalysis.cs | 23 +- .../PropertySetAnalysisContext.cs | 24 +- .../TaintedDataAnalysis.cs | 46 +-- .../TaintedDataAnalysisContext.cs | 28 +- .../ValueContentAbstractValue.cs | 62 ++-- ...eContentAnalysis.CoreAnalysisDataDomain.cs | 3 - ...tentAnalysis.ValueContentAbstractDomain.cs | 5 - ...is.ValueContentDataFlowOperationVisitor.cs | 8 +- .../ValueContentAnalysis.cs | 20 +- .../ValueContentAnalysisContext.cs | 28 +- .../AbstractDataFlowAnalysisContext.cs | 47 ++-- .../AbstractIndex.OperationBasedIndex.cs | 1 - .../Framework/DataFlow/AbstractLocation.cs | 32 +-- ...bstractLocationDataFlowOperationVisitor.cs | 15 +- .../DataFlow/AddressSharedEntitiesProvider.cs | 12 +- .../Framework/DataFlow/AnalysisEntity.cs | 34 +-- ...nalysisEntityBasedPredicateAnalysisData.cs | 2 +- .../AnalysisEntityDataFlowOperationVisitor.cs | 78 +++--- .../DataFlow/AnalysisEntityFactory.cs | 91 +++--- .../AnalysisEntityMapAbstractDomain.cs | 2 - .../Framework/DataFlow/ArgumentInfo.cs | 6 +- .../Framework/DataFlow/CacheBasedEquatable.cs | 8 +- .../Framework/DataFlow/ConversionInference.cs | 4 +- .../Framework/DataFlow/DataFlowAnalysis.cs | 33 ++- .../DataFlow/DataFlowAnalysisResult.cs | 32 +-- .../DataFlow/DataFlowAnalysisResultBuilder.cs | 20 +- .../DataFlow/DataFlowOperationVisitor.cs | 265 +++++++++--------- .../DataFlow/DictionaryAnalysisData.cs | 36 +-- .../DataFlow/IDataFlowAnalysisContext.cs | 4 +- .../DataFlow/IDataFlowAnalysisResult.cs | 4 +- .../DataFlow/InterproceduralAnalysisData.cs | 29 +- .../InterproceduralAnalysisPredicate.cs | 12 +- .../Framework/DataFlow/MapAbstractDomain.cs | 6 - .../PerEntityPredicatedAnalysisData.cs | 6 +- .../DataFlow/PredicatedAnalysisData.cs | 63 ++--- .../DataFlow/PredicatedAnalysisDataDomain.cs | 5 - .../Framework/DataFlow/SetAbstractDomain.cs | 7 - .../Framework/DataFlow/ThrownExceptionInfo.cs | 20 +- .../SingleThreadedConcurrentDictionary.cs | 5 +- 102 files changed, 956 insertions(+), 1012 deletions(-) delete mode 100644 src/Utilities/Compiler/Extensions/ObjectExtensions.cs create mode 100644 src/Utilities/Compiler/NullableAttributes.cs diff --git a/src/Microsoft.NetCore.Analyzers/Core/Runtime/DisposeObjectsBeforeLosingScope.cs b/src/Microsoft.NetCore.Analyzers/Core/Runtime/DisposeObjectsBeforeLosingScope.cs index e77c1d1e5e..2f06bfd5fc 100644 --- a/src/Microsoft.NetCore.Analyzers/Core/Runtime/DisposeObjectsBeforeLosingScope.cs +++ b/src/Microsoft.NetCore.Analyzers/Core/Runtime/DisposeObjectsBeforeLosingScope.cs @@ -77,7 +77,7 @@ public override void Initialize(AnalysisContext context) context.ConfigureGeneratedCodeAnalysis(GeneratedCodeAnalysisFlags.None); context.RegisterCompilationStartAction(compilationContext => { - if (!DisposeAnalysisHelper.TryGetOrCreate(compilationContext.Compilation, out DisposeAnalysisHelper disposeAnalysisHelper)) + if (!DisposeAnalysisHelper.TryGetOrCreate(compilationContext.Compilation, out var disposeAnalysisHelper)) { return; } diff --git a/src/Utilities/Compiler/Analyzer.Utilities.projitems b/src/Utilities/Compiler/Analyzer.Utilities.projitems index 9bf52e066e..64950de813 100644 --- a/src/Utilities/Compiler/Analyzer.Utilities.projitems +++ b/src/Utilities/Compiler/Analyzer.Utilities.projitems @@ -61,7 +61,6 @@ - @@ -70,6 +69,7 @@ + diff --git a/src/Utilities/Compiler/BoundedCacheWithFactory.cs b/src/Utilities/Compiler/BoundedCacheWithFactory.cs index 9a1b66c79e..9a8b2aeedb 100644 --- a/src/Utilities/Compiler/BoundedCacheWithFactory.cs +++ b/src/Utilities/Compiler/BoundedCacheWithFactory.cs @@ -15,13 +15,13 @@ internal class BoundedCacheWithFactory { // Bounded weak reference cache. // Size 5 is an arbitrarily chosen bound, which can be tuned in future as required. - private readonly List> _weakReferencedEntries - = new List> { - new WeakReference(null), - new WeakReference(null), - new WeakReference(null), - new WeakReference(null), - new WeakReference(null), + private readonly List> _weakReferencedEntries + = new List> { + new WeakReference(null), + new WeakReference(null), + new WeakReference(null), + new WeakReference(null), + new WeakReference(null), }; public TValue GetOrCreateValue(TKey key, Func valueFactory) diff --git a/src/Utilities/Compiler/CodeMetrics/CodeAnalysisMetricData.AssemblyMetricData.cs b/src/Utilities/Compiler/CodeMetrics/CodeAnalysisMetricData.AssemblyMetricData.cs index 45e4951547..991ce15b08 100644 --- a/src/Utilities/Compiler/CodeMetrics/CodeAnalysisMetricData.AssemblyMetricData.cs +++ b/src/Utilities/Compiler/CodeMetrics/CodeAnalysisMetricData.AssemblyMetricData.cs @@ -44,7 +44,7 @@ internal static async Task ComputeAsync(IAssemblySymbol asse MetricsHelper.AddCoupledNamedTypes(coupledTypesBuilder, child.CoupledNamedTypes); linesOfCode += child.SourceLines; cyclomaticComplexity += child.CyclomaticComplexity; - depthOfInheritance = Math.Max(child.DepthOfInheritance.Value, depthOfInheritance); + depthOfInheritance = Math.Max(child.DepthOfInheritance.GetValueOrDefault(), depthOfInheritance); // Compat: Maintainability index of an assembly is computed based on the values of types, not namespace children. Debug.Assert(child.Symbol.Kind == SymbolKind.Namespace); diff --git a/src/Utilities/Compiler/CodeMetrics/CodeAnalysisMetricData.NamedTypeMetricData.cs b/src/Utilities/Compiler/CodeMetrics/CodeAnalysisMetricData.NamedTypeMetricData.cs index d3f1eb0135..e3e26016ff 100644 --- a/src/Utilities/Compiler/CodeMetrics/CodeAnalysisMetricData.NamedTypeMetricData.cs +++ b/src/Utilities/Compiler/CodeMetrics/CodeAnalysisMetricData.NamedTypeMetricData.cs @@ -87,7 +87,7 @@ internal static async Task ComputeAsync(INamedTypeSymbol na ImmutableHashSet getFilteredFieldsForComplexity() { - ImmutableHashSet.Builder builderOpt = null; + ImmutableHashSet.Builder? builderOpt = null; var orderedFieldDatas = children.Where(c => c.Symbol.Kind == SymbolKind.Field).OrderBy(c => c.MaintainabilityIndex); var indexThreshold = 99; foreach (CodeAnalysisMetricData fieldData in orderedFieldDatas) diff --git a/src/Utilities/Compiler/CodeMetrics/CodeAnalysisMetricData.NamespaceMetricData.cs b/src/Utilities/Compiler/CodeMetrics/CodeAnalysisMetricData.NamespaceMetricData.cs index 7520f6b2e4..df21b1ef09 100644 --- a/src/Utilities/Compiler/CodeMetrics/CodeAnalysisMetricData.NamespaceMetricData.cs +++ b/src/Utilities/Compiler/CodeMetrics/CodeAnalysisMetricData.NamespaceMetricData.cs @@ -42,7 +42,7 @@ internal static async Task ComputeAsync(INamespaceSymbol @n MetricsHelper.AddCoupledNamedTypes(coupledTypesBuilder, child.CoupledNamedTypes); maintainabilityIndexTotal += child.MaintainabilityIndex; cyclomaticComplexity += child.CyclomaticComplexity; - depthOfInheritance = Math.Max(child.DepthOfInheritance.Value, depthOfInheritance); + depthOfInheritance = Math.Max(child.DepthOfInheritance.GetValueOrDefault(), depthOfInheritance); // Avoid double counting lines for nested types. if (child.Symbol.ContainingType == null) diff --git a/src/Utilities/Compiler/CodeMetrics/CodeAnalysisMetricData.cs b/src/Utilities/Compiler/CodeMetrics/CodeAnalysisMetricData.cs index c41bfeafd7..3816fba433 100644 --- a/src/Utilities/Compiler/CodeMetrics/CodeAnalysisMetricData.cs +++ b/src/Utilities/Compiler/CodeMetrics/CodeAnalysisMetricData.cs @@ -32,7 +32,6 @@ public abstract partial class CodeAnalysisMetricData int? depthOfInheritance, ImmutableArray children) { - Debug.Assert(symbol != null); Debug.Assert( symbol.Kind == SymbolKind.Assembly || symbol.Kind == SymbolKind.Namespace || diff --git a/src/Utilities/Compiler/CodeMetrics/ComputationalComplexityMetrics.cs b/src/Utilities/Compiler/CodeMetrics/ComputationalComplexityMetrics.cs index f205052bd4..949114aa90 100644 --- a/src/Utilities/Compiler/CodeMetrics/ComputationalComplexityMetrics.cs +++ b/src/Utilities/Compiler/CodeMetrics/ComputationalComplexityMetrics.cs @@ -89,19 +89,17 @@ internal sealed class ComputationalComplexityMetrics public static ComputationalComplexityMetrics Compute(IOperation operationBlock) { - Debug.Assert(operationBlock != null); - bool hasSymbolInitializer = false; long executableLinesOfCode = 0; long operatorUsageCounts = 0; long symbolUsageCounts = 0; long constantUsageCounts = 0; - ImmutableHashSet.Builder distinctOperatorKindsBuilder = null; - ImmutableHashSet.Builder distinctBinaryOperatorKindsBuilder = null; - ImmutableHashSet.Builder distinctUnaryOperatorKindsBuilder = null; - ImmutableHashSet.Builder distinctCaseKindsBuilder = null; - ImmutableHashSet.Builder distinctReferencedSymbolsBuilder = null; - ImmutableHashSet.Builder distinctReferencedConstantsBuilder = null; + ImmutableHashSet.Builder? distinctOperatorKindsBuilder = null; + ImmutableHashSet.Builder? distinctBinaryOperatorKindsBuilder = null; + ImmutableHashSet.Builder? distinctUnaryOperatorKindsBuilder = null; + ImmutableHashSet.Builder? distinctCaseKindsBuilder = null; + ImmutableHashSet.Builder? distinctReferencedSymbolsBuilder = null; + ImmutableHashSet.Builder? distinctReferencedConstantsBuilder = null; // Explicit user applied attribute. if (operationBlock.Kind == OperationKind.None && diff --git a/src/Utilities/Compiler/DiagnosticHelpers.cs b/src/Utilities/Compiler/DiagnosticHelpers.cs index cc2aeb4438..3c9e8cb905 100644 --- a/src/Utilities/Compiler/DiagnosticHelpers.cs +++ b/src/Utilities/Compiler/DiagnosticHelpers.cs @@ -87,7 +87,6 @@ public static bool TryConvertToUInt64(object value, SpecialType specialType, out internal static bool TryGetEnumMemberValues(INamedTypeSymbol enumType, out IList values) { - Debug.Assert(enumType != null); Debug.Assert(enumType.TypeKind == TypeKind.Enum); values = new List(); @@ -115,12 +114,10 @@ internal static bool TryGetEnumMemberValues(INamedTypeSymbol enumType, out IList public static string GetMemberName(ISymbol symbol) { // For Types - if (symbol.Kind == SymbolKind.NamedType) + if (symbol is INamedTypeSymbol namedType && + namedType.IsGenericType) { - if ((symbol as INamedTypeSymbol).IsGenericType) - { - return symbol.MetadataName; - } + return symbol.MetadataName; } // For other language constructs diff --git a/src/Utilities/Compiler/DoNotCatchGeneralUnlessRethrown.cs b/src/Utilities/Compiler/DoNotCatchGeneralUnlessRethrown.cs index 4aef2b2789..0111196e3a 100644 --- a/src/Utilities/Compiler/DoNotCatchGeneralUnlessRethrown.cs +++ b/src/Utilities/Compiler/DoNotCatchGeneralUnlessRethrown.cs @@ -17,11 +17,11 @@ namespace Analyzer.Utilities internal abstract class DoNotCatchGeneralUnlessRethrownAnalyzer : DiagnosticAnalyzer { private readonly bool _shouldCheckLambdas; - private readonly string _enablingMethodAttributeFullyQualifiedName; + private readonly string? _enablingMethodAttributeFullyQualifiedName; private bool RequiresAttributeOnMethod => !string.IsNullOrEmpty(_enablingMethodAttributeFullyQualifiedName); - protected DoNotCatchGeneralUnlessRethrownAnalyzer(bool shouldCheckLambdas, string enablingMethodAttributeFullyQualifiedName = null) + protected DoNotCatchGeneralUnlessRethrownAnalyzer(bool shouldCheckLambdas, string? enablingMethodAttributeFullyQualifiedName = null) { _shouldCheckLambdas = shouldCheckLambdas; _enablingMethodAttributeFullyQualifiedName = enablingMethodAttributeFullyQualifiedName; @@ -40,7 +40,7 @@ public override void Initialize(AnalysisContext analysisContext) analysisContext.RegisterCompilationStartAction(compilationStartAnalysisContext => { - INamedTypeSymbol requiredAttributeType = null; + INamedTypeSymbol? requiredAttributeType = null; if (RequiresAttributeOnMethod && (requiredAttributeType = GetRequiredAttributeType(compilationStartAnalysisContext.Compilation)) == null) { return; @@ -61,7 +61,7 @@ public override void Initialize(AnalysisContext analysisContext) var method = (IMethodSymbol)operationBlockAnalysisContext.OwningSymbol; - if (RequiresAttributeOnMethod && !MethodHasAttribute(method, requiredAttributeType)) + if (RequiresAttributeOnMethod && !MethodHasAttribute(method, requiredAttributeType!)) { return; } @@ -80,9 +80,9 @@ public override void Initialize(AnalysisContext analysisContext) }); } - private INamedTypeSymbol GetRequiredAttributeType(Compilation compilation) + private INamedTypeSymbol? GetRequiredAttributeType(Compilation compilation) { - return compilation.GetOrCreateTypeByMetadataName(_enablingMethodAttributeFullyQualifiedName); + return compilation.GetOrCreateTypeByMetadataName(_enablingMethodAttributeFullyQualifiedName!); } private bool MethodHasAttribute(IMethodSymbol method, INamedTypeSymbol attributeType) @@ -97,7 +97,7 @@ private static IReadOnlyCollection GetDisallowedCatchTypes(Com compilation.GetSpecialType(SpecialType.System_Object), compilation.GetOrCreateTypeByMetadataName(WellKnownTypeNames.SystemException), compilation.GetOrCreateTypeByMetadataName(WellKnownTypeNames.SystemSystemException) - }.Where(x => x != null)); + }.WhereNotNull()); } /// diff --git a/src/Utilities/Compiler/Extensions/CompilationExtensions.cs b/src/Utilities/Compiler/Extensions/CompilationExtensions.cs index 1072ef120a..f48756e146 100644 --- a/src/Utilities/Compiler/Extensions/CompilationExtensions.cs +++ b/src/Utilities/Compiler/Extensions/CompilationExtensions.cs @@ -1,4 +1,5 @@ -using System.Linq; +using System.Diagnostics.CodeAnalysis; +using System.Linq; using Microsoft.CodeAnalysis; namespace Analyzer.Utilities.Extensions @@ -14,7 +15,7 @@ internal static class CompilationExtensions /// The compilation. /// Namespace + type name, e.g. "System.Exception". /// The if found, null otherwise. - internal static INamedTypeSymbol GetOrCreateTypeByMetadataName(this Compilation compilation, string fullTypeName) => + internal static INamedTypeSymbol? GetOrCreateTypeByMetadataName(this Compilation compilation, string fullTypeName) => WellKnownTypeProvider.GetOrCreate(compilation).GetOrCreateTypeByMetadataName(fullTypeName); /// @@ -23,7 +24,7 @@ internal static class CompilationExtensions /// The compilation. /// Namespace + type name, e.g. "System.Exception". /// The if found, null otherwise. - internal static bool TryGetOrCreateTypeByMetadataName(this Compilation compilation, string fullTypeName, out INamedTypeSymbol namedTypeSymbol) => + internal static bool TryGetOrCreateTypeByMetadataName(this Compilation compilation, string fullTypeName, [NotNullWhen(returnValue: true)] out INamedTypeSymbol? namedTypeSymbol) => WellKnownTypeProvider.GetOrCreate(compilation).TryGetOrCreateTypeByMetadataName(fullTypeName, out namedTypeSymbol); } } diff --git a/src/Utilities/Compiler/Extensions/DiagnosticExtensions.cs b/src/Utilities/Compiler/Extensions/DiagnosticExtensions.cs index 1493453fd7..056d3a54c0 100644 --- a/src/Utilities/Compiler/Extensions/DiagnosticExtensions.cs +++ b/src/Utilities/Compiler/Extensions/DiagnosticExtensions.cs @@ -126,7 +126,7 @@ internal static class DiagnosticExtensions { if (!location.IsInSource) { - location = null; + location = Location.None; } return Diagnostic.Create( @@ -158,7 +158,7 @@ internal static class DiagnosticExtensions public static Diagnostic CreateDiagnostic( this IEnumerable locations, DiagnosticDescriptor rule, - ImmutableDictionary properties, + ImmutableDictionary? properties, params object[] args) { IEnumerable inSource = locations.Where(l => l.IsInSource); @@ -197,7 +197,7 @@ internal static class DiagnosticExtensions this Compilation compilation, DiagnosticDescriptor rule, Action addDiagnostic, - ImmutableDictionary properties, + ImmutableDictionary? properties, params object[] args) { var effectiveSeverity = GetEffectiveSeverity(); diff --git a/src/Utilities/Compiler/Extensions/IEnumerableExtensions.cs b/src/Utilities/Compiler/Extensions/IEnumerableExtensions.cs index cadf721077..e0e7842a3d 100644 --- a/src/Utilities/Compiler/Extensions/IEnumerableExtensions.cs +++ b/src/Utilities/Compiler/Extensions/IEnumerableExtensions.cs @@ -60,16 +60,16 @@ public static IEnumerable OrderBy(this IEnumerable source, Comparison t1.CompareTo(t2)); } - private static readonly Func s_notNullTest = x => x != null; + private static readonly Func s_notNullTest = x => x != null; - public static IEnumerable WhereNotNull(this IEnumerable source) where T : class + public static IEnumerable WhereNotNull(this IEnumerable source) where T : class { if (source == null) { return ImmutableArray.Empty; } - return source.Where((Func)s_notNullTest); + return source.Where((Func)s_notNullTest)!; } public static ImmutableArray WhereAsArray(this IEnumerable source, Func selector) @@ -95,8 +95,8 @@ public static ImmutableArray WhereAsArray(this IEnumerable(this IEnumerable collection) - where T : IDisposable + public static void Dispose(this IEnumerable collection) + where T : class, IDisposable { foreach (var item in collection) { diff --git a/src/Utilities/Compiler/Extensions/IEnumerableOfIMethodSymbolExtensions.cs b/src/Utilities/Compiler/Extensions/IEnumerableOfIMethodSymbolExtensions.cs index 7f3ef30bb5..2ae0207748 100644 --- a/src/Utilities/Compiler/Extensions/IEnumerableOfIMethodSymbolExtensions.cs +++ b/src/Utilities/Compiler/Extensions/IEnumerableOfIMethodSymbolExtensions.cs @@ -100,7 +100,7 @@ internal static class IEnumerableOfIMethodSymbolExtensions /// /// /// - public static IMethodSymbol GetFirstOrDefaultMemberWithParameterInfos(this IEnumerable members, params ParameterInfo[] expectedParameterTypesInOrder) + public static IMethodSymbol? GetFirstOrDefaultMemberWithParameterInfos(this IEnumerable members, params ParameterInfo[] expectedParameterTypesInOrder) { var expectedParameterCount = expectedParameterTypesInOrder.Length; return members?.FirstOrDefault(member => diff --git a/src/Utilities/Compiler/Extensions/IMethodSymbolExtensions.cs b/src/Utilities/Compiler/Extensions/IMethodSymbolExtensions.cs index c1deb17a4b..66fe2bd43c 100644 --- a/src/Utilities/Compiler/Extensions/IMethodSymbolExtensions.cs +++ b/src/Utilities/Compiler/Extensions/IMethodSymbolExtensions.cs @@ -145,9 +145,9 @@ public static bool IsFinalizer(this IMethodSymbol method) /// Checks if the given method is an implementation of the given interface method /// Substituted with the given typeargument. /// - public static bool IsImplementationOfInterfaceMethod(this IMethodSymbol method, ITypeSymbol typeArgument, INamedTypeSymbol interfaceType, string interfaceMethodName) + public static bool IsImplementationOfInterfaceMethod(this IMethodSymbol method, ITypeSymbol? typeArgument, INamedTypeSymbol? interfaceType, string interfaceMethodName) { - INamedTypeSymbol constructedInterface = typeArgument != null ? interfaceType?.Construct(typeArgument) : interfaceType; + INamedTypeSymbol? constructedInterface = typeArgument != null ? interfaceType?.Construct(typeArgument) : interfaceType; return constructedInterface?.GetMembers(interfaceMethodName).FirstOrDefault() is IMethodSymbol interfaceMethod && method.Equals(method.ContainingType.FindImplementationForInterfaceMember(interfaceMethod)); } @@ -157,14 +157,14 @@ public static bool IsImplementationOfInterfaceMethod(this IMethodSymbol method, /// public static bool IsDisposeImplementation(this IMethodSymbol method, Compilation compilation) { - INamedTypeSymbol iDisposable = compilation.GetOrCreateTypeByMetadataName(WellKnownTypeNames.SystemIDisposable); + INamedTypeSymbol? iDisposable = compilation.GetOrCreateTypeByMetadataName(WellKnownTypeNames.SystemIDisposable); return method.IsDisposeImplementation(iDisposable); } /// /// Checks if the given method implements or overrides an implementation of . /// - public static bool IsDisposeImplementation(this IMethodSymbol method, INamedTypeSymbol iDisposable) + public static bool IsDisposeImplementation(this IMethodSymbol? method, INamedTypeSymbol? iDisposable) { if (method == null) { @@ -221,7 +221,7 @@ private static bool HasDisposeCloseMethodSignature(this IMethodSymbol method) /// /// Checks if the given method has the signature "Task DisposeAsync()". /// - private static bool HasDisposeAsyncMethodSignature(this IMethodSymbol method, INamedTypeSymbol task) + private static bool HasDisposeAsyncMethodSignature(this IMethodSymbol method, INamedTypeSymbol? task) { return method.Name == "DisposeAsync" && method.MethodKind == MethodKind.Ordinary && @@ -232,7 +232,7 @@ private static bool HasDisposeAsyncMethodSignature(this IMethodSymbol method, IN /// /// Checks if the given method has the signature "override Task DisposeCoreAsync(bool)". /// - private static bool HasOverriddenDisposeCoreAsyncMethodSignature(this IMethodSymbol method, INamedTypeSymbol task) + private static bool HasOverriddenDisposeCoreAsyncMethodSignature(this IMethodSymbol method, INamedTypeSymbol? task) { return method.Name == "DisposeCoreAsync" && method.MethodKind == MethodKind.Ordinary && @@ -247,8 +247,8 @@ private static bool HasOverriddenDisposeCoreAsyncMethodSignature(this IMethodSym /// public static DisposeMethodKind GetDisposeMethodKind(this IMethodSymbol method, Compilation compilation) { - INamedTypeSymbol iDisposable = compilation.GetOrCreateTypeByMetadataName(WellKnownTypeNames.SystemIDisposable); - INamedTypeSymbol task = compilation.GetOrCreateTypeByMetadataName(WellKnownTypeNames.SystemThreadingTasksTask); + INamedTypeSymbol? iDisposable = compilation.GetOrCreateTypeByMetadataName(WellKnownTypeNames.SystemIDisposable); + INamedTypeSymbol? task = compilation.GetOrCreateTypeByMetadataName(WellKnownTypeNames.SystemThreadingTasksTask); return method.GetDisposeMethodKind(iDisposable, task); } @@ -257,8 +257,8 @@ public static DisposeMethodKind GetDisposeMethodKind(this IMethodSymbol method, /// public static DisposeMethodKind GetDisposeMethodKind( this IMethodSymbol method, - INamedTypeSymbol iDisposable, - INamedTypeSymbol task) + INamedTypeSymbol? iDisposable, + INamedTypeSymbol? task) { if (method.ContainingType.IsDisposable(iDisposable)) { @@ -359,13 +359,17 @@ public static bool HasOptionalParameters(this IMethodSymbol methodSymbol) return methodSymbol.Parameters.Any(p => p.IsOptional); } - public static IEnumerable GetOverloads(this IMethodSymbol method) + public static IEnumerable GetOverloads(this IMethodSymbol? method) { - foreach (var member in method?.ContainingType?.GetMembers(method.Name).OfType()) + var methods = method?.ContainingType?.GetMembers(method.Name).OfType(); + if (methods != null) { - if (!member.Equals(method)) + foreach (var member in methods) { - yield return member; + if (!member.Equals(method)) + { + yield return member; + } } } } @@ -390,7 +394,7 @@ public static bool IsCollectionAddMethod(this IMethodSymbol method, ImmutableHas /// /// The method to test. /// Task type. - public static bool IsTaskFromResultMethod(this IMethodSymbol method, INamedTypeSymbol taskType) + public static bool IsTaskFromResultMethod(this IMethodSymbol method, INamedTypeSymbol? taskType) => method.Name.Equals("FromResult", StringComparison.Ordinal) && method.ContainingType.Equals(taskType); @@ -399,7 +403,7 @@ public static bool IsTaskFromResultMethod(this IMethodSymbol method, INamedTypeS /// /// The method to test. /// Generic task type. - public static bool IsTaskConfigureAwaitMethod(this IMethodSymbol method, INamedTypeSymbol genericTaskType) + public static bool IsTaskConfigureAwaitMethod(this IMethodSymbol method, INamedTypeSymbol? genericTaskType) => method.Name.Equals("ConfigureAwait", StringComparison.Ordinal) && method.Parameters.Length == 1 && method.Parameters[0].Type.SpecialType == SpecialType.System_Boolean && @@ -411,19 +415,19 @@ public static bool IsTaskConfigureAwaitMethod(this IMethodSymbol method, INamedT /// across analyzers and analyzer callbacks to re-use the operations, semanticModel and control flow graph. /// /// Also see - private static readonly BoundedCache> s_methodToTopmostOperationBlockCache - = new BoundedCache>(); + private static readonly BoundedCache> s_methodToTopmostOperationBlockCache + = new BoundedCache>(); /// /// Returns the topmost for given . /// - public static IBlockOperation GetTopmostOperationBlock(this IMethodSymbol method, Compilation compilation, CancellationToken cancellationToken = default) + public static IBlockOperation? GetTopmostOperationBlock(this IMethodSymbol method, Compilation compilation, CancellationToken cancellationToken = default) { var methodToBlockMap = s_methodToTopmostOperationBlockCache.GetOrCreateValue(compilation); return methodToBlockMap.GetOrAdd(method, ComputeTopmostOperationBlock); // Local functions. - IBlockOperation ComputeTopmostOperationBlock(IMethodSymbol unused) + IBlockOperation? ComputeTopmostOperationBlock(IMethodSymbol unused) { if (!Equals(method.ContainingAssembly, compilation.Assembly)) { @@ -502,13 +506,13 @@ public static int GetParameterIndex(this IMethodSymbol methodSymbol, IParameterS /// the first parameter is of type and the second /// parameter inherits from or equals type. /// - public static bool HasEventHandlerSignature(this IMethodSymbol method, INamedTypeSymbol eventArgsType) + public static bool HasEventHandlerSignature(this IMethodSymbol method, INamedTypeSymbol? eventArgsType) => eventArgsType != null && method.Parameters.Length == 2 && method.Parameters[0].Type.SpecialType == SpecialType.System_Object && method.Parameters[1].Type.DerivesFrom(eventArgsType, baseTypesOnly: true); - public static bool IsLockMethod(this IMethodSymbol method, INamedTypeSymbol systemThreadingMonitor) + public static bool IsLockMethod(this IMethodSymbol method, INamedTypeSymbol? systemThreadingMonitor) { // "System.Threading.Monitor.Enter(object)" OR "System.Threading.Monitor.Enter(object, bool)" return method.Name == "Enter" && @@ -519,7 +523,7 @@ public static bool IsLockMethod(this IMethodSymbol method, INamedTypeSymbol syst } - public static bool IsInterlockedExchangeMethod(this IMethodSymbol method, INamedTypeSymbol systemThreadingInterlocked) + public static bool IsInterlockedExchangeMethod(this IMethodSymbol method, INamedTypeSymbol? systemThreadingInterlocked) { Debug.Assert(method.ContainingType.OriginalDefinition.Equals(systemThreadingInterlocked)); @@ -531,7 +535,7 @@ public static bool IsInterlockedExchangeMethod(this IMethodSymbol method, INamed method.Parameters[0].Type.Equals(method.Parameters[1].Type); } - public static bool IsInterlockedCompareExchangeMethod(this IMethodSymbol method, INamedTypeSymbol systemThreadingInterlocked) + public static bool IsInterlockedCompareExchangeMethod(this IMethodSymbol method, INamedTypeSymbol? systemThreadingInterlocked) { Debug.Assert(method.ContainingType.OriginalDefinition.Equals(systemThreadingInterlocked)); @@ -554,7 +558,7 @@ public static bool HasParameterWithDelegateType(this IMethodSymbol methodSymbol) /// /// The method /// The type has virtual method - public static bool IsOverrideOrVirtualMethodOf(this IMethodSymbol methodSymbol, INamedTypeSymbol typeSymbol) + public static bool IsOverrideOrVirtualMethodOf(this IMethodSymbol? methodSymbol, INamedTypeSymbol? typeSymbol) { if (methodSymbol == null) { diff --git a/src/Utilities/Compiler/Extensions/INamedTypeSymbolExtensions.cs b/src/Utilities/Compiler/Extensions/INamedTypeSymbolExtensions.cs index 92505b0147..72f1c24524 100644 --- a/src/Utilities/Compiler/Extensions/INamedTypeSymbolExtensions.cs +++ b/src/Utilities/Compiler/Extensions/INamedTypeSymbolExtensions.cs @@ -48,7 +48,7 @@ public static bool DerivesFromOrImplementsAnyConstructionOf(this INamedTypeSymbo throw new ArgumentException($"The type {nameof(parentType)} is not a definition; it is a constructed type", nameof(parentType)); } - for (INamedTypeSymbol baseType = type.OriginalDefinition; + for (INamedTypeSymbol? baseType = type.OriginalDefinition; baseType != null; baseType = baseType.BaseType?.OriginalDefinition) { diff --git a/src/Utilities/Compiler/Extensions/IOperationExtensions.cs b/src/Utilities/Compiler/Extensions/IOperationExtensions.cs index 5e9f1e7ade..e1a2da636b 100644 --- a/src/Utilities/Compiler/Extensions/IOperationExtensions.cs +++ b/src/Utilities/Compiler/Extensions/IOperationExtensions.cs @@ -7,6 +7,7 @@ using System.Collections.Generic; using System.Collections.Immutable; using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; using System.Linq; using System.Threading; using Analyzer.Utilities.PooledObjects; @@ -23,7 +24,7 @@ internal static partial class IOperationExtensions /// If the invocation actually involves a conversion from A to some other type, say 'C', on which B is invoked, /// then this method returns type A if is true, and C if false. /// - public static INamedTypeSymbol GetReceiverType(this IInvocationOperation invocation, Compilation compilation, bool beforeConversion, CancellationToken cancellationToken) + public static INamedTypeSymbol? GetReceiverType(this IInvocationOperation invocation, Compilation compilation, bool beforeConversion, CancellationToken cancellationToken) { if (invocation.Instance != null) { @@ -49,7 +50,7 @@ public static INamedTypeSymbol GetReceiverType(this IInvocationOperation invocat return null; } - private static INamedTypeSymbol GetReceiverType(SyntaxNode receiverSyntax, Compilation compilation, CancellationToken cancellationToken) + private static INamedTypeSymbol? GetReceiverType(SyntaxNode receiverSyntax, Compilation compilation, CancellationToken cancellationToken) { var model = compilation.GetSemanticModel(receiverSyntax.SyntaxTree); var typeInfo = model.GetTypeInfo(receiverSyntax, cancellationToken); @@ -133,7 +134,7 @@ private static bool HasConstantValue(Optional constantValue, ITypeSymbol return DiagnosticHelpers.TryConvertToUInt64(constantValue.Value, constantValueType.SpecialType, out ulong convertedValue) && convertedValue == comparand; } - public static ITypeSymbol GetElementType(this IArrayCreationOperation arrayCreation) + public static ITypeSymbol? GetElementType(this IArrayCreationOperation? arrayCreation) { return (arrayCreation?.Type as IArrayTypeSymbol)?.ElementType; } @@ -143,7 +144,7 @@ public static ITypeSymbol GetElementType(this IArrayCreationOperation arrayCreat /// public static ImmutableArray WithoutFullyImplicitOperations(this ImmutableArray operations) { - ImmutableArray.Builder builder = null; + ImmutableArray.Builder? builder = null; for (int i = 0; i < operations.Length; i++) { var operation = operations[i]; @@ -214,10 +215,10 @@ public static bool IsOperationNoneRoot(this IOperation operation) /// /// Returns the topmost containing the given . /// - public static IBlockOperation GetTopmostParentBlock(this IOperation operation) + public static IBlockOperation? GetTopmostParentBlock(this IOperation? operation) { - IOperation currentOperation = operation; - IBlockOperation topmostBlockOperation = null; + IOperation? currentOperation = operation; + IBlockOperation? topmostBlockOperation = null; while (currentOperation != null) { if (currentOperation is IBlockOperation blockOperation) @@ -237,14 +238,15 @@ public static IBlockOperation GetTopmostParentBlock(this IOperation operation) /// 2. If is non-null, it succeeds for the ancestor. /// Returns null if there is no such ancestor. /// - public static TOperation GetAncestor(this IOperation root, OperationKind ancestorKind, Func predicateOpt = null) where TOperation : IOperation + public static TOperation? GetAncestor(this IOperation root, OperationKind ancestorKind, Func? predicateOpt = null) + where TOperation : class, IOperation { if (root == null) { throw new ArgumentNullException(nameof(root)); } - IOperation ancestor = root; + var ancestor = root; do { ancestor = ancestor.Parent; @@ -264,7 +266,7 @@ public static IBlockOperation GetTopmostParentBlock(this IOperation operation) } } - public static IConditionalAccessOperation GetConditionalAccess(this IConditionalAccessInstanceOperation operation) + public static IConditionalAccessOperation? GetConditionalAccess(this IConditionalAccessInstanceOperation operation) { return operation.GetAncestor(OperationKind.ConditionalAccess, (IConditionalAccessOperation c) => c.Operation.Syntax == operation.Syntax); } @@ -278,7 +280,7 @@ public static IConditionalAccessOperation GetConditionalAccess(this IConditional /// /// PERF: Note that the parameter is to improve performance by avoiding walking the entire IOperation parent for non-initializer cases. /// - public static IOperation GetInstance(this IInstanceReferenceOperation operation, bool isInsideAnonymousObjectInitializer) + public static IOperation? GetInstance(this IInstanceReferenceOperation operation, bool isInsideAnonymousObjectInitializer) { Debug.Assert(isInsideAnonymousObjectInitializer == (operation.GetAncestor(OperationKind.AnonymousObjectCreation) != null)); @@ -314,7 +316,7 @@ public static IOperation GetInstance(this IInstanceReferenceOperation operation, /// Gets the instance for the anonymous object being created that is being referenced by . /// Otherwise, returns null /// - public static IAnonymousObjectCreationOperation GetAnonymousObjectCreation(this IPropertyReferenceOperation operation) + public static IAnonymousObjectCreationOperation? GetAnonymousObjectCreation(this IPropertyReferenceOperation operation) { if (operation.Instance == null && operation.Property.ContainingType.IsAnonymousType) @@ -347,10 +349,8 @@ public static bool HasAnyOperationDescendant(this IOperation operationBlock, Fun return operationBlock.HasAnyOperationDescendant(predicate, out _); } - public static bool HasAnyOperationDescendant(this IOperation operationBlock, Func predicate, out IOperation foundOperation) + public static bool HasAnyOperationDescendant(this IOperation operationBlock, Func predicate, [NotNullWhen(returnValue: true)] out IOperation? foundOperation) { - Debug.Assert(operationBlock != null); - Debug.Assert(predicate != null); foreach (var descendant in operationBlock.DescendantsAndSelf()) { if (predicate(descendant)) @@ -414,10 +414,10 @@ public static IOperation GetRoot(this IOperation operation) /// across analyzers and analyzer callbacks to re-use the control flow graph. /// /// Also see - private static readonly BoundedCache> s_operationToCfgCache - = new BoundedCache>(); + private static readonly BoundedCache> s_operationToCfgCache + = new BoundedCache>(); - public static bool TryGetEnclosingControlFlowGraph(this IOperation operation, out ControlFlowGraph cfg) + public static bool TryGetEnclosingControlFlowGraph(this IOperation operation, [NotNullWhen(returnValue: true)] out ControlFlowGraph? cfg) { operation = operation.GetRoot(); var operationToCfgMap = s_operationToCfgCache.GetOrCreateValue(operation.SemanticModel.Compilation); @@ -425,7 +425,7 @@ public static bool TryGetEnclosingControlFlowGraph(this IOperation operation, ou return cfg != null; } - public static ControlFlowGraph GetEnclosingControlFlowGraph(this IBlockOperation blockOperation) + public static ControlFlowGraph? GetEnclosingControlFlowGraph(this IBlockOperation blockOperation) { var success = blockOperation.TryGetEnclosingControlFlowGraph(out var cfg); Debug.Assert(success); @@ -433,7 +433,7 @@ public static ControlFlowGraph GetEnclosingControlFlowGraph(this IBlockOperation return cfg; } - private static ControlFlowGraph CreateControlFlowGraph(IOperation operation) + private static ControlFlowGraph? CreateControlFlowGraph(IOperation operation) { switch (operation) { @@ -530,7 +530,7 @@ public static bool IsWithinLambdaOrLocalFunction(this IOperation operation) => operation.GetAncestor(OperationKind.AnonymousFunction) != null || operation.GetAncestor(OperationKind.LocalFunction) != null; - public static ITypeSymbol GetPatternType(this IPatternOperation pattern) + public static ITypeSymbol? GetPatternType(this IPatternOperation pattern) { return pattern switch { @@ -555,8 +555,8 @@ public static ITypeSymbol GetPatternType(this IPatternOperation pattern) /// which contains the given tupleOperation as a descendant operation. /// public static bool TryGetParentTupleOperation(this ITupleOperation tupleOperation, - out ITupleOperation parentTupleOperation, - out IOperation elementOfParentTupleContainingTuple) + [NotNullWhen(returnValue: true)] out ITupleOperation? parentTupleOperation, + [NotNullWhen(returnValue: true)] out IOperation? elementOfParentTupleContainingTuple) { parentTupleOperation = null; elementOfParentTupleContainingTuple = null; @@ -599,7 +599,7 @@ public static SyntaxNode GetInstance(this IInvocationOperation invocationOperati return invocationOperation.IsExtensionMethodAndHasNoInstance() ? invocationOperation.Arguments[0].Value.Syntax : invocationOperation.Instance.Syntax; } - public static ISymbol GetReferencedMemberOrLocalOrParameter(this IOperation operation) + public static ISymbol? GetReferencedMemberOrLocalOrParameter(this IOperation operation) { return operation switch { @@ -677,7 +677,7 @@ public static IOperation WalkUpConversion(this IOperation operation) return operation; } - public static ITypeSymbol GetThrownExceptionType(this IThrowOperation operation) + public static ITypeSymbol? GetThrownExceptionType(this IThrowOperation operation) { var thrownObject = operation.Exception; diff --git a/src/Utilities/Compiler/Extensions/ISymbolExtensions.cs b/src/Utilities/Compiler/Extensions/ISymbolExtensions.cs index 0d24cf12d1..11f23d0d2f 100644 --- a/src/Utilities/Compiler/Extensions/ISymbolExtensions.cs +++ b/src/Utilities/Compiler/Extensions/ISymbolExtensions.cs @@ -123,10 +123,12 @@ public static bool IsConversionOperator(this ISymbol symbol) public static ImmutableArray GetParameters(this ISymbol symbol) { - return symbol.TypeSwitch( - (IMethodSymbol m) => m.Parameters, - (IPropertySymbol p) => p.Parameters, - _ => ImmutableArray.Create()); + return symbol switch + { + IMethodSymbol m => m.Parameters, + IPropertySymbol p => p.Parameters, + _ => ImmutableArray.Create() + }; } /// @@ -455,7 +457,7 @@ public static bool IsFromMscorlib(this ISymbol symbol, Compilation compilation) /// /// Get overload from the given overloads that matches given method signature + given parameter /// - public static IMethodSymbol GetMatchingOverload(this IMethodSymbol method, IEnumerable overloads, int parameterIndex, INamedTypeSymbol type, CancellationToken cancellationToken) + public static IMethodSymbol? GetMatchingOverload(this IMethodSymbol method, IEnumerable overloads, int parameterIndex, INamedTypeSymbol type, CancellationToken cancellationToken) { foreach (IMethodSymbol overload in overloads) { @@ -529,9 +531,8 @@ public static bool IsImplementationOfInterfaceMember(this ISymbol symbol, ISymbo /// /// Checks if a given symbol implements an interface member or overrides an implementation of an interface member. /// - public static bool IsOverrideOrImplementationOfInterfaceMember(this ISymbol symbol, ISymbol interfaceMember) + public static bool IsOverrideOrImplementationOfInterfaceMember(this ISymbol symbol, ISymbol? interfaceMember) { - Debug.Assert(symbol != null); if (interfaceMember == null) { return false; @@ -552,7 +553,6 @@ public static bool IsOverrideOrImplementationOfInterfaceMember(this ISymbol symb /// Requires that is true for the given . public static ISymbol GetOverriddenMember(this ISymbol symbol) { - Debug.Assert(symbol != null); Debug.Assert(symbol.IsOverride); return symbol switch @@ -570,7 +570,7 @@ public static ISymbol GetOverriddenMember(this ISymbol symbol) /// /// Checks if a given symbol implements an interface member explicitly /// - public static bool IsImplementationOfAnyExplicitInterfaceMember(this ISymbol symbol) + public static bool IsImplementationOfAnyExplicitInterfaceMember(this ISymbol? symbol) { if (symbol is IMethodSymbol methodSymbol && methodSymbol.ExplicitInterfaceImplementations.Any()) { @@ -590,7 +590,7 @@ public static bool IsImplementationOfAnyExplicitInterfaceMember(this ISymbol sym return false; } - public static ITypeSymbol GetMemberOrLocalOrParameterType(this ISymbol symbol) + public static ITypeSymbol? GetMemberOrLocalOrParameterType(this ISymbol symbol) { return symbol.Kind switch { @@ -602,23 +602,23 @@ public static ITypeSymbol GetMemberOrLocalOrParameterType(this ISymbol symbol) }; } - public static ITypeSymbol GetMemberType(this ISymbol symbol) + public static ITypeSymbol? GetMemberType(this ISymbol? symbol) { - return symbol.Kind switch + return symbol switch { - SymbolKind.Event => ((IEventSymbol)symbol).Type, + IEventSymbol eventSymbol => eventSymbol.Type, - SymbolKind.Field => ((IFieldSymbol)symbol).Type, + IFieldSymbol fieldSymbol => fieldSymbol.Type, - SymbolKind.Method => ((IMethodSymbol)symbol).ReturnType, + IMethodSymbol methodSymbol => methodSymbol.ReturnType, - SymbolKind.Property => ((IPropertySymbol)symbol).Type, + IPropertySymbol propertySymbol => propertySymbol.Type, _ => null, }; } - public static bool IsReadOnlyFieldOrProperty(this ISymbol symbol) + public static bool IsReadOnlyFieldOrProperty(this ISymbol? symbol) { return symbol switch { @@ -661,7 +661,7 @@ public static bool IsInSource(this ISymbol symbol) return symbol.Locations.Any(l => l.IsInSource); } - public static bool IsLambdaOrLocalFunction(this ISymbol symbol) + public static bool IsLambdaOrLocalFunction(this ISymbol? symbol) => (symbol as IMethodSymbol)?.IsLambdaOrLocalFunction() == true; /// @@ -669,11 +669,11 @@ public static bool IsLambdaOrLocalFunction(this ISymbol symbol) /// are optionally followed by an integer, such as '_', '_1', '_2', etc. /// These symbols can be treated as special discard symbol names. /// - public static bool IsSymbolWithSpecialDiscardName(this ISymbol symbol) + public static bool IsSymbolWithSpecialDiscardName(this ISymbol? symbol) => symbol?.Name.StartsWith("_", StringComparison.Ordinal) == true && (symbol.Name.Length == 1 || uint.TryParse(symbol.Name.Substring(1), out _)); - public static bool IsConst(this ISymbol symbol) + public static bool IsConst(this ISymbol? symbol) { return symbol switch { @@ -685,7 +685,7 @@ public static bool IsConst(this ISymbol symbol) }; } - public static bool IsReadOnly(this ISymbol symbol) + public static bool IsReadOnly(this ISymbol? symbol) { return symbol switch { diff --git a/src/Utilities/Compiler/Extensions/ITypeSymbolExtensions.cs b/src/Utilities/Compiler/Extensions/ITypeSymbolExtensions.cs index 99791a294f..1ec4c06dc0 100644 --- a/src/Utilities/Compiler/Extensions/ITypeSymbolExtensions.cs +++ b/src/Utilities/Compiler/Extensions/ITypeSymbolExtensions.cs @@ -77,7 +77,7 @@ public static IEnumerable GetBaseTypesAndThis(this ITypeSymbol type } } - public static bool DerivesFrom(this ITypeSymbol symbol, ITypeSymbol candidateBaseType, bool baseTypesOnly = false, bool checkTypeParameterConstraints = true) + public static bool DerivesFrom(this ITypeSymbol? symbol, ITypeSymbol? candidateBaseType, bool baseTypesOnly = false, bool checkTypeParameterConstraints = true) { if (candidateBaseType == null || symbol == null) { @@ -127,13 +127,13 @@ public static bool DerivesFrom(this ITypeSymbol symbol, ITypeSymbol candidateBas /// /// Indicates if the given implements . /// - public static bool ImplementsIDisposable(this ITypeSymbol type, INamedTypeSymbol iDisposable) + public static bool ImplementsIDisposable(this ITypeSymbol type, INamedTypeSymbol? iDisposable) => iDisposable != null && type.AllInterfaces.Contains(iDisposable); /// /// Indicates if the given is a reference type that implements or is type itself. /// - public static bool IsDisposable(this ITypeSymbol type, INamedTypeSymbol iDisposable) + public static bool IsDisposable(this ITypeSymbol type, INamedTypeSymbol? iDisposable) => type.IsReferenceType && (Equals(type, iDisposable) || type.ImplementsIDisposable(iDisposable)); /// diff --git a/src/Utilities/Compiler/Extensions/ObjectExtensions.cs b/src/Utilities/Compiler/Extensions/ObjectExtensions.cs deleted file mode 100644 index 3b18929d66..0000000000 --- a/src/Utilities/Compiler/Extensions/ObjectExtensions.cs +++ /dev/null @@ -1,31 +0,0 @@ -// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System; - -namespace Analyzer.Utilities.Extensions -{ - internal static class ObjectExtensions - { - public static TResult TypeSwitch(this TBaseType obj, Func matchFunc1, Func matchFunc2, Func defaultFunc = null) - where TDerivedType1 : TBaseType - where TDerivedType2 : TBaseType - { - if (obj is TDerivedType1) - { - return matchFunc1((TDerivedType1)obj); - } - else if (obj is TDerivedType2) - { - return matchFunc2((TDerivedType2)obj); - } - else if (defaultFunc != null) - { - return defaultFunc(obj); - } - else - { - return default; - } - } - } -} diff --git a/src/Utilities/Compiler/Extensions/OperationBlockAnalysisContextExtension.cs b/src/Utilities/Compiler/Extensions/OperationBlockAnalysisContextExtension.cs index 0908c41ba7..49cb645ae0 100644 --- a/src/Utilities/Compiler/Extensions/OperationBlockAnalysisContextExtension.cs +++ b/src/Utilities/Compiler/Extensions/OperationBlockAnalysisContextExtension.cs @@ -19,7 +19,7 @@ public static bool IsMethodNotImplementedOrSupported(this OperationBlockAnalysis var operationBlocks = context.OperationBlocks.WhereAsArray(operation => !operation.IsOperationNoneRoot()); - IBlockOperation methodBlock = null; + IBlockOperation? methodBlock = null; if (operationBlocks.Length == 1 && operationBlocks[0].Kind == OperationKind.Block) { methodBlock = (IBlockOperation)operationBlocks[0]; diff --git a/src/Utilities/Compiler/Extensions/SemanticModelExtensions.cs b/src/Utilities/Compiler/Extensions/SemanticModelExtensions.cs index ef832373cd..c8526f4c6f 100644 --- a/src/Utilities/Compiler/Extensions/SemanticModelExtensions.cs +++ b/src/Utilities/Compiler/Extensions/SemanticModelExtensions.cs @@ -7,7 +7,7 @@ namespace Analyzer.Utilities.Extensions { internal static class SemanticModelExtensions { - public static IOperation GetOperationWalkingUpParentChain(this SemanticModel semanticModel, SyntaxNode node, CancellationToken cancellationToken) + public static IOperation? GetOperationWalkingUpParentChain(this SemanticModel semanticModel, SyntaxNode node, CancellationToken cancellationToken) { // Walk up the parent chain to fetch the first non-null operation. do diff --git a/src/Utilities/Compiler/Extensions/UriExtensions.cs b/src/Utilities/Compiler/Extensions/UriExtensions.cs index 958996ff14..565a951ece 100644 --- a/src/Utilities/Compiler/Extensions/UriExtensions.cs +++ b/src/Utilities/Compiler/Extensions/UriExtensions.cs @@ -61,7 +61,7 @@ public static bool SymbolNameContainsUriWords(this ISymbol symbol, CancellationT return false; } - string word; + string? word; var parser = new WordParser(symbol.Name, WordParserOptions.SplitCompoundWords); while ((word = parser.NextWord()) != null) { diff --git a/src/Utilities/Compiler/HashUtilities.cs b/src/Utilities/Compiler/HashUtilities.cs index 7d5c60b7be..c3a2933bf8 100644 --- a/src/Utilities/Compiler/HashUtilities.cs +++ b/src/Utilities/Compiler/HashUtilities.cs @@ -9,7 +9,7 @@ namespace Analyzer.Utilities { internal static class HashUtilities { - internal static int GetHashCodeOrDefault(this object objectOpt) => objectOpt?.GetHashCode() ?? 0; + internal static int GetHashCodeOrDefault(this object? objectOpt) => objectOpt?.GetHashCode() ?? 0; internal static int Combine(int newKey, int currentKey) { @@ -27,7 +27,7 @@ public static int Combine(IEnumerable sequence, int length, int currentKey var hashCode = Combine(length, currentKey); foreach (var element in sequence) { - hashCode = Combine(element.GetHashCode(), hashCode); + hashCode = Combine(element.GetHashCodeOrDefault(), hashCode); } return hashCode; @@ -41,7 +41,7 @@ internal static int Combine(ImmutableStack stack, int currentKey) var stackSize = 0; foreach (var element in stack) { - hashCode = Combine(element.GetHashCode(), hashCode); + hashCode = Combine(element.GetHashCodeOrDefault(), hashCode); stackSize++; } @@ -50,13 +50,13 @@ internal static int Combine(ImmutableStack stack, int currentKey) internal static int Combine(ImmutableHashSet set) => Combine(set, 0); internal static int Combine(ImmutableHashSet set, int currentKey) - => Combine(set.Select(element => element?.GetHashCode() ?? 0).Order(), + => Combine(set.Select(element => element.GetHashCodeOrDefault()).Order(), set.Count, currentKey); internal static int Combine(ImmutableDictionary dictionary) => Combine(dictionary, 0); internal static int Combine(ImmutableDictionary dictionary, int currentKey) - => Combine(dictionary.Select(kvp => Combine(kvp.Key.GetHashCode(), kvp.Value.GetHashCode())).Order(), + => Combine(dictionary.Select(kvp => Combine(kvp.Key.GetHashCodeOrDefault(), kvp.Value.GetHashCodeOrDefault())).Order(), dictionary.Count, currentKey); } diff --git a/src/Utilities/Compiler/NullableAttributes.cs b/src/Utilities/Compiler/NullableAttributes.cs new file mode 100644 index 0000000000..58ba3c084e --- /dev/null +++ b/src/Utilities/Compiler/NullableAttributes.cs @@ -0,0 +1,86 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +// This was copied from https://github.com/dotnet/coreclr/blob/60f1e6265bd1039f023a82e0643b524d6aaf7845/src/System.Private.CoreLib/shared/System/Diagnostics/CodeAnalysis/NullableAttributes.cs +// and updated to have the scope of the attributes be internal. + +namespace System.Diagnostics.CodeAnalysis +{ + /// Specifies that null is allowed as an input even if the corresponding type disallows it. + [AttributeUsage(AttributeTargets.Field | AttributeTargets.Parameter | AttributeTargets.Property, Inherited = false)] + internal sealed class AllowNullAttribute : Attribute { } + + /// Specifies that null is disallowed as an input even if the corresponding type allows it. + [AttributeUsage(AttributeTargets.Field | AttributeTargets.Parameter | AttributeTargets.Property, Inherited = false)] + internal sealed class DisallowNullAttribute : Attribute { } + + /// Specifies that an output may be null even if the corresponding type disallows it. + [AttributeUsage(AttributeTargets.Field | AttributeTargets.Parameter | AttributeTargets.Property | AttributeTargets.ReturnValue, Inherited = false)] + internal sealed class MaybeNullAttribute : Attribute { } + + /// Specifies that an output will not be null even if the corresponding type allows it. + [AttributeUsage(AttributeTargets.Field | AttributeTargets.Parameter | AttributeTargets.Property | AttributeTargets.ReturnValue, Inherited = false)] + internal sealed class NotNullAttribute : Attribute { } + + /// Specifies that when a method returns , the parameter may be null even if the corresponding type disallows it. + [AttributeUsage(AttributeTargets.Parameter, Inherited = false)] + internal sealed class MaybeNullWhenAttribute : Attribute + { + /// Initializes the attribute with the specified return value condition. + /// + /// The return value condition. If the method returns this value, the associated parameter may be null. + /// + public MaybeNullWhenAttribute(bool returnValue) => ReturnValue = returnValue; + + /// Gets the return value condition. + public bool ReturnValue { get; } + } + + /// Specifies that when a method returns , the parameter will not be null even if the corresponding type allows it. + [AttributeUsage(AttributeTargets.Parameter, Inherited = false)] + internal sealed class NotNullWhenAttribute : Attribute + { + /// Initializes the attribute with the specified return value condition. + /// + /// The return value condition. If the method returns this value, the associated parameter will not be null. + /// + public NotNullWhenAttribute(bool returnValue) => ReturnValue = returnValue; + + /// Gets the return value condition. + public bool ReturnValue { get; } + } + + /// Specifies that the output will be non-null if the named parameter is non-null. + [AttributeUsage(AttributeTargets.Parameter | AttributeTargets.Property | AttributeTargets.ReturnValue, AllowMultiple = true, Inherited = false)] + internal sealed class NotNullIfNotNullAttribute : Attribute + { + /// Initializes the attribute with the associated parameter name. + /// + /// The associated parameter name. The output will be non-null if the argument to the parameter specified is non-null. + /// + public NotNullIfNotNullAttribute(string parameterName) => ParameterName = parameterName; + + /// Gets the associated parameter name. + public string ParameterName { get; } + } + + /// Applied to a method that will never return under any circumstance. + [AttributeUsage(AttributeTargets.Method, Inherited = false)] + internal sealed class DoesNotReturnAttribute : Attribute { } + + /// Specifies that the method will not return if the associated Boolean parameter is passed the specified value. + [AttributeUsage(AttributeTargets.Parameter, Inherited = false)] + internal sealed class DoesNotReturnIfAttribute : Attribute + { + /// Initializes the attribute with the specified parameter value. + /// + /// The condition parameter value. Code after the method will be considered unreachable by diagnostics if the argument to + /// the associated parameter matches this value. + /// + public DoesNotReturnIfAttribute(bool parameterValue) => ParameterValue = parameterValue; + + /// Gets the condition parameter value. + public bool ParameterValue { get; } + } +} diff --git a/src/Utilities/Compiler/Options/AnalyzerOptionsExtensions.cs b/src/Utilities/Compiler/Options/AnalyzerOptionsExtensions.cs index e81c4619c4..ea1fdc0d4b 100644 --- a/src/Utilities/Compiler/Options/AnalyzerOptionsExtensions.cs +++ b/src/Utilities/Compiler/Options/AnalyzerOptionsExtensions.cs @@ -158,7 +158,7 @@ static bool TryParseValue(string value, out ImmutableHashSet result) private static SymbolNamesOption GetSymbolNamesOption( this AnalyzerOptions options, string optionName, - string namePrefixOpt, + string? namePrefixOpt, DiagnosticDescriptor rule, Compilation compilation, CancellationToken cancellationToken) diff --git a/src/Utilities/Compiler/Options/CategorizedAnalyzerConfigOptions.cs b/src/Utilities/Compiler/Options/CategorizedAnalyzerConfigOptions.cs index 40ffaec2e5..8845a16e70 100644 --- a/src/Utilities/Compiler/Options/CategorizedAnalyzerConfigOptions.cs +++ b/src/Utilities/Compiler/Options/CategorizedAnalyzerConfigOptions.cs @@ -113,7 +113,7 @@ public T GetOptionValue(string optionName, DiagnosticDescriptor rule, TryPars return defaultValue; } - return (T)_computedOptionValuesMap.GetOrAdd($"{rule.Id}.{optionName}", _ => ComputeOptionValue(optionName, rule, tryParseValue, defaultValue)); + return (T)_computedOptionValuesMap.GetOrAdd($"{rule.Id}.{optionName}", _ => ComputeOptionValue(optionName, rule, tryParseValue, defaultValue)!); } private T ComputeOptionValue(string optionName, DiagnosticDescriptor rule, TryParseValue tryParseValue, T defaultValue) diff --git a/src/Utilities/Compiler/Options/EditorConfigParser.cs b/src/Utilities/Compiler/Options/EditorConfigParser.cs index e5407a8733..ca6376d50f 100644 --- a/src/Utilities/Compiler/Options/EditorConfigParser.cs +++ b/src/Utilities/Compiler/Options/EditorConfigParser.cs @@ -70,7 +70,7 @@ public static CategorizedAnalyzerConfigOptions Parse(SourceText text) Debug.Assert(!string.IsNullOrEmpty(key)); Debug.Assert(key == key.Trim()); - Debug.Assert(value == value?.Trim()); + Debug.Assert(value == value.Trim()); key = CaseInsensitiveComparison.ToLower(key); if (s_reservedKeys.Contains(key) || s_reservedValues.Contains(value)) @@ -78,7 +78,7 @@ public static CategorizedAnalyzerConfigOptions Parse(SourceText text) value = CaseInsensitiveComparison.ToLower(value); } - parsedOptions[key] = value ?? ""; + parsedOptions[key] = value; continue; } } diff --git a/src/Utilities/Compiler/Options/SymbolNamesOption.cs b/src/Utilities/Compiler/Options/SymbolNamesOption.cs index 35fe59e355..af81a1f04b 100644 --- a/src/Utilities/Compiler/Options/SymbolNamesOption.cs +++ b/src/Utilities/Compiler/Options/SymbolNamesOption.cs @@ -29,7 +29,7 @@ private SymbolNamesOption() _symbols = ImmutableHashSet.Empty; } - public static SymbolNamesOption Create(ImmutableArray symbolNames, Compilation compilation, string optionalPrefix) + public static SymbolNamesOption Create(ImmutableArray symbolNames, Compilation compilation, string? optionalPrefix) { if (symbolNames.IsEmpty) { @@ -98,7 +98,7 @@ public override bool Equals(object obj) return Equals(obj as SymbolNamesOption); } - public bool Equals(SymbolNamesOption other) + public bool Equals(SymbolNamesOption? other) { return other != null && _names.SetEquals(other._names) && diff --git a/src/Utilities/Compiler/PooledObjects/ArrayBuilder.Enumerator.cs b/src/Utilities/Compiler/PooledObjects/ArrayBuilder.Enumerator.cs index c828ac605c..c529636bc0 100644 --- a/src/Utilities/Compiler/PooledObjects/ArrayBuilder.Enumerator.cs +++ b/src/Utilities/Compiler/PooledObjects/ArrayBuilder.Enumerator.cs @@ -40,7 +40,7 @@ public void Dispose() { } - object System.Collections.IEnumerator.Current + object? System.Collections.IEnumerator.Current { get { diff --git a/src/Utilities/Compiler/PooledObjects/ArrayBuilder.cs b/src/Utilities/Compiler/PooledObjects/ArrayBuilder.cs index 00fb476c97..c24935b6ee 100644 --- a/src/Utilities/Compiler/PooledObjects/ArrayBuilder.cs +++ b/src/Utilities/Compiler/PooledObjects/ArrayBuilder.cs @@ -4,6 +4,7 @@ using System.Collections.Generic; using System.Collections.Immutable; using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; #pragma warning disable CA1710 // Rename Microsoft.CodeAnalysis.ArrayBuilder to end in 'Collection'. #pragma warning disable CA1000 // Do not declare static members on generic types @@ -47,19 +48,19 @@ public T[] A private readonly ImmutableArray.Builder _builder; - private readonly ObjectPool> _pool; + private readonly ObjectPool>? _pool; public ArrayBuilder(int size) { _builder = ImmutableArray.CreateBuilder(size); } - public ArrayBuilder() : - this(8) + public ArrayBuilder() + : this(8) { } - private ArrayBuilder(ObjectPool> pool) : - this() + private ArrayBuilder(ObjectPool>? pool) + : this() { _pool = pool; } @@ -101,11 +102,11 @@ public int Count /// Write to slot . /// Fills in unallocated slots preceding the , if any. /// - public void SetItem(int index, T value) + public void SetItem(int index, [MaybeNull]T value) { while (index > _builder.Count) { - _builder.Add(default); + _builder.Add(default!); } if (index == _builder.Count) @@ -118,12 +119,12 @@ public void SetItem(int index, T value) } } - public void Add(T item) + public void Add([MaybeNull]T item) { _builder.Add(item); } - public void Insert(int index, T item) + public void Insert(int index, [MaybeNull]T item) { _builder.Insert(index, item); } @@ -141,22 +142,22 @@ public void Clear() _builder.Clear(); } - public bool Contains(T item) + public bool Contains([MaybeNull]T item) { return _builder.Contains(item); } - public int IndexOf(T item) + public int IndexOf([MaybeNull]T item) { return _builder.IndexOf(item); } - public int IndexOf(T item, IEqualityComparer equalityComparer) + public int IndexOf([MaybeNull]T item, IEqualityComparer equalityComparer) { return _builder.IndexOf(item, 0, _builder.Count, equalityComparer); } - public int IndexOf(T item, int startIndex, int count) + public int IndexOf([MaybeNull]T item, int startIndex, int count) { return _builder.IndexOf(item, startIndex, count); } @@ -224,11 +225,13 @@ public void CopyTo(T[] array, int start) _builder.CopyTo(array, start); } + [return: MaybeNull] public T Last() { return _builder[_builder.Count - 1]; } + [return: MaybeNull] public T First() { return _builder[0]; @@ -266,7 +269,7 @@ public ImmutableArray ToDowncastedImmutable() var tmp = ArrayBuilder.GetInstance(Count); foreach (var i in _builder) { - tmp.Add((U)i); + tmp.Add((U)i!); } return tmp.ToImmutableAndFree(); @@ -372,7 +375,7 @@ internal static ObjectPool> CreatePool() internal static ObjectPool> CreatePool(int size) { - ObjectPool> pool = null; + ObjectPool>? pool = null; pool = new ObjectPool>(() => new ArrayBuilder(pool), size); return pool; } @@ -394,7 +397,7 @@ System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() return GetEnumerator(); } - internal Dictionary> ToDictionary(Func keySelector, IEqualityComparer comparer = null) + internal Dictionary> ToDictionary(Func keySelector, IEqualityComparer? comparer = null) { if (this.Count == 1) { @@ -496,7 +499,7 @@ public void ZeroInit(int count) _builder.Count = count; } - public void AddMany(T item, int count) + public void AddMany([MaybeNull] T item, int count) { for (int i = 0; i < count; i++) { diff --git a/src/Utilities/Compiler/PooledObjects/ObjectPool.cs b/src/Utilities/Compiler/PooledObjects/ObjectPool.cs index 18fde7af5f..7c3e193646 100644 --- a/src/Utilities/Compiler/PooledObjects/ObjectPool.cs +++ b/src/Utilities/Compiler/PooledObjects/ObjectPool.cs @@ -44,7 +44,7 @@ internal class ObjectPool where T : class #pragma warning disable CA1051 // Do not declare visible instance fields private struct Element { - internal T Value; + internal T? Value; } #pragma warning restore CA1051 // Do not declare visible instance fields #pragma warning restore CA1815 // Override equals and operator equals on value types @@ -57,7 +57,7 @@ private struct Element // Storage for the pool objects. The first item is stored in a dedicated field because we // expect to be able to satisfy most requests from it. - private T _firstItem; + private T? _firstItem; private readonly Element[] _items; // factory is stored for the lifetime of the pool. We will call this only when pool needs to @@ -137,7 +137,7 @@ internal T Allocate() // Note that the initial read is optimistically not synchronized. That is intentional. // We will interlock only when we have a candidate. in a worst case we may miss some // recently returned objects. Not a big deal. - T inst = _firstItem; + T? inst = _firstItem; if (inst == null || inst != Interlocked.CompareExchange(ref _firstItem, null, inst)) { inst = AllocateSlow(); @@ -164,7 +164,7 @@ private T AllocateSlow() // Note that the initial read is optimistically not synchronized. That is intentional. // We will interlock only when we have a candidate. in a worst case we may miss some // recently returned objects. Not a big deal. - T inst = items[i].Value; + T? inst = items[i].Value; if (inst != null) { if (inst == Interlocked.CompareExchange(ref items[i].Value, null, inst)) @@ -228,7 +228,7 @@ private void FreeSlow(T obj) /// return a larger array to the pool than was originally allocated. /// [Conditional("DEBUG")] - internal static void ForgetTrackedObject(T old, T replacement = null) + internal static void ForgetTrackedObject(T old, T? replacement = null) { #if DETECT_LEAKS LeakTracker tracker; @@ -263,8 +263,6 @@ private static object CaptureStackTrace() [Conditional("DEBUG")] private void Validate(object obj) { - Debug.Assert(obj != null, "freeing null?"); - Debug.Assert(_firstItem != obj, "freeing twice?"); var items = _items; diff --git a/src/Utilities/Compiler/PooledObjects/PooledDictionary.cs b/src/Utilities/Compiler/PooledObjects/PooledDictionary.cs index c1d1c0439b..69b7592fed 100644 --- a/src/Utilities/Compiler/PooledObjects/PooledDictionary.cs +++ b/src/Utilities/Compiler/PooledObjects/PooledDictionary.cs @@ -14,9 +14,9 @@ namespace Analyzer.Utilities.PooledObjects // NOTE: these dictionaries always have the default comparer. internal sealed class PooledDictionary : Dictionary, IDisposable { - private readonly ObjectPool> _pool; + private readonly ObjectPool>? _pool; - private PooledDictionary(ObjectPool> pool, IEqualityComparer keyComparer) + private PooledDictionary(ObjectPool>? pool, IEqualityComparer? keyComparer) : base(keyComparer) { _pool = pool; @@ -53,14 +53,14 @@ public void Free() = new ConcurrentDictionary, ObjectPool>>(); // if someone needs to create a pool; - public static ObjectPool> CreatePool(IEqualityComparer keyComparer = null) + public static ObjectPool> CreatePool(IEqualityComparer? keyComparer = null) { - ObjectPool> pool = null; + ObjectPool>? pool = null; pool = new ObjectPool>(() => new PooledDictionary(pool, keyComparer), 128); return pool; } - public static PooledDictionary GetInstance(IEqualityComparer keyComparer = null) + public static PooledDictionary GetInstance(IEqualityComparer? keyComparer = null) { var pool = keyComparer == null ? s_poolInstance : @@ -70,7 +70,7 @@ public void Free() return instance; } - public static PooledDictionary GetInstance(IEnumerable> initializer, IEqualityComparer keyComparer = null) + public static PooledDictionary GetInstance(IEnumerable> initializer, IEqualityComparer? keyComparer = null) { var instance = GetInstance(keyComparer); foreach (var kvp in initializer) diff --git a/src/Utilities/Compiler/PooledObjects/PooledHashSet.cs b/src/Utilities/Compiler/PooledObjects/PooledHashSet.cs index b3536766c8..68cdd1f79e 100644 --- a/src/Utilities/Compiler/PooledObjects/PooledHashSet.cs +++ b/src/Utilities/Compiler/PooledObjects/PooledHashSet.cs @@ -16,9 +16,9 @@ namespace Analyzer.Utilities.PooledObjects // NOTE: these HashSets always have the default comparer. internal sealed class PooledHashSet : HashSet, IDisposable { - private readonly ObjectPool> _pool; + private readonly ObjectPool>? _pool; - private PooledHashSet(ObjectPool> pool, IEqualityComparer comparer) + private PooledHashSet(ObjectPool>? pool, IEqualityComparer? comparer) : base(comparer) { _pool = pool; @@ -55,14 +55,14 @@ public ImmutableHashSet ToImmutableAndFree() = new ConcurrentDictionary, ObjectPool>>(); // if someone needs to create a pool; - public static ObjectPool> CreatePool(IEqualityComparer comparer = null) + public static ObjectPool> CreatePool(IEqualityComparer? comparer = null) { - ObjectPool> pool = null; + ObjectPool>? pool = null; pool = new ObjectPool>(() => new PooledHashSet(pool, comparer), 128); return pool; } - public static PooledHashSet GetInstance(IEqualityComparer comparer = null) + public static PooledHashSet GetInstance(IEqualityComparer? comparer = null) { var pool = comparer == null ? s_poolInstance : diff --git a/src/Utilities/Compiler/WellKnownTypeProvider.cs b/src/Utilities/Compiler/WellKnownTypeProvider.cs index aee76962ed..03478b775c 100644 --- a/src/Utilities/Compiler/WellKnownTypeProvider.cs +++ b/src/Utilities/Compiler/WellKnownTypeProvider.cs @@ -2,7 +2,7 @@ using System; using System.Collections.Concurrent; -using System.Linq; +using System.Diagnostics.CodeAnalysis; using Analyzer.Utilities.Extensions; using Microsoft.CodeAnalysis; @@ -19,7 +19,7 @@ public class WellKnownTypeProvider private WellKnownTypeProvider(Compilation compilation) { Compilation = compilation; - _fullNameToTypeMap = new ConcurrentDictionary(StringComparer.Ordinal); + _fullNameToTypeMap = new ConcurrentDictionary(StringComparer.Ordinal); } public static WellKnownTypeProvider GetOrCreate(Compilation compilation) @@ -36,7 +36,7 @@ static WellKnownTypeProvider CreateWellKnownTypeProvider(Compilation compilation /// /// Mapping of full name to . /// - private readonly ConcurrentDictionary _fullNameToTypeMap; + private readonly ConcurrentDictionary _fullNameToTypeMap; /// /// Attempts to get the type by the full type name. @@ -44,7 +44,7 @@ static WellKnownTypeProvider CreateWellKnownTypeProvider(Compilation compilation /// Namespace + type name, e.g. "System.Exception". /// Named type symbol, if any. /// True if found in the compilation, false otherwise. - public bool TryGetOrCreateTypeByMetadataName(string fullTypeName, out INamedTypeSymbol namedTypeSymbol) + public bool TryGetOrCreateTypeByMetadataName(string fullTypeName, [NotNullWhen(returnValue: true)] out INamedTypeSymbol? namedTypeSymbol) { namedTypeSymbol = _fullNameToTypeMap.GetOrAdd( fullTypeName, @@ -103,9 +103,9 @@ public bool TryGetOrCreateTypeByMetadataName(string fullTypeName, out INamedType /// /// Namespace + type name, e.g. "System.Exception". /// The if found, null otherwise. - public INamedTypeSymbol GetOrCreateTypeByMetadataName(string fullTypeName) + public INamedTypeSymbol? GetOrCreateTypeByMetadataName(string fullTypeName) { - TryGetOrCreateTypeByMetadataName(fullTypeName, out INamedTypeSymbol namedTypeSymbol); + TryGetOrCreateTypeByMetadataName(fullTypeName, out INamedTypeSymbol? namedTypeSymbol); return namedTypeSymbol; } @@ -117,7 +117,7 @@ public INamedTypeSymbol GetOrCreateTypeByMetadataName(string fullTypeName) /// Predicate to check the 's type argument. /// True if is a with its /// type argument satisfying , false otherwise. - internal bool IsTaskOfType(ITypeSymbol typeSymbol, Func typeArgumentPredicate) + internal bool IsTaskOfType(ITypeSymbol? typeSymbol, Func typeArgumentPredicate) { return typeSymbol != null && typeSymbol.OriginalDefinition != null diff --git a/src/Utilities/Compiler/WordParser.cs b/src/Utilities/Compiler/WordParser.cs index a6961eb73c..243a0ac82d 100644 --- a/src/Utilities/Compiler/WordParser.cs +++ b/src/Utilities/Compiler/WordParser.cs @@ -52,7 +52,7 @@ internal class WordParser private readonly WordParserOptions _options; private readonly StringBuilder _buffer; private readonly string _text; - private string _peekedWord; + private string? _peekedWord; private int _index; private char _prefix; @@ -163,7 +163,7 @@ internal static Collection Parse(string text, WordParserOptions options, WordParser parser = new WordParser(text, options, prefix); Collection words = new Collection(); - string word; + string? word; while ((word = parser.NextWord()) != null) { words.Add(word); @@ -240,7 +240,7 @@ internal static bool ContainsWord(string text, WordParserOptions options, char p WordParser parser = new WordParser(text, options, prefix); - string parsedWord; + string? parsedWord; while ((parsedWord = parser.NextWord()) != null) { foreach (string word in words) @@ -261,14 +261,14 @@ internal static bool ContainsWord(string text, WordParserOptions options, char p /// /// A containing the next word or if there are no more words. /// - public string NextWord() + public string? NextWord() { if (_peekedWord == null) { return NextWordCore(); } - string word = _peekedWord; + string? word = _peekedWord; _peekedWord = null; return word; } @@ -279,7 +279,7 @@ public string NextWord() /// /// A containing the next word or if there are no more words. /// - public string PeekWord() + public string? PeekWord() { if (_peekedWord == null) { @@ -289,7 +289,7 @@ public string PeekWord() return _peekedWord; } - private string NextWordCore() + private string? NextWordCore() { // Reset buffer _buffer.Length = 0; diff --git a/src/Utilities/FlowAnalysis/BranchWithInfo.cs b/src/Utilities/FlowAnalysis/BranchWithInfo.cs index f80e098f28..0fe3e58f44 100644 --- a/src/Utilities/FlowAnalysis/BranchWithInfo.cs +++ b/src/Utilities/FlowAnalysis/BranchWithInfo.cs @@ -39,7 +39,7 @@ internal BranchWithInfo(BasicBlock destination) ImmutableArray leavingRegions, ImmutableArray finallyRegions, ControlFlowBranchSemantics kind, - IOperation branchValueOpt, + IOperation? branchValueOpt, ControlFlowConditionKind controlFlowConditionKind, IEnumerable leavingRegionLocals, IEnumerable leavingRegionFlowCaptures) @@ -60,7 +60,7 @@ internal BranchWithInfo(BasicBlock destination) public ImmutableArray EnteringRegions { get; } public ImmutableArray FinallyRegions { get; } public ImmutableArray LeavingRegions { get; } - public IOperation BranchValueOpt { get; } + public IOperation? BranchValueOpt { get; } #pragma warning disable CA1721 // Property names should not match get methods - https://github.com/dotnet/roslyn-analyzers/issues/2085 public ControlFlowConditionKind ControlFlowConditionKind { get; } @@ -84,7 +84,7 @@ internal BranchWithInfo WithEmptyRegions(BasicBlock destination) } internal BranchWithInfo With( - IOperation branchValueOpt, + IOperation? branchValueOpt, ControlFlowConditionKind controlFlowConditionKind) { return new BranchWithInfo(Destination, EnteringRegions, LeavingRegions, diff --git a/src/Utilities/FlowAnalysis/Extensions/BasicBlockExtensions.cs b/src/Utilities/FlowAnalysis/Extensions/BasicBlockExtensions.cs index 02e07b2904..6bd19f8fb7 100644 --- a/src/Utilities/FlowAnalysis/Extensions/BasicBlockExtensions.cs +++ b/src/Utilities/FlowAnalysis/Extensions/BasicBlockExtensions.cs @@ -3,6 +3,7 @@ using System; using System.Collections.Generic; using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; using Microsoft.CodeAnalysis.Operations; namespace Microsoft.CodeAnalysis.FlowAnalysis @@ -26,7 +27,7 @@ internal static IEnumerable<(BasicBlock predecessorBlock, BranchWithInfo branchW } } - internal static ITypeSymbol GetEnclosingRegionExceptionType(this BasicBlock basicBlock) + internal static ITypeSymbol? GetEnclosingRegionExceptionType(this BasicBlock basicBlock) { var region = basicBlock.EnclosingRegion; while (region != null) @@ -70,7 +71,7 @@ public static bool IsContainedInRegionOfKind(this BasicBlock basicBlock, Control /// /// Returns the innermost control flow region of the given that contains the given . /// - public static ControlFlowRegion GetContainingRegionOfKind(this BasicBlock basicBlock, ControlFlowRegionKind regionKind) + public static ControlFlowRegion? GetContainingRegionOfKind(this BasicBlock basicBlock, ControlFlowRegionKind regionKind) { var enclosingRegion = basicBlock.EnclosingRegion; while (enclosingRegion != null) @@ -89,28 +90,28 @@ public static ControlFlowRegion GetContainingRegionOfKind(this BasicBlock basicB /// /// Returns true if the given basic block is the first block of a finally region. /// - public static bool IsFirstBlockOfFinally(this BasicBlock basicBlock, out ControlFlowRegion finallyRegion) + public static bool IsFirstBlockOfFinally(this BasicBlock basicBlock, [NotNullWhen(returnValue: true)] out ControlFlowRegion? finallyRegion) => basicBlock.IsFirstBlockOfRegionKind(ControlFlowRegionKind.Finally, out finallyRegion); /// /// Returns true if the given basic block is the last block of a finally region. /// - public static bool IsLastBlockOfFinally(this BasicBlock basicBlock, out ControlFlowRegion finallyRegion) + public static bool IsLastBlockOfFinally(this BasicBlock basicBlock, [NotNullWhen(returnValue: true)] out ControlFlowRegion? finallyRegion) => basicBlock.IsLastBlockOfRegionKind(ControlFlowRegionKind.Finally, out finallyRegion); /// /// Returns true if the given basic block is the first block of a region of the given regionKind. /// - public static bool IsFirstBlockOfRegionKind(this BasicBlock basicBlock, ControlFlowRegionKind regionKind, out ControlFlowRegion region) + public static bool IsFirstBlockOfRegionKind(this BasicBlock basicBlock, ControlFlowRegionKind regionKind, [NotNullWhen(returnValue: true)] out ControlFlowRegion? region) => basicBlock.IsFirstOrLastBlockOfRegionKind(regionKind, first: true, out region); /// /// Returns true if the given basic block is the last block of a region of the given regionKind. /// - public static bool IsLastBlockOfRegionKind(this BasicBlock basicBlock, ControlFlowRegionKind regionKind, out ControlFlowRegion region) + public static bool IsLastBlockOfRegionKind(this BasicBlock basicBlock, ControlFlowRegionKind regionKind, [NotNullWhen(returnValue: true)] out ControlFlowRegion? region) => basicBlock.IsFirstOrLastBlockOfRegionKind(regionKind, first: false, out region); - private static bool IsFirstOrLastBlockOfRegionKind(this BasicBlock basicBlock, ControlFlowRegionKind regionKind, bool first, out ControlFlowRegion foundRegion) + private static bool IsFirstOrLastBlockOfRegionKind(this BasicBlock basicBlock, ControlFlowRegionKind regionKind, bool first, [NotNullWhen(returnValue: true)] out ControlFlowRegion? foundRegion) { foundRegion = null; @@ -135,7 +136,7 @@ private static bool IsFirstOrLastBlockOfRegionKind(this BasicBlock basicBlock, C return false; } - internal static ControlFlowRegion GetInnermostRegionStartedByBlock(this BasicBlock basicBlock, ControlFlowRegionKind regionKind) + internal static ControlFlowRegion? GetInnermostRegionStartedByBlock(this BasicBlock basicBlock, ControlFlowRegionKind regionKind) { if (basicBlock.EnclosingRegion?.FirstBlockOrdinal != basicBlock.Ordinal) { @@ -166,11 +167,11 @@ internal static int GetMaxSuccessorOrdinal(this BasicBlock basicBlock) => Math.Max(basicBlock.FallThroughSuccessor?.Destination?.Ordinal ?? -1, basicBlock.ConditionalSuccessor?.Destination?.Ordinal ?? -1); - internal static IOperation GetPreviousOperationInBlock(this BasicBlock basicBlock, IOperation operation) + internal static IOperation? GetPreviousOperationInBlock(this BasicBlock basicBlock, IOperation operation) { Debug.Assert(operation != null); - IOperation previousOperation = null; + IOperation? previousOperation = null; foreach (var currentOperation in basicBlock.Operations) { if (operation == currentOperation) diff --git a/src/Utilities/FlowAnalysis/Extensions/ControlFlowGraphExtensions.cs b/src/Utilities/FlowAnalysis/Extensions/ControlFlowGraphExtensions.cs index 4d37d22905..e2f1344394 100644 --- a/src/Utilities/FlowAnalysis/Extensions/ControlFlowGraphExtensions.cs +++ b/src/Utilities/FlowAnalysis/Extensions/ControlFlowGraphExtensions.cs @@ -1,7 +1,6 @@ // Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System.Collections.Generic; -using System.Diagnostics; using System.Linq; using Analyzer.Utilities.Extensions; using Microsoft.CodeAnalysis.Operations; @@ -26,8 +25,6 @@ public static IEnumerable DescendantOperations(this ControlFlowGraph public static IEnumerable DescendantOperations(this ControlFlowGraph cfg, OperationKind operationKind) where T : IOperation { - Debug.Assert(cfg != null); - foreach (var descendant in cfg.DescendantOperations()) { if (descendant?.Kind == operationKind) diff --git a/src/Utilities/FlowAnalysis/Extensions/OperationBlocksExtensions.cs b/src/Utilities/FlowAnalysis/Extensions/OperationBlocksExtensions.cs index 23db5d128f..f75c2b1353 100644 --- a/src/Utilities/FlowAnalysis/Extensions/OperationBlocksExtensions.cs +++ b/src/Utilities/FlowAnalysis/Extensions/OperationBlocksExtensions.cs @@ -9,11 +9,11 @@ namespace Analyzer.Utilities.Extensions { internal static partial class OperationBlocksExtensions { - public static ControlFlowGraph GetControlFlowGraph(this ImmutableArray operationBlocks) + public static ControlFlowGraph? GetControlFlowGraph(this ImmutableArray operationBlocks) { foreach (var operationRoot in operationBlocks) { - IBlockOperation topmostBlock = operationRoot.GetTopmostParentBlock(); + IBlockOperation? topmostBlock = operationRoot.GetTopmostParentBlock(); if (topmostBlock != null) { return topmostBlock.GetEnclosingControlFlowGraph(); diff --git a/src/Utilities/FlowAnalysis/FlowAnalysis/Analysis/CopyAnalysis/CopyAnalysis.CopyAbstractValueDomain.cs b/src/Utilities/FlowAnalysis/FlowAnalysis/Analysis/CopyAnalysis/CopyAnalysis.CopyAbstractValueDomain.cs index 97674ba135..e6af22ce93 100644 --- a/src/Utilities/FlowAnalysis/FlowAnalysis/Analysis/CopyAnalysis/CopyAnalysis.CopyAbstractValueDomain.cs +++ b/src/Utilities/FlowAnalysis/FlowAnalysis/Analysis/CopyAnalysis/CopyAnalysis.CopyAbstractValueDomain.cs @@ -24,9 +24,6 @@ private sealed class CopyAbstractValueDomain : AbstractValueDomain tryGetAddressSharedCopyValue, + Func tryGetAddressSharedCopyValue, SetCopyAbstractValuePredicateKind? fromPredicateKindOpt = null, bool initializingParameters = false) { @@ -151,14 +147,13 @@ protected override void SetAbstractValueForTupleElementAssignment(AnalysisEntity CopyAnalysisData targetCopyAnalysisData, AnalysisEntity analysisEntity, CopyAbstractValue value, - Func tryGetAddressSharedCopyValue, + Func tryGetAddressSharedCopyValue, SetCopyAbstractValuePredicateKind? fromPredicateKindOpt, bool initializingParameters) { sourceCopyAnalysisData.AssertValidCopyAnalysisData(tryGetAddressSharedCopyValue, initializingParameters); targetCopyAnalysisData.AssertValidCopyAnalysisData(tryGetAddressSharedCopyValue, initializingParameters); Debug.Assert(ReferenceEquals(sourceCopyAnalysisData, targetCopyAnalysisData) || fromPredicateKindOpt.HasValue); - Debug.Assert(tryGetAddressSharedCopyValue != null); // Don't track entities if do not know about it's instance location. if (analysisEntity.HasUnknownInstanceLocation) @@ -188,7 +183,7 @@ protected override void SetAbstractValueForTupleElementAssignment(AnalysisEntity if (existingValue.AnalysisEntities.Count > 1) { - CopyAbstractValue addressSharedCopyValue = tryGetAddressSharedCopyValue(analysisEntity); + CopyAbstractValue? addressSharedCopyValue = tryGetAddressSharedCopyValue(analysisEntity); if (addressSharedCopyValue == null || addressSharedCopyValue != existingValue) { CopyAbstractValue newValueForEntitiesInOldSet = addressSharedCopyValue != null ? @@ -234,7 +229,7 @@ protected override void SetAbstractValueForTupleElementAssignment(AnalysisEntity else { // Include address shared entities, if any. - CopyAbstractValue addressSharedCopyValue = tryGetAddressSharedCopyValue(analysisEntity); + CopyAbstractValue? addressSharedCopyValue = tryGetAddressSharedCopyValue(analysisEntity); if (addressSharedCopyValue != null) { newAnalysisEntities = newAnalysisEntities.Union(addressSharedCopyValue.AnalysisEntities); @@ -247,7 +242,7 @@ protected override void SetAbstractValueForTupleElementAssignment(AnalysisEntity targetCopyAnalysisData.AssertValidCopyAnalysisData(tryGetAddressSharedCopyValue, initializingParameters); } - protected override void SetValueForParameterOnEntry(IParameterSymbol parameter, AnalysisEntity analysisEntity, ArgumentInfo assignedValueOpt) + protected override void SetValueForParameterOnEntry(IParameterSymbol parameter, AnalysisEntity analysisEntity, ArgumentInfo? assignedValueOpt) { CopyAbstractValue copyValue; if (assignedValueOpt != null) @@ -308,7 +303,7 @@ private CopyAbstractValue GetResetValue(AnalysisEntity analysisEntity, CopyAbstr protected override CopyAbstractValue ComputeAnalysisValueForReferenceOperation(IOperation operation, CopyAbstractValue defaultValue) { - if (AnalysisEntityFactory.TryCreate(operation, out AnalysisEntity analysisEntity)) + if (AnalysisEntityFactory.TryCreate(operation, out var analysisEntity)) { return CurrentAnalysisData.TryGetValue(analysisEntity, out CopyAbstractValue value) ? value : GetDefaultCopyValue(analysisEntity); } @@ -440,7 +435,7 @@ protected override void UpdateValuesForAnalysisData(CopyAnalysisData targetAnaly protected override void ApplyMissingCurrentAnalysisDataForUnhandledExceptionData(CopyAnalysisData dataAtException, ThrownExceptionInfo throwBranchWithExceptionType) { - Func predicateOpt = null; + Func? predicateOpt = null; if (throwBranchWithExceptionType.IsDefaultExceptionForExceptionsPathAnalysis) { // Only tracking non-child analysis entities for exceptions path analysis for now. @@ -520,7 +515,7 @@ protected override void ApplyInterproceduralAnalysisResultCore(CopyAnalysisData CurrentAnalysisData.CoreAnalysisData.AddRange(mergedData.CoreAnalysisData); } - private void ApplyMissingCurrentAnalysisDataCore(CopyAnalysisData mergedData, Func predicateOpt) + private void ApplyMissingCurrentAnalysisDataCore(CopyAnalysisData mergedData, Func? predicateOpt) { var processedEntities = PooledHashSet.GetInstance(); try @@ -586,12 +581,12 @@ protected override CopyAnalysisData GetTrimmedCurrentAnalysisData(IEnumerable> argumentValuesMap, - IDictionary pointsToValuesOpt, - IDictionary copyValuesOpt, - IDictionary valueContentValuesOpt, + IDictionary? pointsToValuesOpt, + IDictionary? copyValuesOpt, + IDictionary? valueContentValuesOpt, bool isLambdaOrLocalFunction, bool hasParameterWithDelegateType) { @@ -606,7 +601,7 @@ protected override CopyAnalysisData GetTrimmedCurrentAnalysisData(IEnumerable valueDo public override CoreCopyAnalysisData Merge(CoreCopyAnalysisData map1, CoreCopyAnalysisData map2) { - Debug.Assert(map1 != null); - Debug.Assert(map2 != null); CopyAnalysisData.AssertValidCopyAnalysisData(map1); CopyAnalysisData.AssertValidCopyAnalysisData(map2); diff --git a/src/Utilities/FlowAnalysis/FlowAnalysis/Analysis/CopyAnalysis/CopyAnalysis.cs b/src/Utilities/FlowAnalysis/FlowAnalysis/Analysis/CopyAnalysis/CopyAnalysis.cs index b8224e5f9c..34e2626df1 100644 --- a/src/Utilities/FlowAnalysis/FlowAnalysis/Analysis/CopyAnalysis/CopyAnalysis.cs +++ b/src/Utilities/FlowAnalysis/FlowAnalysis/Analysis/CopyAnalysis/CopyAnalysis.cs @@ -20,13 +20,13 @@ private CopyAnalysis(CopyDataFlowOperationVisitor operationVisitor) { } - public static CopyAnalysisResult TryGetOrComputeResult( + public static CopyAnalysisResult? TryGetOrComputeResult( ControlFlowGraph cfg, ISymbol owningSymbol, AnalyzerOptions analyzerOptions, WellKnownTypeProvider wellKnownTypeProvider, InterproceduralAnalysisConfiguration interproceduralAnalysisConfig, - InterproceduralAnalysisPredicate interproceduralAnalysisPredicateOpt, + InterproceduralAnalysisPredicate? interproceduralAnalysisPredicateOpt, bool pessimisticAnalysis = true, bool performPointsToAnalysis = true, bool exceptionPathsAnalysis = false) @@ -47,7 +47,7 @@ private CopyAnalysis(CopyDataFlowOperationVisitor operationVisitor) return TryGetOrComputeResultForAnalysisContext(analysisContext); } - private static CopyAnalysisResult TryGetOrComputeResultForAnalysisContext(CopyAnalysisContext analysisContext) + private static CopyAnalysisResult? TryGetOrComputeResultForAnalysisContext(CopyAnalysisContext analysisContext) { var operationVisitor = new CopyDataFlowOperationVisitor(analysisContext); var copyAnalysis = new CopyAnalysis(operationVisitor); diff --git a/src/Utilities/FlowAnalysis/FlowAnalysis/Analysis/CopyAnalysis/CopyAnalysisContext.cs b/src/Utilities/FlowAnalysis/FlowAnalysis/Analysis/CopyAnalysis/CopyAnalysisContext.cs index 906a90b0df..435653d0f8 100644 --- a/src/Utilities/FlowAnalysis/FlowAnalysis/Analysis/CopyAnalysis/CopyAnalysisContext.cs +++ b/src/Utilities/FlowAnalysis/FlowAnalysis/Analysis/CopyAnalysis/CopyAnalysisContext.cs @@ -26,11 +26,11 @@ public sealed class CopyAnalysisContext : AbstractDataFlowAnalysisContext tryGetOrComputeAnalysisResult, - ControlFlowGraph parentControlFlowGraphOpt, - InterproceduralCopyAnalysisData interproceduralAnalysisDataOpt, - InterproceduralAnalysisPredicate interproceduralAnalysisPredicateOpt) + PointsToAnalysisResult? pointsToAnalysisResultOpt, + Func tryGetOrComputeAnalysisResult, + ControlFlowGraph? parentControlFlowGraphOpt, + InterproceduralCopyAnalysisData? interproceduralAnalysisDataOpt, + InterproceduralAnalysisPredicate? interproceduralAnalysisPredicateOpt) : base(valueDomain, wellKnownTypeProvider, controlFlowGraph, owningSymbol, analyzerOptions, interproceduralAnalysisConfig, pessimisticAnalysis, predicateAnalysis: true, exceptionPathsAnalysis, copyAnalysisResultOpt: null, pointsToAnalysisResultOpt, valueContentAnalysisResultOpt: null, tryGetOrComputeAnalysisResult, parentControlFlowGraphOpt, interproceduralAnalysisDataOpt, interproceduralAnalysisPredicateOpt) @@ -46,9 +46,9 @@ public sealed class CopyAnalysisContext : AbstractDataFlowAnalysisContext tryGetOrComputeAnalysisResult, - InterproceduralAnalysisPredicate interproceduralAnalysisPredicateOpt) + PointsToAnalysisResult? pointsToAnalysisResultOpt, + Func tryGetOrComputeAnalysisResult, + InterproceduralAnalysisPredicate? interproceduralAnalysisPredicateOpt) { return new CopyAnalysisContext(valueDomain, wellKnownTypeProvider, controlFlowGraph, owningSymbol, analyzerOptions, interproceduralAnalysisConfig, pessimisticAnalysis, exceptionPathsAnalysis, pointsToAnalysisResultOpt, tryGetOrComputeAnalysisResult, @@ -59,10 +59,10 @@ public sealed class CopyAnalysisContext : AbstractDataFlowAnalysisContext With /// We do not support the overload /// that updates copy value for each individual entity. /// - internal void SetAbstactValueForEntities(CopyAbstractValue copyValue, AnalysisEntity entityBeingAssignedOpt) + internal void SetAbstactValueForEntities(CopyAbstractValue copyValue, AnalysisEntity? entityBeingAssignedOpt) { foreach (var entity in copyValue.AnalysisEntities) { @@ -87,7 +87,6 @@ public override void SetAbstractValue(AnalysisEntity key, CopyAbstractValue valu protected override void RemoveEntryInPredicatedData(AnalysisEntity key, CoreCopyAnalysisData predicatedData) { Debug.Assert(HasPredicatedData); - Debug.Assert(predicatedData != null); var hasEntry = predicatedData.TryGetValue(key, out CopyAbstractValue value); base.RemoveEntryInPredicatedData(key, predicatedData); @@ -186,7 +185,7 @@ public override void Reset(Func tryGetDefaultCopyValueOpt = null, bool initializingParameters = false) + internal void AssertValidCopyAnalysisData(Func? tryGetDefaultCopyValueOpt = null, bool initializingParameters = false) { AssertValidCopyAnalysisData(CoreAnalysisData, tryGetDefaultCopyValueOpt, initializingParameters); AssertValidPredicatedAnalysisData(map => AssertValidCopyAnalysisData(map, tryGetDefaultCopyValueOpt, initializingParameters)); @@ -195,7 +194,7 @@ internal void AssertValidCopyAnalysisData(Func map, - Func tryGetDefaultCopyValueOpt = null, + Func? tryGetDefaultCopyValueOpt = null, bool initializingParameters = false) { if (map is CoreCopyAnalysisData coreCopyAnalysisData) diff --git a/src/Utilities/FlowAnalysis/FlowAnalysis/Analysis/DisposeAnalysis/DisposeAbstractValue.cs b/src/Utilities/FlowAnalysis/FlowAnalysis/Analysis/DisposeAnalysis/DisposeAbstractValue.cs index 4a0a0a2d1f..70f58655ac 100644 --- a/src/Utilities/FlowAnalysis/FlowAnalysis/Analysis/DisposeAnalysis/DisposeAbstractValue.cs +++ b/src/Utilities/FlowAnalysis/FlowAnalysis/Analysis/DisposeAnalysis/DisposeAbstractValue.cs @@ -50,8 +50,6 @@ internal DisposeAbstractValue WithNewEscapingOperation(IOperation escapingOperat [Conditional("DEBUG")] private static void VerifyArguments(ImmutableHashSet disposingOrEscapingOperations, DisposeAbstractValueKind kind) { - Debug.Assert(disposingOrEscapingOperations != null); - switch (kind) { case DisposeAbstractValueKind.NotDisposable: diff --git a/src/Utilities/FlowAnalysis/FlowAnalysis/Analysis/DisposeAnalysis/DisposeAnalysis.DisposeAbstractValueDomain.cs b/src/Utilities/FlowAnalysis/FlowAnalysis/Analysis/DisposeAnalysis/DisposeAnalysis.DisposeAbstractValueDomain.cs index e287e0da32..1ef35f795b 100644 --- a/src/Utilities/FlowAnalysis/FlowAnalysis/Analysis/DisposeAnalysis/DisposeAnalysis.DisposeAbstractValueDomain.cs +++ b/src/Utilities/FlowAnalysis/FlowAnalysis/Analysis/DisposeAnalysis/DisposeAnalysis.DisposeAbstractValueDomain.cs @@ -24,9 +24,6 @@ private class DisposeAbstractValueDomain : AbstractValueDomain private sealed class DisposeDataFlowOperationVisitor : AbstractLocationDataFlowOperationVisitor { - private readonly Dictionary _trackedInstanceFieldLocationsOpt; + private readonly Dictionary? _trackedInstanceFieldLocationsOpt; private ImmutableHashSet DisposeOwnershipTransferLikelyTypes => DataFlowAnalysisContext.DisposeOwnershipTransferLikelyTypes; private bool DisposeOwnershipTransferAtConstructor => DataFlowAnalysisContext.DisposeOwnershipTransferAtConstructor; private bool DisposeOwnershipTransferAtMethodCall => DataFlowAnalysisContext.DisposeOwnershipTransferAtMethodCall; @@ -101,9 +101,9 @@ protected override DisposeAbstractValue HandleInstanceCreation(IOperation creati return DisposeAbstractValue.NotDisposed; } - private void HandleDisposingOperation(IOperation disposingOperation, IOperation disposedInstance) + private void HandleDisposingOperation(IOperation disposingOperation, IOperation? disposedInstance) { - if (disposedInstance.Type?.IsDisposable(IDisposableNamedType) == false) + if (disposedInstance == null || disposedInstance.Type?.IsDisposable(IDisposableNamedType) == false) { return; } @@ -151,7 +151,7 @@ protected override void SetAbstractValueForArrayElementInitializer(IArrayCreatio // We do not need to do anything here. } - protected override void SetAbstractValueForAssignment(IOperation target, IOperation assignedValueOperation, DisposeAbstractValue assignedValue, bool mayBeAssignment = false) + protected override void SetAbstractValueForAssignment(IOperation target, IOperation? assignedValueOperation, DisposeAbstractValue assignedValue, bool mayBeAssignment = false) { // Assignments should automatically transfer PointsTo value. // We do not need to do anything here. @@ -213,13 +213,13 @@ protected override bool Equals(DisposeAnalysisData value1, DisposeAnalysisData v => EqualsHelper(value1, value2); #region Visitor methods - public override DisposeAbstractValue DefaultVisit(IOperation operation, object argument) + public override DisposeAbstractValue DefaultVisit(IOperation operation, object? argument) { _ = base.DefaultVisit(operation, argument); return DisposeAbstractValue.NotDisposable; } - public override DisposeAbstractValue Visit(IOperation operation, object argument) + public override DisposeAbstractValue Visit(IOperation operation, object? argument) { var value = base.Visit(operation, argument); HandlePossibleEscapingOperation(operation, GetEscapedLocations(operation)); @@ -263,7 +263,7 @@ private static bool IsDisposableCreationSpecialCase(IMethodSymbol targetMethod) public override DisposeAbstractValue VisitInvocation_NonLambdaOrDelegateOrLocalFunction( IMethodSymbol targetMethod, - IOperation instance, + IOperation? instance, ImmutableArray arguments, bool invokedAsDelegate, IOperation originalOperation, @@ -317,7 +317,8 @@ private static bool IsDisposableCreationSpecialCase(IMethodSymbol targetMethod) base.ApplyInterproceduralAnalysisResult(resultData, isLambdaOrLocalFunction, hasParameterWithDelegateType, interproceduralResult); // Apply the tracked instance field locations from interprocedural analysis. - if (_trackedInstanceFieldLocationsOpt != null) + if (_trackedInstanceFieldLocationsOpt != null && + interproceduralResult.TrackedInstanceFieldPointsToMap != null) { foreach (var (field, pointsToValue) in interproceduralResult.TrackedInstanceFieldPointsToMap) { diff --git a/src/Utilities/FlowAnalysis/FlowAnalysis/Analysis/DisposeAnalysis/DisposeAnalysis.cs b/src/Utilities/FlowAnalysis/FlowAnalysis/Analysis/DisposeAnalysis/DisposeAnalysis.cs index 5d6bb3a2ab..2b60fbbd02 100644 --- a/src/Utilities/FlowAnalysis/FlowAnalysis/Analysis/DisposeAnalysis/DisposeAnalysis.cs +++ b/src/Utilities/FlowAnalysis/FlowAnalysis/Analysis/DisposeAnalysis/DisposeAnalysis.cs @@ -32,7 +32,7 @@ private DisposeAnalysis(DisposeAnalysisDomain analysisDomain, DisposeDataFlowOpe { } - public static DisposeAnalysisResult TryGetOrComputeResult( + public static DisposeAnalysisResult? TryGetOrComputeResult( ControlFlowGraph cfg, ISymbol owningSymbol, WellKnownTypeProvider wellKnownTypeProvider, @@ -42,10 +42,10 @@ private DisposeAnalysis(DisposeAnalysisDomain analysisDomain, DisposeDataFlowOpe bool trackInstanceFields, bool exceptionPathsAnalysis, CancellationToken cancellationToken, - out PointsToAnalysisResult pointsToAnalysisResult, + out PointsToAnalysisResult? pointsToAnalysisResult, InterproceduralAnalysisKind interproceduralAnalysisKind = InterproceduralAnalysisKind.ContextSensitive, bool performCopyAnalysisIfNotUserConfigured = false, - InterproceduralAnalysisPredicate interproceduralAnalysisPredicateOpt = null, + InterproceduralAnalysisPredicate? interproceduralAnalysisPredicateOpt = null, bool defaultDisposeOwnershipTransferAtConstructor = false, bool defaultDisposeOwnershipTransferAtMethodCall = false) { @@ -65,23 +65,22 @@ private DisposeAnalysis(DisposeAnalysisDomain analysisDomain, DisposeDataFlowOpe out pointsToAnalysisResult); } - private static DisposeAnalysisResult TryGetOrComputeResult( + private static DisposeAnalysisResult? TryGetOrComputeResult( ControlFlowGraph cfg, ISymbol owningSymbol, AnalyzerOptions analyzerOptions, WellKnownTypeProvider wellKnownTypeProvider, InterproceduralAnalysisConfiguration interproceduralAnalysisConfig, - InterproceduralAnalysisPredicate interproceduralAnalysisPredicateOpt, + InterproceduralAnalysisPredicate? interproceduralAnalysisPredicateOpt, ImmutableHashSet disposeOwnershipTransferLikelyTypes, bool disposeOwnershipTransferAtConstructor, bool disposeOwnershipTransferAtMethodCall, bool trackInstanceFields, bool exceptionPathsAnalysis, bool performCopyAnalysis, - out PointsToAnalysisResult pointsToAnalysisResult) + out PointsToAnalysisResult? pointsToAnalysisResult) { Debug.Assert(wellKnownTypeProvider.TryGetOrCreateTypeByMetadataName(WellKnownTypeNames.SystemIDisposable, out _)); - Debug.Assert(owningSymbol != null); pointsToAnalysisResult = PointsToAnalysis.PointsToAnalysis.TryGetOrComputeResult( cfg, owningSymbol, analyzerOptions, wellKnownTypeProvider, interproceduralAnalysisConfig, @@ -104,7 +103,7 @@ private DisposeAnalysis(DisposeAnalysisDomain analysisDomain, DisposeDataFlowOpe return TryGetOrComputeResultForAnalysisContext(analysisContext); } - private static DisposeAnalysisResult TryGetOrComputeResultForAnalysisContext(DisposeAnalysisContext disposeAnalysisContext) + private static DisposeAnalysisResult? TryGetOrComputeResultForAnalysisContext(DisposeAnalysisContext disposeAnalysisContext) { var operationVisitor = new DisposeDataFlowOperationVisitor(disposeAnalysisContext); var disposeAnalysis = new DisposeAnalysis(DisposeAnalysisDomainInstance, operationVisitor); diff --git a/src/Utilities/FlowAnalysis/FlowAnalysis/Analysis/DisposeAnalysis/DisposeAnalysisContext.cs b/src/Utilities/FlowAnalysis/FlowAnalysis/Analysis/DisposeAnalysis/DisposeAnalysisContext.cs index 12ea7aef74..089cf117cf 100644 --- a/src/Utilities/FlowAnalysis/FlowAnalysis/Analysis/DisposeAnalysis/DisposeAnalysisContext.cs +++ b/src/Utilities/FlowAnalysis/FlowAnalysis/Analysis/DisposeAnalysis/DisposeAnalysisContext.cs @@ -30,15 +30,15 @@ public sealed class DisposeAnalysisContext : AbstractDataFlowAnalysisContext tryGetOrComputeAnalysisResult, + PointsToAnalysisResult? pointsToAnalysisResultOpt, + Func tryGetOrComputeAnalysisResult, ImmutableHashSet disposeOwnershipTransferLikelyTypes, bool disposeOwnershipTransferAtConstructor, bool disposeOwnershipTransferAtMethodCall, bool trackInstanceFields, - ControlFlowGraph parentControlFlowGraphOpt, - InterproceduralDisposeAnalysisData interproceduralAnalysisDataOpt, - InterproceduralAnalysisPredicate interproceduralAnalysisPredicateOpt) + ControlFlowGraph? parentControlFlowGraphOpt, + InterproceduralDisposeAnalysisData? interproceduralAnalysisDataOpt, + InterproceduralAnalysisPredicate? interproceduralAnalysisPredicateOpt) : base(valueDomain, wellKnownTypeProvider, controlFlowGraph, owningSymbol, analyzerOptions, interproceduralAnalysisConfig, pessimisticAnalysis, predicateAnalysis: false, @@ -64,11 +64,11 @@ public sealed class DisposeAnalysisContext : AbstractDataFlowAnalysisContext tryGetOrComputeAnalysisResult, + PointsToAnalysisResult? pointsToAnalysisResultOpt, + Func tryGetOrComputeAnalysisResult, ImmutableHashSet disposeOwnershipTransferLikelyTypes, bool disposeOwnershipTransferAtConstructor, bool disposeOwnershipTransferAtMethodCall, @@ -87,10 +87,10 @@ public sealed class DisposeAnalysisContext : AbstractDataFlowAnalysisContext _disposeOwnershipTransferLikelyTypes; - private ConcurrentDictionary> _lazyDisposableFieldsMap; - public INamedTypeSymbol IDisposable { get; } - public INamedTypeSymbol Task { get; } + private readonly ImmutableHashSet? _disposeOwnershipTransferLikelyTypes; + private ConcurrentDictionary>? _lazyDisposableFieldsMap; + public INamedTypeSymbol? IDisposable { get; } + public INamedTypeSymbol? Task { get; } private DisposeAnalysisHelper(Compilation compilation) { @@ -60,7 +61,7 @@ private static ImmutableHashSet GetDisposeOwnershipTransferLik var builder = PooledHashSet.GetInstance(); foreach (var typeName in s_disposeOwnershipTransferLikelyTypes) { - INamedTypeSymbol typeSymbol = compilation.GetOrCreateTypeByMetadataName(typeName); + INamedTypeSymbol? typeSymbol = compilation.GetOrCreateTypeByMetadataName(typeName); if (typeSymbol != null) { builder.Add(typeSymbol); @@ -78,7 +79,7 @@ private void EnsureDisposableFieldsMap() } } - public static bool TryGetOrCreate(Compilation compilation, out DisposeAnalysisHelper disposeHelper) + public static bool TryGetOrCreate(Compilation compilation, [NotNullWhen(returnValue: true)] out DisposeAnalysisHelper? disposeHelper) { disposeHelper = s_DisposeHelperCache.GetOrCreateValue(compilation, CreateDisposeAnalysisHelper); if (disposeHelper.IDisposable == null) @@ -102,16 +103,16 @@ static DisposeAnalysisHelper CreateDisposeAnalysisHelper(Compilation compilation bool trackInstanceFields, bool trackExceptionPaths, CancellationToken cancellationToken, - out DisposeAnalysisResult disposeAnalysisResult, - out PointsToAnalysisResult pointsToAnalysisResult, - InterproceduralAnalysisPredicate interproceduralAnalysisPredicateOpt = null, + [NotNullWhen(returnValue: true)] out DisposeAnalysisResult? disposeAnalysisResult, + [NotNullWhen(returnValue: true)] out PointsToAnalysisResult? pointsToAnalysisResult, + InterproceduralAnalysisPredicate? interproceduralAnalysisPredicateOpt = null, bool defaultDisposeOwnershipTransferAtConstructor = false) { var cfg = operationBlocks.GetControlFlowGraph(); - if (cfg != null) + if (cfg != null && IDisposable != null) { disposeAnalysisResult = DisposeAnalysis.TryGetOrComputeResult(cfg, containingMethod, _wellKnownTypeProvider, - analyzerOptions, rule, _disposeOwnershipTransferLikelyTypes, trackInstanceFields, + analyzerOptions, rule, _disposeOwnershipTransferLikelyTypes!, trackInstanceFields, trackExceptionPaths, cancellationToken, out pointsToAnalysisResult, interproceduralAnalysisPredicateOpt: interproceduralAnalysisPredicateOpt, defaultDisposeOwnershipTransferAtConstructor: defaultDisposeOwnershipTransferAtConstructor); @@ -144,7 +145,7 @@ public bool HasAnyDisposableCreationDescendant(ImmutableArray operat public ImmutableHashSet GetDisposableFields(INamedTypeSymbol namedType) { EnsureDisposableFieldsMap(); - if (_lazyDisposableFieldsMap.TryGetValue(namedType, out ImmutableHashSet disposableFields)) + if (_lazyDisposableFieldsMap!.TryGetValue(namedType, out ImmutableHashSet disposableFields)) { return disposableFields; } diff --git a/src/Utilities/FlowAnalysis/FlowAnalysis/Analysis/DisposeAnalysis/DisposeAnalysisResult.cs b/src/Utilities/FlowAnalysis/FlowAnalysis/Analysis/DisposeAnalysis/DisposeAnalysisResult.cs index de2c8741c8..fa798422ea 100644 --- a/src/Utilities/FlowAnalysis/FlowAnalysis/Analysis/DisposeAnalysis/DisposeAnalysisResult.cs +++ b/src/Utilities/FlowAnalysis/FlowAnalysis/Analysis/DisposeAnalysis/DisposeAnalysisResult.cs @@ -11,12 +11,12 @@ public sealed class DisposeAnalysisResult : DataFlowAnalysisResult coreDisposeAnalysisResult, - ImmutableDictionary trackedInstanceFieldPointsToMap) + ImmutableDictionary? trackedInstanceFieldPointsToMap) : base(coreDisposeAnalysisResult) { TrackedInstanceFieldPointsToMap = trackedInstanceFieldPointsToMap; } - public ImmutableDictionary TrackedInstanceFieldPointsToMap { get; } + public ImmutableDictionary? TrackedInstanceFieldPointsToMap { get; } } } diff --git a/src/Utilities/FlowAnalysis/FlowAnalysis/Analysis/ParameterValidationAnalysis/ParameterValidationAnalysis.ParameterValidationDataFlowOperationVisitor.cs b/src/Utilities/FlowAnalysis/FlowAnalysis/Analysis/ParameterValidationAnalysis/ParameterValidationAnalysis.ParameterValidationDataFlowOperationVisitor.cs index 1e93635ff4..18978a782f 100644 --- a/src/Utilities/FlowAnalysis/FlowAnalysis/Analysis/ParameterValidationAnalysis/ParameterValidationAnalysis.ParameterValidationDataFlowOperationVisitor.cs +++ b/src/Utilities/FlowAnalysis/FlowAnalysis/Analysis/ParameterValidationAnalysis/ParameterValidationAnalysis.ParameterValidationDataFlowOperationVisitor.cs @@ -88,7 +88,7 @@ protected override void SetAbstractValue(AbstractLocation location, ParameterVal } } - protected override void SetAbstractValueForAssignment(IOperation target, IOperation assignedValueOperation, ParameterValidationAbstractValue assignedValue, bool mayBeAssignment = false) + protected override void SetAbstractValueForAssignment(IOperation target, IOperation? assignedValueOperation, ParameterValidationAbstractValue assignedValue, bool mayBeAssignment = false) { // If we are assigning to parameter, mark it as validated on this path. if (target is IParameterReferenceOperation) diff --git a/src/Utilities/FlowAnalysis/FlowAnalysis/Analysis/ParameterValidationAnalysis/ParameterValidationAnalysis.cs b/src/Utilities/FlowAnalysis/FlowAnalysis/Analysis/ParameterValidationAnalysis/ParameterValidationAnalysis.cs index 477d4d7d40..bdb332c13e 100644 --- a/src/Utilities/FlowAnalysis/FlowAnalysis/Analysis/ParameterValidationAnalysis/ParameterValidationAnalysis.cs +++ b/src/Utilities/FlowAnalysis/FlowAnalysis/Analysis/ParameterValidationAnalysis/ParameterValidationAnalysis.cs @@ -57,26 +57,27 @@ private ParameterValidationAnalysis(ParameterValidationAnalysisDomain analysisDo bool performCopyAnalysis, bool pessimisticAnalysis = true) { - Debug.Assert(topmostBlock != null); - var cfg = topmostBlock.GetEnclosingControlFlowGraph(); - var wellKnownTypeProvider = WellKnownTypeProvider.GetOrCreate(compilation); - var pointsToAnalysisResult = PointsToAnalysis.PointsToAnalysis.TryGetOrComputeResult(cfg, owningSymbol, analyzerOptions, wellKnownTypeProvider, - interproceduralAnalysisConfig, interproceduralAnalysisPredicateOpt: null, pessimisticAnalysis, performCopyAnalysis); - if (pointsToAnalysisResult != null) + if (cfg != null) { - var result = TryGetOrComputeResult(cfg, owningSymbol, analyzerOptions, wellKnownTypeProvider, - nullCheckValidationMethods, interproceduralAnalysisConfig, pessimisticAnalysis, pointsToAnalysisResult); - if (result != null) + var wellKnownTypeProvider = WellKnownTypeProvider.GetOrCreate(compilation); + var pointsToAnalysisResult = PointsToAnalysis.PointsToAnalysis.TryGetOrComputeResult(cfg, owningSymbol, analyzerOptions, wellKnownTypeProvider, + interproceduralAnalysisConfig, interproceduralAnalysisPredicateOpt: null, pessimisticAnalysis, performCopyAnalysis); + if (pointsToAnalysisResult != null) { - return result.HazardousParameterUsages; + var result = TryGetOrComputeResult(cfg, owningSymbol, analyzerOptions, wellKnownTypeProvider, + nullCheckValidationMethods, interproceduralAnalysisConfig, pessimisticAnalysis, pointsToAnalysisResult); + if (result != null) + { + return result.HazardousParameterUsages; + } } } return ImmutableDictionary.Empty; } - private static ParameterValidationAnalysisResult TryGetOrComputeResult( + private static ParameterValidationAnalysisResult? TryGetOrComputeResult( ControlFlowGraph cfg, ISymbol owningSymbol, AnalyzerOptions analyzerOptions, @@ -86,15 +87,13 @@ private ParameterValidationAnalysis(ParameterValidationAnalysisDomain analysisDo bool pessimisticAnalysis, PointsToAnalysisResult pointsToAnalysisResult) { - Debug.Assert(pointsToAnalysisResult != null); - var analysisContext = ParameterValidationAnalysisContext.Create(ParameterValidationAbstractValueDomain.Default, wellKnownTypeProvider, cfg, owningSymbol, analyzerOptions, nullCheckValidationMethods, interproceduralAnalysisConfig, pessimisticAnalysis, pointsToAnalysisResult, TryGetOrComputeResultForAnalysisContext); return TryGetOrComputeResultForAnalysisContext(analysisContext); } - private static ParameterValidationAnalysisResult TryGetOrComputeResultForAnalysisContext(ParameterValidationAnalysisContext analysisContext) + private static ParameterValidationAnalysisResult? TryGetOrComputeResultForAnalysisContext(ParameterValidationAnalysisContext analysisContext) { var operationVisitor = new ParameterValidationDataFlowOperationVisitor(analysisContext); var analysis = new ParameterValidationAnalysis(ParameterValidationAnalysisDomainInstance, operationVisitor); @@ -121,7 +120,7 @@ private static ParameterValidationAnalysisResult TryGetOrComputeResultForAnalysi if (block.ConditionalSuccessor != null) { - _ = FlowBranch(newOperationVisitor, block.FallThroughSuccessor, data); + _ = FlowBranch(newOperationVisitor, block.ConditionalSuccessor, data); } } diff --git a/src/Utilities/FlowAnalysis/FlowAnalysis/Analysis/ParameterValidationAnalysis/ParameterValidationAnalysisContext.cs b/src/Utilities/FlowAnalysis/FlowAnalysis/Analysis/ParameterValidationAnalysis/ParameterValidationAnalysisContext.cs index a0a378d865..6508ab8a04 100644 --- a/src/Utilities/FlowAnalysis/FlowAnalysis/Analysis/ParameterValidationAnalysis/ParameterValidationAnalysisContext.cs +++ b/src/Utilities/FlowAnalysis/FlowAnalysis/Analysis/ParameterValidationAnalysis/ParameterValidationAnalysisContext.cs @@ -29,10 +29,10 @@ internal sealed class ParameterValidationAnalysisContext : AbstractDataFlowAnaly SymbolNamesOption nullCheckValidationMethods, InterproceduralAnalysisConfiguration interproceduralAnalysisConfig, bool pessimisticAnalysis, - PointsToAnalysisResult pointsToAnalysisResultOpt, - Func tryGetOrComputeAnalysisResult, - ControlFlowGraph parentControlFlowGraphOpt, - InterproceduralParameterValidationAnalysisData interproceduralAnalysisDataOpt, + PointsToAnalysisResult? pointsToAnalysisResultOpt, + Func tryGetOrComputeAnalysisResult, + ControlFlowGraph? parentControlFlowGraphOpt, + InterproceduralParameterValidationAnalysisData? interproceduralAnalysisDataOpt, bool trackHazardousParameterUsages) : base(valueDomain, wellKnownTypeProvider, controlFlowGraph, owningSymbol, analyzerOptions, interproceduralAnalysisConfig, pessimisticAnalysis, predicateAnalysis: false, exceptionPathsAnalysis: false, @@ -53,8 +53,8 @@ internal sealed class ParameterValidationAnalysisContext : AbstractDataFlowAnaly SymbolNamesOption nullCheckValidationMethods, InterproceduralAnalysisConfiguration interproceduralAnalysisConfig, bool pessimisticAnalysis, - PointsToAnalysisResult pointsToAnalysisResultOpt, - Func tryGetOrComputeAnalysisResult) + PointsToAnalysisResult? pointsToAnalysisResultOpt, + Func tryGetOrComputeAnalysisResult) { return new ParameterValidationAnalysisContext( valueDomain, wellKnownTypeProvider, controlFlowGraph, owningSymbol, @@ -67,10 +67,10 @@ internal sealed class ParameterValidationAnalysisContext : AbstractDataFlowAnaly IMethodSymbol invokedMethod, ControlFlowGraph invokedCfg, IOperation operation, - PointsToAnalysisResult pointsToAnalysisResultOpt, - CopyAnalysisResult copyAnalysisResultOpt, - ValueContentAnalysisResult valueContentAnalysisResultOpt, - InterproceduralParameterValidationAnalysisData interproceduralAnalysisData) + PointsToAnalysisResult? pointsToAnalysisResultOpt, + CopyAnalysisResult? copyAnalysisResultOpt, + ValueContentAnalysisResult? valueContentAnalysisResultOpt, + InterproceduralParameterValidationAnalysisData? interproceduralAnalysisData) { Debug.Assert(pointsToAnalysisResultOpt != null); Debug.Assert(copyAnalysisResultOpt == null); diff --git a/src/Utilities/FlowAnalysis/FlowAnalysis/Analysis/PointsToAnalysis/PointsToAbstractValue.cs b/src/Utilities/FlowAnalysis/FlowAnalysis/Analysis/PointsToAnalysis/PointsToAbstractValue.cs index d66a8de1ae..67becc8c00 100644 --- a/src/Utilities/FlowAnalysis/FlowAnalysis/Analysis/PointsToAnalysis/PointsToAbstractValue.cs +++ b/src/Utilities/FlowAnalysis/FlowAnalysis/Analysis/PointsToAnalysis/PointsToAbstractValue.cs @@ -33,7 +33,7 @@ private PointsToAbstractValue(ImmutableHashSet locations, Null Debug.Assert(locations.All(location => !location.IsNull) || nullState != NullAbstractValue.NotNull); Debug.Assert(nullState != NullAbstractValue.Undefined); Debug.Assert(nullState != NullAbstractValue.Invalid); - Debug.Assert(!locations.Any(l => l.IsAnalysisEntityDefaultLocation && l.AnalysisEntityOpt.HasUnknownInstanceLocation)); + Debug.Assert(!locations.Any(l => l.IsAnalysisEntityDefaultLocation && l.AnalysisEntityOpt!.HasUnknownInstanceLocation)); Debug.Assert(locations.Count <= LocationThreshold); Locations = locations; @@ -73,7 +73,6 @@ internal static PointsToAbstractValue Create(AbstractLocation location, bool may internal static PointsToAbstractValue Create(IOperation lValueCapturedOperation) { - Debug.Assert(lValueCapturedOperation != null); return new PointsToAbstractValue(ImmutableHashSet.Create(lValueCapturedOperation)); } diff --git a/src/Utilities/FlowAnalysis/FlowAnalysis/Analysis/PointsToAnalysis/PointsToAnalysis.CorePointsToAnalysisDataDomain.cs b/src/Utilities/FlowAnalysis/FlowAnalysis/Analysis/PointsToAnalysis/PointsToAnalysis.CorePointsToAnalysisDataDomain.cs index 661d5e954f..c77975c49d 100644 --- a/src/Utilities/FlowAnalysis/FlowAnalysis/Analysis/PointsToAnalysis/PointsToAnalysis.CorePointsToAnalysisDataDomain.cs +++ b/src/Utilities/FlowAnalysis/FlowAnalysis/Analysis/PointsToAnalysis/PointsToAnalysis.CorePointsToAnalysisDataDomain.cs @@ -48,11 +48,6 @@ protected override void AssertValidAnalysisData(CorePointsToAnalysisData map) Func> getChildAnalysisEntities, Action resetAbstractValue) { - Debug.Assert(forwardEdgeAnalysisData != null); - Debug.Assert(backEdgeAnalysisData != null); - Debug.Assert(forwardEdgeAnalysisData.CoreAnalysisData != null); - Debug.Assert(backEdgeAnalysisData.CoreAnalysisData != null); - // Stop tracking points to values present in both branches if their is an assignment to a may-be null value from the back edge. // Clone the input forwardEdgeAnalysisData to ensure we don't overwrite the input dictionary. forwardEdgeAnalysisData = (PointsToAnalysisData)forwardEdgeAnalysisData.Clone(); diff --git a/src/Utilities/FlowAnalysis/FlowAnalysis/Analysis/PointsToAnalysis/PointsToAnalysis.PointsToAbstractValueDomain.cs b/src/Utilities/FlowAnalysis/FlowAnalysis/Analysis/PointsToAnalysis/PointsToAnalysis.PointsToAbstractValueDomain.cs index 03afd0c152..0bc6076efd 100644 --- a/src/Utilities/FlowAnalysis/FlowAnalysis/Analysis/PointsToAnalysis/PointsToAnalysis.PointsToAbstractValueDomain.cs +++ b/src/Utilities/FlowAnalysis/FlowAnalysis/Analysis/PointsToAnalysis/PointsToAnalysis.PointsToAbstractValueDomain.cs @@ -23,9 +23,6 @@ private class PointsToAbstractValueDomain : AbstractValueDomain> argumentValuesMap, - IDictionary pointsToValuesOpt, - IDictionary copyValuesOpt, - IDictionary valueContentValuesOpt, + IDictionary? pointsToValuesOpt, + IDictionary? copyValuesOpt, + IDictionary? valueContentValuesOpt, bool isLambdaOrLocalFunction, bool hasParameterWithDelegateType) { @@ -575,9 +573,6 @@ private void HandleEscapingOperation(IOperation escapingOperation, IOperation es private void HandleEscapingOperation(IOperation escapingOperation, IOperation escapedInstance, PooledDictionary.Builder> builder) { - Debug.Assert(escapingOperation != null); - Debug.Assert(escapedInstance != null); - PointsToAbstractValue escapedInstancePointsToValue = GetPointsToAbstractValue(escapedInstance); if (escapedInstancePointsToValue.Kind == PointsToAbstractValueKind.KnownLValueCaptures) { @@ -596,12 +591,10 @@ private void HandleEscapingOperation(IOperation escapingOperation, IOperation es private void HandleEscapingLocations( TKey key, PooledDictionary.Builder> escapedLocationsBuilder, - AnalysisEntity escapedEntityOpt, + AnalysisEntity? escapedEntityOpt, PointsToAbstractValue escapedInstancePointsToValue) where TKey : class { - Debug.Assert(key != null); - // Start by clearing escaped locations from previous flow analysis iterations. if (escapedLocationsBuilder.TryGetValue(key, out var builder)) { @@ -674,7 +667,7 @@ private void HandlePossibleEscapingForAssignment(IOperation target, IOperation v } } - protected override void SetAbstractValueForAssignment(IOperation target, IOperation assignedValueOperation, PointsToAbstractValue assignedValue, bool mayBeAssignment = false) + protected override void SetAbstractValueForAssignment(IOperation target, IOperation? assignedValueOperation, PointsToAbstractValue assignedValue, bool mayBeAssignment = false) { base.SetAbstractValueForAssignment(target, assignedValueOperation, assignedValue, mayBeAssignment); @@ -695,7 +688,7 @@ protected override void SetAbstractValueForArrayElementInitializer(IArrayCreatio #region Visitor methods - public override PointsToAbstractValue DefaultVisit(IOperation operation, object argument) + public override PointsToAbstractValue DefaultVisit(IOperation operation, object? argument) { _ = base.DefaultVisit(operation, argument); @@ -731,7 +724,7 @@ public override PointsToAbstractValue VisitIsType(IIsTypeOperation operation, ob public override PointsToAbstractValue VisitInstanceReference(IInstanceReferenceOperation operation, object argument) { _ = base.VisitInstanceReference(operation, argument); - IOperation currentInstanceOperation = operation.GetInstance(IsInsideAnonymousObjectInitializer); + IOperation? currentInstanceOperation = operation.GetInstance(IsInsideAnonymousObjectInitializer); var value = currentInstanceOperation != null ? GetCachedAbstractValue(currentInstanceOperation) : ThisOrMePointsToAbstractValue; @@ -837,13 +830,13 @@ public override PointsToAbstractValue VisitTypeOf(ITypeOfOperation operation, ob return PointsToAbstractValue.NoLocation; } - private PointsToAbstractValue VisitInvocationCommon(IOperation operation, IOperation instance) + private PointsToAbstractValue VisitInvocationCommon(IOperation operation, IOperation? instance) { if (ShouldBeTracked(operation.Type)) { if (TryGetInterproceduralAnalysisResult(operation, out var interproceduralResult)) { - return interproceduralResult.ReturnValueAndPredicateKindOpt.Value.Value; + return interproceduralResult.ReturnValueAndPredicateKindOpt!.Value.Value; } AbstractLocation location = AbstractLocation.CreateAllocationLocation(operation, operation.Type, DataFlowAnalysisContext); @@ -858,7 +851,7 @@ private PointsToAbstractValue VisitInvocationCommon(IOperation operation, IOpera public override PointsToAbstractValue VisitInvocation_NonLambdaOrDelegateOrLocalFunction( IMethodSymbol method, - IOperation visitedInstance, + IOperation? visitedInstance, ImmutableArray visitedArguments, bool invokedAsDelegate, IOperation originalOperation, @@ -950,7 +943,7 @@ public override PointsToAbstractValue VisitDynamicInvocation(IDynamicInvocationO return VisitInvocationCommon(operation, operation.Operation); } - private NullAbstractValue GetNullStateBasedOnInstanceOrReferenceValue(IOperation referenceOrInstance, ITypeSymbol operationType, NullAbstractValue defaultValue) + private NullAbstractValue GetNullStateBasedOnInstanceOrReferenceValue(IOperation? referenceOrInstance, ITypeSymbol operationType, NullAbstractValue defaultValue) { if (operationType.IsNonNullableValueType()) { @@ -969,7 +962,7 @@ private NullAbstractValue GetNullStateBasedOnInstanceOrReferenceValue(IOperation } } - private PointsToAbstractValue GetValueBasedOnInstanceOrReferenceValue(IOperation referenceOrInstance, IOperation operation, PointsToAbstractValue defaultValue) + private PointsToAbstractValue GetValueBasedOnInstanceOrReferenceValue(IOperation? referenceOrInstance, IOperation operation, PointsToAbstractValue defaultValue) { NullAbstractValue nullState = GetNullStateBasedOnInstanceOrReferenceValue(referenceOrInstance, operation.Type, defaultValue.NullState); return nullState switch @@ -1132,7 +1125,7 @@ public override PointsToAbstractValue VisitFlowCapture(IFlowCaptureOperation ope { var value = base.VisitFlowCapture(operation, argument); if (IsLValueFlowCapture(operation) && - AnalysisEntityFactory.TryCreate(operation, out AnalysisEntity flowCaptureEntity)) + AnalysisEntityFactory.TryCreate(operation, out var flowCaptureEntity)) { value = PointsToAbstractValue.Create(operation.Value); SetAbstractValue(flowCaptureEntity, value); @@ -1145,7 +1138,7 @@ public override PointsToAbstractValue VisitFlowCaptureReference(IFlowCaptureRefe { var value = base.VisitFlowCaptureReference(operation, argument); if (IsLValueFlowCaptureReference(operation) && - AnalysisEntityFactory.TryCreate(operation, out AnalysisEntity flowCaptureEntity)) + AnalysisEntityFactory.TryCreate(operation, out var flowCaptureEntity)) { return GetAbstractValue(flowCaptureEntity); } diff --git a/src/Utilities/FlowAnalysis/FlowAnalysis/Analysis/PointsToAnalysis/PointsToAnalysis.cs b/src/Utilities/FlowAnalysis/FlowAnalysis/Analysis/PointsToAnalysis/PointsToAnalysis.cs index e75ada110c..5466ab0278 100644 --- a/src/Utilities/FlowAnalysis/FlowAnalysis/Analysis/PointsToAnalysis/PointsToAnalysis.cs +++ b/src/Utilities/FlowAnalysis/FlowAnalysis/Analysis/PointsToAnalysis/PointsToAnalysis.cs @@ -23,13 +23,13 @@ private PointsToAnalysis(PointsToAnalysisDomain analysisDomain, PointsToDataFlow { } - public static PointsToAnalysisResult TryGetOrComputeResult( + public static PointsToAnalysisResult? TryGetOrComputeResult( ControlFlowGraph cfg, ISymbol owningSymbol, AnalyzerOptions analyzerOptions, WellKnownTypeProvider wellKnownTypeProvider, InterproceduralAnalysisConfiguration interproceduralAnalysisConfig, - InterproceduralAnalysisPredicate interproceduralAnalysisPredicateOpt, + InterproceduralAnalysisPredicate? interproceduralAnalysisPredicateOpt, bool pessimisticAnalysis = true, bool performCopyAnalysis = false, bool exceptionPathsAnalysis = false) @@ -39,14 +39,14 @@ private PointsToAnalysis(PointsToAnalysisDomain analysisDomain, PointsToDataFlow pessimisticAnalysis, performCopyAnalysis, exceptionPathsAnalysis); } - public static PointsToAnalysisResult TryGetOrComputeResult( + public static PointsToAnalysisResult? TryGetOrComputeResult( ControlFlowGraph cfg, ISymbol owningSymbol, AnalyzerOptions analyzerOptions, WellKnownTypeProvider wellKnownTypeProvider, - out CopyAnalysisResult copyAnalysisResultOpt, + out CopyAnalysisResult? copyAnalysisResultOpt, InterproceduralAnalysisConfiguration interproceduralAnalysisConfig, - InterproceduralAnalysisPredicate interproceduralAnalysisPredicateOpt, + InterproceduralAnalysisPredicate? interproceduralAnalysisPredicateOpt, bool pessimisticAnalysis = true, bool performCopyAnalysis = false, bool exceptionPathsAnalysis = false) @@ -68,7 +68,7 @@ private PointsToAnalysis(PointsToAnalysisDomain analysisDomain, PointsToDataFlow return TryGetOrComputeResultForAnalysisContext(analysisContext); } - private static PointsToAnalysisResult TryGetOrComputeResultForAnalysisContext(PointsToAnalysisContext analysisContext) + private static PointsToAnalysisResult? TryGetOrComputeResultForAnalysisContext(PointsToAnalysisContext analysisContext) { using var trackedEntitiesBuilder = new TrackedEntitiesBuilder(); var defaultPointsToValueGenerator = new DefaultPointsToValueGenerator(trackedEntitiesBuilder); diff --git a/src/Utilities/FlowAnalysis/FlowAnalysis/Analysis/PointsToAnalysis/PointsToAnalysisContext.cs b/src/Utilities/FlowAnalysis/FlowAnalysis/Analysis/PointsToAnalysis/PointsToAnalysisContext.cs index 33bb2bff16..a5dc03d12b 100644 --- a/src/Utilities/FlowAnalysis/FlowAnalysis/Analysis/PointsToAnalysis/PointsToAnalysisContext.cs +++ b/src/Utilities/FlowAnalysis/FlowAnalysis/Analysis/PointsToAnalysis/PointsToAnalysisContext.cs @@ -27,11 +27,11 @@ public sealed class PointsToAnalysisContext : AbstractDataFlowAnalysisContext tryGetOrComputeAnalysisResult, - ControlFlowGraph parentControlFlowGraphOpt, - InterproceduralPointsToAnalysisData interproceduralAnalysisDataOpt, - InterproceduralAnalysisPredicate interproceduralAnalysisPredicateOpt) + CopyAnalysisResult? copyAnalysisResultOpt, + Func tryGetOrComputeAnalysisResult, + ControlFlowGraph? parentControlFlowGraphOpt, + InterproceduralPointsToAnalysisData? interproceduralAnalysisDataOpt, + InterproceduralAnalysisPredicate? interproceduralAnalysisPredicateOpt) : base(valueDomain, wellKnownTypeProvider, controlFlowGraph, owningSymbol, analyzerOptions, interproceduralAnalysisConfig, pessimisticAnalysis, predicateAnalysis: true, exceptionPathsAnalysis, copyAnalysisResultOpt, pointsToAnalysisResultOpt: null, valueContentAnalysisResultOpt: null, tryGetOrComputeAnalysisResult, parentControlFlowGraphOpt, interproceduralAnalysisDataOpt, interproceduralAnalysisPredicateOpt) @@ -47,9 +47,9 @@ public sealed class PointsToAnalysisContext : AbstractDataFlowAnalysisContext tryGetOrComputeAnalysisResult, - InterproceduralAnalysisPredicate interproceduralAnalysisPredicateOpt) + CopyAnalysisResult? copyAnalysisResultOpt, + Func tryGetOrComputeAnalysisResult, + InterproceduralAnalysisPredicate? interproceduralAnalysisPredicateOpt) { return new PointsToAnalysisContext(valueDomain, wellKnownTypeProvider, controlFlowGraph, owningSymbol, analyzerOptions, interproceduralAnalysisConfig, pessimisticAnalysis, exceptionPathsAnalysis, copyAnalysisResultOpt, tryGetOrComputeAnalysisResult, parentControlFlowGraphOpt: null, @@ -60,10 +60,10 @@ public sealed class PointsToAnalysisContext : AbstractDataFlowAnalysisContextInterprocedural dataflow analysis configuration. /// Whether to be pessimistic. /// Property set analysis result. - internal static PropertySetAnalysisResult GetOrComputeResult( + internal static PropertySetAnalysisResult? GetOrComputeResult( ControlFlowGraph cfg, Compilation compilation, ISymbol owningSymbol, @@ -75,8 +75,8 @@ private PropertySetAnalysis(PropertySetAnalysisDomain analysisDomain, PropertySe var wellKnownTypeProvider = WellKnownTypeProvider.GetOrCreate(compilation); - PointsToAnalysisResult pointsToAnalysisResult; - ValueContentAnalysisResult valueContentAnalysisResultOpt; + PointsToAnalysisResult? pointsToAnalysisResult; + ValueContentAnalysisResult? valueContentAnalysisResultOpt; if (!constructorMapper.RequiresValueContentAnalysis && !propertyMappers.RequiresValueContentAnalysis) { pointsToAnalysisResult = PointsToAnalysis.TryGetOrComputeResult( @@ -131,6 +131,7 @@ private PropertySetAnalysis(PropertySetAnalysisDomain analysisDomain, PropertySe var result = TryGetOrComputeResultForAnalysisContext(analysisContext); return result; } + /// /// Gets hazardous usages of an object based on a set of its properties. /// @@ -144,7 +145,7 @@ private PropertySetAnalysis(PropertySetAnalysisDomain analysisDomain, PropertySe /// Whether to be pessimistic. /// Dictionary of and pairs mapping to the kind of hazardous usage (Flagged or MaybeFlagged). The method in the key is null for return/initialization statements. /// Unlike , this overload also performs DFA on all descendant local and anonymous functions. - public static PooledDictionary<(Location Location, IMethodSymbol Method), HazardousUsageEvaluationResult> BatchGetOrComputeHazardousUsages( + public static PooledDictionary<(Location Location, IMethodSymbol Method), HazardousUsageEvaluationResult>? BatchGetOrComputeHazardousUsages( Compilation compilation, IEnumerable<(IOperation Operation, ISymbol ContainingSymbol)> rootOperationsNeedingAnalysis, AnalyzerOptions analyzerOptions, @@ -180,7 +181,7 @@ private PropertySetAnalysis(PropertySetAnalysisDomain analysisDomain, PropertySe /// Whether to be pessimistic. /// Dictionary of and pairs mapping to the kind of hazardous usage (Flagged or MaybeFlagged). The method in the key is null for return/initialization statements. /// Unlike , this overload also performs DFA on all descendant local and anonymous functions. - public static PooledDictionary<(Location Location, IMethodSymbol Method), HazardousUsageEvaluationResult> BatchGetOrComputeHazardousUsages( + public static PooledDictionary<(Location Location, IMethodSymbol Method), HazardousUsageEvaluationResult>? BatchGetOrComputeHazardousUsages( Compilation compilation, IEnumerable<(IOperation Operation, ISymbol ContainingSymbol)> rootOperationsNeedingAnalysis, AnalyzerOptions analyzerOptions, @@ -191,10 +192,10 @@ private PropertySetAnalysis(PropertySetAnalysisDomain analysisDomain, PropertySe InterproceduralAnalysisConfiguration interproceduralAnalysisConfig, bool pessimisticAnalysis = false) { - PooledDictionary<(Location Location, IMethodSymbol Method), HazardousUsageEvaluationResult> allResults = null; + PooledDictionary<(Location Location, IMethodSymbol Method), HazardousUsageEvaluationResult>? allResults = null; foreach ((IOperation Operation, ISymbol ContainingSymbol) in rootOperationsNeedingAnalysis) { - var success = Operation.TryGetEnclosingControlFlowGraph(out ControlFlowGraph enclosingControlFlowGraph); + var success = Operation.TryGetEnclosingControlFlowGraph(out ControlFlowGraph? enclosingControlFlowGraph); Debug.Assert(success); if (enclosingControlFlowGraph == null) { @@ -202,7 +203,7 @@ private PropertySetAnalysis(PropertySetAnalysisDomain analysisDomain, PropertySe continue; } - PropertySetAnalysisResult enclosingResult = InvokeDfaAndAccumulateResults( + PropertySetAnalysisResult? enclosingResult = InvokeDfaAndAccumulateResults( enclosingControlFlowGraph, ContainingSymbol); if (enclosingResult == null) @@ -237,9 +238,9 @@ private PropertySetAnalysis(PropertySetAnalysisDomain analysisDomain, PropertySe return allResults; // Merges results from single PropertySet DFA invocation into allResults. - PropertySetAnalysisResult InvokeDfaAndAccumulateResults(ControlFlowGraph cfg, ISymbol owningSymbol) + PropertySetAnalysisResult? InvokeDfaAndAccumulateResults(ControlFlowGraph cfg, ISymbol owningSymbol) { - PropertySetAnalysisResult propertySetAnalysisResult = + PropertySetAnalysisResult? propertySetAnalysisResult = PropertySetAnalysis.GetOrComputeResult( cfg, compilation, @@ -300,7 +301,7 @@ public static HazardousUsageEvaluationResult MergeHazardousUsageEvaluationResult } } - private static PropertySetAnalysisResult TryGetOrComputeResultForAnalysisContext(PropertySetAnalysisContext analysisContext) + private static PropertySetAnalysisResult? TryGetOrComputeResultForAnalysisContext(PropertySetAnalysisContext analysisContext) { var operationVisitor = new PropertySetDataFlowOperationVisitor(analysisContext); var analysis = new PropertySetAnalysis(PropertySetAnalysisDomainInstance, operationVisitor); diff --git a/src/Utilities/FlowAnalysis/FlowAnalysis/Analysis/PropertySetAnalysis/PropertySetAnalysisContext.cs b/src/Utilities/FlowAnalysis/FlowAnalysis/Analysis/PropertySetAnalysis/PropertySetAnalysisContext.cs index 2552ae6d61..30d51db9b1 100644 --- a/src/Utilities/FlowAnalysis/FlowAnalysis/Analysis/PropertySetAnalysis/PropertySetAnalysisContext.cs +++ b/src/Utilities/FlowAnalysis/FlowAnalysis/Analysis/PropertySetAnalysis/PropertySetAnalysisContext.cs @@ -31,11 +31,11 @@ internal sealed class PropertySetAnalysisContext : AbstractDataFlowAnalysisConte AnalyzerOptions analyzerOptions, InterproceduralAnalysisConfiguration interproceduralAnalysisConfig, bool pessimisticAnalysis, - PointsToAnalysisResult pointsToAnalysisResult, - ValueContentAnalysisResult valueContentAnalysisResultOpt, - Func tryGetOrComputeAnalysisResult, - ControlFlowGraph parentControlFlowGraphOpt, - InterproceduralPropertySetAnalysisData interproceduralAnalysisDataOpt, + PointsToAnalysisResult? pointsToAnalysisResult, + ValueContentAnalysisResult? valueContentAnalysisResultOpt, + Func tryGetOrComputeAnalysisResult, + ControlFlowGraph? parentControlFlowGraphOpt, + InterproceduralPropertySetAnalysisData? interproceduralAnalysisDataOpt, ImmutableHashSet typeToTrackMetadataNames, ConstructorMapper constructorMapper, PropertyMapperCollection propertyMappers, @@ -74,9 +74,9 @@ internal sealed class PropertySetAnalysisContext : AbstractDataFlowAnalysisConte AnalyzerOptions analyzerOptions, InterproceduralAnalysisConfiguration interproceduralAnalysisConfig, bool pessimisticAnalysis, - PointsToAnalysisResult pointsToAnalysisResult, - ValueContentAnalysisResult valueContentAnalysisResultOpt, - Func tryGetOrComputeAnalysisResult, + PointsToAnalysisResult? pointsToAnalysisResult, + ValueContentAnalysisResult? valueContentAnalysisResultOpt, + Func tryGetOrComputeAnalysisResult, ImmutableHashSet typeToTrackMetadataNames, ConstructorMapper constructorMapper, PropertyMapperCollection propertyMappers, @@ -106,10 +106,10 @@ internal sealed class PropertySetAnalysisContext : AbstractDataFlowAnalysisConte IMethodSymbol invokedMethod, ControlFlowGraph invokedCfg, IOperation operation, - PointsToAnalysisResult pointsToAnalysisResultOpt, - CopyAnalysisResult copyAnalysisResultOpt, - ValueContentAnalysisResult valueContentAnalysisResultOpt, - InterproceduralPropertySetAnalysisData interproceduralAnalysisData) + PointsToAnalysisResult? pointsToAnalysisResultOpt, + CopyAnalysisResult? copyAnalysisResultOpt, + ValueContentAnalysisResult? valueContentAnalysisResultOpt, + InterproceduralPropertySetAnalysisData? interproceduralAnalysisData) { Debug.Assert(pointsToAnalysisResultOpt != null); Debug.Assert(copyAnalysisResultOpt == null); diff --git a/src/Utilities/FlowAnalysis/FlowAnalysis/Analysis/TaintedDataAnalysis/TaintedDataAnalysis.cs b/src/Utilities/FlowAnalysis/FlowAnalysis/Analysis/TaintedDataAnalysis/TaintedDataAnalysis.cs index c15383cb11..c5b83ed00f 100644 --- a/src/Utilities/FlowAnalysis/FlowAnalysis/Analysis/TaintedDataAnalysis/TaintedDataAnalysis.cs +++ b/src/Utilities/FlowAnalysis/FlowAnalysis/Analysis/TaintedDataAnalysis/TaintedDataAnalysis.cs @@ -24,7 +24,7 @@ private TaintedDataAnalysis(TaintedDataOperationVisitor operationVisitor) { } - internal static TaintedDataAnalysisResult TryGetOrComputeResult( + internal static TaintedDataAnalysisResult? TryGetOrComputeResult( ControlFlowGraph cfg, Compilation compilation, ISymbol containingMethod, @@ -41,7 +41,7 @@ private TaintedDataAnalysis(TaintedDataOperationVisitor operationVisitor) taintedSanitizerInfos, taintedSinkInfos, interproceduralAnalysisConfig); } - private static TaintedDataAnalysisResult TryGetOrComputeResult( + private static TaintedDataAnalysisResult? TryGetOrComputeResult( ControlFlowGraph cfg, Compilation compilation, ISymbol containingMethod, @@ -58,21 +58,21 @@ private TaintedDataAnalysis(TaintedDataOperationVisitor operationVisitor) } WellKnownTypeProvider wellKnownTypeProvider = WellKnownTypeProvider.GetOrCreate(compilation); - ValueContentAnalysisResult valueContentAnalysisResult = null; - CopyAnalysisResult copyAnalysisResult = null; - PointsToAnalysisResult pointsToAnalysisResult = null; + ValueContentAnalysisResult? valueContentAnalysisResult = null; + CopyAnalysisResult? copyAnalysisResult = null; + PointsToAnalysisResult? pointsToAnalysisResult = null; if (taintedSourceInfos.RequiresValueContentAnalysis || taintedSanitizerInfos.RequiresValueContentAnalysis || taintedSinkInfos.RequiresValueContentAnalysis) { valueContentAnalysisResult = ValueContentAnalysis.TryGetOrComputeResult( - cfg, - containingMethod, - analyzerOptions, - wellKnownTypeProvider, - interproceduralAnalysisConfig, - out copyAnalysisResult, - out pointsToAnalysisResult, - pessimisticAnalysis: true, - performCopyAnalysis: false); + cfg, + containingMethod, + analyzerOptions, + wellKnownTypeProvider, + interproceduralAnalysisConfig, + out copyAnalysisResult, + out pointsToAnalysisResult, + pessimisticAnalysis: true, + performCopyAnalysis: false); if (valueContentAnalysisResult == null) { return null; @@ -81,14 +81,14 @@ private TaintedDataAnalysis(TaintedDataOperationVisitor operationVisitor) else { pointsToAnalysisResult = PointsToAnalysis.TryGetOrComputeResult( - cfg, - containingMethod, - analyzerOptions, - wellKnownTypeProvider, - interproceduralAnalysisConfig, - interproceduralAnalysisPredicateOpt: null, - pessimisticAnalysis: true, - performCopyAnalysis: false); + cfg, + containingMethod, + analyzerOptions, + wellKnownTypeProvider, + interproceduralAnalysisConfig, + interproceduralAnalysisPredicateOpt: null, + pessimisticAnalysis: true, + performCopyAnalysis: false); if (pointsToAnalysisResult == null) { return null; @@ -114,7 +114,7 @@ private TaintedDataAnalysis(TaintedDataOperationVisitor operationVisitor) return TryGetOrComputeResultForAnalysisContext(analysisContext); } - private static TaintedDataAnalysisResult TryGetOrComputeResultForAnalysisContext(TaintedDataAnalysisContext analysisContext) + private static TaintedDataAnalysisResult? TryGetOrComputeResultForAnalysisContext(TaintedDataAnalysisContext analysisContext) { TaintedDataOperationVisitor visitor = new TaintedDataOperationVisitor(analysisContext); TaintedDataAnalysis analysis = new TaintedDataAnalysis(visitor); diff --git a/src/Utilities/FlowAnalysis/FlowAnalysis/Analysis/TaintedDataAnalysis/TaintedDataAnalysisContext.cs b/src/Utilities/FlowAnalysis/FlowAnalysis/Analysis/TaintedDataAnalysis/TaintedDataAnalysisContext.cs index 85294b2bcb..ba81c9a4da 100644 --- a/src/Utilities/FlowAnalysis/FlowAnalysis/Analysis/TaintedDataAnalysis/TaintedDataAnalysisContext.cs +++ b/src/Utilities/FlowAnalysis/FlowAnalysis/Analysis/TaintedDataAnalysis/TaintedDataAnalysisContext.cs @@ -26,12 +26,12 @@ internal sealed class TaintedDataAnalysisContext : AbstractDataFlowAnalysisConte AnalyzerOptions analyzerOptions, InterproceduralAnalysisConfiguration interproceduralAnalysisConfig, bool pessimisticAnalysis, - CopyAnalysisResult copyAnalysisResultOpt, - PointsToAnalysisResult pointsToAnalysisResult, - ValueContentAnalysisResult valueContentAnalysisResult, - Func tryGetOrComputeAnalysisResult, - ControlFlowGraph parentControlFlowGraph, - InterproceduralTaintedDataAnalysisData interproceduralAnalysisDataOpt, + CopyAnalysisResult? copyAnalysisResultOpt, + PointsToAnalysisResult? pointsToAnalysisResult, + ValueContentAnalysisResult? valueContentAnalysisResult, + Func tryGetOrComputeAnalysisResult, + ControlFlowGraph? parentControlFlowGraph, + InterproceduralTaintedDataAnalysisData? interproceduralAnalysisDataOpt, TaintedDataSymbolMap taintedSourceInfos, TaintedDataSymbolMap taintedSanitizerInfos, TaintedDataSymbolMap taintedSinkInfos) @@ -68,10 +68,10 @@ internal sealed class TaintedDataAnalysisContext : AbstractDataFlowAnalysisConte AnalyzerOptions analyzerOptions, InterproceduralAnalysisConfiguration interproceduralAnalysisConfig, bool pessimisticAnalysis, - CopyAnalysisResult copyAnalysisResultOpt, - PointsToAnalysisResult pointsToAnalysisResult, - ValueContentAnalysisResult valueContentAnalysisResult, - Func tryGetOrComputeAnalysisResult, + CopyAnalysisResult? copyAnalysisResultOpt, + PointsToAnalysisResult? pointsToAnalysisResult, + ValueContentAnalysisResult? valueContentAnalysisResult, + Func tryGetOrComputeAnalysisResult, TaintedDataSymbolMap taintedSourceInfos, TaintedDataSymbolMap taintedSanitizerInfos, TaintedDataSymbolMap taintedSinkInfos) @@ -101,10 +101,10 @@ internal sealed class TaintedDataAnalysisContext : AbstractDataFlowAnalysisConte IMethodSymbol invokedMethod, ControlFlowGraph invokedCfg, IOperation operation, - PointsToAnalysisResult pointsToAnalysisResultOpt, - DataFlowAnalysisResult copyAnalysisResultOpt, - DataFlowAnalysisResult valueContentAnalysisResultOpt, - InterproceduralTaintedDataAnalysisData interproceduralAnalysisData) + PointsToAnalysisResult? pointsToAnalysisResultOpt, + DataFlowAnalysisResult? copyAnalysisResultOpt, + DataFlowAnalysisResult? valueContentAnalysisResultOpt, + InterproceduralTaintedDataAnalysisData? interproceduralAnalysisData) { return new TaintedDataAnalysisContext( this.ValueDomain, diff --git a/src/Utilities/FlowAnalysis/FlowAnalysis/Analysis/ValueContentAnalysis/ValueContentAbstractValue.cs b/src/Utilities/FlowAnalysis/FlowAnalysis/Analysis/ValueContentAnalysis/ValueContentAbstractValue.cs index 499089e6b4..26ac09fedb 100644 --- a/src/Utilities/FlowAnalysis/FlowAnalysis/Analysis/ValueContentAnalysis/ValueContentAbstractValue.cs +++ b/src/Utilities/FlowAnalysis/FlowAnalysis/Analysis/ValueContentAnalysis/ValueContentAbstractValue.cs @@ -3,6 +3,7 @@ using System; using System.Collections.Immutable; using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; using System.Globalization; using System.Linq; using Analyzer.Utilities; @@ -20,18 +21,18 @@ public partial class ValueContentAbstractValue : CacheBasedEquatable.Empty, ValueContainsNonLiteralState.Undefined); - public static ValueContentAbstractValue InvalidState { get; } = new ValueContentAbstractValue(ImmutableHashSet.Empty, ValueContainsNonLiteralState.Invalid); - public static ValueContentAbstractValue MayBeContainsNonLiteralState { get; } = new ValueContentAbstractValue(ImmutableHashSet.Empty, ValueContainsNonLiteralState.Maybe); - public static ValueContentAbstractValue DoesNotContainLiteralOrNonLiteralState { get; } = new ValueContentAbstractValue(ImmutableHashSet.Empty, ValueContainsNonLiteralState.No); - public static ValueContentAbstractValue ContainsNullLiteralState { get; } = new ValueContentAbstractValue(ImmutableHashSet.Create((object)null), ValueContainsNonLiteralState.No); - public static ValueContentAbstractValue ContainsEmptyStringLiteralState { get; } = new ValueContentAbstractValue(ImmutableHashSet.Create(string.Empty), ValueContainsNonLiteralState.No); - public static ValueContentAbstractValue ContainsZeroIntergralLiteralState { get; } = new ValueContentAbstractValue(ImmutableHashSet.Create(0), ValueContainsNonLiteralState.No); - public static ValueContentAbstractValue ContainsOneIntergralLiteralState { get; } = new ValueContentAbstractValue(ImmutableHashSet.Create(1), ValueContainsNonLiteralState.No); - private static ValueContentAbstractValue ContainsTrueLiteralState { get; } = new ValueContentAbstractValue(ImmutableHashSet.Create(true), ValueContainsNonLiteralState.No); - private static ValueContentAbstractValue ContainsFalseLiteralState { get; } = new ValueContentAbstractValue(ImmutableHashSet.Create(false), ValueContainsNonLiteralState.No); - - private ValueContentAbstractValue(ImmutableHashSet literalValues, ValueContainsNonLiteralState nonLiteralState) + public static ValueContentAbstractValue UndefinedState { get; } = new ValueContentAbstractValue(ImmutableHashSet.Empty, ValueContainsNonLiteralState.Undefined); + public static ValueContentAbstractValue InvalidState { get; } = new ValueContentAbstractValue(ImmutableHashSet.Empty, ValueContainsNonLiteralState.Invalid); + public static ValueContentAbstractValue MayBeContainsNonLiteralState { get; } = new ValueContentAbstractValue(ImmutableHashSet.Empty, ValueContainsNonLiteralState.Maybe); + public static ValueContentAbstractValue DoesNotContainLiteralOrNonLiteralState { get; } = new ValueContentAbstractValue(ImmutableHashSet.Empty, ValueContainsNonLiteralState.No); + public static ValueContentAbstractValue ContainsNullLiteralState { get; } = new ValueContentAbstractValue(ImmutableHashSet.Create((object?)null), ValueContainsNonLiteralState.No); + public static ValueContentAbstractValue ContainsEmptyStringLiteralState { get; } = new ValueContentAbstractValue(ImmutableHashSet.Create(string.Empty), ValueContainsNonLiteralState.No); + public static ValueContentAbstractValue ContainsZeroIntergralLiteralState { get; } = new ValueContentAbstractValue(ImmutableHashSet.Create(0), ValueContainsNonLiteralState.No); + public static ValueContentAbstractValue ContainsOneIntergralLiteralState { get; } = new ValueContentAbstractValue(ImmutableHashSet.Create(1), ValueContainsNonLiteralState.No); + private static ValueContentAbstractValue ContainsTrueLiteralState { get; } = new ValueContentAbstractValue(ImmutableHashSet.Create(true), ValueContainsNonLiteralState.No); + private static ValueContentAbstractValue ContainsFalseLiteralState { get; } = new ValueContentAbstractValue(ImmutableHashSet.Create(false), ValueContainsNonLiteralState.No); + + private ValueContentAbstractValue(ImmutableHashSet literalValues, ValueContainsNonLiteralState nonLiteralState) { LiteralValues = literalValues; NonLiteralState = nonLiteralState; @@ -39,8 +40,6 @@ private ValueContentAbstractValue(ImmutableHashSet literalValues, ValueC internal static ValueContentAbstractValue Create(object literal, ITypeSymbol type) { - Debug.Assert(literal != null); - switch (type.SpecialType) { case SpecialType.System_Byte: @@ -73,10 +72,10 @@ internal static ValueContentAbstractValue Create(object literal, ITypeSymbol typ return ((bool)literal) ? ContainsTrueLiteralState : ContainsFalseLiteralState; } - return new ValueContentAbstractValue(ImmutableHashSet.Create(literal), ValueContainsNonLiteralState.No); + return new ValueContentAbstractValue(ImmutableHashSet.Create(literal), ValueContainsNonLiteralState.No); } - private static ValueContentAbstractValue Create(ImmutableHashSet literalValues, ValueContainsNonLiteralState nonLiteralState) + private static ValueContentAbstractValue Create(ImmutableHashSet literalValues, ValueContainsNonLiteralState nonLiteralState) { if (literalValues.IsEmpty) { @@ -117,7 +116,7 @@ private static ValueContentAbstractValue Create(ImmutableHashSet literal return new ValueContentAbstractValue(literalValues, nonLiteralState); } - internal static bool IsSupportedType(ITypeSymbol type, out ITypeSymbol valueTypeSymbol) + internal static bool IsSupportedType(ITypeSymbol type, [NotNullWhen(returnValue: true)] out ITypeSymbol? valueTypeSymbol) { if (type.IsPrimitiveType()) { @@ -145,7 +144,7 @@ internal static bool IsSupportedType(ITypeSymbol type, out ITypeSymbol valueType /// /// Gets a collection of the literals that could possibly make up the contents of this abstract value. /// - public ImmutableHashSet LiteralValues { get; } + public ImmutableHashSet LiteralValues { get; } protected override void ComputeHashCodeParts(Action addPart) { @@ -164,7 +163,7 @@ internal ValueContentAbstractValue Merge(ValueContentAbstractValue otherState) throw new ArgumentNullException(nameof(otherState)); } - ImmutableHashSet mergedLiteralValues = LiteralValues.AddRange(otherState.LiteralValues); + ImmutableHashSet mergedLiteralValues = LiteralValues.AddRange(otherState.LiteralValues); if (mergedLiteralValues.Count > LiteralsBound) { return MayBeContainsNonLiteralState; @@ -212,11 +211,11 @@ public bool TryGetSingleNonNullLiteral(out T literalValue) { if (!IsLiteralState || LiteralValues.Count != 1) { - literalValue = default; + literalValue = default!; return false; } - object o = LiteralValues.First(); + object? o = LiteralValues.First(); if (o is T v) { literalValue = v; @@ -224,7 +223,7 @@ public bool TryGetSingleNonNullLiteral(out T literalValue) } else { - literalValue = default; + literalValue = default!; return false; } } @@ -256,12 +255,12 @@ internal ValueContentAbstractValue IntersectLiteralValues(ValueContentAbstractVa } // Merge Literals - var builder = PooledHashSet.GetInstance(); + var builder = PooledHashSet.GetInstance(); foreach (var leftLiteral in LiteralValues) { foreach (var rightLiteral in otherState.LiteralValues) { - if (!TryMerge(leftLiteral, rightLiteral, binaryOperatorKind, leftType, rightType, resultType, out object result)) + if (!TryMerge(leftLiteral, rightLiteral, binaryOperatorKind, leftType, rightType, resultType, out object? result)) { return MayBeContainsNonLiteralState; } @@ -270,7 +269,7 @@ internal ValueContentAbstractValue IntersectLiteralValues(ValueContentAbstractVa } } - ImmutableHashSet mergedLiteralValues = builder.ToImmutableAndFree(); + ImmutableHashSet mergedLiteralValues = builder.ToImmutableAndFree(); ValueContainsNonLiteralState mergedNonLiteralState = Merge(NonLiteralState, otherState.NonLiteralState); return Create(mergedLiteralValues, mergedNonLiteralState); @@ -279,10 +278,15 @@ internal ValueContentAbstractValue IntersectLiteralValues(ValueContentAbstractVa public override string ToString() => string.Format(CultureInfo.InvariantCulture, "L({0}) NL:{1}", LiteralValues.Count, NonLiteralState.ToString()[0]); - private static bool TryMerge(object value1, object value2, BinaryOperatorKind binaryOperatorKind, ITypeSymbol type1, ITypeSymbol type2, ITypeSymbol resultType, out object result) + private static bool TryMerge(object? value1, object? value2, BinaryOperatorKind binaryOperatorKind, ITypeSymbol type1, ITypeSymbol type2, ITypeSymbol resultType, [NotNullWhen(returnValue: true)] out object? result) { result = null; + if (value1 == null || value2 == null) + { + return false; + } + try { switch (type1.SpecialType) @@ -393,7 +397,7 @@ private static bool TryMerge(object value1, object value2, BinaryOperatorKind bi return false; } - private static bool TryMerge(char value1, char value2, BinaryOperatorKind binaryOperatorKind, out object result) + private static bool TryMerge(char value1, char value2, BinaryOperatorKind binaryOperatorKind, [NotNullWhen(returnValue: true)] out object? result) { switch (binaryOperatorKind) { @@ -407,7 +411,7 @@ private static bool TryMerge(char value1, char value2, BinaryOperatorKind binary return false; } - private static bool TryMerge(string value1, string value2, BinaryOperatorKind binaryOperatorKind, out object result) + private static bool TryMerge(string value1, string value2, BinaryOperatorKind binaryOperatorKind, [NotNullWhen(returnValue: true)] out object? result) { if (value1 != null && value2 != null) { @@ -424,7 +428,7 @@ private static bool TryMerge(string value1, string value2, BinaryOperatorKind bi return false; } - private static bool TryMerge(bool value1, bool value2, BinaryOperatorKind binaryOperatorKind, out object result) + private static bool TryMerge(bool value1, bool value2, BinaryOperatorKind binaryOperatorKind, [NotNullWhen(returnValue: true)] out object? result) { switch (binaryOperatorKind) { diff --git a/src/Utilities/FlowAnalysis/FlowAnalysis/Analysis/ValueContentAnalysis/ValueContentAnalysis.CoreAnalysisDataDomain.cs b/src/Utilities/FlowAnalysis/FlowAnalysis/Analysis/ValueContentAnalysis/ValueContentAnalysis.CoreAnalysisDataDomain.cs index 3bbbce9496..3a2265d8ec 100644 --- a/src/Utilities/FlowAnalysis/FlowAnalysis/Analysis/ValueContentAnalysis/ValueContentAnalysis.CoreAnalysisDataDomain.cs +++ b/src/Utilities/FlowAnalysis/FlowAnalysis/Analysis/ValueContentAnalysis/ValueContentAnalysis.CoreAnalysisDataDomain.cs @@ -30,9 +30,6 @@ protected override void AssertValidEntryForMergedMap(AnalysisEntity analysisEnti public CoreValueContentAnalysisData MergeAnalysisDataForBackEdge(CoreValueContentAnalysisData forwardEdgeAnalysisData, CoreValueContentAnalysisData backEdgeAnalysisData) { - Debug.Assert(forwardEdgeAnalysisData != null); - Debug.Assert(backEdgeAnalysisData != null); - // Stop tracking values present in both branches if their is an assignment to different literal values from the back edge. // Clone the input forwardEdgeAnalysisData to ensure we don't overwrite the input dictionary. using (forwardEdgeAnalysisData = new CoreValueContentAnalysisData(forwardEdgeAnalysisData)) diff --git a/src/Utilities/FlowAnalysis/FlowAnalysis/Analysis/ValueContentAnalysis/ValueContentAnalysis.ValueContentAbstractDomain.cs b/src/Utilities/FlowAnalysis/FlowAnalysis/Analysis/ValueContentAnalysis/ValueContentAnalysis.ValueContentAbstractDomain.cs index aed8e7df44..3d2903756c 100644 --- a/src/Utilities/FlowAnalysis/FlowAnalysis/Analysis/ValueContentAnalysis/ValueContentAnalysis.ValueContentAbstractDomain.cs +++ b/src/Utilities/FlowAnalysis/FlowAnalysis/Analysis/ValueContentAnalysis/ValueContentAnalysis.ValueContentAbstractDomain.cs @@ -1,7 +1,5 @@ // Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. -using System.Diagnostics; - namespace Microsoft.CodeAnalysis.FlowAnalysis.DataFlow.ValueContentAnalysis { using ValueContentAnalysisResult = DataFlowAnalysisResult; @@ -23,9 +21,6 @@ private sealed class ValueContentAbstractValueDomain : AbstractValueDomain GetTrimmedCurrentAnalysisDataHelper(withEntities, CurrentAnalysisData.CoreAnalysisData, SetAbstractValue); #region Visitor methods - public override ValueContentAbstractValue DefaultVisit(IOperation operation, object argument) + public override ValueContentAbstractValue DefaultVisit(IOperation operation, object? argument) { _ = base.DefaultVisit(operation, argument); if (operation.Type == null) @@ -163,7 +163,7 @@ public override ValueContentAbstractValue DefaultVisit(IOperation operation, obj return ValueContentAbstractValue.ContainsNullLiteralState; } - if (ValueContentAbstractValue.IsSupportedType(operation.Type, out ITypeSymbol valueTypeSymbol)) + if (ValueContentAbstractValue.IsSupportedType(operation.Type, out var valueTypeSymbol)) { if (operation.ConstantValue.HasValue) { @@ -235,7 +235,7 @@ public override ValueContentAbstractValue VisitFieldReference(IFieldReferenceOpe public override ValueContentAbstractValue VisitInvocation_NonLambdaOrDelegateOrLocalFunction( IMethodSymbol method, - IOperation visitedInstance, + IOperation? visitedInstance, ImmutableArray visitedArguments, bool invokedAsDelegate, IOperation originalOperation, diff --git a/src/Utilities/FlowAnalysis/FlowAnalysis/Analysis/ValueContentAnalysis/ValueContentAnalysis.cs b/src/Utilities/FlowAnalysis/FlowAnalysis/Analysis/ValueContentAnalysis/ValueContentAnalysis.cs index b268dfb46a..83998218a1 100644 --- a/src/Utilities/FlowAnalysis/FlowAnalysis/Analysis/ValueContentAnalysis/ValueContentAnalysis.cs +++ b/src/Utilities/FlowAnalysis/FlowAnalysis/Analysis/ValueContentAnalysis/ValueContentAnalysis.cs @@ -22,7 +22,7 @@ private ValueContentAnalysis(ValueContentDataFlowOperationVisitor operationVisit { } - public static ValueContentAnalysisResult TryGetOrComputeResult( + public static ValueContentAnalysisResult? TryGetOrComputeResult( ControlFlowGraph cfg, ISymbol owningSymbol, WellKnownTypeProvider wellKnownTypeProvider, @@ -38,20 +38,20 @@ private ValueContentAnalysis(ValueContentDataFlowOperationVisitor operationVisit pessimisticAnalysis, performPointsToAnalysis); } - public static ValueContentAnalysisResult TryGetOrComputeResult( + public static ValueContentAnalysisResult? TryGetOrComputeResult( ControlFlowGraph cfg, ISymbol owningSymbol, WellKnownTypeProvider wellKnownTypeProvider, AnalyzerOptions analyzerOptions, DiagnosticDescriptor rule, CancellationToken cancellationToken, - out CopyAnalysisResult copyAnalysisResultOpt, - out PointsToAnalysisResult pointsToAnalysisResultOpt, + out CopyAnalysisResult? copyAnalysisResultOpt, + out PointsToAnalysisResult? pointsToAnalysisResultOpt, InterproceduralAnalysisKind interproceduralAnalysisKind = InterproceduralAnalysisKind.None, bool pessimisticAnalysis = true, bool performPointsToAnalysis = true, bool performCopyAnalysisIfNotUserConfigured = false, - InterproceduralAnalysisPredicate interproceduralAnalysisPredicateOpt = null) + InterproceduralAnalysisPredicate? interproceduralAnalysisPredicateOpt = null) { Debug.Assert(!owningSymbol.IsConfiguredToSkipAnalysis(analyzerOptions, rule, wellKnownTypeProvider.Compilation, cancellationToken)); @@ -64,18 +64,18 @@ private ValueContentAnalysis(ValueContentDataFlowOperationVisitor operationVisit interproceduralAnalysisPredicateOpt: interproceduralAnalysisPredicateOpt); } - internal static ValueContentAnalysisResult TryGetOrComputeResult( + internal static ValueContentAnalysisResult? TryGetOrComputeResult( ControlFlowGraph cfg, ISymbol owningSymbol, AnalyzerOptions analyzerOptions, WellKnownTypeProvider wellKnownTypeProvider, InterproceduralAnalysisConfiguration interproceduralAnalysisConfig, - out CopyAnalysisResult copyAnalysisResultOpt, - out PointsToAnalysisResult pointsToAnalysisResultOpt, + out CopyAnalysisResult? copyAnalysisResultOpt, + out PointsToAnalysisResult? pointsToAnalysisResultOpt, bool pessimisticAnalysis = true, bool performPointsToAnalysis = true, bool performCopyAnalysis = false, - InterproceduralAnalysisPredicate interproceduralAnalysisPredicateOpt = null) + InterproceduralAnalysisPredicate? interproceduralAnalysisPredicateOpt = null) { copyAnalysisResultOpt = null; pointsToAnalysisResultOpt = performPointsToAnalysis ? @@ -96,7 +96,7 @@ private ValueContentAnalysis(ValueContentDataFlowOperationVisitor operationVisit return TryGetOrComputeResultForAnalysisContext(analysisContext); } - private static ValueContentAnalysisResult TryGetOrComputeResultForAnalysisContext(ValueContentAnalysisContext analysisContext) + private static ValueContentAnalysisResult? TryGetOrComputeResultForAnalysisContext(ValueContentAnalysisContext analysisContext) { var operationVisitor = new ValueContentDataFlowOperationVisitor(analysisContext); var nullAnalysis = new ValueContentAnalysis(operationVisitor); diff --git a/src/Utilities/FlowAnalysis/FlowAnalysis/Analysis/ValueContentAnalysis/ValueContentAnalysisContext.cs b/src/Utilities/FlowAnalysis/FlowAnalysis/Analysis/ValueContentAnalysis/ValueContentAnalysisContext.cs index cf40f3aab9..40b0452bdc 100644 --- a/src/Utilities/FlowAnalysis/FlowAnalysis/Analysis/ValueContentAnalysis/ValueContentAnalysisContext.cs +++ b/src/Utilities/FlowAnalysis/FlowAnalysis/Analysis/ValueContentAnalysis/ValueContentAnalysisContext.cs @@ -26,12 +26,12 @@ public sealed class ValueContentAnalysisContext : AbstractDataFlowAnalysisContex AnalyzerOptions analyzerOptions, InterproceduralAnalysisConfiguration interproceduralAnalysisConfig, bool pessimisticAnalysis, - CopyAnalysisResult copyAnalysisResultOpt, - PointsToAnalysisResult pointsToAnalysisResultOpt, - Func tryGetOrComputeAnalysisResult, - ControlFlowGraph parentControlFlowGraphOpt, - InterproceduralValueContentAnalysisData interproceduralAnalysisDataOpt, - InterproceduralAnalysisPredicate interproceduralAnalysisPredicateOpt) + CopyAnalysisResult? copyAnalysisResultOpt, + PointsToAnalysisResult? pointsToAnalysisResultOpt, + Func tryGetOrComputeAnalysisResult, + ControlFlowGraph? parentControlFlowGraphOpt, + InterproceduralValueContentAnalysisData? interproceduralAnalysisDataOpt, + InterproceduralAnalysisPredicate? interproceduralAnalysisPredicateOpt) : base(valueDomain, wellKnownTypeProvider, controlFlowGraph, owningSymbol, analyzerOptions, interproceduralAnalysisConfig, pessimisticAnalysis, predicateAnalysis: true, exceptionPathsAnalysis: false, copyAnalysisResultOpt, pointsToAnalysisResultOpt, valueContentAnalysisResultOpt: null, tryGetOrComputeAnalysisResult, parentControlFlowGraphOpt, @@ -47,10 +47,10 @@ public sealed class ValueContentAnalysisContext : AbstractDataFlowAnalysisContex AnalyzerOptions analyzerOptions, InterproceduralAnalysisConfiguration interproceduralAnalysisConfig, bool pessimisticAnalysis, - CopyAnalysisResult copyAnalysisResultOpt, - PointsToAnalysisResult pointsToAnalysisResultOpt, - Func tryGetOrComputeAnalysisResult, - InterproceduralAnalysisPredicate interproceduralAnalysisPredicateOpt) + CopyAnalysisResult? copyAnalysisResultOpt, + PointsToAnalysisResult? pointsToAnalysisResultOpt, + Func tryGetOrComputeAnalysisResult, + InterproceduralAnalysisPredicate? interproceduralAnalysisPredicateOpt) { return new ValueContentAnalysisContext( valueDomain, wellKnownTypeProvider, controlFlowGraph, owningSymbol, analyzerOptions, @@ -62,10 +62,10 @@ public sealed class ValueContentAnalysisContext : AbstractDataFlowAnalysisContex IMethodSymbol invokedMethod, ControlFlowGraph invokedControlFlowGraph, IOperation operation, - PointsToAnalysisResult pointsToAnalysisResultOpt, - CopyAnalysisResult copyAnalysisResultOpt, - ValueContentAnalysisResult valueContentAnalysisResultOpt, - InterproceduralValueContentAnalysisData interproceduralAnalysisData) + PointsToAnalysisResult? pointsToAnalysisResultOpt, + CopyAnalysisResult? copyAnalysisResultOpt, + ValueContentAnalysisResult? valueContentAnalysisResultOpt, + InterproceduralValueContentAnalysisData? interproceduralAnalysisData) { Debug.Assert(valueContentAnalysisResultOpt == null); diff --git a/src/Utilities/FlowAnalysis/FlowAnalysis/Framework/DataFlow/AbstractDataFlowAnalysisContext.cs b/src/Utilities/FlowAnalysis/FlowAnalysis/Framework/DataFlow/AbstractDataFlowAnalysisContext.cs index d5ecf81969..8da028f41f 100644 --- a/src/Utilities/FlowAnalysis/FlowAnalysis/Framework/DataFlow/AbstractDataFlowAnalysisContext.cs +++ b/src/Utilities/FlowAnalysis/FlowAnalysis/Framework/DataFlow/AbstractDataFlowAnalysisContext.cs @@ -20,7 +20,7 @@ namespace Microsoft.CodeAnalysis.FlowAnalysis.DataFlow public abstract class AbstractDataFlowAnalysisContext : CacheBasedEquatable, IDataFlowAnalysisContext where TAnalysisContext : class, IDataFlowAnalysisContext - where TAnalysisResult : IDataFlowAnalysisResult + where TAnalysisResult : class, IDataFlowAnalysisResult { protected AbstractDataFlowAnalysisContext( AbstractValueDomain valueDomain, @@ -32,24 +32,19 @@ public abstract class AbstractDataFlowAnalysisContext tryGetOrComputeAnalysisResult, - ControlFlowGraph parentControlFlowGraphOpt, - InterproceduralAnalysisData interproceduralAnalysisDataOpt, - InterproceduralAnalysisPredicate interproceduralAnalysisPredicateOpt) + CopyAnalysisResult? copyAnalysisResultOpt, + PointsToAnalysisResult? pointsToAnalysisResultOpt, + ValueContentAnalysisResult? valueContentAnalysisResultOpt, + Func tryGetOrComputeAnalysisResult, + ControlFlowGraph? parentControlFlowGraphOpt, + InterproceduralAnalysisData? interproceduralAnalysisDataOpt, + InterproceduralAnalysisPredicate? interproceduralAnalysisPredicateOpt) { - Debug.Assert(valueDomain != null, "valueDomain must not be null for use in ComputeHashCodeParts"); - Debug.Assert(controlFlowGraph != null); - Debug.Assert(owningSymbol != null); Debug.Assert(owningSymbol.Kind == SymbolKind.Method || owningSymbol.Kind == SymbolKind.Field || owningSymbol.Kind == SymbolKind.Property || owningSymbol.Kind == SymbolKind.Event); Debug.Assert(Equals(owningSymbol.OriginalDefinition, owningSymbol)); - Debug.Assert(wellKnownTypeProvider != null); - Debug.Assert(tryGetOrComputeAnalysisResult != null); Debug.Assert(pointsToAnalysisResultOpt == null || pointsToAnalysisResultOpt.ControlFlowGraph == controlFlowGraph); Debug.Assert(copyAnalysisResultOpt == null || @@ -84,27 +79,27 @@ public abstract class AbstractDataFlowAnalysisContext TryGetOrComputeAnalysisResult { get; } - protected ControlFlowGraph ParentControlFlowGraphOpt { get; } + public Func TryGetOrComputeAnalysisResult { get; } + protected ControlFlowGraph? ParentControlFlowGraphOpt { get; } // Optional data for context sensitive analysis. - public InterproceduralAnalysisData InterproceduralAnalysisDataOpt { get; } - public InterproceduralAnalysisPredicate InterproceduralAnalysisPredicateOpt { get; } + public InterproceduralAnalysisData? InterproceduralAnalysisDataOpt { get; } + public InterproceduralAnalysisPredicate? InterproceduralAnalysisPredicateOpt { get; } public abstract TAnalysisContext ForkForInterproceduralAnalysis( IMethodSymbol invokedMethod, ControlFlowGraph invokedCfg, IOperation operation, - PointsToAnalysisResult pointsToAnalysisResultOpt, - CopyAnalysisResult copyAnalysisResultOpt, - ValueContentAnalysisResult valueContentAnalysisResultOpt, - InterproceduralAnalysisData interproceduralAnalysisData); + PointsToAnalysisResult? pointsToAnalysisResultOpt, + CopyAnalysisResult? copyAnalysisResultOpt, + ValueContentAnalysisResult? valueContentAnalysisResultOpt, + InterproceduralAnalysisData? interproceduralAnalysisData); - public ControlFlowGraph GetLocalFunctionControlFlowGraph(IMethodSymbol localFunction) + public ControlFlowGraph? GetLocalFunctionControlFlowGraph(IMethodSymbol localFunction) { if (localFunction.Equals(OwningSymbol)) { @@ -130,7 +125,7 @@ public ControlFlowGraph GetLocalFunctionControlFlowGraph(IMethodSymbol localFunc return null; } - public ControlFlowGraph GetAnonymousFunctionControlFlowGraph(IFlowAnonymousFunctionOperation lambda) + public ControlFlowGraph? GetAnonymousFunctionControlFlowGraph(IFlowAnonymousFunctionOperation lambda) { // TODO: https://github.com/dotnet/roslyn-analyzers/issues/1812 // Remove the below workaround. diff --git a/src/Utilities/FlowAnalysis/FlowAnalysis/Framework/DataFlow/AbstractIndex.OperationBasedIndex.cs b/src/Utilities/FlowAnalysis/FlowAnalysis/Framework/DataFlow/AbstractIndex.OperationBasedIndex.cs index e4d295a453..75ce53d12c 100644 --- a/src/Utilities/FlowAnalysis/FlowAnalysis/Framework/DataFlow/AbstractIndex.OperationBasedIndex.cs +++ b/src/Utilities/FlowAnalysis/FlowAnalysis/Framework/DataFlow/AbstractIndex.OperationBasedIndex.cs @@ -11,7 +11,6 @@ private sealed class OperationBasedIndex : AbstractIndex { public OperationBasedIndex(IOperation operation) { - Debug.Assert(operation != null); Operation = operation; } diff --git a/src/Utilities/FlowAnalysis/FlowAnalysis/Framework/DataFlow/AbstractLocation.cs b/src/Utilities/FlowAnalysis/FlowAnalysis/Framework/DataFlow/AbstractLocation.cs index a320024512..bc5b60acc6 100644 --- a/src/Utilities/FlowAnalysis/FlowAnalysis/Framework/DataFlow/AbstractLocation.cs +++ b/src/Utilities/FlowAnalysis/FlowAnalysis/Framework/DataFlow/AbstractLocation.cs @@ -31,7 +31,7 @@ public sealed class AbstractLocation : CacheBasedEquatable public static readonly AbstractLocation Null = new AbstractLocation(creationOpt: null, creationCallStackOpt: null, analysisEntityOpt: null, symbolOpt: null, captureIdOpt: null, locationTypeOpt: null, isSpecialSingleton: true); public static readonly AbstractLocation NoLocation = new AbstractLocation(creationOpt: null, creationCallStackOpt: null, analysisEntityOpt: null, symbolOpt: null, captureIdOpt: null, locationTypeOpt: null, isSpecialSingleton: true); - private AbstractLocation(IOperation creationOpt, ImmutableStack creationCallStackOpt, AnalysisEntity analysisEntityOpt, ISymbol symbolOpt, InterproceduralCaptureId? captureIdOpt, ITypeSymbol locationTypeOpt, bool isSpecialSingleton) + private AbstractLocation(IOperation? creationOpt, ImmutableStack? creationCallStackOpt, AnalysisEntity? analysisEntityOpt, ISymbol? symbolOpt, InterproceduralCaptureId? captureIdOpt, ITypeSymbol? locationTypeOpt, bool isSpecialSingleton) { Debug.Assert(isSpecialSingleton ^ (locationTypeOpt != null)); @@ -44,7 +44,7 @@ private AbstractLocation(IOperation creationOpt, ImmutableStack crea _isSpecialSingleton = isSpecialSingleton; } - private static AbstractLocation Create(IOperation creationOpt, ImmutableStack creationCallStackOpt, AnalysisEntity analysisEntityOpt, ISymbol symbolOpt, InterproceduralCaptureId? captureIdOpt, ITypeSymbol locationType) + private static AbstractLocation Create(IOperation? creationOpt, ImmutableStack? creationCallStackOpt, AnalysisEntity? analysisEntityOpt, ISymbol? symbolOpt, InterproceduralCaptureId? captureIdOpt, ITypeSymbol? locationType) { Debug.Assert(creationOpt != null ^ symbolOpt != null ^ analysisEntityOpt != null ^ captureIdOpt != null); Debug.Assert(locationType != null); @@ -54,25 +54,25 @@ private static AbstractLocation Create(IOperation creationOpt, ImmutableStack CreateAllocationLocation(creation, locationType, analysisContext.InterproceduralAnalysisDataOpt?.CallStack); - internal static AbstractLocation CreateAllocationLocation(IOperation creation, ITypeSymbol locationType, ImmutableStack callStackOpt) + internal static AbstractLocation CreateAllocationLocation(IOperation creation, ITypeSymbol locationType, ImmutableStack? callStackOpt) => Create(creation, callStackOpt, analysisEntityOpt: null, symbolOpt: null, captureIdOpt: null, locationType: locationType); public static AbstractLocation CreateAnalysisEntityDefaultLocation(AnalysisEntity analysisEntity) => Create(creationOpt: null, creationCallStackOpt: null, analysisEntityOpt: analysisEntity, symbolOpt: null, captureIdOpt: null, locationType: analysisEntity.Type); - public static AbstractLocation CreateThisOrMeLocation(INamedTypeSymbol namedTypeSymbol, ImmutableStack creationCallStackOpt) + public static AbstractLocation CreateThisOrMeLocation(INamedTypeSymbol namedTypeSymbol, ImmutableStack? creationCallStackOpt) => Create(creationOpt: null, creationCallStackOpt: creationCallStackOpt, analysisEntityOpt: null, symbolOpt: namedTypeSymbol, captureIdOpt: null, locationType: namedTypeSymbol); - public static AbstractLocation CreateSymbolLocation(ISymbol symbol, ImmutableStack creationCallStackOpt) + public static AbstractLocation CreateSymbolLocation(ISymbol symbol, ImmutableStack? creationCallStackOpt) => Create(creationOpt: null, creationCallStackOpt: creationCallStackOpt, analysisEntityOpt: null, symbolOpt: symbol, captureIdOpt: null, locationType: symbol.GetMemberOrLocalOrParameterType()); - public static AbstractLocation CreateFlowCaptureLocation(InterproceduralCaptureId captureId, ITypeSymbol locationType, ImmutableStack creationCallStackOpt) + public static AbstractLocation CreateFlowCaptureLocation(InterproceduralCaptureId captureId, ITypeSymbol locationType, ImmutableStack? creationCallStackOpt) => Create(creationOpt: null, creationCallStackOpt: creationCallStackOpt, analysisEntityOpt: null, symbolOpt: null, captureIdOpt: captureId, locationType: locationType); - public IOperation CreationOpt { get; } + public IOperation? CreationOpt { get; } public ImmutableStack CreationCallStack { get; } /// /// Returns the top of if this location was created through an interprocedural method invocation, i.e. is non-empty. /// Otherwise, returns . /// - public IOperation GetTopOfCreationCallStackOrCreation() + public IOperation? GetTopOfCreationCallStackOrCreation() { if (CreationCallStack.IsEmpty) { @@ -82,10 +82,10 @@ public IOperation GetTopOfCreationCallStackOrCreation() return CreationCallStack.Peek(); } - public AnalysisEntity AnalysisEntityOpt { get; } - public ISymbol SymbolOpt { get; } + public AnalysisEntity? AnalysisEntityOpt { get; } + public ISymbol? SymbolOpt { get; } public InterproceduralCaptureId? CaptureIdOpt { get; } - public ITypeSymbol LocationTypeOpt { get; } + public ITypeSymbol? LocationTypeOpt { get; } public bool IsNull => ReferenceEquals(this, Null); public bool IsNoLocation => ReferenceEquals(this, NoLocation); @@ -110,7 +110,7 @@ protected override void ComputeHashCodeParts(Action addPart) /// Attempts to get the syntax node to report diagnostic for this abstract location /// Returns null if the location is owned by another method invoked through interprocedural analysis. /// - public SyntaxNode TryGetNodeToReportDiagnostic(PointsToAnalysisResult pointsToAnalysisResultOpt) + public SyntaxNode? TryGetNodeToReportDiagnostic(PointsToAnalysisResult pointsToAnalysisResultOpt) { Debug.Assert(CreationOpt != null); @@ -134,10 +134,10 @@ public SyntaxNode TryGetNodeToReportDiagnostic(PointsToAnalysisResult pointsToAn } // Fallback to reporting the diagnostic on the allocation location. - return CreationOpt.Syntax; + return CreationOpt?.Syntax; // Local functions. - SyntaxNode TryGetSyntaxNodeToReportDiagnostic(IOperation creation) + SyntaxNode? TryGetSyntaxNodeToReportDiagnostic(IOperation creation) { // If any of the argument to creation points to this location, then use the argument. var arguments = creation switch @@ -160,12 +160,12 @@ SyntaxNode TryGetSyntaxNodeToReportDiagnostic(IOperation creation) return TryGetSyntaxNodeToReportDiagnosticCore(creation); - SyntaxNode TryGetSyntaxNodeToReportDiagnosticCore(IOperation operation) + SyntaxNode? TryGetSyntaxNodeToReportDiagnosticCore(IOperation operation) { var pointsToValue = pointsToAnalysisResultOpt[operation]; return TryGetSyntaxNodeToReportDiagnosticForPointsValue(pointsToValue, operation); - SyntaxNode TryGetSyntaxNodeToReportDiagnosticForPointsValue(PointsToAbstractValue pointsToValue, IOperation operation) + SyntaxNode? TryGetSyntaxNodeToReportDiagnosticForPointsValue(PointsToAbstractValue pointsToValue, IOperation operation) { foreach (var location in pointsToValue.Locations) { diff --git a/src/Utilities/FlowAnalysis/FlowAnalysis/Framework/DataFlow/AbstractLocationDataFlowOperationVisitor.cs b/src/Utilities/FlowAnalysis/FlowAnalysis/Framework/DataFlow/AbstractLocationDataFlowOperationVisitor.cs index 67d97d71ad..9f0f1e028c 100644 --- a/src/Utilities/FlowAnalysis/FlowAnalysis/Framework/DataFlow/AbstractLocationDataFlowOperationVisitor.cs +++ b/src/Utilities/FlowAnalysis/FlowAnalysis/Framework/DataFlow/AbstractLocationDataFlowOperationVisitor.cs @@ -15,7 +15,7 @@ public abstract class AbstractLocationDataFlowOperationVisitor where TAnalysisData : AbstractAnalysisData where TAnalysisContext : AbstractDataFlowAnalysisContext - where TAnalysisResult : IDataFlowAnalysisResult + where TAnalysisResult : class, IDataFlowAnalysisResult { protected AbstractLocationDataFlowOperationVisitor(TAnalysisContext analysisContext) : base(analysisContext) @@ -89,7 +89,7 @@ protected override TAbstractAnalysisValue ComputeAnalysisValueForEscapedRefOrOut protected abstract void SetValueForParameterPointsToLocationOnEntry(IParameterSymbol parameter, PointsToAbstractValue pointsToAbstractValue); protected abstract void EscapeValueForParameterPointsToLocationOnExit(IParameterSymbol parameter, AnalysisEntity analysisEntity, ImmutableHashSet escapedLocations); - protected override void SetValueForParameterOnEntry(IParameterSymbol parameter, AnalysisEntity analysisEntity, ArgumentInfo assignedValueOpt) + protected override void SetValueForParameterOnEntry(IParameterSymbol parameter, AnalysisEntity analysisEntity, ArgumentInfo? assignedValueOpt) { // Only set the value for non-interprocedural case. // For interprocedural case, we have already initialized values for the underlying locations @@ -115,14 +115,17 @@ protected override void EscapeValueForParameterOnExit(IParameterSymbol parameter /// /// Helper method to reset analysis data for analysis locations. /// - protected void ResetAnalysisData(DictionaryAnalysisData currentAnalysisDataOpt) + protected void ResetAnalysisData(DictionaryAnalysisData? currentAnalysisDataOpt) { // Reset the current analysis data, while ensuring that we don't violate the monotonicity, i.e. we cannot remove any existing key from currentAnalysisData. // Just set the values for existing keys to ValueDomain.UnknownOrMayBeValue. - var keys = currentAnalysisDataOpt?.Keys.ToImmutableArray(); - foreach (var key in keys) + if (currentAnalysisDataOpt != null) { - SetAbstractValue(key, ValueDomain.UnknownOrMayBeValue); + var keys = currentAnalysisDataOpt.Keys.ToImmutableArray(); + foreach (var key in keys) + { + SetAbstractValue(key, ValueDomain.UnknownOrMayBeValue); + } } } diff --git a/src/Utilities/FlowAnalysis/FlowAnalysis/Framework/DataFlow/AddressSharedEntitiesProvider.cs b/src/Utilities/FlowAnalysis/FlowAnalysis/Framework/DataFlow/AddressSharedEntitiesProvider.cs index ac5722ee3e..b71fd0a15d 100644 --- a/src/Utilities/FlowAnalysis/FlowAnalysis/Framework/DataFlow/AddressSharedEntitiesProvider.cs +++ b/src/Utilities/FlowAnalysis/FlowAnalysis/Framework/DataFlow/AddressSharedEntitiesProvider.cs @@ -12,7 +12,7 @@ namespace Microsoft.CodeAnalysis.FlowAnalysis.DataFlow.CopyAnalysis /// internal sealed class AddressSharedEntitiesProvider where TAnalysisContext : AbstractDataFlowAnalysisContext - where TAnalysisResult : IDataFlowAnalysisResult + where TAnalysisResult : class, IDataFlowAnalysisResult { /// /// Map builder from entity to set of entities that share the same instance location. @@ -27,7 +27,7 @@ public AddressSharedEntitiesProvider(TAnalysisContext analysisContext) SetAddressSharedEntities(analysisContext.InterproceduralAnalysisDataOpt?.AddressSharedEntities); } - public void SetAddressSharedEntities(ImmutableDictionary addressSharedEntitiesOpt) + public void SetAddressSharedEntities(ImmutableDictionary? addressSharedEntitiesOpt) { _addressSharedEntitiesBuilder.Clear(); if (addressSharedEntitiesOpt != null) @@ -36,7 +36,7 @@ public void SetAddressSharedEntities(ImmutableDictionary assignedValueOpt) + public void UpdateAddressSharedEntitiesForParameter(IParameterSymbol parameter, AnalysisEntity analysisEntity, ArgumentInfo? assignedValueOpt) { if (parameter.RefKind != RefKind.None && assignedValueOpt?.AnalysisEntityOpt != null) @@ -54,11 +54,11 @@ ImmutableHashSet ComputeAddressSharedEntities() { var builder = PooledHashSet.GetInstance(); AddIfHasKnownInstanceLocation(analysisEntity, builder); - AddIfHasKnownInstanceLocation(assignedValueOpt.AnalysisEntityOpt, builder); + AddIfHasKnownInstanceLocation(assignedValueOpt!.AnalysisEntityOpt!, builder); // We need to handle multiple ref/out parameters passed the same location. // For example, "M(ref a, ref a);" - if (_addressSharedEntitiesBuilder.TryGetValue(assignedValueOpt.AnalysisEntityOpt, out var existingValue)) + if (_addressSharedEntitiesBuilder.TryGetValue(assignedValueOpt.AnalysisEntityOpt!, out var existingValue)) { foreach (var entity in existingValue.AnalysisEntities) { @@ -92,7 +92,7 @@ static void AddIfHasKnownInstanceLocation(AnalysisEntity entity, PooledHashSet TryGetAddressSharedCopyValue(analysisEntity) ?? new CopyAbstractValue(analysisEntity); - public CopyAbstractValue TryGetAddressSharedCopyValue(AnalysisEntity analysisEntity) + public CopyAbstractValue? TryGetAddressSharedCopyValue(AnalysisEntity analysisEntity) => _addressSharedEntitiesBuilder.TryGetValue(analysisEntity, out var addressSharedEntities) ? addressSharedEntities : null; diff --git a/src/Utilities/FlowAnalysis/FlowAnalysis/Framework/DataFlow/AnalysisEntity.cs b/src/Utilities/FlowAnalysis/FlowAnalysis/Framework/DataFlow/AnalysisEntity.cs index ef64788607..f8a9d352af 100644 --- a/src/Utilities/FlowAnalysis/FlowAnalysis/Framework/DataFlow/AnalysisEntity.cs +++ b/src/Utilities/FlowAnalysis/FlowAnalysis/Framework/DataFlow/AnalysisEntity.cs @@ -36,19 +36,17 @@ public sealed class AnalysisEntity : CacheBasedEquatable private readonly int _ignoringLocationHashCode; private AnalysisEntity( - ISymbol symbolOpt, + ISymbol? symbolOpt, ImmutableArray indices, - SyntaxNode instanceReferenceOperationSyntaxOpt, + SyntaxNode? instanceReferenceOperationSyntaxOpt, InterproceduralCaptureId? captureIdOpt, PointsToAbstractValue location, ITypeSymbol type, - AnalysisEntity parentOpt, + AnalysisEntity? parentOpt, bool isThisOrMeInstance) { Debug.Assert(!indices.IsDefault); Debug.Assert(symbolOpt != null || !indices.IsEmpty || instanceReferenceOperationSyntaxOpt != null || captureIdOpt.HasValue); - Debug.Assert(location != null); - Debug.Assert(type != null); Debug.Assert(parentOpt == null || parentOpt.Type.HasValueCopySemantics() || !indices.IsEmpty); SymbolOpt = symbolOpt; @@ -64,7 +62,7 @@ public sealed class AnalysisEntity : CacheBasedEquatable _ignoringLocationHashCode = HashUtilities.Combine(_ignoringLocationHashCodeParts); } - private AnalysisEntity(ISymbol symbolOpt, ImmutableArray indices, PointsToAbstractValue location, ITypeSymbol type, AnalysisEntity parentOpt) + private AnalysisEntity(ISymbol? symbolOpt, ImmutableArray indices, PointsToAbstractValue location, ITypeSymbol type, AnalysisEntity? parentOpt) : this(symbolOpt, indices, instanceReferenceOperationSyntaxOpt: null, captureIdOpt: null, location: location, type: type, parentOpt: parentOpt, isThisOrMeInstance: false) { Debug.Assert(symbolOpt != null || !indices.IsEmpty); @@ -89,12 +87,10 @@ private AnalysisEntity(INamedTypeSymbol namedType, PointsToAbstractValue locatio { } - public static AnalysisEntity Create(ISymbol symbolOpt, ImmutableArray indices, - ITypeSymbol type, PointsToAbstractValue instanceLocation, AnalysisEntity parentOpt) + public static AnalysisEntity Create(ISymbol? symbolOpt, ImmutableArray indices, + ITypeSymbol type, PointsToAbstractValue instanceLocation, AnalysisEntity? parentOpt) { Debug.Assert(symbolOpt != null || !indices.IsEmpty); - Debug.Assert(instanceLocation != null); - Debug.Assert(type != null); Debug.Assert(parentOpt == null || parentOpt.InstanceLocation == instanceLocation); return new AnalysisEntity(symbolOpt, indices, instanceLocation, type, parentOpt); @@ -102,9 +98,6 @@ private AnalysisEntity(INamedTypeSymbol namedType, PointsToAbstractValue locatio public static AnalysisEntity Create(IInstanceReferenceOperation instanceReferenceOperation, PointsToAbstractValue instanceLocation) { - Debug.Assert(instanceReferenceOperation != null); - Debug.Assert(instanceLocation != null); - return new AnalysisEntity(instanceReferenceOperation, instanceLocation); } @@ -118,8 +111,6 @@ public static AnalysisEntity Create(IInstanceReferenceOperation instanceReferenc public static AnalysisEntity CreateThisOrMeInstance(INamedTypeSymbol typeSymbol, PointsToAbstractValue instanceLocation) { - Debug.Assert(typeSymbol != null); - Debug.Assert(instanceLocation != null); Debug.Assert(instanceLocation.Locations.Count == 1); Debug.Assert(instanceLocation.Locations.Single().CreationOpt == null); Debug.Assert(Equals(instanceLocation.Locations.Single().SymbolOpt, typeSymbol)); @@ -129,7 +120,6 @@ public static AnalysisEntity CreateThisOrMeInstance(INamedTypeSymbol typeSymbol, public AnalysisEntity WithMergedInstanceLocation(AnalysisEntity analysisEntityToMerge) { - Debug.Assert(analysisEntityToMerge != null); Debug.Assert(EqualsIgnoringInstanceLocation(analysisEntityToMerge)); Debug.Assert(!InstanceLocation.Equals(analysisEntityToMerge.InstanceLocation)); @@ -182,13 +172,13 @@ public bool HasConstantValue } } - public ISymbol SymbolOpt { get; } + public ISymbol? SymbolOpt { get; } public ImmutableArray Indices { get; } - public SyntaxNode InstanceReferenceOperationSyntaxOpt { get; } + public SyntaxNode? InstanceReferenceOperationSyntaxOpt { get; } public InterproceduralCaptureId? CaptureIdOpt { get; } public PointsToAbstractValue InstanceLocation { get; } public ITypeSymbol Type { get; } - public AnalysisEntity ParentOpt { get; } + public AnalysisEntity? ParentOpt { get; } public bool IsThisOrMeInstance { get; } public bool HasUnknownInstanceLocation @@ -210,7 +200,7 @@ public bool HasUnknownInstanceLocation public bool IsLValueFlowCaptureEntity => CaptureIdOpt.HasValue && CaptureIdOpt.Value.IsLValueFlowCapture; - public bool EqualsIgnoringInstanceLocation(AnalysisEntity other) + public bool EqualsIgnoringInstanceLocation(AnalysisEntity? other) { // Perform fast equality checks first. if (ReferenceEquals(this, other)) @@ -256,9 +246,7 @@ private ImmutableArray ComputeIgnoringLocationHashCodeParts() public bool HasAncestor(AnalysisEntity ancestor) { - Debug.Assert(ancestor != null); - - AnalysisEntity current = this.ParentOpt; + AnalysisEntity? current = this.ParentOpt; while (current != null) { if (current == ancestor) diff --git a/src/Utilities/FlowAnalysis/FlowAnalysis/Framework/DataFlow/AnalysisEntityBasedPredicateAnalysisData.cs b/src/Utilities/FlowAnalysis/FlowAnalysis/Framework/DataFlow/AnalysisEntityBasedPredicateAnalysisData.cs index 522c049c13..3eb1741963 100644 --- a/src/Utilities/FlowAnalysis/FlowAnalysis/Framework/DataFlow/AnalysisEntityBasedPredicateAnalysisData.cs +++ b/src/Utilities/FlowAnalysis/FlowAnalysis/Framework/DataFlow/AnalysisEntityBasedPredicateAnalysisData.cs @@ -139,7 +139,7 @@ public virtual void Reset(Func getResetValue) AssertValidAnalysisData(); } - public void StartTrackingPredicatedData(AnalysisEntity predicatedEntity, AnalysisEntityBasedPredicateAnalysisData truePredicateData, AnalysisEntityBasedPredicateAnalysisData falsePredicateData) + public void StartTrackingPredicatedData(AnalysisEntity predicatedEntity, AnalysisEntityBasedPredicateAnalysisData? truePredicateData, AnalysisEntityBasedPredicateAnalysisData? falsePredicateData) { AssertValidAnalysisData(); diff --git a/src/Utilities/FlowAnalysis/FlowAnalysis/Framework/DataFlow/AnalysisEntityDataFlowOperationVisitor.cs b/src/Utilities/FlowAnalysis/FlowAnalysis/Framework/DataFlow/AnalysisEntityDataFlowOperationVisitor.cs index 86dc3ff5e8..37392537f5 100644 --- a/src/Utilities/FlowAnalysis/FlowAnalysis/Framework/DataFlow/AnalysisEntityDataFlowOperationVisitor.cs +++ b/src/Utilities/FlowAnalysis/FlowAnalysis/Framework/DataFlow/AnalysisEntityDataFlowOperationVisitor.cs @@ -5,7 +5,6 @@ using System.Collections.Immutable; using System.Diagnostics; using System.Linq; -using Analyzer.Utilities; using Analyzer.Utilities.Extensions; using Analyzer.Utilities.PooledObjects; using Analyzer.Utilities.PooledObjects.Extensions; @@ -23,7 +22,7 @@ public abstract class AnalysisEntityDataFlowOperationVisitor where TAnalysisData : AbstractAnalysisData where TAnalysisContext : AbstractDataFlowAnalysisContext - where TAnalysisResult : IDataFlowAnalysisResult + where TAnalysisResult : class, IDataFlowAnalysisResult where TAbstractAnalysisValue : IEquatable { protected AnalysisEntityDataFlowOperationVisitor(TAnalysisContext analysisContext) @@ -42,7 +41,7 @@ protected void AddTrackedEntities(HashSet builder, bool forInter protected override TAbstractAnalysisValue ComputeAnalysisValueForReferenceOperation(IOperation operation, TAbstractAnalysisValue defaultValue) { - if (AnalysisEntityFactory.TryCreate(operation, out AnalysisEntity analysisEntity)) + if (AnalysisEntityFactory.TryCreate(operation, out var analysisEntity)) { if (!HasAbstractValue(analysisEntity)) { @@ -61,7 +60,7 @@ protected sealed override TAbstractAnalysisValue ComputeAnalysisValueForEscapedR { Debug.Assert(operation.Parameter.RefKind == RefKind.Ref || operation.Parameter.RefKind == RefKind.Out); - if (AnalysisEntityFactory.TryCreate(operation, out AnalysisEntity analysisEntity)) + if (AnalysisEntityFactory.TryCreate(operation, out var analysisEntity)) { var value = ComputeAnalysisValueForEscapedRefOrOutArgument(analysisEntity, operation, defaultValue); SetAbstractValueForAssignment(analysisEntity, operation, value); @@ -87,10 +86,13 @@ protected void ResetAnalysisData(DictionaryAnalysisData.GetInstance(); try @@ -223,15 +229,15 @@ protected override TAnalysisData GetMergedAnalysisDataForPossibleThrowingOperati #region Helper methods to handle initialization/assignment operations protected override void SetAbstractValueForArrayElementInitializer(IArrayCreationOperation arrayCreation, ImmutableArray indices, ITypeSymbol elementType, IOperation initializer, TAbstractAnalysisValue value) { - if (AnalysisEntityFactory.TryCreateForArrayElementInitializer(arrayCreation, indices, elementType, out AnalysisEntity analysisEntity)) + if (AnalysisEntityFactory.TryCreateForArrayElementInitializer(arrayCreation, indices, elementType, out var analysisEntity)) { SetAbstractValueForAssignment(analysisEntity, initializer, value); } } - protected override void SetAbstractValueForAssignment(IOperation target, IOperation assignedValueOperation, TAbstractAnalysisValue assignedValue, bool mayBeAssignment = false) + protected override void SetAbstractValueForAssignment(IOperation target, IOperation? assignedValueOperation, TAbstractAnalysisValue assignedValue, bool mayBeAssignment = false) { - if (AnalysisEntityFactory.TryCreate(target, out AnalysisEntity targetAnalysisEntity)) + if (AnalysisEntityFactory.TryCreate(target, out var targetAnalysisEntity)) { if (mayBeAssignment) { @@ -256,9 +262,9 @@ protected override void SetAbstractValueForTupleElementAssignment(AnalysisEntity } } - protected virtual void SetAbstractValueForAssignment(AnalysisEntity targetAnalysisEntity, IOperation assignedValueOperationOpt, TAbstractAnalysisValue assignedValue) + protected virtual void SetAbstractValueForAssignment(AnalysisEntity targetAnalysisEntity, IOperation? assignedValueOperationOpt, TAbstractAnalysisValue assignedValue) { - AnalysisEntity assignedValueEntityOpt = null; + AnalysisEntity? assignedValueEntityOpt = null; if (assignedValueOperationOpt != null) { var success = AnalysisEntityFactory.TryCreate(assignedValueOperationOpt, out assignedValueEntityOpt); @@ -268,7 +274,7 @@ protected virtual void SetAbstractValueForAssignment(AnalysisEntity targetAnalys SetAbstractValueForAssignment(targetAnalysisEntity, assignedValueEntityOpt, assignedValueOperationOpt, assignedValue); } - private void SetAbstractValueForAssignment(AnalysisEntity targetAnalysisEntity, AnalysisEntity assignedValueEntityOpt, IOperation assignedValueOperationOpt, TAbstractAnalysisValue assignedValue) + private void SetAbstractValueForAssignment(AnalysisEntity targetAnalysisEntity, AnalysisEntity? assignedValueEntityOpt, IOperation? assignedValueOperationOpt, TAbstractAnalysisValue assignedValue) { // Value type and string type assignment has copy semantics. if (HasPointsToAnalysisResult && @@ -296,7 +302,7 @@ private void SetAbstractValueForAssignment(AnalysisEntity targetAnalysisEntity, } } - protected override void SetValueForParameterOnEntry(IParameterSymbol parameter, AnalysisEntity analysisEntity, ArgumentInfo assignedValueOpt) + protected override void SetValueForParameterOnEntry(IParameterSymbol parameter, AnalysisEntity analysisEntity, ArgumentInfo? assignedValueOpt) { Debug.Assert(Equals(analysisEntity.SymbolOpt, parameter)); if (assignedValueOpt != null) @@ -364,7 +370,7 @@ private void ResetInstanceAnalysisDataCore(IEnumerable dependant /// This involves transfer of data for of all instances that share the same as or allocation for the /// to all instances that share the same as . /// - private void TransferValueTypeInstanceAnalysisDataForAssignment(AnalysisEntity targetAnalysisEntity, AnalysisEntity valueAnalysisEntityOpt, IOperation assignedValueOperationOpt) + private void TransferValueTypeInstanceAnalysisDataForAssignment(AnalysisEntity targetAnalysisEntity, AnalysisEntity? valueAnalysisEntityOpt, IOperation? assignedValueOperationOpt) { Debug.Assert(HasPointsToAnalysisResult); Debug.Assert(targetAnalysisEntity.Type.HasValueCopySemantics()); @@ -423,10 +429,10 @@ protected static bool IsChildAnalysisEntity(AnalysisEntity entity, AnalysisEntit IsChildAnalysisEntity(entity, ancestorEntity.InstanceLocation); } - protected ImmutableHashSet GetChildAnalysisEntities(PointsToAbstractValue instanceLocationOpt) + protected ImmutableHashSet GetChildAnalysisEntities(PointsToAbstractValue? instanceLocationOpt) => GetChildAnalysisEntities(instanceLocationOpt, predicateOpt: null); - private ImmutableHashSet GetChildAnalysisEntities(PointsToAbstractValue instanceLocationOpt, Func predicateOpt) + private ImmutableHashSet GetChildAnalysisEntities(PointsToAbstractValue? instanceLocationOpt, Func? predicateOpt) { // We are interested only in dependent child/member infos, not the root info. if (instanceLocationOpt == null || instanceLocationOpt.Kind == PointsToAbstractValueKind.Unknown) @@ -473,7 +479,7 @@ protected override void UpdateReachability(BasicBlock basicBlock, TAnalysisData protected override bool IsReachableBlockData(TAnalysisData analysisData) => (analysisData as AnalysisEntityBasedPredicateAnalysisData)?.IsReachableBlockData ?? true; - protected sealed override void StartTrackingPredicatedData(AnalysisEntity predicatedEntity, TAnalysisData truePredicateData, TAnalysisData falsePredicateData) + protected sealed override void StartTrackingPredicatedData(AnalysisEntity predicatedEntity, TAnalysisData? truePredicateData, TAnalysisData? falsePredicateData) => (CurrentAnalysisData as AnalysisEntityBasedPredicateAnalysisData)?.StartTrackingPredicatedData( predicatedEntity, truePredicateData as AnalysisEntityBasedPredicateAnalysisData, @@ -489,9 +495,10 @@ protected sealed override PredicateValueKind ApplyPredicatedDataForEntity(TAnaly protected override void SetPredicateValueKind(IOperation operation, TAnalysisData analysisData, PredicateValueKind predicateValueKind) { base.SetPredicateValueKind(operation, analysisData, predicateValueKind); - if (predicateValueKind == PredicateValueKind.AlwaysFalse) + if (predicateValueKind == PredicateValueKind.AlwaysFalse && + analysisData is AnalysisEntityBasedPredicateAnalysisData analysisEntityBasedData) { - (analysisData as AnalysisEntityBasedPredicateAnalysisData).IsReachableBlockData = false; + analysisEntityBasedData.IsReachableBlockData = false; } } #endregion @@ -499,12 +506,12 @@ protected override void SetPredicateValueKind(IOperation operation, TAnalysisDat #region Interprocedural analysis protected override TAnalysisData GetInitialInterproceduralAnalysisData( IMethodSymbol invokedMethod, - (AnalysisEntity InstanceOpt, PointsToAbstractValue PointsToValue)? invocationInstanceOpt, + (AnalysisEntity? InstanceOpt, PointsToAbstractValue PointsToValue)? invocationInstanceOpt, (AnalysisEntity Instance, PointsToAbstractValue PointsToValue)? thisOrMeInstanceForCallerOpt, ImmutableDictionary> argumentValuesMap, - IDictionary pointsToValuesOpt, - IDictionary copyValuesOpt, - IDictionary valueContentValuesOpt, + IDictionary? pointsToValuesOpt, + IDictionary? copyValuesOpt, + IDictionary? valueContentValuesOpt, bool isLambdaOrLocalFunction, bool hasParameterWithDelegateType) { @@ -638,13 +645,13 @@ protected override void SetPredicateValueKind(IOperation operation, TAnalysisDat } // Local functions. - bool AddWorklistEntityAndPointsToValue(AnalysisEntity analysisEntityOpt) + bool AddWorklistEntityAndPointsToValue(AnalysisEntity? analysisEntityOpt) { if (analysisEntityOpt != null && candidateEntitiesBuilder.Contains(analysisEntityOpt)) { worklistEntities.Add(analysisEntityOpt); - if (pointsToValuesOpt.TryGetValue(analysisEntityOpt, out var pointsToValue)) + if (pointsToValuesOpt!.TryGetValue(analysisEntityOpt, out var pointsToValue)) { AddWorklistPointsToValue(pointsToValue); } @@ -731,7 +738,7 @@ internal bool ShouldStopTrackingEntityAtExit(AnalysisEntity entity) entity.CaptureIdOpt.Value.ControlFlowGraph == DataFlowAnalysisContext.ControlFlowGraph; } - public override TAnalysisData GetMergedDataForUnhandledThrowOperations() + public override TAnalysisData? GetMergedDataForUnhandledThrowOperations() { // For interprocedural analysis, prune analysis data for unhandled exceptions // to remove analysis entities that are only valid in the callee. @@ -778,7 +785,7 @@ public override TAnalysisData GetMergedDataForUnhandledThrowOperations() DictionaryAnalysisData coreCurrentAnalysisData, ThrownExceptionInfo throwBranchWithExceptionType) { - Func predicateOpt = null; + Func? predicateOpt = null; if (throwBranchWithExceptionType.IsDefaultExceptionForExceptionsPathAnalysis) { // Only tracking non-child analysis entities for exceptions path analysis for now. @@ -821,7 +828,7 @@ private void HandleDeconstructionAssignment(IOperation target, ImmutableHashSet< } else if (AnalysisEntityFactory.TryCreate(element, out var elementEntity)) { - var assignedValueEntityOpt = childEntities.FirstOrDefault(c => IsMatchingAssignedEntity(tupleElementEntity, c)); + AnalysisEntity? assignedValueEntityOpt = childEntities.FirstOrDefault(c => IsMatchingAssignedEntity(tupleElementEntity, c)); var assignedValue = assignedValueEntityOpt != null ? GetAbstractValue(assignedValueEntityOpt) : ValueDomain.UnknownOrMayBeValue; SetAbstractValueForAssignment(elementEntity, assignedValueEntityOpt, assignedValueOperationOpt: null, assignedValue); } @@ -831,9 +838,8 @@ private void HandleDeconstructionAssignment(IOperation target, ImmutableHashSet< return; // Local function - static bool IsMatchingAssignedEntity(AnalysisEntity tupleElementEntity, AnalysisEntity childEntity) + static bool IsMatchingAssignedEntity(AnalysisEntity tupleElementEntity, AnalysisEntity? childEntity) { - Debug.Assert(tupleElementEntity != null); if (childEntity == null) { return false; diff --git a/src/Utilities/FlowAnalysis/FlowAnalysis/Framework/DataFlow/AnalysisEntityFactory.cs b/src/Utilities/FlowAnalysis/FlowAnalysis/Framework/DataFlow/AnalysisEntityFactory.cs index b26fd4630c..9ced1a4ca1 100644 --- a/src/Utilities/FlowAnalysis/FlowAnalysis/Framework/DataFlow/AnalysisEntityFactory.cs +++ b/src/Utilities/FlowAnalysis/FlowAnalysis/Framework/DataFlow/AnalysisEntityFactory.cs @@ -4,6 +4,7 @@ using System.Collections.Generic; using System.Collections.Immutable; using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; using System.Linq; using Analyzer.Utilities; using Analyzer.Utilities.Extensions; @@ -22,31 +23,31 @@ public sealed class AnalysisEntityFactory { private readonly ControlFlowGraph _controlFlowGraph; private readonly WellKnownTypeProvider _wellKnownTypeProvider; - private readonly Dictionary _analysisEntityMap; + private readonly Dictionary _analysisEntityMap; private readonly Dictionary> _tupleElementEntitiesMap; private readonly Dictionary _captureIdEntityMap; private readonly Dictionary _instanceLocationsForSymbols; - private readonly Func _getPointsToAbstractValueOpt; + private readonly Func? _getPointsToAbstractValueOpt; private readonly Func _getIsInsideAnonymousObjectInitializer; private readonly Func _getIsLValueFlowCapture; - private readonly AnalysisEntity _interproceduralThisOrMeInstanceForCallerOpt; - private readonly ImmutableStack _interproceduralCallStackOpt; - private readonly Func _interproceduralGetAnalysisEntityForFlowCaptureOpt; - private readonly Func> _getInterproceduralCallStackForOwningSymbol; + private readonly AnalysisEntity? _interproceduralThisOrMeInstanceForCallerOpt; + private readonly ImmutableStack? _interproceduralCallStackOpt; + private readonly Func? _interproceduralGetAnalysisEntityForFlowCaptureOpt; + private readonly Func?> _getInterproceduralCallStackForOwningSymbol; internal AnalysisEntityFactory( ControlFlowGraph controlFlowGraph, WellKnownTypeProvider wellKnownTypeProvider, - Func getPointsToAbstractValueOpt, + Func? getPointsToAbstractValueOpt, Func getIsInsideAnonymousObjectInitializer, Func getIsLValueFlowCapture, INamedTypeSymbol containingTypeSymbol, - AnalysisEntity interproceduralInvocationInstanceOpt, - AnalysisEntity interproceduralThisOrMeInstanceForCallerOpt, - ImmutableStack interproceduralCallStackOpt, - ImmutableDictionary interproceduralCapturedVariablesMapOpt, - Func interproceduralGetAnalysisEntityForFlowCaptureOpt, - Func> getInterproceduralCallStackForOwningSymbol) + AnalysisEntity? interproceduralInvocationInstanceOpt, + AnalysisEntity? interproceduralThisOrMeInstanceForCallerOpt, + ImmutableStack? interproceduralCallStackOpt, + ImmutableDictionary? interproceduralCapturedVariablesMapOpt, + Func? interproceduralGetAnalysisEntityForFlowCaptureOpt, + Func?> getInterproceduralCallStackForOwningSymbol) { _controlFlowGraph = controlFlowGraph; _wellKnownTypeProvider = wellKnownTypeProvider; @@ -58,7 +59,7 @@ public sealed class AnalysisEntityFactory _interproceduralGetAnalysisEntityForFlowCaptureOpt = interproceduralGetAnalysisEntityForFlowCaptureOpt; _getInterproceduralCallStackForOwningSymbol = getInterproceduralCallStackForOwningSymbol; - _analysisEntityMap = new Dictionary(); + _analysisEntityMap = new Dictionary(); _tupleElementEntitiesMap = new Dictionary>(); _captureIdEntityMap = new Dictionary(); @@ -115,7 +116,7 @@ private static AbstractIndex CreateAbstractIndex(IOperation operation) return AbstractIndex.Create(operation); } - public bool TryCreate(IOperation operation, out AnalysisEntity analysisEntity) + public bool TryCreate(IOperation operation, [NotNullWhen(returnValue: true)] out AnalysisEntity? analysisEntity) { if (_analysisEntityMap.TryGetValue(operation, out analysisEntity)) { @@ -123,10 +124,10 @@ public bool TryCreate(IOperation operation, out AnalysisEntity analysisEntity) } analysisEntity = null; - ISymbol symbolOpt = null; + ISymbol? symbolOpt = null; ImmutableArray indices = ImmutableArray.Empty; - IOperation instanceOpt = null; - ITypeSymbol type = operation.Type; + IOperation? instanceOpt = null; + ITypeSymbol? type = operation.Type; switch (operation) { case ILocalReferenceOperation localReference: @@ -162,8 +163,8 @@ public bool TryCreate(IOperation operation, out AnalysisEntity analysisEntity) break; case IConditionalAccessInstanceOperation conditionalAccessInstance: - IConditionalAccessOperation conditionalAccess = conditionalAccessInstance.GetConditionalAccess(); - instanceOpt = conditionalAccess.Operation; + IConditionalAccessOperation? conditionalAccess = conditionalAccessInstance.GetConditionalAccess(); + instanceOpt = conditionalAccess?.Operation; if (conditionalAccessInstance.Parent is IMemberReferenceOperation memberReferenceParent) { GetSymbolAndIndicesForMemberReference(memberReferenceParent, ref symbolOpt, ref indices); @@ -235,14 +236,14 @@ public bool TryCreate(IOperation operation, out AnalysisEntity analysisEntity) if (symbolOpt != null || !indices.IsEmpty) { - TryCreate(symbolOpt, indices, type, instanceOpt, out analysisEntity); + TryCreate(symbolOpt, indices, type!, instanceOpt, out analysisEntity); } _analysisEntityMap[operation] = analysisEntity; return analysisEntity != null; } - private void GetSymbolAndIndicesForMemberReference(IMemberReferenceOperation memberReference, ref ISymbol symbolOpt, ref ImmutableArray indices) + private void GetSymbolAndIndicesForMemberReference(IMemberReferenceOperation memberReference, ref ISymbol? symbolOpt, ref ImmutableArray indices) { switch (memberReference) { @@ -280,20 +281,19 @@ private void GetSymbolAndIndicesForMemberReference(IMemberReferenceOperation mem } } - public bool TryCreateForSymbolDeclaration(ISymbol symbol, out AnalysisEntity analysisEntity) + public bool TryCreateForSymbolDeclaration(ISymbol symbol, [NotNullWhen(returnValue: true)] out AnalysisEntity? analysisEntity) { - Debug.Assert(symbol != null); Debug.Assert(symbol.Kind == SymbolKind.Local || symbol.Kind == SymbolKind.Parameter || symbol.Kind == SymbolKind.Field || symbol.Kind == SymbolKind.Property); var indices = ImmutableArray.Empty; - IOperation instance = null; + IOperation? instance = null; var type = symbol.GetMemberOrLocalOrParameterType(); Debug.Assert(type != null); - return TryCreate(symbol, indices, type, instance, out analysisEntity); + return TryCreate(symbol, indices, type!, instance, out analysisEntity); } - public bool TryCreateForTupleElements(ITupleOperation tupleOperation, out ImmutableArray elementEntities) + public bool TryCreateForTupleElements(ITupleOperation tupleOperation, [NotNullWhen(returnValue: true)] out ImmutableArray elementEntities) { if (_tupleElementEntitiesMap.TryGetValue(tupleOperation, out elementEntities)) { @@ -303,7 +303,8 @@ public bool TryCreateForTupleElements(ITupleOperation tupleOperation, out Immuta try { elementEntities = default; - if (!tupleOperation.Type.IsTupleType) + if (tupleOperation.Type?.IsTupleType != true || + _getPointsToAbstractValueOpt == null) { return false; } @@ -316,7 +317,7 @@ public bool TryCreateForTupleElements(ITupleOperation tupleOperation, out Immuta PointsToAbstractValue instanceLocation = _getPointsToAbstractValueOpt(tupleOperation); var underlyingValueTupleType = tupleType.GetUnderlyingValueTupleTypeOrThis(); - AnalysisEntity parentEntity = null; + AnalysisEntity? parentEntity = null; if (tupleOperation.TryGetParentTupleOperation(out var parentTupleOperationOpt, out var elementOfParentTupleContainingTuple) && TryCreateForTupleElements(parentTupleOperationOpt, out var parentTupleElementEntities)) { @@ -339,7 +340,7 @@ public bool TryCreateForTupleElements(ITupleOperation tupleOperation, out Immuta underlyingValueTupleType, instanceLocation, parentOpt: null); } - Debug.Assert(parentEntity.InstanceLocation == instanceLocation); + Debug.Assert(parentEntity!.InstanceLocation == instanceLocation); var builder = ArrayBuilder.GetInstance(tupleType.TupleElements.Length); foreach (var field in tupleType.TupleElements) @@ -365,20 +366,17 @@ public bool TryCreateForTupleElements(ITupleOperation tupleOperation, out Immuta } } - public bool TryCreateForArrayElementInitializer(IArrayCreationOperation arrayCreation, ImmutableArray indices, ITypeSymbol elementType, out AnalysisEntity analysisEntity) + public bool TryCreateForArrayElementInitializer(IArrayCreationOperation arrayCreation, ImmutableArray indices, ITypeSymbol elementType, [NotNullWhen(returnValue: true)] out AnalysisEntity? analysisEntity) { - Debug.Assert(arrayCreation != null); Debug.Assert(!indices.IsEmpty); - Debug.Assert(elementType != null); - ISymbol symbol = null; - return TryCreate(symbol, indices, elementType, arrayCreation, out analysisEntity); + return TryCreate(symbolOpt: null, indices, elementType, arrayCreation, out analysisEntity); } public bool TryGetForFlowCapture(CaptureId captureId, out AnalysisEntity analysisEntity) => _captureIdEntityMap.TryGetValue(captureId, out analysisEntity); - public bool TryGetForInterproceduralAnalysis(IOperation operation, out AnalysisEntity analysisEntity) + public bool TryGetForInterproceduralAnalysis(IOperation operation, out AnalysisEntity? analysisEntity) => _analysisEntityMap.TryGetValue(operation, out analysisEntity); private AnalysisEntity GetOrCreateForFlowCapture(CaptureId captureId, ITypeSymbol type, IOperation flowCaptureOrReference, bool isLValueFlowCapture) @@ -407,11 +405,10 @@ private AnalysisEntity GetOrCreateForFlowCapture(CaptureId captureId, ITypeSymbo return entity; } - private bool TryCreate(ISymbol symbolOpt, ImmutableArray indices, - ITypeSymbol type, IOperation instanceOpt, out AnalysisEntity analysisEntity) + private bool TryCreate(ISymbol? symbolOpt, ImmutableArray indices, + ITypeSymbol type, IOperation? instanceOpt, [NotNullWhen(returnValue: true)] out AnalysisEntity? analysisEntity) { Debug.Assert(symbolOpt != null || !indices.IsEmpty); - Debug.Assert(type != null); analysisEntity = null; @@ -429,8 +426,8 @@ private AnalysisEntity GetOrCreateForFlowCapture(CaptureId captureId, ITypeSymbo return false; } - PointsToAbstractValue instanceLocationOpt = null; - AnalysisEntity parentOpt = null; + PointsToAbstractValue? instanceLocationOpt = null; + AnalysisEntity? parentOpt = null; if (instanceOpt?.Type != null) { if (instanceOpt.Type.IsValueType) @@ -444,7 +441,7 @@ private AnalysisEntity GetOrCreateForFlowCapture(CaptureId captureId, ITypeSymbo else { // For value type allocations, we store the points to location. - var instancePointsToValue = _getPointsToAbstractValueOpt(instanceOpt); + var instancePointsToValue = _getPointsToAbstractValueOpt!(instanceOpt); if (!ReferenceEquals(instancePointsToValue, PointsToAbstractValue.NoLocation)) { instanceLocationOpt = instancePointsToValue; @@ -458,7 +455,7 @@ private AnalysisEntity GetOrCreateForFlowCapture(CaptureId captureId, ITypeSymbo } else { - instanceLocationOpt = _getPointsToAbstractValueOpt(instanceOpt); + instanceLocationOpt = _getPointsToAbstractValueOpt!(instanceOpt); } } @@ -466,7 +463,7 @@ private AnalysisEntity GetOrCreateForFlowCapture(CaptureId captureId, ITypeSymbo return true; } - private PointsToAbstractValue EnsureLocation(PointsToAbstractValue instanceLocationOpt, ISymbol symbolOpt, AnalysisEntity parentOpt) + private PointsToAbstractValue? EnsureLocation(PointsToAbstractValue? instanceLocationOpt, ISymbol? symbolOpt, AnalysisEntity? parentOpt) { if (instanceLocationOpt == null && symbolOpt != null) { @@ -483,7 +480,7 @@ private PointsToAbstractValue EnsureLocation(PointsToAbstractValue instanceLocat // Symbol instance location for locals and parameters should also include the interprocedural call stack because // we might have recursive invocations to the same method and the symbol declarations // from both the current and prior invocation of the method in the call stack should be distinct entities. - ImmutableStack interproceduralCallStackForSymbolDeclaration; + ImmutableStack? interproceduralCallStackForSymbolDeclaration; if (_interproceduralCallStackOpt != null && (symbolOpt.Kind == SymbolKind.Local || symbolOpt.Kind == SymbolKind.Parameter)) { @@ -505,11 +502,11 @@ private PointsToAbstractValue EnsureLocation(PointsToAbstractValue instanceLocat return instanceLocationOpt; } - private AnalysisEntity Create(ISymbol symbolOpt, ImmutableArray indices, ITypeSymbol type, PointsToAbstractValue instanceLocationOpt, AnalysisEntity parentOpt) + private AnalysisEntity Create(ISymbol? symbolOpt, ImmutableArray indices, ITypeSymbol type, PointsToAbstractValue? instanceLocationOpt, AnalysisEntity? parentOpt) { instanceLocationOpt = EnsureLocation(instanceLocationOpt, symbolOpt, parentOpt); Debug.Assert(instanceLocationOpt != null); - var analysisEntity = AnalysisEntity.Create(symbolOpt, indices, type, instanceLocationOpt, parentOpt); + var analysisEntity = AnalysisEntity.Create(symbolOpt, indices, type, instanceLocationOpt!, parentOpt); return analysisEntity; } diff --git a/src/Utilities/FlowAnalysis/FlowAnalysis/Framework/DataFlow/AnalysisEntityMapAbstractDomain.cs b/src/Utilities/FlowAnalysis/FlowAnalysis/Framework/DataFlow/AnalysisEntityMapAbstractDomain.cs index fcdf8dbab2..41b41a9504 100644 --- a/src/Utilities/FlowAnalysis/FlowAnalysis/Framework/DataFlow/AnalysisEntityMapAbstractDomain.cs +++ b/src/Utilities/FlowAnalysis/FlowAnalysis/Framework/DataFlow/AnalysisEntityMapAbstractDomain.cs @@ -32,9 +32,7 @@ protected virtual void AssertValidAnalysisData(DictionaryAnalysisData Merge(DictionaryAnalysisData map1, DictionaryAnalysisData map2) { - Debug.Assert(map1 != null); AssertValidAnalysisData(map1); - Debug.Assert(map2 != null); AssertValidAnalysisData(map2); TValue GetMergedValueForEntityPresentInOneMap(AnalysisEntity key, TValue value) diff --git a/src/Utilities/FlowAnalysis/FlowAnalysis/Framework/DataFlow/ArgumentInfo.cs b/src/Utilities/FlowAnalysis/FlowAnalysis/Framework/DataFlow/ArgumentInfo.cs index b77326f464..41185883dd 100644 --- a/src/Utilities/FlowAnalysis/FlowAnalysis/Framework/DataFlow/ArgumentInfo.cs +++ b/src/Utilities/FlowAnalysis/FlowAnalysis/Framework/DataFlow/ArgumentInfo.cs @@ -13,7 +13,7 @@ public sealed class ArgumentInfo : CacheBasedEquatable : CacheBasedEquatable addPart) addPart(Operation.GetHashCode()); addPart(AnalysisEntityOpt.GetHashCodeOrDefault()); addPart(InstanceLocation.GetHashCode()); - addPart(Value.GetHashCode()); + addPart(Value.GetHashCodeOrDefault()); } } } diff --git a/src/Utilities/FlowAnalysis/FlowAnalysis/Framework/DataFlow/CacheBasedEquatable.cs b/src/Utilities/FlowAnalysis/FlowAnalysis/Framework/DataFlow/CacheBasedEquatable.cs index a19ebd5c48..34db5b8b9d 100644 --- a/src/Utilities/FlowAnalysis/FlowAnalysis/Framework/DataFlow/CacheBasedEquatable.cs +++ b/src/Utilities/FlowAnalysis/FlowAnalysis/Framework/DataFlow/CacheBasedEquatable.cs @@ -53,8 +53,8 @@ private ImmutableArray ComputeHashCodeParts() public sealed override int GetHashCode() => GetOrComputeHashCode(); - public sealed override bool Equals(object obj) => Equals(obj as T); - public bool Equals(T other) + public sealed override bool Equals(object? obj) => Equals(obj as T); + public bool Equals(T? other) { // Perform fast equality checks first. if (ReferenceEquals(this, other)) @@ -74,7 +74,7 @@ public bool Equals(T other) return _lazyHashCodeParts.SequenceEqual(otherEquatable._lazyHashCodeParts); } - public static bool operator ==(CacheBasedEquatable value1, CacheBasedEquatable value2) + public static bool operator ==(CacheBasedEquatable? value1, CacheBasedEquatable? value2) { if (value1 is null) { @@ -88,7 +88,7 @@ public bool Equals(T other) return value1.Equals(value2); } - public static bool operator !=(CacheBasedEquatable value1, CacheBasedEquatable value2) + public static bool operator !=(CacheBasedEquatable? value1, CacheBasedEquatable? value2) { return !(value1 == value2); } diff --git a/src/Utilities/FlowAnalysis/FlowAnalysis/Framework/DataFlow/ConversionInference.cs b/src/Utilities/FlowAnalysis/FlowAnalysis/Framework/DataFlow/ConversionInference.cs index 4f5a981d3d..846182b8e6 100644 --- a/src/Utilities/FlowAnalysis/FlowAnalysis/Framework/DataFlow/ConversionInference.cs +++ b/src/Utilities/FlowAnalysis/FlowAnalysis/Framework/DataFlow/ConversionInference.cs @@ -25,8 +25,8 @@ public static ConversionInference Create(IIsPatternOperation operation) isTryCast: true); public static ConversionInference Create( - ITypeSymbol targetTypeOpt, - ITypeSymbol sourceTypeOpt, + ITypeSymbol? targetTypeOpt, + ITypeSymbol? sourceTypeOpt, bool isTryCast) { return new ConversionInference diff --git a/src/Utilities/FlowAnalysis/FlowAnalysis/Framework/DataFlow/DataFlowAnalysis.cs b/src/Utilities/FlowAnalysis/FlowAnalysis/Framework/DataFlow/DataFlowAnalysis.cs index 1fdbe6b761..cfca744b81 100644 --- a/src/Utilities/FlowAnalysis/FlowAnalysis/Framework/DataFlow/DataFlowAnalysis.cs +++ b/src/Utilities/FlowAnalysis/FlowAnalysis/Framework/DataFlow/DataFlowAnalysis.cs @@ -32,7 +32,7 @@ protected DataFlowAnalysis(AbstractAnalysisDomain analysisDomain, protected AbstractAnalysisDomain AnalysisDomain { get; } protected DataFlowOperationVisitor OperationVisitor { get; } - protected TAnalysisResult TryGetOrComputeResultCore(TAnalysisContext analysisContext, bool cacheResult) + protected TAnalysisResult? TryGetOrComputeResultCore(TAnalysisContext analysisContext, bool cacheResult) { if (analysisContext == null) { @@ -49,7 +49,7 @@ protected TAnalysisResult TryGetOrComputeResultCore(TAnalysisContext analysisCon return analysisResultsMap.GetOrAdd(analysisContext, _ => Run(analysisContext)); } - private TAnalysisResult Run(TAnalysisContext analysisContext) + private TAnalysisResult? Run(TAnalysisContext analysisContext) { var cfg = analysisContext.ControlFlowGraph; if (cfg?.SupportsFlowAnalysis() != true) @@ -88,7 +88,7 @@ private TAnalysisResult Run(TAnalysisContext analysisContext) var loopRangeMap = PooledDictionary.GetInstance(); ComputeLoopRangeMap(cfg, loopRangeMap); - TAnalysisData normalPathsExitBlockData = null, exceptionPathsExitBlockDataOpt = null; + TAnalysisData? normalPathsExitBlockData = null, exceptionPathsExitBlockDataOpt = null; try { @@ -118,7 +118,7 @@ private TAnalysisResult Run(TAnalysisContext analysisContext) if (analysisContext.ExceptionPathsAnalysis) { // Clone and save exit block data - normalPathsExitBlockData = AnalysisDomain.Clone(normalPathsExitBlockData); + normalPathsExitBlockData = AnalysisDomain.Clone(normalPathsExitBlockData!); OperationVisitor.ExecutingExceptionPathsAnalysisPostPass = true; foreach (var block in cfg.Blocks) @@ -152,7 +152,7 @@ private TAnalysisResult Run(TAnalysisContext analysisContext) var dataflowAnalysisResult = resultBuilder.ToResult(ToBlockResult, OperationVisitor.GetStateMap(), OperationVisitor.GetPredicateValueKindMap(), OperationVisitor.GetReturnValueAndPredicateKind(), OperationVisitor.InterproceduralResultsMap, - resultBuilder.EntryBlockOutputData, normalPathsExitBlockData, exceptionPathsExitBlockDataOpt, + resultBuilder.EntryBlockOutputData!, normalPathsExitBlockData!, exceptionPathsExitBlockDataOpt, mergedDataForUnhandledThrowOperationsOpt, OperationVisitor.AnalysisDataForUnhandledThrowOperations, OperationVisitor.TaskWrappedValuesMapOpt, cfg, OperationVisitor.ValueDomain.UnknownOrMayBeValue); return ToResult(analysisContext, dataflowAnalysisResult); @@ -176,7 +176,7 @@ private TAnalysisResult Run(TAnalysisContext analysisContext) ControlFlowGraph cfg, SortedSet worklist, SortedSet pendingBlocksNeedingAtLeastOnePass, - TAnalysisData initialAnalysisDataOpt, + TAnalysisData? initialAnalysisDataOpt, DataFlowAnalysisResultBuilder resultBuilder, PooledHashSet uniqueSuccessors, PooledDictionary> finallyBlockSuccessorsMap, @@ -266,7 +266,7 @@ private TAnalysisResult Run(TAnalysisContext analysisContext) else { // For catch and filter regions, we track the initial input data in the catchBlockInputDataMap. - ControlFlowRegion enclosingTryAndCatchRegion = GetEnclosingTryAndCatchRegionIfStartsHandler(block); + ControlFlowRegion? enclosingTryAndCatchRegion = GetEnclosingTryAndCatchRegionIfStartsHandler(block); if (enclosingTryAndCatchRegion != null && catchBlockInputDataMap.TryGetValue(enclosingTryAndCatchRegion, out var catchBlockInput)) { @@ -403,17 +403,17 @@ private TAnalysisResult Run(TAnalysisContext analysisContext) // Check if the current input data for the successor block is equal to the new input data from this branch. // If so, we don't need to propagate new input data from this branch. - if (AnalysisDomain.Equals(currentSuccessorInput, newSuccessorInput)) + if (AnalysisDomain.Equals(currentSuccessorInput!, newSuccessorInput)) { newSuccessorInput.Dispose(); continue; } // Otherwise, check if the input data for the successor block changes after merging with the new input data. - mergedSuccessorInput = OperationVisitor.MergeAnalysisData(currentSuccessorInput, newSuccessorInput, isBackEdge); + mergedSuccessorInput = OperationVisitor.MergeAnalysisData(currentSuccessorInput!, newSuccessorInput, isBackEdge); newSuccessorInput.Dispose(); - int compare = AnalysisDomain.Compare(currentSuccessorInput, mergedSuccessorInput); + int compare = AnalysisDomain.Compare(currentSuccessorInput!, mergedSuccessorInput); // The newly computed abstract values for each basic block // must be always greater or equal than the previous value @@ -485,7 +485,7 @@ void UpdateUnreachableBlocks() } } - static ControlFlowRegion TryGetReachableCatchRegionStartingHandler(ControlFlowRegion tryAndCatchRegion, BasicBlock sourceBlock) + static ControlFlowRegion? TryGetReachableCatchRegionStartingHandler(ControlFlowRegion tryAndCatchRegion, BasicBlock sourceBlock) { Debug.Assert(tryAndCatchRegion.Kind == ControlFlowRegionKind.TryAndCatch); @@ -501,7 +501,7 @@ static ControlFlowRegion TryGetReachableCatchRegionStartingHandler(ControlFlowRe return catchRegion; } - ControlFlowRegion MergeIntoCatchInputData(ControlFlowRegion tryAndCatchRegion, TAnalysisData dataToMerge, BasicBlock sourceBlock) + ControlFlowRegion? MergeIntoCatchInputData(ControlFlowRegion tryAndCatchRegion, TAnalysisData dataToMerge, BasicBlock sourceBlock) { var catchRegion = TryGetReachableCatchRegionStartingHandler(tryAndCatchRegion, sourceBlock); if (catchRegion == null) @@ -587,7 +587,7 @@ bool HasUnprocessedPredecessorBlock(BasicBlock block) } // If this block starts a catch/filter region, return the enclosing TryAndCatch region. - static ControlFlowRegion GetEnclosingTryAndCatchRegionIfStartsHandler(BasicBlock block) + static ControlFlowRegion? GetEnclosingTryAndCatchRegionIfStartsHandler(BasicBlock block) { if (block.EnclosingRegion?.FirstBlockOrdinal == block.Ordinal) { @@ -613,7 +613,7 @@ static ControlFlowRegion GetEnclosingTryAndCatchRegionIfStartsHandler(BasicBlock return null; } - IEnumerable<(BranchWithInfo successorWithBranch, BranchWithInfo preadjustSuccessorWithBranch)> GetSuccessorsWithAdjustedBranches(BasicBlock basicBlock) + IEnumerable<(BranchWithInfo successorWithBranch, BranchWithInfo? preadjustSuccessorWithBranch)> GetSuccessorsWithAdjustedBranches(BasicBlock basicBlock) { if (basicBlock.Kind != BasicBlockKind.Exit) { @@ -733,7 +733,7 @@ void AddFinallySuccessor(ControlFlowRegion finallyRegion, BranchWithInfo success } } - private TAnalysisData GetClonedAnalysisDataOrEmptyData(TAnalysisData initialAnalysisDataOpt) + private TAnalysisData GetClonedAnalysisDataOrEmptyData(TAnalysisData? initialAnalysisDataOpt) { if (initialAnalysisDataOpt != null) { @@ -776,8 +776,7 @@ private TAnalysisData GetClonedAnalysisDataOrEmptyData(TAnalysisData initialAnal private void UpdateInput(DataFlowAnalysisResultBuilder builder, BasicBlock block, TAnalysisData newInput) { - Debug.Assert(newInput != null); - Debug.Assert(builder[block] == null || AnalysisDomain.Compare(builder[block], newInput) <= 0, "Non-monotonic update"); + Debug.Assert(builder[block] == null || AnalysisDomain.Compare(builder[block]!, newInput) <= 0, "Non-monotonic update"); builder.Update(block, newInput); } diff --git a/src/Utilities/FlowAnalysis/FlowAnalysis/Framework/DataFlow/DataFlowAnalysisResult.cs b/src/Utilities/FlowAnalysis/FlowAnalysis/Framework/DataFlow/DataFlowAnalysisResult.cs index e765edb137..ad467782ca 100644 --- a/src/Utilities/FlowAnalysis/FlowAnalysis/Framework/DataFlow/DataFlowAnalysisResult.cs +++ b/src/Utilities/FlowAnalysis/FlowAnalysis/Framework/DataFlow/DataFlowAnalysisResult.cs @@ -24,7 +24,7 @@ public class DataFlowAnalysisResult _predicateValueKindMap; private readonly ImmutableDictionary> _interproceduralResultsMap; private readonly TAbstractAnalysisValue _defaultUnknownValue; - private readonly object _analysisDataForUnhandledThrowOperationsOpt; + private readonly object? _analysisDataForUnhandledThrowOperationsOpt; internal DataFlowAnalysisResult( ImmutableDictionary basicBlockStateMap, @@ -34,20 +34,13 @@ public class DataFlowAnalysisResult> interproceduralResultsMap, TBlockAnalysisResult entryBlockOutput, TBlockAnalysisResult exitBlockOutput, - TBlockAnalysisResult exceptionPathsExitBlockOutputOpt, - TBlockAnalysisResult mergedStateForUnhandledThrowOperationsOpt, - object analysisDataForUnhandledThrowOperationsOpt, - Dictionary taskWrappedValuesMapOpt, + TBlockAnalysisResult? exceptionPathsExitBlockOutputOpt, + TBlockAnalysisResult? mergedStateForUnhandledThrowOperationsOpt, + object? analysisDataForUnhandledThrowOperationsOpt, + Dictionary? taskWrappedValuesMapOpt, ControlFlowGraph cfg, TAbstractAnalysisValue defaultUnknownValue) { - Debug.Assert(basicBlockStateMap != null); - Debug.Assert(operationStateMap != null); - Debug.Assert(predicateValueKindMap != null); - Debug.Assert(interproceduralResultsMap != null); - Debug.Assert(entryBlockOutput != null); - Debug.Assert(exitBlockOutput != null); - _basicBlockStateMap = basicBlockStateMap; _operationStateMap = operationStateMap; _predicateValueKindMap = predicateValueKindMap; @@ -75,9 +68,6 @@ protected DataFlowAnalysisResult(DataFlowAnalysisResult( _basicBlockStateMap, _operationStateMap, _predicateValueKindMap, ReturnValueAndPredicateKindOpt, _interproceduralResultsMap, EntryBlockOutput, ExitBlockOutput, ExceptionPathsExitBlockOutputOpt, mergedStateForUnhandledThrowOperationsOpt, @@ -127,7 +117,7 @@ protected DataFlowAnalysisResult(DataFlowAnalysisResult TryGetInterproceduralResult(IOperation operation) + internal DataFlowAnalysisResult? TryGetInterproceduralResult(IOperation operation) { if (_interproceduralResultsMap.TryGetValue(operation, out var result)) { @@ -141,16 +131,16 @@ protected DataFlowAnalysisResult(DataFlowAnalysisResult.AnalysisDataForUnhandledThrowOperationsOpt + object? IDataFlowAnalysisResult.AnalysisDataForUnhandledThrowOperationsOpt => _analysisDataForUnhandledThrowOperationsOpt; - object IDataFlowAnalysisResult.TaskWrappedValuesMapOpt + object? IDataFlowAnalysisResult.TaskWrappedValuesMapOpt => TaskWrappedValuesMapOpt; - public TBlockAnalysisResult MergedStateForUnhandledThrowOperationsOpt { get; } + public TBlockAnalysisResult? MergedStateForUnhandledThrowOperationsOpt { get; } public PredicateValueKind GetPredicateKind(IOperation operation) => _predicateValueKindMap.TryGetValue(operation, out var valueKind) ? valueKind : PredicateValueKind.Unknown; - internal Dictionary TaskWrappedValuesMapOpt { get; } + internal Dictionary? TaskWrappedValuesMapOpt { get; } } } diff --git a/src/Utilities/FlowAnalysis/FlowAnalysis/Framework/DataFlow/DataFlowAnalysisResultBuilder.cs b/src/Utilities/FlowAnalysis/FlowAnalysis/Framework/DataFlow/DataFlowAnalysisResultBuilder.cs index cedb724128..ef5f378ac4 100644 --- a/src/Utilities/FlowAnalysis/FlowAnalysis/Framework/DataFlow/DataFlowAnalysisResultBuilder.cs +++ b/src/Utilities/FlowAnalysis/FlowAnalysis/Framework/DataFlow/DataFlowAnalysisResultBuilder.cs @@ -17,17 +17,17 @@ internal sealed class DataFlowAnalysisResultBuilder : IDisposable where TAnalysisData : AbstractAnalysisData { #pragma warning disable CA2213 // Disposable fields should be disposed - private readonly PooledDictionary _info; + private readonly PooledDictionary _info; #pragma warning restore public DataFlowAnalysisResultBuilder() { - _info = PooledDictionary.GetInstance(); + _info = PooledDictionary.GetInstance(); } - public TAnalysisData this[BasicBlock block] => _info[block]; - public TAnalysisData EntryBlockOutputData { get; set; } - public TAnalysisData ExitBlockOutputData { get; set; } + public TAnalysisData? this[BasicBlock block] => _info[block]; + public TAnalysisData? EntryBlockOutputData { get; set; } + public TAnalysisData? ExitBlockOutputData { get; set; } internal void Add(BasicBlock block) { @@ -47,10 +47,10 @@ internal void Update(BasicBlock block, TAnalysisData newData) ImmutableDictionary> interproceduralResultsMap, TAnalysisData entryBlockOutputData, TAnalysisData exitBlockData, - TAnalysisData exceptionPathsExitBlockDataOpt, - TAnalysisData mergedDataForUnhandledThrowOperationsOpt, - Dictionary analysisDataForUnhandledThrowOperationsOpt, - Dictionary taskWrappedValuesMapOpt, + TAnalysisData? exceptionPathsExitBlockDataOpt, + TAnalysisData? mergedDataForUnhandledThrowOperationsOpt, + Dictionary? analysisDataForUnhandledThrowOperationsOpt, + Dictionary? taskWrappedValuesMapOpt, ControlFlowGraph cfg, TAbstractAnalysisValue defaultUnknownValue) where TBlockAnalysisResult : AbstractBlockAnalysisResult @@ -60,7 +60,7 @@ internal void Update(BasicBlock block, TAnalysisData newData) { var block = kvp.Key; var blockAnalysisData = kvp.Value; - var result = getBlockResult(block, blockAnalysisData); + var result = getBlockResult(block, blockAnalysisData!); resultBuilder.Add(block, result); } diff --git a/src/Utilities/FlowAnalysis/FlowAnalysis/Framework/DataFlow/DataFlowOperationVisitor.cs b/src/Utilities/FlowAnalysis/FlowAnalysis/Framework/DataFlow/DataFlowOperationVisitor.cs index 182319391b..d0e65ac1e4 100644 --- a/src/Utilities/FlowAnalysis/FlowAnalysis/Framework/DataFlow/DataFlowOperationVisitor.cs +++ b/src/Utilities/FlowAnalysis/FlowAnalysis/Framework/DataFlow/DataFlowOperationVisitor.cs @@ -4,6 +4,7 @@ using System.Collections.Generic; using System.Collections.Immutable; using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; using System.Linq; using System.Threading; using Analyzer.Utilities; @@ -24,7 +25,7 @@ namespace Microsoft.CodeAnalysis.FlowAnalysis.DataFlow public abstract class DataFlowOperationVisitor : OperationVisitor where TAnalysisData : AbstractAnalysisData where TAnalysisContext : AbstractDataFlowAnalysisContext - where TAnalysisResult : IDataFlowAnalysisResult + where TAnalysisResult : class, IDataFlowAnalysisResult { private static readonly DiagnosticDescriptor s_dummyDataflowAnalysisDescriptor = new DiagnosticDescriptor( id: "InterproceduralDataflow", @@ -41,10 +42,11 @@ public abstract class DataFlowOperationVisitor _pendingArgumentsToReset; private readonly List _pendingArgumentsToPostProcess; private readonly HashSet _visitedFlowBranchConditions; - private readonly HashSet _returnValueOperationsOpt; - private ImmutableDictionary _lazyParameterEntities; - private ImmutableHashSet _lazyContractCheckMethodsForPredicateAnalysis; - private TAnalysisData _currentAnalysisData; + private readonly HashSet? _returnValueOperationsOpt; + private ImmutableDictionary? _lazyParameterEntities; + private ImmutableHashSet? _lazyContractCheckMethodsForPredicateAnalysis; + private TAnalysisData? _currentAnalysisData; + private BasicBlock? _currentBasicBlock; private int _recursionDepth; #region Fields specific to Interprocedural analysis @@ -86,31 +88,31 @@ private uint MaxInterproceduralLambdaOrLocalFunctionCallChain /// /// Dictionary from interprocedural method symbols invoked to their corresponding . /// - private readonly Dictionary _interproceduralMethodToCfgMapOpt; + private readonly Dictionary? _interproceduralMethodToCfgMapOpt; #endregion protected abstract TAbstractAnalysisValue GetAbstractDefaultValue(ITypeSymbol type); protected virtual TAbstractAnalysisValue GetAbstractDefaultValueForCatchVariable(ICatchClauseOperation catchClause) => ValueDomain.UnknownOrMayBeValue; protected abstract bool HasAnyAbstractValue(TAnalysisData data); - protected abstract void SetValueForParameterOnEntry(IParameterSymbol parameter, AnalysisEntity analysisEntity, ArgumentInfo assignedValueOpt); + protected abstract void SetValueForParameterOnEntry(IParameterSymbol parameter, AnalysisEntity analysisEntity, ArgumentInfo? assignedValueOpt); protected abstract void EscapeValueForParameterOnExit(IParameterSymbol parameter, AnalysisEntity analysisEntity); protected abstract void ResetCurrentAnalysisData(); protected bool HasPointsToAnalysisResult => DataFlowAnalysisContext.PointsToAnalysisResultOpt != null || IsPointsToAnalysis; protected virtual bool IsPointsToAnalysis => false; - internal Dictionary AnalysisDataForUnhandledThrowOperations { get; private set; } + internal Dictionary? AnalysisDataForUnhandledThrowOperations { get; private set; } public ImmutableDictionary> InterproceduralResultsMap => _interproceduralResultsBuilder.ToImmutable(); /// /// Optional map from points to values of tasks to the underlying abstract value returned by the task. /// Awaiting the task produces the task wrapped value from this map. /// - internal Dictionary TaskWrappedValuesMapOpt { get; private set; } + internal Dictionary? TaskWrappedValuesMapOpt { get; private set; } protected TAnalysisContext DataFlowAnalysisContext { get; } public AbstractValueDomain ValueDomain => DataFlowAnalysisContext.ValueDomain; protected ISymbol OwningSymbol => DataFlowAnalysisContext.OwningSymbol; protected WellKnownTypeProvider WellKnownTypeProvider => DataFlowAnalysisContext.WellKnownTypeProvider; - protected Func TryGetOrComputeAnalysisResult + protected Func TryGetOrComputeAnalysisResult => DataFlowAnalysisContext.TryGetOrComputeAnalysisResult; internal bool ExecutingExceptionPathsAnalysisPostPass { get; set; } @@ -118,18 +120,29 @@ protected TAnalysisData CurrentAnalysisData { get { - Debug.Assert(!_currentAnalysisData.IsDisposed); - return _currentAnalysisData; + Debug.Assert(_currentAnalysisData != null); + Debug.Assert(!_currentAnalysisData!.IsDisposed); + return _currentAnalysisData!; } private set { - Debug.Assert(value != null); Debug.Assert(!value.IsDisposed); _currentAnalysisData = value; } } - protected BasicBlock CurrentBasicBlock { get; private set; } + protected BasicBlock CurrentBasicBlock + { + get + { + Debug.Assert(_currentBasicBlock != null); + return _currentBasicBlock!; + } + private set + { + _currentBasicBlock = value; + } + } protected ControlFlowConditionKind FlowBranchConditionKind { get; private set; } protected PointsToAbstractValue ThisOrMePointsToAbstractValue { get; } protected AnalysisEntityFactory AnalysisEntityFactory { get; } @@ -163,7 +176,7 @@ protected bool IsLValueFlowCapture(IFlowCaptureOperation flowCapture) protected bool IsLValueFlowCaptureReference(IFlowCaptureReferenceOperation flowCaptureReference) => flowCaptureReference.IsLValueFlowCaptureReference(); - private Dictionary _exceptionPathsThrownExceptionInfoMapOpt; + private Dictionary? _exceptionPathsThrownExceptionInfoMapOpt; private ThrownExceptionInfo DefaultThrownExceptionInfo { get @@ -225,13 +238,13 @@ protected DataFlowOperationVisitor(TAnalysisContext analysisContext) } else { - _interproceduralMethodToCfgMapOpt = new Dictionary(); + _interproceduralMethodToCfgMapOpt = new Dictionary(); } - AnalysisEntity interproceduralInvocationInstanceOpt; + AnalysisEntity? interproceduralInvocationInstanceOpt; if (analysisContext.InterproceduralAnalysisDataOpt?.InvocationInstanceOpt.HasValue == true) { - (interproceduralInvocationInstanceOpt, ThisOrMePointsToAbstractValue) = analysisContext.InterproceduralAnalysisDataOpt.InvocationInstanceOpt.Value; + (interproceduralInvocationInstanceOpt, ThisOrMePointsToAbstractValue) = analysisContext.InterproceduralAnalysisDataOpt.InvocationInstanceOpt!.Value; } else { @@ -244,7 +257,7 @@ protected DataFlowOperationVisitor(TAnalysisContext analysisContext) DataFlowAnalysisContext.WellKnownTypeProvider, getPointsToAbstractValueOpt: (analysisContext.PointsToAnalysisResultOpt != null || IsPointsToAnalysis) ? GetPointsToAbstractValue : - (Func)null, + (Func?)null, getIsInsideAnonymousObjectInitializer: () => IsInsideAnonymousObjectInitializer, getIsLValueFlowCapture: IsLValueFlowCapture, containingTypeSymbol: analysisContext.OwningSymbol.ContainingType, @@ -259,7 +272,7 @@ protected DataFlowOperationVisitor(TAnalysisContext analysisContext) protected CopyAbstractValue GetDefaultCopyValue(AnalysisEntity analysisEntity) => _addressSharedEntitiesProvider.GetDefaultCopyValue(analysisEntity); - protected CopyAbstractValue TryGetAddressSharedCopyValue(AnalysisEntity analysisEntity) + protected CopyAbstractValue? TryGetAddressSharedCopyValue(AnalysisEntity analysisEntity) => _addressSharedEntitiesProvider.TryGetAddressSharedCopyValue(analysisEntity); public virtual (TAbstractAnalysisValue Value, PredicateValueKind PredicateValueKind)? GetReturnValueAndPredicateKind() @@ -376,7 +389,7 @@ public TAnalysisData OnStartBlockAnalysis(BasicBlock block, TAnalysisData input) public TAnalysisData OnEndBlockAnalysis(BasicBlock block, TAnalysisData analysisData) { - CurrentBasicBlock = block; + _currentBasicBlock = block; CurrentAnalysisData = analysisData; if (block.EnclosingRegion != null && @@ -405,7 +418,7 @@ public TAnalysisData OnEndBlockAnalysis(BasicBlock block, TAnalysisData analysis OnEndExitBlockAnalysis(block); } - CurrentBasicBlock = null; + _currentBasicBlock = null; return CurrentAnalysisData; } @@ -469,18 +482,18 @@ private void OnStartEntryBlockAnalysis(BasicBlock entryBlock) foreach (var parameter in method.Parameters) { - var result = AnalysisEntityFactory.TryCreateForSymbolDeclaration(parameter, out AnalysisEntity analysisEntity); + var result = AnalysisEntityFactory.TryCreateForSymbolDeclaration(parameter, out var analysisEntity); Debug.Assert(result); - builder.Add(parameter, analysisEntity); + builder.Add(parameter, analysisEntity!); - ArgumentInfo assignedValueOpt = null; + ArgumentInfo? assignedValueOpt = null; if (argumentValuesMap.TryGetValue(parameter.OriginalDefinition, out var argumentInfo)) { assignedValueOpt = argumentInfo; } - _addressSharedEntitiesProvider.UpdateAddressSharedEntitiesForParameter(parameter, analysisEntity, assignedValueOpt); - SetValueForParameterOnEntry(parameter, analysisEntity, assignedValueOpt); + _addressSharedEntitiesProvider.UpdateAddressSharedEntitiesForParameter(parameter, analysisEntity!, assignedValueOpt); + SetValueForParameterOnEntry(parameter, analysisEntity!, assignedValueOpt); } _lazyParameterEntities = builder.ToImmutable(); @@ -543,9 +556,6 @@ protected bool IsParameterEntityForCurrentMethod(AnalysisEntity analysisEntity) BranchWithInfo branch, TAnalysisData input) { - Debug.Assert(fromBlock != null); - Debug.Assert(input != null); - var isFeasibleBranch = true; CurrentBasicBlock = fromBlock; CurrentAnalysisData = input; @@ -605,10 +615,9 @@ protected bool IsParameterEntityForCurrentMethod(AnalysisEntity analysisEntity) bool isConditionalBranchNeverTaken() { - Debug.Assert(branch.BranchValueOpt != null); Debug.Assert(branch.ControlFlowConditionKind != ControlFlowConditionKind.None); - if (branch.BranchValueOpt.Type?.SpecialType == SpecialType.System_Boolean && + if (branch.BranchValueOpt!.Type?.SpecialType == SpecialType.System_Boolean && branch.BranchValueOpt.ConstantValue.HasValue) { var alwaysTrue = (bool)branch.BranchValueOpt.ConstantValue.Value; @@ -675,7 +684,7 @@ bool isPredicateAlwaysFalseForBranch(PredicateValueKind predicateValueKind) return ValueDomain.UnknownOrMayBeValue; } - protected virtual void ProcessReturnValue(IOperation returnValueOperation) + protected virtual void ProcessReturnValue(IOperation? returnValueOperation) { if (returnValueOperation != null) { @@ -690,10 +699,8 @@ protected virtual void ProcessReturnValue(IOperation returnValueOperation) } } - private TAbstractAnalysisValue GetAbstractValueForReturnOperation(IOperation returnValueOperation, out PointsToAbstractValue implicitTaskPointsToValueOpt) + private TAbstractAnalysisValue GetAbstractValueForReturnOperation(IOperation returnValueOperation, out PointsToAbstractValue? implicitTaskPointsToValueOpt) { - Debug.Assert(returnValueOperation != null); - implicitTaskPointsToValueOpt = null; var returnValue = GetCachedAbstractValue(returnValueOperation); @@ -732,8 +739,8 @@ protected virtual void HandlePossibleThrowingOperation(IOperation operation) return; } - IOperation instanceOpt = null; - IOperation invocationOpt = null; + IOperation? instanceOpt = null; + IOperation? invocationOpt = null; switch (operation) { case IMemberReferenceOperation memberReference: @@ -781,7 +788,7 @@ protected virtual void HandlePossibleThrowingOperation(IOperation operation) // This operation can throw, so update the analysis data for unhandled exception with 'System.Exception' type. AnalysisDataForUnhandledThrowOperations ??= new Dictionary(); - if (!AnalysisDataForUnhandledThrowOperations.TryGetValue(DefaultThrownExceptionInfo, out var data) || + if (!AnalysisDataForUnhandledThrowOperations.TryGetValue(DefaultThrownExceptionInfo, out TAnalysisData? data) || CurrentBasicBlock.IsContainedInRegionOfKind(ControlFlowRegionKind.Finally)) { data = null; @@ -789,11 +796,11 @@ protected virtual void HandlePossibleThrowingOperation(IOperation operation) data = GetMergedAnalysisDataForPossibleThrowingOperation(data, operation); Debug.Assert(data != null); - AssertValidAnalysisData(data); - AnalysisDataForUnhandledThrowOperations[DefaultThrownExceptionInfo] = data; + AssertValidAnalysisData(data!); + AnalysisDataForUnhandledThrowOperations[DefaultThrownExceptionInfo] = data!; } - protected virtual TAnalysisData GetMergedAnalysisDataForPossibleThrowingOperation(TAnalysisData existingDataOpt, IOperation operation) + protected virtual TAnalysisData GetMergedAnalysisDataForPossibleThrowingOperation(TAnalysisData? existingDataOpt, IOperation operation) { Debug.Assert(DataFlowAnalysisContext.ExceptionPathsAnalysis); Debug.Assert(ExecutingExceptionPathsAnalysisPostPass); @@ -819,7 +826,7 @@ protected virtual TAnalysisData GetMergedAnalysisDataForPossibleThrowingOperatio ProcessOutOfScopeLocalsAndFlowCaptures(leavingRegionLocals, leavingRegionFlowCaptures); - CurrentBasicBlock = null; + _currentBasicBlock = null; return CurrentAnalysisData; } @@ -872,14 +879,14 @@ private bool IsContractCheckArgument(IArgumentOperation operation) internal ImmutableDictionary GetPredicateValueKindMap() => _predicateValueKindCacheBuilder.ToImmutable(); - public virtual TAnalysisData GetMergedDataForUnhandledThrowOperations() + public virtual TAnalysisData? GetMergedDataForUnhandledThrowOperations() { if (AnalysisDataForUnhandledThrowOperations == null) { return default; } - TAnalysisData mergedData = default; + TAnalysisData? mergedData = default; foreach (TAnalysisData data in AnalysisDataForUnhandledThrowOperations.Values) { mergedData = mergedData != null ? MergeAnalysisData(mergedData, data) : data; @@ -1003,19 +1010,17 @@ protected ImmutableHashSet GetEscapedLocations(AnalysisEntity protected bool TryGetPointsToAbstractValueAtEntryBlockEnd(AnalysisEntity analysisEntity, out PointsToAbstractValue pointsToAbstractValue) { - Debug.Assert(CurrentBasicBlock != null); Debug.Assert(CurrentBasicBlock.Kind == BasicBlockKind.Entry); Debug.Assert(DataFlowAnalysisContext.PointsToAnalysisResultOpt != null); - var outputData = DataFlowAnalysisContext.PointsToAnalysisResultOpt.EntryBlockOutput.Data; + var outputData = DataFlowAnalysisContext.PointsToAnalysisResultOpt!.EntryBlockOutput.Data; return outputData.TryGetValue(analysisEntity, out pointsToAbstractValue); } protected bool TryGetNullAbstractValueAtCurrentBlockEntry(AnalysisEntity analysisEntity, out NullAbstractValue nullAbstractValue) { - Debug.Assert(CurrentBasicBlock != null); Debug.Assert(DataFlowAnalysisContext.PointsToAnalysisResultOpt != null); - var inputData = DataFlowAnalysisContext.PointsToAnalysisResultOpt[CurrentBasicBlock].Data; + var inputData = DataFlowAnalysisContext.PointsToAnalysisResultOpt![CurrentBasicBlock].Data; if (inputData.TryGetValue(analysisEntity, out PointsToAbstractValue pointsToAbstractValue)) { nullAbstractValue = pointsToAbstractValue.NullState; @@ -1028,9 +1033,8 @@ protected bool TryGetNullAbstractValueAtCurrentBlockEntry(AnalysisEntity analysi protected bool TryGetMergedNullAbstractValueAtUnhandledThrowOperationsInGraph(AnalysisEntity analysisEntity, out NullAbstractValue nullAbstractValue) { - Debug.Assert(CurrentBasicBlock != null); Debug.Assert(DataFlowAnalysisContext.PointsToAnalysisResultOpt != null); - var inputData = DataFlowAnalysisContext.PointsToAnalysisResultOpt.MergedStateForUnhandledThrowOperationsOpt?.Data; + var inputData = DataFlowAnalysisContext.PointsToAnalysisResultOpt!.MergedStateForUnhandledThrowOperationsOpt?.Data; if (inputData == null || !inputData.TryGetValue(analysisEntity, out PointsToAbstractValue pointsToAbstractValue)) { nullAbstractValue = NullAbstractValue.MaybeNull; @@ -1056,7 +1060,7 @@ private protected bool TryGetTaskWrappedValue(PointsToAbstractValue pointsToAbst { if (TaskWrappedValuesMapOpt == null) { - wrappedValue = default; + wrappedValue = ValueDomain.UnknownOrMayBeValue; return false; } @@ -1100,7 +1104,7 @@ internal bool TryInferConversion(IIsPatternOperation operation, out ConversionIn private bool TryInferConversion( IOperation sourceOperand, - ITypeSymbol targetType, + ITypeSymbol? targetType, bool isTryCast, IOperation operation, out ConversionInference inference) @@ -1200,7 +1204,7 @@ internal bool TryInferConversion(IIsPatternOperation operation, out ConversionIn return false; // We are currently bailing out if an interface or type parameter is involved. - static bool IsInterfaceOrTypeParameter(ITypeSymbol type) => type.TypeKind == TypeKind.Interface || type.TypeKind == TypeKind.TypeParameter; + static bool IsInterfaceOrTypeParameter(ITypeSymbol? type) => type?.TypeKind == TypeKind.Interface || type?.TypeKind == TypeKind.TypeParameter; } #endregion @@ -1255,7 +1259,7 @@ private void PerformPredicateAnalysis(IOperation operation) // Check if we need to perform predicate analysis for the operation and/or set/transfer predicate data. // First find out if this operation is being captured. - AnalysisEntity predicatedFlowCaptureEntityOpt = GetPredicatedFlowCaptureEntity(); + AnalysisEntity? predicatedFlowCaptureEntityOpt = GetPredicatedFlowCaptureEntity(); if (predicatedFlowCaptureEntityOpt == null) { // Operation is not being flow captured, we may have to perform predicate analysis. @@ -1286,9 +1290,9 @@ private void PerformPredicateAnalysis(IOperation operation) if (operation.Kind == OperationKind.FlowCaptureReference) { // FC = FCR0 - var result = AnalysisEntityFactory.TryCreate(operation, out AnalysisEntity flowCaptureReferenceEntity); + var result = AnalysisEntityFactory.TryCreate(operation, out AnalysisEntity? flowCaptureReferenceEntity); Debug.Assert(result); - Debug.Assert(flowCaptureReferenceEntity.CaptureIdOpt != null); + Debug.Assert(flowCaptureReferenceEntity!.CaptureIdOpt != null); Debug.Assert(HasPredicatedDataForEntity(flowCaptureReferenceEntity)); TransferPredicatedData(fromEntity: flowCaptureReferenceEntity, toEntity: predicatedFlowCaptureEntityOpt); } @@ -1363,7 +1367,7 @@ bool IsRootOfCondition() return current == null; } - AnalysisEntity GetPredicatedFlowCaptureEntity() + AnalysisEntity? GetPredicatedFlowCaptureEntity() { var current = operation.Parent; while (current != null) @@ -1465,9 +1469,9 @@ private void PerformPredicateAnalysisCore(IOperation operation, TAnalysisData ta return; case IFlowCaptureReferenceOperation _: - var result = AnalysisEntityFactory.TryCreate(operation, out AnalysisEntity flowCaptureReferenceEntity); + var result = AnalysisEntityFactory.TryCreate(operation, out AnalysisEntity? flowCaptureReferenceEntity); Debug.Assert(result); - Debug.Assert(flowCaptureReferenceEntity.CaptureIdOpt != null); + Debug.Assert(flowCaptureReferenceEntity!.CaptureIdOpt != null); if (!HasPredicatedDataForEntity(targetAnalysisData, flowCaptureReferenceEntity)) { return; @@ -1494,8 +1498,8 @@ private void PerformPredicateAnalysisCore(IOperation operation, TAnalysisData ta break; } - IOperation leftOperand = null; - IOperation rightOperand = null; + IOperation? leftOperand = null; + IOperation? rightOperand = null; bool isReferenceEquality = false; if (invocation.Arguments.Length == 2 && invocation.TargetMethod.IsStaticObjectEqualsOrReferenceEquals()) @@ -1649,7 +1653,7 @@ protected virtual PredicateValueKind SetValueForIsNullComparisonOperator(IOperat throw new NotImplementedException(); } - protected virtual void StartTrackingPredicatedData(AnalysisEntity predicatedEntity, TAnalysisData truePredicateData, TAnalysisData falsePredicateData) + protected virtual void StartTrackingPredicatedData(AnalysisEntity predicatedEntity, TAnalysisData? truePredicateData, TAnalysisData? falsePredicateData) { Debug.Assert(PredicateAnalysis); throw new NotImplementedException(); @@ -1682,7 +1686,7 @@ protected virtual PredicateValueKind ApplyPredicatedDataForEntity(TAnalysisData throw new NotImplementedException(); } - protected virtual void ProcessThrowValue(IOperation thrownValueOpt) + protected virtual void ProcessThrowValue(IOperation? thrownValueOpt) { } @@ -1690,11 +1694,10 @@ protected virtual void ProcessThrowValue(IOperation thrownValueOpt) #region Helper methods to handle initialization/assignment operations protected abstract void SetAbstractValueForArrayElementInitializer(IArrayCreationOperation arrayCreation, ImmutableArray indices, ITypeSymbol elementType, IOperation initializer, TAbstractAnalysisValue value); - protected abstract void SetAbstractValueForAssignment(IOperation target, IOperation assignedValueOperation, TAbstractAnalysisValue assignedValue, bool mayBeAssignment = false); + protected abstract void SetAbstractValueForAssignment(IOperation target, IOperation? assignedValueOperation, TAbstractAnalysisValue assignedValue, bool mayBeAssignment = false); protected abstract void SetAbstractValueForTupleElementAssignment(AnalysisEntity tupleElementEntity, IOperation assignedValueOperation, TAbstractAnalysisValue assignedValue); private void HandleFlowCaptureReferenceAssignment(IFlowCaptureReferenceOperation flowCaptureReference, IOperation assignedValueOperation, TAbstractAnalysisValue assignedValue) { - Debug.Assert(flowCaptureReference != null); Debug.Assert(IsLValueFlowCaptureReference(flowCaptureReference)); var pointsToValue = GetPointsToAbstractValue(flowCaptureReference); @@ -1727,7 +1730,7 @@ private void HandleFlowCaptureReferenceAssignment(IFlowCaptureReferenceOperation bool HasUniqueCapturedEntity() { - AnalysisEntity uniqueAnalysisEntity = null; + AnalysisEntity? uniqueAnalysisEntity = null; foreach (var capturedOperation in pointsToValue.LValueCapturedOperations) { if (AnalysisEntityFactory.TryCreate(capturedOperation, out var entity)) @@ -1773,7 +1776,7 @@ private void ResetValueTypeInstanceAnalysisData(IOperation operation) Debug.Assert(HasPointsToAnalysisResult); Debug.Assert(operation.Type.HasValueCopySemantics()); - if (AnalysisEntityFactory.TryCreate(operation, out AnalysisEntity analysisEntity)) + if (AnalysisEntityFactory.TryCreate(operation, out var analysisEntity)) { if (analysisEntity.Type.HasValueCopySemantics()) { @@ -1805,9 +1808,9 @@ private void ResetReferenceTypeInstanceAnalysisData(IOperation operation) /// Reset all the instance analysis data if is true and is also true. /// If we are using or performing points to analysis, certain operations can invalidate all the analysis data off the containing instance. /// - private void ResetInstanceAnalysisData(IOperation operation) + private void ResetInstanceAnalysisData(IOperation? operation) { - if (operation?.Type == null || !HasPointsToAnalysisResult || !PessimisticAnalysis) + if (operation == null || operation.Type == null || !HasPointsToAnalysisResult || !PessimisticAnalysis) { return; } @@ -1846,7 +1849,7 @@ protected virtual void AssertValidAnalysisData(TAnalysisData analysisData) protected void ApplyMissingCurrentAnalysisDataForUnhandledExceptionData( DictionaryAnalysisData coreDataAtException, DictionaryAnalysisData coreCurrentAnalysisData, - Func predicateOpt) + Func? predicateOpt) { foreach (var (key, value) in coreCurrentAnalysisData) { @@ -1869,12 +1872,12 @@ protected virtual void AssertValidAnalysisData(TAnalysisData analysisData) /// protected virtual TAnalysisData GetInitialInterproceduralAnalysisData( IMethodSymbol invokedMethod, - (AnalysisEntity InstanceOpt, PointsToAbstractValue PointsToValue)? invocationInstanceOpt, + (AnalysisEntity? InstanceOpt, PointsToAbstractValue PointsToValue)? invocationInstanceOpt, (AnalysisEntity Instance, PointsToAbstractValue PointsToValue)? thisOrMeInstanceForCallerOpt, ImmutableDictionary> argumentValuesMap, - IDictionary pointsToValuesOpt, - IDictionary copyValuesOpt, - IDictionary valueContentValuesOpt, + IDictionary? pointsToValuesOpt, + IDictionary? copyValuesOpt, + IDictionary? valueContentValuesOpt, bool isLambdaOrLocalFunction, bool hasParameterWithDelegateType) => GetClonedCurrentAnalysisData(); @@ -1889,8 +1892,6 @@ protected virtual void ApplyInterproceduralAnalysisResult(TAnalysisData resultDa private void ApplyInterproceduralAnalysisDataForUnhandledThrowOperations(Dictionary interproceduralUnhandledThrowOperationsData) { - Debug.Assert(interproceduralUnhandledThrowOperationsData != null); - if (interproceduralUnhandledThrowOperationsData.Count == 0) { // All interprocedural exceptions were handled. @@ -1916,7 +1917,7 @@ void ApplyInterproceduralAnalysisDataForUnhandledThrowOperation(ThrownExceptionI ApplyMissingCurrentAnalysisDataForUnhandledExceptionData(analysisDataAtException, exceptionInfo); AssertValidAnalysisData(analysisDataAtException); - if (!AnalysisDataForUnhandledThrowOperations.TryGetValue(exceptionInfo, out var existingAnalysisDataAtException)) + if (!AnalysisDataForUnhandledThrowOperations!.TryGetValue(exceptionInfo, out var existingAnalysisDataAtException)) { AnalysisDataForUnhandledThrowOperations.Add(exceptionInfo, analysisDataAtException); } @@ -1931,7 +1932,7 @@ void ApplyInterproceduralAnalysisDataForUnhandledThrowOperation(ThrownExceptionI } } - protected bool TryGetInterproceduralAnalysisResult(IOperation operation, out TAnalysisResult analysisResult) + protected bool TryGetInterproceduralAnalysisResult(IOperation operation, [NotNullWhen(returnValue: true)] out TAnalysisResult? analysisResult) { if (_interproceduralResultsBuilder.TryGetValue(operation, out var computedAnalysisResult)) { @@ -1944,9 +1945,9 @@ protected bool TryGetInterproceduralAnalysisResult(IOperation operation, out TAn } private TAbstractAnalysisValue PerformInterproceduralAnalysis( - Func getCfg, + Func getCfg, IMethodSymbol invokedMethod, - IOperation instanceReceiver, + IOperation? instanceReceiver, ImmutableArray arguments, IOperation originalOperation, TAbstractAnalysisValue defaultValue, @@ -1990,7 +1991,7 @@ protected bool TryGetInterproceduralAnalysisResult(IOperation operation, out TAn } // Compute the dependent interprocedural PointsTo and Copy analysis results, if any. - var pointsToAnalysisResultOpt = (PointsToAnalysisResult)DataFlowAnalysisContext.PointsToAnalysisResultOpt?.TryGetInterproceduralResult(originalOperation); + var pointsToAnalysisResultOpt = (PointsToAnalysisResult?)DataFlowAnalysisContext.PointsToAnalysisResultOpt?.TryGetInterproceduralResult(originalOperation); var copyAnalysisResultOpt = DataFlowAnalysisContext.CopyAnalysisResultOpt?.TryGetInterproceduralResult(originalOperation); var valueContentAnalysisResultOpt = DataFlowAnalysisContext.ValueContentAnalysisResultOpt?.TryGetInterproceduralResult(originalOperation); @@ -2017,7 +2018,7 @@ protected bool TryGetInterproceduralAnalysisResult(IOperation operation, out TAn // Compute optional interprocedural analysis data for context-sensitive analysis. bool isContextSensitive = isLambdaOrLocalFunction || InterproceduralAnalysisKind == InterproceduralAnalysisKind.ContextSensitive; var interproceduralAnalysisData = isContextSensitive ? ComputeInterproceduralAnalysisData() : null; - TAnalysisResult analysisResult; + TAnalysisResult? analysisResult; try { @@ -2093,10 +2094,10 @@ protected bool TryGetInterproceduralAnalysisResult(IOperation operation, out TAn if (PredicateAnalysis) { - SetPredicateValueKind(originalOperation, CurrentAnalysisData, analysisResult.ReturnValueAndPredicateKindOpt.Value.PredicateValueKind); + SetPredicateValueKind(originalOperation, CurrentAnalysisData, analysisResult.ReturnValueAndPredicateKindOpt!.Value.PredicateValueKind); } - return analysisResult.ReturnValueAndPredicateKindOpt.Value.Value; + return analysisResult.ReturnValueAndPredicateKindOpt!.Value.Value; // Local functions TAbstractAnalysisValue ResetAnalysisDataAndReturnDefaultValue() @@ -2133,9 +2134,9 @@ void ResetAnalysisData() var invocationInstance = GetInvocationInstance(); var thisOrMeInstance = GetThisOrMeInstance(); var argumentValuesMap = GetArgumentValues(ref invocationInstance); - var pointsToValuesOpt = pointsToAnalysisResultOpt?[cfg.GetEntry()].Data; - var copyValuesOpt = copyAnalysisResultOpt?[cfg.GetEntry()].Data; - var valueContentValuesOpt = valueContentAnalysisResultOpt?[cfg.GetEntry()].Data; + var pointsToValuesOpt = pointsToAnalysisResultOpt?[cfg!.GetEntry()].Data; + var copyValuesOpt = copyAnalysisResultOpt?[cfg!.GetEntry()].Data; + var valueContentValuesOpt = valueContentAnalysisResultOpt?[cfg!.GetEntry()].Data; var initialAnalysisData = GetInitialInterproceduralAnalysisData(invokedMethod, invocationInstance, thisOrMeInstance, argumentValuesMap, pointsToValuesOpt, copyValuesOpt, valueContentValuesOpt, isLambdaOrLocalFunction, hasParameterWithDelegateType); @@ -2154,7 +2155,7 @@ void ResetAnalysisData() getInterproceduralCallStackForOwningSymbol: GetInterproceduralCallStackForOwningSymbol); // Local functions. - (AnalysisEntity, PointsToAbstractValue)? GetInvocationInstance() + (AnalysisEntity?, PointsToAbstractValue)? GetInvocationInstance() { if (isLambdaOrLocalFunction) { @@ -2194,7 +2195,7 @@ void ResetAnalysisData() (AnalysisEntity, PointsToAbstractValue)? GetThisOrMeInstance() => (AnalysisEntityFactory.ThisOrMeInstance, ThisOrMePointsToAbstractValue); - ImmutableDictionary> GetArgumentValues(ref (AnalysisEntity entity, PointsToAbstractValue pointsToValue)? invocationInstanceOpt) + ImmutableDictionary> GetArgumentValues(ref (AnalysisEntity? entity, PointsToAbstractValue pointsToValue)? invocationInstanceOpt) { var builder = PooledDictionary>.GetInstance(); var isExtensionMethodInvocationWithOneLessArgument = invokedMethod.IsExtensionMethod && arguments.Length == invokedMethod.Parameters.Length - 1; @@ -2272,7 +2273,7 @@ IParameterSymbol GetMappedParameterForArgument(IArgumentOperation argumentOperat return ImmutableDictionary.Empty; } - var capturedVariables = cfg.OriginalOperation.GetCaptures(invokedMethod); + var capturedVariables = cfg!.OriginalOperation.GetCaptures(invokedMethod); try { if (capturedVariables.Count == 0) @@ -2294,7 +2295,7 @@ IParameterSymbol GetMappedParameterForArgument(IArgumentOperation argumentOperat var success = AnalysisEntityFactory.TryCreateForSymbolDeclaration(capturedVariable, out var capturedEntity); Debug.Assert(success); - builder.Add(capturedVariable, capturedEntity.InstanceLocation); + builder.Add(capturedVariable, capturedEntity!.InstanceLocation); } return builder.ToImmutable(); @@ -2306,7 +2307,7 @@ IParameterSymbol GetMappedParameterForArgument(IArgumentOperation argumentOperat } } - AnalysisEntity GetAnalysisEntityForFlowCapture(IOperation operation) + AnalysisEntity? GetAnalysisEntityForFlowCapture(IOperation operation) { switch (operation.Kind) { @@ -2330,7 +2331,7 @@ AnalysisEntity GetAnalysisEntityForFlowCapture(IOperation operation) #region Visitor methods - protected TAbstractAnalysisValue VisitArray(IEnumerable operations, object argument) + protected TAbstractAnalysisValue VisitArray(IEnumerable operations, object? argument) { foreach (var operation in operations) { @@ -2340,7 +2341,7 @@ protected TAbstractAnalysisValue VisitArray(IEnumerable operations, return ValueDomain.UnknownOrMayBeValue; } - public override TAbstractAnalysisValue Visit(IOperation operation, object argument) + public override TAbstractAnalysisValue Visit(IOperation operation, object? argument) { if (operation != null) { @@ -2379,7 +2380,7 @@ public override TAbstractAnalysisValue Visit(IOperation operation, object argume return ValueDomain.UnknownOrMayBeValue; } - private TAbstractAnalysisValue VisitCore(IOperation operation, object argument) + private TAbstractAnalysisValue VisitCore(IOperation operation, object? argument) { if (operation.Kind == OperationKind.None) { @@ -2390,7 +2391,7 @@ private TAbstractAnalysisValue VisitCore(IOperation operation, object argument) try { StackGuard.EnsureSufficientExecutionStack(_recursionDepth); - return operation.Accept(this, argument); + return operation.Accept(this, argument!); } finally { @@ -2398,7 +2399,7 @@ private TAbstractAnalysisValue VisitCore(IOperation operation, object argument) } } - public override TAbstractAnalysisValue DefaultVisit(IOperation operation, object argument) + public override TAbstractAnalysisValue DefaultVisit(IOperation operation, object? argument) { return VisitArray(operation.Children, argument); } @@ -2408,7 +2409,7 @@ public override TAbstractAnalysisValue VisitSimpleAssignment(ISimpleAssignmentOp return VisitAssignmentOperation(operation, argument); } - public override TAbstractAnalysisValue VisitCompoundAssignment(ICompoundAssignmentOperation operation, object argument) + public override TAbstractAnalysisValue VisitCompoundAssignment(ICompoundAssignmentOperation operation, object? argument) { TAbstractAnalysisValue targetValue = Visit(operation.Target, argument); TAbstractAnalysisValue assignedValue = Visit(operation.Value, argument); @@ -2427,7 +2428,7 @@ public override TAbstractAnalysisValue VisitCompoundAssignment(ICompoundAssignme return ValueDomain.UnknownOrMayBeValue; } - public override TAbstractAnalysisValue VisitIncrementOrDecrement(IIncrementOrDecrementOperation operation, object argument) + public override TAbstractAnalysisValue VisitIncrementOrDecrement(IIncrementOrDecrementOperation operation, object? argument) { TAbstractAnalysisValue targetValue = Visit(operation.Target, argument); var value = ComputeValueForIncrementOrDecrementOperation(operation, targetValue); @@ -2565,9 +2566,9 @@ void PerformFlowCaptureReferencePredicateAnalysis() return; } - var result = AnalysisEntityFactory.TryCreate(operation, out AnalysisEntity flowCaptureReferenceEntity); + var result = AnalysisEntityFactory.TryCreate(operation, out var flowCaptureReferenceEntity); Debug.Assert(result); - Debug.Assert(flowCaptureReferenceEntity.CaptureIdOpt != null); + Debug.Assert(flowCaptureReferenceEntity!.CaptureIdOpt != null); if (!HasPredicatedDataForEntity(flowCaptureReferenceEntity)) { return; @@ -2602,7 +2603,7 @@ void PerformFlowCapturePredicateAnalysis() { Debug.Assert(flowCaptureEntity.CaptureIdOpt != null); TAnalysisData predicatedData = GetEmptyAnalysisData(); - TAnalysisData truePredicatedData, falsePredicatedData; + TAnalysisData? truePredicatedData, falsePredicatedData; if (constantValue) { truePredicatedData = predicatedData; @@ -2731,7 +2732,7 @@ public override TAbstractAnalysisValue VisitObjectCreation(IObjectCreationOperat var defaultValue = base.VisitObjectCreation(operation, argument); var method = operation.Constructor; - ControlFlowGraph getCfg() => GetInterproceduralControlFlowGraph(method); + ControlFlowGraph? getCfg() => GetInterproceduralControlFlowGraph(method); return PerformInterproceduralAnalysis(getCfg, method, instanceReceiver: null, operation.Arguments, operation, defaultValue, isLambdaOrLocalFunction: false); @@ -2840,13 +2841,13 @@ private TAbstractAnalysisValue VisitInvocation_NonLambdaOrDelegateOrLocalFunctio private TAbstractAnalysisValue VisitInvocation_LambdaOrDelegateOrLocalFunction( IInvocationOperation operation, object argument, - out HashSet<(IMethodSymbol method, IOperation instance)> resolvedMethodTargetsOpt) + out HashSet<(IMethodSymbol method, IOperation? instance)>? resolvedMethodTargetsOpt) { var value = base.VisitInvocation(operation, argument); var knownTargetInvocations = false; - HashSet<(IMethodSymbol method, IOperation instance)> methodTargetsOptBuilder = null; - HashSet lambdaTargetsOpt = null; + HashSet<(IMethodSymbol method, IOperation? instance)>? methodTargetsOptBuilder = null; + HashSet? lambdaTargetsOpt = null; if (HasPointsToAnalysisResult) { @@ -2895,11 +2896,11 @@ out HashSet<(IMethodSymbol method, IOperation instance)> resolvedMethodTargetsOp return value; // Local functions. - void AddMethodTarget(IMethodSymbol method, IOperation instance) + void AddMethodTarget(IMethodSymbol method, IOperation? instance) { Debug.Assert(knownTargetInvocations); - methodTargetsOptBuilder ??= new HashSet<(IMethodSymbol method, IOperation instance)>(); + methodTargetsOptBuilder ??= new HashSet<(IMethodSymbol method, IOperation? instance)>(); methodTargetsOptBuilder.Add((method, instance)); } @@ -2911,7 +2912,7 @@ void AddLambdaTarget(IFlowAnonymousFunctionOperation lambda) lambdaTargetsOpt.Add(lambda); } - bool HandleCreationOpt(IOperation creationOpt) + bool HandleCreationOpt(IOperation? creationOpt) { Debug.Assert(knownTargetInvocations); @@ -2957,14 +2958,14 @@ void AnalyzePossibleTargetInvocations() Debug.Assert(knownTargetInvocations); Debug.Assert(methodTargetsOptBuilder != null || lambdaTargetsOpt != null); - TAnalysisData mergedCurrentAnalysisData = null; + TAnalysisData? mergedCurrentAnalysisData = null; var first = true; var defaultValue = value; using var savedCurrentAnalysisData = GetClonedCurrentAnalysisData(); if (methodTargetsOptBuilder != null) { - foreach ((IMethodSymbol method, IOperation instance) in methodTargetsOptBuilder) + foreach (var (method, instance) in methodTargetsOptBuilder) { var oldMergedAnalysisData = mergedCurrentAnalysisData; mergedCurrentAnalysisData = AnalyzePossibleTargetInvocation( @@ -2973,7 +2974,7 @@ void AnalyzePossibleTargetInvocations() VisitInvocation_NonLambdaOrDelegateOrLocalFunction(method, instance, operation.Arguments, invokedAsDelegate: true, originalOperation: operation, defaultValue: defaultValue), inputAnalysisData: savedCurrentAnalysisData, - mergedAnalysisData: mergedCurrentAnalysisData, + mergedAnalysisData: mergedCurrentAnalysisData!, first: ref first); Debug.Assert(!ReferenceEquals(oldMergedAnalysisData, CurrentAnalysisData)); oldMergedAnalysisData?.Dispose(); @@ -2988,7 +2989,7 @@ void AnalyzePossibleTargetInvocations() mergedCurrentAnalysisData = AnalyzePossibleTargetInvocation( computeValueForInvocation: () => VisitInvocation_Lambda(lambda, operation.Arguments, operation, defaultValue), inputAnalysisData: savedCurrentAnalysisData, - mergedAnalysisData: mergedCurrentAnalysisData, + mergedAnalysisData: mergedCurrentAnalysisData!, first: ref first); Debug.Assert(!ReferenceEquals(oldMergedAnalysisData, CurrentAnalysisData)); oldMergedAnalysisData?.Dispose(); @@ -3032,26 +3033,26 @@ TAnalysisData AnalyzePossibleTargetInvocation(Func compu /// Abstract value of return value. public virtual TAbstractAnalysisValue VisitInvocation_NonLambdaOrDelegateOrLocalFunction( IMethodSymbol method, - IOperation visitedInstance, + IOperation? visitedInstance, ImmutableArray visitedArguments, bool invokedAsDelegate, IOperation originalOperation, TAbstractAnalysisValue defaultValue) { - ControlFlowGraph getCfg() => GetInterproceduralControlFlowGraph(method); + ControlFlowGraph? getCfg() => GetInterproceduralControlFlowGraph(method); return PerformInterproceduralAnalysis(getCfg, method, visitedInstance, visitedArguments, originalOperation, defaultValue, isLambdaOrLocalFunction: false); } - private ControlFlowGraph GetInterproceduralControlFlowGraph(IMethodSymbol method) + private ControlFlowGraph? GetInterproceduralControlFlowGraph(IMethodSymbol method) { if (DataFlowAnalysisContext.InterproceduralAnalysisDataOpt != null) { return DataFlowAnalysisContext.InterproceduralAnalysisDataOpt.GetInterproceduralControlFlowGraph(method); } - if (!_interproceduralMethodToCfgMapOpt.TryGetValue(method, out var cfg)) + if (!_interproceduralMethodToCfgMapOpt!.TryGetValue(method, out var cfg)) { var operation = method.GetTopmostOperationBlock(WellKnownTypeProvider.Compilation); cfg = operation?.GetEnclosingControlFlowGraph(); @@ -3061,7 +3062,7 @@ private ControlFlowGraph GetInterproceduralControlFlowGraph(IMethodSymbol method return cfg; } - private ImmutableStack GetInterproceduralCallStackForOwningSymbol(ISymbol forOwningSymbol) + private ImmutableStack? GetInterproceduralCallStackForOwningSymbol(ISymbol forOwningSymbol) { if (OwningSymbol.Equals(forOwningSymbol)) { @@ -3077,7 +3078,7 @@ private ImmutableStack GetInterproceduralCallStackForOwningSymbol(IS IOperation originalOperation, TAbstractAnalysisValue defaultValue) { - ControlFlowGraph getCfg() => DataFlowAnalysisContext.GetLocalFunctionControlFlowGraph(localFunction); + ControlFlowGraph? getCfg() => DataFlowAnalysisContext.GetLocalFunctionControlFlowGraph(localFunction); return PerformInterproceduralAnalysis(getCfg, localFunction, instanceReceiver: null, arguments: visitedArguments, originalOperation: originalOperation, defaultValue: defaultValue, isLambdaOrLocalFunction: true); } @@ -3088,7 +3089,7 @@ private ImmutableStack GetInterproceduralCallStackForOwningSymbol(IS IOperation originalOperation, TAbstractAnalysisValue defaultValue) { - ControlFlowGraph getCfg() => DataFlowAnalysisContext.GetAnonymousFunctionControlFlowGraph(lambda); + ControlFlowGraph? getCfg() => DataFlowAnalysisContext.GetAnonymousFunctionControlFlowGraph(lambda); return PerformInterproceduralAnalysis(getCfg, lambda.Symbol, instanceReceiver: null, arguments: visitedArguments, originalOperation: originalOperation, defaultValue: defaultValue, isLambdaOrLocalFunction: true); } @@ -3221,7 +3222,7 @@ public override TAbstractAnalysisValue VisitCaughtException(ICaughtExceptionOper return base.VisitCaughtException(operation, argument); } - private void MergeAnalysisDataFromUnhandledThrowOperations(ITypeSymbol caughtExceptionTypeOpt) + private void MergeAnalysisDataFromUnhandledThrowOperations(ITypeSymbol? caughtExceptionTypeOpt) { Debug.Assert(caughtExceptionTypeOpt != null || CurrentBasicBlock.IsFirstBlockOfFinally(out _)); @@ -3257,7 +3258,7 @@ bool ShouldHandlePendingThrow(ThrownExceptionInfo pendingThrow) { // Check if finally region is executed for pending throw. Debug.Assert(CurrentBasicBlock.IsFirstBlockOfFinally(out _)); - var tryFinallyRegion = CurrentBasicBlock.GetContainingRegionOfKind(ControlFlowRegionKind.TryAndFinally); + var tryFinallyRegion = CurrentBasicBlock.GetContainingRegionOfKind(ControlFlowRegionKind.TryAndFinally)!; var tryRegion = tryFinallyRegion.NestedRegions[0]; return tryRegion.FirstBlockOrdinal <= pendingThrow.BasicBlockOrdinal && tryRegion.LastBlockOrdinal >= pendingThrow.BasicBlockOrdinal; } @@ -3529,47 +3530,47 @@ public sealed override TAbstractAnalysisValue VisitLocalFunction(ILocalFunctionO /// /// for /// - protected INamedTypeSymbol ExceptionNamedType { get; } + protected INamedTypeSymbol? ExceptionNamedType { get; } /// /// for 'System.Diagnostics.Contracts.Contract' type. /> /// - protected INamedTypeSymbol ContractNamedType { get; } + protected INamedTypeSymbol? ContractNamedType { get; } /// /// for /// - protected INamedTypeSymbol IDisposableNamedType { get; } + protected INamedTypeSymbol? IDisposableNamedType { get; } /// /// for /// - protected INamedTypeSymbol TaskNamedType { get; } + protected INamedTypeSymbol? TaskNamedType { get; } /// /// for /// - protected INamedTypeSymbol GenericTaskNamedType { get; } + protected INamedTypeSymbol? GenericTaskNamedType { get; } /// /// for /// - protected INamedTypeSymbol MonitorNamedType { get; } + protected INamedTypeSymbol? MonitorNamedType { get; } /// /// for /// - protected INamedTypeSymbol InterlockedNamedType { get; } + protected INamedTypeSymbol? InterlockedNamedType { get; } /// /// for 'System.Runtime.Serialization.SerializationInfo' type /> /// - protected INamedTypeSymbol SerializationInfoNamedType { get; } + protected INamedTypeSymbol? SerializationInfoNamedType { get; } /// /// for /// - protected INamedTypeSymbol GenericIEquatableNamedType { get; } + protected INamedTypeSymbol? GenericIEquatableNamedType { get; } /// /// Set containing following named types, if not null: diff --git a/src/Utilities/FlowAnalysis/FlowAnalysis/Framework/DataFlow/DictionaryAnalysisData.cs b/src/Utilities/FlowAnalysis/FlowAnalysis/Framework/DataFlow/DictionaryAnalysisData.cs index 3e1209346d..b6509684ab 100644 --- a/src/Utilities/FlowAnalysis/FlowAnalysis/Framework/DataFlow/DictionaryAnalysisData.cs +++ b/src/Utilities/FlowAnalysis/FlowAnalysis/Framework/DataFlow/DictionaryAnalysisData.cs @@ -13,7 +13,7 @@ namespace Microsoft.CodeAnalysis.FlowAnalysis.DataFlow public sealed class DictionaryAnalysisData : AbstractAnalysisData, IDictionary { #pragma warning disable CA2213 // Disposable fields should be disposed - private PooledDictionary _coreAnalysisData; + private PooledDictionary? _coreAnalysisData; #pragma warning restore public DictionaryAnalysisData() @@ -37,12 +37,12 @@ public DictionaryAnalysisData(IDictionary initializer) get { Debug.Assert(!IsDisposed); - return _coreAnalysisData[key]; + return _coreAnalysisData![key]; } set { Debug.Assert(!IsDisposed); - _coreAnalysisData[key] = value; + _coreAnalysisData![key] = value; } } @@ -51,7 +51,7 @@ public ICollection Keys get { Debug.Assert(!IsDisposed); - return _coreAnalysisData.Keys; + return _coreAnalysisData!.Keys; } } @@ -61,7 +61,7 @@ public ICollection Values { // "Values" might be accessed during dispose. //Debug.Assert(!IsDisposed); - return _coreAnalysisData.Values; + return _coreAnalysisData!.Values; } } @@ -70,7 +70,7 @@ public int Count get { Debug.Assert(!IsDisposed); - return _coreAnalysisData.Count; + return _coreAnalysisData!.Count; } } @@ -79,56 +79,56 @@ public bool IsReadOnly get { Debug.Assert(!IsDisposed); - return ((IDictionary)_coreAnalysisData).IsReadOnly; + return ((IDictionary)_coreAnalysisData!).IsReadOnly; } } public void Add(TKey key, TValue value) { Debug.Assert(!IsDisposed); - _coreAnalysisData.Add(key, value); + _coreAnalysisData!.Add(key, value); } public void Add(KeyValuePair item) { Debug.Assert(!IsDisposed); - _coreAnalysisData.Add(item.Key, item.Value); + _coreAnalysisData!.Add(item.Key, item.Value); } public void Clear() { Debug.Assert(!IsDisposed); - _coreAnalysisData.Clear(); + _coreAnalysisData!.Clear(); } public bool Contains(KeyValuePair item) { Debug.Assert(!IsDisposed); - return ((IDictionary)_coreAnalysisData).Contains(item); + return ((IDictionary)_coreAnalysisData!).Contains(item); } public bool ContainsKey(TKey key) { Debug.Assert(!IsDisposed); - return _coreAnalysisData.ContainsKey(key); + return _coreAnalysisData!.ContainsKey(key); } public void CopyTo(KeyValuePair[] array, int arrayIndex) { Debug.Assert(!IsDisposed); - ((IDictionary)_coreAnalysisData).CopyTo(array, arrayIndex); + ((IDictionary)_coreAnalysisData!).CopyTo(array, arrayIndex); } public IEnumerator> GetEnumerator() { Debug.Assert(!IsDisposed); - return _coreAnalysisData.GetEnumerator(); + return _coreAnalysisData!.GetEnumerator(); } public bool Remove(TKey key) { Debug.Assert(!IsDisposed); - return _coreAnalysisData.Remove(key); + return _coreAnalysisData!.Remove(key); } public bool Remove(KeyValuePair item) @@ -140,13 +140,13 @@ public bool Remove(KeyValuePair item) public bool TryGetValue(TKey key, out TValue value) { Debug.Assert(!IsDisposed); - return _coreAnalysisData.TryGetValue(key, out value); + return _coreAnalysisData!.TryGetValue(key, out value); } IEnumerator IEnumerable.GetEnumerator() { Debug.Assert(!IsDisposed); - return _coreAnalysisData.GetEnumerator(); + return _coreAnalysisData!.GetEnumerator(); } protected override void Dispose(bool disposing) @@ -158,7 +158,7 @@ protected override void Dispose(bool disposing) if (disposing) { - _coreAnalysisData.Free(); + _coreAnalysisData!.Free(); _coreAnalysisData = null; } diff --git a/src/Utilities/FlowAnalysis/FlowAnalysis/Framework/DataFlow/IDataFlowAnalysisContext.cs b/src/Utilities/FlowAnalysis/FlowAnalysis/Framework/DataFlow/IDataFlowAnalysisContext.cs index a1ade116d0..db467326b7 100644 --- a/src/Utilities/FlowAnalysis/FlowAnalysis/Framework/DataFlow/IDataFlowAnalysisContext.cs +++ b/src/Utilities/FlowAnalysis/FlowAnalysis/Framework/DataFlow/IDataFlowAnalysisContext.cs @@ -10,7 +10,7 @@ public interface IDataFlowAnalysisContext { ControlFlowGraph ControlFlowGraph { get; } ISymbol OwningSymbol { get; } - ControlFlowGraph GetLocalFunctionControlFlowGraph(IMethodSymbol localFunction); - ControlFlowGraph GetAnonymousFunctionControlFlowGraph(IFlowAnonymousFunctionOperation lambda); + ControlFlowGraph? GetLocalFunctionControlFlowGraph(IMethodSymbol localFunction); + ControlFlowGraph? GetAnonymousFunctionControlFlowGraph(IFlowAnonymousFunctionOperation lambda); } } diff --git a/src/Utilities/FlowAnalysis/FlowAnalysis/Framework/DataFlow/IDataFlowAnalysisResult.cs b/src/Utilities/FlowAnalysis/FlowAnalysis/Framework/DataFlow/IDataFlowAnalysisResult.cs index 7029e09769..d92d0e0388 100644 --- a/src/Utilities/FlowAnalysis/FlowAnalysis/Framework/DataFlow/IDataFlowAnalysisResult.cs +++ b/src/Utilities/FlowAnalysis/FlowAnalysis/Framework/DataFlow/IDataFlowAnalysisResult.cs @@ -10,7 +10,7 @@ public interface IDataFlowAnalysisResult { ControlFlowGraph ControlFlowGraph { get; } (TAbstractAnalysisValue Value, PredicateValueKind PredicateValueKind)? ReturnValueAndPredicateKindOpt { get; } - object AnalysisDataForUnhandledThrowOperationsOpt { get; } - object TaskWrappedValuesMapOpt { get; } + object? AnalysisDataForUnhandledThrowOperationsOpt { get; } + object? TaskWrappedValuesMapOpt { get; } } } diff --git a/src/Utilities/FlowAnalysis/FlowAnalysis/Framework/DataFlow/InterproceduralAnalysisData.cs b/src/Utilities/FlowAnalysis/FlowAnalysis/Framework/DataFlow/InterproceduralAnalysisData.cs index 457c21170b..b595f8e08e 100644 --- a/src/Utilities/FlowAnalysis/FlowAnalysis/Framework/DataFlow/InterproceduralAnalysisData.cs +++ b/src/Utilities/FlowAnalysis/FlowAnalysis/Framework/DataFlow/InterproceduralAnalysisData.cs @@ -2,7 +2,6 @@ using System; using System.Collections.Immutable; -using System.Diagnostics; using Analyzer.Utilities; using Microsoft.CodeAnalysis.FlowAnalysis.DataFlow.CopyAnalysis; using Microsoft.CodeAnalysis.FlowAnalysis.DataFlow.PointsToAnalysis; @@ -26,7 +25,7 @@ public sealed class InterproceduralAnalysisData> argumentValuesMap, ImmutableDictionary capturedVariablesMap, @@ -34,20 +33,10 @@ public sealed class InterproceduralAnalysisData callStack, ImmutableHashSet methodsBeingAnalyzed, Func getCachedAbstractValueFromCaller, - Func getInterproceduralControlFlowGraph, - Func getAnalysisEntityForFlowCapture, - Func> getInterproceduralCallStackForOwningSymbol) + Func getInterproceduralControlFlowGraph, + Func getAnalysisEntityForFlowCapture, + Func?> getInterproceduralCallStackForOwningSymbol) { - Debug.Assert(initialAnalysisData != null); - Debug.Assert(argumentValuesMap != null); - Debug.Assert(addressSharedEntities != null); - Debug.Assert(callStack != null); - Debug.Assert(methodsBeingAnalyzed != null); - Debug.Assert(getCachedAbstractValueFromCaller != null); - Debug.Assert(getInterproceduralControlFlowGraph != null); - Debug.Assert(getAnalysisEntityForFlowCapture != null); - Debug.Assert(getInterproceduralCallStackForOwningSymbol != null); - InitialAnalysisData = initialAnalysisData; InvocationInstanceOpt = invocationInstanceOpt; ThisOrMeInstanceForCallerOpt = thisOrMeInstanceForCallerOpt; @@ -63,7 +52,7 @@ public sealed class InterproceduralAnalysisData> ArgumentValuesMap { get; } public ImmutableDictionary CapturedVariablesMap { get; } @@ -71,9 +60,9 @@ public sealed class InterproceduralAnalysisData CallStack { get; } public ImmutableHashSet MethodsBeingAnalyzed { get; } public Func GetCachedAbstractValueFromCaller { get; } - public Func GetInterproceduralControlFlowGraph { get; } - public Func GetAnalysisEntityForFlowCapture { get; } - public Func> GetInterproceduralCallStackForOwningSymbol { get; } + public Func GetInterproceduralControlFlowGraph { get; } + public Func GetAnalysisEntityForFlowCapture { get; } + public Func?> GetInterproceduralCallStackForOwningSymbol { get; } protected override void ComputeHashCodeParts(Action addPart) { @@ -88,7 +77,7 @@ protected override void ComputeHashCodeParts(Action addPart) } private static void AddHashCodeParts( - (AnalysisEntity InstanceOpt, PointsToAbstractValue PointsToValue)? instanceAndPointsToValueOpt, + (AnalysisEntity? InstanceOpt, PointsToAbstractValue PointsToValue)? instanceAndPointsToValueOpt, Action addPart) { if (instanceAndPointsToValueOpt.HasValue) diff --git a/src/Utilities/FlowAnalysis/FlowAnalysis/Framework/DataFlow/InterproceduralAnalysisPredicate.cs b/src/Utilities/FlowAnalysis/FlowAnalysis/Framework/DataFlow/InterproceduralAnalysisPredicate.cs index d0aeb0e789..1ccbded416 100644 --- a/src/Utilities/FlowAnalysis/FlowAnalysis/Framework/DataFlow/InterproceduralAnalysisPredicate.cs +++ b/src/Utilities/FlowAnalysis/FlowAnalysis/Framework/DataFlow/InterproceduralAnalysisPredicate.cs @@ -9,14 +9,14 @@ namespace Microsoft.CodeAnalysis.FlowAnalysis.DataFlow /// public sealed class InterproceduralAnalysisPredicate { - private readonly Func _skipAnalysisForInvokedMethodPredicateOpt; - private readonly Func _skipAnalysisForInvokedLambdaOrLocalFunctionPredicateOpt; - private readonly Func _skipAnalysisForInvokedContextPredicateOpt; + private readonly Func? _skipAnalysisForInvokedMethodPredicateOpt; + private readonly Func? _skipAnalysisForInvokedLambdaOrLocalFunctionPredicateOpt; + private readonly Func? _skipAnalysisForInvokedContextPredicateOpt; public InterproceduralAnalysisPredicate( - Func skipAnalysisForInvokedMethodPredicateOpt, - Func skipAnalysisForInvokedLambdaOrLocalFunctionPredicateOpt, - Func skipAnalysisForInvokedContextPredicateOpt) + Func? skipAnalysisForInvokedMethodPredicateOpt, + Func? skipAnalysisForInvokedLambdaOrLocalFunctionPredicateOpt, + Func? skipAnalysisForInvokedContextPredicateOpt) { if (skipAnalysisForInvokedMethodPredicateOpt == null && skipAnalysisForInvokedLambdaOrLocalFunctionPredicateOpt == null && diff --git a/src/Utilities/FlowAnalysis/FlowAnalysis/Framework/DataFlow/MapAbstractDomain.cs b/src/Utilities/FlowAnalysis/FlowAnalysis/Framework/DataFlow/MapAbstractDomain.cs index c644e06fbd..2099d89645 100644 --- a/src/Utilities/FlowAnalysis/FlowAnalysis/Framework/DataFlow/MapAbstractDomain.cs +++ b/src/Utilities/FlowAnalysis/FlowAnalysis/Framework/DataFlow/MapAbstractDomain.cs @@ -35,9 +35,6 @@ public sealed override bool Equals(DictionaryAnalysisData value1, private int Compare(DictionaryAnalysisData oldValue, DictionaryAnalysisData newValue, bool assertMonotonicity) { - Debug.Assert(oldValue != null); - Debug.Assert(newValue != null); - if (ReferenceEquals(oldValue, newValue)) { return 0; @@ -96,9 +93,6 @@ private static void FireNonMonotonicAssertIfNeeded(bool assertMonotonicity) public override DictionaryAnalysisData Merge(DictionaryAnalysisData value1, DictionaryAnalysisData value2) { - Debug.Assert(value1 != null); - Debug.Assert(value2 != null); - var result = new DictionaryAnalysisData(value1); foreach (var entry in value2) { diff --git a/src/Utilities/FlowAnalysis/FlowAnalysis/Framework/DataFlow/PerEntityPredicatedAnalysisData.cs b/src/Utilities/FlowAnalysis/FlowAnalysis/Framework/DataFlow/PerEntityPredicatedAnalysisData.cs index 3245001c03..036114072b 100644 --- a/src/Utilities/FlowAnalysis/FlowAnalysis/Framework/DataFlow/PerEntityPredicatedAnalysisData.cs +++ b/src/Utilities/FlowAnalysis/FlowAnalysis/Framework/DataFlow/PerEntityPredicatedAnalysisData.cs @@ -14,7 +14,7 @@ public abstract partial class PredicatedAnalysisData /// protected sealed class PerEntityPredicatedAnalysisData : IDisposable { - public PerEntityPredicatedAnalysisData(DictionaryAnalysisData truePredicatedData, DictionaryAnalysisData falsePredicatedData) + public PerEntityPredicatedAnalysisData(DictionaryAnalysisData? truePredicatedData, DictionaryAnalysisData? falsePredicatedData) { Debug.Assert(truePredicatedData != null || falsePredicatedData != null); @@ -38,13 +38,13 @@ public PerEntityPredicatedAnalysisData(PerEntityPredicatedAnalysisData fromData) /// Analysis data for true value of the corresponding on which this data is predicated. /// null value indicates the corresponding can never be true. /// - public DictionaryAnalysisData TruePredicatedData { get; private set; } + public DictionaryAnalysisData? TruePredicatedData { get; private set; } /// /// Analysis data for false value of the corresponding on which this data is predicated. /// null value indicates the corresponding can never be false. /// - public DictionaryAnalysisData FalsePredicatedData { get; private set; } + public DictionaryAnalysisData? FalsePredicatedData { get; private set; } public void Dispose() { diff --git a/src/Utilities/FlowAnalysis/FlowAnalysis/Framework/DataFlow/PredicatedAnalysisData.cs b/src/Utilities/FlowAnalysis/FlowAnalysis/Framework/DataFlow/PredicatedAnalysisData.cs index 87fbd4dea3..aafb0970d6 100644 --- a/src/Utilities/FlowAnalysis/FlowAnalysis/Framework/DataFlow/PredicatedAnalysisData.cs +++ b/src/Utilities/FlowAnalysis/FlowAnalysis/Framework/DataFlow/PredicatedAnalysisData.cs @@ -21,7 +21,7 @@ namespace Microsoft.CodeAnalysis.FlowAnalysis.DataFlow public abstract partial class PredicatedAnalysisData : AbstractAnalysisData { #pragma warning disable CA2213 // Disposable fields should be disposed - https://github.com/dotnet/roslyn-analyzers/issues/2182 - private DictionaryAnalysisData _lazyPredicateDataMap; + private DictionaryAnalysisData? _lazyPredicateDataMap; #pragma warning restore CA2213 // Disposable fields should be disposed protected PredicatedAnalysisData() @@ -85,7 +85,7 @@ private void EnsurePredicatedData() _lazyPredicateDataMap ??= new DictionaryAnalysisData(); } - protected void StartTrackingPredicatedData(AnalysisEntity predicatedEntity, DictionaryAnalysisData truePredicatedData, DictionaryAnalysisData falsePredicatedData) + protected void StartTrackingPredicatedData(AnalysisEntity predicatedEntity, DictionaryAnalysisData? truePredicatedData, DictionaryAnalysisData? falsePredicatedData) { Debug.Assert(predicatedEntity.IsCandidatePredicateEntity()); Debug.Assert(predicatedEntity.CaptureIdOpt != null, "Currently we only support predicated data tracking for flow captures"); @@ -93,7 +93,7 @@ protected void StartTrackingPredicatedData(AnalysisEntity predicatedEntity, Dict AssertValidAnalysisData(); EnsurePredicatedData(); - _lazyPredicateDataMap[predicatedEntity] = new PerEntityPredicatedAnalysisData(truePredicatedData, falsePredicatedData); + _lazyPredicateDataMap![predicatedEntity] = new PerEntityPredicatedAnalysisData(truePredicatedData, falsePredicatedData); AssertValidAnalysisData(); } @@ -104,7 +104,7 @@ public void StopTrackingPredicatedData(AnalysisEntity predicatedEntity) Debug.Assert(predicatedEntity.CaptureIdOpt != null, "Currently we only support predicated data tracking for flow captures"); AssertValidAnalysisData(); - if (_lazyPredicateDataMap.TryGetValue(predicatedEntity, out var perEntityPredicatedAnalysisData)) + if (_lazyPredicateDataMap!.TryGetValue(predicatedEntity, out var perEntityPredicatedAnalysisData)) { perEntityPredicatedAnalysisData.Dispose(); } @@ -119,7 +119,7 @@ public void StopTrackingPredicatedData(AnalysisEntity predicatedEntity) } public bool HasPredicatedDataForEntity(AnalysisEntity predicatedEntity) - => HasPredicatedData && _lazyPredicateDataMap.ContainsKey(predicatedEntity); + => HasPredicatedData && _lazyPredicateDataMap!.ContainsKey(predicatedEntity); public void TransferPredicatedData(AnalysisEntity fromEntity, AnalysisEntity toEntity) { @@ -128,7 +128,7 @@ public void TransferPredicatedData(AnalysisEntity fromEntity, AnalysisEntity toE Debug.Assert(toEntity.CaptureIdOpt != null, "Currently we only support predicated data tracking for flow captures"); AssertValidAnalysisData(); - if (_lazyPredicateDataMap.TryGetValue(fromEntity, out var fromEntityPredicatedData)) + if (_lazyPredicateDataMap!.TryGetValue(fromEntity, out var fromEntityPredicatedData)) { _lazyPredicateDataMap[toEntity] = new PerEntityPredicatedAnalysisData(fromEntityPredicatedData); } @@ -141,7 +141,7 @@ protected PredicateValueKind ApplyPredicatedDataForEntity(DictionaryAnalysisData Debug.Assert(HasPredicatedDataForEntity(predicatedEntity)); AssertValidAnalysisData(); - var perEntityPredicateData = _lazyPredicateDataMap[predicatedEntity]; + var perEntityPredicateData = _lazyPredicateDataMap![predicatedEntity]; var predicatedDataToApply = trueData ? perEntityPredicateData.TruePredicatedData : perEntityPredicateData.FalsePredicatedData; if (predicatedDataToApply == null) { @@ -160,9 +160,6 @@ protected PredicateValueKind ApplyPredicatedDataForEntity(DictionaryAnalysisData protected virtual void ApplyPredicatedData(DictionaryAnalysisData coreAnalysisData, DictionaryAnalysisData predicatedData) { - Debug.Assert(coreAnalysisData != null); - Debug.Assert(predicatedData != null); - foreach (var kvp in predicatedData) { coreAnalysisData[kvp.Key] = kvp.Value; @@ -174,7 +171,7 @@ protected void RemoveEntriesInPredicatedData(TKey key) Debug.Assert(HasPredicatedData); AssertValidAnalysisData(); - foreach (var kvp in _lazyPredicateDataMap) + foreach (var kvp in _lazyPredicateDataMap!) { if (kvp.Value.TruePredicatedData != null) { @@ -195,7 +192,7 @@ protected virtual void RemoveEntryInPredicatedData(TKey key, DictionaryAnalysisD predicatedData.Remove(key); } - private static DictionaryAnalysisData Clone(DictionaryAnalysisData fromData) + private static DictionaryAnalysisData? Clone(DictionaryAnalysisData? fromData) { if (fromData == null) { @@ -211,17 +208,14 @@ protected virtual void RemoveEntryInPredicatedData(TKey key, DictionaryAnalysisD return clonedMap; } - private static DictionaryAnalysisData Merge( - DictionaryAnalysisData predicatedData1, - DictionaryAnalysisData predicatedData2, + private static DictionaryAnalysisData? Merge( + DictionaryAnalysisData? predicatedData1, + DictionaryAnalysisData? predicatedData2, DictionaryAnalysisData coreAnalysisData1, DictionaryAnalysisData coreAnalysisData2, MapAbstractDomain coreDataAnalysisDomain, Action, DictionaryAnalysisData> applyPredicatedData) { - Debug.Assert(coreAnalysisData1 != null); - Debug.Assert(coreAnalysisData2 != null); - if (predicatedData1 == null) { if (predicatedData2 == null) @@ -245,9 +239,6 @@ protected virtual void RemoveEntryInPredicatedData(TKey key, DictionaryAnalysisD DictionaryAnalysisData coreAnalysisDataForOtherBranch, MapAbstractDomain coreDataAnalysisDomain) { - Debug.Assert(predicatedData != null); - Debug.Assert(coreAnalysisDataForOtherBranch != null); - var result = new DictionaryAnalysisData(); foreach (var kvp in predicatedData) { @@ -260,8 +251,8 @@ protected virtual void RemoveEntryInPredicatedData(TKey key, DictionaryAnalysisD return result; } - private static DictionaryAnalysisData MergeForPredicatedDataInOneBranch( - DictionaryAnalysisData predicatedData, + private static DictionaryAnalysisData? MergeForPredicatedDataInOneBranch( + DictionaryAnalysisData? predicatedData, DictionaryAnalysisData coreAnalysisDataForOtherBranch, MapAbstractDomain coreDataAnalysisDomain) { @@ -281,16 +272,11 @@ protected virtual void RemoveEntryInPredicatedData(TKey key, DictionaryAnalysisD MapAbstractDomain coreDataAnalysisDomain, Action, DictionaryAnalysisData> applyPredicatedData) { - Debug.Assert(predicatedData1 != null); - Debug.Assert(predicatedData2 != null); - Debug.Assert(coreAnalysisData1 != null); - Debug.Assert(coreAnalysisData2 != null); - var result = new DictionaryAnalysisData(); foreach (var kvp in predicatedData1) { - DictionaryAnalysisData resultTruePredicatedData; - DictionaryAnalysisData resultFalsePredicatedData; + DictionaryAnalysisData? resultTruePredicatedData; + DictionaryAnalysisData? resultFalsePredicatedData; if (!predicatedData2.TryGetValue(kvp.Key, out var value2)) { // Data predicated by the analysis entity present in only one branch. @@ -313,7 +299,7 @@ protected virtual void RemoveEntryInPredicatedData(TKey key, DictionaryAnalysisD foreach (var kvp in predicatedData2) { - if (!predicatedData1.TryGetValue(kvp.Key, out var value2)) + if (!predicatedData1.TryGetValue(kvp.Key, out _)) { // Data predicated by the analysis entity present in only one branch. // We should merge with the core non-predicate data in other branch. @@ -327,9 +313,9 @@ protected virtual void RemoveEntryInPredicatedData(TKey key, DictionaryAnalysisD return result; } - private static DictionaryAnalysisData Merge( - DictionaryAnalysisData predicateTrueOrFalseData1, - DictionaryAnalysisData predicateTrueOrFalseData2, + private static DictionaryAnalysisData? Merge( + DictionaryAnalysisData? predicateTrueOrFalseData1, + DictionaryAnalysisData? predicateTrueOrFalseData2, DictionaryAnalysisData coreAnalysisData1, DictionaryAnalysisData coreAnalysisData2, MapAbstractDomain coreDataAnalysisDomain, @@ -357,9 +343,6 @@ protected virtual void RemoveEntryInPredicatedData(TKey key, DictionaryAnalysisD DictionaryAnalysisData predicateTrueOrFalseData, Action, DictionaryAnalysisData> applyPredicatedData) { - Debug.Assert(predicateTrueOrFalseData != null); - Debug.Assert(coreAnalysisData != null); - var result = new DictionaryAnalysisData(coreAnalysisData); applyPredicatedData(result, predicateTrueOrFalseData); return result; @@ -367,8 +350,6 @@ protected virtual void RemoveEntryInPredicatedData(TKey key, DictionaryAnalysisD protected int BaseCompareHelper(PredicatedAnalysisData newData) { - Debug.Assert(newData != null); - if (!IsReachableBlockData && newData.IsReachableBlockData) { return -1; @@ -420,7 +401,7 @@ protected bool Equals(PredicatedAnalysisData other) return true; } - protected static bool EqualsHelper(DictionaryAnalysisData dict1, DictionaryAnalysisData dict2) + protected static bool EqualsHelper(DictionaryAnalysisData? dict1, DictionaryAnalysisData? dict2) { if (dict1 == null) { @@ -459,7 +440,7 @@ protected void AssertValidPredicatedAnalysisData(Action @@ -25,9 +23,6 @@ public PredicatedAnalysisDataDomain(MapAbstractDomain co public override TAnalysisData Merge(TAnalysisData value1, TAnalysisData value2) { - Debug.Assert(value1 != null); - Debug.Assert(value2 != null); - AnalysisEntityBasedPredicateAnalysisData result; if (ReferenceEquals(value1, value2)) { diff --git a/src/Utilities/FlowAnalysis/FlowAnalysis/Framework/DataFlow/SetAbstractDomain.cs b/src/Utilities/FlowAnalysis/FlowAnalysis/Framework/DataFlow/SetAbstractDomain.cs index b9067d78ba..a7f8084fa6 100644 --- a/src/Utilities/FlowAnalysis/FlowAnalysis/Framework/DataFlow/SetAbstractDomain.cs +++ b/src/Utilities/FlowAnalysis/FlowAnalysis/Framework/DataFlow/SetAbstractDomain.cs @@ -1,7 +1,6 @@ // Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System.Collections.Immutable; -using System.Diagnostics; #pragma warning disable CA1000 // Do not declare static members on generic types @@ -17,9 +16,6 @@ public class SetAbstractDomain : AbstractDomain> public override int Compare(ImmutableHashSet oldValue, ImmutableHashSet newValue, bool assertMonotonicity) { - Debug.Assert(oldValue != null); - Debug.Assert(newValue != null); - if (ReferenceEquals(oldValue, newValue)) { return 0; @@ -56,9 +52,6 @@ public override int Compare(ImmutableHashSet oldValue, ImmutableHashSet ne private static ImmutableHashSet MergeOrIntersect(ImmutableHashSet value1, ImmutableHashSet value2, bool merge) { - Debug.Assert(value1 != null); - Debug.Assert(value2 != null); - if (value1.IsEmpty) { return value2; diff --git a/src/Utilities/FlowAnalysis/FlowAnalysis/Framework/DataFlow/ThrownExceptionInfo.cs b/src/Utilities/FlowAnalysis/FlowAnalysis/Framework/DataFlow/ThrownExceptionInfo.cs index c228de4e79..c66ce35655 100644 --- a/src/Utilities/FlowAnalysis/FlowAnalysis/Framework/DataFlow/ThrownExceptionInfo.cs +++ b/src/Utilities/FlowAnalysis/FlowAnalysis/Framework/DataFlow/ThrownExceptionInfo.cs @@ -14,10 +14,9 @@ public sealed class ThrownExceptionInfo : IEquatable private ThrownExceptionInfo( BasicBlock block, INamedTypeSymbol exceptionType, - ImmutableStack interproceduralCallStackOpt, + ImmutableStack? interproceduralCallStackOpt, bool isDefaultExceptionForExceptionsPathAnalysis) { - block = block ?? throw new ArgumentNullException(nameof(block)); BasicBlockOrdinal = block.Ordinal; HandlingCatchRegionOpt = GetHandlerRegion(block, exceptionType); ContainingFinallyRegionOpt = block.GetContainingRegionOfKind(ControlFlowRegionKind.Finally); @@ -26,19 +25,19 @@ public sealed class ThrownExceptionInfo : IEquatable IsDefaultExceptionForExceptionsPathAnalysis = isDefaultExceptionForExceptionsPathAnalysis; } - internal static ThrownExceptionInfo Create(BasicBlock block, INamedTypeSymbol exceptionType, ImmutableStack interproceduralCallStackOpt) + internal static ThrownExceptionInfo Create(BasicBlock block, INamedTypeSymbol exceptionType, ImmutableStack? interproceduralCallStackOpt) { return new ThrownExceptionInfo(block, exceptionType, interproceduralCallStackOpt, isDefaultExceptionForExceptionsPathAnalysis: false); } - internal static ThrownExceptionInfo CreateDefaultInfoForExceptionsPathAnalysis(BasicBlock block, WellKnownTypeProvider wellKnownTypeProvider, ImmutableStack interproceduralCallStackOpt) + internal static ThrownExceptionInfo CreateDefaultInfoForExceptionsPathAnalysis(BasicBlock block, WellKnownTypeProvider wellKnownTypeProvider, ImmutableStack? interproceduralCallStackOpt) { var exceptionNamedType = wellKnownTypeProvider.GetOrCreateTypeByMetadataName(WellKnownTypeNames.SystemException); Debug.Assert(exceptionNamedType != null); - return new ThrownExceptionInfo(block, exceptionNamedType, interproceduralCallStackOpt, isDefaultExceptionForExceptionsPathAnalysis: true); + return new ThrownExceptionInfo(block, exceptionNamedType!, interproceduralCallStackOpt, isDefaultExceptionForExceptionsPathAnalysis: true); } - private static ControlFlowRegion GetHandlerRegion(BasicBlock block, INamedTypeSymbol exceptionType) + private static ControlFlowRegion? GetHandlerRegion(BasicBlock block, INamedTypeSymbol exceptionType) { var enclosingRegion = block.EnclosingRegion; while (enclosingRegion != null) @@ -64,7 +63,7 @@ private static ControlFlowRegion GetHandlerRegion(BasicBlock block, INamedTypeSy return null; } - internal ThrownExceptionInfo With(BasicBlock block, ImmutableStack interproceduralCallStackOpt) + internal ThrownExceptionInfo With(BasicBlock block, ImmutableStack? interproceduralCallStackOpt) { Debug.Assert(interproceduralCallStackOpt != InterproceduralCallStack); return new ThrownExceptionInfo(block, ExceptionType, interproceduralCallStackOpt, IsDefaultExceptionForExceptionsPathAnalysis); @@ -78,18 +77,18 @@ internal ThrownExceptionInfo With(BasicBlock block, ImmutableStack i /// /// Optional catch handler that handles this exception. /// - internal ControlFlowRegion HandlingCatchRegionOpt { get; } + internal ControlFlowRegion? HandlingCatchRegionOpt { get; } /// /// If the exception happens within a finally region, this points to that finally. /// - internal ControlFlowRegion ContainingFinallyRegionOpt { get; } + internal ControlFlowRegion? ContainingFinallyRegionOpt { get; } internal INamedTypeSymbol ExceptionType { get; } internal ImmutableStack InterproceduralCallStack { get; } internal bool IsDefaultExceptionForExceptionsPathAnalysis { get; } - public bool Equals(ThrownExceptionInfo other) + public bool Equals(ThrownExceptionInfo? other) { return other != null && BasicBlockOrdinal == other.BasicBlockOrdinal && @@ -102,6 +101,7 @@ public bool Equals(ThrownExceptionInfo other) public override bool Equals(object obj) => Equals(obj as ThrownExceptionInfo); + public override int GetHashCode() => HashUtilities.Combine(InterproceduralCallStack, HashUtilities.Combine(BasicBlockOrdinal.GetHashCodeOrDefault(), diff --git a/src/Utilities/FlowAnalysis/SingleThreadedConcurrentDictionary.cs b/src/Utilities/FlowAnalysis/SingleThreadedConcurrentDictionary.cs index 87819b32d5..3dd82b54ff 100644 --- a/src/Utilities/FlowAnalysis/SingleThreadedConcurrentDictionary.cs +++ b/src/Utilities/FlowAnalysis/SingleThreadedConcurrentDictionary.cs @@ -13,6 +13,7 @@ namespace Analyzer.Utilities /// threads simultaneously request the same key. #pragma warning disable CA1812 // SingleThreadedConcurrentDictionary is too used. internal class SingleThreadedConcurrentDictionary + where TValue : class #pragma warning restore CA1812 { /// @@ -20,7 +21,7 @@ internal class SingleThreadedConcurrentDictionary /// private class Entry { - public TValue Value { get; set; } + public TValue? Value { get; set; } } /// @@ -34,7 +35,7 @@ private class Entry /// Key to add. /// Function to be invoked to generate the key, if necessary. /// Value of the key, which will either be the existing value, or new value if the key was not in the dictionary. - public TValue GetOrAdd(TKey key, Func valueFactory) + public TValue? GetOrAdd(TKey key, Func valueFactory) { if (key == null) { From b424db69f50dbf6134e30173b681f24a99940d44 Mon Sep 17 00:00:00 2001 From: Manish Vasani Date: Thu, 7 Nov 2019 11:58:52 -0800 Subject: [PATCH 03/28] Restrict nullable enable to only shipping projects for now. --- Directory.Build.props | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Directory.Build.props b/Directory.Build.props index 9eb903b60a..27fc261503 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -11,7 +11,9 @@ 8 16 - enable + + + enable From 6398f5f118cb00cfec598250c7754c7a3fc3b9fa Mon Sep 17 00:00:00 2001 From: Manish Vasani Date: Thu, 7 Nov 2019 11:59:07 -0800 Subject: [PATCH 04/28] Nullable annotations in Metrics project --- src/Tools/Metrics/Program.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Tools/Metrics/Program.cs b/src/Tools/Metrics/Program.cs index 8d9e358fa6..eeba967d7c 100644 --- a/src/Tools/Metrics/Program.cs +++ b/src/Tools/Metrics/Program.cs @@ -39,7 +39,7 @@ public static int Main(string[] args) private static async Task RunAsync(string[] args, CancellationToken cancellationToken) { var projectsOrSolutions = new List(); - string outputFile = null; + string? outputFile = null; bool quiet = false; if (args.Length == 0) @@ -219,7 +219,7 @@ static ErrorCode invalidOutputFile(string path) ErrorCode writeOutput() { - XmlTextWriter metricFile = null; + XmlTextWriter? metricFile = null; try { // Create the writer From 05bdcfa99cf7bdbe9af09705ad2751fa34025508 Mon Sep 17 00:00:00 2001 From: Manish Vasani Date: Thu, 7 Nov 2019 12:22:05 -0800 Subject: [PATCH 05/28] Nullable annotations for Roslyn.Diagnostics.Analyzers --- Directory.Build.props | 2 +- .../CSharpSpecializedEnumerableCreationAnalyzer.cs | 1 - ...olDeclaredEventMustBeGeneratedForSourceSymbols.cs | 6 +++--- .../DoNotMixAttributesFromDifferentVersionsOfMEF.cs | 2 +- .../ExportedPartsShouldHaveImportingConstructor.cs | 8 ++++---- ...sShouldHaveImportingConstructorCodeFixProvider.cs | 6 +++--- .../Core/ImportingConstructorShouldBeObsolete.cs | 4 ++-- ...tingConstructorShouldBeObsoleteCodeFixProvider.cs | 2 +- .../Core/SpecializedEnumerableCreationAnalyzer.cs | 6 +++--- ...olDeclaredEventMustBeGeneratedForSourceSymbols.cs | 12 ++++++------ .../Core/TestExportsShouldNotBeDiscoverable.cs | 2 +- ...tExportsShouldNotBeDiscoverableCodeFixProvider.cs | 4 ++-- src/Test.Utilities/AdditionalMetadataReferences.cs | 6 +++--- src/Test.Utilities/DiagnosticAnalyzerTestBase.cs | 3 +++ .../DiagnosticAnalyzerTests.Extensions.cs | 4 ++++ src/Test.Utilities/DiagnosticExtensions.cs | 2 +- src/Test.Utilities/EnsureEnglishUICulture.cs | 6 +++--- src/Test.Utilities/TestAdditionalDocument.cs | 4 ++-- src/Utilities/Compiler/Analyzer.Utilities.projitems | 6 ++++++ .../Compiler/Extensions/ITypeSymbolExtensions.cs | 6 +++--- 20 files changed, 52 insertions(+), 40 deletions(-) diff --git a/Directory.Build.props b/Directory.Build.props index 27fc261503..df5301e19e 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -13,7 +13,7 @@ 16 - enable + enable diff --git a/src/Roslyn.Diagnostics.Analyzers/CSharp/CSharpSpecializedEnumerableCreationAnalyzer.cs b/src/Roslyn.Diagnostics.Analyzers/CSharp/CSharpSpecializedEnumerableCreationAnalyzer.cs index b14f8966f3..a0d546262a 100644 --- a/src/Roslyn.Diagnostics.Analyzers/CSharp/CSharpSpecializedEnumerableCreationAnalyzer.cs +++ b/src/Roslyn.Diagnostics.Analyzers/CSharp/CSharpSpecializedEnumerableCreationAnalyzer.cs @@ -84,7 +84,6 @@ private static void AnalyzeArrayCreationExpression(ArrayCreationExpressionSyntax if (arrayType.RankSpecifiers[0].ChildNodes() .FirstOrDefault(n => n.Kind() == SyntaxKind.NumericLiteralExpression) is LiteralExpressionSyntax literalRankSpecifier) { - Debug.Assert(literalRankSpecifier.Token.Value != null); AnalyzeArrayLength((int)literalRankSpecifier.Token.Value, arrayCreationExpression, addDiagnostic); return; } diff --git a/src/Roslyn.Diagnostics.Analyzers/CSharp/CSharpSymbolDeclaredEventMustBeGeneratedForSourceSymbols.cs b/src/Roslyn.Diagnostics.Analyzers/CSharp/CSharpSymbolDeclaredEventMustBeGeneratedForSourceSymbols.cs index 325474f17c..15fe7b01f6 100644 --- a/src/Roslyn.Diagnostics.Analyzers/CSharp/CSharpSymbolDeclaredEventMustBeGeneratedForSourceSymbols.cs +++ b/src/Roslyn.Diagnostics.Analyzers/CSharp/CSharpSymbolDeclaredEventMustBeGeneratedForSourceSymbols.cs @@ -22,9 +22,9 @@ public class CSharpSymbolDeclaredEventAnalyzer : SymbolDeclaredEventAnalyzer SymbolTypesWithExpectedSymbolDeclaredEvent => s_symbolTypesWithExpectedSymbolDeclaredEvent; - protected override SyntaxNode GetFirstArgumentOfInvocation(SyntaxNode node) + protected override SyntaxNode? GetFirstArgumentOfInvocation(SyntaxNode node) { var invocation = (InvocationExpressionSyntax)node; if (invocation.ArgumentList != null) diff --git a/src/Roslyn.Diagnostics.Analyzers/Core/DoNotMixAttributesFromDifferentVersionsOfMEF.cs b/src/Roslyn.Diagnostics.Analyzers/Core/DoNotMixAttributesFromDifferentVersionsOfMEF.cs index 8db7088fa6..d4e706b79e 100644 --- a/src/Roslyn.Diagnostics.Analyzers/Core/DoNotMixAttributesFromDifferentVersionsOfMEF.cs +++ b/src/Roslyn.Diagnostics.Analyzers/Core/DoNotMixAttributesFromDifferentVersionsOfMEF.cs @@ -56,7 +56,7 @@ public override void Initialize(AnalysisContext context) }); } - private static void AnalyzeSymbol(SymbolAnalysisContext symbolContext, IEnumerable exportAttributes, INamedTypeSymbol attributeUsageAttribute) + private static void AnalyzeSymbol(SymbolAnalysisContext symbolContext, IEnumerable exportAttributes, INamedTypeSymbol? attributeUsageAttribute) { var namedType = (INamedTypeSymbol)symbolContext.Symbol; var namedTypeAttributes = namedType.GetApplicableAttributes(attributeUsageAttribute); diff --git a/src/Roslyn.Diagnostics.Analyzers/Core/ExportedPartsShouldHaveImportingConstructor.cs b/src/Roslyn.Diagnostics.Analyzers/Core/ExportedPartsShouldHaveImportingConstructor.cs index 8f1d6bb388..6f98c4570a 100644 --- a/src/Roslyn.Diagnostics.Analyzers/Core/ExportedPartsShouldHaveImportingConstructor.cs +++ b/src/Roslyn.Diagnostics.Analyzers/Core/ExportedPartsShouldHaveImportingConstructor.cs @@ -76,7 +76,7 @@ public override void Initialize(AnalysisContext context) }); } - private static void AnalyzeSymbolForAttribute(ref SymbolAnalysisContext context, INamedTypeSymbol exportAttributeOpt, INamedTypeSymbol importingConstructorAttribute, INamedTypeSymbol namedType, IEnumerable exportAttributes) + private static void AnalyzeSymbolForAttribute(ref SymbolAnalysisContext context, INamedTypeSymbol? exportAttributeOpt, INamedTypeSymbol? importingConstructorAttribute, INamedTypeSymbol namedType, IEnumerable exportAttributes) { if (exportAttributeOpt is null) { @@ -89,8 +89,8 @@ private static void AnalyzeSymbolForAttribute(ref SymbolAnalysisContext context, return; } - IMethodSymbol importingConstructor = null; - ImmutableArray nonImportingConstructors = ImmutableArray.Empty; + IMethodSymbol? importingConstructor = null; + var nonImportingConstructors = ImmutableArray.Empty; foreach (var constructor in namedType.Constructors) { if (constructor.IsStatic) @@ -127,7 +127,7 @@ private static void AnalyzeSymbolForAttribute(ref SymbolAnalysisContext context, } } - IMethodSymbol missingImportingConstructor = null; + IMethodSymbol? missingImportingConstructor = null; if (importingConstructor is null) { missingImportingConstructor = nonImportingConstructors.FirstOrDefault(constructor => constructor.DeclaredAccessibility == Accessibility.Public) diff --git a/src/Roslyn.Diagnostics.Analyzers/Core/ExportedPartsShouldHaveImportingConstructorCodeFixProvider.cs b/src/Roslyn.Diagnostics.Analyzers/Core/ExportedPartsShouldHaveImportingConstructorCodeFixProvider.cs index 8bb6274d8b..adecf61386 100644 --- a/src/Roslyn.Diagnostics.Analyzers/Core/ExportedPartsShouldHaveImportingConstructorCodeFixProvider.cs +++ b/src/Roslyn.Diagnostics.Analyzers/Core/ExportedPartsShouldHaveImportingConstructorCodeFixProvider.cs @@ -75,7 +75,7 @@ private async Task AddExplicitImportingConstructorAsync(Document docum var exportAttribute = root.FindNode(sourceSpan, getInnermostNodeForTie: true); var exportAttributeSymbol = semanticModel.GetSymbolInfo(exportAttribute, cancellationToken).Symbol?.ContainingType; - INamedTypeSymbol importingConstructorAttributeSymbol = null; + INamedTypeSymbol? importingConstructorAttributeSymbol = null; while (exportAttributeSymbol is object) { importingConstructorAttributeSymbol = exportAttributeSymbol.ContainingNamespace?.GetTypeMembers(nameof(ImportingConstructorAttribute)).FirstOrDefault(); @@ -189,10 +189,10 @@ private async Task AddImportingConstructorAttributeAsync(Document docu return document; } - INamedTypeSymbol importingConstructorAttributeSymbol = null; + INamedTypeSymbol? importingConstructorAttributeSymbol = null; foreach (var attributeData in exportedType.GetAttributes()) { - INamedTypeSymbol exportAttributeSymbol = null; + INamedTypeSymbol? exportAttributeSymbol = null; foreach (var attributeClass in attributeData.AttributeClass.GetBaseTypesAndThis()) { if (attributeClass.Name == nameof(ExportAttribute)) diff --git a/src/Roslyn.Diagnostics.Analyzers/Core/ImportingConstructorShouldBeObsolete.cs b/src/Roslyn.Diagnostics.Analyzers/Core/ImportingConstructorShouldBeObsolete.cs index 3b770c8605..a37fd6ff34 100644 --- a/src/Roslyn.Diagnostics.Analyzers/Core/ImportingConstructorShouldBeObsolete.cs +++ b/src/Roslyn.Diagnostics.Analyzers/Core/ImportingConstructorShouldBeObsolete.cs @@ -69,7 +69,7 @@ public override void Initialize(AnalysisContext context) }); } - private static void AnalyzeSymbolForAttribute(ref SymbolAnalysisContext context, INamedTypeSymbol obsoleteAttribute, INamedTypeSymbol exportAttributeOpt, INamedTypeSymbol importingConstructorAttribute, INamedTypeSymbol namedType, IEnumerable exportAttributes) + private static void AnalyzeSymbolForAttribute(ref SymbolAnalysisContext context, INamedTypeSymbol? obsoleteAttribute, INamedTypeSymbol? exportAttributeOpt, INamedTypeSymbol? importingConstructorAttribute, INamedTypeSymbol namedType, IEnumerable exportAttributes) { if (exportAttributeOpt is null) { @@ -89,7 +89,7 @@ private static void AnalyzeSymbolForAttribute(ref SymbolAnalysisContext context, } var constructorAttributes = constructor.GetAttributes(); - AttributeData importingConstructorAttributeData = null; + AttributeData? importingConstructorAttributeData = null; foreach (var attributeData in constructorAttributes) { if (attributeData.AttributeClass.DerivesFrom(importingConstructorAttribute)) diff --git a/src/Roslyn.Diagnostics.Analyzers/Core/ImportingConstructorShouldBeObsoleteCodeFixProvider.cs b/src/Roslyn.Diagnostics.Analyzers/Core/ImportingConstructorShouldBeObsoleteCodeFixProvider.cs index 327edb6436..0c6ca05e9b 100644 --- a/src/Roslyn.Diagnostics.Analyzers/Core/ImportingConstructorShouldBeObsoleteCodeFixProvider.cs +++ b/src/Roslyn.Diagnostics.Analyzers/Core/ImportingConstructorShouldBeObsoleteCodeFixProvider.cs @@ -243,7 +243,7 @@ private static SyntaxNode GenerateDescriptionArgument(SyntaxGenerator generator, if (knownConstant is object) { attributeArgument = generator.MemberAccessExpression( - generator.TypeExpressionForStaticMemberAccess(mefConstructionType), + generator.TypeExpressionForStaticMemberAccess(mefConstructionType!), generator.IdentifierName("ImportingConstructorMessage")); } else diff --git a/src/Roslyn.Diagnostics.Analyzers/Core/SpecializedEnumerableCreationAnalyzer.cs b/src/Roslyn.Diagnostics.Analyzers/Core/SpecializedEnumerableCreationAnalyzer.cs index 579f116364..615b802af3 100644 --- a/src/Roslyn.Diagnostics.Analyzers/Core/SpecializedEnumerableCreationAnalyzer.cs +++ b/src/Roslyn.Diagnostics.Analyzers/Core/SpecializedEnumerableCreationAnalyzer.cs @@ -54,7 +54,7 @@ public override void Initialize(AnalysisContext analysisContext) analysisContext.RegisterCompilationStartAction( (context) => { - INamedTypeSymbol specializedCollectionsSymbol = context.Compilation.GetOrCreateTypeByMetadataName(SpecializedCollectionsMetadataName); + INamedTypeSymbol? specializedCollectionsSymbol = context.Compilation.GetOrCreateTypeByMetadataName(SpecializedCollectionsMetadataName); if (specializedCollectionsSymbol == null) { // TODO: In the future, we may want to run this analyzer even if the SpecializedCollections @@ -64,13 +64,13 @@ public override void Initialize(AnalysisContext analysisContext) return; } - INamedTypeSymbol genericEnumerableSymbol = context.Compilation.GetOrCreateTypeByMetadataName(WellKnownTypeNames.SystemCollectionsGenericIEnumerable1); + INamedTypeSymbol? genericEnumerableSymbol = context.Compilation.GetOrCreateTypeByMetadataName(WellKnownTypeNames.SystemCollectionsGenericIEnumerable1); if (genericEnumerableSymbol == null) { return; } - INamedTypeSymbol linqEnumerableSymbol = context.Compilation.GetOrCreateTypeByMetadataName(LinqEnumerableMetadataName); + INamedTypeSymbol? linqEnumerableSymbol = context.Compilation.GetOrCreateTypeByMetadataName(LinqEnumerableMetadataName); if (linqEnumerableSymbol == null) { return; diff --git a/src/Roslyn.Diagnostics.Analyzers/Core/SymbolDeclaredEventMustBeGeneratedForSourceSymbols.cs b/src/Roslyn.Diagnostics.Analyzers/Core/SymbolDeclaredEventMustBeGeneratedForSourceSymbols.cs index 0266dffc9e..ef135af9fa 100644 --- a/src/Roslyn.Diagnostics.Analyzers/Core/SymbolDeclaredEventMustBeGeneratedForSourceSymbols.cs +++ b/src/Roslyn.Diagnostics.Analyzers/Core/SymbolDeclaredEventMustBeGeneratedForSourceSymbols.cs @@ -41,10 +41,10 @@ public sealed override void Initialize(AnalysisContext context) context.RegisterCompilationStartAction(compilationContext => { - INamedTypeSymbol symbolType = compilationContext.Compilation.GetOrCreateTypeByMetadataName(s_fullNameOfSymbol); + INamedTypeSymbol? symbolType = compilationContext.Compilation.GetOrCreateTypeByMetadataName(s_fullNameOfSymbol); if (symbolType != null) { - CompilationAnalyzer compilationAnalyzer = GetCompilationAnalyzer(compilationContext.Compilation, symbolType); + CompilationAnalyzer? compilationAnalyzer = GetCompilationAnalyzer(compilationContext.Compilation, symbolType); if (compilationAnalyzer != null) { compilationContext.RegisterSyntaxNodeAction(compilationAnalyzer.AnalyzeNode, InvocationExpressionSyntaxKind); @@ -56,7 +56,7 @@ public sealed override void Initialize(AnalysisContext context) } protected abstract TSyntaxKind InvocationExpressionSyntaxKind { get; } - protected abstract CompilationAnalyzer GetCompilationAnalyzer(Compilation compilation, INamedTypeSymbol symbolType); + protected abstract CompilationAnalyzer? GetCompilationAnalyzer(Compilation compilation, INamedTypeSymbol symbolType); protected abstract class CompilationAnalyzer { @@ -88,7 +88,7 @@ protected CompilationAnalyzer(INamedTypeSymbol symbolType, INamedTypeSymbol comp } } - protected abstract SyntaxNode GetFirstArgumentOfInvocation(SyntaxNode invocation); + protected abstract SyntaxNode? GetFirstArgumentOfInvocation(SyntaxNode invocation); protected abstract ImmutableHashSet SymbolTypesWithExpectedSymbolDeclaredEvent { get; } internal void AnalyzeNode(SyntaxNodeAnalysisContext context) @@ -106,12 +106,12 @@ internal virtual void AnalyzeMethodInvocation(IMethodSymbol invocationSymbol, Sy if (invocationSymbol.Name.Equals(SymbolDeclaredEventName, StringComparison.Ordinal) && _compilationType.Equals(invocationSymbol.ContainingType)) { - SyntaxNode argument = GetFirstArgumentOfInvocation(context.Node); + SyntaxNode? argument = GetFirstArgumentOfInvocation(context.Node); AnalyzeSymbolDeclaredEventInvocation(argument, context); } } - protected bool AnalyzeSymbolDeclaredEventInvocation(SyntaxNode argument, SyntaxNodeAnalysisContext context) + protected bool AnalyzeSymbolDeclaredEventInvocation(SyntaxNode? argument, SyntaxNodeAnalysisContext context) { if (argument != null) { diff --git a/src/Roslyn.Diagnostics.Analyzers/Core/TestExportsShouldNotBeDiscoverable.cs b/src/Roslyn.Diagnostics.Analyzers/Core/TestExportsShouldNotBeDiscoverable.cs index 3d58911aeb..01cfdc9ece 100644 --- a/src/Roslyn.Diagnostics.Analyzers/Core/TestExportsShouldNotBeDiscoverable.cs +++ b/src/Roslyn.Diagnostics.Analyzers/Core/TestExportsShouldNotBeDiscoverable.cs @@ -67,7 +67,7 @@ public override void Initialize(AnalysisContext context) }); } - private static void AnalyzeSymbolForAttribute(ref SymbolAnalysisContext context, INamedTypeSymbol exportAttributeOpt, INamedTypeSymbol namedType, IEnumerable exportAttributes, IEnumerable namedTypeAttributes) + private static void AnalyzeSymbolForAttribute(ref SymbolAnalysisContext context, INamedTypeSymbol? exportAttributeOpt, INamedTypeSymbol namedType, IEnumerable exportAttributes, IEnumerable namedTypeAttributes) { if (exportAttributeOpt is null) { diff --git a/src/Roslyn.Diagnostics.Analyzers/Core/TestExportsShouldNotBeDiscoverableCodeFixProvider.cs b/src/Roslyn.Diagnostics.Analyzers/Core/TestExportsShouldNotBeDiscoverableCodeFixProvider.cs index ab1e58113a..f8ebb0be7e 100644 --- a/src/Roslyn.Diagnostics.Analyzers/Core/TestExportsShouldNotBeDiscoverableCodeFixProvider.cs +++ b/src/Roslyn.Diagnostics.Analyzers/Core/TestExportsShouldNotBeDiscoverableCodeFixProvider.cs @@ -66,10 +66,10 @@ private async Task AddPartNotDiscoverableAttributeAsync(Document docum return document; } - INamedTypeSymbol partNotDiscoverableAttributeSymbol = null; + INamedTypeSymbol? partNotDiscoverableAttributeSymbol = null; foreach (var attributeData in exportedType.GetAttributes()) { - INamedTypeSymbol exportAttributeSymbol = null; + INamedTypeSymbol? exportAttributeSymbol = null; foreach (var attributeClass in attributeData.AttributeClass.GetBaseTypesAndThis()) { if (attributeClass.Name == nameof(ExportAttribute)) diff --git a/src/Test.Utilities/AdditionalMetadataReferences.cs b/src/Test.Utilities/AdditionalMetadataReferences.cs index bf5f280c4c..b268f89b0a 100644 --- a/src/Test.Utilities/AdditionalMetadataReferences.cs +++ b/src/Test.Utilities/AdditionalMetadataReferences.cs @@ -30,7 +30,7 @@ public static class AdditionalMetadataReferences internal static readonly MetadataReference SystemWebExtensions = MetadataReference.CreateFromFile(typeof(System.Web.Script.Serialization.JavaScriptSerializer).Assembly.Location); internal static readonly MetadataReference SystemGlobalization = MetadataReference.CreateFromFile(Assembly.Load("System.Globalization, Version=4.0.10.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a").Location); - private static MetadataReference s_systemRuntimeFacadeRef; + private static MetadataReference? s_systemRuntimeFacadeRef; public static MetadataReference SystemRuntimeFacadeRef { get @@ -46,7 +46,7 @@ public static MetadataReference SystemRuntimeFacadeRef } } - private static MetadataReference s_systemThreadingFacadeRef; + private static MetadataReference? s_systemThreadingFacadeRef; public static MetadataReference SystemThreadingFacadeRef { get @@ -62,7 +62,7 @@ public static MetadataReference SystemThreadingFacadeRef } } - private static MetadataReference s_systemThreadingTasksFacadeRef; + private static MetadataReference? s_systemThreadingTasksFacadeRef; public static MetadataReference SystemThreadingTaskFacadeRef { get diff --git a/src/Test.Utilities/DiagnosticAnalyzerTestBase.cs b/src/Test.Utilities/DiagnosticAnalyzerTestBase.cs index ff54756abc..a91c420083 100644 --- a/src/Test.Utilities/DiagnosticAnalyzerTestBase.cs +++ b/src/Test.Utilities/DiagnosticAnalyzerTestBase.cs @@ -1,5 +1,8 @@ // Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. +// Disable nullable in legacy test framework +#nullable disable + using System; using System.Collections.Generic; using System.Collections.Immutable; diff --git a/src/Test.Utilities/DiagnosticAnalyzerTests.Extensions.cs b/src/Test.Utilities/DiagnosticAnalyzerTests.Extensions.cs index 5fc28dfea6..b042008529 100644 --- a/src/Test.Utilities/DiagnosticAnalyzerTests.Extensions.cs +++ b/src/Test.Utilities/DiagnosticAnalyzerTests.Extensions.cs @@ -1,5 +1,9 @@ // Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. +// Disable nullable in legacy test framework +#nullable disable + + using System; using System.Collections.Generic; using System.Diagnostics; diff --git a/src/Test.Utilities/DiagnosticExtensions.cs b/src/Test.Utilities/DiagnosticExtensions.cs index 30b45e4786..3260d38579 100644 --- a/src/Test.Utilities/DiagnosticExtensions.cs +++ b/src/Test.Utilities/DiagnosticExtensions.cs @@ -16,7 +16,7 @@ public static class DiagnosticExtensions this TCompilation c, DiagnosticAnalyzer[] analyzers, TestValidationMode validationMode, - AnalyzerOptions options = null) + AnalyzerOptions? options = null) where TCompilation : Compilation { var compilationWithAnalyzers = c.WithAnalyzers(analyzers.ToImmutableArray(), options, CancellationToken.None); diff --git a/src/Test.Utilities/EnsureEnglishUICulture.cs b/src/Test.Utilities/EnsureEnglishUICulture.cs index 3ee0c39ae6..73724e32a7 100644 --- a/src/Test.Utilities/EnsureEnglishUICulture.cs +++ b/src/Test.Utilities/EnsureEnglishUICulture.cs @@ -9,7 +9,7 @@ namespace Test.Utilities { public sealed class EnsureEnglishUICulture : IDisposable { - public static CultureInfo PreferredOrNull + public static CultureInfo? PreferredOrNull { get { @@ -24,13 +24,13 @@ public static CultureInfo PreferredOrNull } private bool _needToRestore; - private readonly CultureInfo _threadUICulture; + private readonly CultureInfo? _threadUICulture; private readonly int _threadId; public EnsureEnglishUICulture() { _threadId = Thread.CurrentThread.ManagedThreadId; - CultureInfo preferred = PreferredOrNull; + CultureInfo? preferred = PreferredOrNull; if (preferred != null) { diff --git a/src/Test.Utilities/TestAdditionalDocument.cs b/src/Test.Utilities/TestAdditionalDocument.cs index 1f39fda401..0e8c3ef11d 100644 --- a/src/Test.Utilities/TestAdditionalDocument.cs +++ b/src/Test.Utilities/TestAdditionalDocument.cs @@ -11,7 +11,7 @@ public class TestAdditionalDocument : AdditionalText { private readonly string _filePath; private readonly string _fileName; - private readonly SourceText _sourceText; + private readonly SourceText? _sourceText; public TestAdditionalDocument(string fileName, string text) : this(fileName, fileName, text) @@ -37,7 +37,7 @@ public TestAdditionalDocument(string filePath, string fileName, string text) public override string Path => _filePath; public string Name => _fileName; - public override SourceText GetText(CancellationToken cancellationToken = default) + public override SourceText? GetText(CancellationToken cancellationToken = default) => _sourceText; } } diff --git a/src/Utilities/Compiler/Analyzer.Utilities.projitems b/src/Utilities/Compiler/Analyzer.Utilities.projitems index 64950de813..0387cb4b05 100644 --- a/src/Utilities/Compiler/Analyzer.Utilities.projitems +++ b/src/Utilities/Compiler/Analyzer.Utilities.projitems @@ -11,6 +11,12 @@ $(DefineConstants);HAS_IOPERATION true + + + enable diff --git a/src/Utilities/Compiler/Extensions/ITypeSymbolExtensions.cs b/src/Utilities/Compiler/Extensions/ITypeSymbolExtensions.cs index 1ec4c06dc0..345995abf4 100644 --- a/src/Utilities/Compiler/Extensions/ITypeSymbolExtensions.cs +++ b/src/Utilities/Compiler/Extensions/ITypeSymbolExtensions.cs @@ -32,7 +32,7 @@ public static bool IsPrimitiveType(this ITypeSymbol type) } } - public static bool Inherits(this ITypeSymbol type, ITypeSymbol possibleBase) + public static bool Inherits(this ITypeSymbol? type, ITypeSymbol? possibleBase) { if (type == null || possibleBase == null) { @@ -141,7 +141,7 @@ public static bool IsDisposable(this ITypeSymbol type, INamedTypeSymbol? iDispos /// /// The type symbol. /// The compilation symbol for . - public static IEnumerable GetApplicableAttributes(this INamedTypeSymbol type, INamedTypeSymbol attributeUsageAttribute) + public static IEnumerable GetApplicableAttributes(this INamedTypeSymbol type, INamedTypeSymbol? attributeUsageAttribute) { var attributes = new List(); var onlyIncludeInherited = false; @@ -208,7 +208,7 @@ static bool IsInheritedAttribute(AttributeData attributeData, INamedTypeSymbol a } } - public static IEnumerable GetApplicableExportAttributes(this INamedTypeSymbol type, INamedTypeSymbol exportAttributeV1, INamedTypeSymbol exportAttributeV2, INamedTypeSymbol inheritedExportAttribute) + public static IEnumerable GetApplicableExportAttributes(this INamedTypeSymbol? type, INamedTypeSymbol? exportAttributeV1, INamedTypeSymbol? exportAttributeV2, INamedTypeSymbol? inheritedExportAttribute) { var attributes = new List(); var onlyIncludeInherited = false; From abecfb28573d9d79a2824759eecbd6c13da51d9b Mon Sep 17 00:00:00 2001 From: Manish Vasani Date: Thu, 7 Nov 2019 12:50:58 -0800 Subject: [PATCH 06/28] Nullable annotations for Microsoft.CodeAnalysis.Analyzers --- .../CSharpImmutableObjectMethodAnalyzer.cs | 14 ++--- .../CSharpRegisterActionAnalyzer.cs | 14 ++--- .../CSharpReportDiagnosticAnalyzer.cs | 2 +- .../FixerWithFixAllAnalyzer.Fixer.cs | 9 ++- .../FixAnalyzers/FixerWithFixAllAnalyzer.cs | 18 +++--- .../ConfigureGeneratedCodeAnalysisAnalyzer.cs | 4 +- .../DiagnosticAnalyzerAPIUsageAnalyzer.cs | 2 +- .../DiagnosticAnalyzerAttributeAnalyzer.cs | 10 ++-- ...alyzer.DiagnosticAnalyzerSymbolAnalyzer.cs | 2 +- .../DiagnosticAnalyzerCorrectnessAnalyzer.cs | 8 +-- .../DiagnosticAnalyzerFieldsAnalyzer.cs | 12 ++-- .../DiagnosticDescriptorCreationAnalyzer.cs | 55 ++++++++++--------- .../EnableConcurrentExecutionAnalyzer.cs | 4 +- .../MetaAnalyzers/RegisterActionAnalyzer.cs | 35 ++++++------ .../MetaAnalyzers/ReportDiagnosticAnalyzer.cs | 30 +++++----- 15 files changed, 111 insertions(+), 108 deletions(-) diff --git a/src/Microsoft.CodeAnalysis.Analyzers/CSharp/CSharpImmutableObjectMethodAnalyzer.cs b/src/Microsoft.CodeAnalysis.Analyzers/CSharp/CSharpImmutableObjectMethodAnalyzer.cs index 1e020a0e51..3491c4036f 100644 --- a/src/Microsoft.CodeAnalysis.Analyzers/CSharp/CSharpImmutableObjectMethodAnalyzer.cs +++ b/src/Microsoft.CodeAnalysis.Analyzers/CSharp/CSharpImmutableObjectMethodAnalyzer.cs @@ -50,15 +50,15 @@ public override void Initialize(AnalysisContext context) context.RegisterCompilationStartAction(compilationContext => { - INamedTypeSymbol solutionSymbol = compilationContext.Compilation.GetOrCreateTypeByMetadataName(SolutionFullName); - INamedTypeSymbol projectSymbol = compilationContext.Compilation.GetOrCreateTypeByMetadataName(ProjectFullName); - INamedTypeSymbol documentSymbol = compilationContext.Compilation.GetOrCreateTypeByMetadataName(DocumentFullName); - INamedTypeSymbol syntaxNodeSymbol = compilationContext.Compilation.GetOrCreateTypeByMetadataName(SyntaxNodeFullName); - INamedTypeSymbol compilationSymbol = compilationContext.Compilation.GetOrCreateTypeByMetadataName(CompilationFullName); + INamedTypeSymbol? solutionSymbol = compilationContext.Compilation.GetOrCreateTypeByMetadataName(SolutionFullName); + INamedTypeSymbol? projectSymbol = compilationContext.Compilation.GetOrCreateTypeByMetadataName(ProjectFullName); + INamedTypeSymbol? documentSymbol = compilationContext.Compilation.GetOrCreateTypeByMetadataName(DocumentFullName); + INamedTypeSymbol? syntaxNodeSymbol = compilationContext.Compilation.GetOrCreateTypeByMetadataName(SyntaxNodeFullName); + INamedTypeSymbol? compilationSymbol = compilationContext.Compilation.GetOrCreateTypeByMetadataName(CompilationFullName); - ImmutableArray immutableSymbols = ImmutableArray.Create(solutionSymbol, projectSymbol, documentSymbol, syntaxNodeSymbol, compilationSymbol); + ImmutableArray immutableSymbols = ImmutableArray.CreateRange(new[] { solutionSymbol, projectSymbol, documentSymbol, syntaxNodeSymbol, compilationSymbol }.WhereNotNull()); //Only register our node action if we can find the symbols for our immutable types - if (immutableSymbols.Any(n => n == null)) + if (immutableSymbols.IsEmpty) { return; } diff --git a/src/Microsoft.CodeAnalysis.Analyzers/CSharp/MetaAnalyzers/CSharpRegisterActionAnalyzer.cs b/src/Microsoft.CodeAnalysis.Analyzers/CSharp/MetaAnalyzers/CSharpRegisterActionAnalyzer.cs index 61f823d81b..7b346fc945 100644 --- a/src/Microsoft.CodeAnalysis.Analyzers/CSharp/MetaAnalyzers/CSharpRegisterActionAnalyzer.cs +++ b/src/Microsoft.CodeAnalysis.Analyzers/CSharp/MetaAnalyzers/CSharpRegisterActionAnalyzer.cs @@ -23,19 +23,19 @@ public class CSharpRegisterActionAnalyzer : RegisterActionAnalyzer SyntaxKind.Argument; protected override SyntaxKind ParameterSyntaxKind => SyntaxKind.Parameter; - protected override IEnumerable GetArgumentExpressions(InvocationExpressionSyntax invocation) + protected override IEnumerable? GetArgumentExpressions(InvocationExpressionSyntax invocation) { if (invocation.ArgumentList != null) { @@ -71,7 +71,7 @@ protected override SyntaxNode GetInvocationExpression(InvocationExpressionSyntax return invocation.Expression; } - protected override SyntaxNode GetInvocationReceiver(InvocationExpressionSyntax invocation) + protected override SyntaxNode? GetInvocationReceiver(InvocationExpressionSyntax invocation) { return (invocation.Expression as MemberAccessExpressionSyntax)?.Expression; } diff --git a/src/Microsoft.CodeAnalysis.Analyzers/CSharp/MetaAnalyzers/CSharpReportDiagnosticAnalyzer.cs b/src/Microsoft.CodeAnalysis.Analyzers/CSharp/MetaAnalyzers/CSharpReportDiagnosticAnalyzer.cs index 44e4a40d83..2388580df4 100644 --- a/src/Microsoft.CodeAnalysis.Analyzers/CSharp/MetaAnalyzers/CSharpReportDiagnosticAnalyzer.cs +++ b/src/Microsoft.CodeAnalysis.Analyzers/CSharp/MetaAnalyzers/CSharpReportDiagnosticAnalyzer.cs @@ -24,7 +24,7 @@ public CSharpReportDiagnosticCompilationAnalyzer(ImmutableHashSet GetArgumentExpressions(InvocationExpressionSyntax invocation) + protected override IEnumerable? GetArgumentExpressions(InvocationExpressionSyntax invocation) { if (invocation.ArgumentList != null) { diff --git a/src/Microsoft.CodeAnalysis.Analyzers/Core/FixAnalyzers/FixerWithFixAllAnalyzer.Fixer.cs b/src/Microsoft.CodeAnalysis.Analyzers/Core/FixAnalyzers/FixerWithFixAllAnalyzer.Fixer.cs index 65674a5165..0446b049c3 100644 --- a/src/Microsoft.CodeAnalysis.Analyzers/Core/FixAnalyzers/FixerWithFixAllAnalyzer.Fixer.cs +++ b/src/Microsoft.CodeAnalysis.Analyzers/Core/FixAnalyzers/FixerWithFixAllAnalyzer.Fixer.cs @@ -55,8 +55,13 @@ private static async Task AddMethodAsync(Document document, SyntaxNode var model = await document.GetSemanticModelAsync(cancellationToken).ConfigureAwait(false); var typeIsSealed = ((INamedTypeSymbol)model.GetDeclaredSymbol(classDecl)).IsSealed; - INamedTypeSymbol codeFixProviderSymbol = model.Compilation.GetOrCreateTypeByMetadataName(FixerWithFixAllAnalyzer.CodeFixProviderMetadataName); - IMethodSymbol getFixAllProviderMethod = codeFixProviderSymbol.GetMembers(FixerWithFixAllAnalyzer.GetFixAllProviderMethodName).OfType().First(); + INamedTypeSymbol? codeFixProviderSymbol = model.Compilation.GetOrCreateTypeByMetadataName(FixerWithFixAllAnalyzer.CodeFixProviderMetadataName); + IMethodSymbol? getFixAllProviderMethod = codeFixProviderSymbol?.GetMembers(FixerWithFixAllAnalyzer.GetFixAllProviderMethodName).OfType().FirstOrDefault(); + if (getFixAllProviderMethod == null) + { + return document; + } + var returnStatement = generator.ReturnStatement(generator.MemberAccessExpression( generator.IdentifierName("WellKnownFixAllProviders"), "BatchFixer")); var statements = new SyntaxNode[] { returnStatement }; diff --git a/src/Microsoft.CodeAnalysis.Analyzers/Core/FixAnalyzers/FixerWithFixAllAnalyzer.cs b/src/Microsoft.CodeAnalysis.Analyzers/Core/FixAnalyzers/FixerWithFixAllAnalyzer.cs index 7f2bdea96b..bd7d7d2826 100644 --- a/src/Microsoft.CodeAnalysis.Analyzers/Core/FixAnalyzers/FixerWithFixAllAnalyzer.cs +++ b/src/Microsoft.CodeAnalysis.Analyzers/Core/FixAnalyzers/FixerWithFixAllAnalyzer.cs @@ -86,37 +86,33 @@ private void CreateAnalyzerWithinCompilation(CompilationStartAnalysisContext con { context.CancellationToken.ThrowIfCancellationRequested(); - INamedTypeSymbol codeFixProviderSymbol = context.Compilation.GetOrCreateTypeByMetadataName(CodeFixProviderMetadataName); + INamedTypeSymbol? codeFixProviderSymbol = context.Compilation.GetOrCreateTypeByMetadataName(CodeFixProviderMetadataName); if (codeFixProviderSymbol == null) { return; } - IMethodSymbol getFixAllProviderMethod = codeFixProviderSymbol.GetMembers(GetFixAllProviderMethodName).OfType().FirstOrDefault(); + IMethodSymbol? getFixAllProviderMethod = codeFixProviderSymbol.GetMembers(GetFixAllProviderMethodName).OfType().FirstOrDefault(); if (getFixAllProviderMethod == null) { return; } - INamedTypeSymbol codeActionSymbol = context.Compilation.GetOrCreateTypeByMetadataName(CodeActionMetadataName); + INamedTypeSymbol? codeActionSymbol = context.Compilation.GetOrCreateTypeByMetadataName(CodeActionMetadataName); if (codeActionSymbol == null) { return; } - IEnumerable createSymbols = codeActionSymbol.GetMembers(CreateMethodName).OfType(); - if (createSymbols == null) - { - return; - } - - IPropertySymbol equivalenceKeyProperty = codeActionSymbol.GetMembers(EquivalenceKeyPropertyName).OfType().FirstOrDefault(); + IPropertySymbol? equivalenceKeyProperty = codeActionSymbol.GetMembers(EquivalenceKeyPropertyName).OfType().FirstOrDefault(); if (equivalenceKeyProperty == null) { return; } - CompilationAnalyzer compilationAnalyzer = new CompilationAnalyzer(codeFixProviderSymbol, codeActionSymbol, context.Compilation.Assembly, createMethods: ImmutableHashSet.CreateRange(createSymbols)); + var createMethods = codeActionSymbol.GetMembers(CreateMethodName).OfType().ToImmutableHashSet(); + + CompilationAnalyzer compilationAnalyzer = new CompilationAnalyzer(codeFixProviderSymbol, codeActionSymbol, context.Compilation.Assembly, createMethods); context.RegisterSymbolAction(compilationAnalyzer.AnalyzeNamedTypeSymbol, SymbolKind.NamedType); context.RegisterOperationBlockStartAction(compilationAnalyzer.OperationBlockStart); diff --git a/src/Microsoft.CodeAnalysis.Analyzers/Core/MetaAnalyzers/ConfigureGeneratedCodeAnalysisAnalyzer.cs b/src/Microsoft.CodeAnalysis.Analyzers/Core/MetaAnalyzers/ConfigureGeneratedCodeAnalysisAnalyzer.cs index 50ac08ba23..73f0daa5f4 100644 --- a/src/Microsoft.CodeAnalysis.Analyzers/Core/MetaAnalyzers/ConfigureGeneratedCodeAnalysisAnalyzer.cs +++ b/src/Microsoft.CodeAnalysis.Analyzers/Core/MetaAnalyzers/ConfigureGeneratedCodeAnalysisAnalyzer.cs @@ -39,7 +39,7 @@ public override void Initialize(AnalysisContext context) } [SuppressMessage("AnalyzerPerformance", "RS1012:Start action has no registered actions.", Justification = "Method returns an analyzer that is registered by the caller.")] - protected override DiagnosticAnalyzerSymbolAnalyzer GetDiagnosticAnalyzerSymbolAnalyzer(CompilationStartAnalysisContext compilationContext, INamedTypeSymbol diagnosticAnalyzer, INamedTypeSymbol diagnosticAnalyzerAttribute) + protected override DiagnosticAnalyzerSymbolAnalyzer? GetDiagnosticAnalyzerSymbolAnalyzer(CompilationStartAnalysisContext compilationContext, INamedTypeSymbol diagnosticAnalyzer, INamedTypeSymbol diagnosticAnalyzerAttribute) { var compilation = compilationContext.Compilation; @@ -62,7 +62,7 @@ protected override DiagnosticAnalyzerSymbolAnalyzer GetDiagnosticAnalyzerSymbolA return; } - IParameterSymbol analysisContextParameter = null; + IParameterSymbol? analysisContextParameter = null; foreach (var parameter in method.Parameters) { if (!Equals(parameter.Type, analysisContext)) diff --git a/src/Microsoft.CodeAnalysis.Analyzers/Core/MetaAnalyzers/DiagnosticAnalyzerAPIUsageAnalyzer.cs b/src/Microsoft.CodeAnalysis.Analyzers/Core/MetaAnalyzers/DiagnosticAnalyzerAPIUsageAnalyzer.cs index d3866f9b0c..44bb6f3e8c 100644 --- a/src/Microsoft.CodeAnalysis.Analyzers/Core/MetaAnalyzers/DiagnosticAnalyzerAPIUsageAnalyzer.cs +++ b/src/Microsoft.CodeAnalysis.Analyzers/Core/MetaAnalyzers/DiagnosticAnalyzerAPIUsageAnalyzer.cs @@ -63,7 +63,7 @@ public override void Initialize(AnalysisContext context) return; } - INamedTypeSymbol diagnosticAnalyzer = compilationStartContext.Compilation.GetOrCreateTypeByMetadataName(DiagnosticAnalyzerCorrectnessAnalyzer.DiagnosticAnalyzerTypeFullName); + INamedTypeSymbol? diagnosticAnalyzer = compilationStartContext.Compilation.GetOrCreateTypeByMetadataName(DiagnosticAnalyzerCorrectnessAnalyzer.DiagnosticAnalyzerTypeFullName); if (diagnosticAnalyzer == null) { // Does not contain any diagnostic analyzers. diff --git a/src/Microsoft.CodeAnalysis.Analyzers/Core/MetaAnalyzers/DiagnosticAnalyzerAttributeAnalyzer.cs b/src/Microsoft.CodeAnalysis.Analyzers/Core/MetaAnalyzers/DiagnosticAnalyzerAttributeAnalyzer.cs index 8c68ea2d08..9a07928d18 100644 --- a/src/Microsoft.CodeAnalysis.Analyzers/Core/MetaAnalyzers/DiagnosticAnalyzerAttributeAnalyzer.cs +++ b/src/Microsoft.CodeAnalysis.Analyzers/Core/MetaAnalyzers/DiagnosticAnalyzerAttributeAnalyzer.cs @@ -63,9 +63,9 @@ private sealed class AttributeAnalyzer : DiagnosticAnalyzerSymbolAnalyzer private const string CSharpCompilationFullName = @"Microsoft.CodeAnalysis.CSharp.CSharpCompilation"; private const string BasicCompilationFullName = @"Microsoft.CodeAnalysis.VisualBasic.VisualBasicCompilation"; - private readonly INamedTypeSymbol _attributeUsageAttribute; + private readonly INamedTypeSymbol? _attributeUsageAttribute; - public AttributeAnalyzer(INamedTypeSymbol diagnosticAnalyzer, INamedTypeSymbol diagnosticAnalyzerAttribute, INamedTypeSymbol attributeUsageAttribute) + public AttributeAnalyzer(INamedTypeSymbol diagnosticAnalyzer, INamedTypeSymbol diagnosticAnalyzerAttribute, INamedTypeSymbol? attributeUsageAttribute) : base(diagnosticAnalyzer, diagnosticAnalyzerAttribute) { _attributeUsageAttribute = attributeUsageAttribute; @@ -83,7 +83,7 @@ protected override void AnalyzeDiagnosticAnalyzer(SymbolAnalysisContext symbolCo // 2) AddLanguageSupportToAnalyzerRule: For analyzer supporting only one of C# or VB languages, detect if it can support the other language. var hasAttribute = false; - SyntaxNode attributeSyntax = null; + SyntaxNode? attributeSyntax = null; bool supportsCSharp = false; bool supportsVB = false; @@ -133,11 +133,11 @@ protected override void AnalyzeDiagnosticAnalyzer(SymbolAnalysisContext symbolCo // then the analyzer is pretty likely a language-agnostic analyzer. Compilation compilation = symbolContext.Compilation; string compilationTypeNameToCheck = supportsCSharp ? CSharpCompilationFullName : BasicCompilationFullName; - INamedTypeSymbol compilationType = compilation.GetOrCreateTypeByMetadataName(compilationTypeNameToCheck); + INamedTypeSymbol? compilationType = compilation.GetOrCreateTypeByMetadataName(compilationTypeNameToCheck); if (compilationType == null) { string missingLanguage = supportsCSharp ? LanguageNames.VisualBasic : LanguageNames.CSharp; - Diagnostic diagnostic = Diagnostic.Create(AddLanguageSupportToAnalyzerRule, attributeSyntax.GetLocation(), namedType.Name, missingLanguage); + Diagnostic diagnostic = Diagnostic.Create(AddLanguageSupportToAnalyzerRule, attributeSyntax!.GetLocation(), namedType.Name, missingLanguage); symbolContext.ReportDiagnostic(diagnostic); } } diff --git a/src/Microsoft.CodeAnalysis.Analyzers/Core/MetaAnalyzers/DiagnosticAnalyzerCorrectnessAnalyzer.DiagnosticAnalyzerSymbolAnalyzer.cs b/src/Microsoft.CodeAnalysis.Analyzers/Core/MetaAnalyzers/DiagnosticAnalyzerCorrectnessAnalyzer.DiagnosticAnalyzerSymbolAnalyzer.cs index ae80da31a8..69b2f0a64a 100644 --- a/src/Microsoft.CodeAnalysis.Analyzers/Core/MetaAnalyzers/DiagnosticAnalyzerCorrectnessAnalyzer.DiagnosticAnalyzerSymbolAnalyzer.cs +++ b/src/Microsoft.CodeAnalysis.Analyzers/Core/MetaAnalyzers/DiagnosticAnalyzerCorrectnessAnalyzer.DiagnosticAnalyzerSymbolAnalyzer.cs @@ -35,7 +35,7 @@ internal void AnalyzeSymbol(SymbolAnalysisContext symbolContext) protected abstract void AnalyzeDiagnosticAnalyzer(SymbolAnalysisContext symbolContext); - protected bool HasDiagnosticAnalyzerAttribute(INamedTypeSymbol namedType, INamedTypeSymbol attributeUsageAttribute) + protected bool HasDiagnosticAnalyzerAttribute(INamedTypeSymbol namedType, INamedTypeSymbol? attributeUsageAttribute) { foreach (AttributeData attribute in namedType.GetApplicableAttributes(attributeUsageAttribute)) { diff --git a/src/Microsoft.CodeAnalysis.Analyzers/Core/MetaAnalyzers/DiagnosticAnalyzerCorrectnessAnalyzer.cs b/src/Microsoft.CodeAnalysis.Analyzers/Core/MetaAnalyzers/DiagnosticAnalyzerCorrectnessAnalyzer.cs index 7a7fd2f534..2308826e0d 100644 --- a/src/Microsoft.CodeAnalysis.Analyzers/Core/MetaAnalyzers/DiagnosticAnalyzerCorrectnessAnalyzer.cs +++ b/src/Microsoft.CodeAnalysis.Analyzers/Core/MetaAnalyzers/DiagnosticAnalyzerCorrectnessAnalyzer.cs @@ -54,8 +54,8 @@ public override void Initialize(AnalysisContext context) context.RegisterCompilationStartAction(compilationContext => { - INamedTypeSymbol diagnosticAnalyzer = compilationContext.Compilation.GetOrCreateTypeByMetadataName(DiagnosticAnalyzerTypeFullName); - INamedTypeSymbol diagnosticAnalyzerAttribute = compilationContext.Compilation.GetOrCreateTypeByMetadataName(DiagnosticAnalyzerAttributeFullName); + INamedTypeSymbol? diagnosticAnalyzer = compilationContext.Compilation.GetOrCreateTypeByMetadataName(DiagnosticAnalyzerTypeFullName); + INamedTypeSymbol? diagnosticAnalyzerAttribute = compilationContext.Compilation.GetOrCreateTypeByMetadataName(DiagnosticAnalyzerAttributeFullName); if (diagnosticAnalyzer == null || diagnosticAnalyzerAttribute == null) { @@ -63,7 +63,7 @@ public override void Initialize(AnalysisContext context) return; } - DiagnosticAnalyzerSymbolAnalyzer analyzer = GetDiagnosticAnalyzerSymbolAnalyzer(compilationContext, diagnosticAnalyzer, diagnosticAnalyzerAttribute); + DiagnosticAnalyzerSymbolAnalyzer? analyzer = GetDiagnosticAnalyzerSymbolAnalyzer(compilationContext, diagnosticAnalyzer, diagnosticAnalyzerAttribute); if (analyzer != null) { compilationContext.RegisterSymbolAction(c => analyzer.AnalyzeSymbol(c), SymbolKind.NamedType); @@ -71,6 +71,6 @@ public override void Initialize(AnalysisContext context) }); } - protected abstract DiagnosticAnalyzerSymbolAnalyzer GetDiagnosticAnalyzerSymbolAnalyzer(CompilationStartAnalysisContext compilationContext, INamedTypeSymbol diagnosticAnalyzer, INamedTypeSymbol diagnosticAnalyzerAttribute); + protected abstract DiagnosticAnalyzerSymbolAnalyzer? GetDiagnosticAnalyzerSymbolAnalyzer(CompilationStartAnalysisContext compilationContext, INamedTypeSymbol diagnosticAnalyzer, INamedTypeSymbol diagnosticAnalyzerAttribute); } } diff --git a/src/Microsoft.CodeAnalysis.Analyzers/Core/MetaAnalyzers/DiagnosticAnalyzerFieldsAnalyzer.cs b/src/Microsoft.CodeAnalysis.Analyzers/Core/MetaAnalyzers/DiagnosticAnalyzerFieldsAnalyzer.cs index 9f9b5f9aa3..6d76078beb 100644 --- a/src/Microsoft.CodeAnalysis.Analyzers/Core/MetaAnalyzers/DiagnosticAnalyzerFieldsAnalyzer.cs +++ b/src/Microsoft.CodeAnalysis.Analyzers/Core/MetaAnalyzers/DiagnosticAnalyzerFieldsAnalyzer.cs @@ -44,23 +44,23 @@ public override void Initialize(AnalysisContext context) } [SuppressMessage("AnalyzerPerformance", "RS1012:Start action has no registered actions.", Justification = "Method returns an analyzer that is registered by the caller.")] - protected override DiagnosticAnalyzerSymbolAnalyzer GetDiagnosticAnalyzerSymbolAnalyzer(CompilationStartAnalysisContext compilationContext, INamedTypeSymbol diagnosticAnalyzer, INamedTypeSymbol diagnosticAnalyzerAttribute) + protected override DiagnosticAnalyzerSymbolAnalyzer? GetDiagnosticAnalyzerSymbolAnalyzer(CompilationStartAnalysisContext compilationContext, INamedTypeSymbol diagnosticAnalyzer, INamedTypeSymbol diagnosticAnalyzerAttribute) { Compilation compilation = compilationContext.Compilation; - INamedTypeSymbol compilationType = compilation.GetOrCreateTypeByMetadataName(s_compilationTypeFullName); + INamedTypeSymbol? compilationType = compilation.GetOrCreateTypeByMetadataName(s_compilationTypeFullName); if (compilationType == null) { return null; } - INamedTypeSymbol symbolType = compilation.GetOrCreateTypeByMetadataName(s_symbolTypeFullName); + INamedTypeSymbol? symbolType = compilation.GetOrCreateTypeByMetadataName(s_symbolTypeFullName); if (symbolType == null) { return null; } - INamedTypeSymbol operationType = compilation.GetOrCreateTypeByMetadataName(s_operationTypeFullName); + INamedTypeSymbol? operationType = compilation.GetOrCreateTypeByMetadataName(s_operationTypeFullName); if (operationType == null) { return null; @@ -76,9 +76,9 @@ private sealed class FieldsAnalyzer : SyntaxNodeWithinAnalyzerTypeCompilationAna private readonly INamedTypeSymbol _compilationType; private readonly INamedTypeSymbol _symbolType; private readonly INamedTypeSymbol _operationType; - private readonly INamedTypeSymbol _attributeUsageAttribute; + private readonly INamedTypeSymbol? _attributeUsageAttribute; - public FieldsAnalyzer(INamedTypeSymbol compilationType, INamedTypeSymbol symbolType, INamedTypeSymbol operationType, INamedTypeSymbol attributeUsageAttribute, INamedTypeSymbol diagnosticAnalyzer, INamedTypeSymbol diagnosticAnalyzerAttribute) + public FieldsAnalyzer(INamedTypeSymbol compilationType, INamedTypeSymbol symbolType, INamedTypeSymbol operationType, INamedTypeSymbol? attributeUsageAttribute, INamedTypeSymbol diagnosticAnalyzer, INamedTypeSymbol diagnosticAnalyzerAttribute) : base(diagnosticAnalyzer, diagnosticAnalyzerAttribute) { _compilationType = compilationType; diff --git a/src/Microsoft.CodeAnalysis.Analyzers/Core/MetaAnalyzers/DiagnosticDescriptorCreationAnalyzer.cs b/src/Microsoft.CodeAnalysis.Analyzers/Core/MetaAnalyzers/DiagnosticDescriptorCreationAnalyzer.cs index 9c056ddb11..bbc312783e 100644 --- a/src/Microsoft.CodeAnalysis.Analyzers/Core/MetaAnalyzers/DiagnosticDescriptorCreationAnalyzer.cs +++ b/src/Microsoft.CodeAnalysis.Analyzers/Core/MetaAnalyzers/DiagnosticDescriptorCreationAnalyzer.cs @@ -5,6 +5,7 @@ using System.Collections.Generic; using System.Collections.Immutable; using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; using System.IO; using System.Linq; using System.Threading; @@ -24,7 +25,7 @@ public sealed class DiagnosticDescriptorCreationAnalyzer : DiagnosticAnalyzer private const string DiagnosticIdParameterName = "id"; private const string DiagnosticCategoryAndIdRangeFile = "DiagnosticCategoryAndIdRanges.txt"; - private static readonly (string prefix, int start, int end) s_defaultAllowedIdsInfo = (null, -1, -1); + private static readonly (string? prefix, int start, int end) s_defaultAllowedIdsInfo = (null, -1, -1); private static readonly LocalizableString s_localizableUseLocalizableStringsTitle = new LocalizableResourceString(nameof(CodeAnalysisDiagnosticsResources.UseLocalizableStringsInDescriptorTitle), CodeAnalysisDiagnosticsResources.ResourceManager, typeof(CodeAnalysisDiagnosticsResources)); private static readonly LocalizableString s_localizableUseLocalizableStringsMessage = new LocalizableResourceString(nameof(CodeAnalysisDiagnosticsResources.UseLocalizableStringsInDescriptorMessage), CodeAnalysisDiagnosticsResources.ResourceManager, typeof(CodeAnalysisDiagnosticsResources)); @@ -140,7 +141,7 @@ public override void Initialize(AnalysisContext context) context.RegisterCompilationStartAction(compilationContext => { - INamedTypeSymbol diagnosticDescriptorType = compilationContext.Compilation.GetOrCreateTypeByMetadataName(DiagnosticAnalyzerCorrectnessAnalyzer.DiagnosticDescriptorFullName); + INamedTypeSymbol? diagnosticDescriptorType = compilationContext.Compilation.GetOrCreateTypeByMetadataName(DiagnosticAnalyzerCorrectnessAnalyzer.DiagnosticDescriptorFullName); if (diagnosticDescriptorType == null) { return; @@ -150,9 +151,9 @@ public override void Initialize(AnalysisContext context) var checkCategoryAndAllowedIds = TryGetCategoryAndAllowedIdsMap( compilationContext.Options.AdditionalFiles, compilationContext.CancellationToken, - out AdditionalText additionalTextOpt, - out ImmutableDictionary> categoryAndAllowedIdsMap, - out List invalidFileDiagnostics); + out AdditionalText? additionalTextOpt, + out ImmutableDictionary>? categoryAndAllowedIdsMap, + out List? invalidFileDiagnostics); var idToAnalyzerMap = new ConcurrentDictionary>>(); compilationContext.RegisterOperationAction(operationAnalysisContext => @@ -173,10 +174,10 @@ public override void Initialize(AnalysisContext context) AnalyzeTitle(operationAnalysisContext, objectCreation); AnalyzeHelpLinkUri(operationAnalysisContext, objectCreation); - string categoryOpt = null; + string? categoryOpt = null; if (!checkCategoryAndAllowedIds || !TryAnalyzeCategory(operationAnalysisContext, objectCreation, - additionalTextOpt, categoryAndAllowedIdsMap, out categoryOpt, out var allowedIdsInfoList)) + additionalTextOpt!, categoryAndAllowedIdsMap!, out categoryOpt, out var allowedIdsInfoList)) { allowedIdsInfoList = default; } @@ -259,9 +260,9 @@ private static void AnalyzeHelpLinkUri(OperationAnalysisContext operationAnalysi OperationAnalysisContext operationAnalysisContext, IObjectCreationOperation objectCreation, AdditionalText additionalText, - ImmutableDictionary> categoryAndAllowedIdsInfoMap, - out string category, - out ImmutableArray<(string prefix, int start, int end)> allowedIdsInfoList) + ImmutableDictionary> categoryAndAllowedIdsInfoMap, + [NotNullWhen(returnValue: true)] out string? category, + out ImmutableArray<(string? prefix, int start, int end)> allowedIdsInfoList) { category = null; allowedIdsInfoList = default; @@ -305,13 +306,13 @@ out ImmutableArray<(string prefix, int start, int end)> allowedIdsInfoList) private static void AnalyzeRuleId( OperationAnalysisContext operationAnalysisContext, IObjectCreationOperation objectCreation, - AdditionalText additionalTextOpt, - string categoryOpt, - ImmutableArray<(string prefix, int start, int end)> allowedIdsInfoListOpt, + AdditionalText? additionalTextOpt, + string? categoryOpt, + ImmutableArray<(string? prefix, int start, int end)> allowedIdsInfoListOpt, ConcurrentDictionary>> idToAnalyzerMap) { var analyzer = ((IFieldSymbol)operationAnalysisContext.ContainingSymbol).ContainingType.OriginalDefinition; - string ruleId = null; + string? ruleId = null; foreach (var argument in objectCreation.Arguments) { if (argument.Parameter.Name.Equals(DiagnosticIdParameterName, StringComparison.OrdinalIgnoreCase)) @@ -367,7 +368,7 @@ ConcurrentBag UpdateLocationsFactory(string analyzerName, ConcurrentBa Debug.Assert(additionalTextOpt != null); var foundMatch = false; - static bool ShouldValidateRange((string prefix, int start, int end) range) + static bool ShouldValidateRange((string? prefix, int start, int end) range) => range.start >= 0 && range.end >= 0; // Check if ID matches any one of the required ranges. @@ -379,7 +380,7 @@ static bool ShouldValidateRange((string prefix, int start, int end) range) { if (ShouldValidateRange(allowedIds)) { - var suffix = ruleId.Substring(allowedIds.prefix.Length); + var suffix = ruleId.Substring(allowedIds.prefix!.Length); if (int.TryParse(suffix, out int ruleIdInt) && ruleIdInt >= allowedIds.start && ruleIdInt <= allowedIds.end) @@ -400,7 +401,7 @@ static bool ShouldValidateRange((string prefix, int start, int end) range) { // Diagnostic Id '{0}' belonging to category '{1}' is not in the required range and/or format '{2}' specified in the file '{3}'. string arg1 = ruleId; - string arg2 = categoryOpt; + string arg2 = categoryOpt!; string arg3 = string.Empty; foreach (var range in allowedIdsInfoListOpt) { @@ -412,7 +413,7 @@ static bool ShouldValidateRange((string prefix, int start, int end) range) arg3 += !ShouldValidateRange(range) ? range.prefix + "XXXX" : $"{range.prefix}{range.start}-{range.prefix}{range.end}"; } - string arg4 = Path.GetFileName(additionalTextOpt.Path); + string arg4 = Path.GetFileName(additionalTextOpt!.Path); var diagnostic = Diagnostic.Create(DiagnosticIdMustBeInSpecifiedFormatRule, argument.Value.Syntax.GetLocation(), arg1, arg2, arg3, arg4); operationAnalysisContext.ReportDiagnostic(diagnostic); } @@ -434,9 +435,9 @@ static bool ShouldValidateRange((string prefix, int start, int end) range) private static bool TryGetCategoryAndAllowedIdsMap( ImmutableArray additionalFiles, CancellationToken cancellationToken, - out AdditionalText additionalText, - out ImmutableDictionary> categoryAndAllowedIdsMap, - out List invalidFileDiagnostics) + [NotNullWhen(returnValue: true)] out AdditionalText? additionalText, + [NotNullWhen(returnValue: true)] out ImmutableDictionary>? categoryAndAllowedIdsMap, + out List? invalidFileDiagnostics) { invalidFileDiagnostics = null; categoryAndAllowedIdsMap = null; @@ -448,7 +449,7 @@ static bool ShouldValidateRange((string prefix, int start, int end) range) TryParseCategoryAndAllowedIdsInfoFile(additionalText, cancellationToken, out categoryAndAllowedIdsMap, out invalidFileDiagnostics); } - private static AdditionalText TryGetCategoryAndAllowedIdsInfoFile(ImmutableArray additionalFiles, CancellationToken cancellationToken) + private static AdditionalText? TryGetCategoryAndAllowedIdsInfoFile(ImmutableArray additionalFiles, CancellationToken cancellationToken) { StringComparer comparer = StringComparer.Ordinal; foreach (AdditionalText textFile in additionalFiles) @@ -468,8 +469,8 @@ private static AdditionalText TryGetCategoryAndAllowedIdsInfoFile(ImmutableArray private static bool TryParseCategoryAndAllowedIdsInfoFile( AdditionalText additionalText, CancellationToken cancellationToken, - out ImmutableDictionary> categoryAndAllowedIdsInfoMap, - out List invalidFileDiagnostics) + [NotNullWhen(returnValue: true)] out ImmutableDictionary>? categoryAndAllowedIdsInfoMap, + out List? invalidFileDiagnostics) { // Parse the additional file with allowed diagnostic categories and corresponding ID range. // FORMAT: @@ -478,7 +479,7 @@ private static AdditionalText TryGetCategoryAndAllowedIdsInfoFile(ImmutableArray categoryAndAllowedIdsInfoMap = null; invalidFileDiagnostics = null; - var builder = ImmutableDictionary.CreateBuilder>(); + var builder = ImmutableDictionary.CreateBuilder>(); var lines = additionalText.GetText(cancellationToken).Lines; foreach (var line in lines) { @@ -516,10 +517,10 @@ private static AdditionalText TryGetCategoryAndAllowedIdsInfoFile(ImmutableArray // 'Category': Comma separate list of 'StartId-EndId' or 'Id' or 'Prefix' var ranges = parts[1].Split(','); - var infoList = ImmutableArray.CreateBuilder<(string prefix, int start, int end)>(ranges.Length); + var infoList = ImmutableArray.CreateBuilder<(string? prefix, int start, int end)>(ranges.Length); for (int i = 0; i < ranges.Length; i++) { - (string prefix, int start, int end) allowedIdsInfo = s_defaultAllowedIdsInfo; + (string? prefix, int start, int end) allowedIdsInfo = s_defaultAllowedIdsInfo; string range = ranges[i].Trim(); if (!range.Contains('-')) { diff --git a/src/Microsoft.CodeAnalysis.Analyzers/Core/MetaAnalyzers/EnableConcurrentExecutionAnalyzer.cs b/src/Microsoft.CodeAnalysis.Analyzers/Core/MetaAnalyzers/EnableConcurrentExecutionAnalyzer.cs index f0fbf74e17..8870bf4b9e 100644 --- a/src/Microsoft.CodeAnalysis.Analyzers/Core/MetaAnalyzers/EnableConcurrentExecutionAnalyzer.cs +++ b/src/Microsoft.CodeAnalysis.Analyzers/Core/MetaAnalyzers/EnableConcurrentExecutionAnalyzer.cs @@ -39,7 +39,7 @@ public override void Initialize(AnalysisContext context) } [SuppressMessage("AnalyzerPerformance", "RS1012:Start action has no registered actions.", Justification = "Method returns an analyzer that is registered by the caller.")] - protected override DiagnosticAnalyzerSymbolAnalyzer GetDiagnosticAnalyzerSymbolAnalyzer(CompilationStartAnalysisContext compilationContext, INamedTypeSymbol diagnosticAnalyzer, INamedTypeSymbol diagnosticAnalyzerAttribute) + protected override DiagnosticAnalyzerSymbolAnalyzer? GetDiagnosticAnalyzerSymbolAnalyzer(CompilationStartAnalysisContext compilationContext, INamedTypeSymbol diagnosticAnalyzer, INamedTypeSymbol diagnosticAnalyzerAttribute) { var compilation = compilationContext.Compilation; @@ -62,7 +62,7 @@ protected override DiagnosticAnalyzerSymbolAnalyzer GetDiagnosticAnalyzerSymbolA return; } - IParameterSymbol analysisContextParameter = null; + IParameterSymbol? analysisContextParameter = null; foreach (var parameter in method.Parameters) { if (!Equals(parameter.Type, analysisContext)) diff --git a/src/Microsoft.CodeAnalysis.Analyzers/Core/MetaAnalyzers/RegisterActionAnalyzer.cs b/src/Microsoft.CodeAnalysis.Analyzers/Core/MetaAnalyzers/RegisterActionAnalyzer.cs index 1c63d764d6..46962224d5 100644 --- a/src/Microsoft.CodeAnalysis.Analyzers/Core/MetaAnalyzers/RegisterActionAnalyzer.cs +++ b/src/Microsoft.CodeAnalysis.Analyzers/Core/MetaAnalyzers/RegisterActionAnalyzer.cs @@ -4,6 +4,7 @@ using System.Collections.Generic; using System.Collections.Immutable; using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; using System.Linq; using System.Threading; using Analyzer.Utilities; @@ -117,35 +118,35 @@ public abstract class RegisterActionAnalyzer /// Map from declared analysis context type parameters to invocations of Register methods on them. /// - private Dictionary> _nestedActionsMap; + private Dictionary>? _nestedActionsMap; /// /// Set of declared start analysis context parameters that need to be analyzed for and . /// - private HashSet _declaredStartAnalysisContextParams; + private HashSet? _declaredStartAnalysisContextParams; /// /// Set of declared start analysis context parameters that need to be skipped for and . /// This is to avoid false positives where context types are passed as arguments to a different invocation, and hence the registration responsibility is not on the current method. /// - private HashSet _startAnalysisContextParamsToSkip; + private HashSet? _startAnalysisContextParamsToSkip; protected RegisterActionCodeBlockAnalyzer( INamedTypeSymbol analysisContext, @@ -231,10 +232,10 @@ private struct NodeAndSymbol _startAnalysisContextParamsToSkip = null; } - protected abstract IEnumerable GetArgumentExpressions(TInvocationExpressionSyntax invocation); + protected abstract IEnumerable? GetArgumentExpressions(TInvocationExpressionSyntax invocation); protected abstract SyntaxNode GetArgumentExpression(TArgumentSyntax argument); protected abstract SyntaxNode GetInvocationExpression(TInvocationExpressionSyntax invocation); - protected abstract SyntaxNode GetInvocationReceiver(TInvocationExpressionSyntax invocation); + protected abstract SyntaxNode? GetInvocationReceiver(TInvocationExpressionSyntax invocation); protected abstract bool IsSyntaxKind(ITypeSymbol type); protected abstract TLanguageKindEnum InvocationExpressionKind { get; } protected abstract TLanguageKindEnum ArgumentSyntaxKind { get; } @@ -266,7 +267,7 @@ internal void CodeBlockStartAction(CodeBlockStartAnalysisContext arguments = GetArgumentExpressions(invocation); + IEnumerable? arguments = GetArgumentExpressions(invocation); if (arguments != null) { int argumentCount = arguments.Count(); @@ -385,7 +386,7 @@ private void AnalyzeInvocation(SyntaxNodeAnalysisContext context) if (method.TypeParameters.Length > 0 && (isRegisterSyntaxNodeAction || isRegisterCodeBlockStartAction)) { - ITypeSymbol typeArgument = null; + ITypeSymbol? typeArgument = null; if (method.TypeParameters.Length == 1) { if (method.TypeParameters[0].Name == TLanguageKindEnumName) @@ -469,7 +470,7 @@ private void NoteRegisterActionInvocation(IMethodSymbol method, TInvocationExpre return; } - SyntaxNode receiver = GetInvocationReceiver(invocation); + SyntaxNode? receiver = GetInvocationReceiver(invocation); if (receiver == null) { return; diff --git a/src/Microsoft.CodeAnalysis.Analyzers/Core/MetaAnalyzers/ReportDiagnosticAnalyzer.cs b/src/Microsoft.CodeAnalysis.Analyzers/Core/MetaAnalyzers/ReportDiagnosticAnalyzer.cs index f70bf8d2c4..fc06cfe9b7 100644 --- a/src/Microsoft.CodeAnalysis.Analyzers/Core/MetaAnalyzers/ReportDiagnosticAnalyzer.cs +++ b/src/Microsoft.CodeAnalysis.Analyzers/Core/MetaAnalyzers/ReportDiagnosticAnalyzer.cs @@ -35,65 +35,65 @@ public abstract class ReportDiagnosticAnalyzer SupportedDiagnostics => ImmutableArray.Create(InvalidReportDiagnosticRule); [SuppressMessage("AnalyzerPerformance", "RS1012:Start action has no registered actions.", Justification = "Method returns an analyzer that is registered by the caller.")] - protected override DiagnosticAnalyzerSymbolAnalyzer GetDiagnosticAnalyzerSymbolAnalyzer(CompilationStartAnalysisContext compilationContext, INamedTypeSymbol diagnosticAnalyzer, INamedTypeSymbol diagnosticAnalyzerAttribute) + protected override DiagnosticAnalyzerSymbolAnalyzer? GetDiagnosticAnalyzerSymbolAnalyzer(CompilationStartAnalysisContext compilationContext, INamedTypeSymbol diagnosticAnalyzer, INamedTypeSymbol diagnosticAnalyzerAttribute) { Compilation compilation = compilationContext.Compilation; - INamedTypeSymbol compilationEndAnalysisContext = compilation.GetOrCreateTypeByMetadataName(CompilationEndAnalysisContextFullName); + INamedTypeSymbol? compilationEndAnalysisContext = compilation.GetOrCreateTypeByMetadataName(CompilationEndAnalysisContextFullName); if (compilationEndAnalysisContext == null) { return null; } - INamedTypeSymbol codeBlockAnalysisContext = compilation.GetOrCreateTypeByMetadataName(CodeBlockAnalysisContextFullName); + INamedTypeSymbol? codeBlockAnalysisContext = compilation.GetOrCreateTypeByMetadataName(CodeBlockAnalysisContextFullName); if (codeBlockAnalysisContext == null) { return null; } - INamedTypeSymbol operationBlockAnalysisContext = compilation.GetOrCreateTypeByMetadataName(OperationBlockAnalysisContextFullName); + INamedTypeSymbol? operationBlockAnalysisContext = compilation.GetOrCreateTypeByMetadataName(OperationBlockAnalysisContextFullName); if (operationBlockAnalysisContext == null) { return null; } - INamedTypeSymbol operationAnalysisContext = compilation.GetOrCreateTypeByMetadataName(OperationAnalysisContextFullName); + INamedTypeSymbol? operationAnalysisContext = compilation.GetOrCreateTypeByMetadataName(OperationAnalysisContextFullName); if (operationAnalysisContext == null) { return null; } - INamedTypeSymbol semanticModelAnalysisContext = compilation.GetOrCreateTypeByMetadataName(SemanticModelAnalysisContextFullName); + INamedTypeSymbol? semanticModelAnalysisContext = compilation.GetOrCreateTypeByMetadataName(SemanticModelAnalysisContextFullName); if (semanticModelAnalysisContext == null) { return null; } - INamedTypeSymbol symbolAnalysisContext = compilation.GetOrCreateTypeByMetadataName(SymbolAnalysisContextFullName); + INamedTypeSymbol? symbolAnalysisContext = compilation.GetOrCreateTypeByMetadataName(SymbolAnalysisContextFullName); if (symbolAnalysisContext == null) { return null; } - INamedTypeSymbol syntaxNodeAnalysisContext = compilation.GetOrCreateTypeByMetadataName(SyntaxNodeAnalysisContextFullName); + INamedTypeSymbol? syntaxNodeAnalysisContext = compilation.GetOrCreateTypeByMetadataName(SyntaxNodeAnalysisContextFullName); if (syntaxNodeAnalysisContext == null) { return null; } - INamedTypeSymbol syntaxTreeAnalysisContext = compilation.GetOrCreateTypeByMetadataName(SyntaxTreeAnalysisContextFullName); + INamedTypeSymbol? syntaxTreeAnalysisContext = compilation.GetOrCreateTypeByMetadataName(SyntaxTreeAnalysisContextFullName); if (syntaxTreeAnalysisContext == null) { return null; } - INamedTypeSymbol diagnosticType = compilation.GetOrCreateTypeByMetadataName(DiagnosticFullName); + INamedTypeSymbol? diagnosticType = compilation.GetOrCreateTypeByMetadataName(DiagnosticFullName); if (diagnosticType == null) { return null; } - INamedTypeSymbol diagnosticDescriptorType = compilation.GetOrCreateTypeByMetadataName(DiagnosticDescriptorFullName); + INamedTypeSymbol? diagnosticDescriptorType = compilation.GetOrCreateTypeByMetadataName(DiagnosticDescriptorFullName); if (diagnosticDescriptorType == null) { return null; @@ -124,7 +124,7 @@ public ReportDiagnosticCompilationAnalyzer(ImmutableHashSet co _supportedDescriptorFieldsMap = ImmutableDictionary>.Empty; } - protected abstract IEnumerable GetArgumentExpressions(TInvocationExpressionSyntax invocation); + protected abstract IEnumerable? GetArgumentExpressions(TInvocationExpressionSyntax invocation); protected virtual SyntaxNode GetPropertyGetterBlockSyntax(SyntaxNode declaringSyntaxRefNode) { return declaringSyntaxRefNode; @@ -203,8 +203,8 @@ protected override void AnalyzeNode(SymbolAnalysisContext symbolContext, TInvoca return; } - IEnumerable arguments = GetArgumentExpressions(invocation); - if (arguments.HasExactly(1)) + IEnumerable? arguments = GetArgumentExpressions(invocation); + if (arguments?.HasExactly(1) == true) { SyntaxNode argument = arguments.First(); ITypeSymbol type = semanticModel.GetTypeInfo(argument, symbolContext.CancellationToken).ConvertedType; @@ -213,7 +213,7 @@ protected override void AnalyzeNode(SymbolAnalysisContext symbolContext, TInvoca ISymbol argSymbol = semanticModel.GetSymbolInfo(argument, symbolContext.CancellationToken).Symbol; if (argSymbol != null) { - SyntaxNode diagnosticInitializerOpt = null; + SyntaxNode? diagnosticInitializerOpt = null; if (argSymbol is ILocalSymbol local) { From 73aaa1b11988d43d77be8d85c3a9caf63fd66062 Mon Sep 17 00:00:00 2001 From: Manish Vasani Date: Thu, 7 Nov 2019 12:58:43 -0800 Subject: [PATCH 07/28] Nullable annotations for BannedApiAnalyzers --- .../Core/RestrictedInternalsVisibleToAnalyzer.cs | 6 +++--- .../Core/SymbolIsBannedAnalyzer.cs | 13 +++++++------ 2 files changed, 10 insertions(+), 9 deletions(-) diff --git a/src/Microsoft.CodeAnalysis.BannedApiAnalyzers/Core/RestrictedInternalsVisibleToAnalyzer.cs b/src/Microsoft.CodeAnalysis.BannedApiAnalyzers/Core/RestrictedInternalsVisibleToAnalyzer.cs index 1b030a97e4..3a4d574957 100644 --- a/src/Microsoft.CodeAnalysis.BannedApiAnalyzers/Core/RestrictedInternalsVisibleToAnalyzer.cs +++ b/src/Microsoft.CodeAnalysis.BannedApiAnalyzers/Core/RestrictedInternalsVisibleToAnalyzer.cs @@ -176,7 +176,7 @@ private void OnCompilationStart(CompilationStartAnalysisContext compilationConte } private static void VerifySymbol( - ISymbol symbol, + ISymbol? symbol, SyntaxNode node, Action reportDiagnostic, ImmutableDictionary> restrictedInternalsVisibleToMap, @@ -235,8 +235,8 @@ private void OnCompilationStart(CompilationStartAnalysisContext compilationConte } private static void MarkIsBanned( - INamespaceSymbol startNamespace, - INamespaceSymbol uptoNamespace, + INamespaceSymbol? startNamespace, + INamespaceSymbol? uptoNamespace, ConcurrentDictionary namespaceToIsBannedMap, bool banned) { diff --git a/src/Microsoft.CodeAnalysis.BannedApiAnalyzers/Core/SymbolIsBannedAnalyzer.cs b/src/Microsoft.CodeAnalysis.BannedApiAnalyzers/Core/SymbolIsBannedAnalyzer.cs index ae4dc0aa16..42aac01ae5 100644 --- a/src/Microsoft.CodeAnalysis.BannedApiAnalyzers/Core/SymbolIsBannedAnalyzer.cs +++ b/src/Microsoft.CodeAnalysis.BannedApiAnalyzers/Core/SymbolIsBannedAnalyzer.cs @@ -176,7 +176,7 @@ private void OnCompilationStart(CompilationStartAnalysisContext compilationConte return; - Dictionary ReadBannedApis() + Dictionary? ReadBannedApis() { var query = from additionalFile in compilationContext.Options.AdditionalFiles @@ -253,7 +253,7 @@ void VerifyAttributes(Action reportDiagnostic, ImmutableArray reportDiagnostic, ITypeSymbol type, SyntaxNode syntaxNode) + bool VerifyType(Action reportDiagnostic, ITypeSymbol? type, SyntaxNode syntaxNode) { do { @@ -261,13 +261,14 @@ bool VerifyType(Action reportDiagnostic, ITypeSymbol type, SyntaxNod { return false; } + if (type == null) { // Type will be null for arrays and pointers. return true; } - if (entryBySymbol.TryGetValue(type, out var entry)) + if (entryBySymbol!.TryGetValue(type, out var entry)) { reportDiagnostic( Diagnostic.Create( @@ -285,7 +286,7 @@ bool VerifyType(Action reportDiagnostic, ITypeSymbol type, SyntaxNod return true; } - bool VerifyTypeArguments(Action reportDiagnostic, ITypeSymbol type, SyntaxNode syntaxNode, out ITypeSymbol originalDefinition) + bool VerifyTypeArguments(Action reportDiagnostic, ITypeSymbol? type, SyntaxNode syntaxNode, out ITypeSymbol? originalDefinition) { switch (type) { @@ -311,7 +312,7 @@ bool VerifyTypeArguments(Action reportDiagnostic, ITypeSymbol type, return VerifyType(reportDiagnostic, pointerTypeSymbol.PointedAtType, syntaxNode); default: - originalDefinition = type.OriginalDefinition; + originalDefinition = type?.OriginalDefinition; break; } @@ -323,7 +324,7 @@ void VerifySymbol(Action reportDiagnostic, ISymbol symbol, SyntaxNod { symbol = symbol.OriginalDefinition; - if (entryBySymbol.TryGetValue(symbol, out var entry)) + if (entryBySymbol!.TryGetValue(symbol, out var entry)) { reportDiagnostic( Diagnostic.Create( From bb439cb5a6808dcb290f346be848f835bc8a1f58 Mon Sep 17 00:00:00 2001 From: Manish Vasani Date: Thu, 7 Nov 2019 13:02:45 -0800 Subject: [PATCH 08/28] Nullable annotations for PublicApiAnalyzers --- .../Core/Analyzers/DeclarePublicApiAnalyzer.Impl.cs | 6 +++--- .../Core/Analyzers/DeclarePublicApiAnalyzer.cs | 9 +++++++-- .../Core/CodeFixes/DeclarePublicApiFix.cs | 5 +++-- 3 files changed, 13 insertions(+), 7 deletions(-) diff --git a/src/PublicApiAnalyzers/Core/Analyzers/DeclarePublicApiAnalyzer.Impl.cs b/src/PublicApiAnalyzers/Core/Analyzers/DeclarePublicApiAnalyzer.Impl.cs index c6f50f7da5..96ce829198 100644 --- a/src/PublicApiAnalyzers/Core/Analyzers/DeclarePublicApiAnalyzer.Impl.cs +++ b/src/PublicApiAnalyzers/Core/Analyzers/DeclarePublicApiAnalyzer.Impl.cs @@ -142,7 +142,7 @@ private void CheckPropertyAccessor(SymbolAnalysisContext symbolContext, IMethodS /// Action called to actually report a diagnostic. /// A location to report the diagnostics for a symbol at. If null, then /// the location of the symbol will be used. - private void OnSymbolActionCore(ISymbol symbol, Action reportDiagnostic, Location explicitLocation = null) + private void OnSymbolActionCore(ISymbol symbol, Action reportDiagnostic, Location? explicitLocation = null) { if (!IsPublicAPI(symbol)) { @@ -173,7 +173,7 @@ private void OnSymbolActionCore(ISymbol symbol, Action reportDiagnos /// If the symbol is an implicitly declared constructor. /// A location to report the diagnostics for a symbol at. If null, then /// the location of the symbol will be used. - private void OnSymbolActionCore(ISymbol symbol, Action reportDiagnostic, bool isImplicitlyDeclaredConstructor, Location explicitLocation = null) + private void OnSymbolActionCore(ISymbol symbol, Action reportDiagnostic, bool isImplicitlyDeclaredConstructor, Location? explicitLocation = null) { Debug.Assert(IsPublicAPI(symbol)); @@ -420,7 +420,7 @@ private string GetPublicApiName(ISymbol symbol) { string publicApiName = symbol.ToDisplayString(s_publicApiFormat); - ITypeSymbol memberType = null; + ITypeSymbol? memberType = null; if (symbol is IMethodSymbol) { memberType = ((IMethodSymbol)symbol).ReturnType; diff --git a/src/PublicApiAnalyzers/Core/Analyzers/DeclarePublicApiAnalyzer.cs b/src/PublicApiAnalyzers/Core/Analyzers/DeclarePublicApiAnalyzer.cs index 97ad443a79..f288a4f3e6 100644 --- a/src/PublicApiAnalyzers/Core/Analyzers/DeclarePublicApiAnalyzer.cs +++ b/src/PublicApiAnalyzers/Core/Analyzers/DeclarePublicApiAnalyzer.cs @@ -3,6 +3,7 @@ using System; using System.Collections.Generic; using System.Collections.Immutable; +using System.Diagnostics.CodeAnalysis; using System.IO; using System.Threading; using Analyzer.Utilities; @@ -211,7 +212,7 @@ private static ApiData ReadApiData(string path, SourceText sourceText, bool isSh private static bool TryGetApiData(ImmutableArray additionalTexts, CancellationToken cancellationToken, out ApiData shippedData, out ApiData unshippedData) { - if (!TryGetApiText(additionalTexts, cancellationToken, out AdditionalText shippedText, out AdditionalText unshippedText)) + if (!TryGetApiText(additionalTexts, cancellationToken, out var shippedText, out var unshippedText)) { shippedData = default; unshippedData = default; @@ -223,7 +224,11 @@ private static bool TryGetApiData(ImmutableArray additionalTexts return true; } - private static bool TryGetApiText(ImmutableArray additionalTexts, CancellationToken cancellationToken, out AdditionalText shippedText, out AdditionalText unshippedText) + private static bool TryGetApiText( + ImmutableArray additionalTexts, + CancellationToken cancellationToken, + [NotNullWhen(returnValue: true)] out AdditionalText? shippedText, + [NotNullWhen(returnValue: true)] out AdditionalText? unshippedText) { shippedText = null; unshippedText = null; diff --git a/src/PublicApiAnalyzers/Core/CodeFixes/DeclarePublicApiFix.cs b/src/PublicApiAnalyzers/Core/CodeFixes/DeclarePublicApiFix.cs index 9fcecc0a0d..8ebcaec9fd 100644 --- a/src/PublicApiAnalyzers/Core/CodeFixes/DeclarePublicApiFix.cs +++ b/src/PublicApiAnalyzers/Core/CodeFixes/DeclarePublicApiFix.cs @@ -257,11 +257,11 @@ protected override async Task GetChangedSolutionAsync(CancellationToke private class PublicSurfaceAreaFixAllProvider : FixAllProvider { - public override async Task GetFixAsync(FixAllContext fixAllContext) + public override async Task GetFixAsync(FixAllContext fixAllContext) { var diagnosticsToFix = new List>>(); string titleFormat = "Add all items in {0} {1} to the public API"; - string title = null; + string title; switch (fixAllContext.Scope) { @@ -297,6 +297,7 @@ public override async Task GetFixAsync(FixAllContext fixAllContext) case FixAllScope.Custom: return null; default: + title = titleFormat; break; } From 6f36f66bacbf4c44e735b15bdc476c77083a8fe0 Mon Sep 17 00:00:00 2001 From: Manish Vasani Date: Thu, 7 Nov 2019 13:08:21 -0800 Subject: [PATCH 09/28] Disable nullable for MetaCompilation.Analyzers --- src/MetaCompilation.Analyzers/Core/CodeFixProvider.cs | 2 ++ src/MetaCompilation.Analyzers/Core/DiagnosticAnalyzer.cs | 2 ++ 2 files changed, 4 insertions(+) diff --git a/src/MetaCompilation.Analyzers/Core/CodeFixProvider.cs b/src/MetaCompilation.Analyzers/Core/CodeFixProvider.cs index 6a676486ec..0d79102262 100644 --- a/src/MetaCompilation.Analyzers/Core/CodeFixProvider.cs +++ b/src/MetaCompilation.Analyzers/Core/CodeFixProvider.cs @@ -1,5 +1,7 @@ // Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. +#nullable disable + using System; using System.Collections.Generic; using System.Collections.Immutable; diff --git a/src/MetaCompilation.Analyzers/Core/DiagnosticAnalyzer.cs b/src/MetaCompilation.Analyzers/Core/DiagnosticAnalyzer.cs index 7c7977b168..924567a909 100644 --- a/src/MetaCompilation.Analyzers/Core/DiagnosticAnalyzer.cs +++ b/src/MetaCompilation.Analyzers/Core/DiagnosticAnalyzer.cs @@ -1,5 +1,7 @@ // Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. +#nullable disable + using System.Collections.Generic; using System.Collections.Immutable; using System.Linq; From e1afae9039b3fd1784301c7e6d9a4fe7a42de755 Mon Sep 17 00:00:00 2001 From: Manish Vasani Date: Thu, 7 Nov 2019 13:15:22 -0800 Subject: [PATCH 10/28] Nullable annotations for PerformanceSensitiveAnalyzers --- .../CallSiteImplicitAllocationAnalyzer.cs | 2 +- .../CSharp/DisplayClassAllocationAnalyzer.cs | 4 +- .../TypeConversionAllocationAnalyzer.cs | 71 ++++++++----------- 3 files changed, 32 insertions(+), 45 deletions(-) diff --git a/src/PerformanceSensitiveAnalyzers/CSharp/CallSiteImplicitAllocationAnalyzer.cs b/src/PerformanceSensitiveAnalyzers/CSharp/CallSiteImplicitAllocationAnalyzer.cs index e67408ae6c..7adf33735d 100644 --- a/src/PerformanceSensitiveAnalyzers/CSharp/CallSiteImplicitAllocationAnalyzer.cs +++ b/src/PerformanceSensitiveAnalyzers/CSharp/CallSiteImplicitAllocationAnalyzer.cs @@ -53,7 +53,7 @@ protected override void AnalyzeNode(SyntaxNodeAnalysisContext context, in Perfor Action reportDiagnostic = context.ReportDiagnostic; var cancellationToken = context.CancellationToken; - var invocationExpression = node as InvocationExpressionSyntax; + var invocationExpression = (InvocationExpressionSyntax)node; if (semanticModel.GetSymbolInfo(invocationExpression, cancellationToken).Symbol is IMethodSymbol methodInfo) { diff --git a/src/PerformanceSensitiveAnalyzers/CSharp/DisplayClassAllocationAnalyzer.cs b/src/PerformanceSensitiveAnalyzers/CSharp/DisplayClassAllocationAnalyzer.cs index 10ea3d596d..445faba3fc 100644 --- a/src/PerformanceSensitiveAnalyzers/CSharp/DisplayClassAllocationAnalyzer.cs +++ b/src/PerformanceSensitiveAnalyzers/CSharp/DisplayClassAllocationAnalyzer.cs @@ -90,14 +90,14 @@ protected override void AnalyzeNode(SyntaxNodeAnalysisContext context, in Perfor } } - private static void ClosureCaptureDataFlowAnalysis(DataFlowAnalysis flow, Action reportDiagnostic, Location location) + private static void ClosureCaptureDataFlowAnalysis(DataFlowAnalysis? flow, Action reportDiagnostic, Location location) { if (flow?.Captured.Length <= 0) { return; } - foreach (var capture in flow.Captured) + foreach (var capture in flow!.Captured) { if (capture.Name != null && capture.Locations != null) { diff --git a/src/PerformanceSensitiveAnalyzers/CSharp/TypeConversionAllocationAnalyzer.cs b/src/PerformanceSensitiveAnalyzers/CSharp/TypeConversionAllocationAnalyzer.cs index 8182db852d..699945d524 100644 --- a/src/PerformanceSensitiveAnalyzers/CSharp/TypeConversionAllocationAnalyzer.cs +++ b/src/PerformanceSensitiveAnalyzers/CSharp/TypeConversionAllocationAnalyzer.cs @@ -93,72 +93,71 @@ protected override void AnalyzeNode(SyntaxNodeAnalysisContext context, in Perfor // this.fooObjCall(10); // new myobject(10); - if (node is ArgumentSyntax) + if (node is ArgumentSyntax argumentSyntax) { - ArgumentSyntaxCheck(node, semanticModel, assignedToReadonlyFieldOrProperty, reportDiagnostic, cancellationToken); + ArgumentSyntaxCheck(argumentSyntax, semanticModel, assignedToReadonlyFieldOrProperty, reportDiagnostic, cancellationToken); } // object foo { get { return 0; } } - if (node is ReturnStatementSyntax) + if (node is ReturnStatementSyntax returnStatementSyntax) { - ReturnStatementExpressionCheck(node, semanticModel, reportDiagnostic, cancellationToken); + ReturnStatementExpressionCheck(returnStatementSyntax, semanticModel, reportDiagnostic, cancellationToken); return; } // yield return 0 - if (node is YieldStatementSyntax) + if (node is YieldStatementSyntax yieldStatementSyntax) { - YieldReturnStatementExpressionCheck(node, semanticModel, reportDiagnostic, cancellationToken); + YieldReturnStatementExpressionCheck(yieldStatementSyntax, semanticModel, reportDiagnostic, cancellationToken); return; } // object a = x ?? 0; // var a = 10 as object; - if (node is BinaryExpressionSyntax) + if (node is BinaryExpressionSyntax binaryExpressionSyntax) { - BinaryExpressionCheck(node, semanticModel, assignedToReadonlyFieldOrProperty, reportDiagnostic, cancellationToken); + BinaryExpressionCheck(binaryExpressionSyntax, semanticModel, assignedToReadonlyFieldOrProperty, reportDiagnostic, cancellationToken); return; } // for (object i = 0;;) - if (node is EqualsValueClauseSyntax) + if (node is EqualsValueClauseSyntax equalsValueClauseSyntax) { - EqualsValueClauseCheck(node, semanticModel, assignedToReadonlyFieldOrProperty, reportDiagnostic, cancellationToken); + EqualsValueClauseCheck(equalsValueClauseSyntax, semanticModel, assignedToReadonlyFieldOrProperty, reportDiagnostic, cancellationToken); return; } // object = true ? 0 : obj - if (node is ConditionalExpressionSyntax) + if (node is ConditionalExpressionSyntax conditionalExpressionSyntax) { - ConditionalExpressionCheck(node, semanticModel, reportDiagnostic, cancellationToken); + ConditionalExpressionCheck(conditionalExpressionSyntax, semanticModel, reportDiagnostic, cancellationToken); return; } // string a = $"{1}"; - if (node is InterpolationSyntax) + if (node is InterpolationSyntax interpolationSyntax) { - InterpolationCheck(node, semanticModel, reportDiagnostic, cancellationToken); + InterpolationCheck(interpolationSyntax, semanticModel, reportDiagnostic, cancellationToken); return; } // var f = (object) - if (node is CastExpressionSyntax) + if (node is CastExpressionSyntax castExpressionSyntax) { - CastExpressionCheck(node, semanticModel, reportDiagnostic, cancellationToken); + CastExpressionCheck(castExpressionSyntax, semanticModel, reportDiagnostic, cancellationToken); return; } // object Foo => 1 - if (node is ArrowExpressionClauseSyntax) + if (node is ArrowExpressionClauseSyntax arrowExpressionClauseSyntax) { - ArrowExpressionCheck(node, semanticModel, reportDiagnostic, cancellationToken); + ArrowExpressionCheck(arrowExpressionClauseSyntax, semanticModel, reportDiagnostic, cancellationToken); return; } } - private static void ReturnStatementExpressionCheck(SyntaxNode node, SemanticModel semanticModel, Action reportDiagnostic, CancellationToken cancellationToken) + private static void ReturnStatementExpressionCheck(ReturnStatementSyntax returnStatementExpression, SemanticModel semanticModel, Action reportDiagnostic, CancellationToken cancellationToken) { - var returnStatementExpression = node as ReturnStatementSyntax; if (returnStatementExpression.Expression != null) { var returnConversionInfo = semanticModel.GetConversion(returnStatementExpression.Expression, cancellationToken); @@ -166,9 +165,8 @@ private static void ReturnStatementExpressionCheck(SyntaxNode node, SemanticMode } } - private static void YieldReturnStatementExpressionCheck(SyntaxNode node, SemanticModel semanticModel, Action reportDiagnostic, CancellationToken cancellationToken) + private static void YieldReturnStatementExpressionCheck(YieldStatementSyntax yieldExpression, SemanticModel semanticModel, Action reportDiagnostic, CancellationToken cancellationToken) { - var yieldExpression = node as YieldStatementSyntax; if (yieldExpression.Expression != null) { var returnConversionInfo = semanticModel.GetConversion(yieldExpression.Expression, cancellationToken); @@ -176,9 +174,8 @@ private static void YieldReturnStatementExpressionCheck(SyntaxNode node, Semanti } } - private static void ArgumentSyntaxCheck(SyntaxNode node, SemanticModel semanticModel, bool isAssignmentToReadonly, Action reportDiagnostic, CancellationToken cancellationToken) + private static void ArgumentSyntaxCheck(ArgumentSyntax argument, SemanticModel semanticModel, bool isAssignmentToReadonly, Action reportDiagnostic, CancellationToken cancellationToken) { - var argument = node as ArgumentSyntax; if (argument.Expression != null) { var argumentTypeInfo = semanticModel.GetTypeInfo(argument.Expression, cancellationToken); @@ -188,10 +185,8 @@ private static void ArgumentSyntaxCheck(SyntaxNode node, SemanticModel semanticM } } - private static void BinaryExpressionCheck(SyntaxNode node, SemanticModel semanticModel, bool isAssignmentToReadonly, Action reportDiagnostic, CancellationToken cancellationToken) + private static void BinaryExpressionCheck(BinaryExpressionSyntax binaryExpression, SemanticModel semanticModel, bool isAssignmentToReadonly, Action reportDiagnostic, CancellationToken cancellationToken) { - var binaryExpression = node as BinaryExpressionSyntax; - // as expression if (binaryExpression.IsKind(SyntaxKind.AsExpression) && binaryExpression.Left != null && binaryExpression.Right != null) { @@ -216,9 +211,8 @@ private static void BinaryExpressionCheck(SyntaxNode node, SemanticModel semanti } } - private static void InterpolationCheck(SyntaxNode node, SemanticModel semanticModel, Action reportDiagnostic, CancellationToken cancellationToken) + private static void InterpolationCheck(InterpolationSyntax interpolation, SemanticModel semanticModel, Action reportDiagnostic, CancellationToken cancellationToken) { - var interpolation = node as InterpolationSyntax; var typeInfo = semanticModel.GetTypeInfo(interpolation.Expression, cancellationToken); if (typeInfo.Type?.IsValueType == true) { @@ -226,9 +220,8 @@ private static void InterpolationCheck(SyntaxNode node, SemanticModel semanticMo } } - private static void CastExpressionCheck(SyntaxNode node, SemanticModel semanticModel, Action reportDiagnostic, CancellationToken cancellationToken) + private static void CastExpressionCheck(CastExpressionSyntax castExpression, SemanticModel semanticModel, Action reportDiagnostic, CancellationToken cancellationToken) { - var castExpression = node as CastExpressionSyntax; if (castExpression.Expression != null) { var castTypeInfo = semanticModel.GetTypeInfo(castExpression, cancellationToken); @@ -241,10 +234,8 @@ private static void CastExpressionCheck(SyntaxNode node, SemanticModel semanticM } } - private static void ConditionalExpressionCheck(SyntaxNode node, SemanticModel semanticModel, Action reportDiagnostic, CancellationToken cancellationToken) + private static void ConditionalExpressionCheck(ConditionalExpressionSyntax conditionalExpression, SemanticModel semanticModel, Action reportDiagnostic, CancellationToken cancellationToken) { - var conditionalExpression = node as ConditionalExpressionSyntax; - var trueExp = conditionalExpression.WhenTrue; var falseExp = conditionalExpression.WhenFalse; @@ -259,9 +250,8 @@ private static void ConditionalExpressionCheck(SyntaxNode node, SemanticModel se } } - private static void EqualsValueClauseCheck(SyntaxNode node, SemanticModel semanticModel, bool isAssignmentToReadonly, Action reportDiagnostic, CancellationToken cancellationToken) + private static void EqualsValueClauseCheck(EqualsValueClauseSyntax initializer, SemanticModel semanticModel, bool isAssignmentToReadonly, Action reportDiagnostic, CancellationToken cancellationToken) { - var initializer = node as EqualsValueClauseSyntax; if (initializer.Value != null) { var typeInfo = semanticModel.GetTypeInfo(initializer.Value, cancellationToken); @@ -272,10 +262,8 @@ private static void EqualsValueClauseCheck(SyntaxNode node, SemanticModel semant } - private static void ArrowExpressionCheck(SyntaxNode node, SemanticModel semanticModel, Action reportDiagnostic, CancellationToken cancellationToken) + private static void ArrowExpressionCheck(ArrowExpressionClauseSyntax syntax, SemanticModel semanticModel, Action reportDiagnostic, CancellationToken cancellationToken) { - var syntax = node as ArrowExpressionClauseSyntax; - var typeInfo = semanticModel.GetTypeInfo(syntax.Expression, cancellationToken); var conversionInfo = semanticModel.GetConversion(syntax.Expression, cancellationToken); CheckTypeConversion(conversionInfo, reportDiagnostic, syntax.Expression.GetLocation()); @@ -315,7 +303,7 @@ private static void CheckDelegateCreation(SyntaxNode node, TypeInfo typeInfo, Se } else if (node.IsKind(SyntaxKind.SimpleMemberAccessExpression)) { - var memberAccess = node as MemberAccessExpressionSyntax; + var memberAccess = (MemberAccessExpressionSyntax)node!; if (semanticModel.GetSymbolInfo(memberAccess.Name, cancellationToken).Symbol is IMethodSymbol) { if (isAssignmentToReadonly) @@ -328,9 +316,8 @@ private static void CheckDelegateCreation(SyntaxNode node, TypeInfo typeInfo, Se } } } - else if (node is ArrowExpressionClauseSyntax) + else if (node is ArrowExpressionClauseSyntax arrowClause) { - var arrowClause = node as ArrowExpressionClauseSyntax; if (semanticModel.GetSymbolInfo(arrowClause.Expression, cancellationToken).Symbol is IMethodSymbol) { reportDiagnostic(Diagnostic.Create(MethodGroupAllocationRule, location, EmptyMessageArgs)); From 669b7730fd5112f1ed2daf5564bf553666840ae2 Mon Sep 17 00:00:00 2001 From: Manish Vasani Date: Thu, 7 Nov 2019 14:40:41 -0800 Subject: [PATCH 11/28] Nullable annotation for internal flow analysis utilties --- ...meterValidationDataFlowOperationVisitor.cs | 15 +++-- .../PropertySetAnalysis/ConstructorMapper.cs | 3 + .../HazardousUsageEvaluator.cs | 3 + .../HazardousUsageEvaluatorCollection.cs | 4 +- .../PropertySetAnalysis/PropertyMapper.cs | 3 + .../PropertyMapperCollection.cs | 3 + .../PropertySetAbstractValue.cs | 7 ++- ...Analysis.PropertySetAbstractValueDomain.cs | 6 -- ...wOperationVisitor.TrackedAssignmentData.cs | 4 +- ...sis.PropertySetDataFlowOperationVisitor.cs | 56 ++++++++++++------- .../PropertySetCallbacks.cs | 8 +-- .../PooledHashSetExtensions.cs | 38 ++++++------- .../TaintedDataAbstractValue.cs | 2 - ...ataAnalysis.TaintedDataOperationVisitor.cs | 35 ++++++------ .../TaintedDataSymbolMap.cs | 5 +- .../TaintedDataSymbolMapExtensions.cs | 13 +++-- 16 files changed, 113 insertions(+), 92 deletions(-) diff --git a/src/Utilities/FlowAnalysis/FlowAnalysis/Analysis/ParameterValidationAnalysis/ParameterValidationAnalysis.ParameterValidationDataFlowOperationVisitor.cs b/src/Utilities/FlowAnalysis/FlowAnalysis/Analysis/ParameterValidationAnalysis/ParameterValidationAnalysis.ParameterValidationDataFlowOperationVisitor.cs index 18978a782f..990df51c0d 100644 --- a/src/Utilities/FlowAnalysis/FlowAnalysis/Analysis/ParameterValidationAnalysis/ParameterValidationAnalysis.ParameterValidationDataFlowOperationVisitor.cs +++ b/src/Utilities/FlowAnalysis/FlowAnalysis/Analysis/ParameterValidationAnalysis/ParameterValidationAnalysis.ParameterValidationDataFlowOperationVisitor.cs @@ -5,7 +5,6 @@ using System.Collections.Immutable; using System.Diagnostics; using System.Linq; -using Analyzer.Utilities; using Analyzer.Utilities.Extensions; using Microsoft.CodeAnalysis.FlowAnalysis.DataFlow.PointsToAnalysis; using Microsoft.CodeAnalysis.Operations; @@ -22,7 +21,7 @@ internal partial class ParameterValidationAnalysis : ForwardDataFlowAnalysis { - private readonly ImmutableDictionary.Builder _hazardousParameterUsageBuilderOpt; + private readonly ImmutableDictionary.Builder? _hazardousParameterUsageBuilderOpt; public ParameterValidationDataFlowOperationVisitor(ParameterValidationAnalysisContext analysisContext) : base(analysisContext) @@ -41,7 +40,7 @@ public ParameterValidationDataFlowOperationVisitor(ParameterValidationAnalysisCo get { Debug.Assert(_hazardousParameterUsageBuilderOpt != null); - return _hazardousParameterUsageBuilderOpt.ToImmutable(); + return _hazardousParameterUsageBuilderOpt!.ToImmutable(); } } @@ -184,8 +183,8 @@ private void HandleHazardousOperation(SyntaxNode syntaxNode, IEnumerable EqualsHelper(value1, value2); #region Visit overrides - public override ParameterValidationAbstractValue Visit(IOperation operation, object argument) + public override ParameterValidationAbstractValue Visit(IOperation operation, object? argument) { var value = base.Visit(operation, argument); if (operation != null) @@ -234,7 +233,7 @@ public override ParameterValidationAbstractValue VisitObjectCreation(IObjectCrea public override ParameterValidationAbstractValue VisitInvocation_NonLambdaOrDelegateOrLocalFunction( IMethodSymbol targetMethod, - IOperation visitedInstance, + IOperation? visitedInstance, ImmutableArray visitedArguments, bool invokedAsDelegate, IOperation originalOperation, @@ -319,7 +318,7 @@ private void ProcessRegularInvocationOrCreation(IMethodSymbol targetMethod, Immu var notValidatedLocations = GetNotValidatedLocations(argument); foreach (var location in notValidatedLocations) { - var parameter = (IParameterSymbol)location.SymbolOpt; + var parameter = (IParameterSymbol)location.SymbolOpt!; if (hazardousParameterUsagesInInvokedMethod.ContainsKey(parameter)) { HandlePotentiallyHazardousOperation(argument, notValidatedLocations); diff --git a/src/Utilities/FlowAnalysis/FlowAnalysis/Analysis/PropertySetAnalysis/ConstructorMapper.cs b/src/Utilities/FlowAnalysis/FlowAnalysis/Analysis/PropertySetAnalysis/ConstructorMapper.cs index 2327b9991d..55ac8c1032 100644 --- a/src/Utilities/FlowAnalysis/FlowAnalysis/Analysis/PropertySetAnalysis/ConstructorMapper.cs +++ b/src/Utilities/FlowAnalysis/FlowAnalysis/Analysis/PropertySetAnalysis/ConstructorMapper.cs @@ -1,5 +1,8 @@ // Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. +// TODO(dotpaul): Enable nullable analysis. +#nullable disable + using System; using System.Collections.Generic; using System.Collections.Immutable; diff --git a/src/Utilities/FlowAnalysis/FlowAnalysis/Analysis/PropertySetAnalysis/HazardousUsageEvaluator.cs b/src/Utilities/FlowAnalysis/FlowAnalysis/Analysis/PropertySetAnalysis/HazardousUsageEvaluator.cs index 2a29057815..6224dadb83 100644 --- a/src/Utilities/FlowAnalysis/FlowAnalysis/Analysis/PropertySetAnalysis/HazardousUsageEvaluator.cs +++ b/src/Utilities/FlowAnalysis/FlowAnalysis/Analysis/PropertySetAnalysis/HazardousUsageEvaluator.cs @@ -1,5 +1,8 @@ // Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. +// TODO(dotpaul): Enable nullable analysis. +#nullable disable + using System; using Microsoft.CodeAnalysis; diff --git a/src/Utilities/FlowAnalysis/FlowAnalysis/Analysis/PropertySetAnalysis/HazardousUsageEvaluatorCollection.cs b/src/Utilities/FlowAnalysis/FlowAnalysis/Analysis/PropertySetAnalysis/HazardousUsageEvaluatorCollection.cs index 6e681ea5d3..a9d9c30661 100644 --- a/src/Utilities/FlowAnalysis/FlowAnalysis/Analysis/PropertySetAnalysis/HazardousUsageEvaluatorCollection.cs +++ b/src/Utilities/FlowAnalysis/FlowAnalysis/Analysis/PropertySetAnalysis/HazardousUsageEvaluatorCollection.cs @@ -1,12 +1,14 @@ // Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. +// TODO(dotpaul): Enable nullable analysis. +#nullable disable + using System; using System.Collections.Generic; using System.Collections.Immutable; using System.Linq; using Analyzer.Utilities.PooledObjects; using Microsoft.CodeAnalysis; -using Microsoft.CodeAnalysis.FlowAnalysis.DataFlow; namespace Analyzer.Utilities.FlowAnalysis.Analysis.PropertySetAnalysis { diff --git a/src/Utilities/FlowAnalysis/FlowAnalysis/Analysis/PropertySetAnalysis/PropertyMapper.cs b/src/Utilities/FlowAnalysis/FlowAnalysis/Analysis/PropertySetAnalysis/PropertyMapper.cs index 05ae46a5ac..7c9aa656b8 100644 --- a/src/Utilities/FlowAnalysis/FlowAnalysis/Analysis/PropertySetAnalysis/PropertyMapper.cs +++ b/src/Utilities/FlowAnalysis/FlowAnalysis/Analysis/PropertySetAnalysis/PropertyMapper.cs @@ -1,5 +1,8 @@ // Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. +// TODO(dotpaul): Enable nullable analysis. +#nullable disable + using System; using Microsoft.CodeAnalysis.FlowAnalysis.DataFlow.PointsToAnalysis; using Microsoft.CodeAnalysis.FlowAnalysis.DataFlow.ValueContentAnalysis; diff --git a/src/Utilities/FlowAnalysis/FlowAnalysis/Analysis/PropertySetAnalysis/PropertyMapperCollection.cs b/src/Utilities/FlowAnalysis/FlowAnalysis/Analysis/PropertySetAnalysis/PropertyMapperCollection.cs index 876ef73d9a..483bc2e220 100644 --- a/src/Utilities/FlowAnalysis/FlowAnalysis/Analysis/PropertySetAnalysis/PropertyMapperCollection.cs +++ b/src/Utilities/FlowAnalysis/FlowAnalysis/Analysis/PropertySetAnalysis/PropertyMapperCollection.cs @@ -1,5 +1,8 @@ // Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. +// TODO(dotpaul): Enable nullable analysis. +#nullable disable + using System; using System.Linq; using System.Collections.Generic; diff --git a/src/Utilities/FlowAnalysis/FlowAnalysis/Analysis/PropertySetAnalysis/PropertySetAbstractValue.cs b/src/Utilities/FlowAnalysis/FlowAnalysis/Analysis/PropertySetAnalysis/PropertySetAbstractValue.cs index faaf8a66b0..c4ec259698 100644 --- a/src/Utilities/FlowAnalysis/FlowAnalysis/Analysis/PropertySetAnalysis/PropertySetAbstractValue.cs +++ b/src/Utilities/FlowAnalysis/FlowAnalysis/Analysis/PropertySetAnalysis/PropertySetAbstractValue.cs @@ -4,6 +4,7 @@ using System.Collections.Generic; using System.Collections.Immutable; using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; using Analyzer.Utilities.PooledObjects; namespace Analyzer.Utilities.FlowAnalysis.Analysis.PropertySetAnalysis @@ -40,7 +41,7 @@ public static PropertySetAbstractValue GetInstance(PropertySetAbstractValueKind public static PropertySetAbstractValue GetInstance(ArrayBuilder propertyAbstractValues) { - if (TryGetPooledInstance(propertyAbstractValues, out PropertySetAbstractValue instance)) + if (TryGetPooledInstance(propertyAbstractValues, out PropertySetAbstractValue? instance)) { return instance; } @@ -52,7 +53,7 @@ public static PropertySetAbstractValue GetInstance(ArrayBuilder propertyAbstractValues) { - if (TryGetPooledInstance(propertyAbstractValues, out PropertySetAbstractValue instance)) + if (TryGetPooledInstance(propertyAbstractValues, out PropertySetAbstractValue? instance)) { return instance; } @@ -62,7 +63,7 @@ public static PropertySetAbstractValue GetInstance(ImmutableArray values, out PropertySetAbstractValue instance) + private static bool TryGetPooledInstance(IReadOnlyList values, [NotNullWhen(returnValue: true)] out PropertySetAbstractValue? instance) { if (values.Count == 0) { diff --git a/src/Utilities/FlowAnalysis/FlowAnalysis/Analysis/PropertySetAnalysis/PropertySetAnalysis.PropertySetAbstractValueDomain.cs b/src/Utilities/FlowAnalysis/FlowAnalysis/Analysis/PropertySetAnalysis/PropertySetAnalysis.PropertySetAbstractValueDomain.cs index 9d57d3410b..a531059933 100644 --- a/src/Utilities/FlowAnalysis/FlowAnalysis/Analysis/PropertySetAnalysis/PropertySetAnalysis.PropertySetAbstractValueDomain.cs +++ b/src/Utilities/FlowAnalysis/FlowAnalysis/Analysis/PropertySetAnalysis/PropertySetAnalysis.PropertySetAbstractValueDomain.cs @@ -24,9 +24,6 @@ private class PropertySetAbstractValueDomain : AbstractValueDomain private class TrackedAssignmentData { - public PooledHashSet AssignmentsWithUnknownLocation + public PooledHashSet? AssignmentsWithUnknownLocation { get; private set; } - public PooledDictionary> AbstractLocationsToAssignments + public PooledDictionary>? AbstractLocationsToAssignments { get; private set; diff --git a/src/Utilities/FlowAnalysis/FlowAnalysis/Analysis/PropertySetAnalysis/PropertySetAnalysis.PropertySetDataFlowOperationVisitor.cs b/src/Utilities/FlowAnalysis/FlowAnalysis/Analysis/PropertySetAnalysis/PropertySetAnalysis.PropertySetDataFlowOperationVisitor.cs index 631e3abfe6..26abf5b491 100644 --- a/src/Utilities/FlowAnalysis/FlowAnalysis/Analysis/PropertySetAnalysis/PropertySetAnalysis.PropertySetDataFlowOperationVisitor.cs +++ b/src/Utilities/FlowAnalysis/FlowAnalysis/Analysis/PropertySetAnalysis/PropertySetAnalysis.PropertySetDataFlowOperationVisitor.cs @@ -4,6 +4,7 @@ using System.Collections.Generic; using System.Collections.Immutable; using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; using System.Linq; using Analyzer.Utilities.Extensions; using Analyzer.Utilities.PooledObjects; @@ -41,12 +42,12 @@ private sealed partial class PropertySetDataFlowOperationVisitor : /// /// Mapping of AnalysisEntity (for a field or property of the tracked type) to AbstractLocation(s) to IAssignmentOperation(s) /// - private PooledDictionary TrackedFieldPropertyAssignmentsOpt; + private PooledDictionary? TrackedFieldPropertyAssignmentsOpt; /// /// The types containing the property set we're tracking. /// - private readonly ImmutableHashSet TrackedTypeSymbols; + private readonly ImmutableHashSet TrackedTypeSymbols; public PropertySetDataFlowOperationVisitor(PropertySetAnalysisContext analysisContext) : base(analysisContext) @@ -59,10 +60,10 @@ public PropertySetDataFlowOperationVisitor(PropertySetAnalysisContext analysisCo this._visitedLambdas = ImmutableHashSet.CreateBuilder(); - ImmutableHashSet.Builder builder = ImmutableHashSet.CreateBuilder(); + ImmutableHashSet.Builder builder = ImmutableHashSet.CreateBuilder(); foreach (string typeToTrackMetadataName in analysisContext.TypeToTrackMetadataNames) { - this.WellKnownTypeProvider.TryGetOrCreateTypeByMetadataName(typeToTrackMetadataName, out INamedTypeSymbol trackedTypeSymbol); + this.WellKnownTypeProvider.TryGetOrCreateTypeByMetadataName(typeToTrackMetadataName, out INamedTypeSymbol? trackedTypeSymbol); builder.Add(trackedTypeSymbol); } @@ -213,7 +214,7 @@ public override PropertySetAbstractValue VisitObjectCreation(IObjectCreationOper } else { - if (TryFindNonTrackedTypeHazardousUsageEvaluator(operation.Constructor, operation.Arguments, out HazardousUsageEvaluator hazardousUsageEvaluator, out IOperation propertySetInstance)) + if (TryFindNonTrackedTypeHazardousUsageEvaluator(operation.Constructor, operation.Arguments, out HazardousUsageEvaluator? hazardousUsageEvaluator, out IOperation? propertySetInstance)) { this.EvaluatePotentialHazardousUsage( operation.Syntax, @@ -228,7 +229,7 @@ public override PropertySetAbstractValue VisitObjectCreation(IObjectCreationOper protected override PropertySetAbstractValue VisitAssignmentOperation(IAssignmentOperation operation, object argument) { - PropertySetAbstractValue baseValue = base.VisitAssignmentOperation(operation, argument); + PropertySetAbstractValue? baseValue = base.VisitAssignmentOperation(operation, argument); // If we need to evaluate hazardous usages on initializations, track assignments of properties and fields, so // at the end of the CFG we can figure out which assignment operations to flag. @@ -238,10 +239,10 @@ protected override PropertySetAbstractValue VisitAssignmentOperation(IAssignment || operation.Target.Kind == OperationKind.FieldReference || operation.Target.Kind == OperationKind.FlowCaptureReference)) { - AnalysisEntity targetAnalysisEntity = null; + AnalysisEntity? targetAnalysisEntity = null; if (operation.Target.Kind == OperationKind.FlowCaptureReference) { - if (this.TryUnwrapFlowCaptureReference(operation.Target, out IOperation lValueOperation, OperationKind.PropertyReference, OperationKind.FieldReference)) + if (this.TryUnwrapFlowCaptureReference(operation.Target, out IOperation? lValueOperation, OperationKind.PropertyReference, OperationKind.FieldReference)) { this.AnalysisEntityFactory.TryCreate(lValueOperation, out targetAnalysisEntity); } @@ -285,10 +286,10 @@ protected override PropertySetAbstractValue VisitAssignmentOperation(IAssignment } } - IPropertyReferenceOperation propertyReferenceOperation = operation.Target as IPropertyReferenceOperation; + IPropertyReferenceOperation? propertyReferenceOperation = operation.Target as IPropertyReferenceOperation; if (propertyReferenceOperation == null && operation.Target.Kind == OperationKind.FlowCaptureReference) { - this.TryUnwrapFlowCaptureReference(operation.Target, out IOperation lValue, OperationKind.PropertyReference); + this.TryUnwrapFlowCaptureReference(operation.Target, out IOperation? lValue, OperationKind.PropertyReference); propertyReferenceOperation = lValue as IPropertyReferenceOperation; } @@ -365,12 +366,11 @@ internal void ProcessExitBlock(PropertySetBlockAnalysisResult exitBlockOutput) { this.DataFlowAnalysisContext.HazardousUsageEvaluators.TryGetInitializationHazardousUsageEvaluator( out HazardousUsageEvaluator initializationHazardousUsageEvaluator); - Debug.Assert(initializationHazardousUsageEvaluator != null); foreach (KeyValuePair kvp in this.TrackedFieldPropertyAssignmentsOpt) { - if (!this.DataFlowAnalysisContext.PointsToAnalysisResultOpt.ExitBlockOutput.Data.TryGetValue( + if (!this.DataFlowAnalysisContext.PointsToAnalysisResultOpt!.ExitBlockOutput.Data.TryGetValue( kvp.Key, out PointsToAbstractValue pointsToAbstractValue)) { continue; @@ -410,7 +410,9 @@ internal void ProcessExitBlock(PropertySetBlockAnalysisResult exitBlockOutput) { this.MergeHazardousUsageResult( assignmentOperation.Syntax, +#pragma warning disable CS8625 // Cannot convert null literal to non-nullable reference type. methodSymbol: null, // No method invocation; just evaluating initialization value. +#pragma warning restore CS8625 // Cannot convert null literal to non-nullable reference type. result); } } @@ -434,7 +436,9 @@ internal void ProcessExitBlock(PropertySetBlockAnalysisResult exitBlockOutput) { this.MergeHazardousUsageResult( assignmentOperation.Syntax, +#pragma warning disable CS8625 // Cannot convert null literal to non-nullable reference type. methodSymbol: null, // No method invocation; just evaluating initialization value. +#pragma warning restore CS8625 // Cannot convert null literal to non-nullable reference type. result); } } @@ -466,7 +470,7 @@ internal void ProcessExitBlock(PropertySetBlockAnalysisResult exitBlockOutput) } } - public override PropertySetAbstractValue VisitInvocation_NonLambdaOrDelegateOrLocalFunction(IMethodSymbol method, IOperation visitedInstance, ImmutableArray visitedArguments, bool invokedAsDelegate, IOperation originalOperation, PropertySetAbstractValue defaultValue) + public override PropertySetAbstractValue VisitInvocation_NonLambdaOrDelegateOrLocalFunction(IMethodSymbol method, IOperation? visitedInstance, ImmutableArray visitedArguments, bool invokedAsDelegate, IOperation originalOperation, PropertySetAbstractValue defaultValue) { PropertySetAbstractValue baseValue = base.VisitInvocation_NonLambdaOrDelegateOrLocalFunction(method, visitedInstance, visitedArguments, invokedAsDelegate, originalOperation, defaultValue); @@ -479,7 +483,9 @@ public override PropertySetAbstractValue VisitInvocation_NonLambdaOrDelegateOrLo { this.EvaluatePotentialHazardousUsage( visitedArgument.Value.Syntax, +#pragma warning disable CS8625 // Cannot convert null literal to non-nullable reference type. null, +#pragma warning restore CS8625 // Cannot convert null literal to non-nullable reference type. visitedArgument.Value, (PropertySetAbstractValue abstractValue) => argumentHazardousUsageEvaluator.ValueEvaluator(abstractValue)); } @@ -488,16 +494,18 @@ public override PropertySetAbstractValue VisitInvocation_NonLambdaOrDelegateOrLo // If we have a HazardousUsageEvaluator for a method within the tracked type, // or for a method within a different type. - IOperation propertySetInstance = visitedInstance; + IOperation? propertySetInstance = visitedInstance; if ((visitedInstance != null && this.TrackedTypeSymbols.Any(s => visitedInstance.Type.GetBaseTypesAndThis().Contains(s)) - && this.DataFlowAnalysisContext.HazardousUsageEvaluators.TryGetHazardousUsageEvaluator(method.MetadataName, out HazardousUsageEvaluator hazardousUsageEvaluator)) + && this.DataFlowAnalysisContext.HazardousUsageEvaluators.TryGetHazardousUsageEvaluator(method.MetadataName, out HazardousUsageEvaluator? hazardousUsageEvaluator)) || TryFindNonTrackedTypeHazardousUsageEvaluator(method, visitedArguments, out hazardousUsageEvaluator, out propertySetInstance)) { this.EvaluatePotentialHazardousUsage( originalOperation.Syntax, method, +#pragma warning disable CS8604 // Possible null reference argument. propertySetInstance, +#pragma warning restore CS8604 // Possible null reference argument. (PropertySetAbstractValue abstractValue) => hazardousUsageEvaluator.InvocationEvaluator(method, abstractValue)); } else @@ -515,11 +523,15 @@ public override PropertySetAbstractValue VisitInvocation_NonLambdaOrDelegateOrLo /// IArgumentOperations of this invocation. /// Target evaluator. /// The tracked argument. - bool TryFindNonTrackedTypeHazardousUsageEvaluator(IMethodSymbol method, ImmutableArray visitedArguments, out HazardousUsageEvaluator evaluator, out IOperation instance) + bool TryFindNonTrackedTypeHazardousUsageEvaluator( + IMethodSymbol method, + ImmutableArray visitedArguments, + [NotNullWhen(returnValue: true)] out HazardousUsageEvaluator? evaluator, + [NotNullWhen(returnValue: true)] out IOperation? instance) { evaluator = null; instance = null; - PooledHashSet hazardousUsageTypeNames = null; + PooledHashSet? hazardousUsageTypeNames = null; try { if (!GetNamesOfHazardousUsageTypes(method.ContainingType, out hazardousUsageTypeNames)) @@ -556,7 +568,7 @@ bool TryFindNonTrackedTypeHazardousUsageEvaluator(IMethodSymbol method, Immutabl return false; } - private bool GetNamesOfHazardousUsageTypes(INamedTypeSymbol containingType, out PooledHashSet hazardousUsageTypeNames) + private bool GetNamesOfHazardousUsageTypes(INamedTypeSymbol containingType, [NotNullWhen(returnValue: true)] out PooledHashSet? hazardousUsageTypeNames) { hazardousUsageTypeNames = null; if (this.DataFlowAnalysisContext.HazardousUsageTypesToNames.TryGetValue( @@ -597,7 +609,7 @@ private bool GetNamesOfHazardousUsageTypes(INamedTypeSymbol containingType, out /// IOperation of the tracked type containing the properties to be evaluated. /// Function to evaluate a PropertySetAbstractValue to a HazardousUsageEvaluationResult. /// Optional function to map AbstractLocations to PropertySetAbstractValues. If null, uses this.CurrentAnalysisData. - private void EvaluatePotentialHazardousUsage(SyntaxNode operationSyntax, IMethodSymbol methodSymbol, IOperation propertySetInstance, Func evaluationFunction, Func locationToAbstractValueMapping = null) + private void EvaluatePotentialHazardousUsage(SyntaxNode operationSyntax, IMethodSymbol methodSymbol, IOperation propertySetInstance, Func evaluationFunction, Func? locationToAbstractValueMapping = null) { if (locationToAbstractValueMapping == null) { @@ -660,7 +672,9 @@ protected override void ProcessReturnValue(IOperation? returnValue) { this.EvaluatePotentialHazardousUsage( returnValue.Syntax, +#pragma warning disable CS8625 // Cannot convert null literal to non-nullable reference type. null, +#pragma warning restore CS8625 // Cannot convert null literal to non-nullable reference type. returnValue, (PropertySetAbstractValue abstractValue) => hazardousUsageEvaluator.ValueEvaluator(abstractValue)); } @@ -668,7 +682,7 @@ protected override void ProcessReturnValue(IOperation? returnValue) private void MergeInterproceduralResults(IOperation originalOperation) { - if (!this.TryGetInterproceduralAnalysisResult(originalOperation, out PropertySetAnalysisResult subResult)) + if (!this.TryGetInterproceduralAnalysisResult(originalOperation, out PropertySetAnalysisResult? subResult)) { return; } @@ -703,7 +717,7 @@ private void MergeInterproceduralResults(IOperation originalOperation) /// The found underlying operation, if any. /// Kinds of operations to look for. /// True if found, false otherwise. - private bool TryUnwrapFlowCaptureReference(IOperation flowCaptureReferenceOperation, out IOperation unwrappedOperation, params OperationKind[] kinds) + private bool TryUnwrapFlowCaptureReference(IOperation flowCaptureReferenceOperation, [NotNullWhen(returnValue: true)] out IOperation? unwrappedOperation, params OperationKind[] kinds) { unwrappedOperation = null; if (flowCaptureReferenceOperation != null && flowCaptureReferenceOperation.Kind == OperationKind.FlowCaptureReference) diff --git a/src/Utilities/FlowAnalysis/FlowAnalysis/Analysis/PropertySetAnalysis/PropertySetCallbacks.cs b/src/Utilities/FlowAnalysis/FlowAnalysis/Analysis/PropertySetAnalysis/PropertySetCallbacks.cs index 6d50e440f0..d000c0b363 100644 --- a/src/Utilities/FlowAnalysis/FlowAnalysis/Analysis/PropertySetAnalysis/PropertySetCallbacks.cs +++ b/src/Utilities/FlowAnalysis/FlowAnalysis/Analysis/PropertySetAnalysis/PropertySetCallbacks.cs @@ -1,7 +1,6 @@ // Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System; -using System.Diagnostics; using System.Diagnostics.CodeAnalysis; using System.Linq; using Microsoft.CodeAnalysis; @@ -48,11 +47,8 @@ public static PropertySetAbstractValueKind FlagIfNull(PointsToAbstractValue poin /// public static PropertySetAbstractValueKind EvaluateLiteralValues( ValueContentAbstractValue valueContentAbstractValue, - Func badLiteralValuePredicate) + Func badLiteralValuePredicate) { - Debug.Assert(valueContentAbstractValue != null); - Debug.Assert(badLiteralValuePredicate != null); - switch (valueContentAbstractValue.NonLiteralState) { case ValueContainsNonLiteralState.No: @@ -63,7 +59,7 @@ public static PropertySetAbstractValueKind FlagIfNull(PointsToAbstractValue poin bool allValuesBad = true; bool someValuesBad = false; - foreach (object literalValue in valueContentAbstractValue.LiteralValues) + foreach (object? literalValue in valueContentAbstractValue.LiteralValues) { if (badLiteralValuePredicate(literalValue)) { diff --git a/src/Utilities/FlowAnalysis/FlowAnalysis/Analysis/TaintedDataAnalysis/PooledHashSetExtensions.cs b/src/Utilities/FlowAnalysis/FlowAnalysis/Analysis/TaintedDataAnalysis/PooledHashSetExtensions.cs index c4b20a04ee..0ff5056c2f 100644 --- a/src/Utilities/FlowAnalysis/FlowAnalysis/Analysis/TaintedDataAnalysis/PooledHashSetExtensions.cs +++ b/src/Utilities/FlowAnalysis/FlowAnalysis/Analysis/TaintedDataAnalysis/PooledHashSetExtensions.cs @@ -17,8 +17,8 @@ internal static class PooledHashSetExtensions SinkKind sinkKind, bool isInterface, bool isAnyStringParameterInConstructorASink, - IEnumerable sinkProperties, - IEnumerable<(string Method, string[] Parameters)> sinkMethodParameters) + IEnumerable? sinkProperties, + IEnumerable<(string Method, string[] Parameters)>? sinkMethodParameters) { builder.AddSinkInfo( fullTypeName, @@ -36,8 +36,8 @@ internal static class PooledHashSetExtensions IEnumerable sinkKinds, bool isInterface, bool isAnyStringParameterInConstructorASink, - IEnumerable sinkProperties, - IEnumerable<(string Method, string[] Parameters)> sinkMethodParameters) + IEnumerable? sinkProperties, + IEnumerable<(string Method, string[] Parameters)>? sinkMethodParameters) { SinkInfo sinkInfo = new SinkInfo( fullTypeName, @@ -59,8 +59,8 @@ internal static class PooledHashSetExtensions this PooledHashSet builder, string fullTypeName, bool isInterface, - string[] taintedProperties, - IEnumerable taintedMethods) + string[]? taintedProperties, + IEnumerable? taintedMethods) { SourceInfo metadata = new SourceInfo( fullTypeName, @@ -97,14 +97,14 @@ internal static class PooledHashSetExtensions /// Specify the check functions and tainted targets for methods which need ValueContentAnalysis check. /// public static void AddSourceInfoSpecifyingTaintedTargets( - this PooledHashSet builder, - string fullTypeName, - bool isInterface, - string[] taintedProperties, - IEnumerable<(MethodMatcher methodMatcher, (PointsToCheck pointsToCheck, string taintedTarget)[] pointsToChecksAndTargets)> taintedMethodsNeedsPointsToAnalysis, - IEnumerable<(MethodMatcher methodMatcher, (ValueContentCheck valueContentCheck, string taintedTarget)[] valueContentChecksAndTargets)> taintedMethodsNeedsValueContentAnalysis, - IEnumerable<(MethodMatcher methodMatcher, (string str, string taintedTargets)[] valueContentChecksAndTargets)> transferMethods, - bool taintConstantArray = false) + this PooledHashSet builder, + string fullTypeName, + bool isInterface, + string[]? taintedProperties, + IEnumerable<(MethodMatcher methodMatcher, (PointsToCheck pointsToCheck, string taintedTarget)[] pointsToChecksAndTargets)>? taintedMethodsNeedsPointsToAnalysis, + IEnumerable<(MethodMatcher methodMatcher, (ValueContentCheck valueContentCheck, string taintedTarget)[] valueContentChecksAndTargets)>? taintedMethodsNeedsValueContentAnalysis, + IEnumerable<(MethodMatcher methodMatcher, (string str, string taintedTargets)[] valueContentChecksAndTargets)>? transferMethods, + bool taintConstantArray = false) { SourceInfo metadata = new SourceInfo( fullTypeName, @@ -152,9 +152,9 @@ internal static class PooledHashSetExtensions this PooledHashSet builder, string fullTypeName, bool isInterface, - string[] taintedProperties, - IEnumerable<(MethodMatcher methodMatcher, PointsToCheck[] pointsToChecks)> taintedMethodsNeedsPointsToAnalysis, - IEnumerable<(MethodMatcher methodMatcher, ValueContentCheck[] valueContentChecks)> taintedMethodsNeedsValueContentAnalysis, + string[]? taintedProperties, + IEnumerable<(MethodMatcher methodMatcher, PointsToCheck[] pointsToChecks)>? taintedMethodsNeedsPointsToAnalysis, + IEnumerable<(MethodMatcher methodMatcher, ValueContentCheck[] valueContentChecks)>? taintedMethodsNeedsValueContentAnalysis, bool taintConstantArray = false) { SourceInfo metadata = new SourceInfo( @@ -198,8 +198,8 @@ internal static class PooledHashSetExtensions string fullTypeName, bool isInterface, bool isConstructorSanitizing, - string[] sanitizingMethods, - string[] sanitizingInstanceMethods = null) + string[]? sanitizingMethods, + string[]? sanitizingInstanceMethods = null) { SanitizerInfo info = new SanitizerInfo( fullTypeName, diff --git a/src/Utilities/FlowAnalysis/FlowAnalysis/Analysis/TaintedDataAnalysis/TaintedDataAbstractValue.cs b/src/Utilities/FlowAnalysis/FlowAnalysis/Analysis/TaintedDataAnalysis/TaintedDataAbstractValue.cs index 938bc1a87b..d84047771a 100644 --- a/src/Utilities/FlowAnalysis/FlowAnalysis/Analysis/TaintedDataAnalysis/TaintedDataAbstractValue.cs +++ b/src/Utilities/FlowAnalysis/FlowAnalysis/Analysis/TaintedDataAnalysis/TaintedDataAbstractValue.cs @@ -66,9 +66,7 @@ internal static TaintedDataAbstractValue CreateTainted(ISymbol taintedSymbol, Sy /// Tainted abstract value containing both sets of source origins. internal static TaintedDataAbstractValue MergeTainted(TaintedDataAbstractValue value1, TaintedDataAbstractValue value2) { - Debug.Assert(value1 != null); Debug.Assert(value1.Kind == TaintedDataAbstractValueKind.Tainted); - Debug.Assert(value2 != null); Debug.Assert(value2.Kind == TaintedDataAbstractValueKind.Tainted); return new TaintedDataAbstractValue( diff --git a/src/Utilities/FlowAnalysis/FlowAnalysis/Analysis/TaintedDataAnalysis/TaintedDataAnalysis.TaintedDataOperationVisitor.cs b/src/Utilities/FlowAnalysis/FlowAnalysis/Analysis/TaintedDataAnalysis/TaintedDataAnalysis.TaintedDataOperationVisitor.cs index 987fff5ebf..d35acae70f 100644 --- a/src/Utilities/FlowAnalysis/FlowAnalysis/Analysis/TaintedDataAnalysis/TaintedDataAnalysis.TaintedDataOperationVisitor.cs +++ b/src/Utilities/FlowAnalysis/FlowAnalysis/Analysis/TaintedDataAnalysis/TaintedDataAnalysis.TaintedDataOperationVisitor.cs @@ -4,6 +4,7 @@ using System.Collections.Generic; using System.Collections.Immutable; using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; using System.Linq; using Analyzer.Utilities.Extensions; using Analyzer.Utilities.PooledObjects; @@ -135,7 +136,7 @@ protected override void StopTrackingEntity(AnalysisEntity analysisEntity, Tainte analysisData.RemoveEntries(analysisEntity); } - public override TaintedDataAbstractValue DefaultVisit(IOperation operation, object argument) + public override TaintedDataAbstractValue DefaultVisit(IOperation operation, object? argument) { // This handles most cases of tainted data flowing from child operations to parent operations. // Examples: @@ -143,7 +144,7 @@ public override TaintedDataAbstractValue DefaultVisit(IOperation operation, obje // - adding a tainted value to something makes the result tainted // - instantiating an object with tainted data makes the new object tainted - List taintedValues = null; + List? taintedValues = null; foreach (IOperation childOperation in operation.Children) { TaintedDataAbstractValue childValue = Visit(childOperation, argument); @@ -184,7 +185,7 @@ protected override TaintedDataAbstractValue ComputeAnalysisValueForReferenceOper return TaintedDataAbstractValue.CreateTainted(propertyReferenceOperation.Member, propertyReferenceOperation.Syntax, this.OwningSymbol); } - if (AnalysisEntityFactory.TryCreate(operation, out AnalysisEntity analysisEntity)) + if (AnalysisEntityFactory.TryCreate(operation, out AnalysisEntity? analysisEntity)) { return this.CurrentAnalysisData.TryGetValue(analysisEntity, out TaintedDataAbstractValue value) ? value : defaultValue; } @@ -207,7 +208,7 @@ public override TaintedDataAbstractValue VisitObjectCreation(IObjectCreationOper public override TaintedDataAbstractValue VisitInvocation_NonLambdaOrDelegateOrLocalFunction( IMethodSymbol method, - IOperation visitedInstance, + IOperation? visitedInstance, ImmutableArray visitedArguments, bool invokedAsDelegate, IOperation originalOperation, @@ -228,8 +229,8 @@ public override TaintedDataAbstractValue VisitObjectCreation(IObjectCreationOper ProcessTaintedDataEnteringInvocationOrCreation(method, taintedArguments, originalOperation); } - PooledHashSet taintedTargets = null; - PooledHashSet<(string, string)> taintedParameterPairs = null; + PooledHashSet? taintedTargets = null; + PooledHashSet<(string, string)>? taintedParameterPairs = null; try { if (this.IsSanitizingMethod(method)) @@ -244,8 +245,8 @@ public override TaintedDataAbstractValue VisitObjectCreation(IObjectCreationOper else if (this.DataFlowAnalysisContext.SourceInfos.IsSourceMethod( method, visitedArguments, - new Lazy(() => DataFlowAnalysisContext.PointsToAnalysisResultOpt), - new Lazy(() => DataFlowAnalysisContext.ValueContentAnalysisResultOpt), + new Lazy(() => DataFlowAnalysisContext.PointsToAnalysisResultOpt), + new Lazy(() => DataFlowAnalysisContext.ValueContentAnalysisResultOpt), out taintedTargets)) { foreach (string taintedTarget in taintedTargets) @@ -349,7 +350,7 @@ public override TaintedDataAbstractValue VisitInvocation_LocalFunction(IMethodSy // See HttpRequest_Form_Array_List_Diagnostic and HttpRequest_Form_List_Diagnostic tests. public override TaintedDataAbstractValue VisitArrayInitializer(IArrayInitializerOperation operation, object argument) { - HashSet sourceOrigins = null; + HashSet? sourceOrigins = null; TaintedDataAbstractValue baseAbstractValue = base.VisitArrayInitializer(operation, argument); if (baseAbstractValue.Kind == TaintedDataAbstractValueKind.Tainted) { @@ -365,13 +366,13 @@ public override TaintedDataAbstractValue VisitArrayInitializer(IArrayInitializer taintedAbstractValues = taintedAbstractValues.Concat(baseAbstractValue); } - TaintedDataAbstractValue result = null; + TaintedDataAbstractValue? result = null; if (taintedAbstractValues.Any()) { result = TaintedDataAbstractValue.MergeTainted(taintedAbstractValues); } - IArrayCreationOperation arrayCreationOperation = operation.GetAncestor(OperationKind.ArrayCreation); + IArrayCreationOperation? arrayCreationOperation = operation.GetAncestor(OperationKind.ArrayCreation); if (arrayCreationOperation?.Type is IArrayTypeSymbol arrayTypeSymbol && this.DataFlowAnalysisContext.SourceInfos.IsSourceConstantArrayOfType(arrayTypeSymbol) && operation.ElementValues.All(s => GetValueContentAbstractValue(s).IsLiteralState)) @@ -430,7 +431,7 @@ private void TrackTaintedDataEnteringSink(SymbolAccess sink, IEnumerable taintedArguments, IOperation originalOperation) { - if (this.IsMethodArgumentASink(targetMethod, taintedArguments, out HashSet sinkKinds)) + if (this.IsMethodArgumentASink(targetMethod, taintedArguments, out HashSet? sinkKinds)) { foreach (IArgumentOperation taintedArgument in taintedArguments) { @@ -439,7 +440,7 @@ private void TrackTaintedDataEnteringSink(SymbolAccess sink, IEnumerable sinkKinds)) + && this.IsPropertyASink(propertyReferenceOperation, out HashSet? sinkKinds)) { this.TrackTaintedDataEnteringSink( propertyReferenceOperation.Member, @@ -522,7 +523,7 @@ private bool IsSanitizingInstanceMethod(IMethodSymbol method) /// Method being invoked. /// Arguments passed to the method invocation that are tainted. /// True if any of the tainted data arguments enters a sink, false otherwise. - private bool IsMethodArgumentASink(IMethodSymbol method, IEnumerable taintedArguments, out HashSet sinkKinds) + private bool IsMethodArgumentASink(IMethodSymbol method, IEnumerable taintedArguments, [NotNullWhen(returnValue: true)] out HashSet? sinkKinds) { sinkKinds = null; @@ -569,7 +570,7 @@ private bool IsMethodArgumentASink(IMethodSymbol method, IEnumerableProperty to check if it's a sink. /// If the property is a sink, containing the kinds of sinks; null otherwise. /// True if the property is a sink, false otherwise. - private bool IsPropertyASink(IPropertyReferenceOperation propertyReferenceOperation, out HashSet sinkKinds) + private bool IsPropertyASink(IPropertyReferenceOperation propertyReferenceOperation, [NotNullWhen(returnValue: true)] out HashSet? sinkKinds) { Lazy> lazySinkKinds = new Lazy>(() => new HashSet()); foreach (SinkInfo sinkInfo in this.DataFlowAnalysisContext.SinkInfos.GetInfosForType(propertyReferenceOperation.Member.ContainingType)) @@ -608,7 +609,7 @@ private IEnumerable GetTaintedArguments(ImmutableArray GetInfosForType(INamedTypeSymbol namedTypeSymbol) } } - public bool Equals(TaintedDataSymbolMap other) + public bool Equals(TaintedDataSymbolMap? other) { if (Object.ReferenceEquals(this, other)) { diff --git a/src/Utilities/FlowAnalysis/FlowAnalysis/Analysis/TaintedDataAnalysis/TaintedDataSymbolMapExtensions.cs b/src/Utilities/FlowAnalysis/FlowAnalysis/Analysis/TaintedDataAnalysis/TaintedDataSymbolMapExtensions.cs index 9665a138d6..b25f1678d2 100644 --- a/src/Utilities/FlowAnalysis/FlowAnalysis/Analysis/TaintedDataAnalysis/TaintedDataSymbolMapExtensions.cs +++ b/src/Utilities/FlowAnalysis/FlowAnalysis/Analysis/TaintedDataAnalysis/TaintedDataSymbolMapExtensions.cs @@ -3,6 +3,7 @@ using System; using System.Collections.Generic; using System.Collections.Immutable; +using System.Diagnostics.CodeAnalysis; using System.Linq; using Analyzer.Utilities.PooledObjects; using Microsoft.CodeAnalysis; @@ -31,9 +32,9 @@ internal static class TaintedDataSymbolMapExtensions this TaintedDataSymbolMap sourceSymbolMap, IMethodSymbol method, ImmutableArray arguments, - Lazy pointsToAnalysisResult, - Lazy valueContentAnalysisResult, - out PooledHashSet allTaintedTargets) + Lazy pointsToAnalysisResult, + Lazy valueContentAnalysisResult, + [NotNullWhen(returnValue: true)] out PooledHashSet? allTaintedTargets) { allTaintedTargets = null; foreach (SourceInfo sourceInfo in sourceSymbolMap.GetInfosForType(method.ContainingType)) @@ -58,7 +59,9 @@ internal static class TaintedDataSymbolMapExtensions IEnumerable<(PointsToCheck, string target)> positivePointsToTaintedTargets = pointsToTaintedTargets.Where(s => s.pointsToCheck( arguments.Select(o => +#pragma warning disable CS8602 // Dereference of a possibly null reference. pointsToAnalysisResult.Value[o.Kind, o.Syntax]).ToImmutableArray())); +#pragma warning restore CS8602 // Dereference of a possibly null reference. if (positivePointsToTaintedTargets != null) { if (allTaintedTargets == null) @@ -78,8 +81,10 @@ internal static class TaintedDataSymbolMapExtensions IEnumerable<(ValueContentCheck, string target)> positiveValueContentTaintedTargets = valueContentTaintedTargets.Where(s => s.valueContentCheck( arguments.Select(o => +#pragma warning disable CS8602 // Dereference of a possibly null reference. pointsToAnalysisResult.Value[o.Kind, o.Syntax]).ToImmutableArray(), arguments.Select(o => valueContentAnalysisResult.Value[o.Kind, o.Syntax]).ToImmutableArray())); +#pragma warning restore CS8602 // Dereference of a possibly null reference. if (positiveValueContentTaintedTargets != null) { if (allTaintedTargets == null) @@ -150,7 +155,7 @@ public static bool IsSourceConstantArrayOfType(this TaintedDataSymbolMap arguments, ImmutableArray taintedParameterNames, - out PooledHashSet<(string, string)> taintedParameterPairs) + [NotNullWhen(returnValue: true)] out PooledHashSet<(string, string)>? taintedParameterPairs) { taintedParameterPairs = null; foreach (SourceInfo sourceInfo in sourceSymbolMap.GetInfosForType(method.ContainingType)) From 1c344c2a5e4d8563430d497144a5c525a6f6c027 Mon Sep 17 00:00:00 2001 From: Manish Vasani Date: Thu, 7 Nov 2019 14:45:43 -0800 Subject: [PATCH 12/28] Nullable annotations for Microsoft.CodeQuality.Analyzers --- ...ExceptionsInUnexpectedLocationsAnalyzer.cs | 2 +- .../CSharpEnumStorageShouldBeInt32.Fixer.cs | 5 ++- ...arpPassSystemUriObjectsInsteadOfStrings.cs | 2 +- .../CSharpStaticHolderTypes.Fixer.cs | 2 +- .../CSharpMarkMembersAsStatic.Fixer.cs | 4 +-- ...CSharpUseLiteralsWhereAppropriate.Fixer.cs | 4 +-- ...actTypesShouldNotHaveConstructors.Fixer.cs | 6 ++-- .../AbstractTypesShouldNotHaveConstructors.cs | 2 +- ...CancellationTokenParametersMustComeLast.cs | 2 +- .../CollectionPropertiesShouldBeReadOnly.cs | 12 +++---- ...lectionsShouldImplementGenericInterface.cs | 32 +++++++++---------- .../DefineAccessorsForAttributeArguments.cs | 2 +- .../DoNotDirectlyAwaitATask.cs | 23 ++++++++----- ...NotRaiseExceptionsInUnexpectedLocations.cs | 16 +++++----- .../EnumStorageShouldBeInt32.Fixer.cs | 6 +++- .../EnumStorageShouldBeInt32.cs | 2 +- .../EnumWithFlagsAttribute.Fixer.cs | 8 +++-- .../EnumWithFlagsAttribute.cs | 2 -- .../EnumsShouldHavePluralNames.cs | 2 +- .../EnumsShouldHaveZeroValue.Fixer.cs | 11 ++++--- .../EnumsShouldHaveZeroValue.cs | 2 +- .../EquatableAnalyzer.Fixer.cs | 2 +- .../ApiDesignGuidelines/EquatableAnalyzer.cs | 4 +-- .../ExceptionsShouldBePublic.cs | 2 +- .../Helpers/EnumHelpers.cs | 1 - .../IdentifiersShouldDifferByMoreThanCase.cs | 6 ++-- .../IdentifiersShouldHaveCorrectPrefix.cs | 2 +- .../IdentifiersShouldNotContainUnderscores.cs | 4 +-- .../ImplementIDisposableCorrectly.cs | 14 ++++---- ...mentStandardExceptionConstructors.Fixer.cs | 5 ++- ...thodsShouldBeCallableByChildTypes.Fixer.cs | 12 +++---- .../MarkAssembliesWithComVisible.cs | 4 +-- .../MarkAttributesWithAttributeUsage.cs | 4 +-- .../NestedTypesShouldNotBeVisible.cs | 17 +++++----- ...ratorOverloadsHaveNamedAlternates.Fixer.cs | 27 ++++++++++------ .../OperatorOverloadsHaveNamedAlternates.cs | 8 ++--- .../OverrideMethodsOnComparableTypes.cs | 14 ++++---- ...arameterNamesShouldMatchBaseDeclaration.cs | 7 +++- .../PassSystemUriObjectsInsteadOfStrings.cs | 10 +++--- .../PropertyNamesShouldNotMatchGetMethods.cs | 2 +- .../ProvideObsoleteAttributeMessage.cs | 2 +- .../TypeNamesShouldNotMatchNamespaces.cs | 4 +-- ...isposableFieldsShouldBeDisposable.Fixer.cs | 2 +- .../UriParametersShouldNotBeStrings.Fixer.cs | 2 +- .../UseEventsWhereAppropriate.cs | 2 +- .../UseGenericEventHandlerInstances.cs | 8 ++--- .../AvoidDeadConditionalCode.cs | 9 +++--- .../AvoidUninstantiatedInternalClasses.cs | 32 +++++++++---------- .../Maintainability/CodeMetricsAnalyzer.cs | 19 +++++------ .../DoNotIgnoreMethodResults.cs | 16 +++++----- .../ReviewUnusedParameters.Fixer.cs | 4 +-- .../Maintainability/ReviewUnusedParameters.cs | 20 ++++++------ .../UseNameofInPlaceOfString.Fixer.cs | 6 +++- .../AbstractRemoveEmptyFinalizers.cs | 4 +-- ...NotCallOverridableMethodsInConstructors.cs | 8 ++--- .../MarkMembersAsStatic.Fixer.cs | 8 ++--- .../QualityGuidelines/MarkMembersAsStatic.cs | 4 +-- .../UseLiteralsWhereAppropriate.Fixer.cs | 2 +- .../UseLiteralsWhereAppropriate.cs | 1 + .../ValidateArgumentsOfPublicMethods.cs | 2 +- 60 files changed, 240 insertions(+), 207 deletions(-) diff --git a/src/Microsoft.CodeQuality.Analyzers/CSharp/ApiDesignGuidelines/CSharpDoNotRaiseExceptionsInUnexpectedLocationsAnalyzer.cs b/src/Microsoft.CodeQuality.Analyzers/CSharp/ApiDesignGuidelines/CSharpDoNotRaiseExceptionsInUnexpectedLocationsAnalyzer.cs index 79fad03f01..bd8579b7d3 100644 --- a/src/Microsoft.CodeQuality.Analyzers/CSharp/ApiDesignGuidelines/CSharpDoNotRaiseExceptionsInUnexpectedLocationsAnalyzer.cs +++ b/src/Microsoft.CodeQuality.Analyzers/CSharp/ApiDesignGuidelines/CSharpDoNotRaiseExceptionsInUnexpectedLocationsAnalyzer.cs @@ -13,7 +13,7 @@ namespace Microsoft.CodeQuality.CSharp.Analyzers.ApiDesignGuidelines [DiagnosticAnalyzer(LanguageNames.CSharp)] public class CSharpDoNotRaiseExceptionsInUnexpectedLocationsAnalyzer : DoNotRaiseExceptionsInUnexpectedLocationsAnalyzer { - protected override bool IsAssignableTo(ITypeSymbol fromSymbol, ITypeSymbol toSymbol, Compilation compilation) + protected override bool IsAssignableTo(ITypeSymbol? fromSymbol, ITypeSymbol? toSymbol, Compilation compilation) { return fromSymbol != null && toSymbol != null && diff --git a/src/Microsoft.CodeQuality.Analyzers/CSharp/ApiDesignGuidelines/CSharpEnumStorageShouldBeInt32.Fixer.cs b/src/Microsoft.CodeQuality.Analyzers/CSharp/ApiDesignGuidelines/CSharpEnumStorageShouldBeInt32.Fixer.cs index 91b8030561..68d838540a 100644 --- a/src/Microsoft.CodeQuality.Analyzers/CSharp/ApiDesignGuidelines/CSharpEnumStorageShouldBeInt32.Fixer.cs +++ b/src/Microsoft.CodeQuality.Analyzers/CSharp/ApiDesignGuidelines/CSharpEnumStorageShouldBeInt32.Fixer.cs @@ -14,11 +14,10 @@ namespace Microsoft.CodeQuality.CSharp.Analyzers.ApiDesignGuidelines [ExportCodeFixProvider(LanguageNames.CSharp), Shared] public sealed class CSharpEnumStorageShouldBeInt32Fixer : EnumStorageShouldBeInt32Fixer { - protected override SyntaxNode GetTargetNode(SyntaxNode node) + protected override SyntaxNode? GetTargetNode(SyntaxNode node) { var enumDecl = (EnumDeclarationSyntax)node; - var baseTypeNode = (enumDecl.BaseList.Types.FirstOrDefault() as SimpleBaseTypeSyntax)?.Type; - return baseTypeNode; + return (enumDecl.BaseList.Types.FirstOrDefault() as SimpleBaseTypeSyntax)?.Type; } } } diff --git a/src/Microsoft.CodeQuality.Analyzers/CSharp/ApiDesignGuidelines/CSharpPassSystemUriObjectsInsteadOfStrings.cs b/src/Microsoft.CodeQuality.Analyzers/CSharp/ApiDesignGuidelines/CSharpPassSystemUriObjectsInsteadOfStrings.cs index 10c2e19216..a50da8bc2f 100644 --- a/src/Microsoft.CodeQuality.Analyzers/CSharp/ApiDesignGuidelines/CSharpPassSystemUriObjectsInsteadOfStrings.cs +++ b/src/Microsoft.CodeQuality.Analyzers/CSharp/ApiDesignGuidelines/CSharpPassSystemUriObjectsInsteadOfStrings.cs @@ -13,7 +13,7 @@ namespace Microsoft.CodeQuality.CSharp.Analyzers.ApiDesignGuidelines [DiagnosticAnalyzer(LanguageNames.CSharp)] public sealed class CSharpPassSystemUriObjectsInsteadOfStringsAnalyzer : PassSystemUriObjectsInsteadOfStringsAnalyzer { - protected override SyntaxNode GetInvocationExpression(SyntaxNode node) + protected override SyntaxNode? GetInvocationExpression(SyntaxNode node) { var invocationNode = node as InvocationExpressionSyntax; return invocationNode?.Expression; diff --git a/src/Microsoft.CodeQuality.Analyzers/CSharp/ApiDesignGuidelines/CSharpStaticHolderTypes.Fixer.cs b/src/Microsoft.CodeQuality.Analyzers/CSharp/ApiDesignGuidelines/CSharpStaticHolderTypes.Fixer.cs index 8d0cf5cd34..0ce195ad22 100644 --- a/src/Microsoft.CodeQuality.Analyzers/CSharp/ApiDesignGuidelines/CSharpStaticHolderTypes.Fixer.cs +++ b/src/Microsoft.CodeQuality.Analyzers/CSharp/ApiDesignGuidelines/CSharpStaticHolderTypes.Fixer.cs @@ -34,7 +34,7 @@ public sealed override async Task RegisterCodeFixesAsync(CodeFixContext context) cancellationToken.ThrowIfCancellationRequested(); SyntaxNode root = await document.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false); - ClassDeclarationSyntax classDeclaration = root.FindToken(span.Start).Parent?.FirstAncestorOrSelf(); + ClassDeclarationSyntax? classDeclaration = root.FindToken(span.Start).Parent?.FirstAncestorOrSelf(); if (classDeclaration != null) { string title = MicrosoftCodeQualityAnalyzersResources.MakeClassStatic; diff --git a/src/Microsoft.CodeQuality.Analyzers/CSharp/QualityGuidelines/CSharpMarkMembersAsStatic.Fixer.cs b/src/Microsoft.CodeQuality.Analyzers/CSharp/QualityGuidelines/CSharpMarkMembersAsStatic.Fixer.cs index a03a91e3a4..d9bd2c13bc 100644 --- a/src/Microsoft.CodeQuality.Analyzers/CSharp/QualityGuidelines/CSharpMarkMembersAsStatic.Fixer.cs +++ b/src/Microsoft.CodeQuality.Analyzers/CSharp/QualityGuidelines/CSharpMarkMembersAsStatic.Fixer.cs @@ -15,10 +15,10 @@ namespace Microsoft.CodeQuality.CSharp.Analyzers.QualityGuidelines [ExportCodeFixProvider(LanguageNames.CSharp), Shared] public sealed class CSharpMarkMembersAsStaticFixer : MarkMembersAsStaticFixer { - protected override IEnumerable GetTypeArguments(SyntaxNode node) + protected override IEnumerable? GetTypeArguments(SyntaxNode node) => (node as GenericNameSyntax)?.TypeArgumentList.Arguments; - protected override SyntaxNode GetExpressionOfInvocation(SyntaxNode invocation) + protected override SyntaxNode? GetExpressionOfInvocation(SyntaxNode invocation) => (invocation as InvocationExpressionSyntax)?.Expression; } } \ No newline at end of file diff --git a/src/Microsoft.CodeQuality.Analyzers/CSharp/QualityGuidelines/CSharpUseLiteralsWhereAppropriate.Fixer.cs b/src/Microsoft.CodeQuality.Analyzers/CSharp/QualityGuidelines/CSharpUseLiteralsWhereAppropriate.Fixer.cs index f60a03cb99..01a27f3c63 100644 --- a/src/Microsoft.CodeQuality.Analyzers/CSharp/QualityGuidelines/CSharpUseLiteralsWhereAppropriate.Fixer.cs +++ b/src/Microsoft.CodeQuality.Analyzers/CSharp/QualityGuidelines/CSharpUseLiteralsWhereAppropriate.Fixer.cs @@ -15,14 +15,14 @@ namespace Microsoft.CodeQuality.CSharp.Analyzers.QualityGuidelines [ExportCodeFixProvider(LanguageNames.CSharp), Shared] public sealed class CSharpUseLiteralsWhereAppropriateFixer : UseLiteralsWhereAppropriateFixer { - protected override SyntaxNode GetFieldDeclaration(SyntaxNode syntaxNode) + protected override SyntaxNode? GetFieldDeclaration(SyntaxNode syntaxNode) { while (syntaxNode != null && !(syntaxNode is FieldDeclarationSyntax)) { syntaxNode = syntaxNode.Parent; } - var field = (FieldDeclarationSyntax)syntaxNode; + var field = syntaxNode as FieldDeclarationSyntax; // Multiple declarators are not supported, as one of them may not be constant. return field?.Declaration.Variables.Count > 1 ? null : field; diff --git a/src/Microsoft.CodeQuality.Analyzers/Core/ApiDesignGuidelines/AbstractTypesShouldNotHaveConstructors.Fixer.cs b/src/Microsoft.CodeQuality.Analyzers/Core/ApiDesignGuidelines/AbstractTypesShouldNotHaveConstructors.Fixer.cs index e43189fd39..572846ab54 100644 --- a/src/Microsoft.CodeQuality.Analyzers/Core/ApiDesignGuidelines/AbstractTypesShouldNotHaveConstructors.Fixer.cs +++ b/src/Microsoft.CodeQuality.Analyzers/Core/ApiDesignGuidelines/AbstractTypesShouldNotHaveConstructors.Fixer.cs @@ -1,12 +1,14 @@ // Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System; +using System.Collections.Generic; using System.Collections.Immutable; using System.Composition; using System.Linq; using System.Threading; using System.Threading.Tasks; using Analyzer.Utilities; +using Analyzer.Utilities.Extensions; using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.CodeFixes; using Microsoft.CodeAnalysis.Editing; @@ -33,7 +35,7 @@ public override async Task RegisterCodeFixesAsync(CodeFixContext context) context.Diagnostics); } - private static SyntaxNode GetDeclaration(ISymbol symbol) + private static SyntaxNode? GetDeclaration(ISymbol symbol) { return (symbol.DeclaringSyntaxReferences.Length > 0) ? symbol.DeclaringSyntaxReferences[0].GetSyntax() : null; } @@ -42,7 +44,7 @@ private static async Task ChangeAccessibilityCodeFix(Document document { SemanticModel model = await document.GetSemanticModelAsync(cancellationToken).ConfigureAwait(false); var classSymbol = (INamedTypeSymbol)model.GetDeclaredSymbol(nodeToFix, cancellationToken); - System.Collections.Generic.List instanceConstructors = classSymbol.InstanceConstructors.Where(t => t.DeclaredAccessibility == Accessibility.Public).Select(t => GetDeclaration(t)).Where(d => d != null).ToList(); + List instanceConstructors = classSymbol.InstanceConstructors.Where(t => t.DeclaredAccessibility == Accessibility.Public).Select(t => GetDeclaration(t)).WhereNotNull().ToList(); SyntaxGenerator generator = SyntaxGenerator.GetGenerator(document); SyntaxNode newRoot = root.ReplaceNodes(instanceConstructors, (original, rewritten) => generator.WithAccessibility(original, Accessibility.Protected)); return document.WithSyntaxRoot(newRoot); diff --git a/src/Microsoft.CodeQuality.Analyzers/Core/ApiDesignGuidelines/AbstractTypesShouldNotHaveConstructors.cs b/src/Microsoft.CodeQuality.Analyzers/Core/ApiDesignGuidelines/AbstractTypesShouldNotHaveConstructors.cs index 850ac136e8..3cf44cb566 100644 --- a/src/Microsoft.CodeQuality.Analyzers/Core/ApiDesignGuidelines/AbstractTypesShouldNotHaveConstructors.cs +++ b/src/Microsoft.CodeQuality.Analyzers/Core/ApiDesignGuidelines/AbstractTypesShouldNotHaveConstructors.cs @@ -42,7 +42,7 @@ public override void Initialize(AnalysisContext context) private static void AnalyzeSymbol(SymbolAnalysisContext context) { - var symbol = context.Symbol as INamedTypeSymbol; + var symbol = (INamedTypeSymbol)context.Symbol; if (symbol.IsAbstract && symbol.MatchesConfiguredVisibility(context.Options, Rule, context.CancellationToken)) { diff --git a/src/Microsoft.CodeQuality.Analyzers/Core/ApiDesignGuidelines/CancellationTokenParametersMustComeLast.cs b/src/Microsoft.CodeQuality.Analyzers/Core/ApiDesignGuidelines/CancellationTokenParametersMustComeLast.cs index 3e8ef8cc4f..46f2990b55 100644 --- a/src/Microsoft.CodeQuality.Analyzers/Core/ApiDesignGuidelines/CancellationTokenParametersMustComeLast.cs +++ b/src/Microsoft.CodeQuality.Analyzers/Core/ApiDesignGuidelines/CancellationTokenParametersMustComeLast.cs @@ -37,7 +37,7 @@ public override void Initialize(AnalysisContext context) context.RegisterCompilationStartAction(compilationContext => { - INamedTypeSymbol cancellationTokenType = compilationContext.Compilation.GetOrCreateTypeByMetadataName(WellKnownTypeNames.SystemThreadingCancellationToken); + INamedTypeSymbol? cancellationTokenType = compilationContext.Compilation.GetOrCreateTypeByMetadataName(WellKnownTypeNames.SystemThreadingCancellationToken); if (cancellationTokenType != null) { compilationContext.RegisterSymbolAction(symbolContext => diff --git a/src/Microsoft.CodeQuality.Analyzers/Core/ApiDesignGuidelines/CollectionPropertiesShouldBeReadOnly.cs b/src/Microsoft.CodeQuality.Analyzers/Core/ApiDesignGuidelines/CollectionPropertiesShouldBeReadOnly.cs index e878e0df8b..cd6d688d8c 100644 --- a/src/Microsoft.CodeQuality.Analyzers/Core/ApiDesignGuidelines/CollectionPropertiesShouldBeReadOnly.cs +++ b/src/Microsoft.CodeQuality.Analyzers/Core/ApiDesignGuidelines/CollectionPropertiesShouldBeReadOnly.cs @@ -57,10 +57,10 @@ public override void Initialize(AnalysisContext analysisContext) analysisContext.RegisterCompilationStartAction( (context) => { - INamedTypeSymbol iCollectionType = context.Compilation.GetOrCreateTypeByMetadataName(WellKnownTypeNames.SystemCollectionsICollection); - INamedTypeSymbol genericICollectionType = context.Compilation.GetOrCreateTypeByMetadataName(WellKnownTypeNames.SystemCollectionsGenericICollection1); - INamedTypeSymbol arrayType = context.Compilation.GetSpecialType(SpecialType.System_Array); - INamedTypeSymbol dataMemberAttribute = context.Compilation.GetOrCreateTypeByMetadataName(WellKnownTypeNames.SystemRuntimeSerializationDataMemberAttribute); + INamedTypeSymbol? iCollectionType = context.Compilation.GetOrCreateTypeByMetadataName(WellKnownTypeNames.SystemCollectionsICollection); + INamedTypeSymbol? genericICollectionType = context.Compilation.GetOrCreateTypeByMetadataName(WellKnownTypeNames.SystemCollectionsGenericICollection1); + INamedTypeSymbol? arrayType = context.Compilation.GetSpecialType(SpecialType.System_Array); + INamedTypeSymbol? dataMemberAttribute = context.Compilation.GetOrCreateTypeByMetadataName(WellKnownTypeNames.SystemRuntimeSerializationDataMemberAttribute); ImmutableHashSet immutableInterfaces = GetIImmutableInterfaces(context.Compilation); if (iCollectionType == null || @@ -79,7 +79,7 @@ public override void Initialize(AnalysisContext analysisContext) INamedTypeSymbol iCollectionType, INamedTypeSymbol genericICollectionType, INamedTypeSymbol arrayType, - INamedTypeSymbol dataMemberAttribute, + INamedTypeSymbol? dataMemberAttribute, ImmutableHashSet immutableInterfaces) { var property = (IPropertySymbol)context.Symbol; @@ -147,7 +147,7 @@ private static ImmutableHashSet GetIImmutableInterfaces(Compil return builder.ToImmutable(); // Local functions. - void AddIfNotNull(INamedTypeSymbol type) + void AddIfNotNull(INamedTypeSymbol? type) { if (type != null) { diff --git a/src/Microsoft.CodeQuality.Analyzers/Core/ApiDesignGuidelines/CollectionsShouldImplementGenericInterface.cs b/src/Microsoft.CodeQuality.Analyzers/Core/ApiDesignGuidelines/CollectionsShouldImplementGenericInterface.cs index fbb7fa68fb..d33140287b 100644 --- a/src/Microsoft.CodeQuality.Analyzers/Core/ApiDesignGuidelines/CollectionsShouldImplementGenericInterface.cs +++ b/src/Microsoft.CodeQuality.Analyzers/Core/ApiDesignGuidelines/CollectionsShouldImplementGenericInterface.cs @@ -58,12 +58,12 @@ public override void Initialize(AnalysisContext analysisContext) analysisContext.RegisterCompilationStartAction( (context) => { - INamedTypeSymbol iCollectionType = context.Compilation.GetOrCreateTypeByMetadataName(WellKnownTypeNames.SystemCollectionsICollection); - INamedTypeSymbol genericICollectionType = context.Compilation.GetOrCreateTypeByMetadataName(WellKnownTypeNames.SystemCollectionsGenericICollection1); - INamedTypeSymbol iEnumerableType = context.Compilation.GetOrCreateTypeByMetadataName(WellKnownTypeNames.SystemCollectionsIEnumerable); - INamedTypeSymbol genericIEnumerableType = context.Compilation.GetOrCreateTypeByMetadataName(WellKnownTypeNames.SystemCollectionsGenericIEnumerable1); - INamedTypeSymbol iListType = context.Compilation.GetOrCreateTypeByMetadataName(WellKnownTypeNames.SystemCollectionsIList); - INamedTypeSymbol genericIListType = context.Compilation.GetOrCreateTypeByMetadataName(WellKnownTypeNames.SystemCollectionsGenericIList1); + INamedTypeSymbol? iCollectionType = context.Compilation.GetOrCreateTypeByMetadataName(WellKnownTypeNames.SystemCollectionsICollection); + INamedTypeSymbol? genericICollectionType = context.Compilation.GetOrCreateTypeByMetadataName(WellKnownTypeNames.SystemCollectionsGenericICollection1); + INamedTypeSymbol? iEnumerableType = context.Compilation.GetOrCreateTypeByMetadataName(WellKnownTypeNames.SystemCollectionsIEnumerable); + INamedTypeSymbol? genericIEnumerableType = context.Compilation.GetOrCreateTypeByMetadataName(WellKnownTypeNames.SystemCollectionsGenericIEnumerable1); + INamedTypeSymbol? iListType = context.Compilation.GetOrCreateTypeByMetadataName(WellKnownTypeNames.SystemCollectionsIList); + INamedTypeSymbol? genericIListType = context.Compilation.GetOrCreateTypeByMetadataName(WellKnownTypeNames.SystemCollectionsGenericIList1); if (iCollectionType == null && genericICollectionType == null && iEnumerableType == null && genericIEnumerableType == null && @@ -82,12 +82,12 @@ public override void Initialize(AnalysisContext analysisContext) private static void AnalyzeSymbol( SymbolAnalysisContext context, - INamedTypeSymbol iCollectionType, - INamedTypeSymbol gCollectionType, - INamedTypeSymbol iEnumerableType, - INamedTypeSymbol gEnumerableType, - INamedTypeSymbol iListType, - INamedTypeSymbol gListType) + INamedTypeSymbol? iCollectionType, + INamedTypeSymbol? gCollectionType, + INamedTypeSymbol? iEnumerableType, + INamedTypeSymbol? gEnumerableType, + INamedTypeSymbol? iListType, + INamedTypeSymbol? gListType) { var namedTypeSymbol = (INamedTypeSymbol)context.Symbol; @@ -127,8 +127,8 @@ public override void Initialize(AnalysisContext analysisContext) } } - INamedTypeSymbol missingInterface; - INamedTypeSymbol implementedInterface; + INamedTypeSymbol? missingInterface; + INamedTypeSymbol? implementedInterface; if (allInterfacesStatus.GenericIListPresent) { // Implemented IList, meaning has all 3 generic interfaces. Nothing can be wrong. @@ -172,8 +172,8 @@ public override void Initialize(AnalysisContext analysisContext) context.ReportDiagnostic(Diagnostic.Create(Rule, namedTypeSymbol.Locations.First(), namedTypeSymbol.Name, - implementedInterface.ToDisplayString(SymbolDisplayFormat.MinimallyQualifiedFormat), - missingInterface.ToDisplayString(SymbolDisplayFormat.MinimallyQualifiedFormat))); + implementedInterface!.ToDisplayString(SymbolDisplayFormat.MinimallyQualifiedFormat), + missingInterface!.ToDisplayString(SymbolDisplayFormat.MinimallyQualifiedFormat))); } #pragma warning disable CA1815 // Override equals and operator equals on value types diff --git a/src/Microsoft.CodeQuality.Analyzers/Core/ApiDesignGuidelines/DefineAccessorsForAttributeArguments.cs b/src/Microsoft.CodeQuality.Analyzers/Core/ApiDesignGuidelines/DefineAccessorsForAttributeArguments.cs index 630ad117fa..81ad342f57 100644 --- a/src/Microsoft.CodeQuality.Analyzers/Core/ApiDesignGuidelines/DefineAccessorsForAttributeArguments.cs +++ b/src/Microsoft.CodeQuality.Analyzers/Core/ApiDesignGuidelines/DefineAccessorsForAttributeArguments.cs @@ -65,7 +65,7 @@ public override void Initialize(AnalysisContext analysisContext) analysisContext.RegisterCompilationStartAction(compilationContext => { - INamedTypeSymbol attributeType = compilationContext.Compilation.GetOrCreateTypeByMetadataName(WellKnownTypeNames.SystemAttribute); + INamedTypeSymbol? attributeType = compilationContext.Compilation.GetOrCreateTypeByMetadataName(WellKnownTypeNames.SystemAttribute); if (attributeType == null) { return; diff --git a/src/Microsoft.CodeQuality.Analyzers/Core/ApiDesignGuidelines/DoNotDirectlyAwaitATask.cs b/src/Microsoft.CodeQuality.Analyzers/Core/ApiDesignGuidelines/DoNotDirectlyAwaitATask.cs index d92f84d864..dc7a52416e 100644 --- a/src/Microsoft.CodeQuality.Analyzers/Core/ApiDesignGuidelines/DoNotDirectlyAwaitATask.cs +++ b/src/Microsoft.CodeQuality.Analyzers/Core/ApiDesignGuidelines/DoNotDirectlyAwaitATask.cs @@ -1,6 +1,7 @@ // Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System.Collections.Immutable; +using System.Diagnostics.CodeAnalysis; using System.Linq; using Analyzer.Utilities; using Analyzer.Utilities.Extensions; @@ -48,8 +49,7 @@ public override void Initialize(AnalysisContext analysisContext) return; } - ImmutableArray taskTypes = GetTaskTypes(context.Compilation); - if (taskTypes.Any(t => t == null)) + if (!TryGetTaskTypes(context.Compilation, out ImmutableArray taskTypes)) { return; } @@ -78,22 +78,29 @@ public override void Initialize(AnalysisContext analysisContext) private static void AnalyzeOperation(OperationAnalysisContext context, ImmutableArray taskTypes) { - IAwaitOperation awaitExpression = context.Operation as IAwaitOperation; + var awaitExpression = (IAwaitOperation)context.Operation; // Get the type of the expression being awaited and check it's a task type. - ITypeSymbol typeOfAwaitedExpression = awaitExpression?.Operation?.Type; + ITypeSymbol? typeOfAwaitedExpression = awaitExpression.Operation.Type; if (typeOfAwaitedExpression != null && taskTypes.Contains(typeOfAwaitedExpression.OriginalDefinition)) { context.ReportDiagnostic(awaitExpression.Operation.Syntax.CreateDiagnostic(Rule)); } } - private static ImmutableArray GetTaskTypes(Compilation compilation) + private static bool TryGetTaskTypes(Compilation compilation, [NotNullWhen(returnValue: true)] out ImmutableArray taskTypes) { - INamedTypeSymbol taskType = compilation.GetOrCreateTypeByMetadataName(WellKnownTypeNames.SystemThreadingTasksTask); - INamedTypeSymbol taskOfTType = compilation.GetOrCreateTypeByMetadataName(WellKnownTypeNames.SystemThreadingTasksGenericTask); + INamedTypeSymbol? taskType = compilation.GetOrCreateTypeByMetadataName(WellKnownTypeNames.SystemThreadingTasksTask); + INamedTypeSymbol? taskOfTType = compilation.GetOrCreateTypeByMetadataName(WellKnownTypeNames.SystemThreadingTasksGenericTask); - return ImmutableArray.Create(taskType, taskOfTType); + if (taskType == null || taskOfTType == null) + { + taskTypes = default; + return false; + } + + taskTypes = ImmutableArray.Create(taskType, taskOfTType); + return true; } } } diff --git a/src/Microsoft.CodeQuality.Analyzers/Core/ApiDesignGuidelines/DoNotRaiseExceptionsInUnexpectedLocations.cs b/src/Microsoft.CodeQuality.Analyzers/Core/ApiDesignGuidelines/DoNotRaiseExceptionsInUnexpectedLocations.cs index d14ae34451..521f6010e6 100644 --- a/src/Microsoft.CodeQuality.Analyzers/Core/ApiDesignGuidelines/DoNotRaiseExceptionsInUnexpectedLocations.cs +++ b/src/Microsoft.CodeQuality.Analyzers/Core/ApiDesignGuidelines/DoNotRaiseExceptionsInUnexpectedLocations.cs @@ -67,7 +67,7 @@ public override void Initialize(AnalysisContext analysisContext) analysisContext.RegisterCompilationStartAction(compilationStartContext => { Compilation compilation = compilationStartContext.Compilation; - INamedTypeSymbol exceptionType = compilation.GetOrCreateTypeByMetadataName(WellKnownTypeNames.SystemException); + INamedTypeSymbol? exceptionType = compilation.GetOrCreateTypeByMetadataName(WellKnownTypeNames.SystemException); if (exceptionType == null) { return; @@ -110,7 +110,7 @@ public override void Initialize(AnalysisContext analysisContext) }); } - protected abstract bool IsAssignableTo(ITypeSymbol fromSymbol, ITypeSymbol toSymbol, Compilation compilation); + protected abstract bool IsAssignableTo(ITypeSymbol? fromSymbol, ITypeSymbol? toSymbol, Compilation compilation); /// /// This object describes a class of methods where exception throwing statements should be analyzed. @@ -136,9 +136,9 @@ private class MethodCategory /// List of exception types which are allowed to be thrown inside this category of method. /// This list will be empty if no exceptions are allowed. /// - public ImmutableHashSet AllowedExceptions { get; } + public ImmutableHashSet AllowedExceptions { get; } - public MethodCategory(Func matchFunction, bool analyzeOnlyPublicMethods, DiagnosticDescriptor rule, params ITypeSymbol[] allowedExceptionTypes) + public MethodCategory(Func matchFunction, bool analyzeOnlyPublicMethods, DiagnosticDescriptor rule, params ITypeSymbol?[] allowedExceptionTypes) { _matchFunction = matchFunction; _analyzeOnlyPublicMethods = analyzeOnlyPublicMethods; @@ -251,7 +251,7 @@ private static bool IsEqualsInterfaceImplementation(IMethodSymbol method, Compil { // Substitute the type of the first parameter of Equals in the generic interface and then check if that // interface method is implemented by the given method. - INamedTypeSymbol iEqualityComparer = compilation.GetOrCreateTypeByMetadataName(WellKnownTypeNames.SystemCollectionsGenericIEqualityComparer1); + INamedTypeSymbol? iEqualityComparer = compilation.GetOrCreateTypeByMetadataName(WellKnownTypeNames.SystemCollectionsGenericIEqualityComparer1); if (method.IsImplementationOfInterfaceMethod(method.Parameters.First().Type, iEqualityComparer, WellKnownMemberNames.ObjectEquals)) { return true; @@ -259,7 +259,7 @@ private static bool IsEqualsInterfaceImplementation(IMethodSymbol method, Compil // Substitute the type of the first parameter of Equals in the generic interface and then check if that // interface method is implemented by the given method. - INamedTypeSymbol iEquatable = compilation.GetOrCreateTypeByMetadataName(WellKnownTypeNames.SystemIEquatable1); + INamedTypeSymbol? iEquatable = compilation.GetOrCreateTypeByMetadataName(WellKnownTypeNames.SystemIEquatable1); if (method.IsImplementationOfInterfaceMethod(method.Parameters.First().Type, iEquatable, WellKnownMemberNames.ObjectEquals)) { return true; @@ -286,14 +286,14 @@ private static bool IsGetHashCodeInterfaceImplementation(IMethodSymbol method, C { // Substitute the type of the first parameter of Equals in the generic interface and then check if that // interface method is implemented by the given method. - INamedTypeSymbol iEqualityComparer = compilation.GetOrCreateTypeByMetadataName(WellKnownTypeNames.SystemCollectionsGenericIEqualityComparer1); + INamedTypeSymbol? iEqualityComparer = compilation.GetOrCreateTypeByMetadataName(WellKnownTypeNames.SystemCollectionsGenericIEqualityComparer1); if (method.IsImplementationOfInterfaceMethod(method.Parameters.First().Type, iEqualityComparer, WellKnownMemberNames.ObjectGetHashCode)) { return true; } - INamedTypeSymbol iHashCodeProvider = compilation.GetOrCreateTypeByMetadataName(WellKnownTypeNames.SystemCollectionsIHashCodeProvider); + INamedTypeSymbol? iHashCodeProvider = compilation.GetOrCreateTypeByMetadataName(WellKnownTypeNames.SystemCollectionsIHashCodeProvider); if (method.IsImplementationOfInterfaceMethod(null, iHashCodeProvider, WellKnownMemberNames.ObjectGetHashCode)) { return true; diff --git a/src/Microsoft.CodeQuality.Analyzers/Core/ApiDesignGuidelines/EnumStorageShouldBeInt32.Fixer.cs b/src/Microsoft.CodeQuality.Analyzers/Core/ApiDesignGuidelines/EnumStorageShouldBeInt32.Fixer.cs index c967b6ef91..fedb36dc81 100644 --- a/src/Microsoft.CodeQuality.Analyzers/Core/ApiDesignGuidelines/EnumStorageShouldBeInt32.Fixer.cs +++ b/src/Microsoft.CodeQuality.Analyzers/Core/ApiDesignGuidelines/EnumStorageShouldBeInt32.Fixer.cs @@ -16,7 +16,7 @@ namespace Microsoft.CodeQuality.Analyzers.ApiDesignGuidelines /// public abstract class EnumStorageShouldBeInt32Fixer : CodeFixProvider { - protected abstract SyntaxNode GetTargetNode(SyntaxNode node); + protected abstract SyntaxNode? GetTargetNode(SyntaxNode node); public sealed override ImmutableArray FixableDiagnosticIds => ImmutableArray.Create(EnumStorageShouldBeInt32Analyzer.RuleId); @@ -54,6 +54,10 @@ private async Task ChangeEnumTypeToInt32Async(Document document, Diagn // Find the target syntax node to replace. Was not able to find a language neutral way of doing this. So using the language specific methods var targetNode = GetTargetNode(enumDeclarationNode); + if (targetNode == null) + { + return document; + } // Remove target node editor.RemoveNode(targetNode, SyntaxRemoveOptions.KeepLeadingTrivia | SyntaxRemoveOptions.KeepTrailingTrivia | SyntaxRemoveOptions.KeepExteriorTrivia | SyntaxRemoveOptions.KeepEndOfLine); diff --git a/src/Microsoft.CodeQuality.Analyzers/Core/ApiDesignGuidelines/EnumStorageShouldBeInt32.cs b/src/Microsoft.CodeQuality.Analyzers/Core/ApiDesignGuidelines/EnumStorageShouldBeInt32.cs index eb80776473..771e4924f0 100644 --- a/src/Microsoft.CodeQuality.Analyzers/Core/ApiDesignGuidelines/EnumStorageShouldBeInt32.cs +++ b/src/Microsoft.CodeQuality.Analyzers/Core/ApiDesignGuidelines/EnumStorageShouldBeInt32.cs @@ -45,7 +45,7 @@ public override void Initialize(AnalysisContext analysisContext) analysisContext.RegisterCompilationStartAction(compilationContext => { - INamedTypeSymbol flagsAttribute = compilationContext.Compilation.GetOrCreateTypeByMetadataName(WellKnownTypeNames.SystemFlagsAttribute); + INamedTypeSymbol? flagsAttribute = compilationContext.Compilation.GetOrCreateTypeByMetadataName(WellKnownTypeNames.SystemFlagsAttribute); if (flagsAttribute == null) { return; diff --git a/src/Microsoft.CodeQuality.Analyzers/Core/ApiDesignGuidelines/EnumWithFlagsAttribute.Fixer.cs b/src/Microsoft.CodeQuality.Analyzers/Core/ApiDesignGuidelines/EnumWithFlagsAttribute.Fixer.cs index 4a6710060b..b5641fb619 100644 --- a/src/Microsoft.CodeQuality.Analyzers/Core/ApiDesignGuidelines/EnumWithFlagsAttribute.Fixer.cs +++ b/src/Microsoft.CodeQuality.Analyzers/Core/ApiDesignGuidelines/EnumWithFlagsAttribute.Fixer.cs @@ -30,7 +30,7 @@ public override async Task RegisterCodeFixesAsync(CodeFixContext context) { SemanticModel model = await context.Document.GetSemanticModelAsync(context.CancellationToken).ConfigureAwait(false); - INamedTypeSymbol flagsAttributeType = model.Compilation.GetOrCreateTypeByMetadataName(WellKnownTypeNames.SystemFlagsAttribute); + INamedTypeSymbol? flagsAttributeType = model.Compilation.GetOrCreateTypeByMetadataName(WellKnownTypeNames.SystemFlagsAttribute); if (flagsAttributeType == null) { return; @@ -70,8 +70,10 @@ private static SyntaxNode AddFlagsAttribute(SyntaxGenerator generator, SyntaxNod private static SyntaxNode RemoveFlagsAttribute(SyntaxGenerator generator, SemanticModel model, SyntaxNode enumTypeSyntax, INamedTypeSymbol flagsAttributeType, CancellationToken cancellationToken) { - var enumType = model.GetDeclaredSymbol(enumTypeSyntax, cancellationToken) as INamedTypeSymbol; - Debug.Assert(enumType != null); + if (!(model.GetDeclaredSymbol(enumTypeSyntax, cancellationToken) is INamedTypeSymbol enumType)) + { + return enumTypeSyntax; + } AttributeData flagsAttribute = enumType.GetAttributes().First(a => Equals(a.AttributeClass, flagsAttributeType)); SyntaxNode attributeNode = flagsAttribute.ApplicationSyntaxReference.GetSyntax(cancellationToken); diff --git a/src/Microsoft.CodeQuality.Analyzers/Core/ApiDesignGuidelines/EnumWithFlagsAttribute.cs b/src/Microsoft.CodeQuality.Analyzers/Core/ApiDesignGuidelines/EnumWithFlagsAttribute.cs index dc8e7ed6a1..a7c6b14120 100644 --- a/src/Microsoft.CodeQuality.Analyzers/Core/ApiDesignGuidelines/EnumWithFlagsAttribute.cs +++ b/src/Microsoft.CodeQuality.Analyzers/Core/ApiDesignGuidelines/EnumWithFlagsAttribute.cs @@ -165,8 +165,6 @@ private static bool ShouldBeFlags(IList enumValues) private static ulong GetMissingBitsInBinaryForm(IList values) { - Debug.Assert(values != null); - // all the powers of two that are individually represented ulong powersOfTwo = 0; bool foundNonPowerOfTwo = false; diff --git a/src/Microsoft.CodeQuality.Analyzers/Core/ApiDesignGuidelines/EnumsShouldHavePluralNames.cs b/src/Microsoft.CodeQuality.Analyzers/Core/ApiDesignGuidelines/EnumsShouldHavePluralNames.cs index a3590b361a..84b9ef90ec 100644 --- a/src/Microsoft.CodeQuality.Analyzers/Core/ApiDesignGuidelines/EnumsShouldHavePluralNames.cs +++ b/src/Microsoft.CodeQuality.Analyzers/Core/ApiDesignGuidelines/EnumsShouldHavePluralNames.cs @@ -97,7 +97,7 @@ public override void Initialize(AnalysisContext analysisContext) analysisContext.RegisterCompilationStartAction(compilationContext => { - INamedTypeSymbol flagsAttribute = compilationContext.Compilation.GetOrCreateTypeByMetadataName(WellKnownTypeNames.SystemFlagsAttribute); + INamedTypeSymbol? flagsAttribute = compilationContext.Compilation.GetOrCreateTypeByMetadataName(WellKnownTypeNames.SystemFlagsAttribute); if (flagsAttribute == null) { return; diff --git a/src/Microsoft.CodeQuality.Analyzers/Core/ApiDesignGuidelines/EnumsShouldHaveZeroValue.Fixer.cs b/src/Microsoft.CodeQuality.Analyzers/Core/ApiDesignGuidelines/EnumsShouldHaveZeroValue.Fixer.cs index abd32ab12c..e6083a1f6a 100644 --- a/src/Microsoft.CodeQuality.Analyzers/Core/ApiDesignGuidelines/EnumsShouldHaveZeroValue.Fixer.cs +++ b/src/Microsoft.CodeQuality.Analyzers/Core/ApiDesignGuidelines/EnumsShouldHaveZeroValue.Fixer.cs @@ -3,7 +3,6 @@ using System; using System.Collections.Generic; using System.Collections.Immutable; -using System.Diagnostics; using System.Linq; using System.Threading; using System.Threading.Tasks; @@ -26,7 +25,7 @@ public override async Task RegisterCodeFixesAsync(CodeFixContext context) { SemanticModel model = await context.Document.GetSemanticModelAsync(context.CancellationToken).ConfigureAwait(false); - INamedTypeSymbol flagsAttributeType = model.Compilation.GetOrCreateTypeByMetadataName(WellKnownTypeNames.SystemFlagsAttribute); + INamedTypeSymbol? flagsAttributeType = model.Compilation.GetOrCreateTypeByMetadataName(WellKnownTypeNames.SystemFlagsAttribute); if (flagsAttributeType == null) { return; @@ -38,7 +37,11 @@ public override async Task RegisterCodeFixesAsync(CodeFixContext context) SyntaxNode node = root.FindNode(context.Span); ISymbol declaredSymbol = model.GetDeclaredSymbol(node, context.CancellationToken); - Debug.Assert(declaredSymbol != null); + if (declaredSymbol == null) + { + continue; + } + string title; foreach (string customTag in diagnostic.Descriptor.CustomTags) @@ -72,7 +75,7 @@ public override async Task RegisterCodeFixesAsync(CodeFixContext context) } } - public override FixAllProvider GetFixAllProvider() + public override FixAllProvider? GetFixAllProvider() { // No trivial way to FixAll diagnostics for this code fix. return null; diff --git a/src/Microsoft.CodeQuality.Analyzers/Core/ApiDesignGuidelines/EnumsShouldHaveZeroValue.cs b/src/Microsoft.CodeQuality.Analyzers/Core/ApiDesignGuidelines/EnumsShouldHaveZeroValue.cs index 00c81ca350..6f6a5211be 100644 --- a/src/Microsoft.CodeQuality.Analyzers/Core/ApiDesignGuidelines/EnumsShouldHaveZeroValue.cs +++ b/src/Microsoft.CodeQuality.Analyzers/Core/ApiDesignGuidelines/EnumsShouldHaveZeroValue.cs @@ -86,7 +86,7 @@ public override void Initialize(AnalysisContext context) context.RegisterCompilationStartAction(compilationContext => { - INamedTypeSymbol flagsAttribute = compilationContext.Compilation.GetOrCreateTypeByMetadataName(WellKnownTypeNames.SystemFlagsAttribute); + INamedTypeSymbol? flagsAttribute = compilationContext.Compilation.GetOrCreateTypeByMetadataName(WellKnownTypeNames.SystemFlagsAttribute); if (flagsAttribute == null) { return; diff --git a/src/Microsoft.CodeQuality.Analyzers/Core/ApiDesignGuidelines/EquatableAnalyzer.Fixer.cs b/src/Microsoft.CodeQuality.Analyzers/Core/ApiDesignGuidelines/EquatableAnalyzer.Fixer.cs index 30341ff9e4..141eb89d63 100644 --- a/src/Microsoft.CodeQuality.Analyzers/Core/ApiDesignGuidelines/EquatableAnalyzer.Fixer.cs +++ b/src/Microsoft.CodeQuality.Analyzers/Core/ApiDesignGuidelines/EquatableAnalyzer.Fixer.cs @@ -47,7 +47,7 @@ public override async Task RegisterCodeFixesAsync(CodeFixContext context) return; } - INamedTypeSymbol equatableType = model.Compilation.GetOrCreateTypeByMetadataName(WellKnownTypeNames.SystemIEquatable1); + INamedTypeSymbol? equatableType = model.Compilation.GetOrCreateTypeByMetadataName(WellKnownTypeNames.SystemIEquatable1); if (equatableType == null) { return; diff --git a/src/Microsoft.CodeQuality.Analyzers/Core/ApiDesignGuidelines/EquatableAnalyzer.cs b/src/Microsoft.CodeQuality.Analyzers/Core/ApiDesignGuidelines/EquatableAnalyzer.cs index 535ad99404..5f9214f206 100644 --- a/src/Microsoft.CodeQuality.Analyzers/Core/ApiDesignGuidelines/EquatableAnalyzer.cs +++ b/src/Microsoft.CodeQuality.Analyzers/Core/ApiDesignGuidelines/EquatableAnalyzer.cs @@ -55,8 +55,8 @@ public override void Initialize(AnalysisContext context) private static void OnCompilationStart(CompilationStartAnalysisContext context) { - INamedTypeSymbol objectType = context.Compilation.GetSpecialType(SpecialType.System_Object); - INamedTypeSymbol equatableType = context.Compilation.GetOrCreateTypeByMetadataName(WellKnownTypeNames.SystemIEquatable1); + INamedTypeSymbol? objectType = context.Compilation.GetSpecialType(SpecialType.System_Object); + INamedTypeSymbol? equatableType = context.Compilation.GetOrCreateTypeByMetadataName(WellKnownTypeNames.SystemIEquatable1); if (objectType != null && equatableType != null) { context.RegisterSymbolAction(c => AnalyzeSymbol(c, equatableType), SymbolKind.NamedType); diff --git a/src/Microsoft.CodeQuality.Analyzers/Core/ApiDesignGuidelines/ExceptionsShouldBePublic.cs b/src/Microsoft.CodeQuality.Analyzers/Core/ApiDesignGuidelines/ExceptionsShouldBePublic.cs index 8d96d31fb6..2f97c74e2e 100644 --- a/src/Microsoft.CodeQuality.Analyzers/Core/ApiDesignGuidelines/ExceptionsShouldBePublic.cs +++ b/src/Microsoft.CodeQuality.Analyzers/Core/ApiDesignGuidelines/ExceptionsShouldBePublic.cs @@ -55,7 +55,7 @@ private static void AnalyzeCompilationStart(CompilationStartAnalysisContext csCo // Get named type symbols for targetted exception types ImmutableHashSet exceptionTypes = s_exceptionTypeNames .Select(name => csContext.Compilation.GetOrCreateTypeByMetadataName(name)) - .Where(t => t != null) + .WhereNotNull() .ToImmutableHashSet(); if (!exceptionTypes.IsEmpty) diff --git a/src/Microsoft.CodeQuality.Analyzers/Core/ApiDesignGuidelines/Helpers/EnumHelpers.cs b/src/Microsoft.CodeQuality.Analyzers/Core/ApiDesignGuidelines/Helpers/EnumHelpers.cs index 0bfc233775..3e7e996818 100644 --- a/src/Microsoft.CodeQuality.Analyzers/Core/ApiDesignGuidelines/Helpers/EnumHelpers.cs +++ b/src/Microsoft.CodeQuality.Analyzers/Core/ApiDesignGuidelines/Helpers/EnumHelpers.cs @@ -60,7 +60,6 @@ internal static bool TryConvertToUInt64(object value, SpecialType specialType, o internal static bool TryGetEnumMemberValues(INamedTypeSymbol enumType, out IList values) { - Debug.Assert(enumType != null); Debug.Assert(enumType.TypeKind == TypeKind.Enum); values = new List(); diff --git a/src/Microsoft.CodeQuality.Analyzers/Core/ApiDesignGuidelines/IdentifiersShouldDifferByMoreThanCase.cs b/src/Microsoft.CodeQuality.Analyzers/Core/ApiDesignGuidelines/IdentifiersShouldDifferByMoreThanCase.cs index 13c429825b..f20584f053 100644 --- a/src/Microsoft.CodeQuality.Analyzers/Core/ApiDesignGuidelines/IdentifiersShouldDifferByMoreThanCase.cs +++ b/src/Microsoft.CodeQuality.Analyzers/Core/ApiDesignGuidelines/IdentifiersShouldDifferByMoreThanCase.cs @@ -58,7 +58,7 @@ private static void AnalyzeCompilation(CompilationAnalysisContext context) private static void AnalyzeSymbol(SymbolAnalysisContext context) { - var namedTypeSymbol = context.Symbol as INamedTypeSymbol; + var namedTypeSymbol = (INamedTypeSymbol)context.Symbol; // Do not descent into non-publicly visible types by default // Note: This is the behavior of FxCop, it might be more correct to descend into internal but not private @@ -245,7 +245,7 @@ private static void CheckTypeNames(IEnumerable types, Compilat typesWithName.Add(type); } - foreach (var (name, typesWithName) in typesByName) + foreach (var (_, typesWithName) in typesByName) { if (typesWithName.Count > 1) { @@ -277,7 +277,7 @@ private static void CheckNamespaceNames(IEnumerable namespaces namespacesWithName.Add(namespaceSym); } - foreach (var (name, namespacesWithName) in namespacesByName) + foreach (var (_, namespacesWithName) in namespacesByName) { if (namespacesWithName.Count > 1) { diff --git a/src/Microsoft.CodeQuality.Analyzers/Core/ApiDesignGuidelines/IdentifiersShouldHaveCorrectPrefix.cs b/src/Microsoft.CodeQuality.Analyzers/Core/ApiDesignGuidelines/IdentifiersShouldHaveCorrectPrefix.cs index d1caaf3baa..43aad7c26d 100644 --- a/src/Microsoft.CodeQuality.Analyzers/Core/ApiDesignGuidelines/IdentifiersShouldHaveCorrectPrefix.cs +++ b/src/Microsoft.CodeQuality.Analyzers/Core/ApiDesignGuidelines/IdentifiersShouldHaveCorrectPrefix.cs @@ -116,7 +116,7 @@ private static bool HasCorrectPrefix(ISymbol symbol, char prefix) { WordParser parser = new WordParser(symbol.Name, WordParserOptions.SplitCompoundWords, prefix); - string firstWord = parser.NextWord(); + string? firstWord = parser.NextWord(); if (firstWord == null || firstWord.Length > 1) { diff --git a/src/Microsoft.CodeQuality.Analyzers/Core/ApiDesignGuidelines/IdentifiersShouldNotContainUnderscores.cs b/src/Microsoft.CodeQuality.Analyzers/Core/ApiDesignGuidelines/IdentifiersShouldNotContainUnderscores.cs index 700191e434..4bc0f66e79 100644 --- a/src/Microsoft.CodeQuality.Analyzers/Core/ApiDesignGuidelines/IdentifiersShouldNotContainUnderscores.cs +++ b/src/Microsoft.CodeQuality.Analyzers/Core/ApiDesignGuidelines/IdentifiersShouldNotContainUnderscores.cs @@ -136,7 +136,7 @@ public override void Initialize(AnalysisContext analysisContext) case SymbolKind.NamedType: { - var namedType = symbol as INamedTypeSymbol; + var namedType = (INamedTypeSymbol)symbol; AnalyzeTypeParameters(symbolAnalysisContext, namedType.TypeParameters); if (namedType.TypeKind == TypeKind.Delegate && @@ -156,7 +156,7 @@ public override void Initialize(AnalysisContext analysisContext) case SymbolKind.Field: { - var fieldSymbol = symbol as IFieldSymbol; + var fieldSymbol = (IFieldSymbol)symbol; if (ContainsUnderScore(symbol.Name) && (fieldSymbol.IsConst || (fieldSymbol.IsStatic && fieldSymbol.IsReadOnly))) { symbolAnalysisContext.ReportDiagnostic(symbol.CreateDiagnostic(MemberRule, symbol.ToDisplayString(SymbolDisplayFormat.CSharpErrorMessageFormat))); diff --git a/src/Microsoft.CodeQuality.Analyzers/Core/ApiDesignGuidelines/ImplementIDisposableCorrectly.cs b/src/Microsoft.CodeQuality.Analyzers/Core/ApiDesignGuidelines/ImplementIDisposableCorrectly.cs index df7a9f6699..a4bbd46774 100644 --- a/src/Microsoft.CodeQuality.Analyzers/Core/ApiDesignGuidelines/ImplementIDisposableCorrectly.cs +++ b/src/Microsoft.CodeQuality.Analyzers/Core/ApiDesignGuidelines/ImplementIDisposableCorrectly.cs @@ -129,7 +129,7 @@ public override void Initialize(AnalysisContext analysisContext) analysisContext.RegisterCompilationStartAction( context => { - INamedTypeSymbol disposableType = context.Compilation.GetOrCreateTypeByMetadataName(WellKnownTypeNames.SystemIDisposable); + INamedTypeSymbol? disposableType = context.Compilation.GetOrCreateTypeByMetadataName(WellKnownTypeNames.SystemIDisposable); if (disposableType == null) { return; @@ -140,7 +140,7 @@ public override void Initialize(AnalysisContext analysisContext) return; } - INamedTypeSymbol garbageCollectorType = context.Compilation.GetOrCreateTypeByMetadataName(GarbageCollectorTypeName); + INamedTypeSymbol? garbageCollectorType = context.Compilation.GetOrCreateTypeByMetadataName(GarbageCollectorTypeName); if (garbageCollectorType == null) { return; @@ -197,7 +197,7 @@ private void AnalyzeNamedTypeSymbol(SymbolAnalysisContext context) CheckIDisposableReimplementationRule(type, context, implementsDisposableInBaseType); } - IMethodSymbol disposeMethod = FindDisposeMethod(type); + IMethodSymbol? disposeMethod = FindDisposeMethod(type); if (disposeMethod != null) { CheckDisposeSignatureRule(disposeMethod, type, context); @@ -249,7 +249,7 @@ private void AnalyzeOperationBlock(OperationBlockAnalysisContext context) { if (ImplementsDisposableDirectly(type)) { - IMethodSymbol disposeMethod = FindDisposeMethod(type); + IMethodSymbol? disposeMethod = FindDisposeMethod(type); if (disposeMethod != null) { if (method.Equals(disposeMethod)) @@ -421,7 +421,7 @@ private bool ImplementsDisposableInBaseType(ITypeSymbol type) /// Returns method that implements IDisposable.Dispose operation. /// Only direct implementation is taken into account, implementation in base type is ignored. /// - private IMethodSymbol FindDisposeMethod(INamedTypeSymbol type) + private IMethodSymbol? FindDisposeMethod(INamedTypeSymbol type) { if (type.FindImplementationForInterfaceMember(_disposeInterfaceMethod) is IMethodSymbol disposeMethod && Equals(disposeMethod.ContainingType, type)) { @@ -442,9 +442,9 @@ private static IMethodSymbol FindDisposeBoolMethod(INamedTypeSymbol type) /// /// Returns method defined in the nearest ancestor: void Dispose(bool) /// - private IMethodSymbol FindInheritedDisposeBoolMethod(INamedTypeSymbol type) + private IMethodSymbol? FindInheritedDisposeBoolMethod(INamedTypeSymbol type) { - IMethodSymbol method = null; + IMethodSymbol? method = null; while (type != null && method == null && ImplementsDisposableInBaseType(type)) { diff --git a/src/Microsoft.CodeQuality.Analyzers/Core/ApiDesignGuidelines/ImplementStandardExceptionConstructors.Fixer.cs b/src/Microsoft.CodeQuality.Analyzers/Core/ApiDesignGuidelines/ImplementStandardExceptionConstructors.Fixer.cs index 976144aaaf..6a9c61ec66 100644 --- a/src/Microsoft.CodeQuality.Analyzers/Core/ApiDesignGuidelines/ImplementStandardExceptionConstructors.Fixer.cs +++ b/src/Microsoft.CodeQuality.Analyzers/Core/ApiDesignGuidelines/ImplementStandardExceptionConstructors.Fixer.cs @@ -60,7 +60,10 @@ private static async Task AddConstructorsAsync(Document document, IEnu CodeAnalysis.Text.TextSpan diagnosticSpan = diagnostics.First().Location.SourceSpan; // All the diagnostics are reported at the same location -- the name of the declared class -- so it doesn't matter which one we pick SyntaxNode node = root.FindNode(diagnosticSpan); SyntaxNode targetNode = editor.Generator.GetDeclaration(node, DeclarationKind.Class); - var typeSymbol = model.GetDeclaredSymbol(targetNode) as INamedTypeSymbol; + if (!(model.GetDeclaredSymbol(targetNode) is INamedTypeSymbol typeSymbol)) + { + return document; + } foreach (Diagnostic diagnostic in diagnostics) { diff --git a/src/Microsoft.CodeQuality.Analyzers/Core/ApiDesignGuidelines/InterfaceMethodsShouldBeCallableByChildTypes.Fixer.cs b/src/Microsoft.CodeQuality.Analyzers/Core/ApiDesignGuidelines/InterfaceMethodsShouldBeCallableByChildTypes.Fixer.cs index e3ce67c49f..8c11d56c49 100644 --- a/src/Microsoft.CodeQuality.Analyzers/Core/ApiDesignGuidelines/InterfaceMethodsShouldBeCallableByChildTypes.Fixer.cs +++ b/src/Microsoft.CodeQuality.Analyzers/Core/ApiDesignGuidelines/InterfaceMethodsShouldBeCallableByChildTypes.Fixer.cs @@ -50,7 +50,7 @@ public async override Task RegisterCodeFixesAsync(CodeFixContext context) return; } - IMethodSymbol candidateToIncreaseVisibility = GetExistingNonVisibleAlternate(methodSymbol); + IMethodSymbol? candidateToIncreaseVisibility = GetExistingNonVisibleAlternate(methodSymbol); if (candidateToIncreaseVisibility != null) { ISymbol symbolToChange; @@ -99,7 +99,7 @@ public async override Task RegisterCodeFixesAsync(CodeFixContext context) context.Diagnostics); } - private static IMethodSymbol GetExistingNonVisibleAlternate(IMethodSymbol methodSymbol) + private static IMethodSymbol? GetExistingNonVisibleAlternate(IMethodSymbol methodSymbol) { foreach (IMethodSymbol interfaceMethod in methodSymbol.ExplicitInterfaceImplementations) { @@ -120,8 +120,8 @@ private static async Task MakeProtected(Document document, ISymbol sym { SymbolEditor editor = SymbolEditor.Create(document); - ISymbol getter = null; - ISymbol setter = null; + ISymbol? getter = null; + ISymbol? setter = null; if (symbolToChange.Kind == SymbolKind.Property) { var propertySymbol = (IPropertySymbol)symbolToChange; @@ -157,7 +157,7 @@ private static async Task ChangeToPublicInterfaceImplementation(Docume { SymbolEditor editor = SymbolEditor.Create(document); - IEnumerable explicitImplementations = GetExplicitImplementations(symbolToChange); + IEnumerable? explicitImplementations = GetExplicitImplementations(symbolToChange); if (explicitImplementations == null) { return document; @@ -178,7 +178,7 @@ private static async Task ChangeToPublicInterfaceImplementation(Docume return editor.GetChangedDocuments().First(); } - private static IEnumerable GetExplicitImplementations(ISymbol symbol) + private static IEnumerable? GetExplicitImplementations(ISymbol? symbol) { if (symbol == null) { diff --git a/src/Microsoft.CodeQuality.Analyzers/Core/ApiDesignGuidelines/MarkAssembliesWithComVisible.cs b/src/Microsoft.CodeQuality.Analyzers/Core/ApiDesignGuidelines/MarkAssembliesWithComVisible.cs index 1ab262fd8e..0837fb10ea 100644 --- a/src/Microsoft.CodeQuality.Analyzers/Core/ApiDesignGuidelines/MarkAssembliesWithComVisible.cs +++ b/src/Microsoft.CodeQuality.Analyzers/Core/ApiDesignGuidelines/MarkAssembliesWithComVisible.cs @@ -53,13 +53,13 @@ private static void AnalyzeCompilation(CompilationAnalysisContext context) { if (AssemblyHasPublicTypes(context.Compilation.Assembly)) { - INamedTypeSymbol comVisibleAttributeSymbol = context.Compilation.GetOrCreateTypeByMetadataName(WellKnownTypeNames.SystemRuntimeInteropServicesComVisibleAttribute); + INamedTypeSymbol? comVisibleAttributeSymbol = context.Compilation.GetOrCreateTypeByMetadataName(WellKnownTypeNames.SystemRuntimeInteropServicesComVisibleAttribute); if (comVisibleAttributeSymbol == null) { return; } - AttributeData attributeInstance = context.Compilation.Assembly.GetAttributes().FirstOrDefault(a => a.AttributeClass.Equals(comVisibleAttributeSymbol)); + AttributeData? attributeInstance = context.Compilation.Assembly.GetAttributes().FirstOrDefault(a => a.AttributeClass.Equals(comVisibleAttributeSymbol)); if (attributeInstance != null) { diff --git a/src/Microsoft.CodeQuality.Analyzers/Core/ApiDesignGuidelines/MarkAttributesWithAttributeUsage.cs b/src/Microsoft.CodeQuality.Analyzers/Core/ApiDesignGuidelines/MarkAttributesWithAttributeUsage.cs index 9e00f90688..7c235cb9f0 100644 --- a/src/Microsoft.CodeQuality.Analyzers/Core/ApiDesignGuidelines/MarkAttributesWithAttributeUsage.cs +++ b/src/Microsoft.CodeQuality.Analyzers/Core/ApiDesignGuidelines/MarkAttributesWithAttributeUsage.cs @@ -38,8 +38,8 @@ public override void Initialize(AnalysisContext analysisContext) analysisContext.RegisterCompilationStartAction(compilationContext => { - INamedTypeSymbol attributeType = compilationContext.Compilation.GetOrCreateTypeByMetadataName(WellKnownTypeNames.SystemAttribute); - INamedTypeSymbol attributeUsageAttributeType = compilationContext.Compilation.GetOrCreateTypeByMetadataName(WellKnownTypeNames.SystemAttributeUsageAttribute); + INamedTypeSymbol? attributeType = compilationContext.Compilation.GetOrCreateTypeByMetadataName(WellKnownTypeNames.SystemAttribute); + INamedTypeSymbol? attributeUsageAttributeType = compilationContext.Compilation.GetOrCreateTypeByMetadataName(WellKnownTypeNames.SystemAttributeUsageAttribute); if (attributeType == null || attributeUsageAttributeType == null) { return; diff --git a/src/Microsoft.CodeQuality.Analyzers/Core/ApiDesignGuidelines/NestedTypesShouldNotBeVisible.cs b/src/Microsoft.CodeQuality.Analyzers/Core/ApiDesignGuidelines/NestedTypesShouldNotBeVisible.cs index c989cb0efd..0c2f97b345 100644 --- a/src/Microsoft.CodeQuality.Analyzers/Core/ApiDesignGuidelines/NestedTypesShouldNotBeVisible.cs +++ b/src/Microsoft.CodeQuality.Analyzers/Core/ApiDesignGuidelines/NestedTypesShouldNotBeVisible.cs @@ -57,10 +57,10 @@ public override void Initialize(AnalysisContext analysisContext) { Compilation compilation = compilationStartContext.Compilation; - INamedTypeSymbol enumeratorType = compilation.GetSpecialType(SpecialType.System_Collections_IEnumerator); - INamedTypeSymbol dataSetType = compilation.GetOrCreateTypeByMetadataName(WellKnownTypeNames.SystemDataDataSet); - INamedTypeSymbol dataTableType = compilation.GetOrCreateTypeByMetadataName(WellKnownTypeNames.SystemDataDataTable); - INamedTypeSymbol dataRowType = compilation.GetOrCreateTypeByMetadataName(WellKnownTypeNames.SystemDataDataRow); + INamedTypeSymbol? enumeratorType = compilation.GetSpecialType(SpecialType.System_Collections_IEnumerator); + INamedTypeSymbol? dataSetType = compilation.GetOrCreateTypeByMetadataName(WellKnownTypeNames.SystemDataDataSet); + INamedTypeSymbol? dataTableType = compilation.GetOrCreateTypeByMetadataName(WellKnownTypeNames.SystemDataDataTable); + INamedTypeSymbol? dataRowType = compilation.GetOrCreateTypeByMetadataName(WellKnownTypeNames.SystemDataDataRow); compilationStartContext.RegisterSymbolAction( symbolAnalysisContext => @@ -128,9 +128,9 @@ public override void Initialize(AnalysisContext analysisContext) private static bool IsDataSetSpecialCase( INamedTypeSymbol containingType, INamedTypeSymbol nestedType, - INamedTypeSymbol dataSetType, - INamedTypeSymbol dataTableType, - INamedTypeSymbol dataRowType) + INamedTypeSymbol? dataSetType, + INamedTypeSymbol? dataTableType, + INamedTypeSymbol? dataRowType) { if (!containingType.GetBaseTypes().Contains(dataSetType)) { @@ -138,7 +138,8 @@ public override void Initialize(AnalysisContext analysisContext) } var nestedTypeBases = nestedType.GetBaseTypes().ToList(); - return nestedTypeBases.Contains(dataTableType) || nestedTypeBases.Contains(dataRowType); + return dataTableType != null && nestedTypeBases.Contains(dataTableType) || + dataRowType != null && nestedTypeBases.Contains(dataRowType); } } } \ No newline at end of file diff --git a/src/Microsoft.CodeQuality.Analyzers/Core/ApiDesignGuidelines/OperatorOverloadsHaveNamedAlternates.Fixer.cs b/src/Microsoft.CodeQuality.Analyzers/Core/ApiDesignGuidelines/OperatorOverloadsHaveNamedAlternates.Fixer.cs index 709f3244bb..f14d2ee0cb 100644 --- a/src/Microsoft.CodeQuality.Analyzers/Core/ApiDesignGuidelines/OperatorOverloadsHaveNamedAlternates.Fixer.cs +++ b/src/Microsoft.CodeQuality.Analyzers/Core/ApiDesignGuidelines/OperatorOverloadsHaveNamedAlternates.Fixer.cs @@ -32,12 +32,10 @@ public override async Task RegisterCodeFixesAsync(CodeFixContext context) { SemanticModel semanticModel = await context.Document.GetSemanticModelAsync(context.CancellationToken).ConfigureAwait(false); SyntaxNode root = await context.Document.GetSyntaxRootAsync(context.CancellationToken).ConfigureAwait(false); - SyntaxGenerator generator = context.Document.Project?.LanguageServices?.GetService(); - if (semanticModel != null && generator != null) - { - string title = MicrosoftCodeQualityAnalyzersResources.OperatorOverloadsHaveNamedAlternatesTitle; - context.RegisterCodeFix(new MyCodeAction(title, ct => Fix(context, root, generator, semanticModel, ct), equivalenceKey: title), context.Diagnostics.First()); - } + SyntaxGenerator generator = context.Document.Project.LanguageServices.GetService(); + + string title = MicrosoftCodeQualityAnalyzersResources.OperatorOverloadsHaveNamedAlternatesTitle; + context.RegisterCodeFix(new MyCodeAction(title, ct => Fix(context, root, generator, semanticModel, ct), equivalenceKey: title), context.Diagnostics.First()); } private static async Task Fix(CodeFixContext context, SyntaxNode root, SyntaxGenerator generator, SemanticModel semanticModel, CancellationToken cancellationToken) @@ -72,7 +70,11 @@ private static async Task Fix(CodeFixContext context, SyntaxNode root, else { // add a method - ExpectedMethodSignature expectedSignature = GetExpectedMethodSignature(operatorOverloadSymbol, semanticModel.Compilation); + ExpectedMethodSignature? expectedSignature = GetExpectedMethodSignature(operatorOverloadSymbol, semanticModel.Compilation); + if (expectedSignature == null) + { + return context.Document; + } if (expectedSignature.Name == "CompareTo" && operatorOverloadSymbol.ContainingType.TypeKind == TypeKind.Class) { @@ -114,12 +116,17 @@ private static async Task Fix(CodeFixContext context, SyntaxNode root, } } - private static ExpectedMethodSignature GetExpectedMethodSignature(IMethodSymbol operatorOverloadSymbol, Compilation compilation) + private static ExpectedMethodSignature? GetExpectedMethodSignature(IMethodSymbol operatorOverloadSymbol, Compilation compilation) { var containingType = (ITypeSymbol)operatorOverloadSymbol.ContainingType; ITypeSymbol returnType = operatorOverloadSymbol.ReturnType; - ITypeSymbol parameterType = operatorOverloadSymbol.Parameters.FirstOrDefault()?.Type; - string expectedName = OperatorOverloadsHaveNamedAlternatesAnalyzer.GetExpectedAlternateMethodGroup(operatorOverloadSymbol.Name, returnType, parameterType).AlternateMethod1; + ITypeSymbol? parameterType = operatorOverloadSymbol.Parameters.FirstOrDefault()?.Type; + string? expectedName = OperatorOverloadsHaveNamedAlternatesAnalyzer.GetExpectedAlternateMethodGroup(operatorOverloadSymbol.Name, returnType, parameterType)?.AlternateMethod1; + if (expectedName == null) + { + return null; + } + switch (operatorOverloadSymbol.Name) { case "op_GreaterThan": diff --git a/src/Microsoft.CodeQuality.Analyzers/Core/ApiDesignGuidelines/OperatorOverloadsHaveNamedAlternates.cs b/src/Microsoft.CodeQuality.Analyzers/Core/ApiDesignGuidelines/OperatorOverloadsHaveNamedAlternates.cs index ab4f6b8bb6..85bb852646 100644 --- a/src/Microsoft.CodeQuality.Analyzers/Core/ApiDesignGuidelines/OperatorOverloadsHaveNamedAlternates.cs +++ b/src/Microsoft.CodeQuality.Analyzers/Core/ApiDesignGuidelines/OperatorOverloadsHaveNamedAlternates.cs @@ -112,7 +112,7 @@ private static void AnalyzeSymbol(SymbolAnalysisContext symbolContext) } else { - ExpectedAlternateMethodGroup expectedGroup = GetExpectedAlternateMethodGroup(operatorName, methodSymbol.ReturnType, methodSymbol.Parameters.FirstOrDefault()?.Type); + ExpectedAlternateMethodGroup? expectedGroup = GetExpectedAlternateMethodGroup(operatorName, methodSymbol.ReturnType, methodSymbol.Parameters.FirstOrDefault()?.Type); if (expectedGroup == null) { // no alternate methods required @@ -191,7 +191,7 @@ internal static bool IsPropertyExpected(string operatorName) } } - internal static ExpectedAlternateMethodGroup GetExpectedAlternateMethodGroup(string operatorName, ITypeSymbol returnType, ITypeSymbol parameterType) + internal static ExpectedAlternateMethodGroup? GetExpectedAlternateMethodGroup(string operatorName, ITypeSymbol returnType, ITypeSymbol? parameterType) { // list of operator alternate names: https://docs.microsoft.com/visualstudio/code-quality/ca2225-operator-overloads-have-named-alternates @@ -267,9 +267,9 @@ internal static ExpectedAlternateMethodGroup GetExpectedAlternateMethodGroup(str internal class ExpectedAlternateMethodGroup { public string AlternateMethod1 { get; } - public string AlternateMethod2 { get; } + public string? AlternateMethod2 { get; } - public ExpectedAlternateMethodGroup(string alternateMethod1, string alternateMethod2 = null) + public ExpectedAlternateMethodGroup(string alternateMethod1, string? alternateMethod2 = null) { AlternateMethod1 = alternateMethod1; AlternateMethod2 = alternateMethod2; diff --git a/src/Microsoft.CodeQuality.Analyzers/Core/ApiDesignGuidelines/OverrideMethodsOnComparableTypes.cs b/src/Microsoft.CodeQuality.Analyzers/Core/ApiDesignGuidelines/OverrideMethodsOnComparableTypes.cs index 2a1c80aca0..4739708d31 100644 --- a/src/Microsoft.CodeQuality.Analyzers/Core/ApiDesignGuidelines/OverrideMethodsOnComparableTypes.cs +++ b/src/Microsoft.CodeQuality.Analyzers/Core/ApiDesignGuidelines/OverrideMethodsOnComparableTypes.cs @@ -66,8 +66,8 @@ public override void Initialize(AnalysisContext analysisContext) analysisContext.RegisterCompilationStartAction(compilationContext => { - INamedTypeSymbol comparableType = compilationContext.Compilation.GetOrCreateTypeByMetadataName(WellKnownTypeNames.SystemIComparable); - INamedTypeSymbol genericComparableType = compilationContext.Compilation.GetOrCreateTypeByMetadataName(WellKnownTypeNames.SystemIComparable1); + INamedTypeSymbol? comparableType = compilationContext.Compilation.GetOrCreateTypeByMetadataName(WellKnownTypeNames.SystemIComparable); + INamedTypeSymbol? genericComparableType = compilationContext.Compilation.GetOrCreateTypeByMetadataName(WellKnownTypeNames.SystemIComparable1); // Even if one of them is available, we should continue analysis. if (comparableType == null && genericComparableType == null) @@ -83,7 +83,7 @@ public override void Initialize(AnalysisContext analysisContext) }); } - private static void AnalyzeSymbol(SymbolAnalysisContext context, INamedTypeSymbol comparableType, INamedTypeSymbol genericComparableType) + private static void AnalyzeSymbol(SymbolAnalysisContext context, INamedTypeSymbol? comparableType, INamedTypeSymbol? genericComparableType) { // Note all the descriptors/rules for this analyzer have the same ID and category and hence // will always have identical configured visibility. @@ -115,7 +115,7 @@ private static void AnalyzeSymbol(SymbolAnalysisContext context, INamedTypeSymbo } } - private static bool IsComparableWithBaseNotComparable(INamedTypeSymbol namedTypeSymbol, INamedTypeSymbol comparableType, INamedTypeSymbol genericComparableType) + private static bool IsComparableWithBaseNotComparable(INamedTypeSymbol namedTypeSymbol, INamedTypeSymbol? comparableType, INamedTypeSymbol? genericComparableType) { if (!IsComparableCore(namedTypeSymbol, comparableType, genericComparableType)) { @@ -133,14 +133,14 @@ private static bool IsComparableWithBaseNotComparable(INamedTypeSymbol namedType return true; } - private static bool IsComparableCore(INamedTypeSymbol namedTypeSymbol, INamedTypeSymbol comparableType, INamedTypeSymbol genericComparableType) + private static bool IsComparableCore(INamedTypeSymbol namedTypeSymbol, INamedTypeSymbol? comparableType, INamedTypeSymbol? genericComparableType) => namedTypeSymbol.AllInterfaces.Any(t => t.Equals(comparableType) || (t.ConstructedFrom?.Equals(genericComparableType) ?? false)); private static string GetNeededComparisonOperators(INamedTypeSymbol symbol) { bool first = true; - StringBuilder sb = null; + StringBuilder? sb = null; void Append(string @operator) { if (first) @@ -150,7 +150,7 @@ void Append(string @operator) } else { - sb.Append(", "); + sb!.Append(", "); } sb.Append(@operator); diff --git a/src/Microsoft.CodeQuality.Analyzers/Core/ApiDesignGuidelines/ParameterNamesShouldMatchBaseDeclaration.cs b/src/Microsoft.CodeQuality.Analyzers/Core/ApiDesignGuidelines/ParameterNamesShouldMatchBaseDeclaration.cs index 21fe69c1e6..3bc8da78ad 100644 --- a/src/Microsoft.CodeQuality.Analyzers/Core/ApiDesignGuidelines/ParameterNamesShouldMatchBaseDeclaration.cs +++ b/src/Microsoft.CodeQuality.Analyzers/Core/ApiDesignGuidelines/ParameterNamesShouldMatchBaseDeclaration.cs @@ -71,7 +71,7 @@ private static void AnalyzeMethodSymbol(SymbolAnalysisContext analysisContext) return; } - IMethodSymbol bestMatch = null; + IMethodSymbol? bestMatch = null; int bestMatchScore = -1; foreach (var originalDefinition in originalDefinitions) @@ -108,6 +108,11 @@ private static void AnalyzeMethodSymbol(SymbolAnalysisContext analysisContext) } } + if (bestMatch == null) + { + return; + } + for (int i = 0; i < methodSymbol.Parameters.Length; i++) { IParameterSymbol currentParameter = methodSymbol.Parameters[i]; diff --git a/src/Microsoft.CodeQuality.Analyzers/Core/ApiDesignGuidelines/PassSystemUriObjectsInsteadOfStrings.cs b/src/Microsoft.CodeQuality.Analyzers/Core/ApiDesignGuidelines/PassSystemUriObjectsInsteadOfStrings.cs index a3e482bfa4..0695d15d1f 100644 --- a/src/Microsoft.CodeQuality.Analyzers/Core/ApiDesignGuidelines/PassSystemUriObjectsInsteadOfStrings.cs +++ b/src/Microsoft.CodeQuality.Analyzers/Core/ApiDesignGuidelines/PassSystemUriObjectsInsteadOfStrings.cs @@ -46,8 +46,8 @@ public override void Initialize(AnalysisContext analysisContext) analysisContext.RegisterCompilationStartAction(c => { - INamedTypeSymbol @string = c.Compilation.GetSpecialType(SpecialType.System_String); - INamedTypeSymbol uri = c.Compilation.GetOrCreateTypeByMetadataName(WellKnownTypeNames.SystemUri); + INamedTypeSymbol? @string = c.Compilation.GetSpecialType(SpecialType.System_String); + INamedTypeSymbol? uri = c.Compilation.GetOrCreateTypeByMetadataName(WellKnownTypeNames.SystemUri); if (@string == null || uri == null) { // we don't have required types @@ -59,7 +59,7 @@ public override void Initialize(AnalysisContext analysisContext) }); } - protected abstract SyntaxNode GetInvocationExpression(SyntaxNode invocationNode); + protected abstract SyntaxNode? GetInvocationExpression(SyntaxNode invocationNode); private sealed class PerCompilationAnalyzer { @@ -67,13 +67,13 @@ private sealed class PerCompilationAnalyzer private readonly Compilation _compilation; private readonly INamedTypeSymbol _string; private readonly INamedTypeSymbol _uri; - private readonly Func _expressionGetter; + private readonly Func _expressionGetter; public PerCompilationAnalyzer( Compilation compilation, INamedTypeSymbol @string, INamedTypeSymbol uri, - Func expressionGetter) + Func expressionGetter) { _compilation = compilation; _string = @string; diff --git a/src/Microsoft.CodeQuality.Analyzers/Core/ApiDesignGuidelines/PropertyNamesShouldNotMatchGetMethods.cs b/src/Microsoft.CodeQuality.Analyzers/Core/ApiDesignGuidelines/PropertyNamesShouldNotMatchGetMethods.cs index 006bfd0f28..97e43edc2c 100644 --- a/src/Microsoft.CodeQuality.Analyzers/Core/ApiDesignGuidelines/PropertyNamesShouldNotMatchGetMethods.cs +++ b/src/Microsoft.CodeQuality.Analyzers/Core/ApiDesignGuidelines/PropertyNamesShouldNotMatchGetMethods.cs @@ -76,7 +76,7 @@ private static void AnalyzeSymbol(SymbolAnalysisContext context) // Iterate through all declared types, including base foreach (INamedTypeSymbol type in symbol.ContainingType.GetBaseTypesAndThis()) { - Diagnostic diagnostic = null; + Diagnostic? diagnostic = null; var exposedMembers = type.GetMembers(identifier).Where(member => configuredVisibilities.Contains(member.GetResultantVisibility())); foreach (var member in exposedMembers) diff --git a/src/Microsoft.CodeQuality.Analyzers/Core/ApiDesignGuidelines/ProvideObsoleteAttributeMessage.cs b/src/Microsoft.CodeQuality.Analyzers/Core/ApiDesignGuidelines/ProvideObsoleteAttributeMessage.cs index 41beae89c7..7e4b8c7acc 100644 --- a/src/Microsoft.CodeQuality.Analyzers/Core/ApiDesignGuidelines/ProvideObsoleteAttributeMessage.cs +++ b/src/Microsoft.CodeQuality.Analyzers/Core/ApiDesignGuidelines/ProvideObsoleteAttributeMessage.cs @@ -41,7 +41,7 @@ public override void Initialize(AnalysisContext analysisContext) analysisContext.RegisterCompilationStartAction(compilationContext => { - INamedTypeSymbol obsoleteAttributeType = compilationContext.Compilation.GetOrCreateTypeByMetadataName(WellKnownTypeNames.SystemObsoleteAttribute); + INamedTypeSymbol? obsoleteAttributeType = compilationContext.Compilation.GetOrCreateTypeByMetadataName(WellKnownTypeNames.SystemObsoleteAttribute); if (obsoleteAttributeType == null) { return; diff --git a/src/Microsoft.CodeQuality.Analyzers/Core/ApiDesignGuidelines/TypeNamesShouldNotMatchNamespaces.cs b/src/Microsoft.CodeQuality.Analyzers/Core/ApiDesignGuidelines/TypeNamesShouldNotMatchNamespaces.cs index 708286be0b..6dfdfaed72 100644 --- a/src/Microsoft.CodeQuality.Analyzers/Core/ApiDesignGuidelines/TypeNamesShouldNotMatchNamespaces.cs +++ b/src/Microsoft.CodeQuality.Analyzers/Core/ApiDesignGuidelines/TypeNamesShouldNotMatchNamespaces.cs @@ -47,7 +47,7 @@ public sealed class TypeNamesShouldNotMatchNamespacesAnalyzer : DiagnosticAnalyz public override ImmutableArray SupportedDiagnostics => ImmutableArray.Create(DefaultRule, SystemRule); private static readonly object s_lock = new object(); - private static ImmutableDictionary s_wellKnownSystemNamespaceTable; + private static ImmutableDictionary? s_wellKnownSystemNamespaceTable; public override void Initialize(AnalysisContext analysisContext) { @@ -95,7 +95,7 @@ public override void Initialize(AnalysisContext analysisContext) foreach (INamedTypeSymbol symbol in externallyVisibleNamedTypes) { string symbolName = symbol.Name; - if (s_wellKnownSystemNamespaceTable.ContainsKey(symbolName)) + if (s_wellKnownSystemNamespaceTable!.ContainsKey(symbolName)) { compilationAnalysisContext.ReportDiagnostic(symbol.CreateDiagnostic(SystemRule, symbolName, s_wellKnownSystemNamespaceTable[symbolName])); } diff --git a/src/Microsoft.CodeQuality.Analyzers/Core/ApiDesignGuidelines/TypesThatOwnDisposableFieldsShouldBeDisposable.Fixer.cs b/src/Microsoft.CodeQuality.Analyzers/Core/ApiDesignGuidelines/TypesThatOwnDisposableFieldsShouldBeDisposable.Fixer.cs index 21ad3fd8e6..3a6d039a6f 100644 --- a/src/Microsoft.CodeQuality.Analyzers/Core/ApiDesignGuidelines/TypesThatOwnDisposableFieldsShouldBeDisposable.Fixer.cs +++ b/src/Microsoft.CodeQuality.Analyzers/Core/ApiDesignGuidelines/TypesThatOwnDisposableFieldsShouldBeDisposable.Fixer.cs @@ -54,7 +54,7 @@ private static async Task ImplementIDisposable(Document document, Synt // Find a Dispose method. If one exists make that implement IDisposable, else generate a new method. var typeSymbol = model.GetDeclaredSymbol(declaration) as INamedTypeSymbol; - IMethodSymbol disposeMethod = (typeSymbol?.GetMembers("Dispose"))?.OfType()?.Where(m => m.Parameters.Length == 0).FirstOrDefault(); + IMethodSymbol? disposeMethod = (typeSymbol?.GetMembers("Dispose"))?.OfType()?.Where(m => m.Parameters.Length == 0).FirstOrDefault(); if (disposeMethod != null && disposeMethod.DeclaringSyntaxReferences.Length == 1) { SyntaxNode memberPartNode = await disposeMethod.DeclaringSyntaxReferences.Single().GetSyntaxAsync(cancellationToken).ConfigureAwait(false); diff --git a/src/Microsoft.CodeQuality.Analyzers/Core/ApiDesignGuidelines/UriParametersShouldNotBeStrings.Fixer.cs b/src/Microsoft.CodeQuality.Analyzers/Core/ApiDesignGuidelines/UriParametersShouldNotBeStrings.Fixer.cs index 017d2374e2..fd6ca24428 100644 --- a/src/Microsoft.CodeQuality.Analyzers/Core/ApiDesignGuidelines/UriParametersShouldNotBeStrings.Fixer.cs +++ b/src/Microsoft.CodeQuality.Analyzers/Core/ApiDesignGuidelines/UriParametersShouldNotBeStrings.Fixer.cs @@ -39,7 +39,7 @@ public sealed override async Task RegisterCodeFixesAsync(CodeFixContext context) SemanticModel model = await document.GetSemanticModelAsync(cancellationToken).ConfigureAwait(false); - INamedTypeSymbol uriType = model.Compilation.GetOrCreateTypeByMetadataName(WellKnownTypeNames.SystemUri); + INamedTypeSymbol? uriType = model.Compilation.GetOrCreateTypeByMetadataName(WellKnownTypeNames.SystemUri); if (uriType == null) { return; diff --git a/src/Microsoft.CodeQuality.Analyzers/Core/ApiDesignGuidelines/UseEventsWhereAppropriate.cs b/src/Microsoft.CodeQuality.Analyzers/Core/ApiDesignGuidelines/UseEventsWhereAppropriate.cs index 87b652fa4d..7a049a9552 100644 --- a/src/Microsoft.CodeQuality.Analyzers/Core/ApiDesignGuidelines/UseEventsWhereAppropriate.cs +++ b/src/Microsoft.CodeQuality.Analyzers/Core/ApiDesignGuidelines/UseEventsWhereAppropriate.cs @@ -88,7 +88,7 @@ private static bool HasEventLikeName(IMethodSymbol method) { WordParser parser = new WordParser(method.Name, WordParserOptions.SplitCompoundWords); - string word = parser.NextWord(); + string? word = parser.NextWord(); // Check for 'FireXXX', 'RaiseXXX' if (string.Equals(word, "fire", StringComparison.OrdinalIgnoreCase) || diff --git a/src/Microsoft.CodeQuality.Analyzers/Core/ApiDesignGuidelines/UseGenericEventHandlerInstances.cs b/src/Microsoft.CodeQuality.Analyzers/Core/ApiDesignGuidelines/UseGenericEventHandlerInstances.cs index b59920cdcc..b653e4795f 100644 --- a/src/Microsoft.CodeQuality.Analyzers/Core/ApiDesignGuidelines/UseGenericEventHandlerInstances.cs +++ b/src/Microsoft.CodeQuality.Analyzers/Core/ApiDesignGuidelines/UseGenericEventHandlerInstances.cs @@ -77,7 +77,7 @@ public override void Initialize(AnalysisContext analysisContext) analysisContext.RegisterCompilationStartAction( (context) => { - INamedTypeSymbol eventArgs = context.Compilation.GetOrCreateTypeByMetadataName(WellKnownTypeNames.SystemEventArgs); + INamedTypeSymbol? eventArgs = context.Compilation.GetOrCreateTypeByMetadataName(WellKnownTypeNames.SystemEventArgs); if (eventArgs == null) { return; @@ -95,7 +95,7 @@ public override void Initialize(AnalysisContext analysisContext) bool IsEventArgsParameter(IParameterSymbol parameter) { var type = parameter.Type; - if (IsAssignableTo(context.Compilation, type, eventArgs)) + if (IsAssignableTo(context.Compilation, type, eventArgs!)) { return true; } @@ -111,8 +111,6 @@ bool IsEventArgsParameter(IParameterSymbol parameter) bool IsValidNonGenericEventHandler(IMethodSymbol delegateInvokeMethod) { - Debug.Assert(delegateInvokeMethod != null); - return delegateInvokeMethod.ReturnsVoid && delegateInvokeMethod.Parameters.Length == 2 && delegateInvokeMethod.Parameters[0].Type.SpecialType == SpecialType.System_Object && @@ -133,7 +131,7 @@ bool IsValidNonGenericEventHandler(IMethodSymbol delegateInvokeMethod) } }, SymbolKind.NamedType); - INamedTypeSymbol comSourceInterfacesAttribute = context.Compilation.GetOrCreateTypeByMetadataName(WellKnownTypeNames.SystemRuntimeInteropServicesComSourceInterfacesAttribute); + INamedTypeSymbol? comSourceInterfacesAttribute = context.Compilation.GetOrCreateTypeByMetadataName(WellKnownTypeNames.SystemRuntimeInteropServicesComSourceInterfacesAttribute); bool ContainingTypeHasComSourceInterfacesAttribute(IEventSymbol eventSymbol) => comSourceInterfacesAttribute != null && eventSymbol.ContainingType.GetAttributes().Any(a => Equals(a.AttributeClass, comSourceInterfacesAttribute)); diff --git a/src/Microsoft.CodeQuality.Analyzers/Core/Maintainability/AvoidDeadConditionalCode.cs b/src/Microsoft.CodeQuality.Analyzers/Core/Maintainability/AvoidDeadConditionalCode.cs index b2480fbe24..b1e59cd765 100644 --- a/src/Microsoft.CodeQuality.Analyzers/Core/Maintainability/AvoidDeadConditionalCode.cs +++ b/src/Microsoft.CodeQuality.Analyzers/Core/Maintainability/AvoidDeadConditionalCode.cs @@ -88,13 +88,12 @@ public override void Initialize(AnalysisContext context) var valueContentAnalysisResult = ValueContentAnalysis.TryGetOrComputeResult(cfg, owningSymbol, wellKnownTypeProvider, operationBlockContext.Options, AlwaysTrueFalseOrNullRule, operationBlockContext.CancellationToken, out var copyAnalysisResultOpt, out var pointsToAnalysisResult); - if (valueContentAnalysisResult == null) + if (valueContentAnalysisResult == null || + pointsToAnalysisResult == null) { continue; } - Debug.Assert(pointsToAnalysisResult != null); - foreach (var operation in cfg.DescendantOperations()) { // Skip implicit operations. @@ -173,7 +172,7 @@ PredicateValueKind GetPredicateKind(IOperation operation) binaryOperation.IsComparisonOperator() || operation.Type?.SpecialType == SpecialType.System_Boolean) { - PredicateValueKind predicateKind = pointsToAnalysisResult.GetPredicateKind(operation); + PredicateValueKind predicateKind = pointsToAnalysisResult!.GetPredicateKind(operation); if (predicateKind != PredicateValueKind.Unknown) { return predicateKind; @@ -188,7 +187,7 @@ PredicateValueKind GetPredicateKind(IOperation operation) } } - predicateKind = valueContentAnalysisResult.GetPredicateKind(operation); + predicateKind = valueContentAnalysisResult!.GetPredicateKind(operation); if (predicateKind != PredicateValueKind.Unknown) { return predicateKind; diff --git a/src/Microsoft.CodeQuality.Analyzers/Core/Maintainability/AvoidUninstantiatedInternalClasses.cs b/src/Microsoft.CodeQuality.Analyzers/Core/Maintainability/AvoidUninstantiatedInternalClasses.cs index c597860b7d..fedd20b812 100644 --- a/src/Microsoft.CodeQuality.Analyzers/Core/Maintainability/AvoidUninstantiatedInternalClasses.cs +++ b/src/Microsoft.CodeQuality.Analyzers/Core/Maintainability/AvoidUninstantiatedInternalClasses.cs @@ -44,8 +44,8 @@ public override void Initialize(AnalysisContext analysisContext) analysisContext.RegisterCompilationStartAction(startContext => { - var instantiatedTypes = new ConcurrentDictionary(); - var internalTypes = new ConcurrentDictionary(); + var instantiatedTypes = new ConcurrentDictionary(); + var internalTypes = new ConcurrentDictionary(); var compilation = startContext.Compilation; @@ -202,12 +202,12 @@ static IEnumerable GetAllNamedTypeConstraints(ITypeParameterSy private static bool AssemblyExposesInternals( Compilation compilation, - INamedTypeSymbol internalsVisibleToAttributeSymbol) + INamedTypeSymbol? internalsVisibleToAttributeSymbol) { ISymbol assemblySymbol = compilation.Assembly; var attributes = assemblySymbol.GetAttributes(); - return attributes.Any( - attr => attr.AttributeClass.Equals(internalsVisibleToAttributeSymbol)); + return internalsVisibleToAttributeSymbol == null || + attributes.Any(attr => attr.AttributeClass.Equals(internalsVisibleToAttributeSymbol)); } private bool HasInstantiatedNestedType(INamedTypeSymbol type, IEnumerable instantiatedTypes) @@ -235,13 +235,13 @@ private bool HasInstantiatedNestedType(INamedTypeSymbol type, IEnumerable IsEntryPoint(m, taskSymbol, genericTaskSymbol)); } - private static bool IsEntryPoint(IMethodSymbol method, ITypeSymbol taskSymbol, ITypeSymbol genericTaskSymbol) + private static bool IsEntryPoint(IMethodSymbol method, ITypeSymbol? taskSymbol, ITypeSymbol? genericTaskSymbol) { if (!method.IsStatic) { @@ -355,7 +355,7 @@ private static bool IsEntryPoint(IMethodSymbol method, ITypeSymbol taskSymbol, I return true; } - private static bool IsSupportedReturnType(IMethodSymbol method, ITypeSymbol taskSymbol, ITypeSymbol genericTaskSymbol) + private static bool IsSupportedReturnType(IMethodSymbol method, ITypeSymbol? taskSymbol, ITypeSymbol? genericTaskSymbol) { if (method.ReturnType.SpecialType == SpecialType.System_Int32) { diff --git a/src/Microsoft.CodeQuality.Analyzers/Core/Maintainability/CodeMetricsAnalyzer.cs b/src/Microsoft.CodeQuality.Analyzers/Core/Maintainability/CodeMetricsAnalyzer.cs index 5021534be0..724bd6cd45 100644 --- a/src/Microsoft.CodeQuality.Analyzers/Core/Maintainability/CodeMetricsAnalyzer.cs +++ b/src/Microsoft.CodeQuality.Analyzers/Core/Maintainability/CodeMetricsAnalyzer.cs @@ -3,6 +3,7 @@ using System; using System.Collections.Generic; using System.Collections.Immutable; +using System.Diagnostics.CodeAnalysis; using System.IO; using System.Linq; using System.Threading; @@ -128,9 +129,9 @@ public override void Initialize(AnalysisContext analysisContext) if (!TryGetRuleIdToThresholdMap( compilationContext.Options.AdditionalFiles, compilationContext.CancellationToken, - out AdditionalText additionalTextOpt, - out ImmutableDictionary> ruleIdToThresholdMap, - out List invalidFileDiagnostics) && + out AdditionalText? additionalTextOpt, + out ImmutableDictionary>? ruleIdToThresholdMap, + out List? invalidFileDiagnostics) && invalidFileDiagnostics != null) { // Report any invalid additional file diagnostics. @@ -307,9 +308,9 @@ static bool isApplicableByDefault(string ruleId, SymbolKind symbolKind) private static bool TryGetRuleIdToThresholdMap( ImmutableArray additionalFiles, CancellationToken cancellationToken, - out AdditionalText additionalText, - out ImmutableDictionary> ruleIdToThresholdMap, - out List invalidFileDiagnostics) + [NotNullWhen(returnValue: true)] out AdditionalText? additionalText, + [NotNullWhen(returnValue: true)] out ImmutableDictionary>? ruleIdToThresholdMap, + out List? invalidFileDiagnostics) { invalidFileDiagnostics = null; ruleIdToThresholdMap = null; @@ -321,7 +322,7 @@ static bool isApplicableByDefault(string ruleId, SymbolKind symbolKind) TryParseCodeMetricsConfigurationFile(additionalText, cancellationToken, out ruleIdToThresholdMap, out invalidFileDiagnostics); } - private static AdditionalText TryGetCodeMetricsConfigurationFile(ImmutableArray additionalFiles, CancellationToken cancellationToken) + private static AdditionalText? TryGetCodeMetricsConfigurationFile(ImmutableArray additionalFiles, CancellationToken cancellationToken) { StringComparer comparer = StringComparer.Ordinal; foreach (AdditionalText textFile in additionalFiles) @@ -341,8 +342,8 @@ private static AdditionalText TryGetCodeMetricsConfigurationFile(ImmutableArray< private static bool TryParseCodeMetricsConfigurationFile( AdditionalText additionalText, CancellationToken cancellationToken, - out ImmutableDictionary> ruleIdToThresholdMap, - out List invalidFileDiagnostics) + [NotNullWhen(returnValue: true)] out ImmutableDictionary>? ruleIdToThresholdMap, + out List? invalidFileDiagnostics) { // Parse the additional file with Metric rule ID (which may contain an optional parenthesized SymbolKind suffix) and custom threshold. // # FORMAT: diff --git a/src/Microsoft.CodeQuality.Analyzers/Core/Maintainability/DoNotIgnoreMethodResults.cs b/src/Microsoft.CodeQuality.Analyzers/Core/Maintainability/DoNotIgnoreMethodResults.cs index 4251d7a205..8bdbb49e1a 100644 --- a/src/Microsoft.CodeQuality.Analyzers/Core/Maintainability/DoNotIgnoreMethodResults.cs +++ b/src/Microsoft.CodeQuality.Analyzers/Core/Maintainability/DoNotIgnoreMethodResults.cs @@ -130,9 +130,9 @@ public override void Initialize(AnalysisContext analysisContext) analysisContext.RegisterCompilationStartAction(compilationContext => { - INamedTypeSymbol expectedExceptionType = compilationContext.Compilation.GetOrCreateTypeByMetadataName(WellKnownTypeNames.MicrosoftVisualStudioTestToolsUnitTestingExpectedExceptionAttribute); - INamedTypeSymbol nunitAssertType = compilationContext.Compilation.GetOrCreateTypeByMetadataName(WellKnownTypeNames.NUnitFrameworkAssert); - INamedTypeSymbol xunitAssertType = compilationContext.Compilation.GetOrCreateTypeByMetadataName(WellKnownTypeNames.XunitAssert); + INamedTypeSymbol? expectedExceptionType = compilationContext.Compilation.GetOrCreateTypeByMetadataName(WellKnownTypeNames.MicrosoftVisualStudioTestToolsUnitTestingExpectedExceptionAttribute); + INamedTypeSymbol? nunitAssertType = compilationContext.Compilation.GetOrCreateTypeByMetadataName(WellKnownTypeNames.NUnitFrameworkAssert); + INamedTypeSymbol? xunitAssertType = compilationContext.Compilation.GetOrCreateTypeByMetadataName(WellKnownTypeNames.XunitAssert); compilationContext.RegisterOperationBlockStartAction(osContext => { @@ -144,8 +144,8 @@ public override void Initialize(AnalysisContext analysisContext) osContext.RegisterOperationAction(opContext => { IOperation expression = ((IExpressionStatementOperation)opContext.Operation).Operation; - DiagnosticDescriptor rule = null; - string targetMethodName = null; + DiagnosticDescriptor? rule = null; + string? targetMethodName = null; switch (expression.Kind) { case OperationKind.ObjectCreation: @@ -201,9 +201,9 @@ public override void Initialize(AnalysisContext analysisContext) }); } - private static bool ShouldSkipAnalyzing(OperationAnalysisContext operationContext, INamedTypeSymbol expectedExceptionType, INamedTypeSymbol xunitAssertType, INamedTypeSymbol nunitAssertType) + private static bool ShouldSkipAnalyzing(OperationAnalysisContext operationContext, INamedTypeSymbol? expectedExceptionType, INamedTypeSymbol? xunitAssertType, INamedTypeSymbol? nunitAssertType) { - static bool IsThrowsArgument(IParameterSymbol parameterSymbol, string argumentName, ImmutableHashSet methodNames, INamedTypeSymbol assertSymbol) + static bool IsThrowsArgument(IParameterSymbol parameterSymbol, string argumentName, ImmutableHashSet methodNames, INamedTypeSymbol? assertSymbol) { return parameterSymbol.Name == argumentName && parameterSymbol.ContainingSymbol is IMethodSymbol methodSymbol && @@ -284,7 +284,7 @@ bool IsXunitThrowsArgument(IParameterSymbol parameterSymbol) } else { - IArgumentOperation argumentOperation = enclosingBlock.GetAncestor(OperationKind.Argument); + IArgumentOperation? argumentOperation = enclosingBlock.GetAncestor(OperationKind.Argument); if (argumentOperation == null) { diff --git a/src/Microsoft.CodeQuality.Analyzers/Core/Maintainability/ReviewUnusedParameters.Fixer.cs b/src/Microsoft.CodeQuality.Analyzers/Core/Maintainability/ReviewUnusedParameters.Fixer.cs index 8b68d0d082..c65fa734dc 100644 --- a/src/Microsoft.CodeQuality.Analyzers/Core/Maintainability/ReviewUnusedParameters.Fixer.cs +++ b/src/Microsoft.CodeQuality.Analyzers/Core/Maintainability/ReviewUnusedParameters.Fixer.cs @@ -169,9 +169,9 @@ private static bool IsSafeMethodToRemoveParameter(ISymbol methodDeclarationSymbo case SymbolKind.Property: return false; case SymbolKind.Method: - var methodSymbol = methodDeclarationSymbol as IMethodSymbol; + var methodSymbol = (IMethodSymbol)methodDeclarationSymbol; // Should not remove parameter for a conversion operator. - return (methodSymbol.MethodKind != MethodKind.Conversion); + return methodSymbol.MethodKind != MethodKind.Conversion; default: return true; } diff --git a/src/Microsoft.CodeQuality.Analyzers/Core/Maintainability/ReviewUnusedParameters.cs b/src/Microsoft.CodeQuality.Analyzers/Core/Maintainability/ReviewUnusedParameters.cs index ec9816f7f8..ba955047ac 100644 --- a/src/Microsoft.CodeQuality.Analyzers/Core/Maintainability/ReviewUnusedParameters.cs +++ b/src/Microsoft.CodeQuality.Analyzers/Core/Maintainability/ReviewUnusedParameters.cs @@ -50,19 +50,19 @@ public override void Initialize(AnalysisContext context) context.RegisterCompilationStartAction(compilationStartContext => { - INamedTypeSymbol eventsArgSymbol = compilationStartContext.Compilation.GetOrCreateTypeByMetadataName(WellKnownTypeNames.SystemEventArgs); + INamedTypeSymbol? eventsArgSymbol = compilationStartContext.Compilation.GetOrCreateTypeByMetadataName(WellKnownTypeNames.SystemEventArgs); // Ignore conditional methods (FxCop compat - One conditional will often call another conditional method as its only use of a parameter) - INamedTypeSymbol conditionalAttributeSymbol = compilationStartContext.Compilation.GetOrCreateTypeByMetadataName(WellKnownTypeNames.SystemDiagnosticsConditionalAttribute); + INamedTypeSymbol? conditionalAttributeSymbol = compilationStartContext.Compilation.GetOrCreateTypeByMetadataName(WellKnownTypeNames.SystemDiagnosticsConditionalAttribute); // Ignore methods with special serialization attributes (FxCop compat - All serialization methods need to take 'StreamingContext') - INamedTypeSymbol onDeserializingAttribute = compilationStartContext.Compilation.GetOrCreateTypeByMetadataName(WellKnownTypeNames.SystemRuntimeSerializationOnDeserializingAttribute); - INamedTypeSymbol onDeserializedAttribute = compilationStartContext.Compilation.GetOrCreateTypeByMetadataName(WellKnownTypeNames.SystemRuntimeSerializationOnDeserializedAttribute); - INamedTypeSymbol onSerializingAttribute = compilationStartContext.Compilation.GetOrCreateTypeByMetadataName(WellKnownTypeNames.SystemRuntimeSerializationOnSerializingAttribute); - INamedTypeSymbol onSerializedAttribute = compilationStartContext.Compilation.GetOrCreateTypeByMetadataName(WellKnownTypeNames.SystemRuntimeSerializationOnSerializedAttribute); - INamedTypeSymbol obsoleteAttribute = compilationStartContext.Compilation.GetOrCreateTypeByMetadataName(WellKnownTypeNames.SystemObsoleteAttribute); + INamedTypeSymbol? onDeserializingAttribute = compilationStartContext.Compilation.GetOrCreateTypeByMetadataName(WellKnownTypeNames.SystemRuntimeSerializationOnDeserializingAttribute); + INamedTypeSymbol? onDeserializedAttribute = compilationStartContext.Compilation.GetOrCreateTypeByMetadataName(WellKnownTypeNames.SystemRuntimeSerializationOnDeserializedAttribute); + INamedTypeSymbol? onSerializingAttribute = compilationStartContext.Compilation.GetOrCreateTypeByMetadataName(WellKnownTypeNames.SystemRuntimeSerializationOnSerializingAttribute); + INamedTypeSymbol? onSerializedAttribute = compilationStartContext.Compilation.GetOrCreateTypeByMetadataName(WellKnownTypeNames.SystemRuntimeSerializationOnSerializedAttribute); + INamedTypeSymbol? obsoleteAttribute = compilationStartContext.Compilation.GetOrCreateTypeByMetadataName(WellKnownTypeNames.SystemObsoleteAttribute); - ImmutableHashSet attributeSetForMethodsToIgnore = ImmutableHashSet.Create( + ImmutableHashSet attributeSetForMethodsToIgnore = ImmutableHashSet.Create( conditionalAttributeSymbol, onDeserializedAttribute, onDeserializingAttribute, @@ -118,9 +118,9 @@ public override void Initialize(AnalysisContext context) IMethodSymbol method, OperationBlockStartAnalysisContext startOperationBlockContext, UnusedParameterDictionary unusedMethodParameters, - INamedTypeSymbol eventsArgSymbol, + INamedTypeSymbol? eventsArgSymbol, ISet methodsUsedAsDelegates, - ImmutableHashSet attributeSetForMethodsToIgnore) + ImmutableHashSet attributeSetForMethodsToIgnore) { // We only care about methods with parameters. if (method.Parameters.IsEmpty) diff --git a/src/Microsoft.CodeQuality.Analyzers/Core/Maintainability/UseNameofInPlaceOfString.Fixer.cs b/src/Microsoft.CodeQuality.Analyzers/Core/Maintainability/UseNameofInPlaceOfString.Fixer.cs index b57124e88b..f147f5a72d 100644 --- a/src/Microsoft.CodeQuality.Analyzers/Core/Maintainability/UseNameofInPlaceOfString.Fixer.cs +++ b/src/Microsoft.CodeQuality.Analyzers/Core/Maintainability/UseNameofInPlaceOfString.Fixer.cs @@ -32,10 +32,14 @@ public sealed override async Task RegisterCodeFixesAsync(CodeFixContext context) var root = await context.Document.GetSyntaxRootAsync(context.CancellationToken).ConfigureAwait(false); var diagnostics = context.Diagnostics; var diagnosticSpan = context.Span; + // getInnerModeNodeForTie = true so we are replacing the string literal node and not the whole argument node var nodeToReplace = root.FindNode(diagnosticSpan, getInnermostNodeForTie: true); + if (nodeToReplace == null) + { + return; + } - Debug.Assert(nodeToReplace != null); var stringText = nodeToReplace.FindToken(diagnosticSpan.Start).ValueText; context.RegisterCodeFix(CodeAction.Create( MicrosoftCodeQualityAnalyzersResources.UseNameOfInPlaceOfStringTitle, diff --git a/src/Microsoft.CodeQuality.Analyzers/Core/QualityGuidelines/AbstractRemoveEmptyFinalizers.cs b/src/Microsoft.CodeQuality.Analyzers/Core/QualityGuidelines/AbstractRemoveEmptyFinalizers.cs index d5a6d8f206..981d07768d 100644 --- a/src/Microsoft.CodeQuality.Analyzers/Core/QualityGuidelines/AbstractRemoveEmptyFinalizers.cs +++ b/src/Microsoft.CodeQuality.Analyzers/Core/QualityGuidelines/AbstractRemoveEmptyFinalizers.cs @@ -55,8 +55,8 @@ public override void Initialize(AnalysisContext analysisContext) }); } - protected static bool InvocationIsConditional(IMethodSymbol methodSymbol, INamedTypeSymbol conditionalAttributeSymbol) => - methodSymbol.GetAttributes().Any(n => n.AttributeClass.Equals(conditionalAttributeSymbol)); + protected static bool InvocationIsConditional(IMethodSymbol methodSymbol, INamedTypeSymbol? conditionalAttributeSymbol) => + conditionalAttributeSymbol != null && methodSymbol.GetAttributes().Any(n => n.AttributeClass.Equals(conditionalAttributeSymbol)); protected abstract bool IsEmptyFinalizer(SyntaxNode methodBody, CodeBlockAnalysisContext analysisContext); } diff --git a/src/Microsoft.CodeQuality.Analyzers/Core/QualityGuidelines/DoNotCallOverridableMethodsInConstructors.cs b/src/Microsoft.CodeQuality.Analyzers/Core/QualityGuidelines/DoNotCallOverridableMethodsInConstructors.cs index 851e36751c..0a3adc3d81 100644 --- a/src/Microsoft.CodeQuality.Analyzers/Core/QualityGuidelines/DoNotCallOverridableMethodsInConstructors.cs +++ b/src/Microsoft.CodeQuality.Analyzers/Core/QualityGuidelines/DoNotCallOverridableMethodsInConstructors.cs @@ -44,8 +44,8 @@ public override void Initialize(AnalysisContext analysisContext) analysisContext.RegisterCompilationStartAction(compilationContext => { - INamedTypeSymbol webUiControlType = compilationContext.Compilation.GetOrCreateTypeByMetadataName(WellKnownTypeNames.SystemWebUIControl); - INamedTypeSymbol componentModelComponentType = compilationContext.Compilation.GetOrCreateTypeByMetadataName(WellKnownTypeNames.SystemComponentModelComponent); + INamedTypeSymbol? webUiControlType = compilationContext.Compilation.GetOrCreateTypeByMetadataName(WellKnownTypeNames.SystemWebUIControl); + INamedTypeSymbol? componentModelComponentType = compilationContext.Compilation.GetOrCreateTypeByMetadataName(WellKnownTypeNames.SystemComponentModelComponent); compilationContext.RegisterOperationBlockStartAction(context => { @@ -61,7 +61,7 @@ public override void Initialize(AnalysisContext analysisContext) private static void AnalyzeOperation(OperationAnalysisContext context, INamedTypeSymbol containingType) { - var operation = context.Operation as IInvocationOperation; + var operation = (IInvocationOperation)context.Operation; IMethodSymbol method = operation.TargetMethod; if (method != null && (method.IsAbstract || method.IsVirtual) && @@ -72,7 +72,7 @@ private static void AnalyzeOperation(OperationAnalysisContext context, INamedTyp } } - private static bool ShouldOmitThisDiagnostic(ISymbol symbol, INamedTypeSymbol webUiControlType, INamedTypeSymbol componentModelComponentType) + private static bool ShouldOmitThisDiagnostic(ISymbol symbol, INamedTypeSymbol? webUiControlType, INamedTypeSymbol? componentModelComponentType) { // This diagnostic is only relevant in constructors. // TODO: should this apply to instance field initializers for VB? diff --git a/src/Microsoft.CodeQuality.Analyzers/Core/QualityGuidelines/MarkMembersAsStatic.Fixer.cs b/src/Microsoft.CodeQuality.Analyzers/Core/QualityGuidelines/MarkMembersAsStatic.Fixer.cs index 46b6472fd8..2aacf76065 100644 --- a/src/Microsoft.CodeQuality.Analyzers/Core/QualityGuidelines/MarkMembersAsStatic.Fixer.cs +++ b/src/Microsoft.CodeQuality.Analyzers/Core/QualityGuidelines/MarkMembersAsStatic.Fixer.cs @@ -25,8 +25,8 @@ public abstract class MarkMembersAsStaticFixer : CodeFixProvider { private static readonly SyntaxAnnotation s_annotationForFixedDeclaration = new SyntaxAnnotation(); - protected abstract IEnumerable GetTypeArguments(SyntaxNode node); - protected abstract SyntaxNode GetExpressionOfInvocation(SyntaxNode invocation); + protected abstract IEnumerable? GetTypeArguments(SyntaxNode node); + protected abstract SyntaxNode? GetExpressionOfInvocation(SyntaxNode invocation); protected virtual SyntaxNode GetSyntaxNodeToReplace(IMemberReferenceOperation memberReference) => memberReference.Syntax; @@ -134,7 +134,7 @@ private async Task<(Solution newSolution, bool allReferencesFixed)> UpdateRefere } var operation = semanticModel.GetOperationWalkingUpParentChain(referenceNode, cancellationToken); - SyntaxNode nodeToReplaceOpt = null; + SyntaxNode? nodeToReplaceOpt = null; switch (operation) { case IMemberReferenceOperation memberReference: @@ -213,7 +213,7 @@ static bool IsReplacableOperation(IOperation operation) return false; } - ISymbol GetSymbolForNodeToReplace(SyntaxNode nodeToReplace, SemanticModel semanticModel) + ISymbol? GetSymbolForNodeToReplace(SyntaxNode nodeToReplace, SemanticModel semanticModel) { var symbolInfo = semanticModel.GetSymbolInfo(nodeToReplace, cancellationToken); var symbolForNodeToReplace = symbolInfo.Symbol; diff --git a/src/Microsoft.CodeQuality.Analyzers/Core/QualityGuidelines/MarkMembersAsStatic.cs b/src/Microsoft.CodeQuality.Analyzers/Core/QualityGuidelines/MarkMembersAsStatic.cs index a862d98084..0b771f234d 100644 --- a/src/Microsoft.CodeQuality.Analyzers/Core/QualityGuidelines/MarkMembersAsStatic.cs +++ b/src/Microsoft.CodeQuality.Analyzers/Core/QualityGuidelines/MarkMembersAsStatic.cs @@ -229,9 +229,9 @@ private static bool IsExplicitlyVisibleFromCom(IMethodSymbol methodSymbol, Compi private static ImmutableArray GetSkippedAttributes(Compilation compilation) { - ImmutableArray.Builder builder = null; + ImmutableArray.Builder? builder = null; - void Add(INamedTypeSymbol symbol) + void Add(INamedTypeSymbol? symbol) { if (symbol != null) { diff --git a/src/Microsoft.CodeQuality.Analyzers/Core/QualityGuidelines/UseLiteralsWhereAppropriate.Fixer.cs b/src/Microsoft.CodeQuality.Analyzers/Core/QualityGuidelines/UseLiteralsWhereAppropriate.Fixer.cs index 2590c15e83..7f1f781118 100644 --- a/src/Microsoft.CodeQuality.Analyzers/Core/QualityGuidelines/UseLiteralsWhereAppropriate.Fixer.cs +++ b/src/Microsoft.CodeQuality.Analyzers/Core/QualityGuidelines/UseLiteralsWhereAppropriate.Fixer.cs @@ -91,7 +91,7 @@ private async Task ToConstantDeclarationAsync(Document document, Synta return editor.GetChangedDocument(); } - protected abstract SyntaxNode GetFieldDeclaration(SyntaxNode syntaxNode); + protected abstract SyntaxNode? GetFieldDeclaration(SyntaxNode syntaxNode); protected abstract bool IsStaticKeyword(SyntaxToken syntaxToken); protected abstract bool IsReadonlyKeyword(SyntaxToken syntaxToken); protected abstract SyntaxToken GetConstKeywordToken(); diff --git a/src/Microsoft.CodeQuality.Analyzers/Core/QualityGuidelines/UseLiteralsWhereAppropriate.cs b/src/Microsoft.CodeQuality.Analyzers/Core/QualityGuidelines/UseLiteralsWhereAppropriate.cs index 54de51fe5a..b22d9b4d8c 100644 --- a/src/Microsoft.CodeQuality.Analyzers/Core/QualityGuidelines/UseLiteralsWhereAppropriate.cs +++ b/src/Microsoft.CodeQuality.Analyzers/Core/QualityGuidelines/UseLiteralsWhereAppropriate.cs @@ -61,6 +61,7 @@ public override void Initialize(AnalysisContext analysisContext) var lastField = fieldInitializer?.InitializedFields.LastOrDefault(); var fieldInitializerValue = fieldInitializer?.Value; if (fieldInitializerValue == null || + lastField == null || lastField.IsConst || !lastField.IsReadOnly || !fieldInitializerValue.ConstantValue.HasValue || diff --git a/src/Microsoft.CodeQuality.Analyzers/Core/QualityGuidelines/ValidateArgumentsOfPublicMethods.cs b/src/Microsoft.CodeQuality.Analyzers/Core/QualityGuidelines/ValidateArgumentsOfPublicMethods.cs index ff75ea8559..908de98b65 100644 --- a/src/Microsoft.CodeQuality.Analyzers/Core/QualityGuidelines/ValidateArgumentsOfPublicMethods.cs +++ b/src/Microsoft.CodeQuality.Analyzers/Core/QualityGuidelines/ValidateArgumentsOfPublicMethods.cs @@ -82,7 +82,7 @@ public override void Initialize(AnalysisContext context) } // Perform analysis of all direct/indirect parameter usages in the method to get all non-validated usages that can cause a null dereference. - ImmutableDictionary hazardousParameterUsages = null; + ImmutableDictionary? hazardousParameterUsages = null; foreach (var operationBlock in operationBlockContext.OperationBlocks) { if (operationBlock is IBlockOperation topmostBlock) From a2531f3f7064a06f750fa420d48a273a4a220377 Mon Sep 17 00:00:00 2001 From: Manish Vasani Date: Thu, 7 Nov 2019 15:57:52 -0800 Subject: [PATCH 13/28] Some more nullable annotations for utilities --- .../Extensions/DiagnosticExtensions.cs | 10 +++++----- .../Extensions/IDictionaryExtensions.cs | 6 ++++-- .../IEnumerableOfIMethodSymbolExtensions.cs | 11 +++++++--- .../Compiler/Extensions/ISymbolExtensions.cs | 20 +++++++++---------- .../Extensions/ITypeSymbolExtensions.cs | 3 ++- 5 files changed, 29 insertions(+), 21 deletions(-) diff --git a/src/Utilities/Compiler/Extensions/DiagnosticExtensions.cs b/src/Utilities/Compiler/Extensions/DiagnosticExtensions.cs index 056d3a54c0..a462c20ae2 100644 --- a/src/Utilities/Compiler/Extensions/DiagnosticExtensions.cs +++ b/src/Utilities/Compiler/Extensions/DiagnosticExtensions.cs @@ -34,7 +34,7 @@ internal static class DiagnosticExtensions public static Diagnostic CreateDiagnostic( this SyntaxNode node, DiagnosticDescriptor rule, - ImmutableDictionary properties, + ImmutableDictionary properties, params object[] args) => node .GetLocation() @@ -115,13 +115,13 @@ internal static class DiagnosticExtensions => location .CreateDiagnostic( rule: rule, - properties: ImmutableDictionary.Empty, + properties: ImmutableDictionary.Empty, args: args); public static Diagnostic CreateDiagnostic( this Location location, DiagnosticDescriptor rule, - ImmutableDictionary properties, + ImmutableDictionary properties, params object[] args) { if (!location.IsInSource) @@ -158,7 +158,7 @@ internal static class DiagnosticExtensions public static Diagnostic CreateDiagnostic( this IEnumerable locations, DiagnosticDescriptor rule, - ImmutableDictionary? properties, + ImmutableDictionary? properties, params object[] args) { IEnumerable inSource = locations.Where(l => l.IsInSource); @@ -197,7 +197,7 @@ internal static class DiagnosticExtensions this Compilation compilation, DiagnosticDescriptor rule, Action addDiagnostic, - ImmutableDictionary? properties, + ImmutableDictionary? properties, params object[] args) { var effectiveSeverity = GetEffectiveSeverity(); diff --git a/src/Utilities/Compiler/Extensions/IDictionaryExtensions.cs b/src/Utilities/Compiler/Extensions/IDictionaryExtensions.cs index 7ad339f24b..81eeaa81a6 100644 --- a/src/Utilities/Compiler/Extensions/IDictionaryExtensions.cs +++ b/src/Utilities/Compiler/Extensions/IDictionaryExtensions.cs @@ -8,8 +8,10 @@ internal static class IDictionaryExtensions { public static void AddKeyValueIfNotNull( this IDictionary dictionary, - TKey key, - TValue value) + TKey? key, + TValue? value) + where TKey : class + where TValue : class { if (key != null && value != null) { diff --git a/src/Utilities/Compiler/Extensions/IEnumerableOfIMethodSymbolExtensions.cs b/src/Utilities/Compiler/Extensions/IEnumerableOfIMethodSymbolExtensions.cs index 2ae0207748..f3c31b5402 100644 --- a/src/Utilities/Compiler/Extensions/IEnumerableOfIMethodSymbolExtensions.cs +++ b/src/Utilities/Compiler/Extensions/IEnumerableOfIMethodSymbolExtensions.cs @@ -15,9 +15,14 @@ internal static class IEnumerableOfIMethodSymbolExtensions /// A filtered list of methods. public static IEnumerable WhereMethodDoesNotContainAttribute( this IEnumerable methods, - INamedTypeSymbol attributeType) + INamedTypeSymbol? attributeType) { - return methods.Where(m => !m.GetAttributes().Any(a => a.AttributeClass.Equals(attributeType))); + if (attributeType == null) + { + return methods; + } + + return methods.Where(m => !m.HasAttribute(attributeType)); } /// @@ -100,7 +105,7 @@ internal static class IEnumerableOfIMethodSymbolExtensions /// /// /// - public static IMethodSymbol? GetFirstOrDefaultMemberWithParameterInfos(this IEnumerable members, params ParameterInfo[] expectedParameterTypesInOrder) + public static IMethodSymbol? GetFirstOrDefaultMemberWithParameterInfos(this IEnumerable? members, params ParameterInfo[] expectedParameterTypesInOrder) { var expectedParameterCount = expectedParameterTypesInOrder.Length; return members?.FirstOrDefault(member => diff --git a/src/Utilities/Compiler/Extensions/ISymbolExtensions.cs b/src/Utilities/Compiler/Extensions/ISymbolExtensions.cs index 11f23d0d2f..3acb5d4066 100644 --- a/src/Utilities/Compiler/Extensions/ISymbolExtensions.cs +++ b/src/Utilities/Compiler/Extensions/ISymbolExtensions.cs @@ -83,45 +83,45 @@ public static bool IsPrivate(this ISymbol symbol) return symbol.DeclaredAccessibility == Accessibility.Private; } - public static bool IsErrorType(this ISymbol symbol) + public static bool IsErrorType(this ISymbol? symbol) { return symbol is ITypeSymbol && ((ITypeSymbol)symbol).TypeKind == TypeKind.Error; } - public static bool IsConstructor(this ISymbol symbol) + public static bool IsConstructor(this ISymbol? symbol) { return (symbol as IMethodSymbol)?.MethodKind == MethodKind.Constructor; } - public static bool IsDestructor(this ISymbol symbol) + public static bool IsDestructor(this ISymbol? symbol) { return (symbol as IMethodSymbol)?.IsFinalizer() ?? false; } - public static bool IsIndexer(this ISymbol symbol) + public static bool IsIndexer(this ISymbol? symbol) { return (symbol as IPropertySymbol)?.IsIndexer == true; } - public static bool IsPropertyWithBackingField(this ISymbol symbol) + public static bool IsPropertyWithBackingField(this ISymbol? symbol) { return symbol is IPropertySymbol propertySymbol && propertySymbol.ContainingType.GetMembers().OfType().Any(f => f.IsImplicitlyDeclared && Equals(f.AssociatedSymbol, symbol)); } - public static bool IsUserDefinedOperator(this ISymbol symbol) + public static bool IsUserDefinedOperator(this ISymbol? symbol) { return (symbol as IMethodSymbol)?.MethodKind == MethodKind.UserDefinedOperator; } - public static bool IsConversionOperator(this ISymbol symbol) + public static bool IsConversionOperator(this ISymbol? symbol) { return (symbol as IMethodSymbol)?.MethodKind == MethodKind.Conversion; } - public static ImmutableArray GetParameters(this ISymbol symbol) + public static ImmutableArray GetParameters(this ISymbol? symbol) { return symbol switch { @@ -648,9 +648,9 @@ public static bool IsReadOnlyFieldOrProperty(this ISymbol? symbol) /// If is a type, this method does not find attributes /// on its base types. /// - public static bool HasAttribute(this ISymbol symbol, INamedTypeSymbol attribute) + public static bool HasAttribute(this ISymbol symbol, INamedTypeSymbol? attribute) { - return symbol.GetAttributes().Any(attr => attr.AttributeClass.Equals(attribute)); + return attribute != null && symbol.GetAttributes().Any(attr => attr.AttributeClass.Equals(attribute)); } /// diff --git a/src/Utilities/Compiler/Extensions/ITypeSymbolExtensions.cs b/src/Utilities/Compiler/Extensions/ITypeSymbolExtensions.cs index 345995abf4..f04b1bf01a 100644 --- a/src/Utilities/Compiler/Extensions/ITypeSymbolExtensions.cs +++ b/src/Utilities/Compiler/Extensions/ITypeSymbolExtensions.cs @@ -2,6 +2,7 @@ using System; using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; using System.Linq; using Microsoft.CodeAnalysis; @@ -77,7 +78,7 @@ public static IEnumerable GetBaseTypesAndThis(this ITypeSymbol type } } - public static bool DerivesFrom(this ITypeSymbol? symbol, ITypeSymbol? candidateBaseType, bool baseTypesOnly = false, bool checkTypeParameterConstraints = true) + public static bool DerivesFrom([NotNullWhen(returnValue: true)] this ITypeSymbol? symbol, [NotNullWhen(returnValue: true)] ITypeSymbol? candidateBaseType, bool baseTypesOnly = false, bool checkTypeParameterConstraints = true) { if (candidateBaseType == null || symbol == null) { From 9090966bd93671e908939ef3d3c256647b1f66d4 Mon Sep 17 00:00:00 2001 From: Manish Vasani Date: Thu, 7 Nov 2019 15:58:28 -0800 Subject: [PATCH 14/28] Additional nullable annotations to a code quality analyzer --- .../DefineAccessorsForAttributeArguments.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Microsoft.CodeQuality.Analyzers/Core/ApiDesignGuidelines/DefineAccessorsForAttributeArguments.cs b/src/Microsoft.CodeQuality.Analyzers/Core/ApiDesignGuidelines/DefineAccessorsForAttributeArguments.cs index 81ad342f57..5c78bc46b1 100644 --- a/src/Microsoft.CodeQuality.Analyzers/Core/ApiDesignGuidelines/DefineAccessorsForAttributeArguments.cs +++ b/src/Microsoft.CodeQuality.Analyzers/Core/ApiDesignGuidelines/DefineAccessorsForAttributeArguments.cs @@ -188,19 +188,19 @@ private void AnalyzeParameters(Compilation compilation, IEnumerable { { "case", AddAccessorCase } }.ToImmutableDictionary(), parameter.Name, attributeType.Name); + return parameter.Locations.CreateDiagnostic(DefaultRule, new Dictionary { { "case", AddAccessorCase } }.ToImmutableDictionary(), parameter.Name, attributeType.Name); } private static Diagnostic GetIncreaseVisibilityDiagnostic(IParameterSymbol parameter, IPropertySymbol property) { // If '{0}' is the property accessor for positional argument '{1}', make it public. - return property.GetMethod.Locations.CreateDiagnostic(IncreaseVisibilityRule, new Dictionary { { "case", MakePublicCase } }.ToImmutableDictionary(), property.Name, parameter.Name); + return property.GetMethod.Locations.CreateDiagnostic(IncreaseVisibilityRule, new Dictionary { { "case", MakePublicCase } }.ToImmutableDictionary(), property.Name, parameter.Name); } private static Diagnostic GetRemoveSetterDiagnostic(IParameterSymbol parameter, IPropertySymbol property) { // Remove the property setter from '{0}' or reduce its accessibility because it corresponds to positional argument '{1}'. - return property.SetMethod.Locations.CreateDiagnostic(RemoveSetterRule, new Dictionary { { "case", RemoveSetterCase } }.ToImmutableDictionary(), property.Name, parameter.Name); + return property.SetMethod.Locations.CreateDiagnostic(RemoveSetterRule, new Dictionary { { "case", RemoveSetterCase } }.ToImmutableDictionary(), property.Name, parameter.Name); } } } From 2404ec0009697e2f85bc903343bc15cbe6030165 Mon Sep 17 00:00:00 2001 From: Manish Vasani Date: Thu, 7 Nov 2019 15:58:46 -0800 Subject: [PATCH 15/28] Add nullable annotations for Microsoft.NetCore.Analyzers --- ...harpDoNotUseCountWhenAnyCanBeUsed.Fixer.cs | 55 +++++++++++-------- ...InsteadOfCountMethodWhenAvailable.Fixer.cs | 6 +- .../CSharpUseOrdinalStringComparison.Fixer.cs | 4 +- ...iewSqlQueriesForSecurityVulnerabilities.cs | 6 +- .../PInvokeDiagnosticAnalyzer.cs | 8 +-- ...rshalingForPInvokeStringArguments.Fixer.cs | 8 +-- .../DoNotUseCountWhenAnyCanBeUsed.Fixer.cs | 8 ++- .../DoNotUseCountWhenAnyCanBeUsed.cs | 17 +++--- ...InsteadOfCountMethodWhenAvailable.Fixer.cs | 6 +- ...opertyInsteadOfCountMethodWhenAvailable.cs | 26 ++++----- ...kAssembliesWithNeutralResourcesLanguage.cs | 6 +- ...ibuteStringLiteralsShouldParseCorrectly.cs | 12 ++-- .../Core/Runtime/AvoidUnsealedAttributes.cs | 2 +- .../AvoidZeroLengthArrayAllocations.Fixer.cs | 15 +++-- .../AvoidZeroLengthArrayAllocations.cs | 11 +++- .../CallGCSuppressFinalizeCorrectly.cs | 8 +-- .../DisposableFieldsShouldBeDisposed.cs | 18 ++++-- .../DisposableTypesShouldDeclareFinalizer.cs | 2 +- ...isposeMethodsShouldCallBaseClassDispose.cs | 2 +- .../DisposeObjectsBeforeLosingScope.cs | 6 +- .../DoNotLockOnObjectsWithWeakIdentity.cs | 18 +++--- .../DoNotPassLiteralsAsLocalizedParameters.cs | 42 +++++++------- .../DoNotRaiseReservedExceptionTypes.cs | 4 +- ...mplementSerializationConstructors.Fixer.cs | 13 ++--- .../InstantiateArgumentExceptionsCorrectly.cs | 10 ++-- .../MarkAllNonSerializableFields.Fixer.cs | 2 +- .../Runtime/NormalizeStringsToUppercase.cs | 2 +- ...videCorrectArgumentsToFormattingMethods.cs | 15 ++--- .../SerializationRulesDiagnosticAnalyzer.cs | 10 ++-- .../Core/Runtime/SpecifyIFormatProvider.cs | 10 +++- ...tForEmptyStringsUsingStringLength.Fixer.cs | 4 +- .../Core/Runtime/TestForNaNCorrectly.Fixer.cs | 14 ++--- .../UseOrdinalStringComparison.Fixer.cs | 26 +-------- .../Runtime/UseOrdinalStringComparison.cs | 2 +- .../Security/ApprovedCipherModeAnalyzer.cs | 2 +- ...otCallDangerousMethodsInDeserialization.cs | 20 ++++--- .../DoNotDisableCertificateValidation.cs | 2 +- .../DoNotDisableHttpClientCRLCheck.cs | 6 +- .../Security/DoNotDisableRequestValidation.cs | 3 +- .../Core/Security/DoNotInstallRootCert.cs | 2 +- .../DoNotReferSelfInSerializableClass.cs | 6 +- .../DoNotSerializeTypeWithPointerFields.cs | 4 +- .../Core/Security/DoNotSetSwitch.cs | 4 ++ .../Core/Security/DoNotUseAccountSAS.cs | 3 +- ...DoNotUseCreateEncryptorWithNonDefaultIV.cs | 2 +- .../DoNotUseDeprecatedSecurityProtocols.cs | 9 ++- ...DoNotUseInsecureCryptographicAlgorithms.cs | 6 +- ...ascriptSerializerWithSimpleTypeResolver.cs | 8 +-- ...nsecureDeserializerJsonNetWithoutBinder.cs | 6 +- ...DoNotUseInsecureDeserializerMethodsBase.cs | 5 +- ...seInsecureDeserializerWithoutBinderBase.cs | 14 ++--- .../DoNotUseInsecureSettingsForJsonNet.cs | 10 ++-- .../Security/DoNotUseObsoleteKDFAlgorithm.cs | 4 +- .../Core/Security/DoNotUseWeakKDFAlgorithm.cs | 5 +- ...NotUseWeakKDFInsufficientIterationCount.cs | 2 +- .../Helpers/CompilationSecurityTypes.cs | 22 ++++---- .../Core/Security/Helpers/SecurityHelpers.cs | 8 +-- .../Core/Security/JsonNetTypeNameHandling.cs | 5 +- .../Core/Security/SetHttpOnlyForHttpCookie.cs | 4 +- .../SourceTriggeredTaintedDataAnalyzerBase.cs | 3 + .../Core/Security/SslProtocolsAnalyzer.cs | 11 ++-- .../UseAutoValidateAntiforgeryToken.cs | 5 +- ...UseDefaultDllImportSearchPathsAttribute.cs | 5 +- .../Security/UseSecureCookiesASPNetCore.cs | 2 +- .../UseSharedAccessProtocolHttpsOnly.cs | 6 +- .../Core/Security/UseXmlReaderBase.cs | 18 ++---- 66 files changed, 309 insertions(+), 301 deletions(-) diff --git a/src/Microsoft.NetCore.Analyzers/CSharp/Performance/CSharpDoNotUseCountWhenAnyCanBeUsed.Fixer.cs b/src/Microsoft.NetCore.Analyzers/CSharp/Performance/CSharpDoNotUseCountWhenAnyCanBeUsed.Fixer.cs index bd876f0fd7..ff6d417299 100644 --- a/src/Microsoft.NetCore.Analyzers/CSharp/Performance/CSharpDoNotUseCountWhenAnyCanBeUsed.Fixer.cs +++ b/src/Microsoft.NetCore.Analyzers/CSharp/Performance/CSharpDoNotUseCountWhenAnyCanBeUsed.Fixer.cs @@ -2,6 +2,7 @@ using System.Collections.Generic; using System.Composition; +using System.Diagnostics.CodeAnalysis; using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.CodeFixes; using Microsoft.CodeAnalysis.CSharp.Syntax; @@ -26,21 +27,25 @@ public sealed class CSharpDoNotUseCountWhenAnyCanBeUsedFixer : DoNotUseCountWhen /// If this method returns , contains the arguments from Any to be used on Count. /// if a fixer was found., otherwise. /// - protected override bool TryGetFixer(SyntaxNode node, string operation, bool isAsync, out SyntaxNode expression, out IEnumerable arguments) + protected override bool TryGetFixer( + SyntaxNode node, + string operation, + bool isAsync, + [NotNullWhen(returnValue: true)] out SyntaxNode? expression, + [NotNullWhen(returnValue: true)] out IEnumerable? arguments) { switch (operation) { case DoNotUseCountWhenAnyCanBeUsedAnalyzer.OperationEqualsInstance: { if (node is InvocationExpressionSyntax invocation && - invocation.Expression is MemberAccessExpressionSyntax member) - { - GetExpressionAndInvocationArguments( + invocation.Expression is MemberAccessExpressionSyntax member && + TryGetExpressionAndInvocationArguments( sourceExpression: member.Expression, isAsync: isAsync, expression: out expression, - arguments: out arguments); - + arguments: out arguments)) + { return true; } @@ -49,14 +54,13 @@ protected override bool TryGetFixer(SyntaxNode node, string operation, bool isAs case DoNotUseCountWhenAnyCanBeUsedAnalyzer.OperationEqualsArgument: { if (node is InvocationExpressionSyntax invocation && - invocation.ArgumentList.Arguments.Count == 1) - { - GetExpressionAndInvocationArguments( + invocation.ArgumentList.Arguments.Count == 1 && + TryGetExpressionAndInvocationArguments( sourceExpression: invocation.ArgumentList.Arguments[0].Expression, isAsync: isAsync, expression: out expression, - arguments: out arguments); - + arguments: out arguments)) + { return true; } @@ -64,14 +68,13 @@ protected override bool TryGetFixer(SyntaxNode node, string operation, bool isAs } case DoNotUseCountWhenAnyCanBeUsedAnalyzer.OperationBinaryLeft: { - if (node is BinaryExpressionSyntax binary) - { - GetExpressionAndInvocationArguments( + if (node is BinaryExpressionSyntax binary && + TryGetExpressionAndInvocationArguments( sourceExpression: binary.Left, isAsync: isAsync, expression: out expression, - arguments: out arguments); - + arguments: out arguments)) + { return true; } @@ -79,14 +82,13 @@ protected override bool TryGetFixer(SyntaxNode node, string operation, bool isAs } case DoNotUseCountWhenAnyCanBeUsedAnalyzer.OperationBinaryRight: { - if (node is BinaryExpressionSyntax binary) - { - GetExpressionAndInvocationArguments( + if (node is BinaryExpressionSyntax binary && + TryGetExpressionAndInvocationArguments( sourceExpression: binary.Right, isAsync: isAsync, expression: out expression, - arguments: out arguments); - + arguments: out arguments)) + { return true; } @@ -99,14 +101,18 @@ protected override bool TryGetFixer(SyntaxNode node, string operation, bool isAs return false; } - private static void GetExpressionAndInvocationArguments(ExpressionSyntax sourceExpression, bool isAsync, out SyntaxNode expression, out IEnumerable arguments) + private static bool TryGetExpressionAndInvocationArguments( + ExpressionSyntax sourceExpression, + bool isAsync, + [NotNullWhen(returnValue: true)] out SyntaxNode? expression, + [NotNullWhen(returnValue: true)] out IEnumerable? arguments) { while (sourceExpression is ParenthesizedExpressionSyntax parenthesizedExpression) { sourceExpression = parenthesizedExpression.Expression; } - InvocationExpressionSyntax invocationExpression = null; + InvocationExpressionSyntax? invocationExpression = null; if (isAsync) { @@ -124,11 +130,12 @@ private static void GetExpressionAndInvocationArguments(ExpressionSyntax sourceE { expression = default; arguments = default; - return; + return false; } expression = ((MemberAccessExpressionSyntax)invocationExpression.Expression).Expression; arguments = invocationExpression.ArgumentList.ChildNodes(); + return true; } } } diff --git a/src/Microsoft.NetCore.Analyzers/CSharp/Performance/CSharpUsePropertyInsteadOfCountMethodWhenAvailable.Fixer.cs b/src/Microsoft.NetCore.Analyzers/CSharp/Performance/CSharpUsePropertyInsteadOfCountMethodWhenAvailable.Fixer.cs index 99bf9b2f2a..891a2b8996 100644 --- a/src/Microsoft.NetCore.Analyzers/CSharp/Performance/CSharpUsePropertyInsteadOfCountMethodWhenAvailable.Fixer.cs +++ b/src/Microsoft.NetCore.Analyzers/CSharp/Performance/CSharpUsePropertyInsteadOfCountMethodWhenAvailable.Fixer.cs @@ -1,6 +1,7 @@ // Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System.Composition; +using System.Diagnostics.CodeAnalysis; using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.CodeFixes; using Microsoft.CodeAnalysis.CSharp.Syntax; @@ -25,7 +26,10 @@ public sealed class CSharpUsePropertyInsteadOfCountMethodWhenAvailableFixer : Us /// The name node for the invocation node. /// if a and were found; /// otherwise. - protected override bool TryGetExpression(SyntaxNode invocationNode, out SyntaxNode memberAccessNode, out SyntaxNode nameNode) + protected override bool TryGetExpression( + SyntaxNode invocationNode, + [NotNullWhen(returnValue: true)] out SyntaxNode? memberAccessNode, + [NotNullWhen(returnValue: true)] out SyntaxNode? nameNode) { if (invocationNode is InvocationExpressionSyntax invocationExpression) { diff --git a/src/Microsoft.NetCore.Analyzers/CSharp/Runtime/CSharpUseOrdinalStringComparison.Fixer.cs b/src/Microsoft.NetCore.Analyzers/CSharp/Runtime/CSharpUseOrdinalStringComparison.Fixer.cs index 9453458ff7..d6c03a786e 100644 --- a/src/Microsoft.NetCore.Analyzers/CSharp/Runtime/CSharpUseOrdinalStringComparison.Fixer.cs +++ b/src/Microsoft.NetCore.Analyzers/CSharp/Runtime/CSharpUseOrdinalStringComparison.Fixer.cs @@ -47,11 +47,11 @@ protected override bool IsInIdentifierNameContext(SyntaxNode node) protected override async Task FixIdentifierName(Document document, SyntaxGenerator generator, SyntaxNode root, SyntaxNode identifier, CancellationToken cancellationToken) { - InvocationExpressionSyntax invokeParent = identifier?.Parent?.FirstAncestorOrSelf(); + InvocationExpressionSyntax? invokeParent = identifier?.Parent?.FirstAncestorOrSelf(); if (invokeParent != null) { SemanticModel model = await document.GetSemanticModelAsync(cancellationToken).ConfigureAwait(false); - if (model.GetSymbolInfo((IdentifierNameSyntax)identifier, cancellationToken).Symbol is IMethodSymbol methodSymbol && CanAddStringComparison(methodSymbol, model)) + if (model.GetSymbolInfo((IdentifierNameSyntax)identifier!, cancellationToken).Symbol is IMethodSymbol methodSymbol && CanAddStringComparison(methodSymbol, model)) { // append a new StringComparison.Ordinal argument SyntaxNode newArg = generator.Argument(CreateOrdinalMemberAccess(generator, model)) diff --git a/src/Microsoft.NetCore.Analyzers/Core/Data/ReviewSqlQueriesForSecurityVulnerabilities.cs b/src/Microsoft.NetCore.Analyzers/Core/Data/ReviewSqlQueriesForSecurityVulnerabilities.cs index 5a55ec9eb8..7fcd0f251b 100644 --- a/src/Microsoft.NetCore.Analyzers/Core/Data/ReviewSqlQueriesForSecurityVulnerabilities.cs +++ b/src/Microsoft.NetCore.Analyzers/Core/Data/ReviewSqlQueriesForSecurityVulnerabilities.cs @@ -41,9 +41,9 @@ public override void Initialize(AnalysisContext context) context.ConfigureGeneratedCodeAnalysis(GeneratedCodeAnalysisFlags.None); context.RegisterCompilationStartAction(compilationContext => { - INamedTypeSymbol iDbCommandType = compilationContext.Compilation.GetOrCreateTypeByMetadataName(WellKnownTypeNames.SystemDataIDbCommand); - INamedTypeSymbol iDataAdapterType = compilationContext.Compilation.GetOrCreateTypeByMetadataName(WellKnownTypeNames.SystemDataIDataAdapter); - IPropertySymbol commandTextProperty = iDbCommandType?.GetMembers("CommandText").OfType().FirstOrDefault(); + INamedTypeSymbol? iDbCommandType = compilationContext.Compilation.GetOrCreateTypeByMetadataName(WellKnownTypeNames.SystemDataIDbCommand); + INamedTypeSymbol? iDataAdapterType = compilationContext.Compilation.GetOrCreateTypeByMetadataName(WellKnownTypeNames.SystemDataIDataAdapter); + IPropertySymbol? commandTextProperty = iDbCommandType?.GetMembers("CommandText").OfType().FirstOrDefault(); if (iDbCommandType == null || iDataAdapterType == null || diff --git a/src/Microsoft.NetCore.Analyzers/Core/InteropServices/PInvokeDiagnosticAnalyzer.cs b/src/Microsoft.NetCore.Analyzers/Core/InteropServices/PInvokeDiagnosticAnalyzer.cs index d7817d1135..ce72be2f89 100644 --- a/src/Microsoft.NetCore.Analyzers/Core/InteropServices/PInvokeDiagnosticAnalyzer.cs +++ b/src/Microsoft.NetCore.Analyzers/Core/InteropServices/PInvokeDiagnosticAnalyzer.cs @@ -52,25 +52,25 @@ public override void Initialize(AnalysisContext analysisContext) analysisContext.RegisterCompilationStartAction( (context) => { - INamedTypeSymbol dllImportType = context.Compilation.GetOrCreateTypeByMetadataName(WellKnownTypeNames.SystemRuntimeInteropServicesDllImportAttribute); + INamedTypeSymbol? dllImportType = context.Compilation.GetOrCreateTypeByMetadataName(WellKnownTypeNames.SystemRuntimeInteropServicesDllImportAttribute); if (dllImportType == null) { return; } - INamedTypeSymbol marshalAsType = context.Compilation.GetOrCreateTypeByMetadataName(WellKnownTypeNames.SystemRuntimeInteropServicesMarshalAsAttribute); + INamedTypeSymbol? marshalAsType = context.Compilation.GetOrCreateTypeByMetadataName(WellKnownTypeNames.SystemRuntimeInteropServicesMarshalAsAttribute); if (marshalAsType == null) { return; } - INamedTypeSymbol stringBuilderType = context.Compilation.GetOrCreateTypeByMetadataName(WellKnownTypeNames.SystemTextStringBuilder); + INamedTypeSymbol? stringBuilderType = context.Compilation.GetOrCreateTypeByMetadataName(WellKnownTypeNames.SystemTextStringBuilder); if (stringBuilderType == null) { return; } - INamedTypeSymbol unmanagedType = context.Compilation.GetOrCreateTypeByMetadataName(WellKnownTypeNames.SystemRuntimeInteropServicesUnmanagedType); + INamedTypeSymbol? unmanagedType = context.Compilation.GetOrCreateTypeByMetadataName(WellKnownTypeNames.SystemRuntimeInteropServicesUnmanagedType); if (unmanagedType == null) { return; diff --git a/src/Microsoft.NetCore.Analyzers/Core/InteropServices/SpecifyMarshalingForPInvokeStringArguments.Fixer.cs b/src/Microsoft.NetCore.Analyzers/Core/InteropServices/SpecifyMarshalingForPInvokeStringArguments.Fixer.cs index 6a575cf2ce..d9a7e39950 100644 --- a/src/Microsoft.NetCore.Analyzers/Core/InteropServices/SpecifyMarshalingForPInvokeStringArguments.Fixer.cs +++ b/src/Microsoft.NetCore.Analyzers/Core/InteropServices/SpecifyMarshalingForPInvokeStringArguments.Fixer.cs @@ -31,10 +31,10 @@ public override async Task RegisterCodeFixesAsync(CodeFixContext context) } SemanticModel model = await context.Document.GetSemanticModelAsync(context.CancellationToken).ConfigureAwait(false); - INamedTypeSymbol charSetType = model.Compilation.GetOrCreateTypeByMetadataName(WellKnownTypeNames.SystemRuntimeInteropServicesCharSet); - INamedTypeSymbol dllImportType = model.Compilation.GetOrCreateTypeByMetadataName(WellKnownTypeNames.SystemRuntimeInteropServicesDllImportAttribute); - INamedTypeSymbol marshalAsType = model.Compilation.GetOrCreateTypeByMetadataName(WellKnownTypeNames.SystemRuntimeInteropServicesMarshalAsAttribute); - INamedTypeSymbol unmanagedType = model.Compilation.GetOrCreateTypeByMetadataName(WellKnownTypeNames.SystemRuntimeInteropServicesUnmanagedType); + INamedTypeSymbol? charSetType = model.Compilation.GetOrCreateTypeByMetadataName(WellKnownTypeNames.SystemRuntimeInteropServicesCharSet); + INamedTypeSymbol? dllImportType = model.Compilation.GetOrCreateTypeByMetadataName(WellKnownTypeNames.SystemRuntimeInteropServicesDllImportAttribute); + INamedTypeSymbol? marshalAsType = model.Compilation.GetOrCreateTypeByMetadataName(WellKnownTypeNames.SystemRuntimeInteropServicesMarshalAsAttribute); + INamedTypeSymbol? unmanagedType = model.Compilation.GetOrCreateTypeByMetadataName(WellKnownTypeNames.SystemRuntimeInteropServicesUnmanagedType); if (charSetType == null || dllImportType == null || marshalAsType == null || unmanagedType == null) { return; diff --git a/src/Microsoft.NetCore.Analyzers/Core/Performance/DoNotUseCountWhenAnyCanBeUsed.Fixer.cs b/src/Microsoft.NetCore.Analyzers/Core/Performance/DoNotUseCountWhenAnyCanBeUsed.Fixer.cs index d20a4d4b24..2770e29507 100644 --- a/src/Microsoft.NetCore.Analyzers/Core/Performance/DoNotUseCountWhenAnyCanBeUsed.Fixer.cs +++ b/src/Microsoft.NetCore.Analyzers/Core/Performance/DoNotUseCountWhenAnyCanBeUsed.Fixer.cs @@ -2,6 +2,7 @@ using System.Collections.Generic; using System.Collections.Immutable; +using System.Diagnostics.CodeAnalysis; using System.Threading; using System.Threading.Tasks; using Microsoft.CodeAnalysis; @@ -77,7 +78,12 @@ public sealed override async Task RegisterCodeFixesAsync(CodeFixContext context) /// If this method returns , contains the expression to be used to invoke Any. /// If this method returns , contains the arguments from Any to be used on Count. /// if a fixer was found., otherwise. - protected abstract bool TryGetFixer(SyntaxNode node, string operation, bool isAsync, out SyntaxNode expression, out IEnumerable arguments); + protected abstract bool TryGetFixer( + SyntaxNode node, + string operation, + bool isAsync, + [NotNullWhen(returnValue: true)] out SyntaxNode? expression, + [NotNullWhen(returnValue: true)] out IEnumerable? arguments); private class DoNotUseCountWhenAnyCanBeUsedCodeAction : CodeAction { diff --git a/src/Microsoft.NetCore.Analyzers/Core/Performance/DoNotUseCountWhenAnyCanBeUsed.cs b/src/Microsoft.NetCore.Analyzers/Core/Performance/DoNotUseCountWhenAnyCanBeUsed.cs index 86fc78ee21..e545ae3c43 100644 --- a/src/Microsoft.NetCore.Analyzers/Core/Performance/DoNotUseCountWhenAnyCanBeUsed.cs +++ b/src/Microsoft.NetCore.Analyzers/Core/Performance/DoNotUseCountWhenAnyCanBeUsed.cs @@ -2,6 +2,7 @@ using System; using System.Collections.Immutable; +using System.Diagnostics.CodeAnalysis; using Analyzer.Utilities; using Analyzer.Utilities.Extensions; using Microsoft.CodeAnalysis; @@ -278,7 +279,7 @@ public void AnalyzeInvocationOperation(OperationAnalysisContext context) return; } - var propertiesBuilder = ImmutableDictionary.CreateBuilder(StringComparer.Ordinal); + var propertiesBuilder = ImmutableDictionary.CreateBuilder(StringComparer.Ordinal); propertiesBuilder.Add(OperationKey, operationKey); propertiesBuilder.Add(ShouldNegateKey, null); if (this._isAsync) propertiesBuilder.Add(IsAsyncKey, null); @@ -288,7 +289,7 @@ public void AnalyzeInvocationOperation(OperationAnalysisContext context) invocationOperation.Syntax.CreateDiagnostic( rule: this._rule, properties: properties, - args: methodName)); + args: methodName!)); } } @@ -317,7 +318,7 @@ public void AnalyzeBinaryOperation(OperationAnalysisContext context) return; } - var propertiesBuilder = ImmutableDictionary.CreateBuilder(StringComparer.Ordinal); + var propertiesBuilder = ImmutableDictionary.CreateBuilder(StringComparer.Ordinal); propertiesBuilder.Add(OperationKey, operationKey); if (shouldNegate) propertiesBuilder.Add(ShouldNegateKey, null); if (this._isAsync) propertiesBuilder.Add(IsAsyncKey, null); @@ -354,7 +355,7 @@ private static bool IsEqualsMethod(IMethodSymbol methodSymbol) /// /// if the value of the invocation of one of the in the /// is being compared with 0 using ; otherwise, . - private bool IsCountEqualsZero(IInvocationOperation invocationOperation, out string methodName) + private bool IsCountEqualsZero(IInvocationOperation invocationOperation, out string? methodName) { if (!TryGetZeroOrOneConstant(invocationOperation.Arguments[0].Value, out var constant) || constant != 0) { @@ -372,7 +373,7 @@ private bool IsCountEqualsZero(IInvocationOperation invocationOperation, out str /// The invocation operation. /// if 0 is being compared with the value of the invocation of one of the in the /// using ; otherwise, . - private bool IsZeroEqualsCount(IInvocationOperation invocationOperation, out string methodName) + private bool IsZeroEqualsCount(IInvocationOperation invocationOperation, [NotNullWhen(returnValue: true)] out string? methodName) { if (!TryGetZeroOrOneConstant(invocationOperation.Instance, out var constant) || constant != 0) { @@ -391,7 +392,7 @@ private bool IsZeroEqualsCount(IInvocationOperation invocationOperation, out str /// If the value of the invocation of one of the in the , contains the method name; otherwise. /// if the value of the invocation of one of the in the /// is being compared with 0 or 1 using comparison operators; otherwise, . - private bool IsLeftCountComparison(IBinaryOperation binaryOperation, out string methodName, out bool shouldNegate) + private bool IsLeftCountComparison(IBinaryOperation binaryOperation, [NotNullWhen(returnValue: true)] out string? methodName, out bool shouldNegate) { methodName = null; shouldNegate = false; @@ -448,7 +449,7 @@ private bool IsLeftCountComparison(IBinaryOperation binaryOperation, out string /// If the value of the invocation of one of the in the , contains the method name; otherwise. /// if 0 or 1 is being compared with the value of the invocation of one of the in the /// using comparison operators; otherwise, . - private bool IsRightCountComparison(IBinaryOperation binaryOperation, out string methodName, out bool shouldNegate) + private bool IsRightCountComparison(IBinaryOperation binaryOperation, [NotNullWhen(returnValue: true)] out string? methodName, out bool shouldNegate) { methodName = null; shouldNegate = false; @@ -582,7 +583,7 @@ private static bool TryGetZeroOrOneConstant(IOperation operation, out int consta /// If the is an invocation of one of the in the , contains the method name; otherwise. /// if the is an invocation of one of the in the ; /// otherwise. - private bool IsCountMethodInvocation(IOperation operation, out string methodName) + private bool IsCountMethodInvocation(IOperation operation, [NotNullWhen(returnValue: true)] out string? methodName) { methodName = null; diff --git a/src/Microsoft.NetCore.Analyzers/Core/Performance/UsePropertyInsteadOfCountMethodWhenAvailable.Fixer.cs b/src/Microsoft.NetCore.Analyzers/Core/Performance/UsePropertyInsteadOfCountMethodWhenAvailable.Fixer.cs index 121f92316e..69d9cbf4a5 100644 --- a/src/Microsoft.NetCore.Analyzers/Core/Performance/UsePropertyInsteadOfCountMethodWhenAvailable.Fixer.cs +++ b/src/Microsoft.NetCore.Analyzers/Core/Performance/UsePropertyInsteadOfCountMethodWhenAvailable.Fixer.cs @@ -1,6 +1,7 @@ // Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System.Collections.Immutable; +using System.Diagnostics.CodeAnalysis; using System.Linq; using System.Threading; using System.Threading.Tasks; @@ -69,7 +70,10 @@ public override async Task RegisterCodeFixesAsync(CodeFixContext context) /// The name node for the invocation node. /// if a and were found; /// otherwise. - protected abstract bool TryGetExpression(SyntaxNode invocationNode, out SyntaxNode memberAccessNode, out SyntaxNode nameNode); + protected abstract bool TryGetExpression( + SyntaxNode invocationNode, + [NotNullWhen(returnValue: true)] out SyntaxNode? memberAccessNode, + [NotNullWhen(returnValue: true)] out SyntaxNode? nameNode); /// /// Implements the for replacing the use of diff --git a/src/Microsoft.NetCore.Analyzers/Core/Performance/UsePropertyInsteadOfCountMethodWhenAvailable.cs b/src/Microsoft.NetCore.Analyzers/Core/Performance/UsePropertyInsteadOfCountMethodWhenAvailable.cs index 7913b7a85b..0c424fda9a 100644 --- a/src/Microsoft.NetCore.Analyzers/Core/Performance/UsePropertyInsteadOfCountMethodWhenAvailable.cs +++ b/src/Microsoft.NetCore.Analyzers/Core/Performance/UsePropertyInsteadOfCountMethodWhenAvailable.cs @@ -88,9 +88,9 @@ private void OnCompilationStart(CompilationStartAnalysisContext context) /// protected sealed class OperationActionsContext { - private readonly Lazy _immutableArrayType; - private readonly Lazy _iCollectionCountProperty; - private readonly Lazy _iCollectionOfType; + private readonly Lazy _immutableArrayType; + private readonly Lazy _iCollectionCountProperty; + private readonly Lazy _iCollectionOfType; /// /// Initializes a new instance of the class. @@ -101,9 +101,9 @@ public OperationActionsContext(Compilation compilation, INamedTypeSymbol enumera { Compilation = compilation; EnumerableType = enumerableType; - _immutableArrayType = new Lazy(() => Compilation.GetOrCreateTypeByMetadataName(WellKnownTypeNames.SystemCollectionsImmutableImmutableArray), true); - _iCollectionCountProperty = new Lazy(ResolveICollectionCountProperty, true); - _iCollectionOfType = new Lazy(() => Compilation.GetOrCreateTypeByMetadataName(WellKnownTypeNames.SystemCollectionsGenericICollection1), true); + _immutableArrayType = new Lazy(() => Compilation.GetOrCreateTypeByMetadataName(WellKnownTypeNames.SystemCollectionsImmutableImmutableArray), true); + _iCollectionCountProperty = new Lazy(ResolveICollectionCountProperty, true); + _iCollectionOfType = new Lazy(() => Compilation.GetOrCreateTypeByMetadataName(WellKnownTypeNames.SystemCollectionsGenericICollection1), true); } /// @@ -118,27 +118,27 @@ public OperationActionsContext(Compilation compilation, INamedTypeSymbol enumera /// Gets the property. /// /// The property. - private IPropertySymbol ICollectionCountProperty => _iCollectionCountProperty.Value; + private IPropertySymbol? ICollectionCountProperty => _iCollectionCountProperty.Value; /// /// Gets the type of the type. /// /// The type. - private INamedTypeSymbol ICollectionOfTType => _iCollectionOfType.Value; + private INamedTypeSymbol? ICollectionOfTType => _iCollectionOfType.Value; /// /// Gets the type of the type. /// /// The type. - internal INamedTypeSymbol ImmutableArrayType => _immutableArrayType.Value; + internal INamedTypeSymbol? ImmutableArrayType => _immutableArrayType.Value; /// /// Gets the type of the property, if one and only one exists. /// /// The property. - private IPropertySymbol ResolveICollectionCountProperty() + private IPropertySymbol? ResolveICollectionCountProperty() { - IPropertySymbol countProperty = null; + IPropertySymbol? countProperty = null; if (Compilation.GetOrCreateTypeByMetadataName(WellKnownTypeNames.SystemCollectionsICollection) is INamedTypeSymbol iCollectionType) { @@ -234,7 +234,7 @@ internal bool IsICollectionOfTImplementation(ITypeSymbol invocationTarget) return false; bool isCollectionOfTInterface(ITypeSymbol type) - => this.ICollectionOfTType.Equals(type.OriginalDefinition); + => this.ICollectionOfTType!.Equals(type.OriginalDefinition); } /// @@ -298,7 +298,7 @@ internal void AnalyzeInvocationOperation(OperationAnalysisContext context) /// /// The invocation target. /// The name of the replacement property. - private string GetReplacementProperty(ITypeSymbol invocationTarget) + private string? GetReplacementProperty(ITypeSymbol invocationTarget) { if ((invocationTarget.TypeKind == TypeKind.Array) || Context.IsImmutableArrayType(invocationTarget)) { diff --git a/src/Microsoft.NetCore.Analyzers/Core/Resources/MarkAssembliesWithNeutralResourcesLanguage.cs b/src/Microsoft.NetCore.Analyzers/Core/Resources/MarkAssembliesWithNeutralResourcesLanguage.cs index 179f529c4c..203f0383bd 100644 --- a/src/Microsoft.NetCore.Analyzers/Core/Resources/MarkAssembliesWithNeutralResourcesLanguage.cs +++ b/src/Microsoft.NetCore.Analyzers/Core/Resources/MarkAssembliesWithNeutralResourcesLanguage.cs @@ -96,7 +96,7 @@ protected static bool CheckResxGeneratedFile(SemanticModel model, SyntaxNode att return false; } - INamedTypeSymbol generatedCode = model.Compilation.GetOrCreateTypeByMetadataName(WellKnownTypeNames.SystemCodeDomCompilerGeneratedCodeAttribute); + INamedTypeSymbol? generatedCode = model.Compilation.GetOrCreateTypeByMetadataName(WellKnownTypeNames.SystemCodeDomCompilerGeneratedCodeAttribute); if (model.GetSymbolInfo(attribute, cancellationToken).Symbol?.ContainingType?.Equals(generatedCode) != true) { return false; @@ -123,8 +123,8 @@ protected static bool CheckResxGeneratedFile(SemanticModel model, SyntaxNode att private static bool TryCheckNeutralResourcesLanguageAttribute(CompilationAnalysisContext context, out AttributeData attributeData) { - INamedTypeSymbol attribute = context.Compilation.GetOrCreateTypeByMetadataName(WellKnownTypeNames.SystemResourcesNeutralResourcesLanguageAttribute); - INamedTypeSymbol @string = context.Compilation.GetSpecialType(SpecialType.System_String); + INamedTypeSymbol? attribute = context.Compilation.GetOrCreateTypeByMetadataName(WellKnownTypeNames.SystemResourcesNeutralResourcesLanguageAttribute); + INamedTypeSymbol? @string = context.Compilation.GetSpecialType(SpecialType.System_String); IEnumerable attributes = context.Compilation.Assembly.GetAttributes().Where(d => d.AttributeClass?.Equals(attribute) == true); foreach (AttributeData data in attributes) diff --git a/src/Microsoft.NetCore.Analyzers/Core/Runtime/AttributeStringLiteralsShouldParseCorrectly.cs b/src/Microsoft.NetCore.Analyzers/Core/Runtime/AttributeStringLiteralsShouldParseCorrectly.cs index 79a3fbda2e..8a312fe2c6 100644 --- a/src/Microsoft.NetCore.Analyzers/Core/Runtime/AttributeStringLiteralsShouldParseCorrectly.cs +++ b/src/Microsoft.NetCore.Analyzers/Core/Runtime/AttributeStringLiteralsShouldParseCorrectly.cs @@ -88,7 +88,7 @@ public override void Initialize(AnalysisContext analysisContext) { case SymbolKind.NamedType: { - var namedType = symbol as INamedTypeSymbol; + var namedType = (INamedTypeSymbol)symbol; AnalyzeSymbols(saContext.ReportDiagnostic, namedType.TypeParameters); @@ -102,7 +102,7 @@ public override void Initialize(AnalysisContext analysisContext) case SymbolKind.Method: { - var methodSymbol = symbol as IMethodSymbol; + var methodSymbol = (IMethodSymbol)symbol; if (!methodSymbol.IsAccessorMethod()) { AnalyzeSymbols(saContext.ReportDiagnostic, methodSymbol.Parameters); @@ -114,7 +114,7 @@ public override void Initialize(AnalysisContext analysisContext) case SymbolKind.Property: { - var propertySymbol = symbol as IPropertySymbol; + var propertySymbol = (IPropertySymbol)symbol; AnalyzeSymbols(saContext.ReportDiagnostic, propertySymbol.Parameters); return; } @@ -228,7 +228,7 @@ private static void Analyze(Action reportDiagnostic, AttributeData a } } - private static ValueValidator GetValueValidator(string name) + private static ValueValidator? GetValueValidator(string name) { foreach (var valueValidator in s_tokensToValueValidator) { @@ -244,7 +244,7 @@ private static ValueValidator GetValueValidator(string name) internal class ValueValidator { - private readonly string _ignoredName; + private readonly string? _ignoredName; public ImmutableArray AcceptedTokens { get; } public string TypeName { get; } @@ -255,7 +255,7 @@ public bool IsIgnoredName(string name) return _ignoredName != null && string.Equals(_ignoredName, name, StringComparison.OrdinalIgnoreCase); } - public ValueValidator(ImmutableArray acceptedTokens, string typeName, Func isValidValue, string ignoredName = null) + public ValueValidator(ImmutableArray acceptedTokens, string typeName, Func isValidValue, string? ignoredName = null) { _ignoredName = ignoredName; diff --git a/src/Microsoft.NetCore.Analyzers/Core/Runtime/AvoidUnsealedAttributes.cs b/src/Microsoft.NetCore.Analyzers/Core/Runtime/AvoidUnsealedAttributes.cs index 3229b61279..4df1761488 100644 --- a/src/Microsoft.NetCore.Analyzers/Core/Runtime/AvoidUnsealedAttributes.cs +++ b/src/Microsoft.NetCore.Analyzers/Core/Runtime/AvoidUnsealedAttributes.cs @@ -40,7 +40,7 @@ public override void Initialize(AnalysisContext analysisContext) analysisContext.RegisterCompilationStartAction(compilationContext => { - INamedTypeSymbol attributeType = compilationContext.Compilation.GetOrCreateTypeByMetadataName(WellKnownTypeNames.SystemAttribute); + INamedTypeSymbol? attributeType = compilationContext.Compilation.GetOrCreateTypeByMetadataName(WellKnownTypeNames.SystemAttribute); if (attributeType == null) { return; diff --git a/src/Microsoft.NetCore.Analyzers/Core/Runtime/AvoidZeroLengthArrayAllocations.Fixer.cs b/src/Microsoft.NetCore.Analyzers/Core/Runtime/AvoidZeroLengthArrayAllocations.Fixer.cs index d7c07365fa..467c7bb268 100644 --- a/src/Microsoft.NetCore.Analyzers/Core/Runtime/AvoidZeroLengthArrayAllocations.Fixer.cs +++ b/src/Microsoft.NetCore.Analyzers/Core/Runtime/AvoidZeroLengthArrayAllocations.Fixer.cs @@ -51,18 +51,24 @@ private static async Task ConvertToArrayEmpty(Document document, Synta SemanticModel semanticModel = await document.GetSemanticModelAsync(cancellationToken).ConfigureAwait(false); SyntaxGenerator generator = editor.Generator; - ITypeSymbol elementType = GetArrayElementType(nodeToFix, semanticModel, cancellationToken); + INamedTypeSymbol? arrayTypeSymbol = semanticModel.Compilation.GetOrCreateTypeByMetadataName(AvoidZeroLengthArrayAllocationsAnalyzer.ArrayTypeName); + if (arrayTypeSymbol == null) + { + return document; + } + + ITypeSymbol? elementType = GetArrayElementType(nodeToFix, semanticModel, cancellationToken); if (elementType == null) { return document; } - SyntaxNode arrayEmptyInvocation = GenerateArrayEmptyInvocation(generator, elementType, semanticModel).WithTriviaFrom(nodeToFix); + SyntaxNode arrayEmptyInvocation = GenerateArrayEmptyInvocation(generator, arrayTypeSymbol, elementType).WithTriviaFrom(nodeToFix); editor.ReplaceNode(nodeToFix, arrayEmptyInvocation); return editor.GetChangedDocument(); } - private static ITypeSymbol GetArrayElementType(SyntaxNode arrayCreationExpression, SemanticModel semanticModel, CancellationToken cancellationToken) + private static ITypeSymbol? GetArrayElementType(SyntaxNode arrayCreationExpression, SemanticModel semanticModel, CancellationToken cancellationToken) { var typeInfo = semanticModel.GetTypeInfo(arrayCreationExpression, cancellationToken); // When Type is null in cases like 'T[] goo = { }', use ConvertedType instead (https://github.com/dotnet/roslyn/issues/23545). @@ -72,9 +78,8 @@ private static ITypeSymbol GetArrayElementType(SyntaxNode arrayCreationExpressio return arrayType?.ElementType; } - private static SyntaxNode GenerateArrayEmptyInvocation(SyntaxGenerator generator, ITypeSymbol elementType, SemanticModel semanticModel) + private static SyntaxNode GenerateArrayEmptyInvocation(SyntaxGenerator generator, INamedTypeSymbol arrayTypeSymbol, ITypeSymbol elementType) { - INamedTypeSymbol arrayTypeSymbol = semanticModel.Compilation.GetOrCreateTypeByMetadataName(AvoidZeroLengthArrayAllocationsAnalyzer.ArrayTypeName); SyntaxNode arrayEmptyName = generator.MemberAccessExpression( generator.TypeExpressionForStaticMemberAccess(arrayTypeSymbol), generator.GenericName(AvoidZeroLengthArrayAllocationsAnalyzer.ArrayEmptyMethodName, elementType)); diff --git a/src/Microsoft.NetCore.Analyzers/Core/Runtime/AvoidZeroLengthArrayAllocations.cs b/src/Microsoft.NetCore.Analyzers/Core/Runtime/AvoidZeroLengthArrayAllocations.cs index 7f180e32f9..f6807a8ba2 100644 --- a/src/Microsoft.NetCore.Analyzers/Core/Runtime/AvoidZeroLengthArrayAllocations.cs +++ b/src/Microsoft.NetCore.Analyzers/Core/Runtime/AvoidZeroLengthArrayAllocations.cs @@ -51,7 +51,7 @@ public sealed override void Initialize(AnalysisContext context) // Only if it is, register the syntax node action provided by the derived implementations. context.RegisterCompilationStartAction(ctx => { - INamedTypeSymbol typeSymbol = ctx.Compilation.GetOrCreateTypeByMetadataName(ArrayTypeName); + INamedTypeSymbol? typeSymbol = ctx.Compilation.GetOrCreateTypeByMetadataName(ArrayTypeName); if (typeSymbol != null && typeSymbol.DeclaredAccessibility == Accessibility.Public) { if (typeSymbol.GetMembers(ArrayEmptyMethodName).FirstOrDefault() is IMethodSymbol methodSymbol && methodSymbol.DeclaredAccessibility == Accessibility.Public && @@ -102,6 +102,11 @@ private static void AnalyzeOperation(OperationAnalysisContext context, Func.Empty; if (parent is IInvocationOperation invocation) { @@ -163,7 +168,7 @@ private static bool IsCompilerGeneratedParamsArray(IArrayCreationOperation array return lastArgument != null && lastArgument.Value.Syntax == arrayCreationExpression.Syntax && AreEquivalentZeroLengthArrayCreations(arrayCreationExpression, lastArgument.Value as IArrayCreationOperation); } - private static bool AreEquivalentZeroLengthArrayCreations(IArrayCreationOperation first, IArrayCreationOperation second) + private static bool AreEquivalentZeroLengthArrayCreations(IArrayCreationOperation? first, IArrayCreationOperation? second) { if (first == null || second == null) { diff --git a/src/Microsoft.NetCore.Analyzers/Core/Runtime/CallGCSuppressFinalizeCorrectly.cs b/src/Microsoft.NetCore.Analyzers/Core/Runtime/CallGCSuppressFinalizeCorrectly.cs index 4d1f1c1241..6c10881b13 100644 --- a/src/Microsoft.NetCore.Analyzers/Core/Runtime/CallGCSuppressFinalizeCorrectly.cs +++ b/src/Microsoft.NetCore.Analyzers/Core/Runtime/CallGCSuppressFinalizeCorrectly.cs @@ -121,7 +121,6 @@ private enum SuppressFinalizeUsage private readonly SuppressFinalizeUsage _expectedUsage; private bool _suppressFinalizeCalled; - private SemanticModel _semanticModel; public SuppressFinalizeAnalyzer(IMethodSymbol methodSymbol, IMethodSymbol gcSuppressFinalizeMethodSymbol, Compilation compilation) { @@ -139,11 +138,6 @@ public void Analyze(OperationAnalysisContext analysisContext) { _suppressFinalizeCalled = true; - if (_semanticModel == null) - { - _semanticModel = analysisContext.Compilation.GetSemanticModel(analysisContext.Operation.Syntax.SyntaxTree); - } - // Check for GC.SuppressFinalize outside of IDisposable.Dispose() if (_expectedUsage == SuppressFinalizeUsage.MustNotCall) { @@ -159,7 +153,7 @@ public void Analyze(OperationAnalysisContext analysisContext) return; } - if (!(_semanticModel.GetSymbolInfo(invocationExpression.Arguments.Single().Value.Syntax).Symbol is IParameterSymbol parameterSymbol) || !parameterSymbol.IsThis) + if (!(invocationExpression.SemanticModel.GetSymbolInfo(invocationExpression.Arguments.Single().Value.Syntax).Symbol is IParameterSymbol parameterSymbol) || !parameterSymbol.IsThis) { analysisContext.ReportDiagnostic(invocationExpression.Syntax.CreateDiagnostic( NotPassedThisRule, diff --git a/src/Microsoft.NetCore.Analyzers/Core/Runtime/DisposableFieldsShouldBeDisposed.cs b/src/Microsoft.NetCore.Analyzers/Core/Runtime/DisposableFieldsShouldBeDisposed.cs index 98378ba9a3..32d552683f 100644 --- a/src/Microsoft.NetCore.Analyzers/Core/Runtime/DisposableFieldsShouldBeDisposed.cs +++ b/src/Microsoft.NetCore.Analyzers/Core/Runtime/DisposableFieldsShouldBeDisposed.cs @@ -44,7 +44,7 @@ public override void Initialize(AnalysisContext context) context.RegisterCompilationStartAction(compilationContext => { - if (!DisposeAnalysisHelper.TryGetOrCreate(compilationContext.Compilation, out DisposeAnalysisHelper disposeAnalysisHelper)) + if (!DisposeAnalysisHelper.TryGetOrCreate(compilationContext.Compilation, out DisposeAnalysisHelper? disposeAnalysisHelper)) { return; } @@ -53,7 +53,7 @@ public override void Initialize(AnalysisContext context) void addOrUpdateFieldDisposedValue(IFieldSymbol field, bool disposed) { Debug.Assert(!field.IsStatic); - Debug.Assert(field.Type.IsDisposable(disposeAnalysisHelper.IDisposable)); + Debug.Assert(field.Type.IsDisposable(disposeAnalysisHelper!.IDisposable)); fieldDisposeValueMap.AddOrUpdate(field, addValue: disposed, @@ -94,7 +94,7 @@ void addOrUpdateFieldDisposedValue(IFieldSymbol field, bool disposed) if (disposeAnalysisHelper.HasAnyDisposableCreationDescendant(operationBlockStartContext.OperationBlocks, containingMethod)) { - PointsToAnalysisResult lazyPointsToAnalysisResult = null; + PointsToAnalysisResult? lazyPointsToAnalysisResult = null; operationBlockStartContext.RegisterOperationAction(operationContext => { @@ -122,6 +122,12 @@ void addOrUpdateFieldDisposedValue(IFieldSymbol field, bool disposed) if (lazyPointsToAnalysisResult == null) { var cfg = operationBlockStartContext.OperationBlocks.GetControlFlowGraph(); + if (cfg == null) + { + hasErrors = true; + return; + } + var wellKnownTypeProvider = WellKnownTypeProvider.GetOrCreate(operationContext.Compilation); var interproceduralAnalysisConfig = InterproceduralAnalysisConfiguration.Create( operationBlockStartContext.Options, Rule, InterproceduralAnalysisKind.None, operationBlockStartContext.CancellationToken); @@ -163,7 +169,7 @@ void addOrUpdateFieldDisposedValue(IFieldSymbol field, bool disposed) disposeAnalysisResult: out var disposeAnalysisResult, pointsToAnalysisResult: out var pointsToAnalysisResult)) { BasicBlock exitBlock = disposeAnalysisResult.ControlFlowGraph.GetExit(); - foreach (var fieldWithPointsToValue in disposeAnalysisResult.TrackedInstanceFieldPointsToMap) + foreach (var fieldWithPointsToValue in disposeAnalysisResult!.TrackedInstanceFieldPointsToMap!) { IFieldSymbol field = fieldWithPointsToValue.Key; PointsToAbstractValue pointsToValue = fieldWithPointsToValue.Value; @@ -233,13 +239,13 @@ bool ShouldAnalyze(INamedTypeSymbol namedType) // We only want to analyze types which are disposable (implement System.IDisposable directly or indirectly) // and have at least one disposable field. return !hasErrors && - namedType.IsDisposable(disposeAnalysisHelper.IDisposable) && + namedType.IsDisposable(disposeAnalysisHelper!.IDisposable) && !disposeAnalysisHelper.GetDisposableFields(namedType).IsEmpty && !namedType.IsConfiguredToSkipAnalysis(compilationContext.Options, Rule, compilationContext.Compilation, compilationContext.CancellationToken); } bool IsDisposeMethod(IMethodSymbol method) - => method.GetDisposeMethodKind(disposeAnalysisHelper.IDisposable, disposeAnalysisHelper.Task) != DisposeMethodKind.None; + => method.GetDisposeMethodKind(disposeAnalysisHelper!.IDisposable, disposeAnalysisHelper.Task) != DisposeMethodKind.None; bool HasDisposeMethod(INamedTypeSymbol namedType) { diff --git a/src/Microsoft.NetCore.Analyzers/Core/Runtime/DisposableTypesShouldDeclareFinalizer.cs b/src/Microsoft.NetCore.Analyzers/Core/Runtime/DisposableTypesShouldDeclareFinalizer.cs index 669bf04871..65f097ea41 100644 --- a/src/Microsoft.NetCore.Analyzers/Core/Runtime/DisposableTypesShouldDeclareFinalizer.cs +++ b/src/Microsoft.NetCore.Analyzers/Core/Runtime/DisposableTypesShouldDeclareFinalizer.cs @@ -46,7 +46,7 @@ public override void Initialize(AnalysisContext analysisContext) { Compilation compilation = compilationStartAnalysisContext.Compilation; - ImmutableHashSet nativeResourceTypes = ImmutableHashSet.Create( + ImmutableHashSet nativeResourceTypes = ImmutableHashSet.Create( compilation.GetSpecialType(SpecialType.System_IntPtr), compilation.GetSpecialType(SpecialType.System_UIntPtr), compilation.GetOrCreateTypeByMetadataName(WellKnownTypeNames.SystemRuntimeInteropServicesHandleRef) diff --git a/src/Microsoft.NetCore.Analyzers/Core/Runtime/DisposeMethodsShouldCallBaseClassDispose.cs b/src/Microsoft.NetCore.Analyzers/Core/Runtime/DisposeMethodsShouldCallBaseClassDispose.cs index a70cc02f46..bb8845b7d3 100644 --- a/src/Microsoft.NetCore.Analyzers/Core/Runtime/DisposeMethodsShouldCallBaseClassDispose.cs +++ b/src/Microsoft.NetCore.Analyzers/Core/Runtime/DisposeMethodsShouldCallBaseClassDispose.cs @@ -46,7 +46,7 @@ public override void Initialize(AnalysisContext context) context.RegisterCompilationStartAction(compilationContext => { - if (!DisposeAnalysisHelper.TryGetOrCreate(compilationContext.Compilation, out DisposeAnalysisHelper disposeAnalysisHelper)) + if (!DisposeAnalysisHelper.TryGetOrCreate(compilationContext.Compilation, out DisposeAnalysisHelper? disposeAnalysisHelper)) { return; } diff --git a/src/Microsoft.NetCore.Analyzers/Core/Runtime/DisposeObjectsBeforeLosingScope.cs b/src/Microsoft.NetCore.Analyzers/Core/Runtime/DisposeObjectsBeforeLosingScope.cs index 2f06bfd5fc..9e7e417207 100644 --- a/src/Microsoft.NetCore.Analyzers/Core/Runtime/DisposeObjectsBeforeLosingScope.cs +++ b/src/Microsoft.NetCore.Analyzers/Core/Runtime/DisposeObjectsBeforeLosingScope.cs @@ -123,7 +123,7 @@ public override void Initialize(AnalysisContext context) if (trackExceptionPaths) { // Compute diagnostics for undisposed objects at handled exception exit paths. - var disposeDataAtHandledExceptionPaths = disposeAnalysisResult.ExceptionPathsExitBlockOutputOpt.Data; + var disposeDataAtHandledExceptionPaths = disposeAnalysisResult!.ExceptionPathsExitBlockOutputOpt!.Data; ComputeDiagnostics(disposeDataAtHandledExceptionPaths, notDisposedDiagnostics, mayBeNotDisposedDiagnostics, disposeAnalysisResult, pointsToAnalysisResult, disposeAnalysisKind, isDisposeDataForExceptionPaths: true); @@ -197,7 +197,7 @@ bool SkipInterproceduralAnalysis(IMethodSymbol invokedMethod) bool CanBeDisposable(ITypeSymbol type) => type.SpecialType == SpecialType.System_Object || - type.DerivesFrom(disposeAnalysisHelper.IDisposable) || + type.DerivesFrom(disposeAnalysisHelper!.IDisposable) || type.TypeKind == TypeKind.Delegate; } }); @@ -224,7 +224,7 @@ bool CanBeDisposable(ITypeSymbol type) var isNotDisposed = disposeValue.Kind == DisposeAbstractValueKind.NotDisposed || (disposeValue.DisposingOrEscapingOperations.Count > 0 && - disposeValue.DisposingOrEscapingOperations.All(d => d.IsInsideCatchRegion(disposeAnalysisResult.ControlFlowGraph) && !location.GetTopOfCreationCallStackOrCreation().IsInsideCatchRegion(disposeAnalysisResult.ControlFlowGraph))); + disposeValue.DisposingOrEscapingOperations.All(d => d.IsInsideCatchRegion(disposeAnalysisResult.ControlFlowGraph) && location.GetTopOfCreationCallStackOrCreation()?.IsInsideCatchRegion(disposeAnalysisResult.ControlFlowGraph) != true)); var isMayBeNotDisposed = !isNotDisposed && (disposeValue.Kind == DisposeAbstractValueKind.MaybeDisposed || disposeValue.Kind == DisposeAbstractValueKind.NotDisposedOrEscaped); if (isNotDisposed || diff --git a/src/Microsoft.NetCore.Analyzers/Core/Runtime/DoNotLockOnObjectsWithWeakIdentity.cs b/src/Microsoft.NetCore.Analyzers/Core/Runtime/DoNotLockOnObjectsWithWeakIdentity.cs index d2e7bc75c5..a613a43353 100644 --- a/src/Microsoft.NetCore.Analyzers/Core/Runtime/DoNotLockOnObjectsWithWeakIdentity.cs +++ b/src/Microsoft.NetCore.Analyzers/Core/Runtime/DoNotLockOnObjectsWithWeakIdentity.cs @@ -51,10 +51,10 @@ public override void Initialize(AnalysisContext analysisContext) compilationStartContext.RegisterOperationAction(context => { var lockStatement = (ILockOperation)context.Operation; - ITypeSymbol type = lockStatement.LockedValue?.Type; + ITypeSymbol? type = lockStatement.LockedValue?.Type; if (type != null && TypeHasWeakIdentity(type, compilation)) { - context.ReportDiagnostic(lockStatement.LockedValue.Syntax.CreateDiagnostic(Rule, type.ToDisplayString())); + context.ReportDiagnostic(lockStatement.LockedValue!.Syntax.CreateDiagnostic(Rule, type.ToDisplayString())); } }, OperationKind.Lock); @@ -69,13 +69,13 @@ private static bool TypeHasWeakIdentity(ITypeSymbol type, Compilation compilatio return type is IArrayTypeSymbol arrayType && IsPrimitiveType(arrayType.ElementType); case TypeKind.Class: case TypeKind.TypeParameter: - INamedTypeSymbol marshalByRefObjectTypeSymbol = compilation.GetOrCreateTypeByMetadataName(WellKnownTypeNames.SystemMarshalByRefObject); - INamedTypeSymbol executionEngineExceptionTypeSymbol = compilation.GetOrCreateTypeByMetadataName(WellKnownTypeNames.SystemExecutionEngineException); - INamedTypeSymbol outOfMemoryExceptionTypeSymbol = compilation.GetOrCreateTypeByMetadataName(WellKnownTypeNames.SystemOutOfMemoryException); - INamedTypeSymbol stackOverflowExceptionTypeSymbol = compilation.GetOrCreateTypeByMetadataName(WellKnownTypeNames.SystemStackOverflowException); - INamedTypeSymbol memberInfoTypeSymbol = compilation.GetOrCreateTypeByMetadataName(WellKnownTypeNames.SystemReflectionMemberInfo); - INamedTypeSymbol parameterInfoTypeSymbol = compilation.GetOrCreateTypeByMetadataName(WellKnownTypeNames.SystemReflectionParameterInfo); - INamedTypeSymbol threadTypeSymbol = compilation.GetOrCreateTypeByMetadataName(WellKnownTypeNames.SystemThreadingThread); + INamedTypeSymbol? marshalByRefObjectTypeSymbol = compilation.GetOrCreateTypeByMetadataName(WellKnownTypeNames.SystemMarshalByRefObject); + INamedTypeSymbol? executionEngineExceptionTypeSymbol = compilation.GetOrCreateTypeByMetadataName(WellKnownTypeNames.SystemExecutionEngineException); + INamedTypeSymbol? outOfMemoryExceptionTypeSymbol = compilation.GetOrCreateTypeByMetadataName(WellKnownTypeNames.SystemOutOfMemoryException); + INamedTypeSymbol? stackOverflowExceptionTypeSymbol = compilation.GetOrCreateTypeByMetadataName(WellKnownTypeNames.SystemStackOverflowException); + INamedTypeSymbol? memberInfoTypeSymbol = compilation.GetOrCreateTypeByMetadataName(WellKnownTypeNames.SystemReflectionMemberInfo); + INamedTypeSymbol? parameterInfoTypeSymbol = compilation.GetOrCreateTypeByMetadataName(WellKnownTypeNames.SystemReflectionParameterInfo); + INamedTypeSymbol? threadTypeSymbol = compilation.GetOrCreateTypeByMetadataName(WellKnownTypeNames.SystemThreadingThread); return type.SpecialType == SpecialType.System_String || type.Equals(executionEngineExceptionTypeSymbol) || diff --git a/src/Microsoft.NetCore.Analyzers/Core/Runtime/DoNotPassLiteralsAsLocalizedParameters.cs b/src/Microsoft.NetCore.Analyzers/Core/Runtime/DoNotPassLiteralsAsLocalizedParameters.cs index b48d0a4598..f442a6609c 100644 --- a/src/Microsoft.NetCore.Analyzers/Core/Runtime/DoNotPassLiteralsAsLocalizedParameters.cs +++ b/src/Microsoft.NetCore.Analyzers/Core/Runtime/DoNotPassLiteralsAsLocalizedParameters.cs @@ -53,9 +53,9 @@ public override void Initialize(AnalysisContext context) context.RegisterCompilationStartAction(compilationContext => { - INamedTypeSymbol localizableStateAttributeSymbol = compilationContext.Compilation.GetOrCreateTypeByMetadataName(WellKnownTypeNames.SystemComponentModelLocalizableAttribute); - INamedTypeSymbol conditionalAttributeSymbol = compilationContext.Compilation.GetOrCreateTypeByMetadataName(WellKnownTypeNames.SystemDiagnosticsConditionalAttribute); - INamedTypeSymbol systemConsoleSymbol = compilationContext.Compilation.GetOrCreateTypeByMetadataName(WellKnownTypeNames.SystemConsole); + INamedTypeSymbol? localizableStateAttributeSymbol = compilationContext.Compilation.GetOrCreateTypeByMetadataName(WellKnownTypeNames.SystemComponentModelLocalizableAttribute); + INamedTypeSymbol? conditionalAttributeSymbol = compilationContext.Compilation.GetOrCreateTypeByMetadataName(WellKnownTypeNames.SystemDiagnosticsConditionalAttribute); + INamedTypeSymbol? systemConsoleSymbol = compilationContext.Compilation.GetOrCreateTypeByMetadataName(WellKnownTypeNames.SystemConsole); ImmutableHashSet typesToIgnore = GetTypesToIgnore(compilationContext.Compilation); compilationContext.RegisterOperationBlockStartAction(operationBlockStartContext => @@ -67,13 +67,13 @@ public override void Initialize(AnalysisContext context) return; } - var lazyValueContentResult = new Lazy>( + var lazyValueContentResult = new Lazy?>( valueFactory: ComputeValueContentAnalysisResult, isThreadSafe: false); operationBlockStartContext.RegisterOperationAction(operationContext => { var argument = (IArgumentOperation)operationContext.Operation; - IMethodSymbol targetMethod = null; + IMethodSymbol? targetMethod = null; switch (argument.Parent) { case IInvocationOperation invocation: @@ -108,10 +108,10 @@ public override void Initialize(AnalysisContext context) return; // Local functions - bool ShouldAnalyze(ISymbol symbol) + bool ShouldAnalyze(ISymbol? symbol) => symbol != null && !symbol.IsConfiguredToSkipAnalysis(operationBlockStartContext.Options, Rule, operationBlockStartContext.Compilation, operationBlockStartContext.CancellationToken); - void AnalyzeArgument(IParameterSymbol parameter, IPropertySymbol containingPropertySymbolOpt, IOperation operation, Action reportDiagnostic) + void AnalyzeArgument(IParameterSymbol parameter, IPropertySymbol? containingPropertySymbolOpt, IOperation operation, Action reportDiagnostic) { if (ShouldBeLocalized(parameter.OriginalDefinition, containingPropertySymbolOpt?.OriginalDefinition, localizableStateAttributeSymbol, conditionalAttributeSymbol, systemConsoleSymbol, typesToIgnore) && lazyValueContentResult.Value != null) @@ -126,7 +126,7 @@ void AnalyzeArgument(IParameterSymbol parameter, IPropertySymbol containingPrope return; } - var stringLiteralValues = stringContentValue.LiteralValues.Select(l => (string)l); + var stringLiteralValues = stringContentValue.LiteralValues.Select(l => (string?)l); // FxCop compat: Do not fire if the literal value came from a default parameter value if (stringContentValue.LiteralValues.Count == 1 && @@ -144,14 +144,14 @@ void AnalyzeArgument(IParameterSymbol parameter, IPropertySymbol containingPrope } // FxCop compat: Filter out xml string literals. - var filteredStrings = stringLiteralValues.Where(literal => !LooksLikeXmlTag(literal)); + var filteredStrings = stringLiteralValues.Where(literal => literal != null && !LooksLikeXmlTag(literal)); if (filteredStrings.Any()) { // Method '{0}' passes a literal string as parameter '{1}' of a call to '{2}'. Retrieve the following string(s) from a resource table instead: "{3}". var arg1 = containingMethod.ToDisplayString(SymbolDisplayFormat.MinimallyQualifiedFormat); var arg2 = parameter.Name; var arg3 = parameter.ContainingSymbol.ToDisplayString(SymbolDisplayFormat.MinimallyQualifiedFormat); - var arg4 = FormatLiteralValues(filteredStrings); + var arg4 = FormatLiteralValues(filteredStrings!); var diagnostic = operation.CreateDiagnostic(Rule, arg1, arg2, arg3, arg4); reportDiagnostic(diagnostic); } @@ -159,7 +159,7 @@ void AnalyzeArgument(IParameterSymbol parameter, IPropertySymbol containingPrope } } - DataFlowAnalysisResult ComputeValueContentAnalysisResult() + DataFlowAnalysisResult? ComputeValueContentAnalysisResult() { var cfg = operationBlockStartContext.OperationBlocks.GetControlFlowGraph(); if (cfg != null) @@ -214,10 +214,10 @@ private static ImmutableHashSet GetTypesToIgnore(Compilation c private static bool ShouldBeLocalized( IParameterSymbol parameterSymbol, - IPropertySymbol containingPropertySymbolOpt, - INamedTypeSymbol localizableStateAttributeSymbol, - INamedTypeSymbol conditionalAttributeSymbol, - INamedTypeSymbol systemConsoleSymbol, + IPropertySymbol? containingPropertySymbolOpt, + INamedTypeSymbol? localizableStateAttributeSymbol, + INamedTypeSymbol? conditionalAttributeSymbol, + INamedTypeSymbol? systemConsoleSymbol, ImmutableHashSet typesToIgnore) { Debug.Assert(parameterSymbol.ContainingSymbol.Kind == SymbolKind.Method); @@ -290,7 +290,6 @@ private static ImmutableHashSet GetTypesToIgnore(Compilation c private static LocalizableAttributeState GetLocalizableAttributeState(ISymbol symbol, INamedTypeSymbol localizableAttributeTypeSymbol) { - Debug.Assert(localizableAttributeTypeSymbol != null); if (symbol == null) { return LocalizableAttributeState.Undefined; @@ -308,8 +307,6 @@ private static LocalizableAttributeState GetLocalizableAttributeState(ISymbol sy private static LocalizableAttributeState GetLocalizableAttributeStateCore(ImmutableArray attributeList, INamedTypeSymbol localizableAttributeTypeSymbol) { - Debug.Assert(localizableAttributeTypeSymbol != null); - var localizableAttribute = attributeList.FirstOrDefault(attr => localizableAttributeTypeSymbol.Equals(attr.AttributeClass)); if (localizableAttribute != null && localizableAttribute.AttributeConstructor.Parameters.Length == 1 && @@ -360,10 +357,15 @@ private static bool LooksLikeXmlTag(string literal) /// /// Returns true if any character in literalValues is not a control character /// - private static bool LiteralValuesHaveNonControlCharacters(IEnumerable literalValues) + private static bool LiteralValuesHaveNonControlCharacters(IEnumerable literalValues) { - foreach (string literal in literalValues) + foreach (string? literal in literalValues) { + if (literal == null) + { + continue; + } + foreach (char ch in literal) { if (!char.IsControl(ch)) diff --git a/src/Microsoft.NetCore.Analyzers/Core/Runtime/DoNotRaiseReservedExceptionTypes.cs b/src/Microsoft.NetCore.Analyzers/Core/Runtime/DoNotRaiseReservedExceptionTypes.cs index 6073d7387a..f8d54dffb7 100644 --- a/src/Microsoft.NetCore.Analyzers/Core/Runtime/DoNotRaiseReservedExceptionTypes.cs +++ b/src/Microsoft.NetCore.Analyzers/Core/Runtime/DoNotRaiseReservedExceptionTypes.cs @@ -108,10 +108,10 @@ public override void Initialize(AnalysisContext analysisContext) private static ImmutableHashSet CreateSymbolSet(Compilation compilation, IEnumerable exceptionNames) { - HashSet set = null; + HashSet? set = null; foreach (string exp in exceptionNames) { - INamedTypeSymbol symbol = compilation.GetOrCreateTypeByMetadataName(exp); + INamedTypeSymbol? symbol = compilation.GetOrCreateTypeByMetadataName(exp); if (symbol == null) { continue; diff --git a/src/Microsoft.NetCore.Analyzers/Core/Runtime/ImplementSerializationConstructors.Fixer.cs b/src/Microsoft.NetCore.Analyzers/Core/Runtime/ImplementSerializationConstructors.Fixer.cs index cb69acd7ad..694f448637 100644 --- a/src/Microsoft.NetCore.Analyzers/Core/Runtime/ImplementSerializationConstructors.Fixer.cs +++ b/src/Microsoft.NetCore.Analyzers/Core/Runtime/ImplementSerializationConstructors.Fixer.cs @@ -28,14 +28,13 @@ public override async Task RegisterCodeFixesAsync(CodeFixContext context) SyntaxNode root = await context.Document.GetSyntaxRootAsync(context.CancellationToken).ConfigureAwait(false); SyntaxNode node = root.FindNode(context.Span); SemanticModel model = await context.Document.GetSemanticModelAsync(context.CancellationToken).ConfigureAwait(false); - ISymbol symbol = model.GetDeclaredSymbol(node, context.CancellationToken); - if (symbol == null) + if (!(model.GetDeclaredSymbol(node, context.CancellationToken) is INamedTypeSymbol symbol)) { return; } - INamedTypeSymbol notImplementedExceptionType = model.Compilation.GetOrCreateTypeByMetadataName(WellKnownTypeNames.SystemNotImplementedException); + INamedTypeSymbol? notImplementedExceptionType = model.Compilation.GetOrCreateTypeByMetadataName(WellKnownTypeNames.SystemNotImplementedException); if (notImplementedExceptionType == null) { return; @@ -54,16 +53,15 @@ public override async Task RegisterCodeFixesAsync(CodeFixContext context) else if (symbol.Kind == SymbolKind.Method) { context.RegisterCodeFix(new MyCodeAction(title, - async ct => await SetAccessibility(context.Document, symbol, ct).ConfigureAwait(false), + async ct => await SetAccessibility(context.Document, (IMethodSymbol)symbol, ct).ConfigureAwait(false), equivalenceKey: title), context.Diagnostics); } } - private static async Task GenerateConstructor(Document document, SyntaxNode node, ISymbol symbol, INamedTypeSymbol notImplementedExceptionType, CancellationToken cancellationToken) + private static async Task GenerateConstructor(Document document, SyntaxNode node, INamedTypeSymbol typeSymbol, INamedTypeSymbol notImplementedExceptionType, CancellationToken cancellationToken) { SymbolEditor editor = SymbolEditor.Create(document); - var typeSymbol = symbol as INamedTypeSymbol; await editor.EditOneDeclarationAsync(typeSymbol, node.GetLocation(), (docEditor, declaration) => { @@ -85,10 +83,9 @@ private static async Task GenerateConstructor(Document document, Synta return editor.GetChangedDocuments().First(); } - private static async Task SetAccessibility(Document document, ISymbol symbol, CancellationToken cancellationToken) + private static async Task SetAccessibility(Document document, IMethodSymbol methodSymbol, CancellationToken cancellationToken) { SymbolEditor editor = SymbolEditor.Create(document); - var methodSymbol = symbol as IMethodSymbol; // This would be constructor and can have only one definition. Debug.Assert(methodSymbol.IsConstructor() && methodSymbol.DeclaringSyntaxReferences.HasExactly(1)); diff --git a/src/Microsoft.NetCore.Analyzers/Core/Runtime/InstantiateArgumentExceptionsCorrectly.cs b/src/Microsoft.NetCore.Analyzers/Core/Runtime/InstantiateArgumentExceptionsCorrectly.cs index d22ccaf064..ad86725e7d 100644 --- a/src/Microsoft.NetCore.Analyzers/Core/Runtime/InstantiateArgumentExceptionsCorrectly.cs +++ b/src/Microsoft.NetCore.Analyzers/Core/Runtime/InstantiateArgumentExceptionsCorrectly.cs @@ -45,7 +45,7 @@ public override void Initialize(AnalysisContext analysisContext) compilationContext => { Compilation compilation = compilationContext.Compilation; - ITypeSymbol argumentExceptionType = compilation.GetOrCreateTypeByMetadataName(WellKnownTypeNames.SystemArgumentException); + ITypeSymbol? argumentExceptionType = compilation.GetOrCreateTypeByMetadataName(WellKnownTypeNames.SystemArgumentException); if (argumentExceptionType == null) { @@ -89,7 +89,7 @@ public override void Initialize(AnalysisContext analysisContext) continue; } - string value = argument.Value.ConstantValue.HasValue ? argument.Value.ConstantValue.Value as string : null; + string? value = argument.Value.ConstantValue.HasValue ? argument.Value.ConstantValue.Value as string : null; if (value == null) { continue; @@ -107,7 +107,7 @@ public override void Initialize(AnalysisContext analysisContext) OperationAnalysisContext context) { bool matchesParameter = MatchesParameter(targetSymbol, creation, stringArgument); - LocalizableString format = null; + LocalizableString? format = null; if (IsMessage(parameter) && matchesParameter) { @@ -170,7 +170,7 @@ private static bool HasMessageOrParameterNameConstructor(ITypeSymbol type) return false; } - private static bool MatchesParameter(ISymbol symbol, IObjectCreationOperation creation, string stringArgumentValue) + private static bool MatchesParameter(ISymbol? symbol, IObjectCreationOperation creation, string stringArgumentValue) { if (MatchesParameterCore(symbol, stringArgumentValue)) { @@ -203,7 +203,7 @@ private static bool MatchesParameter(ISymbol symbol, IObjectCreationOperation cr return false; } - private static bool MatchesParameterCore(ISymbol symbol, string stringArgumentValue) + private static bool MatchesParameterCore(ISymbol? symbol, string stringArgumentValue) { foreach (IParameterSymbol parameter in symbol.GetParameters()) { diff --git a/src/Microsoft.NetCore.Analyzers/Core/Runtime/MarkAllNonSerializableFields.Fixer.cs b/src/Microsoft.NetCore.Analyzers/Core/Runtime/MarkAllNonSerializableFields.Fixer.cs index 0842ddbbff..0f72d123e2 100644 --- a/src/Microsoft.NetCore.Analyzers/Core/Runtime/MarkAllNonSerializableFields.Fixer.cs +++ b/src/Microsoft.NetCore.Analyzers/Core/Runtime/MarkAllNonSerializableFields.Fixer.cs @@ -42,7 +42,7 @@ public override async Task RegisterCodeFixesAsync(CodeFixContext context) // Fix 2: If the type of the field is defined in source, then add the serializable attribute to the type. SemanticModel model = await context.Document.GetSemanticModelAsync(context.CancellationToken).ConfigureAwait(false); var fieldSymbol = model.GetDeclaredSymbol(node, context.CancellationToken) as IFieldSymbol; - ITypeSymbol type = fieldSymbol?.Type; + ITypeSymbol? type = fieldSymbol?.Type; if (type != null && type.Locations.Any(l => l.IsInSource)) { context.RegisterCodeFix(new MyCodeAction(MicrosoftNetCoreAnalyzersResources.AddSerializableAttributeCodeActionTitle, diff --git a/src/Microsoft.NetCore.Analyzers/Core/Runtime/NormalizeStringsToUppercase.cs b/src/Microsoft.NetCore.Analyzers/Core/Runtime/NormalizeStringsToUppercase.cs index b316b9d29e..8d2b9d5be2 100644 --- a/src/Microsoft.NetCore.Analyzers/Core/Runtime/NormalizeStringsToUppercase.cs +++ b/src/Microsoft.NetCore.Analyzers/Core/Runtime/NormalizeStringsToUppercase.cs @@ -90,7 +90,7 @@ public override void Initialize(AnalysisContext analysisContext) (method.Equals(toLowerWithCultureInfo) && ((invocation.Arguments.FirstOrDefault()?.Value as IMemberReferenceOperation)?.Member.Equals(invariantCulture) ?? false))) { - var suggestedMethod = toUpperInvariant ?? toUpperWithCultureInfo; + IMethodSymbol suggestedMethod = toUpperInvariant ?? toUpperWithCultureInfo!; // In method {0}, replace the call to {1} with {2}. var diagnostic = Diagnostic.Create(ToUpperRule, invocation.Syntax.GetLocation(), operationAnalysisContext.ContainingSymbol.Name, method.Name, suggestedMethod.Name); diff --git a/src/Microsoft.NetCore.Analyzers/Core/Runtime/ProvideCorrectArgumentsToFormattingMethods.cs b/src/Microsoft.NetCore.Analyzers/Core/Runtime/ProvideCorrectArgumentsToFormattingMethods.cs index 018319054e..5eea627596 100644 --- a/src/Microsoft.NetCore.Analyzers/Core/Runtime/ProvideCorrectArgumentsToFormattingMethods.cs +++ b/src/Microsoft.NetCore.Analyzers/Core/Runtime/ProvideCorrectArgumentsToFormattingMethods.cs @@ -3,6 +3,7 @@ using System; using System.Collections.Generic; using System.Collections.Immutable; +using System.Diagnostics.CodeAnalysis; using Analyzer.Utilities; using Analyzer.Utilities.Extensions; using Microsoft.CodeAnalysis; @@ -49,7 +50,7 @@ public override void Initialize(AnalysisContext analysisContext) { var invocation = (IInvocationOperation)operationContext.Operation; - StringFormatInfo.Info info = formatInfo.TryGet(invocation.TargetMethod, operationContext); + StringFormatInfo.Info? info = formatInfo.TryGet(invocation.TargetMethod, operationContext); if (info == null || invocation.Arguments.Length <= info.FormatStringIndex) { // not a target method @@ -97,7 +98,7 @@ public override void Initialize(AnalysisContext analysisContext) var elementType = arrayCreation.GetElementType(); if (elementType == null || !object.Equals(elementType, formatInfo.Object) || - arrayCreation.DimensionSizes.Length != 1) + arrayCreation!.DimensionSizes.Length != 1) { // wrong format return; @@ -323,7 +324,7 @@ public StringFormatInfo(Compilation compilation) { ImmutableDictionary.Builder builder = ImmutableDictionary.CreateBuilder(); - INamedTypeSymbol console = compilation.GetOrCreateTypeByMetadataName(WellKnownTypeNames.SystemConsole); + INamedTypeSymbol? console = compilation.GetOrCreateTypeByMetadataName(WellKnownTypeNames.SystemConsole); AddStringFormatMap(builder, console, "Write"); AddStringFormatMap(builder, console, "WriteLine"); @@ -339,9 +340,9 @@ public StringFormatInfo(Compilation compilation) public INamedTypeSymbol String { get; } public INamedTypeSymbol Object { get; } - public Info TryGet(IMethodSymbol method, OperationAnalysisContext context) + public Info? TryGet(IMethodSymbol method, OperationAnalysisContext context) { - if (_map.TryGetValue(method, out Info info)) + if (_map.TryGetValue(method, out Info? info)) { return info; } @@ -357,7 +358,7 @@ public Info TryGet(IMethodSymbol method, OperationAnalysisContext context) return null; } - private static void AddStringFormatMap(ImmutableDictionary.Builder builder, INamedTypeSymbol type, string methodName) + private static void AddStringFormatMap(ImmutableDictionary.Builder builder, INamedTypeSymbol? type, string methodName) { if (type == null) { @@ -373,7 +374,7 @@ private static void AddStringFormatMap(ImmutableDictionary. } } - private static bool TryGetFormatInfo(IMethodSymbol method, out Info formatInfo) + private static bool TryGetFormatInfo(IMethodSymbol method, [NotNullWhen(returnValue: true)] out Info? formatInfo) { formatInfo = default; diff --git a/src/Microsoft.NetCore.Analyzers/Core/Runtime/SerializationRulesDiagnosticAnalyzer.cs b/src/Microsoft.NetCore.Analyzers/Core/Runtime/SerializationRulesDiagnosticAnalyzer.cs index 626200ce49..9ce4956b0d 100644 --- a/src/Microsoft.NetCore.Analyzers/Core/Runtime/SerializationRulesDiagnosticAnalyzer.cs +++ b/src/Microsoft.NetCore.Analyzers/Core/Runtime/SerializationRulesDiagnosticAnalyzer.cs @@ -97,31 +97,31 @@ public override void Initialize(AnalysisContext analysisContext) analysisContext.RegisterCompilationStartAction( (context) => { - INamedTypeSymbol iserializableTypeSymbol = context.Compilation.GetOrCreateTypeByMetadataName(WellKnownTypeNames.SystemRuntimeSerializationISerializable); + INamedTypeSymbol? iserializableTypeSymbol = context.Compilation.GetOrCreateTypeByMetadataName(WellKnownTypeNames.SystemRuntimeSerializationISerializable); if (iserializableTypeSymbol == null) { return; } - INamedTypeSymbol serializationInfoTypeSymbol = context.Compilation.GetOrCreateTypeByMetadataName(WellKnownTypeNames.SystemRuntimeSerializationSerializationInfo); + INamedTypeSymbol? serializationInfoTypeSymbol = context.Compilation.GetOrCreateTypeByMetadataName(WellKnownTypeNames.SystemRuntimeSerializationSerializationInfo); if (serializationInfoTypeSymbol == null) { return; } - INamedTypeSymbol streamingContextTypeSymbol = context.Compilation.GetOrCreateTypeByMetadataName(WellKnownTypeNames.SystemRuntimeSerializationStreamingContext); + INamedTypeSymbol? streamingContextTypeSymbol = context.Compilation.GetOrCreateTypeByMetadataName(WellKnownTypeNames.SystemRuntimeSerializationStreamingContext); if (streamingContextTypeSymbol == null) { return; } - INamedTypeSymbol serializableAttributeTypeSymbol = context.Compilation.GetOrCreateTypeByMetadataName(WellKnownTypeNames.SystemSerializableAttribute); + INamedTypeSymbol? serializableAttributeTypeSymbol = context.Compilation.GetOrCreateTypeByMetadataName(WellKnownTypeNames.SystemSerializableAttribute); if (serializableAttributeTypeSymbol == null) { return; } - INamedTypeSymbol nonSerializedAttributeTypeSymbol = context.Compilation.GetOrCreateTypeByMetadataName(WellKnownTypeNames.SystemNonSerializedAttribute); + INamedTypeSymbol? nonSerializedAttributeTypeSymbol = context.Compilation.GetOrCreateTypeByMetadataName(WellKnownTypeNames.SystemNonSerializedAttribute); if (nonSerializedAttributeTypeSymbol == null) { return; diff --git a/src/Microsoft.NetCore.Analyzers/Core/Runtime/SpecifyIFormatProvider.cs b/src/Microsoft.NetCore.Analyzers/Core/Runtime/SpecifyIFormatProvider.cs index f2ba863285..00aaef2505 100644 --- a/src/Microsoft.NetCore.Analyzers/Core/Runtime/SpecifyIFormatProvider.cs +++ b/src/Microsoft.NetCore.Analyzers/Core/Runtime/SpecifyIFormatProvider.cs @@ -84,7 +84,12 @@ public override void Initialize(AnalysisContext analysisContext) var objectType = csaContext.Compilation.GetSpecialType(SpecialType.System_Object); var stringType = csaContext.Compilation.GetSpecialType(SpecialType.System_String); - var stringFormatMembers = stringType?.GetMembers("Format").OfType(); + if (objectType == null || stringType == null) + { + return; + } + + var stringFormatMembers = stringType.GetMembers("Format").OfType(); var stringFormatMemberWithStringAndObjectParameter = stringFormatMembers.GetFirstOrDefaultMemberWithParameterInfos( GetParameterInfo(stringType), @@ -140,6 +145,7 @@ public override void Initialize(AnalysisContext analysisContext) #region "IFormatProviderAlternateStringRule Only" if (stringType != null && cultureInfoType != null && + stringFormatMemberWithIFormatProviderStringAndParamsObjectParameter != null && (targetMethod.Equals(stringFormatMemberWithStringAndObjectParameter) || targetMethod.Equals(stringFormatMemberWithStringObjectAndObjectParameter) || targetMethod.Equals(stringFormatMemberWithStringObjectObjectAndObjectParameter) || @@ -160,7 +166,7 @@ public override void Initialize(AnalysisContext analysisContext) #region "IFormatProviderAlternateStringRule & IFormatProviderAlternateRule" - IEnumerable methodsWithSameNameAsTargetMethod = targetMethod.ContainingType.GetMembers(targetMethod.Name).OfType().WhereMethodDoesNotContainAttribute(obsoleteAttributeType).ToList(); + IEnumerable methodsWithSameNameAsTargetMethod = targetMethod.ContainingType!.GetMembers(targetMethod.Name).OfType().WhereMethodDoesNotContainAttribute(obsoleteAttributeType).ToList(); if (methodsWithSameNameAsTargetMethod.HasMoreThan(1)) { var correctOverloads = methodsWithSameNameAsTargetMethod.GetMethodOverloadsWithDesiredParameterAtLeadingOrTrailing(targetMethod, iformatProviderType).ToList(); diff --git a/src/Microsoft.NetCore.Analyzers/Core/Runtime/TestForEmptyStringsUsingStringLength.Fixer.cs b/src/Microsoft.NetCore.Analyzers/Core/Runtime/TestForEmptyStringsUsingStringLength.Fixer.cs index e7b1657d65..9ec83fd9dd 100644 --- a/src/Microsoft.NetCore.Analyzers/Core/Runtime/TestForEmptyStringsUsingStringLength.Fixer.cs +++ b/src/Microsoft.NetCore.Analyzers/Core/Runtime/TestForEmptyStringsUsingStringLength.Fixer.cs @@ -37,7 +37,7 @@ public sealed override async Task RegisterCodeFixesAsync(CodeFixContext context) SemanticModel model = await context.Document.GetSemanticModelAsync(context.CancellationToken).ConfigureAwait(false); - FixResolution resolution = TryGetFixResolution(binaryExpressionSyntax, model); + FixResolution? resolution = TryGetFixResolution(binaryExpressionSyntax, model); if (resolution != null) { @@ -55,7 +55,7 @@ public sealed override async Task RegisterCodeFixesAsync(CodeFixContext context) } } - private FixResolution TryGetFixResolution(SyntaxNode binaryExpressionSyntax, SemanticModel model) + private FixResolution? TryGetFixResolution(SyntaxNode binaryExpressionSyntax, SemanticModel model) { bool isEqualsOperator = IsEqualsOperator(binaryExpressionSyntax); SyntaxNode leftOperand = GetLeftOperand(binaryExpressionSyntax); diff --git a/src/Microsoft.NetCore.Analyzers/Core/Runtime/TestForNaNCorrectly.Fixer.cs b/src/Microsoft.NetCore.Analyzers/Core/Runtime/TestForNaNCorrectly.Fixer.cs index 5a11154b9d..8687050f6a 100644 --- a/src/Microsoft.NetCore.Analyzers/Core/Runtime/TestForNaNCorrectly.Fixer.cs +++ b/src/Microsoft.NetCore.Analyzers/Core/Runtime/TestForNaNCorrectly.Fixer.cs @@ -37,15 +37,15 @@ public sealed override async Task RegisterCodeFixesAsync(CodeFixContext context) SemanticModel model = await context.Document.GetSemanticModelAsync(context.CancellationToken).ConfigureAwait(false); - INamedTypeSymbol systemSingleType = model.Compilation.GetSpecialType(SpecialType.System_Single); - INamedTypeSymbol systemDoubleType = model.Compilation.GetSpecialType(SpecialType.System_Double); + INamedTypeSymbol? systemSingleType = model.Compilation.GetSpecialType(SpecialType.System_Single); + INamedTypeSymbol? systemDoubleType = model.Compilation.GetSpecialType(SpecialType.System_Double); if (systemSingleType == null || systemDoubleType == null) { return; } - FixResolution resolution = TryGetFixResolution(binaryExpressionSyntax, model, systemSingleType, systemDoubleType); + FixResolution? resolution = TryGetFixResolution(binaryExpressionSyntax, model, systemSingleType, systemDoubleType); if (resolution != null) { @@ -57,19 +57,19 @@ public sealed override async Task RegisterCodeFixesAsync(CodeFixContext context) } } - private FixResolution TryGetFixResolution(SyntaxNode binaryExpressionSyntax, SemanticModel model, INamedTypeSymbol systemSingleType, INamedTypeSymbol systemDoubleType) + private FixResolution? TryGetFixResolution(SyntaxNode binaryExpressionSyntax, SemanticModel model, INamedTypeSymbol systemSingleType, INamedTypeSymbol systemDoubleType) { bool isEqualsOperator = IsEqualsOperator(binaryExpressionSyntax); SyntaxNode leftOperand = GetLeftOperand(binaryExpressionSyntax); SyntaxNode rightOperand = GetRightOperand(binaryExpressionSyntax); - ITypeSymbol systemTypeLeft = TryGetSystemTypeForNanConstantExpression(leftOperand, model, systemSingleType, systemDoubleType); + ITypeSymbol? systemTypeLeft = TryGetSystemTypeForNanConstantExpression(leftOperand, model, systemSingleType, systemDoubleType); if (systemTypeLeft != null) { return new FixResolution(binaryExpressionSyntax, systemTypeLeft, rightOperand, isEqualsOperator); } - ITypeSymbol systemTypeRight = TryGetSystemTypeForNanConstantExpression(rightOperand, model, systemSingleType, systemDoubleType); + ITypeSymbol? systemTypeRight = TryGetSystemTypeForNanConstantExpression(rightOperand, model, systemSingleType, systemDoubleType); if (systemTypeRight != null) { return new FixResolution(binaryExpressionSyntax, systemTypeRight, leftOperand, isEqualsOperator); @@ -78,7 +78,7 @@ private FixResolution TryGetFixResolution(SyntaxNode binaryExpressionSyntax, Sem return null; } - private static ITypeSymbol TryGetSystemTypeForNanConstantExpression(SyntaxNode expressionSyntax, SemanticModel model, INamedTypeSymbol systemSingleType, INamedTypeSymbol systemDoubleType) + private static ITypeSymbol? TryGetSystemTypeForNanConstantExpression(SyntaxNode expressionSyntax, SemanticModel model, INamedTypeSymbol systemSingleType, INamedTypeSymbol systemDoubleType) { if (model.GetSymbolInfo(expressionSyntax).Symbol is IFieldSymbol fieldSymbol) { diff --git a/src/Microsoft.NetCore.Analyzers/Core/Runtime/UseOrdinalStringComparison.Fixer.cs b/src/Microsoft.NetCore.Analyzers/Core/Runtime/UseOrdinalStringComparison.Fixer.cs index a2996b043b..d38cbce2e1 100644 --- a/src/Microsoft.NetCore.Analyzers/Core/Runtime/UseOrdinalStringComparison.Fixer.cs +++ b/src/Microsoft.NetCore.Analyzers/Core/Runtime/UseOrdinalStringComparison.Fixer.cs @@ -9,7 +9,6 @@ using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.CodeFixes; using Microsoft.CodeAnalysis.Editing; -using Microsoft.CodeAnalysis.Formatting; namespace Microsoft.NetCore.Analyzers.Runtime { @@ -51,32 +50,9 @@ public override async Task RegisterCodeFixesAsync(CodeFixContext context) protected abstract bool IsInIdentifierNameContext(SyntaxNode node); protected abstract Task FixIdentifierName(Document document, SyntaxGenerator generator, SyntaxNode root, SyntaxNode identifier, CancellationToken cancellationToken); - internal SyntaxNode CreateEqualsExpression(SyntaxGenerator generator, SemanticModel model, SyntaxNode operand1, SyntaxNode operand2, bool isEquals) - { - INamedTypeSymbol stringType = model.Compilation.GetSpecialType(SpecialType.System_String); - SyntaxNode memberAccess = generator.MemberAccessExpression( - generator.TypeExpressionForStaticMemberAccess(stringType), - generator.IdentifierName(UseOrdinalStringComparisonAnalyzer.EqualsMethodName)); - SyntaxNode ordinal = CreateOrdinalMemberAccess(generator, model); - SyntaxNode invocation = generator.InvocationExpression( - memberAccess, - operand1, - operand2.WithoutTrailingTrivia(), - ordinal) - .WithAdditionalAnnotations(Formatter.Annotation); - if (!isEquals) - { - invocation = generator.LogicalNotExpression(invocation); - } - - invocation = invocation.WithTrailingTrivia(operand2.GetTrailingTrivia()); - - return invocation; - } - internal static SyntaxNode CreateOrdinalMemberAccess(SyntaxGenerator generator, SemanticModel model) { - INamedTypeSymbol stringComparisonType = model.Compilation.GetOrCreateTypeByMetadataName(WellKnownTypeNames.SystemStringComparison); + INamedTypeSymbol stringComparisonType = model.Compilation.GetOrCreateTypeByMetadataName(WellKnownTypeNames.SystemStringComparison)!; return generator.MemberAccessExpression( generator.TypeExpressionForStaticMemberAccess(stringComparisonType), generator.IdentifierName(UseOrdinalStringComparisonAnalyzer.OrdinalText)); diff --git a/src/Microsoft.NetCore.Analyzers/Core/Runtime/UseOrdinalStringComparison.cs b/src/Microsoft.NetCore.Analyzers/Core/Runtime/UseOrdinalStringComparison.cs index 8827509e46..6681fd091d 100644 --- a/src/Microsoft.NetCore.Analyzers/Core/Runtime/UseOrdinalStringComparison.cs +++ b/src/Microsoft.NetCore.Analyzers/Core/Runtime/UseOrdinalStringComparison.cs @@ -46,7 +46,7 @@ public override void Initialize(AnalysisContext analysisContext) analysisContext.RegisterCompilationStartAction( (context) => { - INamedTypeSymbol stringComparisonType = context.Compilation.GetOrCreateTypeByMetadataName(StringComparisonTypeName); + INamedTypeSymbol? stringComparisonType = context.Compilation.GetOrCreateTypeByMetadataName(StringComparisonTypeName); if (stringComparisonType != null) { context.RegisterOperationAction(operationContext => diff --git a/src/Microsoft.NetCore.Analyzers/Core/Security/ApprovedCipherModeAnalyzer.cs b/src/Microsoft.NetCore.Analyzers/Core/Security/ApprovedCipherModeAnalyzer.cs index 7fb7a7515a..af557e290c 100644 --- a/src/Microsoft.NetCore.Analyzers/Core/Security/ApprovedCipherModeAnalyzer.cs +++ b/src/Microsoft.NetCore.Analyzers/Core/Security/ApprovedCipherModeAnalyzer.cs @@ -56,7 +56,7 @@ public sealed override void Initialize(AnalysisContext context) context.RegisterCompilationStartAction( (CompilationStartAnalysisContext compilationStartAnalysisContext) => { - INamedTypeSymbol cipherModeTypeSymbol = + INamedTypeSymbol? cipherModeTypeSymbol = compilationStartAnalysisContext.Compilation.GetOrCreateTypeByMetadataName(WellKnownTypeNames.SystemSecurityCryptographyCipherMode); if (cipherModeTypeSymbol == null) diff --git a/src/Microsoft.NetCore.Analyzers/Core/Security/DoNotCallDangerousMethodsInDeserialization.cs b/src/Microsoft.NetCore.Analyzers/Core/Security/DoNotCallDangerousMethodsInDeserialization.cs index 1203247891..feb8edc6ea 100644 --- a/src/Microsoft.NetCore.Analyzers/Core/Security/DoNotCallDangerousMethodsInDeserialization.cs +++ b/src/Microsoft.NetCore.Analyzers/Core/Security/DoNotCallDangerousMethodsInDeserialization.cs @@ -9,7 +9,6 @@ using Analyzer.Utilities.Extensions; using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.Diagnostics; -using Microsoft.CodeAnalysis.FlowAnalysis.DataFlow; using Microsoft.CodeAnalysis.Operations; namespace Microsoft.NetCore.Analyzers.Security @@ -69,7 +68,7 @@ public sealed override void Initialize(AnalysisContext context) if (!wellKnownTypeProvider.TryGetOrCreateTypeByMetadataName( WellKnownTypeNames.SystemSerializableAttribute, - out INamedTypeSymbol serializableAttributeTypeSymbol)) + out INamedTypeSymbol? serializableAttributeTypeSymbol)) { return; } @@ -80,7 +79,7 @@ public sealed override void Initialize(AnalysisContext context) { if (!wellKnownTypeProvider.TryGetOrCreateTypeByMetadataName( typeName, - out INamedTypeSymbol typeSymbol)) + out INamedTypeSymbol? typeSymbol)) { continue; } @@ -105,22 +104,22 @@ public sealed override void Initialize(AnalysisContext context) if (wellKnownTypeProvider.TryGetOrCreateTypeByMetadataName( WellKnownTypeNames.SystemRuntimeSerializationOnDeserializingAttribute, - out INamedTypeSymbol onDeserializingAttributeTypeSymbol)) + out INamedTypeSymbol? onDeserializingAttributeTypeSymbol)) { attributeTypeSymbolsBuilder.Add(onDeserializingAttributeTypeSymbol); } if (wellKnownTypeProvider.TryGetOrCreateTypeByMetadataName( WellKnownTypeNames.SystemRuntimeSerializationOnDeserializedAttribute, - out INamedTypeSymbol onDeserializedAttributeTypeSymbol)) + out INamedTypeSymbol? onDeserializedAttributeTypeSymbol)) { attributeTypeSymbolsBuilder.Add(onDeserializedAttributeTypeSymbol); } var attributeTypeSymbols = attributeTypeSymbolsBuilder.ToImmutable(); - if (!wellKnownTypeProvider.TryGetOrCreateTypeByMetadataName(WellKnownTypeNames.SystemRuntimeSerializationStreamingContext, out INamedTypeSymbol streamingContextTypeSymbol) || - !wellKnownTypeProvider.TryGetOrCreateTypeByMetadataName(WellKnownTypeNames.SystemRuntimeSerializationIDeserializationCallback, out INamedTypeSymbol IDeserializationCallbackTypeSymbol)) + if (!wellKnownTypeProvider.TryGetOrCreateTypeByMetadataName(WellKnownTypeNames.SystemRuntimeSerializationStreamingContext, out INamedTypeSymbol? streamingContextTypeSymbol) || + !wellKnownTypeProvider.TryGetOrCreateTypeByMetadataName(WellKnownTypeNames.SystemRuntimeSerializationIDeserializationCallback, out INamedTypeSymbol? IDeserializationCallbackTypeSymbol)) { return; } @@ -149,8 +148,8 @@ public sealed override void Initialize(AnalysisContext context) operationBlockStartAnalysisContext.RegisterOperationAction(operationContext => { - ISymbol calledSymbol = null; - ITypeSymbol possibleDelegateSymbol = null; + ISymbol? calledSymbol = null; + ITypeSymbol? possibleDelegateSymbol = null; switch (operationContext.Operation) { @@ -174,6 +173,9 @@ public sealed override void Initialize(AnalysisContext context) } break; + + default: + return; } calledMethods.TryAdd(calledSymbol, true); diff --git a/src/Microsoft.NetCore.Analyzers/Core/Security/DoNotDisableCertificateValidation.cs b/src/Microsoft.NetCore.Analyzers/Core/Security/DoNotDisableCertificateValidation.cs index 18fbb0d6ce..625e215c4b 100644 --- a/src/Microsoft.NetCore.Analyzers/Core/Security/DoNotDisableCertificateValidation.cs +++ b/src/Microsoft.NetCore.Analyzers/Core/Security/DoNotDisableCertificateValidation.cs @@ -80,7 +80,7 @@ public sealed override void Initialize(AnalysisContext context) { case OperationKind.AnonymousFunction: if (!IsCertificateValidationFunction( - (delegateCreationOperation.Target as IAnonymousFunctionOperation).Symbol, + ((IAnonymousFunctionOperation)delegateCreationOperation.Target).Symbol, obj, x509Certificate, x509Chain, diff --git a/src/Microsoft.NetCore.Analyzers/Core/Security/DoNotDisableHttpClientCRLCheck.cs b/src/Microsoft.NetCore.Analyzers/Core/Security/DoNotDisableHttpClientCRLCheck.cs index a7847fe11a..52596058bd 100644 --- a/src/Microsoft.NetCore.Analyzers/Core/Security/DoNotDisableHttpClientCRLCheck.cs +++ b/src/Microsoft.NetCore.Analyzers/Core/Security/DoNotDisableHttpClientCRLCheck.cs @@ -65,7 +65,7 @@ class DoNotDisableHttpClientCRLCheck : DiagnosticAnalyzer (ValueContentAbstractValue valueContentAbstractValue) => PropertySetCallbacks.EvaluateLiteralValues( valueContentAbstractValue, - (object o) => o is bool booleanValue && booleanValue == false), + (object? o) => o is bool booleanValue && booleanValue == false), CheckCertificateRevocationListIndex), new PropertyMapper( "ServerCertificateCustomValidationCallback", @@ -120,7 +120,7 @@ public override void Initialize(AnalysisContext context) { var wellKnownTypeProvider = WellKnownTypeProvider.GetOrCreate(compilationStartAnalysisContext.Compilation); - if (!wellKnownTypeProvider.TryGetOrCreateTypeByMetadataName(WellKnownTypeNames.SystemNetHttpHttpClient, out INamedTypeSymbol httpClientTypeSymbol)) + if (!wellKnownTypeProvider.TryGetOrCreateTypeByMetadataName(WellKnownTypeNames.SystemNetHttpHttpClient, out INamedTypeSymbol? httpClientTypeSymbol)) { return; } @@ -175,7 +175,7 @@ public override void Initialize(AnalysisContext context) compilationStartAnalysisContext.RegisterCompilationEndAction( (CompilationAnalysisContext compilationAnalysisContext) => { - PooledDictionary<(Location Location, IMethodSymbol Method), HazardousUsageEvaluationResult> allResults = null; + PooledDictionary<(Location Location, IMethodSymbol Method), HazardousUsageEvaluationResult>? allResults = null; try { diff --git a/src/Microsoft.NetCore.Analyzers/Core/Security/DoNotDisableRequestValidation.cs b/src/Microsoft.NetCore.Analyzers/Core/Security/DoNotDisableRequestValidation.cs index b49dd9ac5e..51d7b20b5f 100644 --- a/src/Microsoft.NetCore.Analyzers/Core/Security/DoNotDisableRequestValidation.cs +++ b/src/Microsoft.NetCore.Analyzers/Core/Security/DoNotDisableRequestValidation.cs @@ -6,7 +6,6 @@ using Analyzer.Utilities.Extensions; using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.Diagnostics; -using Microsoft.CodeAnalysis.FlowAnalysis.DataFlow; namespace Microsoft.NetCore.Analyzers.Security { @@ -52,7 +51,7 @@ public override void Initialize(AnalysisContext context) { if (!compilationStartAnalysisContext.Compilation.TryGetOrCreateTypeByMetadataName( WellKnownTypeNames.SystemWebMvcValidateInputAttribute, - out INamedTypeSymbol validateInputAttributeTypeSymbol)) + out INamedTypeSymbol? validateInputAttributeTypeSymbol)) { return; } diff --git a/src/Microsoft.NetCore.Analyzers/Core/Security/DoNotInstallRootCert.cs b/src/Microsoft.NetCore.Analyzers/Core/Security/DoNotInstallRootCert.cs index 6795e2b793..83083aa308 100644 --- a/src/Microsoft.NetCore.Analyzers/Core/Security/DoNotInstallRootCert.cs +++ b/src/Microsoft.NetCore.Analyzers/Core/Security/DoNotInstallRootCert.cs @@ -162,7 +162,7 @@ public override void Initialize(AnalysisContext context) compilationStartAnalysisContext.RegisterCompilationEndAction( (CompilationAnalysisContext compilationAnalysisContext) => { - PooledDictionary<(Location Location, IMethodSymbol Method), HazardousUsageEvaluationResult> allResults = null; + PooledDictionary<(Location Location, IMethodSymbol Method), HazardousUsageEvaluationResult>? allResults = null; try { diff --git a/src/Microsoft.NetCore.Analyzers/Core/Security/DoNotReferSelfInSerializableClass.cs b/src/Microsoft.NetCore.Analyzers/Core/Security/DoNotReferSelfInSerializableClass.cs index a2b52a7bc1..4a5fc0fc00 100644 --- a/src/Microsoft.NetCore.Analyzers/Core/Security/DoNotReferSelfInSerializableClass.cs +++ b/src/Microsoft.NetCore.Analyzers/Core/Security/DoNotReferSelfInSerializableClass.cs @@ -78,7 +78,7 @@ public sealed override void Initialize(AnalysisContext context) compilationStartAnalysisContext.RegisterSymbolAction( (SymbolAnalysisContext symbolAnalysisContext) => { - DrawGraph(symbolAnalysisContext.Symbol as ITypeSymbol); + DrawGraph((ITypeSymbol)symbolAnalysisContext.Symbol); }, SymbolKind.NamedType); compilationStartAnalysisContext.RegisterCompilationEndAction( @@ -131,9 +131,9 @@ void DrawGraph(ITypeSymbol point) } if (point.IsInSource() && - point.HasAttribute(serializableAttributeTypeSymbol)) + point.HasAttribute(serializableAttributeTypeSymbol!)) { - var fieldPoints = point.GetMembers().OfType().Where(s => !s.HasAttribute(nonSerializedAttribute) && + var fieldPoints = point.GetMembers().OfType().Where(s => !s.HasAttribute(nonSerializedAttribute!) && !s.IsStatic); foreach (var fieldPoint in fieldPoints) diff --git a/src/Microsoft.NetCore.Analyzers/Core/Security/DoNotSerializeTypeWithPointerFields.cs b/src/Microsoft.NetCore.Analyzers/Core/Security/DoNotSerializeTypeWithPointerFields.cs index 9d8a7f5892..0fde4998b8 100644 --- a/src/Microsoft.NetCore.Analyzers/Core/Security/DoNotSerializeTypeWithPointerFields.cs +++ b/src/Microsoft.NetCore.Analyzers/Core/Security/DoNotSerializeTypeWithPointerFields.cs @@ -86,7 +86,7 @@ public sealed override void Initialize(AnalysisContext context) // typeSymbol: The symbol of the type to be analyzed // relatedFieldSymbol: When relatedFieldSymbol is null, traverse all descendants of typeSymbol to // find pointer fields; otherwise, traverse to find if relatedFieldSymbol is a pointer field - void LookForSerializationWithPointerFields(ITypeSymbol typeSymbol, IFieldSymbol relatedFieldSymbol) + void LookForSerializationWithPointerFields(ITypeSymbol typeSymbol, IFieldSymbol? relatedFieldSymbol) { if (typeSymbol is IPointerTypeSymbol pointerTypeSymbol) { @@ -94,7 +94,9 @@ void LookForSerializationWithPointerFields(ITypeSymbol typeSymbol, IFieldSymbol if (pointerTypeSymbol.PointedAtType.TypeKind == TypeKind.Struct || pointerTypeSymbol.PointedAtType.TypeKind == TypeKind.Pointer) { +#pragma warning disable CS8604 // Possible null reference argument. pointerFields.TryAdd(relatedFieldSymbol, true); +#pragma warning restore CS8604 // Possible null reference argument. } } else if (typeSymbol is INamedTypeSymbol namedTypeSymbol) diff --git a/src/Microsoft.NetCore.Analyzers/Core/Security/DoNotSetSwitch.cs b/src/Microsoft.NetCore.Analyzers/Core/Security/DoNotSetSwitch.cs index b69f0e0c13..e9df312f21 100644 --- a/src/Microsoft.NetCore.Analyzers/Core/Security/DoNotSetSwitch.cs +++ b/src/Microsoft.NetCore.Analyzers/Core/Security/DoNotSetSwitch.cs @@ -129,6 +129,10 @@ public override void Initialize(AnalysisContext context) operationAnalysisContext.CancellationToken), out _, out _); + if (valueContentResult == null) + { + return; + } var switchNameValueContent = valueContentResult[ OperationKind.Argument, diff --git a/src/Microsoft.NetCore.Analyzers/Core/Security/DoNotUseAccountSAS.cs b/src/Microsoft.NetCore.Analyzers/Core/Security/DoNotUseAccountSAS.cs index fdc2ee7b8f..004a49887a 100644 --- a/src/Microsoft.NetCore.Analyzers/Core/Security/DoNotUseAccountSAS.cs +++ b/src/Microsoft.NetCore.Analyzers/Core/Security/DoNotUseAccountSAS.cs @@ -5,7 +5,6 @@ using Analyzer.Utilities.Extensions; using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.Diagnostics; -using Microsoft.CodeAnalysis.FlowAnalysis.DataFlow; using Microsoft.CodeAnalysis.Operations; namespace Microsoft.NetCore.Analyzers.Security @@ -51,7 +50,7 @@ public override void Initialize(AnalysisContext context) { if (!compilationStartAnalysisContext.Compilation.TryGetOrCreateTypeByMetadataName( WellKnownTypeNames.MicrosoftWindowsAzureStorageCloudStorageAccount, - out INamedTypeSymbol cloudStorageAccountTypeSymbol)) + out INamedTypeSymbol? cloudStorageAccountTypeSymbol)) { return; } diff --git a/src/Microsoft.NetCore.Analyzers/Core/Security/DoNotUseCreateEncryptorWithNonDefaultIV.cs b/src/Microsoft.NetCore.Analyzers/Core/Security/DoNotUseCreateEncryptorWithNonDefaultIV.cs index ea58f09b96..13c0c509b7 100644 --- a/src/Microsoft.NetCore.Analyzers/Core/Security/DoNotUseCreateEncryptorWithNonDefaultIV.cs +++ b/src/Microsoft.NetCore.Analyzers/Core/Security/DoNotUseCreateEncryptorWithNonDefaultIV.cs @@ -137,7 +137,7 @@ public override void Initialize(AnalysisContext context) compilationStartAnalysisContext.RegisterCompilationEndAction( (CompilationAnalysisContext compilationAnalysisContext) => { - PooledDictionary<(Location Location, IMethodSymbol Method), HazardousUsageEvaluationResult> allResults = null; + PooledDictionary<(Location Location, IMethodSymbol Method), HazardousUsageEvaluationResult>? allResults = null; try { diff --git a/src/Microsoft.NetCore.Analyzers/Core/Security/DoNotUseDeprecatedSecurityProtocols.cs b/src/Microsoft.NetCore.Analyzers/Core/Security/DoNotUseDeprecatedSecurityProtocols.cs index 458a66f9ad..a55c30340b 100644 --- a/src/Microsoft.NetCore.Analyzers/Core/Security/DoNotUseDeprecatedSecurityProtocols.cs +++ b/src/Microsoft.NetCore.Analyzers/Core/Security/DoNotUseDeprecatedSecurityProtocols.cs @@ -6,7 +6,6 @@ using Analyzer.Utilities.Extensions; using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.Diagnostics; -using Microsoft.CodeAnalysis.FlowAnalysis.DataFlow; using Microsoft.CodeAnalysis.Operations; using Microsoft.NetCore.Analyzers.Security.Helpers; @@ -117,9 +116,9 @@ public override void Initialize(AnalysisContext context) // Find the topmost operation with a bad bit set, unless we find an operation that would've been // flagged by the FieldReference callback above. - IOperation foundDeprecatedOperation = null; + IOperation? foundDeprecatedOperation = null; bool foundDeprecatedReference = false; - IOperation foundHardCodedOperation = null; + IOperation? foundHardCodedOperation = null; bool foundHardCodedReference = false; foreach (IOperation childOperation in assignmentOperation.Value.DescendantsAndSelf()) { @@ -188,7 +187,7 @@ public override void Initialize(AnalysisContext context) out bool isDeprecatedProtocol, out bool isHardCodedOkayProtocol) { - if (securityProtocolTypeTypeSymbol.Equals(fieldReferenceOperation.Field.ContainingType)) + if (securityProtocolTypeTypeSymbol!.Equals(fieldReferenceOperation.Field.ContainingType)) { if (HardCodedSafeProtocolMetadataNames.Contains(fieldReferenceOperation.Field.Name)) { @@ -221,7 +220,7 @@ bool IsAndEqualsServicePointManagerAssignment(ICompoundAssignmentOperation compo return compoundAssignmentOperation.OperatorKind == BinaryOperatorKind.And && compoundAssignmentOperation.Target is IPropertyReferenceOperation targetPropertyReference && targetPropertyReference.Instance == null - && servicePointManagerTypeSymbol.Equals(targetPropertyReference.Property.ContainingType) + && servicePointManagerTypeSymbol!.Equals(targetPropertyReference.Property.ContainingType) && targetPropertyReference.Property.MetadataName == "SecurityProtocol"; } }); diff --git a/src/Microsoft.NetCore.Analyzers/Core/Security/DoNotUseInsecureCryptographicAlgorithms.cs b/src/Microsoft.NetCore.Analyzers/Core/Security/DoNotUseInsecureCryptographicAlgorithms.cs index ce3b658379..46dec5c663 100644 --- a/src/Microsoft.NetCore.Analyzers/Core/Security/DoNotUseInsecureCryptographicAlgorithms.cs +++ b/src/Microsoft.NetCore.Analyzers/Core/Security/DoNotUseInsecureCryptographicAlgorithms.cs @@ -106,8 +106,8 @@ public override void Initialize(AnalysisContext analysisContext) } INamedTypeSymbol type = method.ContainingType; - DiagnosticDescriptor rule = null; - string algorithmName = null; + DiagnosticDescriptor? rule = null; + string? algorithmName = null; if (type.DerivesFrom(cryptTypes.MD5)) { @@ -136,7 +136,9 @@ public override void Initialize(AnalysisContext analysisContext) && method.MetadataName == WellKnownMemberNames.InstanceConstructorName)) { rule = DoNotUseBrokenCryptographyRule; +#pragma warning disable CS8602 // Dereference of a possibly null reference. algorithmName = cryptTypes.DSA.Name; +#pragma warning restore CS8602 // Dereference of a possibly null reference. } else if (type.DerivesFrom(cryptTypes.HMACMD5)) { diff --git a/src/Microsoft.NetCore.Analyzers/Core/Security/DoNotUseInsecureDeserializerJavascriptSerializerWithSimpleTypeResolver.cs b/src/Microsoft.NetCore.Analyzers/Core/Security/DoNotUseInsecureDeserializerJavascriptSerializerWithSimpleTypeResolver.cs index 18b09af79b..abd4e1f79a 100644 --- a/src/Microsoft.NetCore.Analyzers/Core/Security/DoNotUseInsecureDeserializerJavascriptSerializerWithSimpleTypeResolver.cs +++ b/src/Microsoft.NetCore.Analyzers/Core/Security/DoNotUseInsecureDeserializerJavascriptSerializerWithSimpleTypeResolver.cs @@ -77,9 +77,9 @@ public override void Initialize(AnalysisContext context) (CompilationStartAnalysisContext compilationStartAnalysisContext) => { WellKnownTypeProvider wellKnownTypeProvider = WellKnownTypeProvider.GetOrCreate(compilationStartAnalysisContext.Compilation); - if (!wellKnownTypeProvider.TryGetOrCreateTypeByMetadataName(WellKnownTypeNames.SystemWebScriptSerializationJavaScriptSerializer, out INamedTypeSymbol javaScriptSerializerSymbol) - || !wellKnownTypeProvider.TryGetOrCreateTypeByMetadataName(WellKnownTypeNames.SystemWebScriptSerializationJavaScriptTypeResolver, out INamedTypeSymbol javaScriptTypeResolverSymbol) - || !wellKnownTypeProvider.TryGetOrCreateTypeByMetadataName(WellKnownTypeNames.SystemWebScriptSerializationSimpleTypeResolver, out INamedTypeSymbol simpleTypeResolverSymbol)) + if (!wellKnownTypeProvider.TryGetOrCreateTypeByMetadataName(WellKnownTypeNames.SystemWebScriptSerializationJavaScriptSerializer, out INamedTypeSymbol? javaScriptSerializerSymbol) + || !wellKnownTypeProvider.TryGetOrCreateTypeByMetadataName(WellKnownTypeNames.SystemWebScriptSerializationJavaScriptTypeResolver, out INamedTypeSymbol? javaScriptTypeResolverSymbol) + || !wellKnownTypeProvider.TryGetOrCreateTypeByMetadataName(WellKnownTypeNames.SystemWebScriptSerializationSimpleTypeResolver, out INamedTypeSymbol? simpleTypeResolverSymbol)) { return; } @@ -199,7 +199,7 @@ public override void Initialize(AnalysisContext context) compilationStartAnalysisContext.RegisterCompilationEndAction( (CompilationAnalysisContext compilationAnalysisContext) => { - PooledDictionary<(Location Location, IMethodSymbol Method), HazardousUsageEvaluationResult> allResults = null; + PooledDictionary<(Location Location, IMethodSymbol Method), HazardousUsageEvaluationResult>? allResults = null; try { lock (rootOperationsNeedingAnalysis) diff --git a/src/Microsoft.NetCore.Analyzers/Core/Security/DoNotUseInsecureDeserializerJsonNetWithoutBinder.cs b/src/Microsoft.NetCore.Analyzers/Core/Security/DoNotUseInsecureDeserializerJsonNetWithoutBinder.cs index bc38436e2c..a2b32045bf 100644 --- a/src/Microsoft.NetCore.Analyzers/Core/Security/DoNotUseInsecureDeserializerJsonNetWithoutBinder.cs +++ b/src/Microsoft.NetCore.Analyzers/Core/Security/DoNotUseInsecureDeserializerJsonNetWithoutBinder.cs @@ -83,7 +83,7 @@ internal class DoNotUseInsecureDeserializerJsonNetWithoutBinder : DiagnosticAnal (ValueContentAbstractValue valueContentAbstractValue) => PropertySetCallbacks.EvaluateLiteralValues( valueContentAbstractValue, - (object o) => o is int i && i != 0), // None is 0, and anything other than None is flagged. + (object? o) => o is int i && i != 0), // None is 0, and anything other than None is flagged. TypeNameHandlingIndex), new PropertyMapper( "Binder", @@ -116,7 +116,7 @@ public override void Initialize(AnalysisContext context) { if (!compilationStartAnalysisContext.Compilation.TryGetOrCreateTypeByMetadataName( WellKnownTypeNames.NewtonsoftJsonJsonSerializer, - out INamedTypeSymbol jsonSerializerSymbol)) + out INamedTypeSymbol? jsonSerializerSymbol)) { return; } @@ -181,7 +181,7 @@ public override void Initialize(AnalysisContext context) compilationStartAnalysisContext.RegisterCompilationEndAction( (CompilationAnalysisContext compilationAnalysisContext) => { - PooledDictionary<(Location Location, IMethodSymbol Method), HazardousUsageEvaluationResult> allResults = null; + PooledDictionary<(Location Location, IMethodSymbol Method), HazardousUsageEvaluationResult>? allResults = null; try { lock (rootOperationsNeedingAnalysis) diff --git a/src/Microsoft.NetCore.Analyzers/Core/Security/DoNotUseInsecureDeserializerMethodsBase.cs b/src/Microsoft.NetCore.Analyzers/Core/Security/DoNotUseInsecureDeserializerMethodsBase.cs index 4eb43393b6..eba18c8aba 100644 --- a/src/Microsoft.NetCore.Analyzers/Core/Security/DoNotUseInsecureDeserializerMethodsBase.cs +++ b/src/Microsoft.NetCore.Analyzers/Core/Security/DoNotUseInsecureDeserializerMethodsBase.cs @@ -45,10 +45,7 @@ public sealed override void Initialize(AnalysisContext context) { ImmutableHashSet cachedDeserializationMethodNames = this.DeserializationMethodNames; - Debug.Assert(this.DeserializerTypeMetadataName != null); - Debug.Assert(cachedDeserializationMethodNames != null); Debug.Assert(!cachedDeserializationMethodNames.IsEmpty); - Debug.Assert(this.MethodUsedDescriptor != null); context.EnableConcurrentExecution(); @@ -58,7 +55,7 @@ public sealed override void Initialize(AnalysisContext context) context.RegisterCompilationStartAction( (CompilationStartAnalysisContext compilationStartAnalysisContext) => { - INamedTypeSymbol deserializerTypeSymbol = + INamedTypeSymbol? deserializerTypeSymbol = compilationStartAnalysisContext.Compilation.GetOrCreateTypeByMetadataName(this.DeserializerTypeMetadataName); if (deserializerTypeSymbol == null) { diff --git a/src/Microsoft.NetCore.Analyzers/Core/Security/DoNotUseInsecureDeserializerWithoutBinderBase.cs b/src/Microsoft.NetCore.Analyzers/Core/Security/DoNotUseInsecureDeserializerWithoutBinderBase.cs index 0e34733990..268d13a62e 100644 --- a/src/Microsoft.NetCore.Analyzers/Core/Security/DoNotUseInsecureDeserializerWithoutBinderBase.cs +++ b/src/Microsoft.NetCore.Analyzers/Core/Security/DoNotUseInsecureDeserializerWithoutBinderBase.cs @@ -6,7 +6,6 @@ using System.Diagnostics; using System.Diagnostics.CodeAnalysis; using System.Linq; -using Analyzer.Utilities; using Analyzer.Utilities.Extensions; using Analyzer.Utilities.FlowAnalysis.Analysis.PropertySetAnalysis; using Analyzer.Utilities.PooledObjects; @@ -70,7 +69,6 @@ public sealed override void Initialize(AnalysisContext context) Debug.Assert(!String.IsNullOrWhiteSpace(this.DeserializerTypeMetadataName)); Debug.Assert(!String.IsNullOrWhiteSpace(this.SerializationBinderPropertyMetadataName)); - Debug.Assert(cachedDeserializationMethodNames != null); Debug.Assert(!cachedDeserializationMethodNames.IsEmpty); Debug.Assert(this.BinderDefinitelyNotSetDescriptor != null); Debug.Assert(this.BinderMaybeNotSetDescriptor != null); @@ -98,7 +96,7 @@ public sealed override void Initialize(AnalysisContext context) { if (!compilationStartAnalysisContext.Compilation.TryGetOrCreateTypeByMetadataName( this.DeserializerTypeMetadataName, - out INamedTypeSymbol deserializerTypeSymbol)) + out INamedTypeSymbol? deserializerTypeSymbol)) { return; } @@ -112,9 +110,9 @@ public sealed override void Initialize(AnalysisContext context) // TODO: Handle case when exactly one of the below rules is configured to skip analysis. if (owningSymbol.IsConfiguredToSkipAnalysis(operationBlockStartAnalysisContext.Options, - BinderDefinitelyNotSetDescriptor, operationBlockStartAnalysisContext.Compilation, operationBlockStartAnalysisContext.CancellationToken) && + BinderDefinitelyNotSetDescriptor!, operationBlockStartAnalysisContext.Compilation, operationBlockStartAnalysisContext.CancellationToken) && owningSymbol.IsConfiguredToSkipAnalysis(operationBlockStartAnalysisContext.Options, - BinderMaybeNotSetDescriptor, operationBlockStartAnalysisContext.Compilation, operationBlockStartAnalysisContext.CancellationToken)) + BinderMaybeNotSetDescriptor!, operationBlockStartAnalysisContext.Compilation, operationBlockStartAnalysisContext.CancellationToken)) { return; } @@ -171,7 +169,7 @@ public sealed override void Initialize(AnalysisContext context) compilationStartAnalysisContext.RegisterCompilationEndAction( (CompilationAnalysisContext compilationAnalysisContext) => { - PooledDictionary<(Location Location, IMethodSymbol Method), HazardousUsageEvaluationResult> allResults = null; + PooledDictionary<(Location Location, IMethodSymbol Method), HazardousUsageEvaluationResult>? allResults = null; try { lock (rootOperationsNeedingAnalysis) @@ -208,11 +206,11 @@ public sealed override void Initialize(AnalysisContext context) switch (kvp.Value) { case HazardousUsageEvaluationResult.Flagged: - descriptor = this.BinderDefinitelyNotSetDescriptor; + descriptor = this.BinderDefinitelyNotSetDescriptor!; break; case HazardousUsageEvaluationResult.MaybeFlagged: - descriptor = this.BinderMaybeNotSetDescriptor; + descriptor = this.BinderMaybeNotSetDescriptor!; break; default: diff --git a/src/Microsoft.NetCore.Analyzers/Core/Security/DoNotUseInsecureSettingsForJsonNet.cs b/src/Microsoft.NetCore.Analyzers/Core/Security/DoNotUseInsecureSettingsForJsonNet.cs index e129cd70b8..2a0a3a942b 100644 --- a/src/Microsoft.NetCore.Analyzers/Core/Security/DoNotUseInsecureSettingsForJsonNet.cs +++ b/src/Microsoft.NetCore.Analyzers/Core/Security/DoNotUseInsecureSettingsForJsonNet.cs @@ -82,7 +82,7 @@ public sealed class DoNotUseInsecureSettingsForJsonNet : DiagnosticAnalyzer (ValueContentAbstractValue valueContentAbstractValue) => PropertySetCallbacks.EvaluateLiteralValues( valueContentAbstractValue, - (object o) => o is int i && i != 0), // None is 0, and anything other than None is flagged. + (object? o) => o is int i && i != 0), // None is 0, and anything other than None is flagged. TypeNameHandlingIndex), new PropertyMapper( "Binder", @@ -127,9 +127,9 @@ public override void Initialize(AnalysisContext context) (CompilationStartAnalysisContext compilationStartAnalysisContext) => { WellKnownTypeProvider wellKnownTypeProvider = WellKnownTypeProvider.GetOrCreate(compilationStartAnalysisContext.Compilation); - if (!wellKnownTypeProvider.TryGetOrCreateTypeByMetadataName(WellKnownTypeNames.NewtonsoftJsonJsonSerializerSettings, out INamedTypeSymbol jsonSerializerSettingsSymbol) - || !wellKnownTypeProvider.TryGetOrCreateTypeByMetadataName(WellKnownTypeNames.NewtonsoftJsonJsonSerializer, out INamedTypeSymbol jsonSerializerSymbol) - || !wellKnownTypeProvider.TryGetOrCreateTypeByMetadataName(WellKnownTypeNames.NewtonsoftJsonJsonConvert, out INamedTypeSymbol jsonConvertSymbol)) + if (!wellKnownTypeProvider.TryGetOrCreateTypeByMetadataName(WellKnownTypeNames.NewtonsoftJsonJsonSerializerSettings, out INamedTypeSymbol? jsonSerializerSettingsSymbol) + || !wellKnownTypeProvider.TryGetOrCreateTypeByMetadataName(WellKnownTypeNames.NewtonsoftJsonJsonSerializer, out INamedTypeSymbol? jsonSerializerSymbol) + || !wellKnownTypeProvider.TryGetOrCreateTypeByMetadataName(WellKnownTypeNames.NewtonsoftJsonJsonConvert, out INamedTypeSymbol? jsonConvertSymbol)) { return; } @@ -206,7 +206,7 @@ public override void Initialize(AnalysisContext context) compilationStartAnalysisContext.RegisterCompilationEndAction( (CompilationAnalysisContext compilationAnalysisContext) => { - PooledDictionary<(Location Location, IMethodSymbol Method), HazardousUsageEvaluationResult> allResults = null; + PooledDictionary<(Location Location, IMethodSymbol Method), HazardousUsageEvaluationResult>? allResults = null; try { lock (rootOperationsNeedingAnalysis) diff --git a/src/Microsoft.NetCore.Analyzers/Core/Security/DoNotUseObsoleteKDFAlgorithm.cs b/src/Microsoft.NetCore.Analyzers/Core/Security/DoNotUseObsoleteKDFAlgorithm.cs index fd4a2eb754..188c7b4b55 100644 --- a/src/Microsoft.NetCore.Analyzers/Core/Security/DoNotUseObsoleteKDFAlgorithm.cs +++ b/src/Microsoft.NetCore.Analyzers/Core/Security/DoNotUseObsoleteKDFAlgorithm.cs @@ -52,10 +52,10 @@ public override void Initialize(AnalysisContext context) wellKnownTypeProvider.TryGetOrCreateTypeByMetadataName( WellKnownTypeNames.SystemSecurityCryptographyPasswordDeriveBytes, - out INamedTypeSymbol passwordDeriveBytesTypeSymbol); + out INamedTypeSymbol? passwordDeriveBytesTypeSymbol); wellKnownTypeProvider.TryGetOrCreateTypeByMetadataName( WellKnownTypeNames.SystemSecurityCryptographyRfc2898DeriveBytes, - out INamedTypeSymbol rfc2898DeriveBytesTypeSymbol); + out INamedTypeSymbol? rfc2898DeriveBytesTypeSymbol); if (passwordDeriveBytesTypeSymbol == null && rfc2898DeriveBytesTypeSymbol == null) { diff --git a/src/Microsoft.NetCore.Analyzers/Core/Security/DoNotUseWeakKDFAlgorithm.cs b/src/Microsoft.NetCore.Analyzers/Core/Security/DoNotUseWeakKDFAlgorithm.cs index 2bb13d0ebf..9a6ea537d2 100644 --- a/src/Microsoft.NetCore.Analyzers/Core/Security/DoNotUseWeakKDFAlgorithm.cs +++ b/src/Microsoft.NetCore.Analyzers/Core/Security/DoNotUseWeakKDFAlgorithm.cs @@ -6,7 +6,6 @@ using Analyzer.Utilities.Extensions; using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.Diagnostics; -using Microsoft.CodeAnalysis.FlowAnalysis.DataFlow; using Microsoft.CodeAnalysis.Operations; namespace Microsoft.NetCore.Analyzers.Security @@ -56,14 +55,14 @@ public override void Initialize(AnalysisContext context) if (!wellKnownTypeProvider.TryGetOrCreateTypeByMetadataName( WellKnownTypeNames.SystemSecurityCryptographyRfc2898DeriveBytes, - out INamedTypeSymbol rfc2898DeriveBytesTypeSymbol)) + out INamedTypeSymbol? rfc2898DeriveBytesTypeSymbol)) { return; } wellKnownTypeProvider.TryGetOrCreateTypeByMetadataName( WellKnownTypeNames.SystemSecurityCryptographyHashAlgorithmName, - out INamedTypeSymbol hashAlgorithmNameTypeSymbol); + out INamedTypeSymbol? hashAlgorithmNameTypeSymbol); compilationStartAnalysisContext.RegisterOperationAction(operationAnalysisContext => { diff --git a/src/Microsoft.NetCore.Analyzers/Core/Security/DoNotUseWeakKDFInsufficientIterationCount.cs b/src/Microsoft.NetCore.Analyzers/Core/Security/DoNotUseWeakKDFInsufficientIterationCount.cs index 0c87504222..95f4cafa3d 100644 --- a/src/Microsoft.NetCore.Analyzers/Core/Security/DoNotUseWeakKDFInsufficientIterationCount.cs +++ b/src/Microsoft.NetCore.Analyzers/Core/Security/DoNotUseWeakKDFInsufficientIterationCount.cs @@ -157,7 +157,7 @@ public override void Initialize(AnalysisContext context) compilationStartAnalysisContext.RegisterCompilationEndAction( (CompilationAnalysisContext compilationAnalysisContext) => { - PooledDictionary<(Location Location, IMethodSymbol Method), HazardousUsageEvaluationResult> allResults = null; + PooledDictionary<(Location Location, IMethodSymbol Method), HazardousUsageEvaluationResult>? allResults = null; try { diff --git a/src/Microsoft.NetCore.Analyzers/Core/Security/Helpers/CompilationSecurityTypes.cs b/src/Microsoft.NetCore.Analyzers/Core/Security/Helpers/CompilationSecurityTypes.cs index 9e56510b4e..1b1faa656e 100644 --- a/src/Microsoft.NetCore.Analyzers/Core/Security/Helpers/CompilationSecurityTypes.cs +++ b/src/Microsoft.NetCore.Analyzers/Core/Security/Helpers/CompilationSecurityTypes.cs @@ -10,17 +10,17 @@ public class CompilationSecurityTypes { // Some of these types may only exist in .NET Framework and not in .NET Core, but that's okay, we'll look anyway. - public INamedTypeSymbol MD5 { get; private set; } - public INamedTypeSymbol SHA1 { get; private set; } - public INamedTypeSymbol HMACSHA1 { get; private set; } - public INamedTypeSymbol DES { get; private set; } - public INamedTypeSymbol DSA { get; private set; } - public INamedTypeSymbol DSASignatureFormatter { get; private set; } - public INamedTypeSymbol HMACMD5 { get; private set; } - public INamedTypeSymbol RC2 { get; private set; } - public INamedTypeSymbol TripleDES { get; private set; } - public INamedTypeSymbol RIPEMD160 { get; private set; } - public INamedTypeSymbol HMACRIPEMD160 { get; private set; } + public INamedTypeSymbol? MD5 { get; private set; } + public INamedTypeSymbol? SHA1 { get; private set; } + public INamedTypeSymbol? HMACSHA1 { get; private set; } + public INamedTypeSymbol? DES { get; private set; } + public INamedTypeSymbol? DSA { get; private set; } + public INamedTypeSymbol? DSASignatureFormatter { get; private set; } + public INamedTypeSymbol? HMACMD5 { get; private set; } + public INamedTypeSymbol? RC2 { get; private set; } + public INamedTypeSymbol? TripleDES { get; private set; } + public INamedTypeSymbol? RIPEMD160 { get; private set; } + public INamedTypeSymbol? HMACRIPEMD160 { get; private set; } public CompilationSecurityTypes(Compilation compilation) { diff --git a/src/Microsoft.NetCore.Analyzers/Core/Security/Helpers/SecurityHelpers.cs b/src/Microsoft.NetCore.Analyzers/Core/Security/Helpers/SecurityHelpers.cs index a90ab02798..8e2adcc61f 100644 --- a/src/Microsoft.NetCore.Analyzers/Core/Security/Helpers/SecurityHelpers.cs +++ b/src/Microsoft.NetCore.Analyzers/Core/Security/Helpers/SecurityHelpers.cs @@ -29,8 +29,8 @@ internal static class SecurityHelpers string titleResourceStringName, string messageResourceStringName, bool isEnabledByDefault, - string helpLinkUri, - string descriptionResourceStringName = null, + string? helpLinkUri, + string? descriptionResourceStringName = null, params string[] customTags) { return CreateDiagnosticDescriptor( @@ -62,8 +62,8 @@ internal static class SecurityHelpers string titleResourceStringName, string messageResourceStringName, bool isEnabledByDefault, - string helpLinkUri, - string descriptionResourceStringName = null, + string? helpLinkUri, + string? descriptionResourceStringName = null, params string[] customTags) { return new DiagnosticDescriptor( diff --git a/src/Microsoft.NetCore.Analyzers/Core/Security/JsonNetTypeNameHandling.cs b/src/Microsoft.NetCore.Analyzers/Core/Security/JsonNetTypeNameHandling.cs index 7fab591222..0e93461a9f 100644 --- a/src/Microsoft.NetCore.Analyzers/Core/Security/JsonNetTypeNameHandling.cs +++ b/src/Microsoft.NetCore.Analyzers/Core/Security/JsonNetTypeNameHandling.cs @@ -6,7 +6,6 @@ using Analyzer.Utilities.Extensions; using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.Diagnostics; -using Microsoft.CodeAnalysis.FlowAnalysis.DataFlow; using Microsoft.CodeAnalysis.Operations; using Microsoft.NetCore.Analyzers.Security.Helpers; @@ -41,7 +40,7 @@ public override void Initialize(AnalysisContext analysisContext) { if (!compilationStartAnalysisContext.Compilation.TryGetOrCreateTypeByMetadataName( WellKnownTypeNames.NewtonsoftJsonTypeNameHandling, - out INamedTypeSymbol typeNameHandlingSymbol)) + out INamedTypeSymbol? typeNameHandlingSymbol)) { return; } @@ -94,7 +93,7 @@ public override void Initialize(AnalysisContext analysisContext) bool IsOtherThanNone(IFieldReferenceOperation fieldReferenceOperation) { - if (!typeNameHandlingSymbol.Equals(fieldReferenceOperation.Field.ContainingType)) + if (!typeNameHandlingSymbol!.Equals(fieldReferenceOperation.Field.ContainingType)) { return false; } diff --git a/src/Microsoft.NetCore.Analyzers/Core/Security/SetHttpOnlyForHttpCookie.cs b/src/Microsoft.NetCore.Analyzers/Core/Security/SetHttpOnlyForHttpCookie.cs index 59d63fbbf1..65b987df2c 100644 --- a/src/Microsoft.NetCore.Analyzers/Core/Security/SetHttpOnlyForHttpCookie.cs +++ b/src/Microsoft.NetCore.Analyzers/Core/Security/SetHttpOnlyForHttpCookie.cs @@ -68,7 +68,7 @@ public override void Initialize(AnalysisContext context) (CompilationStartAnalysisContext compilationStartAnalysisContext) => { if (!compilationStartAnalysisContext.Compilation.TryGetOrCreateTypeByMetadataName(WellKnownTypeNames.SystemWebHttpCookie, - out INamedTypeSymbol httpCookieSymbol)) + out INamedTypeSymbol? httpCookieSymbol)) { return; } @@ -144,7 +144,7 @@ public override void Initialize(AnalysisContext context) compilationStartAnalysisContext.RegisterCompilationEndAction( (CompilationAnalysisContext compilationAnalysisContext) => { - PooledDictionary<(Location Location, IMethodSymbol Method), HazardousUsageEvaluationResult> allResults = null; + PooledDictionary<(Location Location, IMethodSymbol Method), HazardousUsageEvaluationResult>? allResults = null; try { diff --git a/src/Microsoft.NetCore.Analyzers/Core/Security/SourceTriggeredTaintedDataAnalyzerBase.cs b/src/Microsoft.NetCore.Analyzers/Core/Security/SourceTriggeredTaintedDataAnalyzerBase.cs index 532a95ca84..fe04bbc5b7 100644 --- a/src/Microsoft.NetCore.Analyzers/Core/Security/SourceTriggeredTaintedDataAnalyzerBase.cs +++ b/src/Microsoft.NetCore.Analyzers/Core/Security/SourceTriggeredTaintedDataAnalyzerBase.cs @@ -1,5 +1,8 @@ // Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. +// TODO(dotpaul): Enable nullable analysis. +#nullable disable + using System; using System.Collections.Immutable; using System.Linq; diff --git a/src/Microsoft.NetCore.Analyzers/Core/Security/SslProtocolsAnalyzer.cs b/src/Microsoft.NetCore.Analyzers/Core/Security/SslProtocolsAnalyzer.cs index b77bb89881..5eeb71f1f8 100644 --- a/src/Microsoft.NetCore.Analyzers/Core/Security/SslProtocolsAnalyzer.cs +++ b/src/Microsoft.NetCore.Analyzers/Core/Security/SslProtocolsAnalyzer.cs @@ -7,7 +7,6 @@ using Analyzer.Utilities.Extensions; using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.Diagnostics; -using Microsoft.CodeAnalysis.FlowAnalysis.DataFlow; using Microsoft.CodeAnalysis.Operations; using Microsoft.NetCore.Analyzers.Security.Helpers; @@ -56,7 +55,7 @@ public override void Initialize(AnalysisContext context) { if (!compilationStartAnalysisContext.Compilation.TryGetOrCreateTypeByMetadataName( WellKnownTypeNames.SystemSecurityAuthenticationSslProtocols, - out INamedTypeSymbol sslProtocolsSymbol)) + out INamedTypeSymbol? sslProtocolsSymbol)) { return; } @@ -91,7 +90,7 @@ public override void Initialize(AnalysisContext context) compilationStartAnalysisContext.RegisterOperationAction( (OperationAnalysisContext operationAnalysisContext) => { - IOperation valueOperation; + IOperation? valueOperation; switch (operationAnalysisContext.Operation) { case IAssignmentOperation assignmentOperation: @@ -140,9 +139,9 @@ public override void Initialize(AnalysisContext context) // Find the topmost operation with a bad bit set, unless we find an operation that would've been // flagged by the FieldReference callback above. - IOperation foundDeprecatedOperation = null; + IOperation? foundDeprecatedOperation = null; bool foundDeprecatedReference = false; - IOperation foundHardcodedOperation = null; + IOperation? foundHardcodedOperation = null; bool foundHardcodedReference = false; foreach (IOperation childOperation in valueOperation.DescendantsAndSelf()) { @@ -214,7 +213,7 @@ public override void Initialize(AnalysisContext context) out bool isDeprecatedProtocol, out bool isHardcodedOkayProtocol) { - if (sslProtocolsSymbol.Equals(fieldReferenceOperation.Field.ContainingType)) + if (sslProtocolsSymbol!.Equals(fieldReferenceOperation.Field.ContainingType)) { if (HardcodedSslProtocolsMetadataNames.Contains(fieldReferenceOperation.Field.Name)) { diff --git a/src/Microsoft.NetCore.Analyzers/Core/Security/UseAutoValidateAntiforgeryToken.cs b/src/Microsoft.NetCore.Analyzers/Core/Security/UseAutoValidateAntiforgeryToken.cs index 7ff5c88150..66e3aca099 100644 --- a/src/Microsoft.NetCore.Analyzers/Core/Security/UseAutoValidateAntiforgeryToken.cs +++ b/src/Microsoft.NetCore.Analyzers/Core/Security/UseAutoValidateAntiforgeryToken.cs @@ -11,7 +11,6 @@ using Analyzer.Utilities.Extensions; using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.Diagnostics; -using Microsoft.CodeAnalysis.FlowAnalysis.DataFlow; using Microsoft.CodeAnalysis.Operations; using Microsoft.NetCore.Analyzers.Security.Helpers; @@ -130,8 +129,8 @@ public override void Initialize(AnalysisContext context) operationBlockStartAnalysisContext.RegisterOperationAction(operationContext => { - ISymbol calledSymbol = null; - ConcurrentDictionary callers = null; + ISymbol? calledSymbol = null; + ConcurrentDictionary? callers = null; switch (operationContext.Operation) { diff --git a/src/Microsoft.NetCore.Analyzers/Core/Security/UseDefaultDllImportSearchPathsAttribute.cs b/src/Microsoft.NetCore.Analyzers/Core/Security/UseDefaultDllImportSearchPathsAttribute.cs index 13401fe1e6..9b15a2f141 100644 --- a/src/Microsoft.NetCore.Analyzers/Core/Security/UseDefaultDllImportSearchPathsAttribute.cs +++ b/src/Microsoft.NetCore.Analyzers/Core/Security/UseDefaultDllImportSearchPathsAttribute.cs @@ -8,7 +8,6 @@ using Analyzer.Utilities.Extensions; using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.Diagnostics; -using Microsoft.CodeAnalysis.FlowAnalysis.DataFlow; using Microsoft.NetCore.Analyzers.Security.Helpers; namespace Microsoft.NetCore.Analyzers.Security @@ -56,8 +55,8 @@ public override void Initialize(AnalysisContext context) var compilation = compilationStartAnalysisContext.Compilation; var wellKnownTypeProvider = WellKnownTypeProvider.GetOrCreate(compilation); - if (!wellKnownTypeProvider.TryGetOrCreateTypeByMetadataName(WellKnownTypeNames.SystemRuntimeInteropServicesDllImportAttribute, out INamedTypeSymbol dllImportAttributeTypeSymbol) || - !wellKnownTypeProvider.TryGetOrCreateTypeByMetadataName(WellKnownTypeNames.SystemRuntimeInteropServicesDefaultDllImportSearchPathsAttribute, out INamedTypeSymbol defaultDllImportSearchPathsAttributeTypeSymbol)) + if (!wellKnownTypeProvider.TryGetOrCreateTypeByMetadataName(WellKnownTypeNames.SystemRuntimeInteropServicesDllImportAttribute, out INamedTypeSymbol? dllImportAttributeTypeSymbol) || + !wellKnownTypeProvider.TryGetOrCreateTypeByMetadataName(WellKnownTypeNames.SystemRuntimeInteropServicesDefaultDllImportSearchPathsAttribute, out INamedTypeSymbol? defaultDllImportSearchPathsAttributeTypeSymbol)) { return; } diff --git a/src/Microsoft.NetCore.Analyzers/Core/Security/UseSecureCookiesASPNetCore.cs b/src/Microsoft.NetCore.Analyzers/Core/Security/UseSecureCookiesASPNetCore.cs index dc162d1913..701a7128f1 100644 --- a/src/Microsoft.NetCore.Analyzers/Core/Security/UseSecureCookiesASPNetCore.cs +++ b/src/Microsoft.NetCore.Analyzers/Core/Security/UseSecureCookiesASPNetCore.cs @@ -157,7 +157,7 @@ public override void Initialize(AnalysisContext context) compilationStartAnalysisContext.RegisterCompilationEndAction( (CompilationAnalysisContext compilationAnalysisContext) => { - PooledDictionary<(Location Location, IMethodSymbol Method), HazardousUsageEvaluationResult> allResults = null; + PooledDictionary<(Location Location, IMethodSymbol Method), HazardousUsageEvaluationResult>? allResults = null; try { diff --git a/src/Microsoft.NetCore.Analyzers/Core/Security/UseSharedAccessProtocolHttpsOnly.cs b/src/Microsoft.NetCore.Analyzers/Core/Security/UseSharedAccessProtocolHttpsOnly.cs index b3c30ebfae..3eaad51cdd 100644 --- a/src/Microsoft.NetCore.Analyzers/Core/Security/UseSharedAccessProtocolHttpsOnly.cs +++ b/src/Microsoft.NetCore.Analyzers/Core/Security/UseSharedAccessProtocolHttpsOnly.cs @@ -77,10 +77,10 @@ public override void Initialize(AnalysisContext context) wellKnownTypeProvider.TryGetOrCreateTypeByMetadataName( WellKnownTypeNames.MicrosoftWindowsAzureStorageCloudStorageAccount, - out INamedTypeSymbol cloudStorageAccountTypeSymbol); + out INamedTypeSymbol? cloudStorageAccountTypeSymbol); - if (!wellKnownTypeProvider.TryGetOrCreateTypeByMetadataName(WellKnownTypeNames.SystemNullable1, out INamedTypeSymbol nullableTypeSymbol) || - !wellKnownTypeProvider.TryGetOrCreateTypeByMetadataName(WellKnownTypeNames.MicrosoftWindowsAzureStorageSharedAccessProtocol, out INamedTypeSymbol sharedAccessProtocolTypeSymbol)) + if (!wellKnownTypeProvider.TryGetOrCreateTypeByMetadataName(WellKnownTypeNames.SystemNullable1, out INamedTypeSymbol? nullableTypeSymbol) || + !wellKnownTypeProvider.TryGetOrCreateTypeByMetadataName(WellKnownTypeNames.MicrosoftWindowsAzureStorageSharedAccessProtocol, out INamedTypeSymbol? sharedAccessProtocolTypeSymbol)) { return; } diff --git a/src/Microsoft.NetCore.Analyzers/Core/Security/UseXmlReaderBase.cs b/src/Microsoft.NetCore.Analyzers/Core/Security/UseXmlReaderBase.cs index 6d21ea8f58..e43ba42007 100644 --- a/src/Microsoft.NetCore.Analyzers/Core/Security/UseXmlReaderBase.cs +++ b/src/Microsoft.NetCore.Analyzers/Core/Security/UseXmlReaderBase.cs @@ -2,12 +2,10 @@ using System; using System.Collections.Immutable; -using System.Diagnostics; using Analyzer.Utilities; using Analyzer.Utilities.Extensions; using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.Diagnostics; -using Microsoft.CodeAnalysis.FlowAnalysis.DataFlow; using Microsoft.CodeAnalysis.Operations; namespace Microsoft.NetCore.Analyzers.Security @@ -44,10 +42,6 @@ public abstract class UseXmlReaderBase : DiagnosticAnalyzer public override void Initialize(AnalysisContext context) { - Debug.Assert(TypeMetadataName != null); - Debug.Assert(MethodMetadataName != null); - Debug.Assert(Rule != null); - context.EnableConcurrentExecution(); // Security analyzer - analyze and report diagnostics on generated code. @@ -59,28 +53,28 @@ public override void Initialize(AnalysisContext context) if (!wellKnownTypeProvider.TryGetOrCreateTypeByMetadataName( TypeMetadataName, - out INamedTypeSymbol xmlSchemaTypeSymbol)) + out INamedTypeSymbol? xmlSchemaTypeSymbol)) { return; } - INamedTypeSymbol xmlReaderTypeSymbol = wellKnownTypeProvider.GetOrCreateTypeByMetadataName(WellKnownTypeNames.SystemXmlXmlReader); + INamedTypeSymbol? xmlReaderTypeSymbol = wellKnownTypeProvider.GetOrCreateTypeByMetadataName(WellKnownTypeNames.SystemXmlXmlReader); compilationStartAnalysisContext.RegisterOperationAction(operationAnalysisContext => { var operation = operationAnalysisContext.Operation; - IMethodSymbol methodSymbol = null; - string methodName = null; + IMethodSymbol? methodSymbol = null; + string? methodName = null; switch (operation.Kind) { case OperationKind.Invocation: - methodSymbol = (operation as IInvocationOperation).TargetMethod; + methodSymbol = ((IInvocationOperation)operation).TargetMethod; methodName = methodSymbol.Name; break; case OperationKind.ObjectCreation: - methodSymbol = (operation as IObjectCreationOperation).Constructor; + methodSymbol = ((IObjectCreationOperation)operation).Constructor; methodName = methodSymbol.ContainingType.Name; break; From 28efa043660932a0db4acbe56fb0589c3020be09 Mon Sep 17 00:00:00 2001 From: Manish Vasani Date: Thu, 7 Nov 2019 16:02:32 -0800 Subject: [PATCH 16/28] Add nullable annotations for ReleaseNotesUtil --- src/Tools/ReleaseNotesUtil/FixerExtensions.cs | 10 +++++----- src/Tools/ReleaseNotesUtil/Program.cs | 8 ++++---- src/Tools/ReleaseNotesUtil/RuleInfo.cs | 2 ++ 3 files changed, 11 insertions(+), 9 deletions(-) diff --git a/src/Tools/ReleaseNotesUtil/FixerExtensions.cs b/src/Tools/ReleaseNotesUtil/FixerExtensions.cs index e8809610d1..f3d2dd7381 100644 --- a/src/Tools/ReleaseNotesUtil/FixerExtensions.cs +++ b/src/Tools/ReleaseNotesUtil/FixerExtensions.cs @@ -23,7 +23,7 @@ public static ImmutableArray GetFixers(this AnalyzerFileReferen return ImmutableArray.Empty; } - ImmutableArray.Builder builder = null; + ImmutableArray.Builder? builder = null; try { @@ -67,8 +67,8 @@ public static ImmutableArray GetFixers(this AnalyzerFileReferen private static bool HasImplementation(CodeFixProvider fixer) { MethodInfo method = fixer.GetType().GetTypeInfo().GetMethod("RegisterCodeFixesAsync"); - AsyncStateMachineAttribute stateMachineAttr = method?.GetCustomAttribute(); - MethodInfo moveNextMethod = stateMachineAttr?.StateMachineType.GetTypeInfo().GetDeclaredMethod("MoveNext"); + AsyncStateMachineAttribute? stateMachineAttr = method?.GetCustomAttribute(); + MethodInfo? moveNextMethod = stateMachineAttr?.StateMachineType.GetTypeInfo().GetDeclaredMethod("MoveNext"); if (moveNextMethod != null) { MethodBody body = moveNextMethod.GetMethodBody(); @@ -80,7 +80,7 @@ private static bool HasImplementation(CodeFixProvider fixer) // { // return Task.CompletedTask; // } - byte[] methodBodyIL = method?.GetMethodBody()?.GetILAsByteArray(); + byte[]? methodBodyIL = method?.GetMethodBody()?.GetILAsByteArray(); if (methodBodyIL != null && methodBodyIL.Length == 6 && methodBodyIL[0] == 0x28 // call @@ -92,7 +92,7 @@ private static bool HasImplementation(CodeFixProvider fixer) } int metadataToken = BitConverter.ToInt32(methodBodyIL, 1); - MethodBase calledMethod = method.Module.ResolveMethod(metadataToken); + MethodBase calledMethod = method!.Module.ResolveMethod(metadataToken); if (calledMethod != null && calledMethod.DeclaringType.FullName == "System.Threading.Tasks.Task" && calledMethod.Name == "get_CompletedTask") diff --git a/src/Tools/ReleaseNotesUtil/Program.cs b/src/Tools/ReleaseNotesUtil/Program.cs index 0df05d5110..c00388db68 100644 --- a/src/Tools/ReleaseNotesUtil/Program.cs +++ b/src/Tools/ReleaseNotesUtil/Program.cs @@ -61,7 +61,7 @@ private static void GetRulesJson(string nugetInstalledPackagesPath, string versi string oldRulesJsonPath, string newRulesJsonPath, string outputPath, - string latestRulesJsonPath = null) + string? latestRulesJsonPath = null) { RuleFileContent oldContent = ReadRuleFileContent(oldRulesJsonPath); RuleFileContent newContent = ReadRuleFileContent(newRulesJsonPath); @@ -69,7 +69,7 @@ private static void GetRulesJson(string nugetInstalledPackagesPath, string versi // If we have the latest rules, we can backfill missing help link URLs. if (!string.IsNullOrWhiteSpace(latestRulesJsonPath)) { - RuleFileContent latestContent = ReadRuleFileContent(latestRulesJsonPath); + RuleFileContent latestContent = ReadRuleFileContent(latestRulesJsonPath!); Dictionary latestRulesById = latestContent.Rules.ToDictionary(r => r.Id); foreach (RuleInfo rule in oldContent.Rules.Concat(newContent.Rules)) { @@ -124,7 +124,7 @@ private static void GenerateAddRemovedRulesDiffMarkdown(StringBuilder sb, string IEnumerable sortedRules = rules.OrderBy(r => r, CategoryThenIdComparer.Instance); sb.AppendLine(heading); - string previousCategory = null; + string? previousCategory = null; foreach (RuleInfo rule in sortedRules) { if (rule.Category != previousCategory) @@ -147,7 +147,7 @@ private static void GenerateChangedRulesDiffMarkdown(StringBuilder sb, string he IEnumerable sortedRules = rules.OrderBy(r => r, CategoryThenIdComparer.Instance); sb.AppendLine(heading); - string previousCategory = null; + string? previousCategory = null; foreach (RuleInfo rule in sortedRules) { if (rule.Category != previousCategory) diff --git a/src/Tools/ReleaseNotesUtil/RuleInfo.cs b/src/Tools/ReleaseNotesUtil/RuleInfo.cs index 4702d87072..c0b5223a98 100644 --- a/src/Tools/ReleaseNotesUtil/RuleInfo.cs +++ b/src/Tools/ReleaseNotesUtil/RuleInfo.cs @@ -23,7 +23,9 @@ public RuleInfo(string id, string title, string category, bool isEnabledByDefaul HelpLink = helpLink; } +#pragma warning disable CS8618 // Non-nullable field is uninitialized. Consider declaring as nullable. public RuleInfo() +#pragma warning restore CS8618 // Non-nullable field is uninitialized. Consider declaring as nullable. { } From de1b692fc3a3e499c3c730e3f86aed23c027e6c7 Mon Sep 17 00:00:00 2001 From: Manish Vasani Date: Thu, 7 Nov 2019 16:02:42 -0800 Subject: [PATCH 17/28] Add nullable annotations for GenerateAnalyzerRulesets --- .../CodeFixerExtensions.cs | 6 +++--- .../GenerateAnalyzerRulesets/JsonWriter.cs | 8 ++++---- src/Tools/GenerateAnalyzerRulesets/Program.cs | 20 +++++++++---------- 3 files changed, 17 insertions(+), 17 deletions(-) diff --git a/src/Tools/GenerateAnalyzerRulesets/CodeFixerExtensions.cs b/src/Tools/GenerateAnalyzerRulesets/CodeFixerExtensions.cs index 4163e3c9e4..36c6e64e08 100644 --- a/src/Tools/GenerateAnalyzerRulesets/CodeFixerExtensions.cs +++ b/src/Tools/GenerateAnalyzerRulesets/CodeFixerExtensions.cs @@ -23,7 +23,7 @@ public static ImmutableArray GetFixers(this AnalyzerFileReferen return ImmutableArray.Empty; } - ImmutableArray.Builder builder = null; + ImmutableArray.Builder? builder = null; try { @@ -67,8 +67,8 @@ public static ImmutableArray GetFixers(this AnalyzerFileReferen private static bool HasImplementation(CodeFixProvider fixer) { MethodInfo method = fixer.GetType().GetTypeInfo().GetMethod("RegisterCodeFixesAsync"); - AsyncStateMachineAttribute stateMachineAttr = method?.GetCustomAttribute(); - MethodInfo moveNextMethod = stateMachineAttr?.StateMachineType.GetTypeInfo().GetDeclaredMethod("MoveNext"); + AsyncStateMachineAttribute? stateMachineAttr = method?.GetCustomAttribute(); + MethodInfo? moveNextMethod = stateMachineAttr?.StateMachineType.GetTypeInfo().GetDeclaredMethod("MoveNext"); if (moveNextMethod != null) { MethodBody body = moveNextMethod.GetMethodBody(); diff --git a/src/Tools/GenerateAnalyzerRulesets/JsonWriter.cs b/src/Tools/GenerateAnalyzerRulesets/JsonWriter.cs index c03b866c71..7937cdad9f 100644 --- a/src/Tools/GenerateAnalyzerRulesets/JsonWriter.cs +++ b/src/Tools/GenerateAnalyzerRulesets/JsonWriter.cs @@ -164,7 +164,7 @@ public void Dispose() // private static string EscapeString(string value) { - StringBuilder b = null; + StringBuilder? b = null; if (string.IsNullOrEmpty(value)) { @@ -196,15 +196,15 @@ private static string EscapeString(string value) switch (c) { case '\"': - b.Append("\\\""); + b!.Append("\\\""); break; case '\\': - b.Append("\\\\"); + b!.Append("\\\\"); break; default: if (ShouldAppendAsUnicode(c)) { - AppendCharAsUnicode(b, c); + AppendCharAsUnicode(b!, c); } else { diff --git a/src/Tools/GenerateAnalyzerRulesets/Program.cs b/src/Tools/GenerateAnalyzerRulesets/Program.cs index 3ecf619705..e3a1356640 100644 --- a/src/Tools/GenerateAnalyzerRulesets/Program.cs +++ b/src/Tools/GenerateAnalyzerRulesets/Program.cs @@ -49,7 +49,7 @@ public static int Main(string[] args) var allRulesById = new SortedList(); var fixableDiagnosticIds = new HashSet(); var categories = new HashSet(); - var rulesMetadata = new SortedList rules)>(); + var rulesMetadata = new SortedList rules)>(); foreach (string assembly in assemblyList) { var assemblyName = Path.GetFileNameWithoutExtension(assembly); @@ -63,7 +63,7 @@ public static int Main(string[] args) var analyzerFileReference = new AnalyzerFileReference(path, AnalyzerAssemblyLoader.Instance); var analyzers = analyzerFileReference.GetAnalyzersForAllLanguages(); - var assemblyRulesMetadata = (path, rules: new SortedList()); + var assemblyRulesMetadata = (path, rules: new SortedList()); foreach (var analyzer in analyzers) { @@ -156,8 +156,8 @@ public static int Main(string[] args) string title, string description, RulesetKind rulesetKind, - string categoryOpt = null, - string customTagOpt = null) + string? categoryOpt = null, + string? customTagOpt = null) { CreateRuleset(analyzerRulesetsDir, fileName + ".ruleset", title, description, rulesetKind, categoryOpt, customTagOpt, allRulesById, analyzerPackageName); CreateEditorconfig(analyzerEditorconfigsDir, fileName, title, description, rulesetKind, categoryOpt, customTagOpt, allRulesById); @@ -435,8 +435,8 @@ static string getLevel(DiagnosticSeverity severity) string rulesetTitle, string rulesetDescription, RulesetKind rulesetKind, - string categoryOpt, - string customTagOpt, + string? categoryOpt, + string? customTagOpt, SortedList sortedRulesById, string analyzerPackageName) { @@ -499,8 +499,8 @@ static string getSeverityString(DiagnosticSeverity? severityOpt) string editorconfigTitle, string editorconfigDescription, RulesetKind rulesetKind, - string categoryOpt, - string customTagOpt, + string? categoryOpt, + string? customTagOpt, SortedList sortedRulesById) { var text = GetRulesetOrEditorconfigText( @@ -582,8 +582,8 @@ static string getSeverityString(DiagnosticSeverity? severityOpt) Func getSeverityString, string commentStart, string commentEnd, - string categoryOpt, - string customTagOpt, + string? categoryOpt, + string? customTagOpt, SortedList sortedRulesById) { Debug.Assert(categoryOpt == null || customTagOpt == null); From 3591255f93c76bf86cc2a8372f3fd75c7aa68ea7 Mon Sep 17 00:00:00 2001 From: Manish Vasani Date: Thu, 7 Nov 2019 16:09:18 -0800 Subject: [PATCH 18/28] Fix a unit test failure from incorrect refactoring --- .../Core/Runtime/ImplementSerializationConstructors.Fixer.cs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/Microsoft.NetCore.Analyzers/Core/Runtime/ImplementSerializationConstructors.Fixer.cs b/src/Microsoft.NetCore.Analyzers/Core/Runtime/ImplementSerializationConstructors.Fixer.cs index 694f448637..d5eedea17e 100644 --- a/src/Microsoft.NetCore.Analyzers/Core/Runtime/ImplementSerializationConstructors.Fixer.cs +++ b/src/Microsoft.NetCore.Analyzers/Core/Runtime/ImplementSerializationConstructors.Fixer.cs @@ -28,8 +28,9 @@ public override async Task RegisterCodeFixesAsync(CodeFixContext context) SyntaxNode root = await context.Document.GetSyntaxRootAsync(context.CancellationToken).ConfigureAwait(false); SyntaxNode node = root.FindNode(context.Span); SemanticModel model = await context.Document.GetSemanticModelAsync(context.CancellationToken).ConfigureAwait(false); + ISymbol symbol = model.GetDeclaredSymbol(node, context.CancellationToken); - if (!(model.GetDeclaredSymbol(node, context.CancellationToken) is INamedTypeSymbol symbol)) + if (symbol == null) { return; } @@ -45,7 +46,7 @@ public override async Task RegisterCodeFixesAsync(CodeFixContext context) if (symbol.Kind == SymbolKind.NamedType) { context.RegisterCodeFix(new MyCodeAction(title, - async ct => await GenerateConstructor(context.Document, node, symbol, notImplementedExceptionType, ct).ConfigureAwait(false), + async ct => await GenerateConstructor(context.Document, node, (INamedTypeSymbol)symbol, notImplementedExceptionType, ct).ConfigureAwait(false), equivalenceKey: title), context.Diagnostics); } From 404f9cc401ec9d23ac44b51ea3d7921dd9b432ee Mon Sep 17 00:00:00 2001 From: Manish Vasani Date: Thu, 7 Nov 2019 16:12:53 -0800 Subject: [PATCH 19/28] Disable nullable in TestReferenceAssembly --- src/TestReferenceAssembly/OtherDllClass.cs | 3 +++ src/TestReferenceAssembly/OtherDllStaticMethods.cs | 3 +++ 2 files changed, 6 insertions(+) diff --git a/src/TestReferenceAssembly/OtherDllClass.cs b/src/TestReferenceAssembly/OtherDllClass.cs index 21491eabf8..4a3896044d 100644 --- a/src/TestReferenceAssembly/OtherDllClass.cs +++ b/src/TestReferenceAssembly/OtherDllClass.cs @@ -1,5 +1,8 @@ // Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. +// TODO(dotpaul): Enable nullable analysis. +#nullable disable + #pragma warning disable CA1801 // Remove unused parameter #pragma warning disable IDE0060 // Remove unused parameter diff --git a/src/TestReferenceAssembly/OtherDllStaticMethods.cs b/src/TestReferenceAssembly/OtherDllStaticMethods.cs index a40c332f2e..6bf972c399 100644 --- a/src/TestReferenceAssembly/OtherDllStaticMethods.cs +++ b/src/TestReferenceAssembly/OtherDllStaticMethods.cs @@ -1,5 +1,8 @@ // Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. +// TODO(dotpaul): Enable nullable analysis. +#nullable disable + #pragma warning disable CA1801 // Remove unused parameter #pragma warning disable IDE0060 // Remove unused parameter From c72761d0326ea2bbb1bf9afa1affc2c291641b85 Mon Sep 17 00:00:00 2001 From: Manish Vasani Date: Thu, 7 Nov 2019 16:31:14 -0800 Subject: [PATCH 20/28] Add nullable annotations for Microsoft.NetFramework.Analyzers --- .../CSharp/Helpers/SyntaxNodeHelper.cs | 42 +++++------ .../Core/DoNotUseInsecureDtdProcessing.cs | 3 + ...oNotUseInsecureDtdProcessingInApiDesign.cs | 3 + .../DoNotUseInsecureXSLTScriptExecution.cs | 3 + .../Core/Helpers/CompilationSecurityTypes.cs | 40 +++++------ .../Core/Helpers/SecurityDiagnosticHelpers.cs | 3 + .../Core/Helpers/SyntaxNodeHelper.cs | 69 ++++++++++--------- ...orgeryTokenAnalyzer.MvcAttributeSymbols.cs | 22 +++--- ...ersWithValidateAntiforgeryTokenAnalyzer.cs | 6 +- .../TypesShouldNotExtendCertainBaseTypes.cs | 4 +- 10 files changed, 104 insertions(+), 91 deletions(-) diff --git a/src/Microsoft.NetFramework.Analyzers/CSharp/Helpers/SyntaxNodeHelper.cs b/src/Microsoft.NetFramework.Analyzers/CSharp/Helpers/SyntaxNodeHelper.cs index 21e1701110..9cea774135 100644 --- a/src/Microsoft.NetFramework.Analyzers/CSharp/Helpers/SyntaxNodeHelper.cs +++ b/src/Microsoft.NetFramework.Analyzers/CSharp/Helpers/SyntaxNodeHelper.cs @@ -16,7 +16,7 @@ public sealed class CSharpSyntaxNodeHelper : SyntaxNodeHelper private CSharpSyntaxNodeHelper() { } - public override ITypeSymbol GetClassDeclarationTypeSymbol(SyntaxNode node, SemanticModel semanticModel) + public override ITypeSymbol? GetClassDeclarationTypeSymbol(SyntaxNode? node, SemanticModel semanticModel) { if (node == null) { @@ -32,7 +32,7 @@ public override ITypeSymbol GetClassDeclarationTypeSymbol(SyntaxNode node, Seman return null; } - public override SyntaxNode GetAssignmentLeftNode(SyntaxNode node) + public override SyntaxNode? GetAssignmentLeftNode(SyntaxNode? node) { if (node == null) { @@ -53,7 +53,7 @@ public override SyntaxNode GetAssignmentLeftNode(SyntaxNode node) return null; } - public override SyntaxNode GetAssignmentRightNode(SyntaxNode node) + public override SyntaxNode? GetAssignmentRightNode(SyntaxNode? node) { if (node == null) { @@ -78,7 +78,7 @@ public override SyntaxNode GetAssignmentRightNode(SyntaxNode node) return null; } - public override SyntaxNode GetMemberAccessExpressionNode(SyntaxNode node) + public override SyntaxNode? GetMemberAccessExpressionNode(SyntaxNode? node) { if (node == null) { @@ -94,7 +94,7 @@ public override SyntaxNode GetMemberAccessExpressionNode(SyntaxNode node) return null; } - public override SyntaxNode GetMemberAccessNameNode(SyntaxNode node) + public override SyntaxNode? GetMemberAccessNameNode(SyntaxNode? node) { if (node == null) { @@ -110,7 +110,7 @@ public override SyntaxNode GetMemberAccessNameNode(SyntaxNode node) return null; } - public override SyntaxNode GetInvocationExpressionNode(SyntaxNode node) + public override SyntaxNode? GetInvocationExpressionNode(SyntaxNode? node) { if (node == null) { @@ -126,7 +126,7 @@ public override SyntaxNode GetInvocationExpressionNode(SyntaxNode node) return ((InvocationExpressionSyntax)node).Expression; } - public override SyntaxNode GetCallTargetNode(SyntaxNode node) + public override SyntaxNode? GetCallTargetNode(SyntaxNode? node) { if (node != null) { @@ -145,7 +145,7 @@ public override SyntaxNode GetCallTargetNode(SyntaxNode node) return null; } - public override SyntaxNode GetDefaultValueForAnOptionalParameter(SyntaxNode declNode, int paramIndex) + public override SyntaxNode? GetDefaultValueForAnOptionalParameter(SyntaxNode? declNode, int paramIndex) { if (declNode is BaseMethodDeclarationSyntax methodDecl) { @@ -162,11 +162,11 @@ public override SyntaxNode GetDefaultValueForAnOptionalParameter(SyntaxNode decl return null; } - protected override IEnumerable GetCallArgumentExpressionNodes(SyntaxNode node, CallKinds callKind) + protected override IEnumerable GetCallArgumentExpressionNodes(SyntaxNode? node, CallKinds callKind) { if (node != null) { - ArgumentListSyntax argList = null; + ArgumentListSyntax? argList = null; SyntaxKind kind = node.Kind(); if ((kind == SyntaxKind.InvocationExpression) && ((callKind & CallKinds.Invocation) != 0)) { @@ -187,7 +187,7 @@ protected override IEnumerable GetCallArgumentExpressionNodes(Syntax return Enumerable.Empty(); } - public override IEnumerable GetObjectInitializerExpressionNodes(SyntaxNode node) + public override IEnumerable GetObjectInitializerExpressionNodes(SyntaxNode? node) { IEnumerable empty = Enumerable.Empty(); if (node == null) @@ -210,7 +210,7 @@ public override IEnumerable GetObjectInitializerExpressionNodes(Synt return objectCreationNode.Initializer.Expressions; } - public override bool IsMethodInvocationNode(SyntaxNode node) + public override bool IsMethodInvocationNode(SyntaxNode? node) { if (node == null) { @@ -220,9 +220,9 @@ public override bool IsMethodInvocationNode(SyntaxNode node) return kind == SyntaxKind.InvocationExpression || kind == SyntaxKind.ObjectCreationExpression; } - public override IMethodSymbol GetCalleeMethodSymbol(SyntaxNode node, SemanticModel semanticModel) + public override IMethodSymbol? GetCalleeMethodSymbol(SyntaxNode? node, SemanticModel semanticModel) { - ISymbol symbol = GetReferencedSymbol(node, semanticModel); + ISymbol? symbol = GetReferencedSymbol(node, semanticModel); if (symbol != null && symbol.Kind == SymbolKind.Method) { @@ -232,7 +232,7 @@ public override IMethodSymbol GetCalleeMethodSymbol(SyntaxNode node, SemanticMod return null; } - public override IMethodSymbol GetCallerMethodSymbol(SyntaxNode node, SemanticModel semanticModel) + public override IMethodSymbol? GetCallerMethodSymbol(SyntaxNode? node, SemanticModel semanticModel) { if (node == null) { @@ -254,7 +254,7 @@ public override IMethodSymbol GetCallerMethodSymbol(SyntaxNode node, SemanticMod return null; } - public override ITypeSymbol GetEnclosingTypeSymbol(SyntaxNode node, SemanticModel semanticModel) + public override ITypeSymbol? GetEnclosingTypeSymbol(SyntaxNode? node, SemanticModel semanticModel) { if (node == null) { @@ -271,7 +271,7 @@ public override ITypeSymbol GetEnclosingTypeSymbol(SyntaxNode node, SemanticMode return semanticModel.GetDeclaredSymbol(declaration); } - public override IEnumerable GetDescendantAssignmentExpressionNodes(SyntaxNode node) + public override IEnumerable GetDescendantAssignmentExpressionNodes(SyntaxNode? node) { IEnumerable empty = Enumerable.Empty(); if (node == null) @@ -282,7 +282,7 @@ public override IEnumerable GetDescendantAssignmentExpressionNodes(S return node.DescendantNodesAndSelf().OfType(); } - public override IEnumerable GetDescendantMemberAccessExpressionNodes(SyntaxNode node) + public override IEnumerable GetDescendantMemberAccessExpressionNodes(SyntaxNode? node) { IEnumerable empty = Enumerable.Empty(); if (node == null) @@ -293,18 +293,18 @@ public override IEnumerable GetDescendantMemberAccessExpressionNodes return node.DescendantNodesAndSelf().OfType(); } - public override bool IsObjectCreationExpressionUnderFieldDeclaration(SyntaxNode node) + public override bool IsObjectCreationExpressionUnderFieldDeclaration(SyntaxNode? node) { return node != null && node.Kind() == SyntaxKind.ObjectCreationExpression && node.AncestorsAndSelf().OfType().FirstOrDefault() != null; } - public override SyntaxNode GetVariableDeclaratorOfAFieldDeclarationNode(SyntaxNode node) + public override SyntaxNode? GetVariableDeclaratorOfAFieldDeclarationNode(SyntaxNode? node) { if (IsObjectCreationExpressionUnderFieldDeclaration(node)) { - return node.AncestorsAndSelf().OfType().FirstOrDefault(); + return node!.AncestorsAndSelf().OfType().FirstOrDefault(); } else { diff --git a/src/Microsoft.NetFramework.Analyzers/Core/DoNotUseInsecureDtdProcessing.cs b/src/Microsoft.NetFramework.Analyzers/Core/DoNotUseInsecureDtdProcessing.cs index f418bc6ab1..ec5deac313 100644 --- a/src/Microsoft.NetFramework.Analyzers/Core/DoNotUseInsecureDtdProcessing.cs +++ b/src/Microsoft.NetFramework.Analyzers/Core/DoNotUseInsecureDtdProcessing.cs @@ -1,5 +1,8 @@ // Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. +// TODO(dotpaul): Enable nullable analysis. +#nullable disable + using System; using System.Collections.Generic; using System.Collections.Immutable; diff --git a/src/Microsoft.NetFramework.Analyzers/Core/DoNotUseInsecureDtdProcessingInApiDesign.cs b/src/Microsoft.NetFramework.Analyzers/Core/DoNotUseInsecureDtdProcessingInApiDesign.cs index b5a6a76d49..5de5d1759f 100644 --- a/src/Microsoft.NetFramework.Analyzers/Core/DoNotUseInsecureDtdProcessingInApiDesign.cs +++ b/src/Microsoft.NetFramework.Analyzers/Core/DoNotUseInsecureDtdProcessingInApiDesign.cs @@ -1,5 +1,8 @@ // Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. +// TODO(dotpaul): Enable nullable analysis. +#nullable disable + using System; using System.Collections.Concurrent; using System.Collections.Generic; diff --git a/src/Microsoft.NetFramework.Analyzers/Core/DoNotUseInsecureXSLTScriptExecution.cs b/src/Microsoft.NetFramework.Analyzers/Core/DoNotUseInsecureXSLTScriptExecution.cs index 5fcc256262..8aaa67197f 100644 --- a/src/Microsoft.NetFramework.Analyzers/Core/DoNotUseInsecureXSLTScriptExecution.cs +++ b/src/Microsoft.NetFramework.Analyzers/Core/DoNotUseInsecureXSLTScriptExecution.cs @@ -1,5 +1,8 @@ // Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. +// TODO(dotpaul): Enable nullable analysis. +#nullable disable + using System.Collections.Generic; using System.Collections.Immutable; using System.Linq; diff --git a/src/Microsoft.NetFramework.Analyzers/Core/Helpers/CompilationSecurityTypes.cs b/src/Microsoft.NetFramework.Analyzers/Core/Helpers/CompilationSecurityTypes.cs index 5090bca26e..2ee2743348 100644 --- a/src/Microsoft.NetFramework.Analyzers/Core/Helpers/CompilationSecurityTypes.cs +++ b/src/Microsoft.NetFramework.Analyzers/Core/Helpers/CompilationSecurityTypes.cs @@ -8,26 +8,26 @@ namespace Microsoft.NetFramework.Analyzers.Helpers { public class CompilationSecurityTypes { - public INamedTypeSymbol HandleProcessCorruptedStateExceptionsAttribute { get; private set; } - public INamedTypeSymbol SystemObject { get; private set; } - public INamedTypeSymbol SystemException { get; private set; } - public INamedTypeSymbol SystemSystemException { get; private set; } - public INamedTypeSymbol XmlDocument { get; private set; } - public INamedTypeSymbol XPathDocument { get; private set; } - public INamedTypeSymbol XmlSchema { get; private set; } - public INamedTypeSymbol DataSet { get; private set; } - public INamedTypeSymbol XmlSerializer { get; private set; } - public INamedTypeSymbol DataTable { get; private set; } - public INamedTypeSymbol XmlNode { get; private set; } - public INamedTypeSymbol DataViewManager { get; private set; } - public INamedTypeSymbol XmlTextReader { get; private set; } - public INamedTypeSymbol XmlReader { get; private set; } - public INamedTypeSymbol DtdProcessing { get; private set; } - public INamedTypeSymbol XmlReaderSettings { get; private set; } - public INamedTypeSymbol XslCompiledTransform { get; private set; } - public INamedTypeSymbol XmlResolver { get; private set; } - public INamedTypeSymbol XmlSecureResolver { get; private set; } - public INamedTypeSymbol XsltSettings { get; private set; } + public INamedTypeSymbol? HandleProcessCorruptedStateExceptionsAttribute { get; private set; } + public INamedTypeSymbol? SystemObject { get; private set; } + public INamedTypeSymbol? SystemException { get; private set; } + public INamedTypeSymbol? SystemSystemException { get; private set; } + public INamedTypeSymbol? XmlDocument { get; private set; } + public INamedTypeSymbol? XPathDocument { get; private set; } + public INamedTypeSymbol? XmlSchema { get; private set; } + public INamedTypeSymbol? DataSet { get; private set; } + public INamedTypeSymbol? XmlSerializer { get; private set; } + public INamedTypeSymbol? DataTable { get; private set; } + public INamedTypeSymbol? XmlNode { get; private set; } + public INamedTypeSymbol? DataViewManager { get; private set; } + public INamedTypeSymbol? XmlTextReader { get; private set; } + public INamedTypeSymbol? XmlReader { get; private set; } + public INamedTypeSymbol? DtdProcessing { get; private set; } + public INamedTypeSymbol? XmlReaderSettings { get; private set; } + public INamedTypeSymbol? XslCompiledTransform { get; private set; } + public INamedTypeSymbol? XmlResolver { get; private set; } + public INamedTypeSymbol? XmlSecureResolver { get; private set; } + public INamedTypeSymbol? XsltSettings { get; private set; } public CompilationSecurityTypes(Compilation compilation) diff --git a/src/Microsoft.NetFramework.Analyzers/Core/Helpers/SecurityDiagnosticHelpers.cs b/src/Microsoft.NetFramework.Analyzers/Core/Helpers/SecurityDiagnosticHelpers.cs index 84d7fbbf17..5d3cbbb558 100644 --- a/src/Microsoft.NetFramework.Analyzers/Core/Helpers/SecurityDiagnosticHelpers.cs +++ b/src/Microsoft.NetFramework.Analyzers/Core/Helpers/SecurityDiagnosticHelpers.cs @@ -1,5 +1,8 @@ // Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. +// TODO(dotpaul): Enable nullable analysis. +#nullable disable + using System; using System.Threading; using Analyzer.Utilities; diff --git a/src/Microsoft.NetFramework.Analyzers/Core/Helpers/SyntaxNodeHelper.cs b/src/Microsoft.NetFramework.Analyzers/Core/Helpers/SyntaxNodeHelper.cs index c8740de343..9d7b0c4c7b 100644 --- a/src/Microsoft.NetFramework.Analyzers/Core/Helpers/SyntaxNodeHelper.cs +++ b/src/Microsoft.NetFramework.Analyzers/Core/Helpers/SyntaxNodeHelper.cs @@ -1,5 +1,6 @@ // Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. +using System; using System.Collections.Generic; using Microsoft.CodeAnalysis; @@ -16,37 +17,37 @@ protected enum CallKinds AnyCall = Invocation | ObjectCreation, }; - public abstract IMethodSymbol GetCallerMethodSymbol(SyntaxNode node, SemanticModel semanticModel); - public abstract ITypeSymbol GetEnclosingTypeSymbol(SyntaxNode node, SemanticModel semanticModel); - public abstract ITypeSymbol GetClassDeclarationTypeSymbol(SyntaxNode node, SemanticModel semanticModel); - public abstract SyntaxNode GetAssignmentLeftNode(SyntaxNode node); - public abstract SyntaxNode GetAssignmentRightNode(SyntaxNode node); - public abstract SyntaxNode GetMemberAccessExpressionNode(SyntaxNode node); - public abstract SyntaxNode GetMemberAccessNameNode(SyntaxNode node); - public abstract SyntaxNode GetCallTargetNode(SyntaxNode node); - public abstract SyntaxNode GetInvocationExpressionNode(SyntaxNode node); - public abstract SyntaxNode GetDefaultValueForAnOptionalParameter(SyntaxNode declNode, int paramIndex); - public abstract IEnumerable GetObjectInitializerExpressionNodes(SyntaxNode node); + public abstract IMethodSymbol? GetCallerMethodSymbol(SyntaxNode? node, SemanticModel semanticModel); + public abstract ITypeSymbol? GetEnclosingTypeSymbol(SyntaxNode? node, SemanticModel semanticModel); + public abstract ITypeSymbol? GetClassDeclarationTypeSymbol(SyntaxNode? node, SemanticModel semanticModel); + public abstract SyntaxNode? GetAssignmentLeftNode(SyntaxNode? node); + public abstract SyntaxNode? GetAssignmentRightNode(SyntaxNode? node); + public abstract SyntaxNode? GetMemberAccessExpressionNode(SyntaxNode? node); + public abstract SyntaxNode? GetMemberAccessNameNode(SyntaxNode? node); + public abstract SyntaxNode? GetCallTargetNode(SyntaxNode? node); + public abstract SyntaxNode? GetInvocationExpressionNode(SyntaxNode? node); + public abstract SyntaxNode? GetDefaultValueForAnOptionalParameter(SyntaxNode? declNode, int paramIndex); + public abstract IEnumerable GetObjectInitializerExpressionNodes(SyntaxNode? node); // This will return true iff the SyntaxNode is either InvocationExpression or ObjectCreationExpression (in C# or VB) public abstract bool IsMethodInvocationNode(SyntaxNode node); - protected abstract IEnumerable GetCallArgumentExpressionNodes(SyntaxNode node, CallKinds callKind); - public abstract IEnumerable GetDescendantAssignmentExpressionNodes(SyntaxNode node); - public abstract IEnumerable GetDescendantMemberAccessExpressionNodes(SyntaxNode node); + protected abstract IEnumerable GetCallArgumentExpressionNodes(SyntaxNode? node, CallKinds callKind); + public abstract IEnumerable GetDescendantAssignmentExpressionNodes(SyntaxNode? node); + public abstract IEnumerable GetDescendantMemberAccessExpressionNodes(SyntaxNode? node); // returns true if node is an ObjectCreationExpression and is under a FieldDeclaration node - public abstract bool IsObjectCreationExpressionUnderFieldDeclaration(SyntaxNode node); + public abstract bool IsObjectCreationExpressionUnderFieldDeclaration(SyntaxNode? node); // returns the ancestor VariableDeclarator node for an ObjectCreationExpression if // IsObjectCreationExpressionUnderFieldDeclaration(node) returns true, return null otherwise. - public abstract SyntaxNode GetVariableDeclaratorOfAFieldDeclarationNode(SyntaxNode objectCreationExpression); + public abstract SyntaxNode? GetVariableDeclaratorOfAFieldDeclarationNode(SyntaxNode? objectCreationExpression); - public ISymbol GetEnclosingConstructSymbol(SyntaxNode node, SemanticModel semanticModel) + public ISymbol? GetEnclosingConstructSymbol(SyntaxNode? node, SemanticModel semanticModel) { if (node == null) { return null; } - ISymbol symbol = GetCallerMethodSymbol(node, semanticModel); + ISymbol? symbol = GetCallerMethodSymbol(node, semanticModel); if (symbol == null) { @@ -71,9 +72,9 @@ public IEnumerable GetObjectCreationArgumentExpressionNodes(SyntaxNo return GetCallArgumentExpressionNodes(node, CallKinds.ObjectCreation); } - public abstract IMethodSymbol GetCalleeMethodSymbol(SyntaxNode node, SemanticModel semanticModel); + public abstract IMethodSymbol? GetCalleeMethodSymbol(SyntaxNode? node, SemanticModel semanticModel); - public static IEnumerable GetCandidateCalleeMethodSymbols(SyntaxNode node, SemanticModel semanticModel) + public static IEnumerable GetCandidateCalleeMethodSymbols(SyntaxNode? node, SemanticModel semanticModel) { foreach (ISymbol symbol in GetCandidateReferencedSymbols(node, semanticModel)) { @@ -84,9 +85,9 @@ public static IEnumerable GetCandidateCalleeMethodSymbols(SyntaxN } } - public IEnumerable GetCalleeMethodSymbols(SyntaxNode node, SemanticModel semanticModel) + public IEnumerable GetCalleeMethodSymbols(SyntaxNode? node, SemanticModel semanticModel) { - IMethodSymbol symbol = GetCalleeMethodSymbol(node, semanticModel); + IMethodSymbol? symbol = GetCalleeMethodSymbol(node, semanticModel); if (symbol != null) { return new List() { symbol }; @@ -95,9 +96,9 @@ public IEnumerable GetCalleeMethodSymbols(SyntaxNode node, Semant return GetCandidateCalleeMethodSymbols(node, semanticModel); } - public static IPropertySymbol GetCalleePropertySymbol(SyntaxNode node, SemanticModel semanticModel) + public static IPropertySymbol? GetCalleePropertySymbol(SyntaxNode? node, SemanticModel semanticModel) { - ISymbol symbol = GetReferencedSymbol(node, semanticModel); + ISymbol? symbol = GetReferencedSymbol(node, semanticModel); if (symbol != null && symbol.Kind == SymbolKind.Property) { return (IPropertySymbol)symbol; @@ -106,9 +107,9 @@ public static IPropertySymbol GetCalleePropertySymbol(SyntaxNode node, SemanticM return null; } - public static IFieldSymbol GetCalleeFieldSymbol(SyntaxNode node, SemanticModel semanticModel) + public static IFieldSymbol? GetCalleeFieldSymbol(SyntaxNode? node, SemanticModel semanticModel) { - ISymbol symbol = GetReferencedSymbol(node, semanticModel); + ISymbol? symbol = GetReferencedSymbol(node, semanticModel); if (symbol != null && symbol.Kind == SymbolKind.Field) { return (IFieldSymbol)symbol; @@ -117,12 +118,12 @@ public static IFieldSymbol GetCalleeFieldSymbol(SyntaxNode node, SemanticModel s return null; } - public static ISymbol GetSymbol(SyntaxNode node, SemanticModel semanticModel) + public static ISymbol? GetSymbol(SyntaxNode? node, SemanticModel semanticModel) { return GetDeclaredSymbol(node, semanticModel) ?? GetReferencedSymbol(node, semanticModel); } - public static ISymbol GetDeclaredSymbol(SyntaxNode node, SemanticModel semanticModel) + public static ISymbol? GetDeclaredSymbol(SyntaxNode? node, SemanticModel semanticModel) { if (node == null) { @@ -132,7 +133,7 @@ public static ISymbol GetDeclaredSymbol(SyntaxNode node, SemanticModel semanticM return semanticModel.GetDeclaredSymbol(node); } - public static ISymbol GetReferencedSymbol(SyntaxNode node, SemanticModel semanticModel) + public static ISymbol? GetReferencedSymbol(SyntaxNode? node, SemanticModel semanticModel) { if (node == null) { @@ -142,17 +143,17 @@ public static ISymbol GetReferencedSymbol(SyntaxNode node, SemanticModel semanti return semanticModel.GetSymbolInfo(node).Symbol; } - public static IEnumerable GetCandidateReferencedSymbols(SyntaxNode node, SemanticModel semanticModel) + public static IEnumerable GetCandidateReferencedSymbols(SyntaxNode? node, SemanticModel semanticModel) { if (node == null) { - return null; + return Array.Empty(); } return semanticModel.GetSymbolInfo(node).CandidateSymbols; } - public static bool NodeHasConstantValueNull(SyntaxNode node, SemanticModel model) + public static bool NodeHasConstantValueNull(SyntaxNode? node, SemanticModel? model) { if (node == null || model == null) { @@ -162,7 +163,7 @@ public static bool NodeHasConstantValueNull(SyntaxNode node, SemanticModel model return value.HasValue && value.Value == null; } - public static bool NodeHasConstantValueIntZero(SyntaxNode node, SemanticModel model) + public static bool NodeHasConstantValueIntZero(SyntaxNode? node, SemanticModel? model) { if (node == null || model == null) { @@ -174,7 +175,7 @@ public static bool NodeHasConstantValueIntZero(SyntaxNode node, SemanticModel mo (int)value.Value == 0; } - public static bool NodeHasConstantValueBoolFalse(SyntaxNode node, SemanticModel model) + public static bool NodeHasConstantValueBoolFalse(SyntaxNode? node, SemanticModel? model) { if (node == null || model == null) { diff --git a/src/Microsoft.NetFramework.Analyzers/Core/MarkVerbHandlersWithValidateAntiforgeryTokenAnalyzer.MvcAttributeSymbols.cs b/src/Microsoft.NetFramework.Analyzers/Core/MarkVerbHandlersWithValidateAntiforgeryTokenAnalyzer.MvcAttributeSymbols.cs index 0811f1631d..c9f8ed0618 100644 --- a/src/Microsoft.NetFramework.Analyzers/Core/MarkVerbHandlersWithValidateAntiforgeryTokenAnalyzer.MvcAttributeSymbols.cs +++ b/src/Microsoft.NetFramework.Analyzers/Core/MarkVerbHandlersWithValidateAntiforgeryTokenAnalyzer.MvcAttributeSymbols.cs @@ -15,16 +15,16 @@ public partial class MarkVerbHandlersWithValidateAntiforgeryTokenAnalyzer /// private sealed class MvcAttributeSymbols { - INamedTypeSymbol ValidateAntiforgeryTokenAttributeSymbol { get; set; } - INamedTypeSymbol HttpGetAttributeSymbol { get; set; } - INamedTypeSymbol HttpPostAttributeSymbol { get; set; } - INamedTypeSymbol HttpPutAttributeSymbol { get; set; } - INamedTypeSymbol HttpDeleteAttributeSymbol { get; set; } - INamedTypeSymbol HttpPatchAttributeSymbol { get; set; } - INamedTypeSymbol AcceptVerbsAttributeSymbol { get; set; } - INamedTypeSymbol NonActionAttributeSymbol { get; set; } - INamedTypeSymbol ChildActionOnlyAttributeSymbol { get; set; } - INamedTypeSymbol HttpVerbsSymbol { get; set; } + INamedTypeSymbol? ValidateAntiforgeryTokenAttributeSymbol { get; set; } + INamedTypeSymbol? HttpGetAttributeSymbol { get; set; } + INamedTypeSymbol? HttpPostAttributeSymbol { get; set; } + INamedTypeSymbol? HttpPutAttributeSymbol { get; set; } + INamedTypeSymbol? HttpDeleteAttributeSymbol { get; set; } + INamedTypeSymbol? HttpPatchAttributeSymbol { get; set; } + INamedTypeSymbol? AcceptVerbsAttributeSymbol { get; set; } + INamedTypeSymbol? NonActionAttributeSymbol { get; set; } + INamedTypeSymbol? ChildActionOnlyAttributeSymbol { get; set; } + INamedTypeSymbol? HttpVerbsSymbol { get; set; } public MvcAttributeSymbols(Compilation compilation) { @@ -136,7 +136,7 @@ public MvcAttributeSymbols(Compilation compilation) /// The .NET attribute to check. /// The type of .NET attribute to compare. /// True if .NET attribute's type matches the specified type, false otherwise. - private static bool IsAttributeClass(AttributeData attributeData, INamedTypeSymbol symbol) + private static bool IsAttributeClass(AttributeData attributeData, INamedTypeSymbol? symbol) { return symbol != null && Equals(attributeData.AttributeClass, symbol); } diff --git a/src/Microsoft.NetFramework.Analyzers/Core/MarkVerbHandlersWithValidateAntiforgeryTokenAnalyzer.cs b/src/Microsoft.NetFramework.Analyzers/Core/MarkVerbHandlersWithValidateAntiforgeryTokenAnalyzer.cs index 29ea2da558..9372b417db 100644 --- a/src/Microsoft.NetFramework.Analyzers/Core/MarkVerbHandlersWithValidateAntiforgeryTokenAnalyzer.cs +++ b/src/Microsoft.NetFramework.Analyzers/Core/MarkVerbHandlersWithValidateAntiforgeryTokenAnalyzer.cs @@ -100,9 +100,9 @@ public override void Initialize(AnalysisContext analysisContext) (CompilationStartAnalysisContext compilationStartContext) => { WellKnownTypeProvider wellKnownTypeProvider = WellKnownTypeProvider.GetOrCreate(compilationStartContext.Compilation); - INamedTypeSymbol mvcControllerSymbol = wellKnownTypeProvider.GetOrCreateTypeByMetadataName(WellKnownTypeNames.SystemWebMvcController); - INamedTypeSymbol mvcControllerBaseSymbol = wellKnownTypeProvider.GetOrCreateTypeByMetadataName(WellKnownTypeNames.SystemWebMvcControllerBase); - INamedTypeSymbol actionResultSymbol = wellKnownTypeProvider.GetOrCreateTypeByMetadataName(WellKnownTypeNames.SystemWebMvcActionResult); + INamedTypeSymbol? mvcControllerSymbol = wellKnownTypeProvider.GetOrCreateTypeByMetadataName(WellKnownTypeNames.SystemWebMvcController); + INamedTypeSymbol? mvcControllerBaseSymbol = wellKnownTypeProvider.GetOrCreateTypeByMetadataName(WellKnownTypeNames.SystemWebMvcControllerBase); + INamedTypeSymbol? actionResultSymbol = wellKnownTypeProvider.GetOrCreateTypeByMetadataName(WellKnownTypeNames.SystemWebMvcActionResult); if ((mvcControllerSymbol == null && mvcControllerBaseSymbol == null) || actionResultSymbol == null) { diff --git a/src/Microsoft.NetFramework.Analyzers/Core/TypesShouldNotExtendCertainBaseTypes.cs b/src/Microsoft.NetFramework.Analyzers/Core/TypesShouldNotExtendCertainBaseTypes.cs index cae292221e..0fd63d0d4f 100644 --- a/src/Microsoft.NetFramework.Analyzers/Core/TypesShouldNotExtendCertainBaseTypes.cs +++ b/src/Microsoft.NetFramework.Analyzers/Core/TypesShouldNotExtendCertainBaseTypes.cs @@ -58,14 +58,14 @@ private static void AnalyzeCompilationStart(CompilationStartAnalysisContext cont { ImmutableHashSet badBaseTypes = s_badBaseTypesToMessage.Keys .Select(bt => context.Compilation.GetOrCreateTypeByMetadataName(bt)) - .Where(bt => bt != null) + .WhereNotNull() .ToImmutableHashSet(); if (badBaseTypes.Count > 0) { context.RegisterSymbolAction((saContext) => { - var namedTypeSymbol = saContext.Symbol as INamedTypeSymbol; + var namedTypeSymbol = (INamedTypeSymbol)saContext.Symbol; if (namedTypeSymbol.BaseType != null && badBaseTypes.Contains(namedTypeSymbol.BaseType) && From 64aa452474209b0f35369edeb2e907d2567509c9 Mon Sep 17 00:00:00 2001 From: Manish Vasani Date: Thu, 7 Nov 2019 16:37:42 -0800 Subject: [PATCH 21/28] Add some more missing nullable annotations found after building the entire solution --- .../Core/ApiDesignGuidelines/EnumWithFlagsAttribute.Fixer.cs | 1 - .../ImplementStandardExceptionConstructors.cs | 2 +- .../ApiDesignGuidelines/UseGenericEventHandlerInstances.cs | 1 - .../Core/Maintainability/UseNameofInPlaceOfString.Fixer.cs | 1 - .../QualityGuidelines/BasicRemoveEmptyFinalizersAnalyzer.vb | 3 ++- .../CSharpUsePropertyInsteadOfCountMethodWhenAvailable.cs | 2 +- .../Runtime/CSharpMarkAllNonSerializableFields.Fixer.cs | 2 +- .../CSharp/Runtime/CSharpUseOrdinalStringComparison.cs | 2 +- .../UsePropertyInsteadOfCountMethodWhenAvailable.cs | 2 +- .../Core/Runtime/MarkAllNonSerializableFields.Fixer.cs | 4 ++-- .../CSharp/CSharpSpecializedEnumerableCreationAnalyzer.cs | 1 - src/Tools/ReleaseNotesUtil/RuleFileContent.cs | 2 +- .../Compiler/CodeMetrics/ComputationalComplexityMetrics.cs | 1 - src/Utilities/Compiler/Extensions/CompilationExtensions.cs | 5 +++-- .../CopyAnalysis/CopyAnalysis.CoreCopyAnalysisDataDomain.cs | 1 - .../PropertySetAnalysis.PropertySetAbstractValueDomain.cs | 1 - .../Framework/DataFlow/AbstractIndex.OperationBasedIndex.cs | 1 - 17 files changed, 13 insertions(+), 19 deletions(-) diff --git a/src/Microsoft.CodeQuality.Analyzers/Core/ApiDesignGuidelines/EnumWithFlagsAttribute.Fixer.cs b/src/Microsoft.CodeQuality.Analyzers/Core/ApiDesignGuidelines/EnumWithFlagsAttribute.Fixer.cs index b5641fb619..d841fac6e1 100644 --- a/src/Microsoft.CodeQuality.Analyzers/Core/ApiDesignGuidelines/EnumWithFlagsAttribute.Fixer.cs +++ b/src/Microsoft.CodeQuality.Analyzers/Core/ApiDesignGuidelines/EnumWithFlagsAttribute.Fixer.cs @@ -3,7 +3,6 @@ using System; using System.Collections.Immutable; using System.Composition; -using System.Diagnostics; using System.Linq; using System.Threading; using System.Threading.Tasks; diff --git a/src/Microsoft.CodeQuality.Analyzers/Core/ApiDesignGuidelines/ImplementStandardExceptionConstructors.cs b/src/Microsoft.CodeQuality.Analyzers/Core/ApiDesignGuidelines/ImplementStandardExceptionConstructors.cs index fc5ac15fd8..e59eded262 100644 --- a/src/Microsoft.CodeQuality.Analyzers/Core/ApiDesignGuidelines/ImplementStandardExceptionConstructors.cs +++ b/src/Microsoft.CodeQuality.Analyzers/Core/ApiDesignGuidelines/ImplementStandardExceptionConstructors.cs @@ -130,7 +130,7 @@ private void AnalyzeCompilationSymbol(CompilationStartAnalysisContext context) private static void ReportDiagnostic(SymbolAnalysisContext context, INamedTypeSymbol namedTypeSymbol, MissingCtorSignature missingCtorSignature, string constructorSignature) { //store MissingCtorSignature enum type into dictionary, to set diagnostic property. This is needed because Diagnostic is immutable - ImmutableDictionary.Builder builder = ImmutableDictionary.CreateBuilder(); + ImmutableDictionary.Builder builder = ImmutableDictionary.CreateBuilder(); builder.Add("Signature", missingCtorSignature.ToString()); //create dignostic and store signature into diagnostic property for fixer diff --git a/src/Microsoft.CodeQuality.Analyzers/Core/ApiDesignGuidelines/UseGenericEventHandlerInstances.cs b/src/Microsoft.CodeQuality.Analyzers/Core/ApiDesignGuidelines/UseGenericEventHandlerInstances.cs index b653e4795f..8b6093b446 100644 --- a/src/Microsoft.CodeQuality.Analyzers/Core/ApiDesignGuidelines/UseGenericEventHandlerInstances.cs +++ b/src/Microsoft.CodeQuality.Analyzers/Core/ApiDesignGuidelines/UseGenericEventHandlerInstances.cs @@ -2,7 +2,6 @@ using System; using System.Collections.Immutable; -using System.Diagnostics; using System.Linq; using Analyzer.Utilities; using Analyzer.Utilities.Extensions; diff --git a/src/Microsoft.CodeQuality.Analyzers/Core/Maintainability/UseNameofInPlaceOfString.Fixer.cs b/src/Microsoft.CodeQuality.Analyzers/Core/Maintainability/UseNameofInPlaceOfString.Fixer.cs index f147f5a72d..40f5281d68 100644 --- a/src/Microsoft.CodeQuality.Analyzers/Core/Maintainability/UseNameofInPlaceOfString.Fixer.cs +++ b/src/Microsoft.CodeQuality.Analyzers/Core/Maintainability/UseNameofInPlaceOfString.Fixer.cs @@ -1,7 +1,6 @@ // Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System.Collections.Immutable; -using System.Diagnostics; using System.Threading; using System.Threading.Tasks; using Microsoft.CodeAnalysis; diff --git a/src/Microsoft.CodeQuality.Analyzers/VisualBasic/QualityGuidelines/BasicRemoveEmptyFinalizersAnalyzer.vb b/src/Microsoft.CodeQuality.Analyzers/VisualBasic/QualityGuidelines/BasicRemoveEmptyFinalizersAnalyzer.vb index a7ff4b3934..1c46ca2c33 100644 --- a/src/Microsoft.CodeQuality.Analyzers/VisualBasic/QualityGuidelines/BasicRemoveEmptyFinalizersAnalyzer.vb +++ b/src/Microsoft.CodeQuality.Analyzers/VisualBasic/QualityGuidelines/BasicRemoveEmptyFinalizersAnalyzer.vb @@ -1,4 +1,5 @@ -Imports Analyzer.Utilities +' Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + Imports Analyzer.Utilities.Extensions Imports Microsoft.CodeAnalysis Imports Microsoft.CodeAnalysis.Diagnostics diff --git a/src/Microsoft.NetCore.Analyzers/CSharp/Performance/CSharpUsePropertyInsteadOfCountMethodWhenAvailable.cs b/src/Microsoft.NetCore.Analyzers/CSharp/Performance/CSharpUsePropertyInsteadOfCountMethodWhenAvailable.cs index f33002576d..fd3d11876a 100644 --- a/src/Microsoft.NetCore.Analyzers/CSharp/Performance/CSharpUsePropertyInsteadOfCountMethodWhenAvailable.cs +++ b/src/Microsoft.NetCore.Analyzers/CSharp/Performance/CSharpUsePropertyInsteadOfCountMethodWhenAvailable.cs @@ -42,7 +42,7 @@ internal CSharpOperationActionsHandler(OperationActionsContext context) { } - protected override ITypeSymbol GetEnumerableCountInvocationTargetType(IInvocationOperation invocationOperation) + protected override ITypeSymbol? GetEnumerableCountInvocationTargetType(IInvocationOperation invocationOperation) { var method = invocationOperation.TargetMethod; diff --git a/src/Microsoft.NetCore.Analyzers/CSharp/Runtime/CSharpMarkAllNonSerializableFields.Fixer.cs b/src/Microsoft.NetCore.Analyzers/CSharp/Runtime/CSharpMarkAllNonSerializableFields.Fixer.cs index 117d2a3fb7..13e0d8d767 100644 --- a/src/Microsoft.NetCore.Analyzers/CSharp/Runtime/CSharpMarkAllNonSerializableFields.Fixer.cs +++ b/src/Microsoft.NetCore.Analyzers/CSharp/Runtime/CSharpMarkAllNonSerializableFields.Fixer.cs @@ -11,7 +11,7 @@ namespace Microsoft.NetCore.CSharp.Analyzers.Runtime [ExportCodeFixProvider(LanguageNames.CSharp, Name = "CA2237 CodeFix provider"), Shared] public class CSharpMarkAllNonSerializableFieldsFixer : MarkAllNonSerializableFieldsFixer { - protected override SyntaxNode GetFieldDeclarationNode(SyntaxNode node) + protected override SyntaxNode? GetFieldDeclarationNode(SyntaxNode node) { SyntaxNode fieldNode = node; while (fieldNode != null && fieldNode.Kind() != SyntaxKind.FieldDeclaration) diff --git a/src/Microsoft.NetCore.Analyzers/CSharp/Runtime/CSharpUseOrdinalStringComparison.cs b/src/Microsoft.NetCore.Analyzers/CSharp/Runtime/CSharpUseOrdinalStringComparison.cs index 82d0fadb6c..d2d1a8630e 100644 --- a/src/Microsoft.NetCore.Analyzers/CSharp/Runtime/CSharpUseOrdinalStringComparison.cs +++ b/src/Microsoft.NetCore.Analyzers/CSharp/Runtime/CSharpUseOrdinalStringComparison.cs @@ -16,7 +16,7 @@ protected override Location GetMethodNameLocation(SyntaxNode invocationNode) { Debug.Assert(invocationNode.IsKind(SyntaxKind.InvocationExpression)); - var invocation = invocationNode as InvocationExpressionSyntax; + var invocation = (InvocationExpressionSyntax)invocationNode; if (invocation.Expression.IsKind(SyntaxKind.SimpleMemberAccessExpression)) { return ((MemberAccessExpressionSyntax)invocation.Expression).Name.GetLocation(); diff --git a/src/Microsoft.NetCore.Analyzers/Core/Performance/UsePropertyInsteadOfCountMethodWhenAvailable.cs b/src/Microsoft.NetCore.Analyzers/Core/Performance/UsePropertyInsteadOfCountMethodWhenAvailable.cs index 0c424fda9a..cacae19be1 100644 --- a/src/Microsoft.NetCore.Analyzers/Core/Performance/UsePropertyInsteadOfCountMethodWhenAvailable.cs +++ b/src/Microsoft.NetCore.Analyzers/Core/Performance/UsePropertyInsteadOfCountMethodWhenAvailable.cs @@ -291,7 +291,7 @@ internal void AnalyzeInvocationOperation(OperationAnalysisContext context) /// /// The invocation operation. /// The of the receiver of the extension method. - protected abstract ITypeSymbol GetEnumerableCountInvocationTargetType(IInvocationOperation invocationOperation); + protected abstract ITypeSymbol? GetEnumerableCountInvocationTargetType(IInvocationOperation invocationOperation); /// /// Gets the replacement property. diff --git a/src/Microsoft.NetCore.Analyzers/Core/Runtime/MarkAllNonSerializableFields.Fixer.cs b/src/Microsoft.NetCore.Analyzers/Core/Runtime/MarkAllNonSerializableFields.Fixer.cs index 0f72d123e2..3a008b5bec 100644 --- a/src/Microsoft.NetCore.Analyzers/Core/Runtime/MarkAllNonSerializableFields.Fixer.cs +++ b/src/Microsoft.NetCore.Analyzers/Core/Runtime/MarkAllNonSerializableFields.Fixer.cs @@ -20,13 +20,13 @@ public abstract class MarkAllNonSerializableFieldsFixer : CodeFixProvider { public override ImmutableArray FixableDiagnosticIds => ImmutableArray.Create(SerializationRulesDiagnosticAnalyzer.RuleCA2235Id); - protected abstract SyntaxNode GetFieldDeclarationNode(SyntaxNode node); + protected abstract SyntaxNode? GetFieldDeclarationNode(SyntaxNode node); public override async Task RegisterCodeFixesAsync(CodeFixContext context) { SyntaxNode root = await context.Document.GetSyntaxRootAsync(context.CancellationToken).ConfigureAwait(false); SyntaxNode node = root.FindNode(context.Span); - SyntaxNode fieldNode = GetFieldDeclarationNode(node); + SyntaxNode? fieldNode = GetFieldDeclarationNode(node); if (fieldNode == null) { return; diff --git a/src/Roslyn.Diagnostics.Analyzers/CSharp/CSharpSpecializedEnumerableCreationAnalyzer.cs b/src/Roslyn.Diagnostics.Analyzers/CSharp/CSharpSpecializedEnumerableCreationAnalyzer.cs index a0d546262a..e6b8c4464c 100644 --- a/src/Roslyn.Diagnostics.Analyzers/CSharp/CSharpSpecializedEnumerableCreationAnalyzer.cs +++ b/src/Roslyn.Diagnostics.Analyzers/CSharp/CSharpSpecializedEnumerableCreationAnalyzer.cs @@ -1,7 +1,6 @@ // Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System; -using System.Diagnostics; using System.Linq; using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.CSharp; diff --git a/src/Tools/ReleaseNotesUtil/RuleFileContent.cs b/src/Tools/ReleaseNotesUtil/RuleFileContent.cs index 5715ff6d70..d804c01767 100644 --- a/src/Tools/ReleaseNotesUtil/RuleFileContent.cs +++ b/src/Tools/ReleaseNotesUtil/RuleFileContent.cs @@ -7,6 +7,6 @@ namespace ReleaseNotesUtil internal class RuleFileContent { [DataMember] - public List Rules { get; set; } + public List? Rules { get; set; } } } diff --git a/src/Utilities/Compiler/CodeMetrics/ComputationalComplexityMetrics.cs b/src/Utilities/Compiler/CodeMetrics/ComputationalComplexityMetrics.cs index 949114aa90..72670a9a01 100644 --- a/src/Utilities/Compiler/CodeMetrics/ComputationalComplexityMetrics.cs +++ b/src/Utilities/Compiler/CodeMetrics/ComputationalComplexityMetrics.cs @@ -4,7 +4,6 @@ using System; using System.Collections.Immutable; -using System.Diagnostics; using System.Linq; using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.Operations; diff --git a/src/Utilities/Compiler/Extensions/CompilationExtensions.cs b/src/Utilities/Compiler/Extensions/CompilationExtensions.cs index f48756e146..35af56f541 100644 --- a/src/Utilities/Compiler/Extensions/CompilationExtensions.cs +++ b/src/Utilities/Compiler/Extensions/CompilationExtensions.cs @@ -1,5 +1,6 @@ -using System.Diagnostics.CodeAnalysis; -using System.Linq; +// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System.Diagnostics.CodeAnalysis; using Microsoft.CodeAnalysis; namespace Analyzer.Utilities.Extensions diff --git a/src/Utilities/FlowAnalysis/FlowAnalysis/Analysis/CopyAnalysis/CopyAnalysis.CoreCopyAnalysisDataDomain.cs b/src/Utilities/FlowAnalysis/FlowAnalysis/Analysis/CopyAnalysis/CopyAnalysis.CoreCopyAnalysisDataDomain.cs index ba3d1451ba..d2c8e9f089 100644 --- a/src/Utilities/FlowAnalysis/FlowAnalysis/Analysis/CopyAnalysis/CopyAnalysis.CoreCopyAnalysisDataDomain.cs +++ b/src/Utilities/FlowAnalysis/FlowAnalysis/Analysis/CopyAnalysis/CopyAnalysis.CoreCopyAnalysisDataDomain.cs @@ -1,7 +1,6 @@ // Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System; -using System.Diagnostics; namespace Microsoft.CodeAnalysis.FlowAnalysis.DataFlow.CopyAnalysis { diff --git a/src/Utilities/FlowAnalysis/FlowAnalysis/Analysis/PropertySetAnalysis/PropertySetAnalysis.PropertySetAbstractValueDomain.cs b/src/Utilities/FlowAnalysis/FlowAnalysis/Analysis/PropertySetAnalysis/PropertySetAnalysis.PropertySetAbstractValueDomain.cs index a531059933..59d43eeb00 100644 --- a/src/Utilities/FlowAnalysis/FlowAnalysis/Analysis/PropertySetAnalysis/PropertySetAnalysis.PropertySetAbstractValueDomain.cs +++ b/src/Utilities/FlowAnalysis/FlowAnalysis/Analysis/PropertySetAnalysis/PropertySetAnalysis.PropertySetAbstractValueDomain.cs @@ -1,7 +1,6 @@ // Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System; -using System.Diagnostics; using Analyzer.Utilities.PooledObjects; using Microsoft.CodeAnalysis.FlowAnalysis.DataFlow; diff --git a/src/Utilities/FlowAnalysis/FlowAnalysis/Framework/DataFlow/AbstractIndex.OperationBasedIndex.cs b/src/Utilities/FlowAnalysis/FlowAnalysis/Framework/DataFlow/AbstractIndex.OperationBasedIndex.cs index 75ce53d12c..472a9be1ef 100644 --- a/src/Utilities/FlowAnalysis/FlowAnalysis/Framework/DataFlow/AbstractIndex.OperationBasedIndex.cs +++ b/src/Utilities/FlowAnalysis/FlowAnalysis/Framework/DataFlow/AbstractIndex.OperationBasedIndex.cs @@ -1,7 +1,6 @@ // Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System; -using System.Diagnostics; namespace Microsoft.CodeAnalysis.FlowAnalysis.DataFlow { From 614dde066808f374a731ea7d339bbd8bd795a788 Mon Sep 17 00:00:00 2001 From: Manish Vasani Date: Fri, 8 Nov 2019 06:13:34 -0800 Subject: [PATCH 22/28] Address feedback for symbol extensions --- .../Compiler/Extensions/ISymbolExtensions.cs | 63 ++++++++++--------- 1 file changed, 32 insertions(+), 31 deletions(-) diff --git a/src/Utilities/Compiler/Extensions/ISymbolExtensions.cs b/src/Utilities/Compiler/Extensions/ISymbolExtensions.cs index 3acb5d4066..05ebd7619d 100644 --- a/src/Utilities/Compiler/Extensions/ISymbolExtensions.cs +++ b/src/Utilities/Compiler/Extensions/ISymbolExtensions.cs @@ -4,6 +4,7 @@ using System.Collections.Generic; using System.Collections.Immutable; using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; using System.Linq; using System.Threading; using Microsoft.CodeAnalysis; @@ -13,12 +14,12 @@ namespace Analyzer.Utilities.Extensions { internal static class ISymbolExtensions { - public static bool IsType(this ISymbol symbol) + public static bool IsType([NotNullWhen(returnValue: true)] this ISymbol? symbol) { return symbol is ITypeSymbol typeSymbol && typeSymbol.IsType; } - public static bool IsAccessorMethod(this ISymbol symbol) + public static bool IsAccessorMethod([NotNullWhen(returnValue: true)] this ISymbol? symbol) { return symbol is IMethodSymbol accessorSymbol && (accessorSymbol.IsPropertyAccessor() || accessorSymbol.IsEventAccessor()); @@ -63,7 +64,7 @@ public static IEnumerable GetAccessors(this ISymbol symbol) } } - public static bool IsDefaultConstructor(this ISymbol symbol) + public static bool IsDefaultConstructor([NotNullWhen(returnValue: true)] this ISymbol? symbol) { return symbol.IsConstructor() && symbol.GetParameters().Length == 0; } @@ -83,40 +84,40 @@ public static bool IsPrivate(this ISymbol symbol) return symbol.DeclaredAccessibility == Accessibility.Private; } - public static bool IsErrorType(this ISymbol? symbol) + public static bool IsErrorType([NotNullWhen(returnValue: true)] this ISymbol? symbol) { return - symbol is ITypeSymbol && - ((ITypeSymbol)symbol).TypeKind == TypeKind.Error; + symbol is ITypeSymbol typeSymbol && + typeSymbol.TypeKind == TypeKind.Error; } - public static bool IsConstructor(this ISymbol? symbol) + public static bool IsConstructor([NotNullWhen(returnValue: true)] this ISymbol? symbol) { return (symbol as IMethodSymbol)?.MethodKind == MethodKind.Constructor; } - public static bool IsDestructor(this ISymbol? symbol) + public static bool IsDestructor([NotNullWhen(returnValue: true)] this ISymbol? symbol) { return (symbol as IMethodSymbol)?.IsFinalizer() ?? false; } - public static bool IsIndexer(this ISymbol? symbol) + public static bool IsIndexer([NotNullWhen(returnValue: true)] this ISymbol? symbol) { return (symbol as IPropertySymbol)?.IsIndexer == true; } - public static bool IsPropertyWithBackingField(this ISymbol? symbol) + public static bool IsPropertyWithBackingField([NotNullWhen(returnValue: true)] this ISymbol? symbol) { return symbol is IPropertySymbol propertySymbol && propertySymbol.ContainingType.GetMembers().OfType().Any(f => f.IsImplicitlyDeclared && Equals(f.AssociatedSymbol, symbol)); } - public static bool IsUserDefinedOperator(this ISymbol? symbol) + public static bool IsUserDefinedOperator([NotNullWhen(returnValue: true)] this ISymbol? symbol) { return (symbol as IMethodSymbol)?.MethodKind == MethodKind.UserDefinedOperator; } - public static bool IsConversionOperator(this ISymbol? symbol) + public static bool IsConversionOperator([NotNullWhen(returnValue: true)] this ISymbol? symbol) { return (symbol as IMethodSymbol)?.MethodKind == MethodKind.Conversion; } @@ -261,42 +262,42 @@ public static SymbolVisibility GetResultantVisibility(this ISymbol symbol) return visibility; } - public static bool MatchMemberDerivedByName(this ISymbol member, INamedTypeSymbol type, string name) + public static bool MatchMemberDerivedByName([NotNullWhen(returnValue: true)] this ISymbol? member, INamedTypeSymbol type, string name) { return member != null && member.MetadataName == name && member.ContainingType.DerivesFrom(type); } - public static bool MatchMethodDerivedByName(this IMethodSymbol method, INamedTypeSymbol type, string name) + public static bool MatchMethodDerivedByName([NotNullWhen(returnValue: true)] this IMethodSymbol? method, INamedTypeSymbol type, string name) { return method != null && method.MatchMemberDerivedByName(type, name); } - public static bool MatchMethodByName(this ISymbol member, INamedTypeSymbol type, string name) + public static bool MatchMethodByName([NotNullWhen(returnValue: true)] this ISymbol? member, INamedTypeSymbol type, string name) { return member != null && member.Kind == SymbolKind.Method && member.MatchMemberByName(type, name); } - public static bool MatchPropertyDerivedByName(this ISymbol member, INamedTypeSymbol type, string name) + public static bool MatchPropertyDerivedByName([NotNullWhen(returnValue: true)] this ISymbol? member, INamedTypeSymbol type, string name) { return member != null && member.Kind == SymbolKind.Property && member.MatchMemberDerivedByName(type, name); } - public static bool MatchFieldDerivedByName(this ISymbol member, INamedTypeSymbol type, string name) + public static bool MatchFieldDerivedByName([NotNullWhen(returnValue: true)] this ISymbol? member, INamedTypeSymbol type, string name) { return member != null && member.Kind == SymbolKind.Field && member.MatchMemberDerivedByName(type, name); } - public static bool MatchMemberByName(this ISymbol member, INamedTypeSymbol type, string name) + public static bool MatchMemberByName([NotNullWhen(returnValue: true)] this ISymbol? member, INamedTypeSymbol type, string name) { return member != null && Equals(member.ContainingType, type) && member.MetadataName == name; } - public static bool MatchPropertyByName(this ISymbol member, INamedTypeSymbol type, string name) + public static bool MatchPropertyByName([NotNullWhen(returnValue: true)] this ISymbol? member, INamedTypeSymbol type, string name) { return member != null && member.Kind == SymbolKind.Property && member.MatchMemberByName(type, name); } - public static bool MatchFieldByName(this ISymbol member, INamedTypeSymbol type, string name) + public static bool MatchFieldByName([NotNullWhen(returnValue: true)] this ISymbol? member, INamedTypeSymbol type, string name) { return member != null && member.Kind == SymbolKind.Field && member.MatchMemberByName(type, name); } @@ -503,7 +504,7 @@ public static bool IsImplementationOfAnyImplicitInterfaceMember(this ISymbol sym /// Checks if a given symbol implements an interface member implicitly /// public static bool IsImplementationOfAnyImplicitInterfaceMember(this ISymbol symbol) - where TSymbol : ISymbol + where TSymbol : ISymbol { if (symbol.ContainingType != null) { @@ -522,7 +523,7 @@ public static bool IsImplementationOfAnyImplicitInterfaceMember(this IS return false; } - public static bool IsImplementationOfInterfaceMember(this ISymbol symbol, ISymbol interfaceMember) + public static bool IsImplementationOfInterfaceMember(this ISymbol symbol, [NotNullWhen(returnValue: true)] ISymbol? interfaceMember) { return interfaceMember != null && symbol.Equals(symbol.ContainingType.FindImplementationForInterfaceMember(interfaceMember)); @@ -531,7 +532,7 @@ public static bool IsImplementationOfInterfaceMember(this ISymbol symbol, ISymbo /// /// Checks if a given symbol implements an interface member or overrides an implementation of an interface member. /// - public static bool IsOverrideOrImplementationOfInterfaceMember(this ISymbol symbol, ISymbol? interfaceMember) + public static bool IsOverrideOrImplementationOfInterfaceMember(this ISymbol symbol, [NotNullWhen(returnValue: true)] ISymbol? interfaceMember) { if (interfaceMember == null) { @@ -570,7 +571,7 @@ public static ISymbol GetOverriddenMember(this ISymbol symbol) /// /// Checks if a given symbol implements an interface member explicitly /// - public static bool IsImplementationOfAnyExplicitInterfaceMember(this ISymbol? symbol) + public static bool IsImplementationOfAnyExplicitInterfaceMember([NotNullWhen(returnValue: true)] this ISymbol? symbol) { if (symbol is IMethodSymbol methodSymbol && methodSymbol.ExplicitInterfaceImplementations.Any()) { @@ -602,7 +603,7 @@ public static bool IsImplementationOfAnyExplicitInterfaceMember(this ISymbol? sy }; } - public static ITypeSymbol? GetMemberType(this ISymbol? symbol) + public static ITypeSymbol? GetMemberType([NotNullWhen(returnValue: true)] this ISymbol? symbol) { return symbol switch { @@ -618,7 +619,7 @@ public static bool IsImplementationOfAnyExplicitInterfaceMember(this ISymbol? sy }; } - public static bool IsReadOnlyFieldOrProperty(this ISymbol? symbol) + public static bool IsReadOnlyFieldOrProperty([NotNullWhen(returnValue: true)] this ISymbol? symbol) { return symbol switch { @@ -648,7 +649,7 @@ public static bool IsReadOnlyFieldOrProperty(this ISymbol? symbol) /// If is a type, this method does not find attributes /// on its base types. /// - public static bool HasAttribute(this ISymbol symbol, INamedTypeSymbol? attribute) + public static bool HasAttribute(this ISymbol symbol, [NotNullWhen(returnValue: true)] INamedTypeSymbol? attribute) { return attribute != null && symbol.GetAttributes().Any(attr => attr.AttributeClass.Equals(attribute)); } @@ -661,7 +662,7 @@ public static bool IsInSource(this ISymbol symbol) return symbol.Locations.Any(l => l.IsInSource); } - public static bool IsLambdaOrLocalFunction(this ISymbol? symbol) + public static bool IsLambdaOrLocalFunction([NotNullWhen(returnValue: true)] this ISymbol? symbol) => (symbol as IMethodSymbol)?.IsLambdaOrLocalFunction() == true; /// @@ -669,11 +670,11 @@ public static bool IsLambdaOrLocalFunction(this ISymbol? symbol) /// are optionally followed by an integer, such as '_', '_1', '_2', etc. /// These symbols can be treated as special discard symbol names. /// - public static bool IsSymbolWithSpecialDiscardName(this ISymbol? symbol) + public static bool IsSymbolWithSpecialDiscardName([NotNullWhen(returnValue: true)] this ISymbol? symbol) => symbol?.Name.StartsWith("_", StringComparison.Ordinal) == true && (symbol.Name.Length == 1 || uint.TryParse(symbol.Name.Substring(1), out _)); - public static bool IsConst(this ISymbol? symbol) + public static bool IsConst([NotNullWhen(returnValue: true)] this ISymbol? symbol) { return symbol switch { @@ -685,7 +686,7 @@ public static bool IsConst(this ISymbol? symbol) }; } - public static bool IsReadOnly(this ISymbol? symbol) + public static bool IsReadOnly([NotNullWhen(returnValue: true)] this ISymbol? symbol) { return symbol switch { From b5b948d5e6f5a1d96b6b56ad599bdec2c1419862 Mon Sep 17 00:00:00 2001 From: Manish Vasani Date: Fri, 8 Nov 2019 11:35:14 -0800 Subject: [PATCH 23/28] Address feedback --- .../CSharpImmutableObjectMethodAnalyzer.cs | 18 +++-- .../DiagnosticAnalyzerAttributeAnalyzer.cs | 5 +- .../DiagnosticDescriptorCreationAnalyzer.cs | 15 ++-- .../Core/SymbolIsBannedAnalyzer.cs | 8 ++- ...arpDefineAccessorsForAttributeArguments.cs | 6 +- ...ExceptionsInUnexpectedLocationsAnalyzer.cs | 6 +- .../CSharpUseGenericEventHandlerInstances.cs | 6 +- ...CSharpUseLiteralsWhereAppropriate.Fixer.cs | 2 +- ...lectionsShouldImplementGenericInterface.cs | 7 +- .../DefineAccessorsForAttributeArguments.cs | 8 ++- .../DoNotDirectlyAwaitATask.cs | 5 +- ...NotRaiseExceptionsInUnexpectedLocations.cs | 10 ++- .../EnumsShouldHaveZeroValue.Fixer.cs | 2 +- ...ratorOverloadsHaveNamedAlternates.Fixer.cs | 17 +++-- .../OverrideMethodsOnComparableTypes.cs | 6 +- .../TypeNamesShouldNotMatchNamespaces.cs | 15 +++- .../UseGenericEventHandlerInstances.cs | 8 ++- .../AvoidDeadConditionalCode.cs | 6 +- .../BasicUseGenericEventHandlerInstances.vb | 2 +- .../DoNotUseCountWhenAnyCanBeUsed.cs | 4 +- ...opertyInsteadOfCountMethodWhenAvailable.cs | 10 +-- .../DisposableFieldsShouldBeDisposed.cs | 4 +- .../DisposeObjectsBeforeLosingScope.cs | 2 +- .../DoNotLockOnObjectsWithWeakIdentity.cs | 6 +- .../DoNotPassLiteralsAsLocalizedParameters.cs | 4 +- ...videCorrectArgumentsToFormattingMethods.cs | 7 +- .../DoNotReferSelfInSerializableClass.cs | 6 +- .../Core/Security/DoNotUseDSA.cs | 1 - .../DoNotUseDeprecatedSecurityProtocols.cs | 8 ++- .../Security/DoNotUseInsecureRandomness.cs | 1 - .../Core/Security/JsonNetTypeNameHandling.cs | 3 +- .../Core/Security/SetViewStateUserKey.cs | 1 - .../Core/Security/SslProtocolsAnalyzer.cs | 8 ++- .../Security/UseRSAWithSufficientKeySize.cs | 1 - .../CSharp/Helpers/SyntaxNodeHelper.cs | 5 +- ...structorShouldBeObsoleteCodeFixProvider.cs | 8 +-- src/Tools/ReleaseNotesUtil/FixerExtensions.cs | 5 +- src/Tools/ReleaseNotesUtil/Program.cs | 7 +- .../ReleaseNotesUtil/ReleaseNotesUtil.csproj | 6 +- .../Compiler/Analyzer.Utilities.projitems | 5 +- src/Utilities/Compiler/Debug.cs | 19 ++++++ .../DoNotCatchGeneralUnlessRethrown.cs | 10 +-- .../Extensions/ITypeSymbolExtensions.cs | 14 ++-- .../CategorizedAnalyzerConfigOptions.cs | 6 +- .../Compiler/Options/SymbolNamesOption.cs | 2 +- src/Utilities/Compiler/RoslynString.cs | 21 ++++++ .../DisposeAnalysis/DisposeAnalysisHelper.cs | 4 +- ...meterValidationDataFlowOperationVisitor.cs | 9 +-- .../TaintedDataAnalysis/TaintedDataConfig.cs | 1 - .../DataFlow/AddressSharedEntitiesProvider.cs | 6 +- .../AnalysisEntityDataFlowOperationVisitor.cs | 5 +- .../DataFlow/AnalysisEntityFactory.cs | 4 +- .../Framework/DataFlow/DataFlowAnalysis.cs | 4 +- .../DataFlow/DataFlowOperationVisitor.cs | 68 +++++++++++-------- .../DataFlow/PredicatedAnalysisData.cs | 17 +++-- .../Framework/DataFlow/ThrownExceptionInfo.cs | 6 +- 56 files changed, 281 insertions(+), 169 deletions(-) create mode 100644 src/Utilities/Compiler/Debug.cs create mode 100644 src/Utilities/Compiler/RoslynString.cs diff --git a/src/Microsoft.CodeAnalysis.Analyzers/CSharp/CSharpImmutableObjectMethodAnalyzer.cs b/src/Microsoft.CodeAnalysis.Analyzers/CSharp/CSharpImmutableObjectMethodAnalyzer.cs index 3491c4036f..7954ac0694 100644 --- a/src/Microsoft.CodeAnalysis.Analyzers/CSharp/CSharpImmutableObjectMethodAnalyzer.cs +++ b/src/Microsoft.CodeAnalysis.Analyzers/CSharp/CSharpImmutableObjectMethodAnalyzer.cs @@ -50,24 +50,22 @@ public override void Initialize(AnalysisContext context) context.RegisterCompilationStartAction(compilationContext => { - INamedTypeSymbol? solutionSymbol = compilationContext.Compilation.GetOrCreateTypeByMetadataName(SolutionFullName); - INamedTypeSymbol? projectSymbol = compilationContext.Compilation.GetOrCreateTypeByMetadataName(ProjectFullName); - INamedTypeSymbol? documentSymbol = compilationContext.Compilation.GetOrCreateTypeByMetadataName(DocumentFullName); - INamedTypeSymbol? syntaxNodeSymbol = compilationContext.Compilation.GetOrCreateTypeByMetadataName(SyntaxNodeFullName); - INamedTypeSymbol? compilationSymbol = compilationContext.Compilation.GetOrCreateTypeByMetadataName(CompilationFullName); - - ImmutableArray immutableSymbols = ImmutableArray.CreateRange(new[] { solutionSymbol, projectSymbol, documentSymbol, syntaxNodeSymbol, compilationSymbol }.WhereNotNull()); - //Only register our node action if we can find the symbols for our immutable types - if (immutableSymbols.IsEmpty) + if (!compilationContext.Compilation.TryGetOrCreateTypeByMetadataName(SolutionFullName, out var solutionSymbol) || + !compilationContext.Compilation.TryGetOrCreateTypeByMetadataName(ProjectFullName, out var projectSymbol) || + !compilationContext.Compilation.TryGetOrCreateTypeByMetadataName(DocumentFullName, out var documentSymbol) || + !compilationContext.Compilation.TryGetOrCreateTypeByMetadataName(SyntaxNodeFullName, out var syntaxNodeSymbol) || + !compilationContext.Compilation.TryGetOrCreateTypeByMetadataName(CompilationFullName, out var compilationSymbol)) { + // Only register our node action if we can find the symbols for our immutable types return; } + var immutableSymbols = ImmutableHashSet.Create(solutionSymbol, projectSymbol, documentSymbol, syntaxNodeSymbol, compilationSymbol); compilationContext.RegisterSyntaxNodeAction(sc => AnalyzeInvocationForIgnoredReturnValue(sc, immutableSymbols), SyntaxKind.InvocationExpression); }); } - public static void AnalyzeInvocationForIgnoredReturnValue(SyntaxNodeAnalysisContext context, ImmutableArray immutableTypeSymbols) + public static void AnalyzeInvocationForIgnoredReturnValue(SyntaxNodeAnalysisContext context, ImmutableHashSet immutableTypeSymbols) { SemanticModel model = context.SemanticModel; var candidateInvocation = (InvocationExpressionSyntax)context.Node; diff --git a/src/Microsoft.CodeAnalysis.Analyzers/Core/MetaAnalyzers/DiagnosticAnalyzerAttributeAnalyzer.cs b/src/Microsoft.CodeAnalysis.Analyzers/Core/MetaAnalyzers/DiagnosticAnalyzerAttributeAnalyzer.cs index 9a07928d18..a1dca8ba55 100644 --- a/src/Microsoft.CodeAnalysis.Analyzers/Core/MetaAnalyzers/DiagnosticAnalyzerAttributeAnalyzer.cs +++ b/src/Microsoft.CodeAnalysis.Analyzers/Core/MetaAnalyzers/DiagnosticAnalyzerAttributeAnalyzer.cs @@ -1,7 +1,6 @@ // Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System.Collections.Immutable; -using System.Diagnostics; using Microsoft.CodeAnalysis.Diagnostics; using System.Diagnostics.CodeAnalysis; using Analyzer.Utilities; @@ -127,7 +126,7 @@ protected override void AnalyzeDiagnosticAnalyzer(SymbolAnalysisContext symbolCo } else if (supportsCSharp ^ supportsVB) { - Debug.Assert(attributeSyntax != null); + RoslynDebug.Assert(attributeSyntax != null); // If the analyzer assembly doesn't reference either C# or VB CodeAnalysis assemblies, // then the analyzer is pretty likely a language-agnostic analyzer. @@ -137,7 +136,7 @@ protected override void AnalyzeDiagnosticAnalyzer(SymbolAnalysisContext symbolCo if (compilationType == null) { string missingLanguage = supportsCSharp ? LanguageNames.VisualBasic : LanguageNames.CSharp; - Diagnostic diagnostic = Diagnostic.Create(AddLanguageSupportToAnalyzerRule, attributeSyntax!.GetLocation(), namedType.Name, missingLanguage); + Diagnostic diagnostic = Diagnostic.Create(AddLanguageSupportToAnalyzerRule, attributeSyntax.GetLocation(), namedType.Name, missingLanguage); symbolContext.ReportDiagnostic(diagnostic); } } diff --git a/src/Microsoft.CodeAnalysis.Analyzers/Core/MetaAnalyzers/DiagnosticDescriptorCreationAnalyzer.cs b/src/Microsoft.CodeAnalysis.Analyzers/Core/MetaAnalyzers/DiagnosticDescriptorCreationAnalyzer.cs index bbc312783e..51cfc67987 100644 --- a/src/Microsoft.CodeAnalysis.Analyzers/Core/MetaAnalyzers/DiagnosticDescriptorCreationAnalyzer.cs +++ b/src/Microsoft.CodeAnalysis.Analyzers/Core/MetaAnalyzers/DiagnosticDescriptorCreationAnalyzer.cs @@ -4,7 +4,6 @@ using System.Collections.Concurrent; using System.Collections.Generic; using System.Collections.Immutable; -using System.Diagnostics; using System.Diagnostics.CodeAnalysis; using System.IO; using System.Linq; @@ -363,9 +362,9 @@ ConcurrentBag UpdateLocationsFactory(string analyzerName, ConcurrentBa // If we have an additional file specifying required range and/or format for the ID, validate the ID. if (!allowedIdsInfoListOpt.IsDefault) { - Debug.Assert(!allowedIdsInfoListOpt.IsEmpty); - Debug.Assert(categoryOpt != null); - Debug.Assert(additionalTextOpt != null); + RoslynDebug.Assert(!allowedIdsInfoListOpt.IsEmpty); + RoslynDebug.Assert(categoryOpt != null); + RoslynDebug.Assert(additionalTextOpt != null); var foundMatch = false; static bool ShouldValidateRange((string? prefix, int start, int end) range) @@ -374,13 +373,13 @@ static bool ShouldValidateRange((string? prefix, int start, int end) range) // Check if ID matches any one of the required ranges. foreach (var allowedIds in allowedIdsInfoListOpt) { - Debug.Assert(allowedIds.prefix != null); + RoslynDebug.Assert(allowedIds.prefix != null); if (ruleId.StartsWith(allowedIds.prefix, StringComparison.Ordinal)) { if (ShouldValidateRange(allowedIds)) { - var suffix = ruleId.Substring(allowedIds.prefix!.Length); + var suffix = ruleId.Substring(allowedIds.prefix.Length); if (int.TryParse(suffix, out int ruleIdInt) && ruleIdInt >= allowedIds.start && ruleIdInt <= allowedIds.end) @@ -401,7 +400,7 @@ static bool ShouldValidateRange((string? prefix, int start, int end) range) { // Diagnostic Id '{0}' belonging to category '{1}' is not in the required range and/or format '{2}' specified in the file '{3}'. string arg1 = ruleId; - string arg2 = categoryOpt!; + string arg2 = categoryOpt; string arg3 = string.Empty; foreach (var range in allowedIdsInfoListOpt) { @@ -413,7 +412,7 @@ static bool ShouldValidateRange((string? prefix, int start, int end) range) arg3 += !ShouldValidateRange(range) ? range.prefix + "XXXX" : $"{range.prefix}{range.start}-{range.prefix}{range.end}"; } - string arg4 = Path.GetFileName(additionalTextOpt!.Path); + string arg4 = Path.GetFileName(additionalTextOpt.Path); var diagnostic = Diagnostic.Create(DiagnosticIdMustBeInSpecifiedFormatRule, argument.Value.Syntax.GetLocation(), arg1, arg2, arg3, arg4); operationAnalysisContext.ReportDiagnostic(diagnostic); } diff --git a/src/Microsoft.CodeAnalysis.BannedApiAnalyzers/Core/SymbolIsBannedAnalyzer.cs b/src/Microsoft.CodeAnalysis.BannedApiAnalyzers/Core/SymbolIsBannedAnalyzer.cs index 42aac01ae5..f16c948b51 100644 --- a/src/Microsoft.CodeAnalysis.BannedApiAnalyzers/Core/SymbolIsBannedAnalyzer.cs +++ b/src/Microsoft.CodeAnalysis.BannedApiAnalyzers/Core/SymbolIsBannedAnalyzer.cs @@ -255,6 +255,8 @@ void VerifyAttributes(Action reportDiagnostic, ImmutableArray reportDiagnostic, ITypeSymbol? type, SyntaxNode syntaxNode) { + RoslynDebug.Assert(entryBySymbol != null); + do { if (!VerifyTypeArguments(reportDiagnostic, type, syntaxNode, out type)) @@ -268,7 +270,7 @@ bool VerifyType(Action reportDiagnostic, ITypeSymbol? type, SyntaxNo return true; } - if (entryBySymbol!.TryGetValue(type, out var entry)) + if (entryBySymbol.TryGetValue(type, out var entry)) { reportDiagnostic( Diagnostic.Create( @@ -322,9 +324,11 @@ bool VerifyTypeArguments(Action reportDiagnostic, ITypeSymbol? type, void VerifySymbol(Action reportDiagnostic, ISymbol symbol, SyntaxNode syntaxNode) { + RoslynDebug.Assert(entryBySymbol != null); + symbol = symbol.OriginalDefinition; - if (entryBySymbol!.TryGetValue(symbol, out var entry)) + if (entryBySymbol.TryGetValue(symbol, out var entry)) { reportDiagnostic( Diagnostic.Create( diff --git a/src/Microsoft.CodeQuality.Analyzers/CSharp/ApiDesignGuidelines/CSharpDefineAccessorsForAttributeArguments.cs b/src/Microsoft.CodeQuality.Analyzers/CSharp/ApiDesignGuidelines/CSharpDefineAccessorsForAttributeArguments.cs index d651a613f1..d56dcdb6d5 100644 --- a/src/Microsoft.CodeQuality.Analyzers/CSharp/ApiDesignGuidelines/CSharpDefineAccessorsForAttributeArguments.cs +++ b/src/Microsoft.CodeQuality.Analyzers/CSharp/ApiDesignGuidelines/CSharpDefineAccessorsForAttributeArguments.cs @@ -4,6 +4,7 @@ using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.CSharp; using Microsoft.CodeAnalysis.Diagnostics; +using System.Diagnostics.CodeAnalysis; namespace Microsoft.CodeQuality.CSharp.Analyzers.ApiDesignGuidelines { @@ -16,7 +17,10 @@ namespace Microsoft.CodeQuality.CSharp.Analyzers.ApiDesignGuidelines [DiagnosticAnalyzer(LanguageNames.CSharp)] public class CSharpDefineAccessorsForAttributeArgumentsAnalyzer : DefineAccessorsForAttributeArgumentsAnalyzer { - protected override bool IsAssignableTo(ITypeSymbol fromSymbol, ITypeSymbol toSymbol, Compilation compilation) + protected override bool IsAssignableTo( + [NotNullWhen(returnValue: true)] ITypeSymbol? fromSymbol, + [NotNullWhen(returnValue: true)] ITypeSymbol? toSymbol, + Compilation compilation) { return fromSymbol != null && toSymbol != null && diff --git a/src/Microsoft.CodeQuality.Analyzers/CSharp/ApiDesignGuidelines/CSharpDoNotRaiseExceptionsInUnexpectedLocationsAnalyzer.cs b/src/Microsoft.CodeQuality.Analyzers/CSharp/ApiDesignGuidelines/CSharpDoNotRaiseExceptionsInUnexpectedLocationsAnalyzer.cs index bd8579b7d3..9cfec345e0 100644 --- a/src/Microsoft.CodeQuality.Analyzers/CSharp/ApiDesignGuidelines/CSharpDoNotRaiseExceptionsInUnexpectedLocationsAnalyzer.cs +++ b/src/Microsoft.CodeQuality.Analyzers/CSharp/ApiDesignGuidelines/CSharpDoNotRaiseExceptionsInUnexpectedLocationsAnalyzer.cs @@ -4,6 +4,7 @@ using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.CSharp; using Microsoft.CodeAnalysis.Diagnostics; +using System.Diagnostics.CodeAnalysis; namespace Microsoft.CodeQuality.CSharp.Analyzers.ApiDesignGuidelines { @@ -13,7 +14,10 @@ namespace Microsoft.CodeQuality.CSharp.Analyzers.ApiDesignGuidelines [DiagnosticAnalyzer(LanguageNames.CSharp)] public class CSharpDoNotRaiseExceptionsInUnexpectedLocationsAnalyzer : DoNotRaiseExceptionsInUnexpectedLocationsAnalyzer { - protected override bool IsAssignableTo(ITypeSymbol? fromSymbol, ITypeSymbol? toSymbol, Compilation compilation) + protected override bool IsAssignableTo( + [NotNullWhen(returnValue: true)] ITypeSymbol? fromSymbol, + [NotNullWhen(returnValue: true)] ITypeSymbol? toSymbol, + Compilation compilation) { return fromSymbol != null && toSymbol != null && diff --git a/src/Microsoft.CodeQuality.Analyzers/CSharp/ApiDesignGuidelines/CSharpUseGenericEventHandlerInstances.cs b/src/Microsoft.CodeQuality.Analyzers/CSharp/ApiDesignGuidelines/CSharpUseGenericEventHandlerInstances.cs index 7eea392ccd..f560ee4d7d 100644 --- a/src/Microsoft.CodeQuality.Analyzers/CSharp/ApiDesignGuidelines/CSharpUseGenericEventHandlerInstances.cs +++ b/src/Microsoft.CodeQuality.Analyzers/CSharp/ApiDesignGuidelines/CSharpUseGenericEventHandlerInstances.cs @@ -4,13 +4,17 @@ using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.CSharp; using Microsoft.CodeAnalysis.Diagnostics; +using System.Diagnostics.CodeAnalysis; namespace Microsoft.CodeQuality.CSharp.Analyzers.ApiDesignGuidelines { [DiagnosticAnalyzer(LanguageNames.CSharp)] public class CSharpUseGenericEventHandlerInstancesAnalyzer : UseGenericEventHandlerInstancesAnalyzer { - protected override bool IsAssignableTo(Compilation compilation, ITypeSymbol fromSymbol, ITypeSymbol toSymbol) + protected override bool IsAssignableTo( + [NotNullWhen(returnValue: true)] ITypeSymbol? fromSymbol, + [NotNullWhen(returnValue: true)] ITypeSymbol? toSymbol, + Compilation compilation) { return fromSymbol != null && diff --git a/src/Microsoft.CodeQuality.Analyzers/CSharp/QualityGuidelines/CSharpUseLiteralsWhereAppropriate.Fixer.cs b/src/Microsoft.CodeQuality.Analyzers/CSharp/QualityGuidelines/CSharpUseLiteralsWhereAppropriate.Fixer.cs index 01a27f3c63..a6089bac85 100644 --- a/src/Microsoft.CodeQuality.Analyzers/CSharp/QualityGuidelines/CSharpUseLiteralsWhereAppropriate.Fixer.cs +++ b/src/Microsoft.CodeQuality.Analyzers/CSharp/QualityGuidelines/CSharpUseLiteralsWhereAppropriate.Fixer.cs @@ -22,7 +22,7 @@ public sealed class CSharpUseLiteralsWhereAppropriateFixer : UseLiteralsWhereApp syntaxNode = syntaxNode.Parent; } - var field = syntaxNode as FieldDeclarationSyntax; + var field = (FieldDeclarationSyntax?)syntaxNode; // Multiple declarators are not supported, as one of them may not be constant. return field?.Declaration.Variables.Count > 1 ? null : field; diff --git a/src/Microsoft.CodeQuality.Analyzers/Core/ApiDesignGuidelines/CollectionsShouldImplementGenericInterface.cs b/src/Microsoft.CodeQuality.Analyzers/Core/ApiDesignGuidelines/CollectionsShouldImplementGenericInterface.cs index d33140287b..284c73fb8d 100644 --- a/src/Microsoft.CodeQuality.Analyzers/Core/ApiDesignGuidelines/CollectionsShouldImplementGenericInterface.cs +++ b/src/Microsoft.CodeQuality.Analyzers/Core/ApiDesignGuidelines/CollectionsShouldImplementGenericInterface.cs @@ -1,7 +1,6 @@ // Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System.Collections.Immutable; -using System.Diagnostics; using System.Linq; using Analyzer.Utilities; using Analyzer.Utilities.Extensions; @@ -168,12 +167,12 @@ public override void Initialize(AnalysisContext analysisContext) return; } - Debug.Assert(missingInterface != null && implementedInterface != null); + RoslynDebug.Assert(missingInterface != null && implementedInterface != null); context.ReportDiagnostic(Diagnostic.Create(Rule, namedTypeSymbol.Locations.First(), namedTypeSymbol.Name, - implementedInterface!.ToDisplayString(SymbolDisplayFormat.MinimallyQualifiedFormat), - missingInterface!.ToDisplayString(SymbolDisplayFormat.MinimallyQualifiedFormat))); + implementedInterface.ToDisplayString(SymbolDisplayFormat.MinimallyQualifiedFormat), + missingInterface.ToDisplayString(SymbolDisplayFormat.MinimallyQualifiedFormat))); } #pragma warning disable CA1815 // Override equals and operator equals on value types diff --git a/src/Microsoft.CodeQuality.Analyzers/Core/ApiDesignGuidelines/DefineAccessorsForAttributeArguments.cs b/src/Microsoft.CodeQuality.Analyzers/Core/ApiDesignGuidelines/DefineAccessorsForAttributeArguments.cs index 5c78bc46b1..fe4581bd29 100644 --- a/src/Microsoft.CodeQuality.Analyzers/Core/ApiDesignGuidelines/DefineAccessorsForAttributeArguments.cs +++ b/src/Microsoft.CodeQuality.Analyzers/Core/ApiDesignGuidelines/DefineAccessorsForAttributeArguments.cs @@ -3,6 +3,7 @@ using System; using System.Collections.Generic; using System.Collections.Immutable; +using System.Diagnostics.CodeAnalysis; using System.Linq; using Analyzer.Utilities; using Analyzer.Utilities.Extensions; @@ -92,7 +93,10 @@ private void AnalyzeSymbol(INamedTypeSymbol symbol, INamedTypeSymbol attributeTy } } - protected abstract bool IsAssignableTo(ITypeSymbol fromSymbol, ITypeSymbol toSymbol, Compilation compilation); + protected abstract bool IsAssignableTo( + [NotNullWhen(returnValue: true)] ITypeSymbol? fromSymbol, + [NotNullWhen(returnValue: true)] ITypeSymbol? toSymbol, + Compilation compilation); private static IEnumerable GetAllPublicConstructorParameters(INamedTypeSymbol attributeType) { @@ -142,7 +146,7 @@ private void AnalyzeParameters(Compilation compilation, IEnumerable taskTypes) + private static bool TryGetTaskTypes(Compilation compilation, out ImmutableArray taskTypes) { INamedTypeSymbol? taskType = compilation.GetOrCreateTypeByMetadataName(WellKnownTypeNames.SystemThreadingTasksTask); INamedTypeSymbol? taskOfTType = compilation.GetOrCreateTypeByMetadataName(WellKnownTypeNames.SystemThreadingTasksGenericTask); if (taskType == null || taskOfTType == null) { - taskTypes = default; + taskTypes = ImmutableArray.Empty; return false; } diff --git a/src/Microsoft.CodeQuality.Analyzers/Core/ApiDesignGuidelines/DoNotRaiseExceptionsInUnexpectedLocations.cs b/src/Microsoft.CodeQuality.Analyzers/Core/ApiDesignGuidelines/DoNotRaiseExceptionsInUnexpectedLocations.cs index 521f6010e6..7c25d6721f 100644 --- a/src/Microsoft.CodeQuality.Analyzers/Core/ApiDesignGuidelines/DoNotRaiseExceptionsInUnexpectedLocations.cs +++ b/src/Microsoft.CodeQuality.Analyzers/Core/ApiDesignGuidelines/DoNotRaiseExceptionsInUnexpectedLocations.cs @@ -3,6 +3,7 @@ using System; using System.Collections.Generic; using System.Collections.Immutable; +using System.Diagnostics.CodeAnalysis; using System.Linq; using Analyzer.Utilities; using Analyzer.Utilities.Extensions; @@ -110,7 +111,10 @@ public override void Initialize(AnalysisContext analysisContext) }); } - protected abstract bool IsAssignableTo(ITypeSymbol? fromSymbol, ITypeSymbol? toSymbol, Compilation compilation); + protected abstract bool IsAssignableTo( + [NotNullWhen(returnValue: true)] ITypeSymbol? fromSymbol, + [NotNullWhen(returnValue: true)] ITypeSymbol? toSymbol, + Compilation compilation); /// /// This object describes a class of methods where exception throwing statements should be analyzed. @@ -136,14 +140,14 @@ private class MethodCategory /// List of exception types which are allowed to be thrown inside this category of method. /// This list will be empty if no exceptions are allowed. /// - public ImmutableHashSet AllowedExceptions { get; } + public ImmutableHashSet AllowedExceptions { get; } public MethodCategory(Func matchFunction, bool analyzeOnlyPublicMethods, DiagnosticDescriptor rule, params ITypeSymbol?[] allowedExceptionTypes) { _matchFunction = matchFunction; _analyzeOnlyPublicMethods = analyzeOnlyPublicMethods; this.Rule = rule; - AllowedExceptions = allowedExceptionTypes.ToImmutableHashSet(); + AllowedExceptions = allowedExceptionTypes.WhereNotNull().ToImmutableHashSet(); } /// diff --git a/src/Microsoft.CodeQuality.Analyzers/Core/ApiDesignGuidelines/EnumsShouldHaveZeroValue.Fixer.cs b/src/Microsoft.CodeQuality.Analyzers/Core/ApiDesignGuidelines/EnumsShouldHaveZeroValue.Fixer.cs index e6083a1f6a..c41527922a 100644 --- a/src/Microsoft.CodeQuality.Analyzers/Core/ApiDesignGuidelines/EnumsShouldHaveZeroValue.Fixer.cs +++ b/src/Microsoft.CodeQuality.Analyzers/Core/ApiDesignGuidelines/EnumsShouldHaveZeroValue.Fixer.cs @@ -36,7 +36,7 @@ public override async Task RegisterCodeFixesAsync(CodeFixContext context) SyntaxNode root = await context.Document.GetSyntaxRootAsync(context.CancellationToken).ConfigureAwait(false); SyntaxNode node = root.FindNode(context.Span); - ISymbol declaredSymbol = model.GetDeclaredSymbol(node, context.CancellationToken); + ISymbol? declaredSymbol = model.GetDeclaredSymbol(node, context.CancellationToken); if (declaredSymbol == null) { continue; diff --git a/src/Microsoft.CodeQuality.Analyzers/Core/ApiDesignGuidelines/OperatorOverloadsHaveNamedAlternates.Fixer.cs b/src/Microsoft.CodeQuality.Analyzers/Core/ApiDesignGuidelines/OperatorOverloadsHaveNamedAlternates.Fixer.cs index f14d2ee0cb..93f0fe3add 100644 --- a/src/Microsoft.CodeQuality.Analyzers/Core/ApiDesignGuidelines/OperatorOverloadsHaveNamedAlternates.Fixer.cs +++ b/src/Microsoft.CodeQuality.Analyzers/Core/ApiDesignGuidelines/OperatorOverloadsHaveNamedAlternates.Fixer.cs @@ -30,16 +30,23 @@ public override FixAllProvider GetFixAllProvider() public override async Task RegisterCodeFixesAsync(CodeFixContext context) { - SemanticModel semanticModel = await context.Document.GetSemanticModelAsync(context.CancellationToken).ConfigureAwait(false); - SyntaxNode root = await context.Document.GetSyntaxRootAsync(context.CancellationToken).ConfigureAwait(false); - SyntaxGenerator generator = context.Document.Project.LanguageServices.GetService(); + var root = await context.Document.GetSyntaxRootAsync(context.CancellationToken).ConfigureAwait(false); + SyntaxNode node = root.FindNode(context.Span); + if (node == null) + { + return; + } string title = MicrosoftCodeQualityAnalyzersResources.OperatorOverloadsHaveNamedAlternatesTitle; - context.RegisterCodeFix(new MyCodeAction(title, ct => Fix(context, root, generator, semanticModel, ct), equivalenceKey: title), context.Diagnostics.First()); + context.RegisterCodeFix(new MyCodeAction(title, ct => Fix(context, ct), equivalenceKey: title), context.Diagnostics.First()); } - private static async Task Fix(CodeFixContext context, SyntaxNode root, SyntaxGenerator generator, SemanticModel semanticModel, CancellationToken cancellationToken) + private static async Task Fix(CodeFixContext context, CancellationToken cancellationToken) { + var semanticModel = await context.Document.GetSemanticModelAsync(context.CancellationToken).ConfigureAwait(false); + var root = await context.Document.GetSyntaxRootAsync(context.CancellationToken).ConfigureAwait(false); + var generator = SyntaxGenerator.GetGenerator(context.Document); + SyntaxNode node = root.FindNode(context.Span); Diagnostic diagnostic = context.Diagnostics.First(); switch (diagnostic.Properties[OperatorOverloadsHaveNamedAlternatesAnalyzer.DiagnosticKindText]) diff --git a/src/Microsoft.CodeQuality.Analyzers/Core/ApiDesignGuidelines/OverrideMethodsOnComparableTypes.cs b/src/Microsoft.CodeQuality.Analyzers/Core/ApiDesignGuidelines/OverrideMethodsOnComparableTypes.cs index 4739708d31..df638853a6 100644 --- a/src/Microsoft.CodeQuality.Analyzers/Core/ApiDesignGuidelines/OverrideMethodsOnComparableTypes.cs +++ b/src/Microsoft.CodeQuality.Analyzers/Core/ApiDesignGuidelines/OverrideMethodsOnComparableTypes.cs @@ -139,18 +139,16 @@ private static bool IsComparableCore(INamedTypeSymbol namedTypeSymbol, INamedTyp private static string GetNeededComparisonOperators(INamedTypeSymbol symbol) { - bool first = true; StringBuilder? sb = null; void Append(string @operator) { - if (first) + if (sb == null) { sb = new StringBuilder(); - first = false; } else { - sb!.Append(", "); + sb.Append(", "); } sb.Append(@operator); diff --git a/src/Microsoft.CodeQuality.Analyzers/Core/ApiDesignGuidelines/TypeNamesShouldNotMatchNamespaces.cs b/src/Microsoft.CodeQuality.Analyzers/Core/ApiDesignGuidelines/TypeNamesShouldNotMatchNamespaces.cs index 6dfdfaed72..6ea1b9e822 100644 --- a/src/Microsoft.CodeQuality.Analyzers/Core/ApiDesignGuidelines/TypeNamesShouldNotMatchNamespaces.cs +++ b/src/Microsoft.CodeQuality.Analyzers/Core/ApiDesignGuidelines/TypeNamesShouldNotMatchNamespaces.cs @@ -49,6 +49,16 @@ public sealed class TypeNamesShouldNotMatchNamespacesAnalyzer : DiagnosticAnalyz private static readonly object s_lock = new object(); private static ImmutableDictionary? s_wellKnownSystemNamespaceTable; + private static ImmutableDictionary WellKnownSystemNamespaceTable + { + get + { + InitializeWellKnownSystemNamespaceTable(); + RoslynDebug.Assert(s_wellKnownSystemNamespaceTable != null); + return s_wellKnownSystemNamespaceTable; + } + } + public override void Initialize(AnalysisContext analysisContext) { analysisContext.EnableConcurrentExecution(); @@ -91,13 +101,12 @@ public override void Initialize(AnalysisContext analysisContext) var namespaceComponentToNamespaceNameDictionary = new Dictionary(StringComparer.OrdinalIgnoreCase); UpdateNamespaceTable(namespaceComponentToNamespaceNameDictionary, namespaceNamesInCompilation.ToImmutableSortedSet()); - InitializeWellKnownSystemNamespaceTable(); foreach (INamedTypeSymbol symbol in externallyVisibleNamedTypes) { string symbolName = symbol.Name; - if (s_wellKnownSystemNamespaceTable!.ContainsKey(symbolName)) + if (WellKnownSystemNamespaceTable.ContainsKey(symbolName)) { - compilationAnalysisContext.ReportDiagnostic(symbol.CreateDiagnostic(SystemRule, symbolName, s_wellKnownSystemNamespaceTable[symbolName])); + compilationAnalysisContext.ReportDiagnostic(symbol.CreateDiagnostic(SystemRule, symbolName, WellKnownSystemNamespaceTable[symbolName])); } else if (namespaceComponentToNamespaceNameDictionary.ContainsKey(symbolName)) { diff --git a/src/Microsoft.CodeQuality.Analyzers/Core/ApiDesignGuidelines/UseGenericEventHandlerInstances.cs b/src/Microsoft.CodeQuality.Analyzers/Core/ApiDesignGuidelines/UseGenericEventHandlerInstances.cs index 8b6093b446..1eda911968 100644 --- a/src/Microsoft.CodeQuality.Analyzers/Core/ApiDesignGuidelines/UseGenericEventHandlerInstances.cs +++ b/src/Microsoft.CodeQuality.Analyzers/Core/ApiDesignGuidelines/UseGenericEventHandlerInstances.cs @@ -2,6 +2,7 @@ using System; using System.Collections.Immutable; +using System.Diagnostics.CodeAnalysis; using System.Linq; using Analyzer.Utilities; using Analyzer.Utilities.Extensions; @@ -66,7 +67,10 @@ public abstract class UseGenericEventHandlerInstancesAnalyzer : DiagnosticAnalyz customTags: FxCopWellKnownDiagnosticTags.PortedFxCopRule); public override ImmutableArray SupportedDiagnostics => ImmutableArray.Create(RuleForDelegates, RuleForEvents, RuleForEvents2); - protected abstract bool IsAssignableTo(Compilation compilation, ITypeSymbol fromSymbol, ITypeSymbol toSymbol); + protected abstract bool IsAssignableTo( + [NotNullWhen(returnValue: true)] ITypeSymbol? fromSymbol, + [NotNullWhen(returnValue: true)] ITypeSymbol? toSymbol, + Compilation compilation); public override void Initialize(AnalysisContext analysisContext) { @@ -94,7 +98,7 @@ public override void Initialize(AnalysisContext analysisContext) bool IsEventArgsParameter(IParameterSymbol parameter) { var type = parameter.Type; - if (IsAssignableTo(context.Compilation, type, eventArgs!)) + if (IsAssignableTo(type, eventArgs, context.Compilation)) { return true; } diff --git a/src/Microsoft.CodeQuality.Analyzers/Core/Maintainability/AvoidDeadConditionalCode.cs b/src/Microsoft.CodeQuality.Analyzers/Core/Maintainability/AvoidDeadConditionalCode.cs index b1e59cd765..caf9bcb21e 100644 --- a/src/Microsoft.CodeQuality.Analyzers/Core/Maintainability/AvoidDeadConditionalCode.cs +++ b/src/Microsoft.CodeQuality.Analyzers/Core/Maintainability/AvoidDeadConditionalCode.cs @@ -167,12 +167,14 @@ PredicateValueKind GetPredicateKind(IOperation operation) operation.Kind == OperationKind.Invocation || operation.Kind == OperationKind.IsNull || operation.Kind == OperationKind.IsPattern); + RoslynDebug.Assert(pointsToAnalysisResult != null); + RoslynDebug.Assert(valueContentAnalysisResult != null); if (operation is IBinaryOperation binaryOperation && binaryOperation.IsComparisonOperator() || operation.Type?.SpecialType == SpecialType.System_Boolean) { - PredicateValueKind predicateKind = pointsToAnalysisResult!.GetPredicateKind(operation); + PredicateValueKind predicateKind = pointsToAnalysisResult.GetPredicateKind(operation); if (predicateKind != PredicateValueKind.Unknown) { return predicateKind; @@ -187,7 +189,7 @@ PredicateValueKind GetPredicateKind(IOperation operation) } } - predicateKind = valueContentAnalysisResult!.GetPredicateKind(operation); + predicateKind = valueContentAnalysisResult.GetPredicateKind(operation); if (predicateKind != PredicateValueKind.Unknown) { return predicateKind; diff --git a/src/Microsoft.CodeQuality.Analyzers/VisualBasic/ApiDesignGuidelines/BasicUseGenericEventHandlerInstances.vb b/src/Microsoft.CodeQuality.Analyzers/VisualBasic/ApiDesignGuidelines/BasicUseGenericEventHandlerInstances.vb index a3d7747d0e..401a135df8 100644 --- a/src/Microsoft.CodeQuality.Analyzers/VisualBasic/ApiDesignGuidelines/BasicUseGenericEventHandlerInstances.vb +++ b/src/Microsoft.CodeQuality.Analyzers/VisualBasic/ApiDesignGuidelines/BasicUseGenericEventHandlerInstances.vb @@ -11,7 +11,7 @@ Namespace Microsoft.CodeQuality.VisualBasic.Analyzers.ApiDesignGuidelines Public Class BasicUseGenericEventHandlerInstancesAnalyzer Inherits UseGenericEventHandlerInstancesAnalyzer - Protected Overrides Function IsAssignableTo(compilation As Compilation, fromSymbol As ITypeSymbol, toSymbol As ITypeSymbol) As Boolean + Protected Overrides Function IsAssignableTo(fromSymbol As ITypeSymbol, toSymbol As ITypeSymbol, compilation As Compilation) As Boolean Return fromSymbol IsNot Nothing AndAlso toSymbol IsNot Nothing AndAlso DirectCast(compilation, VisualBasicCompilation).ClassifyConversion(fromSymbol, toSymbol).IsWidening End Function End Class diff --git a/src/Microsoft.NetCore.Analyzers/Core/Performance/DoNotUseCountWhenAnyCanBeUsed.cs b/src/Microsoft.NetCore.Analyzers/Core/Performance/DoNotUseCountWhenAnyCanBeUsed.cs index e545ae3c43..90d3b510c7 100644 --- a/src/Microsoft.NetCore.Analyzers/Core/Performance/DoNotUseCountWhenAnyCanBeUsed.cs +++ b/src/Microsoft.NetCore.Analyzers/Core/Performance/DoNotUseCountWhenAnyCanBeUsed.cs @@ -289,7 +289,7 @@ public void AnalyzeInvocationOperation(OperationAnalysisContext context) invocationOperation.Syntax.CreateDiagnostic( rule: this._rule, properties: properties, - args: methodName!)); + args: methodName)); } } @@ -355,7 +355,7 @@ private static bool IsEqualsMethod(IMethodSymbol methodSymbol) /// /// if the value of the invocation of one of the in the /// is being compared with 0 using ; otherwise, . - private bool IsCountEqualsZero(IInvocationOperation invocationOperation, out string? methodName) + private bool IsCountEqualsZero(IInvocationOperation invocationOperation, [NotNullWhen(returnValue: true)] out string? methodName) { if (!TryGetZeroOrOneConstant(invocationOperation.Arguments[0].Value, out var constant) || constant != 0) { diff --git a/src/Microsoft.NetCore.Analyzers/Core/Performance/UsePropertyInsteadOfCountMethodWhenAvailable.cs b/src/Microsoft.NetCore.Analyzers/Core/Performance/UsePropertyInsteadOfCountMethodWhenAvailable.cs index cacae19be1..94454a9f08 100644 --- a/src/Microsoft.NetCore.Analyzers/Core/Performance/UsePropertyInsteadOfCountMethodWhenAvailable.cs +++ b/src/Microsoft.NetCore.Analyzers/Core/Performance/UsePropertyInsteadOfCountMethodWhenAvailable.cs @@ -194,7 +194,7 @@ internal bool IsICollectionOfTImplementation(ITypeSymbol invocationTarget) return false; } - if (isCollectionOfTInterface(invocationTarget)) + if (isCollectionOfTInterface(invocationTarget, ICollectionOfTType)) { return true; } @@ -209,7 +209,7 @@ internal bool IsICollectionOfTImplementation(ITypeSymbol invocationTarget) foreach (var @interface in invocationTarget.AllInterfaces) { if (@interface.OriginalDefinition is INamedTypeSymbol originalInterfaceDefinition && - isCollectionOfTInterface(originalInterfaceDefinition)) + isCollectionOfTInterface(originalInterfaceDefinition, ICollectionOfTType)) { return true; } @@ -220,7 +220,7 @@ internal bool IsICollectionOfTImplementation(ITypeSymbol invocationTarget) foreach (var @interface in invocationTarget.AllInterfaces) { if (@interface.OriginalDefinition is INamedTypeSymbol originalInterfaceDefinition && - isCollectionOfTInterface(originalInterfaceDefinition)) + isCollectionOfTInterface(originalInterfaceDefinition, ICollectionOfTType)) { if (invocationTarget.FindImplementationForInterfaceMember(@interface.GetMembers(CountPropertyName)[0]) is IPropertySymbol propertyImplementation && !propertyImplementation.ExplicitInterfaceImplementations.Any()) @@ -233,8 +233,8 @@ internal bool IsICollectionOfTImplementation(ITypeSymbol invocationTarget) return false; - bool isCollectionOfTInterface(ITypeSymbol type) - => this.ICollectionOfTType!.Equals(type.OriginalDefinition); + static bool isCollectionOfTInterface(ITypeSymbol type, ITypeSymbol iCollectionOfTType) + => iCollectionOfTType.Equals(type.OriginalDefinition); } /// diff --git a/src/Microsoft.NetCore.Analyzers/Core/Runtime/DisposableFieldsShouldBeDisposed.cs b/src/Microsoft.NetCore.Analyzers/Core/Runtime/DisposableFieldsShouldBeDisposed.cs index 32d552683f..57f98b27eb 100644 --- a/src/Microsoft.NetCore.Analyzers/Core/Runtime/DisposableFieldsShouldBeDisposed.cs +++ b/src/Microsoft.NetCore.Analyzers/Core/Runtime/DisposableFieldsShouldBeDisposed.cs @@ -168,8 +168,10 @@ void addOrUpdateFieldDisposedValue(IFieldSymbol field, bool disposed) operationBlockStartContext.Options, Rule, trackInstanceFields: true, trackExceptionPaths: false, cancellationToken: operationBlockStartContext.CancellationToken, disposeAnalysisResult: out var disposeAnalysisResult, pointsToAnalysisResult: out var pointsToAnalysisResult)) { + RoslynDebug.Assert(disposeAnalysisResult.TrackedInstanceFieldPointsToMap != null); + BasicBlock exitBlock = disposeAnalysisResult.ControlFlowGraph.GetExit(); - foreach (var fieldWithPointsToValue in disposeAnalysisResult!.TrackedInstanceFieldPointsToMap!) + foreach (var fieldWithPointsToValue in disposeAnalysisResult.TrackedInstanceFieldPointsToMap) { IFieldSymbol field = fieldWithPointsToValue.Key; PointsToAbstractValue pointsToValue = fieldWithPointsToValue.Value; diff --git a/src/Microsoft.NetCore.Analyzers/Core/Runtime/DisposeObjectsBeforeLosingScope.cs b/src/Microsoft.NetCore.Analyzers/Core/Runtime/DisposeObjectsBeforeLosingScope.cs index 9e7e417207..d7ce0c2fa6 100644 --- a/src/Microsoft.NetCore.Analyzers/Core/Runtime/DisposeObjectsBeforeLosingScope.cs +++ b/src/Microsoft.NetCore.Analyzers/Core/Runtime/DisposeObjectsBeforeLosingScope.cs @@ -123,7 +123,7 @@ public override void Initialize(AnalysisContext context) if (trackExceptionPaths) { // Compute diagnostics for undisposed objects at handled exception exit paths. - var disposeDataAtHandledExceptionPaths = disposeAnalysisResult!.ExceptionPathsExitBlockOutputOpt!.Data; + var disposeDataAtHandledExceptionPaths = disposeAnalysisResult.ExceptionPathsExitBlockOutputOpt!.Data; ComputeDiagnostics(disposeDataAtHandledExceptionPaths, notDisposedDiagnostics, mayBeNotDisposedDiagnostics, disposeAnalysisResult, pointsToAnalysisResult, disposeAnalysisKind, isDisposeDataForExceptionPaths: true); diff --git a/src/Microsoft.NetCore.Analyzers/Core/Runtime/DoNotLockOnObjectsWithWeakIdentity.cs b/src/Microsoft.NetCore.Analyzers/Core/Runtime/DoNotLockOnObjectsWithWeakIdentity.cs index a613a43353..9c821dc20e 100644 --- a/src/Microsoft.NetCore.Analyzers/Core/Runtime/DoNotLockOnObjectsWithWeakIdentity.cs +++ b/src/Microsoft.NetCore.Analyzers/Core/Runtime/DoNotLockOnObjectsWithWeakIdentity.cs @@ -51,10 +51,10 @@ public override void Initialize(AnalysisContext analysisContext) compilationStartContext.RegisterOperationAction(context => { var lockStatement = (ILockOperation)context.Operation; - ITypeSymbol? type = lockStatement.LockedValue?.Type; - if (type != null && TypeHasWeakIdentity(type, compilation)) + if (lockStatement.LockedValue?.Type is ITypeSymbol type && + TypeHasWeakIdentity(type, compilation)) { - context.ReportDiagnostic(lockStatement.LockedValue!.Syntax.CreateDiagnostic(Rule, type.ToDisplayString())); + context.ReportDiagnostic(lockStatement.LockedValue.Syntax.CreateDiagnostic(Rule, type.ToDisplayString())); } }, OperationKind.Lock); diff --git a/src/Microsoft.NetCore.Analyzers/Core/Runtime/DoNotPassLiteralsAsLocalizedParameters.cs b/src/Microsoft.NetCore.Analyzers/Core/Runtime/DoNotPassLiteralsAsLocalizedParameters.cs index f442a6609c..97a8251b2a 100644 --- a/src/Microsoft.NetCore.Analyzers/Core/Runtime/DoNotPassLiteralsAsLocalizedParameters.cs +++ b/src/Microsoft.NetCore.Analyzers/Core/Runtime/DoNotPassLiteralsAsLocalizedParameters.cs @@ -144,14 +144,14 @@ void AnalyzeArgument(IParameterSymbol parameter, IPropertySymbol? containingProp } // FxCop compat: Filter out xml string literals. - var filteredStrings = stringLiteralValues.Where(literal => literal != null && !LooksLikeXmlTag(literal)); + IEnumerable filteredStrings = stringLiteralValues.Where(literal => literal != null && !LooksLikeXmlTag(literal))!; if (filteredStrings.Any()) { // Method '{0}' passes a literal string as parameter '{1}' of a call to '{2}'. Retrieve the following string(s) from a resource table instead: "{3}". var arg1 = containingMethod.ToDisplayString(SymbolDisplayFormat.MinimallyQualifiedFormat); var arg2 = parameter.Name; var arg3 = parameter.ContainingSymbol.ToDisplayString(SymbolDisplayFormat.MinimallyQualifiedFormat); - var arg4 = FormatLiteralValues(filteredStrings!); + var arg4 = FormatLiteralValues(filteredStrings); var diagnostic = operation.CreateDiagnostic(Rule, arg1, arg2, arg3, arg4); reportDiagnostic(diagnostic); } diff --git a/src/Microsoft.NetCore.Analyzers/Core/Runtime/ProvideCorrectArgumentsToFormattingMethods.cs b/src/Microsoft.NetCore.Analyzers/Core/Runtime/ProvideCorrectArgumentsToFormattingMethods.cs index 5eea627596..9cd923db7d 100644 --- a/src/Microsoft.NetCore.Analyzers/Core/Runtime/ProvideCorrectArgumentsToFormattingMethods.cs +++ b/src/Microsoft.NetCore.Analyzers/Core/Runtime/ProvideCorrectArgumentsToFormattingMethods.cs @@ -94,11 +94,10 @@ public override void Initialize(AnalysisContext analysisContext) return; } - var arrayCreation = paramsArgument.Value as IArrayCreationOperation; - var elementType = arrayCreation.GetElementType(); - if (elementType == null || + if (!(paramsArgument.Value is IArrayCreationOperation arrayCreation) || + !(arrayCreation.GetElementType() is ITypeSymbol elementType) || !object.Equals(elementType, formatInfo.Object) || - arrayCreation!.DimensionSizes.Length != 1) + arrayCreation.DimensionSizes.Length != 1) { // wrong format return; diff --git a/src/Microsoft.NetCore.Analyzers/Core/Security/DoNotReferSelfInSerializableClass.cs b/src/Microsoft.NetCore.Analyzers/Core/Security/DoNotReferSelfInSerializableClass.cs index 4a5fc0fc00..b077161862 100644 --- a/src/Microsoft.NetCore.Analyzers/Core/Security/DoNotReferSelfInSerializableClass.cs +++ b/src/Microsoft.NetCore.Analyzers/Core/Security/DoNotReferSelfInSerializableClass.cs @@ -78,7 +78,7 @@ public sealed override void Initialize(AnalysisContext context) compilationStartAnalysisContext.RegisterSymbolAction( (SymbolAnalysisContext symbolAnalysisContext) => { - DrawGraph((ITypeSymbol)symbolAnalysisContext.Symbol); + DrawGraph((INamedTypeSymbol)symbolAnalysisContext.Symbol); }, SymbolKind.NamedType); compilationStartAnalysisContext.RegisterCompilationEndAction( @@ -131,9 +131,9 @@ void DrawGraph(ITypeSymbol point) } if (point.IsInSource() && - point.HasAttribute(serializableAttributeTypeSymbol!)) + point.HasAttribute(serializableAttributeTypeSymbol)) { - var fieldPoints = point.GetMembers().OfType().Where(s => !s.HasAttribute(nonSerializedAttribute!) && + var fieldPoints = point.GetMembers().OfType().Where(s => !s.HasAttribute(nonSerializedAttribute) && !s.IsStatic); foreach (var fieldPoint in fieldPoints) diff --git a/src/Microsoft.NetCore.Analyzers/Core/Security/DoNotUseDSA.cs b/src/Microsoft.NetCore.Analyzers/Core/Security/DoNotUseDSA.cs index 2f72f96c11..cc9c74fb5f 100644 --- a/src/Microsoft.NetCore.Analyzers/Core/Security/DoNotUseDSA.cs +++ b/src/Microsoft.NetCore.Analyzers/Core/Security/DoNotUseDSA.cs @@ -7,7 +7,6 @@ using Analyzer.Utilities.Extensions; using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.Diagnostics; -using Microsoft.CodeAnalysis.FlowAnalysis.DataFlow; using Microsoft.CodeAnalysis.Operations; namespace Microsoft.NetCore.Analyzers.Security diff --git a/src/Microsoft.NetCore.Analyzers/Core/Security/DoNotUseDeprecatedSecurityProtocols.cs b/src/Microsoft.NetCore.Analyzers/Core/Security/DoNotUseDeprecatedSecurityProtocols.cs index a55c30340b..da01b54113 100644 --- a/src/Microsoft.NetCore.Analyzers/Core/Security/DoNotUseDeprecatedSecurityProtocols.cs +++ b/src/Microsoft.NetCore.Analyzers/Core/Security/DoNotUseDeprecatedSecurityProtocols.cs @@ -187,7 +187,9 @@ public override void Initialize(AnalysisContext context) out bool isDeprecatedProtocol, out bool isHardCodedOkayProtocol) { - if (securityProtocolTypeTypeSymbol!.Equals(fieldReferenceOperation.Field.ContainingType)) + RoslynDebug.Assert(securityProtocolTypeTypeSymbol != null); + + if (securityProtocolTypeTypeSymbol.Equals(fieldReferenceOperation.Field.ContainingType)) { if (HardCodedSafeProtocolMetadataNames.Contains(fieldReferenceOperation.Field.Name)) { @@ -217,10 +219,12 @@ public override void Initialize(AnalysisContext context) bool IsAndEqualsServicePointManagerAssignment(ICompoundAssignmentOperation compoundAssignmentOperation) { + RoslynDebug.Assert(servicePointManagerTypeSymbol != null); + return compoundAssignmentOperation.OperatorKind == BinaryOperatorKind.And && compoundAssignmentOperation.Target is IPropertyReferenceOperation targetPropertyReference && targetPropertyReference.Instance == null - && servicePointManagerTypeSymbol!.Equals(targetPropertyReference.Property.ContainingType) + && servicePointManagerTypeSymbol.Equals(targetPropertyReference.Property.ContainingType) && targetPropertyReference.Property.MetadataName == "SecurityProtocol"; } }); diff --git a/src/Microsoft.NetCore.Analyzers/Core/Security/DoNotUseInsecureRandomness.cs b/src/Microsoft.NetCore.Analyzers/Core/Security/DoNotUseInsecureRandomness.cs index 0954a614f4..7300d31098 100644 --- a/src/Microsoft.NetCore.Analyzers/Core/Security/DoNotUseInsecureRandomness.cs +++ b/src/Microsoft.NetCore.Analyzers/Core/Security/DoNotUseInsecureRandomness.cs @@ -5,7 +5,6 @@ using Analyzer.Utilities.Extensions; using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.Diagnostics; -using Microsoft.CodeAnalysis.FlowAnalysis.DataFlow; using Microsoft.CodeAnalysis.Operations; namespace Microsoft.NetCore.Analyzers.Security diff --git a/src/Microsoft.NetCore.Analyzers/Core/Security/JsonNetTypeNameHandling.cs b/src/Microsoft.NetCore.Analyzers/Core/Security/JsonNetTypeNameHandling.cs index 0e93461a9f..853f767750 100644 --- a/src/Microsoft.NetCore.Analyzers/Core/Security/JsonNetTypeNameHandling.cs +++ b/src/Microsoft.NetCore.Analyzers/Core/Security/JsonNetTypeNameHandling.cs @@ -93,7 +93,8 @@ public override void Initialize(AnalysisContext analysisContext) bool IsOtherThanNone(IFieldReferenceOperation fieldReferenceOperation) { - if (!typeNameHandlingSymbol!.Equals(fieldReferenceOperation.Field.ContainingType)) + RoslynDebug.Assert(typeNameHandlingSymbol != null); + if (!typeNameHandlingSymbol.Equals(fieldReferenceOperation.Field.ContainingType)) { return false; } diff --git a/src/Microsoft.NetCore.Analyzers/Core/Security/SetViewStateUserKey.cs b/src/Microsoft.NetCore.Analyzers/Core/Security/SetViewStateUserKey.cs index 0757e296d7..333ffe2488 100644 --- a/src/Microsoft.NetCore.Analyzers/Core/Security/SetViewStateUserKey.cs +++ b/src/Microsoft.NetCore.Analyzers/Core/Security/SetViewStateUserKey.cs @@ -6,7 +6,6 @@ using Analyzer.Utilities.Extensions; using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.Diagnostics; -using Microsoft.CodeAnalysis.FlowAnalysis.DataFlow; using Microsoft.CodeAnalysis.Operations; namespace Microsoft.NetCore.Analyzers.Security diff --git a/src/Microsoft.NetCore.Analyzers/Core/Security/SslProtocolsAnalyzer.cs b/src/Microsoft.NetCore.Analyzers/Core/Security/SslProtocolsAnalyzer.cs index 5eeb71f1f8..51fe2cd44d 100644 --- a/src/Microsoft.NetCore.Analyzers/Core/Security/SslProtocolsAnalyzer.cs +++ b/src/Microsoft.NetCore.Analyzers/Core/Security/SslProtocolsAnalyzer.cs @@ -123,8 +123,8 @@ public override void Initialize(AnalysisContext context) break; case IVariableInitializerOperation variableInitializerOperation: - if (variableInitializerOperation.Value != null - && !sslProtocolsSymbol.Equals(variableInitializerOperation.Value.Type)) + if (variableInitializerOperation.Value == null + || !sslProtocolsSymbol.Equals(variableInitializerOperation.Value.Type)) { return; } @@ -213,7 +213,9 @@ public override void Initialize(AnalysisContext context) out bool isDeprecatedProtocol, out bool isHardcodedOkayProtocol) { - if (sslProtocolsSymbol!.Equals(fieldReferenceOperation.Field.ContainingType)) + RoslynDebug.Assert(sslProtocolsSymbol != null); + + if (sslProtocolsSymbol.Equals(fieldReferenceOperation.Field.ContainingType)) { if (HardcodedSslProtocolsMetadataNames.Contains(fieldReferenceOperation.Field.Name)) { diff --git a/src/Microsoft.NetCore.Analyzers/Core/Security/UseRSAWithSufficientKeySize.cs b/src/Microsoft.NetCore.Analyzers/Core/Security/UseRSAWithSufficientKeySize.cs index 2cd46ea9db..66f5213775 100644 --- a/src/Microsoft.NetCore.Analyzers/Core/Security/UseRSAWithSufficientKeySize.cs +++ b/src/Microsoft.NetCore.Analyzers/Core/Security/UseRSAWithSufficientKeySize.cs @@ -7,7 +7,6 @@ using Analyzer.Utilities.Extensions; using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.Diagnostics; -using Microsoft.CodeAnalysis.FlowAnalysis.DataFlow; using Microsoft.CodeAnalysis.Operations; namespace Microsoft.NetCore.Analyzers.Security diff --git a/src/Microsoft.NetFramework.Analyzers/CSharp/Helpers/SyntaxNodeHelper.cs b/src/Microsoft.NetFramework.Analyzers/CSharp/Helpers/SyntaxNodeHelper.cs index 9cea774135..e5bd2d42ff 100644 --- a/src/Microsoft.NetFramework.Analyzers/CSharp/Helpers/SyntaxNodeHelper.cs +++ b/src/Microsoft.NetFramework.Analyzers/CSharp/Helpers/SyntaxNodeHelper.cs @@ -6,6 +6,7 @@ using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.CSharp; using Microsoft.CodeAnalysis.CSharp.Syntax; +using System.Diagnostics.CodeAnalysis; namespace Microsoft.NetFramework.CSharp.Analyzers.Helpers { @@ -293,7 +294,7 @@ public override IEnumerable GetDescendantMemberAccessExpressionNodes return node.DescendantNodesAndSelf().OfType(); } - public override bool IsObjectCreationExpressionUnderFieldDeclaration(SyntaxNode? node) + public override bool IsObjectCreationExpressionUnderFieldDeclaration([NotNullWhen(returnValue: true)] SyntaxNode? node) { return node != null && node.Kind() == SyntaxKind.ObjectCreationExpression && @@ -304,7 +305,7 @@ public override bool IsObjectCreationExpressionUnderFieldDeclaration(SyntaxNode? { if (IsObjectCreationExpressionUnderFieldDeclaration(node)) { - return node!.AncestorsAndSelf().OfType().FirstOrDefault(); + return node.AncestorsAndSelf().OfType().FirstOrDefault(); } else { diff --git a/src/Roslyn.Diagnostics.Analyzers/Core/ImportingConstructorShouldBeObsoleteCodeFixProvider.cs b/src/Roslyn.Diagnostics.Analyzers/Core/ImportingConstructorShouldBeObsoleteCodeFixProvider.cs index 0c6ca05e9b..ae2631ef47 100644 --- a/src/Roslyn.Diagnostics.Analyzers/Core/ImportingConstructorShouldBeObsoleteCodeFixProvider.cs +++ b/src/Roslyn.Diagnostics.Analyzers/Core/ImportingConstructorShouldBeObsoleteCodeFixProvider.cs @@ -236,14 +236,12 @@ private async Task SetErrorToTrueAsync(Document document, TextSpan sou private static SyntaxNode GenerateDescriptionArgument(SyntaxGenerator generator, SemanticModel semanticModel) { - var mefConstructionType = semanticModel.Compilation.GetOrCreateTypeByMetadataName(WellKnownTypeNames.MicrosoftCodeAnalysisHostMefMefConstruction); - var knownConstant = mefConstructionType?.GetMembers("ImportingConstructorMessage").OfType().Any(); - SyntaxNode attributeArgument; - if (knownConstant is object) + if (semanticModel.Compilation.TryGetOrCreateTypeByMetadataName(WellKnownTypeNames.MicrosoftCodeAnalysisHostMefMefConstruction, out var mefConstructionType) && + mefConstructionType?.GetMembers("ImportingConstructorMessage").OfType().Any() is object) { attributeArgument = generator.MemberAccessExpression( - generator.TypeExpressionForStaticMemberAccess(mefConstructionType!), + generator.TypeExpressionForStaticMemberAccess(mefConstructionType), generator.IdentifierName("ImportingConstructorMessage")); } else diff --git a/src/Tools/ReleaseNotesUtil/FixerExtensions.cs b/src/Tools/ReleaseNotesUtil/FixerExtensions.cs index f3d2dd7381..994da9781d 100644 --- a/src/Tools/ReleaseNotesUtil/FixerExtensions.cs +++ b/src/Tools/ReleaseNotesUtil/FixerExtensions.cs @@ -80,8 +80,7 @@ private static bool HasImplementation(CodeFixProvider fixer) // { // return Task.CompletedTask; // } - byte[]? methodBodyIL = method?.GetMethodBody()?.GetILAsByteArray(); - if (methodBodyIL != null + if (method?.GetMethodBody()?.GetILAsByteArray() is { } methodBodyIL && methodBodyIL.Length == 6 && methodBodyIL[0] == 0x28 // call && methodBodyIL[5] == 0x2a) // ret @@ -92,7 +91,7 @@ private static bool HasImplementation(CodeFixProvider fixer) } int metadataToken = BitConverter.ToInt32(methodBodyIL, 1); - MethodBase calledMethod = method!.Module.ResolveMethod(metadataToken); + MethodBase calledMethod = method.Module.ResolveMethod(metadataToken); if (calledMethod != null && calledMethod.DeclaringType.FullName == "System.Threading.Tasks.Task" && calledMethod.Name == "get_CompletedTask") diff --git a/src/Tools/ReleaseNotesUtil/Program.cs b/src/Tools/ReleaseNotesUtil/Program.cs index c00388db68..32fd8f794b 100644 --- a/src/Tools/ReleaseNotesUtil/Program.cs +++ b/src/Tools/ReleaseNotesUtil/Program.cs @@ -7,6 +7,7 @@ using System.Linq; using System.Runtime.Serialization.Json; using System.Text; +using Analyzer.Utilities; using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.Diagnostics; @@ -67,13 +68,13 @@ private static void GetRulesJson(string nugetInstalledPackagesPath, string versi RuleFileContent newContent = ReadRuleFileContent(newRulesJsonPath); // If we have the latest rules, we can backfill missing help link URLs. - if (!string.IsNullOrWhiteSpace(latestRulesJsonPath)) + if (!RoslynString.IsNullOrWhiteSpace(latestRulesJsonPath)) { - RuleFileContent latestContent = ReadRuleFileContent(latestRulesJsonPath!); + RuleFileContent latestContent = ReadRuleFileContent(latestRulesJsonPath); Dictionary latestRulesById = latestContent.Rules.ToDictionary(r => r.Id); foreach (RuleInfo rule in oldContent.Rules.Concat(newContent.Rules)) { - if (string.IsNullOrWhiteSpace(rule.HelpLink) + if (RoslynString.IsNullOrWhiteSpace(rule.HelpLink) && latestRulesById.TryGetValue(rule.Id, out RuleInfo latestRule)) { rule.HelpLink = latestRule.HelpLink; diff --git a/src/Tools/ReleaseNotesUtil/ReleaseNotesUtil.csproj b/src/Tools/ReleaseNotesUtil/ReleaseNotesUtil.csproj index 07330a43c6..9aa051d747 100644 --- a/src/Tools/ReleaseNotesUtil/ReleaseNotesUtil.csproj +++ b/src/Tools/ReleaseNotesUtil/ReleaseNotesUtil.csproj @@ -3,7 +3,11 @@ Exe netcoreapp2.0 false - + + + + + diff --git a/src/Utilities/Compiler/Analyzer.Utilities.projitems b/src/Utilities/Compiler/Analyzer.Utilities.projitems index 0387cb4b05..39c021fe23 100644 --- a/src/Utilities/Compiler/Analyzer.Utilities.projitems +++ b/src/Utilities/Compiler/Analyzer.Utilities.projitems @@ -11,8 +11,7 @@ $(DefineConstants);HAS_IOPERATION true - - @@ -38,6 +37,7 @@ + @@ -76,6 +76,7 @@ + diff --git a/src/Utilities/Compiler/Debug.cs b/src/Utilities/Compiler/Debug.cs new file mode 100644 index 0000000000..1ddd73433e --- /dev/null +++ b/src/Utilities/Compiler/Debug.cs @@ -0,0 +1,19 @@ +// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; + +namespace Analyzer.Utilities +{ + internal static class RoslynDebug + { + /// + [Conditional("DEBUG")] + public static void Assert([DoesNotReturnIf(false)]bool b) => Debug.Assert(b); + + /// + [Conditional("DEBUG")] + public static void Assert([DoesNotReturnIf(false)]bool b, string message) + => Debug.Assert(b, message); + } +} diff --git a/src/Utilities/Compiler/DoNotCatchGeneralUnlessRethrown.cs b/src/Utilities/Compiler/DoNotCatchGeneralUnlessRethrown.cs index 0111196e3a..0d3c809968 100644 --- a/src/Utilities/Compiler/DoNotCatchGeneralUnlessRethrown.cs +++ b/src/Utilities/Compiler/DoNotCatchGeneralUnlessRethrown.cs @@ -61,7 +61,7 @@ public override void Initialize(AnalysisContext analysisContext) var method = (IMethodSymbol)operationBlockAnalysisContext.OwningSymbol; - if (RequiresAttributeOnMethod && !MethodHasAttribute(method, requiredAttributeType!)) + if (RequiresAttributeOnMethod && !method.HasAttribute(requiredAttributeType)) { return; } @@ -82,12 +82,8 @@ public override void Initialize(AnalysisContext analysisContext) private INamedTypeSymbol? GetRequiredAttributeType(Compilation compilation) { - return compilation.GetOrCreateTypeByMetadataName(_enablingMethodAttributeFullyQualifiedName!); - } - - private bool MethodHasAttribute(IMethodSymbol method, INamedTypeSymbol attributeType) - { - return method.GetAttributes().Any(attribute => attribute.AttributeClass.Equals(attributeType)); + RoslynDebug.Assert(_enablingMethodAttributeFullyQualifiedName != null); + return compilation.GetOrCreateTypeByMetadataName(_enablingMethodAttributeFullyQualifiedName); } private static IReadOnlyCollection GetDisallowedCatchTypes(Compilation compilation) diff --git a/src/Utilities/Compiler/Extensions/ITypeSymbolExtensions.cs b/src/Utilities/Compiler/Extensions/ITypeSymbolExtensions.cs index f04b1bf01a..0bf71243f1 100644 --- a/src/Utilities/Compiler/Extensions/ITypeSymbolExtensions.cs +++ b/src/Utilities/Compiler/Extensions/ITypeSymbolExtensions.cs @@ -33,7 +33,7 @@ public static bool IsPrimitiveType(this ITypeSymbol type) } } - public static bool Inherits(this ITypeSymbol? type, ITypeSymbol? possibleBase) + public static bool Inherits([NotNullWhen(returnValue: true)] this ITypeSymbol? type, [NotNullWhen(returnValue: true)] ITypeSymbol? possibleBase) { if (type == null || possibleBase == null) { @@ -128,13 +128,13 @@ public static bool DerivesFrom([NotNullWhen(returnValue: true)] this ITypeSymbol /// /// Indicates if the given implements . /// - public static bool ImplementsIDisposable(this ITypeSymbol type, INamedTypeSymbol? iDisposable) + public static bool ImplementsIDisposable(this ITypeSymbol type, [NotNullWhen(returnValue: true)] INamedTypeSymbol? iDisposable) => iDisposable != null && type.AllInterfaces.Contains(iDisposable); /// /// Indicates if the given is a reference type that implements or is type itself. /// - public static bool IsDisposable(this ITypeSymbol type, INamedTypeSymbol? iDisposable) + public static bool IsDisposable(this ITypeSymbol type, [NotNullWhen(returnValue: true)] INamedTypeSymbol? iDisposable) => type.IsReferenceType && (Equals(type, iDisposable) || type.ImplementsIDisposable(iDisposable)); /// @@ -266,16 +266,16 @@ public static bool IsAttribute(this ITypeSymbol symbol) public static bool HasValueCopySemantics(this ITypeSymbol typeSymbol) => typeSymbol.IsValueType || typeSymbol.SpecialType == SpecialType.System_String; - public static bool IsNonNullableValueType(this ITypeSymbol typeSymbol) + public static bool IsNonNullableValueType([NotNullWhen(returnValue: true)] this ITypeSymbol? typeSymbol) => typeSymbol != null && typeSymbol.IsValueType && typeSymbol.OriginalDefinition.SpecialType != SpecialType.System_Nullable_T; - public static bool IsNullableValueType(this ITypeSymbol typeSymbol) + public static bool IsNullableValueType([NotNullWhen(returnValue: true)] this ITypeSymbol? typeSymbol) => typeSymbol != null && typeSymbol.IsValueType && typeSymbol.OriginalDefinition.SpecialType == SpecialType.System_Nullable_T; - public static bool IsReferenceTypeOrNullableValueType(this ITypeSymbol typeSymbol) + public static bool IsReferenceTypeOrNullableValueType([NotNullWhen(returnValue: true)] this ITypeSymbol? typeSymbol) => typeSymbol != null && (typeSymbol.IsReferenceType || typeSymbol.IsNullableValueType()); - public static bool IsNullableOfBoolean(this ITypeSymbol typeSymbol) + public static bool IsNullableOfBoolean([NotNullWhen(returnValue: true)] this ITypeSymbol? typeSymbol) => typeSymbol.IsNullableValueType() && ((INamedTypeSymbol)typeSymbol).TypeArguments[0].SpecialType == SpecialType.System_Boolean; #if HAS_IOPERATION diff --git a/src/Utilities/Compiler/Options/CategorizedAnalyzerConfigOptions.cs b/src/Utilities/Compiler/Options/CategorizedAnalyzerConfigOptions.cs index 8845a16e70..10b9a5c72b 100644 --- a/src/Utilities/Compiler/Options/CategorizedAnalyzerConfigOptions.cs +++ b/src/Utilities/Compiler/Options/CategorizedAnalyzerConfigOptions.cs @@ -36,7 +36,7 @@ internal sealed class CategorizedAnalyzerConfigOptions ImmutableDictionary.Empty, ImmutableDictionary>.Empty); - private readonly ConcurrentDictionary _computedOptionValuesMap; + private readonly ConcurrentDictionary _computedOptionValuesMap; private CategorizedAnalyzerConfigOptions( ImmutableDictionary generalOptions, @@ -44,7 +44,7 @@ internal sealed class CategorizedAnalyzerConfigOptions { GeneralOptions = generalOptions; SpecificOptions = specificOptions; - _computedOptionValuesMap = new ConcurrentDictionary(); + _computedOptionValuesMap = new ConcurrentDictionary(); } public ImmutableDictionary GeneralOptions { get; } @@ -113,7 +113,7 @@ public T GetOptionValue(string optionName, DiagnosticDescriptor rule, TryPars return defaultValue; } - return (T)_computedOptionValuesMap.GetOrAdd($"{rule.Id}.{optionName}", _ => ComputeOptionValue(optionName, rule, tryParseValue, defaultValue)!); + return (T)_computedOptionValuesMap.GetOrAdd($"{rule.Id}.{optionName}", _ => ComputeOptionValue(optionName, rule, tryParseValue, defaultValue))!; } private T ComputeOptionValue(string optionName, DiagnosticDescriptor rule, TryParseValue tryParseValue, T defaultValue) diff --git a/src/Utilities/Compiler/Options/SymbolNamesOption.cs b/src/Utilities/Compiler/Options/SymbolNamesOption.cs index af81a1f04b..0cbef5ae71 100644 --- a/src/Utilities/Compiler/Options/SymbolNamesOption.cs +++ b/src/Utilities/Compiler/Options/SymbolNamesOption.cs @@ -8,7 +8,7 @@ namespace Analyzer.Utilities { - internal sealed class SymbolNamesOption : IEquatable + internal sealed class SymbolNamesOption : IEquatable { public static readonly SymbolNamesOption Empty = new SymbolNamesOption(); diff --git a/src/Utilities/Compiler/RoslynString.cs b/src/Utilities/Compiler/RoslynString.cs new file mode 100644 index 0000000000..bd8b377693 --- /dev/null +++ b/src/Utilities/Compiler/RoslynString.cs @@ -0,0 +1,21 @@ +// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +#nullable enable + +using System.Diagnostics.CodeAnalysis; + +namespace Analyzer.Utilities +{ + internal static class RoslynString + { + /// + public static bool IsNullOrEmpty([NotNullWhen(returnValue: false)] string? value) + => string.IsNullOrEmpty(value); + +#if !NET20 + /// + public static bool IsNullOrWhiteSpace([NotNullWhen(returnValue: false)] string? value) + => string.IsNullOrWhiteSpace(value); +#endif + } +} diff --git a/src/Utilities/FlowAnalysis/FlowAnalysis/Analysis/DisposeAnalysis/DisposeAnalysisHelper.cs b/src/Utilities/FlowAnalysis/FlowAnalysis/Analysis/DisposeAnalysis/DisposeAnalysisHelper.cs index d8d5436564..c2ff87e9df 100644 --- a/src/Utilities/FlowAnalysis/FlowAnalysis/Analysis/DisposeAnalysis/DisposeAnalysisHelper.cs +++ b/src/Utilities/FlowAnalysis/FlowAnalysis/Analysis/DisposeAnalysis/DisposeAnalysisHelper.cs @@ -145,7 +145,9 @@ public bool HasAnyDisposableCreationDescendant(ImmutableArray operat public ImmutableHashSet GetDisposableFields(INamedTypeSymbol namedType) { EnsureDisposableFieldsMap(); - if (_lazyDisposableFieldsMap!.TryGetValue(namedType, out ImmutableHashSet disposableFields)) + RoslynDebug.Assert(_lazyDisposableFieldsMap != null); + + if (_lazyDisposableFieldsMap.TryGetValue(namedType, out ImmutableHashSet disposableFields)) { return disposableFields; } diff --git a/src/Utilities/FlowAnalysis/FlowAnalysis/Analysis/ParameterValidationAnalysis/ParameterValidationAnalysis.ParameterValidationDataFlowOperationVisitor.cs b/src/Utilities/FlowAnalysis/FlowAnalysis/Analysis/ParameterValidationAnalysis/ParameterValidationAnalysis.ParameterValidationDataFlowOperationVisitor.cs index 990df51c0d..00ac05fb1e 100644 --- a/src/Utilities/FlowAnalysis/FlowAnalysis/Analysis/ParameterValidationAnalysis/ParameterValidationAnalysis.ParameterValidationDataFlowOperationVisitor.cs +++ b/src/Utilities/FlowAnalysis/FlowAnalysis/Analysis/ParameterValidationAnalysis/ParameterValidationAnalysis.ParameterValidationDataFlowOperationVisitor.cs @@ -5,6 +5,7 @@ using System.Collections.Immutable; using System.Diagnostics; using System.Linq; +using Analyzer.Utilities; using Analyzer.Utilities.Extensions; using Microsoft.CodeAnalysis.FlowAnalysis.DataFlow.PointsToAnalysis; using Microsoft.CodeAnalysis.Operations; @@ -39,8 +40,8 @@ public ParameterValidationDataFlowOperationVisitor(ParameterValidationAnalysisCo { get { - Debug.Assert(_hazardousParameterUsageBuilderOpt != null); - return _hazardousParameterUsageBuilderOpt!.ToImmutable(); + RoslynDebug.Assert(_hazardousParameterUsageBuilderOpt != null); + return _hazardousParameterUsageBuilderOpt.ToImmutable(); } } @@ -177,14 +178,14 @@ private void HandlePotentiallyHazardousOperation(IOperation operation, IEnumerab private void HandleHazardousOperation(SyntaxNode syntaxNode, IEnumerable nonValidatedLocations) { - Debug.Assert(_hazardousParameterUsageBuilderOpt != null); + RoslynDebug.Assert(_hazardousParameterUsageBuilderOpt != null); foreach (var location in nonValidatedLocations) { Debug.Assert(IsNotOrMaybeValidatedLocation(location)); var parameter = (IParameterSymbol)location.SymbolOpt!; - if (!_hazardousParameterUsageBuilderOpt!.TryGetValue(parameter, out SyntaxNode currentSyntaxNode) || + if (!_hazardousParameterUsageBuilderOpt.TryGetValue(parameter, out SyntaxNode currentSyntaxNode) || syntaxNode.SpanStart < currentSyntaxNode.SpanStart) { _hazardousParameterUsageBuilderOpt[parameter] = syntaxNode; diff --git a/src/Utilities/FlowAnalysis/FlowAnalysis/Analysis/TaintedDataAnalysis/TaintedDataConfig.cs b/src/Utilities/FlowAnalysis/FlowAnalysis/Analysis/TaintedDataAnalysis/TaintedDataConfig.cs index ffcc69662b..c84ef1820a 100644 --- a/src/Utilities/FlowAnalysis/FlowAnalysis/Analysis/TaintedDataAnalysis/TaintedDataConfig.cs +++ b/src/Utilities/FlowAnalysis/FlowAnalysis/Analysis/TaintedDataAnalysis/TaintedDataConfig.cs @@ -8,7 +8,6 @@ using System.Threading; using Analyzer.Utilities.PooledObjects; using Microsoft.CodeAnalysis; -using Microsoft.CodeAnalysis.FlowAnalysis.DataFlow; namespace Analyzer.Utilities.FlowAnalysis.Analysis.TaintedDataAnalysis { diff --git a/src/Utilities/FlowAnalysis/FlowAnalysis/Framework/DataFlow/AddressSharedEntitiesProvider.cs b/src/Utilities/FlowAnalysis/FlowAnalysis/Framework/DataFlow/AddressSharedEntitiesProvider.cs index b71fd0a15d..da87d21c1e 100644 --- a/src/Utilities/FlowAnalysis/FlowAnalysis/Framework/DataFlow/AddressSharedEntitiesProvider.cs +++ b/src/Utilities/FlowAnalysis/FlowAnalysis/Framework/DataFlow/AddressSharedEntitiesProvider.cs @@ -3,6 +3,7 @@ using System.Collections.Immutable; using System.Diagnostics; using System.Linq; +using Analyzer.Utilities; using Analyzer.Utilities.PooledObjects; namespace Microsoft.CodeAnalysis.FlowAnalysis.DataFlow.CopyAnalysis @@ -52,9 +53,12 @@ public void UpdateAddressSharedEntitiesForParameter(IParameterSymbol parameter, ImmutableHashSet ComputeAddressSharedEntities() { + RoslynDebug.Assert(assignedValueOpt != null); + RoslynDebug.Assert(assignedValueOpt.AnalysisEntityOpt != null); + var builder = PooledHashSet.GetInstance(); AddIfHasKnownInstanceLocation(analysisEntity, builder); - AddIfHasKnownInstanceLocation(assignedValueOpt!.AnalysisEntityOpt!, builder); + AddIfHasKnownInstanceLocation(assignedValueOpt.AnalysisEntityOpt, builder); // We need to handle multiple ref/out parameters passed the same location. // For example, "M(ref a, ref a);" diff --git a/src/Utilities/FlowAnalysis/FlowAnalysis/Framework/DataFlow/AnalysisEntityDataFlowOperationVisitor.cs b/src/Utilities/FlowAnalysis/FlowAnalysis/Framework/DataFlow/AnalysisEntityDataFlowOperationVisitor.cs index 37392537f5..ee52e1abe9 100644 --- a/src/Utilities/FlowAnalysis/FlowAnalysis/Framework/DataFlow/AnalysisEntityDataFlowOperationVisitor.cs +++ b/src/Utilities/FlowAnalysis/FlowAnalysis/Framework/DataFlow/AnalysisEntityDataFlowOperationVisitor.cs @@ -5,6 +5,7 @@ using System.Collections.Immutable; using System.Diagnostics; using System.Linq; +using Analyzer.Utilities; using Analyzer.Utilities.Extensions; using Analyzer.Utilities.PooledObjects; using Analyzer.Utilities.PooledObjects.Extensions; @@ -647,11 +648,13 @@ protected override void SetPredicateValueKind(IOperation operation, TAnalysisDat // Local functions. bool AddWorklistEntityAndPointsToValue(AnalysisEntity? analysisEntityOpt) { + RoslynDebug.Assert(pointsToValuesOpt != null); + if (analysisEntityOpt != null && candidateEntitiesBuilder.Contains(analysisEntityOpt)) { worklistEntities.Add(analysisEntityOpt); - if (pointsToValuesOpt!.TryGetValue(analysisEntityOpt, out var pointsToValue)) + if (pointsToValuesOpt.TryGetValue(analysisEntityOpt, out var pointsToValue)) { AddWorklistPointsToValue(pointsToValue); } diff --git a/src/Utilities/FlowAnalysis/FlowAnalysis/Framework/DataFlow/AnalysisEntityFactory.cs b/src/Utilities/FlowAnalysis/FlowAnalysis/Framework/DataFlow/AnalysisEntityFactory.cs index 9ced1a4ca1..80264d58e2 100644 --- a/src/Utilities/FlowAnalysis/FlowAnalysis/Framework/DataFlow/AnalysisEntityFactory.cs +++ b/src/Utilities/FlowAnalysis/FlowAnalysis/Framework/DataFlow/AnalysisEntityFactory.cs @@ -332,7 +332,7 @@ public bool TryCreateForTupleElements(ITupleOperation tupleOperation, [NotNullWh } } - Debug.Assert(parentEntity != null); + RoslynDebug.Assert(parentEntity != null); } else { @@ -340,7 +340,7 @@ public bool TryCreateForTupleElements(ITupleOperation tupleOperation, [NotNullWh underlyingValueTupleType, instanceLocation, parentOpt: null); } - Debug.Assert(parentEntity!.InstanceLocation == instanceLocation); + Debug.Assert(parentEntity.InstanceLocation == instanceLocation); var builder = ArrayBuilder.GetInstance(tupleType.TupleElements.Length); foreach (var field in tupleType.TupleElements) diff --git a/src/Utilities/FlowAnalysis/FlowAnalysis/Framework/DataFlow/DataFlowAnalysis.cs b/src/Utilities/FlowAnalysis/FlowAnalysis/Framework/DataFlow/DataFlowAnalysis.cs index cfca744b81..9e40d67639 100644 --- a/src/Utilities/FlowAnalysis/FlowAnalysis/Framework/DataFlow/DataFlowAnalysis.cs +++ b/src/Utilities/FlowAnalysis/FlowAnalysis/Framework/DataFlow/DataFlowAnalysis.cs @@ -117,8 +117,10 @@ protected DataFlowAnalysis(AbstractAnalysisDomain analysisDomain, if (analysisContext.ExceptionPathsAnalysis) { + RoslynDebug.Assert(normalPathsExitBlockData != null); + // Clone and save exit block data - normalPathsExitBlockData = AnalysisDomain.Clone(normalPathsExitBlockData!); + normalPathsExitBlockData = AnalysisDomain.Clone(normalPathsExitBlockData); OperationVisitor.ExecutingExceptionPathsAnalysisPostPass = true; foreach (var block in cfg.Blocks) diff --git a/src/Utilities/FlowAnalysis/FlowAnalysis/Framework/DataFlow/DataFlowOperationVisitor.cs b/src/Utilities/FlowAnalysis/FlowAnalysis/Framework/DataFlow/DataFlowOperationVisitor.cs index d0e65ac1e4..4bdf244051 100644 --- a/src/Utilities/FlowAnalysis/FlowAnalysis/Framework/DataFlow/DataFlowOperationVisitor.cs +++ b/src/Utilities/FlowAnalysis/FlowAnalysis/Framework/DataFlow/DataFlowOperationVisitor.cs @@ -120,9 +120,9 @@ protected TAnalysisData CurrentAnalysisData { get { - Debug.Assert(_currentAnalysisData != null); - Debug.Assert(!_currentAnalysisData!.IsDisposed); - return _currentAnalysisData!; + RoslynDebug.Assert(_currentAnalysisData != null); + Debug.Assert(!_currentAnalysisData.IsDisposed); + return _currentAnalysisData; } private set { @@ -484,7 +484,8 @@ private void OnStartEntryBlockAnalysis(BasicBlock entryBlock) { var result = AnalysisEntityFactory.TryCreateForSymbolDeclaration(parameter, out var analysisEntity); Debug.Assert(result); - builder.Add(parameter, analysisEntity!); + RoslynDebug.Assert(analysisEntity != null); + builder.Add(parameter, analysisEntity); ArgumentInfo? assignedValueOpt = null; if (argumentValuesMap.TryGetValue(parameter.OriginalDefinition, out var argumentInfo)) @@ -615,9 +616,10 @@ protected bool IsParameterEntityForCurrentMethod(AnalysisEntity analysisEntity) bool isConditionalBranchNeverTaken() { + RoslynDebug.Assert(branch.BranchValueOpt != null); Debug.Assert(branch.ControlFlowConditionKind != ControlFlowConditionKind.None); - if (branch.BranchValueOpt!.Type?.SpecialType == SpecialType.System_Boolean && + if (branch.BranchValueOpt.Type?.SpecialType == SpecialType.System_Boolean && branch.BranchValueOpt.ConstantValue.HasValue) { var alwaysTrue = (bool)branch.BranchValueOpt.ConstantValue.Value; @@ -795,8 +797,8 @@ protected virtual void HandlePossibleThrowingOperation(IOperation operation) } data = GetMergedAnalysisDataForPossibleThrowingOperation(data, operation); - Debug.Assert(data != null); - AssertValidAnalysisData(data!); + RoslynDebug.Assert(data != null); + AssertValidAnalysisData(data); AnalysisDataForUnhandledThrowOperations[DefaultThrownExceptionInfo] = data!; } @@ -1011,16 +1013,16 @@ protected ImmutableHashSet GetEscapedLocations(AnalysisEntity protected bool TryGetPointsToAbstractValueAtEntryBlockEnd(AnalysisEntity analysisEntity, out PointsToAbstractValue pointsToAbstractValue) { Debug.Assert(CurrentBasicBlock.Kind == BasicBlockKind.Entry); - Debug.Assert(DataFlowAnalysisContext.PointsToAnalysisResultOpt != null); + RoslynDebug.Assert(DataFlowAnalysisContext.PointsToAnalysisResultOpt != null); - var outputData = DataFlowAnalysisContext.PointsToAnalysisResultOpt!.EntryBlockOutput.Data; + var outputData = DataFlowAnalysisContext.PointsToAnalysisResultOpt.EntryBlockOutput.Data; return outputData.TryGetValue(analysisEntity, out pointsToAbstractValue); } protected bool TryGetNullAbstractValueAtCurrentBlockEntry(AnalysisEntity analysisEntity, out NullAbstractValue nullAbstractValue) { - Debug.Assert(DataFlowAnalysisContext.PointsToAnalysisResultOpt != null); - var inputData = DataFlowAnalysisContext.PointsToAnalysisResultOpt![CurrentBasicBlock].Data; + RoslynDebug.Assert(DataFlowAnalysisContext.PointsToAnalysisResultOpt != null); + var inputData = DataFlowAnalysisContext.PointsToAnalysisResultOpt[CurrentBasicBlock].Data; if (inputData.TryGetValue(analysisEntity, out PointsToAbstractValue pointsToAbstractValue)) { nullAbstractValue = pointsToAbstractValue.NullState; @@ -1033,8 +1035,8 @@ protected bool TryGetNullAbstractValueAtCurrentBlockEntry(AnalysisEntity analysi protected bool TryGetMergedNullAbstractValueAtUnhandledThrowOperationsInGraph(AnalysisEntity analysisEntity, out NullAbstractValue nullAbstractValue) { - Debug.Assert(DataFlowAnalysisContext.PointsToAnalysisResultOpt != null); - var inputData = DataFlowAnalysisContext.PointsToAnalysisResultOpt!.MergedStateForUnhandledThrowOperationsOpt?.Data; + RoslynDebug.Assert(DataFlowAnalysisContext.PointsToAnalysisResultOpt != null); + var inputData = DataFlowAnalysisContext.PointsToAnalysisResultOpt.MergedStateForUnhandledThrowOperationsOpt?.Data; if (inputData == null || !inputData.TryGetValue(analysisEntity, out PointsToAbstractValue pointsToAbstractValue)) { nullAbstractValue = NullAbstractValue.MaybeNull; @@ -1292,7 +1294,8 @@ private void PerformPredicateAnalysis(IOperation operation) // FC = FCR0 var result = AnalysisEntityFactory.TryCreate(operation, out AnalysisEntity? flowCaptureReferenceEntity); Debug.Assert(result); - Debug.Assert(flowCaptureReferenceEntity!.CaptureIdOpt != null); + RoslynDebug.Assert(flowCaptureReferenceEntity != null); + RoslynDebug.Assert(flowCaptureReferenceEntity.CaptureIdOpt != null); Debug.Assert(HasPredicatedDataForEntity(flowCaptureReferenceEntity)); TransferPredicatedData(fromEntity: flowCaptureReferenceEntity, toEntity: predicatedFlowCaptureEntityOpt); } @@ -1471,7 +1474,8 @@ private void PerformPredicateAnalysisCore(IOperation operation, TAnalysisData ta case IFlowCaptureReferenceOperation _: var result = AnalysisEntityFactory.TryCreate(operation, out AnalysisEntity? flowCaptureReferenceEntity); Debug.Assert(result); - Debug.Assert(flowCaptureReferenceEntity!.CaptureIdOpt != null); + RoslynDebug.Assert(flowCaptureReferenceEntity != null); + RoslynDebug.Assert(flowCaptureReferenceEntity.CaptureIdOpt != null); if (!HasPredicatedDataForEntity(targetAnalysisData, flowCaptureReferenceEntity)) { return; @@ -1913,11 +1917,12 @@ private void ApplyInterproceduralAnalysisDataForUnhandledThrowOperations(Diction // Local functions void ApplyInterproceduralAnalysisDataForUnhandledThrowOperation(ThrownExceptionInfo exceptionInfo, TAnalysisData analysisDataAtException) { + RoslynDebug.Assert(AnalysisDataForUnhandledThrowOperations != null); AssertValidAnalysisData(analysisDataAtException); ApplyMissingCurrentAnalysisDataForUnhandledExceptionData(analysisDataAtException, exceptionInfo); AssertValidAnalysisData(analysisDataAtException); - if (!AnalysisDataForUnhandledThrowOperations!.TryGetValue(exceptionInfo, out var existingAnalysisDataAtException)) + if (!AnalysisDataForUnhandledThrowOperations.TryGetValue(exceptionInfo, out var existingAnalysisDataAtException)) { AnalysisDataForUnhandledThrowOperations.Add(exceptionInfo, analysisDataAtException); } @@ -2086,18 +2091,20 @@ protected bool TryGetInterproceduralAnalysisResult(IOperation operation, [NotNul interproceduralAnalysisData?.InitialAnalysisData?.Dispose(); } - Debug.Assert(invokedMethod.ReturnsVoid == !analysisResult.ReturnValueAndPredicateKindOpt.HasValue); + RoslynDebug.Assert(invokedMethod.ReturnsVoid == !analysisResult.ReturnValueAndPredicateKindOpt.HasValue); if (invokedMethod.ReturnsVoid) { return defaultValue; } + RoslynDebug.Assert(analysisResult.ReturnValueAndPredicateKindOpt != null); + if (PredicateAnalysis) { - SetPredicateValueKind(originalOperation, CurrentAnalysisData, analysisResult.ReturnValueAndPredicateKindOpt!.Value.PredicateValueKind); + SetPredicateValueKind(originalOperation, CurrentAnalysisData, analysisResult.ReturnValueAndPredicateKindOpt.Value.PredicateValueKind); } - return analysisResult.ReturnValueAndPredicateKindOpt!.Value.Value; + return analysisResult.ReturnValueAndPredicateKindOpt.Value.Value; // Local functions TAbstractAnalysisValue ResetAnalysisDataAndReturnDefaultValue() @@ -2131,12 +2138,14 @@ void ResetAnalysisData() InterproceduralAnalysisData ComputeInterproceduralAnalysisData() { + RoslynDebug.Assert(cfg != null); + var invocationInstance = GetInvocationInstance(); var thisOrMeInstance = GetThisOrMeInstance(); var argumentValuesMap = GetArgumentValues(ref invocationInstance); - var pointsToValuesOpt = pointsToAnalysisResultOpt?[cfg!.GetEntry()].Data; - var copyValuesOpt = copyAnalysisResultOpt?[cfg!.GetEntry()].Data; - var valueContentValuesOpt = valueContentAnalysisResultOpt?[cfg!.GetEntry()].Data; + var pointsToValuesOpt = pointsToAnalysisResultOpt?[cfg.GetEntry()].Data; + var copyValuesOpt = copyAnalysisResultOpt?[cfg.GetEntry()].Data; + var valueContentValuesOpt = valueContentAnalysisResultOpt?[cfg.GetEntry()].Data; var initialAnalysisData = GetInitialInterproceduralAnalysisData(invokedMethod, invocationInstance, thisOrMeInstance, argumentValuesMap, pointsToValuesOpt, copyValuesOpt, valueContentValuesOpt, isLambdaOrLocalFunction, hasParameterWithDelegateType); @@ -2268,12 +2277,14 @@ IParameterSymbol GetMappedParameterForArgument(IArgumentOperation argumentOperat ImmutableDictionary GetCapturedVariablesMap() { + RoslynDebug.Assert(cfg != null); + if (!isLambdaOrLocalFunction) { return ImmutableDictionary.Empty; } - var capturedVariables = cfg!.OriginalOperation.GetCaptures(invokedMethod); + var capturedVariables = cfg.OriginalOperation.GetCaptures(invokedMethod); try { if (capturedVariables.Count == 0) @@ -2294,8 +2305,8 @@ IParameterSymbol GetMappedParameterForArgument(IArgumentOperation argumentOperat var success = AnalysisEntityFactory.TryCreateForSymbolDeclaration(capturedVariable, out var capturedEntity); Debug.Assert(success); - - builder.Add(capturedVariable, capturedEntity!.InstanceLocation); + RoslynDebug.Assert(capturedEntity != null); + builder.Add(capturedVariable, capturedEntity.InstanceLocation); } return builder.ToImmutable(); @@ -2568,7 +2579,8 @@ void PerformFlowCaptureReferencePredicateAnalysis() var result = AnalysisEntityFactory.TryCreate(operation, out var flowCaptureReferenceEntity); Debug.Assert(result); - Debug.Assert(flowCaptureReferenceEntity!.CaptureIdOpt != null); + RoslynDebug.Assert(flowCaptureReferenceEntity != null); + RoslynDebug.Assert(flowCaptureReferenceEntity.CaptureIdOpt != null); if (!HasPredicatedDataForEntity(flowCaptureReferenceEntity)) { return; @@ -3052,7 +3064,9 @@ TAnalysisData AnalyzePossibleTargetInvocation(Func compu return DataFlowAnalysisContext.InterproceduralAnalysisDataOpt.GetInterproceduralControlFlowGraph(method); } - if (!_interproceduralMethodToCfgMapOpt!.TryGetValue(method, out var cfg)) + RoslynDebug.Assert(_interproceduralMethodToCfgMapOpt != null); + + if (!_interproceduralMethodToCfgMapOpt.TryGetValue(method, out var cfg)) { var operation = method.GetTopmostOperationBlock(WellKnownTypeProvider.Compilation); cfg = operation?.GetEnclosingControlFlowGraph(); diff --git a/src/Utilities/FlowAnalysis/FlowAnalysis/Framework/DataFlow/PredicatedAnalysisData.cs b/src/Utilities/FlowAnalysis/FlowAnalysis/Framework/DataFlow/PredicatedAnalysisData.cs index aafb0970d6..79bab3a5c2 100644 --- a/src/Utilities/FlowAnalysis/FlowAnalysis/Framework/DataFlow/PredicatedAnalysisData.cs +++ b/src/Utilities/FlowAnalysis/FlowAnalysis/Framework/DataFlow/PredicatedAnalysisData.cs @@ -4,6 +4,7 @@ using System.Collections.Generic; using System.Diagnostics; using System.Linq; +using Analyzer.Utilities; using Analyzer.Utilities.Extensions; using Analyzer.Utilities.PooledObjects; @@ -100,11 +101,12 @@ protected void StartTrackingPredicatedData(AnalysisEntity predicatedEntity, Dict public void StopTrackingPredicatedData(AnalysisEntity predicatedEntity) { + RoslynDebug.Assert(_lazyPredicateDataMap != null); Debug.Assert(HasPredicatedDataForEntity(predicatedEntity)); - Debug.Assert(predicatedEntity.CaptureIdOpt != null, "Currently we only support predicated data tracking for flow captures"); + RoslynDebug.Assert(predicatedEntity.CaptureIdOpt != null, "Currently we only support predicated data tracking for flow captures"); AssertValidAnalysisData(); - if (_lazyPredicateDataMap!.TryGetValue(predicatedEntity, out var perEntityPredicatedAnalysisData)) + if (_lazyPredicateDataMap.TryGetValue(predicatedEntity, out var perEntityPredicatedAnalysisData)) { perEntityPredicatedAnalysisData.Dispose(); } @@ -124,8 +126,9 @@ public bool HasPredicatedDataForEntity(AnalysisEntity predicatedEntity) public void TransferPredicatedData(AnalysisEntity fromEntity, AnalysisEntity toEntity) { Debug.Assert(HasPredicatedDataForEntity(fromEntity)); - Debug.Assert(fromEntity.CaptureIdOpt != null, "Currently we only support predicated data tracking for flow captures"); - Debug.Assert(toEntity.CaptureIdOpt != null, "Currently we only support predicated data tracking for flow captures"); + RoslynDebug.Assert(_lazyPredicateDataMap != null); + RoslynDebug.Assert(fromEntity.CaptureIdOpt != null, "Currently we only support predicated data tracking for flow captures"); + RoslynDebug.Assert(toEntity.CaptureIdOpt != null, "Currently we only support predicated data tracking for flow captures"); AssertValidAnalysisData(); if (_lazyPredicateDataMap!.TryGetValue(fromEntity, out var fromEntityPredicatedData)) @@ -168,10 +171,11 @@ protected virtual void ApplyPredicatedData(DictionaryAnalysisData protected void RemoveEntriesInPredicatedData(TKey key) { + RoslynDebug.Assert(_lazyPredicateDataMap != null); Debug.Assert(HasPredicatedData); AssertValidAnalysisData(); - foreach (var kvp in _lazyPredicateDataMap!) + foreach (var kvp in _lazyPredicateDataMap) { if (kvp.Value.TruePredicatedData != null) { @@ -438,9 +442,10 @@ protected void AssertValidPredicatedAnalysisData(Action + public sealed class ThrownExceptionInfo : IEquatable { private ThrownExceptionInfo( BasicBlock block, @@ -33,8 +33,8 @@ internal static ThrownExceptionInfo Create(BasicBlock block, INamedTypeSymbol ex internal static ThrownExceptionInfo CreateDefaultInfoForExceptionsPathAnalysis(BasicBlock block, WellKnownTypeProvider wellKnownTypeProvider, ImmutableStack? interproceduralCallStackOpt) { var exceptionNamedType = wellKnownTypeProvider.GetOrCreateTypeByMetadataName(WellKnownTypeNames.SystemException); - Debug.Assert(exceptionNamedType != null); - return new ThrownExceptionInfo(block, exceptionNamedType!, interproceduralCallStackOpt, isDefaultExceptionForExceptionsPathAnalysis: true); + RoslynDebug.Assert(exceptionNamedType != null); + return new ThrownExceptionInfo(block, exceptionNamedType, interproceduralCallStackOpt, isDefaultExceptionForExceptionsPathAnalysis: true); } private static ControlFlowRegion? GetHandlerRegion(BasicBlock block, INamedTypeSymbol exceptionType) From 4fdc7cc3827e7f3c777c05ed975628a8633ef8ca Mon Sep 17 00:00:00 2001 From: Manish Vasani Date: Fri, 8 Nov 2019 12:09:58 -0800 Subject: [PATCH 24/28] Minor fix --- .../Core/ImportingConstructorShouldBeObsoleteCodeFixProvider.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Roslyn.Diagnostics.Analyzers/Core/ImportingConstructorShouldBeObsoleteCodeFixProvider.cs b/src/Roslyn.Diagnostics.Analyzers/Core/ImportingConstructorShouldBeObsoleteCodeFixProvider.cs index ae2631ef47..00b1f24b6b 100644 --- a/src/Roslyn.Diagnostics.Analyzers/Core/ImportingConstructorShouldBeObsoleteCodeFixProvider.cs +++ b/src/Roslyn.Diagnostics.Analyzers/Core/ImportingConstructorShouldBeObsoleteCodeFixProvider.cs @@ -238,7 +238,7 @@ private static SyntaxNode GenerateDescriptionArgument(SyntaxGenerator generator, { SyntaxNode attributeArgument; if (semanticModel.Compilation.TryGetOrCreateTypeByMetadataName(WellKnownTypeNames.MicrosoftCodeAnalysisHostMefMefConstruction, out var mefConstructionType) && - mefConstructionType?.GetMembers("ImportingConstructorMessage").OfType().Any() is object) + mefConstructionType.GetMembers("ImportingConstructorMessage").OfType().Any()) { attributeArgument = generator.MemberAccessExpression( generator.TypeExpressionForStaticMemberAccess(mefConstructionType), From a645fc3f137dff2d79ac9929fec82b3965b9eff3 Mon Sep 17 00:00:00 2001 From: Manish Vasani Date: Fri, 8 Nov 2019 14:15:28 -0800 Subject: [PATCH 25/28] Fix unit tests --- .../ImportingConstructorShouldBeObsoleteTests.cs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/Roslyn.Diagnostics.Analyzers/UnitTests/ImportingConstructorShouldBeObsoleteTests.cs b/src/Roslyn.Diagnostics.Analyzers/UnitTests/ImportingConstructorShouldBeObsoleteTests.cs index 54cade8f20..25d14bbf24 100644 --- a/src/Roslyn.Diagnostics.Analyzers/UnitTests/ImportingConstructorShouldBeObsoleteTests.cs +++ b/src/Roslyn.Diagnostics.Analyzers/UnitTests/ImportingConstructorShouldBeObsoleteTests.cs @@ -381,7 +381,7 @@ Class C End Sub End Class -Namespace Global.Microsoft.CodeAnalysis.Host.Mef.MefConstruction +Namespace Global.Microsoft.CodeAnalysis.Host.Mef Module MefConstruction Friend Const ImportingConstructorMessage As String = ""This exported object must be obtained through the MEF export provider."" End Module @@ -394,12 +394,12 @@ Imports System Class C - + Public Sub New() End Sub End Class -Namespace Global.Microsoft.CodeAnalysis.Host.Mef.MefConstruction +Namespace Global.Microsoft.CodeAnalysis.Host.Mef Module MefConstruction Friend Const ImportingConstructorMessage As String = ""This exported object must be obtained through the MEF export provider."" End Module @@ -611,7 +611,7 @@ Class C End Sub End Class -Namespace Global.Microsoft.CodeAnalysis.Host.Mef.MefConstruction +Namespace Global.Microsoft.CodeAnalysis.Host.Mef Module MefConstruction Friend Const ImportingConstructorMessage As String = ""This exported object must be obtained through the MEF export provider."" End Module @@ -624,12 +624,12 @@ Imports System Class C - + Public Sub New() End Sub End Class -Namespace Global.Microsoft.CodeAnalysis.Host.Mef.MefConstruction +Namespace Global.Microsoft.CodeAnalysis.Host.Mef Module MefConstruction Friend Const ImportingConstructorMessage As String = ""This exported object must be obtained through the MEF export provider."" End Module From 9c1ee5b960dbcdab377e230996b2dfad14976016 Mon Sep 17 00:00:00 2001 From: Manish Vasani Date: Fri, 15 Nov 2019 16:01:39 -0800 Subject: [PATCH 26/28] Address feedback from Sam --- .../CSharpImmutableObjectMethodAnalyzer.cs | 4 +- .../PublicAPI.Unshipped.txt | 4 +- .../AvoidUninstantiatedInternalClasses.cs | 12 +- .../AbstractRemoveEmptyFinalizers.cs | 2 +- .../CSharpUseOrdinalStringComparison.Fixer.cs | 3 +- .../DisposeObjectsBeforeLosingScope.cs | 2 +- .../DoNotPassLiteralsAsLocalizedParameters.cs | 2 +- .../Core/Runtime/SpecifyIFormatProvider.cs | 9 +- ...otCallDangerousMethodsInDeserialization.cs | 3 +- .../DoNotDisableHttpClientCRLCheck.cs | 2 +- .../DoNotSerializeTypeWithPointerFields.cs | 7 +- ...DoNotUseInsecureCryptographicAlgorithms.cs | 9 +- ...orgeryTokenAnalyzer.MvcAttributeSymbols.cs | 3 +- .../CSharp/DisplayClassAllocationAnalyzer.cs | 5 +- src/Tools/ReleaseNotesUtil/RuleInfo.cs | 1 + .../Extensions/IMethodSymbolExtensions.cs | 21 +-- .../Compiler/Extensions/ISymbolExtensions.cs | 2 +- .../Compiler/PooledObjects/ArrayBuilder.cs | 19 +- .../Compiler/WellKnownTypeProvider.cs | 2 +- .../IOperationExtensions_FlowAnalysis.cs | 8 +- ...pyAnalysis.CopyDataFlowOperationVisitor.cs | 4 +- .../Analysis/CopyAnalysis/CopyAnalysisData.cs | 4 +- ...nalysis.DisposeDataFlowOperationVisitor.cs | 12 +- .../DisposeAnalysis/DisposeAnalysisHelper.cs | 11 +- ...meterValidationDataFlowOperationVisitor.cs | 8 +- .../ParameterValidationAnalysis.cs | 24 +-- ...alysis.PointsToDataFlowOperationVisitor.cs | 60 +++---- ...sis.PropertySetDataFlowOperationVisitor.cs | 10 +- ...ataAnalysis.TaintedDataOperationVisitor.cs | 6 +- .../TaintedDataSymbolMap.cs | 2 +- .../TaintedDataSymbolMapExtensions.cs | 2 + .../ValueContentAbstractValue.cs | 15 +- ...is.ValueContentDataFlowOperationVisitor.cs | 8 +- .../Framework/DataFlow/AbstractLocation.cs | 12 +- ...bstractLocationDataFlowOperationVisitor.cs | 23 ++- .../DataFlow/AddressSharedEntitiesProvider.cs | 5 +- .../AnalysisEntityDataFlowOperationVisitor.cs | 20 +-- .../DataFlow/AnalysisEntityFactory.cs | 8 +- .../Framework/DataFlow/CacheBasedEquatable.cs | 2 +- .../Framework/DataFlow/DataFlowAnalysis.cs | 8 +- .../DataFlow/DataFlowOperationVisitor.cs | 162 +++++++++--------- .../DataFlow/DictionaryAnalysisData.cs | 41 ++--- .../DataFlow/PredicatedAnalysisData.cs | 2 + 43 files changed, 286 insertions(+), 283 deletions(-) diff --git a/src/Microsoft.CodeAnalysis.Analyzers/CSharp/CSharpImmutableObjectMethodAnalyzer.cs b/src/Microsoft.CodeAnalysis.Analyzers/CSharp/CSharpImmutableObjectMethodAnalyzer.cs index 7954ac0694..405ca36ca0 100644 --- a/src/Microsoft.CodeAnalysis.Analyzers/CSharp/CSharpImmutableObjectMethodAnalyzer.cs +++ b/src/Microsoft.CodeAnalysis.Analyzers/CSharp/CSharpImmutableObjectMethodAnalyzer.cs @@ -60,12 +60,12 @@ public override void Initialize(AnalysisContext context) return; } - var immutableSymbols = ImmutableHashSet.Create(solutionSymbol, projectSymbol, documentSymbol, syntaxNodeSymbol, compilationSymbol); + var immutableSymbols = ImmutableArray.Create(solutionSymbol, projectSymbol, documentSymbol, syntaxNodeSymbol, compilationSymbol); compilationContext.RegisterSyntaxNodeAction(sc => AnalyzeInvocationForIgnoredReturnValue(sc, immutableSymbols), SyntaxKind.InvocationExpression); }); } - public static void AnalyzeInvocationForIgnoredReturnValue(SyntaxNodeAnalysisContext context, ImmutableHashSet immutableTypeSymbols) + public static void AnalyzeInvocationForIgnoredReturnValue(SyntaxNodeAnalysisContext context, ImmutableArray immutableTypeSymbols) { SemanticModel model = context.SemanticModel; var candidateInvocation = (InvocationExpressionSyntax)context.Node; diff --git a/src/Microsoft.CodeAnalysis.FlowAnalysis.Utilities/PublicAPI.Unshipped.txt b/src/Microsoft.CodeAnalysis.FlowAnalysis.Utilities/PublicAPI.Unshipped.txt index 869544e9c9..e9caa55c38 100644 --- a/src/Microsoft.CodeAnalysis.FlowAnalysis.Utilities/PublicAPI.Unshipped.txt +++ b/src/Microsoft.CodeAnalysis.FlowAnalysis.Utilities/PublicAPI.Unshipped.txt @@ -67,7 +67,7 @@ Microsoft.CodeAnalysis.FlowAnalysis.DataFlow.AbstractLocation.TryGetNodeToReport Microsoft.CodeAnalysis.FlowAnalysis.DataFlow.AbstractLocationDataFlowOperationVisitor Microsoft.CodeAnalysis.FlowAnalysis.DataFlow.AbstractLocationDataFlowOperationVisitor.AbstractLocationDataFlowOperationVisitor(TAnalysisContext analysisContext) -> void Microsoft.CodeAnalysis.FlowAnalysis.DataFlow.AbstractLocationDataFlowOperationVisitor.ApplyMissingCurrentAnalysisDataForUnhandledExceptionData(Microsoft.CodeAnalysis.FlowAnalysis.DataFlow.DictionaryAnalysisData coreDataAtException, Microsoft.CodeAnalysis.FlowAnalysis.DataFlow.DictionaryAnalysisData coreCurrentAnalysisData) -> void -Microsoft.CodeAnalysis.FlowAnalysis.DataFlow.AbstractLocationDataFlowOperationVisitor.ResetAnalysisData(Microsoft.CodeAnalysis.FlowAnalysis.DataFlow.DictionaryAnalysisData currentAnalysisDataOpt) -> void +Microsoft.CodeAnalysis.FlowAnalysis.DataFlow.AbstractLocationDataFlowOperationVisitor.ResetAnalysisData(Microsoft.CodeAnalysis.FlowAnalysis.DataFlow.DictionaryAnalysisData currentAnalysisData) -> void Microsoft.CodeAnalysis.FlowAnalysis.DataFlow.AbstractLocationDataFlowOperationVisitor.SetAbstractValue(Microsoft.CodeAnalysis.FlowAnalysis.DataFlow.PointsToAnalysis.PointsToAbstractValue instanceLocation, TAbstractAnalysisValue value) -> void Microsoft.CodeAnalysis.FlowAnalysis.DataFlow.AbstractLocationDataFlowOperationVisitor.SetAbstractValue(System.Collections.Generic.IEnumerable locations, TAbstractAnalysisValue value) -> void Microsoft.CodeAnalysis.FlowAnalysis.DataFlow.AbstractValueDomain @@ -113,7 +113,7 @@ Microsoft.CodeAnalysis.FlowAnalysis.DataFlow.AnalysisEntityDataFlowOperationVisi Microsoft.CodeAnalysis.FlowAnalysis.DataFlow.AnalysisEntityDataFlowOperationVisitor.GetChildAnalysisEntities(Microsoft.CodeAnalysis.FlowAnalysis.DataFlow.PointsToAnalysis.PointsToAbstractValue instanceLocationOpt) -> System.Collections.Immutable.ImmutableHashSet Microsoft.CodeAnalysis.FlowAnalysis.DataFlow.AnalysisEntityDataFlowOperationVisitor.GetClonedAnalysisDataHelper(System.Collections.Generic.IDictionary analysisData) -> Microsoft.CodeAnalysis.FlowAnalysis.DataFlow.DictionaryAnalysisData Microsoft.CodeAnalysis.FlowAnalysis.DataFlow.AnalysisEntityDataFlowOperationVisitor.GetTrimmedCurrentAnalysisDataHelper(System.Collections.Generic.IEnumerable withEntities, System.Collections.Generic.IDictionary existingValues, System.Action setAbstractValue) -> TAnalysisData -Microsoft.CodeAnalysis.FlowAnalysis.DataFlow.AnalysisEntityDataFlowOperationVisitor.ResetAnalysisData(Microsoft.CodeAnalysis.FlowAnalysis.DataFlow.DictionaryAnalysisData currentAnalysisDataOpt) -> void +Microsoft.CodeAnalysis.FlowAnalysis.DataFlow.AnalysisEntityDataFlowOperationVisitor.ResetAnalysisData(Microsoft.CodeAnalysis.FlowAnalysis.DataFlow.DictionaryAnalysisData currentAnalysisData) -> void Microsoft.CodeAnalysis.FlowAnalysis.DataFlow.AnalysisEntityFactory Microsoft.CodeAnalysis.FlowAnalysis.DataFlow.AnalysisEntityFactory.CreateWithNewInstanceRoot(Microsoft.CodeAnalysis.FlowAnalysis.DataFlow.AnalysisEntity analysisEntity, Microsoft.CodeAnalysis.FlowAnalysis.DataFlow.AnalysisEntity newRootInstance) -> Microsoft.CodeAnalysis.FlowAnalysis.DataFlow.AnalysisEntity Microsoft.CodeAnalysis.FlowAnalysis.DataFlow.AnalysisEntityFactory.ThisOrMeInstance.get -> Microsoft.CodeAnalysis.FlowAnalysis.DataFlow.AnalysisEntity diff --git a/src/Microsoft.CodeQuality.Analyzers/Core/Maintainability/AvoidUninstantiatedInternalClasses.cs b/src/Microsoft.CodeQuality.Analyzers/Core/Maintainability/AvoidUninstantiatedInternalClasses.cs index fedd20b812..43acb5832b 100644 --- a/src/Microsoft.CodeQuality.Analyzers/Core/Maintainability/AvoidUninstantiatedInternalClasses.cs +++ b/src/Microsoft.CodeQuality.Analyzers/Core/Maintainability/AvoidUninstantiatedInternalClasses.cs @@ -58,7 +58,7 @@ public override void Initialize(AnalysisContext analysisContext) // instantiated by any friend assembly, but we didn't report the issue) than // to have false positives. var internalsVisibleToAttributeSymbol = compilation.GetOrCreateTypeByMetadataName(WellKnownTypeNames.SystemRuntimeCompilerServicesInternalsVisibleToAttribute); - if (AssemblyExposesInternals(compilation, internalsVisibleToAttributeSymbol)) + if (compilation.Assembly.HasAttribute(internalsVisibleToAttributeSymbol)) { return; } @@ -200,16 +200,6 @@ static IEnumerable GetAllNamedTypeConstraints(ITypeParameterSy }); } - private static bool AssemblyExposesInternals( - Compilation compilation, - INamedTypeSymbol? internalsVisibleToAttributeSymbol) - { - ISymbol assemblySymbol = compilation.Assembly; - var attributes = assemblySymbol.GetAttributes(); - return internalsVisibleToAttributeSymbol == null || - attributes.Any(attr => attr.AttributeClass.Equals(internalsVisibleToAttributeSymbol)); - } - private bool HasInstantiatedNestedType(INamedTypeSymbol type, IEnumerable instantiatedTypes) { // We don't care whether a private nested type is instantiated, because if it diff --git a/src/Microsoft.CodeQuality.Analyzers/Core/QualityGuidelines/AbstractRemoveEmptyFinalizers.cs b/src/Microsoft.CodeQuality.Analyzers/Core/QualityGuidelines/AbstractRemoveEmptyFinalizers.cs index 981d07768d..d26f1e48eb 100644 --- a/src/Microsoft.CodeQuality.Analyzers/Core/QualityGuidelines/AbstractRemoveEmptyFinalizers.cs +++ b/src/Microsoft.CodeQuality.Analyzers/Core/QualityGuidelines/AbstractRemoveEmptyFinalizers.cs @@ -56,7 +56,7 @@ public override void Initialize(AnalysisContext analysisContext) } protected static bool InvocationIsConditional(IMethodSymbol methodSymbol, INamedTypeSymbol? conditionalAttributeSymbol) => - conditionalAttributeSymbol != null && methodSymbol.GetAttributes().Any(n => n.AttributeClass.Equals(conditionalAttributeSymbol)); + methodSymbol.HasAttribute(conditionalAttributeSymbol); protected abstract bool IsEmptyFinalizer(SyntaxNode methodBody, CodeBlockAnalysisContext analysisContext); } diff --git a/src/Microsoft.NetCore.Analyzers/CSharp/Runtime/CSharpUseOrdinalStringComparison.Fixer.cs b/src/Microsoft.NetCore.Analyzers/CSharp/Runtime/CSharpUseOrdinalStringComparison.Fixer.cs index d6c03a786e..2ab2760147 100644 --- a/src/Microsoft.NetCore.Analyzers/CSharp/Runtime/CSharpUseOrdinalStringComparison.Fixer.cs +++ b/src/Microsoft.NetCore.Analyzers/CSharp/Runtime/CSharpUseOrdinalStringComparison.Fixer.cs @@ -47,8 +47,7 @@ protected override bool IsInIdentifierNameContext(SyntaxNode node) protected override async Task FixIdentifierName(Document document, SyntaxGenerator generator, SyntaxNode root, SyntaxNode identifier, CancellationToken cancellationToken) { - InvocationExpressionSyntax? invokeParent = identifier?.Parent?.FirstAncestorOrSelf(); - if (invokeParent != null) + if (identifier?.Parent?.FirstAncestorOrSelf() is InvocationExpressionSyntax invokeParent) { SemanticModel model = await document.GetSemanticModelAsync(cancellationToken).ConfigureAwait(false); if (model.GetSymbolInfo((IdentifierNameSyntax)identifier!, cancellationToken).Symbol is IMethodSymbol methodSymbol && CanAddStringComparison(methodSymbol, model)) diff --git a/src/Microsoft.NetCore.Analyzers/Core/Runtime/DisposeObjectsBeforeLosingScope.cs b/src/Microsoft.NetCore.Analyzers/Core/Runtime/DisposeObjectsBeforeLosingScope.cs index d7ce0c2fa6..b546ca0f1c 100644 --- a/src/Microsoft.NetCore.Analyzers/Core/Runtime/DisposeObjectsBeforeLosingScope.cs +++ b/src/Microsoft.NetCore.Analyzers/Core/Runtime/DisposeObjectsBeforeLosingScope.cs @@ -224,7 +224,7 @@ bool CanBeDisposable(ITypeSymbol type) var isNotDisposed = disposeValue.Kind == DisposeAbstractValueKind.NotDisposed || (disposeValue.DisposingOrEscapingOperations.Count > 0 && - disposeValue.DisposingOrEscapingOperations.All(d => d.IsInsideCatchRegion(disposeAnalysisResult.ControlFlowGraph) && location.GetTopOfCreationCallStackOrCreation()?.IsInsideCatchRegion(disposeAnalysisResult.ControlFlowGraph) != true)); + 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 || diff --git a/src/Microsoft.NetCore.Analyzers/Core/Runtime/DoNotPassLiteralsAsLocalizedParameters.cs b/src/Microsoft.NetCore.Analyzers/Core/Runtime/DoNotPassLiteralsAsLocalizedParameters.cs index 97a8251b2a..122d318d95 100644 --- a/src/Microsoft.NetCore.Analyzers/Core/Runtime/DoNotPassLiteralsAsLocalizedParameters.cs +++ b/src/Microsoft.NetCore.Analyzers/Core/Runtime/DoNotPassLiteralsAsLocalizedParameters.cs @@ -126,7 +126,7 @@ void AnalyzeArgument(IParameterSymbol parameter, IPropertySymbol? containingProp return; } - var stringLiteralValues = stringContentValue.LiteralValues.Select(l => (string?)l); + var stringLiteralValues = stringContentValue.LiteralValues.Cast(); // FxCop compat: Do not fire if the literal value came from a default parameter value if (stringContentValue.LiteralValues.Count == 1 && diff --git a/src/Microsoft.NetCore.Analyzers/Core/Runtime/SpecifyIFormatProvider.cs b/src/Microsoft.NetCore.Analyzers/Core/Runtime/SpecifyIFormatProvider.cs index 00aaef2505..65f99a9419 100644 --- a/src/Microsoft.NetCore.Analyzers/Core/Runtime/SpecifyIFormatProvider.cs +++ b/src/Microsoft.NetCore.Analyzers/Core/Runtime/SpecifyIFormatProvider.cs @@ -134,10 +134,9 @@ public override void Initialize(AnalysisContext analysisContext) var targetMethod = invocationExpression.TargetMethod; #region "Exceptions" - if (targetMethod.IsGenericMethod || targetMethod.ContainingType == null || targetMethod.ContainingType.IsErrorType() || - (targetMethod.ContainingType != null && - (activatorType != null && activatorType.Equals(targetMethod.ContainingType)) || - (resourceManagerType != null && resourceManagerType.Equals(targetMethod.ContainingType)))) + if (targetMethod.IsGenericMethod || targetMethod.ContainingType.IsErrorType() || + (activatorType != null && activatorType.Equals(targetMethod.ContainingType)) || + (resourceManagerType != null && resourceManagerType.Equals(targetMethod.ContainingType))) { return; } @@ -166,7 +165,7 @@ public override void Initialize(AnalysisContext analysisContext) #region "IFormatProviderAlternateStringRule & IFormatProviderAlternateRule" - IEnumerable methodsWithSameNameAsTargetMethod = targetMethod.ContainingType!.GetMembers(targetMethod.Name).OfType().WhereMethodDoesNotContainAttribute(obsoleteAttributeType).ToList(); + IEnumerable methodsWithSameNameAsTargetMethod = targetMethod.ContainingType.GetMembers(targetMethod.Name).OfType().WhereMethodDoesNotContainAttribute(obsoleteAttributeType).ToList(); if (methodsWithSameNameAsTargetMethod.HasMoreThan(1)) { var correctOverloads = methodsWithSameNameAsTargetMethod.GetMethodOverloadsWithDesiredParameterAtLeadingOrTrailing(targetMethod, iformatProviderType).ToList(); diff --git a/src/Microsoft.NetCore.Analyzers/Core/Security/DoNotCallDangerousMethodsInDeserialization.cs b/src/Microsoft.NetCore.Analyzers/Core/Security/DoNotCallDangerousMethodsInDeserialization.cs index feb8edc6ea..49147a12d7 100644 --- a/src/Microsoft.NetCore.Analyzers/Core/Security/DoNotCallDangerousMethodsInDeserialization.cs +++ b/src/Microsoft.NetCore.Analyzers/Core/Security/DoNotCallDangerousMethodsInDeserialization.cs @@ -1,5 +1,6 @@ // Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. +using System; using System.Collections.Concurrent; using System.Collections.Generic; using System.Collections.Immutable; @@ -175,7 +176,7 @@ public sealed override void Initialize(AnalysisContext context) break; default: - return; + throw new NotImplementedException(); } calledMethods.TryAdd(calledSymbol, true); diff --git a/src/Microsoft.NetCore.Analyzers/Core/Security/DoNotDisableHttpClientCRLCheck.cs b/src/Microsoft.NetCore.Analyzers/Core/Security/DoNotDisableHttpClientCRLCheck.cs index 52596058bd..e9cbe8a1b7 100644 --- a/src/Microsoft.NetCore.Analyzers/Core/Security/DoNotDisableHttpClientCRLCheck.cs +++ b/src/Microsoft.NetCore.Analyzers/Core/Security/DoNotDisableHttpClientCRLCheck.cs @@ -65,7 +65,7 @@ class DoNotDisableHttpClientCRLCheck : DiagnosticAnalyzer (ValueContentAbstractValue valueContentAbstractValue) => PropertySetCallbacks.EvaluateLiteralValues( valueContentAbstractValue, - (object? o) => o is bool booleanValue && booleanValue == false), + (object? o) => o is false), CheckCertificateRevocationListIndex), new PropertyMapper( "ServerCertificateCustomValidationCallback", diff --git a/src/Microsoft.NetCore.Analyzers/Core/Security/DoNotSerializeTypeWithPointerFields.cs b/src/Microsoft.NetCore.Analyzers/Core/Security/DoNotSerializeTypeWithPointerFields.cs index 0fde4998b8..65f503a1fe 100644 --- a/src/Microsoft.NetCore.Analyzers/Core/Security/DoNotSerializeTypeWithPointerFields.cs +++ b/src/Microsoft.NetCore.Analyzers/Core/Security/DoNotSerializeTypeWithPointerFields.cs @@ -1,5 +1,8 @@ // Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. +// TODO(dotpaul): Enable nullable analysis. +#nullable disable + using System.Collections.Concurrent; using System.Collections.Immutable; using System.Linq; @@ -86,7 +89,7 @@ public sealed override void Initialize(AnalysisContext context) // typeSymbol: The symbol of the type to be analyzed // relatedFieldSymbol: When relatedFieldSymbol is null, traverse all descendants of typeSymbol to // find pointer fields; otherwise, traverse to find if relatedFieldSymbol is a pointer field - void LookForSerializationWithPointerFields(ITypeSymbol typeSymbol, IFieldSymbol? relatedFieldSymbol) + void LookForSerializationWithPointerFields(ITypeSymbol typeSymbol, IFieldSymbol relatedFieldSymbol) { if (typeSymbol is IPointerTypeSymbol pointerTypeSymbol) { @@ -94,9 +97,7 @@ void LookForSerializationWithPointerFields(ITypeSymbol typeSymbol, IFieldSymbol? if (pointerTypeSymbol.PointedAtType.TypeKind == TypeKind.Struct || pointerTypeSymbol.PointedAtType.TypeKind == TypeKind.Pointer) { -#pragma warning disable CS8604 // Possible null reference argument. pointerFields.TryAdd(relatedFieldSymbol, true); -#pragma warning restore CS8604 // Possible null reference argument. } } else if (typeSymbol is INamedTypeSymbol namedTypeSymbol) diff --git a/src/Microsoft.NetCore.Analyzers/Core/Security/DoNotUseInsecureCryptographicAlgorithms.cs b/src/Microsoft.NetCore.Analyzers/Core/Security/DoNotUseInsecureCryptographicAlgorithms.cs index 46dec5c663..5c6f635766 100644 --- a/src/Microsoft.NetCore.Analyzers/Core/Security/DoNotUseInsecureCryptographicAlgorithms.cs +++ b/src/Microsoft.NetCore.Analyzers/Core/Security/DoNotUseInsecureCryptographicAlgorithms.cs @@ -1,5 +1,8 @@ // Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. +// TODO(dotpaul): Enable nullable analysis. +#nullable disable + using System.Collections.Immutable; using Microsoft.NetCore.Analyzers.Security.Helpers; using Analyzer.Utilities; @@ -106,8 +109,8 @@ public override void Initialize(AnalysisContext analysisContext) } INamedTypeSymbol type = method.ContainingType; - DiagnosticDescriptor? rule = null; - string? algorithmName = null; + DiagnosticDescriptor rule = null; + string algorithmName = null; if (type.DerivesFrom(cryptTypes.MD5)) { @@ -136,9 +139,7 @@ public override void Initialize(AnalysisContext analysisContext) && method.MetadataName == WellKnownMemberNames.InstanceConstructorName)) { rule = DoNotUseBrokenCryptographyRule; -#pragma warning disable CS8602 // Dereference of a possibly null reference. algorithmName = cryptTypes.DSA.Name; -#pragma warning restore CS8602 // Dereference of a possibly null reference. } else if (type.DerivesFrom(cryptTypes.HMACMD5)) { diff --git a/src/Microsoft.NetFramework.Analyzers/Core/MarkVerbHandlersWithValidateAntiforgeryTokenAnalyzer.MvcAttributeSymbols.cs b/src/Microsoft.NetFramework.Analyzers/Core/MarkVerbHandlersWithValidateAntiforgeryTokenAnalyzer.MvcAttributeSymbols.cs index c9f8ed0618..e9ce029e53 100644 --- a/src/Microsoft.NetFramework.Analyzers/Core/MarkVerbHandlersWithValidateAntiforgeryTokenAnalyzer.MvcAttributeSymbols.cs +++ b/src/Microsoft.NetFramework.Analyzers/Core/MarkVerbHandlersWithValidateAntiforgeryTokenAnalyzer.MvcAttributeSymbols.cs @@ -2,6 +2,7 @@ using System; using System.Collections.Immutable; +using System.Diagnostics.CodeAnalysis; using Analyzer.Utilities; using Analyzer.Utilities.Extensions; using Microsoft.CodeAnalysis; @@ -136,7 +137,7 @@ public MvcAttributeSymbols(Compilation compilation) /// The .NET attribute to check. /// The type of .NET attribute to compare. /// True if .NET attribute's type matches the specified type, false otherwise. - private static bool IsAttributeClass(AttributeData attributeData, INamedTypeSymbol? symbol) + private static bool IsAttributeClass(AttributeData attributeData, [NotNullWhen(returnValue: true)] INamedTypeSymbol? symbol) { return symbol != null && Equals(attributeData.AttributeClass, symbol); } diff --git a/src/PerformanceSensitiveAnalyzers/CSharp/DisplayClassAllocationAnalyzer.cs b/src/PerformanceSensitiveAnalyzers/CSharp/DisplayClassAllocationAnalyzer.cs index 445faba3fc..c0ddad4136 100644 --- a/src/PerformanceSensitiveAnalyzers/CSharp/DisplayClassAllocationAnalyzer.cs +++ b/src/PerformanceSensitiveAnalyzers/CSharp/DisplayClassAllocationAnalyzer.cs @@ -92,12 +92,13 @@ protected override void AnalyzeNode(SyntaxNodeAnalysisContext context, in Perfor private static void ClosureCaptureDataFlowAnalysis(DataFlowAnalysis? flow, Action reportDiagnostic, Location location) { - if (flow?.Captured.Length <= 0) + if (flow == null || + flow.Captured.Length <= 0) { return; } - foreach (var capture in flow!.Captured) + foreach (var capture in flow.Captured) { if (capture.Name != null && capture.Locations != null) { diff --git a/src/Tools/ReleaseNotesUtil/RuleInfo.cs b/src/Tools/ReleaseNotesUtil/RuleInfo.cs index c0b5223a98..308fbe6126 100644 --- a/src/Tools/ReleaseNotesUtil/RuleInfo.cs +++ b/src/Tools/ReleaseNotesUtil/RuleInfo.cs @@ -23,6 +23,7 @@ public RuleInfo(string id, string title, string category, bool isEnabledByDefaul HelpLink = helpLink; } + // TODO(dotpaul): Remove the below suppression. #pragma warning disable CS8618 // Non-nullable field is uninitialized. Consider declaring as nullable. public RuleInfo() #pragma warning restore CS8618 // Non-nullable field is uninitialized. Consider declaring as nullable. diff --git a/src/Utilities/Compiler/Extensions/IMethodSymbolExtensions.cs b/src/Utilities/Compiler/Extensions/IMethodSymbolExtensions.cs index 66fe2bd43c..739865d397 100644 --- a/src/Utilities/Compiler/Extensions/IMethodSymbolExtensions.cs +++ b/src/Utilities/Compiler/Extensions/IMethodSymbolExtensions.cs @@ -6,6 +6,7 @@ using System.Linq; using Microsoft.CodeAnalysis; using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; #if HAS_IOPERATION using System.Collections.Concurrent; @@ -145,7 +146,7 @@ public static bool IsFinalizer(this IMethodSymbol method) /// Checks if the given method is an implementation of the given interface method /// Substituted with the given typeargument. /// - public static bool IsImplementationOfInterfaceMethod(this IMethodSymbol method, ITypeSymbol? typeArgument, INamedTypeSymbol? interfaceType, string interfaceMethodName) + public static bool IsImplementationOfInterfaceMethod(this IMethodSymbol method, ITypeSymbol? typeArgument, [NotNullWhen(returnValue: true)] INamedTypeSymbol? interfaceType, string interfaceMethodName) { INamedTypeSymbol? constructedInterface = typeArgument != null ? interfaceType?.Construct(typeArgument) : interfaceType; @@ -164,7 +165,7 @@ public static bool IsDisposeImplementation(this IMethodSymbol method, Compilatio /// /// Checks if the given method implements or overrides an implementation of . /// - public static bool IsDisposeImplementation(this IMethodSymbol? method, INamedTypeSymbol? iDisposable) + public static bool IsDisposeImplementation([NotNullWhen(returnValue: true)] this IMethodSymbol? method, [NotNullWhen(returnValue: true)] INamedTypeSymbol? iDisposable) { if (method == null) { @@ -221,7 +222,7 @@ private static bool HasDisposeCloseMethodSignature(this IMethodSymbol method) /// /// Checks if the given method has the signature "Task DisposeAsync()". /// - private static bool HasDisposeAsyncMethodSignature(this IMethodSymbol method, INamedTypeSymbol? task) + private static bool HasDisposeAsyncMethodSignature(this IMethodSymbol method, [NotNullWhen(returnValue: true)] INamedTypeSymbol? task) { return method.Name == "DisposeAsync" && method.MethodKind == MethodKind.Ordinary && @@ -232,7 +233,7 @@ private static bool HasDisposeAsyncMethodSignature(this IMethodSymbol method, IN /// /// Checks if the given method has the signature "override Task DisposeCoreAsync(bool)". /// - private static bool HasOverriddenDisposeCoreAsyncMethodSignature(this IMethodSymbol method, INamedTypeSymbol? task) + private static bool HasOverriddenDisposeCoreAsyncMethodSignature(this IMethodSymbol method, [NotNullWhen(returnValue: true)] INamedTypeSymbol? task) { return method.Name == "DisposeCoreAsync" && method.MethodKind == MethodKind.Ordinary && @@ -292,7 +293,7 @@ public static DisposeMethodKind GetDisposeMethodKind(this IMethodSymbol method, /// /// Checks if the given method implements 'System.Runtime.Serialization.IDeserializationCallback.OnDeserialization' or overrides an implementation of 'System.Runtime.Serialization.IDeserializationCallback.OnDeserialization'/>. /// - public static bool IsOnDeserializationImplementation(this IMethodSymbol method, INamedTypeSymbol iDeserializationCallback) + public static bool IsOnDeserializationImplementation([NotNullWhen(returnValue: true)] this IMethodSymbol? method, [NotNullWhen(returnValue: true)] INamedTypeSymbol? iDeserializationCallback) { if (method == null) { @@ -394,7 +395,7 @@ public static bool IsCollectionAddMethod(this IMethodSymbol method, ImmutableHas /// /// The method to test. /// Task type. - public static bool IsTaskFromResultMethod(this IMethodSymbol method, INamedTypeSymbol? taskType) + public static bool IsTaskFromResultMethod(this IMethodSymbol method, [NotNullWhen(returnValue: true)] INamedTypeSymbol? taskType) => method.Name.Equals("FromResult", StringComparison.Ordinal) && method.ContainingType.Equals(taskType); @@ -403,7 +404,7 @@ public static bool IsTaskFromResultMethod(this IMethodSymbol method, INamedTypeS /// /// The method to test. /// Generic task type. - public static bool IsTaskConfigureAwaitMethod(this IMethodSymbol method, INamedTypeSymbol? genericTaskType) + public static bool IsTaskConfigureAwaitMethod(this IMethodSymbol method, [NotNullWhen(returnValue: true)] INamedTypeSymbol? genericTaskType) => method.Name.Equals("ConfigureAwait", StringComparison.Ordinal) && method.Parameters.Length == 1 && method.Parameters[0].Type.SpecialType == SpecialType.System_Boolean && @@ -506,13 +507,13 @@ public static int GetParameterIndex(this IMethodSymbol methodSymbol, IParameterS /// the first parameter is of type and the second /// parameter inherits from or equals type. /// - public static bool HasEventHandlerSignature(this IMethodSymbol method, INamedTypeSymbol? eventArgsType) + public static bool HasEventHandlerSignature(this IMethodSymbol method, [NotNullWhen(returnValue: true)] INamedTypeSymbol? eventArgsType) => eventArgsType != null && method.Parameters.Length == 2 && method.Parameters[0].Type.SpecialType == SpecialType.System_Object && method.Parameters[1].Type.DerivesFrom(eventArgsType, baseTypesOnly: true); - public static bool IsLockMethod(this IMethodSymbol method, INamedTypeSymbol? systemThreadingMonitor) + public static bool IsLockMethod(this IMethodSymbol method, [NotNullWhen(returnValue: true)] INamedTypeSymbol? systemThreadingMonitor) { // "System.Threading.Monitor.Enter(object)" OR "System.Threading.Monitor.Enter(object, bool)" return method.Name == "Enter" && @@ -558,7 +559,7 @@ public static bool HasParameterWithDelegateType(this IMethodSymbol methodSymbol) /// /// The method /// The type has virtual method - public static bool IsOverrideOrVirtualMethodOf(this IMethodSymbol? methodSymbol, INamedTypeSymbol? typeSymbol) + public static bool IsOverrideOrVirtualMethodOf([NotNullWhen(returnValue: true)] this IMethodSymbol? methodSymbol, [NotNullWhen(returnValue: true)] INamedTypeSymbol? typeSymbol) { if (methodSymbol == null) { diff --git a/src/Utilities/Compiler/Extensions/ISymbolExtensions.cs b/src/Utilities/Compiler/Extensions/ISymbolExtensions.cs index 05ebd7619d..24a3a3476a 100644 --- a/src/Utilities/Compiler/Extensions/ISymbolExtensions.cs +++ b/src/Utilities/Compiler/Extensions/ISymbolExtensions.cs @@ -603,7 +603,7 @@ public static bool IsImplementationOfAnyExplicitInterfaceMember([NotNullWhen(ret }; } - public static ITypeSymbol? GetMemberType([NotNullWhen(returnValue: true)] this ISymbol? symbol) + public static ITypeSymbol? GetMemberType(this ISymbol? symbol) { return symbol switch { diff --git a/src/Utilities/Compiler/PooledObjects/ArrayBuilder.cs b/src/Utilities/Compiler/PooledObjects/ArrayBuilder.cs index c24935b6ee..f9aab8e5eb 100644 --- a/src/Utilities/Compiler/PooledObjects/ArrayBuilder.cs +++ b/src/Utilities/Compiler/PooledObjects/ArrayBuilder.cs @@ -4,7 +4,6 @@ using System.Collections.Generic; using System.Collections.Immutable; using System.Diagnostics; -using System.Diagnostics.CodeAnalysis; #pragma warning disable CA1710 // Rename Microsoft.CodeAnalysis.ArrayBuilder to end in 'Collection'. #pragma warning disable CA1000 // Do not declare static members on generic types @@ -102,7 +101,7 @@ public int Count /// Write to slot . /// Fills in unallocated slots preceding the , if any. /// - public void SetItem(int index, [MaybeNull]T value) + public void SetItem(int index, T value) { while (index > _builder.Count) { @@ -119,12 +118,12 @@ public void SetItem(int index, [MaybeNull]T value) } } - public void Add([MaybeNull]T item) + public void Add(T item) { _builder.Add(item); } - public void Insert(int index, [MaybeNull]T item) + public void Insert(int index, T item) { _builder.Insert(index, item); } @@ -142,22 +141,22 @@ public void Clear() _builder.Clear(); } - public bool Contains([MaybeNull]T item) + public bool Contains(T item) { return _builder.Contains(item); } - public int IndexOf([MaybeNull]T item) + public int IndexOf(T item) { return _builder.IndexOf(item); } - public int IndexOf([MaybeNull]T item, IEqualityComparer equalityComparer) + public int IndexOf(T item, IEqualityComparer equalityComparer) { return _builder.IndexOf(item, 0, _builder.Count, equalityComparer); } - public int IndexOf([MaybeNull]T item, int startIndex, int count) + public int IndexOf(T item, int startIndex, int count) { return _builder.IndexOf(item, startIndex, count); } @@ -225,13 +224,11 @@ public void CopyTo(T[] array, int start) _builder.CopyTo(array, start); } - [return: MaybeNull] public T Last() { return _builder[_builder.Count - 1]; } - [return: MaybeNull] public T First() { return _builder[0]; @@ -499,7 +496,7 @@ public void ZeroInit(int count) _builder.Count = count; } - public void AddMany([MaybeNull] T item, int count) + public void AddMany(T item, int count) { for (int i = 0; i < count; i++) { diff --git a/src/Utilities/Compiler/WellKnownTypeProvider.cs b/src/Utilities/Compiler/WellKnownTypeProvider.cs index 03478b775c..e6158e6ec8 100644 --- a/src/Utilities/Compiler/WellKnownTypeProvider.cs +++ b/src/Utilities/Compiler/WellKnownTypeProvider.cs @@ -117,7 +117,7 @@ public bool TryGetOrCreateTypeByMetadataName(string fullTypeName, [NotNullWhen(r /// Predicate to check the 's type argument. /// True if is a with its /// type argument satisfying , false otherwise. - internal bool IsTaskOfType(ITypeSymbol? typeSymbol, Func typeArgumentPredicate) + internal bool IsTaskOfType([NotNullWhen(returnValue: true)] ITypeSymbol? typeSymbol, Func typeArgumentPredicate) { return typeSymbol != null && typeSymbol.OriginalDefinition != null diff --git a/src/Utilities/FlowAnalysis/Extensions/IOperationExtensions_FlowAnalysis.cs b/src/Utilities/FlowAnalysis/Extensions/IOperationExtensions_FlowAnalysis.cs index 7289e2d856..589f7166d1 100644 --- a/src/Utilities/FlowAnalysis/Extensions/IOperationExtensions_FlowAnalysis.cs +++ b/src/Utilities/FlowAnalysis/Extensions/IOperationExtensions_FlowAnalysis.cs @@ -1,5 +1,6 @@ // Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. +using System.Diagnostics.CodeAnalysis; using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.FlowAnalysis; using Microsoft.CodeAnalysis.Operations; @@ -8,8 +9,13 @@ namespace Analyzer.Utilities.Extensions { internal static partial class IOperationExtensions { - public static bool IsInsideCatchRegion(this IOperation operation, ControlFlowGraph cfg) + public static bool IsInsideCatchRegion([NotNullWhen(returnValue: true)] this IOperation? operation, ControlFlowGraph cfg) { + if (operation == null) + { + return false; + } + foreach (var block in cfg.Blocks) { var isCatchRegionBlock = false; diff --git a/src/Utilities/FlowAnalysis/FlowAnalysis/Analysis/CopyAnalysis/CopyAnalysis.CopyDataFlowOperationVisitor.cs b/src/Utilities/FlowAnalysis/FlowAnalysis/Analysis/CopyAnalysis/CopyAnalysis.CopyDataFlowOperationVisitor.cs index 96e72d89a0..827461998c 100644 --- a/src/Utilities/FlowAnalysis/FlowAnalysis/Analysis/CopyAnalysis/CopyAnalysis.CopyDataFlowOperationVisitor.cs +++ b/src/Utilities/FlowAnalysis/FlowAnalysis/Analysis/CopyAnalysis/CopyAnalysis.CopyDataFlowOperationVisitor.cs @@ -607,7 +607,7 @@ public override CopyAbstractValue DefaultVisit(IOperation operation, object? arg return CopyAbstractValue.Unknown; } - public override CopyAbstractValue VisitConversion(IConversionOperation operation, object argument) + public override CopyAbstractValue VisitConversion(IConversionOperation operation, object? argument) { var operandValue = Visit(operation.Operand, argument); @@ -659,7 +659,7 @@ private static bool FlowConversionOperandValue(ConversionInference inference, IT return false; } - protected override CopyAbstractValue VisitAssignmentOperation(IAssignmentOperation operation, object argument) + protected override CopyAbstractValue VisitAssignmentOperation(IAssignmentOperation operation, object? argument) { var value = base.VisitAssignmentOperation(operation, argument); if (AnalysisEntityFactory.TryCreate(operation.Target, out var analysisEntity)) diff --git a/src/Utilities/FlowAnalysis/FlowAnalysis/Analysis/CopyAnalysis/CopyAnalysisData.cs b/src/Utilities/FlowAnalysis/FlowAnalysis/Analysis/CopyAnalysis/CopyAnalysisData.cs index 98c1a86f5b..e865be32ee 100644 --- a/src/Utilities/FlowAnalysis/FlowAnalysis/Analysis/CopyAnalysis/CopyAnalysisData.cs +++ b/src/Utilities/FlowAnalysis/FlowAnalysis/Analysis/CopyAnalysis/CopyAnalysisData.cs @@ -88,11 +88,11 @@ protected override void RemoveEntryInPredicatedData(AnalysisEntity key, CoreCopy { Debug.Assert(HasPredicatedData); - var hasEntry = predicatedData.TryGetValue(key, out CopyAbstractValue value); + var hasEntry = predicatedData.TryGetValue(key, out var value); base.RemoveEntryInPredicatedData(key, predicatedData); // If we are removing an entity from predicated data, we need to adjust the copy values of its copy entities. - if (hasEntry && value.AnalysisEntities.Count > 1) + if (hasEntry && value!.AnalysisEntities.Count > 1) { var newValueForOldCopyEntities = value.WithEntityRemoved(key); if (newValueForOldCopyEntities.AnalysisEntities.Count == 1) diff --git a/src/Utilities/FlowAnalysis/FlowAnalysis/Analysis/DisposeAnalysis/DisposeAnalysis.DisposeDataFlowOperationVisitor.cs b/src/Utilities/FlowAnalysis/FlowAnalysis/Analysis/DisposeAnalysis/DisposeAnalysis.DisposeDataFlowOperationVisitor.cs index 033d26e9b4..c2243171e0 100644 --- a/src/Utilities/FlowAnalysis/FlowAnalysis/Analysis/DisposeAnalysis/DisposeAnalysis.DisposeDataFlowOperationVisitor.cs +++ b/src/Utilities/FlowAnalysis/FlowAnalysis/Analysis/DisposeAnalysis/DisposeAnalysis.DisposeDataFlowOperationVisitor.cs @@ -111,7 +111,7 @@ private void HandleDisposingOperation(IOperation disposingOperation, IOperation? PointsToAbstractValue instanceLocation = GetPointsToAbstractValue(disposedInstance); foreach (AbstractLocation location in instanceLocation.Locations) { - if (CurrentAnalysisData.TryGetValue(location, out DisposeAbstractValue currentDisposeValue)) + if (CurrentAnalysisData.TryGetValue(location, out var currentDisposeValue)) { DisposeAbstractValue disposeValue = currentDisposeValue.WithNewDisposingOperation(disposingOperation); SetAbstractValue(location, disposeValue); @@ -124,7 +124,7 @@ private void HandlePossibleInvalidatingOperation(IOperation invalidatedInstance) PointsToAbstractValue instanceLocation = GetPointsToAbstractValue(invalidatedInstance); foreach (AbstractLocation location in instanceLocation.Locations) { - if (CurrentAnalysisData.TryGetValue(location, out DisposeAbstractValue currentDisposeValue) && + if (CurrentAnalysisData.TryGetValue(location, out var currentDisposeValue) && currentDisposeValue.Kind != DisposeAbstractValueKind.NotDisposable) { SetAbstractValue(location, DisposeAbstractValue.Invalid); @@ -136,7 +136,7 @@ private void HandlePossibleEscapingOperation(IOperation escapingOperation, Immut { foreach (AbstractLocation escapedLocation in escapedLocations) { - if (CurrentAnalysisData.TryGetValue(escapedLocation, out DisposeAbstractValue currentDisposeValue) && + if (CurrentAnalysisData.TryGetValue(escapedLocation, out var currentDisposeValue) && currentDisposeValue.Kind != DisposeAbstractValueKind.Unknown) { DisposeAbstractValue newDisposeValue = currentDisposeValue.WithNewEscapingOperation(escapingOperation); @@ -400,7 +400,7 @@ bool IsDisposeOwnershipTransfer() } } - public override DisposeAbstractValue VisitFieldReference(IFieldReferenceOperation operation, object argument) + public override DisposeAbstractValue VisitFieldReference(IFieldReferenceOperation operation, object? argument) { var value = base.VisitFieldReference(operation, argument); if (_trackedInstanceFieldLocationsOpt != null && @@ -438,7 +438,7 @@ public override DisposeAbstractValue VisitFieldReference(IFieldReferenceOperatio return value; } - public override DisposeAbstractValue VisitBinaryOperatorCore(IBinaryOperation operation, object argument) + public override DisposeAbstractValue VisitBinaryOperatorCore(IBinaryOperation operation, object? argument) { var value = base.VisitBinaryOperatorCore(operation, argument); @@ -482,7 +482,7 @@ public override DisposeAbstractValue VisitBinaryOperatorCore(IBinaryOperation op return value; } - public override DisposeAbstractValue VisitIsNull(IIsNullOperation operation, object argument) + public override DisposeAbstractValue VisitIsNull(IIsNullOperation operation, object? argument) { var value = base.VisitIsNull(operation, argument); diff --git a/src/Utilities/FlowAnalysis/FlowAnalysis/Analysis/DisposeAnalysis/DisposeAnalysisHelper.cs b/src/Utilities/FlowAnalysis/FlowAnalysis/Analysis/DisposeAnalysis/DisposeAnalysisHelper.cs index c2ff87e9df..243c1692f3 100644 --- a/src/Utilities/FlowAnalysis/FlowAnalysis/Analysis/DisposeAnalysis/DisposeAnalysisHelper.cs +++ b/src/Utilities/FlowAnalysis/FlowAnalysis/Analysis/DisposeAnalysis/DisposeAnalysisHelper.cs @@ -38,7 +38,7 @@ internal sealed class DisposeAnalysisHelper OperationKind.Invocation); private readonly WellKnownTypeProvider _wellKnownTypeProvider; - private readonly ImmutableHashSet? _disposeOwnershipTransferLikelyTypes; + private readonly ImmutableHashSet _disposeOwnershipTransferLikelyTypes; private ConcurrentDictionary>? _lazyDisposableFieldsMap; public INamedTypeSymbol? IDisposable { get; } public INamedTypeSymbol? Task { get; } @@ -50,10 +50,9 @@ private DisposeAnalysisHelper(Compilation compilation) IDisposable = _wellKnownTypeProvider.GetOrCreateTypeByMetadataName(WellKnownTypeNames.SystemIDisposable); Task = _wellKnownTypeProvider.GetOrCreateTypeByMetadataName(WellKnownTypeNames.SystemThreadingTasksTask); - if (IDisposable != null) - { - _disposeOwnershipTransferLikelyTypes = GetDisposeOwnershipTransferLikelyTypes(compilation); - } + _disposeOwnershipTransferLikelyTypes = IDisposable != null ? + GetDisposeOwnershipTransferLikelyTypes(compilation) : + ImmutableHashSet.Empty; } private static ImmutableHashSet GetDisposeOwnershipTransferLikelyTypes(Compilation compilation) @@ -112,7 +111,7 @@ static DisposeAnalysisHelper CreateDisposeAnalysisHelper(Compilation compilation if (cfg != null && IDisposable != null) { disposeAnalysisResult = DisposeAnalysis.TryGetOrComputeResult(cfg, containingMethod, _wellKnownTypeProvider, - analyzerOptions, rule, _disposeOwnershipTransferLikelyTypes!, trackInstanceFields, + analyzerOptions, rule, _disposeOwnershipTransferLikelyTypes, trackInstanceFields, trackExceptionPaths, cancellationToken, out pointsToAnalysisResult, interproceduralAnalysisPredicateOpt: interproceduralAnalysisPredicateOpt, defaultDisposeOwnershipTransferAtConstructor: defaultDisposeOwnershipTransferAtConstructor); diff --git a/src/Utilities/FlowAnalysis/FlowAnalysis/Analysis/ParameterValidationAnalysis/ParameterValidationAnalysis.ParameterValidationDataFlowOperationVisitor.cs b/src/Utilities/FlowAnalysis/FlowAnalysis/Analysis/ParameterValidationAnalysis/ParameterValidationAnalysis.ParameterValidationDataFlowOperationVisitor.cs index 00ac05fb1e..19370e62ed 100644 --- a/src/Utilities/FlowAnalysis/FlowAnalysis/Analysis/ParameterValidationAnalysis/ParameterValidationAnalysis.ParameterValidationDataFlowOperationVisitor.cs +++ b/src/Utilities/FlowAnalysis/FlowAnalysis/Analysis/ParameterValidationAnalysis/ParameterValidationAnalysis.ParameterValidationDataFlowOperationVisitor.cs @@ -225,7 +225,7 @@ public override ParameterValidationAbstractValue Visit(IOperation operation, obj return value; } - public override ParameterValidationAbstractValue VisitObjectCreation(IObjectCreationOperation operation, object argument) + public override ParameterValidationAbstractValue VisitObjectCreation(IObjectCreationOperation operation, object? argument) { var value = base.VisitObjectCreation(operation, argument); ProcessRegularInvocationOrCreation(operation.Constructor, operation.Arguments, operation); @@ -372,7 +372,7 @@ private void ProcessLambdaOrLocalFunctionInvocation(IMethodSymbol targetMethod, } } - public override ParameterValidationAbstractValue VisitBinaryOperatorCore(IBinaryOperation operation, object argument) + public override ParameterValidationAbstractValue VisitBinaryOperatorCore(IBinaryOperation operation, object? argument) { var value = base.VisitBinaryOperatorCore(operation, argument); @@ -414,7 +414,7 @@ public override ParameterValidationAbstractValue VisitBinaryOperatorCore(IBinary return value; } - public override ParameterValidationAbstractValue VisitIsNull(IIsNullOperation operation, object argument) + public override ParameterValidationAbstractValue VisitIsNull(IIsNullOperation operation, object? argument) { var value = base.VisitIsNull(operation, argument); @@ -425,7 +425,7 @@ public override ParameterValidationAbstractValue VisitIsNull(IIsNullOperation op return value; } - public override ParameterValidationAbstractValue VisitIsType(IIsTypeOperation operation, object argument) + public override ParameterValidationAbstractValue VisitIsType(IIsTypeOperation operation, object? argument) { var value = base.VisitIsType(operation, argument); diff --git a/src/Utilities/FlowAnalysis/FlowAnalysis/Analysis/ParameterValidationAnalysis/ParameterValidationAnalysis.cs b/src/Utilities/FlowAnalysis/FlowAnalysis/Analysis/ParameterValidationAnalysis/ParameterValidationAnalysis.cs index bdb332c13e..7874353540 100644 --- a/src/Utilities/FlowAnalysis/FlowAnalysis/Analysis/ParameterValidationAnalysis/ParameterValidationAnalysis.cs +++ b/src/Utilities/FlowAnalysis/FlowAnalysis/Analysis/ParameterValidationAnalysis/ParameterValidationAnalysis.cs @@ -58,19 +58,21 @@ private ParameterValidationAnalysis(ParameterValidationAnalysisDomain analysisDo bool pessimisticAnalysis = true) { var cfg = topmostBlock.GetEnclosingControlFlowGraph(); - if (cfg != null) + if (cfg == null) { - var wellKnownTypeProvider = WellKnownTypeProvider.GetOrCreate(compilation); - var pointsToAnalysisResult = PointsToAnalysis.PointsToAnalysis.TryGetOrComputeResult(cfg, owningSymbol, analyzerOptions, wellKnownTypeProvider, - interproceduralAnalysisConfig, interproceduralAnalysisPredicateOpt: null, pessimisticAnalysis, performCopyAnalysis); - if (pointsToAnalysisResult != null) + return ImmutableDictionary.Empty; + } + + var wellKnownTypeProvider = WellKnownTypeProvider.GetOrCreate(compilation); + var pointsToAnalysisResult = PointsToAnalysis.PointsToAnalysis.TryGetOrComputeResult(cfg, owningSymbol, analyzerOptions, wellKnownTypeProvider, + interproceduralAnalysisConfig, interproceduralAnalysisPredicateOpt: null, pessimisticAnalysis, performCopyAnalysis); + if (pointsToAnalysisResult != null) + { + var result = TryGetOrComputeResult(cfg, owningSymbol, analyzerOptions, wellKnownTypeProvider, + nullCheckValidationMethods, interproceduralAnalysisConfig, pessimisticAnalysis, pointsToAnalysisResult); + if (result != null) { - var result = TryGetOrComputeResult(cfg, owningSymbol, analyzerOptions, wellKnownTypeProvider, - nullCheckValidationMethods, interproceduralAnalysisConfig, pessimisticAnalysis, pointsToAnalysisResult); - if (result != null) - { - return result.HazardousParameterUsages; - } + return result.HazardousParameterUsages; } } diff --git a/src/Utilities/FlowAnalysis/FlowAnalysis/Analysis/PointsToAnalysis/PointsToAnalysis.PointsToDataFlowOperationVisitor.cs b/src/Utilities/FlowAnalysis/FlowAnalysis/Analysis/PointsToAnalysis/PointsToAnalysis.PointsToDataFlowOperationVisitor.cs index 1b57a4f6fe..5911bf632e 100644 --- a/src/Utilities/FlowAnalysis/FlowAnalysis/Analysis/PointsToAnalysis/PointsToAnalysis.PointsToDataFlowOperationVisitor.cs +++ b/src/Utilities/FlowAnalysis/FlowAnalysis/Analysis/PointsToAnalysis/PointsToAnalysis.PointsToDataFlowOperationVisitor.cs @@ -715,13 +715,13 @@ public override PointsToAbstractValue DefaultVisit(IOperation operation, object? return ValueDomain.UnknownOrMayBeValue; } - public override PointsToAbstractValue VisitIsType(IIsTypeOperation operation, object argument) + public override PointsToAbstractValue VisitIsType(IIsTypeOperation operation, object? argument) { _ = base.VisitIsType(operation, argument); return PointsToAbstractValue.NoLocation; } - public override PointsToAbstractValue VisitInstanceReference(IInstanceReferenceOperation operation, object argument) + public override PointsToAbstractValue VisitInstanceReference(IInstanceReferenceOperation operation, object? argument) { _ = base.VisitInstanceReference(operation, argument); IOperation? currentInstanceOperation = operation.GetInstance(IsInsideAnonymousObjectInitializer); @@ -734,8 +734,8 @@ public override PointsToAbstractValue VisitInstanceReference(IInstanceReferenceO private PointsToAbstractValue VisitTypeCreationWithArgumentsAndInitializer( TOperation operation, - object argument, - Func baseVisit) + object? argument, + Func baseVisit) where TOperation : IOperation { AbstractLocation location = AbstractLocation.CreateAllocationLocation(operation, operation.Type, DataFlowAnalysisContext); @@ -747,22 +747,22 @@ public override PointsToAbstractValue VisitInstanceReference(IInstanceReferenceO return pointsToAbstractValue; } - public override PointsToAbstractValue VisitObjectCreation(IObjectCreationOperation operation, object argument) + public override PointsToAbstractValue VisitObjectCreation(IObjectCreationOperation operation, object? argument) { return VisitTypeCreationWithArgumentsAndInitializer(operation, argument, base.VisitObjectCreation); } - public override PointsToAbstractValue VisitDynamicObjectCreation(IDynamicObjectCreationOperation operation, object argument) + public override PointsToAbstractValue VisitDynamicObjectCreation(IDynamicObjectCreationOperation operation, object? argument) { return VisitTypeCreationWithArgumentsAndInitializer(operation, argument, base.VisitDynamicObjectCreation); } - public override PointsToAbstractValue VisitAnonymousObjectCreation(IAnonymousObjectCreationOperation operation, object argument) + public override PointsToAbstractValue VisitAnonymousObjectCreation(IAnonymousObjectCreationOperation operation, object? argument) { return VisitTypeCreationWithArgumentsAndInitializer(operation, argument, base.VisitAnonymousObjectCreation); } - public override PointsToAbstractValue VisitTuple(ITupleOperation operation, object argument) + public override PointsToAbstractValue VisitTuple(ITupleOperation operation, object? argument) { var type = operation.Type.GetUnderlyingValueTupleTypeOrThis(); AbstractLocation location = AbstractLocation.CreateAllocationLocation(operation, type, DataFlowAnalysisContext); @@ -773,19 +773,19 @@ public override PointsToAbstractValue VisitTuple(ITupleOperation operation, obje return pointsToAbstractValue; } - public override PointsToAbstractValue VisitDelegateCreation(IDelegateCreationOperation operation, object argument) + public override PointsToAbstractValue VisitDelegateCreation(IDelegateCreationOperation operation, object? argument) { _ = base.VisitDelegateCreation(operation, argument); AbstractLocation location = AbstractLocation.CreateAllocationLocation(operation, operation.Type, DataFlowAnalysisContext); return PointsToAbstractValue.Create(location, mayBeNull: false); } - public override PointsToAbstractValue VisitTypeParameterObjectCreation(ITypeParameterObjectCreationOperation operation, object argument) + public override PointsToAbstractValue VisitTypeParameterObjectCreation(ITypeParameterObjectCreationOperation operation, object? argument) { return VisitTypeCreationWithArgumentsAndInitializer(operation, argument, base.VisitTypeParameterObjectCreation); } - public override PointsToAbstractValue VisitArrayInitializer(IArrayInitializerOperation operation, object argument) + public override PointsToAbstractValue VisitArrayInitializer(IArrayInitializerOperation operation, object? argument) { _ = base.VisitArrayInitializer(operation, argument); @@ -795,7 +795,7 @@ public override PointsToAbstractValue VisitArrayInitializer(IArrayInitializerOpe return arrayCreation != null ? GetCachedAbstractValue(arrayCreation) : ValueDomain.UnknownOrMayBeValue; } - public override PointsToAbstractValue VisitArrayCreation(IArrayCreationOperation operation, object argument) + public override PointsToAbstractValue VisitArrayCreation(IArrayCreationOperation operation, object? argument) { var pointsToAbstractValue = PointsToAbstractValue.Create(AbstractLocation.CreateAllocationLocation(operation, operation.Type, DataFlowAnalysisContext), mayBeNull: false); CacheAbstractValue(operation, pointsToAbstractValue); @@ -806,25 +806,25 @@ public override PointsToAbstractValue VisitArrayCreation(IArrayCreationOperation return pointsToAbstractValue; } - public override PointsToAbstractValue VisitInterpolatedString(IInterpolatedStringOperation operation, object argument) + public override PointsToAbstractValue VisitInterpolatedString(IInterpolatedStringOperation operation, object? argument) { _ = base.VisitInterpolatedString(operation, argument); return PointsToAbstractValue.NoLocation; } - public override PointsToAbstractValue VisitBinaryOperatorCore(IBinaryOperation operation, object argument) + public override PointsToAbstractValue VisitBinaryOperatorCore(IBinaryOperation operation, object? argument) { _ = base.VisitBinaryOperatorCore(operation, argument); return PointsToAbstractValue.Unknown; } - public override PointsToAbstractValue VisitSizeOf(ISizeOfOperation operation, object argument) + public override PointsToAbstractValue VisitSizeOf(ISizeOfOperation operation, object? argument) { _ = base.VisitSizeOf(operation, argument); return PointsToAbstractValue.NoLocation; } - public override PointsToAbstractValue VisitTypeOf(ITypeOfOperation operation, object argument) + public override PointsToAbstractValue VisitTypeOf(ITypeOfOperation operation, object? argument) { _ = base.VisitTypeOf(operation, argument); return PointsToAbstractValue.NoLocation; @@ -937,7 +937,7 @@ private static bool IsSpecialEmptyMember(ISymbol symbol) return VisitInvocationCommon(originalOperation, instance: null); } - public override PointsToAbstractValue VisitDynamicInvocation(IDynamicInvocationOperation operation, object argument) + public override PointsToAbstractValue VisitDynamicInvocation(IDynamicInvocationOperation operation, object? argument) { _ = base.VisitDynamicInvocation(operation, argument); return VisitInvocationCommon(operation, operation.Operation); @@ -977,7 +977,7 @@ private PointsToAbstractValue GetValueBasedOnInstanceOrReferenceValue(IOperation }; } - public override PointsToAbstractValue VisitFieldReference(IFieldReferenceOperation operation, object argument) + public override PointsToAbstractValue VisitFieldReference(IFieldReferenceOperation operation, object? argument) { var value = base.VisitFieldReference(operation, argument); @@ -991,7 +991,7 @@ public override PointsToAbstractValue VisitFieldReference(IFieldReferenceOperati return GetValueBasedOnInstanceOrReferenceValue(operation.Instance, operation, value); } - public override PointsToAbstractValue VisitPropertyReference(IPropertyReferenceOperation operation, object argument) + public override PointsToAbstractValue VisitPropertyReference(IPropertyReferenceOperation operation, object? argument) { var value = base.VisitPropertyReference(operation, argument); @@ -1005,37 +1005,37 @@ public override PointsToAbstractValue VisitPropertyReference(IPropertyReferenceO return GetValueBasedOnInstanceOrReferenceValue(operation.Instance, operation, value); } - public override PointsToAbstractValue VisitDynamicMemberReference(IDynamicMemberReferenceOperation operation, object argument) + public override PointsToAbstractValue VisitDynamicMemberReference(IDynamicMemberReferenceOperation operation, object? argument) { var value = base.VisitDynamicMemberReference(operation, argument); return GetValueBasedOnInstanceOrReferenceValue(operation.Instance, operation, value); } - public override PointsToAbstractValue VisitMethodReference(IMethodReferenceOperation operation, object argument) + public override PointsToAbstractValue VisitMethodReference(IMethodReferenceOperation operation, object? argument) { var value = base.VisitMethodReference(operation, argument); return GetValueBasedOnInstanceOrReferenceValue(operation.Instance, operation, value); } - public override PointsToAbstractValue VisitEventReference(IEventReferenceOperation operation, object argument) + public override PointsToAbstractValue VisitEventReference(IEventReferenceOperation operation, object? argument) { var value = base.VisitEventReference(operation, argument); return GetValueBasedOnInstanceOrReferenceValue(operation.Instance, operation, value); } - public override PointsToAbstractValue VisitArrayElementReference(IArrayElementReferenceOperation operation, object argument) + public override PointsToAbstractValue VisitArrayElementReference(IArrayElementReferenceOperation operation, object? argument) { var value = base.VisitArrayElementReference(operation, argument); return GetValueBasedOnInstanceOrReferenceValue(operation.ArrayReference, operation, value); } - public override PointsToAbstractValue VisitDynamicIndexerAccess(IDynamicIndexerAccessOperation operation, object argument) + public override PointsToAbstractValue VisitDynamicIndexerAccess(IDynamicIndexerAccessOperation operation, object? argument) { var value = base.VisitDynamicIndexerAccess(operation, argument); return GetValueBasedOnInstanceOrReferenceValue(operation.Operation, operation, value); } - public override PointsToAbstractValue VisitConversion(IConversionOperation operation, object argument) + public override PointsToAbstractValue VisitConversion(IConversionOperation operation, object? argument) { var value = base.VisitConversion(operation, argument); @@ -1121,7 +1121,7 @@ private static PointsToAbstractValue InferConversionCommon(ConversionInference i } } - public override PointsToAbstractValue VisitFlowCapture(IFlowCaptureOperation operation, object argument) + public override PointsToAbstractValue VisitFlowCapture(IFlowCaptureOperation operation, object? argument) { var value = base.VisitFlowCapture(operation, argument); if (IsLValueFlowCapture(operation) && @@ -1134,7 +1134,7 @@ public override PointsToAbstractValue VisitFlowCapture(IFlowCaptureOperation ope return value; } - public override PointsToAbstractValue VisitFlowCaptureReference(IFlowCaptureReferenceOperation operation, object argument) + public override PointsToAbstractValue VisitFlowCaptureReference(IFlowCaptureReferenceOperation operation, object? argument) { var value = base.VisitFlowCaptureReference(operation, argument); if (IsLValueFlowCaptureReference(operation) && @@ -1157,19 +1157,19 @@ public override PointsToAbstractValue ComputeValueForCompoundAssignment(ICompoun return base.ComputeValueForCompoundAssignment(operation, targetValue, assignedValue, targetType, assignedValueType); } - protected override PointsToAbstractValue VisitAssignmentOperation(IAssignmentOperation operation, object argument) + protected override PointsToAbstractValue VisitAssignmentOperation(IAssignmentOperation operation, object? argument) { var value = base.VisitAssignmentOperation(operation, argument); HandlePossibleEscapingForAssignment(operation.Target, operation.Value, operation); return value; } - public override PointsToAbstractValue VisitDeclarationExpression(IDeclarationExpressionOperation operation, object argument) + public override PointsToAbstractValue VisitDeclarationExpression(IDeclarationExpressionOperation operation, object? argument) { return Visit(operation.Expression, argument); } - public override PointsToAbstractValue VisitCaughtException(ICaughtExceptionOperation operation, object argument) + public override PointsToAbstractValue VisitCaughtException(ICaughtExceptionOperation operation, object? argument) { _ = base.VisitCaughtException(operation, argument); return PointsToAbstractValue.UnknownNotNull; diff --git a/src/Utilities/FlowAnalysis/FlowAnalysis/Analysis/PropertySetAnalysis/PropertySetAnalysis.PropertySetDataFlowOperationVisitor.cs b/src/Utilities/FlowAnalysis/FlowAnalysis/Analysis/PropertySetAnalysis/PropertySetAnalysis.PropertySetDataFlowOperationVisitor.cs index 26abf5b491..4238b721bd 100644 --- a/src/Utilities/FlowAnalysis/FlowAnalysis/Analysis/PropertySetAnalysis/PropertySetAnalysis.PropertySetDataFlowOperationVisitor.cs +++ b/src/Utilities/FlowAnalysis/FlowAnalysis/Analysis/PropertySetAnalysis/PropertySetAnalysis.PropertySetDataFlowOperationVisitor.cs @@ -47,6 +47,7 @@ private sealed partial class PropertySetDataFlowOperationVisitor : /// /// The types containing the property set we're tracking. /// + /// TODO(dotpaul): Consider disallowing null values in this set. private readonly ImmutableHashSet TrackedTypeSymbols; public PropertySetDataFlowOperationVisitor(PropertySetAnalysisContext analysisContext) @@ -155,7 +156,7 @@ protected override void SetAbstractValueForTupleElementAssignment(AnalysisEntity { } - public override PropertySetAbstractValue VisitObjectCreation(IObjectCreationOperation operation, object argument) + public override PropertySetAbstractValue VisitObjectCreation(IObjectCreationOperation operation, object? argument) { PropertySetAbstractValue abstractValue = base.VisitObjectCreation(operation, argument); if (this.TrackedTypeSymbols.Any(s => operation.Type.GetBaseTypesAndThis().Contains(s))) @@ -227,7 +228,7 @@ public override PropertySetAbstractValue VisitObjectCreation(IObjectCreationOper return abstractValue; } - protected override PropertySetAbstractValue VisitAssignmentOperation(IAssignmentOperation operation, object argument) + protected override PropertySetAbstractValue VisitAssignmentOperation(IAssignmentOperation operation, object? argument) { PropertySetAbstractValue? baseValue = base.VisitAssignmentOperation(operation, argument); @@ -410,6 +411,7 @@ internal void ProcessExitBlock(PropertySetBlockAnalysisResult exitBlockOutput) { this.MergeHazardousUsageResult( assignmentOperation.Syntax, + // TODO(dotpaul): Remove the below suppression. #pragma warning disable CS8625 // Cannot convert null literal to non-nullable reference type. methodSymbol: null, // No method invocation; just evaluating initialization value. #pragma warning restore CS8625 // Cannot convert null literal to non-nullable reference type. @@ -436,6 +438,7 @@ internal void ProcessExitBlock(PropertySetBlockAnalysisResult exitBlockOutput) { this.MergeHazardousUsageResult( assignmentOperation.Syntax, + // TODO(dotpaul): Remove the below suppression. #pragma warning disable CS8625 // Cannot convert null literal to non-nullable reference type. methodSymbol: null, // No method invocation; just evaluating initialization value. #pragma warning restore CS8625 // Cannot convert null literal to non-nullable reference type. @@ -483,6 +486,7 @@ public override PropertySetAbstractValue VisitInvocation_NonLambdaOrDelegateOrLo { this.EvaluatePotentialHazardousUsage( visitedArgument.Value.Syntax, + // TODO(dotpaul): Remove the below suppression. #pragma warning disable CS8625 // Cannot convert null literal to non-nullable reference type. null, #pragma warning restore CS8625 // Cannot convert null literal to non-nullable reference type. @@ -503,6 +507,7 @@ public override PropertySetAbstractValue VisitInvocation_NonLambdaOrDelegateOrLo this.EvaluatePotentialHazardousUsage( originalOperation.Syntax, method, + // TODO(dotpaul): Remove the below suppression. #pragma warning disable CS8604 // Possible null reference argument. propertySetInstance, #pragma warning restore CS8604 // Possible null reference argument. @@ -672,6 +677,7 @@ protected override void ProcessReturnValue(IOperation? returnValue) { this.EvaluatePotentialHazardousUsage( returnValue.Syntax, + // TODO(dotpaul): Remove the below suppression. #pragma warning disable CS8625 // Cannot convert null literal to non-nullable reference type. null, #pragma warning restore CS8625 // Cannot convert null literal to non-nullable reference type. diff --git a/src/Utilities/FlowAnalysis/FlowAnalysis/Analysis/TaintedDataAnalysis/TaintedDataAnalysis.TaintedDataOperationVisitor.cs b/src/Utilities/FlowAnalysis/FlowAnalysis/Analysis/TaintedDataAnalysis/TaintedDataAnalysis.TaintedDataOperationVisitor.cs index d35acae70f..4fb256df83 100644 --- a/src/Utilities/FlowAnalysis/FlowAnalysis/Analysis/TaintedDataAnalysis/TaintedDataAnalysis.TaintedDataOperationVisitor.cs +++ b/src/Utilities/FlowAnalysis/FlowAnalysis/Analysis/TaintedDataAnalysis/TaintedDataAnalysis.TaintedDataOperationVisitor.cs @@ -194,7 +194,7 @@ protected override TaintedDataAbstractValue ComputeAnalysisValueForReferenceOper } // So we can hook into constructor calls. - public override TaintedDataAbstractValue VisitObjectCreation(IObjectCreationOperation operation, object argument) + public override TaintedDataAbstractValue VisitObjectCreation(IObjectCreationOperation operation, object? argument) { TaintedDataAbstractValue baseValue = base.VisitObjectCreation(operation, argument); IEnumerable taintedArguments = GetTaintedArguments(operation.Arguments); @@ -348,7 +348,7 @@ public override TaintedDataAbstractValue VisitInvocation_LocalFunction(IMethodSy // So we can treat the array as tainted when it's passed to other object constructors. // See HttpRequest_Form_Array_List_Diagnostic and HttpRequest_Form_List_Diagnostic tests. - public override TaintedDataAbstractValue VisitArrayInitializer(IArrayInitializerOperation operation, object argument) + public override TaintedDataAbstractValue VisitArrayInitializer(IArrayInitializerOperation operation, object? argument) { HashSet? sourceOrigins = null; TaintedDataAbstractValue baseAbstractValue = base.VisitArrayInitializer(operation, argument); @@ -391,7 +391,7 @@ public override TaintedDataAbstractValue VisitArrayInitializer(IArrayInitializer } } - protected override TaintedDataAbstractValue VisitAssignmentOperation(IAssignmentOperation operation, object argument) + protected override TaintedDataAbstractValue VisitAssignmentOperation(IAssignmentOperation operation, object? argument) { TaintedDataAbstractValue taintedDataAbstractValue = base.VisitAssignmentOperation(operation, argument); ProcessAssignmentOperation(operation); diff --git a/src/Utilities/FlowAnalysis/FlowAnalysis/Analysis/TaintedDataAnalysis/TaintedDataSymbolMap.cs b/src/Utilities/FlowAnalysis/FlowAnalysis/Analysis/TaintedDataAnalysis/TaintedDataSymbolMap.cs index 67dafb3ed5..3b86854f13 100644 --- a/src/Utilities/FlowAnalysis/FlowAnalysis/Analysis/TaintedDataAnalysis/TaintedDataSymbolMap.cs +++ b/src/Utilities/FlowAnalysis/FlowAnalysis/Analysis/TaintedDataAnalysis/TaintedDataSymbolMap.cs @@ -13,7 +13,7 @@ namespace Analyzer.Utilities.FlowAnalysis.Analysis.TaintedDataAnalysis /// /// Mapping of to (tainted data source/sanitizer/sink info). /// - internal class TaintedDataSymbolMap : IEquatable> + internal class TaintedDataSymbolMap : IEquatable?> where TInfo : ITaintedDataInfo { public TaintedDataSymbolMap(WellKnownTypeProvider wellKnownTypeProvider, IEnumerable taintedDataInfos) diff --git a/src/Utilities/FlowAnalysis/FlowAnalysis/Analysis/TaintedDataAnalysis/TaintedDataSymbolMapExtensions.cs b/src/Utilities/FlowAnalysis/FlowAnalysis/Analysis/TaintedDataAnalysis/TaintedDataSymbolMapExtensions.cs index b25f1678d2..9c7175b6d1 100644 --- a/src/Utilities/FlowAnalysis/FlowAnalysis/Analysis/TaintedDataAnalysis/TaintedDataSymbolMapExtensions.cs +++ b/src/Utilities/FlowAnalysis/FlowAnalysis/Analysis/TaintedDataAnalysis/TaintedDataSymbolMapExtensions.cs @@ -59,6 +59,7 @@ internal static class TaintedDataSymbolMapExtensions IEnumerable<(PointsToCheck, string target)> positivePointsToTaintedTargets = pointsToTaintedTargets.Where(s => s.pointsToCheck( arguments.Select(o => + // TODO(dotpaul): Remove the below suppression. #pragma warning disable CS8602 // Dereference of a possibly null reference. pointsToAnalysisResult.Value[o.Kind, o.Syntax]).ToImmutableArray())); #pragma warning restore CS8602 // Dereference of a possibly null reference. @@ -81,6 +82,7 @@ internal static class TaintedDataSymbolMapExtensions IEnumerable<(ValueContentCheck, string target)> positiveValueContentTaintedTargets = valueContentTaintedTargets.Where(s => s.valueContentCheck( arguments.Select(o => + // TODO(dotpaul): Remove the below suppression. #pragma warning disable CS8602 // Dereference of a possibly null reference. pointsToAnalysisResult.Value[o.Kind, o.Syntax]).ToImmutableArray(), arguments.Select(o => valueContentAnalysisResult.Value[o.Kind, o.Syntax]).ToImmutableArray())); diff --git a/src/Utilities/FlowAnalysis/FlowAnalysis/Analysis/ValueContentAnalysis/ValueContentAbstractValue.cs b/src/Utilities/FlowAnalysis/FlowAnalysis/Analysis/ValueContentAnalysis/ValueContentAbstractValue.cs index 26ac09fedb..c716e7fe94 100644 --- a/src/Utilities/FlowAnalysis/FlowAnalysis/Analysis/ValueContentAnalysis/ValueContentAbstractValue.cs +++ b/src/Utilities/FlowAnalysis/FlowAnalysis/Analysis/ValueContentAnalysis/ValueContentAbstractValue.cs @@ -207,7 +207,7 @@ private static ValueContainsNonLiteralState Merge(ValueContainsNonLiteralState v /// Literal value, or its default if not a single non-null literal value. /// True if a non-null literal value was found, false otherwise. /// If you're looking for null, you should be looking at . - public bool TryGetSingleNonNullLiteral(out T literalValue) + public bool TryGetSingleNonNullLiteral([MaybeNullWhen(returnValue: false)] out T literalValue) { if (!IsLiteralState || LiteralValues.Count != 1) { @@ -413,15 +413,12 @@ private static bool TryMerge(char value1, char value2, BinaryOperatorKind binary private static bool TryMerge(string value1, string value2, BinaryOperatorKind binaryOperatorKind, [NotNullWhen(returnValue: true)] out object? result) { - if (value1 != null && value2 != null) + switch (binaryOperatorKind) { - switch (binaryOperatorKind) - { - case BinaryOperatorKind.Add: - case BinaryOperatorKind.Concatenate: - result = value1 + value2; - return true; - } + case BinaryOperatorKind.Add: + case BinaryOperatorKind.Concatenate: + result = value1 + value2; + return true; } result = null; diff --git a/src/Utilities/FlowAnalysis/FlowAnalysis/Analysis/ValueContentAnalysis/ValueContentAnalysis.ValueContentDataFlowOperationVisitor.cs b/src/Utilities/FlowAnalysis/FlowAnalysis/Analysis/ValueContentAnalysis/ValueContentAnalysis.ValueContentDataFlowOperationVisitor.cs index 9915f0bec1..db21c5e85a 100644 --- a/src/Utilities/FlowAnalysis/FlowAnalysis/Analysis/ValueContentAnalysis/ValueContentAnalysis.ValueContentDataFlowOperationVisitor.cs +++ b/src/Utilities/FlowAnalysis/FlowAnalysis/Analysis/ValueContentAnalysis/ValueContentAnalysis.ValueContentDataFlowOperationVisitor.cs @@ -187,7 +187,7 @@ public override ValueContentAbstractValue DefaultVisit(IOperation operation, obj return ValueDomain.UnknownOrMayBeValue; } - public override ValueContentAbstractValue VisitBinaryOperatorCore(IBinaryOperation operation, object argument) + public override ValueContentAbstractValue VisitBinaryOperatorCore(IBinaryOperation operation, object? argument) { var leftValue = Visit(operation.LeftOperand, argument); var rightValue = Visit(operation.RightOperand, argument); @@ -212,14 +212,14 @@ public override ValueContentAbstractValue ComputeValueForIncrementOrDecrementOpe return targetValue.MergeBinaryOperation(incrementValue, operationKind, operation.Target.Type, incrementValueType, operation.Type); } - public override ValueContentAbstractValue VisitObjectCreation(IObjectCreationOperation operation, object argument) + public override ValueContentAbstractValue VisitObjectCreation(IObjectCreationOperation operation, object? argument) { // TODO: Analyze string constructor // https://github.com/dotnet/roslyn-analyzers/issues/1547 return base.VisitObjectCreation(operation, argument); } - public override ValueContentAbstractValue VisitFieldReference(IFieldReferenceOperation operation, object argument) + public override ValueContentAbstractValue VisitFieldReference(IFieldReferenceOperation operation, object? argument) { var value = base.VisitFieldReference(operation, argument); @@ -246,7 +246,7 @@ public override ValueContentAbstractValue VisitFieldReference(IFieldReferenceOpe return base.VisitInvocation_NonLambdaOrDelegateOrLocalFunction(method, visitedInstance, visitedArguments, invokedAsDelegate, originalOperation, defaultValue); } - public override ValueContentAbstractValue VisitInterpolatedString(IInterpolatedStringOperation operation, object argument) + public override ValueContentAbstractValue VisitInterpolatedString(IInterpolatedStringOperation operation, object? argument) { if (operation.Parts.IsEmpty) { diff --git a/src/Utilities/FlowAnalysis/FlowAnalysis/Framework/DataFlow/AbstractLocation.cs b/src/Utilities/FlowAnalysis/FlowAnalysis/Framework/DataFlow/AbstractLocation.cs index bc5b60acc6..bd5621cc7d 100644 --- a/src/Utilities/FlowAnalysis/FlowAnalysis/Framework/DataFlow/AbstractLocation.cs +++ b/src/Utilities/FlowAnalysis/FlowAnalysis/Framework/DataFlow/AbstractLocation.cs @@ -110,7 +110,7 @@ protected override void ComputeHashCodeParts(Action addPart) /// Attempts to get the syntax node to report diagnostic for this abstract location /// Returns null if the location is owned by another method invoked through interprocedural analysis. /// - public SyntaxNode? TryGetNodeToReportDiagnostic(PointsToAnalysisResult pointsToAnalysisResultOpt) + public SyntaxNode? TryGetNodeToReportDiagnostic(PointsToAnalysisResult? pointsToAnalysisResultOpt) { Debug.Assert(CreationOpt != null); @@ -119,7 +119,7 @@ protected override void ComputeHashCodeParts(Action addPart) // Attempt to report diagnostic at the bottommost stack frame that owns the location. foreach (var creation in CreationCallStack) { - var syntaxNode = TryGetSyntaxNodeToReportDiagnostic(creation); + var syntaxNode = TryGetSyntaxNodeToReportDiagnostic(creation, pointsToAnalysisResultOpt); if (syntaxNode != null) { return syntaxNode; @@ -137,7 +137,7 @@ protected override void ComputeHashCodeParts(Action addPart) return CreationOpt?.Syntax; // Local functions. - SyntaxNode? TryGetSyntaxNodeToReportDiagnostic(IOperation creation) + SyntaxNode? TryGetSyntaxNodeToReportDiagnostic(IOperation creation, PointsToAnalysisResult pointsToAnalysisResult) { // If any of the argument to creation points to this location, then use the argument. var arguments = creation switch @@ -162,7 +162,7 @@ protected override void ComputeHashCodeParts(Action addPart) SyntaxNode? TryGetSyntaxNodeToReportDiagnosticCore(IOperation operation) { - var pointsToValue = pointsToAnalysisResultOpt[operation]; + var pointsToValue = pointsToAnalysisResult[operation]; return TryGetSyntaxNodeToReportDiagnosticForPointsValue(pointsToValue, operation); SyntaxNode? TryGetSyntaxNodeToReportDiagnosticForPointsValue(PointsToAbstractValue pointsToValue, IOperation operation) @@ -175,8 +175,8 @@ protected override void ComputeHashCodeParts(Action addPart) } } - if (pointsToAnalysisResultOpt.TaskWrappedValuesMapOpt != null && - pointsToAnalysisResultOpt.TaskWrappedValuesMapOpt.TryGetValue(pointsToValue, out var wrappedValue)) + if (pointsToAnalysisResult.TaskWrappedValuesMapOpt != null && + pointsToAnalysisResult.TaskWrappedValuesMapOpt.TryGetValue(pointsToValue, out var wrappedValue)) { return TryGetSyntaxNodeToReportDiagnosticForPointsValue(wrappedValue, operation); } diff --git a/src/Utilities/FlowAnalysis/FlowAnalysis/Framework/DataFlow/AbstractLocationDataFlowOperationVisitor.cs b/src/Utilities/FlowAnalysis/FlowAnalysis/Framework/DataFlow/AbstractLocationDataFlowOperationVisitor.cs index 9f0f1e028c..393cb36c58 100644 --- a/src/Utilities/FlowAnalysis/FlowAnalysis/Framework/DataFlow/AbstractLocationDataFlowOperationVisitor.cs +++ b/src/Utilities/FlowAnalysis/FlowAnalysis/Framework/DataFlow/AbstractLocationDataFlowOperationVisitor.cs @@ -115,17 +115,14 @@ protected override void EscapeValueForParameterOnExit(IParameterSymbol parameter /// /// Helper method to reset analysis data for analysis locations. /// - protected void ResetAnalysisData(DictionaryAnalysisData? currentAnalysisDataOpt) + protected void ResetAnalysisData(DictionaryAnalysisData currentAnalysisData) { // Reset the current analysis data, while ensuring that we don't violate the monotonicity, i.e. we cannot remove any existing key from currentAnalysisData. // Just set the values for existing keys to ValueDomain.UnknownOrMayBeValue. - if (currentAnalysisDataOpt != null) + var keys = currentAnalysisData.Keys.ToImmutableArray(); + foreach (var key in keys) { - var keys = currentAnalysisDataOpt.Keys.ToImmutableArray(); - foreach (var key in keys) - { - SetAbstractValue(key, ValueDomain.UnknownOrMayBeValue); - } + SetAbstractValue(key, ValueDomain.UnknownOrMayBeValue); } } @@ -143,42 +140,42 @@ protected void ResetAnalysisData(DictionaryAnalysisData ComputeAddressSharedEntities() { - RoslynDebug.Assert(assignedValueOpt != null); - RoslynDebug.Assert(assignedValueOpt.AnalysisEntityOpt != null); + RoslynDebug.Assert(assignedValueOpt?.AnalysisEntityOpt != null); var builder = PooledHashSet.GetInstance(); AddIfHasKnownInstanceLocation(analysisEntity, builder); @@ -62,7 +61,7 @@ ImmutableHashSet ComputeAddressSharedEntities() // We need to handle multiple ref/out parameters passed the same location. // For example, "M(ref a, ref a);" - if (_addressSharedEntitiesBuilder.TryGetValue(assignedValueOpt.AnalysisEntityOpt!, out var existingValue)) + if (_addressSharedEntitiesBuilder.TryGetValue(assignedValueOpt.AnalysisEntityOpt, out var existingValue)) { foreach (var entity in existingValue.AnalysisEntities) { diff --git a/src/Utilities/FlowAnalysis/FlowAnalysis/Framework/DataFlow/AnalysisEntityDataFlowOperationVisitor.cs b/src/Utilities/FlowAnalysis/FlowAnalysis/Framework/DataFlow/AnalysisEntityDataFlowOperationVisitor.cs index ee52e1abe9..8a81347e25 100644 --- a/src/Utilities/FlowAnalysis/FlowAnalysis/Framework/DataFlow/AnalysisEntityDataFlowOperationVisitor.cs +++ b/src/Utilities/FlowAnalysis/FlowAnalysis/Framework/DataFlow/AnalysisEntityDataFlowOperationVisitor.cs @@ -21,7 +21,7 @@ namespace Microsoft.CodeAnalysis.FlowAnalysis.DataFlow /// public abstract class AnalysisEntityDataFlowOperationVisitor : DataFlowOperationVisitor - where TAnalysisData : AbstractAnalysisData + where TAnalysisData : AnalysisEntityBasedPredicateAnalysisData where TAnalysisContext : AbstractDataFlowAnalysisContext where TAnalysisResult : class, IDataFlowAnalysisResult where TAbstractAnalysisValue : IEquatable @@ -83,17 +83,14 @@ protected virtual TAbstractAnalysisValue ComputeAnalysisValueForEscapedRefOrOutA /// /// Helper method to reset analysis data for analysis entities. /// - protected void ResetAnalysisData(DictionaryAnalysisData currentAnalysisDataOpt) + protected void ResetAnalysisData(DictionaryAnalysisData currentAnalysisData) { // Reset the current analysis data, while ensuring that we don't violate the monotonicity, i.e. we cannot remove any existing key from currentAnalysisData. // Just set the values for existing keys to ValueDomain.UnknownOrMayBeValue. - if (currentAnalysisDataOpt != null) + var keys = currentAnalysisData.Keys.ToImmutableArray(); + foreach (var key in keys) { - var keys = currentAnalysisDataOpt.Keys.ToImmutableArray(); - foreach (var key in keys) - { - ResetAbstractValue(key); - } + ResetAbstractValue(key); } } @@ -496,10 +493,9 @@ protected sealed override PredicateValueKind ApplyPredicatedDataForEntity(TAnaly protected override void SetPredicateValueKind(IOperation operation, TAnalysisData analysisData, PredicateValueKind predicateValueKind) { base.SetPredicateValueKind(operation, analysisData, predicateValueKind); - if (predicateValueKind == PredicateValueKind.AlwaysFalse && - analysisData is AnalysisEntityBasedPredicateAnalysisData analysisEntityBasedData) + if (predicateValueKind == PredicateValueKind.AlwaysFalse) { - analysisEntityBasedData.IsReachableBlockData = false; + analysisData.IsReachableBlockData = false; } } #endregion @@ -801,7 +797,7 @@ internal bool ShouldStopTrackingEntityAtExit(AnalysisEntity entity) #region Visitor methods - public override TAbstractAnalysisValue VisitDeconstructionAssignment(IDeconstructionAssignmentOperation operation, object argument) + public override TAbstractAnalysisValue VisitDeconstructionAssignment(IDeconstructionAssignmentOperation operation, object? argument) { var value = base.VisitDeconstructionAssignment(operation, argument); var assignedInstance = GetPointsToAbstractValue(operation.Value); diff --git a/src/Utilities/FlowAnalysis/FlowAnalysis/Framework/DataFlow/AnalysisEntityFactory.cs b/src/Utilities/FlowAnalysis/FlowAnalysis/Framework/DataFlow/AnalysisEntityFactory.cs index 80264d58e2..b1c7631eee 100644 --- a/src/Utilities/FlowAnalysis/FlowAnalysis/Framework/DataFlow/AnalysisEntityFactory.cs +++ b/src/Utilities/FlowAnalysis/FlowAnalysis/Framework/DataFlow/AnalysisEntityFactory.cs @@ -288,9 +288,9 @@ public bool TryCreateForSymbolDeclaration(ISymbol symbol, [NotNullWhen(returnVal var indices = ImmutableArray.Empty; IOperation? instance = null; var type = symbol.GetMemberOrLocalOrParameterType(); - Debug.Assert(type != null); + RoslynDebug.Assert(type != null); - return TryCreate(symbol, indices, type!, instance, out analysisEntity); + return TryCreate(symbol, indices, type, instance, out analysisEntity); } public bool TryCreateForTupleElements(ITupleOperation tupleOperation, [NotNullWhen(returnValue: true)] out ImmutableArray elementEntities) @@ -505,8 +505,8 @@ private AnalysisEntity GetOrCreateForFlowCapture(CaptureId captureId, ITypeSymbo private AnalysisEntity Create(ISymbol? symbolOpt, ImmutableArray indices, ITypeSymbol type, PointsToAbstractValue? instanceLocationOpt, AnalysisEntity? parentOpt) { instanceLocationOpt = EnsureLocation(instanceLocationOpt, symbolOpt, parentOpt); - Debug.Assert(instanceLocationOpt != null); - var analysisEntity = AnalysisEntity.Create(symbolOpt, indices, type, instanceLocationOpt!, parentOpt); + RoslynDebug.Assert(instanceLocationOpt != null); + var analysisEntity = AnalysisEntity.Create(symbolOpt, indices, type, instanceLocationOpt, parentOpt); return analysisEntity; } diff --git a/src/Utilities/FlowAnalysis/FlowAnalysis/Framework/DataFlow/CacheBasedEquatable.cs b/src/Utilities/FlowAnalysis/FlowAnalysis/Framework/DataFlow/CacheBasedEquatable.cs index 34db5b8b9d..2c179228ef 100644 --- a/src/Utilities/FlowAnalysis/FlowAnalysis/Framework/DataFlow/CacheBasedEquatable.cs +++ b/src/Utilities/FlowAnalysis/FlowAnalysis/Framework/DataFlow/CacheBasedEquatable.cs @@ -12,7 +12,7 @@ namespace Microsoft.CodeAnalysis.FlowAnalysis.DataFlow /// /// Abstract cache based equatable implementation for objects that are compared frequently and hence need a performance optimization of using a cached hash code. /// - public abstract class CacheBasedEquatable : IEquatable + public abstract class CacheBasedEquatable : IEquatable where T : class { private ImmutableArray _lazyHashCodeParts; diff --git a/src/Utilities/FlowAnalysis/FlowAnalysis/Framework/DataFlow/DataFlowAnalysis.cs b/src/Utilities/FlowAnalysis/FlowAnalysis/Framework/DataFlow/DataFlowAnalysis.cs index 9e40d67639..05fbe1c320 100644 --- a/src/Utilities/FlowAnalysis/FlowAnalysis/Framework/DataFlow/DataFlowAnalysis.cs +++ b/src/Utilities/FlowAnalysis/FlowAnalysis/Framework/DataFlow/DataFlowAnalysis.cs @@ -400,22 +400,24 @@ protected DataFlowAnalysis(AbstractAnalysisDomain analysisDomain, TAnalysisData mergedSuccessorInput; if (needsMerge) { + RoslynDebug.Assert(currentSuccessorInput != null); + // Mark that all input into successorBlockOpt requires a merge as we have non-unique input flow branches into successor block. blockToUniqueInputFlowMap[successorBlockOpt.Ordinal] = null; // Check if the current input data for the successor block is equal to the new input data from this branch. // If so, we don't need to propagate new input data from this branch. - if (AnalysisDomain.Equals(currentSuccessorInput!, newSuccessorInput)) + if (AnalysisDomain.Equals(currentSuccessorInput, newSuccessorInput)) { newSuccessorInput.Dispose(); continue; } // Otherwise, check if the input data for the successor block changes after merging with the new input data. - mergedSuccessorInput = OperationVisitor.MergeAnalysisData(currentSuccessorInput!, newSuccessorInput, isBackEdge); + mergedSuccessorInput = OperationVisitor.MergeAnalysisData(currentSuccessorInput, newSuccessorInput, isBackEdge); newSuccessorInput.Dispose(); - int compare = AnalysisDomain.Compare(currentSuccessorInput!, mergedSuccessorInput); + int compare = AnalysisDomain.Compare(currentSuccessorInput, mergedSuccessorInput); // The newly computed abstract values for each basic block // must be always greater or equal than the previous value diff --git a/src/Utilities/FlowAnalysis/FlowAnalysis/Framework/DataFlow/DataFlowOperationVisitor.cs b/src/Utilities/FlowAnalysis/FlowAnalysis/Framework/DataFlow/DataFlowOperationVisitor.cs index 4bdf244051..669e3a0e2a 100644 --- a/src/Utilities/FlowAnalysis/FlowAnalysis/Framework/DataFlow/DataFlowOperationVisitor.cs +++ b/src/Utilities/FlowAnalysis/FlowAnalysis/Framework/DataFlow/DataFlowOperationVisitor.cs @@ -22,7 +22,7 @@ namespace Microsoft.CodeAnalysis.FlowAnalysis.DataFlow /// /// Operation visitor to flow the abstract dataflow analysis values across a given statement in a basic block. /// - public abstract class DataFlowOperationVisitor : OperationVisitor + public abstract class DataFlowOperationVisitor : OperationVisitor where TAnalysisData : AbstractAnalysisData where TAnalysisContext : AbstractDataFlowAnalysisContext where TAnalysisResult : class, IDataFlowAnalysisResult @@ -2415,7 +2415,7 @@ public override TAbstractAnalysisValue DefaultVisit(IOperation operation, object return VisitArray(operation.Children, argument); } - public override TAbstractAnalysisValue VisitSimpleAssignment(ISimpleAssignmentOperation operation, object argument) + public override TAbstractAnalysisValue VisitSimpleAssignment(ISimpleAssignmentOperation operation, object? argument) { return VisitAssignmentOperation(operation, argument); } @@ -2452,12 +2452,12 @@ public virtual TAbstractAnalysisValue ComputeValueForIncrementOrDecrementOperati return ValueDomain.UnknownOrMayBeValue; } - public override TAbstractAnalysisValue VisitDeconstructionAssignment(IDeconstructionAssignmentOperation operation, object argument) + public override TAbstractAnalysisValue VisitDeconstructionAssignment(IDeconstructionAssignmentOperation operation, object? argument) { return VisitAssignmentOperation(operation, argument); } - protected virtual TAbstractAnalysisValue VisitAssignmentOperation(IAssignmentOperation operation, object argument) + protected virtual TAbstractAnalysisValue VisitAssignmentOperation(IAssignmentOperation operation, object? argument) { _ = Visit(operation.Target, argument); TAbstractAnalysisValue assignedValue = Visit(operation.Value, argument); @@ -2474,7 +2474,7 @@ protected virtual TAbstractAnalysisValue VisitAssignmentOperation(IAssignmentOpe return assignedValue; } - public override TAbstractAnalysisValue VisitArrayInitializer(IArrayInitializerOperation operation, object argument) + public override TAbstractAnalysisValue VisitArrayInitializer(IArrayInitializerOperation operation, object? argument) { var arrayCreation = operation.GetAncestor(OperationKind.ArrayCreation); if (arrayCreation != null) @@ -2496,55 +2496,55 @@ public override TAbstractAnalysisValue VisitArrayInitializer(IArrayInitializerOp return ValueDomain.UnknownOrMayBeValue; } - public override TAbstractAnalysisValue VisitLocalReference(ILocalReferenceOperation operation, object argument) + public override TAbstractAnalysisValue VisitLocalReference(ILocalReferenceOperation operation, object? argument) { var value = base.VisitLocalReference(operation, argument); return ComputeAnalysisValueForReferenceOperation(operation, value); } - public override TAbstractAnalysisValue VisitParameterReference(IParameterReferenceOperation operation, object argument) + public override TAbstractAnalysisValue VisitParameterReference(IParameterReferenceOperation operation, object? argument) { var value = base.VisitParameterReference(operation, argument); return ComputeAnalysisValueForReferenceOperation(operation, value); } - public override TAbstractAnalysisValue VisitArrayElementReference(IArrayElementReferenceOperation operation, object argument) + public override TAbstractAnalysisValue VisitArrayElementReference(IArrayElementReferenceOperation operation, object? argument) { var value = base.VisitArrayElementReference(operation, argument); return ComputeAnalysisValueForReferenceOperation(operation, value); } - public override TAbstractAnalysisValue VisitDynamicMemberReference(IDynamicMemberReferenceOperation operation, object argument) + public override TAbstractAnalysisValue VisitDynamicMemberReference(IDynamicMemberReferenceOperation operation, object? argument) { var value = base.VisitDynamicMemberReference(operation, argument); return ComputeAnalysisValueForReferenceOperation(operation, value); } - public override TAbstractAnalysisValue VisitEventReference(IEventReferenceOperation operation, object argument) + public override TAbstractAnalysisValue VisitEventReference(IEventReferenceOperation operation, object? argument) { var value = base.VisitEventReference(operation, argument); return ComputeAnalysisValueForReferenceOperation(operation, value); } - public override TAbstractAnalysisValue VisitFieldReference(IFieldReferenceOperation operation, object argument) + public override TAbstractAnalysisValue VisitFieldReference(IFieldReferenceOperation operation, object? argument) { var value = base.VisitFieldReference(operation, argument); return ComputeAnalysisValueForReferenceOperation(operation, value); } - public override TAbstractAnalysisValue VisitMethodReference(IMethodReferenceOperation operation, object argument) + public override TAbstractAnalysisValue VisitMethodReference(IMethodReferenceOperation operation, object? argument) { var value = base.VisitMethodReference(operation, argument); return ComputeAnalysisValueForReferenceOperation(operation, value); } - public override TAbstractAnalysisValue VisitPropertyReference(IPropertyReferenceOperation operation, object argument) + public override TAbstractAnalysisValue VisitPropertyReference(IPropertyReferenceOperation operation, object? argument) { var value = base.VisitPropertyReference(operation, argument); return ComputeAnalysisValueForReferenceOperation(operation, value); } - public override TAbstractAnalysisValue VisitFlowCaptureReference(IFlowCaptureReferenceOperation operation, object argument) + public override TAbstractAnalysisValue VisitFlowCaptureReference(IFlowCaptureReferenceOperation operation, object? argument) { var value = base.VisitFlowCaptureReference(operation, argument); if (!IsLValueFlowCaptureReference(operation)) @@ -2591,7 +2591,7 @@ void PerformFlowCaptureReferencePredicateAnalysis() } } - public override TAbstractAnalysisValue VisitFlowCapture(IFlowCaptureOperation operation, object argument) + public override TAbstractAnalysisValue VisitFlowCapture(IFlowCaptureOperation operation, object? argument) { var value = Visit(operation.Value, argument); if (!IsLValueFlowCapture(operation)) @@ -2632,12 +2632,12 @@ void PerformFlowCapturePredicateAnalysis() } } - public override TAbstractAnalysisValue VisitDefaultValue(IDefaultValueOperation operation, object argument) + public override TAbstractAnalysisValue VisitDefaultValue(IDefaultValueOperation operation, object? argument) { return GetAbstractDefaultValue(operation.Type); } - public override TAbstractAnalysisValue VisitInterpolation(IInterpolationOperation operation, object argument) + public override TAbstractAnalysisValue VisitInterpolation(IInterpolationOperation operation, object? argument) { var expressionValue = Visit(operation.Expression, argument); _ = Visit(operation.FormatString, argument); @@ -2645,12 +2645,12 @@ public override TAbstractAnalysisValue VisitInterpolation(IInterpolationOperatio return expressionValue; } - public override TAbstractAnalysisValue VisitInterpolatedStringText(IInterpolatedStringTextOperation operation, object argument) + public override TAbstractAnalysisValue VisitInterpolatedStringText(IInterpolatedStringTextOperation operation, object? argument) { return Visit(operation.Text, argument); } - public sealed override TAbstractAnalysisValue VisitArgument(IArgumentOperation operation, object argument) + public sealed override TAbstractAnalysisValue VisitArgument(IArgumentOperation operation, object? argument) { var value = Visit(operation.Value, argument); @@ -2714,22 +2714,22 @@ private void PostProcessEscapedArgument(IArgumentOperation operation) } } - public override TAbstractAnalysisValue VisitConstantPattern(IConstantPatternOperation operation, object argument) + public override TAbstractAnalysisValue VisitConstantPattern(IConstantPatternOperation operation, object? argument) { return Visit(operation.Value, argument); } - public override TAbstractAnalysisValue VisitParenthesized(IParenthesizedOperation operation, object argument) + public override TAbstractAnalysisValue VisitParenthesized(IParenthesizedOperation operation, object? argument) { return Visit(operation.Operand, argument); } - public override TAbstractAnalysisValue VisitTranslatedQuery(ITranslatedQueryOperation operation, object argument) + public override TAbstractAnalysisValue VisitTranslatedQuery(ITranslatedQueryOperation operation, object? argument) { return Visit(operation.Operation, argument); } - public override TAbstractAnalysisValue VisitConversion(IConversionOperation operation, object argument) + public override TAbstractAnalysisValue VisitConversion(IConversionOperation operation, object? argument) { var operandValue = Visit(operation.Operand, argument); @@ -2737,7 +2737,7 @@ public override TAbstractAnalysisValue VisitConversion(IConversionOperation oper return operation.Conversion.Exists && !operation.Conversion.IsUserDefined ? operandValue : ValueDomain.UnknownOrMayBeValue; } - public override TAbstractAnalysisValue VisitObjectCreation(IObjectCreationOperation operation, object argument) + public override TAbstractAnalysisValue VisitObjectCreation(IObjectCreationOperation operation, object? argument) { Debug.Assert(operation.Initializer == null, "Object or collection initializer must have been lowered in the CFG"); @@ -2750,7 +2750,7 @@ public override TAbstractAnalysisValue VisitObjectCreation(IObjectCreationOperat operation.Arguments, operation, defaultValue, isLambdaOrLocalFunction: false); } - public sealed override TAbstractAnalysisValue VisitInvocation(IInvocationOperation operation, object argument) + public sealed override TAbstractAnalysisValue VisitInvocation(IInvocationOperation operation, object? argument) { TAbstractAnalysisValue value; if (operation.TargetMethod.IsLambdaOrLocalFunctionOrDelegate()) @@ -2843,7 +2843,7 @@ void ProcessInterlockedOperation(IMethodSymbol targetMethod, ImmutableArray? resolvedMethodTargetsOpt) { var value = base.VisitInvocation(operation, argument); @@ -2986,7 +2986,7 @@ void AnalyzePossibleTargetInvocations() VisitInvocation_NonLambdaOrDelegateOrLocalFunction(method, instance, operation.Arguments, invokedAsDelegate: true, originalOperation: operation, defaultValue: defaultValue), inputAnalysisData: savedCurrentAnalysisData, - mergedAnalysisData: mergedCurrentAnalysisData!, + mergedAnalysisData: mergedCurrentAnalysisData, first: ref first); Debug.Assert(!ReferenceEquals(oldMergedAnalysisData, CurrentAnalysisData)); oldMergedAnalysisData?.Dispose(); @@ -3001,7 +3001,7 @@ void AnalyzePossibleTargetInvocations() mergedCurrentAnalysisData = AnalyzePossibleTargetInvocation( computeValueForInvocation: () => VisitInvocation_Lambda(lambda, operation.Arguments, operation, defaultValue), inputAnalysisData: savedCurrentAnalysisData, - mergedAnalysisData: mergedCurrentAnalysisData!, + mergedAnalysisData: mergedCurrentAnalysisData, first: ref first); Debug.Assert(!ReferenceEquals(oldMergedAnalysisData, CurrentAnalysisData)); oldMergedAnalysisData?.Dispose(); @@ -3011,7 +3011,7 @@ void AnalyzePossibleTargetInvocations() Debug.Assert(mergedCurrentAnalysisData == null || ReferenceEquals(mergedCurrentAnalysisData, CurrentAnalysisData)); } - TAnalysisData AnalyzePossibleTargetInvocation(Func computeValueForInvocation, TAnalysisData inputAnalysisData, TAnalysisData mergedAnalysisData, ref bool first) + TAnalysisData AnalyzePossibleTargetInvocation(Func computeValueForInvocation, TAnalysisData inputAnalysisData, TAnalysisData? mergedAnalysisData, ref bool first) { CurrentAnalysisData = GetClonedAnalysisData(inputAnalysisData); var invocationValue = computeValueForInvocation(); @@ -3023,6 +3023,8 @@ TAnalysisData AnalyzePossibleTargetInvocation(Func compu } else { + RoslynDebug.Assert(mergedAnalysisData != null); + value = ValueDomain.Merge(value, invocationValue); var result = MergeAnalysisData(mergedAnalysisData, CurrentAnalysisData); CurrentAnalysisData.Dispose(); @@ -3136,7 +3138,7 @@ private void ResetThisOrMeInstanceAnalysisData() } } - public override TAbstractAnalysisValue VisitTuple(ITupleOperation operation, object argument) + public override TAbstractAnalysisValue VisitTuple(ITupleOperation operation, object? argument) { var elementValueBuilder = ArrayBuilder.GetInstance(operation.Elements.Length); @@ -3183,12 +3185,12 @@ public override TAbstractAnalysisValue VisitTuple(ITupleOperation operation, obj } } - public virtual TAbstractAnalysisValue VisitUnaryOperatorCore(IUnaryOperation operation, object argument) + public virtual TAbstractAnalysisValue VisitUnaryOperatorCore(IUnaryOperation operation, object? argument) { return base.VisitUnaryOperator(operation, argument); } - public sealed override TAbstractAnalysisValue VisitUnaryOperator(IUnaryOperation operation, object argument) + public sealed override TAbstractAnalysisValue VisitUnaryOperator(IUnaryOperation operation, object? argument) { var value = VisitUnaryOperatorCore(operation, argument); if (PredicateAnalysis && operation.OperatorKind == UnaryOperatorKind.Not) @@ -3199,12 +3201,12 @@ public sealed override TAbstractAnalysisValue VisitUnaryOperator(IUnaryOperation return value; } - public virtual TAbstractAnalysisValue VisitBinaryOperatorCore(IBinaryOperation operation, object argument) + public virtual TAbstractAnalysisValue VisitBinaryOperatorCore(IBinaryOperation operation, object? argument) { return base.VisitBinaryOperator(operation, argument); } - public sealed override TAbstractAnalysisValue VisitBinaryOperator(IBinaryOperation operation, object argument) + public sealed override TAbstractAnalysisValue VisitBinaryOperator(IBinaryOperation operation, object? argument) { var value = VisitBinaryOperatorCore(operation, argument); if (PredicateAnalysis && operation.IsComparisonOperator()) @@ -3215,7 +3217,7 @@ public sealed override TAbstractAnalysisValue VisitBinaryOperator(IBinaryOperati return value; } - public override TAbstractAnalysisValue VisitIsNull(IIsNullOperation operation, object argument) + public override TAbstractAnalysisValue VisitIsNull(IIsNullOperation operation, object? argument) { var value = base.VisitIsNull(operation, argument); if (PredicateAnalysis) @@ -3225,7 +3227,7 @@ public override TAbstractAnalysisValue VisitIsNull(IIsNullOperation operation, o return value; } - public override TAbstractAnalysisValue VisitCaughtException(ICaughtExceptionOperation operation, object argument) + public override TAbstractAnalysisValue VisitCaughtException(ICaughtExceptionOperation operation, object? argument) { // Merge data from unhandled exception paths within try that match the caught exception type. if (operation.Type != null) @@ -3281,19 +3283,19 @@ bool ShouldHandlePendingThrow(ThrownExceptionInfo pendingThrow) } } - public override TAbstractAnalysisValue VisitFlowAnonymousFunction(IFlowAnonymousFunctionOperation operation, object argument) + public override TAbstractAnalysisValue VisitFlowAnonymousFunction(IFlowAnonymousFunctionOperation operation, object? argument) { // https://github.com/dotnet/roslyn-analyzers/issues/1571 tracks adding support. return base.VisitFlowAnonymousFunction(operation, argument); } - public override TAbstractAnalysisValue VisitStaticLocalInitializationSemaphore(IStaticLocalInitializationSemaphoreOperation operation, object argument) + public override TAbstractAnalysisValue VisitStaticLocalInitializationSemaphore(IStaticLocalInitializationSemaphoreOperation operation, object? argument) { // https://github.com/dotnet/roslyn-analyzers/issues/1571 tracks adding support. return base.VisitStaticLocalInitializationSemaphore(operation, argument); } - public override TAbstractAnalysisValue VisitAnonymousObjectCreation(IAnonymousObjectCreationOperation operation, object argument) + public override TAbstractAnalysisValue VisitAnonymousObjectCreation(IAnonymousObjectCreationOperation operation, object? argument) { var savedIsInsideAnonymousObjectInitializer = IsInsideAnonymousObjectInitializer; IsInsideAnonymousObjectInitializer = true; @@ -3302,7 +3304,7 @@ public override TAbstractAnalysisValue VisitAnonymousObjectCreation(IAnonymousOb return value; } - public sealed override TAbstractAnalysisValue VisitReturn(IReturnOperation operation, object argument) + public sealed override TAbstractAnalysisValue VisitReturn(IReturnOperation operation, object? argument) { Debug.Assert(operation.Kind == OperationKind.YieldReturn, "IReturnOperation must have been lowered in the CFG"); @@ -3317,7 +3319,7 @@ public virtual TAbstractAnalysisValue GetAssignedValueForPattern(IIsPatternOpera return operandValue; } - public sealed override TAbstractAnalysisValue VisitIsPattern(IIsPatternOperation operation, object argument) + public sealed override TAbstractAnalysisValue VisitIsPattern(IIsPatternOperation operation, object? argument) { // "c is D d" OR "x is 1" var operandValue = Visit(operation.Value, argument); @@ -3340,7 +3342,7 @@ public sealed override TAbstractAnalysisValue VisitIsPattern(IIsPatternOperation return ValueDomain.UnknownOrMayBeValue; } - public override TAbstractAnalysisValue VisitAwait(IAwaitOperation operation, object argument) + public override TAbstractAnalysisValue VisitAwait(IAwaitOperation operation, object? argument) { var value = base.VisitAwait(operation, argument); @@ -3352,187 +3354,187 @@ public override TAbstractAnalysisValue VisitAwait(IAwaitOperation operation, obj #region Overrides for lowered IOperations - public sealed override TAbstractAnalysisValue VisitUsing(IUsingOperation operation, object argument) + public sealed override TAbstractAnalysisValue VisitUsing(IUsingOperation operation, object? argument) { throw new InvalidProgramException($"'{nameof(IUsingOperation)}' must have been lowered in the CFG"); } - public sealed override TAbstractAnalysisValue VisitWhileLoop(IWhileLoopOperation operation, object argument) + public sealed override TAbstractAnalysisValue VisitWhileLoop(IWhileLoopOperation operation, object? argument) { throw new InvalidProgramException($"'{nameof(IWhileLoopOperation)}' must have been lowered in the CFG"); } - public sealed override TAbstractAnalysisValue VisitForEachLoop(IForEachLoopOperation operation, object argument) + public sealed override TAbstractAnalysisValue VisitForEachLoop(IForEachLoopOperation operation, object? argument) { throw new InvalidProgramException($"'{nameof(IForEachLoopOperation)}' must have been lowered in the CFG"); } - public sealed override TAbstractAnalysisValue VisitForLoop(IForLoopOperation operation, object argument) + public sealed override TAbstractAnalysisValue VisitForLoop(IForLoopOperation operation, object? argument) { throw new InvalidProgramException($"'{nameof(IForLoopOperation)}' must have been lowered in the CFG"); } - public sealed override TAbstractAnalysisValue VisitForToLoop(IForToLoopOperation operation, object argument) + public sealed override TAbstractAnalysisValue VisitForToLoop(IForToLoopOperation operation, object? argument) { throw new InvalidProgramException($"'{nameof(IForToLoopOperation)}' must have been lowered in the CFG"); } - public sealed override TAbstractAnalysisValue VisitCoalesce(ICoalesceOperation operation, object argument) + public sealed override TAbstractAnalysisValue VisitCoalesce(ICoalesceOperation operation, object? argument) { throw new InvalidProgramException($"'{nameof(ICoalesceOperation)}' must have been lowered in the CFG"); } - public sealed override TAbstractAnalysisValue VisitConditional(IConditionalOperation operation, object argument) + public sealed override TAbstractAnalysisValue VisitConditional(IConditionalOperation operation, object? argument) { throw new InvalidProgramException($"'{nameof(IConditionalOperation)}' must have been lowered in the CFG"); } - public sealed override TAbstractAnalysisValue VisitConditionalAccess(IConditionalAccessOperation operation, object argument) + public sealed override TAbstractAnalysisValue VisitConditionalAccess(IConditionalAccessOperation operation, object? argument) { throw new InvalidProgramException($"'{nameof(IConditionalAccessOperation)}' must have been lowered in the CFG"); } - public sealed override TAbstractAnalysisValue VisitConditionalAccessInstance(IConditionalAccessInstanceOperation operation, object argument) + public sealed override TAbstractAnalysisValue VisitConditionalAccessInstance(IConditionalAccessInstanceOperation operation, object? argument) { throw new InvalidProgramException($"'{nameof(IConditionalAccessInstanceOperation)}' must have been lowered in the CFG"); } - public sealed override TAbstractAnalysisValue VisitThrow(IThrowOperation operation, object argument) + public sealed override TAbstractAnalysisValue VisitThrow(IThrowOperation operation, object? argument) { throw new InvalidProgramException($"'{nameof(IThrowOperation)}' must have been lowered in the CFG"); } - public sealed override TAbstractAnalysisValue VisitVariableDeclaration(IVariableDeclarationOperation operation, object argument) + public sealed override TAbstractAnalysisValue VisitVariableDeclaration(IVariableDeclarationOperation operation, object? argument) { throw new InvalidProgramException($"'{nameof(IVariableDeclarationOperation)}' must have been lowered in the CFG"); } - public sealed override TAbstractAnalysisValue VisitVariableDeclarationGroup(IVariableDeclarationGroupOperation operation, object argument) + public sealed override TAbstractAnalysisValue VisitVariableDeclarationGroup(IVariableDeclarationGroupOperation operation, object? argument) { throw new InvalidProgramException($"'{nameof(IVariableDeclarationOperation)}' must have been lowered in the CFG"); } - public sealed override TAbstractAnalysisValue VisitVariableDeclarator(IVariableDeclaratorOperation operation, object argument) + public sealed override TAbstractAnalysisValue VisitVariableDeclarator(IVariableDeclaratorOperation operation, object? argument) { throw new InvalidProgramException($"'{nameof(IVariableDeclaratorOperation)}' must have been lowered in the CFG"); } - public sealed override TAbstractAnalysisValue VisitTry(ITryOperation operation, object argument) + public sealed override TAbstractAnalysisValue VisitTry(ITryOperation operation, object? argument) { throw new InvalidProgramException($"'{nameof(ITryOperation)}' must have been lowered in the CFG"); } - public sealed override TAbstractAnalysisValue VisitCatchClause(ICatchClauseOperation operation, object argument) + public sealed override TAbstractAnalysisValue VisitCatchClause(ICatchClauseOperation operation, object? argument) { throw new InvalidProgramException($"'{nameof(ICatchClauseOperation)}' must have been lowered in the CFG"); } - public override TAbstractAnalysisValue VisitLock(ILockOperation operation, object argument) + public override TAbstractAnalysisValue VisitLock(ILockOperation operation, object? argument) { throw new InvalidProgramException($"'{nameof(ILockOperation)}' must have been lowered in the CFG"); } - public sealed override TAbstractAnalysisValue VisitBranch(IBranchOperation operation, object argument) + public sealed override TAbstractAnalysisValue VisitBranch(IBranchOperation operation, object? argument) { throw new InvalidProgramException($"'{nameof(IBranchOperation)}' must have been lowered in the CFG"); } - public sealed override TAbstractAnalysisValue VisitLabeled(ILabeledOperation operation, object argument) + public sealed override TAbstractAnalysisValue VisitLabeled(ILabeledOperation operation, object? argument) { throw new InvalidProgramException($"'{nameof(ILabeledOperation)}' must have been lowered in the CFG"); } - public sealed override TAbstractAnalysisValue VisitSwitch(ISwitchOperation operation, object argument) + public sealed override TAbstractAnalysisValue VisitSwitch(ISwitchOperation operation, object? argument) { throw new InvalidProgramException($"'{nameof(ISwitchOperation)}' must have been lowered in the CFG"); } - public sealed override TAbstractAnalysisValue VisitSwitchCase(ISwitchCaseOperation operation, object argument) + public sealed override TAbstractAnalysisValue VisitSwitchCase(ISwitchCaseOperation operation, object? argument) { throw new InvalidProgramException($"'{nameof(ISwitchCaseOperation)}' must have been lowered in the CFG"); } - public sealed override TAbstractAnalysisValue VisitDefaultCaseClause(IDefaultCaseClauseOperation operation, object argument) + public sealed override TAbstractAnalysisValue VisitDefaultCaseClause(IDefaultCaseClauseOperation operation, object? argument) { throw new InvalidProgramException($"'{nameof(IDefaultCaseClauseOperation)}' must have been lowered in the CFG"); } - public sealed override TAbstractAnalysisValue VisitPatternCaseClause(IPatternCaseClauseOperation operation, object argument) + public sealed override TAbstractAnalysisValue VisitPatternCaseClause(IPatternCaseClauseOperation operation, object? argument) { throw new InvalidProgramException($"'{nameof(IPatternCaseClauseOperation)}' must have been lowered in the CFG"); } - public sealed override TAbstractAnalysisValue VisitRangeCaseClause(IRangeCaseClauseOperation operation, object argument) + public sealed override TAbstractAnalysisValue VisitRangeCaseClause(IRangeCaseClauseOperation operation, object? argument) { throw new InvalidProgramException($"'{nameof(IRangeCaseClauseOperation)}' must have been lowered in the CFG"); } - public sealed override TAbstractAnalysisValue VisitRelationalCaseClause(IRelationalCaseClauseOperation operation, object argument) + public sealed override TAbstractAnalysisValue VisitRelationalCaseClause(IRelationalCaseClauseOperation operation, object? argument) { throw new InvalidProgramException($"'{nameof(IRelationalCaseClauseOperation)}' must have been lowered in the CFG"); } - public sealed override TAbstractAnalysisValue VisitSingleValueCaseClause(ISingleValueCaseClauseOperation operation, object argument) + public sealed override TAbstractAnalysisValue VisitSingleValueCaseClause(ISingleValueCaseClauseOperation operation, object? argument) { throw new InvalidProgramException($"'{nameof(ISingleValueCaseClauseOperation)}' must have been lowered in the CFG"); } - public sealed override TAbstractAnalysisValue VisitObjectOrCollectionInitializer(IObjectOrCollectionInitializerOperation operation, object argument) + public sealed override TAbstractAnalysisValue VisitObjectOrCollectionInitializer(IObjectOrCollectionInitializerOperation operation, object? argument) { throw new InvalidProgramException($"'{nameof(IObjectOrCollectionInitializerOperation)}' must have been lowered in the CFG"); } - public sealed override TAbstractAnalysisValue VisitMemberInitializer(IMemberInitializerOperation operation, object argument) + public sealed override TAbstractAnalysisValue VisitMemberInitializer(IMemberInitializerOperation operation, object? argument) { throw new InvalidProgramException($"'{nameof(IMemberInitializerOperation)}' must have been lowered in the CFG"); } - public sealed override TAbstractAnalysisValue VisitBlock(IBlockOperation operation, object argument) + public sealed override TAbstractAnalysisValue VisitBlock(IBlockOperation operation, object? argument) { throw new InvalidProgramException($"'{nameof(IBlockOperation)}' must have been lowered in the CFG"); } - public sealed override TAbstractAnalysisValue VisitVariableInitializer(IVariableInitializerOperation operation, object argument) + public sealed override TAbstractAnalysisValue VisitVariableInitializer(IVariableInitializerOperation operation, object? argument) { throw new InvalidProgramException($"'{nameof(IVariableInitializerOperation)}' must have been lowered in the CFG"); } - public sealed override TAbstractAnalysisValue VisitFieldInitializer(IFieldInitializerOperation operation, object argument) + public sealed override TAbstractAnalysisValue VisitFieldInitializer(IFieldInitializerOperation operation, object? argument) { throw new InvalidProgramException($"'{nameof(IFieldInitializerOperation)}' must have been lowered in the CFG"); } - public sealed override TAbstractAnalysisValue VisitParameterInitializer(IParameterInitializerOperation operation, object argument) + public sealed override TAbstractAnalysisValue VisitParameterInitializer(IParameterInitializerOperation operation, object? argument) { throw new InvalidProgramException($"'{nameof(IParameterInitializerOperation)}' must have been lowered in the CFG"); } - public sealed override TAbstractAnalysisValue VisitPropertyInitializer(IPropertyInitializerOperation operation, object argument) + public sealed override TAbstractAnalysisValue VisitPropertyInitializer(IPropertyInitializerOperation operation, object? argument) { throw new InvalidProgramException($"'{nameof(IPropertyInitializerOperation)}' must have been lowered in the CFG"); } - public sealed override TAbstractAnalysisValue VisitEnd(IEndOperation operation, object argument) + public sealed override TAbstractAnalysisValue VisitEnd(IEndOperation operation, object? argument) { throw new InvalidProgramException($"'{nameof(IEndOperation)}' must have been lowered in the CFG"); } - public sealed override TAbstractAnalysisValue VisitEmpty(IEmptyOperation operation, object argument) + public sealed override TAbstractAnalysisValue VisitEmpty(IEmptyOperation operation, object? argument) { throw new InvalidProgramException($"'{nameof(IEmptyOperation)}' must have been lowered in the CFG"); } - public sealed override TAbstractAnalysisValue VisitNameOf(INameOfOperation operation, object argument) + public sealed override TAbstractAnalysisValue VisitNameOf(INameOfOperation operation, object? argument) { throw new InvalidProgramException($"'{nameof(INameOfOperation)}' must have been lowered in the CFG"); } - public sealed override TAbstractAnalysisValue VisitAnonymousFunction(IAnonymousFunctionOperation operation, object argument) + public sealed override TAbstractAnalysisValue VisitAnonymousFunction(IAnonymousFunctionOperation operation, object? argument) { throw new InvalidProgramException($"'{nameof(IAnonymousFunctionOperation)}' must have been lowered in the CFG"); } - public sealed override TAbstractAnalysisValue VisitLocalFunction(ILocalFunctionOperation operation, object argument) + public sealed override TAbstractAnalysisValue VisitLocalFunction(ILocalFunctionOperation operation, object? argument) { throw new InvalidProgramException($"'{nameof(ILocalFunctionOperation)}' must have been lowered in the CFG"); } diff --git a/src/Utilities/FlowAnalysis/FlowAnalysis/Framework/DataFlow/DictionaryAnalysisData.cs b/src/Utilities/FlowAnalysis/FlowAnalysis/Framework/DataFlow/DictionaryAnalysisData.cs index b6509684ab..a871014cc3 100644 --- a/src/Utilities/FlowAnalysis/FlowAnalysis/Framework/DataFlow/DictionaryAnalysisData.cs +++ b/src/Utilities/FlowAnalysis/FlowAnalysis/Framework/DataFlow/DictionaryAnalysisData.cs @@ -4,6 +4,7 @@ using System.Collections.Generic; using System.Collections.Immutable; using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; using Analyzer.Utilities.PooledObjects; #pragma warning disable CA1710 // Rename DictionaryAnalysisData to end in 'Dictionary' @@ -13,7 +14,7 @@ namespace Microsoft.CodeAnalysis.FlowAnalysis.DataFlow public sealed class DictionaryAnalysisData : AbstractAnalysisData, IDictionary { #pragma warning disable CA2213 // Disposable fields should be disposed - private PooledDictionary? _coreAnalysisData; + private PooledDictionary _coreAnalysisData; #pragma warning restore public DictionaryAnalysisData() @@ -37,12 +38,12 @@ public DictionaryAnalysisData(IDictionary initializer) get { Debug.Assert(!IsDisposed); - return _coreAnalysisData![key]; + return _coreAnalysisData[key]; } set { Debug.Assert(!IsDisposed); - _coreAnalysisData![key] = value; + _coreAnalysisData[key] = value; } } @@ -51,7 +52,7 @@ public ICollection Keys get { Debug.Assert(!IsDisposed); - return _coreAnalysisData!.Keys; + return _coreAnalysisData.Keys; } } @@ -61,7 +62,7 @@ public ICollection Values { // "Values" might be accessed during dispose. //Debug.Assert(!IsDisposed); - return _coreAnalysisData!.Values; + return _coreAnalysisData.Values; } } @@ -70,7 +71,7 @@ public int Count get { Debug.Assert(!IsDisposed); - return _coreAnalysisData!.Count; + return _coreAnalysisData.Count; } } @@ -79,56 +80,56 @@ public bool IsReadOnly get { Debug.Assert(!IsDisposed); - return ((IDictionary)_coreAnalysisData!).IsReadOnly; + return ((IDictionary)_coreAnalysisData).IsReadOnly; } } public void Add(TKey key, TValue value) { Debug.Assert(!IsDisposed); - _coreAnalysisData!.Add(key, value); + _coreAnalysisData.Add(key, value); } public void Add(KeyValuePair item) { Debug.Assert(!IsDisposed); - _coreAnalysisData!.Add(item.Key, item.Value); + _coreAnalysisData.Add(item.Key, item.Value); } public void Clear() { Debug.Assert(!IsDisposed); - _coreAnalysisData!.Clear(); + _coreAnalysisData.Clear(); } public bool Contains(KeyValuePair item) { Debug.Assert(!IsDisposed); - return ((IDictionary)_coreAnalysisData!).Contains(item); + return ((IDictionary)_coreAnalysisData).Contains(item); } public bool ContainsKey(TKey key) { Debug.Assert(!IsDisposed); - return _coreAnalysisData!.ContainsKey(key); + return _coreAnalysisData.ContainsKey(key); } public void CopyTo(KeyValuePair[] array, int arrayIndex) { Debug.Assert(!IsDisposed); - ((IDictionary)_coreAnalysisData!).CopyTo(array, arrayIndex); + ((IDictionary)_coreAnalysisData).CopyTo(array, arrayIndex); } public IEnumerator> GetEnumerator() { Debug.Assert(!IsDisposed); - return _coreAnalysisData!.GetEnumerator(); + return _coreAnalysisData.GetEnumerator(); } public bool Remove(TKey key) { Debug.Assert(!IsDisposed); - return _coreAnalysisData!.Remove(key); + return _coreAnalysisData.Remove(key); } public bool Remove(KeyValuePair item) @@ -137,16 +138,16 @@ public bool Remove(KeyValuePair item) return Remove(item.Key); } - public bool TryGetValue(TKey key, out TValue value) + public bool TryGetValue(TKey key, [MaybeNullWhen(false)] out TValue value) { Debug.Assert(!IsDisposed); - return _coreAnalysisData!.TryGetValue(key, out value); + return _coreAnalysisData.TryGetValue(key, out value); } IEnumerator IEnumerable.GetEnumerator() { Debug.Assert(!IsDisposed); - return _coreAnalysisData!.GetEnumerator(); + return _coreAnalysisData.GetEnumerator(); } protected override void Dispose(bool disposing) @@ -158,8 +159,8 @@ protected override void Dispose(bool disposing) if (disposing) { - _coreAnalysisData!.Free(); - _coreAnalysisData = null; + _coreAnalysisData.Free(); + _coreAnalysisData = null!; } base.Dispose(disposing); diff --git a/src/Utilities/FlowAnalysis/FlowAnalysis/Framework/DataFlow/PredicatedAnalysisData.cs b/src/Utilities/FlowAnalysis/FlowAnalysis/Framework/DataFlow/PredicatedAnalysisData.cs index 79bab3a5c2..2be44749ea 100644 --- a/src/Utilities/FlowAnalysis/FlowAnalysis/Framework/DataFlow/PredicatedAnalysisData.cs +++ b/src/Utilities/FlowAnalysis/FlowAnalysis/Framework/DataFlow/PredicatedAnalysisData.cs @@ -3,6 +3,7 @@ using System; using System.Collections.Generic; using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; using System.Linq; using Analyzer.Utilities; using Analyzer.Utilities.Extensions; @@ -196,6 +197,7 @@ protected virtual void RemoveEntryInPredicatedData(TKey key, DictionaryAnalysisD predicatedData.Remove(key); } + [return: NotNullIfNotNull(parameterName: "fromData")] private static DictionaryAnalysisData? Clone(DictionaryAnalysisData? fromData) { if (fromData == null) From 533b93e2c59e6b0fe13206b8dcad5ab9c1820cf9 Mon Sep 17 00:00:00 2001 From: Manish Vasani Date: Fri, 15 Nov 2019 18:22:54 -0800 Subject: [PATCH 27/28] Some more fixes --- .../TaintedDataSymbolMapExtensions.cs | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/src/Utilities/FlowAnalysis/FlowAnalysis/Analysis/TaintedDataAnalysis/TaintedDataSymbolMapExtensions.cs b/src/Utilities/FlowAnalysis/FlowAnalysis/Analysis/TaintedDataAnalysis/TaintedDataSymbolMapExtensions.cs index aa9b3c8227..05b92a3aa0 100644 --- a/src/Utilities/FlowAnalysis/FlowAnalysis/Analysis/TaintedDataAnalysis/TaintedDataSymbolMapExtensions.cs +++ b/src/Utilities/FlowAnalysis/FlowAnalysis/Analysis/TaintedDataAnalysis/TaintedDataSymbolMapExtensions.cs @@ -37,8 +37,8 @@ internal static class TaintedDataSymbolMapExtensions [NotNullWhen(returnValue: true)] out PooledHashSet? allTaintedTargets) { allTaintedTargets = null; - PointsToAnalysisResult pointsToAnalysisResult = null; - ValueContentAnalysisResult valueContentAnalysisResult = null; + PointsToAnalysisResult? pointsToAnalysisResult = null; + ValueContentAnalysisResult? valueContentAnalysisResult = null; foreach (SourceInfo sourceInfo in sourceSymbolMap.GetInfosForType(method.ContainingType)) { foreach ((MethodMatcher methodMatcher, ImmutableHashSet taintedTargets) in sourceInfo.TaintedMethods) @@ -67,10 +67,7 @@ internal static class TaintedDataSymbolMapExtensions IEnumerable<(PointsToCheck, string target)> positivePointsToTaintedTargets = pointsToTaintedTargets.Where(s => s.pointsToCheck( arguments.Select(o => - // TODO(dotpaul): Remove the below suppression. -#pragma warning disable CS8602 // Dereference of a possibly null reference. pointsToAnalysisResult[o.Kind, o.Syntax]).ToImmutableArray())); -#pragma warning restore CS8602 // Dereference of a possibly null reference. if (positivePointsToTaintedTargets.Any()) { if (allTaintedTargets == null) @@ -96,11 +93,8 @@ internal static class TaintedDataSymbolMapExtensions IEnumerable<(ValueContentCheck, string target)> positiveValueContentTaintedTargets = valueContentTaintedTargets.Where(s => s.valueContentCheck( - // TODO(dotpaul): Remove the below suppression. -#pragma warning disable CS8602 // Dereference of a possibly null reference. arguments.Select(o => pointsToAnalysisResult[o.Kind, o.Syntax]).ToImmutableArray(), arguments.Select(o => valueContentAnalysisResult[o.Kind, o.Syntax]).ToImmutableArray())); -#pragma warning restore CS8602 // Dereference of a possibly null reference. if (positiveValueContentTaintedTargets.Any()) { if (allTaintedTargets == null) From cbe55d1b9133b3ad45fa56a2b6cefc0f50dc8b5b Mon Sep 17 00:00:00 2001 From: Manish Vasani Date: Mon, 25 Nov 2019 12:57:31 -0800 Subject: [PATCH 28/28] Add nullable annotations after merging latest --- .../TaintedDataAnalysis.CoreTaintedDataAnalysisDataDomain.cs | 2 +- .../ValueContentAnalysis.CoreAnalysisDataDomain.cs | 2 +- .../ValueContentAnalysis.ValueContentAnalysisDomain.cs | 2 +- .../Framework/DataFlow/AnalysisEntityMapAbstractDomain.cs | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Utilities/FlowAnalysis/FlowAnalysis/Analysis/TaintedDataAnalysis/TaintedDataAnalysis.CoreTaintedDataAnalysisDataDomain.cs b/src/Utilities/FlowAnalysis/FlowAnalysis/Analysis/TaintedDataAnalysis/TaintedDataAnalysis.CoreTaintedDataAnalysisDataDomain.cs index 8d27c947fd..f9bfb96f3e 100644 --- a/src/Utilities/FlowAnalysis/FlowAnalysis/Analysis/TaintedDataAnalysis/TaintedDataAnalysis.CoreTaintedDataAnalysisDataDomain.cs +++ b/src/Utilities/FlowAnalysis/FlowAnalysis/Analysis/TaintedDataAnalysis/TaintedDataAnalysis.CoreTaintedDataAnalysisDataDomain.cs @@ -9,7 +9,7 @@ internal partial class TaintedDataAnalysis { private sealed class CoreTaintedDataAnalysisDataDomain : AnalysisEntityMapAbstractDomain { - public CoreTaintedDataAnalysisDataDomain(PointsToAnalysisResult pointsToAnalysisResultOpt) + public CoreTaintedDataAnalysisDataDomain(PointsToAnalysisResult? pointsToAnalysisResultOpt) : base(TaintedDataAbstractValueDomain.Default, pointsToAnalysisResultOpt) { } diff --git a/src/Utilities/FlowAnalysis/FlowAnalysis/Analysis/ValueContentAnalysis/ValueContentAnalysis.CoreAnalysisDataDomain.cs b/src/Utilities/FlowAnalysis/FlowAnalysis/Analysis/ValueContentAnalysis/ValueContentAnalysis.CoreAnalysisDataDomain.cs index 1132f3bcbf..b21909d5c3 100644 --- a/src/Utilities/FlowAnalysis/FlowAnalysis/Analysis/ValueContentAnalysis/ValueContentAnalysis.CoreAnalysisDataDomain.cs +++ b/src/Utilities/FlowAnalysis/FlowAnalysis/Analysis/ValueContentAnalysis/ValueContentAnalysis.CoreAnalysisDataDomain.cs @@ -16,7 +16,7 @@ public partial class ValueContentAnalysis : ForwardDataFlowAnalysis private sealed class CoreAnalysisDataDomain : AnalysisEntityMapAbstractDomain { - public CoreAnalysisDataDomain(AbstractValueDomain valueDomain, PointsToAnalysisResult pointsToAnalysisResultOpt) + public CoreAnalysisDataDomain(AbstractValueDomain valueDomain, PointsToAnalysisResult? pointsToAnalysisResultOpt) : base(valueDomain, pointsToAnalysisResultOpt) { } diff --git a/src/Utilities/FlowAnalysis/FlowAnalysis/Analysis/ValueContentAnalysis/ValueContentAnalysis.ValueContentAnalysisDomain.cs b/src/Utilities/FlowAnalysis/FlowAnalysis/Analysis/ValueContentAnalysis/ValueContentAnalysis.ValueContentAnalysisDomain.cs index 04f8b23c01..7a2ed4106c 100644 --- a/src/Utilities/FlowAnalysis/FlowAnalysis/Analysis/ValueContentAnalysis/ValueContentAnalysis.ValueContentAnalysisDomain.cs +++ b/src/Utilities/FlowAnalysis/FlowAnalysis/Analysis/ValueContentAnalysis/ValueContentAnalysis.ValueContentAnalysisDomain.cs @@ -14,7 +14,7 @@ public partial class ValueContentAnalysis : ForwardDataFlowAnalysis private sealed class ValueContentAnalysisDomain : PredicatedAnalysisDataDomain { - public ValueContentAnalysisDomain(PointsToAnalysisResult pointsToAnalysisResult) + public ValueContentAnalysisDomain(PointsToAnalysisResult? pointsToAnalysisResult) : base(new CoreAnalysisDataDomain(ValueContentAbstractValueDomain.Default, pointsToAnalysisResult)) { } diff --git a/src/Utilities/FlowAnalysis/FlowAnalysis/Framework/DataFlow/AnalysisEntityMapAbstractDomain.cs b/src/Utilities/FlowAnalysis/FlowAnalysis/Framework/DataFlow/AnalysisEntityMapAbstractDomain.cs index 1768e5e0e6..05134568b8 100644 --- a/src/Utilities/FlowAnalysis/FlowAnalysis/Framework/DataFlow/AnalysisEntityMapAbstractDomain.cs +++ b/src/Utilities/FlowAnalysis/FlowAnalysis/Framework/DataFlow/AnalysisEntityMapAbstractDomain.cs @@ -29,7 +29,7 @@ public abstract class AnalysisEntityMapAbstractDomain : MapAbstractDomai _isTrackedPointsToValue = isTrackedPointsToValue ?? throw new ArgumentNullException(nameof(isTrackedPointsToValue)); } - protected AnalysisEntityMapAbstractDomain(AbstractValueDomain valueDomain, PointsToAnalysisResult pointsToAnalysisResultOpt) + protected AnalysisEntityMapAbstractDomain(AbstractValueDomain valueDomain, PointsToAnalysisResult? pointsToAnalysisResultOpt) : this(valueDomain, pointsToAnalysisResultOpt != null ? pointsToAnalysisResultOpt.IsTrackedEntity : s_defaultIsTrackedEntity, pointsToAnalysisResultOpt != null ? pointsToAnalysisResultOpt.IsTrackedPointsToValue : s_defaultIsTrackedPointsToValue)