mirror of
https://github.com/rust-lang/rust.git
synced 2025-05-14 02:49:40 +00:00
Merge #2096
2096: further simplify assists r=matklad a=matklad Co-authored-by: Aleksey Kladov <aleksey.kladov@gmail.com>
This commit is contained in:
commit
534c8a0d78
@ -14,8 +14,8 @@ use crate::{AssistAction, AssistId, AssistLabel};
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub(crate) enum Assist {
|
||||
Unresolved(Vec<AssistLabel>),
|
||||
Resolved(Vec<(AssistLabel, AssistAction)>),
|
||||
Unresolved { label: AssistLabel },
|
||||
Resolved { label: AssistLabel, action: AssistAction },
|
||||
}
|
||||
|
||||
/// `AssistCtx` allows to apply an assist or check if it could be applied.
|
||||
@ -54,7 +54,6 @@ pub(crate) struct AssistCtx<'a, DB> {
|
||||
pub(crate) frange: FileRange,
|
||||
source_file: SourceFile,
|
||||
should_compute_edit: bool,
|
||||
assist: Assist,
|
||||
}
|
||||
|
||||
impl<'a, DB> Clone for AssistCtx<'a, DB> {
|
||||
@ -64,7 +63,6 @@ impl<'a, DB> Clone for AssistCtx<'a, DB> {
|
||||
frange: self.frange,
|
||||
source_file: self.source_file.clone(),
|
||||
should_compute_edit: self.should_compute_edit,
|
||||
assist: self.assist.clone(),
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -75,32 +73,30 @@ impl<'a, DB: HirDatabase> AssistCtx<'a, DB> {
|
||||
F: FnOnce(AssistCtx<DB>) -> T,
|
||||
{
|
||||
let parse = db.parse(frange.file_id);
|
||||
let assist =
|
||||
if should_compute_edit { Assist::Resolved(vec![]) } else { Assist::Unresolved(vec![]) };
|
||||
|
||||
let ctx = AssistCtx { db, frange, source_file: parse.tree(), should_compute_edit, assist };
|
||||
let ctx = AssistCtx { db, frange, source_file: parse.tree(), should_compute_edit };
|
||||
f(ctx)
|
||||
}
|
||||
|
||||
pub(crate) fn add_assist(
|
||||
mut self,
|
||||
self,
|
||||
id: AssistId,
|
||||
label: impl Into<String>,
|
||||
f: impl FnOnce(&mut AssistBuilder),
|
||||
) -> Option<Assist> {
|
||||
let label = AssistLabel { label: label.into(), id };
|
||||
match &mut self.assist {
|
||||
Assist::Unresolved(labels) => labels.push(label),
|
||||
Assist::Resolved(labels_actions) => {
|
||||
let action = {
|
||||
let mut edit = AssistBuilder::default();
|
||||
f(&mut edit);
|
||||
edit.build()
|
||||
};
|
||||
labels_actions.push((label, action));
|
||||
}
|
||||
}
|
||||
Some(self.assist)
|
||||
let assist = if self.should_compute_edit {
|
||||
let action = {
|
||||
let mut edit = AssistBuilder::default();
|
||||
f(&mut edit);
|
||||
edit.build()
|
||||
};
|
||||
Assist::Resolved { label, action }
|
||||
} else {
|
||||
Assist::Unresolved { label }
|
||||
};
|
||||
|
||||
Some(assist)
|
||||
}
|
||||
|
||||
pub(crate) fn token_at_offset(&self) -> TokenAtOffset<SyntaxToken> {
|
||||
|
@ -11,7 +11,6 @@ mod marks;
|
||||
mod doc_tests;
|
||||
|
||||
use hir::db::HirDatabase;
|
||||
use itertools::Itertools;
|
||||
use ra_db::FileRange;
|
||||
use ra_syntax::{TextRange, TextUnit};
|
||||
use ra_text_edit::TextEdit;
|
||||
@ -51,10 +50,10 @@ where
|
||||
.iter()
|
||||
.filter_map(|f| f(ctx.clone()))
|
||||
.map(|a| match a {
|
||||
Assist::Unresolved(labels) => labels,
|
||||
Assist::Resolved(..) => unreachable!(),
|
||||
Assist::Unresolved { label } => label,
|
||||
Assist::Resolved { .. } => unreachable!(),
|
||||
})
|
||||
.concat()
|
||||
.collect()
|
||||
})
|
||||
}
|
||||
|
||||
@ -73,10 +72,10 @@ where
|
||||
.iter()
|
||||
.filter_map(|f| f(ctx.clone()))
|
||||
.map(|a| match a {
|
||||
Assist::Resolved(labels_actions) => labels_actions,
|
||||
Assist::Unresolved(..) => unreachable!(),
|
||||
Assist::Resolved { label, action } => (label, action),
|
||||
Assist::Unresolved { .. } => unreachable!(),
|
||||
})
|
||||
.concat();
|
||||
.collect::<Vec<_>>();
|
||||
a.sort_by(|a, b| match (a.1.target, b.1.target) {
|
||||
(Some(a), Some(b)) => a.len().cmp(&b.len()),
|
||||
(Some(_), None) => Ordering::Less,
|
||||
@ -158,39 +157,6 @@ mod helpers {
|
||||
assist: fn(AssistCtx<MockDatabase>) -> Option<Assist>,
|
||||
before: &str,
|
||||
after: &str,
|
||||
) {
|
||||
check_assist_nth_action(assist, before, after, 0)
|
||||
}
|
||||
|
||||
pub(crate) fn check_assist_range(
|
||||
assist: fn(AssistCtx<MockDatabase>) -> Option<Assist>,
|
||||
before: &str,
|
||||
after: &str,
|
||||
) {
|
||||
check_assist_range_nth_action(assist, before, after, 0)
|
||||
}
|
||||
|
||||
pub(crate) fn check_assist_target(
|
||||
assist: fn(AssistCtx<MockDatabase>) -> Option<Assist>,
|
||||
before: &str,
|
||||
target: &str,
|
||||
) {
|
||||
check_assist_target_nth_action(assist, before, target, 0)
|
||||
}
|
||||
|
||||
pub(crate) fn check_assist_range_target(
|
||||
assist: fn(AssistCtx<MockDatabase>) -> Option<Assist>,
|
||||
before: &str,
|
||||
target: &str,
|
||||
) {
|
||||
check_assist_range_target_nth_action(assist, before, target, 0)
|
||||
}
|
||||
|
||||
pub(crate) fn check_assist_nth_action(
|
||||
assist: fn(AssistCtx<MockDatabase>) -> Option<Assist>,
|
||||
before: &str,
|
||||
after: &str,
|
||||
index: usize,
|
||||
) {
|
||||
let (before_cursor_pos, before) = extract_offset(before);
|
||||
let (db, _source_root, file_id) = MockDatabase::with_single_file(&before);
|
||||
@ -198,12 +164,11 @@ mod helpers {
|
||||
FileRange { file_id, range: TextRange::offset_len(before_cursor_pos, 0.into()) };
|
||||
let assist =
|
||||
AssistCtx::with_ctx(&db, frange, true, assist).expect("code action is not applicable");
|
||||
let labels_actions = match assist {
|
||||
Assist::Unresolved(_) => unreachable!(),
|
||||
Assist::Resolved(labels_actions) => labels_actions,
|
||||
let action = match assist {
|
||||
Assist::Unresolved { .. } => unreachable!(),
|
||||
Assist::Resolved { action, .. } => action,
|
||||
};
|
||||
|
||||
let (_, action) = labels_actions.get(index).expect("expect assist action at index");
|
||||
let actual = action.edit.apply(&before);
|
||||
let actual_cursor_pos = match action.cursor_position {
|
||||
None => action
|
||||
@ -216,23 +181,21 @@ mod helpers {
|
||||
assert_eq_text!(after, &actual);
|
||||
}
|
||||
|
||||
pub(crate) fn check_assist_range_nth_action(
|
||||
pub(crate) fn check_assist_range(
|
||||
assist: fn(AssistCtx<MockDatabase>) -> Option<Assist>,
|
||||
before: &str,
|
||||
after: &str,
|
||||
index: usize,
|
||||
) {
|
||||
let (range, before) = extract_range(before);
|
||||
let (db, _source_root, file_id) = MockDatabase::with_single_file(&before);
|
||||
let frange = FileRange { file_id, range };
|
||||
let assist =
|
||||
AssistCtx::with_ctx(&db, frange, true, assist).expect("code action is not applicable");
|
||||
let labels_actions = match assist {
|
||||
Assist::Unresolved(_) => unreachable!(),
|
||||
Assist::Resolved(labels_actions) => labels_actions,
|
||||
let action = match assist {
|
||||
Assist::Unresolved { .. } => unreachable!(),
|
||||
Assist::Resolved { action, .. } => action,
|
||||
};
|
||||
|
||||
let (_, action) = labels_actions.get(index).expect("expect assist action at index");
|
||||
let mut actual = action.edit.apply(&before);
|
||||
if let Some(pos) = action.cursor_position {
|
||||
actual = add_cursor(&actual, pos);
|
||||
@ -240,11 +203,10 @@ mod helpers {
|
||||
assert_eq_text!(after, &actual);
|
||||
}
|
||||
|
||||
pub(crate) fn check_assist_target_nth_action(
|
||||
pub(crate) fn check_assist_target(
|
||||
assist: fn(AssistCtx<MockDatabase>) -> Option<Assist>,
|
||||
before: &str,
|
||||
target: &str,
|
||||
index: usize,
|
||||
) {
|
||||
let (before_cursor_pos, before) = extract_offset(before);
|
||||
let (db, _source_root, file_id) = MockDatabase::with_single_file(&before);
|
||||
@ -252,33 +214,30 @@ mod helpers {
|
||||
FileRange { file_id, range: TextRange::offset_len(before_cursor_pos, 0.into()) };
|
||||
let assist =
|
||||
AssistCtx::with_ctx(&db, frange, true, assist).expect("code action is not applicable");
|
||||
let labels_actions = match assist {
|
||||
Assist::Unresolved(_) => unreachable!(),
|
||||
Assist::Resolved(labels_actions) => labels_actions,
|
||||
let action = match assist {
|
||||
Assist::Unresolved { .. } => unreachable!(),
|
||||
Assist::Resolved { action, .. } => action,
|
||||
};
|
||||
|
||||
let (_, action) = labels_actions.get(index).expect("expect assist action at index");
|
||||
let range = action.target.expect("expected target on action");
|
||||
assert_eq_text!(&before[range.start().to_usize()..range.end().to_usize()], target);
|
||||
}
|
||||
|
||||
pub(crate) fn check_assist_range_target_nth_action(
|
||||
pub(crate) fn check_assist_range_target(
|
||||
assist: fn(AssistCtx<MockDatabase>) -> Option<Assist>,
|
||||
before: &str,
|
||||
target: &str,
|
||||
index: usize,
|
||||
) {
|
||||
let (range, before) = extract_range(before);
|
||||
let (db, _source_root, file_id) = MockDatabase::with_single_file(&before);
|
||||
let frange = FileRange { file_id, range };
|
||||
let assist =
|
||||
AssistCtx::with_ctx(&db, frange, true, assist).expect("code action is not applicable");
|
||||
let labels_actions = match assist {
|
||||
Assist::Unresolved(_) => unreachable!(),
|
||||
Assist::Resolved(labels_actions) => labels_actions,
|
||||
let action = match assist {
|
||||
Assist::Unresolved { .. } => unreachable!(),
|
||||
Assist::Resolved { action, .. } => action,
|
||||
};
|
||||
|
||||
let (_, action) = labels_actions.get(index).expect("expect assist action at index");
|
||||
let range = action.target.expect("expected target on action");
|
||||
assert_eq_text!(&before[range.start().to_usize()..range.end().to_usize()], target);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user