123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323openImportopenJson.ConvmoduleJson=JsonmoduleId=structtypet=[`Stringofstring|`Intofint]letyojson_of_t=function|`Strings->`Strings|`Inti->`Intilett_of_yojson=function|`Strings->`Strings|`Inti->`Inti|json->Json.error"Id.t"jsonlethashx=Hashtbl.hashxletequal=(=)endmoduleConstant=structletjsonrpc="jsonrpc"letjsonrpcv="2.0"letid="id"letmethod_="method"letparams="params"letresult="result"leterror="error"endletassert_jsonrpc_versionfields=letjsonrpc=Json.field_exnfieldsConstant.jsonrpcJson.Conv.string_of_yojsoninifnot(String.equaljsonrpcConstant.jsonrpcv)thenJson.error("invalid packet: jsonrpc version doesn't match "^jsonrpc)(`Assocfields)moduleStructured=structtypet=[`Assocof(string*Json.t)list|`ListofJson.tlist]lett_of_yojson=function|`Assocxs->`Assocxs|`Listxs->`Listxs|json->Json.error"invalid structured value"jsonletyojson_of_tt=(t:>Json.t)endmoduleNotification=structtypet={method_:string;params:Structured.toption}letfields~method_~params=letjson=[(Constant.method_,`Stringmethod_);(Constant.jsonrpc,`StringConstant.jsonrpcv)]inmatchparamswith|None->json|Someparams->(Constant.params,(params:>Json.t))::jsonletyojson_of_t{method_;params}=`Assoc(fields~method_~params)letcreate?params~method_()={params;method_}endmoduleRequest=structtypet={id:Id.t;method_:string;params:Structured.toption}letyojson_of_t{id;method_;params}=letfields=Notification.fields~method_~paramsin`Assoc((Constant.id,Id.yojson_of_tid)::fields)letcreate?params~id~method_()={params;id;method_}endmoduleResponse=structmoduleError=structmoduleCode=structtypet=|ParseError|InvalidRequest|MethodNotFound|InvalidParams|InternalError(* the codes below are LSP specific *)|ServerErrorStart|ServerErrorEnd|ServerNotInitialized|UnknownErrorCode|RequestFailed|ServerCancelled|ContentModified|RequestCancelled(* all other codes are custom *)|Otherofintletof_int=function|-32700->ParseError|-32600->InvalidRequest|-32601->MethodNotFound|-32602->InvalidParams|-32603->InternalError|-32099->ServerErrorStart|-32000->ServerErrorEnd|-32002->ServerNotInitialized|-32001->UnknownErrorCode|-32800->RequestCancelled|-32801->ContentModified|-32802->ServerCancelled|-32803->RequestFailed|code->Othercodeletto_int=function|ParseError->-32700|InvalidRequest->-32600|MethodNotFound->-32601|InvalidParams->-32602|InternalError->-32603|ServerErrorStart->-32099|ServerErrorEnd->-32000|ServerNotInitialized->-32002|UnknownErrorCode->-32001|RequestCancelled->-32800|ContentModified->-32801|ServerCancelled->-32802|RequestFailed->-32803|Othercode->codelett_of_yojsonjson=matchjsonwith|`Inti->of_inti|_->Json.error"invalid code"jsonletyojson_of_tt=`Int(to_intt)endtypet={code:Code.t;message:string;data:Json.toption}letyojson_of_t{code;message;data}=letassoc=[("code",Code.yojson_of_tcode);("message",`Stringmessage)]inletassoc=matchdatawith|None->assoc|Somedata->("data",data)::associn`Assocassoclett_of_yojsonjson=matchjsonwith|`Assocfields->letcode=Json.field_exnfields"code"Code.t_of_yojsoninletmessage=Json.field_exnfields"message"string_of_yojsoninletdata=Json.fieldfields"data"(funx->x)in{code;message;data}|_->Json.error"Jsonrpc.Response.t"jsonexceptionEoftletraiset=raise(Et)letmake?data~code~message()={data;code;message}letof_exnexn=letmessage=Printexc.to_stringexninmake~code:InternalError~message()endtypet={id:Id.t;result:(Json.t,Error.t)Result.t}letyojson_of_t{id;result}=letresult=matchresultwith|Okjson->(Constant.result,json)|Errore->(Constant.error,Error.yojson_of_te)in`Assoc[(Constant.id,Id.yojson_of_tid);(Constant.jsonrpc,`StringConstant.jsonrpcv);result]lett_of_yojsonjson=matchjsonwith|`Assocfields->(letid=Json.field_exnfieldsConstant.idId.t_of_yojsoninletjsonrpc=Json.field_exnfieldsConstant.jsonrpcJson.Conv.string_of_yojsoninifjsonrpc<>Constant.jsonrpcvthenJson.error"Invalid response"jsonelsematchJson.fieldfieldsConstant.result(funx->x)with|Someres->{id;result=Okres}|None->letresult=Error(Json.field_exnfieldsConstant.errorError.t_of_yojson)in{id;result})|_->Json.error"Jsonrpc.Result.t"jsonletmake~id~result={id;result}letokidresult=make~id~result:(Okresult)leterroriderror=make~id~result:(Errorerror)endmodulePacket=structtypet=|NotificationofNotification.t|RequestofRequest.t|ResponseofResponse.t|Batch_responseofResponse.tlist|Batch_callof[`RequestofRequest.t|`NotificationofNotification.t]listletyojson_of_t=function|Notificationr->Notification.yojson_of_tr|Requestr->Request.yojson_of_tr|Responser->Response.yojson_of_tr|Batch_responser->`List(List.mapr~f:Response.yojson_of_t)|Batch_callr->`List(List.mapr~f:(function|`Requestr->Request.yojson_of_tr|`Notificationr->Notification.yojson_of_tr))lett_of_fields(fields:(string*Json.t)list)=assert_jsonrpc_versionfields;matchJson.fieldfieldsConstant.idId.t_of_yojsonwith|None->letmethod_=Json.field_exnfieldsConstant.method_Json.Conv.string_of_yojsoninletparams=Json.fieldfieldsConstant.paramsStructured.t_of_yojsoninNotification{Notification.params;method_}|Someid->(matchJson.fieldfieldsConstant.method_Json.Conv.string_of_yojsonwith|Somemethod_->letparams=Json.fieldfieldsConstant.paramsStructured.t_of_yojsoninRequest{Request.method_;params;id}|None->Response(matchJson.fieldfieldsConstant.result(funx->x)with|Someresult->{Response.id;result=Okresult}|None->leterror=Json.field_exnfieldsConstant.errorResponse.Error.t_of_yojsonin{id;result=Errorerror}))lett_of_yojson_singlejson=matchjsonwith|`Assocfields->t_of_fieldsfields|_->Json.error"invalid packet"jsonlett_of_yojson(json:Json.t)=matchjsonwith|`List[]->Json.error"invalid packet"json|`List(x::xs)->((* we inspect the first element to see what we're dealing with *)letx=matchxwith|`Assocfields->t_of_fieldsfields|_->Json.error"invalid packet"jsoninmatchmatchxwith|Notificationx->`Call(`Notificationx)|Requestx->`Call(`Requestx)|Responser->`Responser|_->Json.error"invalid packet"jsonwith|`Callx->Batch_call(x::List.mapxs~f:(funcall->letx=t_of_yojson_singlecallinmatchxwith|Notificationn->`Notificationn|Requestn->`Requestn|_->Json.error"invalid packet"json))|`Responsex->Batch_response(x::List.mapxs~f:(funresp->letresp=t_of_yojson_singlerespinmatchrespwith|Responsen->n|_->Json.error"invalid packet"json)))|_->t_of_yojson_singlejsonend