From d1e318051f10b7c9b0b6bd8f0df70fd730208eeb Mon Sep 17 00:00:00 2001 From: Yaacov Rydzinski Date: Tue, 31 May 2022 02:58:52 +0000 Subject: [PATCH] use named parameters for node visit context info --- docs-old/APIReference-Language.md | 4 +- src/language/__tests__/visitor-test.ts | 14 +++---- src/language/visitor.ts | 45 +++++++++------------ src/validation/rules/KnownDirectivesRule.ts | 2 +- src/validation/rules/KnownTypeNamesRule.ts | 2 +- 5 files changed, 30 insertions(+), 37 deletions(-) diff --git a/docs-old/APIReference-Language.md b/docs-old/APIReference-Language.md index 4d430c3787..f8000f03ed 100644 --- a/docs-old/APIReference-Language.md +++ b/docs-old/APIReference-Language.md @@ -215,7 +215,7 @@ visit function. ```js var editedAST = visit(ast, { - enter(node, key, parent, path, ancestors) { + enter(node, { key, parent, path, ancestors }) { // @return // undefined: no action // false: skip visiting this node @@ -223,7 +223,7 @@ var editedAST = visit(ast, { // null: delete this node // any value: replace this node with the returned value }, - leave(node, key, parent, path, ancestors) { + leave(node, { key, parent, path, ancestors }) { // @return // undefined: no action // false: no action diff --git a/src/language/__tests__/visitor-test.ts b/src/language/__tests__/visitor-test.ts index 9149b103e3..369963a35d 100644 --- a/src/language/__tests__/visitor-test.ts +++ b/src/language/__tests__/visitor-test.ts @@ -11,7 +11,7 @@ import type { ASTVisitor, ASTVisitorKeyMap } from '../visitor'; import { BREAK, visit, visitInParallel } from '../visitor'; function checkVisitorFnArgs(ast: any, args: any, isEdited: boolean = false) { - const [node, key, parent, path, ancestors] = args; + const [node, { key, parent, path, ancestors }] = args; expect(node).to.be.an.instanceof(Object); expect(node.kind).to.be.oneOf(Object.values(Kind)); @@ -67,11 +67,11 @@ describe('Visitor', () => { const ast = parse('{ a }', { noLocation: true }); visit(ast, { - enter(_node, _key, _parent, path) { + enter(_node, { path }) { checkVisitorFnArgs(ast, arguments); visited.push(['enter', path.slice()]); }, - leave(_node, _key, _parent, path) { + leave(_node, { path }) { checkVisitorFnArgs(ast, arguments); visited.push(['leave', path.slice()]); }, @@ -96,7 +96,7 @@ describe('Visitor', () => { const visitedNodes: Array = []; visit(ast, { - enter(node, key, parent, _path, ancestors) { + enter(node, { key, parent, ancestors }) { const inArray = typeof key === 'number'; if (inArray) { visitedNodes.push(parent); @@ -106,7 +106,7 @@ describe('Visitor', () => { const expectedAncestors = visitedNodes.slice(0, -2); expect(ancestors).to.deep.equal(expectedAncestors); }, - leave(_node, key, _parent, _path, ancestors) { + leave(_node, { key, ancestors }) { const expectedAncestors = visitedNodes.slice(0, -2); expect(ancestors).to.deep.equal(expectedAncestors); @@ -511,7 +511,7 @@ describe('Visitor', () => { const argsStack: Array = []; visit(ast, { - enter(node, key, parent) { + enter(node, { key, parent }) { visited.push([ 'enter', node.kind, @@ -523,7 +523,7 @@ describe('Visitor', () => { argsStack.push([...arguments]); }, - leave(node, key, parent) { + leave(node, { key, parent }) { visited.push([ 'leave', node.kind, diff --git a/src/language/visitor.ts b/src/language/visitor.ts index 3b38c8a36c..e511c6175e 100644 --- a/src/language/visitor.ts +++ b/src/language/visitor.ts @@ -22,25 +22,29 @@ interface EnterLeaveVisitor { readonly leave?: ASTVisitFn; } -/** - * A visitor is comprised of visit functions, which are called on each node - * during the visitor's traversal. - */ -export type ASTVisitFn = ( - /** The current node being visiting. */ - node: TVisitedNode, +interface VisitContext { /** The index or key to this node from the parent node or Array. */ - key: string | number | undefined, + key: string | number | undefined; /** The parent immediately above this node, which may be an Array. */ - parent: ASTNode | ReadonlyArray | undefined, + parent: ASTNode | ReadonlyArray | undefined; /** The key path to get to this node from the root node. */ - path: ReadonlyArray, + path: ReadonlyArray; /** * All nodes and Arrays visited before reaching parent of this node. * These correspond to array indices in `path`. * Note: ancestors includes arrays which contain the parent of visited node. */ - ancestors: ReadonlyArray>, + ancestors: ReadonlyArray>; +} + +/** + * A visitor is comprised of visit functions, which are called on each node + * during the visitor's traversal. + */ +export type ASTVisitFn = ( + /** The current node being visiting. */ + node: TVisitedNode, + context: VisitContext, ) => any; /** @@ -57,18 +61,7 @@ export type ASTReducer = { type ASTReducerFn = ( /** The current node being visiting. */ node: { [K in keyof TReducedNode]: ReducedField }, - /** The index or key to this node from the parent node or Array. */ - key: string | number | undefined, - /** The parent immediately above this node, which may be an Array. */ - parent: ASTNode | ReadonlyArray | undefined, - /** The key path to get to this node from the root node. */ - path: ReadonlyArray, - /** - * All nodes and Arrays visited before reaching parent of this node. - * These correspond to array indices in `path`. - * Note: ancestors includes arrays which contain the parent of visited node. - */ - ancestors: ReadonlyArray>, + context: VisitContext, ) => R; type ReducedField = T extends null | undefined @@ -102,7 +95,7 @@ export const BREAK: unknown = Object.freeze({}); * * ```ts * const editedAST = visit(ast, { - * enter(node, key, parent, path, ancestors) { + * enter(node, { key, parent, path, ancestors }) { * // @return * // undefined: no action * // false: skip visiting this node @@ -110,7 +103,7 @@ export const BREAK: unknown = Object.freeze({}); * // null: delete this node * // any value: replace this node with the returned value * }, - * leave(node, key, parent, path, ancestors) { + * leave(node, { key, parent, path, ancestors }) { * // @return * // undefined: no action * // false: no action @@ -251,7 +244,7 @@ export function visit( ? enterLeaveMap.get(node.kind)?.leave : enterLeaveMap.get(node.kind)?.enter; - result = visitFn?.call(visitor, node, key, parent, path, ancestors); + result = visitFn?.call(visitor, node, { key, parent, path, ancestors }); if (result === BREAK) { break; diff --git a/src/validation/rules/KnownDirectivesRule.ts b/src/validation/rules/KnownDirectivesRule.ts index 1c7b822388..c21b24e9fc 100644 --- a/src/validation/rules/KnownDirectivesRule.ts +++ b/src/validation/rules/KnownDirectivesRule.ts @@ -45,7 +45,7 @@ export function KnownDirectivesRule( } return { - Directive(node, _key, _parent, _path, ancestors) { + Directive(node, { ancestors }) { const name = node.name.value; const locations = locationsMap[name]; diff --git a/src/validation/rules/KnownTypeNamesRule.ts b/src/validation/rules/KnownTypeNamesRule.ts index fadc080c35..b5d17762e3 100644 --- a/src/validation/rules/KnownTypeNamesRule.ts +++ b/src/validation/rules/KnownTypeNamesRule.ts @@ -46,7 +46,7 @@ export function KnownTypeNamesRule( ]; return { - NamedType(node, _1, parent, _2, ancestors) { + NamedType(node, { parent, ancestors }) { const typeName = node.name.value; if (!existingTypesMap[typeName] && !definedTypes[typeName]) { const definitionNode = ancestors[2] ?? parent;