"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
}) : (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
    Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
    o["default"] = v;
});
var __importStar = (this && this.__importStar) || function (mod) {
    if (mod && mod.__esModule) return mod;
    var result = {};
    if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
    __setModuleDefault(result, mod);
    return result;
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.Converter = exports.convertError = void 0;
// There's lots of funny stuff due to the typing of ts.Node
/* eslint-disable @typescript-eslint/no-explicit-any */
const ts = __importStar(require("typescript"));
const node_utils_1 = require("./node-utils");
const ts_estree_1 = require("./ts-estree");
const version_check_1 = require("./version-check");
const SyntaxKind = ts.SyntaxKind;
/**
 * Extends and formats a given error object
 * @param error the error object
 * @returns converted error object
 */
function convertError(error) {
    return node_utils_1.createError(error.file, error.start, error.message || error.messageText);
}
exports.convertError = convertError;
class Converter {
    /**
     * Converts a TypeScript node into an ESTree node
     * @param ast the full TypeScript AST
     * @param options additional options for the conversion
     * @returns the converted ESTreeNode
     */
    constructor(ast, options) {
        this.esTreeNodeToTSNodeMap = new WeakMap();
        this.tsNodeToESTreeNodeMap = new WeakMap();
        this.allowPattern = false;
        this.inTypeMode = false;
        this.ast = ast;
        this.options = Object.assign({}, options);
    }
    getASTMaps() {
        return {
            esTreeNodeToTSNodeMap: this.esTreeNodeToTSNodeMap,
            tsNodeToESTreeNodeMap: this.tsNodeToESTreeNodeMap,
        };
    }
    convertProgram() {
        return this.converter(this.ast);
    }
    /**
     * Converts a TypeScript node into an ESTree node.
     * @param node the child ts.Node
     * @param parent parentNode
     * @param inTypeMode flag to determine if we are in typeMode
     * @param allowPattern flag to determine if patterns are allowed
     * @returns the converted ESTree node
     */
    converter(node, parent, inTypeMode, allowPattern) {
        /**
         * Exit early for null and undefined
         */
        if (!node) {
            return null;
        }
        const typeMode = this.inTypeMode;
        const pattern = this.allowPattern;
        if (inTypeMode !== undefined) {
            this.inTypeMode = inTypeMode;
        }
        if (allowPattern !== undefined) {
            this.allowPattern = allowPattern;
        }
        const result = this.convertNode(node, (parent !== null && parent !== void 0 ? parent : node.parent));
        this.registerTSNodeInNodeMap(node, result);
        this.inTypeMode = typeMode;
        this.allowPattern = pattern;
        return result;
    }
    /**
     * Fixes the exports of the given ts.Node
     * @param node the ts.Node
     * @param result result
     * @returns the ESTreeNode with fixed exports
     */
    fixExports(node, result) {
        // check for exports
        if (node.modifiers && node.modifiers[0].kind === SyntaxKind.ExportKeyword) {
            /**
             * Make sure that original node is registered instead of export
             */
            this.registerTSNodeInNodeMap(node, result);
            const exportKeyword = node.modifiers[0];
            const nextModifier = node.modifiers[1];
            const declarationIsDefault = nextModifier && nextModifier.kind === SyntaxKind.DefaultKeyword;
            const varToken = declarationIsDefault
                ? node_utils_1.findNextToken(nextModifier, this.ast, this.ast)
                : node_utils_1.findNextToken(exportKeyword, this.ast, this.ast);
            result.range[0] = varToken.getStart(this.ast);
            result.loc = node_utils_1.getLocFor(result.range[0], result.range[1], this.ast);
            if (declarationIsDefault) {
                return this.createNode(node, {
                    type: ts_estree_1.AST_NODE_TYPES.ExportDefaultDeclaration,
                    declaration: result,
                    range: [exportKeyword.getStart(this.ast), result.range[1]],
                    exportKind: 'value',
                });
            }
            else {
                const isType = result.type === ts_estree_1.AST_NODE_TYPES.TSInterfaceDeclaration ||
                    result.type === ts_estree_1.AST_NODE_TYPES.TSTypeAliasDeclaration;
                const isDeclare = result.declare === true;
                return this.createNode(node, {
                    type: ts_estree_1.AST_NODE_TYPES.ExportNamedDeclaration,
                    declaration: result,
                    specifiers: [],
                    source: null,
                    exportKind: isType || isDeclare ? 'type' : 'value',
                    range: [exportKeyword.getStart(this.ast), result.range[1]],
                });
            }
        }
        return result;
    }
    /**
     * Register specific TypeScript node into map with first ESTree node provided
     */
    registerTSNodeInNodeMap(node, result) {
        if (result && this.options.shouldPreserveNodeMaps) {
            if (!this.tsNodeToESTreeNodeMap.has(node)) {
                this.tsNodeToESTreeNodeMap.set(node, result);
            }
        }
    }
    /**
     * Converts a TypeScript node into an ESTree node.
     * @param child the child ts.Node
     * @param parent parentNode
     * @returns the converted ESTree node
     */
    convertPattern(child, parent) {
        return this.converter(child, parent, this.inTypeMode, true);
    }
    /**
     * Converts a TypeScript node into an ESTree node.
     * @param child the child ts.Node
     * @param parent parentNode
     * @returns the converted ESTree node
     */
    convertChild(child, parent) {
        return this.converter(child, parent, this.inTypeMode, false);
    }
    /**
     * Converts a TypeScript node into an ESTree node.
     * @param child the child ts.Node
     * @param parent parentNode
     * @returns the converted ESTree node
     */
    convertType(child, parent) {
        return this.converter(child, parent, true, false);
    }
    createNode(node, data) {
        const result = data;
        if (!result.range) {
            result.range = node_utils_1.getRange(
            // this is completely valid, but TS hates it
            node, this.ast);
        }
        if (!result.loc) {
            result.loc = node_utils_1.getLocFor(result.range[0], result.range[1], this.ast);
        }
        if (result && this.options.shouldPreserveNodeMaps) {
            this.esTreeNodeToTSNodeMap.set(result, node);
        }
        return result;
    }
    convertBindingNameWithTypeAnnotation(name, tsType, parent) {
        const id = this.convertPattern(name);
        if (tsType) {
            id.typeAnnotation = this.convertTypeAnnotation(tsType, parent);
            this.fixParentLocation(id, id.typeAnnotation.range);
        }
        return id;
    }
    /**
     * Converts a child into a type annotation. This creates an intermediary
     * TypeAnnotation node to match what Flow does.
     * @param child The TypeScript AST node to convert.
     * @param parent parentNode
     * @returns The type annotation node.
     */
    convertTypeAnnotation(child, parent) {
        // in FunctionType and ConstructorType typeAnnotation has 2 characters `=>` and in other places is just colon
        const offset = (parent === null || parent === void 0 ? void 0 : parent.kind) === SyntaxKind.FunctionType ||
            (parent === null || parent === void 0 ? void 0 : parent.kind) === SyntaxKind.ConstructorType
            ? 2
            : 1;
        const annotationStartCol = child.getFullStart() - offset;
        const loc = node_utils_1.getLocFor(annotationStartCol, child.end, this.ast);
        return {
            type: ts_estree_1.AST_NODE_TYPES.TSTypeAnnotation,
            loc,
            range: [annotationStartCol, child.end],
            typeAnnotation: this.convertType(child),
        };
    }
    /**
     * Coverts body Nodes and add a directive field to StringLiterals
     * @param nodes of ts.Node
     * @param parent parentNode
     * @returns Array of body statements
     */
    convertBodyExpressions(nodes, parent) {
        let allowDirectives = node_utils_1.canContainDirective(parent);
        return (nodes
            .map(statement => {
            const child = this.convertChild(statement);
            if (allowDirectives) {
                if ((child === null || child === void 0 ? void 0 : child.expression) &&
                    ts.isExpressionStatement(statement) &&
                    ts.isStringLiteral(statement.expression)) {
                    const raw = child.expression.raw;
                    child.directive = raw.slice(1, -1);
                    return child; // child can be null, but it's filtered below
                }
                else {
                    allowDirectives = false;
                }
            }
            return child; // child can be null, but it's filtered below
        })
            // filter out unknown nodes for now
            .filter(statement => statement));
    }
    /**
     * Converts a ts.Node's typeArguments to TSTypeParameterInstantiation node
     * @param typeArguments ts.NodeArray typeArguments
     * @param node parent used to create this node
     * @returns TypeParameterInstantiation node
     */
    convertTypeArgumentsToTypeParameters(typeArguments, node) {
        const greaterThanToken = node_utils_1.findNextToken(typeArguments, this.ast, this.ast);
        return this.createNode(node, {
            type: ts_estree_1.AST_NODE_TYPES.TSTypeParameterInstantiation,
            range: [typeArguments.pos - 1, greaterThanToken.end],
            params: typeArguments.map(typeArgument => this.convertType(typeArgument)),
        });
    }
    /**
     * Converts a ts.Node's typeParameters to TSTypeParameterDeclaration node
     * @param typeParameters ts.Node typeParameters
     * @returns TypeParameterDeclaration node
     */
    convertTSTypeParametersToTypeParametersDeclaration(typeParameters) {
        const greaterThanToken = node_utils_1.findNextToken(typeParameters, this.ast, this.ast);
        return {
            type: ts_estree_1.AST_NODE_TYPES.TSTypeParameterDeclaration,
            range: [typeParameters.pos - 1, greaterThanToken.end],
            loc: node_utils_1.getLocFor(typeParameters.pos - 1, greaterThanToken.end, this.ast),
            params: typeParameters.map(typeParameter => this.convertType(typeParameter)),
        };
    }
    /**
     * Converts an array of ts.Node parameters into an array of ESTreeNode params
     * @param parameters An array of ts.Node params to be converted
     * @returns an array of converted ESTreeNode params
     */
    convertParameters(parameters) {
        if (!parameters || !parameters.length) {
            return [];
        }
        return parameters.map(param => {
            var _a;
            const convertedParam = this.convertChild(param);
            if ((_a = param.decorators) === null || _a === void 0 ? void 0 : _a.length) {
                convertedParam.decorators = param.decorators.map(el => this.convertChild(el));
            }
            return convertedParam;
        });
    }
    convertChainExpression(node, tsNode) {
        const { child, isOptional } = (() => {
            if (node.type === ts_estree_1.AST_NODE_TYPES.MemberExpression) {
                return { child: node.object, isOptional: node.optional };
            }
            if (node.type === ts_estree_1.AST_NODE_TYPES.CallExpression) {
                return { child: node.callee, isOptional: node.optional };
            }
            return { child: node.expression, isOptional: false };
        })();
        const isChildUnwrappable = node_utils_1.isChildUnwrappableOptionalChain(tsNode, child);
        if (!isChildUnwrappable && !isOptional) {
            return node;
        }
        if (isChildUnwrappable && node_utils_1.isChainExpression(child)) {
            // unwrap the chain expression child
            const newChild = child.expression;
            if (node.type === ts_estree_1.AST_NODE_TYPES.MemberExpression) {
                node.object = newChild;
            }
            else if (node.type === ts_estree_1.AST_NODE_TYPES.CallExpression) {
                node.callee = newChild;
            }
            else {
                node.expression = newChild;
            }
        }
        return this.createNode(tsNode, {
            type: ts_estree_1.AST_NODE_TYPES.ChainExpression,
            expression: node,
        });
    }
    /**
     * For nodes that are copied directly from the TypeScript AST into
     * ESTree mostly as-is. The only difference is the addition of a type
     * property instead of a kind property. Recursively copies all children.
     */
    deeplyCopy(node) {
        if (node.kind === ts.SyntaxKind.JSDocFunctionType) {
            throw node_utils_1.createError(this.ast, node.pos, 'JSDoc types can only be used inside documentation comments.');
        }
        const customType = `TS${SyntaxKind[node.kind]}`;
        /**
         * If the "errorOnUnknownASTType" option is set to true, throw an error,
         * otherwise fallback to just including the unknown type as-is.
         */
        if (this.options.errorOnUnknownASTType && !ts_estree_1.AST_NODE_TYPES[customType]) {
            throw new Error(`Unknown AST_NODE_TYPE: "${customType}"`);
        }
        const result = this.createNode(node, {
            type: customType,
        });
        if ('type' in node) {
            result.typeAnnotation =
                node.type && 'kind' in node.type && ts.isTypeNode(node.type)
                    ? this.convertTypeAnnotation(node.type, node)
                    : null;
        }
        if ('typeArguments' in node) {
            result.typeParameters =
                node.typeArguments && 'pos' in node.typeArguments
                    ? this.convertTypeArgumentsToTypeParameters(node.typeArguments, node)
                    : null;
        }
        if ('typeParameters' in node) {
            result.typeParameters =
                node.typeParameters && 'pos' in node.typeParameters
                    ? this.convertTSTypeParametersToTypeParametersDeclaration(node.typeParameters)
                    : null;
        }
        if ('decorators' in node && node.decorators && node.decorators.length) {
            result.decorators = node.decorators.map(el => this.convertChild(el));
        }
        Object.entries(node)
            .filter(([key]) => !/^(?:_children|kind|parent|pos|end|flags|modifierFlagsCache|jsDoc|type|typeArguments|typeParameters|decorators)$/.test(key))
            .forEach(([key, value]) => {
            if (Array.isArray(value)) {
                result[key] = value.map(el => this.convertChild(el));
            }
            else if (value && typeof value === 'object' && value.kind) {
                // need to check node[key].kind to ensure we don't try to convert a symbol
                result[key] = this.convertChild(value);
            }
            else {
                result[key] = value;
            }
        });
        return result;
    }
    /**
     * Converts a TypeScript JSX node.tagName into an ESTree node.name
     * @param node the tagName object from a JSX ts.Node
     * @param parent
     * @returns the converted ESTree name object
     */
    convertJSXTagName(node, parent) {
        let result;
        switch (node.kind) {
            case SyntaxKind.PropertyAccessExpression:
                if (node.name.kind === SyntaxKind.PrivateIdentifier) {
                    // This is one of the few times where TS explicitly errors, and doesn't even gracefully handle the syntax.
                    // So we shouldn't ever get into this state to begin with.
                    throw new Error('Non-private identifier expected.');
                }
                result = this.createNode(node, {
                    type: ts_estree_1.AST_NODE_TYPES.JSXMemberExpression,
                    object: this.convertJSXTagName(node.expression, parent),
                    property: this.convertJSXTagName(node.name, parent),
                });
                break;
            case SyntaxKind.ThisKeyword:
                result = this.createNode(node, {
                    type: ts_estree_1.AST_NODE_TYPES.JSXIdentifier,
                    name: 'this',
                });
                break;
            case SyntaxKind.Identifier:
            default:
                result = this.createNode(node, {
                    type: ts_estree_1.AST_NODE_TYPES.JSXIdentifier,
                    name: node.text,
                });
                break;
        }
        this.registerTSNodeInNodeMap(node, result);
        return result;
    }
    /**
     * Applies the given TS modifiers to the given result object.
     * @param result
     * @param modifiers original ts.Nodes from the node.modifiers array
     * @returns the current result object will be mutated
     * @deprecated This method adds not standardized `modifiers` property in nodes
     */
    applyModifiersToResult(result, modifiers) {
        if (!modifiers || !modifiers.length) {
            return;
        }
        /**
         * Some modifiers are explicitly handled by applying them as
         * boolean values on the result node. As well as adding them
         * to the result, we remove them from the array, so that they
         * are not handled twice.
         */
        const handledModifierIndices = {};
        for (let i = 0; i < modifiers.length; i++) {
            const modifier = modifiers[i];
            switch (modifier.kind) {
                /**
                 * Ignore ExportKeyword and DefaultKeyword, they are handled
                 * via the fixExports utility function
                 */
                case SyntaxKind.ExportKeyword:
                case SyntaxKind.DefaultKeyword:
                    handledModifierIndices[i] = true;
                    break;
                case SyntaxKind.ConstKeyword:
                    result.const = true;
                    handledModifierIndices[i] = true;
                    break;
                case SyntaxKind.DeclareKeyword:
                    result.declare = true;
                    handledModifierIndices[i] = true;
                    break;
                default:
            }
        }
        /**
         * If there are still valid modifiers available which have
         * not been explicitly handled above, we just convert and
         * add the modifiers array to the result node.
         */
        const remainingModifiers = modifiers.filter((_, i) => !handledModifierIndices[i]);
        if (!remainingModifiers || !remainingModifiers.length) {
            return;
        }
        result.modifiers = remainingModifiers.map(el => this.convertChild(el));
    }
    /**
     * Uses the provided range location to adjust the location data of the given Node
     * @param result The node that will have its location data mutated
     * @param childRange The child node range used to expand location
     */
    fixParentLocation(result, childRange) {
        if (childRange[0] < result.range[0]) {
            result.range[0] = childRange[0];
            result.loc.start = node_utils_1.getLineAndCharacterFor(result.range[0], this.ast);
        }
        if (childRange[1] > result.range[1]) {
            result.range[1] = childRange[1];
            result.loc.end = node_utils_1.getLineAndCharacterFor(result.range[1], this.ast);
        }
    }
    /**
     * Converts a TypeScript node into an ESTree node.
     * The core of the conversion logic:
     * Identify and convert each relevant TypeScript SyntaxKind
     * @param node the child ts.Node
     * @param parent parentNode
     * @returns the converted ESTree node
     */
    convertNode(node, parent) {
        var _a, _b, _c, _d, _e, _f, _g, _h, _j;
        switch (node.kind) {
            case SyntaxKind.SourceFile: {
                return this.createNode(node, {
                    type: ts_estree_1.AST_NODE_TYPES.Program,
                    body: this.convertBodyExpressions(node.statements, node),
                    sourceType: node.externalModuleIndicator ? 'module' : 'script',
                    range: [node.getStart(this.ast), node.endOfFileToken.end],
                });
            }
            case SyntaxKind.Block: {
                return this.createNode(node, {
                    type: ts_estree_1.AST_NODE_TYPES.BlockStatement,
                    body: this.convertBodyExpressions(node.statements, node),
                });
            }
            case SyntaxKind.Identifier: {
                return this.createNode(node, {
                    type: ts_estree_1.AST_NODE_TYPES.Identifier,
                    name: node.text,
                });
            }
            case SyntaxKind.WithStatement:
                return this.createNode(node, {
                    type: ts_estree_1.AST_NODE_TYPES.WithStatement,
                    object: this.convertChild(node.expression),
                    body: this.convertChild(node.statement),
                });
            // Control Flow
            case SyntaxKind.ReturnStatement:
                return this.createNode(node, {
                    type: ts_estree_1.AST_NODE_TYPES.ReturnStatement,
                    argument: this.convertChild(node.expression),
                });
            case SyntaxKind.LabeledStatement:
                return this.createNode(node, {
                    type: ts_estree_1.AST_NODE_TYPES.LabeledStatement,
                    label: this.convertChild(node.label),
                    body: this.convertChild(node.statement),
                });
            case SyntaxKind.ContinueStatement:
                return this.createNode(node, {
                    type: ts_estree_1.AST_NODE_TYPES.ContinueStatement,
                    label: this.convertChild(node.label),
                });
            case SyntaxKind.BreakStatement:
                return this.createNode(node, {
                    type: ts_estree_1.AST_NODE_TYPES.BreakStatement,
                    label: this.convertChild(node.label),
                });
            // Choice
            case SyntaxKind.IfStatement:
                return this.createNode(node, {
                    type: ts_estree_1.AST_NODE_TYPES.IfStatement,
                    test: this.convertChild(node.expression),
                    consequent: this.convertChild(node.thenStatement),
                    alternate: this.convertChild(node.elseStatement),
                });
            case SyntaxKind.SwitchStatement:
                return this.createNode(node, {
                    type: ts_estree_1.AST_NODE_TYPES.SwitchStatement,
                    discriminant: this.convertChild(node.expression),
                    cases: node.caseBlock.clauses.map(el => this.convertChild(el)),
                });
            case SyntaxKind.CaseClause:
            case SyntaxKind.DefaultClause:
                return this.createNode(node, {
                    type: ts_estree_1.AST_NODE_TYPES.SwitchCase,
                    // expression is present in case only
                    test: node.kind === SyntaxKind.CaseClause
                        ? this.convertChild(node.expression)
                        : null,
                    consequent: node.statements.map(el => this.convertChild(el)),
                });
            // Exceptions
            case SyntaxKind.ThrowStatement:
                return this.createNode(node, {
                    type: ts_estree_1.AST_NODE_TYPES.ThrowStatement,
                    argument: this.convertChild(node.expression),
                });
            case SyntaxKind.TryStatement:
                return this.createNode(node, {
                    type: ts_estree_1.AST_NODE_TYPES.TryStatement,
                    block: this.convertChild(node.tryBlock),
                    handler: this.convertChild(node.catchClause),
                    finalizer: this.convertChild(node.finallyBlock),
                });
            case SyntaxKind.CatchClause:
                return this.createNode(node, {
                    type: ts_estree_1.AST_NODE_TYPES.CatchClause,
                    param: node.variableDeclaration
                        ? this.convertBindingNameWithTypeAnnotation(node.variableDeclaration.name, node.variableDeclaration.type)
                        : null,
                    body: this.convertChild(node.block),
                });
            // Loops
            case SyntaxKind.WhileStatement:
                return this.createNode(node, {
                    type: ts_estree_1.AST_NODE_TYPES.WhileStatement,
                    test: this.convertChild(node.expression),
                    body: this.convertChild(node.statement),
                });
            /**
             * Unlike other parsers, TypeScript calls a "DoWhileStatement"
             * a "DoStatement"
             */
            case SyntaxKind.DoStatement:
                return this.createNode(node, {
                    type: ts_estree_1.AST_NODE_TYPES.DoWhileStatement,
                    test: this.convertChild(node.expression),
                    body: this.convertChild(node.statement),
                });
            case SyntaxKind.ForStatement:
                return this.createNode(node, {
                    type: ts_estree_1.AST_NODE_TYPES.ForStatement,
                    init: this.convertChild(node.initializer),
                    test: this.convertChild(node.condition),
                    update: this.convertChild(node.incrementor),
                    body: this.convertChild(node.statement),
                });
            case SyntaxKind.ForInStatement:
                return this.createNode(node, {
                    type: ts_estree_1.AST_NODE_TYPES.ForInStatement,
                    left: this.convertPattern(node.initializer),
                    right: this.convertChild(node.expression),
                    body: this.convertChild(node.statement),
                });
            case SyntaxKind.ForOfStatement:
                return this.createNode(node, {
                    type: ts_estree_1.AST_NODE_TYPES.ForOfStatement,
                    left: this.convertPattern(node.initializer),
                    right: this.convertChild(node.expression),
                    body: this.convertChild(node.statement),
                    await: Boolean(node.awaitModifier &&
                        node.awaitModifier.kind === SyntaxKind.AwaitKeyword),
                });
            // Declarations
            case SyntaxKind.FunctionDeclaration: {
                const isDeclare = node_utils_1.hasModifier(SyntaxKind.DeclareKeyword, node);
                const result = this.createNode(node, {
                    type: isDeclare || !node.body
                        ? ts_estree_1.AST_NODE_TYPES.TSDeclareFunction
                        : ts_estree_1.AST_NODE_TYPES.FunctionDeclaration,
                    id: this.convertChild(node.name),
                    generator: !!node.asteriskToken,
                    expression: false,
                    async: node_utils_1.hasModifier(SyntaxKind.AsyncKeyword, node),
                    params: this.convertParameters(node.parameters),
                    body: this.convertChild(node.body) || undefined,
                });
                // Process returnType
                if (node.type) {
                    result.returnType = this.convertTypeAnnotation(node.type, node);
                }
                if (isDeclare) {
                    result.declare = true;
                }
                // Process typeParameters
                if (node.typeParameters) {
                    result.typeParameters = this.convertTSTypeParametersToTypeParametersDeclaration(node.typeParameters);
                }
                // check for exports
                return this.fixExports(node, result);
            }
            case SyntaxKind.VariableDeclaration: {
                const result = this.createNode(node, {
                    type: ts_estree_1.AST_NODE_TYPES.VariableDeclarator,
                    id: this.convertBindingNameWithTypeAnnotation(node.name, node.type, node),
                    init: this.convertChild(node.initializer),
                });
                if (node.exclamationToken) {
                    result.definite = true;
                }
                return result;
            }
            case SyntaxKind.VariableStatement: {
                const result = this.createNode(node, {
                    type: ts_estree_1.AST_NODE_TYPES.VariableDeclaration,
                    declarations: node.declarationList.declarations.map(el => this.convertChild(el)),
                    kind: node_utils_1.getDeclarationKind(node.declarationList),
                });
                /**
                 * Semantically, decorators are not allowed on variable declarations,
                 * but the TypeScript compiler will parse them and produce a valid AST,
                 * so we handle them here too.
                 */
                if (node.decorators) {
                    result.decorators = node.decorators.map(el => this.convertChild(el));
                }
                if (node_utils_1.hasModifier(SyntaxKind.DeclareKeyword, node)) {
                    result.declare = true;
                }
                // check for exports
                return this.fixExports(node, result);
            }
            // mostly for for-of, for-in
            case SyntaxKind.VariableDeclarationList:
                return this.createNode(node, {
                    type: ts_estree_1.AST_NODE_TYPES.VariableDeclaration,
                    declarations: node.declarations.map(el => this.convertChild(el)),
                    kind: node_utils_1.getDeclarationKind(node),
                });
            // Expressions
            case SyntaxKind.ExpressionStatement:
                return this.createNode(node, {
                    type: ts_estree_1.AST_NODE_TYPES.ExpressionStatement,
                    expression: this.convertChild(node.expression),
                });
            case SyntaxKind.ThisKeyword:
                return this.createNode(node, {
                    type: ts_estree_1.AST_NODE_TYPES.ThisExpression,
                });
            case SyntaxKind.ArrayLiteralExpression: {
                // TypeScript uses ArrayLiteralExpression in destructuring assignment, too
                if (this.allowPattern) {
                    return this.createNode(node, {
                        type: ts_estree_1.AST_NODE_TYPES.ArrayPattern,
                        elements: node.elements.map(el => this.convertPattern(el)),
                    });
                }
                else {
                    return this.createNode(node, {
                        type: ts_estree_1.AST_NODE_TYPES.ArrayExpression,
                        elements: node.elements.map(el => this.convertChild(el)),
                    });
                }
            }
            case SyntaxKind.ObjectLiteralExpression: {
                // TypeScript uses ObjectLiteralExpression in destructuring assignment, too
                if (this.allowPattern) {
                    return this.createNode(node, {
                        type: ts_estree_1.AST_NODE_TYPES.ObjectPattern,
                        properties: node.properties.map(el => this.convertPattern(el)),
                    });
                }
                else {
                    return this.createNode(node, {
                        type: ts_estree_1.AST_NODE_TYPES.ObjectExpression,
                        properties: node.properties.map(el => this.convertChild(el)),
                    });
                }
            }
            case SyntaxKind.PropertyAssignment:
                return this.createNode(node, {
                    type: ts_estree_1.AST_NODE_TYPES.Property,
                    key: this.convertChild(node.name),
                    value: this.converter(node.initializer, node, this.inTypeMode, this.allowPattern),
                    computed: node_utils_1.isComputedProperty(node.name),
                    method: false,
                    shorthand: false,
                    kind: 'init',
                });
            case SyntaxKind.ShorthandPropertyAssignment: {
                if (node.objectAssignmentInitializer) {
                    return this.createNode(node, {
                        type: ts_estree_1.AST_NODE_TYPES.Property,
                        key: this.convertChild(node.name),
                        value: this.createNode(node, {
                            type: ts_estree_1.AST_NODE_TYPES.AssignmentPattern,
                            left: this.convertPattern(node.name),
                            right: this.convertChild(node.objectAssignmentInitializer),
                        }),
                        computed: false,
                        method: false,
                        shorthand: true,
                        kind: 'init',
                    });
                }
                else {
                    return this.createNode(node, {
                        type: ts_estree_1.AST_NODE_TYPES.Property,
                        key: this.convertChild(node.name),
                        value: this.convertChild(node.name),
                        computed: false,
                        method: false,
                        shorthand: true,
                        kind: 'init',
                    });
                }
            }
            case SyntaxKind.ComputedPropertyName:
                return this.convertChild(node.expression);
            case SyntaxKind.PropertyDeclaration: {
                const isAbstract = node_utils_1.hasModifier(SyntaxKind.AbstractKeyword, node);
                const result = this.createNode(node, {
                    type: isAbstract
                        ? ts_estree_1.AST_NODE_TYPES.TSAbstractClassProperty
                        : ts_estree_1.AST_NODE_TYPES.ClassProperty,
                    key: this.convertChild(node.name),
                    value: this.convertChild(node.initializer),
                    computed: node_utils_1.isComputedProperty(node.name),
                    static: node_utils_1.hasModifier(SyntaxKind.StaticKeyword, node),
                    readonly: node_utils_1.hasModifier(SyntaxKind.ReadonlyKeyword, node) || undefined,
                    declare: node_utils_1.hasModifier(SyntaxKind.DeclareKeyword, node),
                });
                if (node.type) {
                    result.typeAnnotation = this.convertTypeAnnotation(node.type, node);
                }
                if (node.decorators) {
                    result.decorators = node.decorators.map(el => this.convertChild(el));
                }
                const accessibility = node_utils_1.getTSNodeAccessibility(node);
                if (accessibility) {
                    result.accessibility = accessibility;
                }
                if ((node.name.kind === SyntaxKind.Identifier ||
                    node.name.kind === SyntaxKind.ComputedPropertyName) &&
                    node.questionToken) {
                    result.optional = true;
                }
                if (node.exclamationToken) {
                    result.definite = true;
                }
                if (result.key.type === ts_estree_1.AST_NODE_TYPES.Literal && node.questionToken) {
                    result.optional = true;
                }
                return result;
            }
            case SyntaxKind.GetAccessor:
            case SyntaxKind.SetAccessor:
            case SyntaxKind.MethodDeclaration: {
                const method = this.createNode(node, {
                    type: !node.body
                        ? ts_estree_1.AST_NODE_TYPES.TSEmptyBodyFunctionExpression
                        : ts_estree_1.AST_NODE_TYPES.FunctionExpression,
                    id: null,
                    generator: !!node.asteriskToken,
                    expression: false,
                    async: node_utils_1.hasModifier(SyntaxKind.AsyncKeyword, node),
                    body: this.convertChild(node.body),
                    range: [node.parameters.pos - 1, node.end],
                    params: [],
                });
                if (node.type) {
                    method.returnType = this.convertTypeAnnotation(node.type, node);
                }
                // Process typeParameters
                if (node.typeParameters) {
                    method.typeParameters = this.convertTSTypeParametersToTypeParametersDeclaration(node.typeParameters);
                    this.fixParentLocation(method, method.typeParameters.range);
                }
                let result;
                if (parent.kind === SyntaxKind.ObjectLiteralExpression) {
                    method.params = node.parameters.map(el => this.convertChild(el));
                    result = this.createNode(node, {
                        type: ts_estree_1.AST_NODE_TYPES.Property,
                        key: this.convertChild(node.name),
                        value: method,
                        computed: node_utils_1.isComputedProperty(node.name),
                        method: node.kind === SyntaxKind.MethodDeclaration,
                        shorthand: false,
                        kind: 'init',
                    });
                }
                else {
                    // class
                    /**
                     * Unlike in object literal methods, class method params can have decorators
                     */
                    method.params = this.convertParameters(node.parameters);
                    /**
                     * TypeScript class methods can be defined as "abstract"
                     */
                    const methodDefinitionType = node_utils_1.hasModifier(SyntaxKind.AbstractKeyword, node)
                        ? ts_estree_1.AST_NODE_TYPES.TSAbstractMethodDefinition
                        : ts_estree_1.AST_NODE_TYPES.MethodDefinition;
                    result = this.createNode(node, {
                        type: methodDefinitionType,
                        key: this.convertChild(node.name),
                        value: method,
                        computed: node_utils_1.isComputedProperty(node.name),
                        static: node_utils_1.hasModifier(SyntaxKind.StaticKeyword, node),
                        kind: 'method',
                    });
                    if (node.decorators) {
                        result.decorators = node.decorators.map(el => this.convertChild(el));
                    }
                    const accessibility = node_utils_1.getTSNodeAccessibility(node);
                    if (accessibility) {
                        result.accessibility = accessibility;
                    }
                }
                if (node.questionToken) {
                    result.optional = true;
                }
                if (node.kind === SyntaxKind.GetAccessor) {
                    result.kind = 'get';
                }
                else if (node.kind === SyntaxKind.SetAccessor) {
                    result.kind = 'set';
                }
                else if (!result.static &&
                    node.name.kind === SyntaxKind.StringLiteral &&
                    node.name.text === 'constructor' &&
                    result.type !== ts_estree_1.AST_NODE_TYPES.Property) {
                    result.kind = 'constructor';
                }
                return result;
            }
            // TypeScript uses this even for static methods named "constructor"
            case SyntaxKind.Constructor: {
                const lastModifier = node_utils_1.getLastModifier(node);
                const constructorToken = (lastModifier && node_utils_1.findNextToken(lastModifier, node, this.ast)) ||
                    node.getFirstToken();
                const constructor = this.createNode(node, {
                    type: !node.body
                        ? ts_estree_1.AST_NODE_TYPES.TSEmptyBodyFunctionExpression
                        : ts_estree_1.AST_NODE_TYPES.FunctionExpression,
                    id: null,
                    params: this.convertParameters(node.parameters),
                    generator: false,
                    expression: false,
                    async: false,
                    body: this.convertChild(node.body),
                    range: [node.parameters.pos - 1, node.end],
                });
                // Process typeParameters
                if (node.typeParameters) {
                    constructor.typeParameters = this.convertTSTypeParametersToTypeParametersDeclaration(node.typeParameters);
                    this.fixParentLocation(constructor, constructor.typeParameters.range);
                }
                // Process returnType
                if (node.type) {
                    constructor.returnType = this.convertTypeAnnotation(node.type, node);
                }
                const constructorKey = this.createNode(node, {
                    type: ts_estree_1.AST_NODE_TYPES.Identifier,
                    name: 'constructor',
                    range: [constructorToken.getStart(this.ast), constructorToken.end],
                });
                const isStatic = node_utils_1.hasModifier(SyntaxKind.StaticKeyword, node);
                const result = this.createNode(node, {
                    type: node_utils_1.hasModifier(SyntaxKind.AbstractKeyword, node)
                        ? ts_estree_1.AST_NODE_TYPES.TSAbstractMethodDefinition
                        : ts_estree_1.AST_NODE_TYPES.MethodDefinition,
                    key: constructorKey,
                    value: constructor,
                    computed: false,
                    static: isStatic,
                    kind: isStatic ? 'method' : 'constructor',
                });
                const accessibility = node_utils_1.getTSNodeAccessibility(node);
                if (accessibility) {
                    result.accessibility = accessibility;
                }
                return result;
            }
            case SyntaxKind.FunctionExpression: {
                const result = this.createNode(node, {
                    type: ts_estree_1.AST_NODE_TYPES.FunctionExpression,
                    id: this.convertChild(node.name),
                    generator: !!node.asteriskToken,
                    params: this.convertParameters(node.parameters),
                    body: this.convertChild(node.body),
                    async: node_utils_1.hasModifier(SyntaxKind.AsyncKeyword, node),
                    expression: false,
                });
                // Process returnType
                if (node.type) {
                    result.returnType = this.convertTypeAnnotation(node.type, node);
                }
                // Process typeParameters
                if (node.typeParameters) {
                    result.typeParameters = this.convertTSTypeParametersToTypeParametersDeclaration(node.typeParameters);
                }
                return result;
            }
            case SyntaxKind.SuperKeyword:
                return this.createNode(node, {
                    type: ts_estree_1.AST_NODE_TYPES.Super,
                });
            case SyntaxKind.ArrayBindingPattern:
                return this.createNode(node, {
                    type: ts_estree_1.AST_NODE_TYPES.ArrayPattern,
                    elements: node.elements.map(el => this.convertPattern(el)),
                });
            // occurs with missing array elements like [,]
            case SyntaxKind.OmittedExpression:
                return null;
            case SyntaxKind.ObjectBindingPattern:
                return this.createNode(node, {
                    type: ts_estree_1.AST_NODE_TYPES.ObjectPattern,
                    properties: node.elements.map(el => this.convertPattern(el)),
                });
            case SyntaxKind.BindingElement: {
                if (parent.kind === SyntaxKind.ArrayBindingPattern) {
                    const arrayItem = this.convertChild(node.name, parent);
                    if (node.initializer) {
                        return this.createNode(node, {
                            type: ts_estree_1.AST_NODE_TYPES.AssignmentPattern,
                            left: arrayItem,
                            right: this.convertChild(node.initializer),
                        });
                    }
                    else if (node.dotDotDotToken) {
                        return this.createNode(node, {
                            type: ts_estree_1.AST_NODE_TYPES.RestElement,
                            argument: arrayItem,
                        });
                    }
                    else {
                        return arrayItem;
                    }
                }
                else {
                    let result;
                    if (node.dotDotDotToken) {
                        result = this.createNode(node, {
                            type: ts_estree_1.AST_NODE_TYPES.RestElement,
                            argument: this.convertChild((_a = node.propertyName) !== null && _a !== void 0 ? _a : node.name),
                        });
                    }
                    else {
                        result = this.createNode(node, {
                            type: ts_estree_1.AST_NODE_TYPES.Property,
                            key: this.convertChild((_b = node.propertyName) !== null && _b !== void 0 ? _b : node.name),
                            value: this.convertChild(node.name),
                            computed: Boolean(node.propertyName &&
                                node.propertyName.kind === SyntaxKind.ComputedPropertyName),
                            method: false,
                            shorthand: !node.propertyName,
                            kind: 'init',
                        });
                    }
                    if (node.initializer) {
                        result.value = this.createNode(node, {
                            type: ts_estree_1.AST_NODE_TYPES.AssignmentPattern,
                            left: this.convertChild(node.name),
                            right: this.convertChild(node.initializer),
                            range: [node.name.getStart(this.ast), node.initializer.end],
                        });
                    }
                    return result;
                }
            }
            case SyntaxKind.ArrowFunction: {
                const result = this.createNode(node, {
                    type: ts_estree_1.AST_NODE_TYPES.ArrowFunctionExpression,
                    generator: false,
                    id: null,
                    params: this.convertParameters(node.parameters),
                    body: this.convertChild(node.body),
                    async: node_utils_1.hasModifier(SyntaxKind.AsyncKeyword, node),
                    expression: node.body.kind !== SyntaxKind.Block,
                });
                // Process returnType
                if (node.type) {
                    result.returnType = this.convertTypeAnnotation(node.type, node);
                }
                // Process typeParameters
                if (node.typeParameters) {
                    result.typeParameters = this.convertTSTypeParametersToTypeParametersDeclaration(node.typeParameters);
                }
                return result;
            }
            case SyntaxKind.YieldExpression:
                return this.createNode(node, {
                    type: ts_estree_1.AST_NODE_TYPES.YieldExpression,
                    delegate: !!node.asteriskToken,
                    argument: this.convertChild(node.expression),
                });
            case SyntaxKind.AwaitExpression:
                return this.createNode(node, {
                    type: ts_estree_1.AST_NODE_TYPES.AwaitExpression,
                    argument: this.convertChild(node.expression),
                });
            // Template Literals
            case SyntaxKind.NoSubstitutionTemplateLiteral:
                return this.createNode(node, {
                    type: ts_estree_1.AST_NODE_TYPES.TemplateLiteral,
                    quasis: [
                        this.createNode(node, {
                            type: ts_estree_1.AST_NODE_TYPES.TemplateElement,
                            value: {
                                raw: this.ast.text.slice(node.getStart(this.ast) + 1, node.end - 1),
                                cooked: node.text,
                            },
                            tail: true,
                        }),
                    ],
                    expressions: [],
                });
            case SyntaxKind.TemplateExpression: {
                const result = this.createNode(node, {
                    type: ts_estree_1.AST_NODE_TYPES.TemplateLiteral,
                    quasis: [this.convertChild(node.head)],
                    expressions: [],
                });
                node.templateSpans.forEach(templateSpan => {
                    result.expressions.push(this.convertChild(templateSpan.expression));
                    result.quasis.push(this.convertChild(templateSpan.literal));
                });
                return result;
            }
            case SyntaxKind.TaggedTemplateExpression:
                return this.createNode(node, {
                    type: ts_estree_1.AST_NODE_TYPES.TaggedTemplateExpression,
                    typeParameters: node.typeArguments
                        ? this.convertTypeArgumentsToTypeParameters(node.typeArguments, node)
                        : undefined,
                    tag: this.convertChild(node.tag),
                    quasi: this.convertChild(node.template),
                });
            case SyntaxKind.TemplateHead:
            case SyntaxKind.TemplateMiddle:
            case SyntaxKind.TemplateTail: {
                const tail = node.kind === SyntaxKind.TemplateTail;
                return this.createNode(node, {
                    type: ts_estree_1.AST_NODE_TYPES.TemplateElement,
                    value: {
                        raw: this.ast.text.slice(node.getStart(this.ast) + 1, node.end - (tail ? 1 : 2)),
                        cooked: node.text,
                    },
                    tail,
                });
            }
            // Patterns
            case SyntaxKind.SpreadAssignment:
            case SyntaxKind.SpreadElement: {
                if (this.allowPattern) {
                    return this.createNode(node, {
                        type: ts_estree_1.AST_NODE_TYPES.RestElement,
                        argument: this.convertPattern(node.expression),
                    });
                }
                else {
                    return this.createNode(node, {
                        type: ts_estree_1.AST_NODE_TYPES.SpreadElement,
                        argument: this.convertChild(node.expression),
                    });
                }
            }
            case SyntaxKind.Parameter: {
                let parameter;
                let result;
                if (node.dotDotDotToken) {
                    parameter = result = this.createNode(node, {
                        type: ts_estree_1.AST_NODE_TYPES.RestElement,
                        argument: this.convertChild(node.name),
                    });
                }
                else if (node.initializer) {
                    parameter = this.convertChild(node.name);
                    result = this.createNode(node, {
                        type: ts_estree_1.AST_NODE_TYPES.AssignmentPattern,
                        left: parameter,
                        right: this.convertChild(node.initializer),
                    });
                    if (node.modifiers) {
                        // AssignmentPattern should not contain modifiers in range
                        result.range[0] = parameter.range[0];
                        result.loc = node_utils_1.getLocFor(result.range[0], result.range[1], this.ast);
                    }
                }
                else {
                    parameter = result = this.convertChild(node.name, parent);
                }
                if (node.type) {
                    parameter.typeAnnotation = this.convertTypeAnnotation(node.type, node);
                    this.fixParentLocation(parameter, parameter.typeAnnotation.range);
                }
                if (node.questionToken) {
                    if (node.questionToken.end > parameter.range[1]) {
                        parameter.range[1] = node.questionToken.end;
                        parameter.loc.end = node_utils_1.getLineAndCharacterFor(parameter.range[1], this.ast);
                    }
                    parameter.optional = true;
                }
                if (node.modifiers) {
                    return this.createNode(node, {
                        type: ts_estree_1.AST_NODE_TYPES.TSParameterProperty,
                        accessibility: (_c = node_utils_1.getTSNodeAccessibility(node)) !== null && _c !== void 0 ? _c : undefined,
                        readonly: node_utils_1.hasModifier(SyntaxKind.ReadonlyKeyword, node) || undefined,
                        static: node_utils_1.hasModifier(SyntaxKind.StaticKeyword, node) || undefined,
                        export: node_utils_1.hasModifier(SyntaxKind.ExportKeyword, node) || undefined,
                        parameter: result,
                    });
                }
                return result;
            }
            // Classes
            case SyntaxKind.ClassDeclaration:
            case SyntaxKind.ClassExpression: {
                const heritageClauses = (_d = node.heritageClauses) !== null && _d !== void 0 ? _d : [];
                const classNodeType = node.kind === SyntaxKind.ClassDeclaration
                    ? ts_estree_1.AST_NODE_TYPES.ClassDeclaration
                    : ts_estree_1.AST_NODE_TYPES.ClassExpression;
                const superClass = heritageClauses.find(clause => clause.token === SyntaxKind.ExtendsKeyword);
                const implementsClause = heritageClauses.find(clause => clause.token === SyntaxKind.ImplementsKeyword);
                const result = this.createNode(node, {
                    type: classNodeType,
                    id: this.convertChild(node.name),
                    body: this.createNode(node, {
                        type: ts_estree_1.AST_NODE_TYPES.ClassBody,
                        body: [],
                        range: [node.members.pos - 1, node.end],
                    }),
                    superClass: (superClass === null || superClass === void 0 ? void 0 : superClass.types[0]) ? this.convertChild(superClass.types[0].expression)
                        : null,
                });
                if (superClass) {
                    if (superClass.types.length > 1) {
                        throw node_utils_1.createError(this.ast, superClass.types[1].pos, 'Classes can only extend a single class.');
                    }
                    if ((_e = superClass.types[0]) === null || _e === void 0 ? void 0 : _e.typeArguments) {
                        result.superTypeParameters = this.convertTypeArgumentsToTypeParameters(superClass.types[0].typeArguments, superClass.types[0]);
                    }
                }
                if (node.typeParameters) {
                    result.typeParameters = this.convertTSTypeParametersToTypeParametersDeclaration(node.typeParameters);
                }
                if (implementsClause) {
                    result.implements = implementsClause.types.map(el => this.convertChild(el));
                }
                /**
                 * TypeScript class declarations can be defined as "abstract"
                 */
                if (node_utils_1.hasModifier(SyntaxKind.AbstractKeyword, node)) {
                    result.abstract = true;
                }
                if (node_utils_1.hasModifier(SyntaxKind.DeclareKeyword, node)) {
                    result.declare = true;
                }
                if (node.decorators) {
                    result.decorators = node.decorators.map(el => this.convertChild(el));
                }
                const filteredMembers = node.members.filter(node_utils_1.isESTreeClassMember);
                if (filteredMembers.length) {
                    result.body.body = filteredMembers.map(el => this.convertChild(el));
                }
                // check for exports
                return this.fixExports(node, result);
            }
            // Modules
            case SyntaxKind.ModuleBlock:
                return this.createNode(node, {
                    type: ts_estree_1.AST_NODE_TYPES.TSModuleBlock,
                    body: this.convertBodyExpressions(node.statements, node),
                });
            case SyntaxKind.ImportDeclaration: {
                const result = this.createNode(node, {
                    type: ts_estree_1.AST_NODE_TYPES.ImportDeclaration,
                    source: this.convertChild(node.moduleSpecifier),
                    specifiers: [],
                    importKind: 'value',
                });
                if (node.importClause) {
                    if (node.importClause.isTypeOnly) {
                        result.importKind = 'type';
                    }
                    if (node.importClause.name) {
                        result.specifiers.push(this.convertChild(node.importClause));
                    }
                    if (node.importClause.namedBindings) {
                        switch (node.importClause.namedBindings.kind) {
                            case SyntaxKind.NamespaceImport:
                                result.specifiers.push(this.convertChild(node.importClause.namedBindings));
                                break;
                            case SyntaxKind.NamedImports:
                                result.specifiers = result.specifiers.concat(node.importClause.namedBindings.elements.map(el => this.convertChild(el)));
                                break;
                        }
                    }
                }
                return result;
            }
            case SyntaxKind.NamespaceImport:
                return this.createNode(node, {
                    type: ts_estree_1.AST_NODE_TYPES.ImportNamespaceSpecifier,
                    local: this.convertChild(node.name),
                });
            case SyntaxKind.ImportSpecifier:
                return this.createNode(node, {
                    type: ts_estree_1.AST_NODE_TYPES.ImportSpecifier,
                    local: this.convertChild(node.name),
                    imported: this.convertChild((_f = node.propertyName) !== null && _f !== void 0 ? _f : node.name),
                });
            case SyntaxKind.ImportClause: {
                const local = this.convertChild(node.name);
                return this.createNode(node, {
                    type: ts_estree_1.AST_NODE_TYPES.ImportDefaultSpecifier,
                    local,
                    range: local.range,
                });
            }
            case SyntaxKind.ExportDeclaration:
                if (((_g = node.exportClause) === null || _g === void 0 ? void 0 : _g.kind) === SyntaxKind.NamedExports) {
                    return this.createNode(node, {
                        type: ts_estree_1.AST_NODE_TYPES.ExportNamedDeclaration,
                        source: this.convertChild(node.moduleSpecifier),
                        specifiers: node.exportClause.elements.map(el => this.convertChild(el)),
                        exportKind: node.isTypeOnly ? 'type' : 'value',
                        declaration: null,
                    });
                }
                else {
                    return this.createNode(node, {
                        type: ts_estree_1.AST_NODE_TYPES.ExportAllDeclaration,
                        source: this.convertChild(node.moduleSpecifier),
                        exportKind: node.isTypeOnly ? 'type' : 'value',
                        exported: 
                        // note - for compat with 3.7.x, where node.exportClause is always undefined and
                        //        SyntaxKind.NamespaceExport does not exist yet (i.e. is undefined), this
                        //        cannot be shortened to an optional chain, or else you end up with
                        //        undefined === undefined, and the true path will hard error at runtime
                        node.exportClause &&
                            node.exportClause.kind === SyntaxKind.NamespaceExport
                            ? this.convertChild(node.exportClause.name)
                            : null,
                    });
                }
            case SyntaxKind.ExportSpecifier:
                return this.createNode(node, {
                    type: ts_estree_1.AST_NODE_TYPES.ExportSpecifier,
                    local: this.convertChild((_h = node.propertyName) !== null && _h !== void 0 ? _h : node.name),
                    exported: this.convertChild(node.name),
                });
            case SyntaxKind.ExportAssignment:
                if (node.isExportEquals) {
                    return this.createNode(node, {
                        type: ts_estree_1.AST_NODE_TYPES.TSExportAssignment,
                        expression: this.convertChild(node.expression),
                    });
                }
                else {
                    return this.createNode(node, {
                        type: ts_estree_1.AST_NODE_TYPES.ExportDefaultDeclaration,
                        declaration: this.convertChild(node.expression),
                        exportKind: 'value',
                    });
                }
            // Unary Operations
            case SyntaxKind.PrefixUnaryExpression:
            case SyntaxKind.PostfixUnaryExpression: {
                const operator = node_utils_1.getTextForTokenKind(node.operator);
                /**
                 * ESTree uses UpdateExpression for ++/--
                 */
                if (operator === '++' || operator === '--') {
                    return this.createNode(node, {
                        type: ts_estree_1.AST_NODE_TYPES.UpdateExpression,
                        operator,
                        prefix: node.kind === SyntaxKind.PrefixUnaryExpression,
                        argument: this.convertChild(node.operand),
                    });
                }
                else {
                    return this.createNode(node, {
                        type: ts_estree_1.AST_NODE_TYPES.UnaryExpression,
                        operator,
                        prefix: node.kind === SyntaxKind.PrefixUnaryExpression,
                        argument: this.convertChild(node.operand),
                    });
                }
            }
            case SyntaxKind.DeleteExpression:
                return this.createNode(node, {
                    type: ts_estree_1.AST_NODE_TYPES.UnaryExpression,
                    operator: 'delete',
                    prefix: true,
                    argument: this.convertChild(node.expression),
                });
            case SyntaxKind.VoidExpression:
                return this.createNode(node, {
                    type: ts_estree_1.AST_NODE_TYPES.UnaryExpression,
                    operator: 'void',
                    prefix: true,
                    argument: this.convertChild(node.expression),
                });
            case SyntaxKind.TypeOfExpression:
                return this.createNode(node, {
                    type: ts_estree_1.AST_NODE_TYPES.UnaryExpression,
                    operator: 'typeof',
                    prefix: true,
                    argument: this.convertChild(node.expression),
                });
            case SyntaxKind.TypeOperator:
                return this.createNode(node, {
                    type: ts_estree_1.AST_NODE_TYPES.TSTypeOperator,
                    operator: node_utils_1.getTextForTokenKind(node.operator),
                    typeAnnotation: this.convertChild(node.type),
                });
            // Binary Operations
            case SyntaxKind.BinaryExpression: {
                // TypeScript uses BinaryExpression for sequences as well
                if (node_utils_1.isComma(node.operatorToken)) {
                    const result = this.createNode(node, {
                        type: ts_estree_1.AST_NODE_TYPES.SequenceExpression,
                        expressions: [],
                    });
                    const left = this.convertChild(node.left);
                    if (left.type === ts_estree_1.AST_NODE_TYPES.SequenceExpression &&
                        node.left.kind !== SyntaxKind.ParenthesizedExpression) {
                        result.expressions = result.expressions.concat(left.expressions);
                    }
                    else {
                        result.expressions.push(left);
                    }
                    result.expressions.push(this.convertChild(node.right));
                    return result;
                }
                else {
                    const type = node_utils_1.getBinaryExpressionType(node.operatorToken);
                    if (this.allowPattern &&
                        type === ts_estree_1.AST_NODE_TYPES.AssignmentExpression) {
                        return this.createNode(node, {
                            type: ts_estree_1.AST_NODE_TYPES.AssignmentPattern,
                            left: this.convertPattern(node.left, node),
                            right: this.convertChild(node.right),
                        });
                    }
                    return this.createNode(node, {
                        type,
                        operator: node_utils_1.getTextForTokenKind(node.operatorToken.kind),
                        left: this.converter(node.left, node, this.inTypeMode, type === ts_estree_1.AST_NODE_TYPES.AssignmentExpression),
                        right: this.convertChild(node.right),
                    });
                }
            }
            case SyntaxKind.PropertyAccessExpression: {
                const object = this.convertChild(node.expression);
                const property = this.convertChild(node.name);
                const computed = false;
                const result = this.createNode(node, {
                    type: ts_estree_1.AST_NODE_TYPES.MemberExpression,
                    object,
                    property,
                    computed,
                    optional: node.questionDotToken !== undefined,
                });
                return this.convertChainExpression(result, node);
            }
            case SyntaxKind.ElementAccessExpression: {
                const object = this.convertChild(node.expression);
                const property = this.convertChild(node.argumentExpression);
                const computed = true;
                const result = this.createNode(node, {
                    type: ts_estree_1.AST_NODE_TYPES.MemberExpression,
                    object,
                    property,
                    computed,
                    optional: node.questionDotToken !== undefined,
                });
                return this.convertChainExpression(result, node);
            }
            case SyntaxKind.CallExpression: {
                if (node.expression.kind === SyntaxKind.ImportKeyword) {
                    if (node.arguments.length !== 1) {
                        throw node_utils_1.createError(this.ast, node.arguments.pos, 'Dynamic import must have one specifier as an argument.');
                    }
                    return this.createNode(node, {
                        type: ts_estree_1.AST_NODE_TYPES.ImportExpression,
                        source: this.convertChild(node.arguments[0]),
                    });
                }
                const callee = this.convertChild(node.expression);
                const args = node.arguments.map(el => this.convertChild(el));
                const result = this.createNode(node, {
                    type: ts_estree_1.AST_NODE_TYPES.CallExpression,
                    callee,
                    arguments: args,
                    optional: node.questionDotToken !== undefined,
                });
                if (node.typeArguments) {
                    result.typeParameters = this.convertTypeArgumentsToTypeParameters(node.typeArguments, node);
                }
                return this.convertChainExpression(result, node);
            }
            case SyntaxKind.NewExpression: {
                // NOTE - NewExpression cannot have an optional chain in it
                const result = this.createNode(node, {
                    type: ts_estree_1.AST_NODE_TYPES.NewExpression,
                    callee: this.convertChild(node.expression),
                    arguments: node.arguments
                        ? node.arguments.map(el => this.convertChild(el))
                        : [],
                });
                if (node.typeArguments) {
                    result.typeParameters = this.convertTypeArgumentsToTypeParameters(node.typeArguments, node);
                }
                return result;
            }
            case SyntaxKind.ConditionalExpression:
                return this.createNode(node, {
                    type: ts_estree_1.AST_NODE_TYPES.ConditionalExpression,
                    test: this.convertChild(node.condition),
                    consequent: this.convertChild(node.whenTrue),
                    alternate: this.convertChild(node.whenFalse),
                });
            case SyntaxKind.MetaProperty: {
                return this.createNode(node, {
                    type: ts_estree_1.AST_NODE_TYPES.MetaProperty,
                    meta: this.createNode(
                    // TODO: do we really want to convert it to Token?
                    node.getFirstToken(), {
                        type: ts_estree_1.AST_NODE_TYPES.Identifier,
                        name: node_utils_1.getTextForTokenKind(node.keywordToken),
                    }),
                    property: this.convertChild(node.name),
                });
            }
            case SyntaxKind.Decorator: {
                return this.createNode(node, {
                    type: ts_estree_1.AST_NODE_TYPES.Decorator,
                    expression: this.convertChild(node.expression),
                });
            }
            // Literals
            case SyntaxKind.StringLiteral: {
                const result = this.createNode(node, {
                    type: ts_estree_1.AST_NODE_TYPES.Literal,
                    raw: '',
                    value: '',
                });
                result.raw = this.ast.text.slice(result.range[0], result.range[1]);
                if ('name' in parent && parent.name === node) {
                    result.value = node.text;
                }
                else {
                    result.value = node_utils_1.unescapeStringLiteralText(node.text);
                }
                return result;
            }
            case SyntaxKind.NumericLiteral: {
                return this.createNode(node, {
                    type: ts_estree_1.AST_NODE_TYPES.Literal,
                    value: Number(node.text),
                    raw: node.getText(),
                });
            }
            case SyntaxKind.BigIntLiteral: {
                const range = node_utils_1.getRange(node, this.ast);
                const rawValue = this.ast.text.slice(range[0], range[1]);
                const bigint = rawValue
                    // remove suffix `n`
                    .slice(0, -1)
                    // `BigInt` doesn't accept numeric separator
                    // and `bigint` property should not include numeric separator
                    .replace(/_/g, '');
                const value = typeof BigInt !== 'undefined' ? BigInt(bigint) : null;
                return this.createNode(node, {
                    type: ts_estree_1.AST_NODE_TYPES.Literal,
                    raw: rawValue,
                    value: value,
                    bigint: value === null ? bigint : String(value),
                    range,
                });
            }
            case SyntaxKind.RegularExpressionLiteral: {
                const pattern = node.text.slice(1, node.text.lastIndexOf('/'));
                const flags = node.text.slice(node.text.lastIndexOf('/') + 1);
                let regex = null;
                try {
                    regex = new RegExp(pattern, flags);
                }
                catch (exception) {
                    regex = null;
                }
                return this.createNode(node, {
                    type: ts_estree_1.AST_NODE_TYPES.Literal,
                    value: regex,
                    raw: node.text,
                    regex: {
                        pattern,
                        flags,
                    },
                });
            }
            case SyntaxKind.TrueKeyword:
                return this.createNode(node, {
                    type: ts_estree_1.AST_NODE_TYPES.Literal,
                    value: true,
                    raw: 'true',
                });
            case SyntaxKind.FalseKeyword:
                return this.createNode(node, {
                    type: ts_estree_1.AST_NODE_TYPES.Literal,
                    value: false,
                    raw: 'false',
                });
            case SyntaxKind.NullKeyword: {
                if (!version_check_1.typescriptVersionIsAtLeast['4.0'] && this.inTypeMode) {
                    // 4.0 started nesting null types inside a LiteralType node, but we still need to support pre-4.0
                    return this.createNode(node, {
                        type: ts_estree_1.AST_NODE_TYPES.TSNullKeyword,
                    });
                }
                return this.createNode(node, {
                    type: ts_estree_1.AST_NODE_TYPES.Literal,
                    value: null,
                    raw: 'null',
                });
            }
            case SyntaxKind.EmptyStatement:
                return this.createNode(node, {
                    type: ts_estree_1.AST_NODE_TYPES.EmptyStatement,
                });
            case SyntaxKind.DebuggerStatement:
                return this.createNode(node, {
                    type: ts_estree_1.AST_NODE_TYPES.DebuggerStatement,
                });
            // JSX
            case SyntaxKind.JsxElement:
                return this.createNode(node, {
                    type: ts_estree_1.AST_NODE_TYPES.JSXElement,
                    openingElement: this.convertChild(node.openingElement),
                    closingElement: this.convertChild(node.closingElement),
                    children: node.children.map(el => this.convertChild(el)),
                });
            case SyntaxKind.JsxFragment:
                return this.createNode(node, {
                    type: ts_estree_1.AST_NODE_TYPES.JSXFragment,
                    openingFragment: this.convertChild(node.openingFragment),
                    closingFragment: this.convertChild(node.closingFragment),
                    children: node.children.map(el => this.convertChild(el)),
                });
            case SyntaxKind.JsxSelfClosingElement: {
                return this.createNode(node, {
                    type: ts_estree_1.AST_NODE_TYPES.JSXElement,
                    /**
                     * Convert SyntaxKind.JsxSelfClosingElement to SyntaxKind.JsxOpeningElement,
                     * TypeScript does not seem to have the idea of openingElement when tag is self-closing
                     */
                    openingElement: this.createNode(node, {
                        type: ts_estree_1.AST_NODE_TYPES.JSXOpeningElement,
                        typeParameters: node.typeArguments
                            ? this.convertTypeArgumentsToTypeParameters(node.typeArguments, node)
                            : undefined,
                        selfClosing: true,
                        name: this.convertJSXTagName(node.tagName, node),
                        attributes: node.attributes.properties.map(el => this.convertChild(el)),
                        range: node_utils_1.getRange(node, this.ast),
                    }),
                    closingElement: null,
                    children: [],
                });
            }
            case SyntaxKind.JsxOpeningElement:
                return this.createNode(node, {
                    type: ts_estree_1.AST_NODE_TYPES.JSXOpeningElement,
                    typeParameters: node.typeArguments
                        ? this.convertTypeArgumentsToTypeParameters(node.typeArguments, node)
                        : undefined,
                    selfClosing: false,
                    name: this.convertJSXTagName(node.tagName, node),
                    attributes: node.attributes.properties.map(el => this.convertChild(el)),
                });
            case SyntaxKind.JsxClosingElement:
                return this.createNode(node, {
                    type: ts_estree_1.AST_NODE_TYPES.JSXClosingElement,
                    name: this.convertJSXTagName(node.tagName, node),
                });
            case SyntaxKind.JsxOpeningFragment:
                return this.createNode(node, {
                    type: ts_estree_1.AST_NODE_TYPES.JSXOpeningFragment,
                });
            case SyntaxKind.JsxClosingFragment:
                return this.createNode(node, {
                    type: ts_estree_1.AST_NODE_TYPES.JSXClosingFragment,
                });
            case SyntaxKind.JsxExpression: {
                const expression = node.expression
                    ? this.convertChild(node.expression)
                    : this.createNode(node, {
                        type: ts_estree_1.AST_NODE_TYPES.JSXEmptyExpression,
                        range: [node.getStart(this.ast) + 1, node.getEnd() - 1],
                    });
                if (node.dotDotDotToken) {
                    return this.createNode(node, {
                        type: ts_estree_1.AST_NODE_TYPES.JSXSpreadChild,
                        expression,
                    });
                }
                else {
                    return this.createNode(node, {
                        type: ts_estree_1.AST_NODE_TYPES.JSXExpressionContainer,
                        expression,
                    });
                }
            }
            case SyntaxKind.JsxAttribute: {
                const attributeName = this.convertChild(node.name);
                attributeName.type = ts_estree_1.AST_NODE_TYPES.JSXIdentifier;
                return this.createNode(node, {
                    type: ts_estree_1.AST_NODE_TYPES.JSXAttribute,
                    name: attributeName,
                    value: this.convertChild(node.initializer),
                });
            }
            /**
             * The JSX AST changed the node type for string literals
             * inside a JSX Element from `Literal` to `JSXText`. We
             * provide a flag to support both types until `Literal`
             * node type is deprecated in ESLint v5.
             */
            case SyntaxKind.JsxText: {
                const start = node.getFullStart();
                const end = node.getEnd();
                if (this.options.useJSXTextNode) {
                    return this.createNode(node, {
                        type: ts_estree_1.AST_NODE_TYPES.JSXText,
                        value: this.ast.text.slice(start, end),
                        raw: this.ast.text.slice(start, end),
                        range: [start, end],
                    });
                }
                else {
                    return this.createNode(node, {
                        type: ts_estree_1.AST_NODE_TYPES.Literal,
                        value: this.ast.text.slice(start, end),
                        raw: this.ast.text.slice(start, end),
                        range: [start, end],
                    });
                }
            }
            case SyntaxKind.JsxSpreadAttribute:
                return this.createNode(node, {
                    type: ts_estree_1.AST_NODE_TYPES.JSXSpreadAttribute,
                    argument: this.convertChild(node.expression),
                });
            case SyntaxKind.QualifiedName: {
                return this.createNode(node, {
                    type: ts_estree_1.AST_NODE_TYPES.TSQualifiedName,
                    left: this.convertChild(node.left),
                    right: this.convertChild(node.right),
                });
            }
            // TypeScript specific
            case SyntaxKind.TypeReference: {
                return this.createNode(node, {
                    type: ts_estree_1.AST_NODE_TYPES.TSTypeReference,
                    typeName: this.convertType(node.typeName),
                    typeParameters: node.typeArguments
                        ? this.convertTypeArgumentsToTypeParameters(node.typeArguments, node)
                        : undefined,
                });
            }
            case SyntaxKind.TypeParameter: {
                return this.createNode(node, {
                    type: ts_estree_1.AST_NODE_TYPES.TSTypeParameter,
                    name: this.convertType(node.name),
                    constraint: node.constraint
                        ? this.convertType(node.constraint)
                        : undefined,
                    default: node.default ? this.convertType(node.default) : undefined,
                });
            }
            case SyntaxKind.ThisType:
                return this.createNode(node, {
                    type: ts_estree_1.AST_NODE_TYPES.TSThisType,
                });
            case SyntaxKind.AnyKeyword:
            case SyntaxKind.BigIntKeyword:
            case SyntaxKind.BooleanKeyword:
            case SyntaxKind.NeverKeyword:
            case SyntaxKind.NumberKeyword:
            case SyntaxKind.ObjectKeyword:
            case SyntaxKind.StringKeyword:
            case SyntaxKind.SymbolKeyword:
            case SyntaxKind.UnknownKeyword:
            case SyntaxKind.VoidKeyword:
            case SyntaxKind.UndefinedKeyword: {
                return this.createNode(node, {
                    type: ts_estree_1.AST_NODE_TYPES[`TS${SyntaxKind[node.kind]}`],
                });
            }
            case SyntaxKind.NonNullExpression: {
                const nnExpr = this.createNode(node, {
                    type: ts_estree_1.AST_NODE_TYPES.TSNonNullExpression,
                    expression: this.convertChild(node.expression),
                });
                return this.convertChainExpression(nnExpr, node);
            }
            case SyntaxKind.TypeLiteral: {
                return this.createNode(node, {
                    type: ts_estree_1.AST_NODE_TYPES.TSTypeLiteral,
                    members: node.members.map(el => this.convertChild(el)),
                });
            }
            case SyntaxKind.ArrayType: {
                return this.createNode(node, {
                    type: ts_estree_1.AST_NODE_TYPES.TSArrayType,
                    elementType: this.convertType(node.elementType),
                });
            }
            case SyntaxKind.IndexedAccessType: {
                return this.createNode(node, {
                    type: ts_estree_1.AST_NODE_TYPES.TSIndexedAccessType,
                    objectType: this.convertType(node.objectType),
                    indexType: this.convertType(node.indexType),
                });
            }
            case SyntaxKind.ConditionalType: {
                return this.createNode(node, {
                    type: ts_estree_1.AST_NODE_TYPES.TSConditionalType,
                    checkType: this.convertType(node.checkType),
                    extendsType: this.convertType(node.extendsType),
                    trueType: this.convertType(node.trueType),
                    falseType: this.convertType(node.falseType),
                });
            }
            case SyntaxKind.TypeQuery: {
                return this.createNode(node, {
                    type: ts_estree_1.AST_NODE_TYPES.TSTypeQuery,
                    exprName: this.convertType(node.exprName),
                });
            }
            case SyntaxKind.MappedType: {
                const result = this.createNode(node, {
                    type: ts_estree_1.AST_NODE_TYPES.TSMappedType,
                    typeParameter: this.convertType(node.typeParameter),
                });
                if (node.readonlyToken) {
                    if (node.readonlyToken.kind === SyntaxKind.ReadonlyKeyword) {
                        result.readonly = true;
                    }
                    else {
                        result.readonly = node_utils_1.getTextForTokenKind(node.readonlyToken.kind);
                    }
                }
                if (node.questionToken) {
                    if (node.questionToken.kind === SyntaxKind.QuestionToken) {
                        result.optional = true;
                    }
                    else {
                        result.optional = node_utils_1.getTextForTokenKind(node.questionToken.kind);
                    }
                }
                if (node.type) {
                    result.typeAnnotation = this.convertType(node.type);
                }
                return result;
            }
            case SyntaxKind.ParenthesizedExpression:
                return this.convertChild(node.expression, parent);
            case SyntaxKind.TypeAliasDeclaration: {
                const result = this.createNode(node, {
                    type: ts_estree_1.AST_NODE_TYPES.TSTypeAliasDeclaration,
                    id: this.convertChild(node.name),
                    typeAnnotation: this.convertType(node.type),
                });
                if (node_utils_1.hasModifier(SyntaxKind.DeclareKeyword, node)) {
                    result.declare = true;
                }
                // Process typeParameters
                if (node.typeParameters) {
                    result.typeParameters = this.convertTSTypeParametersToTypeParametersDeclaration(node.typeParameters);
                }
                // check for exports
                return this.fixExports(node, result);
            }
            case SyntaxKind.MethodSignature: {
                const result = this.createNode(node, {
                    type: ts_estree_1.AST_NODE_TYPES.TSMethodSignature,
                    computed: node_utils_1.isComputedProperty(node.name),
                    key: this.convertChild(node.name),
                    params: this.convertParameters(node.parameters),
                });
                if (node_utils_1.isOptional(node)) {
                    result.optional = true;
                }
                if (node.type) {
                    result.returnType = this.convertTypeAnnotation(node.type, node);
                }
                if (node_utils_1.hasModifier(SyntaxKind.ReadonlyKeyword, node)) {
                    result.readonly = true;
                }
                if (node.typeParameters) {
                    result.typeParameters = this.convertTSTypeParametersToTypeParametersDeclaration(node.typeParameters);
                }
                const accessibility = node_utils_1.getTSNodeAccessibility(node);
                if (accessibility) {
                    result.accessibility = accessibility;
                }
                if (node_utils_1.hasModifier(SyntaxKind.ExportKeyword, node)) {
                    result.export = true;
                }
                if (node_utils_1.hasModifier(SyntaxKind.StaticKeyword, node)) {
                    result.static = true;
                }
                return result;
            }
            case SyntaxKind.PropertySignature: {
                const result = this.createNode(node, {
                    type: ts_estree_1.AST_NODE_TYPES.TSPropertySignature,
                    optional: node_utils_1.isOptional(node) || undefined,
                    computed: node_utils_1.isComputedProperty(node.name),
                    key: this.convertChild(node.name),
                    typeAnnotation: node.type
                        ? this.convertTypeAnnotation(node.type, node)
                        : undefined,
                    initializer: this.convertChild(node.initializer) || undefined,
                    readonly: node_utils_1.hasModifier(SyntaxKind.ReadonlyKeyword, node) || undefined,
                    static: node_utils_1.hasModifier(SyntaxKind.StaticKeyword, node) || undefined,
                    export: node_utils_1.hasModifier(SyntaxKind.ExportKeyword, node) || undefined,
                });
                const accessibility = node_utils_1.getTSNodeAccessibility(node);
                if (accessibility) {
                    result.accessibility = accessibility;
                }
                return result;
            }
            case SyntaxKind.IndexSignature: {
                const result = this.createNode(node, {
                    type: ts_estree_1.AST_NODE_TYPES.TSIndexSignature,
                    parameters: node.parameters.map(el => this.convertChild(el)),
                });
                if (node.type) {
                    result.typeAnnotation = this.convertTypeAnnotation(node.type, node);
                }
                if (node_utils_1.hasModifier(SyntaxKind.ReadonlyKeyword, node)) {
                    result.readonly = true;
                }
                const accessibility = node_utils_1.getTSNodeAccessibility(node);
                if (accessibility) {
                    result.accessibility = accessibility;
                }
                if (node_utils_1.hasModifier(SyntaxKind.ExportKeyword, node)) {
                    result.export = true;
                }
                if (node_utils_1.hasModifier(SyntaxKind.StaticKeyword, node)) {
                    result.static = true;
                }
                return result;
            }
            case SyntaxKind.ConstructorType:
            case SyntaxKind.FunctionType:
            case SyntaxKind.ConstructSignature:
            case SyntaxKind.CallSignature: {
                let type;
                switch (node.kind) {
                    case SyntaxKind.ConstructSignature:
                        type = ts_estree_1.AST_NODE_TYPES.TSConstructSignatureDeclaration;
                        break;
                    case SyntaxKind.CallSignature:
                        type = ts_estree_1.AST_NODE_TYPES.TSCallSignatureDeclaration;
                        break;
                    case SyntaxKind.FunctionType:
                        type = ts_estree_1.AST_NODE_TYPES.TSFunctionType;
                        break;
                    case SyntaxKind.ConstructorType:
                    default:
                        type = ts_estree_1.AST_NODE_TYPES.TSConstructorType;
                        break;
                }
                const result = this.createNode(node, {
                    type: type,
                    params: this.convertParameters(node.parameters),
                });
                if (node.type) {
                    result.returnType = this.convertTypeAnnotation(node.type, node);
                }
                if (node.typeParameters) {
                    result.typeParameters = this.convertTSTypeParametersToTypeParametersDeclaration(node.typeParameters);
                }
                return result;
            }
            case SyntaxKind.ExpressionWithTypeArguments: {
                const result = this.createNode(node, {
                    type: parent && parent.kind === SyntaxKind.InterfaceDeclaration
                        ? ts_estree_1.AST_NODE_TYPES.TSInterfaceHeritage
                        : ts_estree_1.AST_NODE_TYPES.TSClassImplements,
                    expression: this.convertChild(node.expression),
                });
                if (node.typeArguments) {
                    result.typeParameters = this.convertTypeArgumentsToTypeParameters(node.typeArguments, node);
                }
                return result;
            }
            case SyntaxKind.InterfaceDeclaration: {
                const interfaceHeritageClauses = (_j = node.heritageClauses) !== null && _j !== void 0 ? _j : [];
                const result = this.createNode(node, {
                    type: ts_estree_1.AST_NODE_TYPES.TSInterfaceDeclaration,
                    body: this.createNode(node, {
                        type: ts_estree_1.AST_NODE_TYPES.TSInterfaceBody,
                        body: node.members.map(member => this.convertChild(member)),
                        range: [node.members.pos - 1, node.end],
                    }),
                    id: this.convertChild(node.name),
                });
                if (node.typeParameters) {
                    result.typeParameters = this.convertTSTypeParametersToTypeParametersDeclaration(node.typeParameters);
                }
                if (interfaceHeritageClauses.length > 0) {
                    const interfaceExtends = [];
                    const interfaceImplements = [];
                    for (const heritageClause of interfaceHeritageClauses) {
                        if (heritageClause.token === SyntaxKind.ExtendsKeyword) {
                            for (const n of heritageClause.types) {
                                interfaceExtends.push(this.convertChild(n, node));
                            }
                        }
                        else {
                            for (const n of heritageClause.types) {
                                interfaceImplements.push(this.convertChild(n, node));
                            }
                        }
                    }
                    if (interfaceExtends.length) {
                        result.extends = interfaceExtends;
                    }
                    if (interfaceImplements.length) {
                        result.implements = interfaceImplements;
                    }
                }
                if (node_utils_1.hasModifier(SyntaxKind.AbstractKeyword, node)) {
                    result.abstract = true;
                }
                if (node_utils_1.hasModifier(SyntaxKind.DeclareKeyword, node)) {
                    result.declare = true;
                }
                // check for exports
                return this.fixExports(node, result);
            }
            case SyntaxKind.TypePredicate: {
                const result = this.createNode(node, {
                    type: ts_estree_1.AST_NODE_TYPES.TSTypePredicate,
                    asserts: node.assertsModifier !== undefined,
                    parameterName: this.convertChild(node.parameterName),
                    typeAnnotation: null,
                });
                /**
                 * Specific fix for type-guard location data
                 */
                if (node.type) {
                    result.typeAnnotation = this.convertTypeAnnotation(node.type, node);
                    result.typeAnnotation.loc = result.typeAnnotation.typeAnnotation.loc;
                    result.typeAnnotation.range =
                        result.typeAnnotation.typeAnnotation.range;
                }
                return result;
            }
            case SyntaxKind.ImportType:
                return this.createNode(node, {
                    type: ts_estree_1.AST_NODE_TYPES.TSImportType,
                    isTypeOf: !!node.isTypeOf,
                    parameter: this.convertChild(node.argument),
                    qualifier: this.convertChild(node.qualifier),
                    typeParameters: node.typeArguments
                        ? this.convertTypeArgumentsToTypeParameters(node.typeArguments, node)
                        : null,
                });
            case SyntaxKind.EnumDeclaration: {
                const result = this.createNode(node, {
                    type: ts_estree_1.AST_NODE_TYPES.TSEnumDeclaration,
                    id: this.convertChild(node.name),
                    members: node.members.map(el => this.convertChild(el)),
                });
                // apply modifiers first...
                this.applyModifiersToResult(result, node.modifiers);
                // ...then check for exports
                return this.fixExports(node, result);
            }
            case SyntaxKind.EnumMember: {
                const result = this.createNode(node, {
                    type: ts_estree_1.AST_NODE_TYPES.TSEnumMember,
                    id: this.convertChild(node.name),
                });
                if (node.initializer) {
                    result.initializer = this.convertChild(node.initializer);
                }
                if (node.name.kind === ts.SyntaxKind.ComputedPropertyName) {
                    result.computed = true;
                }
                return result;
            }
            case SyntaxKind.ModuleDeclaration: {
                const result = this.createNode(node, {
                    type: ts_estree_1.AST_NODE_TYPES.TSModuleDeclaration,
                    id: this.convertChild(node.name),
                });
                if (node.body) {
                    result.body = this.convertChild(node.body);
                }
                // apply modifiers first...
                this.applyModifiersToResult(result, node.modifiers);
                if (node.flags & ts.NodeFlags.GlobalAugmentation) {
                    result.global = true;
                }
                // ...then check for exports
                return this.fixExports(node, result);
            }
            // TypeScript specific types
            case SyntaxKind.ParenthesizedType: {
                return this.createNode(node, {
                    type: ts_estree_1.AST_NODE_TYPES.TSParenthesizedType,
                    typeAnnotation: this.convertType(node.type),
                });
            }
            case SyntaxKind.UnionType: {
                return this.createNode(node, {
                    type: ts_estree_1.AST_NODE_TYPES.TSUnionType,
                    types: node.types.map(el => this.convertType(el)),
                });
            }
            case SyntaxKind.IntersectionType: {
                return this.createNode(node, {
                    type: ts_estree_1.AST_NODE_TYPES.TSIntersectionType,
                    types: node.types.map(el => this.convertType(el)),
                });
            }
            case SyntaxKind.AsExpression: {
                return this.createNode(node, {
                    type: ts_estree_1.AST_NODE_TYPES.TSAsExpression,
                    expression: this.convertChild(node.expression),
                    typeAnnotation: this.convertType(node.type),
                });
            }
            case SyntaxKind.InferType: {
                return this.createNode(node, {
                    type: ts_estree_1.AST_NODE_TYPES.TSInferType,
                    typeParameter: this.convertType(node.typeParameter),
                });
            }
            case SyntaxKind.LiteralType: {
                if (version_check_1.typescriptVersionIsAtLeast['4.0'] &&
                    node.literal.kind === SyntaxKind.NullKeyword) {
                    // 4.0 started nesting null types inside a LiteralType node
                    // but our AST is designed around the old way of null being a keyword
                    return this.createNode(node.literal, {
                        type: ts_estree_1.AST_NODE_TYPES.TSNullKeyword,
                    });
                }
                else {
                    return this.createNode(node, {
                        type: ts_estree_1.AST_NODE_TYPES.TSLiteralType,
                        literal: this.convertType(node.literal),
                    });
                }
            }
            case SyntaxKind.TypeAssertionExpression: {
                return this.createNode(node, {
                    type: ts_estree_1.AST_NODE_TYPES.TSTypeAssertion,
                    typeAnnotation: this.convertType(node.type),
                    expression: this.convertChild(node.expression),
                });
            }
            case SyntaxKind.ImportEqualsDeclaration: {
                return this.createNode(node, {
                    type: ts_estree_1.AST_NODE_TYPES.TSImportEqualsDeclaration,
                    id: this.convertChild(node.name),
                    moduleReference: this.convertChild(node.moduleReference),
                    isExport: node_utils_1.hasModifier(SyntaxKind.ExportKeyword, node),
                });
            }
            case SyntaxKind.ExternalModuleReference: {
                return this.createNode(node, {
                    type: ts_estree_1.AST_NODE_TYPES.TSExternalModuleReference,
                    expression: this.convertChild(node.expression),
                });
            }
            case SyntaxKind.NamespaceExportDeclaration: {
                return this.createNode(node, {
                    type: ts_estree_1.AST_NODE_TYPES.TSNamespaceExportDeclaration,
                    id: this.convertChild(node.name),
                });
            }
            case SyntaxKind.AbstractKeyword: {
                return this.createNode(node, {
                    type: ts_estree_1.AST_NODE_TYPES.TSAbstractKeyword,
                });
            }
            // Tuple
            case SyntaxKind.TupleType: {
                // In TS 4.0, the `elementTypes` property was changed to `elements`.
                // To support both at compile time, we cast to access the newer version
                // if the former does not exist.
                const elementTypes = 'elementTypes' in node
                    ? node.elementTypes.map((el) => this.convertType(el))
                    : node.elements.map((el) => this.convertType(el));
                return this.createNode(node, {
                    type: ts_estree_1.AST_NODE_TYPES.TSTupleType,
                    elementTypes,
                });
            }
            case SyntaxKind.NamedTupleMember: {
                const member = this.createNode(node, {
                    type: ts_estree_1.AST_NODE_TYPES.TSNamedTupleMember,
                    elementType: this.convertType(node.type, node),
                    label: this.convertChild(node.name, node),
                    optional: node.questionToken != null,
                });
                if (node.dotDotDotToken) {
                    // adjust the start to account for the "..."
                    member.range[0] = member.label.range[0];
                    member.loc.start = member.label.loc.start;
                    return this.createNode(node, {
                        type: ts_estree_1.AST_NODE_TYPES.TSRestType,
                        typeAnnotation: member,
                    });
                }
                return member;
            }
            case SyntaxKind.OptionalType: {
                return this.createNode(node, {
                    type: ts_estree_1.AST_NODE_TYPES.TSOptionalType,
                    typeAnnotation: this.convertType(node.type),
                });
            }
            case SyntaxKind.RestType: {
                return this.createNode(node, {
                    type: ts_estree_1.AST_NODE_TYPES.TSRestType,
                    typeAnnotation: this.convertType(node.type),
                });
            }
            default:
                return this.deeplyCopy(node);
        }
    }
}
exports.Converter = Converter;
//# sourceMappingURL=convert.js.map