SourceFile, TextRange, AstNode, TextUnit, SyntaxNode,
algo::{find_leaf_at_offset, find_node_at_offset, find_covering_node, LeafAtOffset},
};
-use ra_ide_api_light::formatting::{leading_indent, reindent};
+use ra_fmt::{leading_indent, reindent};
use crate::{AssistLabel, AssistAction};
+#[derive(Clone, Debug)]
pub(crate) enum Assist {
- Unresolved(AssistLabel),
- Resolved(AssistLabel, AssistAction),
+ Unresolved(Vec<AssistLabel>),
+ Resolved(Vec<(AssistLabel, AssistAction)>),
}
/// `AssistCtx` allows to apply an assist or check if it could be applied.
///
-/// Assists use a somewhat overengineered approach, given the current needs. The
+/// Assists use a somewhat over-engineered approach, given the current needs. The
/// assists workflow consists of two phases. In the first phase, a user asks for
/// the list of available assists. In the second phase, the user picks a
/// particular assist and it gets applied.
pub(crate) frange: FileRange,
source_file: &'a SourceFile,
should_compute_edit: bool,
+ assist: Assist,
}
impl<'a, DB> Clone for AssistCtx<'a, DB> {
frange: self.frange,
source_file: self.source_file,
should_compute_edit: self.should_compute_edit,
+ assist: self.assist.clone(),
}
}
}
F: FnOnce(AssistCtx<DB>) -> T,
{
let source_file = &db.parse(frange.file_id);
- let ctx = AssistCtx {
- db,
- frange,
- source_file,
- should_compute_edit,
- };
+ let assist =
+ if should_compute_edit { Assist::Resolved(vec![]) } else { Assist::Unresolved(vec![]) };
+
+ let ctx = AssistCtx { db, frange, source_file, should_compute_edit, assist };
f(ctx)
}
- pub(crate) fn build(
- self,
+ pub(crate) fn add_action(
+ &mut self,
label: impl Into<String>,
f: impl FnOnce(&mut AssistBuilder),
- ) -> Option<Assist> {
- let label = AssistLabel {
- label: label.into(),
- };
- if !self.should_compute_edit {
- return Some(Assist::Unresolved(label));
+ ) -> &mut Self {
+ let label = AssistLabel { label: label.into() };
+ 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));
+ }
}
- let action = {
- let mut edit = AssistBuilder::default();
- f(&mut edit);
- edit.build()
- };
- Some(Assist::Resolved(label, action))
+ self
+ }
+
+ pub(crate) fn build(self) -> Option<Assist> {
+ Some(self.assist)
}
pub(crate) fn leaf_at_offset(&self) -> LeafAtOffset<&'a SyntaxNode> {
pub(crate) struct AssistBuilder {
edit: TextEditBuilder,
cursor_position: Option<TextUnit>,
+ target: Option<TextRange>,
}
impl AssistBuilder {
self.cursor_position = Some(offset)
}
+ pub(crate) fn target(&mut self, target: TextRange) {
+ self.target = Some(target)
+ }
+
fn build(self) -> AssistAction {
AssistAction {
edit: self.edit.finish(),
cursor_position: self.cursor_position,
+ target: self.target,
}
}
}