unbound_method

package
v0.0.0-...-4178710 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jul 13, 2025 License: MIT Imports: 4 Imported by: 0

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
}

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL