Merge #2356
2356: Move FunctionData to hir_def r=matklad a=matklad Co-authored-by: Aleksey Kladov <aleksey.kladov@gmail.com>
This commit is contained in:
commit
b841c53a0c
18 changed files with 252 additions and 309 deletions
|
|
@ -10,10 +10,10 @@ use hir_def::{
|
|||
adt::VariantData,
|
||||
body::scope::ExprScopes,
|
||||
builtin_type::BuiltinType,
|
||||
data::TraitData,
|
||||
nameres::per_ns::PerNs,
|
||||
resolver::{HasResolver, TypeNs},
|
||||
traits::TraitData,
|
||||
type_ref::{Mutability, TypeRef},
|
||||
type_ref::TypeRef,
|
||||
ContainerId, CrateModuleId, HasModule, ImplId, LocalEnumVariantId, LocalStructFieldId, Lookup,
|
||||
ModuleId, UnionId,
|
||||
};
|
||||
|
|
@ -561,77 +561,6 @@ pub struct Function {
|
|||
pub(crate) id: FunctionId,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
pub struct FnData {
|
||||
pub(crate) name: Name,
|
||||
pub(crate) params: Vec<TypeRef>,
|
||||
pub(crate) ret_type: TypeRef,
|
||||
/// True if the first param is `self`. This is relevant to decide whether this
|
||||
/// can be called as a method.
|
||||
pub(crate) has_self_param: bool,
|
||||
}
|
||||
|
||||
impl FnData {
|
||||
pub(crate) fn fn_data_query(
|
||||
db: &(impl DefDatabase + AstDatabase),
|
||||
func: Function,
|
||||
) -> Arc<FnData> {
|
||||
let src = func.source(db);
|
||||
let name = src.value.name().map(|n| n.as_name()).unwrap_or_else(Name::missing);
|
||||
let mut params = Vec::new();
|
||||
let mut has_self_param = false;
|
||||
if let Some(param_list) = src.value.param_list() {
|
||||
if let Some(self_param) = param_list.self_param() {
|
||||
let self_type = if let Some(type_ref) = self_param.ascribed_type() {
|
||||
TypeRef::from_ast(type_ref)
|
||||
} else {
|
||||
let self_type = TypeRef::Path(name::SELF_TYPE.into());
|
||||
match self_param.kind() {
|
||||
ast::SelfParamKind::Owned => self_type,
|
||||
ast::SelfParamKind::Ref => {
|
||||
TypeRef::Reference(Box::new(self_type), Mutability::Shared)
|
||||
}
|
||||
ast::SelfParamKind::MutRef => {
|
||||
TypeRef::Reference(Box::new(self_type), Mutability::Mut)
|
||||
}
|
||||
}
|
||||
};
|
||||
params.push(self_type);
|
||||
has_self_param = true;
|
||||
}
|
||||
for param in param_list.params() {
|
||||
let type_ref = TypeRef::from_ast_opt(param.ascribed_type());
|
||||
params.push(type_ref);
|
||||
}
|
||||
}
|
||||
let ret_type = if let Some(type_ref) = src.value.ret_type().and_then(|rt| rt.type_ref()) {
|
||||
TypeRef::from_ast(type_ref)
|
||||
} else {
|
||||
TypeRef::unit()
|
||||
};
|
||||
|
||||
let sig = FnData { name, params, ret_type, has_self_param };
|
||||
Arc::new(sig)
|
||||
}
|
||||
pub fn name(&self) -> &Name {
|
||||
&self.name
|
||||
}
|
||||
|
||||
pub fn params(&self) -> &[TypeRef] {
|
||||
&self.params
|
||||
}
|
||||
|
||||
pub fn ret_type(&self) -> &TypeRef {
|
||||
&self.ret_type
|
||||
}
|
||||
|
||||
/// True if the first arg is `self`. This is relevant to decide whether this
|
||||
/// can be called as a method.
|
||||
pub fn has_self_param(&self) -> bool {
|
||||
self.has_self_param
|
||||
}
|
||||
}
|
||||
|
||||
impl Function {
|
||||
pub fn module(self, db: &impl DefDatabase) -> Module {
|
||||
self.id.lookup(db).module(db).into()
|
||||
|
|
@ -642,7 +571,15 @@ impl Function {
|
|||
}
|
||||
|
||||
pub fn name(self, db: &impl HirDatabase) -> Name {
|
||||
self.data(db).name.clone()
|
||||
db.function_data(self.id).name.clone()
|
||||
}
|
||||
|
||||
pub fn has_self_param(self, db: &impl HirDatabase) -> bool {
|
||||
db.function_data(self.id).has_self_param
|
||||
}
|
||||
|
||||
pub fn params(self, db: &impl HirDatabase) -> Vec<TypeRef> {
|
||||
db.function_data(self.id).params.clone()
|
||||
}
|
||||
|
||||
pub(crate) fn body_source_map(self, db: &impl HirDatabase) -> Arc<BodySourceMap> {
|
||||
|
|
@ -657,10 +594,6 @@ impl Function {
|
|||
db.type_for_def(self.into(), Namespace::Values)
|
||||
}
|
||||
|
||||
pub fn data(self, db: &impl HirDatabase) -> Arc<FnData> {
|
||||
db.fn_data(self)
|
||||
}
|
||||
|
||||
pub fn infer(self, db: &impl HirDatabase) -> Arc<InferenceResult> {
|
||||
db.infer(self.into())
|
||||
}
|
||||
|
|
|
|||
|
|
@ -16,15 +16,15 @@ use crate::{
|
|||
CallableDef, FnSig, GenericPredicate, InferenceResult, Namespace, Substs, Ty, TypableDef,
|
||||
TypeCtor,
|
||||
},
|
||||
Const, ConstData, Crate, DefWithBody, FnData, Function, GenericDef, ImplBlock, Module, Static,
|
||||
StructField, Trait,
|
||||
Const, ConstData, Crate, DefWithBody, GenericDef, ImplBlock, Module, Static, StructField,
|
||||
Trait,
|
||||
};
|
||||
|
||||
pub use hir_def::db::{
|
||||
BodyQuery, BodyWithSourceMapQuery, CrateDefMapQuery, DefDatabase2, DefDatabase2Storage,
|
||||
EnumDataQuery, ExprScopesQuery, GenericParamsQuery, ImplDataQuery, InternDatabase,
|
||||
InternDatabaseStorage, RawItemsQuery, RawItemsWithSourceMapQuery, StructDataQuery,
|
||||
TraitDataQuery, TypeAliasDataQuery,
|
||||
EnumDataQuery, ExprScopesQuery, FunctionDataQuery, GenericParamsQuery, ImplDataQuery,
|
||||
InternDatabase, InternDatabaseStorage, RawItemsQuery, RawItemsWithSourceMapQuery,
|
||||
StructDataQuery, TraitDataQuery, TypeAliasDataQuery,
|
||||
};
|
||||
pub use hir_expand::db::{
|
||||
AstDatabase, AstDatabaseStorage, AstIdMapQuery, MacroArgQuery, MacroDefQuery, MacroExpandQuery,
|
||||
|
|
@ -35,9 +35,6 @@ pub use hir_expand::db::{
|
|||
#[salsa::query_group(DefDatabaseStorage)]
|
||||
#[salsa::requires(AstDatabase)]
|
||||
pub trait DefDatabase: HirDebugDatabase + DefDatabase2 {
|
||||
#[salsa::invoke(FnData::fn_data_query)]
|
||||
fn fn_data(&self, func: Function) -> Arc<FnData>;
|
||||
|
||||
#[salsa::invoke(ConstData::const_data_query)]
|
||||
fn const_data(&self, konst: Const) -> Arc<ConstData>;
|
||||
|
||||
|
|
|
|||
|
|
@ -18,11 +18,11 @@ impl HasSource for ImplBlock {
|
|||
|
||||
impl ImplBlock {
|
||||
pub fn target_trait(&self, db: &impl DefDatabase) -> Option<TypeRef> {
|
||||
db.impl_data(self.id).target_trait().cloned()
|
||||
db.impl_data(self.id).target_trait.clone()
|
||||
}
|
||||
|
||||
pub fn target_type(&self, db: &impl DefDatabase) -> TypeRef {
|
||||
db.impl_data(self.id).target_type().clone()
|
||||
db.impl_data(self.id).target_type.clone()
|
||||
}
|
||||
|
||||
pub fn target_ty(&self, db: &impl HirDatabase) -> Ty {
|
||||
|
|
@ -35,11 +35,11 @@ impl ImplBlock {
|
|||
}
|
||||
|
||||
pub fn items(&self, db: &impl DefDatabase) -> Vec<AssocItem> {
|
||||
db.impl_data(self.id).items().iter().map(|it| (*it).into()).collect()
|
||||
db.impl_data(self.id).items.iter().map(|it| (*it).into()).collect()
|
||||
}
|
||||
|
||||
pub fn is_negative(&self, db: &impl DefDatabase) -> bool {
|
||||
db.impl_data(self.id).is_negative()
|
||||
db.impl_data(self.id).is_negative
|
||||
}
|
||||
|
||||
pub fn module(&self, db: &impl DefDatabase) -> Module {
|
||||
|
|
|
|||
|
|
@ -55,9 +55,9 @@ pub use crate::{
|
|||
docs::{DocDef, Docs, Documentation},
|
||||
src::{HasBodySource, HasSource},
|
||||
Adt, AssocItem, Const, ConstData, Container, Crate, CrateDependency, DefWithBody, Enum,
|
||||
EnumVariant, FieldSource, FnData, Function, GenericDef, GenericParam, HasBody, ImplBlock,
|
||||
Local, MacroDef, Module, ModuleDef, ModuleSource, ScopeDef, Static, Struct, StructField,
|
||||
Trait, TypeAlias, Union, VariantDef,
|
||||
EnumVariant, FieldSource, Function, GenericDef, GenericParam, HasBody, ImplBlock, Local,
|
||||
MacroDef, Module, ModuleDef, ModuleSource, ScopeDef, Static, Struct, StructField, Trait,
|
||||
TypeAlias, Union, VariantDef,
|
||||
},
|
||||
expr::ExprScopes,
|
||||
from_source::FromSource,
|
||||
|
|
|
|||
|
|
@ -22,6 +22,7 @@ use ena::unify::{InPlaceUnificationTable, NoError, UnifyKey, UnifyValue};
|
|||
use rustc_hash::FxHashMap;
|
||||
|
||||
use hir_def::{
|
||||
data::FunctionData,
|
||||
path::known,
|
||||
resolver::{HasResolver, Resolver, TypeNs},
|
||||
type_ref::{Mutability, TypeRef},
|
||||
|
|
@ -43,8 +44,8 @@ use crate::{
|
|||
db::HirDatabase,
|
||||
expr::{BindingAnnotation, Body, ExprId, PatId},
|
||||
ty::infer::diagnostics::InferenceDiagnostic,
|
||||
Adt, AssocItem, ConstData, DefWithBody, FloatTy, FnData, Function, HasBody, IntTy, Path,
|
||||
StructField, Trait, VariantDef,
|
||||
Adt, AssocItem, ConstData, DefWithBody, FloatTy, Function, HasBody, IntTy, Path, StructField,
|
||||
Trait, VariantDef,
|
||||
};
|
||||
|
||||
macro_rules! ty_app {
|
||||
|
|
@ -70,7 +71,7 @@ pub fn infer_query(db: &impl HirDatabase, def: DefWithBody) -> Arc<InferenceResu
|
|||
|
||||
match def {
|
||||
DefWithBody::Const(ref c) => ctx.collect_const(&c.data(db)),
|
||||
DefWithBody::Function(ref f) => ctx.collect_fn(&f.data(db)),
|
||||
DefWithBody::Function(ref f) => ctx.collect_fn(&db.function_data(f.id)),
|
||||
DefWithBody::Static(ref s) => ctx.collect_const(&s.data(db)),
|
||||
}
|
||||
|
||||
|
|
@ -562,14 +563,14 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
|
|||
self.return_ty = self.make_ty(data.type_ref());
|
||||
}
|
||||
|
||||
fn collect_fn(&mut self, data: &FnData) {
|
||||
fn collect_fn(&mut self, data: &FunctionData) {
|
||||
let body = Arc::clone(&self.body); // avoid borrow checker problem
|
||||
for (type_ref, pat) in data.params().iter().zip(body.params()) {
|
||||
for (type_ref, pat) in data.params.iter().zip(body.params()) {
|
||||
let ty = self.make_ty(type_ref);
|
||||
|
||||
self.infer_pat(*pat, &ty, BindingMode::default());
|
||||
}
|
||||
self.return_ty = self.make_ty(data.ret_type());
|
||||
self.return_ty = self.make_ty(&data.ret_type);
|
||||
}
|
||||
|
||||
fn infer_body(&mut self) {
|
||||
|
|
|
|||
|
|
@ -622,10 +622,10 @@ pub(crate) fn generic_defaults_query(db: &impl HirDatabase, def: GenericDef) ->
|
|||
}
|
||||
|
||||
fn fn_sig_for_fn(db: &impl HirDatabase, def: Function) -> FnSig {
|
||||
let data = def.data(db);
|
||||
let data = db.function_data(def.id);
|
||||
let resolver = def.id.resolver(db);
|
||||
let params = data.params().iter().map(|tr| Ty::from_hir(db, &resolver, tr)).collect::<Vec<_>>();
|
||||
let ret = Ty::from_hir(db, &resolver, data.ret_type());
|
||||
let params = data.params.iter().map(|tr| Ty::from_hir(db, &resolver, tr)).collect::<Vec<_>>();
|
||||
let ret = Ty::from_hir(db, &resolver, &data.ret_type);
|
||||
FnSig::from_params_and_return(params, ret)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -291,9 +291,9 @@ fn is_valid_candidate(
|
|||
) -> bool {
|
||||
match item {
|
||||
AssocItem::Function(m) => {
|
||||
let data = m.data(db);
|
||||
name.map_or(true, |name| data.name() == name)
|
||||
&& (data.has_self_param() || mode == LookupMode::Path)
|
||||
let data = db.function_data(m.id);
|
||||
name.map_or(true, |name| data.name == *name)
|
||||
&& (data.has_self_param || mode == LookupMode::Path)
|
||||
}
|
||||
AssocItem::Const(c) => {
|
||||
name.map_or(true, |name| Some(name) == c.name(db).as_ref())
|
||||
|
|
|
|||
192
crates/ra_hir_def/src/data.rs
Normal file
192
crates/ra_hir_def/src/data.rs
Normal file
|
|
@ -0,0 +1,192 @@
|
|||
//! Contains basic data about various HIR declarations.
|
||||
|
||||
use std::sync::Arc;
|
||||
|
||||
use hir_expand::{
|
||||
name::{self, AsName, Name},
|
||||
AstId,
|
||||
};
|
||||
use ra_syntax::ast::{self, NameOwner, TypeAscriptionOwner};
|
||||
|
||||
use crate::{
|
||||
db::DefDatabase2,
|
||||
type_ref::{Mutability, TypeRef},
|
||||
AssocItemId, AstItemDef, ConstLoc, ContainerId, FunctionId, FunctionLoc, HasSource, ImplId,
|
||||
Intern, Lookup, TraitId, TypeAliasId, TypeAliasLoc,
|
||||
};
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
pub struct FunctionData {
|
||||
pub name: Name,
|
||||
pub params: Vec<TypeRef>,
|
||||
pub ret_type: TypeRef,
|
||||
/// True if the first param is `self`. This is relevant to decide whether this
|
||||
/// can be called as a method.
|
||||
pub has_self_param: bool,
|
||||
}
|
||||
|
||||
impl FunctionData {
|
||||
pub(crate) fn fn_data_query(db: &impl DefDatabase2, func: FunctionId) -> Arc<FunctionData> {
|
||||
let src = func.lookup(db).source(db);
|
||||
let name = src.value.name().map(|n| n.as_name()).unwrap_or_else(Name::missing);
|
||||
let mut params = Vec::new();
|
||||
let mut has_self_param = false;
|
||||
if let Some(param_list) = src.value.param_list() {
|
||||
if let Some(self_param) = param_list.self_param() {
|
||||
let self_type = if let Some(type_ref) = self_param.ascribed_type() {
|
||||
TypeRef::from_ast(type_ref)
|
||||
} else {
|
||||
let self_type = TypeRef::Path(name::SELF_TYPE.into());
|
||||
match self_param.kind() {
|
||||
ast::SelfParamKind::Owned => self_type,
|
||||
ast::SelfParamKind::Ref => {
|
||||
TypeRef::Reference(Box::new(self_type), Mutability::Shared)
|
||||
}
|
||||
ast::SelfParamKind::MutRef => {
|
||||
TypeRef::Reference(Box::new(self_type), Mutability::Mut)
|
||||
}
|
||||
}
|
||||
};
|
||||
params.push(self_type);
|
||||
has_self_param = true;
|
||||
}
|
||||
for param in param_list.params() {
|
||||
let type_ref = TypeRef::from_ast_opt(param.ascribed_type());
|
||||
params.push(type_ref);
|
||||
}
|
||||
}
|
||||
let ret_type = if let Some(type_ref) = src.value.ret_type().and_then(|rt| rt.type_ref()) {
|
||||
TypeRef::from_ast(type_ref)
|
||||
} else {
|
||||
TypeRef::unit()
|
||||
};
|
||||
|
||||
let sig = FunctionData { name, params, ret_type, has_self_param };
|
||||
Arc::new(sig)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
pub struct TypeAliasData {
|
||||
pub name: Name,
|
||||
pub type_ref: Option<TypeRef>,
|
||||
}
|
||||
|
||||
impl TypeAliasData {
|
||||
pub(crate) fn type_alias_data_query(
|
||||
db: &impl DefDatabase2,
|
||||
typ: TypeAliasId,
|
||||
) -> Arc<TypeAliasData> {
|
||||
let node = typ.lookup(db).source(db).value;
|
||||
let name = node.name().map_or_else(Name::missing, |n| n.as_name());
|
||||
let type_ref = node.type_ref().map(TypeRef::from_ast);
|
||||
Arc::new(TypeAliasData { name, type_ref })
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
pub struct TraitData {
|
||||
pub name: Option<Name>,
|
||||
pub items: Vec<AssocItemId>,
|
||||
pub auto: bool,
|
||||
}
|
||||
|
||||
impl TraitData {
|
||||
pub(crate) fn trait_data_query(db: &impl DefDatabase2, tr: TraitId) -> Arc<TraitData> {
|
||||
let src = tr.source(db);
|
||||
let name = src.value.name().map(|n| n.as_name());
|
||||
let auto = src.value.is_auto();
|
||||
let ast_id_map = db.ast_id_map(src.file_id);
|
||||
let items = if let Some(item_list) = src.value.item_list() {
|
||||
item_list
|
||||
.impl_items()
|
||||
.map(|item_node| match item_node {
|
||||
ast::ImplItem::FnDef(it) => FunctionLoc {
|
||||
container: ContainerId::TraitId(tr),
|
||||
ast_id: AstId::new(src.file_id, ast_id_map.ast_id(&it)),
|
||||
}
|
||||
.intern(db)
|
||||
.into(),
|
||||
ast::ImplItem::ConstDef(it) => ConstLoc {
|
||||
container: ContainerId::TraitId(tr),
|
||||
ast_id: AstId::new(src.file_id, ast_id_map.ast_id(&it)),
|
||||
}
|
||||
.intern(db)
|
||||
.into(),
|
||||
ast::ImplItem::TypeAliasDef(it) => TypeAliasLoc {
|
||||
container: ContainerId::TraitId(tr),
|
||||
ast_id: AstId::new(src.file_id, ast_id_map.ast_id(&it)),
|
||||
}
|
||||
.intern(db)
|
||||
.into(),
|
||||
})
|
||||
.collect()
|
||||
} else {
|
||||
Vec::new()
|
||||
};
|
||||
Arc::new(TraitData { name, items, auto })
|
||||
}
|
||||
|
||||
pub fn associated_types(&self) -> impl Iterator<Item = TypeAliasId> + '_ {
|
||||
self.items.iter().filter_map(|item| match item {
|
||||
AssocItemId::TypeAliasId(t) => Some(*t),
|
||||
_ => None,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
pub struct ImplData {
|
||||
pub target_trait: Option<TypeRef>,
|
||||
pub target_type: TypeRef,
|
||||
pub items: Vec<AssocItemId>,
|
||||
pub is_negative: bool,
|
||||
}
|
||||
|
||||
impl ImplData {
|
||||
pub(crate) fn impl_data_query(db: &impl DefDatabase2, id: ImplId) -> Arc<ImplData> {
|
||||
let src = id.source(db);
|
||||
let items = db.ast_id_map(src.file_id);
|
||||
|
||||
let target_trait = src.value.target_trait().map(TypeRef::from_ast);
|
||||
let target_type = TypeRef::from_ast_opt(src.value.target_type());
|
||||
let is_negative = src.value.is_negative();
|
||||
|
||||
let items = if let Some(item_list) = src.value.item_list() {
|
||||
item_list
|
||||
.impl_items()
|
||||
.map(|item_node| match item_node {
|
||||
ast::ImplItem::FnDef(it) => {
|
||||
let def = FunctionLoc {
|
||||
container: ContainerId::ImplId(id),
|
||||
ast_id: AstId::new(src.file_id, items.ast_id(&it)),
|
||||
}
|
||||
.intern(db);
|
||||
def.into()
|
||||
}
|
||||
ast::ImplItem::ConstDef(it) => {
|
||||
let def = ConstLoc {
|
||||
container: ContainerId::ImplId(id),
|
||||
ast_id: AstId::new(src.file_id, items.ast_id(&it)),
|
||||
}
|
||||
.intern(db);
|
||||
def.into()
|
||||
}
|
||||
ast::ImplItem::TypeAliasDef(it) => {
|
||||
let def = TypeAliasLoc {
|
||||
container: ContainerId::ImplId(id),
|
||||
ast_id: AstId::new(src.file_id, items.ast_id(&it)),
|
||||
}
|
||||
.intern(db);
|
||||
def.into()
|
||||
}
|
||||
})
|
||||
.collect()
|
||||
} else {
|
||||
Vec::new()
|
||||
};
|
||||
|
||||
let res = ImplData { target_trait, target_type, items, is_negative };
|
||||
Arc::new(res)
|
||||
}
|
||||
}
|
||||
|
|
@ -8,15 +8,14 @@ use ra_syntax::ast;
|
|||
use crate::{
|
||||
adt::{EnumData, StructData},
|
||||
body::{scope::ExprScopes, Body, BodySourceMap},
|
||||
data::{FunctionData, ImplData, TraitData, TypeAliasData},
|
||||
generics::GenericParams,
|
||||
impls::ImplData,
|
||||
nameres::{
|
||||
raw::{ImportSourceMap, RawItems},
|
||||
CrateDefMap,
|
||||
},
|
||||
traits::TraitData,
|
||||
type_alias::TypeAliasData,
|
||||
DefWithBodyId, EnumId, GenericDefId, ImplId, ItemLoc, StructOrUnionId, TraitId, TypeAliasId,
|
||||
DefWithBodyId, EnumId, FunctionId, GenericDefId, ImplId, ItemLoc, StructOrUnionId, TraitId,
|
||||
TypeAliasId,
|
||||
};
|
||||
|
||||
#[salsa::query_group(InternDatabaseStorage)]
|
||||
|
|
@ -68,6 +67,9 @@ pub trait DefDatabase2: InternDatabase + AstDatabase {
|
|||
#[salsa::invoke(TypeAliasData::type_alias_data_query)]
|
||||
fn type_alias_data(&self, e: TypeAliasId) -> Arc<TypeAliasData>;
|
||||
|
||||
#[salsa::invoke(FunctionData::fn_data_query)]
|
||||
fn function_data(&self, func: FunctionId) -> Arc<FunctionData>;
|
||||
|
||||
#[salsa::invoke(Body::body_with_source_map_query)]
|
||||
fn body_with_source_map(&self, def: DefWithBodyId) -> (Arc<Body>, Arc<BodySourceMap>);
|
||||
|
||||
|
|
|
|||
|
|
@ -1,86 +0,0 @@
|
|||
//! Defines hir-level representation of impls.
|
||||
//!
|
||||
//! The handling is similar, but is not quite the same as for other items,
|
||||
//! because `impl`s don't have names.
|
||||
|
||||
use std::sync::Arc;
|
||||
|
||||
use hir_expand::AstId;
|
||||
use ra_syntax::ast;
|
||||
|
||||
use crate::{
|
||||
db::DefDatabase2, type_ref::TypeRef, AssocItemId, AstItemDef, ConstLoc, ContainerId,
|
||||
FunctionLoc, ImplId, Intern, TypeAliasLoc,
|
||||
};
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
pub struct ImplData {
|
||||
target_trait: Option<TypeRef>,
|
||||
target_type: TypeRef,
|
||||
items: Vec<AssocItemId>,
|
||||
negative: bool,
|
||||
}
|
||||
|
||||
impl ImplData {
|
||||
pub(crate) fn impl_data_query(db: &impl DefDatabase2, id: ImplId) -> Arc<ImplData> {
|
||||
let src = id.source(db);
|
||||
let items = db.ast_id_map(src.file_id);
|
||||
|
||||
let target_trait = src.value.target_trait().map(TypeRef::from_ast);
|
||||
let target_type = TypeRef::from_ast_opt(src.value.target_type());
|
||||
let negative = src.value.is_negative();
|
||||
|
||||
let items = if let Some(item_list) = src.value.item_list() {
|
||||
item_list
|
||||
.impl_items()
|
||||
.map(|item_node| match item_node {
|
||||
ast::ImplItem::FnDef(it) => {
|
||||
let def = FunctionLoc {
|
||||
container: ContainerId::ImplId(id),
|
||||
ast_id: AstId::new(src.file_id, items.ast_id(&it)),
|
||||
}
|
||||
.intern(db);
|
||||
def.into()
|
||||
}
|
||||
ast::ImplItem::ConstDef(it) => {
|
||||
let def = ConstLoc {
|
||||
container: ContainerId::ImplId(id),
|
||||
ast_id: AstId::new(src.file_id, items.ast_id(&it)),
|
||||
}
|
||||
.intern(db);
|
||||
def.into()
|
||||
}
|
||||
ast::ImplItem::TypeAliasDef(it) => {
|
||||
let def = TypeAliasLoc {
|
||||
container: ContainerId::ImplId(id),
|
||||
ast_id: AstId::new(src.file_id, items.ast_id(&it)),
|
||||
}
|
||||
.intern(db);
|
||||
def.into()
|
||||
}
|
||||
})
|
||||
.collect()
|
||||
} else {
|
||||
Vec::new()
|
||||
};
|
||||
|
||||
let res = ImplData { target_trait, target_type, items, negative };
|
||||
Arc::new(res)
|
||||
}
|
||||
|
||||
pub fn target_trait(&self) -> Option<&TypeRef> {
|
||||
self.target_trait.as_ref()
|
||||
}
|
||||
|
||||
pub fn target_type(&self) -> &TypeRef {
|
||||
&self.target_type
|
||||
}
|
||||
|
||||
pub fn items(&self) -> &[AssocItemId] {
|
||||
&self.items
|
||||
}
|
||||
|
||||
pub fn is_negative(&self) -> bool {
|
||||
self.negative
|
||||
}
|
||||
}
|
||||
|
|
@ -13,14 +13,12 @@ pub mod path;
|
|||
pub mod type_ref;
|
||||
pub mod builtin_type;
|
||||
pub mod adt;
|
||||
pub mod impls;
|
||||
pub mod diagnostics;
|
||||
pub mod expr;
|
||||
pub mod body;
|
||||
pub mod generics;
|
||||
pub mod traits;
|
||||
pub mod resolver;
|
||||
pub mod type_alias;
|
||||
pub mod data;
|
||||
|
||||
#[cfg(test)]
|
||||
mod test_db;
|
||||
|
|
|
|||
|
|
@ -1,66 +0,0 @@
|
|||
//! HIR for trait definitions.
|
||||
|
||||
use std::sync::Arc;
|
||||
|
||||
use hir_expand::{
|
||||
name::{AsName, Name},
|
||||
AstId,
|
||||
};
|
||||
|
||||
use ra_syntax::ast::{self, NameOwner};
|
||||
|
||||
use crate::{
|
||||
db::DefDatabase2, AssocItemId, AstItemDef, ConstLoc, ContainerId, FunctionLoc, Intern, TraitId,
|
||||
TypeAliasId, TypeAliasLoc,
|
||||
};
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
pub struct TraitData {
|
||||
pub name: Option<Name>,
|
||||
pub items: Vec<AssocItemId>,
|
||||
pub auto: bool,
|
||||
}
|
||||
|
||||
impl TraitData {
|
||||
pub(crate) fn trait_data_query(db: &impl DefDatabase2, tr: TraitId) -> Arc<TraitData> {
|
||||
let src = tr.source(db);
|
||||
let name = src.value.name().map(|n| n.as_name());
|
||||
let auto = src.value.is_auto();
|
||||
let ast_id_map = db.ast_id_map(src.file_id);
|
||||
let items = if let Some(item_list) = src.value.item_list() {
|
||||
item_list
|
||||
.impl_items()
|
||||
.map(|item_node| match item_node {
|
||||
ast::ImplItem::FnDef(it) => FunctionLoc {
|
||||
container: ContainerId::TraitId(tr),
|
||||
ast_id: AstId::new(src.file_id, ast_id_map.ast_id(&it)),
|
||||
}
|
||||
.intern(db)
|
||||
.into(),
|
||||
ast::ImplItem::ConstDef(it) => ConstLoc {
|
||||
container: ContainerId::TraitId(tr),
|
||||
ast_id: AstId::new(src.file_id, ast_id_map.ast_id(&it)),
|
||||
}
|
||||
.intern(db)
|
||||
.into(),
|
||||
ast::ImplItem::TypeAliasDef(it) => TypeAliasLoc {
|
||||
container: ContainerId::TraitId(tr),
|
||||
ast_id: AstId::new(src.file_id, ast_id_map.ast_id(&it)),
|
||||
}
|
||||
.intern(db)
|
||||
.into(),
|
||||
})
|
||||
.collect()
|
||||
} else {
|
||||
Vec::new()
|
||||
};
|
||||
Arc::new(TraitData { name, items, auto })
|
||||
}
|
||||
|
||||
pub fn associated_types(&self) -> impl Iterator<Item = TypeAliasId> + '_ {
|
||||
self.items.iter().filter_map(|item| match item {
|
||||
AssocItemId::TypeAliasId(t) => Some(*t),
|
||||
_ => None,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
@ -1,27 +0,0 @@
|
|||
//! HIR for type aliases (i.e. the `type` keyword).
|
||||
|
||||
use std::sync::Arc;
|
||||
|
||||
use hir_expand::name::{AsName, Name};
|
||||
|
||||
use ra_syntax::ast::NameOwner;
|
||||
|
||||
use crate::{db::DefDatabase2, type_ref::TypeRef, HasSource, Lookup, TypeAliasId};
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
pub struct TypeAliasData {
|
||||
pub name: Name,
|
||||
pub type_ref: Option<TypeRef>,
|
||||
}
|
||||
|
||||
impl TypeAliasData {
|
||||
pub(crate) fn type_alias_data_query(
|
||||
db: &impl DefDatabase2,
|
||||
typ: TypeAliasId,
|
||||
) -> Arc<TypeAliasData> {
|
||||
let node = typ.lookup(db).source(db).value;
|
||||
let name = node.name().map_or_else(Name::missing, |n| n.as_name());
|
||||
let type_ref = node.type_ref().map(TypeRef::from_ast);
|
||||
Arc::new(TypeAliasData { name, type_ref })
|
||||
}
|
||||
}
|
||||
|
|
@ -30,7 +30,7 @@ pub(crate) fn call_info(db: &RootDatabase, position: FilePosition) -> Option<Cal
|
|||
let (callable_def, _subst) = analyzer.type_of(db, &expr.expr()?)?.as_callable()?;
|
||||
match callable_def {
|
||||
hir::CallableDef::Function(it) => {
|
||||
(CallInfo::with_fn(db, it), it.data(db).has_self_param())
|
||||
(CallInfo::with_fn(db, it), it.has_self_param(db))
|
||||
}
|
||||
hir::CallableDef::Struct(it) => (CallInfo::with_struct(db, it)?, false),
|
||||
hir::CallableDef::EnumVariant(it) => (CallInfo::with_enum_variant(db, it)?, false),
|
||||
|
|
@ -38,7 +38,7 @@ pub(crate) fn call_info(db: &RootDatabase, position: FilePosition) -> Option<Cal
|
|||
}
|
||||
FnCallNode::MethodCallExpr(expr) => {
|
||||
let function = analyzer.resolve_method_call(&expr)?;
|
||||
(CallInfo::with_fn(db, function), function.data(db).has_self_param())
|
||||
(CallInfo::with_fn(db, function), function.has_self_param(db))
|
||||
}
|
||||
FnCallNode::MacroCallExpr(expr) => {
|
||||
let macro_def = analyzer.resolve_macro_call(db, &expr)?;
|
||||
|
|
|
|||
|
|
@ -313,7 +313,7 @@ impl RootDatabase {
|
|||
hir::db::RawItemsQuery
|
||||
hir::db::CrateDefMapQuery
|
||||
hir::db::GenericParamsQuery
|
||||
hir::db::FnDataQuery
|
||||
hir::db::FunctionDataQuery
|
||||
hir::db::TypeAliasDataQuery
|
||||
hir::db::ConstDataQuery
|
||||
hir::db::StaticDataQuery
|
||||
|
|
|
|||
|
|
@ -59,8 +59,7 @@ fn complete_fields(acc: &mut Completions, ctx: &CompletionContext, receiver: Ty)
|
|||
fn complete_methods(acc: &mut Completions, ctx: &CompletionContext, receiver: Ty) {
|
||||
let mut seen_methods = FxHashSet::default();
|
||||
ctx.analyzer.iterate_method_candidates(ctx.db, receiver, None, |_ty, func| {
|
||||
let data = func.data(ctx.db);
|
||||
if data.has_self_param() && seen_methods.insert(data.name().clone()) {
|
||||
if func.has_self_param(ctx.db) && seen_methods.insert(func.name(ctx.db)) {
|
||||
acc.add_function(ctx, func);
|
||||
}
|
||||
None::<()>
|
||||
|
|
|
|||
|
|
@ -53,8 +53,7 @@ pub(super) fn complete_path(acc: &mut Completions, ctx: &CompletionContext) {
|
|||
ctx.analyzer.iterate_path_candidates(ctx.db, ty.clone(), None, |_ty, item| {
|
||||
match item {
|
||||
hir::AssocItem::Function(func) => {
|
||||
let data = func.data(ctx.db);
|
||||
if !data.has_self_param() {
|
||||
if !func.has_self_param(ctx.db) {
|
||||
acc.add_function(ctx, func);
|
||||
}
|
||||
}
|
||||
|
|
@ -80,8 +79,7 @@ pub(super) fn complete_path(acc: &mut Completions, ctx: &CompletionContext) {
|
|||
for item in t.items(ctx.db) {
|
||||
match item {
|
||||
hir::AssocItem::Function(func) => {
|
||||
let data = func.data(ctx.db);
|
||||
if !data.has_self_param() {
|
||||
if !func.has_self_param(ctx.db) {
|
||||
acc.add_function(ctx, func);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -199,14 +199,17 @@ impl Completions {
|
|||
name: Option<String>,
|
||||
func: hir::Function,
|
||||
) {
|
||||
let data = func.data(ctx.db);
|
||||
let name = name.unwrap_or_else(|| data.name().to_string());
|
||||
let func_name = func.name(ctx.db);
|
||||
let has_self_param = func.has_self_param(ctx.db);
|
||||
let params = func.params(ctx.db);
|
||||
|
||||
let name = name.unwrap_or_else(|| func_name.to_string());
|
||||
let ast_node = func.source(ctx.db).value;
|
||||
let detail = function_label(&ast_node);
|
||||
|
||||
let mut builder =
|
||||
CompletionItem::new(CompletionKind::Reference, ctx.source_range(), name.clone())
|
||||
.kind(if data.has_self_param() {
|
||||
.kind(if has_self_param {
|
||||
CompletionItemKind::Method
|
||||
} else {
|
||||
CompletionItemKind::Function
|
||||
|
|
@ -221,12 +224,11 @@ impl Completions {
|
|||
&& ctx.db.feature_flags.get("completion.insertion.add-call-parenthesis")
|
||||
{
|
||||
tested_by!(inserts_parens_for_function_calls);
|
||||
let (snippet, label) =
|
||||
if data.params().is_empty() || data.has_self_param() && data.params().len() == 1 {
|
||||
(format!("{}()$0", data.name()), format!("{}()", name))
|
||||
} else {
|
||||
(format!("{}($0)", data.name()), format!("{}(…)", name))
|
||||
};
|
||||
let (snippet, label) = if params.is_empty() || has_self_param && params.len() == 1 {
|
||||
(format!("{}()$0", func_name), format!("{}()", name))
|
||||
} else {
|
||||
(format!("{}($0)", func_name), format!("{}(…)", name))
|
||||
};
|
||||
builder = builder.lookup_by(name).label(label).insert_snippet(snippet);
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue