| File: SplitOrMergeIfStatements\CSharpIfLikeStatementGenerator.cs | Web Access |
| Project: src\roslyn\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; using System.Collections.Immutable; using System.Composition; using Microsoft.CodeAnalysis.CSharp.Extensions; using Microsoft.CodeAnalysis.CSharp.Syntax; using Microsoft.CodeAnalysis.Editing; using Microsoft.CodeAnalysis.Host.Mef; using Microsoft.CodeAnalysis.SplitOrMergeIfStatements; namespace Microsoft.CodeAnalysis.CSharp.SplitOrMergeIfStatements; using static SyntaxFactory; [ExportLanguageService(typeof(IIfLikeStatementGenerator), LanguageNames.CSharp), Shared] internal sealed class CSharpIfLikeStatementGenerator : IIfLikeStatementGenerator { [ImportingConstructor] [Obsolete(MefConstruction.ImportingConstructorMessage, error: true)] public CSharpIfLikeStatementGenerator() { } public bool IsIfOrElseIf(SyntaxNode node) => node is IfStatementSyntax; public bool IsCondition(SyntaxNode expression, out SyntaxNode ifOrElseIf) { if (expression.Parent is IfStatementSyntax ifStatement && ifStatement.Condition == expression) { ifOrElseIf = ifStatement; return true; } ifOrElseIf = null; return false; } public bool IsElseIfClause(SyntaxNode node, out SyntaxNode parentIfOrElseIf) { if (node is IfStatementSyntax && node.Parent is ElseClauseSyntax) { parentIfOrElseIf = (IfStatementSyntax)node.Parent.Parent; return true; } parentIfOrElseIf = null; return false; } public bool HasElseIfClause(SyntaxNode ifOrElseIf, out SyntaxNode elseIfClause) { var ifStatement = (IfStatementSyntax)ifOrElseIf; if (ifStatement.Else?.Statement is IfStatementSyntax elseIfStatement) { elseIfClause = elseIfStatement; return true; } elseIfClause = null; return false; } public SyntaxNode GetCondition(SyntaxNode ifOrElseIf) { var ifStatement = (IfStatementSyntax)ifOrElseIf; return ifStatement.Condition; } public SyntaxNode GetRootIfStatement(SyntaxNode ifOrElseIf) { var ifStatement = (IfStatementSyntax)ifOrElseIf; while (ifStatement.Parent is ElseClauseSyntax elseClause) { ifStatement = (IfStatementSyntax)elseClause.Parent; } return ifStatement; } public ImmutableArray<SyntaxNode> GetElseIfAndElseClauses(SyntaxNode ifOrElseIf) { var ifStatement = (IfStatementSyntax)ifOrElseIf; var builder = ImmutableArray.CreateBuilder<SyntaxNode>(); while (ifStatement.Else?.Statement is IfStatementSyntax elseIfStatement) { builder.Add(elseIfStatement); ifStatement = elseIfStatement; } if (ifStatement.Else != null) { builder.Add(ifStatement.Else); } return builder.ToImmutable(); } public SyntaxNode WithCondition(SyntaxNode ifOrElseIf, SyntaxNode condition) { var ifStatement = (IfStatementSyntax)ifOrElseIf; return ifStatement.WithCondition((ExpressionSyntax)condition); } public SyntaxNode WithStatementInBlock(SyntaxNode ifOrElseIf, SyntaxNode statement) { var ifStatement = (IfStatementSyntax)ifOrElseIf; return ifStatement.WithStatement(Block((StatementSyntax)statement)); } public SyntaxNode WithStatementsOf(SyntaxNode ifOrElseIf, SyntaxNode otherIfOrElseIf) { var ifStatement = (IfStatementSyntax)ifOrElseIf; var otherIfStatement = (IfStatementSyntax)otherIfOrElseIf; return ifStatement.WithStatement(otherIfStatement.Statement); } public SyntaxNode WithElseIfAndElseClausesOf(SyntaxNode ifStatement, SyntaxNode otherIfStatement) => ((IfStatementSyntax)ifStatement).WithElse(((IfStatementSyntax)otherIfStatement).Else); public SyntaxNode ToIfStatement(SyntaxNode ifOrElseIf) => ifOrElseIf; public SyntaxNode ToElseIfClause(SyntaxNode ifOrElseIf) => ((IfStatementSyntax)ifOrElseIf).WithElse(null); public void InsertElseIfClause(SyntaxEditor editor, SyntaxNode afterIfOrElseIf, SyntaxNode elseIfClause) { editor.ReplaceNode(afterIfOrElseIf, (currentNode, _) => { var ifStatement = (IfStatementSyntax)currentNode; var elseIfStatement = (IfStatementSyntax)elseIfClause; var newElseIfStatement = elseIfStatement.WithElse(ifStatement.Else); var newIfStatement = ifStatement.WithElse(ElseClause(newElseIfStatement.WithLeadingTrivia(Space))); if (ifStatement.Else == null && ContainsEmbeddedIfStatement(ifStatement)) { // If the if statement contains an embedded if statement (not wrapped inside a block), adding an else // clause might introduce a dangling else problem (the 'else' would bind to the inner if statement), // so if there used to be no else clause, we'll insert a new block to prevent that. newIfStatement = newIfStatement.WithStatement(Block(newIfStatement.Statement)); } return newIfStatement; }); } public void RemoveElseIfClause(SyntaxEditor editor, SyntaxNode elseIfClause) { editor.ReplaceNode(elseIfClause.Parent.Parent, (currentNode, _) => { var parentIfStatement = (IfStatementSyntax)currentNode; var elseClause = parentIfStatement.Else; var elseIfStatement = (IfStatementSyntax)elseClause.Statement; return parentIfStatement.WithElse(elseIfStatement.Else); }); } private static bool ContainsEmbeddedIfStatement(IfStatementSyntax ifStatement) { for (var statement = ifStatement.Statement; statement.IsEmbeddedStatementOwner(); statement = statement.GetEmbeddedStatement()) { if (statement.IsKind(SyntaxKind.IfStatement)) { return true; } } return false; } }