|
4 | 4 | import 'package:analyzer/dart/ast/ast.dart'; |
5 | 5 | import 'package:analyzer/dart/ast/token.dart'; |
6 | 6 |
|
| 7 | +import 'piece/list.dart'; |
| 8 | + |
7 | 9 | extension AstNodeExtensions on AstNode { |
8 | 10 | /// The first token at the beginning of this AST node, not including any |
9 | 11 | /// tokens for leading doc comments. |
@@ -149,58 +151,66 @@ extension ExpressionExtensions on Expression { |
149 | 151 | /// |
150 | 152 | /// Completely empty delimited constructs like `[]` and `foo()` don't allow |
151 | 153 | /// splitting inside them, so are not considered block-like. |
152 | | - bool get canBlockSplit { |
153 | | - // Unwrap named expressions to get the real expression inside. |
154 | | - var expression = this; |
155 | | - if (expression is NamedExpression) { |
156 | | - expression = expression.expression; |
157 | | - } |
| 154 | + bool get canBlockSplit => blockFormatType != BlockFormat.none; |
| 155 | + |
| 156 | + /// When this expression is in an argument list, what kind of block formatting |
| 157 | + /// category it belongs to. |
| 158 | + BlockFormat get blockFormatType { |
| 159 | + return switch (this) { |
| 160 | + // Unwrap named expressions to get the real expression inside. |
| 161 | + NamedExpression(:var expression) => expression.blockFormatType, |
158 | 162 |
|
159 | | - // TODO(tall): Consider whether immediately-invoked function expressions |
160 | | - // should be block argument candidates, like: |
161 | | - // |
162 | | - // function(() { |
163 | | - // body; |
164 | | - // }()); |
165 | | - return switch (expression) { |
166 | 163 | // Allow the target of a single-section cascade to be block formatted. |
167 | | - CascadeExpression(:var target, :var cascadeSections) => |
168 | | - cascadeSections.length == 1 && target.canBlockSplit, |
| 164 | + CascadeExpression(:var target, :var cascadeSections) |
| 165 | + when cascadeSections.length == 1 && target.canBlockSplit => |
| 166 | + BlockFormat.invocation, |
169 | 167 |
|
170 | 168 | // A function expression can use either a non-empty parameter list or a |
171 | 169 | // non-empty block body for block formatting. |
172 | | - FunctionExpression(:var parameters?, :var body) => |
173 | | - parameters.parameters.canSplit(parameters.rightParenthesis) || |
174 | | - (body is BlockFunctionBody && |
175 | | - body.block.statements.canSplit(body.block.rightBracket)), |
| 170 | + FunctionExpression(:var parameters?, :var body) |
| 171 | + when parameters.parameters.canSplit(parameters.rightParenthesis) || |
| 172 | + (body is BlockFunctionBody && |
| 173 | + body.block.statements.canSplit(body.block.rightBracket)) => |
| 174 | + BlockFormat.function, |
| 175 | + |
| 176 | + // An immediately invoked function expression is formatted like a |
| 177 | + // function expression. |
| 178 | + FunctionExpressionInvocation(:FunctionExpression function) |
| 179 | + when function.blockFormatType == BlockFormat.function => |
| 180 | + BlockFormat.function, |
176 | 181 |
|
177 | 182 | // Non-empty collection literals can block split. |
178 | 183 | ListLiteral(:var elements, :var rightBracket) || |
179 | | - SetOrMapLiteral(:var elements, :var rightBracket) => |
180 | | - elements.canSplit(rightBracket), |
181 | | - RecordLiteral(:var fields, :var rightParenthesis) => |
182 | | - fields.canSplit(rightParenthesis), |
183 | | - SwitchExpression(:var cases, :var rightBracket) => |
184 | | - cases.canSplit(rightBracket), |
| 184 | + SetOrMapLiteral(:var elements, :var rightBracket) |
| 185 | + when elements.canSplit(rightBracket) => |
| 186 | + BlockFormat.collection, |
| 187 | + RecordLiteral(:var fields, :var rightParenthesis) |
| 188 | + when fields.canSplit(rightParenthesis) => |
| 189 | + BlockFormat.collection, |
| 190 | + SwitchExpression(:var cases, :var rightBracket) |
| 191 | + when cases.canSplit(rightBracket) => |
| 192 | + BlockFormat.collection, |
185 | 193 |
|
186 | 194 | // Function calls can block split if their argument lists can. |
187 | 195 | InstanceCreationExpression(:var argumentList) || |
188 | | - MethodInvocation(:var argumentList) => |
189 | | - argumentList.arguments.canSplit(argumentList.rightParenthesis), |
| 196 | + MethodInvocation(:var argumentList) |
| 197 | + when argumentList.arguments.canSplit(argumentList.rightParenthesis) => |
| 198 | + BlockFormat.invocation, |
190 | 199 |
|
191 | 200 | // Note: Using a separate case instead of `||` for this type because |
192 | 201 | // Dart 3.0 reports an error that [argumentList] has a different type |
193 | 202 | // here than in the previous two clauses. |
194 | | - FunctionExpressionInvocation(:var argumentList) => |
195 | | - argumentList.arguments.canSplit(argumentList.rightParenthesis), |
| 203 | + FunctionExpressionInvocation(:var argumentList) |
| 204 | + when argumentList.arguments.canSplit(argumentList.rightParenthesis) => |
| 205 | + BlockFormat.invocation, |
196 | 206 |
|
197 | 207 | // Multi-line strings can. |
198 | | - StringInterpolation(isMultiline: true) => true, |
199 | | - SimpleStringLiteral(isMultiline: true) => true, |
| 208 | + StringInterpolation(isMultiline: true) => BlockFormat.collection, |
| 209 | + SimpleStringLiteral(isMultiline: true) => BlockFormat.collection, |
200 | 210 |
|
201 | | - // Parenthesized expressions can if the inner one can. |
202 | | - ParenthesizedExpression(:var expression) => expression.canBlockSplit, |
203 | | - _ => false, |
| 211 | + // Parenthesized expressions unwrap the inner expression. |
| 212 | + ParenthesizedExpression(:var expression) => expression.blockFormatType, |
| 213 | + _ => BlockFormat.none, |
204 | 214 | }; |
205 | 215 | } |
206 | 216 |
|
|
0 commit comments