fix(linter): false positive in no-return-assign (#6128)

This commit is contained in:
DonIsaac 2024-09-27 21:16:50 +00:00
parent ae539af675
commit e7e8eada69
2 changed files with 106 additions and 83 deletions

View file

@ -6,8 +6,10 @@ use serde_json::Value;
use crate::{context::LintContext, rule::Rule, AstNode}; use crate::{context::LintContext, rule::Rule, AstNode};
fn no_return_assign_diagnostic(span: Span, message: &str) -> OxcDiagnostic { fn no_return_assign_diagnostic(span: Span, message: &'static str) -> OxcDiagnostic {
OxcDiagnostic::warn(message.to_string()).with_label(span) OxcDiagnostic::warn(message)
.with_label(span)
.with_help("Did you mean to use `==` instead of `=`?")
} }
#[derive(Debug, Default, Clone)] #[derive(Debug, Default, Clone)]
@ -39,7 +41,7 @@ declare_oxc_lint!(
/// ``` /// ```
NoReturnAssign, NoReturnAssign,
style, style,
suggestion pending // TODO: add a suggestion
); );
fn is_sentinel_node(ast_kind: AstKind) -> bool { fn is_sentinel_node(ast_kind: AstKind) -> bool {
@ -60,7 +62,9 @@ impl Rule for NoReturnAssign {
} }
fn run<'a>(&self, node: &AstNode<'a>, ctx: &LintContext<'a>) { fn run<'a>(&self, node: &AstNode<'a>, ctx: &LintContext<'a>) {
if let AstKind::AssignmentExpression(_) = node.kind() { let AstKind::AssignmentExpression(assign) = node.kind() else {
return;
};
if !self.always_disallow_assignment_in_return if !self.always_disallow_assignment_in_return
&& ctx && ctx
.nodes() .nodes()
@ -69,6 +73,7 @@ impl Rule for NoReturnAssign {
{ {
return; return;
} }
let mut parent_node = ctx.nodes().parent_node(node.id()); let mut parent_node = ctx.nodes().parent_node(node.id());
while parent_node.is_some_and(|parent| !is_sentinel_node(parent.kind())) { while parent_node.is_some_and(|parent| !is_sentinel_node(parent.kind())) {
parent_node = ctx.nodes().parent_node(parent_node.unwrap().id()); parent_node = ctx.nodes().parent_node(parent_node.unwrap().id());
@ -77,22 +82,23 @@ impl Rule for NoReturnAssign {
match parent.kind() { match parent.kind() {
AstKind::ReturnStatement(_) => { AstKind::ReturnStatement(_) => {
ctx.diagnostic(no_return_assign_diagnostic( ctx.diagnostic(no_return_assign_diagnostic(
parent.span(), assign.span(),
"Return statement should not contain an assignment.", "Return statements should not contain an assignment.",
)); ));
} }
AstKind::ArrowFunctionExpression(_) => { AstKind::ArrowFunctionExpression(arrow) => {
if arrow.expression {
ctx.diagnostic(no_return_assign_diagnostic( ctx.diagnostic(no_return_assign_diagnostic(
parent.span(), assign.span(),
"Arrow function should not return an assignment.", "Arrow functions should not return an assignment.",
)); ));
} }
}
_ => (), _ => (),
} }
} }
} }
} }
}
#[test] #[test]
fn test() { fn test() {
@ -116,6 +122,7 @@ fn test() {
"function x() { return function y() { result = a * b }; }", "function x() { return function y() { result = a * b }; }",
Some(serde_json::json!(["always"])), Some(serde_json::json!(["always"])),
), ),
("() => { a = b; }", None),
("() => { return (result = a * b); }", Some(serde_json::json!(["except-parens"]))), ("() => { return (result = a * b); }", Some(serde_json::json!(["except-parens"]))),
("() => (result = a * b)", Some(serde_json::json!(["except-parens"]))), ("() => (result = a * b)", Some(serde_json::json!(["except-parens"]))),
("const foo = (a,b,c) => ((a = b), c)", None), ("const foo = (a,b,c) => ((a = b), c)", None),

View file

@ -1,111 +1,127 @@
--- ---
source: crates/oxc_linter/src/tester.rs source: crates/oxc_linter/src/tester.rs
--- ---
⚠ eslint(no-return-assign): Return statement should not contain an assignment. ⚠ eslint(no-return-assign): Return statements should not contain an assignment.
╭─[no_return_assign.tsx:1:16] ╭─[no_return_assign.tsx:1:23]
1 │ function x() { return result = a * b; }; 1 │ function x() { return result = a * b; };
· ────────────────────── · ──────────────
╰──── ╰────
help: Did you mean to use `==` instead of `=`?
⚠ eslint(no-return-assign): Return statement should not contain an assignment. ⚠ eslint(no-return-assign): Return statements should not contain an assignment.
╭─[no_return_assign.tsx:1:16] ╭─[no_return_assign.tsx:1:23]
1 │ function x() { return (result) = (a * b); }; 1 │ function x() { return (result) = (a * b); };
· ────────────────────────── · ──────────────────
╰──── ╰────
help: Did you mean to use `==` instead of `=`?
⚠ eslint(no-return-assign): Return statement should not contain an assignment. ⚠ eslint(no-return-assign): Return statements should not contain an assignment.
╭─[no_return_assign.tsx:1:16] ╭─[no_return_assign.tsx:1:23]
1 │ function x() { return result = a * b; }; 1 │ function x() { return result = a * b; };
· ────────────────────── · ──────────────
╰──── ╰────
help: Did you mean to use `==` instead of `=`?
⚠ eslint(no-return-assign): Return statement should not contain an assignment. ⚠ eslint(no-return-assign): Return statements should not contain an assignment.
╭─[no_return_assign.tsx:1:16] ╭─[no_return_assign.tsx:1:23]
1 │ function x() { return (result) = (a * b); }; 1 │ function x() { return (result) = (a * b); };
· ────────────────────────── · ──────────────────
╰──── ╰────
help: Did you mean to use `==` instead of `=`?
⚠ eslint(no-return-assign): Return statement should not contain an assignment. ⚠ eslint(no-return-assign): Return statements should not contain an assignment.
╭─[no_return_assign.tsx:1:9] ╭─[no_return_assign.tsx:1:16]
1 │ () => { return result = a * b; } 1 │ () => { return result = a * b; }
· ────────────────────── · ──────────────
╰──── ╰────
help: Did you mean to use `==` instead of `=`?
⚠ eslint(no-return-assign): Arrow function should not return an assignment. ⚠ eslint(no-return-assign): Arrow functions should not return an assignment.
╭─[no_return_assign.tsx:1:1] ╭─[no_return_assign.tsx:1:7]
1 │ () => result = a * b 1 │ () => result = a * b
· ──────────────────── · ──────────────
╰──── ╰────
help: Did you mean to use `==` instead of `=`?
⚠ eslint(no-return-assign): Return statement should not contain an assignment. ⚠ eslint(no-return-assign): Return statements should not contain an assignment.
╭─[no_return_assign.tsx:1:16] ╭─[no_return_assign.tsx:1:23]
1 │ function x() { return result = a * b; }; 1 │ function x() { return result = a * b; };
· ────────────────────── · ──────────────
╰──── ╰────
help: Did you mean to use `==` instead of `=`?
⚠ eslint(no-return-assign): Return statement should not contain an assignment. ⚠ eslint(no-return-assign): Return statements should not contain an assignment.
╭─[no_return_assign.tsx:1:16] ╭─[no_return_assign.tsx:1:24]
1 │ function x() { return (result = a * b); }; 1 │ function x() { return (result = a * b); };
· ──────────────────────── · ──────────────
╰──── ╰────
help: Did you mean to use `==` instead of `=`?
⚠ eslint(no-return-assign): Return statement should not contain an assignment. ⚠ eslint(no-return-assign): Return statements should not contain an assignment.
╭─[no_return_assign.tsx:1:16] ╭─[no_return_assign.tsx:1:34]
1 │ function x() { return result || (result = a * b); }; 1 │ function x() { return result || (result = a * b); };
· ────────────────────────────────── · ──────────────
╰──── ╰────
help: Did you mean to use `==` instead of `=`?
⚠ eslint(no-return-assign): Return statement should not contain an assignment. ⚠ eslint(no-return-assign): Return statements should not contain an assignment.
╭─[no_return_assign.tsx:2:20] ╭─[no_return_assign.tsx:2:27]
1 │ function foo(){ 1 │ function foo(){
2 │ return a = b 2 │ return a = b
· ──────────── · ─────
3 │ } 3 │ }
╰──── ╰────
help: Did you mean to use `==` instead of `=`?
⚠ eslint(no-return-assign): Return statement should not contain an assignment. ⚠ eslint(no-return-assign): Return statements should not contain an assignment.
╭─[no_return_assign.tsx:2:20] ╭─[no_return_assign.tsx:2:27]
1 │ function doSomething() { 1 │ function doSomething() {
2 │ return foo = bar && foo > 0; 2 │ return foo = bar && foo > 0;
· ──────────────────────────── · ────────────────────
3 │ } 3 │ }
╰──── ╰────
help: Did you mean to use `==` instead of `=`?
⚠ eslint(no-return-assign): Return statement should not contain an assignment. ⚠ eslint(no-return-assign): Return statements should not contain an assignment.
╭─[no_return_assign.tsx:2:20] ╭─[no_return_assign.tsx:2:27]
1 │ function doSomething() { 1 │ function doSomething() {
2 │ ╭─▶ return foo = function(){ 2 │ ╭─▶ return foo = function(){
3 │ │ return (bar = bar1) 3 │ │ return (bar = bar1)
4 │ ╰─▶ } 4 │ ╰─▶ }
5 │ } 5 │ }
╰──── ╰────
help: Did you mean to use `==` instead of `=`?
⚠ eslint(no-return-assign): Return statement should not contain an assignment. ⚠ eslint(no-return-assign): Return statements should not contain an assignment.
╭─[no_return_assign.tsx:2:20]
1 │ function doSomething() {
2 │ return foo = () => a
· ────────────────────
3 │ }
╰────
⚠ eslint(no-return-assign): Arrow function should not return an assignment.
╭─[no_return_assign.tsx:2:27] ╭─[no_return_assign.tsx:2:27]
1 │ function doSomething() { 1 │ function doSomething() {
2 │ return () => a = () => b 2 │ return foo = () => a
· ───────────────── · ─────────────
3 │ } 3 │ }
╰──── ╰────
help: Did you mean to use `==` instead of `=`?
⚠ eslint(no-return-assign): Return statement should not contain an assignment. ⚠ eslint(no-return-assign): Arrow functions should not return an assignment.
╭─[no_return_assign.tsx:3:24] ╭─[no_return_assign.tsx:2:33]
1 │ function doSomething() {
2 │ return () => a = () => b
· ───────────
3 │ }
╰────
help: Did you mean to use `==` instead of `=`?
⚠ eslint(no-return-assign): Return statements should not contain an assignment.
╭─[no_return_assign.tsx:3:31]
2 │ return function bar(b){ 2 │ return function bar(b){
3 │ return a = b 3 │ return a = b
· ──────────── · ─────
4 │ } 4 │ }
╰──── ╰────
help: Did you mean to use `==` instead of `=`?
⚠ eslint(no-return-assign): Arrow function should not return an assignment. ⚠ eslint(no-return-assign): Arrow functions should not return an assignment.
╭─[no_return_assign.tsx:1:20] ╭─[no_return_assign.tsx:1:27]
1 │ const foo = (a) => (b) => a = b 1 │ const foo = (a) => (b) => a = b
· ──────────── · ─────
╰──── ╰────
help: Did you mean to use `==` instead of `=`?