Repository: eslint/eslint
File: lib/types/index.d.ts (TypeScript)

Code before:
        ThrowStatement?(node: ESTree.ThrowStatement & NodeParentExtension): void;
        "ThrowStatement:exit"?(node: ESTree.ThrowStatement & NodeParentExtension): void;
        TryStatement?(node: ESTree.TryStatement & NodeParentExtension): void;
        "TryStatement:exit"?(node: ESTree.TryStatement & NodeParentExtension): void;
        UnaryExpression?(node: ESTree.UnaryExpression & NodeParentExtension): void;
        "UnaryExpression:exit"?(node: ESTree.UnaryExpression & NodeParentExtension): void;
        UpdateExpression?(node: ESTree.UpdateExpression & NodeParentExtension): void;
        "UpdateExpression:exit"?(node: ESTree.UpdateExpression & NodeParentExtension): void;
        VariableDeclaration?(node: ESTree.VariableDeclaration & NodeParentExtension): void;
        "VariableDeclaration:exit"?(node: ESTree.VariableDeclaration & NodeParentExtension): void;
        VariableDeclarator?(node: ESTree.VariableDeclarator & NodeParentExtension): void;
        "VariableDeclarator:exit"?(node: ESTree.VariableDeclarator & NodeParentExtension): void;
        WhileStatement?(node: ESTree.WhileStatement & NodeParentExtension): void;
        "WhileStatement:exit"?(node: ESTree.WhileStatement & NodeParentExtension): void;
        WithStatement?(node: ESTree.WithStatement & NodeParentExtension): void;
        "WithStatement:exit"?(node: ESTree.WithStatement & NodeParentExtension): void;
        YieldExpression?(node: ESTree.YieldExpression & NodeParentExtension): void;
        "YieldExpression:exit"?(node: ESTree.YieldExpression & NodeParentExtension): void;
    }

    interface NodeParentExtension {
        parent: Node;
    }
    type Node = ESTree.Node & NodeParentExtension;

    type RuleListener = NodeListener & {
        onCodePathStart?(codePath: CodePath, node: Node): void;

        onCodePathEnd?(codePath: CodePath, node: Node): void;

        onCodePathSegmentStart?(segment: CodePathSegment, node: Node): void;

        onCodePathSegmentEnd?(segment: CodePathSegment, node: Node): void;

        onCodePathSegmentLoop?(fromSegment: CodePathSegment, toSegment: CodePathSegment, node: Node): void;

        [key: string]:
        | ((codePath: CodePath, node: Node) => void)
        | ((segment: CodePathSegment, node: Node) => void)
        | ((fromSegment: CodePathSegment, toSegment: CodePathSegment, node: Node) => void)
        | ((node: Node) => void)
        | NodeListener[keyof NodeListener]
        | undefined;
    }

    type CodePathOrigin = "program" | "function" | "class-field-initializer" | "class-static-block";

    interface CodePath {
        id: string;
        origin: CodePathOrigin;
        initialSegment: CodePathSegment;

Review comment (suggestion):
I couldn't get this to validly extend `NodeListener`, so opted for a union type instead, which seemed more appropriate anyway.

Code after:
        "ThisExpression:exit"?: ((node: ESTree.ThisExpression & NodeParentExtension) => void) | undefined;
        ThrowStatement?: ((node: ESTree.ThrowStatement & NodeParentExtension) => void) | undefined;
        "ThrowStatement:exit"?: ((node: ESTree.ThrowStatement & NodeParentExtension) => void) | undefined;
        TryStatement?: ((node: ESTree.TryStatement & NodeParentExtension) => void) | undefined;
        "TryStatement:exit"?: ((node: ESTree.TryStatement & NodeParentExtension) => void) | undefined;
        UnaryExpression?: ((node: ESTree.UnaryExpression & NodeParentExtension) => void) | undefined;
        "UnaryExpression:exit"?: ((node: ESTree.UnaryExpression & NodeParentExtension) => void) | undefined;
        UpdateExpression?: ((node: ESTree.UpdateExpression & NodeParentExtension) => void) | undefined;
        "UpdateExpression:exit"?: ((node: ESTree.UpdateExpression & NodeParentExtension) => void) | undefined;
        VariableDeclaration?: ((node: ESTree.VariableDeclaration & NodeParentExtension) => void) | undefined;
        "VariableDeclaration:exit"?: ((node: ESTree.VariableDeclaration & NodeParentExtension) => void) | undefined;
        VariableDeclarator?: ((node: ESTree.VariableDeclarator & NodeParentExtension) => void) | undefined;
        "VariableDeclarator:exit"?: ((node: ESTree.VariableDeclarator & NodeParentExtension) => void) | undefined;
        WhileStatement?: ((node: ESTree.WhileStatement & NodeParentExtension) => void) | undefined;
        "WhileStatement:exit"?: ((node: ESTree.WhileStatement & NodeParentExtension) => void) | undefined;
        WithStatement?: ((node: ESTree.WithStatement & NodeParentExtension) => void) | undefined;
        "WithStatement:exit"?: ((node: ESTree.WithStatement & NodeParentExtension) => void) | undefined;
        YieldExpression?: ((node: ESTree.YieldExpression & NodeParentExtension) => void) | undefined;
        "YieldExpression:exit"?: ((node: ESTree.YieldExpression & NodeParentExtension) => void) | undefined;
    }

    interface NodeParentExtension {
        parent: Node;
    }
    type Node = ESTree.Node & NodeParentExtension;

    interface RuleListener extends NodeListener {
        onCodePathStart?(codePath: CodePath, node: Node): void;

        onCodePathEnd?(codePath: CodePath, node: Node): void;

        onCodePathSegmentStart?(segment: CodePathSegment, node: Node): void;

        onCodePathSegmentEnd?(segment: CodePathSegment, node: Node): void;

        onCodePathSegmentLoop?(fromSegment: CodePathSegment, toSegment: CodePathSegment, node: Node): void;

        [key: string]:
        | ((codePath: CodePath, node: Node) => void)
        | ((segment: CodePathSegment, node: Node) => void)
        | ((fromSegment: CodePathSegment, toSegment: CodePathSegment, node: Node) => void)
        | ((node: Node) => void)
        | NodeListener[keyof NodeListener]
        | undefined;
    }

    type CodePathOrigin = "program" | "function" | "class-field-initializer" | "class-static-block";

    interface CodePath {
        id: string;
        origin: CodePathOrigin;