Skip to content

Commit

Permalink
Bring back
Browse files Browse the repository at this point in the history
  • Loading branch information
ardatan committed Aug 27, 2021
1 parent 2d61e22 commit 8b41d52
Show file tree
Hide file tree
Showing 4 changed files with 48 additions and 13 deletions.
1 change: 1 addition & 0 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -234,6 +234,7 @@ export type {
/** Visitor utilities */
ASTVisitor,
ASTVisitFn,
VisitorKeyMap,
/** AST nodes */
ASTNode,
ASTKindToNode,
Expand Down
38 changes: 37 additions & 1 deletion src/language/__tests__/visitor-test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,11 @@ import { describe, it } from 'mocha';

import { kitchenSinkQuery } from '../../__testUtils__/kitchenSinkQuery';

import type { ASTNode, SelectionSetNode } from '../ast';
import type { ASTKindToNode, ASTNode, SelectionSetNode } from '../ast';
import { isNode } from '../ast';
import { Kind } from '../kinds';
import { parse } from '../parser';
import type { VisitorKeyMap, ASTVisitor } from '../visitor';
import { visit, visitInParallel, BREAK } from '../visitor';

function checkVisitorFnArgs(ast: any, args: any, isEdited: boolean = false) {
Expand Down Expand Up @@ -893,6 +894,41 @@ describe('Visitor', () => {
]);
});

it('visits only the specified `Kind` in visitorKeyMap', () => {
const visited: Array<[string, string, ReturnType<typeof getValue>]> = [];

const visitorKeyMap: VisitorKeyMap<ASTKindToNode> = {
Document: ['definitions'],
OperationDefinition: ['name'],
};

const visitor: ASTVisitor = {
enter(node) {
visited.push(['enter', node.kind, getValue(node)]);
},
leave(node) {
visited.push(['leave', node.kind, getValue(node)]);
},
};

const exampleDocumentAST = parse(/* GraphQL */ `
query ExampleOperation {
someField
}
`);

visit(exampleDocumentAST, visitor, visitorKeyMap);

expect(visited).to.deep.equal([
['enter', Kind.DOCUMENT, undefined],
['enter', Kind.OPERATION_DEFINITION, undefined],
['enter', Kind.NAME, 'ExampleOperation'],
['leave', Kind.NAME, 'ExampleOperation'],
['leave', Kind.OPERATION_DEFINITION, undefined],
['leave', Kind.DOCUMENT, undefined],
]);
});

describe('visitInParallel', () => {
// Note: nearly identical to the above test of the same test but
// using visitInParallel.
Expand Down
2 changes: 1 addition & 1 deletion src/language/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ export type { ParseOptions } from './parser';
export { print } from './printer';

export { visit, visitInParallel, getVisitFn, BREAK } from './visitor';
export type { ASTVisitor, ASTVisitFn } from './visitor';
export type { ASTVisitor, ASTVisitFn, VisitorKeyMap } from './visitor';

export { Location, Token } from './ast';
export type {
Expand Down
20 changes: 9 additions & 11 deletions src/language/visitor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -76,9 +76,12 @@ type ReducedField<T, R> = T extends null | undefined
? ReadonlyArray<R>
: R;

const QueryDocumentKeys = {
Name: [],
/**
* A KeyMap describes each the traversable properties of each kind of node.
*/
export type VisitorKeyMap<KindToNode> = { [P in keyof KindToNode]?: ReadonlyArray<keyof KindToNode[P]> };

export const QueryDocumentKeys: VisitorKeyMap<ASTKindToNode> = {
Document: ['definitions'],
OperationDefinition: [
'name',
Expand All @@ -103,12 +106,6 @@ const QueryDocumentKeys = {
'selectionSet',
],

IntValue: [],
FloatValue: [],
StringValue: [],
BooleanValue: [],
NullValue: [],
EnumValue: [],
ListValue: ['values'],
ObjectValue: ['fields'],
ObjectField: ['name', 'value'],
Expand Down Expand Up @@ -242,11 +239,12 @@ export const BREAK: unknown = Object.freeze({});
* })
* ```
*/
export function visit<N extends ASTNode>(root: N, visitor: ASTVisitor): N;
export function visit<R>(root: ASTNode, visitor: ASTReducer<R>): R;
export function visit<N extends ASTNode>(root: N, visitor: ASTVisitor, visitorKeys?: VisitorKeyMap<ASTKindToNode>): N;
export function visit<R>(root: ASTNode, visitor: ASTReducer<R>, visitorKeys?: VisitorKeyMap<ASTKindToNode>): R;
export function visit(
root: ASTNode,
visitor: ASTVisitor | ASTReducer<any>,
visitorKeys: VisitorKeyMap<ASTKindToNode> = QueryDocumentKeys
): any {
/* eslint-disable no-undef-init */
let stack: any = undefined;
Expand Down Expand Up @@ -346,7 +344,7 @@ export function visit(
} else {
stack = { inArray, index, keys, edits, prev: stack };
inArray = Array.isArray(node);
keys = inArray ? node : (QueryDocumentKeys as any)[node.kind] ?? [];
keys = inArray ? node : (visitorKeys as any)[node.kind] ?? [];
index = -1;
edits = [];
if (parent) {
Expand Down

0 comments on commit 8b41d52

Please sign in to comment.