aboutsummaryrefslogtreecommitdiff
path: root/crates
diff options
context:
space:
mode:
Diffstat (limited to 'crates')
-rw-r--r--crates/ra_mbe/src/lib.rs258
-rw-r--r--crates/ra_mbe/src/mbe_expander.rs57
-rw-r--r--crates/ra_mbe/src/tt_cursor.rs13
3 files changed, 304 insertions, 24 deletions
diff --git a/crates/ra_mbe/src/lib.rs b/crates/ra_mbe/src/lib.rs
index eedc0c5dd..d7b18dd0f 100644
--- a/crates/ra_mbe/src/lib.rs
+++ b/crates/ra_mbe/src/lib.rs
@@ -384,7 +384,7 @@ impl_froms!(TokenTree: Leaf, Subtree);
384"#, 384"#,
385 ); 385 );
386 386
387 assert_expansion(&rules, "foo! { foo, bar }", "fn baz {foo () ; bar () ;}"); 387 assert_expansion(&rules, "foo! { foo, bar }", "fn baz {foo () ; bar ()}");
388 } 388 }
389 389
390 #[test] 390 #[test]
@@ -1066,4 +1066,260 @@ macro_rules! int_base {
1066 "# [stable (feature = \"rust1\" , since = \"1.0.0\")] impl fmt :: Binary for isize {fn fmt (& self , f : & mut fmt :: Formatter < \'_ >) -> fmt :: Result {Binary . fmt_int (* self as usize , f)}}" 1066 "# [stable (feature = \"rust1\" , since = \"1.0.0\")] impl fmt :: Binary for isize {fn fmt (& self , f : & mut fmt :: Formatter < \'_ >) -> fmt :: Result {Binary . fmt_int (* self as usize , f)}}"
1067 ); 1067 );
1068 } 1068 }
1069
1070 #[test]
1071 fn test_generate_pattern_iterators() {
1072 // from https://github.com/rust-lang/rust/blob/316a391dcb7d66dc25f1f9a4ec9d368ef7615005/src/libcore/str/mod.rs
1073 let rules = create_rules(
1074 r#"
1075macro_rules! generate_pattern_iterators {
1076 { double ended; with $(#[$common_stability_attribute:meta])*,
1077 $forward_iterator:ident,
1078 $reverse_iterator:ident, $iterty:ty
1079 } => {
1080 fn foo(){}
1081 }
1082}
1083"#,
1084 );
1085
1086 assert_expansion(&rules, r#"generate_pattern_iterators ! ( double ended ; with # [ stable ( feature = "rust1" , since = "1.0.0" ) ] , Split , RSplit , & 'a str )"#,
1087 "fn foo () {}");
1088 }
1089
1090 #[test]
1091 fn test_impl_fn_for_zst() {
1092 // from https://github.com/rust-lang/rust/blob/5d20ff4d2718c820632b38c1e49d4de648a9810b/src/libcore/internal_macros.rs
1093 let rules = create_rules(
1094 r#"
1095macro_rules! impl_fn_for_zst {
1096 { $( $( #[$attr: meta] )*
1097 struct $Name: ident impl$( <$( $lifetime : lifetime ),+> )? Fn =
1098 |$( $arg: ident: $ArgTy: ty ),*| -> $ReturnTy: ty
1099$body: block; )+
1100 } => {
1101 fn foo(){}
1102 }
1103}
1104"#,
1105 );
1106
1107 assert_expansion(&rules, r#"
1108impl_fn_for_zst ! {
1109 # [ derive ( Clone ) ]
1110 struct CharEscapeDebugContinue impl Fn = | c : char | -> char :: EscapeDebug {
1111 c . escape_debug_ext ( false )
1112 } ;
1113
1114 # [ derive ( Clone ) ]
1115 struct CharEscapeUnicode impl Fn = | c : char | -> char :: EscapeUnicode {
1116 c . escape_unicode ( )
1117 } ;
1118 # [ derive ( Clone ) ]
1119 struct CharEscapeDefault impl Fn = | c : char | -> char :: EscapeDefault {
1120 c . escape_default ( )
1121 } ;
1122 }
1123"#,
1124 "fn foo () {}");
1125 }
1126
1127 #[test]
1128 fn test_impl_nonzero_fmt() {
1129 // from https://github.com/rust-lang/rust/blob/316a391dcb7d66dc25f1f9a4ec9d368ef7615005/src/libcore/num/mod.rs#L12
1130 let rules = create_rules(
1131 r#"
1132 macro_rules! impl_nonzero_fmt {
1133 ( #[$stability: meta] ( $( $Trait: ident ),+ ) for $Ty: ident ) => {
1134 fn foo() {}
1135 }
1136 }
1137"#,
1138 );
1139
1140 assert_expansion(&rules, r#"impl_nonzero_fmt ! { # [ stable ( feature = "nonzero" , since = "1.28.0" ) ] ( Debug , Display , Binary , Octal , LowerHex , UpperHex ) for NonZeroU8 }"#,
1141 "fn foo () {}");
1142 }
1143
1144 #[test]
1145 fn test_tuple_impls() {
1146 // from https://github.com/rust-lang/rust/blob/316a391dcb7d66dc25f1f9a4ec9d368ef7615005/src/libcore/num/mod.rs#L12
1147 let rules = create_rules(
1148 r#"
1149 macro_rules! tuple_impls {
1150 ($(
1151 $Tuple:ident {
1152 $(($idx:tt) -> $T:ident)+
1153 }
1154 )+) => {
1155 $(
1156 #[stable(feature = "rust1", since = "1.0.0")]
1157 impl<$($T:PartialEq),+> PartialEq for ($($T,)+) where last_type!($($T,)+): ?Sized {
1158 #[inline]
1159 fn eq(&self, other: &($($T,)+)) -> bool {
1160 $(self.$idx == other.$idx)&&+
1161 }
1162 #[inline]
1163 fn ne(&self, other: &($($T,)+)) -> bool {
1164 $(self.$idx != other.$idx)||+
1165 }
1166 }
1167
1168 #[stable(feature = "rust1", since = "1.0.0")]
1169 impl<$($T:Eq),+> Eq for ($($T,)+) where last_type!($($T,)+): ?Sized {}
1170
1171 #[stable(feature = "rust1", since = "1.0.0")]
1172 impl<$($T:PartialOrd + PartialEq),+> PartialOrd for ($($T,)+)
1173 where last_type!($($T,)+): ?Sized {
1174 #[inline]
1175 fn partial_cmp(&self, other: &($($T,)+)) -> Option<Ordering> {
1176 lexical_partial_cmp!($(self.$idx, other.$idx),+)
1177 }
1178 #[inline]
1179 fn lt(&self, other: &($($T,)+)) -> bool {
1180 lexical_ord!(lt, $(self.$idx, other.$idx),+)
1181 }
1182 #[inline]
1183 fn le(&self, other: &($($T,)+)) -> bool {
1184 lexical_ord!(le, $(self.$idx, other.$idx),+)
1185 }
1186 #[inline]
1187 fn ge(&self, other: &($($T,)+)) -> bool {
1188 lexical_ord!(ge, $(self.$idx, other.$idx),+)
1189 }
1190 #[inline]
1191 fn gt(&self, other: &($($T,)+)) -> bool {
1192 lexical_ord!(gt, $(self.$idx, other.$idx),+)
1193 }
1194 }
1195
1196 #[stable(feature = "rust1", since = "1.0.0")]
1197 impl<$($T:Ord),+> Ord for ($($T,)+) where last_type!($($T,)+): ?Sized {
1198 #[inline]
1199 fn cmp(&self, other: &($($T,)+)) -> Ordering {
1200 lexical_cmp!($(self.$idx, other.$idx),+)
1201 }
1202 }
1203
1204 #[stable(feature = "rust1", since = "1.0.0")]
1205 impl<$($T:Default),+> Default for ($($T,)+) {
1206 #[inline]
1207 fn default() -> ($($T,)+) {
1208 ($({ let x: $T = Default::default(); x},)+)
1209 }
1210 }
1211 )+
1212 }
1213}"#,
1214 );
1215
1216 assert_expansion(
1217 &rules,
1218 r#"tuple_impls ! {
1219 Tuple1 {
1220 ( 0 ) -> A
1221 }
1222 Tuple2 {
1223 ( 0 ) -> A
1224 ( 1 ) -> B
1225 }
1226 Tuple3 {
1227 ( 0 ) -> A
1228 ( 1 ) -> B
1229 ( 2 ) -> C
1230 }
1231 Tuple4 {
1232 ( 0 ) -> A
1233 ( 1 ) -> B
1234 ( 2 ) -> C
1235 ( 3 ) -> D
1236 }
1237 Tuple5 {
1238 ( 0 ) -> A
1239 ( 1 ) -> B
1240 ( 2 ) -> C
1241 ( 3 ) -> D
1242 ( 4 ) -> E
1243 }
1244 Tuple6 {
1245 ( 0 ) -> A
1246 ( 1 ) -> B
1247 ( 2 ) -> C
1248 ( 3 ) -> D
1249 ( 4 ) -> E
1250 ( 5 ) -> F
1251 }
1252 Tuple7 {
1253 ( 0 ) -> A
1254 ( 1 ) -> B
1255 ( 2 ) -> C
1256 ( 3 ) -> D
1257 ( 4 ) -> E
1258 ( 5 ) -> F
1259 ( 6 ) -> G
1260 }
1261 Tuple8 {
1262 ( 0 ) -> A
1263 ( 1 ) -> B
1264 ( 2 ) -> C
1265 ( 3 ) -> D
1266 ( 4 ) -> E
1267 ( 5 ) -> F
1268 ( 6 ) -> G
1269 ( 7 ) -> H
1270 }
1271 Tuple9 {
1272 ( 0 ) -> A
1273 ( 1 ) -> B
1274 ( 2 ) -> C
1275 ( 3 ) -> D
1276 ( 4 ) -> E
1277 ( 5 ) -> F
1278 ( 6 ) -> G
1279 ( 7 ) -> H
1280 ( 8 ) -> I
1281 }
1282 Tuple10 {
1283 ( 0 ) -> A
1284 ( 1 ) -> B
1285 ( 2 ) -> C
1286 ( 3 ) -> D
1287 ( 4 ) -> E
1288 ( 5 ) -> F
1289 ( 6 ) -> G
1290 ( 7 ) -> H
1291 ( 8 ) -> I
1292 ( 9 ) -> J
1293 }
1294 Tuple11 {
1295 ( 0 ) -> A
1296 ( 1 ) -> B
1297 ( 2 ) -> C
1298 ( 3 ) -> D
1299 ( 4 ) -> E
1300 ( 5 ) -> F
1301 ( 6 ) -> G
1302 ( 7 ) -> H
1303 ( 8 ) -> I
1304 ( 9 ) -> J
1305 ( 10 ) -> K
1306 }
1307 Tuple12 {
1308 ( 0 ) -> A
1309 ( 1 ) -> B
1310 ( 2 ) -> C
1311 ( 3 ) -> D
1312 ( 4 ) -> E
1313 ( 5 ) -> F
1314 ( 6 ) -> G
1315 ( 7 ) -> H
1316 ( 8 ) -> I
1317 ( 9 ) -> J
1318 ( 10 ) -> K
1319 ( 11 ) -> L
1320 }
1321}"#,
1322 "fn foo () {}",
1323 );
1324 }
1069} 1325}
diff --git a/crates/ra_mbe/src/mbe_expander.rs b/crates/ra_mbe/src/mbe_expander.rs
index 00fb09a3b..91b6db522 100644
--- a/crates/ra_mbe/src/mbe_expander.rs
+++ b/crates/ra_mbe/src/mbe_expander.rs
@@ -179,10 +179,10 @@ fn match_lhs(pattern: &crate::Subtree, input: &mut TtCursor) -> Result<Bindings,
179 // Enable followiing code when everything is fixed 179 // Enable followiing code when everything is fixed
180 // At least we can dogfood itself to not stackoverflow 180 // At least we can dogfood itself to not stackoverflow
181 // 181 //
182 // "tt" => { 182 "tt" => {
183 // let token = input.eat().ok_or(ExpandError::UnexpectedToken)?.clone(); 183 let token = input.eat().ok_or(ExpandError::UnexpectedToken)?.clone();
184 // res.inner.insert(text.clone(), Binding::Simple(token.into())); 184 res.inner.insert(text.clone(), Binding::Simple(token.into()));
185 // } 185 }
186 "item" => { 186 "item" => {
187 let item = 187 let item =
188 input.eat_item().ok_or(ExpandError::UnexpectedToken)?.clone(); 188 input.eat_item().ok_or(ExpandError::UnexpectedToken)?.clone();
@@ -226,18 +226,36 @@ fn match_lhs(pattern: &crate::Subtree, input: &mut TtCursor) -> Result<Bindings,
226 // This should be replaced by a propper macro-by-example implementation 226 // This should be replaced by a propper macro-by-example implementation
227 let mut limit = 128; 227 let mut limit = 128;
228 let mut counter = 0; 228 let mut counter = 0;
229 while let Ok(nested) = match_lhs(subtree, input) { 229
230 counter += 1; 230 let mut memento = input.save();
231 limit -= 1; 231
232 if limit == 0 { 232 loop {
233 break; 233 match match_lhs(subtree, input) {
234 } 234 Ok(nested) => {
235 res.push_nested(nested)?; 235 counter += 1;
236 if let Some(separator) = *separator { 236 limit -= 1;
237 if !input.is_eof() { 237 if limit == 0 {
238 if input.eat_punct().map(|p| p.char) != Some(separator) { 238 break;
239 return Err(ExpandError::UnexpectedToken);
240 } 239 }
240
241 memento = input.save();
242 res.push_nested(nested)?;
243 if counter == 1 {
244 if let crate::RepeatKind::ZeroOrOne = kind {
245 break;
246 }
247 }
248
249 if let Some(separator) = *separator {
250 if input.eat_punct().map(|p| p.char) != Some(separator) {
251 input.rollback(memento);
252 break;
253 }
254 }
255 }
256 Err(_) => {
257 input.rollback(memento);
258 break;
241 } 259 }
242 } 260 }
243 } 261 }
@@ -246,10 +264,6 @@ fn match_lhs(pattern: &crate::Subtree, input: &mut TtCursor) -> Result<Bindings,
246 crate::RepeatKind::OneOrMore if counter == 0 => { 264 crate::RepeatKind::OneOrMore if counter == 0 => {
247 return Err(ExpandError::UnexpectedToken); 265 return Err(ExpandError::UnexpectedToken);
248 } 266 }
249 crate::RepeatKind::ZeroOrOne if counter > 1 => {
250 return Err(ExpandError::UnexpectedToken);
251 }
252
253 _ => {} 267 _ => {}
254 } 268 }
255 } 269 }
@@ -333,10 +347,7 @@ fn expand_tt(
333 } 347 }
334 } 348 }
335 nesting.pop().unwrap(); 349 nesting.pop().unwrap();
336 350 if has_sep {
337 // Dirty hack for remove the last sep
338 // if it is a "," undo the push
339 if has_sep && repeat.separator.unwrap() == ',' {
340 token_trees.pop(); 351 token_trees.pop();
341 } 352 }
342 353
diff --git a/crates/ra_mbe/src/tt_cursor.rs b/crates/ra_mbe/src/tt_cursor.rs
index 741b5ea1c..87bcf8b0d 100644
--- a/crates/ra_mbe/src/tt_cursor.rs
+++ b/crates/ra_mbe/src/tt_cursor.rs
@@ -7,6 +7,10 @@ pub(crate) struct TtCursor<'a> {
7 pos: usize, 7 pos: usize,
8} 8}
9 9
10pub(crate) struct TtCursorMemento {
11 pos: usize,
12}
13
10impl<'a> TtCursor<'a> { 14impl<'a> TtCursor<'a> {
11 pub(crate) fn new(subtree: &'a tt::Subtree) -> TtCursor<'a> { 15 pub(crate) fn new(subtree: &'a tt::Subtree) -> TtCursor<'a> {
12 TtCursor { subtree, pos: 0 } 16 TtCursor { subtree, pos: 0 }
@@ -157,4 +161,13 @@ impl<'a> TtCursor<'a> {
157 Err(ParseError::Expected(format!("`{}`", char))) 161 Err(ParseError::Expected(format!("`{}`", char)))
158 } 162 }
159 } 163 }
164
165 #[must_use]
166 pub(crate) fn save(&self) -> TtCursorMemento {
167 TtCursorMemento { pos: self.pos }
168 }
169
170 pub(crate) fn rollback(&mut self, memento: TtCursorMemento) {
171 self.pos = memento.pos;
172 }
160} 173}