@@ -1385,4 +1385,521 @@ r"blork2.rs:2:1: 2:12
1385
1385
diag. highlight_lines( & msp, Level :: Error ) . unwrap( ) ;
1386
1386
} ) ;
1387
1387
}
1388
+
1389
+ #[ test]
1390
+ fn tab ( ) {
1391
+ let file_text = "
1392
+ fn foo() {
1393
+ \t bar;
1394
+ }
1395
+ " ;
1396
+
1397
+ let cm = Rc :: new ( CodeMap :: new ( ) ) ;
1398
+ let foo = cm. new_filemap_and_lines ( "foo.rs" , None , file_text) ;
1399
+ let span_bar = cm. span_substr ( & foo, file_text, "bar" , 0 ) ;
1400
+
1401
+ let mut snippet = SnippetData :: new ( cm, Some ( span_bar) ) ;
1402
+ snippet. push ( span_bar, true , None ) ;
1403
+
1404
+ let lines = snippet. render_lines ( ) ;
1405
+ let text = make_string ( & lines) ;
1406
+ assert_eq ! ( & text[ ..] , & "
1407
+ --> foo.rs:3:2
1408
+ |>
1409
+ 3 |> \t bar;
1410
+ |> \t ^^^
1411
+ " [ 1 ..] ) ;
1412
+ }
1413
+
1414
+ #[ test]
1415
+ fn one_line ( ) {
1416
+ let file_text = r#"
1417
+ fn foo() {
1418
+ vec.push(vec.pop().unwrap());
1419
+ }
1420
+ "# ;
1421
+
1422
+ let cm = Rc :: new ( CodeMap :: new ( ) ) ;
1423
+ let foo = cm. new_filemap_and_lines ( "foo.rs" , None , file_text) ;
1424
+ let span_vec0 = cm. span_substr ( & foo, file_text, "vec" , 0 ) ;
1425
+ let span_vec1 = cm. span_substr ( & foo, file_text, "vec" , 1 ) ;
1426
+ let span_semi = cm. span_substr ( & foo, file_text, ";" , 0 ) ;
1427
+
1428
+ let mut snippet = SnippetData :: new ( cm, None ) ;
1429
+ snippet. push ( span_vec0, false , Some ( format ! ( "previous borrow of `vec` occurs here" ) ) ) ;
1430
+ snippet. push ( span_vec1, false , Some ( format ! ( "error occurs here" ) ) ) ;
1431
+ snippet. push ( span_semi, false , Some ( format ! ( "previous borrow ends here" ) ) ) ;
1432
+
1433
+ let lines = snippet. render_lines ( ) ;
1434
+ println ! ( "{:#?}" , lines) ;
1435
+
1436
+ let text: String = make_string ( & lines) ;
1437
+
1438
+ println ! ( "text=\n {}" , text) ;
1439
+ assert_eq ! ( & text[ ..] , & r#"
1440
+ ::: foo.rs
1441
+ |>
1442
+ 3 |> vec.push(vec.pop().unwrap());
1443
+ |> --- --- - previous borrow ends here
1444
+ |> | |
1445
+ |> | error occurs here
1446
+ |> previous borrow of `vec` occurs here
1447
+ "# [ 1 ..] ) ;
1448
+ }
1449
+
1450
+ #[ test]
1451
+ fn two_files ( ) {
1452
+ let file_text_foo = r#"
1453
+ fn foo() {
1454
+ vec.push(vec.pop().unwrap());
1455
+ }
1456
+ "# ;
1457
+
1458
+ let file_text_bar = r#"
1459
+ fn bar() {
1460
+ // these blank links here
1461
+ // serve to ensure that the line numbers
1462
+ // from bar.rs
1463
+ // require more digits
1464
+
1465
+
1466
+
1467
+
1468
+
1469
+
1470
+
1471
+
1472
+
1473
+
1474
+ vec.push();
1475
+
1476
+ // this line will get elided
1477
+
1478
+ vec.pop().unwrap());
1479
+ }
1480
+ "# ;
1481
+
1482
+ let cm = Rc :: new ( CodeMap :: new ( ) ) ;
1483
+ let foo_map = cm. new_filemap_and_lines ( "foo.rs" , None , file_text_foo) ;
1484
+ let span_foo_vec0 = cm. span_substr ( & foo_map, file_text_foo, "vec" , 0 ) ;
1485
+ let span_foo_vec1 = cm. span_substr ( & foo_map, file_text_foo, "vec" , 1 ) ;
1486
+ let span_foo_semi = cm. span_substr ( & foo_map, file_text_foo, ";" , 0 ) ;
1487
+
1488
+ let bar_map = cm. new_filemap_and_lines ( "bar.rs" , None , file_text_bar) ;
1489
+ let span_bar_vec0 = cm. span_substr ( & bar_map, file_text_bar, "vec" , 0 ) ;
1490
+ let span_bar_vec1 = cm. span_substr ( & bar_map, file_text_bar, "vec" , 1 ) ;
1491
+ let span_bar_semi = cm. span_substr ( & bar_map, file_text_bar, ";" , 0 ) ;
1492
+
1493
+ let mut snippet = SnippetData :: new ( cm, Some ( span_foo_vec1) ) ;
1494
+ snippet. push ( span_foo_vec0, false , Some ( format ! ( "a" ) ) ) ;
1495
+ snippet. push ( span_foo_vec1, true , Some ( format ! ( "b" ) ) ) ;
1496
+ snippet. push ( span_foo_semi, false , Some ( format ! ( "c" ) ) ) ;
1497
+ snippet. push ( span_bar_vec0, false , Some ( format ! ( "d" ) ) ) ;
1498
+ snippet. push ( span_bar_vec1, false , Some ( format ! ( "e" ) ) ) ;
1499
+ snippet. push ( span_bar_semi, false , Some ( format ! ( "f" ) ) ) ;
1500
+
1501
+ let lines = snippet. render_lines ( ) ;
1502
+ println ! ( "{:#?}" , lines) ;
1503
+
1504
+ let text: String = make_string ( & lines) ;
1505
+
1506
+ println ! ( "text=\n {}" , text) ;
1507
+
1508
+ // Note that the `|>` remain aligned across both files:
1509
+ assert_eq ! ( & text[ ..] , & r#"
1510
+ --> foo.rs:3:14
1511
+ |>
1512
+ 3 |> vec.push(vec.pop().unwrap());
1513
+ |> --- ^^^ - c
1514
+ |> | |
1515
+ |> | b
1516
+ |> a
1517
+ ::: bar.rs
1518
+ |>
1519
+ 17 |> vec.push();
1520
+ |> --- - f
1521
+ |> |
1522
+ |> d
1523
+ ...
1524
+ 21 |> vec.pop().unwrap());
1525
+ |> --- e
1526
+ "# [ 1 ..] ) ;
1527
+ }
1528
+
1529
+ #[ test]
1530
+ fn multi_line ( ) {
1531
+ let file_text = r#"
1532
+ fn foo() {
1533
+ let name = find_id(&data, 22).unwrap();
1534
+
1535
+ // Add one more item we forgot to the vector. Silly us.
1536
+ data.push(Data { name: format!("Hera"), id: 66 });
1537
+
1538
+ // Print everything out.
1539
+ println!("Name: {:?}", name);
1540
+ println!("Data: {:?}", data);
1541
+ }
1542
+ "# ;
1543
+
1544
+ let cm = Rc :: new ( CodeMap :: new ( ) ) ;
1545
+ let foo = cm. new_filemap_and_lines ( "foo.rs" , None , file_text) ;
1546
+ let span_data0 = cm. span_substr ( & foo, file_text, "data" , 0 ) ;
1547
+ let span_data1 = cm. span_substr ( & foo, file_text, "data" , 1 ) ;
1548
+ let span_rbrace = cm. span_substr ( & foo, file_text, "}" , 3 ) ;
1549
+
1550
+ let mut snippet = SnippetData :: new ( cm, None ) ;
1551
+ snippet. push ( span_data0, false , Some ( format ! ( "immutable borrow begins here" ) ) ) ;
1552
+ snippet. push ( span_data1, false , Some ( format ! ( "mutable borrow occurs here" ) ) ) ;
1553
+ snippet. push ( span_rbrace, false , Some ( format ! ( "immutable borrow ends here" ) ) ) ;
1554
+
1555
+ let lines = snippet. render_lines ( ) ;
1556
+ println ! ( "{:#?}" , lines) ;
1557
+
1558
+ let text: String = make_string ( & lines) ;
1559
+
1560
+ println ! ( "text=\n {}" , text) ;
1561
+ assert_eq ! ( & text[ ..] , & r#"
1562
+ ::: foo.rs
1563
+ |>
1564
+ 3 |> let name = find_id(&data, 22).unwrap();
1565
+ |> ---- immutable borrow begins here
1566
+ ...
1567
+ 6 |> data.push(Data { name: format!("Hera"), id: 66 });
1568
+ |> ---- mutable borrow occurs here
1569
+ ...
1570
+ 11 |> }
1571
+ |> - immutable borrow ends here
1572
+ "# [ 1 ..] ) ;
1573
+ }
1574
+
1575
+ #[ test]
1576
+ fn overlapping ( ) {
1577
+ let file_text = r#"
1578
+ fn foo() {
1579
+ vec.push(vec.pop().unwrap());
1580
+ }
1581
+ "# ;
1582
+
1583
+ let cm = Rc :: new ( CodeMap :: new ( ) ) ;
1584
+ let foo = cm. new_filemap_and_lines ( "foo.rs" , None , file_text) ;
1585
+ let span0 = cm. span_substr ( & foo, file_text, "vec.push" , 0 ) ;
1586
+ let span1 = cm. span_substr ( & foo, file_text, "vec" , 0 ) ;
1587
+ let span2 = cm. span_substr ( & foo, file_text, "ec.push" , 0 ) ;
1588
+ let span3 = cm. span_substr ( & foo, file_text, "unwrap" , 0 ) ;
1589
+
1590
+ let mut snippet = SnippetData :: new ( cm, None ) ;
1591
+ snippet. push ( span0, false , Some ( format ! ( "A" ) ) ) ;
1592
+ snippet. push ( span1, false , Some ( format ! ( "B" ) ) ) ;
1593
+ snippet. push ( span2, false , Some ( format ! ( "C" ) ) ) ;
1594
+ snippet. push ( span3, false , Some ( format ! ( "D" ) ) ) ;
1595
+
1596
+ let lines = snippet. render_lines ( ) ;
1597
+ println ! ( "{:#?}" , lines) ;
1598
+ let text: String = make_string ( & lines) ;
1599
+
1600
+ println ! ( "text=r#\" \n {}\" .trim_left()" , text) ;
1601
+ assert_eq ! ( & text[ ..] , & r#"
1602
+ ::: foo.rs
1603
+ |>
1604
+ 3 |> vec.push(vec.pop().unwrap());
1605
+ |> -------- ------ D
1606
+ |> ||
1607
+ |> |C
1608
+ |> A
1609
+ |> B
1610
+ "# [ 1 ..] ) ;
1611
+ }
1612
+
1613
+ #[ test]
1614
+ fn one_line_out_of_order ( ) {
1615
+ let file_text = r#"
1616
+ fn foo() {
1617
+ vec.push(vec.pop().unwrap());
1618
+ }
1619
+ "# ;
1620
+
1621
+ let cm = Rc :: new ( CodeMap :: new ( ) ) ;
1622
+ let foo = cm. new_filemap_and_lines ( "foo.rs" , None , file_text) ;
1623
+ let span_vec0 = cm. span_substr ( & foo, file_text, "vec" , 0 ) ;
1624
+ let span_vec1 = cm. span_substr ( & foo, file_text, "vec" , 1 ) ;
1625
+ let span_semi = cm. span_substr ( & foo, file_text, ";" , 0 ) ;
1626
+
1627
+ // intentionally don't push the snippets left to right
1628
+ let mut snippet = SnippetData :: new ( cm, None ) ;
1629
+ snippet. push ( span_vec1, false , Some ( format ! ( "error occurs here" ) ) ) ;
1630
+ snippet. push ( span_vec0, false , Some ( format ! ( "previous borrow of `vec` occurs here" ) ) ) ;
1631
+ snippet. push ( span_semi, false , Some ( format ! ( "previous borrow ends here" ) ) ) ;
1632
+
1633
+ let lines = snippet. render_lines ( ) ;
1634
+ println ! ( "{:#?}" , lines) ;
1635
+ let text: String = make_string ( & lines) ;
1636
+
1637
+ println ! ( "text=r#\" \n {}\" .trim_left()" , text) ;
1638
+ assert_eq ! ( & text[ ..] , & r#"
1639
+ ::: foo.rs
1640
+ |>
1641
+ 3 |> vec.push(vec.pop().unwrap());
1642
+ |> --- --- - previous borrow ends here
1643
+ |> | |
1644
+ |> | error occurs here
1645
+ |> previous borrow of `vec` occurs here
1646
+ "# [ 1 ..] ) ;
1647
+ }
1648
+
1649
+ #[ test]
1650
+ fn elide_unnecessary_lines ( ) {
1651
+ let file_text = r#"
1652
+ fn foo() {
1653
+ let mut vec = vec![0, 1, 2];
1654
+ let mut vec2 = vec;
1655
+ vec2.push(3);
1656
+ vec2.push(4);
1657
+ vec2.push(5);
1658
+ vec2.push(6);
1659
+ vec.push(7);
1660
+ }
1661
+ "# ;
1662
+
1663
+ let cm = Rc :: new ( CodeMap :: new ( ) ) ;
1664
+ let foo = cm. new_filemap_and_lines ( "foo.rs" , None , file_text) ;
1665
+ let span_vec0 = cm. span_substr ( & foo, file_text, "vec" , 3 ) ;
1666
+ let span_vec1 = cm. span_substr ( & foo, file_text, "vec" , 8 ) ;
1667
+
1668
+ let mut snippet = SnippetData :: new ( cm, None ) ;
1669
+ snippet. push ( span_vec0, false , Some ( format ! ( "`vec` moved here because it \
1670
+ has type `collections::vec::Vec<i32>`") ) ) ;
1671
+ snippet. push ( span_vec1, false , Some ( format ! ( "use of moved value: `vec`" ) ) ) ;
1672
+
1673
+ let lines = snippet. render_lines ( ) ;
1674
+ println ! ( "{:#?}" , lines) ;
1675
+ let text: String = make_string ( & lines) ;
1676
+ println ! ( "text=r#\" \n {}\" .trim_left()" , text) ;
1677
+ assert_eq ! ( & text[ ..] , & r#"
1678
+ ::: foo.rs
1679
+ |>
1680
+ 4 |> let mut vec2 = vec;
1681
+ |> --- `vec` moved here because it has type `collections::vec::Vec<i32>`
1682
+ ...
1683
+ 9 |> vec.push(7);
1684
+ |> --- use of moved value: `vec`
1685
+ "# [ 1 ..] ) ;
1686
+ }
1687
+
1688
+ #[ test]
1689
+ fn spans_without_labels ( ) {
1690
+ let file_text = r#"
1691
+ fn foo() {
1692
+ let mut vec = vec![0, 1, 2];
1693
+ let mut vec2 = vec;
1694
+ vec2.push(3);
1695
+ vec2.push(4);
1696
+ vec2.push(5);
1697
+ vec2.push(6);
1698
+ vec.push(7);
1699
+ }
1700
+ "# ;
1701
+
1702
+ let cm = Rc :: new ( CodeMap :: new ( ) ) ;
1703
+ let foo = cm. new_filemap_and_lines ( "foo.rs" , None , file_text) ;
1704
+
1705
+ let mut snippet = SnippetData :: new ( cm. clone ( ) , None ) ;
1706
+ for i in 0 ..4 {
1707
+ let span_veci = cm. span_substr ( & foo, file_text, "vec" , i) ;
1708
+ snippet. push ( span_veci, false , None ) ;
1709
+ }
1710
+
1711
+ let lines = snippet. render_lines ( ) ;
1712
+ let text: String = make_string ( & lines) ;
1713
+ println ! ( "text=&r#\" \n {}\n \" #[1..]" , text) ;
1714
+ assert_eq ! ( text, & r#"
1715
+ ::: foo.rs
1716
+ |>
1717
+ 3 |> let mut vec = vec![0, 1, 2];
1718
+ |> --- ---
1719
+ 4 |> let mut vec2 = vec;
1720
+ |> --- ---
1721
+ "# [ 1 ..] ) ;
1722
+ }
1723
+
1724
+ #[ test]
1725
+ fn span_long_selection ( ) {
1726
+ let file_text = r#"
1727
+ impl SomeTrait for () {
1728
+ fn foo(x: u32) {
1729
+ // impl 1
1730
+ // impl 2
1731
+ // impl 3
1732
+ }
1733
+ }
1734
+ "# ;
1735
+
1736
+ let cm = Rc :: new ( CodeMap :: new ( ) ) ;
1737
+ let foo = cm. new_filemap_and_lines ( "foo.rs" , None , file_text) ;
1738
+
1739
+ let mut snippet = SnippetData :: new ( cm. clone ( ) , None ) ;
1740
+ let fn_span = cm. span_substr ( & foo, file_text, "fn" , 0 ) ;
1741
+ let rbrace_span = cm. span_substr ( & foo, file_text, "}" , 0 ) ;
1742
+ snippet. push ( splice ( fn_span, rbrace_span) , false , None ) ;
1743
+ let lines = snippet. render_lines ( ) ;
1744
+ let text: String = make_string ( & lines) ;
1745
+ println ! ( "r#\" \n {}\" " , text) ;
1746
+ assert_eq ! ( text, & r#"
1747
+ ::: foo.rs
1748
+ |>
1749
+ 3 |> fn foo(x: u32) {
1750
+ |> -
1751
+ "# [ 1 ..] ) ;
1752
+ }
1753
+
1754
+ #[ test]
1755
+ fn span_overlap_label ( ) {
1756
+ // Test that we don't put `x_span` to the right of its highlight,
1757
+ // since there is another highlight that overlaps it.
1758
+
1759
+ let file_text = r#"
1760
+ fn foo(x: u32) {
1761
+ }
1762
+ }
1763
+ "# ;
1764
+
1765
+ let cm = Rc :: new ( CodeMap :: new ( ) ) ;
1766
+ let foo = cm. new_filemap_and_lines ( "foo.rs" , None , file_text) ;
1767
+
1768
+ let mut snippet = SnippetData :: new ( cm. clone ( ) , None ) ;
1769
+ let fn_span = cm. span_substr ( & foo, file_text, "fn foo(x: u32)" , 0 ) ;
1770
+ let x_span = cm. span_substr ( & foo, file_text, "x" , 0 ) ;
1771
+ snippet. push ( fn_span, false , Some ( format ! ( "fn_span" ) ) ) ;
1772
+ snippet. push ( x_span, false , Some ( format ! ( "x_span" ) ) ) ;
1773
+ let lines = snippet. render_lines ( ) ;
1774
+ let text: String = make_string ( & lines) ;
1775
+ println ! ( "r#\" \n {}\" " , text) ;
1776
+ assert_eq ! ( text, & r#"
1777
+ ::: foo.rs
1778
+ |>
1779
+ 2 |> fn foo(x: u32) {
1780
+ |> --------------
1781
+ |> | |
1782
+ |> | x_span
1783
+ |> fn_span
1784
+ "# [ 1 ..] ) ;
1785
+ }
1786
+
1787
+ #[ test]
1788
+ fn span_overlap_label2 ( ) {
1789
+ // Test that we don't put `x_span` to the right of its highlight,
1790
+ // since there is another highlight that overlaps it. In this
1791
+ // case, the overlap is only at the beginning, but it's still
1792
+ // better to show the beginning more clearly.
1793
+
1794
+ let file_text = r#"
1795
+ fn foo(x: u32) {
1796
+ }
1797
+ }
1798
+ "# ;
1799
+
1800
+ let cm = Rc :: new ( CodeMap :: new ( ) ) ;
1801
+ let foo = cm. new_filemap_and_lines ( "foo.rs" , None , file_text) ;
1802
+
1803
+ let mut snippet = SnippetData :: new ( cm. clone ( ) , None ) ;
1804
+ let fn_span = cm. span_substr ( & foo, file_text, "fn foo(x" , 0 ) ;
1805
+ let x_span = cm. span_substr ( & foo, file_text, "x: u32)" , 0 ) ;
1806
+ snippet. push ( fn_span, false , Some ( format ! ( "fn_span" ) ) ) ;
1807
+ snippet. push ( x_span, false , Some ( format ! ( "x_span" ) ) ) ;
1808
+ let lines = snippet. render_lines ( ) ;
1809
+ let text: String = make_string ( & lines) ;
1810
+ println ! ( "r#\" \n {}\" " , text) ;
1811
+ assert_eq ! ( text, & r#"
1812
+ ::: foo.rs
1813
+ |>
1814
+ 2 |> fn foo(x: u32) {
1815
+ |> --------------
1816
+ |> | |
1817
+ |> | x_span
1818
+ |> fn_span
1819
+ "# [ 1 ..] ) ;
1820
+ }
1821
+
1822
+ #[ test]
1823
+ fn span_overlap_label3 ( ) {
1824
+ // Test that we don't put `x_span` to the right of its highlight,
1825
+ // since there is another highlight that overlaps it. In this
1826
+ // case, the overlap is only at the beginning, but it's still
1827
+ // better to show the beginning more clearly.
1828
+
1829
+ let file_text = r#"
1830
+ fn foo() {
1831
+ let closure = || {
1832
+ inner
1833
+ };
1834
+ }
1835
+ }
1836
+ "# ;
1837
+
1838
+ let cm = Rc :: new ( CodeMap :: new ( ) ) ;
1839
+ let foo = cm. new_filemap_and_lines ( "foo.rs" , None , file_text) ;
1840
+
1841
+ let mut snippet = SnippetData :: new ( cm. clone ( ) , None ) ;
1842
+
1843
+ let closure_span = {
1844
+ let closure_start_span = cm. span_substr ( & foo, file_text, "||" , 0 ) ;
1845
+ let closure_end_span = cm. span_substr ( & foo, file_text, "}" , 0 ) ;
1846
+ splice ( closure_start_span, closure_end_span)
1847
+ } ;
1848
+
1849
+ let inner_span = cm. span_substr ( & foo, file_text, "inner" , 0 ) ;
1850
+
1851
+ snippet. push ( closure_span, false , Some ( format ! ( "foo" ) ) ) ;
1852
+ snippet. push ( inner_span, false , Some ( format ! ( "bar" ) ) ) ;
1853
+
1854
+ let lines = snippet. render_lines ( ) ;
1855
+ let text: String = make_string ( & lines) ;
1856
+ println ! ( "r#\" \n {}\" " , text) ;
1857
+ assert_eq ! ( text, & r#"
1858
+ ::: foo.rs
1859
+ |>
1860
+ 3 |> let closure = || {
1861
+ |> - foo
1862
+ 4 |> inner
1863
+ |> ----- bar
1864
+ "# [ 1 ..] ) ;
1865
+ }
1866
+
1867
+ #[ test]
1868
+ fn span_empty ( ) {
1869
+ // In one of the unit tests, we found that the parser sometimes
1870
+ // gives empty spans, and in particular it supplied an EOF span
1871
+ // like this one, which points at the very end. We want to
1872
+ // fallback gracefully in this case.
1873
+
1874
+ let file_text = r#"
1875
+ fn main() {
1876
+ struct Foo;
1877
+
1878
+ impl !Sync for Foo {}
1879
+
1880
+ unsafe impl Send for &'static Foo {
1881
+ // error: cross-crate traits with a default impl, like `core::marker::Send`,
1882
+ // can only be implemented for a struct/enum type, not
1883
+ // `&'static Foo`
1884
+ }"# ;
1885
+
1886
+
1887
+ let cm = Rc :: new ( CodeMap :: new ( ) ) ;
1888
+ let foo = cm. new_filemap_and_lines ( "foo.rs" , None , file_text) ;
1889
+
1890
+ let mut rbrace_span = cm. span_substr ( & foo, file_text, "}" , 1 ) ;
1891
+ rbrace_span. lo = rbrace_span. hi ;
1892
+
1893
+ let mut snippet = SnippetData :: new ( cm. clone ( ) , Some ( rbrace_span) ) ;
1894
+ snippet. push ( rbrace_span, false , None ) ;
1895
+ let lines = snippet. render_lines ( ) ;
1896
+ let text: String = make_string ( & lines) ;
1897
+ println ! ( "r#\" \n {}\" " , text) ;
1898
+ assert_eq ! ( text, & r#"
1899
+ --> foo.rs:11:2
1900
+ |>
1901
+ 11 |> }
1902
+ |> -
1903
+ "# [ 1 ..] ) ;
1904
+ }
1388
1905
}
0 commit comments