diff --git a/src/LanguageServer.jl b/src/LanguageServer.jl index d784cfdb..f9a35a30 100644 --- a/src/LanguageServer.jl +++ b/src/LanguageServer.jl @@ -17,6 +17,71 @@ using .URIs2 JSON.lower(uri::URI) = string(uri) +# these are the endpoints of JSON-RPC error codes +# per the LSP spec, no LSP error codes should lie +# between these +const SERVER_ERROR_END = -32000 +const SERVER_ERROR_START = -32099 + +# These are existing reserved errors for JSONRPC.jl +# We shouldn't throw these manually +const SERVER_NOT_INITIALIZED = -32002 +const UNKNOWN_ERROR_CODE = -32001 + +# LSP specific error codes +# these are the defined ranges for LSP errors +# not real error codes. Custom errors must lie +# outside this range +const LSP_RESERVED_ERROR_START = -32899 +const LSP_RESERVED_ERROR_END = -32800 + +const REQUEST_CANCELLED = -32800 +const CONTENT_MODIFIED = -32801 +const SERVER_CANCELLED = -32802 +const REQUEST_FAILED = -32803 + +# Specific to our implementation +const FORMATTING_FAILED = -33000 +const NO_DOCUMENT = -33100 +const MISMATCHED_VERSION = -33101 +const SHUTDOWN_REQUEST = -32600 + +const ERROR_CODES = ( + REQUEST_CANCELLED, + CONTENT_MODIFIED, + SERVER_CANCELLED, + REQUEST_FAILED, + FORMATTING_FAILED, + NO_DOCUMENT, + MISMATCHED_VERSION, + SHUTDOWN_REQUEST +) + +function __init__() + # init JSONRPC error messages + conflicting_codes = filter(ERROR_CODES) do code + !haskey(JSONRPC.JSONRPCErrorStrings, code) && return false + return JSONRPC.JSONRPCErrorStrings[code] != "ServerError" + end + # if any of the codes we want to use are already set, + # it means we have a conflict with another application + # using JSONRPC.jl at the same time in this process + # warn the user of this, so that they can debug/work around it + if !isempty(conflicting_codes) + @warn """JSONRPC Error Codes conflict! + + Another library besides LanguageServer.jl is using JSONRPC.jl with conflicting error codes. + LanguageServer.jl will overwrite this with its own state. Faulty behavior/error printing may arise. + """ Codes=conflicting_codes + end + + JSONRPC.RPCErrorStrings[REQUEST_CANCELLED] = "RequestCancelled" + JSONRPC.RPCErrorStrings[CONTENT_MODIFIED] = "ContentModified" + JSONRPC.RPCErrorStrings[SERVER_CANCELLED] = "ServerCancelled" + JSONRPC.RPCErrorStrings[REQUEST_FAILED] = "RequestFailed" + nothing +end + include("exception_types.jl") include("protocol/protocol.jl") include("extensions/extensions.jl") diff --git a/src/languageserverinstance.jl b/src/languageserverinstance.jl index e207fb59..f90b41b4 100644 --- a/src/languageserverinstance.jl +++ b/src/languageserverinstance.jl @@ -257,7 +257,7 @@ function request_wrapper(func, server::LanguageServerInstance) # it's fine to always return a value here, even for notifications, because # JSONRPC discards it anyways in that case return JSONRPC.JSONRPCError( - -32600, + SHUTDOWN_REQUEST, "LS shutdown was requested.", nothing ) diff --git a/src/requests/features.jl b/src/requests/features.jl index 9d232b64..0652ec57 100644 --- a/src/requests/features.jl +++ b/src/requests/features.jl @@ -160,7 +160,7 @@ function textDocument_formatting_request(params::DocumentFormattingParams, serve format_text(get_text(doc), params, config) catch err return JSONRPC.JSONRPCError( - -32000, + FORMATTING_FAILED, "Failed to format document: $err.", nothing ) @@ -210,7 +210,7 @@ function textDocument_range_formatting_request(params::DocumentRangeFormattingPa format_text(text_marked, params, config) catch err return JSONRPC.JSONRPCError( - -33000, + FORMATTING_FAILED, "Failed to format document: $err.", nothing ) diff --git a/src/utilities.jl b/src/utilities.jl index 73487f04..f91b187d 100644 --- a/src/utilities.jl +++ b/src/utilities.jl @@ -3,7 +3,7 @@ function nodocument_error(uri, data=nothing) return JSONRPC.JSONRPCError( - -33100, + NO_DOCUMENT, "document $(uri) requested but not present in the JLS", data ) @@ -11,7 +11,7 @@ end function mismatched_version_error(uri, doc, params, msg, data=nothing) return JSONRPC.JSONRPCError( - -33101, + MISMATCHED_VERSION, "version mismatch in $(msg) request for $(uri): JLS $(get_version(doc)), client: $(params.version)", data )