exhaustive_deps

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: 11 Imported by: 0

Documentation

Overview

Package exhaustive_deps implements the rslint port of upstream `react-hooks/exhaustive-deps`.

The upstream rule (facebook/react/packages/eslint-plugin-react-hooks) leans heavily on ESLint's scope manager: every Identifier reference is preresolved to a Variable, references inside a callback can be enumerated by walking the callback's Scope.references, and references across the entire file get a `from` Scope and `resolved` Variable. rslint has no scope manager. Instead we resolve identifiers via the TypeChecker (`GetSymbolAtLocation`), then look at the symbol's declaration to infer scope membership. When the TypeChecker is unavailable (gap files, parse errors), we fall back to a name-based best-effort: scan the call's enclosing function for declarations matching the identifier text, and treat anything else as external.

The diagnostics intentionally mirror upstream's wording so consumers of the JS rule can switch over without rewriting message assertions. The autofix and suggestion shapes also mirror upstream — replacing the deps-array text wholesale, or inserting a deps array after the callback when none was provided.

Index

Constants

This section is empty.

Variables

View Source
var ExhaustiveDepsRule = rule.Rule{
	Name: "react-hooks/exhaustive-deps",
	Run: func(ctx rule.RuleContext, options any) rule.RuleListeners {
		opts := parseOptions(options, ctx.Settings)
		sf := ctx.SourceFile
		tc := ctx.TypeChecker

		caches := &runCaches{
			extraWrite:    map[*ast.Symbol]bool{},
			currentAssign: map[*ast.Symbol]bool{},
			usedOutside:   map[*ast.Node]bool{},
		}

		report := func(node *ast.Node, msg string) {
			ctx.ReportNode(node, rule.RuleMessage{Description: msg})
		}
		reportWithSuggestions := func(node *ast.Node, msg string, sugs ...rule.RuleSuggestion) {
			if opts.EnableDangerousAutofixThisMayCauseInfiniteLoops && len(sugs) > 0 && len(sugs[0].FixesArr) > 0 {

				firstFix := []rule.RuleFix{sugs[0].FixesArr[0]}
				if ctx.ReportNodeWithFixesAndSuggestions != nil {
					ctx.ReportNodeWithFixesAndSuggestions(node, rule.RuleMessage{Description: msg}, firstFix, sugs)
					return
				}
				ctx.ReportNodeWithFixes(node, rule.RuleMessage{Description: msg}, firstFix...)
				return
			}
			if len(sugs) == 0 {
				ctx.ReportNode(node, rule.RuleMessage{Description: msg})
				return
			}
			ctx.ReportNodeWithSuggestions(node, rule.RuleMessage{Description: msg}, sugs...)
		}

		return rule.RuleListeners{
			ast.KindCallExpression: func(node *ast.Node) {
				visitCall(ctx, sf, tc, opts, caches, node, report, reportWithSuggestions)
			},
		}
	},
}

ExhaustiveDepsRule is the rslint port of upstream `react-hooks/exhaustive-deps`.

Architectural difference from upstream: instead of relying on ESLint's scope manager to enumerate `scope.references`, we walk the callback body and resolve each Identifier reference via the TypeChecker. The "pure scope" check (does this identifier resolve to a binding declared outside the callback but inside the component?) is encoded as `containsNode(componentBody, declSite) && !containsNode(callback, declSite)`. When the TypeChecker is unavailable, the same check degrades to a best-effort name walk over the component body.

Diagnostics intentionally mirror upstream wording for switchover parity.

Functions

This section is empty.

Types

type Options

type Options struct {
	AdditionalHooks                                 *regexp.Regexp
	EnableDangerousAutofixThisMayCauseInfiniteLoops bool
	RequireExplicitEffectDeps                       bool
	// AutoDepsHooks: experimental_autoDependenciesHooks. When the hook's
	// bare name is in this list, missing deps are inferred ("auto deps")
	// rather than being flagged. Mirrors upstream's same-named option.
	AutoDepsHooks map[string]bool
}

Options holds the parsed rule options.

Jump to

Keyboard shortcuts

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