11use crate :: { ContextHost , FrameworkFlags } ;
2- use oxc_ast:: { AstKind , ast:: Expression } ;
2+ use oxc_ast:: {
3+ AstKind ,
4+ ast:: { CallExpression , Expression } ,
5+ } ;
36use oxc_diagnostics:: OxcDiagnostic ;
47use oxc_macros:: declare_oxc_lint;
58use oxc_span:: Span ;
@@ -57,28 +60,21 @@ declare_oxc_lint!(
5760 ForwardRefUsesRef ,
5861 react,
5962 correctness,
60- pending
61- // TODO: two ways to fix it: add `ref` param or remove `forwardRef` call
63+ fix
6264) ;
6365
64- fn check_forward_ref_inner ( exp : & Expression , ctx : & LintContext ) {
65- match exp {
66- Expression :: ArrowFunctionExpression ( f) => {
67- if f. params . parameters_count ( ) >= 2 || f. params . rest . is_some ( ) {
68- return ;
69- }
70- ctx. diagnostic ( forward_ref_uses_ref_diagnostic ( f. span ) ) ;
71- }
72- Expression :: FunctionExpression ( f) => {
73- if f. params . parameters_count ( ) >= 2 || f. params . rest . is_some ( ) {
74- return ;
75- }
76- ctx. diagnostic ( forward_ref_uses_ref_diagnostic ( f. span ) ) ;
77- }
78- // NOTE: Not sure whether to warn in `forwardRef(((props, ref) => null))` (with parentheses)
79- // Expression::ParenthesizedExpression(p) => check_forward_ref_inner(&p.expression),
80- _ => { }
66+ fn check_forward_ref_inner ( exp : & Expression , call_expr : & CallExpression , ctx : & LintContext ) {
67+ let ( params, span) = match exp {
68+ Expression :: ArrowFunctionExpression ( f) => ( & f. params , f. span ) ,
69+ Expression :: FunctionExpression ( f) => ( & f. params , f. span ) ,
70+ _ => return ,
71+ } ;
72+ if params. parameters_count ( ) != 1 || params. rest . is_some ( ) {
73+ return ;
8174 }
75+ ctx. diagnostic_with_fix ( forward_ref_uses_ref_diagnostic ( span) , |fixer| {
76+ fixer. replace_with ( call_expr, exp)
77+ } ) ;
8278}
8379
8480impl Rule for ForwardRefUsesRef {
@@ -97,7 +93,7 @@ impl Rule for ForwardRefUsesRef {
9793 return ; // SpreadElement like forwardRef(...x)
9894 } ;
9995
100- check_forward_ref_inner ( first_arg_as_exp, ctx) ;
96+ check_forward_ref_inner ( first_arg_as_exp, call_expr , ctx) ;
10197 }
10298
10399 fn should_run ( & self , ctx : & ContextHost ) -> bool {
@@ -165,6 +161,9 @@ fn test() {
165161 import * as React from 'react'
166162 (props) => null;
167163 " ,
164+ "forwardRef(() => {})" ,
165+ "forwardRef(function () {})" ,
166+ "forwardRef(function (a, b, c) {})" ,
168167 ] ;
169168
170169 let fail = vec ! [
@@ -198,10 +197,19 @@ fn test() {
198197 " ,
199198 ] ;
200199
200+ let fix = vec ! [
201+ ( "forwardRef((a) => {})" , "(a) => {}" ) ,
202+ ( "forwardRef(a => {})" , "a => {}" ) ,
203+ ( "forwardRef(function (a) {})" , "function (a) {}" ) ,
204+ ( "forwardRef(function(a,) {})" , "function(a,) {}" ) ,
205+ ( "React.forwardRef(function(a) {})" , "function(a) {}" ) ,
206+ ] ;
207+
201208 Tester :: new ( ForwardRefUsesRef :: NAME , ForwardRefUsesRef :: PLUGIN , pass, fail)
202209 . with_lint_options ( LintOptions {
203210 framework_hints : FrameworkFlags :: React ,
204211 ..LintOptions :: default ( )
205212 } )
213+ . expect_fix ( fix)
206214 . test_and_snapshot ( ) ;
207215}
0 commit comments