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.rs75
1 files changed, 38 insertions, 37 deletions
diff --git a/crates/ra_ide/src/diagnostics.rs b/crates/ra_ide/src/diagnostics.rs
index 15dc50cf1..e1bfd72f9 100644
--- a/crates/ra_ide/src/diagnostics.rs
+++ b/crates/ra_ide/src/diagnostics.rs
@@ -21,7 +21,7 @@ use ra_syntax::{
21}; 21};
22use ra_text_edit::{TextEdit, TextEditBuilder}; 22use ra_text_edit::{TextEdit, TextEditBuilder};
23 23
24use crate::{Diagnostic, FileId, FileSystemEdit, Fix, SourceChange, SourceFileEdit}; 24use crate::{Diagnostic, FileId, FileSystemEdit, Fix, SourceFileEdit};
25 25
26#[derive(Debug, Copy, Clone)] 26#[derive(Debug, Copy, Clone)]
27pub enum Severity { 27pub enum Severity {
@@ -115,7 +115,7 @@ pub(crate) fn diagnostics(db: &RootDatabase, file_id: FileId) -> Vec<Diagnostic>
115 let node = d.ast(db); 115 let node = d.ast(db);
116 let replacement = format!("Ok({})", node.syntax()); 116 let replacement = format!("Ok({})", node.syntax());
117 let edit = TextEdit::replace(node.syntax().text_range(), replacement); 117 let edit = TextEdit::replace(node.syntax().text_range(), replacement);
118 let source_change = SourceChange::source_file_edit_from(file_id, edit); 118 let source_change = SourceFileEdit { file_id, edit }.into();
119 let fix = Fix::new("Wrap with ok", source_change); 119 let fix = Fix::new("Wrap with ok", source_change);
120 res.borrow_mut().push(Diagnostic { 120 res.borrow_mut().push(Diagnostic {
121 range: sema.diagnostics_range(d).range, 121 range: sema.diagnostics_range(d).range,
@@ -187,7 +187,8 @@ fn check_struct_shorthand_initialization(
187 if let (Some(name_ref), Some(expr)) = (record_field.name_ref(), record_field.expr()) { 187 if let (Some(name_ref), Some(expr)) = (record_field.name_ref(), record_field.expr()) {
188 let field_name = name_ref.syntax().text().to_string(); 188 let field_name = name_ref.syntax().text().to_string();
189 let field_expr = expr.syntax().text().to_string(); 189 let field_expr = expr.syntax().text().to_string();
190 if field_name == field_expr { 190 let field_name_is_tup_index = name_ref.as_tuple_field().is_some();
191 if field_name == field_expr && !field_name_is_tup_index {
191 let mut edit_builder = TextEditBuilder::default(); 192 let mut edit_builder = TextEditBuilder::default();
192 edit_builder.delete(record_field.syntax().text_range()); 193 edit_builder.delete(record_field.syntax().text_range());
193 edit_builder.insert(record_field.syntax().text_range().start(), field_name); 194 edit_builder.insert(record_field.syntax().text_range().start(), field_name);
@@ -321,29 +322,26 @@ mod tests {
321 fn test_wrap_return_type() { 322 fn test_wrap_return_type() {
322 let before = r#" 323 let before = r#"
323 //- /main.rs 324 //- /main.rs
324 use std::{string::String, result::Result::{self, Ok, Err}}; 325 use core::result::Result::{self, Ok, Err};
325 326
326 fn div(x: i32, y: i32) -> Result<i32, String> { 327 fn div(x: i32, y: i32) -> Result<i32, ()> {
327 if y == 0 { 328 if y == 0 {
328 return Err("div by zero".into()); 329 return Err(());
329 } 330 }
330 x / y<|> 331 x / y<|>
331 } 332 }
332 333
333 //- /std/lib.rs 334 //- /core/lib.rs
334 pub mod string {
335 pub struct String { }
336 }
337 pub mod result { 335 pub mod result {
338 pub enum Result<T, E> { Ok(T), Err(E) } 336 pub enum Result<T, E> { Ok(T), Err(E) }
339 } 337 }
340 "#; 338 "#;
341 let after = r#" 339 let after = r#"
342 use std::{string::String, result::Result::{self, Ok, Err}}; 340 use core::result::Result::{self, Ok, Err};
343 341
344 fn div(x: i32, y: i32) -> Result<i32, String> { 342 fn div(x: i32, y: i32) -> Result<i32, ()> {
345 if y == 0 { 343 if y == 0 {
346 return Err("div by zero".into()); 344 return Err(());
347 } 345 }
348 Ok(x / y) 346 Ok(x / y)
349 } 347 }
@@ -355,7 +353,7 @@ mod tests {
355 fn test_wrap_return_type_handles_generic_functions() { 353 fn test_wrap_return_type_handles_generic_functions() {
356 let before = r#" 354 let before = r#"
357 //- /main.rs 355 //- /main.rs
358 use std::result::Result::{self, Ok, Err}; 356 use core::result::Result::{self, Ok, Err};
359 357
360 fn div<T>(x: T) -> Result<T, i32> { 358 fn div<T>(x: T) -> Result<T, i32> {
361 if x == 0 { 359 if x == 0 {
@@ -364,13 +362,13 @@ mod tests {
364 <|>x 362 <|>x
365 } 363 }
366 364
367 //- /std/lib.rs 365 //- /core/lib.rs
368 pub mod result { 366 pub mod result {
369 pub enum Result<T, E> { Ok(T), Err(E) } 367 pub enum Result<T, E> { Ok(T), Err(E) }
370 } 368 }
371 "#; 369 "#;
372 let after = r#" 370 let after = r#"
373 use std::result::Result::{self, Ok, Err}; 371 use core::result::Result::{self, Ok, Err};
374 372
375 fn div<T>(x: T) -> Result<T, i32> { 373 fn div<T>(x: T) -> Result<T, i32> {
376 if x == 0 { 374 if x == 0 {
@@ -386,32 +384,29 @@ mod tests {
386 fn test_wrap_return_type_handles_type_aliases() { 384 fn test_wrap_return_type_handles_type_aliases() {
387 let before = r#" 385 let before = r#"
388 //- /main.rs 386 //- /main.rs
389 use std::{string::String, result::Result::{self, Ok, Err}}; 387 use core::result::Result::{self, Ok, Err};
390 388
391 type MyResult<T> = Result<T, String>; 389 type MyResult<T> = Result<T, ()>;
392 390
393 fn div(x: i32, y: i32) -> MyResult<i32> { 391 fn div(x: i32, y: i32) -> MyResult<i32> {
394 if y == 0 { 392 if y == 0 {
395 return Err("div by zero".into()); 393 return Err(());
396 } 394 }
397 x <|>/ y 395 x <|>/ y
398 } 396 }
399 397
400 //- /std/lib.rs 398 //- /core/lib.rs
401 pub mod string {
402 pub struct String { }
403 }
404 pub mod result { 399 pub mod result {
405 pub enum Result<T, E> { Ok(T), Err(E) } 400 pub enum Result<T, E> { Ok(T), Err(E) }
406 } 401 }
407 "#; 402 "#;
408 let after = r#" 403 let after = r#"
409 use std::{string::String, result::Result::{self, Ok, Err}}; 404 use core::result::Result::{self, Ok, Err};
410 405
411 type MyResult<T> = Result<T, String>; 406 type MyResult<T> = Result<T, ()>;
412 fn div(x: i32, y: i32) -> MyResult<i32> { 407 fn div(x: i32, y: i32) -> MyResult<i32> {
413 if y == 0 { 408 if y == 0 {
414 return Err("div by zero".into()); 409 return Err(());
415 } 410 }
416 Ok(x / y) 411 Ok(x / y)
417 } 412 }
@@ -423,16 +418,13 @@ mod tests {
423 fn test_wrap_return_type_not_applicable_when_expr_type_does_not_match_ok_type() { 418 fn test_wrap_return_type_not_applicable_when_expr_type_does_not_match_ok_type() {
424 let content = r#" 419 let content = r#"
425 //- /main.rs 420 //- /main.rs
426 use std::{string::String, result::Result::{self, Ok, Err}}; 421 use core::result::Result::{self, Ok, Err};
427 422
428 fn foo() -> Result<String, i32> { 423 fn foo() -> Result<(), i32> {
429 0<|> 424 0<|>
430 } 425 }
431 426
432 //- /std/lib.rs 427 //- /core/lib.rs
433 pub mod string {
434 pub struct String { }
435 }
436 pub mod result { 428 pub mod result {
437 pub enum Result<T, E> { Ok(T), Err(E) } 429 pub enum Result<T, E> { Ok(T), Err(E) }
438 } 430 }
@@ -444,7 +436,7 @@ mod tests {
444 fn test_wrap_return_type_not_applicable_when_return_type_is_not_result() { 436 fn test_wrap_return_type_not_applicable_when_return_type_is_not_result() {
445 let content = r#" 437 let content = r#"
446 //- /main.rs 438 //- /main.rs
447 use std::{string::String, result::Result::{self, Ok, Err}}; 439 use core::result::Result::{self, Ok, Err};
448 440
449 enum SomeOtherEnum { 441 enum SomeOtherEnum {
450 Ok(i32), 442 Ok(i32),
@@ -455,10 +447,7 @@ mod tests {
455 0<|> 447 0<|>
456 } 448 }
457 449
458 //- /std/lib.rs 450 //- /core/lib.rs
459 pub mod string {
460 pub struct String { }
461 }
462 pub mod result { 451 pub mod result {
463 pub enum Result<T, E> { Ok(T), Err(E) } 452 pub enum Result<T, E> { Ok(T), Err(E) }
464 } 453 }
@@ -731,6 +720,18 @@ mod tests {
731 "#, 720 "#,
732 check_struct_shorthand_initialization, 721 check_struct_shorthand_initialization,
733 ); 722 );
723 check_not_applicable(
724 r#"
725 struct A(usize);
726
727 fn main() {
728 A {
729 0: 0
730 }
731 }
732 "#,
733 check_struct_shorthand_initialization,
734 );
734 735
735 check_apply( 736 check_apply(
736 r#" 737 r#"