From e375b8525213ac5a63b1eb2e5007ad896d25d44b Mon Sep 17 00:00:00 2001 From: David Anthoff Date: Fri, 20 Dec 2024 09:12:48 -0800 Subject: [PATCH 1/2] Move all marking logic for testitems and diag here --- Project.toml | 2 +- src/LanguageServer.jl | 1 + src/languageserverinstance.jl | 6 +- src/requests/init.jl | 6 +- src/requests/textdocument.jl | 110 ++------------------- src/requests/workspace.jl | 14 ++- src/testitem_diagnostic_marking.jl | 147 +++++++++++++++++++++++++++++ 7 files changed, 165 insertions(+), 121 deletions(-) create mode 100644 src/testitem_diagnostic_marking.jl diff --git a/Project.toml b/Project.toml index fc17937f..6a0c15ad 100644 --- a/Project.toml +++ b/Project.toml @@ -27,7 +27,7 @@ JSONRPC = "1.1" JuliaFormatter = "0.20.0, 0.21, 0.22, 0.23, 1" PrecompileTools = "1" StaticLint = "8.0" -JuliaWorkspaces = "4.7" +JuliaWorkspaces = "5" SymbolServer = "8" Tokenize = "0.5.10" URIs = "1.3" diff --git a/src/LanguageServer.jl b/src/LanguageServer.jl index b6f56131..d2929a5a 100644 --- a/src/LanguageServer.jl +++ b/src/LanguageServer.jl @@ -28,6 +28,7 @@ include("languageserverinstance.jl") include("multienv.jl") include("runserver.jl") include("staticlint.jl") +include("testitem_diagnostic_marking.jl") include("requests/misc.jl") include("requests/textdocument.jl") diff --git a/src/languageserverinstance.jl b/src/languageserverinstance.jl index a4cd3413..29b81028 100644 --- a/src/languageserverinstance.jl +++ b/src/languageserverinstance.jl @@ -490,8 +490,7 @@ function Base.run(server::LanguageServerInstance; timings = []) end function relintserver(server) - JuliaWorkspaces.mark_current_diagnostics(server.workspace) - JuliaWorkspaces.mark_current_testitems(server.workspace) + marked_versions = mark_current_diagnostics_testitems(server.workspace) roots = Set{Document}() documents = collect(getdocuments_value(server)) @@ -514,6 +513,5 @@ function relintserver(server) lint!(doc, server) end end - publish_diagnostics(get_uri.(documents), server, server.jr_endpoint, "relintserver") - publish_tests(server) + publish_diagnostics_testitems(server, marked_versions, get_uri.(documents)) end diff --git a/src/requests/init.jl b/src/requests/init.jl index 7e845f3e..4cda0a43 100644 --- a/src/requests/init.jl +++ b/src/requests/init.jl @@ -224,8 +224,7 @@ function initialized_notification(params::InitializedParams, server::LanguageSer end - JuliaWorkspaces.mark_current_diagnostics(server.workspace) - JuliaWorkspaces.mark_current_testitems(server.workspace) + marked_versions = mark_current_diagnostics_testitems(server.workspace) added_docs = Document[] if server.workspaceFolders !== nothing @@ -289,8 +288,7 @@ function initialized_notification(params::InitializedParams, server::LanguageSer end end - publish_diagnostics(get_uri.(added_docs), server, conn, "initialized_notification") - publish_tests(server) + publish_diagnostics_testitems(server, marked_versions, get_uri.(added_docs)) request_julia_config(server, conn) diff --git a/src/requests/textdocument.jl b/src/requests/textdocument.jl index 2f1e6e41..840e1433 100644 --- a/src/requests/textdocument.jl +++ b/src/requests/textdocument.jl @@ -1,6 +1,5 @@ function textDocument_didOpen_notification(params::DidOpenTextDocumentParams, server::LanguageServerInstance, conn) - JuliaWorkspaces.mark_current_diagnostics(server.workspace) - JuliaWorkspaces.mark_current_testitems(server.workspace) + marked_versions = mark_current_diagnostics_testitems(server.workspace) uri = params.textDocument.uri if hasdocument(server, uri) @@ -33,8 +32,7 @@ function textDocument_didOpen_notification(params::DidOpenTextDocumentParams, se parse_all(doc, server) lint!(doc, server) - publish_diagnostics([get_uri(doc)], server, conn, "textDocument_didOpen_notification") - publish_tests(server) + publish_diagnostics_testitems(server, marked_versions, [get_uri(doc)]) end @@ -42,7 +40,7 @@ function textDocument_didClose_notification(params::DidCloseTextDocumentParams, uri = params.textDocument.uri doc = getdocument(server, uri) - JuliaWorkspaces.mark_current_testitems(server.workspace) + marked_versions = mark_current_diagnostics_testitems(server.workspace) if is_workspace_file(doc) set_open_in_editor(doc, false) @@ -74,7 +72,7 @@ function textDocument_didClose_notification(params::DidCloseTextDocumentParams, JuliaWorkspaces.remove_file!(server.workspace, uri) end - publish_tests(server) + publish_diagnostics_testitems(server, marked_versions, []) end function textDocument_didSave_notification(params::DidSaveTextDocumentParams, server::LanguageServerInstance, conn) @@ -137,8 +135,7 @@ function measure_sub_operation(f, request_name, server) end function textDocument_didChange_notification(params::DidChangeTextDocumentParams, server::LanguageServerInstance, conn) - JuliaWorkspaces.mark_current_diagnostics(server.workspace) - JuliaWorkspaces.mark_current_testitems(server.workspace) + marked_versions = mark_current_diagnostics_testitems(server.workspace) uri = params.textDocument.uri @@ -186,8 +183,7 @@ function textDocument_didChange_notification(params::DidChangeTextDocumentParams lint!(doc, server) end - publish_diagnostics([get_uri(doc)], server, conn, "textDocument_didChange_notification") - publish_tests(server) + publish_diagnostics_testitems(server, marked_versions, [get_uri(doc)]) end function parse_all(doc::Document, server::LanguageServerInstance) @@ -398,97 +394,3 @@ function try_to_load_parents(child_path, server) end end end - -function publish_diagnostics(uris::Vector{URI}, server, conn, source) - jw_diagnostics_updated, jw_diagnostics_deleted = JuliaWorkspaces.get_files_with_updated_diagnostics(server.workspace) - - all_uris_with_updates = Set{URI}() - - for uri in uris - push!(all_uris_with_updates, uri) - end - - for uri in jw_diagnostics_updated - push!(all_uris_with_updates, uri) - end - - diagnostics = Dict{URI,Vector{Diagnostic}}() - - for uri in all_uris_with_updates - diags = Diagnostic[] - diagnostics[uri] = diags - - if hasdocument(server, uri) - doc = getdocument(server, uri) - - if server.runlinter && (is_workspace_file(doc) || isunsavedfile(doc)) - pkgpath = getpath(doc) - if any(is_in_target_dir_of_package.(Ref(pkgpath), server.lint_disableddirs)) - filter!(!is_diag_dependent_on_env, doc.diagnostics) - end - append!(diags, doc.diagnostics) - end - end - - if JuliaWorkspaces.has_file(server.workspace, uri) - st = JuliaWorkspaces.get_text_file(server.workspace, uri).content - - new_diags = JuliaWorkspaces.get_diagnostic(server.workspace, uri) - - append!(diags, Diagnostic( - Range(st, i.range), - if i.severity==:error - DiagnosticSeverities.Error - elseif i.severity==:warning - DiagnosticSeverities.Warning - elseif i.severity==:info - DiagnosticSeverities.Information - else - error("Unknown severity $(i.severity)") - end, - missing, - missing, - i.source, - i.message, - missing, - missing - ) for i in new_diags) - end - end - - for (uri,diags) in diagnostics - version = get(server._open_file_versions, uri, missing) - params = PublishDiagnosticsParams(uri, version, diags) - JSONRPC.send(conn, textDocument_publishDiagnostics_notification_type, params) - end -end - -function publish_tests(server::LanguageServerInstance) - if !ismissing(server.initialization_options) && get(server.initialization_options, "julialangTestItemIdentification", false) - updated_files, deleted_files = JuliaWorkspaces.get_files_with_updated_testitems(server.workspace) - - for uri in updated_files - testitems_results = JuliaWorkspaces.get_test_items(server.workspace, uri) - st = JuliaWorkspaces.get_text_file(server.workspace, uri).content - - testitems = TestItemDetail[TestItemDetail(i.id, i.name, Range(st, i.range), i.code, Range(st, i.code_range), i.option_default_imports, string.(i.option_tags), string.(i.option_setup)) for i in testitems_results.testitems] - testsetups= TestSetupDetail[TestSetupDetail(string(i.name), string(i.kind), Range(st, i.range), i.code, Range(st, i.code_range), ) for i in testitems_results.testsetups] - testerrors = TestErrorDetail[TestErrorDetail(te.id, te.name, Range(st, te.range), te.message) for te in testitems_results.testerrors] - - version = get(server._open_file_versions, uri, missing) - - params = PublishTestsParams( - uri, - version, - testitems, - testsetups, - testerrors - ) - JSONRPC.send(server.jr_endpoint, textDocument_publishTests_notification_type, params) - end - - for uri in deleted_files - JSONRPC.send(server.jr_endpoint, textDocument_publishTests_notification_type, PublishTestsParams(uri, missing, TestItemDetail[], TestSetupDetail[], TestErrorDetail[])) - end - end -end diff --git a/src/requests/workspace.jl b/src/requests/workspace.jl index 473fdda5..1df7acfe 100644 --- a/src/requests/workspace.jl +++ b/src/requests/workspace.jl @@ -1,6 +1,5 @@ function workspace_didChangeWatchedFiles_notification(params::DidChangeWatchedFilesParams, server::LanguageServerInstance, conn) - JuliaWorkspaces.mark_current_diagnostics(server.workspace) - JuliaWorkspaces.mark_current_testitems(server.workspace) + marked_versions = mark_current_diagnostics_testitems(server.workspace) docs_to_lint = Document[] @@ -82,8 +81,8 @@ function workspace_didChangeWatchedFiles_notification(params::DidChangeWatchedFi for lint_doc in docs_to_lint lint!(lint_doc, server) end - publish_diagnostics(get_uri.(docs_to_lint), server, conn, "workspace_didChangeWatchedFiles_notification") - publish_tests(server) + + publish_diagnostics_testitems(server, marked_versions, get_uri.(docs_to_lint)) end function workspace_didChangeConfiguration_notification(params::DidChangeConfigurationParams, server::LanguageServerInstance, conn) @@ -174,8 +173,7 @@ function gc_files_from_workspace(server::LanguageServerInstance) end function workspace_didChangeWorkspaceFolders_notification(params::DidChangeWorkspaceFoldersParams, server::LanguageServerInstance, conn) - JuliaWorkspaces.mark_current_diagnostics(server.workspace) - JuliaWorkspaces.mark_current_testitems(server.workspace) + marked_versions = mark_current_diagnostics_testitems(server.workspace) added_docs = Document[] @@ -209,8 +207,8 @@ function workspace_didChangeWorkspaceFolders_notification(params::DidChangeWorks for doc in added_docs lint!(doc, server) end - publish_diagnostics(get_uri.(added_docs), server, conn, "workspace_didChangeWorkspaceFolders_notification") - publish_tests(server) + + publish_diagnostics_testitems(server, marked_versions, get_uri.(added_docs)) end function workspace_symbol_request(params::WorkspaceSymbolParams, server::LanguageServerInstance, conn) diff --git a/src/testitem_diagnostic_marking.jl b/src/testitem_diagnostic_marking.jl new file mode 100644 index 00000000..afc1bd49 --- /dev/null +++ b/src/testitem_diagnostic_marking.jl @@ -0,0 +1,147 @@ +function mark_current_diagnostics_testitems(jw::JuliaWorkspace) + ti_results = Dict{URI,UInt}(k => hash(v) for (k,v) in JuliaWorkspaces.get_test_items(jw)) + + diag_results = Dict{URI,UInt}(k => hash(v) for (k,v) in JuliaWorkspaces.get_diagnostics(jw)) + + return (testitems=ti_results, diagnostics=diag_results) +end + +function get_files_with_updated_diagnostics_testitems(jw::JuliaWorkspace, old_marked_versions::@NamedTuple{testitems::Dict{URI,UInt},diagnostics::Dict{URI,UInt}}) + # Testitems + new_marked_versions_ti = Dict{URI,UInt}(k => hash(v) for (k,v) in JuliaWorkspaces.get_test_items(jw)) + + old_text_files_ti = Set{URI}(keys(old_marked_versions.testitems)) + new_text_files_ti = Set{URI}(keys(new_marked_versions_ti)) + + deleted_files_ti = setdiff(old_text_files_ti, new_text_files_ti) + updated_files_ti = Set{URI}() + + for (uri,hash_value) in new_marked_versions_ti + if !(uri in old_text_files_ti) + push!(updated_files_ti, uri) + else + if hash_value != old_marked_versions.testitems[uri] + push!(updated_files_ti, uri) + end + end + end + + # Diagnostics + new_marked_versions_diag = Dict{URI,UInt}(k => hash(v) for (k,v) in JuliaWorkspaces.get_diagnostics(jw)) + + old_text_files_diag = Set{URI}(keys(old_marked_versions.diagnostics)) + new_text_files_diag = Set{URI}(keys(new_marked_versions_diag)) + + deleted_files_diag = setdiff(old_text_files_diag, new_text_files_diag) + updated_files_diag = Set{URI}() + + for (uri,hash_value) in new_marked_versions_diag + if !(uri in old_text_files_diag) + push!(updated_files_diag, uri) + else + if hash_value != old_marked_versions.diagnostics[uri] + push!(updated_files_diag, uri) + end + end + end + + return (;updated_files_ti, deleted_files_ti, updated_files_diag, deleted_files_diag) +end + +function publish_diagnostics(server, jw_diagnostics_updated, jw_diagnostics_deleted, uris::Vector{URI}) + all_uris_with_updates = Set{URI}() + + for uri in uris + push!(all_uris_with_updates, uri) + end + + for uri in jw_diagnostics_updated + push!(all_uris_with_updates, uri) + end + + diagnostics = Dict{URI,Vector{Diagnostic}}() + + for uri in all_uris_with_updates + diags = Diagnostic[] + diagnostics[uri] = diags + + if hasdocument(server, uri) + doc = getdocument(server, uri) + + if server.runlinter && (is_workspace_file(doc) || isunsavedfile(doc)) + pkgpath = getpath(doc) + if any(is_in_target_dir_of_package.(Ref(pkgpath), server.lint_disableddirs)) + filter!(!is_diag_dependent_on_env, doc.diagnostics) + end + append!(diags, doc.diagnostics) + end + end + + if JuliaWorkspaces.has_file(server.workspace, uri) + st = JuliaWorkspaces.get_text_file(server.workspace, uri).content + + new_diags = JuliaWorkspaces.get_diagnostic(server.workspace, uri) + + append!(diags, Diagnostic( + Range(st, i.range), + if i.severity==:error + DiagnosticSeverities.Error + elseif i.severity==:warning + DiagnosticSeverities.Warning + elseif i.severity==:info + DiagnosticSeverities.Information + else + error("Unknown severity $(i.severity)") + end, + missing, + missing, + i.source, + i.message, + missing, + missing + ) for i in new_diags) + end + end + + for (uri,diags) in diagnostics + version = get(server._open_file_versions, uri, missing) + params = PublishDiagnosticsParams(uri, version, diags) + JSONRPC.send(server.jr_endpoint, textDocument_publishDiagnostics_notification_type, params) + end +end + +function publish_tests(server::LanguageServerInstance, updated_files, deleted_files) + if !ismissing(server.initialization_options) && get(server.initialization_options, "julialangTestItemIdentification", false) + for uri in updated_files + testitems_results = JuliaWorkspaces.get_test_items(server.workspace, uri) + st = JuliaWorkspaces.get_text_file(server.workspace, uri).content + + testitems = TestItemDetail[TestItemDetail(i.id, i.name, Range(st, i.range), i.code, Range(st, i.code_range), i.option_default_imports, string.(i.option_tags), string.(i.option_setup)) for i in testitems_results.testitems] + testsetups= TestSetupDetail[TestSetupDetail(string(i.name), string(i.kind), Range(st, i.range), i.code, Range(st, i.code_range), ) for i in testitems_results.testsetups] + testerrors = TestErrorDetail[TestErrorDetail(te.id, te.name, Range(st, te.range), te.message) for te in testitems_results.testerrors] + + version = get(server._open_file_versions, uri, missing) + + params = PublishTestsParams( + uri, + version, + testitems, + testsetups, + testerrors + ) + JSONRPC.send(server.jr_endpoint, textDocument_publishTests_notification_type, params) + end + + for uri in deleted_files + JSONRPC.send(server.jr_endpoint, textDocument_publishTests_notification_type, PublishTestsParams(uri, missing, TestItemDetail[], TestSetupDetail[], TestErrorDetail[])) + end + end +end + + +function publish_diagnostics_testitems(server, marked_versions, uris::Vector{URI}) + updated_files = get_files_with_updated_diagnostics_testitems(server.workspace, marked_versions) + + publish_diagnostics(server, updated_files.updated_files_diag, updated_files.deleted_files_diag, uris) + publish_tests(server, updated_files.updated_files_ti, updated_files.deleted_files_ti) +end From 5c26bbce8a4b0d3a82582ea6c38361d5318769c1 Mon Sep 17 00:00:00 2001 From: David Anthoff Date: Fri, 20 Dec 2024 09:22:34 -0800 Subject: [PATCH 2/2] Fix a bug --- src/requests/textdocument.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/requests/textdocument.jl b/src/requests/textdocument.jl index 840e1433..f3ed0e91 100644 --- a/src/requests/textdocument.jl +++ b/src/requests/textdocument.jl @@ -72,7 +72,7 @@ function textDocument_didClose_notification(params::DidCloseTextDocumentParams, JuliaWorkspaces.remove_file!(server.workspace, uri) end - publish_diagnostics_testitems(server, marked_versions, []) + publish_diagnostics_testitems(server, marked_versions, JuliaWorkspaces.URIs2.URI[]) end function textDocument_didSave_notification(params::DidSaveTextDocumentParams, server::LanguageServerInstance, conn)