diff options
Diffstat (limited to 'crates/ra_assists/src')
22 files changed, 297 insertions, 91 deletions
diff --git a/crates/ra_assists/src/assist_ctx.rs b/crates/ra_assists/src/assist_ctx.rs index c3e653299..2fe7c3de3 100644 --- a/crates/ra_assists/src/assist_ctx.rs +++ b/crates/ra_assists/src/assist_ctx.rs | |||
@@ -5,12 +5,12 @@ use ra_fmt::{leading_indent, reindent}; | |||
5 | use ra_ide_db::RootDatabase; | 5 | use ra_ide_db::RootDatabase; |
6 | use ra_syntax::{ | 6 | use ra_syntax::{ |
7 | algo::{self, find_covering_element, find_node_at_offset}, | 7 | algo::{self, find_covering_element, find_node_at_offset}, |
8 | AstNode, SourceFile, SyntaxElement, SyntaxKind, SyntaxNode, SyntaxToken, TextRange, TextUnit, | 8 | AstNode, SourceFile, SyntaxElement, SyntaxKind, SyntaxNode, SyntaxToken, TextRange, TextSize, |
9 | TokenAtOffset, | 9 | TokenAtOffset, |
10 | }; | 10 | }; |
11 | use ra_text_edit::TextEditBuilder; | 11 | use ra_text_edit::TextEditBuilder; |
12 | 12 | ||
13 | use crate::{AssistAction, AssistId, AssistLabel, GroupLabel, ResolvedAssist}; | 13 | use crate::{AssistAction, AssistFile, AssistId, AssistLabel, GroupLabel, ResolvedAssist}; |
14 | use algo::SyntaxRewriter; | 14 | use algo::SyntaxRewriter; |
15 | 15 | ||
16 | #[derive(Clone, Debug)] | 16 | #[derive(Clone, Debug)] |
@@ -178,8 +178,9 @@ impl<'a> AssistGroup<'a> { | |||
178 | #[derive(Default)] | 178 | #[derive(Default)] |
179 | pub(crate) struct ActionBuilder { | 179 | pub(crate) struct ActionBuilder { |
180 | edit: TextEditBuilder, | 180 | edit: TextEditBuilder, |
181 | cursor_position: Option<TextUnit>, | 181 | cursor_position: Option<TextSize>, |
182 | target: Option<TextRange>, | 182 | target: Option<TextRange>, |
183 | file: AssistFile, | ||
183 | } | 184 | } |
184 | 185 | ||
185 | impl ActionBuilder { | 186 | impl ActionBuilder { |
@@ -210,12 +211,12 @@ impl ActionBuilder { | |||
210 | } | 211 | } |
211 | 212 | ||
212 | /// Append specified `text` at the given `offset` | 213 | /// Append specified `text` at the given `offset` |
213 | pub(crate) fn insert(&mut self, offset: TextUnit, text: impl Into<String>) { | 214 | pub(crate) fn insert(&mut self, offset: TextSize, text: impl Into<String>) { |
214 | self.edit.insert(offset, text.into()) | 215 | self.edit.insert(offset, text.into()) |
215 | } | 216 | } |
216 | 217 | ||
217 | /// Specify desired position of the cursor after the assist is applied. | 218 | /// Specify desired position of the cursor after the assist is applied. |
218 | pub(crate) fn set_cursor(&mut self, offset: TextUnit) { | 219 | pub(crate) fn set_cursor(&mut self, offset: TextSize) { |
219 | self.cursor_position = Some(offset) | 220 | self.cursor_position = Some(offset) |
220 | } | 221 | } |
221 | 222 | ||
@@ -241,11 +242,16 @@ impl ActionBuilder { | |||
241 | algo::diff(&node, &new).into_text_edit(&mut self.edit) | 242 | algo::diff(&node, &new).into_text_edit(&mut self.edit) |
242 | } | 243 | } |
243 | 244 | ||
245 | pub(crate) fn set_file(&mut self, assist_file: AssistFile) { | ||
246 | self.file = assist_file | ||
247 | } | ||
248 | |||
244 | fn build(self) -> AssistAction { | 249 | fn build(self) -> AssistAction { |
245 | AssistAction { | 250 | AssistAction { |
246 | edit: self.edit.finish(), | 251 | edit: self.edit.finish(), |
247 | cursor_position: self.cursor_position, | 252 | cursor_position: self.cursor_position, |
248 | target: self.target, | 253 | target: self.target, |
254 | file: self.file, | ||
249 | } | 255 | } |
250 | } | 256 | } |
251 | } | 257 | } |
diff --git a/crates/ra_assists/src/doc_tests/generated.rs b/crates/ra_assists/src/doc_tests/generated.rs index b39e60870..e4fa9ee36 100644 --- a/crates/ra_assists/src/doc_tests/generated.rs +++ b/crates/ra_assists/src/doc_tests/generated.rs | |||
@@ -66,7 +66,7 @@ fn doctest_add_function() { | |||
66 | struct Baz; | 66 | struct Baz; |
67 | fn baz() -> Baz { Baz } | 67 | fn baz() -> Baz { Baz } |
68 | fn foo() { | 68 | fn foo() { |
69 | bar<|>("", baz()); | 69 | bar<|>("", baz()); |
70 | } | 70 | } |
71 | 71 | ||
72 | "#####, | 72 | "#####, |
@@ -74,7 +74,7 @@ fn foo() { | |||
74 | struct Baz; | 74 | struct Baz; |
75 | fn baz() -> Baz { Baz } | 75 | fn baz() -> Baz { Baz } |
76 | fn foo() { | 76 | fn foo() { |
77 | bar("", baz()); | 77 | bar("", baz()); |
78 | } | 78 | } |
79 | 79 | ||
80 | fn bar(arg: &str, baz: Baz) { | 80 | fn bar(arg: &str, baz: Baz) { |
diff --git a/crates/ra_assists/src/handlers/add_custom_impl.rs b/crates/ra_assists/src/handlers/add_custom_impl.rs index 15f9b216b..4ea26a550 100644 --- a/crates/ra_assists/src/handlers/add_custom_impl.rs +++ b/crates/ra_assists/src/handlers/add_custom_impl.rs | |||
@@ -2,7 +2,7 @@ use ra_syntax::{ | |||
2 | ast::{self, AstNode}, | 2 | ast::{self, AstNode}, |
3 | Direction, SmolStr, | 3 | Direction, SmolStr, |
4 | SyntaxKind::{IDENT, WHITESPACE}, | 4 | SyntaxKind::{IDENT, WHITESPACE}, |
5 | TextRange, TextUnit, | 5 | TextRange, TextSize, |
6 | }; | 6 | }; |
7 | use stdx::SepBy; | 7 | use stdx::SepBy; |
8 | 8 | ||
@@ -60,7 +60,6 @@ pub(crate) fn add_custom_impl(ctx: AssistCtx) -> Option<Assist> { | |||
60 | .collect::<Vec<SmolStr>>(); | 60 | .collect::<Vec<SmolStr>>(); |
61 | let has_more_derives = !new_attr_input.is_empty(); | 61 | let has_more_derives = !new_attr_input.is_empty(); |
62 | let new_attr_input = new_attr_input.iter().sep_by(", ").surround_with("(", ")").to_string(); | 62 | let new_attr_input = new_attr_input.iter().sep_by(", ").surround_with("(", ")").to_string(); |
63 | let new_attr_input_len = new_attr_input.len(); | ||
64 | 63 | ||
65 | let mut buf = String::new(); | 64 | let mut buf = String::new(); |
66 | buf.push_str("\n\nimpl "); | 65 | buf.push_str("\n\nimpl "); |
@@ -70,8 +69,9 @@ pub(crate) fn add_custom_impl(ctx: AssistCtx) -> Option<Assist> { | |||
70 | buf.push_str(" {\n"); | 69 | buf.push_str(" {\n"); |
71 | 70 | ||
72 | let cursor_delta = if has_more_derives { | 71 | let cursor_delta = if has_more_derives { |
72 | let delta = input.syntax().text_range().len() - TextSize::of(&new_attr_input); | ||
73 | edit.replace(input.syntax().text_range(), new_attr_input); | 73 | edit.replace(input.syntax().text_range(), new_attr_input); |
74 | input.syntax().text_range().len() - TextUnit::from_usize(new_attr_input_len) | 74 | delta |
75 | } else { | 75 | } else { |
76 | let attr_range = attr.syntax().text_range(); | 76 | let attr_range = attr.syntax().text_range(); |
77 | edit.delete(attr_range); | 77 | edit.delete(attr_range); |
@@ -81,13 +81,13 @@ pub(crate) fn add_custom_impl(ctx: AssistCtx) -> Option<Assist> { | |||
81 | .next_sibling_or_token() | 81 | .next_sibling_or_token() |
82 | .filter(|t| t.kind() == WHITESPACE) | 82 | .filter(|t| t.kind() == WHITESPACE) |
83 | .map(|t| t.text_range()) | 83 | .map(|t| t.text_range()) |
84 | .unwrap_or_else(|| TextRange::from_to(TextUnit::from(0), TextUnit::from(0))); | 84 | .unwrap_or_else(|| TextRange::new(TextSize::from(0), TextSize::from(0))); |
85 | edit.delete(line_break_range); | 85 | edit.delete(line_break_range); |
86 | 86 | ||
87 | attr_range.len() + line_break_range.len() | 87 | attr_range.len() + line_break_range.len() |
88 | }; | 88 | }; |
89 | 89 | ||
90 | edit.set_cursor(start_offset + TextUnit::of_str(&buf) - cursor_delta); | 90 | edit.set_cursor(start_offset + TextSize::of(&buf) - cursor_delta); |
91 | buf.push_str("\n}"); | 91 | buf.push_str("\n}"); |
92 | edit.insert(start_offset, buf); | 92 | edit.insert(start_offset, buf); |
93 | }) | 93 | }) |
diff --git a/crates/ra_assists/src/handlers/add_derive.rs b/crates/ra_assists/src/handlers/add_derive.rs index b0d1a0a80..6254eb7c4 100644 --- a/crates/ra_assists/src/handlers/add_derive.rs +++ b/crates/ra_assists/src/handlers/add_derive.rs | |||
@@ -1,7 +1,7 @@ | |||
1 | use ra_syntax::{ | 1 | use ra_syntax::{ |
2 | ast::{self, AstNode, AttrsOwner}, | 2 | ast::{self, AstNode, AttrsOwner}, |
3 | SyntaxKind::{COMMENT, WHITESPACE}, | 3 | SyntaxKind::{COMMENT, WHITESPACE}, |
4 | TextUnit, | 4 | TextSize, |
5 | }; | 5 | }; |
6 | 6 | ||
7 | use crate::{Assist, AssistCtx, AssistId}; | 7 | use crate::{Assist, AssistCtx, AssistId}; |
@@ -37,9 +37,9 @@ pub(crate) fn add_derive(ctx: AssistCtx) -> Option<Assist> { | |||
37 | let offset = match derive_attr { | 37 | let offset = match derive_attr { |
38 | None => { | 38 | None => { |
39 | edit.insert(node_start, "#[derive()]\n"); | 39 | edit.insert(node_start, "#[derive()]\n"); |
40 | node_start + TextUnit::of_str("#[derive(") | 40 | node_start + TextSize::of("#[derive(") |
41 | } | 41 | } |
42 | Some(tt) => tt.syntax().text_range().end() - TextUnit::of_char(')'), | 42 | Some(tt) => tt.syntax().text_range().end() - TextSize::of(')'), |
43 | }; | 43 | }; |
44 | edit.target(nominal.syntax().text_range()); | 44 | edit.target(nominal.syntax().text_range()); |
45 | edit.set_cursor(offset) | 45 | edit.set_cursor(offset) |
@@ -47,7 +47,7 @@ pub(crate) fn add_derive(ctx: AssistCtx) -> Option<Assist> { | |||
47 | } | 47 | } |
48 | 48 | ||
49 | // Insert `derive` after doc comments. | 49 | // Insert `derive` after doc comments. |
50 | fn derive_insertion_offset(nominal: &ast::NominalDef) -> Option<TextUnit> { | 50 | fn derive_insertion_offset(nominal: &ast::NominalDef) -> Option<TextSize> { |
51 | let non_ws_child = nominal | 51 | let non_ws_child = nominal |
52 | .syntax() | 52 | .syntax() |
53 | .children_with_tokens() | 53 | .children_with_tokens() |
diff --git a/crates/ra_assists/src/handlers/add_explicit_type.rs b/crates/ra_assists/src/handlers/add_explicit_type.rs index 6c56d93d8..bc313782b 100644 --- a/crates/ra_assists/src/handlers/add_explicit_type.rs +++ b/crates/ra_assists/src/handlers/add_explicit_type.rs | |||
@@ -37,8 +37,8 @@ pub(crate) fn add_explicit_type(ctx: AssistCtx) -> Option<Assist> { | |||
37 | let stmt_range = stmt.syntax().text_range(); | 37 | let stmt_range = stmt.syntax().text_range(); |
38 | let eq_range = stmt.eq_token()?.text_range(); | 38 | let eq_range = stmt.eq_token()?.text_range(); |
39 | // Assist should only be applicable if cursor is between 'let' and '=' | 39 | // Assist should only be applicable if cursor is between 'let' and '=' |
40 | let let_range = TextRange::from_to(stmt_range.start(), eq_range.start()); | 40 | let let_range = TextRange::new(stmt_range.start(), eq_range.start()); |
41 | let cursor_in_range = ctx.frange.range.is_subrange(&let_range); | 41 | let cursor_in_range = let_range.contains_range(ctx.frange.range); |
42 | if !cursor_in_range { | 42 | if !cursor_in_range { |
43 | return None; | 43 | return None; |
44 | } | 44 | } |
diff --git a/crates/ra_assists/src/handlers/add_from_impl_for_enum.rs b/crates/ra_assists/src/handlers/add_from_impl_for_enum.rs index 0621487e8..03806724a 100644 --- a/crates/ra_assists/src/handlers/add_from_impl_for_enum.rs +++ b/crates/ra_assists/src/handlers/add_from_impl_for_enum.rs | |||
@@ -1,6 +1,6 @@ | |||
1 | use ra_syntax::{ | 1 | use ra_syntax::{ |
2 | ast::{self, AstNode, NameOwner}, | 2 | ast::{self, AstNode, NameOwner}, |
3 | TextUnit, | 3 | TextSize, |
4 | }; | 4 | }; |
5 | use stdx::format_to; | 5 | use stdx::format_to; |
6 | 6 | ||
@@ -65,7 +65,7 @@ impl From<{0}> for {1} {{ | |||
65 | variant_name | 65 | variant_name |
66 | ); | 66 | ); |
67 | edit.insert(start_offset, buf); | 67 | edit.insert(start_offset, buf); |
68 | edit.set_cursor(start_offset + TextUnit::of_str("\n\n")); | 68 | edit.set_cursor(start_offset + TextSize::of("\n\n")); |
69 | }, | 69 | }, |
70 | ) | 70 | ) |
71 | } | 71 | } |
diff --git a/crates/ra_assists/src/handlers/add_function.rs b/crates/ra_assists/src/handlers/add_function.rs index ad4ab66ed..6c7456579 100644 --- a/crates/ra_assists/src/handlers/add_function.rs +++ b/crates/ra_assists/src/handlers/add_function.rs | |||
@@ -1,10 +1,10 @@ | |||
1 | use ra_syntax::{ | 1 | use ra_syntax::{ |
2 | ast::{self, AstNode}, | 2 | ast::{self, AstNode}, |
3 | SyntaxKind, SyntaxNode, TextUnit, | 3 | SyntaxKind, SyntaxNode, TextSize, |
4 | }; | 4 | }; |
5 | 5 | ||
6 | use crate::{Assist, AssistCtx, AssistId}; | 6 | use crate::{Assist, AssistCtx, AssistFile, AssistId}; |
7 | use ast::{edit::IndentLevel, ArgListOwner, CallExpr, Expr}; | 7 | use ast::{edit::IndentLevel, ArgListOwner, ModuleItemOwner}; |
8 | use hir::HirDisplay; | 8 | use hir::HirDisplay; |
9 | use rustc_hash::{FxHashMap, FxHashSet}; | 9 | use rustc_hash::{FxHashMap, FxHashSet}; |
10 | 10 | ||
@@ -16,7 +16,7 @@ use rustc_hash::{FxHashMap, FxHashSet}; | |||
16 | // struct Baz; | 16 | // struct Baz; |
17 | // fn baz() -> Baz { Baz } | 17 | // fn baz() -> Baz { Baz } |
18 | // fn foo() { | 18 | // fn foo() { |
19 | // bar<|>("", baz()); | 19 | // bar<|>("", baz()); |
20 | // } | 20 | // } |
21 | // | 21 | // |
22 | // ``` | 22 | // ``` |
@@ -25,7 +25,7 @@ use rustc_hash::{FxHashMap, FxHashSet}; | |||
25 | // struct Baz; | 25 | // struct Baz; |
26 | // fn baz() -> Baz { Baz } | 26 | // fn baz() -> Baz { Baz } |
27 | // fn foo() { | 27 | // fn foo() { |
28 | // bar("", baz()); | 28 | // bar("", baz()); |
29 | // } | 29 | // } |
30 | // | 30 | // |
31 | // fn bar(arg: &str, baz: Baz) { | 31 | // fn bar(arg: &str, baz: Baz) { |
@@ -38,21 +38,30 @@ pub(crate) fn add_function(ctx: AssistCtx) -> Option<Assist> { | |||
38 | let call = path_expr.syntax().parent().and_then(ast::CallExpr::cast)?; | 38 | let call = path_expr.syntax().parent().and_then(ast::CallExpr::cast)?; |
39 | let path = path_expr.path()?; | 39 | let path = path_expr.path()?; |
40 | 40 | ||
41 | if path.qualifier().is_some() { | ||
42 | return None; | ||
43 | } | ||
44 | |||
45 | if ctx.sema.resolve_path(&path).is_some() { | 41 | if ctx.sema.resolve_path(&path).is_some() { |
46 | // The function call already resolves, no need to add a function | 42 | // The function call already resolves, no need to add a function |
47 | return None; | 43 | return None; |
48 | } | 44 | } |
49 | 45 | ||
50 | let function_builder = FunctionBuilder::from_call(&ctx, &call)?; | 46 | let target_module = if let Some(qualifier) = path.qualifier() { |
47 | if let Some(hir::PathResolution::Def(hir::ModuleDef::Module(module))) = | ||
48 | ctx.sema.resolve_path(&qualifier) | ||
49 | { | ||
50 | Some(module.definition_source(ctx.sema.db)) | ||
51 | } else { | ||
52 | return None; | ||
53 | } | ||
54 | } else { | ||
55 | None | ||
56 | }; | ||
57 | |||
58 | let function_builder = FunctionBuilder::from_call(&ctx, &call, &path, target_module)?; | ||
51 | 59 | ||
52 | ctx.add_assist(AssistId("add_function"), "Add function", |edit| { | 60 | ctx.add_assist(AssistId("add_function"), "Add function", |edit| { |
53 | edit.target(call.syntax().text_range()); | 61 | edit.target(call.syntax().text_range()); |
54 | 62 | ||
55 | if let Some(function_template) = function_builder.render() { | 63 | if let Some(function_template) = function_builder.render() { |
64 | edit.set_file(function_template.file); | ||
56 | edit.set_cursor(function_template.cursor_offset); | 65 | edit.set_cursor(function_template.cursor_offset); |
57 | edit.insert(function_template.insert_offset, function_template.fn_def.to_string()); | 66 | edit.insert(function_template.insert_offset, function_template.fn_def.to_string()); |
58 | } | 67 | } |
@@ -60,32 +69,70 @@ pub(crate) fn add_function(ctx: AssistCtx) -> Option<Assist> { | |||
60 | } | 69 | } |
61 | 70 | ||
62 | struct FunctionTemplate { | 71 | struct FunctionTemplate { |
63 | insert_offset: TextUnit, | 72 | insert_offset: TextSize, |
64 | cursor_offset: TextUnit, | 73 | cursor_offset: TextSize, |
65 | fn_def: ast::SourceFile, | 74 | fn_def: ast::SourceFile, |
75 | file: AssistFile, | ||
66 | } | 76 | } |
67 | 77 | ||
68 | struct FunctionBuilder { | 78 | struct FunctionBuilder { |
69 | append_fn_at: SyntaxNode, | 79 | target: GeneratedFunctionTarget, |
70 | fn_name: ast::Name, | 80 | fn_name: ast::Name, |
71 | type_params: Option<ast::TypeParamList>, | 81 | type_params: Option<ast::TypeParamList>, |
72 | params: ast::ParamList, | 82 | params: ast::ParamList, |
83 | file: AssistFile, | ||
84 | needs_pub: bool, | ||
73 | } | 85 | } |
74 | 86 | ||
75 | impl FunctionBuilder { | 87 | impl FunctionBuilder { |
76 | fn from_call(ctx: &AssistCtx, call: &ast::CallExpr) -> Option<Self> { | 88 | /// Prepares a generated function that matches `call` in `generate_in` |
77 | let append_fn_at = next_space_for_fn(&call)?; | 89 | /// (or as close to `call` as possible, if `generate_in` is `None`) |
78 | let fn_name = fn_name(&call)?; | 90 | fn from_call( |
91 | ctx: &AssistCtx, | ||
92 | call: &ast::CallExpr, | ||
93 | path: &ast::Path, | ||
94 | target_module: Option<hir::InFile<hir::ModuleSource>>, | ||
95 | ) -> Option<Self> { | ||
96 | let needs_pub = target_module.is_some(); | ||
97 | let mut file = AssistFile::default(); | ||
98 | let target = if let Some(target_module) = target_module { | ||
99 | let (in_file, target) = next_space_for_fn_in_module(ctx.sema.db, target_module)?; | ||
100 | file = in_file; | ||
101 | target | ||
102 | } else { | ||
103 | next_space_for_fn_after_call_site(&call)? | ||
104 | }; | ||
105 | let fn_name = fn_name(&path)?; | ||
79 | let (type_params, params) = fn_args(ctx, &call)?; | 106 | let (type_params, params) = fn_args(ctx, &call)?; |
80 | Some(Self { append_fn_at, fn_name, type_params, params }) | 107 | Some(Self { target, fn_name, type_params, params, file, needs_pub }) |
81 | } | 108 | } |
109 | |||
82 | fn render(self) -> Option<FunctionTemplate> { | 110 | fn render(self) -> Option<FunctionTemplate> { |
83 | let placeholder_expr = ast::make::expr_todo(); | 111 | let placeholder_expr = ast::make::expr_todo(); |
84 | let fn_body = ast::make::block_expr(vec![], Some(placeholder_expr)); | 112 | let fn_body = ast::make::block_expr(vec![], Some(placeholder_expr)); |
85 | let fn_def = ast::make::fn_def(self.fn_name, self.type_params, self.params, fn_body); | 113 | let mut fn_def = ast::make::fn_def(self.fn_name, self.type_params, self.params, fn_body); |
86 | let fn_def = ast::make::add_newlines(2, fn_def); | 114 | if self.needs_pub { |
87 | let fn_def = IndentLevel::from_node(&self.append_fn_at).increase_indent(fn_def); | 115 | fn_def = ast::make::add_pub_crate_modifier(fn_def); |
88 | let insert_offset = self.append_fn_at.text_range().end(); | 116 | } |
117 | |||
118 | let (fn_def, insert_offset) = match self.target { | ||
119 | GeneratedFunctionTarget::BehindItem(it) => { | ||
120 | let with_leading_blank_line = ast::make::add_leading_newlines(2, fn_def); | ||
121 | let indented = IndentLevel::from_node(&it).increase_indent(with_leading_blank_line); | ||
122 | (indented, it.text_range().end()) | ||
123 | } | ||
124 | GeneratedFunctionTarget::InEmptyItemList(it) => { | ||
125 | let indent_once = IndentLevel(1); | ||
126 | let indent = IndentLevel::from_node(it.syntax()); | ||
127 | |||
128 | let fn_def = ast::make::add_leading_newlines(1, fn_def); | ||
129 | let fn_def = indent_once.increase_indent(fn_def); | ||
130 | let fn_def = ast::make::add_trailing_newlines(1, fn_def); | ||
131 | let fn_def = indent.increase_indent(fn_def); | ||
132 | (fn_def, it.syntax().text_range().start() + TextSize::of('{')) | ||
133 | } | ||
134 | }; | ||
135 | |||
89 | let cursor_offset_from_fn_start = fn_def | 136 | let cursor_offset_from_fn_start = fn_def |
90 | .syntax() | 137 | .syntax() |
91 | .descendants() | 138 | .descendants() |
@@ -94,19 +141,24 @@ impl FunctionBuilder { | |||
94 | .text_range() | 141 | .text_range() |
95 | .start(); | 142 | .start(); |
96 | let cursor_offset = insert_offset + cursor_offset_from_fn_start; | 143 | let cursor_offset = insert_offset + cursor_offset_from_fn_start; |
97 | Some(FunctionTemplate { insert_offset, cursor_offset, fn_def }) | 144 | Some(FunctionTemplate { insert_offset, cursor_offset, fn_def, file: self.file }) |
98 | } | 145 | } |
99 | } | 146 | } |
100 | 147 | ||
101 | fn fn_name(call: &CallExpr) -> Option<ast::Name> { | 148 | enum GeneratedFunctionTarget { |
102 | let name = call.expr()?.syntax().to_string(); | 149 | BehindItem(SyntaxNode), |
150 | InEmptyItemList(ast::ItemList), | ||
151 | } | ||
152 | |||
153 | fn fn_name(call: &ast::Path) -> Option<ast::Name> { | ||
154 | let name = call.segment()?.syntax().to_string(); | ||
103 | Some(ast::make::name(&name)) | 155 | Some(ast::make::name(&name)) |
104 | } | 156 | } |
105 | 157 | ||
106 | /// Computes the type variables and arguments required for the generated function | 158 | /// Computes the type variables and arguments required for the generated function |
107 | fn fn_args( | 159 | fn fn_args( |
108 | ctx: &AssistCtx, | 160 | ctx: &AssistCtx, |
109 | call: &CallExpr, | 161 | call: &ast::CallExpr, |
110 | ) -> Option<(Option<ast::TypeParamList>, ast::ParamList)> { | 162 | ) -> Option<(Option<ast::TypeParamList>, ast::ParamList)> { |
111 | let mut arg_names = Vec::new(); | 163 | let mut arg_names = Vec::new(); |
112 | let mut arg_types = Vec::new(); | 164 | let mut arg_types = Vec::new(); |
@@ -158,9 +210,9 @@ fn deduplicate_arg_names(arg_names: &mut Vec<String>) { | |||
158 | } | 210 | } |
159 | } | 211 | } |
160 | 212 | ||
161 | fn fn_arg_name(fn_arg: &Expr) -> Option<String> { | 213 | fn fn_arg_name(fn_arg: &ast::Expr) -> Option<String> { |
162 | match fn_arg { | 214 | match fn_arg { |
163 | Expr::CastExpr(cast_expr) => fn_arg_name(&cast_expr.expr()?), | 215 | ast::Expr::CastExpr(cast_expr) => fn_arg_name(&cast_expr.expr()?), |
164 | _ => Some( | 216 | _ => Some( |
165 | fn_arg | 217 | fn_arg |
166 | .syntax() | 218 | .syntax() |
@@ -172,7 +224,7 @@ fn fn_arg_name(fn_arg: &Expr) -> Option<String> { | |||
172 | } | 224 | } |
173 | } | 225 | } |
174 | 226 | ||
175 | fn fn_arg_type(ctx: &AssistCtx, fn_arg: &Expr) -> Option<String> { | 227 | fn fn_arg_type(ctx: &AssistCtx, fn_arg: &ast::Expr) -> Option<String> { |
176 | let ty = ctx.sema.type_of_expr(fn_arg)?; | 228 | let ty = ctx.sema.type_of_expr(fn_arg)?; |
177 | if ty.is_unknown() { | 229 | if ty.is_unknown() { |
178 | return None; | 230 | return None; |
@@ -184,7 +236,7 @@ fn fn_arg_type(ctx: &AssistCtx, fn_arg: &Expr) -> Option<String> { | |||
184 | /// directly after the current block | 236 | /// directly after the current block |
185 | /// We want to write the generated function directly after | 237 | /// We want to write the generated function directly after |
186 | /// fns, impls or macro calls, but inside mods | 238 | /// fns, impls or macro calls, but inside mods |
187 | fn next_space_for_fn(expr: &CallExpr) -> Option<SyntaxNode> { | 239 | fn next_space_for_fn_after_call_site(expr: &ast::CallExpr) -> Option<GeneratedFunctionTarget> { |
188 | let mut ancestors = expr.syntax().ancestors().peekable(); | 240 | let mut ancestors = expr.syntax().ancestors().peekable(); |
189 | let mut last_ancestor: Option<SyntaxNode> = None; | 241 | let mut last_ancestor: Option<SyntaxNode> = None; |
190 | while let Some(next_ancestor) = ancestors.next() { | 242 | while let Some(next_ancestor) = ancestors.next() { |
@@ -201,7 +253,32 @@ fn next_space_for_fn(expr: &CallExpr) -> Option<SyntaxNode> { | |||
201 | } | 253 | } |
202 | last_ancestor = Some(next_ancestor); | 254 | last_ancestor = Some(next_ancestor); |
203 | } | 255 | } |
204 | last_ancestor | 256 | last_ancestor.map(GeneratedFunctionTarget::BehindItem) |
257 | } | ||
258 | |||
259 | fn next_space_for_fn_in_module( | ||
260 | db: &dyn hir::db::AstDatabase, | ||
261 | module: hir::InFile<hir::ModuleSource>, | ||
262 | ) -> Option<(AssistFile, GeneratedFunctionTarget)> { | ||
263 | let file = module.file_id.original_file(db); | ||
264 | let assist_file = AssistFile::TargetFile(file); | ||
265 | let assist_item = match module.value { | ||
266 | hir::ModuleSource::SourceFile(it) => { | ||
267 | if let Some(last_item) = it.items().last() { | ||
268 | GeneratedFunctionTarget::BehindItem(last_item.syntax().clone()) | ||
269 | } else { | ||
270 | GeneratedFunctionTarget::BehindItem(it.syntax().clone()) | ||
271 | } | ||
272 | } | ||
273 | hir::ModuleSource::Module(it) => { | ||
274 | if let Some(last_item) = it.item_list().and_then(|it| it.items().last()) { | ||
275 | GeneratedFunctionTarget::BehindItem(last_item.syntax().clone()) | ||
276 | } else { | ||
277 | GeneratedFunctionTarget::InEmptyItemList(it.item_list()?) | ||
278 | } | ||
279 | } | ||
280 | }; | ||
281 | Some((assist_file, assist_item)) | ||
205 | } | 282 | } |
206 | 283 | ||
207 | #[cfg(test)] | 284 | #[cfg(test)] |
@@ -714,6 +791,111 @@ fn bar(baz_1: Baz, baz_2: Baz, arg_1: &str, arg_2: &str) { | |||
714 | } | 791 | } |
715 | 792 | ||
716 | #[test] | 793 | #[test] |
794 | fn add_function_in_module() { | ||
795 | check_assist( | ||
796 | add_function, | ||
797 | r" | ||
798 | mod bar {} | ||
799 | |||
800 | fn foo() { | ||
801 | bar::my_fn<|>() | ||
802 | } | ||
803 | ", | ||
804 | r" | ||
805 | mod bar { | ||
806 | pub(crate) fn my_fn() { | ||
807 | <|>todo!() | ||
808 | } | ||
809 | } | ||
810 | |||
811 | fn foo() { | ||
812 | bar::my_fn() | ||
813 | } | ||
814 | ", | ||
815 | ) | ||
816 | } | ||
817 | |||
818 | #[test] | ||
819 | fn add_function_in_module_containing_other_items() { | ||
820 | check_assist( | ||
821 | add_function, | ||
822 | r" | ||
823 | mod bar { | ||
824 | fn something_else() {} | ||
825 | } | ||
826 | |||
827 | fn foo() { | ||
828 | bar::my_fn<|>() | ||
829 | } | ||
830 | ", | ||
831 | r" | ||
832 | mod bar { | ||
833 | fn something_else() {} | ||
834 | |||
835 | pub(crate) fn my_fn() { | ||
836 | <|>todo!() | ||
837 | } | ||
838 | } | ||
839 | |||
840 | fn foo() { | ||
841 | bar::my_fn() | ||
842 | } | ||
843 | ", | ||
844 | ) | ||
845 | } | ||
846 | |||
847 | #[test] | ||
848 | fn add_function_in_nested_module() { | ||
849 | check_assist( | ||
850 | add_function, | ||
851 | r" | ||
852 | mod bar { | ||
853 | mod baz {} | ||
854 | } | ||
855 | |||
856 | fn foo() { | ||
857 | bar::baz::my_fn<|>() | ||
858 | } | ||
859 | ", | ||
860 | r" | ||
861 | mod bar { | ||
862 | mod baz { | ||
863 | pub(crate) fn my_fn() { | ||
864 | <|>todo!() | ||
865 | } | ||
866 | } | ||
867 | } | ||
868 | |||
869 | fn foo() { | ||
870 | bar::baz::my_fn() | ||
871 | } | ||
872 | ", | ||
873 | ) | ||
874 | } | ||
875 | |||
876 | #[test] | ||
877 | fn add_function_in_another_file() { | ||
878 | check_assist( | ||
879 | add_function, | ||
880 | r" | ||
881 | //- /main.rs | ||
882 | mod foo; | ||
883 | |||
884 | fn main() { | ||
885 | foo::bar<|>() | ||
886 | } | ||
887 | //- /foo.rs | ||
888 | ", | ||
889 | r" | ||
890 | |||
891 | |||
892 | pub(crate) fn bar() { | ||
893 | <|>todo!() | ||
894 | }", | ||
895 | ) | ||
896 | } | ||
897 | |||
898 | #[test] | ||
717 | fn add_function_not_applicable_if_function_already_exists() { | 899 | fn add_function_not_applicable_if_function_already_exists() { |
718 | check_assist_not_applicable( | 900 | check_assist_not_applicable( |
719 | add_function, | 901 | add_function, |
diff --git a/crates/ra_assists/src/handlers/add_impl.rs b/crates/ra_assists/src/handlers/add_impl.rs index 6622eadb2..d26f8b93d 100644 --- a/crates/ra_assists/src/handlers/add_impl.rs +++ b/crates/ra_assists/src/handlers/add_impl.rs | |||
@@ -1,6 +1,6 @@ | |||
1 | use ra_syntax::{ | 1 | use ra_syntax::{ |
2 | ast::{self, AstNode, NameOwner, TypeParamsOwner}, | 2 | ast::{self, AstNode, NameOwner, TypeParamsOwner}, |
3 | TextUnit, | 3 | TextSize, |
4 | }; | 4 | }; |
5 | use stdx::{format_to, SepBy}; | 5 | use stdx::{format_to, SepBy}; |
6 | 6 | ||
@@ -51,7 +51,7 @@ pub(crate) fn add_impl(ctx: AssistCtx) -> Option<Assist> { | |||
51 | format_to!(buf, "<{}>", generic_params) | 51 | format_to!(buf, "<{}>", generic_params) |
52 | } | 52 | } |
53 | buf.push_str(" {\n"); | 53 | buf.push_str(" {\n"); |
54 | edit.set_cursor(start_offset + TextUnit::of_str(&buf)); | 54 | edit.set_cursor(start_offset + TextSize::of(&buf)); |
55 | buf.push_str("\n}"); | 55 | buf.push_str("\n}"); |
56 | edit.insert(start_offset, buf); | 56 | edit.insert(start_offset, buf); |
57 | }) | 57 | }) |
diff --git a/crates/ra_assists/src/handlers/add_new.rs b/crates/ra_assists/src/handlers/add_new.rs index 240b19fa3..0f9174a29 100644 --- a/crates/ra_assists/src/handlers/add_new.rs +++ b/crates/ra_assists/src/handlers/add_new.rs | |||
@@ -3,7 +3,7 @@ use ra_syntax::{ | |||
3 | ast::{ | 3 | ast::{ |
4 | self, AstNode, NameOwner, StructKind, TypeAscriptionOwner, TypeParamsOwner, VisibilityOwner, | 4 | self, AstNode, NameOwner, StructKind, TypeAscriptionOwner, TypeParamsOwner, VisibilityOwner, |
5 | }, | 5 | }, |
6 | TextUnit, T, | 6 | TextSize, T, |
7 | }; | 7 | }; |
8 | use stdx::{format_to, SepBy}; | 8 | use stdx::{format_to, SepBy}; |
9 | 9 | ||
@@ -77,16 +77,16 @@ pub(crate) fn add_new(ctx: AssistCtx) -> Option<Assist> { | |||
77 | .text_range() | 77 | .text_range() |
78 | .end(); | 78 | .end(); |
79 | 79 | ||
80 | Some((start, TextUnit::from_usize(1))) | 80 | Some((start, TextSize::of("\n"))) |
81 | }) | 81 | }) |
82 | .unwrap_or_else(|| { | 82 | .unwrap_or_else(|| { |
83 | buf = generate_impl_text(&strukt, &buf); | 83 | buf = generate_impl_text(&strukt, &buf); |
84 | let start = strukt.syntax().text_range().end(); | 84 | let start = strukt.syntax().text_range().end(); |
85 | 85 | ||
86 | (start, TextUnit::from_usize(3)) | 86 | (start, TextSize::of("\n}\n")) |
87 | }); | 87 | }); |
88 | 88 | ||
89 | edit.set_cursor(start_offset + TextUnit::of_str(&buf) - end_offset); | 89 | edit.set_cursor(start_offset + TextSize::of(&buf) - end_offset); |
90 | edit.insert(start_offset, buf); | 90 | edit.insert(start_offset, buf); |
91 | }) | 91 | }) |
92 | } | 92 | } |
diff --git a/crates/ra_assists/src/handlers/apply_demorgan.rs b/crates/ra_assists/src/handlers/apply_demorgan.rs index 239807e24..260b9e073 100644 --- a/crates/ra_assists/src/handlers/apply_demorgan.rs +++ b/crates/ra_assists/src/handlers/apply_demorgan.rs | |||
@@ -26,7 +26,7 @@ pub(crate) fn apply_demorgan(ctx: AssistCtx) -> Option<Assist> { | |||
26 | let op = expr.op_kind()?; | 26 | let op = expr.op_kind()?; |
27 | let op_range = expr.op_token()?.text_range(); | 27 | let op_range = expr.op_token()?.text_range(); |
28 | let opposite_op = opposite_logic_op(op)?; | 28 | let opposite_op = opposite_logic_op(op)?; |
29 | let cursor_in_range = ctx.frange.range.is_subrange(&op_range); | 29 | let cursor_in_range = op_range.contains_range(ctx.frange.range); |
30 | if !cursor_in_range { | 30 | if !cursor_in_range { |
31 | return None; | 31 | return None; |
32 | } | 32 | } |
diff --git a/crates/ra_assists/src/handlers/change_visibility.rs b/crates/ra_assists/src/handlers/change_visibility.rs index cd6d1ee6c..44f6a1dae 100644 --- a/crates/ra_assists/src/handlers/change_visibility.rs +++ b/crates/ra_assists/src/handlers/change_visibility.rs | |||
@@ -5,7 +5,7 @@ use ra_syntax::{ | |||
5 | ATTR, COMMENT, CONST_DEF, ENUM_DEF, FN_DEF, MODULE, STRUCT_DEF, TRAIT_DEF, VISIBILITY, | 5 | ATTR, COMMENT, CONST_DEF, ENUM_DEF, FN_DEF, MODULE, STRUCT_DEF, TRAIT_DEF, VISIBILITY, |
6 | WHITESPACE, | 6 | WHITESPACE, |
7 | }, | 7 | }, |
8 | SyntaxNode, TextUnit, T, | 8 | SyntaxNode, TextSize, T, |
9 | }; | 9 | }; |
10 | 10 | ||
11 | use crate::{Assist, AssistCtx, AssistId}; | 11 | use crate::{Assist, AssistCtx, AssistId}; |
@@ -67,7 +67,7 @@ fn add_vis(ctx: AssistCtx) -> Option<Assist> { | |||
67 | }) | 67 | }) |
68 | } | 68 | } |
69 | 69 | ||
70 | fn vis_offset(node: &SyntaxNode) -> TextUnit { | 70 | fn vis_offset(node: &SyntaxNode) -> TextSize { |
71 | node.children_with_tokens() | 71 | node.children_with_tokens() |
72 | .skip_while(|it| match it.kind() { | 72 | .skip_while(|it| match it.kind() { |
73 | WHITESPACE | COMMENT | ATTR => true, | 73 | WHITESPACE | COMMENT | ATTR => true, |
diff --git a/crates/ra_assists/src/handlers/flip_binexpr.rs b/crates/ra_assists/src/handlers/flip_binexpr.rs index bfcc09e90..8030efb35 100644 --- a/crates/ra_assists/src/handlers/flip_binexpr.rs +++ b/crates/ra_assists/src/handlers/flip_binexpr.rs | |||
@@ -23,7 +23,7 @@ pub(crate) fn flip_binexpr(ctx: AssistCtx) -> Option<Assist> { | |||
23 | let rhs = expr.rhs()?.syntax().clone(); | 23 | let rhs = expr.rhs()?.syntax().clone(); |
24 | let op_range = expr.op_token()?.text_range(); | 24 | let op_range = expr.op_token()?.text_range(); |
25 | // The assist should be applied only if the cursor is on the operator | 25 | // The assist should be applied only if the cursor is on the operator |
26 | let cursor_in_range = ctx.frange.range.is_subrange(&op_range); | 26 | let cursor_in_range = op_range.contains_range(ctx.frange.range); |
27 | if !cursor_in_range { | 27 | if !cursor_in_range { |
28 | return None; | 28 | return None; |
29 | } | 29 | } |
diff --git a/crates/ra_assists/src/handlers/inline_local_variable.rs b/crates/ra_assists/src/handlers/inline_local_variable.rs index c4fb425b0..f5702f6e0 100644 --- a/crates/ra_assists/src/handlers/inline_local_variable.rs +++ b/crates/ra_assists/src/handlers/inline_local_variable.rs | |||
@@ -52,7 +52,7 @@ pub(crate) fn inline_local_variable(ctx: AssistCtx) -> Option<Assist> { | |||
52 | .next_sibling_or_token() | 52 | .next_sibling_or_token() |
53 | .and_then(|it| ast::Whitespace::cast(it.as_token()?.clone())) | 53 | .and_then(|it| ast::Whitespace::cast(it.as_token()?.clone())) |
54 | { | 54 | { |
55 | TextRange::from_to( | 55 | TextRange::new( |
56 | let_stmt.syntax().text_range().start(), | 56 | let_stmt.syntax().text_range().start(), |
57 | whitespace.syntax().text_range().end(), | 57 | whitespace.syntax().text_range().end(), |
58 | ) | 58 | ) |
diff --git a/crates/ra_assists/src/handlers/introduce_variable.rs b/crates/ra_assists/src/handlers/introduce_variable.rs index 8c09e6bcd..eda9ac296 100644 --- a/crates/ra_assists/src/handlers/introduce_variable.rs +++ b/crates/ra_assists/src/handlers/introduce_variable.rs | |||
@@ -4,7 +4,7 @@ use ra_syntax::{ | |||
4 | BLOCK_EXPR, BREAK_EXPR, COMMENT, LAMBDA_EXPR, LOOP_EXPR, MATCH_ARM, PATH_EXPR, RETURN_EXPR, | 4 | BLOCK_EXPR, BREAK_EXPR, COMMENT, LAMBDA_EXPR, LOOP_EXPR, MATCH_ARM, PATH_EXPR, RETURN_EXPR, |
5 | WHITESPACE, | 5 | WHITESPACE, |
6 | }, | 6 | }, |
7 | SyntaxNode, TextUnit, | 7 | SyntaxNode, TextSize, |
8 | }; | 8 | }; |
9 | use stdx::format_to; | 9 | use stdx::format_to; |
10 | use test_utils::tested_by; | 10 | use test_utils::tested_by; |
@@ -47,10 +47,10 @@ pub(crate) fn introduce_variable(ctx: AssistCtx) -> Option<Assist> { | |||
47 | 47 | ||
48 | let cursor_offset = if wrap_in_block { | 48 | let cursor_offset = if wrap_in_block { |
49 | buf.push_str("{ let var_name = "); | 49 | buf.push_str("{ let var_name = "); |
50 | TextUnit::of_str("{ let ") | 50 | TextSize::of("{ let ") |
51 | } else { | 51 | } else { |
52 | buf.push_str("let var_name = "); | 52 | buf.push_str("let var_name = "); |
53 | TextUnit::of_str("let ") | 53 | TextSize::of("let ") |
54 | }; | 54 | }; |
55 | format_to!(buf, "{}", expr.syntax()); | 55 | format_to!(buf, "{}", expr.syntax()); |
56 | let full_stmt = ast::ExprStmt::cast(anchor_stmt.clone()); | 56 | let full_stmt = ast::ExprStmt::cast(anchor_stmt.clone()); |
diff --git a/crates/ra_assists/src/handlers/invert_if.rs b/crates/ra_assists/src/handlers/invert_if.rs index 4c5716868..682e08512 100644 --- a/crates/ra_assists/src/handlers/invert_if.rs +++ b/crates/ra_assists/src/handlers/invert_if.rs | |||
@@ -28,7 +28,7 @@ pub(crate) fn invert_if(ctx: AssistCtx) -> Option<Assist> { | |||
28 | let if_keyword = ctx.find_token_at_offset(T![if])?; | 28 | let if_keyword = ctx.find_token_at_offset(T![if])?; |
29 | let expr = ast::IfExpr::cast(if_keyword.parent())?; | 29 | let expr = ast::IfExpr::cast(if_keyword.parent())?; |
30 | let if_range = if_keyword.text_range(); | 30 | let if_range = if_keyword.text_range(); |
31 | let cursor_in_range = ctx.frange.range.is_subrange(&if_range); | 31 | let cursor_in_range = if_range.contains_range(ctx.frange.range); |
32 | if !cursor_in_range { | 32 | if !cursor_in_range { |
33 | return None; | 33 | return None; |
34 | } | 34 | } |
diff --git a/crates/ra_assists/src/handlers/merge_match_arms.rs b/crates/ra_assists/src/handlers/merge_match_arms.rs index eb967ab92..5a77d3dbc 100644 --- a/crates/ra_assists/src/handlers/merge_match_arms.rs +++ b/crates/ra_assists/src/handlers/merge_match_arms.rs | |||
@@ -3,7 +3,7 @@ use std::iter::successors; | |||
3 | use ra_syntax::{ | 3 | use ra_syntax::{ |
4 | algo::neighbor, | 4 | algo::neighbor, |
5 | ast::{self, AstNode}, | 5 | ast::{self, AstNode}, |
6 | Direction, TextUnit, | 6 | Direction, TextSize, |
7 | }; | 7 | }; |
8 | 8 | ||
9 | use crate::{Assist, AssistCtx, AssistId, TextRange}; | 9 | use crate::{Assist, AssistCtx, AssistId, TextRange}; |
@@ -42,8 +42,8 @@ pub(crate) fn merge_match_arms(ctx: AssistCtx) -> Option<Assist> { | |||
42 | let current_text_range = current_arm.syntax().text_range(); | 42 | let current_text_range = current_arm.syntax().text_range(); |
43 | 43 | ||
44 | enum CursorPos { | 44 | enum CursorPos { |
45 | InExpr(TextUnit), | 45 | InExpr(TextSize), |
46 | InPat(TextUnit), | 46 | InPat(TextSize), |
47 | } | 47 | } |
48 | let cursor_pos = ctx.frange.range.start(); | 48 | let cursor_pos = ctx.frange.range.start(); |
49 | let cursor_pos = if current_expr.syntax().text_range().contains(cursor_pos) { | 49 | let cursor_pos = if current_expr.syntax().text_range().contains(cursor_pos) { |
@@ -89,10 +89,10 @@ pub(crate) fn merge_match_arms(ctx: AssistCtx) -> Option<Assist> { | |||
89 | 89 | ||
90 | edit.target(current_text_range); | 90 | edit.target(current_text_range); |
91 | edit.set_cursor(match cursor_pos { | 91 | edit.set_cursor(match cursor_pos { |
92 | CursorPos::InExpr(back_offset) => start + TextUnit::from_usize(arm.len()) - back_offset, | 92 | CursorPos::InExpr(back_offset) => start + TextSize::of(&arm) - back_offset, |
93 | CursorPos::InPat(offset) => offset, | 93 | CursorPos::InPat(offset) => offset, |
94 | }); | 94 | }); |
95 | edit.replace(TextRange::from_to(start, end), arm); | 95 | edit.replace(TextRange::new(start, end), arm); |
96 | }) | 96 | }) |
97 | } | 97 | } |
98 | 98 | ||
diff --git a/crates/ra_assists/src/handlers/move_guard.rs b/crates/ra_assists/src/handlers/move_guard.rs index 1cc498638..d5ccdd91c 100644 --- a/crates/ra_assists/src/handlers/move_guard.rs +++ b/crates/ra_assists/src/handlers/move_guard.rs | |||
@@ -1,7 +1,7 @@ | |||
1 | use ra_syntax::{ | 1 | use ra_syntax::{ |
2 | ast, | 2 | ast, |
3 | ast::{AstNode, AstToken, IfExpr, MatchArm}, | 3 | ast::{AstNode, AstToken, IfExpr, MatchArm}, |
4 | TextUnit, | 4 | TextSize, |
5 | }; | 5 | }; |
6 | 6 | ||
7 | use crate::{Assist, AssistCtx, AssistId}; | 7 | use crate::{Assist, AssistCtx, AssistId}; |
@@ -49,16 +49,16 @@ pub(crate) fn move_guard_to_arm_body(ctx: AssistCtx) -> Option<Assist> { | |||
49 | edit.delete(ele); | 49 | edit.delete(ele); |
50 | ele.len() | 50 | ele.len() |
51 | } else { | 51 | } else { |
52 | TextUnit::from(0) | 52 | TextSize::from(0) |
53 | } | 53 | } |
54 | } | 54 | } |
55 | _ => TextUnit::from(0), | 55 | _ => TextSize::from(0), |
56 | }; | 56 | }; |
57 | 57 | ||
58 | edit.delete(guard.syntax().text_range()); | 58 | edit.delete(guard.syntax().text_range()); |
59 | edit.replace_node_and_indent(arm_expr.syntax(), buf); | 59 | edit.replace_node_and_indent(arm_expr.syntax(), buf); |
60 | edit.set_cursor( | 60 | edit.set_cursor( |
61 | arm_expr.syntax().text_range().start() + TextUnit::from(3) - offseting_amount, | 61 | arm_expr.syntax().text_range().start() + TextSize::from(3) - offseting_amount, |
62 | ); | 62 | ); |
63 | }) | 63 | }) |
64 | } | 64 | } |
@@ -123,7 +123,7 @@ pub(crate) fn move_arm_cond_to_match_guard(ctx: AssistCtx) -> Option<Assist> { | |||
123 | } | 123 | } |
124 | 124 | ||
125 | edit.insert(match_pat.syntax().text_range().end(), buf); | 125 | edit.insert(match_pat.syntax().text_range().end(), buf); |
126 | edit.set_cursor(match_pat.syntax().text_range().end() + TextUnit::from(1)); | 126 | edit.set_cursor(match_pat.syntax().text_range().end() + TextSize::from(1)); |
127 | }, | 127 | }, |
128 | ) | 128 | ) |
129 | } | 129 | } |
diff --git a/crates/ra_assists/src/handlers/raw_string.rs b/crates/ra_assists/src/handlers/raw_string.rs index 7e4b83f13..567400b9c 100644 --- a/crates/ra_assists/src/handlers/raw_string.rs +++ b/crates/ra_assists/src/handlers/raw_string.rs | |||
@@ -2,7 +2,7 @@ use ra_syntax::{ | |||
2 | ast::{self, HasStringValue}, | 2 | ast::{self, HasStringValue}, |
3 | AstToken, | 3 | AstToken, |
4 | SyntaxKind::{RAW_STRING, STRING}, | 4 | SyntaxKind::{RAW_STRING, STRING}, |
5 | TextUnit, | 5 | TextSize, |
6 | }; | 6 | }; |
7 | 7 | ||
8 | use crate::{Assist, AssistCtx, AssistId}; | 8 | use crate::{Assist, AssistCtx, AssistId}; |
@@ -81,7 +81,7 @@ pub(crate) fn add_hash(ctx: AssistCtx) -> Option<Assist> { | |||
81 | let token = ctx.find_token_at_offset(RAW_STRING)?; | 81 | let token = ctx.find_token_at_offset(RAW_STRING)?; |
82 | ctx.add_assist(AssistId("add_hash"), "Add # to raw string", |edit| { | 82 | ctx.add_assist(AssistId("add_hash"), "Add # to raw string", |edit| { |
83 | edit.target(token.text_range()); | 83 | edit.target(token.text_range()); |
84 | edit.insert(token.text_range().start() + TextUnit::of_char('r'), "#"); | 84 | edit.insert(token.text_range().start() + TextSize::of('r'), "#"); |
85 | edit.insert(token.text_range().end(), "#"); | 85 | edit.insert(token.text_range().end(), "#"); |
86 | }) | 86 | }) |
87 | } | 87 | } |
diff --git a/crates/ra_assists/src/handlers/remove_dbg.rs b/crates/ra_assists/src/handlers/remove_dbg.rs index 5085649b4..4e5eb4350 100644 --- a/crates/ra_assists/src/handlers/remove_dbg.rs +++ b/crates/ra_assists/src/handlers/remove_dbg.rs | |||
@@ -1,6 +1,6 @@ | |||
1 | use ra_syntax::{ | 1 | use ra_syntax::{ |
2 | ast::{self, AstNode}, | 2 | ast::{self, AstNode}, |
3 | TextUnit, T, | 3 | TextSize, T, |
4 | }; | 4 | }; |
5 | 5 | ||
6 | use crate::{Assist, AssistCtx, AssistId}; | 6 | use crate::{Assist, AssistCtx, AssistId}; |
@@ -38,9 +38,9 @@ pub(crate) fn remove_dbg(ctx: AssistCtx) -> Option<Assist> { | |||
38 | let offset_start = file_range | 38 | let offset_start = file_range |
39 | .start() | 39 | .start() |
40 | .checked_sub(macro_range.start()) | 40 | .checked_sub(macro_range.start()) |
41 | .unwrap_or_else(|| TextUnit::from(0)); | 41 | .unwrap_or_else(|| TextSize::from(0)); |
42 | 42 | ||
43 | let dbg_size = TextUnit::of_str("dbg!("); | 43 | let dbg_size = TextSize::of("dbg!("); |
44 | 44 | ||
45 | if offset_start > dbg_size { | 45 | if offset_start > dbg_size { |
46 | file_range.start() - dbg_size | 46 | file_range.start() - dbg_size |
@@ -53,7 +53,7 @@ pub(crate) fn remove_dbg(ctx: AssistCtx) -> Option<Assist> { | |||
53 | let macro_args = macro_call.token_tree()?.syntax().clone(); | 53 | let macro_args = macro_call.token_tree()?.syntax().clone(); |
54 | 54 | ||
55 | let text = macro_args.text(); | 55 | let text = macro_args.text(); |
56 | let without_parens = TextUnit::of_char('(')..text.len() - TextUnit::of_char(')'); | 56 | let without_parens = TextSize::of('(')..text.len() - TextSize::of(')'); |
57 | text.slice(without_parens).to_string() | 57 | text.slice(without_parens).to_string() |
58 | }; | 58 | }; |
59 | 59 | ||
diff --git a/crates/ra_assists/src/handlers/remove_mut.rs b/crates/ra_assists/src/handlers/remove_mut.rs index 6884830eb..e598023b2 100644 --- a/crates/ra_assists/src/handlers/remove_mut.rs +++ b/crates/ra_assists/src/handlers/remove_mut.rs | |||
@@ -27,6 +27,6 @@ pub(crate) fn remove_mut(ctx: AssistCtx) -> Option<Assist> { | |||
27 | 27 | ||
28 | ctx.add_assist(AssistId("remove_mut"), "Remove `mut` keyword", |edit| { | 28 | ctx.add_assist(AssistId("remove_mut"), "Remove `mut` keyword", |edit| { |
29 | edit.set_cursor(delete_from); | 29 | edit.set_cursor(delete_from); |
30 | edit.delete(TextRange::from_to(delete_from, delete_to)); | 30 | edit.delete(TextRange::new(delete_from, delete_to)); |
31 | }) | 31 | }) |
32 | } | 32 | } |
diff --git a/crates/ra_assists/src/handlers/replace_qualified_name_with_use.rs b/crates/ra_assists/src/handlers/replace_qualified_name_with_use.rs index 94f5d6c50..2f02df303 100644 --- a/crates/ra_assists/src/handlers/replace_qualified_name_with_use.rs +++ b/crates/ra_assists/src/handlers/replace_qualified_name_with_use.rs | |||
@@ -43,7 +43,7 @@ pub(crate) fn replace_qualified_name_with_use(ctx: AssistCtx) -> Option<Assist> | |||
43 | if let Some(last) = path.segment() { | 43 | if let Some(last) = path.segment() { |
44 | // Here we are assuming the assist will provide a correct use statement | 44 | // Here we are assuming the assist will provide a correct use statement |
45 | // so we can delete the path qualifier | 45 | // so we can delete the path qualifier |
46 | edit.delete(TextRange::from_to( | 46 | edit.delete(TextRange::new( |
47 | path.syntax().text_range().start(), | 47 | path.syntax().text_range().start(), |
48 | last.syntax().text_range().start(), | 48 | last.syntax().text_range().start(), |
49 | )); | 49 | )); |
diff --git a/crates/ra_assists/src/lib.rs b/crates/ra_assists/src/lib.rs index a00136da1..64bd87afb 100644 --- a/crates/ra_assists/src/lib.rs +++ b/crates/ra_assists/src/lib.rs | |||
@@ -17,9 +17,9 @@ mod doc_tests; | |||
17 | pub mod utils; | 17 | pub mod utils; |
18 | pub mod ast_transform; | 18 | pub mod ast_transform; |
19 | 19 | ||
20 | use ra_db::FileRange; | 20 | use ra_db::{FileId, FileRange}; |
21 | use ra_ide_db::RootDatabase; | 21 | use ra_ide_db::RootDatabase; |
22 | use ra_syntax::{TextRange, TextUnit}; | 22 | use ra_syntax::{TextRange, TextSize}; |
23 | use ra_text_edit::TextEdit; | 23 | use ra_text_edit::TextEdit; |
24 | 24 | ||
25 | pub(crate) use crate::assist_ctx::{Assist, AssistCtx, AssistHandler}; | 25 | pub(crate) use crate::assist_ctx::{Assist, AssistCtx, AssistHandler}; |
@@ -51,9 +51,10 @@ impl AssistLabel { | |||
51 | #[derive(Debug, Clone)] | 51 | #[derive(Debug, Clone)] |
52 | pub struct AssistAction { | 52 | pub struct AssistAction { |
53 | pub edit: TextEdit, | 53 | pub edit: TextEdit, |
54 | pub cursor_position: Option<TextUnit>, | 54 | pub cursor_position: Option<TextSize>, |
55 | // FIXME: This belongs to `AssistLabel` | 55 | // FIXME: This belongs to `AssistLabel` |
56 | pub target: Option<TextRange>, | 56 | pub target: Option<TextRange>, |
57 | pub file: AssistFile, | ||
57 | } | 58 | } |
58 | 59 | ||
59 | #[derive(Debug, Clone)] | 60 | #[derive(Debug, Clone)] |
@@ -63,6 +64,18 @@ pub struct ResolvedAssist { | |||
63 | pub action: AssistAction, | 64 | pub action: AssistAction, |
64 | } | 65 | } |
65 | 66 | ||
67 | #[derive(Debug, Clone, Copy)] | ||
68 | pub enum AssistFile { | ||
69 | CurrentFile, | ||
70 | TargetFile(FileId), | ||
71 | } | ||
72 | |||
73 | impl Default for AssistFile { | ||
74 | fn default() -> Self { | ||
75 | Self::CurrentFile | ||
76 | } | ||
77 | } | ||
78 | |||
66 | /// Return all the assists applicable at the given position. | 79 | /// Return all the assists applicable at the given position. |
67 | /// | 80 | /// |
68 | /// Assists are returned in the "unresolved" state, that is only labels are | 81 | /// Assists are returned in the "unresolved" state, that is only labels are |
@@ -91,7 +104,7 @@ pub fn resolved_assists(db: &RootDatabase, range: FileRange) -> Vec<ResolvedAssi | |||
91 | .flat_map(|it| it.0) | 104 | .flat_map(|it| it.0) |
92 | .map(|it| it.into_resolved().unwrap()) | 105 | .map(|it| it.into_resolved().unwrap()) |
93 | .collect::<Vec<_>>(); | 106 | .collect::<Vec<_>>(); |
94 | a.sort_by_key(|it| it.action.target.map_or(TextUnit::from(!0u32), |it| it.len())); | 107 | a.sort_by_key(|it| it.action.target.map_or(TextSize::from(!0u32), |it| it.len())); |
95 | a | 108 | a |
96 | } | 109 | } |
97 | 110 | ||
@@ -184,7 +197,7 @@ mod helpers { | |||
184 | use ra_ide_db::{symbol_index::SymbolsDatabase, RootDatabase}; | 197 | use ra_ide_db::{symbol_index::SymbolsDatabase, RootDatabase}; |
185 | use test_utils::{add_cursor, assert_eq_text, extract_range_or_offset, RangeOrOffset}; | 198 | use test_utils::{add_cursor, assert_eq_text, extract_range_or_offset, RangeOrOffset}; |
186 | 199 | ||
187 | use crate::{AssistCtx, AssistHandler}; | 200 | use crate::{AssistCtx, AssistFile, AssistHandler}; |
188 | use hir::Semantics; | 201 | use hir::Semantics; |
189 | 202 | ||
190 | pub(crate) fn with_single_file(text: &str) -> (RootDatabase, FileId) { | 203 | pub(crate) fn with_single_file(text: &str) -> (RootDatabase, FileId) { |
@@ -246,7 +259,13 @@ mod helpers { | |||
246 | (Some(assist), ExpectedResult::After(after)) => { | 259 | (Some(assist), ExpectedResult::After(after)) => { |
247 | let action = assist.0[0].action.clone().unwrap(); | 260 | let action = assist.0[0].action.clone().unwrap(); |
248 | 261 | ||
249 | let mut actual = action.edit.apply(&text_without_caret); | 262 | let assisted_file_text = if let AssistFile::TargetFile(file_id) = action.file { |
263 | db.file_text(file_id).as_ref().to_owned() | ||
264 | } else { | ||
265 | text_without_caret | ||
266 | }; | ||
267 | |||
268 | let mut actual = action.edit.apply(&assisted_file_text); | ||
250 | match action.cursor_position { | 269 | match action.cursor_position { |
251 | None => { | 270 | None => { |
252 | if let RangeOrOffset::Offset(before_cursor_pos) = range_or_offset { | 271 | if let RangeOrOffset::Offset(before_cursor_pos) = range_or_offset { |
@@ -289,8 +308,7 @@ mod tests { | |||
289 | let before = "struct Foo { <|>bar: u32 }"; | 308 | let before = "struct Foo { <|>bar: u32 }"; |
290 | let (before_cursor_pos, before) = extract_offset(before); | 309 | let (before_cursor_pos, before) = extract_offset(before); |
291 | let (db, file_id) = helpers::with_single_file(&before); | 310 | let (db, file_id) = helpers::with_single_file(&before); |
292 | let frange = | 311 | let frange = FileRange { file_id, range: TextRange::empty(before_cursor_pos) }; |
293 | FileRange { file_id, range: TextRange::offset_len(before_cursor_pos, 0.into()) }; | ||
294 | let assists = resolved_assists(&db, frange); | 312 | let assists = resolved_assists(&db, frange); |
295 | let mut assists = assists.iter(); | 313 | let mut assists = assists.iter(); |
296 | 314 | ||