Skip to content

Commit

Permalink
fix(eslint-plugin): improve object property checks (#5079)
Browse files Browse the repository at this point in the history
* fix(eslint-plugin): improve object property checks

* prettier
  • Loading branch information
Newbie012 authored Mar 6, 2023
1 parent d86e343 commit df512e5
Show file tree
Hide file tree
Showing 3 changed files with 54 additions and 8 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,7 @@ export const rule = createRule({
const queryKeyValue = queryKeyNode
const refs = ASTUtils.getExternalRefs({
scopeManager,
sourceCode,
node: queryFn.value,
})

Expand All @@ -104,7 +105,8 @@ export const rule = createRule({
return (
!ref.isTypeReference &&
!ASTUtils.isAncestorIsCallee(ref.identifier) &&
!existingKeys.some((existingKey) => existingKey === text)
!existingKeys.some((existingKey) => existingKey === text) &&
!existingKeys.includes(text.split('.')[0] ?? '')
)
})
.map(({ ref, text }) => ({
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ ruleTester.run('exhaustive-deps', rule, {
type Result = {};
function MyComponent(props) {
useQuery({
queryKey: ["foo", dep1],
queryKey: ["foo", dep],
queryFn: () => api.get<Result>(dep),
});
}
Expand Down Expand Up @@ -236,6 +236,17 @@ ruleTester.run('exhaustive-deps', rule, {
}
`,
},
{
name: 'should not fail if queryKey is having the whole object while queryFn uses some props of it',
code: normalizeIndent`
const state = { foo: 'foo', bar: 'bar' }
useQuery({
queryKey: ['state', state],
queryFn: () => Promise.resolve({ foo: state.foo, bar: state.bar })
})
`,
},
],
invalid: [
{
Expand Down Expand Up @@ -560,5 +571,22 @@ ruleTester.run('exhaustive-deps', rule, {
},
],
},
{
name: 'should fail if queryFn is using multiple object props when only one of them is in the queryKey',
code: normalizeIndent`
const state = { foo: 'foo', bar: 'bar' }
useQuery({
queryKey: ['state', state.foo],
queryFn: () => Promise.resolve({ foo: state.foo, bar: state.bar })
})
`,
errors: [
{
messageId: 'missingDeps',
data: { deps: 'state.bar' },
},
],
},
],
})
28 changes: 22 additions & 6 deletions packages/eslint-plugin-query/src/utils/ast-utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -142,24 +142,40 @@ export const ASTUtils = {
},
getExternalRefs(params: {
scopeManager: TSESLint.Scope.ScopeManager
sourceCode: Readonly<TSESLint.SourceCode>
node: TSESTree.Node
}): TSESLint.Scope.Reference[] {
const { scopeManager, node } = params
const { scopeManager, sourceCode, node } = params
const scope = scopeManager.acquire(node)

if (scope === null) {
return []
}

const readOnlyRefs = scope.references.filter((x) => x.isRead())
const references = scope.references
.filter((x) => x.isRead())
.map((x) => {
const referenceNode = ASTUtils.traverseUpOnly(x.identifier, [
AST_NODE_TYPES.MemberExpression,
AST_NODE_TYPES.Identifier,
])

return {
variable: x,
node: referenceNode,
text: sourceCode.getText(referenceNode),
}
})

const localRefIds = new Set(
[...scope.set.values()].map((x) => x.identifiers[0]),
[...scope.set.values()].map((x) => sourceCode.getText(x.identifiers[0])),
)
const externalRefs = readOnlyRefs.filter(
(x) => x.resolved === null || !localRefIds.has(x.resolved.identifiers[0]),

const externalRefs = references.filter(
(x) => x.variable.resolved === null || !localRefIds.has(x.text),
)

return uniqueBy(externalRefs, (x) => x.resolved)
return uniqueBy(externalRefs, (x) => x.text).map((x) => x.variable)
},
mapKeyNodeToText(
node: TSESTree.Node,
Expand Down

0 comments on commit df512e5

Please sign in to comment.