aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_hir_def/src/path.rs
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_hir_def/src/path.rs')
-rw-r--r--crates/ra_hir_def/src/path.rs110
1 files changed, 4 insertions, 106 deletions
diff --git a/crates/ra_hir_def/src/path.rs b/crates/ra_hir_def/src/path.rs
index e547b2f03..ec9d13e82 100644
--- a/crates/ra_hir_def/src/path.rs
+++ b/crates/ra_hir_def/src/path.rs
@@ -1,4 +1,5 @@
1//! A desugared representation of paths like `crate::foo` or `<Type as Trait>::bar`. 1//! A desugared representation of paths like `crate::foo` or `<Type as Trait>::bar`.
2mod lower_use;
2 3
3use std::{iter, sync::Arc}; 4use std::{iter, sync::Arc};
4 5
@@ -9,7 +10,7 @@ use hir_expand::{
9}; 10};
10use ra_db::CrateId; 11use ra_db::CrateId;
11use ra_syntax::{ 12use ra_syntax::{
12 ast::{self, NameOwner, TypeAscriptionOwner}, 13 ast::{self, TypeAscriptionOwner},
13 AstNode, 14 AstNode,
14}; 15};
15 16
@@ -28,8 +29,7 @@ pub struct PathSegment {
28} 29}
29 30
30/// Generic arguments to a path segment (e.g. the `i32` in `Option<i32>`). This 31/// Generic arguments to a path segment (e.g. the `i32` in `Option<i32>`). This
31/// can (in the future) also include bindings of associated types, like in 32/// also includes bindings of associated types, like in `Iterator<Item = Foo>`.
32/// `Iterator<Item = Foo>`.
33#[derive(Debug, Clone, PartialEq, Eq, Hash)] 33#[derive(Debug, Clone, PartialEq, Eq, Hash)]
34pub struct GenericArgs { 34pub struct GenericArgs {
35 pub args: Vec<GenericArg>, 35 pub args: Vec<GenericArg>,
@@ -72,7 +72,7 @@ impl Path {
72 mut cb: impl FnMut(Path, &ast::UseTree, bool, Option<Name>), 72 mut cb: impl FnMut(Path, &ast::UseTree, bool, Option<Name>),
73 ) { 73 ) {
74 if let Some(tree) = item_src.value.use_tree() { 74 if let Some(tree) = item_src.value.use_tree() {
75 expand_use_tree(None, tree, hygiene, &mut cb); 75 lower_use::lower_use_tree(None, tree, hygiene, &mut cb);
76 } 76 }
77 } 77 }
78 78
@@ -296,108 +296,6 @@ impl From<Name> for Path {
296 } 296 }
297} 297}
298 298
299fn expand_use_tree(
300 prefix: Option<Path>,
301 tree: ast::UseTree,
302 hygiene: &Hygiene,
303 cb: &mut dyn FnMut(Path, &ast::UseTree, bool, Option<Name>),
304) {
305 if let Some(use_tree_list) = tree.use_tree_list() {
306 let prefix = match tree.path() {
307 // E.g. use something::{{{inner}}};
308 None => prefix,
309 // E.g. `use something::{inner}` (prefix is `None`, path is `something`)
310 // or `use something::{path::{inner::{innerer}}}` (prefix is `something::path`, path is `inner`)
311 Some(path) => match convert_path(prefix, path, hygiene) {
312 Some(it) => Some(it),
313 None => return, // FIXME: report errors somewhere
314 },
315 };
316 for child_tree in use_tree_list.use_trees() {
317 expand_use_tree(prefix.clone(), child_tree, hygiene, cb);
318 }
319 } else {
320 let alias = tree.alias().and_then(|a| a.name()).map(|a| a.as_name());
321 if let Some(ast_path) = tree.path() {
322 // Handle self in a path.
323 // E.g. `use something::{self, <...>}`
324 if ast_path.qualifier().is_none() {
325 if let Some(segment) = ast_path.segment() {
326 if segment.kind() == Some(ast::PathSegmentKind::SelfKw) {
327 if let Some(prefix) = prefix {
328 cb(prefix, &tree, false, alias);
329 return;
330 }
331 }
332 }
333 }
334 if let Some(path) = convert_path(prefix, ast_path, hygiene) {
335 let is_glob = tree.has_star();
336 cb(path, &tree, is_glob, alias)
337 }
338 // FIXME: report errors somewhere
339 // We get here if we do
340 }
341 }
342}
343
344fn convert_path(prefix: Option<Path>, path: ast::Path, hygiene: &Hygiene) -> Option<Path> {
345 let prefix = if let Some(qual) = path.qualifier() {
346 Some(convert_path(prefix, qual, hygiene)?)
347 } else {
348 prefix
349 };
350
351 let segment = path.segment()?;
352 let res = match segment.kind()? {
353 ast::PathSegmentKind::Name(name_ref) => {
354 match hygiene.name_ref_to_name(name_ref) {
355 Either::Left(name) => {
356 // no type args in use
357 let mut res = prefix.unwrap_or_else(|| Path {
358 kind: PathKind::Plain,
359 segments: Vec::with_capacity(1),
360 });
361 res.segments.push(PathSegment {
362 name,
363 args_and_bindings: None, // no type args in use
364 });
365 res
366 }
367 Either::Right(crate_id) => {
368 return Some(Path::from_simple_segments(
369 PathKind::DollarCrate(crate_id),
370 iter::empty(),
371 ))
372 }
373 }
374 }
375 ast::PathSegmentKind::CrateKw => {
376 if prefix.is_some() {
377 return None;
378 }
379 Path::from_simple_segments(PathKind::Crate, iter::empty())
380 }
381 ast::PathSegmentKind::SelfKw => {
382 if prefix.is_some() {
383 return None;
384 }
385 Path::from_simple_segments(PathKind::Self_, iter::empty())
386 }
387 ast::PathSegmentKind::SuperKw => {
388 if prefix.is_some() {
389 return None;
390 }
391 Path::from_simple_segments(PathKind::Super, iter::empty())
392 }
393 ast::PathSegmentKind::Type { .. } => {
394 // not allowed in imports
395 return None;
396 }
397 };
398 Some(res)
399}
400
401pub mod known { 299pub mod known {
402 use hir_expand::name; 300 use hir_expand::name;
403 301