@@ -79,37 +79,7 @@ public ImmutableArray<TextChange> GetFormattingChangesOnTypedCharacter(
7979 var token = root . FindToken ( Math . Max ( 0 , caretPosition - 1 ) , findInsideTrivia : true ) ;
8080 var formattingRules = GetFormattingRules ( document , caretPosition , token ) ;
8181
82- // Do not attempt to format on open/close brace if autoformat on close brace feature is off, instead just smart
83- // indent.
84- //
85- // We want this behavior because it's totally reasonable for a user to want to not have on automatic formatting
86- // because they feel it is too aggressive. However, by default, if you have smart-indentation on and are just
87- // hitting enter, you'll common have the caret placed one indent higher than your current construct. For
88- // example, if you have:
89- //
90- // if (true)
91- // $ <-- smart indent will have placed the caret here here.
92- //
93- // This is acceptable given that the user may want to just write a simple statement there. However, if they
94- // start writing `{`, then things should snap over to be:
95- //
96- // if (true)
97- // {
98- //
99- // Importantly, this is just an indentation change, no actual 'formatting' is done. We do the same with close
100- // brace. If you have:
101- //
102- // if (...)
103- // {
104- // bad . ly ( for (mmated+code) ) ;
105- // $ <-- smart indent will have placed the care here.
106- //
107- // If the user hits `}` then we will properly smart indent the `}` to match the `{`. However, we won't touch any
108- // of the other code in that block, unlike if we were formatting.
109- var onlySmartIndent =
110- ( token . IsKind ( SyntaxKind . CloseBraceToken ) && OnlySmartIndentCloseBrace ( indentationOptions . AutoFormattingOptions ) ) ||
111- ( token . IsKind ( SyntaxKind . OpenBraceToken ) && OnlySmartIndentOpenBrace ( indentationOptions . AutoFormattingOptions ) ) ;
112-
82+ var onlySmartIndent = OnlySmartIndentBraceToken ( ) || OnlySmartIndentElseKeyword ( ) ;
11383 if ( onlySmartIndent )
11484 {
11585 // if we're only doing smart indent, then ignore all edits to this token that occur before the span of the
@@ -124,6 +94,62 @@ public ImmutableArray<TextChange> GetFormattingChangesOnTypedCharacter(
12494 return changes ;
12595
12696 return [ .. FormatToken ( document , indentationOptions , token , formattingRules , cancellationToken ) ] ;
97+
98+ bool OnlySmartIndentBraceToken ( )
99+ {
100+ // Do not attempt to format on open/close brace if autoformat on close brace feature is off, instead just smart
101+ // indent.
102+ //
103+ // We want this behavior because it's totally reasonable for a user to want to not have on automatic formatting
104+ // because they feel it is too aggressive. However, by default, if you have smart-indentation on and are just
105+ // hitting enter, you'll common have the caret placed one indent higher than your current construct. For
106+ // example, if you have:
107+ //
108+ // if (true)
109+ // $ <-- smart indent will have placed the caret here here.
110+ //
111+ // This is acceptable given that the user may want to just write a simple statement there. However, if they
112+ // start writing `{`, then things should snap over to be:
113+ //
114+ // if (true)
115+ // {
116+ //
117+ // Importantly, this is just an indentation change, no actual 'formatting' is done. We do the same with close
118+ // brace. If you have:
119+ //
120+ // if (...)
121+ // {
122+ // bad . ly ( for (mmated+code) ) ;
123+ // $ <-- smart indent will have placed the care here.
124+ //
125+ // If the user hits `}` then we will properly smart indent the `}` to match the `{`. However, we won't touch any
126+ // of the other code in that block, unlike if we were formatting.
127+ return
128+ ( token . IsKind ( SyntaxKind . CloseBraceToken ) && OnlySmartIndentCloseBrace ( indentationOptions . AutoFormattingOptions ) ) ||
129+ ( token . IsKind ( SyntaxKind . OpenBraceToken ) && OnlySmartIndentOpenBrace ( indentationOptions . AutoFormattingOptions ) ) ;
130+ }
131+
132+ bool OnlySmartIndentElseKeyword ( )
133+ {
134+ // If the user has typed the `e` in `else` we only want to indent the 'else' token itself (the purpose is to
135+ // place the `else` token properly in cases like:
136+ //
137+ // foreach (var item in collection)
138+ // if (item.IsValid)
139+ // Process(item);
140+ // els //<-- user types 'e' here
141+ //
142+ // In this case we want to indent 'else' to match the 'if' above. We do not want to adjust the formatting of
143+ // anything else. This is especially important as 'else' takes an embedded statement, and we don't want the
144+ // following unrelated statement to get reformatted (unless it's a block that should travel with the else.
145+ if ( token . Kind ( ) != SyntaxKind . ElseKeyword )
146+ return false ;
147+
148+ if ( token . Parent is not ElseClauseSyntax elseClause )
149+ return false ;
150+
151+ return elseClause . Statement is not BlockSyntax ;
152+ }
127153 }
128154
129155 private static bool OnlySmartIndentCloseBrace ( in AutoFormattingOptions options )
0 commit comments