Skip to content

Commit

Permalink
Per joaotavora/eglot#63: Add support for eclipse.jdt.ls server
Browse files Browse the repository at this point in the history
* eglot.el (eglot-server-programs): Add java-mode entry.
(eglot-eclipse-jdt): New class.
(eglot-initialization-options): Override for eglot-eclipse-jdt.
(eglot--eclipse-jdt-contact): New function.
  • Loading branch information
mkcms committed Oct 18, 2018
1 parent 41810ac commit 77e9831
Showing 1 changed file with 93 additions and 1 deletion.
94 changes: 93 additions & 1 deletion lisp/progmodes/eglot.el
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,9 @@
language-server/bin/php-language-server.php"))
(haskell-mode . ("hie-wrapper"))
(kotlin-mode . ("kotlin-language-server"))
(go-mode . ("go-langserver" "-mode=stdio" "-gocodecompletion")))
(go-mode . ("go-langserver" "-mode=stdio"
"-gocodecompletion"))
(java-mode . eglot--eclipse-jdt-contact))
"How the command `eglot' guesses the server to start.
An association list of (MAJOR-MODE . CONTACT) pairs. MAJOR-MODE
is a mode symbol, or a list of mode symbols. The associated
Expand Down Expand Up @@ -1892,6 +1894,96 @@ If SKIP-SIGNATURE, don't try to send textDocument/signatureHelp."
(list :cacheDirectory (file-name-as-directory cache)
:progressReportFrequencyMs -1)))


;;; eclipse-jdt-specific
;;;
(defclass eglot-eclipse-jdt (eglot-lsp-server) ()
:documentation "Eclipse's Java Development Tools Language Server.")

(cl-defmethod eglot-initialization-options ((server eglot-eclipse-jdt))
"Passes through required jdt initialization options"
`(:workspaceFolders
[,@(cl-delete-duplicates
(mapcar #'eglot--path-to-uri
(let* ((roots (project-roots (eglot--project server)))
(root (car roots)))
(append
roots
(mapcar
#'file-name-directory
(append
(file-expand-wildcards (concat root "*/pom.xml"))
(file-expand-wildcards (concat root "*/build.gradle"))
(file-expand-wildcards (concat root "*/.project")))))))
:test #'string=)]
,@(if-let ((home (or (getenv "JAVA_HOME")
(ignore-errors
(expand-file-name
".."
(file-name-directory
(file-chase-links (executable-find "javac"))))))))
`(:settings (:java (:home ,home)))
(ignore (eglot--warn "JAVA_HOME env var not set")))))

(defun eglot--eclipse-jdt-contact (interactive)
"Return a contact for connecting to eclipse.jdt.ls server, as a cons cell."
(cl-labels
((is-the-jar
(path)
(and (string-match-p
"org\\.eclipse\\.equinox\\.launcher_.*\\.jar$"
(file-name-nondirectory path))
(file-exists-p path))))
(let* ((classpath (or (getenv "CLASSPATH") ":"))
(cp-jar (cl-find-if #'is-the-jar (split-string classpath ":")))
(jar cp-jar)
(dir
(cond
(jar (file-name-as-directory
(expand-file-name ".." (file-name-directory jar))))
(interactive
(expand-file-name
(read-directory-name
(concat "Path to eclipse.jdt.ls directory (could not"
" find it in CLASSPATH): ")
nil nil t)))
(t (error "Could not find eclipse.jdt.ls jar in CLASSPATH"))))
(repodir
(concat dir
"org.eclipse.jdt.ls.product/target/repository/"))
(repodir (if (file-directory-p repodir) repodir dir))
(config
(concat
repodir
(cond
((string= system-type "darwin") "config_mac")
((string= system-type "windows-nt") "config_win")
(t "config_linux"))))
(workspace
(expand-file-name (md5 (car (project-roots (project-current))))
(concat user-emacs-directory
"eglot-eclipse-jdt-cache"))))
(unless jar
(setq jar
(cl-find-if #'is-the-jar
(directory-files (concat repodir "plugins") t))))
(unless (and jar (file-exists-p jar) (file-directory-p config))
(error "Could not find required eclipse.jdt.ls files (build required?)"))
(when (and interactive (not cp-jar)
(y-or-n-p (concat "Add path to the server program "
"to CLASSPATH environment variable?")))
(setenv "CLASSPATH" (concat (getenv "CLASSPATH") ":" jar)))
(unless (file-directory-p workspace)
(make-directory workspace t))
(cons 'eglot-eclipse-jdt
(list (executable-find "java")
"-Declipse.application=org.eclipse.jdt.ls.core.id1"
"-Dosgi.bundles.defaultStartLevel=4"
"-Declipse.product=org.eclipse.jdt.ls.core.product"
"-jar" jar
"-configuration" config
"-data" workspace)))))


;; FIXME: A horrible hack of Flymake's insufficient API that must go
;; into Emacs master, or better, 26.2
Expand Down

0 comments on commit 77e9831

Please sign in to comment.