diff options
Diffstat (limited to 'crates/hir_def/src')
-rw-r--r-- | crates/hir_def/src/attr.rs | 56 | ||||
-rw-r--r-- | crates/hir_def/src/body/lower.rs | 2 | ||||
-rw-r--r-- | crates/hir_def/src/body/scope.rs | 30 | ||||
-rw-r--r-- | crates/hir_def/src/db.rs | 11 | ||||
-rw-r--r-- | crates/hir_def/src/diagnostics.rs | 4 | ||||
-rw-r--r-- | crates/hir_def/src/find_path.rs | 48 | ||||
-rw-r--r-- | crates/hir_def/src/import_map.rs | 287 | ||||
-rw-r--r-- | crates/hir_def/src/item_scope.rs | 3 | ||||
-rw-r--r-- | crates/hir_def/src/nameres/collector.rs | 33 | ||||
-rw-r--r-- | crates/hir_def/src/nameres/tests/incremental.rs | 4 | ||||
-rw-r--r-- | crates/hir_def/src/path.rs | 1 |
11 files changed, 311 insertions, 168 deletions
diff --git a/crates/hir_def/src/attr.rs b/crates/hir_def/src/attr.rs index 6b79e7bad..9e6426b31 100644 --- a/crates/hir_def/src/attr.rs +++ b/crates/hir_def/src/attr.rs | |||
@@ -2,6 +2,7 @@ | |||
2 | 2 | ||
3 | use std::{ops, sync::Arc}; | 3 | use std::{ops, sync::Arc}; |
4 | 4 | ||
5 | use arena::map::ArenaMap; | ||
5 | use base_db::CrateId; | 6 | use base_db::CrateId; |
6 | use cfg::{CfgExpr, CfgOptions}; | 7 | use cfg::{CfgExpr, CfgOptions}; |
7 | use either::Either; | 8 | use either::Either; |
@@ -21,7 +22,8 @@ use crate::{ | |||
21 | nameres::ModuleSource, | 22 | nameres::ModuleSource, |
22 | path::{ModPath, PathKind}, | 23 | path::{ModPath, PathKind}, |
23 | src::HasChildSource, | 24 | src::HasChildSource, |
24 | AdtId, AttrDefId, GenericParamId, Lookup, | 25 | AdtId, AttrDefId, EnumId, GenericParamId, HasModule, LocalEnumVariantId, LocalFieldId, Lookup, |
26 | VariantId, | ||
25 | }; | 27 | }; |
26 | 28 | ||
27 | /// Holds documentation | 29 | /// Holds documentation |
@@ -210,16 +212,10 @@ impl Attrs { | |||
210 | } | 212 | } |
211 | } | 213 | } |
212 | AttrDefId::FieldId(it) => { | 214 | AttrDefId::FieldId(it) => { |
213 | let src = it.parent.child_source(db); | 215 | return db.fields_attrs(it.parent)[it.local_id].clone(); |
214 | match &src.value[it.local_id] { | ||
215 | Either::Left(_tuple) => RawAttrs::default(), | ||
216 | Either::Right(record) => RawAttrs::from_attrs_owner(db, src.with_value(record)), | ||
217 | } | ||
218 | } | 216 | } |
219 | AttrDefId::EnumVariantId(var_id) => { | 217 | AttrDefId::EnumVariantId(it) => { |
220 | let src = var_id.parent.child_source(db); | 218 | return db.variants_attrs(it.parent)[it.local_id].clone(); |
221 | let src = src.as_ref().map(|it| &it[var_id.local_id]); | ||
222 | RawAttrs::from_attrs_owner(db, src.map(|it| it as &dyn AttrsOwner)) | ||
223 | } | 219 | } |
224 | AttrDefId::AdtId(it) => match it { | 220 | AttrDefId::AdtId(it) => match it { |
225 | AdtId::StructId(it) => attrs_from_item_tree(it.lookup(db).id, db), | 221 | AdtId::StructId(it) => attrs_from_item_tree(it.lookup(db).id, db), |
@@ -259,6 +255,46 @@ impl Attrs { | |||
259 | raw_attrs.filter(db, def.krate(db)) | 255 | raw_attrs.filter(db, def.krate(db)) |
260 | } | 256 | } |
261 | 257 | ||
258 | pub(crate) fn variants_attrs_query( | ||
259 | db: &dyn DefDatabase, | ||
260 | e: EnumId, | ||
261 | ) -> Arc<ArenaMap<LocalEnumVariantId, Attrs>> { | ||
262 | let krate = e.lookup(db).container.module(db).krate; | ||
263 | let src = e.child_source(db); | ||
264 | let mut res = ArenaMap::default(); | ||
265 | |||
266 | for (id, var) in src.value.iter() { | ||
267 | let attrs = RawAttrs::from_attrs_owner(db, src.with_value(var as &dyn AttrsOwner)) | ||
268 | .filter(db, krate); | ||
269 | |||
270 | res.insert(id, attrs) | ||
271 | } | ||
272 | |||
273 | Arc::new(res) | ||
274 | } | ||
275 | |||
276 | pub(crate) fn fields_attrs_query( | ||
277 | db: &dyn DefDatabase, | ||
278 | v: VariantId, | ||
279 | ) -> Arc<ArenaMap<LocalFieldId, Attrs>> { | ||
280 | let krate = v.module(db).krate; | ||
281 | let src = v.child_source(db); | ||
282 | let mut res = ArenaMap::default(); | ||
283 | |||
284 | for (id, fld) in src.value.iter() { | ||
285 | let attrs = match fld { | ||
286 | Either::Left(_tuple) => Attrs::default(), | ||
287 | Either::Right(record) => { | ||
288 | RawAttrs::from_attrs_owner(db, src.with_value(record)).filter(db, krate) | ||
289 | } | ||
290 | }; | ||
291 | |||
292 | res.insert(id, attrs); | ||
293 | } | ||
294 | |||
295 | Arc::new(res) | ||
296 | } | ||
297 | |||
262 | pub fn by_key(&self, key: &'static str) -> AttrQuery<'_> { | 298 | pub fn by_key(&self, key: &'static str) -> AttrQuery<'_> { |
263 | AttrQuery { attrs: self, key } | 299 | AttrQuery { attrs: self, key } |
264 | } | 300 | } |
diff --git a/crates/hir_def/src/body/lower.rs b/crates/hir_def/src/body/lower.rs index 17c72779b..6be1eaade 100644 --- a/crates/hir_def/src/body/lower.rs +++ b/crates/hir_def/src/body/lower.rs | |||
@@ -695,7 +695,7 @@ impl ExprCollector<'_> { | |||
695 | self.collect_stmts_items(block.statements()); | 695 | self.collect_stmts_items(block.statements()); |
696 | let statements = | 696 | let statements = |
697 | block.statements().filter_map(|s| self.collect_stmt(s)).flatten().collect(); | 697 | block.statements().filter_map(|s| self.collect_stmt(s)).flatten().collect(); |
698 | let tail = block.expr().map(|e| self.collect_expr(e)); | 698 | let tail = block.tail_expr().map(|e| self.collect_expr(e)); |
699 | self.alloc_expr(Expr::Block { statements, tail, label: None }, syntax_node_ptr) | 699 | self.alloc_expr(Expr::Block { statements, tail, label: None }, syntax_node_ptr) |
700 | } | 700 | } |
701 | 701 | ||
diff --git a/crates/hir_def/src/body/scope.rs b/crates/hir_def/src/body/scope.rs index 9142bc05b..065785da7 100644 --- a/crates/hir_def/src/body/scope.rs +++ b/crates/hir_def/src/body/scope.rs | |||
@@ -194,7 +194,7 @@ mod tests { | |||
194 | let mut buf = String::new(); | 194 | let mut buf = String::new(); |
195 | let off: usize = offset.into(); | 195 | let off: usize = offset.into(); |
196 | buf.push_str(&code[..off]); | 196 | buf.push_str(&code[..off]); |
197 | buf.push_str("<|>marker"); | 197 | buf.push_str("$0marker"); |
198 | buf.push_str(&code[off..]); | 198 | buf.push_str(&code[off..]); |
199 | buf | 199 | buf |
200 | }; | 200 | }; |
@@ -231,7 +231,7 @@ mod tests { | |||
231 | r" | 231 | r" |
232 | fn quux(foo: i32) { | 232 | fn quux(foo: i32) { |
233 | let f = |bar, baz: i32| { | 233 | let f = |bar, baz: i32| { |
234 | <|> | 234 | $0 |
235 | }; | 235 | }; |
236 | }", | 236 | }", |
237 | &["bar", "baz", "foo"], | 237 | &["bar", "baz", "foo"], |
@@ -243,7 +243,7 @@ mod tests { | |||
243 | do_check( | 243 | do_check( |
244 | r" | 244 | r" |
245 | fn quux() { | 245 | fn quux() { |
246 | f(|x| <|> ); | 246 | f(|x| $0 ); |
247 | }", | 247 | }", |
248 | &["x"], | 248 | &["x"], |
249 | ); | 249 | ); |
@@ -254,7 +254,7 @@ mod tests { | |||
254 | do_check( | 254 | do_check( |
255 | r" | 255 | r" |
256 | fn quux() { | 256 | fn quux() { |
257 | z.f(|x| <|> ); | 257 | z.f(|x| $0 ); |
258 | }", | 258 | }", |
259 | &["x"], | 259 | &["x"], |
260 | ); | 260 | ); |
@@ -267,7 +267,7 @@ mod tests { | |||
267 | fn quux() { | 267 | fn quux() { |
268 | loop { | 268 | loop { |
269 | let x = (); | 269 | let x = (); |
270 | <|> | 270 | $0 |
271 | }; | 271 | }; |
272 | }", | 272 | }", |
273 | &["x"], | 273 | &["x"], |
@@ -281,7 +281,7 @@ mod tests { | |||
281 | fn quux() { | 281 | fn quux() { |
282 | match () { | 282 | match () { |
283 | Some(x) => { | 283 | Some(x) => { |
284 | <|> | 284 | $0 |
285 | } | 285 | } |
286 | }; | 286 | }; |
287 | }", | 287 | }", |
@@ -294,7 +294,7 @@ mod tests { | |||
294 | do_check( | 294 | do_check( |
295 | r" | 295 | r" |
296 | fn foo(x: String) { | 296 | fn foo(x: String) { |
297 | let x : &str = &x<|>; | 297 | let x : &str = &x$0; |
298 | }", | 298 | }", |
299 | &["x"], | 299 | &["x"], |
300 | ); | 300 | ); |
@@ -307,7 +307,7 @@ mod tests { | |||
307 | fn foo() { | 307 | fn foo() { |
308 | match Some(()) { | 308 | match Some(()) { |
309 | opt @ Some(unit) => { | 309 | opt @ Some(unit) => { |
310 | <|> | 310 | $0 |
311 | } | 311 | } |
312 | _ => {} | 312 | _ => {} |
313 | } | 313 | } |
@@ -330,7 +330,7 @@ fn foo() { | |||
330 | 330 | ||
331 | fn foo() { | 331 | fn foo() { |
332 | mac!(); | 332 | mac!(); |
333 | <|> | 333 | $0 |
334 | } | 334 | } |
335 | ", | 335 | ", |
336 | &[], | 336 | &[], |
@@ -343,7 +343,7 @@ fn foo() { | |||
343 | r" | 343 | r" |
344 | fn foo() { | 344 | fn foo() { |
345 | trait {} | 345 | trait {} |
346 | <|> | 346 | $0 |
347 | } | 347 | } |
348 | ", | 348 | ", |
349 | &[], | 349 | &[], |
@@ -391,7 +391,7 @@ fn foo(x: i32, y: u32) { | |||
391 | let z = x * 2; | 391 | let z = x * 2; |
392 | } | 392 | } |
393 | { | 393 | { |
394 | let t = x<|> * 3; | 394 | let t = x$0 * 3; |
395 | } | 395 | } |
396 | } | 396 | } |
397 | "#, | 397 | "#, |
@@ -404,7 +404,7 @@ fn foo(x: i32, y: u32) { | |||
404 | do_check_local_name( | 404 | do_check_local_name( |
405 | r#" | 405 | r#" |
406 | fn foo(x: String) { | 406 | fn foo(x: String) { |
407 | let x : &str = &x<|>; | 407 | let x : &str = &x$0; |
408 | } | 408 | } |
409 | "#, | 409 | "#, |
410 | 7, | 410 | 7, |
@@ -417,7 +417,7 @@ fn foo(x: String) { | |||
417 | r" | 417 | r" |
418 | fn foo(x: String) { | 418 | fn foo(x: String) { |
419 | let x : &str = &x; | 419 | let x : &str = &x; |
420 | x<|> | 420 | x$0 |
421 | } | 421 | } |
422 | ", | 422 | ", |
423 | 28, | 423 | 28, |
@@ -430,7 +430,7 @@ fn foo(x: String) { | |||
430 | r" | 430 | r" |
431 | fn foo() { | 431 | fn foo() { |
432 | if let Some(&from) = bar() { | 432 | if let Some(&from) = bar() { |
433 | from<|>; | 433 | from$0; |
434 | } | 434 | } |
435 | } | 435 | } |
436 | ", | 436 | ", |
@@ -446,7 +446,7 @@ fn foo() { | |||
446 | fn test() { | 446 | fn test() { |
447 | let foo: Option<f32> = None; | 447 | let foo: Option<f32> = None; |
448 | while let Option::Some(spam) = foo { | 448 | while let Option::Some(spam) = foo { |
449 | spam<|> | 449 | spam$0 |
450 | } | 450 | } |
451 | } | 451 | } |
452 | "#, | 452 | "#, |
diff --git a/crates/hir_def/src/db.rs b/crates/hir_def/src/db.rs index d1a459066..d3bf5b34c 100644 --- a/crates/hir_def/src/db.rs +++ b/crates/hir_def/src/db.rs | |||
@@ -1,6 +1,7 @@ | |||
1 | //! Defines database & queries for name resolution. | 1 | //! Defines database & queries for name resolution. |
2 | use std::sync::Arc; | 2 | use std::sync::Arc; |
3 | 3 | ||
4 | use arena::map::ArenaMap; | ||
4 | use base_db::{salsa, CrateId, SourceDatabase, Upcast}; | 5 | use base_db::{salsa, CrateId, SourceDatabase, Upcast}; |
5 | use hir_expand::{db::AstDatabase, HirFileId}; | 6 | use hir_expand::{db::AstDatabase, HirFileId}; |
6 | use syntax::SmolStr; | 7 | use syntax::SmolStr; |
@@ -16,8 +17,8 @@ use crate::{ | |||
16 | lang_item::{LangItemTarget, LangItems}, | 17 | lang_item::{LangItemTarget, LangItems}, |
17 | nameres::CrateDefMap, | 18 | nameres::CrateDefMap, |
18 | AttrDefId, ConstId, ConstLoc, DefWithBodyId, EnumId, EnumLoc, FunctionId, FunctionLoc, | 19 | AttrDefId, ConstId, ConstLoc, DefWithBodyId, EnumId, EnumLoc, FunctionId, FunctionLoc, |
19 | GenericDefId, ImplId, ImplLoc, StaticId, StaticLoc, StructId, StructLoc, TraitId, TraitLoc, | 20 | GenericDefId, ImplId, ImplLoc, LocalEnumVariantId, LocalFieldId, StaticId, StaticLoc, StructId, |
20 | TypeAliasId, TypeAliasLoc, UnionId, UnionLoc, | 21 | StructLoc, TraitId, TraitLoc, TypeAliasId, TypeAliasLoc, UnionId, UnionLoc, VariantId, |
21 | }; | 22 | }; |
22 | 23 | ||
23 | #[salsa::query_group(InternDatabaseStorage)] | 24 | #[salsa::query_group(InternDatabaseStorage)] |
@@ -92,6 +93,12 @@ pub trait DefDatabase: InternDatabase + AstDatabase + Upcast<dyn AstDatabase> { | |||
92 | #[salsa::invoke(GenericParams::generic_params_query)] | 93 | #[salsa::invoke(GenericParams::generic_params_query)] |
93 | fn generic_params(&self, def: GenericDefId) -> Arc<GenericParams>; | 94 | fn generic_params(&self, def: GenericDefId) -> Arc<GenericParams>; |
94 | 95 | ||
96 | #[salsa::invoke(Attrs::variants_attrs_query)] | ||
97 | fn variants_attrs(&self, def: EnumId) -> Arc<ArenaMap<LocalEnumVariantId, Attrs>>; | ||
98 | |||
99 | #[salsa::invoke(Attrs::fields_attrs_query)] | ||
100 | fn fields_attrs(&self, def: VariantId) -> Arc<ArenaMap<LocalFieldId, Attrs>>; | ||
101 | |||
95 | #[salsa::invoke(Attrs::attrs_query)] | 102 | #[salsa::invoke(Attrs::attrs_query)] |
96 | fn attrs(&self, def: AttrDefId) -> Attrs; | 103 | fn attrs(&self, def: AttrDefId) -> Attrs; |
97 | 104 | ||
diff --git a/crates/hir_def/src/diagnostics.rs b/crates/hir_def/src/diagnostics.rs index c71266dc0..ab3f059ce 100644 --- a/crates/hir_def/src/diagnostics.rs +++ b/crates/hir_def/src/diagnostics.rs | |||
@@ -133,6 +133,10 @@ impl Diagnostic for InactiveCode { | |||
133 | // This diagnostic is shown when a procedural macro can not be found. This usually means that | 133 | // This diagnostic is shown when a procedural macro can not be found. This usually means that |
134 | // procedural macro support is simply disabled (and hence is only a weak hint instead of an error), | 134 | // procedural macro support is simply disabled (and hence is only a weak hint instead of an error), |
135 | // but can also indicate project setup problems. | 135 | // but can also indicate project setup problems. |
136 | // | ||
137 | // If you are seeing a lot of "proc macro not expanded" warnings, you can add this option to the | ||
138 | // `rust-analyzer.diagnostics.disabled` list to prevent them from showing. Alternatively you can | ||
139 | // enable support for procedural macros (see `rust-analyzer.procMacro.enable`). | ||
136 | #[derive(Debug, Clone, Eq, PartialEq)] | 140 | #[derive(Debug, Clone, Eq, PartialEq)] |
137 | pub struct UnresolvedProcMacro { | 141 | pub struct UnresolvedProcMacro { |
138 | pub file: HirFileId, | 142 | pub file: HirFileId, |
diff --git a/crates/hir_def/src/find_path.rs b/crates/hir_def/src/find_path.rs index 02613c4c4..4a212d291 100644 --- a/crates/hir_def/src/find_path.rs +++ b/crates/hir_def/src/find_path.rs | |||
@@ -410,7 +410,7 @@ mod tests { | |||
410 | let code = r#" | 410 | let code = r#" |
411 | //- /main.rs | 411 | //- /main.rs |
412 | struct S; | 412 | struct S; |
413 | <|> | 413 | $0 |
414 | "#; | 414 | "#; |
415 | check_found_path(code, "S", "S", "crate::S", "self::S"); | 415 | check_found_path(code, "S", "S", "crate::S", "self::S"); |
416 | } | 416 | } |
@@ -420,7 +420,7 @@ mod tests { | |||
420 | let code = r#" | 420 | let code = r#" |
421 | //- /main.rs | 421 | //- /main.rs |
422 | enum E { A } | 422 | enum E { A } |
423 | <|> | 423 | $0 |
424 | "#; | 424 | "#; |
425 | check_found_path(code, "E::A", "E::A", "E::A", "E::A"); | 425 | check_found_path(code, "E::A", "E::A", "E::A", "E::A"); |
426 | } | 426 | } |
@@ -432,7 +432,7 @@ mod tests { | |||
432 | mod foo { | 432 | mod foo { |
433 | pub struct S; | 433 | pub struct S; |
434 | } | 434 | } |
435 | <|> | 435 | $0 |
436 | "#; | 436 | "#; |
437 | check_found_path(code, "foo::S", "foo::S", "crate::foo::S", "self::foo::S"); | 437 | check_found_path(code, "foo::S", "foo::S", "crate::foo::S", "self::foo::S"); |
438 | } | 438 | } |
@@ -446,7 +446,7 @@ mod tests { | |||
446 | mod bar; | 446 | mod bar; |
447 | struct S; | 447 | struct S; |
448 | //- /foo/bar.rs | 448 | //- /foo/bar.rs |
449 | <|> | 449 | $0 |
450 | "#; | 450 | "#; |
451 | check_found_path(code, "super::S", "super::S", "crate::foo::S", "super::S"); | 451 | check_found_path(code, "super::S", "super::S", "crate::foo::S", "super::S"); |
452 | } | 452 | } |
@@ -457,7 +457,7 @@ mod tests { | |||
457 | //- /main.rs | 457 | //- /main.rs |
458 | mod foo; | 458 | mod foo; |
459 | //- /foo.rs | 459 | //- /foo.rs |
460 | <|> | 460 | $0 |
461 | "#; | 461 | "#; |
462 | check_found_path(code, "self", "self", "crate::foo", "self"); | 462 | check_found_path(code, "self", "self", "crate::foo", "self"); |
463 | } | 463 | } |
@@ -468,7 +468,7 @@ mod tests { | |||
468 | //- /main.rs | 468 | //- /main.rs |
469 | mod foo; | 469 | mod foo; |
470 | //- /foo.rs | 470 | //- /foo.rs |
471 | <|> | 471 | $0 |
472 | "#; | 472 | "#; |
473 | check_found_path(code, "crate", "crate", "crate", "crate"); | 473 | check_found_path(code, "crate", "crate", "crate", "crate"); |
474 | } | 474 | } |
@@ -480,7 +480,7 @@ mod tests { | |||
480 | mod foo; | 480 | mod foo; |
481 | struct S; | 481 | struct S; |
482 | //- /foo.rs | 482 | //- /foo.rs |
483 | <|> | 483 | $0 |
484 | "#; | 484 | "#; |
485 | check_found_path(code, "crate::S", "crate::S", "crate::S", "crate::S"); | 485 | check_found_path(code, "crate::S", "crate::S", "crate::S", "crate::S"); |
486 | } | 486 | } |
@@ -489,7 +489,7 @@ mod tests { | |||
489 | fn different_crate() { | 489 | fn different_crate() { |
490 | let code = r#" | 490 | let code = r#" |
491 | //- /main.rs crate:main deps:std | 491 | //- /main.rs crate:main deps:std |
492 | <|> | 492 | $0 |
493 | //- /std.rs crate:std | 493 | //- /std.rs crate:std |
494 | pub struct S; | 494 | pub struct S; |
495 | "#; | 495 | "#; |
@@ -501,7 +501,7 @@ mod tests { | |||
501 | let code = r#" | 501 | let code = r#" |
502 | //- /main.rs crate:main deps:std | 502 | //- /main.rs crate:main deps:std |
503 | extern crate std as std_renamed; | 503 | extern crate std as std_renamed; |
504 | <|> | 504 | $0 |
505 | //- /std.rs crate:std | 505 | //- /std.rs crate:std |
506 | pub struct S; | 506 | pub struct S; |
507 | "#; | 507 | "#; |
@@ -523,7 +523,7 @@ mod tests { | |||
523 | //- /main.rs crate:main deps:syntax | 523 | //- /main.rs crate:main deps:syntax |
524 | 524 | ||
525 | use syntax::ast; | 525 | use syntax::ast; |
526 | <|> | 526 | $0 |
527 | 527 | ||
528 | //- /lib.rs crate:syntax | 528 | //- /lib.rs crate:syntax |
529 | pub mod ast { | 529 | pub mod ast { |
@@ -543,7 +543,7 @@ mod tests { | |||
543 | let code = r#" | 543 | let code = r#" |
544 | //- /main.rs crate:main deps:syntax | 544 | //- /main.rs crate:main deps:syntax |
545 | 545 | ||
546 | <|> | 546 | $0 |
547 | 547 | ||
548 | //- /lib.rs crate:syntax | 548 | //- /lib.rs crate:syntax |
549 | pub mod ast { | 549 | pub mod ast { |
@@ -569,7 +569,7 @@ mod tests { | |||
569 | mod foo { pub(super) struct S; } | 569 | mod foo { pub(super) struct S; } |
570 | pub(crate) use foo::*; | 570 | pub(crate) use foo::*; |
571 | } | 571 | } |
572 | <|> | 572 | $0 |
573 | "#; | 573 | "#; |
574 | check_found_path(code, "bar::S", "bar::S", "crate::bar::S", "self::bar::S"); | 574 | check_found_path(code, "bar::S", "bar::S", "crate::bar::S", "self::bar::S"); |
575 | } | 575 | } |
@@ -582,7 +582,7 @@ mod tests { | |||
582 | mod foo { pub(super) struct S; } | 582 | mod foo { pub(super) struct S; } |
583 | pub(crate) use foo::S as U; | 583 | pub(crate) use foo::S as U; |
584 | } | 584 | } |
585 | <|> | 585 | $0 |
586 | "#; | 586 | "#; |
587 | check_found_path(code, "bar::U", "bar::U", "crate::bar::U", "self::bar::U"); | 587 | check_found_path(code, "bar::U", "bar::U", "crate::bar::U", "self::bar::U"); |
588 | } | 588 | } |
@@ -591,7 +591,7 @@ mod tests { | |||
591 | fn different_crate_reexport() { | 591 | fn different_crate_reexport() { |
592 | let code = r#" | 592 | let code = r#" |
593 | //- /main.rs crate:main deps:std | 593 | //- /main.rs crate:main deps:std |
594 | <|> | 594 | $0 |
595 | //- /std.rs crate:std deps:core | 595 | //- /std.rs crate:std deps:core |
596 | pub use core::S; | 596 | pub use core::S; |
597 | //- /core.rs crate:core | 597 | //- /core.rs crate:core |
@@ -604,7 +604,7 @@ mod tests { | |||
604 | fn prelude() { | 604 | fn prelude() { |
605 | let code = r#" | 605 | let code = r#" |
606 | //- /main.rs crate:main deps:std | 606 | //- /main.rs crate:main deps:std |
607 | <|> | 607 | $0 |
608 | //- /std.rs crate:std | 608 | //- /std.rs crate:std |
609 | pub mod prelude { pub struct S; } | 609 | pub mod prelude { pub struct S; } |
610 | #[prelude_import] | 610 | #[prelude_import] |
@@ -617,7 +617,7 @@ mod tests { | |||
617 | fn enum_variant_from_prelude() { | 617 | fn enum_variant_from_prelude() { |
618 | let code = r#" | 618 | let code = r#" |
619 | //- /main.rs crate:main deps:std | 619 | //- /main.rs crate:main deps:std |
620 | <|> | 620 | $0 |
621 | //- /std.rs crate:std | 621 | //- /std.rs crate:std |
622 | pub mod prelude { | 622 | pub mod prelude { |
623 | pub enum Option<T> { Some(T), None } | 623 | pub enum Option<T> { Some(T), None } |
@@ -637,7 +637,7 @@ mod tests { | |||
637 | pub mod foo; | 637 | pub mod foo; |
638 | pub mod baz; | 638 | pub mod baz; |
639 | struct S; | 639 | struct S; |
640 | <|> | 640 | $0 |
641 | //- /foo.rs | 641 | //- /foo.rs |
642 | pub mod bar { pub struct S; } | 642 | pub mod bar { pub struct S; } |
643 | //- /baz.rs | 643 | //- /baz.rs |
@@ -654,7 +654,7 @@ mod tests { | |||
654 | pub mod bar { pub struct S; } | 654 | pub mod bar { pub struct S; } |
655 | use bar::S; | 655 | use bar::S; |
656 | //- /foo.rs | 656 | //- /foo.rs |
657 | <|> | 657 | $0 |
658 | "#; | 658 | "#; |
659 | // crate::S would be shorter, but using private imports seems wrong | 659 | // crate::S would be shorter, but using private imports seems wrong |
660 | check_found_path(code, "crate::bar::S", "crate::bar::S", "crate::bar::S", "crate::bar::S"); | 660 | check_found_path(code, "crate::bar::S", "crate::bar::S", "crate::bar::S", "crate::bar::S"); |
@@ -668,7 +668,7 @@ mod tests { | |||
668 | pub mod bar; | 668 | pub mod bar; |
669 | pub mod baz; | 669 | pub mod baz; |
670 | //- /bar.rs | 670 | //- /bar.rs |
671 | <|> | 671 | $0 |
672 | //- /foo.rs | 672 | //- /foo.rs |
673 | pub use super::baz; | 673 | pub use super::baz; |
674 | pub struct S; | 674 | pub struct S; |
@@ -683,7 +683,7 @@ mod tests { | |||
683 | mark::check!(prefer_std_paths); | 683 | mark::check!(prefer_std_paths); |
684 | let code = r#" | 684 | let code = r#" |
685 | //- /main.rs crate:main deps:alloc,std | 685 | //- /main.rs crate:main deps:alloc,std |
686 | <|> | 686 | $0 |
687 | 687 | ||
688 | //- /std.rs crate:std deps:alloc | 688 | //- /std.rs crate:std deps:alloc |
689 | pub mod sync { | 689 | pub mod sync { |
@@ -711,7 +711,7 @@ mod tests { | |||
711 | //- /main.rs crate:main deps:core,std | 711 | //- /main.rs crate:main deps:core,std |
712 | #![no_std] | 712 | #![no_std] |
713 | 713 | ||
714 | <|> | 714 | $0 |
715 | 715 | ||
716 | //- /std.rs crate:std deps:core | 716 | //- /std.rs crate:std deps:core |
717 | 717 | ||
@@ -740,7 +740,7 @@ mod tests { | |||
740 | //- /main.rs crate:main deps:alloc,std | 740 | //- /main.rs crate:main deps:alloc,std |
741 | #![no_std] | 741 | #![no_std] |
742 | 742 | ||
743 | <|> | 743 | $0 |
744 | 744 | ||
745 | //- /std.rs crate:std deps:alloc | 745 | //- /std.rs crate:std deps:alloc |
746 | 746 | ||
@@ -767,7 +767,7 @@ mod tests { | |||
767 | fn prefer_shorter_paths_if_not_alloc() { | 767 | fn prefer_shorter_paths_if_not_alloc() { |
768 | let code = r#" | 768 | let code = r#" |
769 | //- /main.rs crate:main deps:megaalloc,std | 769 | //- /main.rs crate:main deps:megaalloc,std |
770 | <|> | 770 | $0 |
771 | 771 | ||
772 | //- /std.rs crate:std deps:megaalloc | 772 | //- /std.rs crate:std deps:megaalloc |
773 | pub mod sync { | 773 | pub mod sync { |
@@ -790,7 +790,7 @@ mod tests { | |||
790 | fn builtins_are_in_scope() { | 790 | fn builtins_are_in_scope() { |
791 | let code = r#" | 791 | let code = r#" |
792 | //- /main.rs | 792 | //- /main.rs |
793 | <|> | 793 | $0 |
794 | 794 | ||
795 | pub mod primitive { | 795 | pub mod primitive { |
796 | pub use u8; | 796 | pub use u8; |
diff --git a/crates/hir_def/src/import_map.rs b/crates/hir_def/src/import_map.rs index 30b22f51d..e5368b293 100644 --- a/crates/hir_def/src/import_map.rs +++ b/crates/hir_def/src/import_map.rs | |||
@@ -7,9 +7,8 @@ use fst::{self, Streamer}; | |||
7 | use hir_expand::name::Name; | 7 | use hir_expand::name::Name; |
8 | use indexmap::{map::Entry, IndexMap}; | 8 | use indexmap::{map::Entry, IndexMap}; |
9 | use itertools::Itertools; | 9 | use itertools::Itertools; |
10 | use rustc_hash::{FxHashMap, FxHashSet, FxHasher}; | 10 | use rustc_hash::{FxHashSet, FxHasher}; |
11 | use smallvec::SmallVec; | 11 | use test_utils::mark; |
12 | use syntax::SmolStr; | ||
13 | 12 | ||
14 | use crate::{ | 13 | use crate::{ |
15 | db::DefDatabase, item_scope::ItemInNs, visibility::Visibility, AssocItemId, ModuleDefId, | 14 | db::DefDatabase, item_scope::ItemInNs, visibility::Visibility, AssocItemId, ModuleDefId, |
@@ -25,6 +24,8 @@ pub struct ImportInfo { | |||
25 | pub path: ImportPath, | 24 | pub path: ImportPath, |
26 | /// The module containing this item. | 25 | /// The module containing this item. |
27 | pub container: ModuleId, | 26 | pub container: ModuleId, |
27 | /// Whether the import is a trait associated item or not. | ||
28 | pub is_trait_assoc_item: bool, | ||
28 | } | 29 | } |
29 | 30 | ||
30 | #[derive(Debug, Clone, Eq, PartialEq)] | 31 | #[derive(Debug, Clone, Eq, PartialEq)] |
@@ -64,10 +65,6 @@ pub struct ImportMap { | |||
64 | /// the index of the first one. | 65 | /// the index of the first one. |
65 | importables: Vec<ItemInNs>, | 66 | importables: Vec<ItemInNs>, |
66 | fst: fst::Map<Vec<u8>>, | 67 | fst: fst::Map<Vec<u8>>, |
67 | |||
68 | /// Maps names of associated items to the item's ID. Only includes items whose defining trait is | ||
69 | /// exported. | ||
70 | assoc_map: FxHashMap<SmolStr, SmallVec<[AssocItemId; 1]>>, | ||
71 | } | 68 | } |
72 | 69 | ||
73 | impl ImportMap { | 70 | impl ImportMap { |
@@ -108,14 +105,27 @@ impl ImportMap { | |||
108 | 105 | ||
109 | for item in per_ns.iter_items() { | 106 | for item in per_ns.iter_items() { |
110 | let path = mk_path(); | 107 | let path = mk_path(); |
108 | let path_len = path.len(); | ||
109 | let import_info = | ||
110 | ImportInfo { path, container: module, is_trait_assoc_item: false }; | ||
111 | |||
112 | if let Some(ModuleDefId::TraitId(tr)) = item.as_module_def_id() { | ||
113 | import_map.collect_trait_assoc_items( | ||
114 | db, | ||
115 | tr, | ||
116 | matches!(item, ItemInNs::Types(_)), | ||
117 | &import_info, | ||
118 | ); | ||
119 | } | ||
120 | |||
111 | match import_map.map.entry(item) { | 121 | match import_map.map.entry(item) { |
112 | Entry::Vacant(entry) => { | 122 | Entry::Vacant(entry) => { |
113 | entry.insert(ImportInfo { path, container: module }); | 123 | entry.insert(import_info); |
114 | } | 124 | } |
115 | Entry::Occupied(mut entry) => { | 125 | Entry::Occupied(mut entry) => { |
116 | // If the new path is shorter, prefer that one. | 126 | // If the new path is shorter, prefer that one. |
117 | if path.len() < entry.get().path.len() { | 127 | if path_len < entry.get().path.len() { |
118 | *entry.get_mut() = ImportInfo { path, container: module }; | 128 | *entry.get_mut() = import_info; |
119 | } else { | 129 | } else { |
120 | continue; | 130 | continue; |
121 | } | 131 | } |
@@ -128,11 +138,6 @@ impl ImportMap { | |||
128 | if let Some(ModuleDefId::ModuleId(mod_id)) = item.as_module_def_id() { | 138 | if let Some(ModuleDefId::ModuleId(mod_id)) = item.as_module_def_id() { |
129 | worklist.push((mod_id, mk_path())); | 139 | worklist.push((mod_id, mk_path())); |
130 | } | 140 | } |
131 | |||
132 | // If we've added a path to a trait, add the trait's methods to the method map. | ||
133 | if let Some(ModuleDefId::TraitId(tr)) = item.as_module_def_id() { | ||
134 | import_map.collect_trait_methods(db, tr); | ||
135 | } | ||
136 | } | 141 | } |
137 | } | 142 | } |
138 | } | 143 | } |
@@ -153,12 +158,10 @@ impl ImportMap { | |||
153 | } | 158 | } |
154 | } | 159 | } |
155 | 160 | ||
156 | let start = last_batch_start; | 161 | let key = fst_path(&importables[last_batch_start].1.path); |
157 | last_batch_start = idx + 1; | 162 | builder.insert(key, last_batch_start as u64).unwrap(); |
158 | |||
159 | let key = fst_path(&importables[start].1.path); | ||
160 | 163 | ||
161 | builder.insert(key, start as u64).unwrap(); | 164 | last_batch_start = idx + 1; |
162 | } | 165 | } |
163 | 166 | ||
164 | import_map.fst = fst::Map::new(builder.into_inner().unwrap()).unwrap(); | 167 | import_map.fst = fst::Map::new(builder.into_inner().unwrap()).unwrap(); |
@@ -176,10 +179,34 @@ impl ImportMap { | |||
176 | self.map.get(&item) | 179 | self.map.get(&item) |
177 | } | 180 | } |
178 | 181 | ||
179 | fn collect_trait_methods(&mut self, db: &dyn DefDatabase, tr: TraitId) { | 182 | fn collect_trait_assoc_items( |
180 | let data = db.trait_data(tr); | 183 | &mut self, |
181 | for (name, item) in data.items.iter() { | 184 | db: &dyn DefDatabase, |
182 | self.assoc_map.entry(name.to_string().into()).or_default().push(*item); | 185 | tr: TraitId, |
186 | is_type_in_ns: bool, | ||
187 | original_import_info: &ImportInfo, | ||
188 | ) { | ||
189 | for (assoc_item_name, item) in &db.trait_data(tr).items { | ||
190 | let module_def_id = match item { | ||
191 | AssocItemId::FunctionId(f) => ModuleDefId::from(*f), | ||
192 | AssocItemId::ConstId(c) => ModuleDefId::from(*c), | ||
193 | // cannot use associated type aliases directly: need a `<Struct as Trait>::TypeAlias` | ||
194 | // qualifier, ergo no need to store it for imports in import_map | ||
195 | AssocItemId::TypeAliasId(_) => { | ||
196 | mark::hit!(type_aliases_ignored); | ||
197 | continue; | ||
198 | } | ||
199 | }; | ||
200 | let assoc_item = if is_type_in_ns { | ||
201 | ItemInNs::Types(module_def_id) | ||
202 | } else { | ||
203 | ItemInNs::Values(module_def_id) | ||
204 | }; | ||
205 | |||
206 | let mut assoc_item_info = original_import_info.clone(); | ||
207 | assoc_item_info.path.segments.push(assoc_item_name.to_owned()); | ||
208 | assoc_item_info.is_trait_assoc_item = true; | ||
209 | self.map.insert(assoc_item, assoc_item_info); | ||
183 | } | 210 | } |
184 | } | 211 | } |
185 | } | 212 | } |
@@ -302,38 +329,38 @@ impl Query { | |||
302 | self.exclude_import_kinds.insert(import_kind); | 329 | self.exclude_import_kinds.insert(import_kind); |
303 | self | 330 | self |
304 | } | 331 | } |
305 | } | ||
306 | 332 | ||
307 | fn contains_query(query: &Query, input_path: &ImportPath, enforce_lowercase: bool) -> bool { | 333 | fn import_matches(&self, import: &ImportInfo, enforce_lowercase: bool) -> bool { |
308 | let mut input = if query.name_only { | 334 | let mut input = if import.is_trait_assoc_item || self.name_only { |
309 | input_path.segments.last().unwrap().to_string() | 335 | import.path.segments.last().unwrap().to_string() |
310 | } else { | 336 | } else { |
311 | input_path.to_string() | 337 | import.path.to_string() |
312 | }; | 338 | }; |
313 | if enforce_lowercase || !query.case_sensitive { | 339 | if enforce_lowercase || !self.case_sensitive { |
314 | input.make_ascii_lowercase(); | 340 | input.make_ascii_lowercase(); |
315 | } | 341 | } |
316 | 342 | ||
317 | let query_string = | 343 | let query_string = |
318 | if !enforce_lowercase && query.case_sensitive { &query.query } else { &query.lowercased }; | 344 | if !enforce_lowercase && self.case_sensitive { &self.query } else { &self.lowercased }; |
319 | 345 | ||
320 | match query.search_mode { | 346 | match self.search_mode { |
321 | SearchMode::Equals => &input == query_string, | 347 | SearchMode::Equals => &input == query_string, |
322 | SearchMode::Contains => input.contains(query_string), | 348 | SearchMode::Contains => input.contains(query_string), |
323 | SearchMode::Fuzzy => { | 349 | SearchMode::Fuzzy => { |
324 | let mut unchecked_query_chars = query_string.chars(); | 350 | let mut unchecked_query_chars = query_string.chars(); |
325 | let mut mismatching_query_char = unchecked_query_chars.next(); | 351 | let mut mismatching_query_char = unchecked_query_chars.next(); |
326 | 352 | ||
327 | for input_char in input.chars() { | 353 | for input_char in input.chars() { |
328 | match mismatching_query_char { | 354 | match mismatching_query_char { |
329 | None => return true, | 355 | None => return true, |
330 | Some(matching_query_char) if matching_query_char == input_char => { | 356 | Some(matching_query_char) if matching_query_char == input_char => { |
331 | mismatching_query_char = unchecked_query_chars.next(); | 357 | mismatching_query_char = unchecked_query_chars.next(); |
358 | } | ||
359 | _ => (), | ||
332 | } | 360 | } |
333 | _ => (), | ||
334 | } | 361 | } |
362 | mismatching_query_char.is_none() | ||
335 | } | 363 | } |
336 | mismatching_query_char.is_none() | ||
337 | } | 364 | } |
338 | } | 365 | } |
339 | } | 366 | } |
@@ -366,13 +393,13 @@ pub fn search_dependencies<'a>( | |||
366 | let import_map = &import_maps[indexed_value.index]; | 393 | let import_map = &import_maps[indexed_value.index]; |
367 | let importables = &import_map.importables[indexed_value.value as usize..]; | 394 | let importables = &import_map.importables[indexed_value.value as usize..]; |
368 | 395 | ||
369 | // Path shared by the importable items in this group. | 396 | let common_importable_data = &import_map.map[&importables[0]]; |
370 | let common_importables_path = &import_map.map[&importables[0]].path; | 397 | if !query.import_matches(common_importable_data, true) { |
371 | if !contains_query(&query, common_importables_path, true) { | ||
372 | continue; | 398 | continue; |
373 | } | 399 | } |
374 | 400 | ||
375 | let common_importables_path_fst = fst_path(common_importables_path); | 401 | // Path shared by the importable items in this group. |
402 | let common_importables_path_fst = fst_path(&common_importable_data.path); | ||
376 | // Add the items from this `ModPath` group. Those are all subsequent items in | 403 | // Add the items from this `ModPath` group. Those are all subsequent items in |
377 | // `importables` whose paths match `path`. | 404 | // `importables` whose paths match `path`. |
378 | let iter = importables | 405 | let iter = importables |
@@ -387,7 +414,7 @@ pub fn search_dependencies<'a>( | |||
387 | }) | 414 | }) |
388 | .filter(|item| { | 415 | .filter(|item| { |
389 | !query.case_sensitive // we've already checked the common importables path case-insensitively | 416 | !query.case_sensitive // we've already checked the common importables path case-insensitively |
390 | || contains_query(&query, &import_map.map[item].path, false) | 417 | || query.import_matches(&import_map.map[item], false) |
391 | }); | 418 | }); |
392 | res.extend(iter); | 419 | res.extend(iter); |
393 | 420 | ||
@@ -398,19 +425,6 @@ pub fn search_dependencies<'a>( | |||
398 | } | 425 | } |
399 | } | 426 | } |
400 | 427 | ||
401 | // Add all exported associated items whose names match the query (exactly). | ||
402 | for map in &import_maps { | ||
403 | if let Some(v) = map.assoc_map.get(&*query.query) { | ||
404 | res.extend(v.iter().map(|&assoc| { | ||
405 | ItemInNs::Types(match assoc { | ||
406 | AssocItemId::FunctionId(it) => it.into(), | ||
407 | AssocItemId::ConstId(it) => it.into(), | ||
408 | AssocItemId::TypeAliasId(it) => it.into(), | ||
409 | }) | ||
410 | })); | ||
411 | } | ||
412 | } | ||
413 | |||
414 | res | 428 | res |
415 | } | 429 | } |
416 | 430 | ||
@@ -432,9 +446,9 @@ fn item_import_kind(item: ItemInNs) -> Option<ImportKind> { | |||
432 | mod tests { | 446 | mod tests { |
433 | use base_db::{fixture::WithFixture, SourceDatabase, Upcast}; | 447 | use base_db::{fixture::WithFixture, SourceDatabase, Upcast}; |
434 | use expect_test::{expect, Expect}; | 448 | use expect_test::{expect, Expect}; |
435 | use stdx::format_to; | 449 | use test_utils::mark; |
436 | 450 | ||
437 | use crate::{data::FunctionData, test_db::TestDB, AssocContainerId, Lookup}; | 451 | use crate::{test_db::TestDB, AssocContainerId, Lookup}; |
438 | 452 | ||
439 | use super::*; | 453 | use super::*; |
440 | 454 | ||
@@ -451,46 +465,66 @@ mod tests { | |||
451 | 465 | ||
452 | let actual = search_dependencies(db.upcast(), krate, query) | 466 | let actual = search_dependencies(db.upcast(), krate, query) |
453 | .into_iter() | 467 | .into_iter() |
454 | .filter_map(|item| { | 468 | .filter_map(|dependency| { |
455 | let mark = match item { | 469 | let dependency_krate = dependency.krate(db.upcast())?; |
456 | ItemInNs::Types(ModuleDefId::FunctionId(_)) | 470 | let dependency_imports = db.import_map(dependency_krate); |
457 | | ItemInNs::Values(ModuleDefId::FunctionId(_)) => "f", | 471 | |
458 | ItemInNs::Types(_) => "t", | 472 | let (path, mark) = match assoc_item_path(&db, &dependency_imports, dependency) { |
459 | ItemInNs::Values(_) => "v", | 473 | Some(assoc_item_path) => (assoc_item_path, "a"), |
460 | ItemInNs::Macros(_) => "m", | 474 | None => ( |
475 | dependency_imports.path_of(dependency)?.to_string(), | ||
476 | match dependency { | ||
477 | ItemInNs::Types(ModuleDefId::FunctionId(_)) | ||
478 | | ItemInNs::Values(ModuleDefId::FunctionId(_)) => "f", | ||
479 | ItemInNs::Types(_) => "t", | ||
480 | ItemInNs::Values(_) => "v", | ||
481 | ItemInNs::Macros(_) => "m", | ||
482 | }, | ||
483 | ), | ||
461 | }; | 484 | }; |
462 | item.krate(db.upcast()).map(|krate| { | 485 | |
463 | let map = db.import_map(krate); | 486 | Some(format!( |
464 | 487 | "{}::{} ({})\n", | |
465 | let path = match assoc_to_trait(&db, item) { | 488 | crate_graph[dependency_krate].display_name.as_ref()?, |
466 | Some(trait_) => { | 489 | path, |
467 | let mut full_path = map.path_of(trait_).unwrap().to_string(); | 490 | mark |
468 | if let ItemInNs::Types(ModuleDefId::FunctionId(function_id)) | 491 | )) |
469 | | ItemInNs::Values(ModuleDefId::FunctionId(function_id)) = item | ||
470 | { | ||
471 | format_to!( | ||
472 | full_path, | ||
473 | "::{}", | ||
474 | FunctionData::fn_data_query(&db, function_id).name, | ||
475 | ); | ||
476 | } | ||
477 | full_path | ||
478 | } | ||
479 | None => map.path_of(item).unwrap().to_string(), | ||
480 | }; | ||
481 | |||
482 | format!( | ||
483 | "{}::{} ({})\n", | ||
484 | crate_graph[krate].display_name.as_ref().unwrap(), | ||
485 | path, | ||
486 | mark | ||
487 | ) | ||
488 | }) | ||
489 | }) | 492 | }) |
490 | .collect::<String>(); | 493 | .collect::<String>(); |
491 | expect.assert_eq(&actual) | 494 | expect.assert_eq(&actual) |
492 | } | 495 | } |
493 | 496 | ||
497 | fn assoc_item_path( | ||
498 | db: &dyn DefDatabase, | ||
499 | dependency_imports: &ImportMap, | ||
500 | dependency: ItemInNs, | ||
501 | ) -> Option<String> { | ||
502 | let dependency_assoc_item_id = match dependency { | ||
503 | ItemInNs::Types(ModuleDefId::FunctionId(id)) | ||
504 | | ItemInNs::Values(ModuleDefId::FunctionId(id)) => AssocItemId::from(id), | ||
505 | ItemInNs::Types(ModuleDefId::ConstId(id)) | ||
506 | | ItemInNs::Values(ModuleDefId::ConstId(id)) => AssocItemId::from(id), | ||
507 | ItemInNs::Types(ModuleDefId::TypeAliasId(id)) | ||
508 | | ItemInNs::Values(ModuleDefId::TypeAliasId(id)) => AssocItemId::from(id), | ||
509 | _ => return None, | ||
510 | }; | ||
511 | |||
512 | let trait_ = assoc_to_trait(db, dependency)?; | ||
513 | if let ModuleDefId::TraitId(tr) = trait_.as_module_def_id()? { | ||
514 | let trait_data = db.trait_data(tr); | ||
515 | let assoc_item_name = | ||
516 | trait_data.items.iter().find_map(|(assoc_item_name, assoc_item_id)| { | ||
517 | if &dependency_assoc_item_id == assoc_item_id { | ||
518 | Some(assoc_item_name) | ||
519 | } else { | ||
520 | None | ||
521 | } | ||
522 | })?; | ||
523 | return Some(format!("{}::{}", dependency_imports.path_of(trait_)?, assoc_item_name)); | ||
524 | } | ||
525 | None | ||
526 | } | ||
527 | |||
494 | fn assoc_to_trait(db: &dyn DefDatabase, item: ItemInNs) -> Option<ItemInNs> { | 528 | fn assoc_to_trait(db: &dyn DefDatabase, item: ItemInNs) -> Option<ItemInNs> { |
495 | let assoc: AssocItemId = match item { | 529 | let assoc: AssocItemId = match item { |
496 | ItemInNs::Types(it) | ItemInNs::Values(it) => match it { | 530 | ItemInNs::Types(it) | ItemInNs::Values(it) => match it { |
@@ -749,6 +783,37 @@ mod tests { | |||
749 | } | 783 | } |
750 | 784 | ||
751 | #[test] | 785 | #[test] |
786 | fn fuzzy_import_trait_and_assoc_items() { | ||
787 | mark::check!(type_aliases_ignored); | ||
788 | let ra_fixture = r#" | ||
789 | //- /main.rs crate:main deps:dep | ||
790 | //- /dep.rs crate:dep | ||
791 | pub mod fmt { | ||
792 | pub trait Display { | ||
793 | type FmtTypeAlias; | ||
794 | const FMT_CONST: bool; | ||
795 | |||
796 | fn format_function(); | ||
797 | fn format_method(&self); | ||
798 | } | ||
799 | } | ||
800 | "#; | ||
801 | |||
802 | check_search( | ||
803 | ra_fixture, | ||
804 | "main", | ||
805 | Query::new("fmt".to_string()).search_mode(SearchMode::Fuzzy), | ||
806 | expect![[r#" | ||
807 | dep::fmt (t) | ||
808 | dep::fmt::Display (t) | ||
809 | dep::fmt::Display::FMT_CONST (a) | ||
810 | dep::fmt::Display::format_function (a) | ||
811 | dep::fmt::Display::format_method (a) | ||
812 | "#]], | ||
813 | ); | ||
814 | } | ||
815 | |||
816 | #[test] | ||
752 | fn search_mode() { | 817 | fn search_mode() { |
753 | let ra_fixture = r#" | 818 | let ra_fixture = r#" |
754 | //- /main.rs crate:main deps:dep | 819 | //- /main.rs crate:main deps:dep |
@@ -784,8 +849,8 @@ mod tests { | |||
784 | dep::Fmt (v) | 849 | dep::Fmt (v) |
785 | dep::Fmt (m) | 850 | dep::Fmt (m) |
786 | dep::fmt::Display (t) | 851 | dep::fmt::Display (t) |
852 | dep::fmt::Display::fmt (a) | ||
787 | dep::format (f) | 853 | dep::format (f) |
788 | dep::fmt::Display::fmt (f) | ||
789 | "#]], | 854 | "#]], |
790 | ); | 855 | ); |
791 | 856 | ||
@@ -798,7 +863,7 @@ mod tests { | |||
798 | dep::Fmt (t) | 863 | dep::Fmt (t) |
799 | dep::Fmt (v) | 864 | dep::Fmt (v) |
800 | dep::Fmt (m) | 865 | dep::Fmt (m) |
801 | dep::fmt::Display::fmt (f) | 866 | dep::fmt::Display::fmt (a) |
802 | "#]], | 867 | "#]], |
803 | ); | 868 | ); |
804 | 869 | ||
@@ -812,7 +877,7 @@ mod tests { | |||
812 | dep::Fmt (v) | 877 | dep::Fmt (v) |
813 | dep::Fmt (m) | 878 | dep::Fmt (m) |
814 | dep::fmt::Display (t) | 879 | dep::fmt::Display (t) |
815 | dep::fmt::Display::fmt (f) | 880 | dep::fmt::Display::fmt (a) |
816 | "#]], | 881 | "#]], |
817 | ); | 882 | ); |
818 | } | 883 | } |
@@ -853,7 +918,7 @@ mod tests { | |||
853 | dep::Fmt (v) | 918 | dep::Fmt (v) |
854 | dep::Fmt (m) | 919 | dep::Fmt (m) |
855 | dep::fmt::Display (t) | 920 | dep::fmt::Display (t) |
856 | dep::fmt::Display::fmt (f) | 921 | dep::fmt::Display::fmt (a) |
857 | "#]], | 922 | "#]], |
858 | ); | 923 | ); |
859 | 924 | ||
@@ -866,7 +931,7 @@ mod tests { | |||
866 | dep::Fmt (t) | 931 | dep::Fmt (t) |
867 | dep::Fmt (v) | 932 | dep::Fmt (v) |
868 | dep::Fmt (m) | 933 | dep::Fmt (m) |
869 | dep::fmt::Display::fmt (f) | 934 | dep::fmt::Display::fmt (a) |
870 | "#]], | 935 | "#]], |
871 | ); | 936 | ); |
872 | } | 937 | } |
diff --git a/crates/hir_def/src/item_scope.rs b/crates/hir_def/src/item_scope.rs index 62ab3b2bd..2750e1c91 100644 --- a/crates/hir_def/src/item_scope.rs +++ b/crates/hir_def/src/item_scope.rs | |||
@@ -10,10 +10,9 @@ use once_cell::sync::Lazy; | |||
10 | use rustc_hash::{FxHashMap, FxHashSet}; | 10 | use rustc_hash::{FxHashMap, FxHashSet}; |
11 | use test_utils::mark; | 11 | use test_utils::mark; |
12 | 12 | ||
13 | use crate::ModuleId; | ||
14 | use crate::{ | 13 | use crate::{ |
15 | db::DefDatabase, per_ns::PerNs, visibility::Visibility, AdtId, BuiltinType, HasModule, ImplId, | 14 | db::DefDatabase, per_ns::PerNs, visibility::Visibility, AdtId, BuiltinType, HasModule, ImplId, |
16 | LocalModuleId, Lookup, MacroDefId, ModuleDefId, TraitId, | 15 | LocalModuleId, Lookup, MacroDefId, ModuleDefId, ModuleId, TraitId, |
17 | }; | 16 | }; |
18 | 17 | ||
19 | #[derive(Copy, Clone)] | 18 | #[derive(Copy, Clone)] |
diff --git a/crates/hir_def/src/nameres/collector.rs b/crates/hir_def/src/nameres/collector.rs index a636ec77d..77017e4ea 100644 --- a/crates/hir_def/src/nameres/collector.rs +++ b/crates/hir_def/src/nameres/collector.rs | |||
@@ -13,7 +13,7 @@ use hir_expand::{ | |||
13 | builtin_macro::find_builtin_macro, | 13 | builtin_macro::find_builtin_macro, |
14 | name::{AsName, Name}, | 14 | name::{AsName, Name}, |
15 | proc_macro::ProcMacroExpander, | 15 | proc_macro::ProcMacroExpander, |
16 | HirFileId, MacroCallId, MacroDefId, MacroDefKind, | 16 | HirFileId, MacroCallId, MacroCallKind, MacroDefId, MacroDefKind, |
17 | }; | 17 | }; |
18 | use hir_expand::{InFile, MacroCallLoc}; | 18 | use hir_expand::{InFile, MacroCallLoc}; |
19 | use rustc_hash::{FxHashMap, FxHashSet}; | 19 | use rustc_hash::{FxHashMap, FxHashSet}; |
@@ -860,6 +860,37 @@ impl DefCollector<'_> { | |||
860 | } | 860 | } |
861 | 861 | ||
862 | fn finish(mut self) -> CrateDefMap { | 862 | fn finish(mut self) -> CrateDefMap { |
863 | // Emit diagnostics for all remaining unexpanded macros. | ||
864 | |||
865 | for directive in &self.unexpanded_macros { | ||
866 | let mut error = None; | ||
867 | directive.ast_id.as_call_id_with_errors( | ||
868 | self.db, | ||
869 | self.def_map.krate, | ||
870 | |path| { | ||
871 | let resolved_res = self.def_map.resolve_path_fp_with_macro( | ||
872 | self.db, | ||
873 | ResolveMode::Other, | ||
874 | directive.module_id, | ||
875 | &path, | ||
876 | BuiltinShadowMode::Module, | ||
877 | ); | ||
878 | resolved_res.resolved_def.take_macros() | ||
879 | }, | ||
880 | &mut |e| { | ||
881 | error.get_or_insert(e); | ||
882 | }, | ||
883 | ); | ||
884 | |||
885 | if let Some(err) = error { | ||
886 | self.def_map.diagnostics.push(DefDiagnostic::macro_error( | ||
887 | directive.module_id, | ||
888 | MacroCallKind::FnLike(directive.ast_id.ast_id), | ||
889 | err.to_string(), | ||
890 | )); | ||
891 | } | ||
892 | } | ||
893 | |||
863 | // Emit diagnostics for all remaining unresolved imports. | 894 | // Emit diagnostics for all remaining unresolved imports. |
864 | 895 | ||
865 | // We'd like to avoid emitting a diagnostics avalanche when some `extern crate` doesn't | 896 | // We'd like to avoid emitting a diagnostics avalanche when some `extern crate` doesn't |
diff --git a/crates/hir_def/src/nameres/tests/incremental.rs b/crates/hir_def/src/nameres/tests/incremental.rs index 8981fa7c9..509e1bbbc 100644 --- a/crates/hir_def/src/nameres/tests/incremental.rs +++ b/crates/hir_def/src/nameres/tests/incremental.rs | |||
@@ -28,7 +28,7 @@ fn typing_inside_a_function_should_not_invalidate_def_map() { | |||
28 | check_def_map_is_not_recomputed( | 28 | check_def_map_is_not_recomputed( |
29 | r" | 29 | r" |
30 | //- /lib.rs | 30 | //- /lib.rs |
31 | mod foo;<|> | 31 | mod foo;$0 |
32 | 32 | ||
33 | use crate::foo::bar::Baz; | 33 | use crate::foo::bar::Baz; |
34 | 34 | ||
@@ -81,7 +81,7 @@ fn typing_inside_a_macro_should_not_invalidate_def_map() { | |||
81 | pub mod bar; | 81 | pub mod bar; |
82 | 82 | ||
83 | //- /foo/bar.rs | 83 | //- /foo/bar.rs |
84 | <|> | 84 | $0 |
85 | m!(X); | 85 | m!(X); |
86 | ", | 86 | ", |
87 | ); | 87 | ); |
diff --git a/crates/hir_def/src/path.rs b/crates/hir_def/src/path.rs index e2bf85bbc..3dd7c3cbb 100644 --- a/crates/hir_def/src/path.rs +++ b/crates/hir_def/src/path.rs | |||
@@ -305,6 +305,7 @@ pub use hir_expand::name as __name; | |||
305 | macro_rules! __known_path { | 305 | macro_rules! __known_path { |
306 | (core::iter::IntoIterator) => {}; | 306 | (core::iter::IntoIterator) => {}; |
307 | (core::result::Result) => {}; | 307 | (core::result::Result) => {}; |
308 | (core::option::Option) => {}; | ||
308 | (core::ops::Range) => {}; | 309 | (core::ops::Range) => {}; |
309 | (core::ops::RangeFrom) => {}; | 310 | (core::ops::RangeFrom) => {}; |
310 | (core::ops::RangeFull) => {}; | 311 | (core::ops::RangeFull) => {}; |