123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116(************************************************************************)(* * The Coq Proof Assistant / The Coq Development Team *)(* v * INRIA, CNRS and contributors - Copyright 1999-2018 *)(* <O___,, * (see CREDITS file for the list of authors) *)(* \VV/ **************************************************************)(* // * This file is distributed under the terms of the *)(* * GNU Lesser General Public License Version 2.1 *)(* * (see LICENSE file for the text of the license) *)(************************************************************************)(************************************************************************)(* Coq Language Server Protocol *)(* Copyright 2019 MINES ParisTech -- Dual License LGPL 2.1 / GPL3+ *)(* Copyright 2019-2022 Inria -- Dual License LGPL 2.1 / GPL3+ *)(* Written by: Emilio J. Gallego Arias *)(************************************************************************)moduleF=FormatmoduleJ=Yojson.SafemoduleTraceValue=structtypet=|Off|Messages|Verboseletparse=function|"messages"->Messages|"verbose"->Verbose|"off"->Off|_->raise(Invalid_argument"TraceValue.parse")letto_string=function|Off->"off"|Messages->"messages"|Verbose->"verbose"endletoc=refF.std_formatterletset_log_channelc=oc:=clettrace_value=refTraceValue.Offletset_trace_valuevalue=trace_value:=valueletread_request_rawic=letcl=input_lineicinletsin=Scanf.Scanning.from_stringclinletraw_obj=Scanf.bscanfsin"Content-Length: %d\r"(funsize->letbuf=Bytes.createsizein(* Consume the second \r\n or header *)letohdr=input_lineicin(* If the second line is a return, then no more headers *)let()=ifohdr.[0]='\r'then()else(* Fixme (or use ocaml-lsp) Skip the Content-type header *)ignore(input_lineic)inreally_inputicbuf0size;Bytes.to_stringbuf)inJ.from_stringraw_objexceptionReadErrorofstringletread_requestic=tryread_request_rawicwith(* if the end of input is encountered while some more characters are needed to
read the current conversion specification, or the lsp server closes *)|End_of_file->raise(ReadError"EOF")(* if the input does not match the format. *)|Scanf.Scan_failuremsg(* if a conversion to a number is not possible. *)|Failuremsg(* if the format string is invalid. *)|Invalid_argumentmsg->raise(ReadErrormsg)letmut=Mutex.create()letlog=ref(fun__->())letsend_jsonfmtobj=Mutex.lockmut;ifFleche.Debug.sendthen!log"send"obj;letmsg=F.asprintf"%a"J.(pretty_print~std:true)objinletsize=String.lengthmsginF.fprintffmt"Content-Length: %d\r\n\r\n%s%!"sizemsg;Mutex.unlockmutletlogMessage~lvl~message=letmethod_="window/logMessage"inletparams=[("type",`Intlvl);("message",`Stringmessage)]inletmsg=Base.mk_notification~method_~paramsinsend_json!ocmsgletlogTrace~message~extra=letmethod_="$/logTrace"inletparams=match(!trace_value,extra)with|Verbose,Someextra->[("message",`Stringmessage);("verbose",`Stringextra)]|_,_->[("message",`Stringmessage)]inBase.mk_notification~method_~params|>send_json!oclettracehdr?extramsg=letmessage=Format.asprintf"[%s]: @[%s@]"hdrmsginlogTrace~message~extralettrace_objecthdrobj=letmessage=Format.asprintf"[%s]: @[%a@]"hdrYojson.Safe.(pretty_print~std:false)objin(* Fixme, use the extra parameter *)tracehdrmessagelet()=log:=trace_object