diff options
author | bors[bot] <26634292+bors[bot]@users.noreply.github.com> | 2020-01-16 16:58:13 +0000 |
---|---|---|
committer | GitHub <[email protected]> | 2020-01-16 16:58:13 +0000 |
commit | d3c4fbbbc45afc7d480185493b5ce77b5daa1747 (patch) | |
tree | aa12838a1b0c45710bb7657f6f3c34947519484c | |
parent | e614356de10256c64e02f5d0f82cfa39e27b0f07 (diff) | |
parent | 846f11c2177f3e3a6348acb67503028180b3c1f8 (diff) |
Merge #2862
2862: Move from `from_source` to `SourceBinder` r=matklad a=matklad
bors r+
Co-authored-by: Aleksey Kladov <[email protected]>
-rw-r--r-- | crates/ra_assists/src/assist_ctx.rs | 8 | ||||
-rw-r--r-- | crates/ra_assists/src/assists/add_new.rs | 7 | ||||
-rw-r--r-- | crates/ra_hir/src/from_source.rs | 265 | ||||
-rw-r--r-- | crates/ra_hir/src/lib.rs | 2 | ||||
-rw-r--r-- | crates/ra_hir/src/source_binder.rs | 252 | ||||
-rw-r--r-- | crates/ra_hir_def/src/keys.rs | 4 | ||||
-rw-r--r-- | crates/ra_hir_def/src/nameres.rs | 36 | ||||
-rw-r--r-- | crates/ra_ide/src/completion/completion_context.rs | 10 | ||||
-rw-r--r-- | crates/ra_ide/src/diagnostics.rs | 6 | ||||
-rw-r--r-- | crates/ra_ide/src/goto_definition.rs | 38 | ||||
-rw-r--r-- | crates/ra_ide/src/impls.rs | 43 | ||||
-rw-r--r-- | crates/ra_ide/src/parent_module.rs | 29 | ||||
-rw-r--r-- | crates/ra_ide/src/references/classify.rs | 28 | ||||
-rw-r--r-- | crates/ra_ide/src/references/name_definition.rs | 2 | ||||
-rw-r--r-- | crates/ra_ide/src/references/rename.rs | 2 | ||||
-rw-r--r-- | crates/ra_ide/src/runnables.rs | 4 |
16 files changed, 306 insertions, 430 deletions
diff --git a/crates/ra_assists/src/assist_ctx.rs b/crates/ra_assists/src/assist_ctx.rs index 9d533fa0c..43f0d664b 100644 --- a/crates/ra_assists/src/assist_ctx.rs +++ b/crates/ra_assists/src/assist_ctx.rs | |||
@@ -1,6 +1,6 @@ | |||
1 | //! This module defines `AssistCtx` -- the API surface that is exposed to assists. | 1 | //! This module defines `AssistCtx` -- the API surface that is exposed to assists. |
2 | use either::Either; | 2 | use either::Either; |
3 | use hir::{db::HirDatabase, InFile, SourceAnalyzer}; | 3 | use hir::{db::HirDatabase, InFile, SourceAnalyzer, SourceBinder}; |
4 | use ra_db::FileRange; | 4 | use ra_db::FileRange; |
5 | use ra_fmt::{leading_indent, reindent}; | 5 | use ra_fmt::{leading_indent, reindent}; |
6 | use ra_syntax::{ | 6 | use ra_syntax::{ |
@@ -142,12 +142,16 @@ impl<'a, DB: HirDatabase> AssistCtx<'a, DB> { | |||
142 | pub(crate) fn covering_element(&self) -> SyntaxElement { | 142 | pub(crate) fn covering_element(&self) -> SyntaxElement { |
143 | find_covering_element(self.source_file.syntax(), self.frange.range) | 143 | find_covering_element(self.source_file.syntax(), self.frange.range) |
144 | } | 144 | } |
145 | pub(crate) fn source_binder(&self) -> SourceBinder<'a, DB> { | ||
146 | SourceBinder::new(self.db) | ||
147 | } | ||
145 | pub(crate) fn source_analyzer( | 148 | pub(crate) fn source_analyzer( |
146 | &self, | 149 | &self, |
147 | node: &SyntaxNode, | 150 | node: &SyntaxNode, |
148 | offset: Option<TextUnit>, | 151 | offset: Option<TextUnit>, |
149 | ) -> SourceAnalyzer { | 152 | ) -> SourceAnalyzer { |
150 | SourceAnalyzer::new(self.db, InFile::new(self.frange.file_id.into(), node), offset) | 153 | let src = InFile::new(self.frange.file_id.into(), node); |
154 | self.source_binder().analyze(src, offset) | ||
151 | } | 155 | } |
152 | 156 | ||
153 | pub(crate) fn covering_node_for_range(&self, range: TextRange) -> SyntaxElement { | 157 | pub(crate) fn covering_node_for_range(&self, range: TextRange) -> SyntaxElement { |
diff --git a/crates/ra_assists/src/assists/add_new.rs b/crates/ra_assists/src/assists/add_new.rs index d148d6e73..8db63f762 100644 --- a/crates/ra_assists/src/assists/add_new.rs +++ b/crates/ra_assists/src/assists/add_new.rs | |||
@@ -1,5 +1,5 @@ | |||
1 | use format_buf::format; | 1 | use format_buf::format; |
2 | use hir::{db::HirDatabase, FromSource, InFile}; | 2 | use hir::{db::HirDatabase, InFile}; |
3 | use join_to_string::join; | 3 | use join_to_string::join; |
4 | use ra_syntax::{ | 4 | use ra_syntax::{ |
5 | ast::{ | 5 | ast::{ |
@@ -136,15 +136,16 @@ fn find_struct_impl( | |||
136 | let module = strukt.syntax().ancestors().find(|node| { | 136 | let module = strukt.syntax().ancestors().find(|node| { |
137 | ast::Module::can_cast(node.kind()) || ast::SourceFile::can_cast(node.kind()) | 137 | ast::Module::can_cast(node.kind()) || ast::SourceFile::can_cast(node.kind()) |
138 | })?; | 138 | })?; |
139 | let mut sb = ctx.source_binder(); | ||
139 | 140 | ||
140 | let struct_ty = { | 141 | let struct_ty = { |
141 | let src = InFile { file_id: ctx.frange.file_id.into(), value: strukt.clone() }; | 142 | let src = InFile { file_id: ctx.frange.file_id.into(), value: strukt.clone() }; |
142 | hir::Struct::from_source(db, src)?.ty(db) | 143 | sb.to_def(src)?.ty(db) |
143 | }; | 144 | }; |
144 | 145 | ||
145 | let block = module.descendants().filter_map(ast::ImplBlock::cast).find_map(|impl_blk| { | 146 | let block = module.descendants().filter_map(ast::ImplBlock::cast).find_map(|impl_blk| { |
146 | let src = InFile { file_id: ctx.frange.file_id.into(), value: impl_blk.clone() }; | 147 | let src = InFile { file_id: ctx.frange.file_id.into(), value: impl_blk.clone() }; |
147 | let blk = hir::ImplBlock::from_source(db, src)?; | 148 | let blk = sb.to_def(src)?; |
148 | 149 | ||
149 | let same_ty = blk.target_ty(db) == struct_ty; | 150 | let same_ty = blk.target_ty(db) == struct_ty; |
150 | let not_trait_impl = blk.target_trait(db).is_none(); | 151 | let not_trait_impl = blk.target_trait(db).is_none(); |
diff --git a/crates/ra_hir/src/from_source.rs b/crates/ra_hir/src/from_source.rs deleted file mode 100644 index 6314be8d4..000000000 --- a/crates/ra_hir/src/from_source.rs +++ /dev/null | |||
@@ -1,265 +0,0 @@ | |||
1 | //! Finds a corresponding hir data structure for a syntax node in a specific | ||
2 | //! file. | ||
3 | |||
4 | use hir_def::{ | ||
5 | child_by_source::ChildBySource, dyn_map::DynMap, keys, keys::Key, nameres::ModuleSource, | ||
6 | ConstId, DefWithBodyId, EnumId, EnumVariantId, FunctionId, GenericDefId, ImplId, ModuleId, | ||
7 | StaticId, StructId, TraitId, TypeAliasId, UnionId, VariantId, | ||
8 | }; | ||
9 | use hir_expand::{name::AsName, AstId, MacroDefId, MacroDefKind}; | ||
10 | use ra_db::FileId; | ||
11 | use ra_prof::profile; | ||
12 | use ra_syntax::{ | ||
13 | ast::{self, AstNode, NameOwner}, | ||
14 | match_ast, SyntaxNode, | ||
15 | }; | ||
16 | |||
17 | use crate::{ | ||
18 | db::{DefDatabase, HirDatabase}, | ||
19 | Const, DefWithBody, Enum, EnumVariant, FieldSource, Function, ImplBlock, InFile, Local, | ||
20 | MacroDef, Module, Static, Struct, StructField, Trait, TypeAlias, TypeParam, Union, | ||
21 | }; | ||
22 | |||
23 | pub trait FromSource: Sized { | ||
24 | type Ast; | ||
25 | fn from_source(db: &impl DefDatabase, src: InFile<Self::Ast>) -> Option<Self>; | ||
26 | } | ||
27 | |||
28 | pub trait FromSourceByContainer: Sized { | ||
29 | type Ast: AstNode + 'static; | ||
30 | type Id: Copy + 'static; | ||
31 | const KEY: Key<Self::Ast, Self::Id>; | ||
32 | } | ||
33 | |||
34 | impl<T: FromSourceByContainer> FromSource for T | ||
35 | where | ||
36 | T: From<<T as FromSourceByContainer>::Id>, | ||
37 | { | ||
38 | type Ast = <T as FromSourceByContainer>::Ast; | ||
39 | fn from_source(db: &impl DefDatabase, src: InFile<Self::Ast>) -> Option<Self> { | ||
40 | analyze_container(db, src.as_ref().map(|it| it.syntax()))[T::KEY] | ||
41 | .get(&src) | ||
42 | .copied() | ||
43 | .map(Self::from) | ||
44 | } | ||
45 | } | ||
46 | |||
47 | macro_rules! from_source_by_container_impls { | ||
48 | ($(($hir:ident, $id:ident, $ast:path, $key:path)),* ,) => {$( | ||
49 | impl FromSourceByContainer for $hir { | ||
50 | type Ast = $ast; | ||
51 | type Id = $id; | ||
52 | const KEY: Key<Self::Ast, Self::Id> = $key; | ||
53 | } | ||
54 | )*} | ||
55 | } | ||
56 | |||
57 | from_source_by_container_impls![ | ||
58 | (Struct, StructId, ast::StructDef, keys::STRUCT), | ||
59 | (Union, UnionId, ast::UnionDef, keys::UNION), | ||
60 | (Enum, EnumId, ast::EnumDef, keys::ENUM), | ||
61 | (Trait, TraitId, ast::TraitDef, keys::TRAIT), | ||
62 | (Function, FunctionId, ast::FnDef, keys::FUNCTION), | ||
63 | (Static, StaticId, ast::StaticDef, keys::STATIC), | ||
64 | (Const, ConstId, ast::ConstDef, keys::CONST), | ||
65 | (TypeAlias, TypeAliasId, ast::TypeAliasDef, keys::TYPE_ALIAS), | ||
66 | (ImplBlock, ImplId, ast::ImplBlock, keys::IMPL), | ||
67 | ]; | ||
68 | |||
69 | impl FromSource for MacroDef { | ||
70 | type Ast = ast::MacroCall; | ||
71 | fn from_source(db: &impl DefDatabase, src: InFile<Self::Ast>) -> Option<Self> { | ||
72 | let kind = MacroDefKind::Declarative; | ||
73 | |||
74 | let module_src = ModuleSource::from_child_node(db, src.as_ref().map(|it| it.syntax())); | ||
75 | let module = Module::from_definition(db, InFile::new(src.file_id, module_src))?; | ||
76 | let krate = Some(module.krate().id); | ||
77 | |||
78 | let ast_id = Some(AstId::new(src.file_id, db.ast_id_map(src.file_id).ast_id(&src.value))); | ||
79 | |||
80 | let id: MacroDefId = MacroDefId { krate, ast_id, kind }; | ||
81 | Some(MacroDef { id }) | ||
82 | } | ||
83 | } | ||
84 | |||
85 | impl FromSource for EnumVariant { | ||
86 | type Ast = ast::EnumVariant; | ||
87 | fn from_source(db: &impl DefDatabase, src: InFile<Self::Ast>) -> Option<Self> { | ||
88 | let parent_enum = src.value.parent_enum(); | ||
89 | let src_enum = InFile { file_id: src.file_id, value: parent_enum }; | ||
90 | let parent_enum = Enum::from_source(db, src_enum)?; | ||
91 | parent_enum.id.child_by_source(db)[keys::ENUM_VARIANT] | ||
92 | .get(&src) | ||
93 | .copied() | ||
94 | .map(EnumVariant::from) | ||
95 | } | ||
96 | } | ||
97 | |||
98 | impl FromSource for StructField { | ||
99 | type Ast = FieldSource; | ||
100 | fn from_source(db: &impl DefDatabase, src: InFile<Self::Ast>) -> Option<Self> { | ||
101 | let src = src.as_ref(); | ||
102 | |||
103 | // FIXME this is buggy | ||
104 | let variant_id: VariantId = match src.value { | ||
105 | FieldSource::Named(field) => { | ||
106 | let value = field.syntax().ancestors().find_map(ast::StructDef::cast)?; | ||
107 | let src = InFile { file_id: src.file_id, value }; | ||
108 | let def = Struct::from_source(db, src)?; | ||
109 | def.id.into() | ||
110 | } | ||
111 | FieldSource::Pos(field) => { | ||
112 | let value = field.syntax().ancestors().find_map(ast::EnumVariant::cast)?; | ||
113 | let src = InFile { file_id: src.file_id, value }; | ||
114 | let def = EnumVariant::from_source(db, src)?; | ||
115 | EnumVariantId::from(def).into() | ||
116 | } | ||
117 | }; | ||
118 | |||
119 | let dyn_map = variant_id.child_by_source(db); | ||
120 | match src.value { | ||
121 | FieldSource::Pos(it) => dyn_map[keys::TUPLE_FIELD].get(&src.with_value(it.clone())), | ||
122 | FieldSource::Named(it) => dyn_map[keys::RECORD_FIELD].get(&src.with_value(it.clone())), | ||
123 | } | ||
124 | .copied() | ||
125 | .map(StructField::from) | ||
126 | } | ||
127 | } | ||
128 | |||
129 | impl Local { | ||
130 | pub fn from_source(db: &impl HirDatabase, src: InFile<ast::BindPat>) -> Option<Self> { | ||
131 | let file_id = src.file_id; | ||
132 | let parent: DefWithBody = src.value.syntax().ancestors().find_map(|it| { | ||
133 | let res = match_ast! { | ||
134 | match it { | ||
135 | ast::ConstDef(value) => { Const::from_source(db, InFile { value, file_id})?.into() }, | ||
136 | ast::StaticDef(value) => { Static::from_source(db, InFile { value, file_id})?.into() }, | ||
137 | ast::FnDef(value) => { Function::from_source(db, InFile { value, file_id})?.into() }, | ||
138 | _ => return None, | ||
139 | } | ||
140 | }; | ||
141 | Some(res) | ||
142 | })?; | ||
143 | let (_body, source_map) = db.body_with_source_map(parent.into()); | ||
144 | let src = src.map(ast::Pat::from); | ||
145 | let pat_id = source_map.node_pat(src.as_ref())?; | ||
146 | Some(Local { parent, pat_id }) | ||
147 | } | ||
148 | } | ||
149 | |||
150 | impl TypeParam { | ||
151 | pub fn from_source(db: &impl HirDatabase, src: InFile<ast::TypeParam>) -> Option<Self> { | ||
152 | let file_id = src.file_id; | ||
153 | let parent: GenericDefId = src.value.syntax().ancestors().find_map(|it| { | ||
154 | let res = match_ast! { | ||
155 | match it { | ||
156 | ast::FnDef(value) => { Function::from_source(db, InFile { value, file_id})?.id.into() }, | ||
157 | ast::StructDef(value) => { Struct::from_source(db, InFile { value, file_id})?.id.into() }, | ||
158 | ast::EnumDef(value) => { Enum::from_source(db, InFile { value, file_id})?.id.into() }, | ||
159 | ast::TraitDef(value) => { Trait::from_source(db, InFile { value, file_id})?.id.into() }, | ||
160 | ast::TypeAliasDef(value) => { TypeAlias::from_source(db, InFile { value, file_id})?.id.into() }, | ||
161 | ast::ImplBlock(value) => { ImplBlock::from_source(db, InFile { value, file_id})?.id.into() }, | ||
162 | _ => return None, | ||
163 | } | ||
164 | }; | ||
165 | Some(res) | ||
166 | })?; | ||
167 | let &id = parent.child_by_source(db)[keys::TYPE_PARAM].get(&src)?; | ||
168 | Some(TypeParam { id }) | ||
169 | } | ||
170 | } | ||
171 | |||
172 | impl Module { | ||
173 | pub fn from_declaration(db: &impl DefDatabase, src: InFile<ast::Module>) -> Option<Self> { | ||
174 | let _p = profile("Module::from_declaration"); | ||
175 | let parent_declaration = src.value.syntax().ancestors().skip(1).find_map(ast::Module::cast); | ||
176 | |||
177 | let parent_module = match parent_declaration { | ||
178 | Some(parent_declaration) => { | ||
179 | let src_parent = InFile { file_id: src.file_id, value: parent_declaration }; | ||
180 | Module::from_declaration(db, src_parent) | ||
181 | } | ||
182 | None => { | ||
183 | let source_file = db.parse(src.file_id.original_file(db)).tree(); | ||
184 | let src_parent = | ||
185 | InFile { file_id: src.file_id, value: ModuleSource::SourceFile(source_file) }; | ||
186 | Module::from_definition(db, src_parent) | ||
187 | } | ||
188 | }?; | ||
189 | |||
190 | let child_name = src.value.name()?.as_name(); | ||
191 | let def_map = db.crate_def_map(parent_module.id.krate); | ||
192 | let child_id = def_map[parent_module.id.local_id].children.get(&child_name)?; | ||
193 | Some(parent_module.with_module_id(*child_id)) | ||
194 | } | ||
195 | |||
196 | pub fn from_definition(db: &impl DefDatabase, src: InFile<ModuleSource>) -> Option<Self> { | ||
197 | let _p = profile("Module::from_definition"); | ||
198 | match src.value { | ||
199 | ModuleSource::Module(ref module) => { | ||
200 | assert!(!module.has_semi()); | ||
201 | return Module::from_declaration( | ||
202 | db, | ||
203 | InFile { file_id: src.file_id, value: module.clone() }, | ||
204 | ); | ||
205 | } | ||
206 | ModuleSource::SourceFile(_) => (), | ||
207 | }; | ||
208 | |||
209 | let original_file = src.file_id.original_file(db); | ||
210 | Module::from_file(db, original_file) | ||
211 | } | ||
212 | |||
213 | fn from_file(db: &impl DefDatabase, file: FileId) -> Option<Self> { | ||
214 | let _p = profile("Module::from_file"); | ||
215 | let (krate, local_id) = db.relevant_crates(file).iter().find_map(|&crate_id| { | ||
216 | let crate_def_map = db.crate_def_map(crate_id); | ||
217 | let local_id = crate_def_map.modules_for_file(file).next()?; | ||
218 | Some((crate_id, local_id)) | ||
219 | })?; | ||
220 | Some(Module { id: ModuleId { krate, local_id } }) | ||
221 | } | ||
222 | } | ||
223 | |||
224 | fn analyze_container(db: &impl DefDatabase, src: InFile<&SyntaxNode>) -> DynMap { | ||
225 | let _p = profile("analyze_container"); | ||
226 | return child_by_source(db, src).unwrap_or_default(); | ||
227 | |||
228 | fn child_by_source(db: &impl DefDatabase, src: InFile<&SyntaxNode>) -> Option<DynMap> { | ||
229 | for container in src.value.ancestors().skip(1) { | ||
230 | let res = match_ast! { | ||
231 | match container { | ||
232 | ast::TraitDef(it) => { | ||
233 | let def = Trait::from_source(db, src.with_value(it))?; | ||
234 | def.id.child_by_source(db) | ||
235 | }, | ||
236 | ast::ImplBlock(it) => { | ||
237 | let def = ImplBlock::from_source(db, src.with_value(it))?; | ||
238 | def.id.child_by_source(db) | ||
239 | }, | ||
240 | ast::FnDef(it) => { | ||
241 | let def = Function::from_source(db, src.with_value(it))?; | ||
242 | DefWithBodyId::from(def.id) | ||
243 | .child_by_source(db) | ||
244 | }, | ||
245 | ast::StaticDef(it) => { | ||
246 | let def = Static::from_source(db, src.with_value(it))?; | ||
247 | DefWithBodyId::from(def.id) | ||
248 | .child_by_source(db) | ||
249 | }, | ||
250 | ast::ConstDef(it) => { | ||
251 | let def = Const::from_source(db, src.with_value(it))?; | ||
252 | DefWithBodyId::from(def.id) | ||
253 | .child_by_source(db) | ||
254 | }, | ||
255 | _ => { continue }, | ||
256 | } | ||
257 | }; | ||
258 | return Some(res); | ||
259 | } | ||
260 | |||
261 | let module_source = ModuleSource::from_child_node(db, src); | ||
262 | let c = Module::from_definition(db, src.with_value(module_source))?; | ||
263 | Some(c.id.child_by_source(db)) | ||
264 | } | ||
265 | } | ||
diff --git a/crates/ra_hir/src/lib.rs b/crates/ra_hir/src/lib.rs index a2350573c..e1c7b7a20 100644 --- a/crates/ra_hir/src/lib.rs +++ b/crates/ra_hir/src/lib.rs | |||
@@ -36,7 +36,6 @@ mod from_id; | |||
36 | mod code_model; | 36 | mod code_model; |
37 | 37 | ||
38 | mod has_source; | 38 | mod has_source; |
39 | mod from_source; | ||
40 | 39 | ||
41 | pub use crate::{ | 40 | pub use crate::{ |
42 | code_model::{ | 41 | code_model::{ |
@@ -45,7 +44,6 @@ pub use crate::{ | |||
45 | MacroDef, Module, ModuleDef, ScopeDef, Static, Struct, StructField, Trait, Type, TypeAlias, | 44 | MacroDef, Module, ModuleDef, ScopeDef, Static, Struct, StructField, Trait, Type, TypeAlias, |
46 | TypeParam, Union, VariantDef, | 45 | TypeParam, Union, VariantDef, |
47 | }, | 46 | }, |
48 | from_source::FromSource, | ||
49 | has_source::HasSource, | 47 | has_source::HasSource, |
50 | source_analyzer::{PathResolution, ScopeEntryWithSyntax, SourceAnalyzer}, | 48 | source_analyzer::{PathResolution, ScopeEntryWithSyntax, SourceAnalyzer}, |
51 | source_binder::SourceBinder, | 49 | source_binder::SourceBinder, |
diff --git a/crates/ra_hir/src/source_binder.rs b/crates/ra_hir/src/source_binder.rs index 00541dbe1..f3150f578 100644 --- a/crates/ra_hir/src/source_binder.rs +++ b/crates/ra_hir/src/source_binder.rs | |||
@@ -1,22 +1,24 @@ | |||
1 | //! `SourceBinder` should be the main entry point for getting info about source code. | 1 | //! `SourceBinder` is the main entry point for getting info about source code. |
2 | //! It's main task is to map source syntax trees to hir-level IDs. | 2 | //! It's main task is to map source syntax trees to hir-level IDs. |
3 | //! | ||
4 | //! It is intended to subsume `FromSource` and `SourceAnalyzer`. | ||
5 | 3 | ||
6 | use hir_def::{ | 4 | use hir_def::{ |
7 | child_by_source::ChildBySource, | 5 | child_by_source::ChildBySource, |
8 | dyn_map::DynMap, | 6 | dyn_map::DynMap, |
9 | keys::{self, Key}, | 7 | keys::{self, Key}, |
10 | resolver::{HasResolver, Resolver}, | 8 | resolver::{HasResolver, Resolver}, |
11 | ConstId, DefWithBodyId, EnumId, EnumVariantId, FunctionId, ImplId, ModuleId, StaticId, | 9 | ConstId, DefWithBodyId, EnumId, EnumVariantId, FunctionId, GenericDefId, ImplId, ModuleId, |
12 | StructFieldId, StructId, TraitId, TypeAliasId, UnionId, VariantId, | 10 | StaticId, StructFieldId, StructId, TraitId, TypeAliasId, UnionId, VariantId, |
13 | }; | 11 | }; |
14 | use hir_expand::InFile; | 12 | use hir_expand::{name::AsName, AstId, InFile, MacroDefId, MacroDefKind}; |
15 | use ra_prof::profile; | 13 | use ra_prof::profile; |
16 | use ra_syntax::{ast, match_ast, AstNode, SyntaxNode, TextUnit}; | 14 | use ra_syntax::{ |
15 | ast::{self, NameOwner}, | ||
16 | match_ast, AstNode, SyntaxNode, TextUnit, | ||
17 | }; | ||
17 | use rustc_hash::FxHashMap; | 18 | use rustc_hash::FxHashMap; |
18 | 19 | ||
19 | use crate::{db::HirDatabase, ModuleSource, SourceAnalyzer}; | 20 | use crate::{db::HirDatabase, Local, Module, SourceAnalyzer, TypeParam}; |
21 | use ra_db::FileId; | ||
20 | 22 | ||
21 | pub struct SourceBinder<'a, DB> { | 23 | pub struct SourceBinder<'a, DB> { |
22 | pub db: &'a DB, | 24 | pub db: &'a DB, |
@@ -48,32 +50,27 @@ impl<DB: HirDatabase> SourceBinder<'_, DB> { | |||
48 | ChildContainer::ModuleId(it) => it.resolver(self.db), | 50 | ChildContainer::ModuleId(it) => it.resolver(self.db), |
49 | ChildContainer::EnumId(it) => it.resolver(self.db), | 51 | ChildContainer::EnumId(it) => it.resolver(self.db), |
50 | ChildContainer::VariantId(it) => it.resolver(self.db), | 52 | ChildContainer::VariantId(it) => it.resolver(self.db), |
53 | ChildContainer::GenericDefId(it) => it.resolver(self.db), | ||
51 | }; | 54 | }; |
52 | SourceAnalyzer::new_for_resolver(resolver, src) | 55 | SourceAnalyzer::new_for_resolver(resolver, src) |
53 | } | 56 | } |
54 | 57 | ||
55 | pub fn to_def<D, T>(&mut self, src: InFile<T>) -> Option<D> | 58 | pub fn to_def<T: ToDef>(&mut self, src: InFile<T>) -> Option<T::Def> { |
56 | where | 59 | T::to_def(self, src) |
57 | D: From<T::ID>, | 60 | } |
58 | T: ToId, | 61 | |
59 | { | 62 | pub fn to_module_def(&mut self, file: FileId) -> Option<Module> { |
60 | let id: T::ID = self.to_id(src)?; | 63 | let _p = profile("SourceBinder::to_module_def"); |
61 | Some(id.into()) | 64 | let (krate, local_id) = self.db.relevant_crates(file).iter().find_map(|&crate_id| { |
65 | let crate_def_map = self.db.crate_def_map(crate_id); | ||
66 | let local_id = crate_def_map.modules_for_file(file).next()?; | ||
67 | Some((crate_id, local_id)) | ||
68 | })?; | ||
69 | Some(Module { id: ModuleId { krate, local_id } }) | ||
62 | } | 70 | } |
63 | 71 | ||
64 | fn to_id<T: ToId>(&mut self, src: InFile<T>) -> Option<T::ID> { | 72 | fn to_id<T: ToId>(&mut self, src: InFile<T>) -> Option<T::ID> { |
65 | let container = self.find_container(src.as_ref().map(|it| it.syntax()))?; | 73 | T::to_id(self, src) |
66 | let db = self.db; | ||
67 | let dyn_map = | ||
68 | &*self.child_by_source_cache.entry(container).or_insert_with(|| match container { | ||
69 | ChildContainer::DefWithBodyId(it) => it.child_by_source(db), | ||
70 | ChildContainer::ModuleId(it) => it.child_by_source(db), | ||
71 | ChildContainer::TraitId(it) => it.child_by_source(db), | ||
72 | ChildContainer::ImplId(it) => it.child_by_source(db), | ||
73 | ChildContainer::EnumId(it) => it.child_by_source(db), | ||
74 | ChildContainer::VariantId(it) => it.child_by_source(db), | ||
75 | }); | ||
76 | dyn_map[T::KEY].get(&src).copied() | ||
77 | } | 74 | } |
78 | 75 | ||
79 | fn find_container(&mut self, src: InFile<&SyntaxNode>) -> Option<ChildContainer> { | 76 | fn find_container(&mut self, src: InFile<&SyntaxNode>) -> Option<ChildContainer> { |
@@ -112,19 +109,75 @@ impl<DB: HirDatabase> SourceBinder<'_, DB> { | |||
112 | let def: UnionId = self.to_id(container.with_value(it))?; | 109 | let def: UnionId = self.to_id(container.with_value(it))?; |
113 | VariantId::from(def).into() | 110 | VariantId::from(def).into() |
114 | }, | 111 | }, |
115 | // FIXME: handle out-of-line modules here | 112 | ast::Module(it) => { |
113 | let def: ModuleId = self.to_id(container.with_value(it))?; | ||
114 | def.into() | ||
115 | }, | ||
116 | _ => { continue }, | 116 | _ => { continue }, |
117 | } | 117 | } |
118 | }; | 118 | }; |
119 | return Some(res); | 119 | return Some(res); |
120 | } | 120 | } |
121 | 121 | ||
122 | let module_source = ModuleSource::from_child_node(self.db, src); | 122 | let c = self.to_module_def(src.file_id.original_file(self.db))?; |
123 | let c = crate::Module::from_definition(self.db, src.with_value(module_source))?; | ||
124 | Some(c.id.into()) | 123 | Some(c.id.into()) |
125 | } | 124 | } |
125 | |||
126 | fn child_by_source(&mut self, container: ChildContainer) -> &DynMap { | ||
127 | let db = self.db; | ||
128 | self.child_by_source_cache.entry(container).or_insert_with(|| match container { | ||
129 | ChildContainer::DefWithBodyId(it) => it.child_by_source(db), | ||
130 | ChildContainer::ModuleId(it) => it.child_by_source(db), | ||
131 | ChildContainer::TraitId(it) => it.child_by_source(db), | ||
132 | ChildContainer::ImplId(it) => it.child_by_source(db), | ||
133 | ChildContainer::EnumId(it) => it.child_by_source(db), | ||
134 | ChildContainer::VariantId(it) => it.child_by_source(db), | ||
135 | ChildContainer::GenericDefId(it) => it.child_by_source(db), | ||
136 | }) | ||
137 | } | ||
126 | } | 138 | } |
127 | 139 | ||
140 | pub trait ToId: Sized { | ||
141 | type ID: Sized + Copy + 'static; | ||
142 | fn to_id<DB: HirDatabase>(sb: &mut SourceBinder<'_, DB>, src: InFile<Self>) | ||
143 | -> Option<Self::ID>; | ||
144 | } | ||
145 | |||
146 | pub trait ToDef: Sized + AstNode + 'static { | ||
147 | type Def; | ||
148 | fn to_def<DB: HirDatabase>( | ||
149 | sb: &mut SourceBinder<'_, DB>, | ||
150 | src: InFile<Self>, | ||
151 | ) -> Option<Self::Def>; | ||
152 | } | ||
153 | |||
154 | macro_rules! to_def_impls { | ||
155 | ($(($def:path, $ast:path)),* ,) => {$( | ||
156 | impl ToDef for $ast { | ||
157 | type Def = $def; | ||
158 | fn to_def<DB: HirDatabase>(sb: &mut SourceBinder<'_, DB>, src: InFile<Self>) | ||
159 | -> Option<Self::Def> | ||
160 | { sb.to_id(src).map(Into::into) } | ||
161 | } | ||
162 | )*} | ||
163 | } | ||
164 | |||
165 | to_def_impls![ | ||
166 | (crate::Module, ast::Module), | ||
167 | (crate::Struct, ast::StructDef), | ||
168 | (crate::Enum, ast::EnumDef), | ||
169 | (crate::Union, ast::UnionDef), | ||
170 | (crate::Trait, ast::TraitDef), | ||
171 | (crate::ImplBlock, ast::ImplBlock), | ||
172 | (crate::TypeAlias, ast::TypeAliasDef), | ||
173 | (crate::Const, ast::ConstDef), | ||
174 | (crate::Static, ast::StaticDef), | ||
175 | (crate::Function, ast::FnDef), | ||
176 | (crate::StructField, ast::RecordFieldDef), | ||
177 | (crate::EnumVariant, ast::EnumVariant), | ||
178 | (crate::MacroDef, ast::MacroCall), // this one is dubious, not all calls are macros | ||
179 | ]; | ||
180 | |||
128 | #[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)] | 181 | #[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)] |
129 | enum ChildContainer { | 182 | enum ChildContainer { |
130 | DefWithBodyId(DefWithBodyId), | 183 | DefWithBodyId(DefWithBodyId), |
@@ -133,6 +186,9 @@ enum ChildContainer { | |||
133 | ImplId(ImplId), | 186 | ImplId(ImplId), |
134 | EnumId(EnumId), | 187 | EnumId(EnumId), |
135 | VariantId(VariantId), | 188 | VariantId(VariantId), |
189 | /// XXX: this might be the same def as, for example an `EnumId`. However, | ||
190 | /// here the children generic parameters, and not, eg enum variants. | ||
191 | GenericDefId(GenericDefId), | ||
136 | } | 192 | } |
137 | impl_froms! { | 193 | impl_froms! { |
138 | ChildContainer: | 194 | ChildContainer: |
@@ -142,23 +198,46 @@ impl_froms! { | |||
142 | ImplId, | 198 | ImplId, |
143 | EnumId, | 199 | EnumId, |
144 | VariantId, | 200 | VariantId, |
201 | GenericDefId | ||
145 | } | 202 | } |
146 | 203 | ||
147 | pub trait ToId: Sized + AstNode + 'static { | 204 | pub trait ToIdByKey: Sized + AstNode + 'static { |
148 | type ID: Sized + Copy + 'static; | 205 | type ID: Sized + Copy + 'static; |
149 | const KEY: Key<Self, Self::ID>; | 206 | const KEY: Key<Self, Self::ID>; |
150 | } | 207 | } |
151 | 208 | ||
152 | macro_rules! to_id_impls { | 209 | impl<T: ToIdByKey> ToId for T { |
210 | type ID = <T as ToIdByKey>::ID; | ||
211 | fn to_id<DB: HirDatabase>( | ||
212 | sb: &mut SourceBinder<'_, DB>, | ||
213 | src: InFile<Self>, | ||
214 | ) -> Option<Self::ID> { | ||
215 | let container = sb.find_container(src.as_ref().map(|it| it.syntax()))?; | ||
216 | let db = sb.db; | ||
217 | let dyn_map = | ||
218 | &*sb.child_by_source_cache.entry(container).or_insert_with(|| match container { | ||
219 | ChildContainer::DefWithBodyId(it) => it.child_by_source(db), | ||
220 | ChildContainer::ModuleId(it) => it.child_by_source(db), | ||
221 | ChildContainer::TraitId(it) => it.child_by_source(db), | ||
222 | ChildContainer::ImplId(it) => it.child_by_source(db), | ||
223 | ChildContainer::EnumId(it) => it.child_by_source(db), | ||
224 | ChildContainer::VariantId(it) => it.child_by_source(db), | ||
225 | ChildContainer::GenericDefId(it) => it.child_by_source(db), | ||
226 | }); | ||
227 | dyn_map[T::KEY].get(&src).copied() | ||
228 | } | ||
229 | } | ||
230 | |||
231 | macro_rules! to_id_key_impls { | ||
153 | ($(($id:ident, $ast:path, $key:path)),* ,) => {$( | 232 | ($(($id:ident, $ast:path, $key:path)),* ,) => {$( |
154 | impl ToId for $ast { | 233 | impl ToIdByKey for $ast { |
155 | type ID = $id; | 234 | type ID = $id; |
156 | const KEY: Key<Self, Self::ID> = $key; | 235 | const KEY: Key<Self, Self::ID> = $key; |
157 | } | 236 | } |
158 | )*} | 237 | )*} |
159 | } | 238 | } |
160 | 239 | ||
161 | to_id_impls![ | 240 | to_id_key_impls![ |
162 | (StructId, ast::StructDef, keys::STRUCT), | 241 | (StructId, ast::StructDef, keys::STRUCT), |
163 | (UnionId, ast::UnionDef, keys::UNION), | 242 | (UnionId, ast::UnionDef, keys::UNION), |
164 | (EnumId, ast::EnumDef, keys::ENUM), | 243 | (EnumId, ast::EnumDef, keys::ENUM), |
@@ -171,3 +250,108 @@ to_id_impls![ | |||
171 | (StructFieldId, ast::RecordFieldDef, keys::RECORD_FIELD), | 250 | (StructFieldId, ast::RecordFieldDef, keys::RECORD_FIELD), |
172 | (EnumVariantId, ast::EnumVariant, keys::ENUM_VARIANT), | 251 | (EnumVariantId, ast::EnumVariant, keys::ENUM_VARIANT), |
173 | ]; | 252 | ]; |
253 | |||
254 | // FIXME: use DynMap as well? | ||
255 | impl ToId for ast::MacroCall { | ||
256 | type ID = MacroDefId; | ||
257 | fn to_id<DB: HirDatabase>( | ||
258 | sb: &mut SourceBinder<'_, DB>, | ||
259 | src: InFile<Self>, | ||
260 | ) -> Option<Self::ID> { | ||
261 | let kind = MacroDefKind::Declarative; | ||
262 | |||
263 | let krate = sb.to_module_def(src.file_id.original_file(sb.db))?.id.krate; | ||
264 | |||
265 | let ast_id = | ||
266 | Some(AstId::new(src.file_id, sb.db.ast_id_map(src.file_id).ast_id(&src.value))); | ||
267 | |||
268 | Some(MacroDefId { krate: Some(krate), ast_id, kind }) | ||
269 | } | ||
270 | } | ||
271 | |||
272 | impl ToDef for ast::BindPat { | ||
273 | type Def = Local; | ||
274 | |||
275 | fn to_def<DB: HirDatabase>(sb: &mut SourceBinder<'_, DB>, src: InFile<Self>) -> Option<Local> { | ||
276 | let file_id = src.file_id; | ||
277 | let parent: DefWithBodyId = src.value.syntax().ancestors().find_map(|it| { | ||
278 | let res = match_ast! { | ||
279 | match it { | ||
280 | ast::ConstDef(value) => { sb.to_id(InFile { value, file_id})?.into() }, | ||
281 | ast::StaticDef(value) => { sb.to_id(InFile { value, file_id})?.into() }, | ||
282 | ast::FnDef(value) => { sb.to_id(InFile { value, file_id})?.into() }, | ||
283 | _ => return None, | ||
284 | } | ||
285 | }; | ||
286 | Some(res) | ||
287 | })?; | ||
288 | let (_body, source_map) = sb.db.body_with_source_map(parent); | ||
289 | let src = src.map(ast::Pat::from); | ||
290 | let pat_id = source_map.node_pat(src.as_ref())?; | ||
291 | Some(Local { parent: parent.into(), pat_id }) | ||
292 | } | ||
293 | } | ||
294 | |||
295 | impl ToDef for ast::TypeParam { | ||
296 | type Def = TypeParam; | ||
297 | |||
298 | fn to_def<DB: HirDatabase>( | ||
299 | sb: &mut SourceBinder<'_, DB>, | ||
300 | src: InFile<ast::TypeParam>, | ||
301 | ) -> Option<TypeParam> { | ||
302 | let mut sb = SourceBinder::new(sb.db); | ||
303 | let file_id = src.file_id; | ||
304 | let parent: GenericDefId = src.value.syntax().ancestors().find_map(|it| { | ||
305 | let res = match_ast! { | ||
306 | match it { | ||
307 | ast::FnDef(value) => { sb.to_id(InFile { value, file_id})?.into() }, | ||
308 | ast::StructDef(value) => { sb.to_id(InFile { value, file_id})?.into() }, | ||
309 | ast::EnumDef(value) => { sb.to_id(InFile { value, file_id})?.into() }, | ||
310 | ast::TraitDef(value) => { sb.to_id(InFile { value, file_id})?.into() }, | ||
311 | ast::TypeAliasDef(value) => { sb.to_id(InFile { value, file_id})?.into() }, | ||
312 | ast::ImplBlock(value) => { sb.to_id(InFile { value, file_id})?.into() }, | ||
313 | _ => return None, | ||
314 | } | ||
315 | }; | ||
316 | Some(res) | ||
317 | })?; | ||
318 | let &id = sb.child_by_source(parent.into())[keys::TYPE_PARAM].get(&src)?; | ||
319 | Some(TypeParam { id }) | ||
320 | } | ||
321 | } | ||
322 | |||
323 | impl ToId for ast::Module { | ||
324 | type ID = ModuleId; | ||
325 | |||
326 | fn to_id<DB: HirDatabase>( | ||
327 | sb: &mut SourceBinder<'_, DB>, | ||
328 | src: InFile<ast::Module>, | ||
329 | ) -> Option<ModuleId> { | ||
330 | { | ||
331 | let _p = profile("ast::Module::to_def"); | ||
332 | let parent_declaration = src | ||
333 | .as_ref() | ||
334 | .map(|it| it.syntax()) | ||
335 | .cloned() | ||
336 | .ancestors_with_macros(sb.db) | ||
337 | .skip(1) | ||
338 | .find_map(|it| { | ||
339 | let m = ast::Module::cast(it.value.clone())?; | ||
340 | Some(it.with_value(m)) | ||
341 | }); | ||
342 | |||
343 | let parent_module = match parent_declaration { | ||
344 | Some(parent_declaration) => sb.to_id(parent_declaration)?, | ||
345 | None => { | ||
346 | let file_id = src.file_id.original_file(sb.db); | ||
347 | sb.to_module_def(file_id)?.id | ||
348 | } | ||
349 | }; | ||
350 | |||
351 | let child_name = src.value.name()?.as_name(); | ||
352 | let def_map = sb.db.crate_def_map(parent_module.krate); | ||
353 | let child_id = *def_map[parent_module.local_id].children.get(&child_name)?; | ||
354 | Some(ModuleId { krate: parent_module.krate, local_id: child_id }) | ||
355 | } | ||
356 | } | ||
357 | } | ||
diff --git a/crates/ra_hir_def/src/keys.rs b/crates/ra_hir_def/src/keys.rs index d844f7a62..5913f12b1 100644 --- a/crates/ra_hir_def/src/keys.rs +++ b/crates/ra_hir_def/src/keys.rs | |||
@@ -2,7 +2,7 @@ | |||
2 | 2 | ||
3 | use std::marker::PhantomData; | 3 | use std::marker::PhantomData; |
4 | 4 | ||
5 | use hir_expand::InFile; | 5 | use hir_expand::{InFile, MacroDefId}; |
6 | use ra_syntax::{ast, AstNode, AstPtr}; | 6 | use ra_syntax::{ast, AstNode, AstPtr}; |
7 | use rustc_hash::FxHashMap; | 7 | use rustc_hash::FxHashMap; |
8 | 8 | ||
@@ -29,6 +29,8 @@ pub const TUPLE_FIELD: Key<ast::TupleFieldDef, StructFieldId> = Key::new(); | |||
29 | pub const RECORD_FIELD: Key<ast::RecordFieldDef, StructFieldId> = Key::new(); | 29 | pub const RECORD_FIELD: Key<ast::RecordFieldDef, StructFieldId> = Key::new(); |
30 | pub const TYPE_PARAM: Key<ast::TypeParam, TypeParamId> = Key::new(); | 30 | pub const TYPE_PARAM: Key<ast::TypeParam, TypeParamId> = Key::new(); |
31 | 31 | ||
32 | pub const MACRO: Key<ast::MacroCall, MacroDefId> = Key::new(); | ||
33 | |||
32 | /// XXX: AST Nodes and SyntaxNodes have identity equality semantics: nodes are | 34 | /// XXX: AST Nodes and SyntaxNodes have identity equality semantics: nodes are |
33 | /// equal if they point to exactly the same object. | 35 | /// equal if they point to exactly the same object. |
34 | /// | 36 | /// |
diff --git a/crates/ra_hir_def/src/nameres.rs b/crates/ra_hir_def/src/nameres.rs index e1a6a46df..27c12e46c 100644 --- a/crates/ra_hir_def/src/nameres.rs +++ b/crates/ra_hir_def/src/nameres.rs | |||
@@ -59,12 +59,9 @@ use std::sync::Arc; | |||
59 | 59 | ||
60 | use hir_expand::{diagnostics::DiagnosticSink, name::Name, InFile}; | 60 | use hir_expand::{diagnostics::DiagnosticSink, name::Name, InFile}; |
61 | use ra_arena::Arena; | 61 | use ra_arena::Arena; |
62 | use ra_db::{CrateId, Edition, FileId, FilePosition}; | 62 | use ra_db::{CrateId, Edition, FileId}; |
63 | use ra_prof::profile; | 63 | use ra_prof::profile; |
64 | use ra_syntax::{ | 64 | use ra_syntax::ast; |
65 | ast::{self, AstNode}, | ||
66 | SyntaxNode, | ||
67 | }; | ||
68 | use rustc_hash::FxHashMap; | 65 | use rustc_hash::FxHashMap; |
69 | 66 | ||
70 | use crate::{ | 67 | use crate::{ |
@@ -255,35 +252,6 @@ pub enum ModuleSource { | |||
255 | Module(ast::Module), | 252 | Module(ast::Module), |
256 | } | 253 | } |
257 | 254 | ||
258 | impl ModuleSource { | ||
259 | // FIXME: this methods do not belong here | ||
260 | pub fn from_position(db: &impl DefDatabase, position: FilePosition) -> ModuleSource { | ||
261 | let parse = db.parse(position.file_id); | ||
262 | match &ra_syntax::algo::find_node_at_offset::<ast::Module>( | ||
263 | parse.tree().syntax(), | ||
264 | position.offset, | ||
265 | ) { | ||
266 | Some(m) if !m.has_semi() => ModuleSource::Module(m.clone()), | ||
267 | _ => { | ||
268 | let source_file = parse.tree(); | ||
269 | ModuleSource::SourceFile(source_file) | ||
270 | } | ||
271 | } | ||
272 | } | ||
273 | |||
274 | pub fn from_child_node(db: &impl DefDatabase, child: InFile<&SyntaxNode>) -> ModuleSource { | ||
275 | if let Some(m) = | ||
276 | child.value.ancestors().filter_map(ast::Module::cast).find(|it| !it.has_semi()) | ||
277 | { | ||
278 | ModuleSource::Module(m) | ||
279 | } else { | ||
280 | let file_id = child.file_id.original_file(db); | ||
281 | let source_file = db.parse(file_id).tree(); | ||
282 | ModuleSource::SourceFile(source_file) | ||
283 | } | ||
284 | } | ||
285 | } | ||
286 | |||
287 | mod diagnostics { | 255 | mod diagnostics { |
288 | use hir_expand::diagnostics::DiagnosticSink; | 256 | use hir_expand::diagnostics::DiagnosticSink; |
289 | use ra_db::RelativePathBuf; | 257 | use ra_db::RelativePathBuf; |
diff --git a/crates/ra_ide/src/completion/completion_context.rs b/crates/ra_ide/src/completion/completion_context.rs index 48d69f7e5..deaacda6c 100644 --- a/crates/ra_ide/src/completion/completion_context.rs +++ b/crates/ra_ide/src/completion/completion_context.rs | |||
@@ -52,15 +52,11 @@ impl<'a> CompletionContext<'a> { | |||
52 | original_parse: &'a Parse<ast::SourceFile>, | 52 | original_parse: &'a Parse<ast::SourceFile>, |
53 | position: FilePosition, | 53 | position: FilePosition, |
54 | ) -> Option<CompletionContext<'a>> { | 54 | ) -> Option<CompletionContext<'a>> { |
55 | let src = hir::ModuleSource::from_position(db, position); | 55 | let mut sb = hir::SourceBinder::new(db); |
56 | let module = hir::Module::from_definition( | 56 | let module = sb.to_module_def(position.file_id); |
57 | db, | ||
58 | hir::InFile { file_id: position.file_id.into(), value: src }, | ||
59 | ); | ||
60 | let token = | 57 | let token = |
61 | original_parse.tree().syntax().token_at_offset(position.offset).left_biased()?; | 58 | original_parse.tree().syntax().token_at_offset(position.offset).left_biased()?; |
62 | let analyzer = hir::SourceAnalyzer::new( | 59 | let analyzer = sb.analyze( |
63 | db, | ||
64 | hir::InFile::new(position.file_id.into(), &token.parent()), | 60 | hir::InFile::new(position.file_id.into(), &token.parent()), |
65 | Some(position.offset), | 61 | Some(position.offset), |
66 | ); | 62 | ); |
diff --git a/crates/ra_ide/src/diagnostics.rs b/crates/ra_ide/src/diagnostics.rs index 478368529..f403b3bcf 100644 --- a/crates/ra_ide/src/diagnostics.rs +++ b/crates/ra_ide/src/diagnostics.rs | |||
@@ -23,6 +23,7 @@ pub enum Severity { | |||
23 | 23 | ||
24 | pub(crate) fn diagnostics(db: &RootDatabase, file_id: FileId) -> Vec<Diagnostic> { | 24 | pub(crate) fn diagnostics(db: &RootDatabase, file_id: FileId) -> Vec<Diagnostic> { |
25 | let _p = profile("diagnostics"); | 25 | let _p = profile("diagnostics"); |
26 | let mut sb = hir::SourceBinder::new(db); | ||
26 | let parse = db.parse(file_id); | 27 | let parse = db.parse(file_id); |
27 | let mut res = Vec::new(); | 28 | let mut res = Vec::new(); |
28 | 29 | ||
@@ -108,10 +109,7 @@ pub(crate) fn diagnostics(db: &RootDatabase, file_id: FileId) -> Vec<Diagnostic> | |||
108 | fix: Some(fix), | 109 | fix: Some(fix), |
109 | }) | 110 | }) |
110 | }); | 111 | }); |
111 | let source_file = db.parse(file_id).tree(); | 112 | if let Some(m) = sb.to_module_def(file_id) { |
112 | let src = | ||
113 | hir::InFile { file_id: file_id.into(), value: hir::ModuleSource::SourceFile(source_file) }; | ||
114 | if let Some(m) = hir::Module::from_definition(db, src) { | ||
115 | m.diagnostics(db, &mut sink); | 113 | m.diagnostics(db, &mut sink); |
116 | }; | 114 | }; |
117 | drop(sink); | 115 | drop(sink); |
diff --git a/crates/ra_ide/src/goto_definition.rs b/crates/ra_ide/src/goto_definition.rs index f2b5af321..5a12a619c 100644 --- a/crates/ra_ide/src/goto_definition.rs +++ b/crates/ra_ide/src/goto_definition.rs | |||
@@ -24,13 +24,14 @@ pub(crate) fn goto_definition( | |||
24 | let original_token = pick_best(file.token_at_offset(position.offset))?; | 24 | let original_token = pick_best(file.token_at_offset(position.offset))?; |
25 | let token = descend_into_macros(db, position.file_id, original_token.clone()); | 25 | let token = descend_into_macros(db, position.file_id, original_token.clone()); |
26 | 26 | ||
27 | let mut sb = SourceBinder::new(db); | ||
27 | let nav_targets = match_ast! { | 28 | let nav_targets = match_ast! { |
28 | match (token.value.parent()) { | 29 | match (token.value.parent()) { |
29 | ast::NameRef(name_ref) => { | 30 | ast::NameRef(name_ref) => { |
30 | reference_definition(db, token.with_value(&name_ref)).to_vec() | 31 | reference_definition(&mut sb, token.with_value(&name_ref)).to_vec() |
31 | }, | 32 | }, |
32 | ast::Name(name) => { | 33 | ast::Name(name) => { |
33 | name_definition(db, token.with_value(&name))? | 34 | name_definition(&mut sb, token.with_value(&name))? |
34 | }, | 35 | }, |
35 | _ => return None, | 36 | _ => return None, |
36 | } | 37 | } |
@@ -67,20 +68,19 @@ impl ReferenceResult { | |||
67 | } | 68 | } |
68 | 69 | ||
69 | pub(crate) fn reference_definition( | 70 | pub(crate) fn reference_definition( |
70 | db: &RootDatabase, | 71 | sb: &mut SourceBinder<RootDatabase>, |
71 | name_ref: InFile<&ast::NameRef>, | 72 | name_ref: InFile<&ast::NameRef>, |
72 | ) -> ReferenceResult { | 73 | ) -> ReferenceResult { |
73 | use self::ReferenceResult::*; | 74 | use self::ReferenceResult::*; |
74 | 75 | ||
75 | let mut sb = SourceBinder::new(db); | 76 | let name_kind = classify_name_ref(sb, name_ref).map(|d| d.kind); |
76 | let name_kind = classify_name_ref(&mut sb, name_ref).map(|d| d.kind); | ||
77 | match name_kind { | 77 | match name_kind { |
78 | Some(Macro(it)) => return Exact(it.to_nav(db)), | 78 | Some(Macro(it)) => return Exact(it.to_nav(sb.db)), |
79 | Some(Field(it)) => return Exact(it.to_nav(db)), | 79 | Some(Field(it)) => return Exact(it.to_nav(sb.db)), |
80 | Some(TypeParam(it)) => return Exact(it.to_nav(db)), | 80 | Some(TypeParam(it)) => return Exact(it.to_nav(sb.db)), |
81 | Some(AssocItem(it)) => return Exact(it.to_nav(db)), | 81 | Some(AssocItem(it)) => return Exact(it.to_nav(sb.db)), |
82 | Some(Local(it)) => return Exact(it.to_nav(db)), | 82 | Some(Local(it)) => return Exact(it.to_nav(sb.db)), |
83 | Some(Def(def)) => match NavigationTarget::from_def(db, def) { | 83 | Some(Def(def)) => match NavigationTarget::from_def(sb.db, def) { |
84 | Some(nav) => return Exact(nav), | 84 | Some(nav) => return Exact(nav), |
85 | None => return Approximate(vec![]), | 85 | None => return Approximate(vec![]), |
86 | }, | 86 | }, |
@@ -88,21 +88,21 @@ pub(crate) fn reference_definition( | |||
88 | // FIXME: ideally, this should point to the type in the impl, and | 88 | // FIXME: ideally, this should point to the type in the impl, and |
89 | // not at the whole impl. And goto **type** definition should bring | 89 | // not at the whole impl. And goto **type** definition should bring |
90 | // us to the actual type | 90 | // us to the actual type |
91 | return Exact(imp.to_nav(db)); | 91 | return Exact(imp.to_nav(sb.db)); |
92 | } | 92 | } |
93 | None => {} | 93 | None => {} |
94 | }; | 94 | }; |
95 | 95 | ||
96 | // Fallback index based approach: | 96 | // Fallback index based approach: |
97 | let navs = crate::symbol_index::index_resolve(db, name_ref.value) | 97 | let navs = crate::symbol_index::index_resolve(sb.db, name_ref.value) |
98 | .into_iter() | 98 | .into_iter() |
99 | .map(|s| s.to_nav(db)) | 99 | .map(|s| s.to_nav(sb.db)) |
100 | .collect(); | 100 | .collect(); |
101 | Approximate(navs) | 101 | Approximate(navs) |
102 | } | 102 | } |
103 | 103 | ||
104 | pub(crate) fn name_definition( | 104 | fn name_definition( |
105 | db: &RootDatabase, | 105 | sb: &mut SourceBinder<RootDatabase>, |
106 | name: InFile<&ast::Name>, | 106 | name: InFile<&ast::Name>, |
107 | ) -> Option<Vec<NavigationTarget>> { | 107 | ) -> Option<Vec<NavigationTarget>> { |
108 | let parent = name.value.syntax().parent()?; | 108 | let parent = name.value.syntax().parent()?; |
@@ -110,14 +110,14 @@ pub(crate) fn name_definition( | |||
110 | if let Some(module) = ast::Module::cast(parent.clone()) { | 110 | if let Some(module) = ast::Module::cast(parent.clone()) { |
111 | if module.has_semi() { | 111 | if module.has_semi() { |
112 | let src = name.with_value(module); | 112 | let src = name.with_value(module); |
113 | if let Some(child_module) = hir::Module::from_declaration(db, src) { | 113 | if let Some(child_module) = sb.to_def(src) { |
114 | let nav = child_module.to_nav(db); | 114 | let nav = child_module.to_nav(sb.db); |
115 | return Some(vec![nav]); | 115 | return Some(vec![nav]); |
116 | } | 116 | } |
117 | } | 117 | } |
118 | } | 118 | } |
119 | 119 | ||
120 | if let Some(nav) = named_target(db, name.with_value(&parent)) { | 120 | if let Some(nav) = named_target(sb.db, name.with_value(&parent)) { |
121 | return Some(vec![nav]); | 121 | return Some(vec![nav]); |
122 | } | 122 | } |
123 | 123 | ||
diff --git a/crates/ra_ide/src/impls.rs b/crates/ra_ide/src/impls.rs index 31195036e..9834025d3 100644 --- a/crates/ra_ide/src/impls.rs +++ b/crates/ra_ide/src/impls.rs | |||
@@ -1,6 +1,6 @@ | |||
1 | //! FIXME: write short doc here | 1 | //! FIXME: write short doc here |
2 | 2 | ||
3 | use hir::{FromSource, ImplBlock}; | 3 | use hir::{Crate, ImplBlock, SourceBinder}; |
4 | use ra_db::SourceDatabase; | 4 | use ra_db::SourceDatabase; |
5 | use ra_syntax::{algo::find_node_at_offset, ast, AstNode}; | 5 | use ra_syntax::{algo::find_node_at_offset, ast, AstNode}; |
6 | 6 | ||
@@ -12,22 +12,19 @@ pub(crate) fn goto_implementation( | |||
12 | ) -> Option<RangeInfo<Vec<NavigationTarget>>> { | 12 | ) -> Option<RangeInfo<Vec<NavigationTarget>>> { |
13 | let parse = db.parse(position.file_id); | 13 | let parse = db.parse(position.file_id); |
14 | let syntax = parse.tree().syntax().clone(); | 14 | let syntax = parse.tree().syntax().clone(); |
15 | let mut sb = SourceBinder::new(db); | ||
15 | 16 | ||
16 | let src = hir::ModuleSource::from_position(db, position); | 17 | let krate = sb.to_module_def(position.file_id)?.krate(); |
17 | let module = hir::Module::from_definition( | ||
18 | db, | ||
19 | hir::InFile { file_id: position.file_id.into(), value: src }, | ||
20 | )?; | ||
21 | 18 | ||
22 | if let Some(nominal_def) = find_node_at_offset::<ast::NominalDef>(&syntax, position.offset) { | 19 | if let Some(nominal_def) = find_node_at_offset::<ast::NominalDef>(&syntax, position.offset) { |
23 | return Some(RangeInfo::new( | 20 | return Some(RangeInfo::new( |
24 | nominal_def.syntax().text_range(), | 21 | nominal_def.syntax().text_range(), |
25 | impls_for_def(db, position, &nominal_def, module)?, | 22 | impls_for_def(&mut sb, position, &nominal_def, krate)?, |
26 | )); | 23 | )); |
27 | } else if let Some(trait_def) = find_node_at_offset::<ast::TraitDef>(&syntax, position.offset) { | 24 | } else if let Some(trait_def) = find_node_at_offset::<ast::TraitDef>(&syntax, position.offset) { |
28 | return Some(RangeInfo::new( | 25 | return Some(RangeInfo::new( |
29 | trait_def.syntax().text_range(), | 26 | trait_def.syntax().text_range(), |
30 | impls_for_trait(db, position, &trait_def, module)?, | 27 | impls_for_trait(&mut sb, position, &trait_def, krate)?, |
31 | )); | 28 | )); |
32 | } | 29 | } |
33 | 30 | ||
@@ -35,51 +32,49 @@ pub(crate) fn goto_implementation( | |||
35 | } | 32 | } |
36 | 33 | ||
37 | fn impls_for_def( | 34 | fn impls_for_def( |
38 | db: &RootDatabase, | 35 | sb: &mut SourceBinder<RootDatabase>, |
39 | position: FilePosition, | 36 | position: FilePosition, |
40 | node: &ast::NominalDef, | 37 | node: &ast::NominalDef, |
41 | module: hir::Module, | 38 | krate: Crate, |
42 | ) -> Option<Vec<NavigationTarget>> { | 39 | ) -> Option<Vec<NavigationTarget>> { |
43 | let ty = match node { | 40 | let ty = match node { |
44 | ast::NominalDef::StructDef(def) => { | 41 | ast::NominalDef::StructDef(def) => { |
45 | let src = hir::InFile { file_id: position.file_id.into(), value: def.clone() }; | 42 | let src = hir::InFile { file_id: position.file_id.into(), value: def.clone() }; |
46 | hir::Struct::from_source(db, src)?.ty(db) | 43 | sb.to_def(src)?.ty(sb.db) |
47 | } | 44 | } |
48 | ast::NominalDef::EnumDef(def) => { | 45 | ast::NominalDef::EnumDef(def) => { |
49 | let src = hir::InFile { file_id: position.file_id.into(), value: def.clone() }; | 46 | let src = hir::InFile { file_id: position.file_id.into(), value: def.clone() }; |
50 | hir::Enum::from_source(db, src)?.ty(db) | 47 | sb.to_def(src)?.ty(sb.db) |
51 | } | 48 | } |
52 | ast::NominalDef::UnionDef(def) => { | 49 | ast::NominalDef::UnionDef(def) => { |
53 | let src = hir::InFile { file_id: position.file_id.into(), value: def.clone() }; | 50 | let src = hir::InFile { file_id: position.file_id.into(), value: def.clone() }; |
54 | hir::Union::from_source(db, src)?.ty(db) | 51 | sb.to_def(src)?.ty(sb.db) |
55 | } | 52 | } |
56 | }; | 53 | }; |
57 | 54 | ||
58 | let krate = module.krate(); | 55 | let impls = ImplBlock::all_in_crate(sb.db, krate); |
59 | let impls = ImplBlock::all_in_crate(db, krate); | ||
60 | 56 | ||
61 | Some( | 57 | Some( |
62 | impls | 58 | impls |
63 | .into_iter() | 59 | .into_iter() |
64 | .filter(|impl_block| ty.is_equal_for_find_impls(&impl_block.target_ty(db))) | 60 | .filter(|impl_block| ty.is_equal_for_find_impls(&impl_block.target_ty(sb.db))) |
65 | .map(|imp| imp.to_nav(db)) | 61 | .map(|imp| imp.to_nav(sb.db)) |
66 | .collect(), | 62 | .collect(), |
67 | ) | 63 | ) |
68 | } | 64 | } |
69 | 65 | ||
70 | fn impls_for_trait( | 66 | fn impls_for_trait( |
71 | db: &RootDatabase, | 67 | sb: &mut SourceBinder<RootDatabase>, |
72 | position: FilePosition, | 68 | position: FilePosition, |
73 | node: &ast::TraitDef, | 69 | node: &ast::TraitDef, |
74 | module: hir::Module, | 70 | krate: Crate, |
75 | ) -> Option<Vec<NavigationTarget>> { | 71 | ) -> Option<Vec<NavigationTarget>> { |
76 | let src = hir::InFile { file_id: position.file_id.into(), value: node.clone() }; | 72 | let src = hir::InFile { file_id: position.file_id.into(), value: node.clone() }; |
77 | let tr = hir::Trait::from_source(db, src)?; | 73 | let tr = sb.to_def(src)?; |
78 | 74 | ||
79 | let krate = module.krate(); | 75 | let impls = ImplBlock::for_trait(sb.db, krate, tr); |
80 | let impls = ImplBlock::for_trait(db, krate, tr); | ||
81 | 76 | ||
82 | Some(impls.into_iter().map(|imp| imp.to_nav(db)).collect()) | 77 | Some(impls.into_iter().map(|imp| imp.to_nav(sb.db)).collect()) |
83 | } | 78 | } |
84 | 79 | ||
85 | #[cfg(test)] | 80 | #[cfg(test)] |
@@ -210,7 +205,7 @@ mod tests { | |||
210 | " | 205 | " |
211 | //- /lib.rs | 206 | //- /lib.rs |
212 | #[derive(Copy)] | 207 | #[derive(Copy)] |
213 | struct Foo<|>; | 208 | struct Foo<|>; |
214 | ", | 209 | ", |
215 | &["impl IMPL_BLOCK FileId(1) [0; 15)"], | 210 | &["impl IMPL_BLOCK FileId(1) [0; 15)"], |
216 | ); | 211 | ); |
diff --git a/crates/ra_ide/src/parent_module.rs b/crates/ra_ide/src/parent_module.rs index f5a788c07..2dbccfc3b 100644 --- a/crates/ra_ide/src/parent_module.rs +++ b/crates/ra_ide/src/parent_module.rs | |||
@@ -1,17 +1,23 @@ | |||
1 | //! FIXME: write short doc here | 1 | //! FIXME: write short doc here |
2 | 2 | ||
3 | use ra_db::{CrateId, FileId, FilePosition, SourceDatabase}; | 3 | use ra_db::{CrateId, FileId, FilePosition, SourceDatabase}; |
4 | use ra_syntax::{ | ||
5 | algo::find_node_at_offset, | ||
6 | ast::{self, AstNode}, | ||
7 | }; | ||
4 | 8 | ||
5 | use crate::{db::RootDatabase, NavigationTarget}; | 9 | use crate::{db::RootDatabase, NavigationTarget}; |
6 | 10 | ||
7 | /// This returns `Vec` because a module may be included from several places. We | 11 | /// This returns `Vec` because a module may be included from several places. We |
8 | /// don't handle this case yet though, so the Vec has length at most one. | 12 | /// don't handle this case yet though, so the Vec has length at most one. |
9 | pub(crate) fn parent_module(db: &RootDatabase, position: FilePosition) -> Vec<NavigationTarget> { | 13 | pub(crate) fn parent_module(db: &RootDatabase, position: FilePosition) -> Vec<NavigationTarget> { |
10 | let src = hir::ModuleSource::from_position(db, position); | 14 | let mut sb = hir::SourceBinder::new(db); |
11 | let module = match hir::Module::from_definition( | 15 | let parse = db.parse(position.file_id); |
12 | db, | 16 | let module = match find_node_at_offset::<ast::Module>(parse.tree().syntax(), position.offset) { |
13 | hir::InFile { file_id: position.file_id.into(), value: src }, | 17 | Some(module) => sb.to_def(hir::InFile::new(position.file_id.into(), module)), |
14 | ) { | 18 | None => sb.to_module_def(position.file_id), |
19 | }; | ||
20 | let module = match module { | ||
15 | None => return Vec::new(), | 21 | None => return Vec::new(), |
16 | Some(it) => it, | 22 | Some(it) => it, |
17 | }; | 23 | }; |
@@ -21,14 +27,11 @@ pub(crate) fn parent_module(db: &RootDatabase, position: FilePosition) -> Vec<Na | |||
21 | 27 | ||
22 | /// Returns `Vec` for the same reason as `parent_module` | 28 | /// Returns `Vec` for the same reason as `parent_module` |
23 | pub(crate) fn crate_for(db: &RootDatabase, file_id: FileId) -> Vec<CrateId> { | 29 | pub(crate) fn crate_for(db: &RootDatabase, file_id: FileId) -> Vec<CrateId> { |
24 | let source_file = db.parse(file_id).tree(); | 30 | let mut sb = hir::SourceBinder::new(db); |
25 | let src = hir::ModuleSource::SourceFile(source_file); | 31 | let module = match sb.to_module_def(file_id) { |
26 | let module = | 32 | Some(it) => it, |
27 | match hir::Module::from_definition(db, hir::InFile { file_id: file_id.into(), value: src }) | 33 | None => return Vec::new(), |
28 | { | 34 | }; |
29 | Some(it) => it, | ||
30 | None => return Vec::new(), | ||
31 | }; | ||
32 | let krate = module.krate(); | 35 | let krate = module.krate(); |
33 | vec![krate.into()] | 36 | vec![krate.into()] |
34 | } | 37 | } |
diff --git a/crates/ra_ide/src/references/classify.rs b/crates/ra_ide/src/references/classify.rs index 4a6e11e27..46cba30a3 100644 --- a/crates/ra_ide/src/references/classify.rs +++ b/crates/ra_ide/src/references/classify.rs | |||
@@ -1,6 +1,6 @@ | |||
1 | //! Functions that are used to classify an element from its definition or reference. | 1 | //! Functions that are used to classify an element from its definition or reference. |
2 | 2 | ||
3 | use hir::{FromSource, InFile, Module, ModuleSource, PathResolution, SourceBinder}; | 3 | use hir::{InFile, PathResolution, SourceBinder}; |
4 | use ra_prof::profile; | 4 | use ra_prof::profile; |
5 | use ra_syntax::{ast, match_ast, AstNode}; | 5 | use ra_syntax::{ast, match_ast, AstNode}; |
6 | use test_utils::tested_by; | 6 | use test_utils::tested_by; |
@@ -22,7 +22,7 @@ pub(crate) fn classify_name( | |||
22 | match parent { | 22 | match parent { |
23 | ast::BindPat(it) => { | 23 | ast::BindPat(it) => { |
24 | let src = name.with_value(it); | 24 | let src = name.with_value(it); |
25 | let local = hir::Local::from_source(sb.db, src)?; | 25 | let local = sb.to_def(src)?; |
26 | Some(NameDefinition { | 26 | Some(NameDefinition { |
27 | visibility: None, | 27 | visibility: None, |
28 | container: local.module(sb.db), | 28 | container: local.module(sb.db), |
@@ -35,16 +35,7 @@ pub(crate) fn classify_name( | |||
35 | Some(from_struct_field(sb.db, field)) | 35 | Some(from_struct_field(sb.db, field)) |
36 | }, | 36 | }, |
37 | ast::Module(it) => { | 37 | ast::Module(it) => { |
38 | let def = { | 38 | let def = sb.to_def(name.with_value(it))?; |
39 | if !it.has_semi() { | ||
40 | let ast = hir::ModuleSource::Module(it); | ||
41 | let src = name.with_value(ast); | ||
42 | hir::Module::from_definition(sb.db, src) | ||
43 | } else { | ||
44 | let src = name.with_value(it); | ||
45 | hir::Module::from_declaration(sb.db, src) | ||
46 | } | ||
47 | }?; | ||
48 | Some(from_module_def(sb.db, def.into(), None)) | 39 | Some(from_module_def(sb.db, def.into(), None)) |
49 | }, | 40 | }, |
50 | ast::StructDef(it) => { | 41 | ast::StructDef(it) => { |
@@ -101,10 +92,9 @@ pub(crate) fn classify_name( | |||
101 | }, | 92 | }, |
102 | ast::MacroCall(it) => { | 93 | ast::MacroCall(it) => { |
103 | let src = name.with_value(it); | 94 | let src = name.with_value(it); |
104 | let def = hir::MacroDef::from_source(sb.db, src.clone())?; | 95 | let def = sb.to_def(src.clone())?; |
105 | 96 | ||
106 | let module_src = ModuleSource::from_child_node(sb.db, src.as_ref().map(|it| it.syntax())); | 97 | let module = sb.to_module_def(src.file_id.original_file(sb.db))?; |
107 | let module = Module::from_definition(sb.db, src.with_value(module_src))?; | ||
108 | 98 | ||
109 | Some(NameDefinition { | 99 | Some(NameDefinition { |
110 | visibility: None, | 100 | visibility: None, |
@@ -114,7 +104,7 @@ pub(crate) fn classify_name( | |||
114 | }, | 104 | }, |
115 | ast::TypeParam(it) => { | 105 | ast::TypeParam(it) => { |
116 | let src = name.with_value(it); | 106 | let src = name.with_value(it); |
117 | let def = hir::TypeParam::from_source(sb.db, src)?; | 107 | let def = sb.to_def(src)?; |
118 | Some(NameDefinition { | 108 | Some(NameDefinition { |
119 | visibility: None, | 109 | visibility: None, |
120 | container: def.module(sb.db), | 110 | container: def.module(sb.db), |
@@ -157,10 +147,9 @@ pub(crate) fn classify_name_ref( | |||
157 | } | 147 | } |
158 | } | 148 | } |
159 | 149 | ||
160 | let ast = ModuleSource::from_child_node(sb.db, name_ref.with_value(&parent)); | ||
161 | // FIXME: find correct container and visibility for each case | 150 | // FIXME: find correct container and visibility for each case |
162 | let container = Module::from_definition(sb.db, name_ref.with_value(ast))?; | ||
163 | let visibility = None; | 151 | let visibility = None; |
152 | let container = sb.to_module_def(name_ref.file_id.original_file(sb.db))?; | ||
164 | 153 | ||
165 | if let Some(macro_call) = parent.ancestors().find_map(ast::MacroCall::cast) { | 154 | if let Some(macro_call) = parent.ancestors().find_map(ast::MacroCall::cast) { |
166 | tested_by!(goto_def_for_macros); | 155 | tested_by!(goto_def_for_macros); |
@@ -178,12 +167,13 @@ pub(crate) fn classify_name_ref( | |||
178 | PathResolution::Def(def) => Some(from_module_def(sb.db, def, Some(container))), | 167 | PathResolution::Def(def) => Some(from_module_def(sb.db, def, Some(container))), |
179 | PathResolution::AssocItem(item) => Some(from_assoc_item(sb.db, item)), | 168 | PathResolution::AssocItem(item) => Some(from_assoc_item(sb.db, item)), |
180 | PathResolution::Local(local) => { | 169 | PathResolution::Local(local) => { |
181 | let container = local.module(sb.db); | ||
182 | let kind = NameKind::Local(local); | 170 | let kind = NameKind::Local(local); |
171 | let container = local.module(sb.db); | ||
183 | Some(NameDefinition { kind, container, visibility: None }) | 172 | Some(NameDefinition { kind, container, visibility: None }) |
184 | } | 173 | } |
185 | PathResolution::TypeParam(par) => { | 174 | PathResolution::TypeParam(par) => { |
186 | let kind = NameKind::TypeParam(par); | 175 | let kind = NameKind::TypeParam(par); |
176 | let container = par.module(sb.db); | ||
187 | Some(NameDefinition { kind, container, visibility }) | 177 | Some(NameDefinition { kind, container, visibility }) |
188 | } | 178 | } |
189 | PathResolution::Macro(def) => { | 179 | PathResolution::Macro(def) => { |
diff --git a/crates/ra_ide/src/references/name_definition.rs b/crates/ra_ide/src/references/name_definition.rs index 8c67c8863..1e4226ab9 100644 --- a/crates/ra_ide/src/references/name_definition.rs +++ b/crates/ra_ide/src/references/name_definition.rs | |||
@@ -25,6 +25,8 @@ pub enum NameKind { | |||
25 | #[derive(PartialEq, Eq)] | 25 | #[derive(PartialEq, Eq)] |
26 | pub(crate) struct NameDefinition { | 26 | pub(crate) struct NameDefinition { |
27 | pub visibility: Option<ast::Visibility>, | 27 | pub visibility: Option<ast::Visibility>, |
28 | /// FIXME: this doesn't really make sense. For example, builtin types don't | ||
29 | /// really have a module. | ||
28 | pub container: Module, | 30 | pub container: Module, |
29 | pub kind: NameKind, | 31 | pub kind: NameKind, |
30 | } | 32 | } |
diff --git a/crates/ra_ide/src/references/rename.rs b/crates/ra_ide/src/references/rename.rs index e02985dcd..626efb603 100644 --- a/crates/ra_ide/src/references/rename.rs +++ b/crates/ra_ide/src/references/rename.rs | |||
@@ -63,7 +63,7 @@ fn rename_mod( | |||
63 | let mut source_file_edits = Vec::new(); | 63 | let mut source_file_edits = Vec::new(); |
64 | let mut file_system_edits = Vec::new(); | 64 | let mut file_system_edits = Vec::new(); |
65 | let module_src = hir::InFile { file_id: position.file_id.into(), value: ast_module.clone() }; | 65 | let module_src = hir::InFile { file_id: position.file_id.into(), value: ast_module.clone() }; |
66 | if let Some(module) = hir::Module::from_declaration(db, module_src) { | 66 | if let Some(module) = hir::SourceBinder::new(db).to_def(module_src) { |
67 | let src = module.definition_source(db); | 67 | let src = module.definition_source(db); |
68 | let file_id = src.file_id.original_file(db); | 68 | let file_id = src.file_id.original_file(db); |
69 | match src.value { | 69 | match src.value { |
diff --git a/crates/ra_ide/src/runnables.rs b/crates/ra_ide/src/runnables.rs index e213e1a06..7533692f6 100644 --- a/crates/ra_ide/src/runnables.rs +++ b/crates/ra_ide/src/runnables.rs | |||
@@ -66,8 +66,8 @@ fn runnable_mod(db: &RootDatabase, file_id: FileId, module: ast::Module) -> Opti | |||
66 | return None; | 66 | return None; |
67 | } | 67 | } |
68 | let range = module.syntax().text_range(); | 68 | let range = module.syntax().text_range(); |
69 | let src = hir::ModuleSource::from_child_node(db, InFile::new(file_id.into(), &module.syntax())); | 69 | let mut sb = hir::SourceBinder::new(db); |
70 | let module = hir::Module::from_definition(db, InFile::new(file_id.into(), src))?; | 70 | let module = sb.to_def(InFile::new(file_id.into(), module))?; |
71 | 71 | ||
72 | let path = module.path_to_root(db).into_iter().rev().filter_map(|it| it.name(db)).join("::"); | 72 | let path = module.path_to_root(db).into_iter().rev().filter_map(|it| it.name(db)).join("::"); |
73 | Some(Runnable { range, kind: RunnableKind::TestMod { path } }) | 73 | Some(Runnable { range, kind: RunnableKind::TestMod { path } }) |