From 4926bed42680d329f906be93450bec6b2ba0e99b Mon Sep 17 00:00:00 2001 From: uHOOCCOOHu Date: Thu, 12 Sep 2019 02:01:07 +0800 Subject: Support path starting with a type --- crates/ra_hir/src/path.rs | 81 +++++++++++++++++++++++++++++++---------------- 1 file changed, 53 insertions(+), 28 deletions(-) (limited to 'crates/ra_hir/src/path.rs') diff --git a/crates/ra_hir/src/path.rs b/crates/ra_hir/src/path.rs index d6c78593b..7c19fda14 100644 --- a/crates/ra_hir/src/path.rs +++ b/crates/ra_hir/src/path.rs @@ -1,4 +1,4 @@ -use std::sync::Arc; +use std::{iter, sync::Arc}; use ra_syntax::{ ast::{self, NameOwner, TypeAscriptionOwner}, @@ -10,6 +10,7 @@ use crate::{name, type_ref::TypeRef, AsName, Name}; #[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct Path { pub kind: PathKind, + pub type_ref: Option>, pub segments: Vec, } @@ -50,6 +51,8 @@ pub enum PathKind { Crate, // Absolute path Abs, + // Type based path like `::foo` + Type, } impl Path { @@ -63,10 +66,22 @@ impl Path { } } + pub fn from_simple_segments(kind: PathKind, segments: impl IntoIterator) -> Path { + Path { + kind, + type_ref: None, + segments: segments + .into_iter() + .map(|name| PathSegment { name, args_and_bindings: None }) + .collect(), + } + } + /// Converts an `ast::Path` to `Path`. Works with use trees. pub fn from_ast(mut path: ast::Path) -> Option { let mut kind = PathKind::Plain; let mut segments = Vec::new(); + let mut path_type_ref = None; loop { let segment = path.segment()?; @@ -92,24 +107,33 @@ impl Path { ast::PathSegmentKind::Type { type_ref, trait_ref } => { assert!(path.qualifier().is_none()); // this can only occur at the first segment - // FIXME: handle syntax (type segments without trait) - - // >::Foo desugars to Trait::Foo - let path = Path::from_ast(trait_ref?.path()?)?; - kind = path.kind; - let mut prefix_segments = path.segments; - prefix_segments.reverse(); - segments.extend(prefix_segments); - // Insert the type reference (T in the above example) as Self parameter for the trait let self_type = TypeRef::from_ast(type_ref?); - let mut last_segment = segments.last_mut()?; - if last_segment.args_and_bindings.is_none() { - last_segment.args_and_bindings = Some(Arc::new(GenericArgs::empty())); - }; - let args = last_segment.args_and_bindings.as_mut().unwrap(); - let mut args_inner = Arc::make_mut(args); - args_inner.has_self_type = true; - args_inner.args.insert(0, GenericArg::Type(self_type)); + + match trait_ref { + // ::foo + None => { + kind = PathKind::Type; + path_type_ref = Some(Box::new(self_type)); + } + // >::Foo desugars to Trait::Foo + Some(trait_ref) => { + let path = Path::from_ast(trait_ref.path()?)?; + kind = path.kind; + let mut prefix_segments = path.segments; + prefix_segments.reverse(); + segments.extend(prefix_segments); + // Insert the type reference (T in the above example) as Self parameter for the trait + let mut last_segment = segments.last_mut()?; + if last_segment.args_and_bindings.is_none() { + last_segment.args_and_bindings = + Some(Arc::new(GenericArgs::empty())); + }; + let args = last_segment.args_and_bindings.as_mut().unwrap(); + let mut args_inner = Arc::make_mut(args); + args_inner.has_self_type = true; + args_inner.args.insert(0, GenericArg::Type(self_type)); + } + } } ast::PathSegmentKind::CrateKw => { kind = PathKind::Crate; @@ -130,7 +154,7 @@ impl Path { }; } segments.reverse(); - return Some(Path { kind, segments }); + return Some(Path { kind, type_ref: path_type_ref, segments }); fn qualifier(path: &ast::Path) -> Option { if let Some(q) = path.qualifier() { @@ -230,10 +254,7 @@ impl GenericArgs { impl From for Path { fn from(name: Name) -> Path { - Path { - kind: PathKind::Plain, - segments: vec![PathSegment { name, args_and_bindings: None }], - } + Path::from_simple_segments(PathKind::Plain, iter::once(name)) } } @@ -287,8 +308,12 @@ fn convert_path(prefix: Option, path: ast::Path) -> Option { let segment = path.segment()?; let res = match segment.kind()? { ast::PathSegmentKind::Name(name) => { - let mut res = prefix - .unwrap_or_else(|| Path { kind: PathKind::Plain, segments: Vec::with_capacity(1) }); + // no type args in use + let mut res = prefix.unwrap_or_else(|| Path { + kind: PathKind::Plain, + type_ref: None, + segments: Vec::with_capacity(1), + }); res.segments.push(PathSegment { name: name.as_name(), args_and_bindings: None, // no type args in use @@ -299,19 +324,19 @@ fn convert_path(prefix: Option, path: ast::Path) -> Option { if prefix.is_some() { return None; } - Path { kind: PathKind::Crate, segments: Vec::new() } + Path::from_simple_segments(PathKind::Crate, iter::empty()) } ast::PathSegmentKind::SelfKw => { if prefix.is_some() { return None; } - Path { kind: PathKind::Self_, segments: Vec::new() } + Path::from_simple_segments(PathKind::Self_, iter::empty()) } ast::PathSegmentKind::SuperKw => { if prefix.is_some() { return None; } - Path { kind: PathKind::Super, segments: Vec::new() } + Path::from_simple_segments(PathKind::Super, iter::empty()) } ast::PathSegmentKind::Type { .. } => { // not allowed in imports -- cgit v1.2.3 From de9670fe456d89f97e8044d4e0919d2c16d1087f Mon Sep 17 00:00:00 2001 From: uHOOCCOOHu Date: Sun, 15 Sep 2019 19:48:24 +0800 Subject: Move store TypeRef of type based path in PathKind --- crates/ra_hir/src/path.rs | 19 ++++++------------- 1 file changed, 6 insertions(+), 13 deletions(-) (limited to 'crates/ra_hir/src/path.rs') diff --git a/crates/ra_hir/src/path.rs b/crates/ra_hir/src/path.rs index 7c19fda14..9e449f6cc 100644 --- a/crates/ra_hir/src/path.rs +++ b/crates/ra_hir/src/path.rs @@ -10,7 +10,6 @@ use crate::{name, type_ref::TypeRef, AsName, Name}; #[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct Path { pub kind: PathKind, - pub type_ref: Option>, pub segments: Vec, } @@ -43,7 +42,7 @@ pub enum GenericArg { // or lifetime... } -#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] +#[derive(Debug, Clone, PartialEq, Eq, Hash)] pub enum PathKind { Plain, Self_, @@ -52,7 +51,7 @@ pub enum PathKind { // Absolute path Abs, // Type based path like `::foo` - Type, + Type(Box), } impl Path { @@ -69,7 +68,6 @@ impl Path { pub fn from_simple_segments(kind: PathKind, segments: impl IntoIterator) -> Path { Path { kind, - type_ref: None, segments: segments .into_iter() .map(|name| PathSegment { name, args_and_bindings: None }) @@ -81,7 +79,6 @@ impl Path { pub fn from_ast(mut path: ast::Path) -> Option { let mut kind = PathKind::Plain; let mut segments = Vec::new(); - let mut path_type_ref = None; loop { let segment = path.segment()?; @@ -112,8 +109,7 @@ impl Path { match trait_ref { // ::foo None => { - kind = PathKind::Type; - path_type_ref = Some(Box::new(self_type)); + kind = PathKind::Type(Box::new(self_type)); } // >::Foo desugars to Trait::Foo Some(trait_ref) => { @@ -154,7 +150,7 @@ impl Path { }; } segments.reverse(); - return Some(Path { kind, type_ref: path_type_ref, segments }); + return Some(Path { kind, segments }); fn qualifier(path: &ast::Path) -> Option { if let Some(q) = path.qualifier() { @@ -309,11 +305,8 @@ fn convert_path(prefix: Option, path: ast::Path) -> Option { let res = match segment.kind()? { ast::PathSegmentKind::Name(name) => { // no type args in use - let mut res = prefix.unwrap_or_else(|| Path { - kind: PathKind::Plain, - type_ref: None, - segments: Vec::with_capacity(1), - }); + let mut res = prefix + .unwrap_or_else(|| Path { kind: PathKind::Plain, segments: Vec::with_capacity(1) }); res.segments.push(PathSegment { name: name.as_name(), args_and_bindings: None, // no type args in use -- cgit v1.2.3 From 7ed3be32916facf3b709d5277381408cd3ec134a Mon Sep 17 00:00:00 2001 From: uHOOCCOOHu Date: Sun, 15 Sep 2019 20:14:33 +0800 Subject: Define known paths and group names --- crates/ra_hir/src/path.rs | 30 +++++++++++++++++++++++++++++- 1 file changed, 29 insertions(+), 1 deletion(-) (limited to 'crates/ra_hir/src/path.rs') diff --git a/crates/ra_hir/src/path.rs b/crates/ra_hir/src/path.rs index 9e449f6cc..a61161b63 100644 --- a/crates/ra_hir/src/path.rs +++ b/crates/ra_hir/src/path.rs @@ -234,7 +234,7 @@ impl GenericArgs { } if let Some(ret_type) = ret_type { let type_ref = TypeRef::from_ast_opt(ret_type.type_ref()); - bindings.push((name::OUTPUT, type_ref)) + bindings.push((name::OUTPUT_TYPE, type_ref)) } if args.is_empty() && bindings.is_empty() { None @@ -338,3 +338,31 @@ fn convert_path(prefix: Option, path: ast::Path) -> Option { }; Some(res) } + +pub mod known { + use super::{Path, PathKind}; + use crate::name; + + pub fn std_iter_into_iterator() -> Path { + Path::from_simple_segments( + PathKind::Abs, + vec![name::STD, name::ITER, name::INTO_ITERATOR_TYPE], + ) + } + + pub fn std_ops_try() -> Path { + Path::from_simple_segments(PathKind::Abs, vec![name::STD, name::OPS, name::TRY_TYPE]) + } + + pub fn std_result_result() -> Path { + Path::from_simple_segments(PathKind::Abs, vec![name::STD, name::RESULT, name::RESULT_TYPE]) + } + + pub fn std_future_future() -> Path { + Path::from_simple_segments(PathKind::Abs, vec![name::STD, name::FUTURE, name::FUTURE_TYPE]) + } + + pub fn std_boxed_box() -> Path { + Path::from_simple_segments(PathKind::Abs, vec![name::STD, name::BOXED, name::BOX_TYPE]) + } +} -- cgit v1.2.3