Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -371,6 +371,61 @@ async def convert(cls, ctx: Context, argument: str) -> Self:
"""
return

# DOC102 - Test case from issue #20959: comma-separated parameters
def leq(x: object, y: object) -> bool:
"""Compare two objects for loose equality.

Parameters
----------
x1, x2 : object
Objects.

Returns
-------
bool
Whether the objects are identical or equal.
"""
return x is y or x == y


# OK - comma-separated parameters that match function signature
def compare_values(x1: int, x2: int) -> bool:
"""Compare two integer values.

Parameters
----------
x1, x2 : int
Values to compare.

Returns
-------
bool
True if values are equal.
"""
return x1 == x2


# DOC102 - mixed comma-separated and regular parameters
def process_data(data, x1: str, x2: str) -> str:
"""Process data with multiple string parameters.

Parameters
----------
data : list
Input data to process.
x1, x2 : str
String parameters for processing.
extra_param : str
Extra parameter not in signature.

Returns
-------
str
Processed result.
"""
return f"{x1}{x2}{len(data)}"


# OK
def baz(x: int) -> int:
"""
Expand All @@ -389,3 +444,21 @@ def baz(x: int) -> int:
int
"""
return x


# OK - comma-separated parameters without type annotations
def add_numbers(a, b):
"""
Adds two numbers and returns the result.

Parameters
----------
a, b
The numbers to add.

Returns
-------
int
The sum of the two numbers.
"""
return a + b
38 changes: 25 additions & 13 deletions crates/ruff_linter/src/rules/pydoclint/rules/check_docstring.rs
Original file line number Diff line number Diff line change
Expand Up @@ -661,19 +661,31 @@ fn parse_parameters_numpy(content: &str, content_start: TextSize) -> Vec<Paramet
.is_some_and(|first_char| !first_char.is_whitespace())
{
if let Some(before_colon) = entry.split(':').next() {
let param = before_colon.trim_end();
let param_name = param.trim_start_matches('*');
if is_identifier(param_name) {
let param_start = line_start + indentation.text_len();
let param_end = param_start + param.text_len();

entries.push(ParameterEntry {
name: param_name,
range: TextRange::new(
content_start + param_start,
content_start + param_end,
),
});
let param_line = before_colon.trim_end();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I suspect that the trim_end call here now is unnecessary, given that you also trim each parameter part.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Removing it causes incorrect column positions in the diagnostic ranges, from my testing.

Even though we trim() each parameter part, the offset calculation happens before trimming, so the trailing whitespace in before_colon affects the positions.


// 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();
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -187,3 +187,36 @@ DOC102 Documented parameter `a` is not in the function's signature
302 | b
|
help: Remove the extraneous parameter from the docstring

DOC102 Documented parameter `x1` is not in the function's signature
--> DOC102_numpy.py:380:5
|
378 | Parameters
379 | ----------
380 | x1, x2 : object
| ^^
381 | Objects.
|
help: Remove the extraneous parameter from the docstring

DOC102 Documented parameter `x2` is not in the function's signature
--> DOC102_numpy.py:380:9
|
378 | Parameters
379 | ----------
380 | x1, x2 : object
| ^^
381 | Objects.
|
help: Remove the extraneous parameter from the docstring

DOC102 Documented parameter `extra_param` is not in the function's signature
--> DOC102_numpy.py:418:5
|
416 | x1, x2 : str
417 | String parameters for processing.
418 | extra_param : str
| ^^^^^^^^^^^
419 | Extra parameter not in signature.
|
help: Remove the extraneous parameter from the docstring