Introduce a DiscardSyntaxClassifier - #40396
Conversation
|
hi @lameox thanks for the contribution! |
| } | ||
|
|
||
|
|
||
| return SpecializedCollections.EmptyEnumerable<TextSpan>(); |
There was a problem hiding this comment.
should be impossible to hit this. we should throw here.
There was a problem hiding this comment.
can use a switch expression here as well.
There was a problem hiding this comment.
Since this is argument syntax (as opposed to parameter syntax), wouldn't this be hit for most arguments?
There was a problem hiding this comment.
Yeah i think so. This is why I originally used AbstractKeywordHighlighter instead of AbstractKeywordHighlighter<ArgumentSyntax> and overwrote IsHighlightableNode so GetHighlightsForNode only got called for the required types of nodes. However it was suggested I should use AbstractKeywordHighlighter<ArgumentSyntax> which unfortunately seals IsHighlightableNode. Therefore this code always executes and I need to return the empty enumerable.
There was a problem hiding this comment.
I'm not seeing how this woudl be subtantively different. Both cases need to check all nodes to see if they should run against them.
| namespace Microsoft.CodeAnalysis.Editor.CSharp.Highlighting.KeywordHighlighters | ||
| { | ||
| [ExportHighlighter(LanguageNames.CSharp)] | ||
| internal class DiscardParameterHighlighter : AbstractKeywordHighlighter |
There was a problem hiding this comment.
ther's a different baseclass you can subclass right? where you can specify through a type argument that you are constrained to ArgumentSyntax right?
There was a problem hiding this comment.
yes, it's AbstractKeywordHighlighter<ArgumentSyntax>.
CyrusNajmabadi
left a comment
There was a problem hiding this comment.
Can be simplified
| { | ||
| var syntax = (IdentifierNameSyntax)node.Expression; | ||
|
|
||
| if (syntax.Identifier.Text == "_") |
There was a problem hiding this comment.
Switch to typechecks
|
@jinujoseph can we get a buddy for this community pr? Thanks! |
| if (node.Expression is IdentifierNameSyntax nameSyntax | ||
| && nameSyntax.Identifier.Text == "_") |
There was a problem hiding this comment.
💡 Can use pattern matching here:
if (node.Expression is IdentifierNameSyntax { Identifier: { Text: "_" } } nameSyntax)
There was a problem hiding this comment.
I still need to get used to pattern matching tbh. Should all new code aim to make use of pattern matching or is it up to preference?
There was a problem hiding this comment.
It's up to preference. in some places it works nicely (like here), in others, it can feel more forced/unpleasant.
| } | ||
|
|
||
|
|
||
| return SpecializedCollections.EmptyEnumerable<TextSpan>(); |
There was a problem hiding this comment.
Since this is argument syntax (as opposed to parameter syntax), wouldn't this be hit for most arguments?
| { | ||
| void Method() | ||
| { | ||
| int i = int.TryParse("""", out var {|Cursor:[|_|]|}); |
There was a problem hiding this comment.
💡 Should add a test showing that this does not highlight the argument if you write it as @_. This token has the same ValueText as _, but different Text, and in this case the difference is meaningful.
There was a problem hiding this comment.
Added tests covering that case.
Added a test to ensure @_ is not highlighted incorrectly.
…d of DiscardParameterHighlighter
|
Hi @lameox, Thanks for taking time to work on this. I am not sure that a highlighter is the proper way to go about this. The Keyword highlighters are intended for providing extra information about Keywords under the cursor. For instance when the cursor is on an If Keyword the Else and Else If keywords will be highlighted to provided extra context about the If keyword. The original issue was with the classification of the discard keyword in code like -Joey |
|
Hey there, thank you for your feedback. I am really new to the codebase and therefore not yet familiar with where to do certain changes. Since it is 1 am where i live i will try to look into moving this fix to the correct place tomorrow and update this PR accordingly. I am sorry if i caused some wasted time to the people helping me so far. Are there any resources I can use to locate where in the codebase to do changes? I searched through the existing unit tests for this but seem to have arrived at the wrong place :( Thank's for your time |
JoeRobich
left a comment
There was a problem hiding this comment.
LGTM
Can you add a test for _ = int.Parse("");?
|
@JoeRobich Sure thing. This uncovered the missing case for Another thing i was kind of suprised about was the test for _ = int.Parse("");In this case we get the following symbol classifications: This is in contrast to all other tests where the order of the |
@lameox Leave it as is. We are likely to make some changes with regards to the |
…tion/DiscardSyntaxClassifier.cs Co-Authored-By: Joey Robichaud <joseph.robichaud@microsoft.com>
…n't discards from the compilers view. Kept the tests around and tweaked them so they now check that nothing is classified in these cases.
|
Close and reopen to trigger retest |
…rTests.cs Co-Authored-By: Joey Robichaud <joseph.robichaud@microsoft.com>
| [Fact, Trait(Traits.Feature, Traits.Features.Classification)] | ||
| public async Task DiscardsInLambda() | ||
| { | ||
| await TestAsync(@" | ||
| class X | ||
| { | ||
| void N() | ||
| { | ||
| System.Func<int, int, int> a = (int _, int _) => 0; | ||
| } | ||
| }", | ||
| Namespace("System"), | ||
| Delegate("Func"), | ||
| Keyword("_"), | ||
| Keyword("_")); | ||
| } | ||
|
|
||
| [Fact, Trait(Traits.Feature, Traits.Features.Classification)] | ||
| public async Task DiscardsInLambdaWithInferredType() | ||
| { | ||
| await TestAsync(@" | ||
| class X | ||
| { | ||
| void N() | ||
| { | ||
| System.Func<int, int, int> a = (_, _) => 0; | ||
| } | ||
| }", | ||
| Namespace("System"), | ||
| Delegate("Func"), | ||
| Keyword("_"), | ||
| Keyword("_")); | ||
| } |
There was a problem hiding this comment.
These tests did not actually show success. The syntactic pass applied ParameterName in addition to the semantic pass adding Keyword, and the merge step prioritizes ParameterName over Keyword. The tests needed to be written past the merge step.
Fixed in #85225
…cally, resolving classification conflict (#85225) Fixes #51553. Roslyn classifies discards as keywords for syntax highlighting which shows whether or not `_` is referring to a symbol. <img width="329" height="230" alt="image" src="https://github.com/user-attachments/assets/3364de33-039c-451a-94e5-25cc2f091731" /> However, it's not working for lambda parameter discards: <img width="394" height="49" alt="image" src="https://github.com/user-attachments/assets/60c81709-2e7d-45ce-9821-f3830cea834a" /> There was an attempt to implement it in #40396 for lambda parameter discards: https://github.com/dotnet/roslyn/blob/6de0973c513f7d3940cc0b52ff7cd7d55b869982/src/Workspaces/CSharp/Portable/Classification/SyntaxClassification/DiscardSyntaxClassifier.cs#L36-L44 But this was insufficient because it was implemented in the semantic classifier. The syntactic classifier already classified it as ParameterName, and the two are merged with ordering rules which cause ParameterName to win over Keyword. https://github.com/dotnet/roslyn/blob/6de0973c513f7d3940cc0b52ff7cd7d55b869982/src/EditorFeatures/Core/Classification/ClassificationTypeFormatDefinitions.cs#L520-L523 This PR fixes the issue by implementing the proper classification in the syntactic classifier instead of the semantic classifier. This is preferable because the semantic classifier may run after more of a delay, so this is less visual flicker in the IDE. ###### Microsoft Reviewers: [Open in CodeFlow](https://microsoft.github.io/open-pr/?codeflow=https://github.com/dotnet/roslyn/pull/85225)
fixes #39768 .
This is my first contribution so please let me know if there is anything else needed apart from the exported highlighter or if there is a better place in the codebase to introduce the changes.