aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_hir/src/ty/tests.rs
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_hir/src/ty/tests.rs')
-rw-r--r--crates/ra_hir/src/ty/tests.rs134
1 files changed, 134 insertions, 0 deletions
diff --git a/crates/ra_hir/src/ty/tests.rs b/crates/ra_hir/src/ty/tests.rs
new file mode 100644
index 000000000..b6c02cd80
--- /dev/null
+++ b/crates/ra_hir/src/ty/tests.rs
@@ -0,0 +1,134 @@
1use std::fmt::Write;
2use std::path::{PathBuf, Path};
3use std::fs;
4
5use ra_db::{SyntaxDatabase};
6use ra_syntax::ast::{self, AstNode};
7use test_utils::{project_dir, assert_eq_text, read_text};
8
9use crate::{
10 source_binder,
11 mock::MockDatabase,
12};
13
14// These tests compare the inference results for all expressions in a file
15// against snapshots of the current results. If you change something and these
16// tests fail expectedly, you can update the comparison files by deleting them
17// and running the tests again. Similarly, to add a new test, just write the
18// test here in the same pattern and it will automatically write the snapshot.
19
20#[test]
21fn infer_basics() {
22 check_inference(
23 r#"
24fn test(a: u32, b: isize, c: !, d: &str) {
25 a;
26 b;
27 c;
28 d;
29 1usize;
30 1isize;
31 "test";
32 1.0f32;
33}"#,
34 "0001_basics.txt",
35 );
36}
37
38#[test]
39fn infer_let() {
40 check_inference(
41 r#"
42fn test() {
43 let a = 1isize;
44 let b: usize = 1;
45 let c = b;
46}
47}"#,
48 "0002_let.txt",
49 );
50}
51
52#[test]
53fn infer_paths() {
54 check_inference(
55 r#"
56fn a() -> u32 { 1 }
57
58mod b {
59 fn c() -> u32 { 1 }
60}
61
62fn test() {
63 a();
64 b::c();
65}
66}"#,
67 "0003_paths.txt",
68 );
69}
70
71fn infer(content: &str) -> String {
72 let (db, _, file_id) = MockDatabase::with_single_file(content);
73 let source_file = db.source_file(file_id);
74 let mut acc = String::new();
75 for fn_def in source_file
76 .syntax()
77 .descendants()
78 .filter_map(ast::FnDef::cast)
79 {
80 let func = source_binder::function_from_source(&db, file_id, fn_def)
81 .unwrap()
82 .unwrap();
83 let inference_result = func.infer(&db).unwrap();
84 for (syntax_ptr, ty) in &inference_result.type_of {
85 let node = syntax_ptr.resolve(&source_file);
86 write!(
87 acc,
88 "{} '{}': {}\n",
89 syntax_ptr.range(),
90 ellipsize(node.text().to_string().replace("\n", " "), 15),
91 ty
92 )
93 .unwrap();
94 }
95 }
96 acc
97}
98
99fn check_inference(content: &str, data_file: impl AsRef<Path>) {
100 let data_file_path = test_data_dir().join(data_file);
101 let result = infer(content);
102
103 if !data_file_path.exists() {
104 println!("File with expected result doesn't exist, creating...\n");
105 println!("{}\n{}", content, result);
106 fs::write(&data_file_path, &result).unwrap();
107 panic!("File {:?} with expected result was created", data_file_path);
108 }
109
110 let expected = read_text(&data_file_path);
111 assert_eq_text!(&expected, &result);
112}
113
114fn ellipsize(mut text: String, max_len: usize) -> String {
115 if text.len() <= max_len {
116 return text;
117 }
118 let ellipsis = "...";
119 let e_len = ellipsis.len();
120 let mut prefix_len = (max_len - e_len) / 2;
121 while !text.is_char_boundary(prefix_len) {
122 prefix_len += 1;
123 }
124 let mut suffix_len = max_len - e_len - prefix_len;
125 while !text.is_char_boundary(text.len() - suffix_len) {
126 suffix_len += 1;
127 }
128 text.replace_range(prefix_len..text.len() - suffix_len, ellipsis);
129 text
130}
131
132fn test_data_dir() -> PathBuf {
133 project_dir().join("crates/ra_hir/src/ty/tests/data")
134}