-
Notifications
You must be signed in to change notification settings - Fork 1.6k
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
New assist to add/edit hide
at import for ambiguous import
#56830
Comments
Summary: This issue proposes a new quick-fix for ambiguous imports. It suggests adding a "hide" combinator to the import statement to resolve the ambiguity, either by adding a new "hide" or editing an existing one. |
It's possible for an ambiguous name to be imported through more than 2 imports. For example, given three libraries, L1, L2, and L3, that all define a class named Probably more common is that a single definition of the ambiguous name might be imported from multiple libraries. For example, given the libraries, L1 and L2, that both define a class named That raises a question about the DX. Rather than require the user to select one fix for every import that should have a Or maybe the set of imports from which it shouldn't be hidden, such as in the second example, where there's no point in hiding it from either L1 or L3 if the declaration in L1 is the one the user wants to use. Or maybe what's important isn't the import(s) to be unchanged, but the declaration (element in API terms) to be used. Although identifying the declaration might be tricky because the defining library might be an internal library that the user wouldn't recognize. Of maybe those scenarios are too complex and we should just not offer the fix in those cases. Curious to hear your thoughts. |
Yes, thank you for the suggestion. I hadn't thought of the multi-step process. However, I believe this would probably be hard to happen unless multiple libraries which export (say L2 exports L1) each other (or something similar) suddenly received a new declaration (say you declare
Yes, I do believe that this is ideal. The error message for If we had something like the "Docs side panel" (not sure what to call that) that we have for auto-complete options, in assists, we could show the element in the assist text and make sure our user was aware of which imports was it coming from. But since that is not the case I don't believe this would be a good option.
Although I see your very valid point here, I don't believe it would be easy for everyone to understand why more than one import was left without the While I prefer the "hide every other import" option, I was wondering what should we do in cases where one of the other imports is |
Maybe we could change the text in these cases for the fix adding something like |
Great points Brian about how maybe we should offer choices to the user like "Use the one from L1.dart". I worry about the length of a single quick fix text if it includes 2 or more URIs. Like if And like @FMorschel says, what if the imports are like: import 'package:foo/thingy/foo.dart';
import 'package:foo/thingy/bar.dart' show X;
import 'package:foo/thingy/baz.dart'; Then "Hide X from the 'package:foo/thingy/foo.dart' and 'package:foo/thingy/bar.dart' imports." is a little technically not correct, because we would (probably) add a So I like the "Use X from 'package:foo/thingy/baz.dart'" message. I don't think we need the "(removing 'show')" text (in some cases you would remove WDYT, @bwilkerson ? |
Yes, I'm aware. This suggestion was only to make sure the user knows we are removing a This is mainly because today all I actually wanted something shorter but could not think of a shorter message that would convey the same meaning. |
Sorry for the slow response. I was out for a couple of days a couple of weeks ago and I'm still digging my way out from under.
I wouldn't expect it to be very common, but then I would hope that most developers don't re-use names at all and almost never need to worry about resolving conflicts. (Something that isn't true in the analyzer code bases, sadly enough.) But if that were true then this assist would be a low-value proposition.
Good question. I would take the explicit Maybe the better solution is to add a prefix for one of the elements in order to allow both to be referenced.
I worry about the length of a message that contains a single URI. 😄
The messages don't need to, and I'd go so far as to say shouldn't, spell out every edit that needs to be made. They should be as short as possible while still telling the user what to expect. I'm not sure the "Use X ..." message does that because it doesn't indicate whether it will be done by updating combinators or by adding prefixes, but I do like the brevity. I'm not sure we can formulate a good message until we know exactly what the fix will do, and I'm not convinced we've gotten to that point yet. |
After considering your last comments I was considering maybe renaming it to:
About the
It would replace the first assist whenever any of the other imports had a WDYT? |
To note, I found #56255 which I think this is a dupe of. |
I think naming is hard. I still don't like the fact that they describe the edits to be made ("Hide others" and "Remove show"). What if the current state of the imports is such that we'd need to add |
I was thinking about it too but then I figured this would be better for when we create a fix that triggers an import rename it could say that there as well before the "to use" (like "Rename import to use...").
For this case - I know this is not ideal but - I'd choose the "remove show" since that would have a bigger impact on the user's code meaning. It would also be lower on the list, as suggested above, so less likely that the user will go for it. |
What do you mean by "an import rename"? If you mean a rename refactoring on the import prefix, then I don't believe that there's any way to do that. The fixes are currently required to produce the edits before the option is presented to the user, and that precludes them from prompting for more information. But maybe you mean something different?
On further reflection, I'm not sure it's possible to be in a state where both operations would need to be performed.
I still don't like it, but I'm not going to refuse to support the feature just because we can't find an ideal name for it. |
I was not aware of that. I was talking about this second suggestion (maybe add a specific not-in-use name and trigger a rename? Not a discussion for this issue but anyway): sdk/pkg/analysis_server/lib/src/services/correction/error_fix_status.yaml Lines 158 to 164 in 253e715
On normal day-to-day use I wouldn't expect so. But if you have the following:
class A {} And your code looks something like this: import 'lib1.dart' show A; // There could be other classes here that would conflict or the user just prefers using 'show'
import 'lib2.dart' hide A; // There could be other classes here that are needed
import 'lib3.dart'; // <-- Just added
A? a; Now we have the error being triggered and our suggestions would show As I said, I would not expect this to be the selected choice since I know it is not ideal, but if we ever think of a shorter name that expresses the same meaning we could always change this description and do some kind of public announcement for this kind of thing (not sure if it would be that important because of the same meaning part, but anyway). If you still dislike the action description we could go back to simply "Use X..." but even though this is shorter I would prefer the longer action descriptions for clarity (mainly for removing |
I might have written that, but I don't like that suggestion. I don't think there would be any places where the name would be ambiguous.
I think that's an uncommon enough occurrence that we should just not provide a fix in that case. If we solve the common case we've still improved life for a lot of users.
Exactly. Let's go with the "Hide others" and "Remove show" versions that you suggested earlier. |
@bwilkerson, I've rebased, migrated to the new element model and refactored considering the reviews from srawlins (he only looked at the correction producers and not the tests, although he said he would look at them today). Could you take a look at the CL when you have some time, please? Thanks a lot! |
After that issue, I made a new push that solved the current part files. I'm unsure about the new enhanced parts. I think this is good enough for now and we can open a new issue following this one to make it work for those cases. The problem for them currently, from what I understand: Say three files That is what I need to work on to fix. The way I understand the enhanced parts feature, there won't be any case where I would need to edit two different files, like for fixing a problem on |
Also to note, this could also maybe be a plausible fix for |
@srawlins and @bwilkerson can I get new reviews and an answer here so we can close this? Thanks for all the help! |
I've added a failing test for multi-level part files. Copied from the "Go to imports". Studied it a bit and I think I get it now. I don't think I did it right or there is still something missing in the implementation for it. I was expecting an error there but it found none. |
I found out that #58326 was the reason the test failed. Edited the test. |
Hi again @bwilkerson and @srawlins. I've merged main into this branch again. Everything is in order. Can I get new reviews here? Thanks a lot! |
@scheglov noticed that we have a small case to worry about here. How should we handle cases like: lib1.dart var foo = 0;
var bar = 0;
var baz = 0; lib2.dart var foo = 0; main.dart import 'lib1.dart' hide bar;
import 'lib1.dart' hide baz;
import 'lib2.dart';
void f() {
print(bar);
print(baz);
print(foo);
} In the sense that we have two imports with the same URL.
Up until my last patchset where uris were handled with a WDYT @bwilkerson? |
Correct. The imports from a parent part are only used if a name couldn't be resolved using the imports in the child part.
This is another case that I think is likely to be very uncommon, and hence probably not worth fixing at this time.
I think we should take option (1) and not display the fix. It's perfectly reasonable to ship a fix that handles the 90% case and doesn't appear for the remaining 10%, and doing so means that we get a solution for the majority of users that much sooner. (I will point out that having two or more imports of the same URI, all with either |
This issue is to track https://dart-review.googlesource.com/c/sdk/+/386020 and #56762.
This change would add a new quick-fix option to
ambiguous_import
to add ahide
combinator (or edit the current one to edit it). So cases like:a.dart
b.dart
c.dart
Would trigger this fix options to add
hide
to 'a.dart' or to edit thehide
at 'b.dart'.CC: @bwilkerson
The text was updated successfully, but these errors were encountered: