aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_analysis/src
diff options
context:
space:
mode:
authorAleksey Kladov <[email protected]>2018-11-21 14:51:02 +0000
committerAleksey Kladov <[email protected]>2018-11-21 14:51:02 +0000
commit11f19b784923ac701bc6fc39a6aea712f0091bf7 (patch)
tree6a5b5ba2543bc52d10501d41a8514bae68b78c36 /crates/ra_analysis/src
parent5a87a24f8288d905428db755c7ea806640b6ac1d (diff)
name res uses paths
Diffstat (limited to 'crates/ra_analysis/src')
-rw-r--r--crates/ra_analysis/src/completion/reference_completion.rs64
-rw-r--r--crates/ra_analysis/src/descriptors/mod.rs2
-rw-r--r--crates/ra_analysis/src/descriptors/module/nameres.rs4
-rw-r--r--crates/ra_analysis/src/descriptors/path.rs51
4 files changed, 74 insertions, 47 deletions
diff --git a/crates/ra_analysis/src/completion/reference_completion.rs b/crates/ra_analysis/src/completion/reference_completion.rs
index 84383b547..a96570415 100644
--- a/crates/ra_analysis/src/completion/reference_completion.rs
+++ b/crates/ra_analysis/src/completion/reference_completion.rs
@@ -10,8 +10,11 @@ use ra_syntax::{
10use crate::{ 10use crate::{
11 db::RootDatabase, 11 db::RootDatabase,
12 completion::CompletionItem, 12 completion::CompletionItem,
13 descriptors::module::{ModuleDescriptor}, 13 descriptors::{
14 descriptors::function::FnScopes, 14 module::{ModuleDescriptor},
15 function::FnScopes,
16 Path, PathKind,
17 },
15 Cancelable 18 Cancelable
16}; 19};
17 20
@@ -55,7 +58,7 @@ pub(super) fn completions(
55 }), 58 }),
56 ); 59 );
57 } 60 }
58 NameRefKind::CratePath(path) => complete_path(acc, db, module, path)?, 61 NameRefKind::Path(path) => complete_path(acc, db, module, path)?,
59 NameRefKind::BareIdentInMod => { 62 NameRefKind::BareIdentInMod => {
60 let name_range = name_ref.syntax().range(); 63 let name_range = name_ref.syntax().range();
61 let top_node = name_ref 64 let top_node = name_ref
@@ -79,8 +82,8 @@ enum NameRefKind<'a> {
79 LocalRef { 82 LocalRef {
80 enclosing_fn: Option<ast::FnDef<'a>>, 83 enclosing_fn: Option<ast::FnDef<'a>>,
81 }, 84 },
82 /// NameRef is the last segment in crate:: path 85 /// NameRef is the last segment in some path
83 CratePath(Vec<ast::NameRef<'a>>), 86 Path(Path),
84 /// NameRef is bare identifier at the module's root. 87 /// NameRef is bare identifier at the module's root.
85 /// Used for keyword completion 88 /// Used for keyword completion
86 BareIdentInMod, 89 BareIdentInMod,
@@ -102,8 +105,10 @@ fn classify_name_ref(name_ref: ast::NameRef) -> Option<NameRefKind> {
102 let parent = name_ref.syntax().parent()?; 105 let parent = name_ref.syntax().parent()?;
103 if let Some(segment) = ast::PathSegment::cast(parent) { 106 if let Some(segment) = ast::PathSegment::cast(parent) {
104 let path = segment.parent_path(); 107 let path = segment.parent_path();
105 if let Some(crate_path) = crate_path(path) { 108 if let Some(path) = Path::from_ast(path) {
106 return Some(NameRefKind::CratePath(crate_path)); 109 if !path.is_ident() {
110 return Some(NameRefKind::Path(path));
111 }
107 } 112 }
108 if path.qualifier().is_none() { 113 if path.qualifier().is_none() {
109 let enclosing_fn = name_ref 114 let enclosing_fn = name_ref
@@ -117,32 +122,6 @@ fn classify_name_ref(name_ref: ast::NameRef) -> Option<NameRefKind> {
117 None 122 None
118} 123}
119 124
120fn crate_path(mut path: ast::Path) -> Option<Vec<ast::NameRef>> {
121 let mut res = Vec::new();
122 loop {
123 let segment = path.segment()?;
124 match segment.kind()? {
125 ast::PathSegmentKind::Name(name) => res.push(name),
126 ast::PathSegmentKind::CrateKw => break,
127 ast::PathSegmentKind::SelfKw | ast::PathSegmentKind::SuperKw => return None,
128 }
129 path = qualifier(path)?;
130 }
131 res.reverse();
132 return Some(res);
133
134 fn qualifier(path: ast::Path) -> Option<ast::Path> {
135 if let Some(q) = path.qualifier() {
136 return Some(q);
137 }
138 // TODO: this bottom up traversal is not too precise.
139 // Should we handle do a top-down analysiss, recording results?
140 let use_tree_list = path.syntax().ancestors().find_map(ast::UseTreeList::cast)?;
141 let use_tree = use_tree_list.parent_use_tree();
142 use_tree.path()
143 }
144}
145
146fn complete_fn(name_ref: ast::NameRef, scopes: &FnScopes, acc: &mut Vec<CompletionItem>) { 125fn complete_fn(name_ref: ast::NameRef, scopes: &FnScopes, acc: &mut Vec<CompletionItem>) {
147 let mut shadowed = FxHashSet::default(); 126 let mut shadowed = FxHashSet::default();
148 acc.extend( 127 acc.extend(
@@ -169,9 +148,9 @@ fn complete_path(
169 acc: &mut Vec<CompletionItem>, 148 acc: &mut Vec<CompletionItem>,
170 db: &RootDatabase, 149 db: &RootDatabase,
171 module: &ModuleDescriptor, 150 module: &ModuleDescriptor,
172 crate_path: Vec<ast::NameRef>, 151 path: Path,
173) -> Cancelable<()> { 152) -> Cancelable<()> {
174 let target_module = match find_target_module(module, crate_path) { 153 let target_module = match find_target_module(module, path) {
175 None => return Ok(()), 154 None => return Ok(()),
176 Some(it) => it, 155 Some(it) => it,
177 }; 156 };
@@ -188,14 +167,15 @@ fn complete_path(
188 Ok(()) 167 Ok(())
189} 168}
190 169
191fn find_target_module( 170fn find_target_module(module: &ModuleDescriptor, path: Path) -> Option<ModuleDescriptor> {
192 module: &ModuleDescriptor, 171 if path.kind != PathKind::Crate {
193 mut crate_path: Vec<ast::NameRef>, 172 return None;
194) -> Option<ModuleDescriptor> { 173 }
195 crate_path.pop(); 174 let mut segments = path.segments;
175 segments.pop();
196 let mut target_module = module.crate_root(); 176 let mut target_module = module.crate_root();
197 for name in crate_path { 177 for name in segments {
198 target_module = target_module.child(name.text().as_str())?; 178 target_module = target_module.child(&name)?;
199 } 179 }
200 Some(target_module) 180 Some(target_module)
201} 181}
diff --git a/crates/ra_analysis/src/descriptors/mod.rs b/crates/ra_analysis/src/descriptors/mod.rs
index e6225479d..97750ea64 100644
--- a/crates/ra_analysis/src/descriptors/mod.rs
+++ b/crates/ra_analysis/src/descriptors/mod.rs
@@ -5,7 +5,7 @@ mod path;
5use std::sync::Arc; 5use std::sync::Arc;
6 6
7use ra_syntax::{ 7use ra_syntax::{
8 ast::{self, FnDefNode}, 8 ast::{self, FnDefNode, AstNode},
9 TextRange, 9 TextRange,
10}; 10};
11 11
diff --git a/crates/ra_analysis/src/descriptors/module/nameres.rs b/crates/ra_analysis/src/descriptors/module/nameres.rs
index bf671470c..4c555421d 100644
--- a/crates/ra_analysis/src/descriptors/module/nameres.rs
+++ b/crates/ra_analysis/src/descriptors/module/nameres.rs
@@ -23,7 +23,7 @@ use rustc_hash::FxHashMap;
23 23
24use ra_syntax::{ 24use ra_syntax::{
25 SmolStr, SyntaxKind::{self, *}, 25 SmolStr, SyntaxKind::{self, *},
26 ast::{self, AstNode, ModuleItemOwner} 26 ast::{self, ModuleItemOwner}
27}; 27};
28 28
29use crate::{ 29use crate::{
@@ -309,7 +309,7 @@ where
309 309
310 let mut curr = match import.path.kind { 310 let mut curr = match import.path.kind {
311 // TODO: handle extern crates 311 // TODO: handle extern crates
312 PathKind::Abs => return, 312 PathKind::Plain => return,
313 PathKind::Self_ => module_id, 313 PathKind::Self_ => module_id,
314 PathKind::Super => { 314 PathKind::Super => {
315 match module_id.parent(&self.module_tree) { 315 match module_id.parent(&self.module_tree) {
diff --git a/crates/ra_analysis/src/descriptors/path.rs b/crates/ra_analysis/src/descriptors/path.rs
index 4ed561b51..99fca18b1 100644
--- a/crates/ra_analysis/src/descriptors/path.rs
+++ b/crates/ra_analysis/src/descriptors/path.rs
@@ -10,13 +10,14 @@ pub(crate) struct Path {
10 10
11#[derive(Debug, Clone, Copy, PartialEq, Eq)] 11#[derive(Debug, Clone, Copy, PartialEq, Eq)]
12pub(crate) enum PathKind { 12pub(crate) enum PathKind {
13 Abs, 13 Plain,
14 Self_, 14 Self_,
15 Super, 15 Super,
16 Crate, 16 Crate,
17} 17}
18 18
19impl Path { 19impl Path {
20 /// Calls `cb` with all paths, represented by this use item.
20 pub(crate) fn expand_use_item( 21 pub(crate) fn expand_use_item(
21 item: ast::UseItem, 22 item: ast::UseItem,
22 mut cb: impl FnMut(Path, Option<LocalSyntaxPtr>), 23 mut cb: impl FnMut(Path, Option<LocalSyntaxPtr>),
@@ -25,6 +26,52 @@ impl Path {
25 expand_use_tree(None, tree, &mut cb); 26 expand_use_tree(None, tree, &mut cb);
26 } 27 }
27 } 28 }
29
30 /// Converts an `ast::Path` to `Path`. Works with use trees.
31 pub(crate) fn from_ast(mut path: ast::Path) -> Option<Path> {
32 let mut kind = PathKind::Plain;
33 let mut segments = Vec::new();
34 loop {
35 let segment = path.segment()?;
36 match segment.kind()? {
37 ast::PathSegmentKind::Name(name) => segments.push(name.text()),
38 ast::PathSegmentKind::CrateKw => {
39 kind = PathKind::Crate;
40 break;
41 }
42 ast::PathSegmentKind::SelfKw => {
43 kind = PathKind::Self_;
44 break;
45 }
46 ast::PathSegmentKind::SuperKw => {
47 kind = PathKind::Super;
48 break;
49 }
50 }
51 path = match qualifier(path) {
52 Some(it) => it,
53 None => break,
54 };
55 }
56 segments.reverse();
57 return Some(Path { kind, segments });
58
59 fn qualifier(path: ast::Path) -> Option<ast::Path> {
60 if let Some(q) = path.qualifier() {
61 return Some(q);
62 }
63 // TODO: this bottom up traversal is not too precise.
64 // Should we handle do a top-down analysiss, recording results?
65 let use_tree_list = path.syntax().ancestors().find_map(ast::UseTreeList::cast)?;
66 let use_tree = use_tree_list.parent_use_tree();
67 use_tree.path()
68 }
69 }
70
71 /// `true` is this path is a single identifier, like `foo`
72 pub(crate) fn is_ident(&self) -> bool {
73 self.kind == PathKind::Plain && self.segments.len() == 1
74 }
28} 75}
29 76
30fn expand_use_tree( 77fn expand_use_tree(
@@ -68,7 +115,7 @@ fn convert_path(prefix: Option<Path>, path: ast::Path) -> Option<Path> {
68 let res = match segment.kind()? { 115 let res = match segment.kind()? {
69 ast::PathSegmentKind::Name(name) => { 116 ast::PathSegmentKind::Name(name) => {
70 let mut res = prefix.unwrap_or_else(|| Path { 117 let mut res = prefix.unwrap_or_else(|| Path {
71 kind: PathKind::Abs, 118 kind: PathKind::Plain,
72 segments: Vec::with_capacity(1), 119 segments: Vec::with_capacity(1),
73 }); 120 });
74 res.segments.push(name.text()); 121 res.segments.push(name.text());