-
Notifications
You must be signed in to change notification settings - Fork 1.8k
feat: Added remove unused imports assist #14723
New issue
Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? # to your account
Conversation
The tests are failing due to trailing whitespace. This whitespace is in my test cases, how do I bypass this? Or should I go through and make sure that the assist never leaves behind trailing whitespace? |
Cleaning up trailing ws would be better! This is something Also, take a look at edit_in_place.rs --- "remove use" probably belongs there.
Yeah, we definitely should be better. At the same time, I think it's ok to land a poorly performing version first, it it is disabled via config (see I think what we want perhaps is "not used in the current file". Like, yes, there's always a possibility that some module somewhere does |
|
I am not sure I agree. Consider the test module. Uses in the test module shouldn't count as uses in the overall file. I didn't realize that |
56615d1
to
fb0a675
Compare
☔ The latest upstream changes (presumably #14733) made this pull request unmergeable. Please resolve the merge conflicts. |
Please remove the merge commit, we prefer rebases |
☔ The latest upstream changes (presumably #14881) made this pull request unmergeable. Please resolve the merge conflicts. |
This would be nice as a diagnostic too 😅. |
Did you change the behavior here? |
I don't think so (been a few weeks, not 100% sure); I might have just forgotten to fix that. I will try to take a look at that tonight. |
Went ahead and added a function for this. I needed a way to split a |
Sorry for the long silence, have been busy and sick (and slowly reviewing other PRs here), will try to get back to this this week. |
crates/ide-db/src/search.rs
Outdated
fn split_at_subrange( | ||
first: TextRange, | ||
second: TextRange, | ||
) -> (TextRange, Option<TextRange>) { | ||
let intersect = first.intersect(second); | ||
if let Some(intersect) = intersect { | ||
let start_range = TextRange::new(first.start(), intersect.start()); | ||
|
||
if intersect.end() < first.end() { | ||
(start_range, Some(TextRange::new(intersect.end(), first.end()))) | ||
} else { | ||
(start_range, None) | ||
} | ||
} else { | ||
(first, None) | ||
} | ||
} | ||
|
||
if let Some(range) = range { | ||
let mut ranges = vec![range]; | ||
|
||
for child in module.children(db) { | ||
let rng = match child.definition_source(db).value { | ||
ModuleSource::SourceFile(_) => continue, | ||
ModuleSource::Module(it) => it.syntax().text_range(), | ||
ModuleSource::BlockExpr(it) => it.syntax().text_range(), | ||
}; | ||
let mut new_ranges = Vec::new(); | ||
for old_range in ranges.iter_mut() { | ||
let split = split_at_subrange(old_range.clone(), rng); | ||
*old_range = split.0; | ||
new_ranges.extend(split.1); | ||
} | ||
|
||
ranges.append(&mut new_ranges); | ||
} | ||
|
||
for range in ranges { | ||
entries.insert(file_id, Some(range)); | ||
} | ||
} else { | ||
entries.insert(file_id, range); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let's not add this stuff here, it's fine if we include inline child modules in a modules search range (in fact, the current logic here will remove block expressions if the declare items which is also definitely unexpected).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Without this we can have a mismatch between the rustc warning and the assist. Is that ok? I can fix the block expression thing just by ignoring that case in the match.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As in an import that is not used in the module but in the child would silence the assist?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That is correct. use_in_submodule_doesnt_count
tests this. If you remove this code then that test will fail.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Well, I also just realized that this doesn't work here since SearchScope's entries is a hashmap (so the code here currently only sets the search range to the last one). I think it would be better to just construct the whole module search scope then and have the remove_unused_imports assist split the searchscope accordingly into multiple for each range of the module then (like is done here right now)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I moved this to remove_unused_imports.rs
and made it return a Vec<SearchScope>
. This function could still easily go in search.rs I think.
Apologies for the delay. Final Fantasy 16, then life got me. Gonna update this tonight. |
…the search scope by reference.
@bors r+ |
☀️ Test successful - checks-actions |
remove-unused-imports.mp4 |
finally! |
This feature also seems to remove imports of attributes like |
@heksesang Probably want to put in an issue for that. That might be a limitation of the current find usages code. |
This resolves the most important part of #5131. I needed to make a couple of cosmetic changes to the search infrastructure to do this.
A few open questions: