dotnet/roslyn

"Pull Member Up" produces an incorrect level of indentation when Base class already has members

オープン

#54,847 opened on 2021/07/15

 (0 件のコメント) (0 件のリアクション) (0 人の担当者)C# (4,257 件のフォーク)batch import
Area-IDEBugIDE-Formatterhelp wanted

Repository metrics

Stars
 (20,414 個のスター)
PR merge metrics
 (平均マージ 6d 17h) (30d で 256 merged PRs)

説明

Steps to Reproduce: When we have a file such as this, where the derived class has a different indentation level than the base class (from namespaces or otherwise):

namespace TestNs1
{
    public class Base
    {
    }
}
namespace TestNs2
{
    namespace InnerNs
    {
        public class Derived : Base
        {
            public int TestMethod()
            {
                return 5;
            }
        }
    }
}

And we use Ctrl + . or the lightbulb to open Quick Actions on TestMethod() and Pull Member up to Base, we get the correct level of indentation for TestMethod(), i.e. one level more than Base. However, if we produce a file with at least one existing base member as follows:

namespace TestNs1
{
    using System;

    public class Base
    {
        public int Num { get; set; }
    }
}
namespace TestNs2
{
    namespace InnerNs
    {
        public class Derived : Base
        {
            public int TestMethod()
            {
                return 5;
            }
        }
    }
}

Then TestMethod(), when moved to Base will have the same indentation level as it did in Derived, which is not the correct indentation level for a member of Base. Expected Behavior:

namespace TestNs1
{
    using System;

    public class Base
    {
        public int Num { get; set; }
        public int TestMethod()
        {
            return 5;
        }
    }
}
namespace TestNs2
{
    namespace InnerNs
    {
        public class Derived : Base
        {
        }
    }
}

Actual Behavior:

namespace TestNs1
{
    using System;

    public class Base
    {
        public int Num { get; set; }
            public int TestMethod()
            {
                return 5;
            }
    }
}
namespace TestNs2
{
    namespace InnerNs
    {
        public class Derived : Base
        {
        }
    }
}

Note how TestMethod() is indented one more than Num.

I believe this is caused by the formatter annotation not being applied when the member list is larger than 1. In CSharpCodeGenerationHelpers, there is a method which only adds a formatter annotation if there is exactly one member. It is called near the very end of the member adding process. I suspect the formatter annotation would find the correct indentation, which is why moving a single member has the correct indentation, while multiple member moves or moves to types with existing members keeps indentation as before.

This may be an issue with other code generation services which add members or otherwise call this helper.

コントリビューターガイド