574: refactor completions to use TextEdit instead of InsertText r=matklad a=gfreezy

1. migrate from `insertText` to `TextEdit` from `CompleteItem`
2. use `insta` to test completions

Co-authored-by: gfreezy <gfreezy@gmail.com>
This commit is contained in:
bors[bot] 2019-01-20 18:27:23 +00:00
commit f133702f72
54 changed files with 2206 additions and 318 deletions

View file

@ -19,7 +19,7 @@ use crate::{
},
};
pub use crate::completion::completion_item::{CompletionItem, InsertText, CompletionItemKind};
pub use crate::completion::completion_item::{CompletionItem, CompletionItemKind, InsertTextFormat};
/// Main entry point for completion. We run completion as a two-phase process.
///
@ -60,15 +60,3 @@ pub(crate) fn completions(db: &db::RootDatabase, position: FilePosition) -> Opti
Some(acc)
}
#[cfg(test)]
fn check_completion(code: &str, expected_completions: &str, kind: CompletionKind) {
use crate::mock_analysis::{single_file_with_position, analysis_and_position};
let (analysis, position) = if code.contains("//-") {
analysis_and_position(code)
} else {
single_file_with_position(code)
};
let completions = completions(&analysis.db, position).unwrap();
completions.assert_match(expected_completions, kind);
}

View file

@ -1,6 +1,7 @@
use hir::{Ty, Def};
use crate::completion::{CompletionContext, Completions, CompletionKind, CompletionItem, CompletionItemKind};
use crate::completion::{CompletionContext, Completions, CompletionItem, CompletionItemKind};
use crate::completion::completion_item::CompletionKind;
/// Complete dot accesses, i.e. fields or methods (currently only fields).
pub(super) fn complete_dot(acc: &mut Completions, ctx: &CompletionContext) {
@ -32,6 +33,7 @@ fn complete_fields(acc: &mut Completions, ctx: &CompletionContext, receiver: Ty)
for field in s.fields(ctx.db) {
CompletionItem::new(
CompletionKind::Reference,
ctx.source_range(),
field.name().to_string(),
)
.kind(CompletionItemKind::Field)
@ -45,9 +47,13 @@ fn complete_fields(acc: &mut Completions, ctx: &CompletionContext, receiver: Ty)
}
Ty::Tuple(fields) => {
for (i, _ty) in fields.iter().enumerate() {
CompletionItem::new(CompletionKind::Reference, i.to_string())
.kind(CompletionItemKind::Field)
.add_to(acc);
CompletionItem::new(
CompletionKind::Reference,
ctx.source_range(),
i.to_string(),
)
.kind(CompletionItemKind::Field)
.add_to(acc);
}
}
_ => {}
@ -59,10 +65,14 @@ fn complete_methods(acc: &mut Completions, ctx: &CompletionContext, receiver: Ty
receiver.iterate_methods(ctx.db, |func| {
let sig = func.signature(ctx.db);
if sig.has_self_param() {
CompletionItem::new(CompletionKind::Reference, sig.name().to_string())
.from_function(ctx, func)
.kind(CompletionItemKind::Method)
.add_to(acc);
CompletionItem::new(
CompletionKind::Reference,
ctx.source_range(),
sig.name().to_string(),
)
.from_function(ctx, func)
.kind(CompletionItemKind::Method)
.add_to(acc);
}
None::<()>
});
@ -71,27 +81,29 @@ fn complete_methods(acc: &mut Completions, ctx: &CompletionContext, receiver: Ty
#[cfg(test)]
mod tests {
use crate::completion::*;
use crate::completion::completion_item::check_completion;
fn check_ref_completion(code: &str, expected_completions: &str) {
check_completion(code, expected_completions, CompletionKind::Reference);
fn check_ref_completion(name: &str, code: &str) {
check_completion(name, code, CompletionKind::Reference);
}
#[test]
fn test_struct_field_completion() {
check_ref_completion(
"struct_field_completion",
r"
struct A { the_field: u32 }
fn foo(a: A) {
a.<|>
}
",
r#"the_field "u32""#,
);
}
#[test]
fn test_struct_field_completion_self() {
check_ref_completion(
"struct_field_completion_self",
r"
struct A { the_field: (u32,) }
impl A {
@ -100,14 +112,13 @@ mod tests {
}
}
",
r#"the_field "(u32,)"
foo "foo($0)""#,
);
}
#[test]
fn test_struct_field_completion_autoderef() {
check_ref_completion(
"struct_field_completion_autoderef",
r"
struct A { the_field: (u32, i32) }
impl A {
@ -116,27 +127,26 @@ mod tests {
}
}
",
r#"the_field "(u32, i32)"
foo "foo($0)""#,
);
}
#[test]
fn test_no_struct_field_completion_for_method_call() {
check_ref_completion(
"no_struct_field_completion_for_method_call",
r"
struct A { the_field: u32 }
fn foo(a: A) {
a.<|>()
}
",
r#""#,
);
}
#[test]
fn test_method_completion() {
check_ref_completion(
"method_completion",
r"
struct A {}
impl A {
@ -146,13 +156,13 @@ mod tests {
a.<|>
}
",
r#"the_method "the_method($0)""#,
);
}
#[test]
fn test_no_non_self_method() {
check_ref_completion(
"no_non_self_method",
r"
struct A {}
impl A {
@ -162,7 +172,6 @@ mod tests {
a.<|>
}
",
r#""#,
);
}
}

View file

@ -34,7 +34,7 @@ pub(super) fn complete_fn_param(acc: &mut Completions, ctx: &CompletionContext)
}
})
.for_each(|(label, lookup)| {
CompletionItem::new(CompletionKind::Magic, label)
CompletionItem::new(CompletionKind::Magic, ctx.source_range(), label)
.lookup_by(lookup)
.add_to(acc)
});
@ -56,38 +56,40 @@ pub(super) fn complete_fn_param(acc: &mut Completions, ctx: &CompletionContext)
#[cfg(test)]
mod tests {
use crate::completion::*;
use crate::completion::completion_item::check_completion;
fn check_magic_completion(code: &str, expected_completions: &str) {
check_completion(code, expected_completions, CompletionKind::Magic);
fn check_magic_completion(name: &str, code: &str) {
check_completion(name, code, CompletionKind::Magic);
}
#[test]
fn test_param_completion_last_param() {
check_magic_completion(
"param_completion_last_param",
r"
fn foo(file_id: FileId) {}
fn bar(file_id: FileId) {}
fn baz(file<|>) {}
",
r#"file_id "file_id: FileId""#,
);
}
#[test]
fn test_param_completion_nth_param() {
check_magic_completion(
"param_completion_nth_param",
r"
fn foo(file_id: FileId) {}
fn bar(file_id: FileId) {}
fn baz(file<|>, x: i32) {}
",
r#"file_id "file_id: FileId""#,
);
}
#[test]
fn test_param_completion_trait_param() {
check_magic_completion(
"param_completion_trait_param",
r"
pub(crate) trait SourceRoot {
pub fn contains(&self, file_id: FileId) -> bool;
@ -96,7 +98,6 @@ mod tests {
pub fn syntax(&self, file<|>)
}
",
r#"file_id "file_id: FileId""#,
);
}
}

View file

@ -9,38 +9,36 @@ use crate::completion::{CompletionContext, CompletionItem, Completions, Completi
pub(super) fn complete_use_tree_keyword(acc: &mut Completions, ctx: &CompletionContext) {
// complete keyword "crate" in use stmt
let source_range = ctx.source_range();
match (ctx.use_item_syntax.as_ref(), ctx.path_prefix.as_ref()) {
(Some(_), None) => {
CompletionItem::new(CompletionKind::Keyword, "crate")
CompletionItem::new(CompletionKind::Keyword, source_range, "crate")
.kind(CompletionItemKind::Keyword)
.lookup_by("crate")
.snippet("crate::")
.insert_text("crate::")
.add_to(acc);
CompletionItem::new(CompletionKind::Keyword, "self")
CompletionItem::new(CompletionKind::Keyword, source_range, "self")
.kind(CompletionItemKind::Keyword)
.lookup_by("self")
.add_to(acc);
CompletionItem::new(CompletionKind::Keyword, "super")
CompletionItem::new(CompletionKind::Keyword, source_range, "super")
.kind(CompletionItemKind::Keyword)
.lookup_by("super")
.insert_text("super::")
.add_to(acc);
}
(Some(_), Some(_)) => {
CompletionItem::new(CompletionKind::Keyword, "self")
CompletionItem::new(CompletionKind::Keyword, source_range, "self")
.kind(CompletionItemKind::Keyword)
.lookup_by("self")
.add_to(acc);
CompletionItem::new(CompletionKind::Keyword, "super")
CompletionItem::new(CompletionKind::Keyword, source_range, "super")
.kind(CompletionItemKind::Keyword)
.lookup_by("super")
.insert_text("super::")
.add_to(acc);
}
_ => {}
}
}
fn keyword(kw: &str, snippet: &str) -> CompletionItem {
CompletionItem::new(CompletionKind::Keyword, kw)
fn keyword(ctx: &CompletionContext, kw: &str, snippet: &str) -> CompletionItem {
CompletionItem::new(CompletionKind::Keyword, ctx.source_range(), kw)
.kind(CompletionItemKind::Keyword)
.snippet(snippet)
.build()
@ -55,25 +53,25 @@ pub(super) fn complete_expr_keyword(acc: &mut Completions, ctx: &CompletionConte
Some(it) => it,
None => return,
};
acc.add(keyword("if", "if $0 {}"));
acc.add(keyword("match", "match $0 {}"));
acc.add(keyword("while", "while $0 {}"));
acc.add(keyword("loop", "loop {$0}"));
acc.add(keyword(ctx, "if", "if $0 {}"));
acc.add(keyword(ctx, "match", "match $0 {}"));
acc.add(keyword(ctx, "while", "while $0 {}"));
acc.add(keyword(ctx, "loop", "loop {$0}"));
if ctx.after_if {
acc.add(keyword("else", "else {$0}"));
acc.add(keyword("else if", "else if $0 {}"));
acc.add(keyword(ctx, "else", "else {$0}"));
acc.add(keyword(ctx, "else if", "else if $0 {}"));
}
if is_in_loop_body(ctx.leaf) {
if ctx.can_be_stmt {
acc.add(keyword("continue", "continue;"));
acc.add(keyword("break", "break;"));
acc.add(keyword(ctx, "continue", "continue;"));
acc.add(keyword(ctx, "break", "break;"));
} else {
acc.add(keyword("continue", "continue"));
acc.add(keyword("break", "break"));
acc.add(keyword(ctx, "continue", "continue"));
acc.add(keyword(ctx, "break", "break"));
}
}
acc.add_all(complete_return(fn_def, ctx.can_be_stmt));
acc.add_all(complete_return(ctx, fn_def, ctx.can_be_stmt));
}
fn is_in_loop_body(leaf: &SyntaxNode) -> bool {
@ -95,78 +93,69 @@ fn is_in_loop_body(leaf: &SyntaxNode) -> bool {
false
}
fn complete_return(fn_def: &ast::FnDef, can_be_stmt: bool) -> Option<CompletionItem> {
fn complete_return(
ctx: &CompletionContext,
fn_def: &ast::FnDef,
can_be_stmt: bool,
) -> Option<CompletionItem> {
let snip = match (can_be_stmt, fn_def.ret_type().is_some()) {
(true, true) => "return $0;",
(true, false) => "return;",
(false, true) => "return $0",
(false, false) => "return",
};
Some(keyword("return", snip))
Some(keyword(ctx, "return", snip))
}
#[cfg(test)]
mod tests {
use crate::completion::{CompletionKind, check_completion};
fn check_keyword_completion(code: &str, expected_completions: &str) {
check_completion(code, expected_completions, CompletionKind::Keyword);
use crate::completion::CompletionKind;
use crate::completion::completion_item::check_completion;
fn check_keyword_completion(name: &str, code: &str) {
check_completion(name, code, CompletionKind::Keyword);
}
#[test]
fn completes_keywords_in_use_stmt() {
check_keyword_completion(
"keywords_in_use_stmt1",
r"
use <|>
",
r#"
crate "crate" "crate::"
self "self"
super "super"
"#,
);
check_keyword_completion(
"keywords_in_use_stmt2",
r"
use a::<|>
",
r#"
self "self"
super "super"
"#,
);
check_keyword_completion(
"keywords_in_use_stmt3",
r"
use a::{b, <|>}
",
r#"
self "self"
super "super"
"#,
);
}
#[test]
fn completes_various_keywords_in_function() {
check_keyword_completion(
"keywords_in_function1",
r"
fn quux() {
<|>
}
",
r#"
if "if $0 {}"
match "match $0 {}"
while "while $0 {}"
loop "loop {$0}"
return "return;"
"#,
);
}
#[test]
fn completes_else_after_if() {
check_keyword_completion(
"keywords_in_function2",
r"
fn quux() {
if true {
@ -174,55 +163,35 @@ mod tests {
} <|>
}
",
r#"
if "if $0 {}"
match "match $0 {}"
while "while $0 {}"
loop "loop {$0}"
else "else {$0}"
else if "else if $0 {}"
return "return;"
"#,
);
}
#[test]
fn test_completion_return_value() {
check_keyword_completion(
"keywords_in_function3",
r"
fn quux() -> i32 {
<|>
92
}
",
r#"
if "if $0 {}"
match "match $0 {}"
while "while $0 {}"
loop "loop {$0}"
return "return $0;"
"#,
);
check_keyword_completion(
"keywords_in_function4",
r"
fn quux() {
<|>
92
}
",
r#"
if "if $0 {}"
match "match $0 {}"
while "while $0 {}"
loop "loop {$0}"
return "return;"
"#,
);
}
#[test]
fn dont_add_semi_after_return_if_not_a_statement() {
check_keyword_completion(
"dont_add_semi_after_return_if_not_a_statement",
r"
fn quux() -> i32 {
match () {
@ -230,19 +199,13 @@ mod tests {
}
}
",
r#"
if "if $0 {}"
match "match $0 {}"
while "while $0 {}"
loop "loop {$0}"
return "return $0"
"#,
);
}
#[test]
fn last_return_in_block_has_semi() {
check_keyword_completion(
"last_return_in_block_has_semi1",
r"
fn quux() -> i32 {
if condition {
@ -250,15 +213,9 @@ mod tests {
}
}
",
r#"
if "if $0 {}"
match "match $0 {}"
while "while $0 {}"
loop "loop {$0}"
return "return $0;"
"#,
);
check_keyword_completion(
"last_return_in_block_has_semi2",
r"
fn quux() -> i32 {
if condition {
@ -268,54 +225,35 @@ mod tests {
x
}
",
r#"
if "if $0 {}"
match "match $0 {}"
while "while $0 {}"
loop "loop {$0}"
return "return $0;"
"#,
);
}
#[test]
fn completes_break_and_continue_in_loops() {
check_keyword_completion(
"completes_break_and_continue_in_loops1",
r"
fn quux() -> i32 {
loop { <|> }
}
",
r#"
if "if $0 {}"
match "match $0 {}"
while "while $0 {}"
loop "loop {$0}"
continue "continue;"
break "break;"
return "return $0;"
"#,
);
// No completion: lambda isolates control flow
check_keyword_completion(
"completes_break_and_continue_in_loops2",
r"
fn quux() -> i32 {
loop { || { <|> } }
}
",
r#"
if "if $0 {}"
match "match $0 {}"
while "while $0 {}"
loop "loop {$0}"
return "return $0;"
"#,
);
}
#[test]
fn no_semi_after_break_continue_in_expr() {
check_keyword_completion(
"no_semi_after_break_continue_in_expr",
r"
fn f() {
loop {
@ -325,15 +263,6 @@ mod tests {
}
}
",
r#"
if "if $0 {}"
match "match $0 {}"
while "while $0 {}"
loop "loop {$0}"
continue "continue"
break "break"
return "return"
"#,
)
}
}

View file

@ -15,18 +15,26 @@ pub(super) fn complete_path(acc: &mut Completions, ctx: &CompletionContext) {
hir::Def::Module(module) => {
let module_scope = module.scope(ctx.db);
for (name, res) in module_scope.entries() {
CompletionItem::new(CompletionKind::Reference, name.to_string())
.from_resolution(ctx, res)
.add_to(acc);
CompletionItem::new(
CompletionKind::Reference,
ctx.source_range(),
name.to_string(),
)
.from_resolution(ctx, res)
.add_to(acc);
}
}
hir::Def::Enum(e) => {
e.variants(ctx.db)
.into_iter()
.for_each(|(variant_name, _variant)| {
CompletionItem::new(CompletionKind::Reference, variant_name.to_string())
.kind(CompletionItemKind::EnumVariant)
.add_to(acc)
CompletionItem::new(
CompletionKind::Reference,
ctx.source_range(),
variant_name.to_string(),
)
.kind(CompletionItemKind::EnumVariant)
.add_to(acc)
});
}
_ => return,
@ -35,7 +43,8 @@ pub(super) fn complete_path(acc: &mut Completions, ctx: &CompletionContext) {
#[cfg(test)]
mod tests {
use crate::completion::{CompletionKind, check_completion};
use crate::completion::CompletionKind;
use crate::completion::completion_item::check_completion;
fn check_reference_completion(code: &str, expected_completions: &str) {
check_completion(code, expected_completions, CompletionKind::Reference);
@ -44,6 +53,7 @@ mod tests {
#[test]
fn completes_use_item_starting_with_self() {
check_reference_completion(
"use_item_starting_with_self",
r"
use self::m::<|>;
@ -51,13 +61,13 @@ mod tests {
struct Bar;
}
",
"Bar",
);
}
#[test]
fn completes_use_item_starting_with_crate() {
check_reference_completion(
"use_item_starting_with_crate",
"
//- /lib.rs
mod foo;
@ -65,13 +75,13 @@ mod tests {
//- /foo.rs
use crate::Sp<|>
",
"Spam;foo",
);
}
#[test]
fn completes_nested_use_tree() {
check_reference_completion(
"nested_use_tree",
"
//- /lib.rs
mod foo;
@ -79,13 +89,13 @@ mod tests {
//- /foo.rs
use crate::{Sp<|>};
",
"Spam;foo",
);
}
#[test]
fn completes_deeply_nested_use_tree() {
check_reference_completion(
"deeply_nested_use_tree",
"
//- /lib.rs
mod foo;
@ -97,37 +107,37 @@ mod tests {
//- /foo.rs
use crate::{bar::{baz::Sp<|>}};
",
"Spam",
);
}
#[test]
fn completes_enum_variant() {
check_reference_completion(
"reference_completion",
"
//- /lib.rs
enum E { Foo, Bar(i32) }
fn foo() { let _ = E::<|> }
",
"Foo;Bar",
);
}
#[test]
fn dont_render_function_parens_in_use_item() {
check_reference_completion(
"dont_render_function_parens_in_use_item",
"
//- /lib.rs
mod m { pub fn foo() {} }
use crate::m::f<|>;
",
"foo",
)
}
#[test]
fn dont_render_function_parens_if_already_call() {
check_reference_completion(
"dont_render_function_parens_if_already_call",
"
//- /lib.rs
fn frobnicate() {}
@ -135,7 +145,6 @@ mod tests {
frob<|>();
}
",
"main;frobnicate",
)
}
}

View file

@ -1,6 +1,5 @@
use rustc_hash::FxHashSet;
use ra_syntax::{AstNode, TextUnit};
use ra_syntax::ast::AstNode;
use crate::completion::{CompletionItem, CompletionItemKind, Completions, CompletionKind, CompletionContext};
pub(super) fn complete_scope(acc: &mut Completions, ctx: &CompletionContext) {
@ -13,7 +12,7 @@ pub(super) fn complete_scope(acc: &mut Completions, ctx: &CompletionContext) {
};
if let Some(function) = &ctx.function {
let scopes = function.scopes(ctx.db);
complete_fn(acc, &scopes, ctx.offset);
complete_fn(acc, &scopes, ctx);
}
let module_scope = module.scope(ctx.db);
@ -30,36 +29,50 @@ pub(super) fn complete_scope(acc: &mut Completions, ctx: &CompletionContext) {
}
})
.for_each(|(name, res)| {
CompletionItem::new(CompletionKind::Reference, name.to_string())
.from_resolution(ctx, res)
.add_to(acc)
CompletionItem::new(
CompletionKind::Reference,
ctx.source_range(),
name.to_string(),
)
.from_resolution(ctx, res)
.add_to(acc)
});
}
fn complete_fn(acc: &mut Completions, scopes: &hir::ScopesWithSyntaxMapping, offset: TextUnit) {
fn complete_fn(
acc: &mut Completions,
scopes: &hir::ScopesWithSyntaxMapping,
ctx: &CompletionContext,
) {
let mut shadowed = FxHashSet::default();
scopes
.scope_chain_for_offset(offset)
.scope_chain_for_offset(ctx.offset)
.flat_map(|scope| scopes.scopes.entries(scope).iter())
.filter(|entry| shadowed.insert(entry.name()))
.for_each(|entry| {
CompletionItem::new(CompletionKind::Reference, entry.name().to_string())
.kind(CompletionItemKind::Binding)
.add_to(acc)
CompletionItem::new(
CompletionKind::Reference,
ctx.source_range(),
entry.name().to_string(),
)
.kind(CompletionItemKind::Binding)
.add_to(acc)
});
}
#[cfg(test)]
mod tests {
use crate::completion::{CompletionKind, check_completion};
use crate::completion::CompletionKind;
use crate::completion::completion_item::check_completion;
fn check_reference_completion(code: &str, expected_completions: &str) {
check_completion(code, expected_completions, CompletionKind::Reference);
fn check_reference_completion(name: &str, code: &str) {
check_completion(name, code, CompletionKind::Reference);
}
#[test]
fn completes_bindings_from_let() {
check_reference_completion(
"bindings_from_let",
r"
fn quux(x: i32) {
let y = 92;
@ -67,13 +80,13 @@ mod tests {
let z = ();
}
",
r#"y;x;quux "quux($0)""#,
);
}
#[test]
fn completes_bindings_from_if_let() {
check_reference_completion(
"bindings_from_if_let",
r"
fn quux() {
if let Some(x) = foo() {
@ -85,13 +98,13 @@ mod tests {
}
}
",
r#"b;a;quux "quux()$0""#,
);
}
#[test]
fn completes_bindings_from_for() {
check_reference_completion(
"bindings_from_for",
r"
fn quux() {
for x in &[1, 2, 3] {
@ -99,13 +112,13 @@ mod tests {
}
}
",
r#"x;quux "quux()$0""#,
);
}
#[test]
fn completes_module_items() {
check_reference_completion(
"module_items",
r"
struct Foo;
enum Baz {}
@ -113,13 +126,13 @@ mod tests {
<|>
}
",
r#"quux "quux()$0";Foo;Baz"#,
);
}
#[test]
fn completes_module_items_in_nested_modules() {
check_reference_completion(
"module_items_in_nested_modules",
r"
struct Foo;
mod m {
@ -127,24 +140,24 @@ mod tests {
fn quux() { <|> }
}
",
r#"quux "quux()$0";Bar"#,
);
}
#[test]
fn completes_return_type() {
check_reference_completion(
"return_type",
r"
struct Foo;
fn x() -> <|>
",
r#"Foo;x "x()$0""#,
)
}
#[test]
fn dont_show_both_completions_for_shadowing() {
check_reference_completion(
"dont_show_both_completions_for_shadowing",
r"
fn foo() -> {
let bar = 92;
@ -154,32 +167,29 @@ mod tests {
}
}
",
r#"bar;foo "foo()$0""#,
)
}
#[test]
fn completes_self_in_methods() {
check_reference_completion(r"impl S { fn foo(&self) { <|> } }", "self")
check_reference_completion("self_in_methods", r"impl S { fn foo(&self) { <|> } }")
}
#[test]
fn inserts_parens_for_function_calls() {
check_reference_completion(
"inserts_parens_for_function_calls1",
r"
fn no_args() {}
fn main() { no_<|> }
",
r#"no_args "no_args()$0"
main "main()$0""#,
);
check_reference_completion(
"inserts_parens_for_function_calls2",
r"
fn with_args(x: i32, y: String) {}
fn main() { with_<|> }
",
r#"main "main()$0"
with_args "with_args($0)""#,
);
}
}

View file

@ -1,7 +1,7 @@
use crate::completion::{CompletionItem, Completions, CompletionKind, CompletionItemKind, CompletionContext, completion_item::Builder};
fn snippet(label: &str, snippet: &str) -> Builder {
CompletionItem::new(CompletionKind::Snippet, label)
fn snippet(ctx: &CompletionContext, label: &str, snippet: &str) -> Builder {
CompletionItem::new(CompletionKind::Snippet, ctx.source_range(), label)
.snippet(snippet)
.kind(CompletionItemKind::Snippet)
}
@ -10,8 +10,8 @@ pub(super) fn complete_expr_snippet(acc: &mut Completions, ctx: &CompletionConte
if !(ctx.is_trivial_path && ctx.function_syntax.is_some()) {
return;
}
snippet("pd", "eprintln!(\"$0 = {:?}\", $0);").add_to(acc);
snippet("ppd", "eprintln!(\"$0 = {:#?}\", $0);").add_to(acc);
snippet(ctx, "pd", "eprintln!(\"$0 = {:?}\", $0);").add_to(acc);
snippet(ctx, "ppd", "eprintln!(\"$0 = {:#?}\", $0);").add_to(acc);
}
pub(super) fn complete_item_snippet(acc: &mut Completions, ctx: &CompletionContext) {
@ -19,6 +19,7 @@ pub(super) fn complete_item_snippet(acc: &mut Completions, ctx: &CompletionConte
return;
}
snippet(
ctx,
"Test function",
"\
#[test]
@ -29,45 +30,33 @@ fn ${1:feature}() {
.lookup_by("tfn")
.add_to(acc);
snippet("pub(crate)", "pub(crate) $0").add_to(acc);
snippet(ctx, "pub(crate)", "pub(crate) $0").add_to(acc);
}
#[cfg(test)]
mod tests {
use crate::completion::{CompletionKind, check_completion};
fn check_snippet_completion(code: &str, expected_completions: &str) {
check_completion(code, expected_completions, CompletionKind::Snippet);
use crate::completion::CompletionKind;
use crate::completion::completion_item::check_completion;
fn check_snippet_completion(name: &str, code: &str) {
check_completion(name, code, CompletionKind::Snippet);
}
#[test]
fn completes_snippets_in_expressions() {
check_snippet_completion(
r"fn foo(x: i32) { <|> }",
r##"
pd "eprintln!(\"$0 = {:?}\", $0);"
ppd "eprintln!(\"$0 = {:#?}\", $0);"
"##,
);
check_snippet_completion("snippets_in_expressions", r"fn foo(x: i32) { <|> }");
}
#[test]
fn completes_snippets_in_items() {
// check_snippet_completion(r"
// <|>
// ",
// r##"[CompletionItem { label: "Test function", lookup: None, snippet: Some("#[test]\nfn test_${1:feature}() {\n$0\n}"##,
// );
check_snippet_completion(
"snippets_in_items",
r"
#[cfg(test)]
mod tests {
<|>
}
",
r##"
tfn "Test function" "#[test]\nfn ${1:feature}() {\n $0\n}"
pub(crate) "pub(crate) $0"
"##,
);
}
}

View file

@ -12,7 +12,7 @@ use crate::{db, FilePosition};
/// `CompletionContext` is created early during completion to figure out, where
/// exactly is the cursor, syntax-wise.
#[derive(Debug)]
pub(super) struct CompletionContext<'a> {
pub(crate) struct CompletionContext<'a> {
pub(super) db: &'a db::RootDatabase,
pub(super) offset: TextUnit,
pub(super) leaf: &'a SyntaxNode,
@ -65,6 +65,17 @@ impl<'a> CompletionContext<'a> {
Some(ctx)
}
// The range of the identifier that is being completed.
// This is purely advisory and can be used, for example, to highlight this range in the editor.
// Clients are expected to ignore this field.
pub(crate) fn source_range(&self) -> TextRange {
match self.leaf.kind() {
// workaroud when completion is triggered by trigger characters.
DOT | COLONCOLON => TextRange::from_to(self.offset, self.offset),
_ => self.leaf.range(),
}
}
fn fill(&mut self, original_file: &'a SourceFile, offset: TextUnit) {
// Insert a fake ident to get a valid parse tree. We will use this file
// to determine context, though the original_file will be used for

View file

@ -1,6 +1,8 @@
use hir::PerNs;
use crate::completion::CompletionContext;
use crate::completion::completion_context::CompletionContext;
use ra_syntax::TextRange;
use ra_text_edit::TextEdit;
/// `CompletionItem` describes a single completion variant in the editor pop-up.
/// It is basically a POD with various properties. To construct a
@ -11,15 +13,13 @@ pub struct CompletionItem {
/// completion.
completion_kind: CompletionKind,
label: String,
kind: Option<CompletionItemKind>,
detail: Option<String>,
lookup: Option<String>,
snippet: Option<String>,
kind: Option<CompletionItemKind>,
}
pub enum InsertText {
PlainText { text: String },
Snippet { text: String },
insert_text: Option<String>,
insert_text_format: InsertTextFormat,
source_range: TextRange,
text_edit: Option<TextEdit>,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
@ -40,7 +40,7 @@ pub enum CompletionItemKind {
Method,
}
#[derive(Debug, PartialEq, Eq)]
#[derive(Debug, PartialEq, Eq, Copy, Clone)]
pub(crate) enum CompletionKind {
/// Parser-based keyword completion.
Keyword,
@ -51,16 +51,29 @@ pub(crate) enum CompletionKind {
Snippet,
}
#[derive(Debug, PartialEq, Eq, Copy, Clone)]
pub enum InsertTextFormat {
PlainText,
Snippet,
}
impl CompletionItem {
pub(crate) fn new(completion_kind: CompletionKind, label: impl Into<String>) -> Builder {
pub(crate) fn new(
completion_kind: CompletionKind,
replace_range: TextRange,
label: impl Into<String>,
) -> Builder {
let label = label.into();
Builder {
source_range: replace_range,
completion_kind,
label,
insert_text: None,
insert_text_format: InsertTextFormat::PlainText,
detail: None,
lookup: None,
snippet: None,
kind: None,
text_edit: None,
}
}
/// What user sees in pop-up in the UI.
@ -78,30 +91,39 @@ impl CompletionItem {
.map(|it| it.as_str())
.unwrap_or(self.label())
}
/// What is inserted.
pub fn insert_text(&self) -> InsertText {
match &self.snippet {
None => InsertText::PlainText {
text: self.label.clone(),
},
Some(it) => InsertText::Snippet { text: it.clone() },
pub fn insert_text_format(&self) -> InsertTextFormat {
self.insert_text_format.clone()
}
pub fn insert_text(&self) -> String {
match &self.insert_text {
Some(t) => t.clone(),
None => self.label.clone(),
}
}
pub fn kind(&self) -> Option<CompletionItemKind> {
self.kind
}
pub fn take_text_edit(&mut self) -> Option<TextEdit> {
self.text_edit.take()
}
pub fn source_range(&self) -> TextRange {
self.source_range
}
}
/// A helper to make `CompletionItem`s.
#[must_use]
pub(crate) struct Builder {
source_range: TextRange,
completion_kind: CompletionKind,
label: String,
insert_text: Option<String>,
insert_text_format: InsertTextFormat,
detail: Option<String>,
lookup: Option<String>,
snippet: Option<String>,
kind: Option<CompletionItemKind>,
text_edit: Option<TextEdit>,
}
impl Builder {
@ -111,27 +133,44 @@ impl Builder {
pub(crate) fn build(self) -> CompletionItem {
CompletionItem {
source_range: self.source_range,
label: self.label,
detail: self.detail,
insert_text_format: self.insert_text_format,
lookup: self.lookup,
snippet: self.snippet,
kind: self.kind,
completion_kind: self.completion_kind,
text_edit: self.text_edit,
insert_text: self.insert_text,
}
}
pub(crate) fn lookup_by(mut self, lookup: impl Into<String>) -> Builder {
self.lookup = Some(lookup.into());
self
}
pub(crate) fn snippet(mut self, snippet: impl Into<String>) -> Builder {
self.snippet = Some(snippet.into());
pub(crate) fn insert_text(mut self, insert_text: impl Into<String>) -> Builder {
self.insert_text = Some(insert_text.into());
self
}
#[allow(unused)]
pub(crate) fn insert_text_format(mut self, insert_text_format: InsertTextFormat) -> Builder {
self.insert_text_format = insert_text_format;
self
}
pub(crate) fn snippet(mut self, snippet: impl Into<String>) -> Builder {
self.insert_text_format = InsertTextFormat::Snippet;
self.insert_text(snippet)
}
pub(crate) fn kind(mut self, kind: CompletionItemKind) -> Builder {
self.kind = Some(kind);
self
}
#[allow(unused)]
pub(crate) fn text_edit(mut self, edit: TextEdit) -> Builder {
self.text_edit = Some(edit);
self
}
#[allow(unused)]
pub(crate) fn detail(self, detail: impl Into<String>) -> Builder {
self.set_detail(Some(detail))
}
@ -192,17 +231,18 @@ impl Builder {
// If not an import, add parenthesis automatically.
if ctx.use_item_syntax.is_none() && !ctx.is_call {
if function.signature(ctx.db).params().is_empty() {
self.snippet = Some(format!("{}()$0", self.label));
self.insert_text = Some(format!("{}()$0", self.label));
} else {
self.snippet = Some(format!("{}($0)", self.label));
self.insert_text = Some(format!("{}($0)", self.label));
}
self.insert_text_format = InsertTextFormat::Snippet;
}
self.kind = Some(CompletionItemKind::Function);
self
}
}
impl Into<CompletionItem> for Builder {
impl<'a> Into<CompletionItem> for Builder {
fn into(self) -> CompletionItem {
self.build()
}
@ -225,60 +265,6 @@ impl Completions {
{
items.into_iter().for_each(|item| self.add(item.into()))
}
#[cfg(test)]
pub(crate) fn assert_match(&self, expected: &str, kind: CompletionKind) {
let expected = normalize(expected);
let actual = self.debug_render(kind);
test_utils::assert_eq_text!(expected.as_str(), actual.as_str(),);
/// Normalize the textual representation of `Completions`:
/// replace `;` with newlines, normalize whitespace
fn normalize(expected: &str) -> String {
use ra_syntax::{tokenize, TextUnit, TextRange, SyntaxKind::SEMI};
let mut res = String::new();
for line in expected.trim().lines() {
let line = line.trim();
let mut start_offset: TextUnit = 0.into();
// Yep, we use rust tokenize in completion tests :-)
for token in tokenize(line) {
let range = TextRange::offset_len(start_offset, token.len);
start_offset += token.len;
if token.kind == SEMI {
res.push('\n');
} else {
res.push_str(&line[range]);
}
}
res.push('\n');
}
res
}
}
#[cfg(test)]
fn debug_render(&self, kind: CompletionKind) -> String {
let mut res = String::new();
for c in self.buf.iter() {
if c.completion_kind == kind {
if let Some(lookup) = &c.lookup {
res.push_str(lookup);
res.push_str(&format!(" {:?}", c.label));
} else {
res.push_str(&c.label);
}
if let Some(detail) = &c.detail {
res.push_str(&format!(" {:?}", detail));
}
if let Some(snippet) = &c.snippet {
res.push_str(&format!(" {:?}", snippet));
}
res.push('\n');
}
}
res
}
}
impl Into<Vec<CompletionItem>> for Completions {
@ -286,3 +272,22 @@ impl Into<Vec<CompletionItem>> for Completions {
self.buf
}
}
#[cfg(test)]
pub(crate) fn check_completion(test_name: &str, code: &str, kind: CompletionKind) {
use crate::mock_analysis::{single_file_with_position, analysis_and_position};
use crate::completion::completions;
use insta::assert_debug_snapshot_matches;
let (analysis, position) = if code.contains("//-") {
analysis_and_position(code)
} else {
single_file_with_position(code)
};
let completions = completions(&analysis.db, position).unwrap();
let completion_items: Vec<CompletionItem> = completions.into();
let kind_completions: Vec<CompletionItem> = completion_items
.into_iter()
.filter(|c| c.completion_kind == kind)
.collect();
assert_debug_snapshot_matches!(test_name, kind_completions);
}

View file

@ -0,0 +1,34 @@
Created: 2019-01-20T04:00:48.241096+00:00
Creator: insta@0.1.4
Source: crates/ra_ide_api/src/completion/completion_item.rs
[
CompletionItem {
completion_kind: Reference,
label: "x",
kind: Some(
Binding
),
detail: None,
lookup: None,
insert_text: None,
insert_text_format: PlainText,
source_range: [62; 100),
text_edit: None
},
CompletionItem {
completion_kind: Reference,
label: "quux",
kind: Some(
Function
),
detail: None,
lookup: None,
insert_text: Some(
"quux()$0"
),
insert_text_format: Snippet,
source_range: [62; 100),
text_edit: None
}
]

View file

@ -0,0 +1,47 @@
Created: 2019-01-20T04:00:48.242456+00:00
Creator: insta@0.1.4
Source: crates/ra_ide_api/src/completion/completion_item.rs
[
CompletionItem {
completion_kind: Reference,
label: "b",
kind: Some(
Binding
),
detail: None,
lookup: None,
insert_text: None,
insert_text_format: PlainText,
source_range: [213; 231),
text_edit: None
},
CompletionItem {
completion_kind: Reference,
label: "a",
kind: Some(
Binding
),
detail: None,
lookup: None,
insert_text: None,
insert_text_format: PlainText,
source_range: [213; 231),
text_edit: None
},
CompletionItem {
completion_kind: Reference,
label: "quux",
kind: Some(
Function
),
detail: None,
lookup: None,
insert_text: Some(
"quux()$0"
),
insert_text_format: Snippet,
source_range: [213; 231),
text_edit: None
}
]

View file

@ -0,0 +1,47 @@
Created: 2019-01-20T04:00:48.243016+00:00
Creator: insta@0.1.4
Source: crates/ra_ide_api/src/completion/completion_item.rs
[
CompletionItem {
completion_kind: Reference,
label: "y",
kind: Some(
Binding
),
detail: None,
lookup: None,
insert_text: None,
insert_text_format: PlainText,
source_range: [78; 79),
text_edit: None
},
CompletionItem {
completion_kind: Reference,
label: "x",
kind: Some(
Binding
),
detail: None,
lookup: None,
insert_text: None,
insert_text_format: PlainText,
source_range: [78; 79),
text_edit: None
},
CompletionItem {
completion_kind: Reference,
label: "quux",
kind: Some(
Function
),
detail: None,
lookup: None,
insert_text: Some(
"quux($0)"
),
insert_text_format: Snippet,
source_range: [78; 79),
text_edit: None
}
]

View file

@ -0,0 +1,111 @@
Created: 2019-01-20T04:00:48.206357+00:00
Creator: insta@0.1.4
Source: crates/ra_ide_api/src/completion/completion_item.rs
[
CompletionItem {
completion_kind: Keyword,
label: "if",
kind: Some(
Keyword
),
detail: None,
lookup: None,
insert_text: Some(
"if $0 {}"
),
insert_text_format: Snippet,
source_range: [54; 56),
text_edit: None
},
CompletionItem {
completion_kind: Keyword,
label: "match",
kind: Some(
Keyword
),
detail: None,
lookup: None,
insert_text: Some(
"match $0 {}"
),
insert_text_format: Snippet,
source_range: [54; 56),
text_edit: None
},
CompletionItem {
completion_kind: Keyword,
label: "while",
kind: Some(
Keyword
),
detail: None,
lookup: None,
insert_text: Some(
"while $0 {}"
),
insert_text_format: Snippet,
source_range: [54; 56),
text_edit: None
},
CompletionItem {
completion_kind: Keyword,
label: "loop",
kind: Some(
Keyword
),
detail: None,
lookup: None,
insert_text: Some(
"loop {$0}"
),
insert_text_format: Snippet,
source_range: [54; 56),
text_edit: None
},
CompletionItem {
completion_kind: Keyword,
label: "continue",
kind: Some(
Keyword
),
detail: None,
lookup: None,
insert_text: Some(
"continue;"
),
insert_text_format: Snippet,
source_range: [54; 56),
text_edit: None
},
CompletionItem {
completion_kind: Keyword,
label: "break",
kind: Some(
Keyword
),
detail: None,
lookup: None,
insert_text: Some(
"break;"
),
insert_text_format: Snippet,
source_range: [54; 56),
text_edit: None
},
CompletionItem {
completion_kind: Keyword,
label: "return",
kind: Some(
Keyword
),
detail: None,
lookup: None,
insert_text: Some(
"return $0;"
),
insert_text_format: Snippet,
source_range: [54; 56),
text_edit: None
}
]

View file

@ -0,0 +1,81 @@
Created: 2019-01-20T04:00:48.217822+00:00
Creator: insta@0.1.4
Source: crates/ra_ide_api/src/completion/completion_item.rs
[
CompletionItem {
completion_kind: Keyword,
label: "if",
kind: Some(
Keyword
),
detail: None,
lookup: None,
insert_text: Some(
"if $0 {}"
),
insert_text_format: Snippet,
source_range: [59; 61),
text_edit: None
},
CompletionItem {
completion_kind: Keyword,
label: "match",
kind: Some(
Keyword
),
detail: None,
lookup: None,
insert_text: Some(
"match $0 {}"
),
insert_text_format: Snippet,
source_range: [59; 61),
text_edit: None
},
CompletionItem {
completion_kind: Keyword,
label: "while",
kind: Some(
Keyword
),
detail: None,
lookup: None,
insert_text: Some(
"while $0 {}"
),
insert_text_format: Snippet,
source_range: [59; 61),
text_edit: None
},
CompletionItem {
completion_kind: Keyword,
label: "loop",
kind: Some(
Keyword
),
detail: None,
lookup: None,
insert_text: Some(
"loop {$0}"
),
insert_text_format: Snippet,
source_range: [59; 61),
text_edit: None
},
CompletionItem {
completion_kind: Keyword,
label: "return",
kind: Some(
Keyword
),
detail: None,
lookup: None,
insert_text: Some(
"return $0;"
),
insert_text_format: Snippet,
source_range: [59; 61),
text_edit: None
}
]

View file

@ -0,0 +1,102 @@
Created: 2019-01-19T13:50:41.824939+00:00
Creator: insta@0.1.4
Source: crates/ra_ide_api/src/completion/completion_item.rs
[
CompletionItem {
completion_kind: Postfix,
label: "not",
kind: None,
detail: None,
lookup: None,
insert_text_format: Snippet,
text_edit: Some(
AtomTextEdit {
delete: [78; 78),
insert: "!not"
}
),
additional_text_edits: Some(
TextEdit {
atoms: [
AtomTextEdit {
delete: [72; 78),
insert: ""
}
]
}
)
},
CompletionItem {
completion_kind: Postfix,
label: "if",
kind: None,
detail: None,
lookup: None,
insert_text_format: Snippet,
text_edit: Some(
AtomTextEdit {
delete: [78; 78),
insert: "if bar {$0}"
}
),
additional_text_edits: Some(
TextEdit {
atoms: [
AtomTextEdit {
delete: [72; 78),
insert: ""
}
]
}
)
},
CompletionItem {
completion_kind: Postfix,
label: "match",
kind: None,
detail: None,
lookup: None,
insert_text_format: Snippet,
text_edit: Some(
AtomTextEdit {
delete: [78; 78),
insert: "match bar {\n${1:_} => {$0\\},\n}"
}
),
additional_text_edits: Some(
TextEdit {
atoms: [
AtomTextEdit {
delete: [72; 78),
insert: ""
}
]
}
)
},
CompletionItem {
completion_kind: Postfix,
label: "while",
kind: None,
detail: None,
lookup: None,
insert_text_format: Snippet,
text_edit: Some(
AtomTextEdit {
delete: [78; 78),
insert: "while bar {\n$0\n}"
}
),
additional_text_edits: Some(
TextEdit {
atoms: [
AtomTextEdit {
delete: [72; 78),
insert: ""
}
]
}
)
}
]

View file

@ -0,0 +1,19 @@
Created: 2019-01-20T04:00:48.217724+00:00
Creator: insta@0.1.4
Source: crates/ra_ide_api/src/completion/completion_item.rs
[
CompletionItem {
completion_kind: Reference,
label: "Spam",
kind: Some(
Struct
),
detail: None,
lookup: None,
insert_text: None,
insert_text_format: PlainText,
source_range: [23; 25),
text_edit: None
}
]

View file

@ -0,0 +1,81 @@
Created: 2019-01-20T04:00:48.208392+00:00
Creator: insta@0.1.4
Source: crates/ra_ide_api/src/completion/completion_item.rs
[
CompletionItem {
completion_kind: Keyword,
label: "if",
kind: Some(
Keyword
),
detail: None,
lookup: None,
insert_text: Some(
"if $0 {}"
),
insert_text_format: Snippet,
source_range: [84; 102),
text_edit: None
},
CompletionItem {
completion_kind: Keyword,
label: "match",
kind: Some(
Keyword
),
detail: None,
lookup: None,
insert_text: Some(
"match $0 {}"
),
insert_text_format: Snippet,
source_range: [84; 102),
text_edit: None
},
CompletionItem {
completion_kind: Keyword,
label: "while",
kind: Some(
Keyword
),
detail: None,
lookup: None,
insert_text: Some(
"while $0 {}"
),
insert_text_format: Snippet,
source_range: [84; 102),
text_edit: None
},
CompletionItem {
completion_kind: Keyword,
label: "loop",
kind: Some(
Keyword
),
detail: None,
lookup: None,
insert_text: Some(
"loop {$0}"
),
insert_text_format: Snippet,
source_range: [84; 102),
text_edit: None
},
CompletionItem {
completion_kind: Keyword,
label: "return",
kind: Some(
Keyword
),
detail: None,
lookup: None,
insert_text: Some(
"return $0"
),
insert_text_format: Snippet,
source_range: [84; 102),
text_edit: None
}
]

View file

@ -0,0 +1,32 @@
Created: 2019-01-20T04:00:48.239872+00:00
Creator: insta@0.1.4
Source: crates/ra_ide_api/src/completion/completion_item.rs
[
CompletionItem {
completion_kind: Reference,
label: "main",
kind: Some(
Function
),
detail: None,
lookup: None,
insert_text: None,
insert_text_format: PlainText,
source_range: [35; 39),
text_edit: None
},
CompletionItem {
completion_kind: Reference,
label: "frobnicate",
kind: Some(
Function
),
detail: None,
lookup: None,
insert_text: None,
insert_text_format: PlainText,
source_range: [35; 39),
text_edit: None
}
]

View file

@ -0,0 +1,19 @@
Created: 2019-01-20T04:00:48.239894+00:00
Creator: insta@0.1.4
Source: crates/ra_ide_api/src/completion/completion_item.rs
[
CompletionItem {
completion_kind: Reference,
label: "foo",
kind: Some(
Function
),
detail: None,
lookup: None,
insert_text: None,
insert_text_format: PlainText,
source_range: [40; 41),
text_edit: None
}
]

View file

@ -0,0 +1,34 @@
Created: 2019-01-20T04:00:48.248606+00:00
Creator: insta@0.1.4
Source: crates/ra_ide_api/src/completion/completion_item.rs
[
CompletionItem {
completion_kind: Reference,
label: "bar",
kind: Some(
Binding
),
detail: None,
lookup: None,
insert_text: None,
insert_text_format: PlainText,
source_range: [108; 146),
text_edit: None
},
CompletionItem {
completion_kind: Reference,
label: "foo",
kind: Some(
Function
),
detail: None,
lookup: None,
insert_text: Some(
"foo()$0"
),
insert_text_format: Snippet,
source_range: [108; 146),
text_edit: None
}
]

View file

@ -0,0 +1,36 @@
Created: 2019-01-20T04:00:48.249349+00:00
Creator: insta@0.1.4
Source: crates/ra_ide_api/src/completion/completion_item.rs
[
CompletionItem {
completion_kind: Reference,
label: "no_args",
kind: Some(
Function
),
detail: None,
lookup: None,
insert_text: Some(
"no_args()$0"
),
insert_text_format: Snippet,
source_range: [53; 56),
text_edit: None
},
CompletionItem {
completion_kind: Reference,
label: "main",
kind: Some(
Function
),
detail: None,
lookup: None,
insert_text: Some(
"main()$0"
),
insert_text_format: Snippet,
source_range: [53; 56),
text_edit: None
}
]

View file

@ -0,0 +1,36 @@
Created: 2019-01-20T04:00:48.255317+00:00
Creator: insta@0.1.4
Source: crates/ra_ide_api/src/completion/completion_item.rs
[
CompletionItem {
completion_kind: Reference,
label: "main",
kind: Some(
Function
),
detail: None,
lookup: None,
insert_text: Some(
"main()$0"
),
insert_text_format: Snippet,
source_range: [72; 77),
text_edit: None
},
CompletionItem {
completion_kind: Reference,
label: "with_args",
kind: Some(
Function
),
detail: None,
lookup: None,
insert_text: Some(
"with_args($0)"
),
insert_text_format: Snippet,
source_range: [72; 77),
text_edit: None
}
]

View file

@ -0,0 +1,81 @@
Created: 2019-01-20T04:00:48.207728+00:00
Creator: insta@0.1.4
Source: crates/ra_ide_api/src/completion/completion_item.rs
[
CompletionItem {
completion_kind: Keyword,
label: "if",
kind: Some(
Keyword
),
detail: None,
lookup: None,
insert_text: Some(
"if $0 {}"
),
insert_text_format: Snippet,
source_range: [24; 54),
text_edit: None
},
CompletionItem {
completion_kind: Keyword,
label: "match",
kind: Some(
Keyword
),
detail: None,
lookup: None,
insert_text: Some(
"match $0 {}"
),
insert_text_format: Snippet,
source_range: [24; 54),
text_edit: None
},
CompletionItem {
completion_kind: Keyword,
label: "while",
kind: Some(
Keyword
),
detail: None,
lookup: None,
insert_text: Some(
"while $0 {}"
),
insert_text_format: Snippet,
source_range: [24; 54),
text_edit: None
},
CompletionItem {
completion_kind: Keyword,
label: "loop",
kind: Some(
Keyword
),
detail: None,
lookup: None,
insert_text: Some(
"loop {$0}"
),
insert_text_format: Snippet,
source_range: [24; 54),
text_edit: None
},
CompletionItem {
completion_kind: Keyword,
label: "return",
kind: Some(
Keyword
),
detail: None,
lookup: None,
insert_text: Some(
"return;"
),
insert_text_format: Snippet,
source_range: [24; 54),
text_edit: None
}
]

View file

@ -0,0 +1,111 @@
Created: 2019-01-20T04:00:48.207381+00:00
Creator: insta@0.1.4
Source: crates/ra_ide_api/src/completion/completion_item.rs
[
CompletionItem {
completion_kind: Keyword,
label: "if",
kind: Some(
Keyword
),
detail: None,
lookup: None,
insert_text: Some(
"if $0 {}"
),
insert_text_format: Snippet,
source_range: [91; 105),
text_edit: None
},
CompletionItem {
completion_kind: Keyword,
label: "match",
kind: Some(
Keyword
),
detail: None,
lookup: None,
insert_text: Some(
"match $0 {}"
),
insert_text_format: Snippet,
source_range: [91; 105),
text_edit: None
},
CompletionItem {
completion_kind: Keyword,
label: "while",
kind: Some(
Keyword
),
detail: None,
lookup: None,
insert_text: Some(
"while $0 {}"
),
insert_text_format: Snippet,
source_range: [91; 105),
text_edit: None
},
CompletionItem {
completion_kind: Keyword,
label: "loop",
kind: Some(
Keyword
),
detail: None,
lookup: None,
insert_text: Some(
"loop {$0}"
),
insert_text_format: Snippet,
source_range: [91; 105),
text_edit: None
},
CompletionItem {
completion_kind: Keyword,
label: "else",
kind: Some(
Keyword
),
detail: None,
lookup: None,
insert_text: Some(
"else {$0}"
),
insert_text_format: Snippet,
source_range: [91; 105),
text_edit: None
},
CompletionItem {
completion_kind: Keyword,
label: "else if",
kind: Some(
Keyword
),
detail: None,
lookup: None,
insert_text: Some(
"else if $0 {}"
),
insert_text_format: Snippet,
source_range: [91; 105),
text_edit: None
},
CompletionItem {
completion_kind: Keyword,
label: "return",
kind: Some(
Keyword
),
detail: None,
lookup: None,
insert_text: Some(
"return;"
),
insert_text_format: Snippet,
source_range: [91; 105),
text_edit: None
}
]

View file

@ -0,0 +1,81 @@
Created: 2019-01-20T04:00:48.211090+00:00
Creator: insta@0.1.4
Source: crates/ra_ide_api/src/completion/completion_item.rs
[
CompletionItem {
completion_kind: Keyword,
label: "if",
kind: Some(
Keyword
),
detail: None,
lookup: None,
insert_text: Some(
"if $0 {}"
),
insert_text_format: Snippet,
source_range: [31; 65),
text_edit: None
},
CompletionItem {
completion_kind: Keyword,
label: "match",
kind: Some(
Keyword
),
detail: None,
lookup: None,
insert_text: Some(
"match $0 {}"
),
insert_text_format: Snippet,
source_range: [31; 65),
text_edit: None
},
CompletionItem {
completion_kind: Keyword,
label: "while",
kind: Some(
Keyword
),
detail: None,
lookup: None,
insert_text: Some(
"while $0 {}"
),
insert_text_format: Snippet,
source_range: [31; 65),
text_edit: None
},
CompletionItem {
completion_kind: Keyword,
label: "loop",
kind: Some(
Keyword
),
detail: None,
lookup: None,
insert_text: Some(
"loop {$0}"
),
insert_text_format: Snippet,
source_range: [31; 65),
text_edit: None
},
CompletionItem {
completion_kind: Keyword,
label: "return",
kind: Some(
Keyword
),
detail: None,
lookup: None,
insert_text: Some(
"return $0;"
),
insert_text_format: Snippet,
source_range: [31; 65),
text_edit: None
}
]

View file

@ -0,0 +1,81 @@
Created: 2019-01-20T04:00:48.218272+00:00
Creator: insta@0.1.4
Source: crates/ra_ide_api/src/completion/completion_item.rs
[
CompletionItem {
completion_kind: Keyword,
label: "if",
kind: Some(
Keyword
),
detail: None,
lookup: None,
insert_text: Some(
"if $0 {}"
),
insert_text_format: Snippet,
source_range: [24; 58),
text_edit: None
},
CompletionItem {
completion_kind: Keyword,
label: "match",
kind: Some(
Keyword
),
detail: None,
lookup: None,
insert_text: Some(
"match $0 {}"
),
insert_text_format: Snippet,
source_range: [24; 58),
text_edit: None
},
CompletionItem {
completion_kind: Keyword,
label: "while",
kind: Some(
Keyword
),
detail: None,
lookup: None,
insert_text: Some(
"while $0 {}"
),
insert_text_format: Snippet,
source_range: [24; 58),
text_edit: None
},
CompletionItem {
completion_kind: Keyword,
label: "loop",
kind: Some(
Keyword
),
detail: None,
lookup: None,
insert_text: Some(
"loop {$0}"
),
insert_text_format: Snippet,
source_range: [24; 58),
text_edit: None
},
CompletionItem {
completion_kind: Keyword,
label: "return",
kind: Some(
Keyword
),
detail: None,
lookup: None,
insert_text: Some(
"return;"
),
insert_text_format: Snippet,
source_range: [24; 58),
text_edit: None
}
]

View file

@ -0,0 +1,49 @@
Created: 2019-01-20T04:00:48.207433+00:00
Creator: insta@0.1.4
Source: crates/ra_ide_api/src/completion/completion_item.rs
[
CompletionItem {
completion_kind: Keyword,
label: "crate",
kind: Some(
Keyword
),
detail: None,
lookup: None,
insert_text: Some(
"crate::"
),
insert_text_format: PlainText,
source_range: [16; 30),
text_edit: None
},
CompletionItem {
completion_kind: Keyword,
label: "self",
kind: Some(
Keyword
),
detail: None,
lookup: None,
insert_text: None,
insert_text_format: PlainText,
source_range: [16; 30),
text_edit: None
},
CompletionItem {
completion_kind: Keyword,
label: "super",
kind: Some(
Keyword
),
detail: None,
lookup: None,
insert_text: Some(
"super::"
),
insert_text_format: PlainText,
source_range: [16; 30),
text_edit: None
}
]

View file

@ -0,0 +1,34 @@
Created: 2019-01-20T09:26:20.872623+00:00
Creator: insta@0.1.4
Source: crates/ra_ide_api/src/completion/completion_item.rs
[
CompletionItem {
completion_kind: Keyword,
label: "self",
kind: Some(
Keyword
),
detail: None,
lookup: None,
insert_text: None,
insert_text_format: PlainText,
source_range: [20; 20),
text_edit: None
},
CompletionItem {
completion_kind: Keyword,
label: "super",
kind: Some(
Keyword
),
detail: None,
lookup: None,
insert_text: Some(
"super::"
),
insert_text_format: PlainText,
source_range: [20; 20),
text_edit: None
}
]

View file

@ -0,0 +1,34 @@
Created: 2019-01-20T04:00:48.217815+00:00
Creator: insta@0.1.4
Source: crates/ra_ide_api/src/completion/completion_item.rs
[
CompletionItem {
completion_kind: Keyword,
label: "self",
kind: Some(
Keyword
),
detail: None,
lookup: None,
insert_text: None,
insert_text_format: PlainText,
source_range: [23; 24),
text_edit: None
},
CompletionItem {
completion_kind: Keyword,
label: "super",
kind: Some(
Keyword
),
detail: None,
lookup: None,
insert_text: Some(
"super::"
),
insert_text_format: PlainText,
source_range: [23; 24),
text_edit: None
}
]

View file

@ -0,0 +1,81 @@
Created: 2019-01-20T04:00:48.208669+00:00
Creator: insta@0.1.4
Source: crates/ra_ide_api/src/completion/completion_item.rs
[
CompletionItem {
completion_kind: Keyword,
label: "if",
kind: Some(
Keyword
),
detail: None,
lookup: None,
insert_text: Some(
"if $0 {}"
),
insert_text_format: Snippet,
source_range: [62; 100),
text_edit: None
},
CompletionItem {
completion_kind: Keyword,
label: "match",
kind: Some(
Keyword
),
detail: None,
lookup: None,
insert_text: Some(
"match $0 {}"
),
insert_text_format: Snippet,
source_range: [62; 100),
text_edit: None
},
CompletionItem {
completion_kind: Keyword,
label: "while",
kind: Some(
Keyword
),
detail: None,
lookup: None,
insert_text: Some(
"while $0 {}"
),
insert_text_format: Snippet,
source_range: [62; 100),
text_edit: None
},
CompletionItem {
completion_kind: Keyword,
label: "loop",
kind: Some(
Keyword
),
detail: None,
lookup: None,
insert_text: Some(
"loop {$0}"
),
insert_text_format: Snippet,
source_range: [62; 100),
text_edit: None
},
CompletionItem {
completion_kind: Keyword,
label: "return",
kind: Some(
Keyword
),
detail: None,
lookup: None,
insert_text: Some(
"return $0;"
),
insert_text_format: Snippet,
source_range: [62; 100),
text_edit: None
}
]

View file

@ -0,0 +1,81 @@
Created: 2019-01-20T04:00:48.221138+00:00
Creator: insta@0.1.4
Source: crates/ra_ide_api/src/completion/completion_item.rs
[
CompletionItem {
completion_kind: Keyword,
label: "if",
kind: Some(
Keyword
),
detail: None,
lookup: None,
insert_text: Some(
"if $0 {}"
),
insert_text_format: Snippet,
source_range: [62; 100),
text_edit: None
},
CompletionItem {
completion_kind: Keyword,
label: "match",
kind: Some(
Keyword
),
detail: None,
lookup: None,
insert_text: Some(
"match $0 {}"
),
insert_text_format: Snippet,
source_range: [62; 100),
text_edit: None
},
CompletionItem {
completion_kind: Keyword,
label: "while",
kind: Some(
Keyword
),
detail: None,
lookup: None,
insert_text: Some(
"while $0 {}"
),
insert_text_format: Snippet,
source_range: [62; 100),
text_edit: None
},
CompletionItem {
completion_kind: Keyword,
label: "loop",
kind: Some(
Keyword
),
detail: None,
lookup: None,
insert_text: Some(
"loop {$0}"
),
insert_text_format: Snippet,
source_range: [62; 100),
text_edit: None
},
CompletionItem {
completion_kind: Keyword,
label: "return",
kind: Some(
Keyword
),
detail: None,
lookup: None,
insert_text: Some(
"return $0;"
),
insert_text_format: Snippet,
source_range: [62; 100),
text_edit: None
}
]

View file

@ -0,0 +1,21 @@
Created: 2019-01-20T09:26:20.868112+00:00
Creator: insta@0.1.4
Source: crates/ra_ide_api/src/completion/completion_item.rs
[
CompletionItem {
completion_kind: Reference,
label: "the_method",
kind: Some(
Method
),
detail: None,
lookup: None,
insert_text: Some(
"the_method($0)"
),
insert_text_format: Snippet,
source_range: [144; 144),
text_edit: None
}
]

View file

@ -0,0 +1,47 @@
Created: 2019-01-20T04:00:48.243581+00:00
Creator: insta@0.1.4
Source: crates/ra_ide_api/src/completion/completion_item.rs
[
CompletionItem {
completion_kind: Reference,
label: "quux",
kind: Some(
Function
),
detail: None,
lookup: None,
insert_text: Some(
"quux()$0"
),
insert_text_format: Snippet,
source_range: [72; 102),
text_edit: None
},
CompletionItem {
completion_kind: Reference,
label: "Foo",
kind: Some(
Struct
),
detail: None,
lookup: None,
insert_text: None,
insert_text_format: PlainText,
source_range: [72; 102),
text_edit: None
},
CompletionItem {
completion_kind: Reference,
label: "Baz",
kind: Some(
Enum
),
detail: None,
lookup: None,
insert_text: None,
insert_text_format: PlainText,
source_range: [72; 102),
text_edit: None
}
]

View file

@ -0,0 +1,34 @@
Created: 2019-01-20T04:00:48.244757+00:00
Creator: insta@0.1.4
Source: crates/ra_ide_api/src/completion/completion_item.rs
[
CompletionItem {
completion_kind: Reference,
label: "quux",
kind: Some(
Function
),
detail: None,
lookup: None,
insert_text: Some(
"quux()$0"
),
insert_text_format: Snippet,
source_range: [100; 102),
text_edit: None
},
CompletionItem {
completion_kind: Reference,
label: "Bar",
kind: Some(
Struct
),
detail: None,
lookup: None,
insert_text: None,
insert_text_format: PlainText,
source_range: [100; 102),
text_edit: None
}
]

View file

@ -0,0 +1,32 @@
Created: 2019-01-20T04:00:48.222109+00:00
Creator: insta@0.1.4
Source: crates/ra_ide_api/src/completion/completion_item.rs
[
CompletionItem {
completion_kind: Reference,
label: "Spam",
kind: Some(
Struct
),
detail: None,
lookup: None,
insert_text: None,
insert_text_format: PlainText,
source_range: [12; 14),
text_edit: None
},
CompletionItem {
completion_kind: Reference,
label: "foo",
kind: Some(
Module
),
detail: None,
lookup: None,
insert_text: None,
insert_text_format: PlainText,
source_range: [12; 14),
text_edit: None
}
]

View file

@ -0,0 +1,5 @@
Created: 2019-01-19T11:34:11.702251+00:00
Creator: insta@0.1.4
Source: crates/ra_ide_api/src/completion/completion_item.rs
[]

View file

@ -0,0 +1,111 @@
Created: 2019-01-20T04:00:48.209867+00:00
Creator: insta@0.1.4
Source: crates/ra_ide_api/src/completion/completion_item.rs
[
CompletionItem {
completion_kind: Keyword,
label: "if",
kind: Some(
Keyword
),
detail: None,
lookup: None,
insert_text: Some(
"if $0 {}"
),
insert_text_format: Snippet,
source_range: [106; 108),
text_edit: None
},
CompletionItem {
completion_kind: Keyword,
label: "match",
kind: Some(
Keyword
),
detail: None,
lookup: None,
insert_text: Some(
"match $0 {}"
),
insert_text_format: Snippet,
source_range: [106; 108),
text_edit: None
},
CompletionItem {
completion_kind: Keyword,
label: "while",
kind: Some(
Keyword
),
detail: None,
lookup: None,
insert_text: Some(
"while $0 {}"
),
insert_text_format: Snippet,
source_range: [106; 108),
text_edit: None
},
CompletionItem {
completion_kind: Keyword,
label: "loop",
kind: Some(
Keyword
),
detail: None,
lookup: None,
insert_text: Some(
"loop {$0}"
),
insert_text_format: Snippet,
source_range: [106; 108),
text_edit: None
},
CompletionItem {
completion_kind: Keyword,
label: "continue",
kind: Some(
Keyword
),
detail: None,
lookup: None,
insert_text: Some(
"continue"
),
insert_text_format: Snippet,
source_range: [106; 108),
text_edit: None
},
CompletionItem {
completion_kind: Keyword,
label: "break",
kind: Some(
Keyword
),
detail: None,
lookup: None,
insert_text: Some(
"break"
),
insert_text_format: Snippet,
source_range: [106; 108),
text_edit: None
},
CompletionItem {
completion_kind: Keyword,
label: "return",
kind: Some(
Keyword
),
detail: None,
lookup: None,
insert_text: Some(
"return"
),
insert_text_format: Snippet,
source_range: [106; 108),
text_edit: None
}
]

View file

@ -0,0 +1,5 @@
Created: 2019-01-19T11:34:11.702201+00:00
Creator: insta@0.1.4
Source: crates/ra_ide_api/src/completion/completion_item.rs
[]

View file

@ -0,0 +1,19 @@
Created: 2019-01-20T04:00:48.203211+00:00
Creator: insta@0.1.4
Source: crates/ra_ide_api/src/completion/completion_item.rs
[
CompletionItem {
completion_kind: Magic,
label: "file_id: FileId",
kind: None,
detail: None,
lookup: Some(
"file_id"
),
insert_text: None,
insert_text_format: PlainText,
source_range: [98; 102),
text_edit: None
}
]

View file

@ -0,0 +1,19 @@
Created: 2019-01-20T04:00:48.203236+00:00
Creator: insta@0.1.4
Source: crates/ra_ide_api/src/completion/completion_item.rs
[
CompletionItem {
completion_kind: Magic,
label: "file_id: FileId",
kind: None,
detail: None,
lookup: Some(
"file_id"
),
insert_text: None,
insert_text_format: PlainText,
source_range: [98; 102),
text_edit: None
}
]

View file

@ -0,0 +1,19 @@
Created: 2019-01-20T04:00:48.206552+00:00
Creator: insta@0.1.4
Source: crates/ra_ide_api/src/completion/completion_item.rs
[
CompletionItem {
completion_kind: Magic,
label: "file_id: FileId",
kind: None,
detail: None,
lookup: Some(
"file_id"
),
insert_text: None,
insert_text_format: PlainText,
source_range: [269; 273),
text_edit: None
}
]

View file

@ -0,0 +1,32 @@
Created: 2019-01-20T09:26:20.899262+00:00
Creator: insta@0.1.4
Source: crates/ra_ide_api/src/completion/completion_item.rs
[
CompletionItem {
completion_kind: Reference,
label: "Foo",
kind: Some(
EnumVariant
),
detail: None,
lookup: None,
insert_text: None,
insert_text_format: PlainText,
source_range: [47; 47),
text_edit: None
},
CompletionItem {
completion_kind: Reference,
label: "Bar",
kind: Some(
EnumVariant
),
detail: None,
lookup: None,
insert_text: None,
insert_text_format: PlainText,
source_range: [47; 47),
text_edit: None
}
]

View file

@ -0,0 +1,34 @@
Created: 2019-01-20T04:00:48.245820+00:00
Creator: insta@0.1.4
Source: crates/ra_ide_api/src/completion/completion_item.rs
[
CompletionItem {
completion_kind: Reference,
label: "Foo",
kind: Some(
Struct
),
detail: None,
lookup: None,
insert_text: None,
insert_text_format: PlainText,
source_range: [46; 60),
text_edit: None
},
CompletionItem {
completion_kind: Reference,
label: "x",
kind: Some(
Function
),
detail: None,
lookup: None,
insert_text: Some(
"x()$0"
),
insert_text_format: Snippet,
source_range: [46; 60),
text_edit: None
}
]

View file

@ -0,0 +1,19 @@
Created: 2019-01-20T04:00:48.244260+00:00
Creator: insta@0.1.4
Source: crates/ra_ide_api/src/completion/completion_item.rs
[
CompletionItem {
completion_kind: Reference,
label: "self",
kind: Some(
Binding
),
detail: None,
lookup: None,
insert_text: None,
insert_text_format: PlainText,
source_range: [24; 26),
text_edit: None
}
]

View file

@ -0,0 +1,36 @@
Created: 2019-01-20T04:00:48.252281+00:00
Creator: insta@0.1.4
Source: crates/ra_ide_api/src/completion/completion_item.rs
[
CompletionItem {
completion_kind: Snippet,
label: "pd",
kind: Some(
Snippet
),
detail: None,
lookup: None,
insert_text: Some(
"eprintln!(\"$0 = {:?}\", $0);"
),
insert_text_format: Snippet,
source_range: [16; 18),
text_edit: None
},
CompletionItem {
completion_kind: Snippet,
label: "ppd",
kind: Some(
Snippet
),
detail: None,
lookup: None,
insert_text: Some(
"eprintln!(\"$0 = {:#?}\", $0);"
),
insert_text_format: Snippet,
source_range: [16; 18),
text_edit: None
}
]

View file

@ -0,0 +1,38 @@
Created: 2019-01-20T04:00:48.253073+00:00
Creator: insta@0.1.4
Source: crates/ra_ide_api/src/completion/completion_item.rs
[
CompletionItem {
completion_kind: Snippet,
label: "Test function",
kind: Some(
Snippet
),
detail: None,
lookup: Some(
"tfn"
),
insert_text: Some(
"#[test]\nfn ${1:feature}() {\n $0\n}"
),
insert_text_format: Snippet,
source_range: [49; 79),
text_edit: None
},
CompletionItem {
completion_kind: Snippet,
label: "pub(crate)",
kind: Some(
Snippet
),
detail: None,
lookup: None,
insert_text: Some(
"pub(crate) $0"
),
insert_text_format: Snippet,
source_range: [49; 79),
text_edit: None
}
]

View file

@ -0,0 +1,21 @@
Created: 2019-01-20T09:26:20.868146+00:00
Creator: insta@0.1.4
Source: crates/ra_ide_api/src/completion/completion_item.rs
[
CompletionItem {
completion_kind: Reference,
label: "the_field",
kind: Some(
Field
),
detail: Some(
"u32"
),
lookup: None,
insert_text: None,
insert_text_format: PlainText,
source_range: [85; 85),
text_edit: None
}
]

View file

@ -0,0 +1,36 @@
Created: 2019-01-20T09:26:20.868561+00:00
Creator: insta@0.1.4
Source: crates/ra_ide_api/src/completion/completion_item.rs
[
CompletionItem {
completion_kind: Reference,
label: "the_field",
kind: Some(
Field
),
detail: Some(
"(u32, i32)"
),
lookup: None,
insert_text: None,
insert_text_format: PlainText,
source_range: [126; 126),
text_edit: None
},
CompletionItem {
completion_kind: Reference,
label: "foo",
kind: Some(
Method
),
detail: None,
lookup: None,
insert_text: Some(
"foo($0)"
),
insert_text_format: Snippet,
source_range: [126; 126),
text_edit: None
}
]

View file

@ -0,0 +1,36 @@
Created: 2019-01-20T09:26:20.868333+00:00
Creator: insta@0.1.4
Source: crates/ra_ide_api/src/completion/completion_item.rs
[
CompletionItem {
completion_kind: Reference,
label: "the_field",
kind: Some(
Field
),
detail: Some(
"(u32,)"
),
lookup: None,
insert_text: None,
insert_text_format: PlainText,
source_range: [121; 121),
text_edit: None
},
CompletionItem {
completion_kind: Reference,
label: "foo",
kind: Some(
Method
),
detail: None,
lookup: None,
insert_text: Some(
"foo($0)"
),
insert_text_format: Snippet,
source_range: [121; 121),
text_edit: None
}
]

View file

@ -0,0 +1,32 @@
Created: 2019-01-20T04:00:48.223130+00:00
Creator: insta@0.1.4
Source: crates/ra_ide_api/src/completion/completion_item.rs
[
CompletionItem {
completion_kind: Reference,
label: "Spam",
kind: Some(
Struct
),
detail: None,
lookup: None,
insert_text: None,
insert_text_format: PlainText,
source_range: [11; 13),
text_edit: None
},
CompletionItem {
completion_kind: Reference,
label: "foo",
kind: Some(
Module
),
detail: None,
lookup: None,
insert_text: None,
insert_text_format: PlainText,
source_range: [11; 13),
text_edit: None
}
]

View file

@ -0,0 +1,19 @@
Created: 2019-01-20T09:26:20.899584+00:00
Creator: insta@0.1.4
Source: crates/ra_ide_api/src/completion/completion_item.rs
[
CompletionItem {
completion_kind: Reference,
label: "Bar",
kind: Some(
Struct
),
detail: None,
lookup: None,
insert_text: None,
insert_text_format: PlainText,
source_range: [26; 26),
text_edit: None
}
]

View file

@ -43,7 +43,7 @@ use crate::{
};
pub use crate::{
completion::{CompletionItem, CompletionItemKind, InsertText},
completion::{CompletionItem, CompletionItemKind, InsertTextFormat},
runnables::{Runnable, RunnableKind},
navigation_target::NavigationTarget,
};

View file

@ -1,13 +1,13 @@
use lsp_types::{
self, CreateFile, DocumentChangeOperation, DocumentChanges, InsertTextFormat, Location, LocationLink,
self, CreateFile, DocumentChangeOperation, DocumentChanges, Location, LocationLink,
Position, Range, RenameFile, ResourceOp, SymbolKind, TextDocumentEdit, TextDocumentIdentifier,
TextDocumentItem, TextDocumentPositionParams, Url, VersionedTextDocumentIdentifier,
WorkspaceEdit,
};
use ra_ide_api::{
CompletionItem, CompletionItemKind, FileId, FilePosition, FileRange, FileSystemEdit,
InsertText, NavigationTarget, SourceChange, SourceFileEdit, RangeInfo,
LineCol, LineIndex, translate_offset_with_edit
NavigationTarget, SourceChange, SourceFileEdit, RangeInfo,
LineCol, LineIndex, translate_offset_with_edit, InsertTextFormat
};
use ra_syntax::{SyntaxKind, TextRange, TextUnit};
use ra_text_edit::{AtomTextEdit, TextEdit};
@ -74,27 +74,33 @@ impl Conv for CompletionItemKind {
}
}
impl Conv for CompletionItem {
impl ConvWith for CompletionItem {
type Ctx = LineIndex;
type Output = ::lsp_types::CompletionItem;
fn conv(self) -> <Self as Conv>::Output {
let mut res = ::lsp_types::CompletionItem {
fn conv_with(mut self, ctx: &LineIndex) -> ::lsp_types::CompletionItem {
let atom_text_edit = AtomTextEdit::replace(self.source_range(), self.insert_text());
let text_edit = (&atom_text_edit).conv_with(ctx);
let additional_text_edits = if let Some(edit) = self.take_text_edit() {
Some(edit.conv_with(ctx))
} else {
None
};
let mut res = lsp_types::CompletionItem {
label: self.label().to_string(),
detail: self.detail().map(|it| it.to_string()),
filter_text: Some(self.lookup().to_string()),
kind: self.kind().map(|it| it.conv()),
text_edit: Some(text_edit),
additional_text_edits,
..Default::default()
};
match self.insert_text() {
InsertText::PlainText { text } => {
res.insert_text = Some(text);
res.insert_text_format = Some(InsertTextFormat::PlainText);
}
InsertText::Snippet { text } => {
res.insert_text = Some(text);
res.insert_text_format = Some(InsertTextFormat::Snippet);
}
}
res.insert_text_format = Some(match self.insert_text_format() {
InsertTextFormat::Snippet => lsp_types::InsertTextFormat::Snippet,
InsertTextFormat::PlainText => lsp_types::InsertTextFormat::PlainText,
});
res
}
}

View file

@ -340,7 +340,11 @@ pub fn handle_completion(
None => return Ok(None),
Some(items) => items,
};
let items = items.into_iter().map(|item| item.conv()).collect();
let line_index = world.analysis().file_line_index(position.file_id);
let items = items
.into_iter()
.map(|item| item.conv_with(&line_index))
.collect();
Ok(Some(req::CompletionResponse::Array(items)))
}