diff options
Diffstat (limited to 'crates/ra_hir/src/source_binder.rs')
-rw-r--r-- | crates/ra_hir/src/source_binder.rs | 52 |
1 files changed, 33 insertions, 19 deletions
diff --git a/crates/ra_hir/src/source_binder.rs b/crates/ra_hir/src/source_binder.rs index f28e9c931..ca40e3b54 100644 --- a/crates/ra_hir/src/source_binder.rs +++ b/crates/ra_hir/src/source_binder.rs | |||
@@ -7,8 +7,11 @@ | |||
7 | //! purely for "IDE needs". | 7 | //! purely for "IDE needs". |
8 | use std::sync::Arc; | 8 | use std::sync::Arc; |
9 | 9 | ||
10 | use hir_def::path::known; | 10 | use hir_def::{ |
11 | use hir_expand::name::AsName; | 11 | expr::{ExprId, PatId}, |
12 | path::known, | ||
13 | }; | ||
14 | use hir_expand::{name::AsName, Source}; | ||
12 | use ra_db::FileId; | 15 | use ra_db::FileId; |
13 | use ra_syntax::{ | 16 | use ra_syntax::{ |
14 | ast::{self, AstNode}, | 17 | ast::{self, AstNode}, |
@@ -20,11 +23,7 @@ use rustc_hash::FxHashSet; | |||
20 | 23 | ||
21 | use crate::{ | 24 | use crate::{ |
22 | db::HirDatabase, | 25 | db::HirDatabase, |
23 | expr::{ | 26 | expr::{self, BodySourceMap, ExprScopes, ScopeId}, |
24 | self, | ||
25 | scope::{ExprScopes, ScopeId}, | ||
26 | BodySourceMap, | ||
27 | }, | ||
28 | ids::LocationCtx, | 27 | ids::LocationCtx, |
29 | resolve::{ScopeDef, TypeNs, ValueNs}, | 28 | resolve::{ScopeDef, TypeNs, ValueNs}, |
30 | ty::method_resolution::{self, implements_trait}, | 29 | ty::method_resolution::{self, implements_trait}, |
@@ -93,6 +92,8 @@ fn def_with_body_from_child_node( | |||
93 | /// original source files. It should not be used inside the HIR itself. | 92 | /// original source files. It should not be used inside the HIR itself. |
94 | #[derive(Debug)] | 93 | #[derive(Debug)] |
95 | pub struct SourceAnalyzer { | 94 | pub struct SourceAnalyzer { |
95 | // FIXME: this doesn't handle macros at all | ||
96 | file_id: FileId, | ||
96 | resolver: Resolver, | 97 | resolver: Resolver, |
97 | body_owner: Option<DefWithBody>, | 98 | body_owner: Option<DefWithBody>, |
98 | body_source_map: Option<Arc<BodySourceMap>>, | 99 | body_source_map: Option<Arc<BodySourceMap>>, |
@@ -145,9 +146,9 @@ impl SourceAnalyzer { | |||
145 | let def_with_body = def_with_body_from_child_node(db, file_id, node); | 146 | let def_with_body = def_with_body_from_child_node(db, file_id, node); |
146 | if let Some(def) = def_with_body { | 147 | if let Some(def) = def_with_body { |
147 | let source_map = def.body_source_map(db); | 148 | let source_map = def.body_source_map(db); |
148 | let scopes = db.expr_scopes(def); | 149 | let scopes = def.expr_scopes(db); |
149 | let scope = match offset { | 150 | let scope = match offset { |
150 | None => scope_for(&scopes, &source_map, &node), | 151 | None => scope_for(&scopes, &source_map, file_id.into(), &node), |
151 | Some(offset) => scope_for_offset(&scopes, &source_map, file_id.into(), offset), | 152 | Some(offset) => scope_for_offset(&scopes, &source_map, file_id.into(), offset), |
152 | }; | 153 | }; |
153 | let resolver = expr::resolver_for_scope(db, def, scope); | 154 | let resolver = expr::resolver_for_scope(db, def, scope); |
@@ -157,6 +158,7 @@ impl SourceAnalyzer { | |||
157 | body_source_map: Some(source_map), | 158 | body_source_map: Some(source_map), |
158 | infer: Some(def.infer(db)), | 159 | infer: Some(def.infer(db)), |
159 | scopes: Some(scopes), | 160 | scopes: Some(scopes), |
161 | file_id, | ||
160 | } | 162 | } |
161 | } else { | 163 | } else { |
162 | SourceAnalyzer { | 164 | SourceAnalyzer { |
@@ -168,17 +170,28 @@ impl SourceAnalyzer { | |||
168 | body_source_map: None, | 170 | body_source_map: None, |
169 | infer: None, | 171 | infer: None, |
170 | scopes: None, | 172 | scopes: None, |
173 | file_id, | ||
171 | } | 174 | } |
172 | } | 175 | } |
173 | } | 176 | } |
174 | 177 | ||
178 | fn expr_id(&self, expr: &ast::Expr) -> Option<ExprId> { | ||
179 | let src = Source { file_id: self.file_id.into(), ast: expr }; | ||
180 | self.body_source_map.as_ref()?.node_expr(src) | ||
181 | } | ||
182 | |||
183 | fn pat_id(&self, pat: &ast::Pat) -> Option<PatId> { | ||
184 | let src = Source { file_id: self.file_id.into(), ast: pat }; | ||
185 | self.body_source_map.as_ref()?.node_pat(src) | ||
186 | } | ||
187 | |||
175 | pub fn type_of(&self, _db: &impl HirDatabase, expr: &ast::Expr) -> Option<crate::Ty> { | 188 | pub fn type_of(&self, _db: &impl HirDatabase, expr: &ast::Expr) -> Option<crate::Ty> { |
176 | let expr_id = self.body_source_map.as_ref()?.node_expr(expr)?; | 189 | let expr_id = self.expr_id(expr)?; |
177 | Some(self.infer.as_ref()?[expr_id].clone()) | 190 | Some(self.infer.as_ref()?[expr_id].clone()) |
178 | } | 191 | } |
179 | 192 | ||
180 | pub fn type_of_pat(&self, _db: &impl HirDatabase, pat: &ast::Pat) -> Option<crate::Ty> { | 193 | pub fn type_of_pat(&self, _db: &impl HirDatabase, pat: &ast::Pat) -> Option<crate::Ty> { |
181 | let pat_id = self.body_source_map.as_ref()?.node_pat(pat)?; | 194 | let pat_id = self.pat_id(pat)?; |
182 | Some(self.infer.as_ref()?[pat_id].clone()) | 195 | Some(self.infer.as_ref()?[pat_id].clone()) |
183 | } | 196 | } |
184 | 197 | ||
@@ -191,22 +204,22 @@ impl SourceAnalyzer { | |||
191 | } | 204 | } |
192 | 205 | ||
193 | pub fn resolve_method_call(&self, call: &ast::MethodCallExpr) -> Option<Function> { | 206 | pub fn resolve_method_call(&self, call: &ast::MethodCallExpr) -> Option<Function> { |
194 | let expr_id = self.body_source_map.as_ref()?.node_expr(&call.clone().into())?; | 207 | let expr_id = self.expr_id(&call.clone().into())?; |
195 | self.infer.as_ref()?.method_resolution(expr_id) | 208 | self.infer.as_ref()?.method_resolution(expr_id) |
196 | } | 209 | } |
197 | 210 | ||
198 | pub fn resolve_field(&self, field: &ast::FieldExpr) -> Option<crate::StructField> { | 211 | pub fn resolve_field(&self, field: &ast::FieldExpr) -> Option<crate::StructField> { |
199 | let expr_id = self.body_source_map.as_ref()?.node_expr(&field.clone().into())?; | 212 | let expr_id = self.expr_id(&field.clone().into())?; |
200 | self.infer.as_ref()?.field_resolution(expr_id) | 213 | self.infer.as_ref()?.field_resolution(expr_id) |
201 | } | 214 | } |
202 | 215 | ||
203 | pub fn resolve_record_literal(&self, record_lit: &ast::RecordLit) -> Option<crate::VariantDef> { | 216 | pub fn resolve_record_literal(&self, record_lit: &ast::RecordLit) -> Option<crate::VariantDef> { |
204 | let expr_id = self.body_source_map.as_ref()?.node_expr(&record_lit.clone().into())?; | 217 | let expr_id = self.expr_id(&record_lit.clone().into())?; |
205 | self.infer.as_ref()?.variant_resolution_for_expr(expr_id) | 218 | self.infer.as_ref()?.variant_resolution_for_expr(expr_id) |
206 | } | 219 | } |
207 | 220 | ||
208 | pub fn resolve_record_pattern(&self, record_pat: &ast::RecordPat) -> Option<crate::VariantDef> { | 221 | pub fn resolve_record_pattern(&self, record_pat: &ast::RecordPat) -> Option<crate::VariantDef> { |
209 | let pat_id = self.body_source_map.as_ref()?.node_pat(&record_pat.clone().into())?; | 222 | let pat_id = self.pat_id(&record_pat.clone().into())?; |
210 | self.infer.as_ref()?.variant_resolution_for_pat(pat_id) | 223 | self.infer.as_ref()?.variant_resolution_for_pat(pat_id) |
211 | } | 224 | } |
212 | 225 | ||
@@ -264,13 +277,13 @@ impl SourceAnalyzer { | |||
264 | 277 | ||
265 | pub fn resolve_path(&self, db: &impl HirDatabase, path: &ast::Path) -> Option<PathResolution> { | 278 | pub fn resolve_path(&self, db: &impl HirDatabase, path: &ast::Path) -> Option<PathResolution> { |
266 | if let Some(path_expr) = path.syntax().parent().and_then(ast::PathExpr::cast) { | 279 | if let Some(path_expr) = path.syntax().parent().and_then(ast::PathExpr::cast) { |
267 | let expr_id = self.body_source_map.as_ref()?.node_expr(&path_expr.into())?; | 280 | let expr_id = self.expr_id(&path_expr.into())?; |
268 | if let Some(assoc) = self.infer.as_ref()?.assoc_resolutions_for_expr(expr_id) { | 281 | if let Some(assoc) = self.infer.as_ref()?.assoc_resolutions_for_expr(expr_id) { |
269 | return Some(PathResolution::AssocItem(assoc)); | 282 | return Some(PathResolution::AssocItem(assoc)); |
270 | } | 283 | } |
271 | } | 284 | } |
272 | if let Some(path_pat) = path.syntax().parent().and_then(ast::PathPat::cast) { | 285 | if let Some(path_pat) = path.syntax().parent().and_then(ast::PathPat::cast) { |
273 | let pat_id = self.body_source_map.as_ref()?.node_pat(&path_pat.into())?; | 286 | let pat_id = self.pat_id(&path_pat.into())?; |
274 | if let Some(assoc) = self.infer.as_ref()?.assoc_resolutions_for_pat(pat_id) { | 287 | if let Some(assoc) = self.infer.as_ref()?.assoc_resolutions_for_pat(pat_id) { |
275 | return Some(PathResolution::AssocItem(assoc)); | 288 | return Some(PathResolution::AssocItem(assoc)); |
276 | } | 289 | } |
@@ -285,7 +298,7 @@ impl SourceAnalyzer { | |||
285 | let name = name_ref.as_name(); | 298 | let name = name_ref.as_name(); |
286 | let source_map = self.body_source_map.as_ref()?; | 299 | let source_map = self.body_source_map.as_ref()?; |
287 | let scopes = self.scopes.as_ref()?; | 300 | let scopes = self.scopes.as_ref()?; |
288 | let scope = scope_for(scopes, source_map, name_ref.syntax()); | 301 | let scope = scope_for(scopes, source_map, self.file_id.into(), name_ref.syntax()); |
289 | let ret = scopes | 302 | let ret = scopes |
290 | .scope_chain(scope) | 303 | .scope_chain(scope) |
291 | .flat_map(|scope| scopes.entries(scope).iter()) | 304 | .flat_map(|scope| scopes.entries(scope).iter()) |
@@ -418,11 +431,12 @@ impl SourceAnalyzer { | |||
418 | fn scope_for( | 431 | fn scope_for( |
419 | scopes: &ExprScopes, | 432 | scopes: &ExprScopes, |
420 | source_map: &BodySourceMap, | 433 | source_map: &BodySourceMap, |
434 | file_id: HirFileId, | ||
421 | node: &SyntaxNode, | 435 | node: &SyntaxNode, |
422 | ) -> Option<ScopeId> { | 436 | ) -> Option<ScopeId> { |
423 | node.ancestors() | 437 | node.ancestors() |
424 | .filter_map(ast::Expr::cast) | 438 | .filter_map(ast::Expr::cast) |
425 | .filter_map(|it| source_map.node_expr(&it)) | 439 | .filter_map(|it| source_map.node_expr(Source { file_id, ast: &it })) |
426 | .find_map(|it| scopes.scope_for(it)) | 440 | .find_map(|it| scopes.scope_for(it)) |
427 | } | 441 | } |
428 | 442 | ||