Documentation
¶
Index ¶
Constants ¶
This section is empty.
Variables ¶
View Source
var NoImplicitCoercionRule = rule.Rule{ Name: "no-implicit-coercion", Run: func(ctx rule.RuleContext, rawOptions any) rule.RuleListeners { opts := parseOptions(rawOptions) report := func(node *ast.Node, recommendation string, shouldSuggest, shouldFix bool) { msg := rule.RuleMessage{ Id: "implicitCoercion", Description: "Unexpected implicit coercion encountered. Use `" + recommendation + "` instead.", } replacement := recommendation start := utils.TrimNodeTextRange(ctx.SourceFile, node).Pos() if utils.NeedsLeadingSpaceForReplacement(ctx.SourceFile.Text(), start, recommendation) { replacement = " " + recommendation } if shouldFix { ctx.ReportNodeWithFixes(node, msg, rule.RuleFixReplace(ctx.SourceFile, node, replacement)) return } if shouldSuggest { ctx.ReportNodeWithSuggestions(node, msg, rule.RuleSuggestion{ Message: rule.RuleMessage{ Id: "useRecommendation", Description: "Use `" + recommendation + "` instead.", }, FixesArr: []rule.RuleFix{rule.RuleFixReplace(ctx.SourceFile, node, replacement)}, }) return } ctx.ReportNode(node, msg) } checkUnary := func(node *ast.Node) { pue := node.AsPrefixUnaryExpression() if pue == nil || pue.Operand == nil { return } if opts.boolean && !opts.allow.Has("!!") && isDoubleLogicalNegating(pue) { innerPue := ast.SkipParentheses(pue.Operand).AsPrefixUnaryExpression() target := ast.SkipParentheses(innerPue.Operand) recommendation := "Boolean(" + utils.TrimmedNodeText(ctx.SourceFile, target) + ")" shouldFix := !utils.IsShadowed(node, "Boolean") report(node, recommendation, true, shouldFix) } if opts.boolean && !opts.allow.Has("~") && isBinaryNegatingOfIndexOf(pue) { callNode := ast.SkipParentheses(pue.Operand) comparison := "!== -1" if ast.IsOptionalChain(callNode) { comparison = ">= 0" } recommendation := utils.TrimmedNodeText(ctx.SourceFile, callNode) + " " + comparison report(node, recommendation, false, false) } if opts.number && !opts.allow.Has("+") && pue.Operator == ast.KindPlusToken { operand := ast.SkipParentheses(pue.Operand) if !isNumeric(operand) { recommendation := "Number(" + utils.TrimmedNodeText(ctx.SourceFile, operand) + ")" report(node, recommendation, true, false) } } if opts.number && !opts.allow.Has("- -") && pue.Operator == ast.KindMinusToken { inner := ast.SkipParentheses(pue.Operand) if inner != nil && inner.Kind == ast.KindPrefixUnaryExpression { innerPue := inner.AsPrefixUnaryExpression() operand := ast.SkipParentheses(innerPue.Operand) if innerPue.Operator == ast.KindMinusToken && !isNumeric(operand) { recommendation := "Number(" + utils.TrimmedNodeText(ctx.SourceFile, operand) + ")" report(node, recommendation, true, false) } } } } checkBinary := func(node *ast.Node) { bin := node.AsBinaryExpression() if bin == nil || bin.OperatorToken == nil { return } switch bin.OperatorToken.Kind { case ast.KindAsteriskToken: if opts.number && !opts.allow.Has("*") && isMultiplyByOne(bin) && !isMultiplyByFractionOfOne(node) { if operand := getNonNumericOperand(bin); operand != nil { recommendation := "Number(" + utils.TrimmedNodeText(ctx.SourceFile, operand) + ")" report(node, recommendation, true, false) } } case ast.KindMinusToken: if opts.number && !opts.allow.Has("-") { left := ast.SkipParentheses(bin.Left) if isLiteralZero(ast.SkipParentheses(bin.Right)) && !isNumeric(left) { recommendation := "Number(" + utils.TrimmedNodeText(ctx.SourceFile, left) + ")" report(node, recommendation, true, false) } } case ast.KindPlusToken: if opts.str && !opts.allow.Has("+") && isConcatWithEmptyString(bin) { operand := ast.SkipParentheses(getNonEmptyOperand(bin)) recommendation := "String(" + utils.TrimmedNodeText(ctx.SourceFile, operand) + ")" report(node, recommendation, true, false) } case ast.KindPlusEqualsToken: if opts.str && !opts.allow.Has("+") && isEmptyString(ast.SkipParentheses(bin.Right)) { leftText := utils.TrimmedNodeText(ctx.SourceFile, ast.SkipParentheses(bin.Left)) recommendation := leftText + " = String(" + leftText + ")" report(node, recommendation, true, false) } } } checkTemplate := func(node *ast.Node) { if !opts.disallowTemplateShorthand { return } if node.Parent != nil && node.Parent.Kind == ast.KindTaggedTemplateExpression { return } te := node.AsTemplateExpression() if te == nil || te.Head == nil || te.TemplateSpans == nil { return } if len(te.TemplateSpans.Nodes) != 1 || te.Head.Text() != "" { return } span := te.TemplateSpans.Nodes[0].AsTemplateSpan() if span == nil || span.Literal == nil || span.Expression == nil || span.Literal.Text() != "" { return } expr := ast.SkipParentheses(span.Expression) if isStringType(expr) { return } recommendation := "String(" + utils.TrimmedNodeText(ctx.SourceFile, expr) + ")" report(node, recommendation, true, false) } return rule.RuleListeners{ ast.KindPrefixUnaryExpression: checkUnary, rule.ListenerOnExit(ast.KindBinaryExpression): checkBinary, ast.KindTemplateExpression: checkTemplate, } }, }
NoImplicitCoercionRule disallows shorthand type conversions, suggesting explicit `Boolean()` / `Number()` / `String()` calls instead. https://eslint.org/docs/latest/rules/no-implicit-coercion
Functions ¶
This section is empty.
Types ¶
This section is empty.
Click to show internal directories.
Click to hide internal directories.