Open anthroid opened 4 years ago
I have taken a look at the sources. This is a problem somewhat specific to the C++ extension and to the way in which it provides document highlights. Document highlights can have an optional kind. This is useful for highlighting read access to a variable/argument/member vs. write access. Languages like TypeScript/JavaScript distinguish and return highlights with the kind set to Read or Write. Most languages do this.
DocumentHighlightKind.Read
, then the used color is editor.wordHighlightBackground
DocumentHighlightKind.Write
, then the used color is editor.wordHighlightStrongBackground
DocumentHighlightKind.Text
, then the used color is editor.selectionHighlightBackground
I think in this case, the kind is missing from the highlights and that ends up using the color editor.selectionHighlightBackground
, which, I tend to agree, is a rather dubious choice.
I did some blame on the sources, and it looks like Text highlights have always used the selectinoHighlight
color, since the first VS Code public release https://github.com/microsoft/vscode/blame/79ee367cd6b7b1bf36d84faf9f80c90126ac2ea1/src/vs/editor/contrib/wordHighlighter/common/wordHighlighter.ts#L249
I think we can do two things:
DocumentHighlightKind.Text
which defaults to editor.selectionHighlightBackground
if not defined.Read
and Write
.@sean-mcmanus @Colengms Would it be possible for the C++ extension to use the kinds Read
and Write
in the document highlights it returns?
@alexdima Our reference highlighting implementation is inherited from VS, which just obtains a range for the references and not a kind. From looking at the code, it doesn't appear trivial to add (we would need to file a feature request on VS at https://developercommunity.visualstudio.com/content/idea/post.html?space=62). We would prefer to be able to return a new DocumentHighlightKind in the LSP (https://microsoft.github.io/language-server-protocol/specification):
/**
* Reference to a symbol (read or write undetermined).
*/
export const Symbol = 4;
Or whatever wording you think is appropriate. And it could default to use the Read color.
But just changing the default color would be fine with us too (or some way for our extension to opt-in to the new color).
@sean-mcmanus Thank you, I was thinking it might be something like that -- difficult to determine read vs write usages. In this case, I think we should add on our side a custom color for DocumentHighlightKind.Text
. Please let me know if you have any naming suggestions.
Hi, I just wanted to add an update here, and pose a couple questions. Since opening this issue, I have continually found it nearly impossible to work with this behavior (not being able to see the actual selection when the extension's occurrence highlight clobbers it, and additionally not being able to differentiate between selection occurrences and symbol occurrences because they are both highlighted), so I ended up completely disabling the C/C++ extension.
I primarily work with C, and I still wanted to use completions and other features the extension provides, so I installed the C/C++ Clang Command Adapter extension (mitaki28.vscode-clang
), which does not appear to implement any range-highlighting functionality, so this just works predictably with the native occurrence and selection highlight behavior (as with no language extension), and the behavior is correct. Symbolic occurrences are highlighted with a single click, and selections are highlighted without an overlapping symbol highlight.
With a partial symbol selected, only the selection occurrences are highlighted (using editor.selectionHighlightBackground
, and the primary selection uses editor.selectionBackground
. There is no overlapping symbol occurrence highlighting:
Behavior is still correct:
Behavior is still correct (partial symbol highlighted, no conflicting highlight):
Single-click full-symbol highlighting also still works as expected (cursor is on an instance of foo
, no selection):
So I wanted to ask:
Is there any additional functionality gained by the C/C++ extension providing these highlight ranges, or is this just creating a conflict with the native occurrence highlighting? Could it simply be removed from the extension?
If there is additional functionality provided by highlighting these ranges that extends beyond the scope of the "native" highlighting behavior, shouldn't the extension use its own setting instead of using the global editor.occurrencesHighlight
and editor.selectionHighlight
? By using these global settings, this means the user must disable all occurrence highlighting behavior completely, rather than being able to keep the native behavior enabled, and simply disabling the extension's highlighting behavior.
@anthroid Our C++ reference highlighting is semantic instead of just textual -- it only highlights the actual confirmed references to the selected item and not references to other programmatic entities. See the screenshot in which the hidden "iii" and static class member are not highlighted: and without our extension:
In regards to issue 2, we implement https://microsoft.github.io/language-server-protocol/specification#textDocument_documentHighlight We could add a setting to disable our reference highlighting; however, I think you're the only user who has asked for it. I filed an issue at https://github.com/microsoft/vscode-cpptools/issues/6056 in case other users want to upvote that or make a PR for the TypeScript changes.
@sean-mcmanus Thanks for the explanation and for looking into it. In the meantime, I'll look into making the TS changes to make the setting independent and see what I can come up with.
I'm seeing this problem too. It is intensely frustrating to work in C with this C/C++ extension enabled.
I can confirm the same issue with essentially all languages using semantic highlighting.
The way I see it the problem is the fact that selection highlight is rendered below the symbol highlight. Just do it the other way around and everything will be fine.
In the example below you can see the behaviour of VS Code on the left and JetBrains Rider on the right. In both cases "Ad" is selected in the first line, but in VS Code the selection is not visible because because it comes below the symbol highlighting.
Hi @alexdima, do you know if implementation on this could be expected from MS?
I imagine there is a threshold of some N +1's for issues to receive such attention. However I sadly would not expect this to reach N. Mainly because I would guess that the set of people that program in C has very little overlap with the set that know a lot about TS (I being an example of being in the former set but very much not the latter). Probably similarly small overlap with the the set that will report such an issue rather than just moving on to another plugin or editor.
(Please tell me I'm wrong on any point 😄 )
I have simply stopped using this extension because of this issue.
The extension authors say it is a VSCode problem, VSCode authors say it is an extension problem.
Either way it results in unusable editing. VSCode is a file editor and one can run C/C++ builds from the CLI easily enough; so really the extension brings no real added value for me.
I kinda solved the issue.
The thing is that selection highlights are rendered in a separate DOM element .view-overlays
above the text elements. And each highlight is basically a div with it's own z-index
.
To switch occurrence highlight and selection highlight layers we need to set one above the other. This can be done with Custom CSS and JS extension.
/* selection background */
.monaco-editor .lines-content .cslr {
z-index: 1; /* default: unset */
}
/* occurrence / word highlight background */
.monaco-editor .lines-content .cdr {
z-index: 0; /* default: 4 */
}
You might wanna play with z-indexes of each layer in case they interfere with another selection layers.
Examples:
When selecting text or placing the cursor on a symbol with the C/C++ extension disabled, the other occurrences of the symbol are highlighted, or if there is a selection, the occurrences of the selection are highlighted. The selection is highlighted with the regular selection highlight color (
editor.selectionBackground
), and the occurrences are highlighted using the occurrences highlight color (editor.selectionHighlightBackground
).With the C/C++ extension enabled, if the global setting
Editor: Occurrences Highlight
is enabled, VS Code will always do both, with the symbolic occurrence highlighting rendered after the selection highlight, and all occurrences of both the selected text, and the symbol are highlighted in the same style, with no way to differentiate between them. This causes the selected text, which is more specific, and a direct result of a user action, and therefore arguably higher precedence, to be completely obscured by the symbol occurrence provided by the extension, which is arguably lower precedence.Here, in an unsaved buffer, with the language set to
C
, the behavior is predictable and correct. When placing the cursor on an occurrence of a symbol with no selection, the other occurrences of the symbol are highlighted:Here, in the same unsaved buffer, part of the symbol
foo
is selected. The behavior is still predictable and correct. The other occurrences of the selection are highlighted in the highlight color (editor.selectionHighlightBackground
), and the selection itself is highlighted in the selection color (editor.selectionBackground
):Likewise, if the entire symbol
foo
is selected, the behavior is still as expected, with the selection itself highlighted with the selection color, and the other occurrences of the selection highlighted in the highlight color:If the file is saved, and the C/C++ extension becomes enabled for the file, the behavior becomes problematic. Here, as in the first example, the cursor is placed within a symbol, but no selection is made. The behavior is as expected, with the symbol and all other occurrences highlighted in the highlight color:
Here, when part of the symbol is selected in the saved file, the symbol occurrences overlap the selection occurrences. The first two characters of the symbol
foo
are selected, but due to the overlapping, both the selection is obscured, and additionally, there are now two different occurrences being highlighted throughout the file at the same time, in the same color and style (both the selection,fo
, and the symbol,foo
), making them impossible to differentiate:Here, when the entire symbol is selected, the selection color is lost, so it is impossible to identify which text is selected:
If both colors are made to be transparent, or a highlight border is added, it becomes obvious that both highlight actions are taking place, first the selection occurrences, then the symbolic occurrences (there is also a noticeable delay for the second highlight, so the selection highlighting can be seen briefly before being obscured). Setting these colors to be transparent would seem to resolve the problem, but the occurrence highlighting feature becomes almost useless when the highlight transparency is adjusted to the point where the original selection is visible through it. I also firmly believe that transparency is not a solution to this issue, because most color combinations either result in the underlying selection not being visible enough to distinguish through the occurrence highlight, or the occurrence highlighting not being visible against the background. The other core problem is that both the selection and the symbol are highlighted using the same
editor.selectionHighlightBackground
color, so even if there was no visible problem overlapping at the location of the selection itself, all of the instances of both the selection and the symbol occurrences are highlighted the same, which is confusing.This can be seen here, where
editor.selectionBackground
is set to a bright, opaque color#ff0000
, andeditor.selectionHighlightBackground
is set to a bright, but also transparent color#00ff0050
, in order to keep the main highlight color visible underneath: This makes the selection highlighting visible, but unfortunately also causes whitespace decorations to be obscured, which is another problem with relying on transparency for symbol visibility. This is one of the best case scenarios (a bright, opaque selection color with a bright, transparent highlight color), but still suffers from all highlighted occurrences being styled the same (bothfoo
andfo
are highlighted green). Most normal combinations of transparent highlight colors are hardly visible, especially if using a saneeditor.selectionBackground
.Setting both colors to transparent values allows whitespace decorations to be shown, but results in hardly usable or visible highlighting in either case. Here, both are set to transparent values, and the selection itself can hardly be seen, and still, all occurrences of both the selection and the symbol are the same color:
As far as I can tell, there is no way to disable the 'overlapping' occurrence highlighting feature without losing other important functionality, like single-clicking on a symbol and the other instances being automatically highlighted, or without completely disabling the C/C++ extension and losing Intellisense features.
It appears the most straightforward solution would be to do one, or ideally both of the following:
It would also make sense to render whitespace and other related decorations after the highlighting as well, so they would be visible regardless of the selection and/or occurrence highlighting, and regardless of the transparency of the selected colors.
Steps to Reproduce:
Prepare the environment:
Editor: Occurrences Highlight
editor.selectionBackground
andeditor.selectionHighlightBackground
insettings.json
->workbench.colorCustomizations
to two different, opaque colors. For example,#ff0000
and#0000ff
.Test the behavior:
.c
file in the folder..c
file, add the code in the screenshots above, or any other validC
code with several occurrences of a given symbol, ideally one that shares likeness with another symbol or keyword in order to demonstrate the problem (testvar1
andtemp2
for example, sharing the prefixte
)..c.
file.C
, and paste the copied text into the buffer. Do not save the buffer.Expected behavior Highlighted occurrences of selected text take precedence over symbolic highlighting occurrences, only occurrences of the selected text are highlighted if a selection is present, or both are visible and differentiated.
Does this issue occur when all extensions are disabled?: No. However, I initially filed this issue in the C/C++ extension repository and was instructed to file it here based on extensions not having any control over the highlight rendering, only the ranges to be highlighted as per https://microsoft.github.io/language-server-protocol/specification#textDocument_documentHighlight.