no_unsafe

package
v0.5.3 Latest Latest
Warning

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

Go to latest
Published: May 14, 2026 License: MIT Imports: 4 Imported by: 0

Documentation

Index

Constants

This section is empty.

Variables

View Source
var NoUnsafeRule = rule.Rule{
	Name: "react/no-unsafe",
	Run: func(ctx rule.RuleContext, options any) rule.RuleListeners {

		if reactutil.ReactVersionLessThan(ctx.Settings, 16, 3, 0) {
			return rule.RuleListeners{}
		}

		checkAliases := parseOptions(options)
		unsafeMap := buildUnsafeMap(checkAliases)
		pragma := reactutil.GetReactPragma(ctx.Settings)
		createClass := reactutil.GetReactCreateClass(ctx.Settings)

		checkLifeCycleMethods := func(members []*ast.Node) {
			counts := map[string]int{}
			firstNode := map[string]*ast.Node{}
			// First pass: count occurrences and remember first node per name.
			// Order of first appearance is recorded by the slice below so
			// our output order is deterministic and matches a source-order
			// (== ESLint reporter (line,column)) walk.
			var orderedNames []string
			for _, m := range members {
				if m == nil {
					continue
				}
				name := memberKeyName(m)
				if name == "" {
					continue
				}
				if _, ok := unsafeMap[name]; !ok {
					continue
				}
				if _, seen := firstNode[name]; !seen {
					firstNode[name] = m
					orderedNames = append(orderedNames, name)
				}
				counts[name]++
			}

			for _, name := range orderedNames {
				meta := unsafeMap[name]
				node := firstNode[name]
				for range counts[name] {
					ctx.ReportNode(node, rule.RuleMessage{
						Id:          "unsafeMethod",
						Description: formatMessage(name, meta),
					})
				}
			}
		}

		isES5Component := func(obj *ast.Node) bool {
			if obj == nil || obj.Kind != ast.KindObjectLiteralExpression {
				return false
			}
			cur := obj
			for cur.Parent != nil && cur.Parent.Kind == ast.KindParenthesizedExpression {
				cur = cur.Parent
			}
			parent := cur.Parent
			if parent == nil {
				return false
			}
			var calleeExpr *ast.Node
			var args *ast.NodeList
			switch parent.Kind {
			case ast.KindCallExpression:
				ce := parent.AsCallExpression()
				calleeExpr = ce.Expression
				args = ce.Arguments
			case ast.KindNewExpression:
				ne := parent.AsNewExpression()
				calleeExpr = ne.Expression
				args = ne.Arguments
			default:
				return false
			}

			if args == nil {
				return false
			}
			inArgs := false
			for _, arg := range args.Nodes {
				if arg == cur {
					inArgs = true
					break
				}
			}
			if !inArgs {
				return false
			}

			callee := ast.SkipParentheses(calleeExpr)
			switch callee.Kind {
			case ast.KindIdentifier:
				return callee.AsIdentifier().Text == createClass
			case ast.KindPropertyAccessExpression:
				pa := callee.AsPropertyAccessExpression()
				obj := ast.SkipParentheses(pa.Expression)
				if obj.Kind != ast.KindIdentifier || obj.AsIdentifier().Text != pragma {
					return false
				}
				name := pa.Name()
				if name == nil || name.Kind != ast.KindIdentifier {
					return false
				}
				return name.AsIdentifier().Text == createClass
			}
			return false
		}

		return rule.RuleListeners{
			ast.KindClassDeclaration: func(node *ast.Node) {
				if !reactutil.ExtendsReactComponent(node, pragma) {
					return
				}
				checkLifeCycleMethods(node.Members())
			},
			ast.KindClassExpression: func(node *ast.Node) {
				if !reactutil.ExtendsReactComponent(node, pragma) {
					return
				}
				checkLifeCycleMethods(node.Members())
			},
			ast.KindObjectLiteralExpression: func(node *ast.Node) {
				if !isES5Component(node) {
					return
				}
				ol := node.AsObjectLiteralExpression()
				if ol == nil || ol.Properties == nil {
					return
				}
				checkLifeCycleMethods(ol.Properties.Nodes)
			},
		}
	},
}

Functions

This section is empty.

Types

This section is empty.

Jump to

Keyboard shortcuts

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