diff options
author | Ekaterina Babshukova <[email protected]> | 2019-09-16 11:48:54 +0100 |
---|---|---|
committer | Ekaterina Babshukova <[email protected]> | 2019-09-19 17:38:27 +0100 |
commit | 2867c40925e8f7b440ff50a421a2d3726b9ff334 (patch) | |
tree | 95a8f33d0c334debf5eec41c2edf6fb01a5dcb49 /crates/ra_hir/src/source_binder.rs | |
parent | c35ef7e1ed97172ab644248185b75dceebb0d35a (diff) |
introduce FromSource trait
Diffstat (limited to 'crates/ra_hir/src/source_binder.rs')
-rw-r--r-- | crates/ra_hir/src/source_binder.rs | 124 |
1 files changed, 17 insertions, 107 deletions
diff --git a/crates/ra_hir/src/source_binder.rs b/crates/ra_hir/src/source_binder.rs index 4d895f0a1..296acc364 100644 --- a/crates/ra_hir/src/source_binder.rs +++ b/crates/ra_hir/src/source_binder.rs | |||
@@ -7,10 +7,9 @@ | |||
7 | /// purely for "IDE needs". | 7 | /// purely for "IDE needs". |
8 | use std::sync::Arc; | 8 | use std::sync::Arc; |
9 | 9 | ||
10 | use ra_db::{FileId, FilePosition}; | 10 | use ra_db::FileId; |
11 | use ra_syntax::{ | 11 | use ra_syntax::{ |
12 | algo::find_node_at_offset, | 12 | ast::{self, AstNode}, |
13 | ast::{self, AstNode, NameOwner}, | ||
14 | AstPtr, | 13 | AstPtr, |
15 | SyntaxKind::*, | 14 | SyntaxKind::*, |
16 | SyntaxNode, SyntaxNodePtr, TextRange, TextUnit, | 15 | SyntaxNode, SyntaxNodePtr, TextRange, TextUnit, |
@@ -28,119 +27,28 @@ use crate::{ | |||
28 | path::known, | 27 | path::known, |
29 | resolve::{ScopeDef, TypeNs, ValueNs}, | 28 | resolve::{ScopeDef, TypeNs, ValueNs}, |
30 | ty::method_resolution::implements_trait, | 29 | ty::method_resolution::implements_trait, |
31 | AsName, AstId, Const, Crate, DefWithBody, Either, Enum, Function, HasBody, HirFileId, MacroDef, | 30 | AsName, Const, DefWithBody, Either, Enum, FromSource, Function, HasBody, HirFileId, MacroDef, |
32 | Module, Name, Path, Resolver, Static, Struct, Trait, Ty, | 31 | Module, Name, Path, Resolver, Static, Struct, Ty, |
33 | }; | 32 | }; |
34 | 33 | ||
35 | /// Locates the module by `FileId`. Picks topmost module in the file. | ||
36 | pub fn module_from_file_id(db: &impl HirDatabase, file_id: FileId) -> Option<Module> { | ||
37 | module_from_source(db, file_id.into(), None) | ||
38 | } | ||
39 | |||
40 | /// Locates the child module by `mod child;` declaration. | ||
41 | pub fn module_from_declaration( | ||
42 | db: &impl HirDatabase, | ||
43 | file_id: FileId, | ||
44 | decl: ast::Module, | ||
45 | ) -> Option<Module> { | ||
46 | let parent_module = module_from_file_id(db, file_id); | ||
47 | let child_name = decl.name(); | ||
48 | match (parent_module, child_name) { | ||
49 | (Some(parent_module), Some(child_name)) => parent_module.child(db, &child_name.as_name()), | ||
50 | _ => None, | ||
51 | } | ||
52 | } | ||
53 | |||
54 | /// Locates the module by position in the source code. | ||
55 | pub fn module_from_position(db: &impl HirDatabase, position: FilePosition) -> Option<Module> { | ||
56 | let parse = db.parse(position.file_id); | ||
57 | match &find_node_at_offset::<ast::Module>(parse.tree().syntax(), position.offset) { | ||
58 | Some(m) if !m.has_semi() => module_from_inline(db, position.file_id, m.clone()), | ||
59 | _ => module_from_file_id(db, position.file_id), | ||
60 | } | ||
61 | } | ||
62 | |||
63 | fn module_from_inline( | ||
64 | db: &impl HirDatabase, | ||
65 | file_id: FileId, | ||
66 | module: ast::Module, | ||
67 | ) -> Option<Module> { | ||
68 | assert!(!module.has_semi()); | ||
69 | let file_id = file_id.into(); | ||
70 | let ast_id_map = db.ast_id_map(file_id); | ||
71 | let item_id = ast_id_map.ast_id(&module).with_file_id(file_id); | ||
72 | module_from_source(db, file_id, Some(item_id)) | ||
73 | } | ||
74 | |||
75 | /// Locates the module by child syntax element within the module | ||
76 | pub fn module_from_child_node( | ||
77 | db: &impl HirDatabase, | ||
78 | file_id: FileId, | ||
79 | child: &SyntaxNode, | ||
80 | ) -> Option<Module> { | ||
81 | if let Some(m) = child.ancestors().filter_map(ast::Module::cast).find(|it| !it.has_semi()) { | ||
82 | module_from_inline(db, file_id, m) | ||
83 | } else { | ||
84 | module_from_file_id(db, file_id) | ||
85 | } | ||
86 | } | ||
87 | |||
88 | fn module_from_source( | ||
89 | db: &impl HirDatabase, | ||
90 | file_id: HirFileId, | ||
91 | decl_id: Option<AstId<ast::Module>>, | ||
92 | ) -> Option<Module> { | ||
93 | let source_root_id = db.file_source_root(file_id.as_original_file()); | ||
94 | db.source_root_crates(source_root_id).iter().map(|&crate_id| Crate { crate_id }).find_map( | ||
95 | |krate| { | ||
96 | let def_map = db.crate_def_map(krate); | ||
97 | let module_id = def_map.find_module_by_source(file_id, decl_id)?; | ||
98 | Some(Module { krate, module_id }) | ||
99 | }, | ||
100 | ) | ||
101 | } | ||
102 | |||
103 | pub fn struct_from_module( | ||
104 | db: &impl HirDatabase, | ||
105 | module: Module, | ||
106 | struct_def: &ast::StructDef, | ||
107 | ) -> Struct { | ||
108 | let file_id = module.definition_source(db).file_id; | ||
109 | let ctx = LocationCtx::new(db, module, file_id); | ||
110 | Struct { id: ctx.to_def(struct_def) } | ||
111 | } | ||
112 | |||
113 | pub fn enum_from_module(db: &impl HirDatabase, module: Module, enum_def: &ast::EnumDef) -> Enum { | ||
114 | let file_id = module.definition_source(db).file_id; | ||
115 | let ctx = LocationCtx::new(db, module, file_id); | ||
116 | Enum { id: ctx.to_def(enum_def) } | ||
117 | } | ||
118 | |||
119 | pub fn trait_from_module( | ||
120 | db: &impl HirDatabase, | ||
121 | module: Module, | ||
122 | trait_def: &ast::TraitDef, | ||
123 | ) -> Trait { | ||
124 | let file_id = module.definition_source(db).file_id; | ||
125 | let ctx = LocationCtx::new(db, module, file_id); | ||
126 | Trait { id: ctx.to_def(trait_def) } | ||
127 | } | ||
128 | |||
129 | fn try_get_resolver_for_node( | 34 | fn try_get_resolver_for_node( |
130 | db: &impl HirDatabase, | 35 | db: &impl HirDatabase, |
131 | file_id: FileId, | 36 | file_id: FileId, |
132 | node: &SyntaxNode, | 37 | node: &SyntaxNode, |
133 | ) -> Option<Resolver> { | 38 | ) -> Option<Resolver> { |
134 | if let Some(module) = ast::Module::cast(node.clone()) { | 39 | if let Some(module) = ast::Module::cast(node.clone()) { |
135 | Some(module_from_declaration(db, file_id, module)?.resolver(db)) | 40 | let src = crate::Source { file_id: file_id.into(), ast: module }; |
136 | } else if let Some(_) = ast::SourceFile::cast(node.clone()) { | 41 | Some(crate::Module::from_declaration(db, src)?.resolver(db)) |
137 | Some(module_from_source(db, file_id.into(), None)?.resolver(db)) | 42 | } else if let Some(file) = ast::SourceFile::cast(node.clone()) { |
43 | let src = | ||
44 | crate::Source { file_id: file_id.into(), ast: crate::ModuleSource::SourceFile(file) }; | ||
45 | Some(crate::Module::from_definition(db, src)?.resolver(db)) | ||
138 | } else if let Some(s) = ast::StructDef::cast(node.clone()) { | 46 | } else if let Some(s) = ast::StructDef::cast(node.clone()) { |
139 | let module = module_from_child_node(db, file_id, s.syntax())?; | 47 | let src = crate::Source { file_id: file_id.into(), ast: s }; |
140 | Some(struct_from_module(db, module, &s).resolver(db)) | 48 | Some(Struct::from_source(db, src)?.resolver(db)) |
141 | } else if let Some(e) = ast::EnumDef::cast(node.clone()) { | 49 | } else if let Some(e) = ast::EnumDef::cast(node.clone()) { |
142 | let module = module_from_child_node(db, file_id, e.syntax())?; | 50 | let src = crate::Source { file_id: file_id.into(), ast: e }; |
143 | Some(enum_from_module(db, module, &e).resolver(db)) | 51 | Some(Enum::from_source(db, src)?.resolver(db)) |
144 | } else if node.kind() == FN_DEF || node.kind() == CONST_DEF || node.kind() == STATIC_DEF { | 52 | } else if node.kind() == FN_DEF || node.kind() == CONST_DEF || node.kind() == STATIC_DEF { |
145 | Some(def_with_body_from_child_node(db, file_id, node)?.resolver(db)) | 53 | Some(def_with_body_from_child_node(db, file_id, node)?.resolver(db)) |
146 | } else { | 54 | } else { |
@@ -154,8 +62,10 @@ fn def_with_body_from_child_node( | |||
154 | file_id: FileId, | 62 | file_id: FileId, |
155 | node: &SyntaxNode, | 63 | node: &SyntaxNode, |
156 | ) -> Option<DefWithBody> { | 64 | ) -> Option<DefWithBody> { |
157 | let module = module_from_child_node(db, file_id, node)?; | 65 | let src = crate::ModuleSource::from_child_node(db, file_id, node); |
66 | let module = Module::from_definition(db, crate::Source { file_id: file_id.into(), ast: src })?; | ||
158 | let ctx = LocationCtx::new(db, module, file_id.into()); | 67 | let ctx = LocationCtx::new(db, module, file_id.into()); |
68 | |||
159 | node.ancestors().find_map(|node| { | 69 | node.ancestors().find_map(|node| { |
160 | if let Some(def) = ast::FnDef::cast(node.clone()) { | 70 | if let Some(def) = ast::FnDef::cast(node.clone()) { |
161 | return Some(Function { id: ctx.to_def(&def) }.into()); | 71 | return Some(Function { id: ctx.to_def(&def) }.into()); |