Skip to content

Commit e4ead8a

Browse files
committed
Auto merge of rust-lang#12412 - yue4u:fix/visibility-completion, r=Veykril
fix: Retrigger visibility completion after parentheses close rust-lang#12390 This PR add `(` to trigger_characters as discussed in original issue. Some questions: 1. Is lsp's `ctx.trigger_character` from `params.context` is the same as `ctx.original_token` inside actually completions? 1. If not what's the difference? 2. if they are the same, it's unnecessary to pass it down from handler at all. 3. if they are the same, maybe we could parse it from fixture directly instead of using the `check_with_trigger_character` I added. 2. Some completion fixtures written as `($0)` ( https://github.com/rust-lang/rust-analyzer/blob/master/crates/ide-completion/src/tests/fn_param.rs#L105 as an example), If I understand correctly they are not invoked outside tests at all? 1. using `ctx.original_token` directly would break these tests as well as parsing trigger_character from fixture for now. 2. I think it make sense to allow `(` triggering these cases? 3. I hope this line up with rust-lang#12144
2 parents f94fa62 + 1b5f046 commit e4ead8a

File tree

9 files changed

+103
-57
lines changed

9 files changed

+103
-57
lines changed

crates/ide-completion/src/lib.rs

+28-24
Original file line numberDiff line numberDiff line change
@@ -143,36 +143,40 @@ pub fn completions(
143143
db: &RootDatabase,
144144
config: &CompletionConfig,
145145
position: FilePosition,
146+
trigger_character: Option<&str>,
146147
) -> Option<Completions> {
147148
let ctx = &CompletionContext::new(db, position, config)?;
148149
let mut acc = Completions::default();
149150

150151
{
151152
let acc = &mut acc;
152-
completions::attribute::complete_attribute(acc, ctx);
153-
completions::attribute::complete_derive(acc, ctx);
154-
completions::attribute::complete_known_attribute_input(acc, ctx);
155-
completions::dot::complete_dot(acc, ctx);
156-
completions::expr::complete_expr_path(acc, ctx);
157-
completions::extern_abi::complete_extern_abi(acc, ctx);
158-
completions::flyimport::import_on_the_fly(acc, ctx);
159-
completions::fn_param::complete_fn_param(acc, ctx);
160-
completions::format_string::format_string(acc, ctx);
161-
completions::item_list::complete_item_list(acc, ctx);
162-
completions::keyword::complete_expr_keyword(acc, ctx);
163-
completions::lifetime::complete_label(acc, ctx);
164-
completions::lifetime::complete_lifetime(acc, ctx);
165-
completions::mod_::complete_mod(acc, ctx);
166-
completions::pattern::complete_pattern(acc, ctx);
167-
completions::postfix::complete_postfix(acc, ctx);
168-
completions::record::complete_record_literal(acc, ctx);
169-
completions::record::complete_record(acc, ctx);
170-
completions::snippet::complete_expr_snippet(acc, ctx);
171-
completions::snippet::complete_item_snippet(acc, ctx);
172-
completions::trait_impl::complete_trait_impl(acc, ctx);
173-
completions::r#type::complete_type_path(acc, ctx);
174-
completions::r#type::complete_inferred_type(acc, ctx);
175-
completions::use_::complete_use_tree(acc, ctx);
153+
// prevent `(` from triggering unwanted completion noise
154+
if trigger_character != Some("(") {
155+
completions::attribute::complete_attribute(acc, ctx);
156+
completions::attribute::complete_derive(acc, ctx);
157+
completions::attribute::complete_known_attribute_input(acc, ctx);
158+
completions::dot::complete_dot(acc, ctx);
159+
completions::expr::complete_expr_path(acc, ctx);
160+
completions::extern_abi::complete_extern_abi(acc, ctx);
161+
completions::flyimport::import_on_the_fly(acc, ctx);
162+
completions::fn_param::complete_fn_param(acc, ctx);
163+
completions::format_string::format_string(acc, ctx);
164+
completions::item_list::complete_item_list(acc, ctx);
165+
completions::keyword::complete_expr_keyword(acc, ctx);
166+
completions::lifetime::complete_label(acc, ctx);
167+
completions::lifetime::complete_lifetime(acc, ctx);
168+
completions::mod_::complete_mod(acc, ctx);
169+
completions::pattern::complete_pattern(acc, ctx);
170+
completions::postfix::complete_postfix(acc, ctx);
171+
completions::record::complete_record_literal(acc, ctx);
172+
completions::record::complete_record(acc, ctx);
173+
completions::snippet::complete_expr_snippet(acc, ctx);
174+
completions::snippet::complete_item_snippet(acc, ctx);
175+
completions::trait_impl::complete_trait_impl(acc, ctx);
176+
completions::r#type::complete_type_path(acc, ctx);
177+
completions::r#type::complete_inferred_type(acc, ctx);
178+
completions::use_::complete_use_tree(acc, ctx);
179+
}
176180
completions::vis::complete_vis_path(acc, ctx);
177181
}
178182

crates/ide-completion/src/render.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -410,15 +410,15 @@ mod tests {
410410

411411
#[track_caller]
412412
fn check_relevance_for_kinds(ra_fixture: &str, kinds: &[CompletionItemKind], expect: Expect) {
413-
let mut actual = get_all_items(TEST_CONFIG, ra_fixture);
413+
let mut actual = get_all_items(TEST_CONFIG, ra_fixture, None);
414414
actual.retain(|it| kinds.contains(&it.kind()));
415415
actual.sort_by_key(|it| cmp::Reverse(it.relevance().score()));
416416
check_relevance_(actual, expect);
417417
}
418418

419419
#[track_caller]
420420
fn check_relevance(ra_fixture: &str, expect: Expect) {
421-
let mut actual = get_all_items(TEST_CONFIG, ra_fixture);
421+
let mut actual = get_all_items(TEST_CONFIG, ra_fixture, None);
422422
actual.retain(|it| it.kind() != CompletionItemKind::Snippet);
423423
actual.retain(|it| it.kind() != CompletionItemKind::Keyword);
424424
actual.retain(|it| it.kind() != CompletionItemKind::BuiltinType);

crates/ide-completion/src/tests.rs

+20-7
Original file line numberDiff line numberDiff line change
@@ -79,20 +79,28 @@ pub(crate) const TEST_CONFIG: CompletionConfig = CompletionConfig {
7979
};
8080

8181
pub(crate) fn completion_list(ra_fixture: &str) -> String {
82-
completion_list_with_config(TEST_CONFIG, ra_fixture, true)
82+
completion_list_with_config(TEST_CONFIG, ra_fixture, true, None)
8383
}
8484

8585
pub(crate) fn completion_list_no_kw(ra_fixture: &str) -> String {
86-
completion_list_with_config(TEST_CONFIG, ra_fixture, false)
86+
completion_list_with_config(TEST_CONFIG, ra_fixture, false, None)
87+
}
88+
89+
pub(crate) fn completion_list_with_trigger_character(
90+
ra_fixture: &str,
91+
trigger_character: Option<&str>,
92+
) -> String {
93+
completion_list_with_config(TEST_CONFIG, ra_fixture, true, trigger_character)
8794
}
8895

8996
fn completion_list_with_config(
9097
config: CompletionConfig,
9198
ra_fixture: &str,
9299
include_keywords: bool,
100+
trigger_character: Option<&str>,
93101
) -> String {
94102
// filter out all but one builtintype completion for smaller test outputs
95-
let items = get_all_items(config, ra_fixture);
103+
let items = get_all_items(config, ra_fixture, trigger_character);
96104
let mut bt_seen = false;
97105
let items = items
98106
.into_iter()
@@ -126,7 +134,7 @@ pub(crate) fn do_completion_with_config(
126134
code: &str,
127135
kind: CompletionItemKind,
128136
) -> Vec<CompletionItem> {
129-
get_all_items(config, code)
137+
get_all_items(config, code, None)
130138
.into_iter()
131139
.filter(|c| c.kind() == kind)
132140
.sorted_by(|l, r| l.label().cmp(r.label()))
@@ -173,7 +181,7 @@ pub(crate) fn check_edit_with_config(
173181
let ra_fixture_after = trim_indent(ra_fixture_after);
174182
let (db, position) = position(ra_fixture_before);
175183
let completions: Vec<CompletionItem> =
176-
crate::completions(&db, &config, position).unwrap().into();
184+
crate::completions(&db, &config, position, None).unwrap().into();
177185
let (completion,) = completions
178186
.iter()
179187
.filter(|it| it.lookup() == what)
@@ -214,9 +222,14 @@ pub(crate) fn check_pattern_is_applicable(code: &str, check: impl FnOnce(SyntaxE
214222
assert!(check(NodeOrToken::Token(token)));
215223
}
216224

217-
pub(crate) fn get_all_items(config: CompletionConfig, code: &str) -> Vec<CompletionItem> {
225+
pub(crate) fn get_all_items(
226+
config: CompletionConfig,
227+
code: &str,
228+
trigger_character: Option<&str>,
229+
) -> Vec<CompletionItem> {
218230
let (db, position) = position(code);
219-
let res = crate::completions(&db, &config, position).map_or_else(Vec::default, Into::into);
231+
let res = crate::completions(&db, &config, position, trigger_character)
232+
.map_or_else(Vec::default, Into::into);
220233
// validate
221234
res.iter().for_each(|it| {
222235
let sr = it.source_range();

crates/ide-completion/src/tests/fn_param.rs

+17-1
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,17 @@
11
use expect_test::{expect, Expect};
22

3-
use crate::tests::completion_list;
3+
use crate::tests::{completion_list, completion_list_with_trigger_character};
44

55
fn check(ra_fixture: &str, expect: Expect) {
66
let actual = completion_list(ra_fixture);
77
expect.assert_eq(&actual);
88
}
99

10+
fn check_with_trigger_character(ra_fixture: &str, trigger_character: Option<&str>, expect: Expect) {
11+
let actual = completion_list_with_trigger_character(ra_fixture, trigger_character);
12+
expect.assert_eq(&actual)
13+
}
14+
1015
#[test]
1116
fn only_param() {
1217
check(
@@ -113,6 +118,17 @@ fn outer(text: &str) {
113118
)
114119
}
115120

121+
#[test]
122+
fn trigger_by_l_paren() {
123+
check_with_trigger_character(
124+
r#"
125+
fn foo($0)
126+
"#,
127+
Some("("),
128+
expect![[]],
129+
)
130+
}
131+
116132
#[test]
117133
fn shows_non_ident_pat_param() {
118134
check(

crates/ide-completion/src/tests/visibility.rs

+8-2
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,26 @@
11
//! Completion tests for visibility modifiers.
22
use expect_test::{expect, Expect};
33

4-
use crate::tests::completion_list;
4+
use crate::tests::{completion_list, completion_list_with_trigger_character};
55

66
fn check(ra_fixture: &str, expect: Expect) {
77
let actual = completion_list(ra_fixture);
88
expect.assert_eq(&actual)
99
}
1010

11+
fn check_with_trigger_character(ra_fixture: &str, trigger_character: Option<&str>, expect: Expect) {
12+
let actual = completion_list_with_trigger_character(ra_fixture, trigger_character);
13+
expect.assert_eq(&actual)
14+
}
15+
1116
#[test]
1217
fn empty_pub() {
1318
cov_mark::check!(kw_completion_in);
14-
check(
19+
check_with_trigger_character(
1520
r#"
1621
pub($0)
1722
"#,
23+
Some("("),
1824
expect![[r#"
1925
kw crate
2026
kw in

crates/ide/src/lib.rs

+4-1
Original file line numberDiff line numberDiff line change
@@ -547,8 +547,11 @@ impl Analysis {
547547
&self,
548548
config: &CompletionConfig,
549549
position: FilePosition,
550+
trigger_character: Option<&str>,
550551
) -> Cancellable<Option<Vec<CompletionItem>>> {
551-
self.with_db(|db| ide_completion::completions(db, config, position).map(Into::into))
552+
self.with_db(|db| {
553+
ide_completion::completions(db, config, position, trigger_character).map(Into::into)
554+
})
552555
}
553556

554557
/// Resolves additional completion data at the position given.

crates/rust-analyzer/src/caps.rs

+6-1
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,12 @@ pub fn server_capabilities(config: &Config) -> ServerCapabilities {
2929
hover_provider: Some(HoverProviderCapability::Simple(true)),
3030
completion_provider: Some(CompletionOptions {
3131
resolve_provider: completions_resolve_provider(config.caps()),
32-
trigger_characters: Some(vec![":".to_string(), ".".to_string(), "'".to_string()]),
32+
trigger_characters: Some(vec![
33+
":".to_string(),
34+
".".to_string(),
35+
"'".to_string(),
36+
"(".to_string(),
37+
]),
3338
all_commit_characters: None,
3439
completion_item: None,
3540
work_done_progress_options: WorkDoneProgressOptions { work_done_progress: None },

crates/rust-analyzer/src/handlers.rs

+16-17
Original file line numberDiff line numberDiff line change
@@ -796,27 +796,26 @@ pub(crate) fn handle_completion(
796796
let _p = profile::span("handle_completion");
797797
let text_document_position = params.text_document_position.clone();
798798
let position = from_proto::file_position(&snap, params.text_document_position)?;
799-
let completion_triggered_after_single_colon = {
800-
let mut res = false;
801-
if let Some(ctx) = params.context {
802-
if ctx.trigger_character.as_deref() == Some(":") {
803-
let source_file = snap.analysis.parse(position.file_id)?;
804-
let left_token =
805-
source_file.syntax().token_at_offset(position.offset).left_biased();
806-
match left_token {
807-
Some(left_token) => res = left_token.kind() == T![:],
808-
None => res = true,
809-
}
810-
}
799+
let completion_trigger_character = params.context.and_then(|ctx| ctx.trigger_character);
800+
801+
if Some(":") == completion_trigger_character.as_deref() {
802+
let source_file = snap.analysis.parse(position.file_id)?;
803+
let left_token = source_file.syntax().token_at_offset(position.offset).left_biased();
804+
let completion_triggered_after_single_colon = match left_token {
805+
Some(left_token) => left_token.kind() == T![:],
806+
None => true,
807+
};
808+
if completion_triggered_after_single_colon {
809+
return Ok(None);
811810
}
812-
res
813-
};
814-
if completion_triggered_after_single_colon {
815-
return Ok(None);
816811
}
817812

818813
let completion_config = &snap.config.completion();
819-
let items = match snap.analysis.completions(completion_config, position)? {
814+
let items = match snap.analysis.completions(
815+
completion_config,
816+
position,
817+
completion_trigger_character.as_deref(),
818+
)? {
820819
None => return Ok(None),
821820
Some(items) => items,
822821
};

crates/rust-analyzer/src/integrated_benchmarks.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -148,7 +148,7 @@ fn integrated_completion_benchmark() {
148148
};
149149
let position =
150150
FilePosition { file_id, offset: TextSize::try_from(completion_offset).unwrap() };
151-
analysis.completions(&config, position).unwrap();
151+
analysis.completions(&config, position, None).unwrap();
152152
}
153153

154154
let completion_offset = {
@@ -185,7 +185,7 @@ fn integrated_completion_benchmark() {
185185
};
186186
let position =
187187
FilePosition { file_id, offset: TextSize::try_from(completion_offset).unwrap() };
188-
analysis.completions(&config, position).unwrap();
188+
analysis.completions(&config, position, None).unwrap();
189189
}
190190
}
191191

0 commit comments

Comments
 (0)