Complete paths in use trees

This commit is contained in:
Aleksey Kladov 2018-11-07 21:38:41 +03:00
parent 06fbc6e3ed
commit 6d253b58da
3 changed files with 66 additions and 5 deletions

View File

@ -105,6 +105,9 @@ fn classify_name_ref(name_ref: ast::NameRef) -> Option<NameRefKind> {
let parent = name_ref.syntax().parent()?;
if let Some(segment) = ast::PathSegment::cast(parent) {
let path = segment.parent_path();
if let Some(crate_path) = crate_path(path) {
return Some(NameRefKind::CratePath(crate_path));
}
if path.qualifier().is_none() {
let enclosing_fn = name_ref
.syntax()
@ -113,9 +116,6 @@ fn classify_name_ref(name_ref: ast::NameRef) -> Option<NameRefKind> {
.find_map(ast::FnDef::cast);
return Some(NameRefKind::LocalRef { enclosing_fn });
}
if let Some(crate_path) = crate_path(path) {
return Some(NameRefKind::CratePath(crate_path));
}
}
None
}
@ -129,10 +129,21 @@ fn crate_path(mut path: ast::Path) -> Option<Vec<ast::NameRef>> {
ast::PathSegmentKind::CrateKw => break,
ast::PathSegmentKind::SelfKw | ast::PathSegmentKind::SuperKw => return None,
}
path = path.qualifier()?;
path = qualifier(path)?;
}
res.reverse();
Some(res)
return Some(res);
fn qualifier(path: ast::Path) -> Option<ast::Path> {
if let Some(q) = path.qualifier() {
return Some(q);
}
// TODO: this bottom up traversal is not too precise.
// Should we handle do a top-down analysiss, recording results?
let use_tree_list = path.syntax().ancestors().find_map(ast::UseTreeList::cast)?;
let use_tree = use_tree_list.parent_use_tree();
use_tree.path()
}
}
fn complete_fn(name_ref: ast::NameRef, scopes: &FnScopes, acc: &mut Vec<CompletionItem>) {

View File

@ -452,3 +452,44 @@ fn test_complete_crate_path() {
&completions,
);
}
#[test]
fn test_complete_crate_path_with_braces() {
let (analysis, position) = analysis_and_position(
"
//- /lib.rs
mod foo;
struct Spam;
//- /foo.rs
use crate::{Sp<|>};
",
);
let completions = analysis.completions(position).unwrap().unwrap();
assert_eq_dbg(
r#"[CompletionItem { label: "foo", lookup: None, snippet: None },
CompletionItem { label: "Spam", lookup: None, snippet: None }]"#,
&completions,
);
}
#[test]
fn test_complete_crate_path_in_nested_tree() {
let (analysis, position) = analysis_and_position(
"
//- /lib.rs
mod foo;
pub mod bar {
pub mod baz {
pub struct Spam;
}
}
//- /foo.rs
use crate::{bar::{baz::Sp<|>}};
",
);
let completions = analysis.completions(position).unwrap().unwrap();
assert_eq_dbg(
r#"[CompletionItem { label: "Spam", lookup: None, snippet: None }]"#,
&completions,
);
}

View File

@ -296,6 +296,15 @@ impl<'a> PathSegment<'a> {
}
}
impl<'a> UseTreeList<'a> {
pub fn parent_use_tree(self) -> UseTree<'a> {
self.syntax()
.parent()
.and_then(UseTree::cast)
.expect("UseTreeLists are always nested in UseTrees")
}
}
fn child_opt<'a, P: AstNode<'a>, C: AstNode<'a>>(parent: P) -> Option<C> {
children(parent).next()
}