File: SymbolUsageAnalysis.OperationTreeAnalysisData.cs
Web Access
Project: ..\..\..\src\CodeStyle\Core\Analyzers\Microsoft.CodeAnalysis.CodeStyle.csproj (Microsoft.CodeAnalysis.CodeStyle)
// 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.
 
#nullable disable
 
using System;
using System.Collections.Immutable;
using System.Threading;
using Microsoft.CodeAnalysis.Operations;
using Microsoft.CodeAnalysis.PooledObjects;
using Microsoft.CodeAnalysis.Shared.Extensions;
using Roslyn.Utilities;
 
namespace Microsoft.CodeAnalysis.FlowAnalysis.SymbolUsageAnalysis
{
    internal static partial class SymbolUsageAnalysis
    {
        private sealed class OperationTreeAnalysisData : AnalysisData
        {
            private readonly Func<IMethodSymbol, BasicBlockAnalysisData> _analyzeLocalFunction;
 
            private OperationTreeAnalysisData(
                PooledDictionary<(ISymbol symbol, IOperation operation), bool> symbolsWriteMap,
                PooledHashSet<ISymbol> symbolsRead,
                PooledHashSet<IMethodSymbol> lambdaOrLocalFunctionsBeingAnalyzed,
                Func<IMethodSymbol, BasicBlockAnalysisData> analyzeLocalFunction)
            {
                _analyzeLocalFunction = analyzeLocalFunction;
                SymbolsWriteBuilder = symbolsWriteMap;
                SymbolsReadBuilder = symbolsRead;
                LambdaOrLocalFunctionsBeingAnalyzed = lambdaOrLocalFunctionsBeingAnalyzed;
            }
 
            protected override PooledHashSet<ISymbol> SymbolsReadBuilder { get; }
 
            protected override PooledDictionary<(ISymbol symbol, IOperation operation), bool> SymbolsWriteBuilder { get; }
 
            protected override PooledHashSet<IMethodSymbol> LambdaOrLocalFunctionsBeingAnalyzed { get; }
 
            public static OperationTreeAnalysisData Create(
                ISymbol owningSymbol,
                Func<IMethodSymbol, BasicBlockAnalysisData> analyzeLocalFunction)
            {
                return new OperationTreeAnalysisData(
                    symbolsWriteMap: CreateSymbolsWriteMap(owningSymbol.GetParameters()),
                    symbolsRead: PooledHashSet<ISymbol>.GetInstance(),
                    lambdaOrLocalFunctionsBeingAnalyzed: PooledHashSet<IMethodSymbol>.GetInstance(),
                    analyzeLocalFunction);
            }
 
            protected override BasicBlockAnalysisData AnalyzeLocalFunctionInvocationCore(IMethodSymbol localFunction, CancellationToken cancellationToken)
            {
                _ = UpdateSymbolsWriteMap(SymbolsWriteBuilder, localFunction.Parameters);
                return _analyzeLocalFunction(localFunction);
            }
 
            // Lambda target needs flow analysis, not supported/reachable in operation tree based analysis.
            protected override BasicBlockAnalysisData AnalyzeLambdaInvocationCore(IFlowAnonymousFunctionOperation lambda, CancellationToken cancellationToken)
                => throw ExceptionUtilities.Unreachable();
 
            public override bool IsLValueFlowCapture(CaptureId captureId)
                => throw ExceptionUtilities.Unreachable();
            public override bool IsRValueFlowCapture(CaptureId captureId)
                => throw ExceptionUtilities.Unreachable();
            public override void OnLValueCaptureFound(ISymbol symbol, IOperation operation, CaptureId captureId)
                => throw ExceptionUtilities.Unreachable();
            public override void OnLValueDereferenceFound(CaptureId captureId)
                => throw ExceptionUtilities.Unreachable();
 
            public override bool IsTrackingDelegateCreationTargets => false;
            public override void SetLambdaTargetForDelegate(IOperation write, IFlowAnonymousFunctionOperation lambdaTarget)
                => throw ExceptionUtilities.Unreachable();
            public override void SetLocalFunctionTargetForDelegate(IOperation write, IMethodReferenceOperation localFunctionTarget)
                => throw ExceptionUtilities.Unreachable();
            public override void SetEmptyInvocationTargetsForDelegate(IOperation write)
                => throw ExceptionUtilities.Unreachable();
            public override void SetTargetsFromSymbolForDelegate(IOperation write, ISymbol symbol)
                => throw ExceptionUtilities.Unreachable();
            public override bool TryGetDelegateInvocationTargets(IOperation write, out ImmutableHashSet<IOperation> targets)
                => throw ExceptionUtilities.Unreachable();
 
            public override void Dispose()
            {
                SymbolsWriteBuilder.Free();
                SymbolsReadBuilder.Free();
                LambdaOrLocalFunctionsBeingAnalyzed.Free();
 
                base.Dispose();
            }
        }
    }
}