aboutsummaryrefslogtreecommitdiff
path: root/crates/hir_ty/src/tests.rs
diff options
context:
space:
mode:
Diffstat (limited to 'crates/hir_ty/src/tests.rs')
-rw-r--r--crates/hir_ty/src/tests.rs98
1 files changed, 97 insertions, 1 deletions
diff --git a/crates/hir_ty/src/tests.rs b/crates/hir_ty/src/tests.rs
index 9d726b024..b873585c4 100644
--- a/crates/hir_ty/src/tests.rs
+++ b/crates/hir_ty/src/tests.rs
@@ -9,7 +9,7 @@ mod macros;
9mod display_source_code; 9mod display_source_code;
10mod incremental; 10mod incremental;
11 11
12use std::{env, sync::Arc}; 12use std::{collections::HashMap, env, sync::Arc};
13 13
14use base_db::{fixture::WithFixture, FileRange, SourceDatabase, SourceDatabaseExt}; 14use base_db::{fixture::WithFixture, FileRange, SourceDatabase, SourceDatabaseExt};
15use expect_test::Expect; 15use expect_test::Expect;
@@ -83,9 +83,105 @@ fn check_types_impl(ra_fixture: &str, display_source: bool) {
83 checked_one = true; 83 checked_one = true;
84 } 84 }
85 } 85 }
86
86 assert!(checked_one, "no `//^` annotations found"); 87 assert!(checked_one, "no `//^` annotations found");
87} 88}
88 89
90fn check_no_mismatches(ra_fixture: &str) {
91 check_mismatches_impl(ra_fixture, true)
92}
93
94#[allow(unused)]
95fn check_mismatches(ra_fixture: &str) {
96 check_mismatches_impl(ra_fixture, false)
97}
98
99fn check_mismatches_impl(ra_fixture: &str, allow_none: bool) {
100 let _tracing = setup_tracing();
101 let (db, file_id) = TestDB::with_single_file(ra_fixture);
102 let module = db.module_for_file(file_id);
103 let def_map = module.def_map(&db);
104
105 let mut defs: Vec<DefWithBodyId> = Vec::new();
106 visit_module(&db, &def_map, module.local_id, &mut |it| defs.push(it));
107 defs.sort_by_key(|def| match def {
108 DefWithBodyId::FunctionId(it) => {
109 let loc = it.lookup(&db);
110 loc.source(&db).value.syntax().text_range().start()
111 }
112 DefWithBodyId::ConstId(it) => {
113 let loc = it.lookup(&db);
114 loc.source(&db).value.syntax().text_range().start()
115 }
116 DefWithBodyId::StaticId(it) => {
117 let loc = it.lookup(&db);
118 loc.source(&db).value.syntax().text_range().start()
119 }
120 });
121 let mut mismatches = HashMap::new();
122 let mut push_mismatch = |src_ptr: InFile<SyntaxNode>, mismatch: TypeMismatch| {
123 let range = src_ptr.value.text_range();
124 if src_ptr.file_id.call_node(&db).is_some() {
125 panic!("type mismatch in macro expansion");
126 }
127 let file_range = FileRange { file_id: src_ptr.file_id.original_file(&db), range };
128 let actual = format!(
129 "expected {}, got {}",
130 mismatch.expected.display_test(&db),
131 mismatch.actual.display_test(&db)
132 );
133 mismatches.insert(file_range, actual);
134 };
135 for def in defs {
136 let (_body, body_source_map) = db.body_with_source_map(def);
137 let inference_result = db.infer(def);
138 for (pat, mismatch) in inference_result.pat_type_mismatches() {
139 let syntax_ptr = match body_source_map.pat_syntax(pat) {
140 Ok(sp) => {
141 let root = db.parse_or_expand(sp.file_id).unwrap();
142 sp.map(|ptr| {
143 ptr.either(
144 |it| it.to_node(&root).syntax().clone(),
145 |it| it.to_node(&root).syntax().clone(),
146 )
147 })
148 }
149 Err(SyntheticSyntax) => continue,
150 };
151 push_mismatch(syntax_ptr, mismatch.clone());
152 }
153 for (expr, mismatch) in inference_result.expr_type_mismatches() {
154 let node = match body_source_map.expr_syntax(expr) {
155 Ok(sp) => {
156 let root = db.parse_or_expand(sp.file_id).unwrap();
157 sp.map(|ptr| ptr.to_node(&root).syntax().clone())
158 }
159 Err(SyntheticSyntax) => continue,
160 };
161 push_mismatch(node, mismatch.clone());
162 }
163 }
164 let mut checked_one = false;
165 for (file_id, annotations) in db.extract_annotations() {
166 for (range, expected) in annotations {
167 let file_range = FileRange { file_id, range };
168 if let Some(mismatch) = mismatches.remove(&file_range) {
169 assert_eq!(mismatch, expected);
170 } else {
171 assert!(false, "Expected mismatch not encountered: {}\n", expected);
172 }
173 checked_one = true;
174 }
175 }
176 let mut buf = String::new();
177 for (range, mismatch) in mismatches {
178 format_to!(buf, "{:?}: {}\n", range.range, mismatch,);
179 }
180 assert!(buf.is_empty(), "Unexpected type mismatches:\n{}", buf);
181
182 assert!(checked_one || allow_none, "no `//^` annotations found");
183}
184
89fn type_at_range(db: &TestDB, pos: FileRange) -> Ty { 185fn type_at_range(db: &TestDB, pos: FileRange) -> Ty {
90 let file = db.parse(pos.file_id).ok().unwrap(); 186 let file = db.parse(pos.file_id).ok().unwrap();
91 let expr = algo::find_node_at_range::<ast::Expr>(file.syntax(), pos.range).unwrap(); 187 let expr = algo::find_node_at_range::<ast::Expr>(file.syntax(), pos.range).unwrap();