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.rs86
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,