123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102# 1 "src/extend/extend_helper.ml"openParsetree(** Generate an extension node that will be reported as a syntax error by
Merlin. *)letsyntax_errormsgloc:extension=letstr=Location.mkloc"merlin.syntax-error"locinletpayload=PStr[{pstr_loc=Location.none;pstr_desc=Pstr_eval(Ast_helper.(Exp.constant(const_stringmsg)),[])}]in(str,payload)(** Physical locations might be too precise for some features.
For instance in:
let x = f in y
^1 ^2
Merlin cannot distinguish position ^1 from ^2 in the normal AST,
because IN doesn't appear in abstract syntax. This is a problem when
completing, because a different environment should be selected for both
positions.
One can add relaxed_location attributes to make some locations closer to
the concrete syntax.
Here is the same line annotated with physical and relaxed locations:
let x = f in y
[ ] [ ] -- physical locations for f and y nodes
[ ][ ] -- relaxed locations for f and y nodes
*)letrelaxed_locationloc:attribute=letstr=Location.mkloc"merlin.relaxed-location"locinAst_helper.Attr.mkstr(PStr[])(** If some code should be ignored by merlin when reporting information to
the user, put a hide_node attribute.
This is useful for generated/desugared code which doesn't correspond to
anything in concrete syntax (example use-case: encoding of some
js_of_ocaml constructs).
*)lethide_node:attribute=Ast_helper.Attr.mk(Location.mknoloc"merlin.hide")(PStr[])(** The converse: when merlin should focus on a specific node of the AST.
The main use case is also for js_of_ocaml.
Assuming <code> is translated to:
let module M = struct
let prolog = ... (* boilerplate *)
let code = <mapping-of-code>
let epilog = ... (* boilerplate *)
end
in M.boilerplate
To make merlin focus on [M.code] and ignore the boilerplate ([M.prolog]
and [M.epilog]), add a [focus_node] attribute to the [M.code] item.
*)letfocus_node:attribute=Ast_helper.Attr.mk(Location.mknoloc"merlin.focus")(PStr[])(* Projections for merlin attributes and extensions *)letclassify_extension((id,_):extension):[`Other|`Syntax_error]=matchid.Location.txtwith|"merlin.syntax-error"->`Syntax_error|_->`Otherletclassify_attributeattr:[`Other|`Relaxed_location|`Hide|`Focus]=letid,_=Ast_helper.Attr.as_tupleattrinmatchid.Location.txtwith|"merlin.relaxed-location"->`Relaxed_location|"merlin.hide"->`Hide|"merlin.focus"->`Focus|_->`Otherletextract_syntax_error((id,payload):extension):string*Location.t=ifid.Location.txt<>"merlin.syntax-error"theninvalid_arg"Merlin_extend.Reader_helper.extract_syntax_error";letinvalid_msg="Warning: extension produced an incorrect syntax-error node"inletmsg=matchAst_helper.extract_str_payloadpayloadwith|Some(msg,_loc)->msg|None->invalid_msgin(msg,id.Location.loc)letextract_relaxed_locationattr:Location.t=matchAst_helper.Attr.as_tupleattrwith|{Location.txt="merlin.relaxed-location";loc},_->loc|_->invalid_arg"Merlin_extend.Reader_helper.extract_relaxed_location"