diff options
Diffstat (limited to 'crates/ra_hir')
-rw-r--r-- | crates/ra_hir/Cargo.toml | 2 | ||||
-rw-r--r-- | crates/ra_hir/src/code_model.rs | 179 | ||||
-rw-r--r-- | crates/ra_hir/src/db.rs | 10 | ||||
-rw-r--r-- | crates/ra_hir/src/diagnostics.rs | 8 | ||||
-rw-r--r-- | crates/ra_hir/src/has_source.rs | 42 | ||||
-rw-r--r-- | crates/ra_hir/src/lib.rs | 32 | ||||
-rw-r--r-- | crates/ra_hir/src/semantics.rs | 381 | ||||
-rw-r--r-- | crates/ra_hir/src/semantics/source_to_def.rs | 81 | ||||
-rw-r--r-- | crates/ra_hir/src/source_analyzer.rs | 41 |
9 files changed, 522 insertions, 254 deletions
diff --git a/crates/ra_hir/Cargo.toml b/crates/ra_hir/Cargo.toml index ba7b39a19..c260bb193 100644 --- a/crates/ra_hir/Cargo.toml +++ b/crates/ra_hir/Cargo.toml | |||
@@ -3,6 +3,7 @@ edition = "2018" | |||
3 | name = "ra_hir" | 3 | name = "ra_hir" |
4 | version = "0.1.0" | 4 | version = "0.1.0" |
5 | authors = ["rust-analyzer developers"] | 5 | authors = ["rust-analyzer developers"] |
6 | license = "MIT OR Apache-2.0" | ||
6 | 7 | ||
7 | [lib] | 8 | [lib] |
8 | doctest = false | 9 | doctest = false |
@@ -15,6 +16,7 @@ arrayvec = "0.5.1" | |||
15 | 16 | ||
16 | itertools = "0.9.0" | 17 | itertools = "0.9.0" |
17 | 18 | ||
19 | stdx = { path = "../stdx" } | ||
18 | ra_syntax = { path = "../ra_syntax" } | 20 | ra_syntax = { path = "../ra_syntax" } |
19 | ra_db = { path = "../ra_db" } | 21 | ra_db = { path = "../ra_db" } |
20 | ra_prof = { path = "../ra_prof" } | 22 | ra_prof = { path = "../ra_prof" } |
diff --git a/crates/ra_hir/src/code_model.rs b/crates/ra_hir/src/code_model.rs index 8c5e1b746..5d88c5c64 100644 --- a/crates/ra_hir/src/code_model.rs +++ b/crates/ra_hir/src/code_model.rs | |||
@@ -1,5 +1,5 @@ | |||
1 | //! FIXME: write short doc here | 1 | //! FIXME: write short doc here |
2 | use std::sync::Arc; | 2 | use std::{iter, sync::Arc}; |
3 | 3 | ||
4 | use arrayvec::ArrayVec; | 4 | use arrayvec::ArrayVec; |
5 | use either::Either; | 5 | use either::Either; |
@@ -12,6 +12,7 @@ use hir_def::{ | |||
12 | import_map, | 12 | import_map, |
13 | per_ns::PerNs, | 13 | per_ns::PerNs, |
14 | resolver::{HasResolver, Resolver}, | 14 | resolver::{HasResolver, Resolver}, |
15 | src::HasSource as _, | ||
15 | type_ref::{Mutability, TypeRef}, | 16 | type_ref::{Mutability, TypeRef}, |
16 | AdtId, AssocContainerId, ConstId, DefWithBodyId, EnumId, FunctionId, GenericDefId, HasModule, | 17 | AdtId, AssocContainerId, ConstId, DefWithBodyId, EnumId, FunctionId, GenericDefId, HasModule, |
17 | ImplId, LocalEnumVariantId, LocalFieldId, LocalModuleId, Lookup, ModuleId, StaticId, StructId, | 18 | ImplId, LocalEnumVariantId, LocalFieldId, LocalModuleId, Lookup, ModuleId, StaticId, StructId, |
@@ -25,21 +26,22 @@ use hir_expand::{ | |||
25 | use hir_ty::{ | 26 | use hir_ty::{ |
26 | autoderef, | 27 | autoderef, |
27 | display::{HirDisplayError, HirFormatter}, | 28 | display::{HirDisplayError, HirFormatter}, |
28 | expr::ExprValidator, | 29 | method_resolution, ApplicationTy, CallableDefId, Canonical, FnSig, GenericPredicate, |
29 | method_resolution, | 30 | InEnvironment, Substs, TraitEnvironment, Ty, TyDefId, TypeCtor, |
30 | unsafe_validation::UnsafeValidator, | ||
31 | ApplicationTy, Canonical, GenericPredicate, InEnvironment, Substs, TraitEnvironment, Ty, | ||
32 | TyDefId, TypeCtor, | ||
33 | }; | 31 | }; |
34 | use ra_db::{CrateId, CrateName, Edition, FileId}; | 32 | use ra_db::{CrateId, Edition, FileId}; |
35 | use ra_prof::profile; | 33 | use ra_prof::profile; |
36 | use ra_syntax::ast::{self, AttrsOwner, NameOwner}; | 34 | use ra_syntax::{ |
35 | ast::{self, AttrsOwner, NameOwner}, | ||
36 | AstNode, | ||
37 | }; | ||
37 | use rustc_hash::FxHashSet; | 38 | use rustc_hash::FxHashSet; |
39 | use stdx::impl_from; | ||
38 | 40 | ||
39 | use crate::{ | 41 | use crate::{ |
40 | db::{DefDatabase, HirDatabase}, | 42 | db::{DefDatabase, HirDatabase}, |
41 | has_source::HasSource, | 43 | has_source::HasSource, |
42 | CallableDef, HirDisplay, InFile, Name, | 44 | HirDisplay, InFile, Name, |
43 | }; | 45 | }; |
44 | 46 | ||
45 | /// hir::Crate describes a single crate. It's the main interface with which | 47 | /// hir::Crate describes a single crate. It's the main interface with which |
@@ -94,8 +96,8 @@ impl Crate { | |||
94 | db.crate_graph()[self.id].edition | 96 | db.crate_graph()[self.id].edition |
95 | } | 97 | } |
96 | 98 | ||
97 | pub fn display_name(self, db: &dyn HirDatabase) -> Option<CrateName> { | 99 | pub fn display_name(self, db: &dyn HirDatabase) -> Option<String> { |
98 | db.crate_graph()[self.id].display_name.as_ref().cloned() | 100 | db.crate_graph()[self.id].display_name.clone() |
99 | } | 101 | } |
100 | 102 | ||
101 | pub fn query_external_importables( | 103 | pub fn query_external_importables( |
@@ -139,8 +141,8 @@ pub enum ModuleDef { | |||
139 | TypeAlias(TypeAlias), | 141 | TypeAlias(TypeAlias), |
140 | BuiltinType(BuiltinType), | 142 | BuiltinType(BuiltinType), |
141 | } | 143 | } |
142 | impl_froms!( | 144 | impl_from!( |
143 | ModuleDef: Module, | 145 | Module, |
144 | Function, | 146 | Function, |
145 | Adt(Struct, Enum, Union), | 147 | Adt(Struct, Enum, Union), |
146 | EnumVariant, | 148 | EnumVariant, |
@@ -149,6 +151,7 @@ impl_froms!( | |||
149 | Trait, | 151 | Trait, |
150 | TypeAlias, | 152 | TypeAlias, |
151 | BuiltinType | 153 | BuiltinType |
154 | for ModuleDef | ||
152 | ); | 155 | ); |
153 | 156 | ||
154 | impl ModuleDef { | 157 | impl ModuleDef { |
@@ -376,8 +379,8 @@ pub struct Field { | |||
376 | 379 | ||
377 | #[derive(Debug, PartialEq, Eq)] | 380 | #[derive(Debug, PartialEq, Eq)] |
378 | pub enum FieldSource { | 381 | pub enum FieldSource { |
379 | Named(ast::RecordFieldDef), | 382 | Named(ast::RecordField), |
380 | Pos(ast::TupleFieldDef), | 383 | Pos(ast::TupleField), |
381 | } | 384 | } |
382 | 385 | ||
383 | impl Field { | 386 | impl Field { |
@@ -556,7 +559,7 @@ pub enum Adt { | |||
556 | Union(Union), | 559 | Union(Union), |
557 | Enum(Enum), | 560 | Enum(Enum), |
558 | } | 561 | } |
559 | impl_froms!(Adt: Struct, Union, Enum); | 562 | impl_from!(Struct, Union, Enum for Adt); |
560 | 563 | ||
561 | impl Adt { | 564 | impl Adt { |
562 | pub fn has_non_default_type_params(self, db: &dyn HirDatabase) -> bool { | 565 | pub fn has_non_default_type_params(self, db: &dyn HirDatabase) -> bool { |
@@ -599,7 +602,7 @@ pub enum VariantDef { | |||
599 | Union(Union), | 602 | Union(Union), |
600 | EnumVariant(EnumVariant), | 603 | EnumVariant(EnumVariant), |
601 | } | 604 | } |
602 | impl_froms!(VariantDef: Struct, Union, EnumVariant); | 605 | impl_from!(Struct, Union, EnumVariant for VariantDef); |
603 | 606 | ||
604 | impl VariantDef { | 607 | impl VariantDef { |
605 | pub fn fields(self, db: &dyn HirDatabase) -> Vec<Field> { | 608 | pub fn fields(self, db: &dyn HirDatabase) -> Vec<Field> { |
@@ -642,8 +645,7 @@ pub enum DefWithBody { | |||
642 | Static(Static), | 645 | Static(Static), |
643 | Const(Const), | 646 | Const(Const), |
644 | } | 647 | } |
645 | 648 | impl_from!(Function, Const, Static for DefWithBody); | |
646 | impl_froms!(DefWithBody: Function, Const, Static); | ||
647 | 649 | ||
648 | impl DefWithBody { | 650 | impl DefWithBody { |
649 | pub fn module(self, db: &dyn HirDatabase) -> Module { | 651 | pub fn module(self, db: &dyn HirDatabase) -> Module { |
@@ -694,13 +696,7 @@ impl Function { | |||
694 | } | 696 | } |
695 | 697 | ||
696 | pub fn diagnostics(self, db: &dyn HirDatabase, sink: &mut DiagnosticSink) { | 698 | pub fn diagnostics(self, db: &dyn HirDatabase, sink: &mut DiagnosticSink) { |
697 | let _p = profile("Function::diagnostics"); | 699 | hir_ty::diagnostics::validate_body(db, self.id.into(), sink) |
698 | let infer = db.infer(self.id.into()); | ||
699 | infer.add_diagnostics(db, self.id, sink); | ||
700 | let mut validator = ExprValidator::new(self.id, infer.clone(), sink); | ||
701 | validator.validate_body(db); | ||
702 | let mut validator = UnsafeValidator::new(self.id, infer, sink); | ||
703 | validator.validate_body(db); | ||
704 | } | 700 | } |
705 | } | 701 | } |
706 | 702 | ||
@@ -945,14 +941,15 @@ pub enum GenericDef { | |||
945 | // consts can have type parameters from their parents (i.e. associated consts of traits) | 941 | // consts can have type parameters from their parents (i.e. associated consts of traits) |
946 | Const(Const), | 942 | Const(Const), |
947 | } | 943 | } |
948 | impl_froms!( | 944 | impl_from!( |
949 | GenericDef: Function, | 945 | Function, |
950 | Adt(Struct, Enum, Union), | 946 | Adt(Struct, Enum, Union), |
951 | Trait, | 947 | Trait, |
952 | TypeAlias, | 948 | TypeAlias, |
953 | ImplDef, | 949 | ImplDef, |
954 | EnumVariant, | 950 | EnumVariant, |
955 | Const | 951 | Const |
952 | for GenericDef | ||
956 | ); | 953 | ); |
957 | 954 | ||
958 | impl GenericDef { | 955 | impl GenericDef { |
@@ -973,6 +970,16 @@ pub struct Local { | |||
973 | } | 970 | } |
974 | 971 | ||
975 | impl Local { | 972 | impl Local { |
973 | pub fn is_param(self, db: &dyn HirDatabase) -> bool { | ||
974 | let src = self.source(db); | ||
975 | match src.value { | ||
976 | Either::Left(bind_pat) => { | ||
977 | bind_pat.syntax().ancestors().any(|it| ast::Param::can_cast(it.kind())) | ||
978 | } | ||
979 | Either::Right(_self_param) => true, | ||
980 | } | ||
981 | } | ||
982 | |||
976 | // FIXME: why is this an option? It shouldn't be? | 983 | // FIXME: why is this an option? It shouldn't be? |
977 | pub fn name(self, db: &dyn HirDatabase) -> Option<Name> { | 984 | pub fn name(self, db: &dyn HirDatabase) -> Option<Name> { |
978 | let body = db.body(self.parent.into()); | 985 | let body = db.body(self.parent.into()); |
@@ -1071,12 +1078,14 @@ pub struct ImplDef { | |||
1071 | 1078 | ||
1072 | impl ImplDef { | 1079 | impl ImplDef { |
1073 | pub fn all_in_crate(db: &dyn HirDatabase, krate: Crate) -> Vec<ImplDef> { | 1080 | pub fn all_in_crate(db: &dyn HirDatabase, krate: Crate) -> Vec<ImplDef> { |
1074 | let impls = db.impls_in_crate(krate.id); | 1081 | let inherent = db.inherent_impls_in_crate(krate.id); |
1075 | impls.all_impls().map(Self::from).collect() | 1082 | let trait_ = db.trait_impls_in_crate(krate.id); |
1083 | |||
1084 | inherent.all_impls().chain(trait_.all_impls()).map(Self::from).collect() | ||
1076 | } | 1085 | } |
1077 | pub fn for_trait(db: &dyn HirDatabase, krate: Crate, trait_: Trait) -> Vec<ImplDef> { | 1086 | pub fn for_trait(db: &dyn HirDatabase, krate: Crate, trait_: Trait) -> Vec<ImplDef> { |
1078 | let impls = db.impls_in_crate(krate.id); | 1087 | let impls = db.trait_impls_in_crate(krate.id); |
1079 | impls.lookup_impl_defs_for_trait(trait_.id).map(Self::from).collect() | 1088 | impls.for_trait(trait_.id).map(Self::from).collect() |
1080 | } | 1089 | } |
1081 | 1090 | ||
1082 | pub fn target_trait(self, db: &dyn HirDatabase) -> Option<TypeRef> { | 1091 | pub fn target_trait(self, db: &dyn HirDatabase) -> Option<TypeRef> { |
@@ -1178,6 +1187,12 @@ impl Type { | |||
1178 | Type::new(db, krate, def, ty) | 1187 | Type::new(db, krate, def, ty) |
1179 | } | 1188 | } |
1180 | 1189 | ||
1190 | pub fn is_unit(&self) -> bool { | ||
1191 | matches!( | ||
1192 | self.ty.value, | ||
1193 | Ty::Apply(ApplicationTy { ctor: TypeCtor::Tuple { cardinality: 0 }, .. }) | ||
1194 | ) | ||
1195 | } | ||
1181 | pub fn is_bool(&self) -> bool { | 1196 | pub fn is_bool(&self) -> bool { |
1182 | matches!(self.ty.value, Ty::Apply(ApplicationTy { ctor: TypeCtor::Bool, .. })) | 1197 | matches!(self.ty.value, Ty::Apply(ApplicationTy { ctor: TypeCtor::Bool, .. })) |
1183 | } | 1198 | } |
@@ -1205,7 +1220,7 @@ impl Type { | |||
1205 | None => return false, | 1220 | None => return false, |
1206 | }; | 1221 | }; |
1207 | 1222 | ||
1208 | let canonical_ty = Canonical { value: self.ty.value.clone(), num_vars: 0 }; | 1223 | let canonical_ty = Canonical { value: self.ty.value.clone(), kinds: Arc::new([]) }; |
1209 | method_resolution::implements_trait( | 1224 | method_resolution::implements_trait( |
1210 | &canonical_ty, | 1225 | &canonical_ty, |
1211 | db, | 1226 | db, |
@@ -1229,15 +1244,20 @@ impl Type { | |||
1229 | self.ty.environment.clone(), | 1244 | self.ty.environment.clone(), |
1230 | hir_ty::Obligation::Trait(trait_ref), | 1245 | hir_ty::Obligation::Trait(trait_ref), |
1231 | ), | 1246 | ), |
1232 | num_vars: 0, | 1247 | kinds: Arc::new([]), |
1233 | }; | 1248 | }; |
1234 | 1249 | ||
1235 | db.trait_solve(self.krate, goal).is_some() | 1250 | db.trait_solve(self.krate, goal).is_some() |
1236 | } | 1251 | } |
1237 | 1252 | ||
1238 | // FIXME: this method is broken, as it doesn't take closures into account. | 1253 | pub fn as_callable(&self, db: &dyn HirDatabase) -> Option<Callable> { |
1239 | pub fn as_callable(&self) -> Option<CallableDef> { | 1254 | let def = match self.ty.value { |
1240 | Some(self.ty.value.as_callable()?.0) | 1255 | Ty::Apply(ApplicationTy { ctor: TypeCtor::FnDef(def), parameters: _ }) => Some(def), |
1256 | _ => None, | ||
1257 | }; | ||
1258 | |||
1259 | let sig = self.ty.value.callable_sig(db)?; | ||
1260 | Some(Callable { ty: self.clone(), sig, def, is_bound_method: false }) | ||
1241 | } | 1261 | } |
1242 | 1262 | ||
1243 | pub fn is_closure(&self) -> bool { | 1263 | pub fn is_closure(&self) -> bool { |
@@ -1304,7 +1324,7 @@ impl Type { | |||
1304 | pub fn autoderef<'a>(&'a self, db: &'a dyn HirDatabase) -> impl Iterator<Item = Type> + 'a { | 1324 | pub fn autoderef<'a>(&'a self, db: &'a dyn HirDatabase) -> impl Iterator<Item = Type> + 'a { |
1305 | // There should be no inference vars in types passed here | 1325 | // There should be no inference vars in types passed here |
1306 | // FIXME check that? | 1326 | // FIXME check that? |
1307 | let canonical = Canonical { value: self.ty.value.clone(), num_vars: 0 }; | 1327 | let canonical = Canonical { value: self.ty.value.clone(), kinds: Arc::new([]) }; |
1308 | let environment = self.ty.environment.clone(); | 1328 | let environment = self.ty.environment.clone(); |
1309 | let ty = InEnvironment { value: canonical, environment }; | 1329 | let ty = InEnvironment { value: canonical, environment }; |
1310 | autoderef(db, Some(self.krate), ty) | 1330 | autoderef(db, Some(self.krate), ty) |
@@ -1321,10 +1341,10 @@ impl Type { | |||
1321 | mut callback: impl FnMut(AssocItem) -> Option<T>, | 1341 | mut callback: impl FnMut(AssocItem) -> Option<T>, |
1322 | ) -> Option<T> { | 1342 | ) -> Option<T> { |
1323 | for krate in self.ty.value.def_crates(db, krate.id)? { | 1343 | for krate in self.ty.value.def_crates(db, krate.id)? { |
1324 | let impls = db.impls_in_crate(krate); | 1344 | let impls = db.inherent_impls_in_crate(krate); |
1325 | 1345 | ||
1326 | for impl_def in impls.lookup_impl_defs(&self.ty.value) { | 1346 | for impl_def in impls.for_self_ty(&self.ty.value) { |
1327 | for &item in db.impl_data(impl_def).items.iter() { | 1347 | for &item in db.impl_data(*impl_def).items.iter() { |
1328 | if let Some(result) = callback(item.into()) { | 1348 | if let Some(result) = callback(item.into()) { |
1329 | return Some(result); | 1349 | return Some(result); |
1330 | } | 1350 | } |
@@ -1345,7 +1365,7 @@ impl Type { | |||
1345 | // There should be no inference vars in types passed here | 1365 | // There should be no inference vars in types passed here |
1346 | // FIXME check that? | 1366 | // FIXME check that? |
1347 | // FIXME replace Unknown by bound vars here | 1367 | // FIXME replace Unknown by bound vars here |
1348 | let canonical = Canonical { value: self.ty.value.clone(), num_vars: 0 }; | 1368 | let canonical = Canonical { value: self.ty.value.clone(), kinds: Arc::new([]) }; |
1349 | 1369 | ||
1350 | let env = self.ty.environment.clone(); | 1370 | let env = self.ty.environment.clone(); |
1351 | let krate = krate.id; | 1371 | let krate = krate.id; |
@@ -1376,7 +1396,7 @@ impl Type { | |||
1376 | // There should be no inference vars in types passed here | 1396 | // There should be no inference vars in types passed here |
1377 | // FIXME check that? | 1397 | // FIXME check that? |
1378 | // FIXME replace Unknown by bound vars here | 1398 | // FIXME replace Unknown by bound vars here |
1379 | let canonical = Canonical { value: self.ty.value.clone(), num_vars: 0 }; | 1399 | let canonical = Canonical { value: self.ty.value.clone(), kinds: Arc::new([]) }; |
1380 | 1400 | ||
1381 | let env = self.ty.environment.clone(); | 1401 | let env = self.ty.environment.clone(); |
1382 | let krate = krate.id; | 1402 | let krate = krate.id; |
@@ -1522,6 +1542,74 @@ impl HirDisplay for Type { | |||
1522 | } | 1542 | } |
1523 | } | 1543 | } |
1524 | 1544 | ||
1545 | // FIXME: closures | ||
1546 | #[derive(Debug)] | ||
1547 | pub struct Callable { | ||
1548 | ty: Type, | ||
1549 | sig: FnSig, | ||
1550 | def: Option<CallableDefId>, | ||
1551 | pub(crate) is_bound_method: bool, | ||
1552 | } | ||
1553 | |||
1554 | pub enum CallableKind { | ||
1555 | Function(Function), | ||
1556 | TupleStruct(Struct), | ||
1557 | TupleEnumVariant(EnumVariant), | ||
1558 | Closure, | ||
1559 | } | ||
1560 | |||
1561 | impl Callable { | ||
1562 | pub fn kind(&self) -> CallableKind { | ||
1563 | match self.def { | ||
1564 | Some(CallableDefId::FunctionId(it)) => CallableKind::Function(it.into()), | ||
1565 | Some(CallableDefId::StructId(it)) => CallableKind::TupleStruct(it.into()), | ||
1566 | Some(CallableDefId::EnumVariantId(it)) => CallableKind::TupleEnumVariant(it.into()), | ||
1567 | None => CallableKind::Closure, | ||
1568 | } | ||
1569 | } | ||
1570 | pub fn receiver_param(&self, db: &dyn HirDatabase) -> Option<ast::SelfParam> { | ||
1571 | let func = match self.def { | ||
1572 | Some(CallableDefId::FunctionId(it)) if self.is_bound_method => it, | ||
1573 | _ => return None, | ||
1574 | }; | ||
1575 | let src = func.lookup(db.upcast()).source(db.upcast()); | ||
1576 | let param_list = src.value.param_list()?; | ||
1577 | param_list.self_param() | ||
1578 | } | ||
1579 | pub fn n_params(&self) -> usize { | ||
1580 | self.sig.params().len() - if self.is_bound_method { 1 } else { 0 } | ||
1581 | } | ||
1582 | pub fn params( | ||
1583 | &self, | ||
1584 | db: &dyn HirDatabase, | ||
1585 | ) -> Vec<(Option<Either<ast::SelfParam, ast::Pat>>, Type)> { | ||
1586 | let types = self | ||
1587 | .sig | ||
1588 | .params() | ||
1589 | .iter() | ||
1590 | .skip(if self.is_bound_method { 1 } else { 0 }) | ||
1591 | .map(|ty| self.ty.derived(ty.clone())); | ||
1592 | let patterns = match self.def { | ||
1593 | Some(CallableDefId::FunctionId(func)) => { | ||
1594 | let src = func.lookup(db.upcast()).source(db.upcast()); | ||
1595 | src.value.param_list().map(|param_list| { | ||
1596 | param_list | ||
1597 | .self_param() | ||
1598 | .map(|it| Some(Either::Left(it))) | ||
1599 | .filter(|_| !self.is_bound_method) | ||
1600 | .into_iter() | ||
1601 | .chain(param_list.params().map(|it| it.pat().map(Either::Right))) | ||
1602 | }) | ||
1603 | } | ||
1604 | _ => None, | ||
1605 | }; | ||
1606 | patterns.into_iter().flatten().chain(iter::repeat(None)).zip(types).collect() | ||
1607 | } | ||
1608 | pub fn return_type(&self) -> Type { | ||
1609 | self.ty.derived(self.sig.ret().clone()) | ||
1610 | } | ||
1611 | } | ||
1612 | |||
1525 | /// For IDE only | 1613 | /// For IDE only |
1526 | #[derive(Debug)] | 1614 | #[derive(Debug)] |
1527 | pub enum ScopeDef { | 1615 | pub enum ScopeDef { |
@@ -1581,8 +1669,8 @@ pub enum AttrDef { | |||
1581 | MacroDef(MacroDef), | 1669 | MacroDef(MacroDef), |
1582 | } | 1670 | } |
1583 | 1671 | ||
1584 | impl_froms!( | 1672 | impl_from!( |
1585 | AttrDef: Module, | 1673 | Module, |
1586 | Field, | 1674 | Field, |
1587 | Adt(Struct, Enum, Union), | 1675 | Adt(Struct, Enum, Union), |
1588 | EnumVariant, | 1676 | EnumVariant, |
@@ -1592,6 +1680,7 @@ impl_froms!( | |||
1592 | Trait, | 1680 | Trait, |
1593 | TypeAlias, | 1681 | TypeAlias, |
1594 | MacroDef | 1682 | MacroDef |
1683 | for AttrDef | ||
1595 | ); | 1684 | ); |
1596 | 1685 | ||
1597 | pub trait HasAttrs { | 1686 | pub trait HasAttrs { |
diff --git a/crates/ra_hir/src/db.rs b/crates/ra_hir/src/db.rs index bb67952de..a2b9f3e35 100644 --- a/crates/ra_hir/src/db.rs +++ b/crates/ra_hir/src/db.rs | |||
@@ -11,15 +11,15 @@ pub use hir_def::db::{ | |||
11 | }; | 11 | }; |
12 | pub use hir_expand::db::{ | 12 | pub use hir_expand::db::{ |
13 | AstDatabase, AstDatabaseStorage, AstIdMapQuery, InternEagerExpansionQuery, InternMacroQuery, | 13 | AstDatabase, AstDatabaseStorage, AstIdMapQuery, InternEagerExpansionQuery, InternMacroQuery, |
14 | MacroArgQuery, MacroDefQuery, MacroExpandQuery, ParseMacroQuery, | 14 | MacroArgTextQuery, MacroDefQuery, MacroExpandQuery, ParseMacroQuery, |
15 | }; | 15 | }; |
16 | pub use hir_ty::db::{ | 16 | pub use hir_ty::db::{ |
17 | AssociatedTyDataQuery, AssociatedTyValueQuery, CallableItemSignatureQuery, FieldTypesQuery, | 17 | AssociatedTyDataQuery, AssociatedTyValueQuery, CallableItemSignatureQuery, FieldTypesQuery, |
18 | GenericDefaultsQuery, GenericPredicatesForParamQuery, GenericPredicatesQuery, HirDatabase, | 18 | GenericDefaultsQuery, GenericPredicatesForParamQuery, GenericPredicatesQuery, HirDatabase, |
19 | HirDatabaseStorage, ImplDatumQuery, ImplSelfTyQuery, ImplTraitQuery, ImplsFromDepsQuery, | 19 | HirDatabaseStorage, ImplDatumQuery, ImplSelfTyQuery, ImplTraitQuery, InferQueryQuery, |
20 | ImplsInCrateQuery, InferQueryQuery, InternAssocTyValueQuery, InternChalkImplQuery, | 20 | InherentImplsInCrateQuery, InternTypeParamIdQuery, ReturnTypeImplTraitsQuery, StructDatumQuery, |
21 | InternTypeCtorQuery, InternTypeParamIdQuery, ReturnTypeImplTraitsQuery, StructDatumQuery, | 21 | TraitDatumQuery, TraitImplsInCrateQuery, TraitImplsInDepsQuery, TraitSolveQuery, TyQuery, |
22 | TraitDatumQuery, TraitSolveQuery, TyQuery, ValueTyQuery, | 22 | ValueTyQuery, |
23 | }; | 23 | }; |
24 | 24 | ||
25 | #[test] | 25 | #[test] |
diff --git a/crates/ra_hir/src/diagnostics.rs b/crates/ra_hir/src/diagnostics.rs index c82883d0c..266b513dc 100644 --- a/crates/ra_hir/src/diagnostics.rs +++ b/crates/ra_hir/src/diagnostics.rs | |||
@@ -1,4 +1,8 @@ | |||
1 | //! FIXME: write short doc here | 1 | //! FIXME: write short doc here |
2 | pub use hir_def::diagnostics::UnresolvedModule; | 2 | pub use hir_def::diagnostics::UnresolvedModule; |
3 | pub use hir_expand::diagnostics::{AstDiagnostic, Diagnostic, DiagnosticSink}; | 3 | pub use hir_expand::diagnostics::{ |
4 | pub use hir_ty::diagnostics::{MissingFields, MissingMatchArms, MissingOkInTailExpr, NoSuchField}; | 4 | AstDiagnostic, Diagnostic, DiagnosticSink, DiagnosticSinkBuilder, |
5 | }; | ||
6 | pub use hir_ty::diagnostics::{ | ||
7 | MismatchedArgCount, MissingFields, MissingMatchArms, MissingOkInTailExpr, NoSuchField, | ||
8 | }; | ||
diff --git a/crates/ra_hir/src/has_source.rs b/crates/ra_hir/src/has_source.rs index 76c32fc17..1c691d961 100644 --- a/crates/ra_hir/src/has_source.rs +++ b/crates/ra_hir/src/has_source.rs | |||
@@ -57,56 +57,56 @@ impl HasSource for Field { | |||
57 | } | 57 | } |
58 | } | 58 | } |
59 | impl HasSource for Struct { | 59 | impl HasSource for Struct { |
60 | type Ast = ast::StructDef; | 60 | type Ast = ast::Struct; |
61 | fn source(self, db: &dyn HirDatabase) -> InFile<ast::StructDef> { | 61 | fn source(self, db: &dyn HirDatabase) -> InFile<ast::Struct> { |
62 | self.id.lookup(db.upcast()).source(db.upcast()) | 62 | self.id.lookup(db.upcast()).source(db.upcast()) |
63 | } | 63 | } |
64 | } | 64 | } |
65 | impl HasSource for Union { | 65 | impl HasSource for Union { |
66 | type Ast = ast::UnionDef; | 66 | type Ast = ast::Union; |
67 | fn source(self, db: &dyn HirDatabase) -> InFile<ast::UnionDef> { | 67 | fn source(self, db: &dyn HirDatabase) -> InFile<ast::Union> { |
68 | self.id.lookup(db.upcast()).source(db.upcast()) | 68 | self.id.lookup(db.upcast()).source(db.upcast()) |
69 | } | 69 | } |
70 | } | 70 | } |
71 | impl HasSource for Enum { | 71 | impl HasSource for Enum { |
72 | type Ast = ast::EnumDef; | 72 | type Ast = ast::Enum; |
73 | fn source(self, db: &dyn HirDatabase) -> InFile<ast::EnumDef> { | 73 | fn source(self, db: &dyn HirDatabase) -> InFile<ast::Enum> { |
74 | self.id.lookup(db.upcast()).source(db.upcast()) | 74 | self.id.lookup(db.upcast()).source(db.upcast()) |
75 | } | 75 | } |
76 | } | 76 | } |
77 | impl HasSource for EnumVariant { | 77 | impl HasSource for EnumVariant { |
78 | type Ast = ast::EnumVariant; | 78 | type Ast = ast::Variant; |
79 | fn source(self, db: &dyn HirDatabase) -> InFile<ast::EnumVariant> { | 79 | fn source(self, db: &dyn HirDatabase) -> InFile<ast::Variant> { |
80 | self.parent.id.child_source(db.upcast()).map(|map| map[self.id].clone()) | 80 | self.parent.id.child_source(db.upcast()).map(|map| map[self.id].clone()) |
81 | } | 81 | } |
82 | } | 82 | } |
83 | impl HasSource for Function { | 83 | impl HasSource for Function { |
84 | type Ast = ast::FnDef; | 84 | type Ast = ast::Fn; |
85 | fn source(self, db: &dyn HirDatabase) -> InFile<ast::FnDef> { | 85 | fn source(self, db: &dyn HirDatabase) -> InFile<ast::Fn> { |
86 | self.id.lookup(db.upcast()).source(db.upcast()) | 86 | self.id.lookup(db.upcast()).source(db.upcast()) |
87 | } | 87 | } |
88 | } | 88 | } |
89 | impl HasSource for Const { | 89 | impl HasSource for Const { |
90 | type Ast = ast::ConstDef; | 90 | type Ast = ast::Const; |
91 | fn source(self, db: &dyn HirDatabase) -> InFile<ast::ConstDef> { | 91 | fn source(self, db: &dyn HirDatabase) -> InFile<ast::Const> { |
92 | self.id.lookup(db.upcast()).source(db.upcast()) | 92 | self.id.lookup(db.upcast()).source(db.upcast()) |
93 | } | 93 | } |
94 | } | 94 | } |
95 | impl HasSource for Static { | 95 | impl HasSource for Static { |
96 | type Ast = ast::StaticDef; | 96 | type Ast = ast::Static; |
97 | fn source(self, db: &dyn HirDatabase) -> InFile<ast::StaticDef> { | 97 | fn source(self, db: &dyn HirDatabase) -> InFile<ast::Static> { |
98 | self.id.lookup(db.upcast()).source(db.upcast()) | 98 | self.id.lookup(db.upcast()).source(db.upcast()) |
99 | } | 99 | } |
100 | } | 100 | } |
101 | impl HasSource for Trait { | 101 | impl HasSource for Trait { |
102 | type Ast = ast::TraitDef; | 102 | type Ast = ast::Trait; |
103 | fn source(self, db: &dyn HirDatabase) -> InFile<ast::TraitDef> { | 103 | fn source(self, db: &dyn HirDatabase) -> InFile<ast::Trait> { |
104 | self.id.lookup(db.upcast()).source(db.upcast()) | 104 | self.id.lookup(db.upcast()).source(db.upcast()) |
105 | } | 105 | } |
106 | } | 106 | } |
107 | impl HasSource for TypeAlias { | 107 | impl HasSource for TypeAlias { |
108 | type Ast = ast::TypeAliasDef; | 108 | type Ast = ast::TypeAlias; |
109 | fn source(self, db: &dyn HirDatabase) -> InFile<ast::TypeAliasDef> { | 109 | fn source(self, db: &dyn HirDatabase) -> InFile<ast::TypeAlias> { |
110 | self.id.lookup(db.upcast()).source(db.upcast()) | 110 | self.id.lookup(db.upcast()).source(db.upcast()) |
111 | } | 111 | } |
112 | } | 112 | } |
@@ -120,14 +120,14 @@ impl HasSource for MacroDef { | |||
120 | } | 120 | } |
121 | } | 121 | } |
122 | impl HasSource for ImplDef { | 122 | impl HasSource for ImplDef { |
123 | type Ast = ast::ImplDef; | 123 | type Ast = ast::Impl; |
124 | fn source(self, db: &dyn HirDatabase) -> InFile<ast::ImplDef> { | 124 | fn source(self, db: &dyn HirDatabase) -> InFile<ast::Impl> { |
125 | self.id.lookup(db.upcast()).source(db.upcast()) | 125 | self.id.lookup(db.upcast()).source(db.upcast()) |
126 | } | 126 | } |
127 | } | 127 | } |
128 | 128 | ||
129 | impl HasSource for TypeParam { | 129 | impl HasSource for TypeParam { |
130 | type Ast = Either<ast::TraitDef, ast::TypeParam>; | 130 | type Ast = Either<ast::Trait, ast::TypeParam>; |
131 | fn source(self, db: &dyn HirDatabase) -> InFile<Self::Ast> { | 131 | fn source(self, db: &dyn HirDatabase) -> InFile<Self::Ast> { |
132 | let child_source = self.id.parent.child_source(db.upcast()); | 132 | let child_source = self.id.parent.child_source(db.upcast()); |
133 | child_source.map(|it| it[self.id.local_id].clone()) | 133 | child_source.map(|it| it[self.id.local_id].clone()) |
diff --git a/crates/ra_hir/src/lib.rs b/crates/ra_hir/src/lib.rs index fe34b30bc..e2d13dbfd 100644 --- a/crates/ra_hir/src/lib.rs +++ b/crates/ra_hir/src/lib.rs | |||
@@ -19,25 +19,6 @@ | |||
19 | 19 | ||
20 | #![recursion_limit = "512"] | 20 | #![recursion_limit = "512"] |
21 | 21 | ||
22 | macro_rules! impl_froms { | ||
23 | ($e:ident: $($v:ident $(($($sv:ident),*))?),*$(,)?) => { | ||
24 | $( | ||
25 | impl From<$v> for $e { | ||
26 | fn from(it: $v) -> $e { | ||
27 | $e::$v(it) | ||
28 | } | ||
29 | } | ||
30 | $($( | ||
31 | impl From<$sv> for $e { | ||
32 | fn from(it: $sv) -> $e { | ||
33 | $e::$v($v::$sv(it)) | ||
34 | } | ||
35 | } | ||
36 | )*)? | ||
37 | )* | ||
38 | } | ||
39 | } | ||
40 | |||
41 | mod semantics; | 22 | mod semantics; |
42 | pub mod db; | 23 | pub mod db; |
43 | mod source_analyzer; | 24 | mod source_analyzer; |
@@ -51,10 +32,10 @@ mod has_source; | |||
51 | 32 | ||
52 | pub use crate::{ | 33 | pub use crate::{ |
53 | code_model::{ | 34 | code_model::{ |
54 | Adt, AsAssocItem, AssocItem, AssocItemContainer, AttrDef, Const, Crate, CrateDependency, | 35 | Adt, AsAssocItem, AssocItem, AssocItemContainer, AttrDef, Callable, CallableKind, Const, |
55 | DefWithBody, Docs, Enum, EnumVariant, Field, FieldSource, Function, GenericDef, HasAttrs, | 36 | Crate, CrateDependency, DefWithBody, Docs, Enum, EnumVariant, Field, FieldSource, Function, |
56 | HasVisibility, ImplDef, Local, MacroDef, Module, ModuleDef, ScopeDef, Static, Struct, | 37 | GenericDef, HasAttrs, HasVisibility, ImplDef, Local, MacroDef, Module, ModuleDef, ScopeDef, |
57 | Trait, Type, TypeAlias, TypeParam, Union, VariantDef, Visibility, | 38 | Static, Struct, Trait, Type, TypeAlias, TypeParam, Union, VariantDef, Visibility, |
58 | }, | 39 | }, |
59 | has_source::HasSource, | 40 | has_source::HasSource, |
60 | semantics::{original_range, PathResolution, Semantics, SemanticsScope}, | 41 | semantics::{original_range, PathResolution, Semantics, SemanticsScope}, |
@@ -74,6 +55,7 @@ pub use hir_def::{ | |||
74 | pub use hir_expand::{ | 55 | pub use hir_expand::{ |
75 | hygiene::Hygiene, | 56 | hygiene::Hygiene, |
76 | name::{AsName, Name}, | 57 | name::{AsName, Name}, |
77 | HirFileId, InFile, MacroCallId, MacroCallLoc, MacroDefId, MacroFile, Origin, | 58 | HirFileId, InFile, MacroCallId, MacroCallLoc, MacroDefId, /* FIXME */ |
59 | MacroFile, Origin, | ||
78 | }; | 60 | }; |
79 | pub use hir_ty::{display::HirDisplay, CallableDef}; | 61 | pub use hir_ty::display::HirDisplay; |
diff --git a/crates/ra_hir/src/semantics.rs b/crates/ra_hir/src/semantics.rs index 6a49c424a..6f3b3dc9a 100644 --- a/crates/ra_hir/src/semantics.rs +++ b/crates/ra_hir/src/semantics.rs | |||
@@ -6,7 +6,7 @@ use std::{cell::RefCell, fmt, iter::successors}; | |||
6 | 6 | ||
7 | use hir_def::{ | 7 | use hir_def::{ |
8 | resolver::{self, HasResolver, Resolver}, | 8 | resolver::{self, HasResolver, Resolver}, |
9 | AsMacroCall, TraitId, VariantId, | 9 | AsMacroCall, FunctionId, TraitId, VariantId, |
10 | }; | 10 | }; |
11 | use hir_expand::{diagnostics::AstDiagnostic, hygiene::Hygiene, ExpansionInfo}; | 11 | use hir_expand::{diagnostics::AstDiagnostic, hygiene::Hygiene, ExpansionInfo}; |
12 | use hir_ty::associated_type_shorthand_candidates; | 12 | use hir_ty::associated_type_shorthand_candidates; |
@@ -24,8 +24,8 @@ use crate::{ | |||
24 | diagnostics::Diagnostic, | 24 | diagnostics::Diagnostic, |
25 | semantics::source_to_def::{ChildContainer, SourceToDefCache, SourceToDefCtx}, | 25 | semantics::source_to_def::{ChildContainer, SourceToDefCache, SourceToDefCtx}, |
26 | source_analyzer::{resolve_hir_path, resolve_hir_path_qualifier, SourceAnalyzer}, | 26 | source_analyzer::{resolve_hir_path, resolve_hir_path_qualifier, SourceAnalyzer}, |
27 | AssocItem, Field, Function, HirFileId, ImplDef, InFile, Local, MacroDef, Module, ModuleDef, | 27 | AssocItem, Callable, Field, Function, HirFileId, ImplDef, InFile, Local, MacroDef, Module, |
28 | Name, Origin, Path, ScopeDef, Trait, Type, TypeAlias, TypeParam, | 28 | ModuleDef, Name, Origin, Path, ScopeDef, Trait, Type, TypeAlias, TypeParam, VariantDef, |
29 | }; | 29 | }; |
30 | use resolver::TypeNs; | 30 | use resolver::TypeNs; |
31 | 31 | ||
@@ -83,7 +83,13 @@ impl PathResolution { | |||
83 | /// Primary API to get semantic information, like types, from syntax trees. | 83 | /// Primary API to get semantic information, like types, from syntax trees. |
84 | pub struct Semantics<'db, DB> { | 84 | pub struct Semantics<'db, DB> { |
85 | pub db: &'db DB, | 85 | pub db: &'db DB, |
86 | imp: SemanticsImpl<'db>, | ||
87 | } | ||
88 | |||
89 | pub struct SemanticsImpl<'db> { | ||
90 | pub db: &'db dyn HirDatabase, | ||
86 | s2d_cache: RefCell<SourceToDefCache>, | 91 | s2d_cache: RefCell<SourceToDefCache>, |
92 | expansion_info_cache: RefCell<FxHashMap<HirFileId, Option<ExpansionInfo>>>, | ||
87 | cache: RefCell<FxHashMap<SyntaxNode, HirFileId>>, | 93 | cache: RefCell<FxHashMap<SyntaxNode, HirFileId>>, |
88 | } | 94 | } |
89 | 95 | ||
@@ -95,23 +101,199 @@ impl<DB> fmt::Debug for Semantics<'_, DB> { | |||
95 | 101 | ||
96 | impl<'db, DB: HirDatabase> Semantics<'db, DB> { | 102 | impl<'db, DB: HirDatabase> Semantics<'db, DB> { |
97 | pub fn new(db: &DB) -> Semantics<DB> { | 103 | pub fn new(db: &DB) -> Semantics<DB> { |
98 | Semantics { db, s2d_cache: Default::default(), cache: Default::default() } | 104 | let impl_ = SemanticsImpl::new(db); |
105 | Semantics { db, imp: impl_ } | ||
99 | } | 106 | } |
100 | 107 | ||
101 | pub fn parse(&self, file_id: FileId) -> ast::SourceFile { | 108 | pub fn parse(&self, file_id: FileId) -> ast::SourceFile { |
102 | let tree = self.db.parse(file_id).tree(); | 109 | self.imp.parse(file_id) |
103 | self.cache(tree.syntax().clone(), file_id.into()); | ||
104 | tree | ||
105 | } | 110 | } |
106 | 111 | ||
107 | pub fn ast<T: AstDiagnostic + Diagnostic>(&self, d: &T) -> <T as AstDiagnostic>::AST { | 112 | pub fn ast<T: AstDiagnostic + Diagnostic>(&self, d: &T) -> <T as AstDiagnostic>::AST { |
108 | let file_id = d.source().file_id; | 113 | let file_id = d.source().file_id; |
109 | let root = self.db.parse_or_expand(file_id).unwrap(); | 114 | let root = self.db.parse_or_expand(file_id).unwrap(); |
110 | self.cache(root, file_id); | 115 | self.imp.cache(root, file_id); |
111 | d.ast(self.db) | 116 | d.ast(self.db.upcast()) |
112 | } | 117 | } |
113 | 118 | ||
114 | pub fn expand(&self, macro_call: &ast::MacroCall) -> Option<SyntaxNode> { | 119 | pub fn expand(&self, macro_call: &ast::MacroCall) -> Option<SyntaxNode> { |
120 | self.imp.expand(macro_call) | ||
121 | } | ||
122 | |||
123 | pub fn expand_hypothetical( | ||
124 | &self, | ||
125 | actual_macro_call: &ast::MacroCall, | ||
126 | hypothetical_args: &ast::TokenTree, | ||
127 | token_to_map: SyntaxToken, | ||
128 | ) -> Option<(SyntaxNode, SyntaxToken)> { | ||
129 | self.imp.expand_hypothetical(actual_macro_call, hypothetical_args, token_to_map) | ||
130 | } | ||
131 | |||
132 | pub fn descend_into_macros(&self, token: SyntaxToken) -> SyntaxToken { | ||
133 | self.imp.descend_into_macros(token) | ||
134 | } | ||
135 | |||
136 | pub fn descend_node_at_offset<N: ast::AstNode>( | ||
137 | &self, | ||
138 | node: &SyntaxNode, | ||
139 | offset: TextSize, | ||
140 | ) -> Option<N> { | ||
141 | self.imp.descend_node_at_offset(node, offset).find_map(N::cast) | ||
142 | } | ||
143 | |||
144 | pub fn original_range(&self, node: &SyntaxNode) -> FileRange { | ||
145 | self.imp.original_range(node) | ||
146 | } | ||
147 | |||
148 | pub fn diagnostics_range(&self, diagnostics: &dyn Diagnostic) -> FileRange { | ||
149 | self.imp.diagnostics_range(diagnostics) | ||
150 | } | ||
151 | |||
152 | pub fn ancestors_with_macros(&self, node: SyntaxNode) -> impl Iterator<Item = SyntaxNode> + '_ { | ||
153 | self.imp.ancestors_with_macros(node) | ||
154 | } | ||
155 | |||
156 | pub fn ancestors_at_offset_with_macros( | ||
157 | &self, | ||
158 | node: &SyntaxNode, | ||
159 | offset: TextSize, | ||
160 | ) -> impl Iterator<Item = SyntaxNode> + '_ { | ||
161 | self.imp.ancestors_at_offset_with_macros(node, offset) | ||
162 | } | ||
163 | |||
164 | /// Find a AstNode by offset inside SyntaxNode, if it is inside *Macrofile*, | ||
165 | /// search up until it is of the target AstNode type | ||
166 | pub fn find_node_at_offset_with_macros<N: AstNode>( | ||
167 | &self, | ||
168 | node: &SyntaxNode, | ||
169 | offset: TextSize, | ||
170 | ) -> Option<N> { | ||
171 | self.imp.ancestors_at_offset_with_macros(node, offset).find_map(N::cast) | ||
172 | } | ||
173 | |||
174 | /// Find a AstNode by offset inside SyntaxNode, if it is inside *MacroCall*, | ||
175 | /// descend it and find again | ||
176 | pub fn find_node_at_offset_with_descend<N: AstNode>( | ||
177 | &self, | ||
178 | node: &SyntaxNode, | ||
179 | offset: TextSize, | ||
180 | ) -> Option<N> { | ||
181 | if let Some(it) = find_node_at_offset(&node, offset) { | ||
182 | return Some(it); | ||
183 | } | ||
184 | |||
185 | self.imp.descend_node_at_offset(node, offset).find_map(N::cast) | ||
186 | } | ||
187 | |||
188 | pub fn type_of_expr(&self, expr: &ast::Expr) -> Option<Type> { | ||
189 | self.imp.type_of_expr(expr) | ||
190 | } | ||
191 | |||
192 | pub fn type_of_pat(&self, pat: &ast::Pat) -> Option<Type> { | ||
193 | self.imp.type_of_pat(pat) | ||
194 | } | ||
195 | |||
196 | pub fn type_of_self(&self, param: &ast::SelfParam) -> Option<Type> { | ||
197 | self.imp.type_of_self(param) | ||
198 | } | ||
199 | |||
200 | pub fn resolve_method_call(&self, call: &ast::MethodCallExpr) -> Option<Function> { | ||
201 | self.imp.resolve_method_call(call).map(Function::from) | ||
202 | } | ||
203 | |||
204 | pub fn resolve_method_call_as_callable(&self, call: &ast::MethodCallExpr) -> Option<Callable> { | ||
205 | self.imp.resolve_method_call_as_callable(call) | ||
206 | } | ||
207 | |||
208 | pub fn resolve_field(&self, field: &ast::FieldExpr) -> Option<Field> { | ||
209 | self.imp.resolve_field(field) | ||
210 | } | ||
211 | |||
212 | pub fn resolve_record_field( | ||
213 | &self, | ||
214 | field: &ast::RecordExprField, | ||
215 | ) -> Option<(Field, Option<Local>)> { | ||
216 | self.imp.resolve_record_field(field) | ||
217 | } | ||
218 | |||
219 | pub fn resolve_record_field_pat(&self, field: &ast::RecordFieldPat) -> Option<Field> { | ||
220 | self.imp.resolve_record_field_pat(field) | ||
221 | } | ||
222 | |||
223 | pub fn resolve_macro_call(&self, macro_call: &ast::MacroCall) -> Option<MacroDef> { | ||
224 | self.imp.resolve_macro_call(macro_call) | ||
225 | } | ||
226 | |||
227 | pub fn resolve_path(&self, path: &ast::Path) -> Option<PathResolution> { | ||
228 | self.imp.resolve_path(path) | ||
229 | } | ||
230 | |||
231 | pub fn resolve_variant(&self, record_lit: ast::RecordExpr) -> Option<VariantDef> { | ||
232 | self.imp.resolve_variant(record_lit).map(VariantDef::from) | ||
233 | } | ||
234 | |||
235 | pub fn lower_path(&self, path: &ast::Path) -> Option<Path> { | ||
236 | self.imp.lower_path(path) | ||
237 | } | ||
238 | |||
239 | pub fn resolve_bind_pat_to_const(&self, pat: &ast::BindPat) -> Option<ModuleDef> { | ||
240 | self.imp.resolve_bind_pat_to_const(pat) | ||
241 | } | ||
242 | |||
243 | // FIXME: use this instead? | ||
244 | // pub fn resolve_name_ref(&self, name_ref: &ast::NameRef) -> Option<???>; | ||
245 | |||
246 | pub fn record_literal_missing_fields(&self, literal: &ast::RecordExpr) -> Vec<(Field, Type)> { | ||
247 | self.imp.record_literal_missing_fields(literal) | ||
248 | } | ||
249 | |||
250 | pub fn record_pattern_missing_fields(&self, pattern: &ast::RecordPat) -> Vec<(Field, Type)> { | ||
251 | self.imp.record_pattern_missing_fields(pattern) | ||
252 | } | ||
253 | |||
254 | pub fn to_def<T: ToDef>(&self, src: &T) -> Option<T::Def> { | ||
255 | let src = self.imp.find_file(src.syntax().clone()).with_value(src).cloned(); | ||
256 | T::to_def(&self.imp, src) | ||
257 | } | ||
258 | |||
259 | pub fn to_module_def(&self, file: FileId) -> Option<Module> { | ||
260 | self.imp.to_module_def(file) | ||
261 | } | ||
262 | |||
263 | pub fn scope(&self, node: &SyntaxNode) -> SemanticsScope<'db> { | ||
264 | self.imp.scope(node) | ||
265 | } | ||
266 | |||
267 | pub fn scope_at_offset(&self, node: &SyntaxNode, offset: TextSize) -> SemanticsScope<'db> { | ||
268 | self.imp.scope_at_offset(node, offset) | ||
269 | } | ||
270 | |||
271 | pub fn scope_for_def(&self, def: Trait) -> SemanticsScope<'db> { | ||
272 | self.imp.scope_for_def(def) | ||
273 | } | ||
274 | |||
275 | pub fn assert_contains_node(&self, node: &SyntaxNode) { | ||
276 | self.imp.assert_contains_node(node) | ||
277 | } | ||
278 | } | ||
279 | |||
280 | impl<'db> SemanticsImpl<'db> { | ||
281 | fn new(db: &'db dyn HirDatabase) -> Self { | ||
282 | SemanticsImpl { | ||
283 | db, | ||
284 | s2d_cache: Default::default(), | ||
285 | cache: Default::default(), | ||
286 | expansion_info_cache: Default::default(), | ||
287 | } | ||
288 | } | ||
289 | |||
290 | fn parse(&self, file_id: FileId) -> ast::SourceFile { | ||
291 | let tree = self.db.parse(file_id).tree(); | ||
292 | self.cache(tree.syntax().clone(), file_id.into()); | ||
293 | tree | ||
294 | } | ||
295 | |||
296 | fn expand(&self, macro_call: &ast::MacroCall) -> Option<SyntaxNode> { | ||
115 | let macro_call = self.find_file(macro_call.syntax().clone()).with_value(macro_call); | 297 | let macro_call = self.find_file(macro_call.syntax().clone()).with_value(macro_call); |
116 | let sa = self.analyze2(macro_call.map(|it| it.syntax()), None); | 298 | let sa = self.analyze2(macro_call.map(|it| it.syntax()), None); |
117 | let file_id = sa.expand(self.db, macro_call)?; | 299 | let file_id = sa.expand(self.db, macro_call)?; |
@@ -120,7 +302,7 @@ impl<'db, DB: HirDatabase> Semantics<'db, DB> { | |||
120 | Some(node) | 302 | Some(node) |
121 | } | 303 | } |
122 | 304 | ||
123 | pub fn expand_hypothetical( | 305 | fn expand_hypothetical( |
124 | &self, | 306 | &self, |
125 | actual_macro_call: &ast::MacroCall, | 307 | actual_macro_call: &ast::MacroCall, |
126 | hypothetical_args: &ast::TokenTree, | 308 | hypothetical_args: &ast::TokenTree, |
@@ -130,24 +312,38 @@ impl<'db, DB: HirDatabase> Semantics<'db, DB> { | |||
130 | self.find_file(actual_macro_call.syntax().clone()).with_value(actual_macro_call); | 312 | self.find_file(actual_macro_call.syntax().clone()).with_value(actual_macro_call); |
131 | let sa = self.analyze2(macro_call.map(|it| it.syntax()), None); | 313 | let sa = self.analyze2(macro_call.map(|it| it.syntax()), None); |
132 | let krate = sa.resolver.krate()?; | 314 | let krate = sa.resolver.krate()?; |
133 | let macro_call_id = macro_call | 315 | let macro_call_id = macro_call.as_call_id(self.db.upcast(), krate, |path| { |
134 | .as_call_id(self.db, krate, |path| sa.resolver.resolve_path_as_macro(self.db, &path))?; | 316 | sa.resolver.resolve_path_as_macro(self.db.upcast(), &path) |
135 | hir_expand::db::expand_hypothetical(self.db, macro_call_id, hypothetical_args, token_to_map) | 317 | })?; |
136 | } | 318 | hir_expand::db::expand_hypothetical( |
137 | 319 | self.db.upcast(), | |
138 | pub fn descend_into_macros(&self, token: SyntaxToken) -> SyntaxToken { | 320 | macro_call_id, |
321 | hypothetical_args, | ||
322 | token_to_map, | ||
323 | ) | ||
324 | } | ||
325 | |||
326 | fn descend_into_macros(&self, token: SyntaxToken) -> SyntaxToken { | ||
327 | let _p = profile("descend_into_macros"); | ||
139 | let parent = token.parent(); | 328 | let parent = token.parent(); |
140 | let parent = self.find_file(parent); | 329 | let parent = self.find_file(parent); |
141 | let sa = self.analyze2(parent.as_ref(), None); | 330 | let sa = self.analyze2(parent.as_ref(), None); |
142 | 331 | ||
143 | let token = successors(Some(parent.with_value(token)), |token| { | 332 | let token = successors(Some(parent.with_value(token)), |token| { |
333 | self.db.check_canceled(); | ||
144 | let macro_call = token.value.ancestors().find_map(ast::MacroCall::cast)?; | 334 | let macro_call = token.value.ancestors().find_map(ast::MacroCall::cast)?; |
145 | let tt = macro_call.token_tree()?; | 335 | let tt = macro_call.token_tree()?; |
146 | if !tt.syntax().text_range().contains_range(token.value.text_range()) { | 336 | if !tt.syntax().text_range().contains_range(token.value.text_range()) { |
147 | return None; | 337 | return None; |
148 | } | 338 | } |
149 | let file_id = sa.expand(self.db, token.with_value(¯o_call))?; | 339 | let file_id = sa.expand(self.db, token.with_value(¯o_call))?; |
150 | let token = file_id.expansion_info(self.db)?.map_token_down(token.as_ref())?; | 340 | let token = self |
341 | .expansion_info_cache | ||
342 | .borrow_mut() | ||
343 | .entry(file_id) | ||
344 | .or_insert_with(|| file_id.expansion_info(self.db.upcast())) | ||
345 | .as_ref()? | ||
346 | .map_token_down(token.as_ref())?; | ||
151 | 347 | ||
152 | self.cache(find_root(&token.value.parent()), token.file_id); | 348 | self.cache(find_root(&token.value.parent()), token.file_id); |
153 | 349 | ||
@@ -159,35 +355,36 @@ impl<'db, DB: HirDatabase> Semantics<'db, DB> { | |||
159 | token.value | 355 | token.value |
160 | } | 356 | } |
161 | 357 | ||
162 | pub fn descend_node_at_offset<N: ast::AstNode>( | 358 | fn descend_node_at_offset( |
163 | &self, | 359 | &self, |
164 | node: &SyntaxNode, | 360 | node: &SyntaxNode, |
165 | offset: TextSize, | 361 | offset: TextSize, |
166 | ) -> Option<N> { | 362 | ) -> impl Iterator<Item = SyntaxNode> + '_ { |
167 | // Handle macro token cases | 363 | // Handle macro token cases |
168 | node.token_at_offset(offset) | 364 | node.token_at_offset(offset) |
169 | .map(|token| self.descend_into_macros(token)) | 365 | .map(|token| self.descend_into_macros(token)) |
170 | .find_map(|it| self.ancestors_with_macros(it.parent()).find_map(N::cast)) | 366 | .map(|it| self.ancestors_with_macros(it.parent())) |
367 | .flatten() | ||
171 | } | 368 | } |
172 | 369 | ||
173 | pub fn original_range(&self, node: &SyntaxNode) -> FileRange { | 370 | fn original_range(&self, node: &SyntaxNode) -> FileRange { |
174 | let node = self.find_file(node.clone()); | 371 | let node = self.find_file(node.clone()); |
175 | original_range(self.db, node.as_ref()) | 372 | original_range(self.db, node.as_ref()) |
176 | } | 373 | } |
177 | 374 | ||
178 | pub fn diagnostics_range(&self, diagnostics: &dyn Diagnostic) -> FileRange { | 375 | fn diagnostics_range(&self, diagnostics: &dyn Diagnostic) -> FileRange { |
179 | let src = diagnostics.source(); | 376 | let src = diagnostics.source(); |
180 | let root = self.db.parse_or_expand(src.file_id).unwrap(); | 377 | let root = self.db.parse_or_expand(src.file_id).unwrap(); |
181 | let node = src.value.to_node(&root); | 378 | let node = src.value.to_node(&root); |
182 | original_range(self.db, src.with_value(&node)) | 379 | original_range(self.db, src.with_value(&node)) |
183 | } | 380 | } |
184 | 381 | ||
185 | pub fn ancestors_with_macros(&self, node: SyntaxNode) -> impl Iterator<Item = SyntaxNode> + '_ { | 382 | fn ancestors_with_macros(&self, node: SyntaxNode) -> impl Iterator<Item = SyntaxNode> + '_ { |
186 | let node = self.find_file(node); | 383 | let node = self.find_file(node); |
187 | node.ancestors_with_macros(self.db).map(|it| it.value) | 384 | node.ancestors_with_macros(self.db.upcast()).map(|it| it.value) |
188 | } | 385 | } |
189 | 386 | ||
190 | pub fn ancestors_at_offset_with_macros( | 387 | fn ancestors_at_offset_with_macros( |
191 | &self, | 388 | &self, |
192 | node: &SyntaxNode, | 389 | node: &SyntaxNode, |
193 | offset: TextSize, | 390 | offset: TextSize, |
@@ -197,120 +394,104 @@ impl<'db, DB: HirDatabase> Semantics<'db, DB> { | |||
197 | .kmerge_by(|node1, node2| node1.text_range().len() < node2.text_range().len()) | 394 | .kmerge_by(|node1, node2| node1.text_range().len() < node2.text_range().len()) |
198 | } | 395 | } |
199 | 396 | ||
200 | /// Find a AstNode by offset inside SyntaxNode, if it is inside *Macrofile*, | 397 | fn type_of_expr(&self, expr: &ast::Expr) -> Option<Type> { |
201 | /// search up until it is of the target AstNode type | 398 | self.analyze(expr.syntax()).type_of_expr(self.db, &expr) |
202 | pub fn find_node_at_offset_with_macros<N: AstNode>( | ||
203 | &self, | ||
204 | node: &SyntaxNode, | ||
205 | offset: TextSize, | ||
206 | ) -> Option<N> { | ||
207 | self.ancestors_at_offset_with_macros(node, offset).find_map(N::cast) | ||
208 | } | 399 | } |
209 | 400 | ||
210 | /// Find a AstNode by offset inside SyntaxNode, if it is inside *MacroCall*, | 401 | fn type_of_pat(&self, pat: &ast::Pat) -> Option<Type> { |
211 | /// descend it and find again | 402 | self.analyze(pat.syntax()).type_of_pat(self.db, &pat) |
212 | pub fn find_node_at_offset_with_descend<N: AstNode>( | ||
213 | &self, | ||
214 | node: &SyntaxNode, | ||
215 | offset: TextSize, | ||
216 | ) -> Option<N> { | ||
217 | if let Some(it) = find_node_at_offset(&node, offset) { | ||
218 | return Some(it); | ||
219 | } | ||
220 | self.descend_node_at_offset(&node, offset) | ||
221 | } | 403 | } |
222 | 404 | ||
223 | pub fn type_of_expr(&self, expr: &ast::Expr) -> Option<Type> { | 405 | fn type_of_self(&self, param: &ast::SelfParam) -> Option<Type> { |
224 | self.analyze(expr.syntax()).type_of(self.db, &expr) | 406 | self.analyze(param.syntax()).type_of_self(self.db, ¶m) |
225 | } | 407 | } |
226 | 408 | ||
227 | pub fn type_of_pat(&self, pat: &ast::Pat) -> Option<Type> { | 409 | fn resolve_method_call(&self, call: &ast::MethodCallExpr) -> Option<FunctionId> { |
228 | self.analyze(pat.syntax()).type_of_pat(self.db, &pat) | 410 | self.analyze(call.syntax()).resolve_method_call(self.db, call) |
229 | } | 411 | } |
230 | 412 | ||
231 | pub fn resolve_method_call(&self, call: &ast::MethodCallExpr) -> Option<Function> { | 413 | fn resolve_method_call_as_callable(&self, call: &ast::MethodCallExpr) -> Option<Callable> { |
232 | self.analyze(call.syntax()).resolve_method_call(self.db, call) | 414 | // FIXME: this erases Substs |
415 | let func = self.resolve_method_call(call)?; | ||
416 | let ty = self.db.value_ty(func.into()); | ||
417 | let resolver = self.analyze(call.syntax()).resolver; | ||
418 | let ty = Type::new_with_resolver(self.db, &resolver, ty.value)?; | ||
419 | let mut res = ty.as_callable(self.db)?; | ||
420 | res.is_bound_method = true; | ||
421 | Some(res) | ||
233 | } | 422 | } |
234 | 423 | ||
235 | pub fn resolve_field(&self, field: &ast::FieldExpr) -> Option<Field> { | 424 | fn resolve_field(&self, field: &ast::FieldExpr) -> Option<Field> { |
236 | self.analyze(field.syntax()).resolve_field(self.db, field) | 425 | self.analyze(field.syntax()).resolve_field(self.db, field) |
237 | } | 426 | } |
238 | 427 | ||
239 | pub fn resolve_record_field(&self, field: &ast::RecordField) -> Option<(Field, Option<Local>)> { | 428 | fn resolve_record_field(&self, field: &ast::RecordExprField) -> Option<(Field, Option<Local>)> { |
240 | self.analyze(field.syntax()).resolve_record_field(self.db, field) | 429 | self.analyze(field.syntax()).resolve_record_field(self.db, field) |
241 | } | 430 | } |
242 | 431 | ||
243 | pub fn resolve_record_field_pat(&self, field: &ast::RecordFieldPat) -> Option<Field> { | 432 | fn resolve_record_field_pat(&self, field: &ast::RecordFieldPat) -> Option<Field> { |
244 | self.analyze(field.syntax()).resolve_record_field_pat(self.db, field) | 433 | self.analyze(field.syntax()).resolve_record_field_pat(self.db, field) |
245 | } | 434 | } |
246 | 435 | ||
247 | pub fn resolve_macro_call(&self, macro_call: &ast::MacroCall) -> Option<MacroDef> { | 436 | fn resolve_macro_call(&self, macro_call: &ast::MacroCall) -> Option<MacroDef> { |
248 | let sa = self.analyze(macro_call.syntax()); | 437 | let sa = self.analyze(macro_call.syntax()); |
249 | let macro_call = self.find_file(macro_call.syntax().clone()).with_value(macro_call); | 438 | let macro_call = self.find_file(macro_call.syntax().clone()).with_value(macro_call); |
250 | sa.resolve_macro_call(self.db, macro_call) | 439 | sa.resolve_macro_call(self.db, macro_call) |
251 | } | 440 | } |
252 | 441 | ||
253 | pub fn resolve_path(&self, path: &ast::Path) -> Option<PathResolution> { | 442 | fn resolve_path(&self, path: &ast::Path) -> Option<PathResolution> { |
254 | self.analyze(path.syntax()).resolve_path(self.db, path) | 443 | self.analyze(path.syntax()).resolve_path(self.db, path) |
255 | } | 444 | } |
256 | 445 | ||
257 | pub fn resolve_variant(&self, record_lit: ast::RecordLit) -> Option<VariantId> { | 446 | fn resolve_variant(&self, record_lit: ast::RecordExpr) -> Option<VariantId> { |
258 | self.analyze(record_lit.syntax()).resolve_variant(self.db, record_lit) | 447 | self.analyze(record_lit.syntax()).resolve_variant(self.db, record_lit) |
259 | } | 448 | } |
260 | 449 | ||
261 | pub fn lower_path(&self, path: &ast::Path) -> Option<Path> { | 450 | fn lower_path(&self, path: &ast::Path) -> Option<Path> { |
262 | let src = self.find_file(path.syntax().clone()); | 451 | let src = self.find_file(path.syntax().clone()); |
263 | Path::from_src(path.clone(), &Hygiene::new(self.db.upcast(), src.file_id.into())) | 452 | Path::from_src(path.clone(), &Hygiene::new(self.db.upcast(), src.file_id.into())) |
264 | } | 453 | } |
265 | 454 | ||
266 | pub fn resolve_bind_pat_to_const(&self, pat: &ast::BindPat) -> Option<ModuleDef> { | 455 | fn resolve_bind_pat_to_const(&self, pat: &ast::BindPat) -> Option<ModuleDef> { |
267 | self.analyze(pat.syntax()).resolve_bind_pat_to_const(self.db, pat) | 456 | self.analyze(pat.syntax()).resolve_bind_pat_to_const(self.db, pat) |
268 | } | 457 | } |
269 | 458 | ||
270 | // FIXME: use this instead? | 459 | fn record_literal_missing_fields(&self, literal: &ast::RecordExpr) -> Vec<(Field, Type)> { |
271 | // pub fn resolve_name_ref(&self, name_ref: &ast::NameRef) -> Option<???>; | ||
272 | |||
273 | pub fn record_literal_missing_fields(&self, literal: &ast::RecordLit) -> Vec<(Field, Type)> { | ||
274 | self.analyze(literal.syntax()) | 460 | self.analyze(literal.syntax()) |
275 | .record_literal_missing_fields(self.db, literal) | 461 | .record_literal_missing_fields(self.db, literal) |
276 | .unwrap_or_default() | 462 | .unwrap_or_default() |
277 | } | 463 | } |
278 | 464 | ||
279 | pub fn record_pattern_missing_fields(&self, pattern: &ast::RecordPat) -> Vec<(Field, Type)> { | 465 | fn record_pattern_missing_fields(&self, pattern: &ast::RecordPat) -> Vec<(Field, Type)> { |
280 | self.analyze(pattern.syntax()) | 466 | self.analyze(pattern.syntax()) |
281 | .record_pattern_missing_fields(self.db, pattern) | 467 | .record_pattern_missing_fields(self.db, pattern) |
282 | .unwrap_or_default() | 468 | .unwrap_or_default() |
283 | } | 469 | } |
284 | 470 | ||
285 | pub fn to_def<T: ToDef>(&self, src: &T) -> Option<T::Def> { | ||
286 | let src = self.find_file(src.syntax().clone()).with_value(src).cloned(); | ||
287 | T::to_def(self, src) | ||
288 | } | ||
289 | |||
290 | fn with_ctx<F: FnOnce(&mut SourceToDefCtx) -> T, T>(&self, f: F) -> T { | 471 | fn with_ctx<F: FnOnce(&mut SourceToDefCtx) -> T, T>(&self, f: F) -> T { |
291 | let mut cache = self.s2d_cache.borrow_mut(); | 472 | let mut cache = self.s2d_cache.borrow_mut(); |
292 | let mut ctx = SourceToDefCtx { db: self.db, cache: &mut *cache }; | 473 | let mut ctx = SourceToDefCtx { db: self.db, cache: &mut *cache }; |
293 | f(&mut ctx) | 474 | f(&mut ctx) |
294 | } | 475 | } |
295 | 476 | ||
296 | pub fn to_module_def(&self, file: FileId) -> Option<Module> { | 477 | fn to_module_def(&self, file: FileId) -> Option<Module> { |
297 | self.with_ctx(|ctx| ctx.file_to_def(file)).map(Module::from) | 478 | self.with_ctx(|ctx| ctx.file_to_def(file)).map(Module::from) |
298 | } | 479 | } |
299 | 480 | ||
300 | pub fn scope(&self, node: &SyntaxNode) -> SemanticsScope<'db, DB> { | 481 | fn scope(&self, node: &SyntaxNode) -> SemanticsScope<'db> { |
301 | let node = self.find_file(node.clone()); | 482 | let node = self.find_file(node.clone()); |
302 | let resolver = self.analyze2(node.as_ref(), None).resolver; | 483 | let resolver = self.analyze2(node.as_ref(), None).resolver; |
303 | SemanticsScope { db: self.db, resolver } | 484 | SemanticsScope { db: self.db, resolver } |
304 | } | 485 | } |
305 | 486 | ||
306 | pub fn scope_at_offset(&self, node: &SyntaxNode, offset: TextSize) -> SemanticsScope<'db, DB> { | 487 | fn scope_at_offset(&self, node: &SyntaxNode, offset: TextSize) -> SemanticsScope<'db> { |
307 | let node = self.find_file(node.clone()); | 488 | let node = self.find_file(node.clone()); |
308 | let resolver = self.analyze2(node.as_ref(), Some(offset)).resolver; | 489 | let resolver = self.analyze2(node.as_ref(), Some(offset)).resolver; |
309 | SemanticsScope { db: self.db, resolver } | 490 | SemanticsScope { db: self.db, resolver } |
310 | } | 491 | } |
311 | 492 | ||
312 | pub fn scope_for_def(&self, def: Trait) -> SemanticsScope<'db, DB> { | 493 | fn scope_for_def(&self, def: Trait) -> SemanticsScope<'db> { |
313 | let resolver = def.id.resolver(self.db); | 494 | let resolver = def.id.resolver(self.db.upcast()); |
314 | SemanticsScope { db: self.db, resolver } | 495 | SemanticsScope { db: self.db, resolver } |
315 | } | 496 | } |
316 | 497 | ||
@@ -331,12 +512,13 @@ impl<'db, DB: HirDatabase> Semantics<'db, DB> { | |||
331 | ChildContainer::DefWithBodyId(def) => { | 512 | ChildContainer::DefWithBodyId(def) => { |
332 | return SourceAnalyzer::new_for_body(self.db, def, src, offset) | 513 | return SourceAnalyzer::new_for_body(self.db, def, src, offset) |
333 | } | 514 | } |
334 | ChildContainer::TraitId(it) => it.resolver(self.db), | 515 | ChildContainer::TraitId(it) => it.resolver(self.db.upcast()), |
335 | ChildContainer::ImplId(it) => it.resolver(self.db), | 516 | ChildContainer::ImplId(it) => it.resolver(self.db.upcast()), |
336 | ChildContainer::ModuleId(it) => it.resolver(self.db), | 517 | ChildContainer::ModuleId(it) => it.resolver(self.db.upcast()), |
337 | ChildContainer::EnumId(it) => it.resolver(self.db), | 518 | ChildContainer::EnumId(it) => it.resolver(self.db.upcast()), |
338 | ChildContainer::VariantId(it) => it.resolver(self.db), | 519 | ChildContainer::VariantId(it) => it.resolver(self.db.upcast()), |
339 | ChildContainer::GenericDefId(it) => it.resolver(self.db), | 520 | ChildContainer::TypeAliasId(it) => it.resolver(self.db.upcast()), |
521 | ChildContainer::GenericDefId(it) => it.resolver(self.db.upcast()), | ||
340 | }; | 522 | }; |
341 | SourceAnalyzer::new_for_resolver(resolver, src) | 523 | SourceAnalyzer::new_for_resolver(resolver, src) |
342 | } | 524 | } |
@@ -348,7 +530,7 @@ impl<'db, DB: HirDatabase> Semantics<'db, DB> { | |||
348 | assert!(prev == None || prev == Some(file_id)) | 530 | assert!(prev == None || prev == Some(file_id)) |
349 | } | 531 | } |
350 | 532 | ||
351 | pub fn assert_contains_node(&self, node: &SyntaxNode) { | 533 | fn assert_contains_node(&self, node: &SyntaxNode) { |
352 | self.find_file(node.clone()); | 534 | self.find_file(node.clone()); |
353 | } | 535 | } |
354 | 536 | ||
@@ -382,14 +564,14 @@ impl<'db, DB: HirDatabase> Semantics<'db, DB> { | |||
382 | pub trait ToDef: AstNode + Clone { | 564 | pub trait ToDef: AstNode + Clone { |
383 | type Def; | 565 | type Def; |
384 | 566 | ||
385 | fn to_def<DB: HirDatabase>(sema: &Semantics<DB>, src: InFile<Self>) -> Option<Self::Def>; | 567 | fn to_def(sema: &SemanticsImpl, src: InFile<Self>) -> Option<Self::Def>; |
386 | } | 568 | } |
387 | 569 | ||
388 | macro_rules! to_def_impls { | 570 | macro_rules! to_def_impls { |
389 | ($(($def:path, $ast:path, $meth:ident)),* ,) => {$( | 571 | ($(($def:path, $ast:path, $meth:ident)),* ,) => {$( |
390 | impl ToDef for $ast { | 572 | impl ToDef for $ast { |
391 | type Def = $def; | 573 | type Def = $def; |
392 | fn to_def<DB: HirDatabase>(sema: &Semantics<DB>, src: InFile<Self>) -> Option<Self::Def> { | 574 | fn to_def(sema: &SemanticsImpl, src: InFile<Self>) -> Option<Self::Def> { |
393 | sema.with_ctx(|ctx| ctx.$meth(src)).map(<$def>::from) | 575 | sema.with_ctx(|ctx| ctx.$meth(src)).map(<$def>::from) |
394 | } | 576 | } |
395 | } | 577 | } |
@@ -398,18 +580,18 @@ macro_rules! to_def_impls { | |||
398 | 580 | ||
399 | to_def_impls![ | 581 | to_def_impls![ |
400 | (crate::Module, ast::Module, module_to_def), | 582 | (crate::Module, ast::Module, module_to_def), |
401 | (crate::Struct, ast::StructDef, struct_to_def), | 583 | (crate::Struct, ast::Struct, struct_to_def), |
402 | (crate::Enum, ast::EnumDef, enum_to_def), | 584 | (crate::Enum, ast::Enum, enum_to_def), |
403 | (crate::Union, ast::UnionDef, union_to_def), | 585 | (crate::Union, ast::Union, union_to_def), |
404 | (crate::Trait, ast::TraitDef, trait_to_def), | 586 | (crate::Trait, ast::Trait, trait_to_def), |
405 | (crate::ImplDef, ast::ImplDef, impl_to_def), | 587 | (crate::ImplDef, ast::Impl, impl_to_def), |
406 | (crate::TypeAlias, ast::TypeAliasDef, type_alias_to_def), | 588 | (crate::TypeAlias, ast::TypeAlias, type_alias_to_def), |
407 | (crate::Const, ast::ConstDef, const_to_def), | 589 | (crate::Const, ast::Const, const_to_def), |
408 | (crate::Static, ast::StaticDef, static_to_def), | 590 | (crate::Static, ast::Static, static_to_def), |
409 | (crate::Function, ast::FnDef, fn_to_def), | 591 | (crate::Function, ast::Fn, fn_to_def), |
410 | (crate::Field, ast::RecordFieldDef, record_field_to_def), | 592 | (crate::Field, ast::RecordField, record_field_to_def), |
411 | (crate::Field, ast::TupleFieldDef, tuple_field_to_def), | 593 | (crate::Field, ast::TupleField, tuple_field_to_def), |
412 | (crate::EnumVariant, ast::EnumVariant, enum_variant_to_def), | 594 | (crate::EnumVariant, ast::Variant, enum_variant_to_def), |
413 | (crate::TypeParam, ast::TypeParam, type_param_to_def), | 595 | (crate::TypeParam, ast::TypeParam, type_param_to_def), |
414 | (crate::MacroDef, ast::MacroCall, macro_call_to_def), // this one is dubious, not all calls are macros | 596 | (crate::MacroDef, ast::MacroCall, macro_call_to_def), // this one is dubious, not all calls are macros |
415 | (crate::Local, ast::BindPat, bind_pat_to_def), | 597 | (crate::Local, ast::BindPat, bind_pat_to_def), |
@@ -419,12 +601,13 @@ fn find_root(node: &SyntaxNode) -> SyntaxNode { | |||
419 | node.ancestors().last().unwrap() | 601 | node.ancestors().last().unwrap() |
420 | } | 602 | } |
421 | 603 | ||
422 | pub struct SemanticsScope<'a, DB> { | 604 | #[derive(Debug)] |
423 | pub db: &'a DB, | 605 | pub struct SemanticsScope<'a> { |
606 | pub db: &'a dyn HirDatabase, | ||
424 | resolver: Resolver, | 607 | resolver: Resolver, |
425 | } | 608 | } |
426 | 609 | ||
427 | impl<'a, DB: HirDatabase> SemanticsScope<'a, DB> { | 610 | impl<'a> SemanticsScope<'a> { |
428 | pub fn module(&self) -> Option<Module> { | 611 | pub fn module(&self) -> Option<Module> { |
429 | Some(Module { id: self.resolver.module()? }) | 612 | Some(Module { id: self.resolver.module()? }) |
430 | } | 613 | } |
@@ -433,13 +616,13 @@ impl<'a, DB: HirDatabase> SemanticsScope<'a, DB> { | |||
433 | // FIXME: rename to visible_traits to not repeat scope? | 616 | // FIXME: rename to visible_traits to not repeat scope? |
434 | pub fn traits_in_scope(&self) -> FxHashSet<TraitId> { | 617 | pub fn traits_in_scope(&self) -> FxHashSet<TraitId> { |
435 | let resolver = &self.resolver; | 618 | let resolver = &self.resolver; |
436 | resolver.traits_in_scope(self.db) | 619 | resolver.traits_in_scope(self.db.upcast()) |
437 | } | 620 | } |
438 | 621 | ||
439 | pub fn process_all_names(&self, f: &mut dyn FnMut(Name, ScopeDef)) { | 622 | pub fn process_all_names(&self, f: &mut dyn FnMut(Name, ScopeDef)) { |
440 | let resolver = &self.resolver; | 623 | let resolver = &self.resolver; |
441 | 624 | ||
442 | resolver.process_all_names(self.db, &mut |name, def| { | 625 | resolver.process_all_names(self.db.upcast(), &mut |name, def| { |
443 | let def = match def { | 626 | let def = match def { |
444 | resolver::ScopeDef::PerNs(it) => { | 627 | resolver::ScopeDef::PerNs(it) => { |
445 | let items = ScopeDef::all_items(it); | 628 | let items = ScopeDef::all_items(it); |
diff --git a/crates/ra_hir/src/semantics/source_to_def.rs b/crates/ra_hir/src/semantics/source_to_def.rs index 8af64fdc1..d1994e2e7 100644 --- a/crates/ra_hir/src/semantics/source_to_def.rs +++ b/crates/ra_hir/src/semantics/source_to_def.rs | |||
@@ -16,6 +16,7 @@ use ra_syntax::{ | |||
16 | match_ast, AstNode, SyntaxNode, | 16 | match_ast, AstNode, SyntaxNode, |
17 | }; | 17 | }; |
18 | use rustc_hash::FxHashMap; | 18 | use rustc_hash::FxHashMap; |
19 | use stdx::impl_from; | ||
19 | 20 | ||
20 | use crate::{db::HirDatabase, InFile, MacroDefId}; | 21 | use crate::{db::HirDatabase, InFile, MacroDefId}; |
21 | 22 | ||
@@ -64,53 +65,44 @@ impl SourceToDefCtx<'_, '_> { | |||
64 | Some(ModuleId { krate: parent_module.krate, local_id: child_id }) | 65 | Some(ModuleId { krate: parent_module.krate, local_id: child_id }) |
65 | } | 66 | } |
66 | 67 | ||
67 | pub(super) fn trait_to_def(&mut self, src: InFile<ast::TraitDef>) -> Option<TraitId> { | 68 | pub(super) fn trait_to_def(&mut self, src: InFile<ast::Trait>) -> Option<TraitId> { |
68 | self.to_def(src, keys::TRAIT) | 69 | self.to_def(src, keys::TRAIT) |
69 | } | 70 | } |
70 | pub(super) fn impl_to_def(&mut self, src: InFile<ast::ImplDef>) -> Option<ImplId> { | 71 | pub(super) fn impl_to_def(&mut self, src: InFile<ast::Impl>) -> Option<ImplId> { |
71 | self.to_def(src, keys::IMPL) | 72 | self.to_def(src, keys::IMPL) |
72 | } | 73 | } |
73 | pub(super) fn fn_to_def(&mut self, src: InFile<ast::FnDef>) -> Option<FunctionId> { | 74 | pub(super) fn fn_to_def(&mut self, src: InFile<ast::Fn>) -> Option<FunctionId> { |
74 | self.to_def(src, keys::FUNCTION) | 75 | self.to_def(src, keys::FUNCTION) |
75 | } | 76 | } |
76 | pub(super) fn struct_to_def(&mut self, src: InFile<ast::StructDef>) -> Option<StructId> { | 77 | pub(super) fn struct_to_def(&mut self, src: InFile<ast::Struct>) -> Option<StructId> { |
77 | self.to_def(src, keys::STRUCT) | 78 | self.to_def(src, keys::STRUCT) |
78 | } | 79 | } |
79 | pub(super) fn enum_to_def(&mut self, src: InFile<ast::EnumDef>) -> Option<EnumId> { | 80 | pub(super) fn enum_to_def(&mut self, src: InFile<ast::Enum>) -> Option<EnumId> { |
80 | self.to_def(src, keys::ENUM) | 81 | self.to_def(src, keys::ENUM) |
81 | } | 82 | } |
82 | pub(super) fn union_to_def(&mut self, src: InFile<ast::UnionDef>) -> Option<UnionId> { | 83 | pub(super) fn union_to_def(&mut self, src: InFile<ast::Union>) -> Option<UnionId> { |
83 | self.to_def(src, keys::UNION) | 84 | self.to_def(src, keys::UNION) |
84 | } | 85 | } |
85 | pub(super) fn static_to_def(&mut self, src: InFile<ast::StaticDef>) -> Option<StaticId> { | 86 | pub(super) fn static_to_def(&mut self, src: InFile<ast::Static>) -> Option<StaticId> { |
86 | self.to_def(src, keys::STATIC) | 87 | self.to_def(src, keys::STATIC) |
87 | } | 88 | } |
88 | pub(super) fn const_to_def(&mut self, src: InFile<ast::ConstDef>) -> Option<ConstId> { | 89 | pub(super) fn const_to_def(&mut self, src: InFile<ast::Const>) -> Option<ConstId> { |
89 | self.to_def(src, keys::CONST) | 90 | self.to_def(src, keys::CONST) |
90 | } | 91 | } |
91 | pub(super) fn type_alias_to_def( | 92 | pub(super) fn type_alias_to_def(&mut self, src: InFile<ast::TypeAlias>) -> Option<TypeAliasId> { |
92 | &mut self, | ||
93 | src: InFile<ast::TypeAliasDef>, | ||
94 | ) -> Option<TypeAliasId> { | ||
95 | self.to_def(src, keys::TYPE_ALIAS) | 93 | self.to_def(src, keys::TYPE_ALIAS) |
96 | } | 94 | } |
97 | pub(super) fn record_field_to_def( | 95 | pub(super) fn record_field_to_def(&mut self, src: InFile<ast::RecordField>) -> Option<FieldId> { |
98 | &mut self, | ||
99 | src: InFile<ast::RecordFieldDef>, | ||
100 | ) -> Option<FieldId> { | ||
101 | self.to_def(src, keys::RECORD_FIELD) | 96 | self.to_def(src, keys::RECORD_FIELD) |
102 | } | 97 | } |
103 | pub(super) fn tuple_field_to_def( | 98 | pub(super) fn tuple_field_to_def(&mut self, src: InFile<ast::TupleField>) -> Option<FieldId> { |
104 | &mut self, | ||
105 | src: InFile<ast::TupleFieldDef>, | ||
106 | ) -> Option<FieldId> { | ||
107 | self.to_def(src, keys::TUPLE_FIELD) | 99 | self.to_def(src, keys::TUPLE_FIELD) |
108 | } | 100 | } |
109 | pub(super) fn enum_variant_to_def( | 101 | pub(super) fn enum_variant_to_def( |
110 | &mut self, | 102 | &mut self, |
111 | src: InFile<ast::EnumVariant>, | 103 | src: InFile<ast::Variant>, |
112 | ) -> Option<EnumVariantId> { | 104 | ) -> Option<EnumVariantId> { |
113 | self.to_def(src, keys::ENUM_VARIANT) | 105 | self.to_def(src, keys::VARIANT) |
114 | } | 106 | } |
115 | pub(super) fn bind_pat_to_def( | 107 | pub(super) fn bind_pat_to_def( |
116 | &mut self, | 108 | &mut self, |
@@ -162,38 +154,42 @@ impl SourceToDefCtx<'_, '_> { | |||
162 | let def = self.module_to_def(container.with_value(it))?; | 154 | let def = self.module_to_def(container.with_value(it))?; |
163 | def.into() | 155 | def.into() |
164 | }, | 156 | }, |
165 | ast::TraitDef(it) => { | 157 | ast::Trait(it) => { |
166 | let def = self.trait_to_def(container.with_value(it))?; | 158 | let def = self.trait_to_def(container.with_value(it))?; |
167 | def.into() | 159 | def.into() |
168 | }, | 160 | }, |
169 | ast::ImplDef(it) => { | 161 | ast::Impl(it) => { |
170 | let def = self.impl_to_def(container.with_value(it))?; | 162 | let def = self.impl_to_def(container.with_value(it))?; |
171 | def.into() | 163 | def.into() |
172 | }, | 164 | }, |
173 | ast::FnDef(it) => { | 165 | ast::Fn(it) => { |
174 | let def = self.fn_to_def(container.with_value(it))?; | 166 | let def = self.fn_to_def(container.with_value(it))?; |
175 | DefWithBodyId::from(def).into() | 167 | DefWithBodyId::from(def).into() |
176 | }, | 168 | }, |
177 | ast::StructDef(it) => { | 169 | ast::Struct(it) => { |
178 | let def = self.struct_to_def(container.with_value(it))?; | 170 | let def = self.struct_to_def(container.with_value(it))?; |
179 | VariantId::from(def).into() | 171 | VariantId::from(def).into() |
180 | }, | 172 | }, |
181 | ast::EnumDef(it) => { | 173 | ast::Enum(it) => { |
182 | let def = self.enum_to_def(container.with_value(it))?; | 174 | let def = self.enum_to_def(container.with_value(it))?; |
183 | def.into() | 175 | def.into() |
184 | }, | 176 | }, |
185 | ast::UnionDef(it) => { | 177 | ast::Union(it) => { |
186 | let def = self.union_to_def(container.with_value(it))?; | 178 | let def = self.union_to_def(container.with_value(it))?; |
187 | VariantId::from(def).into() | 179 | VariantId::from(def).into() |
188 | }, | 180 | }, |
189 | ast::StaticDef(it) => { | 181 | ast::Static(it) => { |
190 | let def = self.static_to_def(container.with_value(it))?; | 182 | let def = self.static_to_def(container.with_value(it))?; |
191 | DefWithBodyId::from(def).into() | 183 | DefWithBodyId::from(def).into() |
192 | }, | 184 | }, |
193 | ast::ConstDef(it) => { | 185 | ast::Const(it) => { |
194 | let def = self.const_to_def(container.with_value(it))?; | 186 | let def = self.const_to_def(container.with_value(it))?; |
195 | DefWithBodyId::from(def).into() | 187 | DefWithBodyId::from(def).into() |
196 | }, | 188 | }, |
189 | ast::TypeAlias(it) => { | ||
190 | let def = self.type_alias_to_def(container.with_value(it))?; | ||
191 | def.into() | ||
192 | }, | ||
197 | _ => continue, | 193 | _ => continue, |
198 | } | 194 | } |
199 | }; | 195 | }; |
@@ -208,12 +204,12 @@ impl SourceToDefCtx<'_, '_> { | |||
208 | for container in src.cloned().ancestors_with_macros(self.db.upcast()).skip(1) { | 204 | for container in src.cloned().ancestors_with_macros(self.db.upcast()).skip(1) { |
209 | let res: GenericDefId = match_ast! { | 205 | let res: GenericDefId = match_ast! { |
210 | match (container.value) { | 206 | match (container.value) { |
211 | ast::FnDef(it) => self.fn_to_def(container.with_value(it))?.into(), | 207 | ast::Fn(it) => self.fn_to_def(container.with_value(it))?.into(), |
212 | ast::StructDef(it) => self.struct_to_def(container.with_value(it))?.into(), | 208 | ast::Struct(it) => self.struct_to_def(container.with_value(it))?.into(), |
213 | ast::EnumDef(it) => self.enum_to_def(container.with_value(it))?.into(), | 209 | ast::Enum(it) => self.enum_to_def(container.with_value(it))?.into(), |
214 | ast::TraitDef(it) => self.trait_to_def(container.with_value(it))?.into(), | 210 | ast::Trait(it) => self.trait_to_def(container.with_value(it))?.into(), |
215 | ast::TypeAliasDef(it) => self.type_alias_to_def(container.with_value(it))?.into(), | 211 | ast::TypeAlias(it) => self.type_alias_to_def(container.with_value(it))?.into(), |
216 | ast::ImplDef(it) => self.impl_to_def(container.with_value(it))?.into(), | 212 | ast::Impl(it) => self.impl_to_def(container.with_value(it))?.into(), |
217 | _ => continue, | 213 | _ => continue, |
218 | } | 214 | } |
219 | }; | 215 | }; |
@@ -226,9 +222,9 @@ impl SourceToDefCtx<'_, '_> { | |||
226 | for container in src.cloned().ancestors_with_macros(self.db.upcast()).skip(1) { | 222 | for container in src.cloned().ancestors_with_macros(self.db.upcast()).skip(1) { |
227 | let res: DefWithBodyId = match_ast! { | 223 | let res: DefWithBodyId = match_ast! { |
228 | match (container.value) { | 224 | match (container.value) { |
229 | ast::ConstDef(it) => self.const_to_def(container.with_value(it))?.into(), | 225 | ast::Const(it) => self.const_to_def(container.with_value(it))?.into(), |
230 | ast::StaticDef(it) => self.static_to_def(container.with_value(it))?.into(), | 226 | ast::Static(it) => self.static_to_def(container.with_value(it))?.into(), |
231 | ast::FnDef(it) => self.fn_to_def(container.with_value(it))?.into(), | 227 | ast::Fn(it) => self.fn_to_def(container.with_value(it))?.into(), |
232 | _ => continue, | 228 | _ => continue, |
233 | } | 229 | } |
234 | }; | 230 | }; |
@@ -246,19 +242,21 @@ pub(crate) enum ChildContainer { | |||
246 | ImplId(ImplId), | 242 | ImplId(ImplId), |
247 | EnumId(EnumId), | 243 | EnumId(EnumId), |
248 | VariantId(VariantId), | 244 | VariantId(VariantId), |
245 | TypeAliasId(TypeAliasId), | ||
249 | /// XXX: this might be the same def as, for example an `EnumId`. However, | 246 | /// XXX: this might be the same def as, for example an `EnumId`. However, |
250 | /// here the children generic parameters, and not, eg enum variants. | 247 | /// here the children generic parameters, and not, eg enum variants. |
251 | GenericDefId(GenericDefId), | 248 | GenericDefId(GenericDefId), |
252 | } | 249 | } |
253 | impl_froms! { | 250 | impl_from! { |
254 | ChildContainer: | ||
255 | DefWithBodyId, | 251 | DefWithBodyId, |
256 | ModuleId, | 252 | ModuleId, |
257 | TraitId, | 253 | TraitId, |
258 | ImplId, | 254 | ImplId, |
259 | EnumId, | 255 | EnumId, |
260 | VariantId, | 256 | VariantId, |
257 | TypeAliasId, | ||
261 | GenericDefId | 258 | GenericDefId |
259 | for ChildContainer | ||
262 | } | 260 | } |
263 | 261 | ||
264 | impl ChildContainer { | 262 | impl ChildContainer { |
@@ -271,6 +269,7 @@ impl ChildContainer { | |||
271 | ChildContainer::ImplId(it) => it.child_by_source(db), | 269 | ChildContainer::ImplId(it) => it.child_by_source(db), |
272 | ChildContainer::EnumId(it) => it.child_by_source(db), | 270 | ChildContainer::EnumId(it) => it.child_by_source(db), |
273 | ChildContainer::VariantId(it) => it.child_by_source(db), | 271 | ChildContainer::VariantId(it) => it.child_by_source(db), |
272 | ChildContainer::TypeAliasId(_) => DynMap::default(), | ||
274 | ChildContainer::GenericDefId(it) => it.child_by_source(db), | 273 | ChildContainer::GenericDefId(it) => it.child_by_source(db), |
275 | } | 274 | } |
276 | } | 275 | } |
diff --git a/crates/ra_hir/src/source_analyzer.rs b/crates/ra_hir/src/source_analyzer.rs index 1d6c47103..f2e630ef1 100644 --- a/crates/ra_hir/src/source_analyzer.rs +++ b/crates/ra_hir/src/source_analyzer.rs | |||
@@ -14,11 +14,11 @@ use hir_def::{ | |||
14 | }, | 14 | }, |
15 | expr::{ExprId, Pat, PatId}, | 15 | expr::{ExprId, Pat, PatId}, |
16 | resolver::{resolver_for_scope, Resolver, TypeNs, ValueNs}, | 16 | resolver::{resolver_for_scope, Resolver, TypeNs, ValueNs}, |
17 | AsMacroCall, DefWithBodyId, FieldId, LocalFieldId, VariantId, | 17 | AsMacroCall, DefWithBodyId, FieldId, FunctionId, LocalFieldId, VariantId, |
18 | }; | 18 | }; |
19 | use hir_expand::{hygiene::Hygiene, name::AsName, HirFileId, InFile}; | 19 | use hir_expand::{hygiene::Hygiene, name::AsName, HirFileId, InFile}; |
20 | use hir_ty::{ | 20 | use hir_ty::{ |
21 | expr::{record_literal_missing_fields, record_pattern_missing_fields}, | 21 | diagnostics::{record_literal_missing_fields, record_pattern_missing_fields}, |
22 | InferenceResult, Substs, Ty, | 22 | InferenceResult, Substs, Ty, |
23 | }; | 23 | }; |
24 | use ra_syntax::{ | 24 | use ra_syntax::{ |
@@ -115,7 +115,7 @@ impl SourceAnalyzer { | |||
115 | Some(res) | 115 | Some(res) |
116 | } | 116 | } |
117 | 117 | ||
118 | pub(crate) fn type_of(&self, db: &dyn HirDatabase, expr: &ast::Expr) -> Option<Type> { | 118 | pub(crate) fn type_of_expr(&self, db: &dyn HirDatabase, expr: &ast::Expr) -> Option<Type> { |
119 | let expr_id = self.expr_id(db, expr)?; | 119 | let expr_id = self.expr_id(db, expr)?; |
120 | let ty = self.infer.as_ref()?[expr_id].clone(); | 120 | let ty = self.infer.as_ref()?[expr_id].clone(); |
121 | Type::new_with_resolver(db, &self.resolver, ty) | 121 | Type::new_with_resolver(db, &self.resolver, ty) |
@@ -127,13 +127,24 @@ impl SourceAnalyzer { | |||
127 | Type::new_with_resolver(db, &self.resolver, ty) | 127 | Type::new_with_resolver(db, &self.resolver, ty) |
128 | } | 128 | } |
129 | 129 | ||
130 | pub(crate) fn type_of_self( | ||
131 | &self, | ||
132 | db: &dyn HirDatabase, | ||
133 | param: &ast::SelfParam, | ||
134 | ) -> Option<Type> { | ||
135 | let src = InFile { file_id: self.file_id, value: param }; | ||
136 | let pat_id = self.body_source_map.as_ref()?.node_self_param(src)?; | ||
137 | let ty = self.infer.as_ref()?[pat_id].clone(); | ||
138 | Type::new_with_resolver(db, &self.resolver, ty) | ||
139 | } | ||
140 | |||
130 | pub(crate) fn resolve_method_call( | 141 | pub(crate) fn resolve_method_call( |
131 | &self, | 142 | &self, |
132 | db: &dyn HirDatabase, | 143 | db: &dyn HirDatabase, |
133 | call: &ast::MethodCallExpr, | 144 | call: &ast::MethodCallExpr, |
134 | ) -> Option<Function> { | 145 | ) -> Option<FunctionId> { |
135 | let expr_id = self.expr_id(db, &call.clone().into())?; | 146 | let expr_id = self.expr_id(db, &call.clone().into())?; |
136 | self.infer.as_ref()?.method_resolution(expr_id).map(Function::from) | 147 | self.infer.as_ref()?.method_resolution(expr_id) |
137 | } | 148 | } |
138 | 149 | ||
139 | pub(crate) fn resolve_field( | 150 | pub(crate) fn resolve_field( |
@@ -148,7 +159,7 @@ impl SourceAnalyzer { | |||
148 | pub(crate) fn resolve_record_field( | 159 | pub(crate) fn resolve_record_field( |
149 | &self, | 160 | &self, |
150 | db: &dyn HirDatabase, | 161 | db: &dyn HirDatabase, |
151 | field: &ast::RecordField, | 162 | field: &ast::RecordExprField, |
152 | ) -> Option<(Field, Option<Local>)> { | 163 | ) -> Option<(Field, Option<Local>)> { |
153 | let expr = field.expr()?; | 164 | let expr = field.expr()?; |
154 | let expr_id = self.expr_id(db, &expr)?; | 165 | let expr_id = self.expr_id(db, &expr)?; |
@@ -235,7 +246,7 @@ impl SourceAnalyzer { | |||
235 | } | 246 | } |
236 | } | 247 | } |
237 | 248 | ||
238 | if let Some(rec_lit) = path.syntax().parent().and_then(ast::RecordLit::cast) { | 249 | if let Some(rec_lit) = path.syntax().parent().and_then(ast::RecordExpr::cast) { |
239 | let expr_id = self.expr_id(db, &rec_lit.into())?; | 250 | let expr_id = self.expr_id(db, &rec_lit.into())?; |
240 | if let Some(VariantId::EnumVariantId(variant)) = | 251 | if let Some(VariantId::EnumVariantId(variant)) = |
241 | self.infer.as_ref()?.variant_resolution_for_expr(expr_id) | 252 | self.infer.as_ref()?.variant_resolution_for_expr(expr_id) |
@@ -273,7 +284,7 @@ impl SourceAnalyzer { | |||
273 | pub(crate) fn record_literal_missing_fields( | 284 | pub(crate) fn record_literal_missing_fields( |
274 | &self, | 285 | &self, |
275 | db: &dyn HirDatabase, | 286 | db: &dyn HirDatabase, |
276 | literal: &ast::RecordLit, | 287 | literal: &ast::RecordExpr, |
277 | ) -> Option<Vec<(Field, Type)>> { | 288 | ) -> Option<Vec<(Field, Type)>> { |
278 | let krate = self.resolver.krate()?; | 289 | let krate = self.resolver.krate()?; |
279 | let body = self.body.as_ref()?; | 290 | let body = self.body.as_ref()?; |
@@ -341,13 +352,13 @@ impl SourceAnalyzer { | |||
341 | let macro_call_id = macro_call.as_call_id(db.upcast(), krate, |path| { | 352 | let macro_call_id = macro_call.as_call_id(db.upcast(), krate, |path| { |
342 | self.resolver.resolve_path_as_macro(db.upcast(), &path) | 353 | self.resolver.resolve_path_as_macro(db.upcast(), &path) |
343 | })?; | 354 | })?; |
344 | Some(macro_call_id.as_file()) | 355 | Some(macro_call_id.as_file()).filter(|it| it.expansion_level(db.upcast()) < 64) |
345 | } | 356 | } |
346 | 357 | ||
347 | pub(crate) fn resolve_variant( | 358 | pub(crate) fn resolve_variant( |
348 | &self, | 359 | &self, |
349 | db: &dyn HirDatabase, | 360 | db: &dyn HirDatabase, |
350 | record_lit: ast::RecordLit, | 361 | record_lit: ast::RecordExpr, |
351 | ) -> Option<VariantId> { | 362 | ) -> Option<VariantId> { |
352 | let infer = self.infer.as_ref()?; | 363 | let infer = self.infer.as_ref()?; |
353 | let expr_id = self.expr_id(db, &record_lit.into())?; | 364 | let expr_id = self.expr_id(db, &record_lit.into())?; |
@@ -394,8 +405,7 @@ fn scope_for_offset( | |||
394 | ) | 405 | ) |
395 | }) | 406 | }) |
396 | .map(|(expr_range, scope)| { | 407 | .map(|(expr_range, scope)| { |
397 | adjust(db, scopes, source_map, expr_range, offset.file_id, offset.value) | 408 | adjust(db, scopes, source_map, expr_range, offset).unwrap_or(*scope) |
398 | .unwrap_or(*scope) | ||
399 | }) | 409 | }) |
400 | } | 410 | } |
401 | 411 | ||
@@ -406,8 +416,7 @@ fn adjust( | |||
406 | scopes: &ExprScopes, | 416 | scopes: &ExprScopes, |
407 | source_map: &BodySourceMap, | 417 | source_map: &BodySourceMap, |
408 | expr_range: TextRange, | 418 | expr_range: TextRange, |
409 | file_id: HirFileId, | 419 | offset: InFile<TextSize>, |
410 | offset: TextSize, | ||
411 | ) -> Option<ScopeId> { | 420 | ) -> Option<ScopeId> { |
412 | let child_scopes = scopes | 421 | let child_scopes = scopes |
413 | .scope_by_expr() | 422 | .scope_by_expr() |
@@ -415,7 +424,7 @@ fn adjust( | |||
415 | .filter_map(|(id, scope)| { | 424 | .filter_map(|(id, scope)| { |
416 | let source = source_map.expr_syntax(*id).ok()?; | 425 | let source = source_map.expr_syntax(*id).ok()?; |
417 | // FIXME: correctly handle macro expansion | 426 | // FIXME: correctly handle macro expansion |
418 | if source.file_id != file_id { | 427 | if source.file_id != offset.file_id { |
419 | return None; | 428 | return None; |
420 | } | 429 | } |
421 | let root = source.file_syntax(db.upcast()); | 430 | let root = source.file_syntax(db.upcast()); |
@@ -423,7 +432,7 @@ fn adjust( | |||
423 | Some((node.syntax().text_range(), scope)) | 432 | Some((node.syntax().text_range(), scope)) |
424 | }) | 433 | }) |
425 | .filter(|&(range, _)| { | 434 | .filter(|&(range, _)| { |
426 | range.start() <= offset && expr_range.contains_range(range) && range != expr_range | 435 | range.start() <= offset.value && expr_range.contains_range(range) && range != expr_range |
427 | }); | 436 | }); |
428 | 437 | ||
429 | child_scopes | 438 | child_scopes |