diff options
-rw-r--r-- | crates/ra_hir/src/expr/validation.rs | 2 | ||||
-rw-r--r-- | crates/ra_ide_api/src/diagnostics.rs | 62 | ||||
-rw-r--r-- | crates/ra_ide_api/src/mock_analysis.rs | 17 |
3 files changed, 65 insertions, 16 deletions
diff --git a/crates/ra_hir/src/expr/validation.rs b/crates/ra_hir/src/expr/validation.rs index 0e7b08c54..ca7db61bc 100644 --- a/crates/ra_hir/src/expr/validation.rs +++ b/crates/ra_hir/src/expr/validation.rs | |||
@@ -106,12 +106,10 @@ impl<'a, 'b> ExprValidator<'a, 'b> { | |||
106 | Some(m) => m, | 106 | Some(m) => m, |
107 | None => return, | 107 | None => return, |
108 | }; | 108 | }; |
109 | |||
110 | let ret = match &mismatch.expected { | 109 | let ret = match &mismatch.expected { |
111 | Ty::Apply(t) => t, | 110 | Ty::Apply(t) => t, |
112 | _ => return, | 111 | _ => return, |
113 | }; | 112 | }; |
114 | |||
115 | let ret_enum = match ret.ctor { | 113 | let ret_enum = match ret.ctor { |
116 | TypeCtor::Adt(AdtDef::Enum(e)) => e, | 114 | TypeCtor::Adt(AdtDef::Enum(e)) => e, |
117 | _ => return, | 115 | _ => return, |
diff --git a/crates/ra_ide_api/src/diagnostics.rs b/crates/ra_ide_api/src/diagnostics.rs index be5197767..84d2b7fb1 100644 --- a/crates/ra_ide_api/src/diagnostics.rs +++ b/crates/ra_ide_api/src/diagnostics.rs | |||
@@ -187,7 +187,7 @@ mod tests { | |||
187 | use ra_syntax::SourceFile; | 187 | use ra_syntax::SourceFile; |
188 | use test_utils::assert_eq_text; | 188 | use test_utils::assert_eq_text; |
189 | 189 | ||
190 | use crate::mock_analysis::single_file; | 190 | use crate::mock_analysis::{fixture_with_target_file, single_file}; |
191 | 191 | ||
192 | use super::*; | 192 | use super::*; |
193 | 193 | ||
@@ -216,6 +216,15 @@ mod tests { | |||
216 | assert_eq_text!(after, &actual); | 216 | assert_eq_text!(after, &actual); |
217 | } | 217 | } |
218 | 218 | ||
219 | fn check_apply_diagnostic_fix_for_target_file(target_file: &str, fixture: &str, after: &str) { | ||
220 | let (analysis, file_id, target_file_contents) = fixture_with_target_file(fixture, target_file); | ||
221 | let diagnostic = analysis.diagnostics(file_id).unwrap().pop().unwrap(); | ||
222 | let mut fix = diagnostic.fix.unwrap(); | ||
223 | let edit = fix.source_file_edits.pop().unwrap().edit; | ||
224 | let actual = edit.apply(&target_file_contents); | ||
225 | assert_eq_text!(after, &actual); | ||
226 | } | ||
227 | |||
219 | fn check_apply_diagnostic_fix(before: &str, after: &str) { | 228 | fn check_apply_diagnostic_fix(before: &str, after: &str) { |
220 | let (analysis, file_id) = single_file(before); | 229 | let (analysis, file_id) = single_file(before); |
221 | let diagnostic = analysis.diagnostics(file_id).unwrap().pop().unwrap(); | 230 | let diagnostic = analysis.diagnostics(file_id).unwrap().pop().unwrap(); |
@@ -225,6 +234,12 @@ mod tests { | |||
225 | assert_eq_text!(after, &actual); | 234 | assert_eq_text!(after, &actual); |
226 | } | 235 | } |
227 | 236 | ||
237 | fn check_no_diagnostic_for_target_file(target_file: &str, fixture: &str) { | ||
238 | let (analysis, file_id, _) = fixture_with_target_file(fixture, target_file); | ||
239 | let diagnostics = analysis.diagnostics(file_id).unwrap(); | ||
240 | assert_eq!(diagnostics.len(), 0); | ||
241 | } | ||
242 | |||
228 | fn check_no_diagnostic(content: &str) { | 243 | fn check_no_diagnostic(content: &str) { |
229 | let (analysis, file_id) = single_file(content); | 244 | let (analysis, file_id) = single_file(content); |
230 | let diagnostics = analysis.diagnostics(file_id).unwrap(); | 245 | let diagnostics = analysis.diagnostics(file_id).unwrap(); |
@@ -234,8 +249,8 @@ mod tests { | |||
234 | #[test] | 249 | #[test] |
235 | fn test_wrap_return_type() { | 250 | fn test_wrap_return_type() { |
236 | let before = r#" | 251 | let before = r#" |
237 | enum Result<T, E> { Ok(T), Err(E) } | 252 | //- /main.rs |
238 | struct String { } | 253 | use std::{string::String, result::Result::{self, Ok, Err}}; |
239 | 254 | ||
240 | fn div(x: i32, y: i32) -> Result<i32, String> { | 255 | fn div(x: i32, y: i32) -> Result<i32, String> { |
241 | if y == 0 { | 256 | if y == 0 { |
@@ -243,29 +258,48 @@ mod tests { | |||
243 | } | 258 | } |
244 | x / y | 259 | x / y |
245 | } | 260 | } |
246 | "#; | ||
247 | let after = r#" | ||
248 | enum Result<T, E> { Ok(T), Err(E) } | ||
249 | struct String { } | ||
250 | 261 | ||
251 | fn div(x: i32, y: i32) -> Result<i32, String> { | 262 | //- /std/lib.rs |
252 | if y == 0 { | 263 | pub mod string { |
253 | return Err("div by zero".into()); | 264 | pub struct String { } |
254 | } | 265 | } |
255 | Ok(x / y) | 266 | pub mod result { |
267 | pub enum Result<T, E> { Ok(T), Err(E) } | ||
256 | } | 268 | } |
257 | "#; | 269 | "#; |
258 | check_apply_diagnostic_fix(before, after); | 270 | // The formatting here is a bit odd due to how the parse_fixture function works in test_utils - |
271 | // it strips empty lines and leading whitespace. The important part of this test is that the final | ||
272 | // `x / y` expr is now wrapped in `Ok(..)` | ||
273 | let after = r#"use std::{string::String, result::Result::{self, Ok, Err}}; | ||
274 | fn div(x: i32, y: i32) -> Result<i32, String> { | ||
275 | if y == 0 { | ||
276 | return Err("div by zero".into()); | ||
277 | } | ||
278 | Ok(x / y) | ||
279 | } | ||
280 | "#; | ||
281 | check_apply_diagnostic_fix_for_target_file("/main.rs", before, after); | ||
259 | } | 282 | } |
260 | 283 | ||
261 | #[test] | 284 | #[test] |
262 | fn test_wrap_return_type_not_applicable() { | 285 | fn test_wrap_return_type_not_applicable() { |
263 | let content = r#" | 286 | let content = r#" |
287 | //- /main.rs | ||
288 | use std::{string::String, result::Result::{self, Ok, Err}}; | ||
289 | |||
264 | fn foo() -> Result<String, i32> { | 290 | fn foo() -> Result<String, i32> { |
265 | 0 | 291 | 0 |
266 | } | 292 | } |
293 | |||
294 | //- /std/lib.rs | ||
295 | pub mod string { | ||
296 | pub struct String { } | ||
297 | } | ||
298 | pub mod result { | ||
299 | pub enum Result<T, E> { Ok(T), Err(E) } | ||
300 | } | ||
267 | "#; | 301 | "#; |
268 | check_no_diagnostic(content); | 302 | check_no_diagnostic_for_target_file("/main.rs", content); |
269 | } | 303 | } |
270 | 304 | ||
271 | #[test] | 305 | #[test] |
diff --git a/crates/ra_ide_api/src/mock_analysis.rs b/crates/ra_ide_api/src/mock_analysis.rs index 132f6f875..0eaf5d15a 100644 --- a/crates/ra_ide_api/src/mock_analysis.rs +++ b/crates/ra_ide_api/src/mock_analysis.rs | |||
@@ -80,6 +80,15 @@ impl MockAnalysis { | |||
80 | .expect("no file in this mock"); | 80 | .expect("no file in this mock"); |
81 | FileId(idx as u32 + 1) | 81 | FileId(idx as u32 + 1) |
82 | } | 82 | } |
83 | pub fn id_and_contents_of(&self, path: &str) -> (FileId, String) { | ||
84 | let (idx, contents) = self | ||
85 | .files | ||
86 | .iter() | ||
87 | .enumerate() | ||
88 | .find(|(_, (p, _text))| path == p) | ||
89 | .expect("no file in this mock"); | ||
90 | (FileId(idx as u32 + 1), contents.1.to_string()) | ||
91 | } | ||
83 | pub fn analysis_host(self) -> AnalysisHost { | 92 | pub fn analysis_host(self) -> AnalysisHost { |
84 | let mut host = AnalysisHost::default(); | 93 | let mut host = AnalysisHost::default(); |
85 | let source_root = SourceRootId(0); | 94 | let source_root = SourceRootId(0); |
@@ -124,6 +133,14 @@ pub fn single_file(code: &str) -> (Analysis, FileId) { | |||
124 | (mock.analysis(), file_id) | 133 | (mock.analysis(), file_id) |
125 | } | 134 | } |
126 | 135 | ||
136 | /// Creates analysis from a fixture with multiple files | ||
137 | /// and returns the file id and contents of the target file. | ||
138 | pub fn fixture_with_target_file(fixture: &str, target_file: &str) -> (Analysis, FileId, String) { | ||
139 | let mock = MockAnalysis::with_files(fixture); | ||
140 | let (target_file_id, target_file_contents) = mock.id_and_contents_of(target_file); | ||
141 | (mock.analysis(), target_file_id, target_file_contents) | ||
142 | } | ||
143 | |||
127 | /// Creates analysis for a single file, returns position marked with <|>. | 144 | /// Creates analysis for a single file, returns position marked with <|>. |
128 | pub fn single_file_with_position(code: &str) -> (Analysis, FilePosition) { | 145 | pub fn single_file_with_position(code: &str) -> (Analysis, FilePosition) { |
129 | let mut mock = MockAnalysis::new(); | 146 | let mut mock = MockAnalysis::new(); |