mirror of
https://github.com/rust-lang/rust.git
synced 2024-12-02 03:33:59 +00:00
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 <aleksey.kladov@gmail.com>
This commit is contained in:
commit
efb63a7666
@ -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));
|
||||||
}
|
|
||||||
_ => (),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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
|
||||||
},
|
},
|
||||||
|
@ -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]
|
||||||
|
@ -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()
|
||||||
|
@ -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},
|
||||||
|
@ -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>,
|
||||||
}
|
}
|
||||||
|
@ -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();
|
||||||
|
@ -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,
|
||||||
|
@ -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
97
crates/ra_hir/src/name.rs
Normal 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,
|
||||||
|
}
|
@ -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 => {
|
||||||
|
@ -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))
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -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,
|
||||||
|
@ -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));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user