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