Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

LSP - support attaching to paths within archives #11500

Open
tknawara opened this issue Aug 15, 2024 · 3 comments
Open

LSP - support attaching to paths within archives #11500

tknawara opened this issue Aug 15, 2024 · 3 comments
Labels
A-language-server Area: Language server client C-enhancement Category: Improvements

Comments

@tknawara
Copy link

tknawara commented Aug 15, 2024

Hey,

From previous discussion around an issue with lsp go to definition, in turned out that for some languages (like JVM based languages ex: clojure). When the editor initiates a go-to-definition, the language server returns a path in the format zipfile://<actual path> the file could be a .jar file for example.

example log.txt for an interaction with clojure-lsp

2024-08-14T17:44:22.578 helix_lsp::transport [INFO] clojure-lsp -> {"jsonrpc":"2.0","method":"initialize","params":{"capabilities":{"general":{"positionEncodings":["utf-8","utf-32","utf-16"]},"textDocument":{"codeAction":{"codeActionLiteralSupport":{"codeActionKind":{"valueSet":["","quickfix","refactor","refactor.extract","refactor.inline","refactor.rewrite","source","source.organizeImports"]}},"dataSupport":true,"disabledSupport":true,"isPreferredSupport":true,"resolveSupport":{"properties":["edit","command"]}},"completion":{"completionItem":{"deprecatedSupport":true,"insertReplaceSupport":true,"resolveSupport":{"properties":["documentation","detail","additionalTextEdits"]},"snippetSupport":true,"tagSupport":{"valueSet":[1]}},"completionItemKind":{}},"formatting":{"dynamicRegistration":false},"hover":{"contentFormat":["markdown"]},"inlayHint":{"dynamicRegistration":false},"publishDiagnostics":{"tagSupport":{"valueSet":[1,2]},"versionSupport":true},"rename":{"dynamicRegistration":false,"honorsChangeAnnotations":false,"prepareSupport":true},"signatureHelp":{"signatureInformation":{"activeParameterSupport":true,"documentationFormat":["markdown"],"parameterInformation":{"labelOffsetSupport":true}}}},"window":{"workDoneProgress":true},"workspace":{"applyEdit":true,"configuration":true,"didChangeConfiguration":{"dynamicRegistration":false},"didChangeWatchedFiles":{"dynamicRegistration":true,"relativePatternSupport":false},"executeCommand":{"dynamicRegistration":false},"fileOperations":{"didRename":true,"willRename":true},"inlayHint":{"refreshSupport":false},"symbol":{"dynamicRegistration":false},"workspaceEdit":{"documentChanges":true,"failureHandling":"abort","normalizesLineEndings":false,"resourceOperations":["create","rename","delete"]},"workspaceFolders":true}},"clientInfo":{"name":"helix","version":"24.7 (079f5442)"},"processId":6150,"rootPath":"/home/tarek/workspace/clojure/ps","rootUri":"file:///home/tarek/workspace/clojure/ps","workspaceFolders":[{"name":"ps","uri":"file:///home/tarek/workspace/clojure/ps"}]},"id":0}
2024-08-14T17:44:23.131 helix_lsp::transport [INFO] clojure-lsp <- {"jsonrpc":"2.0","method":"textDocument/publishDiagnostics","params":{"uri":"file:///home/tarek/workspace/clojure/ps/src/ps/core.clj","diagnostics":[{"range":{"start":{"line":6,"character":5},"end":{"line":6,"character":9}},"tags":[1],"message":"unused binding args","code":"unused-binding","langs":[],"severity":2,"source":"clj-kondo"},{"range":{"start":{"line":9,"character":13},"end":{"line":9,"character":26}},"tags":[],"message":"Unresolved var: hk-client/get","code":"unresolved-var","langs":[],"severity":2,"source":"clj-kondo"},{"range":{"start":{"line":10,"character":13},"end":{"line":10,"character":26}},"tags":[],"message":"Unresolved var: hk-client/get","code":"unresolved-var","langs":[],"severity":2,"source":"clj-kondo"},{"range":{"start":{"line":14,"character":6},"end":{"line":14,"character":19}},"tags":[1],"message":"Unused public var 'ps.core/error-message'","code":"clojure-lsp/unused-public-var","langs":[],"severity":3,"source":"clojure-lsp"}]}}
2024-08-14T17:44:23.133 helix_lsp::transport [INFO] clojure-lsp <- {"jsonrpc":"2.0","method":"textDocument/publishDiagnostics","params":{"uri":"file:///home/tarek/workspace/clojure/ps/test/ps/core_test.clj","diagnostics":[{"range":{"start":{"line":1,"character":33},"end":{"line":1,"character":37}},"tags":[],"message":"use alias or :refer [deftest is testing]","code":"refer-all","langs":[],"severity":2,"source":"clj-kondo","data":{"refers":["deftest","is","testing"]}},{"range":{"start":{"line":2,"character":28},"end":{"line":2,"character":32}},"tags":[],"message":"use alias or :refer","code":"refer-all","langs":[],"severity":2,"source":"clj-kondo","data":{"refers":[]}}]}}
2024-08-14T17:44:23.133 helix_lsp::transport [INFO] clojure-lsp <- {"jsonrpc":"2.0","id":0,"result":{"capabilities":{"documentSymbolProvider":true,"textDocumentSync":{"openClose":true,"change":1,"save":{"includeText":true}},"declarationProvider":true,"semanticTokensProvider":{"legend":{"tokenTypes":["namespace","type","function","macro","keyword","class","variable","method","event","interface"],"tokenModifiers":["definition","defaultLibrary","implementation"]},"range":true,"full":true},"linkedEditingRangeProvider":true,"workspaceSymbolProvider":true,"experimental":{"testTree":true,"projectTree":true,"cursorInfo":true,"serverInfo":true,"clojuredocs":true},"codeActionProvider":{"codeActionKinds":["quickfix","refactor","refactor.extract","refactor.inline","refactor.rewrite","source","source.organizeImports"]},"documentHighlightProvider":true,"completionProvider":{"resolveProvider":true,"triggerCharacters":[":","/"]},"workspace":{"fileOperations":{"willRename":{"filters":[{"scheme":"file","pattern":{"glob":"**/*.{clj,cljs,cljc,cljd,edn,bb,clj_kondo}","matches":"file"}}]},"didRename":{"filters":[{"scheme":"file","pattern":{"glob":"**/*.{clj,cljs,cljc,cljd,edn,bb,clj_kondo}","matches":"file"}}]}}},"implementationProvider":true,"signatureHelpProvider":{"triggerCharacters":[]},"documentRangeFormattingProvider":true,"executeCommandProvider":{"commands":["add-import-to-namespace","add-missing-import","add-missing-libspec","add-require-suggestion","backward-barf","backward-slurp","change-coll","clean-ns","create-function","create-test","cursor-info","cycle-coll","cycle-keyword-auto-resolve","cycle-privacy","demote-fn","destructure-keys","drag-backward","drag-forward","drag-param-backward","drag-param-forward","expand-let","extract-function","extract-to-def","forward-barf","forward-slurp","get-in-all","get-in-less","get-in-more","get-in-none","inline-symbol","introduce-let","kill-sexp","move-coll-entry-down","move-coll-entry-up","move-form","move-to-let","promote-fn","raise-sexp","replace-refer-all-with-alias","replace-refer-all-with-refer","resolve-macro-as","restructure-keys","server-info","sort-clauses","sort-map","suppress-diagnostic","thread-first","thread-first-all","thread-last","thread-last-all","unwind-all","unwind-thread"]},"referencesProvider":true,"codeLensProvider":{"resolveProvider":true},"foldingRangeProvider":true,"callHierarchyProvider":true,"documentFormattingProvider":true,"renameProvider":{"prepareProvider":true},"definitionProvider":true,"hoverProvider":true}}}
2024-08-14T17:44:23.133 helix_lsp::transport [INFO] clojure-lsp <- {"capabilities":{"callHierarchyProvider":true,"codeActionProvider":{"codeActionKinds":["quickfix","refactor","refactor.extract","refactor.inline","refactor.rewrite","source","source.organizeImports"]},"codeLensProvider":{"resolveProvider":true},"completionProvider":{"resolveProvider":true,"triggerCharacters":[":","/"]},"declarationProvider":true,"definitionProvider":true,"documentFormattingProvider":true,"documentHighlightProvider":true,"documentRangeFormattingProvider":true,"documentSymbolProvider":true,"executeCommandProvider":{"commands":["add-import-to-namespace","add-missing-import","add-missing-libspec","add-require-suggestion","backward-barf","backward-slurp","change-coll","clean-ns","create-function","create-test","cursor-info","cycle-coll","cycle-keyword-auto-resolve","cycle-privacy","demote-fn","destructure-keys","drag-backward","drag-forward","drag-param-backward","drag-param-forward","expand-let","extract-function","extract-to-def","forward-barf","forward-slurp","get-in-all","get-in-less","get-in-more","get-in-none","inline-symbol","introduce-let","kill-sexp","move-coll-entry-down","move-coll-entry-up","move-form","move-to-let","promote-fn","raise-sexp","replace-refer-all-with-alias","replace-refer-all-with-refer","resolve-macro-as","restructure-keys","server-info","sort-clauses","sort-map","suppress-diagnostic","thread-first","thread-first-all","thread-last","thread-last-all","unwind-all","unwind-thread"]},"experimental":{"clojuredocs":true,"cursorInfo":true,"projectTree":true,"serverInfo":true,"testTree":true},"foldingRangeProvider":true,"hoverProvider":true,"implementationProvider":true,"linkedEditingRangeProvider":true,"referencesProvider":true,"renameProvider":{"prepareProvider":true},"semanticTokensProvider":{"full":true,"legend":{"tokenModifiers":["definition","defaultLibrary","implementation"],"tokenTypes":["namespace","type","function","macro","keyword","class","variable","method","event","interface"]},"range":true},"signatureHelpProvider":{"triggerCharacters":[]},"textDocumentSync":{"change":1,"openClose":true,"save":{"includeText":true}},"workspace":{"fileOperations":{"didRename":{"filters":[{"pattern":{"glob":"**/*.{clj,cljs,cljc,cljd,edn,bb,clj_kondo}","matches":"file"},"scheme":"file"}]},"willRename":{"filters":[{"pattern":{"glob":"**/*.{clj,cljs,cljc,cljd,edn,bb,clj_kondo}","matches":"file"},"scheme":"file"}]}}},"workspaceSymbolProvider":true}}
2024-08-14T17:44:23.133 helix_lsp::transport [INFO] clojure-lsp -> {"jsonrpc":"2.0","method":"initialized","params":{}}
2024-08-14T17:44:23.134 helix_lsp::transport [INFO] clojure-lsp -> {"jsonrpc":"2.0","method":"textDocument/didOpen","params":{"textDocument":{"languageId":"clojure","text":"(ns ps.core\n  (:gen-class)\n  (:require [org.httpkit.client :as hk-client]))\n\n(defn -main\n  \"I don't do a whole lot ... yet.\"\n  [& args]\n  (println \"Hello, World!\"))\n\n(let [resp1 (hk-client/get \"http://http-kit.org/\")\n      resp2 (hk-client/get \"http://clojure.org/\")]\n  (println \"Response 1's status: \" (:status @resp1))\n  (println \"Response 2's status: \" (:status @resp2)))\n\n(defn error-message\n  [severity]\n  (str \"OH GOD! IT'S A DISASTER! WE'RE \"\n       (if (= severity :mild)\n         \"MILDLY INCONVENIENCED!\"\n         \"DOOOOOOOOMED!\")))\n","uri":"file:///home/tarek/workspace/clojure/ps/src/ps/core.clj","version":0}}}
2024-08-14T17:44:23.136 helix_lsp::transport [INFO] clojure-lsp <- {"jsonrpc":"2.0","method":"client/registerCapability","params":{"registrations":[{"id":"id","method":"workspace/didChangeWatchedFiles","registerOptions":{"watchers":[{"globPattern":"**/*.{clj,cljs,cljc,cljd,edn,bb,clj_kondo}"}]}}]},"id":1}
2024-08-14T17:44:23.136 helix_lsp::transport [INFO] clojure-lsp -> {"jsonrpc":"2.0","result":null,"id":1}
2024-08-14T17:44:23.204 helix_lsp::transport [INFO] clojure-lsp <- {"jsonrpc":"2.0","method":"textDocument/publishDiagnostics","params":{"uri":"file:///home/tarek/workspace/clojure/ps/src/ps/core.clj","diagnostics":[{"range":{"start":{"line":6,"character":5},"end":{"line":6,"character":9}},"tags":[1],"message":"unused binding args","code":"unused-binding","langs":[],"severity":2,"source":"clj-kondo"},{"range":{"start":{"line":9,"character":13},"end":{"line":9,"character":26}},"tags":[],"message":"Unresolved var: hk-client/get","code":"unresolved-var","langs":[],"severity":2,"source":"clj-kondo"},{"range":{"start":{"line":10,"character":13},"end":{"line":10,"character":26}},"tags":[],"message":"Unresolved var: hk-client/get","code":"unresolved-var","langs":[],"severity":2,"source":"clj-kondo"},{"range":{"start":{"line":14,"character":6},"end":{"line":14,"character":19}},"tags":[1],"message":"Unused public var 'ps.core/error-message'","code":"clojure-lsp/unused-public-var","langs":[],"severity":3,"source":"clojure-lsp"}]}}
2024-08-14T17:44:27.107 helix_lsp::transport [INFO] clojure-lsp -> {"jsonrpc":"2.0","method":"textDocument/definition","params":{"position":{"character":24,"line":9},"textDocument":{"uri":"file:///home/tarek/workspace/clojure/ps/src/ps/core.clj"}},"id":1}
2024-08-14T17:44:27.113 helix_lsp::transport [INFO] clojure-lsp <- {"jsonrpc":"2.0","id":1,"result":{"uri":"zipfile:///home/tarek/.m2/repository/http-kit/http-kit/2.8.0/http-kit-2.8.0.jar::org/httpkit/client.clj","range":{"start":{"line":0,"character":4},"end":{"line":0,"character":22}}}}
2024-08-14T17:44:27.113 helix_lsp::transport [INFO] clojure-lsp <- {"range":{"end":{"character":22,"line":0},"start":{"character":4,"line":0}},"uri":"zipfile:///home/tarek/.m2/repository/http-kit/http-kit/2.8.0/http-kit-2.8.0.jar::org/httpkit/client.clj"}
2024-08-14T17:44:27.113 helix_lsp::transport [INFO] clojure-lsp -> {"jsonrpc":"2.0","method":"textDocument/didOpen","params":{"textDocument":{"languageId":"clojure","text":"\n","uri":"file:///home/tarek/.m2/repository/http-kit/http-kit/2.8.0/http-kit-2.8.0.jar::org/httpkit/client.clj","version":0}}}
2024-08-14T17:44:27.168 helix_lsp::transport [INFO] clojure-lsp <- {"jsonrpc":"2.0","method":"textDocument/publishDiagnostics","params":{"uri":"file:///home/tarek/.m2/repository/http-kit/http-kit/2.8.0/http-kit-2.8.0.jar::org/httpkit/client.clj","diagnostics":[]}}
2024-08-14T17:44:30.068 helix_lsp::transport [INFO] clojure-lsp -> {"jsonrpc":"2.0","method":"shutdown","id":2}
2024-08-14T17:44:30.069 helix_lsp::transport [INFO] clojure-lsp <- {"jsonrpc":"2.0","id":2,"result":null}
2024-08-14T17:44:30.069 helix_lsp::transport [INFO] clojure-lsp <- null
2024-08-14T17:44:30.069 helix_lsp::transport [INFO] clojure-lsp -> {"jsonrpc":"2.0","method":"exit"}

This is the path given by the server

2024-08-14T17:44:27.113 helix_lsp::transport [INFO] clojure-lsp <- {"jsonrpc":"2.0","id":1,"result":{"uri":"zipfile:///home/tarek/.m2/repository/http-kit/http-kit/2.8.0/http-kit-2.8.0.jar::org/httpkit/client.clj","range":{"start":{"line":0,"character":4},"end":{"line":0,"character":22}}}}

and lsp implementation

atm, helix doesn't support attaching to these paths, the current behavior is to show an empty buffer, but there is a fix to show proper error messages for when the editor can't attach to the path given by the lsp.

Having proper errors in place is great, but it would be even better to support this use case, here are similar efforts done by other editors, example neovim.

@tknawara tknawara added the C-enhancement Category: Improvements label Aug 15, 2024
@the-mikedavis the-mikedavis changed the title LSP - support attaching to paths within archieve LSP - support attaching to paths within archives Aug 16, 2024
@kirawi
Copy link
Member

kirawi commented Aug 27, 2024

It doesn't sound to me like this is part of the LSP standard, so this would likely have to be implemented as a plugin.

@kirawi kirawi added the A-plugin Area: Plugin system label Aug 27, 2024
@the-mikedavis
Copy link
Member

This is not quite an extension to the LSP spec: the spec allows sending any kind of URI and the zipfile://path-to-file.zip::path-within-zip URI does seem to be valid and has some use by other editors. Whether opening files within zipfiles is in scope for core I'm not sure and don't have a strong opinion on.

@kirawi kirawi added A-language-server Area: Language server client and removed A-plugin Area: Plugin system labels Aug 27, 2024
@pascalkuthe
Copy link
Member

I think this is kne of the "non-standardized" clientside features. Same as client-side commands. They are technicallypart of the spec but it's just a blackboard string and the implementation is up to the server/client. So it feels like this is out of scope for similar reasons that client-side commands are out of scope.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-language-server Area: Language server client C-enhancement Category: Improvements
Projects
None yet
Development

No branches or pull requests

4 participants