prettycsharp 1.1.5__tar.gz → 1.1.7__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.
Files changed (90) hide show
  1. {prettycsharp-1.1.5 → prettycsharp-1.1.7}/CHANGELOG.md +12 -0
  2. {prettycsharp-1.1.5 → prettycsharp-1.1.7}/DESIGN.md +7 -0
  3. {prettycsharp-1.1.5 → prettycsharp-1.1.7}/PKG-INFO +1 -1
  4. {prettycsharp-1.1.5 → prettycsharp-1.1.7}/src/prettycsharp/__init__.py +1 -1
  5. {prettycsharp-1.1.5 → prettycsharp-1.1.7}/src/prettycsharp/printer/statements.py +16 -5
  6. {prettycsharp-1.1.5 → prettycsharp-1.1.7}/tests/test_layout.py +45 -0
  7. {prettycsharp-1.1.5 → prettycsharp-1.1.7}/.gitattributes +0 -0
  8. {prettycsharp-1.1.5 → prettycsharp-1.1.7}/.github/codeql/codeql-config.yml +0 -0
  9. {prettycsharp-1.1.5 → prettycsharp-1.1.7}/.github/dependabot.yml +0 -0
  10. {prettycsharp-1.1.5 → prettycsharp-1.1.7}/.github/requirements/build.in +0 -0
  11. {prettycsharp-1.1.5 → prettycsharp-1.1.7}/.github/requirements/build.txt +0 -0
  12. {prettycsharp-1.1.5 → prettycsharp-1.1.7}/.github/requirements/fuzz.in +0 -0
  13. {prettycsharp-1.1.5 → prettycsharp-1.1.7}/.github/requirements/fuzz.txt +0 -0
  14. {prettycsharp-1.1.5 → prettycsharp-1.1.7}/.github/requirements/pip-audit.in +0 -0
  15. {prettycsharp-1.1.5 → prettycsharp-1.1.7}/.github/requirements/pip-audit.txt +0 -0
  16. {prettycsharp-1.1.5 → prettycsharp-1.1.7}/.github/requirements/runtime.in +0 -0
  17. {prettycsharp-1.1.5 → prettycsharp-1.1.7}/.github/requirements/runtime.txt +0 -0
  18. {prettycsharp-1.1.5 → prettycsharp-1.1.7}/.github/requirements/test.in +0 -0
  19. {prettycsharp-1.1.5 → prettycsharp-1.1.7}/.github/requirements/test.txt +0 -0
  20. {prettycsharp-1.1.5 → prettycsharp-1.1.7}/.github/requirements/zizmor.in +0 -0
  21. {prettycsharp-1.1.5 → prettycsharp-1.1.7}/.github/requirements/zizmor.txt +0 -0
  22. {prettycsharp-1.1.5 → prettycsharp-1.1.7}/.github/security/accepted.toml +0 -0
  23. {prettycsharp-1.1.5 → prettycsharp-1.1.7}/.github/security/clamav/Dockerfile +0 -0
  24. {prettycsharp-1.1.5 → prettycsharp-1.1.7}/.github/security/malware-accepted.toml +0 -0
  25. {prettycsharp-1.1.5 → prettycsharp-1.1.7}/.github/security/semgrep/Dockerfile +0 -0
  26. {prettycsharp-1.1.5 → prettycsharp-1.1.7}/.github/security/yara.json +0 -0
  27. {prettycsharp-1.1.5 → prettycsharp-1.1.7}/.github/security/yara_update.py +0 -0
  28. {prettycsharp-1.1.5 → prettycsharp-1.1.7}/.github/workflows/auto-merge.yml +0 -0
  29. {prettycsharp-1.1.5 → prettycsharp-1.1.7}/.github/workflows/ci.yml +0 -0
  30. {prettycsharp-1.1.5 → prettycsharp-1.1.7}/.github/workflows/fuzz.yml +0 -0
  31. {prettycsharp-1.1.5 → prettycsharp-1.1.7}/.github/workflows/malware-scan.yml +0 -0
  32. {prettycsharp-1.1.5 → prettycsharp-1.1.7}/.github/workflows/publish.yml +0 -0
  33. {prettycsharp-1.1.5 → prettycsharp-1.1.7}/.github/workflows/scorecard.yml +0 -0
  34. {prettycsharp-1.1.5 → prettycsharp-1.1.7}/.github/workflows/security.yml +0 -0
  35. {prettycsharp-1.1.5 → prettycsharp-1.1.7}/.github/workflows/update-yara-rules.yml +0 -0
  36. {prettycsharp-1.1.5 → prettycsharp-1.1.7}/.github/zizmor.yml +0 -0
  37. {prettycsharp-1.1.5 → prettycsharp-1.1.7}/.gitignore +0 -0
  38. {prettycsharp-1.1.5 → prettycsharp-1.1.7}/AGENTS.md +0 -0
  39. {prettycsharp-1.1.5 → prettycsharp-1.1.7}/CLAUDE.md +0 -0
  40. {prettycsharp-1.1.5 → prettycsharp-1.1.7}/LICENSE +0 -0
  41. {prettycsharp-1.1.5 → prettycsharp-1.1.7}/README.md +0 -0
  42. {prettycsharp-1.1.5 → prettycsharp-1.1.7}/SECURITY.md +0 -0
  43. {prettycsharp-1.1.5 → prettycsharp-1.1.7}/fuzz/fuzz_formatter.py +0 -0
  44. {prettycsharp-1.1.5 → prettycsharp-1.1.7}/pyproject.toml +0 -0
  45. {prettycsharp-1.1.5 → prettycsharp-1.1.7}/scripts/security/malware_report.py +0 -0
  46. {prettycsharp-1.1.5 → prettycsharp-1.1.7}/scripts/security/security_report.py +0 -0
  47. {prettycsharp-1.1.5 → prettycsharp-1.1.7}/src/prettycsharp/__main__.py +0 -0
  48. {prettycsharp-1.1.5 → prettycsharp-1.1.7}/src/prettycsharp/cli.py +0 -0
  49. {prettycsharp-1.1.5 → prettycsharp-1.1.7}/src/prettycsharp/conditional.py +0 -0
  50. {prettycsharp-1.1.5 → prettycsharp-1.1.7}/src/prettycsharp/config.py +0 -0
  51. {prettycsharp-1.1.5 → prettycsharp-1.1.7}/src/prettycsharp/doc.py +0 -0
  52. {prettycsharp-1.1.5 → prettycsharp-1.1.7}/src/prettycsharp/formatter.py +0 -0
  53. {prettycsharp-1.1.5 → prettycsharp-1.1.7}/src/prettycsharp/ignore.py +0 -0
  54. {prettycsharp-1.1.5 → prettycsharp-1.1.7}/src/prettycsharp/isolate.py +0 -0
  55. {prettycsharp-1.1.5 → prettycsharp-1.1.7}/src/prettycsharp/parsing.py +0 -0
  56. {prettycsharp-1.1.5 → prettycsharp-1.1.7}/src/prettycsharp/printer/__init__.py +0 -0
  57. {prettycsharp-1.1.5 → prettycsharp-1.1.7}/src/prettycsharp/printer/core.py +0 -0
  58. {prettycsharp-1.1.5 → prettycsharp-1.1.7}/src/prettycsharp/printer/declarations.py +0 -0
  59. {prettycsharp-1.1.5 → prettycsharp-1.1.7}/src/prettycsharp/printer/expressions.py +0 -0
  60. {prettycsharp-1.1.5 → prettycsharp-1.1.7}/src/prettycsharp/project.py +0 -0
  61. {prettycsharp-1.1.5 → prettycsharp-1.1.7}/src/prettycsharp/py.typed +0 -0
  62. {prettycsharp-1.1.5 → prettycsharp-1.1.7}/src/prettycsharp/rewrites.py +0 -0
  63. {prettycsharp-1.1.5 → prettycsharp-1.1.7}/src/prettycsharp/settings.py +0 -0
  64. {prettycsharp-1.1.5 → prettycsharp-1.1.7}/src/prettycsharp/syntax.py +0 -0
  65. {prettycsharp-1.1.5 → prettycsharp-1.1.7}/src/prettycsharp/verify.py +0 -0
  66. {prettycsharp-1.1.5 → prettycsharp-1.1.7}/tests/fuzz_corpus/csharp/comment_only_accessor_list.cs +0 -0
  67. {prettycsharp-1.1.5 → prettycsharp-1.1.7}/tests/fuzz_corpus/csharp/declarations.cs +0 -0
  68. {prettycsharp-1.1.5 → prettycsharp-1.1.7}/tests/fuzz_corpus/csharp/directives.cs +0 -0
  69. {prettycsharp-1.1.5 → prettycsharp-1.1.7}/tests/fuzz_corpus/csharp/embedded_statements.cs +0 -0
  70. {prettycsharp-1.1.5 → prettycsharp-1.1.7}/tests/fuzz_corpus/csharp/expressions.cs +0 -0
  71. {prettycsharp-1.1.5 → prettycsharp-1.1.7}/tests/fuzz_corpus/csharp/members.cs +0 -0
  72. {prettycsharp-1.1.5 → prettycsharp-1.1.7}/tests/fuzz_corpus/csharp/order.cs +0 -0
  73. {prettycsharp-1.1.5 → prettycsharp-1.1.7}/tests/fuzz_corpus/csharp/queries_and_patterns.cs +0 -0
  74. {prettycsharp-1.1.5 → prettycsharp-1.1.7}/tests/fuzz_corpus/csharp/split_by_conditionals.cs +0 -0
  75. {prettycsharp-1.1.5 → prettycsharp-1.1.7}/tests/fuzz_corpus/csharp/statements.cs +0 -0
  76. {prettycsharp-1.1.5 → prettycsharp-1.1.7}/tests/fuzz_corpus/csharp/strings.cs +0 -0
  77. {prettycsharp-1.1.5 → prettycsharp-1.1.7}/tests/support.py +0 -0
  78. {prettycsharp-1.1.5 → prettycsharp-1.1.7}/tests/test_cli.py +0 -0
  79. {prettycsharp-1.1.5 → prettycsharp-1.1.7}/tests/test_conditional.py +0 -0
  80. {prettycsharp-1.1.5 → prettycsharp-1.1.7}/tests/test_config.py +0 -0
  81. {prettycsharp-1.1.5 → prettycsharp-1.1.7}/tests/test_doc.py +0 -0
  82. {prettycsharp-1.1.5 → prettycsharp-1.1.7}/tests/test_docs.py +0 -0
  83. {prettycsharp-1.1.5 → prettycsharp-1.1.7}/tests/test_format_around.py +0 -0
  84. {prettycsharp-1.1.5 → prettycsharp-1.1.7}/tests/test_fuzz_corpus.py +0 -0
  85. {prettycsharp-1.1.5 → prettycsharp-1.1.7}/tests/test_ignore.py +0 -0
  86. {prettycsharp-1.1.5 → prettycsharp-1.1.7}/tests/test_parsing.py +0 -0
  87. {prettycsharp-1.1.5 → prettycsharp-1.1.7}/tests/test_project.py +0 -0
  88. {prettycsharp-1.1.5 → prettycsharp-1.1.7}/tests/test_rewrites.py +0 -0
  89. {prettycsharp-1.1.5 → prettycsharp-1.1.7}/tests/test_settings.py +0 -0
  90. {prettycsharp-1.1.5 → prettycsharp-1.1.7}/tests/test_verify.py +0 -0
@@ -2,6 +2,18 @@
2
2
 
3
3
  Each release's section becomes the body of its GitHub release.
4
4
 
5
+ ## [1.1.7] - 2026-10-18
6
+
7
+ - Comments after the final `switch` section align with its statements
8
+ instead of its case label, avoiding Visual Studio's IDE0055 formatting
9
+ diagnostic. Switches containing only comments keep one indentation level.
10
+
11
+ ## [1.1.6] - 2026-10-18
12
+
13
+ - `for` headers keep a space between semicolons when the condition is
14
+ omitted, such as `for (var start = 0; ;)`, avoiding Visual Studio's
15
+ IDE0055 formatting diagnostic. Fully empty headers print `for (; ; )`.
16
+
5
17
  ## [1.1.5] - 2026-10-18
6
18
 
7
19
  - Nullable array types print tight, `object?[]?`, instead of
@@ -161,6 +161,10 @@ public void Ship()
161
161
 
162
162
  ### Line breaking
163
163
 
164
+ `for` headers keep a space after each semicolon even when the next clause
165
+ is omitted: `for (var i = 0; ;)`. There is no space before the closing
166
+ parenthesis unless all three clauses are empty: `for (; ; )`.
167
+
164
168
  | Setting | Default | Alternatives |
165
169
  | --- | --- | --- |
166
170
  | `argument_wrap` | `one_per_line`: each argument on its own line, `)` on its own line. Also applies to parameter lists. | `one_per_line_close_on_last`, `fill`, `align` |
@@ -269,6 +273,9 @@ public enum Status
269
273
  | `switch_case_indent` | `true` | `false` |
270
274
  | `switch_case_blank_lines` | `true`: blank line between case sections; stacked fall-through labels stay together | `false` |
271
275
 
276
+ Comments after the final switch section align with its statements. A switch
277
+ containing only comments indents them one level inside its braces.
278
+
272
279
  ### Syntax rewrites
273
280
 
274
281
  These change tokens, not only whitespace. Verification accounts for each one.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: prettycsharp
3
- Version: 1.1.5
3
+ Version: 1.1.7
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.5"
7
+ __version__ = "1.1.7"
8
8
 
9
9
  __all__ = [
10
10
  "CSharpSyntaxError",
@@ -227,18 +227,25 @@ class Statements(Expressions):
227
227
  close_tok = node.children[close_index]
228
228
  body = node.children[close_index + 1] if close_index + 1 < len(node.children) else None
229
229
  open_index = node.children.index(open_tok)
230
+ header_children = node.children[open_index + 1 : close_index]
231
+ empty = not any(child.named for child in header_children)
230
232
  inner: list[Doc] = []
231
233
  pending_space = False
232
- for child in node.children[open_index + 1 : close_index]:
234
+ for child in header_children:
235
+ if pending_space:
236
+ inner.append(LINE)
233
237
  if child.text in (";", ",") and not child.named:
234
238
  inner.append(self.tok(child))
235
239
  pending_space = True
236
240
  continue
237
- if pending_space:
238
- inner.append(LINE)
239
241
  pending_space = False
240
242
  inner.append(self.print(child))
241
- header = group([self.tok(keyword), " ", self.tok(open_tok), indent([SOFTLINE, inner]), SOFTLINE, self.tok(close_tok)])
243
+ header = group(
244
+ [
245
+ self.tok(keyword), " ", self.tok(open_tok), indent([SOFTLINE, inner]),
246
+ LINE if empty else SOFTLINE, self.tok(close_tok),
247
+ ]
248
+ )
242
249
  if body is None:
243
250
  return header
244
251
  return [header, self.embedded(body, close_tok, node)]
@@ -320,7 +327,11 @@ class Statements(Expressions):
320
327
  lines = [HARDLINE, self.print_list(sections, self.section_blank)]
321
328
  # Case labels sit one level in, or flush with switch.
322
329
  body = indent(lines) if self.settings.switch_case_indent else lines
323
- return [self.tok(open_tok), body, self.close_comments(close_tok), HARDLINE, self.tok(close_tok, leading=False)]
330
+ comments = self.close_comments(close_tok)
331
+ # Trailing comments belong at the final section's statement level.
332
+ if self.settings.switch_case_indent and any(section.type == "switch_section" for section in sections):
333
+ comments = indent(comments)
334
+ return [self.tok(open_tok), body, comments, HARDLINE, self.tok(close_tok, leading=False)]
324
335
 
325
336
  def section_blank(self, previous: Node, item: Node) -> bool:
326
337
  if self.tight_directive(previous, item):
@@ -1,8 +1,30 @@
1
1
  """The default layout, one DESIGN.md decision per test."""
2
2
 
3
+ import pytest
4
+
3
5
  from support import check, fmt
4
6
 
5
7
 
8
+ @pytest.mark.parametrize(
9
+ ("source", "expected"),
10
+ [
11
+ (";;", "; ; "),
12
+ ("int i=0;;", "int i = 0; ;"),
13
+ (";i<10;", "; i < 10;"),
14
+ (";;i++", "; ; i++"),
15
+ ("int i=0;i<10;", "int i = 0; i < 10;"),
16
+ ("int i=0;;i++", "int i = 0; ; i++"),
17
+ (";i<10;i++", "; i < 10; i++"),
18
+ ("int i=0;i<10;i++", "int i = 0; i < 10; i++"),
19
+ ("int i=0,j=1;;i++,j--", "int i = 0, j = 1; ; i++, j--"),
20
+ ("var start=query[0]=='?'?1:0;;", "var start = query[0] == '?' ? 1 : 0; ;"),
21
+ ("int i=0;/* condition omitted */;", "int i = 0; /* condition omitted */ ;"),
22
+ ],
23
+ )
24
+ def test_for_header_spacing_with_omitted_clauses(source: str, expected: str) -> None:
25
+ check(f"for({source}){{break;}}", f"for ({expected})\n{{\n break;\n}}\n")
26
+
27
+
6
28
  def test_allman_braces_with_blank_line_before_continuations() -> None:
7
29
  check(
8
30
  """
@@ -539,6 +561,29 @@ def test_nothing_is_padded_into_columns() -> None:
539
561
  )
540
562
 
541
563
 
564
+ @pytest.mark.parametrize("case_indent", [True, False])
565
+ @pytest.mark.parametrize("comment", ["// Unknown settings are ignored.", "/* Unknown settings are ignored. */"])
566
+ @pytest.mark.parametrize("blank", ["", "\n"])
567
+ def test_trailing_switch_comment_aligns_with_statements(case_indent: bool, comment: str, blank: str) -> None:
568
+ label_indent = " " if case_indent else ""
569
+ statement_indent = label_indent + " "
570
+ check(
571
+ f"switch(x){{case 9:break;\n{blank}{comment}\n}}",
572
+ f"switch (x)\n{{\n{label_indent}case 9:\n{statement_indent}break;\n"
573
+ f"{blank}{statement_indent}{comment}\n}}\n",
574
+ switch_case_indent=case_indent,
575
+ )
576
+
577
+
578
+ @pytest.mark.parametrize("case_indent", [True, False])
579
+ def test_comment_only_switch_keeps_one_indent(case_indent: bool) -> None:
580
+ check(
581
+ "switch(x){\n// No cases yet.\n}",
582
+ "switch (x)\n{\n // No cases yet.\n}\n",
583
+ switch_case_indent=case_indent,
584
+ )
585
+
586
+
542
587
  def test_switch_expression_arms_align_when_turned_on() -> None:
543
588
  check(
544
589
  """
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes