Skip to content

Commit

Permalink
refactor(linter/yoda): simplify code (#7941)
Browse files Browse the repository at this point in the history
Follow-on after #7679.

Simplify `do_diagnostic_with_fix`, in particular the search for the operator. Also reduce `span()` calls, as they have a cost.
  • Loading branch information
overlookmotel committed Dec 16, 2024
1 parent c3c76cb commit ff2a68f
Showing 1 changed file with 28 additions and 36 deletions.
64 changes: 28 additions & 36 deletions crates/oxc_linter/src/rules/eslint/yoda.rs
Original file line number Diff line number Diff line change
Expand Up @@ -266,61 +266,53 @@ fn is_not_yoda(expr: &BinaryExpression) -> bool {
#[allow(clippy::cast_possible_truncation)]
fn do_diagnostic_with_fix(expr: &BinaryExpression, ctx: &LintContext, never: bool) {
ctx.diagnostic_with_fix(yoda_diagnostic(expr.span, never, expr.operator.as_str()), |fix| {
let flipped_operator = flip_operator(expr.operator);

let left_str = ctx.source_range(expr.left.span());
let right_str = ctx.source_range(expr.right.span());
let flipped_operator_str = flipped_operator.as_str();
let left_span = expr.left.span();
let right_span = expr.right.span();

let operator_str = expr.operator.as_str();
let source_str = ctx.source_range(
Span::new(expr.left.span().end, expr.right.span().start)
let str_between_left_and_right = ctx.source_range(
Span::new(left_span.end, right_span.start)
);

let source_chars = source_str.char_indices().collect::<Vec<_>>();

let search_start_position = expr.left.span().end;

let operator_position_start = source_chars.windows(operator_str.len()).find(|str| {
if str.iter().enumerate().all(|(i, (_pos, c))| *c == operator_str.chars().nth(i).unwrap()) {
!ctx.comments().iter().any(|c| {
c.span.start <= (str[0].0 as u32) + search_start_position && (str[0].0 as u32) + operator_str.len() as u32 + search_start_position <= c.span.end
})
} else {
false
}
});

let Some(operator_position_start) = operator_position_start else {
debug_assert!(false);
return fix.noop();
};

let operator_position_start = search_start_position + operator_position_start[0].0 as u32;
let (operator_start, operator_end) = str_between_left_and_right
.as_bytes()
.windows(operator_str.len())
.enumerate()
.find_map(|(index, chunk)| {
if chunk == operator_str.as_bytes() {
let pos_start = index as u32 + left_span.end;
let pos_end = pos_start + operator_str.len() as u32;
if !ctx.comments().iter().any(|comment| comment.span.start <= pos_start && pos_end <= comment.span.end) {
return Some((pos_start, pos_end));
}
}
None
})
.unwrap();

let operator_position_end = operator_position_start + operator_str.len() as u32;
let str_between_left_and_operator = ctx.source_range(Span::new(expr.left.span().end, operator_position_start));
let str_between_operator_and_right = ctx.source_range(Span::new(operator_position_end, expr.right.span().start));
let str_between_left_and_operator = ctx.source_range(Span::new(left_span.end, operator_start));
let str_between_operator_and_right = ctx.source_range(Span::new(operator_end, right_span.start));

let left_start = expr.left.span().start;
let left_prev_token = if left_start > 0 && (expr.right.is_literal() || expr.right.is_identifier_reference() ) {
let tokens = ctx.source_range(Span::new(0, left_start));
let left_prev_token = if left_span.start > 0 && (expr.right.is_literal() || expr.right.is_identifier_reference() ) {
let tokens = ctx.source_range(Span::new(0, left_span.start));
let token = tokens.chars().last();
match_token(token)
} else {
false
};

let right_end = expr.right.span().end;
let source_size = u32::try_from(ctx.source_text().len()).unwrap();
let right_next_token = if right_end < source_size && (expr.left.is_literal() || expr.left.is_identifier_reference()) {
let tokens = ctx.source_range(Span::new(right_end, source_size));
let right_next_token = if right_span.end < source_size && (expr.left.is_literal() || expr.left.is_identifier_reference()) {
let tokens = ctx.source_range(Span::new(right_span.end, source_size));
let token = tokens.chars().next();
match_token(token)
} else {
false
};

let left_str = ctx.source_range(left_span);
let right_str = ctx.source_range(right_span);
let flipped_operator_str = flip_operator(expr.operator).as_str();
let replacement = format!(
"{}{right_str}{str_between_left_and_operator}{flipped_operator_str}{str_between_operator_and_right}{left_str}{}",
if left_prev_token { " " } else { "" },
Expand Down

0 comments on commit ff2a68f

Please sign in to comment.