aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--crates/ra_hir/src/expr/validation.rs2
-rw-r--r--crates/ra_ide_api/src/diagnostics.rs62
-rw-r--r--crates/ra_ide_api/src/mock_analysis.rs17
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}};
274fn 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.
138pub 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 <|>.
128pub fn single_file_with_position(code: &str) -> (Analysis, FilePosition) { 145pub fn single_file_with_position(code: &str) -> (Analysis, FilePosition) {
129 let mut mock = MockAnalysis::new(); 146 let mut mock = MockAnalysis::new();