diff options
author | bors[bot] <26634292+bors[bot]@users.noreply.github.com> | 2020-07-16 17:50:37 +0100 |
---|---|---|
committer | GitHub <[email protected]> | 2020-07-16 17:50:37 +0100 |
commit | 081596dd584ac39fbfa6a7e47dfe9dd4a58c362a (patch) | |
tree | b6d564a63068530ef3aabb8855699bf20c45a608 /crates/ra_hir/src/code_model.rs | |
parent | 9210fcc076808e53e9bde84be26307fc0dc7d688 (diff) | |
parent | e1e79cf0648624e7a3787d0013c0c7e86210772f (diff) |
Merge #5413
5413: Semantical call info r=matklad a=matklad
Co-authored-by: Aleksey Kladov <[email protected]>
Diffstat (limited to 'crates/ra_hir/src/code_model.rs')
-rw-r--r-- | crates/ra_hir/src/code_model.rs | 86 |
1 files changed, 79 insertions, 7 deletions
diff --git a/crates/ra_hir/src/code_model.rs b/crates/ra_hir/src/code_model.rs index 9891b0785..eb6a14eda 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,8 +26,8 @@ use hir_expand::{ | |||
25 | use hir_ty::{ | 26 | use hir_ty::{ |
26 | autoderef, | 27 | autoderef, |
27 | display::{HirDisplayError, HirFormatter}, | 28 | display::{HirDisplayError, HirFormatter}, |
28 | method_resolution, ApplicationTy, Canonical, GenericPredicate, InEnvironment, Substs, | 29 | method_resolution, ApplicationTy, CallableDefId, Canonical, FnSig, GenericPredicate, |
29 | TraitEnvironment, Ty, TyDefId, TypeCtor, | 30 | InEnvironment, Substs, TraitEnvironment, Ty, TyDefId, TypeCtor, |
30 | }; | 31 | }; |
31 | use ra_db::{CrateId, Edition, FileId}; | 32 | use ra_db::{CrateId, Edition, FileId}; |
32 | use ra_prof::profile; | 33 | use ra_prof::profile; |
@@ -40,7 +41,7 @@ use stdx::impl_from; | |||
40 | use crate::{ | 41 | use crate::{ |
41 | db::{DefDatabase, HirDatabase}, | 42 | db::{DefDatabase, HirDatabase}, |
42 | has_source::HasSource, | 43 | has_source::HasSource, |
43 | CallableDefId, HirDisplay, InFile, Name, | 44 | HirDisplay, InFile, Name, |
44 | }; | 45 | }; |
45 | 46 | ||
46 | /// 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 |
@@ -1168,6 +1169,12 @@ impl Type { | |||
1168 | Type::new(db, krate, def, ty) | 1169 | Type::new(db, krate, def, ty) |
1169 | } | 1170 | } |
1170 | 1171 | ||
1172 | pub fn is_unit(&self) -> bool { | ||
1173 | matches!( | ||
1174 | self.ty.value, | ||
1175 | Ty::Apply(ApplicationTy { ctor: TypeCtor::Tuple { cardinality: 0 }, .. }) | ||
1176 | ) | ||
1177 | } | ||
1171 | pub fn is_bool(&self) -> bool { | 1178 | pub fn is_bool(&self) -> bool { |
1172 | matches!(self.ty.value, Ty::Apply(ApplicationTy { ctor: TypeCtor::Bool, .. })) | 1179 | matches!(self.ty.value, Ty::Apply(ApplicationTy { ctor: TypeCtor::Bool, .. })) |
1173 | } | 1180 | } |
@@ -1225,9 +1232,10 @@ impl Type { | |||
1225 | db.trait_solve(self.krate, goal).is_some() | 1232 | db.trait_solve(self.krate, goal).is_some() |
1226 | } | 1233 | } |
1227 | 1234 | ||
1228 | // FIXME: this method is broken, as it doesn't take closures into account. | 1235 | pub fn as_callable(&self, db: &dyn HirDatabase) -> Option<Callable> { |
1229 | pub fn as_callable(&self) -> Option<CallableDefId> { | 1236 | let (id, substs) = self.ty.value.as_callable()?; |
1230 | Some(self.ty.value.as_callable()?.0) | 1237 | let sig = db.callable_item_signature(id).subst(substs); |
1238 | Some(Callable { ty: self.clone(), sig, id, is_bound_method: false }) | ||
1231 | } | 1239 | } |
1232 | 1240 | ||
1233 | pub fn is_closure(&self) -> bool { | 1241 | pub fn is_closure(&self) -> bool { |
@@ -1512,6 +1520,70 @@ impl HirDisplay for Type { | |||
1512 | } | 1520 | } |
1513 | } | 1521 | } |
1514 | 1522 | ||
1523 | // FIXME: closures | ||
1524 | #[derive(Debug)] | ||
1525 | pub struct Callable { | ||
1526 | ty: Type, | ||
1527 | sig: FnSig, | ||
1528 | id: CallableDefId, | ||
1529 | pub(crate) is_bound_method: bool, | ||
1530 | } | ||
1531 | |||
1532 | pub enum CallableKind { | ||
1533 | Function(Function), | ||
1534 | TupleStruct(Struct), | ||
1535 | TupleEnumVariant(EnumVariant), | ||
1536 | } | ||
1537 | |||
1538 | impl Callable { | ||
1539 | pub fn kind(&self) -> CallableKind { | ||
1540 | match self.id { | ||
1541 | CallableDefId::FunctionId(it) => CallableKind::Function(it.into()), | ||
1542 | CallableDefId::StructId(it) => CallableKind::TupleStruct(it.into()), | ||
1543 | CallableDefId::EnumVariantId(it) => CallableKind::TupleEnumVariant(it.into()), | ||
1544 | } | ||
1545 | } | ||
1546 | pub fn receiver_param(&self, db: &dyn HirDatabase) -> Option<ast::SelfParam> { | ||
1547 | let func = match self.id { | ||
1548 | CallableDefId::FunctionId(it) if self.is_bound_method => it, | ||
1549 | _ => return None, | ||
1550 | }; | ||
1551 | let src = func.lookup(db.upcast()).source(db.upcast()); | ||
1552 | let param_list = src.value.param_list()?; | ||
1553 | param_list.self_param() | ||
1554 | } | ||
1555 | pub fn params( | ||
1556 | &self, | ||
1557 | db: &dyn HirDatabase, | ||
1558 | ) -> Vec<(Option<Either<ast::SelfParam, ast::Pat>>, Type)> { | ||
1559 | let types = self | ||
1560 | .sig | ||
1561 | .params() | ||
1562 | .iter() | ||
1563 | .skip(if self.is_bound_method { 1 } else { 0 }) | ||
1564 | .map(|ty| self.ty.derived(ty.clone())); | ||
1565 | let patterns = match self.id { | ||
1566 | CallableDefId::FunctionId(func) => { | ||
1567 | let src = func.lookup(db.upcast()).source(db.upcast()); | ||
1568 | src.value.param_list().map(|param_list| { | ||
1569 | param_list | ||
1570 | .self_param() | ||
1571 | .map(|it| Some(Either::Left(it))) | ||
1572 | .filter(|_| !self.is_bound_method) | ||
1573 | .into_iter() | ||
1574 | .chain(param_list.params().map(|it| it.pat().map(Either::Right))) | ||
1575 | }) | ||
1576 | } | ||
1577 | CallableDefId::StructId(_) => None, | ||
1578 | CallableDefId::EnumVariantId(_) => None, | ||
1579 | }; | ||
1580 | patterns.into_iter().flatten().chain(iter::repeat(None)).zip(types).collect() | ||
1581 | } | ||
1582 | pub fn return_type(&self) -> Type { | ||
1583 | self.ty.derived(self.sig.ret().clone()) | ||
1584 | } | ||
1585 | } | ||
1586 | |||
1515 | /// For IDE only | 1587 | /// For IDE only |
1516 | #[derive(Debug)] | 1588 | #[derive(Debug)] |
1517 | pub enum ScopeDef { | 1589 | pub enum ScopeDef { |