1 //! Contains basic data about various HIR declarations.
6 name::{name, AsName, Name},
9 use ra_syntax::ast::{self, NameOwner, TypeAscriptionOwner};
14 type_ref::{Mutability, TypeRef},
15 AssocContainerId, AssocItemId, ConstId, ConstLoc, FunctionId, FunctionLoc, ImplId, Intern,
16 Lookup, StaticId, TraitId, TypeAliasId, TypeAliasLoc,
19 #[derive(Debug, Clone, PartialEq, Eq)]
20 pub struct FunctionData {
22 pub params: Vec<TypeRef>,
23 pub ret_type: TypeRef,
24 /// True if the first param is `self`. This is relevant to decide whether this
25 /// can be called as a method.
26 pub has_self_param: bool,
30 pub(crate) fn fn_data_query(db: &impl DefDatabase, func: FunctionId) -> Arc<FunctionData> {
31 let src = func.lookup(db).source(db);
32 let name = src.value.name().map(|n| n.as_name()).unwrap_or_else(Name::missing);
33 let mut params = Vec::new();
34 let mut has_self_param = false;
35 if let Some(param_list) = src.value.param_list() {
36 if let Some(self_param) = param_list.self_param() {
37 let self_type = if let Some(type_ref) = self_param.ascribed_type() {
38 TypeRef::from_ast(type_ref)
40 let self_type = TypeRef::Path(name![Self].into());
41 match self_param.kind() {
42 ast::SelfParamKind::Owned => self_type,
43 ast::SelfParamKind::Ref => {
44 TypeRef::Reference(Box::new(self_type), Mutability::Shared)
46 ast::SelfParamKind::MutRef => {
47 TypeRef::Reference(Box::new(self_type), Mutability::Mut)
51 params.push(self_type);
52 has_self_param = true;
54 for param in param_list.params() {
55 let type_ref = TypeRef::from_ast_opt(param.ascribed_type());
56 params.push(type_ref);
59 let ret_type = if let Some(type_ref) = src.value.ret_type().and_then(|rt| rt.type_ref()) {
60 TypeRef::from_ast(type_ref)
65 let sig = FunctionData { name, params, ret_type, has_self_param };
70 #[derive(Debug, Clone, PartialEq, Eq)]
71 pub struct TypeAliasData {
73 pub type_ref: Option<TypeRef>,
77 pub(crate) fn type_alias_data_query(
78 db: &impl DefDatabase,
80 ) -> Arc<TypeAliasData> {
81 let node = typ.lookup(db).source(db).value;
82 let name = node.name().map_or_else(Name::missing, |n| n.as_name());
83 let type_ref = node.type_ref().map(TypeRef::from_ast);
84 Arc::new(TypeAliasData { name, type_ref })
88 #[derive(Debug, Clone, PartialEq, Eq)]
89 pub struct TraitData {
91 pub items: Vec<(Name, AssocItemId)>,
96 pub(crate) fn trait_data_query(db: &impl DefDatabase, tr: TraitId) -> Arc<TraitData> {
97 let src = tr.lookup(db).source(db);
98 let name = src.value.name().map_or_else(Name::missing, |n| n.as_name());
99 let auto = src.value.is_auto();
100 let ast_id_map = db.ast_id_map(src.file_id);
102 let container = AssocContainerId::TraitId(tr);
103 let items = if let Some(item_list) = src.value.item_list() {
106 .map(|item_node| match item_node {
107 ast::ImplItem::FnDef(it) => {
108 let name = it.name().map_or_else(Name::missing, |it| it.as_name());
109 let def = FunctionLoc {
111 ast_id: AstId::new(src.file_id, ast_id_map.ast_id(&it)),
117 ast::ImplItem::ConstDef(it) => {
118 let name = it.name().map_or_else(Name::missing, |it| it.as_name());
121 ast_id: AstId::new(src.file_id, ast_id_map.ast_id(&it)),
127 ast::ImplItem::TypeAliasDef(it) => {
128 let name = it.name().map_or_else(Name::missing, |it| it.as_name());
129 let def = TypeAliasLoc {
131 ast_id: AstId::new(src.file_id, ast_id_map.ast_id(&it)),
142 Arc::new(TraitData { name, items, auto })
145 pub fn associated_types(&self) -> impl Iterator<Item = TypeAliasId> + '_ {
146 self.items.iter().filter_map(|(_name, item)| match item {
147 AssocItemId::TypeAliasId(t) => Some(*t),
152 pub fn associated_type_by_name(&self, name: &Name) -> Option<TypeAliasId> {
153 self.items.iter().find_map(|(item_name, item)| match item {
154 AssocItemId::TypeAliasId(t) if item_name == name => Some(*t),
160 #[derive(Debug, Clone, PartialEq, Eq)]
161 pub struct ImplData {
162 pub target_trait: Option<TypeRef>,
163 pub target_type: TypeRef,
164 pub items: Vec<AssocItemId>,
165 pub is_negative: bool,
169 pub(crate) fn impl_data_query(db: &impl DefDatabase, id: ImplId) -> Arc<ImplData> {
170 let src = id.lookup(db).source(db);
171 let items = db.ast_id_map(src.file_id);
173 let target_trait = src.value.target_trait().map(TypeRef::from_ast);
174 let target_type = TypeRef::from_ast_opt(src.value.target_type());
175 let is_negative = src.value.is_negative();
177 let items = if let Some(item_list) = src.value.item_list() {
180 .map(|item_node| match item_node {
181 ast::ImplItem::FnDef(it) => {
182 let def = FunctionLoc {
183 container: AssocContainerId::ImplId(id),
184 ast_id: AstId::new(src.file_id, items.ast_id(&it)),
189 ast::ImplItem::ConstDef(it) => {
191 container: AssocContainerId::ImplId(id),
192 ast_id: AstId::new(src.file_id, items.ast_id(&it)),
197 ast::ImplItem::TypeAliasDef(it) => {
198 let def = TypeAliasLoc {
199 container: AssocContainerId::ImplId(id),
200 ast_id: AstId::new(src.file_id, items.ast_id(&it)),
211 let res = ImplData { target_trait, target_type, items, is_negative };
216 #[derive(Debug, Clone, PartialEq, Eq)]
217 pub struct ConstData {
218 /// const _: () = ();
219 pub name: Option<Name>,
220 pub type_ref: TypeRef,
224 pub(crate) fn const_data_query(db: &impl DefDatabase, konst: ConstId) -> Arc<ConstData> {
225 let node = konst.lookup(db).source(db).value;
226 Arc::new(ConstData::new(&node))
229 pub(crate) fn static_data_query(db: &impl DefDatabase, konst: StaticId) -> Arc<ConstData> {
230 let node = konst.lookup(db).source(db).value;
231 Arc::new(ConstData::new(&node))
234 fn new<N: NameOwner + TypeAscriptionOwner>(node: &N) -> ConstData {
235 let name = node.name().map(|n| n.as_name());
236 let type_ref = TypeRef::from_ast_opt(node.ascribed_type());
237 ConstData { name, type_ref }