import { ASTNode, Location, DefinitionNode, OperationTypeNode, NameNode, NamedTypeNode, ParseOptions } from 'graphql';

type ExtendedASTNode = ASTNode | ExtendedDocumentNode | InvalidOperationDefinitionNode | InvalidFragmentDefinitionNode | InvalidNode | IgnoredNode;
interface ExtendedASTKindToNode {
    ExtendedDocument: ExtendedDocumentNode;
    InvalidOperationDefinition: InvalidOperationDefinitionNode;
    InvalidFragmentDefinition: InvalidFragmentDefinitionNode;
    Ignored: IgnoredNode;
}
/**
 * Store definitions with Invalid and Ignored nodes in `sections` array
 */
interface ExtendedDocumentNode {
    readonly kind: "ExtendedDocument";
    readonly loc?: Location | undefined;
    readonly sections: ReadonlyArray<SectionNode>;
}
declare function isExtendedDocumentNode(node: unknown): node is ExtendedDocumentNode;
type SectionNode = DefinitionNode | InvalidDefinitionNode | InvalidNode | IgnoredNode;
type InvalidDefinitionNode = InvalidOperationDefinitionNode | InvalidFragmentDefinitionNode;
interface InvalidOperationDefinitionNode {
    readonly kind: "InvalidOperationDefinition";
    readonly loc?: Location | undefined;
    readonly operation: OperationTypeNode;
    readonly name?: NameNode | undefined;
    readonly value: string;
}
interface InvalidFragmentDefinitionNode {
    readonly kind: "InvalidFragmentDefinition";
    readonly loc?: Location | undefined;
    readonly name: NameNode;
    readonly typeCondition: NamedTypeNode;
    readonly value: string;
}
interface InvalidNode {
    readonly kind: "Invalid";
    readonly loc?: Location | undefined;
    readonly value: string;
}
interface IgnoredNode {
    readonly kind: "Ignored";
    readonly loc?: Location | undefined;
    readonly value: string;
}

declare function analyze(source: string, options?: ParseOptions): ExtendedDocumentNode;

/**
 * For a document with invalid operations or fragments,
 * interpolate valid nodes from a reference document
 *
 * Approach:
 *
 * 1. Conservatively, only interpolate if documents have same "outline"
 *    (same number of operations / fragments)
 * 2. Anonymous operations are interpolated by "outline" index
 * 3. Named operations and fragments are interpolated by name
 */
declare function interpolate(document: ExtendedDocumentNode, reference: ExtendedDocumentNode): ExtendedDocumentNode;

declare function print(ast: ASTNode | ExtendedDocumentNode): string;

/**
 * Visit an Extended Document
 */
declare function visit(root: ExtendedASTNode, visitor: ExtendedASTVisitor): any;
type ExtendedASTVisitor = EnterLeaveVisitor<ExtendedASTNode> | KindVisitor;
type KindVisitor = {
    readonly [TNode in ExtendedASTNode as TNode["kind"]]?: VisitFn<TNode> | EnterLeaveVisitor<TNode>;
};
interface EnterLeaveVisitor<TNode extends ExtendedASTNode> {
    readonly enter?: VisitFn<TNode> | undefined;
    readonly leave?: VisitFn<TNode> | undefined;
}
type VisitFn<TVisitedNode extends ExtendedASTNode> = (node: TVisitedNode, key: string | number | undefined, parent: ASTNode | ReadonlyArray<ASTNode> | undefined, path: ReadonlyArray<string | number>, ancestors: ReadonlyArray<ASTNode | ReadonlyArray<ASTNode>>) => any;

export { ExtendedASTKindToNode, ExtendedASTNode, ExtendedASTVisitor, ExtendedDocumentNode, IgnoredNode, InvalidDefinitionNode, InvalidFragmentDefinitionNode, InvalidOperationDefinitionNode, SectionNode, analyze, interpolate, isExtendedDocumentNode, print, visit };
