Skip to content

Commit b356ab4

Browse files
bors[bot]eulerdisk
andcommitted
Merge #781
781: Refactor to allow for multiple assists r=matklad a=eulerdisk This is necessary to allow assist "providers" (which currently are simple free function) to produce multiple assists. I'm not sure this is the best possible refactoring tough. Co-authored-by: Andrea Pretto <[email protected]>
2 parents 77ccac7 + 5c9c0d3 commit b356ab4

14 files changed

+146
-64
lines changed

Cargo.lock

+1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

crates/ra_assists/Cargo.toml

+1
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ authors = ["rust-analyzer developers"]
66

77
[dependencies]
88
join_to_string = "0.1.3"
9+
itertools = "0.8.0"
910

1011
ra_syntax = { path = "../ra_syntax" }
1112
ra_text_edit = { path = "../ra_text_edit" }

crates/ra_assists/src/add_derive.rs

+5-3
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,10 @@ use ra_syntax::{
77

88
use crate::{AssistCtx, Assist};
99

10-
pub(crate) fn add_derive(ctx: AssistCtx<impl HirDatabase>) -> Option<Assist> {
10+
pub(crate) fn add_derive(mut ctx: AssistCtx<impl HirDatabase>) -> Option<Assist> {
1111
let nominal = ctx.node_at_offset::<ast::NominalDef>()?;
1212
let node_start = derive_insertion_offset(nominal)?;
13-
ctx.build("add `#[derive]`", |edit| {
13+
ctx.add_action("add `#[derive]`", |edit| {
1414
let derive_attr = nominal
1515
.attrs()
1616
.filter_map(|x| x.as_call())
@@ -26,7 +26,9 @@ pub(crate) fn add_derive(ctx: AssistCtx<impl HirDatabase>) -> Option<Assist> {
2626
};
2727
edit.target(nominal.syntax().range());
2828
edit.set_cursor(offset)
29-
})
29+
});
30+
31+
ctx.build()
3032
}
3133

3234
// Insert `derive` after doc comments.

crates/ra_assists/src/add_impl.rs

+5-3
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,10 @@ use ra_syntax::{
77

88
use crate::{AssistCtx, Assist};
99

10-
pub(crate) fn add_impl(ctx: AssistCtx<impl HirDatabase>) -> Option<Assist> {
10+
pub(crate) fn add_impl(mut ctx: AssistCtx<impl HirDatabase>) -> Option<Assist> {
1111
let nominal = ctx.node_at_offset::<ast::NominalDef>()?;
1212
let name = nominal.name()?;
13-
ctx.build("add impl", |edit| {
13+
ctx.add_action("add impl", |edit| {
1414
edit.target(nominal.syntax().range());
1515
let type_params = nominal.type_param_list();
1616
let start_offset = nominal.syntax().range().end();
@@ -32,7 +32,9 @@ pub(crate) fn add_impl(ctx: AssistCtx<impl HirDatabase>) -> Option<Assist> {
3232
edit.set_cursor(start_offset + TextUnit::of_str(&buf));
3333
buf.push_str("\n}");
3434
edit.insert(start_offset, buf);
35-
})
35+
});
36+
37+
ctx.build()
3638
}
3739

3840
#[cfg(test)]

crates/ra_assists/src/assist_ctx.rs

+27-14
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,10 @@ use ra_fmt::{leading_indent, reindent};
99

1010
use crate::{AssistLabel, AssistAction};
1111

12+
#[derive(Clone, Debug)]
1213
pub(crate) enum Assist {
13-
Unresolved(AssistLabel),
14-
Resolved(AssistLabel, AssistAction),
14+
Unresolved(Vec<AssistLabel>),
15+
Resolved(Vec<(AssistLabel, AssistAction)>),
1516
}
1617

1718
/// `AssistCtx` allows to apply an assist or check if it could be applied.
@@ -50,6 +51,7 @@ pub(crate) struct AssistCtx<'a, DB> {
5051
pub(crate) frange: FileRange,
5152
source_file: &'a SourceFile,
5253
should_compute_edit: bool,
54+
assist: Assist,
5355
}
5456

5557
impl<'a, DB> Clone for AssistCtx<'a, DB> {
@@ -59,6 +61,7 @@ impl<'a, DB> Clone for AssistCtx<'a, DB> {
5961
frange: self.frange,
6062
source_file: self.source_file,
6163
should_compute_edit: self.should_compute_edit,
64+
assist: self.assist.clone(),
6265
}
6366
}
6467
}
@@ -69,25 +72,35 @@ impl<'a, DB: HirDatabase> AssistCtx<'a, DB> {
6972
F: FnOnce(AssistCtx<DB>) -> T,
7073
{
7174
let source_file = &db.parse(frange.file_id);
72-
let ctx = AssistCtx { db, frange, source_file, should_compute_edit };
75+
let assist =
76+
if should_compute_edit { Assist::Resolved(vec![]) } else { Assist::Unresolved(vec![]) };
77+
78+
let ctx = AssistCtx { db, frange, source_file, should_compute_edit, assist };
7379
f(ctx)
7480
}
7581

76-
pub(crate) fn build(
77-
self,
82+
pub(crate) fn add_action(
83+
&mut self,
7884
label: impl Into<String>,
7985
f: impl FnOnce(&mut AssistBuilder),
80-
) -> Option<Assist> {
86+
) -> &mut Self {
8187
let label = AssistLabel { label: label.into() };
82-
if !self.should_compute_edit {
83-
return Some(Assist::Unresolved(label));
88+
match &mut self.assist {
89+
Assist::Unresolved(labels) => labels.push(label),
90+
Assist::Resolved(labels_actions) => {
91+
let action = {
92+
let mut edit = AssistBuilder::default();
93+
f(&mut edit);
94+
edit.build()
95+
};
96+
labels_actions.push((label, action));
97+
}
8498
}
85-
let action = {
86-
let mut edit = AssistBuilder::default();
87-
f(&mut edit);
88-
edit.build()
89-
};
90-
Some(Assist::Resolved(label, action))
99+
self
100+
}
101+
102+
pub(crate) fn build(self) -> Option<Assist> {
103+
Some(self.assist)
91104
}
92105

93106
pub(crate) fn leaf_at_offset(&self) -> LeafAtOffset<&'a SyntaxNode> {

crates/ra_assists/src/auto_import.rs

+5-3
Original file line numberDiff line numberDiff line change
@@ -480,7 +480,7 @@ fn make_assist_add_nested_import(
480480
}
481481
}
482482

483-
pub(crate) fn auto_import(ctx: AssistCtx<impl HirDatabase>) -> Option<Assist> {
483+
pub(crate) fn auto_import(mut ctx: AssistCtx<impl HirDatabase>) -> Option<Assist> {
484484
let node = ctx.covering_node();
485485
let current_file = node.ancestors().find_map(ast::SourceFile::cast)?;
486486

@@ -495,7 +495,7 @@ pub(crate) fn auto_import(ctx: AssistCtx<impl HirDatabase>) -> Option<Assist> {
495495
return None;
496496
}
497497

498-
ctx.build(format!("import {} in the current file", fmt_segments(&segments)), |edit| {
498+
ctx.add_action(format!("import {} in the current file", fmt_segments(&segments)), |edit| {
499499
let action = best_action_for_target(current_file.syntax(), path, &segments);
500500
make_assist(&action, segments.as_slice(), edit);
501501
if let Some(last_segment) = path.segment() {
@@ -506,7 +506,9 @@ pub(crate) fn auto_import(ctx: AssistCtx<impl HirDatabase>) -> Option<Assist> {
506506
last_segment.syntax().range().start(),
507507
));
508508
}
509-
})
509+
});
510+
511+
ctx.build()
510512
}
511513

512514
#[cfg(test)]

crates/ra_assists/src/change_visibility.rs

+13-7
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ pub(crate) fn change_visibility(ctx: AssistCtx<impl HirDatabase>) -> Option<Assi
1414
add_vis(ctx)
1515
}
1616

17-
fn add_vis(ctx: AssistCtx<impl HirDatabase>) -> Option<Assist> {
17+
fn add_vis(mut ctx: AssistCtx<impl HirDatabase>) -> Option<Assist> {
1818
let item_keyword = ctx.leaf_at_offset().find(|leaf| match leaf.kind() {
1919
FN_KW | MOD_KW | STRUCT_KW | ENUM_KW | TRAIT_KW => true,
2020
_ => false,
@@ -41,11 +41,13 @@ fn add_vis(ctx: AssistCtx<impl HirDatabase>) -> Option<Assist> {
4141
(vis_offset(field.syntax()), ident.range())
4242
};
4343

44-
ctx.build("make pub(crate)", |edit| {
44+
ctx.add_action("make pub(crate)", |edit| {
4545
edit.target(target);
4646
edit.insert(offset, "pub(crate) ");
4747
edit.set_cursor(offset);
48-
})
48+
});
49+
50+
ctx.build()
4951
}
5052

5153
fn vis_offset(node: &SyntaxNode) -> TextUnit {
@@ -59,20 +61,24 @@ fn vis_offset(node: &SyntaxNode) -> TextUnit {
5961
.unwrap_or(node.range().start())
6062
}
6163

62-
fn change_vis(ctx: AssistCtx<impl HirDatabase>, vis: &ast::Visibility) -> Option<Assist> {
64+
fn change_vis(mut ctx: AssistCtx<impl HirDatabase>, vis: &ast::Visibility) -> Option<Assist> {
6365
if vis.syntax().text() == "pub" {
64-
return ctx.build("change to pub(crate)", |edit| {
66+
ctx.add_action("change to pub(crate)", |edit| {
6567
edit.target(vis.syntax().range());
6668
edit.replace(vis.syntax().range(), "pub(crate)");
67-
edit.set_cursor(vis.syntax().range().start());
69+
edit.set_cursor(vis.syntax().range().start())
6870
});
71+
72+
return ctx.build();
6973
}
7074
if vis.syntax().text() == "pub(crate)" {
71-
return ctx.build("change to pub", |edit| {
75+
ctx.add_action("change to pub", |edit| {
7276
edit.target(vis.syntax().range());
7377
edit.replace(vis.syntax().range(), "pub");
7478
edit.set_cursor(vis.syntax().range().start());
7579
});
80+
81+
return ctx.build();
7682
}
7783
None
7884
}

crates/ra_assists/src/fill_match_arms.rs

+5-3
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ use ra_syntax::ast::{self, AstNode};
88

99
use crate::{AssistCtx, Assist};
1010

11-
pub(crate) fn fill_match_arms(ctx: AssistCtx<impl HirDatabase>) -> Option<Assist> {
11+
pub(crate) fn fill_match_arms(mut ctx: AssistCtx<impl HirDatabase>) -> Option<Assist> {
1212
let match_expr = ctx.node_at_offset::<ast::MatchExpr>()?;
1313

1414
// We already have some match arms, so we don't provide any assists.
@@ -33,7 +33,7 @@ pub(crate) fn fill_match_arms(ctx: AssistCtx<impl HirDatabase>) -> Option<Assist
3333
let enum_name = enum_def.name(ctx.db)?;
3434
let db = ctx.db;
3535

36-
ctx.build("fill match arms", |edit| {
36+
ctx.add_action("fill match arms", |edit| {
3737
let mut buf = format!("match {} {{\n", expr.syntax().text().to_string());
3838
let variants = enum_def.variants(db);
3939
for variant in variants {
@@ -68,7 +68,9 @@ pub(crate) fn fill_match_arms(ctx: AssistCtx<impl HirDatabase>) -> Option<Assist
6868
edit.target(match_expr.syntax().range());
6969
edit.set_cursor(expr.syntax().range().start());
7070
edit.replace_node_and_indent(match_expr.syntax(), buf);
71-
})
71+
});
72+
73+
ctx.build()
7274
}
7375

7476
#[cfg(test)]

crates/ra_assists/src/flip_comma.rs

+5-3
Original file line numberDiff line numberDiff line change
@@ -6,15 +6,17 @@ use ra_syntax::{
66

77
use crate::{AssistCtx, Assist, non_trivia_sibling};
88

9-
pub(crate) fn flip_comma(ctx: AssistCtx<impl HirDatabase>) -> Option<Assist> {
9+
pub(crate) fn flip_comma(mut ctx: AssistCtx<impl HirDatabase>) -> Option<Assist> {
1010
let comma = ctx.leaf_at_offset().find(|leaf| leaf.kind() == COMMA)?;
1111
let prev = non_trivia_sibling(comma, Direction::Prev)?;
1212
let next = non_trivia_sibling(comma, Direction::Next)?;
13-
ctx.build("flip comma", |edit| {
13+
ctx.add_action("flip comma", |edit| {
1414
edit.target(comma.range());
1515
edit.replace(prev.range(), next.text());
1616
edit.replace(next.range(), prev.text());
17-
})
17+
});
18+
19+
ctx.build()
1820
}
1921

2022
#[cfg(test)]

crates/ra_assists/src/introduce_variable.rs

+5-3
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ use ra_syntax::{
88

99
use crate::{AssistCtx, Assist};
1010

11-
pub(crate) fn introduce_variable(ctx: AssistCtx<impl HirDatabase>) -> Option<Assist> {
11+
pub(crate) fn introduce_variable(mut ctx: AssistCtx<impl HirDatabase>) -> Option<Assist> {
1212
let node = ctx.covering_node();
1313
if !valid_covering_node(node) {
1414
return None;
@@ -19,7 +19,7 @@ pub(crate) fn introduce_variable(ctx: AssistCtx<impl HirDatabase>) -> Option<Ass
1919
if indent.kind() != WHITESPACE {
2020
return None;
2121
}
22-
ctx.build("introduce variable", move |edit| {
22+
ctx.add_action("introduce variable", move |edit| {
2323
let mut buf = String::new();
2424

2525
let cursor_offset = if wrap_in_block {
@@ -68,7 +68,9 @@ pub(crate) fn introduce_variable(ctx: AssistCtx<impl HirDatabase>) -> Option<Ass
6868
}
6969
}
7070
edit.set_cursor(anchor_stmt.range().start() + cursor_offset);
71-
})
71+
});
72+
73+
ctx.build()
7274
}
7375

7476
fn valid_covering_node(node: &SyntaxNode) -> bool {

0 commit comments

Comments
 (0)