-
Notifications
You must be signed in to change notification settings - Fork 200
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Code actions missing (?) in javascript project #847
Comments
After digging a bit further, I fixed half of my problem. I looked at eglots code and then evaluated the following: (eglot--code-action eglot-code-action-organize-imports-ts "source.organizeImports.ts") After that, I can execute (eglot--code-action eglot-code-action-add-missing-imports-ts "source.addMissingImports.ts") Source: https://github.com/typescript-language-server/typescript-language-server#code-actions-on-save But this doesn't work. It says |
One more update. I was testing this in a javascript application. I just did the same thing in a typescript application using |
I have hard time understanding this part of the specification. The client declares what kinds of codeActions it supports in its CodeActionClientCapabilities. However, the server replies with CodeActionKinds that list the actions the server may return. What's the relationship between two lists is unclear. Also, if the client doesn't specify an The event log of the original bug report does not include a textDocument/codeAction request, so it's impossible to say how the server reacted to a 'give-me-all' request ( |
In the typescript project, in
Works as expected. Doing exactly the same thing in javascript project (
|
Okay I got it fixed: One needs a {
"compilerOptions": {
"target": "es5",
"lib": [
"dom",
"dom.iterable",
"esnext"
],
"allowJs": true,
"checkJs": true,
"skipLibCheck": true,
"esModuleInterop": true,
"allowSyntheticDefaultImports": true,
"strict": true,
"forceConsistentCasingInFileNames": true,
"noFallthroughCasesInSwitch": true,
"module": "esnext",
"moduleResolution": "node",
"resolveJsonModule": true,
"isolatedModules": true,
"noEmit": true,
"jsx": "react-jsx"
},
"include": [
"src"
]
}
|
I thought the server must reply with a subset of the client's list of codeActionKind during the initialization. But it's clearly not the case. The typescript-language-server returns these [1]: ["source.fixAll.ts" "source.removeUnused.ts" "source.addMissingImports.ts" ...] The clangd server returns these [2]: ["quickfix" "refactor" "info"] (Additionally, in the current code there is a mismatch between what Eglot initially sent and the completing read arguemnt of eglot-code-actions. "source" and "refactor" is missing from `eglot-code-actions'. Was this intentional?) Now, Eglot plays safe, and offers the union of the two lists as possible completions in `eglot-code-actions'. [1]: #847 (comment) [2]: #860
Hello, Unfortunately I need to reopen this issue. I just revisited this as I haven't touched it in a while. I am not able to execute the The same thing works with VSCode, this is what vscode sends to the server: {
"seq": 34,
"type": "request",
"command": "organizeImports",
"arguments": {
"scope": {
"type": "file",
"args": {
"file": "/home/db/.local/share/git/gaia/client/platform/web/src/ui/Component/File/Hotspot.jsx"
}
},
"skipDestructiveCodeActions": false,
"mode": "All"
}
} I'm not quite sure how to trigger this in eglot. Unfortunately, I can't post the output of my eglot events buffer, because it's empty for some reason. However in general, the connection to the lsp works (I get ts warning, errors, actions like rename etc work fine). No idea why it's empty. Also, the hack I mentioned here is not working anymore, if I do this, I get the same message saying that the action is not available like above. In addition, when executing
It seems to only happen when the cursor is not on a symbol (but maybe an empty line). Another thing I noticed is, that in order to get the correct available code actions, I need to select (mark) the symbol the cursor is on: const theme = useTheme() Say I have not imported Again, unfortunately my events buffer remains empty, so I can't post its output. My eglot related config is here and here. In essence, these are the questions I have:
I am on eglot version Thanks in advance! |
Well, mine isn't, so the likely culprit is something in your configuration. Please understand that very little can be done without the eglot events buffer or without an I got lucky this time and managed to find a way to study the problem quickly with a single file.
The previous technique you uses in 2022 should work. #847 (comment) If it doesn't, the only way to debug this is to have that recipe I ask for.
You don't. LSP dictates that LSP code actions are requested for a range. As explained in
The last sentence is relevant, we can use it to invoke exactly the action the server is supplying.
I can execute some actions just fine. Notice how
This works today. I may of course also ask the server to Here, the TS servers still returns actions, but says they're of kind At first I thought this was a server bug, but it isn't. The names are hierarchical. I've pushed a fix to master so eventually Eglot 1.17 will have it and have some understanding of this hierarchy. If you want, you can get Emacs master right now or get bleeding edge Eglot from GNU-devel ELPA in a day or so. |
Github-reference: joaotavora/eglot#847 Servers like typescript-language-server, when asked for {"only" : "source.organizeImports"}, return actions with the "source.organizeImports.ts" kind. Eglot rejected these actions, but according to the spec: Kinds are a hierarchical list of identifiers separated by `.` [...] The set of kinds is open. So I guess we can use string-prefix-p * lisp/progmodes/eglot.el (eglot-code-actions): Use string-prefix-p.
You don't sound bitter. I can completely understand that it's frustrating reading comments not providing the information needed. Sorry. I was able to get the events buffer back, I had misconfigured something. I also updated to typescript-language-server 4.2.0 and typescript 5.3.3. However, to minimize interference, I start emacs with:
Emacs start, I open a JSX file in my work project, I go to an empty line,
I also tested this. Except I used my project file instead of the snippet you posted. I get
Full log: https://pastebin.com/EHY9GUWV Thanks! |
And what was the outcome?
OK, but first try it with the I can't try your recipe because I don't have your |
I actually have a hard time getting this to work. I have
On NixOS, It doesn't work to have
So I start emacs with this:
Then
I do Log: https://pastebin.com/f1mxXZ4T
Apart from what I already explained above, I like to specifically set paths for (add-to-list
'eglot-server-programs
'((js-ts-mode
typescript-ts-mode
tsx-ts-mode) . ("${customNodePackages.typescript-language-server}/bin/typescript-language-server" "--stdio"
:initializationOptions
(:tsserver (:path "${customNodePackages.typescript}/lib/node_modules/typescript/lib")))))) That nix configuration will eventually be used to create my emacs config, and the package ( Anyway, I just explained this to give you some background information. Doing it like this is common practice is the nix-world. But regardless, it should of course work even if I want to directly specify those paths. And I don't think nix is a problem here. As I mentioned before, eglot generally works (flymake errors, code actions like |
Whatever Nix does is not a problem unless you're trying to communicate a bug report to someone who doesn't use it. I you should just omit irrelevant s stuff like that if it is indeed irrelevant. I'll double check my recipe |
There is no bug with NixOS and I don't intend to report a bug. You asked
and I was trying to provide some background information for clarity. Regardless, in an effort to
I did the following:
Result is same as before. Eglot connects fine and seems to work (I get flymake errors), but I can't execute Log: https://pastebin.com/UdXd8FrK EDIT: |
Aha! OK, so sanity finally achieved. This is consistent to what I found in the log excerpt, too. When you ask for
The bleeding edge Eglot should fix this, until then, you should use C-u M-x..., or use your previous hack. So what you should probalby do now, is to check in your more elaborated project and see if you can find a similar mismatch between the requested kind and the actual kind returned. |
I just opened the same js project/file that I worked on before and that was producing the errors. Everything seems to work with this setup now. Also these code actions worked fine, using I now try to figure out why it breaks when I manually specify the paths to Thanks for your help so far. |
Findings so far: I'm still running into this error, even when using
It happens if I move the cursor to an empty line or a line with a comment. Log: https://pastebin.com/kwVWdTuf @joaotavora Can you tell me an email to send the JSX file to? I can't share that publicly. |
Ah, good. So you confirm that bare
This is a pure server error. I don't think it has anything to do with Eglot. Unless Eglot somehow provided the server with bad data before, which I doubt. I suggest you report this error to the server devs!
My email is in the source. if I can help you I will, But I only have an Archlinux and Node installation, and installing more toolchains wasn't in my plans :-) |
It has nothing to do with nix paths. In my latest test I installed
I created an issue here. Still seems unlikely to me that this is an internal |
@joaotavora I talked to the |
Let's get one thing straight. Eglot does not have Javascript code, it's written in Elisp. So if a server is spewing out a Javascript
Wherever this comes from, whatever this is, this tells me there's something to fix on the server side.
Wrong request? OK. Nonsensical requests do happen. It's impossible to tell from that message, but I will have a look. We've seen how Eglot does this request perfectly for other kinds of projects with this server and, what's more, for literally tens of other servers. |
I'm aware of that, there is no need to point that out. I'm just trying to fix this bug.
Yes and no. An exception has been thrown because something unexpected happened. This "unexcepted" thing could be something internal, could be something coming from eglot. Should the server react differently and not just error out an throw an exception? Sure it should, they should probably fix that. But that doesn't mean that it's impossible the client caused this.
You come across quite hostile and I don't really know why. I didn't say "It's eglot's fault". The maintainer of the LSP server did. Whether that is true or not, I don't know. I'm just forwarding to you what they told me. Nothing more. |
I tried your I could also confirm the incorrect request on behalf of Emacs. But was it Eglot who was reponsible? I can only judge by what I can experiment with and in a much simpler setup like the one I gave you earlier with
As you can see only the diagnostic that is overlapping the range for which code actions are requested is included in the request. I suggest you try this on your end with the
I wrote "Wrong request? OK. Nonsensical requests do happen. It's impossible to tell from that message, but I will have a look." This is what I'm doing, at 11 PM in the evening. If that is hostile to you, I don't know what to say. |
I've put on my JS kid hat and done this recipe exactly npx create-react-app my-app --template typescript
cd my-app
path/to/emacs -Q src/App.tsx -f tsx-ts-mode -f eglot
;;; delete use line that uses the "logo" import, whatever that does
;;; Go back to start of buffer
M-x eglot-code-action-organize-imports Everything works as expected (I suppose, since organizing imports just changed the order of two imports on lines 2 and 3). Then check the events log:
Everything looks OK. I.e. no extra diagnostcs reported. |
Invoking code actions without a marked region or over a symbol will trip certain servers up since BEG and END in eglot-code-actions will be nil, causing 'eglot--pos-to-lsp-position' to assume point (which is OK) but the 'flymake-diagnostics' call to return all diagnostics. This causes an absolutely undecipherable JavaScript backtrace to be sent back to Eglot from typescript-language-server. Github-reference: joaotavora/eglot#847 * lisp/progmodes/eglot.el (eglot--code-action-bounds): Avoid returning (list nil nil)
HOWEVER... If we do a little innocent tweak to that recipe: npx create-react-app my-app --template typescript
cd my-app
path/to/emacs -Q src/App.tsx -f tsx-ts-mode -f eglot
;;; delete use line that uses the "logo" import, whatever that does
;;; GO TO AN EMPTY LINE (like the fourth one)
M-x eglot-code-action-organize-imports Then everything still works but now the events log shows this
And if you bother reading through that first line, you'll see that Eglot is reporting too many diagnostics. Here, it didn't trip up the server to that undecipherable JS crash, but I suppose it may. This is very easy to fix so I've pushed a fix. As before, the bleeding edge Eglot should fix this, until then, you should make sure to invoke Now to address some earlier words. I never said this couldn't be a problem in Eglot. I wrote I doubt it.
And I had good reasons to doubt it, given all the examples I had seen before and the undecipherable nature of a JS backtrace.
Never said anything to the contrary either. Hardly anything is impossible in this world. Legend goes the term bug was coined after an actual insect. Here, the combination of:
...led to a very hard investigation. But hopefully to a fix. |
Hello, thank you for taking the time and fixing this issue. I will get latest Emacs and test your changes.
Regarding our conversation as a whole, I apologize for the turn it took. Communication via chat can sometimes be misleading. I understand this was a frustrating issue to debug on your end, especially since you normally don't work in JS. I was expressing the impression I got from our conversation, I never meant to allege that you were actually being hostile or that you said it couldn't be a fault on eglot's side. Given how hard it was for you to finally come up with a recipe that is reproducible, I now know that I should have taken more time to investigate this myself and come up with that recipe for you since I have a background in JS. If we ever end up in the same situation I will try to do so. One more thing, and maybe a new issue is the right place for this, I don't know. Something the maintainer said caught my eye:
I noticed that eglot is using I fixed this on my end by defining a derived mode (add-to-list
'eglot-server-programs
'(((jsx-ts-mode :language-id "javascriptreact") ;; needs to come before js-ts-mode
(js-ts-mode :language-id "javascript")
(tsx-ts-mode :language-id "typescriptreact") ;; needs to come before typescrip-ts-mode
(typescript-ts-mode :language-id "typescript")) . ("${pkgs.nodePackages.typescript-language-server}/bin/typescript-language-server" "--stdio"
:initializationOptions
(:tsserver (:path "${pkgs.nodePackages.typescript}/lib/node_modules/typescript/lib"))))) The only caveat is that it needs to come before Long story short, is this something we should fix in eglot? |
Invoking code actions without a marked region or over a symbol will trip certain servers up since BEG and END in eglot-code-actions will be nil, causing 'eglot--pos-to-lsp-position' to assume point (which is OK) but the 'flymake-diagnostics' call to return all diagnostics. This causes an absolutely undecipherable JavaScript backtrace to be sent back to Eglot from typescript-language-server. Github-reference: joaotavora/eglot#847 * lisp/progmodes/eglot.el (eglot--code-action-bounds): Avoid returning (list nil nil)
Hello,
If this issue has been reported already I'm sorry, but I wasn't able to find any information on the issue tracker or Google in general.
I'd like to use eglot with react using the typescript-language-server. My setup is working, meaning I get diagnostics and can use code actions and so on.
For testing purposes, I created a new react app using create-react-app and ran npm install. Then I opened
src/App.js
(and modified it a bit):There are two things I don't understand how to use:
AddMissingImports: According to their doc, the typescript-language-server supports adding missing imports (this also works using VSCode for example). However I don't know how to trigger it. In the example above,
useState
needs to be imported. But the action is not available when doingeglot-code-actions
. I tried placing the cursor on theu
ofuseState
, select the word and select the line. It always reportseglot--error: [eglot] No code actions here
. Is it simply not implemented yet or am I missing something?OrganizeImports: In the example above, the
useContext
import should be cleaned up. When doingeglot-code-action-organize-imports
it reportseglot--error: [eglot] No "source.organizeImports" code actions here
. I tried selecting the whole buffer too. the only way I got this working is by placing the cursor onu
ofuseContext
and when doingeglot-code-actions
it prompts withRemove unsused declaration for 'useContext'?
. This works. However ideally I'd do this for all input at once.Thanks in advance. Again if I missed something obvious then sorry. Really trying eglot for the first time, coming from lsp-mode.
Cheers,
Demis.
LSP transcript - M-x eglot-events-buffer (mandatory unless Emacs inoperable)
Minimal configuration (mandatory)
The text was updated successfully, but these errors were encountered: