File: IntroduceVariable\CSharpIntroduceVariableService.Rewriter.cs
Web Access
Project: src\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.
 
using System.Collections.Generic;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.CodeAnalysis.Shared.Extensions;
using Microsoft.CodeAnalysis.Simplification;
 
namespace Microsoft.CodeAnalysis.CSharp.IntroduceVariable;
 
using static SyntaxFactory;
 
internal sealed partial class CSharpIntroduceVariableService
{
    private sealed class Rewriter : CSharpSyntaxRewriter
    {
        private static readonly SyntaxAnnotation s_replacementAnnotation = new();
 
        private readonly SyntaxNode _replacementNode;
        private readonly ISet<ExpressionSyntax> _matches;
 
        private Rewriter(SyntaxNode replacementNode, ISet<ExpressionSyntax> matches)
        {
            _replacementNode = replacementNode;
            _matches = matches;
        }
 
        public override SyntaxNode? Visit(SyntaxNode? node)
        {
            if (node is ExpressionSyntax expression && _matches.Contains(expression))
            {
                return _replacementNode
                    .WithLeadingTrivia(expression.GetLeadingTrivia())
                    .WithTrailingTrivia(expression.GetTrailingTrivia())
                    .WithAdditionalAnnotations(s_replacementAnnotation);
            }
 
            return base.Visit(node);
        }
 
        public override SyntaxNode? VisitAnonymousObjectMemberDeclarator(AnonymousObjectMemberDeclaratorSyntax node)
        {
            var newNode = (AnonymousObjectMemberDeclaratorSyntax)base.VisitAnonymousObjectMemberDeclarator(node)!;
            if (node.NameEquals == null &&
                newNode != node &&
                newNode.Expression.HasAnnotation(s_replacementAnnotation))
            {
                var inferredName = node.Expression.TryGetInferredMemberName();
                if (inferredName != null)
                {
                    return newNode.WithNameEquals(NameEquals(IdentifierName(inferredName))).WithAdditionalAnnotations(Simplifier.Annotation);
                }
            }
 
            return newNode;
        }
 
        public override SyntaxNode? VisitArgument(ArgumentSyntax node)
        {
            var newNode = (ArgumentSyntax)base.VisitArgument(node)!;
            if (node.NameColon == null &&
                newNode != node &&
                newNode.Expression.HasAnnotation(s_replacementAnnotation) &&
                node.Parent is TupleExpressionSyntax)
            {
                var inferredName = node.Expression.TryGetInferredMemberName();
                if (inferredName != null)
                {
                    return newNode.WithNameColon(NameColon(IdentifierName(inferredName))).WithAdditionalAnnotations(Simplifier.Annotation);
                }
            }
 
            return newNode;
        }
 
        public override SyntaxNode? VisitParenthesizedExpression(ParenthesizedExpressionSyntax node)
        {
            var newNode = base.VisitParenthesizedExpression(node);
            if (node != newNode &&
                newNode is ParenthesizedExpressionSyntax parenthesizedExpression)
            {
                var innerExpression = parenthesizedExpression.OpenParenToken.GetNextToken().GetRequiredParent();
                if (innerExpression.HasAnnotation(s_replacementAnnotation))
                {
                    return newNode.WithAdditionalAnnotations(Simplifier.Annotation);
                }
            }
 
            return newNode;
        }
 
        public static SyntaxNode Visit(SyntaxNode node, SyntaxNode replacementNode, ISet<ExpressionSyntax> matches)
            => new Rewriter(replacementNode, matches).Visit(node)!;
    }
}