diff options
Diffstat (limited to 'crates')
-rw-r--r-- | crates/hir_ty/src/tests.rs | 142 | ||||
-rw-r--r-- | crates/hir_ty/src/tests/display_source_code.rs | 10 |
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 | ||
12 | use std::{collections::HashMap, env, sync::Arc}; | 12 | use std::{collections::HashMap, env, sync::Arc}; |
13 | 13 | ||
14 | use base_db::{fixture::WithFixture, FileRange, SourceDatabase, SourceDatabaseExt}; | 14 | use base_db::{fixture::WithFixture, FileRange, SourceDatabaseExt}; |
15 | use expect_test::Expect; | 15 | use expect_test::Expect; |
16 | use hir_def::{ | 16 | use 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 | }; |
26 | use hir_expand::{db::AstDatabase, InFile}; | 25 | use hir_expand::{db::AstDatabase, InFile}; |
27 | use once_cell::race::OnceBool; | 26 | use once_cell::race::OnceBool; |
28 | use stdx::format_to; | 27 | use stdx::format_to; |
29 | use syntax::{ | 28 | use 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 | ||
61 | fn check_types(ra_fixture: &str) { | 59 | fn check_types(ra_fixture: &str) { |
62 | check_impl(ra_fixture, false, true) | 60 | check_impl(ra_fixture, false, true, false) |
63 | } | 61 | } |
64 | 62 | ||
65 | fn check_types_source_code(ra_fixture: &str) { | 63 | fn 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 | |||
70 | fn 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 | ||
92 | fn check_no_mismatches(ra_fixture: &str) { | 67 | fn 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 | ||
96 | fn check(ra_fixture: &str) { | 71 | fn check(ra_fixture: &str) { |
97 | check_impl(ra_fixture, false, false) | 72 | check_impl(ra_fixture, false, false, false) |
98 | } | 73 | } |
99 | 74 | ||
100 | fn check_impl(ra_fixture: &str, allow_none: bool, only_types: bool) { | 75 | fn 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 | ||
252 | fn type_at_range(db: &TestDB, pos: FileRange) -> Ty { | 218 | fn 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") | 232 | fn 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 | ||
269 | fn infer(ra_fixture: &str) -> String { | 251 | fn 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 | ||
11 | fn bar() { | 11 | fn 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 } | |||
25 | fn main() { | 25 | fn 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 } | |||
35 | fn main() { | 35 | fn 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 {} } | |||
50 | fn main() { | 50 | fn 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 | } |