Implement full-fidelity parsing and formatting for the coroutine keyword
[hiphop-php.git] / hphp / hack / src / parser / full_fidelity_pretty_printer.ml
blob7aa07497fa84721629d13f1d4f484e5b67d45043
1 (**
2 * Copyright (c) 2016, Facebook, Inc.
3 * All rights reserved.
5 * This source code is licensed under the BSD-style license found in the
6 * LICENSE file in the "hack" directory of this source tree. An additional grant
7 * of patent rights can be found in the PATENTS file in the same directory.
9 *)
11 (* The general approach of the pretty printer is to give as much flexibility in
12 * terms of where a newline can occur as possible, while maintaining a sensible
13 * layout that is considerred human readable and "normal"
14 * An optional break is introduced whenever it is possible for a line break to
15 * occur in real life. Small components are grouped together so that each
16 * component decide their layouts individually.
17 * Single line comments is the exception to everything: a newline is forced at
18 * the end of a single line comments even if the line otherwise fits. This rule
19 * overrides the default behaviour of some operators, such as immediate_cons ^^^
20 * which otherwise does not even introduce a break.
21 * Design decisions include:
22 * 1. Each statement is separated from others using a line break
23 * 2. Brackets/parenthesis/braces are either both on different lines with child
24 * or both on the same line with the entire child on one line as well
25 * 3. binary operators can be on different lines with arguments
26 * 4. unary operators must be on the same line as the argument
27 * 5. semicolons have to be on the same line as the last line of the statement
28 * that it ends
31 (* The main data type that is used in the pretty printer is a 5 tuple:
33 * (l_trivia, l_single, doc, r_trivia, r_single)
35 * l_trivia: the doc generated from the leading trivia of the syntax node
36 * l_single: whether the leading trivia contains a single line comment
37 * doc : the doc generated from the main body of the syntax node
38 * r_trivia: the doc generated from trailing trivia of the syntax node
39 * r_single: whether the trailing trivia contains a single line comment
41 open Pretty_printing_library_sig
42 open Limited_width_pretty_printing_library
43 (* utility functions to make combinators look simpler
44 * See Lindig's paper for reference *)
45 module Utility (P : Library) = struct
46 include P
48 let space = text " "
50 let absorb_nil_cons doc1 doc2 delimiter =
51 match doc1, doc2 with
52 | Nil, _ -> doc2
53 | _, Nil -> doc1
54 | _, _ -> doc1 ^^ delimiter ^^ doc2
56 let break_cons doc1 doc2 = absorb_nil_cons doc1 doc2 break
58 let space_cons doc1 doc2 = absorb_nil_cons doc1 doc2 space
60 let choose_cons must is_empty x y =
61 let delimiter =
62 if must then must_break
63 else if is_empty then breakwith ""
64 else break
66 absorb_nil_cons x y delimiter
69 let group_doc (x_lead, x_lead_single, x, x_trail, x_trail_single) =
70 let optional_group = if x = Nil then x else group x in
71 (x_lead, x_lead_single, optional_group, x_trail, x_trail_single)
73 let combine (l_lead, l_lead_single, l, l_trail, l_trail_single) =
74 let front_part = choose_cons l_lead_single false l_lead (group l) in
75 space_cons front_part l_trail
77 (* higher order function to combine two docs with leading and trailing
78 * comments. This function creates a front part and a back part in a fixed
79 * way and takes a function that combines the two parts in different ways *)
80 let doc_combinor x y combinor =
81 let (l_lead, l_lead_single, l, l_trail, l_trail_single) = x in
82 let (r_lead, r_lead_single, r, r_trail, r_trail_single) = y in
83 let front_p = space_cons l l_trail in
84 let end_p = choose_cons r_lead_single false r_lead r in
85 match l, r with
86 | Nil, _ -> (r_lead, r_lead_single, r, r_trail, r_trail_single)
87 | _, Nil -> (l_lead, l_lead_single, l, l_trail, l_trail_single)
88 | _, _ ->
89 (l_lead, l_lead_single, combinor front_p end_p, r_trail, r_trail_single)
91 let doc_cons_opt empty x y =
92 let (_, _, _, _, l_trail_single) = x in
93 let combinor front_part end_part =
94 choose_cons l_trail_single empty front_part end_part in
95 doc_combinor x y combinor
97 let doc_cons = doc_cons_opt false
98 let (^|) = doc_cons
100 let doc_cons_empty = doc_cons_opt true
101 let (^^|) = doc_cons_empty
103 let immediate_cons x y =
104 let (_, _, _, _, l_trail_single) = x in
105 let (_, r_lead_single, _, _, _) = y in
106 let combinor front_part end_part =
107 if l_trail_single || r_lead_single then
108 choose_cons true false front_part end_part
109 else front_part ^^ end_part
111 doc_combinor x y combinor
112 let (^^^) = immediate_cons
114 (* indent [r] by [indent] after [l] using the suitable line break *)
115 let choose_indent_doc empty x y indent =
116 let (_, _, _, _, l_trail_single) = x in
117 let combinor front_part end_part =
118 let break_choice =
119 if l_trail_single then must_break
120 else if empty then breakwith ""
121 else break
123 front_part ^^ nest indent (break_choice ^^ end_part)
125 doc_combinor x y combinor
127 (* put a break before [r] and nest [r] by [indent] in vertical layout *)
128 let indent_doc = choose_indent_doc false
130 let indent_doc_no_space = choose_indent_doc true
132 (* typically we will want to indent block [blk] that is enclosed by
133 * [l] and [r] by amount [indt] *)
134 let indent_block l blk r indt =
135 group_doc (indent_doc l blk indt ^| r)
137 let indent_block_no_space l blk r indt =
138 group_doc ((indent_doc_no_space l blk indt) ^^| r)
140 let add_break (a, b, c, d, e) = (a, b, c, d, true)
143 module LineConf = struct
144 let line_width = 80
146 module Comparator = WidthConstrainedDocComparator(LineConf)
147 module Core = Pretty_printing_library.Make(Comparator)
148 module Printer = Utility(Core)
149 module Syntax = Full_fidelity_editable_syntax
150 module EditableToken = Full_fidelity_editable_token
151 open Syntax
152 open Printer
154 let get_doc_from_trivia trivia_lst allow_break =
155 (* generate a document from a list of trivias. Return the doc, as well
156 * as whether the trivia list contains a single line comment *)
157 let module Trivia = Full_fidelity_editable_trivia in
158 let module Kind = Full_fidelity_trivia_kind in
159 let handle_trivia trivia = match Trivia.kind trivia with
160 | Kind.WhiteSpace -> (nil, false)
161 | Kind.EndOfLine -> (nil, false)
162 | Kind.Unsafe
163 | Kind.FallThrough
164 | Kind.SingleLineComment ->
165 (* no code after comments *)
166 (text (Trivia.text trivia), true)
167 | Kind.Markup
168 | Kind.FixMe
169 | Kind.IgnoreError
170 | Kind.UnsafeExpression
171 | Kind.DelimitedComment ->
172 (text (Trivia.text trivia), false)
174 let concat = if allow_break then break_cons else space_cons in
175 let fold_fun x y =
176 let (a, c1) = x in
177 let (b, c2) = y in
178 let result = concat a b in
179 (result, c1 || c2)
181 (* no group here, since all breaks are compulsory. Will group on top level *)
182 List.fold_left fold_fun (nil, false) (List.map handle_trivia trivia_lst)
184 let from_token x =
185 let front_trivias = EditableToken.leading x in
186 let end_trivias = EditableToken.trailing x in
187 let (front_doc, front_single) = get_doc_from_trivia front_trivias true in
188 let (end_doc, end_single) = get_doc_from_trivia end_trivias false in
189 let doc = text (EditableToken.text x) in
190 (front_doc, front_single, doc, end_doc, end_single)
192 (* create a 5-tuple (see top of file) from x with no trivias *)
193 let make_simple x = (nil, false, x, nil, false)
194 let indt = 2
195 let missing = make_simple nil
196 let error_header = make_simple (text "Error:")
197 let space = make_simple (text " ")
198 let colon = make_simple (text ":")
199 let comma = make_simple (text ",")
200 let l_square = make_simple (text "[")
201 let r_square = make_simple (text "]")
202 let question = make_simple (text "?")
203 let ellipsis = make_simple (text "...")
205 let rec get_doc node =
206 match syntax node with
207 | Missing -> missing
208 | Token x -> from_token x
210 | SyntaxList x -> get_from_children x
211 | ErrorSyntax { error_error } -> get_doc error_error
212 | LiteralExpression x ->
213 begin
214 match syntax x.literal_expression with
215 | SyntaxList l -> get_from_children_no_space l
216 | _ -> get_doc x.literal_expression
218 | VariableExpression x -> get_doc x.variable_expression
219 | QualifiedNameExpression x -> get_doc x.qualified_name_expression
220 | PipeVariableExpression x -> get_doc x.pipe_variable_expression
221 | ListItem x -> (get_doc x.list_item) ^^^ (get_doc x.list_separator)
222 | EndOfFile { end_of_file_token } -> get_doc end_of_file_token
223 | ScriptHeader x -> get_doc x.header_less_than ^^^
224 get_doc x.header_question ^^^
225 (x.header_language |> get_doc |> add_break)
226 | Script x -> group_doc ( get_doc x.script_header
227 ^| get_doc x.script_declarations )
228 | ClassishDeclaration
229 { classish_attribute; classish_modifiers; classish_keyword;
230 classish_name; classish_type_parameters; classish_extends_keyword;
231 classish_extends_list; classish_implements_keyword;
232 classish_implements_list; classish_body } ->
233 let attr = add_break (get_doc classish_attribute) in
234 let preface = group_doc (
235 get_doc classish_modifiers ^|
236 get_doc classish_keyword
237 ) in
239 let name_and_generics =
240 let name = get_doc classish_name in
241 let type_params = get_doc classish_type_parameters in
242 group_doc (indent_doc name type_params indt)
245 let extends =
246 let extends_token = get_doc classish_extends_keyword in
247 let extends_list = get_doc classish_extends_list in
248 group_doc (indent_doc extends_token extends_list indt)
251 let implements =
252 let implements_token = get_doc classish_implements_keyword in
253 let implements_list = get_doc classish_implements_list in
254 group_doc (indent_doc implements_token implements_list indt)
257 let body = get_doc classish_body in
259 (* TODO: Make this better *)
260 attr ^^^
261 group_doc (
262 group_doc (
263 preface ^|
264 name_and_generics
265 ) ^|
266 group_doc (
267 extends ^|
268 implements
269 ) ^|
270 body
272 | ClassishBody x ->
273 let left = get_doc x.classish_body_left_brace in
274 let right = get_doc x.classish_body_right_brace in
275 let body = get_doc x.classish_body_elements in
276 indent_block_no_space left body right indt
277 | XHPRequired { xhp_required_at; xhp_required_keyword } ->
278 let a = get_doc xhp_required_at in
279 let r = get_doc xhp_required_keyword in
280 a ^^^ r
281 | XHPChildrenDeclaration {
282 xhp_children_keyword;
283 xhp_children_expression;
284 xhp_children_semicolon } ->
285 let c = get_doc xhp_children_keyword in
286 let e = get_doc xhp_children_expression in
287 let s = get_doc xhp_children_semicolon in
288 c ^| e ^^^ s
289 | XHPChildrenParenthesizedList {
290 xhp_children_list_left_paren;
291 xhp_children_list_xhp_children;
292 xhp_children_list_right_paren } ->
293 let l = get_doc xhp_children_list_left_paren in
294 let c = get_doc xhp_children_list_xhp_children in
295 let r = get_doc xhp_children_list_right_paren in
296 l ^| c ^| r
297 | XHPCategoryDeclaration {
298 xhp_category_keyword;
299 xhp_category_categories;
300 xhp_category_semicolon } ->
301 let c = get_doc xhp_category_keyword in
302 let l = get_doc xhp_category_categories in
303 let s = get_doc xhp_category_semicolon in
304 c ^| l ^^^ s
305 | XHPEnumType x ->
306 let e = get_doc x.xhp_enum_keyword in
307 let l = get_doc x.xhp_enum_left_brace in
308 let v = get_doc x.xhp_enum_values in
309 let r = get_doc x.xhp_enum_right_brace in
310 group_doc (e ^| l ^| v ^| r)
311 | XHPClassAttributeDeclaration {
312 xhp_attribute_keyword;
313 xhp_attribute_attributes;
314 xhp_attribute_semicolon } ->
315 let attr = get_doc xhp_attribute_keyword in
316 let attrs = get_doc xhp_attribute_attributes in
317 let semi = get_doc xhp_attribute_semicolon in
318 group_doc (attr ^| attrs ^^^ semi)
319 | XHPClassAttribute
320 { xhp_attribute_decl_type; xhp_attribute_decl_name;
321 xhp_attribute_decl_initializer; xhp_attribute_decl_required } ->
322 let t = get_doc xhp_attribute_decl_type in
323 let n = get_doc xhp_attribute_decl_name in
324 let i = get_doc xhp_attribute_decl_initializer in
325 let r = get_doc xhp_attribute_decl_required in
326 group_doc (t ^| n ^| i ^| r)
327 | XHPSimpleClassAttribute { xhp_simple_class_attribute_type } ->
328 get_doc xhp_simple_class_attribute_type
329 | TraitUse {
330 trait_use_keyword;
331 trait_use_names;
332 trait_use_semicolon } ->
333 let use = get_doc trait_use_keyword in
334 let name_list = get_doc trait_use_names in
335 let semi = get_doc trait_use_semicolon in
336 use ^| name_list ^^^ semi
337 | RequireClause x ->
338 let r = get_doc x.require_keyword in
339 let k = get_doc x.require_kind in
340 let n = get_doc x.require_name in
341 let s = get_doc x.require_semicolon in
342 r ^| k ^| n ^^^ s
343 | ConstDeclaration {
344 const_abstract;
345 const_keyword;
346 const_type_specifier;
347 const_declarators;
348 const_semicolon } ->
349 let abstr = get_doc const_abstract in
350 let token = get_doc const_keyword in
351 let ty = get_doc const_type_specifier in
352 let lst = get_doc const_declarators in
353 let semi = get_doc const_semicolon in
354 group_doc (abstr ^| token ^| ty ) ^| lst ^^^ semi
355 | ConstantDeclarator x ->
356 let name = get_doc x.constant_declarator_name in
357 let init = get_doc x.constant_declarator_initializer in
358 group_doc (name ^| init)
359 | TypeConstDeclaration x ->
360 let abstr = get_doc x.type_const_abstract in
361 let const = get_doc x.type_const_keyword in
362 let type_ = get_doc x.type_const_type_keyword in
363 let name = get_doc x.type_const_name in
364 let type_constraint = get_doc x.type_const_type_constraint in
365 let equal = get_doc x.type_const_equal in
366 let type_spec = get_doc x.type_const_type_specifier in
367 let semicolon = get_doc x.type_const_semicolon in
368 group_doc (
369 group_doc (abstr ^| const ^| type_ ^| name) ^|
370 type_constraint ^|
371 equal ^|
372 group_doc (type_spec ^^^ semicolon)
374 | EnumDeclaration {
375 enum_attribute_spec;
376 enum_keyword;
377 enum_name;
378 enum_colon;
379 enum_base;
380 enum_type;
381 enum_left_brace;
382 enum_enumerators;
383 enum_right_brace } ->
384 let attrs = get_doc enum_attribute_spec in
385 let en = get_doc enum_keyword in
386 let na = get_doc enum_name in
387 let co = get_doc enum_colon in
388 let ba = get_doc enum_base in
389 let ty = get_doc enum_type in
390 let lb = get_doc enum_left_brace in
391 let es = get_doc enum_enumerators in
392 let rb = get_doc enum_right_brace in
393 (* TODO: This could be a lot better. Add indentation, etc. *)
394 attrs ^| en ^| na ^| co ^| ba ^| ty ^| lb ^| es ^| rb
395 | Enumerator x ->
396 let n = get_doc x.enumerator_name in
397 let e = get_doc x.enumerator_equal in
398 let v = get_doc x.enumerator_value in
399 let semicolon = get_doc x.enumerator_semicolon in
400 n ^| e ^| v ^^^ semicolon
401 | AliasDeclaration x ->
402 (* TODO: What's the best way to ensure that there's a newline between the
403 attribute and the alias declaration proper? *)
404 let attr = get_doc x.alias_attribute_spec in
405 let a = get_doc x.alias_keyword in
406 let n = get_doc x.alias_name in
407 let generic = get_doc x.alias_generic_parameter in
408 let c = get_doc x.alias_constraint in
409 let e = get_doc x.alias_equal in
410 let t = get_doc x.alias_type in
411 let s = get_doc x.alias_semicolon in
412 attr ^| a ^| n ^| generic ^| c ^| e ^| t ^^^ s
413 | PropertyDeclaration
414 { property_modifiers; property_type;
415 property_declarators; property_semicolon } ->
416 let m = get_doc property_modifiers in
417 let t = get_doc property_type in
418 let d = get_doc property_declarators in
419 let s = get_doc property_semicolon in
420 m ^| t ^| d ^^^ s
421 | PropertyDeclarator { property_name; property_initializer } ->
422 let n = get_doc property_name in
423 let i = get_doc property_initializer in
424 n ^| i
425 | NamespaceDeclaration x ->
426 let t = get_doc x.namespace_keyword in
427 let n = get_doc x.namespace_name in
428 let b = get_doc x.namespace_body in
429 t ^| n ^| b
430 | NamespaceBody x ->
431 let left = get_doc x.namespace_left_brace in
432 let body = get_doc x.namespace_declarations in
433 let right = get_doc x.namespace_right_brace in
434 indent_block_no_space left body right indt |> add_break
435 | NamespaceUseDeclaration x ->
436 let u = get_doc x.namespace_use_keyword in
437 let k = get_doc x.namespace_use_kind in
438 let c = get_doc x.namespace_use_clauses in
439 let s = get_doc x.namespace_use_semicolon in
440 u ^| k ^| c ^^^ s
441 | NamespaceUseClause x ->
442 let k = get_doc x.namespace_use_clause_kind in
443 let n = get_doc x.namespace_use_name in
444 let a = get_doc x.namespace_use_as in
445 let l = get_doc x.namespace_use_alias in
446 k ^| n ^| a ^| l
447 | NamespaceGroupUseDeclaration x ->
448 let u = get_doc x.namespace_group_use_keyword in
449 let k = get_doc x.namespace_group_use_kind in
450 let p = get_doc x.namespace_group_use_prefix in
451 let l = get_doc x.namespace_group_use_left_brace in
452 let c = get_doc x.namespace_group_use_clauses in
453 let r = get_doc x.namespace_group_use_right_brace in
454 let s = get_doc x.namespace_group_use_semicolon in
455 u ^| k ^| p ^| l ^| c ^| r ^^^ s
456 | FunctionDeclaration x ->
457 let attr = get_doc x.function_attribute_spec in
458 let header = get_doc x.function_declaration_header in
459 let body = x.function_body in
460 let after_attr = handle_compound_inline_brace header body missing in
461 group_doc (attr ^| after_attr)
462 | FunctionDeclarationHeader
463 { function_async;
464 function_coroutine;
465 function_keyword;
466 function_ampersand;
467 function_name;
468 function_type_parameter_list;
469 function_left_paren;
470 function_parameter_list;
471 function_right_paren;
472 function_colon;
473 function_type;
474 function_where_clause }
476 let preface = group_doc (
477 get_doc function_async
478 ^| get_doc function_coroutine
479 ^| get_doc function_keyword
480 ) in
481 let name_and_generics =
482 let type_params = get_doc function_type_parameter_list in
483 let ampersand = get_doc function_ampersand in
484 let name = get_doc function_name in
485 group_doc (indent_doc (ampersand ^^^ name) type_params indt)
487 let parameters =
488 let left = get_doc function_left_paren in
489 let right = get_doc function_right_paren in
490 let params = get_doc function_parameter_list in
491 indent_block_no_space left params right indt
493 let type_declaration =
494 let fun_colon = get_doc function_colon in
495 let fun_type = get_doc function_type in
496 let where_clause = get_doc function_where_clause in
497 group_doc (fun_colon ^| fun_type ^| where_clause)
499 group_doc (
500 group_doc ( group_doc (preface ^| name_and_generics) ^^| parameters )
501 ^| type_declaration
503 | WhereClause { where_clause_keyword; where_clause_constraints } ->
504 let w = get_doc where_clause_keyword in
505 let c = get_doc where_clause_constraints in
506 w ^| c
507 | WhereConstraint { where_constraint_left_type; where_constraint_operator ;
508 where_constraint_right_type } ->
509 let l = get_doc where_constraint_left_type in
510 let o = get_doc where_constraint_operator in
511 let r = get_doc where_constraint_right_type in
512 l ^| o ^| r
513 | MethodishDeclaration
514 { methodish_attribute; methodish_modifiers; methodish_function_decl_header;
515 methodish_function_body; methodish_semicolon } ->
516 let methodish_attr = get_doc methodish_attribute in
517 let methodish_modifiers = get_doc methodish_modifiers in
518 let function_header = get_doc methodish_function_decl_header in
519 let body_node = methodish_function_body in
520 let semicolon = get_doc methodish_semicolon in
521 let before_body = group_doc (methodish_modifiers ^| function_header) in
522 let after_attr =
523 handle_compound_inline_brace before_body body_node missing in
524 let after_attr = after_attr ^^^ semicolon in
525 group_doc (methodish_attr ^| after_attr)
526 | DecoratedExpression x ->
527 let decorator = get_doc x.decorated_expression_decorator in
528 let expression = get_doc x.decorated_expression_expression in
529 group_doc (decorator ^^^ expression)
530 | ParameterDeclaration {
531 parameter_attribute;
532 parameter_visibility;
533 parameter_type;
534 parameter_name;
535 parameter_default_value } ->
536 let attr = get_doc parameter_attribute in
537 let visibility = get_doc parameter_visibility in
538 let parameter_type = get_doc parameter_type in
539 let parameter_name = get_doc parameter_name in
540 let parameter_default = get_doc parameter_default_value in
541 group_doc
542 ( attr ^| visibility ^| parameter_type ^| parameter_name
543 ^| parameter_default )
544 | VariadicParameter { variadic_parameter_ellipsis } ->
545 get_doc variadic_parameter_ellipsis
546 | AttributeSpecification {
547 attribute_specification_left_double_angle;
548 attribute_specification_attributes;
549 attribute_specification_right_double_angle } ->
550 let left = get_doc attribute_specification_left_double_angle in
551 let specs = get_doc attribute_specification_attributes in
552 let right = get_doc attribute_specification_right_double_angle in
553 indent_block_no_space left specs right indt
554 | Attribute x ->
555 let name = get_doc x.attribute_name in
556 let left = get_doc x.attribute_left_paren in
557 let right = get_doc x.attribute_right_paren in
558 let values = get_doc x.attribute_values in
559 let left_part = group_doc (name ^^| left) in
560 indent_block_no_space left_part values right indt
561 | InclusionExpression x ->
562 let rq = get_doc x.inclusion_require in
563 let fn = get_doc x.inclusion_filename in
564 rq ^| fn
565 | InclusionDirective x ->
566 let ex = get_doc x.inclusion_expression in
567 let se = get_doc x.inclusion_semicolon in
568 ex ^^^ se
569 | CompoundStatement x ->
570 let left = get_doc x.compound_left_brace in
571 let right = get_doc x.compound_right_brace in
572 let body = get_doc x.compound_statements in
573 indent_block_no_space left body right indt |> add_break
574 | ExpressionStatement {
575 expression_statement_expression;
576 expression_statement_semicolon } ->
577 let body = get_doc expression_statement_expression in
578 let semicolon = get_doc expression_statement_semicolon in
579 (* semicolon always follows the last line *)
580 body ^^^ semicolon |> group_doc |> add_break
581 | UnsetStatement {
582 unset_keyword;
583 unset_left_paren;
584 unset_variables;
585 unset_right_paren;
586 unset_semicolon} ->
587 let u = get_doc unset_keyword in
588 let l = get_doc unset_left_paren in
589 let v = get_doc unset_variables in
590 let r = get_doc unset_right_paren in
591 let s = get_doc unset_semicolon in
592 group_doc (u ^^^ l ^^^ v ^^^ r ^^^ s)
593 | WhileStatement
594 { while_keyword; while_left_paren; while_condition; while_right_paren;
595 while_body } ->
596 let keyword = get_doc while_keyword in
597 let left = get_doc while_left_paren in
598 let condition = get_doc while_condition in
599 let right = get_doc while_right_paren in
600 let left_part = group_doc (keyword ^^| left) in
601 let start_block = indent_block_no_space left_part condition right indt in
602 handle_compound_brace_prefix_indent start_block while_body indt
603 |> add_break
604 | IfStatement
605 { if_keyword; if_left_paren; if_condition; if_right_paren; if_statement;
606 if_elseif_clauses; if_else_clause }->
607 let keyword = get_doc if_keyword in
608 let left = get_doc if_left_paren in
609 let condition = get_doc if_condition in
610 let right = get_doc if_right_paren in
611 let if_stmt = if_statement in
612 let elseif_clause = get_doc if_elseif_clauses in
613 let else_clause = get_doc if_else_clause in
614 let left_part = group_doc (keyword ^^| left) in
615 let start_block = indent_block_no_space left_part condition right indt in
616 let if_statement =
617 handle_compound_brace_prefix_indent start_block if_stmt indt in
618 let if_statement = add_break if_statement in
619 group_doc (if_statement ^| elseif_clause ^| else_clause)
620 | ElseifClause
621 { elseif_keyword; elseif_left_paren; elseif_condition; elseif_right_paren;
622 elseif_statement } ->
623 let keyword = get_doc elseif_keyword in
624 let left = get_doc elseif_left_paren in
625 let condition = get_doc elseif_condition in
626 let right = get_doc elseif_right_paren in
627 let elif_statement_syntax = elseif_statement in
628 let left_part = group_doc (keyword ^^| left) in
629 let start_block = indent_block_no_space left_part condition right indt in
630 handle_compound_brace_prefix_indent start_block elif_statement_syntax indt
631 |> add_break
632 | ElseClause x ->
633 let keyword = get_doc x.else_keyword in
634 let statement = x.else_statement in
635 handle_compound_brace_prefix_indent keyword statement indt
636 |> add_break
637 | TryStatement
638 { try_keyword;
639 try_compound_statement;
640 try_catch_clauses;
641 try_finally_clause } ->
642 let keyword = get_doc try_keyword in
643 let compound_stmt = try_compound_statement in
644 let try_part =
645 handle_compound_brace_prefix_indent keyword compound_stmt indt in
646 let catch_clauses = get_doc try_catch_clauses in
647 let finally_clause = get_doc try_finally_clause in
648 group_doc (try_part ^| catch_clauses ^| finally_clause)
649 |> add_break
650 | CatchClause {
651 catch_keyword;
652 catch_left_paren;
653 catch_type;
654 catch_variable;
655 catch_right_paren;
656 catch_body } ->
657 let keyword = get_doc catch_keyword in
658 let left = get_doc catch_left_paren in
659 let ty = get_doc catch_type in
660 let var = get_doc catch_variable in
661 let param = ty ^| var in
662 let right = get_doc catch_right_paren in
663 let stmt = catch_body in
664 let front_part = group_doc (keyword ^| left) in
665 let before_stmt = indent_block_no_space front_part param right indt in
666 handle_compound_brace_prefix_indent before_stmt stmt indt
667 |> add_break
668 | FinallyClause {
669 finally_keyword;
670 finally_body } ->
671 let keyword = get_doc finally_keyword in
672 handle_compound_brace_prefix_indent keyword finally_body indt
673 |> add_break
674 | DoStatement {
675 do_keyword;
676 do_body;
677 do_while_keyword;
678 do_left_paren;
679 do_condition;
680 do_right_paren;
681 do_semicolon } ->
682 let keyword = get_doc do_keyword in
683 let statement = do_body in
684 let while_keyword = get_doc do_while_keyword in
685 let left = get_doc do_left_paren in
686 let right = get_doc do_right_paren in
687 let condition = get_doc do_condition in
688 let semicolon = get_doc do_semicolon in
689 let statement_part =
690 handle_compound_brace_prefix_indent keyword statement indt |> add_break in
691 let left_part = group_doc (while_keyword ^^| left) in
692 let condition_part = indent_block_no_space left_part condition right indt in
693 group_doc (statement_part ^| condition_part) ^^^ semicolon
694 | ForStatement {
695 for_keyword;
696 for_left_paren;
697 for_initializer;
698 for_first_semicolon;
699 for_control;
700 for_second_semicolon;
701 for_end_of_loop;
702 for_right_paren;
703 for_body } ->
704 let keyword = get_doc for_keyword in
705 let left_paren = get_doc for_left_paren in
706 let initializer_expr = get_doc for_initializer in
707 let first_semicolon = get_doc for_first_semicolon in
708 let control_expr = get_doc for_control in
709 let second_semicolon = get_doc for_second_semicolon in
710 let end_of_loop_expr = get_doc for_end_of_loop in
711 let right_paren = get_doc for_right_paren in
712 let statement = for_body in
713 let left_part = group_doc (keyword ^^| left_paren) in
714 let for_expressions =
715 control_expr ^^^ second_semicolon ^| end_of_loop_expr in
716 let for_expressions = if is_missing for_control
717 then first_semicolon ^^| for_expressions
718 else first_semicolon ^| for_expressions in
719 let for_expressions = group_doc (initializer_expr ^^^ for_expressions) in
720 let start_block =
721 indent_block_no_space left_part for_expressions right_paren indt in
722 handle_compound_brace_prefix_indent start_block statement indt |> add_break
723 | ForeachStatement {
724 foreach_keyword;
725 foreach_left_paren;
726 foreach_collection;
727 foreach_await_keyword;
728 foreach_as;
729 foreach_key;
730 foreach_arrow;
731 foreach_value;
732 foreach_right_paren;
733 foreach_body }->
734 let keyword = get_doc foreach_keyword in
735 let left = get_doc foreach_left_paren in
736 let right = get_doc foreach_right_paren in
737 let collection_name = get_doc foreach_collection in
738 let await_keyword = get_doc foreach_await_keyword in
739 let as_keyword = get_doc foreach_as in
740 let key = get_doc foreach_key in
741 let arrow = get_doc foreach_arrow in
742 let value = get_doc foreach_value in
743 let statement = foreach_body in
744 let left_part = group_doc (keyword ^| left) in
745 let arrow_part = group_doc (group_doc (key ^| arrow) ^| value) in
746 let as_part = group_doc (await_keyword ^| as_keyword) in
747 let as_part = group_doc (collection_name ^| as_part) in
748 let middle_part = group_doc (as_part ^| arrow_part) in
749 let start_block = indent_block_no_space left_part middle_part right indt in
750 handle_compound_brace_prefix_indent start_block statement indt |> add_break
751 | SwitchStatement {
752 switch_keyword;
753 switch_left_paren;
754 switch_expression;
755 switch_right_paren;
756 switch_left_brace;
757 switch_sections;
758 switch_right_brace } ->
759 let keyword = get_doc switch_keyword in
760 let lparen= get_doc switch_left_paren in
761 let expr = get_doc switch_expression in
762 let rparen = get_doc switch_right_paren in
763 let lbrace = get_doc switch_left_brace in
764 let sections = get_doc switch_sections in
765 let rbrace = get_doc switch_right_brace in
766 (* TODO Fix this *)
767 let h = keyword ^| lparen ^| expr ^| rparen ^| space ^| lbrace in
768 let h = add_break h in
769 h ^| sections ^| rbrace
770 | SwitchSection {
771 switch_section_labels;
772 switch_section_statements;
773 switch_section_fallthrough } ->
774 (* TODO Fix this *)
775 let labels = get_doc switch_section_labels in
776 let statements = get_doc switch_section_statements in
777 let fallthrough = get_doc switch_section_fallthrough in
778 (add_break labels) ^| (add_break statements) ^| (add_break fallthrough)
779 | SwitchFallthrough {
780 fallthrough_keyword;
781 fallthrough_semicolon
782 } ->
783 let f = get_doc fallthrough_keyword in
784 let s = get_doc fallthrough_semicolon in
785 f ^^^ s
786 | ScopeResolutionExpression x ->
787 let q = get_doc x.scope_resolution_qualifier in
788 let o = get_doc x.scope_resolution_operator in
789 let n = get_doc x.scope_resolution_name in
790 group_doc (q ^^^ o ^^^ n)
791 | MemberSelectionExpression
792 { member_object; member_operator; member_name } ->
793 let ob = get_doc member_object in
794 let op = get_doc member_operator in
795 let nm = get_doc member_name in
796 group_doc (ob ^^^ op ^^^ nm)
797 | SafeMemberSelectionExpression
798 { safe_member_object; safe_member_operator; safe_member_name } ->
799 let ob = get_doc safe_member_object in
800 let op = get_doc safe_member_operator in
801 let nm = get_doc safe_member_name in
802 group_doc (ob ^^^ op ^^^ nm)
803 | EmbeddedMemberSelectionExpression
804 { embedded_member_object;
805 embedded_member_operator;
806 embedded_member_name } ->
807 let ob = get_doc embedded_member_object in
808 let op = get_doc embedded_member_operator in
809 let nm = get_doc embedded_member_name in
810 group_doc (ob ^^^ op ^^^ nm)
811 | YieldExpression x ->
812 let y = get_doc x.yield_keyword in
813 let o = get_doc x.yield_operand in
814 group_doc (y ^| o)
815 | PrintExpression {
816 print_keyword;
817 print_expression } ->
818 let t = get_doc print_keyword in
819 let e = get_doc print_expression in
820 group_doc (t ^| e)
821 | CastExpression x ->
822 let l = get_doc x.cast_left_paren in
823 let t = get_doc x.cast_type in
824 let r = get_doc x.cast_right_paren in
825 let o = get_doc x.cast_operand in
826 group_doc (l ^^^ t ^^^ r ^^^ o)
827 | LambdaExpression {
828 lambda_async;
829 lambda_coroutine;
830 lambda_signature;
831 lambda_arrow;
832 lambda_body;
833 } ->
834 let async = get_doc lambda_async in
835 let coroutine = get_doc lambda_coroutine in
836 let signature = get_doc lambda_signature in
837 let arrow = get_doc lambda_arrow in
838 let body = get_doc lambda_body in
839 group_doc (async ^| coroutine ^| signature ^| arrow ^| body)
840 | LambdaSignature
841 { lambda_left_paren; lambda_parameters; lambda_right_paren;
842 lambda_colon; lambda_type } ->
843 let left = get_doc lambda_left_paren in
844 let params = get_doc lambda_parameters in
845 let right = get_doc lambda_right_paren in
846 let colon = get_doc lambda_colon in
847 let ty = get_doc lambda_type in
848 group_doc (left ^| params ^| right ^| colon ^| ty)
849 | AnonymousFunction
850 { anonymous_async_keyword;
851 anonymous_coroutine_keyword;
852 anonymous_function_keyword;
853 anonymous_left_paren;
854 anonymous_parameters;
855 anonymous_right_paren;
856 anonymous_colon;
857 anonymous_type;
858 anonymous_use;
859 anonymous_body } ->
860 let async = get_doc anonymous_async_keyword in
861 let coroutine = get_doc anonymous_coroutine_keyword in
862 let fn = get_doc anonymous_function_keyword in
863 let left = get_doc anonymous_left_paren in
864 let params = get_doc anonymous_parameters in
865 let right = get_doc anonymous_right_paren in
866 let colon = get_doc anonymous_colon in
867 let return_type = get_doc anonymous_type in
868 let preface = group_doc ( async ^| coroutine ^| fn ) in
869 let parameters = indent_block_no_space left params right indt in
870 let type_declaration = group_doc (colon ^| return_type) in
871 let uses = get_doc anonymous_use in
872 let body = anonymous_body in
873 let before_body =
874 group_doc (
875 group_doc ( group_doc preface ^^| parameters )
876 ^| type_declaration ^| uses
877 ) in
878 handle_compound_inline_brace before_body body missing
879 | AnonymousFunctionUseClause x ->
880 let u = get_doc x.anonymous_use_keyword in
881 let l = get_doc x.anonymous_use_left_paren in
882 let v = get_doc x.anonymous_use_variables in
883 let r = get_doc x.anonymous_use_right_paren in
884 u ^| l ^^^ v ^^^ r
885 | PrefixUnaryExpression
886 { prefix_unary_operator; prefix_unary_operand } ->
887 if is_separable_prefix prefix_unary_operator then
888 get_doc prefix_unary_operator ^| get_doc prefix_unary_operand
889 else
890 get_doc prefix_unary_operator ^^^ get_doc prefix_unary_operand
891 | PostfixUnaryExpression
892 { postfix_unary_operand; postfix_unary_operator } ->
893 get_doc postfix_unary_operand ^^^ get_doc postfix_unary_operator
894 | BinaryExpression x ->
895 let left = get_doc x.binary_left_operand in
896 let op = get_doc x.binary_operator in
897 let right = get_doc x.binary_right_operand in
898 group_doc (left ^| op ^| right)
899 | InstanceofExpression x ->
900 let left = get_doc x.instanceof_left_operand in
901 let op = get_doc x.instanceof_operator in
902 let right = get_doc x.instanceof_right_operand in
903 group_doc (left ^| op ^| right)
904 | ConditionalExpression x ->
905 let tst = get_doc x.conditional_test in
906 let qm = get_doc x.conditional_question in
907 let con = get_doc x.conditional_consequence in
908 let col = get_doc x.conditional_colon in
909 let alt = get_doc x.conditional_alternative in
910 (* TODO: Could this be improved? *)
911 group_doc ( tst ^| qm ^| con ^| col ^| alt )
912 | FunctionCallExpression {
913 function_call_receiver;
914 function_call_left_paren;
915 function_call_argument_list;
916 function_call_right_paren } ->
917 let receiver = get_doc function_call_receiver in
918 let lparen = get_doc function_call_left_paren in
919 let args = get_doc function_call_argument_list in
920 let rparen = get_doc function_call_right_paren in
921 receiver ^^^ lparen ^^^ args ^^^ rparen
922 | EvalExpression {
923 eval_keyword;
924 eval_left_paren;
925 eval_argument;
926 eval_right_paren } ->
927 let keyword = get_doc eval_keyword in
928 let lparen = get_doc eval_left_paren in
929 let arg = get_doc eval_argument in
930 let rparen = get_doc eval_right_paren in
931 keyword ^^^ lparen ^^^ arg ^^^ rparen
932 | EmptyExpression {
933 empty_keyword;
934 empty_left_paren;
935 empty_argument;
936 empty_right_paren } ->
937 let keyword = get_doc empty_keyword in
938 let lparen = get_doc empty_left_paren in
939 let arg = get_doc empty_argument in
940 let rparen = get_doc empty_right_paren in
941 keyword ^^^ lparen ^^^ arg ^^^ rparen
942 | IssetExpression {
943 isset_keyword;
944 isset_left_paren;
945 isset_argument_list;
946 isset_right_paren } ->
947 let keyword = get_doc isset_keyword in
948 let lparen = get_doc isset_left_paren in
949 let args = get_doc isset_argument_list in
950 let rparen = get_doc isset_right_paren in
951 keyword ^^^ lparen ^^^ args ^^^ rparen
952 | DefineExpression {
953 define_keyword;
954 define_left_paren;
955 define_argument_list;
956 define_right_paren } ->
957 let keyword = get_doc define_keyword in
958 let lparen = get_doc define_left_paren in
959 let args = get_doc define_argument_list in
960 let rparen = get_doc define_right_paren in
961 keyword ^^^ lparen ^^^ args ^^^ rparen
962 | ParenthesizedExpression {
963 parenthesized_expression_left_paren;
964 parenthesized_expression_expression;
965 parenthesized_expression_right_paren } ->
966 let left = get_doc parenthesized_expression_left_paren in
967 let expr = get_doc parenthesized_expression_expression in
968 let right = get_doc parenthesized_expression_right_paren in
969 indent_block_no_space left expr right indt
970 | BracedExpression {
971 braced_expression_left_brace;
972 braced_expression_expression;
973 braced_expression_right_brace } ->
974 let left = get_doc braced_expression_left_brace in
975 let expr = get_doc braced_expression_expression in
976 let right = get_doc braced_expression_right_brace in
977 indent_block_no_space left expr right indt
978 | EmbeddedBracedExpression {
979 embedded_braced_expression_left_brace;
980 embedded_braced_expression_expression;
981 embedded_braced_expression_right_brace } ->
982 let left = get_doc embedded_braced_expression_left_brace in
983 let expr = get_doc embedded_braced_expression_expression in
984 let right = get_doc embedded_braced_expression_right_brace in
985 indent_block_no_space left expr right indt
986 | ListExpression
987 { list_keyword; list_left_paren; list_members; list_right_paren } ->
988 let keyword = get_doc list_keyword in
989 let left_paren = get_doc list_left_paren in
990 let members = get_doc list_members in
991 let right_paren = get_doc list_right_paren in
992 let left = group_doc (keyword ^| left_paren) in
993 indent_block_no_space left members right_paren indt
994 | CollectionLiteralExpression x ->
995 let token = get_doc x.collection_literal_name in
996 let left_brace = get_doc x.collection_literal_left_brace in
997 let expression_list = get_doc x.collection_literal_initializers in
998 let right_brace = get_doc x.collection_literal_right_brace in
999 token ^| left_brace ^| expression_list ^| right_brace
1000 | ObjectCreationExpression
1001 { object_creation_new_keyword;
1002 object_creation_type;
1003 object_creation_left_paren;
1004 object_creation_argument_list;
1005 object_creation_right_paren } ->
1006 let n = get_doc object_creation_new_keyword in
1007 let c = get_doc object_creation_type in
1008 let l = get_doc object_creation_left_paren in
1009 let a = get_doc object_creation_argument_list in
1010 let r = get_doc object_creation_right_paren in
1011 n ^| c ^^^ l ^^^ a ^^^ r
1012 | FieldInitializer
1013 { field_initializer_name; field_initializer_arrow;
1014 field_initializer_value }->
1015 let n = get_doc field_initializer_name in
1016 let a = get_doc field_initializer_arrow in
1017 let v = get_doc field_initializer_value in
1018 n ^| a ^| v
1019 | ShapeExpression
1020 { shape_expression_keyword; shape_expression_left_paren;
1021 shape_expression_fields; shape_expression_right_paren } ->
1022 let sh = get_doc shape_expression_keyword in
1023 let lp = get_doc shape_expression_left_paren in
1024 let fs = get_doc shape_expression_fields in
1025 let rp = get_doc shape_expression_right_paren in
1026 sh ^| lp ^^^ fs ^^^ rp
1027 | TupleExpression
1028 { tuple_expression_keyword; tuple_expression_left_paren;
1029 tuple_expression_items; tuple_expression_right_paren } ->
1030 let tu = get_doc tuple_expression_keyword in
1031 let lp = get_doc tuple_expression_left_paren in
1032 let xs = get_doc tuple_expression_items in
1033 let rp = get_doc tuple_expression_right_paren in
1034 tu ^| lp ^^^ xs ^^^ rp
1035 | ArrayCreationExpression x ->
1036 let left_bracket = get_doc x.array_creation_left_bracket in
1037 let right_bracket = get_doc x.array_creation_right_bracket in
1038 let members = get_doc x.array_creation_members in
1039 indent_block_no_space left_bracket members right_bracket indt
1040 | ArrayIntrinsicExpression {
1041 array_intrinsic_keyword;
1042 array_intrinsic_left_paren;
1043 array_intrinsic_members;
1044 array_intrinsic_right_paren } ->
1045 let keyword = get_doc array_intrinsic_keyword in
1046 let left = get_doc array_intrinsic_left_paren in
1047 let members = get_doc array_intrinsic_members in
1048 let right = get_doc array_intrinsic_right_paren in
1049 let left_part = group_doc (keyword ^^| left) in
1050 indent_block_no_space left_part members right indt
1051 | DarrayIntrinsicExpression {
1052 darray_intrinsic_keyword;
1053 darray_intrinsic_left_bracket;
1054 darray_intrinsic_members;
1055 darray_intrinsic_right_bracket } ->
1056 let keyword = get_doc darray_intrinsic_keyword in
1057 let left = get_doc darray_intrinsic_left_bracket in
1058 let members = get_doc darray_intrinsic_members in
1059 let right = get_doc darray_intrinsic_right_bracket in
1060 let left_part = group_doc (keyword ^^| left) in
1061 indent_block_no_space left_part members right indt
1062 | DictionaryIntrinsicExpression {
1063 dictionary_intrinsic_keyword;
1064 dictionary_intrinsic_left_bracket;
1065 dictionary_intrinsic_members;
1066 dictionary_intrinsic_right_bracket } ->
1067 let keyword = get_doc dictionary_intrinsic_keyword in
1068 let left = get_doc dictionary_intrinsic_left_bracket in
1069 let members = get_doc dictionary_intrinsic_members in
1070 let right = get_doc dictionary_intrinsic_right_bracket in
1071 let left_part = group_doc (keyword ^^| left) in
1072 indent_block_no_space left_part members right indt
1073 | KeysetIntrinsicExpression {
1074 keyset_intrinsic_keyword;
1075 keyset_intrinsic_left_bracket;
1076 keyset_intrinsic_members;
1077 keyset_intrinsic_right_bracket } ->
1078 let keyword = get_doc keyset_intrinsic_keyword in
1079 let left = get_doc keyset_intrinsic_left_bracket in
1080 let members = get_doc keyset_intrinsic_members in
1081 let right = get_doc keyset_intrinsic_right_bracket in
1082 let left_part = group_doc (keyword ^^| left) in
1083 indent_block_no_space left_part members right indt
1084 | VarrayIntrinsicExpression {
1085 varray_intrinsic_keyword;
1086 varray_intrinsic_left_bracket;
1087 varray_intrinsic_members;
1088 varray_intrinsic_right_bracket } ->
1089 let keyword = get_doc varray_intrinsic_keyword in
1090 let left = get_doc varray_intrinsic_left_bracket in
1091 let members = get_doc varray_intrinsic_members in
1092 let right = get_doc varray_intrinsic_right_bracket in
1093 let left_part = group_doc (keyword ^^| left) in
1094 indent_block_no_space left_part members right indt
1095 | VectorIntrinsicExpression {
1096 vector_intrinsic_keyword;
1097 vector_intrinsic_left_bracket;
1098 vector_intrinsic_members;
1099 vector_intrinsic_right_bracket } ->
1100 let keyword = get_doc vector_intrinsic_keyword in
1101 let left = get_doc vector_intrinsic_left_bracket in
1102 let members = get_doc vector_intrinsic_members in
1103 let right = get_doc vector_intrinsic_right_bracket in
1104 let left_part = group_doc (keyword ^^| left) in
1105 indent_block_no_space left_part members right indt
1106 | ElementInitializer x ->
1107 let k = get_doc x.element_key in
1108 let a = get_doc x.element_arrow in
1109 let v = get_doc x.element_value in
1110 k ^| a ^| v
1111 | SubscriptExpression x ->
1112 let receiver = get_doc x.subscript_receiver in
1113 let left = get_doc x.subscript_left_bracket in
1114 let index = get_doc x.subscript_index in
1115 let right = get_doc x.subscript_right_bracket in
1116 receiver ^^^ left ^^^ index ^^^ right
1117 | EmbeddedSubscriptExpression x ->
1118 let receiver = get_doc x.embedded_subscript_receiver in
1119 let left = get_doc x.embedded_subscript_left_bracket in
1120 let index = get_doc x.embedded_subscript_index in
1121 let right = get_doc x.embedded_subscript_right_bracket in
1122 receiver ^^^ left ^^^ index ^^^ right
1123 | AwaitableCreationExpression x ->
1124 let async = get_doc x.awaitable_async in
1125 let coroutine = get_doc x.awaitable_coroutine in
1126 let stmt = x.awaitable_compound_statement in
1127 handle_compound_brace_prefix_indent (async ^| coroutine) stmt indt
1128 | XHPExpression x ->
1129 let left = get_doc x.xhp_open in
1130 let expr = get_doc x.xhp_body in
1131 let right = get_doc x.xhp_close in
1132 left ^^^ expr ^^^ right
1133 | XHPOpen {
1134 xhp_open_left_angle;
1135 xhp_open_name;
1136 xhp_open_attributes;
1137 xhp_open_right_angle } ->
1138 let left = get_doc xhp_open_left_angle in
1139 let name = get_doc xhp_open_name in
1140 let attrs = get_doc xhp_open_attributes in
1141 let right = get_doc xhp_open_right_angle in
1142 group_doc (group_doc (indent_doc (left ^^^ name) attrs indt) ^| right)
1143 | XHPAttribute
1144 { xhp_attribute_name; xhp_attribute_equal; xhp_attribute_expression }->
1145 let name = get_doc xhp_attribute_name in
1146 let equals = get_doc xhp_attribute_equal in
1147 let expr = get_doc xhp_attribute_expression in
1148 group_doc (group_doc (name ^^| equals) ^^| expr)
1149 | XHPClose x ->
1150 let left = get_doc x.xhp_close_left_angle in
1151 let name = get_doc x.xhp_close_name in
1152 let right = get_doc x.xhp_close_right_angle in
1153 left ^^^ name ^^^ right
1154 | TypeConstant x ->
1155 let left = get_doc x.type_constant_left_type in
1156 let right = get_doc x.type_constant_right_type in
1157 let separator = get_doc x.type_constant_separator in
1158 left ^^^ separator ^^^ right
1159 | SimpleTypeSpecifier x -> get_doc x.simple_type_specifier
1160 | TypeConstraint { constraint_keyword; constraint_type } ->
1161 let k = get_doc constraint_keyword in
1162 let t = get_doc constraint_type in
1163 k ^| t
1164 | TypeParameter x ->
1165 let variance = get_doc x.type_variance in
1166 let name = get_doc x.type_name in
1167 let constraints = get_doc x.type_constraints in
1168 variance ^^^ name ^| constraints
1169 | NullableTypeSpecifier x ->
1170 let qm = get_doc x.nullable_question in
1171 let ty = get_doc x.nullable_type in
1172 qm ^^^ ty
1173 | SoftTypeSpecifier x ->
1174 let a = get_doc x.soft_at in
1175 let t = get_doc x.soft_type in
1176 a ^^^ t
1177 | GenericTypeSpecifier
1178 { generic_class_type;
1179 generic_argument_list } ->
1180 let name = get_doc generic_class_type in
1181 let argument = get_doc generic_argument_list in
1182 group_doc (indent_doc_no_space name argument indt)
1183 | VarrayTypeSpecifier {
1184 varray_keyword;
1185 varray_left_angle;
1186 varray_type;
1187 varray_optional_comma;
1188 varray_right_angle
1189 } ->
1190 let ar = get_doc varray_keyword in
1191 let la = get_doc varray_left_angle in
1192 let ty = get_doc varray_type in
1193 let oc = get_doc varray_optional_comma in
1194 let ra = get_doc varray_right_angle in
1195 ar ^^^ la ^^^ ty ^^^ oc ^^^ ra
1196 | VectorArrayTypeSpecifier {
1197 vector_array_keyword;
1198 vector_array_left_angle;
1199 vector_array_type;
1200 vector_array_right_angle
1201 } ->
1202 let ar = get_doc vector_array_keyword in
1203 let la = get_doc vector_array_left_angle in
1204 let ty = get_doc vector_array_type in
1205 let ra = get_doc vector_array_right_angle in
1206 ar ^^^ la ^^^ ty ^^^ ra
1207 | VectorTypeSpecifier {
1208 vector_type_keyword;
1209 vector_type_left_angle;
1210 vector_type_type;
1211 vector_type_right_angle
1212 } ->
1213 let ar = get_doc vector_type_keyword in
1214 let la = get_doc vector_type_left_angle in
1215 let ty = get_doc vector_type_type in
1216 let ra = get_doc vector_type_right_angle in
1217 ar ^^^ la ^^^ ty ^^^ ra
1218 | KeysetTypeSpecifier {
1219 keyset_type_keyword;
1220 keyset_type_left_angle;
1221 keyset_type_type;
1222 keyset_type_right_angle
1223 } ->
1224 let ar = get_doc keyset_type_keyword in
1225 let la = get_doc keyset_type_left_angle in
1226 let ty = get_doc keyset_type_type in
1227 let ra = get_doc keyset_type_right_angle in
1228 ar ^^^ la ^^^ ty ^^^ ra
1229 | DictionaryTypeSpecifier {
1230 dictionary_type_keyword;
1231 dictionary_type_left_angle;
1232 dictionary_type_members;
1233 dictionary_type_right_angle
1234 } ->
1235 let ar = get_doc dictionary_type_keyword in
1236 let la = get_doc dictionary_type_left_angle in
1237 let ms = get_doc dictionary_type_members in
1238 let ra = get_doc dictionary_type_right_angle in
1239 ar ^^^ la ^^^ ms ^^^ ra
1240 | DarrayTypeSpecifier {
1241 darray_keyword;
1242 darray_left_angle;
1243 darray_key;
1244 darray_comma;
1245 darray_value;
1246 darray_optional_comma;
1247 darray_right_angle
1248 } ->
1249 let ar = get_doc darray_keyword in
1250 let la = get_doc darray_left_angle in
1251 let kt = get_doc darray_key in
1252 let co = get_doc darray_comma in
1253 let vt = get_doc darray_value in
1254 let oc = get_doc darray_optional_comma in
1255 let ra = get_doc darray_right_angle in
1256 ar ^^^ la ^^^ kt ^^^ co ^| vt ^^^ oc ^^^ ra
1257 | MapArrayTypeSpecifier {
1258 map_array_keyword;
1259 map_array_left_angle;
1260 map_array_key;
1261 map_array_comma;
1262 map_array_value;
1263 map_array_right_angle
1264 } ->
1265 let ar = get_doc map_array_keyword in
1266 let la = get_doc map_array_left_angle in
1267 let kt = get_doc map_array_key in
1268 let co = get_doc map_array_comma in
1269 let vt = get_doc map_array_value in
1270 let ra = get_doc map_array_right_angle in
1271 ar ^^^ la ^^^ kt ^^^ co ^| vt ^^^ ra
1272 | ClosureTypeSpecifier
1273 { closure_outer_left_paren;
1274 closure_function_keyword;
1275 closure_inner_left_paren;
1276 closure_parameter_types;
1277 closure_inner_right_paren;
1278 closure_colon;
1279 closure_return_type;
1280 closure_outer_right_paren } ->
1281 let olp = get_doc closure_outer_left_paren in
1282 let fnc = get_doc closure_function_keyword in
1283 let ilp = get_doc closure_inner_left_paren in
1284 let pts = get_doc closure_parameter_types in
1285 let irp = get_doc closure_inner_right_paren in
1286 let col = get_doc closure_colon in
1287 let ret = get_doc closure_return_type in
1288 let orp = get_doc closure_outer_right_paren in
1289 olp ^^^ fnc ^^| ilp ^^^ pts ^^^ irp ^^^ col ^^^ ret ^^^ orp
1290 | ClassnameTypeSpecifier x ->
1291 let cn = get_doc x.classname_keyword in
1292 let la = get_doc x.classname_left_angle in
1293 let ty = get_doc x.classname_type in
1294 let ra = get_doc x.classname_right_angle in
1295 cn ^^^ la ^^^ ty ^^^ ra
1296 | FieldSpecifier x ->
1297 let q = get_doc x.field_question in
1298 let n = get_doc x.field_name in
1299 let a = get_doc x.field_arrow in
1300 let t = get_doc x.field_type in
1301 q ^| n ^| a ^| t
1302 | ShapeTypeSpecifier
1303 { shape_type_keyword; shape_type_left_paren;
1304 shape_type_fields; shape_type_ellipsis; shape_type_right_paren } ->
1305 let sh = get_doc shape_type_keyword in
1306 let lp = get_doc shape_type_left_paren in
1307 let fs = get_doc shape_type_fields in
1308 let ellipsis = get_doc shape_type_ellipsis in
1309 let rp = get_doc shape_type_right_paren in
1310 sh ^| lp ^^^ fs ^| ellipsis ^^^ rp
1311 | TypeArguments {
1312 type_arguments_left_angle;
1313 type_arguments_types;
1314 type_arguments_right_angle } ->
1315 let left = get_doc type_arguments_left_angle in
1316 let args = get_doc type_arguments_types in
1317 let right = get_doc type_arguments_right_angle in
1318 indent_block_no_space left args right indt
1319 | TypeParameters {
1320 type_parameters_left_angle;
1321 type_parameters_parameters;
1322 type_parameters_right_angle } ->
1323 let left = get_doc type_parameters_left_angle in
1324 let params = get_doc type_parameters_parameters in
1325 let right = get_doc type_parameters_right_angle in
1326 indent_block_no_space left params right indt
1327 | TupleTypeSpecifier x ->
1328 let left = get_doc x.tuple_left_paren in
1329 let types = get_doc x.tuple_types in
1330 let right = get_doc x.tuple_right_paren in
1331 indent_block_no_space left types right indt
1332 (* this ideally should never be called *)
1333 | CaseLabel {
1334 case_keyword;
1335 case_expression;
1336 case_colon } ->
1337 let keyword = get_doc case_keyword in
1338 let expr = get_doc case_expression in
1339 let colon = get_doc case_colon in
1340 keyword ^^^ space ^^^ expr ^^^ colon
1341 | DefaultLabel {
1342 default_keyword;
1343 default_colon } ->
1344 let keyword = get_doc default_keyword in
1345 let colon = get_doc default_colon in
1346 keyword ^^^ colon
1347 | ReturnStatement x ->
1348 let keyword = get_doc x.return_keyword in
1349 let expr = get_doc x.return_expression in
1350 let semicolon = get_doc x.return_semicolon in
1351 let back_part = expr ^^^ semicolon in
1352 group_doc (indent_doc keyword back_part indt)
1353 | GotoLabel {
1354 goto_label_name;
1355 goto_label_colon; } ->
1356 let goto_label_name = get_doc goto_label_name in
1357 let goto_label_colon = get_doc goto_label_colon in
1358 goto_label_name ^^^ goto_label_colon
1359 | GotoStatement {
1360 goto_statement_keyword;
1361 goto_statement_label_name;
1362 goto_statement_semicolon; } ->
1363 let keyword = get_doc goto_statement_keyword in
1364 let label_name = get_doc goto_statement_label_name in
1365 let semicolon = get_doc goto_statement_semicolon in
1366 keyword ^| label_name ^^^ semicolon
1367 | ThrowStatement x ->
1368 let keyword = get_doc x.throw_keyword in
1369 let expr = get_doc x.throw_expression in
1370 let semicolon = get_doc x.throw_semicolon in
1371 let back_part = expr ^^^ semicolon in
1372 group_doc (indent_doc keyword back_part indt)
1373 | BreakStatement x ->
1374 let b = get_doc x.break_keyword in
1375 let l = get_doc x.break_level in
1376 let s = get_doc x.break_semicolon in
1377 if is_missing x.break_level then group_doc (b ^^^ l ^^^ s)
1378 else group_doc (b ^| l ^^^ s)
1379 | ContinueStatement x ->
1380 let c = get_doc x.continue_keyword in
1381 let l = get_doc x.continue_level in
1382 let s = get_doc x.continue_semicolon in
1383 if is_missing x.continue_level then group_doc (c ^^^ l ^^^ s)
1384 else group_doc (c ^| l ^^^ s)
1385 | FunctionStaticStatement {
1386 static_static_keyword;
1387 static_declarations;
1388 static_semicolon } ->
1389 let st = get_doc static_static_keyword in
1390 let ds = get_doc static_declarations in
1391 let se = get_doc static_semicolon in
1392 st ^| ds ^^^ se
1393 | StaticDeclarator
1394 { static_name; static_initializer } ->
1395 let n = get_doc static_name in
1396 let i = get_doc static_initializer in
1397 group_doc (n ^| i)
1398 | EchoStatement x ->
1399 let echo = get_doc x.echo_keyword in
1400 let expr_list = get_doc x.echo_expressions in
1401 let semicolon = get_doc x.echo_semicolon in
1402 echo ^| expr_list ^^^ semicolon
1403 | GlobalStatement {
1404 global_keyword;
1405 global_variables;
1406 global_semicolon } ->
1407 let g = get_doc global_keyword in
1408 let v = get_doc global_variables in
1409 let s = get_doc global_semicolon in
1410 g ^| v ^^^ s
1411 | SimpleInitializer
1412 { simple_initializer_equal; simple_initializer_value } ->
1413 let e = get_doc simple_initializer_equal in
1414 let v = get_doc simple_initializer_value in
1415 group_doc (e ^| v)
1417 (* sep is the compulsory separator separating the children in the list *)
1418 and get_from_children_no_space children =
1419 let fold_fun acc el = acc ^^^ get_doc el in
1420 group_doc (List.fold_left fold_fun (make_simple nil) children)
1421 and get_from_children_with_sep sep children =
1422 let fold_fun acc el = (acc ^^^ sep) ^| get_doc el in
1423 group_doc (List.fold_left fold_fun (make_simple nil) children)
1424 and get_from_children node = get_from_children_with_sep (make_simple nil) node
1425 (* if it is a compound statement, the curly braces do not need indent *)
1426 and peek_and_decide_indent x default =
1427 match syntax x with
1428 | CompoundStatement _ -> 0
1429 | _ -> default
1430 (* puts [prefix] on the same line as a compound brace. If the statement is not
1431 * compound, put an optional newline and group the result *)
1432 and handle_compound_inline_brace prefix statement postfix =
1433 match syntax statement with
1434 | CompoundStatement compound_stmt ->
1435 let left = get_doc compound_stmt.compound_left_brace in
1436 let right = get_doc compound_stmt.compound_right_brace in
1437 let statement = get_doc compound_stmt.compound_statements in
1438 let prefix = group_doc (prefix ^| left) in
1439 let postfix = group_doc (right ^| postfix) in
1440 indent_block prefix statement postfix indt
1441 | _ -> group_doc (prefix ^| get_doc statement ^| postfix)
1442 (* keep open brace of compound statement on the same line as the prefix.
1443 * If statement is not a compound statement, then indent it with [indt] *)
1444 and handle_compound_brace_prefix_indent prefix statement indt =
1445 if is_compound_statement statement then
1446 handle_compound_inline_brace prefix statement missing
1447 else
1448 group_doc (indent_doc prefix (get_doc statement) indt)
1450 let pretty_print node =
1451 let empty_string = make_simple (text "") in
1452 let to_print = node |> get_doc |> add_break in
1453 let to_print = to_print ^| empty_string in
1454 let to_print = combine to_print in
1455 pretty 0 to_print