diff --git a/src/main/clojure/com/github/clojure_lsp/intellij/extension/language_server_factory.clj b/src/main/clojure/com/github/clojure_lsp/intellij/extension/language_server_factory.clj index a6b20d9..a94ee7e 100644 --- a/src/main/clojure/com/github/clojure_lsp/intellij/extension/language_server_factory.clj +++ b/src/main/clojure/com/github/clojure_lsp/intellij/extension/language_server_factory.clj @@ -11,6 +11,7 @@ [com.github.clojure-lsp.intellij.editor :as editor] [com.github.clojure-lsp.intellij.server :as server] [com.github.clojure-lsp.intellij.settings :as settings] + [com.github.ericdallo.clj4intellij.tasks :as tasks] [com.rpl.proxy-plus :refer [proxy+]]) (:import [com.intellij.execution.configurations GeneralCommandLine] @@ -20,6 +21,7 @@ [com.redhat.devtools.lsp4ij LSPIJUtils ServerStatus] [com.redhat.devtools.lsp4ij.client LanguageClientImpl] [com.redhat.devtools.lsp4ij.client.features LSPClientFeatures LSPProgressFeature] + [com.redhat.devtools.lsp4ij.installation LanguageServerInstallerBase] [com.redhat.devtools.lsp4ij.server OSProcessStreamConnectionProvider] [java.io File] [java.util List] @@ -27,16 +29,16 @@ (set! *warn-on-reflection* true) -(defonce ^:private server (atom {:status :not-found - :path nil})) +(defonce ^:private server-path* (atom nil)) +(defonce ^:private server-installing* (atom false)) (defn -createConnectionProvider [_ ^Project _project] - (let [server-path (loop [] - (Thread/sleep 100) - (or (settings/server-path) - (some-> ^File (:path @server) .getCanonicalPath) - (recur))) - command [server-path "listen"]] + (let [path (loop [] + (Thread/sleep 100) + (or (settings/server-path) + (some-> ^File @server-path* .getCanonicalPath) + (recur))) + command [path "listen"]] (doto (proxy+ [] OSProcessStreamConnectionProvider) @@ -48,14 +50,6 @@ (defn -getServerInterface [_] com.github.clojure_lsp.intellij.ClojureLanguageServer) -(defn ^:private install-server [project] - (swap! server assoc :status :installing) - (server/install-server - project - (fn [{:keys [status path]}] - (swap! server assoc :status status :path path) - (server/start! project)))) - (defn ^:private create-temp-file ^VirtualFile [^Project project ^String path ^String text] (let [temp-file (io/file (config/project-cache-path project) path)] @@ -96,28 +90,33 @@ (defn -createClientFeatures [_] (doto (proxy+ [] LSPClientFeatures - (isEnabled [_this ^VirtualFile file] - (case (:status @server) - :installing - false - - :installed - true - - :not-found - (do (install-server (editor/guess-project-for file)) - false))) + (keepServerAlive [_] true) (initializeParams [_ ^InitializeParams params] (.setWorkDoneToken params "clojure-lsp-startup") (.setInitializationOptions params {"dependency-scheme" "jar" "hover" {"arity-on-same-line?" true}})) (findFileByUri ^VirtualFile [_ ^String uri] (find-file-by-uri uri)) - (keepServerAlive [_] true) (handleServerStatusChanged [^LSPClientFeatures this ^ServerStatus server-status] (let [status (keyword (.toString server-status))] (db/assoc-in (.getProject this) [:status] status) (run! #(% status) (db/get-in (.getProject this) [:on-status-changed-fns]))))) (.setProgressFeature (proxy+ [] LSPProgressFeature (updateMessage [_ ^String message ^ProgressIndicator indicator] - (.setText indicator (str "LSP: " message))))))) + (.setText indicator (str "LSP: " message))))) + (.setServerInstaller (proxy+ [] LanguageServerInstallerBase + (getInstallationTaskTitle [_] "LSP: installing clojure-lsp") + (progressCheckingServerInstalled [_ indicator] (tasks/set-progress indicator "LSP: checking for clojure-lsp")) + (progressInstallingServer [_ indicator] (tasks/set-progress indicator "LSP: downloading clojure-lsp")) + (checkServerInstalled [_ _indicator] + (let [{:keys [status path]} (server/server-install-status)] + (if (identical? :installed status) + (do + (when-not @server-path* (reset! server-path* path)) + true) + false))) + (install [^LanguageServerInstallerBase this _indicator] + (when-not @server-installing* + (reset! server-installing* true) + (reset! server-path* (server/install-server! (.getProject (.getClientFeatures this)))) + (reset! server-installing* false))))))) diff --git a/src/main/clojure/com/github/clojure_lsp/intellij/server.clj b/src/main/clojure/com/github/clojure_lsp/intellij/server.clj index 6736dcc..4a0742d 100644 --- a/src/main/clojure/com/github/clojure_lsp/intellij/server.clj +++ b/src/main/clojure/com/github/clojure_lsp/intellij/server.clj @@ -7,8 +7,7 @@ [com.github.clojure-lsp.intellij.notification :as notification] [com.github.clojure-lsp.intellij.server :as server] [com.github.clojure-lsp.intellij.settings :as settings] - [com.github.ericdallo.clj4intellij.logger :as logger] - [com.github.ericdallo.clj4intellij.tasks :as tasks]) + [com.github.ericdallo.clj4intellij.logger :as logger]) (:import [com.intellij.openapi.project Project] [com.intellij.openapi.project Project] @@ -53,8 +52,7 @@ (clojure.java.io/copy stream dest-file)) (recur (.getNextEntry stream)))))) -(defn ^:private download-server! [project indicator ^File download-path ^File server-version-path latest-version] - (tasks/set-progress indicator "LSP: downloading clojure-lsp") +(defn ^:private download-server! [project ^File download-path ^File server-version-path latest-version] (let [platform (os-name) arch (os-arch) artifact-name (get-in artifacts [platform arch]) @@ -71,34 +69,37 @@ (db/assoc-in project [:downloaded-server-path] dest-path) (logger/info "Downloaded clojure-lsp to" dest-path))) -(defn install-server [project installed-fn] - (tasks/run-background-task! - project - "LSP: install clojure-lsp" - (fn [indicator] - (let [download-path (config/download-server-path) - server-version-path (config/download-server-version-path) - latest-version* (delay (try (string/trim (slurp latest-version-uri)) (catch Exception _ nil))) - custom-server-path (settings/server-path)] - (cond - custom-server-path - (installed-fn {:status :installed :path custom-server-path}) +(defn server-install-status [] + (let [download-path (config/download-server-path) + server-version-path (config/download-server-version-path) + latest-version* (delay (try (string/trim (slurp latest-version-uri)) (catch Exception _ nil))) + custom-server-path (settings/server-path)] + (cond + custom-server-path + {:status :installed :path custom-server-path} + + (and (.exists download-path) + (or (not @latest-version*) ;; on network connection issues we use any downloaded server + (= (try (slurp server-version-path) (catch Exception _ :error-checking-local-version)) + @latest-version*))) + {:status :installed :path download-path} - (and (.exists download-path) - (or (not @latest-version*) ;; on network connection issues we use any downloaded server - (= (try (slurp server-version-path) (catch Exception _ :error-checking-local-version)) - @latest-version*))) - (installed-fn {:status :installed :path download-path}) + @latest-version* + {:status :not-installed :path download-path :version @latest-version* :version-path server-version-path} - @latest-version* - (do (download-server! project indicator download-path server-version-path @latest-version*) - (installed-fn {:status :installed :path download-path})) + :else + {:status :error}))) - :else - (notification/show-notification! {:project project - :type :error - :title "Clojure LSP download error" - :message "There is no server downloaded and there was a network issue to download the latest one"})))))) +(defn install-server! [project] + (let [{:keys [status path version version-path]} (server-install-status)] + (case status + :installed path + :not-installed (do (download-server! project path version-path version) + path) + (notification/show-notification! {:project project + :type :error + :title "Clojure LSP download error" + :message "There is no server downloaded and there was a network issue to download the latest one"})))) (defn start! [^Project project] (.start (LanguageServerManager/getInstance project) "clojure-lsp"))