You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Pasting code with unknown color symbol prefixes it with colorScheme. #4757
Well that is odd. I was expecting to not be able to reproduce this, but if I create a new file with:
import'package:flutter/material.dart';
var a =ElevatedButton.styleFrom(
backgroundColor: backgroundColor,
);
And then press Save (which triggers fix-all-on-save), then I see the same thing:
import'package:flutter/material.dart';
var a =ElevatedButton.styleFrom(
backgroundColor: colorScheme.background,
);
I think this might be coming from a Flutter fix - there are a few that seems to migrate to "colorScheme.background" (such as flutter/flutter#110162), but at a glance, they all seem to have filters that I would expect to stop them firing here. I'll try to narrow it down.
# Changes made in https://github.com/flutter/flutter/pull/110162
- title: "Migrate to 'ColorScheme.background'"date: 2022-08-24element:
uris: [ 'material.dart' ]field: 'backgroundColor'inClass: 'ThemeData'changes:
- kind: 'rename'newName: 'colorScheme.foo'
@bwilkerson does this seem like a bug in the data driven fixes? The fix has inClass: 'ThemeData' but there's no ThemeData involved here - there's an unresolved variable called backgroundColor and it's being substituted (see my comment above for a repo - that's the only thing in the file).
The description makes it sounds like this is happening on 'paste', but I'm guessing that this is happening on 'save'. Even so, it's not clear to me that we want this kind of fix to run on save, given that the user might be mid-thought and have a different kind of fix in mind.
That said, yes, it seems like this is a bug. We know that the backgroundColor the transformation is referring to is in ThemeData, but there's (presumably) no way the reference can be referring to that field, so we shouldn't be transforming the reference.
backgroundColor is just a Color constant, so no, it doesn't refer to ThemeData.
I tried to replicate it right now to see if it was triggered on paste (as I vaguely remember it), or only on save (as @bwilkerson assumes). Right now I can't replicate this, for some reason, even though I have seen it happen several times. I hit save constantly (old Eclipse habit, since it saves a history marker in Eclipse every time you do that), so I may not have remembered that it was save and not paste that did it.
As far as I know, we're not able to perform a code change like that on 'paste', hence my guess. But however it's happening I think its a bug that we're making the transformation in this case, and maybe that we're applying transformation at this time even if it were only performing correct transformations.
As far as I know, we're not able to perform a code change like that on 'paste', hence my guess.
This is correct - there is no paste event in VS Code (well, it's still a proposed API so we can't use it yet). Though you can have auto-save enabled, as well as fix-all-on-save, so you could still see fixes run "just after" pasting. When reproducing this, I saw the change and thought I had also not saved.. however I then couldn't reproduce it without saving, so also assume I must have done it out of habit.
Even so, it's not clear to me that we want this kind of fix to run on save
Do you mean this fix specifically, or do you think all data-driven fixes should be excluded when fixes run on-save?
If it's going to do things like this, I'd agree - but if this issue was fixed, I'm less sure. If the user has chosen to fix-all-on-save, any fixes that are excluded are a potential source of confusion ("running Fix All fixes this, but setting fix-all-on-save does not"). Are these kinds of fixes (when working correctly) likely to be (or potentially) disruptive?
// The node has fewer components, which can happen, for example, when we
// can't figure out the class that used to define a field. We treat the
// missing components as wildcards and match the rest.
elementComponents is ["backgroundColor", "ThemeData"] and components is ["backgroundColor"]`. Since there's no class in components, it only compares the first items and they match. Disallowing these mismatched lengths fixes this issue, but (unsurprisingly) breaks a lot of other tests. It's not clear to me what a correct fix would be.
I'm not sure of the impact of this bug - if it's likely low and the fix is complex, I could also commit a test marked as failing for later.
Btw, while looking at this I initially found this function which I think is unused (perhaps superseded by the ElementMatcher class linked above?).
The code in element matcher is there so that if we find code of the form data.backgroundColor and don't know what data is we can still update the use site. I think the right fix is to notice when there is no receiver (data), which means that the identifier can only refer to a local variable or a field in the hierarchy. For the second case we should check to see whether the class containing the identifier (assuming it isn't in a function or static method) is a subtype of the class defining the element that was transformed (such as ThemeData). If it is a subtype, then the transform still makes sense; if not, then it doesn't.
I don't know whether the function is being used; I'd have to search for references to it. If it is unused, then it would be good to get rid of it.
Activity
DanTup commentedon Sep 25, 2023
Well that is odd. I was expecting to not be able to reproduce this, but if I create a new file with:
And then press Save (which triggers fix-all-on-save), then I see the same thing:
I think this might be coming from a Flutter fix - there are a few that seems to migrate to "colorScheme.background" (such as flutter/flutter#110162), but at a glance, they all seem to have filters that I would expect to stop them firing here. I'll try to narrow it down.
DanTup commentedon Sep 25, 2023
Looks like it's coming from this:
@bwilkerson does this seem like a bug in the data driven fixes? The fix has
inClass: 'ThemeData'but there's noThemeDatainvolved here - there's an unresolved variable calledbackgroundColorand it's being substituted (see my comment above for a repo - that's the only thing in the file).bwilkerson commentedon Sep 25, 2023
The description makes it sounds like this is happening on 'paste', but I'm guessing that this is happening on 'save'. Even so, it's not clear to me that we want this kind of fix to run on save, given that the user might be mid-thought and have a different kind of fix in mind.
That said, yes, it seems like this is a bug. We know that the
backgroundColorthe transformation is referring to is inThemeData, but there's (presumably) no way the reference can be referring to that field, so we shouldn't be transforming the reference.lukehutch commentedon Sep 25, 2023
backgroundColoris just aColorconstant, so no, it doesn't refer toThemeData.I tried to replicate it right now to see if it was triggered on paste (as I vaguely remember it), or only on save (as @bwilkerson assumes). Right now I can't replicate this, for some reason, even though I have seen it happen several times. I hit save constantly (old Eclipse habit, since it saves a history marker in Eclipse every time you do that), so I may not have remembered that it was save and not paste that did it.
bwilkerson commentedon Sep 25, 2023
As far as I know, we're not able to perform a code change like that on 'paste', hence my guess. But however it's happening I think its a bug that we're making the transformation in this case, and maybe that we're applying transformation at this time even if it were only performing correct transformations.
DanTup commentedon Sep 25, 2023
This is correct - there is no paste event in VS Code (well, it's still a proposed API so we can't use it yet). Though you can have auto-save enabled, as well as fix-all-on-save, so you could still see fixes run "just after" pasting. When reproducing this, I saw the change and thought I had also not saved.. however I then couldn't reproduce it without saving, so also assume I must have done it out of habit.
Do you mean this fix specifically, or do you think all data-driven fixes should be excluded when fixes run on-save?
If it's going to do things like this, I'd agree - but if this issue was fixed, I'm less sure. If the user has chosen to fix-all-on-save, any fixes that are excluded are a potential source of confusion ("running Fix All fixes this, but setting fix-all-on-save does not"). Are these kinds of fixes (when working correctly) likely to be (or potentially) disruptive?
bwilkerson commentedon Sep 25, 2023
I was probably reacting more to the buggy behavior than to the behavior is ought to have once the bug is fixed.
DanTup commentedon Sep 26, 2023
@bwilkerson got it, thanks!
I'm not very familiar with this code, but it seems to go wrong here:
https://github.com/dart-lang/sdk/blob/3c4d4ad450a472ad9d11635a81d9ba278896c576/pkg/analysis_server/lib/src/services/correction/fix/data_driven/element_matcher.dart#L68-L75
elementComponentsis["backgroundColor", "ThemeData"]andcomponents is["backgroundColor"]`. Since there's no class in components, it only compares the first items and they match. Disallowing these mismatched lengths fixes this issue, but (unsurprisingly) breaks a lot of other tests. It's not clear to me what a correct fix would be.I'm not sure of the impact of this bug - if it's likely low and the fix is complex, I could also commit a test marked as failing for later.
Btw, while looking at this I initially found this function which I think is unused (perhaps superseded by the
ElementMatcherclass linked above?).bwilkerson commentedon Sep 26, 2023
The code in element matcher is there so that if we find code of the form
data.backgroundColorand don't know whatdatais we can still update the use site. I think the right fix is to notice when there is no receiver (data), which means that the identifier can only refer to a local variable or a field in the hierarchy. For the second case we should check to see whether the class containing the identifier (assuming it isn't in a function or static method) is a subtype of the class defining the element that was transformed (such asThemeData). If it is a subtype, then the transform still makes sense; if not, then it doesn't.I don't know whether the function is being used; I'd have to search for references to it. If it is unused, then it would be good to get rid of it.
@keertip
keertip commentedon Sep 26, 2023
I will take a look.
Fix data driven fix bug when the element in question is not resolved.
keertip commentedon Sep 29, 2023
I have landed a fix for this. Will be in the next release of the SDK.
DanTup commentedon Sep 29, 2023
Great, thanks!
Closing this as fixed by dart-lang/sdk@c452dfc.
lukehutch commentedon Sep 29, 2023
Thanks @keertip!