Legend:
Page
Library
Module
Module type
Parameter
Class
Class type
Source
Source file ppx_js_style.ml
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546openBaseopenPpxlibletannotated_ignores=reftrueletcheck_comments=reffalseletcompat_32=reffalseletallow_toplevel_expression=reffalseletcheck_underscored_literal=reftrueletcold_instead_of_inline_never=reftrueletrequire_dated_deprecation=refIn_janestreet.in_janestreetletallow_letop_uses=ref(notIn_janestreet.in_janestreet)leterrorf~locfmt=Location.raise_errorf~loc(Caml.(^^)"Jane Street style: "fmt);;moduleIgnored_reason=structtypet=Argument_to_ignore|Underscore_patternletfail~loc_t=errorf~loc"Ignored expression must come with a type annotation"endmoduleInvalid_deprecated=structtypet=|Not_a_string|Missing_date|Invalid_monthletfail~loc=function|Not_a_string->errorf~loc"Invalid [@@deprecated payload], must be a string"|Missing_date->errorf~loc"deprecated message must start with the date in this format: \
[since YYYY-MM]"|Invalid_month->errorf~loc"invalid month in deprecation date"endmoduleInvalid_constant=structtypet=string*stringletfail~loc((s,typ):t)=Location.raise_errorf~loc"Integer literal %s exceeds the range of representable \
integers of type %s on 32bit architectures"stypendmoduleSuspicious_literal=structtypet=string*stringletfail~loc((s,typ):t)=Location.raise_errorf~loc"The %s literal %s contains underscores at suspicious positions"typsendmoduleInvalid_ocamlformat_attribute=structtypet=stringletfail~loc(reason:t)=Location.raise_errorf~loc"Invalid ocamlformat attribute. %s"reasonletkind{attr_name=name;attr_payload=payload;attr_loc=_;}=matchname.txt,payloadwith|"ocamlformat",PStr([%str"disable"]|[%str"enable"])->`Enable_disable|"ocamlformat",_->`Other|_->`Not_ocamlformatendtypeerror=|Invalid_deprecatedofInvalid_deprecated.t|Missing_type_annotationofIgnored_reason.t|Invalid_constantofInvalid_constant.t|Suspicious_literalofSuspicious_literal.t|Invalid_ocamlformat_attributeofInvalid_ocamlformat_attribute.t|Docstring_on_open|Use_of_letopof{op_name:string}letfail~loc=function|Invalid_deprecatede->Invalid_deprecated.faile~loc|Missing_type_annotatione->Ignored_reason.faile~loc|Invalid_constante->Invalid_constant.faile~loc|Suspicious_literale->Suspicious_literal.faile~loc|Invalid_ocamlformat_attributee->Invalid_ocamlformat_attribute.faile~loc|Docstring_on_open->errorf~loc"A documentation comment is attached to this [open] which will be dropped by odoc."|Use_of_letop{op_name}->errorf~loc"This use of ( %s ) is forbidden.@.\
ppx_let is currently more featureful, please use that instead to keep a consistent \
style"op_name;;letlocal_ocamlformat_config_disallowed=Invalid_ocamlformat_attribute"Ocamlformat cannot be configured locally"letcheck_deprecated_string~f~locs=matchCaml.Scanf.sscanfs"[since %u-%u]"(funym->(y,m))with|exception_->f~loc(Invalid_deprecatedMissing_date)|(_year,month)->ifmonth=0||month>12thenf~loc(Invalid_deprecatedInvalid_month);;letignored_expr_must_be_annotatedignored_reason(expr:Parsetree.expression)~f=matchexpr.pexp_descwith(* explicitely annotated -> good *)|Pexp_constraint_|Pexp_coerce_(* no need to warn people trying to silence other warnings *)|Pexp_construct_|Pexp_ident_|Pexp_fun_|Pexp_function_->()|_->f~loc:expr.pexp_loc(Missing_type_annotationignored_reason);;moduleConstant=structletmax_int_31=Int64.(-)(Int64.shift_left1L30)1Lletmin_int_31=Int64.neg(Int64.shift_left1L30)letcheck_compat_32~locc=if!compat_32thenmatchcwith|Pconst_integer(s,Some'n')->begintryignore(Int32.of_strings)with_->fail~loc(Invalid_constant(s,"nativeint"))end|Pconst_integer(s,None)->begintryleti=Int64.of_stringsinifInt64.(i<min_int_31||i>max_int_31)thenfailwith"out of bound"with_->fail~loc(Invalid_constant(s,"int"))end|_->()letcheck_underscored~locc=if!check_underscored_literalthen(letcheck_segment~name~start~stop~kinds=(* start and stop are inclusive *)letincr=ifstart<stopthen1else-1inletmodulo=matchkindwith|`Decimal->3|`Hexadecimal|`Binary|`Octal->2inletrecloopstring_pos~number_offset=letnumber_offset=matchs.[string_pos]with|'0'..'9'|'a'..'f'|'A'..'F'->number_offset+1|'_'->ifnumber_offset%modulo<>0thenfail~loc(Suspicious_literal(s,name))elsenumber_offset|_->assertfalseinifstop<>string_posthenloop(string_pos+incr)~number_offsetinloopstart~number_offset:0inletparse_prefixs=leti=matchs.[0]with|'-'|'+'->1|_->0inifString.lengths>=i+2thenbeginmatchs.[i],s.[i+1]with|'0',('x'|'X')->`Hexadecimal,i+2|'0',('b'|'B')->`Binary,i+2|'0',('o'|'O')->`Octal,i+2|_->`Decimal,iendelse`Decimal,iinletshould_check=lethas_double_underscoress=String.is_substring~substring:"__"sinlethas_underscores=String.exists~f:(func->Char.(=)c'_')sinfuns->has_underscores&¬(has_double_underscoress)inmatchcwith|Pconst_integer(s,_)->ifshould_checksthenletkind,lower=parse_prefixsincheck_segment~name:"integer"~start:(String.lengths-1)~stop:lower~kinds|Pconst_float(s,_)->ifshould_checksthenletkind,lower=parse_prefixsinletupper=(* only validate the mantissa *)letpower_split=matchkindwith|`Decimal->String.lfindis~f:(fun_c->matchcwith'e'|'E'->true|_->false)|`Hexadecimal->String.lfindis~f:(fun_c->matchcwith'p'|'P'->true|_->false)|`Binary|`Octal->assertfalseinmatchpower_splitwith|None->String.lengths-1|Somei->i-1inletname="float"inbeginmatchString.index_fromslower'.'with|None->check_segment~name~start:upper~stop:lower~kinds|Somei->iflower<>ithencheck_segment~name~start:(i-1)~stop:lower~kinds;ifupper<>ithencheck_segment~name~start:(i+1)~stop:upper~kindsend|Pconst_char_|Pconst_string_->())letcheck~locc=check_compat_32~locc;check_underscored~loccendletis_deprecated=function|"ocaml.deprecated"|"deprecated"->true|_->falseletis_inline=function|"ocaml.inline"|"inline"->true|_->falseletcheck_deprecatedattr=ifis_deprecatedattr.attr_name.txtthenerrorf~loc:(loc_of_attributeattr)"Invalid deprecated attribute, it will be ignored by the compiler"letis_mlt_or_mdxfname=String.is_suffixfname~suffix:".mlt"||String.is_suffixfname~suffix:".mdx"||String.equal"//toplevel//"fnameletiter_style_errors~f=object(self)inheritAst_traverse.iterassupermethod!attribute({attr_name=name;attr_payload=payload;attr_loc=_}asattr)=letloc=loc_of_attributeattrin(if!require_dated_deprecation&&is_deprecatedname.txtthenmatchAst_pattern.(parse(single_expr_payload(estring__')))locpayload(funs->s)with|exception_->f~loc(Invalid_deprecatedNot_a_string)|{Location.loc;txt=s}->check_deprecated_string~f~locs);(matchInvalid_ocamlformat_attribute.kindattrwith|`Enable_disable->f~loc(Invalid_ocamlformat_attribute"Ocamlformat can only be disabled at toplevel\n\
(e.g [@@@ocamlformat \"disable\"])")|`Other->f~loclocal_ocamlformat_config_disallowed|`Not_ocamlformat->())method!payloadp=matchpwith|PStrl->(* toplevel expressions in payload are fine. *)List.iterl~f:(funitem->self#check_structure_itemitem~allow_toplevel_expression:true)|_->super#payloadpmethod!open_descriptionod=if!check_commentsthen(lethas_doc_comments=List.existsod.popen_attributes~f:(fun{attr_name;_}->matchattr_name.txtwith|"ocaml.doc"|"doc"->true|_->false)inifhas_doc_commentsthenf~loc:od.popen_locDocstring_on_open);super#open_descriptionodmethod!value_bindingvb=if!annotated_ignoresthen(letloc=vb.Parsetree.pvb_locinmatchAst_pattern.(parseppat_any)locvb.Parsetree.pvb_pat()with|exception_->()|()->ignored_expr_must_be_annotatedUnderscore_pattern~fvb.Parsetree.pvb_expr);super#value_bindingvbmethod!expressione=beginmatchewith|{pexp_desc=Pexp_constantc;pexp_loc;_}->Constant.check~loc:pexp_locc|[%exprignore[%e?ignored]]when!annotated_ignores->ignored_expr_must_be_annotatedArgument_to_ignore~fignored|{pexp_desc=Pexp_letop{let_;_};_}whennot!allow_letop_uses->fail~loc:let_.pbop_op.loc(Use_of_letop{op_name=let_.pbop_op.txt})|_->()end;super#expressionemethod!patterne=beginmatchewith|{ppat_desc=Ppat_constantc;ppat_loc;_}->Constant.check~loc:ppat_locc|_->()end;super#patternemethod!core_typet=List.itert.ptyp_attributes~f:check_deprecated;super#core_typetmethodprivatecheck_structure_itemt~allow_toplevel_expression=(matcht.pstr_descwith|Pstr_eval(_,_)whennotallow_toplevel_expression&¬(is_mlt_or_mdxt.pstr_loc.Location.loc_start.Lexing.pos_fname)->errorf~loc:t.pstr_loc"Toplevel expression are not allowed here."|Pstr_attributea->(matchInvalid_ocamlformat_attribute.kindawith|`Enable_disable->()|`Other->f~loc:t.pstr_loclocal_ocamlformat_config_disallowed|`Not_ocamlformat->super#structure_itemt)|_->super#structure_itemt)method!structure_itemt=self#check_structure_itemt~allow_toplevel_expression:!allow_toplevel_expressionmethod!signature_itemt=(matcht.psig_descwith|Psig_attributea->(matchInvalid_ocamlformat_attribute.kindawith|`Enable_disable->()|`Other->f~loc:t.psig_loclocal_ocamlformat_config_disallowed|`Not_ocamlformat->super#signature_itemt)|_->super#signature_itemt)endletcheck=iter_style_errors~f:failletenforce_cold=objectinherit[Driver.Lint_error.tlist]Ast_traverse.foldmethod!attributeattracc=letloc=loc_of_attributeattrinif!cold_instead_of_inline_never&&is_inlineattr.attr_name.txtthenmatchAst_pattern.(parse(single_expr_payload(pexp_ident__')))locattr.attr_payloadFn.idwith|exception_->acc|{Location.loc;txt=Lident"never"}->(Driver.Lint_error.of_stringloc"Attribute error: please use [@cold] instead of [@inline never]")::acc|_->accelseaccendmoduleComments_checking=structleterrorf~locfmt=Location.raise_errorf~loc(Caml.(^^)"Documentation error: "fmt)(* Assumption in the following functions: [s <> ""] *)letis_cr_comments=lets=String.stripsin(String.is_prefixs~prefix:"CR")||(String.is_prefixs~prefix:"XX")||(String.is_prefixs~prefix:"XCR")||(String.is_prefixs~prefix:"JS-only")letis_cinapss=Char.equals.[0]'$'letis_doc_comments=Char.equals.[0]'*'letis_ignored_comments=Char.equals.[0]'_'letcan_appear_in_mlis=is_doc_comments||is_ignored_comments||is_cr_comments||is_cinapssletsyntax_check_doc_comment~loccomment=matchOctavius.parse(Lexing.from_stringcomment)with|Ok_->()|Error{Octavius.Errors.error;location}->letoctavius_msg=Octavius.Errors.messageerrorinletoctavius_loc=let{Octavius.Errors.start;finish}=locationinletloc_start=loc.Location.loc_startinletopenLexinginletloc_start=letpos_bol=ifstart.line=1thenloc_start.pos_bolelse0in{loc_startwithpos_bol;pos_lnum=loc_start.pos_lnum+start.line-1;pos_cnum=ifstart.line=1thenloc_start.pos_cnum+start.columnelsestart.column}inletloc_end=letpos_bol=iffinish.line=1thenloc_start.pos_bolelse0in{loc_startwithpos_bol;pos_lnum=loc_start.pos_lnum+finish.line-1;pos_cnum=iffinish.line=1thenloc_start.pos_cnum+finish.columnelsefinish.column}in{locwithLocation.loc_start;loc_end}inerrorf~loc:octavius_loc"%s\nYou can look at \
http://caml.inria.fr/pub/docs/manual-ocaml/ocamldoc.html#sec318\n\
for a description of the recognized syntax."octavius_msgletis_intf_dot_mlfname=String.is_suffix(Caml.Filename.chop_extensionfname)~suffix:"_intf"letcheck_all?(intf=false)()=List.iter~f:(fun(comment,loc)->letintf=intf||is_intf_dot_mlloc.Location.loc_start.Lexing.pos_fnameinif(String.(<>)comment"")then((* Ensures that all comments present in the file are either ocamldoc comments
or (*_ *) comments. *)ifintf&¬(can_appear_in_mlicomment)thenbeginerrorf~loc"That kind of comment shouldn't be present in interfaces.\n\
Either turn it to a documentation comment or use the special (*_ *) form."end;ifis_doc_commentcommentthensyntax_check_doc_comment~loccomment))(Lexer.comments())endlet()=(* We rely on the fact that let%test and similar things are preprocessed before we run,
because ppx_driver applies the [~extension] arguments of
[Driver.register_transformation] before applying the [~impl] argument that
ppx_js_style uses.
It means that [let%test _ = ..] doesn't count as unannotated ignore, although
[let%bind _ = ..] also doesn't count as unannotated ignore for the same reason. *)Driver.add_arg"-annotated-ignores"(Setannotated_ignores)~doc:" If set, forces all ignored expressions (either under ignore or \
inside a \"let _ = ...\") to have a type annotation. (This is the default.)";;let()=letdisable_annotated_ignores()=annotated_ignores:=falseinDriver.add_arg"-allow-unannotated-ignores"(Unitdisable_annotated_ignores)~doc:" If set, allows ignored expressions (either under ignore or inside a \"let _ = \
...\") not to have a type annotation.";;let()=Driver.add_arg"-compat-32"(Setcompat_32)~doc:" If set, checks that all constants are representable on 32bit architectures.";;(* Enable warning 50 by default, one can opt-out with [-dont-check-doc-comments-attachment] *)let()=(* A bit hackish: as we're running ppx_driver with -pp the parsing is done
by ppx_driver and not ocaml itself, so giving "-w @50" to ocaml (as we
did up to now) had no incidence.
We want to enable the warning here. For some reason one can't just enable
a warning programatically, one has to call [parse_options]... *)ignore(Ocaml_common.Warnings.parse_optionsfalse"+50")let()=letdisable_w50()=ignore(Ocaml_common.Warnings.parse_optionsfalse"-50")inDriver.add_arg"-dont-check-doc-comments-attachment"(Unitdisable_w50)~doc:" ignore warning 50 on the file.";;let()=letdisable_check_underscored_literal()=check_underscored_literal:=falseinDriver.add_arg"-dont-check-underscored-literal"(Unitdisable_check_underscored_literal)~doc:" do not check position of underscores in numbers.";;let()=letenable_checks()=check_comments:=trueinDriver.add_arg"-check-doc-comments"(Unitenable_checks)~doc:" If set, ensures that all comments in .mli files are either \
documentation or (*_ *) comments. Also check the syntax of doc comments.";;let()=letallow_top_expr()=allow_toplevel_expression:=trueinDriver.add_arg"-allow-toplevel-expression"(Unitallow_top_expr)~doc:" If set, allow toplevel expression.";;let()=letenable()=require_dated_deprecation:=trueinletdisable()=require_dated_deprecation:=falseinDriver.add_arg"-dated-deprecation"(Unitenable)~doc:{| If set, ensures that all `[@@deprecated]` attributes must contain \
the date of deprecation, using the format `"[since MM-YYYY] ..."`.|};Driver.add_arg"-no-dated-deprecation"(Unitdisable)~doc:" inverse of -dated-deprecation."let()=letallow()=allow_letop_uses:=trueinletforbid()=allow_letop_uses:=falseinDriver.add_arg"-allow-let-operators"(Unitallow)~doc:{| allow uses of let-operators|};Driver.add_arg"-forbid-let-operators"(Unitforbid)~doc:{| forbid uses of let-operators|}let()=Driver.register_transformation"js_style"~intf:(funsg->check#signaturesg;if!check_commentsthenComments_checking.check_all~intf:true();sg)~impl:(funst->check#structurest;if!check_commentsthenComments_checking.check_all();st)(* note: we do not use ~impl because we want the check to run before ppx
processing (ppx_cold will replace `[@cold]` with `[@inline never] ...`)*)~lint_impl:(funst->enforce_cold#structurest[]);;