Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
fixed bang depth bug
  • Loading branch information
TheJDen committed Jul 12, 2024
commit 467c8a2dbf42306f8b14e2a4f5f5412ee6023e1a
Original file line number Diff line number Diff line change
Expand Up @@ -31,61 +31,69 @@ declare_oxc_lint!(

fn not_need_no_confusing_non_null_assertion_diagnostic(op_str: &str, span: Span) -> OxcDiagnostic {
OxcDiagnostic::warn(format!(
"Confusing combinations of non-null assertion and equal test like \"a! {op_str} b\", which looks very similar to not equal \"a !{op_str} b\"."
"typescript-eslint(no-confusing-non-null-assertion): Confusing combinations of non-null assertion and equal test like \"a! {op_str} b\", which looks very similar to not equal \"a !{op_str} b\"."
))
.with_help(
if op_str == "=" {
"Unnecessary non-null assertion (!) in assignment left hand."
}
else {
"Unnecessary non-null assertion (!) in equal test"
})
.with_help("Remove the \"!\", or prefix the \"=\" with it.")
.with_label(span)
}

fn wrap_up_no_confusing_non_null_assertion_diagnostic(span: Span) -> OxcDiagnostic {
OxcDiagnostic::warn(
"Confusing combinations of non-null assertion and equal test like \"a! = b\", which looks very similar to not equal \"a != b\"."
"typescript-eslint(no-confusing-non-null-assertion): Confusing combinations of non-null assertion and equal test like \"a! = b\", which looks very similar to not equal \"a != b\"."
)
.with_help("Wrap left-hand side in parentheses to avoid putting non-null assertion \"!\" and \"=\" together.")
.with_label(span)
}

fn ends_in_bang(expr: &Expression<'_>) -> bool {
fn get_depth_ends_in_bang(expr: &Expression<'_>) -> Option<u32> {
match expr {
Expression::TSNonNullExpression(_) => true,
Expression::BinaryExpression(binary_expr) => ends_in_bang(&binary_expr.right),
Expression::UnaryExpression(unary_expr) => ends_in_bang(&unary_expr.argument),
Expression::AssignmentExpression(assignment_expr) => ends_in_bang(&assignment_expr.right),
_ => false,
Expression::TSNonNullExpression(_) => Some(0),
Expression::BinaryExpression(binary_expr) => {
get_depth_ends_in_bang(&binary_expr.right).map(|x| x + 1)
}
Expression::UnaryExpression(unary_expr) => {
get_depth_ends_in_bang(&unary_expr.argument).map(|x| x + 1)
}
Expression::AssignmentExpression(assignment_expr) => {
get_depth_ends_in_bang(&assignment_expr.right).map(|x| x + 1)
}
_ => None,
}
}


impl Rule for NoConfusingNonNullAssertion {
fn run<'a>(&self, node: &AstNode<'a>, ctx: &LintContext<'a>) {
match node.kind() {
AstKind::BinaryExpression(binary_expr) => {
if !ends_in_bang(&binary_expr.left) {
let Some(bang_depth) = get_depth_ends_in_bang(&binary_expr.left) else {
return;
};
if bang_depth == 0 {
ctx.diagnostic(not_need_no_confusing_non_null_assertion_diagnostic(
binary_expr.operator.as_str(),
binary_expr.span,
));
} else {
ctx.diagnostic_with_fix(
wrap_up_no_confusing_non_null_assertion_diagnostic(binary_expr.span),
|fixer| {
vec![
fixer.insert_text_before(&binary_expr.left, "("),
fixer.insert_text_after(&binary_expr.left, ")"),
]
},
);
}
ctx.diagnostic(not_need_no_confusing_non_null_assertion_diagnostic(
binary_expr.operator.as_str(),
binary_expr.span,
));
}
AstKind::AssignmentExpression(assignment_expr) => {
let Some(simple_target) = assignment_expr.left.as_simple_assignment_target() else {return;};
let SimpleAssignmentTarget::TSNonNullExpression(_) = simple_target else {return};
ctx.diagnostic_with_fix(
wrap_up_no_confusing_non_null_assertion_diagnostic(assignment_expr.span),
|fixer| {
vec![
fixer.insert_text_before(&assignment_expr.left, "("),
fixer.insert_text_after(&assignment_expr.left, ")"),
]
},
);
let Some(simple_target) = assignment_expr.left.as_simple_assignment_target() else {
return;
};
let SimpleAssignmentTarget::TSNonNullExpression(_) = simple_target else { return };
ctx.diagnostic(not_need_no_confusing_non_null_assertion_diagnostic(
assignment_expr.operator.as_str(),
assignment_expr.span,
));
}
_ => {}
}
Expand All @@ -108,9 +116,9 @@ fn test() {
"(a=b)! =c;",
];
let fix = vec![
// source, expected, rule_config?
("f = 1 + d! == 2", "f = (1 + d!) == 2", None),
("f = d! == 2", "f = d == 2", None)
// source, expected, rule_config?
("f = 1 + d! == 2", "f = (1 + d!) == 2", None),
// ("f = d! == 2", "f = d == 2", None), TODO: Add suggest remove bang
];
Tester::new(NoConfusingNonNullAssertion::NAME, pass, fail).expect_fix(fix).test_and_snapshot();
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
---
source: crates/oxc_linter/src/tester.rs
---
⚠ typescript-eslint(no-confusing-non-null-assertion): Confusing combinations of non-null assertion and equal test like "a! == b", which looks very similar to not equal "a !== b".
╭─[no_confusing_non_null_assertion.tsx:1:1]
1 │ a! == b;
· ───────
╰────
help: Remove the "!", or prefix the "=" with it.

⚠ typescript-eslint(no-confusing-non-null-assertion): Confusing combinations of non-null assertion and equal test like "a! === b", which looks very similar to not equal "a !=== b".
╭─[no_confusing_non_null_assertion.tsx:1:1]
1 │ a! === b;
· ────────
╰────
help: Remove the "!", or prefix the "=" with it.

⚠ typescript-eslint(no-confusing-non-null-assertion): Confusing combinations of non-null assertion and equal test like "a! = b", which looks very similar to not equal "a != b".
╭─[no_confusing_non_null_assertion.tsx:1:1]
1 │ a + b! == c;
· ───────────
╰────
help: Wrap left-hand side in parentheses to avoid putting non-null assertion "!" and "=" together.

⚠ typescript-eslint(no-confusing-non-null-assertion): Confusing combinations of non-null assertion and equal test like "a! == b", which looks very similar to not equal "a !== b".
╭─[no_confusing_non_null_assertion.tsx:1:1]
1 │ (obj = new new OuterObj().InnerObj).Name! == c;
· ──────────────────────────────────────────────
╰────
help: Remove the "!", or prefix the "=" with it.

⚠ typescript-eslint(no-confusing-non-null-assertion): Confusing combinations of non-null assertion and equal test like "a! == b", which looks very similar to not equal "a !== b".
╭─[no_confusing_non_null_assertion.tsx:1:1]
1 │ (a==b)! ==c;
· ───────────
╰────
help: Remove the "!", or prefix the "=" with it.

⚠ typescript-eslint(no-confusing-non-null-assertion): Confusing combinations of non-null assertion and equal test like "a! = b", which looks very similar to not equal "a != b".
╭─[no_confusing_non_null_assertion.tsx:1:1]
1 │ a! = b;
· ──────
╰────
help: Remove the "!", or prefix the "=" with it.

⚠ typescript-eslint(no-confusing-non-null-assertion): Confusing combinations of non-null assertion and equal test like "a! = b", which looks very similar to not equal "a != b".
╭─[no_confusing_non_null_assertion.tsx:1:1]
1 │ (obj = new new OuterObj().InnerObj).Name! = c;
· ─────────────────────────────────────────────
╰────
help: Remove the "!", or prefix the "=" with it.

⚠ typescript-eslint(no-confusing-non-null-assertion): Confusing combinations of non-null assertion and equal test like "a! = b", which looks very similar to not equal "a != b".
╭─[no_confusing_non_null_assertion.tsx:1:1]
1 │ (a=b)! =c;
· ─────────
╰────
help: Remove the "!", or prefix the "=" with it.

This file was deleted.