diff options
Diffstat (limited to 'crates/ra_hir/src/source_binder.rs')
-rw-r--r-- | crates/ra_hir/src/source_binder.rs | 79 |
1 files changed, 61 insertions, 18 deletions
diff --git a/crates/ra_hir/src/source_binder.rs b/crates/ra_hir/src/source_binder.rs index c42ceabdf..cbfeca3ab 100644 --- a/crates/ra_hir/src/source_binder.rs +++ b/crates/ra_hir/src/source_binder.rs | |||
@@ -13,7 +13,9 @@ use hir_def::{ | |||
13 | resolver::{self, resolver_for_scope, HasResolver, Resolver, TypeNs, ValueNs}, | 13 | resolver::{self, resolver_for_scope, HasResolver, Resolver, TypeNs, ValueNs}, |
14 | DefWithBodyId, | 14 | DefWithBodyId, |
15 | }; | 15 | }; |
16 | use hir_expand::{name::AsName, AstId, MacroCallId, MacroCallLoc, MacroFileKind, Source}; | 16 | use hir_expand::{ |
17 | name::AsName, AstId, HirFileId, MacroCallId, MacroCallLoc, MacroFileKind, Source, | ||
18 | }; | ||
17 | use ra_syntax::{ | 19 | use ra_syntax::{ |
18 | ast::{self, AstNode}, | 20 | ast::{self, AstNode}, |
19 | match_ast, AstPtr, | 21 | match_ast, AstPtr, |
@@ -24,11 +26,12 @@ use ra_syntax::{ | |||
24 | use crate::{ | 26 | use crate::{ |
25 | db::HirDatabase, | 27 | db::HirDatabase, |
26 | expr::{BodySourceMap, ExprScopes, ScopeId}, | 28 | expr::{BodySourceMap, ExprScopes, ScopeId}, |
27 | ids::LocationCtx, | 29 | ty::{ |
28 | ty::method_resolution::{self, implements_trait}, | 30 | method_resolution::{self, implements_trait}, |
31 | TraitEnvironment, | ||
32 | }, | ||
29 | Adt, AssocItem, Const, DefWithBody, Either, Enum, EnumVariant, FromSource, Function, | 33 | Adt, AssocItem, Const, DefWithBody, Either, Enum, EnumVariant, FromSource, Function, |
30 | GenericParam, HasBody, HirFileId, Local, MacroDef, Module, Name, Path, ScopeDef, Static, | 34 | GenericParam, Local, MacroDef, Name, Path, ScopeDef, Static, Struct, Trait, Ty, TypeAlias, |
31 | Struct, Trait, Ty, TypeAlias, | ||
32 | }; | 35 | }; |
33 | 36 | ||
34 | fn try_get_resolver_for_node(db: &impl HirDatabase, node: Source<&SyntaxNode>) -> Option<Resolver> { | 37 | fn try_get_resolver_for_node(db: &impl HirDatabase, node: Source<&SyntaxNode>) -> Option<Resolver> { |
@@ -67,16 +70,12 @@ fn def_with_body_from_child_node( | |||
67 | db: &impl HirDatabase, | 70 | db: &impl HirDatabase, |
68 | child: Source<&SyntaxNode>, | 71 | child: Source<&SyntaxNode>, |
69 | ) -> Option<DefWithBody> { | 72 | ) -> Option<DefWithBody> { |
70 | let module_source = crate::ModuleSource::from_child_node(db, child); | ||
71 | let module = Module::from_definition(db, Source::new(child.file_id, module_source))?; | ||
72 | let ctx = LocationCtx::new(db, module.id, child.file_id); | ||
73 | |||
74 | child.value.ancestors().find_map(|node| { | 73 | child.value.ancestors().find_map(|node| { |
75 | match_ast! { | 74 | match_ast! { |
76 | match node { | 75 | match node { |
77 | ast::FnDef(def) => { return Function::from_source(db, child.with_value(def)).map(DefWithBody::from); }, | 76 | ast::FnDef(def) => { return Function::from_source(db, child.with_value(def)).map(DefWithBody::from); }, |
78 | ast::ConstDef(def) => { return Const::from_source(db, child.with_value(def)).map(DefWithBody::from); }, | 77 | ast::ConstDef(def) => { return Const::from_source(db, child.with_value(def)).map(DefWithBody::from); }, |
79 | ast::StaticDef(def) => { Some(Static { id: ctx.to_def(&def) }.into()) }, | 78 | ast::StaticDef(def) => { return Static::from_source(db, child.with_value(def)).map(DefWithBody::from); }, |
80 | _ => { None }, | 79 | _ => { None }, |
81 | } | 80 | } |
82 | } | 81 | } |
@@ -131,6 +130,7 @@ pub struct ReferenceDescriptor { | |||
131 | } | 130 | } |
132 | 131 | ||
133 | pub struct Expansion { | 132 | pub struct Expansion { |
133 | macro_file_kind: MacroFileKind, | ||
134 | macro_call_id: MacroCallId, | 134 | macro_call_id: MacroCallId, |
135 | } | 135 | } |
136 | 136 | ||
@@ -145,7 +145,7 @@ impl Expansion { | |||
145 | } | 145 | } |
146 | 146 | ||
147 | pub fn file_id(&self) -> HirFileId { | 147 | pub fn file_id(&self) -> HirFileId { |
148 | self.macro_call_id.as_file(MacroFileKind::Items) | 148 | self.macro_call_id.as_file(self.macro_file_kind) |
149 | } | 149 | } |
150 | } | 150 | } |
151 | 151 | ||
@@ -157,8 +157,8 @@ impl SourceAnalyzer { | |||
157 | ) -> SourceAnalyzer { | 157 | ) -> SourceAnalyzer { |
158 | let def_with_body = def_with_body_from_child_node(db, node); | 158 | let def_with_body = def_with_body_from_child_node(db, node); |
159 | if let Some(def) = def_with_body { | 159 | if let Some(def) = def_with_body { |
160 | let source_map = def.body_source_map(db); | 160 | let (_body, source_map) = db.body_with_source_map(def.into()); |
161 | let scopes = def.expr_scopes(db); | 161 | let scopes = db.expr_scopes(def.into()); |
162 | let scope = match offset { | 162 | let scope = match offset { |
163 | None => scope_for(&scopes, &source_map, node), | 163 | None => scope_for(&scopes, &source_map, node), |
164 | Some(offset) => scope_for_offset(&scopes, &source_map, node.with_value(offset)), | 164 | Some(offset) => scope_for_offset(&scopes, &source_map, node.with_value(offset)), |
@@ -168,7 +168,7 @@ impl SourceAnalyzer { | |||
168 | resolver, | 168 | resolver, |
169 | body_owner: Some(def), | 169 | body_owner: Some(def), |
170 | body_source_map: Some(source_map), | 170 | body_source_map: Some(source_map), |
171 | infer: Some(def.infer(db)), | 171 | infer: Some(db.infer(def)), |
172 | scopes: Some(scopes), | 172 | scopes: Some(scopes), |
173 | file_id: node.file_id, | 173 | file_id: node.file_id, |
174 | } | 174 | } |
@@ -218,6 +218,11 @@ impl SourceAnalyzer { | |||
218 | self.infer.as_ref()?.field_resolution(expr_id) | 218 | self.infer.as_ref()?.field_resolution(expr_id) |
219 | } | 219 | } |
220 | 220 | ||
221 | pub fn resolve_record_field(&self, field: &ast::RecordField) -> Option<crate::StructField> { | ||
222 | let expr_id = self.expr_id(&field.expr()?)?; | ||
223 | self.infer.as_ref()?.record_field_resolution(expr_id) | ||
224 | } | ||
225 | |||
221 | pub fn resolve_record_literal(&self, record_lit: &ast::RecordLit) -> Option<crate::VariantDef> { | 226 | pub fn resolve_record_literal(&self, record_lit: &ast::RecordLit) -> Option<crate::VariantDef> { |
222 | let expr_id = self.expr_id(&record_lit.clone().into())?; | 227 | let expr_id = self.expr_id(&record_lit.clone().into())?; |
223 | self.infer.as_ref()?.variant_resolution_for_expr(expr_id) | 228 | self.infer.as_ref()?.variant_resolution_for_expr(expr_id) |
@@ -246,7 +251,7 @@ impl SourceAnalyzer { | |||
246 | let types = self.resolver.resolve_path_in_type_ns_fully(db, &path).map(|ty| match ty { | 251 | let types = self.resolver.resolve_path_in_type_ns_fully(db, &path).map(|ty| match ty { |
247 | TypeNs::SelfType(it) => PathResolution::SelfType(it.into()), | 252 | TypeNs::SelfType(it) => PathResolution::SelfType(it.into()), |
248 | TypeNs::GenericParam(idx) => PathResolution::GenericParam(GenericParam { | 253 | TypeNs::GenericParam(idx) => PathResolution::GenericParam(GenericParam { |
249 | parent: self.resolver.generic_def().unwrap().into(), | 254 | parent: self.resolver.generic_def().unwrap(), |
250 | idx, | 255 | idx, |
251 | }), | 256 | }), |
252 | TypeNs::AdtSelfType(it) | TypeNs::AdtId(it) => { | 257 | TypeNs::AdtSelfType(it) | TypeNs::AdtId(it) => { |
@@ -321,7 +326,7 @@ impl SourceAnalyzer { | |||
321 | resolver::ScopeDef::ImplSelfType(it) => ScopeDef::ImplSelfType(it.into()), | 326 | resolver::ScopeDef::ImplSelfType(it) => ScopeDef::ImplSelfType(it.into()), |
322 | resolver::ScopeDef::AdtSelfType(it) => ScopeDef::AdtSelfType(it.into()), | 327 | resolver::ScopeDef::AdtSelfType(it) => ScopeDef::AdtSelfType(it.into()), |
323 | resolver::ScopeDef::GenericParam(idx) => { | 328 | resolver::ScopeDef::GenericParam(idx) => { |
324 | let parent = self.resolver.generic_def().unwrap().into(); | 329 | let parent = self.resolver.generic_def().unwrap(); |
325 | ScopeDef::GenericParam(GenericParam { parent, idx }) | 330 | ScopeDef::GenericParam(GenericParam { parent, idx }) |
326 | } | 331 | } |
327 | resolver::ScopeDef::Local(pat_id) => { | 332 | resolver::ScopeDef::Local(pat_id) => { |
@@ -406,7 +411,10 @@ impl SourceAnalyzer { | |||
406 | // There should be no inference vars in types passed here | 411 | // There should be no inference vars in types passed here |
407 | // FIXME check that? | 412 | // FIXME check that? |
408 | let canonical = crate::ty::Canonical { value: ty, num_vars: 0 }; | 413 | let canonical = crate::ty::Canonical { value: ty, num_vars: 0 }; |
409 | crate::ty::autoderef(db, &self.resolver, canonical).map(|canonical| canonical.value) | 414 | let krate = self.resolver.krate(); |
415 | let environment = TraitEnvironment::lower(db, &self.resolver); | ||
416 | let ty = crate::ty::InEnvironment { value: canonical, environment }; | ||
417 | crate::ty::autoderef(db, krate, ty).map(|canonical| canonical.value) | ||
410 | } | 418 | } |
411 | 419 | ||
412 | /// Checks that particular type `ty` implements `std::future::Future`. | 420 | /// Checks that particular type `ty` implements `std::future::Future`. |
@@ -439,7 +447,10 @@ impl SourceAnalyzer { | |||
439 | db.ast_id_map(macro_call.file_id).ast_id(macro_call.value), | 447 | db.ast_id_map(macro_call.file_id).ast_id(macro_call.value), |
440 | ); | 448 | ); |
441 | let macro_call_loc = MacroCallLoc { def, ast_id }; | 449 | let macro_call_loc = MacroCallLoc { def, ast_id }; |
442 | Some(Expansion { macro_call_id: db.intern_macro(macro_call_loc) }) | 450 | Some(Expansion { |
451 | macro_call_id: db.intern_macro(macro_call_loc), | ||
452 | macro_file_kind: to_macro_file_kind(macro_call.value), | ||
453 | }) | ||
443 | } | 454 | } |
444 | 455 | ||
445 | #[cfg(test)] | 456 | #[cfg(test)] |
@@ -538,3 +549,35 @@ fn adjust( | |||
538 | }) | 549 | }) |
539 | .map(|(_ptr, scope)| *scope) | 550 | .map(|(_ptr, scope)| *scope) |
540 | } | 551 | } |
552 | |||
553 | /// Given a `ast::MacroCall`, return what `MacroKindFile` it belongs to. | ||
554 | /// FIXME: Not completed | ||
555 | fn to_macro_file_kind(macro_call: &ast::MacroCall) -> MacroFileKind { | ||
556 | let syn = macro_call.syntax(); | ||
557 | let parent = match syn.parent() { | ||
558 | Some(it) => it, | ||
559 | None => { | ||
560 | // FIXME: | ||
561 | // If it is root, which means the parent HirFile | ||
562 | // MacroKindFile must be non-items | ||
563 | // return expr now. | ||
564 | return MacroFileKind::Expr; | ||
565 | } | ||
566 | }; | ||
567 | |||
568 | match parent.kind() { | ||
569 | MACRO_ITEMS | SOURCE_FILE => MacroFileKind::Items, | ||
570 | LET_STMT => { | ||
571 | // FIXME: Handle Pattern | ||
572 | MacroFileKind::Expr | ||
573 | } | ||
574 | EXPR_STMT => MacroFileKind::Statements, | ||
575 | BLOCK => MacroFileKind::Statements, | ||
576 | ARG_LIST => MacroFileKind::Expr, | ||
577 | TRY_EXPR => MacroFileKind::Expr, | ||
578 | _ => { | ||
579 | // Unknown , Just guess it is `Items` | ||
580 | MacroFileKind::Items | ||
581 | } | ||
582 | } | ||
583 | } | ||