Documentation
¶
Index ¶
Constants ¶
This section is empty.
Variables ¶
View Source
var UnboundMethodRule = rule.Rule{ Name: "unbound-method", Run: func(ctx rule.RuleContext, options any) rule.RuleListeners { opts, ok := options.(UnboundMethodOptions) if !ok { opts = UnboundMethodOptions{} } if opts.IgnoreStatic == nil { opts.IgnoreStatic = utils.Ref(false) } isNativelyBound := func(object *ast.Node, property *ast.Node) bool { if ast.IsIdentifier(object) && ast.IsIdentifier(property) { objectSymbol := ctx.TypeChecker.GetSymbolAtLocation(object) notImported := objectSymbol != nil && isNotImported(objectSymbol, ctx.SourceFile) if notImported { if members, ok := nativelyBoundMembers[object.Text()]; ok { if _, ok := members[property.Text()]; ok { return true } } } } return utils.IsBuiltinSymbolLike(ctx.Program, ctx.TypeChecker, ctx.TypeChecker.GetTypeAtLocation(object), supportedGlobalTypes...) && utils.IsAnyBuiltinSymbolLike(ctx.Program, ctx.TypeChecker, ctx.TypeChecker.GetTypeAtLocation(property)) } checkIfMethodAndReport := func(node *ast.Node, symbol *ast.Symbol) bool { if symbol == nil { return false } dangerous, firstParamIsThis := checkIfMethod(symbol, *opts.IgnoreStatic) if !dangerous { return false } if firstParamIsThis { ctx.ReportNode(node, buildUnboundMessage()) } else { ctx.ReportNode(node, buildUnboundWithoutThisAnnotationMessage()) } return true } checkBindingProperty := func(patternNode *ast.Node, initNode *ast.Node, propertyName *ast.Node, parentIsAssignmentPatternLike bool) { if initNode != nil { if !isNativelyBound(initNode, propertyName) { reported := checkIfMethodAndReport(propertyName, checker.Checker_getPropertyOfType(ctx.TypeChecker, ctx.TypeChecker.GetTypeAtLocation(initNode), propertyName.Text())) if reported { return } } else if !parentIsAssignmentPatternLike { return } } utils.TypeRecurser(ctx.TypeChecker.GetTypeAtLocation(patternNode), func(t *checker.Type) bool { return checkIfMethodAndReport(propertyName, checker.Checker_getPropertyOfType(ctx.TypeChecker, t, propertyName.Text())) }) } return rule.RuleListeners{ ast.KindPropertyAccessExpression: func(node *ast.Node) { if isSafeUse(node) || isNativelyBound(node.Expression(), node.Name()) { return } checkIfMethodAndReport(node, ctx.TypeChecker.GetSymbolAtLocation(node)) }, rule.ListenerOnAllowPattern(ast.KindObjectLiteralExpression): func(node *ast.Node) { if !ast.IsAssignmentExpression(node.Parent, true) { return } initNode := node.Parent.AsBinaryExpression().Right for _, property := range node.AsObjectLiteralExpression().Properties.Nodes { if !ast.IsPropertyAssignment(property) && !ast.IsShorthandPropertyAssignment(property) { continue } checkBindingProperty(node, initNode, property.Name(), true) } }, ast.KindObjectBindingPattern: func(node *ast.Node) { if isNodeInsideTypeDeclaration(node) { return } var initNode *ast.Node parentIsAssignmentPatternLike := ast.IsBindingElement(node.Parent) || ast.IsParameter(node.Parent) if ast.IsVariableDeclaration(node.Parent) || parentIsAssignmentPatternLike { initNode = node.Parent.Initializer() } for _, property := range node.AsBindingPattern().Elements.Nodes { if !ast.IsBindingElement(property) { continue } bindingElem := property.AsBindingElement() propertyName := bindingElem.PropertyName if propertyName == nil { propertyName = bindingElem.Name() } if bindingElem.DotDotDotToken != nil || !ast.IsIdentifier(propertyName) { continue } checkBindingProperty(node, initNode, propertyName, parentIsAssignmentPatternLike) } }, } }, }
Functions ¶
This section is empty.
Types ¶
type UnboundMethodOptions ¶
type UnboundMethodOptions struct {
IgnoreStatic *bool
}
Click to show internal directories.
Click to hide internal directories.