Unnamed repository; edit this file 'description' to name the repository.
Diffstat (limited to 'crates/ide-assists/src/handlers/generate_documentation_template.rs')
| -rw-r--r-- | crates/ide-assists/src/handlers/generate_documentation_template.rs | 86 |
1 files changed, 71 insertions, 15 deletions
diff --git a/crates/ide-assists/src/handlers/generate_documentation_template.rs b/crates/ide-assists/src/handlers/generate_documentation_template.rs index d4d1b3490c..77232dfebd 100644 --- a/crates/ide-assists/src/handlers/generate_documentation_template.rs +++ b/crates/ide-assists/src/handlers/generate_documentation_template.rs @@ -148,11 +148,11 @@ fn make_example_for_fn(ast_func: &ast::Fn, ctx: &AssistContext<'_>) -> Option<St let self_name = self_name(ast_func); format_to!(example, "use {use_path};\n\n"); - if let Some(self_name) = &self_name { - if let Some(mut_) = is_ref_mut_self(ast_func) { - let mut_ = if mut_ { "mut " } else { "" }; - format_to!(example, "let {mut_}{self_name} = ;\n"); - } + if let Some(self_name) = &self_name + && let Some(mut_) = is_ref_mut_self(ast_func) + { + let mut_ = if mut_ { "mut " } else { "" }; + format_to!(example, "let {mut_}{self_name} = ;\n"); } for param_name in &ref_mut_params { format_to!(example, "let mut {param_name} = ;\n"); @@ -170,10 +170,10 @@ fn make_example_for_fn(ast_func: &ast::Fn, ctx: &AssistContext<'_>) -> Option<St format_to!(example, "{function_call};\n"); } // Check the mutated values - if let Some(self_name) = &self_name { - if is_ref_mut_self(ast_func) == Some(true) { - format_to!(example, "assert_eq!({self_name}, );"); - } + if let Some(self_name) = &self_name + && is_ref_mut_self(ast_func) == Some(true) + { + format_to!(example, "assert_eq!({self_name}, );"); } for param_name in &ref_mut_params { format_to!(example, "assert_eq!({param_name}, );"); @@ -313,12 +313,28 @@ fn crate_name(ast_func: &ast::Fn, ctx: &AssistContext<'_>) -> Option<String> { /// `None` if function without a body; some bool to guess if function can panic fn can_panic(ast_func: &ast::Fn) -> Option<bool> { let body = ast_func.body()?.to_string(); - let can_panic = body.contains("panic!(") - // FIXME it would be better to not match `debug_assert*!` macro invocations - || body.contains("assert!(") - || body.contains(".unwrap()") - || body.contains(".expect("); - Some(can_panic) + let mut iter = body.chars(); + let assert_postfix = |s| { + ["!(", "_eq!(", "_ne!(", "_matches!("].iter().any(|postfix| str::starts_with(s, postfix)) + }; + + while !iter.as_str().is_empty() { + let s = iter.as_str(); + iter.next(); + if s.strip_prefix("debug_assert").is_some_and(assert_postfix) { + iter.nth(10); + continue; + } + if s.strip_prefix("assert").is_some_and(assert_postfix) + || s.starts_with("panic!(") + || s.starts_with(".unwrap()") + || s.starts_with(".expect(") + { + return Some(true); + } + } + + Some(false) } /// Helper function to get the name that should be given to `self` arguments @@ -678,6 +694,24 @@ pub fn panics_if(a: bool) { } #[test] + fn guesses_debug_assert_macro_cannot_panic() { + check_assist( + generate_documentation_template, + r#" +pub fn $0debug_panics_if_not(a: bool) { + debug_assert!(a == true); +} +"#, + r#" +/// . +pub fn debug_panics_if_not(a: bool) { + debug_assert!(a == true); +} +"#, + ); + } + + #[test] fn guesses_assert_macro_can_panic() { check_assist( generate_documentation_template, @@ -700,6 +734,28 @@ pub fn panics_if_not(a: bool) { } #[test] + fn guesses_assert_eq_macro_can_panic() { + check_assist( + generate_documentation_template, + r#" +pub fn $0panics_if_not(a: bool) { + assert_eq!(a, true); +} +"#, + r#" +/// . +/// +/// # Panics +/// +/// Panics if . +pub fn panics_if_not(a: bool) { + assert_eq!(a, true); +} +"#, + ); + } + + #[test] fn guesses_unwrap_can_panic() { check_assist( generate_documentation_template, |