diff options
Diffstat (limited to 'crates/ra_hir/src/source_binder.rs')
-rw-r--r-- | crates/ra_hir/src/source_binder.rs | 115 |
1 files changed, 87 insertions, 28 deletions
diff --git a/crates/ra_hir/src/source_binder.rs b/crates/ra_hir/src/source_binder.rs index 727310f06..797f90d50 100644 --- a/crates/ra_hir/src/source_binder.rs +++ b/crates/ra_hir/src/source_binder.rs | |||
@@ -10,6 +10,8 @@ use std::sync::Arc; | |||
10 | use hir_def::{ | 10 | use hir_def::{ |
11 | expr::{ExprId, PatId}, | 11 | expr::{ExprId, PatId}, |
12 | path::known, | 12 | path::known, |
13 | resolver::{self, resolver_for_scope, HasResolver, Resolver, TypeNs, ValueNs}, | ||
14 | DefWithBodyId, | ||
13 | }; | 15 | }; |
14 | use hir_expand::{name::AsName, AstId, MacroCallId, MacroCallLoc, MacroFileKind, Source}; | 16 | use hir_expand::{name::AsName, AstId, MacroCallId, MacroCallLoc, MacroFileKind, Source}; |
15 | use ra_syntax::{ | 17 | use ra_syntax::{ |
@@ -21,12 +23,12 @@ use ra_syntax::{ | |||
21 | 23 | ||
22 | use crate::{ | 24 | use crate::{ |
23 | db::HirDatabase, | 25 | db::HirDatabase, |
24 | expr::{self, BodySourceMap, ExprScopes, ScopeId}, | 26 | expr::{BodySourceMap, ExprScopes, ScopeId}, |
25 | ids::LocationCtx, | 27 | ids::LocationCtx, |
26 | resolve::{HasResolver, ScopeDef, TypeNs, ValueNs}, | ||
27 | ty::method_resolution::{self, implements_trait}, | 28 | ty::method_resolution::{self, implements_trait}, |
28 | AssocItem, Const, DefWithBody, Either, Enum, FromSource, Function, GenericParam, HasBody, | 29 | Adt, AssocItem, Const, DefWithBody, Either, Enum, EnumVariant, FromSource, Function, |
29 | HirFileId, Local, MacroDef, Module, Name, Path, Resolver, Static, Struct, Ty, | 30 | GenericParam, HasBody, HirFileId, Local, MacroDef, Module, Name, Path, ScopeDef, Static, |
31 | Struct, Trait, Ty, TypeAlias, | ||
30 | }; | 32 | }; |
31 | 33 | ||
32 | fn try_get_resolver_for_node(db: &impl HirDatabase, node: Source<&SyntaxNode>) -> Option<Resolver> { | 34 | fn try_get_resolver_for_node(db: &impl HirDatabase, node: Source<&SyntaxNode>) -> Option<Resolver> { |
@@ -34,23 +36,25 @@ fn try_get_resolver_for_node(db: &impl HirDatabase, node: Source<&SyntaxNode>) - | |||
34 | match (node.value) { | 36 | match (node.value) { |
35 | ast::Module(it) => { | 37 | ast::Module(it) => { |
36 | let src = node.with_value(it); | 38 | let src = node.with_value(it); |
37 | Some(crate::Module::from_declaration(db, src)?.resolver(db)) | 39 | Some(crate::Module::from_declaration(db, src)?.id.resolver(db)) |
38 | }, | 40 | }, |
39 | ast::SourceFile(it) => { | 41 | ast::SourceFile(it) => { |
40 | let src = node.with_value(crate::ModuleSource::SourceFile(it)); | 42 | let src = node.with_value(crate::ModuleSource::SourceFile(it)); |
41 | Some(crate::Module::from_definition(db, src)?.resolver(db)) | 43 | Some(crate::Module::from_definition(db, src)?.id.resolver(db)) |
42 | }, | 44 | }, |
43 | ast::StructDef(it) => { | 45 | ast::StructDef(it) => { |
44 | let src = node.with_value(it); | 46 | let src = node.with_value(it); |
45 | Some(Struct::from_source(db, src)?.resolver(db)) | 47 | Some(Struct::from_source(db, src)?.id.resolver(db)) |
46 | }, | 48 | }, |
47 | ast::EnumDef(it) => { | 49 | ast::EnumDef(it) => { |
48 | let src = node.with_value(it); | 50 | let src = node.with_value(it); |
49 | Some(Enum::from_source(db, src)?.resolver(db)) | 51 | Some(Enum::from_source(db, src)?.id.resolver(db)) |
50 | }, | 52 | }, |
51 | _ => match node.value.kind() { | 53 | _ => match node.value.kind() { |
52 | FN_DEF | CONST_DEF | STATIC_DEF => { | 54 | FN_DEF | CONST_DEF | STATIC_DEF => { |
53 | Some(def_with_body_from_child_node(db, node)?.resolver(db)) | 55 | let def = def_with_body_from_child_node(db, node)?; |
56 | let def = DefWithBodyId::from(def); | ||
57 | Some(def.resolver(db)) | ||
54 | } | 58 | } |
55 | // FIXME add missing cases | 59 | // FIXME add missing cases |
56 | _ => None | 60 | _ => None |
@@ -127,6 +131,7 @@ pub struct ReferenceDescriptor { | |||
127 | } | 131 | } |
128 | 132 | ||
129 | pub struct Expansion { | 133 | pub struct Expansion { |
134 | macro_file_kind: MacroFileKind, | ||
130 | macro_call_id: MacroCallId, | 135 | macro_call_id: MacroCallId, |
131 | } | 136 | } |
132 | 137 | ||
@@ -141,7 +146,7 @@ impl Expansion { | |||
141 | } | 146 | } |
142 | 147 | ||
143 | pub fn file_id(&self) -> HirFileId { | 148 | pub fn file_id(&self) -> HirFileId { |
144 | self.macro_call_id.as_file(MacroFileKind::Items) | 149 | self.macro_call_id.as_file(self.macro_file_kind) |
145 | } | 150 | } |
146 | } | 151 | } |
147 | 152 | ||
@@ -159,7 +164,7 @@ impl SourceAnalyzer { | |||
159 | None => scope_for(&scopes, &source_map, node), | 164 | None => scope_for(&scopes, &source_map, node), |
160 | Some(offset) => scope_for_offset(&scopes, &source_map, node.with_value(offset)), | 165 | Some(offset) => scope_for_offset(&scopes, &source_map, node.with_value(offset)), |
161 | }; | 166 | }; |
162 | let resolver = expr::resolver_for_scope(db, def, scope); | 167 | let resolver = resolver_for_scope(db, def.into(), scope); |
163 | SourceAnalyzer { | 168 | SourceAnalyzer { |
164 | resolver, | 169 | resolver, |
165 | body_owner: Some(def), | 170 | body_owner: Some(def), |
@@ -231,7 +236,7 @@ impl SourceAnalyzer { | |||
231 | ) -> Option<MacroDef> { | 236 | ) -> Option<MacroDef> { |
232 | // This must be a normal source file rather than macro file. | 237 | // This must be a normal source file rather than macro file. |
233 | let path = macro_call.path().and_then(Path::from_ast)?; | 238 | let path = macro_call.path().and_then(Path::from_ast)?; |
234 | self.resolver.resolve_path_as_macro(db, &path) | 239 | self.resolver.resolve_path_as_macro(db, &path).map(|it| it.into()) |
235 | } | 240 | } |
236 | 241 | ||
237 | pub fn resolve_hir_path( | 242 | pub fn resolve_hir_path( |
@@ -240,16 +245,18 @@ impl SourceAnalyzer { | |||
240 | path: &crate::Path, | 245 | path: &crate::Path, |
241 | ) -> Option<PathResolution> { | 246 | ) -> Option<PathResolution> { |
242 | let types = self.resolver.resolve_path_in_type_ns_fully(db, &path).map(|ty| match ty { | 247 | let types = self.resolver.resolve_path_in_type_ns_fully(db, &path).map(|ty| match ty { |
243 | TypeNs::SelfType(it) => PathResolution::SelfType(it), | 248 | TypeNs::SelfType(it) => PathResolution::SelfType(it.into()), |
244 | TypeNs::GenericParam(idx) => PathResolution::GenericParam(GenericParam { | 249 | TypeNs::GenericParam(idx) => PathResolution::GenericParam(GenericParam { |
245 | parent: self.resolver.generic_def().unwrap(), | 250 | parent: self.resolver.generic_def().unwrap().into(), |
246 | idx, | 251 | idx, |
247 | }), | 252 | }), |
248 | TypeNs::AdtSelfType(it) | TypeNs::Adt(it) => PathResolution::Def(it.into()), | 253 | TypeNs::AdtSelfType(it) | TypeNs::AdtId(it) => { |
249 | TypeNs::EnumVariant(it) => PathResolution::Def(it.into()), | 254 | PathResolution::Def(Adt::from(it).into()) |
250 | TypeNs::TypeAlias(it) => PathResolution::Def(it.into()), | 255 | } |
256 | TypeNs::EnumVariantId(it) => PathResolution::Def(EnumVariant::from(it).into()), | ||
257 | TypeNs::TypeAliasId(it) => PathResolution::Def(TypeAlias::from(it).into()), | ||
251 | TypeNs::BuiltinType(it) => PathResolution::Def(it.into()), | 258 | TypeNs::BuiltinType(it) => PathResolution::Def(it.into()), |
252 | TypeNs::Trait(it) => PathResolution::Def(it.into()), | 259 | TypeNs::TraitId(it) => PathResolution::Def(Trait::from(it).into()), |
253 | }); | 260 | }); |
254 | let values = self.resolver.resolve_path_in_value_ns_fully(db, &path).and_then(|val| { | 261 | let values = self.resolver.resolve_path_in_value_ns_fully(db, &path).and_then(|val| { |
255 | let res = match val { | 262 | let res = match val { |
@@ -257,11 +264,11 @@ impl SourceAnalyzer { | |||
257 | let var = Local { parent: self.body_owner?, pat_id }; | 264 | let var = Local { parent: self.body_owner?, pat_id }; |
258 | PathResolution::Local(var) | 265 | PathResolution::Local(var) |
259 | } | 266 | } |
260 | ValueNs::Function(it) => PathResolution::Def(it.into()), | 267 | ValueNs::FunctionId(it) => PathResolution::Def(Function::from(it).into()), |
261 | ValueNs::Const(it) => PathResolution::Def(it.into()), | 268 | ValueNs::ConstId(it) => PathResolution::Def(Const::from(it).into()), |
262 | ValueNs::Static(it) => PathResolution::Def(it.into()), | 269 | ValueNs::StaticId(it) => PathResolution::Def(Static::from(it).into()), |
263 | ValueNs::Struct(it) => PathResolution::Def(it.into()), | 270 | ValueNs::StructId(it) => PathResolution::Def(Struct::from(it).into()), |
264 | ValueNs::EnumVariant(it) => PathResolution::Def(it.into()), | 271 | ValueNs::EnumVariantId(it) => PathResolution::Def(EnumVariant::from(it).into()), |
265 | }; | 272 | }; |
266 | Some(res) | 273 | Some(res) |
267 | }); | 274 | }); |
@@ -272,7 +279,9 @@ impl SourceAnalyzer { | |||
272 | .take_types() | 279 | .take_types() |
273 | .map(|it| PathResolution::Def(it.into())); | 280 | .map(|it| PathResolution::Def(it.into())); |
274 | types.or(values).or(items).or_else(|| { | 281 | types.or(values).or(items).or_else(|| { |
275 | self.resolver.resolve_path_as_macro(db, &path).map(|def| PathResolution::Macro(def)) | 282 | self.resolver |
283 | .resolve_path_as_macro(db, &path) | ||
284 | .map(|def| PathResolution::Macro(def.into())) | ||
276 | }) | 285 | }) |
277 | } | 286 | } |
278 | 287 | ||
@@ -307,7 +316,22 @@ impl SourceAnalyzer { | |||
307 | } | 316 | } |
308 | 317 | ||
309 | pub fn process_all_names(&self, db: &impl HirDatabase, f: &mut dyn FnMut(Name, ScopeDef)) { | 318 | pub fn process_all_names(&self, db: &impl HirDatabase, f: &mut dyn FnMut(Name, ScopeDef)) { |
310 | self.resolver.process_all_names(db, f) | 319 | self.resolver.process_all_names(db, &mut |name, def| { |
320 | let def = match def { | ||
321 | resolver::ScopeDef::PerNs(it) => it.into(), | ||
322 | resolver::ScopeDef::ImplSelfType(it) => ScopeDef::ImplSelfType(it.into()), | ||
323 | resolver::ScopeDef::AdtSelfType(it) => ScopeDef::AdtSelfType(it.into()), | ||
324 | resolver::ScopeDef::GenericParam(idx) => { | ||
325 | let parent = self.resolver.generic_def().unwrap().into(); | ||
326 | ScopeDef::GenericParam(GenericParam { parent, idx }) | ||
327 | } | ||
328 | resolver::ScopeDef::Local(pat_id) => { | ||
329 | let parent = self.resolver.body_owner().unwrap().into(); | ||
330 | ScopeDef::Local(Local { parent, pat_id }) | ||
331 | } | ||
332 | }; | ||
333 | f(name, def) | ||
334 | }) | ||
311 | } | 335 | } |
312 | 336 | ||
313 | // FIXME: we only use this in `inline_local_variable` assist, ideally, we | 337 | // FIXME: we only use this in `inline_local_variable` assist, ideally, we |
@@ -392,7 +416,7 @@ impl SourceAnalyzer { | |||
392 | let std_future_path = known::std_future_future(); | 416 | let std_future_path = known::std_future_future(); |
393 | 417 | ||
394 | let std_future_trait = match self.resolver.resolve_known_trait(db, &std_future_path) { | 418 | let std_future_trait = match self.resolver.resolve_known_trait(db, &std_future_path) { |
395 | Some(it) => it, | 419 | Some(it) => it.into(), |
396 | _ => return false, | 420 | _ => return false, |
397 | }; | 421 | }; |
398 | 422 | ||
@@ -402,7 +426,7 @@ impl SourceAnalyzer { | |||
402 | }; | 426 | }; |
403 | 427 | ||
404 | let canonical_ty = crate::ty::Canonical { value: ty, num_vars: 0 }; | 428 | let canonical_ty = crate::ty::Canonical { value: ty, num_vars: 0 }; |
405 | implements_trait(&canonical_ty, db, &self.resolver, krate, std_future_trait) | 429 | implements_trait(&canonical_ty, db, &self.resolver, krate.into(), std_future_trait) |
406 | } | 430 | } |
407 | 431 | ||
408 | pub fn expand( | 432 | pub fn expand( |
@@ -416,7 +440,10 @@ impl SourceAnalyzer { | |||
416 | db.ast_id_map(macro_call.file_id).ast_id(macro_call.value), | 440 | db.ast_id_map(macro_call.file_id).ast_id(macro_call.value), |
417 | ); | 441 | ); |
418 | let macro_call_loc = MacroCallLoc { def, ast_id }; | 442 | let macro_call_loc = MacroCallLoc { def, ast_id }; |
419 | Some(Expansion { macro_call_id: db.intern_macro(macro_call_loc) }) | 443 | Some(Expansion { |
444 | macro_call_id: db.intern_macro(macro_call_loc), | ||
445 | macro_file_kind: to_macro_file_kind(macro_call.value), | ||
446 | }) | ||
420 | } | 447 | } |
421 | 448 | ||
422 | #[cfg(test)] | 449 | #[cfg(test)] |
@@ -515,3 +542,35 @@ fn adjust( | |||
515 | }) | 542 | }) |
516 | .map(|(_ptr, scope)| *scope) | 543 | .map(|(_ptr, scope)| *scope) |
517 | } | 544 | } |
545 | |||
546 | /// Given a `ast::MacroCall`, return what `MacroKindFile` it belongs to. | ||
547 | /// FIXME: Not completed | ||
548 | fn to_macro_file_kind(macro_call: &ast::MacroCall) -> MacroFileKind { | ||
549 | let syn = macro_call.syntax(); | ||
550 | let parent = match syn.parent() { | ||
551 | Some(it) => it, | ||
552 | None => { | ||
553 | // FIXME: | ||
554 | // If it is root, which means the parent HirFile | ||
555 | // MacroKindFile must be non-items | ||
556 | // return expr now. | ||
557 | return MacroFileKind::Expr; | ||
558 | } | ||
559 | }; | ||
560 | |||
561 | match parent.kind() { | ||
562 | MACRO_ITEMS | SOURCE_FILE => MacroFileKind::Items, | ||
563 | LET_STMT => { | ||
564 | // FIXME: Handle Pattern | ||
565 | MacroFileKind::Expr | ||
566 | } | ||
567 | EXPR_STMT => MacroFileKind::Statements, | ||
568 | BLOCK => MacroFileKind::Statements, | ||
569 | ARG_LIST => MacroFileKind::Expr, | ||
570 | TRY_EXPR => MacroFileKind::Expr, | ||
571 | _ => { | ||
572 | // Unknown , Just guess it is `Items` | ||
573 | MacroFileKind::Items | ||
574 | } | ||
575 | } | ||
576 | } | ||