123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137openPpxlibletis_punned_labelled_expressionelbl=matche.pexp_descwith|Pexp_ident{txt;_}|Pexp_constraint({pexp_desc=Pexp_ident{txt;_};_},_)|Pexp_coerce({pexp_desc=Pexp_ident{txt;_};_},_,_)->Reason_syntax_util.parse_lidlbl=txt|_->false(* We manually check the length of `Thing.map(foo, bar, baz`,
* in `Thing.map(foo, bar, baz, (a) => doStuff(a))`
* because Easyformat doesn't have a hook to change printing when a list breaks
*
* we check if all arguments aside from the final one are either strings or identifiers,
* where the sum of the string contents and identifier names are less than the print width
*)letfunAppCallbackExceedsWidth~printWidth~args~funExpr()=letfunLen=matchfunExpr.pexp_descwith|Pexp_identident->letidentList=Longident.flatten_exnident.txtinletlengthOfDots=List.lengthidentList-1inletlen=List.fold_left(funacccurr->acc+String.lengthcurr)lengthOfDotsidentListinlen|_->-1in(* eats an argument & substract its length from the printWidth
* as soon as the print width reaches a sub-zero value,
* we know the print width is exceeded & returns *)letrecauxlen=function|_whenlen<0->true|[]->false|arg::args->(matchargwith|label,({pexp_desc=Pexp_identident;_}ase)->letidentLen=List.fold_left(funacccurr->acc+String.lengthcurr)len(Longident.flatten_exnident.txt)in(matchlabelwith|Nolabel->aux(len-identLen)args|Labelledswhenis_punned_labelled_expressiones->aux(len-(identLen+1))args|Labelleds->aux(len-(identLen+2+String.lengths))args|Optionals->aux(len-(identLen+3+String.lengths))args)|label,{pexp_desc=Pexp_constant(Pconst_string(str,_,_));_}->letstrLen=String.lengthstrin(matchlabelwith|Nolabel->aux(len-strLen)args|Labelleds->aux(len-(strLen+2+String.lengths))args|Optionals->aux(len-(strLen+3+String.lengths))args)|_->(* if we encounter a non-string or non-identifier argument exit *)true)inaux(printWidth-funLen)args(*
* Whether or not an identiier is small enough to justify omitting the
* trailing comma for single identifier patterns. For single identifier
* patterns, usually the identifier is not "far right" in the document, and
* is one of the last things to require breaking. We can omit the trailing comma
* in these cases because it likely will never render anyways and therefore the
* space taken up by the trailing comma doesn't disrupt wrapping length calculations.
*
* For example, the `X` hardly ever benefits from a trailing comma.
* | X(y) =>
*)letsingleTokenPatternOmmitTrailtxt=String.lengthtxt<4(* Indicates whether an expression can be printed with the uncurried
* dot notation. At the moment uncurried function application & definition
* only makes sense in the context of a Pexp_apply or Pexp_fun
*
* Examples:
* [@bs] add(2, 3); -> add(. 2, 3); (* Pexp_apply *)
* setTimeout([@bs] () => Js.log("hola"), 1000); (* Pexp_fun *)
* -> setTimeout((.) => Js.log("hola"), 1000);
*)letbsExprCanBeUncurriedexpr=matchParsetree.(expr.pexp_desc)with|Pexp_fun_|Pexp_apply_->true|_->falseletisUnderscoreIdentexpr=matchParsetree.(expr.pexp_desc)with|Pexp_ident{txt=Lident"_";_}->true|_->falseletisPipeFirste=matchParsetree.(e.pexp_desc)with|Pexp_ident{txt=Longident.Lident"|.";_}->true|Pexp_apply({pexp_desc=Pexp_ident{txt=Longident.Lident"|.";_};_},_)->true|_->falseletisUnderscoreApplicationexpr=matchexprwith|{pexp_attributes=[];pexp_desc=Pexp_fun(Nolabel,None,{ppat_desc=Ppat_var{txt="__x";_};ppat_attributes=[];_},_);_}->true|_->false(* <div> {items->Belt.Array.map(ReasonReact.string)->ReasonReact.array} </div>;
* An application with pipe first inside jsx children requires special treatment.
* Jsx children don't allow expression application, hence we need the braces
* preserved in this case. *)letisPipeFirstWithNonSimpleJSXChilde=matchParsetree.(e.pexp_desc)with|Pexp_apply({pexp_desc=Pexp_ident{txt=Longident.Lident"|.";_};_},[(Nolabel,{pexp_desc=Pexp_apply_;_});_])->true(* Handle <div> {url->a(b, _)} </div>;
* underscore sugar needs protection *)|Pexp_apply({pexp_desc=Pexp_ident{txt=Longident.Lident"|.";_};_},[_;(Nolabel,fe)])whenisUnderscoreApplicationfe->true|_->false