From 4af2353ef90daee60da166b19d8b10dbbbe4d56f Mon Sep 17 00:00:00 2001 From: Charlie Marsh Date: Fri, 20 Jan 2023 07:41:58 -0500 Subject: [PATCH] Avoid trimming docstring if ends in trailing quote (#2025) Closes #2017. --- resources/test/fixtures/pydocstyle/D.py | 9 ++++++ .../rules/no_surrounding_whitespace.rs | 30 +++++++++---------- src/rules/pydocstyle/rules/one_liner.rs | 15 ++++++---- ...__rules__pydocstyle__tests__D200_D.py.snap | 10 +++++++ ...__rules__pydocstyle__tests__D213_D.py.snap | 10 +++++++ ...__rules__pydocstyle__tests__D400_D.py.snap | 17 +++++++++++ ...__rules__pydocstyle__tests__D415_D.py.snap | 17 +++++++++++ 7 files changed, 87 insertions(+), 21 deletions(-) diff --git a/resources/test/fixtures/pydocstyle/D.py b/resources/test/fixtures/pydocstyle/D.py index 3cc98389f6..866bce865a 100644 --- a/resources/test/fixtures/pydocstyle/D.py +++ b/resources/test/fixtures/pydocstyle/D.py @@ -606,3 +606,12 @@ def one_liner(): r"""Wrong. """ + + +@expect('D200: One-line docstring should fit on one line with quotes ' + '(found 3)') +@expect('D212: Multi-line docstring summary should start at the first line') +def one_liner(): + """Wrong." + + """ diff --git a/src/rules/pydocstyle/rules/no_surrounding_whitespace.rs b/src/rules/pydocstyle/rules/no_surrounding_whitespace.rs index 50d4e7590c..c9bb1d2ab0 100644 --- a/src/rules/pydocstyle/rules/no_surrounding_whitespace.rs +++ b/src/rules/pydocstyle/rules/no_surrounding_whitespace.rs @@ -30,22 +30,20 @@ pub fn no_surrounding_whitespace(checker: &mut Checker, docstring: &Docstring) { ); if checker.patch(diagnostic.kind.rule()) { if let Some(pattern) = leading_quote(contents) { - if let Some(quote) = pattern.chars().last() { - // If removing whitespace would lead to an invalid string of quote - // characters, avoid applying the fix. - if !trimmed.ends_with(quote) { - diagnostic.amend(Fix::replacement( - trimmed.to_string(), - Location::new( - docstring.expr.location.row(), - docstring.expr.location.column() + pattern.len(), - ), - Location::new( - docstring.expr.location.row(), - docstring.expr.location.column() + pattern.len() + line.chars().count(), - ), - )); - } + // If removing whitespace would lead to an invalid string of quote + // characters, avoid applying the fix. + if !trimmed.ends_with(pattern.chars().last().unwrap()) { + diagnostic.amend(Fix::replacement( + trimmed.to_string(), + Location::new( + docstring.expr.location.row(), + docstring.expr.location.column() + pattern.len(), + ), + Location::new( + docstring.expr.location.row(), + docstring.expr.location.column() + pattern.len() + line.chars().count(), + ), + )); } } } diff --git a/src/rules/pydocstyle/rules/one_liner.rs b/src/rules/pydocstyle/rules/one_liner.rs index e02fae30e7..c16b443f00 100644 --- a/src/rules/pydocstyle/rules/one_liner.rs +++ b/src/rules/pydocstyle/rules/one_liner.rs @@ -31,11 +31,16 @@ pub fn one_liner(checker: &mut Checker, docstring: &Docstring) { helpers::leading_quote(docstring.contents), helpers::trailing_quote(docstring.contents), ) { - diagnostic.amend(Fix::replacement( - format!("{leading}{}{trailing}", docstring.body.trim()), - docstring.expr.location, - docstring.expr.end_location.unwrap(), - )); + // If removing whitespace would lead to an invalid string of quote + // characters, avoid applying the fix. + let trimmed = docstring.body.trim(); + if !trimmed.ends_with(trailing.chars().last().unwrap()) { + diagnostic.amend(Fix::replacement( + format!("{leading}{trimmed}{trailing}"), + docstring.expr.location, + docstring.expr.end_location.unwrap(), + )); + } } } checker.diagnostics.push(diagnostic); diff --git a/src/rules/pydocstyle/snapshots/ruff__rules__pydocstyle__tests__D200_D.py.snap b/src/rules/pydocstyle/snapshots/ruff__rules__pydocstyle__tests__D200_D.py.snap index 3d6c82b048..e521e7dac7 100644 --- a/src/rules/pydocstyle/snapshots/ruff__rules__pydocstyle__tests__D200_D.py.snap +++ b/src/rules/pydocstyle/snapshots/ruff__rules__pydocstyle__tests__D200_D.py.snap @@ -53,4 +53,14 @@ expression: diagnostics row: 608 column: 7 parent: ~ +- kind: + FitsOnOneLine: ~ + location: + row: 615 + column: 4 + end_location: + row: 617 + column: 7 + fix: ~ + parent: ~ diff --git a/src/rules/pydocstyle/snapshots/ruff__rules__pydocstyle__tests__D213_D.py.snap b/src/rules/pydocstyle/snapshots/ruff__rules__pydocstyle__tests__D213_D.py.snap index 6cbf7b00fe..83f8b64d15 100644 --- a/src/rules/pydocstyle/snapshots/ruff__rules__pydocstyle__tests__D213_D.py.snap +++ b/src/rules/pydocstyle/snapshots/ruff__rules__pydocstyle__tests__D213_D.py.snap @@ -212,4 +212,14 @@ expression: diagnostics column: 7 fix: ~ parent: ~ +- kind: + MultiLineSummarySecondLine: ~ + location: + row: 615 + column: 4 + end_location: + row: 617 + column: 7 + fix: ~ + parent: ~ diff --git a/src/rules/pydocstyle/snapshots/ruff__rules__pydocstyle__tests__D400_D.py.snap b/src/rules/pydocstyle/snapshots/ruff__rules__pydocstyle__tests__D400_D.py.snap index cd8dff92e5..21914efd49 100644 --- a/src/rules/pydocstyle/snapshots/ruff__rules__pydocstyle__tests__D400_D.py.snap +++ b/src/rules/pydocstyle/snapshots/ruff__rules__pydocstyle__tests__D400_D.py.snap @@ -240,4 +240,21 @@ expression: diagnostics row: 581 column: 47 parent: ~ +- kind: + EndsInPeriod: ~ + location: + row: 615 + column: 4 + end_location: + row: 617 + column: 7 + fix: + content: "." + location: + row: 615 + column: 14 + end_location: + row: 615 + column: 14 + parent: ~ diff --git a/src/rules/pydocstyle/snapshots/ruff__rules__pydocstyle__tests__D415_D.py.snap b/src/rules/pydocstyle/snapshots/ruff__rules__pydocstyle__tests__D415_D.py.snap index 63aecb0f7d..196c8b8c2e 100644 --- a/src/rules/pydocstyle/snapshots/ruff__rules__pydocstyle__tests__D415_D.py.snap +++ b/src/rules/pydocstyle/snapshots/ruff__rules__pydocstyle__tests__D415_D.py.snap @@ -223,4 +223,21 @@ expression: diagnostics row: 581 column: 47 parent: ~ +- kind: + EndsInPunctuation: ~ + location: + row: 615 + column: 4 + end_location: + row: 617 + column: 7 + fix: + content: "." + location: + row: 615 + column: 14 + end_location: + row: 615 + column: 14 + parent: ~