Add remove_unused_with assist
Some checks failed
CI / Code style check (push) Has been cancelled
CI / Test (push) Has been cancelled
CI / Flake package (push) Has been cancelled
CI / Legacy package (push) Has been cancelled

This commit is contained in:
C P 2025-09-24 17:42:11 +01:00 committed by oxalica
parent 01e573c9e3
commit 504599f7e5
3 changed files with 93 additions and 0 deletions

View file

@ -21,6 +21,7 @@ mod pack_bindings;
mod remove_empty_inherit;
mod remove_empty_let_in;
mod remove_unused_binding;
mod remove_unused_with;
mod rewrite_string;
use crate::{DefDatabase, FileRange, TextEdit, WorkspaceEdit};
@ -53,6 +54,7 @@ pub(crate) fn assists(db: &dyn DefDatabase, frange: FileRange) -> Vec<Assist> {
remove_empty_inherit::remove_empty_inherit,
remove_empty_let_in::remove_empty_let_in,
remove_unused_binding::remove_unused_binding,
remove_unused_with::remove_unused_with,
rewrite_string::quote_attr,
rewrite_string::rewrite_indented_to_string,
rewrite_string::rewrite_string_to_indented,

View file

@ -0,0 +1,79 @@
//! Remove an unused `with ...`.
//!
//! ```nix
//! foo = with pkgs; [ pkgs.bar ];
//! ```
//! =>
//! ```nix
//! foo = [ pkgs.bar ];
//! ```
use super::{AssistKind, AssistsCtx};
use crate::DiagnosticKind::UnusedWith;
use crate::TextEdit;
use syntax::ast;
pub(super) fn remove_unused_with(ctx: &mut AssistsCtx<'_>) -> Option<()> {
let cursor_with = ctx.covering_node::<ast::With>()?;
let with_range = cursor_with.with_token()?.text_range();
let file = ctx.frange.file_id;
let check = ctx.db.liveness_check(file);
let diags = check.as_ref().to_diagnostics(ctx.db, file);
let no_relevant_diags = diags
.filter(|d| d.kind == UnusedWith && d.range.intersect(with_range).is_some())
.count()
== 0;
if no_relevant_diags {
return None;
}
let semicolon_token = cursor_with.semicolon_token()?;
let trivia_range = std::iter::successors(semicolon_token.next_token(), |tok| tok.next_token())
.take_while(|tok| tok.kind().is_trivia())
.last()
.unwrap_or(semicolon_token);
ctx.add(
"remove_unused_with",
"Remove unused with",
AssistKind::QuickFix,
vec![TextEdit {
delete: with_range.cover(trivia_range.text_range()),
insert: Default::default(),
}],
);
Some(())
}
#[cfg(test)]
mod tests {
use expect_test::expect;
define_check_assist!(super::remove_unused_with);
#[test]
fn in_use_with() {
check_no("a: $0with lib; bar");
}
#[test]
fn unused_with() {
// Simple
check("a: $0with 1;a", expect!["a: a"]);
// With trivia
check("a: $0with /* trivia */ 1; a", expect!["a: a"]);
// With array
check("a: $0with [ 1 ]; a", expect!["a: a"]);
// 1st of multiple
check("a: $0with 1; with 2; a", expect!["a: with 2; a"]);
// 2nd of multiple
check("a: with 1; $0with 2; a", expect!["a: with 1; a"]);
}
}

View file

@ -142,6 +142,18 @@ let
in {}
```
### `remove_unused_with`
Remove an unused `with ...`.
```nix
foo = with pkgs; [ pkgs.bar ];
```
=>
```nix
foo = [ pkgs.bar ];
```
### `rewrite_string_to_indented` and `rewrite_indented_to_string`
Rewrite between double quoted strings and indented strings