aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--crates/ra_hir_def/src/data.rs149
-rw-r--r--crates/ra_hir_ty/src/tests/traits.rs40
2 files changed, 88 insertions, 101 deletions
diff --git a/crates/ra_hir_def/src/data.rs b/crates/ra_hir_def/src/data.rs
index 7a2067e49..0633eddee 100644
--- a/crates/ra_hir_def/src/data.rs
+++ b/crates/ra_hir_def/src/data.rs
@@ -150,51 +150,31 @@ pub struct TraitData {
150 150
151impl TraitData { 151impl TraitData {
152 pub(crate) fn trait_data_query(db: &dyn DefDatabase, tr: TraitId) -> Arc<TraitData> { 152 pub(crate) fn trait_data_query(db: &dyn DefDatabase, tr: TraitId) -> Arc<TraitData> {
153 let src = tr.lookup(db).source(db); 153 let tr_loc = tr.lookup(db);
154 let src = tr_loc.source(db);
154 let name = src.value.name().map_or_else(Name::missing, |n| n.as_name()); 155 let name = src.value.name().map_or_else(Name::missing, |n| n.as_name());
155 let auto = src.value.auto_token().is_some(); 156 let auto = src.value.auto_token().is_some();
156 let ast_id_map = db.ast_id_map(src.file_id); 157 let module_id = tr_loc.container.module(db);
157 158
158 let container = AssocContainerId::TraitId(tr); 159 let container = AssocContainerId::TraitId(tr);
159 let items = if let Some(item_list) = src.value.item_list() { 160 let mut items = Vec::new();
160 item_list 161
161 .impl_items() 162 if let Some(item_list) = src.value.item_list() {
162 .map(|item_node| match item_node { 163 let mut expander = Expander::new(db, tr_loc.ast_id.file_id, module_id);
163 ast::ImplItem::FnDef(it) => { 164 items.extend(collect_impl_items(
164 let name = it.name().map_or_else(Name::missing, |it| it.as_name()); 165 db,
165 let def = FunctionLoc { 166 &mut expander,
166 container, 167 item_list.impl_items(),
167 ast_id: AstId::new(src.file_id, ast_id_map.ast_id(&it)), 168 src.file_id,
168 } 169 container,
169 .intern(db) 170 ));
170 .into(); 171 items.extend(collect_impl_items_in_macros(
171 (name, def) 172 db,
172 } 173 &mut expander,
173 ast::ImplItem::ConstDef(it) => { 174 &src.with_value(item_list),
174 let name = it.name().map_or_else(Name::missing, |it| it.as_name()); 175 container,
175 let def = ConstLoc { 176 ));
176 container, 177 }
177 ast_id: AstId::new(src.file_id, ast_id_map.ast_id(&it)),
178 }
179 .intern(db)
180 .into();
181 (name, def)
182 }
183 ast::ImplItem::TypeAliasDef(it) => {
184 let name = it.name().map_or_else(Name::missing, |it| it.as_name());
185 let def = TypeAliasLoc {
186 container,
187 ast_id: AstId::new(src.file_id, ast_id_map.ast_id(&it)),
188 }
189 .intern(db)
190 .into();
191 (name, def)
192 }
193 })
194 .collect()
195 } else {
196 Vec::new()
197 };
198 Arc::new(TraitData { name, items, auto }) 178 Arc::new(TraitData { name, items, auto })
199 } 179 }
200 180
@@ -232,24 +212,33 @@ impl ImplData {
232 let target_type = TypeRef::from_ast_opt(&lower_ctx, src.value.target_type()); 212 let target_type = TypeRef::from_ast_opt(&lower_ctx, src.value.target_type());
233 let is_negative = src.value.excl_token().is_some(); 213 let is_negative = src.value.excl_token().is_some();
234 let module_id = impl_loc.container.module(db); 214 let module_id = impl_loc.container.module(db);
215 let container = AssocContainerId::ImplId(id);
235 216
236 let mut items = Vec::new(); 217 let mut items: Vec<AssocItemId> = Vec::new();
237 218
238 if let Some(item_list) = src.value.item_list() { 219 if let Some(item_list) = src.value.item_list() {
239 let mut expander = Expander::new(db, impl_loc.ast_id.file_id, module_id); 220 let mut expander = Expander::new(db, impl_loc.ast_id.file_id, module_id);
240 items.extend(collect_impl_items( 221 items.extend(
241 db, 222 collect_impl_items(
242 &mut expander, 223 db,
243 item_list.impl_items(), 224 &mut expander,
244 src.file_id, 225 item_list.impl_items(),
245 id, 226 src.file_id,
246 )); 227 container,
247 items.extend(collect_impl_items_in_macros( 228 )
248 db, 229 .into_iter()
249 &mut expander, 230 .map(|(_, item)| item),
250 &src.with_value(item_list), 231 );
251 id, 232 items.extend(
252 )); 233 collect_impl_items_in_macros(
234 db,
235 &mut expander,
236 &src.with_value(item_list),
237 container,
238 )
239 .into_iter()
240 .map(|(_, item)| item),
241 );
253 } 242 }
254 243
255 let res = ImplData { target_trait, target_type, items, is_negative }; 244 let res = ImplData { target_trait, target_type, items, is_negative };
@@ -296,15 +285,15 @@ fn collect_impl_items_in_macros(
296 db: &dyn DefDatabase, 285 db: &dyn DefDatabase,
297 expander: &mut Expander, 286 expander: &mut Expander,
298 impl_def: &InFile<ast::ItemList>, 287 impl_def: &InFile<ast::ItemList>,
299 id: ImplId, 288 container: AssocContainerId,
300) -> Vec<AssocItemId> { 289) -> Vec<(Name, AssocItemId)> {
301 let mut res = Vec::new(); 290 let mut res = Vec::new();
302 291
303 // We set a limit to protect against infinite recursion 292 // We set a limit to protect against infinite recursion
304 let limit = 100; 293 let limit = 100;
305 294
306 for m in impl_def.value.syntax().children().filter_map(ast::MacroCall::cast) { 295 for m in impl_def.value.syntax().children().filter_map(ast::MacroCall::cast) {
307 res.extend(collect_impl_items_in_macro(db, expander, m, id, limit)) 296 res.extend(collect_impl_items_in_macro(db, expander, m, container, limit))
308 } 297 }
309 298
310 res 299 res
@@ -314,9 +303,9 @@ fn collect_impl_items_in_macro(
314 db: &dyn DefDatabase, 303 db: &dyn DefDatabase,
315 expander: &mut Expander, 304 expander: &mut Expander,
316 m: ast::MacroCall, 305 m: ast::MacroCall,
317 id: ImplId, 306 container: AssocContainerId,
318 limit: usize, 307 limit: usize,
319) -> Vec<AssocItemId> { 308) -> Vec<(Name, AssocItemId)> {
320 if limit == 0 { 309 if limit == 0 {
321 return Vec::new(); 310 return Vec::new();
322 } 311 }
@@ -328,13 +317,14 @@ fn collect_impl_items_in_macro(
328 expander, 317 expander,
329 items.value.items().filter_map(|it| ImplItem::cast(it.syntax().clone())), 318 items.value.items().filter_map(|it| ImplItem::cast(it.syntax().clone())),
330 items.file_id, 319 items.file_id,
331 id, 320 container,
332 ); 321 );
322
333 // Recursive collect macros 323 // Recursive collect macros
334 // Note that ast::ModuleItem do not include ast::MacroCall 324 // Note that ast::ModuleItem do not include ast::MacroCall
335 // We cannot use ModuleItemOwner::items here 325 // We cannot use ModuleItemOwner::items here
336 for it in items.value.syntax().children().filter_map(ast::MacroCall::cast) { 326 for it in items.value.syntax().children().filter_map(ast::MacroCall::cast) {
337 res.extend(collect_impl_items_in_macro(db, expander, it, id, limit - 1)) 327 res.extend(collect_impl_items_in_macro(db, expander, it, container, limit - 1))
338 } 328 }
339 expander.exit(db, mark); 329 expander.exit(db, mark);
340 res 330 res
@@ -348,39 +338,34 @@ fn collect_impl_items(
348 expander: &mut Expander, 338 expander: &mut Expander,
349 impl_items: impl Iterator<Item = ImplItem>, 339 impl_items: impl Iterator<Item = ImplItem>,
350 file_id: crate::HirFileId, 340 file_id: crate::HirFileId,
351 id: ImplId, 341 container: AssocContainerId,
352) -> Vec<AssocItemId> { 342) -> Vec<(Name, AssocItemId)> {
353 let items = db.ast_id_map(file_id); 343 let items = db.ast_id_map(file_id);
354 344
355 impl_items 345 impl_items
356 .filter_map(|item_node| match item_node { 346 .filter_map(|item_node| match item_node {
357 ast::ImplItem::FnDef(it) => { 347 ast::ImplItem::FnDef(it) => {
348 let name = it.name().map_or_else(Name::missing, |it| it.as_name());
358 let attrs = expander.parse_attrs(&it); 349 let attrs = expander.parse_attrs(&it);
359 if !expander.is_cfg_enabled(&attrs) { 350 if !expander.is_cfg_enabled(&attrs) {
360 return None; 351 return None;
361 } 352 }
362 let def = FunctionLoc { 353 let def = FunctionLoc { container, ast_id: AstId::new(file_id, items.ast_id(&it)) }
363 container: AssocContainerId::ImplId(id), 354 .intern(db);
364 ast_id: AstId::new(file_id, items.ast_id(&it)), 355 Some((name, def.into()))
365 }
366 .intern(db);
367 Some(def.into())
368 } 356 }
369 ast::ImplItem::ConstDef(it) => { 357 ast::ImplItem::ConstDef(it) => {
370 let def = ConstLoc { 358 let name = it.name().map_or_else(Name::missing, |it| it.as_name());
371 container: AssocContainerId::ImplId(id), 359 let def = ConstLoc { container, ast_id: AstId::new(file_id, items.ast_id(&it)) }
372 ast_id: AstId::new(file_id, items.ast_id(&it)), 360 .intern(db);
373 } 361 Some((name, def.into()))
374 .intern(db);
375 Some(def.into())
376 } 362 }
377 ast::ImplItem::TypeAliasDef(it) => { 363 ast::ImplItem::TypeAliasDef(it) => {
378 let def = TypeAliasLoc { 364 let name = it.name().map_or_else(Name::missing, |it| it.as_name());
379 container: AssocContainerId::ImplId(id), 365 let def =
380 ast_id: AstId::new(file_id, items.ast_id(&it)), 366 TypeAliasLoc { container, ast_id: AstId::new(file_id, items.ast_id(&it)) }
381 } 367 .intern(db);
382 .intern(db); 368 Some((name, def.into()))
383 Some(def.into())
384 } 369 }
385 }) 370 })
386 .collect() 371 .collect()
diff --git a/crates/ra_hir_ty/src/tests/traits.rs b/crates/ra_hir_ty/src/tests/traits.rs
index e555c879a..23f682eff 100644
--- a/crates/ra_hir_ty/src/tests/traits.rs
+++ b/crates/ra_hir_ty/src/tests/traits.rs
@@ -2055,7 +2055,7 @@ fn test<I: Iterator<Item: Iterator<Item = u32>>>() {
2055#[test] 2055#[test]
2056fn proc_macro_server_types() { 2056fn proc_macro_server_types() {
2057 assert_snapshot!( 2057 assert_snapshot!(
2058 infer_with_mismatches(r#" 2058 infer(r#"
2059macro_rules! with_api { 2059macro_rules! with_api {
2060 ($S:ident, $self:ident, $m:ident) => { 2060 ($S:ident, $self:ident, $m:ident) => {
2061 $m! { 2061 $m! {
@@ -2069,9 +2069,9 @@ macro_rules! with_api {
2069} 2069}
2070macro_rules! associated_item { 2070macro_rules! associated_item {
2071 (type TokenStream) => 2071 (type TokenStream) =>
2072 (type TokenStream: 'static + Clone;); 2072 (type TokenStream: 'static;);
2073 (type Group) => 2073 (type Group) =>
2074 (type Group: 'static + Clone;); 2074 (type Group: 'static;);
2075 ($($item:tt)*) => ($($item)*;) 2075 ($($item:tt)*) => ($($item)*;)
2076} 2076}
2077macro_rules! declare_server_traits { 2077macro_rules! declare_server_traits {
@@ -2083,39 +2083,41 @@ macro_rules! declare_server_traits {
2083 } 2083 }
2084 2084
2085 $(pub trait $name: Types { 2085 $(pub trait $name: Types {
2086 $(associated_item!(fn $method(&mut self, $($arg: $arg_ty),*) $(-> $ret_ty)?);)* 2086 $(associated_item!(fn $method($($arg: $arg_ty),*) $(-> $ret_ty)?);)*
2087 })* 2087 })*
2088 2088
2089 pub trait Server: Types $(+ $name)* {} 2089 pub trait Server: Types $(+ $name)* {}
2090 impl<S: Types $(+ $name)*> Server for S {} 2090 impl<S: Types $(+ $name)*> Server for S {}
2091 } 2091 }
2092} 2092}
2093
2093with_api!(Self, self_, declare_server_traits); 2094with_api!(Self, self_, declare_server_traits);
2094struct Group {} 2095struct G {}
2095struct TokenStream {} 2096struct T {}
2096struct Rustc; 2097struct Rustc;
2097impl Types for Rustc { 2098impl Types for Rustc {
2098 type TokenStream = TokenStream; 2099 type TokenStream = T;
2099 type Group = Group; 2100 type Group = G;
2100} 2101}
2102
2101fn make<T>() -> T { loop {} } 2103fn make<T>() -> T { loop {} }
2102impl TokenStream for Rustc { 2104impl TokenStream for Rustc {
2103 fn new() -> Self::TokenStream { 2105 fn new() -> Self::TokenStream {
2104 let group: Self::Group = make(); 2106 let group: Self::Group = make();
2105 make() 2107 make()
2106 } 2108 }
2107} 2109}
2108"#, true), 2110"#),
2109 @r###" 2111 @r###"
2110 1115..1126 '{ loop {} }': T 2112 1062..1073 '{ loop {} }': T
2111 1117..1124 'loop {}': ! 2113 1064..1071 'loop {}': !
2112 1122..1124 '{}': () 2114 1069..1071 '{}': ()
2113 1190..1253 '{ ... }': {unknown} 2115 1137..1200 '{ ... }': T
2114 1204..1209 'group': {unknown} 2116 1151..1156 'group': G
2115 1225..1229 'make': fn make<{unknown}>() -> {unknown} 2117 1172..1176 'make': fn make<G>() -> G
2116 1225..1231 'make()': {unknown} 2118 1172..1178 'make()': G
2117 1241..1245 'make': fn make<{unknown}>() -> {unknown} 2119 1188..1192 'make': fn make<T>() -> T
2118 1241..1247 'make()': {unknown} 2120 1188..1194 'make()': T
2119 "### 2121 "###
2120 ); 2122 );
2121} 2123}