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 <aleksey.kladov@gmail.com>
This commit is contained in:
bors[bot] 2018-12-27 20:33:47 +00:00
commit efb63a7666
15 changed files with 286 additions and 110 deletions

View File

@ -243,7 +243,7 @@ impl AnalysisImpl {
rr.add_resolution( rr.add_resolution(
position.file_id, position.file_id,
FileSymbol { FileSymbol {
name: entry.name().clone(), name: entry.name().to_string().into(),
node_range: entry.ptr().range(), node_range: entry.ptr().range(),
kind: NAME, kind: NAME,
}, },
@ -261,23 +261,21 @@ impl AnalysisImpl {
let mut rr = ReferenceResolution::new(name.syntax().range()); let mut rr = ReferenceResolution::new(name.syntax().range());
if let Some(module) = name.syntax().parent().and_then(ast::Module::cast) { if let Some(module) = name.syntax().parent().and_then(ast::Module::cast) {
if module.has_semi() { if module.has_semi() {
let parent_module = if let Some(child_module) =
source_binder::module_from_file_id(&*self.db, position.file_id)?; source_binder::module_from_declaration(&*self.db, position.file_id, module)?
let child_name = module.name(); {
match (parent_module, child_name) { let file_id = child_module.source().file_id();
(Some(parent_module), Some(child_name)) => { let name = match child_module.name() {
if let Some(child) = parent_module.child(&child_name.text()) { Some(name) => name.to_string().into(),
let file_id = child.source().file_id(); None => "".into(),
let symbol = FileSymbol { };
name: child_name.text(), let symbol = FileSymbol {
node_range: TextRange::offset_len(0.into(), 0.into()), name,
kind: MODULE, node_range: TextRange::offset_len(0.into(), 0.into()),
}; kind: MODULE,
rr.add_resolution(file_id, symbol); };
return Ok(Some(rr)); rr.add_resolution(file_id, symbol);
} return Ok(Some(rr));
}
_ => (),
} }
} }
} }

View File

@ -14,7 +14,7 @@ pub use crate::{
cancelation::{Canceled, Cancelable}, cancelation::{Canceled, Cancelable},
syntax_ptr::LocalSyntaxPtr, syntax_ptr::LocalSyntaxPtr,
input::{ input::{
FilesDatabase, FileId, CrateId, SourceRoot, SourceRootId, CrateGraph, FilesDatabase, FileId, CrateId, SourceRoot, SourceRootId, CrateGraph, Dependency,
FileTextQuery, FileSourceRootQuery, SourceRootQuery, LocalRootsQuery, LibraryRootsQuery, CrateGraphQuery, FileTextQuery, FileSourceRootQuery, SourceRootQuery, LocalRootsQuery, LibraryRootsQuery, CrateGraphQuery,
FileRelativePathQuery FileRelativePathQuery
}, },

View File

@ -1,7 +1,7 @@
use rustc_hash::{FxHashMap, FxHashSet}; use rustc_hash::{FxHashMap, FxHashSet};
use ra_syntax::{ use ra_syntax::{
AstNode, SmolStr, SyntaxNodeRef, TextUnit, TextRange, AstNode, SyntaxNodeRef, TextUnit, TextRange,
algo::generate, algo::generate,
ast::{self, ArgListOwner, LoopBodyOwner, NameOwner}, ast::{self, ArgListOwner, LoopBodyOwner, NameOwner},
}; };
@ -9,6 +9,7 @@ use ra_db::LocalSyntaxPtr;
use crate::{ use crate::{
arena::{Arena, Id}, arena::{Arena, Id},
Name, AsName,
}; };
pub(crate) type ScopeId = Id<ScopeData>; pub(crate) type ScopeId = Id<ScopeData>;
@ -22,7 +23,7 @@ pub struct FnScopes {
#[derive(Debug, PartialEq, Eq)] #[derive(Debug, PartialEq, Eq)]
pub struct ScopeEntry { pub struct ScopeEntry {
name: SmolStr, name: Name,
ptr: LocalSyntaxPtr, ptr: LocalSyntaxPtr,
} }
@ -101,11 +102,12 @@ impl FnScopes {
pub fn resolve_local_name<'a>(&'a self, name_ref: ast::NameRef) -> Option<&'a ScopeEntry> { pub fn resolve_local_name<'a>(&'a self, name_ref: ast::NameRef) -> Option<&'a ScopeEntry> {
let mut shadowed = FxHashSet::default(); let mut shadowed = FxHashSet::default();
let name = name_ref.as_name();
let ret = self let ret = self
.scope_chain(name_ref.syntax()) .scope_chain(name_ref.syntax())
.flat_map(|scope| self.entries(scope).iter()) .flat_map(|scope| self.entries(scope).iter())
.filter(|entry| shadowed.insert(entry.name())) .filter(|entry| shadowed.insert(entry.name()))
.filter(|entry| entry.name() == &name_ref.text()) .filter(|entry| entry.name() == &name)
.nth(0); .nth(0);
ret ret
} }
@ -170,14 +172,14 @@ impl FnScopes {
impl ScopeEntry { impl ScopeEntry {
fn new(pat: ast::BindPat) -> Option<ScopeEntry> { fn new(pat: ast::BindPat) -> Option<ScopeEntry> {
let name = pat.name()?; let name = pat.name()?.as_name();
let res = ScopeEntry { let res = ScopeEntry {
name: name.text(), name,
ptr: LocalSyntaxPtr::new(pat.syntax()), ptr: LocalSyntaxPtr::new(pat.syntax()),
}; };
Some(res) Some(res)
} }
pub fn name(&self) -> &SmolStr { pub fn name(&self) -> &Name {
&self.name &self.name
} }
pub fn ptr(&self) -> LocalSyntaxPtr { pub fn ptr(&self) -> LocalSyntaxPtr {
@ -334,7 +336,7 @@ pub struct ReferenceDescriptor {
mod tests { mod tests {
use ra_editor::find_node_at_offset; use ra_editor::find_node_at_offset;
use ra_syntax::SourceFileNode; use ra_syntax::SourceFileNode;
use test_utils::extract_offset; use test_utils::{extract_offset, assert_eq_text};
use super::*; use super::*;
@ -355,9 +357,11 @@ mod tests {
let actual = scopes let actual = scopes
.scope_chain(marker.syntax()) .scope_chain(marker.syntax())
.flat_map(|scope| scopes.entries(scope)) .flat_map(|scope| scopes.entries(scope))
.map(|it| it.name()) .map(|it| it.name().to_string())
.collect::<Vec<_>>(); .collect::<Vec<_>>()
assert_eq!(actual.as_slice(), expected); .join("\n");
let expected = expected.join("\n");
assert_eq_text!(&actual, &expected);
} }
#[test] #[test]

View File

@ -1,7 +1,6 @@
use ra_syntax::SmolStr;
pub use ra_db::CrateId; 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 /// 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 /// crate's dependencies interact. Mostly, it should be just a proxy for the
@ -14,7 +13,7 @@ pub struct Crate {
#[derive(Debug)] #[derive(Debug)]
pub struct CrateDependency { pub struct CrateDependency {
pub krate: Crate, pub krate: Crate,
pub name: SmolStr, pub name: Name,
} }
impl Crate { impl Crate {
@ -27,7 +26,7 @@ impl Crate {
.dependencies(self.crate_id) .dependencies(self.crate_id)
.map(|dep| { .map(|dep| {
let krate = Crate::new(dep.crate_id()); let krate = Crate::new(dep.crate_id());
let name = dep.name.clone(); let name = dep.as_name();
CrateDependency { krate, name } CrateDependency { krate, name }
}) })
.collect() .collect()

View File

@ -22,6 +22,7 @@ mod path;
mod arena; mod arena;
pub mod source_binder; pub mod source_binder;
mod name;
mod krate; mod krate;
mod module; mod module;
mod function; mod function;
@ -37,10 +38,12 @@ use ra_db::{LocationIntener, SourceRootId, FileId, Cancelable};
use crate::{ use crate::{
db::HirDatabase, db::HirDatabase,
arena::{Arena, Id}, arena::{Arena, Id},
name::{AsName, KnownName},
}; };
pub use self::{ pub use self::{
path::{Path, PathKind}, path::{Path, PathKind},
name::Name,
krate::Crate, krate::Crate,
module::{Module, ModuleId, Problem, nameres::{ItemMap, PerNs, Namespace}, ModuleScope, Resolution}, module::{Module, ModuleId, Problem, nameres::{ItemMap, PerNs, Namespace}, ModuleScope, Resolution},
function::{Function, FnScopes}, function::{Function, FnScopes},

View File

@ -7,13 +7,14 @@ use log;
use ra_syntax::{ use ra_syntax::{
algo::generate, algo::generate,
ast::{self, AstNode, NameOwner}, ast::{self, AstNode, NameOwner},
SmolStr, SyntaxNode, SyntaxNode,
}; };
use ra_db::{SourceRootId, FileId, Cancelable}; use ra_db::{SourceRootId, FileId, Cancelable};
use relative_path::RelativePathBuf; use relative_path::RelativePathBuf;
use crate::{ use crate::{
DefKind, DefLoc, DefId, Path, PathKind, HirDatabase, SourceItemId, SourceFileItemId, Crate, DefKind, DefLoc, DefId, Path, PathKind, HirDatabase, SourceItemId, SourceFileItemId, Crate,
Name,
arena::{Arena, Id}, arena::{Arena, Id},
}; };
@ -84,7 +85,7 @@ impl Module {
} }
/// `name` is `None` for the crate's root module /// `name` is `None` for the crate's root module
pub fn name(&self) -> Option<SmolStr> { pub fn name(&self) -> Option<&Name> {
let link = self.module_id.parent_link(&self.tree)?; let link = self.module_id.parent_link(&self.tree)?;
Some(link.name(&self.tree)) Some(link.name(&self.tree))
} }
@ -100,7 +101,7 @@ impl Module {
} }
/// Finds a child module with the specified name. /// Finds a child module with the specified name.
pub fn child(&self, name: &str) -> Option<Module> { pub fn child(&self, name: &Name) -> Option<Module> {
let child_id = self.module_id.child(&self.tree, name)?; let child_id = self.module_id.child(&self.tree, name)?;
Some(Module { Some(Module {
module_id: child_id, module_id: child_id,
@ -230,15 +231,15 @@ impl ModuleId {
.last() .last()
.unwrap() .unwrap()
} }
fn child(self, tree: &ModuleTree, name: &str) -> Option<ModuleId> { fn child(self, tree: &ModuleTree, name: &Name) -> Option<ModuleId> {
let link = tree.mods[self] let link = tree.mods[self]
.children .children
.iter() .iter()
.map(|&it| &tree.links[it]) .map(|&it| &tree.links[it])
.find(|it| it.name == name)?; .find(|it| it.name == *name)?;
Some(*link.points_to.first()?) Some(*link.points_to.first()?)
} }
fn children<'a>(self, tree: &'a ModuleTree) -> impl Iterator<Item = (SmolStr, ModuleId)> + 'a { fn children<'a>(self, tree: &'a ModuleTree) -> impl Iterator<Item = (Name, ModuleId)> + 'a {
tree.mods[self].children.iter().filter_map(move |&it| { tree.mods[self].children.iter().filter_map(move |&it| {
let link = &tree.links[it]; let link = &tree.links[it];
let module = *link.points_to.first()?; let module = *link.points_to.first()?;
@ -263,8 +264,8 @@ impl LinkId {
fn owner(self, tree: &ModuleTree) -> ModuleId { fn owner(self, tree: &ModuleTree) -> ModuleId {
tree.links[self].owner tree.links[self].owner
} }
fn name(self, tree: &ModuleTree) -> SmolStr { fn name(self, tree: &ModuleTree) -> &Name {
tree.links[self].name.clone() &tree.links[self].name
} }
fn bind_source<'a>(self, tree: &ModuleTree, db: &impl HirDatabase) -> ast::ModuleNode { fn bind_source<'a>(self, tree: &ModuleTree, db: &impl HirDatabase) -> ast::ModuleNode {
let owner = self.owner(tree); let owner = self.owner(tree);
@ -328,7 +329,7 @@ impl ModuleSource {
#[derive(Hash, Debug, PartialEq, Eq)] #[derive(Hash, Debug, PartialEq, Eq)]
struct LinkData { struct LinkData {
owner: ModuleId, owner: ModuleId,
name: SmolStr, name: Name,
points_to: Vec<ModuleId>, points_to: Vec<ModuleId>,
problem: Option<Problem>, problem: Option<Problem>,
} }

View File

@ -1,16 +1,13 @@
use std::sync::Arc; use std::sync::Arc;
use ra_syntax::{ use ra_syntax::ast::{self, NameOwner};
ast::{self, NameOwner},
SmolStr,
};
use relative_path::RelativePathBuf; use relative_path::RelativePathBuf;
use rustc_hash::{FxHashMap, FxHashSet}; use rustc_hash::{FxHashMap, FxHashSet};
use arrayvec::ArrayVec; use arrayvec::ArrayVec;
use ra_db::{SourceRoot, SourceRootId, Cancelable, FileId}; use ra_db::{SourceRoot, SourceRootId, Cancelable, FileId};
use crate::{ use crate::{
HirDatabase, HirDatabase, Name, AsName,
}; };
use super::{ use super::{
@ -20,12 +17,12 @@ use super::{
#[derive(Clone, Hash, PartialEq, Eq, Debug)] #[derive(Clone, Hash, PartialEq, Eq, Debug)]
pub enum Submodule { pub enum Submodule {
Declaration(SmolStr), Declaration(Name),
Definition(SmolStr, ModuleSource), Definition(Name, ModuleSource),
} }
impl Submodule { impl Submodule {
fn name(&self) -> &SmolStr { fn name(&self) -> &Name {
match self { match self {
Submodule::Declaration(name) => name, Submodule::Declaration(name) => name,
Submodule::Definition(name, _) => name, Submodule::Definition(name, _) => name,
@ -35,14 +32,14 @@ impl Submodule {
pub(crate) fn modules<'a>( pub(crate) fn modules<'a>(
root: impl ast::ModuleItemOwner<'a>, root: impl ast::ModuleItemOwner<'a>,
) -> impl Iterator<Item = (SmolStr, ast::Module<'a>)> { ) -> impl Iterator<Item = (Name, ast::Module<'a>)> {
root.items() root.items()
.filter_map(|item| match item { .filter_map(|item| match item {
ast::ModuleItem::Module(m) => Some(m), ast::ModuleItem::Module(m) => Some(m),
_ => None, _ => None,
}) })
.filter_map(|module| { .filter_map(|module| {
let name = module.name()?.text(); let name = module.name()?.as_name();
Some((name, module)) Some((name, module))
}) })
} }
@ -155,7 +152,7 @@ fn build_subtree(
fn resolve_submodule( fn resolve_submodule(
db: &impl HirDatabase, db: &impl HirDatabase,
source: ModuleSource, source: ModuleSource,
name: &SmolStr, name: &Name,
) -> (Vec<FileId>, Option<Problem>) { ) -> (Vec<FileId>, Option<Problem>) {
// FIXME: handle submodules of inline modules properly // FIXME: handle submodules of inline modules properly
let file_id = source.file_id(); let file_id = source.file_id();

View File

@ -14,14 +14,12 @@
//! modifications (that is, typing inside a function shold not change IMIs), //! modifications (that is, typing inside a function shold not change IMIs),
//! such that the results of name resolution can be preserved unless the module //! such that the results of name resolution can be preserved unless the module
//! structure itself is modified. //! structure itself is modified.
use std::{ use std::sync::Arc;
sync::Arc,
};
use rustc_hash::FxHashMap; use rustc_hash::FxHashMap;
use ra_syntax::{ use ra_syntax::{
TextRange, TextRange,
SmolStr, SyntaxKind::{self, *}, SyntaxKind::{self, *},
ast::{self, AstNode} ast::{self, AstNode}
}; };
use ra_db::SourceRootId; use ra_db::SourceRootId;
@ -32,6 +30,7 @@ use crate::{
SourceItemId, SourceFileItemId, SourceFileItems, SourceItemId, SourceFileItemId, SourceFileItems,
Path, PathKind, Path, PathKind,
HirDatabase, Crate, HirDatabase, Crate,
Name, AsName,
module::{Module, ModuleId, ModuleTree}, module::{Module, ModuleId, ModuleTree},
}; };
@ -45,14 +44,14 @@ pub struct ItemMap {
#[derive(Debug, Default, PartialEq, Eq, Clone)] #[derive(Debug, Default, PartialEq, Eq, Clone)]
pub struct ModuleScope { pub struct ModuleScope {
items: FxHashMap<SmolStr, Resolution>, items: FxHashMap<Name, Resolution>,
} }
impl ModuleScope { impl ModuleScope {
pub fn entries<'a>(&'a self) -> impl Iterator<Item = (&'a SmolStr, &'a Resolution)> + 'a { pub fn entries<'a>(&'a self) -> impl Iterator<Item = (&'a Name, &'a Resolution)> + 'a {
self.items.iter() self.items.iter()
} }
pub fn get(&self, name: &SmolStr) -> Option<&Resolution> { pub fn get(&self, name: &Name) -> Option<&Resolution> {
self.items.get(name) self.items.get(name)
} }
} }
@ -72,7 +71,7 @@ pub struct InputModuleItems {
#[derive(Debug, PartialEq, Eq)] #[derive(Debug, PartialEq, Eq)]
struct ModuleItem { struct ModuleItem {
id: SourceFileItemId, id: SourceFileItemId,
name: SmolStr, name: Name,
kind: SyntaxKind, kind: SyntaxKind,
vis: Vis, vis: Vis,
} }
@ -260,7 +259,7 @@ impl InputModuleItems {
impl ModuleItem { impl ModuleItem {
fn new<'a>(file_items: &SourceFileItems, item: impl ast::NameOwner<'a>) -> Option<ModuleItem> { fn new<'a>(file_items: &SourceFileItems, item: impl ast::NameOwner<'a>) -> Option<ModuleItem> {
let name = item.name()?.text(); let name = item.name()?.as_name();
let kind = item.syntax().kind(); let kind = item.syntax().kind();
let vis = Vis::Other; let vis = Vis::Other;
let id = file_items.id_of_unchecked(item.syntax()); let id = file_items.id_of_unchecked(item.syntax());
@ -328,7 +327,11 @@ where
for dep in krate.dependencies(self.db) { for dep in krate.dependencies(self.db) {
if let Some(module) = dep.krate.root_module(self.db)? { if let Some(module) = dep.krate.root_module(self.db)? {
let def_id = module.def_id(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(()) Ok(())
} }
fn add_module_item(&self, module_items: &mut ModuleScope, name: SmolStr, def_id: PerNs<DefId>) { fn add_module_item(&self, module_items: &mut ModuleScope, name: Name, def_id: PerNs<DefId>) {
let resolution = Resolution { let resolution = Resolution {
def_id, def_id,
import: None, import: None,

View File

@ -2,8 +2,8 @@ use std::sync::Arc;
use salsa::Database; use salsa::Database;
use ra_db::{FilesDatabase, CrateGraph}; use ra_db::{FilesDatabase, CrateGraph};
use ra_syntax::SmolStr;
use relative_path::RelativePath; use relative_path::RelativePath;
use test_utils::assert_eq_text;
use crate::{ use crate::{
self as hir, self as hir,
@ -21,6 +21,35 @@ fn item_map(fixture: &str) -> (Arc<hir::ItemMap>, hir::ModuleId) {
(db.item_map(source_root).unwrap(), module_id) (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::<Vec<_>>();
lines.sort();
let actual = lines.join("\n");
let expected = expected
.trim()
.lines()
.map(|it| it.trim())
.collect::<Vec<_>>()
.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] #[test]
fn item_map_smoke_test() { fn item_map_smoke_test() {
let (item_map, module_id) = item_map( let (item_map, module_id) = item_map(
@ -38,13 +67,18 @@ fn item_map_smoke_test() {
pub struct Baz; pub struct Baz;
", ",
); );
let name = SmolStr::from("Baz"); check_module_item_map(
let resolution = &item_map.per_module[&module_id].items[&name]; &item_map,
assert!(resolution.def_id.take_types().is_some()); module_id,
"
Baz: t v
foo: t
",
);
} }
#[test] #[test]
fn test_self() { fn item_map_using_self() {
let (item_map, module_id) = item_map( let (item_map, module_id) = item_map(
" "
//- /lib.rs //- /lib.rs
@ -57,9 +91,14 @@ fn test_self() {
pub struct Baz; pub struct Baz;
", ",
); );
let name = SmolStr::from("Baz"); check_module_item_map(
let resolution = &item_map.per_module[&module_id].items[&name]; &item_map,
assert!(resolution.def_id.take_types().is_some()); module_id,
"
Baz: t v
foo: t
",
);
} }
#[test] #[test]
@ -90,9 +129,14 @@ fn item_map_across_crates() {
let module_id = module.module_id; let module_id = module.module_id;
let item_map = db.item_map(source_root).unwrap(); let item_map = db.item_map(source_root).unwrap();
let name = SmolStr::from("Baz"); check_module_item_map(
let resolution = &item_map.per_module[&module_id].items[&name]; &item_map,
assert!(resolution.def_id.take_types().is_some()); module_id,
"
Baz: t v
test_crate: t
",
);
} }
#[test] #[test]

97
crates/ra_hir/src/name.rs Normal file
View File

@ -0,0 +1,97 @@
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(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 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<KnownName> {
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)
}
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())
}
}
// 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,
}

View File

@ -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)] #[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct Path { pub struct Path {
pub kind: PathKind, pub kind: PathKind,
pub segments: Vec<SmolStr>, pub segments: Vec<Name>,
} }
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
@ -29,7 +31,7 @@ impl Path {
loop { loop {
let segment = path.segment()?; let segment = path.segment()?;
match segment.kind()? { match segment.kind()? {
ast::PathSegmentKind::Name(name) => segments.push(name.text()), ast::PathSegmentKind::Name(name) => segments.push(name.as_name()),
ast::PathSegmentKind::CrateKw => { ast::PathSegmentKind::CrateKw => {
kind = PathKind::Crate; kind = PathKind::Crate;
break; break;
@ -67,6 +69,14 @@ impl Path {
pub fn is_ident(&self) -> bool { pub fn is_ident(&self) -> bool {
self.kind == PathKind::Plain && self.segments.len() == 1 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( fn expand_use_tree(
@ -130,7 +140,7 @@ fn convert_path(prefix: Option<Path>, path: ast::Path) -> Option<Path> {
kind: PathKind::Plain, kind: PathKind::Plain,
segments: Vec::with_capacity(1), segments: Vec::with_capacity(1),
}); });
res.segments.push(name.text()); res.segments.push(name.as_name());
res res
} }
ast::PathSegmentKind::CrateKw => { ast::PathSegmentKind::CrateKw => {

View File

@ -11,7 +11,7 @@ use ra_syntax::{
use ra_db::{SourceRootId, FileId, Cancelable,}; use ra_db::{SourceRootId, FileId, Cancelable,};
use crate::{ use crate::{
SourceFileItems, SourceItemId, DefKind, Function, DefId, SourceFileItems, SourceItemId, DefKind, Function, DefId, Name, AsName,
db::HirDatabase, db::HirDatabase,
function::{FnScopes, FnId}, function::{FnScopes, FnId},
module::{ module::{
@ -130,14 +130,14 @@ pub(crate) fn submodules(
pub(crate) fn modules<'a>( pub(crate) fn modules<'a>(
root: impl ast::ModuleItemOwner<'a>, root: impl ast::ModuleItemOwner<'a>,
) -> impl Iterator<Item = (SmolStr, ast::Module<'a>)> { ) -> impl Iterator<Item = (Name, ast::Module<'a>)> {
root.items() root.items()
.filter_map(|item| match item { .filter_map(|item| match item {
ast::ModuleItem::Module(m) => Some(m), ast::ModuleItem::Module(m) => Some(m),
_ => None, _ => None,
}) })
.filter_map(|module| { .filter_map(|module| {
let name = module.name()?.text(); let name = module.name()?.as_name();
Some((name, module)) Some((name, module))
}) })
} }

View File

@ -8,14 +8,14 @@
use ra_db::{FileId, FilePosition, Cancelable}; use ra_db::{FileId, FilePosition, Cancelable};
use ra_editor::find_node_at_offset; use ra_editor::find_node_at_offset;
use ra_syntax::{ use ra_syntax::{
ast::{self, AstNode}, ast::{self, AstNode, NameOwner},
SyntaxNodeRef, SyntaxNodeRef,
}; };
use crate::{ use crate::{
HirDatabase, Module, Function, SourceItemId, HirDatabase, Module, Function, SourceItemId,
module::ModuleSource, module::ModuleSource,
DefKind, DefLoc DefKind, DefLoc, AsName,
}; };
/// Locates the module by `FileId`. Picks topmost module in the file. /// 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) 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<Option<Module>> {
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. /// Locates the module by position in the source code.
pub fn module_from_position( pub fn module_from_position(
db: &impl HirDatabase, db: &impl HirDatabase,

View File

@ -95,7 +95,7 @@ pub enum Ty {
Tuple(Vec<Ty>), Tuple(Vec<Ty>),
// The projection of an associated type. For example, // The projection of an associated type. For example,
// `<T as Trait<..>>::N`. // `<T as Trait<..>>::N`.pub
// Projection(ProjectionTy), // Projection(ProjectionTy),
// Opaque (`impl Trait`) type found in a return type. // Opaque (`impl Trait`) type found in a return type.
@ -179,13 +179,12 @@ impl Ty {
module: &Module, module: &Module,
path: &Path, path: &Path,
) -> Cancelable<Self> { ) -> Cancelable<Self> {
if path.is_ident() { if let Some(name) = path.as_ident() {
let name = &path.segments[0]; if let Some(int_ty) = primitive::IntTy::from_name(name) {
if let Some(int_ty) = primitive::IntTy::from_string(&name) {
return Ok(Ty::Int(int_ty)); 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)); 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)); return Ok(Ty::Float(float_ty));
} }
} }

View File

@ -1,5 +1,7 @@
use std::fmt; use std::fmt;
use crate::{Name, KnownName};
#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Copy)] #[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Copy)]
pub enum IntTy { pub enum IntTy {
Isize, Isize,
@ -34,14 +36,14 @@ impl IntTy {
} }
} }
pub fn from_string(s: &str) -> Option<IntTy> { pub fn from_name(name: &Name) -> Option<IntTy> {
match s { match name.as_known_name()? {
"isize" => Some(IntTy::Isize), KnownName::Isize => Some(IntTy::Isize),
"i8" => Some(IntTy::I8), KnownName::I8 => Some(IntTy::I8),
"i16" => Some(IntTy::I16), KnownName::I16 => Some(IntTy::I16),
"i32" => Some(IntTy::I32), KnownName::I32 => Some(IntTy::I32),
"i64" => Some(IntTy::I64), KnownName::I64 => Some(IntTy::I64),
"i128" => Some(IntTy::I128), KnownName::I128 => Some(IntTy::I128),
_ => None, _ => None,
} }
} }
@ -69,14 +71,14 @@ impl UintTy {
} }
} }
pub fn from_string(s: &str) -> Option<UintTy> { pub fn from_name(name: &Name) -> Option<UintTy> {
match s { match name.as_known_name()? {
"usize" => Some(UintTy::Usize), KnownName::Usize => Some(UintTy::Usize),
"u8" => Some(UintTy::U8), KnownName::U8 => Some(UintTy::U8),
"u16" => Some(UintTy::U16), KnownName::U16 => Some(UintTy::U16),
"u32" => Some(UintTy::U32), KnownName::U32 => Some(UintTy::U32),
"u64" => Some(UintTy::U64), KnownName::U64 => Some(UintTy::U64),
"u128" => Some(UintTy::U128), KnownName::U128 => Some(UintTy::U128),
_ => None, _ => None,
} }
} }
@ -120,10 +122,10 @@ impl FloatTy {
} }
} }
pub fn from_string(s: &str) -> Option<FloatTy> { pub fn from_name(name: &Name) -> Option<FloatTy> {
match s { match name.as_known_name()? {
"f32" => Some(FloatTy::F32), KnownName::F32 => Some(FloatTy::F32),
"f64" => Some(FloatTy::F64), KnownName::F64 => Some(FloatTy::F64),
_ => None, _ => None,
} }
} }