From d963042ca9da93be8d5922ce46ea26dc6a79c929 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Thu, 27 Dec 2018 20:07:21 +0300 Subject: introduce hir::Name --- crates/ra_db/src/lib.rs | 2 +- crates/ra_hir/src/krate.rs | 7 ++-- crates/ra_hir/src/lib.rs | 3 ++ crates/ra_hir/src/module.rs | 19 ++++++----- crates/ra_hir/src/module/imp.rs | 19 +++++------ crates/ra_hir/src/module/nameres.rs | 25 ++++++++------ crates/ra_hir/src/module/nameres/tests.rs | 7 ++-- crates/ra_hir/src/name.rs | 56 +++++++++++++++++++++++++++++++ crates/ra_hir/src/path.rs | 18 +++++++--- crates/ra_hir/src/query_definitions.rs | 6 ++-- crates/ra_hir/src/ty.rs | 10 +++--- 11 files changed, 121 insertions(+), 51 deletions(-) create mode 100644 crates/ra_hir/src/name.rs (limited to 'crates') diff --git a/crates/ra_db/src/lib.rs b/crates/ra_db/src/lib.rs index 1f7c9187b..3028db17c 100644 --- a/crates/ra_db/src/lib.rs +++ b/crates/ra_db/src/lib.rs @@ -14,7 +14,7 @@ pub use crate::{ cancelation::{Canceled, Cancelable}, syntax_ptr::LocalSyntaxPtr, input::{ - FilesDatabase, FileId, CrateId, SourceRoot, SourceRootId, CrateGraph, + FilesDatabase, FileId, CrateId, SourceRoot, SourceRootId, CrateGraph, Dependency, FileTextQuery, FileSourceRootQuery, SourceRootQuery, LocalRootsQuery, LibraryRootsQuery, CrateGraphQuery, FileRelativePathQuery }, diff --git a/crates/ra_hir/src/krate.rs b/crates/ra_hir/src/krate.rs index 1196dcef1..89b1e639e 100644 --- a/crates/ra_hir/src/krate.rs +++ b/crates/ra_hir/src/krate.rs @@ -1,7 +1,6 @@ -use ra_syntax::SmolStr; pub use ra_db::CrateId; -use crate::{HirDatabase, Module, Cancelable}; +use crate::{HirDatabase, Module, Cancelable, Name, AsName}; /// hir::Crate describes a single crate. It's the main inteface with which /// crate's dependencies interact. Mostly, it should be just a proxy for the @@ -14,7 +13,7 @@ pub struct Crate { #[derive(Debug)] pub struct CrateDependency { pub krate: Crate, - pub name: SmolStr, + pub name: Name, } impl Crate { @@ -27,7 +26,7 @@ impl Crate { .dependencies(self.crate_id) .map(|dep| { let krate = Crate::new(dep.crate_id()); - let name = dep.name.clone(); + let name = dep.as_name(); CrateDependency { krate, name } }) .collect() diff --git a/crates/ra_hir/src/lib.rs b/crates/ra_hir/src/lib.rs index f1cc0ccd0..bf43cd0ae 100644 --- a/crates/ra_hir/src/lib.rs +++ b/crates/ra_hir/src/lib.rs @@ -22,6 +22,7 @@ mod path; mod arena; pub mod source_binder; +mod name; mod krate; mod module; mod function; @@ -37,10 +38,12 @@ use ra_db::{LocationIntener, SourceRootId, FileId, Cancelable}; use crate::{ db::HirDatabase, arena::{Arena, Id}, + name::AsName, }; pub use self::{ path::{Path, PathKind}, + name::Name, krate::Crate, module::{Module, ModuleId, Problem, nameres::{ItemMap, PerNs, Namespace}, ModuleScope, Resolution}, function::{Function, FnScopes}, diff --git a/crates/ra_hir/src/module.rs b/crates/ra_hir/src/module.rs index b9d36f01f..43413acb8 100644 --- a/crates/ra_hir/src/module.rs +++ b/crates/ra_hir/src/module.rs @@ -7,13 +7,14 @@ use log; use ra_syntax::{ algo::generate, ast::{self, AstNode, NameOwner}, - SmolStr, SyntaxNode, + SyntaxNode, }; use ra_db::{SourceRootId, FileId, Cancelable}; use relative_path::RelativePathBuf; use crate::{ DefKind, DefLoc, DefId, Path, PathKind, HirDatabase, SourceItemId, SourceFileItemId, Crate, + Name, arena::{Arena, Id}, }; @@ -84,7 +85,7 @@ impl Module { } /// `name` is `None` for the crate's root module - pub fn name(&self) -> Option { + pub fn name(&self) -> Option<&Name> { let link = self.module_id.parent_link(&self.tree)?; Some(link.name(&self.tree)) } @@ -100,7 +101,7 @@ impl Module { } /// Finds a child module with the specified name. - pub fn child(&self, name: &str) -> Option { + pub fn child(&self, name: &Name) -> Option { let child_id = self.module_id.child(&self.tree, name)?; Some(Module { module_id: child_id, @@ -230,15 +231,15 @@ impl ModuleId { .last() .unwrap() } - fn child(self, tree: &ModuleTree, name: &str) -> Option { + fn child(self, tree: &ModuleTree, name: &Name) -> Option { let link = tree.mods[self] .children .iter() .map(|&it| &tree.links[it]) - .find(|it| it.name == name)?; + .find(|it| it.name == *name)?; Some(*link.points_to.first()?) } - fn children<'a>(self, tree: &'a ModuleTree) -> impl Iterator + 'a { + fn children<'a>(self, tree: &'a ModuleTree) -> impl Iterator + 'a { tree.mods[self].children.iter().filter_map(move |&it| { let link = &tree.links[it]; let module = *link.points_to.first()?; @@ -263,8 +264,8 @@ impl LinkId { fn owner(self, tree: &ModuleTree) -> ModuleId { tree.links[self].owner } - fn name(self, tree: &ModuleTree) -> SmolStr { - tree.links[self].name.clone() + fn name(self, tree: &ModuleTree) -> &Name { + &tree.links[self].name } fn bind_source<'a>(self, tree: &ModuleTree, db: &impl HirDatabase) -> ast::ModuleNode { let owner = self.owner(tree); @@ -328,7 +329,7 @@ impl ModuleSource { #[derive(Hash, Debug, PartialEq, Eq)] struct LinkData { owner: ModuleId, - name: SmolStr, + name: Name, points_to: Vec, problem: Option, } diff --git a/crates/ra_hir/src/module/imp.rs b/crates/ra_hir/src/module/imp.rs index 748fdb64e..eded85a63 100644 --- a/crates/ra_hir/src/module/imp.rs +++ b/crates/ra_hir/src/module/imp.rs @@ -1,16 +1,13 @@ use std::sync::Arc; -use ra_syntax::{ - ast::{self, NameOwner}, - SmolStr, -}; +use ra_syntax::ast::{self, NameOwner}; use relative_path::RelativePathBuf; use rustc_hash::{FxHashMap, FxHashSet}; use arrayvec::ArrayVec; use ra_db::{SourceRoot, SourceRootId, Cancelable, FileId}; use crate::{ - HirDatabase, + HirDatabase, Name, AsName, }; use super::{ @@ -20,12 +17,12 @@ use super::{ #[derive(Clone, Hash, PartialEq, Eq, Debug)] pub enum Submodule { - Declaration(SmolStr), - Definition(SmolStr, ModuleSource), + Declaration(Name), + Definition(Name, ModuleSource), } impl Submodule { - fn name(&self) -> &SmolStr { + fn name(&self) -> &Name { match self { Submodule::Declaration(name) => name, Submodule::Definition(name, _) => name, @@ -35,14 +32,14 @@ impl Submodule { pub(crate) fn modules<'a>( root: impl ast::ModuleItemOwner<'a>, -) -> impl Iterator)> { +) -> impl Iterator)> { root.items() .filter_map(|item| match item { ast::ModuleItem::Module(m) => Some(m), _ => None, }) .filter_map(|module| { - let name = module.name()?.text(); + let name = module.name()?.as_name(); Some((name, module)) }) } @@ -155,7 +152,7 @@ fn build_subtree( fn resolve_submodule( db: &impl HirDatabase, source: ModuleSource, - name: &SmolStr, + name: &Name, ) -> (Vec, Option) { // FIXME: handle submodules of inline modules properly let file_id = source.file_id(); diff --git a/crates/ra_hir/src/module/nameres.rs b/crates/ra_hir/src/module/nameres.rs index 98cd225dd..68eb02a98 100644 --- a/crates/ra_hir/src/module/nameres.rs +++ b/crates/ra_hir/src/module/nameres.rs @@ -14,14 +14,12 @@ //! modifications (that is, typing inside a function shold not change IMIs), //! such that the results of name resolution can be preserved unless the module //! structure itself is modified. -use std::{ - sync::Arc, -}; +use std::sync::Arc; use rustc_hash::FxHashMap; use ra_syntax::{ TextRange, - SmolStr, SyntaxKind::{self, *}, + SyntaxKind::{self, *}, ast::{self, AstNode} }; use ra_db::SourceRootId; @@ -32,6 +30,7 @@ use crate::{ SourceItemId, SourceFileItemId, SourceFileItems, Path, PathKind, HirDatabase, Crate, + Name, AsName, module::{Module, ModuleId, ModuleTree}, }; @@ -45,14 +44,14 @@ pub struct ItemMap { #[derive(Debug, Default, PartialEq, Eq, Clone)] pub struct ModuleScope { - items: FxHashMap, + items: FxHashMap, } impl ModuleScope { - pub fn entries<'a>(&'a self) -> impl Iterator + 'a { + pub fn entries<'a>(&'a self) -> impl Iterator + 'a { self.items.iter() } - pub fn get(&self, name: &SmolStr) -> Option<&Resolution> { + pub fn get(&self, name: &Name) -> Option<&Resolution> { self.items.get(name) } } @@ -72,7 +71,7 @@ pub struct InputModuleItems { #[derive(Debug, PartialEq, Eq)] struct ModuleItem { id: SourceFileItemId, - name: SmolStr, + name: Name, kind: SyntaxKind, vis: Vis, } @@ -260,7 +259,7 @@ impl InputModuleItems { impl ModuleItem { fn new<'a>(file_items: &SourceFileItems, item: impl ast::NameOwner<'a>) -> Option { - let name = item.name()?.text(); + let name = item.name()?.as_name(); let kind = item.syntax().kind(); let vis = Vis::Other; let id = file_items.id_of_unchecked(item.syntax()); @@ -328,7 +327,11 @@ where for dep in krate.dependencies(self.db) { if let Some(module) = dep.krate.root_module(self.db)? { let def_id = module.def_id(self.db); - self.add_module_item(&mut module_items, dep.name, PerNs::types(def_id)); + self.add_module_item( + &mut module_items, + dep.name.clone(), + PerNs::types(def_id), + ); } } }; @@ -389,7 +392,7 @@ where Ok(()) } - fn add_module_item(&self, module_items: &mut ModuleScope, name: SmolStr, def_id: PerNs) { + fn add_module_item(&self, module_items: &mut ModuleScope, name: Name, def_id: PerNs) { let resolution = Resolution { def_id, import: None, diff --git a/crates/ra_hir/src/module/nameres/tests.rs b/crates/ra_hir/src/module/nameres/tests.rs index 03ea5c1d6..165ac81c8 100644 --- a/crates/ra_hir/src/module/nameres/tests.rs +++ b/crates/ra_hir/src/module/nameres/tests.rs @@ -9,6 +9,7 @@ use crate::{ self as hir, db::HirDatabase, mock::MockDatabase, + Name, }; fn item_map(fixture: &str) -> (Arc, hir::ModuleId) { @@ -38,7 +39,7 @@ fn item_map_smoke_test() { pub struct Baz; ", ); - let name = SmolStr::from("Baz"); + let name = Name::new(SmolStr::from("Baz")); let resolution = &item_map.per_module[&module_id].items[&name]; assert!(resolution.def_id.take_types().is_some()); } @@ -57,7 +58,7 @@ fn test_self() { pub struct Baz; ", ); - let name = SmolStr::from("Baz"); + let name = Name::new(SmolStr::from("Baz")); let resolution = &item_map.per_module[&module_id].items[&name]; assert!(resolution.def_id.take_types().is_some()); } @@ -90,7 +91,7 @@ fn item_map_across_crates() { let module_id = module.module_id; let item_map = db.item_map(source_root).unwrap(); - let name = SmolStr::from("Baz"); + let name = Name::new(SmolStr::from("Baz")); let resolution = &item_map.per_module[&module_id].items[&name]; assert!(resolution.def_id.take_types().is_some()); } diff --git a/crates/ra_hir/src/name.rs b/crates/ra_hir/src/name.rs new file mode 100644 index 000000000..7f42c9f04 --- /dev/null +++ b/crates/ra_hir/src/name.rs @@ -0,0 +1,56 @@ +use std::fmt; + +use ra_syntax::{ast, SmolStr}; + +/// `Name` is a wrapper around string, which is used in hir for both references +/// and declarations. In theory, names should also carry hygene info, but we are +/// not there yet! +#[derive(Debug, Clone, PartialEq, Eq, Hash)] +pub struct Name { + text: SmolStr, +} + +impl fmt::Display for Name { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + fmt::Display::fmt(&self.text, f) + } +} + +impl Name { + // TODO: get rid of this? + pub(crate) fn as_str(&self) -> &str { + self.text.as_str() + } + + #[cfg(not(test))] + fn new(text: SmolStr) -> Name { + Name { text } + } + + #[cfg(test)] + pub(crate) fn new(text: SmolStr) -> Name { + Name { text } + } +} + +pub(crate) trait AsName { + fn as_name(&self) -> Name; +} + +impl AsName for ast::NameRef<'_> { + fn as_name(&self) -> Name { + Name::new(self.text()) + } +} + +impl AsName for ast::Name<'_> { + fn as_name(&self) -> Name { + Name::new(self.text()) + } +} + +impl AsName for ra_db::Dependency { + fn as_name(&self) -> Name { + Name::new(self.name.clone()) + } +} diff --git a/crates/ra_hir/src/path.rs b/crates/ra_hir/src/path.rs index 0b260072c..93f7203fe 100644 --- a/crates/ra_hir/src/path.rs +++ b/crates/ra_hir/src/path.rs @@ -1,9 +1,11 @@ -use ra_syntax::{SmolStr, ast, AstNode, TextRange}; +use ra_syntax::{ast, AstNode, TextRange}; + +use crate::{Name, AsName}; #[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct Path { pub kind: PathKind, - pub segments: Vec, + pub segments: Vec, } #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] @@ -29,7 +31,7 @@ impl Path { loop { let segment = path.segment()?; match segment.kind()? { - ast::PathSegmentKind::Name(name) => segments.push(name.text()), + ast::PathSegmentKind::Name(name) => segments.push(name.as_name()), ast::PathSegmentKind::CrateKw => { kind = PathKind::Crate; break; @@ -67,6 +69,14 @@ impl Path { pub fn is_ident(&self) -> bool { self.kind == PathKind::Plain && self.segments.len() == 1 } + + /// If this path is a single identifier, like `foo`, return its name. + pub fn as_ident(&self) -> Option<&Name> { + if self.kind != PathKind::Plain || self.segments.len() > 1 { + return None; + } + self.segments.first() + } } fn expand_use_tree( @@ -130,7 +140,7 @@ fn convert_path(prefix: Option, path: ast::Path) -> Option { kind: PathKind::Plain, segments: Vec::with_capacity(1), }); - res.segments.push(name.text()); + res.segments.push(name.as_name()); res } ast::PathSegmentKind::CrateKw => { diff --git a/crates/ra_hir/src/query_definitions.rs b/crates/ra_hir/src/query_definitions.rs index 4a7958a12..e6241342a 100644 --- a/crates/ra_hir/src/query_definitions.rs +++ b/crates/ra_hir/src/query_definitions.rs @@ -11,7 +11,7 @@ use ra_syntax::{ use ra_db::{SourceRootId, FileId, Cancelable,}; use crate::{ - SourceFileItems, SourceItemId, DefKind, Function, DefId, + SourceFileItems, SourceItemId, DefKind, Function, DefId, Name, AsName, db::HirDatabase, function::{FnScopes, FnId}, module::{ @@ -130,14 +130,14 @@ pub(crate) fn submodules( pub(crate) fn modules<'a>( root: impl ast::ModuleItemOwner<'a>, -) -> impl Iterator)> { +) -> impl Iterator)> { root.items() .filter_map(|item| match item { ast::ModuleItem::Module(m) => Some(m), _ => None, }) .filter_map(|module| { - let name = module.name()?.text(); + let name = module.name()?.as_name(); Some((name, module)) }) } diff --git a/crates/ra_hir/src/ty.rs b/crates/ra_hir/src/ty.rs index 67b523c2c..dc3323b1a 100644 --- a/crates/ra_hir/src/ty.rs +++ b/crates/ra_hir/src/ty.rs @@ -179,13 +179,13 @@ impl Ty { module: &Module, path: &Path, ) -> Cancelable { - if path.is_ident() { - let name = &path.segments[0]; - if let Some(int_ty) = primitive::IntTy::from_string(&name) { + if let Some(name) = path.as_ident() { + let name = name.as_str(); // :-( + if let Some(int_ty) = primitive::IntTy::from_string(name) { return Ok(Ty::Int(int_ty)); - } else if let Some(uint_ty) = primitive::UintTy::from_string(&name) { + } else if let Some(uint_ty) = primitive::UintTy::from_string(name) { return Ok(Ty::Uint(uint_ty)); - } else if let Some(float_ty) = primitive::FloatTy::from_string(&name) { + } else if let Some(float_ty) = primitive::FloatTy::from_string(name) { return Ok(Ty::Float(float_ty)); } } -- cgit v1.2.3 From a9f55029b9db3bcd439d31c5007785299f7d4025 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Thu, 27 Dec 2018 20:26:15 +0300 Subject: introduce known names --- crates/ra_hir/src/lib.rs | 2 +- crates/ra_hir/src/name.rs | 47 ++++++++++++++++++++++++++++++++++++--- crates/ra_hir/src/ty.rs | 9 ++++---- crates/ra_hir/src/ty/primitive.rs | 42 +++++++++++++++++----------------- 4 files changed, 71 insertions(+), 29 deletions(-) (limited to 'crates') diff --git a/crates/ra_hir/src/lib.rs b/crates/ra_hir/src/lib.rs index bf43cd0ae..5bbb09c01 100644 --- a/crates/ra_hir/src/lib.rs +++ b/crates/ra_hir/src/lib.rs @@ -38,7 +38,7 @@ use ra_db::{LocationIntener, SourceRootId, FileId, Cancelable}; use crate::{ db::HirDatabase, arena::{Arena, Id}, - name::AsName, + name::{AsName, KnownName}, }; pub use self::{ diff --git a/crates/ra_hir/src/name.rs b/crates/ra_hir/src/name.rs index 7f42c9f04..cdad31be7 100644 --- a/crates/ra_hir/src/name.rs +++ b/crates/ra_hir/src/name.rs @@ -17,9 +17,25 @@ impl fmt::Display for Name { } impl Name { - // TODO: get rid of this? - pub(crate) fn as_str(&self) -> &str { - self.text.as_str() + pub(crate) fn as_known_name(&self) -> Option { + let name = match self.text.as_str() { + "isize" => KnownName::Isize, + "i8" => KnownName::I8, + "i16" => KnownName::I16, + "i32" => KnownName::I32, + "i64" => KnownName::I64, + "i128" => KnownName::I128, + "usize" => KnownName::Usize, + "u8" => KnownName::U8, + "u16" => KnownName::U16, + "u32" => KnownName::U32, + "u64" => KnownName::U64, + "u128" => KnownName::U128, + "f32" => KnownName::F32, + "f64" => KnownName::F64, + _ => return None, + }; + Some(name) } #[cfg(not(test))] @@ -54,3 +70,28 @@ impl AsName for ra_db::Dependency { Name::new(self.name.clone()) } } + +// Ideally, should be replaced with +// ``` +// const ISIZE: Name = Name::new("isize") +// ``` +// but const-fn is not that powerful yet. +#[derive(Debug)] +pub(crate) enum KnownName { + Isize, + I8, + I16, + I32, + I64, + I128, + + Usize, + U8, + U16, + U32, + U64, + U128, + + F32, + F64, +} diff --git a/crates/ra_hir/src/ty.rs b/crates/ra_hir/src/ty.rs index dc3323b1a..ad097d1f1 100644 --- a/crates/ra_hir/src/ty.rs +++ b/crates/ra_hir/src/ty.rs @@ -95,7 +95,7 @@ pub enum Ty { Tuple(Vec), // The projection of an associated type. For example, - // `>::N`. + // `>::N`.pub // Projection(ProjectionTy), // Opaque (`impl Trait`) type found in a return type. @@ -180,12 +180,11 @@ impl Ty { path: &Path, ) -> Cancelable { if let Some(name) = path.as_ident() { - let name = name.as_str(); // :-( - if let Some(int_ty) = primitive::IntTy::from_string(name) { + if let Some(int_ty) = primitive::IntTy::from_name(name) { return Ok(Ty::Int(int_ty)); - } else if let Some(uint_ty) = primitive::UintTy::from_string(name) { + } else if let Some(uint_ty) = primitive::UintTy::from_name(name) { return Ok(Ty::Uint(uint_ty)); - } else if let Some(float_ty) = primitive::FloatTy::from_string(name) { + } else if let Some(float_ty) = primitive::FloatTy::from_name(name) { return Ok(Ty::Float(float_ty)); } } diff --git a/crates/ra_hir/src/ty/primitive.rs b/crates/ra_hir/src/ty/primitive.rs index ad79b17e4..498d42d52 100644 --- a/crates/ra_hir/src/ty/primitive.rs +++ b/crates/ra_hir/src/ty/primitive.rs @@ -1,5 +1,7 @@ use std::fmt; +use crate::{Name, KnownName}; + #[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Copy)] pub enum IntTy { Isize, @@ -34,14 +36,14 @@ impl IntTy { } } - pub fn from_string(s: &str) -> Option { - match s { - "isize" => Some(IntTy::Isize), - "i8" => Some(IntTy::I8), - "i16" => Some(IntTy::I16), - "i32" => Some(IntTy::I32), - "i64" => Some(IntTy::I64), - "i128" => Some(IntTy::I128), + pub fn from_name(name: &Name) -> Option { + match name.as_known_name()? { + KnownName::Isize => Some(IntTy::Isize), + KnownName::I8 => Some(IntTy::I8), + KnownName::I16 => Some(IntTy::I16), + KnownName::I32 => Some(IntTy::I32), + KnownName::I64 => Some(IntTy::I64), + KnownName::I128 => Some(IntTy::I128), _ => None, } } @@ -69,14 +71,14 @@ impl UintTy { } } - pub fn from_string(s: &str) -> Option { - match s { - "usize" => Some(UintTy::Usize), - "u8" => Some(UintTy::U8), - "u16" => Some(UintTy::U16), - "u32" => Some(UintTy::U32), - "u64" => Some(UintTy::U64), - "u128" => Some(UintTy::U128), + pub fn from_name(name: &Name) -> Option { + match name.as_known_name()? { + KnownName::Usize => Some(UintTy::Usize), + KnownName::U8 => Some(UintTy::U8), + KnownName::U16 => Some(UintTy::U16), + KnownName::U32 => Some(UintTy::U32), + KnownName::U64 => Some(UintTy::U64), + KnownName::U128 => Some(UintTy::U128), _ => None, } } @@ -120,10 +122,10 @@ impl FloatTy { } } - pub fn from_string(s: &str) -> Option { - match s { - "f32" => Some(FloatTy::F32), - "f64" => Some(FloatTy::F64), + pub fn from_name(name: &Name) -> Option { + match name.as_known_name()? { + KnownName::F32 => Some(FloatTy::F32), + KnownName::F64 => Some(FloatTy::F64), _ => None, } } -- cgit v1.2.3 From 63f54d234f0d622d043dca8176f0715889a6ed48 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Thu, 27 Dec 2018 21:02:08 +0300 Subject: dont leak Name details in testing --- crates/ra_hir/src/module/nameres/tests.rs | 67 +++++++++++++++++++++++++------ crates/ra_hir/src/name.rs | 14 +++---- 2 files changed, 62 insertions(+), 19 deletions(-) (limited to 'crates') diff --git a/crates/ra_hir/src/module/nameres/tests.rs b/crates/ra_hir/src/module/nameres/tests.rs index 165ac81c8..ca20f064f 100644 --- a/crates/ra_hir/src/module/nameres/tests.rs +++ b/crates/ra_hir/src/module/nameres/tests.rs @@ -2,14 +2,13 @@ use std::sync::Arc; use salsa::Database; use ra_db::{FilesDatabase, CrateGraph}; -use ra_syntax::SmolStr; use relative_path::RelativePath; +use test_utils::assert_eq_text; use crate::{ self as hir, db::HirDatabase, mock::MockDatabase, - Name, }; fn item_map(fixture: &str) -> (Arc, hir::ModuleId) { @@ -22,6 +21,35 @@ fn item_map(fixture: &str) -> (Arc, hir::ModuleId) { (db.item_map(source_root).unwrap(), module_id) } +fn check_module_item_map(map: &hir::ItemMap, module_id: hir::ModuleId, expected: &str) { + let mut lines = map.per_module[&module_id] + .items + .iter() + .map(|(name, res)| format!("{}: {}", name, dump_resolution(res))) + .collect::>(); + lines.sort(); + let actual = lines.join("\n"); + let expected = expected + .trim() + .lines() + .map(|it| it.trim()) + .collect::>() + .join("\n"); + assert_eq_text!(&actual, &expected); + + fn dump_resolution(resolution: &hir::Resolution) -> &'static str { + match ( + resolution.def_id.types.is_some(), + resolution.def_id.values.is_some(), + ) { + (true, true) => "t v", + (true, false) => "t", + (false, true) => "v", + (false, false) => "_", + } + } +} + #[test] fn item_map_smoke_test() { let (item_map, module_id) = item_map( @@ -39,13 +67,18 @@ fn item_map_smoke_test() { pub struct Baz; ", ); - let name = Name::new(SmolStr::from("Baz")); - let resolution = &item_map.per_module[&module_id].items[&name]; - assert!(resolution.def_id.take_types().is_some()); + check_module_item_map( + &item_map, + module_id, + " + Baz: t v + foo: t + ", + ); } #[test] -fn test_self() { +fn item_map_using_self() { let (item_map, module_id) = item_map( " //- /lib.rs @@ -58,9 +91,14 @@ fn test_self() { pub struct Baz; ", ); - let name = Name::new(SmolStr::from("Baz")); - let resolution = &item_map.per_module[&module_id].items[&name]; - assert!(resolution.def_id.take_types().is_some()); + check_module_item_map( + &item_map, + module_id, + " + Baz: t v + foo: t + ", + ); } #[test] @@ -91,9 +129,14 @@ fn item_map_across_crates() { let module_id = module.module_id; let item_map = db.item_map(source_root).unwrap(); - let name = Name::new(SmolStr::from("Baz")); - let resolution = &item_map.per_module[&module_id].items[&name]; - assert!(resolution.def_id.take_types().is_some()); + check_module_item_map( + &item_map, + module_id, + " + Baz: t v + test_crate: t + ", + ); } #[test] diff --git a/crates/ra_hir/src/name.rs b/crates/ra_hir/src/name.rs index cdad31be7..e4fc141a6 100644 --- a/crates/ra_hir/src/name.rs +++ b/crates/ra_hir/src/name.rs @@ -5,7 +5,7 @@ use ra_syntax::{ast, SmolStr}; /// `Name` is a wrapper around string, which is used in hir for both references /// and declarations. In theory, names should also carry hygene info, but we are /// not there yet! -#[derive(Debug, Clone, PartialEq, Eq, Hash)] +#[derive(Clone, PartialEq, Eq, Hash)] pub struct Name { text: SmolStr, } @@ -16,6 +16,12 @@ impl fmt::Display for Name { } } +impl fmt::Debug for Name { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + fmt::Debug::fmt(&self.text, f) + } +} + impl Name { pub(crate) fn as_known_name(&self) -> Option { let name = match self.text.as_str() { @@ -38,15 +44,9 @@ impl Name { Some(name) } - #[cfg(not(test))] fn new(text: SmolStr) -> Name { Name { text } } - - #[cfg(test)] - pub(crate) fn new(text: SmolStr) -> Name { - Name { text } - } } pub(crate) trait AsName { -- cgit v1.2.3 From e0660506719476a0546e10bee816d7220be85440 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Thu, 27 Dec 2018 21:21:10 +0300 Subject: use names everywhere --- crates/ra_analysis/src/imp.rs | 34 ++++++++++++++++------------------ crates/ra_hir/src/function/scope.rs | 24 ++++++++++++++---------- crates/ra_hir/src/source_binder.rs | 23 +++++++++++++++++++++-- 3 files changed, 51 insertions(+), 30 deletions(-) (limited to 'crates') diff --git a/crates/ra_analysis/src/imp.rs b/crates/ra_analysis/src/imp.rs index 38a5c1a7d..0471a2fca 100644 --- a/crates/ra_analysis/src/imp.rs +++ b/crates/ra_analysis/src/imp.rs @@ -243,7 +243,7 @@ impl AnalysisImpl { rr.add_resolution( position.file_id, FileSymbol { - name: entry.name().clone(), + name: entry.name().to_string().into(), node_range: entry.ptr().range(), kind: NAME, }, @@ -261,23 +261,21 @@ impl AnalysisImpl { let mut rr = ReferenceResolution::new(name.syntax().range()); if let Some(module) = name.syntax().parent().and_then(ast::Module::cast) { if module.has_semi() { - let parent_module = - source_binder::module_from_file_id(&*self.db, position.file_id)?; - let child_name = module.name(); - match (parent_module, child_name) { - (Some(parent_module), Some(child_name)) => { - if let Some(child) = parent_module.child(&child_name.text()) { - let file_id = child.source().file_id(); - let symbol = FileSymbol { - name: child_name.text(), - node_range: TextRange::offset_len(0.into(), 0.into()), - kind: MODULE, - }; - rr.add_resolution(file_id, symbol); - return Ok(Some(rr)); - } - } - _ => (), + if let Some(child_module) = + source_binder::module_from_declaration(&*self.db, position.file_id, module)? + { + let file_id = child_module.source().file_id(); + let name = match child_module.name() { + Some(name) => name.to_string().into(), + None => "".into(), + }; + let symbol = FileSymbol { + name, + node_range: TextRange::offset_len(0.into(), 0.into()), + kind: MODULE, + }; + rr.add_resolution(file_id, symbol); + return Ok(Some(rr)); } } } diff --git a/crates/ra_hir/src/function/scope.rs b/crates/ra_hir/src/function/scope.rs index a1a580979..3e4cfad0c 100644 --- a/crates/ra_hir/src/function/scope.rs +++ b/crates/ra_hir/src/function/scope.rs @@ -1,7 +1,7 @@ use rustc_hash::{FxHashMap, FxHashSet}; use ra_syntax::{ - AstNode, SmolStr, SyntaxNodeRef, TextUnit, TextRange, + AstNode, SyntaxNodeRef, TextUnit, TextRange, algo::generate, ast::{self, ArgListOwner, LoopBodyOwner, NameOwner}, }; @@ -9,6 +9,7 @@ use ra_db::LocalSyntaxPtr; use crate::{ arena::{Arena, Id}, + Name, AsName, }; pub(crate) type ScopeId = Id; @@ -22,7 +23,7 @@ pub struct FnScopes { #[derive(Debug, PartialEq, Eq)] pub struct ScopeEntry { - name: SmolStr, + name: Name, ptr: LocalSyntaxPtr, } @@ -101,11 +102,12 @@ impl FnScopes { pub fn resolve_local_name<'a>(&'a self, name_ref: ast::NameRef) -> Option<&'a ScopeEntry> { let mut shadowed = FxHashSet::default(); + let name = name_ref.as_name(); let ret = self .scope_chain(name_ref.syntax()) .flat_map(|scope| self.entries(scope).iter()) .filter(|entry| shadowed.insert(entry.name())) - .filter(|entry| entry.name() == &name_ref.text()) + .filter(|entry| entry.name() == &name) .nth(0); ret } @@ -170,14 +172,14 @@ impl FnScopes { impl ScopeEntry { fn new(pat: ast::BindPat) -> Option { - let name = pat.name()?; + let name = pat.name()?.as_name(); let res = ScopeEntry { - name: name.text(), + name, ptr: LocalSyntaxPtr::new(pat.syntax()), }; Some(res) } - pub fn name(&self) -> &SmolStr { + pub fn name(&self) -> &Name { &self.name } pub fn ptr(&self) -> LocalSyntaxPtr { @@ -334,7 +336,7 @@ pub struct ReferenceDescriptor { mod tests { use ra_editor::find_node_at_offset; use ra_syntax::SourceFileNode; - use test_utils::extract_offset; + use test_utils::{extract_offset, assert_eq_text}; use super::*; @@ -355,9 +357,11 @@ mod tests { let actual = scopes .scope_chain(marker.syntax()) .flat_map(|scope| scopes.entries(scope)) - .map(|it| it.name()) - .collect::>(); - assert_eq!(actual.as_slice(), expected); + .map(|it| it.name().to_string()) + .collect::>() + .join("\n"); + let expected = expected.join("\n"); + assert_eq_text!(&actual, &expected); } #[test] diff --git a/crates/ra_hir/src/source_binder.rs b/crates/ra_hir/src/source_binder.rs index a0165aef2..a0d1daf71 100644 --- a/crates/ra_hir/src/source_binder.rs +++ b/crates/ra_hir/src/source_binder.rs @@ -8,14 +8,14 @@ use ra_db::{FileId, FilePosition, Cancelable}; use ra_editor::find_node_at_offset; use ra_syntax::{ - ast::{self, AstNode}, + ast::{self, AstNode, NameOwner}, SyntaxNodeRef, }; use crate::{ HirDatabase, Module, Function, SourceItemId, module::ModuleSource, - DefKind, DefLoc + DefKind, DefLoc, AsName, }; /// Locates the module by `FileId`. Picks topmost module in the file. @@ -24,6 +24,25 @@ pub fn module_from_file_id(db: &impl HirDatabase, file_id: FileId) -> Cancelable module_from_source(db, module_source) } +/// Locates the child module by `mod child;` declaration. +pub fn module_from_declaration( + db: &impl HirDatabase, + file_id: FileId, + decl: ast::Module, +) -> Cancelable> { + let parent_module = module_from_file_id(db, file_id)?; + let child_name = decl.name(); + match (parent_module, child_name) { + (Some(parent_module), Some(child_name)) => { + if let Some(child) = parent_module.child(&child_name.as_name()) { + return Ok(Some(child)); + } + } + _ => (), + } + Ok(None) +} + /// Locates the module by position in the source code. pub fn module_from_position( db: &impl HirDatabase, -- cgit v1.2.3