diff options
author | bors[bot] <26634292+bors[bot]@users.noreply.github.com> | 2019-11-22 14:43:32 +0000 |
---|---|---|
committer | GitHub <[email protected]> | 2019-11-22 14:43:32 +0000 |
commit | b841c53a0c93cdca3f08b1c917c9fa8a63d31604 (patch) | |
tree | 2b1d06598328b9d1922e83c791f181b5789eb789 /crates/ra_hir_def/src/data.rs | |
parent | a132cc715ed05cab83fd058156eb152f0be96982 (diff) | |
parent | 64df759418a83fd05fab850b8351fcddbdd3ef63 (diff) |
Merge #2356
2356: Move FunctionData to hir_def r=matklad a=matklad
Co-authored-by: Aleksey Kladov <[email protected]>
Diffstat (limited to 'crates/ra_hir_def/src/data.rs')
-rw-r--r-- | crates/ra_hir_def/src/data.rs | 192 |
1 files changed, 192 insertions, 0 deletions
diff --git a/crates/ra_hir_def/src/data.rs b/crates/ra_hir_def/src/data.rs new file mode 100644 index 000000000..ba47629db --- /dev/null +++ b/crates/ra_hir_def/src/data.rs | |||
@@ -0,0 +1,192 @@ | |||
1 | //! Contains basic data about various HIR declarations. | ||
2 | |||
3 | use std::sync::Arc; | ||
4 | |||
5 | use hir_expand::{ | ||
6 | name::{self, AsName, Name}, | ||
7 | AstId, | ||
8 | }; | ||
9 | use ra_syntax::ast::{self, NameOwner, TypeAscriptionOwner}; | ||
10 | |||
11 | use crate::{ | ||
12 | db::DefDatabase2, | ||
13 | type_ref::{Mutability, TypeRef}, | ||
14 | AssocItemId, AstItemDef, ConstLoc, ContainerId, FunctionId, FunctionLoc, HasSource, ImplId, | ||
15 | Intern, Lookup, TraitId, TypeAliasId, TypeAliasLoc, | ||
16 | }; | ||
17 | |||
18 | #[derive(Debug, Clone, PartialEq, Eq)] | ||
19 | pub struct FunctionData { | ||
20 | pub name: Name, | ||
21 | pub params: Vec<TypeRef>, | ||
22 | pub ret_type: TypeRef, | ||
23 | /// True if the first param is `self`. This is relevant to decide whether this | ||
24 | /// can be called as a method. | ||
25 | pub has_self_param: bool, | ||
26 | } | ||
27 | |||
28 | impl FunctionData { | ||
29 | pub(crate) fn fn_data_query(db: &impl DefDatabase2, func: FunctionId) -> Arc<FunctionData> { | ||
30 | let src = func.lookup(db).source(db); | ||
31 | let name = src.value.name().map(|n| n.as_name()).unwrap_or_else(Name::missing); | ||
32 | let mut params = Vec::new(); | ||
33 | let mut has_self_param = false; | ||
34 | if let Some(param_list) = src.value.param_list() { | ||
35 | if let Some(self_param) = param_list.self_param() { | ||
36 | let self_type = if let Some(type_ref) = self_param.ascribed_type() { | ||
37 | TypeRef::from_ast(type_ref) | ||
38 | } else { | ||
39 | let self_type = TypeRef::Path(name::SELF_TYPE.into()); | ||
40 | match self_param.kind() { | ||
41 | ast::SelfParamKind::Owned => self_type, | ||
42 | ast::SelfParamKind::Ref => { | ||
43 | TypeRef::Reference(Box::new(self_type), Mutability::Shared) | ||
44 | } | ||
45 | ast::SelfParamKind::MutRef => { | ||
46 | TypeRef::Reference(Box::new(self_type), Mutability::Mut) | ||
47 | } | ||
48 | } | ||
49 | }; | ||
50 | params.push(self_type); | ||
51 | has_self_param = true; | ||
52 | } | ||
53 | for param in param_list.params() { | ||
54 | let type_ref = TypeRef::from_ast_opt(param.ascribed_type()); | ||
55 | params.push(type_ref); | ||
56 | } | ||
57 | } | ||
58 | let ret_type = if let Some(type_ref) = src.value.ret_type().and_then(|rt| rt.type_ref()) { | ||
59 | TypeRef::from_ast(type_ref) | ||
60 | } else { | ||
61 | TypeRef::unit() | ||
62 | }; | ||
63 | |||
64 | let sig = FunctionData { name, params, ret_type, has_self_param }; | ||
65 | Arc::new(sig) | ||
66 | } | ||
67 | } | ||
68 | |||
69 | #[derive(Debug, Clone, PartialEq, Eq)] | ||
70 | pub struct TypeAliasData { | ||
71 | pub name: Name, | ||
72 | pub type_ref: Option<TypeRef>, | ||
73 | } | ||
74 | |||
75 | impl TypeAliasData { | ||
76 | pub(crate) fn type_alias_data_query( | ||
77 | db: &impl DefDatabase2, | ||
78 | typ: TypeAliasId, | ||
79 | ) -> Arc<TypeAliasData> { | ||
80 | let node = typ.lookup(db).source(db).value; | ||
81 | let name = node.name().map_or_else(Name::missing, |n| n.as_name()); | ||
82 | let type_ref = node.type_ref().map(TypeRef::from_ast); | ||
83 | Arc::new(TypeAliasData { name, type_ref }) | ||
84 | } | ||
85 | } | ||
86 | |||
87 | #[derive(Debug, Clone, PartialEq, Eq)] | ||
88 | pub struct TraitData { | ||
89 | pub name: Option<Name>, | ||
90 | pub items: Vec<AssocItemId>, | ||
91 | pub auto: bool, | ||
92 | } | ||
93 | |||
94 | impl TraitData { | ||
95 | pub(crate) fn trait_data_query(db: &impl DefDatabase2, tr: TraitId) -> Arc<TraitData> { | ||
96 | let src = tr.source(db); | ||
97 | let name = src.value.name().map(|n| n.as_name()); | ||
98 | let auto = src.value.is_auto(); | ||
99 | let ast_id_map = db.ast_id_map(src.file_id); | ||
100 | let items = if let Some(item_list) = src.value.item_list() { | ||
101 | item_list | ||
102 | .impl_items() | ||
103 | .map(|item_node| match item_node { | ||
104 | ast::ImplItem::FnDef(it) => FunctionLoc { | ||
105 | container: ContainerId::TraitId(tr), | ||
106 | ast_id: AstId::new(src.file_id, ast_id_map.ast_id(&it)), | ||
107 | } | ||
108 | .intern(db) | ||
109 | .into(), | ||
110 | ast::ImplItem::ConstDef(it) => ConstLoc { | ||
111 | container: ContainerId::TraitId(tr), | ||
112 | ast_id: AstId::new(src.file_id, ast_id_map.ast_id(&it)), | ||
113 | } | ||
114 | .intern(db) | ||
115 | .into(), | ||
116 | ast::ImplItem::TypeAliasDef(it) => TypeAliasLoc { | ||
117 | container: ContainerId::TraitId(tr), | ||
118 | ast_id: AstId::new(src.file_id, ast_id_map.ast_id(&it)), | ||
119 | } | ||
120 | .intern(db) | ||
121 | .into(), | ||
122 | }) | ||
123 | .collect() | ||
124 | } else { | ||
125 | Vec::new() | ||
126 | }; | ||
127 | Arc::new(TraitData { name, items, auto }) | ||
128 | } | ||
129 | |||
130 | pub fn associated_types(&self) -> impl Iterator<Item = TypeAliasId> + '_ { | ||
131 | self.items.iter().filter_map(|item| match item { | ||
132 | AssocItemId::TypeAliasId(t) => Some(*t), | ||
133 | _ => None, | ||
134 | }) | ||
135 | } | ||
136 | } | ||
137 | |||
138 | #[derive(Debug, Clone, PartialEq, Eq)] | ||
139 | pub struct ImplData { | ||
140 | pub target_trait: Option<TypeRef>, | ||
141 | pub target_type: TypeRef, | ||
142 | pub items: Vec<AssocItemId>, | ||
143 | pub is_negative: bool, | ||
144 | } | ||
145 | |||
146 | impl ImplData { | ||
147 | pub(crate) fn impl_data_query(db: &impl DefDatabase2, id: ImplId) -> Arc<ImplData> { | ||
148 | let src = id.source(db); | ||
149 | let items = db.ast_id_map(src.file_id); | ||
150 | |||
151 | let target_trait = src.value.target_trait().map(TypeRef::from_ast); | ||
152 | let target_type = TypeRef::from_ast_opt(src.value.target_type()); | ||
153 | let is_negative = src.value.is_negative(); | ||
154 | |||
155 | let items = if let Some(item_list) = src.value.item_list() { | ||
156 | item_list | ||
157 | .impl_items() | ||
158 | .map(|item_node| match item_node { | ||
159 | ast::ImplItem::FnDef(it) => { | ||
160 | let def = FunctionLoc { | ||
161 | container: ContainerId::ImplId(id), | ||
162 | ast_id: AstId::new(src.file_id, items.ast_id(&it)), | ||
163 | } | ||
164 | .intern(db); | ||
165 | def.into() | ||
166 | } | ||
167 | ast::ImplItem::ConstDef(it) => { | ||
168 | let def = ConstLoc { | ||
169 | container: ContainerId::ImplId(id), | ||
170 | ast_id: AstId::new(src.file_id, items.ast_id(&it)), | ||
171 | } | ||
172 | .intern(db); | ||
173 | def.into() | ||
174 | } | ||
175 | ast::ImplItem::TypeAliasDef(it) => { | ||
176 | let def = TypeAliasLoc { | ||
177 | container: ContainerId::ImplId(id), | ||
178 | ast_id: AstId::new(src.file_id, items.ast_id(&it)), | ||
179 | } | ||
180 | .intern(db); | ||
181 | def.into() | ||
182 | } | ||
183 | }) | ||
184 | .collect() | ||
185 | } else { | ||
186 | Vec::new() | ||
187 | }; | ||
188 | |||
189 | let res = ImplData { target_trait, target_type, items, is_negative }; | ||
190 | Arc::new(res) | ||
191 | } | ||
192 | } | ||