File: src\RoslynAnalyzers\Utilities\FlowAnalysis\FlowAnalysis\Analysis\PointsToAnalysis\DefaultPointsToValueGenerator.cs
Web Access
Project: src\src\RoslynAnalyzers\Microsoft.CodeAnalysis.AnalyzerUtilities\Microsoft.CodeAnalysis.AnalyzerUtilities.csproj (Microsoft.CodeAnalysis.AnalyzerUtilities)
// 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.
 
using System.Collections.Immutable;
using Analyzer.Utilities.Extensions;
 
namespace Microsoft.CodeAnalysis.FlowAnalysis.DataFlow.PointsToAnalysis
{
    /// <summary>
    /// Generates and stores the default <see cref="PointsToAbstractValue"/> for <see cref="AnalysisEntity"/> instances generated for member and element reference operations.
    /// </summary>
    internal sealed class DefaultPointsToValueGenerator
    {
        private readonly TrackedEntitiesBuilder _trackedEntitiesBuilder;
        private readonly ImmutableDictionary<AnalysisEntity, PointsToAbstractValue>.Builder _defaultPointsToValueMapBuilder;
 
        public DefaultPointsToValueGenerator(TrackedEntitiesBuilder trackedEntitiesBuilder)
        {
            _trackedEntitiesBuilder = trackedEntitiesBuilder;
            _defaultPointsToValueMapBuilder = ImmutableDictionary.CreateBuilder<AnalysisEntity, PointsToAbstractValue>();
        }
 
        public PointsToAnalysisKind PointsToAnalysisKind => _trackedEntitiesBuilder.PointsToAnalysisKind;
 
        public PointsToAbstractValue GetOrCreateDefaultValue(AnalysisEntity analysisEntity)
        {
            if (!_defaultPointsToValueMapBuilder.TryGetValue(analysisEntity, out var value))
            {
                if (analysisEntity.Symbol?.Kind == SymbolKind.Local ||
                    analysisEntity.Symbol is IParameterSymbol parameter && parameter.RefKind == RefKind.Out ||
                    analysisEntity.CaptureId != null)
                {
                    return PointsToAbstractValue.Undefined;
                }
                else if (analysisEntity.Type.IsNonNullableValueType())
                {
                    return PointsToAbstractValue.NoLocation;
                }
                else if (analysisEntity.HasUnknownInstanceLocation)
                {
                    return PointsToAbstractValue.Unknown;
                }
 
                value = PointsToAbstractValue.Create(AbstractLocation.CreateAnalysisEntityDefaultLocation(analysisEntity), mayBeNull: true);
 
                // PERF: Do not track entity and its points to value for partial analysis for entities requiring complete analysis.
                if (analysisEntity.ShouldBeTrackedForPointsToAnalysis(PointsToAnalysisKind))
                {
                    _trackedEntitiesBuilder.AddEntityAndPointsToValue(analysisEntity, value);
                    _defaultPointsToValueMapBuilder.Add(analysisEntity, value);
                }
            }
 
            return value;
        }
 
        public bool IsTrackedEntity(AnalysisEntity analysisEntity) => _defaultPointsToValueMapBuilder.ContainsKey(analysisEntity);
        public bool IsTrackedPointsToValue(PointsToAbstractValue value) => _trackedEntitiesBuilder.IsTrackedPointsToValue(value);
        public void AddTrackedPointsToValue(PointsToAbstractValue value) => _trackedEntitiesBuilder.AddTrackedPointsToValue(value);
        public bool HasAnyTrackedEntity => _defaultPointsToValueMapBuilder.Count > 0;
    }
}