Does `rhs.body` have a shape safe to reformat without optional parens around it? Returns True for only a subset of potentially nice looking formattings but the point is to not return false positives that end up producing lines that are too long.
(
rhs: RHSResult,
line_length: int,
)
| 1364 | |
| 1365 | |
| 1366 | def can_omit_invisible_parens( |
| 1367 | rhs: RHSResult, |
| 1368 | line_length: int, |
| 1369 | ) -> bool: |
| 1370 | """Does `rhs.body` have a shape safe to reformat without optional parens around it? |
| 1371 | |
| 1372 | Returns True for only a subset of potentially nice looking formattings but |
| 1373 | the point is to not return false positives that end up producing lines that |
| 1374 | are too long. |
| 1375 | """ |
| 1376 | line = rhs.body |
| 1377 | |
| 1378 | # We can't omit parens if doing so would result in a type: ignore comment |
| 1379 | # sharing a line with other comments, as that breaks type: ignore parsing. |
| 1380 | # Check if the opening bracket (last leaf of head) has comments that would merge |
| 1381 | # with comments from the first line of the body. |
| 1382 | if rhs.head.leaves: |
| 1383 | opening_bracket = rhs.head.leaves[-1] |
| 1384 | head_comments = rhs.head.comments.get(id(opening_bracket), []) |
| 1385 | |
| 1386 | # If there are comments on the opening bracket line, check if any would |
| 1387 | # conflict with type: ignore comments in the body |
| 1388 | if head_comments: |
| 1389 | has_type_ignore_in_head = any( |
| 1390 | is_type_ignore_comment(comment, mode=rhs.head.mode) |
| 1391 | for comment in head_comments |
| 1392 | ) |
| 1393 | has_other_comment_in_head = any( |
| 1394 | not is_type_ignore_comment(comment, mode=rhs.head.mode) |
| 1395 | for comment in head_comments |
| 1396 | ) |
| 1397 | |
| 1398 | # Check for comments in the body that would potentially end up on the |
| 1399 | # same line as the head comments when parens are removed |
| 1400 | has_type_ignore_in_body = False |
| 1401 | has_other_comment_in_body = False |
| 1402 | for leaf in rhs.body.leaves: |
| 1403 | for comment in rhs.body.comments.get(id(leaf), []): |
| 1404 | if is_type_ignore_comment(comment, mode=rhs.body.mode): |
| 1405 | has_type_ignore_in_body = True |
| 1406 | else: |
| 1407 | has_other_comment_in_body = True |
| 1408 | |
| 1409 | # Preserve parens if we have both type: ignore and other comments that |
| 1410 | # could end up on the same line |
| 1411 | if (has_type_ignore_in_head and has_other_comment_in_body) or ( |
| 1412 | has_other_comment_in_head and has_type_ignore_in_body |
| 1413 | ): |
| 1414 | return False |
| 1415 | |
| 1416 | # We need optional parens in order to split standalone comments to their own lines |
| 1417 | # if there are no nested parens around the standalone comments |
| 1418 | closing_bracket: Leaf | None = None |
| 1419 | for leaf in reversed(line.leaves): |
| 1420 | if closing_bracket and leaf is closing_bracket.opening_bracket: |
| 1421 | closing_bracket = None |
| 1422 | if leaf.type == STANDALONE_COMMENT and not closing_bracket: |
| 1423 | return False |
no test coverage detected