aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_hir/src
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_hir/src')
-rw-r--r--crates/ra_hir/src/code_model_api.rs10
-rw-r--r--crates/ra_hir/src/expr.rs16
-rw-r--r--crates/ra_hir/src/expr/scope.rs2
-rw-r--r--crates/ra_hir/src/lib.rs1
-rw-r--r--crates/ra_hir/src/source_binder.rs100
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
119impl BodySourceMap { 119impl 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)]
111pub struct ScopesWithSourceMap { 111pub 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
71pub use self::code_model_api::{ 72pub 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".
8use std::sync::Arc;
9
8use ra_db::{FileId, FilePosition}; 10use ra_db::{FileId, FilePosition};
9use ra_syntax::{ 11use 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
15use crate::{ 17use 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)]
266pub 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)]
273pub 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
284impl 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
347impl 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}