prettycsharp 1.0.0__py3-none-any.whl
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/__init__.py +9 -0
- prettycsharp/__main__.py +5 -0
- prettycsharp/cli.py +250 -0
- prettycsharp/config.py +263 -0
- prettycsharp/doc.py +537 -0
- prettycsharp/formatter.py +106 -0
- prettycsharp/ignore.py +184 -0
- prettycsharp/parsing.py +53 -0
- prettycsharp/printer/__init__.py +28 -0
- prettycsharp/printer/core.py +540 -0
- prettycsharp/printer/declarations.py +623 -0
- prettycsharp/printer/expressions.py +1107 -0
- prettycsharp/printer/statements.py +603 -0
- prettycsharp/project.py +214 -0
- prettycsharp/py.typed +0 -0
- prettycsharp/rewrites.py +732 -0
- prettycsharp/settings.py +192 -0
- prettycsharp/syntax.py +367 -0
- prettycsharp/verify.py +312 -0
- prettycsharp-1.0.0.dist-info/METADATA +212 -0
- prettycsharp-1.0.0.dist-info/RECORD +24 -0
- prettycsharp-1.0.0.dist-info/WHEEL +4 -0
- prettycsharp-1.0.0.dist-info/entry_points.txt +2 -0
- prettycsharp-1.0.0.dist-info/licenses/LICENSE +21 -0
|
@@ -0,0 +1,623 @@
|
|
|
1
|
+
"""Declarations: the file, namespaces, types, members, attributes and directives."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from collections.abc import Sequence
|
|
6
|
+
|
|
7
|
+
from prettycsharp.doc import HARDLINE, LINE, SOFTLINE, TRIM_INDENT, Doc, group, indent, join
|
|
8
|
+
from prettycsharp.printer.core import split
|
|
9
|
+
from prettycsharp.printer.statements import Statements
|
|
10
|
+
from prettycsharp.rewrites import using_key
|
|
11
|
+
from prettycsharp.syntax import DIRECTIVE_TYPES, Node
|
|
12
|
+
|
|
13
|
+
TYPE_DECLARATIONS = frozenset(
|
|
14
|
+
{
|
|
15
|
+
"class_declaration",
|
|
16
|
+
"struct_declaration",
|
|
17
|
+
"interface_declaration",
|
|
18
|
+
"record_declaration",
|
|
19
|
+
"enum_declaration",
|
|
20
|
+
}
|
|
21
|
+
)
|
|
22
|
+
|
|
23
|
+
MEMBER_DECLARATIONS = frozenset(
|
|
24
|
+
{
|
|
25
|
+
"method_declaration",
|
|
26
|
+
"constructor_declaration",
|
|
27
|
+
"destructor_declaration",
|
|
28
|
+
"operator_declaration",
|
|
29
|
+
"conversion_operator_declaration",
|
|
30
|
+
"property_declaration",
|
|
31
|
+
"indexer_declaration",
|
|
32
|
+
"event_declaration",
|
|
33
|
+
"event_field_declaration",
|
|
34
|
+
"field_declaration",
|
|
35
|
+
"delegate_declaration",
|
|
36
|
+
"local_function_statement",
|
|
37
|
+
}
|
|
38
|
+
)
|
|
39
|
+
|
|
40
|
+
# Children printed after the header: what follows a member's signature.
|
|
41
|
+
_TAIL_FIELDS = ("body", "accessors")
|
|
42
|
+
_NO_SPACE_BEFORE = frozenset(
|
|
43
|
+
{"parameter_list", "bracketed_parameter_list", "type_parameter_list", "argument_list", "bracketed_argument_list"}
|
|
44
|
+
)
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
class Declarations(Statements):
|
|
48
|
+
# The file -------------------------------------------------------------
|
|
49
|
+
|
|
50
|
+
def p_compilation_unit(self, node: Node) -> Doc:
|
|
51
|
+
items = node.children
|
|
52
|
+
parts: list[Doc] = []
|
|
53
|
+
if items:
|
|
54
|
+
aligned = (
|
|
55
|
+
self.align_runs(items, self.assignment_split, self.top_blank) if self.settings.align_assignments else None
|
|
56
|
+
)
|
|
57
|
+
parts.append(self.print_list(items, self.top_blank, aligned=aligned))
|
|
58
|
+
trailing = self.file.trailing_comments
|
|
59
|
+
if trailing:
|
|
60
|
+
holder = Node(type="eof", text="")
|
|
61
|
+
holder.leading = list(trailing)
|
|
62
|
+
comments = self.leading_comments(holder, first_blank_allowed=False)
|
|
63
|
+
assert isinstance(comments, list)
|
|
64
|
+
while comments and comments[-1] is HARDLINE:
|
|
65
|
+
comments.pop()
|
|
66
|
+
if items:
|
|
67
|
+
parts.append(HARDLINE)
|
|
68
|
+
if trailing[0].newlines_before >= 2 and self.settings.max_blank_lines > 0:
|
|
69
|
+
parts.append(HARDLINE)
|
|
70
|
+
parts.append(comments)
|
|
71
|
+
return parts
|
|
72
|
+
|
|
73
|
+
def top_blank(self, previous: Node, item: Node) -> bool:
|
|
74
|
+
if previous.type == "file_scoped_namespace_declaration":
|
|
75
|
+
return self.settings.max_blank_lines > 0
|
|
76
|
+
if previous.type in DIRECTIVE_TYPES or item.type in DIRECTIVE_TYPES:
|
|
77
|
+
return self.directive_blank(previous, item)
|
|
78
|
+
if previous.type == item.type == "using_directive":
|
|
79
|
+
return self.using_blank(previous, item)
|
|
80
|
+
if previous.type == item.type and previous.type in ("extern_alias_directive", "global_attribute"):
|
|
81
|
+
return False
|
|
82
|
+
if previous.type == "global_statement" and item.type == "global_statement":
|
|
83
|
+
return self.statement_blank(previous, item)
|
|
84
|
+
return self.settings.max_blank_lines > 0
|
|
85
|
+
|
|
86
|
+
def using_blank(self, previous: Node, item: Node) -> bool:
|
|
87
|
+
"""Usings stay together, except between groups when the order is grouped."""
|
|
88
|
+
if self.settings.using_order != "system_first_grouped" or self.settings.max_blank_lines == 0:
|
|
89
|
+
return False
|
|
90
|
+
return _using_group(previous) != _using_group(item)
|
|
91
|
+
|
|
92
|
+
def directive_blank(self, previous: Node, item: Node) -> bool:
|
|
93
|
+
if self.settings.regions == "normalize":
|
|
94
|
+
if previous.type == "preproc_region" or item.type == "preproc_endregion":
|
|
95
|
+
return True
|
|
96
|
+
return self.has_blank_before(item)
|
|
97
|
+
|
|
98
|
+
# Directives -----------------------------------------------------------
|
|
99
|
+
|
|
100
|
+
def p_preproc_if(self, node: Node) -> Doc:
|
|
101
|
+
return self.conditional_directive(node)
|
|
102
|
+
|
|
103
|
+
def p_preproc_elif(self, node: Node) -> Doc:
|
|
104
|
+
return self.conditional_directive(node)
|
|
105
|
+
|
|
106
|
+
def p_preproc_else(self, node: Node) -> Doc:
|
|
107
|
+
return self.conditional_directive(node)
|
|
108
|
+
|
|
109
|
+
def conditional_directive(self, node: Node) -> Doc:
|
|
110
|
+
children = node.children
|
|
111
|
+
if not children:
|
|
112
|
+
return self.generic(node)
|
|
113
|
+
condition = node.child("condition")
|
|
114
|
+
header_end = children.index(condition) if condition is not None else 0
|
|
115
|
+
header = self.verbatim_range(children[: header_end + 1])
|
|
116
|
+
blank = self.current_blank()
|
|
117
|
+
parts: list[Doc] = [header]
|
|
118
|
+
# In source order: runs of items, the next branch, and #endif.
|
|
119
|
+
run: list[Node] = []
|
|
120
|
+
|
|
121
|
+
def flush() -> None:
|
|
122
|
+
if run:
|
|
123
|
+
parts.append(self.directive_line(run[0]))
|
|
124
|
+
parts.append(self.print_list(list(run), blank))
|
|
125
|
+
run.clear()
|
|
126
|
+
|
|
127
|
+
for child in children[header_end + 1 :]:
|
|
128
|
+
if child.field == "alternative" or child.text == "#endif":
|
|
129
|
+
flush()
|
|
130
|
+
parts.append(self.directive_line(child))
|
|
131
|
+
parts.append(self.print(child) if child.text is None else self.verbatim_range([child]))
|
|
132
|
+
else:
|
|
133
|
+
run.append(child)
|
|
134
|
+
flush()
|
|
135
|
+
return parts
|
|
136
|
+
|
|
137
|
+
def directive_line(self, node: Node) -> Doc:
|
|
138
|
+
"""The line break before a directive line or the first item after one."""
|
|
139
|
+
# A directive written at column 0 stays there; #endif is a bare token.
|
|
140
|
+
at_zero = self.is_column_zero_directive(node) or (
|
|
141
|
+
node.text is not None and node.text.startswith("#") and node.column == 0 and not node.leading
|
|
142
|
+
)
|
|
143
|
+
line: Doc = HARDLINE
|
|
144
|
+
if self.has_blank_before(node):
|
|
145
|
+
line = [HARDLINE, HARDLINE]
|
|
146
|
+
return [line, TRIM_INDENT] if at_zero else line
|
|
147
|
+
|
|
148
|
+
def p_preproc_region(self, node: Node) -> Doc:
|
|
149
|
+
return self.verbatim(node)
|
|
150
|
+
|
|
151
|
+
def p_preproc_endregion(self, node: Node) -> Doc:
|
|
152
|
+
return self.verbatim(node)
|
|
153
|
+
|
|
154
|
+
def p_shebang_directive(self, node: Node) -> Doc:
|
|
155
|
+
return self.verbatim(node)
|
|
156
|
+
|
|
157
|
+
def generic_directive(self, node: Node) -> Doc:
|
|
158
|
+
return self.verbatim(node)
|
|
159
|
+
|
|
160
|
+
p_preproc_define = generic_directive
|
|
161
|
+
p_preproc_undef = generic_directive
|
|
162
|
+
p_preproc_pragma = generic_directive
|
|
163
|
+
p_preproc_nullable = generic_directive
|
|
164
|
+
p_preproc_error = generic_directive
|
|
165
|
+
p_preproc_warning = generic_directive
|
|
166
|
+
p_preproc_line = generic_directive
|
|
167
|
+
p_preproc_if_in_attribute_list = generic_directive
|
|
168
|
+
|
|
169
|
+
# Usings and namespaces --------------------------------------------------
|
|
170
|
+
|
|
171
|
+
def p_using_directive(self, node: Node) -> Doc:
|
|
172
|
+
return self.words(node.children)
|
|
173
|
+
|
|
174
|
+
def p_extern_alias_directive(self, node: Node) -> Doc:
|
|
175
|
+
return self.words(node.children)
|
|
176
|
+
|
|
177
|
+
def words(self, nodes: Sequence[Node]) -> Doc:
|
|
178
|
+
"""Nodes separated by spaces, with none before ``;``."""
|
|
179
|
+
parts: list[Doc] = []
|
|
180
|
+
for i, child in enumerate(nodes):
|
|
181
|
+
if i and child.text != ";":
|
|
182
|
+
parts.append(" ")
|
|
183
|
+
parts.append(self.print(child))
|
|
184
|
+
return parts
|
|
185
|
+
|
|
186
|
+
def p_namespace_declaration(self, node: Node) -> Doc:
|
|
187
|
+
body = node.child("body")
|
|
188
|
+
if body is None or body.type != "declaration_list":
|
|
189
|
+
return self.generic(node)
|
|
190
|
+
index = node.children.index(body)
|
|
191
|
+
return [self.words(node.children[:index]), self.declaration_body(body, "namespace"), self.words(node.children[index + 1 :])]
|
|
192
|
+
|
|
193
|
+
def p_file_scoped_namespace_declaration(self, node: Node) -> Doc:
|
|
194
|
+
return self.words(node.children)
|
|
195
|
+
|
|
196
|
+
def declaration_body(self, body: Node, context: str) -> Doc:
|
|
197
|
+
if len(body.children) < 2 or body.verbatim:
|
|
198
|
+
return [" ", self.print(body)]
|
|
199
|
+
open_tok = body.children[0]
|
|
200
|
+
close_tok = body.children[-1]
|
|
201
|
+
items = body.children[1:-1]
|
|
202
|
+
if not items and not close_tok.leading and not open_tok.trailing:
|
|
203
|
+
if self.settings.empty_bodies == "inline":
|
|
204
|
+
return [" ", self.tok(open_tok), " ", self.tok(close_tok)]
|
|
205
|
+
return [self.open_brace(context), self.tok(open_tok), HARDLINE, self.tok(close_tok)]
|
|
206
|
+
inner: Doc = ""
|
|
207
|
+
if items:
|
|
208
|
+
inner = indent([HARDLINE, self.members(items)])
|
|
209
|
+
return [
|
|
210
|
+
self.open_brace(context),
|
|
211
|
+
self.tok(open_tok),
|
|
212
|
+
inner,
|
|
213
|
+
self.close_comments(close_tok),
|
|
214
|
+
HARDLINE,
|
|
215
|
+
self.tok(close_tok, leading=False),
|
|
216
|
+
]
|
|
217
|
+
|
|
218
|
+
def members(self, items: Sequence[Node]) -> Doc:
|
|
219
|
+
aligned = (
|
|
220
|
+
self.align_runs(items, self.assignment_split, self.member_blank) if self.settings.align_assignments else None
|
|
221
|
+
)
|
|
222
|
+
return self.print_list(items, self.member_blank, aligned=aligned)
|
|
223
|
+
|
|
224
|
+
def member_blank(self, previous: Node, item: Node) -> bool:
|
|
225
|
+
if previous.type in DIRECTIVE_TYPES or item.type in DIRECTIVE_TYPES:
|
|
226
|
+
return self.directive_blank(previous, item)
|
|
227
|
+
if self.settings.max_blank_lines == 0:
|
|
228
|
+
return False
|
|
229
|
+
mode = self.settings.member_blank_lines
|
|
230
|
+
if mode == "preserve":
|
|
231
|
+
return self.has_blank_before(item)
|
|
232
|
+
if mode == "all":
|
|
233
|
+
return True
|
|
234
|
+
if previous.type == item.type == "using_directive":
|
|
235
|
+
return self.using_blank(previous, item)
|
|
236
|
+
if previous.type == item.type == "extern_alias_directive":
|
|
237
|
+
return False
|
|
238
|
+
if (
|
|
239
|
+
self.is_tight(previous)
|
|
240
|
+
and self.is_tight(item)
|
|
241
|
+
and previous.type == item.type
|
|
242
|
+
and not self.has_comments_before(item)
|
|
243
|
+
):
|
|
244
|
+
return False
|
|
245
|
+
return True
|
|
246
|
+
|
|
247
|
+
def is_tight(self, node: Node) -> bool:
|
|
248
|
+
if node.type in ("field_declaration", "event_field_declaration"):
|
|
249
|
+
return True
|
|
250
|
+
if node.type == "property_declaration":
|
|
251
|
+
accessors = node.child("accessors")
|
|
252
|
+
if accessors is None:
|
|
253
|
+
return True
|
|
254
|
+
return all(a.child("body") is None for a in accessors.children if a.type == "accessor_declaration")
|
|
255
|
+
return False
|
|
256
|
+
|
|
257
|
+
# Types ------------------------------------------------------------------
|
|
258
|
+
|
|
259
|
+
def type_declaration(self, node: Node) -> Doc:
|
|
260
|
+
body = node.child("body")
|
|
261
|
+
if body is None:
|
|
262
|
+
body = node.first_of("declaration_list", "enum_member_declaration_list")
|
|
263
|
+
attributes, header, constraints, tail = self.split_declaration(node, body)
|
|
264
|
+
parts: list[Doc] = [self.attribute_lines(attributes), self.header(header)]
|
|
265
|
+
if constraints:
|
|
266
|
+
parts.append(self.constraints(constraints))
|
|
267
|
+
if body is not None:
|
|
268
|
+
if body.type == "enum_member_declaration_list":
|
|
269
|
+
parts.append(self.enum_body(body))
|
|
270
|
+
else:
|
|
271
|
+
parts.append(self.declaration_body(body, "type"))
|
|
272
|
+
parts.append(self.words(tail) if tail else "")
|
|
273
|
+
return parts
|
|
274
|
+
|
|
275
|
+
p_class_declaration = type_declaration
|
|
276
|
+
p_struct_declaration = type_declaration
|
|
277
|
+
p_interface_declaration = type_declaration
|
|
278
|
+
p_record_declaration = type_declaration
|
|
279
|
+
p_enum_declaration = type_declaration
|
|
280
|
+
|
|
281
|
+
def split_declaration(
|
|
282
|
+
self, node: Node, body: Node | None
|
|
283
|
+
) -> tuple[list[Node], list[Node], list[Node], list[Node]]:
|
|
284
|
+
"""(attribute lists, header, constraint clauses, what follows the body)."""
|
|
285
|
+
attributes: list[Node] = []
|
|
286
|
+
header: list[Node] = []
|
|
287
|
+
constraints: list[Node] = []
|
|
288
|
+
tail: list[Node] = []
|
|
289
|
+
seen_body = False
|
|
290
|
+
for child in node.children:
|
|
291
|
+
if child is body:
|
|
292
|
+
seen_body = True
|
|
293
|
+
elif seen_body:
|
|
294
|
+
tail.append(child)
|
|
295
|
+
elif child.type == "attribute_list" and not header:
|
|
296
|
+
attributes.append(child)
|
|
297
|
+
elif child.type == "type_parameter_constraints_clause":
|
|
298
|
+
constraints.append(child)
|
|
299
|
+
else:
|
|
300
|
+
header.append(child)
|
|
301
|
+
return attributes, header, constraints, tail
|
|
302
|
+
|
|
303
|
+
def attribute_lines(self, attributes: Sequence[Node]) -> Doc:
|
|
304
|
+
return [[self.print(a), HARDLINE] for a in attributes]
|
|
305
|
+
|
|
306
|
+
def header(self, nodes: Sequence[Node]) -> Doc:
|
|
307
|
+
parts: list[Doc] = []
|
|
308
|
+
previous: Node | None = None
|
|
309
|
+
for child in nodes:
|
|
310
|
+
if previous is not None and self.header_space(previous, child):
|
|
311
|
+
parts.append(" ")
|
|
312
|
+
parts.append(self.print(child))
|
|
313
|
+
previous = child
|
|
314
|
+
return parts
|
|
315
|
+
|
|
316
|
+
def header_space(self, previous: Node, child: Node) -> bool:
|
|
317
|
+
if child.type in _NO_SPACE_BEFORE:
|
|
318
|
+
return False
|
|
319
|
+
if previous.text == "~" or previous.type == "explicit_interface_specifier":
|
|
320
|
+
return False
|
|
321
|
+
if child.text == ";":
|
|
322
|
+
return False
|
|
323
|
+
return True
|
|
324
|
+
|
|
325
|
+
def constraints(self, clauses: Sequence[Node]) -> Doc:
|
|
326
|
+
return group(indent([[LINE, self.print(c)] for c in clauses]))
|
|
327
|
+
|
|
328
|
+
def p_base_list(self, node: Node) -> Doc:
|
|
329
|
+
if not node.children or node.children[0].text != ":":
|
|
330
|
+
return self.generic(node)
|
|
331
|
+
colon = node.children[0]
|
|
332
|
+
items, commas = split(node.children[1:])
|
|
333
|
+
docs: list[Doc] = []
|
|
334
|
+
for i, item in enumerate(items):
|
|
335
|
+
doc = self.join_tokens([(c, self.print(c)) for c in item])
|
|
336
|
+
if i < len(commas):
|
|
337
|
+
doc = [doc, self.tok(commas[i])]
|
|
338
|
+
docs.append(doc)
|
|
339
|
+
return group([self.tok(colon), indent([LINE, join(LINE, docs)])]) if len(docs) > 1 else [self.tok(colon), " ", docs[0] if docs else ""]
|
|
340
|
+
|
|
341
|
+
def p_primary_constructor_base_type(self, node: Node) -> Doc:
|
|
342
|
+
return self.join_tokens([(c, self.print(c)) for c in node.children])
|
|
343
|
+
|
|
344
|
+
def p_type_parameter_constraints_clause(self, node: Node) -> Doc:
|
|
345
|
+
colon = node.first_of(":")
|
|
346
|
+
if colon is None:
|
|
347
|
+
return self.generic(node)
|
|
348
|
+
index = node.children.index(colon)
|
|
349
|
+
items, commas = split(node.children[index + 1 :])
|
|
350
|
+
docs: list[Doc] = []
|
|
351
|
+
for i, item in enumerate(items):
|
|
352
|
+
doc = self.generic_sequence(item)
|
|
353
|
+
if i < len(commas):
|
|
354
|
+
doc = [doc, self.tok(commas[i])]
|
|
355
|
+
docs.append(doc)
|
|
356
|
+
return [self.words(node.children[:index]), " ", self.tok(colon), " ", join(" ", docs)]
|
|
357
|
+
|
|
358
|
+
def p_type_parameter_constraint(self, node: Node) -> Doc:
|
|
359
|
+
return self.generic_sequence(node.children)
|
|
360
|
+
|
|
361
|
+
def p_constructor_constraint(self, node: Node) -> Doc:
|
|
362
|
+
return self.join_tokens([(c, self.print(c)) for c in node.children])
|
|
363
|
+
|
|
364
|
+
# Enums ----------------------------------------------------------------
|
|
365
|
+
|
|
366
|
+
def enum_body(self, body: Node) -> Doc:
|
|
367
|
+
if len(body.children) < 2 or any(c.type in DIRECTIVE_TYPES for c in body.children):
|
|
368
|
+
return [" ", self.verbatim(body)]
|
|
369
|
+
open_tok = body.children[0]
|
|
370
|
+
close_tok = body.children[-1]
|
|
371
|
+
items, commas = self.items_and_commas(body)
|
|
372
|
+
if not items and not close_tok.leading:
|
|
373
|
+
if self.settings.empty_bodies == "inline":
|
|
374
|
+
return [" ", self.tok(open_tok), " ", self.tok(close_tok)]
|
|
375
|
+
return [self.open_brace("type"), self.tok(open_tok), HARDLINE, self.tok(close_tok)]
|
|
376
|
+
members = [item[0] for item in items if len(item) == 1]
|
|
377
|
+
if len(members) != len(items):
|
|
378
|
+
return [" ", self.verbatim(body)]
|
|
379
|
+
aligned: dict[int, Doc] = {}
|
|
380
|
+
if self.settings.align_enum_values:
|
|
381
|
+
aligned = self.align_runs(members, self.enum_split, lambda a, b: self.has_blank_before(b)) or {}
|
|
382
|
+
docs: list[Doc] = []
|
|
383
|
+
for i, member in enumerate(members):
|
|
384
|
+
doc = aligned.get(id(member)) or self.print(member)
|
|
385
|
+
if i < len(commas):
|
|
386
|
+
keep = i < len(members) - 1 or self.settings.trailing_commas != "remove"
|
|
387
|
+
if keep:
|
|
388
|
+
doc = [doc, self.tok(commas[i])]
|
|
389
|
+
elif i < len(members) - 1:
|
|
390
|
+
doc = [doc, ","]
|
|
391
|
+
elif self.settings.trailing_commas == "add":
|
|
392
|
+
doc = [doc, ","]
|
|
393
|
+
docs.append(doc)
|
|
394
|
+
lines: list[Doc] = []
|
|
395
|
+
for i, (member, doc) in enumerate(zip(members, docs, strict=True)):
|
|
396
|
+
if i:
|
|
397
|
+
lines.append([HARDLINE, HARDLINE] if self.has_blank_before(member) else HARDLINE)
|
|
398
|
+
lines.append(doc)
|
|
399
|
+
return [
|
|
400
|
+
self.open_brace("type"),
|
|
401
|
+
self.tok(open_tok),
|
|
402
|
+
indent([HARDLINE, lines]),
|
|
403
|
+
self.close_comments(close_tok),
|
|
404
|
+
HARDLINE,
|
|
405
|
+
self.tok(close_tok, leading=False),
|
|
406
|
+
]
|
|
407
|
+
|
|
408
|
+
def enum_split(self, member: Node) -> tuple[Doc, Node, Node, Doc] | None:
|
|
409
|
+
equals = member.first_of("=")
|
|
410
|
+
value = member.child("value")
|
|
411
|
+
name = member.child("name")
|
|
412
|
+
if equals is None or value is None or name is None or member.first_of("attribute_list") is not None:
|
|
413
|
+
return None
|
|
414
|
+
return (self.print(name), equals, value, "")
|
|
415
|
+
|
|
416
|
+
def p_enum_member_declaration(self, node: Node) -> Doc:
|
|
417
|
+
attributes = [c for c in node.children if c.type == "attribute_list"]
|
|
418
|
+
rest = [c for c in node.children if c.type != "attribute_list"]
|
|
419
|
+
equals = next((c for c in rest if c.text == "="), None)
|
|
420
|
+
if equals is not None and len(rest) == 3 and rest[1] is equals:
|
|
421
|
+
return [self.attribute_lines(attributes), self.rhs(self.print(rest[0]), equals, rest[2])]
|
|
422
|
+
return [self.attribute_lines(attributes), self.words(rest)]
|
|
423
|
+
|
|
424
|
+
# Members ----------------------------------------------------------------
|
|
425
|
+
|
|
426
|
+
def member(self, node: Node) -> Doc:
|
|
427
|
+
body = node.child("body")
|
|
428
|
+
accessors = node.child("accessors")
|
|
429
|
+
arrow_value = node.child("value") if node.type in ("property_declaration", "indexer_declaration") else None
|
|
430
|
+
initializer_start = None
|
|
431
|
+
if node.type == "property_declaration" and accessors is not None:
|
|
432
|
+
equals = next((c for c in node.children if c.text == "=" and not c.named), None)
|
|
433
|
+
if equals is not None:
|
|
434
|
+
initializer_start = node.children.index(equals)
|
|
435
|
+
attributes: list[Node] = []
|
|
436
|
+
header: list[Node] = []
|
|
437
|
+
constraints: list[Node] = []
|
|
438
|
+
ctor_init: Node | None = None
|
|
439
|
+
tail_start = len(node.children)
|
|
440
|
+
for i, child in enumerate(node.children):
|
|
441
|
+
if child is body or child is accessors or (arrow_value is not None and child is arrow_value and child.type == "arrow_expression_clause"):
|
|
442
|
+
tail_start = i
|
|
443
|
+
break
|
|
444
|
+
if child.type == "attribute_list" and not header:
|
|
445
|
+
attributes.append(child)
|
|
446
|
+
elif child.type == "type_parameter_constraints_clause":
|
|
447
|
+
constraints.append(child)
|
|
448
|
+
elif child.type == "constructor_initializer":
|
|
449
|
+
ctor_init = child
|
|
450
|
+
elif child.text == ";" and i == len(node.children) - 1:
|
|
451
|
+
tail_start = i
|
|
452
|
+
break
|
|
453
|
+
else:
|
|
454
|
+
header.append(child)
|
|
455
|
+
parts: list[Doc] = [self.attribute_lines(attributes), self.header(header)]
|
|
456
|
+
if ctor_init is not None:
|
|
457
|
+
parts.append(group(indent([LINE, self.print(ctor_init)])))
|
|
458
|
+
if constraints:
|
|
459
|
+
parts.append(self.constraints(constraints))
|
|
460
|
+
rest = node.children[tail_start:]
|
|
461
|
+
i = 0
|
|
462
|
+
while i < len(rest):
|
|
463
|
+
child = rest[i]
|
|
464
|
+
if child is body and child.type == "block":
|
|
465
|
+
parts.append(self.block(child, "member"))
|
|
466
|
+
elif child.type == "arrow_expression_clause":
|
|
467
|
+
parts.append(self.expression_body(child))
|
|
468
|
+
elif child is accessors:
|
|
469
|
+
parts.append(self.accessor_list(child))
|
|
470
|
+
elif initializer_start is not None and child is node.children[initializer_start]:
|
|
471
|
+
value = rest[i + 1] if i + 1 < len(rest) else None
|
|
472
|
+
if value is not None and value.text != ";":
|
|
473
|
+
parts.append(self.rhs("", child, value))
|
|
474
|
+
i += 2
|
|
475
|
+
continue
|
|
476
|
+
parts.append([" ", self.tok(child)])
|
|
477
|
+
elif child.text == ";":
|
|
478
|
+
parts.append(self.tok(child))
|
|
479
|
+
else:
|
|
480
|
+
parts.append([" ", self.print(child)])
|
|
481
|
+
i += 1
|
|
482
|
+
return parts
|
|
483
|
+
|
|
484
|
+
p_method_declaration = member
|
|
485
|
+
p_constructor_declaration = member
|
|
486
|
+
p_destructor_declaration = member
|
|
487
|
+
p_operator_declaration = member
|
|
488
|
+
p_conversion_operator_declaration = member
|
|
489
|
+
p_property_declaration = member
|
|
490
|
+
p_indexer_declaration = member
|
|
491
|
+
p_event_declaration = member
|
|
492
|
+
p_delegate_declaration = member
|
|
493
|
+
p_local_function_statement = member
|
|
494
|
+
|
|
495
|
+
def p_field_declaration(self, node: Node) -> Doc:
|
|
496
|
+
attributes = [c for c in node.children if c.type == "attribute_list"]
|
|
497
|
+
rest = [c for c in node.children if c.type != "attribute_list"]
|
|
498
|
+
return [self.attribute_lines(attributes), self.words(rest)]
|
|
499
|
+
|
|
500
|
+
p_event_field_declaration = p_field_declaration
|
|
501
|
+
|
|
502
|
+
def p_constructor_initializer(self, node: Node) -> Doc:
|
|
503
|
+
if not node.children or node.children[0].text != ":":
|
|
504
|
+
return self.generic(node)
|
|
505
|
+
rest = node.children[1:]
|
|
506
|
+
return [self.tok(node.children[0]), " ", self.join_tokens([(c, self.print(c)) for c in rest])]
|
|
507
|
+
|
|
508
|
+
def accessor_list(self, node: Node) -> Doc:
|
|
509
|
+
if len(node.children) < 2 or node.verbatim:
|
|
510
|
+
return [" ", self.print(node)]
|
|
511
|
+
open_tok = node.children[0]
|
|
512
|
+
close_tok = node.children[-1]
|
|
513
|
+
accessors = node.children[1:-1]
|
|
514
|
+
simple = all(
|
|
515
|
+
a.type == "accessor_declaration"
|
|
516
|
+
and a.child("body") is None
|
|
517
|
+
and a.first_of("attribute_list") is None
|
|
518
|
+
and not any(t.leading or t.trailing for t in a.tokens())
|
|
519
|
+
for a in accessors
|
|
520
|
+
) and not close_tok.leading and not open_tok.trailing
|
|
521
|
+
if simple and accessors:
|
|
522
|
+
return [" ", self.tok(open_tok), " ", join(" ", [self.print(a) for a in accessors]), " ", self.tok(close_tok)]
|
|
523
|
+
if not accessors and not close_tok.leading:
|
|
524
|
+
return [" ", self.tok(open_tok), " ", self.tok(close_tok)]
|
|
525
|
+
return [
|
|
526
|
+
self.open_brace("accessor"),
|
|
527
|
+
self.tok(open_tok),
|
|
528
|
+
indent([HARDLINE, self.print_list(accessors, lambda a, b: self.has_blank_before(b))]),
|
|
529
|
+
self.close_comments(close_tok),
|
|
530
|
+
HARDLINE,
|
|
531
|
+
self.tok(close_tok, leading=False),
|
|
532
|
+
]
|
|
533
|
+
|
|
534
|
+
def p_accessor_list(self, node: Node) -> Doc:
|
|
535
|
+
return self.accessor_list(node)
|
|
536
|
+
|
|
537
|
+
def p_accessor_declaration(self, node: Node) -> Doc:
|
|
538
|
+
body = node.child("body")
|
|
539
|
+
attributes = [c for c in node.children if c.type == "attribute_list"]
|
|
540
|
+
header: list[Node] = []
|
|
541
|
+
rest: list[Node] = []
|
|
542
|
+
for child in node.children:
|
|
543
|
+
if child.type == "attribute_list":
|
|
544
|
+
continue
|
|
545
|
+
if child is body or rest or child.text == ";":
|
|
546
|
+
rest.append(child)
|
|
547
|
+
else:
|
|
548
|
+
header.append(child)
|
|
549
|
+
parts: list[Doc] = [self.attribute_lines(attributes), self.words(header)]
|
|
550
|
+
for child in rest:
|
|
551
|
+
if child is body and child.type == "block":
|
|
552
|
+
parts.append(self.block(child, "accessor"))
|
|
553
|
+
elif child.type == "arrow_expression_clause":
|
|
554
|
+
parts.append(self.expression_body(child))
|
|
555
|
+
else:
|
|
556
|
+
parts.append(self.tok(child))
|
|
557
|
+
return parts
|
|
558
|
+
|
|
559
|
+
def p_arrow_expression_clause(self, node: Node) -> Doc:
|
|
560
|
+
return self.expression_body(node)
|
|
561
|
+
|
|
562
|
+
# Parameters ------------------------------------------------------------
|
|
563
|
+
|
|
564
|
+
def p_parameter_list(self, node: Node) -> Doc:
|
|
565
|
+
return self.parameters(node)
|
|
566
|
+
|
|
567
|
+
def p_bracketed_parameter_list(self, node: Node) -> Doc:
|
|
568
|
+
return self.parameters(node)
|
|
569
|
+
|
|
570
|
+
def parameters(self, node: Node) -> Doc:
|
|
571
|
+
if len(node.children) < 2 or node.children[0].text not in ("(", "["):
|
|
572
|
+
return self.generic(node)
|
|
573
|
+
open_tok = node.children[0]
|
|
574
|
+
close_tok = node.children[-1]
|
|
575
|
+
items, commas = self.items_and_commas(node)
|
|
576
|
+
if not items:
|
|
577
|
+
return [self.tok(open_tok), self.close_comments(close_tok), self.tok(close_tok, leading=False)]
|
|
578
|
+
docs: list[Doc] = []
|
|
579
|
+
for i, item in enumerate(items):
|
|
580
|
+
doc = self.parameter_item(item)
|
|
581
|
+
if i < len(commas):
|
|
582
|
+
doc = [doc, self.tok(commas[i])]
|
|
583
|
+
docs.append(doc)
|
|
584
|
+
style = self.settings.argument_wrap
|
|
585
|
+
if style == "one_per_line" or style not in ("one_per_line_close_on_last", "fill", "align"):
|
|
586
|
+
return group([self.tok(open_tok), indent([SOFTLINE, join(LINE, docs)]), SOFTLINE, self.close_comments(close_tok), self.tok(close_tok, leading=False)])
|
|
587
|
+
return self.argument_layout(open_tok, docs, close_tok, [])
|
|
588
|
+
|
|
589
|
+
def parameter_item(self, item: Sequence[Node]) -> Doc:
|
|
590
|
+
if len(item) == 1:
|
|
591
|
+
return self.print(item[0])
|
|
592
|
+
# A params parameter is not wrapped in a node: params int[] values.
|
|
593
|
+
return self.words(item)
|
|
594
|
+
|
|
595
|
+
def p_parameter(self, node: Node) -> Doc:
|
|
596
|
+
return self.words(node.children)
|
|
597
|
+
|
|
598
|
+
def p_implicit_parameter(self, node: Node) -> Doc:
|
|
599
|
+
return self.generic(node)
|
|
600
|
+
|
|
601
|
+
# Attributes -------------------------------------------------------------
|
|
602
|
+
|
|
603
|
+
def p_attribute_list(self, node: Node) -> Doc:
|
|
604
|
+
parts: list[Doc] = []
|
|
605
|
+
for child in node.children:
|
|
606
|
+
parts.append(self.print(child))
|
|
607
|
+
if child.text in (",", ":") and not child.named or child.type == "attribute_target_specifier":
|
|
608
|
+
parts.append(" ")
|
|
609
|
+
return parts
|
|
610
|
+
|
|
611
|
+
p_global_attribute = p_attribute_list
|
|
612
|
+
|
|
613
|
+
def p_attribute_target_specifier(self, node: Node) -> Doc:
|
|
614
|
+
return [self.print(c) for c in node.children]
|
|
615
|
+
|
|
616
|
+
def p_attribute(self, node: Node) -> Doc:
|
|
617
|
+
return self.join_tokens([(c, self.print(c)) for c in node.children])
|
|
618
|
+
|
|
619
|
+
|
|
620
|
+
def _using_group(node: Node) -> tuple[int, int, str]:
|
|
621
|
+
"""global or not, plain, static or alias, and the first part of the name."""
|
|
622
|
+
is_global, kind, _, name = using_key(node, "system_first_grouped")
|
|
623
|
+
return (is_global, kind, name.split(".")[0])
|