File: CodeActions\InlineMethod\CSharpInlineMethodTests.cs
Web Access
Project: src\src\EditorFeatures\CSharpTest\Microsoft.CodeAnalysis.CSharp.EditorFeatures.UnitTests.csproj (Microsoft.CodeAnalysis.CSharp.EditorFeatures.UnitTests)
// 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.Collections.Generic;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis.CSharp.CodeRefactorings.InlineMethod;
using Microsoft.CodeAnalysis.Editor.UnitTests.CodeActions;
using Microsoft.CodeAnalysis.Test.Utilities;
using Microsoft.CodeAnalysis.Testing;
using Xunit;
 
namespace Microsoft.CodeAnalysis.Editor.CSharp.UnitTests.InlineMethod;
 
[UseExportProvider]
[Trait(Traits.Feature, Traits.Features.CodeActionsInlineMethod)]
public class CSharpInlineMethodTests
{
    private class TestVerifier : CSharpCodeRefactoringVerifier<CSharpInlineMethodRefactoringProvider>.Test
    {
        private const string Marker = "##";
 
        public static async Task TestInRegularScriptsInDifferentFilesAsync(
            string initialMarkUpForFile1,
            string initialMarkUpForFile2,
            string expectedMarkUpForFile1,
            string expectedMarkUpForFile2,
            List<DiagnosticResult> diagnosticResults = null,
            bool keepInlinedMethod = true)
        {
            diagnosticResults ??= [];
            var test = new TestVerifier
            {
                CodeActionIndex = keepInlinedMethod ? 1 : 0,
                TestState =
                {
                    Sources =
                    {
                        ("File1", initialMarkUpForFile1),
                        ("File2", initialMarkUpForFile2),
                    }
                },
                FixedState =
                {
                    Sources =
                    {
                        ("File1", expectedMarkUpForFile1),
                        ("File2", expectedMarkUpForFile2),
                    }
                },
                CodeActionValidationMode = CodeActionValidationMode.None,
                LanguageVersion = CodeAnalysis.CSharp.LanguageVersion.CSharp9,
            };
            test.FixedState.ExpectedDiagnostics.AddRange(diagnosticResults);
            await test.RunAsync().ConfigureAwait(false);
        }
 
        public static async Task TestInRegularAndScriptInTheSameFileAsync(
            string initialMarkUp,
            string expectedMarkUp,
            List<DiagnosticResult> diagnosticResults = null,
            bool keepInlinedMethod = true)
        {
            diagnosticResults ??= [];
            var test = new TestVerifier
            {
                CodeActionIndex = keepInlinedMethod ? 1 : 0,
                TestState =
                {
                    Sources = { initialMarkUp }
                },
                FixedState =
                {
                    Sources = { expectedMarkUp },
                },
                CodeActionValidationMode = CodeActionValidationMode.None,
                LanguageVersion = CodeAnalysis.CSharp.LanguageVersion.CSharp9,
            };
            test.FixedState.ExpectedDiagnostics.AddRange(diagnosticResults);
            await test.RunAsync().ConfigureAwait(false);
        }
 
        public static async Task TestBothKeepAndRemoveInlinedMethodInDifferentFileAsync(
            string initialMarkUpForCaller,
            string initialMarkUpForCallee,
            string expectedMarkUpForCaller,
            string expectedMarkUpForCallee,
            List<DiagnosticResult> diagnosticResultsWhenKeepInlinedMethod = null,
            List<DiagnosticResult> diagnosticResultsWhenRemoveInlinedMethod = null)
        {
            var firstMarkerIndex = expectedMarkUpForCallee.IndexOf(Marker);
            var secondMarkerIndex = expectedMarkUpForCallee.LastIndexOf(Marker);
            if (firstMarkerIndex == -1 || secondMarkerIndex == -1 || firstMarkerIndex == secondMarkerIndex)
            {
                Assert.True(false, "Can't find proper marks that contains inlined method.");
            }
 
            var firstPartitionBeforeMarkUp = expectedMarkUpForCallee[..firstMarkerIndex];
            var inlinedMethod = expectedMarkUpForCallee.Substring(firstMarkerIndex + 2, secondMarkerIndex - firstMarkerIndex - 2);
            var lastPartitionAfterMarkup = expectedMarkUpForCallee[(secondMarkerIndex + 2)..];
 
            await TestInRegularScriptsInDifferentFilesAsync(
                initialMarkUpForCaller,
                initialMarkUpForCallee,
                expectedMarkUpForCaller,
                string.Concat(firstPartitionBeforeMarkUp, inlinedMethod, lastPartitionAfterMarkup),
                diagnosticResultsWhenKeepInlinedMethod,
                keepInlinedMethod: true).ConfigureAwait(false);
 
            await TestInRegularScriptsInDifferentFilesAsync(
                initialMarkUpForCaller,
                initialMarkUpForCallee,
                expectedMarkUpForCaller,
                string.Concat(firstPartitionBeforeMarkUp, lastPartitionAfterMarkup),
                diagnosticResultsWhenRemoveInlinedMethod,
                keepInlinedMethod: false).ConfigureAwait(false);
        }
 
        public static async Task TestBothKeepAndRemoveInlinedMethodInSameFileAsync(
            string initialMarkUp,
            string expectedMarkUp,
            List<DiagnosticResult> diagnosticResultsWhenKeepInlinedMethod = null,
            List<DiagnosticResult> diagnosticResultsWhenRemoveInlinedMethod = null)
        {
            var firstMarkerIndex = expectedMarkUp.IndexOf(Marker);
            var secondMarkerIndex = expectedMarkUp.LastIndexOf(Marker);
            if (firstMarkerIndex == -1 || secondMarkerIndex == -1 || firstMarkerIndex == secondMarkerIndex)
            {
                Assert.True(false, "Can't find proper marks that contains inlined method.");
            }
 
            var firstPartitionBeforeMarkUp = expectedMarkUp[..firstMarkerIndex];
            var inlinedMethod = expectedMarkUp.Substring(firstMarkerIndex + 2, secondMarkerIndex - firstMarkerIndex - 2);
            var lastPartitionAfterMarkup = expectedMarkUp[(secondMarkerIndex + 2)..];
 
            await TestInRegularAndScriptInTheSameFileAsync(
                initialMarkUp,
                string.Concat(
                    firstPartitionBeforeMarkUp,
                    inlinedMethod,
                    lastPartitionAfterMarkup),
                diagnosticResultsWhenKeepInlinedMethod,
                keepInlinedMethod: true).ConfigureAwait(false);
 
            await TestInRegularAndScriptInTheSameFileAsync(
                initialMarkUp,
                string.Concat(
                    firstPartitionBeforeMarkUp,
                    lastPartitionAfterMarkup),
                diagnosticResultsWhenRemoveInlinedMethod,
                keepInlinedMethod: false).ConfigureAwait(false);
        }
    }
 
    [Fact]
    public Task TestInlineInvocationExpressionForExpressionStatement()
        => TestVerifier.TestBothKeepAndRemoveInlinedMethodInSameFileAsync(
            """
            using System.Collections.Generic;
            public class TestClass
            {
                private void Caller(int i)
                {
                    var h = new HashSet<int>();
                    Ca[||]llee(i, h);
                }
 
                private bool Callee(int i, HashSet<int> set)
                {
                    return set.Add(i);
                }
            }
            """,
            """
            using System.Collections.Generic;
            public class TestClass
            {
                private void Caller(int i)
                {
                    var h = new HashSet<int>();
                    h.Add(i);
                }
            ##
                private bool Callee(int i, HashSet<int> set)
                {
                    return set.Add(i);
                }
            ##}
            """);
 
    [Fact]
    public Task TestInlineMethodWithSingleStatement()
        => TestVerifier.TestBothKeepAndRemoveInlinedMethodInSameFileAsync(
            """
            public class TestClass
            {
                private void Caller(int i, int j)
                {
                    Ca[||]llee(i, j);
                }
 
                private void Callee(int i, int j)
                {
                    System.Console.WriteLine(i + j);
                }
            }
            """,
            """
            public class TestClass
            {
                private void Caller(int i, int j)
                {
                    System.Console.WriteLine(i + j);
                }
            ##
                private void Callee(int i, int j)
                {
                    System.Console.WriteLine(i + j);
                }
            ##}
            """);
 
    [Fact]
    public Task TestInlineMethodWithSingleStatementAcrossFile()
        => TestVerifier.TestBothKeepAndRemoveInlinedMethodInDifferentFileAsync(
            """
            public partial class TestClass
            {
                private void Caller(int i, int j)
                {
                    Ca[||]llee(i, j);
                }
            }
            """,
            """
            public partial class TestClass
            {
                private void Callee(int i, int j)
                {
                    System.Console.WriteLine(i + j);
                }
            }
            """,
            """
            public partial class TestClass
            {
                private void Caller(int i, int j)
                {
                    System.Console.WriteLine(i + j);
                }
            }
            """,
            """
            public partial class TestClass
            {##
                private void Callee(int i, int j)
                {
                    System.Console.WriteLine(i + j);
                }##
            }
            """);
 
    [Fact]
    public Task TestExtractArrowExpressionBody()
        => TestVerifier.TestBothKeepAndRemoveInlinedMethodInSameFileAsync("""
            public class TestClass
            {
                private void Caller(int i, int j)
                {
                    Ca[||]llee(i, j);
                }
 
                private void Callee(int i, int j)
                    => System.Console.WriteLine(i + j);
            }
            """,
            """
            public class TestClass
            {
                private void Caller(int i, int j)
                {
                    System.Console.WriteLine(i + j);
                }
            ##
                private void Callee(int i, int j)
                    => System.Console.WriteLine(i + j);
            ##}
            """);
 
    [Fact]
    public Task TestExtractArrowExpressionBodyAcrossFile()
        => TestVerifier.TestBothKeepAndRemoveInlinedMethodInDifferentFileAsync(
            """
            public partial class TestClass
            {
                private void Caller(int i, int j)
                {
                    Ca[||]llee(i, j);
                }
            }
            """,
            """
            public partial class TestClass
            {
                private void Callee(int i, int j)
                    => System.Console.WriteLine(i + j);
            }
            """,
            """
            public partial class TestClass
            {
                private void Caller(int i, int j)
                {
                    System.Console.WriteLine(i + j);
                }
            }
            """,
            """
            public partial class TestClass
            {##
                private void Callee(int i, int j)
                    => System.Console.WriteLine(i + j);##
            }
            """);
 
    [Fact]
    public Task TestExtractExpressionBody()
        => TestVerifier.TestBothKeepAndRemoveInlinedMethodInSameFileAsync(
            """
            public class TestClass
            {
                private const int i = 10;
                private const int j = 20;
                private int X = Cal[||]lee(i, j);
 
                private static int Callee(int i, int j)
                    => i + j;
            }
            """,
            """
            public class TestClass
            {
                private const int i = 10;
                private const int j = 20;
                private int X = i + j;
            ##
                private static int Callee(int i, int j)
                    => i + j;
            ##}
            """);
 
    [Fact]
    public Task TestDefaultValueReplacementForExpressionStatement()
        => TestVerifier.TestBothKeepAndRemoveInlinedMethodInSameFileAsync(
            """
            public class TestClass
            {
                private TestClass()
                {
                    Cal[||]lee();
                }
 
                private void Callee(int i = 1, string c = null, bool y = false)
                {
                    System.Console.WriteLine(y ? i : (c ?? "Hello").Length);
                }
            }
            """,
            """
            public class TestClass
            {
                private TestClass()
                {
                    System.Console.WriteLine(false ? 1 : (null ?? "Hello").Length);
                }
            ##
                private void Callee(int i = 1, string c = null, bool y = false)
                {
                    System.Console.WriteLine(y ? i : (c ?? "Hello").Length);
                }
            ##}
            """);
 
    [Fact]
    public Task TestDefaultValueReplacementForExpressionStatementAcrossFile()
        => TestVerifier.TestBothKeepAndRemoveInlinedMethodInDifferentFileAsync(
            """
            public partial class TestClass
            {
                private void Caller()
                {
                    Cal[||]lee();
                }
            }
            """,
            """
            public partial class TestClass
            {
                private void Callee(int i = 1, string c = null, bool y = false)
                {
                    System.Console.WriteLine(y ? i : (c ?? "Hello").Length);
                }
            }
            """,
            """
            public partial class TestClass
            {
                private void Caller()
                {
                    System.Console.WriteLine(false ? 1 : (null ?? "Hello").Length);
                }
            }
            """,
            """
            public partial class TestClass
            {##
                private void Callee(int i = 1, string c = null, bool y = false)
                {
                    System.Console.WriteLine(y ? i : (c ?? "Hello").Length);
                }##
            }
            """);
 
    [Fact]
    public Task TestDefaultValueReplacementForArrowExpression()
        => TestVerifier.TestBothKeepAndRemoveInlinedMethodInSameFileAsync(
            """
            public enum A
            {
                Value1,
                Value2
            }
            public class TestClass
            {
                private void Caller()
                {
                    Cal[||]lee();
                }
 
                private void Callee(int i = default, string c = default, bool y = false, A a = default) =>
                    System.Console.WriteLine((y ? i : (c ?? "Hello").Length) + (int)a);
            }
            """,
            """
            public enum A
            {
                Value1,
                Value2
            }
            public class TestClass
            {
                private void Caller()
                {
                    System.Console.WriteLine((false ? 0 : (null ?? "Hello").Length) + (int)A.Value1);
                }
            ##
                private void Callee(int i = default, string c = default, bool y = false, A a = default) =>
                    System.Console.WriteLine((y ? i : (c ?? "Hello").Length) + (int)a);
            ##}
            """);
 
    [Fact]
    public Task TestInlineMethodWithLiteralValue()
        => TestVerifier.TestBothKeepAndRemoveInlinedMethodInSameFileAsync(
            """
            using System;
            public enum A
            {
                Value1,
                Value2
            }
            public class TestClass
            {
                event EventHandler E
                {
                    add
                    {
                        Cal[||]lee(1, 'y', true, "Hello", A.Value2);
                    }
                    remove
                    {}
                }
 
                private void Callee(int i, char c, bool x, string y, A a) =>
                    System.Console.WriteLine(i + (int)c + (int)a + (x ? 1 : y.Length));
            }
            """,
            """
            using System;
            public enum A
            {
                Value1,
                Value2
            }
            public class TestClass
            {
                event EventHandler E
                {
                    add
                    {
                        System.Console.WriteLine(1 + (int)'y' + (int)A.Value2 + (true ? 1 : "Hello".Length));
                    }
                    remove
                    {}
                }
            ##
                private void Callee(int i, char c, bool x, string y, A a) =>
                    System.Console.WriteLine(i + (int)c + (int)a + (x ? 1 : y.Length));
            ##}
            """);
 
    [Fact]
    public Task TestInlineMethodWithLiteralValueAcrossFile()
        => TestVerifier.TestBothKeepAndRemoveInlinedMethodInDifferentFileAsync(
            """
            public partial class TestClass
            {
                private void Caller()
                {
                    Cal[||]lee(1, 'y', true, "Hello");
                }
            }
            """,
            """
            public partial class TestClass
            {
                private void Callee(int i, char c, bool x, string y) =>
                    System.Console.WriteLine(i + (int)c + (x ? 1 : y.Length));
            }
            """,
            """
            public partial class TestClass
            {
                private void Caller()
                {
                    System.Console.WriteLine(1 + (int)'y' + (true ? 1 : "Hello".Length));
                }
            }
            """,
            """
            public partial class TestClass
            {##
                private void Callee(int i, char c, bool x, string y) =>
                    System.Console.WriteLine(i + (int)c + (x ? 1 : y.Length));##
            }
            """);
 
    [Fact]
    public Task TestInlineMethodWithIdentifierReplacement()
        => TestVerifier.TestBothKeepAndRemoveInlinedMethodInSameFileAsync(
            """
            public class TestClass
            {
                private void Caller(int m)
                {
                    Cal[||]lee(10, m, k: "Hello");
                }
 
                private void Callee(int i, int j = 100, string k = null)
                {
                    System.Console.WriteLine(i + j + (k ?? ""));
                }
            }
            """,
            """
            public class TestClass
            {
                private void Caller(int m)
                {
                    System.Console.WriteLine(10 + m + ("Hello" ?? ""));
                }
            ##
                private void Callee(int i, int j = 100, string k = null)
                {
                    System.Console.WriteLine(i + j + (k ?? ""));
                }
            ##}
            """);
 
    [Fact]
    public Task TestInlineMethodWithIdentifierReplacementAcrossFile()
        => TestVerifier.TestBothKeepAndRemoveInlinedMethodInDifferentFileAsync(
            """
            public partial class TestClass
            {
                private void Caller(int m)
                {
                    Cal[||]lee(10, m, k: "Hello");
                }
            }
            """,
            """
            public partial class TestClass
            {
                private void Callee(int i, int j = 100, string k = null)
                {
                    System.Console.WriteLine(i + j + (k ?? ""));
                }
            }
            """,
            """
            public partial class TestClass
            {
                private void Caller(int m)
                {
                    System.Console.WriteLine(10 + m + ("Hello" ?? ""));
                }
            }
            """, """
            public partial class TestClass
            {##
                private void Callee(int i, int j = 100, string k = null)
                {
                    System.Console.WriteLine(i + j + (k ?? ""));
                }##
            }
            """);
 
    [Fact]
    public Task TestInlineMethodWithNoMethodExtraction()
        => TestVerifier.TestBothKeepAndRemoveInlinedMethodInSameFileAsync(
            """
            public class TestClass
            {
                private void Caller(float r1, float r2)
                {
                    Cal[||]lee(SomeCaculation(r1), SomeCaculation(r2));
                }
 
                private void Callee(float s1, float s2)
                {
                    System.Console.WriteLine("This is s1" + s1 + "This is S2" + s2);
                }
 
                public float SomeCaculation(float r)
                {
                    return r * r * 3.14f;
                }
            }
            """,
            """
            public class TestClass
            {
                private void Caller(float r1, float r2)
                {
                    System.Console.WriteLine("This is s1" + SomeCaculation(r1) + "This is S2" + SomeCaculation(r2));
                }
            ##
                private void Callee(float s1, float s2)
                {
                    System.Console.WriteLine("This is s1" + s1 + "This is S2" + s2);
                }
            ##
                public float SomeCaculation(float r)
                {
                    return r * r * 3.14f;
                }
            }
            """);
 
    [Fact]
    public Task TestInlineMethodWithNoMethodExtractionAcrossFile()
        => TestVerifier.TestBothKeepAndRemoveInlinedMethodInDifferentFileAsync(
            """
            public partial class TestClass
            {
                public void Caller(float r1, float r2)
                {
                    Cal[||]lee(SomeCaculation(r1), SomeCaculation(r2));
                }
 
                public float SomeCaculation(float r)
                {
                    return r * r * 3.14f;
                }
            }
            """,
            """
            public partial class TestClass
            {
                private void Callee(float s1, float s2)
                {
                    System.Console.WriteLine("This is s1" + s1 + "This is S2" + s2);
                }
            }
            """,
            """
            public partial class TestClass
            {
                public void Caller(float r1, float r2)
                {
                    System.Console.WriteLine("This is s1" + SomeCaculation(r1) + "This is S2" + SomeCaculation(r2));
                }
 
                public float SomeCaculation(float r)
                {
                    return r * r * 3.14f;
                }
            }
            """,
            """
            public partial class TestClass
            {##
                private void Callee(float s1, float s2)
                {
                    System.Console.WriteLine("This is s1" + s1 + "This is S2" + s2);
                }##
            }
            """);
 
    [Fact]
    public Task TestInlineParamsArrayWithArrayImplicitInitializerExpression()
        => TestVerifier.TestBothKeepAndRemoveInlinedMethodInSameFileAsync("""
            public class TestClass
            {
                private void Caller()
                {
                    Cal[||]lee(new int[] {1, 2, 3, 4, 5, 6});
                }
 
                private void Callee(params int[] x)
                {
                    System.Console.WriteLine(x.Length);
                }
            }
            """
,
            """
            public class TestClass
            {
                private void Caller()
                {
                    System.Console.WriteLine((new int[] {1, 2, 3, 4, 5, 6}).Length);
                }
            ##
                private void Callee(params int[] x)
                {
                    System.Console.WriteLine(x.Length);
                }
            ##}
            """);
 
    [Fact]
    public Task TestInlineParamsArrayWithArrayImplicitInitializerExpressionAcrossFile()
        => TestVerifier.TestBothKeepAndRemoveInlinedMethodInDifferentFileAsync(
            """
            public partial class TestClass
            {
                private void Caller()
                {
                    Cal[||]lee(new int[] {1, 2, 3, 4, 5, 6});
                }
            }
            """,
            """
            public partial class TestClass
            {
                private void Callee(params int[] x)
                {
                    System.Console.WriteLine(x.Length);
                }
            }
            """,
            """
            public partial class TestClass
            {
                private void Caller()
                {
                    System.Console.WriteLine((new int[] {1, 2, 3, 4, 5, 6}).Length);
                }
            }
            """,
            """
            public partial class TestClass
            {##
                private void Callee(params int[] x)
                {
                    System.Console.WriteLine(x.Length);
                }##
            }
            """);
 
    [Fact]
    public Task TestInlineParamsArrayWithArrayInitializerExpression()
        => TestVerifier.TestBothKeepAndRemoveInlinedMethodInSameFileAsync("""
            public class TestClass
            {
                private void Caller()
                {
                    Cal[||]lee(new int[6] {1, 2, 3, 4, 5, 6});
                }
 
                private void Callee(params int[] x)
                {
                    System.Console.WriteLine(x.Length);
                }
            }
            """
,
            """
            public class TestClass
            {
                private void Caller()
                {
                    System.Console.WriteLine((new int[6] {1, 2, 3, 4, 5, 6}).Length);
                }
            ##
                private void Callee(params int[] x)
                {
                    System.Console.WriteLine(x.Length);
                }
            ##}
            """);
 
    [Fact]
    public Task TestInlineParamsArrayWithArrayInitializerExpressionAcrossFile()
        => TestVerifier.TestBothKeepAndRemoveInlinedMethodInDifferentFileAsync(
            """
            public partial class TestClass
            {
                private void Caller()
                {
                    Cal[||]lee(new int[6] {1, 2, 3, 4, 5, 6});
                }
            }
            """,
            """
            public partial class TestClass
            {
                private void Callee(params int[] x)
                {
                    System.Console.WriteLine(x.Length);
                }
            }
            """,
            """
            public partial class TestClass
            {
                private void Caller()
                {
                    System.Console.WriteLine((new int[6] {1, 2, 3, 4, 5, 6}).Length);
                }
            }
            """,
            """
            public partial class TestClass
            {##
                private void Callee(params int[] x)
                {
                    System.Console.WriteLine(x.Length);
                }##
            }
            """);
 
    [Fact]
    public Task TestInlineParamsArrayWithOneElement()
        => TestVerifier.TestBothKeepAndRemoveInlinedMethodInSameFileAsync("""
            public class TestClass
            {
                private void Caller()
                {
                    Cal[||]lee(1);
                }
 
                private void Callee(params int[] x)
                {
                    System.Console.WriteLine(x.Length);
                }
            }
            """
,
            """
            public class TestClass
            {
                private void Caller()
                {
                    System.Console.WriteLine((new int[] { 1 }).Length);
                }
            ##
                private void Callee(params int[] x)
                {
                    System.Console.WriteLine(x.Length);
                }
            ##}
            """);
 
    [Fact]
    public Task TestInlineParamsArrayWithOneElementAcrossFile()
        => TestVerifier.TestBothKeepAndRemoveInlinedMethodInDifferentFileAsync(
            """
            public partial class TestClass
            {
                private void Caller()
                {
                    Cal[||]lee(1);
                }
            }
            """,
            """
            public partial class TestClass
            {
                private void Callee(params int[] x)
                {
                    System.Console.WriteLine(x.Length);
                }
            }
            """,
            """
            public partial class TestClass
            {
                private void Caller()
                {
                    System.Console.WriteLine((new int[] { 1 }).Length);
                }
            }
            """,
            """
            public partial class TestClass
            {##
                private void Callee(params int[] x)
                {
                    System.Console.WriteLine(x.Length);
                }##
            }
            """);
 
    [Fact]
    public Task TestInlineParamsArrayMethodWithIdentifier()
        => TestVerifier.TestBothKeepAndRemoveInlinedMethodInSameFileAsync("""
            public class TestClass
            {
                private void Caller()
                {
                    var i = new int[] {1, 2, 3, 4, 5};
                    Cal[||]lee(i);
                }
 
                private void Callee(params int[] x)
                {
                    System.Console.WriteLine(x.Length);
                }
            }
            """,
            """
            public class TestClass
            {
                private void Caller()
                {
                    var i = new int[] {1, 2, 3, 4, 5};
                    System.Console.WriteLine(i.Length);
                }
            ##
                private void Callee(params int[] x)
                {
                    System.Console.WriteLine(x.Length);
                }
            ##}
            """);
    [Fact]
    public Task TestInlineMethodWithNoElementInParamsArray()
        => TestVerifier.TestBothKeepAndRemoveInlinedMethodInSameFileAsync(
                """
                public class TestClass
                {
                    private void Caller()
                    {
                        Cal[||]lee();
                    }
 
                    private void Callee(params int[] x)
                    {
                        System.Console.WriteLine(x.Length);
                    }
                }
                """,
                """
                public class TestClass
                {
                    private void Caller()
                    {
                        System.Console.WriteLine((new int[] { }).Length);
                    }
                ##
                    private void Callee(params int[] x)
                    {
                        System.Console.WriteLine(x.Length);
                    }
                ##}
                """);
 
    [Fact]
    public Task TestInlineMethodWithParamsArray()
        => TestVerifier.TestBothKeepAndRemoveInlinedMethodInSameFileAsync(
            """
            public class TestClass
            {
                private void Caller()
                {
                    Ca[||]llee("Hello", 1, 2, 3, 4, 5, 6);
                }
 
                private void Callee(string z, params int[] x)
                {
                    System.Console.WriteLine(x.Length);
                }
            }
            """,
            """
            public class TestClass
            {
                private void Caller()
                {
                    System.Console.WriteLine((new int[] { 1, 2, 3, 4, 5, 6 }).Length);
                }
            ##
                private void Callee(string z, params int[] x)
                {
                    System.Console.WriteLine(x.Length);
                }
            ##}
            """);
 
    [Fact]
    public Task TestInlineMethodWithVariableDeclaration1()
        => TestVerifier.TestBothKeepAndRemoveInlinedMethodInSameFileAsync(
            """
            public class TestClass
            {
                private void Caller()
                {
                    Cal[||]lee(out var x);
                }
 
                private void Callee(out int z)
                {
                    z = 10;
                }
            }
            """,
            """
            public class TestClass
            {
                private void Caller()
                {
                    int x = 10;
                }
            ##
                private void Callee(out int z)
                {
                    z = 10;
                }
            ##}
            """);
 
    [Fact]
    public Task TestInlineMethodWithVariableDeclaration1AcrossFile()
        => TestVerifier.TestBothKeepAndRemoveInlinedMethodInDifferentFileAsync(
            """
            public partial class TestClass
            {
                private void Caller()
                {
                    Cal[||]lee(out var x);
                }
            }
            """,
            """
            public partial class TestClass
            {
                private void Callee(out int z)
                {
                    z = 10;
                }
            }
            """,
            """
            public partial class TestClass
            {
                private void Caller()
                {
                    int x = 10;
                }
            }
            """,
            """
            public partial class TestClass
            {##
                private void Callee(out int z)
                {
                    z = 10;
                }##
            }
            """);
 
    [Fact]
    public Task TestInlineMethodWithVariableDeclaration2()
        => TestVerifier.TestBothKeepAndRemoveInlinedMethodInSameFileAsync(
            """
            public class TestClass
            {
                private void Caller()
                {
                    Cal[||]lee(out var x, out var y, out var z);
                }
 
                private void Callee(out int z, out int x, out int y)
                {
                    z = x = y = 10;
                }
            }
            """,
            """
            public class TestClass
            {
                private void Caller()
                {
                    int x;
                    int y;
                    int z;
                    x = y = z = 10;
                }
            ##
                private void Callee(out int z, out int x, out int y)
                {
                    z = x = y = 10;
                }
            ##}
            """);
 
    [Fact]
    public Task TestInlineMethodWithVariableDeclaration2AcrossFile()
        => TestVerifier.TestBothKeepAndRemoveInlinedMethodInDifferentFileAsync(
            """
            public partial class TestClass
            {
                private void Caller()
                {
                    Cal[||]lee(out var x, out var y, out var z);
                }
            }
            """,
            """
            public partial class TestClass
            {
                private void Callee(out int z, out int x, out int y)
                {
                    z = x = y = 10;
                }
            }
            """,
            """
            public partial class TestClass
            {
                private void Caller()
                {
                    int x;
                    int y;
                    int z;
                    x = y = z = 10;
                }
            }
            """,
            """
            public partial class TestClass
            {##
                private void Callee(out int z, out int x, out int y)
                {
                    z = x = y = 10;
                }##
            }
            """);
 
    [Fact]
    public Task TestInlineMethodWithVariableDeclaration3()
        => TestVerifier.TestBothKeepAndRemoveInlinedMethodInSameFileAsync(
            """
            public class TestClass
            {
                private void Caller()
                {
                    Cal[||]lee(out var x);
                }
 
                private void Callee(out int z)
                {
                    DoSometing(out z);
                }
 
                private void DoSometing(out int z)
                {
                    z = 100;
                }
            }
            """,
            """
            public class TestClass
            {
                private void Caller()
                {
                    int x;
                    DoSometing(out x);
                }
            ##
                private void Callee(out int z)
                {
                    DoSometing(out z);
                }
            ##
                private void DoSometing(out int z)
                {
                    z = 100;
                }
            }
            """);
 
    [Fact]
    public Task TestInlineMethodWithVariableDeclaration3AcrossFile()
        => TestVerifier.TestBothKeepAndRemoveInlinedMethodInDifferentFileAsync(
            """
            public partial class TestClass
            {
                private void Caller()
                {
                    Cal[||]lee(out var x);
                }
 
                private void DoSometing(out int z)
                {
                    z = 100;
                }
            }
            """,
            """
            public partial class TestClass
            {
                private void Callee(out int z)
                {
                    DoSometing(out z);
                }
            }
            """,
            """
            public partial class TestClass
            {
                private void Caller()
                {
                    int x;
                    DoSometing(out x);
                }
 
                private void DoSometing(out int z)
                {
                    z = 100;
                }
            }
            """,
            """
            public partial class TestClass
            {##
                private void Callee(out int z)
                {
                    DoSometing(out z);
                }##
            }
            """);
 
    [Fact]
    public Task TestInlineCalleeSelf()
        => TestVerifier.TestInRegularAndScriptInTheSameFileAsync(
            """
            public class TestClass
            {
                public TestClass()
                {
                    var x = Callee1(Cal[||]lee1(Callee1(Callee1(10))));
                }
 
                private int Callee1(int j)
                {
                    return 1 + 2 + j;
                }
            }
            """,
            """
            public class TestClass
            {
                public TestClass()
                {
                    var x = Callee1(1 + 2 + Callee1(Callee1(10)));
                }
 
                private int Callee1(int j)
                {
                    return 1 + 2 + j;
                }
            }
            """);
    [Fact]
    public Task TestInlineMethodWithConditionalExpression()
        => TestVerifier.TestInRegularAndScriptInTheSameFileAsync(
            """
            public class TestClass
            {
                public void Caller(bool x)
                {
                    int t = C[||]allee(x ? Callee(1) : Callee(2));
                }
 
                private int Callee(int i)
                {
                    return i + 1;
                }
            }
            """,
            """
            public class TestClass
            {
                public void Caller(bool x)
                {
                    int t = (x ? Callee(1) : Callee(2)) + 1;
                }
 
                private int Callee(int i)
                {
                    return i + 1;
                }
            }
            """);
 
    [Fact]
    public Task TestInlineExpressionWithoutAssignedToVariable()
        => TestVerifier.TestBothKeepAndRemoveInlinedMethodInSameFileAsync("""
            public class TestClass
            {
                public void Caller(int j)
                {
                    Cal[||]lee(j);
                }
 
                private int Callee(int i)
                {
                    return i + 1;
                }
            }
            """, """
            public class TestClass
            {
                public void Caller(int j)
                {
                    int temp = j + 1;
                }
            ##
                private int Callee(int i)
                {
                    return i + 1;
                }
            ##}
            """);
 
    [Fact]
    public Task TestInlineExpressionWithoutAssignedToVariableAcrossFile()
        => TestVerifier.TestBothKeepAndRemoveInlinedMethodInDifferentFileAsync(
            """
            public partial class TestClass
            {
                public void Caller(int j)
                {
                    Cal[||]lee(j);
                }
            }
            """,
            """
            public partial class TestClass
            {
                private int Callee(int i)
                {
                    return i + 1;
                }
            }
            """,
            """
            public partial class TestClass
            {
                public void Caller(int j)
                {
                    int temp = j + 1;
                }
            }
            """,
            """
            public partial class TestClass
            {##
                private int Callee(int i)
                {
                    return i + 1;
                }##
            }
            """);
 
    [Fact]
    public Task TestInlineMethodWithNullCoalescingExpression()
        => TestVerifier.TestBothKeepAndRemoveInlinedMethodInSameFileAsync("""
            public class TestClass
            {
                public void Caller(int? i)
                {
                    var t = Cal[||]lee(i ?? 1);
                }
 
                private int Callee(int i)
                {
                    return i + 1;
                }
            }
            """, """
            public class TestClass
            {
                public void Caller(int? i)
                {
                    var t = (i ?? 1) + 1;
                }
            ##
                private int Callee(int i)
                {
                    return i + 1;
                }
            ##}
            """);
 
    [Fact]
    public Task TestInlineSimpleLambdaExpression()
        => TestVerifier.TestBothKeepAndRemoveInlinedMethodInSameFileAsync("""
            public class TestClass
            {
                public System.Func<int, int, int> Caller()
                {
                    return Ca[||]llee();
                }
 
                private System.Func<int, int, int> Callee() => (i, j) => i + j;
            }
            """, """
            public class TestClass
            {
                public System.Func<int, int, int> Caller()
                {
                    return (i, j) => i + j;
                }
            ##
                private System.Func<int, int, int> Callee() => (i, j) => i + j;
            ##}
            """);
 
    [Fact]
    public Task TestInlineSimpleLambdaExpressionAcrossFile()
        => TestVerifier.TestBothKeepAndRemoveInlinedMethodInDifferentFileAsync(
            """
            public partial class TestClass
            {
                public System.Func<int, int, int> Caller()
                {
                    return Ca[||]llee();
                }
            }
            """,
            """
            public partial class TestClass
            {
                private System.Func<int, int, int> Callee() => (i, j) => i + j;
            }
            """,
            """
            public partial class TestClass
            {
                public System.Func<int, int, int> Caller()
                {
                    return (i, j) => i + j;
                }
            }
            """,
            """
            public partial class TestClass
            {##
                private System.Func<int, int, int> Callee() => (i, j) => i + j;##
            }
            """);
 
    [Fact]
    public Task TestInlineMethodWithGenericsArguments()
        => TestVerifier.TestBothKeepAndRemoveInlinedMethodInSameFileAsync(
            """
            using System;
            public class TestClass
            {
                private void Caller<U>()
                {
                    Ca[||]llee<int, U>(1, 2, 3);
                }
 
                private void Callee<T, U>(params T[] i)
                {
                    System.Console.WriteLine(typeof(T).Name.Length + i.Length + typeof(U).Name.Length);
                }
            }
            """,
            """
            using System;
            public class TestClass
            {
                private void Caller<U>()
                {
                    System.Console.WriteLine(typeof(int).Name.Length + (new int[] { 1, 2, 3 }).Length + typeof(U).Name.Length);
                }
            ##
                private void Callee<T, U>(params T[] i)
                {
                    System.Console.WriteLine(typeof(T).Name.Length + i.Length + typeof(U).Name.Length);
                }
            ##}
            """);
 
    [Fact]
    public Task TestInlineMethodWithGenericsArgumentsAcrossFile()
        => TestVerifier.TestBothKeepAndRemoveInlinedMethodInDifferentFileAsync(
            """
            public partial class TestClass
            {
                private void Caller<U>()
                {
                    Ca[||]llee<int, U>(1, 2, 3);
                }
            }
            """,
            """
            public partial class TestClass
            {
                private void Callee<T, U>(params T[] i)
                {
                    System.Console.WriteLine(typeof(T).Name.Length + i.Length + typeof(U).Name.Length);
                }
            }
            """,
            """
            public partial class TestClass
            {
                private void Caller<U>()
                {
                    System.Console.WriteLine(typeof(int).Name.Length + (new int[] { 1, 2, 3 }).Length + typeof(U).Name.Length);
                }
            }
            """,
            """
            public partial class TestClass
            {##
                private void Callee<T, U>(params T[] i)
                {
                    System.Console.WriteLine(typeof(T).Name.Length + i.Length + typeof(U).Name.Length);
                }##
            }
            """);
 
    [Fact]
    public Task TestAwaitExpressionInMethod1()
        => TestVerifier.TestBothKeepAndRemoveInlinedMethodInSameFileAsync(
            """
            using System.Threading.Tasks;
            using System;
            public class TestClass
            {
                public Task<int> Caller(bool x)
                {
                    System.Console.WriteLine("");
                    return Call[||]ee(10, x ? 1 : 2);
                }
 
                private async Task<int> Callee(int i, int j)
                {
                    return await Task.FromResult(i + j);
                }
            }
            """,
            """
            using System.Threading.Tasks;
            using System;
            public class TestClass
            {
                public Task<int> Caller(bool x)
                {
                    System.Console.WriteLine("");
                    return Task.FromResult(10 + (x ? 1 : 2));
                }
            ##
                private async Task<int> Callee(int i, int j)
                {
                    return await Task.FromResult(i + j);
                }
            ##}
            """);
 
    [Fact]
    public Task TestAwaitExpressionInMethodAcrossFile()
        => TestVerifier.TestBothKeepAndRemoveInlinedMethodInDifferentFileAsync(
            """
            using System.Threading.Tasks;
            public partial class TestClass
            {
                public Task<int> Caller(bool x)
                {
                    System.Console.WriteLine("");
                    return Call[||]ee(10, x ? 1 : 2);
                }
            }
            """,
            """
            using System.Threading.Tasks;
            public partial class TestClass
            {
                private async Task<int> Callee(int i, int j)
                {
                    return await Task.FromResult(i + j);
                }
            }
            """,
            """
            using System.Threading.Tasks;
            public partial class TestClass
            {
                public Task<int> Caller(bool x)
                {
                    System.Console.WriteLine("");
                    return Task.FromResult(10 + (x ? 1 : 2));
                }
            }
            """,
            """
            using System.Threading.Tasks;
            public partial class TestClass
            {##
                private async Task<int> Callee(int i, int j)
                {
                    return await Task.FromResult(i + j);
                }##
            }
            """);
 
    [Fact]
    public Task TestAwaitExpressionInMethod2()
        => TestVerifier.TestBothKeepAndRemoveInlinedMethodInSameFileAsync(
            """
            using System.Threading.Tasks;
            using System;
            public class TestClass
            {
                public void Caller(bool x)
                {
                    System.Console.WriteLine("");
                    var f = C[||]allee();
                }
 
                private Func<Task> Callee()
                {
                    return async () => await Task.Delay(100);
                }
            }
            """,
            """
            using System.Threading.Tasks;
            using System;
            public class TestClass
            {
                public void Caller(bool x)
                {
                    System.Console.WriteLine("");
                    var f = (Func<Task>)(async () => await Task.Delay(100));
                }
            ##
                private Func<Task> Callee()
                {
                    return async () => await Task.Delay(100);
                }
            ##}
            """);
 
    [Fact]
    public Task TestAwaitExpressionInMethod2AcrossFile()
        => TestVerifier.TestBothKeepAndRemoveInlinedMethodInDifferentFileAsync(
            """
            using System.Threading.Tasks;
            using System;
            public partial class TestClass
            {
                public void Caller(bool x)
                {
                    System.Console.WriteLine("");
                    var f = C[||]allee();
                }
            }
            """,
            """
            using System.Threading.Tasks;
            using System;
            public partial class TestClass
            {
                private Func<Task> Callee()
                {
                    return async () => await Task.Delay(100);
                }
            }
            """,
            """
            using System.Threading.Tasks;
            using System;
            public partial class TestClass
            {
                public void Caller(bool x)
                {
                    System.Console.WriteLine("");
                    var f = (Func<Task>)(async () => await Task.Delay(100));
                }
            }
            """,
            """
            using System.Threading.Tasks;
            using System;
            public partial class TestClass
            {##
                private Func<Task> Callee()
                {
                    return async () => await Task.Delay(100);
                }##
            }
            """);
 
    [Fact]
    public Task TestAwaitExpresssion1()
        => TestVerifier.TestBothKeepAndRemoveInlinedMethodInSameFileAsync(
            """
            using System.Threading.Tasks;
            public class TestClass
            {
                public Task Caller()
                {
                    return Cal[||]lee();
                }
 
                private async Task Callee()
                {
                    await Task.CompletedTask;
                }
            }
            """,
            """
            using System.Threading.Tasks;
            public class TestClass
            {
                public Task Caller()
                {
                    return Task.CompletedTask;
                }
            ##
                private async Task Callee()
                {
                    await Task.CompletedTask;
                }
            ##}
            """);
 
    [Fact]
    public Task TestAwaitExpresssion2()
        => TestVerifier.TestBothKeepAndRemoveInlinedMethodInSameFileAsync(
            """
            using System.Threading.Tasks;
            public class TestClass
            {
                public async Task Caller()
                {
                    await Cal[||]lee().ConfigureAwait(false);
                }
 
                private async Task Callee() => await Task.CompletedTask;
            }
            """,
            """
            using System.Threading.Tasks;
            public class TestClass
            {
                public async Task Caller()
                {
                    await Task.CompletedTask.ConfigureAwait(false);
                }
            ##
                private async Task Callee() => await Task.CompletedTask;
            ##}
            """);
 
    [Fact]
    public Task TestAwaitExpresssion3()
        => TestVerifier.TestBothKeepAndRemoveInlinedMethodInSameFileAsync(
            """
            using System.Threading.Tasks;
            public class TestClass
            {
                public Task<int> Caller()
                {
                    return Cal[||]lee();
                }
 
                private async Task<int> Callee() => await Task.FromResult(1);
            }
            """,
            """
            using System.Threading.Tasks;
            public class TestClass
            {
                public Task<int> Caller()
                {
                    return Task.FromResult(1);
                }
            ##
                private async Task<int> Callee() => await Task.FromResult(1);
            ##}
            """);
 
    [Fact]
    public Task TestAwaitExpresssion4()
        => TestVerifier.TestBothKeepAndRemoveInlinedMethodInSameFileAsync(
            """
            using System.Threading.Tasks;
            public class TestClass
            {
                public void Caller()
                {
                    var x = Cal[||]lee();
                }
 
                private async Task<int> Callee()
                {
                    return await Task.FromResult(await SomeCalculation());
                }
 
                private async Task<int> SomeCalculation() => await Task.FromResult(10);
            }
            """,
            """
            using System.Threading.Tasks;
            public class TestClass
            {
                public async void Caller()
                {
                    var x = Task.FromResult(await SomeCalculation());
                }
            ##
                private async Task<int> Callee()
                {
                    return await Task.FromResult(await SomeCalculation());
                }
            ##
                private async Task<int> SomeCalculation() => await Task.FromResult(10);
            }
            """);
 
    [Fact]
    public Task TestAwaitExpressionInMethod4AcrossFile()
        => TestVerifier.TestBothKeepAndRemoveInlinedMethodInDifferentFileAsync(
            """
            using System.Threading.Tasks;
            public partial class TestClass
            {
                public void Caller()
                {
                    var x = Cal[||]lee();
                }
 
                private async Task<int> SomeCalculation() => await Task.FromResult(10);
            }
            """,
            """
            using System.Threading.Tasks;
            public partial class TestClass
            {
                private async Task<int> Callee()
                {
                    return await Task.FromResult(await SomeCalculation());
                }
            }
            """,
            """
            using System.Threading.Tasks;
            public partial class TestClass
            {
                public async void Caller()
                {
                    var x = Task.FromResult(await SomeCalculation());
                }
 
                private async Task<int> SomeCalculation() => await Task.FromResult(10);
            }
            """,
            """
            using System.Threading.Tasks;
            public partial class TestClass
            {##
                private async Task<int> Callee()
                {
                    return await Task.FromResult(await SomeCalculation());
                }##
            }
            """);
 
    [Fact]
    public Task TestAwaitExpresssion5()
    {
        var diagnostic = new List<DiagnosticResult>()
        {
            // Await can't be used in non-async method.
            DiagnosticResult.CompilerError("CS4032").WithSpan(6, 33, 6, 56).WithArguments("int")
        };
        return TestVerifier.TestBothKeepAndRemoveInlinedMethodInSameFileAsync(
                       """
                       using System.Threading.Tasks;
                       public class TestClass
                       {
                           public int Caller()
                           {
                               var x = Cal[||]lee();
                               return 1;
                           }
 
                           private async Task<int> Callee()
                           {
                               return await Task.FromResult(await SomeCalculation());
                           }
 
                           private async Task<int> SomeCalculation() => await Task.FromResult(10);
                       }
                       """,
                       """
                       using System.Threading.Tasks;
                       public class TestClass
                       {
                           public int Caller()
                           {
                               var x = Task.FromResult(await SomeCalculation());
                               return 1;
                           }
                       ##
                           private async Task<int> Callee()
                           {
                               return await Task.FromResult(await SomeCalculation());
                           }
                       ##
                           private async Task<int> SomeCalculation() => await Task.FromResult(10);
                       }
                       """, diagnosticResultsWhenKeepInlinedMethod: diagnostic, diagnosticResultsWhenRemoveInlinedMethod: diagnostic);
    }
 
    [Fact]
    public Task TestAwaitExpresssion6()
        => TestVerifier.TestBothKeepAndRemoveInlinedMethodInSameFileAsync(
            """
            using System.Threading.Tasks;
            public class TestClass
            {
                public void Caller()
                {
                    var x = Cal[||]lee().Result;
                }
 
                private async Task<int> Callee()
                {
                    return await Task.FromResult(100);
                }
            }
            """,
            """
            using System.Threading.Tasks;
            public class TestClass
            {
                public void Caller()
                {
                    var x = Task.FromResult(100).Result;
                }
            ##
                private async Task<int> Callee()
                {
                    return await Task.FromResult(100);
                }
            ##}
            """);
 
    [Fact]
    public Task TestAwaitExpressionInLambda()
        => TestVerifier.TestBothKeepAndRemoveInlinedMethodInSameFileAsync(
            """
            using System;
            using System.Threading.Tasks;
            public class TestClass
            {
                private void Method()
                {
                    Func<bool, Task<int>> x1 = (x) =>
                    {
                        System.Console.WriteLine("");
                        return Call[||]ee();
                    };
                }
 
                private async Task<int> Callee()
                {
                    return await Task.FromResult(10);
                }
            }
            """,
            """
            using System;
            using System.Threading.Tasks;
            public class TestClass
            {
                private void Method()
                {
                    Func<bool, Task<int>> x1 = (x) =>
                    {
                        System.Console.WriteLine("");
                        return Task.FromResult(10);
                    };
                }
            ##
                private async Task<int> Callee()
                {
                    return await Task.FromResult(10);
                }
            ##}
            """);
 
    [Fact]
    public Task TestAwaitExpressionInLocalMethod()
        => TestVerifier.TestBothKeepAndRemoveInlinedMethodInSameFileAsync(
            """
            using System.Threading.Tasks;
            public class TestClass
            {
                private void Method()
                {
                    Task<int> Caller(bool x)
                    {
                        System.Console.WriteLine("");
                        return Call[||]ee(10, x ? 1 : 2);
                    }
                }
 
                private async Task<int> Callee(int i, int j)
                {
                    return await Task.FromResult(i + j);
                }
            }
            """,
            """
            using System.Threading.Tasks;
            public class TestClass
            {
                private void Method()
                {
                    Task<int> Caller(bool x)
                    {
                        System.Console.WriteLine("");
                        return Task.FromResult(10 + (x ? 1 : 2));
                    }
                }
            ##
                private async Task<int> Callee(int i, int j)
                {
                    return await Task.FromResult(i + j);
                }
            ##}
            """);
    [Fact]
    public Task TestInlineMethodForLambda1()
        => TestVerifier.TestBothKeepAndRemoveInlinedMethodInSameFileAsync(
            """
            using System;
            public class TestClass
            {
                public void Caller()
                {
                    Call[||]ee()(10);
                }
 
                private Func<int, int> Callee()
                    => i => 1;
            }
            """,
            """
            using System;
            public class TestClass
            {
                public void Caller()
                {
                    ((Func<int, int>)(i => 1))(10);
                }
            ##
                private Func<int, int> Callee()
                    => i => 1;
            ##}
            """);
 
    [Fact]
    public Task TestInlineMethodForLambda2()
        => TestVerifier.TestBothKeepAndRemoveInlinedMethodInSameFileAsync(
            """
            using System;
            using System.Threading.Tasks;
            public class TestClass
            {
                public void Caller()
                {
                    var x = Call[||]ee();
                }
 
                private Func<Task> Callee()
                    => async () => await Task.CompletedTask;
            }
            """,
            """
            using System;
            using System.Threading.Tasks;
            public class TestClass
            {
                public void Caller()
                {
                    var x = (Func<Task>)(async () => await Task.CompletedTask);
                }
            ##
                private Func<Task> Callee()
                    => async () => await Task.CompletedTask;
            ##}
            """);
 
    [Fact]
    public Task TestInlineWithinDoStatement()
        => TestVerifier.TestBothKeepAndRemoveInlinedMethodInSameFileAsync(
            """
            public class TestClass
            {
                private void Caller()
                {
                    do
                    {
                    } while(Cal[||]lee(SomeInt()) == 1);
                }
 
                private int Callee(int i)
                {
                    return i + 1;
                }
 
                private int SomeInt() => 10;
            }
            """,
            """
            public class TestClass
            {
                private void Caller()
                {
                    do
                    {
                    } while(SomeInt() + 1 == 1);
                }
            ##
                private int Callee(int i)
                {
                    return i + 1;
                }
            ##
                private int SomeInt() => 10;
            }
            """);
 
    [Fact]
    public Task TestInlineWithinForStatement()
        => TestVerifier.TestBothKeepAndRemoveInlinedMethodInSameFileAsync(
            """
            public class TestClass
            {
                private void Caller()
                {
                    for (int i = Ca[||]llee(SomeInt()); i < 10; i++)
                    {
                    }
                }
 
                private int Callee(int i)
                {
                    return i + 1;
                }
 
                private int SomeInt() => 10;
            }
            """,
            """
            public class TestClass
            {
                private void Caller()
                {
                    for (int i = SomeInt() + 1; i < 10; i++)
                    {
                    }
                }
            ##
                private int Callee(int i)
                {
                    return i + 1;
                }
            ##
                private int SomeInt() => 10;
            }
            """);
 
    [Fact]
    public Task TestInlineWithinIfStatement()
        => TestVerifier.TestBothKeepAndRemoveInlinedMethodInSameFileAsync(
            """
            public class TestClass
            {
                private void Caller()
                {
                    if (Ca[||]llee(SomeInt()) == 1)
                    {
                    }
                }
 
                private int Callee(int i)
                {
                    return i + 1;
                }
 
                private int SomeInt() => 10;
            }
            """,
            """
            public class TestClass
            {
                private void Caller()
                {
                    if (SomeInt() + 1 == 1)
                    {
                    }
                }
            ##
                private int Callee(int i)
                {
                    return i + 1;
                }
            ##
                private int SomeInt() => 10;
            }
            """);
 
    [Fact]
    public Task TestInlineWithinLockStatement()
        => TestVerifier.TestBothKeepAndRemoveInlinedMethodInSameFileAsync(
            """
            public class TestClass
            {
                private void Caller()
                {
                    lock (Ca[||]llee(SomeInt()))
                    {
                    }
                }
 
                private string Callee(int i)
                {
                    return "Hello" + i;
                }
 
                private int SomeInt() => 10;
            }
            """,
            """
            public class TestClass
            {
                private void Caller()
                {
                    lock ("Hello" + SomeInt())
                    {
                    }
                }
            ##
                private string Callee(int i)
                {
                    return "Hello" + i;
                }
            ##
                private int SomeInt() => 10;
            }
            """);
 
    [Fact]
    public Task TestInlineWithinReturnStatement()
        => TestVerifier.TestBothKeepAndRemoveInlinedMethodInSameFileAsync(
            """
            public class TestClass
            {
                private string Caller()
                {
                    return Call[||]ee(SomeInt());
                }
 
                private string Callee(int i)
                {
                    return "Hello" + i;
                }
 
                private int SomeInt() => 10;
            }
            """,
            """
            public class TestClass
            {
                private string Caller()
                {
                    return "Hello" + SomeInt();
                }
            ##
                private string Callee(int i)
                {
                    return "Hello" + i;
                }
            ##
                private int SomeInt() => 10;
            }
            """);
 
    [Fact]
    public Task TestInlineMethodWithinThrowStatement()
        => TestVerifier.TestBothKeepAndRemoveInlinedMethodInSameFileAsync(
            """
            public class TestClass
            {
                private void Caller()
                {
                    throw new System.Exception(Call[||]ee(SomeInt()) + "");
                }
 
                private int Callee(int i)
                {
                    return i + 20;
                }
 
                private int SomeInt() => 10;
            }
            """,
            """
            public class TestClass
            {
                private void Caller()
                {
                    throw new System.Exception(SomeInt() + 20 + "");
                }
            ##
                private int Callee(int i)
                {
                    return i + 20;
                }
            ##
                private int SomeInt() => 10;
            }
            """);
 
    [Fact]
    public Task TestInlineWithinWhileStatement()
        => TestVerifier.TestBothKeepAndRemoveInlinedMethodInSameFileAsync(
            """
            public class TestClass
            {
                private void Caller()
                {
                    while (Cal[||]lee(SomeInt()) == 1)
                    {}
                }
 
                private int Callee(int i)
                {
                    return i + 1;
                }
 
                private int SomeInt() => 10;
            }
            """,
            """
            public class TestClass
            {
                private void Caller()
                {
                    while (SomeInt() + 1 == 1)
                    {}
                }
            ##
                private int Callee(int i)
                {
                    return i + 1;
                }
            ##
                private int SomeInt() => 10;
            }
            """);
 
    [Fact]
    public Task TestInlineMethodWithinTryStatement()
        => TestVerifier.TestBothKeepAndRemoveInlinedMethodInSameFileAsync(
        """
        public class TestClass
        {
            private void Calller()
            {
                try
                {
                }
                catch (System.Exception e) when (Ca[||]llee(e, SomeInt()))
                {
                }
            }
 
            private bool Callee(System.Exception e, int i) => i == 1;
 
            private int SomeInt() => 10;
        }
        """,
            """
            public class TestClass
            {
                private void Calller()
                {
                    try
                    {
                    }
                    catch (System.Exception e) when (SomeInt() == 1)
                    {
                    }
                }
            ##
                private bool Callee(System.Exception e, int i) => i == 1;
            ##
                private int SomeInt() => 10;
            }
            """);
 
    [Fact]
    public Task TestInlineMethodWithinYieldReturnStatement()
        => TestVerifier.TestBothKeepAndRemoveInlinedMethodInSameFileAsync(
            """
            public class TestClass2
            {
                private System.Collections.Generic.IEnumerable<int> Calller()
                {
                    yield return 1;
                    yield return Cal[||]lee(SomeInt());
                    yield return 3;
                }
 
                private int Callee(int i) => i + 10;
 
                private int SomeInt() => 10;
            }
            """,
            """
            public class TestClass2
            {
                private System.Collections.Generic.IEnumerable<int> Calller()
                {
                    yield return 1;
                    yield return SomeInt() + 10;
                    yield return 3;
                }
            ##
                private int Callee(int i) => i + 10;
            ##
                private int SomeInt() => 10;
            }
            """);
 
    [Fact]
    public Task TestInlineExtensionMethod1()
        => TestVerifier.TestBothKeepAndRemoveInlinedMethodInSameFileAsync(
            """
            static class Program
            {
                static void Main(string[] args)
                {
                    var value = 0;
                    value.Ge[||]tNext();
                }
 
                private static int GetNext(this int i)
                {
                    return i + 1;
                }
            }
            """,
            """
            static class Program
            {
                static void Main(string[] args)
                {
                    var value = 0;
                    int temp = value + 1;
                }
            ##
                private static int GetNext(this int i)
                {
                    return i + 1;
                }
            ##}
            """);
 
    [Fact]
    public Task TestInlineExtensionMethod2()
        => TestVerifier.TestBothKeepAndRemoveInlinedMethodInSameFileAsync(
            """
            static class Program
            {
                static void Main(string[] args)
                {
                    var x = 0.Ge[||]tNext();
                }
 
                private static int GetNext(this int i)
                {
                    return i + 1;
                }
            }
            """,
            """
            static class Program
            {
                static void Main(string[] args)
                {
                    var x = 0 + 1;
                }
            ##
                private static int GetNext(this int i)
                {
                    return i + 1;
                }
            ##}
            """);
 
    [Fact]
    public Task TestInlineExtensionMethod3()
        => TestVerifier.TestBothKeepAndRemoveInlinedMethodInSameFileAsync(
            """
            static class Program
            {
                static void Main(string[] args)
                {
                    GetInt().Ge[||]tNext();
                }
 
                private static int GetInt() => 10;
 
                private static int GetNext(this int i)
                {
                    return i + 1;
                }
            }
            """,
            """
            static class Program
            {
                static void Main(string[] args)
                {
                    int temp = GetInt() + 1;
                }
 
                private static int GetInt() => 10;
            ##
                private static int GetNext(this int i)
                {
                    return i + 1;
                }
            ##}
            """);
 
    [Fact]
    public Task TestIsExpression()
        => TestVerifier.TestBothKeepAndRemoveInlinedMethodInSameFileAsync(
            """
            public class TestClass
            {
                public bool Caller(int i, int j)
                {
                    return Ca[||]llee(i, j) is int;
                }
 
                private bool Callee(int i, int j)
                {
                    return i == j;
                }
            }
            """,
            """
            public class TestClass
            {
                public bool Caller(int i, int j)
                {
                    return (i == j) is int;
                }
            ##
                private bool Callee(int i, int j)
                {
                    return i == j;
                }
            ##}
            """);
 
    [Fact]
    public Task TestUnaryPlusOperator()
        => TestVerifier.TestBothKeepAndRemoveInlinedMethodInSameFileAsync(
            """
            public class TestClass
            {
                public int Caller()
                {
                    return +Call[||]ee();
                }
 
                private int Callee()
                {
                    return 1 + 2;
                }
            }
            """,
            """
            public class TestClass
            {
                public int Caller()
                {
                    return +(1 + 2);
                }
            ##
                private int Callee()
                {
                    return 1 + 2;
                }
            ##}
            """);
 
    [Fact]
    public Task TestLogicalNotExpression()
        => TestVerifier.TestBothKeepAndRemoveInlinedMethodInSameFileAsync(
            """
            public class TestClass
            {
                public bool Caller(int i, int j)
                {
                    return !Ca[||]llee(i, j);
                }
 
                private bool Callee(int i, int j)
                {
                    return i == j;
                }
            }
            """,
            """
            public class TestClass
            {
                public bool Caller(int i, int j)
                {
                    return !(i == j);
                }
            ##
                private bool Callee(int i, int j)
                {
                    return i == j;
                }
            ##}
            """);
 
    [Fact]
    public Task TestCastExpression()
        => TestVerifier.TestBothKeepAndRemoveInlinedMethodInSameFileAsync(
            """
            public class TestClass
            {
                public char Caller(int i, int j)
                {
                    return (char)Call[||]ee(i, j);
                }
 
                private int Callee(int i, int j)
                {
                    return i + j;
                }
            }
            """,
            """
            public class TestClass
            {
                public char Caller(int i, int j)
                {
                    return (char)(i + j);
                }
            ##
                private int Callee(int i, int j)
                {
                    return i + j;
                }
            ##}
            """);
 
    [Fact]
    public Task TestIsPatternExpression()
        => TestVerifier.TestBothKeepAndRemoveInlinedMethodInSameFileAsync(
            """
            public class TestClass
            {
                public void Calller()
                {
                    if (Ca[||]llee() is int i)
                    {
                    }
                }
 
                private int Callee()
                {
                    return 1 | 2;
                }
            }
            """,
            """
            public class TestClass
            {
                public void Calller()
                {
                    if ((1 | 2) is int i)
                    {
                    }
                }
            ##
                private int Callee()
                {
                    return 1 | 2;
                }
            ##}
            """);
 
    [Fact]
    public Task TestCoalesceExpression()
        => TestVerifier.TestBothKeepAndRemoveInlinedMethodInSameFileAsync(
            """
            public class TestClass
            {
                public int Caller(int? c)
                {
                    return 1 + Cal[||]lee(c);
                }
 
                private int Callee(int? c)
                {
                    return c ?? 1;
                }
            }
            """,
            """
            public class TestClass
            {
                public int Caller(int? c)
                {
                    return 1 + (c ?? 1);
                }
            ##
                private int Callee(int? c)
                {
                    return c ?? 1;
                }
            ##}
            """);
 
    [Fact]
    public Task TestCoalesceExpressionAsRightValue()
        => TestVerifier.TestBothKeepAndRemoveInlinedMethodInSameFileAsync(
            """
            public class TestClass
            {
                public string Caller(string c)
                {
                    return c ?? Cal[||]lee(null);
                }
 
                private string Callee(string c2)
                {
                    return c2 ?? "Hello";
                }
            }
            """,
            """
            public class TestClass
            {
                public string Caller(string c)
                {
                    return c ?? null ?? "Hello";
                }
            ##
                private string Callee(string c2)
                {
                    return c2 ?? "Hello";
                }
            ##}
            """);
 
    [Fact]
    public Task TestSimpleMemberAccessExpression()
        => TestVerifier.TestBothKeepAndRemoveInlinedMethodInSameFileAsync(
            """
            public class TestClass
            {
                public void Caller()
                {
                    var x = C[||]allee().Length;
                }
 
                private string Callee() => "H" + "L";
            }
            """,
            """
            public class TestClass
            {
                public void Caller()
                {
                    var x = ("H" + "L").Length;
                }
            ##
                private string Callee() => "H" + "L";
            ##}
            """);
 
    [Fact]
    public Task TestSwitchExpression()
        => TestVerifier.TestBothKeepAndRemoveInlinedMethodInSameFileAsync("""
            public class TestClass
            {
                private void Calller()
                {
                    var x = C[||]allee() switch
                    {
                        1 => 1,
                        2 => 2,
                        _ => 3
                    };
                }
 
                private int Callee() => 1 + 2;
            }
            """,
            """
            public class TestClass
            {
                private void Calller()
                {
                    var x = (1 + 2) switch
                    {
                        1 => 1,
                        2 => 2,
                        _ => 3
                    };
                }
            ##
                private int Callee() => 1 + 2;
            ##}
            """);
 
    [Fact]
    public Task TestSuppressNullableWarningExpression()
        => TestVerifier.TestBothKeepAndRemoveInlinedMethodInSameFileAsync("""
            #nullable enable
            public class TestClass
            {
                private object Calller(int x)
                {
                    return Ca[||]llee(x)!;
                }
 
                private object Callee(int x) => x = 1;
            }
            """,
            """
            #nullable enable
            public class TestClass
            {
                private object Calller(int x)
                {
                    return (x = 1)!;
                }
            ##
                private object Callee(int x) => x = 1;
            ##}
            """);
 
    [Fact]
    public Task TestSimpleAssignmentExpression()
        => TestVerifier.TestBothKeepAndRemoveInlinedMethodInSameFileAsync("""
            public class TestClass
            {
                private int Calller(int x)
                {
                    return Ca[||]llee(x) + 1;
                }
 
                private int Callee(int x) => x = 1;
            }
            """,
            """
            public class TestClass
            {
                private int Calller(int x)
                {
                    return (x = 1) + 1;
                }
            ##
                private int Callee(int x) => x = 1;
            ##}
            """);
 
    [Theory]
    [InlineData("++")]
    [InlineData("--")]
    public Task TestPreExpression(string op)
        => TestVerifier.TestBothKeepAndRemoveInlinedMethodInSameFileAsync(
            """
            public class TestClass
            {
                public void Caller()
                {
                    int i = 1;
                    Cal[||]lee(i);
                }
 
                private int Callee(int i)
                {
                    return (op)i;
                }
            }
            """.Replace("(op)", op),
            """
            public class TestClass
            {
                public void Caller()
                {
                    int i = 1;
                    (op)i;
                }
            ##
                private int Callee(int i)
                {
                    return (op)i;
                }
            ##}
            """.Replace("(op)", op));
 
    [Fact]
    public Task TestAwaitExpressionWithFireAndForgot()
        => TestVerifier.TestBothKeepAndRemoveInlinedMethodInSameFileAsync("""
            using System.Threading.Tasks;
            public class TestClass
            {
                public async void Caller()
                {
                    Cal[||]lee();
                }
                private async Task Callee()
                {
                    await Task.Delay(100);
                }
            }
            """,
            """
            using System.Threading.Tasks;
            public class TestClass
            {
                public async void Caller()
                {
                    Task.Delay(100);
                }
            ##    private async Task Callee()
                {
                    await Task.Delay(100);
                }
            ##}
            """);
 
    [Theory]
    [InlineData("++")]
    [InlineData("--")]
    public Task TestPostExpression(string op)
        => TestVerifier.TestBothKeepAndRemoveInlinedMethodInSameFileAsync(
            """
            public class TestClass
            {
                public void Caller()
                {
                    int i = 1;
                    Cal[||]lee(i);
                }
 
                private int Callee(int i)
                {
                    return i(op);
                }
            }
            """.Replace("(op)", op),
            """
            public class TestClass
            {
                public void Caller()
                {
                    int i = 1;
                    i(op);
                }
            ##
                private int Callee(int i)
                {
                    return i(op);
                }
            ##}
            """.Replace("(op)", op));
 
    [Fact]
    public Task TestConditionalInvocationExpression1()
        => TestVerifier.TestBothKeepAndRemoveInlinedMethodInSameFileAsync(
            """
            public class TestClass
            {
                public void Caller()
                {
                    Cal[||]lee();
                }
 
                private char[] Callee() => ("Hello" + "World")?.ToCharArray();
            }
            """,
            """
            public class TestClass
            {
                public void Caller()
                {
                    ("Hello" + "World")?.ToCharArray();
                }
            ##
                private char[] Callee() => ("Hello" + "World")?.ToCharArray();
            ##}
            """);
 
    [Fact]
    public Task TestInlineLambdaInsideInvocation()
        => TestVerifier.TestBothKeepAndRemoveInlinedMethodInSameFileAsync("""
            using System;
            public class TestClass
            {
                public void Caller()
                {
                    var x = Cal[||]lee()();
                }
 
                private Func<int> Callee()
                {
                    return () => 1;
                }
            }
            """, """
            using System;
            public class TestClass
            {
                public void Caller()
                {
                    var x = ((Func<int>)(() => 1))();
                }
            ##
                private Func<int> Callee()
                {
                    return () => 1;
                }
            ##}
            """);
 
    [Fact]
    public Task TestInlineLambda1()
        => TestVerifier.TestBothKeepAndRemoveInlinedMethodInSameFileAsync("""
            using System;
            using System.Threading.Tasks;
            public class TestClass
            {
                public void Caller()
                {
                    var x = Cal[||]lee();
                }
 
                private Func<Task> Callee()
                {
                    return async () => await Task.CompletedTask;
                }
            }
            """, """
            using System;
            using System.Threading.Tasks;
            public class TestClass
            {
                public void Caller()
                {
                    var x = (Func<Task>)(async () => await Task.CompletedTask);
                }
            ##
                private Func<Task> Callee()
                {
                    return async () => await Task.CompletedTask;
                }
            ##}
            """);
 
    [Fact]
    public Task TestInlineLambda2()
        => TestVerifier.TestBothKeepAndRemoveInlinedMethodInSameFileAsync("""
            using System;
            using System.Threading.Tasks;
            public class TestClass
            {
                public void Caller()
                {
                    var x = Cal[||]lee();
                }
 
                private Func<Task<int>> Callee()
                {
                    return async () => { return await Task.FromResult(100); };
                }
            }
            """, """
            using System;
            using System.Threading.Tasks;
            public class TestClass
            {
                public void Caller()
                {
                    var x = (Func<Task<int>>)(async () => { return await Task.FromResult(100); });
                }
            ##
                private Func<Task<int>> Callee()
                {
                    return async () => { return await Task.FromResult(100); };
                }
            ##}
            """);
 
    [Fact]
    public Task TestInlineTypeCast()
        => TestVerifier.TestBothKeepAndRemoveInlinedMethodInSameFileAsync("""
            public class TestClass
            {
                public void Caller()
                {
                    var x = Cal[||]lee();
                }
 
                private long Callee()
                {
                    return 1;
                }
            }
            """, """
            public class TestClass
            {
                public void Caller()
                {
                    var x = (long)1;
                }
            ##
                private long Callee()
                {
                    return 1;
                }
            ##}
            """);
 
    [Fact]
    public Task TestNestedConditionalInvocationExpression1()
        => TestVerifier.TestBothKeepAndRemoveInlinedMethodInSameFileAsync("""
            public class LinkedList
            {
                public LinkedList Next { get; }
            }
 
            public class TestClass
            {
                public void Caller()
                {
                    var l = new LinkedList();
                    Cal[||]lee(l);
                }
 
                private string Callee(LinkedList l)
                {
                    return l?.Next?.Next?.Next?.Next?.ToString();
                }
            }
            """, """
            public class LinkedList
            {
                public LinkedList Next { get; }
            }
 
            public class TestClass
            {
                public void Caller()
                {
                    var l = new LinkedList();
                    l?.Next?.Next?.Next?.Next?.ToString();
                }
            ##
                private string Callee(LinkedList l)
                {
                    return l?.Next?.Next?.Next?.Next?.ToString();
                }
            ##}
            """);
 
    [Fact]
    public Task TestNestedConditionalInvocationExpression2()
        => TestVerifier.TestBothKeepAndRemoveInlinedMethodInSameFileAsync("""
            public class LinkedList
            {
                public LinkedList Next { get; }
            }
 
            public class TestClass
            {
                public void Caller()
                {
                    var l = new LinkedList();
                    Cal[||]lee(l);
                }
 
                private string Callee(LinkedList l)
                {
                    return l?.ToString();
                }
            }
            """, """
            public class LinkedList
            {
                public LinkedList Next { get; }
            }
 
            public class TestClass
            {
                public void Caller()
                {
                    var l = new LinkedList();
                    l?.ToString();
                }
            ##
                private string Callee(LinkedList l)
                {
                    return l?.ToString();
                }
            ##}
            """);
 
    [Fact]
    public Task TestNestedConditionalInvocationExpression3()
        => TestVerifier.TestBothKeepAndRemoveInlinedMethodInSameFileAsync("""
            public class LinkedList
            {
                public LinkedList Next { get; }
            }
 
            public class TestClass
            {
                public void Caller()
                {
                    var l = new LinkedList();
                    Cal[||]lee(l);
                }
 
                private string Callee(LinkedList l)
                {
                    return l?.Next.ToString();
                }
            }
            """, """
            public class LinkedList
            {
                public LinkedList Next { get; }
            }
 
            public class TestClass
            {
                public void Caller()
                {
                    var l = new LinkedList();
                    l?.Next.ToString();
                }
            ##
                private string Callee(LinkedList l)
                {
                    return l?.Next.ToString();
                }
            ##}
            """);
 
    [Fact]
    public Task TestThrowStatement()
        => TestVerifier.TestBothKeepAndRemoveInlinedMethodInSameFileAsync("""
            using System;
            public class TestClass
            {
                public void Caller()
                {
                    Call[||]ee();
                }
 
                private string Callee()
                {
                    throw new Exception();
                }
            }
            """, """
            using System;
            public class TestClass
            {
                public void Caller()
                {
                    throw new Exception();
                }
            ##
                private string Callee()
                {
                    throw new Exception();
                }
            ##}
            """);
 
    [Fact]
    public Task TestThrowExpressionToThrowStatement()
        => TestVerifier.TestBothKeepAndRemoveInlinedMethodInSameFileAsync("""
            using System;
            public class TestClass
            {
                public void Caller()
                {
                    Call[||]ee();
                }
 
                private string Callee() => throw new Exception();
            }
            """, """
            using System;
            public class TestClass
            {
                public void Caller()
                {
                    throw new Exception();
                }
            ##
                private string Callee() => throw new Exception();
            ##}
            """);
 
    [Fact]
    public Task TestThrowExpression1()
        => TestVerifier.TestBothKeepAndRemoveInlinedMethodInSameFileAsync("""
            using System;
            public class TestClass
            {
                public void Caller(bool a)
                {
                    var x = a ? Call[||]ee() : "Hello";
                }
 
                private string Callee() => throw new Exception();
            }
            """, """
            using System;
            public class TestClass
            {
                public void Caller(bool a)
                {
                    var x = a ? throw new Exception() : "Hello";
                }
            ##
                private string Callee() => throw new Exception();
            ##}
            """);
 
    [Fact]
    public Task TestThrowExpression2()
        => TestVerifier.TestBothKeepAndRemoveInlinedMethodInSameFileAsync("""
            using System;
            public class TestClass
            {
                public void Caller(bool a) => Ca[||]llee();
 
                private string Callee() => throw new Exception();
            }
            """, """
            using System;
            public class TestClass
            {
                public void Caller(bool a) => throw new Exception();
            ##
                private string Callee() => throw new Exception();
            ##}
            """);
 
    [Fact]
    public Task TestThrowStatementToThrowExpression()
        => TestVerifier.TestBothKeepAndRemoveInlinedMethodInSameFileAsync("""
            using System;
            public class TestClass
            {
                public void Caller(bool a)
                {
                    var x = a ? Call[||]ee() : "Hello";
                }
 
                private string Callee()
                {
                    throw new Exception();
                }
            }
            """, """
            using System;
            public class TestClass
            {
                public void Caller(bool a)
                {
                    var x = a ? throw new Exception() : "Hello";
                }
            ##
                private string Callee()
                {
                    throw new Exception();
                }
            ##}
            """);
 
    [Fact]
    public Task TestWriteSingleParameter()
        => TestVerifier.TestBothKeepAndRemoveInlinedMethodInSameFileAsync("""
            public class TestClass
            {
                public void Caller(bool a)
                {
                    var x = C[||]allee(a ? 10 : 100);
                }
 
                private int Callee(int c)
                {
                    return c = 1000;
                }
            }
            """, """
            public class TestClass
            {
                public void Caller(bool a)
                {
                    int c = a ? 10 : 100;
                    var x = c = 1000;
                }
            ##
                private int Callee(int c)
                {
                    return c = 1000;
                }
            ##}
            """);
 
    [Fact]
    public Task TestReadMultipleTimesForParameter()
        => TestVerifier.TestBothKeepAndRemoveInlinedMethodInSameFileAsync("""
            public class TestClass
            {
                public void Caller(bool a)
                {
                    var x = C[||]allee(a ? 10 : 100, a);
                }
 
                private int Callee(int c, bool a)
                {
                    return a ? c + 1000 : c + 10000;
                }
            }
            """, """
            public class TestClass
            {
                public void Caller(bool a)
                {
                    int c = a ? 10 : 100;
                    var x = a ? c + 1000 : c + 10000;
                }
            ##
                private int Callee(int c, bool a)
                {
                    return a ? c + 1000 : c + 10000;
                }
            ##}
            """);
 
    [Fact]
    public Task TestInlineInArrowFunction1()
        => TestVerifier.TestBothKeepAndRemoveInlinedMethodInSameFileAsync("""
            public class TestClass
            {
                public int Caller(bool a) => Ca[||]llee(SomeInt(), a);
 
                private int SomeInt() => 1;
 
                private int Callee(int c, bool a)
                {
                    return a ? c + 1000 : c + 10000;
                }
            }
            """, """
            public class TestClass
            {
                public int Caller(bool a) => a ? SomeInt() + 1000 : SomeInt() + 10000;
 
                private int SomeInt() => 1;
            ##
                private int Callee(int c, bool a)
                {
                    return a ? c + 1000 : c + 10000;
                }
            ##}
            """);
 
    [Fact]
    public Task TestInlineInArrowFunction2()
    {
        var diagnostic = new List<DiagnosticResult>()
        {
            // User is inlining method in arrow function, there is no place to put the declaration of 'i'
            DiagnosticResult.CompilerError("CS0103").WithSpan(3, 29, 3, 30).WithArguments("i")
        };
        return TestVerifier.TestBothKeepAndRemoveInlinedMethodInSameFileAsync("""
            public class TestClass
            {
                public void Caller() => Ca[||]llee(out var j);
 
                private void Callee(out int i) => i = 1;
            }
            """, """
            public class TestClass
            {
                public void Caller() => i = 1;
            ##
                private void Callee(out int i) => i = 1;
            ##}
            """, diagnostic, diagnostic);
    }
 
    [Fact]
    public Task TestInlineInArrowProperty1()
        => TestVerifier.TestBothKeepAndRemoveInlinedMethodInSameFileAsync("""
            public class TestClass
            {
                private const int i = 10;
                public int Caller => Ca[||]llee();
 
                private int Callee() => i + 1;
            }
            """, """
            public class TestClass
            {
                private const int i = 10;
                public int Caller => i + 1;
            ##
                private int Callee() => i + 1;
            ##}
            """);
 
    [Fact]
    public Task TestInlineInArrowProperty2()
        => TestVerifier.TestBothKeepAndRemoveInlinedMethodInSameFileAsync("""
            public class TestClass
            {
                private const int i = 10;
                public int Caller { get => Cal[||]lee(); }
 
                private int Callee() => i + 1;
            }
            """, """
            public class TestClass
            {
                private const int i = 10;
                public int Caller { get => i + 1; }
            ##
                private int Callee() => i + 1;
            ##}
            """);
 
    [Fact]
    public Task TestInlineInArrowLambda1()
    {
        var diagnostic = new List<DiagnosticResult>()
        {
            // User is inlining method in arrow function, there is no place to put the declaration of 'i'
            DiagnosticResult.CompilerError("CS0103").WithSpan(6, 26, 6, 27).WithArguments("i")
        };
        return TestVerifier.TestBothKeepAndRemoveInlinedMethodInSameFileAsync("""
            using System;
            public class TestClass
            {
                public void Caller()
                {
                    Action f = () => Cal[||]lee(out var j);
                }
 
                private void Callee(out int i) => i = 1;
            }
            """, """
            using System;
            public class TestClass
            {
                public void Caller()
                {
                    Action f = () => i = 1;
                }
            ##
                private void Callee(out int i) => i = 1;
            ##}
            """, diagnostic, diagnostic);
    }
 
    [Fact]
    public Task TestInlineInArrowLambda2()
        => TestVerifier.TestBothKeepAndRemoveInlinedMethodInSameFileAsync("""
            using System;
            public class TestClass
            {
                public void Caller()
                {
                    Action f = () => { Cal[||]lee(out var j); };
                }
 
                private void Callee(out int i) => i = 1;
            }
            """, """
            using System;
            public class TestClass
            {
                public void Caller()
                {
                    Action f = () => { int j = 1; };
                }
            ##
                private void Callee(out int i) => i = 1;
            ##}
            """);
 
    [Fact]
    public Task TestInlineInLocalFunction()
        => TestVerifier.TestBothKeepAndRemoveInlinedMethodInSameFileAsync("""
            using System;
            public class TestClass
            {
                public void Caller()
                {
                    void Helper() { Cal[||]lee(out var j); }
                }
 
                private void Callee(out int i) => i = 1;
            }
            """, """
            using System;
            public class TestClass
            {
                public void Caller()
                {
                    void Helper() { int j = 1; }
                }
            ##
                private void Callee(out int i) => i = 1;
            ##}
            """);
 
    [Fact]
    public Task TestForPartialMethod1()
        => TestVerifier.TestBothKeepAndRemoveInlinedMethodInDifferentFileAsync(
        """
        public partial class TestClass
        {
            void Caller()
            {
                Call[||]ee();
            }
        }
        """,
            """
            public partial class TestClass
            {
                partial void Callee();
 
                partial void Callee()
                {
                    System.Console.WriteLine("10");
                }
            }
            """,
            """
            public partial class TestClass
            {
                void Caller()
                {
                    System.Console.WriteLine("10");
                }
            }
            """, """
            public partial class TestClass
            {
                partial void Callee();
            ##
                partial void Callee()
                {
                    System.Console.WriteLine("10");
                }
            ##}
            """);
 
    [Fact]
    public Task TestForExtendedPartialMethod1()
        => TestVerifier.TestInRegularScriptsInDifferentFilesAsync(
        """
        public partial class TestClass
        {
            void Caller()
            {
                Call[||]ee();
            }
        }
        """,
            """
            public partial class TestClass
            {
                private partial void Callee();
 
                private partial void Callee()
                {
                    System.Console.WriteLine("10");
                }
            }
            """,
            """
            public partial class TestClass
            {
                void Caller()
                {
                    System.Console.WriteLine("10");
                }
            }
            """, """
            public partial class TestClass
            {
                private partial void Callee();
 
                private partial void Callee()
                {
                    System.Console.WriteLine("10");
                }
            }
            """, keepInlinedMethod: true);
 
    [Fact]
    public Task TestForPartialMethod2()
        => TestVerifier.TestInRegularAndScriptInTheSameFileAsync(
        """
        public partial class TestClass
        {
            partial void Caller()
            {
                Call[||]ee();
            }
        }
        public partial class TestClass
        {
            partial void Caller();
            partial void Callee();
 
            partial void Callee()
            {
                System.Console.WriteLine("10");
            }
        }
        """,
            """
            public partial class TestClass
            {
                partial void Caller()
                {
                    System.Console.WriteLine("10");
                }
            }
            public partial class TestClass
            {
                partial void Caller();
                partial void Callee();
 
                partial void Callee()
                {
                    System.Console.WriteLine("10");
                }
            }
            """, keepInlinedMethod: true);
 
    [Fact]
    public Task TestForExtendedPartialMethod2()
        => TestVerifier.TestInRegularAndScriptInTheSameFileAsync(
        """
        public partial class TestClass
        {
            private partial void Caller()
            {
                Call[||]ee();
            }
        }
        public partial class TestClass
        {
            private partial void Caller();
            private partial void Callee();
 
            private partial void Callee()
            {
                System.Console.WriteLine("10");
            }
        }
        """,
            """
            public partial class TestClass
            {
                private partial void Caller()
                {
                    System.Console.WriteLine("10");
                }
            }
            public partial class TestClass
            {
                private partial void Caller();
                private partial void Callee();
 
                private partial void Callee()
                {
                    System.Console.WriteLine("10");
                }
            }
            """, keepInlinedMethod: true);
}