diff options
79 files changed, 1468 insertions, 860 deletions
diff --git a/Cargo.lock b/Cargo.lock index 51a07abe3..b1fef2e80 100644 --- a/Cargo.lock +++ b/Cargo.lock | |||
@@ -107,9 +107,9 @@ checksum = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693" | |||
107 | 107 | ||
108 | [[package]] | 108 | [[package]] |
109 | name = "byteorder" | 109 | name = "byteorder" |
110 | version = "1.4.2" | 110 | version = "1.4.3" |
111 | source = "registry+https://github.com/rust-lang/crates.io-index" | 111 | source = "registry+https://github.com/rust-lang/crates.io-index" |
112 | checksum = "ae44d1a3d5a19df61dd0c8beb138458ac2a53a7ac09eba97d55592540004306b" | 112 | checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610" |
113 | 113 | ||
114 | [[package]] | 114 | [[package]] |
115 | name = "camino" | 115 | name = "camino" |
@@ -524,7 +524,9 @@ name = "hir_expand" | |||
524 | version = "0.0.0" | 524 | version = "0.0.0" |
525 | dependencies = [ | 525 | dependencies = [ |
526 | "base_db", | 526 | "base_db", |
527 | "cfg", | ||
527 | "either", | 528 | "either", |
529 | "expect-test", | ||
528 | "la-arena", | 530 | "la-arena", |
529 | "log", | 531 | "log", |
530 | "mbe", | 532 | "mbe", |
@@ -897,6 +899,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index" | |||
897 | checksum = "0ee1c47aaa256ecabcaea351eae4a9b01ef39ed810004e298d2511ed284b1525" | 899 | checksum = "0ee1c47aaa256ecabcaea351eae4a9b01ef39ed810004e298d2511ed284b1525" |
898 | 900 | ||
899 | [[package]] | 901 | [[package]] |
902 | name = "memmap" | ||
903 | version = "0.7.0" | ||
904 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
905 | checksum = "6585fd95e7bb50d6cc31e20d4cf9afb4e2ba16c5846fc76793f11218da9c475b" | ||
906 | dependencies = [ | ||
907 | "libc", | ||
908 | "winapi", | ||
909 | ] | ||
910 | |||
911 | [[package]] | ||
900 | name = "memmap2" | 912 | name = "memmap2" |
901 | version = "0.2.1" | 913 | version = "0.2.1" |
902 | source = "registry+https://github.com/rust-lang/crates.io-index" | 914 | source = "registry+https://github.com/rust-lang/crates.io-index" |
@@ -1159,8 +1171,11 @@ dependencies = [ | |||
1159 | "crossbeam-channel", | 1171 | "crossbeam-channel", |
1160 | "jod-thread", | 1172 | "jod-thread", |
1161 | "log", | 1173 | "log", |
1174 | "memmap", | ||
1175 | "object", | ||
1162 | "serde", | 1176 | "serde", |
1163 | "serde_json", | 1177 | "serde_json", |
1178 | "snap", | ||
1164 | "stdx", | 1179 | "stdx", |
1165 | "tt", | 1180 | "tt", |
1166 | ] | 1181 | ] |
@@ -1375,9 +1390,9 @@ dependencies = [ | |||
1375 | 1390 | ||
1376 | [[package]] | 1391 | [[package]] |
1377 | name = "rustc-ap-rustc_lexer" | 1392 | name = "rustc-ap-rustc_lexer" |
1378 | version = "709.0.0" | 1393 | version = "710.0.0" |
1379 | source = "registry+https://github.com/rust-lang/crates.io-index" | 1394 | source = "registry+https://github.com/rust-lang/crates.io-index" |
1380 | checksum = "f69f83314702aaccf29c7401cc63bb0d9fa7869a185a23b8379f08c91514b3f3" | 1395 | checksum = "b0bba1ca6787b6d4af505b7a940eae9ecb084dd03e07f03bf3ddbf78e738b617" |
1381 | dependencies = [ | 1396 | dependencies = [ |
1382 | "unicode-xid", | 1397 | "unicode-xid", |
1383 | ] | 1398 | ] |
@@ -1546,6 +1561,12 @@ dependencies = [ | |||
1546 | ] | 1561 | ] |
1547 | 1562 | ||
1548 | [[package]] | 1563 | [[package]] |
1564 | name = "snap" | ||
1565 | version = "1.0.4" | ||
1566 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
1567 | checksum = "dc725476a1398f0480d56cd0ad381f6f32acf2642704456f8f59a35df464b59a" | ||
1568 | |||
1569 | [[package]] | ||
1549 | name = "socket2" | 1570 | name = "socket2" |
1550 | version = "0.3.19" | 1571 | version = "0.3.19" |
1551 | source = "registry+https://github.com/rust-lang/crates.io-index" | 1572 | source = "registry+https://github.com/rust-lang/crates.io-index" |
@@ -1566,9 +1587,9 @@ dependencies = [ | |||
1566 | 1587 | ||
1567 | [[package]] | 1588 | [[package]] |
1568 | name = "syn" | 1589 | name = "syn" |
1569 | version = "1.0.62" | 1590 | version = "1.0.63" |
1570 | source = "registry+https://github.com/rust-lang/crates.io-index" | 1591 | source = "registry+https://github.com/rust-lang/crates.io-index" |
1571 | checksum = "123a78a3596b24fee53a6464ce52d8ecbf62241e6294c7e7fe12086cd161f512" | 1592 | checksum = "8fd9bc7ccc2688b3344c2f48b9b546648b25ce0b20fc717ee7fa7981a8ca9717" |
1572 | dependencies = [ | 1593 | dependencies = [ |
1573 | "proc-macro2", | 1594 | "proc-macro2", |
1574 | "quote", | 1595 | "quote", |
@@ -1761,9 +1782,9 @@ dependencies = [ | |||
1761 | 1782 | ||
1762 | [[package]] | 1783 | [[package]] |
1763 | name = "tracing-tree" | 1784 | name = "tracing-tree" |
1764 | version = "0.1.8" | 1785 | version = "0.1.9" |
1765 | source = "registry+https://github.com/rust-lang/crates.io-index" | 1786 | source = "registry+https://github.com/rust-lang/crates.io-index" |
1766 | checksum = "1a60657cfbf397c603257a8230b3f427e6a2a4e5911a59331b9bb4dffff5b608" | 1787 | checksum = "1712b40907f8d9bc2bc66763ab61dec914b7123d7149e59feb0d4e2a95fc4967" |
1767 | dependencies = [ | 1788 | dependencies = [ |
1768 | "ansi_term", | 1789 | "ansi_term", |
1769 | "atty", | 1790 | "atty", |
diff --git a/crates/hir/src/lib.rs b/crates/hir/src/lib.rs index d5a3d9034..58adc8fd3 100644 --- a/crates/hir/src/lib.rs +++ b/crates/hir/src/lib.rs | |||
@@ -305,7 +305,6 @@ impl ModuleDef { | |||
305 | ModuleDef::Module(it) => it.name(db), | 305 | ModuleDef::Module(it) => it.name(db), |
306 | ModuleDef::Const(it) => it.name(db), | 306 | ModuleDef::Const(it) => it.name(db), |
307 | ModuleDef::Static(it) => it.name(db), | 307 | ModuleDef::Static(it) => it.name(db), |
308 | |||
309 | ModuleDef::BuiltinType(it) => Some(it.name()), | 308 | ModuleDef::BuiltinType(it) => Some(it.name()), |
310 | } | 309 | } |
311 | } | 310 | } |
@@ -535,7 +534,7 @@ pub struct Struct { | |||
535 | 534 | ||
536 | impl Struct { | 535 | impl Struct { |
537 | pub fn module(self, db: &dyn HirDatabase) -> Module { | 536 | pub fn module(self, db: &dyn HirDatabase) -> Module { |
538 | Module { id: self.id.lookup(db.upcast()).container.module(db.upcast()) } | 537 | Module { id: self.id.lookup(db.upcast()).container } |
539 | } | 538 | } |
540 | 539 | ||
541 | pub fn krate(self, db: &dyn HirDatabase) -> Option<Crate> { | 540 | pub fn krate(self, db: &dyn HirDatabase) -> Option<Crate> { |
@@ -556,11 +555,7 @@ impl Struct { | |||
556 | } | 555 | } |
557 | 556 | ||
558 | pub fn ty(self, db: &dyn HirDatabase) -> Type { | 557 | pub fn ty(self, db: &dyn HirDatabase) -> Type { |
559 | Type::from_def( | 558 | Type::from_def(db, self.id.lookup(db.upcast()).container.krate(), self.id) |
560 | db, | ||
561 | self.id.lookup(db.upcast()).container.module(db.upcast()).krate(), | ||
562 | self.id, | ||
563 | ) | ||
564 | } | 559 | } |
565 | 560 | ||
566 | pub fn repr(self, db: &dyn HirDatabase) -> Option<ReprKind> { | 561 | pub fn repr(self, db: &dyn HirDatabase) -> Option<ReprKind> { |
@@ -587,15 +582,11 @@ impl Union { | |||
587 | } | 582 | } |
588 | 583 | ||
589 | pub fn module(self, db: &dyn HirDatabase) -> Module { | 584 | pub fn module(self, db: &dyn HirDatabase) -> Module { |
590 | Module { id: self.id.lookup(db.upcast()).container.module(db.upcast()) } | 585 | Module { id: self.id.lookup(db.upcast()).container } |
591 | } | 586 | } |
592 | 587 | ||
593 | pub fn ty(self, db: &dyn HirDatabase) -> Type { | 588 | pub fn ty(self, db: &dyn HirDatabase) -> Type { |
594 | Type::from_def( | 589 | Type::from_def(db, self.id.lookup(db.upcast()).container.krate(), self.id) |
595 | db, | ||
596 | self.id.lookup(db.upcast()).container.module(db.upcast()).krate(), | ||
597 | self.id, | ||
598 | ) | ||
599 | } | 590 | } |
600 | 591 | ||
601 | pub fn fields(self, db: &dyn HirDatabase) -> Vec<Field> { | 592 | pub fn fields(self, db: &dyn HirDatabase) -> Vec<Field> { |
@@ -619,7 +610,7 @@ pub struct Enum { | |||
619 | 610 | ||
620 | impl Enum { | 611 | impl Enum { |
621 | pub fn module(self, db: &dyn HirDatabase) -> Module { | 612 | pub fn module(self, db: &dyn HirDatabase) -> Module { |
622 | Module { id: self.id.lookup(db.upcast()).container.module(db.upcast()) } | 613 | Module { id: self.id.lookup(db.upcast()).container } |
623 | } | 614 | } |
624 | 615 | ||
625 | pub fn krate(self, db: &dyn HirDatabase) -> Option<Crate> { | 616 | pub fn krate(self, db: &dyn HirDatabase) -> Option<Crate> { |
@@ -635,11 +626,7 @@ impl Enum { | |||
635 | } | 626 | } |
636 | 627 | ||
637 | pub fn ty(self, db: &dyn HirDatabase) -> Type { | 628 | pub fn ty(self, db: &dyn HirDatabase) -> Type { |
638 | Type::from_def( | 629 | Type::from_def(db, self.id.lookup(db.upcast()).container.krate(), self.id) |
639 | db, | ||
640 | self.id.lookup(db.upcast()).container.module(db.upcast()).krate(), | ||
641 | self.id, | ||
642 | ) | ||
643 | } | 630 | } |
644 | } | 631 | } |
645 | 632 | ||
@@ -1001,7 +988,7 @@ pub struct Trait { | |||
1001 | 988 | ||
1002 | impl Trait { | 989 | impl Trait { |
1003 | pub fn module(self, db: &dyn HirDatabase) -> Module { | 990 | pub fn module(self, db: &dyn HirDatabase) -> Module { |
1004 | Module { id: self.id.lookup(db.upcast()).container.module(db.upcast()) } | 991 | Module { id: self.id.lookup(db.upcast()).container } |
1005 | } | 992 | } |
1006 | 993 | ||
1007 | pub fn name(self, db: &dyn HirDatabase) -> Name { | 994 | pub fn name(self, db: &dyn HirDatabase) -> Name { |
@@ -1157,7 +1144,7 @@ where | |||
1157 | { | 1144 | { |
1158 | match id.lookup(db.upcast()).container { | 1145 | match id.lookup(db.upcast()).container { |
1159 | AssocContainerId::TraitId(_) | AssocContainerId::ImplId(_) => Some(ctor(DEF::from(id))), | 1146 | AssocContainerId::TraitId(_) | AssocContainerId::ImplId(_) => Some(ctor(DEF::from(id))), |
1160 | AssocContainerId::ContainerId(_) => None, | 1147 | AssocContainerId::ModuleId(_) => None, |
1161 | } | 1148 | } |
1162 | } | 1149 | } |
1163 | 1150 | ||
@@ -1185,7 +1172,7 @@ impl AssocItem { | |||
1185 | match container { | 1172 | match container { |
1186 | AssocContainerId::TraitId(id) => AssocItemContainer::Trait(id.into()), | 1173 | AssocContainerId::TraitId(id) => AssocItemContainer::Trait(id.into()), |
1187 | AssocContainerId::ImplId(id) => AssocItemContainer::Impl(id.into()), | 1174 | AssocContainerId::ImplId(id) => AssocItemContainer::Impl(id.into()), |
1188 | AssocContainerId::ContainerId(_) => panic!("invalid AssocItem"), | 1175 | AssocContainerId::ModuleId(_) => panic!("invalid AssocItem"), |
1189 | } | 1176 | } |
1190 | } | 1177 | } |
1191 | 1178 | ||
@@ -1296,13 +1283,7 @@ impl Local { | |||
1296 | 1283 | ||
1297 | pub fn is_mut(self, db: &dyn HirDatabase) -> bool { | 1284 | pub fn is_mut(self, db: &dyn HirDatabase) -> bool { |
1298 | let body = db.body(self.parent.into()); | 1285 | let body = db.body(self.parent.into()); |
1299 | match &body[self.pat_id] { | 1286 | matches!(&body[self.pat_id], Pat::Bind { mode: BindingAnnotation::Mutable, .. }) |
1300 | Pat::Bind { mode, .. } => match mode { | ||
1301 | BindingAnnotation::Mutable | BindingAnnotation::RefMut => true, | ||
1302 | _ => false, | ||
1303 | }, | ||
1304 | _ => false, | ||
1305 | } | ||
1306 | } | 1287 | } |
1307 | 1288 | ||
1308 | pub fn parent(self, _db: &dyn HirDatabase) -> DefWithBody { | 1289 | pub fn parent(self, _db: &dyn HirDatabase) -> DefWithBody { |
@@ -1516,7 +1497,7 @@ impl Impl { | |||
1516 | pub fn target_ty(self, db: &dyn HirDatabase) -> Type { | 1497 | pub fn target_ty(self, db: &dyn HirDatabase) -> Type { |
1517 | let impl_data = db.impl_data(self.id); | 1498 | let impl_data = db.impl_data(self.id); |
1518 | let resolver = self.id.resolver(db.upcast()); | 1499 | let resolver = self.id.resolver(db.upcast()); |
1519 | let krate = self.id.lookup(db.upcast()).container.module(db.upcast()).krate(); | 1500 | let krate = self.id.lookup(db.upcast()).container.krate(); |
1520 | let ctx = hir_ty::TyLoweringContext::new(db, &resolver); | 1501 | let ctx = hir_ty::TyLoweringContext::new(db, &resolver); |
1521 | let ty = Ty::from_hir(&ctx, &impl_data.target_type); | 1502 | let ty = Ty::from_hir(&ctx, &impl_data.target_type); |
1522 | Type::new_with_resolver_inner(db, krate, &resolver, ty) | 1503 | Type::new_with_resolver_inner(db, krate, &resolver, ty) |
@@ -1531,7 +1512,7 @@ impl Impl { | |||
1531 | } | 1512 | } |
1532 | 1513 | ||
1533 | pub fn module(self, db: &dyn HirDatabase) -> Module { | 1514 | pub fn module(self, db: &dyn HirDatabase) -> Module { |
1534 | self.id.lookup(db.upcast()).container.module(db.upcast()).into() | 1515 | self.id.lookup(db.upcast()).container.into() |
1535 | } | 1516 | } |
1536 | 1517 | ||
1537 | pub fn krate(self, db: &dyn HirDatabase) -> Crate { | 1518 | pub fn krate(self, db: &dyn HirDatabase) -> Crate { |
@@ -1614,10 +1595,9 @@ impl Type { | |||
1614 | } | 1595 | } |
1615 | 1596 | ||
1616 | pub fn remove_ref(&self) -> Option<Type> { | 1597 | pub fn remove_ref(&self) -> Option<Type> { |
1617 | if let Ty::Ref(.., substs) = &self.ty.value { | 1598 | match &self.ty.value { |
1618 | Some(self.derived(substs[0].clone())) | 1599 | Ty::Ref(.., substs) => Some(self.derived(substs[0].clone())), |
1619 | } else { | 1600 | _ => None, |
1620 | None | ||
1621 | } | 1601 | } |
1622 | } | 1602 | } |
1623 | 1603 | ||
diff --git a/crates/hir_def/Cargo.toml b/crates/hir_def/Cargo.toml index 2f07b6d01..c2d99280f 100644 --- a/crates/hir_def/Cargo.toml +++ b/crates/hir_def/Cargo.toml | |||
@@ -28,10 +28,10 @@ base_db = { path = "../base_db", version = "0.0.0" } | |||
28 | syntax = { path = "../syntax", version = "0.0.0" } | 28 | syntax = { path = "../syntax", version = "0.0.0" } |
29 | profile = { path = "../profile", version = "0.0.0" } | 29 | profile = { path = "../profile", version = "0.0.0" } |
30 | hir_expand = { path = "../hir_expand", version = "0.0.0" } | 30 | hir_expand = { path = "../hir_expand", version = "0.0.0" } |
31 | test_utils = { path = "../test_utils", version = "0.0.0" } | ||
32 | mbe = { path = "../mbe", version = "0.0.0" } | 31 | mbe = { path = "../mbe", version = "0.0.0" } |
33 | cfg = { path = "../cfg", version = "0.0.0" } | 32 | cfg = { path = "../cfg", version = "0.0.0" } |
34 | tt = { path = "../tt", version = "0.0.0" } | 33 | tt = { path = "../tt", version = "0.0.0" } |
35 | 34 | ||
36 | [dev-dependencies] | 35 | [dev-dependencies] |
36 | test_utils = { path = "../test_utils" } | ||
37 | expect-test = "1.1" | 37 | expect-test = "1.1" |
diff --git a/crates/hir_def/src/adt.rs b/crates/hir_def/src/adt.rs index ed36c3109..efbde17d8 100644 --- a/crates/hir_def/src/adt.rs +++ b/crates/hir_def/src/adt.rs | |||
@@ -21,8 +21,7 @@ use crate::{ | |||
21 | trace::Trace, | 21 | trace::Trace, |
22 | type_ref::TypeRef, | 22 | type_ref::TypeRef, |
23 | visibility::RawVisibility, | 23 | visibility::RawVisibility, |
24 | EnumId, HasModule, LocalEnumVariantId, LocalFieldId, Lookup, ModuleId, StructId, UnionId, | 24 | EnumId, LocalEnumVariantId, LocalFieldId, Lookup, ModuleId, StructId, UnionId, VariantId, |
25 | VariantId, | ||
26 | }; | 25 | }; |
27 | use cfg::CfgOptions; | 26 | use cfg::CfgOptions; |
28 | 27 | ||
@@ -92,10 +91,10 @@ fn parse_repr_tt(tt: &Subtree) -> Option<ReprKind> { | |||
92 | impl StructData { | 91 | impl StructData { |
93 | pub(crate) fn struct_data_query(db: &dyn DefDatabase, id: StructId) -> Arc<StructData> { | 92 | pub(crate) fn struct_data_query(db: &dyn DefDatabase, id: StructId) -> Arc<StructData> { |
94 | let loc = id.lookup(db); | 93 | let loc = id.lookup(db); |
95 | let krate = loc.container.module(db).krate; | 94 | let krate = loc.container.krate; |
96 | let item_tree = db.item_tree(loc.id.file_id); | 95 | let item_tree = db.item_tree(loc.id.file_id); |
97 | let repr = repr_from_value(db, krate, &item_tree, ModItem::from(loc.id.value).into()); | 96 | let repr = repr_from_value(db, krate, &item_tree, ModItem::from(loc.id.value).into()); |
98 | let cfg_options = db.crate_graph()[loc.container.module(db).krate].cfg_options.clone(); | 97 | let cfg_options = db.crate_graph()[loc.container.krate].cfg_options.clone(); |
99 | 98 | ||
100 | let strukt = &item_tree[loc.id.value]; | 99 | let strukt = &item_tree[loc.id.value]; |
101 | let variant_data = lower_fields(db, krate, &item_tree, &cfg_options, &strukt.fields, None); | 100 | let variant_data = lower_fields(db, krate, &item_tree, &cfg_options, &strukt.fields, None); |
@@ -107,10 +106,10 @@ impl StructData { | |||
107 | } | 106 | } |
108 | pub(crate) fn union_data_query(db: &dyn DefDatabase, id: UnionId) -> Arc<StructData> { | 107 | pub(crate) fn union_data_query(db: &dyn DefDatabase, id: UnionId) -> Arc<StructData> { |
109 | let loc = id.lookup(db); | 108 | let loc = id.lookup(db); |
110 | let krate = loc.container.module(db).krate; | 109 | let krate = loc.container.krate; |
111 | let item_tree = db.item_tree(loc.id.file_id); | 110 | let item_tree = db.item_tree(loc.id.file_id); |
112 | let repr = repr_from_value(db, krate, &item_tree, ModItem::from(loc.id.value).into()); | 111 | let repr = repr_from_value(db, krate, &item_tree, ModItem::from(loc.id.value).into()); |
113 | let cfg_options = db.crate_graph()[loc.container.module(db).krate].cfg_options.clone(); | 112 | let cfg_options = db.crate_graph()[loc.container.krate].cfg_options.clone(); |
114 | 113 | ||
115 | let union = &item_tree[loc.id.value]; | 114 | let union = &item_tree[loc.id.value]; |
116 | let variant_data = lower_fields(db, krate, &item_tree, &cfg_options, &union.fields, None); | 115 | let variant_data = lower_fields(db, krate, &item_tree, &cfg_options, &union.fields, None); |
@@ -126,7 +125,7 @@ impl StructData { | |||
126 | impl EnumData { | 125 | impl EnumData { |
127 | pub(crate) fn enum_data_query(db: &dyn DefDatabase, e: EnumId) -> Arc<EnumData> { | 126 | pub(crate) fn enum_data_query(db: &dyn DefDatabase, e: EnumId) -> Arc<EnumData> { |
128 | let loc = e.lookup(db); | 127 | let loc = e.lookup(db); |
129 | let krate = loc.container.module(db).krate; | 128 | let krate = loc.container.krate; |
130 | let item_tree = db.item_tree(loc.id.file_id); | 129 | let item_tree = db.item_tree(loc.id.file_id); |
131 | let cfg_options = db.crate_graph()[krate].cfg_options.clone(); | 130 | let cfg_options = db.crate_graph()[krate].cfg_options.clone(); |
132 | 131 | ||
@@ -168,7 +167,7 @@ impl HasChildSource<LocalEnumVariantId> for EnumId { | |||
168 | ) -> InFile<ArenaMap<LocalEnumVariantId, Self::Value>> { | 167 | ) -> InFile<ArenaMap<LocalEnumVariantId, Self::Value>> { |
169 | let src = self.lookup(db).source(db); | 168 | let src = self.lookup(db).source(db); |
170 | let mut trace = Trace::new_for_map(); | 169 | let mut trace = Trace::new_for_map(); |
171 | lower_enum(db, &mut trace, &src, self.lookup(db).container.module(db)); | 170 | lower_enum(db, &mut trace, &src, self.lookup(db).container); |
172 | src.with_value(trace.into_map()) | 171 | src.with_value(trace.into_map()) |
173 | } | 172 | } |
174 | } | 173 | } |
@@ -238,10 +237,10 @@ impl HasChildSource<LocalFieldId> for VariantId { | |||
238 | // I don't really like the fact that we call into parent source | 237 | // I don't really like the fact that we call into parent source |
239 | // here, this might add to more queries then necessary. | 238 | // here, this might add to more queries then necessary. |
240 | let src = it.parent.child_source(db); | 239 | let src = it.parent.child_source(db); |
241 | (src.map(|map| map[it.local_id].kind()), it.parent.lookup(db).container.module(db)) | 240 | (src.map(|map| map[it.local_id].kind()), it.parent.lookup(db).container) |
242 | } | 241 | } |
243 | VariantId::StructId(it) => { | 242 | VariantId::StructId(it) => { |
244 | (it.lookup(db).source(db).map(|it| it.kind()), it.lookup(db).container.module(db)) | 243 | (it.lookup(db).source(db).map(|it| it.kind()), it.lookup(db).container) |
245 | } | 244 | } |
246 | VariantId::UnionId(it) => ( | 245 | VariantId::UnionId(it) => ( |
247 | it.lookup(db).source(db).map(|it| { | 246 | it.lookup(db).source(db).map(|it| { |
@@ -249,7 +248,7 @@ impl HasChildSource<LocalFieldId> for VariantId { | |||
249 | .map(ast::StructKind::Record) | 248 | .map(ast::StructKind::Record) |
250 | .unwrap_or(ast::StructKind::Unit) | 249 | .unwrap_or(ast::StructKind::Unit) |
251 | }), | 250 | }), |
252 | it.lookup(db).container.module(db), | 251 | it.lookup(db).container, |
253 | ), | 252 | ), |
254 | }; | 253 | }; |
255 | let mut expander = CfgExpander::new(db, src.file_id, module_id.krate); | 254 | let mut expander = CfgExpander::new(db, src.file_id, module_id.krate); |
diff --git a/crates/hir_def/src/attr.rs b/crates/hir_def/src/attr.rs index b716d5f6e..97cdbbb9e 100644 --- a/crates/hir_def/src/attr.rs +++ b/crates/hir_def/src/attr.rs | |||
@@ -267,7 +267,7 @@ impl Attrs { | |||
267 | db: &dyn DefDatabase, | 267 | db: &dyn DefDatabase, |
268 | e: EnumId, | 268 | e: EnumId, |
269 | ) -> Arc<ArenaMap<LocalEnumVariantId, Attrs>> { | 269 | ) -> Arc<ArenaMap<LocalEnumVariantId, Attrs>> { |
270 | let krate = e.lookup(db).container.module(db).krate; | 270 | let krate = e.lookup(db).container.krate; |
271 | let src = e.child_source(db); | 271 | let src = e.child_source(db); |
272 | let mut res = ArenaMap::default(); | 272 | let mut res = ArenaMap::default(); |
273 | 273 | ||
diff --git a/crates/hir_def/src/body.rs b/crates/hir_def/src/body.rs index b1a3fe1cb..19c4eb521 100644 --- a/crates/hir_def/src/body.rs +++ b/crates/hir_def/src/body.rs | |||
@@ -28,11 +28,10 @@ use crate::{ | |||
28 | db::DefDatabase, | 28 | db::DefDatabase, |
29 | expr::{Expr, ExprId, Label, LabelId, Pat, PatId}, | 29 | expr::{Expr, ExprId, Label, LabelId, Pat, PatId}, |
30 | item_scope::BuiltinShadowMode, | 30 | item_scope::BuiltinShadowMode, |
31 | item_scope::ItemScope, | ||
32 | nameres::DefMap, | 31 | nameres::DefMap, |
33 | path::{ModPath, Path}, | 32 | path::{ModPath, Path}, |
34 | src::HasSource, | 33 | src::HasSource, |
35 | AsMacroCall, DefWithBodyId, HasModule, LocalModuleId, Lookup, ModuleId, | 34 | AsMacroCall, BlockId, DefWithBodyId, HasModule, LocalModuleId, Lookup, ModuleId, |
36 | }; | 35 | }; |
37 | 36 | ||
38 | /// A subset of Expander that only deals with cfg attributes. We only need it to | 37 | /// A subset of Expander that only deals with cfg attributes. We only need it to |
@@ -226,7 +225,8 @@ pub struct Body { | |||
226 | pub params: Vec<PatId>, | 225 | pub params: Vec<PatId>, |
227 | /// The `ExprId` of the actual body expression. | 226 | /// The `ExprId` of the actual body expression. |
228 | pub body_expr: ExprId, | 227 | pub body_expr: ExprId, |
229 | pub item_scope: ItemScope, | 228 | /// Block expressions in this body that may contain inner items. |
229 | pub block_scopes: Vec<BlockId>, | ||
230 | _c: Count<Self>, | 230 | _c: Count<Self>, |
231 | } | 231 | } |
232 | 232 | ||
@@ -295,7 +295,7 @@ impl Body { | |||
295 | } | 295 | } |
296 | }; | 296 | }; |
297 | let expander = Expander::new(db, file_id, module); | 297 | let expander = Expander::new(db, file_id, module); |
298 | let (body, source_map) = Body::new(db, def, expander, params, body); | 298 | let (body, source_map) = Body::new(db, expander, params, body); |
299 | (Arc::new(body), Arc::new(source_map)) | 299 | (Arc::new(body), Arc::new(source_map)) |
300 | } | 300 | } |
301 | 301 | ||
@@ -305,12 +305,11 @@ impl Body { | |||
305 | 305 | ||
306 | fn new( | 306 | fn new( |
307 | db: &dyn DefDatabase, | 307 | db: &dyn DefDatabase, |
308 | def: DefWithBodyId, | ||
309 | expander: Expander, | 308 | expander: Expander, |
310 | params: Option<ast::ParamList>, | 309 | params: Option<ast::ParamList>, |
311 | body: Option<ast::Expr>, | 310 | body: Option<ast::Expr>, |
312 | ) -> (Body, BodySourceMap) { | 311 | ) -> (Body, BodySourceMap) { |
313 | lower::lower(db, def, expander, params, body) | 312 | lower::lower(db, expander, params, body) |
314 | } | 313 | } |
315 | } | 314 | } |
316 | 315 | ||
diff --git a/crates/hir_def/src/body/lower.rs b/crates/hir_def/src/body/lower.rs index d4abe819d..8c8eb8007 100644 --- a/crates/hir_def/src/body/lower.rs +++ b/crates/hir_def/src/body/lower.rs | |||
@@ -1,17 +1,16 @@ | |||
1 | //! Transforms `ast::Expr` into an equivalent `hir_def::expr::Expr` | 1 | //! Transforms `ast::Expr` into an equivalent `hir_def::expr::Expr` |
2 | //! representation. | 2 | //! representation. |
3 | 3 | ||
4 | use std::{any::type_name, mem, sync::Arc}; | 4 | use std::mem; |
5 | 5 | ||
6 | use either::Either; | 6 | use either::Either; |
7 | use hir_expand::{ | 7 | use hir_expand::{ |
8 | hygiene::Hygiene, | 8 | hygiene::Hygiene, |
9 | name::{name, AsName, Name}, | 9 | name::{name, AsName, Name}, |
10 | ExpandError, HirFileId, MacroDefId, MacroDefKind, | 10 | ExpandError, HirFileId, |
11 | }; | 11 | }; |
12 | use la_arena::Arena; | 12 | use la_arena::Arena; |
13 | use profile::Count; | 13 | use profile::Count; |
14 | use rustc_hash::FxHashMap; | ||
15 | use syntax::{ | 14 | use syntax::{ |
16 | ast::{ | 15 | ast::{ |
17 | self, ArgListOwner, ArrayExprKind, AstChildren, LiteralKind, LoopBodyOwner, NameOwner, | 16 | self, ArgListOwner, ArrayExprKind, AstChildren, LiteralKind, LoopBodyOwner, NameOwner, |
@@ -32,11 +31,9 @@ use crate::{ | |||
32 | Statement, | 31 | Statement, |
33 | }, | 32 | }, |
34 | item_scope::BuiltinShadowMode, | 33 | item_scope::BuiltinShadowMode, |
35 | item_tree::{ItemTree, ItemTreeId, ItemTreeNode}, | ||
36 | path::{GenericArgs, Path}, | 34 | path::{GenericArgs, Path}, |
37 | type_ref::{Mutability, Rawness, TypeRef}, | 35 | type_ref::{Mutability, Rawness, TypeRef}, |
38 | AdtId, BlockLoc, ConstLoc, ContainerId, DefWithBodyId, EnumLoc, FunctionLoc, Intern, | 36 | AdtId, BlockLoc, ModuleDefId, |
39 | ModuleDefId, StaticLoc, StructLoc, TraitLoc, TypeAliasLoc, UnionLoc, | ||
40 | }; | 37 | }; |
41 | 38 | ||
42 | use super::{diagnostics::BodyDiagnostic, ExprSource, PatSource}; | 39 | use super::{diagnostics::BodyDiagnostic, ExprSource, PatSource}; |
@@ -60,15 +57,12 @@ impl LowerCtx { | |||
60 | 57 | ||
61 | pub(super) fn lower( | 58 | pub(super) fn lower( |
62 | db: &dyn DefDatabase, | 59 | db: &dyn DefDatabase, |
63 | def: DefWithBodyId, | ||
64 | expander: Expander, | 60 | expander: Expander, |
65 | params: Option<ast::ParamList>, | 61 | params: Option<ast::ParamList>, |
66 | body: Option<ast::Expr>, | 62 | body: Option<ast::Expr>, |
67 | ) -> (Body, BodySourceMap) { | 63 | ) -> (Body, BodySourceMap) { |
68 | let item_tree = db.item_tree(expander.current_file_id); | ||
69 | ExprCollector { | 64 | ExprCollector { |
70 | db, | 65 | db, |
71 | def, | ||
72 | source_map: BodySourceMap::default(), | 66 | source_map: BodySourceMap::default(), |
73 | body: Body { | 67 | body: Body { |
74 | exprs: Arena::default(), | 68 | exprs: Arena::default(), |
@@ -76,14 +70,9 @@ pub(super) fn lower( | |||
76 | labels: Arena::default(), | 70 | labels: Arena::default(), |
77 | params: Vec::new(), | 71 | params: Vec::new(), |
78 | body_expr: dummy_expr_id(), | 72 | body_expr: dummy_expr_id(), |
79 | item_scope: Default::default(), | 73 | block_scopes: Vec::new(), |
80 | _c: Count::new(), | 74 | _c: Count::new(), |
81 | }, | 75 | }, |
82 | item_trees: { | ||
83 | let mut map = FxHashMap::default(); | ||
84 | map.insert(expander.current_file_id, item_tree); | ||
85 | map | ||
86 | }, | ||
87 | expander, | 76 | expander, |
88 | } | 77 | } |
89 | .collect(params, body) | 78 | .collect(params, body) |
@@ -91,12 +80,9 @@ pub(super) fn lower( | |||
91 | 80 | ||
92 | struct ExprCollector<'a> { | 81 | struct ExprCollector<'a> { |
93 | db: &'a dyn DefDatabase, | 82 | db: &'a dyn DefDatabase, |
94 | def: DefWithBodyId, | ||
95 | expander: Expander, | 83 | expander: Expander, |
96 | body: Body, | 84 | body: Body, |
97 | source_map: BodySourceMap, | 85 | source_map: BodySourceMap, |
98 | |||
99 | item_trees: FxHashMap<HirFileId, Arc<ItemTree>>, | ||
100 | } | 86 | } |
101 | 87 | ||
102 | impl ExprCollector<'_> { | 88 | impl ExprCollector<'_> { |
@@ -593,9 +579,6 @@ impl ExprCollector<'_> { | |||
593 | } else { | 579 | } else { |
594 | self.source_map.expansions.insert(macro_call, self.expander.current_file_id); | 580 | self.source_map.expansions.insert(macro_call, self.expander.current_file_id); |
595 | 581 | ||
596 | let item_tree = self.db.item_tree(self.expander.current_file_id); | ||
597 | self.item_trees.insert(self.expander.current_file_id, item_tree); | ||
598 | |||
599 | let id = collector(self, Some(expansion)); | 582 | let id = collector(self, Some(expansion)); |
600 | self.expander.exit(self.db, mark); | 583 | self.expander.exit(self.db, mark); |
601 | id | 584 | id |
@@ -605,32 +588,6 @@ impl ExprCollector<'_> { | |||
605 | } | 588 | } |
606 | } | 589 | } |
607 | 590 | ||
608 | fn find_inner_item<N: ItemTreeNode>(&self, ast: &N::Source) -> Option<ItemTreeId<N>> { | ||
609 | let id = self.expander.ast_id(ast); | ||
610 | let tree = &self.item_trees[&id.file_id]; | ||
611 | |||
612 | // FIXME: This probably breaks with `use` items, since they produce multiple item tree nodes | ||
613 | |||
614 | // Root file (non-macro). | ||
615 | let item_tree_id = tree | ||
616 | .all_inner_items() | ||
617 | .chain(tree.top_level_items().iter().copied()) | ||
618 | .filter_map(|mod_item| mod_item.downcast::<N>()) | ||
619 | .find(|tree_id| tree[*tree_id].ast_id().upcast() == id.value.upcast()) | ||
620 | .or_else(|| { | ||
621 | log::debug!( | ||
622 | "couldn't find inner {} item for {:?} (AST: `{}` - {:?})", | ||
623 | type_name::<N>(), | ||
624 | id, | ||
625 | ast.syntax(), | ||
626 | ast.syntax(), | ||
627 | ); | ||
628 | None | ||
629 | })?; | ||
630 | |||
631 | Some(ItemTreeId::new(id.file_id, item_tree_id)) | ||
632 | } | ||
633 | |||
634 | fn collect_expr_opt(&mut self, expr: Option<ast::Expr>) -> ExprId { | 591 | fn collect_expr_opt(&mut self, expr: Option<ast::Expr>) -> ExprId { |
635 | if let Some(expr) = expr { | 592 | if let Some(expr) = expr { |
636 | self.collect_expr(expr) | 593 | self.collect_expr(expr) |
@@ -662,7 +619,6 @@ impl ExprCollector<'_> { | |||
662 | match expansion { | 619 | match expansion { |
663 | Some(expansion) => { | 620 | Some(expansion) => { |
664 | let statements: ast::MacroStmts = expansion; | 621 | let statements: ast::MacroStmts = expansion; |
665 | this.collect_stmts_items(statements.statements()); | ||
666 | 622 | ||
667 | statements.statements().for_each(|stmt| { | 623 | statements.statements().for_each(|stmt| { |
668 | if let Some(mut r) = this.collect_stmt(stmt) { | 624 | if let Some(mut r) = this.collect_stmt(stmt) { |
@@ -700,6 +656,8 @@ impl ExprCollector<'_> { | |||
700 | let block_loc = | 656 | let block_loc = |
701 | BlockLoc { ast_id, module: self.expander.def_map.module_id(self.expander.module) }; | 657 | BlockLoc { ast_id, module: self.expander.def_map.module_id(self.expander.module) }; |
702 | let block_id = self.db.intern_block(block_loc); | 658 | let block_id = self.db.intern_block(block_loc); |
659 | self.body.block_scopes.push(block_id); | ||
660 | |||
703 | let opt_def_map = self.db.block_def_map(block_id); | 661 | let opt_def_map = self.db.block_def_map(block_id); |
704 | let has_def_map = opt_def_map.is_some(); | 662 | let has_def_map = opt_def_map.is_some(); |
705 | let def_map = opt_def_map.unwrap_or_else(|| self.expander.def_map.clone()); | 663 | let def_map = opt_def_map.unwrap_or_else(|| self.expander.def_map.clone()); |
@@ -707,7 +665,6 @@ impl ExprCollector<'_> { | |||
707 | let prev_def_map = mem::replace(&mut self.expander.def_map, def_map); | 665 | let prev_def_map = mem::replace(&mut self.expander.def_map, def_map); |
708 | let prev_local_module = mem::replace(&mut self.expander.module, module); | 666 | let prev_local_module = mem::replace(&mut self.expander.module, module); |
709 | 667 | ||
710 | self.collect_stmts_items(block.statements()); | ||
711 | let statements = | 668 | let statements = |
712 | block.statements().filter_map(|s| self.collect_stmt(s)).flatten().collect(); | 669 | block.statements().filter_map(|s| self.collect_stmt(s)).flatten().collect(); |
713 | let tail = block.tail_expr().map(|e| self.collect_expr(e)); | 670 | let tail = block.tail_expr().map(|e| self.collect_expr(e)); |
@@ -722,108 +679,6 @@ impl ExprCollector<'_> { | |||
722 | expr_id | 679 | expr_id |
723 | } | 680 | } |
724 | 681 | ||
725 | fn collect_stmts_items(&mut self, stmts: ast::AstChildren<ast::Stmt>) { | ||
726 | let container = ContainerId::DefWithBodyId(self.def); | ||
727 | |||
728 | let items = stmts | ||
729 | .filter_map(|stmt| match stmt { | ||
730 | ast::Stmt::Item(it) => Some(it), | ||
731 | ast::Stmt::LetStmt(_) | ast::Stmt::ExprStmt(_) => None, | ||
732 | }) | ||
733 | .filter_map(|item| { | ||
734 | let (def, name): (ModuleDefId, Option<ast::Name>) = match item { | ||
735 | ast::Item::Fn(def) => { | ||
736 | let id = self.find_inner_item(&def)?; | ||
737 | ( | ||
738 | FunctionLoc { container: container.into(), id }.intern(self.db).into(), | ||
739 | def.name(), | ||
740 | ) | ||
741 | } | ||
742 | ast::Item::TypeAlias(def) => { | ||
743 | let id = self.find_inner_item(&def)?; | ||
744 | ( | ||
745 | TypeAliasLoc { container: container.into(), id }.intern(self.db).into(), | ||
746 | def.name(), | ||
747 | ) | ||
748 | } | ||
749 | ast::Item::Const(def) => { | ||
750 | let id = self.find_inner_item(&def)?; | ||
751 | ( | ||
752 | ConstLoc { container: container.into(), id }.intern(self.db).into(), | ||
753 | def.name(), | ||
754 | ) | ||
755 | } | ||
756 | ast::Item::Static(def) => { | ||
757 | let id = self.find_inner_item(&def)?; | ||
758 | (StaticLoc { container, id }.intern(self.db).into(), def.name()) | ||
759 | } | ||
760 | ast::Item::Struct(def) => { | ||
761 | let id = self.find_inner_item(&def)?; | ||
762 | (StructLoc { container, id }.intern(self.db).into(), def.name()) | ||
763 | } | ||
764 | ast::Item::Enum(def) => { | ||
765 | let id = self.find_inner_item(&def)?; | ||
766 | (EnumLoc { container, id }.intern(self.db).into(), def.name()) | ||
767 | } | ||
768 | ast::Item::Union(def) => { | ||
769 | let id = self.find_inner_item(&def)?; | ||
770 | (UnionLoc { container, id }.intern(self.db).into(), def.name()) | ||
771 | } | ||
772 | ast::Item::Trait(def) => { | ||
773 | let id = self.find_inner_item(&def)?; | ||
774 | (TraitLoc { container, id }.intern(self.db).into(), def.name()) | ||
775 | } | ||
776 | ast::Item::ExternBlock(_) => return None, // FIXME: collect from extern blocks | ||
777 | ast::Item::Impl(_) | ||
778 | | ast::Item::Use(_) | ||
779 | | ast::Item::ExternCrate(_) | ||
780 | | ast::Item::Module(_) | ||
781 | | ast::Item::MacroCall(_) => return None, | ||
782 | ast::Item::MacroRules(def) => { | ||
783 | return Some(Either::Right(ast::Macro::from(def))); | ||
784 | } | ||
785 | ast::Item::MacroDef(def) => { | ||
786 | return Some(Either::Right(ast::Macro::from(def))); | ||
787 | } | ||
788 | }; | ||
789 | |||
790 | Some(Either::Left((def, name))) | ||
791 | }) | ||
792 | .collect::<Vec<_>>(); | ||
793 | |||
794 | for either in items { | ||
795 | match either { | ||
796 | Either::Left((def, name)) => { | ||
797 | self.body.item_scope.define_def(def); | ||
798 | if let Some(name) = name { | ||
799 | let vis = crate::visibility::Visibility::Public; // FIXME determine correctly | ||
800 | let has_constructor = match def { | ||
801 | ModuleDefId::AdtId(AdtId::StructId(s)) => { | ||
802 | self.db.struct_data(s).variant_data.kind() != StructKind::Record | ||
803 | } | ||
804 | _ => true, | ||
805 | }; | ||
806 | self.body.item_scope.push_res( | ||
807 | name.as_name(), | ||
808 | crate::per_ns::PerNs::from_def(def, vis, has_constructor), | ||
809 | ); | ||
810 | } | ||
811 | } | ||
812 | Either::Right(e) => { | ||
813 | let mac = MacroDefId { | ||
814 | krate: self.expander.def_map.krate(), | ||
815 | ast_id: Some(self.expander.ast_id(&e)), | ||
816 | kind: MacroDefKind::Declarative, | ||
817 | local_inner: false, | ||
818 | }; | ||
819 | if let Some(name) = e.name() { | ||
820 | self.body.item_scope.define_legacy_macro(name.as_name(), mac); | ||
821 | } | ||
822 | } | ||
823 | } | ||
824 | } | ||
825 | } | ||
826 | |||
827 | fn collect_block_opt(&mut self, expr: Option<ast::BlockExpr>) -> ExprId { | 682 | fn collect_block_opt(&mut self, expr: Option<ast::BlockExpr>) -> ExprId { |
828 | if let Some(block) = expr { | 683 | if let Some(block) = expr { |
829 | self.collect_block(block) | 684 | self.collect_block(block) |
diff --git a/crates/hir_def/src/child_by_source.rs b/crates/hir_def/src/child_by_source.rs index 75c2d756b..2a331dcaf 100644 --- a/crates/hir_def/src/child_by_source.rs +++ b/crates/hir_def/src/child_by_source.rs | |||
@@ -17,13 +17,16 @@ use crate::{ | |||
17 | }; | 17 | }; |
18 | 18 | ||
19 | pub trait ChildBySource { | 19 | pub trait ChildBySource { |
20 | fn child_by_source(&self, db: &dyn DefDatabase) -> DynMap; | ||
21 | } | ||
22 | |||
23 | impl ChildBySource for TraitId { | ||
24 | fn child_by_source(&self, db: &dyn DefDatabase) -> DynMap { | 20 | fn child_by_source(&self, db: &dyn DefDatabase) -> DynMap { |
25 | let mut res = DynMap::default(); | 21 | let mut res = DynMap::default(); |
22 | self.child_by_source_to(db, &mut res); | ||
23 | res | ||
24 | } | ||
25 | fn child_by_source_to(&self, db: &dyn DefDatabase, map: &mut DynMap); | ||
26 | } | ||
26 | 27 | ||
28 | impl ChildBySource for TraitId { | ||
29 | fn child_by_source_to(&self, db: &dyn DefDatabase, res: &mut DynMap) { | ||
27 | let data = db.trait_data(*self); | 30 | let data = db.trait_data(*self); |
28 | for (_name, item) in data.items.iter() { | 31 | for (_name, item) in data.items.iter() { |
29 | match *item { | 32 | match *item { |
@@ -41,15 +44,11 @@ impl ChildBySource for TraitId { | |||
41 | } | 44 | } |
42 | } | 45 | } |
43 | } | 46 | } |
44 | |||
45 | res | ||
46 | } | 47 | } |
47 | } | 48 | } |
48 | 49 | ||
49 | impl ChildBySource for ImplId { | 50 | impl ChildBySource for ImplId { |
50 | fn child_by_source(&self, db: &dyn DefDatabase) -> DynMap { | 51 | fn child_by_source_to(&self, db: &dyn DefDatabase, res: &mut DynMap) { |
51 | let mut res = DynMap::default(); | ||
52 | |||
53 | let data = db.impl_data(*self); | 52 | let data = db.impl_data(*self); |
54 | for &item in data.items.iter() { | 53 | for &item in data.items.iter() { |
55 | match item { | 54 | match item { |
@@ -67,25 +66,21 @@ impl ChildBySource for ImplId { | |||
67 | } | 66 | } |
68 | } | 67 | } |
69 | } | 68 | } |
70 | |||
71 | res | ||
72 | } | 69 | } |
73 | } | 70 | } |
74 | 71 | ||
75 | impl ChildBySource for ModuleId { | 72 | impl ChildBySource for ModuleId { |
76 | fn child_by_source(&self, db: &dyn DefDatabase) -> DynMap { | 73 | fn child_by_source_to(&self, db: &dyn DefDatabase, res: &mut DynMap) { |
77 | let def_map = self.def_map(db); | 74 | let def_map = self.def_map(db); |
78 | let module_data = &def_map[self.local_id]; | 75 | let module_data = &def_map[self.local_id]; |
79 | module_data.scope.child_by_source(db) | 76 | module_data.scope.child_by_source_to(db, res); |
80 | } | 77 | } |
81 | } | 78 | } |
82 | 79 | ||
83 | impl ChildBySource for ItemScope { | 80 | impl ChildBySource for ItemScope { |
84 | fn child_by_source(&self, db: &dyn DefDatabase) -> DynMap { | 81 | fn child_by_source_to(&self, db: &dyn DefDatabase, res: &mut DynMap) { |
85 | let mut res = DynMap::default(); | 82 | self.declarations().for_each(|item| add_module_def(db, res, item)); |
86 | self.declarations().for_each(|item| add_module_def(db, &mut res, item)); | 83 | self.impls().for_each(|imp| add_impl(db, res, imp)); |
87 | self.impls().for_each(|imp| add_impl(db, &mut res, imp)); | ||
88 | return res; | ||
89 | 84 | ||
90 | fn add_module_def(db: &dyn DefDatabase, map: &mut DynMap, item: ModuleDefId) { | 85 | fn add_module_def(db: &dyn DefDatabase, map: &mut DynMap, item: ModuleDefId) { |
91 | match item { | 86 | match item { |
@@ -134,9 +129,7 @@ impl ChildBySource for ItemScope { | |||
134 | } | 129 | } |
135 | 130 | ||
136 | impl ChildBySource for VariantId { | 131 | impl ChildBySource for VariantId { |
137 | fn child_by_source(&self, db: &dyn DefDatabase) -> DynMap { | 132 | fn child_by_source_to(&self, db: &dyn DefDatabase, res: &mut DynMap) { |
138 | let mut res = DynMap::default(); | ||
139 | |||
140 | let arena_map = self.child_source(db); | 133 | let arena_map = self.child_source(db); |
141 | let arena_map = arena_map.as_ref(); | 134 | let arena_map = arena_map.as_ref(); |
142 | for (local_id, source) in arena_map.value.iter() { | 135 | for (local_id, source) in arena_map.value.iter() { |
@@ -150,28 +143,27 @@ impl ChildBySource for VariantId { | |||
150 | } | 143 | } |
151 | } | 144 | } |
152 | } | 145 | } |
153 | res | ||
154 | } | 146 | } |
155 | } | 147 | } |
156 | 148 | ||
157 | impl ChildBySource for EnumId { | 149 | impl ChildBySource for EnumId { |
158 | fn child_by_source(&self, db: &dyn DefDatabase) -> DynMap { | 150 | fn child_by_source_to(&self, db: &dyn DefDatabase, res: &mut DynMap) { |
159 | let mut res = DynMap::default(); | ||
160 | |||
161 | let arena_map = self.child_source(db); | 151 | let arena_map = self.child_source(db); |
162 | let arena_map = arena_map.as_ref(); | 152 | let arena_map = arena_map.as_ref(); |
163 | for (local_id, source) in arena_map.value.iter() { | 153 | for (local_id, source) in arena_map.value.iter() { |
164 | let id = EnumVariantId { parent: *self, local_id }; | 154 | let id = EnumVariantId { parent: *self, local_id }; |
165 | res[keys::VARIANT].insert(arena_map.with_value(source.clone()), id) | 155 | res[keys::VARIANT].insert(arena_map.with_value(source.clone()), id) |
166 | } | 156 | } |
167 | |||
168 | res | ||
169 | } | 157 | } |
170 | } | 158 | } |
171 | 159 | ||
172 | impl ChildBySource for DefWithBodyId { | 160 | impl ChildBySource for DefWithBodyId { |
173 | fn child_by_source(&self, db: &dyn DefDatabase) -> DynMap { | 161 | fn child_by_source_to(&self, db: &dyn DefDatabase, res: &mut DynMap) { |
174 | let body = db.body(*self); | 162 | let body = db.body(*self); |
175 | body.item_scope.child_by_source(db) | 163 | for def_map in body.block_scopes.iter().filter_map(|block| db.block_def_map(*block)) { |
164 | // All block expressions are merged into the same map, because they logically all add | ||
165 | // inner items to the containing `DefWithBodyId`. | ||
166 | def_map[def_map.root()].scope.child_by_source_to(db, res); | ||
167 | } | ||
176 | } | 168 | } |
177 | } | 169 | } |
diff --git a/crates/hir_def/src/data.rs b/crates/hir_def/src/data.rs index d3380e0f4..aea53d527 100644 --- a/crates/hir_def/src/data.rs +++ b/crates/hir_def/src/data.rs | |||
@@ -97,7 +97,7 @@ impl TraitData { | |||
97 | let tr_def = &item_tree[tr_loc.id.value]; | 97 | let tr_def = &item_tree[tr_loc.id.value]; |
98 | let name = tr_def.name.clone(); | 98 | let name = tr_def.name.clone(); |
99 | let auto = tr_def.auto; | 99 | let auto = tr_def.auto; |
100 | let module_id = tr_loc.container.module(db); | 100 | let module_id = tr_loc.container; |
101 | let container = AssocContainerId::TraitId(tr); | 101 | let container = AssocContainerId::TraitId(tr); |
102 | let mut expander = Expander::new(db, tr_loc.id.file_id, module_id); | 102 | let mut expander = Expander::new(db, tr_loc.id.file_id, module_id); |
103 | 103 | ||
@@ -147,7 +147,7 @@ impl ImplData { | |||
147 | let target_trait = impl_def.target_trait.map(|id| item_tree[id].clone()); | 147 | let target_trait = impl_def.target_trait.map(|id| item_tree[id].clone()); |
148 | let target_type = item_tree[impl_def.target_type].clone(); | 148 | let target_type = item_tree[impl_def.target_type].clone(); |
149 | let is_negative = impl_def.is_negative; | 149 | let is_negative = impl_def.is_negative; |
150 | let module_id = impl_loc.container.module(db); | 150 | let module_id = impl_loc.container; |
151 | let container = AssocContainerId::ImplId(id); | 151 | let container = AssocContainerId::ImplId(id); |
152 | let mut expander = Expander::new(db, impl_loc.id.file_id, module_id); | 152 | let mut expander = Expander::new(db, impl_loc.id.file_id, module_id); |
153 | 153 | ||
diff --git a/crates/hir_def/src/generics.rs b/crates/hir_def/src/generics.rs index 3ace3be1f..a056ab797 100644 --- a/crates/hir_def/src/generics.rs +++ b/crates/hir_def/src/generics.rs | |||
@@ -421,8 +421,7 @@ impl HasChildSource<LocalConstParamId> for GenericDefId { | |||
421 | } | 421 | } |
422 | 422 | ||
423 | impl ChildBySource for GenericDefId { | 423 | impl ChildBySource for GenericDefId { |
424 | fn child_by_source(&self, db: &dyn DefDatabase) -> DynMap { | 424 | fn child_by_source_to(&self, db: &dyn DefDatabase, res: &mut DynMap) { |
425 | let mut res = DynMap::default(); | ||
426 | let (_, sm) = GenericParams::new(db, *self); | 425 | let (_, sm) = GenericParams::new(db, *self); |
427 | 426 | ||
428 | let sm = sm.as_ref(); | 427 | let sm = sm.as_ref(); |
@@ -440,6 +439,5 @@ impl ChildBySource for GenericDefId { | |||
440 | let id = ConstParamId { parent: *self, local_id }; | 439 | let id = ConstParamId { parent: *self, local_id }; |
441 | res[keys::CONST_PARAM].insert(sm.with_value(src.clone()), id); | 440 | res[keys::CONST_PARAM].insert(sm.with_value(src.clone()), id); |
442 | } | 441 | } |
443 | res | ||
444 | } | 442 | } |
445 | } | 443 | } |
diff --git a/crates/hir_def/src/item_scope.rs b/crates/hir_def/src/item_scope.rs index 919933813..aafd73b60 100644 --- a/crates/hir_def/src/item_scope.rs +++ b/crates/hir_def/src/item_scope.rs | |||
@@ -168,37 +168,6 @@ impl ItemScope { | |||
168 | self.unnamed_trait_imports.insert(tr, vis); | 168 | self.unnamed_trait_imports.insert(tr, vis); |
169 | } | 169 | } |
170 | 170 | ||
171 | pub(crate) fn push_res(&mut self, name: Name, def: PerNs) -> bool { | ||
172 | let mut changed = false; | ||
173 | |||
174 | if let Some(types) = def.types { | ||
175 | self.types.entry(name.clone()).or_insert_with(|| { | ||
176 | changed = true; | ||
177 | types | ||
178 | }); | ||
179 | } | ||
180 | if let Some(values) = def.values { | ||
181 | self.values.entry(name.clone()).or_insert_with(|| { | ||
182 | changed = true; | ||
183 | values | ||
184 | }); | ||
185 | } | ||
186 | if let Some(macros) = def.macros { | ||
187 | self.macros.entry(name.clone()).or_insert_with(|| { | ||
188 | changed = true; | ||
189 | macros | ||
190 | }); | ||
191 | } | ||
192 | |||
193 | if def.is_none() { | ||
194 | if self.unresolved.insert(name) { | ||
195 | changed = true; | ||
196 | } | ||
197 | } | ||
198 | |||
199 | changed | ||
200 | } | ||
201 | |||
202 | pub(crate) fn push_res_with_import( | 171 | pub(crate) fn push_res_with_import( |
203 | &mut self, | 172 | &mut self, |
204 | glob_imports: &mut PerNsGlobImports, | 173 | glob_imports: &mut PerNsGlobImports, |
diff --git a/crates/hir_def/src/lib.rs b/crates/hir_def/src/lib.rs index 4498d94bb..6d11c5be4 100644 --- a/crates/hir_def/src/lib.rs +++ b/crates/hir_def/src/lib.rs | |||
@@ -108,7 +108,7 @@ pub type LocalModuleId = Idx<nameres::ModuleData>; | |||
108 | 108 | ||
109 | #[derive(Debug)] | 109 | #[derive(Debug)] |
110 | pub struct ItemLoc<N: ItemTreeNode> { | 110 | pub struct ItemLoc<N: ItemTreeNode> { |
111 | pub container: ContainerId, | 111 | pub container: ModuleId, |
112 | pub id: ItemTreeId<N>, | 112 | pub id: ItemTreeId<N>, |
113 | } | 113 | } |
114 | 114 | ||
@@ -279,18 +279,12 @@ pub struct ConstParamId { | |||
279 | pub type LocalConstParamId = Idx<generics::ConstParamData>; | 279 | pub type LocalConstParamId = Idx<generics::ConstParamData>; |
280 | 280 | ||
281 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] | 281 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] |
282 | pub enum ContainerId { | ||
283 | ModuleId(ModuleId), | ||
284 | DefWithBodyId(DefWithBodyId), | ||
285 | } | ||
286 | |||
287 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] | ||
288 | pub enum AssocContainerId { | 282 | pub enum AssocContainerId { |
289 | ContainerId(ContainerId), | 283 | ModuleId(ModuleId), |
290 | ImplId(ImplId), | 284 | ImplId(ImplId), |
291 | TraitId(TraitId), | 285 | TraitId(TraitId), |
292 | } | 286 | } |
293 | impl_from!(ContainerId for AssocContainerId); | 287 | impl_from!(ModuleId for AssocContainerId); |
294 | 288 | ||
295 | /// A Data Type | 289 | /// A Data Type |
296 | #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)] | 290 | #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)] |
@@ -447,21 +441,12 @@ pub trait HasModule { | |||
447 | fn module(&self, db: &dyn db::DefDatabase) -> ModuleId; | 441 | fn module(&self, db: &dyn db::DefDatabase) -> ModuleId; |
448 | } | 442 | } |
449 | 443 | ||
450 | impl HasModule for ContainerId { | ||
451 | fn module(&self, db: &dyn db::DefDatabase) -> ModuleId { | ||
452 | match *self { | ||
453 | ContainerId::ModuleId(it) => it, | ||
454 | ContainerId::DefWithBodyId(it) => it.module(db), | ||
455 | } | ||
456 | } | ||
457 | } | ||
458 | |||
459 | impl HasModule for AssocContainerId { | 444 | impl HasModule for AssocContainerId { |
460 | fn module(&self, db: &dyn db::DefDatabase) -> ModuleId { | 445 | fn module(&self, db: &dyn db::DefDatabase) -> ModuleId { |
461 | match *self { | 446 | match *self { |
462 | AssocContainerId::ContainerId(it) => it.module(db), | 447 | AssocContainerId::ModuleId(it) => it, |
463 | AssocContainerId::ImplId(it) => it.lookup(db).container.module(db), | 448 | AssocContainerId::ImplId(it) => it.lookup(db).container, |
464 | AssocContainerId::TraitId(it) => it.lookup(db).container.module(db), | 449 | AssocContainerId::TraitId(it) => it.lookup(db).container, |
465 | } | 450 | } |
466 | } | 451 | } |
467 | } | 452 | } |
@@ -479,16 +464,15 @@ impl HasModule for AdtId { | |||
479 | AdtId::UnionId(it) => it.lookup(db).container, | 464 | AdtId::UnionId(it) => it.lookup(db).container, |
480 | AdtId::EnumId(it) => it.lookup(db).container, | 465 | AdtId::EnumId(it) => it.lookup(db).container, |
481 | } | 466 | } |
482 | .module(db) | ||
483 | } | 467 | } |
484 | } | 468 | } |
485 | 469 | ||
486 | impl HasModule for VariantId { | 470 | impl HasModule for VariantId { |
487 | fn module(&self, db: &dyn db::DefDatabase) -> ModuleId { | 471 | fn module(&self, db: &dyn db::DefDatabase) -> ModuleId { |
488 | match self { | 472 | match self { |
489 | VariantId::EnumVariantId(it) => it.parent.lookup(db).container.module(db), | 473 | VariantId::EnumVariantId(it) => it.parent.lookup(db).container, |
490 | VariantId::StructId(it) => it.lookup(db).container.module(db), | 474 | VariantId::StructId(it) => it.lookup(db).container, |
491 | VariantId::UnionId(it) => it.lookup(db).container.module(db), | 475 | VariantId::UnionId(it) => it.lookup(db).container, |
492 | } | 476 | } |
493 | } | 477 | } |
494 | } | 478 | } |
@@ -518,18 +502,18 @@ impl HasModule for GenericDefId { | |||
518 | match self { | 502 | match self { |
519 | GenericDefId::FunctionId(it) => it.lookup(db).module(db), | 503 | GenericDefId::FunctionId(it) => it.lookup(db).module(db), |
520 | GenericDefId::AdtId(it) => it.module(db), | 504 | GenericDefId::AdtId(it) => it.module(db), |
521 | GenericDefId::TraitId(it) => it.lookup(db).container.module(db), | 505 | GenericDefId::TraitId(it) => it.lookup(db).container, |
522 | GenericDefId::TypeAliasId(it) => it.lookup(db).module(db), | 506 | GenericDefId::TypeAliasId(it) => it.lookup(db).module(db), |
523 | GenericDefId::ImplId(it) => it.lookup(db).container.module(db), | 507 | GenericDefId::ImplId(it) => it.lookup(db).container, |
524 | GenericDefId::EnumVariantId(it) => it.parent.lookup(db).container.module(db), | 508 | GenericDefId::EnumVariantId(it) => it.parent.lookup(db).container, |
525 | GenericDefId::ConstId(it) => it.lookup(db).module(db), | 509 | GenericDefId::ConstId(it) => it.lookup(db).module(db), |
526 | } | 510 | } |
527 | } | 511 | } |
528 | } | 512 | } |
529 | 513 | ||
530 | impl HasModule for StaticLoc { | 514 | impl HasModule for StaticLoc { |
531 | fn module(&self, db: &dyn db::DefDatabase) -> ModuleId { | 515 | fn module(&self, _db: &dyn db::DefDatabase) -> ModuleId { |
532 | self.container.module(db) | 516 | self.container |
533 | } | 517 | } |
534 | } | 518 | } |
535 | 519 | ||
@@ -542,10 +526,10 @@ impl ModuleDefId { | |||
542 | ModuleDefId::ModuleId(id) => *id, | 526 | ModuleDefId::ModuleId(id) => *id, |
543 | ModuleDefId::FunctionId(id) => id.lookup(db).module(db), | 527 | ModuleDefId::FunctionId(id) => id.lookup(db).module(db), |
544 | ModuleDefId::AdtId(id) => id.module(db), | 528 | ModuleDefId::AdtId(id) => id.module(db), |
545 | ModuleDefId::EnumVariantId(id) => id.parent.lookup(db).container.module(db), | 529 | ModuleDefId::EnumVariantId(id) => id.parent.lookup(db).container, |
546 | ModuleDefId::ConstId(id) => id.lookup(db).container.module(db), | 530 | ModuleDefId::ConstId(id) => id.lookup(db).container.module(db), |
547 | ModuleDefId::StaticId(id) => id.lookup(db).container.module(db), | 531 | ModuleDefId::StaticId(id) => id.lookup(db).container, |
548 | ModuleDefId::TraitId(id) => id.lookup(db).container.module(db), | 532 | ModuleDefId::TraitId(id) => id.lookup(db).container, |
549 | ModuleDefId::TypeAliasId(id) => id.lookup(db).module(db), | 533 | ModuleDefId::TypeAliasId(id) => id.lookup(db).module(db), |
550 | ModuleDefId::BuiltinType(_) => return None, | 534 | ModuleDefId::BuiltinType(_) => return None, |
551 | }) | 535 | }) |
@@ -559,12 +543,12 @@ impl AttrDefId { | |||
559 | AttrDefId::FieldId(it) => it.parent.module(db).krate, | 543 | AttrDefId::FieldId(it) => it.parent.module(db).krate, |
560 | AttrDefId::AdtId(it) => it.module(db).krate, | 544 | AttrDefId::AdtId(it) => it.module(db).krate, |
561 | AttrDefId::FunctionId(it) => it.lookup(db).module(db).krate, | 545 | AttrDefId::FunctionId(it) => it.lookup(db).module(db).krate, |
562 | AttrDefId::EnumVariantId(it) => it.parent.lookup(db).container.module(db).krate, | 546 | AttrDefId::EnumVariantId(it) => it.parent.lookup(db).container.krate, |
563 | AttrDefId::StaticId(it) => it.lookup(db).module(db).krate, | 547 | AttrDefId::StaticId(it) => it.lookup(db).module(db).krate, |
564 | AttrDefId::ConstId(it) => it.lookup(db).module(db).krate, | 548 | AttrDefId::ConstId(it) => it.lookup(db).module(db).krate, |
565 | AttrDefId::TraitId(it) => it.lookup(db).container.module(db).krate, | 549 | AttrDefId::TraitId(it) => it.lookup(db).container.krate, |
566 | AttrDefId::TypeAliasId(it) => it.lookup(db).module(db).krate, | 550 | AttrDefId::TypeAliasId(it) => it.lookup(db).module(db).krate, |
567 | AttrDefId::ImplId(it) => it.lookup(db).container.module(db).krate, | 551 | AttrDefId::ImplId(it) => it.lookup(db).container.krate, |
568 | AttrDefId::GenericParamId(it) => { | 552 | AttrDefId::GenericParamId(it) => { |
569 | match it { | 553 | match it { |
570 | GenericParamId::TypeParamId(it) => it.parent, | 554 | GenericParamId::TypeParamId(it) => it.parent, |
diff --git a/crates/hir_def/src/nameres/collector.rs b/crates/hir_def/src/nameres/collector.rs index 3bb69d935..9ed48c506 100644 --- a/crates/hir_def/src/nameres/collector.rs +++ b/crates/hir_def/src/nameres/collector.rs | |||
@@ -37,9 +37,9 @@ use crate::{ | |||
37 | path::{ImportAlias, ModPath, PathKind}, | 37 | path::{ImportAlias, ModPath, PathKind}, |
38 | per_ns::PerNs, | 38 | per_ns::PerNs, |
39 | visibility::{RawVisibility, Visibility}, | 39 | visibility::{RawVisibility, Visibility}, |
40 | AdtId, AstId, AstIdWithPath, ConstLoc, ContainerId, EnumLoc, EnumVariantId, FunctionLoc, | 40 | AdtId, AstId, AstIdWithPath, ConstLoc, EnumLoc, EnumVariantId, FunctionLoc, ImplLoc, Intern, |
41 | ImplLoc, Intern, LocalModuleId, ModuleDefId, StaticLoc, StructLoc, TraitLoc, TypeAliasLoc, | 41 | LocalModuleId, ModuleDefId, StaticLoc, StructLoc, TraitLoc, TypeAliasLoc, UnionLoc, |
42 | UnionLoc, UnresolvedMacro, | 42 | UnresolvedMacro, |
43 | }; | 43 | }; |
44 | 44 | ||
45 | const GLOB_RECURSION_LIMIT: usize = 100; | 45 | const GLOB_RECURSION_LIMIT: usize = 100; |
@@ -1042,7 +1042,6 @@ impl ModCollector<'_, '_> { | |||
1042 | } | 1042 | } |
1043 | } | 1043 | } |
1044 | let module = self.def_collector.def_map.module_id(self.module_id); | 1044 | let module = self.def_collector.def_map.module_id(self.module_id); |
1045 | let container = ContainerId::ModuleId(module); | ||
1046 | 1045 | ||
1047 | let mut def = None; | 1046 | let mut def = None; |
1048 | match item { | 1047 | match item { |
@@ -1109,9 +1108,9 @@ impl ModCollector<'_, '_> { | |||
1109 | } | 1108 | } |
1110 | ModItem::Impl(imp) => { | 1109 | ModItem::Impl(imp) => { |
1111 | let module = self.def_collector.def_map.module_id(self.module_id); | 1110 | let module = self.def_collector.def_map.module_id(self.module_id); |
1112 | let container = ContainerId::ModuleId(module); | 1111 | let impl_id = |
1113 | let impl_id = ImplLoc { container, id: ItemTreeId::new(self.file_id, imp) } | 1112 | ImplLoc { container: module, id: ItemTreeId::new(self.file_id, imp) } |
1114 | .intern(self.def_collector.db); | 1113 | .intern(self.def_collector.db); |
1115 | self.def_collector.def_map.modules[self.module_id].scope.define_impl(impl_id) | 1114 | self.def_collector.def_map.modules[self.module_id].scope.define_impl(impl_id) |
1116 | } | 1115 | } |
1117 | ModItem::Function(id) => { | 1116 | ModItem::Function(id) => { |
@@ -1121,7 +1120,7 @@ impl ModCollector<'_, '_> { | |||
1121 | 1120 | ||
1122 | def = Some(DefData { | 1121 | def = Some(DefData { |
1123 | id: FunctionLoc { | 1122 | id: FunctionLoc { |
1124 | container: container.into(), | 1123 | container: module.into(), |
1125 | id: ItemTreeId::new(self.file_id, id), | 1124 | id: ItemTreeId::new(self.file_id, id), |
1126 | } | 1125 | } |
1127 | .intern(self.def_collector.db) | 1126 | .intern(self.def_collector.db) |
@@ -1140,7 +1139,7 @@ impl ModCollector<'_, '_> { | |||
1140 | self.collect_derives(&attrs, it.ast_id.upcast()); | 1139 | self.collect_derives(&attrs, it.ast_id.upcast()); |
1141 | 1140 | ||
1142 | def = Some(DefData { | 1141 | def = Some(DefData { |
1143 | id: StructLoc { container, id: ItemTreeId::new(self.file_id, id) } | 1142 | id: StructLoc { container: module, id: ItemTreeId::new(self.file_id, id) } |
1144 | .intern(self.def_collector.db) | 1143 | .intern(self.def_collector.db) |
1145 | .into(), | 1144 | .into(), |
1146 | name: &it.name, | 1145 | name: &it.name, |
@@ -1157,7 +1156,7 @@ impl ModCollector<'_, '_> { | |||
1157 | self.collect_derives(&attrs, it.ast_id.upcast()); | 1156 | self.collect_derives(&attrs, it.ast_id.upcast()); |
1158 | 1157 | ||
1159 | def = Some(DefData { | 1158 | def = Some(DefData { |
1160 | id: UnionLoc { container, id: ItemTreeId::new(self.file_id, id) } | 1159 | id: UnionLoc { container: module, id: ItemTreeId::new(self.file_id, id) } |
1161 | .intern(self.def_collector.db) | 1160 | .intern(self.def_collector.db) |
1162 | .into(), | 1161 | .into(), |
1163 | name: &it.name, | 1162 | name: &it.name, |
@@ -1174,7 +1173,7 @@ impl ModCollector<'_, '_> { | |||
1174 | self.collect_derives(&attrs, it.ast_id.upcast()); | 1173 | self.collect_derives(&attrs, it.ast_id.upcast()); |
1175 | 1174 | ||
1176 | def = Some(DefData { | 1175 | def = Some(DefData { |
1177 | id: EnumLoc { container, id: ItemTreeId::new(self.file_id, id) } | 1176 | id: EnumLoc { container: module, id: ItemTreeId::new(self.file_id, id) } |
1178 | .intern(self.def_collector.db) | 1177 | .intern(self.def_collector.db) |
1179 | .into(), | 1178 | .into(), |
1180 | name: &it.name, | 1179 | name: &it.name, |
@@ -1188,7 +1187,7 @@ impl ModCollector<'_, '_> { | |||
1188 | if let Some(name) = &it.name { | 1187 | if let Some(name) = &it.name { |
1189 | def = Some(DefData { | 1188 | def = Some(DefData { |
1190 | id: ConstLoc { | 1189 | id: ConstLoc { |
1191 | container: container.into(), | 1190 | container: module.into(), |
1192 | id: ItemTreeId::new(self.file_id, id), | 1191 | id: ItemTreeId::new(self.file_id, id), |
1193 | } | 1192 | } |
1194 | .intern(self.def_collector.db) | 1193 | .intern(self.def_collector.db) |
@@ -1203,7 +1202,7 @@ impl ModCollector<'_, '_> { | |||
1203 | let it = &self.item_tree[id]; | 1202 | let it = &self.item_tree[id]; |
1204 | 1203 | ||
1205 | def = Some(DefData { | 1204 | def = Some(DefData { |
1206 | id: StaticLoc { container, id: ItemTreeId::new(self.file_id, id) } | 1205 | id: StaticLoc { container: module, id: ItemTreeId::new(self.file_id, id) } |
1207 | .intern(self.def_collector.db) | 1206 | .intern(self.def_collector.db) |
1208 | .into(), | 1207 | .into(), |
1209 | name: &it.name, | 1208 | name: &it.name, |
@@ -1215,7 +1214,7 @@ impl ModCollector<'_, '_> { | |||
1215 | let it = &self.item_tree[id]; | 1214 | let it = &self.item_tree[id]; |
1216 | 1215 | ||
1217 | def = Some(DefData { | 1216 | def = Some(DefData { |
1218 | id: TraitLoc { container, id: ItemTreeId::new(self.file_id, id) } | 1217 | id: TraitLoc { container: module, id: ItemTreeId::new(self.file_id, id) } |
1219 | .intern(self.def_collector.db) | 1218 | .intern(self.def_collector.db) |
1220 | .into(), | 1219 | .into(), |
1221 | name: &it.name, | 1220 | name: &it.name, |
@@ -1228,7 +1227,7 @@ impl ModCollector<'_, '_> { | |||
1228 | 1227 | ||
1229 | def = Some(DefData { | 1228 | def = Some(DefData { |
1230 | id: TypeAliasLoc { | 1229 | id: TypeAliasLoc { |
1231 | container: container.into(), | 1230 | container: module.into(), |
1232 | id: ItemTreeId::new(self.file_id, id), | 1231 | id: ItemTreeId::new(self.file_id, id), |
1233 | } | 1232 | } |
1234 | .intern(self.def_collector.db) | 1233 | .intern(self.def_collector.db) |
diff --git a/crates/hir_def/src/nameres/path_resolution.rs b/crates/hir_def/src/nameres/path_resolution.rs index 8258dcffb..db459b1ed 100644 --- a/crates/hir_def/src/nameres/path_resolution.rs +++ b/crates/hir_def/src/nameres/path_resolution.rs | |||
@@ -156,7 +156,7 @@ impl DefMap { | |||
156 | } | 156 | } |
157 | } | 157 | } |
158 | 158 | ||
159 | pub(super) fn resolve_path_fp_with_macro_single( | 159 | fn resolve_path_fp_with_macro_single( |
160 | &self, | 160 | &self, |
161 | db: &dyn DefDatabase, | 161 | db: &dyn DefDatabase, |
162 | mode: ResolveMode, | 162 | mode: ResolveMode, |
@@ -384,10 +384,16 @@ impl DefMap { | |||
384 | } | 384 | } |
385 | } | 385 | } |
386 | }; | 386 | }; |
387 | let from_extern_prelude = self | 387 | // Give precedence to names in outer `DefMap`s over the extern prelude; only check prelude |
388 | .extern_prelude | 388 | // from the crate DefMap. |
389 | .get(name) | 389 | let from_extern_prelude = match self.block { |
390 | .map_or(PerNs::none(), |&it| PerNs::types(it, Visibility::Public)); | 390 | Some(_) => PerNs::none(), |
391 | None => self | ||
392 | .extern_prelude | ||
393 | .get(name) | ||
394 | .map_or(PerNs::none(), |&it| PerNs::types(it, Visibility::Public)), | ||
395 | }; | ||
396 | |||
391 | let from_prelude = self.resolve_in_prelude(db, name); | 397 | let from_prelude = self.resolve_in_prelude(db, name); |
392 | 398 | ||
393 | from_legacy_macro.or(from_scope_or_builtin).or(from_extern_prelude).or(from_prelude) | 399 | from_legacy_macro.or(from_scope_or_builtin).or(from_extern_prelude).or(from_prelude) |
diff --git a/crates/hir_def/src/resolver.rs b/crates/hir_def/src/resolver.rs index 77ff21739..42736171e 100644 --- a/crates/hir_def/src/resolver.rs +++ b/crates/hir_def/src/resolver.rs | |||
@@ -19,10 +19,10 @@ use crate::{ | |||
19 | path::{ModPath, PathKind}, | 19 | path::{ModPath, PathKind}, |
20 | per_ns::PerNs, | 20 | per_ns::PerNs, |
21 | visibility::{RawVisibility, Visibility}, | 21 | visibility::{RawVisibility, Visibility}, |
22 | AdtId, AssocContainerId, ConstId, ConstParamId, ContainerId, DefWithBodyId, EnumId, | 22 | AdtId, AssocContainerId, ConstId, ConstParamId, DefWithBodyId, EnumId, EnumVariantId, |
23 | EnumVariantId, FunctionId, GenericDefId, GenericParamId, HasModule, ImplId, LifetimeParamId, | 23 | FunctionId, GenericDefId, GenericParamId, HasModule, ImplId, LifetimeParamId, LocalModuleId, |
24 | LocalModuleId, Lookup, ModuleDefId, ModuleId, StaticId, StructId, TraitId, TypeAliasId, | 24 | Lookup, ModuleDefId, ModuleId, StaticId, StructId, TraitId, TypeAliasId, TypeParamId, |
25 | TypeParamId, VariantId, | 25 | VariantId, |
26 | }; | 26 | }; |
27 | 27 | ||
28 | #[derive(Debug, Clone, Default)] | 28 | #[derive(Debug, Clone, Default)] |
@@ -342,6 +342,16 @@ impl Resolver { | |||
342 | traits.extend(prelude_def_map[prelude.local_id].scope.traits()); | 342 | traits.extend(prelude_def_map[prelude.local_id].scope.traits()); |
343 | } | 343 | } |
344 | traits.extend(m.def_map[m.module_id].scope.traits()); | 344 | traits.extend(m.def_map[m.module_id].scope.traits()); |
345 | |||
346 | // Add all traits that are in scope because of the containing DefMaps | ||
347 | m.def_map.with_ancestor_maps(db, m.module_id, &mut |def_map, module| { | ||
348 | if let Some(prelude) = def_map.prelude() { | ||
349 | let prelude_def_map = prelude.def_map(db); | ||
350 | traits.extend(prelude_def_map[prelude.local_id].scope.traits()); | ||
351 | } | ||
352 | traits.extend(def_map[module].scope.traits()); | ||
353 | None::<()> | ||
354 | }); | ||
345 | } | 355 | } |
346 | } | 356 | } |
347 | traits | 357 | traits |
@@ -678,19 +688,10 @@ impl HasResolver for DefWithBodyId { | |||
678 | } | 688 | } |
679 | } | 689 | } |
680 | 690 | ||
681 | impl HasResolver for ContainerId { | ||
682 | fn resolver(self, db: &dyn DefDatabase) -> Resolver { | ||
683 | match self { | ||
684 | ContainerId::ModuleId(it) => it.resolver(db), | ||
685 | ContainerId::DefWithBodyId(it) => it.module(db).resolver(db), | ||
686 | } | ||
687 | } | ||
688 | } | ||
689 | |||
690 | impl HasResolver for AssocContainerId { | 691 | impl HasResolver for AssocContainerId { |
691 | fn resolver(self, db: &dyn DefDatabase) -> Resolver { | 692 | fn resolver(self, db: &dyn DefDatabase) -> Resolver { |
692 | match self { | 693 | match self { |
693 | AssocContainerId::ContainerId(it) => it.resolver(db), | 694 | AssocContainerId::ModuleId(it) => it.resolver(db), |
694 | AssocContainerId::TraitId(it) => it.resolver(db), | 695 | AssocContainerId::TraitId(it) => it.resolver(db), |
695 | AssocContainerId::ImplId(it) => it.resolver(db), | 696 | AssocContainerId::ImplId(it) => it.resolver(db), |
696 | } | 697 | } |
diff --git a/crates/hir_expand/Cargo.toml b/crates/hir_expand/Cargo.toml index 5271110d2..f649ab925 100644 --- a/crates/hir_expand/Cargo.toml +++ b/crates/hir_expand/Cargo.toml | |||
@@ -16,9 +16,13 @@ rustc-hash = "1.0.0" | |||
16 | la-arena = { version = "0.2.0", path = "../../lib/arena" } | 16 | la-arena = { version = "0.2.0", path = "../../lib/arena" } |
17 | 17 | ||
18 | base_db = { path = "../base_db", version = "0.0.0" } | 18 | base_db = { path = "../base_db", version = "0.0.0" } |
19 | cfg = { path = "../cfg", version = "0.0.0" } | ||
19 | syntax = { path = "../syntax", version = "0.0.0" } | 20 | syntax = { path = "../syntax", version = "0.0.0" } |
20 | parser = { path = "../parser", version = "0.0.0" } | 21 | parser = { path = "../parser", version = "0.0.0" } |
21 | profile = { path = "../profile", version = "0.0.0" } | 22 | profile = { path = "../profile", version = "0.0.0" } |
22 | tt = { path = "../tt", version = "0.0.0" } | 23 | tt = { path = "../tt", version = "0.0.0" } |
23 | mbe = { path = "../mbe", version = "0.0.0" } | 24 | mbe = { path = "../mbe", version = "0.0.0" } |
24 | test_utils = { path = "../test_utils", version = "0.0.0" } | 25 | |
26 | [dev-dependencies] | ||
27 | test_utils = { path = "../test_utils" } | ||
28 | expect-test = "1.1" | ||
diff --git a/crates/hir_expand/src/builtin_derive.rs b/crates/hir_expand/src/builtin_derive.rs index b7f1aae8f..dfdb9cf59 100644 --- a/crates/hir_expand/src/builtin_derive.rs +++ b/crates/hir_expand/src/builtin_derive.rs | |||
@@ -267,13 +267,14 @@ fn partial_ord_expand( | |||
267 | #[cfg(test)] | 267 | #[cfg(test)] |
268 | mod tests { | 268 | mod tests { |
269 | use base_db::{fixture::WithFixture, CrateId, SourceDatabase}; | 269 | use base_db::{fixture::WithFixture, CrateId, SourceDatabase}; |
270 | use expect_test::{expect, Expect}; | ||
270 | use name::{known, Name}; | 271 | use name::{known, Name}; |
271 | 272 | ||
272 | use crate::{test_db::TestDB, AstId, MacroCallId, MacroCallKind, MacroCallLoc}; | 273 | use crate::{test_db::TestDB, AstId, MacroCallId, MacroCallKind, MacroCallLoc}; |
273 | 274 | ||
274 | use super::*; | 275 | use super::*; |
275 | 276 | ||
276 | fn expand_builtin_derive(s: &str, name: Name) -> String { | 277 | fn expand_builtin_derive(ra_fixture: &str, name: Name) -> String { |
277 | let expander = BuiltinDeriveExpander::find_by_name(&name).unwrap(); | 278 | let expander = BuiltinDeriveExpander::find_by_name(&name).unwrap(); |
278 | let fixture = format!( | 279 | let fixture = format!( |
279 | r#"//- /main.rs crate:main deps:core | 280 | r#"//- /main.rs crate:main deps:core |
@@ -282,7 +283,7 @@ $0 | |||
282 | //- /lib.rs crate:core | 283 | //- /lib.rs crate:core |
283 | // empty | 284 | // empty |
284 | "#, | 285 | "#, |
285 | s | 286 | ra_fixture |
286 | ); | 287 | ); |
287 | 288 | ||
288 | let (db, file_pos) = TestDB::with_position(&fixture); | 289 | let (db, file_pos) = TestDB::with_position(&fixture); |
@@ -314,66 +315,57 @@ $0 | |||
314 | parsed.text().to_string() | 315 | parsed.text().to_string() |
315 | } | 316 | } |
316 | 317 | ||
318 | fn check_derive(ra_fixture: &str, name: Name, expected: Expect) { | ||
319 | let expanded = expand_builtin_derive(ra_fixture, name); | ||
320 | expected.assert_eq(&expanded); | ||
321 | } | ||
322 | |||
317 | #[test] | 323 | #[test] |
318 | fn test_copy_expand_simple() { | 324 | fn test_copy_expand_simple() { |
319 | let expanded = expand_builtin_derive( | 325 | check_derive( |
320 | r#" | 326 | r#" |
321 | #[derive(Copy)] | 327 | #[derive(Copy)] |
322 | struct Foo; | 328 | struct Foo; |
323 | "#, | 329 | "#, |
324 | known::Copy, | 330 | known::Copy, |
331 | expect![["impl< >core::marker::CopyforFoo< >{}"]], | ||
325 | ); | 332 | ); |
326 | |||
327 | assert_eq!(expanded, "impl< >core::marker::CopyforFoo< >{}"); | ||
328 | } | 333 | } |
329 | 334 | ||
330 | #[test] | 335 | #[test] |
331 | fn test_copy_expand_with_type_params() { | 336 | fn test_copy_expand_with_type_params() { |
332 | let expanded = expand_builtin_derive( | 337 | check_derive( |
333 | r#" | 338 | r#" |
334 | #[derive(Copy)] | 339 | #[derive(Copy)] |
335 | struct Foo<A, B>; | 340 | struct Foo<A, B>; |
336 | "#, | 341 | "#, |
337 | known::Copy, | 342 | known::Copy, |
338 | ); | 343 | expect![["impl<T0:core::marker::Copy,T1:core::marker::Copy>core::marker::CopyforFoo<T0,T1>{}"]], |
339 | |||
340 | assert_eq!( | ||
341 | expanded, | ||
342 | "impl<T0:core::marker::Copy,T1:core::marker::Copy>core::marker::CopyforFoo<T0,T1>{}" | ||
343 | ); | 344 | ); |
344 | } | 345 | } |
345 | 346 | ||
346 | #[test] | 347 | #[test] |
347 | fn test_copy_expand_with_lifetimes() { | 348 | fn test_copy_expand_with_lifetimes() { |
348 | let expanded = expand_builtin_derive( | 349 | check_derive( |
349 | r#" | 350 | r#" |
350 | #[derive(Copy)] | 351 | #[derive(Copy)] |
351 | struct Foo<A, B, 'a, 'b>; | 352 | struct Foo<A, B, 'a, 'b>; |
352 | "#, | 353 | "#, |
353 | known::Copy, | 354 | known::Copy, |
354 | ); | 355 | // We currently just ignore lifetimes |
355 | 356 | expect![["impl<T0:core::marker::Copy,T1:core::marker::Copy>core::marker::CopyforFoo<T0,T1>{}"]], | |
356 | // We currently just ignore lifetimes | ||
357 | |||
358 | assert_eq!( | ||
359 | expanded, | ||
360 | "impl<T0:core::marker::Copy,T1:core::marker::Copy>core::marker::CopyforFoo<T0,T1>{}" | ||
361 | ); | 357 | ); |
362 | } | 358 | } |
363 | 359 | ||
364 | #[test] | 360 | #[test] |
365 | fn test_clone_expand() { | 361 | fn test_clone_expand() { |
366 | let expanded = expand_builtin_derive( | 362 | check_derive( |
367 | r#" | 363 | r#" |
368 | #[derive(Clone)] | 364 | #[derive(Clone)] |
369 | struct Foo<A, B>; | 365 | struct Foo<A, B>; |
370 | "#, | 366 | "#, |
371 | known::Clone, | 367 | known::Clone, |
372 | ); | 368 | expect![["impl<T0:core::clone::Clone,T1:core::clone::Clone>core::clone::CloneforFoo<T0,T1>{}"]], |
373 | |||
374 | assert_eq!( | ||
375 | expanded, | ||
376 | "impl<T0:core::clone::Clone,T1:core::clone::Clone>core::clone::CloneforFoo<T0,T1>{}" | ||
377 | ); | 369 | ); |
378 | } | 370 | } |
379 | } | 371 | } |
diff --git a/crates/hir_expand/src/builtin_macro.rs b/crates/hir_expand/src/builtin_macro.rs index eb57ea7d6..2a79c892b 100644 --- a/crates/hir_expand/src/builtin_macro.rs +++ b/crates/hir_expand/src/builtin_macro.rs | |||
@@ -5,6 +5,7 @@ use crate::{ | |||
5 | }; | 5 | }; |
6 | 6 | ||
7 | use base_db::{AnchoredPath, FileId}; | 7 | use base_db::{AnchoredPath, FileId}; |
8 | use cfg::CfgExpr; | ||
8 | use either::Either; | 9 | use either::Either; |
9 | use mbe::{parse_exprs_with_sep, parse_to_token_tree, ExpandResult}; | 10 | use mbe::{parse_exprs_with_sep, parse_to_token_tree, ExpandResult}; |
10 | use parser::FragmentKind; | 11 | use parser::FragmentKind; |
@@ -97,6 +98,7 @@ register_builtin! { | |||
97 | (format_args_nl, FormatArgsNl) => format_args_expand, | 98 | (format_args_nl, FormatArgsNl) => format_args_expand, |
98 | (llvm_asm, LlvmAsm) => asm_expand, | 99 | (llvm_asm, LlvmAsm) => asm_expand, |
99 | (asm, Asm) => asm_expand, | 100 | (asm, Asm) => asm_expand, |
101 | (cfg, Cfg) => cfg_expand, | ||
100 | 102 | ||
101 | EAGER: | 103 | EAGER: |
102 | (compile_error, CompileError) => compile_error_expand, | 104 | (compile_error, CompileError) => compile_error_expand, |
@@ -258,6 +260,18 @@ fn asm_expand( | |||
258 | ExpandResult::ok(expanded) | 260 | ExpandResult::ok(expanded) |
259 | } | 261 | } |
260 | 262 | ||
263 | fn cfg_expand( | ||
264 | db: &dyn AstDatabase, | ||
265 | id: LazyMacroId, | ||
266 | tt: &tt::Subtree, | ||
267 | ) -> ExpandResult<tt::Subtree> { | ||
268 | let loc = db.lookup_intern_macro(id); | ||
269 | let expr = CfgExpr::parse(tt); | ||
270 | let enabled = db.crate_graph()[loc.krate].cfg_options.check(&expr) != Some(false); | ||
271 | let expanded = if enabled { quote!(true) } else { quote!(false) }; | ||
272 | ExpandResult::ok(expanded) | ||
273 | } | ||
274 | |||
261 | fn unquote_str(lit: &tt::Literal) -> Option<String> { | 275 | fn unquote_str(lit: &tt::Literal) -> Option<String> { |
262 | let lit = ast::make::tokens::literal(&lit.to_string()); | 276 | let lit = ast::make::tokens::literal(&lit.to_string()); |
263 | let token = ast::String::cast(lit)?; | 277 | let token = ast::String::cast(lit)?; |
@@ -477,6 +491,7 @@ mod tests { | |||
477 | MacroCallLoc, | 491 | MacroCallLoc, |
478 | }; | 492 | }; |
479 | use base_db::{fixture::WithFixture, SourceDatabase}; | 493 | use base_db::{fixture::WithFixture, SourceDatabase}; |
494 | use expect_test::{expect, Expect}; | ||
480 | use std::sync::Arc; | 495 | use std::sync::Arc; |
481 | use syntax::ast::NameOwner; | 496 | use syntax::ast::NameOwner; |
482 | 497 | ||
@@ -560,87 +575,86 @@ mod tests { | |||
560 | db.parse_or_expand(file_id).unwrap().to_string() | 575 | db.parse_or_expand(file_id).unwrap().to_string() |
561 | } | 576 | } |
562 | 577 | ||
578 | fn check_expansion(ra_fixture: &str, expect: Expect) { | ||
579 | let expansion = expand_builtin_macro(ra_fixture); | ||
580 | expect.assert_eq(&expansion); | ||
581 | } | ||
582 | |||
563 | #[test] | 583 | #[test] |
564 | fn test_column_expand() { | 584 | fn test_column_expand() { |
565 | let expanded = expand_builtin_macro( | 585 | check_expansion( |
566 | r#" | 586 | r#" |
567 | #[rustc_builtin_macro] | 587 | #[rustc_builtin_macro] |
568 | macro_rules! column {() => {}} | 588 | macro_rules! column {() => {}} |
569 | column!() | 589 | column!() |
570 | "#, | 590 | "#, |
591 | expect![["0"]], | ||
571 | ); | 592 | ); |
572 | |||
573 | assert_eq!(expanded, "0"); | ||
574 | } | 593 | } |
575 | 594 | ||
576 | #[test] | 595 | #[test] |
577 | fn test_line_expand() { | 596 | fn test_line_expand() { |
578 | let expanded = expand_builtin_macro( | 597 | check_expansion( |
579 | r#" | 598 | r#" |
580 | #[rustc_builtin_macro] | 599 | #[rustc_builtin_macro] |
581 | macro_rules! line {() => {}} | 600 | macro_rules! line {() => {}} |
582 | line!() | 601 | line!() |
583 | "#, | 602 | "#, |
603 | expect![["0"]], | ||
584 | ); | 604 | ); |
585 | |||
586 | assert_eq!(expanded, "0"); | ||
587 | } | 605 | } |
588 | 606 | ||
589 | #[test] | 607 | #[test] |
590 | fn test_stringify_expand() { | 608 | fn test_stringify_expand() { |
591 | let expanded = expand_builtin_macro( | 609 | check_expansion( |
592 | r#" | 610 | r#" |
593 | #[rustc_builtin_macro] | 611 | #[rustc_builtin_macro] |
594 | macro_rules! stringify {() => {}} | 612 | macro_rules! stringify {() => {}} |
595 | stringify!(a b c) | 613 | stringify!(a b c) |
596 | "#, | 614 | "#, |
615 | expect![["\"a b c\""]], | ||
597 | ); | 616 | ); |
598 | |||
599 | assert_eq!(expanded, "\"a b c\""); | ||
600 | } | 617 | } |
601 | 618 | ||
602 | #[test] | 619 | #[test] |
603 | fn test_env_expand() { | 620 | fn test_env_expand() { |
604 | let expanded = expand_builtin_macro( | 621 | check_expansion( |
605 | r#" | 622 | r#" |
606 | #[rustc_builtin_macro] | 623 | #[rustc_builtin_macro] |
607 | macro_rules! env {() => {}} | 624 | macro_rules! env {() => {}} |
608 | env!("TEST_ENV_VAR") | 625 | env!("TEST_ENV_VAR") |
609 | "#, | 626 | "#, |
627 | expect![["\"__RA_UNIMPLEMENTED__\""]], | ||
610 | ); | 628 | ); |
611 | |||
612 | assert_eq!(expanded, "\"__RA_UNIMPLEMENTED__\""); | ||
613 | } | 629 | } |
614 | 630 | ||
615 | #[test] | 631 | #[test] |
616 | fn test_option_env_expand() { | 632 | fn test_option_env_expand() { |
617 | let expanded = expand_builtin_macro( | 633 | check_expansion( |
618 | r#" | 634 | r#" |
619 | #[rustc_builtin_macro] | 635 | #[rustc_builtin_macro] |
620 | macro_rules! option_env {() => {}} | 636 | macro_rules! option_env {() => {}} |
621 | option_env!("TEST_ENV_VAR") | 637 | option_env!("TEST_ENV_VAR") |
622 | "#, | 638 | "#, |
639 | expect![["std::option::Option::None:: < &str>"]], | ||
623 | ); | 640 | ); |
624 | |||
625 | assert_eq!(expanded, "std::option::Option::None:: < &str>"); | ||
626 | } | 641 | } |
627 | 642 | ||
628 | #[test] | 643 | #[test] |
629 | fn test_file_expand() { | 644 | fn test_file_expand() { |
630 | let expanded = expand_builtin_macro( | 645 | check_expansion( |
631 | r#" | 646 | r#" |
632 | #[rustc_builtin_macro] | 647 | #[rustc_builtin_macro] |
633 | macro_rules! file {() => {}} | 648 | macro_rules! file {() => {}} |
634 | file!() | 649 | file!() |
635 | "#, | 650 | "#, |
651 | expect![[r#""""#]], | ||
636 | ); | 652 | ); |
637 | |||
638 | assert_eq!(expanded, "\"\""); | ||
639 | } | 653 | } |
640 | 654 | ||
641 | #[test] | 655 | #[test] |
642 | fn test_assert_expand() { | 656 | fn test_assert_expand() { |
643 | let expanded = expand_builtin_macro( | 657 | check_expansion( |
644 | r#" | 658 | r#" |
645 | #[rustc_builtin_macro] | 659 | #[rustc_builtin_macro] |
646 | macro_rules! assert { | 660 | macro_rules! assert { |
@@ -649,14 +663,13 @@ mod tests { | |||
649 | } | 663 | } |
650 | assert!(true, "{} {:?}", arg1(a, b, c), arg2); | 664 | assert!(true, "{} {:?}", arg1(a, b, c), arg2); |
651 | "#, | 665 | "#, |
666 | expect![["{{(&(true), &(\"{} {:?}\"), &(arg1(a,b,c)), &(arg2),);}}"]], | ||
652 | ); | 667 | ); |
653 | |||
654 | assert_eq!(expanded, "{{(&(true), &(\"{} {:?}\"), &(arg1(a,b,c)), &(arg2),);}}"); | ||
655 | } | 668 | } |
656 | 669 | ||
657 | #[test] | 670 | #[test] |
658 | fn test_compile_error_expand() { | 671 | fn test_compile_error_expand() { |
659 | let expanded = expand_builtin_macro( | 672 | check_expansion( |
660 | r#" | 673 | r#" |
661 | #[rustc_builtin_macro] | 674 | #[rustc_builtin_macro] |
662 | macro_rules! compile_error { | 675 | macro_rules! compile_error { |
@@ -665,15 +678,14 @@ mod tests { | |||
665 | } | 678 | } |
666 | compile_error!("error!"); | 679 | compile_error!("error!"); |
667 | "#, | 680 | "#, |
681 | // This expands to nothing (since it's in item position), but emits an error. | ||
682 | expect![[""]], | ||
668 | ); | 683 | ); |
669 | |||
670 | // This expands to nothing (since it's in item position), but emits an error. | ||
671 | assert_eq!(expanded, ""); | ||
672 | } | 684 | } |
673 | 685 | ||
674 | #[test] | 686 | #[test] |
675 | fn test_format_args_expand() { | 687 | fn test_format_args_expand() { |
676 | let expanded = expand_builtin_macro( | 688 | check_expansion( |
677 | r#" | 689 | r#" |
678 | #[rustc_builtin_macro] | 690 | #[rustc_builtin_macro] |
679 | macro_rules! format_args { | 691 | macro_rules! format_args { |
@@ -682,17 +694,15 @@ mod tests { | |||
682 | } | 694 | } |
683 | format_args!("{} {:?}", arg1(a, b, c), arg2); | 695 | format_args!("{} {:?}", arg1(a, b, c), arg2); |
684 | "#, | 696 | "#, |
685 | ); | 697 | expect![[ |
686 | 698 | r#"std::fmt::Arguments::new_v1(&[], &[std::fmt::ArgumentV1::new(&(arg1(a,b,c)),std::fmt::Display::fmt),std::fmt::ArgumentV1::new(&(arg2),std::fmt::Display::fmt),])"# | |
687 | assert_eq!( | 699 | ]], |
688 | expanded, | ||
689 | r#"std::fmt::Arguments::new_v1(&[], &[std::fmt::ArgumentV1::new(&(arg1(a,b,c)),std::fmt::Display::fmt),std::fmt::ArgumentV1::new(&(arg2),std::fmt::Display::fmt),])"# | ||
690 | ); | 700 | ); |
691 | } | 701 | } |
692 | 702 | ||
693 | #[test] | 703 | #[test] |
694 | fn test_format_args_expand_with_comma_exprs() { | 704 | fn test_format_args_expand_with_comma_exprs() { |
695 | let expanded = expand_builtin_macro( | 705 | check_expansion( |
696 | r#" | 706 | r#" |
697 | #[rustc_builtin_macro] | 707 | #[rustc_builtin_macro] |
698 | macro_rules! format_args { | 708 | macro_rules! format_args { |
@@ -701,17 +711,15 @@ mod tests { | |||
701 | } | 711 | } |
702 | format_args!("{} {:?}", a::<A,B>(), b); | 712 | format_args!("{} {:?}", a::<A,B>(), b); |
703 | "#, | 713 | "#, |
704 | ); | 714 | expect![[ |
705 | 715 | r#"std::fmt::Arguments::new_v1(&[], &[std::fmt::ArgumentV1::new(&(a::<A,B>()),std::fmt::Display::fmt),std::fmt::ArgumentV1::new(&(b),std::fmt::Display::fmt),])"# | |
706 | assert_eq!( | 716 | ]], |
707 | expanded, | ||
708 | r#"std::fmt::Arguments::new_v1(&[], &[std::fmt::ArgumentV1::new(&(a::<A,B>()),std::fmt::Display::fmt),std::fmt::ArgumentV1::new(&(b),std::fmt::Display::fmt),])"# | ||
709 | ); | 717 | ); |
710 | } | 718 | } |
711 | 719 | ||
712 | #[test] | 720 | #[test] |
713 | fn test_include_bytes_expand() { | 721 | fn test_include_bytes_expand() { |
714 | let expanded = expand_builtin_macro( | 722 | check_expansion( |
715 | r#" | 723 | r#" |
716 | #[rustc_builtin_macro] | 724 | #[rustc_builtin_macro] |
717 | macro_rules! include_bytes { | 725 | macro_rules! include_bytes { |
@@ -720,21 +728,19 @@ mod tests { | |||
720 | } | 728 | } |
721 | include_bytes("foo"); | 729 | include_bytes("foo"); |
722 | "#, | 730 | "#, |
731 | expect![[r#"b"""#]], | ||
723 | ); | 732 | ); |
724 | |||
725 | assert_eq!(expanded, r#"b"""#); | ||
726 | } | 733 | } |
727 | 734 | ||
728 | #[test] | 735 | #[test] |
729 | fn test_concat_expand() { | 736 | fn test_concat_expand() { |
730 | let expanded = expand_builtin_macro( | 737 | check_expansion( |
731 | r##" | 738 | r##" |
732 | #[rustc_builtin_macro] | 739 | #[rustc_builtin_macro] |
733 | macro_rules! concat {} | 740 | macro_rules! concat {} |
734 | concat!("foo", "r", 0, r#"bar"#, false); | 741 | concat!("foo", "r", 0, r#"bar"#, false); |
735 | "##, | 742 | "##, |
743 | expect![[r#""foor0barfalse""#]], | ||
736 | ); | 744 | ); |
737 | |||
738 | assert_eq!(expanded, r#""foor0barfalse""#); | ||
739 | } | 745 | } |
740 | } | 746 | } |
diff --git a/crates/hir_expand/src/name.rs b/crates/hir_expand/src/name.rs index c94fb580a..e833e032c 100644 --- a/crates/hir_expand/src/name.rs +++ b/crates/hir_expand/src/name.rs | |||
@@ -154,6 +154,7 @@ pub mod known { | |||
154 | macro_rules, | 154 | macro_rules, |
155 | derive, | 155 | derive, |
156 | doc, | 156 | doc, |
157 | cfg, | ||
157 | cfg_attr, | 158 | cfg_attr, |
158 | // Components of known path (value or mod name) | 159 | // Components of known path (value or mod name) |
159 | std, | 160 | std, |
diff --git a/crates/hir_expand/src/quote.rs b/crates/hir_expand/src/quote.rs index 219bc2097..08bc5aa49 100644 --- a/crates/hir_expand/src/quote.rs +++ b/crates/hir_expand/src/quote.rs | |||
@@ -188,8 +188,9 @@ macro_rules! impl_to_to_tokentrees { | |||
188 | 188 | ||
189 | impl_to_to_tokentrees! { | 189 | impl_to_to_tokentrees! { |
190 | u32 => self { tt::Literal{text: self.to_string().into(), id: tt::TokenId::unspecified()} }; | 190 | u32 => self { tt::Literal{text: self.to_string().into(), id: tt::TokenId::unspecified()} }; |
191 | usize => self { tt::Literal{text: self.to_string().into(), id: tt::TokenId::unspecified()}}; | 191 | usize => self { tt::Literal{text: self.to_string().into(), id: tt::TokenId::unspecified()} }; |
192 | i32 => self { tt::Literal{text: self.to_string().into(), id: tt::TokenId::unspecified()}}; | 192 | i32 => self { tt::Literal{text: self.to_string().into(), id: tt::TokenId::unspecified()} }; |
193 | bool => self { tt::Ident{text: self.to_string().into(), id: tt::TokenId::unspecified()} }; | ||
193 | tt::Leaf => self { self }; | 194 | tt::Leaf => self { self }; |
194 | tt::Literal => self { self }; | 195 | tt::Literal => self { self }; |
195 | tt::Ident => self { self }; | 196 | tt::Ident => self { self }; |
diff --git a/crates/hir_ty/Cargo.toml b/crates/hir_ty/Cargo.toml index 6131ebee8..b9c93f56f 100644 --- a/crates/hir_ty/Cargo.toml +++ b/crates/hir_ty/Cargo.toml | |||
@@ -29,9 +29,9 @@ hir_expand = { path = "../hir_expand", version = "0.0.0" } | |||
29 | base_db = { path = "../base_db", version = "0.0.0" } | 29 | base_db = { path = "../base_db", version = "0.0.0" } |
30 | profile = { path = "../profile", version = "0.0.0" } | 30 | profile = { path = "../profile", version = "0.0.0" } |
31 | syntax = { path = "../syntax", version = "0.0.0" } | 31 | syntax = { path = "../syntax", version = "0.0.0" } |
32 | test_utils = { path = "../test_utils", version = "0.0.0" } | ||
33 | 32 | ||
34 | [dev-dependencies] | 33 | [dev-dependencies] |
34 | test_utils = { path = "../test_utils" } | ||
35 | expect-test = "1.1" | 35 | expect-test = "1.1" |
36 | tracing = "0.1" | 36 | tracing = "0.1" |
37 | tracing-subscriber = { version = "0.2", default-features = false, features = ["env-filter", "registry"] } | 37 | tracing-subscriber = { version = "0.2", default-features = false, features = ["env-filter", "registry"] } |
diff --git a/crates/hir_ty/src/diagnostics.rs b/crates/hir_ty/src/diagnostics.rs index 6bca7aa0d..86f937e1d 100644 --- a/crates/hir_ty/src/diagnostics.rs +++ b/crates/hir_ty/src/diagnostics.rs | |||
@@ -706,6 +706,35 @@ fn x(a: S) { | |||
706 | } | 706 | } |
707 | 707 | ||
708 | #[test] | 708 | #[test] |
709 | fn import_extern_crate_clash_with_inner_item() { | ||
710 | // This is more of a resolver test, but doesn't really work with the hir_def testsuite. | ||
711 | |||
712 | check_diagnostics( | ||
713 | r#" | ||
714 | //- /lib.rs crate:lib deps:jwt | ||
715 | mod permissions; | ||
716 | |||
717 | use permissions::jwt; | ||
718 | |||
719 | fn f() { | ||
720 | fn inner() {} | ||
721 | jwt::Claims {}; // should resolve to the local one with 0 fields, and not get a diagnostic | ||
722 | } | ||
723 | |||
724 | //- /permissions.rs | ||
725 | pub mod jwt { | ||
726 | pub struct Claims {} | ||
727 | } | ||
728 | |||
729 | //- /jwt/lib.rs crate:jwt | ||
730 | pub struct Claims { | ||
731 | field: u8, | ||
732 | } | ||
733 | "#, | ||
734 | ); | ||
735 | } | ||
736 | |||
737 | #[test] | ||
709 | fn break_outside_of_loop() { | 738 | fn break_outside_of_loop() { |
710 | check_diagnostics( | 739 | check_diagnostics( |
711 | r#" | 740 | r#" |
diff --git a/crates/hir_ty/src/diagnostics/decl_check.rs b/crates/hir_ty/src/diagnostics/decl_check.rs index e230f9765..3605ca581 100644 --- a/crates/hir_ty/src/diagnostics/decl_check.rs +++ b/crates/hir_ty/src/diagnostics/decl_check.rs | |||
@@ -99,9 +99,14 @@ impl<'a, 'b> DeclValidator<'a, 'b> { | |||
99 | let body = self.db.body(func.into()); | 99 | let body = self.db.body(func.into()); |
100 | 100 | ||
101 | // Recursively validate inner scope items, such as static variables and constants. | 101 | // Recursively validate inner scope items, such as static variables and constants. |
102 | for (item_id, _) in body.item_scope.values() { | 102 | let db = self.db; |
103 | let mut validator = DeclValidator::new(self.db, self.krate, self.sink); | 103 | for block_def_map in body.block_scopes.iter().filter_map(|block| db.block_def_map(*block)) { |
104 | validator.validate_item(item_id); | 104 | for (_, module) in block_def_map.modules() { |
105 | for (def_id, _) in module.scope.values() { | ||
106 | let mut validator = DeclValidator::new(self.db, self.krate, self.sink); | ||
107 | validator.validate_item(def_id); | ||
108 | } | ||
109 | } | ||
105 | } | 110 | } |
106 | 111 | ||
107 | // Check whether non-snake case identifiers are allowed for this function. | 112 | // Check whether non-snake case identifiers are allowed for this function. |
diff --git a/crates/hir_ty/src/display.rs b/crates/hir_ty/src/display.rs index a0882a2a1..ab51cb0a6 100644 --- a/crates/hir_ty/src/display.rs +++ b/crates/hir_ty/src/display.rs | |||
@@ -6,7 +6,7 @@ use arrayvec::ArrayVec; | |||
6 | use chalk_ir::Mutability; | 6 | use chalk_ir::Mutability; |
7 | use hir_def::{ | 7 | use hir_def::{ |
8 | db::DefDatabase, find_path, generics::TypeParamProvenance, item_scope::ItemInNs, | 8 | db::DefDatabase, find_path, generics::TypeParamProvenance, item_scope::ItemInNs, |
9 | AssocContainerId, HasModule, Lookup, ModuleId, TraitId, | 9 | AssocContainerId, Lookup, ModuleId, TraitId, |
10 | }; | 10 | }; |
11 | use hir_expand::name::Name; | 11 | use hir_expand::name::Name; |
12 | 12 | ||
@@ -611,7 +611,7 @@ impl HirDisplay for CallableSig { | |||
611 | } | 611 | } |
612 | 612 | ||
613 | fn fn_traits(db: &dyn DefDatabase, trait_: TraitId) -> impl Iterator<Item = TraitId> { | 613 | fn fn_traits(db: &dyn DefDatabase, trait_: TraitId) -> impl Iterator<Item = TraitId> { |
614 | let krate = trait_.lookup(db).container.module(db).krate(); | 614 | let krate = trait_.lookup(db).container.krate(); |
615 | let fn_traits = [ | 615 | let fn_traits = [ |
616 | db.lang_item(krate, "fn".into()), | 616 | db.lang_item(krate, "fn".into()), |
617 | db.lang_item(krate, "fn_mut".into()), | 617 | db.lang_item(krate, "fn_mut".into()), |
diff --git a/crates/hir_ty/src/infer/path.rs b/crates/hir_ty/src/infer/path.rs index 5d541104e..ae3554bac 100644 --- a/crates/hir_ty/src/infer/path.rs +++ b/crates/hir_ty/src/infer/path.rs | |||
@@ -260,7 +260,7 @@ impl<'a> InferenceContext<'a> { | |||
260 | })); | 260 | })); |
261 | Some(trait_substs) | 261 | Some(trait_substs) |
262 | } | 262 | } |
263 | AssocContainerId::ContainerId(_) => None, | 263 | AssocContainerId::ModuleId(_) => None, |
264 | }; | 264 | }; |
265 | 265 | ||
266 | self.write_assoc_resolution(id, item); | 266 | self.write_assoc_resolution(id, item); |
diff --git a/crates/hir_ty/src/lower.rs b/crates/hir_ty/src/lower.rs index b90fdc382..5fa83567b 100644 --- a/crates/hir_ty/src/lower.rs +++ b/crates/hir_ty/src/lower.rs | |||
@@ -1130,8 +1130,8 @@ impl CallableDefId { | |||
1130 | let db = db.upcast(); | 1130 | let db = db.upcast(); |
1131 | match self { | 1131 | match self { |
1132 | CallableDefId::FunctionId(f) => f.lookup(db).module(db), | 1132 | CallableDefId::FunctionId(f) => f.lookup(db).module(db), |
1133 | CallableDefId::StructId(s) => s.lookup(db).container.module(db), | 1133 | CallableDefId::StructId(s) => s.lookup(db).container, |
1134 | CallableDefId::EnumVariantId(e) => e.parent.lookup(db).container.module(db), | 1134 | CallableDefId::EnumVariantId(e) => e.parent.lookup(db).container, |
1135 | } | 1135 | } |
1136 | .krate() | 1136 | .krate() |
1137 | } | 1137 | } |
diff --git a/crates/hir_ty/src/method_resolution.rs b/crates/hir_ty/src/method_resolution.rs index 24db33c49..ccc12c075 100644 --- a/crates/hir_ty/src/method_resolution.rs +++ b/crates/hir_ty/src/method_resolution.rs | |||
@@ -267,7 +267,7 @@ impl Ty { | |||
267 | LangItemTarget::ImplDefId(it) => Some(it), | 267 | LangItemTarget::ImplDefId(it) => Some(it), |
268 | _ => None, | 268 | _ => None, |
269 | }) | 269 | }) |
270 | .map(|it| it.lookup(db.upcast()).container.module(db.upcast()).krate()) | 270 | .map(|it| it.lookup(db.upcast()).container.krate()) |
271 | .collect(); | 271 | .collect(); |
272 | Some(res) | 272 | Some(res) |
273 | } | 273 | } |
@@ -715,7 +715,7 @@ fn transform_receiver_ty( | |||
715 | .fill_with_unknown() | 715 | .fill_with_unknown() |
716 | .build() | 716 | .build() |
717 | } | 717 | } |
718 | AssocContainerId::ContainerId(_) => unreachable!(), | 718 | AssocContainerId::ModuleId(_) => unreachable!(), |
719 | }; | 719 | }; |
720 | let sig = db.callable_item_signature(function_id.into()); | 720 | let sig = db.callable_item_signature(function_id.into()); |
721 | Some(sig.value.params()[0].clone().subst_bound_vars(&substs)) | 721 | Some(sig.value.params()[0].clone().subst_bound_vars(&substs)) |
diff --git a/crates/hir_ty/src/tests.rs b/crates/hir_ty/src/tests.rs index 7386a4e7b..fc770ea60 100644 --- a/crates/hir_ty/src/tests.rs +++ b/crates/hir_ty/src/tests.rs | |||
@@ -13,7 +13,7 @@ use std::{env, sync::Arc}; | |||
13 | use base_db::{fixture::WithFixture, FileRange, SourceDatabase, SourceDatabaseExt}; | 13 | use base_db::{fixture::WithFixture, FileRange, SourceDatabase, SourceDatabaseExt}; |
14 | use expect_test::Expect; | 14 | use expect_test::Expect; |
15 | use hir_def::{ | 15 | use hir_def::{ |
16 | body::{BodySourceMap, SyntheticSyntax}, | 16 | body::{Body, BodySourceMap, SyntheticSyntax}, |
17 | child_by_source::ChildBySource, | 17 | child_by_source::ChildBySource, |
18 | db::DefDatabase, | 18 | db::DefDatabase, |
19 | item_scope::ItemScope, | 19 | item_scope::ItemScope, |
@@ -234,13 +234,13 @@ fn visit_module( | |||
234 | let def = it.into(); | 234 | let def = it.into(); |
235 | cb(def); | 235 | cb(def); |
236 | let body = db.body(def); | 236 | let body = db.body(def); |
237 | visit_scope(db, crate_def_map, &body.item_scope, cb); | 237 | visit_body(db, &body, cb); |
238 | } | 238 | } |
239 | AssocItemId::ConstId(it) => { | 239 | AssocItemId::ConstId(it) => { |
240 | let def = it.into(); | 240 | let def = it.into(); |
241 | cb(def); | 241 | cb(def); |
242 | let body = db.body(def); | 242 | let body = db.body(def); |
243 | visit_scope(db, crate_def_map, &body.item_scope, cb); | 243 | visit_body(db, &body, cb); |
244 | } | 244 | } |
245 | AssocItemId::TypeAliasId(_) => (), | 245 | AssocItemId::TypeAliasId(_) => (), |
246 | } | 246 | } |
@@ -259,19 +259,19 @@ fn visit_module( | |||
259 | let def = it.into(); | 259 | let def = it.into(); |
260 | cb(def); | 260 | cb(def); |
261 | let body = db.body(def); | 261 | let body = db.body(def); |
262 | visit_scope(db, crate_def_map, &body.item_scope, cb); | 262 | visit_body(db, &body, cb); |
263 | } | 263 | } |
264 | ModuleDefId::ConstId(it) => { | 264 | ModuleDefId::ConstId(it) => { |
265 | let def = it.into(); | 265 | let def = it.into(); |
266 | cb(def); | 266 | cb(def); |
267 | let body = db.body(def); | 267 | let body = db.body(def); |
268 | visit_scope(db, crate_def_map, &body.item_scope, cb); | 268 | visit_body(db, &body, cb); |
269 | } | 269 | } |
270 | ModuleDefId::StaticId(it) => { | 270 | ModuleDefId::StaticId(it) => { |
271 | let def = it.into(); | 271 | let def = it.into(); |
272 | cb(def); | 272 | cb(def); |
273 | let body = db.body(def); | 273 | let body = db.body(def); |
274 | visit_scope(db, crate_def_map, &body.item_scope, cb); | 274 | visit_body(db, &body, cb); |
275 | } | 275 | } |
276 | ModuleDefId::TraitId(it) => { | 276 | ModuleDefId::TraitId(it) => { |
277 | let trait_data = db.trait_data(it); | 277 | let trait_data = db.trait_data(it); |
@@ -288,6 +288,14 @@ fn visit_module( | |||
288 | } | 288 | } |
289 | } | 289 | } |
290 | } | 290 | } |
291 | |||
292 | fn visit_body(db: &TestDB, body: &Body, cb: &mut dyn FnMut(DefWithBodyId)) { | ||
293 | for def_map in body.block_scopes.iter().filter_map(|block| db.block_def_map(*block)) { | ||
294 | for (mod_id, _) in def_map.modules() { | ||
295 | visit_module(db, &def_map, mod_id, cb); | ||
296 | } | ||
297 | } | ||
298 | } | ||
291 | } | 299 | } |
292 | 300 | ||
293 | fn ellipsize(mut text: String, max_len: usize) -> String { | 301 | fn ellipsize(mut text: String, max_len: usize) -> String { |
diff --git a/crates/hir_ty/src/tests/traits.rs b/crates/hir_ty/src/tests/traits.rs index 528092082..e185b1c0a 100644 --- a/crates/hir_ty/src/tests/traits.rs +++ b/crates/hir_ty/src/tests/traits.rs | |||
@@ -3174,6 +3174,39 @@ fn f() { | |||
3174 | } | 3174 | } |
3175 | 3175 | ||
3176 | #[test] | 3176 | #[test] |
3177 | fn trait_in_scope_with_inner_item() { | ||
3178 | check_infer( | ||
3179 | r#" | ||
3180 | mod m { | ||
3181 | pub trait Tr { | ||
3182 | fn method(&self) -> u8 { 0 } | ||
3183 | } | ||
3184 | |||
3185 | impl Tr for () {} | ||
3186 | } | ||
3187 | |||
3188 | use m::Tr; | ||
3189 | |||
3190 | fn f() { | ||
3191 | fn inner() { | ||
3192 | ().method(); | ||
3193 | //^^^^^^^^^^^ u8 | ||
3194 | } | ||
3195 | } | ||
3196 | "#, | ||
3197 | expect![[r#" | ||
3198 | 46..50 'self': &Self | ||
3199 | 58..63 '{ 0 }': u8 | ||
3200 | 60..61 '0': u8 | ||
3201 | 115..185 '{ ... } }': () | ||
3202 | 132..183 '{ ... }': () | ||
3203 | 142..144 '()': () | ||
3204 | 142..153 '().method()': u8 | ||
3205 | "#]], | ||
3206 | ); | ||
3207 | } | ||
3208 | |||
3209 | #[test] | ||
3177 | fn inner_use_in_block() { | 3210 | fn inner_use_in_block() { |
3178 | check_types( | 3211 | check_types( |
3179 | r#" | 3212 | r#" |
diff --git a/crates/hir_ty/src/traits/chalk.rs b/crates/hir_ty/src/traits/chalk.rs index 4378a9723..565672b6b 100644 --- a/crates/hir_ty/src/traits/chalk.rs +++ b/crates/hir_ty/src/traits/chalk.rs | |||
@@ -424,7 +424,7 @@ pub(crate) fn trait_datum_query( | |||
424 | let bound_vars = Substs::bound_vars(&generic_params, DebruijnIndex::INNERMOST); | 424 | let bound_vars = Substs::bound_vars(&generic_params, DebruijnIndex::INNERMOST); |
425 | let flags = rust_ir::TraitFlags { | 425 | let flags = rust_ir::TraitFlags { |
426 | auto: trait_data.auto, | 426 | auto: trait_data.auto, |
427 | upstream: trait_.lookup(db.upcast()).container.module(db.upcast()).krate() != krate, | 427 | upstream: trait_.lookup(db.upcast()).container.krate() != krate, |
428 | non_enumerable: true, | 428 | non_enumerable: true, |
429 | coinductive: false, // only relevant for Chalk testing | 429 | coinductive: false, // only relevant for Chalk testing |
430 | // FIXME: set these flags correctly | 430 | // FIXME: set these flags correctly |
@@ -548,7 +548,7 @@ fn impl_def_datum( | |||
548 | let generic_params = generics(db.upcast(), impl_id.into()); | 548 | let generic_params = generics(db.upcast(), impl_id.into()); |
549 | let bound_vars = Substs::bound_vars(&generic_params, DebruijnIndex::INNERMOST); | 549 | let bound_vars = Substs::bound_vars(&generic_params, DebruijnIndex::INNERMOST); |
550 | let trait_ = trait_ref.trait_; | 550 | let trait_ = trait_ref.trait_; |
551 | let impl_type = if impl_id.lookup(db.upcast()).container.module(db.upcast()).krate() == krate { | 551 | let impl_type = if impl_id.lookup(db.upcast()).container.krate() == krate { |
552 | rust_ir::ImplType::Local | 552 | rust_ir::ImplType::Local |
553 | } else { | 553 | } else { |
554 | rust_ir::ImplType::External | 554 | rust_ir::ImplType::External |
diff --git a/crates/hir_ty/src/utils.rs b/crates/hir_ty/src/utils.rs index 65b79df0d..7351e4e54 100644 --- a/crates/hir_ty/src/utils.rs +++ b/crates/hir_ty/src/utils.rs | |||
@@ -259,6 +259,6 @@ fn parent_generic_def(db: &dyn DefDatabase, def: GenericDefId) -> Option<Generic | |||
259 | match container { | 259 | match container { |
260 | AssocContainerId::ImplId(it) => Some(it.into()), | 260 | AssocContainerId::ImplId(it) => Some(it.into()), |
261 | AssocContainerId::TraitId(it) => Some(it.into()), | 261 | AssocContainerId::TraitId(it) => Some(it.into()), |
262 | AssocContainerId::ContainerId(_) => None, | 262 | AssocContainerId::ModuleId(_) => None, |
263 | } | 263 | } |
264 | } | 264 | } |
diff --git a/crates/ide/Cargo.toml b/crates/ide/Cargo.toml index f7c5efaf3..107bd8432 100644 --- a/crates/ide/Cargo.toml +++ b/crates/ide/Cargo.toml | |||
@@ -27,7 +27,6 @@ text_edit = { path = "../text_edit", version = "0.0.0" } | |||
27 | ide_db = { path = "../ide_db", version = "0.0.0" } | 27 | ide_db = { path = "../ide_db", version = "0.0.0" } |
28 | cfg = { path = "../cfg", version = "0.0.0" } | 28 | cfg = { path = "../cfg", version = "0.0.0" } |
29 | profile = { path = "../profile", version = "0.0.0" } | 29 | profile = { path = "../profile", version = "0.0.0" } |
30 | test_utils = { path = "../test_utils", version = "0.0.0" } | ||
31 | ide_assists = { path = "../ide_assists", version = "0.0.0" } | 30 | ide_assists = { path = "../ide_assists", version = "0.0.0" } |
32 | ide_ssr = { path = "../ide_ssr", version = "0.0.0" } | 31 | ide_ssr = { path = "../ide_ssr", version = "0.0.0" } |
33 | ide_completion = { path = "../ide_completion", version = "0.0.0" } | 32 | ide_completion = { path = "../ide_completion", version = "0.0.0" } |
@@ -37,4 +36,5 @@ ide_completion = { path = "../ide_completion", version = "0.0.0" } | |||
37 | hir = { path = "../hir", version = "0.0.0" } | 36 | hir = { path = "../hir", version = "0.0.0" } |
38 | 37 | ||
39 | [dev-dependencies] | 38 | [dev-dependencies] |
39 | test_utils = { path = "../test_utils" } | ||
40 | expect-test = "1.1" | 40 | expect-test = "1.1" |
diff --git a/crates/ide/src/display/short_label.rs b/crates/ide/src/display/short_label.rs index 84b8883de..2df9266b4 100644 --- a/crates/ide/src/display/short_label.rs +++ b/crates/ide/src/display/short_label.rs | |||
@@ -71,11 +71,7 @@ impl ShortLabel for ast::TypeAlias { | |||
71 | 71 | ||
72 | impl ShortLabel for ast::Const { | 72 | impl ShortLabel for ast::Const { |
73 | fn short_label(&self) -> Option<String> { | 73 | fn short_label(&self) -> Option<String> { |
74 | let mut new_buf = short_label_from_ty(self, self.ty(), "const ")?; | 74 | short_label_from_ty(self, self.ty(), "const ") |
75 | if let Some(expr) = self.body() { | ||
76 | format_to!(new_buf, " = {}", expr.syntax()); | ||
77 | } | ||
78 | Some(new_buf) | ||
79 | } | 75 | } |
80 | } | 76 | } |
81 | 77 | ||
diff --git a/crates/ide/src/hover.rs b/crates/ide/src/hover.rs index 5d1cc2052..ea45086ce 100644 --- a/crates/ide/src/hover.rs +++ b/crates/ide/src/hover.rs | |||
@@ -1,3 +1,4 @@ | |||
1 | use either::Either; | ||
1 | use hir::{ | 2 | use hir::{ |
2 | Adt, AsAssocItem, AssocItemContainer, FieldSource, GenericParam, HasAttrs, HasSource, | 3 | Adt, AsAssocItem, AssocItemContainer, FieldSource, GenericParam, HasAttrs, HasSource, |
3 | HirDisplay, Module, ModuleDef, ModuleSource, Semantics, | 4 | HirDisplay, Module, ModuleDef, ModuleSource, Semantics, |
@@ -366,7 +367,7 @@ fn hover_for_definition( | |||
366 | .and_then(|fd| hover_for_builtin(fd, it)) | 367 | .and_then(|fd| hover_for_builtin(fd, it)) |
367 | .or_else(|| Some(Markup::fenced_block(&it.name()))), | 368 | .or_else(|| Some(Markup::fenced_block(&it.name()))), |
368 | }, | 369 | }, |
369 | Definition::Local(it) => Some(Markup::fenced_block(&it.ty(db).display(db))), | 370 | Definition::Local(it) => hover_for_local(it, db), |
370 | Definition::SelfType(impl_def) => { | 371 | Definition::SelfType(impl_def) => { |
371 | impl_def.target_ty(db).as_adt().and_then(|adt| match adt { | 372 | impl_def.target_ty(db).as_adt().and_then(|adt| match adt { |
372 | Adt::Struct(it) => from_def_source(db, it, mod_path), | 373 | Adt::Struct(it) => from_def_source(db, it, mod_path), |
@@ -405,6 +406,29 @@ fn hover_for_definition( | |||
405 | } | 406 | } |
406 | } | 407 | } |
407 | 408 | ||
409 | fn hover_for_local(it: hir::Local, db: &RootDatabase) -> Option<Markup> { | ||
410 | let ty = it.ty(db); | ||
411 | let ty = ty.display(db); | ||
412 | let is_mut = if it.is_mut(db) { "mut " } else { "" }; | ||
413 | let desc = match it.source(db).value { | ||
414 | Either::Left(ident) => { | ||
415 | let name = it.name(db).unwrap(); | ||
416 | let let_kw = if ident | ||
417 | .syntax() | ||
418 | .parent() | ||
419 | .map_or(false, |p| p.kind() == LET_STMT || p.kind() == CONDITION) | ||
420 | { | ||
421 | "let " | ||
422 | } else { | ||
423 | "" | ||
424 | }; | ||
425 | format!("{}{}{}: {}", let_kw, is_mut, name, ty) | ||
426 | } | ||
427 | Either::Right(_) => format!("{}self: {}", is_mut, ty), | ||
428 | }; | ||
429 | hover_markup(None, Some(desc), None) | ||
430 | } | ||
431 | |||
408 | fn hover_for_keyword( | 432 | fn hover_for_keyword( |
409 | sema: &Semantics<RootDatabase>, | 433 | sema: &Semantics<RootDatabase>, |
410 | links_in_hover: bool, | 434 | links_in_hover: bool, |
@@ -574,7 +598,7 @@ fn main() { | |||
574 | *iter* | 598 | *iter* |
575 | 599 | ||
576 | ```rust | 600 | ```rust |
577 | Iter<Scan<OtherStruct<OtherStruct<i32>>, |&mut u32, &u32, &mut u32| -> Option<u32>, u32>> | 601 | let mut iter: Iter<Scan<OtherStruct<OtherStruct<i32>>, |&mut u32, &u32, &mut u32| -> Option<u32>, u32>> |
578 | ``` | 602 | ``` |
579 | "#]], | 603 | "#]], |
580 | ); | 604 | ); |
@@ -798,7 +822,7 @@ fn main() { | |||
798 | ``` | 822 | ``` |
799 | 823 | ||
800 | ```rust | 824 | ```rust |
801 | const foo: u32 = 123 | 825 | const foo: u32 |
802 | ``` | 826 | ``` |
803 | "#]], | 827 | "#]], |
804 | ); | 828 | ); |
@@ -831,7 +855,7 @@ fn main() { | |||
831 | *zz* | 855 | *zz* |
832 | 856 | ||
833 | ```rust | 857 | ```rust |
834 | Test<i32, u8> | 858 | let zz: Test<i32, u8> |
835 | ``` | 859 | ``` |
836 | "#]], | 860 | "#]], |
837 | ); | 861 | ); |
@@ -870,7 +894,7 @@ fn main() { let b$0ar = Some(12); } | |||
870 | *bar* | 894 | *bar* |
871 | 895 | ||
872 | ```rust | 896 | ```rust |
873 | Option<i32> | 897 | let bar: Option<i32> |
874 | ``` | 898 | ``` |
875 | "#]], | 899 | "#]], |
876 | ); | 900 | ); |
@@ -938,7 +962,7 @@ fn main() { | |||
938 | *foo* | 962 | *foo* |
939 | 963 | ||
940 | ```rust | 964 | ```rust |
941 | i32 | 965 | foo: i32 |
942 | ``` | 966 | ``` |
943 | "#]], | 967 | "#]], |
944 | ) | 968 | ) |
@@ -952,7 +976,7 @@ fn main() { | |||
952 | *foo* | 976 | *foo* |
953 | 977 | ||
954 | ```rust | 978 | ```rust |
955 | i32 | 979 | foo: i32 |
956 | ``` | 980 | ``` |
957 | "#]], | 981 | "#]], |
958 | ) | 982 | ) |
@@ -966,7 +990,7 @@ fn main() { | |||
966 | *foo* | 990 | *foo* |
967 | 991 | ||
968 | ```rust | 992 | ```rust |
969 | i32 | 993 | foo: i32 |
970 | ``` | 994 | ``` |
971 | "#]], | 995 | "#]], |
972 | ) | 996 | ) |
@@ -980,7 +1004,7 @@ fn main() { | |||
980 | *foo* | 1004 | *foo* |
981 | 1005 | ||
982 | ```rust | 1006 | ```rust |
983 | i32 | 1007 | foo: i32 |
984 | ``` | 1008 | ``` |
985 | "#]], | 1009 | "#]], |
986 | ) | 1010 | ) |
@@ -1000,7 +1024,7 @@ fn main() { | |||
1000 | *_x* | 1024 | *_x* |
1001 | 1025 | ||
1002 | ```rust | 1026 | ```rust |
1003 | impl Deref<Target = u8> + DerefMut<Target = u8> | 1027 | _x: impl Deref<Target = u8> + DerefMut<Target = u8> |
1004 | ``` | 1028 | ``` |
1005 | "#]], | 1029 | "#]], |
1006 | ) | 1030 | ) |
@@ -1022,7 +1046,7 @@ fn main() { let foo_$0test = Thing::new(); } | |||
1022 | *foo_test* | 1046 | *foo_test* |
1023 | 1047 | ||
1024 | ```rust | 1048 | ```rust |
1025 | Thing | 1049 | let foo_test: Thing |
1026 | ``` | 1050 | ``` |
1027 | "#]], | 1051 | "#]], |
1028 | ) | 1052 | ) |
@@ -1081,7 +1105,7 @@ fn main() { | |||
1081 | ``` | 1105 | ``` |
1082 | 1106 | ||
1083 | ```rust | 1107 | ```rust |
1084 | const C: u32 = 1 | 1108 | const C: u32 |
1085 | ``` | 1109 | ``` |
1086 | "#]], | 1110 | "#]], |
1087 | ) | 1111 | ) |
@@ -1182,7 +1206,7 @@ fn y() { | |||
1182 | *x* | 1206 | *x* |
1183 | 1207 | ||
1184 | ```rust | 1208 | ```rust |
1185 | i32 | 1209 | let x: i32 |
1186 | ``` | 1210 | ``` |
1187 | "#]], | 1211 | "#]], |
1188 | ) | 1212 | ) |
@@ -1259,7 +1283,7 @@ fn foo(bar:u32) { let a = id!(ba$0r); } | |||
1259 | *bar* | 1283 | *bar* |
1260 | 1284 | ||
1261 | ```rust | 1285 | ```rust |
1262 | u32 | 1286 | bar: u32 |
1263 | ``` | 1287 | ``` |
1264 | "#]], | 1288 | "#]], |
1265 | ); | 1289 | ); |
@@ -1277,7 +1301,7 @@ fn foo(bar:u32) { let a = id!(ba$0r); } | |||
1277 | *bar* | 1301 | *bar* |
1278 | 1302 | ||
1279 | ```rust | 1303 | ```rust |
1280 | u32 | 1304 | bar: u32 |
1281 | ``` | 1305 | ``` |
1282 | "#]], | 1306 | "#]], |
1283 | ); | 1307 | ); |
@@ -3302,7 +3326,7 @@ fn main() { | |||
3302 | *f* | 3326 | *f* |
3303 | 3327 | ||
3304 | ```rust | 3328 | ```rust |
3305 | &i32 | 3329 | f: &i32 |
3306 | ``` | 3330 | ``` |
3307 | "#]], | 3331 | "#]], |
3308 | ); | 3332 | ); |
@@ -3321,7 +3345,7 @@ impl Foo { | |||
3321 | *self* | 3345 | *self* |
3322 | 3346 | ||
3323 | ```rust | 3347 | ```rust |
3324 | &Foo | 3348 | self: &Foo |
3325 | ``` | 3349 | ``` |
3326 | "#]], | 3350 | "#]], |
3327 | ); | 3351 | ); |
@@ -3341,7 +3365,7 @@ impl Foo { | |||
3341 | *self* | 3365 | *self* |
3342 | 3366 | ||
3343 | ```rust | 3367 | ```rust |
3344 | Arc<Foo> | 3368 | self: Arc<Foo> |
3345 | ``` | 3369 | ``` |
3346 | "#]], | 3370 | "#]], |
3347 | ); | 3371 | ); |
@@ -3537,7 +3561,7 @@ fn foo() { | |||
3537 | ``` | 3561 | ``` |
3538 | 3562 | ||
3539 | ```rust | 3563 | ```rust |
3540 | const FOO: usize = 3 | 3564 | const FOO: usize |
3541 | ``` | 3565 | ``` |
3542 | 3566 | ||
3543 | --- | 3567 | --- |
diff --git a/crates/ide/src/lib.rs b/crates/ide/src/lib.rs index f83ed65d5..0a493d2f3 100644 --- a/crates/ide/src/lib.rs +++ b/crates/ide/src/lib.rs | |||
@@ -41,6 +41,7 @@ mod parent_module; | |||
41 | mod references; | 41 | mod references; |
42 | mod fn_references; | 42 | mod fn_references; |
43 | mod runnables; | 43 | mod runnables; |
44 | mod ssr; | ||
44 | mod status; | 45 | mod status; |
45 | mod syntax_highlighting; | 46 | mod syntax_highlighting; |
46 | mod syntax_tree; | 47 | mod syntax_tree; |
@@ -51,6 +52,7 @@ mod doc_links; | |||
51 | use std::sync::Arc; | 52 | use std::sync::Arc; |
52 | 53 | ||
53 | use cfg::CfgOptions; | 54 | use cfg::CfgOptions; |
55 | |||
54 | use ide_db::base_db::{ | 56 | use ide_db::base_db::{ |
55 | salsa::{self, ParallelDatabase}, | 57 | salsa::{self, ParallelDatabase}, |
56 | CheckCanceled, Env, FileLoader, FileSet, SourceDatabase, VfsPath, | 58 | CheckCanceled, Env, FileLoader, FileSet, SourceDatabase, VfsPath, |
@@ -85,7 +87,7 @@ pub use crate::{ | |||
85 | pub use hir::{Documentation, Semantics}; | 87 | pub use hir::{Documentation, Semantics}; |
86 | pub use ide_assists::{Assist, AssistConfig, AssistId, AssistKind}; | 88 | pub use ide_assists::{Assist, AssistConfig, AssistId, AssistKind}; |
87 | pub use ide_completion::{ | 89 | pub use ide_completion::{ |
88 | CompletionConfig, CompletionItem, CompletionItemKind, CompletionScore, ImportEdit, | 90 | CompletionConfig, CompletionItem, CompletionItemKind, CompletionRelevance, ImportEdit, |
89 | InsertTextFormat, | 91 | InsertTextFormat, |
90 | }; | 92 | }; |
91 | pub use ide_db::{ | 93 | pub use ide_db::{ |
@@ -502,7 +504,11 @@ impl Analysis { | |||
502 | resolve: bool, | 504 | resolve: bool, |
503 | frange: FileRange, | 505 | frange: FileRange, |
504 | ) -> Cancelable<Vec<Assist>> { | 506 | ) -> Cancelable<Vec<Assist>> { |
505 | self.with_db(|db| Assist::get(db, config, resolve, frange)) | 507 | self.with_db(|db| { |
508 | let mut acc = Assist::get(db, config, resolve, frange); | ||
509 | ssr::add_ssr_assist(db, &mut acc, resolve, frange); | ||
510 | acc | ||
511 | }) | ||
506 | } | 512 | } |
507 | 513 | ||
508 | /// Computes the set of diagnostics for the given file. | 514 | /// Computes the set of diagnostics for the given file. |
diff --git a/crates/ide/src/references/rename.rs b/crates/ide/src/references/rename.rs index 05c73de88..1e378279d 100644 --- a/crates/ide/src/references/rename.rs +++ b/crates/ide/src/references/rename.rs | |||
@@ -21,7 +21,7 @@ use crate::{display::TryToNav, FilePosition, FileSystemEdit, RangeInfo, SourceCh | |||
21 | 21 | ||
22 | type RenameResult<T> = Result<T, RenameError>; | 22 | type RenameResult<T> = Result<T, RenameError>; |
23 | #[derive(Debug)] | 23 | #[derive(Debug)] |
24 | pub struct RenameError(pub(crate) String); | 24 | pub struct RenameError(String); |
25 | 25 | ||
26 | impl fmt::Display for RenameError { | 26 | impl fmt::Display for RenameError { |
27 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { | 27 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
@@ -47,16 +47,15 @@ pub(crate) fn prepare_rename( | |||
47 | let sema = Semantics::new(db); | 47 | let sema = Semantics::new(db); |
48 | let source_file = sema.parse(position.file_id); | 48 | let source_file = sema.parse(position.file_id); |
49 | let syntax = source_file.syntax(); | 49 | let syntax = source_file.syntax(); |
50 | let range = match &sema | 50 | let name_like = sema |
51 | .find_node_at_offset_with_descend(&syntax, position.offset) | 51 | .find_node_at_offset_with_descend(&syntax, position.offset) |
52 | .ok_or_else(|| format_err!("No references found at position"))? | 52 | .ok_or_else(|| format_err!("No references found at position"))?; |
53 | { | 53 | let node = match &name_like { |
54 | ast::NameLike::Name(it) => it.syntax(), | 54 | ast::NameLike::Name(it) => it.syntax(), |
55 | ast::NameLike::NameRef(it) => it.syntax(), | 55 | ast::NameLike::NameRef(it) => it.syntax(), |
56 | ast::NameLike::Lifetime(it) => it.syntax(), | 56 | ast::NameLike::Lifetime(it) => it.syntax(), |
57 | } | 57 | }; |
58 | .text_range(); | 58 | Ok(RangeInfo::new(sema.original_range(node).range, ())) |
59 | Ok(RangeInfo::new(range, ())) | ||
60 | } | 59 | } |
61 | 60 | ||
62 | // Feature: Rename | 61 | // Feature: Rename |
@@ -94,6 +93,7 @@ pub(crate) fn rename_with_semantics( | |||
94 | } | 93 | } |
95 | } | 94 | } |
96 | 95 | ||
96 | /// Called by the client when it is about to rename a file. | ||
97 | pub(crate) fn will_rename_file( | 97 | pub(crate) fn will_rename_file( |
98 | db: &RootDatabase, | 98 | db: &RootDatabase, |
99 | file_id: FileId, | 99 | file_id: FileId, |
@@ -545,6 +545,8 @@ mod tests { | |||
545 | 545 | ||
546 | use crate::{fixture, FileId}; | 546 | use crate::{fixture, FileId}; |
547 | 547 | ||
548 | use super::{RangeInfo, RenameError}; | ||
549 | |||
548 | fn check(new_name: &str, ra_fixture_before: &str, ra_fixture_after: &str) { | 550 | fn check(new_name: &str, ra_fixture_before: &str, ra_fixture_after: &str) { |
549 | let ra_fixture_after = &trim_indent(ra_fixture_after); | 551 | let ra_fixture_after = &trim_indent(ra_fixture_after); |
550 | let (analysis, position) = fixture::position(ra_fixture_before); | 552 | let (analysis, position) = fixture::position(ra_fixture_before); |
@@ -590,6 +592,45 @@ mod tests { | |||
590 | expect.assert_debug_eq(&source_change) | 592 | expect.assert_debug_eq(&source_change) |
591 | } | 593 | } |
592 | 594 | ||
595 | fn check_prepare(ra_fixture: &str, expect: Expect) { | ||
596 | let (analysis, position) = fixture::position(ra_fixture); | ||
597 | let result = analysis | ||
598 | .prepare_rename(position) | ||
599 | .unwrap_or_else(|err| panic!("PrepareRename was cancelled: {}", err)); | ||
600 | match result { | ||
601 | Ok(RangeInfo { range, info: () }) => { | ||
602 | let source = analysis.file_text(position.file_id).unwrap(); | ||
603 | expect.assert_eq(&format!("{:?}: {}", range, &source[range])) | ||
604 | } | ||
605 | Err(RenameError(err)) => expect.assert_eq(&err), | ||
606 | }; | ||
607 | } | ||
608 | |||
609 | #[test] | ||
610 | fn test_prepare_rename_namelikes() { | ||
611 | check_prepare(r"fn name$0<'lifetime>() {}", expect![[r#"3..7: name"#]]); | ||
612 | check_prepare(r"fn name<'lifetime$0>() {}", expect![[r#"8..17: 'lifetime"#]]); | ||
613 | check_prepare(r"fn name<'lifetime>() { name$0(); }", expect![[r#"23..27: name"#]]); | ||
614 | } | ||
615 | |||
616 | #[test] | ||
617 | fn test_prepare_rename_in_macro() { | ||
618 | check_prepare( | ||
619 | r"macro_rules! foo { | ||
620 | ($ident:ident) => { | ||
621 | pub struct $ident; | ||
622 | } | ||
623 | } | ||
624 | foo!(Foo$0);", | ||
625 | expect![[r#"83..86: Foo"#]], | ||
626 | ); | ||
627 | } | ||
628 | |||
629 | #[test] | ||
630 | fn test_prepare_rename_keyword() { | ||
631 | check_prepare(r"struct$0 Foo;", expect![[r#"No references found at position"#]]); | ||
632 | } | ||
633 | |||
593 | #[test] | 634 | #[test] |
594 | fn test_rename_to_underscore() { | 635 | fn test_rename_to_underscore() { |
595 | check("_", r#"fn main() { let i$0 = 1; }"#, r#"fn main() { let _ = 1; }"#); | 636 | check("_", r#"fn main() { let i$0 = 1; }"#, r#"fn main() { let _ = 1; }"#); |
diff --git a/crates/ide/src/ssr.rs b/crates/ide/src/ssr.rs new file mode 100644 index 000000000..f3638d928 --- /dev/null +++ b/crates/ide/src/ssr.rs | |||
@@ -0,0 +1,259 @@ | |||
1 | //! This module provides an SSR assist. It is not desirable to include this | ||
2 | //! assist in ide_assists because that would require the ide_assists crate | ||
3 | //! depend on the ide_ssr crate. | ||
4 | |||
5 | use ide_assists::{Assist, AssistId, AssistKind, GroupLabel}; | ||
6 | use ide_db::{base_db::FileRange, label::Label, source_change::SourceChange, RootDatabase}; | ||
7 | |||
8 | pub(crate) fn add_ssr_assist( | ||
9 | db: &RootDatabase, | ||
10 | base: &mut Vec<Assist>, | ||
11 | resolve: bool, | ||
12 | frange: FileRange, | ||
13 | ) -> Option<()> { | ||
14 | let (match_finder, comment_range) = ide_ssr::ssr_from_comment(db, frange)?; | ||
15 | |||
16 | let (source_change_for_file, source_change_for_workspace) = if resolve { | ||
17 | let edits = match_finder.edits(); | ||
18 | |||
19 | let source_change_for_file = { | ||
20 | let text_edit_for_file = edits.get(&frange.file_id).cloned().unwrap_or_default(); | ||
21 | SourceChange::from_text_edit(frange.file_id, text_edit_for_file) | ||
22 | }; | ||
23 | |||
24 | let source_change_for_workspace = SourceChange::from(match_finder.edits()); | ||
25 | |||
26 | (Some(source_change_for_file), Some(source_change_for_workspace)) | ||
27 | } else { | ||
28 | (None, None) | ||
29 | }; | ||
30 | |||
31 | let assists = vec![ | ||
32 | ("Apply SSR in file", source_change_for_file), | ||
33 | ("Apply SSR in workspace", source_change_for_workspace), | ||
34 | ]; | ||
35 | |||
36 | for (label, source_change) in assists.into_iter() { | ||
37 | let assist = Assist { | ||
38 | id: AssistId("ssr", AssistKind::RefactorRewrite), | ||
39 | label: Label::new(label), | ||
40 | group: Some(GroupLabel("Apply SSR".into())), | ||
41 | target: comment_range, | ||
42 | source_change, | ||
43 | }; | ||
44 | |||
45 | base.push(assist); | ||
46 | } | ||
47 | Some(()) | ||
48 | } | ||
49 | |||
50 | #[cfg(test)] | ||
51 | mod tests { | ||
52 | use std::sync::Arc; | ||
53 | |||
54 | use expect_test::expect; | ||
55 | use ide_assists::Assist; | ||
56 | use ide_db::{ | ||
57 | base_db::{fixture::WithFixture, salsa::Durability, FileRange}, | ||
58 | symbol_index::SymbolsDatabase, | ||
59 | RootDatabase, | ||
60 | }; | ||
61 | use rustc_hash::FxHashSet; | ||
62 | |||
63 | use super::add_ssr_assist; | ||
64 | |||
65 | fn get_assists(ra_fixture: &str, resolve: bool) -> Vec<Assist> { | ||
66 | let (mut db, file_id, range_or_offset) = RootDatabase::with_range_or_offset(ra_fixture); | ||
67 | let mut local_roots = FxHashSet::default(); | ||
68 | local_roots.insert(ide_db::base_db::fixture::WORKSPACE); | ||
69 | db.set_local_roots_with_durability(Arc::new(local_roots), Durability::HIGH); | ||
70 | |||
71 | let mut assists = vec![]; | ||
72 | |||
73 | add_ssr_assist( | ||
74 | &db, | ||
75 | &mut assists, | ||
76 | resolve, | ||
77 | FileRange { file_id, range: range_or_offset.into() }, | ||
78 | ); | ||
79 | |||
80 | assists | ||
81 | } | ||
82 | |||
83 | #[test] | ||
84 | fn not_applicable_comment_not_ssr() { | ||
85 | let ra_fixture = r#" | ||
86 | //- /lib.rs | ||
87 | |||
88 | // This is foo $0 | ||
89 | fn foo() {} | ||
90 | "#; | ||
91 | let resolve = true; | ||
92 | |||
93 | let assists = get_assists(ra_fixture, resolve); | ||
94 | |||
95 | assert_eq!(0, assists.len()); | ||
96 | } | ||
97 | |||
98 | #[test] | ||
99 | fn resolve_edits_true() { | ||
100 | let resolve = true; | ||
101 | let assists = get_assists( | ||
102 | r#" | ||
103 | //- /lib.rs | ||
104 | mod bar; | ||
105 | |||
106 | // 2 ==>> 3$0 | ||
107 | fn foo() { 2 } | ||
108 | |||
109 | //- /bar.rs | ||
110 | fn bar() { 2 } | ||
111 | "#, | ||
112 | resolve, | ||
113 | ); | ||
114 | |||
115 | assert_eq!(2, assists.len()); | ||
116 | let mut assists = assists.into_iter(); | ||
117 | |||
118 | let apply_in_file_assist = assists.next().unwrap(); | ||
119 | expect![[r#" | ||
120 | Assist { | ||
121 | id: AssistId( | ||
122 | "ssr", | ||
123 | RefactorRewrite, | ||
124 | ), | ||
125 | label: "Apply SSR in file", | ||
126 | group: Some( | ||
127 | GroupLabel( | ||
128 | "Apply SSR", | ||
129 | ), | ||
130 | ), | ||
131 | target: 10..21, | ||
132 | source_change: Some( | ||
133 | SourceChange { | ||
134 | source_file_edits: { | ||
135 | FileId( | ||
136 | 0, | ||
137 | ): TextEdit { | ||
138 | indels: [ | ||
139 | Indel { | ||
140 | insert: "3", | ||
141 | delete: 33..34, | ||
142 | }, | ||
143 | ], | ||
144 | }, | ||
145 | }, | ||
146 | file_system_edits: [], | ||
147 | is_snippet: false, | ||
148 | }, | ||
149 | ), | ||
150 | } | ||
151 | "#]] | ||
152 | .assert_debug_eq(&apply_in_file_assist); | ||
153 | |||
154 | let apply_in_workspace_assist = assists.next().unwrap(); | ||
155 | expect![[r#" | ||
156 | Assist { | ||
157 | id: AssistId( | ||
158 | "ssr", | ||
159 | RefactorRewrite, | ||
160 | ), | ||
161 | label: "Apply SSR in workspace", | ||
162 | group: Some( | ||
163 | GroupLabel( | ||
164 | "Apply SSR", | ||
165 | ), | ||
166 | ), | ||
167 | target: 10..21, | ||
168 | source_change: Some( | ||
169 | SourceChange { | ||
170 | source_file_edits: { | ||
171 | FileId( | ||
172 | 0, | ||
173 | ): TextEdit { | ||
174 | indels: [ | ||
175 | Indel { | ||
176 | insert: "3", | ||
177 | delete: 33..34, | ||
178 | }, | ||
179 | ], | ||
180 | }, | ||
181 | FileId( | ||
182 | 1, | ||
183 | ): TextEdit { | ||
184 | indels: [ | ||
185 | Indel { | ||
186 | insert: "3", | ||
187 | delete: 11..12, | ||
188 | }, | ||
189 | ], | ||
190 | }, | ||
191 | }, | ||
192 | file_system_edits: [], | ||
193 | is_snippet: false, | ||
194 | }, | ||
195 | ), | ||
196 | } | ||
197 | "#]] | ||
198 | .assert_debug_eq(&apply_in_workspace_assist); | ||
199 | } | ||
200 | |||
201 | #[test] | ||
202 | fn resolve_edits_false() { | ||
203 | let resolve = false; | ||
204 | let assists = get_assists( | ||
205 | r#" | ||
206 | //- /lib.rs | ||
207 | mod bar; | ||
208 | |||
209 | // 2 ==>> 3$0 | ||
210 | fn foo() { 2 } | ||
211 | |||
212 | //- /bar.rs | ||
213 | fn bar() { 2 } | ||
214 | "#, | ||
215 | resolve, | ||
216 | ); | ||
217 | |||
218 | assert_eq!(2, assists.len()); | ||
219 | let mut assists = assists.into_iter(); | ||
220 | |||
221 | let apply_in_file_assist = assists.next().unwrap(); | ||
222 | expect![[r#" | ||
223 | Assist { | ||
224 | id: AssistId( | ||
225 | "ssr", | ||
226 | RefactorRewrite, | ||
227 | ), | ||
228 | label: "Apply SSR in file", | ||
229 | group: Some( | ||
230 | GroupLabel( | ||
231 | "Apply SSR", | ||
232 | ), | ||
233 | ), | ||
234 | target: 10..21, | ||
235 | source_change: None, | ||
236 | } | ||
237 | "#]] | ||
238 | .assert_debug_eq(&apply_in_file_assist); | ||
239 | |||
240 | let apply_in_workspace_assist = assists.next().unwrap(); | ||
241 | expect![[r#" | ||
242 | Assist { | ||
243 | id: AssistId( | ||
244 | "ssr", | ||
245 | RefactorRewrite, | ||
246 | ), | ||
247 | label: "Apply SSR in workspace", | ||
248 | group: Some( | ||
249 | GroupLabel( | ||
250 | "Apply SSR", | ||
251 | ), | ||
252 | ), | ||
253 | target: 10..21, | ||
254 | source_change: None, | ||
255 | } | ||
256 | "#]] | ||
257 | .assert_debug_eq(&apply_in_workspace_assist); | ||
258 | } | ||
259 | } | ||
diff --git a/crates/ide/src/syntax_highlighting/highlight.rs b/crates/ide/src/syntax_highlighting/highlight.rs index 24fcbb584..b0cfdd8b7 100644 --- a/crates/ide/src/syntax_highlighting/highlight.rs +++ b/crates/ide/src/syntax_highlighting/highlight.rs | |||
@@ -330,10 +330,11 @@ fn highlight_def(db: &RootDatabase, def: Definition) -> Highlight { | |||
330 | HlTag::Symbol(SymbolKind::Local) | 330 | HlTag::Symbol(SymbolKind::Local) |
331 | }; | 331 | }; |
332 | let mut h = Highlight::new(tag); | 332 | let mut h = Highlight::new(tag); |
333 | if local.is_mut(db) || local.ty(db).is_mutable_reference() { | 333 | let ty = local.ty(db); |
334 | if local.is_mut(db) || ty.is_mutable_reference() { | ||
334 | h |= HlMod::Mutable; | 335 | h |= HlMod::Mutable; |
335 | } | 336 | } |
336 | if local.ty(db).as_callable(db).is_some() || local.ty(db).impls_fnonce(db) { | 337 | if ty.as_callable(db).is_some() || ty.impls_fnonce(db) { |
337 | h |= HlMod::Callable; | 338 | h |= HlMod::Callable; |
338 | } | 339 | } |
339 | return h; | 340 | return h; |
diff --git a/crates/ide_assists/Cargo.toml b/crates/ide_assists/Cargo.toml index 3bf0099a9..dd9aa27c6 100644 --- a/crates/ide_assists/Cargo.toml +++ b/crates/ide_assists/Cargo.toml | |||
@@ -21,7 +21,7 @@ text_edit = { path = "../text_edit", version = "0.0.0" } | |||
21 | profile = { path = "../profile", version = "0.0.0" } | 21 | profile = { path = "../profile", version = "0.0.0" } |
22 | ide_db = { path = "../ide_db", version = "0.0.0" } | 22 | ide_db = { path = "../ide_db", version = "0.0.0" } |
23 | hir = { path = "../hir", version = "0.0.0" } | 23 | hir = { path = "../hir", version = "0.0.0" } |
24 | test_utils = { path = "../test_utils", version = "0.0.0" } | ||
25 | 24 | ||
26 | [dev-dependencies] | 25 | [dev-dependencies] |
26 | test_utils = { path = "../test_utils" } | ||
27 | expect-test = "1.1" | 27 | expect-test = "1.1" |
diff --git a/crates/ide_assists/src/handlers/add_turbo_fish.rs b/crates/ide_assists/src/handlers/add_turbo_fish.rs index 3b6efbab4..ee879c151 100644 --- a/crates/ide_assists/src/handlers/add_turbo_fish.rs +++ b/crates/ide_assists/src/handlers/add_turbo_fish.rs | |||
@@ -56,13 +56,20 @@ pub(crate) fn add_turbo_fish(acc: &mut Assists, ctx: &AssistContext) -> Option<( | |||
56 | if let Some(let_stmt) = ctx.find_node_at_offset::<ast::LetStmt>() { | 56 | if let Some(let_stmt) = ctx.find_node_at_offset::<ast::LetStmt>() { |
57 | if let_stmt.colon_token().is_none() { | 57 | if let_stmt.colon_token().is_none() { |
58 | let type_pos = let_stmt.pat()?.syntax().last_token()?.text_range().end(); | 58 | let type_pos = let_stmt.pat()?.syntax().last_token()?.text_range().end(); |
59 | let semi_pos = let_stmt.syntax().last_token()?.text_range().end(); | ||
60 | |||
59 | acc.add( | 61 | acc.add( |
60 | AssistId("add_type_ascription", AssistKind::RefactorRewrite), | 62 | AssistId("add_type_ascription", AssistKind::RefactorRewrite), |
61 | "Add `: _` before assignment operator", | 63 | "Add `: _` before assignment operator", |
62 | ident.text_range(), | 64 | ident.text_range(), |
63 | |builder| match ctx.config.snippet_cap { | 65 | |builder| { |
64 | Some(cap) => builder.insert_snippet(cap, type_pos, ": ${0:_}"), | 66 | if let_stmt.semicolon_token().is_none() { |
65 | None => builder.insert(type_pos, ": _"), | 67 | builder.insert(semi_pos, ";"); |
68 | } | ||
69 | match ctx.config.snippet_cap { | ||
70 | Some(cap) => builder.insert_snippet(cap, type_pos, ": ${0:_}"), | ||
71 | None => builder.insert(type_pos, ": _"), | ||
72 | } | ||
66 | }, | 73 | }, |
67 | )? | 74 | )? |
68 | } else { | 75 | } else { |
@@ -265,4 +272,24 @@ fn main() { | |||
265 | "#, | 272 | "#, |
266 | ); | 273 | ); |
267 | } | 274 | } |
275 | |||
276 | #[test] | ||
277 | fn add_type_ascription_append_semicolon() { | ||
278 | check_assist_by_label( | ||
279 | add_turbo_fish, | ||
280 | r#" | ||
281 | fn make<T>() -> T {} | ||
282 | fn main() { | ||
283 | let x = make$0() | ||
284 | } | ||
285 | "#, | ||
286 | r#" | ||
287 | fn make<T>() -> T {} | ||
288 | fn main() { | ||
289 | let x: ${0:_} = make(); | ||
290 | } | ||
291 | "#, | ||
292 | "Add `: _` before assignment operator", | ||
293 | ); | ||
294 | } | ||
268 | } | 295 | } |
diff --git a/crates/ide_assists/src/handlers/auto_import.rs b/crates/ide_assists/src/handlers/auto_import.rs index 7caee8df0..7019039b9 100644 --- a/crates/ide_assists/src/handlers/auto_import.rs +++ b/crates/ide_assists/src/handlers/auto_import.rs | |||
@@ -1,7 +1,7 @@ | |||
1 | use ide_db::helpers::{ | 1 | use ide_db::helpers::{ |
2 | import_assets::{ImportAssets, ImportCandidate}, | 2 | import_assets::{ImportAssets, ImportCandidate}, |
3 | insert_use::{insert_use, ImportScope}, | 3 | insert_use::{insert_use, ImportScope}, |
4 | item_name, mod_path_to_ast, | 4 | mod_path_to_ast, |
5 | }; | 5 | }; |
6 | use syntax::{ast, AstNode, SyntaxNode}; | 6 | use syntax::{ast, AstNode, SyntaxNode}; |
7 | 7 | ||
@@ -90,17 +90,13 @@ pub(crate) fn auto_import(acc: &mut Assists, ctx: &AssistContext) -> Option<()> | |||
90 | } | 90 | } |
91 | 91 | ||
92 | let range = ctx.sema.original_range(&syntax_under_caret).range; | 92 | let range = ctx.sema.original_range(&syntax_under_caret).range; |
93 | let group = import_group_message(import_assets.import_candidate()); | 93 | let group_label = group_label(import_assets.import_candidate()); |
94 | let scope = ImportScope::find_insert_use_container(&syntax_under_caret, &ctx.sema)?; | 94 | let scope = ImportScope::find_insert_use_container(&syntax_under_caret, &ctx.sema)?; |
95 | for import in proposed_imports { | 95 | for import in proposed_imports { |
96 | let name = match item_name(ctx.db(), import.original_item) { | ||
97 | Some(name) => name, | ||
98 | None => continue, | ||
99 | }; | ||
100 | acc.add_group( | 96 | acc.add_group( |
101 | &group, | 97 | &group_label, |
102 | AssistId("auto_import", AssistKind::QuickFix), | 98 | AssistId("auto_import", AssistKind::QuickFix), |
103 | format!("Import `{}`", name), | 99 | format!("Import `{}`", import.import_path), |
104 | range, | 100 | range, |
105 | |builder| { | 101 | |builder| { |
106 | let rewriter = | 102 | let rewriter = |
@@ -126,7 +122,7 @@ pub(super) fn find_importable_node(ctx: &AssistContext) -> Option<(ImportAssets, | |||
126 | } | 122 | } |
127 | } | 123 | } |
128 | 124 | ||
129 | fn import_group_message(import_candidate: &ImportCandidate) -> GroupLabel { | 125 | fn group_label(import_candidate: &ImportCandidate) -> GroupLabel { |
130 | let name = match import_candidate { | 126 | let name = match import_candidate { |
131 | ImportCandidate::Path(candidate) => format!("Import {}", candidate.name.text()), | 127 | ImportCandidate::Path(candidate) => format!("Import {}", candidate.name.text()), |
132 | ImportCandidate::TraitAssocItem(candidate) => { | 128 | ImportCandidate::TraitAssocItem(candidate) => { |
diff --git a/crates/ide_assists/src/handlers/qualify_path.rs b/crates/ide_assists/src/handlers/qualify_path.rs index 272874ae3..30b23da6c 100644 --- a/crates/ide_assists/src/handlers/qualify_path.rs +++ b/crates/ide_assists/src/handlers/qualify_path.rs | |||
@@ -3,7 +3,7 @@ use std::iter; | |||
3 | use hir::AsAssocItem; | 3 | use hir::AsAssocItem; |
4 | use ide_db::helpers::{ | 4 | use ide_db::helpers::{ |
5 | import_assets::{ImportCandidate, LocatedImport}, | 5 | import_assets::{ImportCandidate, LocatedImport}, |
6 | item_name, mod_path_to_ast, | 6 | mod_path_to_ast, |
7 | }; | 7 | }; |
8 | use ide_db::RootDatabase; | 8 | use ide_db::RootDatabase; |
9 | use syntax::{ | 9 | use syntax::{ |
@@ -78,7 +78,7 @@ pub(crate) fn qualify_path(acc: &mut Assists, ctx: &AssistContext) -> Option<()> | |||
78 | acc.add_group( | 78 | acc.add_group( |
79 | &group_label, | 79 | &group_label, |
80 | AssistId("qualify_path", AssistKind::QuickFix), | 80 | AssistId("qualify_path", AssistKind::QuickFix), |
81 | label(ctx.db(), candidate, &import), | 81 | label(candidate, &import), |
82 | range, | 82 | range, |
83 | |builder| { | 83 | |builder| { |
84 | qualify_candidate.qualify( | 84 | qualify_candidate.qualify( |
@@ -199,21 +199,17 @@ fn group_label(candidate: &ImportCandidate) -> GroupLabel { | |||
199 | GroupLabel(format!("Qualify {}", name)) | 199 | GroupLabel(format!("Qualify {}", name)) |
200 | } | 200 | } |
201 | 201 | ||
202 | fn label(db: &RootDatabase, candidate: &ImportCandidate, import: &LocatedImport) -> String { | 202 | fn label(candidate: &ImportCandidate, import: &LocatedImport) -> String { |
203 | let display_path = match item_name(db, import.original_item) { | ||
204 | Some(display_path) => display_path.to_string(), | ||
205 | None => "{unknown}".to_string(), | ||
206 | }; | ||
207 | match candidate { | 203 | match candidate { |
208 | ImportCandidate::Path(candidate) => { | 204 | ImportCandidate::Path(candidate) => { |
209 | if candidate.qualifier.is_some() { | 205 | if candidate.qualifier.is_some() { |
210 | format!("Qualify with `{}`", display_path) | 206 | format!("Qualify with `{}`", import.import_path) |
211 | } else { | 207 | } else { |
212 | format!("Qualify as `{}`", display_path) | 208 | format!("Qualify as `{}`", import.import_path) |
213 | } | 209 | } |
214 | } | 210 | } |
215 | ImportCandidate::TraitAssocItem(_) => format!("Qualify `{}`", display_path), | 211 | ImportCandidate::TraitAssocItem(_) => format!("Qualify `{}`", import.import_path), |
216 | ImportCandidate::TraitMethod(_) => format!("Qualify with cast as `{}`", display_path), | 212 | ImportCandidate::TraitMethod(_) => format!("Qualify with cast as `{}`", import.import_path), |
217 | } | 213 | } |
218 | } | 214 | } |
219 | 215 | ||
diff --git a/crates/ide_completion/Cargo.toml b/crates/ide_completion/Cargo.toml index 84aa40736..585ecca50 100644 --- a/crates/ide_completion/Cargo.toml +++ b/crates/ide_completion/Cargo.toml | |||
@@ -22,11 +22,11 @@ text_edit = { path = "../text_edit", version = "0.0.0" } | |||
22 | base_db = { path = "../base_db", version = "0.0.0" } | 22 | base_db = { path = "../base_db", version = "0.0.0" } |
23 | ide_db = { path = "../ide_db", version = "0.0.0" } | 23 | ide_db = { path = "../ide_db", version = "0.0.0" } |
24 | profile = { path = "../profile", version = "0.0.0" } | 24 | profile = { path = "../profile", version = "0.0.0" } |
25 | test_utils = { path = "../test_utils", version = "0.0.0" } | ||
26 | 25 | ||
27 | # completions crate should depend only on the top-level `hir` package. if you need | 26 | # completions crate should depend only on the top-level `hir` package. if you need |
28 | # something from some `hir_xxx` subpackage, reexport the API via `hir`. | 27 | # something from some `hir_xxx` subpackage, reexport the API via `hir`. |
29 | hir = { path = "../hir", version = "0.0.0" } | 28 | hir = { path = "../hir", version = "0.0.0" } |
30 | 29 | ||
31 | [dev-dependencies] | 30 | [dev-dependencies] |
31 | test_utils = { path = "../test_utils" } | ||
32 | expect-test = "1.1" | 32 | expect-test = "1.1" |
diff --git a/crates/ide_completion/src/completions/attribute.rs b/crates/ide_completion/src/completions/attribute.rs index cb05e85fc..e846678b4 100644 --- a/crates/ide_completion/src/completions/attribute.rs +++ b/crates/ide_completion/src/completions/attribute.rs | |||
@@ -45,15 +45,15 @@ fn complete_attribute_start(acc: &mut Completions, ctx: &CompletionContext, attr | |||
45 | CompletionKind::Attribute, | 45 | CompletionKind::Attribute, |
46 | ctx.source_range(), | 46 | ctx.source_range(), |
47 | attr_completion.label, | 47 | attr_completion.label, |
48 | ) | 48 | ); |
49 | .kind(CompletionItemKind::Attribute); | 49 | item.kind(CompletionItemKind::Attribute); |
50 | 50 | ||
51 | if let Some(lookup) = attr_completion.lookup { | 51 | if let Some(lookup) = attr_completion.lookup { |
52 | item = item.lookup_by(lookup); | 52 | item.lookup_by(lookup); |
53 | } | 53 | } |
54 | 54 | ||
55 | if let Some((snippet, cap)) = attr_completion.snippet.zip(ctx.config.snippet_cap) { | 55 | if let Some((snippet, cap)) = attr_completion.snippet.zip(ctx.config.snippet_cap) { |
56 | item = item.insert_snippet(cap, snippet); | 56 | item.insert_snippet(cap, snippet); |
57 | } | 57 | } |
58 | 58 | ||
59 | if attribute.kind() == ast::AttrKind::Inner || !attr_completion.prefer_inner { | 59 | if attribute.kind() == ast::AttrKind::Inner || !attr_completion.prefer_inner { |
@@ -168,16 +168,20 @@ fn complete_derive(acc: &mut Completions, ctx: &CompletionContext, derive_input: | |||
168 | ); | 168 | ); |
169 | let lookup = components.join(", "); | 169 | let lookup = components.join(", "); |
170 | let label = components.iter().rev().join(", "); | 170 | let label = components.iter().rev().join(", "); |
171 | CompletionItem::new(CompletionKind::Attribute, ctx.source_range(), label) | 171 | let mut item = |
172 | .lookup_by(lookup) | 172 | CompletionItem::new(CompletionKind::Attribute, ctx.source_range(), label); |
173 | .kind(CompletionItemKind::Attribute) | 173 | item.lookup_by(lookup).kind(CompletionItemKind::Attribute); |
174 | .add_to(acc) | 174 | item.add_to(acc); |
175 | } | 175 | } |
176 | 176 | ||
177 | for custom_derive_name in get_derive_names_in_scope(ctx).difference(&existing_derives) { | 177 | for custom_derive_name in get_derive_names_in_scope(ctx).difference(&existing_derives) { |
178 | CompletionItem::new(CompletionKind::Attribute, ctx.source_range(), custom_derive_name) | 178 | let mut item = CompletionItem::new( |
179 | .kind(CompletionItemKind::Attribute) | 179 | CompletionKind::Attribute, |
180 | .add_to(acc) | 180 | ctx.source_range(), |
181 | custom_derive_name, | ||
182 | ); | ||
183 | item.kind(CompletionItemKind::Attribute); | ||
184 | item.add_to(acc); | ||
181 | } | 185 | } |
182 | } | 186 | } |
183 | } | 187 | } |
@@ -193,14 +197,13 @@ fn complete_lint( | |||
193 | .into_iter() | 197 | .into_iter() |
194 | .filter(|completion| !existing_lints.contains(completion.label)) | 198 | .filter(|completion| !existing_lints.contains(completion.label)) |
195 | { | 199 | { |
196 | CompletionItem::new( | 200 | let mut item = CompletionItem::new( |
197 | CompletionKind::Attribute, | 201 | CompletionKind::Attribute, |
198 | ctx.source_range(), | 202 | ctx.source_range(), |
199 | lint_completion.label, | 203 | lint_completion.label, |
200 | ) | 204 | ); |
201 | .kind(CompletionItemKind::Attribute) | 205 | item.kind(CompletionItemKind::Attribute).detail(lint_completion.description); |
202 | .detail(lint_completion.description) | 206 | item.add_to(acc) |
203 | .add_to(acc) | ||
204 | } | 207 | } |
205 | } | 208 | } |
206 | } | 209 | } |
diff --git a/crates/ide_completion/src/completions/fn_param.rs b/crates/ide_completion/src/completions/fn_param.rs index 1bcc8727f..0243dce56 100644 --- a/crates/ide_completion/src/completions/fn_param.rs +++ b/crates/ide_completion/src/completions/fn_param.rs | |||
@@ -54,10 +54,9 @@ pub(crate) fn complete_fn_param(acc: &mut Completions, ctx: &CompletionContext) | |||
54 | } | 54 | } |
55 | 55 | ||
56 | params.into_iter().for_each(|(label, lookup)| { | 56 | params.into_iter().for_each(|(label, lookup)| { |
57 | CompletionItem::new(CompletionKind::Magic, ctx.source_range(), label) | 57 | let mut item = CompletionItem::new(CompletionKind::Magic, ctx.source_range(), label); |
58 | .kind(CompletionItemKind::Binding) | 58 | item.kind(CompletionItemKind::Binding).lookup_by(lookup); |
59 | .lookup_by(lookup) | 59 | item.add_to(acc) |
60 | .add_to(acc) | ||
61 | }); | 60 | }); |
62 | } | 61 | } |
63 | 62 | ||
diff --git a/crates/ide_completion/src/completions/keyword.rs b/crates/ide_completion/src/completions/keyword.rs index 80aa9fb06..b635e0ca3 100644 --- a/crates/ide_completion/src/completions/keyword.rs +++ b/crates/ide_completion/src/completions/keyword.rs | |||
@@ -12,21 +12,19 @@ pub(crate) fn complete_use_tree_keyword(acc: &mut Completions, ctx: &CompletionC | |||
12 | 12 | ||
13 | if ctx.use_item_syntax.is_some() { | 13 | if ctx.use_item_syntax.is_some() { |
14 | if ctx.path_qual.is_none() { | 14 | if ctx.path_qual.is_none() { |
15 | CompletionItem::new(CompletionKind::Keyword, source_range, "crate::") | 15 | let mut item = CompletionItem::new(CompletionKind::Keyword, source_range, "crate::"); |
16 | .kind(CompletionItemKind::Keyword) | 16 | item.kind(CompletionItemKind::Keyword).insert_text("crate::"); |
17 | .insert_text("crate::") | 17 | item.add_to(acc); |
18 | .add_to(acc); | ||
19 | } | 18 | } |
20 | CompletionItem::new(CompletionKind::Keyword, source_range, "self") | 19 | let mut item = CompletionItem::new(CompletionKind::Keyword, source_range, "self"); |
21 | .kind(CompletionItemKind::Keyword) |