Documentation
¶
Index ¶
Constants ¶
This section is empty.
Variables ¶
View Source
var NoExtraBindRule = rule.Rule{ Name: "no-extra-bind", Run: func(ctx rule.RuleContext, options any) rule.RuleListeners { type scopeInfo struct { match *bindMatch thisFound bool upper *scopeInfo } var scope *scopeInfo getBindMatch := func(funcNode *ast.Node) *bindMatch { current := funcNode.Parent for current != nil && current.Kind == ast.KindParenthesizedExpression { current = current.Parent } if current == nil { return nil } var memberNode *ast.Node switch current.Kind { case ast.KindPropertyAccessExpression: propAccess := current.AsPropertyAccessExpression() if propAccess == nil || propAccess.Name() == nil { return nil } if propAccess.Name().Text() != "bind" { return nil } memberNode = current case ast.KindElementAccessExpression: elemAccess := current.AsElementAccessExpression() if elemAccess == nil || elemAccess.ArgumentExpression == nil { return nil } arg := elemAccess.ArgumentExpression if arg.Kind == ast.KindStringLiteral && arg.Text() == "bind" { memberNode = current } else if arg.Kind == ast.KindNoSubstitutionTemplateLiteral && arg.Text() == "bind" { memberNode = current } else { return nil } default: return nil } callParent := memberNode.Parent for callParent != nil && callParent.Kind == ast.KindParenthesizedExpression { callParent = callParent.Parent } if callParent == nil || callParent.Kind != ast.KindCallExpression { return nil } callExpr := callParent.AsCallExpression() if callExpr == nil { return nil } callee := callExpr.Expression for callee != nil && callee.Kind == ast.KindParenthesizedExpression { callee = callee.AsParenthesizedExpression().Expression } if callee != memberNode { return nil } argCount := 0 if callExpr.Arguments != nil { argCount = len(callExpr.Arguments.Nodes) } if argCount != 1 { return nil } firstArg := callExpr.Arguments.Nodes[0] if firstArg.Kind == ast.KindSpreadElement { return nil } return &bindMatch{callNode: callParent, memberNode: memberNode} } msg := rule.RuleMessage{ Id: "unexpected", Description: "The function binding is unnecessary.", } buildFixes := func(m *bindMatch) []rule.RuleFix { callExpr := m.callNode.AsCallExpression() firstArg := callExpr.Arguments.Nodes[0] if !isSideEffectFree(firstArg) { return nil } // The expression to keep (left side of the member access) var keepExpr *ast.Node switch m.memberNode.Kind { case ast.KindPropertyAccessExpression: keepExpr = m.memberNode.AsPropertyAccessExpression().Expression case ast.KindElementAccessExpression: keepExpr = m.memberNode.AsElementAccessExpression().Expression } if keepExpr == nil { return nil } sourceText := ctx.SourceFile.Text() tokenStart := scanner.SkipTrivia(sourceText, keepExpr.End()) fix1 := rule.RuleFixRemoveRange(core.NewTextRange(tokenStart, m.memberNode.End())) fix2 := rule.RuleFixRemoveRange(core.NewTextRange(callExpr.Expression.End(), m.callNode.End())) return []rule.RuleFix{fix1, fix2} } report := func(m *bindMatch) { if fixes := buildFixes(m); len(fixes) > 0 { ctx.ReportNodeWithFixes(m.callNode, msg, fixes...) } else { ctx.ReportNode(m.callNode, msg) } } enterFunction := func(node *ast.Node) { scope = &scopeInfo{ match: getBindMatch(node), thisFound: false, upper: scope, } } exitFunction := func(node *ast.Node) { if scope != nil { if scope.match != nil && !scope.thisFound { report(scope.match) } scope = scope.upper } } enterThisScope := func(node *ast.Node) { scope = &scopeInfo{ match: nil, thisFound: false, upper: scope, } } exitThisScope := func(node *ast.Node) { if scope != nil { scope = scope.upper } } return rule.RuleListeners{ ast.KindFunctionExpression: enterFunction, rule.ListenerOnExit(ast.KindFunctionExpression): exitFunction, ast.KindFunctionDeclaration: enterFunction, rule.ListenerOnExit(ast.KindFunctionDeclaration): exitFunction, ast.KindMethodDeclaration: enterThisScope, rule.ListenerOnExit(ast.KindMethodDeclaration): exitThisScope, ast.KindGetAccessor: enterThisScope, rule.ListenerOnExit(ast.KindGetAccessor): exitThisScope, ast.KindSetAccessor: enterThisScope, rule.ListenerOnExit(ast.KindSetAccessor): exitThisScope, ast.KindConstructor: enterThisScope, rule.ListenerOnExit(ast.KindConstructor): exitThisScope, ast.KindArrowFunction: func(node *ast.Node) { if m := getBindMatch(node); m != nil { report(m) } }, ast.KindThisKeyword: func(node *ast.Node) { if scope == nil { return } target := scope if isThisInComputedPropertyName(node) && scope.upper != nil { target = scope.upper } target.thisFound = true }, } }, }
Functions ¶
This section is empty.
Types ¶
This section is empty.
Click to show internal directories.
Click to hide internal directories.