diff options
Diffstat (limited to 'crates/ide/src/completion/test_utils.rs')
-rw-r--r-- | crates/ide/src/completion/test_utils.rs | 114 |
1 files changed, 114 insertions, 0 deletions
diff --git a/crates/ide/src/completion/test_utils.rs b/crates/ide/src/completion/test_utils.rs new file mode 100644 index 000000000..1452d7e9e --- /dev/null +++ b/crates/ide/src/completion/test_utils.rs | |||
@@ -0,0 +1,114 @@ | |||
1 | //! Runs completion for testing purposes. | ||
2 | |||
3 | use hir::Semantics; | ||
4 | use itertools::Itertools; | ||
5 | use stdx::{format_to, trim_indent}; | ||
6 | use syntax::{AstNode, NodeOrToken, SyntaxElement}; | ||
7 | use test_utils::assert_eq_text; | ||
8 | |||
9 | use crate::{ | ||
10 | completion::{completion_item::CompletionKind, CompletionConfig}, | ||
11 | mock_analysis::analysis_and_position, | ||
12 | CompletionItem, | ||
13 | }; | ||
14 | |||
15 | pub(crate) fn do_completion(code: &str, kind: CompletionKind) -> Vec<CompletionItem> { | ||
16 | do_completion_with_config(CompletionConfig::default(), code, kind) | ||
17 | } | ||
18 | |||
19 | pub(crate) fn do_completion_with_config( | ||
20 | config: CompletionConfig, | ||
21 | code: &str, | ||
22 | kind: CompletionKind, | ||
23 | ) -> Vec<CompletionItem> { | ||
24 | let mut kind_completions: Vec<CompletionItem> = get_all_completion_items(config, code) | ||
25 | .into_iter() | ||
26 | .filter(|c| c.completion_kind == kind) | ||
27 | .collect(); | ||
28 | kind_completions.sort_by(|l, r| l.label().cmp(r.label())); | ||
29 | kind_completions | ||
30 | } | ||
31 | |||
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(); | ||
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); | ||
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() | ||
114 | } | ||