Skip to content

Commit

Permalink
visit: remove template arguments for possible nodes
Browse files Browse the repository at this point in the history
  • Loading branch information
IvanGoncharov committed Feb 20, 2021
1 parent b67ed17 commit ffb16fa
Show file tree
Hide file tree
Showing 8 changed files with 40 additions and 44 deletions.
3 changes: 1 addition & 2 deletions src/index.d.ts
Expand Up @@ -227,8 +227,7 @@ export {
DirectiveLocationEnum,
// Visitor utilities
ASTVisitor,
Visitor,
VisitFn,
ASTVisitFn,
// AST nodes
ASTNode,
ASTKindToNode,
Expand Down
3 changes: 1 addition & 2 deletions src/index.js
Expand Up @@ -214,8 +214,7 @@ export type {
DirectiveLocationEnum,
// Visitor utilities
ASTVisitor,
Visitor,
VisitFn,
ASTVisitFn,
// AST nodes
ASTNode,
ASTKindToNode,
Expand Down
3 changes: 1 addition & 2 deletions src/language/index.d.ts
Expand Up @@ -14,8 +14,7 @@ export {
getVisitFn,
BREAK,
ASTVisitor,
Visitor,
VisitFn,
ASTVisitFn,
} 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 } from './visitor';
export type { ASTVisitor, ASTVisitFn } from './visitor';

export { Location, Token } from './ast';
export type {
Expand Down
34 changes: 16 additions & 18 deletions src/language/visitor.d.ts
Expand Up @@ -6,45 +6,43 @@ import { ASTNode, ASTKindToNode } from './ast';
* A visitor is provided to visit, it contains the collection of
* relevant functions to be called during the visitor's traversal.
*/
export type ASTVisitor = Visitor<ASTKindToNode>;
export type Visitor<KindToNode, Nodes = KindToNode[keyof KindToNode]> =
| EnterLeaveVisitor<KindToNode, Nodes>
| ShapeMapVisitor<KindToNode, Nodes>;
export type ASTVisitor = EnterLeaveVisitor | ShapeMapVisitor;

interface EnterLeave<T> {
readonly enter?: T;
readonly leave?: T;
}

type EnterLeaveVisitor<KindToNode, Nodes> = EnterLeave<
VisitFn<Nodes> | { [K in keyof KindToNode]?: VisitFn<Nodes, KindToNode[K]> }
type EnterLeaveVisitor = EnterLeave<
| ASTVisitFn<ASTNode>
| { [K in keyof ASTKindToNode]?: ASTVisitFn<ASTKindToNode[K]> }
>;

type ShapeMapVisitor<KindToNode, Nodes> = {
[K in keyof KindToNode]?:
| VisitFn<Nodes, KindToNode[K]>
| EnterLeave<VisitFn<Nodes, KindToNode[K]>>;
type ShapeMapVisitor = {
[K in keyof ASTKindToNode]?:
| ASTVisitFn<ASTKindToNode[K]>
| EnterLeave<ASTVisitFn<ASTKindToNode[K]>>;
};

/**
* A visitor is comprised of visit functions, which are called on each node
* during the visitor's traversal.
*/
export type VisitFn<TAnyNode, TVisitedNode = TAnyNode> = (
export type ASTVisitFn<TVisitedNode extends ASTNode> = (
/** The current node being visiting. */
node: TVisitedNode,
/** 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: TAnyNode | ReadonlyArray<TAnyNode> | undefined,
parent: ASTNode | ReadonlyArray<ASTNode> | undefined,
/** The key path to get to this node from the root node. */
path: ReadonlyArray<string | number>,
/**
* 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<TAnyNode | ReadonlyArray<TAnyNode>>,
ancestors: ReadonlyArray<ASTNode | ReadonlyArray<ASTNode>>,
) => any;

export const BREAK: any;
Expand Down Expand Up @@ -135,7 +133,7 @@ export const BREAK: any;
* }
* })
*/
export function visit(root: ASTNode, visitor: Visitor<ASTKindToNode>): any;
export function visit(root: ASTNode, visitor: ASTVisitor): any;

/**
* Creates a new visitor instance which delegates to many visitors to run in
Expand All @@ -144,15 +142,15 @@ export function visit(root: ASTNode, visitor: Visitor<ASTKindToNode>): any;
* If a prior visitor edits a node, no following visitors will see that node.
*/
export function visitInParallel(
visitors: ReadonlyArray<Visitor<ASTKindToNode>>,
): Visitor<ASTKindToNode>;
visitors: ReadonlyArray<ASTVisitor>,
): ASTVisitor;

/**
* Given a visitor instance, if it is leaving or not, and a node kind, return
* the function the visitor runtime should call.
*/
export function getVisitFn(
visitor: Visitor<any>,
visitor: ASTVisitor,
kind: string,
isLeaving: boolean,
): Maybe<VisitFn<any>>;
): Maybe<ASTVisitFn<ASTNode>>;
29 changes: 15 additions & 14 deletions src/language/visitor.js
Expand Up @@ -7,15 +7,14 @@ import { isNode } from './ast';
* A visitor is provided to visit, it contains the collection of
* relevant functions to be called during the visitor's traversal.
*/
export type ASTVisitor = Visitor<ASTKindToNode>;
export type Visitor<KindToNode, Nodes = $Values<KindToNode>> =
export type ASTVisitor =
| EnterLeave<
| VisitFn<Nodes>
| ShapeMap<KindToNode, <Node>(Node) => VisitFn<Nodes, Node>>,
| ASTVisitFn<ASTNode>
| ShapeMap<ASTKindToNode, <Node>(Node) => ASTVisitFn<Node>>,
>
| ShapeMap<
KindToNode,
<Node>(Node) => VisitFn<Nodes, Node> | EnterLeave<VisitFn<Nodes, Node>>,
ASTKindToNode,
<Node>(Node) => ASTVisitFn<Node> | EnterLeave<ASTVisitFn<Node>>,
>;
type EnterLeave<T> = {| +enter?: T, +leave?: T |};
type ShapeMap<O, F> = $Shape<$ObjMap<O, F>>;
Expand All @@ -24,19 +23,19 @@ type ShapeMap<O, F> = $Shape<$ObjMap<O, F>>;
* A visitor is comprised of visit functions, which are called on each node
* during the visitor's traversal.
*/
export type VisitFn<TAnyNode, TVisitedNode: TAnyNode = TAnyNode> = (
export type ASTVisitFn<TVisitedNode: ASTNode> = (
// The current node being visiting.
node: TVisitedNode,
// The index or key to this node from the parent node or Array.
key: string | number | void,
// The parent immediately above this node, which may be an Array.
parent: TAnyNode | $ReadOnlyArray<TAnyNode> | void,
parent: ASTNode | $ReadOnlyArray<ASTNode> | void,
// The key path to get to this node from the root node.
path: $ReadOnlyArray<string | number>,
// 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<TAnyNode | $ReadOnlyArray<TAnyNode>>,
ancestors: $ReadOnlyArray<ASTNode | $ReadOnlyArray<ASTNode>>,
) => any;

const QueryDocumentKeys = {
Expand Down Expand Up @@ -213,7 +212,7 @@ export const BREAK: { ... } = Object.freeze({});
* }
* })
*/
export function visit(root: ASTNode, visitor: Visitor<ASTKindToNode>): any {
export function visit(root: ASTNode, visitor: ASTVisitor): any {
/* eslint-disable no-undef-init */
let stack: any = undefined;
let inArray = Array.isArray(root);
Expand Down Expand Up @@ -284,6 +283,7 @@ export function visit(root: ASTNode, visitor: Visitor<ASTKindToNode>): any {
}
const visitFn = getVisitFn(visitor, node.kind, isLeaving);
if (visitFn) {
// $FlowFixMe[incompatible-call]
result = visitFn.call(visitor, node, key, parent, path, ancestors);

if (result === BREAK) {
Expand Down Expand Up @@ -342,8 +342,8 @@ export function visit(root: ASTNode, visitor: Visitor<ASTKindToNode>): any {
* If a prior visitor edits a node, no following visitors will see that node.
*/
export function visitInParallel(
visitors: $ReadOnlyArray<Visitor<ASTKindToNode>>,
): Visitor<ASTKindToNode> {
visitors: $ReadOnlyArray<ASTVisitor>,
): ASTVisitor {
const skipping = new Array(visitors.length);

return {
Expand Down Expand Up @@ -389,10 +389,10 @@ export function visitInParallel(
* the function the visitor runtime should call.
*/
export function getVisitFn(
visitor: Visitor<any>,
visitor: ASTVisitor,
kind: string,
isLeaving: boolean,
): ?VisitFn<any> {
): ?ASTVisitFn<ASTNode> {
const kindVisitor = visitor[kind];
if (kindVisitor) {
if (!isLeaving && typeof kindVisitor === 'function') {
Expand All @@ -407,6 +407,7 @@ export function getVisitFn(
return kindSpecificVisitor;
}
} else {
// $FlowFixMe[prop-missing]
const specificVisitor = isLeaving ? visitor.leave : visitor.enter;
if (specificVisitor) {
if (typeof specificVisitor === 'function') {
Expand Down
2 changes: 1 addition & 1 deletion src/utilities/TypeInfo.d.ts
@@ -1,6 +1,6 @@
import { Maybe } from '../jsutils/Maybe';

import { Visitor } from '../language/visitor';
import { ASTVisitor } from '../language/visitor';
import { ASTNode, ASTKindToNode, FieldNode } from '../language/ast';
import { GraphQLSchema } from '../type/schema';
import { GraphQLDirective } from '../type/directives';
Expand Down
8 changes: 4 additions & 4 deletions src/utilities/TypeInfo.js
@@ -1,5 +1,5 @@
import type { Visitor } from '../language/visitor';
import type { ASTNode, ASTKindToNode, FieldNode } from '../language/ast';
import type { ASTVisitor } from '../language/visitor';
import type { ASTNode, FieldNode } from '../language/ast';
import { Kind } from '../language/kinds';
import { isNode } from '../language/ast';
import { getVisitFn } from '../language/visitor';
Expand Down Expand Up @@ -324,8 +324,8 @@ function getFieldDef(
*/
export function visitWithTypeInfo(
typeInfo: TypeInfo,
visitor: Visitor<ASTKindToNode>,
): Visitor<ASTKindToNode> {
visitor: ASTVisitor,
): ASTVisitor {
return {
enter(node) {
typeInfo.enter(node);
Expand Down

0 comments on commit ffb16fa

Please sign in to comment.