File: ExtractMethod\CSharpSelectionResult.StatementResult.cs
Web Access
Project: ..\..\..\src\Features\CSharp\Portable\Microsoft.CodeAnalysis.CSharp.Features.csproj (Microsoft.CodeAnalysis.CSharp.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.Linq;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.CodeAnalysis.ExtractMethod;
using Microsoft.CodeAnalysis.Options;
using Microsoft.CodeAnalysis.Shared.Extensions;
using Microsoft.CodeAnalysis.Text;
using Roslyn.Utilities;
 
namespace Microsoft.CodeAnalysis.CSharp.ExtractMethod
{
    internal partial class CSharpSelectionResult
    {
        private class StatementResult : CSharpSelectionResult
        {
            public StatementResult(
                OperationStatus status,
                TextSpan originalSpan,
                TextSpan finalSpan,
                ExtractMethodOptions options,
                bool selectionInExpression,
                SemanticDocument document,
                SyntaxAnnotation firstTokenAnnotation,
                SyntaxAnnotation lastTokenAnnotation)
                : base(status, originalSpan, finalSpan, options, selectionInExpression, document, firstTokenAnnotation, lastTokenAnnotation)
            {
            }
 
            public override bool ContainingScopeHasAsyncKeyword()
            {
                var node = GetContainingScope();
 
                return node switch
                {
                    AccessorDeclarationSyntax _ => false,
                    MethodDeclarationSyntax method => method.Modifiers.Any(SyntaxKind.AsyncKeyword),
                    ParenthesizedLambdaExpressionSyntax lambda => lambda.AsyncKeyword.Kind() == SyntaxKind.AsyncKeyword,
                    SimpleLambdaExpressionSyntax lambda => lambda.AsyncKeyword.Kind() == SyntaxKind.AsyncKeyword,
                    AnonymousMethodExpressionSyntax anonymous => anonymous.AsyncKeyword.Kind() == SyntaxKind.AsyncKeyword,
                    _ => false,
                };
            }
 
            public override SyntaxNode GetContainingScope()
            {
                Contract.ThrowIfNull(SemanticDocument);
                Contract.ThrowIfTrue(SelectionInExpression);
 
                // it contains statements
                var firstToken = GetFirstTokenInSelection();
                return firstToken.GetAncestors<SyntaxNode>().FirstOrDefault(n =>
                {
                    return n is AccessorDeclarationSyntax or
                           LocalFunctionStatementSyntax or
                           BaseMethodDeclarationSyntax or
                           AccessorDeclarationSyntax or
                           ParenthesizedLambdaExpressionSyntax or
                           SimpleLambdaExpressionSyntax or
                           AnonymousMethodExpressionSyntax or
                           CompilationUnitSyntax;
                });
            }
 
            public override ITypeSymbol GetContainingScopeType()
            {
                Contract.ThrowIfTrue(SelectionInExpression);
 
                var node = GetContainingScope();
                var semanticModel = SemanticDocument.SemanticModel;
 
                switch (node)
                {
                    case AccessorDeclarationSyntax access:
                        // property or event case
                        if (access.Parent == null || access.Parent.Parent == null)
                        {
                            return null;
                        }
 
                        return semanticModel.GetDeclaredSymbol(access.Parent.Parent) switch
                        {
                            IPropertySymbol propertySymbol => propertySymbol.Type,
                            IEventSymbol eventSymbol => eventSymbol.Type,
                            _ => null,
                        };
 
                    case MethodDeclarationSyntax method:
                        return semanticModel.GetDeclaredSymbol(method).ReturnType;
 
                    case ParenthesizedLambdaExpressionSyntax lambda:
                        return semanticModel.GetLambdaOrAnonymousMethodReturnType(lambda);
 
                    case SimpleLambdaExpressionSyntax lambda:
                        return semanticModel.GetLambdaOrAnonymousMethodReturnType(lambda);
 
                    case AnonymousMethodExpressionSyntax anonymous:
                        return semanticModel.GetLambdaOrAnonymousMethodReturnType(anonymous);
 
                    default:
                        return null;
                }
            }
        }
    }
}