lsp-java
lsp-java copied to clipboard
xref-find-references fails with "Wrong type argument: hash-table-p, nil"
Describe the bug
When running xref-find-references
, I get a Wrong type argument: hash-table-p, nil
error. The lsp function lsp-find-references
seems to work properly, so it is something with the xref integration. For comparison, xref-find-references
works properly with lsp-mode in rust-mode.
To Reproduce
Put cursor over method definition, press <M-?> (default key binding for xref-find-references
)
Expected behavior A list of users of method pops up.
Can you include client server communication and error callstack after doing toggle-debug-on-error. Also, do you get the same results when using lsp-find-references?
lsp-find-references
works normally, as I mentioned.
Stack:
Debugger entered--Lisp error: (wrong-type-argument hash-table-p nil)
gethash("uri" nil)
lsp--location-to-td-position(nil)
lsp--symbol-info-to-identifier(#<hash-table equal 6/65 0x4da831e5>)
mapcar(lsp--symbol-info-to-identifier (#<hash-table equal 6/65 0x4da831e5> #<hash-table equal 7/65 0x418fcd5d>))
#f(compiled-function (function sequence) #<bytecode 0x40aff1bf>)(lsp--symbol-info-to-identifier (#<hash-table equal 6/65 0x4da831e5> #<hash-table equal 7/65 0x418fcd5d>))
apply(#f(compiled-function (function sequence) #<bytecode 0x40aff1bf>) lsp--symbol-info-to-identifier (#<hash-table equal 6/65 0x4da831e5> #<hash-table equal 7/65 0x418fcd5d>) nil)
seq-map(lsp--symbol-info-to-identifier (#<hash-table equal 6/65 0x4da831e5> #<hash-table equal 7/65 0x418fcd5d>))
#f(compiled-function (backend) #<bytecode 0x4366ade5>)(xref-lsp)
apply(#f(compiled-function (backend) #<bytecode 0x4366ade5>) xref-lsp nil)
xref-backend-identifier-completion-table(xref-lsp)
xref--read-identifier("Find references of: ")
byte-code("\300\301!C\207" [xref--read-identifier "Find references of: "] 2)
call-interactively(xref-find-references nil nil)
command-execute(xref-find-references)
Server communication:
{
"jsonrpc": "2.0",
"method": "textDocument/documentSymbol",
"params": {
"textDocument": {
"uri": "file:///Users/muir/scratch/java/Foo.java"
}
},
"id": 26
}
<<<< jdtls:7388
{
"jsonrpc": "2.0",
"method": "window/logMessage",
"params": {
"type": 3,
"message": "Apr 10, 2019 10:27:19 AM >> document/documentSymbol"
}
}
Apr 10, 2019 10:27:19 AM >> document/documentSymbol
<<<< jdtls:7388
{
"jsonrpc": "2.0",
"id": 26,
"result": [
{
"name": "foo",
"kind": 4,
"range": {
"start": {
"line": 6,
"character": 0
},
"end": {
"line": 6,
"character": 12
}
},
"selectionRange": {
"start": {
"line": 6,
"character": 0
},
"end": {
"line": 6,
"character": 12
}
},
"detail": "",
"deprecated": false
},
{
"name": "Foo",
"kind": 5,
"range": {
"start": {
"line": 8,
"character": 0
},
"end": {
"line": 13,
"character": 1
}
},
"selectionRange": {
"start": {
"line": 8,
"character": 13
},
"end": {
"line": 8,
"character": 16
}
},
"detail": "",
"deprecated": false,
"children": [
{
"name": "foo()",
"kind": 6,
"range": {
"start": {
"line": 9,
"character": 2
},
"end": {
"line": 9,
"character": 24
}
},
"selectionRange": {
"start": {
"line": 9,
"character": 15
},
"end": {
"line": 9,
"character": 18
}
},
"detail": " : void",
"deprecated": false,
"children": []
},
{
"name": "bar()",
"kind": 6,
"range": {
"start": {
"line": 10,
"character": 2
},
"end": {
"line": 12,
"character": 3
}
},
"selectionRange": {
"start": {
"line": 10,
"character": 15
},
"end": {
"line": 10,
"character": 18
}
},
"detail": " : void",
"deprecated": false,
"children": []
}
]
}
]
}
lsp-find-references works normally, as I mentioned.
Ops, I misread your original comment.
This was my test Foo.java file for your reference:
package foo;
public class Foo {
private void foo() { }
private void bar() {
foo();
}
}
@muirrn can you include the call textDocument/references
response which corresponds. I just want to make sure that I am fixing the correct thing.
There was no "document/references" call when I did xref-find-references. It only called "document/documentSymbol" (or it crashed before getting to the "document/references" call). Below is the "document/references" call when I run lsp-find-references
:
{
"jsonrpc": "2.0",
"method": "textDocument/references",
"params": {
"textDocument": {
"uri": "file:///Users/muir/scratch/java/Foo.java"
},
"position": {
"line": 9,
"character": 17
},
"context": {
"includeDeclaration": false
}
},
"id": 382
}
<<<< jdtls:7388
{
"jsonrpc": "2.0",
"method": "window/logMessage",
"params": {
"type": 3,
"message": "Apr 10, 2019 11:16:19 AM >> document/references"
}
}
Apr 10, 2019 11:16:19 AM >> document/references
<<<< jdtls:7388
{
"jsonrpc": "2.0",
"id": 382,
"result": [
{
"uri": "file:///Users/muir/scratch/java/Foo.java",
"range": {
"start": {
"line": 13,
"character": 4
},
"end": {
"line": 13,
"character": 9
}
}
}
]
}
I am able to reproduce this problem by doing C-u M-x xref-find-references which I think was impossible to support for some reason (mismatch of xref requirements/lsp spec) and that's why we introduced lsp-find-references .
Ah, I see now. The problem is xref-find-references
always prompts for the identifier, and the lsp supplied identifier list has no context, so all variables in your file named "foo" just show up as separate "foo" entries and there is no way to select the particular "foo" you want.
I was able to fix it by adding xref-find-references
to the list of xref commands that will use point instead of prompting for identifier. With this change, xref-find-references
works properly for me in lsp-mode.
(setq xref-prompt-for-identifier '(not xref-find-definitions
xref-find-definitions-other-window
xref-find-definitions-other-frame
xref-find-references))
Perhaps we should include this setting in some lsp-mode documentation? Or maybe even do this automatically if the lsp-mode xref integration is enabled? xref-find-references is pretty useless w/ lsp-mode as is.
For reference: https://github.com/emacs-lsp/lsp-mode/issues/194 https://debbugs.gnu.org/cgi/bugreport.cgi?bug=29619 https://github.com/joaotavora/eglot/issues/147
It is still worth noting that without my above workaround lsp-java behaves differently from other lsp-mode languages (e.g. rust). In rust, xref-find-references
prompts for the identifier and works if you pick the correct identifier, but lsp-java immediately errors out.
Yeah, on my machine xref-prompt-for-identifier
is preconfigured(I am using spacemacs).
I think this is related to the fact that JDT LS does (not) support hierarchical document symbols which is breaking lsp--symbol-info-to-identifier
. I am still struggling to figure out how it is supposed to work since I am not the author of that code. An alternative solution is to remap xref-find-references to lsp-find-references in lsp-mode map.
Same here. I am setting xref-prompt-for-identifier
to t.
Question, even if lsp cannot fetch all the available references for the completion, can it just provide simple prompt with no completion? This is how lookup works in CIDER (which doesn't rely on xref for M-.
). Better than nothing.
@vspinu the problem is that the lsp api works by file+position and cannot accept symbol. I am considering rebinding xref-find-definition to lsp-find-definition in lsp-mode-map.
Oh, boy. That's a such a handicap. Then I guess you don't have a choice then.
Wait a sec, which map do you mean? lsp-mode-map
is empty. I have just spent an entire evening populating my own java-mode-map
with lsp commands trying to figure out what is available. Would be nice to have a recommended map somewhere.
You still need java-mode-map since a lot of the commands are java specific and it does not make sense to put them in lsp-mode-map unless you do not plan to use lsp-mode for other languages.
Well, of course. My suggestion was to provide an example of a java-mode-map configuration with all the functionality currently available, even better a separate configuration or a function which would install those bindings in some meaningful way. Currently hunting all the available commands and trying to figure out what they do from the sparse docstring is a painful exercise.
Well, of course. My suggestion was to provide an example of a java-mode-map configuration with all the functionality currently available, even better a separate configuration or a function which would install those bindings in some meaningful way. Currently hunting all the available commands and trying to figure out what they do from the sparse docstring is a painful exercise.
@vspinu we are planning to create packaging project which will be host this functionality (lsp-ide project) but we still cannot figure out the structure of that package.
Hi @yyoncho, I have just tried out the newest version of LSP mode and it got a similar error. I have tried it on two of my pc and i still got the same error.
Here is the log i got: logs Here is my configuration: configuration
Can you please help check this out?
Note:
- It is a simple Spring boot project only. It is gradle and spring version 2.3.0. My java version is openjdk version "1.8.0_252".
@YumiSuki you are using boot integration as well, right?
@YumiSuki you are using boot integration as well, right?
In the above configuration i uploaded on pastebin, I have something like below at the bottom of the file:
(require 'lsp-java-boot)
;; to enable the lenses
(add-hook 'lsp-mode-hook #'lsp-lens-mode)
(add-hook 'java-mode-hook #'lsp-java-boot-lens-mode)
I'm using an internal language server for another language we created and am seeing the same issue. Using M-x lsp-find-references works, using M-x xref-find-references results in "lsp--position-to-point: Wrong type argument: hash-table-p, nil." when using lsp from Nov-25-2020, the 2645 commit https://github.com/emacs-lsp/lsp-mode/tree/d045920385bc337faf635ed87cb0dd164b798767
At some point, I believe this worked for us (the language server does work with VSCode). I thought it worked with a version of lsp-mode from June, but I just went back and checked and it's also broken with that.
Attached is the backtrace from toggle-debug-on-error. Any thoughts on where I could help find the issue?
One more item I noticed is the ':display-action' of lsp-find-references doesn't work, i.e.
(lsp-find-references nil :display-action 'frame)
won't pop up in another frame.