aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_ide/src/diagnostics.rs
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_ide/src/diagnostics.rs')
-rw-r--r--crates/ra_ide/src/diagnostics.rs91
1 files changed, 44 insertions, 47 deletions
diff --git a/crates/ra_ide/src/diagnostics.rs b/crates/ra_ide/src/diagnostics.rs
index bf14a467f..fd9abb55b 100644
--- a/crates/ra_ide/src/diagnostics.rs
+++ b/crates/ra_ide/src/diagnostics.rs
@@ -11,7 +11,7 @@ use hir::{
11 Semantics, 11 Semantics,
12}; 12};
13use itertools::Itertools; 13use itertools::Itertools;
14use ra_db::{RelativePath, SourceDatabase, SourceDatabaseExt}; 14use ra_db::SourceDatabase;
15use ra_ide_db::RootDatabase; 15use ra_ide_db::RootDatabase;
16use ra_prof::profile; 16use ra_prof::profile;
17use ra_syntax::{ 17use ra_syntax::{
@@ -57,14 +57,10 @@ pub(crate) fn diagnostics(db: &RootDatabase, file_id: FileId) -> Vec<Diagnostic>
57 }) 57 })
58 .on::<hir::diagnostics::UnresolvedModule, _>(|d| { 58 .on::<hir::diagnostics::UnresolvedModule, _>(|d| {
59 let original_file = d.source().file_id.original_file(db); 59 let original_file = d.source().file_id.original_file(db);
60 let source_root = db.file_source_root(original_file); 60 let fix = Fix::new(
61 let path = db 61 "Create module",
62 .file_relative_path(original_file) 62 FileSystemEdit::CreateFile { anchor: original_file, dst: d.candidate.clone() }.into(),
63 .parent() 63 );
64 .unwrap_or_else(|| RelativePath::new(""))
65 .join(&d.candidate);
66 let fix =
67 Fix::new("Create module", FileSystemEdit::CreateFile { source_root, path }.into());
68 res.borrow_mut().push(Diagnostic { 64 res.borrow_mut().push(Diagnostic {
69 range: sema.diagnostics_range(d).range, 65 range: sema.diagnostics_range(d).range,
70 message: d.message(), 66 message: d.message(),
@@ -187,7 +183,8 @@ fn check_struct_shorthand_initialization(
187 if let (Some(name_ref), Some(expr)) = (record_field.name_ref(), record_field.expr()) { 183 if let (Some(name_ref), Some(expr)) = (record_field.name_ref(), record_field.expr()) {
188 let field_name = name_ref.syntax().text().to_string(); 184 let field_name = name_ref.syntax().text().to_string();
189 let field_expr = expr.syntax().text().to_string(); 185 let field_expr = expr.syntax().text().to_string();
190 if field_name == field_expr { 186 let field_name_is_tup_index = name_ref.as_tuple_field().is_some();
187 if field_name == field_expr && !field_name_is_tup_index {
191 let mut edit_builder = TextEditBuilder::default(); 188 let mut edit_builder = TextEditBuilder::default();
192 edit_builder.delete(record_field.syntax().text_range()); 189 edit_builder.delete(record_field.syntax().text_range());
193 edit_builder.insert(record_field.syntax().text_range().start(), field_name); 190 edit_builder.insert(record_field.syntax().text_range().start(), field_name);
@@ -321,29 +318,26 @@ mod tests {
321 fn test_wrap_return_type() { 318 fn test_wrap_return_type() {
322 let before = r#" 319 let before = r#"
323 //- /main.rs 320 //- /main.rs
324 use std::{string::String, result::Result::{self, Ok, Err}}; 321 use core::result::Result::{self, Ok, Err};
325 322
326 fn div(x: i32, y: i32) -> Result<i32, String> { 323 fn div(x: i32, y: i32) -> Result<i32, ()> {
327 if y == 0 { 324 if y == 0 {
328 return Err("div by zero".into()); 325 return Err(());
329 } 326 }
330 x / y<|> 327 x / y<|>
331 } 328 }
332 329
333 //- /std/lib.rs 330 //- /core/lib.rs
334 pub mod string {
335 pub struct String { }
336 }
337 pub mod result { 331 pub mod result {
338 pub enum Result<T, E> { Ok(T), Err(E) } 332 pub enum Result<T, E> { Ok(T), Err(E) }
339 } 333 }
340 "#; 334 "#;
341 let after = r#" 335 let after = r#"
342 use std::{string::String, result::Result::{self, Ok, Err}}; 336 use core::result::Result::{self, Ok, Err};
343 337
344 fn div(x: i32, y: i32) -> Result<i32, String> { 338 fn div(x: i32, y: i32) -> Result<i32, ()> {
345 if y == 0 { 339 if y == 0 {
346 return Err("div by zero".into()); 340 return Err(());
347 } 341 }
348 Ok(x / y) 342 Ok(x / y)
349 } 343 }
@@ -355,7 +349,7 @@ mod tests {
355 fn test_wrap_return_type_handles_generic_functions() { 349 fn test_wrap_return_type_handles_generic_functions() {
356 let before = r#" 350 let before = r#"
357 //- /main.rs 351 //- /main.rs
358 use std::result::Result::{self, Ok, Err}; 352 use core::result::Result::{self, Ok, Err};
359 353
360 fn div<T>(x: T) -> Result<T, i32> { 354 fn div<T>(x: T) -> Result<T, i32> {
361 if x == 0 { 355 if x == 0 {
@@ -364,13 +358,13 @@ mod tests {
364 <|>x 358 <|>x
365 } 359 }
366 360
367 //- /std/lib.rs 361 //- /core/lib.rs
368 pub mod result { 362 pub mod result {
369 pub enum Result<T, E> { Ok(T), Err(E) } 363 pub enum Result<T, E> { Ok(T), Err(E) }
370 } 364 }
371 "#; 365 "#;
372 let after = r#" 366 let after = r#"
373 use std::result::Result::{self, Ok, Err}; 367 use core::result::Result::{self, Ok, Err};
374 368
375 fn div<T>(x: T) -> Result<T, i32> { 369 fn div<T>(x: T) -> Result<T, i32> {
376 if x == 0 { 370 if x == 0 {
@@ -386,32 +380,29 @@ mod tests {
386 fn test_wrap_return_type_handles_type_aliases() { 380 fn test_wrap_return_type_handles_type_aliases() {
387 let before = r#" 381 let before = r#"
388 //- /main.rs 382 //- /main.rs
389 use std::{string::String, result::Result::{self, Ok, Err}}; 383 use core::result::Result::{self, Ok, Err};
390 384
391 type MyResult<T> = Result<T, String>; 385 type MyResult<T> = Result<T, ()>;
392 386
393 fn div(x: i32, y: i32) -> MyResult<i32> { 387 fn div(x: i32, y: i32) -> MyResult<i32> {
394 if y == 0 { 388 if y == 0 {
395 return Err("div by zero".into()); 389 return Err(());
396 } 390 }
397 x <|>/ y 391 x <|>/ y
398 } 392 }
399 393
400 //- /std/lib.rs 394 //- /core/lib.rs
401 pub mod string {
402 pub struct String { }
403 }
404 pub mod result { 395 pub mod result {
405 pub enum Result<T, E> { Ok(T), Err(E) } 396 pub enum Result<T, E> { Ok(T), Err(E) }
406 } 397 }
407 "#; 398 "#;
408 let after = r#" 399 let after = r#"
409 use std::{string::String, result::Result::{self, Ok, Err}}; 400 use core::result::Result::{self, Ok, Err};
410 401
411 type MyResult<T> = Result<T, String>; 402 type MyResult<T> = Result<T, ()>;
412 fn div(x: i32, y: i32) -> MyResult<i32> { 403 fn div(x: i32, y: i32) -> MyResult<i32> {
413 if y == 0 { 404 if y == 0 {
414 return Err("div by zero".into()); 405 return Err(());
415 } 406 }
416 Ok(x / y) 407 Ok(x / y)
417 } 408 }
@@ -423,16 +414,13 @@ mod tests {
423 fn test_wrap_return_type_not_applicable_when_expr_type_does_not_match_ok_type() { 414 fn test_wrap_return_type_not_applicable_when_expr_type_does_not_match_ok_type() {
424 let content = r#" 415 let content = r#"
425 //- /main.rs 416 //- /main.rs
426 use std::{string::String, result::Result::{self, Ok, Err}}; 417 use core::result::Result::{self, Ok, Err};
427 418
428 fn foo() -> Result<String, i32> { 419 fn foo() -> Result<(), i32> {
429 0<|> 420 0<|>
430 } 421 }
431 422
432 //- /std/lib.rs 423 //- /core/lib.rs
433 pub mod string {
434 pub struct String { }
435 }
436 pub mod result { 424 pub mod result {
437 pub enum Result<T, E> { Ok(T), Err(E) } 425 pub enum Result<T, E> { Ok(T), Err(E) }
438 } 426 }
@@ -444,7 +432,7 @@ mod tests {
444 fn test_wrap_return_type_not_applicable_when_return_type_is_not_result() { 432 fn test_wrap_return_type_not_applicable_when_return_type_is_not_result() {
445 let content = r#" 433 let content = r#"
446 //- /main.rs 434 //- /main.rs
447 use std::{string::String, result::Result::{self, Ok, Err}}; 435 use core::result::Result::{self, Ok, Err};
448 436
449 enum SomeOtherEnum { 437 enum SomeOtherEnum {
450 Ok(i32), 438 Ok(i32),
@@ -455,10 +443,7 @@ mod tests {
455 0<|> 443 0<|>
456 } 444 }
457 445
458 //- /std/lib.rs 446 //- /core/lib.rs
459 pub mod string {
460 pub struct String { }
461 }
462 pub mod result { 447 pub mod result {
463 pub enum Result<T, E> { Ok(T), Err(E) } 448 pub enum Result<T, E> { Ok(T), Err(E) }
464 } 449 }
@@ -623,10 +608,10 @@ mod tests {
623 source_file_edits: [], 608 source_file_edits: [],
624 file_system_edits: [ 609 file_system_edits: [
625 CreateFile { 610 CreateFile {
626 source_root: SourceRootId( 611 anchor: FileId(
627 0, 612 1,
628 ), 613 ),
629 path: "foo.rs", 614 dst: "foo.rs",
630 }, 615 },
631 ], 616 ],
632 is_snippet: false, 617 is_snippet: false,
@@ -731,6 +716,18 @@ mod tests {
731 "#, 716 "#,
732 check_struct_shorthand_initialization, 717 check_struct_shorthand_initialization,
733 ); 718 );
719 check_not_applicable(
720 r#"
721 struct A(usize);
722
723 fn main() {
724 A {
725 0: 0
726 }
727 }
728 "#,
729 check_struct_shorthand_initialization,
730 );
734 731
735 check_apply( 732 check_apply(
736 r#" 733 r#"