Repository navigation
Highlighting bug for named record fields #5294
Copy link
Copy link
Closed
Labels
in editorRelates to code editing or language featuresRelates to code editing or language featuresin lsp/analysis serverSomething to be fixed in the Dart analysis serverSomething to be fixed in the Dart analysis serveris bugrelies on sdk changesSomething that requires changes in the Dart/Flutter SDK to ship before it will become availableSomething that requires changes in the Dart/Flutter SDK to ship before it will become available
Milestone
Description
Describe the bug
Selecting the name of a record field highlights everything matching the name.
Dart-Code-Log-2024-09-02 08-36-25.txt
To Reproduce
Steps to reproduce the behavior:
- Open a new project
- Add the repro:
void foo(int variable) {
var record = (variable: variable,);
}- Select the parameter
variableand see it highlighting itself and its use (the lastvariableon line 2) - Select the record name
variableand see everyvariablehighlighted.
Expected behavior
I expect the only highlight to be the record name in the second case.
Please complete the following information:
Workspace Environment
Dart Code extension: 3.99.20240930
Flutter extension: 3.99.20240930 (activated)
App: Visual Studio Code
App Host: desktop
Version: win 1.93.1
Workspace type: Dart (LSP)
Workspace name: bug
Dart (3.6.0-edge.c3b2672a19ef46317e8d71d73e7094eb4c5bca1a): C:\Users\felip_0vh5fa6\dart
Flutter (3.24.3): C:\Users\felip_0vh5fa6\.puro\envs\stable\flutter (No device)
Output from 'dart info'
C:\Users\felip_0vh5fa6\dart\bin\dart.exe info
If providing this information as part of reporting a bug, please review the information
below to ensure it only contains things you're comfortable posting publicly.
General info
- Dart 3.6.0-edge.c3b2672a19ef46317e8d71d73e7094eb4c5bca1a (main) (Mon Sep 23 21:51:31 2024 +0000) on "windows_x64"
- on windows / "Windows 10 Pro" 10.0 (Build 22631)
- locale is pt-BR
Project info
- sdk constraint: '>=3.3.0 <4.0.0'
- dependencies: collection, dart_either, either_dart, equatable, path, test, time
- dev_dependencies: dart_code_metrics, lints
Process info
| Memory | CPU | Elapsed time | Command line |
|---|---|---|---|
| 0 MB | -- | dart.exe | |
| 0 MB | -- | dart.exe | |
| 0 MB | -- | dart.exe | |
| 0 MB | -- | dart.exe | |
| 0 MB | -- | dart.exe |
Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
in editorRelates to code editing or language featuresRelates to code editing or language featuresin lsp/analysis serverSomething to be fixed in the Dart analysis serverSomething to be fixed in the Dart analysis serveris bugrelies on sdk changesSomething that requires changes in the Dart/Flutter SDK to ship before it will become availableSomething that requires changes in the Dart/Flutter SDK to ship before it will become available
Activity
DanTup commentedon Oct 1, 2024
The reason this occurs is that we don't find any occurrences here, so we return
null. This causes VS Code to fall back to its built-in behaviour of searching the document.While we could change this to return an empty list instead of null, in the example above it would prevent the single
variablesymbol where the cursor is from being highlighted - really we should be returning a single instance that covers that symbol. Probably record named fields just aren't handled correctly by the occurrences code.DanTup commentedon Oct 2, 2024
I've a fix at https://dart-review.googlesource.com/c/sdk/+/387961 that will prevent the bad highlighting (by returning an empty list instead of
null, preventing VS Code trying to handle this).However, because we don't produce any occurrence (not even one for the field name under the cursor), it also means we don't highlight the symbol like we would for other things. Here, "paramName" gets highlighted when I put my cursor in it, but
recordFieldNamedoes not:occurrences.mp4
I think it would be nice to fix that even if there's no element (but currently Occurrences are based entirely on elements). But I think it would even be nice to support linking the field names on records as occurrences if they are the same record type. For example the
as in the variablesaandchere, and bothprintstatements that use them, I think should be considered references:@bwilkerson any opinions on this? It means Occurrences (or a variation of) would need to handle named record fields (and possibly indexed fields) specifically (without elements). This might not be compatible with the legacy protocol (which returns the
Elements), but we could make something protocol-agnostic and then just filter to the element-based occurences for that.Although - I do also wonder whether this "problem" goes further than occurrences... For example today I can't do "Find References" on a record name, but it would sure be nice if I could (I've tried this so many times and then remembered it doesn't work). Is there a way we could handle all of those? For example something like a synthetic
Elementfor these record fields (that we could also find references for)?FMorschel commentedon Oct 2, 2024
Whenever we have an extension type that wraps a record (of course also adding the getters) we have the right highlighting. Maybe something similar to this? It would also work for "Find References" I think.
Edit
Today we have dart-lang/language#3839 for tracking
extension typetoimplementsits own record type.bwilkerson commentedon Oct 2, 2024
The problem is that record types (and function types) are structural types. See dart-lang/sdk#53024 (comment) for more context.
[analysis_server] Return empty document highlights instead of null wh…
DanTup commentedon Oct 2, 2024
Assuming this means we couldn't/shouldn't consider fields with the same name of two records with the same shape to be equivalent generally, what about just supporting it for Document Highlights (which only apply to the current file)?
Eg. instead of using an
elementas the container for the references, we just produce some synthetic identifier that is a combination of the type (so each differently shaped record would be unique) and the field name/index? It seems a shame that in code like:That we don't highlight both
as when the cursor is in one, regardless of the specifics. We could perhaps limit it to just the scope where a record variable is defined - however I don't think users would be surprised if identically shaped records in the file were also highlighted as being related, because it's very possible the same type is being passed between functions within the file.Although, perhaps this is a slippery slope... if they highlight, it might then be unclear why things like Find References don't work... and then a special case just for document highlights might not look like the right choice.
bwilkerson commentedon Oct 2, 2024
It's a thorny issue, and I agree that we probably need to look at all of our features to make sure that we're handling it consistently.
Two records with the same shape (type) could be completely unrelated, so I'm not sure that's enough. Unless the records have named fields, the shape is defined purely by the types of the fields.
I agree, 100%
But it would also be a shame to highlight references to two unrelated fields at the same time just because they had the same name.
DanTup commentedon Oct 3, 2024
Yeah, that's fair. Is there any path from a record field name back to where the type for it was defined? For example in the code:
Is there an easy/quick way from
ainr1.ato know that the type comes from the parameter, and thatainr2.athat the type comes from the local variable, and thatainr3.aalso comes from ther2local variable? Although, again, if we implemented that for document highlights, maybe there would be an expectation for Find References/rename etc. to work too, so perhaps solving it in document highlights isn't the right approach.If there's the possibility of supporting this, should I move this to the SDK (or update dart-lang/sdk#53024 to be more general)? If it's unlikely, we can just close this with the fix above (which stops the incorrect highlighting, but by not providing any highlighting for this case).
bwilkerson commentedon Oct 3, 2024
Yes. If we have a reference to a field on a record-typed variable then we could look at the declaration of the variable to see whether there's a type. If there is, then we could conclude that the field in the type is related to the field in the access.
Yes. We could extend the logic above to look, when there's no type annotation on the variable, to look at the initializer to see whether it's a record literal. If it is, then we could conclude that the accessed field and the field in the literal are related.
Yes, but it would require having a data flow analysis that we don't currently have.
I hope that we will be able to do a better job with structural types at some point, but I don't know whether it will ever be a high enough priority to actually schedule the work it would take. That's not the answer I'd like to give, but I think that's the reality of the situation.
DanTup commentedon Oct 3, 2024
Thanks for the info! I think it makes sense to close this with the fix above then (we no longer cause VS Code to highlight incorrect references). I'll add a note on dart-lang/sdk#53024 about this issue since they're similar and another issue can be split out if one is to be implemented in a way that doesn't solve the other.