completion for trait params

This commit is contained in:
Aleksey Kladov 2018-09-03 15:46:14 +03:00
parent 4798a89a12
commit 2f2feef9af
3 changed files with 33 additions and 10 deletions

View file

@ -35,11 +35,17 @@ pub fn scope_completion(file: &File, offset: TextUnit) -> Option<Vec<CompletionI
let mut res = Vec::new();
if let Some(name_ref) = find_node_at_offset::<ast::NameRef>(file.syntax(), offset) {
has_completions = true;
complete_name_ref(&file, name_ref, &mut res)
complete_name_ref(&file, name_ref, &mut res);
// special case, `trait T { fn foo(i_am_a_name_ref) {} }`
if is_node::<ast::Param>(name_ref.syntax()) {
param_completions(name_ref.syntax(), &mut res);
}
}
if let Some(name) = find_node_at_offset::<ast::Name>(file.syntax(), offset) {
has_completions = true;
complete_name(&file, name, &mut res)
if is_node::<ast::Param>(name.syntax()) {
has_completions = true;
param_completions(name.syntax(), &mut res);
}
}
if has_completions {
Some(res)
@ -71,15 +77,12 @@ fn complete_name_ref(file: &File, name_ref: ast::NameRef, acc: &mut Vec<Completi
}
}
fn complete_name(_file: &File, name: ast::Name, acc: &mut Vec<CompletionItem>) {
if !is_node::<ast::Param>(name.syntax()) {
return;
}
fn param_completions(ctx: SyntaxNodeRef, acc: &mut Vec<CompletionItem>) {
let mut params = HashMap::new();
for node in ancestors(name.syntax()) {
for node in ancestors(ctx) {
let _ = visitor_ctx(&mut params)
.visit::<ast::Root, _>(process)
.visit::<ast::ItemList, _>(process)
.accept(node);
}
params.into_iter()
@ -420,16 +423,34 @@ mod tests {
}
#[test]
fn test_param_completion() {
fn test_param_completion_last_param() {
check_scope_completion(r"
fn foo(file_id: FileId) {}
fn bar(file_id: FileId) {}
fn baz(file<|>) {}
", r#"[CompletionItem { label: "file_id: FileId", lookup: Some("file_id"), snippet: None }]"#);
}
#[test]
fn test_param_completion_nth_param() {
check_scope_completion(r"
fn foo(file_id: FileId) {}
fn bar(file_id: FileId) {}
fn baz(file<|>, x: i32) {}
", r#"[CompletionItem { label: "file_id: FileId", lookup: Some("file_id"), snippet: None }]"#);
}
#[test]
fn test_param_completion_trait_param() {
check_scope_completion(r"
pub(crate) trait SourceRoot {
pub fn contains(&self, file_id: FileId) -> bool;
pub fn module_map(&self) -> &ModuleMap;
pub fn lines(&self, file_id: FileId) -> &LineIndex;
pub fn syntax(&self, file<|>)
}
", r#"[CompletionItem { label: "self", lookup: None, snippet: None },
CompletionItem { label: "SourceRoot", lookup: None, snippet: None },
CompletionItem { label: "file_id: FileId", lookup: Some("file_id"), snippet: None }]"#);
}
}

View file

@ -698,6 +698,7 @@ impl<'a> AstNode<'a> for ItemList<'a> {
fn syntax(self) -> SyntaxNodeRef<'a> { self.syntax }
}
impl<'a> ast::FnDefOwner<'a> for ItemList<'a> {}
impl<'a> ItemList<'a> {
pub fn items(self) -> impl Iterator<Item = ModuleItem<'a>> + 'a {
super::children(self)

View file

@ -275,6 +275,7 @@ Grammar(
options: [ "ItemList" ]
),
"ItemList": (
traits: [ "FnDefOwner" ],
collections: [ ["items", "ModuleItem"] ]
),
"ConstDef": ( traits: [