fix(rome_analyze): fix the find_diff_range in case tokens were only removed
MODIFY
crates/rome_analyze/src/signals.rs
crates/rome_analyze/src/signals.rs
@@ -183,22 +183,24 @@ where
});
match (range_start, range_end) {
- (Some(start), Some((prev_end, next_end))) => Some((
+ (Some(start), Some((prev_end, next_end))) => {
+ // Ensure the end of the new range ends is higher or equal to the
+ // start, the value of next_end may sometimes cross the start if
+ // the diff only removed some tokens as both search iterations stop
+ // after the first difference
+ let next_end = next_end.max(start);
+
+ Some((
TextRange::new(start, prev_end),
TextRange::new(start, next_end),
- )),
+ ))
+ }
(Some(start), None) => Some((
TextRange::new(start, prev.text_range().end()),
TextRange::new(start, next.text_range().end()),
)),
- (None, None) => None,
-
- // This branch is unreachable since `range_start` can only be `None` if
- // it consumes the entire `tokens` iterator without ever returning
- // `Some(_)`, then `range_end` will also necessarily return `None` as
- // there as not items left to inspect
- (None, Some(_)) => unreachable!(),
+ (None, _) => None,
}
}
@@ -206,12 +208,14 @@ where
mod tests {
use rome_js_factory::make;
use rome_js_syntax::{JsAnyExpression, JsAnyStatement, TextRange, TextSize, T};
- use rome_rowan::AstNode;
+ use rome_rowan::{AstNode, AstNodeListExt};
use super::find_diff_range;
#[test]
- fn diff_range() {
+ /// Checks the [find_diff_range] function returns the correct result when
+ /// tokens are reused from the input in the middle of the range
+ fn diff_range_split() {
let before = make::js_if_statement(
make::token(T![if]),
make::token(T!['(']),
@@ -263,4 +267,52 @@ mod tests {
(TextRange::new(start, end), TextRange::new(start, end))
);
}
+
+ #[test]
+ /// Checks the [find_diff_range] function returns the correct result when
+ /// tokens are removed from the input
+ fn diff_range_remove() {
+ let before = make::js_statement_list(vec![
+ JsAnyStatement::JsExpressionStatement(
+ make::js_expression_statement(JsAnyExpression::JsIdentifierExpression(
+ make::js_identifier_expression(make::js_reference_identifier(make::ident(
+ "statement1",
+ ))),
+ ))
+ .with_semicolon_token(make::token(T![;]))
+ .build(),
+ ),
+ JsAnyStatement::JsExpressionStatement(
+ make::js_expression_statement(JsAnyExpression::JsIdentifierExpression(
+ make::js_identifier_expression(make::js_reference_identifier(make::ident(
+ "statement2",
+ ))),
+ ))
+ .with_semicolon_token(make::token(T![;]))
+ .build(),
+ ),
+ JsAnyStatement::JsExpressionStatement(
+ make::js_expression_statement(JsAnyExpression::JsIdentifierExpression(
+ make::js_identifier_expression(make::js_reference_identifier(make::ident(
+ "statement3",
+ ))),
+ ))
+ .with_semicolon_token(make::token(T![;]))
+ .build(),
+ ),
+ ]);
+
+ let after = before.clone().splice(1..=1, None);
+
+ let diff = find_diff_range(before.syntax(), after.syntax())
+ .expect("failed to calculate diff range");
+
+ let start = TextSize::of("statement1;");
+ let end = TextSize::of("statement1;statement2");
+
+ assert_eq!(
+ diff,
+ (TextRange::new(start, end), TextRange::new(start, start))
+ );
+ }
}

fix(rome_analyze): fix the find_diff_range in case tokens were only removed (#2694)