aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_analysis/src/hir/query_definitions.rs
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_analysis/src/hir/query_definitions.rs')
-rw-r--r--crates/ra_analysis/src/hir/query_definitions.rs158
1 files changed, 158 insertions, 0 deletions
diff --git a/crates/ra_analysis/src/hir/query_definitions.rs b/crates/ra_analysis/src/hir/query_definitions.rs
new file mode 100644
index 000000000..8584a8d64
--- /dev/null
+++ b/crates/ra_analysis/src/hir/query_definitions.rs
@@ -0,0 +1,158 @@
1use std::{
2 sync::Arc,
3 time::Instant,
4};
5
6use rustc_hash::FxHashMap;
7use ra_syntax::{
8 AstNode, SyntaxNode, SmolStr,
9 ast::{self, FnDef, FnDefNode, NameOwner, ModuleItemOwner}
10};
11
12use crate::{
13 FileId, Cancelable,
14 hir::{
15 db::HirDatabase,
16 function::{FnId, FnScopes},
17 module::{
18 ModuleSource, ModuleSourceNode, ModuleId,
19 imp::Submodule,
20 nameres::{FileItems, FileItemId, InputModuleItems, ItemMap, Resolver},
21 },
22 },
23 input::SourceRootId,
24};
25
26/// Resolve `FnId` to the corresponding `SyntaxNode`
27pub(super) fn fn_syntax(db: &impl HirDatabase, fn_id: FnId) -> FnDefNode {
28 let ptr = db.id_maps().fn_ptr(fn_id);
29 let syntax = db.resolve_syntax_ptr(ptr);
30 FnDef::cast(syntax.borrowed()).unwrap().owned()
31}
32
33pub(super) fn fn_scopes(db: &impl HirDatabase, fn_id: FnId) -> Arc<FnScopes> {
34 let syntax = db.fn_syntax(fn_id);
35 let res = FnScopes::new(syntax.borrowed());
36 Arc::new(res)
37}
38
39pub(super) fn file_items(db: &impl HirDatabase, file_id: FileId) -> Arc<FileItems> {
40 let source_file = db.file_syntax(file_id);
41 let source_file = source_file.borrowed();
42 let mut res = FileItems::default();
43 source_file
44 .syntax()
45 .descendants()
46 .filter_map(ast::ModuleItem::cast)
47 .map(|it| it.syntax().owned())
48 .for_each(|it| {
49 res.alloc(it);
50 });
51 Arc::new(res)
52}
53
54pub(super) fn file_item(
55 db: &impl HirDatabase,
56 file_id: FileId,
57 file_item_id: FileItemId,
58) -> SyntaxNode {
59 db.file_items(file_id)[file_item_id].clone()
60}
61
62pub(crate) fn submodules(
63 db: &impl HirDatabase,
64 source: ModuleSource,
65) -> Cancelable<Arc<Vec<Submodule>>> {
66 db.check_canceled()?;
67 let file_id = source.file_id();
68 let submodules = match source.resolve(db) {
69 ModuleSourceNode::SourceFile(it) => collect_submodules(file_id, it.borrowed()),
70 ModuleSourceNode::Module(it) => it
71 .borrowed()
72 .item_list()
73 .map(|it| collect_submodules(file_id, it))
74 .unwrap_or_else(Vec::new),
75 };
76 return Ok(Arc::new(submodules));
77
78 fn collect_submodules<'a>(
79 file_id: FileId,
80 root: impl ast::ModuleItemOwner<'a>,
81 ) -> Vec<Submodule> {
82 modules(root)
83 .map(|(name, m)| {
84 if m.has_semi() {
85 Submodule::Declaration(name)
86 } else {
87 let src = ModuleSource::new_inline(file_id, m);
88 Submodule::Definition(name, src)
89 }
90 })
91 .collect()
92 }
93}
94
95pub(crate) fn modules<'a>(
96 root: impl ast::ModuleItemOwner<'a>,
97) -> impl Iterator<Item = (SmolStr, ast::Module<'a>)> {
98 root.items()
99 .filter_map(|item| match item {
100 ast::ModuleItem::Module(m) => Some(m),
101 _ => None,
102 })
103 .filter_map(|module| {
104 let name = module.name()?.text();
105 Some((name, module))
106 })
107}
108
109pub(super) fn input_module_items(
110 db: &impl HirDatabase,
111 source_root: SourceRootId,
112 module_id: ModuleId,
113) -> Cancelable<Arc<InputModuleItems>> {
114 let module_tree = db.module_tree(source_root)?;
115 let source = module_id.source(&module_tree);
116 let file_items = db.file_items(source.file_id());
117 let res = match source.resolve(db) {
118 ModuleSourceNode::SourceFile(it) => {
119 let items = it.borrowed().items();
120 InputModuleItems::new(&file_items, items)
121 }
122 ModuleSourceNode::Module(it) => {
123 let items = it
124 .borrowed()
125 .item_list()
126 .into_iter()
127 .flat_map(|it| it.items());
128 InputModuleItems::new(&file_items, items)
129 }
130 };
131 Ok(Arc::new(res))
132}
133
134pub(super) fn item_map(
135 db: &impl HirDatabase,
136 source_root: SourceRootId,
137) -> Cancelable<Arc<ItemMap>> {
138 let start = Instant::now();
139 let module_tree = db.module_tree(source_root)?;
140 let input = module_tree
141 .modules()
142 .map(|id| {
143 let items = db.input_module_items(source_root, id)?;
144 Ok((id, items))
145 })
146 .collect::<Cancelable<FxHashMap<_, _>>>()?;
147 let resolver = Resolver {
148 db: db,
149 input: &input,
150 source_root,
151 module_tree,
152 result: ItemMap::default(),
153 };
154 let res = resolver.resolve()?;
155 let elapsed = start.elapsed();
156 log::info!("item_map: {:?}", elapsed);
157 Ok(Arc::new(res))
158}