mirror of
https://github.com/rust-lang/rust.git
synced 2025-06-05 11:48:30 +00:00
Complete paths in use trees
This commit is contained in:
parent
06fbc6e3ed
commit
6d253b58da
@ -105,6 +105,9 @@ fn classify_name_ref(name_ref: ast::NameRef) -> Option<NameRefKind> {
|
|||||||
let parent = name_ref.syntax().parent()?;
|
let parent = name_ref.syntax().parent()?;
|
||||||
if let Some(segment) = ast::PathSegment::cast(parent) {
|
if let Some(segment) = ast::PathSegment::cast(parent) {
|
||||||
let path = segment.parent_path();
|
let path = segment.parent_path();
|
||||||
|
if let Some(crate_path) = crate_path(path) {
|
||||||
|
return Some(NameRefKind::CratePath(crate_path));
|
||||||
|
}
|
||||||
if path.qualifier().is_none() {
|
if path.qualifier().is_none() {
|
||||||
let enclosing_fn = name_ref
|
let enclosing_fn = name_ref
|
||||||
.syntax()
|
.syntax()
|
||||||
@ -113,9 +116,6 @@ fn classify_name_ref(name_ref: ast::NameRef) -> Option<NameRefKind> {
|
|||||||
.find_map(ast::FnDef::cast);
|
.find_map(ast::FnDef::cast);
|
||||||
return Some(NameRefKind::LocalRef { enclosing_fn });
|
return Some(NameRefKind::LocalRef { enclosing_fn });
|
||||||
}
|
}
|
||||||
if let Some(crate_path) = crate_path(path) {
|
|
||||||
return Some(NameRefKind::CratePath(crate_path));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
@ -129,10 +129,21 @@ fn crate_path(mut path: ast::Path) -> Option<Vec<ast::NameRef>> {
|
|||||||
ast::PathSegmentKind::CrateKw => break,
|
ast::PathSegmentKind::CrateKw => break,
|
||||||
ast::PathSegmentKind::SelfKw | ast::PathSegmentKind::SuperKw => return None,
|
ast::PathSegmentKind::SelfKw | ast::PathSegmentKind::SuperKw => return None,
|
||||||
}
|
}
|
||||||
path = path.qualifier()?;
|
path = qualifier(path)?;
|
||||||
}
|
}
|
||||||
res.reverse();
|
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>) {
|
fn complete_fn(name_ref: ast::NameRef, scopes: &FnScopes, acc: &mut Vec<CompletionItem>) {
|
||||||
|
@ -452,3 +452,44 @@ fn test_complete_crate_path() {
|
|||||||
&completions,
|
&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,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
@ -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> {
|
fn child_opt<'a, P: AstNode<'a>, C: AstNode<'a>>(parent: P) -> Option<C> {
|
||||||
children(parent).next()
|
children(parent).next()
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user