diff --git a/internal/linter/linter.go b/internal/linter/linter.go index 02c786ae..47d5b31e 100644 --- a/internal/linter/linter.go +++ b/internal/linter/linter.go @@ -161,7 +161,8 @@ func RunLinterOnProgram(logLevel utils.LogLevel, program *compiler.Program, file SourceFile: file, }) }, - ReportRangeWithSuggestions: func(textRange core.TextRange, msg rule.RuleMessage, suggestions ...rule.RuleSuggestion) { + ReportRangeWithSuggestions: func(textRange core.TextRange, msg rule.RuleMessage, suggestionsFn func() []rule.RuleSuggestion) { + suggestions := suggestionsFn() onDiagnostic(rule.RuleDiagnostic{ RuleName: r.Name, Range: textRange, @@ -178,7 +179,8 @@ func RunLinterOnProgram(logLevel utils.LogLevel, program *compiler.Program, file SourceFile: file, }) }, - ReportNodeWithFixes: func(node *ast.Node, msg rule.RuleMessage, fixes ...rule.RuleFix) { + ReportNodeWithFixes: func(node *ast.Node, msg rule.RuleMessage, fixesFn func() []rule.RuleFix) { + fixes := fixesFn() onDiagnostic(rule.RuleDiagnostic{ RuleName: r.Name, Range: utils.TrimNodeTextRange(file, node), @@ -188,7 +190,8 @@ func RunLinterOnProgram(logLevel utils.LogLevel, program *compiler.Program, file }) }, - ReportNodeWithSuggestions: func(node *ast.Node, msg rule.RuleMessage, suggestions ...rule.RuleSuggestion) { + ReportNodeWithSuggestions: func(node *ast.Node, msg rule.RuleMessage, suggestionsFn func() []rule.RuleSuggestion) { + suggestions := suggestionsFn() onDiagnostic(rule.RuleDiagnostic{ RuleName: r.Name, Range: utils.TrimNodeTextRange(file, node), diff --git a/internal/rule/rule.go b/internal/rule/rule.go index adc7a6d2..d3a32025 100644 --- a/internal/rule/rule.go +++ b/internal/rule/rule.go @@ -114,19 +114,21 @@ type RuleContext struct { Program *compiler.Program TypeChecker *checker.Checker ReportRange func(textRange core.TextRange, msg RuleMessage) - ReportRangeWithSuggestions func(textRange core.TextRange, msg RuleMessage, suggestions ...RuleSuggestion) + ReportRangeWithSuggestions func(textRange core.TextRange, msg RuleMessage, suggestionsFn func() []RuleSuggestion) ReportNode func(node *ast.Node, msg RuleMessage) - ReportNodeWithFixes func(node *ast.Node, msg RuleMessage, fixes ...RuleFix) - ReportNodeWithSuggestions func(node *ast.Node, msg RuleMessage, suggestions ...RuleSuggestion) + ReportNodeWithFixes func(node *ast.Node, msg RuleMessage, fixesFn func() []RuleFix) + ReportNodeWithSuggestions func(node *ast.Node, msg RuleMessage, suggestionsFn func() []RuleSuggestion) } func ReportNodeWithFixesOrSuggestions(ctx RuleContext, node *ast.Node, fix bool, msg RuleMessage, suggestionMsg RuleMessage, fixes ...RuleFix) { if fix { - ctx.ReportNodeWithFixes(node, msg, fixes...) + ctx.ReportNodeWithFixes(node, msg, func() []RuleFix { return fixes }) } else { - ctx.ReportNodeWithSuggestions(node, msg, RuleSuggestion{ - Message: suggestionMsg, - FixesArr: fixes, + ctx.ReportNodeWithSuggestions(node, msg, func() []RuleSuggestion { + return []RuleSuggestion{{ + Message: suggestionMsg, + FixesArr: fixes, + }} }) } } diff --git a/internal/rules/await_thenable/await_thenable.go b/internal/rules/await_thenable/await_thenable.go index 0eb889b7..2bb0b63c 100644 --- a/internal/rules/await_thenable/await_thenable.go +++ b/internal/rules/await_thenable/await_thenable.go @@ -52,11 +52,13 @@ var AwaitThenableRule = rule.Rule{ certainty := utils.NeedsToBeAwaited(ctx.TypeChecker, awaitArgument, awaitArgumentType) if certainty == utils.TypeAwaitableNever { - ctx.ReportNodeWithSuggestions(node, buildAwaitMessage(), rule.RuleSuggestion{ - Message: buildRemoveAwaitMessage(), - FixesArr: []rule.RuleFix{ - rule.RuleFixRemoveRange(scanner.GetRangeOfTokenAtPosition(ctx.SourceFile, node.Pos())), - }, + ctx.ReportNodeWithSuggestions(node, buildAwaitMessage(), func() []rule.RuleSuggestion { + return []rule.RuleSuggestion{{ + Message: buildRemoveAwaitMessage(), + FixesArr: []rule.RuleFix{ + rule.RuleFixRemoveRange(scanner.GetRangeOfTokenAtPosition(ctx.SourceFile, node.Pos())), + }, + }} }) } }, @@ -80,13 +82,15 @@ var AwaitThenableRule = rule.Rule{ ctx.ReportRangeWithSuggestions( utils.GetForStatementHeadLoc(ctx.SourceFile, node), buildForAwaitOfNonAsyncIterableMessage(), - // Note that this suggestion causes broken code for sync iterables - // of promises, since the loop variable is not awaited. - rule.RuleSuggestion{ - Message: buildConvertToOrdinaryForMessage(), - FixesArr: []rule.RuleFix{ - rule.RuleFixRemove(ctx.SourceFile, stmt.AwaitModifier), - }, + func() []rule.RuleSuggestion { + // Note that this suggestion causes broken code for sync iterables + // of promises, since the loop variable is not awaited. + return []rule.RuleSuggestion{{ + Message: buildConvertToOrdinaryForMessage(), + FixesArr: []rule.RuleFix{ + rule.RuleFixRemove(ctx.SourceFile, stmt.AwaitModifier), + }, + }} }, ) }, @@ -126,7 +130,7 @@ var AwaitThenableRule = rule.Rule{ }) } - ctx.ReportNodeWithSuggestions(init, buildAwaitUsingOfNonAsyncDisposableMessage(), suggestions...) + ctx.ReportNodeWithSuggestions(init, buildAwaitUsingOfNonAsyncDisposableMessage(), func() []rule.RuleSuggestion { return suggestions }) } }, } diff --git a/internal/rules/no_array_delete/no_array_delete.go b/internal/rules/no_array_delete/no_array_delete.go index e186607d..b4e37ce1 100644 --- a/internal/rules/no_array_delete/no_array_delete.go +++ b/internal/rules/no_array_delete/no_array_delete.go @@ -72,13 +72,15 @@ var NoArrayDeleteRule = rule.Rule{ leftBracketTokenRange := scanner.GetRangeOfTokenAtPosition(ctx.SourceFile, expressionRange.End()) rightBracketTokenRange := scanner.GetRangeOfTokenAtPosition(ctx.SourceFile, argumentRange.End()) - ctx.ReportNodeWithSuggestions(node, buildNoArrayDeleteMessage(), rule.RuleSuggestion{ - Message: buildUseSpliceMessage(), - FixesArr: []rule.RuleFix{ - rule.RuleFixRemoveRange(deleteTokenRange), - rule.RuleFixReplaceRange(leftBracketTokenRange, ".splice("), - rule.RuleFixReplaceRange(rightBracketTokenRange, ", 1)"), - }, + ctx.ReportNodeWithSuggestions(node, buildNoArrayDeleteMessage(), func() []rule.RuleSuggestion { + return []rule.RuleSuggestion{{ + Message: buildUseSpliceMessage(), + FixesArr: []rule.RuleFix{ + rule.RuleFixRemoveRange(deleteTokenRange), + rule.RuleFixReplaceRange(leftBracketTokenRange, ".splice("), + rule.RuleFixReplaceRange(rightBracketTokenRange, ", 1)"), + }, + }} }) }, } diff --git a/internal/rules/no_confusing_void_expression/no_confusing_void_expression.go b/internal/rules/no_confusing_void_expression/no_confusing_void_expression.go index 9e3acc68..27e59d34 100644 --- a/internal/rules/no_confusing_void_expression/no_confusing_void_expression.go +++ b/internal/rules/no_confusing_void_expression/no_confusing_void_expression.go @@ -206,7 +206,7 @@ var NoConfusingVoidExpressionRule = rule.Rule{ } if opts.IgnoreVoidOperator { - ctx.ReportNodeWithFixes(node, buildInvalidVoidExprArrowWrapVoidMessage(), insertVoidFix()) + ctx.ReportNodeWithFixes(node, buildInvalidVoidExprArrowWrapVoidMessage(), func() []rule.RuleFix { return []rule.RuleFix{insertVoidFix()} }) return } @@ -220,7 +220,7 @@ var NoConfusingVoidExpressionRule = rule.Rule{ } } - ctx.ReportNodeWithFixes(node, buildInvalidVoidExprArrowMessage(), fixes...) + ctx.ReportNodeWithFixes(node, buildInvalidVoidExprArrowMessage(), func() []rule.RuleFix { return fixes }) return } @@ -234,7 +234,7 @@ var NoConfusingVoidExpressionRule = rule.Rule{ } if opts.IgnoreVoidOperator { - ctx.ReportNodeWithFixes(node, buildInvalidVoidExprReturnWrapVoidMessage(), insertVoidFix()) + ctx.ReportNodeWithFixes(node, buildInvalidVoidExprReturnWrapVoidMessage(), func() []rule.RuleFix { return []rule.RuleFix{insertVoidFix()} }) return } @@ -251,7 +251,7 @@ var NoConfusingVoidExpressionRule = rule.Rule{ fixes = append(fixes, rule.RuleFixReplaceRange(returnToken, replaceText)) } - ctx.ReportNodeWithFixes(node, buildInvalidVoidExprReturnLastMessage(), fixes...) + ctx.ReportNodeWithFixes(node, buildInvalidVoidExprReturnLastMessage(), func() []rule.RuleFix { return fixes }) return } @@ -272,14 +272,16 @@ var NoConfusingVoidExpressionRule = rule.Rule{ rule.RuleFixInsertAfter(invalidAncestor, " }"), ) } - ctx.ReportNodeWithFixes(node, buildInvalidVoidExprReturnMessage(), fixes...) + ctx.ReportNodeWithFixes(node, buildInvalidVoidExprReturnMessage(), func() []rule.RuleFix { return fixes }) return } if opts.IgnoreVoidOperator { - ctx.ReportNodeWithSuggestions(node, buildInvalidVoidExprWrapVoidMessage(), rule.RuleSuggestion{ - Message: buildVoidExprWrapVoidMessage(), - FixesArr: []rule.RuleFix{insertVoidFix()}, + ctx.ReportNodeWithSuggestions(node, buildInvalidVoidExprWrapVoidMessage(), func() []rule.RuleSuggestion { + return []rule.RuleSuggestion{{ + Message: buildVoidExprWrapVoidMessage(), + FixesArr: []rule.RuleFix{insertVoidFix()}, + }} }) return } diff --git a/internal/rules/no_duplicate_type_constituents/no_duplicate_type_constituents.go b/internal/rules/no_duplicate_type_constituents/no_duplicate_type_constituents.go index a1fd16c3..f1edecda 100644 --- a/internal/rules/no_duplicate_type_constituents/no_duplicate_type_constituents.go +++ b/internal/rules/no_duplicate_type_constituents/no_duplicate_type_constituents.go @@ -166,7 +166,7 @@ var NoDuplicateTypeConstituentsRule = rule.Rule{ } } } - ctx.ReportNodeWithFixes(constituentNode, message, fixes...) + ctx.ReportNodeWithFixes(constituentNode, message, func() []rule.RuleFix { return fixes }) } var checkDuplicateRecursively func( diff --git a/internal/rules/no_floating_promises/no_floating_promises.go b/internal/rules/no_floating_promises/no_floating_promises.go index 2ca913b3..5628a121 100644 --- a/internal/rules/no_floating_promises/no_floating_promises.go +++ b/internal/rules/no_floating_promises/no_floating_promises.go @@ -410,20 +410,25 @@ var NoFloatingPromisesRule = rule.Rule{ msg = buildFloatingVoidMessage() } - ctx.ReportNodeWithSuggestions(node, msg, rule.RuleSuggestion{ - Message: buildFloatingFixVoidMessage(), - FixesArr: (func() []rule.RuleFix { - if isHigherPrecedenceThanUnary(exprStatement.Expression) { - return []rule.RuleFix{rule.RuleFixInsertBefore(ctx.SourceFile, node, "void ")} - } - return []rule.RuleFix{ - rule.RuleFixInsertBefore(ctx.SourceFile, node, "void ("), - rule.RuleFixInsertAfter(expression, ")"), - } - })(), - }, rule.RuleSuggestion{ - Message: buildFloatingFixAwaitMessage(), - FixesArr: addAwait(expression, exprStatement), + ctx.ReportNodeWithSuggestions(node, msg, func() []rule.RuleSuggestion { + return []rule.RuleSuggestion{ + { + Message: buildFloatingFixVoidMessage(), + FixesArr: func() []rule.RuleFix { + if isHigherPrecedenceThanUnary(exprStatement.Expression) { + return []rule.RuleFix{rule.RuleFixInsertBefore(ctx.SourceFile, node, "void ")} + } + return []rule.RuleFix{ + rule.RuleFixInsertBefore(ctx.SourceFile, node, "void ("), + rule.RuleFixInsertAfter(expression, ")"), + } + }(), + }, + { + Message: buildFloatingFixAwaitMessage(), + FixesArr: addAwait(expression, exprStatement), + }, + } }) } else { var msg rule.RuleMessage @@ -432,9 +437,11 @@ var NoFloatingPromisesRule = rule.Rule{ } else { msg = buildFloatingMessage() } - ctx.ReportNodeWithSuggestions(node, msg, rule.RuleSuggestion{ - Message: buildFloatingFixAwaitMessage(), - FixesArr: addAwait(expression, exprStatement), + ctx.ReportNodeWithSuggestions(node, msg, func() []rule.RuleSuggestion { + return []rule.RuleSuggestion{{ + Message: buildFloatingFixAwaitMessage(), + FixesArr: addAwait(expression, exprStatement), + }} }) } }, diff --git a/internal/rules/no_meaningless_void_operator/no_meaningless_void_operator.go b/internal/rules/no_meaningless_void_operator/no_meaningless_void_operator.go index e2d1be23..821e4a87 100644 --- a/internal/rules/no_meaningless_void_operator/no_meaningless_void_operator.go +++ b/internal/rules/no_meaningless_void_operator/no_meaningless_void_operator.go @@ -53,11 +53,13 @@ var NoMeaninglessVoidOperatorRule = rule.Rule{ } if mask&checker.TypeFlagsVoidLike != 0 { - ctx.ReportNodeWithFixes(node, buildMeaninglessVoidOperatorMessage(ctx.TypeChecker.TypeToString(argType)), fixRemoveVoidKeyword()) + ctx.ReportNodeWithFixes(node, buildMeaninglessVoidOperatorMessage(ctx.TypeChecker.TypeToString(argType)), func() []rule.RuleFix { return []rule.RuleFix{fixRemoveVoidKeyword()} }) } else if *opts.CheckNever && mask&checker.TypeFlagsNever != 0 { - ctx.ReportNodeWithSuggestions(node, buildMeaninglessVoidOperatorMessage(ctx.TypeChecker.TypeToString(argType)), rule.RuleSuggestion{ - Message: buildRemoveVoidMessage(), - FixesArr: []rule.RuleFix{fixRemoveVoidKeyword()}, + ctx.ReportNodeWithSuggestions(node, buildMeaninglessVoidOperatorMessage(ctx.TypeChecker.TypeToString(argType)), func() []rule.RuleSuggestion { + return []rule.RuleSuggestion{{ + Message: buildRemoveVoidMessage(), + FixesArr: []rule.RuleFix{fixRemoveVoidKeyword()}, + }} }) } }, diff --git a/internal/rules/no_misused_spread/no_misused_spread.go b/internal/rules/no_misused_spread/no_misused_spread.go index 9b747008..a297db9f 100644 --- a/internal/rules/no_misused_spread/no_misused_spread.go +++ b/internal/rules/no_misused_spread/no_misused_spread.go @@ -227,9 +227,11 @@ var NoMisusedSpreadRule = rule.Rule{ } if isPromise(ctx.Program, ctx.TypeChecker, t) { - ctx.ReportNodeWithSuggestions(node, buildNoPromiseSpreadInObjectMessage(), rule.RuleSuggestion{ - Message: buildAddAwaitMessage(), - FixesArr: insertAwaitFix(ast.SkipParentheses(argument)), + ctx.ReportNodeWithSuggestions(node, buildNoPromiseSpreadInObjectMessage(), func() []rule.RuleSuggestion { + return []rule.RuleSuggestion{{ + Message: buildAddAwaitMessage(), + FixesArr: insertAwaitFix(ast.SkipParentheses(argument)), + }} }) return @@ -242,7 +244,7 @@ var NoMisusedSpreadRule = rule.Rule{ } if isMap(ctx.Program, ctx.TypeChecker, t) { - ctx.ReportNodeWithSuggestions(node, buildNoMapSpreadInObjectMessage(), getMapSpreadSuggestions(node, argument, t)...) + ctx.ReportNodeWithSuggestions(node, buildNoMapSpreadInObjectMessage(), func() []rule.RuleSuggestion { return getMapSpreadSuggestions(node, argument, t) }) return } diff --git a/internal/rules/no_unnecessary_boolean_literal_compare/no_unnecessary_boolean_literal_compare.go b/internal/rules/no_unnecessary_boolean_literal_compare/no_unnecessary_boolean_literal_compare.go index e69159d6..8a654419 100644 --- a/internal/rules/no_unnecessary_boolean_literal_compare/no_unnecessary_boolean_literal_compare.go +++ b/internal/rules/no_unnecessary_boolean_literal_compare/no_unnecessary_boolean_literal_compare.go @@ -204,7 +204,7 @@ var NoUnnecessaryBooleanLiteralCompareRule = rule.Rule{ fixes = append(fixes, rule.RuleFixInsertBefore(ctx.SourceFile, mutatedNode, "("), rule.RuleFixInsertAfter(mutatedNode, " ?? true)")) } - ctx.ReportNodeWithFixes(node, msg, fixes...) + ctx.ReportNodeWithFixes(node, msg, func() []rule.RuleFix { return fixes }) }, } }, diff --git a/internal/rules/no_unnecessary_type_arguments/no_unnecessary_type_arguments.go b/internal/rules/no_unnecessary_type_arguments/no_unnecessary_type_arguments.go index 9de8b9ac..500a6c7f 100644 --- a/internal/rules/no_unnecessary_type_arguments/no_unnecessary_type_arguments.go +++ b/internal/rules/no_unnecessary_type_arguments/no_unnecessary_type_arguments.go @@ -139,7 +139,7 @@ var NoUnnecessaryTypeArgumentsRule = rule.Rule{ } else { removeRange = arg.Loc.WithPos(arguments.Nodes[i-1].End()) } - ctx.ReportNodeWithFixes(arg, buildUnnecessaryTypeParameterMessage(), rule.RuleFixRemoveRange(removeRange)) + ctx.ReportNodeWithFixes(arg, buildUnnecessaryTypeParameterMessage(), func() []rule.RuleFix { return []rule.RuleFix{rule.RuleFixRemoveRange(removeRange)} }) } diff --git a/internal/rules/no_unnecessary_type_assertion/no_unnecessary_type_assertion.go b/internal/rules/no_unnecessary_type_assertion/no_unnecessary_type_assertion.go index 06d78848..79e153f9 100644 --- a/internal/rules/no_unnecessary_type_assertion/no_unnecessary_type_assertion.go +++ b/internal/rules/no_unnecessary_type_assertion/no_unnecessary_type_assertion.go @@ -222,7 +222,9 @@ var NoUnnecessaryTypeAssertionRule = rule.Rule{ s := scanner.GetScannerForSourceFile(ctx.SourceFile, expression.End()) asKeywordRange := s.TokenRange() - ctx.ReportNodeWithFixes(node, msg, rule.RuleFixRemoveRange(asKeywordRange), rule.RuleFixRemove(ctx.SourceFile, typeNode)) + ctx.ReportNodeWithFixes(node, msg, func() []rule.RuleFix { + return []rule.RuleFix{rule.RuleFixRemoveRange(asKeywordRange), rule.RuleFixRemove(ctx.SourceFile, typeNode)} + }) } else { s := scanner.GetScannerForSourceFile(ctx.SourceFile, node.Pos()) openingAngleBracket := s.TokenRange() @@ -230,7 +232,9 @@ var NoUnnecessaryTypeAssertionRule = rule.Rule{ s.Scan() closingAngleBracket := s.TokenRange() - ctx.ReportNodeWithFixes(node, msg, rule.RuleFixRemoveRange(openingAngleBracket.WithEnd(closingAngleBracket.End()))) + ctx.ReportNodeWithFixes(node, msg, func() []rule.RuleFix { + return []rule.RuleFix{rule.RuleFixRemoveRange(openingAngleBracket.WithEnd(closingAngleBracket.End()))} + }) } // TODO - add contextually unnecessary check for this } @@ -249,7 +253,7 @@ var NoUnnecessaryTypeAssertionRule = rule.Rule{ if ast.IsAssignmentExpression(node.Parent, true) { if node.Parent.AsBinaryExpression().Left == node { - ctx.ReportNodeWithFixes(node, buildContextuallyUnnecessaryMessage(), buildRemoveExclamationFix()) + ctx.ReportNodeWithFixes(node, buildContextuallyUnnecessaryMessage(), func() []rule.RuleFix { return []rule.RuleFix{buildRemoveExclamationFix()} }) } // for all other = assignments we ignore non-null checks // this is because non-null assertions can change the type-flow of the code @@ -272,7 +276,7 @@ var NoUnnecessaryTypeAssertionRule = rule.Rule{ if ast.IsIdentifier(expression) && isPossiblyUsedBeforeAssigned(expression) { return } - ctx.ReportNodeWithFixes(node, buildUnnecessaryAssertionMessage(), buildRemoveExclamationFix()) + ctx.ReportNodeWithFixes(node, buildUnnecessaryAssertionMessage(), func() []rule.RuleFix { return []rule.RuleFix{buildRemoveExclamationFix()} }) } else { // we know it's a nullable type // so figure out if the variable is used in a place that accepts nullable types @@ -304,7 +308,7 @@ var NoUnnecessaryTypeAssertionRule = rule.Rule{ isValidVoid := !typeIncludesVoid || contextualTypeIncludesVoid if isValidUndefined && isValidNull && isValidVoid { - ctx.ReportNodeWithFixes(node, buildContextuallyUnnecessaryMessage(), buildRemoveExclamationFix()) + ctx.ReportNodeWithFixes(node, buildContextuallyUnnecessaryMessage(), func() []rule.RuleFix { return []rule.RuleFix{buildRemoveExclamationFix()} }) } } } diff --git a/internal/rules/non_nullable_type_assertion_style/non_nullable_type_assertion_style.go b/internal/rules/non_nullable_type_assertion_style/non_nullable_type_assertion_style.go index f6143135..9ccda5c1 100644 --- a/internal/rules/non_nullable_type_assertion_style/non_nullable_type_assertion_style.go +++ b/internal/rules/non_nullable_type_assertion_style/non_nullable_type_assertion_style.go @@ -91,9 +91,13 @@ var NonNullableTypeAssertionStyleRule = rule.Rule{ removeRange = node.Loc.WithEnd(expression.Pos()) } if higherPrecedenceThanUnary { - ctx.ReportNodeWithFixes(node, buildPreferNonNullAssertionMessage(), rule.RuleFixRemoveRange(removeRange), rule.RuleFixInsertAfter(expression, "!")) + ctx.ReportNodeWithFixes(node, buildPreferNonNullAssertionMessage(), func() []rule.RuleFix { + return []rule.RuleFix{rule.RuleFixRemoveRange(removeRange), rule.RuleFixInsertAfter(expression, "!")} + }) } else { - ctx.ReportNodeWithFixes(node, buildPreferNonNullAssertionMessage(), rule.RuleFixRemoveRange(removeRange), rule.RuleFixInsertBefore(ctx.SourceFile, expression, "("), rule.RuleFixInsertAfter(expression, ")!")) + ctx.ReportNodeWithFixes(node, buildPreferNonNullAssertionMessage(), func() []rule.RuleFix { + return []rule.RuleFix{rule.RuleFixRemoveRange(removeRange), rule.RuleFixInsertBefore(ctx.SourceFile, expression, "("), rule.RuleFixInsertAfter(expression, ")!")} + }) } } diff --git a/internal/rules/prefer_reduce_type_parameter/prefer_reduce_type_parameter.go b/internal/rules/prefer_reduce_type_parameter/prefer_reduce_type_parameter.go index d1190640..3961cbac 100644 --- a/internal/rules/prefer_reduce_type_parameter/prefer_reduce_type_parameter.go +++ b/internal/rules/prefer_reduce_type_parameter/prefer_reduce_type_parameter.go @@ -68,7 +68,7 @@ var PreferReduceTypeParameterRule = rule.Rule{ if expr.TypeArguments == nil { fixes = append(fixes, rule.RuleFixInsertAfter(callee, "<"+ctx.SourceFile.Text()[assertionType.Pos():assertionType.End()]+">")) } - ctx.ReportNodeWithFixes(secondArg, buildPreferTypeParameterMessage(), fixes...) + ctx.ReportNodeWithFixes(secondArg, buildPreferTypeParameterMessage(), func() []rule.RuleFix { return fixes }) }, } }, diff --git a/internal/rules/prefer_return_this_type/prefer_return_this_type.go b/internal/rules/prefer_return_this_type/prefer_return_this_type.go index 3fcb0078..28475b75 100644 --- a/internal/rules/prefer_return_this_type/prefer_return_this_type.go +++ b/internal/rules/prefer_return_this_type/prefer_return_this_type.go @@ -98,7 +98,7 @@ var PreferReturnThisTypeRule = rule.Rule{ } } - ctx.ReportNodeWithFixes(node, buildUseThisTypeMessage(), rule.RuleFixReplace(ctx.SourceFile, node, "this")) + ctx.ReportNodeWithFixes(node, buildUseThisTypeMessage(), func() []rule.RuleFix { return []rule.RuleFix{rule.RuleFixReplace(ctx.SourceFile, node, "this")} }) } return rule.RuleListeners{ diff --git a/internal/rules/promise_function_async/promise_function_async.go b/internal/rules/promise_function_async/promise_function_async.go index 08631f2e..f4ff7c61 100644 --- a/internal/rules/promise_function_async/promise_function_async.go +++ b/internal/rules/promise_function_async/promise_function_async.go @@ -133,7 +133,9 @@ var PromiseFunctionAsyncRule = rule.Rule{ insertAsyncBeforeNode = node.Name() } // TODO(port): getFunctionHeadLoc - ctx.ReportNodeWithFixes(node, buildMissingAsyncMessage(), rule.RuleFixInsertBefore(ctx.SourceFile, insertAsyncBeforeNode, " async ")) + ctx.ReportNodeWithFixes(node, buildMissingAsyncMessage(), func() []rule.RuleFix { + return []rule.RuleFix{rule.RuleFixInsertBefore(ctx.SourceFile, insertAsyncBeforeNode, " async ")} + }) } if *opts.CheckArrowFunctions { diff --git a/internal/rules/return_await/return_await.go b/internal/rules/return_await/return_await.go index 4fac68cc..bf9a715d 100644 --- a/internal/rules/return_await/return_await.go +++ b/internal/rules/return_await/return_await.go @@ -250,7 +250,7 @@ var ReturnAwaitRule = rule.Rule{ return } - ctx.ReportNodeWithFixes(node, buildNonPromiseAwaitMessage(), removeAwaitFix(node)) + ctx.ReportNodeWithFixes(node, buildNonPromiseAwaitMessage(), func() []rule.RuleFix { return []rule.RuleFix{removeAwaitFix(node)} }) } return } diff --git a/internal/rules/use_unknown_in_catch_callback_variable/use_unknown_in_catch_callback_variable.go b/internal/rules/use_unknown_in_catch_callback_variable/use_unknown_in_catch_callback_variable.go index 563463c3..4d469110 100644 --- a/internal/rules/use_unknown_in_catch_callback_variable/use_unknown_in_catch_callback_variable.go +++ b/internal/rules/use_unknown_in_catch_callback_variable/use_unknown_in_catch_callback_variable.go @@ -166,18 +166,22 @@ var UseUnknownInCatchCallbackVariableRule = rule.Rule{ if catchParam.DotDotDotToken != nil { if catchTypeAnnotation == nil { - ctx.ReportNodeWithSuggestions(catchParamNode, buildUseUnknownMessage(method), rule.RuleSuggestion{ - Message: buildAddUnknownRestTypeAnnotationSuggestionMessage(), - FixesArr: []rule.RuleFix{rule.RuleFixInsertAfter(catchVariable, ": [unknown]")}, + ctx.ReportNodeWithSuggestions(catchParamNode, buildUseUnknownMessage(method), func() []rule.RuleSuggestion { + return []rule.RuleSuggestion{{ + Message: buildAddUnknownRestTypeAnnotationSuggestionMessage(), + FixesArr: []rule.RuleFix{rule.RuleFixInsertAfter(catchVariable, ": [unknown]")}, + }} }) continue } - ctx.ReportNodeWithSuggestions(catchParamNode, buildUseUnknownMessage(method), rule.RuleSuggestion{ - Message: buildWrongRestTypeAnnotationSuggestionMessage(), - FixesArr: []rule.RuleFix{ - rule.RuleFixReplace(ctx.SourceFile, catchTypeAnnotation, "[unknown]"), - }, + ctx.ReportNodeWithSuggestions(catchParamNode, buildUseUnknownMessage(method), func() []rule.RuleSuggestion { + return []rule.RuleSuggestion{{ + Message: buildWrongRestTypeAnnotationSuggestionMessage(), + FixesArr: []rule.RuleFix{ + rule.RuleFixReplace(ctx.SourceFile, catchTypeAnnotation, "[unknown]"), + }, + }} }) continue } @@ -201,15 +205,19 @@ var UseUnknownInCatchCallbackVariableRule = rule.Rule{ } } - ctx.ReportNodeWithSuggestions(catchParamNode, buildUseUnknownMessage(method), rule.RuleSuggestion{ - Message: buildAddUnknownTypeAnnotationSuggestionMessage(), - FixesArr: fixes, + ctx.ReportNodeWithSuggestions(catchParamNode, buildUseUnknownMessage(method), func() []rule.RuleSuggestion { + return []rule.RuleSuggestion{{ + Message: buildAddUnknownTypeAnnotationSuggestionMessage(), + FixesArr: fixes, + }} }) break } - ctx.ReportNodeWithSuggestions(catchParamNode, buildUseUnknownMessage(method), rule.RuleSuggestion{ - Message: buildWrongTypeAnnotationSuggestionMessage(), - FixesArr: []rule.RuleFix{rule.RuleFixReplace(ctx.SourceFile, catchTypeAnnotation, "unknown")}, + ctx.ReportNodeWithSuggestions(catchParamNode, buildUseUnknownMessage(method), func() []rule.RuleSuggestion { + return []rule.RuleSuggestion{{ + Message: buildWrongTypeAnnotationSuggestionMessage(), + FixesArr: []rule.RuleFix{rule.RuleFixReplace(ctx.SourceFile, catchTypeAnnotation, "unknown")}, + }} }) case ast.KindArrayBindingPattern: ctx.ReportNode(catchParamNode, buildUseUnknownArrayDestructuringPatternMessage(method))