Skip to content
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

CMD+ALT+Click on a header file opens the source file twice in two separate editors #711

Open
CodingMarkus opened this issue Oct 31, 2024 · 6 comments
Labels
bug Something isn't working

Comments

@CodingMarkus
Copy link

I thought this is a VSCode issue but I can only reproduce that issue when clicking C header files and have the clangd extension enabled (well, without that extension I cannot click C header files to begin with but I don't see that issue when clicking C symbols or symbols in any other language).

Steps to Reproduce:

  1. Have two code editors open side by side
  2. One shows file A (left), the other shows file B (right)
  3. Click a header file include in editor A while pressing CMD+ALT

Expected behavior:
The editor to the right now shows the clicked header file. Alternatively a 3rd editor opens that shows the header file and the middle editor still shows file B. Both could be expected, yet I would expect the first one to happen.

Actual behavior:
The editor to the right now shows the header file but another editor is also opened and this editor also shows header file. The header file is now shown twice in an existing and a new editor.

Screenshots:

Initial situation:

Image

I hold CMD+ALT and click on em_asm.h and this is what I get:

Image

Note how the editor to the right changes to em_asm.h but also note there is also a third editor now that also shows that file.

System information
Clangd version (from the log, or clangd --version): Apple clangd version 16.0.0 (clang-1600.0.26.3)
clangd extension version: v0.1.29
Operating system: macOS 14.6.1

@CodingMarkus CodingMarkus added the bug Something isn't working label Oct 31, 2024
@HighCommander4
Copy link
Contributor

HighCommander4 commented Nov 1, 2024

I can reproduce this, but I don't think it's an issue in vscode-clangd or the clangd server.

The only involvement clangd has in this process is that the clangd server responds to textDocument/documentLink requests sent by the client with source ranges in the file which should link to other files, and what files they link to.

The code for sending these requests, and for responding to any clicks on the links and opening any new editors, lives in the vscode-languageclient package (which lives in this repo: https://github.com/microsoft/vscode-languageserver-node), or vscode itself (https://github.com/microsoft/vscode). I would suggest filing an issue in one of those repos.

@HighCommander4
Copy link
Contributor

For good measure, I did double check that in a simple scenario where I open a source file with one #include and then click on the #include, clangd only gets one documentLink request, and the response only contains one link. (But nonetheless the editor opens two copies of the file.)

@CodingMarkus
Copy link
Author

But why does it only happen when clicking a header include? It does not happen when clicking a symbol. When clicking a symbol with ALT+CMD, it just opens the file containing the symbol in the editor to the right, which is exactly the expected behavior. If the issue is in VSCode itself, shouldn't it always misbehave the same way? Are you sending the same data to VSCode in both cases?

And I already did file a VSCode issue (microsoft/vscode#232725) as I also thought it probably is the IDE itself handling this case incorrectly but that was before I noticed that it only happens for headers and does work for other symbols.

@HighCommander4
Copy link
Contributor

HighCommander4 commented Nov 1, 2024

But why does it only happen when clicking a header include? It does not happen when clicking a symbol.

Your comment made me realize what is going on here.

There are two different editor features at play here:

  • Go to definition. This applies to arbitrary tokens in the code. The editor sends a textDocument/definition request on demand for a given source location (i.e. when go-to-definition is invoked by the user at that location), and the language server responds with the location of the definition of the symbol at the input location (and the editor then navigates there, including opening the target file if it's different from the original file).
  • Document links. This is meant for source ranges in a document which are references/links to another document. This is requested once for the entire document with textDocument/documentLink and the response contains all links in the document. The editor then renders these ranges as links (e.g. with an underline) and can provide a way to follow the link.

For #include directives, clangd supports both of these features: it includes them in textDocument/documentLinks, and it responds to textDocument/definition on them with the first character position of the included file.

Now, it looks like VSCode binds the same shortcut, Ctrl+Alt+Click (or Cmd+Alt+Click on Mac), to both of these editor features. This is why two copies of the target file are opened.


I'm not quite sure whether that makes this a VSCode bug or not.

I would say clangd has a good reason for supporting both documentLinks and definition for #include directives:

  • documentLinks makes the links underlined, and enables whatever navigation action the editor provides for links
    • For VSCode, this is "Ctrl+Click" for "open link in the same editor group" and "Ctrl+Alt+Click" for "open link in a different editor group", both of which are shared by definition as well. But one could imagine an editor providing a dedicated shortcut for links specifically, and we'd want to enable that for #include directives.
  • definition enables the go-to-definition command and shortcut (F12 by default in VSCode).

So, I don't think we'd want clangd to stop doing either of these.

I think it would be better if this was fixed on the VSCode side by e.g. making it so that if there is a document link at a given position, then Ctrl+Alt+Click does not also invoke definition at the same position.

@HighCommander4
Copy link
Contributor

By the way, a workaround I can think of is to disable document links (possibly only for C/C++ source files) as discussed in this comment.

@CodingMarkus
Copy link
Author

By the way, a workaround I can think of is to disable document links (possibly only for C/C++ source files) as discussed in this comment.

This works, yet requires [c] as well to work for both languages

    "[cpp][c]": {
       "editor.links": false
    }

but has the downside that when you have includes with paths

#include <a/b/c/file.h>

now a, b, c and file.h all become links of their own, yet the all lead to file.h. But I guess it's better than nothing.

Maybe I can get some feedback from the VSCode devs what they think about it. If they think clangd should not behave that way or if documentLinks must take precedence over definitions (or the other way round). Triggering two distinct actions with only one click just doesn't seem meaningful to me.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

2 participants