File: ExtractMethod\MethodExtractor.VariableInfo.cs
Web Access
Project: src\src\Features\Core\Portable\Microsoft.CodeAnalysis.Features.csproj (Microsoft.CodeAnalysis.Features)
// 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.Generic;
using System.Linq;
using System.Threading;
using Microsoft.CodeAnalysis.PooledObjects;
using Roslyn.Utilities;
 
namespace Microsoft.CodeAnalysis.ExtractMethod;
 
internal abstract partial class MethodExtractor<TSelectionResult, TStatementSyntax, TExpressionSyntax>
{
    protected class VariableInfo(
        VariableSymbol variableSymbol,
        VariableStyle variableStyle,
        bool useAsReturnValue = false) : IComparable<VariableInfo>
    {
        private readonly VariableSymbol _variableSymbol = variableSymbol;
        private readonly VariableStyle _variableStyle = variableStyle;
        private readonly bool _useAsReturnValue = useAsReturnValue;
 
        public bool UseAsReturnValue
        {
            get
            {
                Contract.ThrowIfFalse(!_useAsReturnValue || _variableStyle.ReturnStyle.ReturnBehavior != ReturnBehavior.None);
                return _useAsReturnValue;
            }
        }
 
        public bool CanBeUsedAsReturnValue
        {
            get
            {
                return _variableStyle.ReturnStyle.ReturnBehavior != ReturnBehavior.None;
            }
        }
 
        public bool UseAsParameter
        {
            get
            {
                return (!_useAsReturnValue && _variableStyle.ParameterStyle.ParameterBehavior != ParameterBehavior.None) ||
                       (_useAsReturnValue && _variableStyle.ReturnStyle.ParameterBehavior != ParameterBehavior.None);
            }
        }
 
        public ParameterBehavior ParameterModifier
        {
            get
            {
                return _useAsReturnValue ? _variableStyle.ReturnStyle.ParameterBehavior : _variableStyle.ParameterStyle.ParameterBehavior;
            }
        }
 
        public DeclarationBehavior GetDeclarationBehavior(CancellationToken cancellationToken)
        {
            if (_useAsReturnValue)
            {
                return _variableStyle.ReturnStyle.DeclarationBehavior;
            }
 
            if (_variableSymbol.GetUseSaferDeclarationBehavior(cancellationToken))
            {
                return _variableStyle.ParameterStyle.SaferDeclarationBehavior;
            }
 
            return _variableStyle.ParameterStyle.DeclarationBehavior;
        }
 
        public ReturnBehavior ReturnBehavior
        {
            get
            {
                if (_useAsReturnValue)
                {
                    return _variableStyle.ReturnStyle.ReturnBehavior;
                }
 
                return ReturnBehavior.None;
            }
        }
 
        public static VariableInfo CreateReturnValue(VariableInfo variable)
        {
            Contract.ThrowIfNull(variable);
            Contract.ThrowIfFalse(variable.CanBeUsedAsReturnValue);
            Contract.ThrowIfFalse(variable.ParameterModifier is ParameterBehavior.Out or ParameterBehavior.Ref);
 
            return new VariableInfo(variable._variableSymbol, variable._variableStyle, useAsReturnValue: true);
        }
 
        public void AddIdentifierTokenAnnotationPair(
            List<(SyntaxToken, SyntaxAnnotation)> annotations, CancellationToken cancellationToken)
        {
            _variableSymbol.AddIdentifierTokenAnnotationPair(annotations, cancellationToken);
        }
 
        public string Name => _variableSymbol.Name;
 
        /// <summary>
        /// Returns true, if the variable could be either passed as a parameter
        /// to the new local function or the local function can capture the variable.
        /// </summary>
        public bool CanBeCapturedByLocalFunction
            => _variableSymbol.CanBeCapturedByLocalFunction;
 
        public bool OriginalTypeHadAnonymousTypeOrDelegate => _variableSymbol.OriginalTypeHadAnonymousTypeOrDelegate;
 
        public ITypeSymbol OriginalType => _variableSymbol.OriginalType;
 
        public ITypeSymbol GetVariableType()
            => _variableSymbol.OriginalType;
 
        public SyntaxToken GetIdentifierTokenAtDeclaration(SemanticDocument document)
            => document.GetTokenWithAnnotation(_variableSymbol.IdentifierTokenAnnotation);
 
        public SyntaxToken GetIdentifierTokenAtDeclaration(SyntaxNode node)
            => node.GetAnnotatedTokens(_variableSymbol.IdentifierTokenAnnotation).SingleOrDefault();
 
        public SyntaxToken GetOriginalIdentifierToken(CancellationToken cancellationToken) => _variableSymbol.GetOriginalIdentifierToken(cancellationToken);
 
        public static void SortVariables(ArrayBuilder<VariableInfo> variables)
            => variables.Sort();
 
        public int CompareTo(VariableInfo other)
            => VariableSymbol.Compare(this._variableSymbol, other._variableSymbol);
    }
}