diff options
author | bors[bot] <26634292+bors[bot]@users.noreply.github.com> | 2019-09-19 19:18:41 +0100 |
---|---|---|
committer | GitHub <[email protected]> | 2019-09-19 19:18:41 +0100 |
commit | cd9b222ba0555424d73d549eac43d9aaf1765d7d (patch) | |
tree | 88eea12084b65ba7b0f808cc2c626c7b57c7ac53 | |
parent | 44bab3621d74f1aec922300a3b3f4476907ba2ac (diff) | |
parent | 2867c40925e8f7b440ff50a421a2d3726b9ff334 (diff) |
Merge #1853
1853: Introduce FromSource trait r=matklad a=viorina
The idea is to provide an ability to get HIR from AST in a more general way than it's possible using `source_binder`.
It also could help with #1622 fixing.
Co-authored-by: Ekaterina Babshukova <[email protected]>
-rw-r--r-- | crates/ra_hir/src/code_model.rs | 2 | ||||
-rw-r--r-- | crates/ra_hir/src/from_source.rs | 211 | ||||
-rw-r--r-- | crates/ra_hir/src/lib.rs | 3 | ||||
-rw-r--r-- | crates/ra_hir/src/mock.rs | 6 | ||||
-rw-r--r-- | crates/ra_hir/src/nameres/tests/incremental.rs | 12 | ||||
-rw-r--r-- | crates/ra_hir/src/source_binder.rs | 124 | ||||
-rw-r--r-- | crates/ra_ide_api/src/completion/completion_context.rs | 7 | ||||
-rw-r--r-- | crates/ra_ide_api/src/diagnostics.rs | 10 | ||||
-rw-r--r-- | crates/ra_ide_api/src/goto_definition.rs | 5 | ||||
-rw-r--r-- | crates/ra_ide_api/src/impls.rs | 25 | ||||
-rw-r--r-- | crates/ra_ide_api/src/parent_module.rs | 16 | ||||
-rw-r--r-- | crates/ra_ide_api/src/references.rs | 7 | ||||
-rw-r--r-- | crates/ra_ide_api/src/runnables.rs | 4 |
13 files changed, 294 insertions, 138 deletions
diff --git a/crates/ra_hir/src/code_model.rs b/crates/ra_hir/src/code_model.rs index 706d24c32..28002f740 100644 --- a/crates/ra_hir/src/code_model.rs +++ b/crates/ra_hir/src/code_model.rs | |||
@@ -313,7 +313,7 @@ pub struct StructField { | |||
313 | pub(crate) id: StructFieldId, | 313 | pub(crate) id: StructFieldId, |
314 | } | 314 | } |
315 | 315 | ||
316 | #[derive(Debug)] | 316 | #[derive(Debug, PartialEq, Eq)] |
317 | pub enum FieldSource { | 317 | pub enum FieldSource { |
318 | Named(ast::RecordFieldDef), | 318 | Named(ast::RecordFieldDef), |
319 | Pos(ast::TupleFieldDef), | 319 | Pos(ast::TupleFieldDef), |
diff --git a/crates/ra_hir/src/from_source.rs b/crates/ra_hir/src/from_source.rs new file mode 100644 index 000000000..c6ad85fc7 --- /dev/null +++ b/crates/ra_hir/src/from_source.rs | |||
@@ -0,0 +1,211 @@ | |||
1 | use ra_db::{FileId, FilePosition}; | ||
2 | use ra_syntax::{ | ||
3 | algo::find_node_at_offset, | ||
4 | ast::{self, AstNode, NameOwner}, | ||
5 | SyntaxNode, | ||
6 | }; | ||
7 | |||
8 | use crate::{ | ||
9 | db::{AstDatabase, DefDatabase, HirDatabase}, | ||
10 | ids::{AstItemDef, LocationCtx}, | ||
11 | name::AsName, | ||
12 | Const, Crate, Enum, EnumVariant, FieldSource, Function, HasSource, ImplBlock, Module, | ||
13 | ModuleSource, Source, Static, Struct, StructField, Trait, TypeAlias, Union, VariantDef, | ||
14 | }; | ||
15 | |||
16 | pub trait FromSource: Sized { | ||
17 | type Ast; | ||
18 | fn from_source(db: &(impl DefDatabase + AstDatabase), src: Source<Self::Ast>) -> Option<Self>; | ||
19 | } | ||
20 | |||
21 | impl FromSource for Struct { | ||
22 | type Ast = ast::StructDef; | ||
23 | fn from_source(db: &(impl DefDatabase + AstDatabase), src: Source<Self::Ast>) -> Option<Self> { | ||
24 | let id = from_source(db, src)?; | ||
25 | Some(Struct { id }) | ||
26 | } | ||
27 | } | ||
28 | impl FromSource for Union { | ||
29 | type Ast = ast::StructDef; | ||
30 | fn from_source(db: &(impl DefDatabase + AstDatabase), src: Source<Self::Ast>) -> Option<Self> { | ||
31 | let id = from_source(db, src)?; | ||
32 | Some(Union { id }) | ||
33 | } | ||
34 | } | ||
35 | impl FromSource for Enum { | ||
36 | type Ast = ast::EnumDef; | ||
37 | fn from_source(db: &(impl DefDatabase + AstDatabase), src: Source<Self::Ast>) -> Option<Self> { | ||
38 | let id = from_source(db, src)?; | ||
39 | Some(Enum { id }) | ||
40 | } | ||
41 | } | ||
42 | impl FromSource for Trait { | ||
43 | type Ast = ast::TraitDef; | ||
44 | fn from_source(db: &(impl DefDatabase + AstDatabase), src: Source<Self::Ast>) -> Option<Self> { | ||
45 | let id = from_source(db, src)?; | ||
46 | Some(Trait { id }) | ||
47 | } | ||
48 | } | ||
49 | impl FromSource for Function { | ||
50 | type Ast = ast::FnDef; | ||
51 | fn from_source(db: &(impl DefDatabase + AstDatabase), src: Source<Self::Ast>) -> Option<Self> { | ||
52 | let id = from_source(db, src)?; | ||
53 | Some(Function { id }) | ||
54 | } | ||
55 | } | ||
56 | impl FromSource for Const { | ||
57 | type Ast = ast::ConstDef; | ||
58 | fn from_source(db: &(impl DefDatabase + AstDatabase), src: Source<Self::Ast>) -> Option<Self> { | ||
59 | let id = from_source(db, src)?; | ||
60 | Some(Const { id }) | ||
61 | } | ||
62 | } | ||
63 | impl FromSource for Static { | ||
64 | type Ast = ast::StaticDef; | ||
65 | fn from_source(db: &(impl DefDatabase + AstDatabase), src: Source<Self::Ast>) -> Option<Self> { | ||
66 | let id = from_source(db, src)?; | ||
67 | Some(Static { id }) | ||
68 | } | ||
69 | } | ||
70 | impl FromSource for TypeAlias { | ||
71 | type Ast = ast::TypeAliasDef; | ||
72 | fn from_source(db: &(impl DefDatabase + AstDatabase), src: Source<Self::Ast>) -> Option<Self> { | ||
73 | let id = from_source(db, src)?; | ||
74 | Some(TypeAlias { id }) | ||
75 | } | ||
76 | } | ||
77 | // FIXME: add impl FromSource for MacroDef | ||
78 | |||
79 | impl FromSource for ImplBlock { | ||
80 | type Ast = ast::ImplBlock; | ||
81 | fn from_source(db: &(impl DefDatabase + AstDatabase), src: Source<Self::Ast>) -> Option<Self> { | ||
82 | let module_src = crate::ModuleSource::from_child_node( | ||
83 | db, | ||
84 | src.file_id.original_file(db), | ||
85 | &src.ast.syntax(), | ||
86 | ); | ||
87 | let module = Module::from_definition(db, Source { file_id: src.file_id, ast: module_src })?; | ||
88 | let impls = module.impl_blocks(db); | ||
89 | impls.into_iter().find(|b| b.source(db) == src) | ||
90 | } | ||
91 | } | ||
92 | |||
93 | impl FromSource for EnumVariant { | ||
94 | type Ast = ast::EnumVariant; | ||
95 | fn from_source(db: &(impl DefDatabase + AstDatabase), src: Source<Self::Ast>) -> Option<Self> { | ||
96 | let parent_enum = src.ast.parent_enum(); | ||
97 | let src_enum = Source { file_id: src.file_id, ast: parent_enum }; | ||
98 | let variants = Enum::from_source(db, src_enum)?.variants(db); | ||
99 | variants.into_iter().find(|v| v.source(db) == src) | ||
100 | } | ||
101 | } | ||
102 | |||
103 | impl FromSource for StructField { | ||
104 | type Ast = FieldSource; | ||
105 | fn from_source(db: &(impl DefDatabase + AstDatabase), src: Source<Self::Ast>) -> Option<Self> { | ||
106 | let variant_def: VariantDef = match src.ast { | ||
107 | FieldSource::Named(ref field) => { | ||
108 | let ast = field.syntax().ancestors().find_map(ast::StructDef::cast)?; | ||
109 | let src = Source { file_id: src.file_id, ast }; | ||
110 | let def = Struct::from_source(db, src)?; | ||
111 | VariantDef::from(def) | ||
112 | } | ||
113 | FieldSource::Pos(ref field) => { | ||
114 | let ast = field.syntax().ancestors().find_map(ast::EnumVariant::cast)?; | ||
115 | let src = Source { file_id: src.file_id, ast }; | ||
116 | let def = EnumVariant::from_source(db, src)?; | ||
117 | VariantDef::from(def) | ||
118 | } | ||
119 | }; | ||
120 | variant_def | ||
121 | .variant_data(db) | ||
122 | .fields() | ||
123 | .into_iter() | ||
124 | .flat_map(|it| it.iter()) | ||
125 | .map(|(id, _)| StructField { parent: variant_def.clone(), id }) | ||
126 | .find(|f| f.source(db) == src) | ||
127 | } | ||
128 | } | ||
129 | |||
130 | // FIXME: simplify it | ||
131 | impl ModuleSource { | ||
132 | pub fn from_position( | ||
133 | db: &(impl DefDatabase + AstDatabase), | ||
134 | position: FilePosition, | ||
135 | ) -> ModuleSource { | ||
136 | let parse = db.parse(position.file_id); | ||
137 | match &find_node_at_offset::<ast::Module>(parse.tree().syntax(), position.offset) { | ||
138 | Some(m) if !m.has_semi() => ModuleSource::Module(m.clone()), | ||
139 | _ => { | ||
140 | let source_file = parse.tree().to_owned(); | ||
141 | ModuleSource::SourceFile(source_file) | ||
142 | } | ||
143 | } | ||
144 | } | ||
145 | |||
146 | pub fn from_child_node( | ||
147 | db: &(impl DefDatabase + AstDatabase), | ||
148 | file_id: FileId, | ||
149 | child: &SyntaxNode, | ||
150 | ) -> ModuleSource { | ||
151 | if let Some(m) = child.ancestors().filter_map(ast::Module::cast).find(|it| !it.has_semi()) { | ||
152 | ModuleSource::Module(m.clone()) | ||
153 | } else { | ||
154 | let source_file = db.parse(file_id).tree().to_owned(); | ||
155 | ModuleSource::SourceFile(source_file) | ||
156 | } | ||
157 | } | ||
158 | |||
159 | pub fn from_file_id(db: &(impl DefDatabase + AstDatabase), file_id: FileId) -> ModuleSource { | ||
160 | let source_file = db.parse(file_id).tree().to_owned(); | ||
161 | ModuleSource::SourceFile(source_file) | ||
162 | } | ||
163 | } | ||
164 | |||
165 | impl Module { | ||
166 | pub fn from_declaration(db: &impl HirDatabase, src: Source<ast::Module>) -> Option<Self> { | ||
167 | let src_parent = Source { | ||
168 | file_id: src.file_id, | ||
169 | ast: ModuleSource::new(db, Some(src.file_id.original_file(db)), None), | ||
170 | }; | ||
171 | let parent_module = Module::from_definition(db, src_parent)?; | ||
172 | let child_name = src.ast.name()?; | ||
173 | parent_module.child(db, &child_name.as_name()) | ||
174 | } | ||
175 | |||
176 | pub fn from_definition( | ||
177 | db: &(impl DefDatabase + AstDatabase), | ||
178 | src: Source<ModuleSource>, | ||
179 | ) -> Option<Self> { | ||
180 | let decl_id = match src.ast { | ||
181 | ModuleSource::Module(ref module) => { | ||
182 | assert!(!module.has_semi()); | ||
183 | let ast_id_map = db.ast_id_map(src.file_id); | ||
184 | let item_id = ast_id_map.ast_id(module).with_file_id(src.file_id); | ||
185 | Some(item_id) | ||
186 | } | ||
187 | ModuleSource::SourceFile(_) => None, | ||
188 | }; | ||
189 | |||
190 | let source_root_id = db.file_source_root(src.file_id.original_file(db)); | ||
191 | db.source_root_crates(source_root_id).iter().map(|&crate_id| Crate { crate_id }).find_map( | ||
192 | |krate| { | ||
193 | let def_map = db.crate_def_map(krate); | ||
194 | let module_id = def_map.find_module_by_source(src.file_id, decl_id)?; | ||
195 | Some(Module { krate, module_id }) | ||
196 | }, | ||
197 | ) | ||
198 | } | ||
199 | } | ||
200 | |||
201 | fn from_source<N, DEF>(db: &(impl DefDatabase + AstDatabase), src: Source<N>) -> Option<DEF> | ||
202 | where | ||
203 | N: AstNode, | ||
204 | DEF: AstItemDef<N>, | ||
205 | { | ||
206 | let module_src = | ||
207 | crate::ModuleSource::from_child_node(db, src.file_id.original_file(db), &src.ast.syntax()); | ||
208 | let module = Module::from_definition(db, Source { file_id: src.file_id, ast: module_src })?; | ||
209 | let ctx = LocationCtx::new(db, module, src.file_id); | ||
210 | Some(DEF::from_ast(ctx, &src.ast)) | ||
211 | } | ||
diff --git a/crates/ra_hir/src/lib.rs b/crates/ra_hir/src/lib.rs index e7a576aa0..a9de9fb6b 100644 --- a/crates/ra_hir/src/lib.rs +++ b/crates/ra_hir/src/lib.rs | |||
@@ -53,6 +53,8 @@ pub mod diagnostics; | |||
53 | 53 | ||
54 | mod code_model; | 54 | mod code_model; |
55 | 55 | ||
56 | pub mod from_source; | ||
57 | |||
56 | #[cfg(test)] | 58 | #[cfg(test)] |
57 | mod marks; | 59 | mod marks; |
58 | 60 | ||
@@ -67,6 +69,7 @@ pub use self::{ | |||
67 | adt::VariantDef, | 69 | adt::VariantDef, |
68 | either::Either, | 70 | either::Either, |
69 | expr::ExprScopes, | 71 | expr::ExprScopes, |
72 | from_source::FromSource, | ||
70 | generics::{GenericParam, GenericParams, HasGenericParams}, | 73 | generics::{GenericParam, GenericParams, HasGenericParams}, |
71 | ids::{HirFileId, MacroCallId, MacroCallLoc, MacroDefId, MacroFile}, | 74 | ids::{HirFileId, MacroCallId, MacroCallLoc, MacroDefId, MacroFile}, |
72 | impl_block::ImplBlock, | 75 | impl_block::ImplBlock, |
diff --git a/crates/ra_hir/src/mock.rs b/crates/ra_hir/src/mock.rs index 8dcea5071..cb405091e 100644 --- a/crates/ra_hir/src/mock.rs +++ b/crates/ra_hir/src/mock.rs | |||
@@ -93,7 +93,11 @@ impl MockDatabase { | |||
93 | let mut files: Vec<FileId> = self.files.values().copied().collect(); | 93 | let mut files: Vec<FileId> = self.files.values().copied().collect(); |
94 | files.sort(); | 94 | files.sort(); |
95 | for file in files { | 95 | for file in files { |
96 | let module = crate::source_binder::module_from_file_id(self, file).unwrap(); | 96 | let src = crate::Source { |
97 | file_id: file.into(), | ||
98 | ast: crate::ModuleSource::new(self, Some(file), None), | ||
99 | }; | ||
100 | let module = crate::Module::from_definition(self, src).unwrap(); | ||
97 | module.diagnostics( | 101 | module.diagnostics( |
98 | self, | 102 | self, |
99 | &mut DiagnosticSink::new(|d| { | 103 | &mut DiagnosticSink::new(|d| { |
diff --git a/crates/ra_hir/src/nameres/tests/incremental.rs b/crates/ra_hir/src/nameres/tests/incremental.rs index bc721f6e0..c41862a0b 100644 --- a/crates/ra_hir/src/nameres/tests/incremental.rs +++ b/crates/ra_hir/src/nameres/tests/incremental.rs | |||
@@ -114,7 +114,11 @@ fn typing_inside_a_macro_should_not_invalidate_def_map() { | |||
114 | ); | 114 | ); |
115 | { | 115 | { |
116 | let events = db.log_executed(|| { | 116 | let events = db.log_executed(|| { |
117 | let module = crate::source_binder::module_from_file_id(&db, pos.file_id).unwrap(); | 117 | let src = crate::Source { |
118 | file_id: pos.file_id.into(), | ||
119 | ast: crate::ModuleSource::new(&db, Some(pos.file_id), None), | ||
120 | }; | ||
121 | let module = crate::Module::from_definition(&db, src).unwrap(); | ||
118 | let decls = module.declarations(&db); | 122 | let decls = module.declarations(&db); |
119 | assert_eq!(decls.len(), 18); | 123 | assert_eq!(decls.len(), 18); |
120 | }); | 124 | }); |
@@ -124,7 +128,11 @@ fn typing_inside_a_macro_should_not_invalidate_def_map() { | |||
124 | 128 | ||
125 | { | 129 | { |
126 | let events = db.log_executed(|| { | 130 | let events = db.log_executed(|| { |
127 | let module = crate::source_binder::module_from_file_id(&db, pos.file_id).unwrap(); | 131 | let src = crate::Source { |
132 | file_id: pos.file_id.into(), | ||
133 | ast: crate::ModuleSource::new(&db, Some(pos.file_id), None), | ||
134 | }; | ||
135 | let module = crate::Module::from_definition(&db, src).unwrap(); | ||
128 | let decls = module.declarations(&db); | 136 | let decls = module.declarations(&db); |
129 | assert_eq!(decls.len(), 18); | 137 | assert_eq!(decls.len(), 18); |
130 | }); | 138 | }); |
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()); |
diff --git a/crates/ra_ide_api/src/completion/completion_context.rs b/crates/ra_ide_api/src/completion/completion_context.rs index 7139947b3..59bd3689b 100644 --- a/crates/ra_ide_api/src/completion/completion_context.rs +++ b/crates/ra_ide_api/src/completion/completion_context.rs | |||
@@ -1,4 +1,3 @@ | |||
1 | use hir::source_binder; | ||
2 | use ra_syntax::{ | 1 | use ra_syntax::{ |
3 | algo::{find_covering_element, find_node_at_offset}, | 2 | algo::{find_covering_element, find_node_at_offset}, |
4 | ast, AstNode, Parse, SourceFile, | 3 | ast, AstNode, Parse, SourceFile, |
@@ -47,7 +46,11 @@ impl<'a> CompletionContext<'a> { | |||
47 | original_parse: &'a Parse<ast::SourceFile>, | 46 | original_parse: &'a Parse<ast::SourceFile>, |
48 | position: FilePosition, | 47 | position: FilePosition, |
49 | ) -> Option<CompletionContext<'a>> { | 48 | ) -> Option<CompletionContext<'a>> { |
50 | let module = source_binder::module_from_position(db, position); | 49 | let src = hir::ModuleSource::from_position(db, position); |
50 | let module = hir::Module::from_definition( | ||
51 | db, | ||
52 | hir::Source { file_id: position.file_id.into(), ast: src }, | ||
53 | ); | ||
51 | let token = | 54 | let token = |
52 | original_parse.tree().syntax().token_at_offset(position.offset).left_biased()?; | 55 | original_parse.tree().syntax().token_at_offset(position.offset).left_biased()?; |
53 | let analyzer = | 56 | let analyzer = |
diff --git a/crates/ra_ide_api/src/diagnostics.rs b/crates/ra_ide_api/src/diagnostics.rs index c448aa8c5..1ae152e5b 100644 --- a/crates/ra_ide_api/src/diagnostics.rs +++ b/crates/ra_ide_api/src/diagnostics.rs | |||
@@ -1,9 +1,6 @@ | |||
1 | use std::cell::RefCell; | 1 | use std::cell::RefCell; |
2 | 2 | ||
3 | use hir::{ | 3 | use hir::diagnostics::{AstDiagnostic, Diagnostic as _, DiagnosticSink}; |
4 | diagnostics::{AstDiagnostic, Diagnostic as _, DiagnosticSink}, | ||
5 | source_binder, | ||
6 | }; | ||
7 | use itertools::Itertools; | 4 | use itertools::Itertools; |
8 | use ra_assists::ast_editor::{AstBuilder, AstEditor}; | 5 | use ra_assists::ast_editor::{AstBuilder, AstEditor}; |
9 | use ra_db::SourceDatabase; | 6 | use ra_db::SourceDatabase; |
@@ -89,7 +86,10 @@ pub(crate) fn diagnostics(db: &RootDatabase, file_id: FileId) -> Vec<Diagnostic> | |||
89 | fix: Some(fix), | 86 | fix: Some(fix), |
90 | }) | 87 | }) |
91 | }); | 88 | }); |
92 | if let Some(m) = source_binder::module_from_file_id(db, file_id) { | 89 | let source_file = db.parse(file_id).tree().to_owned(); |
90 | let src = | ||
91 | hir::Source { file_id: file_id.into(), ast: hir::ModuleSource::SourceFile(source_file) }; | ||
92 | if let Some(m) = hir::Module::from_definition(db, src) { | ||
93 | m.diagnostics(db, &mut sink); | 93 | m.diagnostics(db, &mut sink); |
94 | }; | 94 | }; |
95 | drop(sink); | 95 | drop(sink); |
diff --git a/crates/ra_ide_api/src/goto_definition.rs b/crates/ra_ide_api/src/goto_definition.rs index 503dcacff..bc8863dad 100644 --- a/crates/ra_ide_api/src/goto_definition.rs +++ b/crates/ra_ide_api/src/goto_definition.rs | |||
@@ -96,9 +96,8 @@ pub(crate) fn name_definition( | |||
96 | 96 | ||
97 | if let Some(module) = ast::Module::cast(parent.clone()) { | 97 | if let Some(module) = ast::Module::cast(parent.clone()) { |
98 | if module.has_semi() { | 98 | if module.has_semi() { |
99 | if let Some(child_module) = | 99 | let src = hir::Source { file_id: file_id.into(), ast: module }; |
100 | hir::source_binder::module_from_declaration(db, file_id, module) | 100 | if let Some(child_module) = hir::Module::from_declaration(db, src) { |
101 | { | ||
102 | let nav = NavigationTarget::from_module(db, child_module); | 101 | let nav = NavigationTarget::from_module(db, child_module); |
103 | return Some(vec![nav]); | 102 | return Some(vec![nav]); |
104 | } | 103 | } |
diff --git a/crates/ra_ide_api/src/impls.rs b/crates/ra_ide_api/src/impls.rs index c5620dd52..f57f9a21b 100644 --- a/crates/ra_ide_api/src/impls.rs +++ b/crates/ra_ide_api/src/impls.rs | |||
@@ -1,4 +1,4 @@ | |||
1 | use hir::{db::HirDatabase, source_binder, ApplicationTy, Ty, TypeCtor}; | 1 | use hir::{db::HirDatabase, ApplicationTy, FromSource, Ty, TypeCtor}; |
2 | use ra_db::SourceDatabase; | 2 | use ra_db::SourceDatabase; |
3 | use ra_syntax::{algo::find_node_at_offset, ast, AstNode}; | 3 | use ra_syntax::{algo::find_node_at_offset, ast, AstNode}; |
4 | 4 | ||
@@ -11,17 +11,21 @@ pub(crate) fn goto_implementation( | |||
11 | let parse = db.parse(position.file_id); | 11 | let parse = db.parse(position.file_id); |
12 | let syntax = parse.tree().syntax().clone(); | 12 | let syntax = parse.tree().syntax().clone(); |
13 | 13 | ||
14 | let module = source_binder::module_from_position(db, position)?; | 14 | let src = hir::ModuleSource::from_position(db, position); |
15 | let module = hir::Module::from_definition( | ||
16 | db, | ||
17 | hir::Source { file_id: position.file_id.into(), ast: src }, | ||
18 | )?; | ||
15 | 19 | ||
16 | if let Some(nominal_def) = find_node_at_offset::<ast::NominalDef>(&syntax, position.offset) { | 20 | if let Some(nominal_def) = find_node_at_offset::<ast::NominalDef>(&syntax, position.offset) { |
17 | return Some(RangeInfo::new( | 21 | return Some(RangeInfo::new( |
18 | nominal_def.syntax().text_range(), | 22 | nominal_def.syntax().text_range(), |
19 | impls_for_def(db, &nominal_def, module)?, | 23 | impls_for_def(db, position, &nominal_def, module)?, |
20 | )); | 24 | )); |
21 | } else if let Some(trait_def) = find_node_at_offset::<ast::TraitDef>(&syntax, position.offset) { | 25 | } else if let Some(trait_def) = find_node_at_offset::<ast::TraitDef>(&syntax, position.offset) { |
22 | return Some(RangeInfo::new( | 26 | return Some(RangeInfo::new( |
23 | trait_def.syntax().text_range(), | 27 | trait_def.syntax().text_range(), |
24 | impls_for_trait(db, &trait_def, module)?, | 28 | impls_for_trait(db, position, &trait_def, module)?, |
25 | )); | 29 | )); |
26 | } | 30 | } |
27 | 31 | ||
@@ -30,14 +34,19 @@ pub(crate) fn goto_implementation( | |||
30 | 34 | ||
31 | fn impls_for_def( | 35 | fn impls_for_def( |
32 | db: &RootDatabase, | 36 | db: &RootDatabase, |
37 | position: FilePosition, | ||
33 | node: &ast::NominalDef, | 38 | node: &ast::NominalDef, |
34 | module: hir::Module, | 39 | module: hir::Module, |
35 | ) -> Option<Vec<NavigationTarget>> { | 40 | ) -> Option<Vec<NavigationTarget>> { |
36 | let ty = match node { | 41 | let ty = match node { |
37 | ast::NominalDef::StructDef(def) => { | 42 | ast::NominalDef::StructDef(def) => { |
38 | source_binder::struct_from_module(db, module, &def).ty(db) | 43 | let src = hir::Source { file_id: position.file_id.into(), ast: def.clone() }; |
44 | hir::Struct::from_source(db, src)?.ty(db) | ||
45 | } | ||
46 | ast::NominalDef::EnumDef(def) => { | ||
47 | let src = hir::Source { file_id: position.file_id.into(), ast: def.clone() }; | ||
48 | hir::Enum::from_source(db, src)?.ty(db) | ||
39 | } | 49 | } |
40 | ast::NominalDef::EnumDef(def) => source_binder::enum_from_module(db, module, &def).ty(db), | ||
41 | }; | 50 | }; |
42 | 51 | ||
43 | let krate = module.krate(db)?; | 52 | let krate = module.krate(db)?; |
@@ -54,10 +63,12 @@ fn impls_for_def( | |||
54 | 63 | ||
55 | fn impls_for_trait( | 64 | fn impls_for_trait( |
56 | db: &RootDatabase, | 65 | db: &RootDatabase, |
66 | position: FilePosition, | ||
57 | node: &ast::TraitDef, | 67 | node: &ast::TraitDef, |
58 | module: hir::Module, | 68 | module: hir::Module, |
59 | ) -> Option<Vec<NavigationTarget>> { | 69 | ) -> Option<Vec<NavigationTarget>> { |
60 | let tr = source_binder::trait_from_module(db, module, node); | 70 | let src = hir::Source { file_id: position.file_id.into(), ast: node.clone() }; |
71 | let tr = hir::Trait::from_source(db, src)?; | ||
61 | 72 | ||
62 | let krate = module.krate(db)?; | 73 | let krate = module.krate(db)?; |
63 | let impls = db.impls_in_crate(krate); | 74 | let impls = db.impls_in_crate(krate); |
diff --git a/crates/ra_ide_api/src/parent_module.rs b/crates/ra_ide_api/src/parent_module.rs index 7d5f9ea2c..3668da8d7 100644 --- a/crates/ra_ide_api/src/parent_module.rs +++ b/crates/ra_ide_api/src/parent_module.rs | |||
@@ -5,7 +5,11 @@ use crate::{db::RootDatabase, NavigationTarget}; | |||
5 | /// This returns `Vec` because a module may be included from several places. We | 5 | /// This returns `Vec` because a module may be included from several places. We |
6 | /// don't handle this case yet though, so the Vec has length at most one. | 6 | /// don't handle this case yet though, so the Vec has length at most one. |
7 | pub(crate) fn parent_module(db: &RootDatabase, position: FilePosition) -> Vec<NavigationTarget> { | 7 | pub(crate) fn parent_module(db: &RootDatabase, position: FilePosition) -> Vec<NavigationTarget> { |
8 | let module = match hir::source_binder::module_from_position(db, position) { | 8 | let src = hir::ModuleSource::from_position(db, position); |
9 | let module = match hir::Module::from_definition( | ||
10 | db, | ||
11 | hir::Source { file_id: position.file_id.into(), ast: src }, | ||
12 | ) { | ||
9 | None => return Vec::new(), | 13 | None => return Vec::new(), |
10 | Some(it) => it, | 14 | Some(it) => it, |
11 | }; | 15 | }; |
@@ -15,10 +19,12 @@ pub(crate) fn parent_module(db: &RootDatabase, position: FilePosition) -> Vec<Na | |||
15 | 19 | ||
16 | /// Returns `Vec` for the same reason as `parent_module` | 20 | /// Returns `Vec` for the same reason as `parent_module` |
17 | pub(crate) fn crate_for(db: &RootDatabase, file_id: FileId) -> Vec<CrateId> { | 21 | pub(crate) fn crate_for(db: &RootDatabase, file_id: FileId) -> Vec<CrateId> { |
18 | let module = match hir::source_binder::module_from_file_id(db, file_id) { | 22 | let src = hir::ModuleSource::from_file_id(db, file_id); |
19 | Some(it) => it, | 23 | let module = |
20 | None => return Vec::new(), | 24 | match hir::Module::from_definition(db, hir::Source { file_id: file_id.into(), ast: src }) { |
21 | }; | 25 | Some(it) => it, |
26 | None => return Vec::new(), | ||
27 | }; | ||
22 | let krate = match module.krate(db) { | 28 | let krate = match module.krate(db) { |
23 | Some(it) => it, | 29 | Some(it) => it, |
24 | None => return Vec::new(), | 30 | None => return Vec::new(), |
diff --git a/crates/ra_ide_api/src/references.rs b/crates/ra_ide_api/src/references.rs index 5f1f0efc3..acca71f2a 100644 --- a/crates/ra_ide_api/src/references.rs +++ b/crates/ra_ide_api/src/references.rs | |||
@@ -1,4 +1,4 @@ | |||
1 | use hir::{source_binder, Either, ModuleSource}; | 1 | use hir::{Either, ModuleSource}; |
2 | use ra_db::SourceDatabase; | 2 | use ra_db::SourceDatabase; |
3 | use ra_syntax::{algo::find_node_at_offset, ast, AstNode, SourceFile, SyntaxNode}; | 3 | use ra_syntax::{algo::find_node_at_offset, ast, AstNode, SourceFile, SyntaxNode}; |
4 | use relative_path::{RelativePath, RelativePathBuf}; | 4 | use relative_path::{RelativePath, RelativePathBuf}; |
@@ -135,9 +135,8 @@ fn rename_mod( | |||
135 | ) -> Option<SourceChange> { | 135 | ) -> Option<SourceChange> { |
136 | let mut source_file_edits = Vec::new(); | 136 | let mut source_file_edits = Vec::new(); |
137 | let mut file_system_edits = Vec::new(); | 137 | let mut file_system_edits = Vec::new(); |
138 | if let Some(module) = | 138 | let module_src = hir::Source { file_id: position.file_id.into(), ast: ast_module.clone() }; |
139 | source_binder::module_from_declaration(db, position.file_id, ast_module.clone()) | 139 | if let Some(module) = hir::Module::from_declaration(db, module_src) { |
140 | { | ||
141 | let src = module.definition_source(db); | 140 | let src = module.definition_source(db); |
142 | let file_id = src.file_id.as_original_file(); | 141 | let file_id = src.file_id.as_original_file(); |
143 | match src.ast { | 142 | match src.ast { |
diff --git a/crates/ra_ide_api/src/runnables.rs b/crates/ra_ide_api/src/runnables.rs index 9d84b3d08..095ca56c4 100644 --- a/crates/ra_ide_api/src/runnables.rs +++ b/crates/ra_ide_api/src/runnables.rs | |||
@@ -63,7 +63,9 @@ fn runnable_mod(db: &RootDatabase, file_id: FileId, module: ast::Module) -> Opti | |||
63 | return None; | 63 | return None; |
64 | } | 64 | } |
65 | let range = module.syntax().text_range(); | 65 | let range = module.syntax().text_range(); |
66 | let module = hir::source_binder::module_from_child_node(db, file_id, module.syntax())?; | 66 | let src = hir::ModuleSource::from_child_node(db, file_id, &module.syntax()); |
67 | let module = | ||
68 | hir::Module::from_definition(db, hir::Source { file_id: file_id.into(), ast: src })?; | ||
67 | 69 | ||
68 | let path = module.path_to_root(db).into_iter().rev().filter_map(|it| it.name(db)).join("::"); | 70 | let path = module.path_to_root(db).into_iter().rev().filter_map(|it| it.name(db)).join("::"); |
69 | Some(Runnable { range, kind: RunnableKind::TestMod { path } }) | 71 | Some(Runnable { range, kind: RunnableKind::TestMod { path } }) |