File: CSharpMoveDeclarationNearReferenceService.cs
Web Access
Project: ..\..\..\src\CodeStyle\CSharp\CodeFixes\Microsoft.CodeAnalysis.CSharp.CodeStyle.Fixes.csproj (Microsoft.CodeAnalysis.CSharp.CodeStyle.Fixes)
// 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.Composition;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis.CSharp.Extensions;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.CodeAnalysis.Host.Mef;
using Microsoft.CodeAnalysis.MoveDeclarationNearReference;
 
namespace Microsoft.CodeAnalysis.CSharp.MoveDeclarationNearReference
{
    [ExportLanguageService(typeof(IMoveDeclarationNearReferenceService), LanguageNames.CSharp), Shared]
    internal partial class CSharpMoveDeclarationNearReferenceService :
        AbstractMoveDeclarationNearReferenceService<
            CSharpMoveDeclarationNearReferenceService,
            StatementSyntax,
            LocalDeclarationStatementSyntax,
            VariableDeclaratorSyntax>
    {
        [ImportingConstructor]
        [Obsolete(MefConstruction.ImportingConstructorMessage, error: true)]
        public CSharpMoveDeclarationNearReferenceService()
        {
        }
 
        protected override bool IsMeaningfulBlock(SyntaxNode node)
        {
            return node is AnonymousFunctionExpressionSyntax or
                   LocalFunctionStatementSyntax or
                   CommonForEachStatementSyntax or
                   ForStatementSyntax or
                   WhileStatementSyntax or
                   DoStatementSyntax or
                   CheckedStatementSyntax;
        }
 
        protected override SyntaxNode GetVariableDeclaratorSymbolNode(VariableDeclaratorSyntax variableDeclarator)
            => variableDeclarator;
 
        protected override bool IsValidVariableDeclarator(VariableDeclaratorSyntax variableDeclarator)
            => true;
 
        protected override SyntaxToken GetIdentifierOfVariableDeclarator(VariableDeclaratorSyntax variableDeclarator)
            => variableDeclarator.Identifier;
 
        protected override async Task<bool> TypesAreCompatibleAsync(
            Document document, ILocalSymbol localSymbol,
            LocalDeclarationStatementSyntax declarationStatement,
            SyntaxNode right, CancellationToken cancellationToken)
        {
            var type = declarationStatement.Declaration.Type;
            if (type.IsVar)
            {
                // Type inference.  Only merge if types match.
                var semanticModel = await document.GetSemanticModelAsync(cancellationToken).ConfigureAwait(false);
                var rightType = semanticModel.GetTypeInfo(right, cancellationToken);
                return Equals(localSymbol.Type, rightType.Type);
            }
 
            return true;
        }
 
        protected override bool CanMoveToBlock(ILocalSymbol localSymbol, SyntaxNode currentBlock, SyntaxNode destinationBlock)
            => localSymbol.CanSafelyMoveLocalToBlock(currentBlock, destinationBlock);
    }
}