aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_hir/src/lib.rs
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_hir/src/lib.rs')
-rw-r--r--crates/ra_hir/src/lib.rs141
1 files changed, 141 insertions, 0 deletions
diff --git a/crates/ra_hir/src/lib.rs b/crates/ra_hir/src/lib.rs
new file mode 100644
index 000000000..e7b6a81f4
--- /dev/null
+++ b/crates/ra_hir/src/lib.rs
@@ -0,0 +1,141 @@
1//! HIR (previsouly known as descriptors) provides a high-level OO acess to Rust
2//! code.
3//!
4//! The principal difference between HIR and syntax trees is that HIR is bound
5//! to a particular crate instance. That is, it has cfg flags and features
6//! applied. So, there relation between syntax and HIR is many-to-one.
7
8macro_rules! ctry {
9 ($expr:expr) => {
10 match $expr {
11 None => return Ok(None),
12 Some(it) => it,
13 }
14 };
15}
16
17pub mod db;
18#[cfg(test)]
19mod mock;
20mod query_definitions;
21mod function;
22mod module;
23mod path;
24mod arena;
25
26use std::ops::Index;
27
28use ra_syntax::{SyntaxNodeRef, SyntaxNode};
29use ra_db::{LocationIntener, SourceRootId, FileId, Cancelable};
30
31use crate::{
32 db::HirDatabase,
33 arena::{Arena, Id},
34};
35
36pub use self::{
37 path::{Path, PathKind},
38 module::{Module, ModuleId, Problem, nameres::ItemMap},
39 function::{Function, FnScopes},
40};
41
42pub use self::function::FnSignatureInfo;
43
44#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
45pub struct FnId(u32);
46ra_db::impl_numeric_id!(FnId);
47
48impl FnId {
49 pub fn from_loc(
50 db: &impl AsRef<LocationIntener<SourceItemId, FnId>>,
51 loc: &SourceItemId,
52 ) -> FnId {
53 db.as_ref().loc2id(loc)
54 }
55 pub fn loc(self, db: &impl AsRef<LocationIntener<SourceItemId, FnId>>) -> SourceItemId {
56 db.as_ref().id2loc(self)
57 }
58}
59
60#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
61pub struct DefId(u32);
62ra_db::impl_numeric_id!(DefId);
63
64#[derive(Clone, Debug, PartialEq, Eq, Hash)]
65pub enum DefLoc {
66 Module {
67 id: ModuleId,
68 source_root: SourceRootId,
69 },
70 Item {
71 source_item_id: SourceItemId,
72 },
73}
74
75impl DefId {
76 pub fn loc(self, db: &impl AsRef<LocationIntener<DefLoc, DefId>>) -> DefLoc {
77 db.as_ref().id2loc(self)
78 }
79}
80
81impl DefLoc {
82 pub fn id(&self, db: &impl AsRef<LocationIntener<DefLoc, DefId>>) -> DefId {
83 db.as_ref().loc2id(&self)
84 }
85}
86
87pub enum Def {
88 Module(Module),
89 Item,
90}
91
92impl DefId {
93 pub fn resolve(self, db: &impl HirDatabase) -> Cancelable<Def> {
94 let loc = self.loc(db);
95 let res = match loc {
96 DefLoc::Module { id, source_root } => {
97 let descr = Module::new(db, source_root, id)?;
98 Def::Module(descr)
99 }
100 DefLoc::Item { .. } => Def::Item,
101 };
102 Ok(res)
103 }
104}
105
106/// Identifier of item within a specific file. This is stable over reparses, so
107/// it's OK to use it as a salsa key/value.
108pub(crate) type SourceFileItemId = Id<SyntaxNode>;
109
110#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
111pub struct SourceItemId {
112 file_id: FileId,
113 item_id: SourceFileItemId,
114}
115
116/// Maps item's `SyntaxNode`s to `SourceFileItemId` and back.
117#[derive(Debug, PartialEq, Eq, Default)]
118pub struct SourceFileItems {
119 arena: Arena<SyntaxNode>,
120}
121
122impl SourceFileItems {
123 fn alloc(&mut self, item: SyntaxNode) -> SourceFileItemId {
124 self.arena.alloc(item)
125 }
126 pub fn id_of(&self, item: SyntaxNodeRef) -> SourceFileItemId {
127 let (id, _item) = self
128 .arena
129 .iter()
130 .find(|(_id, i)| i.borrowed() == item)
131 .unwrap();
132 id
133 }
134}
135
136impl Index<SourceFileItemId> for SourceFileItems {
137 type Output = SyntaxNode;
138 fn index(&self, idx: SourceFileItemId) -> &SyntaxNode {
139 &self.arena[idx]
140 }
141}