move more stuff to ids
This commit is contained in:
parent
37ed2f35ba
commit
42cc77703b
@ -1,9 +1,10 @@
|
||||
use std::sync::Arc;
|
||||
|
||||
use ra_db::Cancelable;
|
||||
use ra_syntax::ast::{self, NameOwner, StructFlavor};
|
||||
|
||||
use crate::{
|
||||
DefId, Cancelable, Name, AsName,
|
||||
DefId, Name, AsName,
|
||||
db::HirDatabase,
|
||||
type_ref::TypeRef,
|
||||
};
|
||||
|
@ -1,6 +1,10 @@
|
||||
use crate::{FileId, MacroCallId, HirDatabase};
|
||||
use ra_db::{SourceRootId, LocationIntener, Cancelable, FileId};
|
||||
use ra_syntax::{SourceFileNode, SyntaxKind, SyntaxNode, SyntaxNodeRef, SourceFile, AstNode, ast};
|
||||
|
||||
use ra_syntax::SourceFileNode;
|
||||
use crate::{
|
||||
MacroCallId, HirDatabase, PerNs, ModuleId, Module, Def, Function, Struct, Enum,
|
||||
arena::{Arena, Id},
|
||||
};
|
||||
|
||||
/// hir makes a heavy use of ids: integer (u32) handlers to various things. You
|
||||
/// can think of id as a pointer (but without a lifetime) or a file descriptor
|
||||
@ -72,3 +76,170 @@ impl From<MacroCallId> for HirFileId {
|
||||
HirFileId(HirFileIdRepr::Macro(macro_call_id))
|
||||
}
|
||||
}
|
||||
|
||||
/// Def's are a core concept of hir. A `Def` is an Item (function, module, etc)
|
||||
/// in a specific module.
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
||||
pub struct DefId(u32);
|
||||
ra_db::impl_numeric_id!(DefId);
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
|
||||
pub struct DefLoc {
|
||||
pub(crate) kind: DefKind,
|
||||
pub(crate) source_root_id: SourceRootId,
|
||||
pub(crate) module_id: ModuleId,
|
||||
pub(crate) source_item_id: SourceItemId,
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
|
||||
pub(crate) enum DefKind {
|
||||
Module,
|
||||
Function,
|
||||
Struct,
|
||||
Enum,
|
||||
Item,
|
||||
|
||||
StructCtor,
|
||||
}
|
||||
|
||||
impl DefId {
|
||||
pub(crate) fn loc(self, db: &impl AsRef<LocationIntener<DefLoc, DefId>>) -> DefLoc {
|
||||
db.as_ref().id2loc(self)
|
||||
}
|
||||
|
||||
pub fn resolve(self, db: &impl HirDatabase) -> Cancelable<Def> {
|
||||
let loc = self.loc(db);
|
||||
let res = match loc.kind {
|
||||
DefKind::Module => {
|
||||
let module = Module::new(db, loc.source_root_id, loc.module_id)?;
|
||||
Def::Module(module)
|
||||
}
|
||||
DefKind::Function => {
|
||||
let function = Function::new(self);
|
||||
Def::Function(function)
|
||||
}
|
||||
DefKind::Struct => {
|
||||
let struct_def = Struct::new(self);
|
||||
Def::Struct(struct_def)
|
||||
}
|
||||
DefKind::Enum => {
|
||||
let enum_def = Enum::new(self);
|
||||
Def::Enum(enum_def)
|
||||
}
|
||||
DefKind::StructCtor => Def::Item,
|
||||
DefKind::Item => Def::Item,
|
||||
};
|
||||
Ok(res)
|
||||
}
|
||||
|
||||
/// For a module, returns that module; for any other def, returns the containing module.
|
||||
pub fn module(self, db: &impl HirDatabase) -> Cancelable<Module> {
|
||||
let loc = self.loc(db);
|
||||
Module::new(db, loc.source_root_id, loc.module_id)
|
||||
}
|
||||
}
|
||||
|
||||
impl DefLoc {
|
||||
pub(crate) fn id(&self, db: &impl AsRef<LocationIntener<DefLoc, DefId>>) -> DefId {
|
||||
db.as_ref().loc2id(&self)
|
||||
}
|
||||
}
|
||||
|
||||
impl DefKind {
|
||||
pub(crate) fn for_syntax_kind(kind: SyntaxKind) -> PerNs<DefKind> {
|
||||
match kind {
|
||||
SyntaxKind::FN_DEF => PerNs::values(DefKind::Function),
|
||||
SyntaxKind::MODULE => PerNs::types(DefKind::Module),
|
||||
SyntaxKind::STRUCT_DEF => PerNs::both(DefKind::Struct, DefKind::StructCtor),
|
||||
SyntaxKind::ENUM_DEF => PerNs::types(DefKind::Enum),
|
||||
// These define items, but don't have their own DefKinds yet:
|
||||
SyntaxKind::TRAIT_DEF => PerNs::types(DefKind::Item),
|
||||
SyntaxKind::TYPE_DEF => PerNs::types(DefKind::Item),
|
||||
SyntaxKind::CONST_DEF => PerNs::values(DefKind::Item),
|
||||
SyntaxKind::STATIC_DEF => PerNs::values(DefKind::Item),
|
||||
_ => PerNs::none(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Identifier of item within a specific file. This is stable over reparses, so
|
||||
/// it's OK to use it as a salsa key/value.
|
||||
pub(crate) type SourceFileItemId = Id<SyntaxNode>;
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
||||
pub struct SourceItemId {
|
||||
pub(crate) file_id: HirFileId,
|
||||
/// None for the whole file.
|
||||
pub(crate) item_id: Option<SourceFileItemId>,
|
||||
}
|
||||
|
||||
/// Maps item's `SyntaxNode`s to `SourceFileItemId` and back.
|
||||
#[derive(Debug, PartialEq, Eq)]
|
||||
pub struct SourceFileItems {
|
||||
file_id: HirFileId,
|
||||
arena: Arena<SyntaxNode>,
|
||||
}
|
||||
|
||||
impl SourceFileItems {
|
||||
pub(crate) fn new(file_id: HirFileId, source_file: SourceFile) -> SourceFileItems {
|
||||
let mut res = SourceFileItems {
|
||||
file_id,
|
||||
arena: Arena::default(),
|
||||
};
|
||||
res.init(source_file);
|
||||
res
|
||||
}
|
||||
|
||||
fn init(&mut self, source_file: SourceFile) {
|
||||
source_file.syntax().descendants().for_each(|it| {
|
||||
if let Some(module_item) = ast::ModuleItem::cast(it) {
|
||||
self.alloc(module_item.syntax().owned());
|
||||
} else if let Some(macro_call) = ast::MacroCall::cast(it) {
|
||||
self.alloc(macro_call.syntax().owned());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
fn alloc(&mut self, item: SyntaxNode) -> SourceFileItemId {
|
||||
self.arena.alloc(item)
|
||||
}
|
||||
pub(crate) fn id_of(&self, file_id: HirFileId, item: SyntaxNodeRef) -> SourceFileItemId {
|
||||
assert_eq!(
|
||||
self.file_id, file_id,
|
||||
"SourceFileItems: wrong file, expected {:?}, got {:?}",
|
||||
self.file_id, file_id
|
||||
);
|
||||
self.id_of_unchecked(item)
|
||||
}
|
||||
pub(crate) fn id_of_unchecked(&self, item: SyntaxNodeRef) -> SourceFileItemId {
|
||||
if let Some((id, _)) = self.arena.iter().find(|(_id, i)| i.borrowed() == item) {
|
||||
return id;
|
||||
}
|
||||
// This should not happen. Let's try to give a sensible diagnostics.
|
||||
if let Some((id, i)) = self.arena.iter().find(|(_id, i)| i.range() == item.range()) {
|
||||
// FIXME(#288): whyyy are we getting here?
|
||||
log::error!(
|
||||
"unequal syntax nodes with the same range:\n{:?}\n{:?}",
|
||||
item,
|
||||
i
|
||||
);
|
||||
return id;
|
||||
}
|
||||
panic!(
|
||||
"Can't find {:?} in SourceFileItems:\n{:?}",
|
||||
item,
|
||||
self.arena.iter().map(|(_id, i)| i).collect::<Vec<_>>(),
|
||||
);
|
||||
}
|
||||
pub fn id_of_source_file(&self) -> SourceFileItemId {
|
||||
let (id, _syntax) = self.arena.iter().next().unwrap();
|
||||
id
|
||||
}
|
||||
}
|
||||
|
||||
impl std::ops::Index<SourceFileItemId> for SourceFileItems {
|
||||
type Output = SyntaxNode;
|
||||
fn index(&self, idx: SourceFileItemId) -> &SyntaxNode {
|
||||
&self.arena[idx]
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
pub use ra_db::CrateId;
|
||||
pub use ra_db::{CrateId, Cancelable};
|
||||
|
||||
use crate::{HirDatabase, Module, Cancelable, Name, AsName, HirFileId};
|
||||
use crate::{HirDatabase, Module, Name, AsName, HirFileId};
|
||||
|
||||
/// 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
|
||||
|
@ -32,22 +32,17 @@ mod adt;
|
||||
mod type_ref;
|
||||
mod ty;
|
||||
|
||||
use std::ops::Index;
|
||||
|
||||
use ra_syntax::{SyntaxNodeRef, SyntaxNode, SyntaxKind, SourceFile, AstNode, ast};
|
||||
use ra_db::{LocationIntener, SourceRootId, FileId, Cancelable};
|
||||
|
||||
use crate::{
|
||||
db::HirDatabase,
|
||||
arena::{Arena, Id},
|
||||
name::{AsName, KnownName},
|
||||
ids::{DefKind, SourceItemId, SourceFileItemId, SourceFileItems},
|
||||
};
|
||||
|
||||
pub use self::{
|
||||
path::{Path, PathKind},
|
||||
name::Name,
|
||||
krate::Crate,
|
||||
ids::HirFileId,
|
||||
ids::{HirFileId, DefId, DefLoc},
|
||||
macros::{MacroDef, MacroInput, MacroExpansion, MacroCallId, MacroCallLoc},
|
||||
module::{Module, ModuleId, Problem, nameres::{ItemMap, PerNs, Namespace}, ModuleScope, Resolution},
|
||||
function::{Function, FnScopes},
|
||||
@ -57,60 +52,6 @@ pub use self::{
|
||||
|
||||
pub use self::function::FnSignatureInfo;
|
||||
|
||||
/// Def's are a core concept of hir. A `Def` is an Item (function, module, etc)
|
||||
/// in a specific module.
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
||||
pub struct DefId(u32);
|
||||
ra_db::impl_numeric_id!(DefId);
|
||||
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
|
||||
pub(crate) enum DefKind {
|
||||
Module,
|
||||
Function,
|
||||
Struct,
|
||||
Enum,
|
||||
Item,
|
||||
|
||||
StructCtor,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
|
||||
pub struct DefLoc {
|
||||
pub(crate) kind: DefKind,
|
||||
source_root_id: SourceRootId,
|
||||
module_id: ModuleId,
|
||||
source_item_id: SourceItemId,
|
||||
}
|
||||
|
||||
impl DefKind {
|
||||
pub(crate) fn for_syntax_kind(kind: SyntaxKind) -> PerNs<DefKind> {
|
||||
match kind {
|
||||
SyntaxKind::FN_DEF => PerNs::values(DefKind::Function),
|
||||
SyntaxKind::MODULE => PerNs::types(DefKind::Module),
|
||||
SyntaxKind::STRUCT_DEF => PerNs::both(DefKind::Struct, DefKind::StructCtor),
|
||||
SyntaxKind::ENUM_DEF => PerNs::types(DefKind::Enum),
|
||||
// These define items, but don't have their own DefKinds yet:
|
||||
SyntaxKind::TRAIT_DEF => PerNs::types(DefKind::Item),
|
||||
SyntaxKind::TYPE_DEF => PerNs::types(DefKind::Item),
|
||||
SyntaxKind::CONST_DEF => PerNs::values(DefKind::Item),
|
||||
SyntaxKind::STATIC_DEF => PerNs::values(DefKind::Item),
|
||||
_ => PerNs::none(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl DefId {
|
||||
pub(crate) fn loc(self, db: &impl AsRef<LocationIntener<DefLoc, DefId>>) -> DefLoc {
|
||||
db.as_ref().id2loc(self)
|
||||
}
|
||||
}
|
||||
|
||||
impl DefLoc {
|
||||
pub(crate) fn id(&self, db: &impl AsRef<LocationIntener<DefLoc, DefId>>) -> DefId {
|
||||
db.as_ref().loc2id(&self)
|
||||
}
|
||||
}
|
||||
|
||||
pub enum Def {
|
||||
Module(Module),
|
||||
Function(Function),
|
||||
@ -118,118 +59,3 @@ pub enum Def {
|
||||
Enum(Enum),
|
||||
Item,
|
||||
}
|
||||
|
||||
impl DefId {
|
||||
pub fn resolve(self, db: &impl HirDatabase) -> Cancelable<Def> {
|
||||
let loc = self.loc(db);
|
||||
let res = match loc.kind {
|
||||
DefKind::Module => {
|
||||
let module = Module::new(db, loc.source_root_id, loc.module_id)?;
|
||||
Def::Module(module)
|
||||
}
|
||||
DefKind::Function => {
|
||||
let function = Function::new(self);
|
||||
Def::Function(function)
|
||||
}
|
||||
DefKind::Struct => {
|
||||
let struct_def = Struct::new(self);
|
||||
Def::Struct(struct_def)
|
||||
}
|
||||
DefKind::Enum => {
|
||||
let enum_def = Enum::new(self);
|
||||
Def::Enum(enum_def)
|
||||
}
|
||||
DefKind::StructCtor => Def::Item,
|
||||
DefKind::Item => Def::Item,
|
||||
};
|
||||
Ok(res)
|
||||
}
|
||||
|
||||
/// For a module, returns that module; for any other def, returns the containing module.
|
||||
pub fn module(self, db: &impl HirDatabase) -> Cancelable<Module> {
|
||||
let loc = self.loc(db);
|
||||
Module::new(db, loc.source_root_id, loc.module_id)
|
||||
}
|
||||
}
|
||||
|
||||
/// Identifier of item within a specific file. This is stable over reparses, so
|
||||
/// it's OK to use it as a salsa key/value.
|
||||
pub(crate) type SourceFileItemId = Id<SyntaxNode>;
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
||||
pub struct SourceItemId {
|
||||
file_id: HirFileId,
|
||||
/// None for the whole file.
|
||||
item_id: Option<SourceFileItemId>,
|
||||
}
|
||||
|
||||
/// Maps item's `SyntaxNode`s to `SourceFileItemId` and back.
|
||||
#[derive(Debug, PartialEq, Eq)]
|
||||
pub struct SourceFileItems {
|
||||
file_id: HirFileId,
|
||||
arena: Arena<SyntaxNode>,
|
||||
}
|
||||
|
||||
impl SourceFileItems {
|
||||
fn new(file_id: HirFileId, source_file: SourceFile) -> SourceFileItems {
|
||||
let mut res = SourceFileItems {
|
||||
file_id,
|
||||
arena: Arena::default(),
|
||||
};
|
||||
res.init(source_file);
|
||||
res
|
||||
}
|
||||
|
||||
fn init(&mut self, source_file: SourceFile) {
|
||||
source_file.syntax().descendants().for_each(|it| {
|
||||
if let Some(module_item) = ast::ModuleItem::cast(it) {
|
||||
self.alloc(module_item.syntax().owned());
|
||||
} else if let Some(macro_call) = ast::MacroCall::cast(it) {
|
||||
self.alloc(macro_call.syntax().owned());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
fn alloc(&mut self, item: SyntaxNode) -> SourceFileItemId {
|
||||
self.arena.alloc(item)
|
||||
}
|
||||
pub fn id_of(&self, file_id: HirFileId, item: SyntaxNodeRef) -> SourceFileItemId {
|
||||
assert_eq!(
|
||||
self.file_id, file_id,
|
||||
"SourceFileItems: wrong file, expected {:?}, got {:?}",
|
||||
self.file_id, file_id
|
||||
);
|
||||
self.id_of_unchecked(item)
|
||||
}
|
||||
fn id_of_unchecked(&self, item: SyntaxNodeRef) -> SourceFileItemId {
|
||||
if let Some((id, _)) = self.arena.iter().find(|(_id, i)| i.borrowed() == item) {
|
||||
return id;
|
||||
}
|
||||
// This should not happen. Let's try to give a sensible diagnostics.
|
||||
if let Some((id, i)) = self.arena.iter().find(|(_id, i)| i.range() == item.range()) {
|
||||
// FIXME(#288): whyyy are we getting here?
|
||||
log::error!(
|
||||
"unequal syntax nodes with the same range:\n{:?}\n{:?}",
|
||||
item,
|
||||
i
|
||||
);
|
||||
return id;
|
||||
}
|
||||
panic!(
|
||||
"Can't find {:?} in SourceFileItems:\n{:?}",
|
||||
item,
|
||||
self.arena.iter().map(|(_id, i)| i).collect::<Vec<_>>(),
|
||||
);
|
||||
}
|
||||
pub fn id_of_source_file(&self) -> SourceFileItemId {
|
||||
let (id, _syntax) = self.arena.iter().next().unwrap();
|
||||
id
|
||||
}
|
||||
}
|
||||
|
||||
impl Index<SourceFileItemId> for SourceFileItems {
|
||||
type Output = SyntaxNode;
|
||||
fn index(&self, idx: SourceFileItemId) -> &SyntaxNode {
|
||||
&self.arena[idx]
|
||||
}
|
||||
}
|
||||
|
@ -1,12 +1,12 @@
|
||||
use std::sync::Arc;
|
||||
|
||||
use ra_db::{LocalSyntaxPtr, LocationIntener};
|
||||
use ra_db::{SourceRootId, LocalSyntaxPtr, LocationIntener};
|
||||
use ra_syntax::{
|
||||
TextRange, TextUnit, SourceFileNode, AstNode, SyntaxNode,
|
||||
ast::{self, NameOwner},
|
||||
};
|
||||
|
||||
use crate::{SourceRootId, module::ModuleId, SourceItemId, HirDatabase};
|
||||
use crate::{module::ModuleId, SourceItemId, HirDatabase};
|
||||
|
||||
/// Def's are a core concept of hir. A `Def` is an Item (function, module, etc)
|
||||
/// in a specific module.
|
||||
|
@ -22,10 +22,10 @@ use ra_syntax::{
|
||||
SyntaxKind::{self, *},
|
||||
ast::{self, AstNode}
|
||||
};
|
||||
use ra_db::SourceRootId;
|
||||
use ra_db::{SourceRootId, Cancelable, FileId};
|
||||
|
||||
use crate::{
|
||||
Cancelable, HirFileId, FileId,
|
||||
HirFileId,
|
||||
DefId, DefLoc, DefKind,
|
||||
SourceItemId, SourceFileItemId, SourceFileItems,
|
||||
Path, PathKind,
|
||||
|
Loading…
x
Reference in New Issue
Block a user