prettycsharp 1.1.8__tar.gz → 1.1.10__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {prettycsharp-1.1.8 → prettycsharp-1.1.10}/CHANGELOG.md +22 -0
- {prettycsharp-1.1.8 → prettycsharp-1.1.10}/DESIGN.md +19 -0
- {prettycsharp-1.1.8 → prettycsharp-1.1.10}/PKG-INFO +1 -1
- {prettycsharp-1.1.8 → prettycsharp-1.1.10}/src/prettycsharp/__init__.py +1 -1
- {prettycsharp-1.1.8 → prettycsharp-1.1.10}/src/prettycsharp/printer/expressions.py +86 -6
- {prettycsharp-1.1.8 → prettycsharp-1.1.10}/src/prettycsharp/printer/statements.py +7 -2
- {prettycsharp-1.1.8 → prettycsharp-1.1.10}/tests/test_layout.py +162 -5
- {prettycsharp-1.1.8 → prettycsharp-1.1.10}/.gitattributes +0 -0
- {prettycsharp-1.1.8 → prettycsharp-1.1.10}/.github/codeql/codeql-config.yml +0 -0
- {prettycsharp-1.1.8 → prettycsharp-1.1.10}/.github/dependabot.yml +0 -0
- {prettycsharp-1.1.8 → prettycsharp-1.1.10}/.github/requirements/build.in +0 -0
- {prettycsharp-1.1.8 → prettycsharp-1.1.10}/.github/requirements/build.txt +0 -0
- {prettycsharp-1.1.8 → prettycsharp-1.1.10}/.github/requirements/fuzz.in +0 -0
- {prettycsharp-1.1.8 → prettycsharp-1.1.10}/.github/requirements/fuzz.txt +0 -0
- {prettycsharp-1.1.8 → prettycsharp-1.1.10}/.github/requirements/pip-audit.in +0 -0
- {prettycsharp-1.1.8 → prettycsharp-1.1.10}/.github/requirements/pip-audit.txt +0 -0
- {prettycsharp-1.1.8 → prettycsharp-1.1.10}/.github/requirements/runtime.in +0 -0
- {prettycsharp-1.1.8 → prettycsharp-1.1.10}/.github/requirements/runtime.txt +0 -0
- {prettycsharp-1.1.8 → prettycsharp-1.1.10}/.github/requirements/test.in +0 -0
- {prettycsharp-1.1.8 → prettycsharp-1.1.10}/.github/requirements/test.txt +0 -0
- {prettycsharp-1.1.8 → prettycsharp-1.1.10}/.github/requirements/zizmor.in +0 -0
- {prettycsharp-1.1.8 → prettycsharp-1.1.10}/.github/requirements/zizmor.txt +0 -0
- {prettycsharp-1.1.8 → prettycsharp-1.1.10}/.github/security/accepted.toml +0 -0
- {prettycsharp-1.1.8 → prettycsharp-1.1.10}/.github/security/clamav/Dockerfile +0 -0
- {prettycsharp-1.1.8 → prettycsharp-1.1.10}/.github/security/malware-accepted.toml +0 -0
- {prettycsharp-1.1.8 → prettycsharp-1.1.10}/.github/security/semgrep/Dockerfile +0 -0
- {prettycsharp-1.1.8 → prettycsharp-1.1.10}/.github/security/yara.json +0 -0
- {prettycsharp-1.1.8 → prettycsharp-1.1.10}/.github/security/yara_update.py +0 -0
- {prettycsharp-1.1.8 → prettycsharp-1.1.10}/.github/workflows/auto-merge.yml +0 -0
- {prettycsharp-1.1.8 → prettycsharp-1.1.10}/.github/workflows/ci.yml +0 -0
- {prettycsharp-1.1.8 → prettycsharp-1.1.10}/.github/workflows/fuzz.yml +0 -0
- {prettycsharp-1.1.8 → prettycsharp-1.1.10}/.github/workflows/malware-scan.yml +0 -0
- {prettycsharp-1.1.8 → prettycsharp-1.1.10}/.github/workflows/publish.yml +0 -0
- {prettycsharp-1.1.8 → prettycsharp-1.1.10}/.github/workflows/scorecard.yml +0 -0
- {prettycsharp-1.1.8 → prettycsharp-1.1.10}/.github/workflows/security.yml +0 -0
- {prettycsharp-1.1.8 → prettycsharp-1.1.10}/.github/workflows/update-yara-rules.yml +0 -0
- {prettycsharp-1.1.8 → prettycsharp-1.1.10}/.github/zizmor.yml +0 -0
- {prettycsharp-1.1.8 → prettycsharp-1.1.10}/.gitignore +0 -0
- {prettycsharp-1.1.8 → prettycsharp-1.1.10}/AGENTS.md +0 -0
- {prettycsharp-1.1.8 → prettycsharp-1.1.10}/CLAUDE.md +0 -0
- {prettycsharp-1.1.8 → prettycsharp-1.1.10}/LICENSE +0 -0
- {prettycsharp-1.1.8 → prettycsharp-1.1.10}/README.md +0 -0
- {prettycsharp-1.1.8 → prettycsharp-1.1.10}/SECURITY.md +0 -0
- {prettycsharp-1.1.8 → prettycsharp-1.1.10}/fuzz/fuzz_formatter.py +0 -0
- {prettycsharp-1.1.8 → prettycsharp-1.1.10}/pyproject.toml +0 -0
- {prettycsharp-1.1.8 → prettycsharp-1.1.10}/scripts/security/malware_report.py +0 -0
- {prettycsharp-1.1.8 → prettycsharp-1.1.10}/scripts/security/security_report.py +0 -0
- {prettycsharp-1.1.8 → prettycsharp-1.1.10}/src/prettycsharp/__main__.py +0 -0
- {prettycsharp-1.1.8 → prettycsharp-1.1.10}/src/prettycsharp/cli.py +0 -0
- {prettycsharp-1.1.8 → prettycsharp-1.1.10}/src/prettycsharp/conditional.py +0 -0
- {prettycsharp-1.1.8 → prettycsharp-1.1.10}/src/prettycsharp/config.py +0 -0
- {prettycsharp-1.1.8 → prettycsharp-1.1.10}/src/prettycsharp/doc.py +0 -0
- {prettycsharp-1.1.8 → prettycsharp-1.1.10}/src/prettycsharp/formatter.py +0 -0
- {prettycsharp-1.1.8 → prettycsharp-1.1.10}/src/prettycsharp/ignore.py +0 -0
- {prettycsharp-1.1.8 → prettycsharp-1.1.10}/src/prettycsharp/isolate.py +0 -0
- {prettycsharp-1.1.8 → prettycsharp-1.1.10}/src/prettycsharp/parsing.py +0 -0
- {prettycsharp-1.1.8 → prettycsharp-1.1.10}/src/prettycsharp/printer/__init__.py +0 -0
- {prettycsharp-1.1.8 → prettycsharp-1.1.10}/src/prettycsharp/printer/core.py +0 -0
- {prettycsharp-1.1.8 → prettycsharp-1.1.10}/src/prettycsharp/printer/declarations.py +0 -0
- {prettycsharp-1.1.8 → prettycsharp-1.1.10}/src/prettycsharp/project.py +0 -0
- {prettycsharp-1.1.8 → prettycsharp-1.1.10}/src/prettycsharp/py.typed +0 -0
- {prettycsharp-1.1.8 → prettycsharp-1.1.10}/src/prettycsharp/rewrites.py +0 -0
- {prettycsharp-1.1.8 → prettycsharp-1.1.10}/src/prettycsharp/settings.py +0 -0
- {prettycsharp-1.1.8 → prettycsharp-1.1.10}/src/prettycsharp/syntax.py +0 -0
- {prettycsharp-1.1.8 → prettycsharp-1.1.10}/src/prettycsharp/verify.py +0 -0
- {prettycsharp-1.1.8 → prettycsharp-1.1.10}/tests/fuzz_corpus/csharp/comment_only_accessor_list.cs +0 -0
- {prettycsharp-1.1.8 → prettycsharp-1.1.10}/tests/fuzz_corpus/csharp/conditional_assignments.cs +0 -0
- {prettycsharp-1.1.8 → prettycsharp-1.1.10}/tests/fuzz_corpus/csharp/declarations.cs +0 -0
- {prettycsharp-1.1.8 → prettycsharp-1.1.10}/tests/fuzz_corpus/csharp/directives.cs +0 -0
- {prettycsharp-1.1.8 → prettycsharp-1.1.10}/tests/fuzz_corpus/csharp/embedded_statements.cs +0 -0
- {prettycsharp-1.1.8 → prettycsharp-1.1.10}/tests/fuzz_corpus/csharp/expressions.cs +0 -0
- {prettycsharp-1.1.8 → prettycsharp-1.1.10}/tests/fuzz_corpus/csharp/members.cs +0 -0
- {prettycsharp-1.1.8 → prettycsharp-1.1.10}/tests/fuzz_corpus/csharp/order.cs +0 -0
- {prettycsharp-1.1.8 → prettycsharp-1.1.10}/tests/fuzz_corpus/csharp/queries_and_patterns.cs +0 -0
- {prettycsharp-1.1.8 → prettycsharp-1.1.10}/tests/fuzz_corpus/csharp/split_by_conditionals.cs +0 -0
- {prettycsharp-1.1.8 → prettycsharp-1.1.10}/tests/fuzz_corpus/csharp/statements.cs +0 -0
- {prettycsharp-1.1.8 → prettycsharp-1.1.10}/tests/fuzz_corpus/csharp/strings.cs +0 -0
- {prettycsharp-1.1.8 → prettycsharp-1.1.10}/tests/support.py +0 -0
- {prettycsharp-1.1.8 → prettycsharp-1.1.10}/tests/test_cli.py +0 -0
- {prettycsharp-1.1.8 → prettycsharp-1.1.10}/tests/test_conditional.py +0 -0
- {prettycsharp-1.1.8 → prettycsharp-1.1.10}/tests/test_config.py +0 -0
- {prettycsharp-1.1.8 → prettycsharp-1.1.10}/tests/test_doc.py +0 -0
- {prettycsharp-1.1.8 → prettycsharp-1.1.10}/tests/test_docs.py +0 -0
- {prettycsharp-1.1.8 → prettycsharp-1.1.10}/tests/test_format_around.py +0 -0
- {prettycsharp-1.1.8 → prettycsharp-1.1.10}/tests/test_fuzz_corpus.py +0 -0
- {prettycsharp-1.1.8 → prettycsharp-1.1.10}/tests/test_grammar_compatibility.py +0 -0
- {prettycsharp-1.1.8 → prettycsharp-1.1.10}/tests/test_ignore.py +0 -0
- {prettycsharp-1.1.8 → prettycsharp-1.1.10}/tests/test_parsing.py +0 -0
- {prettycsharp-1.1.8 → prettycsharp-1.1.10}/tests/test_project.py +0 -0
- {prettycsharp-1.1.8 → prettycsharp-1.1.10}/tests/test_rewrites.py +0 -0
- {prettycsharp-1.1.8 → prettycsharp-1.1.10}/tests/test_settings.py +0 -0
- {prettycsharp-1.1.8 → prettycsharp-1.1.10}/tests/test_verify.py +0 -0
|
@@ -2,6 +2,28 @@
|
|
|
2
2
|
|
|
3
3
|
Each release's section becomes the body of its GitHub release.
|
|
4
4
|
|
|
5
|
+
## [1.1.10] - 2026-10-18
|
|
6
|
+
|
|
7
|
+
- A tuple argument ending in a multiline block lambda closes the tuple and
|
|
8
|
+
call parentheses on their own line at the call's indentation, matching
|
|
9
|
+
Visual Studio's formatting. Ordinary lambda arguments keep their layout.
|
|
10
|
+
- Empty argument parentheses without interior comments stay together as
|
|
11
|
+
`()`. Long empty-constructor assignments break after `=` instead of
|
|
12
|
+
splitting the parentheses. Interior comments are preserved.
|
|
13
|
+
|
|
14
|
+
## [1.1.9] - 2026-10-18
|
|
15
|
+
|
|
16
|
+
- With the default `binary_wrap`, multiline conditions in catch filters,
|
|
17
|
+
`if`, and loops start below `(` and put `)` on its own line. This includes
|
|
18
|
+
pattern chains, mixed Boolean conditions, and predicate calls.
|
|
19
|
+
- Inline collection expressions keep tight brackets around complex elements
|
|
20
|
+
and spreads, such as `[new HpackField(wire, "")]` and `[.. source.Select(...)]`,
|
|
21
|
+
avoiding Visual Studio's IDE0055 formatting diagnostic.
|
|
22
|
+
- A multiline collection argument no longer adds a blank line after the
|
|
23
|
+
call's opening parenthesis.
|
|
24
|
+
- Chains of negated patterns, including `is not A and not B` followed by
|
|
25
|
+
Boolean operators, wrap at one consistent continuation indentation level.
|
|
26
|
+
|
|
5
27
|
## [1.1.8] - 2026-10-18
|
|
6
28
|
|
|
7
29
|
- Long `or` and `and` patterns wrap at the configured line width using
|
|
@@ -177,7 +177,21 @@ parenthesis unless all three clauses are empty: `for (; ; )`.
|
|
|
177
177
|
| `ternary_wrap` | `before`: break before `?` and `:` when too long | `after`, `always` |
|
|
178
178
|
| `lambda_body` | `hug`: the last argument hangs off the call line when it is a lambda with a block body or a broken member chain, or a creation with a broken initializer | `argument` |
|
|
179
179
|
|
|
180
|
+
With `lambda_body = "hug"` and `argument_wrap = "one_per_line"`, a single
|
|
181
|
+
tuple argument ending in a multiline block lambda closes both enclosing
|
|
182
|
+
parentheses on their own line at the call's indentation.
|
|
183
|
+
|
|
184
|
+
Empty argument parentheses without interior comments stay together as `()`.
|
|
185
|
+
An overlong assignment to an empty constructor breaks after `=` instead of
|
|
186
|
+
splitting the empty parentheses.
|
|
187
|
+
|
|
180
188
|
`binary_wrap` also controls line breaks in `or` and `and` patterns.
|
|
189
|
+
With `before_operator_paren_own_line`, broken conditions in catch
|
|
190
|
+
filters, `if`, `while`, and `do` loops put the expression below `(` and `)`
|
|
191
|
+
on its own line, including predicate calls and mixed Boolean/pattern
|
|
192
|
+
conditions. Pattern operators take one further continuation indent.
|
|
193
|
+
Negated pattern chains and trailing Boolean operators share one continuation
|
|
194
|
+
indent, including `value is not A and not B && condition`.
|
|
181
195
|
|
|
182
196
|
```csharp
|
|
183
197
|
var invoice = invoiceService.CreateInvoice(
|
|
@@ -225,6 +239,11 @@ orders.ForEach(order =>
|
|
|
225
239
|
| `simple_lists_inline` | `true`: lists of literals, constants, and plain names stay on one line when they fit | `false` |
|
|
226
240
|
| `trailing_commas` | `remove` | `add`, `preserve` |
|
|
227
241
|
|
|
242
|
+
Inline collection expressions keep their brackets tight, including complex
|
|
243
|
+
elements: `[new Item()]`. Broken collections put the elements on new lines.
|
|
244
|
+
When a collection starts on an argument's own line, its opening bracket
|
|
245
|
+
does not add another line break.
|
|
246
|
+
|
|
228
247
|
```csharp
|
|
229
248
|
var empty = new Order { Id = 42 };
|
|
230
249
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: prettycsharp
|
|
3
|
-
Version: 1.1.
|
|
3
|
+
Version: 1.1.10
|
|
4
4
|
Summary: An opinionated formatter for C#, in the spirit of Prettier
|
|
5
5
|
Project-URL: Homepage, https://github.com/WilliamSmithEdward/prettyCSharp
|
|
6
6
|
Project-URL: Repository, https://github.com/WilliamSmithEdward/prettyCSharp
|
|
@@ -4,7 +4,7 @@ from prettycsharp.formatter import FormatResult, FormattingError, format_details
|
|
|
4
4
|
from prettycsharp.parsing import CSharpSyntaxError
|
|
5
5
|
from prettycsharp.settings import Settings, SettingsError
|
|
6
6
|
|
|
7
|
-
__version__ = "1.1.
|
|
7
|
+
__version__ = "1.1.10"
|
|
8
8
|
|
|
9
9
|
__all__ = [
|
|
10
10
|
"CSharpSyntaxError",
|
|
@@ -7,6 +7,7 @@ from collections.abc import Sequence
|
|
|
7
7
|
from dataclasses import dataclass, field
|
|
8
8
|
|
|
9
9
|
from prettycsharp.doc import (
|
|
10
|
+
ENSURE_LINE,
|
|
10
11
|
HARDLINE,
|
|
11
12
|
LINE,
|
|
12
13
|
SOFTLINE,
|
|
@@ -227,6 +228,14 @@ class Expressions(Core):
|
|
|
227
228
|
if value.verbatim:
|
|
228
229
|
return False
|
|
229
230
|
kind = value.type
|
|
231
|
+
if kind in ("object_creation_expression", "implicit_object_creation_expression") and not self.block_like(value):
|
|
232
|
+
arguments = value.first_of("argument_list")
|
|
233
|
+
if arguments is not None and len(arguments.children) == 2:
|
|
234
|
+
opening, closing = arguments.children
|
|
235
|
+
if not opening.trailing and not closing.leading:
|
|
236
|
+
# An empty constructor cannot break internally; move the
|
|
237
|
+
# whole value after the assignment operator when needed.
|
|
238
|
+
return False
|
|
230
239
|
if kind in _SELF_BREAKING:
|
|
231
240
|
return True
|
|
232
241
|
if kind == "await_expression":
|
|
@@ -460,7 +469,31 @@ class Expressions(Core):
|
|
|
460
469
|
close_tok = node.children[-1]
|
|
461
470
|
items, commas = self.items_and_commas(node)
|
|
462
471
|
if not items:
|
|
472
|
+
if not open_tok.trailing and not close_tok.leading:
|
|
473
|
+
return [self.tok(open_tok), self.tok(close_tok)]
|
|
463
474
|
return group([self.tok(open_tok), self.closing(close_tok, SOFTLINE)])
|
|
475
|
+
if (
|
|
476
|
+
node.type == "argument_list" and self.settings.lambda_body == "hug"
|
|
477
|
+
and self.settings.argument_wrap == "one_per_line" and len(items) == 1 and len(items[0]) == 1
|
|
478
|
+
):
|
|
479
|
+
argument = items[0][0]
|
|
480
|
+
target = argument.children[-1] if argument.type == "argument" and len(argument.children) == 1 else argument
|
|
481
|
+
if target.type == "tuple_expression" and not target.verbatim:
|
|
482
|
+
tuple_items, tuple_commas = self.items_and_commas(target)
|
|
483
|
+
last = tuple_items[-1][0] if tuple_items and len(tuple_items[-1]) == 1 else None
|
|
484
|
+
value = last.children[-1] if last is not None and last.type == "argument" and last.children else last
|
|
485
|
+
body = value.child("body") if value is not None and value.type == "lambda_expression" else None
|
|
486
|
+
if (
|
|
487
|
+
body is not None and body.type == "block" and self._can_hug(tuple_items)
|
|
488
|
+
and (len(body.children) > 2 or any(t.leading or t.trailing for t in body.tokens()))
|
|
489
|
+
):
|
|
490
|
+
# Keep the tuple's lambda with the call header, but close
|
|
491
|
+
# both parentheses at the call's indentation after its body.
|
|
492
|
+
tuple_docs = self._comma_docs(tuple_items, tuple_commas)
|
|
493
|
+
return [
|
|
494
|
+
self.tok(open_tok), indent([self.tok(target.children[0]), join(" ", tuple_docs)]),
|
|
495
|
+
self.closing(target.children[-1], HARDLINE), self.closing(close_tok, ""),
|
|
496
|
+
]
|
|
464
497
|
docs = [self.print_item(item) for item in items]
|
|
465
498
|
for i, comma in enumerate(commas):
|
|
466
499
|
if i < len(docs):
|
|
@@ -678,7 +711,10 @@ class Expressions(Core):
|
|
|
678
711
|
return group([self.tok(open_tok), indent([SOFTLINE, body]), self.closing(close_tok, SOFTLINE)])
|
|
679
712
|
force = self._forced_initializer([[_element_value(i[0])] for i in items if len(i) == 1])
|
|
680
713
|
return group(
|
|
681
|
-
[
|
|
714
|
+
[
|
|
715
|
+
IfBreak(ENSURE_LINE, ""), self.tok(open_tok),
|
|
716
|
+
indent([SOFTLINE, join(LINE, docs)]), self.closing(close_tok, SOFTLINE),
|
|
717
|
+
],
|
|
682
718
|
should_break=force,
|
|
683
719
|
)
|
|
684
720
|
|
|
@@ -870,8 +906,16 @@ class Expressions(Core):
|
|
|
870
906
|
def p_is_expression(self, node: Node) -> Doc:
|
|
871
907
|
return self.spaced(node.children)
|
|
872
908
|
|
|
873
|
-
def p_is_pattern_expression(self, node: Node) -> Doc:
|
|
874
|
-
|
|
909
|
+
def p_is_pattern_expression(self, node: Node, *, in_condition: bool = False) -> Doc:
|
|
910
|
+
pattern = node.child("pattern")
|
|
911
|
+
if not in_condition or pattern is None or pattern.verbatim or pattern.type not in (
|
|
912
|
+
"and_pattern", "or_pattern", "negated_pattern"
|
|
913
|
+
):
|
|
914
|
+
return self.spaced(node.children)
|
|
915
|
+
return join(" ", [
|
|
916
|
+
self.logical_pattern(child, group_result=False) if child is pattern else self.print(child)
|
|
917
|
+
for child in node.children
|
|
918
|
+
])
|
|
875
919
|
|
|
876
920
|
def p_range_expression(self, node: Node) -> Doc:
|
|
877
921
|
return self.join_tokens([(c, self.print(c)) for c in node.children])
|
|
@@ -941,13 +985,49 @@ class Expressions(Core):
|
|
|
941
985
|
return self.spaced(node.children)
|
|
942
986
|
|
|
943
987
|
def p_and_pattern(self, node: Node) -> Doc:
|
|
944
|
-
return self.
|
|
988
|
+
return self.logical_pattern(node)
|
|
945
989
|
|
|
946
990
|
def p_or_pattern(self, node: Node) -> Doc:
|
|
947
|
-
return self.
|
|
991
|
+
return self.logical_pattern(node)
|
|
948
992
|
|
|
949
993
|
def p_negated_pattern(self, node: Node) -> Doc:
|
|
950
|
-
return self.
|
|
994
|
+
return self.logical_pattern(node)
|
|
995
|
+
|
|
996
|
+
def logical_pattern(self, node: Node, *, group_result: bool = True) -> Doc:
|
|
997
|
+
# The grammar nests `not A and not B` under successive negations,
|
|
998
|
+
# sometimes including trailing &&/|| expressions in constant patterns.
|
|
999
|
+
# Share a continuation level without moving any tokens or parentheses.
|
|
1000
|
+
segments: list[list[Node]] = [[]]
|
|
1001
|
+
operators: list[Node] = []
|
|
1002
|
+
stack = [node]
|
|
1003
|
+
while stack:
|
|
1004
|
+
current = stack.pop()
|
|
1005
|
+
if current.type == "constant_pattern" and len(current.children) == 1 and not current.verbatim:
|
|
1006
|
+
value = current.children[0]
|
|
1007
|
+
value_op = value.child("operator")
|
|
1008
|
+
if value.type == "binary_expression" and value_op is not None and value_op.text in ("&&", "||"):
|
|
1009
|
+
stack.append(value)
|
|
1010
|
+
continue
|
|
1011
|
+
op = current.child("operator")
|
|
1012
|
+
logical = current.type in ("and_pattern", "or_pattern", "negated_pattern") or (
|
|
1013
|
+
current.type == "binary_expression" and op is not None and op.text in ("&&", "||")
|
|
1014
|
+
)
|
|
1015
|
+
if logical and not current.verbatim:
|
|
1016
|
+
stack.extend(reversed(current.children))
|
|
1017
|
+
elif not current.named and current.text in ("and", "or", "&&", "||"):
|
|
1018
|
+
operators.append(current)
|
|
1019
|
+
segments.append([])
|
|
1020
|
+
else:
|
|
1021
|
+
segments[-1].append(current)
|
|
1022
|
+
first = self.spaced(segments[0])
|
|
1023
|
+
rest: list[Doc] = []
|
|
1024
|
+
for operator, segment in zip(operators, segments[1:], strict=True):
|
|
1025
|
+
if self.settings.binary_wrap == "after_operator":
|
|
1026
|
+
rest.append([" ", self.tok(operator), LINE, self.spaced(segment)])
|
|
1027
|
+
else:
|
|
1028
|
+
rest.append([LINE, self.tok(operator), " ", self.spaced(segment)])
|
|
1029
|
+
contents: Doc = [first, indent(rest)]
|
|
1030
|
+
return group(contents) if group_result else contents
|
|
951
1031
|
|
|
952
1032
|
def p_declaration_pattern(self, node: Node) -> Doc:
|
|
953
1033
|
return self.spaced(node.children)
|
|
@@ -144,13 +144,18 @@ class Statements(Expressions):
|
|
|
144
144
|
def condition(self, open_tok: Node, condition: Node, close_tok: Node) -> Doc:
|
|
145
145
|
if (
|
|
146
146
|
self.settings.binary_wrap == "before_operator_paren_own_line"
|
|
147
|
-
and condition.type == "binary_expression"
|
|
148
147
|
and not condition.verbatim
|
|
149
148
|
):
|
|
149
|
+
if condition.type == "binary_expression":
|
|
150
|
+
contents = self.binary(condition, in_condition=True)
|
|
151
|
+
elif condition.type == "is_pattern_expression":
|
|
152
|
+
contents = self.p_is_pattern_expression(condition, in_condition=True)
|
|
153
|
+
else:
|
|
154
|
+
contents = self.print(condition)
|
|
150
155
|
return group(
|
|
151
156
|
[
|
|
152
157
|
self.tok(open_tok),
|
|
153
|
-
indent([SOFTLINE,
|
|
158
|
+
indent([SOFTLINE, contents]),
|
|
154
159
|
SOFTLINE,
|
|
155
160
|
self.tok(close_tok),
|
|
156
161
|
]
|
|
@@ -113,8 +113,67 @@ def test_catch_filter_wraps_logical_pattern_before_expanding_property_pattern()
|
|
|
113
113
|
'try { Run(); } catch (Exception error) when (error is ObjectDisposedException or SocketException '
|
|
114
114
|
'or ArgumentException { ParamName: "socketAddress" }) { Stop(); }',
|
|
115
115
|
'try\n{\n Run();\n}\n\n'
|
|
116
|
-
'catch (Exception error) when (error is ObjectDisposedException\n'
|
|
117
|
-
'
|
|
116
|
+
'catch (Exception error) when (\n error is ObjectDisposedException\n'
|
|
117
|
+
' or SocketException\n or ArgumentException { ParamName: "socketAddress" }\n)\n{\n Stop();\n}\n',
|
|
118
|
+
)
|
|
119
|
+
|
|
120
|
+
|
|
121
|
+
def test_broken_pattern_catch_filter_puts_parentheses_on_own_lines() -> None:
|
|
122
|
+
check(
|
|
123
|
+
'try { Run(); } catch (Exception error) when '
|
|
124
|
+
'(error is SocketException or ObjectDisposedException or OperationCanceledException) { }',
|
|
125
|
+
'try\n{\n Run();\n}\n\ncatch (Exception error) when (\n'
|
|
126
|
+
' error is SocketException\n or ObjectDisposedException\n'
|
|
127
|
+
' or OperationCanceledException\n)\n{ }\n',
|
|
128
|
+
max_line_length=90,
|
|
129
|
+
)
|
|
130
|
+
|
|
131
|
+
|
|
132
|
+
@pytest.mark.parametrize("keyword", ["if", "while"])
|
|
133
|
+
def test_broken_pattern_conditions_share_catch_filter_layout(keyword: str) -> None:
|
|
134
|
+
check(
|
|
135
|
+
f'{keyword} (error is SocketException or ObjectDisposedException or OperationCanceledException) {{ Stop(); }}',
|
|
136
|
+
f'{keyword} (\n error is SocketException\n or ObjectDisposedException\n'
|
|
137
|
+
' or OperationCanceledException\n)\n{\n Stop();\n}\n',
|
|
138
|
+
max_line_length=65,
|
|
139
|
+
)
|
|
140
|
+
|
|
141
|
+
|
|
142
|
+
def test_broken_pattern_do_while_condition_has_own_parenthesis_lines() -> None:
|
|
143
|
+
check(
|
|
144
|
+
'do { Run(); } while (error is SocketException or ObjectDisposedException or OperationCanceledException);',
|
|
145
|
+
'do\n{\n Run();\n}\n\nwhile (\n error is SocketException\n'
|
|
146
|
+
' or ObjectDisposedException\n or OperationCanceledException\n);\n',
|
|
147
|
+
max_line_length=65,
|
|
148
|
+
)
|
|
149
|
+
|
|
150
|
+
|
|
151
|
+
@pytest.mark.parametrize("keyword", ["if", "while"])
|
|
152
|
+
def test_short_pattern_condition_stays_inline(keyword: str) -> None:
|
|
153
|
+
check(f'{keyword} (x is A or B) {{ Run(); }}', f'{keyword} (x is A or B)\n{{\n Run();\n}}\n')
|
|
154
|
+
|
|
155
|
+
|
|
156
|
+
@pytest.mark.parametrize("keyword", ["if", "while"])
|
|
157
|
+
def test_multiline_predicate_condition_uses_own_parenthesis_lines(keyword: str) -> None:
|
|
158
|
+
check(
|
|
159
|
+
f'{keyword} (Predicate(veryLongArgumentName, anotherLongArgumentName)) {{ Run(); }}',
|
|
160
|
+
f'{keyword} (\n Predicate(\n veryLongArgumentName,\n'
|
|
161
|
+
' anotherLongArgumentName\n )\n)\n{\n Run();\n}\n',
|
|
162
|
+
max_line_length=50,
|
|
163
|
+
)
|
|
164
|
+
|
|
165
|
+
|
|
166
|
+
@pytest.mark.parametrize("wrap", ["before_operator", "after_operator"])
|
|
167
|
+
def test_pattern_conditions_respect_alternative_parenthesis_layout(wrap: str) -> None:
|
|
168
|
+
if wrap == "after_operator":
|
|
169
|
+
pattern = 'error is SocketException or\n ObjectDisposedException or\n OperationCanceledException'
|
|
170
|
+
else:
|
|
171
|
+
pattern = 'error is SocketException\n or ObjectDisposedException\n or OperationCanceledException'
|
|
172
|
+
check(
|
|
173
|
+
'if (error is SocketException or ObjectDisposedException or OperationCanceledException) { Run(); }',
|
|
174
|
+
f'if ({pattern})\n{{\n Run();\n}}\n',
|
|
175
|
+
max_line_length=65,
|
|
176
|
+
binary_wrap=wrap,
|
|
118
177
|
)
|
|
119
178
|
|
|
120
179
|
|
|
@@ -154,6 +213,16 @@ def test_short_logical_patterns_keep_grouping_and_stay_inline(pattern: str) -> N
|
|
|
154
213
|
check(f"var ok=value is {pattern};", f"var ok = value is {pattern};\n")
|
|
155
214
|
|
|
156
215
|
|
|
216
|
+
def test_negated_pattern_chain_and_boolean_tail_share_one_indent() -> None:
|
|
217
|
+
check(
|
|
218
|
+
"var persistent = _status is not 400 and not 408 and not 411 and not 413 and not 414 "
|
|
219
|
+
"and not 500 and not 503 && !_transport.IsDraining && KeepAlive;",
|
|
220
|
+
"var persistent = _status is not 400\n"
|
|
221
|
+
" and not 408\n and not 411\n and not 413\n and not 414\n"
|
|
222
|
+
" and not 500\n and not 503\n && !_transport.IsDraining\n && KeepAlive;\n",
|
|
223
|
+
)
|
|
224
|
+
|
|
225
|
+
|
|
157
226
|
def test_call_breaks_one_argument_per_line_with_paren_on_its_own_line() -> None:
|
|
158
227
|
check(
|
|
159
228
|
"""
|
|
@@ -827,6 +896,30 @@ def test_empty_collection_moves_to_the_next_line_whole() -> None:
|
|
|
827
896
|
)
|
|
828
897
|
|
|
829
898
|
|
|
899
|
+
def test_long_empty_constructor_keeps_parentheses_together() -> None:
|
|
900
|
+
check(
|
|
901
|
+
'private readonly ConcurrentDictionary<IPAddress, ConcurrentBag<long>> _failRegexMatches = '
|
|
902
|
+
'new ConcurrentDictionary<IPAddress, ConcurrentBag<long>>();',
|
|
903
|
+
'private readonly ConcurrentDictionary<IPAddress, ConcurrentBag<long>> _failRegexMatches =\n'
|
|
904
|
+
' new ConcurrentDictionary<IPAddress, ConcurrentBag<long>>();\n',
|
|
905
|
+
)
|
|
906
|
+
|
|
907
|
+
|
|
908
|
+
@pytest.mark.parametrize("wrap", ["one_per_line", "one_per_line_close_on_last", "fill", "align"])
|
|
909
|
+
def test_empty_call_parentheses_never_split(wrap: str) -> None:
|
|
910
|
+
check(
|
|
911
|
+
'SomeVeryLongMethodName();', 'SomeVeryLongMethodName();\n',
|
|
912
|
+
max_line_length=12, argument_wrap=wrap,
|
|
913
|
+
)
|
|
914
|
+
|
|
915
|
+
|
|
916
|
+
def test_comments_inside_empty_constructor_are_preserved() -> None:
|
|
917
|
+
source = 'var instance = new Item( // Keep this note.\n);'
|
|
918
|
+
output = fmt(source)
|
|
919
|
+
assert '// Keep this note.\n' in output
|
|
920
|
+
assert fmt(output) == output
|
|
921
|
+
|
|
922
|
+
|
|
830
923
|
def test_spread_elements_are_spaced_and_ranges_are_not() -> None:
|
|
831
924
|
assert fmt("x = [..entries, 1, ..more];\n") == "x = [.. entries, 1, .. more];\n"
|
|
832
925
|
assert fmt("var r = entries[1..] + entries[..2] + entries[..];\n") == (
|
|
@@ -834,6 +927,50 @@ def test_spread_elements_are_spaced_and_ranges_are_not() -> None:
|
|
|
834
927
|
)
|
|
835
928
|
|
|
836
929
|
|
|
930
|
+
@pytest.mark.parametrize("element", ['new HpackField(wire, "")', "GetField()", "wire.Length + 1", "wire"])
|
|
931
|
+
@pytest.mark.parametrize("simple_inline", [True, False])
|
|
932
|
+
def test_inline_collection_brackets_stay_tight(element: str, simple_inline: bool) -> None:
|
|
933
|
+
check(
|
|
934
|
+
f"Validate([ {element} ]);",
|
|
935
|
+
f"Validate([{element}]);\n",
|
|
936
|
+
simple_lists_inline=simple_inline,
|
|
937
|
+
)
|
|
938
|
+
|
|
939
|
+
|
|
940
|
+
def test_collection_brackets_in_awaited_send_stay_tight() -> None:
|
|
941
|
+
check(
|
|
942
|
+
'await SendAsync([ new Http2Frame(6, 1, 0, frame.Payload) ], token).ConfigureAwait(false);',
|
|
943
|
+
'await SendAsync([new Http2Frame(6, 1, 0, frame.Payload)], token).ConfigureAwait(false);\n',
|
|
944
|
+
)
|
|
945
|
+
|
|
946
|
+
|
|
947
|
+
def test_multiline_collection_argument_has_no_extra_blank_line() -> None:
|
|
948
|
+
check(
|
|
949
|
+
'await SendHeadersAsync([new HpackField(":status", "200"), '
|
|
950
|
+
'new HpackField("content-length", bytes.Length.ToString(CultureInfo.InvariantCulture))], '
|
|
951
|
+
'bytes.Length == 0 || Request.Method == "HEAD", token).ConfigureAwait(false);',
|
|
952
|
+
'await SendHeadersAsync(\n'
|
|
953
|
+
' [\n'
|
|
954
|
+
' new HpackField(":status", "200"),\n'
|
|
955
|
+
' new HpackField("content-length", bytes.Length.ToString(CultureInfo.InvariantCulture))\n'
|
|
956
|
+
' ],\n'
|
|
957
|
+
' bytes.Length == 0 || Request.Method == "HEAD",\n'
|
|
958
|
+
' token\n'
|
|
959
|
+
').ConfigureAwait(false);\n',
|
|
960
|
+
)
|
|
961
|
+
|
|
962
|
+
|
|
963
|
+
def test_spread_of_call_in_multiline_arguments_keeps_brackets_tight() -> None:
|
|
964
|
+
check(
|
|
965
|
+
'_session = Session.Start([ .. _prefixes.Select(value => new ListenerPrefix(value)) ], '
|
|
966
|
+
'_certificates, TlsPolicy, _native, DeferContinue, Telemetry, _bodyPolicy, _dispatcher);',
|
|
967
|
+
'_session = Session.Start(\n'
|
|
968
|
+
' [.. _prefixes.Select(value => new ListenerPrefix(value))],\n'
|
|
969
|
+
' _certificates,\n TlsPolicy,\n _native,\n DeferContinue,\n'
|
|
970
|
+
' Telemetry,\n _bodyPolicy,\n _dispatcher\n);\n',
|
|
971
|
+
)
|
|
972
|
+
|
|
973
|
+
|
|
837
974
|
def test_empty_body_after_a_header_that_spans_lines_gets_its_own_line() -> None:
|
|
838
975
|
# Visual Studio (IDE0055) keeps `{ }` on the header's line only when the
|
|
839
976
|
# header is one line.
|
|
@@ -901,9 +1038,9 @@ def test_empty_catch_and_lambda_bodies_after_a_header_that_spans_lines() -> None
|
|
|
901
1038
|
try { }
|
|
902
1039
|
|
|
903
1040
|
// Ignored.
|
|
904
|
-
catch (Exception error) when (
|
|
905
|
-
error
|
|
906
|
-
)
|
|
1041
|
+
catch (Exception error) when (
|
|
1042
|
+
IsRecoverable(error)
|
|
1043
|
+
)
|
|
907
1044
|
{ }
|
|
908
1045
|
|
|
909
1046
|
Run((
|
|
@@ -967,6 +1104,26 @@ def test_auto_properties_and_empty_bodies_stay_on_one_line() -> None:
|
|
|
967
1104
|
)
|
|
968
1105
|
|
|
969
1106
|
|
|
1107
|
+
def test_tuple_block_lambda_closes_parentheses_on_the_call_line_indent() -> None:
|
|
1108
|
+
check(
|
|
1109
|
+
'_dataHandlerPairs.Add((data, (ctx, route) => { handler(ctx, route); return Task.CompletedTask; }));',
|
|
1110
|
+
'_dataHandlerPairs.Add((data, (ctx, route) =>\n'
|
|
1111
|
+
' {\n handler(ctx, route);\n return Task.CompletedTask;\n }\n));\n',
|
|
1112
|
+
)
|
|
1113
|
+
|
|
1114
|
+
|
|
1115
|
+
def test_ordinary_block_lambda_argument_keeps_hugged_parenthesis() -> None:
|
|
1116
|
+
check(
|
|
1117
|
+
'Run(data, (ctx, route) => { handler(ctx, route); return Task.CompletedTask; });',
|
|
1118
|
+
'Run(data, (ctx, route) =>\n'
|
|
1119
|
+
'{\n handler(ctx, route);\n return Task.CompletedTask;\n});\n',
|
|
1120
|
+
)
|
|
1121
|
+
|
|
1122
|
+
|
|
1123
|
+
def test_empty_tuple_lambda_stays_inline() -> None:
|
|
1124
|
+
check('Run((data, () => { }));', 'Run((data, () => { }));\n')
|
|
1125
|
+
|
|
1126
|
+
|
|
970
1127
|
def test_object_initializer_hugs_the_last_argument() -> None:
|
|
971
1128
|
check(
|
|
972
1129
|
"""
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{prettycsharp-1.1.8 → prettycsharp-1.1.10}/tests/fuzz_corpus/csharp/comment_only_accessor_list.cs
RENAMED
|
File without changes
|
{prettycsharp-1.1.8 → prettycsharp-1.1.10}/tests/fuzz_corpus/csharp/conditional_assignments.cs
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{prettycsharp-1.1.8 → prettycsharp-1.1.10}/tests/fuzz_corpus/csharp/split_by_conditionals.cs
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|