aboutsummaryrefslogtreecommitdiff
path: root/crates/hir_ty/src
diff options
context:
space:
mode:
Diffstat (limited to 'crates/hir_ty/src')
-rw-r--r--crates/hir_ty/src/tests.rs142
-rw-r--r--crates/hir_ty/src/tests/display_source_code.rs10
2 files changed, 67 insertions, 85 deletions
diff --git a/crates/hir_ty/src/tests.rs b/crates/hir_ty/src/tests.rs
index c4f981b44..0651f34ae 100644
--- a/crates/hir_ty/src/tests.rs
+++ b/crates/hir_ty/src/tests.rs
@@ -11,23 +11,21 @@ mod incremental;
11 11
12use std::{collections::HashMap, 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, SourceDatabaseExt};
15use expect_test::Expect; 15use expect_test::Expect;
16use hir_def::{ 16use hir_def::{
17 body::{Body, BodySourceMap, SyntheticSyntax}, 17 body::{Body, BodySourceMap, SyntheticSyntax},
18 child_by_source::ChildBySource,
19 db::DefDatabase, 18 db::DefDatabase,
19 expr::{ExprId, PatId},
20 item_scope::ItemScope, 20 item_scope::ItemScope,
21 keys,
22 nameres::DefMap, 21 nameres::DefMap,
23 src::HasSource, 22 src::HasSource,
24 AssocItemId, DefWithBodyId, LocalModuleId, Lookup, ModuleDefId, 23 AssocItemId, DefWithBodyId, HasModule, LocalModuleId, Lookup, ModuleDefId,
25}; 24};
26use hir_expand::{db::AstDatabase, InFile}; 25use hir_expand::{db::AstDatabase, InFile};
27use once_cell::race::OnceBool; 26use once_cell::race::OnceBool;
28use stdx::format_to; 27use stdx::format_to;
29use syntax::{ 28use syntax::{
30 algo,
31 ast::{self, AstNode, NameOwner}, 29 ast::{self, AstNode, NameOwner},
32 SyntaxNode, 30 SyntaxNode,
33}; 31};
@@ -59,45 +57,22 @@ fn setup_tracing() -> Option<tracing::subscriber::DefaultGuard> {
59} 57}
60 58
61fn check_types(ra_fixture: &str) { 59fn check_types(ra_fixture: &str) {
62 check_impl(ra_fixture, false, true) 60 check_impl(ra_fixture, false, true, false)
63} 61}
64 62
65fn check_types_source_code(ra_fixture: &str) { 63fn check_types_source_code(ra_fixture: &str) {
66 // TODO 64 check_impl(ra_fixture, false, true, true)
67 check_types_impl(ra_fixture, true)
68}
69
70fn check_types_impl(ra_fixture: &str, display_source: bool) {
71 // TODO
72 let _tracing = setup_tracing();
73 let db = TestDB::with_files(ra_fixture);
74 let mut checked_one = false;
75 for (file_id, annotations) in db.extract_annotations() {
76 for (range, expected) in annotations {
77 let ty = type_at_range(&db, FileRange { file_id, range });
78 let actual = if display_source {
79 let module = db.module_for_file(file_id);
80 ty.display_source_code(&db, module).unwrap()
81 } else {
82 ty.display_test(&db).to_string()
83 };
84 assert_eq!(expected, actual);
85 checked_one = true;
86 }
87 }
88
89 assert!(checked_one, "no `//^` annotations found");
90} 65}
91 66
92fn check_no_mismatches(ra_fixture: &str) { 67fn check_no_mismatches(ra_fixture: &str) {
93 check_impl(ra_fixture, true, false) 68 check_impl(ra_fixture, true, false, false)
94} 69}
95 70
96fn check(ra_fixture: &str) { 71fn check(ra_fixture: &str) {
97 check_impl(ra_fixture, false, false) 72 check_impl(ra_fixture, false, false, false)
98} 73}
99 74
100fn check_impl(ra_fixture: &str, allow_none: bool, only_types: bool) { 75fn check_impl(ra_fixture: &str, allow_none: bool, only_types: bool, display_source: bool) {
101 let _tracing = setup_tracing(); 76 let _tracing = setup_tracing();
102 let (db, files) = TestDB::with_many_files(ra_fixture); 77 let (db, files) = TestDB::with_many_files(ra_fixture);
103 78
@@ -151,50 +126,41 @@ fn check_impl(ra_fixture: &str, allow_none: bool, only_types: bool) {
151 let inference_result = db.infer(def); 126 let inference_result = db.infer(def);
152 127
153 for (pat, ty) in inference_result.type_of_pat.iter() { 128 for (pat, ty) in inference_result.type_of_pat.iter() {
154 let node = match body_source_map.pat_syntax(pat) { 129 let node = match pat_node(&body_source_map, pat, &db) {
155 Ok(sp) => { 130 Some(value) => value,
156 let root = db.parse_or_expand(sp.file_id).unwrap(); 131 None => continue,
157 sp.map(|ptr| {
158 ptr.either(
159 |it| it.to_node(&root).syntax().clone(),
160 |it| it.to_node(&root).syntax().clone(),
161 )
162 })
163 }
164 Err(SyntheticSyntax) => continue,
165 }; 132 };
166 let range = node.as_ref().original_file_range(&db); 133 let range = node.as_ref().original_file_range(&db);
167 if let Some(annotation) = types.remove(&range) { 134 if let Some(expected) = types.remove(&range) {
168 assert_eq!(ty.display_test(&db).to_string(), annotation); 135 let actual = if display_source {
136 ty.display_source_code(&db, def.module(&db)).unwrap()
137 } else {
138 ty.display_test(&db).to_string()
139 };
140 assert_eq!(actual, expected);
169 } 141 }
170 } 142 }
171 143
172 for (expr, ty) in inference_result.type_of_expr.iter() { 144 for (expr, ty) in inference_result.type_of_expr.iter() {
173 let node = match body_source_map.expr_syntax(expr) { 145 let node = match expr_node(&body_source_map, expr, &db) {
174 Ok(sp) => { 146 Some(value) => value,
175 let root = db.parse_or_expand(sp.file_id).unwrap(); 147 None => continue,
176 sp.map(|ptr| ptr.to_node(&root).syntax().clone())
177 }
178 Err(SyntheticSyntax) => continue,
179 }; 148 };
180 let range = node.as_ref().original_file_range(&db); 149 let range = node.as_ref().original_file_range(&db);
181 if let Some(annotation) = types.remove(&range) { 150 if let Some(expected) = types.remove(&range) {
182 assert_eq!(ty.display_test(&db).to_string(), annotation); 151 let actual = if display_source {
152 ty.display_source_code(&db, def.module(&db)).unwrap()
153 } else {
154 ty.display_test(&db).to_string()
155 };
156 assert_eq!(actual, expected);
183 } 157 }
184 } 158 }
185 159
186 for (pat, mismatch) in inference_result.pat_type_mismatches() { 160 for (pat, mismatch) in inference_result.pat_type_mismatches() {
187 let node = match body_source_map.pat_syntax(pat) { 161 let node = match pat_node(&body_source_map, pat, &db) {
188 Ok(sp) => { 162 Some(value) => value,
189 let root = db.parse_or_expand(sp.file_id).unwrap(); 163 None => continue,
190 sp.map(|ptr| {
191 ptr.either(
192 |it| it.to_node(&root).syntax().clone(),
193 |it| it.to_node(&root).syntax().clone(),
194 )
195 })
196 }
197 Err(SyntheticSyntax) => continue,
198 }; 164 };
199 let range = node.as_ref().original_file_range(&db); 165 let range = node.as_ref().original_file_range(&db);
200 let actual = format!( 166 let actual = format!(
@@ -249,21 +215,37 @@ fn check_impl(ra_fixture: &str, allow_none: bool, only_types: bool) {
249 assert!(buf.is_empty(), "{}", buf); 215 assert!(buf.is_empty(), "{}", buf);
250} 216}
251 217
252fn type_at_range(db: &TestDB, pos: FileRange) -> Ty { 218fn expr_node(
253 let file = db.parse(pos.file_id).ok().unwrap(); 219 body_source_map: &BodySourceMap,
254 let expr = algo::find_node_at_range::<ast::Expr>(file.syntax(), pos.range).unwrap(); 220 expr: ExprId,
255 let fn_def = expr.syntax().ancestors().find_map(ast::Fn::cast).unwrap(); 221 db: &TestDB,
256 let module = db.module_for_file(pos.file_id); 222) -> Option<InFile<SyntaxNode>> {
257 let func = *module.child_by_source(db)[keys::FUNCTION] 223 Some(match body_source_map.expr_syntax(expr) {
258 .get(&InFile::new(pos.file_id.into(), fn_def)) 224 Ok(sp) => {
259 .unwrap(); 225 let root = db.parse_or_expand(sp.file_id).unwrap();
260 226 sp.map(|ptr| ptr.to_node(&root).syntax().clone())
261 let (_body, source_map) = db.body_with_source_map(func.into()); 227 }
262 if let Some(expr_id) = source_map.node_expr(InFile::new(pos.file_id.into(), &expr)) { 228 Err(SyntheticSyntax) => return None,
263 let infer = db.infer(func.into()); 229 })
264 return infer[expr_id].clone(); 230}
265 } 231
266 panic!("Can't find expression") 232fn pat_node(
233 body_source_map: &BodySourceMap,
234 pat: PatId,
235 db: &TestDB,
236) -> Option<InFile<SyntaxNode>> {
237 Some(match body_source_map.pat_syntax(pat) {
238 Ok(sp) => {
239 let root = db.parse_or_expand(sp.file_id).unwrap();
240 sp.map(|ptr| {
241 ptr.either(
242 |it| it.to_node(&root).syntax().clone(),
243 |it| it.to_node(&root).syntax().clone(),
244 )
245 })
246 }
247 Err(SyntheticSyntax) => return None,
248 })
267} 249}
268 250
269fn infer(ra_fixture: &str) -> String { 251fn infer(ra_fixture: &str) -> String {
diff --git a/crates/hir_ty/src/tests/display_source_code.rs b/crates/hir_ty/src/tests/display_source_code.rs
index 3d29021aa..058cd02d7 100644
--- a/crates/hir_ty/src/tests/display_source_code.rs
+++ b/crates/hir_ty/src/tests/display_source_code.rs
@@ -10,8 +10,8 @@ mod foo {
10 10
11fn bar() { 11fn bar() {
12 let foo: foo::Foo = foo::Foo; 12 let foo: foo::Foo = foo::Foo;
13 foo 13 foo;
14} //^ foo::Foo 14} //^^^ foo::Foo
15 15
16"#, 16"#,
17 ); 17 );
@@ -25,7 +25,7 @@ struct Foo<T = u8> { t: T }
25fn main() { 25fn main() {
26 let foo = Foo { t: 5u8 }; 26 let foo = Foo { t: 5u8 };
27 foo; 27 foo;
28} //^ Foo 28} //^^^ Foo
29"#, 29"#,
30 ); 30 );
31 31
@@ -35,7 +35,7 @@ struct Foo<K, T = u8> { k: K, t: T }
35fn main() { 35fn main() {
36 let foo = Foo { k: 400, t: 5u8 }; 36 let foo = Foo { k: 400, t: 5u8 };
37 foo; 37 foo;
38} //^ Foo<i32> 38} //^^^ Foo<i32>
39"#, 39"#,
40 ); 40 );
41} 41}
@@ -50,7 +50,7 @@ fn foo() -> *const (impl Unpin + Sized) { loop {} }
50fn main() { 50fn main() {
51 let foo = foo(); 51 let foo = foo();
52 foo; 52 foo;
53} //^ *const (impl Unpin + Sized) 53} //^^^ *const (impl Unpin + Sized)
54"#, 54"#,
55 ); 55 );
56} 56}