From 42cc77703b041436b2507816cb394ad6fd3d07e0 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Wed, 2 Jan 2019 00:30:00 +0300 Subject: move more stuff to ids --- crates/ra_hir/src/adt.rs | 3 +- crates/ra_hir/src/ids.rs | 175 ++++++++++++++++++++++++++++++++++- crates/ra_hir/src/krate.rs | 4 +- crates/ra_hir/src/lib.rs | 178 +----------------------------------- crates/ra_hir/src/macros.rs | 4 +- crates/ra_hir/src/module/nameres.rs | 4 +- 6 files changed, 183 insertions(+), 185 deletions(-) (limited to 'crates/ra_hir') diff --git a/crates/ra_hir/src/adt.rs b/crates/ra_hir/src/adt.rs index e839a5a90..c6463235c 100644 --- a/crates/ra_hir/src/adt.rs +++ b/crates/ra_hir/src/adt.rs @@ -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, }; diff --git a/crates/ra_hir/src/ids.rs b/crates/ra_hir/src/ids.rs index 3eba35a24..cd32033f3 100644 --- a/crates/ra_hir/src/ids.rs +++ b/crates/ra_hir/src/ids.rs @@ -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 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>) -> DefLoc { + db.as_ref().id2loc(self) + } + + pub fn resolve(self, db: &impl HirDatabase) -> Cancelable { + 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 { + 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>) -> DefId { + db.as_ref().loc2id(&self) + } +} + +impl DefKind { + pub(crate) fn for_syntax_kind(kind: SyntaxKind) -> PerNs { + 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; + +#[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, +} + +/// Maps item's `SyntaxNode`s to `SourceFileItemId` and back. +#[derive(Debug, PartialEq, Eq)] +pub struct SourceFileItems { + file_id: HirFileId, + arena: Arena, +} + +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::>(), + ); + } + pub fn id_of_source_file(&self) -> SourceFileItemId { + let (id, _syntax) = self.arena.iter().next().unwrap(); + id + } +} + +impl std::ops::Index for SourceFileItems { + type Output = SyntaxNode; + fn index(&self, idx: SourceFileItemId) -> &SyntaxNode { + &self.arena[idx] + } +} diff --git a/crates/ra_hir/src/krate.rs b/crates/ra_hir/src/krate.rs index 4d4f59949..a0821d15d 100644 --- a/crates/ra_hir/src/krate.rs +++ b/crates/ra_hir/src/krate.rs @@ -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 diff --git a/crates/ra_hir/src/lib.rs b/crates/ra_hir/src/lib.rs index c1386601d..5e939b79e 100644 --- a/crates/ra_hir/src/lib.rs +++ b/crates/ra_hir/src/lib.rs @@ -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 { - 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>) -> DefLoc { - db.as_ref().id2loc(self) - } -} - -impl DefLoc { - pub(crate) fn id(&self, db: &impl AsRef>) -> 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 { - 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 { - 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; - -#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] -pub struct SourceItemId { - file_id: HirFileId, - /// None for the whole file. - item_id: Option, -} - -/// Maps item's `SyntaxNode`s to `SourceFileItemId` and back. -#[derive(Debug, PartialEq, Eq)] -pub struct SourceFileItems { - file_id: HirFileId, - arena: Arena, -} - -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::>(), - ); - } - pub fn id_of_source_file(&self) -> SourceFileItemId { - let (id, _syntax) = self.arena.iter().next().unwrap(); - id - } -} - -impl Index for SourceFileItems { - type Output = SyntaxNode; - fn index(&self, idx: SourceFileItemId) -> &SyntaxNode { - &self.arena[idx] - } -} diff --git a/crates/ra_hir/src/macros.rs b/crates/ra_hir/src/macros.rs index 1f141dbac..288fbe3c6 100644 --- a/crates/ra_hir/src/macros.rs +++ b/crates/ra_hir/src/macros.rs @@ -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. diff --git a/crates/ra_hir/src/module/nameres.rs b/crates/ra_hir/src/module/nameres.rs index cc60ba077..40aa33ffa 100644 --- a/crates/ra_hir/src/module/nameres.rs +++ b/crates/ra_hir/src/module/nameres.rs @@ -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, -- cgit v1.2.3