rust/crates/ra_hir/src/lib.rs

146 lines
3.4 KiB
Rust
Raw Normal View History

2018-11-28 01:42:26 +01:00
//! 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,
}
};
}
2018-11-28 02:09:44 +01:00
pub mod db;
2018-11-28 14:19:01 +01:00
#[cfg(test)]
mod mock;
2018-11-28 01:42:26 +01:00
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},
};
2018-11-28 02:09:44 +01:00
pub use self::{
2018-11-28 01:42:26 +01:00
path::{Path, PathKind},
2018-11-28 02:09:44 +01:00
module::{Module, ModuleId, Problem, nameres::ItemMap},
2018-11-28 01:42:26 +01:00
function::{Function, FnScopes},
};
pub use self::function::FnSignatureInfo;
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
2018-11-28 02:09:44 +01:00
pub struct FnId(u32);
2018-11-28 01:42:26 +01:00
ra_db::impl_numeric_id!(FnId);
impl FnId {
2018-11-28 02:09:44 +01:00
pub fn from_loc(
2018-11-28 01:42:26 +01:00
db: &impl AsRef<LocationIntener<SourceItemId, FnId>>,
loc: &SourceItemId,
) -> FnId {
db.as_ref().loc2id(loc)
}
2018-11-28 02:09:44 +01:00
pub fn loc(self, db: &impl AsRef<LocationIntener<SourceItemId, FnId>>) -> SourceItemId {
2018-11-28 01:42:26 +01:00
db.as_ref().id2loc(self)
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
2018-11-28 02:09:44 +01:00
pub struct DefId(u32);
2018-11-28 01:42:26 +01:00
ra_db::impl_numeric_id!(DefId);
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
2018-11-28 02:09:44 +01:00
pub enum DefLoc {
2018-11-28 01:42:26 +01:00
Module {
id: ModuleId,
source_root: SourceRootId,
},
Item {
source_item_id: SourceItemId,
},
}
impl DefId {
2018-11-28 02:09:44 +01:00
pub fn loc(self, db: &impl AsRef<LocationIntener<DefLoc, DefId>>) -> DefLoc {
2018-11-28 01:42:26 +01:00
db.as_ref().id2loc(self)
}
}
impl DefLoc {
2018-11-28 02:09:44 +01:00
pub fn id(&self, db: &impl AsRef<LocationIntener<DefLoc, DefId>>) -> DefId {
2018-11-28 01:42:26 +01:00
db.as_ref().loc2id(&self)
}
}
2018-11-28 02:09:44 +01:00
pub enum Def {
2018-11-28 01:42:26 +01:00
Module(Module),
Item,
}
impl DefId {
2018-11-28 02:09:44 +01:00
pub fn resolve(self, db: &impl HirDatabase) -> Cancelable<Def> {
2018-11-28 01:42:26 +01:00
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<SyntaxNode>;
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
2018-11-28 02:09:44 +01:00
pub struct SourceItemId {
2018-11-28 01:42:26 +01:00
file_id: FileId,
item_id: SourceFileItemId,
}
/// Maps item's `SyntaxNode`s to `SourceFileItemId` and back.
#[derive(Debug, PartialEq, Eq, Default)]
2018-11-28 02:09:44 +01:00
pub struct SourceFileItems {
2018-11-28 01:42:26 +01:00
arena: Arena<SyntaxNode>,
}
impl SourceFileItems {
fn alloc(&mut self, item: SyntaxNode) -> SourceFileItemId {
self.arena.alloc(item)
}
2018-11-28 02:09:44 +01:00
pub fn id_of(&self, item: SyntaxNodeRef) -> SourceFileItemId {
2018-11-28 01:42:26 +01:00
let (id, _item) = self
.arena
.iter()
.find(|(_id, i)| i.borrowed() == item)
.unwrap();
id
}
2018-12-04 20:46:23 +01:00
pub fn id_of_source_file(&self) -> SourceFileItemId {
let (id, _syntax) = self.arena.iter().next().unwrap();
id
}
2018-11-28 01:42:26 +01:00
}
impl Index<SourceFileItemId> for SourceFileItems {
type Output = SyntaxNode;
fn index(&self, idx: SourceFileItemId) -> &SyntaxNode {
&self.arena[idx]
}
}