aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Cargo.lock68
-rw-r--r--crates/hir/src/lib.rs15
-rw-r--r--crates/hir_def/src/nameres/collector.rs165
-rw-r--r--crates/ide/src/references/rename.rs81
-rw-r--r--crates/ide_assists/src/handlers/add_missing_impl_members.rs6
-rw-r--r--crates/ide_assists/src/handlers/convert_comment_block.rs46
-rw-r--r--crates/ide_assists/src/handlers/reorder_fields.rs112
-rw-r--r--crates/syntax/src/ast/token_ext.rs5
8 files changed, 226 insertions, 272 deletions
diff --git a/Cargo.lock b/Cargo.lock
index 19ee689cb..7f666ca61 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -35,9 +35,9 @@ dependencies = [
35 35
36[[package]] 36[[package]]
37name = "anyhow" 37name = "anyhow"
38version = "1.0.38" 38version = "1.0.39"
39source = "registry+https://github.com/rust-lang/crates.io-index" 39source = "registry+https://github.com/rust-lang/crates.io-index"
40checksum = "afddf7f520a80dbf76e6f50a35bca42a2331ef227a28b3b6dc5c2e2338d114b1" 40checksum = "81cddc5f91628367664cc7c69714ff08deee8a3efc54623011c772544d7b2767"
41 41
42[[package]] 42[[package]]
43name = "anymap" 43name = "anymap"
@@ -111,9 +111,9 @@ checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610"
111 111
112[[package]] 112[[package]]
113name = "camino" 113name = "camino"
114version = "1.0.2" 114version = "1.0.4"
115source = "registry+https://github.com/rust-lang/crates.io-index" 115source = "registry+https://github.com/rust-lang/crates.io-index"
116checksum = "cd065703998b183ed0b348a22555691373a9345a1431141e5778b48bb17e4703" 116checksum = "d4648c6d00a709aa069a236adcaae4f605a6241c72bf5bee79331a4b625921a9"
117dependencies = [ 117dependencies = [
118 "serde", 118 "serde",
119] 119]
@@ -794,9 +794,9 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
794 794
795[[package]] 795[[package]]
796name = "libc" 796name = "libc"
797version = "0.2.88" 797version = "0.2.91"
798source = "registry+https://github.com/rust-lang/crates.io-index" 798source = "registry+https://github.com/rust-lang/crates.io-index"
799checksum = "03b07a082330a35e43f63177cc01689da34fbffa0105e1246cf0311472cac73a" 799checksum = "8916b1f6ca17130ec6568feccee27c156ad12037880833a3b842a823236502e7"
800 800
801[[package]] 801[[package]]
802name = "libloading" 802name = "libloading"
@@ -946,9 +946,9 @@ dependencies = [
946 946
947[[package]] 947[[package]]
948name = "mio" 948name = "mio"
949version = "0.7.9" 949version = "0.7.11"
950source = "registry+https://github.com/rust-lang/crates.io-index" 950source = "registry+https://github.com/rust-lang/crates.io-index"
951checksum = "a5dede4e2065b3842b8b0af444119f3aa331cc7cc2dd20388bfb0f5d5a38823a" 951checksum = "cf80d3e903b34e0bd7282b218398aec54e082c840d9baf8339e0080a0c542956"
952dependencies = [ 952dependencies = [
953 "libc", 953 "libc",
954 "log", 954 "log",
@@ -959,11 +959,10 @@ dependencies = [
959 959
960[[package]] 960[[package]]
961name = "miow" 961name = "miow"
962version = "0.3.6" 962version = "0.3.7"
963source = "registry+https://github.com/rust-lang/crates.io-index" 963source = "registry+https://github.com/rust-lang/crates.io-index"
964checksum = "5a33c1b55807fbed163481b5ba66db4b2fa6cde694a5027be10fb724206c5897" 964checksum = "b9f1c5b025cda876f66ef43a113f91ebc9f4ccef34843000e0adf6ebbab84e21"
965dependencies = [ 965dependencies = [
966 "socket2",
967 "winapi", 966 "winapi",
968] 967]
969 968
@@ -1299,9 +1298,9 @@ dependencies = [
1299 1298
1300[[package]] 1299[[package]]
1301name = "regex" 1300name = "regex"
1302version = "1.4.3" 1301version = "1.4.5"
1303source = "registry+https://github.com/rust-lang/crates.io-index" 1302source = "registry+https://github.com/rust-lang/crates.io-index"
1304checksum = "d9251239e129e16308e70d853559389de218ac275b515068abc96829d05b948a" 1303checksum = "957056ecddbeba1b26965114e191d2e8589ce74db242b6ea25fc4062427a5c19"
1305dependencies = [ 1304dependencies = [
1306 "regex-syntax", 1305 "regex-syntax",
1307] 1306]
@@ -1318,9 +1317,9 @@ dependencies = [
1318 1317
1319[[package]] 1318[[package]]
1320name = "regex-syntax" 1319name = "regex-syntax"
1321version = "0.6.22" 1320version = "0.6.23"
1322source = "registry+https://github.com/rust-lang/crates.io-index" 1321source = "registry+https://github.com/rust-lang/crates.io-index"
1323checksum = "b5eb417147ba9860a96cfe72a0b93bf88fee1744b5636ec99ab20c1aa9376581" 1322checksum = "24d5f089152e60f62d28b835fbff2cd2e8dc0baf1ac13343bef92ab7eed84548"
1324 1323
1325[[package]] 1324[[package]]
1326name = "rowan" 1325name = "rowan"
@@ -1485,18 +1484,18 @@ dependencies = [
1485 1484
1486[[package]] 1485[[package]]
1487name = "serde" 1486name = "serde"
1488version = "1.0.124" 1487version = "1.0.125"
1489source = "registry+https://github.com/rust-lang/crates.io-index" 1488source = "registry+https://github.com/rust-lang/crates.io-index"
1490checksum = "bd761ff957cb2a45fbb9ab3da6512de9de55872866160b23c25f1a841e99d29f" 1489checksum = "558dc50e1a5a5fa7112ca2ce4effcb321b0300c0d4ccf0776a9f60cd89031171"
1491dependencies = [ 1490dependencies = [
1492 "serde_derive", 1491 "serde_derive",
1493] 1492]
1494 1493
1495[[package]] 1494[[package]]
1496name = "serde_derive" 1495name = "serde_derive"
1497version = "1.0.124" 1496version = "1.0.125"
1498source = "registry+https://github.com/rust-lang/crates.io-index" 1497source = "registry+https://github.com/rust-lang/crates.io-index"
1499checksum = "1800f7693e94e186f5e25a28291ae1570da908aff7d97a095dec1e56ff99069b" 1498checksum = "b093b7a2bb58203b5da3056c05b4ec1fed827dcfdb37347a8841695263b3d06d"
1500dependencies = [ 1499dependencies = [
1501 "proc-macro2", 1500 "proc-macro2",
1502 "quote", 1501 "quote",
@@ -1566,17 +1565,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
1566checksum = "dc725476a1398f0480d56cd0ad381f6f32acf2642704456f8f59a35df464b59a" 1565checksum = "dc725476a1398f0480d56cd0ad381f6f32acf2642704456f8f59a35df464b59a"
1567 1566
1568[[package]] 1567[[package]]
1569name = "socket2"
1570version = "0.3.19"
1571source = "registry+https://github.com/rust-lang/crates.io-index"
1572checksum = "122e570113d28d773067fab24266b66753f6ea915758651696b6e35e49f88d6e"
1573dependencies = [
1574 "cfg-if",
1575 "libc",
1576 "winapi",
1577]
1578
1579[[package]]
1580name = "stdx" 1568name = "stdx"
1581version = "0.0.0" 1569version = "0.0.0"
1582dependencies = [ 1570dependencies = [
@@ -1586,9 +1574,9 @@ dependencies = [
1586 1574
1587[[package]] 1575[[package]]
1588name = "syn" 1576name = "syn"
1589version = "1.0.63" 1577version = "1.0.64"
1590source = "registry+https://github.com/rust-lang/crates.io-index" 1578source = "registry+https://github.com/rust-lang/crates.io-index"
1591checksum = "8fd9bc7ccc2688b3344c2f48b9b546648b25ce0b20fc717ee7fa7981a8ca9717" 1579checksum = "3fd9d1e9976102a03c542daa2eff1b43f9d72306342f3f8b3ed5fb8908195d6f"
1592dependencies = [ 1580dependencies = [
1593 "proc-macro2", 1581 "proc-macro2",
1594 "quote", 1582 "quote",
@@ -1718,9 +1706,9 @@ dependencies = [
1718 1706
1719[[package]] 1707[[package]]
1720name = "tracing-attributes" 1708name = "tracing-attributes"
1721version = "0.1.13" 1709version = "0.1.15"
1722source = "registry+https://github.com/rust-lang/crates.io-index" 1710source = "registry+https://github.com/rust-lang/crates.io-index"
1723checksum = "a8a9bd1db7706f2373a190b0d067146caa39350c486f3d455b0e33b431f94c07" 1711checksum = "c42e6fa53307c8a17e4ccd4dc81cf5ec38db9209f59b222210375b54ee40d1e2"
1724dependencies = [ 1712dependencies = [
1725 "proc-macro2", 1713 "proc-macro2",
1726 "quote", 1714 "quote",
@@ -1759,9 +1747,9 @@ dependencies = [
1759 1747
1760[[package]] 1748[[package]]
1761name = "tracing-subscriber" 1749name = "tracing-subscriber"
1762version = "0.2.16" 1750version = "0.2.17"
1763source = "registry+https://github.com/rust-lang/crates.io-index" 1751source = "registry+https://github.com/rust-lang/crates.io-index"
1764checksum = "8ab8966ac3ca27126141f7999361cc97dd6fb4b71da04c02044fa9045d98bb96" 1752checksum = "705096c6f83bf68ea5d357a6aa01829ddbdac531b357b45abeca842938085baa"
1765dependencies = [ 1753dependencies = [
1766 "ansi_term", 1754 "ansi_term",
1767 "chrono", 1755 "chrono",
@@ -1867,9 +1855,9 @@ dependencies = [
1867 1855
1868[[package]] 1856[[package]]
1869name = "version_check" 1857name = "version_check"
1870version = "0.9.2" 1858version = "0.9.3"
1871source = "registry+https://github.com/rust-lang/crates.io-index" 1859source = "registry+https://github.com/rust-lang/crates.io-index"
1872checksum = "b5a972e5669d67ba988ce3dc826706fb0a8b01471c088cb0b6110b805cc36aed" 1860checksum = "5fecdca9a5291cc2b8dcf7dc02453fee791a280f3743cb0905f8822ae463b3fe"
1873 1861
1874[[package]] 1862[[package]]
1875name = "vfs" 1863name = "vfs"
@@ -1896,9 +1884,9 @@ dependencies = [
1896 1884
1897[[package]] 1885[[package]]
1898name = "walkdir" 1886name = "walkdir"
1899version = "2.3.1" 1887version = "2.3.2"
1900source = "registry+https://github.com/rust-lang/crates.io-index" 1888source = "registry+https://github.com/rust-lang/crates.io-index"
1901checksum = "777182bc735b6424e1a57516d35ed72cb8019d85c8c9bf536dccb3445c1a2f7d" 1889checksum = "808cf2735cd4b6866113f648b791c6adc5714537bc222d9347bb203386ffda56"
1902dependencies = [ 1890dependencies = [
1903 "same-file", 1891 "same-file",
1904 "winapi", 1892 "winapi",
diff --git a/crates/hir/src/lib.rs b/crates/hir/src/lib.rs
index bdc1ad852..eb7865c84 100644
--- a/crates/hir/src/lib.rs
+++ b/crates/hir/src/lib.rs
@@ -973,6 +973,14 @@ impl SelfParam {
973 Access::Owned => "self", 973 Access::Owned => "self",
974 } 974 }
975 } 975 }
976
977 pub fn source(&self, db: &dyn HirDatabase) -> Option<InFile<ast::SelfParam>> {
978 let InFile { file_id, value } = Function::from(self.func).source(db)?;
979 value
980 .param_list()
981 .and_then(|params| params.self_param())
982 .map(|value| InFile { file_id, value })
983 }
976} 984}
977 985
978impl HasVisibility for Function { 986impl HasVisibility for Function {
@@ -1348,6 +1356,13 @@ impl Local {
1348 } 1356 }
1349 } 1357 }
1350 1358
1359 pub fn as_self_param(self, db: &dyn HirDatabase) -> Option<SelfParam> {
1360 match self.parent {
1361 DefWithBodyId::FunctionId(func) if self.is_self(db) => Some(SelfParam { func }),
1362 _ => None,
1363 }
1364 }
1365
1351 // FIXME: why is this an option? It shouldn't be? 1366 // FIXME: why is this an option? It shouldn't be?
1352 pub fn name(self, db: &dyn HirDatabase) -> Option<Name> { 1367 pub fn name(self, db: &dyn HirDatabase) -> Option<Name> {
1353 let body = db.body(self.parent); 1368 let body = db.body(self.parent);
diff --git a/crates/hir_def/src/nameres/collector.rs b/crates/hir_def/src/nameres/collector.rs
index 28b73c3a1..d8fabe49b 100644
--- a/crates/hir_def/src/nameres/collector.rs
+++ b/crates/hir_def/src/nameres/collector.rs
@@ -91,7 +91,6 @@ pub(super) fn collect_defs(
91 resolved_imports: Vec::new(), 91 resolved_imports: Vec::new(),
92 92
93 unexpanded_macros: Vec::new(), 93 unexpanded_macros: Vec::new(),
94 unexpanded_attribute_macros: Vec::new(),
95 mod_dirs: FxHashMap::default(), 94 mod_dirs: FxHashMap::default(),
96 cfg_options, 95 cfg_options,
97 proc_macros, 96 proc_macros,
@@ -202,15 +201,14 @@ struct ImportDirective {
202#[derive(Clone, Debug, Eq, PartialEq)] 201#[derive(Clone, Debug, Eq, PartialEq)]
203struct MacroDirective { 202struct MacroDirective {
204 module_id: LocalModuleId, 203 module_id: LocalModuleId,
205 ast_id: AstIdWithPath<ast::MacroCall>,
206 legacy: Option<MacroCallId>,
207 depth: usize, 204 depth: usize,
205 kind: MacroDirectiveKind,
208} 206}
209 207
210#[derive(Clone, Debug, Eq, PartialEq)] 208#[derive(Clone, Debug, Eq, PartialEq)]
211struct DeriveDirective { 209enum MacroDirectiveKind {
212 module_id: LocalModuleId, 210 FnLike { ast_id: AstIdWithPath<ast::MacroCall>, legacy: Option<MacroCallId> },
213 ast_id: AstIdWithPath<ast::Item>, 211 Derive { ast_id: AstIdWithPath<ast::Item> },
214} 212}
215 213
216struct DefData<'a> { 214struct DefData<'a> {
@@ -228,7 +226,6 @@ struct DefCollector<'a> {
228 unresolved_imports: Vec<ImportDirective>, 226 unresolved_imports: Vec<ImportDirective>,
229 resolved_imports: Vec<ImportDirective>, 227 resolved_imports: Vec<ImportDirective>,
230 unexpanded_macros: Vec<MacroDirective>, 228 unexpanded_macros: Vec<MacroDirective>,
231 unexpanded_attribute_macros: Vec<DeriveDirective>,
232 mod_dirs: FxHashMap<LocalModuleId, ModDir>, 229 mod_dirs: FxHashMap<LocalModuleId, ModDir>,
233 cfg_options: &'a CfgOptions, 230 cfg_options: &'a CfgOptions,
234 /// List of procedural macros defined by this crate. This is read from the dynamic library 231 /// List of procedural macros defined by this crate. This is read from the dynamic library
@@ -782,60 +779,58 @@ impl DefCollector<'_> {
782 779
783 fn resolve_macros(&mut self) -> ReachedFixedPoint { 780 fn resolve_macros(&mut self) -> ReachedFixedPoint {
784 let mut macros = std::mem::replace(&mut self.unexpanded_macros, Vec::new()); 781 let mut macros = std::mem::replace(&mut self.unexpanded_macros, Vec::new());
785 let mut attribute_macros =
786 std::mem::replace(&mut self.unexpanded_attribute_macros, Vec::new());
787 let mut resolved = Vec::new(); 782 let mut resolved = Vec::new();
788 let mut res = ReachedFixedPoint::Yes; 783 let mut res = ReachedFixedPoint::Yes;
789 macros.retain(|directive| { 784 macros.retain(|directive| {
790 if let Some(call_id) = directive.legacy { 785 match &directive.kind {
791 res = ReachedFixedPoint::No; 786 MacroDirectiveKind::FnLike { ast_id, legacy } => {
792 resolved.push((directive.module_id, call_id, directive.depth)); 787 if let Some(call_id) = legacy {
793 return false; 788 res = ReachedFixedPoint::No;
794 } 789 resolved.push((directive.module_id, *call_id, directive.depth));
790 return false;
791 }
795 792
796 match macro_call_as_call_id( 793 match macro_call_as_call_id(
797 &directive.ast_id, 794 ast_id,
798 self.db,
799 self.def_map.krate,
800 |path| {
801 let resolved_res = self.def_map.resolve_path_fp_with_macro(
802 self.db, 795 self.db,
803 ResolveMode::Other, 796 self.def_map.krate,
804 directive.module_id, 797 |path| {
805 &path, 798 let resolved_res = self.def_map.resolve_path_fp_with_macro(
806 BuiltinShadowMode::Module, 799 self.db,
807 ); 800 ResolveMode::Other,
808 resolved_res.resolved_def.take_macros() 801 directive.module_id,
809 }, 802 &path,
810 &mut |_err| (), 803 BuiltinShadowMode::Module,
811 ) { 804 );
812 Ok(Ok(call_id)) => { 805 resolved_res.resolved_def.take_macros()
813 resolved.push((directive.module_id, call_id, directive.depth)); 806 },
814 res = ReachedFixedPoint::No; 807 &mut |_err| (),
815 return false; 808 ) {
809 Ok(Ok(call_id)) => {
810 resolved.push((directive.module_id, call_id, directive.depth));
811 res = ReachedFixedPoint::No;
812 return false;
813 }
814 Err(UnresolvedMacro) | Ok(Err(_)) => {}
815 }
816 } 816 }
817 Err(UnresolvedMacro) | Ok(Err(_)) => {} 817 MacroDirectiveKind::Derive { ast_id } => {
818 } 818 match derive_macro_as_call_id(ast_id, self.db, self.def_map.krate, |path| {
819 819 self.resolve_derive_macro(directive.module_id, &path)
820 true 820 }) {
821 }); 821 Ok(call_id) => {
822 attribute_macros.retain(|directive| { 822 resolved.push((directive.module_id, call_id, 0));
823 match derive_macro_as_call_id(&directive.ast_id, self.db, self.def_map.krate, |path| { 823 res = ReachedFixedPoint::No;
824 self.resolve_derive_macro(&directive, &path) 824 return false;
825 }) { 825 }
826 Ok(call_id) => { 826 Err(UnresolvedMacro) => (),
827 resolved.push((directive.module_id, call_id, 0)); 827 }
828 res = ReachedFixedPoint::No;
829 return false;
830 } 828 }
831 Err(UnresolvedMacro) => (),
832 } 829 }
833 830
834 true 831 true
835 }); 832 });
836
837 self.unexpanded_macros = macros; 833 self.unexpanded_macros = macros;
838 self.unexpanded_attribute_macros = attribute_macros;
839 834
840 for (module_id, macro_call_id, depth) in resolved { 835 for (module_id, macro_call_id, depth) in resolved {
841 self.collect_macro_expansion(module_id, macro_call_id, depth); 836 self.collect_macro_expansion(module_id, macro_call_id, depth);
@@ -844,15 +839,11 @@ impl DefCollector<'_> {
844 res 839 res
845 } 840 }
846 841
847 fn resolve_derive_macro( 842 fn resolve_derive_macro(&self, module: LocalModuleId, path: &ModPath) -> Option<MacroDefId> {
848 &self,
849 directive: &DeriveDirective,
850 path: &ModPath,
851 ) -> Option<MacroDefId> {
852 let resolved_res = self.def_map.resolve_path_fp_with_macro( 843 let resolved_res = self.def_map.resolve_path_fp_with_macro(
853 self.db, 844 self.db,
854 ResolveMode::Other, 845 ResolveMode::Other,
855 directive.module_id, 846 module,
856 &path, 847 &path,
857 BuiltinShadowMode::Module, 848 BuiltinShadowMode::Module,
858 ); 849 );
@@ -912,33 +903,35 @@ impl DefCollector<'_> {
912 // Emit diagnostics for all remaining unexpanded macros. 903 // Emit diagnostics for all remaining unexpanded macros.
913 904
914 for directive in &self.unexpanded_macros { 905 for directive in &self.unexpanded_macros {
915 let mut error = None; 906 match &directive.kind {
916 match macro_call_as_call_id( 907 MacroDirectiveKind::FnLike { ast_id, .. } => match macro_call_as_call_id(
917 &directive.ast_id, 908 ast_id,
918 self.db, 909 self.db,
919 self.def_map.krate, 910 self.def_map.krate,
920 |path| { 911 |path| {
921 let resolved_res = self.def_map.resolve_path_fp_with_macro( 912 let resolved_res = self.def_map.resolve_path_fp_with_macro(
922 self.db, 913 self.db,
923 ResolveMode::Other, 914 ResolveMode::Other,
924 directive.module_id, 915 directive.module_id,
925 &path, 916 &path,
926 BuiltinShadowMode::Module, 917 BuiltinShadowMode::Module,
927 ); 918 );
928 resolved_res.resolved_def.take_macros() 919 resolved_res.resolved_def.take_macros()
929 }, 920 },
930 &mut |e| { 921 &mut |_| (),
931 error.get_or_insert(e); 922 ) {
923 Ok(_) => (),
924 Err(UnresolvedMacro) => {
925 self.def_map.diagnostics.push(DefDiagnostic::unresolved_macro_call(
926 directive.module_id,
927 ast_id.ast_id,
928 ));
929 }
932 }, 930 },
933 ) { 931 MacroDirectiveKind::Derive { .. } => {
934 Ok(_) => (), 932 // FIXME: we might want to diagnose this too
935 Err(UnresolvedMacro) => {
936 self.def_map.diagnostics.push(DefDiagnostic::unresolved_macro_call(
937 directive.module_id,
938 directive.ast_id.ast_id,
939 ));
940 } 933 }
941 }; 934 }
942 } 935 }
943 936
944 // Emit diagnostics for all remaining unresolved imports. 937 // Emit diagnostics for all remaining unresolved imports.
@@ -1380,9 +1373,11 @@ impl ModCollector<'_, '_> {
1380 Some(derive_macros) => { 1373 Some(derive_macros) => {
1381 for path in derive_macros { 1374 for path in derive_macros {
1382 let ast_id = AstIdWithPath::new(self.file_id, ast_id, path); 1375 let ast_id = AstIdWithPath::new(self.file_id, ast_id, path);
1383 self.def_collector 1376 self.def_collector.unexpanded_macros.push(MacroDirective {
1384 .unexpanded_attribute_macros 1377 module_id: self.module_id,
1385 .push(DeriveDirective { module_id: self.module_id, ast_id }); 1378 depth: self.macro_depth + 1,
1379 kind: MacroDirectiveKind::Derive { ast_id },
1380 });
1386 } 1381 }
1387 } 1382 }
1388 None => { 1383 None => {
@@ -1497,9 +1492,8 @@ impl ModCollector<'_, '_> {
1497 1492
1498 self.def_collector.unexpanded_macros.push(MacroDirective { 1493 self.def_collector.unexpanded_macros.push(MacroDirective {
1499 module_id: self.module_id, 1494 module_id: self.module_id,
1500 ast_id,
1501 legacy: None,
1502 depth: self.macro_depth + 1, 1495 depth: self.macro_depth + 1,
1496 kind: MacroDirectiveKind::FnLike { ast_id, legacy: None },
1503 }); 1497 });
1504 } 1498 }
1505 1499
@@ -1542,7 +1536,6 @@ mod tests {
1542 unresolved_imports: Vec::new(), 1536 unresolved_imports: Vec::new(),
1543 resolved_imports: Vec::new(), 1537 resolved_imports: Vec::new(),
1544 unexpanded_macros: Vec::new(), 1538 unexpanded_macros: Vec::new(),
1545 unexpanded_attribute_macros: Vec::new(),
1546 mod_dirs: FxHashMap::default(), 1539 mod_dirs: FxHashMap::default(),
1547 cfg_options: &CfgOptions::default(), 1540 cfg_options: &CfgOptions::default(),
1548 proc_macros: Default::default(), 1541 proc_macros: Default::default(),
diff --git a/crates/ide/src/references/rename.rs b/crates/ide/src/references/rename.rs
index b1ca6d50f..26d6dc9c9 100644
--- a/crates/ide/src/references/rename.rs
+++ b/crates/ide/src/references/rename.rs
@@ -219,40 +219,44 @@ fn rename_reference(
219) -> RenameResult<SourceChange> { 219) -> RenameResult<SourceChange> {
220 let ident_kind = check_identifier(new_name)?; 220 let ident_kind = check_identifier(new_name)?;
221 221
222 let def_is_lbl_or_lt = matches!( 222 if matches!(
223 def, 223 def, // is target a lifetime?
224 Definition::GenericParam(hir::GenericParam::LifetimeParam(_)) | Definition::Label(_) 224 Definition::GenericParam(hir::GenericParam::LifetimeParam(_)) | Definition::Label(_)
225 ); 225 ) {
226 match (ident_kind, def) { 226 match ident_kind {
227 (IdentifierKind::ToSelf, _) 227 IdentifierKind::Ident | IdentifierKind::ToSelf | IdentifierKind::Underscore => {
228 | (IdentifierKind::Underscore, _) 228 cov_mark::hit!(rename_not_a_lifetime_ident_ref);
229 | (IdentifierKind::Ident, _) 229 bail!("Invalid name `{}`: not a lifetime identifier", new_name);
230 if def_is_lbl_or_lt => 230 }
231 { 231 IdentifierKind::Lifetime => cov_mark::hit!(rename_lifetime),
232 cov_mark::hit!(rename_not_a_lifetime_ident_ref);
233 bail!("Invalid name `{}`: not a lifetime identifier", new_name)
234 }
235 (IdentifierKind::Lifetime, _) if def_is_lbl_or_lt => cov_mark::hit!(rename_lifetime),
236 (IdentifierKind::Lifetime, _) => {
237 cov_mark::hit!(rename_not_an_ident_ref);
238 bail!("Invalid name `{}`: not an identifier", new_name)
239 }
240 (IdentifierKind::ToSelf, Definition::Local(local)) if local.is_self(sema.db) => {
241 // no-op
242 cov_mark::hit!(rename_self_to_self);
243 return Ok(SourceChange::default());
244 }
245 (ident_kind, Definition::Local(local)) if local.is_self(sema.db) => {
246 cov_mark::hit!(rename_self_to_param);
247 return rename_self_to_param(sema, local, new_name, ident_kind);
248 }
249 (IdentifierKind::ToSelf, Definition::Local(local)) => {
250 cov_mark::hit!(rename_to_self);
251 return rename_to_self(sema, local);
252 } 232 }
253 (IdentifierKind::ToSelf, _) => bail!("Invalid name `{}`: not an identifier", new_name), 233 } else {
254 (IdentifierKind::Ident, _) | (IdentifierKind::Underscore, _) => { 234 match (ident_kind, def) {
255 cov_mark::hit!(rename_ident) 235 (IdentifierKind::Lifetime, _) => {
236 cov_mark::hit!(rename_not_an_ident_ref);
237 bail!("Invalid name `{}`: not an identifier", new_name);
238 }
239 (IdentifierKind::ToSelf, Definition::Local(local)) => {
240 if local.is_self(sema.db) {
241 // no-op
242 cov_mark::hit!(rename_self_to_self);
243 return Ok(SourceChange::default());
244 } else {
245 cov_mark::hit!(rename_to_self);
246 return rename_to_self(sema, local);
247 }
248 }
249 (ident_kind, Definition::Local(local)) => {
250 if let Some(self_param) = local.as_self_param(sema.db) {
251 cov_mark::hit!(rename_self_to_param);
252 return rename_self_to_param(sema, local, self_param, new_name, ident_kind);
253 } else {
254 cov_mark::hit!(rename_local);
255 }
256 }
257 (IdentifierKind::ToSelf, _) => bail!("Invalid name `{}`: not an identifier", new_name),
258 (IdentifierKind::Ident, _) => cov_mark::hit!(rename_non_local),
259 (IdentifierKind::Underscore, _) => (),
256 } 260 }
257 } 261 }
258 262
@@ -336,16 +340,12 @@ fn rename_to_self(sema: &Semantics<RootDatabase>, local: hir::Local) -> RenameRe
336fn rename_self_to_param( 340fn rename_self_to_param(
337 sema: &Semantics<RootDatabase>, 341 sema: &Semantics<RootDatabase>,
338 local: hir::Local, 342 local: hir::Local,
343 self_param: hir::SelfParam,
339 new_name: &str, 344 new_name: &str,
340 identifier_kind: IdentifierKind, 345 identifier_kind: IdentifierKind,
341) -> RenameResult<SourceChange> { 346) -> RenameResult<SourceChange> {
342 let (file_id, self_param) = match local.source(sema.db) { 347 let InFile { file_id, value: self_param } =
343 InFile { file_id, value: Either::Right(self_param) } => (file_id, self_param), 348 self_param.source(sema.db).ok_or_else(|| format_err!("cannot find function source"))?;
344 _ => {
345 never!(true, "rename_self_to_param invoked on a non-self local");
346 bail!("rename_self_to_param invoked on a non-self local");
347 }
348 };
349 349
350 let def = Definition::Local(local); 350 let def = Definition::Local(local);
351 let usages = def.usages(sema).all(); 351 let usages = def.usages(sema).all();
@@ -701,7 +701,7 @@ foo!(Foo$0);",
701 701
702 #[test] 702 #[test]
703 fn test_rename_for_local() { 703 fn test_rename_for_local() {
704 cov_mark::check!(rename_ident); 704 cov_mark::check!(rename_local);
705 check( 705 check(
706 "k", 706 "k",
707 r#" 707 r#"
@@ -1242,6 +1242,7 @@ pub mod foo$0;
1242 1242
1243 #[test] 1243 #[test]
1244 fn test_enum_variant_from_module_1() { 1244 fn test_enum_variant_from_module_1() {
1245 cov_mark::check!(rename_non_local);
1245 check( 1246 check(
1246 "Baz", 1247 "Baz",
1247 r#" 1248 r#"
diff --git a/crates/ide_assists/src/handlers/add_missing_impl_members.rs b/crates/ide_assists/src/handlers/add_missing_impl_members.rs
index 63cea754d..0148635f9 100644
--- a/crates/ide_assists/src/handlers/add_missing_impl_members.rs
+++ b/crates/ide_assists/src/handlers/add_missing_impl_members.rs
@@ -3,9 +3,9 @@ use syntax::ast::{self, AstNode};
3 3
4use crate::{ 4use crate::{
5 assist_context::{AssistContext, Assists}, 5 assist_context::{AssistContext, Assists},
6 utils::add_trait_assoc_items_to_impl, 6 utils::{
7 utils::DefaultMethods, 7 add_trait_assoc_items_to_impl, filter_assoc_items, render_snippet, Cursor, DefaultMethods,
8 utils::{filter_assoc_items, render_snippet, Cursor}, 8 },
9 AssistId, AssistKind, 9 AssistId, AssistKind,
10}; 10};
11 11
diff --git a/crates/ide_assists/src/handlers/convert_comment_block.rs b/crates/ide_assists/src/handlers/convert_comment_block.rs
index 9dc3ee28f..d202a85f9 100644
--- a/crates/ide_assists/src/handlers/convert_comment_block.rs
+++ b/crates/ide_assists/src/handlers/convert_comment_block.rs
@@ -1,13 +1,6 @@
1use itertools::Itertools; 1use itertools::Itertools;
2use syntax::{ 2use syntax::{
3 ast::{ 3 ast::{self, edit::IndentLevel, Comment, CommentKind, CommentShape, Whitespace},
4 self,
5 edit::IndentLevel,
6 Comment, CommentKind,
7 CommentPlacement::{Inner, Outer},
8 CommentShape::{self, Block, Line},
9 Whitespace,
10 },
11 AstToken, Direction, SyntaxElement, TextRange, 4 AstToken, Direction, SyntaxElement, TextRange,
12}; 5};
13 6
@@ -29,21 +22,18 @@ use crate::{AssistContext, AssistId, AssistKind, Assists};
29/// */ 22/// */
30/// ``` 23/// ```
31pub(crate) fn convert_comment_block(acc: &mut Assists, ctx: &AssistContext) -> Option<()> { 24pub(crate) fn convert_comment_block(acc: &mut Assists, ctx: &AssistContext) -> Option<()> {
32 if let Some(comment) = ctx.find_token_at_offset::<ast::Comment>() { 25 let comment = ctx.find_token_at_offset::<ast::Comment>()?;
33 // Only allow comments which are alone on their line 26 // Only allow comments which are alone on their line
34 if let Some(prev) = comment.syntax().prev_token() { 27 if let Some(prev) = comment.syntax().prev_token() {
35 if Whitespace::cast(prev).filter(|w| w.text().contains('\n')).is_none() { 28 if Whitespace::cast(prev).filter(|w| w.text().contains('\n')).is_none() {
36 return None; 29 return None;
37 }
38 } 30 }
39
40 return match comment.kind().shape {
41 ast::CommentShape::Block => block_to_line(acc, comment),
42 ast::CommentShape::Line => line_to_block(acc, comment),
43 };
44 } 31 }
45 32
46 return None; 33 match comment.kind().shape {
34 ast::CommentShape::Block => block_to_line(acc, comment),
35 ast::CommentShape::Line => line_to_block(acc, comment),
36 }
47} 37}
48 38
49fn block_to_line(acc: &mut Assists, comment: ast::Comment) -> Option<()> { 39fn block_to_line(acc: &mut Assists, comment: ast::Comment) -> Option<()> {
@@ -55,8 +45,7 @@ fn block_to_line(acc: &mut Assists, comment: ast::Comment) -> Option<()> {
55 target, 45 target,
56 |edit| { 46 |edit| {
57 let indentation = IndentLevel::from_token(comment.syntax()); 47 let indentation = IndentLevel::from_token(comment.syntax());
58 let line_prefix = 48 let line_prefix = CommentKind { shape: CommentShape::Line, ..comment.kind() }.prefix();
59 comment_kind_prefix(CommentKind { shape: CommentShape::Line, ..comment.kind() });
60 49
61 let text = comment.text(); 50 let text = comment.text();
62 let text = &text[comment.prefix().len()..(text.len() - "*/".len())].trim(); 51 let text = &text[comment.prefix().len()..(text.len() - "*/".len())].trim();
@@ -105,7 +94,7 @@ fn line_to_block(acc: &mut Assists, comment: ast::Comment) -> Option<()> {
105 comments.into_iter().map(|c| line_comment_text(indentation, c)).join("\n"); 94 comments.into_iter().map(|c| line_comment_text(indentation, c)).join("\n");
106 95
107 let block_prefix = 96 let block_prefix =
108 comment_kind_prefix(CommentKind { shape: CommentShape::Block, ..comment.kind() }); 97 CommentKind { shape: CommentShape::Block, ..comment.kind() }.prefix();
109 98
110 let output = 99 let output =
111 format!("{}\n{}\n{}*/", block_prefix, block_comment_body, indentation.to_string()); 100 format!("{}\n{}\n{}*/", block_prefix, block_comment_body, indentation.to_string());
@@ -182,17 +171,6 @@ fn line_comment_text(indentation: IndentLevel, comm: ast::Comment) -> String {
182 } 171 }
183} 172}
184 173
185fn comment_kind_prefix(ck: ast::CommentKind) -> &'static str {
186 match (ck.shape, ck.doc) {
187 (Line, Some(Inner)) => "//!",
188 (Line, Some(Outer)) => "///",
189 (Line, None) => "//",
190 (Block, Some(Inner)) => "/*!",
191 (Block, Some(Outer)) => "/**",
192 (Block, None) => "/*",
193 }
194}
195
196#[cfg(test)] 174#[cfg(test)]
197mod tests { 175mod tests {
198 use crate::tests::{check_assist, check_assist_not_applicable}; 176 use crate::tests::{check_assist, check_assist_not_applicable};
diff --git a/crates/ide_assists/src/handlers/reorder_fields.rs b/crates/ide_assists/src/handlers/reorder_fields.rs
index 794c89323..383ca6c47 100644
--- a/crates/ide_assists/src/handlers/reorder_fields.rs
+++ b/crates/ide_assists/src/handlers/reorder_fields.rs
@@ -1,9 +1,6 @@
1use itertools::Itertools;
2use rustc_hash::FxHashMap; 1use rustc_hash::FxHashMap;
3 2
4use hir::{Adt, ModuleDef, PathResolution, Semantics, Struct}; 3use syntax::{algo, ast, match_ast, AstNode, SyntaxKind::*, SyntaxNode};
5use ide_db::RootDatabase;
6use syntax::{algo, ast, match_ast, AstNode, SyntaxKind, SyntaxKind::*, SyntaxNode};
7 4
8use crate::{AssistContext, AssistId, AssistKind, Assists}; 5use crate::{AssistContext, AssistId, AssistKind, Assists};
9 6
@@ -23,26 +20,39 @@ use crate::{AssistContext, AssistId, AssistKind, Assists};
23// ``` 20// ```
24// 21//
25pub(crate) fn reorder_fields(acc: &mut Assists, ctx: &AssistContext) -> Option<()> { 22pub(crate) fn reorder_fields(acc: &mut Assists, ctx: &AssistContext) -> Option<()> {
26 reorder::<ast::RecordExpr>(acc, ctx).or_else(|| reorder::<ast::RecordPat>(acc, ctx)) 23 let record = ctx
27} 24 .find_node_at_offset::<ast::RecordExpr>()
25 .map(|it| it.syntax().clone())
26 .or_else(|| ctx.find_node_at_offset::<ast::RecordPat>().map(|it| it.syntax().clone()))?;
28 27
29fn reorder<R: AstNode>(acc: &mut Assists, ctx: &AssistContext) -> Option<()> { 28 let path = record.children().find_map(ast::Path::cast)?;
30 let record = ctx.find_node_at_offset::<R>()?;
31 let path = record.syntax().children().find_map(ast::Path::cast)?;
32 29
33 let ranks = compute_fields_ranks(&path, &ctx)?; 30 let ranks = compute_fields_ranks(&path, &ctx)?;
34 31
35 let fields = get_fields(&record.syntax()); 32 let fields: Vec<SyntaxNode> = {
36 let sorted_fields = sorted_by_rank(&fields, |node| { 33 let field_kind = match record.kind() {
37 *ranks.get(&get_field_name(node)).unwrap_or(&usize::max_value()) 34 RECORD_EXPR => RECORD_EXPR_FIELD,
38 }); 35 RECORD_PAT => RECORD_PAT_FIELD,
36 _ => {
37 stdx::never!();
38 return None;
39 }
40 };
41 record.children().flat_map(|n| n.children()).filter(|n| n.kind() == field_kind).collect()
42 };
43
44 let sorted_fields = {
45 let mut fields = fields.clone();
46 fields.sort_by_key(|node| *ranks.get(&get_field_name(node)).unwrap_or(&usize::max_value()));
47 fields
48 };
39 49
40 if sorted_fields == fields { 50 if sorted_fields == fields {
41 cov_mark::hit!(reorder_sorted_fields); 51 cov_mark::hit!(reorder_sorted_fields);
42 return None; 52 return None;
43 } 53 }
44 54
45 let target = record.syntax().text_range(); 55 let target = record.text_range();
46 acc.add( 56 acc.add(
47 AssistId("reorder_fields", AssistKind::RefactorRewrite), 57 AssistId("reorder_fields", AssistKind::RefactorRewrite),
48 "Reorder record fields", 58 "Reorder record fields",
@@ -57,14 +67,6 @@ fn reorder<R: AstNode>(acc: &mut Assists, ctx: &AssistContext) -> Option<()> {
57 ) 67 )
58} 68}
59 69
60fn get_fields_kind(node: &SyntaxNode) -> Vec<SyntaxKind> {
61 match node.kind() {
62 RECORD_EXPR => vec![RECORD_EXPR_FIELD],
63 RECORD_PAT => vec![RECORD_PAT_FIELD, IDENT_PAT],
64 _ => vec![],
65 }
66}
67
68fn get_field_name(node: &SyntaxNode) -> String { 70fn get_field_name(node: &SyntaxNode) -> String {
69 let res = match_ast! { 71 let res = match_ast! {
70 match node { 72 match node {
@@ -76,34 +78,20 @@ fn get_field_name(node: &SyntaxNode) -> String {
76 res.unwrap_or_default() 78 res.unwrap_or_default()
77} 79}
78 80
79fn get_fields(record: &SyntaxNode) -> Vec<SyntaxNode> { 81fn compute_fields_ranks(path: &ast::Path, ctx: &AssistContext) -> Option<FxHashMap<String, usize>> {
80 let kinds = get_fields_kind(record); 82 let strukt = match ctx.sema.resolve_path(path) {
81 record.children().flat_map(|n| n.children()).filter(|n| kinds.contains(&n.kind())).collect() 83 Some(hir::PathResolution::Def(hir::ModuleDef::Adt(hir::Adt::Struct(it)))) => it,
82} 84 _ => return None,
83 85 };
84fn sorted_by_rank(
85 fields: &[SyntaxNode],
86 get_rank: impl Fn(&SyntaxNode) -> usize,
87) -> Vec<SyntaxNode> {
88 fields.iter().cloned().sorted_by_key(get_rank).collect()
89}
90 86
91fn struct_definition(path: &ast::Path, sema: &Semantics<RootDatabase>) -> Option<Struct> { 87 let res = strukt
92 match sema.resolve_path(path) { 88 .fields(ctx.db())
93 Some(PathResolution::Def(ModuleDef::Adt(Adt::Struct(s)))) => Some(s), 89 .iter()
94 _ => None, 90 .enumerate()
95 } 91 .map(|(idx, field)| (field.name(ctx.db()).to_string(), idx))
96} 92 .collect();
97 93
98fn compute_fields_ranks(path: &ast::Path, ctx: &AssistContext) -> Option<FxHashMap<String, usize>> { 94 Some(res)
99 Some(
100 struct_definition(path, &ctx.sema)?
101 .fields(ctx.db())
102 .iter()
103 .enumerate()
104 .map(|(idx, field)| (field.name(ctx.db()).to_string(), idx))
105 .collect(),
106 )
107} 95}
108 96
109#[cfg(test)] 97#[cfg(test)]
@@ -118,11 +106,7 @@ mod tests {
118 check_assist_not_applicable( 106 check_assist_not_applicable(
119 reorder_fields, 107 reorder_fields,
120 r#" 108 r#"
121struct Foo { 109struct Foo { foo: i32, bar: i32 }
122 foo: i32,
123 bar: i32,
124}
125
126const test: Foo = $0Foo { foo: 0, bar: 0 }; 110const test: Foo = $0Foo { foo: 0, bar: 0 };
127"#, 111"#,
128 ) 112 )
@@ -133,8 +117,8 @@ const test: Foo = $0Foo { foo: 0, bar: 0 };
133 check_assist_not_applicable( 117 check_assist_not_applicable(
134 reorder_fields, 118 reorder_fields,
135 r#" 119 r#"
136struct Foo {}; 120struct Foo {}
137const test: Foo = $0Foo {} 121const test: Foo = $0Foo {};
138"#, 122"#,
139 ) 123 )
140 } 124 }
@@ -144,12 +128,12 @@ const test: Foo = $0Foo {}
144 check_assist( 128 check_assist(
145 reorder_fields, 129 reorder_fields,
146 r#" 130 r#"
147struct Foo {foo: i32, bar: i32}; 131struct Foo { foo: i32, bar: i32 }
148const test: Foo = $0Foo {bar: 0, foo: 1} 132const test: Foo = $0Foo { bar: 0, foo: 1 };
149"#, 133"#,
150 r#" 134 r#"
151struct Foo {foo: i32, bar: i32}; 135struct Foo { foo: i32, bar: i32 }
152const test: Foo = Foo {foo: 1, bar: 0} 136const test: Foo = Foo { foo: 1, bar: 0 };
153"#, 137"#,
154 ) 138 )
155 } 139 }
@@ -186,10 +170,7 @@ fn f(f: Foo) -> {
186 check_assist( 170 check_assist(
187 reorder_fields, 171 reorder_fields,
188 r#" 172 r#"
189struct Foo { 173struct Foo { foo: String, bar: String }
190 foo: String,
191 bar: String,
192}
193 174
194impl Foo { 175impl Foo {
195 fn new() -> Foo { 176 fn new() -> Foo {
@@ -203,10 +184,7 @@ impl Foo {
203} 184}
204"#, 185"#,
205 r#" 186 r#"
206struct Foo { 187struct Foo { foo: String, bar: String }
207 foo: String,
208 bar: String,
209}
210 188
211impl Foo { 189impl Foo {
212 fn new() -> Foo { 190 fn new() -> Foo {
diff --git a/crates/syntax/src/ast/token_ext.rs b/crates/syntax/src/ast/token_ext.rs
index 090282d28..29d25a58a 100644
--- a/crates/syntax/src/ast/token_ext.rs
+++ b/crates/syntax/src/ast/token_ext.rs
@@ -102,8 +102,9 @@ impl CommentKind {
102 kind 102 kind
103 } 103 }
104 104
105 fn prefix(&self) -> &'static str { 105 pub fn prefix(&self) -> &'static str {
106 let &(prefix, _) = CommentKind::BY_PREFIX.iter().find(|(_, kind)| kind == self).unwrap(); 106 let &(prefix, _) =
107 CommentKind::BY_PREFIX.iter().rev().find(|(_, kind)| kind == self).unwrap();
107 prefix 108 prefix
108 } 109 }
109} 110}