Repository: astral-sh/ruff
File: crates/ruff_linter/src/rules/pydoclint/rules/check_docstring.rs (Rust)

Code before:
        current_pos = content.full_line_end(line_start);

        if let Some(entry) = potential.strip_prefix(indentation) {
            if entry
                .chars()
                .next()
                .is_some_and(|first_char| !first_char.is_whitespace())
            {
                if let Some(before_colon) = entry.split(':').next() {
                    let param_line = before_colon.trim_end();

                    // Split on commas to handle comma-separated parameters
                    for param_part in param_line.split(',') {
                        let param_part_trimmed = param_part.trim();
                        let param_name = param_part_trimmed.trim_start_matches('*');
                        if is_identifier(param_name) {
                            // Calculate the position of this specific parameter part within the line
                            let param_start_in_line =
                                param_line.find(param_part_trimmed).unwrap_or(0);
                            let param_start = line_start
                                + indentation.text_len()
                                + TextSize::from(u32::try_from(param_start_in_line).unwrap_or(0));
                            let param_end = param_start
                                + TextSize::from(
                                    u32::try_from(param_part_trimmed.len()).unwrap_or(0),
                                );

                            entries.push(ParameterEntry {
                                name: param_name,
                                range: TextRange::new(
                                    content_start + param_start,
                                    content_start + param_end,
                                ),
                            });
                        }
                    }
                }
            }
        }
    }
    entries
}

/// Parse the entries in a "Raises" section of a docstring.
///
/// Attempts to parse using the specified [`SectionStyle`], falling back to the other style if no
/// entries are found.
fn parse_raises(content: &str, style: Option<SectionStyle>) -> Vec<QualifiedName<'_>> {
    match style {
        Some(SectionStyle::Google) => parse_raises_google(content),
        Some(SectionStyle::Numpy) => parse_raises_numpy(content),

Review comment (suggestion):
I think this is just
```suggestion
                                + param_part_trimmed.text_len();
```

Code after:
    let Some(dashes) = lines.next() else {
        return entries;
    };
    let indentation = &dashes[..dashes.len() - dashes.trim_start().len()];

    let mut current_pos = content.full_line_end(dashes.text_len());
    for potential in lines {
        let line_start = current_pos;
        current_pos = content.full_line_end(line_start);

        if let Some(entry) = potential.strip_prefix(indentation) {
            if entry
                .chars()
                .next()
                .is_some_and(|first_char| !first_char.is_whitespace())
            {
                if let Some(before_colon) = entry.split(':').next() {
                    let param_line = before_colon.trim_end();

                    // Split on commas to handle comma-separated parameters
                    let mut current_offset = TextSize::from(0);
                    for param_part in param_line.split(',') {
                        let param_part_trimmed = param_part.trim();
                        let param_name = param_part_trimmed.trim_start_matches('*');
                        if is_identifier(param_name) {
                            // Calculate the position of this specific parameter part within the line
                            // Account for leading whitespace that gets trimmed
                            let param_start_in_line = current_offset
                                + (param_part.text_len() - param_part_trimmed.text_len());
                            let param_start =
                                line_start + indentation.text_len() + param_start_in_line;

                            entries.push(ParameterEntry {
                                name: param_name,
                                range: TextRange::at(
                                    content_start + param_start,
                                    param_part_trimmed.text_len(),
                                ),
                            });
                        }
                        // Update offset for next iteration: add the part length plus comma length
                        current_offset = current_offset + param_part.text_len() + ','.text_len();
                    }
                }
            }
        }
    }
    entries
}

/// Parse the entries in a "Raises" section of a docstring.