Auto merge of #13611 - yue4u:fix/completion-after-colon, r=yue4u
fix: filter unnecessary completions after colon close #13597 related: #10173 This PR also happens to fix two extra issues: 1. The test case in https://github.com/rust-lang/rust-analyzer/blob/master/crates/ide-completion/src/tests/attribute.rs#L778-L801 was never triggered in previous behavior. after: https://user-images.githubusercontent.com/26110087/201476995-56adf955-0fa7-4f75-ab32-28a8e6cb9504.mp4 <del> 2. completions were triggered even in invalid paths, like ```rust fn main() { core:::::$0 } ``` ```rust #[:::::$0] struct X; ``` </del> only `:::` is excluded as discussed in https://github.com/rust-lang/rust-analyzer/pull/13611#discussion_r1031845205
This commit is contained in:
commit
34e2bc6a54
@ -19,7 +19,7 @@
|
|||||||
ast::{self, AttrKind, NameOrNameRef},
|
ast::{self, AttrKind, NameOrNameRef},
|
||||||
AstNode,
|
AstNode,
|
||||||
SyntaxKind::{self, *},
|
SyntaxKind::{self, *},
|
||||||
SyntaxToken, TextRange, TextSize,
|
SyntaxToken, TextRange, TextSize, T,
|
||||||
};
|
};
|
||||||
use text_edit::Indel;
|
use text_edit::Indel;
|
||||||
|
|
||||||
@ -569,6 +569,32 @@ pub(super) fn new(
|
|||||||
// completing on
|
// completing on
|
||||||
let original_token = original_file.syntax().token_at_offset(offset).left_biased()?;
|
let original_token = original_file.syntax().token_at_offset(offset).left_biased()?;
|
||||||
|
|
||||||
|
// try to skip completions on path with invalid colons
|
||||||
|
// this approach works in normal path and inside token tree
|
||||||
|
match original_token.kind() {
|
||||||
|
T![:] => {
|
||||||
|
// return if no prev token before colon
|
||||||
|
let prev_token = original_token.prev_token()?;
|
||||||
|
|
||||||
|
// only has a single colon
|
||||||
|
if prev_token.kind() != T![:] {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
|
||||||
|
// has 3 colon or 2 coloncolon in a row
|
||||||
|
// special casing this as per discussion in https://github.com/rust-lang/rust-analyzer/pull/13611#discussion_r1031845205
|
||||||
|
// and https://github.com/rust-lang/rust-analyzer/pull/13611#discussion_r1032812751
|
||||||
|
if prev_token
|
||||||
|
.prev_token()
|
||||||
|
.map(|t| t.kind() == T![:] || t.kind() == T![::])
|
||||||
|
.unwrap_or(false)
|
||||||
|
{
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
|
||||||
let AnalysisResult {
|
let AnalysisResult {
|
||||||
analysis,
|
analysis,
|
||||||
expected: (expected_type, expected_name),
|
expected: (expected_type, expected_name),
|
||||||
|
@ -164,7 +164,6 @@ pub fn completions(
|
|||||||
completions::vis::complete_vis_path(&mut completions, ctx, path_ctx, has_in_token);
|
completions::vis::complete_vis_path(&mut completions, ctx, path_ctx, has_in_token);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// prevent `(` from triggering unwanted completion noise
|
|
||||||
return Some(completions.into());
|
return Some(completions.into());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -607,6 +607,30 @@ fn attr_in_source_file_end() {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn invalid_path() {
|
||||||
|
check(
|
||||||
|
r#"
|
||||||
|
//- proc_macros: identity
|
||||||
|
#[proc_macros:::$0]
|
||||||
|
struct Foo;
|
||||||
|
"#,
|
||||||
|
expect![[r#""#]],
|
||||||
|
);
|
||||||
|
|
||||||
|
check(
|
||||||
|
r#"
|
||||||
|
//- minicore: derive, copy
|
||||||
|
mod foo {
|
||||||
|
pub use Copy as Bar;
|
||||||
|
}
|
||||||
|
#[derive(foo:::::$0)]
|
||||||
|
struct Foo;
|
||||||
|
"#,
|
||||||
|
expect![""],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
mod cfg {
|
mod cfg {
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
|
@ -2,13 +2,22 @@
|
|||||||
|
|
||||||
use expect_test::{expect, Expect};
|
use expect_test::{expect, Expect};
|
||||||
|
|
||||||
use crate::tests::{check_edit, completion_list_no_kw};
|
use crate::tests::{check_edit, completion_list_no_kw, completion_list_with_trigger_character};
|
||||||
|
|
||||||
fn check(ra_fixture: &str, expect: Expect) {
|
fn check(ra_fixture: &str, expect: Expect) {
|
||||||
let actual = completion_list_no_kw(ra_fixture);
|
let actual = completion_list_no_kw(ra_fixture);
|
||||||
expect.assert_eq(&actual)
|
expect.assert_eq(&actual)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub(crate) fn check_with_trigger_character(
|
||||||
|
ra_fixture: &str,
|
||||||
|
trigger_character: Option<char>,
|
||||||
|
expect: Expect,
|
||||||
|
) {
|
||||||
|
let actual = completion_list_with_trigger_character(ra_fixture, trigger_character);
|
||||||
|
expect.assert_eq(&actual)
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn completes_if_prefix_is_keyword() {
|
fn completes_if_prefix_is_keyword() {
|
||||||
check_edit(
|
check_edit(
|
||||||
@ -893,3 +902,82 @@ fn f() {
|
|||||||
"#]],
|
"#]],
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn completes_after_colon_with_trigger() {
|
||||||
|
check_with_trigger_character(
|
||||||
|
r#"
|
||||||
|
//- minicore: option
|
||||||
|
fn foo { ::$0 }
|
||||||
|
"#,
|
||||||
|
Some(':'),
|
||||||
|
expect![[r#"
|
||||||
|
md core
|
||||||
|
"#]],
|
||||||
|
);
|
||||||
|
check_with_trigger_character(
|
||||||
|
r#"
|
||||||
|
//- minicore: option
|
||||||
|
fn foo { /* test */::$0 }
|
||||||
|
"#,
|
||||||
|
Some(':'),
|
||||||
|
expect![[r#"
|
||||||
|
md core
|
||||||
|
"#]],
|
||||||
|
);
|
||||||
|
|
||||||
|
check_with_trigger_character(
|
||||||
|
r#"
|
||||||
|
fn foo { crate::$0 }
|
||||||
|
"#,
|
||||||
|
Some(':'),
|
||||||
|
expect![[r#"
|
||||||
|
fn foo() fn()
|
||||||
|
"#]],
|
||||||
|
);
|
||||||
|
|
||||||
|
check_with_trigger_character(
|
||||||
|
r#"
|
||||||
|
fn foo { crate:$0 }
|
||||||
|
"#,
|
||||||
|
Some(':'),
|
||||||
|
expect![""],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn completes_after_colon_without_trigger() {
|
||||||
|
check_with_trigger_character(
|
||||||
|
r#"
|
||||||
|
fn foo { crate::$0 }
|
||||||
|
"#,
|
||||||
|
None,
|
||||||
|
expect![[r#"
|
||||||
|
fn foo() fn()
|
||||||
|
"#]],
|
||||||
|
);
|
||||||
|
|
||||||
|
check_with_trigger_character(
|
||||||
|
r#"
|
||||||
|
fn foo { crate:$0 }
|
||||||
|
"#,
|
||||||
|
None,
|
||||||
|
expect![""],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn no_completions_in_invalid_path() {
|
||||||
|
check(
|
||||||
|
r#"
|
||||||
|
fn foo { crate:::$0 }
|
||||||
|
"#,
|
||||||
|
expect![""],
|
||||||
|
);
|
||||||
|
check(
|
||||||
|
r#"
|
||||||
|
fn foo { crate::::$0 }
|
||||||
|
"#,
|
||||||
|
expect![""],
|
||||||
|
)
|
||||||
|
}
|
||||||
|
@ -28,7 +28,7 @@
|
|||||||
use project_model::{ManifestPath, ProjectWorkspace, TargetKind};
|
use project_model::{ManifestPath, ProjectWorkspace, TargetKind};
|
||||||
use serde_json::json;
|
use serde_json::json;
|
||||||
use stdx::{format_to, never};
|
use stdx::{format_to, never};
|
||||||
use syntax::{algo, ast, AstNode, TextRange, TextSize, T};
|
use syntax::{algo, ast, AstNode, TextRange, TextSize};
|
||||||
use vfs::AbsPathBuf;
|
use vfs::AbsPathBuf;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
@ -812,18 +812,6 @@ pub(crate) fn handle_completion(
|
|||||||
let completion_trigger_character =
|
let completion_trigger_character =
|
||||||
params.context.and_then(|ctx| ctx.trigger_character).and_then(|s| s.chars().next());
|
params.context.and_then(|ctx| ctx.trigger_character).and_then(|s| s.chars().next());
|
||||||
|
|
||||||
if Some(':') == completion_trigger_character {
|
|
||||||
let source_file = snap.analysis.parse(position.file_id)?;
|
|
||||||
let left_token = source_file.syntax().token_at_offset(position.offset).left_biased();
|
|
||||||
let completion_triggered_after_single_colon = match left_token {
|
|
||||||
Some(left_token) => left_token.kind() == T![:],
|
|
||||||
None => true,
|
|
||||||
};
|
|
||||||
if completion_triggered_after_single_colon {
|
|
||||||
return Ok(None);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let completion_config = &snap.config.completion();
|
let completion_config = &snap.config.completion();
|
||||||
let items = match snap.analysis.completions(
|
let items = match snap.analysis.completions(
|
||||||
completion_config,
|
completion_config,
|
||||||
|
Loading…
Reference in New Issue
Block a user