diff options
Diffstat (limited to 'crates/ra_analysis/src/hir/query_definitions.rs')
-rw-r--r-- | crates/ra_analysis/src/hir/query_definitions.rs | 158 |
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 @@ | |||
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 | |||
12 | use 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` | ||
27 | pub(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 | |||
33 | pub(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 | |||
39 | pub(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 | |||
54 | pub(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 | |||
62 | pub(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 | |||
95 | pub(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 | |||
109 | pub(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 | |||
134 | pub(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 | } | ||