]>
Commit | Line | Data |
---|---|---|
064997fb FG |
1 | mod block; |
2 | ||
3 | use base_db::{fixture::WithFixture, SourceDatabase}; | |
781aab86 | 4 | use expect_test::{expect, Expect}; |
064997fb | 5 | |
add651ee | 6 | use crate::{test_db::TestDB, ModuleDefId}; |
064997fb FG |
7 | |
8 | use super::*; | |
9 | ||
781aab86 | 10 | fn lower(ra_fixture: &str) -> (TestDB, Arc<Body>, DefWithBodyId) { |
add651ee | 11 | let db = TestDB::with_files(ra_fixture); |
064997fb FG |
12 | |
13 | let krate = db.crate_graph().iter().next().unwrap(); | |
14 | let def_map = db.crate_def_map(krate); | |
15 | let mut fn_def = None; | |
16 | 'outer: for (_, module) in def_map.modules() { | |
17 | for decl in module.scope.declarations() { | |
18 | if let ModuleDefId::FunctionId(it) = decl { | |
19 | fn_def = Some(it); | |
20 | break 'outer; | |
21 | } | |
22 | } | |
23 | } | |
781aab86 | 24 | let fn_def = fn_def.unwrap().into(); |
064997fb | 25 | |
781aab86 FG |
26 | let body = db.body(fn_def); |
27 | (db, body, fn_def) | |
064997fb FG |
28 | } |
29 | ||
add651ee FG |
30 | fn def_map_at(ra_fixture: &str) -> String { |
31 | let (db, position) = TestDB::with_position(ra_fixture); | |
064997fb FG |
32 | |
33 | let module = db.module_at_position(position); | |
34 | module.def_map(&db).dump(&db) | |
35 | } | |
36 | ||
37 | fn check_block_scopes_at(ra_fixture: &str, expect: Expect) { | |
add651ee | 38 | let (db, position) = TestDB::with_position(ra_fixture); |
064997fb FG |
39 | |
40 | let module = db.module_at_position(position); | |
41 | let actual = module.def_map(&db).dump_block_scopes(&db); | |
42 | expect.assert_eq(&actual); | |
43 | } | |
44 | ||
45 | fn check_at(ra_fixture: &str, expect: Expect) { | |
add651ee | 46 | let actual = def_map_at(ra_fixture); |
064997fb FG |
47 | expect.assert_eq(&actual); |
48 | } | |
49 | ||
50 | #[test] | |
51 | fn your_stack_belongs_to_me() { | |
52 | cov_mark::check!(your_stack_belongs_to_me); | |
53 | lower( | |
54 | r#" | |
55 | macro_rules! n_nuple { | |
56 | ($e:tt) => (); | |
57 | ($($rest:tt)*) => {{ | |
58 | (n_nuple!($($rest)*)None,) | |
59 | }}; | |
60 | } | |
61 | fn main() { n_nuple!(1,2,3); } | |
62 | "#, | |
63 | ); | |
64 | } | |
65 | ||
9ffffee4 FG |
66 | #[test] |
67 | fn your_stack_belongs_to_me2() { | |
68 | cov_mark::check!(overflow_but_not_me); | |
69 | lower( | |
70 | r#" | |
71 | macro_rules! foo { | |
72 | () => {{ foo!(); foo!(); }} | |
73 | } | |
74 | fn main() { foo!(); } | |
75 | "#, | |
76 | ); | |
77 | } | |
78 | ||
064997fb FG |
79 | #[test] |
80 | fn recursion_limit() { | |
81 | cov_mark::check!(your_stack_belongs_to_me); | |
82 | ||
83 | lower( | |
84 | r#" | |
85 | #![recursion_limit = "2"] | |
86 | macro_rules! n_nuple { | |
87 | ($e:tt) => (); | |
88 | ($first:tt $($rest:tt)*) => {{ | |
89 | n_nuple!($($rest)*) | |
90 | }}; | |
91 | } | |
92 | fn main() { n_nuple!(1,2,3); } | |
93 | "#, | |
94 | ); | |
95 | } | |
96 | ||
97 | #[test] | |
98 | fn issue_3642_bad_macro_stackover() { | |
99 | lower( | |
100 | r#" | |
101 | #[macro_export] | |
102 | macro_rules! match_ast { | |
103 | (match $node:ident { $($tt:tt)* }) => { match_ast!(match ($node) { $($tt)* }) }; | |
104 | ||
105 | (match ($node:expr) { | |
106 | $( ast::$ast:ident($it:ident) => $res:expr, )* | |
107 | _ => $catch_all:expr $(,)? | |
108 | }) => {{ | |
109 | $( if let Some($it) = ast::$ast::cast($node.clone()) { $res } else )* | |
110 | { $catch_all } | |
111 | }}; | |
112 | } | |
113 | ||
114 | fn main() { | |
115 | let anchor = match_ast! { | |
116 | match parent { | |
117 | as => {}, | |
118 | _ => return None | |
119 | } | |
120 | }; | |
121 | }"#, | |
122 | ); | |
123 | } | |
124 | ||
125 | #[test] | |
126 | fn macro_resolve() { | |
127 | // Regression test for a path resolution bug introduced with inner item handling. | |
128 | lower( | |
129 | r#" | |
130 | macro_rules! vec { | |
131 | () => { () }; | |
132 | ($elem:expr; $n:expr) => { () }; | |
133 | ($($x:expr),+ $(,)?) => { () }; | |
134 | } | |
135 | mod m { | |
136 | fn outer() { | |
137 | let _ = vec![FileSet::default(); self.len()]; | |
138 | } | |
139 | } | |
140 | "#, | |
141 | ); | |
142 | } | |
781aab86 FG |
143 | |
144 | #[test] | |
145 | fn desugar_builtin_format_args() { | |
781aab86 FG |
146 | let (db, body, def) = lower( |
147 | r#" | |
148 | //- minicore: fmt | |
149 | fn main() { | |
150 | let are = "are"; | |
151 | let count = 10; | |
152 | builtin#format_args("hello {count:02} {} friends, we {are:?} {0}{last}", "fancy", last = "!"); | |
153 | } | |
154 | "#, | |
155 | ); | |
156 | ||
157 | expect![[r#" | |
158 | fn main() { | |
159 | let are = "are"; | |
160 | let count = 10; | |
161 | builtin#lang(Arguments::new_v1_formatted)( | |
162 | &[ | |
4b012472 | 163 | "hello ", " ", " friends, we ", " ", "", |
781aab86 FG |
164 | ], |
165 | &[ | |
166 | builtin#lang(Argument::new_display)( | |
167 | &count, | |
168 | ), builtin#lang(Argument::new_display)( | |
169 | &"fancy", | |
170 | ), builtin#lang(Argument::new_debug)( | |
171 | &are, | |
172 | ), builtin#lang(Argument::new_display)( | |
173 | &"!", | |
174 | ), | |
175 | ], | |
176 | &[ | |
177 | builtin#lang(Placeholder::new)( | |
178 | 0usize, | |
179 | ' ', | |
180 | builtin#lang(Alignment::Unknown), | |
181 | 8u32, | |
182 | builtin#lang(Count::Implied), | |
183 | builtin#lang(Count::Is)( | |
184 | 2usize, | |
185 | ), | |
186 | ), builtin#lang(Placeholder::new)( | |
187 | 1usize, | |
188 | ' ', | |
189 | builtin#lang(Alignment::Unknown), | |
190 | 0u32, | |
191 | builtin#lang(Count::Implied), | |
192 | builtin#lang(Count::Implied), | |
193 | ), builtin#lang(Placeholder::new)( | |
194 | 2usize, | |
195 | ' ', | |
196 | builtin#lang(Alignment::Unknown), | |
197 | 0u32, | |
198 | builtin#lang(Count::Implied), | |
199 | builtin#lang(Count::Implied), | |
200 | ), builtin#lang(Placeholder::new)( | |
201 | 1usize, | |
202 | ' ', | |
203 | builtin#lang(Alignment::Unknown), | |
204 | 0u32, | |
205 | builtin#lang(Count::Implied), | |
206 | builtin#lang(Count::Implied), | |
207 | ), builtin#lang(Placeholder::new)( | |
208 | 3usize, | |
209 | ' ', | |
210 | builtin#lang(Alignment::Unknown), | |
211 | 0u32, | |
212 | builtin#lang(Count::Implied), | |
213 | builtin#lang(Count::Implied), | |
214 | ), | |
215 | ], | |
216 | unsafe { | |
217 | builtin#lang(UnsafeArg::new)() | |
218 | }, | |
219 | ); | |
220 | }"#]] | |
221 | .assert_eq(&body.pretty_print(&db, def)) | |
222 | } | |
4b012472 FG |
223 | |
224 | #[test] | |
225 | fn test_macro_hygiene() { | |
226 | let (db, body, def) = lower( | |
227 | r##" | |
228 | //- minicore: fmt, from | |
229 | //- /main.rs | |
230 | mod error; | |
231 | ||
232 | use crate::error::error; | |
233 | ||
234 | fn main() { | |
235 | // _ = forces body expansion instead of block def map expansion | |
236 | _ = error!("Failed to resolve path `{}`", node.text()); | |
237 | } | |
238 | //- /error.rs | |
239 | macro_rules! _error { | |
240 | ($fmt:expr, $($arg:tt)+) => {$crate::error::intermediate!(format_args!($fmt, $($arg)+))} | |
241 | } | |
242 | pub(crate) use _error as error; | |
243 | macro_rules! _intermediate { | |
244 | ($arg:expr) => {$crate::error::SsrError::new($arg)} | |
245 | } | |
246 | pub(crate) use _intermediate as intermediate; | |
247 | ||
248 | pub struct SsrError(pub(crate) core::fmt::Arguments); | |
249 | ||
250 | impl SsrError { | |
251 | pub(crate) fn new(message: impl Into<core::fmt::Arguments>) -> SsrError { | |
252 | SsrError(message.into()) | |
253 | } | |
254 | } | |
255 | "##, | |
256 | ); | |
257 | ||
258 | assert_eq!(db.body_with_source_map(def.into()).1.diagnostics(), &[]); | |
259 | expect![[r#" | |
260 | fn main() { | |
261 | _ = $crate::error::SsrError::new( | |
262 | builtin#lang(Arguments::new_v1_formatted)( | |
263 | &[ | |
264 | "Failed to resolve path `", "`", | |
265 | ], | |
266 | &[ | |
267 | builtin#lang(Argument::new_display)( | |
268 | &node.text(), | |
269 | ), | |
270 | ], | |
271 | &[ | |
272 | builtin#lang(Placeholder::new)( | |
273 | 0usize, | |
274 | ' ', | |
275 | builtin#lang(Alignment::Unknown), | |
276 | 0u32, | |
277 | builtin#lang(Count::Implied), | |
278 | builtin#lang(Count::Implied), | |
279 | ), | |
280 | ], | |
281 | unsafe { | |
282 | builtin#lang(UnsafeArg::new)() | |
283 | }, | |
284 | ), | |
285 | ); | |
286 | }"#]] | |
287 | .assert_eq(&body.pretty_print(&db, def)) | |
288 | } | |
289 | ||
290 | #[test] | |
291 | fn regression_10300() { | |
292 | let (db, body, def) = lower( | |
293 | r#" | |
294 | //- minicore: concat, panic | |
295 | mod private { | |
296 | pub use core::concat; | |
297 | } | |
298 | ||
299 | macro_rules! m { | |
300 | () => { | |
301 | panic!(concat!($crate::private::concat!("cc"))); | |
302 | }; | |
303 | } | |
304 | ||
305 | fn f() { | |
306 | m!(); | |
307 | } | |
308 | "#, | |
309 | ); | |
310 | ||
311 | let (_, source_map) = db.body_with_source_map(def.into()); | |
312 | assert_eq!(source_map.diagnostics(), &[]); | |
313 | ||
314 | for (_, def_map) in body.blocks(&db) { | |
315 | assert_eq!(def_map.diagnostics(), &[]); | |
316 | } | |
317 | ||
318 | expect![[r#" | |
319 | fn f() { | |
320 | $crate::panicking::panic_fmt( | |
321 | builtin#lang(Arguments::new_v1_formatted)( | |
322 | &[ | |
323 | "cc", | |
324 | ], | |
325 | &[], | |
326 | &[], | |
327 | unsafe { | |
328 | builtin#lang(UnsafeArg::new)() | |
329 | }, | |
330 | ), | |
331 | ); | |
332 | }"#]] | |
333 | .assert_eq(&body.pretty_print(&db, def)) | |
334 | } |