|
| 1 | +;;; lsp-java.el --- Spring boot support for lsp-java |
| 2 | + |
| 3 | +;; Version: 2.0 |
| 4 | +;; Keywords: java |
| 5 | +;; URL: https://github.com/emacs-lsp/lsp-java |
| 6 | + |
| 7 | +;; This program is free software: you can redistribute it and/or modify |
| 8 | +;; it under the terms of the GNU General Public License as published by |
| 9 | +;; the Free Software Foundation, either version 3 of the License, or |
| 10 | +;; (at your option) any later version. |
| 11 | + |
| 12 | +;; This program is distributed in the hope that it will be useful, |
| 13 | +;; but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 14 | +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| 15 | +;; GNU General Public License for more details. |
| 16 | + |
| 17 | +;; You should have received a copy of the GNU General Public License |
| 18 | +;; along with this program. If not, see <http://www.gnu.org/licenses/>. |
| 19 | + |
| 20 | +;;; Commentary: LSP Java support for Spring Boot. |
| 21 | + |
| 22 | +;;; Code: |
| 23 | + |
| 24 | +(require 'dash) |
| 25 | +(require 'lsp-mode) |
| 26 | +(require 'lsp-java) |
| 27 | +(require 'cl) |
| 28 | + |
| 29 | +(defcustom lsp-java-boot-enabled t |
| 30 | + "If non-nil start the boot server when opening java files." |
| 31 | + :group 'lsp-java-boot |
| 32 | + :type 'boolean) |
| 33 | + |
| 34 | +(defcustom lsp-java-boot-java-tools-jar nil |
| 35 | + "Path to tools jar. If it is not specified it will be calculated using `JAVA_HOME'." |
| 36 | + :group 'lsp-java-boot |
| 37 | + :type 'file) |
| 38 | + |
| 39 | +(defvar lsp-java-boot--callback nil) |
| 40 | + |
| 41 | +(defun lsp-java-boot--find-tools-jar () |
| 42 | + "Calculate the path to tools.jar." |
| 43 | + (let ((tools-jar (or lsp-java-boot-java-tools-jar |
| 44 | + (f-join (getenv "JAVA_HOME") "lib/tools.jar")))) |
| 45 | + (unless (f-exists? tools-jar) |
| 46 | + (error "Please configure either JAVA_HOME or lsp-java-boot-java-tools-jar")) |
| 47 | + tools-jar)) |
| 48 | + |
| 49 | +(defun lsp-java--sts-javadoc-hover-link (_workspace params) |
| 50 | + "Handler for java doc hover." |
| 51 | + (with-lsp-workspace (lsp-find-workspace 'jdtls nil) |
| 52 | + (lsp-request "workspace/executeCommand" |
| 53 | + (list :command "sts.java.addClasspathListener" |
| 54 | + :arguments (gethash "callbackCommandId" params)) |
| 55 | + :no-wait t))) |
| 56 | + |
| 57 | +(defun lsp-java-boot--sts-add-classpath-listener (_workspace params) |
| 58 | + (with-lsp-workspace (lsp-find-workspace 'jdtls nil) |
| 59 | + (lsp-request "workspace/executeCommand" |
| 60 | + (list :command "sts.java.addClasspathListener" |
| 61 | + :arguments (gethash "callbackCommandId" params)) |
| 62 | + :no-wait t))) |
| 63 | + |
| 64 | +(defun lsp-java-boot--workspace-execute-client-command (_jdt-ls-workspace params) |
| 65 | + "PARAMS is the classpath info." |
| 66 | + (with-lsp-workspace (lsp-find-workspace 'boot-ls nil) |
| 67 | + (-let (((&hash "command" "arguments") params)) |
| 68 | + (setf (nth 2 arguments) (if (nth 2 arguments) t :json-false)) |
| 69 | + (lsp-request "workspace/executeCommand" |
| 70 | + (list :command command :arguments arguments) |
| 71 | + :no-wait t)))) |
| 72 | + |
| 73 | +(defun lsp-java-boot--lens-backend (_ callback) |
| 74 | + "Boot backend. |
| 75 | +Store CALLBACK to use it `sts/highlight'." |
| 76 | + (setq-local lsp-java-boot--callback callback)) |
| 77 | + |
| 78 | +;;;###autoload |
| 79 | +(define-minor-mode lsp-java-boot-lens-mode |
| 80 | + "Toggle code-lens overlays." |
| 81 | + :group 'lsp-java-boot |
| 82 | + :global nil |
| 83 | + :init-value nil |
| 84 | + :lighter "BLens" |
| 85 | + (cond |
| 86 | + (lsp-java-boot-lens-mode |
| 87 | + (setq-local lsp-lens-backends (pushnew 'lsp-java-boot--lens-backend lsp-lens-backends)) |
| 88 | + (lsp--lens-refresh t)) |
| 89 | + (t (setq-local lsp-lens-backends (delete 'lsp-java-boot--lens-backend lsp-lens-backends)) |
| 90 | + (setq-local lsp-java-boot--callback nil)))) |
| 91 | + |
| 92 | +(cl-defmethod lsp-execute-command |
| 93 | + (server (command (eql sts.open.url)) params) |
| 94 | + (browse-url (first params))) |
| 95 | + |
| 96 | +(cl-defmethod lsp-execute-command (server (command (eql sts.showHoverAtPosition)) params) |
| 97 | + (goto-char (lsp--position-to-point (first params))) |
| 98 | + (lsp-describe-thing-at-point)) |
| 99 | + |
| 100 | +(defun lsp-java-boot--sts/hightlight (workspace params) |
| 101 | + "WORKSPACE PARAMS." |
| 102 | + (with-lsp-workspace workspace |
| 103 | + (-let (((&hash "doc" (&hash "uri" "version") "codeLenses" code-lenses) params)) |
| 104 | + (when-let (buf (find-buffer-visiting (lsp--uri-to-path uri))) |
| 105 | + (with-current-buffer buf |
| 106 | + (when (and lsp-java-boot--callback lsp-java-boot-lens-mode) |
| 107 | + (funcall lsp-java-boot--callback code-lenses version))))))) |
| 108 | + |
| 109 | +(defun lsp-java-boot--server-jar () |
| 110 | + "Return the spring boot jar." |
| 111 | + (or (-> lsp-java-server-install-dir |
| 112 | + (expand-file-name) |
| 113 | + (f-join "boot-server") |
| 114 | + f-files |
| 115 | + first) |
| 116 | + (lsp-log "Unable to find spring boot server jar."))) |
| 117 | + |
| 118 | +(defun lsp-java-boot--ls-command (port) |
| 119 | + "Create LS command for PORT." |
| 120 | + (list lsp-java-java-path |
| 121 | + (format "-Dloader.path=%s" (lsp-java-boot--find-tools-jar)) |
| 122 | + (format "-Dspring.lsp.client-port=%s" port) |
| 123 | + (format "-Dserver.port=%s" port) |
| 124 | + "-Dsts.lsp.client=vscode" |
| 125 | + (concat "-Dsts.log.file=" (make-temp-file "sts-log-file" nil ".log")) |
| 126 | + (concat "-Dlogging.file=" (make-temp-file "logging-file" nil ".log")) |
| 127 | + "-jar" |
| 128 | + (lsp-java-boot--server-jar))) |
| 129 | + |
| 130 | +(lsp-register-client |
| 131 | + (make-lsp-client :new-connection |
| 132 | + (lsp-tcp-server #'lsp-java-boot--ls-command) |
| 133 | + :activation-fn (lambda (filename major-mode) |
| 134 | + (and lsp-java-boot-enabled |
| 135 | + (memq major-mode '(java-mode conf-javaprop-mode yaml-mode)) |
| 136 | + (lsp-java-boot--server-jar))) |
| 137 | + :request-handlers (ht ("sts/addClasspathListener" #'lsp-java-boot--sts-add-classpath-listener) |
| 138 | + ("sts/javadocHoverLink" #'lsp-java--sts-javadoc-hover-link)) |
| 139 | + :notification-handlers (ht ("sts/highlight" #'lsp-java-boot--sts/hightlight) |
| 140 | + ("sts/progress" #'ignore)) |
| 141 | + :initialized-fn (lambda (workspace) |
| 142 | + (puthash |
| 143 | + "triggerCharacters" |
| 144 | + '("." "@" "#" "*") |
| 145 | + (gethash "completionProvider" (lsp--workspace-server-capabilities workspace)))) |
| 146 | + :multi-root t |
| 147 | + :add-on? t |
| 148 | + :server-id 'boot-ls)) |
| 149 | + |
| 150 | +(provide 'lsp-java-boot) |
| 151 | +;;; lsp-java-boot.el ends here |
0 commit comments