Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

visitor: remove visitorKeys argument #2930

Merged
merged 1 commit into from Feb 20, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
1 change: 0 additions & 1 deletion src/index.d.ts
Expand Up @@ -229,7 +229,6 @@ export {
ASTVisitor,
Visitor,
VisitFn,
VisitorKeyMap,
// AST nodes
ASTNode,
ASTKindToNode,
Expand Down
1 change: 0 additions & 1 deletion src/index.js
Expand Up @@ -216,7 +216,6 @@ export type {
ASTVisitor,
Visitor,
VisitFn,
VisitorKeyMap,
// AST nodes
ASTNode,
ASTKindToNode,
Expand Down
41 changes: 1 addition & 40 deletions src/language/__tests__/visitor-test.js
Expand Up @@ -8,7 +8,7 @@ import { invariant } from '../../jsutils/invariant';
import type { ASTNode } from '../ast';
import { Kind } from '../kinds';
import { parse } from '../parser';
import { visit, visitInParallel, BREAK, QueryDocumentKeys } from '../visitor';
import { visit, visitInParallel, BREAK } from '../visitor';

function checkVisitorFnArgs(ast: any, args: any, isEdited: boolean = false) {
const [node, key, parent, path, ancestors] = args;
Expand Down Expand Up @@ -913,45 +913,6 @@ describe('Visitor', () => {
['leave', 'Document', undefined],
]);
});

it('does traverse unknown node kinds with visitor keys', () => {
const customQueryDocumentKeys = { ...QueryDocumentKeys };
(customQueryDocumentKeys: any).CustomField = ['name', 'selectionSet'];

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

expect(visited).to.deep.equal([
['enter', 'Document', undefined],
['enter', 'OperationDefinition', undefined],
['enter', 'SelectionSet', undefined],
['enter', 'Field', undefined],
['enter', 'Name', 'a'],
['leave', 'Name', 'a'],
['leave', 'Field', undefined],
['enter', 'CustomField', undefined],
['enter', 'Name', 'b'],
['leave', 'Name', 'b'],
['enter', 'SelectionSet', undefined],
['enter', 'CustomField', undefined],
['enter', 'Name', 'c'],
['leave', 'Name', 'c'],
['leave', 'CustomField', undefined],
['leave', 'SelectionSet', undefined],
['leave', 'CustomField', undefined],
['leave', 'SelectionSet', undefined],
['leave', 'OperationDefinition', undefined],
['leave', 'Document', undefined],
]);
});
});

describe('visitInParallel', () => {
Expand Down
1 change: 0 additions & 1 deletion src/language/index.d.ts
Expand Up @@ -16,7 +16,6 @@ export {
ASTVisitor,
Visitor,
VisitFn,
VisitorKeyMap,
} from './visitor';

export {
Expand Down
2 changes: 1 addition & 1 deletion src/language/index.js
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, Visitor, VisitFn, VisitorKeyMap } from './visitor';
export type { ASTVisitor, Visitor, VisitFn } from './visitor';

export { Location, Token } from './ast';
export type {
Expand Down
106 changes: 1 addition & 105 deletions src/language/visitor.d.ts
Expand Up @@ -47,106 +47,6 @@ export type VisitFn<TAnyNode, TVisitedNode = TAnyNode> = (
ancestors: ReadonlyArray<TAnyNode | ReadonlyArray<TAnyNode>>,
) => any;

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

// TODO: Should be `[]`, but that requires TypeScript@3
type EmptyTuple = Array<never>;

export const QueryDocumentKeys: {
Name: EmptyTuple;

Document: ['definitions'];
// Prettier forces trailing commas, but TS pre 3.2 doesn't allow them.
// prettier-ignore
OperationDefinition: [
'name',
'variableDefinitions',
'directives',
'selectionSet'
];
VariableDefinition: ['variable', 'type', 'defaultValue', 'directives'];
Variable: ['name'];
SelectionSet: ['selections'];
Field: ['alias', 'name', 'arguments', 'directives', 'selectionSet'];
Argument: ['name', 'value'];

FragmentSpread: ['name', 'directives'];
InlineFragment: ['typeCondition', 'directives', 'selectionSet'];
// prettier-ignore
FragmentDefinition: [
'name',
// Note: fragment variable definitions are deprecated and will removed in v17.0.0
'variableDefinitions',
'typeCondition',
'directives',
'selectionSet'
];

IntValue: EmptyTuple;
FloatValue: EmptyTuple;
StringValue: EmptyTuple;
BooleanValue: EmptyTuple;
NullValue: EmptyTuple;
EnumValue: EmptyTuple;
ListValue: ['values'];
ObjectValue: ['fields'];
ObjectField: ['name', 'value'];

Directive: ['name', 'arguments'];

NamedType: ['name'];
ListType: ['type'];
NonNullType: ['type'];

SchemaDefinition: ['description', 'directives', 'operationTypes'];
OperationTypeDefinition: ['type'];

ScalarTypeDefinition: ['description', 'name', 'directives'];
// prettier-ignore
ObjectTypeDefinition: [
'description',
'name',
'interfaces',
'directives',
'fields'
];
FieldDefinition: ['description', 'name', 'arguments', 'type', 'directives'];
// prettier-ignore
InputValueDefinition: [
'description',
'name',
'type',
'defaultValue',
'directives'
];
// prettier-ignore
InterfaceTypeDefinition: [
'description',
'name',
'interfaces',
'directives',
'fields'
];
UnionTypeDefinition: ['description', 'name', 'directives', 'types'];
EnumTypeDefinition: ['description', 'name', 'directives', 'values'];
EnumValueDefinition: ['description', 'name', 'directives'];
InputObjectTypeDefinition: ['description', 'name', 'directives', 'fields'];

DirectiveDefinition: ['description', 'name', 'arguments', 'locations'];

SchemaExtension: ['directives', 'operationTypes'];

ScalarTypeExtension: ['name', 'directives'];
ObjectTypeExtension: ['name', 'interfaces', 'directives', 'fields'];
InterfaceTypeExtension: ['name', 'interfaces', 'directives', 'fields'];
UnionTypeExtension: ['name', 'directives', 'types'];
EnumTypeExtension: ['name', 'directives', 'values'];
InputObjectTypeExtension: ['name', 'directives', 'fields'];
};

export const BREAK: any;

/**
Expand Down Expand Up @@ -235,11 +135,7 @@ export const BREAK: any;
* }
* })
*/
export function visit(
root: ASTNode,
visitor: Visitor<ASTKindToNode>,
visitorKeys?: VisitorKeyMap<ASTKindToNode>, // default: QueryDocumentKeys
): any;
export function visit(root: ASTNode, visitor: Visitor<ASTKindToNode>): any;

/**
* Creates a new visitor instance which delegates to many visitors to run in
Expand Down
18 changes: 3 additions & 15 deletions src/language/visitor.js
Expand Up @@ -39,15 +39,7 @@ export type VisitFn<TAnyNode, TVisitedNode: TAnyNode = TAnyNode> = (
ancestors: $ReadOnlyArray<TAnyNode | $ReadOnlyArray<TAnyNode>>,
) => any;

/**
* A KeyMap describes each the traversable properties of each kind of node.
*/
export type VisitorKeyMap<KindToNode> = $ObjMap<
KindToNode,
<T>(T) => $ReadOnlyArray<$Keys<T>>,
>;

export const QueryDocumentKeys: VisitorKeyMap<ASTKindToNode> = {
const QueryDocumentKeys = {
Name: [],

Document: ['definitions'],
Expand Down Expand Up @@ -221,11 +213,7 @@ export const BREAK: { ... } = Object.freeze({});
* }
* })
*/
export function visit(
root: ASTNode,
visitor: Visitor<ASTKindToNode>,
visitorKeys: VisitorKeyMap<ASTKindToNode> = QueryDocumentKeys,
): any {
export function visit(root: ASTNode, visitor: Visitor<ASTKindToNode>): any {
/* eslint-disable no-undef-init */
let stack: any = undefined;
let inArray = Array.isArray(root);
Expand Down Expand Up @@ -330,7 +318,7 @@ export function visit(
} else {
stack = { inArray, index, keys, edits, prev: stack };
inArray = Array.isArray(node);
keys = inArray ? node : visitorKeys[node.kind] ?? [];
keys = inArray ? node : QueryDocumentKeys[node.kind] ?? [];
index = -1;
edits = [];
if (parent) {
Expand Down