aboutsummaryrefslogtreecommitdiff
path: root/crates
diff options
context:
space:
mode:
authorbors[bot] <bors[bot]@users.noreply.github.com>2018-12-27 20:33:47 +0000
committerbors[bot] <bors[bot]@users.noreply.github.com>2018-12-27 20:33:47 +0000
commitefb63a7666cc9532d97fa7e0da14b540ae8bd5df (patch)
treec4c1b80d8e2dfbb6533cfbdf0bb647ddbeff9419 /crates
parentb26ab3603d8f73c8e57e9e90d44486a608bc9370 (diff)
parente0660506719476a0546e10bee816d7220be85440 (diff)
Merge #330
330: WIP: introduce hir::Name r=matklad a=matklad Currently we are using `SmolStr` throughout the hir as a name, but that is really suboptimal choice: we'll probably want some kind of interning in the future, and we'll definitely need to add hygene info to names. This PR aims to replace strings with a slightly more abstract `Name` type. Co-authored-by: Aleksey Kladov <[email protected]>
Diffstat (limited to 'crates')
-rw-r--r--crates/ra_analysis/src/imp.rs34
-rw-r--r--crates/ra_db/src/lib.rs2
-rw-r--r--crates/ra_hir/src/function/scope.rs24
-rw-r--r--crates/ra_hir/src/krate.rs7
-rw-r--r--crates/ra_hir/src/lib.rs3
-rw-r--r--crates/ra_hir/src/module.rs19
-rw-r--r--crates/ra_hir/src/module/imp.rs19
-rw-r--r--crates/ra_hir/src/module/nameres.rs25
-rw-r--r--crates/ra_hir/src/module/nameres/tests.rs66
-rw-r--r--crates/ra_hir/src/name.rs97
-rw-r--r--crates/ra_hir/src/path.rs18
-rw-r--r--crates/ra_hir/src/query_definitions.rs6
-rw-r--r--crates/ra_hir/src/source_binder.rs23
-rw-r--r--crates/ra_hir/src/ty.rs11
-rw-r--r--crates/ra_hir/src/ty/primitive.rs42
15 files changed, 286 insertions, 110 deletions
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 {
243 rr.add_resolution( 243 rr.add_resolution(
244 position.file_id, 244 position.file_id,
245 FileSymbol { 245 FileSymbol {
246 name: entry.name().clone(), 246 name: entry.name().to_string().into(),
247 node_range: entry.ptr().range(), 247 node_range: entry.ptr().range(),
248 kind: NAME, 248 kind: NAME,
249 }, 249 },
@@ -261,23 +261,21 @@ impl AnalysisImpl {
261 let mut rr = ReferenceResolution::new(name.syntax().range()); 261 let mut rr = ReferenceResolution::new(name.syntax().range());
262 if let Some(module) = name.syntax().parent().and_then(ast::Module::cast) { 262 if let Some(module) = name.syntax().parent().and_then(ast::Module::cast) {
263 if module.has_semi() { 263 if module.has_semi() {
264 let parent_module = 264 if let Some(child_module) =
265 source_binder::module_from_file_id(&*self.db, position.file_id)?; 265 source_binder::module_from_declaration(&*self.db, position.file_id, module)?
266 let child_name = module.name(); 266 {
267 match (parent_module, child_name) { 267 let file_id = child_module.source().file_id();
268 (Some(parent_module), Some(child_name)) => { 268 let name = match child_module.name() {
269 if let Some(child) = parent_module.child(&child_name.text()) { 269 Some(name) => name.to_string().into(),
270 let file_id = child.source().file_id(); 270 None => "".into(),
271 let symbol = FileSymbol { 271 };
272 name: child_name.text(), 272 let symbol = FileSymbol {
273 node_range: TextRange::offset_len(0.into(), 0.into()), 273 name,
274 kind: MODULE, 274 node_range: TextRange::offset_len(0.into(), 0.into()),
275 }; 275 kind: MODULE,
276 rr.add_resolution(file_id, symbol); 276 };
277 return Ok(Some(rr)); 277 rr.add_resolution(file_id, symbol);
278 } 278 return Ok(Some(rr));
279 }
280 _ => (),
281 } 279 }
282 } 280 }
283 } 281 }
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::{
14 cancelation::{Canceled, Cancelable}, 14 cancelation::{Canceled, Cancelable},
15 syntax_ptr::LocalSyntaxPtr, 15 syntax_ptr::LocalSyntaxPtr,
16 input::{ 16 input::{
17 FilesDatabase, FileId, CrateId, SourceRoot, SourceRootId, CrateGraph, 17 FilesDatabase, FileId, CrateId, SourceRoot, SourceRootId, CrateGraph, Dependency,
18 FileTextQuery, FileSourceRootQuery, SourceRootQuery, LocalRootsQuery, LibraryRootsQuery, CrateGraphQuery, 18 FileTextQuery, FileSourceRootQuery, SourceRootQuery, LocalRootsQuery, LibraryRootsQuery, CrateGraphQuery,
19 FileRelativePathQuery 19 FileRelativePathQuery
20 }, 20 },
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 @@
1use rustc_hash::{FxHashMap, FxHashSet}; 1use rustc_hash::{FxHashMap, FxHashSet};
2 2
3use ra_syntax::{ 3use ra_syntax::{
4 AstNode, SmolStr, SyntaxNodeRef, TextUnit, TextRange, 4 AstNode, SyntaxNodeRef, TextUnit, TextRange,
5 algo::generate, 5 algo::generate,
6 ast::{self, ArgListOwner, LoopBodyOwner, NameOwner}, 6 ast::{self, ArgListOwner, LoopBodyOwner, NameOwner},
7}; 7};
@@ -9,6 +9,7 @@ use ra_db::LocalSyntaxPtr;
9 9
10use crate::{ 10use crate::{
11 arena::{Arena, Id}, 11 arena::{Arena, Id},
12 Name, AsName,
12}; 13};
13 14
14pub(crate) type ScopeId = Id<ScopeData>; 15pub(crate) type ScopeId = Id<ScopeData>;
@@ -22,7 +23,7 @@ pub struct FnScopes {
22 23
23#[derive(Debug, PartialEq, Eq)] 24#[derive(Debug, PartialEq, Eq)]
24pub struct ScopeEntry { 25pub struct ScopeEntry {
25 name: SmolStr, 26 name: Name,
26 ptr: LocalSyntaxPtr, 27 ptr: LocalSyntaxPtr,
27} 28}
28 29
@@ -101,11 +102,12 @@ impl FnScopes {
101 102
102 pub fn resolve_local_name<'a>(&'a self, name_ref: ast::NameRef) -> Option<&'a ScopeEntry> { 103 pub fn resolve_local_name<'a>(&'a self, name_ref: ast::NameRef) -> Option<&'a ScopeEntry> {
103 let mut shadowed = FxHashSet::default(); 104 let mut shadowed = FxHashSet::default();
105 let name = name_ref.as_name();
104 let ret = self 106 let ret = self
105 .scope_chain(name_ref.syntax()) 107 .scope_chain(name_ref.syntax())
106 .flat_map(|scope| self.entries(scope).iter()) 108 .flat_map(|scope| self.entries(scope).iter())
107 .filter(|entry| shadowed.insert(entry.name())) 109 .filter(|entry| shadowed.insert(entry.name()))
108 .filter(|entry| entry.name() == &name_ref.text()) 110 .filter(|entry| entry.name() == &name)
109 .nth(0); 111 .nth(0);
110 ret 112 ret
111 } 113 }
@@ -170,14 +172,14 @@ impl FnScopes {
170 172
171impl ScopeEntry { 173impl ScopeEntry {
172 fn new(pat: ast::BindPat) -> Option<ScopeEntry> { 174 fn new(pat: ast::BindPat) -> Option<ScopeEntry> {
173 let name = pat.name()?; 175 let name = pat.name()?.as_name();
174 let res = ScopeEntry { 176 let res = ScopeEntry {
175 name: name.text(), 177 name,
176 ptr: LocalSyntaxPtr::new(pat.syntax()), 178 ptr: LocalSyntaxPtr::new(pat.syntax()),
177 }; 179 };
178 Some(res) 180 Some(res)
179 } 181 }
180 pub fn name(&self) -> &SmolStr { 182 pub fn name(&self) -> &Name {
181 &self.name 183 &self.name
182 } 184 }
183 pub fn ptr(&self) -> LocalSyntaxPtr { 185 pub fn ptr(&self) -> LocalSyntaxPtr {
@@ -334,7 +336,7 @@ pub struct ReferenceDescriptor {
334mod tests { 336mod tests {
335 use ra_editor::find_node_at_offset; 337 use ra_editor::find_node_at_offset;
336 use ra_syntax::SourceFileNode; 338 use ra_syntax::SourceFileNode;
337 use test_utils::extract_offset; 339 use test_utils::{extract_offset, assert_eq_text};
338 340
339 use super::*; 341 use super::*;
340 342
@@ -355,9 +357,11 @@ mod tests {
355 let actual = scopes 357 let actual = scopes
356 .scope_chain(marker.syntax()) 358 .scope_chain(marker.syntax())
357 .flat_map(|scope| scopes.entries(scope)) 359 .flat_map(|scope| scopes.entries(scope))
358 .map(|it| it.name()) 360 .map(|it| it.name().to_string())
359 .collect::<Vec<_>>(); 361 .collect::<Vec<_>>()
360 assert_eq!(actual.as_slice(), expected); 362 .join("\n");
363 let expected = expected.join("\n");
364 assert_eq_text!(&actual, &expected);
361 } 365 }
362 366
363 #[test] 367 #[test]
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 @@
1use ra_syntax::SmolStr;
2pub use ra_db::CrateId; 1pub use ra_db::CrateId;
3 2
4use crate::{HirDatabase, Module, Cancelable}; 3use crate::{HirDatabase, Module, Cancelable, Name, AsName};
5 4
6/// hir::Crate describes a single crate. It's the main inteface with which 5/// hir::Crate describes a single crate. It's the main inteface with which
7/// crate's dependencies interact. Mostly, it should be just a proxy for the 6/// crate's dependencies interact. Mostly, it should be just a proxy for the
@@ -14,7 +13,7 @@ pub struct Crate {
14#[derive(Debug)] 13#[derive(Debug)]
15pub struct CrateDependency { 14pub struct CrateDependency {
16 pub krate: Crate, 15 pub krate: Crate,
17 pub name: SmolStr, 16 pub name: Name,
18} 17}
19 18
20impl Crate { 19impl Crate {
@@ -27,7 +26,7 @@ impl Crate {
27 .dependencies(self.crate_id) 26 .dependencies(self.crate_id)
28 .map(|dep| { 27 .map(|dep| {
29 let krate = Crate::new(dep.crate_id()); 28 let krate = Crate::new(dep.crate_id());
30 let name = dep.name.clone(); 29 let name = dep.as_name();
31 CrateDependency { krate, name } 30 CrateDependency { krate, name }
32 }) 31 })
33 .collect() 32 .collect()
diff --git a/crates/ra_hir/src/lib.rs b/crates/ra_hir/src/lib.rs
index f1cc0ccd0..5bbb09c01 100644
--- a/crates/ra_hir/src/lib.rs
+++ b/crates/ra_hir/src/lib.rs
@@ -22,6 +22,7 @@ mod path;
22mod arena; 22mod arena;
23pub mod source_binder; 23pub mod source_binder;
24 24
25mod name;
25mod krate; 26mod krate;
26mod module; 27mod module;
27mod function; 28mod function;
@@ -37,10 +38,12 @@ use ra_db::{LocationIntener, SourceRootId, FileId, Cancelable};
37use crate::{ 38use crate::{
38 db::HirDatabase, 39 db::HirDatabase,
39 arena::{Arena, Id}, 40 arena::{Arena, Id},
41 name::{AsName, KnownName},
40}; 42};
41 43
42pub use self::{ 44pub use self::{
43 path::{Path, PathKind}, 45 path::{Path, PathKind},
46 name::Name,
44 krate::Crate, 47 krate::Crate,
45 module::{Module, ModuleId, Problem, nameres::{ItemMap, PerNs, Namespace}, ModuleScope, Resolution}, 48 module::{Module, ModuleId, Problem, nameres::{ItemMap, PerNs, Namespace}, ModuleScope, Resolution},
46 function::{Function, FnScopes}, 49 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;
7use ra_syntax::{ 7use ra_syntax::{
8 algo::generate, 8 algo::generate,
9 ast::{self, AstNode, NameOwner}, 9 ast::{self, AstNode, NameOwner},
10 SmolStr, SyntaxNode, 10 SyntaxNode,
11}; 11};
12use ra_db::{SourceRootId, FileId, Cancelable}; 12use ra_db::{SourceRootId, FileId, Cancelable};
13use relative_path::RelativePathBuf; 13use relative_path::RelativePathBuf;
14 14
15use crate::{ 15use crate::{
16 DefKind, DefLoc, DefId, Path, PathKind, HirDatabase, SourceItemId, SourceFileItemId, Crate, 16 DefKind, DefLoc, DefId, Path, PathKind, HirDatabase, SourceItemId, SourceFileItemId, Crate,
17 Name,
17 arena::{Arena, Id}, 18 arena::{Arena, Id},
18}; 19};
19 20
@@ -84,7 +85,7 @@ impl Module {
84 } 85 }
85 86
86 /// `name` is `None` for the crate's root module 87 /// `name` is `None` for the crate's root module
87 pub fn name(&self) -> Option<SmolStr> { 88 pub fn name(&self) -> Option<&Name> {
88 let link = self.module_id.parent_link(&self.tree)?; 89 let link = self.module_id.parent_link(&self.tree)?;
89 Some(link.name(&self.tree)) 90 Some(link.name(&self.tree))
90 } 91 }
@@ -100,7 +101,7 @@ impl Module {
100 } 101 }
101 102
102 /// Finds a child module with the specified name. 103 /// Finds a child module with the specified name.
103 pub fn child(&self, name: &str) -> Option<Module> { 104 pub fn child(&self, name: &Name) -> Option<Module> {
104 let child_id = self.module_id.child(&self.tree, name)?; 105 let child_id = self.module_id.child(&self.tree, name)?;
105 Some(Module { 106 Some(Module {
106 module_id: child_id, 107 module_id: child_id,
@@ -230,15 +231,15 @@ impl ModuleId {
230 .last() 231 .last()
231 .unwrap() 232 .unwrap()
232 } 233 }
233 fn child(self, tree: &ModuleTree, name: &str) -> Option<ModuleId> { 234 fn child(self, tree: &ModuleTree, name: &Name) -> Option<ModuleId> {
234 let link = tree.mods[self] 235 let link = tree.mods[self]
235 .children 236 .children
236 .iter() 237 .iter()
237 .map(|&it| &tree.links[it]) 238 .map(|&it| &tree.links[it])
238 .find(|it| it.name == name)?; 239 .find(|it| it.name == *name)?;
239 Some(*link.points_to.first()?) 240 Some(*link.points_to.first()?)
240 } 241 }
241 fn children<'a>(self, tree: &'a ModuleTree) -> impl Iterator<Item = (SmolStr, ModuleId)> + 'a { 242 fn children<'a>(self, tree: &'a ModuleTree) -> impl Iterator<Item = (Name, ModuleId)> + 'a {
242 tree.mods[self].children.iter().filter_map(move |&it| { 243 tree.mods[self].children.iter().filter_map(move |&it| {
243 let link = &tree.links[it]; 244 let link = &tree.links[it];
244 let module = *link.points_to.first()?; 245 let module = *link.points_to.first()?;
@@ -263,8 +264,8 @@ impl LinkId {
263 fn owner(self, tree: &ModuleTree) -> ModuleId { 264 fn owner(self, tree: &ModuleTree) -> ModuleId {
264 tree.links[self].owner 265 tree.links[self].owner
265 } 266 }
266 fn name(self, tree: &ModuleTree) -> SmolStr { 267 fn name(self, tree: &ModuleTree) -> &Name {
267 tree.links[self].name.clone() 268 &tree.links[self].name
268 } 269 }
269 fn bind_source<'a>(self, tree: &ModuleTree, db: &impl HirDatabase) -> ast::ModuleNode { 270 fn bind_source<'a>(self, tree: &ModuleTree, db: &impl HirDatabase) -> ast::ModuleNode {
270 let owner = self.owner(tree); 271 let owner = self.owner(tree);
@@ -328,7 +329,7 @@ impl ModuleSource {
328#[derive(Hash, Debug, PartialEq, Eq)] 329#[derive(Hash, Debug, PartialEq, Eq)]
329struct LinkData { 330struct LinkData {
330 owner: ModuleId, 331 owner: ModuleId,
331 name: SmolStr, 332 name: Name,
332 points_to: Vec<ModuleId>, 333 points_to: Vec<ModuleId>,
333 problem: Option<Problem>, 334 problem: Option<Problem>,
334} 335}
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 @@
1use std::sync::Arc; 1use std::sync::Arc;
2 2
3use ra_syntax::{ 3use ra_syntax::ast::{self, NameOwner};
4 ast::{self, NameOwner},
5 SmolStr,
6};
7use relative_path::RelativePathBuf; 4use relative_path::RelativePathBuf;
8use rustc_hash::{FxHashMap, FxHashSet}; 5use rustc_hash::{FxHashMap, FxHashSet};
9use arrayvec::ArrayVec; 6use arrayvec::ArrayVec;
10use ra_db::{SourceRoot, SourceRootId, Cancelable, FileId}; 7use ra_db::{SourceRoot, SourceRootId, Cancelable, FileId};
11 8
12use crate::{ 9use crate::{
13 HirDatabase, 10 HirDatabase, Name, AsName,
14}; 11};
15 12
16use super::{ 13use super::{
@@ -20,12 +17,12 @@ use super::{
20 17
21#[derive(Clone, Hash, PartialEq, Eq, Debug)] 18#[derive(Clone, Hash, PartialEq, Eq, Debug)]
22pub enum Submodule { 19pub enum Submodule {
23 Declaration(SmolStr), 20 Declaration(Name),
24 Definition(SmolStr, ModuleSource), 21 Definition(Name, ModuleSource),
25} 22}
26 23
27impl Submodule { 24impl Submodule {
28 fn name(&self) -> &SmolStr { 25 fn name(&self) -> &Name {
29 match self { 26 match self {
30 Submodule::Declaration(name) => name, 27 Submodule::Declaration(name) => name,
31 Submodule::Definition(name, _) => name, 28 Submodule::Definition(name, _) => name,
@@ -35,14 +32,14 @@ impl Submodule {
35 32
36pub(crate) fn modules<'a>( 33pub(crate) fn modules<'a>(
37 root: impl ast::ModuleItemOwner<'a>, 34 root: impl ast::ModuleItemOwner<'a>,
38) -> impl Iterator<Item = (SmolStr, ast::Module<'a>)> { 35) -> impl Iterator<Item = (Name, ast::Module<'a>)> {
39 root.items() 36 root.items()
40 .filter_map(|item| match item { 37 .filter_map(|item| match item {
41 ast::ModuleItem::Module(m) => Some(m), 38 ast::ModuleItem::Module(m) => Some(m),
42 _ => None, 39 _ => None,
43 }) 40 })
44 .filter_map(|module| { 41 .filter_map(|module| {
45 let name = module.name()?.text(); 42 let name = module.name()?.as_name();
46 Some((name, module)) 43 Some((name, module))
47 }) 44 })
48} 45}
@@ -155,7 +152,7 @@ fn build_subtree(
155fn resolve_submodule( 152fn resolve_submodule(
156 db: &impl HirDatabase, 153 db: &impl HirDatabase,
157 source: ModuleSource, 154 source: ModuleSource,
158 name: &SmolStr, 155 name: &Name,
159) -> (Vec<FileId>, Option<Problem>) { 156) -> (Vec<FileId>, Option<Problem>) {
160 // FIXME: handle submodules of inline modules properly 157 // FIXME: handle submodules of inline modules properly
161 let file_id = source.file_id(); 158 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 @@
14//! modifications (that is, typing inside a function shold not change IMIs), 14//! modifications (that is, typing inside a function shold not change IMIs),
15//! such that the results of name resolution can be preserved unless the module 15//! such that the results of name resolution can be preserved unless the module
16//! structure itself is modified. 16//! structure itself is modified.
17use std::{ 17use std::sync::Arc;
18 sync::Arc,
19};
20 18
21use rustc_hash::FxHashMap; 19use rustc_hash::FxHashMap;
22use ra_syntax::{ 20use ra_syntax::{
23 TextRange, 21 TextRange,
24 SmolStr, SyntaxKind::{self, *}, 22 SyntaxKind::{self, *},
25 ast::{self, AstNode} 23 ast::{self, AstNode}
26}; 24};
27use ra_db::SourceRootId; 25use ra_db::SourceRootId;
@@ -32,6 +30,7 @@ use crate::{
32 SourceItemId, SourceFileItemId, SourceFileItems, 30 SourceItemId, SourceFileItemId, SourceFileItems,
33 Path, PathKind, 31 Path, PathKind,
34 HirDatabase, Crate, 32 HirDatabase, Crate,
33 Name, AsName,
35 module::{Module, ModuleId, ModuleTree}, 34 module::{Module, ModuleId, ModuleTree},
36}; 35};
37 36
@@ -45,14 +44,14 @@ pub struct ItemMap {
45 44
46#[derive(Debug, Default, PartialEq, Eq, Clone)] 45#[derive(Debug, Default, PartialEq, Eq, Clone)]
47pub struct ModuleScope { 46pub struct ModuleScope {
48 items: FxHashMap<SmolStr, Resolution>, 47 items: FxHashMap<Name, Resolution>,
49} 48}
50 49
51impl ModuleScope { 50impl ModuleScope {
52 pub fn entries<'a>(&'a self) -> impl Iterator<Item = (&'a SmolStr, &'a Resolution)> + 'a { 51 pub fn entries<'a>(&'a self) -> impl Iterator<Item = (&'a Name, &'a Resolution)> + 'a {
53 self.items.iter() 52 self.items.iter()
54 } 53 }
55 pub fn get(&self, name: &SmolStr) -> Option<&Resolution> { 54 pub fn get(&self, name: &Name) -> Option<&Resolution> {
56 self.items.get(name) 55 self.items.get(name)
57 } 56 }
58} 57}
@@ -72,7 +71,7 @@ pub struct InputModuleItems {
72#[derive(Debug, PartialEq, Eq)] 71#[derive(Debug, PartialEq, Eq)]
73struct ModuleItem { 72struct ModuleItem {
74 id: SourceFileItemId, 73 id: SourceFileItemId,
75 name: SmolStr, 74 name: Name,
76 kind: SyntaxKind, 75 kind: SyntaxKind,
77 vis: Vis, 76 vis: Vis,
78} 77}
@@ -260,7 +259,7 @@ impl InputModuleItems {
260 259
261impl ModuleItem { 260impl ModuleItem {
262 fn new<'a>(file_items: &SourceFileItems, item: impl ast::NameOwner<'a>) -> Option<ModuleItem> { 261 fn new<'a>(file_items: &SourceFileItems, item: impl ast::NameOwner<'a>) -> Option<ModuleItem> {
263 let name = item.name()?.text(); 262 let name = item.name()?.as_name();
264 let kind = item.syntax().kind(); 263 let kind = item.syntax().kind();
265 let vis = Vis::Other; 264 let vis = Vis::Other;
266 let id = file_items.id_of_unchecked(item.syntax()); 265 let id = file_items.id_of_unchecked(item.syntax());
@@ -328,7 +327,11 @@ where
328 for dep in krate.dependencies(self.db) { 327 for dep in krate.dependencies(self.db) {
329 if let Some(module) = dep.krate.root_module(self.db)? { 328 if let Some(module) = dep.krate.root_module(self.db)? {
330 let def_id = module.def_id(self.db); 329 let def_id = module.def_id(self.db);
331 self.add_module_item(&mut module_items, dep.name, PerNs::types(def_id)); 330 self.add_module_item(
331 &mut module_items,
332 dep.name.clone(),
333 PerNs::types(def_id),
334 );
332 } 335 }
333 } 336 }
334 }; 337 };
@@ -389,7 +392,7 @@ where
389 Ok(()) 392 Ok(())
390 } 393 }
391 394
392 fn add_module_item(&self, module_items: &mut ModuleScope, name: SmolStr, def_id: PerNs<DefId>) { 395 fn add_module_item(&self, module_items: &mut ModuleScope, name: Name, def_id: PerNs<DefId>) {
393 let resolution = Resolution { 396 let resolution = Resolution {
394 def_id, 397 def_id,
395 import: None, 398 import: None,
diff --git a/crates/ra_hir/src/module/nameres/tests.rs b/crates/ra_hir/src/module/nameres/tests.rs
index 03ea5c1d6..ca20f064f 100644
--- a/crates/ra_hir/src/module/nameres/tests.rs
+++ b/crates/ra_hir/src/module/nameres/tests.rs
@@ -2,8 +2,8 @@ use std::sync::Arc;
2 2
3use salsa::Database; 3use salsa::Database;
4use ra_db::{FilesDatabase, CrateGraph}; 4use ra_db::{FilesDatabase, CrateGraph};
5use ra_syntax::SmolStr;
6use relative_path::RelativePath; 5use relative_path::RelativePath;
6use test_utils::assert_eq_text;
7 7
8use crate::{ 8use crate::{
9 self as hir, 9 self as hir,
@@ -21,6 +21,35 @@ fn item_map(fixture: &str) -> (Arc<hir::ItemMap>, hir::ModuleId) {
21 (db.item_map(source_root).unwrap(), module_id) 21 (db.item_map(source_root).unwrap(), module_id)
22} 22}
23 23
24fn check_module_item_map(map: &hir::ItemMap, module_id: hir::ModuleId, expected: &str) {
25 let mut lines = map.per_module[&module_id]
26 .items
27 .iter()
28 .map(|(name, res)| format!("{}: {}", name, dump_resolution(res)))
29 .collect::<Vec<_>>();
30 lines.sort();
31 let actual = lines.join("\n");
32 let expected = expected
33 .trim()
34 .lines()
35 .map(|it| it.trim())
36 .collect::<Vec<_>>()
37 .join("\n");
38 assert_eq_text!(&actual, &expected);
39
40 fn dump_resolution(resolution: &hir::Resolution) -> &'static str {
41 match (
42 resolution.def_id.types.is_some(),
43 resolution.def_id.values.is_some(),
44 ) {
45 (true, true) => "t v",
46 (true, false) => "t",
47 (false, true) => "v",
48 (false, false) => "_",
49 }
50 }
51}
52
24#[test] 53#[test]
25fn item_map_smoke_test() { 54fn item_map_smoke_test() {
26 let (item_map, module_id) = item_map( 55 let (item_map, module_id) = item_map(
@@ -38,13 +67,18 @@ fn item_map_smoke_test() {
38 pub struct Baz; 67 pub struct Baz;
39 ", 68 ",
40 ); 69 );
41 let name = SmolStr::from("Baz"); 70 check_module_item_map(
42 let resolution = &item_map.per_module[&module_id].items[&name]; 71 &item_map,
43 assert!(resolution.def_id.take_types().is_some()); 72 module_id,
73 "
74 Baz: t v
75 foo: t
76 ",
77 );
44} 78}
45 79
46#[test] 80#[test]
47fn test_self() { 81fn item_map_using_self() {
48 let (item_map, module_id) = item_map( 82 let (item_map, module_id) = item_map(
49 " 83 "
50 //- /lib.rs 84 //- /lib.rs
@@ -57,9 +91,14 @@ fn test_self() {
57 pub struct Baz; 91 pub struct Baz;
58 ", 92 ",
59 ); 93 );
60 let name = SmolStr::from("Baz"); 94 check_module_item_map(
61 let resolution = &item_map.per_module[&module_id].items[&name]; 95 &item_map,
62 assert!(resolution.def_id.take_types().is_some()); 96 module_id,
97 "
98 Baz: t v
99 foo: t
100 ",
101 );
63} 102}
64 103
65#[test] 104#[test]
@@ -90,9 +129,14 @@ fn item_map_across_crates() {
90 let module_id = module.module_id; 129 let module_id = module.module_id;
91 let item_map = db.item_map(source_root).unwrap(); 130 let item_map = db.item_map(source_root).unwrap();
92 131
93 let name = SmolStr::from("Baz"); 132 check_module_item_map(
94 let resolution = &item_map.per_module[&module_id].items[&name]; 133 &item_map,
95 assert!(resolution.def_id.take_types().is_some()); 134 module_id,
135 "
136 Baz: t v
137 test_crate: t
138 ",
139 );
96} 140}
97 141
98#[test] 142#[test]
diff --git a/crates/ra_hir/src/name.rs b/crates/ra_hir/src/name.rs
new file mode 100644
index 000000000..e4fc141a6
--- /dev/null
+++ b/crates/ra_hir/src/name.rs
@@ -0,0 +1,97 @@
1use std::fmt;
2
3use ra_syntax::{ast, SmolStr};
4
5/// `Name` is a wrapper around string, which is used in hir for both references
6/// and declarations. In theory, names should also carry hygene info, but we are
7/// not there yet!
8#[derive(Clone, PartialEq, Eq, Hash)]
9pub struct Name {
10 text: SmolStr,
11}
12
13impl fmt::Display for Name {
14 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
15 fmt::Display::fmt(&self.text, f)
16 }
17}
18
19impl fmt::Debug for Name {
20 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
21 fmt::Debug::fmt(&self.text, f)
22 }
23}
24
25impl Name {
26 pub(crate) fn as_known_name(&self) -> Option<KnownName> {
27 let name = match self.text.as_str() {
28 "isize" => KnownName::Isize,
29 "i8" => KnownName::I8,
30 "i16" => KnownName::I16,
31 "i32" => KnownName::I32,
32 "i64" => KnownName::I64,
33 "i128" => KnownName::I128,
34 "usize" => KnownName::Usize,
35 "u8" => KnownName::U8,
36 "u16" => KnownName::U16,
37 "u32" => KnownName::U32,
38 "u64" => KnownName::U64,
39 "u128" => KnownName::U128,
40 "f32" => KnownName::F32,
41 "f64" => KnownName::F64,
42 _ => return None,
43 };
44 Some(name)
45 }
46
47 fn new(text: SmolStr) -> Name {
48 Name { text }
49 }
50}
51
52pub(crate) trait AsName {
53 fn as_name(&self) -> Name;
54}
55
56impl AsName for ast::NameRef<'_> {
57 fn as_name(&self) -> Name {
58 Name::new(self.text())
59 }
60}
61
62impl AsName for ast::Name<'_> {
63 fn as_name(&self) -> Name {
64 Name::new(self.text())
65 }
66}
67
68impl AsName for ra_db::Dependency {
69 fn as_name(&self) -> Name {
70 Name::new(self.name.clone())
71 }
72}
73
74// Ideally, should be replaced with
75// ```
76// const ISIZE: Name = Name::new("isize")
77// ```
78// but const-fn is not that powerful yet.
79#[derive(Debug)]
80pub(crate) enum KnownName {
81 Isize,
82 I8,
83 I16,
84 I32,
85 I64,
86 I128,
87
88 Usize,
89 U8,
90 U16,
91 U32,
92 U64,
93 U128,
94
95 F32,
96 F64,
97}
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 @@
1use ra_syntax::{SmolStr, ast, AstNode, TextRange}; 1use ra_syntax::{ast, AstNode, TextRange};
2
3use crate::{Name, AsName};
2 4
3#[derive(Debug, Clone, PartialEq, Eq, Hash)] 5#[derive(Debug, Clone, PartialEq, Eq, Hash)]
4pub struct Path { 6pub struct Path {
5 pub kind: PathKind, 7 pub kind: PathKind,
6 pub segments: Vec<SmolStr>, 8 pub segments: Vec<Name>,
7} 9}
8 10
9#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] 11#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
@@ -29,7 +31,7 @@ impl Path {
29 loop { 31 loop {
30 let segment = path.segment()?; 32 let segment = path.segment()?;
31 match segment.kind()? { 33 match segment.kind()? {
32 ast::PathSegmentKind::Name(name) => segments.push(name.text()), 34 ast::PathSegmentKind::Name(name) => segments.push(name.as_name()),
33 ast::PathSegmentKind::CrateKw => { 35 ast::PathSegmentKind::CrateKw => {
34 kind = PathKind::Crate; 36 kind = PathKind::Crate;
35 break; 37 break;
@@ -67,6 +69,14 @@ impl Path {
67 pub fn is_ident(&self) -> bool { 69 pub fn is_ident(&self) -> bool {
68 self.kind == PathKind::Plain && self.segments.len() == 1 70 self.kind == PathKind::Plain && self.segments.len() == 1
69 } 71 }
72
73 /// If this path is a single identifier, like `foo`, return its name.
74 pub fn as_ident(&self) -> Option<&Name> {
75 if self.kind != PathKind::Plain || self.segments.len() > 1 {
76 return None;
77 }
78 self.segments.first()
79 }
70} 80}
71 81
72fn expand_use_tree( 82fn expand_use_tree(
@@ -130,7 +140,7 @@ fn convert_path(prefix: Option<Path>, path: ast::Path) -> Option<Path> {
130 kind: PathKind::Plain, 140 kind: PathKind::Plain,
131 segments: Vec::with_capacity(1), 141 segments: Vec::with_capacity(1),
132 }); 142 });
133 res.segments.push(name.text()); 143 res.segments.push(name.as_name());
134 res 144 res
135 } 145 }
136 ast::PathSegmentKind::CrateKw => { 146 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::{
11use ra_db::{SourceRootId, FileId, Cancelable,}; 11use ra_db::{SourceRootId, FileId, Cancelable,};
12 12
13use crate::{ 13use crate::{
14 SourceFileItems, SourceItemId, DefKind, Function, DefId, 14 SourceFileItems, SourceItemId, DefKind, Function, DefId, Name, AsName,
15 db::HirDatabase, 15 db::HirDatabase,
16 function::{FnScopes, FnId}, 16 function::{FnScopes, FnId},
17 module::{ 17 module::{
@@ -130,14 +130,14 @@ pub(crate) fn submodules(
130 130
131pub(crate) fn modules<'a>( 131pub(crate) fn modules<'a>(
132 root: impl ast::ModuleItemOwner<'a>, 132 root: impl ast::ModuleItemOwner<'a>,
133) -> impl Iterator<Item = (SmolStr, ast::Module<'a>)> { 133) -> impl Iterator<Item = (Name, ast::Module<'a>)> {
134 root.items() 134 root.items()
135 .filter_map(|item| match item { 135 .filter_map(|item| match item {
136 ast::ModuleItem::Module(m) => Some(m), 136 ast::ModuleItem::Module(m) => Some(m),
137 _ => None, 137 _ => None,
138 }) 138 })
139 .filter_map(|module| { 139 .filter_map(|module| {
140 let name = module.name()?.text(); 140 let name = module.name()?.as_name();
141 Some((name, module)) 141 Some((name, module))
142 }) 142 })
143} 143}
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 @@
8use ra_db::{FileId, FilePosition, Cancelable}; 8use ra_db::{FileId, FilePosition, Cancelable};
9use ra_editor::find_node_at_offset; 9use ra_editor::find_node_at_offset;
10use ra_syntax::{ 10use ra_syntax::{
11 ast::{self, AstNode}, 11 ast::{self, AstNode, NameOwner},
12 SyntaxNodeRef, 12 SyntaxNodeRef,
13}; 13};
14 14
15use crate::{ 15use crate::{
16 HirDatabase, Module, Function, SourceItemId, 16 HirDatabase, Module, Function, SourceItemId,
17 module::ModuleSource, 17 module::ModuleSource,
18 DefKind, DefLoc 18 DefKind, DefLoc, AsName,
19}; 19};
20 20
21/// Locates the module by `FileId`. Picks topmost module in the file. 21/// 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
24 module_from_source(db, module_source) 24 module_from_source(db, module_source)
25} 25}
26 26
27/// Locates the child module by `mod child;` declaration.
28pub fn module_from_declaration(
29 db: &impl HirDatabase,
30 file_id: FileId,
31 decl: ast::Module,
32) -> Cancelable<Option<Module>> {
33 let parent_module = module_from_file_id(db, file_id)?;
34 let child_name = decl.name();
35 match (parent_module, child_name) {
36 (Some(parent_module), Some(child_name)) => {
37 if let Some(child) = parent_module.child(&child_name.as_name()) {
38 return Ok(Some(child));
39 }
40 }
41 _ => (),
42 }
43 Ok(None)
44}
45
27/// Locates the module by position in the source code. 46/// Locates the module by position in the source code.
28pub fn module_from_position( 47pub fn module_from_position(
29 db: &impl HirDatabase, 48 db: &impl HirDatabase,
diff --git a/crates/ra_hir/src/ty.rs b/crates/ra_hir/src/ty.rs
index 67b523c2c..ad097d1f1 100644
--- a/crates/ra_hir/src/ty.rs
+++ b/crates/ra_hir/src/ty.rs
@@ -95,7 +95,7 @@ pub enum Ty {
95 Tuple(Vec<Ty>), 95 Tuple(Vec<Ty>),
96 96
97 // The projection of an associated type. For example, 97 // The projection of an associated type. For example,
98 // `<T as Trait<..>>::N`. 98 // `<T as Trait<..>>::N`.pub
99 // Projection(ProjectionTy), 99 // Projection(ProjectionTy),
100 100
101 // Opaque (`impl Trait`) type found in a return type. 101 // Opaque (`impl Trait`) type found in a return type.
@@ -179,13 +179,12 @@ impl Ty {
179 module: &Module, 179 module: &Module,
180 path: &Path, 180 path: &Path,
181 ) -> Cancelable<Self> { 181 ) -> Cancelable<Self> {
182 if path.is_ident() { 182 if let Some(name) = path.as_ident() {
183 let name = &path.segments[0]; 183 if let Some(int_ty) = primitive::IntTy::from_name(name) {
184 if let Some(int_ty) = primitive::IntTy::from_string(&name) {
185 return Ok(Ty::Int(int_ty)); 184 return Ok(Ty::Int(int_ty));
186 } else if let Some(uint_ty) = primitive::UintTy::from_string(&name) { 185 } else if let Some(uint_ty) = primitive::UintTy::from_name(name) {
187 return Ok(Ty::Uint(uint_ty)); 186 return Ok(Ty::Uint(uint_ty));
188 } else if let Some(float_ty) = primitive::FloatTy::from_string(&name) { 187 } else if let Some(float_ty) = primitive::FloatTy::from_name(name) {
189 return Ok(Ty::Float(float_ty)); 188 return Ok(Ty::Float(float_ty));
190 } 189 }
191 } 190 }
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 @@
1use std::fmt; 1use std::fmt;
2 2
3use crate::{Name, KnownName};
4
3#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Copy)] 5#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Copy)]
4pub enum IntTy { 6pub enum IntTy {
5 Isize, 7 Isize,
@@ -34,14 +36,14 @@ impl IntTy {
34 } 36 }
35 } 37 }
36 38
37 pub fn from_string(s: &str) -> Option<IntTy> { 39 pub fn from_name(name: &Name) -> Option<IntTy> {
38 match s { 40 match name.as_known_name()? {
39 "isize" => Some(IntTy::Isize), 41 KnownName::Isize => Some(IntTy::Isize),
40 "i8" => Some(IntTy::I8), 42 KnownName::I8 => Some(IntTy::I8),
41 "i16" => Some(IntTy::I16), 43 KnownName::I16 => Some(IntTy::I16),
42 "i32" => Some(IntTy::I32), 44 KnownName::I32 => Some(IntTy::I32),
43 "i64" => Some(IntTy::I64), 45 KnownName::I64 => Some(IntTy::I64),
44 "i128" => Some(IntTy::I128), 46 KnownName::I128 => Some(IntTy::I128),
45 _ => None, 47 _ => None,
46 } 48 }
47 } 49 }
@@ -69,14 +71,14 @@ impl UintTy {
69 } 71 }
70 } 72 }
71 73
72 pub fn from_string(s: &str) -> Option<UintTy> { 74 pub fn from_name(name: &Name) -> Option<UintTy> {
73 match s { 75 match name.as_known_name()? {
74 "usize" => Some(UintTy::Usize), 76 KnownName::Usize => Some(UintTy::Usize),
75 "u8" => Some(UintTy::U8), 77 KnownName::U8 => Some(UintTy::U8),
76 "u16" => Some(UintTy::U16), 78 KnownName::U16 => Some(UintTy::U16),
77 "u32" => Some(UintTy::U32), 79 KnownName::U32 => Some(UintTy::U32),
78 "u64" => Some(UintTy::U64), 80 KnownName::U64 => Some(UintTy::U64),
79 "u128" => Some(UintTy::U128), 81 KnownName::U128 => Some(UintTy::U128),
80 _ => None, 82 _ => None,
81 } 83 }
82 } 84 }
@@ -120,10 +122,10 @@ impl FloatTy {
120 } 122 }
121 } 123 }
122 124
123 pub fn from_string(s: &str) -> Option<FloatTy> { 125 pub fn from_name(name: &Name) -> Option<FloatTy> {
124 match s { 126 match name.as_known_name()? {
125 "f32" => Some(FloatTy::F32), 127 KnownName::F32 => Some(FloatTy::F32),
126 "f64" => Some(FloatTy::F64), 128 KnownName::F64 => Some(FloatTy::F64),
127 _ => None, 129 _ => None,
128 } 130 }
129 } 131 }