aboutsummaryrefslogtreecommitdiff
path: root/crates
diff options
context:
space:
mode:
authorAleksey Kladov <[email protected]>2020-06-29 13:21:57 +0100
committerAleksey Kladov <[email protected]>2020-06-29 16:23:01 +0100
commite805e8c1d5bf26e9716fb855f97d950395129c20 (patch)
treed42f406a04551626fba261e75edd752ffb1894c2 /crates
parent82ce5792ab70ab8d20a1afde72c5400c27b9c190 (diff)
(T): make typification tests more data driven
Diffstat (limited to 'crates')
-rw-r--r--crates/ra_hir_ty/src/test_db.rs13
-rw-r--r--crates/ra_hir_ty/src/tests.rs16
-rw-r--r--crates/ra_hir_ty/src/tests/never_type.rs118
-rw-r--r--crates/ra_hir_ty/src/tests/simple.rs89
-rw-r--r--crates/test_utils/src/lib.rs34
5 files changed, 137 insertions, 133 deletions
diff --git a/crates/ra_hir_ty/src/test_db.rs b/crates/ra_hir_ty/src/test_db.rs
index 9c2c6959d..0481a7b12 100644
--- a/crates/ra_hir_ty/src/test_db.rs
+++ b/crates/ra_hir_ty/src/test_db.rs
@@ -154,6 +154,19 @@ impl TestDB {
154 }); 154 });
155 (buf, count) 155 (buf, count)
156 } 156 }
157
158 pub fn all_files(&self) -> Vec<FileId> {
159 let mut res = Vec::new();
160 let crate_graph = self.crate_graph();
161 for krate in crate_graph.iter() {
162 let crate_def_map = self.crate_def_map(krate);
163 for (module_id, _) in crate_def_map.modules.iter() {
164 let file_id = crate_def_map[module_id].origin.file_id();
165 res.extend(file_id)
166 }
167 }
168 res
169 }
157} 170}
158 171
159impl TestDB { 172impl TestDB {
diff --git a/crates/ra_hir_ty/src/tests.rs b/crates/ra_hir_ty/src/tests.rs
index 2a85ce85d..4d0dc3011 100644
--- a/crates/ra_hir_ty/src/tests.rs
+++ b/crates/ra_hir_ty/src/tests.rs
@@ -28,6 +28,7 @@ use ra_syntax::{
28 SyntaxNode, 28 SyntaxNode,
29}; 29};
30use stdx::format_to; 30use stdx::format_to;
31use test_utils::extract_annotations;
31 32
32use crate::{ 33use crate::{
33 db::HirDatabase, display::HirDisplay, infer::TypeMismatch, test_db::TestDB, InferenceResult, Ty, 34 db::HirDatabase, display::HirDisplay, infer::TypeMismatch, test_db::TestDB, InferenceResult, Ty,
@@ -37,6 +38,21 @@ use crate::{
37// against snapshots of the expected results using insta. Use cargo-insta to 38// against snapshots of the expected results using insta. Use cargo-insta to
38// update the snapshots. 39// update the snapshots.
39 40
41fn check_types(ra_fixture: &str) {
42 let db = TestDB::with_files(ra_fixture);
43 let mut checked_one = false;
44 for file_id in db.all_files() {
45 let text = db.parse(file_id).syntax_node().to_string();
46 let annotations = extract_annotations(&text);
47 for (offset, expected) in annotations {
48 let actual = type_at_pos(&db, FilePosition { file_id, offset });
49 assert_eq!(expected, actual);
50 checked_one = true;
51 }
52 }
53 assert!(checked_one, "no `//^` annotations found");
54}
55
40fn type_at_pos(db: &TestDB, pos: FilePosition) -> String { 56fn type_at_pos(db: &TestDB, pos: FilePosition) -> String {
41 type_at_pos_displayed(db, pos, |ty, _| ty.display(db).to_string()) 57 type_at_pos_displayed(db, pos, |ty, _| ty.display(db).to_string())
42} 58}
diff --git a/crates/ra_hir_ty/src/tests/never_type.rs b/crates/ra_hir_ty/src/tests/never_type.rs
index ab9a990f5..64d421d40 100644
--- a/crates/ra_hir_ty/src/tests/never_type.rs
+++ b/crates/ra_hir_ty/src/tests/never_type.rs
@@ -1,99 +1,91 @@
1use insta::assert_snapshot; 1use insta::assert_snapshot;
2 2
3use super::{infer_with_mismatches, type_at}; 3use super::{check_types, infer_with_mismatches};
4 4
5#[test] 5#[test]
6fn infer_never1() { 6fn infer_never1() {
7 let t = type_at( 7 check_types(
8 r#" 8 r#"
9//- /main.rs
10fn test() { 9fn test() {
11 let t = return; 10 let t = return;
12 t<|>; 11 t;
13} 12} //^ !
14"#, 13"#,
15 ); 14 );
16 assert_eq!(t, "!");
17} 15}
18 16
19#[test] 17#[test]
20fn infer_never2() { 18fn infer_never2() {
21 let t = type_at( 19 check_types(
22 r#" 20 r#"
23//- /main.rs
24fn gen<T>() -> T { loop {} } 21fn gen<T>() -> T { loop {} }
25 22
26fn test() { 23fn test() {
27 let a = gen(); 24 let a = gen();
28 if false { a } else { loop {} }; 25 if false { a } else { loop {} };
29 a<|>; 26 a;
30} 27} //^ !
31"#, 28"#,
32 ); 29 );
33 assert_eq!(t, "!");
34} 30}
35 31
36#[test] 32#[test]
37fn infer_never3() { 33fn infer_never3() {
38 let t = type_at( 34 check_types(
39 r#" 35 r#"
40//- /main.rs
41fn gen<T>() -> T { loop {} } 36fn gen<T>() -> T { loop {} }
42 37
43fn test() { 38fn test() {
44 let a = gen(); 39 let a = gen();
45 if false { loop {} } else { a }; 40 if false { loop {} } else { a };
46 a<|>; 41 a;
42 //^ !
47} 43}
48"#, 44"#,
49 ); 45 );
50 assert_eq!(t, "!");
51} 46}
52 47
53#[test] 48#[test]
54fn never_type_in_generic_args() { 49fn never_type_in_generic_args() {
55 let t = type_at( 50 check_types(
56 r#" 51 r#"
57//- /main.rs
58enum Option<T> { None, Some(T) } 52enum Option<T> { None, Some(T) }
59 53
60fn test() { 54fn test() {
61 let a = if true { Option::None } else { Option::Some(return) }; 55 let a = if true { Option::None } else { Option::Some(return) };
62 a<|>; 56 a;
63} 57} //^ Option<!>
64"#, 58"#,
65 ); 59 );
66 assert_eq!(t, "Option<!>");
67} 60}
68 61
69#[test] 62#[test]
70fn never_type_can_be_reinferred1() { 63fn never_type_can_be_reinferred1() {
71 let t = type_at( 64 check_types(
72 r#" 65 r#"
73//- /main.rs
74fn gen<T>() -> T { loop {} } 66fn gen<T>() -> T { loop {} }
75 67
76fn test() { 68fn test() {
77 let a = gen(); 69 let a = gen();
78 if false { loop {} } else { a }; 70 if false { loop {} } else { a };
79 a<|>; 71 a;
72 //^ ()
80 if false { a }; 73 if false { a };
81} 74}
82"#, 75"#,
83 ); 76 );
84 assert_eq!(t, "()");
85} 77}
86 78
87#[test] 79#[test]
88fn never_type_can_be_reinferred2() { 80fn never_type_can_be_reinferred2() {
89 let t = type_at( 81 check_types(
90 r#" 82 r#"
91//- /main.rs
92enum Option<T> { None, Some(T) } 83enum Option<T> { None, Some(T) }
93 84
94fn test() { 85fn test() {
95 let a = if true { Option::None } else { Option::Some(return) }; 86 let a = if true { Option::None } else { Option::Some(return) };
96 a<|>; 87 a;
88 //^ Option<i32>
97 match 42 { 89 match 42 {
98 42 => a, 90 42 => a,
99 _ => Option::Some(42), 91 _ => Option::Some(42),
@@ -101,19 +93,18 @@ fn test() {
101} 93}
102"#, 94"#,
103 ); 95 );
104 assert_eq!(t, "Option<i32>");
105} 96}
106 97
107#[test] 98#[test]
108fn never_type_can_be_reinferred3() { 99fn never_type_can_be_reinferred3() {
109 let t = type_at( 100 check_types(
110 r#" 101 r#"
111//- /main.rs
112enum Option<T> { None, Some(T) } 102enum Option<T> { None, Some(T) }
113 103
114fn test() { 104fn test() {
115 let a = if true { Option::None } else { Option::Some(return) }; 105 let a = if true { Option::None } else { Option::Some(return) };
116 a<|>; 106 a;
107 //^ Option<&str>
117 match 42 { 108 match 42 {
118 42 => a, 109 42 => a,
119 _ => Option::Some("str"), 110 _ => Option::Some("str"),
@@ -121,82 +112,72 @@ fn test() {
121} 112}
122"#, 113"#,
123 ); 114 );
124 assert_eq!(t, "Option<&str>");
125} 115}
126 116
127#[test] 117#[test]
128fn match_no_arm() { 118fn match_no_arm() {
129 let t = type_at( 119 check_types(
130 r#" 120 r#"
131//- /main.rs
132enum Void {} 121enum Void {}
133 122
134fn test(a: Void) { 123fn test(a: Void) {
135 let t = match a {}; 124 let t = match a {};
136 t<|>; 125 t;
137} 126} //^ !
138"#, 127"#,
139 ); 128 );
140 assert_eq!(t, "!");
141} 129}
142 130
143#[test] 131#[test]
144fn match_unknown_arm() { 132fn match_unknown_arm() {
145 let t = type_at( 133 check_types(
146 r#" 134 r#"
147//- /main.rs
148fn test(a: Option) { 135fn test(a: Option) {
149 let t = match 0 { 136 let t = match 0 {
150 _ => unknown, 137 _ => unknown,
151 }; 138 };
152 t<|>; 139 t;
153} 140} //^ {unknown}
154"#, 141"#,
155 ); 142 );
156 assert_eq!(t, "{unknown}");
157} 143}
158 144
159#[test] 145#[test]
160fn if_never() { 146fn if_never() {
161 let t = type_at( 147 check_types(
162 r#" 148 r#"
163//- /main.rs
164fn test() { 149fn test() {
165 let i = if true { 150 let i = if true {
166 loop {} 151 loop {}
167 } else { 152 } else {
168 3.0 153 3.0
169 }; 154 };
170 i<|>; 155 i;
171} 156} //^ f64
172"#, 157"#,
173 ); 158 );
174 assert_eq!(t, "f64");
175} 159}
176 160
177#[test] 161#[test]
178fn if_else_never() { 162fn if_else_never() {
179 let t = type_at( 163 check_types(
180 r#" 164 r#"
181//- /main.rs
182fn test(input: bool) { 165fn test(input: bool) {
183 let i = if input { 166 let i = if input {
184 2.0 167 2.0
185 } else { 168 } else {
186 return 169 return
187 }; 170 };
188 i<|>; 171 i;
189} 172} //^ f64
190"#, 173"#,
191 ); 174 );
192 assert_eq!(t, "f64");
193} 175}
194 176
195#[test] 177#[test]
196fn match_first_arm_never() { 178fn match_first_arm_never() {
197 let t = type_at( 179 check_types(
198 r#" 180 r#"
199//- /main.rs
200fn test(a: i32) { 181fn test(a: i32) {
201 let i = match a { 182 let i = match a {
202 1 => return, 183 1 => return,
@@ -204,18 +185,16 @@ fn test(a: i32) {
204 3 => loop {}, 185 3 => loop {},
205 _ => 3.0, 186 _ => 3.0,
206 }; 187 };
207 i<|>; 188 i;
208} 189} //^ f64
209"#, 190"#,
210 ); 191 );
211 assert_eq!(t, "f64");
212} 192}
213 193
214#[test] 194#[test]
215fn match_second_arm_never() { 195fn match_second_arm_never() {
216 let t = type_at( 196 check_types(
217 r#" 197 r#"
218//- /main.rs
219fn test(a: i32) { 198fn test(a: i32) {
220 let i = match a { 199 let i = match a {
221 1 => 3.0, 200 1 => 3.0,
@@ -223,45 +202,40 @@ fn test(a: i32) {
223 3 => 3.0, 202 3 => 3.0,
224 _ => return, 203 _ => return,
225 }; 204 };
226 i<|>; 205 i;
227} 206} //^ f64
228"#, 207"#,
229 ); 208 );
230 assert_eq!(t, "f64");
231} 209}
232 210
233#[test] 211#[test]
234fn match_all_arms_never() { 212fn match_all_arms_never() {
235 let t = type_at( 213 check_types(
236 r#" 214 r#"
237//- /main.rs
238fn test(a: i32) { 215fn test(a: i32) {
239 let i = match a { 216 let i = match a {
240 2 => return, 217 2 => return,
241 _ => loop {}, 218 _ => loop {},
242 }; 219 };
243 i<|>; 220 i;
244} 221} //^ !
245"#, 222"#,
246 ); 223 );
247 assert_eq!(t, "!");
248} 224}
249 225
250#[test] 226#[test]
251fn match_no_never_arms() { 227fn match_no_never_arms() {
252 let t = type_at( 228 check_types(
253 r#" 229 r#"
254//- /main.rs
255fn test(a: i32) { 230fn test(a: i32) {
256 let i = match a { 231 let i = match a {
257 2 => 2.0, 232 2 => 2.0,
258 _ => 3.0, 233 _ => 3.0,
259 }; 234 };
260 i<|>; 235 i;
261} 236} //^ f64
262"#, 237"#,
263 ); 238 );
264 assert_eq!(t, "f64");
265} 239}
266 240
267#[test] 241#[test]
diff --git a/crates/ra_hir_ty/src/tests/simple.rs b/crates/ra_hir_ty/src/tests/simple.rs
index 5e3f2bd3c..de63f4cce 100644
--- a/crates/ra_hir_ty/src/tests/simple.rs
+++ b/crates/ra_hir_ty/src/tests/simple.rs
@@ -1,19 +1,17 @@
1use super::{infer, type_at, type_at_pos};
2use crate::test_db::TestDB;
3use insta::assert_snapshot; 1use insta::assert_snapshot;
4use ra_db::fixture::WithFixture; 2
3use super::{check_types, infer};
5 4
6#[test] 5#[test]
7fn infer_box() { 6fn infer_box() {
8 let (db, pos) = TestDB::with_position( 7 check_types(
9 r#" 8 r#"
10//- /main.rs crate:main deps:std 9//- /main.rs crate:main deps:std
11
12fn test() { 10fn test() {
13 let x = box 1; 11 let x = box 1;
14 let t = (x, box x, box &1, box [1]); 12 let t = (x, box x, box &1, box [1]);
15 t<|>; 13 t;
16} 14} //^ (Box<i32>, Box<Box<i32>>, Box<&i32>, Box<[i32; _]>)
17 15
18//- /std.rs crate:std 16//- /std.rs crate:std
19#[prelude_import] use prelude::*; 17#[prelude_import] use prelude::*;
@@ -25,29 +23,24 @@ mod boxed {
25 inner: *mut T, 23 inner: *mut T,
26 } 24 }
27} 25}
28
29"#, 26"#,
30 ); 27 );
31 assert_eq!("(Box<i32>, Box<Box<i32>>, Box<&i32>, Box<[i32; _]>)", type_at_pos(&db, pos));
32} 28}
33 29
34#[test] 30#[test]
35fn infer_adt_self() { 31fn infer_adt_self() {
36 let (db, pos) = TestDB::with_position( 32 check_types(
37 r#" 33 r#"
38//- /main.rs
39enum Nat { Succ(Self), Demo(Nat), Zero } 34enum Nat { Succ(Self), Demo(Nat), Zero }
40 35
41fn test() { 36fn test() {
42 let foo: Nat = Nat::Zero; 37 let foo: Nat = Nat::Zero;
43 if let Nat::Succ(x) = foo { 38 if let Nat::Succ(x) = foo {
44 x<|> 39 x
45 } 40 } //^ Nat
46} 41}
47
48"#, 42"#,
49 ); 43 );
50 assert_eq!("Nat", type_at_pos(&db, pos));
51} 44}
52 45
53#[test] 46#[test]
@@ -93,7 +86,7 @@ fn foo() {
93 86
94#[test] 87#[test]
95fn infer_ranges() { 88fn infer_ranges() {
96 let (db, pos) = TestDB::with_position( 89 check_types(
97 r#" 90 r#"
98//- /main.rs crate:main deps:core 91//- /main.rs crate:main deps:core
99fn test() { 92fn test() {
@@ -105,8 +98,8 @@ fn test() {
105 let f = 'a'..='z'; 98 let f = 'a'..='z';
106 99
107 let t = (a, b, c, d, e, f); 100 let t = (a, b, c, d, e, f);
108 t<|>; 101 t;
109} 102} //^ (RangeFull, RangeFrom<i32>, RangeTo<u32>, Range<usize>, RangeToInclusive<i32>, RangeInclusive<char>)
110 103
111//- /core.rs crate:core 104//- /core.rs crate:core
112#[prelude_import] use prelude::*; 105#[prelude_import] use prelude::*;
@@ -135,29 +128,22 @@ pub mod ops {
135} 128}
136"#, 129"#,
137 ); 130 );
138 assert_eq!(
139 "(RangeFull, RangeFrom<i32>, RangeTo<u32>, Range<usize>, RangeToInclusive<i32>, RangeInclusive<char>)",
140 type_at_pos(&db, pos),
141 );
142} 131}
143 132
144#[test] 133#[test]
145fn infer_while_let() { 134fn infer_while_let() {
146 let (db, pos) = TestDB::with_position( 135 check_types(
147 r#" 136 r#"
148//- /main.rs
149enum Option<T> { Some(T), None } 137enum Option<T> { Some(T), None }
150 138
151fn test() { 139fn test() {
152 let foo: Option<f32> = None; 140 let foo: Option<f32> = None;
153 while let Option::Some(x) = foo { 141 while let Option::Some(x) = foo {
154 <|>x 142 x
155 } 143 } //^ f32
156} 144}
157
158"#, 145"#,
159 ); 146 );
160 assert_eq!("f32", type_at_pos(&db, pos));
161} 147}
162 148
163#[test] 149#[test]
@@ -1687,9 +1673,8 @@ fn test() {
1687 1673
1688#[test] 1674#[test]
1689fn shadowing_primitive() { 1675fn shadowing_primitive() {
1690 let t = type_at( 1676 check_types(
1691 r#" 1677 r#"
1692//- /main.rs
1693struct i32; 1678struct i32;
1694struct Foo; 1679struct Foo;
1695 1680
@@ -1697,15 +1682,15 @@ impl i32 { fn foo(&self) -> Foo { Foo } }
1697 1682
1698fn main() { 1683fn main() {
1699 let x: i32 = i32; 1684 let x: i32 = i32;
1700 x.foo()<|>; 1685 x.foo();
1686 //^ Foo
1701}"#, 1687}"#,
1702 ); 1688 );
1703 assert_eq!(t, "Foo");
1704} 1689}
1705 1690
1706#[test] 1691#[test]
1707fn not_shadowing_primitive_by_module() { 1692fn not_shadowing_primitive_by_module() {
1708 let t = type_at( 1693 check_types(
1709 r#" 1694 r#"
1710//- /str.rs 1695//- /str.rs
1711fn foo() {} 1696fn foo() {}
@@ -1715,15 +1700,15 @@ mod str;
1715fn foo() -> &'static str { "" } 1700fn foo() -> &'static str { "" }
1716 1701
1717fn main() { 1702fn main() {
1718 foo()<|>; 1703 foo();
1704 //^ &str
1719}"#, 1705}"#,
1720 ); 1706 );
1721 assert_eq!(t, "&str");
1722} 1707}
1723 1708
1724#[test] 1709#[test]
1725fn not_shadowing_module_by_primitive() { 1710fn not_shadowing_module_by_primitive() {
1726 let t = type_at( 1711 check_types(
1727 r#" 1712 r#"
1728//- /str.rs 1713//- /str.rs
1729fn foo() -> u32 {0} 1714fn foo() -> u32 {0}
@@ -1733,10 +1718,10 @@ mod str;
1733fn foo() -> &'static str { "" } 1718fn foo() -> &'static str { "" }
1734 1719
1735fn main() { 1720fn main() {
1736 str::foo()<|>; 1721 str::foo();
1722 //^ u32
1737}"#, 1723}"#,
1738 ); 1724 );
1739 assert_eq!(t, "u32");
1740} 1725}
1741 1726
1742// This test is actually testing the shadowing behavior within ra_hir_def. It 1727// This test is actually testing the shadowing behavior within ra_hir_def. It
@@ -1744,27 +1729,7 @@ fn main() {
1744// capable of asserting the necessary conditions. 1729// capable of asserting the necessary conditions.
1745#[test] 1730#[test]
1746fn should_be_shadowing_imports() { 1731fn should_be_shadowing_imports() {
1747 let t = type_at( 1732 check_types(
1748 r#"
1749mod a {
1750 pub fn foo() -> i8 {0}
1751 pub struct foo { a: i8 }
1752}
1753mod b { pub fn foo () -> u8 {0} }
1754mod c { pub struct foo { a: u8 } }
1755mod d {
1756 pub use super::a::*;
1757 pub use super::c::foo;
1758 pub use super::b::foo;
1759}
1760
1761fn main() {
1762 d::foo()<|>;
1763}"#,
1764 );
1765 assert_eq!(t, "u8");
1766
1767 let t = type_at(
1768 r#" 1733 r#"
1769mod a { 1734mod a {
1770 pub fn foo() -> i8 {0} 1735 pub fn foo() -> i8 {0}
@@ -1779,10 +1744,12 @@ mod d {
1779} 1744}
1780 1745
1781fn main() { 1746fn main() {
1782 d::foo{a:0<|>}; 1747 d::foo();
1748 //^ u8
1749 d::foo{a:0};
1750 //^ u8
1783}"#, 1751}"#,
1784 ); 1752 );
1785 assert_eq!(t, "u8");
1786} 1753}
1787 1754
1788#[test] 1755#[test]
diff --git a/crates/test_utils/src/lib.rs b/crates/test_utils/src/lib.rs
index eaeeeb97b..e74f3b263 100644
--- a/crates/test_utils/src/lib.rs
+++ b/crates/test_utils/src/lib.rs
@@ -16,6 +16,7 @@ use std::{
16}; 16};
17 17
18use serde_json::Value; 18use serde_json::Value;
19use stdx::lines_with_ends;
19use text_size::{TextRange, TextSize}; 20use text_size::{TextRange, TextSize};
20 21
21pub use difference::Changeset as __Changeset; 22pub use difference::Changeset as __Changeset;
@@ -159,6 +160,39 @@ pub fn add_cursor(text: &str, offset: TextSize) -> String {
159 res 160 res
160} 161}
161 162
163/// Extracts `//^ some text` annotations
164pub fn extract_annotations(text: &str) -> Vec<(TextSize, String)> {
165 let mut res = Vec::new();
166 let mut prev_line_start: Option<TextSize> = None;
167 let mut line_start: TextSize = 0.into();
168 for line in lines_with_ends(text) {
169 if let Some(idx) = line.find("//^") {
170 let offset = prev_line_start.unwrap() + TextSize::of(&line[..idx + "//".len()]);
171 let data = line[idx + "//^".len()..].trim().to_string();
172 res.push((offset, data))
173 }
174 prev_line_start = Some(line_start);
175 line_start += TextSize::of(line);
176 }
177 res
178}
179
180#[test]
181fn test_extract_annotations() {
182 let res = extract_annotations(&trim_indent(
183 r#"
184fn main() {
185 let x = 92;
186 //^ def
187
188 x + 1
189} //^ i32
190 "#,
191 ));
192
193 assert_eq!(res, vec![(20.into(), "def".into()), (47.into(), "i32".into())]);
194}
195
162// Comparison functionality borrowed from cargo: 196// Comparison functionality borrowed from cargo:
163 197
164/// Compare a line with an expected pattern. 198/// Compare a line with an expected pattern.