//! }
//!
//! impl SomeTrait for () {
-//! fn f<|>
+//! fn f$0
//! }
//! ```
//!
//! # }
//!
//! impl SomeTrait for () {
-//! fn foo() {}<|>
+//! fn foo() {}$0
//! }
//! ```
fn completion_match(ctx: &CompletionContext) -> Option<(ImplCompletionKind, SyntaxNode, Impl)> {
let mut token = ctx.token.clone();
- // For keywork without name like `impl .. { fn <|> }`, the current position is inside
+ // For keywork without name like `impl .. { fn $0 }`, the current position is inside
// the whitespace token, which is outside `FN` syntax node.
// We need to follow the previous token in this case.
if token.kind() == SyntaxKind::WHITESPACE {
}
let impl_item_offset = match token.kind() {
- // `impl .. { const <|> }`
+ // `impl .. { const $0 }`
// ERROR 0
// CONST_KW <- *
- SyntaxKind::CONST_KW => 0,
- // `impl .. { fn/type <|> }`
+ T![const] => 0,
+ // `impl .. { fn/type $0 }`
// FN/TYPE_ALIAS 0
// FN_KW <- *
- SyntaxKind::FN_KW | SyntaxKind::TYPE_KW => 0,
- // `impl .. { fn/type/const foo<|> }`
+ T![fn] | T![type] => 0,
+ // `impl .. { fn/type/const foo$0 }`
// FN/TYPE_ALIAS/CONST 1
// NAME 0
// IDENT <- *
SyntaxKind::IDENT if token.parent().kind() == SyntaxKind::NAME => 1,
- // `impl .. { foo<|> }`
+ // `impl .. { foo$0 }`
// MACRO_CALL 3
// PATH 2
// PATH_SEGMENT 1
// <item>
let impl_def = ast::Impl::cast(impl_item.parent()?.parent()?)?;
let kind = match impl_item.kind() {
- // `impl ... { const <|> fn/type/const }`
- _ if token.kind() == SyntaxKind::CONST_KW => ImplCompletionKind::Const,
+ // `impl ... { const $0 fn/type/const }`
+ _ if token.kind() == T![const] => ImplCompletionKind::Const,
SyntaxKind::CONST | SyntaxKind::ERROR => ImplCompletionKind::Const,
SyntaxKind::TYPE_ALIAS => ImplCompletionKind::TypeAlias,
SyntaxKind::FN => ImplCompletionKind::Fn,
};
let range = TextRange::new(fn_def_node.text_range().start(), ctx.source_range().end());
- let function_decl = function_declaration(&func.source(ctx.db).value);
- match ctx.config.snippet_cap {
- Some(cap) => {
- let snippet = format!("{} {{\n $0\n}}", function_decl);
- builder.snippet_edit(cap, TextEdit::replace(range, snippet))
- }
- None => {
- let header = format!("{} {{", function_decl);
- builder.text_edit(TextEdit::replace(range, header))
+ if let Some(src) = func.source(ctx.db) {
+ let function_decl = function_declaration(&src.value);
+ match ctx.config.snippet_cap {
+ Some(cap) => {
+ let snippet = format!("{} {{\n $0\n}}", function_decl);
+ builder.snippet_edit(cap, TextEdit::replace(range, snippet))
+ }
+ None => {
+ let header = format!("{} {{", function_decl);
+ builder.text_edit(TextEdit::replace(range, header))
+ }
}
+ .kind(completion_kind)
+ .add_to(acc);
}
- .kind(completion_kind)
- .add_to(acc);
}
fn add_type_alias_impl(
let const_name = const_.name(ctx.db).map(|n| n.to_string());
if let Some(const_name) = const_name {
- let snippet = make_const_compl_syntax(&const_.source(ctx.db).value);
-
- let range = TextRange::new(const_def_node.text_range().start(), ctx.source_range().end());
-
- CompletionItem::new(CompletionKind::Magic, ctx.source_range(), snippet.clone())
- .text_edit(TextEdit::replace(range, snippet))
- .lookup_by(const_name)
- .kind(CompletionItemKind::Const)
- .set_documentation(const_.docs(ctx.db))
- .add_to(acc);
+ if let Some(source) = const_.source(ctx.db) {
+ let snippet = make_const_compl_syntax(&source.value);
+
+ let range =
+ TextRange::new(const_def_node.text_range().start(), ctx.source_range().end());
+
+ CompletionItem::new(CompletionKind::Magic, ctx.source_range(), snippet.clone())
+ .text_edit(TextEdit::replace(range, snippet))
+ .lookup_by(const_name)
+ .kind(CompletionItemKind::Const)
+ .set_documentation(const_.docs(ctx.db))
+ .add_to(acc);
+ }
}
}
struct T;
impl Test for T {
- t<|>
+ t$0
}
"#,
expect![["
+ta type TestType = \n\
ct const TEST_CONST: u16 = \n\
fn fn test()
-ta type TestType = \n\
- "]],
+"]],
);
}
impl Test for T {
fn test() {
- t<|>
+ t$0
}
}
",
impl Test for T {
fn test() {
- fn t<|>
+ fn t$0
}
}
",
impl Test for T {
fn test() {
- fn <|>
+ fn $0
}
}
",
impl Test for T {
fn test() {
- foo.<|>
+ foo.$0
}
}
",
struct T;
impl Test for T {
- fn test(t<|>)
+ fn test(t$0)
}
",
expect![[""]],
struct T;
impl Test for T {
- fn test(f: fn <|>)
+ fn test(f: fn $0)
}
",
expect![[""]],
struct T;
impl Test for T {
- const TEST: fn <|>
+ const TEST: fn $0
}
",
expect![[""]],
struct T;
impl Test for T {
- const TEST: T<|>
+ const TEST: T$0
}
",
expect![[""]],
struct T;
impl Test for T {
- const TEST: u32 = f<|>
+ const TEST: u32 = f$0
}
",
expect![[""]],
impl Test for T {
const TEST: u32 = {
- t<|>
+ t$0
};
}
",
impl Test for T {
const TEST: u32 = {
- fn <|>
+ fn $0
};
}
",
impl Test for T {
const TEST: u32 = {
- fn t<|>
+ fn t$0
};
}
",
struct T;
impl Test for T {
- type Test = T<|>;
+ type Test = T$0;
}
",
expect![[""]],
struct T;
impl Test for T {
- type Test = fn <|>;
+ type Test = fn $0;
}
",
expect![[""]],
struct T;
impl Test for T {
- t<|>
+ t$0
}
"#,
r#"
struct T;
impl Test for T {
- fn t<|>
+ fn t$0
}
"#,
r#"
impl Test for T {
fn foo() {}
- fn f<|>
+ fn f$0
}
"#,
expect![[r#"
struct T;
impl Test for T {
- fn f<|>
+ fn f$0
}
"#,
r#"
struct T;
impl Test for T {
- fn f<|>
+ fn f$0
}
"#,
r#"
}
impl Test for () {
- type S<|>
+ type S$0
}
"#,
"
}
impl Test for () {
- const S<|>
+ const S$0
}
"#,
"
}
impl Test for () {
- const S<|>
+ const S$0
}
"#,
"
// Enumerate some possible next siblings.
for next_sibling in &[
"",
- "fn other_fn() {}", // `const <|> fn` -> `const fn`
+ "fn other_fn() {}", // `const $0 fn` -> `const fn`
"type OtherType = i32;",
"const OTHER_CONST: i32 = 0;",
"async fn other_fn() {}",
"default type OtherType = i32;",
"default const OTHER_CONST: i32 = 0;",
] {
- test("bar", "fn <|>", "fn bar() {\n $0\n}", next_sibling);
- test("Foo", "type <|>", "type Foo = ", next_sibling);
- test("CONST", "const <|>", "const CONST: u16 = ", next_sibling);
+ test("bar", "fn $0", "fn bar() {\n $0\n}", next_sibling);
+ test("Foo", "type $0", "type Foo = ", next_sibling);
+ test("CONST", "const $0", "const CONST: u16 = ", next_sibling);
}
}
}