Update D208 to preserve indentation offsets when fixing overindente… · astral-sh/ruff@bd99175 (original) (raw)

`@@ -3,7 +3,7 @@ use ruff_diagnostics::{Diagnostic, Edit, Fix};

`

3

3

`use ruff_macros::{derive_message_formats, violation};

`

4

4

`use ruff_python_ast::docstrings::{clean_space, leading_space};

`

5

5

`use ruff_source_file::NewlineWithTrailingNewline;

`

6

``

`-

use ruff_text_size::Ranged;

`

``

6

`+

use ruff_text_size::{Ranged, TextSize};

`

7

7

`use ruff_text_size::{TextLen, TextRange};

`

8

8

``

9

9

`use crate::checkers::ast::Checker;

`

`@@ -172,6 +172,7 @@ pub(crate) fn indent(checker: &mut Checker, docstring: &Docstring) {

`

172

172

`let mut has_seen_tab = docstring.indentation.contains('\t');

`

173

173

`let mut is_over_indented = true;

`

174

174

`let mut over_indented_lines = vec![];

`

``

175

`+

let mut over_indented_offset = TextSize::from(u32::MAX);

`

175

176

``

176

177

`for i in 0..lines.len() {

`

177

178

`// First lines and continuations doesn't need any indentation.

`

`@@ -217,7 +218,13 @@ pub(crate) fn indent(checker: &mut Checker, docstring: &Docstring) {

`

217

218

`// the over-indentation status of every line.

`

218

219

`if i < lines.len() - 1 {

`

219

220

`if line_indent.len() > docstring.indentation.len() {

`

220

``

`-

over_indented_lines.push(TextRange::at(line.start(), line_indent.text_len()));

`

``

221

`+

over_indented_lines.push(line);

`

``

222

+

``

223

`+

// Track the smallest offset we see

`

``

224

`+

over_indented_offset = std::cmp::min(

`

``

225

`+

line_indent.text_len() - docstring.indentation.text_len(),

`

``

226

`+

over_indented_offset,

`

``

227

`+

);

`

221

228

`} else {

`

222

229

` is_over_indented = false;

`

223

230

`}

`

`@@ -235,16 +242,21 @@ pub(crate) fn indent(checker: &mut Checker, docstring: &Docstring) {

`

235

242

`if checker.enabled(Rule::OverIndentation) {

`

236

243

`// If every line (except the last) is over-indented...

`

237

244

`if is_over_indented {

`

238

``

`-

for over_indented in over_indented_lines {

`

``

245

`+

for line in over_indented_lines {

`

``

246

`+

let line_indent = leading_space(line);

`

``

247

`+

let indent = clean_space(docstring.indentation);

`

``

248

+

239

249

`// We report over-indentation on every line. This isn't great, but

`

240

250

`// enables fix.

`

241

251

`let mut diagnostic =

`

242

``

`-

Diagnostic::new(OverIndentation, TextRange::empty(over_indented.start()));

`

243

``

`-

let indent = clean_space(docstring.indentation);

`

``

252

`+

Diagnostic::new(OverIndentation, TextRange::empty(line.start()));

`

244

253

`let edit = if indent.is_empty() {

`

245

``

`-

Edit::range_deletion(over_indented)

`

``

254

`+

Edit::range_deletion(TextRange::at(line.start(), line_indent.text_len()))

`

246

255

`} else {

`

247

``

`-

Edit::range_replacement(indent, over_indented)

`

``

256

`+

Edit::range_replacement(

`

``

257

`+

indent.clone(),

`

``

258

`+

TextRange::at(line.start(), indent.text_len() + over_indented_offset),

`

``

259

`+

)

`

248

260

`};

`

249

261

` diagnostic.set_fix(Fix::safe_edit(edit));

`

250

262

` checker.diagnostics.push(diagnostic);

`