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

visit: remove template arguments for possible nodes #2931

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
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
8 changes: 4 additions & 4 deletions src/utilities/TypeInfo.d.ts
@@ -1,7 +1,7 @@
import { Maybe } from '../jsutils/Maybe';

import { Visitor } from '../language/visitor';
import { ASTNode, ASTKindToNode, FieldNode } from '../language/ast';
import { ASTVisitor } from '../language/visitor';
import { ASTNode, FieldNode } from '../language/ast';
import { GraphQLSchema } from '../type/schema';
import { GraphQLDirective } from '../type/directives';
import {
Expand Down Expand Up @@ -55,5 +55,5 @@ type getFieldDef = (
*/
export function visitWithTypeInfo(
typeInfo: TypeInfo,
visitor: Visitor<ASTKindToNode>,
): Visitor<ASTKindToNode>;
visitor: ASTVisitor,
): ASTVisitor;
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