diff options
Diffstat (limited to 'crates/ra_hir/src')
-rw-r--r-- | crates/ra_hir/src/code_model_api.rs | 10 | ||||
-rw-r--r-- | crates/ra_hir/src/expr.rs | 16 | ||||
-rw-r--r-- | crates/ra_hir/src/expr/scope.rs | 2 | ||||
-rw-r--r-- | crates/ra_hir/src/lib.rs | 1 | ||||
-rw-r--r-- | crates/ra_hir/src/source_binder.rs | 100 |
5 files changed, 109 insertions, 20 deletions
diff --git a/crates/ra_hir/src/code_model_api.rs b/crates/ra_hir/src/code_model_api.rs index f13a6b37a..660edf006 100644 --- a/crates/ra_hir/src/code_model_api.rs +++ b/crates/ra_hir/src/code_model_api.rs | |||
@@ -450,10 +450,6 @@ impl DefWithBody { | |||
450 | db.infer(*self) | 450 | db.infer(*self) |
451 | } | 451 | } |
452 | 452 | ||
453 | pub fn body_source_map(&self, db: &impl HirDatabase) -> Arc<BodySourceMap> { | ||
454 | db.body_with_source_map(*self).1 | ||
455 | } | ||
456 | |||
457 | pub fn body(&self, db: &impl HirDatabase) -> Arc<Body> { | 453 | pub fn body(&self, db: &impl HirDatabase) -> Arc<Body> { |
458 | db.body_hir(*self) | 454 | db.body_hir(*self) |
459 | } | 455 | } |
@@ -523,7 +519,7 @@ impl Function { | |||
523 | self.signature(db).name.clone() | 519 | self.signature(db).name.clone() |
524 | } | 520 | } |
525 | 521 | ||
526 | pub fn body_source_map(&self, db: &impl HirDatabase) -> Arc<BodySourceMap> { | 522 | pub(crate) fn body_source_map(&self, db: &impl HirDatabase) -> Arc<BodySourceMap> { |
527 | db.body_with_source_map((*self).into()).1 | 523 | db.body_with_source_map((*self).into()).1 |
528 | } | 524 | } |
529 | 525 | ||
@@ -606,7 +602,7 @@ impl Const { | |||
606 | db.infer((*self).into()) | 602 | db.infer((*self).into()) |
607 | } | 603 | } |
608 | 604 | ||
609 | pub fn body_source_map(&self, db: &impl HirDatabase) -> Arc<BodySourceMap> { | 605 | pub(crate) fn body_source_map(&self, db: &impl HirDatabase) -> Arc<BodySourceMap> { |
610 | db.body_with_source_map((*self).into()).1 | 606 | db.body_with_source_map((*self).into()).1 |
611 | } | 607 | } |
612 | 608 | ||
@@ -679,7 +675,7 @@ impl Static { | |||
679 | db.infer((*self).into()) | 675 | db.infer((*self).into()) |
680 | } | 676 | } |
681 | 677 | ||
682 | pub fn body_source_map(&self, db: &impl HirDatabase) -> Arc<BodySourceMap> { | 678 | pub(crate) fn body_source_map(&self, db: &impl HirDatabase) -> Arc<BodySourceMap> { |
683 | db.body_with_source_map((*self).into()).1 | 679 | db.body_with_source_map((*self).into()).1 |
684 | } | 680 | } |
685 | } | 681 | } |
diff --git a/crates/ra_hir/src/expr.rs b/crates/ra_hir/src/expr.rs index a8e115e47..3806a3605 100644 --- a/crates/ra_hir/src/expr.rs +++ b/crates/ra_hir/src/expr.rs | |||
@@ -117,31 +117,27 @@ impl Index<PatId> for Body { | |||
117 | } | 117 | } |
118 | 118 | ||
119 | impl BodySourceMap { | 119 | impl BodySourceMap { |
120 | pub fn expr_syntax(&self, expr: ExprId) -> Option<SyntaxNodePtr> { | 120 | pub(crate) fn expr_syntax(&self, expr: ExprId) -> Option<SyntaxNodePtr> { |
121 | self.expr_map_back.get(expr).cloned() | 121 | self.expr_map_back.get(expr).cloned() |
122 | } | 122 | } |
123 | 123 | ||
124 | pub fn syntax_expr(&self, ptr: SyntaxNodePtr) -> Option<ExprId> { | 124 | pub(crate) fn syntax_expr(&self, ptr: SyntaxNodePtr) -> Option<ExprId> { |
125 | self.expr_map.get(&ptr).cloned() | 125 | self.expr_map.get(&ptr).cloned() |
126 | } | 126 | } |
127 | 127 | ||
128 | pub fn node_expr(&self, node: &ast::Expr) -> Option<ExprId> { | 128 | pub(crate) fn node_expr(&self, node: &ast::Expr) -> Option<ExprId> { |
129 | self.expr_map.get(&SyntaxNodePtr::new(node.syntax())).cloned() | 129 | self.expr_map.get(&SyntaxNodePtr::new(node.syntax())).cloned() |
130 | } | 130 | } |
131 | 131 | ||
132 | pub fn pat_syntax(&self, pat: PatId) -> Option<PatPtr> { | 132 | pub(crate) fn pat_syntax(&self, pat: PatId) -> Option<PatPtr> { |
133 | self.pat_map_back.get(pat).cloned() | 133 | self.pat_map_back.get(pat).cloned() |
134 | } | 134 | } |
135 | 135 | ||
136 | pub fn syntax_pat(&self, ptr: PatPtr) -> Option<PatId> { | 136 | pub(crate) fn node_pat(&self, node: &ast::Pat) -> Option<PatId> { |
137 | self.pat_map.get(&ptr).cloned() | ||
138 | } | ||
139 | |||
140 | pub fn node_pat(&self, node: &ast::Pat) -> Option<PatId> { | ||
141 | self.pat_map.get(&Either::A(AstPtr::new(node))).cloned() | 137 | self.pat_map.get(&Either::A(AstPtr::new(node))).cloned() |
142 | } | 138 | } |
143 | 139 | ||
144 | pub fn field_syntax(&self, expr: ExprId, field: usize) -> AstPtr<ast::NamedField> { | 140 | pub(crate) fn field_syntax(&self, expr: ExprId, field: usize) -> AstPtr<ast::NamedField> { |
145 | self.field_map[&(expr, field)].clone() | 141 | self.field_map[&(expr, field)].clone() |
146 | } | 142 | } |
147 | } | 143 | } |
diff --git a/crates/ra_hir/src/expr/scope.rs b/crates/ra_hir/src/expr/scope.rs index 725b6c00e..404c979eb 100644 --- a/crates/ra_hir/src/expr/scope.rs +++ b/crates/ra_hir/src/expr/scope.rs | |||
@@ -109,7 +109,7 @@ impl ExprScopes { | |||
109 | 109 | ||
110 | #[derive(Debug, Clone, PartialEq, Eq)] | 110 | #[derive(Debug, Clone, PartialEq, Eq)] |
111 | pub struct ScopesWithSourceMap { | 111 | pub struct ScopesWithSourceMap { |
112 | pub source_map: Arc<BodySourceMap>, | 112 | pub(crate) source_map: Arc<BodySourceMap>, |
113 | pub scopes: Arc<ExprScopes>, | 113 | pub scopes: Arc<ExprScopes>, |
114 | } | 114 | } |
115 | 115 | ||
diff --git a/crates/ra_hir/src/lib.rs b/crates/ra_hir/src/lib.rs index 0881939a2..59b402c57 100644 --- a/crates/ra_hir/src/lib.rs +++ b/crates/ra_hir/src/lib.rs | |||
@@ -66,6 +66,7 @@ pub use self::{ | |||
66 | adt::AdtDef, | 66 | adt::AdtDef, |
67 | expr::{ExprScopes, ScopesWithSourceMap, ScopeEntryWithSyntax}, | 67 | expr::{ExprScopes, ScopesWithSourceMap, ScopeEntryWithSyntax}, |
68 | resolve::{Resolver, Resolution}, | 68 | resolve::{Resolver, Resolution}, |
69 | source_binder::{SourceAnalyser, PathResolution}, | ||
69 | }; | 70 | }; |
70 | 71 | ||
71 | pub use self::code_model_api::{ | 72 | pub use self::code_model_api::{ |
diff --git a/crates/ra_hir/src/source_binder.rs b/crates/ra_hir/src/source_binder.rs index 182ed4c91..79e304383 100644 --- a/crates/ra_hir/src/source_binder.rs +++ b/crates/ra_hir/src/source_binder.rs | |||
@@ -5,15 +5,17 @@ | |||
5 | /// | 5 | /// |
6 | /// So, this modules should not be used during hir construction, it exists | 6 | /// So, this modules should not be used during hir construction, it exists |
7 | /// purely for "IDE needs". | 7 | /// purely for "IDE needs". |
8 | use std::sync::Arc; | ||
9 | |||
8 | use ra_db::{FileId, FilePosition}; | 10 | use ra_db::{FileId, FilePosition}; |
9 | use ra_syntax::{ | 11 | use ra_syntax::{ |
10 | SyntaxNode, | 12 | SyntaxNode, AstPtr, |
11 | ast::{self, AstNode, NameOwner}, | 13 | ast::{self, AstNode, NameOwner}, |
12 | algo::{find_node_at_offset, find_token_at_offset}, | 14 | algo::{find_node_at_offset, find_token_at_offset}, |
13 | }; | 15 | }; |
14 | 16 | ||
15 | use crate::{ | 17 | use crate::{ |
16 | HirDatabase, Function, Struct, Enum,Const,Static, | 18 | HirDatabase, Function, Struct, Enum, Const, Static, Either, |
17 | AsName, Module, HirFileId, Crate, Trait, Resolver, | 19 | AsName, Module, HirFileId, Crate, Trait, Resolver, |
18 | ids::LocationCtx, | 20 | ids::LocationCtx, |
19 | expr, AstId | 21 | expr, AstId |
@@ -258,3 +260,97 @@ fn try_get_resolver_for_node( | |||
258 | None | 260 | None |
259 | } | 261 | } |
260 | } | 262 | } |
263 | |||
264 | // Name is bad, don't use inside HIR | ||
265 | #[derive(Debug)] | ||
266 | pub struct SourceAnalyser { | ||
267 | resolver: Resolver, | ||
268 | body_source_map: Option<Arc<crate::expr::BodySourceMap>>, | ||
269 | infer: Option<Arc<crate::ty::InferenceResult>>, | ||
270 | } | ||
271 | |||
272 | #[derive(Debug, Clone, PartialEq, Eq)] | ||
273 | pub enum PathResolution { | ||
274 | /// An item | ||
275 | Def(crate::ModuleDef), | ||
276 | /// A local binding (only value namespace) | ||
277 | LocalBinding(crate::expr::PatId), | ||
278 | /// A generic parameter | ||
279 | GenericParam(u32), | ||
280 | SelfType(crate::ImplBlock), | ||
281 | AssocItem(crate::ImplItem), | ||
282 | } | ||
283 | |||
284 | impl SourceAnalyser { | ||
285 | pub fn new(db: &impl HirDatabase, file_id: FileId, node: &SyntaxNode) -> SourceAnalyser { | ||
286 | let resolver = resolver_for_node(db, file_id, node); | ||
287 | let function = function_from_child_node(db, file_id, node); | ||
288 | if let Some(function) = function { | ||
289 | SourceAnalyser { | ||
290 | resolver, | ||
291 | body_source_map: Some(function.body_source_map(db)), | ||
292 | infer: Some(function.infer(db)), | ||
293 | } | ||
294 | } else { | ||
295 | SourceAnalyser { resolver, body_source_map: None, infer: None } | ||
296 | } | ||
297 | } | ||
298 | |||
299 | pub fn type_of(&self, _db: &impl HirDatabase, expr: &ast::Expr) -> Option<crate::Ty> { | ||
300 | let expr_id = self.body_source_map.as_ref()?.node_expr(expr)?; | ||
301 | Some(self.infer.as_ref()?[expr_id].clone()) | ||
302 | } | ||
303 | |||
304 | pub fn type_of_pat(&self, _db: &impl HirDatabase, pat: &ast::Pat) -> Option<crate::Ty> { | ||
305 | let pat_id = self.body_source_map.as_ref()?.node_pat(pat)?; | ||
306 | Some(self.infer.as_ref()?[pat_id].clone()) | ||
307 | } | ||
308 | |||
309 | pub fn resolve_method_call(&self, call: &ast::MethodCallExpr) -> Option<Function> { | ||
310 | let expr_id = self.body_source_map.as_ref()?.node_expr(call.into())?; | ||
311 | self.infer.as_ref()?.method_resolution(expr_id) | ||
312 | } | ||
313 | |||
314 | pub fn resolve_field(&self, field: &ast::FieldExpr) -> Option<crate::StructField> { | ||
315 | let expr_id = self.body_source_map.as_ref()?.node_expr(field.into())?; | ||
316 | self.infer.as_ref()?.field_resolution(expr_id) | ||
317 | } | ||
318 | |||
319 | pub fn resolve_path(&self, db: &impl HirDatabase, path: &ast::Path) -> Option<PathResolution> { | ||
320 | if let Some(path_expr) = path.syntax().parent().and_then(ast::PathExpr::cast) { | ||
321 | let expr_id = self.body_source_map.as_ref()?.node_expr(path_expr.into())?; | ||
322 | if let Some(assoc) = self.infer.as_ref()?.assoc_resolutions_for_expr(expr_id) { | ||
323 | return Some(PathResolution::AssocItem(assoc)); | ||
324 | } | ||
325 | } | ||
326 | if let Some(path_pat) = path.syntax().parent().and_then(ast::PathPat::cast) { | ||
327 | let pat_id = self.body_source_map.as_ref()?.node_pat(path_pat.into())?; | ||
328 | if let Some(assoc) = self.infer.as_ref()?.assoc_resolutions_for_pat(pat_id) { | ||
329 | return Some(PathResolution::AssocItem(assoc)); | ||
330 | } | ||
331 | } | ||
332 | let hir_path = crate::Path::from_ast(path)?; | ||
333 | let res = self.resolver.resolve_path(db, &hir_path); | ||
334 | let res = res.clone().take_types().or_else(|| res.take_values())?; | ||
335 | Some(res.into()) | ||
336 | } | ||
337 | |||
338 | pub fn pat_syntax( | ||
339 | &self, | ||
340 | _db: &impl HirDatabase, | ||
341 | pat: crate::expr::PatId, | ||
342 | ) -> Option<Either<AstPtr<ast::Pat>, AstPtr<ast::SelfParam>>> { | ||
343 | self.body_source_map.as_ref()?.pat_syntax(pat) | ||
344 | } | ||
345 | } | ||
346 | |||
347 | impl From<crate::Resolution> for PathResolution { | ||
348 | fn from(res: crate::Resolution) -> PathResolution { | ||
349 | match res { | ||
350 | crate::Resolution::Def(it) => PathResolution::Def(it), | ||
351 | crate::Resolution::LocalBinding(it) => PathResolution::LocalBinding(it), | ||
352 | crate::Resolution::GenericParam(it) => PathResolution::GenericParam(it), | ||
353 | crate::Resolution::SelfType(it) => PathResolution::SelfType(it), | ||
354 | } | ||
355 | } | ||
356 | } | ||