diff options
-rw-r--r-- | crates/ra_assists/src/assists/introduce_variable.rs | 18 | ||||
-rw-r--r-- | crates/ra_assists/src/doc_tests.rs | 7 | ||||
-rw-r--r-- | crates/ra_assists/src/doc_tests/generated.rs | 18 | ||||
-rw-r--r-- | crates/test_utils/src/lib.rs | 34 | ||||
-rw-r--r-- | docs/user/assists.md | 17 |
5 files changed, 85 insertions, 9 deletions
diff --git a/crates/ra_assists/src/assists/introduce_variable.rs b/crates/ra_assists/src/assists/introduce_variable.rs index 43378c4b0..8245dc99f 100644 --- a/crates/ra_assists/src/assists/introduce_variable.rs +++ b/crates/ra_assists/src/assists/introduce_variable.rs | |||
@@ -1,5 +1,3 @@ | |||
1 | //! FIXME: write short doc here | ||
2 | |||
3 | use format_buf::format; | 1 | use format_buf::format; |
4 | use hir::db::HirDatabase; | 2 | use hir::db::HirDatabase; |
5 | use ra_syntax::{ | 3 | use ra_syntax::{ |
@@ -14,6 +12,22 @@ use test_utils::tested_by; | |||
14 | 12 | ||
15 | use crate::{Assist, AssistCtx, AssistId}; | 13 | use crate::{Assist, AssistCtx, AssistId}; |
16 | 14 | ||
15 | // Assist: introduce_variable | ||
16 | // | ||
17 | // Extracts subexpression into a variable. | ||
18 | // | ||
19 | // ``` | ||
20 | // fn main() { | ||
21 | // <|>(1 + 2)<|> * 4; | ||
22 | // } | ||
23 | // ``` | ||
24 | // -> | ||
25 | // ``` | ||
26 | // fn main() { | ||
27 | // let var_name = (1 + 2); | ||
28 | // var_name * 4; | ||
29 | // } | ||
30 | // ``` | ||
17 | pub(crate) fn introduce_variable(mut ctx: AssistCtx<impl HirDatabase>) -> Option<Assist> { | 31 | pub(crate) fn introduce_variable(mut ctx: AssistCtx<impl HirDatabase>) -> Option<Assist> { |
18 | if ctx.frange.range.is_empty() { | 32 | if ctx.frange.range.is_empty() { |
19 | return None; | 33 | return None; |
diff --git a/crates/ra_assists/src/doc_tests.rs b/crates/ra_assists/src/doc_tests.rs index 872bbdf17..0ccf9d730 100644 --- a/crates/ra_assists/src/doc_tests.rs +++ b/crates/ra_assists/src/doc_tests.rs | |||
@@ -7,13 +7,12 @@ mod generated; | |||
7 | 7 | ||
8 | use hir::mock::MockDatabase; | 8 | use hir::mock::MockDatabase; |
9 | use ra_db::FileRange; | 9 | use ra_db::FileRange; |
10 | use ra_syntax::TextRange; | 10 | use test_utils::{assert_eq_text, extract_range_or_offset}; |
11 | use test_utils::{assert_eq_text, extract_offset}; | ||
12 | 11 | ||
13 | fn check(assist_id: &str, before: &str, after: &str) { | 12 | fn check(assist_id: &str, before: &str, after: &str) { |
14 | let (before_cursor_pos, before) = extract_offset(before); | 13 | let (selection, before) = extract_range_or_offset(before); |
15 | let (db, _source_root, file_id) = MockDatabase::with_single_file(&before); | 14 | let (db, _source_root, file_id) = MockDatabase::with_single_file(&before); |
16 | let frange = FileRange { file_id, range: TextRange::offset_len(before_cursor_pos, 0.into()) }; | 15 | let frange = FileRange { file_id, range: selection.into() }; |
17 | 16 | ||
18 | let (_assist_id, action) = crate::assists(&db, frange) | 17 | let (_assist_id, action) = crate::assists(&db, frange) |
19 | .into_iter() | 18 | .into_iter() |
diff --git a/crates/ra_assists/src/doc_tests/generated.rs b/crates/ra_assists/src/doc_tests/generated.rs index d390db33c..493bd94d0 100644 --- a/crates/ra_assists/src/doc_tests/generated.rs +++ b/crates/ra_assists/src/doc_tests/generated.rs | |||
@@ -255,3 +255,21 @@ fn main() { | |||
255 | "#####, | 255 | "#####, |
256 | ) | 256 | ) |
257 | } | 257 | } |
258 | |||
259 | #[test] | ||
260 | fn doctest_introduce_variable() { | ||
261 | check( | ||
262 | "introduce_variable", | ||
263 | r#####" | ||
264 | fn main() { | ||
265 | <|>(1 + 2)<|> * 4; | ||
266 | } | ||
267 | "#####, | ||
268 | r#####" | ||
269 | fn main() { | ||
270 | let var_name = (1 + 2); | ||
271 | var_name * 4; | ||
272 | } | ||
273 | "#####, | ||
274 | ) | ||
275 | } | ||
diff --git a/crates/test_utils/src/lib.rs b/crates/test_utils/src/lib.rs index c40943b63..1244ea8cf 100644 --- a/crates/test_utils/src/lib.rs +++ b/crates/test_utils/src/lib.rs | |||
@@ -1,4 +1,10 @@ | |||
1 | //! FIXME: write short doc here | 1 | //! Assorted testing utilities. |
2 | //! | ||
3 | //! Most notable things are: | ||
4 | //! | ||
5 | //! * Rich text comparison, which outputs a diff. | ||
6 | //! * Extracting markup (mainly, `<|>` markers) out of fixture strings. | ||
7 | //! * marks (see the eponymous module). | ||
2 | 8 | ||
3 | #[macro_use] | 9 | #[macro_use] |
4 | pub mod marks; | 10 | pub mod marks; |
@@ -43,7 +49,7 @@ pub fn extract_offset(text: &str) -> (TextUnit, String) { | |||
43 | } | 49 | } |
44 | } | 50 | } |
45 | 51 | ||
46 | pub fn try_extract_offset(text: &str) -> Option<(TextUnit, String)> { | 52 | fn try_extract_offset(text: &str) -> Option<(TextUnit, String)> { |
47 | let cursor_pos = text.find(CURSOR_MARKER)?; | 53 | let cursor_pos = text.find(CURSOR_MARKER)?; |
48 | let mut new_text = String::with_capacity(text.len() - CURSOR_MARKER.len()); | 54 | let mut new_text = String::with_capacity(text.len() - CURSOR_MARKER.len()); |
49 | new_text.push_str(&text[..cursor_pos]); | 55 | new_text.push_str(&text[..cursor_pos]); |
@@ -59,12 +65,34 @@ pub fn extract_range(text: &str) -> (TextRange, String) { | |||
59 | } | 65 | } |
60 | } | 66 | } |
61 | 67 | ||
62 | pub fn try_extract_range(text: &str) -> Option<(TextRange, String)> { | 68 | fn try_extract_range(text: &str) -> Option<(TextRange, String)> { |
63 | let (start, text) = try_extract_offset(text)?; | 69 | let (start, text) = try_extract_offset(text)?; |
64 | let (end, text) = try_extract_offset(&text)?; | 70 | let (end, text) = try_extract_offset(&text)?; |
65 | Some((TextRange::from_to(start, end), text)) | 71 | Some((TextRange::from_to(start, end), text)) |
66 | } | 72 | } |
67 | 73 | ||
74 | pub enum RangeOrOffset { | ||
75 | Range(TextRange), | ||
76 | Offset(TextUnit), | ||
77 | } | ||
78 | |||
79 | impl From<RangeOrOffset> for TextRange { | ||
80 | fn from(selection: RangeOrOffset) -> Self { | ||
81 | match selection { | ||
82 | RangeOrOffset::Range(it) => it, | ||
83 | RangeOrOffset::Offset(it) => TextRange::from_to(it, it), | ||
84 | } | ||
85 | } | ||
86 | } | ||
87 | |||
88 | pub fn extract_range_or_offset(text: &str) -> (RangeOrOffset, String) { | ||
89 | if let Some((range, text)) = try_extract_range(text) { | ||
90 | return (RangeOrOffset::Range(range), text); | ||
91 | } | ||
92 | let (offset, text) = extract_offset(text); | ||
93 | (RangeOrOffset::Offset(offset), text) | ||
94 | } | ||
95 | |||
68 | /// Extracts ranges, marked with `<tag> </tag>` paris from the `text` | 96 | /// Extracts ranges, marked with `<tag> </tag>` paris from the `text` |
69 | pub fn extract_ranges(mut text: &str, tag: &str) -> (Vec<TextRange>, String) { | 97 | pub fn extract_ranges(mut text: &str, tag: &str) -> (Vec<TextRange>, String) { |
70 | let open = format!("<{}>", tag); | 98 | let open = format!("<{}>", tag); |
diff --git a/docs/user/assists.md b/docs/user/assists.md index 8e2e8cc94..182f07e98 100644 --- a/docs/user/assists.md +++ b/docs/user/assists.md | |||
@@ -245,3 +245,20 @@ fn main() { | |||
245 | (1 + 2) * 4; | 245 | (1 + 2) * 4; |
246 | } | 246 | } |
247 | ``` | 247 | ``` |
248 | |||
249 | ## `introduce_variable` | ||
250 | |||
251 | Extracts subexpression into a variable. | ||
252 | |||
253 | ```rust | ||
254 | // BEFORE | ||
255 | fn main() { | ||
256 | <|>(1 + 2)<|> * 4; | ||
257 | } | ||
258 | |||
259 | // AFTER | ||
260 | fn main() { | ||
261 | let var_name = (1 + 2); | ||
262 | var_name * 4; | ||
263 | } | ||
264 | ``` | ||