dotnet / roslyn

The Roslyn .NET compiler provides C# and Visual Basic languages with rich code analysis APIs.
https://docs.microsoft.com/dotnet/csharp/roslyn-sdk/
MIT License
18.95k stars 4.02k forks source link

Please stop the C# auto-formatter indent based on global scope #43189

Open vsfeedback opened 4 years ago

vsfeedback commented 4 years ago

This issue has been moved from a ticket on Developer Community.


The C# auto-formatter indents according to its view of the world, not the scope it’s really in. If you have some code that (for good reason) is not indented exacly to the level the auto-formatter would indent it to if it was let lose to do its thing for the whole file, it indents code within the currently edited scope completely up the walls.

Let’s say you have some code inside a method that the auto-formatter thinks should be at indentation level N, but you have for good reason de-indented it to be at level M. Let’s take a concrete example.

(using indent=2 here to keep it readable in a web browser)

  void method()
  {
    ...
      if (something) // <- manually de-indented to level M
      {
        if (blah1 && blah2 && many_more_checks)
        {
        }
      }
    ...
  }

If you now decide to break the conditional checks up into multi-line, you might f.ex. select the first &&, engage multi-select with Shift-Alt-Dot (both because it’s 100-1000 times faster than waiting for the refactoring to suggest it, and because you want to keep && at EOL), hit Right, and finalize with Return, expecting the following

  void method()
  {
    ...
      if (something)
      {
        if (blah1 &&
            blah2 &&
            many_more_checks)
        {
        }
      }
    ...
  }

Instead you are given

  void method()
  {
    ...
      if (something)
      {
        if (blah1 &&
                blah2 && // <- bad auto-formatter, no cookie [1]
                many_more_checks)
        {
        }
      }
    ...
  }

Now you need to manually de-indent this broken indentation the auto-formatter inserted。

The reason for this misbehaviour is that the auto-formatter doesn’t give a rat’s about what the surrounding scope indentation is. It looks at the indentation from the method (or even file) level, and indents the code according to how it thinks the world should look - globally.

The fix is obvious; Priority #1 for the auto-formatter’s indentation choice should be to indent relative to the surrounding scope. Only if that fails could it be let out of its cage

Sidenote: This pain is induced for many more editing scenarios, for the same reason, but perhaps getting this specific scenario fixed could provide a starting point.

[1] I won’t even touch the fact it’s using indent N+1 there, instead of the proper indent M followed by four spaces for alignment (sizeof("if (")) – I’ve already experienced the futility of trying to explain the difference between indentation and aligment.


Original Comments

Visual Studio Feedback System on 4/7/2020, 01:14 AM:

We have directed your feedback to the appropriate engineering team for further evaluation. The team will review the feedback and notify you about the next steps.


Original Solutions

(no solutions)

sharwell commented 4 years ago

I agree that the behavior observed above is incorrect. The indentation engine should use the narrowest (i.e. innermost) scope as the baseline for determining relative indentation adjustments. This approach works both for cases where the inner scope matches the global expectations, and for cases where it has been changed in ways that differ from global expectations.