基础协议
基础协议由标头和内容组成。标头和内容之间使用 \r\n
分隔。
标头
标头由标头字段组成。每个标头字段包含一个名称和值,用 :
(冒号和空格)分隔。标头字段的结构符合 HTTP 语义。每个标头字段都以 \r\n
结尾。考虑到每个标头字段和整个标头都以 \r\n
结尾,并且至少有一个标头字段,这意味着在内容之前始终都有两个 \r\n
。
目前支持的标头字段:
标头字段名 | 值类型 | 描述 |
---|---|---|
Content-Length | number | 内容部分以字节计算的长度,这个标头是必须的。 |
Content-Type | string | 内容部分的 MIME 类型。默认是 application/vscode-jsonrpc; charset=utf-8 。 |
标头部分使用 ascii
编码进行编码。这包括分隔标题和内容部分的 \r\n
。
内容
包含消息实际的内容。消息的内容部分使用 JSON-RPC 来描述请求、响应和通知。内容部分使用 Content-Type
字段中提供的字符集进行编码。它默认为 utf-8,这是目前唯一支持的编码。如果服务器或客户端收到的标头编码与 utf-8
不同,则应响应错误。
该协议的早期版本使用字符串常量 utf8
,根据规范,它不是正确的编码常量。为了向后兼容,强烈建议客户端和服务器将字符串 utf8
视为 utf-8
。
示例:
Content-Length: ...\r\n
\r\n
{
"jsonrpc": "2.0",
"id": 1,
"method": "textDocument/completion",
"params": {
...
}
}
基础协议 JSON 结构
以下 TypeScript
定义描述了基本 JSON-RPC
协议:
基础类型
该协议对整数、无符号整数、十进制数、对象和数组使用以下定义:
/**
* Defines an integer number in the range of -2^31 to 2^31 - 1.
*/
export type integer = number;
/**
* Defines an unsigned integer number in the range of 0 to 2^31 - 1.
*/
export type uinteger = number;
/**
* Defines a decimal number. Since decimal numbers are very
* rare in the language server specification we denote the
* exact range with every decimal using the mathematics
* interval notation (e.g. [0, 1] denotes all decimals d with
* 0 <= d <= 1.
*/
export type decimal = number;
/**
* The LSP any type
*
* @since 3.17.0
*/
export type LSPAny = LSPObject | LSPArray | string | integer | uinteger |
decimal | boolean | null;
/**
* LSP object definition.
*
* @since 3.17.0
*/
export type LSPObject = { [key: string]: LSPAny };
/**
* LSP arrays.
*
* @since 3.17.0
*/
export type LSPArray = LSPAny[];
抽象消息
由 JSON-RPC 定义的常规消息。语言服务器协议始终使用 "2.0" 作为 jsonrpc 版本。
interface Message {
jsonrpc: string;
}
请求消息
用于描述客户端和服务器之间的请求的请求消息(可以由客户端发出,也可以由服务端发出)。每个已处理的请求都必须将响应发送回请求的发送方。
interface RequestMessage extends Message {
/**
* The request id.
*/
id: integer | string;
/**
* The method to be invoked.
*/
method: string;
/**
* The method's params.
*/
params?: array | object;
}
响应消息
响应消息作为请求的结果发送。如果请求未提供结果值,请求的接收方仍需要返回响应消息以符合 JSON-RPC
规范。在这种情况下,应将 ResponseMessage
的 result
属性设置为 null
以表示请求成功。
interface ResponseMessage extends Message {
/**
* The request id.
*/
id: integer | string | null;
/**
* The result of a request. This member is REQUIRED on success.
* This member MUST NOT exist if there was an error invoking the method.
*/
result?: string | number | boolean | array | object | null;
/**
* The error object in case a request fails.
*/
error?: ResponseError;
}
interface ResponseError {
/**
* A number indicating the error type that occurred.
*/
code: integer;
/**
* A string providing a short description of the error.
*/
message: string;
/**
* A primitive or structured value that contains additional
* information about the error. Can be omitted.
*/
data?: string | number | boolean | array | object | null;
}
export namespace ErrorCodes {
// Defined by JSON-RPC
export const ParseError: integer = -32700;
export const InvalidRequest: integer = -32600;
export const MethodNotFound: integer = -32601;
export const InvalidParams: integer = -32602;
export const InternalError: integer = -32603;
/**
* This is the start range of JSON-RPC reserved error codes.
* It doesn't denote a real error code. No LSP error codes should
* be defined between the start and end range. For backwards
* compatibility the `ServerNotInitialized` and the `UnknownErrorCode`
* are left in the range.
*
* @since 3.16.0
*/
export const jsonrpcReservedErrorRangeStart: integer = -32099;
/** @deprecated use jsonrpcReservedErrorRangeStart */
export const serverErrorStart: integer = jsonrpcReservedErrorRangeStart;
/**
* Error code indicating that a server received a notification or
* request before the server has received the `initialize` request.
*/
export const ServerNotInitialized: integer = -32002;
export const UnknownErrorCode: integer = -32001;
/**
* This is the end range of JSON-RPC reserved error codes.
* It doesn't denote a real error code.
*
* @since 3.16.0
*/
export const jsonrpcReservedErrorRangeEnd = -32000;
/** @deprecated use jsonrpcReservedErrorRangeEnd */
export const serverErrorEnd: integer = jsonrpcReservedErrorRangeEnd;
/**
* This is the start range of LSP reserved error codes.
* It doesn't denote a real error code.
*
* @since 3.16.0
*/
export const lspReservedErrorRangeStart: integer = -32899;
/**
* A request failed but it was syntactically correct, e.g the
* method name was known and the parameters were valid. The error
* message should contain human readable information about why
* the request failed.
*
* @since 3.17.0
*/
export const RequestFailed: integer = -32803;
/**
* The server cancelled the request. This error code should
* only be used for requests that explicitly support being
* server cancellable.
*
* @since 3.17.0
*/
export const ServerCancelled: integer = -32802;
/**
* The server detected that the content of a document got
* modified outside normal conditions. A server should
* NOT send this error code if it detects a content change
* in it unprocessed messages. The result even computed
* on an older state might still be useful for the client.
*
* If a client decides that a result is not of any use anymore
* the client should cancel the request.
*/
export const ContentModified: integer = -32801;
/**
* The client has canceled a request and a server has detected
* the cancel.
*/
export const RequestCancelled: integer = -32800;
/**
* This is the end range of LSP reserved error codes.
* It doesn't denote a real error code.
*
* @since 3.16.0
*/
export const lspReservedErrorRangeEnd: integer = -32800;
}
通知消息
通知消息。已处理的通知消息不得发回响应。它们像事件一样工作。
interface NotificationMessage extends Message {
/**
* The method to be invoked.
*/
method: string;
/**
* The notification's params.
*/
params?: array | object;
}
$通知和请求
方法以 $/
开头的通知和请求是依赖于协议(由客户端和服务器自行约定)实现的消息,可能无法在所有客户端或服务器中实现。例如,如果服务器实现使用单线程同步编程语言,则服务器几乎无法对 $/cancelRequest
通知做出反应。如果服务器或客户端收到以 $/
开头的通知,则可以忽略该通知。如果服务器或客户端收到以 $/
开头的请求,则必须使用错误代码 MethodNotFound
(例如 -32601)响应请求。
支持取消
基本协议支持取消请求。若要取消请求,将发送具有以下属性的通知消息:
- method: "$/cancelRequest"
- params:
CancelParams
定义如下:
interface CancelParams {
/**
* The request id to cancel.
*/
id: integer | string;
}
已取消的请求仍需要从服务器返回并发送回响应。它不能保持打开/挂起。这符合 JSON-RPC
协议,该协议要求每个请求都发送回响应。此外,它还允许在取消时返回部分结果。如果请求在取消时返回错误响应,建议将错误代码设置为 ErrorCodes.RequestCancelled。
支持进度
Since version 3.15.0
基本协议还支持以通用方式报告进度。此机制可用于报告任何类型的进度,包括已完成的工作进度(通常用于使用进度条在用户界面中报告进度)和部分结果进度,以支持结果流式处理。
进度通知具有以下属性:
- method: "$/progress"
- params:
ProgressParams
定义如下:
interface ProgressParams<T> {
/**
* The progress token provided by the client or server.
*/
token: ProgressToken;
/**
* The progress data.
*/
value: T;
}
type ProgressToken = integer | string;
泛型
T
由协议约定
针对 token
报告进度。token
与请求 id 不同,它允许带外数据报告进度。