From: Eli Zaretskii Date: Sat, 13 Apr 2019 07:42:14 +0000 (+0300) Subject: Improve documentation of JSONRPC X-Git-Tag: emacs-27.0.90~3259^2~15 X-Git-Url: http://git.eshelyaron.com/gitweb/?a=commitdiff_plain;h=d82d4fb9157dd86359e4489c8da100943754a4d0;p=emacs.git Improve documentation of JSONRPC * doc/lispref/text.texi (JSONRPC Overview) (Process-based JSONRPC connections) (JSONRPC JSON object format): Fix wording and markup. Add indexing. --- diff --git a/doc/lispref/text.texi b/doc/lispref/text.texi index e8de8177e30..500df1f8f0d 100644 --- a/doc/lispref/text.texi +++ b/doc/lispref/text.texi @@ -5197,11 +5197,12 @@ the value if contains a valid JSON object; otherwise it signals the @node JSONRPC @section JSONRPC communication @cindex JSON remote procedure call protocol +@cindex JSONRPC The @code{jsonrpc} library implements the @acronym{JSONRPC} specification, version 2.0, as it is described in @uref{http://www.jsonrpc.org/}. As the name suggests, JSONRPC is a -generic @code{Remote Procedure Call} protocol designed around +generic @dfn{Remote Procedure Call} protocol designed around @acronym{JSON} objects, which you can convert to and from Lisp objects (@pxref{Parsing JSON}). @@ -5220,81 +5221,96 @@ transport agnostic in that the concepts can be used within the same process, over sockets, over http, or in many various message passing environments." +@findex jsonrpc-connection To model this agnosticism, the @code{jsonrpc} library uses objects of -a @code{jsonrpc-connection} class, which represent a connection the +a @code{jsonrpc-connection} class, which represent a connection to a remote JSON endpoint (for details on Emacs's object system, @pxref{Top,EIEIO,,eieio,EIEIO}). In modern object-oriented parlance, -this class is ``abstract'', i.e. the actual class of a useful -connection object used is always a subclass of it. Nevertheless, we -can define two distinct API's around the @code{jsonrpc-connection} -class: +this class is ``abstract'', i.e.@: the actual class of a useful +connection object is always a subclass of @code{jsonrpc-connection}. +Nevertheless, we can define two distinct APIs around the +@code{jsonrpc-connection} class: +@cindex JSONRPC application interfaces @enumerate @item A user interface for building JSONRPC applications +@findex :request-dispatcher +@findex :notification-dispatcher +@findex jsonrpc-notify +@findex jsonrpc-request +@findex jsonrpc-async-request In this scenario, the JSONRPC application selects a concrete subclass of @code{jsonrpc-connection}, and proceeds to create objects of that subclass using @code{make-instance}. To initiate a contact to the remote endpoint, the JSONRPC application passes this object to the -functions @code{jsonrpc-notify'}, @code{jsonrpc-request} and +functions @code{jsonrpc-notify}, @code{jsonrpc-request}, and/or @code{jsonrpc-async-request}. For handling remotely initiated contacts, which generally come in asynchronously, the instantiation should include @code{:request-dispatcher} and @code{:notification-dispatcher} initargs, which are both functions of 3 arguments: the connection object; a symbol naming the JSONRPC method -invoked remotely; and a JSONRPC "params" object. +invoked remotely; and a JSONRPC @code{params} object. +@findex jsonrpc-error The function passed as @code{:request-dispatcher} is responsible for handling the remote endpoint's requests, which expect a reply from the local endpoint (in this case, the program you're building). Inside -that function, you may either return locally (normally) or non-locally -(error). A local return value must be a Lisp object serializable as -JSON (@pxref{Parsing JSON}). This determines a success response, and -the object is forwarded to the server as the JSONRPC "result" object. -A non-local return, achieved by calling the function -@code{jsonrpc-error}, causes an error response to be sent to the -server. The details of the accompanying JSONRPC "error" are filled -out with whatever was passed to @code{jsonrpc-error}. A non-local -return triggered by an unexpected error of any other type also causes -an error response to be sent (unless you have set -@code{debug-on-error}, in which case this should land you in the -debugger, @pxref{Error Debugging}). +that function, you may either return locally (a normal return) or +non-locally (an error return). A local return value must be a Lisp +object that can be serialized as JSON (@pxref{Parsing JSON}). This +determines a success response, and the object is forwarded to the +server as the JSONRPC @code{result} object. A non-local return, +achieved by calling the function @code{jsonrpc-error}, causes an error +response to be sent to the server. The details of the accompanying +JSONRPC @code{error} are filled out with whatever was passed to +@code{jsonrpc-error}. A non-local return triggered by an unexpected +error of any other type also causes an error response to be sent +(unless you have set @code{debug-on-error}, in which case this calls +the Lisp debugger, @pxref{Error Debugging}). @item A inheritance interface for building JSONRPC transport implementations In this scenario, @code{jsonrpc-connection} is subclassed to implement a different underlying transport strategy (for details on how to -subclass, @pxref{Inheritance,Inheritance,,eieio}). Users of the +subclass, see @ref{Inheritance,Inheritance,,eieio}.). Users of the application-building interface can then instantiate objects of this concrete class (using the @code{make-instance} function) and connect to JSONRPC endpoints using that strategy. This API has mandatory and optional parts. +@findex jsonrpc-connection-send To allow its users to initiate JSONRPC contacts (notifications or -requests) or reply to endpoint requests, the method -@code{jsonrpc-connection-send} must be implemented for the subclass. +requests) or reply to endpoint requests, the subclass must have an +implementation of the @code{jsonrpc-connection-send} method. +@findex jsonrpc-connection-receive Likewise, for handling the three types of remote contacts (requests, -notifications and responses to local requests) the transport +notifications, and responses to local requests), the transport implementation must arrange for the function @code{jsonrpc-connection-receive} to be called after noticing a new JSONRPC message on the wire (whatever that "wire" may be). +@findex jsonrpc-shutdown +@findex jsonrpc-running-p Finally, and optionally, the @code{jsonrpc-connection} subclass should -implement @code{jsonrpc-shutdown} and @code{jsonrpc-running-p} if -these concepts apply to the transport. If they do, then any system -resources (e.g. processes, timers, etc..) used listen for messages on -the wire should be released in @code{jsonrpc-shutdown}, i.e. they -should only be needed while @code{jsonrpc-running-p} is non-nil. +implement the @code{jsonrpc-shutdown} and @code{jsonrpc-running-p} +methods if these concepts apply to the transport. If they do, then +any system resources (e.g.@: processes, timers, etc.) used to listen for +messages on the wire should be released in @code{jsonrpc-shutdown}, +i.e.@: they should only be needed while @code{jsonrpc-running-p} is +non-nil. @end enumerate @node Process-based JSONRPC connections @subsection Process-based JSONRPC connections +@cindex JSONRPC process-based connections -For convenience, the @code{jsonrpc} library comes built-in with a +@findex jsonrpc-process-connection +For convenience, the @code{jsonrpc} library comes with a built-in @code{jsonrpc-process-connection} transport implementation that can talk to local subprocesses (using the standard input and standard output); or TCP hosts (using sockets); or any other remote endpoint @@ -5309,6 +5325,7 @@ JSONRPC, see the @uref{https://microsoft.github.io/language-server-protocol/specification, Language Server Protocol}. +@cindex JSONRPC connection initargs Along with the mandatory @code{:request-dispatcher} and @code{:notification-dispatcher} initargs, users of the @code{jsonrpc-process-connection} class should pass the following @@ -5317,29 +5334,32 @@ initargs as keyword-value pairs to @code{make-instance}: @table @code @item :process Value must be a live process object or a function of no arguments -producing one such object. If passed a process object, that is -expected to contain an pre-established connection; otherwise, the +producing one such object. If passed a process object, the object is +expected to contain a pre-established connection; otherwise, the function is called immediately after the object is made. @item :on-shutdown Value must be a function of a single argument, the @code{jsonrpc-process-connection} object. The function is called after the underlying process object has been deleted (either -deliberately by @code{jsonrpc-shutdown} or unexpectedly, because of +deliberately by @code{jsonrpc-shutdown}, or unexpectedly, because of some external cause). @end table @node JSONRPC JSON object format -@subsection JSON object format +@subsection JSONRPC JSON object format +@cindex JSONRPC object format -JSON objects are exchanged as Lisp plists (@pxref{Parsing JSON}): -JSON-compatible plists are handed to the dispatcher functions and, -likewise, JSON-compatible plists should be given to -@code{jsonrpc-notify}, @code{jsonrpc-request} and +JSONRPC JSON objects are exchanged as Lisp plists (@pxref{Property +Lists}): JSON-compatible plists are handed to the dispatcher functions +and, likewise, JSON-compatible plists should be given to +@code{jsonrpc-notify}, @code{jsonrpc-request}, and @code{jsonrpc-async-request}. -To facilitate handling plists, this library make liberal use of -@code{cl-lib} library and suggests (but doesn't force) its clients to +@findex jsonrpc-lambda +To facilitate handling plists, this library makes liberal use of +@code{cl-lib} library (@pxref{Top,cl-lib,,cl,Common Lisp Extensions +for GNU Emacs Lisp}) and suggests (but doesn't force) its clients to do the same. A macro @code{jsonrpc-lambda} can be used to create a lambda for destructuring a JSON-object like in this example: @@ -5355,7 +5375,8 @@ lambda for destructuring a JSON-object like in this example: @end example @node JSONRPC deferred requests -@subsection Deferred requests +@subsection Deferred JSONRPC requests +@cindex JSONRPC deferred requests In many @acronym{RPC} situations, synchronization between the two communicating endpoints is a matter of correctly designing the RPC @@ -5367,6 +5388,7 @@ is still uncertainty about the state of the remote endpoint. Furthermore, acting on these events may only sometimes demand synchronization, depending on the event's specific nature. +@findex :deferred@r{, JSONRPC keyword} The @code{:deferred} keyword argument to @code{jsonrpc-request} and @code{jsonrpc-async-request} is designed to let the caller indicate that the specific request needs synchronization and its actual @@ -5377,9 +5399,10 @@ isn't sent immediately, @code{jsonrpc} will make renewed efforts to send it at certain key times during communication, such as when receiving or sending other messages to the endpoint. +@findex jsonrpc-connection-ready-p Before any attempt to send the request, the application-specific -conditions are checked. Since the @code{jsonrpc} library can't known -what these conditions are, the programmer may use the +conditions are checked. Since the @code{jsonrpc} library can't know +what these conditions are, the program can use the @code{jsonrpc-connection-ready-p} generic function (@pxref{Generic Functions}) to specify them. The default method for this function returns @code{t}, but you can add overriding methods that return