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.rs139
1 files changed, 139 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..7bf06c7f7
--- /dev/null
+++ b/crates/ra_hir/src/lib.rs
@@ -0,0 +1,139 @@
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(crate) mod db;
18mod query_definitions;
19mod function;
20mod module;
21mod path;
22mod arena;
23
24use std::ops::Index;
25
26use ra_syntax::{SyntaxNodeRef, SyntaxNode};
27use ra_db::{LocationIntener, SourceRootId, FileId, Cancelable};
28
29use crate::{
30 db::HirDatabase,
31 arena::{Arena, Id},
32};
33
34pub(crate) use self::{
35 path::{Path, PathKind},
36 module::{Module, ModuleId, Problem},
37 function::{Function, FnScopes},
38};
39
40pub use self::function::FnSignatureInfo;
41
42#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
43pub(crate) struct FnId(u32);
44ra_db::impl_numeric_id!(FnId);
45
46impl FnId {
47 pub(crate) fn from_loc(
48 db: &impl AsRef<LocationIntener<SourceItemId, FnId>>,
49 loc: &SourceItemId,
50 ) -> FnId {
51 db.as_ref().loc2id(loc)
52 }
53 pub(crate) fn loc(self, db: &impl AsRef<LocationIntener<SourceItemId, FnId>>) -> SourceItemId {
54 db.as_ref().id2loc(self)
55 }
56}
57
58#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
59pub(crate) struct DefId(u32);
60ra_db::impl_numeric_id!(DefId);
61
62#[derive(Clone, Debug, PartialEq, Eq, Hash)]
63pub(crate) enum DefLoc {
64 Module {
65 id: ModuleId,
66 source_root: SourceRootId,
67 },
68 Item {
69 source_item_id: SourceItemId,
70 },
71}
72
73impl DefId {
74 pub(crate) fn loc(self, db: &impl AsRef<LocationIntener<DefLoc, DefId>>) -> DefLoc {
75 db.as_ref().id2loc(self)
76 }
77}
78
79impl DefLoc {
80 pub(crate) fn id(&self, db: &impl AsRef<LocationIntener<DefLoc, DefId>>) -> DefId {
81 db.as_ref().loc2id(&self)
82 }
83}
84
85pub(crate) enum Def {
86 Module(Module),
87 Item,
88}
89
90impl DefId {
91 pub(crate) fn resolve(self, db: &impl HirDatabase) -> Cancelable<Def> {
92 let loc = self.loc(db);
93 let res = match loc {
94 DefLoc::Module { id, source_root } => {
95 let descr = Module::new(db, source_root, id)?;
96 Def::Module(descr)
97 }
98 DefLoc::Item { .. } => Def::Item,
99 };
100 Ok(res)
101 }
102}
103
104/// Identifier of item within a specific file. This is stable over reparses, so
105/// it's OK to use it as a salsa key/value.
106pub(crate) type SourceFileItemId = Id<SyntaxNode>;
107
108#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
109pub(crate) struct SourceItemId {
110 file_id: FileId,
111 item_id: SourceFileItemId,
112}
113
114/// Maps item's `SyntaxNode`s to `SourceFileItemId` and back.
115#[derive(Debug, PartialEq, Eq, Default)]
116pub(crate) struct SourceFileItems {
117 arena: Arena<SyntaxNode>,
118}
119
120impl SourceFileItems {
121 fn alloc(&mut self, item: SyntaxNode) -> SourceFileItemId {
122 self.arena.alloc(item)
123 }
124 fn id_of(&self, item: SyntaxNodeRef) -> SourceFileItemId {
125 let (id, _item) = self
126 .arena
127 .iter()
128 .find(|(_id, i)| i.borrowed() == item)
129 .unwrap();
130 id
131 }
132}
133
134impl Index<SourceFileItemId> for SourceFileItems {
135 type Output = SyntaxNode;
136 fn index(&self, idx: SourceFileItemId) -> &SyntaxNode {
137 &self.arena[idx]
138 }
139}