aboutsummaryrefslogtreecommitdiff
path: root/crates/completion/src/test_utils.rs
diff options
context:
space:
mode:
authorbors[bot] <26634292+bors[bot]@users.noreply.github.com>2020-10-18 11:41:46 +0100
committerGitHub <[email protected]>2020-10-18 11:41:46 +0100
commit886cfd68212bb0b4487d6a822476c350a6eb114f (patch)
tree5b144eabe1eaf62aa1ec5b804ee6fff00f5f84e9 /crates/completion/src/test_utils.rs
parent2067a410f31810f6e1941a86cdea0247c3b7d6f4 (diff)
parent9e7c952bbddc2e6763c49f0511a295362e9893d6 (diff)
Merge #6276
6276: Extract call_info and completion into separate crates r=matklad a=popzxc As it was discussed in [zulip](https://rust-lang.zulipchat.com/#narrow/stream/185405-t-compiler.2Fwg-rls-2.2E0/topic/Completion.20refactoring), we need to move `completions` into a separate crate. Unfortunately, the dependency on `call_info::ActiveParameter` doesn't look easy to get rid of, and it seems to be a topic for a separate PR, thus I also extracted `call_info` into a separate crate (on which both `ide` and `completion` crates depend). Additionally, a few `FIXME`s in doc-comments were resolved in order to make `tidy` happy. Co-authored-by: Igor Aleksanov <[email protected]>
Diffstat (limited to 'crates/completion/src/test_utils.rs')
-rw-r--r--crates/completion/src/test_utils.rs130
1 files changed, 130 insertions, 0 deletions
diff --git a/crates/completion/src/test_utils.rs b/crates/completion/src/test_utils.rs
new file mode 100644
index 000000000..f2cf2561f
--- /dev/null
+++ b/crates/completion/src/test_utils.rs
@@ -0,0 +1,130 @@
1//! Runs completion for testing purposes.
2
3use base_db::{fixture::ChangeFixture, FileLoader, FilePosition};
4use hir::Semantics;
5use ide_db::RootDatabase;
6use itertools::Itertools;
7use stdx::{format_to, trim_indent};
8use syntax::{AstNode, NodeOrToken, SyntaxElement};
9use test_utils::{assert_eq_text, RangeOrOffset};
10
11use crate::{completion_item::CompletionKind, CompletionConfig, CompletionItem};
12
13/// Creates analysis from a multi-file fixture, returns positions marked with <|>.
14pub(crate) fn position(ra_fixture: &str) -> (RootDatabase, FilePosition) {
15 let change_fixture = ChangeFixture::parse(ra_fixture);
16 let mut database = RootDatabase::default();
17 database.apply_change(change_fixture.change);
18 let (file_id, range_or_offset) = change_fixture.file_position.expect("expected a marker (<|>)");
19 let offset = match range_or_offset {
20 RangeOrOffset::Range(_) => panic!(),
21 RangeOrOffset::Offset(it) => it,
22 };
23 (database, FilePosition { file_id, offset })
24}
25
26pub(crate) fn do_completion(code: &str, kind: CompletionKind) -> Vec<CompletionItem> {
27 do_completion_with_config(CompletionConfig::default(), code, kind)
28}
29
30pub(crate) fn do_completion_with_config(
31 config: CompletionConfig,
32 code: &str,
33 kind: CompletionKind,
34) -> Vec<CompletionItem> {
35 let mut kind_completions: Vec<CompletionItem> = get_all_completion_items(config, code)
36 .into_iter()
37 .filter(|c| c.completion_kind == kind)
38 .collect();
39 kind_completions.sort_by(|l, r| l.label().cmp(r.label()));
40 kind_completions
41}
42
43pub(crate) fn completion_list(code: &str, kind: CompletionKind) -> String {
44 completion_list_with_config(CompletionConfig::default(), code, kind)
45}
46
47pub(crate) fn completion_list_with_config(
48 config: CompletionConfig,
49 code: &str,
50 kind: CompletionKind,
51) -> String {
52 let mut kind_completions: Vec<CompletionItem> = get_all_completion_items(config, code)
53 .into_iter()
54 .filter(|c| c.completion_kind == kind)
55 .collect();
56 kind_completions.sort_by_key(|c| c.label().to_owned());
57 let label_width = kind_completions
58 .iter()
59 .map(|it| monospace_width(it.label()))
60 .max()
61 .unwrap_or_default()
62 .min(16);
63 kind_completions
64 .into_iter()
65 .map(|it| {
66 let tag = it.kind().unwrap().tag();
67 let var_name = format!("{} {}", tag, it.label());
68 let mut buf = var_name;
69 if let Some(detail) = it.detail() {
70 let width = label_width.saturating_sub(monospace_width(it.label()));
71 format_to!(buf, "{:width$} {}", "", detail, width = width);
72 }
73 format_to!(buf, "\n");
74 buf
75 })
76 .collect()
77}
78
79fn monospace_width(s: &str) -> usize {
80 s.chars().count()
81}
82
83pub(crate) fn check_edit(what: &str, ra_fixture_before: &str, ra_fixture_after: &str) {
84 check_edit_with_config(CompletionConfig::default(), what, ra_fixture_before, ra_fixture_after)
85}
86
87pub(crate) fn check_edit_with_config(
88 config: CompletionConfig,
89 what: &str,
90 ra_fixture_before: &str,
91 ra_fixture_after: &str,
92) {
93 let ra_fixture_after = trim_indent(ra_fixture_after);
94 let (db, position) = position(ra_fixture_before);
95 let completions: Vec<CompletionItem> =
96 crate::completions(&db, &config, position).unwrap().into();
97 let (completion,) = completions
98 .iter()
99 .filter(|it| it.lookup() == what)
100 .collect_tuple()
101 .unwrap_or_else(|| panic!("can't find {:?} completion in {:#?}", what, completions));
102 let mut actual = db.file_text(position.file_id).to_string();
103 completion.text_edit().apply(&mut actual);
104 assert_eq_text!(&ra_fixture_after, &actual)
105}
106
107pub(crate) fn check_pattern_is_applicable(code: &str, check: fn(SyntaxElement) -> bool) {
108 let (db, pos) = position(code);
109
110 let sema = Semantics::new(&db);
111 let original_file = sema.parse(pos.file_id);
112 let token = original_file.syntax().token_at_offset(pos.offset).left_biased().unwrap();
113 assert!(check(NodeOrToken::Token(token)));
114}
115
116pub(crate) fn check_pattern_is_not_applicable(code: &str, check: fn(SyntaxElement) -> bool) {
117 let (db, pos) = position(code);
118 let sema = Semantics::new(&db);
119 let original_file = sema.parse(pos.file_id);
120 let token = original_file.syntax().token_at_offset(pos.offset).left_biased().unwrap();
121 assert!(!check(NodeOrToken::Token(token)));
122}
123
124pub(crate) fn get_all_completion_items(
125 config: CompletionConfig,
126 code: &str,
127) -> Vec<CompletionItem> {
128 let (db, position) = position(code);
129 crate::completions(&db, &config, position).unwrap().into()
130}