aboutsummaryrefslogtreecommitdiff
path: root/crates/ide_db/src/helpers/insert_use
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ide_db/src/helpers/insert_use')
-rw-r--r--crates/ide_db/src/helpers/insert_use/tests.rs620
1 files changed, 620 insertions, 0 deletions
diff --git a/crates/ide_db/src/helpers/insert_use/tests.rs b/crates/ide_db/src/helpers/insert_use/tests.rs
new file mode 100644
index 000000000..86bfa5b41
--- /dev/null
+++ b/crates/ide_db/src/helpers/insert_use/tests.rs
@@ -0,0 +1,620 @@
1use super::*;
2
3use test_utils::assert_eq_text;
4
5#[test]
6fn insert_existing() {
7 check_full("std::fs", "use std::fs;", "use std::fs;")
8}
9
10#[test]
11fn insert_start() {
12 check_none(
13 "std::bar::AA",
14 r"
15use std::bar::B;
16use std::bar::D;
17use std::bar::F;
18use std::bar::G;",
19 r"
20use std::bar::AA;
21use std::bar::B;
22use std::bar::D;
23use std::bar::F;
24use std::bar::G;",
25 )
26}
27
28#[test]
29fn insert_start_indent() {
30 mark::check!(insert_use_indent_after);
31 check_none(
32 "std::bar::AA",
33 r"
34 use std::bar::B;
35 use std::bar::D;",
36 r"
37 use std::bar::AA;
38 use std::bar::B;
39 use std::bar::D;",
40 )
41}
42
43#[test]
44fn insert_middle() {
45 check_none(
46 "std::bar::EE",
47 r"
48use std::bar::A;
49use std::bar::D;
50use std::bar::F;
51use std::bar::G;",
52 r"
53use std::bar::A;
54use std::bar::D;
55use std::bar::EE;
56use std::bar::F;
57use std::bar::G;",
58 )
59}
60
61#[test]
62fn insert_middle_indent() {
63 check_none(
64 "std::bar::EE",
65 r"
66 use std::bar::A;
67 use std::bar::D;
68 use std::bar::F;
69 use std::bar::G;",
70 r"
71 use std::bar::A;
72 use std::bar::D;
73 use std::bar::EE;
74 use std::bar::F;
75 use std::bar::G;",
76 )
77}
78
79#[test]
80fn insert_end() {
81 check_none(
82 "std::bar::ZZ",
83 r"
84use std::bar::A;
85use std::bar::D;
86use std::bar::F;
87use std::bar::G;",
88 r"
89use std::bar::A;
90use std::bar::D;
91use std::bar::F;
92use std::bar::G;
93use std::bar::ZZ;",
94 )
95}
96
97#[test]
98fn insert_end_indent() {
99 mark::check!(insert_use_indent_before);
100 check_none(
101 "std::bar::ZZ",
102 r"
103 use std::bar::A;
104 use std::bar::D;
105 use std::bar::F;
106 use std::bar::G;",
107 r"
108 use std::bar::A;
109 use std::bar::D;
110 use std::bar::F;
111 use std::bar::G;
112 use std::bar::ZZ;",
113 )
114}
115
116#[test]
117fn insert_middle_nested() {
118 check_none(
119 "std::bar::EE",
120 r"
121use std::bar::A;
122use std::bar::{D, Z}; // example of weird imports due to user
123use std::bar::F;
124use std::bar::G;",
125 r"
126use std::bar::A;
127use std::bar::EE;
128use std::bar::{D, Z}; // example of weird imports due to user
129use std::bar::F;
130use std::bar::G;",
131 )
132}
133
134#[test]
135fn insert_middle_groups() {
136 check_none(
137 "foo::bar::GG",
138 r"
139 use std::bar::A;
140 use std::bar::D;
141
142 use foo::bar::F;
143 use foo::bar::H;",
144 r"
145 use std::bar::A;
146 use std::bar::D;
147
148 use foo::bar::F;
149 use foo::bar::GG;
150 use foo::bar::H;",
151 )
152}
153
154#[test]
155fn insert_first_matching_group() {
156 check_none(
157 "foo::bar::GG",
158 r"
159 use foo::bar::A;
160 use foo::bar::D;
161
162 use std;
163
164 use foo::bar::F;
165 use foo::bar::H;",
166 r"
167 use foo::bar::A;
168 use foo::bar::D;
169 use foo::bar::GG;
170
171 use std;
172
173 use foo::bar::F;
174 use foo::bar::H;",
175 )
176}
177
178#[test]
179fn insert_missing_group_std() {
180 check_none(
181 "std::fmt",
182 r"
183 use foo::bar::A;
184 use foo::bar::D;",
185 r"
186 use std::fmt;
187
188 use foo::bar::A;
189 use foo::bar::D;",
190 )
191}
192
193#[test]
194fn insert_missing_group_self() {
195 check_none(
196 "self::fmt",
197 r"
198use foo::bar::A;
199use foo::bar::D;",
200 r"
201use foo::bar::A;
202use foo::bar::D;
203
204use self::fmt;",
205 )
206}
207
208#[test]
209fn insert_no_imports() {
210 check_full(
211 "foo::bar",
212 "fn main() {}",
213 r"use foo::bar;
214
215fn main() {}",
216 )
217}
218
219#[test]
220fn insert_empty_file() {
221 // empty files will get two trailing newlines
222 // this is due to the test case insert_no_imports above
223 check_full(
224 "foo::bar",
225 "",
226 r"use foo::bar;
227
228",
229 )
230}
231
232#[test]
233fn insert_empty_module() {
234 mark::check!(insert_use_no_indent_after);
235 check(
236 "foo::bar",
237 "mod x {}",
238 r"{
239 use foo::bar;
240}",
241 None,
242 true,
243 )
244}
245
246#[test]
247fn insert_after_inner_attr() {
248 check_full(
249 "foo::bar",
250 r"#![allow(unused_imports)]",
251 r"#![allow(unused_imports)]
252
253use foo::bar;",
254 )
255}
256
257#[test]
258fn insert_after_inner_attr2() {
259 check_full(
260 "foo::bar",
261 r"#![allow(unused_imports)]
262
263#![no_std]
264fn main() {}",
265 r"#![allow(unused_imports)]
266
267#![no_std]
268
269use foo::bar;
270fn main() {}",
271 );
272}
273
274#[test]
275fn inserts_after_single_line_inner_comments() {
276 check_none(
277 "foo::bar::Baz",
278 "//! Single line inner comments do not allow any code before them.",
279 r#"//! Single line inner comments do not allow any code before them.
280
281use foo::bar::Baz;"#,
282 );
283}
284
285#[test]
286fn inserts_after_multiline_inner_comments() {
287 check_none(
288 "foo::bar::Baz",
289 r#"/*! Multiline inner comments do not allow any code before them. */
290
291/*! Still an inner comment, cannot place any code before. */
292fn main() {}"#,
293 r#"/*! Multiline inner comments do not allow any code before them. */
294
295/*! Still an inner comment, cannot place any code before. */
296
297use foo::bar::Baz;
298fn main() {}"#,
299 )
300}
301
302#[test]
303fn inserts_after_all_inner_items() {
304 check_none(
305 "foo::bar::Baz",
306 r#"#![allow(unused_imports)]
307/*! Multiline line comment 2 */
308
309
310//! Single line comment 1
311#![no_std]
312//! Single line comment 2
313fn main() {}"#,
314 r#"#![allow(unused_imports)]
315/*! Multiline line comment 2 */
316
317
318//! Single line comment 1
319#![no_std]
320//! Single line comment 2
321
322use foo::bar::Baz;
323fn main() {}"#,
324 )
325}
326
327#[test]
328fn merge_groups() {
329 check_last("std::io", r"use std::fmt;", r"use std::{fmt, io};")
330}
331
332#[test]
333fn merge_groups_last() {
334 check_last(
335 "std::io",
336 r"use std::fmt::{Result, Display};",
337 r"use std::fmt::{Result, Display};
338use std::io;",
339 )
340}
341
342#[test]
343fn merge_last_into_self() {
344 check_last("foo::bar::baz", r"use foo::bar;", r"use foo::bar::{self, baz};");
345}
346
347#[test]
348fn merge_groups_full() {
349 check_full(
350 "std::io",
351 r"use std::fmt::{Result, Display};",
352 r"use std::{fmt::{Result, Display}, io};",
353 )
354}
355
356#[test]
357fn merge_groups_long_full() {
358 check_full("std::foo::bar::Baz", r"use std::foo::bar::Qux;", r"use std::foo::bar::{Baz, Qux};")
359}
360
361#[test]
362fn merge_groups_long_last() {
363 check_last("std::foo::bar::Baz", r"use std::foo::bar::Qux;", r"use std::foo::bar::{Baz, Qux};")
364}
365
366#[test]
367fn merge_groups_long_full_list() {
368 check_full(
369 "std::foo::bar::Baz",
370 r"use std::foo::bar::{Qux, Quux};",
371 r"use std::foo::bar::{Baz, Quux, Qux};",
372 )
373}
374
375#[test]
376fn merge_groups_long_last_list() {
377 check_last(
378 "std::foo::bar::Baz",
379 r"use std::foo::bar::{Qux, Quux};",
380 r"use std::foo::bar::{Baz, Quux, Qux};",
381 )
382}
383
384#[test]
385fn merge_groups_long_full_nested() {
386 check_full(
387 "std::foo::bar::Baz",
388 r"use std::foo::bar::{Qux, quux::{Fez, Fizz}};",
389 r"use std::foo::bar::{Baz, Qux, quux::{Fez, Fizz}};",
390 )
391}
392
393#[test]
394fn merge_groups_long_last_nested() {
395 check_last(
396 "std::foo::bar::Baz",
397 r"use std::foo::bar::{Qux, quux::{Fez, Fizz}};",
398 r"use std::foo::bar::Baz;
399use std::foo::bar::{Qux, quux::{Fez, Fizz}};",
400 )
401}
402
403#[test]
404fn merge_groups_full_nested_deep() {
405 check_full(
406 "std::foo::bar::quux::Baz",
407 r"use std::foo::bar::{Qux, quux::{Fez, Fizz}};",
408 r"use std::foo::bar::{Qux, quux::{Baz, Fez, Fizz}};",
409 )
410}
411
412#[test]
413fn merge_groups_full_nested_long() {
414 check_full(
415 "std::foo::bar::Baz",
416 r"use std::{foo::bar::Qux};",
417 r"use std::{foo::bar::{Baz, Qux}};",
418 );
419}
420
421#[test]
422fn merge_groups_last_nested_long() {
423 check_full(
424 "std::foo::bar::Baz",
425 r"use std::{foo::bar::Qux};",
426 r"use std::{foo::bar::{Baz, Qux}};",
427 );
428}
429
430#[test]
431fn merge_groups_skip_pub() {
432 check_full(
433 "std::io",
434 r"pub use std::fmt::{Result, Display};",
435 r"pub use std::fmt::{Result, Display};
436use std::io;",
437 )
438}
439
440#[test]
441fn merge_groups_skip_pub_crate() {
442 check_full(
443 "std::io",
444 r"pub(crate) use std::fmt::{Result, Display};",
445 r"pub(crate) use std::fmt::{Result, Display};
446use std::io;",
447 )
448}
449
450#[test]
451#[ignore] // FIXME: Support this
452fn split_out_merge() {
453 check_last(
454 "std::fmt::Result",
455 r"use std::{fmt, io};",
456 r"use std::fmt::{self, Result};
457use std::io;",
458 )
459}
460
461#[test]
462fn merge_into_module_import() {
463 check_full("std::fmt::Result", r"use std::{fmt, io};", r"use std::{fmt::{self, Result}, io};")
464}
465
466#[test]
467fn merge_groups_self() {
468 check_full("std::fmt::Debug", r"use std::fmt;", r"use std::fmt::{self, Debug};")
469}
470
471#[test]
472fn merge_mod_into_glob() {
473 check_full("token::TokenKind", r"use token::TokenKind::*;", r"use token::TokenKind::{*, self};")
474 // FIXME: have it emit `use token::TokenKind::{self, *}`?
475}
476
477#[test]
478fn merge_self_glob() {
479 check_full("self", r"use self::*;", r"use self::{*, self};")
480 // FIXME: have it emit `use {self, *}`?
481}
482
483#[test]
484fn merge_glob_nested() {
485 check_full(
486 "foo::bar::quux::Fez",
487 r"use foo::bar::{Baz, quux::*};",
488 r"use foo::bar::{Baz, quux::{self::*, Fez}};",
489 )
490}
491
492#[test]
493fn merge_nested_considers_first_segments() {
494 check_full(
495 "hir_ty::display::write_bounds_like_dyn_trait",
496 r"use hir_ty::{autoderef, display::{HirDisplayError, HirFormatter}, method_resolution};",
497 r"use hir_ty::{autoderef, display::{HirDisplayError, HirFormatter, write_bounds_like_dyn_trait}, method_resolution};",
498 );
499}
500
501#[test]
502fn skip_merge_last_too_long() {
503 check_last(
504 "foo::bar",
505 r"use foo::bar::baz::Qux;",
506 r"use foo::bar;
507use foo::bar::baz::Qux;",
508 );
509}
510
511#[test]
512fn skip_merge_last_too_long2() {
513 check_last(
514 "foo::bar::baz::Qux",
515 r"use foo::bar;",
516 r"use foo::bar;
517use foo::bar::baz::Qux;",
518 );
519}
520
521#[test]
522fn insert_short_before_long() {
523 check_none(
524 "foo::bar",
525 r"use foo::bar::baz::Qux;",
526 r"use foo::bar;
527use foo::bar::baz::Qux;",
528 );
529}
530
531#[test]
532fn merge_last_fail() {
533 check_merge_only_fail(
534 r"use foo::bar::{baz::{Qux, Fez}};",
535 r"use foo::bar::{baaz::{Quux, Feez}};",
536 MergeBehaviour::Last,
537 );
538}
539
540#[test]
541fn merge_last_fail1() {
542 check_merge_only_fail(
543 r"use foo::bar::{baz::{Qux, Fez}};",
544 r"use foo::bar::baaz::{Quux, Feez};",
545 MergeBehaviour::Last,
546 );
547}
548
549#[test]
550fn merge_last_fail2() {
551 check_merge_only_fail(
552 r"use foo::bar::baz::{Qux, Fez};",
553 r"use foo::bar::{baaz::{Quux, Feez}};",
554 MergeBehaviour::Last,
555 );
556}
557
558#[test]
559fn merge_last_fail3() {
560 check_merge_only_fail(
561 r"use foo::bar::baz::{Qux, Fez};",
562 r"use foo::bar::baaz::{Quux, Feez};",
563 MergeBehaviour::Last,
564 );
565}
566
567fn check(
568 path: &str,
569 ra_fixture_before: &str,
570 ra_fixture_after: &str,
571 mb: Option<MergeBehaviour>,
572 module: bool,
573) {
574 let mut syntax = ast::SourceFile::parse(ra_fixture_before).tree().syntax().clone();
575 if module {
576 syntax = syntax.descendants().find_map(ast::Module::cast).unwrap().syntax().clone();
577 }
578 let file = super::ImportScope::from(syntax).unwrap();
579 let path = ast::SourceFile::parse(&format!("use {};", path))
580 .tree()
581 .syntax()
582 .descendants()
583 .find_map(ast::Path::cast)
584 .unwrap();
585
586 let rewriter = insert_use(&file, path, mb);
587 let result = rewriter.rewrite(file.as_syntax_node()).to_string();
588 assert_eq_text!(&result, ra_fixture_after);
589}
590
591fn check_full(path: &str, ra_fixture_before: &str, ra_fixture_after: &str) {
592 check(path, ra_fixture_before, ra_fixture_after, Some(MergeBehaviour::Full), false)
593}
594
595fn check_last(path: &str, ra_fixture_before: &str, ra_fixture_after: &str) {
596 check(path, ra_fixture_before, ra_fixture_after, Some(MergeBehaviour::Last), false)
597}
598
599fn check_none(path: &str, ra_fixture_before: &str, ra_fixture_after: &str) {
600 check(path, ra_fixture_before, ra_fixture_after, None, false)
601}
602
603fn check_merge_only_fail(ra_fixture0: &str, ra_fixture1: &str, mb: MergeBehaviour) {
604 let use0 = ast::SourceFile::parse(ra_fixture0)
605 .tree()
606 .syntax()
607 .descendants()
608 .find_map(ast::Use::cast)
609 .unwrap();
610
611 let use1 = ast::SourceFile::parse(ra_fixture1)
612 .tree()
613 .syntax()
614 .descendants()
615 .find_map(ast::Use::cast)
616 .unwrap();
617
618 let result = try_merge_imports(&use0, &use1, mb);
619 assert_eq!(result.map(|u| u.to_string()), None);
620}