Coder Social home page Coder Social logo

eglot-java's People

Contributors

francesco-cadei avatar lina-bh avatar magielbruntink avatar tomrss avatar yveszoundi avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar

eglot-java's Issues

Cannot launch while trying to use Nix to provide jdtls.

I really enjoy this package, but it wholly expects us to let it manage the download and build of the JDT Language Server.

This is fine for most cases. However, if you're a weirdo like me, who strives to make their configurations work as reliably as possible across systems, we like to use things like Nix/OS to provide runtime dependencies. This is mainly because in the nixpkgs stable checkout we can usually expect all of the runtime dependencies to work together really well. When we update our things, if they break due to some change in requirements, we can roll back until such a time that we can investigate what changed.

It would be nice if we could configure eglot-java to not have hard-coded paths to the jdt language server launcher, or the launcher config directory. Or better yet, be able to take an arbitrary launch command for the guess contact function to accept and use to bypass the built-in convenience features :)

Thoughts?

Support running specific @Test method

Problem

Currently it's only possible to run tests for an entire class.

Proposed Solution

Approach

The eglot-java-run-test function behavior will be changed:

  • If there's an enclosing method near the current cursor location ("the point"), that specific method will be executed
  • Otherwise, all the tests in the current file will be executed (current behavior at this time)

Technical constraints

There's no built-in LSP server handler that will return automatically all the available test methods in a given file.

If the mouse cursor is near a helper method, this package will blindly assume that "you know what you're doing" and you'll get an error message from the Junit console logs.

Crashes on Emacs master. `exited abnormally with code 13`

I am editing a simple Java for Android project, and (eglot-java-mode) does not even start.
Error buffer:

[jsonrpc] D[09:52:40.631] Running language server: /usr/lib64/zulu-openjdk11/bin/java -Declipse.application=org.eclipse.jdt.ls.core.id1 -Dosgi.bundles.defaultStartLevel=4 -Declipse.product=org.eclipse.jdt.ls.core.product -jar /home/lockywolf/.emacs.d/share/eclipse.jdt.ls/plugins/org.eclipse.equinox.launcher_1.6.700.v20231214-2017.jar -configuration /home/lockywolf/.emacs.d/share/eclipse.jdt.ls/config_linux -data /home/lockywolf/.emacs.d/eglot-java-eclipse-jdt-cache/fb975d1c5daaeb77385e3b232729edd2
[jsonrpc] e[09:52:40.633] --> initialize[1] {"jsonrpc":"2.0","id":1,"method":"initialize","params":{"processId":4795,"clientInfo":{"name":"Eglot","version":"1.15"},"rootPath":"/home/lockywolf/OfficialRepos/Telegram/TMessagesProj/","rootUri":"file:///home/lockywolf/OfficialRepos/Telegram/TMessagesProj","initializationOptions":{"extendedClientCapabilities":{"classFileContentsSupport":true},"workspaceFolders":["file:///home/lockywolf/OfficialRepos/Telegram/TMessagesProj"],"settings":{"java":{"home":"/usr/lib64/zulu-openjdk8"},"import":{"gradle":{"enabled":true},"wrapper":{"enabled":true}}}},"capabilities":{"workspace":{"applyEdit":true,"executeCommand":{"dynamicRegistration":false},"workspaceEdit":{"documentChanges":true},"didChangeWatchedFiles":{"dynamicRegistration":true},"symbol":{"dynamicRegistration":false},"configuration":true,"workspaceFolders":true},"textDocument":{"synchronization":{"dynamicRegistration":false,"willSave":true,"willSaveWaitUntil":true,"didSave":true},"completion":{"dynamicRegistration":false,"completionItem":{"snippetSupport":true,"deprecatedSupport":true,"resolveSupport":{"properties":["documentation","details","additionalTextEdits"]},"tagSupport":{"valueSet":[1]}},"contextSupport":true},"hover":{"dynamicRegistration":false,"contentFormat":["markdown","plaintext"]},"signatureHelp":{"dynamicRegistration":false,"signatureInformation":{"parameterInformation":{"labelOffsetSupport":true},"documentationFormat":["markdown","plaintext"],"activeParameterSupport":true}},"references":{"dynamicRegistration":false},"definition":{"dynamicRegistration":false,"linkSupport":true},"declaration":{"dynamicRegistration":false,"linkSupport":true},"implementation":{"dynamicRegistration":false,"linkSupport":true},"typeDefinition":{"dynamicRegistration":false,"linkSupport":true},"documentSymbol":{"dynamicRegistration":false,"hierarchicalDocumentSymbolSupport":true,"symbolKind":{"valueSet":[1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26]}},"documentHighlight":{"dynamicRegistration":false},"codeAction":{"dynamicRegistration":false,"resolveSupport":{"properties":["edit","command"]},"dataSupport":true,"codeActionLiteralSupport":{"codeActionKind":{"valueSet":["quickfix","refactor","refactor.extract","refactor.inline","refactor.rewrite","source","source.organizeImports"]}},"isPreferredSupport":true},"formatting":{"dynamicRegistration":false},"rangeFormatting":{"dynamicRegistration":false},"rename":{"dynamicRegistration":false},"inlayHint":{"dynamicRegistration":false},"publishDiagnostics":{"relatedInformation":false,"codeDescriptionSupport":false,"tagSupport":{"valueSet":[1,2]}}},"window":{"showDocument":{"support":true},"workDoneProgress":true},"general":{"positionEncodings":["utf-32","utf-8","utf-16"]},"experimental":{}},"workspaceFolders":[{"uri":"file:///home/lockywolf/OfficialRepos/Telegram/TMessagesProj","name":"~/OfficialRepos/Telegram/TMessagesProj/"}]}}
[stderr]  Picked up _JAVA_OPTIONS:  -Dsun.java2d.uiScale=1.35 -Dawt.useSystemAAFontSettings=on -Dswing.aatext=true -Dswing.defaultlaf=com.sun.java.swing.plaf.gtk.GTKLookAndFeel -Dswing.crossplatformlaf=com.sun.java.swing.plaf.gtk.GTKLookAndFeel
[stderr]  Jan 19, 2024 9:52:41 AM org.apache.aries.spifly.BaseActivator log
[stderr]  INFO: Registered provider ch.qos.logback.classic.servlet.LogbackServletContainerInitializer of service jakarta.servlet.ServletContainerInitializer in bundle ch.qos.logback.classic
[stderr]  Jan 19, 2024 9:52:41 AM org.apache.aries.spifly.BaseActivator log
[stderr]  INFO: Registered provider ch.qos.logback.classic.spi.LogbackServiceProvider of service org.slf4j.spi.SLF4JServiceProvider in bundle ch.qos.logback.classic
[jsonrpc] D[09:52:41.541] Connection state change: `exited abnormally with code 13
'

----------b---y---e---b---y---e----------
[stderr]  
[stderr]  
[stderr]  nil
[stderr]  nil
[stderr]  Process EGLOT (TMessagesProj/(java-mode java-ts-mode)) stderr finished

how to use dape with junit in java-debug

Hi, I managed to use eglot-java to setup dape to debug when there is a main method in class, but got error when integrate dape with junit in test mehod. Is there a demo for setting up junit test method debug works?

image

FYI, thanks for your package, it saves me lots of time 😄

Support JDT URIs from textDocument/defintion requests

I have been looking at an issue over in the JDT LSP repository: eclipse-jdtls/eclipse.jdt.ls#2322

A summary of how I reproduce this issue (with the latest snapshot of jdtls, not using eglot-java at all)

  • Add this entry to the eglot-server-programs: (java-mode . ("jdtls" :initializationOptions (:extendedClientCapabilities (:classFileContentsSupport t))))
  • clone groot, commit 1f275a41cb63dfb985c797934005bcd7159ed0a7
  • cd groot && mvn compile
  • visit groot/src/main/java/org/jlab/groot/math/F1D.java
  • Execute xref-find-definitions on the Expression symbol on line 23

The relevant eglot logs

(:jsonrpc "2.0" :id 8 :method "textDocument/definition" :params
          (:textDocument
           (:uri "file:///home/user/dev/groot/src/main/java/org/jlab/groot/math/F1D.java")
           :position
           (:line 22 :character 4)))
[server-reply] (id:8) Sun Nov 13 13:37:57 2022:
(:jsonrpc "2.0" :id 8 :result
          [(:uri "jdt://contents/exp4j-0.4.4.jar/net.objecthunter.exp4j/Expression.class?=groot/%5C/home%5C/user%5C/.m2%5C/repository%5C/net%5C/objecthunter%5C/exp4j%5C/0.4.4%5C/exp4j-0.4.4.jar=/maven.pomderived=/true=/=/javadoc_location=/jar:file:%5C/home%5C/user%5C/.m2%5C/repository%5C/net%5C/objecthunter%5C/exp4j%5C/0.4.4%5C/exp4j-0.4.4-javadoc.jar%5C!%5C/=/=/maven.groupId=/net.objecthunter=/=/maven.artifactId=/exp4j=/=/maven.version=/0.4.4=/=/maven.scope=/compile=/=/maven.pomderived=/true=/%3Cnet.objecthunter.exp4j(Expression.class" :range
                 (:start
                  (:line 24 :character 13)
                  :end
                  (:line 24 :character 23)))])

I think this package would be a good place to handle those JDT URIs. There is a reply in the issue over in JDTLS repository that explains the process for handling them. Essentially the client must make an extra request to the java/classFileContents method of the language server, which will serve back the contents of the decompiled class. From there the client is free to dump the contents into a buffer.

I would be happy to take a swing at implementing this here at some point, but wanted to drop an issue here in case someone else wants to try and beat me to it.

Add few more custom variables

Background

Since 2017-2018 (before the code was even on GitHub), eglot-java always had very minimal configuration options for the Eclipse JDT language server. It might be time to add few settings found in forks.

Problem

It's not possible to manual define the following

  • JAVA_HOME location
  • An explicit PATH to the java executable, if the java executable is not already in the user PATH environment variable
  • Few gradle options
    • Enabling/Disabling gradle wrapper support at the Java language server level
    • Specifying a Gradle version when Gradle wrapper support is disabled or missing

Discussion: run/debug configurations

Now that with eglot-java it's possible to easily run main classes and test classes/methods, I would like to understand how it could support specific configurations for such runs.

The following come to mind:

  • environment vars
  • main class args
  • other JVM args

One specific case is for projects that use Lombok. With the following in .dir-locals.el we can convince jdtls to process Lombok's annotations:

((nil . ((eval . (setq-local eglot-java-eclipse-jdt-args
                             (push (concat "-javaagent:" "/PATH/TO/lombok.jar")
                                   eglot-java-eclipse-jdt-args))))))

I wonder whether .dir-locals.el is a good mechanism to set Java run configurations in general. For main class args that doesn't seem very convenient, but for environment vars and JVM args it may be.

What are you thoughts?

Gracefully support older eglot versions

Background

Obsolete eglot functions were removed as part of #37, as well as some "hacks" (AOP advices) handling older eglot versions. This removes compilation warnings (among other things), but introduce challenging side effects.

Problem

When people get error messages such as void function eglot-path-to-uri, there are no clear action items:

  • This pertains especially for new emacs users ("... but I'm using the built-in eglot version in Emacs ...")
  • This is also applicable to other emacs users, who don't really know or care that much about how eglot itself works
    • They might be managing their packages differently (git submodules, guix, nixos, etc.)
    • It might take lots of time and documentation to explain what is going on and what to do (what to update and where, all that accordingly to their specific operating system which is problematic in the context of Linux distributions for specific support)

See this reddit comment thread as reference: https://www.reddit.com/r/emacs/comments/1ce0ho9/comment/l1h36jn/

Additional Information

Screenshot of the problem for someone using the built-in eglot version on Arch Linux.
eglot-java-startup-err

Impacts

Users cannot start eglot-java.

The functions and hacks removed create problems for users running older eglot and emacs versions.

  • People using older emacs versions that have older eglot built-in (tough to explain: upgrade packages, compile emacs, etc.)
  • People using older eglot.el packages from either MELPA or GNU ELPA (easier to tell people to upgrade here): See the end of this comment.

Proposed Soluion

Undo changes introduced in #37, without trying to conditionally add aliases and other logic (defalias and more code branches).

Infinite loop with project-root function on emacs-master?

Background

The initial rationale was to used default project.el functions (See #35). This essentially seems to translate into an infinite loop, maybe only on emacs-master.

  • As of few days ago, I didn't have issues with a local build based on the emacs-29 branch.
  • I only switched to the emacs master branch on Feb 26th.
(cl-defmethod project-root ((project (head java)))
  "Get the root of a JAVA PROJECT."
  (project-root project))

Emacs version

Emacs git master: GNU Emacs 30.0.50 (build 1, x86_64-pc-linux-gnu, GTK+ Version 3.24.33, cairo version 1.16.0) of 2024-02-26

How to reproduce

Example on a Git versioned Java project (maven-wrapper), open any Java file.

Debugger entered--Lisp error: (error "Lisp nesting exceeds ‘max-lisp-eval-depth’")
  project-root((java . "~/Projects/maven-wrapper/"))
  #f(compiled-function (project) "Get the root of a JAVA PROJECT." #<bytecode 0x1383aa4aefdec6fc>)((java . "~/Projects/maven-wrapper/"))
  apply(#f(compiled-function (project) "Get the root of a JAVA PROJECT." #<bytecode 0x1383aa4aefdec6fc>) (java . "~/Projects/maven-wrapper/") nil)
  #f(compiled-function (arg &rest args) #<bytecode 0x18d0a9b38b36bb46>)((java . "~/Projects/maven-wrapper/"))
  apply(#f(compiled-function (arg &rest args) #<bytecode 0x18d0a9b38b36bb46>) (java . "~/Projects/maven-wrapper/"))
  project-root((java . "~/Projects/maven-wrapper/"))
  #f(compiled-function (project) "Get the root of a JAVA PROJECT." #<bytecode 0x1383aa4aefdec6fc>)((java . "~/Projects/maven-wrapper/"))
  apply(#f(compiled-function (project) "Get the root of a JAVA PROJECT." #<bytecode 0x1383aa4aefdec6fc>) (java . "~/Projects/maven-wrapper/") nil)
  #f(compiled-function (arg &rest args) #<bytecode 0x18d0a9b38b36bb46>)((java . "~/Projects/maven-wrapper/"))
  apply(#f(compiled-function (arg &rest args) #<bytecode 0x18d0a9b38b36bb46>) (java . "~/Projects/maven-wrapper/"))
  project-root((java . "~/Projects/maven-wrapper/"))
  #f(compiled-function (project) "Get the root of a JAVA PROJECT." #<bytecode 0x1383aa4aefdec6fc>)((java . "~/Projects/maven-wrapper/"))

JDT formatter options

Hi! Awesome package and much appreciated :)

Small tweaks here would make it perfect for my use cases:

  • build.gradle.kts auto detection (I believe this is quite simple looking through the code, but am not certain of it)
  • a wiki to help setting up eclipse JDT formatter options (and maybe some quick tips for auto-format hooked into eglot-format)

These are small things... I am always wondered by the Emacs evolution in recent years!

I am currently in a Termux session so can't really try to open a PR easilly here but I might try it in the future. Leaving this here for reference if anyone can do it before me (which might take a while since I am no pro in Elisp).

Thanks once again for your work! Happy incoming new year!

build.gradle.kts auto detection

Background

Gradle added Kotlin support in late 2016, starting with version 3.0.

eglot-java never included any Kotlin support for Gradle projects for 2 main reasons:

  • I never used Kotlin professionally, but I did try it few times (mostly in its early days)
  • I don't really program professionally anymore, and I completely forgot about Kotlin

As of mid-2023, it seems that Kotlin is now the default DSL for Gradle project files.

Problem

There's no support for Gradle Kotlin files : no build.gradle.kts or settings.gradle.kts existence checks.
Some people might prefer Kotlin to the Groovy syntax, maybe even more likely when working on Android projects.

Potential Approach

  • Update the conceptual notion of a project for project.el (see eglot-java--project-try)
  • Update the test for gradle projects (see eglot-java--project-gradle-p)
  • Update Gradle project name support (best effort) by considering setttings.gradle.kts if it exists (See eglot-java--project-name-gradle)
  • Update Gradle projects build refresh logic to account for a potential build.gradle.kts file (See eglot-java-project-build-refresh)

Allow upgrading the Junit standalone jar for tests

Background

When you invoke the eglot-java-run-test function, it will attempt to download the maven junit-platform-console-standalone jar artifact (if not already cached locally). You can describe the variable eglot-java-junit-platform-console-standalone-jar for more details (C-h v).

Problem

It is not current possible to systemically upgrade the install junit standalone console jar. This is similar in nature to issue #16 .

Solution

Approach

Check for the latest version and then upgrade any existing download.

  • If there was no previously recorded junit version, prompt the user for a new installation
  • Otherwise, upgrade to the latest version, if available

Challenges

It is possible that a version might denote a milestone (e.g., 1.0.0-M1 or 1.0.0-rc1). It is not guaranteed that those versions will be recorded as "releases" in the maven repository metadata.xml.

Core emacs functions will report 1.0.0-M1 as invalid, in comparison to 1.0.0. => (version< "1.0.0-M1" "1.0.0")

See sample metadata.xml
<?xml version="1.0" encoding="UTF-8"?>
<metadata>
  <groupId>org.junit</groupId>
  <artifactId>junit-gradle</artifactId>
  <versioning>
    <latest>5.0.0-ALPHA</latest>
    <release>5.0.0-ALPHA</release>
    <versions>
      <version>5.0.0-ALPHA</version>
    </versions>
    <lastUpdated>20160201140008</lastUpdated>
  </versioning>
</metadata>

Let's assume that the latest available version is 1.0.0-M2 and the installed version is 1.0.0-M1:

  • Check for the presence of a dash (-)
  • Comparse the first portion of the string (version<= "1.0.0" "1.0.0")
  • If the latest version was winning, then stop (e.g., the installed version was "1.0.1")
  • Otherwise, sort compare the rest of the string M2 with the installed version M1
    • If the installed version didn't have any suffix, the installed version wins (and vice-versa)
    • Otherwise, compare the version suffixes with emacs built-in functions (string> "M2" "M1")

Custom timeout settings?

Background

When eglot tries to launch an LSP server, a timeout error can happen if the LSP server is not ready very quickly.

Problem

From a user perspective, the timeout error could be seen as a bug??

Potential solution

  • Custom variable just for the Java LSP server?
  • Or documentation task? "if you get timeout issues, please consult the documentation of the eglot-sync-connect variable...."

The documentation task seem like a better option. The user may want all the connectivity to be async with eglot-sync-connect set to 0.

Download issues for Junit standalone jar behind VPN

Background

When you invoke the eglot-java-run-test function, it will attempt to download the maven junit-platform-console-standalone jar artifact (if not already cached locally).

  • This will look for the jar artifact in sonatype.org repositories.
  • For more information, please also inspect the value of the eglot-java-junit-platform-console-standalone-jar-url variable (C-h v).

Problem

When behind a VPN (e.g., NordVPN), sonatype.org might request some user credentials for the junit jar download (as no browser captcha will be displayed to check whether you're a bot or a real human).

Please note that I'm not promoting a specific VPN such as NordVPN.

Potential Solution

  • Create a new custom variable holding the junit-platform-console-standalone root maven url, such as https://repo1.maven.org/maven2/. If that URL creates problems, users can change it themselves with another URL that doesn't attempt to block them behind their particular network setup.
  • Mark the variable eglot-java-junit-platform-console-standalone-jar-url as obsolete (See the make-obsolete-variable function)
  • Get the latest version from the maven-metadata.xml (metadata > versioning > latest).
    • Insert the metadata.xml contents into a temporary buffer (with the url-insert-file-contents function)
    • Parse the XML string (XML_STRING) by parsing the current temporary XML buffer
    • Extract the version (caddar (xml-get-children (car (xml-get-children (car (XML_STRING)) 'versioning)) 'release))
  • Download the latest available jar artifact, after computing accordingly the jar URL location.

recent change created invalid property list

I have a failure with ensure-eglot due to these lines. This can't be serialized to JSON because it's an invalid property list (a tag with 2 values).

eglot-java/eglot-java.el

Lines 146 to 149 in ea51c47

`(:settings (:java (:home ,home))
(:import (:gradle (:enabled t)))
)

Moving a left parenthesis seems to fix it, though I'm just guessing that :import is another setting of :java.

          `(:settings (:java (:home ,home)
                       :import (:gradle (:enabled t)))
                      
                      )

Attempt to mitigate some doom-emacs issues

Background

https://discourse.doomemacs.org/t/error-when-loading-eglot-java/3923

Problem

  • Some functions don't seem to be autoloaded in other emacs variants (while apparently working just fine on "plain emacs").
  • Extracting the Eclipse JDT archive (tar.gz file) fails because of multi-byte settings??? It could be that multi-byte defaults are not necessarily the same across emacs variants????

Potential solution

For multibyte issues, not really sure about what can be done, buffer local settings would be set for a given file mode apparently.

For functions not automatically discovered, libraries can be eagerly loaded (xml and tar-mode libraries)

Eglot-java would not start when open java file

Eglot and eglot-java didn't start when I open any file with java source code from my project.

Steps to reproduce:

  1. Install eglot and eglot-java
  2. Go to folder with java project and open any java file
  3. Got message: File mode specification error: (wrong-type-argument consp nil)
  4. Eclipse Java Language Server didn't installs automatically.

Emacs 28.2
Eglot 1.10
Eglot-java 20221218.1809 from MELPA

Му configuration:

(use-package eglot)

(use-package eglot-java
  :requires eglot
  :config
  (progn
    (add-hook 'java-mode-hook 'eglot-java-mode)))

I found (via M-x toggle-debug-on-error) what problem also reproduces, when I call M-x eglot-java-mode after open the java file.

Debugger entered--Lisp error: (wrong-type-argument consp nil)
  eglot-java--init()
  eglot-java-mode(toggle)
  funcall-interactively(eglot-java-mode toggle)
  call-interactively(eglot-java-mode record nil)
  command-execute(eglot-java-mode record)
  execute-extended-command(nil "eglot-java-mode" "eglot-java-m")
  funcall-interactively(execute-extended-command nil "eglot-java-mode" "eglot-java-m")
  call-interactively(execute-extended-command nil nil)
  command-execute(execute-extended-command)

A new eglot process is started for each project in a Gradle multi-project

I use eglot-java with a Gradle multi-project. For example the sub-projects are named "lib" and "app". I visit a Java file of project "lib" and enable eglot-java-mode. This starts a jdtls process. I visit a Java file of project "app" and enable eglot-java-mode. This starts another jdtls process. So there are two jdtls processes running in parallel. When I do the same just with eglot-mode itself, only one jdtls process is running.

For projects with a lot of sub-projects a lot of memory might be allocated. Is there a way to achieve that only one process is started for the whole multi-project?

I guess the function eglot-java--project-try is involved because it finds the Gradle build file of the sub-project. This function is added to the project-find-functions by eglot-java--init.

Setting JVM arguments for the LSP server not working with lombok

Emacs version 28.2
OS version: MacOS 13.3.1
Architecture: ARM (Apple M1)

(setq eglot-java-eclipse-jdt-args
'(
"-noverify"
"-Xmx1G"
"-XX:+UseG1GC"
"-XX:+UseStringDeduplication"
"-javaagent:/.m2/repository/org/projectlombok/lombok/1.18.20/lombok-1.18.20.jar"
"-Xbootclasspath/a:
/.m2/repository/org/projectlombok/lombok/1.18.20/lombok-1.18.20.jar"
))

jsonrpc-request: jsonrpc-error: "request id=73 failed:", (jsonrpc-error-code . -32603), (jsonrpc-error-message . "Internal error."), (jsonrpc-error-data . "java.util.concurrent.CompletionException: java.lang.reflect.InaccessibleObjectException: Unable to make protected final java.lang.Class java.lang.ClassLoader.defineClass(java.lang.String,byte[],int,int) throws java.lang.ClassFormatError accessible: module java.base does not "opens java.lang" to unnamed module @377c7eaf
at java.base/java.util.concurrent.CompletableFuture.encodeThrowable(CompletableFuture.java:315)
at java.base/java.util.concurrent.CompletableFuture.completeThrowable(CompletableFuture.java:320)
at java.base/java.util.concurrent.CompletableFuture$UniApply.tryFire(CompletableFuture.java:649)
at java.base/java.util.concurrent.CompletableFuture$Completion.exec(CompletableFuture.java:483)
at java.base/java.util.concurrent.ForkJoinTask.doExec(ForkJoinTask.java:373)
at java.base/java.util.concurrent.ForkJoinPool$WorkQueue.topLevelExec(ForkJoinPool.java:1182)
at java.base/java.util.concurrent.ForkJoinPool.scan(ForkJoinPool.java:1655)
at java.base/java.util.concurrent.ForkJoinPool.runWorker(ForkJoinPool.java:1622)
at java.base/java.util.concurrent.ForkJoinWorkerThread.run(ForkJoinWorkerThread.java:165)
Caused by: java.lang.reflect.InaccessibleObjectException: Unable to make protected final java.lang.Class java.lang.ClassLoader.defineClass(java.lang.String,byte[],int,int) throws java.lang.ClassFormatError accessible: module java.base does not "opens java.lang" to unnamed module @377c7eaf
at java.base/java.lang.reflect.AccessibleObject.checkCanSetAccessible(AccessibleObject.java:354)
at java.base/java.lang.reflect.AccessibleObject.checkCanSetAccessible(AccessibleObject.java:297)
at java.base/java.lang.reflect.Method.checkCanSetAccessible(Method.java:199)
at java.base/java.lang.reflect.Method.setAccessible(Method.java:193)
at org.eclipse.osgi.internal.loader.ModuleClassLoader.overrideLoadResult(ModuleClassLoader.java:86)
at org.eclipse.osgi.internal.loader.ModuleClassLoader.loadClass(ModuleClassLoader.java)
at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:520)
at org.eclipse.jdt.internal.compiler.parser.Parser.consumeExitVariableWithInitialization(Parser.java:4205)
at org.eclipse.jdt.internal.compiler.SourceElementParser.consumeExitVariableWithInitialization(SourceElementParser.java:406)
at org.eclipse.jdt.internal.compiler.parser.Parser.consumeRule(Parser.java:7156)
at org.eclipse.jdt.internal.compiler.parser.Parser.parse(Parser.java:13179)
at org.eclipse.jdt.internal.compiler.parser.Parser.parse(Parser.java:13434)
at org.eclipse.jdt.internal.compiler.parser.Parser.parse(Parser.java:13391)
at org.eclipse.jdt.internal.compiler.SourceElementParser.parseCompilationUnit(SourceElementParser.java:1122)
at org.eclipse.jdt.internal.core.CompilationUnit.buildStructure(CompilationUnit.java:196)
at org.eclipse.jdt.internal.core.Openable.generateInfos(Openable.java:266)
at org.eclipse.jdt.internal.core.JavaElement.openWhenClosed(JavaElement.java:597)
at org.eclipse.jdt.internal.core.JavaElement.getElementInfo(JavaElement.java:328)
at org.eclipse.jdt.internal.core.JavaElement.getElementInfo(JavaElement.java:314)
at org.eclipse.jdt.internal.core.Openable.getBuffer(Openable.java:296)
at org.eclipse.jdt.ls.core.internal.JDTUtils.findElementsAtSelection(JDTUtils.java:992)
at org.eclipse.jdt.ls.core.internal.JDTUtils.findElementAtSelection(JDTUtils.java:978)
at org.eclipse.jdt.ls.core.internal.handlers.NavigateToDefinitionHandler.computeDefinitionNavigation(NavigateToDefinitionHandler.java:83)
at org.eclipse.jdt.ls.core.internal.handlers.NavigateToDefinitionHandler.definition(NavigateToDefinitionHandler.java:73)
at org.eclipse.jdt.ls.core.internal.handlers.JDTLanguageServer.lambda$7(JDTLanguageServer.java:658)
at org.eclipse.jdt.ls.core.internal.BaseJDTLanguageServer.lambda$0(BaseJDTLanguageServer.java:87)
at java.base/java.util.concurrent.CompletableFuture$UniApply.tryFire(CompletableFuture.java:646)
... 6 more
")

The above setting for lsp-java does work, so I wonder why passing the same jvm argument will cause the discrepancy.

Lombok does not always seem to work correctly

I cannot imagine why it would work in some cases, but not in others, but throughout the majority of the project things work fine, until I see the @Getter annotation.

Everything works fine when I compile the thing.

Also, my lombok verrsion (1.18.30) seems to work fine with lsp-mode and nvim-jdtls.

When things go wrong, I get a lint error at the top of the buffer which reads:
Java [0]: Lombok annotation handler class lombok.eclipse.handlers.HandleGetter failed - See error log. and sometimes, but not always, missing references down the buffer from there.

My vmargs are set as such:

(defun td-eglot-java-setup ()
  (setq eglot-java-eclipse-jdt-args (list (concat "-javaagent:"
                                               td-eglot-java-lombok-path)))
  (td-bind-keys '(("C-c e n" . eglot-java-file-new)
                  ("C-c e x" . eglot-java-run-main)
                  ("C-c e t" . eglot-java-run-test)
                  ("C-c e N" . eglot-java-project-new)
                  ("C-c e T" . eglot-java-project-build-task)
                  ("C-c e R" . eglot-java-project-build-refresh))
                eglot-java-mode-map))

(add-hook 'eglot-java-mode-hook 'td-eglot-java-setup)

When I check the jdt args at run time, they look pretty good to me:

Its value is
("-javaagent:/home/trev/.emacs.d/eglot-java/lombok/lombok.jar" "-jar" "/home/trev/.emacs.d/share/eclipse.jdt.ls/plugins/org.eclipse.equinox.launcher_1.6.700.v20231214-2017.jar" "-configuration" "/home/trev/.emacs.d/share/eclipse.jdt.ls/config_linux" "-data" "/home/trev/.emacs.d/eglot-java-eclipse-jdt-cache/ba359c4c589a8cb98349d0107123787e")
Original value was nil

Any ideas as to what's going on here?

Improve automatic JDT LS installation

Problem

Default value of eglot-java-eclipse-jdt-ls-download-url is a snapshot download. If you are unlucky to install it a time when the latest snapshot is buggy, good luck understanding what's wrong when you are not familiar with eglot.

Potential solution

Switching from release snapshots to release milestones could mitigate this issue.

Sadly, it seems that there's no official Eclipse website API endpoint to retrieve available jdtls releases. (i.e., in comparison to let's say fetching GitHub releases for a given project).

Approach

One option is to leverage the Homebrew jdtls formula REST endpoint to retrieve the latest "known" stable version.

The property paths of interest are .urls.stable.url and .versions.stable, per JSON response exceprt below.

Toggle JSON response exceprt
{
  "name": "jdtls",
  ...
  "versions": {
    "stable": "1.30.0",
    "head": null,
    "bottle": true
  },
  "urls": {
    "stable": {
      "url": "https://www.eclipse.org/downloads/download.php?file=/jdtls/milestones/1.30.0/jdt-language-server-1.30.0-202311301503.tar.gz",
      "tag": null,
      "revision": null,
      "using": null,
      "checksum": "579809f27df5f4e53566217f7273fa25cd45a22d3870c0aafd4f84cdd4c97acd"
    }
  },
  ...
}

Other considerations

We probably need to record the installed jdtls version ( in some form of metadata file??).

Caveats

  • The jdtls version recorded in the Homebrew formula might not be the latest available release milestone.
  • A relase milestone is usually more stable than a release snaphsot, but the milestone could be buggy as well...

Upgrade existing JDT LS installation

Problem

There appears to be no "official" way to upgrade the installed JDT LS. You could delete the installation directory, but it's obviously a hack. Probably also need to shut down (how exactly?) the eglot server and (manually?) start again after deleting.

Potential solution

  • Check the currently installed version against the latest known available version
  • For each opened buffer associated with eglot-java-mode, ensure that the eglot-server is not running, otherwise stop it: Maybe just disabling eglot-java-mode is good enough
  • Install the new jdtls version to a temporary folder
  • If the installation succeeds
    • Move the old jdtls installation folder to a temporary folder
    • Move the new jdtls to its new destination
    • Delete the old jdtls installation folder
  • For each opened buffer associated with java-mode, ensure that the eglot-server is running, by reassociating the buffer with eglot-java-mode

References

This depends on #15 .

RFC fixing class rename

At present when doing eglot-rename on a type, the class file is not renamed at the same time and the server sends an error about the two not matching. Doing rename-visited-file confuses the server further because the file open and close events aren't sent. This is pretty annoying for me as i like to chop and change my names pretty often if I'm working on my own project. From what I can see, JDT.LS does send a rename event if the client sends capabilities.workspaceEdit.resourceOperations: ["rename"] but Eglot by default does not.

I did have some code that tried to brute force figuring out whether we just renamed a class and to do the rename in Emacs, but it didn't feel safe for a potentially destructive action. The other option I'm thinking of is trying to send the resourceOperations capability to the server and listening for rename events inside eglot-java. (Of course the nicer option would be to have this work inside Eglot itself, but I do not have the patience for trying to get code into Emacs git.) Any comments would be welcomed

Publish eglot-java on ELPA?

Hi,

would you consider adding this package to ELPA? If so, may I suggest to get in touch with @phikal to check what you need to do?

Thank you!

Use jdtls startup script by default?

Background

By default, eglot-java doesn't use the Eclipse JDT LS startup scripts (jdtls binary).

  • This package was created before jdtls startup scripts existed (See eclipse-jdtls/eclipse.jdt.ls#1823)
  • The jdtls startup scripts require a Python installation
    • On Linux, Python is typically pre-installed on Linux, as many programs use that
    • On Windows, Python is not pre-installed
    • On Mac OS, Python is also not bundled anymore as of MacOS Monterey 12.3

Problem

By default, eglot-java dynamically modifies the eglot-server-programs variable for launching the Eclipse JDT LS server.
Some users might not realize that, even though it's documented (Package headers and GitHub project README), and that will result into both frustration and time wasted.

Scenario 1 - eglot changes how LSP servers can be mapped to programming modes

  • Evidence: #8
  • Problem: eglot won't be able to start the LSP server, with obscure error emacs-lisp messages

Scenario 2 - users have already configured eglot-server-programs to their liking for jdtls

Request

Changes

There's an existing variable that controls how eglot-java dynamically modifies the value of eglot-server-programs.

eglot-java-eglot-server-programs-manual-updates is a variable defined in ‘eglot-java.el’.

Its value is nil

Do not try to automatically update eglot-server-programs

The change will change the default value of eglot-java-eglot-server-programs-manual-updates to t. The project documentation will also need to be updated to reflect that

Expected Impacts

  • Potentially negligible for the vast majority of new users.
    • People typically installed eglot-java when they do not want an involved configuration
    • By that time, they might already have an awareness of jdtls startup scripts and mostly value eglot-java for its ability to automatically install the Eclipse JDT LS server.
  • Potentially annoying for existing users, as it may break their existing customization
    • Any custom JVM arguments would be ignored when switching to the jdtls script
    • Windows or Mac OS users don't necessarily have Python installed and they might not be aware that the jdtls script needs it...

Caveats

I don't feel that eglot java defaults are that good myself: see joaotavora/eglot#1008 (comment). Either way, it's probably better to have an explicit user opt-in (eglot-java magic), instead of people continuously running into configuration issues...

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.