Skip LibCST parsing for standard dedent adjustments (#9769)

## Summary

Often, when fixing, we need to dedent a block of code (e.g., if we
remove an `if` and dedent its body). Today, we use LibCST to parse and
adjust the indentation, which is really expensive -- but this is only
really necessary if the block contains a multiline string, since naively
adjusting the indentation for such a string can change the whitespace
_within_ the string.

This PR uses a simple dedent implementation for cases in which the block
doesn't intersect with a multi-line string (or an f-string, since we
don't support tracking multi-line strings for f-strings right now).

We could improve this even further by using the ranges to guide the
dedent function, such that we don't apply the dedent if the line starts
within a multiline string. But that would also need to take f-strings
into account, which is a little tricky.

## Test Plan

`cargo test`
This commit is contained in:
Charlie Marsh 2024-02-02 10:13:46 -08:00 committed by GitHub
parent 4f7fb566f0
commit c3ca34543f
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
12 changed files with 193 additions and 19 deletions

View file

@ -19,11 +19,11 @@ impl CommentRanges {
Self { raw: ranges }
}
/// Returns `true` if the given range includes a comment.
/// Returns `true` if the given range intersects with any comment range.
pub fn intersects(&self, target: TextRange) -> bool {
self.raw
.binary_search_by(|range| {
if target.contains_range(*range) {
if target.intersect(*range).is_some() {
std::cmp::Ordering::Equal
} else if range.end() < target.start() {
std::cmp::Ordering::Less