123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115(**************************************************************************)(* *)(* VSCoq *)(* *)(* Copyright INRIA and contributors *)(* (see version control and README file for authors & dates) *)(* *)(**************************************************************************)(* *)(* This file is distributed under the terms of the MIT License. *)(* See LICENSE file. *)(* *)(**************************************************************************)openTypesletlsp_initialization_done=reffalseletinitialization_feedback_queue=Queue.create()letinit_log=trySome(letoc=open_out@@Filename.temp_file"vscoq_init_log."".txt"inoutput_stringoc"command line:\n";output_stringoc(String.concat" "(Sys.argv|>Array.to_list));output_stringoc"\nstatic initialization:\n";oc)with_->Noneletwrite_to_init_logstr=Option.iter(funoc->output_stringocstr;output_charoc'\n';flushoc)init_logletrecis_enabledname=function|[]->false|"-vscoq-d"::"all"::_->true|"-vscoq-d"::v::rest->List.memname(String.split_on_char','v)||is_enablednamerest|_::rest->is_enablednamerestletlogs=ref[]lethandle_events=Printf.eprintf"%s\n"sletmk_logname=logs:=name::!logs;letflag=is_enabledname(Array.to_listSys.argv)inletflag_init=is_enabled"init"(Array.to_listSys.argv)inwrite_to_init_log("log "^name^" is "^ifflagthen"on"else"off");Log(funmsg->letshould_print_log=flag||(flag_init&¬!lsp_initialization_done)inifshould_print_logthenbeginlettxt=Format.asprintf"[%-20s, %d, %f] %s"name(Unix.getpid())(Unix.gettimeofday())msginifnot!lsp_initialization_donethenbeginwrite_to_init_logtxt;Queue.pushtxtinitialization_feedback_queue(* Emission must be delayed as per LSP spec *)endelsehandle_eventtxtendelse())letlogs()=List.sortString.compare!logstypeevent=stringtypeevents=eventSel.Event.tlist[%%ifcoq="8.18"||coq="8.19"||coq="8.20"]letfeedback_add_feeder_on_Messagef=Feedback.add_feeder(funfb->matchfb.Feedback.contentswith|Feedback.Message(a,b,c)->ffb.Feedback.routefb.Feedback.span_idfb.Feedback.doc_idab[]c|_->())[%%else]letfeedback_add_feeder_on_Messagef=Feedback.add_feeder(funfb->matchfb.Feedback.contentswith|Feedback.Message(a,b,c,d)->ffb.Feedback.routefb.Feedback.span_idfb.Feedback.doc_idabcd|_->())[%%endif]letinstall_debug_feedbackf=feedback_add_feeder_on_Message(fun_route_span_doclvlloc_qfm->matchlvl,locwith|Feedback.Debug,None->fPp.(string_of_ppcmdsm)|_->())(* We go through a queue in case we receive a debug feedback from Coq before we
replied to Initialize *)letcoq_debug_feedback_queue=Queue.create()letmain_debug_feeder=install_debug_feedback(funtxt->Queue.pushtxtcoq_debug_feedback_queue)letdebug:eventSel.Event.t=Sel.On.queue~name:"debug"~priority:PriorityManager.feedbackcoq_debug_feedback_queue(funx->x)letcancel_debug_event=Sel.Event.get_cancellation_handledebugletlsp_initialization_done()=lsp_initialization_done:=true;Option.iterclose_out_noerrinit_log;Queue.iterhandle_eventinitialization_feedback_queue;Queue.clearinitialization_feedback_queue;[debug]letworker_initialization_begins()=Sel.Event.cancelcancel_debug_event;Feedback.del_feedermain_debug_feeder;(* We do not want to inherit master's Feedback reader (feeder), otherwise we
would output on the worker's stderr.
Debug feedback from worker is forwarded to master via a specific handler
(see [worker_initialization_done]) *)Queue.clearcoq_debug_feedback_queueletworker_initialization_done~fwd_event=let_=install_debug_feedbackfwd_eventin()