Skip to content

Commit

Permalink
feat: ESLint v9 Support (#7543)
Browse files Browse the repository at this point in the history
* update to latest packages

* remove duplicated test case

* fix rule types

* migrate to `sourceCode.getAncestors`

* rename type

* remove unused export

---------

Co-authored-by: Dominik Dorfmeister <office@dorfmeister.cc>
  • Loading branch information
davidjbng and TkDodo committed Jun 10, 2024
1 parent a42a2ed commit 1c0d0f0
Show file tree
Hide file tree
Showing 11 changed files with 437 additions and 211 deletions.
8 changes: 4 additions & 4 deletions packages/eslint-plugin-query/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -46,13 +46,13 @@
"src"
],
"dependencies": {
"@typescript-eslint/utils": "^6.20.0"
"@typescript-eslint/utils": "8.0.0-alpha.28"
},
"devDependencies": {
"@typescript-eslint/rule-tester": "^6.20.0",
"eslint": "^8.56.0"
"@typescript-eslint/rule-tester": "8.0.0-alpha.28",
"eslint": "^9.4.0"
},
"peerDependencies": {
"eslint": "^8.0.0"
"eslint": "^8.0.0 | ^9.0.0"
}
}
27 changes: 0 additions & 27 deletions packages/eslint-plugin-query/src/__tests__/exhaustive-deps.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -679,33 +679,6 @@ ruleTester.run('exhaustive-deps', rule, {
},
],
},
{
name: 'should fail when a queryKey is a reference of an array expression with a missing dep',
code: normalizeIndent`
const x = 5;
const queryKey = ['foo']
useQuery({ queryKey, queryFn: () => x })
`,
errors: [
{
messageId: 'missingDeps',
data: { deps: 'x' },
suggestions: [
{
messageId: 'fixTo',
data: {
result: "['foo', x]",
},
output: normalizeIndent`
const x = 5;
const queryKey = ['foo', x]
useQuery({ queryKey, queryFn: () => x })
`,
},
],
},
],
},
{
name: 'should fail when queryKey is a queryKeyFactory while having missing dep',
code: normalizeIndent`
Expand Down
5 changes: 3 additions & 2 deletions packages/eslint-plugin-query/src/configs.ts
Original file line number Diff line number Diff line change
@@ -1,18 +1,19 @@
import { rules } from './rules'
import type { ESLintUtils } from '@typescript-eslint/utils'
import type { ExtraRuleDocs } from './types'

function generateRecommendedConfig(
allRules: Record<
string,
ESLintUtils.RuleModule<
string,
ReadonlyArray<unknown>,
ExtraRuleDocs,
ESLintUtils.RuleListener
>
>,
) {
return Object.entries(allRules).reduce(
// @ts-expect-error
(memo, [name, rule]) => {
const { recommended } = rule.meta.docs || {}

Expand All @@ -21,7 +22,7 @@ function generateRecommendedConfig(
...(recommended ? { [`@tanstack/query/${name}`]: recommended } : {}),
}
},
{} as Record<string, 'strict' | 'error' | 'warn'>,
{} as Record<string, ExtraRuleDocs['recommended']>,
)
}

Expand Down
2 changes: 2 additions & 0 deletions packages/eslint-plugin-query/src/rules.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,14 @@ import * as exhaustiveDeps from './rules/exhaustive-deps/exhaustive-deps.rule'
import * as stableQueryClient from './rules/stable-query-client/stable-query-client.rule'
import * as noRestDestructuring from './rules/no-rest-destructuring/no-rest-destructuring.rule'
import type { ESLintUtils } from '@typescript-eslint/utils'
import type { ExtraRuleDocs } from './types'

export const rules: Record<
string,
ESLintUtils.RuleModule<
string,
ReadonlyArray<unknown>,
ExtraRuleDocs,
ESLintUtils.RuleListener
>
> = {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,21 +5,22 @@ import { uniqueBy } from '../../utils/unique-by'
import { detectTanstackQueryImports } from '../../utils/detect-react-query-imports'
import { ExhaustiveDepsUtils } from './exhaustive-deps.utils'
import type { TSESLint } from '@typescript-eslint/utils'
import type { ExtraRuleDocs } from '../../types'

const QUERY_KEY = 'queryKey'
const QUERY_FN = 'queryFn'

export const name = 'exhaustive-deps'

const createRule = ESLintUtils.RuleCreator(getDocsUrl)
const createRule = ESLintUtils.RuleCreator<ExtraRuleDocs>(getDocsUrl)

export const rule = createRule({
name,
meta: {
type: 'problem',
docs: {
description: 'Exhaustive deps rule for useQuery',
recommended: 'error' as any,
recommended: 'error',
},
messages: {
missingDeps: `The following dependencies are missing in your queryKey: {{deps}}`,
Expand Down Expand Up @@ -92,9 +93,10 @@ export const rule = createRule({

const relevantRefs = externalRefs.filter((reference) =>
ExhaustiveDepsUtils.isRelevantReference({
context,
sourceCode: context.sourceCode,
reference,
scopeManager,
node: queryFn.value,
}),
)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,13 @@ import type { TSESLint, TSESTree } from '@typescript-eslint/utils'

export const ExhaustiveDepsUtils = {
isRelevantReference(params: {
context: Readonly<TSESLint.RuleContext<string, ReadonlyArray<unknown>>>
sourceCode: Readonly<TSESLint.SourceCode>
reference: TSESLint.Scope.Reference
scopeManager: TSESLint.Scope.ScopeManager
node: TSESTree.Node
}) {
const { reference, scopeManager, context } = params
const component = ASTUtils.getFunctionAncestor(context)
const { sourceCode, reference, scopeManager, node } = params
const component = ASTUtils.getFunctionAncestor(sourceCode, node)

if (
component !== undefined &&
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,20 +3,21 @@ import { getDocsUrl } from '../../utils/get-docs-url'
import { ASTUtils } from '../../utils/ast-utils'
import { detectTanstackQueryImports } from '../../utils/detect-react-query-imports'
import { NoRestDestructuringUtils } from './no-rest-destructuring.utils'
import type { ExtraRuleDocs } from '../../types'

export const name = 'no-rest-destructuring'

const queryHooks = ['useQuery', 'useQueries', 'useInfiniteQuery']

const createRule = ESLintUtils.RuleCreator(getDocsUrl)
const createRule = ESLintUtils.RuleCreator<ExtraRuleDocs>(getDocsUrl)

export const rule = createRule({
name,
meta: {
type: 'problem',
docs: {
description: 'Disallows rest destructuring in queries',
recommended: 'warn' as any,
recommended: 'warn',
},
messages: {
objectRestDestructure: `Object rest destructuring on a query will observe all changes to the query, leading to excessive re-renders.`,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,18 +3,19 @@ import { ASTUtils } from '../../utils/ast-utils'
import { getDocsUrl } from '../../utils/get-docs-url'
import { detectTanstackQueryImports } from '../../utils/detect-react-query-imports'
import type { TSESLint } from '@typescript-eslint/utils'
import type { ExtraRuleDocs } from '../../types'

export const name = 'stable-query-client'

const createRule = ESLintUtils.RuleCreator(getDocsUrl)
const createRule = ESLintUtils.RuleCreator<ExtraRuleDocs>(getDocsUrl)

export const rule = createRule({
name,
meta: {
type: 'problem',
docs: {
description: 'Makes sure that QueryClient is stable',
recommended: 'error' as any,
recommended: 'error',
},
messages: {
unstable: [
Expand Down Expand Up @@ -44,7 +45,10 @@ export const rule = createRule({
return
}

const fnAncestor = ASTUtils.getFunctionAncestor(context)
const fnAncestor = ASTUtils.getFunctionAncestor(
context.sourceCode,
node,
)
const isReactServerComponent = fnAncestor?.async === true

if (
Expand Down
3 changes: 3 additions & 0 deletions packages/eslint-plugin-query/src/types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export type ExtraRuleDocs = {
recommended: 'strict' | 'error' | 'warn'
}
5 changes: 3 additions & 2 deletions packages/eslint-plugin-query/src/utils/ast-utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -219,9 +219,10 @@ export const ASTUtils = {
)
},
getFunctionAncestor(
context: Readonly<TSESLint.RuleContext<string, ReadonlyArray<unknown>>>,
sourceCode: Readonly<TSESLint.SourceCode>,
node: TSESTree.Node,
) {
for (const ancestor of context.getAncestors()) {
for (const ancestor of sourceCode.getAncestors(node)) {
if (ancestor.type === AST_NODE_TYPES.FunctionDeclaration) {
return ancestor
}
Expand Down
Loading

0 comments on commit 1c0d0f0

Please sign in to comment.