diff --git a/crates/ruff_linter/resources/test/fixtures/flake8_pytest_style/PT014.py b/crates/ruff_linter/resources/test/fixtures/flake8_pytest_style/PT014.py index b408063d9b235..6a401491efeac 100644 --- a/crates/ruff_linter/resources/test/fixtures/flake8_pytest_style/PT014.py +++ b/crates/ruff_linter/resources/test/fixtures/flake8_pytest_style/PT014.py @@ -51,3 +51,8 @@ def test_error_parentheses_trailing_comma(x): @pytest.mark.parametrize("x", [1, 2]) def test_ok(x): ... + + +@pytest.mark.parametrize('data, spec', [(1.0, 1.0), (1.0, 1.0)]) +def test_numbers(data, spec): + ... diff --git a/crates/ruff_linter/src/rules/flake8_pytest_style/rules/parametrize.rs b/crates/ruff_linter/src/rules/flake8_pytest_style/rules/parametrize.rs index ded974d879624..ae9760c7e9a8d 100644 --- a/crates/ruff_linter/src/rules/flake8_pytest_style/rules/parametrize.rs +++ b/crates/ruff_linter/src/rules/flake8_pytest_style/rules/parametrize.rs @@ -644,10 +644,15 @@ fn check_values(checker: &mut Checker, names: &Expr, values: &Expr) { /// Tokenize this range to locate the comma. /// ) /// ``` -fn trailing_comma(element: &Expr, source: &str) -> Option { - SimpleTokenizer::starts_at(element.end(), source) - .find(|token| token.kind == SimpleTokenKind::Comma) - .map(|token| token.start()) +fn trailing_comma(element: &Expr, source: &str, max_index: TextSize) -> TextSize { + for token in SimpleTokenizer::starts_at(element.end(), source) { + if matches!(token.kind, SimpleTokenKind::Comma) { + return token.start(); + } else if token.start() >= max_index { + return max_index; + } + } + max_index } /// PT014 @@ -672,9 +677,9 @@ fn check_duplicates(checker: &mut Checker, values: &Expr) { if let Some(prev) = prev { let values_end = values.end() - TextSize::new(1); let previous_end = - trailing_comma(prev, checker.locator().contents()).unwrap_or(values_end); + trailing_comma(prev, checker.locator().contents(), values_end); let element_end = - trailing_comma(element, checker.locator().contents()).unwrap_or(values_end); + trailing_comma(element, checker.locator().contents(), values_end); let deletion_range = TextRange::new(previous_end, element_end); if !checker .indexer() diff --git a/crates/ruff_linter/src/rules/flake8_pytest_style/snapshots/ruff_linter__rules__flake8_pytest_style__tests__PT014.snap b/crates/ruff_linter/src/rules/flake8_pytest_style/snapshots/ruff_linter__rules__flake8_pytest_style__tests__PT014.snap index 2b532f9df688e..92240183c3672 100644 --- a/crates/ruff_linter/src/rules/flake8_pytest_style/snapshots/ruff_linter__rules__flake8_pytest_style__tests__PT014.snap +++ b/crates/ruff_linter/src/rules/flake8_pytest_style/snapshots/ruff_linter__rules__flake8_pytest_style__tests__PT014.snap @@ -166,4 +166,20 @@ PT014.py:44:11: PT014 [*] Duplicate of test case at index 0 in `@pytest_mark.par 46 45 | ) 47 46 | def test_error_parentheses_trailing_comma(x): +PT014.py:56:53: PT014 [*] Duplicate of test case at index 0 in `@pytest_mark.parametrize` + | +56 | @pytest.mark.parametrize('data, spec', [(1.0, 1.0), (1.0, 1.0)]) + | ^^^^^^^^^^ PT014 +57 | def test_numbers(data, spec): +58 | ... + | + = help: Remove duplicate test case +ℹ Unsafe fix +53 53 | ... +54 54 | +55 55 | +56 |-@pytest.mark.parametrize('data, spec', [(1.0, 1.0), (1.0, 1.0)]) + 56 |+@pytest.mark.parametrize('data, spec', [(1.0, 1.0)]) +57 57 | def test_numbers(data, spec): +58 58 | ...