introduce hir::Name
This commit is contained in:
parent
3b820bcca3
commit
d963042ca9
@ -14,7 +14,7 @@
|
||||
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
|
||||
},
|
||||
|
@ -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 @@ pub fn dependencies(&self, db: &impl HirDatabase) -> Vec<CrateDependency> {
|
||||
.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()
|
||||
|
@ -22,6 +22,7 @@ macro_rules! ctry {
|
||||
mod arena;
|
||||
pub mod source_binder;
|
||||
|
||||
mod name;
|
||||
mod krate;
|
||||
mod module;
|
||||
mod function;
|
||||
@ -37,10 +38,12 @@ macro_rules! ctry {
|
||||
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},
|
||||
|
@ -7,13 +7,14 @@
|
||||
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 @@ pub fn crate_root(&self) -> 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)?;
|
||||
Some(link.name(&self.tree))
|
||||
}
|
||||
@ -100,7 +101,7 @@ pub fn def_id(&self, db: &impl HirDatabase) -> DefId {
|
||||
}
|
||||
|
||||
/// 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)?;
|
||||
Some(Module {
|
||||
module_id: child_id,
|
||||
@ -230,15 +231,15 @@ fn crate_root(self, tree: &ModuleTree) -> ModuleId {
|
||||
.last()
|
||||
.unwrap()
|
||||
}
|
||||
fn child(self, tree: &ModuleTree, name: &str) -> Option<ModuleId> {
|
||||
fn child(self, tree: &ModuleTree, name: &Name) -> Option<ModuleId> {
|
||||
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<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| {
|
||||
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 @@ pub(crate) fn resolve(self, db: &impl HirDatabase) -> ModuleSourceNode {
|
||||
#[derive(Hash, Debug, PartialEq, Eq)]
|
||||
struct LinkData {
|
||||
owner: ModuleId,
|
||||
name: SmolStr,
|
||||
name: Name,
|
||||
points_to: Vec<ModuleId>,
|
||||
problem: Option<Problem>,
|
||||
}
|
||||
|
@ -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 @@
|
||||
|
||||
#[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 @@ fn name(&self) -> &SmolStr {
|
||||
|
||||
pub(crate) fn modules<'a>(
|
||||
root: impl ast::ModuleItemOwner<'a>,
|
||||
) -> impl Iterator<Item = (SmolStr, ast::Module<'a>)> {
|
||||
) -> impl Iterator<Item = (Name, ast::Module<'a>)> {
|
||||
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<FileId>, Option<Problem>) {
|
||||
// FIXME: handle submodules of inline modules properly
|
||||
let file_id = source.file_id();
|
||||
|
@ -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 @@
|
||||
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<SmolStr, Resolution>,
|
||||
items: FxHashMap<Name, Resolution>,
|
||||
}
|
||||
|
||||
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()
|
||||
}
|
||||
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 @@ fn add_use_item(&mut self, file_items: &SourceFileItems, item: ast::UseItem) {
|
||||
|
||||
impl 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 vis = Vis::Other;
|
||||
let id = file_items.id_of_unchecked(item.syntax());
|
||||
@ -328,7 +327,11 @@ fn populate_module(&mut self, module_id: ModuleId, input: &InputModuleItems) ->
|
||||
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 @@ fn populate_module(&mut self, module_id: ModuleId, input: &InputModuleItems) ->
|
||||
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 {
|
||||
def_id,
|
||||
import: None,
|
||||
|
@ -9,6 +9,7 @@
|
||||
self as hir,
|
||||
db::HirDatabase,
|
||||
mock::MockDatabase,
|
||||
Name,
|
||||
};
|
||||
|
||||
fn item_map(fixture: &str) -> (Arc<hir::ItemMap>, 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());
|
||||
}
|
||||
|
56
crates/ra_hir/src/name.rs
Normal file
56
crates/ra_hir/src/name.rs
Normal file
@ -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())
|
||||
}
|
||||
}
|
@ -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<SmolStr>,
|
||||
pub segments: Vec<Name>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
||||
@ -29,7 +31,7 @@ pub fn from_ast(mut path: ast::Path) -> Option<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 @@ fn qualifier(path: ast::Path) -> Option<ast::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>, path: ast::Path) -> Option<Path> {
|
||||
kind: PathKind::Plain,
|
||||
segments: Vec::with_capacity(1),
|
||||
});
|
||||
res.segments.push(name.text());
|
||||
res.segments.push(name.as_name());
|
||||
res
|
||||
}
|
||||
ast::PathSegmentKind::CrateKw => {
|
||||
|
@ -11,7 +11,7 @@
|
||||
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 @@ fn collect_submodules<'a>(
|
||||
|
||||
pub(crate) fn modules<'a>(
|
||||
root: impl ast::ModuleItemOwner<'a>,
|
||||
) -> impl Iterator<Item = (SmolStr, ast::Module<'a>)> {
|
||||
) -> impl Iterator<Item = (Name, ast::Module<'a>)> {
|
||||
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))
|
||||
})
|
||||
}
|
||||
|
@ -179,13 +179,13 @@ pub(crate) fn from_hir_path(
|
||||
module: &Module,
|
||||
path: &Path,
|
||||
) -> Cancelable<Self> {
|
||||
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));
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user