diff options
Diffstat (limited to 'crates/ra_ide/src/completion/test_utils.rs')
-rw-r--r-- | crates/ra_ide/src/completion/test_utils.rs | 111 |
1 files changed, 98 insertions, 13 deletions
diff --git a/crates/ra_ide/src/completion/test_utils.rs b/crates/ra_ide/src/completion/test_utils.rs index bf22452a2..919177745 100644 --- a/crates/ra_ide/src/completion/test_utils.rs +++ b/crates/ra_ide/src/completion/test_utils.rs | |||
@@ -1,29 +1,114 @@ | |||
1 | //! Runs completion for testing purposes. | 1 | //! Runs completion for testing purposes. |
2 | 2 | ||
3 | use hir::Semantics; | ||
4 | use itertools::Itertools; | ||
5 | use ra_syntax::{AstNode, NodeOrToken, SyntaxElement}; | ||
6 | use stdx::{format_to, trim_indent}; | ||
7 | use test_utils::assert_eq_text; | ||
8 | |||
3 | use crate::{ | 9 | use crate::{ |
4 | completion::{completion_item::CompletionKind, CompletionConfig}, | 10 | completion::{completion_item::CompletionKind, CompletionConfig}, |
5 | mock_analysis::{analysis_and_position, single_file_with_position}, | 11 | mock_analysis::analysis_and_position, |
6 | CompletionItem, | 12 | CompletionItem, |
7 | }; | 13 | }; |
8 | 14 | ||
9 | pub(crate) fn do_completion(code: &str, kind: CompletionKind) -> Vec<CompletionItem> { | 15 | pub(crate) fn do_completion(code: &str, kind: CompletionKind) -> Vec<CompletionItem> { |
10 | do_completion_with_options(code, kind, &CompletionConfig::default()) | 16 | do_completion_with_config(CompletionConfig::default(), code, kind) |
11 | } | 17 | } |
12 | 18 | ||
13 | pub(crate) fn do_completion_with_options( | 19 | pub(crate) fn do_completion_with_config( |
20 | config: CompletionConfig, | ||
14 | code: &str, | 21 | code: &str, |
15 | kind: CompletionKind, | 22 | kind: CompletionKind, |
16 | options: &CompletionConfig, | ||
17 | ) -> Vec<CompletionItem> { | 23 | ) -> Vec<CompletionItem> { |
18 | let (analysis, position) = if code.contains("//-") { | 24 | let mut kind_completions: Vec<CompletionItem> = get_all_completion_items(config, code) |
19 | analysis_and_position(code) | 25 | .into_iter() |
20 | } else { | 26 | .filter(|c| c.completion_kind == kind) |
21 | single_file_with_position(code) | 27 | .collect(); |
22 | }; | 28 | kind_completions.sort_by(|l, r| l.label().cmp(r.label())); |
23 | let completions = analysis.completions(options, position).unwrap().unwrap(); | 29 | kind_completions |
24 | let completion_items: Vec<CompletionItem> = completions.into(); | 30 | } |
25 | let mut kind_completions: Vec<CompletionItem> = | 31 | |
26 | completion_items.into_iter().filter(|c| c.completion_kind == kind).collect(); | 32 | pub(crate) fn completion_list(code: &str, kind: CompletionKind) -> String { |
33 | completion_list_with_config(CompletionConfig::default(), code, kind) | ||
34 | } | ||
35 | |||
36 | pub(crate) fn completion_list_with_config( | ||
37 | config: CompletionConfig, | ||
38 | code: &str, | ||
39 | kind: CompletionKind, | ||
40 | ) -> String { | ||
41 | let mut kind_completions: Vec<CompletionItem> = get_all_completion_items(config, code) | ||
42 | .into_iter() | ||
43 | .filter(|c| c.completion_kind == kind) | ||
44 | .collect(); | ||
27 | kind_completions.sort_by_key(|c| c.label().to_owned()); | 45 | kind_completions.sort_by_key(|c| c.label().to_owned()); |
46 | let label_width = kind_completions | ||
47 | .iter() | ||
48 | .map(|it| monospace_width(it.label())) | ||
49 | .max() | ||
50 | .unwrap_or_default() | ||
51 | .min(16); | ||
28 | kind_completions | 52 | kind_completions |
53 | .into_iter() | ||
54 | .map(|it| { | ||
55 | let tag = it.kind().unwrap().tag(); | ||
56 | let var_name = format!("{} {}", tag, it.label()); | ||
57 | let mut buf = var_name; | ||
58 | if let Some(detail) = it.detail() { | ||
59 | let width = label_width.saturating_sub(monospace_width(it.label())); | ||
60 | format_to!(buf, "{:width$} {}", "", detail, width = width); | ||
61 | } | ||
62 | format_to!(buf, "\n"); | ||
63 | buf | ||
64 | }) | ||
65 | .collect() | ||
66 | } | ||
67 | |||
68 | fn monospace_width(s: &str) -> usize { | ||
69 | s.chars().count() | ||
70 | } | ||
71 | |||
72 | pub(crate) fn check_edit(what: &str, ra_fixture_before: &str, ra_fixture_after: &str) { | ||
73 | check_edit_with_config(CompletionConfig::default(), what, ra_fixture_before, ra_fixture_after) | ||
74 | } | ||
75 | |||
76 | pub(crate) fn check_edit_with_config( | ||
77 | config: CompletionConfig, | ||
78 | what: &str, | ||
79 | ra_fixture_before: &str, | ||
80 | ra_fixture_after: &str, | ||
81 | ) { | ||
82 | let ra_fixture_after = trim_indent(ra_fixture_after); | ||
83 | let (analysis, position) = analysis_and_position(ra_fixture_before); | ||
84 | let completions: Vec<CompletionItem> = | ||
85 | analysis.completions(&config, position).unwrap().unwrap().into(); | ||
86 | let (completion,) = completions | ||
87 | .iter() | ||
88 | .filter(|it| it.lookup() == what) | ||
89 | .collect_tuple() | ||
90 | .unwrap_or_else(|| panic!("can't find {:?} completion in {:#?}", what, completions)); | ||
91 | let mut actual = analysis.file_text(position.file_id).unwrap().to_string(); | ||
92 | completion.text_edit().apply(&mut actual); | ||
93 | assert_eq_text!(&ra_fixture_after, &actual) | ||
94 | } | ||
95 | |||
96 | pub(crate) fn check_pattern_is_applicable(code: &str, check: fn(SyntaxElement) -> bool) { | ||
97 | let (analysis, pos) = analysis_and_position(code); | ||
98 | analysis | ||
99 | .with_db(|db| { | ||
100 | let sema = Semantics::new(db); | ||
101 | let original_file = sema.parse(pos.file_id); | ||
102 | let token = original_file.syntax().token_at_offset(pos.offset).left_biased().unwrap(); | ||
103 | assert!(check(NodeOrToken::Token(token))); | ||
104 | }) | ||
105 | .unwrap(); | ||
106 | } | ||
107 | |||
108 | pub(crate) fn get_all_completion_items( | ||
109 | config: CompletionConfig, | ||
110 | code: &str, | ||
111 | ) -> Vec<CompletionItem> { | ||
112 | let (analysis, position) = analysis_and_position(code); | ||
113 | analysis.completions(&config, position).unwrap().unwrap().into() | ||
29 | } | 114 | } |