From 0e4b710af83844f4a7c471c5335c99aaaa25a90c Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Wed, 28 Nov 2018 03:42:26 +0300 Subject: introduce hir crate --- crates/ra_hir/src/lib.rs | 139 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 139 insertions(+) create mode 100644 crates/ra_hir/src/lib.rs (limited to 'crates/ra_hir/src/lib.rs') diff --git a/crates/ra_hir/src/lib.rs b/crates/ra_hir/src/lib.rs new file mode 100644 index 000000000..7bf06c7f7 --- /dev/null +++ b/crates/ra_hir/src/lib.rs @@ -0,0 +1,139 @@ +//! HIR (previsouly known as descriptors) provides a high-level OO acess to Rust +//! code. +//! +//! The principal difference between HIR and syntax trees is that HIR is bound +//! to a particular crate instance. That is, it has cfg flags and features +//! applied. So, there relation between syntax and HIR is many-to-one. + +macro_rules! ctry { + ($expr:expr) => { + match $expr { + None => return Ok(None), + Some(it) => it, + } + }; +} + +pub(crate) mod db; +mod query_definitions; +mod function; +mod module; +mod path; +mod arena; + +use std::ops::Index; + +use ra_syntax::{SyntaxNodeRef, SyntaxNode}; +use ra_db::{LocationIntener, SourceRootId, FileId, Cancelable}; + +use crate::{ + db::HirDatabase, + arena::{Arena, Id}, +}; + +pub(crate) use self::{ + path::{Path, PathKind}, + module::{Module, ModuleId, Problem}, + function::{Function, FnScopes}, +}; + +pub use self::function::FnSignatureInfo; + +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] +pub(crate) struct FnId(u32); +ra_db::impl_numeric_id!(FnId); + +impl FnId { + pub(crate) fn from_loc( + db: &impl AsRef>, + loc: &SourceItemId, + ) -> FnId { + db.as_ref().loc2id(loc) + } + pub(crate) fn loc(self, db: &impl AsRef>) -> SourceItemId { + db.as_ref().id2loc(self) + } +} + +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] +pub(crate) struct DefId(u32); +ra_db::impl_numeric_id!(DefId); + +#[derive(Clone, Debug, PartialEq, Eq, Hash)] +pub(crate) enum DefLoc { + Module { + id: ModuleId, + source_root: SourceRootId, + }, + Item { + source_item_id: SourceItemId, + }, +} + +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(crate) enum Def { + Module(Module), + Item, +} + +impl DefId { + pub(crate) fn resolve(self, db: &impl HirDatabase) -> Cancelable { + let loc = self.loc(db); + let res = match loc { + DefLoc::Module { id, source_root } => { + let descr = Module::new(db, source_root, id)?; + Def::Module(descr) + } + DefLoc::Item { .. } => Def::Item, + }; + Ok(res) + } +} + +/// 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(crate) struct SourceItemId { + file_id: FileId, + item_id: SourceFileItemId, +} + +/// Maps item's `SyntaxNode`s to `SourceFileItemId` and back. +#[derive(Debug, PartialEq, Eq, Default)] +pub(crate) struct SourceFileItems { + arena: Arena, +} + +impl SourceFileItems { + fn alloc(&mut self, item: SyntaxNode) -> SourceFileItemId { + self.arena.alloc(item) + } + fn id_of(&self, item: SyntaxNodeRef) -> SourceFileItemId { + let (id, _item) = self + .arena + .iter() + .find(|(_id, i)| i.borrowed() == item) + .unwrap(); + id + } +} + +impl Index for SourceFileItems { + type Output = SyntaxNode; + fn index(&self, idx: SourceFileItemId) -> &SyntaxNode { + &self.arena[idx] + } +} -- cgit v1.2.3