diff --git a/Project.toml b/Project.toml index 39765098..677c848f 100644 --- a/Project.toml +++ b/Project.toml @@ -13,6 +13,7 @@ Tokenize = "0796e94c-ce3b-5d07-9a54-7f471281c624" JSONRPC = "b9b8584e-8fd3-41f9-ad0c-7255d428e418" SymbolServer = "cf896787-08d5-524d-9de7-132aaa0cb996" URIParser = "30578b45-9adc-5946-b283-645ec420af67" +Markdown = "d6f4376e-aef5-505a-96c1-9c027394607a" [extras] Pkg = "44cfe95a-1eb2-52ea-b672-e2afdf69b78f" diff --git a/src/LanguageServer.jl b/src/LanguageServer.jl index a0231577..b56293f6 100644 --- a/src/LanguageServer.jl +++ b/src/LanguageServer.jl @@ -4,6 +4,7 @@ using JSON, REPL, CSTParser, DocumentFormat, SymbolServer, StaticLint using CSTParser: EXPR, Tokenize.Tokens, typof, kindof, parentof, valof using StaticLint: refof, scopeof, bindingof using UUIDs +using Base.Docs, Markdown import JSONRPC using JSONRPC: Outbound, @dict_readable diff --git a/src/languageserverinstance.jl b/src/languageserverinstance.jl index 5b9309f3..95f53f1a 100644 --- a/src/languageserverinstance.jl +++ b/src/languageserverinstance.jl @@ -276,6 +276,7 @@ function Base.run(server::LanguageServerInstance) msg_dispatcher[textDocument_rename_request_type] = (conn, params)->textDocument_rename_request(params, server, conn) msg_dispatcher[textDocument_documentSymbol_request_type] = (conn, params)->textDocument_documentSymbol_request(params, server, conn) msg_dispatcher[julia_getModuleAt_request_type] = (conn, params)->julia_getModuleAt_request(params, server, conn) + msg_dispatcher[julia_getDocAt_request_type] = (conn, params)->julia_getDocAt_request(params, server, conn) msg_dispatcher[textDocument_hover_request_type] = (conn, params)->textDocument_hover_request(params, server, conn) msg_dispatcher[initialize_request_type] = (conn, params)->initialize_request(params, server, conn) msg_dispatcher[initialized_notification_type] = (conn, params)->initialized_notification(params, server, conn) @@ -323,5 +324,3 @@ function Base.run(server::LanguageServerInstance) end end end - - diff --git a/src/protocol/messagedefs.jl b/src/protocol/messagedefs.jl index f7613933..a197bb5a 100644 --- a/src/protocol/messagedefs.jl +++ b/src/protocol/messagedefs.jl @@ -22,9 +22,9 @@ const workspace_didChangeConfiguration_notification_type = JSONRPC.NotificationT const workspace_didChangeWorkspaceFolders_notification_type = JSONRPC.NotificationType("workspace/didChangeWorkspaceFolders", DidChangeWorkspaceFoldersParams) const workspace_applyEdit_request_type = JSONRPC.RequestType("workspace/applyEdit", ApplyWorkspaceEditParams, ApplyWorkspaceEditResponse) const workspace_configuration_request_type = JSONRPC.RequestType("workspace/configuration", ConfigurationParams, Vector{Any}) - const julia_getModuleAt_request_type = JSONRPC.RequestType("julia/getModuleAt", VersionedTextDocumentPositionParams, String) const julia_getCurrentBlockRange_request_type = JSONRPC.RequestType("julia/getCurrentBlockRange", VersionedTextDocumentPositionParams, Position) +const julia_getDocAt_request_type = JSONRPC.RequestType("julia/getDocAt", VersionedTextDocumentPositionParams, String) const julia_activateenvironment_notification_type = JSONRPC.NotificationType("julia/activateenvironment", String) const initialize_request_type = JSONRPC.RequestType("initialize", InitializeParams, InitializeResult) diff --git a/src/requests/features.jl b/src/requests/features.jl index a1f28953..838e51b5 100644 --- a/src/requests/features.jl +++ b/src/requests/features.jl @@ -358,10 +358,10 @@ function julia_getModuleAt_request(params::VersionedTextDocumentPositionParams, end end else - return JSONRPC.JSONRPCError(-32099, "version mismatch in getModuleAt for $(uri): JLS $(doc._version), client: $(params.version)", nothing) + return mismatched_version_error(uri, doc, params, "getModuleAt") end else - return JSONRPC.JSONRPCError(-32099, "document $(uri) requested but not present in the JLS", nothing) + return nodocuemnt_error(uri) end return "Main" end @@ -376,3 +376,44 @@ function get_module_of(s::StaticLint.Scope, ms = []) return isempty(ms) ? "Main" : join(ms, ".") end end + +using Base.Docs, Markdown + +function julia_getDocAt_request(params::VersionedTextDocumentPositionParams, server::LanguageServerInstance, conn) + uri = URI2(params.textDocument.uri) + hasdocument(server, uri) || return nodocuemnt_error(uri) + + doc = getdocument(server, uri) + if doc._version !== params.version + return mismatched_version_error(uri, doc, params, "getDocAt") + end + + x = get_expr1(getcst(doc), get_offset(doc, params.position)) + x isa EXPR && typof(x) === CSTParser.OPERATOR && resolve_op_ref(x, server) + documentation = get_hover(x, "", server) + md = Markdown.parse(documentation) + return webview_html(md) +end + +const CODE_LANG_REGEX = r"\(?!\>).+)\"\>" + +function webview_html(md) + # HACK goes on ... + s = html(md) + if haskey(md.meta, :module) + mod = md.meta[:module] + newhref = string("julia-vscode", '/', mod) + s = replace(s, " " annotate_highlight_js) + return s +end + +function annotate_highlight_js(s) + m::RegexMatch = match(CODE_LANG_REGEX, s) + lang = m[:lang] + if lang == "jldoctest" + lang = "julia-repl" + end + return "" +end diff --git a/src/requests/misc.jl b/src/requests/misc.jl index 7617424e..96dc923c 100644 --- a/src/requests/misc.jl +++ b/src/requests/misc.jl @@ -9,12 +9,12 @@ function julia_getCurrentBlockRange_request(tdpp::VersionedTextDocumentPositionP fallback = (Position(0, 0), Position(0, 0), tdpp.position) uri = URI2(tdpp.textDocument.uri) - hasdocument(server, uri) || return JSONRPC.JSONRPCError(-32099, "document $(uri) requested but not present in the JLS", nothing) + hasdocument(server, uri) || return nodocuemnt_error(uri) doc = getdocument(server, uri) if doc._version !== tdpp.version - return JSONRPC.JSONRPCError(-32099, "version mismatch in getCurrentBlockRange for $(uri): JLS $(doc._version), client: $(tdpp.version)", nothing) + return mismatched_version_error(uri, doc, tdpp, "getCurrentBlockRange") end offset = get_offset(doc, tdpp.position) diff --git a/src/utilities.jl b/src/utilities.jl index 74208e4f..f7a4c022 100644 --- a/src/utilities.jl +++ b/src/utilities.jl @@ -1,3 +1,14 @@ +nodocuemnt_error(uri, data = nothing) = + return JSONRPC.JSONRPCError(-32099, "document $(uri) requested but not present in the JLS", data) + +function mismatched_version_error(uri, doc, params, msg, data = nothing) + return JSONRPC.JSONRPCError( + -32099, + "version mismatch in $(msg) request for $(uri): JLS $(doc._version), client: $(params.version)", + nothing + ) +end + function uri2filepath(uri::AbstractString) parsed_uri = try URIParser.URI(uri)