diff options
Diffstat (limited to 'crates/ra_ide/src')
23 files changed, 527 insertions, 221 deletions
diff --git a/crates/ra_ide/src/completion.rs b/crates/ra_ide/src/completion.rs index a27e0fc15..93e53c921 100644 --- a/crates/ra_ide/src/completion.rs +++ b/crates/ra_ide/src/completion.rs | |||
@@ -16,11 +16,11 @@ mod complete_scope; | |||
16 | mod complete_postfix; | 16 | mod complete_postfix; |
17 | mod complete_macro_in_item_position; | 17 | mod complete_macro_in_item_position; |
18 | mod complete_trait_impl; | 18 | mod complete_trait_impl; |
19 | #[cfg(test)] | ||
20 | mod test_utils; | ||
19 | 21 | ||
20 | use ra_ide_db::RootDatabase; | 22 | use ra_ide_db::RootDatabase; |
21 | 23 | ||
22 | #[cfg(test)] | ||
23 | use crate::completion::completion_item::do_completion; | ||
24 | use crate::{ | 24 | use crate::{ |
25 | completion::{ | 25 | completion::{ |
26 | completion_context::CompletionContext, | 26 | completion_context::CompletionContext, |
diff --git a/crates/ra_ide/src/completion/complete_dot.rs b/crates/ra_ide/src/completion/complete_dot.rs index d8f6f0d9d..81e5037aa 100644 --- a/crates/ra_ide/src/completion/complete_dot.rs +++ b/crates/ra_ide/src/completion/complete_dot.rs | |||
@@ -70,7 +70,7 @@ fn complete_methods(acc: &mut Completions, ctx: &CompletionContext, receiver: &T | |||
70 | 70 | ||
71 | #[cfg(test)] | 71 | #[cfg(test)] |
72 | mod tests { | 72 | mod tests { |
73 | use crate::completion::{do_completion, CompletionItem, CompletionKind}; | 73 | use crate::completion::{test_utils::do_completion, CompletionItem, CompletionKind}; |
74 | use insta::assert_debug_snapshot; | 74 | use insta::assert_debug_snapshot; |
75 | 75 | ||
76 | fn do_ref_completion(code: &str) -> Vec<CompletionItem> { | 76 | fn do_ref_completion(code: &str) -> Vec<CompletionItem> { |
diff --git a/crates/ra_ide/src/completion/complete_fn_param.rs b/crates/ra_ide/src/completion/complete_fn_param.rs index 502458706..9226ac055 100644 --- a/crates/ra_ide/src/completion/complete_fn_param.rs +++ b/crates/ra_ide/src/completion/complete_fn_param.rs | |||
@@ -52,7 +52,7 @@ pub(super) fn complete_fn_param(acc: &mut Completions, ctx: &CompletionContext) | |||
52 | 52 | ||
53 | #[cfg(test)] | 53 | #[cfg(test)] |
54 | mod tests { | 54 | mod tests { |
55 | use crate::completion::{do_completion, CompletionItem, CompletionKind}; | 55 | use crate::completion::{test_utils::do_completion, CompletionItem, CompletionKind}; |
56 | use insta::assert_debug_snapshot; | 56 | use insta::assert_debug_snapshot; |
57 | 57 | ||
58 | fn do_magic_completion(code: &str) -> Vec<CompletionItem> { | 58 | fn do_magic_completion(code: &str) -> Vec<CompletionItem> { |
diff --git a/crates/ra_ide/src/completion/complete_keyword.rs b/crates/ra_ide/src/completion/complete_keyword.rs index e1c0ffb1f..1e053ea4a 100644 --- a/crates/ra_ide/src/completion/complete_keyword.rs +++ b/crates/ra_ide/src/completion/complete_keyword.rs | |||
@@ -117,7 +117,7 @@ fn complete_return( | |||
117 | 117 | ||
118 | #[cfg(test)] | 118 | #[cfg(test)] |
119 | mod tests { | 119 | mod tests { |
120 | use crate::completion::{do_completion, CompletionItem, CompletionKind}; | 120 | use crate::completion::{test_utils::do_completion, CompletionItem, CompletionKind}; |
121 | use insta::assert_debug_snapshot; | 121 | use insta::assert_debug_snapshot; |
122 | 122 | ||
123 | fn do_keyword_completion(code: &str) -> Vec<CompletionItem> { | 123 | fn do_keyword_completion(code: &str) -> Vec<CompletionItem> { |
diff --git a/crates/ra_ide/src/completion/complete_macro_in_item_position.rs b/crates/ra_ide/src/completion/complete_macro_in_item_position.rs index 1866d9e6c..270e96df0 100644 --- a/crates/ra_ide/src/completion/complete_macro_in_item_position.rs +++ b/crates/ra_ide/src/completion/complete_macro_in_item_position.rs | |||
@@ -15,9 +15,10 @@ pub(super) fn complete_macro_in_item_position(acc: &mut Completions, ctx: &Compl | |||
15 | 15 | ||
16 | #[cfg(test)] | 16 | #[cfg(test)] |
17 | mod tests { | 17 | mod tests { |
18 | use crate::completion::{do_completion, CompletionItem, CompletionKind}; | ||
19 | use insta::assert_debug_snapshot; | 18 | use insta::assert_debug_snapshot; |
20 | 19 | ||
20 | use crate::completion::{test_utils::do_completion, CompletionItem, CompletionKind}; | ||
21 | |||
21 | fn do_reference_completion(code: &str) -> Vec<CompletionItem> { | 22 | fn do_reference_completion(code: &str) -> Vec<CompletionItem> { |
22 | do_completion(code, CompletionKind::Reference) | 23 | do_completion(code, CompletionKind::Reference) |
23 | } | 24 | } |
diff --git a/crates/ra_ide/src/completion/complete_path.rs b/crates/ra_ide/src/completion/complete_path.rs index 3c4a70561..d588ee364 100644 --- a/crates/ra_ide/src/completion/complete_path.rs +++ b/crates/ra_ide/src/completion/complete_path.rs | |||
@@ -103,7 +103,7 @@ pub(super) fn complete_path(acc: &mut Completions, ctx: &CompletionContext) { | |||
103 | mod tests { | 103 | mod tests { |
104 | use test_utils::covers; | 104 | use test_utils::covers; |
105 | 105 | ||
106 | use crate::completion::{do_completion, CompletionItem, CompletionKind}; | 106 | use crate::completion::{test_utils::do_completion, CompletionItem, CompletionKind}; |
107 | use insta::assert_debug_snapshot; | 107 | use insta::assert_debug_snapshot; |
108 | 108 | ||
109 | fn do_reference_completion(code: &str) -> Vec<CompletionItem> { | 109 | fn do_reference_completion(code: &str) -> Vec<CompletionItem> { |
diff --git a/crates/ra_ide/src/completion/complete_pattern.rs b/crates/ra_ide/src/completion/complete_pattern.rs index fa8aeceda..6a1a66ef1 100644 --- a/crates/ra_ide/src/completion/complete_pattern.rs +++ b/crates/ra_ide/src/completion/complete_pattern.rs | |||
@@ -27,7 +27,7 @@ pub(super) fn complete_pattern(acc: &mut Completions, ctx: &CompletionContext) { | |||
27 | 27 | ||
28 | #[cfg(test)] | 28 | #[cfg(test)] |
29 | mod tests { | 29 | mod tests { |
30 | use crate::completion::{do_completion, CompletionItem, CompletionKind}; | 30 | use crate::completion::{test_utils::do_completion, CompletionItem, CompletionKind}; |
31 | use insta::assert_debug_snapshot; | 31 | use insta::assert_debug_snapshot; |
32 | 32 | ||
33 | fn complete(code: &str) -> Vec<CompletionItem> { | 33 | fn complete(code: &str) -> Vec<CompletionItem> { |
diff --git a/crates/ra_ide/src/completion/complete_postfix.rs b/crates/ra_ide/src/completion/complete_postfix.rs index 6d000548d..0ba382165 100644 --- a/crates/ra_ide/src/completion/complete_postfix.rs +++ b/crates/ra_ide/src/completion/complete_postfix.rs | |||
@@ -81,7 +81,7 @@ fn postfix_snippet(ctx: &CompletionContext, label: &str, detail: &str, snippet: | |||
81 | mod tests { | 81 | mod tests { |
82 | use insta::assert_debug_snapshot; | 82 | use insta::assert_debug_snapshot; |
83 | 83 | ||
84 | use crate::completion::{do_completion, CompletionItem, CompletionKind}; | 84 | use crate::completion::{test_utils::do_completion, CompletionItem, CompletionKind}; |
85 | 85 | ||
86 | fn do_postfix_completion(code: &str) -> Vec<CompletionItem> { | 86 | fn do_postfix_completion(code: &str) -> Vec<CompletionItem> { |
87 | do_completion(code, CompletionKind::Postfix) | 87 | do_completion(code, CompletionKind::Postfix) |
diff --git a/crates/ra_ide/src/completion/complete_record_literal.rs b/crates/ra_ide/src/completion/complete_record_literal.rs index be6e4194f..83ed1d52c 100644 --- a/crates/ra_ide/src/completion/complete_record_literal.rs +++ b/crates/ra_ide/src/completion/complete_record_literal.rs | |||
@@ -18,7 +18,7 @@ pub(super) fn complete_record_literal(acc: &mut Completions, ctx: &CompletionCon | |||
18 | 18 | ||
19 | #[cfg(test)] | 19 | #[cfg(test)] |
20 | mod tests { | 20 | mod tests { |
21 | use crate::completion::{do_completion, CompletionItem, CompletionKind}; | 21 | use crate::completion::{test_utils::do_completion, CompletionItem, CompletionKind}; |
22 | use insta::assert_debug_snapshot; | 22 | use insta::assert_debug_snapshot; |
23 | 23 | ||
24 | fn complete(code: &str) -> Vec<CompletionItem> { | 24 | fn complete(code: &str) -> Vec<CompletionItem> { |
diff --git a/crates/ra_ide/src/completion/complete_record_pattern.rs b/crates/ra_ide/src/completion/complete_record_pattern.rs index 687c57d3e..962376428 100644 --- a/crates/ra_ide/src/completion/complete_record_pattern.rs +++ b/crates/ra_ide/src/completion/complete_record_pattern.rs | |||
@@ -17,7 +17,7 @@ pub(super) fn complete_record_pattern(acc: &mut Completions, ctx: &CompletionCon | |||
17 | 17 | ||
18 | #[cfg(test)] | 18 | #[cfg(test)] |
19 | mod tests { | 19 | mod tests { |
20 | use crate::completion::{do_completion, CompletionItem, CompletionKind}; | 20 | use crate::completion::{test_utils::do_completion, CompletionItem, CompletionKind}; |
21 | use insta::assert_debug_snapshot; | 21 | use insta::assert_debug_snapshot; |
22 | 22 | ||
23 | fn complete(code: &str) -> Vec<CompletionItem> { | 23 | fn complete(code: &str) -> Vec<CompletionItem> { |
diff --git a/crates/ra_ide/src/completion/complete_scope.rs b/crates/ra_ide/src/completion/complete_scope.rs index eb3c8cf1b..bd4adf23a 100644 --- a/crates/ra_ide/src/completion/complete_scope.rs +++ b/crates/ra_ide/src/completion/complete_scope.rs | |||
@@ -14,10 +14,10 @@ pub(super) fn complete_scope(acc: &mut Completions, ctx: &CompletionContext) { | |||
14 | mod tests { | 14 | mod tests { |
15 | use insta::assert_debug_snapshot; | 15 | use insta::assert_debug_snapshot; |
16 | 16 | ||
17 | use crate::completion::{do_completion, CompletionItem, CompletionKind}; | 17 | use crate::completion::{test_utils::do_completion, CompletionItem, CompletionKind}; |
18 | 18 | ||
19 | fn do_reference_completion(code: &str) -> Vec<CompletionItem> { | 19 | fn do_reference_completion(ra_fixture: &str) -> Vec<CompletionItem> { |
20 | do_completion(code, CompletionKind::Reference) | 20 | do_completion(ra_fixture, CompletionKind::Reference) |
21 | } | 21 | } |
22 | 22 | ||
23 | #[test] | 23 | #[test] |
diff --git a/crates/ra_ide/src/completion/complete_snippet.rs b/crates/ra_ide/src/completion/complete_snippet.rs index 731b4fd82..f731e9b9a 100644 --- a/crates/ra_ide/src/completion/complete_snippet.rs +++ b/crates/ra_ide/src/completion/complete_snippet.rs | |||
@@ -42,7 +42,7 @@ fn ${1:feature}() { | |||
42 | 42 | ||
43 | #[cfg(test)] | 43 | #[cfg(test)] |
44 | mod tests { | 44 | mod tests { |
45 | use crate::completion::{do_completion, CompletionItem, CompletionKind}; | 45 | use crate::completion::{test_utils::do_completion, CompletionItem, CompletionKind}; |
46 | use insta::assert_debug_snapshot; | 46 | use insta::assert_debug_snapshot; |
47 | 47 | ||
48 | fn do_snippet_completion(code: &str) -> Vec<CompletionItem> { | 48 | fn do_snippet_completion(code: &str) -> Vec<CompletionItem> { |
diff --git a/crates/ra_ide/src/completion/complete_trait_impl.rs b/crates/ra_ide/src/completion/complete_trait_impl.rs index 2bf654a57..7fefa2c7a 100644 --- a/crates/ra_ide/src/completion/complete_trait_impl.rs +++ b/crates/ra_ide/src/completion/complete_trait_impl.rs | |||
@@ -217,7 +217,7 @@ fn make_const_compl_syntax(const_: &ast::ConstDef) -> String { | |||
217 | 217 | ||
218 | #[cfg(test)] | 218 | #[cfg(test)] |
219 | mod tests { | 219 | mod tests { |
220 | use crate::completion::{do_completion, CompletionItem, CompletionKind}; | 220 | use crate::completion::{test_utils::do_completion, CompletionItem, CompletionKind}; |
221 | use insta::assert_debug_snapshot; | 221 | use insta::assert_debug_snapshot; |
222 | 222 | ||
223 | fn complete(code: &str) -> Vec<CompletionItem> { | 223 | fn complete(code: &str) -> Vec<CompletionItem> { |
diff --git a/crates/ra_ide/src/completion/completion_item.rs b/crates/ra_ide/src/completion/completion_item.rs index 1d14e9636..ef0eb43b2 100644 --- a/crates/ra_ide/src/completion/completion_item.rs +++ b/crates/ra_ide/src/completion/completion_item.rs | |||
@@ -13,7 +13,7 @@ pub struct CompletionItem { | |||
13 | /// Used only internally in tests, to check only specific kind of | 13 | /// Used only internally in tests, to check only specific kind of |
14 | /// completion (postfix, keyword, reference, etc). | 14 | /// completion (postfix, keyword, reference, etc). |
15 | #[allow(unused)] | 15 | #[allow(unused)] |
16 | completion_kind: CompletionKind, | 16 | pub(crate) completion_kind: CompletionKind, |
17 | /// Label in the completion pop up which identifies completion. | 17 | /// Label in the completion pop up which identifies completion. |
18 | label: String, | 18 | label: String, |
19 | /// Range of identifier that is being completed. | 19 | /// Range of identifier that is being completed. |
@@ -318,24 +318,3 @@ impl Into<Vec<CompletionItem>> for Completions { | |||
318 | self.buf | 318 | self.buf |
319 | } | 319 | } |
320 | } | 320 | } |
321 | |||
322 | #[cfg(test)] | ||
323 | pub(crate) fn do_completion(code: &str, kind: CompletionKind) -> Vec<CompletionItem> { | ||
324 | use crate::{ | ||
325 | completion::{completions, CompletionOptions}, | ||
326 | mock_analysis::{analysis_and_position, single_file_with_position}, | ||
327 | }; | ||
328 | |||
329 | let (analysis, position) = if code.contains("//-") { | ||
330 | analysis_and_position(code) | ||
331 | } else { | ||
332 | single_file_with_position(code) | ||
333 | }; | ||
334 | let options = CompletionOptions::default(); | ||
335 | let completions = completions(&analysis.db, position, &options).unwrap(); | ||
336 | let completion_items: Vec<CompletionItem> = completions.into(); | ||
337 | let mut kind_completions: Vec<CompletionItem> = | ||
338 | completion_items.into_iter().filter(|c| c.completion_kind == kind).collect(); | ||
339 | kind_completions.sort_by_key(|c| c.label.clone()); | ||
340 | kind_completions | ||
341 | } | ||
diff --git a/crates/ra_ide/src/completion/presentation.rs b/crates/ra_ide/src/completion/presentation.rs index 3dc56e4a3..5213def20 100644 --- a/crates/ra_ide/src/completion/presentation.rs +++ b/crates/ra_ide/src/completion/presentation.rs | |||
@@ -307,12 +307,22 @@ mod tests { | |||
307 | use insta::assert_debug_snapshot; | 307 | use insta::assert_debug_snapshot; |
308 | use test_utils::covers; | 308 | use test_utils::covers; |
309 | 309 | ||
310 | use crate::completion::{do_completion, CompletionItem, CompletionKind}; | 310 | use crate::completion::{ |
311 | test_utils::{do_completion, do_completion_with_options}, | ||
312 | CompletionItem, CompletionKind, CompletionOptions, | ||
313 | }; | ||
311 | 314 | ||
312 | fn do_reference_completion(ra_fixture: &str) -> Vec<CompletionItem> { | 315 | fn do_reference_completion(ra_fixture: &str) -> Vec<CompletionItem> { |
313 | do_completion(ra_fixture, CompletionKind::Reference) | 316 | do_completion(ra_fixture, CompletionKind::Reference) |
314 | } | 317 | } |
315 | 318 | ||
319 | fn do_reference_completion_with_options( | ||
320 | ra_fixture: &str, | ||
321 | options: CompletionOptions, | ||
322 | ) -> Vec<CompletionItem> { | ||
323 | do_completion_with_options(ra_fixture, CompletionKind::Reference, &options) | ||
324 | } | ||
325 | |||
316 | #[test] | 326 | #[test] |
317 | fn enum_detail_includes_names_for_record() { | 327 | fn enum_detail_includes_names_for_record() { |
318 | assert_debug_snapshot!( | 328 | assert_debug_snapshot!( |
@@ -533,7 +543,7 @@ mod tests { | |||
533 | } | 543 | } |
534 | 544 | ||
535 | #[test] | 545 | #[test] |
536 | fn parens_for_method_call() { | 546 | fn arg_snippets_for_method_call() { |
537 | assert_debug_snapshot!( | 547 | assert_debug_snapshot!( |
538 | do_reference_completion( | 548 | do_reference_completion( |
539 | r" | 549 | r" |
@@ -563,6 +573,40 @@ mod tests { | |||
563 | } | 573 | } |
564 | 574 | ||
565 | #[test] | 575 | #[test] |
576 | fn no_arg_snippets_for_method_call() { | ||
577 | assert_debug_snapshot!( | ||
578 | do_reference_completion_with_options( | ||
579 | r" | ||
580 | struct S {} | ||
581 | impl S { | ||
582 | fn foo(&self, x: i32) {} | ||
583 | } | ||
584 | fn bar(s: &S) { | ||
585 | s.f<|> | ||
586 | } | ||
587 | ", | ||
588 | CompletionOptions { | ||
589 | add_call_argument_snippets: false, | ||
590 | .. Default::default() | ||
591 | } | ||
592 | ), | ||
593 | @r###" | ||
594 | [ | ||
595 | CompletionItem { | ||
596 | label: "foo(…)", | ||
597 | source_range: [171; 172), | ||
598 | delete: [171; 172), | ||
599 | insert: "foo($0)", | ||
600 | kind: Method, | ||
601 | lookup: "foo", | ||
602 | detail: "fn foo(&self, x: i32)", | ||
603 | }, | ||
604 | ] | ||
605 | "### | ||
606 | ) | ||
607 | } | ||
608 | |||
609 | #[test] | ||
566 | fn dont_render_function_parens_in_use_item() { | 610 | fn dont_render_function_parens_in_use_item() { |
567 | assert_debug_snapshot!( | 611 | assert_debug_snapshot!( |
568 | do_reference_completion( | 612 | do_reference_completion( |
diff --git a/crates/ra_ide/src/completion/test_utils.rs b/crates/ra_ide/src/completion/test_utils.rs new file mode 100644 index 000000000..136857315 --- /dev/null +++ b/crates/ra_ide/src/completion/test_utils.rs | |||
@@ -0,0 +1,29 @@ | |||
1 | //! Runs completion for testing purposes. | ||
2 | |||
3 | use crate::{ | ||
4 | completion::{completion_item::CompletionKind, CompletionOptions}, | ||
5 | mock_analysis::{analysis_and_position, single_file_with_position}, | ||
6 | CompletionItem, | ||
7 | }; | ||
8 | |||
9 | pub(crate) fn do_completion(code: &str, kind: CompletionKind) -> Vec<CompletionItem> { | ||
10 | do_completion_with_options(code, kind, &CompletionOptions::default()) | ||
11 | } | ||
12 | |||
13 | pub(crate) fn do_completion_with_options( | ||
14 | code: &str, | ||
15 | kind: CompletionKind, | ||
16 | options: &CompletionOptions, | ||
17 | ) -> Vec<CompletionItem> { | ||
18 | let (analysis, position) = if code.contains("//-") { | ||
19 | analysis_and_position(code) | ||
20 | } else { | ||
21 | single_file_with_position(code) | ||
22 | }; | ||
23 | let completions = analysis.completions(position, options).unwrap().unwrap(); | ||
24 | let completion_items: Vec<CompletionItem> = completions.into(); | ||
25 | let mut kind_completions: Vec<CompletionItem> = | ||
26 | completion_items.into_iter().filter(|c| c.completion_kind == kind).collect(); | ||
27 | kind_completions.sort_by_key(|c| c.label().to_owned()); | ||
28 | kind_completions | ||
29 | } | ||
diff --git a/crates/ra_ide/src/hover.rs b/crates/ra_ide/src/hover.rs index 25e038a55..0bbba4855 100644 --- a/crates/ra_ide/src/hover.rs +++ b/crates/ra_ide/src/hover.rs | |||
@@ -833,19 +833,34 @@ fn func(foo: i32) { if true { <|>foo; }; } | |||
833 | } | 833 | } |
834 | 834 | ||
835 | #[test] | 835 | #[test] |
836 | fn test_hover_through_assert_macro() { | ||
837 | let hover_on = check_hover_result( | ||
838 | r#" | ||
839 | //- /lib.rs | ||
840 | #[rustc_builtin_macro] | ||
841 | macro_rules! assert {} | ||
842 | |||
843 | fn bar() -> bool { true } | ||
844 | fn foo() { | ||
845 | assert!(ba<|>r()); | ||
846 | } | ||
847 | "#, | ||
848 | &["fn bar() -> bool"], | ||
849 | ); | ||
850 | |||
851 | assert_eq!(hover_on, "bar"); | ||
852 | } | ||
853 | |||
854 | #[test] | ||
836 | fn test_hover_through_literal_string_in_builtin_macro() { | 855 | fn test_hover_through_literal_string_in_builtin_macro() { |
837 | check_hover_no_result( | 856 | check_hover_no_result( |
838 | r#" | 857 | r#" |
839 | //- /lib.rs | 858 | //- /lib.rs |
840 | #[rustc_builtin_macro] | 859 | #[rustc_builtin_macro] |
841 | macro_rules! assert { | 860 | macro_rules! format {} |
842 | ($cond:expr) => {{ /* compiler built-in */ }}; | ||
843 | ($cond:expr,) => {{ /* compiler built-in */ }}; | ||
844 | ($cond:expr, $($arg:tt)+) => {{ /* compiler built-in */ }}; | ||
845 | } | ||
846 | 861 | ||
847 | fn foo() { | 862 | fn foo() { |
848 | assert!("hel<|>lo"); | 863 | format!("hel<|>lo {}", 0); |
849 | } | 864 | } |
850 | "#, | 865 | "#, |
851 | ); | 866 | ); |
diff --git a/crates/ra_ide/src/lib.rs b/crates/ra_ide/src/lib.rs index a3acfd225..922e4caa8 100644 --- a/crates/ra_ide/src/lib.rs +++ b/crates/ra_ide/src/lib.rs | |||
@@ -212,6 +212,7 @@ impl Analysis { | |||
212 | None, | 212 | None, |
213 | cfg_options, | 213 | cfg_options, |
214 | Env::default(), | 214 | Env::default(), |
215 | Default::default(), | ||
215 | ); | 216 | ); |
216 | change.add_file(source_root, file_id, "main.rs".into(), Arc::new(text)); | 217 | change.add_file(source_root, file_id, "main.rs".into(), Arc::new(text)); |
217 | change.set_crate_graph(crate_graph); | 218 | change.set_crate_graph(crate_graph); |
diff --git a/crates/ra_ide/src/mock_analysis.rs b/crates/ra_ide/src/mock_analysis.rs index 90f84b052..25816cf6f 100644 --- a/crates/ra_ide/src/mock_analysis.rs +++ b/crates/ra_ide/src/mock_analysis.rs | |||
@@ -102,6 +102,7 @@ impl MockAnalysis { | |||
102 | None, | 102 | None, |
103 | cfg_options, | 103 | cfg_options, |
104 | Env::default(), | 104 | Env::default(), |
105 | Default::default(), | ||
105 | )); | 106 | )); |
106 | } else if path.ends_with("/lib.rs") { | 107 | } else if path.ends_with("/lib.rs") { |
107 | let crate_name = path.parent().unwrap().file_name().unwrap(); | 108 | let crate_name = path.parent().unwrap().file_name().unwrap(); |
@@ -111,6 +112,7 @@ impl MockAnalysis { | |||
111 | Some(crate_name.to_owned()), | 112 | Some(crate_name.to_owned()), |
112 | cfg_options, | 113 | cfg_options, |
113 | Env::default(), | 114 | Env::default(), |
115 | Default::default(), | ||
114 | ); | 116 | ); |
115 | if let Some(root_crate) = root_crate { | 117 | if let Some(root_crate) = root_crate { |
116 | crate_graph | 118 | crate_graph |
diff --git a/crates/ra_ide/src/parent_module.rs b/crates/ra_ide/src/parent_module.rs index b73cefd97..76d130b9b 100644 --- a/crates/ra_ide/src/parent_module.rs +++ b/crates/ra_ide/src/parent_module.rs | |||
@@ -136,6 +136,7 @@ mod tests { | |||
136 | None, | 136 | None, |
137 | CfgOptions::default(), | 137 | CfgOptions::default(), |
138 | Env::default(), | 138 | Env::default(), |
139 | Default::default(), | ||
139 | ); | 140 | ); |
140 | let mut change = AnalysisChange::new(); | 141 | let mut change = AnalysisChange::new(); |
141 | change.set_crate_graph(crate_graph); | 142 | change.set_crate_graph(crate_graph); |
diff --git a/crates/ra_ide/src/references/rename.rs b/crates/ra_ide/src/references/rename.rs index 5b4bcf434..7d1190af9 100644 --- a/crates/ra_ide/src/references/rename.rs +++ b/crates/ra_ide/src/references/rename.rs | |||
@@ -9,7 +9,8 @@ use ra_syntax::{ | |||
9 | use ra_text_edit::TextEdit; | 9 | use ra_text_edit::TextEdit; |
10 | 10 | ||
11 | use crate::{ | 11 | use crate::{ |
12 | FileId, FilePosition, FileSystemEdit, RangeInfo, SourceChange, SourceFileEdit, TextRange, | 12 | FilePosition, FileSystemEdit, RangeInfo, Reference, ReferenceKind, SourceChange, |
13 | SourceFileEdit, TextRange, | ||
13 | }; | 14 | }; |
14 | 15 | ||
15 | use super::find_all_refs; | 16 | use super::find_all_refs; |
@@ -46,12 +47,29 @@ fn find_name_and_module_at_offset( | |||
46 | Some((ast_name, ast_module)) | 47 | Some((ast_name, ast_module)) |
47 | } | 48 | } |
48 | 49 | ||
49 | fn source_edit_from_file_id_range( | 50 | fn source_edit_from_reference(reference: Reference, new_name: &str) -> SourceFileEdit { |
50 | file_id: FileId, | 51 | let mut replacement_text = String::new(); |
51 | range: TextRange, | 52 | let file_id = reference.file_range.file_id; |
52 | new_name: &str, | 53 | let range = match reference.kind { |
53 | ) -> SourceFileEdit { | 54 | ReferenceKind::StructFieldShorthandForField => { |
54 | SourceFileEdit { file_id, edit: TextEdit::replace(range, new_name.into()) } | 55 | replacement_text.push_str(new_name); |
56 | replacement_text.push_str(": "); | ||
57 | TextRange::from_to( | ||
58 | reference.file_range.range.start(), | ||
59 | reference.file_range.range.start(), | ||
60 | ) | ||
61 | } | ||
62 | ReferenceKind::StructFieldShorthandForLocal => { | ||
63 | replacement_text.push_str(": "); | ||
64 | replacement_text.push_str(new_name); | ||
65 | TextRange::from_to(reference.file_range.range.end(), reference.file_range.range.end()) | ||
66 | } | ||
67 | _ => { | ||
68 | replacement_text.push_str(new_name); | ||
69 | reference.file_range.range | ||
70 | } | ||
71 | }; | ||
72 | SourceFileEdit { file_id, edit: TextEdit::replace(range, replacement_text) } | ||
55 | } | 73 | } |
56 | 74 | ||
57 | fn rename_mod( | 75 | fn rename_mod( |
@@ -99,13 +117,10 @@ fn rename_mod( | |||
99 | source_file_edits.push(edit); | 117 | source_file_edits.push(edit); |
100 | 118 | ||
101 | if let Some(RangeInfo { range: _, info: refs }) = find_all_refs(sema.db, position, None) { | 119 | if let Some(RangeInfo { range: _, info: refs }) = find_all_refs(sema.db, position, None) { |
102 | let ref_edits = refs.references.into_iter().map(|reference| { | 120 | let ref_edits = refs |
103 | source_edit_from_file_id_range( | 121 | .references |
104 | reference.file_range.file_id, | 122 | .into_iter() |
105 | reference.file_range.range, | 123 | .map(|reference| source_edit_from_reference(reference, new_name)); |
106 | new_name, | ||
107 | ) | ||
108 | }); | ||
109 | source_file_edits.extend(ref_edits); | 124 | source_file_edits.extend(ref_edits); |
110 | } | 125 | } |
111 | 126 | ||
@@ -121,13 +136,7 @@ fn rename_reference( | |||
121 | 136 | ||
122 | let edit = refs | 137 | let edit = refs |
123 | .into_iter() | 138 | .into_iter() |
124 | .map(|reference| { | 139 | .map(|reference| source_edit_from_reference(reference, new_name)) |
125 | source_edit_from_file_id_range( | ||
126 | reference.file_range.file_id, | ||
127 | reference.file_range.range, | ||
128 | new_name, | ||
129 | ) | ||
130 | }) | ||
131 | .collect::<Vec<_>>(); | 140 | .collect::<Vec<_>>(); |
132 | 141 | ||
133 | if edit.is_empty() { | 142 | if edit.is_empty() { |
@@ -286,6 +295,163 @@ mod tests { | |||
286 | } | 295 | } |
287 | 296 | ||
288 | #[test] | 297 | #[test] |
298 | fn test_rename_struct_field() { | ||
299 | test_rename( | ||
300 | r#" | ||
301 | struct Foo { | ||
302 | i<|>: i32, | ||
303 | } | ||
304 | |||
305 | impl Foo { | ||
306 | fn new(i: i32) -> Self { | ||
307 | Self { i: i } | ||
308 | } | ||
309 | } | ||
310 | "#, | ||
311 | "j", | ||
312 | r#" | ||
313 | struct Foo { | ||
314 | j: i32, | ||
315 | } | ||
316 | |||
317 | impl Foo { | ||
318 | fn new(i: i32) -> Self { | ||
319 | Self { j: i } | ||
320 | } | ||
321 | } | ||
322 | "#, | ||
323 | ); | ||
324 | } | ||
325 | |||
326 | #[test] | ||
327 | fn test_rename_struct_field_for_shorthand() { | ||
328 | test_rename( | ||
329 | r#" | ||
330 | struct Foo { | ||
331 | i<|>: i32, | ||
332 | } | ||
333 | |||
334 | impl Foo { | ||
335 | fn new(i: i32) -> Self { | ||
336 | Self { i } | ||
337 | } | ||
338 | } | ||
339 | "#, | ||
340 | "j", | ||
341 | r#" | ||
342 | struct Foo { | ||
343 | j: i32, | ||
344 | } | ||
345 | |||
346 | impl Foo { | ||
347 | fn new(i: i32) -> Self { | ||
348 | Self { j: i } | ||
349 | } | ||
350 | } | ||
351 | "#, | ||
352 | ); | ||
353 | } | ||
354 | |||
355 | #[test] | ||
356 | fn test_rename_local_for_field_shorthand() { | ||
357 | test_rename( | ||
358 | r#" | ||
359 | struct Foo { | ||
360 | i: i32, | ||
361 | } | ||
362 | |||
363 | impl Foo { | ||
364 | fn new(i<|>: i32) -> Self { | ||
365 | Self { i } | ||
366 | } | ||
367 | } | ||
368 | "#, | ||
369 | "j", | ||
370 | r#" | ||
371 | struct Foo { | ||
372 | i: i32, | ||
373 | } | ||
374 | |||
375 | impl Foo { | ||
376 | fn new(j: i32) -> Self { | ||
377 | Self { i: j } | ||
378 | } | ||
379 | } | ||
380 | "#, | ||
381 | ); | ||
382 | } | ||
383 | |||
384 | #[test] | ||
385 | fn test_field_shorthand_correct_struct() { | ||
386 | test_rename( | ||
387 | r#" | ||
388 | struct Foo { | ||
389 | i<|>: i32, | ||
390 | } | ||
391 | |||
392 | struct Bar { | ||
393 | i: i32, | ||
394 | } | ||
395 | |||
396 | impl Bar { | ||
397 | fn new(i: i32) -> Self { | ||
398 | Self { i } | ||
399 | } | ||
400 | } | ||
401 | "#, | ||
402 | "j", | ||
403 | r#" | ||
404 | struct Foo { | ||
405 | j: i32, | ||
406 | } | ||
407 | |||
408 | struct Bar { | ||
409 | i: i32, | ||
410 | } | ||
411 | |||
412 | impl Bar { | ||
413 | fn new(i: i32) -> Self { | ||
414 | Self { i } | ||
415 | } | ||
416 | } | ||
417 | "#, | ||
418 | ); | ||
419 | } | ||
420 | |||
421 | #[test] | ||
422 | fn test_shadow_local_for_struct_shorthand() { | ||
423 | test_rename( | ||
424 | r#" | ||
425 | struct Foo { | ||
426 | i: i32, | ||
427 | } | ||
428 | |||
429 | fn baz(i<|>: i32) -> Self { | ||
430 | let x = Foo { i }; | ||
431 | { | ||
432 | let i = 0; | ||
433 | Foo { i } | ||
434 | } | ||
435 | } | ||
436 | "#, | ||
437 | "j", | ||
438 | r#" | ||
439 | struct Foo { | ||
440 | i: i32, | ||
441 | } | ||
442 | |||
443 | fn baz(j: i32) -> Self { | ||
444 | let x = Foo { i: j }; | ||
445 | { | ||
446 | let i = 0; | ||
447 | Foo { i } | ||
448 | } | ||
449 | } | ||
450 | "#, | ||
451 | ); | ||
452 | } | ||
453 | |||
454 | #[test] | ||
289 | fn test_rename_mod() { | 455 | fn test_rename_mod() { |
290 | let (analysis, position) = analysis_and_position( | 456 | let (analysis, position) = analysis_and_position( |
291 | " | 457 | " |
diff --git a/crates/ra_ide/src/typing.rs b/crates/ra_ide/src/typing.rs index 7f1b9150f..53c65f8bc 100644 --- a/crates/ra_ide/src/typing.rs +++ b/crates/ra_ide/src/typing.rs | |||
@@ -13,77 +13,21 @@ | |||
13 | //! Language server executes such typing assists synchronously. That is, they | 13 | //! Language server executes such typing assists synchronously. That is, they |
14 | //! block user's typing and should be pretty fast for this reason! | 14 | //! block user's typing and should be pretty fast for this reason! |
15 | 15 | ||
16 | mod on_enter; | ||
17 | |||
16 | use ra_db::{FilePosition, SourceDatabase}; | 18 | use ra_db::{FilePosition, SourceDatabase}; |
17 | use ra_fmt::leading_indent; | 19 | use ra_fmt::leading_indent; |
18 | use ra_ide_db::RootDatabase; | 20 | use ra_ide_db::RootDatabase; |
19 | use ra_syntax::{ | 21 | use ra_syntax::{ |
20 | algo::find_node_at_offset, | 22 | algo::find_node_at_offset, |
21 | ast::{self, AstToken}, | 23 | ast::{self, AstToken}, |
22 | AstNode, SmolStr, SourceFile, | 24 | AstNode, SourceFile, TextRange, TextUnit, |
23 | SyntaxKind::*, | ||
24 | SyntaxToken, TextRange, TextUnit, TokenAtOffset, | ||
25 | }; | 25 | }; |
26 | use ra_text_edit::TextEdit; | 26 | use ra_text_edit::TextEdit; |
27 | 27 | ||
28 | use crate::{source_change::SingleFileChange, SourceChange, SourceFileEdit}; | 28 | use crate::{source_change::SingleFileChange, SourceChange}; |
29 | |||
30 | pub(crate) fn on_enter(db: &RootDatabase, position: FilePosition) -> Option<SourceChange> { | ||
31 | let parse = db.parse(position.file_id); | ||
32 | let file = parse.tree(); | ||
33 | let comment = file | ||
34 | .syntax() | ||
35 | .token_at_offset(position.offset) | ||
36 | .left_biased() | ||
37 | .and_then(ast::Comment::cast)?; | ||
38 | |||
39 | if comment.kind().shape.is_block() { | ||
40 | return None; | ||
41 | } | ||
42 | |||
43 | let prefix = comment.prefix(); | ||
44 | let comment_range = comment.syntax().text_range(); | ||
45 | if position.offset < comment_range.start() + TextUnit::of_str(prefix) { | ||
46 | return None; | ||
47 | } | ||
48 | |||
49 | // Continuing non-doc line comments (like this one :) ) is annoying | ||
50 | if prefix == "//" && comment_range.end() == position.offset { | ||
51 | return None; | ||
52 | } | ||
53 | |||
54 | let indent = node_indent(&file, comment.syntax())?; | ||
55 | let inserted = format!("\n{}{} ", indent, prefix); | ||
56 | let cursor_position = position.offset + TextUnit::of_str(&inserted); | ||
57 | let edit = TextEdit::insert(position.offset, inserted); | ||
58 | 29 | ||
59 | Some( | 30 | pub(crate) use on_enter::on_enter; |
60 | SourceChange::source_file_edit( | ||
61 | "on enter", | ||
62 | SourceFileEdit { edit, file_id: position.file_id }, | ||
63 | ) | ||
64 | .with_cursor(FilePosition { offset: cursor_position, file_id: position.file_id }), | ||
65 | ) | ||
66 | } | ||
67 | |||
68 | fn node_indent(file: &SourceFile, token: &SyntaxToken) -> Option<SmolStr> { | ||
69 | let ws = match file.syntax().token_at_offset(token.text_range().start()) { | ||
70 | TokenAtOffset::Between(l, r) => { | ||
71 | assert!(r == *token); | ||
72 | l | ||
73 | } | ||
74 | TokenAtOffset::Single(n) => { | ||
75 | assert!(n == *token); | ||
76 | return Some("".into()); | ||
77 | } | ||
78 | TokenAtOffset::None => unreachable!(), | ||
79 | }; | ||
80 | if ws.kind() != WHITESPACE { | ||
81 | return None; | ||
82 | } | ||
83 | let text = ws.text(); | ||
84 | let pos = text.rfind('\n').map(|it| it + 1).unwrap_or(0); | ||
85 | Some(text[pos..].into()) | ||
86 | } | ||
87 | 31 | ||
88 | pub(crate) const TRIGGER_CHARS: &str = ".=>"; | 32 | pub(crate) const TRIGGER_CHARS: &str = ".=>"; |
89 | 33 | ||
@@ -196,102 +140,10 @@ fn on_arrow_typed(file: &SourceFile, offset: TextUnit) -> Option<SingleFileChang | |||
196 | 140 | ||
197 | #[cfg(test)] | 141 | #[cfg(test)] |
198 | mod tests { | 142 | mod tests { |
199 | use test_utils::{add_cursor, assert_eq_text, extract_offset}; | 143 | use test_utils::{assert_eq_text, extract_offset}; |
200 | |||
201 | use crate::mock_analysis::single_file; | ||
202 | 144 | ||
203 | use super::*; | 145 | use super::*; |
204 | 146 | ||
205 | #[test] | ||
206 | fn test_on_enter() { | ||
207 | fn apply_on_enter(before: &str) -> Option<String> { | ||
208 | let (offset, before) = extract_offset(before); | ||
209 | let (analysis, file_id) = single_file(&before); | ||
210 | let result = analysis.on_enter(FilePosition { offset, file_id }).unwrap()?; | ||
211 | |||
212 | assert_eq!(result.source_file_edits.len(), 1); | ||
213 | let actual = result.source_file_edits[0].edit.apply(&before); | ||
214 | let actual = add_cursor(&actual, result.cursor_position.unwrap().offset); | ||
215 | Some(actual) | ||
216 | } | ||
217 | |||
218 | fn do_check(before: &str, after: &str) { | ||
219 | let actual = apply_on_enter(before).unwrap(); | ||
220 | assert_eq_text!(after, &actual); | ||
221 | } | ||
222 | |||
223 | fn do_check_noop(text: &str) { | ||
224 | assert!(apply_on_enter(text).is_none()) | ||
225 | } | ||
226 | |||
227 | do_check( | ||
228 | r" | ||
229 | /// Some docs<|> | ||
230 | fn foo() { | ||
231 | } | ||
232 | ", | ||
233 | r" | ||
234 | /// Some docs | ||
235 | /// <|> | ||
236 | fn foo() { | ||
237 | } | ||
238 | ", | ||
239 | ); | ||
240 | do_check( | ||
241 | r" | ||
242 | impl S { | ||
243 | /// Some<|> docs. | ||
244 | fn foo() {} | ||
245 | } | ||
246 | ", | ||
247 | r" | ||
248 | impl S { | ||
249 | /// Some | ||
250 | /// <|> docs. | ||
251 | fn foo() {} | ||
252 | } | ||
253 | ", | ||
254 | ); | ||
255 | do_check( | ||
256 | r" | ||
257 | fn main() { | ||
258 | // Fix<|> me | ||
259 | let x = 1 + 1; | ||
260 | } | ||
261 | ", | ||
262 | r" | ||
263 | fn main() { | ||
264 | // Fix | ||
265 | // <|> me | ||
266 | let x = 1 + 1; | ||
267 | } | ||
268 | ", | ||
269 | ); | ||
270 | do_check( | ||
271 | r" | ||
272 | ///<|> Some docs | ||
273 | fn foo() { | ||
274 | } | ||
275 | ", | ||
276 | r" | ||
277 | /// | ||
278 | /// <|> Some docs | ||
279 | fn foo() { | ||
280 | } | ||
281 | ", | ||
282 | ); | ||
283 | do_check_noop( | ||
284 | r" | ||
285 | fn main() { | ||
286 | // Fix me<|> | ||
287 | let x = 1 + 1; | ||
288 | } | ||
289 | ", | ||
290 | ); | ||
291 | |||
292 | do_check_noop(r"<|>//! docz"); | ||
293 | } | ||
294 | |||
295 | fn do_type_char(char_typed: char, before: &str) -> Option<(String, SingleFileChange)> { | 147 | fn do_type_char(char_typed: char, before: &str) -> Option<(String, SingleFileChange)> { |
296 | let (offset, before) = extract_offset(before); | 148 | let (offset, before) = extract_offset(before); |
297 | let edit = TextEdit::insert(offset, char_typed.to_string()); | 149 | let edit = TextEdit::insert(offset, char_typed.to_string()); |
diff --git a/crates/ra_ide/src/typing/on_enter.rs b/crates/ra_ide/src/typing/on_enter.rs new file mode 100644 index 000000000..6bcf2d72b --- /dev/null +++ b/crates/ra_ide/src/typing/on_enter.rs | |||
@@ -0,0 +1,216 @@ | |||
1 | //! Handles the `Enter` key press. At the momently, this only continues | ||
2 | //! comments, but should handle indent some time in the future as well. | ||
3 | |||
4 | use ra_db::{FilePosition, SourceDatabase}; | ||
5 | use ra_ide_db::RootDatabase; | ||
6 | use ra_syntax::{ | ||
7 | ast::{self, AstToken}, | ||
8 | AstNode, SmolStr, SourceFile, | ||
9 | SyntaxKind::*, | ||
10 | SyntaxToken, TextUnit, TokenAtOffset, | ||
11 | }; | ||
12 | use ra_text_edit::TextEdit; | ||
13 | |||
14 | use crate::{SourceChange, SourceFileEdit}; | ||
15 | |||
16 | pub(crate) fn on_enter(db: &RootDatabase, position: FilePosition) -> Option<SourceChange> { | ||
17 | let parse = db.parse(position.file_id); | ||
18 | let file = parse.tree(); | ||
19 | let comment = file | ||
20 | .syntax() | ||
21 | .token_at_offset(position.offset) | ||
22 | .left_biased() | ||
23 | .and_then(ast::Comment::cast)?; | ||
24 | |||
25 | if comment.kind().shape.is_block() { | ||
26 | return None; | ||
27 | } | ||
28 | |||
29 | let prefix = comment.prefix(); | ||
30 | let comment_range = comment.syntax().text_range(); | ||
31 | if position.offset < comment_range.start() + TextUnit::of_str(prefix) { | ||
32 | return None; | ||
33 | } | ||
34 | |||
35 | // Continuing single-line non-doc comments (like this one :) ) is annoying | ||
36 | if prefix == "//" && comment_range.end() == position.offset && !followed_by_comment(&comment) { | ||
37 | return None; | ||
38 | } | ||
39 | |||
40 | let indent = node_indent(&file, comment.syntax())?; | ||
41 | let inserted = format!("\n{}{} ", indent, prefix); | ||
42 | let cursor_position = position.offset + TextUnit::of_str(&inserted); | ||
43 | let edit = TextEdit::insert(position.offset, inserted); | ||
44 | |||
45 | Some( | ||
46 | SourceChange::source_file_edit( | ||
47 | "on enter", | ||
48 | SourceFileEdit { edit, file_id: position.file_id }, | ||
49 | ) | ||
50 | .with_cursor(FilePosition { offset: cursor_position, file_id: position.file_id }), | ||
51 | ) | ||
52 | } | ||
53 | |||
54 | fn followed_by_comment(comment: &ast::Comment) -> bool { | ||
55 | let ws = match comment.syntax().next_token().and_then(ast::Whitespace::cast) { | ||
56 | Some(it) => it, | ||
57 | None => return false, | ||
58 | }; | ||
59 | if ws.spans_multiple_lines() { | ||
60 | return false; | ||
61 | } | ||
62 | ws.syntax().next_token().and_then(ast::Comment::cast).is_some() | ||
63 | } | ||
64 | |||
65 | fn node_indent(file: &SourceFile, token: &SyntaxToken) -> Option<SmolStr> { | ||
66 | let ws = match file.syntax().token_at_offset(token.text_range().start()) { | ||
67 | TokenAtOffset::Between(l, r) => { | ||
68 | assert!(r == *token); | ||
69 | l | ||
70 | } | ||
71 | TokenAtOffset::Single(n) => { | ||
72 | assert!(n == *token); | ||
73 | return Some("".into()); | ||
74 | } | ||
75 | TokenAtOffset::None => unreachable!(), | ||
76 | }; | ||
77 | if ws.kind() != WHITESPACE { | ||
78 | return None; | ||
79 | } | ||
80 | let text = ws.text(); | ||
81 | let pos = text.rfind('\n').map(|it| it + 1).unwrap_or(0); | ||
82 | Some(text[pos..].into()) | ||
83 | } | ||
84 | |||
85 | #[cfg(test)] | ||
86 | mod tests { | ||
87 | use test_utils::{add_cursor, assert_eq_text, extract_offset}; | ||
88 | |||
89 | use crate::mock_analysis::single_file; | ||
90 | |||
91 | use super::*; | ||
92 | |||
93 | fn apply_on_enter(before: &str) -> Option<String> { | ||
94 | let (offset, before) = extract_offset(before); | ||
95 | let (analysis, file_id) = single_file(&before); | ||
96 | let result = analysis.on_enter(FilePosition { offset, file_id }).unwrap()?; | ||
97 | |||
98 | assert_eq!(result.source_file_edits.len(), 1); | ||
99 | let actual = result.source_file_edits[0].edit.apply(&before); | ||
100 | let actual = add_cursor(&actual, result.cursor_position.unwrap().offset); | ||
101 | Some(actual) | ||
102 | } | ||
103 | |||
104 | fn do_check(ra_fixture_before: &str, ra_fixture_after: &str) { | ||
105 | let actual = apply_on_enter(ra_fixture_before).unwrap(); | ||
106 | assert_eq_text!(ra_fixture_after, &actual); | ||
107 | } | ||
108 | |||
109 | fn do_check_noop(ra_fixture_text: &str) { | ||
110 | assert!(apply_on_enter(ra_fixture_text).is_none()) | ||
111 | } | ||
112 | |||
113 | #[test] | ||
114 | fn continues_doc_comment() { | ||
115 | do_check( | ||
116 | r" | ||
117 | /// Some docs<|> | ||
118 | fn foo() { | ||
119 | } | ||
120 | ", | ||
121 | r" | ||
122 | /// Some docs | ||
123 | /// <|> | ||
124 | fn foo() { | ||
125 | } | ||
126 | ", | ||
127 | ); | ||
128 | |||
129 | do_check( | ||
130 | r" | ||
131 | impl S { | ||
132 | /// Some<|> docs. | ||
133 | fn foo() {} | ||
134 | } | ||
135 | ", | ||
136 | r" | ||
137 | impl S { | ||
138 | /// Some | ||
139 | /// <|> docs. | ||
140 | fn foo() {} | ||
141 | } | ||
142 | ", | ||
143 | ); | ||
144 | |||
145 | do_check( | ||
146 | r" | ||
147 | ///<|> Some docs | ||
148 | fn foo() { | ||
149 | } | ||
150 | ", | ||
151 | r" | ||
152 | /// | ||
153 | /// <|> Some docs | ||
154 | fn foo() { | ||
155 | } | ||
156 | ", | ||
157 | ); | ||
158 | } | ||
159 | |||
160 | #[test] | ||
161 | fn does_not_continue_before_doc_comment() { | ||
162 | do_check_noop(r"<|>//! docz"); | ||
163 | } | ||
164 | |||
165 | #[test] | ||
166 | fn continues_code_comment_in_the_middle_of_line() { | ||
167 | do_check( | ||
168 | r" | ||
169 | fn main() { | ||
170 | // Fix<|> me | ||
171 | let x = 1 + 1; | ||
172 | } | ||
173 | ", | ||
174 | r" | ||
175 | fn main() { | ||
176 | // Fix | ||
177 | // <|> me | ||
178 | let x = 1 + 1; | ||
179 | } | ||
180 | ", | ||
181 | ); | ||
182 | } | ||
183 | |||
184 | #[test] | ||
185 | fn continues_code_comment_in_the_middle_several_lines() { | ||
186 | do_check( | ||
187 | r" | ||
188 | fn main() { | ||
189 | // Fix<|> | ||
190 | // me | ||
191 | let x = 1 + 1; | ||
192 | } | ||
193 | ", | ||
194 | r" | ||
195 | fn main() { | ||
196 | // Fix | ||
197 | // <|> | ||
198 | // me | ||
199 | let x = 1 + 1; | ||
200 | } | ||
201 | ", | ||
202 | ); | ||
203 | } | ||
204 | |||
205 | #[test] | ||
206 | fn does_not_continue_end_of_code_comment() { | ||
207 | do_check_noop( | ||
208 | r" | ||
209 | fn main() { | ||
210 | // Fix me<|> | ||
211 | let x = 1 + 1; | ||
212 | } | ||
213 | ", | ||
214 | ); | ||
215 | } | ||
216 | } | ||