import { N as NoTarget, c as createSourceFile, S as SyntaxKind, a as createDiagnostic, m as mutate, i as isArray, I as IdentifierKind, D as DuplicateTracker, b as isDefined, d as createRekeyableMap, M as MultiKeyMap, e as createDiagnosticCreator } from './index-rzprlTNi.js';
import { i as isPathAbsolute, g as getDirectoryPath, j as joinPaths } from './path-utils-DDA4_T0g.js';

var commonjsGlobal = typeof globalThis !== 'undefined' ? globalThis : typeof window !== 'undefined' ? window : typeof global !== 'undefined' ? global : typeof self !== 'undefined' ? self : {};

function getAugmentedNamespace(n) {
  if (n.__esModule) return n;
  var f = n.default;
	if (typeof f == "function") {
		var a = function a () {
			if (this instanceof a) {
        return Reflect.construct(f, arguments, this.constructor);
			}
			return f.apply(this, arguments);
		};
		a.prototype = f.prototype;
  } else a = {};
  Object.defineProperty(a, '__esModule', {value: true});
	Object.keys(n).forEach(function (k) {
		var d = Object.getOwnPropertyDescriptor(n, k);
		Object.defineProperty(a, k, d.get ? d : {
			enumerable: true,
			get: function () {
				return n[k];
			}
		});
	});
	return a;
}

var ajv = {exports: {}};

var core$2 = {};

var validate = {};

var boolSchema = {};

var errors = {};

var codegen = {};

var code$1 = {};

var hasRequiredCode$1;

function requireCode$1 () {
	if (hasRequiredCode$1) return code$1;
	hasRequiredCode$1 = 1;
	(function (exports) {
		Object.defineProperty(exports, "__esModule", { value: true });
		exports.regexpCode = exports.getEsmExportName = exports.getProperty = exports.safeStringify = exports.stringify = exports.strConcat = exports.addCodeArg = exports.str = exports._ = exports.nil = exports._Code = exports.Name = exports.IDENTIFIER = exports._CodeOrName = void 0;
		class _CodeOrName {
		}
		exports._CodeOrName = _CodeOrName;
		exports.IDENTIFIER = /^[a-z$_][a-z$_0-9]*$/i;
		class Name extends _CodeOrName {
		    constructor(s) {
		        super();
		        if (!exports.IDENTIFIER.test(s))
		            throw new Error("CodeGen: name must be a valid identifier");
		        this.str = s;
		    }
		    toString() {
		        return this.str;
		    }
		    emptyStr() {
		        return false;
		    }
		    get names() {
		        return { [this.str]: 1 };
		    }
		}
		exports.Name = Name;
		class _Code extends _CodeOrName {
		    constructor(code) {
		        super();
		        this._items = typeof code === "string" ? [code] : code;
		    }
		    toString() {
		        return this.str;
		    }
		    emptyStr() {
		        if (this._items.length > 1)
		            return false;
		        const item = this._items[0];
		        return item === "" || item === '""';
		    }
		    get str() {
		        var _a;
		        return ((_a = this._str) !== null && _a !== void 0 ? _a : (this._str = this._items.reduce((s, c) => `${s}${c}`, "")));
		    }
		    get names() {
		        var _a;
		        return ((_a = this._names) !== null && _a !== void 0 ? _a : (this._names = this._items.reduce((names, c) => {
		            if (c instanceof Name)
		                names[c.str] = (names[c.str] || 0) + 1;
		            return names;
		        }, {})));
		    }
		}
		exports._Code = _Code;
		exports.nil = new _Code("");
		function _(strs, ...args) {
		    const code = [strs[0]];
		    let i = 0;
		    while (i < args.length) {
		        addCodeArg(code, args[i]);
		        code.push(strs[++i]);
		    }
		    return new _Code(code);
		}
		exports._ = _;
		const plus = new _Code("+");
		function str(strs, ...args) {
		    const expr = [safeStringify(strs[0])];
		    let i = 0;
		    while (i < args.length) {
		        expr.push(plus);
		        addCodeArg(expr, args[i]);
		        expr.push(plus, safeStringify(strs[++i]));
		    }
		    optimize(expr);
		    return new _Code(expr);
		}
		exports.str = str;
		function addCodeArg(code, arg) {
		    if (arg instanceof _Code)
		        code.push(...arg._items);
		    else if (arg instanceof Name)
		        code.push(arg);
		    else
		        code.push(interpolate(arg));
		}
		exports.addCodeArg = addCodeArg;
		function optimize(expr) {
		    let i = 1;
		    while (i < expr.length - 1) {
		        if (expr[i] === plus) {
		            const res = mergeExprItems(expr[i - 1], expr[i + 1]);
		            if (res !== undefined) {
		                expr.splice(i - 1, 3, res);
		                continue;
		            }
		            expr[i++] = "+";
		        }
		        i++;
		    }
		}
		function mergeExprItems(a, b) {
		    if (b === '""')
		        return a;
		    if (a === '""')
		        return b;
		    if (typeof a == "string") {
		        if (b instanceof Name || a[a.length - 1] !== '"')
		            return;
		        if (typeof b != "string")
		            return `${a.slice(0, -1)}${b}"`;
		        if (b[0] === '"')
		            return a.slice(0, -1) + b.slice(1);
		        return;
		    }
		    if (typeof b == "string" && b[0] === '"' && !(a instanceof Name))
		        return `"${a}${b.slice(1)}`;
		    return;
		}
		function strConcat(c1, c2) {
		    return c2.emptyStr() ? c1 : c1.emptyStr() ? c2 : str `${c1}${c2}`;
		}
		exports.strConcat = strConcat;
		// TODO do not allow arrays here
		function interpolate(x) {
		    return typeof x == "number" || typeof x == "boolean" || x === null
		        ? x
		        : safeStringify(Array.isArray(x) ? x.join(",") : x);
		}
		function stringify(x) {
		    return new _Code(safeStringify(x));
		}
		exports.stringify = stringify;
		function safeStringify(x) {
		    return JSON.stringify(x)
		        .replace(/\u2028/g, "\\u2028")
		        .replace(/\u2029/g, "\\u2029");
		}
		exports.safeStringify = safeStringify;
		function getProperty(key) {
		    return typeof key == "string" && exports.IDENTIFIER.test(key) ? new _Code(`.${key}`) : _ `[${key}]`;
		}
		exports.getProperty = getProperty;
		//Does best effort to format the name properly
		function getEsmExportName(key) {
		    if (typeof key == "string" && exports.IDENTIFIER.test(key)) {
		        return new _Code(`${key}`);
		    }
		    throw new Error(`CodeGen: invalid export name: ${key}, use explicit $id name mapping`);
		}
		exports.getEsmExportName = getEsmExportName;
		function regexpCode(rx) {
		    return new _Code(rx.toString());
		}
		exports.regexpCode = regexpCode;
		
	} (code$1));
	return code$1;
}

var scope = {};

var hasRequiredScope;

function requireScope () {
	if (hasRequiredScope) return scope;
	hasRequiredScope = 1;
	(function (exports) {
		Object.defineProperty(exports, "__esModule", { value: true });
		exports.ValueScope = exports.ValueScopeName = exports.Scope = exports.varKinds = exports.UsedValueState = void 0;
		const code_1 = requireCode$1();
		class ValueError extends Error {
		    constructor(name) {
		        super(`CodeGen: "code" for ${name} not defined`);
		        this.value = name.value;
		    }
		}
		var UsedValueState;
		(function (UsedValueState) {
		    UsedValueState[UsedValueState["Started"] = 0] = "Started";
		    UsedValueState[UsedValueState["Completed"] = 1] = "Completed";
		})(UsedValueState || (exports.UsedValueState = UsedValueState = {}));
		exports.varKinds = {
		    const: new code_1.Name("const"),
		    let: new code_1.Name("let"),
		    var: new code_1.Name("var"),
		};
		class Scope {
		    constructor({ prefixes, parent } = {}) {
		        this._names = {};
		        this._prefixes = prefixes;
		        this._parent = parent;
		    }
		    toName(nameOrPrefix) {
		        return nameOrPrefix instanceof code_1.Name ? nameOrPrefix : this.name(nameOrPrefix);
		    }
		    name(prefix) {
		        return new code_1.Name(this._newName(prefix));
		    }
		    _newName(prefix) {
		        const ng = this._names[prefix] || this._nameGroup(prefix);
		        return `${prefix}${ng.index++}`;
		    }
		    _nameGroup(prefix) {
		        var _a, _b;
		        if (((_b = (_a = this._parent) === null || _a === void 0 ? void 0 : _a._prefixes) === null || _b === void 0 ? void 0 : _b.has(prefix)) || (this._prefixes && !this._prefixes.has(prefix))) {
		            throw new Error(`CodeGen: prefix "${prefix}" is not allowed in this scope`);
		        }
		        return (this._names[prefix] = { prefix, index: 0 });
		    }
		}
		exports.Scope = Scope;
		class ValueScopeName extends code_1.Name {
		    constructor(prefix, nameStr) {
		        super(nameStr);
		        this.prefix = prefix;
		    }
		    setValue(value, { property, itemIndex }) {
		        this.value = value;
		        this.scopePath = (0, code_1._) `.${new code_1.Name(property)}[${itemIndex}]`;
		    }
		}
		exports.ValueScopeName = ValueScopeName;
		const line = (0, code_1._) `\n`;
		class ValueScope extends Scope {
		    constructor(opts) {
		        super(opts);
		        this._values = {};
		        this._scope = opts.scope;
		        this.opts = { ...opts, _n: opts.lines ? line : code_1.nil };
		    }
		    get() {
		        return this._scope;
		    }
		    name(prefix) {
		        return new ValueScopeName(prefix, this._newName(prefix));
		    }
		    value(nameOrPrefix, value) {
		        var _a;
		        if (value.ref === undefined)
		            throw new Error("CodeGen: ref must be passed in value");
		        const name = this.toName(nameOrPrefix);
		        const { prefix } = name;
		        const valueKey = (_a = value.key) !== null && _a !== void 0 ? _a : value.ref;
		        let vs = this._values[prefix];
		        if (vs) {
		            const _name = vs.get(valueKey);
		            if (_name)
		                return _name;
		        }
		        else {
		            vs = this._values[prefix] = new Map();
		        }
		        vs.set(valueKey, name);
		        const s = this._scope[prefix] || (this._scope[prefix] = []);
		        const itemIndex = s.length;
		        s[itemIndex] = value.ref;
		        name.setValue(value, { property: prefix, itemIndex });
		        return name;
		    }
		    getValue(prefix, keyOrRef) {
		        const vs = this._values[prefix];
		        if (!vs)
		            return;
		        return vs.get(keyOrRef);
		    }
		    scopeRefs(scopeName, values = this._values) {
		        return this._reduceValues(values, (name) => {
		            if (name.scopePath === undefined)
		                throw new Error(`CodeGen: name "${name}" has no value`);
		            return (0, code_1._) `${scopeName}${name.scopePath}`;
		        });
		    }
		    scopeCode(values = this._values, usedValues, getCode) {
		        return this._reduceValues(values, (name) => {
		            if (name.value === undefined)
		                throw new Error(`CodeGen: name "${name}" has no value`);
		            return name.value.code;
		        }, usedValues, getCode);
		    }
		    _reduceValues(values, valueCode, usedValues = {}, getCode) {
		        let code = code_1.nil;
		        for (const prefix in values) {
		            const vs = values[prefix];
		            if (!vs)
		                continue;
		            const nameSet = (usedValues[prefix] = usedValues[prefix] || new Map());
		            vs.forEach((name) => {
		                if (nameSet.has(name))
		                    return;
		                nameSet.set(name, UsedValueState.Started);
		                let c = valueCode(name);
		                if (c) {
		                    const def = this.opts.es5 ? exports.varKinds.var : exports.varKinds.const;
		                    code = (0, code_1._) `${code}${def} ${name} = ${c};${this.opts._n}`;
		                }
		                else if ((c = getCode === null || getCode === void 0 ? void 0 : getCode(name))) {
		                    code = (0, code_1._) `${code}${c}${this.opts._n}`;
		                }
		                else {
		                    throw new ValueError(name);
		                }
		                nameSet.set(name, UsedValueState.Completed);
		            });
		        }
		        return code;
		    }
		}
		exports.ValueScope = ValueScope;
		
	} (scope));
	return scope;
}

var hasRequiredCodegen;

function requireCodegen () {
	if (hasRequiredCodegen) return codegen;
	hasRequiredCodegen = 1;
	(function (exports) {
		Object.defineProperty(exports, "__esModule", { value: true });
		exports.or = exports.and = exports.not = exports.CodeGen = exports.operators = exports.varKinds = exports.ValueScopeName = exports.ValueScope = exports.Scope = exports.Name = exports.regexpCode = exports.stringify = exports.getProperty = exports.nil = exports.strConcat = exports.str = exports._ = void 0;
		const code_1 = requireCode$1();
		const scope_1 = requireScope();
		var code_2 = requireCode$1();
		Object.defineProperty(exports, "_", { enumerable: true, get: function () { return code_2._; } });
		Object.defineProperty(exports, "str", { enumerable: true, get: function () { return code_2.str; } });
		Object.defineProperty(exports, "strConcat", { enumerable: true, get: function () { return code_2.strConcat; } });
		Object.defineProperty(exports, "nil", { enumerable: true, get: function () { return code_2.nil; } });
		Object.defineProperty(exports, "getProperty", { enumerable: true, get: function () { return code_2.getProperty; } });
		Object.defineProperty(exports, "stringify", { enumerable: true, get: function () { return code_2.stringify; } });
		Object.defineProperty(exports, "regexpCode", { enumerable: true, get: function () { return code_2.regexpCode; } });
		Object.defineProperty(exports, "Name", { enumerable: true, get: function () { return code_2.Name; } });
		var scope_2 = requireScope();
		Object.defineProperty(exports, "Scope", { enumerable: true, get: function () { return scope_2.Scope; } });
		Object.defineProperty(exports, "ValueScope", { enumerable: true, get: function () { return scope_2.ValueScope; } });
		Object.defineProperty(exports, "ValueScopeName", { enumerable: true, get: function () { return scope_2.ValueScopeName; } });
		Object.defineProperty(exports, "varKinds", { enumerable: true, get: function () { return scope_2.varKinds; } });
		exports.operators = {
		    GT: new code_1._Code(">"),
		    GTE: new code_1._Code(">="),
		    LT: new code_1._Code("<"),
		    LTE: new code_1._Code("<="),
		    EQ: new code_1._Code("==="),
		    NEQ: new code_1._Code("!=="),
		    NOT: new code_1._Code("!"),
		    OR: new code_1._Code("||"),
		    AND: new code_1._Code("&&"),
		    ADD: new code_1._Code("+"),
		};
		class Node {
		    optimizeNodes() {
		        return this;
		    }
		    optimizeNames(_names, _constants) {
		        return this;
		    }
		}
		class Def extends Node {
		    constructor(varKind, name, rhs) {
		        super();
		        this.varKind = varKind;
		        this.name = name;
		        this.rhs = rhs;
		    }
		    render({ es5, _n }) {
		        const varKind = es5 ? scope_1.varKinds.var : this.varKind;
		        const rhs = this.rhs === undefined ? "" : ` = ${this.rhs}`;
		        return `${varKind} ${this.name}${rhs};` + _n;
		    }
		    optimizeNames(names, constants) {
		        if (!names[this.name.str])
		            return;
		        if (this.rhs)
		            this.rhs = optimizeExpr(this.rhs, names, constants);
		        return this;
		    }
		    get names() {
		        return this.rhs instanceof code_1._CodeOrName ? this.rhs.names : {};
		    }
		}
		class Assign extends Node {
		    constructor(lhs, rhs, sideEffects) {
		        super();
		        this.lhs = lhs;
		        this.rhs = rhs;
		        this.sideEffects = sideEffects;
		    }
		    render({ _n }) {
		        return `${this.lhs} = ${this.rhs};` + _n;
		    }
		    optimizeNames(names, constants) {
		        if (this.lhs instanceof code_1.Name && !names[this.lhs.str] && !this.sideEffects)
		            return;
		        this.rhs = optimizeExpr(this.rhs, names, constants);
		        return this;
		    }
		    get names() {
		        const names = this.lhs instanceof code_1.Name ? {} : { ...this.lhs.names };
		        return addExprNames(names, this.rhs);
		    }
		}
		class AssignOp extends Assign {
		    constructor(lhs, op, rhs, sideEffects) {
		        super(lhs, rhs, sideEffects);
		        this.op = op;
		    }
		    render({ _n }) {
		        return `${this.lhs} ${this.op}= ${this.rhs};` + _n;
		    }
		}
		class Label extends Node {
		    constructor(label) {
		        super();
		        this.label = label;
		        this.names = {};
		    }
		    render({ _n }) {
		        return `${this.label}:` + _n;
		    }
		}
		class Break extends Node {
		    constructor(label) {
		        super();
		        this.label = label;
		        this.names = {};
		    }
		    render({ _n }) {
		        const label = this.label ? ` ${this.label}` : "";
		        return `break${label};` + _n;
		    }
		}
		class Throw extends Node {
		    constructor(error) {
		        super();
		        this.error = error;
		    }
		    render({ _n }) {
		        return `throw ${this.error};` + _n;
		    }
		    get names() {
		        return this.error.names;
		    }
		}
		class AnyCode extends Node {
		    constructor(code) {
		        super();
		        this.code = code;
		    }
		    render({ _n }) {
		        return `${this.code};` + _n;
		    }
		    optimizeNodes() {
		        return `${this.code}` ? this : undefined;
		    }
		    optimizeNames(names, constants) {
		        this.code = optimizeExpr(this.code, names, constants);
		        return this;
		    }
		    get names() {
		        return this.code instanceof code_1._CodeOrName ? this.code.names : {};
		    }
		}
		class ParentNode extends Node {
		    constructor(nodes = []) {
		        super();
		        this.nodes = nodes;
		    }
		    render(opts) {
		        return this.nodes.reduce((code, n) => code + n.render(opts), "");
		    }
		    optimizeNodes() {
		        const { nodes } = this;
		        let i = nodes.length;
		        while (i--) {
		            const n = nodes[i].optimizeNodes();
		            if (Array.isArray(n))
		                nodes.splice(i, 1, ...n);
		            else if (n)
		                nodes[i] = n;
		            else
		                nodes.splice(i, 1);
		        }
		        return nodes.length > 0 ? this : undefined;
		    }
		    optimizeNames(names, constants) {
		        const { nodes } = this;
		        let i = nodes.length;
		        while (i--) {
		            // iterating backwards improves 1-pass optimization
		            const n = nodes[i];
		            if (n.optimizeNames(names, constants))
		                continue;
		            subtractNames(names, n.names);
		            nodes.splice(i, 1);
		        }
		        return nodes.length > 0 ? this : undefined;
		    }
		    get names() {
		        return this.nodes.reduce((names, n) => addNames(names, n.names), {});
		    }
		}
		class BlockNode extends ParentNode {
		    render(opts) {
		        return "{" + opts._n + super.render(opts) + "}" + opts._n;
		    }
		}
		class Root extends ParentNode {
		}
		class Else extends BlockNode {
		}
		Else.kind = "else";
		class If extends BlockNode {
		    constructor(condition, nodes) {
		        super(nodes);
		        this.condition = condition;
		    }
		    render(opts) {
		        let code = `if(${this.condition})` + super.render(opts);
		        if (this.else)
		            code += "else " + this.else.render(opts);
		        return code;
		    }
		    optimizeNodes() {
		        super.optimizeNodes();
		        const cond = this.condition;
		        if (cond === true)
		            return this.nodes; // else is ignored here
		        let e = this.else;
		        if (e) {
		            const ns = e.optimizeNodes();
		            e = this.else = Array.isArray(ns) ? new Else(ns) : ns;
		        }
		        if (e) {
		            if (cond === false)
		                return e instanceof If ? e : e.nodes;
		            if (this.nodes.length)
		                return this;
		            return new If(not(cond), e instanceof If ? [e] : e.nodes);
		        }
		        if (cond === false || !this.nodes.length)
		            return undefined;
		        return this;
		    }
		    optimizeNames(names, constants) {
		        var _a;
		        this.else = (_a = this.else) === null || _a === void 0 ? void 0 : _a.optimizeNames(names, constants);
		        if (!(super.optimizeNames(names, constants) || this.else))
		            return;
		        this.condition = optimizeExpr(this.condition, names, constants);
		        return this;
		    }
		    get names() {
		        const names = super.names;
		        addExprNames(names, this.condition);
		        if (this.else)
		            addNames(names, this.else.names);
		        return names;
		    }
		}
		If.kind = "if";
		class For extends BlockNode {
		}
		For.kind = "for";
		class ForLoop extends For {
		    constructor(iteration) {
		        super();
		        this.iteration = iteration;
		    }
		    render(opts) {
		        return `for(${this.iteration})` + super.render(opts);
		    }
		    optimizeNames(names, constants) {
		        if (!super.optimizeNames(names, constants))
		            return;
		        this.iteration = optimizeExpr(this.iteration, names, constants);
		        return this;
		    }
		    get names() {
		        return addNames(super.names, this.iteration.names);
		    }
		}
		class ForRange extends For {
		    constructor(varKind, name, from, to) {
		        super();
		        this.varKind = varKind;
		        this.name = name;
		        this.from = from;
		        this.to = to;
		    }
		    render(opts) {
		        const varKind = opts.es5 ? scope_1.varKinds.var : this.varKind;
		        const { name, from, to } = this;
		        return `for(${varKind} ${name}=${from}; ${name}<${to}; ${name}++)` + super.render(opts);
		    }
		    get names() {
		        const names = addExprNames(super.names, this.from);
		        return addExprNames(names, this.to);
		    }
		}
		class ForIter extends For {
		    constructor(loop, varKind, name, iterable) {
		        super();
		        this.loop = loop;
		        this.varKind = varKind;
		        this.name = name;
		        this.iterable = iterable;
		    }
		    render(opts) {
		        return `for(${this.varKind} ${this.name} ${this.loop} ${this.iterable})` + super.render(opts);
		    }
		    optimizeNames(names, constants) {
		        if (!super.optimizeNames(names, constants))
		            return;
		        this.iterable = optimizeExpr(this.iterable, names, constants);
		        return this;
		    }
		    get names() {
		        return addNames(super.names, this.iterable.names);
		    }
		}
		class Func extends BlockNode {
		    constructor(name, args, async) {
		        super();
		        this.name = name;
		        this.args = args;
		        this.async = async;
		    }
		    render(opts) {
		        const _async = this.async ? "async " : "";
		        return `${_async}function ${this.name}(${this.args})` + super.render(opts);
		    }
		}
		Func.kind = "func";
		class Return extends ParentNode {
		    render(opts) {
		        return "return " + super.render(opts);
		    }
		}
		Return.kind = "return";
		class Try extends BlockNode {
		    render(opts) {
		        let code = "try" + super.render(opts);
		        if (this.catch)
		            code += this.catch.render(opts);
		        if (this.finally)
		            code += this.finally.render(opts);
		        return code;
		    }
		    optimizeNodes() {
		        var _a, _b;
		        super.optimizeNodes();
		        (_a = this.catch) === null || _a === void 0 ? void 0 : _a.optimizeNodes();
		        (_b = this.finally) === null || _b === void 0 ? void 0 : _b.optimizeNodes();
		        return this;
		    }
		    optimizeNames(names, constants) {
		        var _a, _b;
		        super.optimizeNames(names, constants);
		        (_a = this.catch) === null || _a === void 0 ? void 0 : _a.optimizeNames(names, constants);
		        (_b = this.finally) === null || _b === void 0 ? void 0 : _b.optimizeNames(names, constants);
		        return this;
		    }
		    get names() {
		        const names = super.names;
		        if (this.catch)
		            addNames(names, this.catch.names);
		        if (this.finally)
		            addNames(names, this.finally.names);
		        return names;
		    }
		}
		class Catch extends BlockNode {
		    constructor(error) {
		        super();
		        this.error = error;
		    }
		    render(opts) {
		        return `catch(${this.error})` + super.render(opts);
		    }
		}
		Catch.kind = "catch";
		class Finally extends BlockNode {
		    render(opts) {
		        return "finally" + super.render(opts);
		    }
		}
		Finally.kind = "finally";
		class CodeGen {
		    constructor(extScope, opts = {}) {
		        this._values = {};
		        this._blockStarts = [];
		        this._constants = {};
		        this.opts = { ...opts, _n: opts.lines ? "\n" : "" };
		        this._extScope = extScope;
		        this._scope = new scope_1.Scope({ parent: extScope });
		        this._nodes = [new Root()];
		    }
		    toString() {
		        return this._root.render(this.opts);
		    }
		    // returns unique name in the internal scope
		    name(prefix) {
		        return this._scope.name(prefix);
		    }
		    // reserves unique name in the external scope
		    scopeName(prefix) {
		        return this._extScope.name(prefix);
		    }
		    // reserves unique name in the external scope and assigns value to it
		    scopeValue(prefixOrName, value) {
		        const name = this._extScope.value(prefixOrName, value);
		        const vs = this._values[name.prefix] || (this._values[name.prefix] = new Set());
		        vs.add(name);
		        return name;
		    }
		    getScopeValue(prefix, keyOrRef) {
		        return this._extScope.getValue(prefix, keyOrRef);
		    }
		    // return code that assigns values in the external scope to the names that are used internally
		    // (same names that were returned by gen.scopeName or gen.scopeValue)
		    scopeRefs(scopeName) {
		        return this._extScope.scopeRefs(scopeName, this._values);
		    }
		    scopeCode() {
		        return this._extScope.scopeCode(this._values);
		    }
		    _def(varKind, nameOrPrefix, rhs, constant) {
		        const name = this._scope.toName(nameOrPrefix);
		        if (rhs !== undefined && constant)
		            this._constants[name.str] = rhs;
		        this._leafNode(new Def(varKind, name, rhs));
		        return name;
		    }
		    // `const` declaration (`var` in es5 mode)
		    const(nameOrPrefix, rhs, _constant) {
		        return this._def(scope_1.varKinds.const, nameOrPrefix, rhs, _constant);
		    }
		    // `let` declaration with optional assignment (`var` in es5 mode)
		    let(nameOrPrefix, rhs, _constant) {
		        return this._def(scope_1.varKinds.let, nameOrPrefix, rhs, _constant);
		    }
		    // `var` declaration with optional assignment
		    var(nameOrPrefix, rhs, _constant) {
		        return this._def(scope_1.varKinds.var, nameOrPrefix, rhs, _constant);
		    }
		    // assignment code
		    assign(lhs, rhs, sideEffects) {
		        return this._leafNode(new Assign(lhs, rhs, sideEffects));
		    }
		    // `+=` code
		    add(lhs, rhs) {
		        return this._leafNode(new AssignOp(lhs, exports.operators.ADD, rhs));
		    }
		    // appends passed SafeExpr to code or executes Block
		    code(c) {
		        if (typeof c == "function")
		            c();
		        else if (c !== code_1.nil)
		            this._leafNode(new AnyCode(c));
		        return this;
		    }
		    // returns code for object literal for the passed argument list of key-value pairs
		    object(...keyValues) {
		        const code = ["{"];
		        for (const [key, value] of keyValues) {
		            if (code.length > 1)
		                code.push(",");
		            code.push(key);
		            if (key !== value || this.opts.es5) {
		                code.push(":");
		                (0, code_1.addCodeArg)(code, value);
		            }
		        }
		        code.push("}");
		        return new code_1._Code(code);
		    }
		    // `if` clause (or statement if `thenBody` and, optionally, `elseBody` are passed)
		    if(condition, thenBody, elseBody) {
		        this._blockNode(new If(condition));
		        if (thenBody && elseBody) {
		            this.code(thenBody).else().code(elseBody).endIf();
		        }
		        else if (thenBody) {
		            this.code(thenBody).endIf();
		        }
		        else if (elseBody) {
		            throw new Error('CodeGen: "else" body without "then" body');
		        }
		        return this;
		    }
		    // `else if` clause - invalid without `if` or after `else` clauses
		    elseIf(condition) {
		        return this._elseNode(new If(condition));
		    }
		    // `else` clause - only valid after `if` or `else if` clauses
		    else() {
		        return this._elseNode(new Else());
		    }
		    // end `if` statement (needed if gen.if was used only with condition)
		    endIf() {
		        return this._endBlockNode(If, Else);
		    }
		    _for(node, forBody) {
		        this._blockNode(node);
		        if (forBody)
		            this.code(forBody).endFor();
		        return this;
		    }
		    // a generic `for` clause (or statement if `forBody` is passed)
		    for(iteration, forBody) {
		        return this._for(new ForLoop(iteration), forBody);
		    }
		    // `for` statement for a range of values
		    forRange(nameOrPrefix, from, to, forBody, varKind = this.opts.es5 ? scope_1.varKinds.var : scope_1.varKinds.let) {
		        const name = this._scope.toName(nameOrPrefix);
		        return this._for(new ForRange(varKind, name, from, to), () => forBody(name));
		    }
		    // `for-of` statement (in es5 mode replace with a normal for loop)
		    forOf(nameOrPrefix, iterable, forBody, varKind = scope_1.varKinds.const) {
		        const name = this._scope.toName(nameOrPrefix);
		        if (this.opts.es5) {
		            const arr = iterable instanceof code_1.Name ? iterable : this.var("_arr", iterable);
		            return this.forRange("_i", 0, (0, code_1._) `${arr}.length`, (i) => {
		                this.var(name, (0, code_1._) `${arr}[${i}]`);
		                forBody(name);
		            });
		        }
		        return this._for(new ForIter("of", varKind, name, iterable), () => forBody(name));
		    }
		    // `for-in` statement.
		    // With option `ownProperties` replaced with a `for-of` loop for object keys
		    forIn(nameOrPrefix, obj, forBody, varKind = this.opts.es5 ? scope_1.varKinds.var : scope_1.varKinds.const) {
		        if (this.opts.ownProperties) {
		            return this.forOf(nameOrPrefix, (0, code_1._) `Object.keys(${obj})`, forBody);
		        }
		        const name = this._scope.toName(nameOrPrefix);
		        return this._for(new ForIter("in", varKind, name, obj), () => forBody(name));
		    }
		    // end `for` loop
		    endFor() {
		        return this._endBlockNode(For);
		    }
		    // `label` statement
		    label(label) {
		        return this._leafNode(new Label(label));
		    }
		    // `break` statement
		    break(label) {
		        return this._leafNode(new Break(label));
		    }
		    // `return` statement
		    return(value) {
		        const node = new Return();
		        this._blockNode(node);
		        this.code(value);
		        if (node.nodes.length !== 1)
		            throw new Error('CodeGen: "return" should have one node');
		        return this._endBlockNode(Return);
		    }
		    // `try` statement
		    try(tryBody, catchCode, finallyCode) {
		        if (!catchCode && !finallyCode)
		            throw new Error('CodeGen: "try" without "catch" and "finally"');
		        const node = new Try();
		        this._blockNode(node);
		        this.code(tryBody);
		        if (catchCode) {
		            const error = this.name("e");
		            this._currNode = node.catch = new Catch(error);
		            catchCode(error);
		        }
		        if (finallyCode) {
		            this._currNode = node.finally = new Finally();
		            this.code(finallyCode);
		        }
		        return this._endBlockNode(Catch, Finally);
		    }
		    // `throw` statement
		    throw(error) {
		        return this._leafNode(new Throw(error));
		    }
		    // start self-balancing block
		    block(body, nodeCount) {
		        this._blockStarts.push(this._nodes.length);
		        if (body)
		            this.code(body).endBlock(nodeCount);
		        return this;
		    }
		    // end the current self-balancing block
		    endBlock(nodeCount) {
		        const len = this._blockStarts.pop();
		        if (len === undefined)
		            throw new Error("CodeGen: not in self-balancing block");
		        const toClose = this._nodes.length - len;
		        if (toClose < 0 || (nodeCount !== undefined && toClose !== nodeCount)) {
		            throw new Error(`CodeGen: wrong number of nodes: ${toClose} vs ${nodeCount} expected`);
		        }
		        this._nodes.length = len;
		        return this;
		    }
		    // `function` heading (or definition if funcBody is passed)
		    func(name, args = code_1.nil, async, funcBody) {
		        this._blockNode(new Func(name, args, async));
		        if (funcBody)
		            this.code(funcBody).endFunc();
		        return this;
		    }
		    // end function definition
		    endFunc() {
		        return this._endBlockNode(Func);
		    }
		    optimize(n = 1) {
		        while (n-- > 0) {
		            this._root.optimizeNodes();
		            this._root.optimizeNames(this._root.names, this._constants);
		        }
		    }
		    _leafNode(node) {
		        this._currNode.nodes.push(node);
		        return this;
		    }
		    _blockNode(node) {
		        this._currNode.nodes.push(node);
		        this._nodes.push(node);
		    }
		    _endBlockNode(N1, N2) {
		        const n = this._currNode;
		        if (n instanceof N1 || (N2 && n instanceof N2)) {
		            this._nodes.pop();
		            return this;
		        }
		        throw new Error(`CodeGen: not in block "${N2 ? `${N1.kind}/${N2.kind}` : N1.kind}"`);
		    }
		    _elseNode(node) {
		        const n = this._currNode;
		        if (!(n instanceof If)) {
		            throw new Error('CodeGen: "else" without "if"');
		        }
		        this._currNode = n.else = node;
		        return this;
		    }
		    get _root() {
		        return this._nodes[0];
		    }
		    get _currNode() {
		        const ns = this._nodes;
		        return ns[ns.length - 1];
		    }
		    set _currNode(node) {
		        const ns = this._nodes;
		        ns[ns.length - 1] = node;
		    }
		}
		exports.CodeGen = CodeGen;
		function addNames(names, from) {
		    for (const n in from)
		        names[n] = (names[n] || 0) + (from[n] || 0);
		    return names;
		}
		function addExprNames(names, from) {
		    return from instanceof code_1._CodeOrName ? addNames(names, from.names) : names;
		}
		function optimizeExpr(expr, names, constants) {
		    if (expr instanceof code_1.Name)
		        return replaceName(expr);
		    if (!canOptimize(expr))
		        return expr;
		    return new code_1._Code(expr._items.reduce((items, c) => {
		        if (c instanceof code_1.Name)
		            c = replaceName(c);
		        if (c instanceof code_1._Code)
		            items.push(...c._items);
		        else
		            items.push(c);
		        return items;
		    }, []));
		    function replaceName(n) {
		        const c = constants[n.str];
		        if (c === undefined || names[n.str] !== 1)
		            return n;
		        delete names[n.str];
		        return c;
		    }
		    function canOptimize(e) {
		        return (e instanceof code_1._Code &&
		            e._items.some((c) => c instanceof code_1.Name && names[c.str] === 1 && constants[c.str] !== undefined));
		    }
		}
		function subtractNames(names, from) {
		    for (const n in from)
		        names[n] = (names[n] || 0) - (from[n] || 0);
		}
		function not(x) {
		    return typeof x == "boolean" || typeof x == "number" || x === null ? !x : (0, code_1._) `!${par(x)}`;
		}
		exports.not = not;
		const andCode = mappend(exports.operators.AND);
		// boolean AND (&&) expression with the passed arguments
		function and(...args) {
		    return args.reduce(andCode);
		}
		exports.and = and;
		const orCode = mappend(exports.operators.OR);
		// boolean OR (||) expression with the passed arguments
		function or(...args) {
		    return args.reduce(orCode);
		}
		exports.or = or;
		function mappend(op) {
		    return (x, y) => (x === code_1.nil ? y : y === code_1.nil ? x : (0, code_1._) `${par(x)} ${op} ${par(y)}`);
		}
		function par(x) {
		    return x instanceof code_1.Name ? x : (0, code_1._) `(${x})`;
		}
		
	} (codegen));
	return codegen;
}

var util$1 = {};

Object.defineProperty(util$1, "__esModule", { value: true });
util$1.checkStrictMode = util$1.getErrorPath = util$1.Type = util$1.useFunc = util$1.setEvaluated = util$1.evaluatedPropsToName = util$1.mergeEvaluated = util$1.eachItem = util$1.unescapeJsonPointer = util$1.escapeJsonPointer = util$1.escapeFragment = util$1.unescapeFragment = util$1.schemaRefOrVal = util$1.schemaHasRulesButRef = util$1.schemaHasRules = util$1.checkUnknownRules = util$1.alwaysValidSchema = util$1.toHash = void 0;
const codegen_1$o = requireCodegen();
const code_1$9 = requireCode$1();
// TODO refactor to use Set
function toHash(arr) {
    const hash = {};
    for (const item of arr)
        hash[item] = true;
    return hash;
}
util$1.toHash = toHash;
function alwaysValidSchema(it, schema) {
    if (typeof schema == "boolean")
        return schema;
    if (Object.keys(schema).length === 0)
        return true;
    checkUnknownRules(it, schema);
    return !schemaHasRules(schema, it.self.RULES.all);
}
util$1.alwaysValidSchema = alwaysValidSchema;
function checkUnknownRules(it, schema = it.schema) {
    const { opts, self } = it;
    if (!opts.strictSchema)
        return;
    if (typeof schema === "boolean")
        return;
    const rules = self.RULES.keywords;
    for (const key in schema) {
        if (!rules[key])
            checkStrictMode(it, `unknown keyword: "${key}"`);
    }
}
util$1.checkUnknownRules = checkUnknownRules;
function schemaHasRules(schema, rules) {
    if (typeof schema == "boolean")
        return !schema;
    for (const key in schema)
        if (rules[key])
            return true;
    return false;
}
util$1.schemaHasRules = schemaHasRules;
function schemaHasRulesButRef(schema, RULES) {
    if (typeof schema == "boolean")
        return !schema;
    for (const key in schema)
        if (key !== "$ref" && RULES.all[key])
            return true;
    return false;
}
util$1.schemaHasRulesButRef = schemaHasRulesButRef;
function schemaRefOrVal({ topSchemaRef, schemaPath }, schema, keyword, $data) {
    if (!$data) {
        if (typeof schema == "number" || typeof schema == "boolean")
            return schema;
        if (typeof schema == "string")
            return (0, codegen_1$o._) `${schema}`;
    }
    return (0, codegen_1$o._) `${topSchemaRef}${schemaPath}${(0, codegen_1$o.getProperty)(keyword)}`;
}
util$1.schemaRefOrVal = schemaRefOrVal;
function unescapeFragment(str) {
    return unescapeJsonPointer(decodeURIComponent(str));
}
util$1.unescapeFragment = unescapeFragment;
function escapeFragment(str) {
    return encodeURIComponent(escapeJsonPointer(str));
}
util$1.escapeFragment = escapeFragment;
function escapeJsonPointer(str) {
    if (typeof str == "number")
        return `${str}`;
    return str.replace(/~/g, "~0").replace(/\//g, "~1");
}
util$1.escapeJsonPointer = escapeJsonPointer;
function unescapeJsonPointer(str) {
    return str.replace(/~1/g, "/").replace(/~0/g, "~");
}
util$1.unescapeJsonPointer = unescapeJsonPointer;
function eachItem(xs, f) {
    if (Array.isArray(xs)) {
        for (const x of xs)
            f(x);
    }
    else {
        f(xs);
    }
}
util$1.eachItem = eachItem;
function makeMergeEvaluated({ mergeNames, mergeToName, mergeValues, resultToName, }) {
    return (gen, from, to, toName) => {
        const res = to === undefined
            ? from
            : to instanceof codegen_1$o.Name
                ? (from instanceof codegen_1$o.Name ? mergeNames(gen, from, to) : mergeToName(gen, from, to), to)
                : from instanceof codegen_1$o.Name
                    ? (mergeToName(gen, to, from), from)
                    : mergeValues(from, to);
        return toName === codegen_1$o.Name && !(res instanceof codegen_1$o.Name) ? resultToName(gen, res) : res;
    };
}
util$1.mergeEvaluated = {
    props: makeMergeEvaluated({
        mergeNames: (gen, from, to) => gen.if((0, codegen_1$o._) `${to} !== true && ${from} !== undefined`, () => {
            gen.if((0, codegen_1$o._) `${from} === true`, () => gen.assign(to, true), () => gen.assign(to, (0, codegen_1$o._) `${to} || {}`).code((0, codegen_1$o._) `Object.assign(${to}, ${from})`));
        }),
        mergeToName: (gen, from, to) => gen.if((0, codegen_1$o._) `${to} !== true`, () => {
            if (from === true) {
                gen.assign(to, true);
            }
            else {
                gen.assign(to, (0, codegen_1$o._) `${to} || {}`);
                setEvaluated(gen, to, from);
            }
        }),
        mergeValues: (from, to) => (from === true ? true : { ...from, ...to }),
        resultToName: evaluatedPropsToName,
    }),
    items: makeMergeEvaluated({
        mergeNames: (gen, from, to) => gen.if((0, codegen_1$o._) `${to} !== true && ${from} !== undefined`, () => gen.assign(to, (0, codegen_1$o._) `${from} === true ? true : ${to} > ${from} ? ${to} : ${from}`)),
        mergeToName: (gen, from, to) => gen.if((0, codegen_1$o._) `${to} !== true`, () => gen.assign(to, from === true ? true : (0, codegen_1$o._) `${to} > ${from} ? ${to} : ${from}`)),
        mergeValues: (from, to) => (from === true ? true : Math.max(from, to)),
        resultToName: (gen, items) => gen.var("items", items),
    }),
};
function evaluatedPropsToName(gen, ps) {
    if (ps === true)
        return gen.var("props", true);
    const props = gen.var("props", (0, codegen_1$o._) `{}`);
    if (ps !== undefined)
        setEvaluated(gen, props, ps);
    return props;
}
util$1.evaluatedPropsToName = evaluatedPropsToName;
function setEvaluated(gen, props, ps) {
    Object.keys(ps).forEach((p) => gen.assign((0, codegen_1$o._) `${props}${(0, codegen_1$o.getProperty)(p)}`, true));
}
util$1.setEvaluated = setEvaluated;
const snippets = {};
function useFunc(gen, f) {
    return gen.scopeValue("func", {
        ref: f,
        code: snippets[f.code] || (snippets[f.code] = new code_1$9._Code(f.code)),
    });
}
util$1.useFunc = useFunc;
var Type;
(function (Type) {
    Type[Type["Num"] = 0] = "Num";
    Type[Type["Str"] = 1] = "Str";
})(Type || (util$1.Type = Type = {}));
function getErrorPath$1(dataProp, dataPropType, jsPropertySyntax) {
    // let path
    if (dataProp instanceof codegen_1$o.Name) {
        const isNumber = dataPropType === Type.Num;
        return jsPropertySyntax
            ? isNumber
                ? (0, codegen_1$o._) `"[" + ${dataProp} + "]"`
                : (0, codegen_1$o._) `"['" + ${dataProp} + "']"`
            : isNumber
                ? (0, codegen_1$o._) `"/" + ${dataProp}`
                : (0, codegen_1$o._) `"/" + ${dataProp}.replace(/~/g, "~0").replace(/\\//g, "~1")`; // TODO maybe use global escapePointer
    }
    return jsPropertySyntax ? (0, codegen_1$o.getProperty)(dataProp).toString() : "/" + escapeJsonPointer(dataProp);
}
util$1.getErrorPath = getErrorPath$1;
function checkStrictMode(it, msg, mode = it.opts.strictSchema) {
    if (!mode)
        return;
    msg = `strict mode: ${msg}`;
    if (mode === true)
        throw new Error(msg);
    it.self.logger.warn(msg);
}
util$1.checkStrictMode = checkStrictMode;

var names = {};

var hasRequiredNames;

function requireNames () {
	if (hasRequiredNames) return names;
	hasRequiredNames = 1;
	Object.defineProperty(names, "__esModule", { value: true });
	const codegen_1 = requireCodegen();
	const names$1 = {
	    // validation function arguments
	    data: new codegen_1.Name("data"), // data passed to validation function
	    // args passed from referencing schema
	    valCxt: new codegen_1.Name("valCxt"), // validation/data context - should not be used directly, it is destructured to the names below
	    instancePath: new codegen_1.Name("instancePath"),
	    parentData: new codegen_1.Name("parentData"),
	    parentDataProperty: new codegen_1.Name("parentDataProperty"),
	    rootData: new codegen_1.Name("rootData"), // root data - same as the data passed to the first/top validation function
	    dynamicAnchors: new codegen_1.Name("dynamicAnchors"), // used to support recursiveRef and dynamicRef
	    // function scoped variables
	    vErrors: new codegen_1.Name("vErrors"), // null or array of validation errors
	    errors: new codegen_1.Name("errors"), // counter of validation errors
	    this: new codegen_1.Name("this"),
	    // "globals"
	    self: new codegen_1.Name("self"),
	    scope: new codegen_1.Name("scope"),
	    // JTD serialize/parse name for JSON string and position
	    json: new codegen_1.Name("json"),
	    jsonPos: new codegen_1.Name("jsonPos"),
	    jsonLen: new codegen_1.Name("jsonLen"),
	    jsonPart: new codegen_1.Name("jsonPart"),
	};
	names.default = names$1;
	
	return names;
}

var hasRequiredErrors;

function requireErrors () {
	if (hasRequiredErrors) return errors;
	hasRequiredErrors = 1;
	(function (exports) {
		Object.defineProperty(exports, "__esModule", { value: true });
		exports.extendErrors = exports.resetErrorsCount = exports.reportExtraError = exports.reportError = exports.keyword$DataError = exports.keywordError = void 0;
		const codegen_1 = requireCodegen();
		const util_1 = util$1;
		const names_1 = requireNames();
		exports.keywordError = {
		    message: ({ keyword }) => (0, codegen_1.str) `must pass "${keyword}" keyword validation`,
		};
		exports.keyword$DataError = {
		    message: ({ keyword, schemaType }) => schemaType
		        ? (0, codegen_1.str) `"${keyword}" keyword must be ${schemaType} ($data)`
		        : (0, codegen_1.str) `"${keyword}" keyword is invalid ($data)`,
		};
		function reportError(cxt, error = exports.keywordError, errorPaths, overrideAllErrors) {
		    const { it } = cxt;
		    const { gen, compositeRule, allErrors } = it;
		    const errObj = errorObjectCode(cxt, error, errorPaths);
		    if (overrideAllErrors !== null && overrideAllErrors !== void 0 ? overrideAllErrors : (compositeRule || allErrors)) {
		        addError(gen, errObj);
		    }
		    else {
		        returnErrors(it, (0, codegen_1._) `[${errObj}]`);
		    }
		}
		exports.reportError = reportError;
		function reportExtraError(cxt, error = exports.keywordError, errorPaths) {
		    const { it } = cxt;
		    const { gen, compositeRule, allErrors } = it;
		    const errObj = errorObjectCode(cxt, error, errorPaths);
		    addError(gen, errObj);
		    if (!(compositeRule || allErrors)) {
		        returnErrors(it, names_1.default.vErrors);
		    }
		}
		exports.reportExtraError = reportExtraError;
		function resetErrorsCount(gen, errsCount) {
		    gen.assign(names_1.default.errors, errsCount);
		    gen.if((0, codegen_1._) `${names_1.default.vErrors} !== null`, () => gen.if(errsCount, () => gen.assign((0, codegen_1._) `${names_1.default.vErrors}.length`, errsCount), () => gen.assign(names_1.default.vErrors, null)));
		}
		exports.resetErrorsCount = resetErrorsCount;
		function extendErrors({ gen, keyword, schemaValue, data, errsCount, it, }) {
		    /* istanbul ignore if */
		    if (errsCount === undefined)
		        throw new Error("ajv implementation error");
		    const err = gen.name("err");
		    gen.forRange("i", errsCount, names_1.default.errors, (i) => {
		        gen.const(err, (0, codegen_1._) `${names_1.default.vErrors}[${i}]`);
		        gen.if((0, codegen_1._) `${err}.instancePath === undefined`, () => gen.assign((0, codegen_1._) `${err}.instancePath`, (0, codegen_1.strConcat)(names_1.default.instancePath, it.errorPath)));
		        gen.assign((0, codegen_1._) `${err}.schemaPath`, (0, codegen_1.str) `${it.errSchemaPath}/${keyword}`);
		        if (it.opts.verbose) {
		            gen.assign((0, codegen_1._) `${err}.schema`, schemaValue);
		            gen.assign((0, codegen_1._) `${err}.data`, data);
		        }
		    });
		}
		exports.extendErrors = extendErrors;
		function addError(gen, errObj) {
		    const err = gen.const("err", errObj);
		    gen.if((0, codegen_1._) `${names_1.default.vErrors} === null`, () => gen.assign(names_1.default.vErrors, (0, codegen_1._) `[${err}]`), (0, codegen_1._) `${names_1.default.vErrors}.push(${err})`);
		    gen.code((0, codegen_1._) `${names_1.default.errors}++`);
		}
		function returnErrors(it, errs) {
		    const { gen, validateName, schemaEnv } = it;
		    if (schemaEnv.$async) {
		        gen.throw((0, codegen_1._) `new ${it.ValidationError}(${errs})`);
		    }
		    else {
		        gen.assign((0, codegen_1._) `${validateName}.errors`, errs);
		        gen.return(false);
		    }
		}
		const E = {
		    keyword: new codegen_1.Name("keyword"),
		    schemaPath: new codegen_1.Name("schemaPath"), // also used in JTD errors
		    params: new codegen_1.Name("params"),
		    propertyName: new codegen_1.Name("propertyName"),
		    message: new codegen_1.Name("message"),
		    schema: new codegen_1.Name("schema"),
		    parentSchema: new codegen_1.Name("parentSchema"),
		};
		function errorObjectCode(cxt, error, errorPaths) {
		    const { createErrors } = cxt.it;
		    if (createErrors === false)
		        return (0, codegen_1._) `{}`;
		    return errorObject(cxt, error, errorPaths);
		}
		function errorObject(cxt, error, errorPaths = {}) {
		    const { gen, it } = cxt;
		    const keyValues = [
		        errorInstancePath(it, errorPaths),
		        errorSchemaPath(cxt, errorPaths),
		    ];
		    extraErrorProps(cxt, error, keyValues);
		    return gen.object(...keyValues);
		}
		function errorInstancePath({ errorPath }, { instancePath }) {
		    const instPath = instancePath
		        ? (0, codegen_1.str) `${errorPath}${(0, util_1.getErrorPath)(instancePath, util_1.Type.Str)}`
		        : errorPath;
		    return [names_1.default.instancePath, (0, codegen_1.strConcat)(names_1.default.instancePath, instPath)];
		}
		function errorSchemaPath({ keyword, it: { errSchemaPath } }, { schemaPath, parentSchema }) {
		    let schPath = parentSchema ? errSchemaPath : (0, codegen_1.str) `${errSchemaPath}/${keyword}`;
		    if (schemaPath) {
		        schPath = (0, codegen_1.str) `${schPath}${(0, util_1.getErrorPath)(schemaPath, util_1.Type.Str)}`;
		    }
		    return [E.schemaPath, schPath];
		}
		function extraErrorProps(cxt, { params, message }, keyValues) {
		    const { keyword, data, schemaValue, it } = cxt;
		    const { opts, propertyName, topSchemaRef, schemaPath } = it;
		    keyValues.push([E.keyword, keyword], [E.params, typeof params == "function" ? params(cxt) : params || (0, codegen_1._) `{}`]);
		    if (opts.messages) {
		        keyValues.push([E.message, typeof message == "function" ? message(cxt) : message]);
		    }
		    if (opts.verbose) {
		        keyValues.push([E.schema, schemaValue], [E.parentSchema, (0, codegen_1._) `${topSchemaRef}${schemaPath}`], [names_1.default.data, data]);
		    }
		    if (propertyName)
		        keyValues.push([E.propertyName, propertyName]);
		}
		
	} (errors));
	return errors;
}

var hasRequiredBoolSchema;

function requireBoolSchema () {
	if (hasRequiredBoolSchema) return boolSchema;
	hasRequiredBoolSchema = 1;
	Object.defineProperty(boolSchema, "__esModule", { value: true });
	boolSchema.boolOrEmptySchema = boolSchema.topBoolOrEmptySchema = void 0;
	const errors_1 = requireErrors();
	const codegen_1 = requireCodegen();
	const names_1 = requireNames();
	const boolError = {
	    message: "boolean schema is false",
	};
	function topBoolOrEmptySchema(it) {
	    const { gen, schema, validateName } = it;
	    if (schema === false) {
	        falseSchemaError(it, false);
	    }
	    else if (typeof schema == "object" && schema.$async === true) {
	        gen.return(names_1.default.data);
	    }
	    else {
	        gen.assign((0, codegen_1._) `${validateName}.errors`, null);
	        gen.return(true);
	    }
	}
	boolSchema.topBoolOrEmptySchema = topBoolOrEmptySchema;
	function boolOrEmptySchema(it, valid) {
	    const { gen, schema } = it;
	    if (schema === false) {
	        gen.var(valid, false); // TODO var
	        falseSchemaError(it);
	    }
	    else {
	        gen.var(valid, true); // TODO var
	    }
	}
	boolSchema.boolOrEmptySchema = boolOrEmptySchema;
	function falseSchemaError(it, overrideAllErrors) {
	    const { gen, data } = it;
	    // TODO maybe some other interface should be used for non-keyword validation errors...
	    const cxt = {
	        gen,
	        keyword: "false schema",
	        data,
	        schema: false,
	        schemaCode: false,
	        schemaValue: false,
	        params: {},
	        it,
	    };
	    (0, errors_1.reportError)(cxt, boolError, undefined, overrideAllErrors);
	}
	
	return boolSchema;
}

var dataType = {};

var rules = {};

Object.defineProperty(rules, "__esModule", { value: true });
rules.getRules = rules.isJSONType = void 0;
const _jsonTypes = ["string", "number", "integer", "boolean", "null", "object", "array"];
const jsonTypes = new Set(_jsonTypes);
function isJSONType(x) {
    return typeof x == "string" && jsonTypes.has(x);
}
rules.isJSONType = isJSONType;
function getRules() {
    const groups = {
        number: { type: "number", rules: [] },
        string: { type: "string", rules: [] },
        array: { type: "array", rules: [] },
        object: { type: "object", rules: [] },
    };
    return {
        types: { ...groups, integer: true, boolean: true, null: true },
        rules: [{ rules: [] }, groups.number, groups.string, groups.array, groups.object],
        post: { rules: [] },
        all: {},
        keywords: {},
    };
}
rules.getRules = getRules;

var applicability = {};

var hasRequiredApplicability;

function requireApplicability () {
	if (hasRequiredApplicability) return applicability;
	hasRequiredApplicability = 1;
	Object.defineProperty(applicability, "__esModule", { value: true });
	applicability.shouldUseRule = applicability.shouldUseGroup = applicability.schemaHasRulesForType = void 0;
	function schemaHasRulesForType({ schema, self }, type) {
	    const group = self.RULES.types[type];
	    return group && group !== true && shouldUseGroup(schema, group);
	}
	applicability.schemaHasRulesForType = schemaHasRulesForType;
	function shouldUseGroup(schema, group) {
	    return group.rules.some((rule) => shouldUseRule(schema, rule));
	}
	applicability.shouldUseGroup = shouldUseGroup;
	function shouldUseRule(schema, rule) {
	    var _a;
	    return (schema[rule.keyword] !== undefined ||
	        ((_a = rule.definition.implements) === null || _a === void 0 ? void 0 : _a.some((kwd) => schema[kwd] !== undefined)));
	}
	applicability.shouldUseRule = shouldUseRule;
	
	return applicability;
}

Object.defineProperty(dataType, "__esModule", { value: true });
dataType.reportTypeError = dataType.checkDataTypes = dataType.checkDataType = dataType.coerceAndCheckDataType = dataType.getJSONTypes = dataType.getSchemaTypes = dataType.DataType = void 0;
const rules_1 = rules;
const applicability_1 = requireApplicability();
const errors_1 = requireErrors();
const codegen_1$n = requireCodegen();
const util_1$m = util$1;
var DataType;
(function (DataType) {
    DataType[DataType["Correct"] = 0] = "Correct";
    DataType[DataType["Wrong"] = 1] = "Wrong";
})(DataType || (dataType.DataType = DataType = {}));
function getSchemaTypes(schema) {
    const types = getJSONTypes(schema.type);
    const hasNull = types.includes("null");
    if (hasNull) {
        if (schema.nullable === false)
            throw new Error("type: null contradicts nullable: false");
    }
    else {
        if (!types.length && schema.nullable !== undefined) {
            throw new Error('"nullable" cannot be used without "type"');
        }
        if (schema.nullable === true)
            types.push("null");
    }
    return types;
}
dataType.getSchemaTypes = getSchemaTypes;
// eslint-disable-next-line @typescript-eslint/no-redundant-type-constituents
function getJSONTypes(ts) {
    const types = Array.isArray(ts) ? ts : ts ? [ts] : [];
    if (types.every(rules_1.isJSONType))
        return types;
    throw new Error("type must be JSONType or JSONType[]: " + types.join(","));
}
dataType.getJSONTypes = getJSONTypes;
function coerceAndCheckDataType(it, types) {
    const { gen, data, opts } = it;
    const coerceTo = coerceToTypes(types, opts.coerceTypes);
    const checkTypes = types.length > 0 &&
        !(coerceTo.length === 0 && types.length === 1 && (0, applicability_1.schemaHasRulesForType)(it, types[0]));
    if (checkTypes) {
        const wrongType = checkDataTypes(types, data, opts.strictNumbers, DataType.Wrong);
        gen.if(wrongType, () => {
            if (coerceTo.length)
                coerceData(it, types, coerceTo);
            else
                reportTypeError(it);
        });
    }
    return checkTypes;
}
dataType.coerceAndCheckDataType = coerceAndCheckDataType;
const COERCIBLE = new Set(["string", "number", "integer", "boolean", "null"]);
function coerceToTypes(types, coerceTypes) {
    return coerceTypes
        ? types.filter((t) => COERCIBLE.has(t) || (coerceTypes === "array" && t === "array"))
        : [];
}
function coerceData(it, types, coerceTo) {
    const { gen, data, opts } = it;
    const dataType = gen.let("dataType", (0, codegen_1$n._) `typeof ${data}`);
    const coerced = gen.let("coerced", (0, codegen_1$n._) `undefined`);
    if (opts.coerceTypes === "array") {
        gen.if((0, codegen_1$n._) `${dataType} == 'object' && Array.isArray(${data}) && ${data}.length == 1`, () => gen
            .assign(data, (0, codegen_1$n._) `${data}[0]`)
            .assign(dataType, (0, codegen_1$n._) `typeof ${data}`)
            .if(checkDataTypes(types, data, opts.strictNumbers), () => gen.assign(coerced, data)));
    }
    gen.if((0, codegen_1$n._) `${coerced} !== undefined`);
    for (const t of coerceTo) {
        if (COERCIBLE.has(t) || (t === "array" && opts.coerceTypes === "array")) {
            coerceSpecificType(t);
        }
    }
    gen.else();
    reportTypeError(it);
    gen.endIf();
    gen.if((0, codegen_1$n._) `${coerced} !== undefined`, () => {
        gen.assign(data, coerced);
        assignParentData(it, coerced);
    });
    function coerceSpecificType(t) {
        switch (t) {
            case "string":
                gen
                    .elseIf((0, codegen_1$n._) `${dataType} == "number" || ${dataType} == "boolean"`)
                    .assign(coerced, (0, codegen_1$n._) `"" + ${data}`)
                    .elseIf((0, codegen_1$n._) `${data} === null`)
                    .assign(coerced, (0, codegen_1$n._) `""`);
                return;
            case "number":
                gen
                    .elseIf((0, codegen_1$n._) `${dataType} == "boolean" || ${data} === null
              || (${dataType} == "string" && ${data} && ${data} == +${data})`)
                    .assign(coerced, (0, codegen_1$n._) `+${data}`);
                return;
            case "integer":
                gen
                    .elseIf((0, codegen_1$n._) `${dataType} === "boolean" || ${data} === null
              || (${dataType} === "string" && ${data} && ${data} == +${data} && !(${data} % 1))`)
                    .assign(coerced, (0, codegen_1$n._) `+${data}`);
                return;
            case "boolean":
                gen
                    .elseIf((0, codegen_1$n._) `${data} === "false" || ${data} === 0 || ${data} === null`)
                    .assign(coerced, false)
                    .elseIf((0, codegen_1$n._) `${data} === "true" || ${data} === 1`)
                    .assign(coerced, true);
                return;
            case "null":
                gen.elseIf((0, codegen_1$n._) `${data} === "" || ${data} === 0 || ${data} === false`);
                gen.assign(coerced, null);
                return;
            case "array":
                gen
                    .elseIf((0, codegen_1$n._) `${dataType} === "string" || ${dataType} === "number"
              || ${dataType} === "boolean" || ${data} === null`)
                    .assign(coerced, (0, codegen_1$n._) `[${data}]`);
        }
    }
}
function assignParentData({ gen, parentData, parentDataProperty }, expr) {
    // TODO use gen.property
    gen.if((0, codegen_1$n._) `${parentData} !== undefined`, () => gen.assign((0, codegen_1$n._) `${parentData}[${parentDataProperty}]`, expr));
}
function checkDataType(dataType, data, strictNums, correct = DataType.Correct) {
    const EQ = correct === DataType.Correct ? codegen_1$n.operators.EQ : codegen_1$n.operators.NEQ;
    let cond;
    switch (dataType) {
        case "null":
            return (0, codegen_1$n._) `${data} ${EQ} null`;
        case "array":
            cond = (0, codegen_1$n._) `Array.isArray(${data})`;
            break;
        case "object":
            cond = (0, codegen_1$n._) `${data} && typeof ${data} == "object" && !Array.isArray(${data})`;
            break;
        case "integer":
            cond = numCond((0, codegen_1$n._) `!(${data} % 1) && !isNaN(${data})`);
            break;
        case "number":
            cond = numCond();
            break;
        default:
            return (0, codegen_1$n._) `typeof ${data} ${EQ} ${dataType}`;
    }
    return correct === DataType.Correct ? cond : (0, codegen_1$n.not)(cond);
    function numCond(_cond = codegen_1$n.nil) {
        return (0, codegen_1$n.and)((0, codegen_1$n._) `typeof ${data} == "number"`, _cond, strictNums ? (0, codegen_1$n._) `isFinite(${data})` : codegen_1$n.nil);
    }
}
dataType.checkDataType = checkDataType;
function checkDataTypes(dataTypes, data, strictNums, correct) {
    if (dataTypes.length === 1) {
        return checkDataType(dataTypes[0], data, strictNums, correct);
    }
    let cond;
    const types = (0, util_1$m.toHash)(dataTypes);
    if (types.array && types.object) {
        const notObj = (0, codegen_1$n._) `typeof ${data} != "object"`;
        cond = types.null ? notObj : (0, codegen_1$n._) `!${data} || ${notObj}`;
        delete types.null;
        delete types.array;
        delete types.object;
    }
    else {
        cond = codegen_1$n.nil;
    }
    if (types.number)
        delete types.integer;
    for (const t in types)
        cond = (0, codegen_1$n.and)(cond, checkDataType(t, data, strictNums, correct));
    return cond;
}
dataType.checkDataTypes = checkDataTypes;
const typeError = {
    message: ({ schema }) => `must be ${schema}`,
    params: ({ schema, schemaValue }) => typeof schema == "string" ? (0, codegen_1$n._) `{type: ${schema}}` : (0, codegen_1$n._) `{type: ${schemaValue}}`,
};
function reportTypeError(it) {
    const cxt = getTypeErrorContext(it);
    (0, errors_1.reportError)(cxt, typeError);
}
dataType.reportTypeError = reportTypeError;
function getTypeErrorContext(it) {
    const { gen, data, schema } = it;
    const schemaCode = (0, util_1$m.schemaRefOrVal)(it, schema, "type");
    return {
        gen,
        keyword: "type",
        data,
        schema: schema.type,
        schemaCode,
        schemaValue: schemaCode,
        parentSchema: schema,
        params: {},
        it,
    };
}

var defaults = {};

var hasRequiredDefaults;

function requireDefaults () {
	if (hasRequiredDefaults) return defaults;
	hasRequiredDefaults = 1;
	Object.defineProperty(defaults, "__esModule", { value: true });
	defaults.assignDefaults = void 0;
	const codegen_1 = requireCodegen();
	const util_1 = util$1;
	function assignDefaults(it, ty) {
	    const { properties, items } = it.schema;
	    if (ty === "object" && properties) {
	        for (const key in properties) {
	            assignDefault(it, key, properties[key].default);
	        }
	    }
	    else if (ty === "array" && Array.isArray(items)) {
	        items.forEach((sch, i) => assignDefault(it, i, sch.default));
	    }
	}
	defaults.assignDefaults = assignDefaults;
	function assignDefault(it, prop, defaultValue) {
	    const { gen, compositeRule, data, opts } = it;
	    if (defaultValue === undefined)
	        return;
	    const childData = (0, codegen_1._) `${data}${(0, codegen_1.getProperty)(prop)}`;
	    if (compositeRule) {
	        (0, util_1.checkStrictMode)(it, `default is ignored for: ${childData}`);
	        return;
	    }
	    let condition = (0, codegen_1._) `${childData} === undefined`;
	    if (opts.useDefaults === "empty") {
	        condition = (0, codegen_1._) `${condition} || ${childData} === null || ${childData} === ""`;
	    }
	    // `${childData} === undefined` +
	    // (opts.useDefaults === "empty" ? ` || ${childData} === null || ${childData} === ""` : "")
	    gen.if(condition, (0, codegen_1._) `${childData} = ${(0, codegen_1.stringify)(defaultValue)}`);
	}
	
	return defaults;
}

var keyword = {};

var code = {};

var hasRequiredCode;

function requireCode () {
	if (hasRequiredCode) return code;
	hasRequiredCode = 1;
	Object.defineProperty(code, "__esModule", { value: true });
	code.validateUnion = code.validateArray = code.usePattern = code.callValidateCode = code.schemaProperties = code.allSchemaProperties = code.noPropertyInData = code.propertyInData = code.isOwnProperty = code.hasPropFunc = code.reportMissingProp = code.checkMissingProp = code.checkReportMissingProp = void 0;
	const codegen_1 = requireCodegen();
	const util_1 = util$1;
	const names_1 = requireNames();
	const util_2 = util$1;
	function checkReportMissingProp(cxt, prop) {
	    const { gen, data, it } = cxt;
	    gen.if(noPropertyInData(gen, data, prop, it.opts.ownProperties), () => {
	        cxt.setParams({ missingProperty: (0, codegen_1._) `${prop}` }, true);
	        cxt.error();
	    });
	}
	code.checkReportMissingProp = checkReportMissingProp;
	function checkMissingProp({ gen, data, it: { opts } }, properties, missing) {
	    return (0, codegen_1.or)(...properties.map((prop) => (0, codegen_1.and)(noPropertyInData(gen, data, prop, opts.ownProperties), (0, codegen_1._) `${missing} = ${prop}`)));
	}
	code.checkMissingProp = checkMissingProp;
	function reportMissingProp(cxt, missing) {
	    cxt.setParams({ missingProperty: missing }, true);
	    cxt.error();
	}
	code.reportMissingProp = reportMissingProp;
	function hasPropFunc(gen) {
	    return gen.scopeValue("func", {
	        // eslint-disable-next-line @typescript-eslint/unbound-method
	        ref: Object.prototype.hasOwnProperty,
	        code: (0, codegen_1._) `Object.prototype.hasOwnProperty`,
	    });
	}
	code.hasPropFunc = hasPropFunc;
	function isOwnProperty(gen, data, property) {
	    return (0, codegen_1._) `${hasPropFunc(gen)}.call(${data}, ${property})`;
	}
	code.isOwnProperty = isOwnProperty;
	function propertyInData(gen, data, property, ownProperties) {
	    const cond = (0, codegen_1._) `${data}${(0, codegen_1.getProperty)(property)} !== undefined`;
	    return ownProperties ? (0, codegen_1._) `${cond} && ${isOwnProperty(gen, data, property)}` : cond;
	}
	code.propertyInData = propertyInData;
	function noPropertyInData(gen, data, property, ownProperties) {
	    const cond = (0, codegen_1._) `${data}${(0, codegen_1.getProperty)(property)} === undefined`;
	    return ownProperties ? (0, codegen_1.or)(cond, (0, codegen_1.not)(isOwnProperty(gen, data, property))) : cond;
	}
	code.noPropertyInData = noPropertyInData;
	function allSchemaProperties(schemaMap) {
	    return schemaMap ? Object.keys(schemaMap).filter((p) => p !== "__proto__") : [];
	}
	code.allSchemaProperties = allSchemaProperties;
	function schemaProperties(it, schemaMap) {
	    return allSchemaProperties(schemaMap).filter((p) => !(0, util_1.alwaysValidSchema)(it, schemaMap[p]));
	}
	code.schemaProperties = schemaProperties;
	function callValidateCode({ schemaCode, data, it: { gen, topSchemaRef, schemaPath, errorPath }, it }, func, context, passSchema) {
	    const dataAndSchema = passSchema ? (0, codegen_1._) `${schemaCode}, ${data}, ${topSchemaRef}${schemaPath}` : data;
	    const valCxt = [
	        [names_1.default.instancePath, (0, codegen_1.strConcat)(names_1.default.instancePath, errorPath)],
	        [names_1.default.parentData, it.parentData],
	        [names_1.default.parentDataProperty, it.parentDataProperty],
	        [names_1.default.rootData, names_1.default.rootData],
	    ];
	    if (it.opts.dynamicRef)
	        valCxt.push([names_1.default.dynamicAnchors, names_1.default.dynamicAnchors]);
	    const args = (0, codegen_1._) `${dataAndSchema}, ${gen.object(...valCxt)}`;
	    return context !== codegen_1.nil ? (0, codegen_1._) `${func}.call(${context}, ${args})` : (0, codegen_1._) `${func}(${args})`;
	}
	code.callValidateCode = callValidateCode;
	const newRegExp = (0, codegen_1._) `new RegExp`;
	function usePattern({ gen, it: { opts } }, pattern) {
	    const u = opts.unicodeRegExp ? "u" : "";
	    const { regExp } = opts.code;
	    const rx = regExp(pattern, u);
	    return gen.scopeValue("pattern", {
	        key: rx.toString(),
	        ref: rx,
	        code: (0, codegen_1._) `${regExp.code === "new RegExp" ? newRegExp : (0, util_2.useFunc)(gen, regExp)}(${pattern}, ${u})`,
	    });
	}
	code.usePattern = usePattern;
	function validateArray(cxt) {
	    const { gen, data, keyword, it } = cxt;
	    const valid = gen.name("valid");
	    if (it.allErrors) {
	        const validArr = gen.let("valid", true);
	        validateItems(() => gen.assign(validArr, false));
	        return validArr;
	    }
	    gen.var(valid, true);
	    validateItems(() => gen.break());
	    return valid;
	    function validateItems(notValid) {
	        const len = gen.const("len", (0, codegen_1._) `${data}.length`);
	        gen.forRange("i", 0, len, (i) => {
	            cxt.subschema({
	                keyword,
	                dataProp: i,
	                dataPropType: util_1.Type.Num,
	            }, valid);
	            gen.if((0, codegen_1.not)(valid), notValid);
	        });
	    }
	}
	code.validateArray = validateArray;
	function validateUnion(cxt) {
	    const { gen, schema, keyword, it } = cxt;
	    /* istanbul ignore if */
	    if (!Array.isArray(schema))
	        throw new Error("ajv implementation error");
	    const alwaysValid = schema.some((sch) => (0, util_1.alwaysValidSchema)(it, sch));
	    if (alwaysValid && !it.opts.unevaluated)
	        return;
	    const valid = gen.let("valid", false);
	    const schValid = gen.name("_valid");
	    gen.block(() => schema.forEach((_sch, i) => {
	        const schCxt = cxt.subschema({
	            keyword,
	            schemaProp: i,
	            compositeRule: true,
	        }, schValid);
	        gen.assign(valid, (0, codegen_1._) `${valid} || ${schValid}`);
	        const merged = cxt.mergeValidEvaluated(schCxt, schValid);
	        // can short-circuit if `unevaluatedProperties/Items` not supported (opts.unevaluated !== true)
	        // or if all properties and items were evaluated (it.props === true && it.items === true)
	        if (!merged)
	            gen.if((0, codegen_1.not)(valid));
	    }));
	    cxt.result(valid, () => cxt.reset(), () => cxt.error(true));
	}
	code.validateUnion = validateUnion;
	
	return code;
}

var hasRequiredKeyword;

function requireKeyword () {
	if (hasRequiredKeyword) return keyword;
	hasRequiredKeyword = 1;
	Object.defineProperty(keyword, "__esModule", { value: true });
	keyword.validateKeywordUsage = keyword.validSchemaType = keyword.funcKeywordCode = keyword.macroKeywordCode = void 0;
	const codegen_1 = requireCodegen();
	const names_1 = requireNames();
	const code_1 = requireCode();
	const errors_1 = requireErrors();
	function macroKeywordCode(cxt, def) {
	    const { gen, keyword, schema, parentSchema, it } = cxt;
	    const macroSchema = def.macro.call(it.self, schema, parentSchema, it);
	    const schemaRef = useKeyword(gen, keyword, macroSchema);
	    if (it.opts.validateSchema !== false)
	        it.self.validateSchema(macroSchema, true);
	    const valid = gen.name("valid");
	    cxt.subschema({
	        schema: macroSchema,
	        schemaPath: codegen_1.nil,
	        errSchemaPath: `${it.errSchemaPath}/${keyword}`,
	        topSchemaRef: schemaRef,
	        compositeRule: true,
	    }, valid);
	    cxt.pass(valid, () => cxt.error(true));
	}
	keyword.macroKeywordCode = macroKeywordCode;
	function funcKeywordCode(cxt, def) {
	    var _a;
	    const { gen, keyword, schema, parentSchema, $data, it } = cxt;
	    checkAsyncKeyword(it, def);
	    const validate = !$data && def.compile ? def.compile.call(it.self, schema, parentSchema, it) : def.validate;
	    const validateRef = useKeyword(gen, keyword, validate);
	    const valid = gen.let("valid");
	    cxt.block$data(valid, validateKeyword);
	    cxt.ok((_a = def.valid) !== null && _a !== void 0 ? _a : valid);
	    function validateKeyword() {
	        if (def.errors === false) {
	            assignValid();
	            if (def.modifying)
	                modifyData(cxt);
	            reportErrs(() => cxt.error());
	        }
	        else {
	            const ruleErrs = def.async ? validateAsync() : validateSync();
	            if (def.modifying)
	                modifyData(cxt);
	            reportErrs(() => addErrs(cxt, ruleErrs));
	        }
	    }
	    function validateAsync() {
	        const ruleErrs = gen.let("ruleErrs", null);
	        gen.try(() => assignValid((0, codegen_1._) `await `), (e) => gen.assign(valid, false).if((0, codegen_1._) `${e} instanceof ${it.ValidationError}`, () => gen.assign(ruleErrs, (0, codegen_1._) `${e}.errors`), () => gen.throw(e)));
	        return ruleErrs;
	    }
	    function validateSync() {
	        const validateErrs = (0, codegen_1._) `${validateRef}.errors`;
	        gen.assign(validateErrs, null);
	        assignValid(codegen_1.nil);
	        return validateErrs;
	    }
	    function assignValid(_await = def.async ? (0, codegen_1._) `await ` : codegen_1.nil) {
	        const passCxt = it.opts.passContext ? names_1.default.this : names_1.default.self;
	        const passSchema = !(("compile" in def && !$data) || def.schema === false);
	        gen.assign(valid, (0, codegen_1._) `${_await}${(0, code_1.callValidateCode)(cxt, validateRef, passCxt, passSchema)}`, def.modifying);
	    }
	    function reportErrs(errors) {
	        var _a;
	        gen.if((0, codegen_1.not)((_a = def.valid) !== null && _a !== void 0 ? _a : valid), errors);
	    }
	}
	keyword.funcKeywordCode = funcKeywordCode;
	function modifyData(cxt) {
	    const { gen, data, it } = cxt;
	    gen.if(it.parentData, () => gen.assign(data, (0, codegen_1._) `${it.parentData}[${it.parentDataProperty}]`));
	}
	function addErrs(cxt, errs) {
	    const { gen } = cxt;
	    gen.if((0, codegen_1._) `Array.isArray(${errs})`, () => {
	        gen
	            .assign(names_1.default.vErrors, (0, codegen_1._) `${names_1.default.vErrors} === null ? ${errs} : ${names_1.default.vErrors}.concat(${errs})`)
	            .assign(names_1.default.errors, (0, codegen_1._) `${names_1.default.vErrors}.length`);
	        (0, errors_1.extendErrors)(cxt);
	    }, () => cxt.error());
	}
	function checkAsyncKeyword({ schemaEnv }, def) {
	    if (def.async && !schemaEnv.$async)
	        throw new Error("async keyword in sync schema");
	}
	function useKeyword(gen, keyword, result) {
	    if (result === undefined)
	        throw new Error(`keyword "${keyword}" failed to compile`);
	    return gen.scopeValue("keyword", typeof result == "function" ? { ref: result } : { ref: result, code: (0, codegen_1.stringify)(result) });
	}
	function validSchemaType(schema, schemaType, allowUndefined = false) {
	    // TODO add tests
	    return (!schemaType.length ||
	        schemaType.some((st) => st === "array"
	            ? Array.isArray(schema)
	            : st === "object"
	                ? schema && typeof schema == "object" && !Array.isArray(schema)
	                : typeof schema == st || (allowUndefined && typeof schema == "undefined")));
	}
	keyword.validSchemaType = validSchemaType;
	function validateKeywordUsage({ schema, opts, self, errSchemaPath }, def, keyword) {
	    /* istanbul ignore if */
	    if (Array.isArray(def.keyword) ? !def.keyword.includes(keyword) : def.keyword !== keyword) {
	        throw new Error("ajv implementation error");
	    }
	    const deps = def.dependencies;
	    if (deps === null || deps === void 0 ? void 0 : deps.some((kwd) => !Object.prototype.hasOwnProperty.call(schema, kwd))) {
	        throw new Error(`parent schema must have dependencies of ${keyword}: ${deps.join(",")}`);
	    }
	    if (def.validateSchema) {
	        const valid = def.validateSchema(schema[keyword]);
	        if (!valid) {
	            const msg = `keyword "${keyword}" value is invalid at path "${errSchemaPath}": ` +
	                self.errorsText(def.validateSchema.errors);
	            if (opts.validateSchema === "log")
	                self.logger.error(msg);
	            else
	                throw new Error(msg);
	        }
	    }
	}
	keyword.validateKeywordUsage = validateKeywordUsage;
	
	return keyword;
}

var subschema = {};

var hasRequiredSubschema;

function requireSubschema () {
	if (hasRequiredSubschema) return subschema;
	hasRequiredSubschema = 1;
	Object.defineProperty(subschema, "__esModule", { value: true });
	subschema.extendSubschemaMode = subschema.extendSubschemaData = subschema.getSubschema = void 0;
	const codegen_1 = requireCodegen();
	const util_1 = util$1;
	function getSubschema(it, { keyword, schemaProp, schema, schemaPath, errSchemaPath, topSchemaRef }) {
	    if (keyword !== undefined && schema !== undefined) {
	        throw new Error('both "keyword" and "schema" passed, only one allowed');
	    }
	    if (keyword !== undefined) {
	        const sch = it.schema[keyword];
	        return schemaProp === undefined
	            ? {
	                schema: sch,
	                schemaPath: (0, codegen_1._) `${it.schemaPath}${(0, codegen_1.getProperty)(keyword)}`,
	                errSchemaPath: `${it.errSchemaPath}/${keyword}`,
	            }
	            : {
	                schema: sch[schemaProp],
	                schemaPath: (0, codegen_1._) `${it.schemaPath}${(0, codegen_1.getProperty)(keyword)}${(0, codegen_1.getProperty)(schemaProp)}`,
	                errSchemaPath: `${it.errSchemaPath}/${keyword}/${(0, util_1.escapeFragment)(schemaProp)}`,
	            };
	    }
	    if (schema !== undefined) {
	        if (schemaPath === undefined || errSchemaPath === undefined || topSchemaRef === undefined) {
	            throw new Error('"schemaPath", "errSchemaPath" and "topSchemaRef" are required with "schema"');
	        }
	        return {
	            schema,
	            schemaPath,
	            topSchemaRef,
	            errSchemaPath,
	        };
	    }
	    throw new Error('either "keyword" or "schema" must be passed');
	}
	subschema.getSubschema = getSubschema;
	function extendSubschemaData(subschema, it, { dataProp, dataPropType: dpType, data, dataTypes, propertyName }) {
	    if (data !== undefined && dataProp !== undefined) {
	        throw new Error('both "data" and "dataProp" passed, only one allowed');
	    }
	    const { gen } = it;
	    if (dataProp !== undefined) {
	        const { errorPath, dataPathArr, opts } = it;
	        const nextData = gen.let("data", (0, codegen_1._) `${it.data}${(0, codegen_1.getProperty)(dataProp)}`, true);
	        dataContextProps(nextData);
	        subschema.errorPath = (0, codegen_1.str) `${errorPath}${(0, util_1.getErrorPath)(dataProp, dpType, opts.jsPropertySyntax)}`;
	        subschema.parentDataProperty = (0, codegen_1._) `${dataProp}`;
	        subschema.dataPathArr = [...dataPathArr, subschema.parentDataProperty];
	    }
	    if (data !== undefined) {
	        const nextData = data instanceof codegen_1.Name ? data : gen.let("data", data, true); // replaceable if used once?
	        dataContextProps(nextData);
	        if (propertyName !== undefined)
	            subschema.propertyName = propertyName;
	        // TODO something is possibly wrong here with not changing parentDataProperty and not appending dataPathArr
	    }
	    if (dataTypes)
	        subschema.dataTypes = dataTypes;
	    function dataContextProps(_nextData) {
	        subschema.data = _nextData;
	        subschema.dataLevel = it.dataLevel + 1;
	        subschema.dataTypes = [];
	        it.definedProperties = new Set();
	        subschema.parentData = it.data;
	        subschema.dataNames = [...it.dataNames, _nextData];
	    }
	}
	subschema.extendSubschemaData = extendSubschemaData;
	function extendSubschemaMode(subschema, { jtdDiscriminator, jtdMetadata, compositeRule, createErrors, allErrors }) {
	    if (compositeRule !== undefined)
	        subschema.compositeRule = compositeRule;
	    if (createErrors !== undefined)
	        subschema.createErrors = createErrors;
	    if (allErrors !== undefined)
	        subschema.allErrors = allErrors;
	    subschema.jtdDiscriminator = jtdDiscriminator; // not inherited
	    subschema.jtdMetadata = jtdMetadata; // not inherited
	}
	subschema.extendSubschemaMode = extendSubschemaMode;
	
	return subschema;
}

var resolve$1 = {};

// do not edit .js files directly - edit src/index.jst



var fastDeepEqual = function equal(a, b) {
  if (a === b) return true;

  if (a && b && typeof a == 'object' && typeof b == 'object') {
    if (a.constructor !== b.constructor) return false;

    var length, i, keys;
    if (Array.isArray(a)) {
      length = a.length;
      if (length != b.length) return false;
      for (i = length; i-- !== 0;)
        if (!equal(a[i], b[i])) return false;
      return true;
    }



    if (a.constructor === RegExp) return a.source === b.source && a.flags === b.flags;
    if (a.valueOf !== Object.prototype.valueOf) return a.valueOf() === b.valueOf();
    if (a.toString !== Object.prototype.toString) return a.toString() === b.toString();

    keys = Object.keys(a);
    length = keys.length;
    if (length !== Object.keys(b).length) return false;

    for (i = length; i-- !== 0;)
      if (!Object.prototype.hasOwnProperty.call(b, keys[i])) return false;

    for (i = length; i-- !== 0;) {
      var key = keys[i];

      if (!equal(a[key], b[key])) return false;
    }

    return true;
  }

  // true if both NaN, false otherwise
  return a!==a && b!==b;
};

var jsonSchemaTraverse = {exports: {}};

var traverse$1 = jsonSchemaTraverse.exports = function (schema, opts, cb) {
  // Legacy support for v0.3.1 and earlier.
  if (typeof opts == 'function') {
    cb = opts;
    opts = {};
  }

  cb = opts.cb || cb;
  var pre = (typeof cb == 'function') ? cb : cb.pre || function() {};
  var post = cb.post || function() {};

  _traverse(opts, pre, post, schema, '', schema);
};


traverse$1.keywords = {
  additionalItems: true,
  items: true,
  contains: true,
  additionalProperties: true,
  propertyNames: true,
  not: true,
  if: true,
  then: true,
  else: true
};

traverse$1.arrayKeywords = {
  items: true,
  allOf: true,
  anyOf: true,
  oneOf: true
};

traverse$1.propsKeywords = {
  $defs: true,
  definitions: true,
  properties: true,
  patternProperties: true,
  dependencies: true
};

traverse$1.skipKeywords = {
  default: true,
  enum: true,
  const: true,
  required: true,
  maximum: true,
  minimum: true,
  exclusiveMaximum: true,
  exclusiveMinimum: true,
  multipleOf: true,
  maxLength: true,
  minLength: true,
  pattern: true,
  format: true,
  maxItems: true,
  minItems: true,
  uniqueItems: true,
  maxProperties: true,
  minProperties: true
};


function _traverse(opts, pre, post, schema, jsonPtr, rootSchema, parentJsonPtr, parentKeyword, parentSchema, keyIndex) {
  if (schema && typeof schema == 'object' && !Array.isArray(schema)) {
    pre(schema, jsonPtr, rootSchema, parentJsonPtr, parentKeyword, parentSchema, keyIndex);
    for (var key in schema) {
      var sch = schema[key];
      if (Array.isArray(sch)) {
        if (key in traverse$1.arrayKeywords) {
          for (var i=0; i<sch.length; i++)
            _traverse(opts, pre, post, sch[i], jsonPtr + '/' + key + '/' + i, rootSchema, jsonPtr, key, schema, i);
        }
      } else if (key in traverse$1.propsKeywords) {
        if (sch && typeof sch == 'object') {
          for (var prop in sch)
            _traverse(opts, pre, post, sch[prop], jsonPtr + '/' + key + '/' + escapeJsonPtr(prop), rootSchema, jsonPtr, key, schema, prop);
        }
      } else if (key in traverse$1.keywords || (opts.allKeys && !(key in traverse$1.skipKeywords))) {
        _traverse(opts, pre, post, sch, jsonPtr + '/' + key, rootSchema, jsonPtr, key, schema);
      }
    }
    post(schema, jsonPtr, rootSchema, parentJsonPtr, parentKeyword, parentSchema, keyIndex);
  }
}


function escapeJsonPtr(str) {
  return str.replace(/~/g, '~0').replace(/\//g, '~1');
}

var jsonSchemaTraverseExports = jsonSchemaTraverse.exports;

Object.defineProperty(resolve$1, "__esModule", { value: true });
resolve$1.getSchemaRefs = resolve$1.resolveUrl = resolve$1.normalizeId = resolve$1._getFullPath = resolve$1.getFullPath = resolve$1.inlineRef = void 0;
const util_1$l = util$1;
const equal$2 = fastDeepEqual;
const traverse = jsonSchemaTraverseExports;
// TODO refactor to use keyword definitions
const SIMPLE_INLINED = new Set([
    "type",
    "format",
    "pattern",
    "maxLength",
    "minLength",
    "maxProperties",
    "minProperties",
    "maxItems",
    "minItems",
    "maximum",
    "minimum",
    "uniqueItems",
    "multipleOf",
    "required",
    "enum",
    "const",
]);
function inlineRef(schema, limit = true) {
    if (typeof schema == "boolean")
        return true;
    if (limit === true)
        return !hasRef(schema);
    if (!limit)
        return false;
    return countKeys(schema) <= limit;
}
resolve$1.inlineRef = inlineRef;
const REF_KEYWORDS = new Set([
    "$ref",
    "$recursiveRef",
    "$recursiveAnchor",
    "$dynamicRef",
    "$dynamicAnchor",
]);
function hasRef(schema) {
    for (const key in schema) {
        if (REF_KEYWORDS.has(key))
            return true;
        const sch = schema[key];
        if (Array.isArray(sch) && sch.some(hasRef))
            return true;
        if (typeof sch == "object" && hasRef(sch))
            return true;
    }
    return false;
}
function countKeys(schema) {
    let count = 0;
    for (const key in schema) {
        if (key === "$ref")
            return Infinity;
        count++;
        if (SIMPLE_INLINED.has(key))
            continue;
        if (typeof schema[key] == "object") {
            (0, util_1$l.eachItem)(schema[key], (sch) => (count += countKeys(sch)));
        }
        if (count === Infinity)
            return Infinity;
    }
    return count;
}
function getFullPath(resolver, id = "", normalize) {
    if (normalize !== false)
        id = normalizeId(id);
    const p = resolver.parse(id);
    return _getFullPath(resolver, p);
}
resolve$1.getFullPath = getFullPath;
function _getFullPath(resolver, p) {
    const serialized = resolver.serialize(p);
    return serialized.split("#")[0] + "#";
}
resolve$1._getFullPath = _getFullPath;
const TRAILING_SLASH_HASH = /#\/?$/;
function normalizeId(id) {
    return id ? id.replace(TRAILING_SLASH_HASH, "") : "";
}
resolve$1.normalizeId = normalizeId;
function resolveUrl(resolver, baseId, id) {
    id = normalizeId(id);
    return resolver.resolve(baseId, id);
}
resolve$1.resolveUrl = resolveUrl;
const ANCHOR = /^[a-z_][-a-z0-9._]*$/i;
function getSchemaRefs(schema, baseId) {
    if (typeof schema == "boolean")
        return {};
    const { schemaId, uriResolver } = this.opts;
    const schId = normalizeId(schema[schemaId] || baseId);
    const baseIds = { "": schId };
    const pathPrefix = getFullPath(uriResolver, schId, false);
    const localRefs = {};
    const schemaRefs = new Set();
    traverse(schema, { allKeys: true }, (sch, jsonPtr, _, parentJsonPtr) => {
        if (parentJsonPtr === undefined)
            return;
        const fullPath = pathPrefix + jsonPtr;
        let innerBaseId = baseIds[parentJsonPtr];
        if (typeof sch[schemaId] == "string")
            innerBaseId = addRef.call(this, sch[schemaId]);
        addAnchor.call(this, sch.$anchor);
        addAnchor.call(this, sch.$dynamicAnchor);
        baseIds[jsonPtr] = innerBaseId;
        function addRef(ref) {
            // eslint-disable-next-line @typescript-eslint/unbound-method
            const _resolve = this.opts.uriResolver.resolve;
            ref = normalizeId(innerBaseId ? _resolve(innerBaseId, ref) : ref);
            if (schemaRefs.has(ref))
                throw ambiguos(ref);
            schemaRefs.add(ref);
            let schOrRef = this.refs[ref];
            if (typeof schOrRef == "string")
                schOrRef = this.refs[schOrRef];
            if (typeof schOrRef == "object") {
                checkAmbiguosRef(sch, schOrRef.schema, ref);
            }
            else if (ref !== normalizeId(fullPath)) {
                if (ref[0] === "#") {
                    checkAmbiguosRef(sch, localRefs[ref], ref);
                    localRefs[ref] = sch;
                }
                else {
                    this.refs[ref] = fullPath;
                }
            }
            return ref;
        }
        function addAnchor(anchor) {
            if (typeof anchor == "string") {
                if (!ANCHOR.test(anchor))
                    throw new Error(`invalid anchor "${anchor}"`);
                addRef.call(this, `#${anchor}`);
            }
        }
    });
    return localRefs;
    function checkAmbiguosRef(sch1, sch2, ref) {
        if (sch2 !== undefined && !equal$2(sch1, sch2))
            throw ambiguos(ref);
    }
    function ambiguos(ref) {
        return new Error(`reference "${ref}" resolves to more than one schema`);
    }
}
resolve$1.getSchemaRefs = getSchemaRefs;

var hasRequiredValidate;

function requireValidate () {
	if (hasRequiredValidate) return validate;
	hasRequiredValidate = 1;
	Object.defineProperty(validate, "__esModule", { value: true });
	validate.getData = validate.KeywordCxt = validate.validateFunctionCode = void 0;
	const boolSchema_1 = requireBoolSchema();
	const dataType_1 = dataType;
	const applicability_1 = requireApplicability();
	const dataType_2 = dataType;
	const defaults_1 = requireDefaults();
	const keyword_1 = requireKeyword();
	const subschema_1 = requireSubschema();
	const codegen_1 = requireCodegen();
	const names_1 = requireNames();
	const resolve_1 = resolve$1;
	const util_1 = util$1;
	const errors_1 = requireErrors();
	// schema compilation - generates validation function, subschemaCode (below) is used for subschemas
	function validateFunctionCode(it) {
	    if (isSchemaObj(it)) {
	        checkKeywords(it);
	        if (schemaCxtHasRules(it)) {
	            topSchemaObjCode(it);
	            return;
	        }
	    }
	    validateFunction(it, () => (0, boolSchema_1.topBoolOrEmptySchema)(it));
	}
	validate.validateFunctionCode = validateFunctionCode;
	function validateFunction({ gen, validateName, schema, schemaEnv, opts }, body) {
	    if (opts.code.es5) {
	        gen.func(validateName, (0, codegen_1._) `${names_1.default.data}, ${names_1.default.valCxt}`, schemaEnv.$async, () => {
	            gen.code((0, codegen_1._) `"use strict"; ${funcSourceUrl(schema, opts)}`);
	            destructureValCxtES5(gen, opts);
	            gen.code(body);
	        });
	    }
	    else {
	        gen.func(validateName, (0, codegen_1._) `${names_1.default.data}, ${destructureValCxt(opts)}`, schemaEnv.$async, () => gen.code(funcSourceUrl(schema, opts)).code(body));
	    }
	}
	function destructureValCxt(opts) {
	    return (0, codegen_1._) `{${names_1.default.instancePath}="", ${names_1.default.parentData}, ${names_1.default.parentDataProperty}, ${names_1.default.rootData}=${names_1.default.data}${opts.dynamicRef ? (0, codegen_1._) `, ${names_1.default.dynamicAnchors}={}` : codegen_1.nil}}={}`;
	}
	function destructureValCxtES5(gen, opts) {
	    gen.if(names_1.default.valCxt, () => {
	        gen.var(names_1.default.instancePath, (0, codegen_1._) `${names_1.default.valCxt}.${names_1.default.instancePath}`);
	        gen.var(names_1.default.parentData, (0, codegen_1._) `${names_1.default.valCxt}.${names_1.default.parentData}`);
	        gen.var(names_1.default.parentDataProperty, (0, codegen_1._) `${names_1.default.valCxt}.${names_1.default.parentDataProperty}`);
	        gen.var(names_1.default.rootData, (0, codegen_1._) `${names_1.default.valCxt}.${names_1.default.rootData}`);
	        if (opts.dynamicRef)
	            gen.var(names_1.default.dynamicAnchors, (0, codegen_1._) `${names_1.default.valCxt}.${names_1.default.dynamicAnchors}`);
	    }, () => {
	        gen.var(names_1.default.instancePath, (0, codegen_1._) `""`);
	        gen.var(names_1.default.parentData, (0, codegen_1._) `undefined`);
	        gen.var(names_1.default.parentDataProperty, (0, codegen_1._) `undefined`);
	        gen.var(names_1.default.rootData, names_1.default.data);
	        if (opts.dynamicRef)
	            gen.var(names_1.default.dynamicAnchors, (0, codegen_1._) `{}`);
	    });
	}
	function topSchemaObjCode(it) {
	    const { schema, opts, gen } = it;
	    validateFunction(it, () => {
	        if (opts.$comment && schema.$comment)
	            commentKeyword(it);
	        checkNoDefault(it);
	        gen.let(names_1.default.vErrors, null);
	        gen.let(names_1.default.errors, 0);
	        if (opts.unevaluated)
	            resetEvaluated(it);
	        typeAndKeywords(it);
	        returnResults(it);
	    });
	    return;
	}
	function resetEvaluated(it) {
	    // TODO maybe some hook to execute it in the end to check whether props/items are Name, as in assignEvaluated
	    const { gen, validateName } = it;
	    it.evaluated = gen.const("evaluated", (0, codegen_1._) `${validateName}.evaluated`);
	    gen.if((0, codegen_1._) `${it.evaluated}.dynamicProps`, () => gen.assign((0, codegen_1._) `${it.evaluated}.props`, (0, codegen_1._) `undefined`));
	    gen.if((0, codegen_1._) `${it.evaluated}.dynamicItems`, () => gen.assign((0, codegen_1._) `${it.evaluated}.items`, (0, codegen_1._) `undefined`));
	}
	function funcSourceUrl(schema, opts) {
	    const schId = typeof schema == "object" && schema[opts.schemaId];
	    return schId && (opts.code.source || opts.code.process) ? (0, codegen_1._) `/*# sourceURL=${schId} */` : codegen_1.nil;
	}
	// schema compilation - this function is used recursively to generate code for sub-schemas
	function subschemaCode(it, valid) {
	    if (isSchemaObj(it)) {
	        checkKeywords(it);
	        if (schemaCxtHasRules(it)) {
	            subSchemaObjCode(it, valid);
	            return;
	        }
	    }
	    (0, boolSchema_1.boolOrEmptySchema)(it, valid);
	}
	function schemaCxtHasRules({ schema, self }) {
	    if (typeof schema == "boolean")
	        return !schema;
	    for (const key in schema)
	        if (self.RULES.all[key])
	            return true;
	    return false;
	}
	function isSchemaObj(it) {
	    return typeof it.schema != "boolean";
	}
	function subSchemaObjCode(it, valid) {
	    const { schema, gen, opts } = it;
	    if (opts.$comment && schema.$comment)
	        commentKeyword(it);
	    updateContext(it);
	    checkAsyncSchema(it);
	    const errsCount = gen.const("_errs", names_1.default.errors);
	    typeAndKeywords(it, errsCount);
	    // TODO var
	    gen.var(valid, (0, codegen_1._) `${errsCount} === ${names_1.default.errors}`);
	}
	function checkKeywords(it) {
	    (0, util_1.checkUnknownRules)(it);
	    checkRefsAndKeywords(it);
	}
	function typeAndKeywords(it, errsCount) {
	    if (it.opts.jtd)
	        return schemaKeywords(it, [], false, errsCount);
	    const types = (0, dataType_1.getSchemaTypes)(it.schema);
	    const checkedTypes = (0, dataType_1.coerceAndCheckDataType)(it, types);
	    schemaKeywords(it, types, !checkedTypes, errsCount);
	}
	function checkRefsAndKeywords(it) {
	    const { schema, errSchemaPath, opts, self } = it;
	    if (schema.$ref && opts.ignoreKeywordsWithRef && (0, util_1.schemaHasRulesButRef)(schema, self.RULES)) {
	        self.logger.warn(`$ref: keywords ignored in schema at path "${errSchemaPath}"`);
	    }
	}
	function checkNoDefault(it) {
	    const { schema, opts } = it;
	    if (schema.default !== undefined && opts.useDefaults && opts.strictSchema) {
	        (0, util_1.checkStrictMode)(it, "default is ignored in the schema root");
	    }
	}
	function updateContext(it) {
	    const schId = it.schema[it.opts.schemaId];
	    if (schId)
	        it.baseId = (0, resolve_1.resolveUrl)(it.opts.uriResolver, it.baseId, schId);
	}
	function checkAsyncSchema(it) {
	    if (it.schema.$async && !it.schemaEnv.$async)
	        throw new Error("async schema in sync schema");
	}
	function commentKeyword({ gen, schemaEnv, schema, errSchemaPath, opts }) {
	    const msg = schema.$comment;
	    if (opts.$comment === true) {
	        gen.code((0, codegen_1._) `${names_1.default.self}.logger.log(${msg})`);
	    }
	    else if (typeof opts.$comment == "function") {
	        const schemaPath = (0, codegen_1.str) `${errSchemaPath}/$comment`;
	        const rootName = gen.scopeValue("root", { ref: schemaEnv.root });
	        gen.code((0, codegen_1._) `${names_1.default.self}.opts.$comment(${msg}, ${schemaPath}, ${rootName}.schema)`);
	    }
	}
	function returnResults(it) {
	    const { gen, schemaEnv, validateName, ValidationError, opts } = it;
	    if (schemaEnv.$async) {
	        // TODO assign unevaluated
	        gen.if((0, codegen_1._) `${names_1.default.errors} === 0`, () => gen.return(names_1.default.data), () => gen.throw((0, codegen_1._) `new ${ValidationError}(${names_1.default.vErrors})`));
	    }
	    else {
	        gen.assign((0, codegen_1._) `${validateName}.errors`, names_1.default.vErrors);
	        if (opts.unevaluated)
	            assignEvaluated(it);
	        gen.return((0, codegen_1._) `${names_1.default.errors} === 0`);
	    }
	}
	function assignEvaluated({ gen, evaluated, props, items }) {
	    if (props instanceof codegen_1.Name)
	        gen.assign((0, codegen_1._) `${evaluated}.props`, props);
	    if (items instanceof codegen_1.Name)
	        gen.assign((0, codegen_1._) `${evaluated}.items`, items);
	}
	function schemaKeywords(it, types, typeErrors, errsCount) {
	    const { gen, schema, data, allErrors, opts, self } = it;
	    const { RULES } = self;
	    if (schema.$ref && (opts.ignoreKeywordsWithRef || !(0, util_1.schemaHasRulesButRef)(schema, RULES))) {
	        gen.block(() => keywordCode(it, "$ref", RULES.all.$ref.definition)); // TODO typecast
	        return;
	    }
	    if (!opts.jtd)
	        checkStrictTypes(it, types);
	    gen.block(() => {
	        for (const group of RULES.rules)
	            groupKeywords(group);
	        groupKeywords(RULES.post);
	    });
	    function groupKeywords(group) {
	        if (!(0, applicability_1.shouldUseGroup)(schema, group))
	            return;
	        if (group.type) {
	            gen.if((0, dataType_2.checkDataType)(group.type, data, opts.strictNumbers));
	            iterateKeywords(it, group);
	            if (types.length === 1 && types[0] === group.type && typeErrors) {
	                gen.else();
	                (0, dataType_2.reportTypeError)(it);
	            }
	            gen.endIf();
	        }
	        else {
	            iterateKeywords(it, group);
	        }
	        // TODO make it "ok" call?
	        if (!allErrors)
	            gen.if((0, codegen_1._) `${names_1.default.errors} === ${errsCount || 0}`);
	    }
	}
	function iterateKeywords(it, group) {
	    const { gen, schema, opts: { useDefaults }, } = it;
	    if (useDefaults)
	        (0, defaults_1.assignDefaults)(it, group.type);
	    gen.block(() => {
	        for (const rule of group.rules) {
	            if ((0, applicability_1.shouldUseRule)(schema, rule)) {
	                keywordCode(it, rule.keyword, rule.definition, group.type);
	            }
	        }
	    });
	}
	function checkStrictTypes(it, types) {
	    if (it.schemaEnv.meta || !it.opts.strictTypes)
	        return;
	    checkContextTypes(it, types);
	    if (!it.opts.allowUnionTypes)
	        checkMultipleTypes(it, types);
	    checkKeywordTypes(it, it.dataTypes);
	}
	function checkContextTypes(it, types) {
	    if (!types.length)
	        return;
	    if (!it.dataTypes.length) {
	        it.dataTypes = types;
	        return;
	    }
	    types.forEach((t) => {
	        if (!includesType(it.dataTypes, t)) {
	            strictTypesError(it, `type "${t}" not allowed by context "${it.dataTypes.join(",")}"`);
	        }
	    });
	    narrowSchemaTypes(it, types);
	}
	function checkMultipleTypes(it, ts) {
	    if (ts.length > 1 && !(ts.length === 2 && ts.includes("null"))) {
	        strictTypesError(it, "use allowUnionTypes to allow union type keyword");
	    }
	}
	function checkKeywordTypes(it, ts) {
	    const rules = it.self.RULES.all;
	    for (const keyword in rules) {
	        const rule = rules[keyword];
	        if (typeof rule == "object" && (0, applicability_1.shouldUseRule)(it.schema, rule)) {
	            const { type } = rule.definition;
	            if (type.length && !type.some((t) => hasApplicableType(ts, t))) {
	                strictTypesError(it, `missing type "${type.join(",")}" for keyword "${keyword}"`);
	            }
	        }
	    }
	}
	function hasApplicableType(schTs, kwdT) {
	    return schTs.includes(kwdT) || (kwdT === "number" && schTs.includes("integer"));
	}
	function includesType(ts, t) {
	    return ts.includes(t) || (t === "integer" && ts.includes("number"));
	}
	function narrowSchemaTypes(it, withTypes) {
	    const ts = [];
	    for (const t of it.dataTypes) {
	        if (includesType(withTypes, t))
	            ts.push(t);
	        else if (withTypes.includes("integer") && t === "number")
	            ts.push("integer");
	    }
	    it.dataTypes = ts;
	}
	function strictTypesError(it, msg) {
	    const schemaPath = it.schemaEnv.baseId + it.errSchemaPath;
	    msg += ` at "${schemaPath}" (strictTypes)`;
	    (0, util_1.checkStrictMode)(it, msg, it.opts.strictTypes);
	}
	class KeywordCxt {
	    constructor(it, def, keyword) {
	        (0, keyword_1.validateKeywordUsage)(it, def, keyword);
	        this.gen = it.gen;
	        this.allErrors = it.allErrors;
	        this.keyword = keyword;
	        this.data = it.data;
	        this.schema = it.schema[keyword];
	        this.$data = def.$data && it.opts.$data && this.schema && this.schema.$data;
	        this.schemaValue = (0, util_1.schemaRefOrVal)(it, this.schema, keyword, this.$data);
	        this.schemaType = def.schemaType;
	        this.parentSchema = it.schema;
	        this.params = {};
	        this.it = it;
	        this.def = def;
	        if (this.$data) {
	            this.schemaCode = it.gen.const("vSchema", getData(this.$data, it));
	        }
	        else {
	            this.schemaCode = this.schemaValue;
	            if (!(0, keyword_1.validSchemaType)(this.schema, def.schemaType, def.allowUndefined)) {
	                throw new Error(`${keyword} value must be ${JSON.stringify(def.schemaType)}`);
	            }
	        }
	        if ("code" in def ? def.trackErrors : def.errors !== false) {
	            this.errsCount = it.gen.const("_errs", names_1.default.errors);
	        }
	    }
	    result(condition, successAction, failAction) {
	        this.failResult((0, codegen_1.not)(condition), successAction, failAction);
	    }
	    failResult(condition, successAction, failAction) {
	        this.gen.if(condition);
	        if (failAction)
	            failAction();
	        else
	            this.error();
	        if (successAction) {
	            this.gen.else();
	            successAction();
	            if (this.allErrors)
	                this.gen.endIf();
	        }
	        else {
	            if (this.allErrors)
	                this.gen.endIf();
	            else
	                this.gen.else();
	        }
	    }
	    pass(condition, failAction) {
	        this.failResult((0, codegen_1.not)(condition), undefined, failAction);
	    }
	    fail(condition) {
	        if (condition === undefined) {
	            this.error();
	            if (!this.allErrors)
	                this.gen.if(false); // this branch will be removed by gen.optimize
	            return;
	        }
	        this.gen.if(condition);
	        this.error();
	        if (this.allErrors)
	            this.gen.endIf();
	        else
	            this.gen.else();
	    }
	    fail$data(condition) {
	        if (!this.$data)
	            return this.fail(condition);
	        const { schemaCode } = this;
	        this.fail((0, codegen_1._) `${schemaCode} !== undefined && (${(0, codegen_1.or)(this.invalid$data(), condition)})`);
	    }
	    error(append, errorParams, errorPaths) {
	        if (errorParams) {
	            this.setParams(errorParams);
	            this._error(append, errorPaths);
	            this.setParams({});
	            return;
	        }
	        this._error(append, errorPaths);
	    }
	    _error(append, errorPaths) {
	        (append ? errors_1.reportExtraError : errors_1.reportError)(this, this.def.error, errorPaths);
	    }
	    $dataError() {
	        (0, errors_1.reportError)(this, this.def.$dataError || errors_1.keyword$DataError);
	    }
	    reset() {
	        if (this.errsCount === undefined)
	            throw new Error('add "trackErrors" to keyword definition');
	        (0, errors_1.resetErrorsCount)(this.gen, this.errsCount);
	    }
	    ok(cond) {
	        if (!this.allErrors)
	            this.gen.if(cond);
	    }
	    setParams(obj, assign) {
	        if (assign)
	            Object.assign(this.params, obj);
	        else
	            this.params = obj;
	    }
	    block$data(valid, codeBlock, $dataValid = codegen_1.nil) {
	        this.gen.block(() => {
	            this.check$data(valid, $dataValid);
	            codeBlock();
	        });
	    }
	    check$data(valid = codegen_1.nil, $dataValid = codegen_1.nil) {
	        if (!this.$data)
	            return;
	        const { gen, schemaCode, schemaType, def } = this;
	        gen.if((0, codegen_1.or)((0, codegen_1._) `${schemaCode} === undefined`, $dataValid));
	        if (valid !== codegen_1.nil)
	            gen.assign(valid, true);
	        if (schemaType.length || def.validateSchema) {
	            gen.elseIf(this.invalid$data());
	            this.$dataError();
	            if (valid !== codegen_1.nil)
	                gen.assign(valid, false);
	        }
	        gen.else();
	    }
	    invalid$data() {
	        const { gen, schemaCode, schemaType, def, it } = this;
	        return (0, codegen_1.or)(wrong$DataType(), invalid$DataSchema());
	        function wrong$DataType() {
	            if (schemaType.length) {
	                /* istanbul ignore if */
	                if (!(schemaCode instanceof codegen_1.Name))
	                    throw new Error("ajv implementation error");
	                const st = Array.isArray(schemaType) ? schemaType : [schemaType];
	                return (0, codegen_1._) `${(0, dataType_2.checkDataTypes)(st, schemaCode, it.opts.strictNumbers, dataType_2.DataType.Wrong)}`;
	            }
	            return codegen_1.nil;
	        }
	        function invalid$DataSchema() {
	            if (def.validateSchema) {
	                const validateSchemaRef = gen.scopeValue("validate$data", { ref: def.validateSchema }); // TODO value.code for standalone
	                return (0, codegen_1._) `!${validateSchemaRef}(${schemaCode})`;
	            }
	            return codegen_1.nil;
	        }
	    }
	    subschema(appl, valid) {
	        const subschema = (0, subschema_1.getSubschema)(this.it, appl);
	        (0, subschema_1.extendSubschemaData)(subschema, this.it, appl);
	        (0, subschema_1.extendSubschemaMode)(subschema, appl);
	        const nextContext = { ...this.it, ...subschema, items: undefined, props: undefined };
	        subschemaCode(nextContext, valid);
	        return nextContext;
	    }
	    mergeEvaluated(schemaCxt, toName) {
	        const { it, gen } = this;
	        if (!it.opts.unevaluated)
	            return;
	        if (it.props !== true && schemaCxt.props !== undefined) {
	            it.props = util_1.mergeEvaluated.props(gen, schemaCxt.props, it.props, toName);
	        }
	        if (it.items !== true && schemaCxt.items !== undefined) {
	            it.items = util_1.mergeEvaluated.items(gen, schemaCxt.items, it.items, toName);
	        }
	    }
	    mergeValidEvaluated(schemaCxt, valid) {
	        const { it, gen } = this;
	        if (it.opts.unevaluated && (it.props !== true || it.items !== true)) {
	            gen.if(valid, () => this.mergeEvaluated(schemaCxt, codegen_1.Name));
	            return true;
	        }
	    }
	}
	validate.KeywordCxt = KeywordCxt;
	function keywordCode(it, keyword, def, ruleType) {
	    const cxt = new KeywordCxt(it, def, keyword);
	    if ("code" in def) {
	        def.code(cxt, ruleType);
	    }
	    else if (cxt.$data && def.validate) {
	        (0, keyword_1.funcKeywordCode)(cxt, def);
	    }
	    else if ("macro" in def) {
	        (0, keyword_1.macroKeywordCode)(cxt, def);
	    }
	    else if (def.compile || def.validate) {
	        (0, keyword_1.funcKeywordCode)(cxt, def);
	    }
	}
	const JSON_POINTER = /^\/(?:[^~]|~0|~1)*$/;
	const RELATIVE_JSON_POINTER = /^([0-9]+)(#|\/(?:[^~]|~0|~1)*)?$/;
	function getData($data, { dataLevel, dataNames, dataPathArr }) {
	    let jsonPointer;
	    let data;
	    if ($data === "")
	        return names_1.default.rootData;
	    if ($data[0] === "/") {
	        if (!JSON_POINTER.test($data))
	            throw new Error(`Invalid JSON-pointer: ${$data}`);
	        jsonPointer = $data;
	        data = names_1.default.rootData;
	    }
	    else {
	        const matches = RELATIVE_JSON_POINTER.exec($data);
	        if (!matches)
	            throw new Error(`Invalid JSON-pointer: ${$data}`);
	        const up = +matches[1];
	        jsonPointer = matches[2];
	        if (jsonPointer === "#") {
	            if (up >= dataLevel)
	                throw new Error(errorMsg("property/index", up));
	            return dataPathArr[dataLevel - up];
	        }
	        if (up > dataLevel)
	            throw new Error(errorMsg("data", up));
	        data = dataNames[dataLevel - up];
	        if (!jsonPointer)
	            return data;
	    }
	    let expr = data;
	    const segments = jsonPointer.split("/");
	    for (const segment of segments) {
	        if (segment) {
	            data = (0, codegen_1._) `${data}${(0, codegen_1.getProperty)((0, util_1.unescapeJsonPointer)(segment))}`;
	            expr = (0, codegen_1._) `${expr} && ${data}`;
	        }
	    }
	    return expr;
	    function errorMsg(pointerType, up) {
	        return `Cannot access ${pointerType} ${up} levels up, current level is ${dataLevel}`;
	    }
	}
	validate.getData = getData;
	
	return validate;
}

var validation_error = {};

var hasRequiredValidation_error;

function requireValidation_error () {
	if (hasRequiredValidation_error) return validation_error;
	hasRequiredValidation_error = 1;
	Object.defineProperty(validation_error, "__esModule", { value: true });
	class ValidationError extends Error {
	    constructor(errors) {
	        super("validation failed");
	        this.errors = errors;
	        this.ajv = this.validation = true;
	    }
	}
	validation_error.default = ValidationError;
	
	return validation_error;
}

var ref_error = {};

var hasRequiredRef_error;

function requireRef_error () {
	if (hasRequiredRef_error) return ref_error;
	hasRequiredRef_error = 1;
	Object.defineProperty(ref_error, "__esModule", { value: true });
	const resolve_1 = resolve$1;
	class MissingRefError extends Error {
	    constructor(resolver, baseId, ref, msg) {
	        super(msg || `can't resolve reference ${ref} from id ${baseId}`);
	        this.missingRef = (0, resolve_1.resolveUrl)(resolver, baseId, ref);
	        this.missingSchema = (0, resolve_1.normalizeId)((0, resolve_1.getFullPath)(resolver, this.missingRef));
	    }
	}
	ref_error.default = MissingRefError;
	
	return ref_error;
}

var compile = {};

Object.defineProperty(compile, "__esModule", { value: true });
compile.resolveSchema = compile.getCompilingSchema = compile.resolveRef = compile.compileSchema = compile.SchemaEnv = void 0;
const codegen_1$m = requireCodegen();
const validation_error_1 = requireValidation_error();
const names_1$2 = requireNames();
const resolve_1 = resolve$1;
const util_1$k = util$1;
const validate_1$1 = requireValidate();
class SchemaEnv {
    constructor(env) {
        var _a;
        this.refs = {};
        this.dynamicAnchors = {};
        let schema;
        if (typeof env.schema == "object")
            schema = env.schema;
        this.schema = env.schema;
        this.schemaId = env.schemaId;
        this.root = env.root || this;
        this.baseId = (_a = env.baseId) !== null && _a !== void 0 ? _a : (0, resolve_1.normalizeId)(schema === null || schema === void 0 ? void 0 : schema[env.schemaId || "$id"]);
        this.schemaPath = env.schemaPath;
        this.localRefs = env.localRefs;
        this.meta = env.meta;
        this.$async = schema === null || schema === void 0 ? void 0 : schema.$async;
        this.refs = {};
    }
}
compile.SchemaEnv = SchemaEnv;
// let codeSize = 0
// let nodeCount = 0
// Compiles schema in SchemaEnv
function compileSchema(sch) {
    // TODO refactor - remove compilations
    const _sch = getCompilingSchema.call(this, sch);
    if (_sch)
        return _sch;
    const rootId = (0, resolve_1.getFullPath)(this.opts.uriResolver, sch.root.baseId); // TODO if getFullPath removed 1 tests fails
    const { es5, lines } = this.opts.code;
    const { ownProperties } = this.opts;
    const gen = new codegen_1$m.CodeGen(this.scope, { es5, lines, ownProperties });
    let _ValidationError;
    if (sch.$async) {
        _ValidationError = gen.scopeValue("Error", {
            ref: validation_error_1.default,
            code: (0, codegen_1$m._) `require("ajv/dist/runtime/validation_error").default`,
        });
    }
    const validateName = gen.scopeName("validate");
    sch.validateName = validateName;
    const schemaCxt = {
        gen,
        allErrors: this.opts.allErrors,
        data: names_1$2.default.data,
        parentData: names_1$2.default.parentData,
        parentDataProperty: names_1$2.default.parentDataProperty,
        dataNames: [names_1$2.default.data],
        dataPathArr: [codegen_1$m.nil], // TODO can its length be used as dataLevel if nil is removed?
        dataLevel: 0,
        dataTypes: [],
        definedProperties: new Set(),
        topSchemaRef: gen.scopeValue("schema", this.opts.code.source === true
            ? { ref: sch.schema, code: (0, codegen_1$m.stringify)(sch.schema) }
            : { ref: sch.schema }),
        validateName,
        ValidationError: _ValidationError,
        schema: sch.schema,
        schemaEnv: sch,
        rootId,
        baseId: sch.baseId || rootId,
        schemaPath: codegen_1$m.nil,
        errSchemaPath: sch.schemaPath || (this.opts.jtd ? "" : "#"),
        errorPath: (0, codegen_1$m._) `""`,
        opts: this.opts,
        self: this,
    };
    let sourceCode;
    try {
        this._compilations.add(sch);
        (0, validate_1$1.validateFunctionCode)(schemaCxt);
        gen.optimize(this.opts.code.optimize);
        // gen.optimize(1)
        const validateCode = gen.toString();
        sourceCode = `${gen.scopeRefs(names_1$2.default.scope)}return ${validateCode}`;
        // console.log((codeSize += sourceCode.length), (nodeCount += gen.nodeCount))
        if (this.opts.code.process)
            sourceCode = this.opts.code.process(sourceCode, sch);
        // console.log("\n\n\n *** \n", sourceCode)
        const makeValidate = new Function(`${names_1$2.default.self}`, `${names_1$2.default.scope}`, sourceCode);
        const validate = makeValidate(this, this.scope.get());
        this.scope.value(validateName, { ref: validate });
        validate.errors = null;
        validate.schema = sch.schema;
        validate.schemaEnv = sch;
        if (sch.$async)
            validate.$async = true;
        if (this.opts.code.source === true) {
            validate.source = { validateName, validateCode, scopeValues: gen._values };
        }
        if (this.opts.unevaluated) {
            const { props, items } = schemaCxt;
            validate.evaluated = {
                props: props instanceof codegen_1$m.Name ? undefined : props,
                items: items instanceof codegen_1$m.Name ? undefined : items,
                dynamicProps: props instanceof codegen_1$m.Name,
                dynamicItems: items instanceof codegen_1$m.Name,
            };
            if (validate.source)
                validate.source.evaluated = (0, codegen_1$m.stringify)(validate.evaluated);
        }
        sch.validate = validate;
        return sch;
    }
    catch (e) {
        delete sch.validate;
        delete sch.validateName;
        if (sourceCode)
            this.logger.error("Error compiling schema, function code:", sourceCode);
        // console.log("\n\n\n *** \n", sourceCode, this.opts)
        throw e;
    }
    finally {
        this._compilations.delete(sch);
    }
}
compile.compileSchema = compileSchema;
function resolveRef(root, baseId, ref) {
    var _a;
    ref = (0, resolve_1.resolveUrl)(this.opts.uriResolver, baseId, ref);
    const schOrFunc = root.refs[ref];
    if (schOrFunc)
        return schOrFunc;
    let _sch = resolve.call(this, root, ref);
    if (_sch === undefined) {
        const schema = (_a = root.localRefs) === null || _a === void 0 ? void 0 : _a[ref]; // TODO maybe localRefs should hold SchemaEnv
        const { schemaId } = this.opts;
        if (schema)
            _sch = new SchemaEnv({ schema, schemaId, root, baseId });
    }
    if (_sch === undefined)
        return;
    return (root.refs[ref] = inlineOrCompile.call(this, _sch));
}
compile.resolveRef = resolveRef;
function inlineOrCompile(sch) {
    if ((0, resolve_1.inlineRef)(sch.schema, this.opts.inlineRefs))
        return sch.schema;
    return sch.validate ? sch : compileSchema.call(this, sch);
}
// Index of schema compilation in the currently compiled list
function getCompilingSchema(schEnv) {
    for (const sch of this._compilations) {
        if (sameSchemaEnv(sch, schEnv))
            return sch;
    }
}
compile.getCompilingSchema = getCompilingSchema;
function sameSchemaEnv(s1, s2) {
    return s1.schema === s2.schema && s1.root === s2.root && s1.baseId === s2.baseId;
}
// resolve and compile the references ($ref)
// TODO returns AnySchemaObject (if the schema can be inlined) or validation function
function resolve(root, // information about the root schema for the current schema
ref // reference to resolve
) {
    let sch;
    while (typeof (sch = this.refs[ref]) == "string")
        ref = sch;
    return sch || this.schemas[ref] || resolveSchema.call(this, root, ref);
}
// Resolve schema, its root and baseId
function resolveSchema(root, // root object with properties schema, refs TODO below SchemaEnv is assigned to it
ref // reference to resolve
) {
    const p = this.opts.uriResolver.parse(ref);
    const refPath = (0, resolve_1._getFullPath)(this.opts.uriResolver, p);
    let baseId = (0, resolve_1.getFullPath)(this.opts.uriResolver, root.baseId, undefined);
    // TODO `Object.keys(root.schema).length > 0` should not be needed - but removing breaks 2 tests
    if (Object.keys(root.schema).length > 0 && refPath === baseId) {
        return getJsonPointer.call(this, p, root);
    }
    const id = (0, resolve_1.normalizeId)(refPath);
    const schOrRef = this.refs[id] || this.schemas[id];
    if (typeof schOrRef == "string") {
        const sch = resolveSchema.call(this, root, schOrRef);
        if (typeof (sch === null || sch === void 0 ? void 0 : sch.schema) !== "object")
            return;
        return getJsonPointer.call(this, p, sch);
    }
    if (typeof (schOrRef === null || schOrRef === void 0 ? void 0 : schOrRef.schema) !== "object")
        return;
    if (!schOrRef.validate)
        compileSchema.call(this, schOrRef);
    if (id === (0, resolve_1.normalizeId)(ref)) {
        const { schema } = schOrRef;
        const { schemaId } = this.opts;
        const schId = schema[schemaId];
        if (schId)
            baseId = (0, resolve_1.resolveUrl)(this.opts.uriResolver, baseId, schId);
        return new SchemaEnv({ schema, schemaId, root, baseId });
    }
    return getJsonPointer.call(this, p, schOrRef);
}
compile.resolveSchema = resolveSchema;
const PREVENT_SCOPE_CHANGE = new Set([
    "properties",
    "patternProperties",
    "enum",
    "dependencies",
    "definitions",
]);
function getJsonPointer(parsedRef, { baseId, schema, root }) {
    var _a;
    if (((_a = parsedRef.fragment) === null || _a === void 0 ? void 0 : _a[0]) !== "/")
        return;
    for (const part of parsedRef.fragment.slice(1).split("/")) {
        if (typeof schema === "boolean")
            return;
        const partSchema = schema[(0, util_1$k.unescapeFragment)(part)];
        if (partSchema === undefined)
            return;
        schema = partSchema;
        // TODO PREVENT_SCOPE_CHANGE could be defined in keyword def?
        const schId = typeof schema === "object" && schema[this.opts.schemaId];
        if (!PREVENT_SCOPE_CHANGE.has(part) && schId) {
            baseId = (0, resolve_1.resolveUrl)(this.opts.uriResolver, baseId, schId);
        }
    }
    let env;
    if (typeof schema != "boolean" && schema.$ref && !(0, util_1$k.schemaHasRulesButRef)(schema, this.RULES)) {
        const $ref = (0, resolve_1.resolveUrl)(this.opts.uriResolver, baseId, schema.$ref);
        env = resolveSchema.call(this, root, $ref);
    }
    // even though resolution failed we need to return SchemaEnv to throw exception
    // so that compileAsync loads missing schema.
    const { schemaId } = this.opts;
    env = env || new SchemaEnv({ schema, schemaId, root, baseId });
    if (env.schema !== env.root.schema)
        return env;
    return undefined;
}

var $id$1 = "https://raw.githubusercontent.com/ajv-validator/ajv/master/lib/refs/data.json#";
var description = "Meta-schema for $data reference (JSON AnySchema extension proposal)";
var type$1 = "object";
var required$1 = [
	"$data"
];
var properties$2 = {
	$data: {
		type: "string",
		anyOf: [
			{
				format: "relative-json-pointer"
			},
			{
				format: "json-pointer"
			}
		]
	}
};
var additionalProperties$1 = false;
var require$$9 = {
	$id: $id$1,
	description: description,
	type: type$1,
	required: required$1,
	properties: properties$2,
	additionalProperties: additionalProperties$1
};

var uri$1 = {};

var uri_all = {exports: {}};

/** @license URI.js v4.4.1 (c) 2011 Gary Court. License: http://github.com/garycourt/uri-js */

(function (module, exports) {
	(function (global, factory) {
		factory(exports) ;
	}(commonjsGlobal, (function (exports) {
	function merge() {
	    for (var _len = arguments.length, sets = Array(_len), _key = 0; _key < _len; _key++) {
	        sets[_key] = arguments[_key];
	    }

	    if (sets.length > 1) {
	        sets[0] = sets[0].slice(0, -1);
	        var xl = sets.length - 1;
	        for (var x = 1; x < xl; ++x) {
	            sets[x] = sets[x].slice(1, -1);
	        }
	        sets[xl] = sets[xl].slice(1);
	        return sets.join('');
	    } else {
	        return sets[0];
	    }
	}
	function subexp(str) {
	    return "(?:" + str + ")";
	}
	function typeOf(o) {
	    return o === undefined ? "undefined" : o === null ? "null" : Object.prototype.toString.call(o).split(" ").pop().split("]").shift().toLowerCase();
	}
	function toUpperCase(str) {
	    return str.toUpperCase();
	}
	function toArray(obj) {
	    return obj !== undefined && obj !== null ? obj instanceof Array ? obj : typeof obj.length !== "number" || obj.split || obj.setInterval || obj.call ? [obj] : Array.prototype.slice.call(obj) : [];
	}
	function assign(target, source) {
	    var obj = target;
	    if (source) {
	        for (var key in source) {
	            obj[key] = source[key];
	        }
	    }
	    return obj;
	}

	function buildExps(isIRI) {
	    var ALPHA$$ = "[A-Za-z]",
	        DIGIT$$ = "[0-9]",
	        HEXDIG$$ = merge(DIGIT$$, "[A-Fa-f]"),
	        PCT_ENCODED$ = subexp(subexp("%[EFef]" + HEXDIG$$ + "%" + HEXDIG$$ + HEXDIG$$ + "%" + HEXDIG$$ + HEXDIG$$) + "|" + subexp("%[89A-Fa-f]" + HEXDIG$$ + "%" + HEXDIG$$ + HEXDIG$$) + "|" + subexp("%" + HEXDIG$$ + HEXDIG$$)),
	        //expanded
	    GEN_DELIMS$$ = "[\\:\\/\\?\\#\\[\\]\\@]",
	        SUB_DELIMS$$ = "[\\!\\$\\&\\'\\(\\)\\*\\+\\,\\;\\=]",
	        RESERVED$$ = merge(GEN_DELIMS$$, SUB_DELIMS$$),
	        UCSCHAR$$ = isIRI ? "[\\xA0-\\u200D\\u2010-\\u2029\\u202F-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF]" : "[]",
	        //subset, excludes bidi control characters
	    IPRIVATE$$ = isIRI ? "[\\uE000-\\uF8FF]" : "[]",
	        //subset
	    UNRESERVED$$ = merge(ALPHA$$, DIGIT$$, "[\\-\\.\\_\\~]", UCSCHAR$$);
	        subexp(ALPHA$$ + merge(ALPHA$$, DIGIT$$, "[\\+\\-\\.]") + "*");
	        subexp(subexp(PCT_ENCODED$ + "|" + merge(UNRESERVED$$, SUB_DELIMS$$, "[\\:]")) + "*");
	        var DEC_OCTET_RELAXED$ = subexp(subexp("25[0-5]") + "|" + subexp("2[0-4]" + DIGIT$$) + "|" + subexp("1" + DIGIT$$ + DIGIT$$) + "|" + subexp("0?[1-9]" + DIGIT$$) + "|0?0?" + DIGIT$$),
	        //relaxed parsing rules
	    IPV4ADDRESS$ = subexp(DEC_OCTET_RELAXED$ + "\\." + DEC_OCTET_RELAXED$ + "\\." + DEC_OCTET_RELAXED$ + "\\." + DEC_OCTET_RELAXED$),
	        H16$ = subexp(HEXDIG$$ + "{1,4}"),
	        LS32$ = subexp(subexp(H16$ + "\\:" + H16$) + "|" + IPV4ADDRESS$),
	        IPV6ADDRESS1$ = subexp(subexp(H16$ + "\\:") + "{6}" + LS32$),
	        //                           6( h16 ":" ) ls32
	    IPV6ADDRESS2$ = subexp("\\:\\:" + subexp(H16$ + "\\:") + "{5}" + LS32$),
	        //                      "::" 5( h16 ":" ) ls32
	    IPV6ADDRESS3$ = subexp(subexp(H16$) + "?\\:\\:" + subexp(H16$ + "\\:") + "{4}" + LS32$),
	        //[               h16 ] "::" 4( h16 ":" ) ls32
	    IPV6ADDRESS4$ = subexp(subexp(subexp(H16$ + "\\:") + "{0,1}" + H16$) + "?\\:\\:" + subexp(H16$ + "\\:") + "{3}" + LS32$),
	        //[ *1( h16 ":" ) h16 ] "::" 3( h16 ":" ) ls32
	    IPV6ADDRESS5$ = subexp(subexp(subexp(H16$ + "\\:") + "{0,2}" + H16$) + "?\\:\\:" + subexp(H16$ + "\\:") + "{2}" + LS32$),
	        //[ *2( h16 ":" ) h16 ] "::" 2( h16 ":" ) ls32
	    IPV6ADDRESS6$ = subexp(subexp(subexp(H16$ + "\\:") + "{0,3}" + H16$) + "?\\:\\:" + H16$ + "\\:" + LS32$),
	        //[ *3( h16 ":" ) h16 ] "::"    h16 ":"   ls32
	    IPV6ADDRESS7$ = subexp(subexp(subexp(H16$ + "\\:") + "{0,4}" + H16$) + "?\\:\\:" + LS32$),
	        //[ *4( h16 ":" ) h16 ] "::"              ls32
	    IPV6ADDRESS8$ = subexp(subexp(subexp(H16$ + "\\:") + "{0,5}" + H16$) + "?\\:\\:" + H16$),
	        //[ *5( h16 ":" ) h16 ] "::"              h16
	    IPV6ADDRESS9$ = subexp(subexp(subexp(H16$ + "\\:") + "{0,6}" + H16$) + "?\\:\\:"),
	        //[ *6( h16 ":" ) h16 ] "::"
	    IPV6ADDRESS$ = subexp([IPV6ADDRESS1$, IPV6ADDRESS2$, IPV6ADDRESS3$, IPV6ADDRESS4$, IPV6ADDRESS5$, IPV6ADDRESS6$, IPV6ADDRESS7$, IPV6ADDRESS8$, IPV6ADDRESS9$].join("|")),
	        ZONEID$ = subexp(subexp(UNRESERVED$$ + "|" + PCT_ENCODED$) + "+");
	        //RFC 6874, with relaxed parsing rules
	    subexp("[vV]" + HEXDIG$$ + "+\\." + merge(UNRESERVED$$, SUB_DELIMS$$, "[\\:]") + "+");
	        //RFC 6874
	    subexp(subexp(PCT_ENCODED$ + "|" + merge(UNRESERVED$$, SUB_DELIMS$$)) + "*");
	        var PCHAR$ = subexp(PCT_ENCODED$ + "|" + merge(UNRESERVED$$, SUB_DELIMS$$, "[\\:\\@]"));
	        subexp(subexp(PCT_ENCODED$ + "|" + merge(UNRESERVED$$, SUB_DELIMS$$, "[\\@]")) + "+");
	        subexp(subexp(PCHAR$ + "|" + merge("[\\/\\?]", IPRIVATE$$)) + "*");
	    return {
	        NOT_SCHEME: new RegExp(merge("[^]", ALPHA$$, DIGIT$$, "[\\+\\-\\.]"), "g"),
	        NOT_USERINFO: new RegExp(merge("[^\\%\\:]", UNRESERVED$$, SUB_DELIMS$$), "g"),
	        NOT_HOST: new RegExp(merge("[^\\%\\[\\]\\:]", UNRESERVED$$, SUB_DELIMS$$), "g"),
	        NOT_PATH: new RegExp(merge("[^\\%\\/\\:\\@]", UNRESERVED$$, SUB_DELIMS$$), "g"),
	        NOT_PATH_NOSCHEME: new RegExp(merge("[^\\%\\/\\@]", UNRESERVED$$, SUB_DELIMS$$), "g"),
	        NOT_QUERY: new RegExp(merge("[^\\%]", UNRESERVED$$, SUB_DELIMS$$, "[\\:\\@\\/\\?]", IPRIVATE$$), "g"),
	        NOT_FRAGMENT: new RegExp(merge("[^\\%]", UNRESERVED$$, SUB_DELIMS$$, "[\\:\\@\\/\\?]"), "g"),
	        ESCAPE: new RegExp(merge("[^]", UNRESERVED$$, SUB_DELIMS$$), "g"),
	        UNRESERVED: new RegExp(UNRESERVED$$, "g"),
	        OTHER_CHARS: new RegExp(merge("[^\\%]", UNRESERVED$$, RESERVED$$), "g"),
	        PCT_ENCODED: new RegExp(PCT_ENCODED$, "g"),
	        IPV4ADDRESS: new RegExp("^(" + IPV4ADDRESS$ + ")$"),
	        IPV6ADDRESS: new RegExp("^\\[?(" + IPV6ADDRESS$ + ")" + subexp(subexp("\\%25|\\%(?!" + HEXDIG$$ + "{2})") + "(" + ZONEID$ + ")") + "?\\]?$") //RFC 6874, with relaxed parsing rules
	    };
	}
	var URI_PROTOCOL = buildExps(false);

	var IRI_PROTOCOL = buildExps(true);

	var slicedToArray = function () {
	  function sliceIterator(arr, i) {
	    var _arr = [];
	    var _n = true;
	    var _d = false;
	    var _e = undefined;

	    try {
	      for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) {
	        _arr.push(_s.value);

	        if (i && _arr.length === i) break;
	      }
	    } catch (err) {
	      _d = true;
	      _e = err;
	    } finally {
	      try {
	        if (!_n && _i["return"]) _i["return"]();
	      } finally {
	        if (_d) throw _e;
	      }
	    }

	    return _arr;
	  }

	  return function (arr, i) {
	    if (Array.isArray(arr)) {
	      return arr;
	    } else if (Symbol.iterator in Object(arr)) {
	      return sliceIterator(arr, i);
	    } else {
	      throw new TypeError("Invalid attempt to destructure non-iterable instance");
	    }
	  };
	}();













	var toConsumableArray = function (arr) {
	  if (Array.isArray(arr)) {
	    for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) arr2[i] = arr[i];

	    return arr2;
	  } else {
	    return Array.from(arr);
	  }
	};

	/** Highest positive signed 32-bit float value */

	var maxInt = 2147483647; // aka. 0x7FFFFFFF or 2^31-1

	/** Bootstring parameters */
	var base = 36;
	var tMin = 1;
	var tMax = 26;
	var skew = 38;
	var damp = 700;
	var initialBias = 72;
	var initialN = 128; // 0x80
	var delimiter = '-'; // '\x2D'

	/** Regular expressions */
	var regexPunycode = /^xn--/;
	var regexNonASCII = /[^\0-\x7E]/; // non-ASCII chars
	var regexSeparators = /[\x2E\u3002\uFF0E\uFF61]/g; // RFC 3490 separators

	/** Error messages */
	var errors = {
		'overflow': 'Overflow: input needs wider integers to process',
		'not-basic': 'Illegal input >= 0x80 (not a basic code point)',
		'invalid-input': 'Invalid input'
	};

	/** Convenience shortcuts */
	var baseMinusTMin = base - tMin;
	var floor = Math.floor;
	var stringFromCharCode = String.fromCharCode;

	/*--------------------------------------------------------------------------*/

	/**
	 * A generic error utility function.
	 * @private
	 * @param {String} type The error type.
	 * @returns {Error} Throws a `RangeError` with the applicable error message.
	 */
	function error$1(type) {
		throw new RangeError(errors[type]);
	}

	/**
	 * A generic `Array#map` utility function.
	 * @private
	 * @param {Array} array The array to iterate over.
	 * @param {Function} callback The function that gets called for every array
	 * item.
	 * @returns {Array} A new array of values returned by the callback function.
	 */
	function map(array, fn) {
		var result = [];
		var length = array.length;
		while (length--) {
			result[length] = fn(array[length]);
		}
		return result;
	}

	/**
	 * A simple `Array#map`-like wrapper to work with domain name strings or email
	 * addresses.
	 * @private
	 * @param {String} domain The domain name or email address.
	 * @param {Function} callback The function that gets called for every
	 * character.
	 * @returns {Array} A new string of characters returned by the callback
	 * function.
	 */
	function mapDomain(string, fn) {
		var parts = string.split('@');
		var result = '';
		if (parts.length > 1) {
			// In email addresses, only the domain name should be punycoded. Leave
			// the local part (i.e. everything up to `@`) intact.
			result = parts[0] + '@';
			string = parts[1];
		}
		// Avoid `split(regex)` for IE8 compatibility. See #17.
		string = string.replace(regexSeparators, '\x2E');
		var labels = string.split('.');
		var encoded = map(labels, fn).join('.');
		return result + encoded;
	}

	/**
	 * Creates an array containing the numeric code points of each Unicode
	 * character in the string. While JavaScript uses UCS-2 internally,
	 * this function will convert a pair of surrogate halves (each of which
	 * UCS-2 exposes as separate characters) into a single code point,
	 * matching UTF-16.
	 * @see `punycode.ucs2.encode`
	 * @see <https://mathiasbynens.be/notes/javascript-encoding>
	 * @memberOf punycode.ucs2
	 * @name decode
	 * @param {String} string The Unicode input string (UCS-2).
	 * @returns {Array} The new array of code points.
	 */
	function ucs2decode(string) {
		var output = [];
		var counter = 0;
		var length = string.length;
		while (counter < length) {
			var value = string.charCodeAt(counter++);
			if (value >= 0xD800 && value <= 0xDBFF && counter < length) {
				// It's a high surrogate, and there is a next character.
				var extra = string.charCodeAt(counter++);
				if ((extra & 0xFC00) == 0xDC00) {
					// Low surrogate.
					output.push(((value & 0x3FF) << 10) + (extra & 0x3FF) + 0x10000);
				} else {
					// It's an unmatched surrogate; only append this code unit, in case the
					// next code unit is the high surrogate of a surrogate pair.
					output.push(value);
					counter--;
				}
			} else {
				output.push(value);
			}
		}
		return output;
	}

	/**
	 * Creates a string based on an array of numeric code points.
	 * @see `punycode.ucs2.decode`
	 * @memberOf punycode.ucs2
	 * @name encode
	 * @param {Array} codePoints The array of numeric code points.
	 * @returns {String} The new Unicode string (UCS-2).
	 */
	var ucs2encode = function ucs2encode(array) {
		return String.fromCodePoint.apply(String, toConsumableArray(array));
	};

	/**
	 * Converts a basic code point into a digit/integer.
	 * @see `digitToBasic()`
	 * @private
	 * @param {Number} codePoint The basic numeric code point value.
	 * @returns {Number} The numeric value of a basic code point (for use in
	 * representing integers) in the range `0` to `base - 1`, or `base` if
	 * the code point does not represent a value.
	 */
	var basicToDigit = function basicToDigit(codePoint) {
		if (codePoint - 0x30 < 0x0A) {
			return codePoint - 0x16;
		}
		if (codePoint - 0x41 < 0x1A) {
			return codePoint - 0x41;
		}
		if (codePoint - 0x61 < 0x1A) {
			return codePoint - 0x61;
		}
		return base;
	};

	/**
	 * Converts a digit/integer into a basic code point.
	 * @see `basicToDigit()`
	 * @private
	 * @param {Number} digit The numeric value of a basic code point.
	 * @returns {Number} The basic code point whose value (when used for
	 * representing integers) is `digit`, which needs to be in the range
	 * `0` to `base - 1`. If `flag` is non-zero, the uppercase form is
	 * used; else, the lowercase form is used. The behavior is undefined
	 * if `flag` is non-zero and `digit` has no uppercase form.
	 */
	var digitToBasic = function digitToBasic(digit, flag) {
		//  0..25 map to ASCII a..z or A..Z
		// 26..35 map to ASCII 0..9
		return digit + 22 + 75 * (digit < 26) - ((flag != 0) << 5);
	};

	/**
	 * Bias adaptation function as per section 3.4 of RFC 3492.
	 * https://tools.ietf.org/html/rfc3492#section-3.4
	 * @private
	 */
	var adapt = function adapt(delta, numPoints, firstTime) {
		var k = 0;
		delta = firstTime ? floor(delta / damp) : delta >> 1;
		delta += floor(delta / numPoints);
		for (; /* no initialization */delta > baseMinusTMin * tMax >> 1; k += base) {
			delta = floor(delta / baseMinusTMin);
		}
		return floor(k + (baseMinusTMin + 1) * delta / (delta + skew));
	};

	/**
	 * Converts a Punycode string of ASCII-only symbols to a string of Unicode
	 * symbols.
	 * @memberOf punycode
	 * @param {String} input The Punycode string of ASCII-only symbols.
	 * @returns {String} The resulting string of Unicode symbols.
	 */
	var decode = function decode(input) {
		// Don't use UCS-2.
		var output = [];
		var inputLength = input.length;
		var i = 0;
		var n = initialN;
		var bias = initialBias;

		// Handle the basic code points: let `basic` be the number of input code
		// points before the last delimiter, or `0` if there is none, then copy
		// the first basic code points to the output.

		var basic = input.lastIndexOf(delimiter);
		if (basic < 0) {
			basic = 0;
		}

		for (var j = 0; j < basic; ++j) {
			// if it's not a basic code point
			if (input.charCodeAt(j) >= 0x80) {
				error$1('not-basic');
			}
			output.push(input.charCodeAt(j));
		}

		// Main decoding loop: start just after the last delimiter if any basic code
		// points were copied; start at the beginning otherwise.

		for (var index = basic > 0 ? basic + 1 : 0; index < inputLength;) /* no final expression */{

			// `index` is the index of the next character to be consumed.
			// Decode a generalized variable-length integer into `delta`,
			// which gets added to `i`. The overflow checking is easier
			// if we increase `i` as we go, then subtract off its starting
			// value at the end to obtain `delta`.
			var oldi = i;
			for (var w = 1, k = base;; /* no condition */k += base) {

				if (index >= inputLength) {
					error$1('invalid-input');
				}

				var digit = basicToDigit(input.charCodeAt(index++));

				if (digit >= base || digit > floor((maxInt - i) / w)) {
					error$1('overflow');
				}

				i += digit * w;
				var t = k <= bias ? tMin : k >= bias + tMax ? tMax : k - bias;

				if (digit < t) {
					break;
				}

				var baseMinusT = base - t;
				if (w > floor(maxInt / baseMinusT)) {
					error$1('overflow');
				}

				w *= baseMinusT;
			}

			var out = output.length + 1;
			bias = adapt(i - oldi, out, oldi == 0);

			// `i` was supposed to wrap around from `out` to `0`,
			// incrementing `n` each time, so we'll fix that now:
			if (floor(i / out) > maxInt - n) {
				error$1('overflow');
			}

			n += floor(i / out);
			i %= out;

			// Insert `n` at position `i` of the output.
			output.splice(i++, 0, n);
		}

		return String.fromCodePoint.apply(String, output);
	};

	/**
	 * Converts a string of Unicode symbols (e.g. a domain name label) to a
	 * Punycode string of ASCII-only symbols.
	 * @memberOf punycode
	 * @param {String} input The string of Unicode symbols.
	 * @returns {String} The resulting Punycode string of ASCII-only symbols.
	 */
	var encode = function encode(input) {
		var output = [];

		// Convert the input in UCS-2 to an array of Unicode code points.
		input = ucs2decode(input);

		// Cache the length.
		var inputLength = input.length;

		// Initialize the state.
		var n = initialN;
		var delta = 0;
		var bias = initialBias;

		// Handle the basic code points.
		var _iteratorNormalCompletion = true;
		var _didIteratorError = false;
		var _iteratorError = undefined;

		try {
			for (var _iterator = input[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) {
				var _currentValue2 = _step.value;

				if (_currentValue2 < 0x80) {
					output.push(stringFromCharCode(_currentValue2));
				}
			}
		} catch (err) {
			_didIteratorError = true;
			_iteratorError = err;
		} finally {
			try {
				if (!_iteratorNormalCompletion && _iterator.return) {
					_iterator.return();
				}
			} finally {
				if (_didIteratorError) {
					throw _iteratorError;
				}
			}
		}

		var basicLength = output.length;
		var handledCPCount = basicLength;

		// `handledCPCount` is the number of code points that have been handled;
		// `basicLength` is the number of basic code points.

		// Finish the basic string with a delimiter unless it's empty.
		if (basicLength) {
			output.push(delimiter);
		}

		// Main encoding loop:
		while (handledCPCount < inputLength) {

			// All non-basic code points < n have been handled already. Find the next
			// larger one:
			var m = maxInt;
			var _iteratorNormalCompletion2 = true;
			var _didIteratorError2 = false;
			var _iteratorError2 = undefined;

			try {
				for (var _iterator2 = input[Symbol.iterator](), _step2; !(_iteratorNormalCompletion2 = (_step2 = _iterator2.next()).done); _iteratorNormalCompletion2 = true) {
					var currentValue = _step2.value;

					if (currentValue >= n && currentValue < m) {
						m = currentValue;
					}
				}

				// Increase `delta` enough to advance the decoder's <n,i> state to <m,0>,
				// but guard against overflow.
			} catch (err) {
				_didIteratorError2 = true;
				_iteratorError2 = err;
			} finally {
				try {
					if (!_iteratorNormalCompletion2 && _iterator2.return) {
						_iterator2.return();
					}
				} finally {
					if (_didIteratorError2) {
						throw _iteratorError2;
					}
				}
			}

			var handledCPCountPlusOne = handledCPCount + 1;
			if (m - n > floor((maxInt - delta) / handledCPCountPlusOne)) {
				error$1('overflow');
			}

			delta += (m - n) * handledCPCountPlusOne;
			n = m;

			var _iteratorNormalCompletion3 = true;
			var _didIteratorError3 = false;
			var _iteratorError3 = undefined;

			try {
				for (var _iterator3 = input[Symbol.iterator](), _step3; !(_iteratorNormalCompletion3 = (_step3 = _iterator3.next()).done); _iteratorNormalCompletion3 = true) {
					var _currentValue = _step3.value;

					if (_currentValue < n && ++delta > maxInt) {
						error$1('overflow');
					}
					if (_currentValue == n) {
						// Represent delta as a generalized variable-length integer.
						var q = delta;
						for (var k = base;; /* no condition */k += base) {
							var t = k <= bias ? tMin : k >= bias + tMax ? tMax : k - bias;
							if (q < t) {
								break;
							}
							var qMinusT = q - t;
							var baseMinusT = base - t;
							output.push(stringFromCharCode(digitToBasic(t + qMinusT % baseMinusT, 0)));
							q = floor(qMinusT / baseMinusT);
						}

						output.push(stringFromCharCode(digitToBasic(q, 0)));
						bias = adapt(delta, handledCPCountPlusOne, handledCPCount == basicLength);
						delta = 0;
						++handledCPCount;
					}
				}
			} catch (err) {
				_didIteratorError3 = true;
				_iteratorError3 = err;
			} finally {
				try {
					if (!_iteratorNormalCompletion3 && _iterator3.return) {
						_iterator3.return();
					}
				} finally {
					if (_didIteratorError3) {
						throw _iteratorError3;
					}
				}
			}

			++delta;
			++n;
		}
		return output.join('');
	};

	/**
	 * Converts a Punycode string representing a domain name or an email address
	 * to Unicode. Only the Punycoded parts of the input will be converted, i.e.
	 * it doesn't matter if you call it on a string that has already been
	 * converted to Unicode.
	 * @memberOf punycode
	 * @param {String} input The Punycoded domain name or email address to
	 * convert to Unicode.
	 * @returns {String} The Unicode representation of the given Punycode
	 * string.
	 */
	var toUnicode = function toUnicode(input) {
		return mapDomain(input, function (string) {
			return regexPunycode.test(string) ? decode(string.slice(4).toLowerCase()) : string;
		});
	};

	/**
	 * Converts a Unicode string representing a domain name or an email address to
	 * Punycode. Only the non-ASCII parts of the domain name will be converted,
	 * i.e. it doesn't matter if you call it with a domain that's already in
	 * ASCII.
	 * @memberOf punycode
	 * @param {String} input The domain name or email address to convert, as a
	 * Unicode string.
	 * @returns {String} The Punycode representation of the given domain name or
	 * email address.
	 */
	var toASCII = function toASCII(input) {
		return mapDomain(input, function (string) {
			return regexNonASCII.test(string) ? 'xn--' + encode(string) : string;
		});
	};

	/*--------------------------------------------------------------------------*/

	/** Define the public API */
	var punycode = {
		/**
	  * A string representing the current Punycode.js version number.
	  * @memberOf punycode
	  * @type String
	  */
		'version': '2.1.0',
		/**
	  * An object of methods to convert from JavaScript's internal character
	  * representation (UCS-2) to Unicode code points, and back.
	  * @see <https://mathiasbynens.be/notes/javascript-encoding>
	  * @memberOf punycode
	  * @type Object
	  */
		'ucs2': {
			'decode': ucs2decode,
			'encode': ucs2encode
		},
		'decode': decode,
		'encode': encode,
		'toASCII': toASCII,
		'toUnicode': toUnicode
	};

	/**
	 * URI.js
	 *
	 * @fileoverview An RFC 3986 compliant, scheme extendable URI parsing/validating/resolving library for JavaScript.
	 * @author <a href="mailto:gary.court@gmail.com">Gary Court</a>
	 * @see http://github.com/garycourt/uri-js
	 */
	/**
	 * Copyright 2011 Gary Court. All rights reserved.
	 *
	 * Redistribution and use in source and binary forms, with or without modification, are
	 * permitted provided that the following conditions are met:
	 *
	 *    1. Redistributions of source code must retain the above copyright notice, this list of
	 *       conditions and the following disclaimer.
	 *
	 *    2. Redistributions in binary form must reproduce the above copyright notice, this list
	 *       of conditions and the following disclaimer in the documentation and/or other materials
	 *       provided with the distribution.
	 *
	 * THIS SOFTWARE IS PROVIDED BY GARY COURT ``AS IS'' AND ANY EXPRESS OR IMPLIED
	 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
	 * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GARY COURT OR
	 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
	 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
	 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
	 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
	 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
	 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
	 *
	 * The views and conclusions contained in the software and documentation are those of the
	 * authors and should not be interpreted as representing official policies, either expressed
	 * or implied, of Gary Court.
	 */
	var SCHEMES = {};
	function pctEncChar(chr) {
	    var c = chr.charCodeAt(0);
	    var e = void 0;
	    if (c < 16) e = "%0" + c.toString(16).toUpperCase();else if (c < 128) e = "%" + c.toString(16).toUpperCase();else if (c < 2048) e = "%" + (c >> 6 | 192).toString(16).toUpperCase() + "%" + (c & 63 | 128).toString(16).toUpperCase();else e = "%" + (c >> 12 | 224).toString(16).toUpperCase() + "%" + (c >> 6 & 63 | 128).toString(16).toUpperCase() + "%" + (c & 63 | 128).toString(16).toUpperCase();
	    return e;
	}
	function pctDecChars(str) {
	    var newStr = "";
	    var i = 0;
	    var il = str.length;
	    while (i < il) {
	        var c = parseInt(str.substr(i + 1, 2), 16);
	        if (c < 128) {
	            newStr += String.fromCharCode(c);
	            i += 3;
	        } else if (c >= 194 && c < 224) {
	            if (il - i >= 6) {
	                var c2 = parseInt(str.substr(i + 4, 2), 16);
	                newStr += String.fromCharCode((c & 31) << 6 | c2 & 63);
	            } else {
	                newStr += str.substr(i, 6);
	            }
	            i += 6;
	        } else if (c >= 224) {
	            if (il - i >= 9) {
	                var _c = parseInt(str.substr(i + 4, 2), 16);
	                var c3 = parseInt(str.substr(i + 7, 2), 16);
	                newStr += String.fromCharCode((c & 15) << 12 | (_c & 63) << 6 | c3 & 63);
	            } else {
	                newStr += str.substr(i, 9);
	            }
	            i += 9;
	        } else {
	            newStr += str.substr(i, 3);
	            i += 3;
	        }
	    }
	    return newStr;
	}
	function _normalizeComponentEncoding(components, protocol) {
	    function decodeUnreserved(str) {
	        var decStr = pctDecChars(str);
	        return !decStr.match(protocol.UNRESERVED) ? str : decStr;
	    }
	    if (components.scheme) components.scheme = String(components.scheme).replace(protocol.PCT_ENCODED, decodeUnreserved).toLowerCase().replace(protocol.NOT_SCHEME, "");
	    if (components.userinfo !== undefined) components.userinfo = String(components.userinfo).replace(protocol.PCT_ENCODED, decodeUnreserved).replace(protocol.NOT_USERINFO, pctEncChar).replace(protocol.PCT_ENCODED, toUpperCase);
	    if (components.host !== undefined) components.host = String(components.host).replace(protocol.PCT_ENCODED, decodeUnreserved).toLowerCase().replace(protocol.NOT_HOST, pctEncChar).replace(protocol.PCT_ENCODED, toUpperCase);
	    if (components.path !== undefined) components.path = String(components.path).replace(protocol.PCT_ENCODED, decodeUnreserved).replace(components.scheme ? protocol.NOT_PATH : protocol.NOT_PATH_NOSCHEME, pctEncChar).replace(protocol.PCT_ENCODED, toUpperCase);
	    if (components.query !== undefined) components.query = String(components.query).replace(protocol.PCT_ENCODED, decodeUnreserved).replace(protocol.NOT_QUERY, pctEncChar).replace(protocol.PCT_ENCODED, toUpperCase);
	    if (components.fragment !== undefined) components.fragment = String(components.fragment).replace(protocol.PCT_ENCODED, decodeUnreserved).replace(protocol.NOT_FRAGMENT, pctEncChar).replace(protocol.PCT_ENCODED, toUpperCase);
	    return components;
	}

	function _stripLeadingZeros(str) {
	    return str.replace(/^0*(.*)/, "$1") || "0";
	}
	function _normalizeIPv4(host, protocol) {
	    var matches = host.match(protocol.IPV4ADDRESS) || [];

	    var _matches = slicedToArray(matches, 2),
	        address = _matches[1];

	    if (address) {
	        return address.split(".").map(_stripLeadingZeros).join(".");
	    } else {
	        return host;
	    }
	}
	function _normalizeIPv6(host, protocol) {
	    var matches = host.match(protocol.IPV6ADDRESS) || [];

	    var _matches2 = slicedToArray(matches, 3),
	        address = _matches2[1],
	        zone = _matches2[2];

	    if (address) {
	        var _address$toLowerCase$ = address.toLowerCase().split('::').reverse(),
	            _address$toLowerCase$2 = slicedToArray(_address$toLowerCase$, 2),
	            last = _address$toLowerCase$2[0],
	            first = _address$toLowerCase$2[1];

	        var firstFields = first ? first.split(":").map(_stripLeadingZeros) : [];
	        var lastFields = last.split(":").map(_stripLeadingZeros);
	        var isLastFieldIPv4Address = protocol.IPV4ADDRESS.test(lastFields[lastFields.length - 1]);
	        var fieldCount = isLastFieldIPv4Address ? 7 : 8;
	        var lastFieldsStart = lastFields.length - fieldCount;
	        var fields = Array(fieldCount);
	        for (var x = 0; x < fieldCount; ++x) {
	            fields[x] = firstFields[x] || lastFields[lastFieldsStart + x] || '';
	        }
	        if (isLastFieldIPv4Address) {
	            fields[fieldCount - 1] = _normalizeIPv4(fields[fieldCount - 1], protocol);
	        }
	        var allZeroFields = fields.reduce(function (acc, field, index) {
	            if (!field || field === "0") {
	                var lastLongest = acc[acc.length - 1];
	                if (lastLongest && lastLongest.index + lastLongest.length === index) {
	                    lastLongest.length++;
	                } else {
	                    acc.push({ index: index, length: 1 });
	                }
	            }
	            return acc;
	        }, []);
	        var longestZeroFields = allZeroFields.sort(function (a, b) {
	            return b.length - a.length;
	        })[0];
	        var newHost = void 0;
	        if (longestZeroFields && longestZeroFields.length > 1) {
	            var newFirst = fields.slice(0, longestZeroFields.index);
	            var newLast = fields.slice(longestZeroFields.index + longestZeroFields.length);
	            newHost = newFirst.join(":") + "::" + newLast.join(":");
	        } else {
	            newHost = fields.join(":");
	        }
	        if (zone) {
	            newHost += "%" + zone;
	        }
	        return newHost;
	    } else {
	        return host;
	    }
	}
	var URI_PARSE = /^(?:([^:\/?#]+):)?(?:\/\/((?:([^\/?#@]*)@)?(\[[^\/?#\]]+\]|[^\/?#:]*)(?:\:(\d*))?))?([^?#]*)(?:\?([^#]*))?(?:#((?:.|\n|\r)*))?/i;
	var NO_MATCH_IS_UNDEFINED = "".match(/(){0}/)[1] === undefined;
	function parse(uriString) {
	    var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};

	    var components = {};
	    var protocol = options.iri !== false ? IRI_PROTOCOL : URI_PROTOCOL;
	    if (options.reference === "suffix") uriString = (options.scheme ? options.scheme + ":" : "") + "//" + uriString;
	    var matches = uriString.match(URI_PARSE);
	    if (matches) {
	        if (NO_MATCH_IS_UNDEFINED) {
	            //store each component
	            components.scheme = matches[1];
	            components.userinfo = matches[3];
	            components.host = matches[4];
	            components.port = parseInt(matches[5], 10);
	            components.path = matches[6] || "";
	            components.query = matches[7];
	            components.fragment = matches[8];
	            //fix port number
	            if (isNaN(components.port)) {
	                components.port = matches[5];
	            }
	        } else {
	            //IE FIX for improper RegExp matching
	            //store each component
	            components.scheme = matches[1] || undefined;
	            components.userinfo = uriString.indexOf("@") !== -1 ? matches[3] : undefined;
	            components.host = uriString.indexOf("//") !== -1 ? matches[4] : undefined;
	            components.port = parseInt(matches[5], 10);
	            components.path = matches[6] || "";
	            components.query = uriString.indexOf("?") !== -1 ? matches[7] : undefined;
	            components.fragment = uriString.indexOf("#") !== -1 ? matches[8] : undefined;
	            //fix port number
	            if (isNaN(components.port)) {
	                components.port = uriString.match(/\/\/(?:.|\n)*\:(?:\/|\?|\#|$)/) ? matches[4] : undefined;
	            }
	        }
	        if (components.host) {
	            //normalize IP hosts
	            components.host = _normalizeIPv6(_normalizeIPv4(components.host, protocol), protocol);
	        }
	        //determine reference type
	        if (components.scheme === undefined && components.userinfo === undefined && components.host === undefined && components.port === undefined && !components.path && components.query === undefined) {
	            components.reference = "same-document";
	        } else if (components.scheme === undefined) {
	            components.reference = "relative";
	        } else if (components.fragment === undefined) {
	            components.reference = "absolute";
	        } else {
	            components.reference = "uri";
	        }
	        //check for reference errors
	        if (options.reference && options.reference !== "suffix" && options.reference !== components.reference) {
	            components.error = components.error || "URI is not a " + options.reference + " reference.";
	        }
	        //find scheme handler
	        var schemeHandler = SCHEMES[(options.scheme || components.scheme || "").toLowerCase()];
	        //check if scheme can't handle IRIs
	        if (!options.unicodeSupport && (!schemeHandler || !schemeHandler.unicodeSupport)) {
	            //if host component is a domain name
	            if (components.host && (options.domainHost || schemeHandler && schemeHandler.domainHost)) {
	                //convert Unicode IDN -> ASCII IDN
	                try {
	                    components.host = punycode.toASCII(components.host.replace(protocol.PCT_ENCODED, pctDecChars).toLowerCase());
	                } catch (e) {
	                    components.error = components.error || "Host's domain name can not be converted to ASCII via punycode: " + e;
	                }
	            }
	            //convert IRI -> URI
	            _normalizeComponentEncoding(components, URI_PROTOCOL);
	        } else {
	            //normalize encodings
	            _normalizeComponentEncoding(components, protocol);
	        }
	        //perform scheme specific parsing
	        if (schemeHandler && schemeHandler.parse) {
	            schemeHandler.parse(components, options);
	        }
	    } else {
	        components.error = components.error || "URI can not be parsed.";
	    }
	    return components;
	}

	function _recomposeAuthority(components, options) {
	    var protocol = options.iri !== false ? IRI_PROTOCOL : URI_PROTOCOL;
	    var uriTokens = [];
	    if (components.userinfo !== undefined) {
	        uriTokens.push(components.userinfo);
	        uriTokens.push("@");
	    }
	    if (components.host !== undefined) {
	        //normalize IP hosts, add brackets and escape zone separator for IPv6
	        uriTokens.push(_normalizeIPv6(_normalizeIPv4(String(components.host), protocol), protocol).replace(protocol.IPV6ADDRESS, function (_, $1, $2) {
	            return "[" + $1 + ($2 ? "%25" + $2 : "") + "]";
	        }));
	    }
	    if (typeof components.port === "number" || typeof components.port === "string") {
	        uriTokens.push(":");
	        uriTokens.push(String(components.port));
	    }
	    return uriTokens.length ? uriTokens.join("") : undefined;
	}

	var RDS1 = /^\.\.?\//;
	var RDS2 = /^\/\.(\/|$)/;
	var RDS3 = /^\/\.\.(\/|$)/;
	var RDS5 = /^\/?(?:.|\n)*?(?=\/|$)/;
	function removeDotSegments(input) {
	    var output = [];
	    while (input.length) {
	        if (input.match(RDS1)) {
	            input = input.replace(RDS1, "");
	        } else if (input.match(RDS2)) {
	            input = input.replace(RDS2, "/");
	        } else if (input.match(RDS3)) {
	            input = input.replace(RDS3, "/");
	            output.pop();
	        } else if (input === "." || input === "..") {
	            input = "";
	        } else {
	            var im = input.match(RDS5);
	            if (im) {
	                var s = im[0];
	                input = input.slice(s.length);
	                output.push(s);
	            } else {
	                throw new Error("Unexpected dot segment condition");
	            }
	        }
	    }
	    return output.join("");
	}

	function serialize(components) {
	    var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};

	    var protocol = options.iri ? IRI_PROTOCOL : URI_PROTOCOL;
	    var uriTokens = [];
	    //find scheme handler
	    var schemeHandler = SCHEMES[(options.scheme || components.scheme || "").toLowerCase()];
	    //perform scheme specific serialization
	    if (schemeHandler && schemeHandler.serialize) schemeHandler.serialize(components, options);
	    if (components.host) {
	        //if host component is an IPv6 address
	        if (protocol.IPV6ADDRESS.test(components.host)) ;
	        //TODO: normalize IPv6 address as per RFC 5952

	        //if host component is a domain name
	        else if (options.domainHost || schemeHandler && schemeHandler.domainHost) {
	                //convert IDN via punycode
	                try {
	                    components.host = !options.iri ? punycode.toASCII(components.host.replace(protocol.PCT_ENCODED, pctDecChars).toLowerCase()) : punycode.toUnicode(components.host);
	                } catch (e) {
	                    components.error = components.error || "Host's domain name can not be converted to " + (!options.iri ? "ASCII" : "Unicode") + " via punycode: " + e;
	                }
	            }
	    }
	    //normalize encoding
	    _normalizeComponentEncoding(components, protocol);
	    if (options.reference !== "suffix" && components.scheme) {
	        uriTokens.push(components.scheme);
	        uriTokens.push(":");
	    }
	    var authority = _recomposeAuthority(components, options);
	    if (authority !== undefined) {
	        if (options.reference !== "suffix") {
	            uriTokens.push("//");
	        }
	        uriTokens.push(authority);
	        if (components.path && components.path.charAt(0) !== "/") {
	            uriTokens.push("/");
	        }
	    }
	    if (components.path !== undefined) {
	        var s = components.path;
	        if (!options.absolutePath && (!schemeHandler || !schemeHandler.absolutePath)) {
	            s = removeDotSegments(s);
	        }
	        if (authority === undefined) {
	            s = s.replace(/^\/\//, "/%2F"); //don't allow the path to start with "//"
	        }
	        uriTokens.push(s);
	    }
	    if (components.query !== undefined) {
	        uriTokens.push("?");
	        uriTokens.push(components.query);
	    }
	    if (components.fragment !== undefined) {
	        uriTokens.push("#");
	        uriTokens.push(components.fragment);
	    }
	    return uriTokens.join(""); //merge tokens into a string
	}

	function resolveComponents(base, relative) {
	    var options = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
	    var skipNormalization = arguments[3];

	    var target = {};
	    if (!skipNormalization) {
	        base = parse(serialize(base, options), options); //normalize base components
	        relative = parse(serialize(relative, options), options); //normalize relative components
	    }
	    options = options || {};
	    if (!options.tolerant && relative.scheme) {
	        target.scheme = relative.scheme;
	        //target.authority = relative.authority;
	        target.userinfo = relative.userinfo;
	        target.host = relative.host;
	        target.port = relative.port;
	        target.path = removeDotSegments(relative.path || "");
	        target.query = relative.query;
	    } else {
	        if (relative.userinfo !== undefined || relative.host !== undefined || relative.port !== undefined) {
	            //target.authority = relative.authority;
	            target.userinfo = relative.userinfo;
	            target.host = relative.host;
	            target.port = relative.port;
	            target.path = removeDotSegments(relative.path || "");
	            target.query = relative.query;
	        } else {
	            if (!relative.path) {
	                target.path = base.path;
	                if (relative.query !== undefined) {
	                    target.query = relative.query;
	                } else {
	                    target.query = base.query;
	                }
	            } else {
	                if (relative.path.charAt(0) === "/") {
	                    target.path = removeDotSegments(relative.path);
	                } else {
	                    if ((base.userinfo !== undefined || base.host !== undefined || base.port !== undefined) && !base.path) {
	                        target.path = "/" + relative.path;
	                    } else if (!base.path) {
	                        target.path = relative.path;
	                    } else {
	                        target.path = base.path.slice(0, base.path.lastIndexOf("/") + 1) + relative.path;
	                    }
	                    target.path = removeDotSegments(target.path);
	                }
	                target.query = relative.query;
	            }
	            //target.authority = base.authority;
	            target.userinfo = base.userinfo;
	            target.host = base.host;
	            target.port = base.port;
	        }
	        target.scheme = base.scheme;
	    }
	    target.fragment = relative.fragment;
	    return target;
	}

	function resolve(baseURI, relativeURI, options) {
	    var schemelessOptions = assign({ scheme: 'null' }, options);
	    return serialize(resolveComponents(parse(baseURI, schemelessOptions), parse(relativeURI, schemelessOptions), schemelessOptions, true), schemelessOptions);
	}

	function normalize(uri, options) {
	    if (typeof uri === "string") {
	        uri = serialize(parse(uri, options), options);
	    } else if (typeOf(uri) === "object") {
	        uri = parse(serialize(uri, options), options);
	    }
	    return uri;
	}

	function equal(uriA, uriB, options) {
	    if (typeof uriA === "string") {
	        uriA = serialize(parse(uriA, options), options);
	    } else if (typeOf(uriA) === "object") {
	        uriA = serialize(uriA, options);
	    }
	    if (typeof uriB === "string") {
	        uriB = serialize(parse(uriB, options), options);
	    } else if (typeOf(uriB) === "object") {
	        uriB = serialize(uriB, options);
	    }
	    return uriA === uriB;
	}

	function escapeComponent(str, options) {
	    return str && str.toString().replace(!options || !options.iri ? URI_PROTOCOL.ESCAPE : IRI_PROTOCOL.ESCAPE, pctEncChar);
	}

	function unescapeComponent(str, options) {
	    return str && str.toString().replace(!options || !options.iri ? URI_PROTOCOL.PCT_ENCODED : IRI_PROTOCOL.PCT_ENCODED, pctDecChars);
	}

	var handler = {
	    scheme: "http",
	    domainHost: true,
	    parse: function parse(components, options) {
	        //report missing host
	        if (!components.host) {
	            components.error = components.error || "HTTP URIs must have a host.";
	        }
	        return components;
	    },
	    serialize: function serialize(components, options) {
	        var secure = String(components.scheme).toLowerCase() === "https";
	        //normalize the default port
	        if (components.port === (secure ? 443 : 80) || components.port === "") {
	            components.port = undefined;
	        }
	        //normalize the empty path
	        if (!components.path) {
	            components.path = "/";
	        }
	        //NOTE: We do not parse query strings for HTTP URIs
	        //as WWW Form Url Encoded query strings are part of the HTML4+ spec,
	        //and not the HTTP spec.
	        return components;
	    }
	};

	var handler$1 = {
	    scheme: "https",
	    domainHost: handler.domainHost,
	    parse: handler.parse,
	    serialize: handler.serialize
	};

	function isSecure(wsComponents) {
	    return typeof wsComponents.secure === 'boolean' ? wsComponents.secure : String(wsComponents.scheme).toLowerCase() === "wss";
	}
	//RFC 6455
	var handler$2 = {
	    scheme: "ws",
	    domainHost: true,
	    parse: function parse(components, options) {
	        var wsComponents = components;
	        //indicate if the secure flag is set
	        wsComponents.secure = isSecure(wsComponents);
	        //construct resouce name
	        wsComponents.resourceName = (wsComponents.path || '/') + (wsComponents.query ? '?' + wsComponents.query : '');
	        wsComponents.path = undefined;
	        wsComponents.query = undefined;
	        return wsComponents;
	    },
	    serialize: function serialize(wsComponents, options) {
	        //normalize the default port
	        if (wsComponents.port === (isSecure(wsComponents) ? 443 : 80) || wsComponents.port === "") {
	            wsComponents.port = undefined;
	        }
	        //ensure scheme matches secure flag
	        if (typeof wsComponents.secure === 'boolean') {
	            wsComponents.scheme = wsComponents.secure ? 'wss' : 'ws';
	            wsComponents.secure = undefined;
	        }
	        //reconstruct path from resource name
	        if (wsComponents.resourceName) {
	            var _wsComponents$resourc = wsComponents.resourceName.split('?'),
	                _wsComponents$resourc2 = slicedToArray(_wsComponents$resourc, 2),
	                path = _wsComponents$resourc2[0],
	                query = _wsComponents$resourc2[1];

	            wsComponents.path = path && path !== '/' ? path : undefined;
	            wsComponents.query = query;
	            wsComponents.resourceName = undefined;
	        }
	        //forbid fragment component
	        wsComponents.fragment = undefined;
	        return wsComponents;
	    }
	};

	var handler$3 = {
	    scheme: "wss",
	    domainHost: handler$2.domainHost,
	    parse: handler$2.parse,
	    serialize: handler$2.serialize
	};

	var O = {};
	//RFC 3986
	var UNRESERVED$$ = "[A-Za-z0-9\\-\\.\\_\\~" + ("\\xA0-\\u200D\\u2010-\\u2029\\u202F-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF" ) + "]";
	var HEXDIG$$ = "[0-9A-Fa-f]"; //case-insensitive
	var PCT_ENCODED$ = subexp(subexp("%[EFef]" + HEXDIG$$ + "%" + HEXDIG$$ + HEXDIG$$ + "%" + HEXDIG$$ + HEXDIG$$) + "|" + subexp("%[89A-Fa-f]" + HEXDIG$$ + "%" + HEXDIG$$ + HEXDIG$$) + "|" + subexp("%" + HEXDIG$$ + HEXDIG$$)); //expanded
	//RFC 5322, except these symbols as per RFC 6068: @ : / ? # [ ] & ; =
	//const ATEXT$$ = "[A-Za-z0-9\\!\\#\\$\\%\\&\\'\\*\\+\\-\\/\\=\\?\\^\\_\\`\\{\\|\\}\\~]";
	//const WSP$$ = "[\\x20\\x09]";
	//const OBS_QTEXT$$ = "[\\x01-\\x08\\x0B\\x0C\\x0E-\\x1F\\x7F]";  //(%d1-8 / %d11-12 / %d14-31 / %d127)
	//const QTEXT$$ = merge("[\\x21\\x23-\\x5B\\x5D-\\x7E]", OBS_QTEXT$$);  //%d33 / %d35-91 / %d93-126 / obs-qtext
	//const VCHAR$$ = "[\\x21-\\x7E]";
	//const WSP$$ = "[\\x20\\x09]";
	//const OBS_QP$ = subexp("\\\\" + merge("[\\x00\\x0D\\x0A]", OBS_QTEXT$$));  //%d0 / CR / LF / obs-qtext
	//const FWS$ = subexp(subexp(WSP$$ + "*" + "\\x0D\\x0A") + "?" + WSP$$ + "+");
	//const QUOTED_PAIR$ = subexp(subexp("\\\\" + subexp(VCHAR$$ + "|" + WSP$$)) + "|" + OBS_QP$);
	//const QUOTED_STRING$ = subexp('\\"' + subexp(FWS$ + "?" + QCONTENT$) + "*" + FWS$ + "?" + '\\"');
	var ATEXT$$ = "[A-Za-z0-9\\!\\$\\%\\'\\*\\+\\-\\^\\_\\`\\{\\|\\}\\~]";
	var QTEXT$$ = "[\\!\\$\\%\\'\\(\\)\\*\\+\\,\\-\\.0-9\\<\\>A-Z\\x5E-\\x7E]";
	var VCHAR$$ = merge(QTEXT$$, "[\\\"\\\\]");
	var SOME_DELIMS$$ = "[\\!\\$\\'\\(\\)\\*\\+\\,\\;\\:\\@]";
	var UNRESERVED = new RegExp(UNRESERVED$$, "g");
	var PCT_ENCODED = new RegExp(PCT_ENCODED$, "g");
	var NOT_LOCAL_PART = new RegExp(merge("[^]", ATEXT$$, "[\\.]", '[\\"]', VCHAR$$), "g");
	var NOT_HFNAME = new RegExp(merge("[^]", UNRESERVED$$, SOME_DELIMS$$), "g");
	var NOT_HFVALUE = NOT_HFNAME;
	function decodeUnreserved(str) {
	    var decStr = pctDecChars(str);
	    return !decStr.match(UNRESERVED) ? str : decStr;
	}
	var handler$4 = {
	    scheme: "mailto",
	    parse: function parse$$1(components, options) {
	        var mailtoComponents = components;
	        var to = mailtoComponents.to = mailtoComponents.path ? mailtoComponents.path.split(",") : [];
	        mailtoComponents.path = undefined;
	        if (mailtoComponents.query) {
	            var unknownHeaders = false;
	            var headers = {};
	            var hfields = mailtoComponents.query.split("&");
	            for (var x = 0, xl = hfields.length; x < xl; ++x) {
	                var hfield = hfields[x].split("=");
	                switch (hfield[0]) {
	                    case "to":
	                        var toAddrs = hfield[1].split(",");
	                        for (var _x = 0, _xl = toAddrs.length; _x < _xl; ++_x) {
	                            to.push(toAddrs[_x]);
	                        }
	                        break;
	                    case "subject":
	                        mailtoComponents.subject = unescapeComponent(hfield[1], options);
	                        break;
	                    case "body":
	                        mailtoComponents.body = unescapeComponent(hfield[1], options);
	                        break;
	                    default:
	                        unknownHeaders = true;
	                        headers[unescapeComponent(hfield[0], options)] = unescapeComponent(hfield[1], options);
	                        break;
	                }
	            }
	            if (unknownHeaders) mailtoComponents.headers = headers;
	        }
	        mailtoComponents.query = undefined;
	        for (var _x2 = 0, _xl2 = to.length; _x2 < _xl2; ++_x2) {
	            var addr = to[_x2].split("@");
	            addr[0] = unescapeComponent(addr[0]);
	            if (!options.unicodeSupport) {
	                //convert Unicode IDN -> ASCII IDN
	                try {
	                    addr[1] = punycode.toASCII(unescapeComponent(addr[1], options).toLowerCase());
	                } catch (e) {
	                    mailtoComponents.error = mailtoComponents.error || "Email address's domain name can not be converted to ASCII via punycode: " + e;
	                }
	            } else {
	                addr[1] = unescapeComponent(addr[1], options).toLowerCase();
	            }
	            to[_x2] = addr.join("@");
	        }
	        return mailtoComponents;
	    },
	    serialize: function serialize$$1(mailtoComponents, options) {
	        var components = mailtoComponents;
	        var to = toArray(mailtoComponents.to);
	        if (to) {
	            for (var x = 0, xl = to.length; x < xl; ++x) {
	                var toAddr = String(to[x]);
	                var atIdx = toAddr.lastIndexOf("@");
	                var localPart = toAddr.slice(0, atIdx).replace(PCT_ENCODED, decodeUnreserved).replace(PCT_ENCODED, toUpperCase).replace(NOT_LOCAL_PART, pctEncChar);
	                var domain = toAddr.slice(atIdx + 1);
	                //convert IDN via punycode
	                try {
	                    domain = !options.iri ? punycode.toASCII(unescapeComponent(domain, options).toLowerCase()) : punycode.toUnicode(domain);
	                } catch (e) {
	                    components.error = components.error || "Email address's domain name can not be converted to " + (!options.iri ? "ASCII" : "Unicode") + " via punycode: " + e;
	                }
	                to[x] = localPart + "@" + domain;
	            }
	            components.path = to.join(",");
	        }
	        var headers = mailtoComponents.headers = mailtoComponents.headers || {};
	        if (mailtoComponents.subject) headers["subject"] = mailtoComponents.subject;
	        if (mailtoComponents.body) headers["body"] = mailtoComponents.body;
	        var fields = [];
	        for (var name in headers) {
	            if (headers[name] !== O[name]) {
	                fields.push(name.replace(PCT_ENCODED, decodeUnreserved).replace(PCT_ENCODED, toUpperCase).replace(NOT_HFNAME, pctEncChar) + "=" + headers[name].replace(PCT_ENCODED, decodeUnreserved).replace(PCT_ENCODED, toUpperCase).replace(NOT_HFVALUE, pctEncChar));
	            }
	        }
	        if (fields.length) {
	            components.query = fields.join("&");
	        }
	        return components;
	    }
	};

	var URN_PARSE = /^([^\:]+)\:(.*)/;
	//RFC 2141
	var handler$5 = {
	    scheme: "urn",
	    parse: function parse$$1(components, options) {
	        var matches = components.path && components.path.match(URN_PARSE);
	        var urnComponents = components;
	        if (matches) {
	            var scheme = options.scheme || urnComponents.scheme || "urn";
	            var nid = matches[1].toLowerCase();
	            var nss = matches[2];
	            var urnScheme = scheme + ":" + (options.nid || nid);
	            var schemeHandler = SCHEMES[urnScheme];
	            urnComponents.nid = nid;
	            urnComponents.nss = nss;
	            urnComponents.path = undefined;
	            if (schemeHandler) {
	                urnComponents = schemeHandler.parse(urnComponents, options);
	            }
	        } else {
	            urnComponents.error = urnComponents.error || "URN can not be parsed.";
	        }
	        return urnComponents;
	    },
	    serialize: function serialize$$1(urnComponents, options) {
	        var scheme = options.scheme || urnComponents.scheme || "urn";
	        var nid = urnComponents.nid;
	        var urnScheme = scheme + ":" + (options.nid || nid);
	        var schemeHandler = SCHEMES[urnScheme];
	        if (schemeHandler) {
	            urnComponents = schemeHandler.serialize(urnComponents, options);
	        }
	        var uriComponents = urnComponents;
	        var nss = urnComponents.nss;
	        uriComponents.path = (nid || options.nid) + ":" + nss;
	        return uriComponents;
	    }
	};

	var UUID = /^[0-9A-Fa-f]{8}(?:\-[0-9A-Fa-f]{4}){3}\-[0-9A-Fa-f]{12}$/;
	//RFC 4122
	var handler$6 = {
	    scheme: "urn:uuid",
	    parse: function parse(urnComponents, options) {
	        var uuidComponents = urnComponents;
	        uuidComponents.uuid = uuidComponents.nss;
	        uuidComponents.nss = undefined;
	        if (!options.tolerant && (!uuidComponents.uuid || !uuidComponents.uuid.match(UUID))) {
	            uuidComponents.error = uuidComponents.error || "UUID is not valid.";
	        }
	        return uuidComponents;
	    },
	    serialize: function serialize(uuidComponents, options) {
	        var urnComponents = uuidComponents;
	        //normalize UUID
	        urnComponents.nss = (uuidComponents.uuid || "").toLowerCase();
	        return urnComponents;
	    }
	};

	SCHEMES[handler.scheme] = handler;
	SCHEMES[handler$1.scheme] = handler$1;
	SCHEMES[handler$2.scheme] = handler$2;
	SCHEMES[handler$3.scheme] = handler$3;
	SCHEMES[handler$4.scheme] = handler$4;
	SCHEMES[handler$5.scheme] = handler$5;
	SCHEMES[handler$6.scheme] = handler$6;

	exports.SCHEMES = SCHEMES;
	exports.pctEncChar = pctEncChar;
	exports.pctDecChars = pctDecChars;
	exports.parse = parse;
	exports.removeDotSegments = removeDotSegments;
	exports.serialize = serialize;
	exports.resolveComponents = resolveComponents;
	exports.resolve = resolve;
	exports.normalize = normalize;
	exports.equal = equal;
	exports.escapeComponent = escapeComponent;
	exports.unescapeComponent = unescapeComponent;

	Object.defineProperty(exports, '__esModule', { value: true });

	})));
	
} (uri_all, uri_all.exports));

var uri_allExports = uri_all.exports;

Object.defineProperty(uri$1, "__esModule", { value: true });
const uri = uri_allExports;
uri.code = 'require("ajv/dist/runtime/uri").default';
uri$1.default = uri;

(function (exports) {
	Object.defineProperty(exports, "__esModule", { value: true });
	exports.CodeGen = exports.Name = exports.nil = exports.stringify = exports.str = exports._ = exports.KeywordCxt = void 0;
	var validate_1 = requireValidate();
	Object.defineProperty(exports, "KeywordCxt", { enumerable: true, get: function () { return validate_1.KeywordCxt; } });
	var codegen_1 = requireCodegen();
	Object.defineProperty(exports, "_", { enumerable: true, get: function () { return codegen_1._; } });
	Object.defineProperty(exports, "str", { enumerable: true, get: function () { return codegen_1.str; } });
	Object.defineProperty(exports, "stringify", { enumerable: true, get: function () { return codegen_1.stringify; } });
	Object.defineProperty(exports, "nil", { enumerable: true, get: function () { return codegen_1.nil; } });
	Object.defineProperty(exports, "Name", { enumerable: true, get: function () { return codegen_1.Name; } });
	Object.defineProperty(exports, "CodeGen", { enumerable: true, get: function () { return codegen_1.CodeGen; } });
	const validation_error_1 = requireValidation_error();
	const ref_error_1 = requireRef_error();
	const rules_1 = rules;
	const compile_1 = compile;
	const codegen_2 = requireCodegen();
	const resolve_1 = resolve$1;
	const dataType_1 = dataType;
	const util_1 = util$1;
	const $dataRefSchema = require$$9;
	const uri_1 = uri$1;
	const defaultRegExp = (str, flags) => new RegExp(str, flags);
	defaultRegExp.code = "new RegExp";
	const META_IGNORE_OPTIONS = ["removeAdditional", "useDefaults", "coerceTypes"];
	const EXT_SCOPE_NAMES = new Set([
	    "validate",
	    "serialize",
	    "parse",
	    "wrapper",
	    "root",
	    "schema",
	    "keyword",
	    "pattern",
	    "formats",
	    "validate$data",
	    "func",
	    "obj",
	    "Error",
	]);
	const removedOptions = {
	    errorDataPath: "",
	    format: "`validateFormats: false` can be used instead.",
	    nullable: '"nullable" keyword is supported by default.',
	    jsonPointers: "Deprecated jsPropertySyntax can be used instead.",
	    extendRefs: "Deprecated ignoreKeywordsWithRef can be used instead.",
	    missingRefs: "Pass empty schema with $id that should be ignored to ajv.addSchema.",
	    processCode: "Use option `code: {process: (code, schemaEnv: object) => string}`",
	    sourceCode: "Use option `code: {source: true}`",
	    strictDefaults: "It is default now, see option `strict`.",
	    strictKeywords: "It is default now, see option `strict`.",
	    uniqueItems: '"uniqueItems" keyword is always validated.',
	    unknownFormats: "Disable strict mode or pass `true` to `ajv.addFormat` (or `formats` option).",
	    cache: "Map is used as cache, schema object as key.",
	    serialize: "Map is used as cache, schema object as key.",
	    ajvErrors: "It is default now.",
	};
	const deprecatedOptions = {
	    ignoreKeywordsWithRef: "",
	    jsPropertySyntax: "",
	    unicode: '"minLength"/"maxLength" account for unicode characters by default.',
	};
	const MAX_EXPRESSION = 200;
	// eslint-disable-next-line complexity
	function requiredOptions(o) {
	    var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t, _u, _v, _w, _x, _y, _z, _0;
	    const s = o.strict;
	    const _optz = (_a = o.code) === null || _a === void 0 ? void 0 : _a.optimize;
	    const optimize = _optz === true || _optz === undefined ? 1 : _optz || 0;
	    const regExp = (_c = (_b = o.code) === null || _b === void 0 ? void 0 : _b.regExp) !== null && _c !== void 0 ? _c : defaultRegExp;
	    const uriResolver = (_d = o.uriResolver) !== null && _d !== void 0 ? _d : uri_1.default;
	    return {
	        strictSchema: (_f = (_e = o.strictSchema) !== null && _e !== void 0 ? _e : s) !== null && _f !== void 0 ? _f : true,
	        strictNumbers: (_h = (_g = o.strictNumbers) !== null && _g !== void 0 ? _g : s) !== null && _h !== void 0 ? _h : true,
	        strictTypes: (_k = (_j = o.strictTypes) !== null && _j !== void 0 ? _j : s) !== null && _k !== void 0 ? _k : "log",
	        strictTuples: (_m = (_l = o.strictTuples) !== null && _l !== void 0 ? _l : s) !== null && _m !== void 0 ? _m : "log",
	        strictRequired: (_p = (_o = o.strictRequired) !== null && _o !== void 0 ? _o : s) !== null && _p !== void 0 ? _p : false,
	        code: o.code ? { ...o.code, optimize, regExp } : { optimize, regExp },
	        loopRequired: (_q = o.loopRequired) !== null && _q !== void 0 ? _q : MAX_EXPRESSION,
	        loopEnum: (_r = o.loopEnum) !== null && _r !== void 0 ? _r : MAX_EXPRESSION,
	        meta: (_s = o.meta) !== null && _s !== void 0 ? _s : true,
	        messages: (_t = o.messages) !== null && _t !== void 0 ? _t : true,
	        inlineRefs: (_u = o.inlineRefs) !== null && _u !== void 0 ? _u : true,
	        schemaId: (_v = o.schemaId) !== null && _v !== void 0 ? _v : "$id",
	        addUsedSchema: (_w = o.addUsedSchema) !== null && _w !== void 0 ? _w : true,
	        validateSchema: (_x = o.validateSchema) !== null && _x !== void 0 ? _x : true,
	        validateFormats: (_y = o.validateFormats) !== null && _y !== void 0 ? _y : true,
	        unicodeRegExp: (_z = o.unicodeRegExp) !== null && _z !== void 0 ? _z : true,
	        int32range: (_0 = o.int32range) !== null && _0 !== void 0 ? _0 : true,
	        uriResolver: uriResolver,
	    };
	}
	class Ajv {
	    constructor(opts = {}) {
	        this.schemas = {};
	        this.refs = {};
	        this.formats = {};
	        this._compilations = new Set();
	        this._loading = {};
	        this._cache = new Map();
	        opts = this.opts = { ...opts, ...requiredOptions(opts) };
	        const { es5, lines } = this.opts.code;
	        this.scope = new codegen_2.ValueScope({ scope: {}, prefixes: EXT_SCOPE_NAMES, es5, lines });
	        this.logger = getLogger(opts.logger);
	        const formatOpt = opts.validateFormats;
	        opts.validateFormats = false;
	        this.RULES = (0, rules_1.getRules)();
	        checkOptions.call(this, removedOptions, opts, "NOT SUPPORTED");
	        checkOptions.call(this, deprecatedOptions, opts, "DEPRECATED", "warn");
	        this._metaOpts = getMetaSchemaOptions.call(this);
	        if (opts.formats)
	            addInitialFormats.call(this);
	        this._addVocabularies();
	        this._addDefaultMetaSchema();
	        if (opts.keywords)
	            addInitialKeywords.call(this, opts.keywords);
	        if (typeof opts.meta == "object")
	            this.addMetaSchema(opts.meta);
	        addInitialSchemas.call(this);
	        opts.validateFormats = formatOpt;
	    }
	    _addVocabularies() {
	        this.addKeyword("$async");
	    }
	    _addDefaultMetaSchema() {
	        const { $data, meta, schemaId } = this.opts;
	        let _dataRefSchema = $dataRefSchema;
	        if (schemaId === "id") {
	            _dataRefSchema = { ...$dataRefSchema };
	            _dataRefSchema.id = _dataRefSchema.$id;
	            delete _dataRefSchema.$id;
	        }
	        if (meta && $data)
	            this.addMetaSchema(_dataRefSchema, _dataRefSchema[schemaId], false);
	    }
	    defaultMeta() {
	        const { meta, schemaId } = this.opts;
	        return (this.opts.defaultMeta = typeof meta == "object" ? meta[schemaId] || meta : undefined);
	    }
	    validate(schemaKeyRef, // key, ref or schema object
	    // eslint-disable-next-line @typescript-eslint/no-redundant-type-constituents
	    data // to be validated
	    ) {
	        let v;
	        if (typeof schemaKeyRef == "string") {
	            v = this.getSchema(schemaKeyRef);
	            if (!v)
	                throw new Error(`no schema with key or ref "${schemaKeyRef}"`);
	        }
	        else {
	            v = this.compile(schemaKeyRef);
	        }
	        const valid = v(data);
	        if (!("$async" in v))
	            this.errors = v.errors;
	        return valid;
	    }
	    compile(schema, _meta) {
	        const sch = this._addSchema(schema, _meta);
	        return (sch.validate || this._compileSchemaEnv(sch));
	    }
	    compileAsync(schema, meta) {
	        if (typeof this.opts.loadSchema != "function") {
	            throw new Error("options.loadSchema should be a function");
	        }
	        const { loadSchema } = this.opts;
	        return runCompileAsync.call(this, schema, meta);
	        async function runCompileAsync(_schema, _meta) {
	            await loadMetaSchema.call(this, _schema.$schema);
	            const sch = this._addSchema(_schema, _meta);
	            return sch.validate || _compileAsync.call(this, sch);
	        }
	        async function loadMetaSchema($ref) {
	            if ($ref && !this.getSchema($ref)) {
	                await runCompileAsync.call(this, { $ref }, true);
	            }
	        }
	        async function _compileAsync(sch) {
	            try {
	                return this._compileSchemaEnv(sch);
	            }
	            catch (e) {
	                if (!(e instanceof ref_error_1.default))
	                    throw e;
	                checkLoaded.call(this, e);
	                await loadMissingSchema.call(this, e.missingSchema);
	                return _compileAsync.call(this, sch);
	            }
	        }
	        function checkLoaded({ missingSchema: ref, missingRef }) {
	            if (this.refs[ref]) {
	                throw new Error(`AnySchema ${ref} is loaded but ${missingRef} cannot be resolved`);
	            }
	        }
	        async function loadMissingSchema(ref) {
	            const _schema = await _loadSchema.call(this, ref);
	            if (!this.refs[ref])
	                await loadMetaSchema.call(this, _schema.$schema);
	            if (!this.refs[ref])
	                this.addSchema(_schema, ref, meta);
	        }
	        async function _loadSchema(ref) {
	            const p = this._loading[ref];
	            if (p)
	                return p;
	            try {
	                return await (this._loading[ref] = loadSchema(ref));
	            }
	            finally {
	                delete this._loading[ref];
	            }
	        }
	    }
	    // Adds schema to the instance
	    addSchema(schema, // If array is passed, `key` will be ignored
	    key, // Optional schema key. Can be passed to `validate` method instead of schema object or id/ref. One schema per instance can have empty `id` and `key`.
	    _meta, // true if schema is a meta-schema. Used internally, addMetaSchema should be used instead.
	    _validateSchema = this.opts.validateSchema // false to skip schema validation. Used internally, option validateSchema should be used instead.
	    ) {
	        if (Array.isArray(schema)) {
	            for (const sch of schema)
	                this.addSchema(sch, undefined, _meta, _validateSchema);
	            return this;
	        }
	        let id;
	        if (typeof schema === "object") {
	            const { schemaId } = this.opts;
	            id = schema[schemaId];
	            if (id !== undefined && typeof id != "string") {
	                throw new Error(`schema ${schemaId} must be string`);
	            }
	        }
	        key = (0, resolve_1.normalizeId)(key || id);
	        this._checkUnique(key);
	        this.schemas[key] = this._addSchema(schema, _meta, key, _validateSchema, true);
	        return this;
	    }
	    // Add schema that will be used to validate other schemas
	    // options in META_IGNORE_OPTIONS are alway set to false
	    addMetaSchema(schema, key, // schema key
	    _validateSchema = this.opts.validateSchema // false to skip schema validation, can be used to override validateSchema option for meta-schema
	    ) {
	        this.addSchema(schema, key, true, _validateSchema);
	        return this;
	    }
	    //  Validate schema against its meta-schema
	    validateSchema(schema, throwOrLogError) {
	        if (typeof schema == "boolean")
	            return true;
	        let $schema;
	        $schema = schema.$schema;
	        if ($schema !== undefined && typeof $schema != "string") {
	            throw new Error("$schema must be a string");
	        }
	        $schema = $schema || this.opts.defaultMeta || this.defaultMeta();
	        if (!$schema) {
	            this.logger.warn("meta-schema not available");
	            this.errors = null;
	            return true;
	        }
	        const valid = this.validate($schema, schema);
	        if (!valid && throwOrLogError) {
	            const message = "schema is invalid: " + this.errorsText();
	            if (this.opts.validateSchema === "log")
	                this.logger.error(message);
	            else
	                throw new Error(message);
	        }
	        return valid;
	    }
	    // Get compiled schema by `key` or `ref`.
	    // (`key` that was passed to `addSchema` or full schema reference - `schema.$id` or resolved id)
	    getSchema(keyRef) {
	        let sch;
	        while (typeof (sch = getSchEnv.call(this, keyRef)) == "string")
	            keyRef = sch;
	        if (sch === undefined) {
	            const { schemaId } = this.opts;
	            const root = new compile_1.SchemaEnv({ schema: {}, schemaId });
	            sch = compile_1.resolveSchema.call(this, root, keyRef);
	            if (!sch)
	                return;
	            this.refs[keyRef] = sch;
	        }
	        return (sch.validate || this._compileSchemaEnv(sch));
	    }
	    // Remove cached schema(s).
	    // If no parameter is passed all schemas but meta-schemas are removed.
	    // If RegExp is passed all schemas with key/id matching pattern but meta-schemas are removed.
	    // Even if schema is referenced by other schemas it still can be removed as other schemas have local references.
	    removeSchema(schemaKeyRef) {
	        if (schemaKeyRef instanceof RegExp) {
	            this._removeAllSchemas(this.schemas, schemaKeyRef);
	            this._removeAllSchemas(this.refs, schemaKeyRef);
	            return this;
	        }
	        switch (typeof schemaKeyRef) {
	            case "undefined":
	                this._removeAllSchemas(this.schemas);
	                this._removeAllSchemas(this.refs);
	                this._cache.clear();
	                return this;
	            case "string": {
	                const sch = getSchEnv.call(this, schemaKeyRef);
	                if (typeof sch == "object")
	                    this._cache.delete(sch.schema);
	                delete this.schemas[schemaKeyRef];
	                delete this.refs[schemaKeyRef];
	                return this;
	            }
	            case "object": {
	                const cacheKey = schemaKeyRef;
	                this._cache.delete(cacheKey);
	                let id = schemaKeyRef[this.opts.schemaId];
	                if (id) {
	                    id = (0, resolve_1.normalizeId)(id);
	                    delete this.schemas[id];
	                    delete this.refs[id];
	                }
	                return this;
	            }
	            default:
	                throw new Error("ajv.removeSchema: invalid parameter");
	        }
	    }
	    // add "vocabulary" - a collection of keywords
	    addVocabulary(definitions) {
	        for (const def of definitions)
	            this.addKeyword(def);
	        return this;
	    }
	    addKeyword(kwdOrDef, def // deprecated
	    ) {
	        let keyword;
	        if (typeof kwdOrDef == "string") {
	            keyword = kwdOrDef;
	            if (typeof def == "object") {
	                this.logger.warn("these parameters are deprecated, see docs for addKeyword");
	                def.keyword = keyword;
	            }
	        }
	        else if (typeof kwdOrDef == "object" && def === undefined) {
	            def = kwdOrDef;
	            keyword = def.keyword;
	            if (Array.isArray(keyword) && !keyword.length) {
	                throw new Error("addKeywords: keyword must be string or non-empty array");
	            }
	        }
	        else {
	            throw new Error("invalid addKeywords parameters");
	        }
	        checkKeyword.call(this, keyword, def);
	        if (!def) {
	            (0, util_1.eachItem)(keyword, (kwd) => addRule.call(this, kwd));
	            return this;
	        }
	        keywordMetaschema.call(this, def);
	        const definition = {
	            ...def,
	            type: (0, dataType_1.getJSONTypes)(def.type),
	            schemaType: (0, dataType_1.getJSONTypes)(def.schemaType),
	        };
	        (0, util_1.eachItem)(keyword, definition.type.length === 0
	            ? (k) => addRule.call(this, k, definition)
	            : (k) => definition.type.forEach((t) => addRule.call(this, k, definition, t)));
	        return this;
	    }
	    getKeyword(keyword) {
	        const rule = this.RULES.all[keyword];
	        return typeof rule == "object" ? rule.definition : !!rule;
	    }
	    // Remove keyword
	    removeKeyword(keyword) {
	        // TODO return type should be Ajv
	        const { RULES } = this;
	        delete RULES.keywords[keyword];
	        delete RULES.all[keyword];
	        for (const group of RULES.rules) {
	            const i = group.rules.findIndex((rule) => rule.keyword === keyword);
	            if (i >= 0)
	                group.rules.splice(i, 1);
	        }
	        return this;
	    }
	    // Add format
	    addFormat(name, format) {
	        if (typeof format == "string")
	            format = new RegExp(format);
	        this.formats[name] = format;
	        return this;
	    }
	    errorsText(errors = this.errors, // optional array of validation errors
	    { separator = ", ", dataVar = "data" } = {} // optional options with properties `separator` and `dataVar`
	    ) {
	        if (!errors || errors.length === 0)
	            return "No errors";
	        return errors
	            .map((e) => `${dataVar}${e.instancePath} ${e.message}`)
	            .reduce((text, msg) => text + separator + msg);
	    }
	    $dataMetaSchema(metaSchema, keywordsJsonPointers) {
	        const rules = this.RULES.all;
	        metaSchema = JSON.parse(JSON.stringify(metaSchema));
	        for (const jsonPointer of keywordsJsonPointers) {
	            const segments = jsonPointer.split("/").slice(1); // first segment is an empty string
	            let keywords = metaSchema;
	            for (const seg of segments)
	                keywords = keywords[seg];
	            for (const key in rules) {
	                const rule = rules[key];
	                if (typeof rule != "object")
	                    continue;
	                const { $data } = rule.definition;
	                const schema = keywords[key];
	                if ($data && schema)
	                    keywords[key] = schemaOrData(schema);
	            }
	        }
	        return metaSchema;
	    }
	    _removeAllSchemas(schemas, regex) {
	        for (const keyRef in schemas) {
	            const sch = schemas[keyRef];
	            if (!regex || regex.test(keyRef)) {
	                if (typeof sch == "string") {
	                    delete schemas[keyRef];
	                }
	                else if (sch && !sch.meta) {
	                    this._cache.delete(sch.schema);
	                    delete schemas[keyRef];
	                }
	            }
	        }
	    }
	    _addSchema(schema, meta, baseId, validateSchema = this.opts.validateSchema, addSchema = this.opts.addUsedSchema) {
	        let id;
	        const { schemaId } = this.opts;
	        if (typeof schema == "object") {
	            id = schema[schemaId];
	        }
	        else {
	            if (this.opts.jtd)
	                throw new Error("schema must be object");
	            else if (typeof schema != "boolean")
	                throw new Error("schema must be object or boolean");
	        }
	        let sch = this._cache.get(schema);
	        if (sch !== undefined)
	            return sch;
	        baseId = (0, resolve_1.normalizeId)(id || baseId);
	        const localRefs = resolve_1.getSchemaRefs.call(this, schema, baseId);
	        sch = new compile_1.SchemaEnv({ schema, schemaId, meta, baseId, localRefs });
	        this._cache.set(sch.schema, sch);
	        if (addSchema && !baseId.startsWith("#")) {
	            // TODO atm it is allowed to overwrite schemas without id (instead of not adding them)
	            if (baseId)
	                this._checkUnique(baseId);
	            this.refs[baseId] = sch;
	        }
	        if (validateSchema)
	            this.validateSchema(schema, true);
	        return sch;
	    }
	    _checkUnique(id) {
	        if (this.schemas[id] || this.refs[id]) {
	            throw new Error(`schema with key or id "${id}" already exists`);
	        }
	    }
	    _compileSchemaEnv(sch) {
	        if (sch.meta)
	            this._compileMetaSchema(sch);
	        else
	            compile_1.compileSchema.call(this, sch);
	        /* istanbul ignore if */
	        if (!sch.validate)
	            throw new Error("ajv implementation error");
	        return sch.validate;
	    }
	    _compileMetaSchema(sch) {
	        const currentOpts = this.opts;
	        this.opts = this._metaOpts;
	        try {
	            compile_1.compileSchema.call(this, sch);
	        }
	        finally {
	            this.opts = currentOpts;
	        }
	    }
	}
	Ajv.ValidationError = validation_error_1.default;
	Ajv.MissingRefError = ref_error_1.default;
	exports.default = Ajv;
	function checkOptions(checkOpts, options, msg, log = "error") {
	    for (const key in checkOpts) {
	        const opt = key;
	        if (opt in options)
	            this.logger[log](`${msg}: option ${key}. ${checkOpts[opt]}`);
	    }
	}
	function getSchEnv(keyRef) {
	    keyRef = (0, resolve_1.normalizeId)(keyRef); // TODO tests fail without this line
	    return this.schemas[keyRef] || this.refs[keyRef];
	}
	function addInitialSchemas() {
	    const optsSchemas = this.opts.schemas;
	    if (!optsSchemas)
	        return;
	    if (Array.isArray(optsSchemas))
	        this.addSchema(optsSchemas);
	    else
	        for (const key in optsSchemas)
	            this.addSchema(optsSchemas[key], key);
	}
	function addInitialFormats() {
	    for (const name in this.opts.formats) {
	        const format = this.opts.formats[name];
	        if (format)
	            this.addFormat(name, format);
	    }
	}
	function addInitialKeywords(defs) {
	    if (Array.isArray(defs)) {
	        this.addVocabulary(defs);
	        return;
	    }
	    this.logger.warn("keywords option as map is deprecated, pass array");
	    for (const keyword in defs) {
	        const def = defs[keyword];
	        if (!def.keyword)
	            def.keyword = keyword;
	        this.addKeyword(def);
	    }
	}
	function getMetaSchemaOptions() {
	    const metaOpts = { ...this.opts };
	    for (const opt of META_IGNORE_OPTIONS)
	        delete metaOpts[opt];
	    return metaOpts;
	}
	const noLogs = { log() { }, warn() { }, error() { } };
	function getLogger(logger) {
	    if (logger === false)
	        return noLogs;
	    if (logger === undefined)
	        return console;
	    if (logger.log && logger.warn && logger.error)
	        return logger;
	    throw new Error("logger must implement log, warn and error methods");
	}
	const KEYWORD_NAME = /^[a-z_$][a-z0-9_$:-]*$/i;
	function checkKeyword(keyword, def) {
	    const { RULES } = this;
	    (0, util_1.eachItem)(keyword, (kwd) => {
	        if (RULES.keywords[kwd])
	            throw new Error(`Keyword ${kwd} is already defined`);
	        if (!KEYWORD_NAME.test(kwd))
	            throw new Error(`Keyword ${kwd} has invalid name`);
	    });
	    if (!def)
	        return;
	    if (def.$data && !("code" in def || "validate" in def)) {
	        throw new Error('$data keyword must have "code" or "validate" function');
	    }
	}
	function addRule(keyword, definition, dataType) {
	    var _a;
	    const post = definition === null || definition === void 0 ? void 0 : definition.post;
	    if (dataType && post)
	        throw new Error('keyword with "post" flag cannot have "type"');
	    const { RULES } = this;
	    let ruleGroup = post ? RULES.post : RULES.rules.find(({ type: t }) => t === dataType);
	    if (!ruleGroup) {
	        ruleGroup = { type: dataType, rules: [] };
	        RULES.rules.push(ruleGroup);
	    }
	    RULES.keywords[keyword] = true;
	    if (!definition)
	        return;
	    const rule = {
	        keyword,
	        definition: {
	            ...definition,
	            type: (0, dataType_1.getJSONTypes)(definition.type),
	            schemaType: (0, dataType_1.getJSONTypes)(definition.schemaType),
	        },
	    };
	    if (definition.before)
	        addBeforeRule.call(this, ruleGroup, rule, definition.before);
	    else
	        ruleGroup.rules.push(rule);
	    RULES.all[keyword] = rule;
	    (_a = definition.implements) === null || _a === void 0 ? void 0 : _a.forEach((kwd) => this.addKeyword(kwd));
	}
	function addBeforeRule(ruleGroup, rule, before) {
	    const i = ruleGroup.rules.findIndex((_rule) => _rule.keyword === before);
	    if (i >= 0) {
	        ruleGroup.rules.splice(i, 0, rule);
	    }
	    else {
	        ruleGroup.rules.push(rule);
	        this.logger.warn(`rule ${before} is not defined`);
	    }
	}
	function keywordMetaschema(def) {
	    let { metaSchema } = def;
	    if (metaSchema === undefined)
	        return;
	    if (def.$data && this.opts.$data)
	        metaSchema = schemaOrData(metaSchema);
	    def.validateSchema = this.compile(metaSchema, true);
	}
	const $dataRef = {
	    $ref: "https://raw.githubusercontent.com/ajv-validator/ajv/master/lib/refs/data.json#",
	};
	function schemaOrData(schema) {
	    return { anyOf: [schema, $dataRef] };
	}
	
} (core$2));

var draft7 = {};

var core$1 = {};

var id = {};

Object.defineProperty(id, "__esModule", { value: true });
const def$s = {
    keyword: "id",
    code() {
        throw new Error('NOT SUPPORTED: keyword "id", use "$id" for schema ID');
    },
};
id.default = def$s;

var ref = {};

Object.defineProperty(ref, "__esModule", { value: true });
ref.callRef = ref.getValidate = void 0;
const ref_error_1$1 = requireRef_error();
const code_1$8 = requireCode();
const codegen_1$l = requireCodegen();
const names_1$1 = requireNames();
const compile_1$1 = compile;
const util_1$j = util$1;
const def$r = {
    keyword: "$ref",
    schemaType: "string",
    code(cxt) {
        const { gen, schema: $ref, it } = cxt;
        const { baseId, schemaEnv: env, validateName, opts, self } = it;
        const { root } = env;
        if (($ref === "#" || $ref === "#/") && baseId === root.baseId)
            return callRootRef();
        const schOrEnv = compile_1$1.resolveRef.call(self, root, baseId, $ref);
        if (schOrEnv === undefined)
            throw new ref_error_1$1.default(it.opts.uriResolver, baseId, $ref);
        if (schOrEnv instanceof compile_1$1.SchemaEnv)
            return callValidate(schOrEnv);
        return inlineRefSchema(schOrEnv);
        function callRootRef() {
            if (env === root)
                return callRef(cxt, validateName, env, env.$async);
            const rootName = gen.scopeValue("root", { ref: root });
            return callRef(cxt, (0, codegen_1$l._) `${rootName}.validate`, root, root.$async);
        }
        function callValidate(sch) {
            const v = getValidate(cxt, sch);
            callRef(cxt, v, sch, sch.$async);
        }
        function inlineRefSchema(sch) {
            const schName = gen.scopeValue("schema", opts.code.source === true ? { ref: sch, code: (0, codegen_1$l.stringify)(sch) } : { ref: sch });
            const valid = gen.name("valid");
            const schCxt = cxt.subschema({
                schema: sch,
                dataTypes: [],
                schemaPath: codegen_1$l.nil,
                topSchemaRef: schName,
                errSchemaPath: $ref,
            }, valid);
            cxt.mergeEvaluated(schCxt);
            cxt.ok(valid);
        }
    },
};
function getValidate(cxt, sch) {
    const { gen } = cxt;
    return sch.validate
        ? gen.scopeValue("validate", { ref: sch.validate })
        : (0, codegen_1$l._) `${gen.scopeValue("wrapper", { ref: sch })}.validate`;
}
ref.getValidate = getValidate;
function callRef(cxt, v, sch, $async) {
    const { gen, it } = cxt;
    const { allErrors, schemaEnv: env, opts } = it;
    const passCxt = opts.passContext ? names_1$1.default.this : codegen_1$l.nil;
    if ($async)
        callAsyncRef();
    else
        callSyncRef();
    function callAsyncRef() {
        if (!env.$async)
            throw new Error("async schema referenced by sync schema");
        const valid = gen.let("valid");
        gen.try(() => {
            gen.code((0, codegen_1$l._) `await ${(0, code_1$8.callValidateCode)(cxt, v, passCxt)}`);
            addEvaluatedFrom(v); // TODO will not work with async, it has to be returned with the result
            if (!allErrors)
                gen.assign(valid, true);
        }, (e) => {
            gen.if((0, codegen_1$l._) `!(${e} instanceof ${it.ValidationError})`, () => gen.throw(e));
            addErrorsFrom(e);
            if (!allErrors)
                gen.assign(valid, false);
        });
        cxt.ok(valid);
    }
    function callSyncRef() {
        cxt.result((0, code_1$8.callValidateCode)(cxt, v, passCxt), () => addEvaluatedFrom(v), () => addErrorsFrom(v));
    }
    function addErrorsFrom(source) {
        const errs = (0, codegen_1$l._) `${source}.errors`;
        gen.assign(names_1$1.default.vErrors, (0, codegen_1$l._) `${names_1$1.default.vErrors} === null ? ${errs} : ${names_1$1.default.vErrors}.concat(${errs})`); // TODO tagged
        gen.assign(names_1$1.default.errors, (0, codegen_1$l._) `${names_1$1.default.vErrors}.length`);
    }
    function addEvaluatedFrom(source) {
        var _a;
        if (!it.opts.unevaluated)
            return;
        const schEvaluated = (_a = sch === null || sch === void 0 ? void 0 : sch.validate) === null || _a === void 0 ? void 0 : _a.evaluated;
        // TODO refactor
        if (it.props !== true) {
            if (schEvaluated && !schEvaluated.dynamicProps) {
                if (schEvaluated.props !== undefined) {
                    it.props = util_1$j.mergeEvaluated.props(gen, schEvaluated.props, it.props);
                }
            }
            else {
                const props = gen.var("props", (0, codegen_1$l._) `${source}.evaluated.props`);
                it.props = util_1$j.mergeEvaluated.props(gen, props, it.props, codegen_1$l.Name);
            }
        }
        if (it.items !== true) {
            if (schEvaluated && !schEvaluated.dynamicItems) {
                if (schEvaluated.items !== undefined) {
                    it.items = util_1$j.mergeEvaluated.items(gen, schEvaluated.items, it.items);
                }
            }
            else {
                const items = gen.var("items", (0, codegen_1$l._) `${source}.evaluated.items`);
                it.items = util_1$j.mergeEvaluated.items(gen, items, it.items, codegen_1$l.Name);
            }
        }
    }
}
ref.callRef = callRef;
ref.default = def$r;

Object.defineProperty(core$1, "__esModule", { value: true });
const id_1 = id;
const ref_1 = ref;
const core = [
    "$schema",
    "$id",
    "$defs",
    "$vocabulary",
    { keyword: "$comment" },
    "definitions",
    id_1.default,
    ref_1.default,
];
core$1.default = core;

var validation$1 = {};

var limitNumber = {};

Object.defineProperty(limitNumber, "__esModule", { value: true });
const codegen_1$k = requireCodegen();
const ops = codegen_1$k.operators;
const KWDs = {
    maximum: { okStr: "<=", ok: ops.LTE, fail: ops.GT },
    minimum: { okStr: ">=", ok: ops.GTE, fail: ops.LT },
    exclusiveMaximum: { okStr: "<", ok: ops.LT, fail: ops.GTE },
    exclusiveMinimum: { okStr: ">", ok: ops.GT, fail: ops.LTE },
};
const error$i = {
    message: ({ keyword, schemaCode }) => (0, codegen_1$k.str) `must be ${KWDs[keyword].okStr} ${schemaCode}`,
    params: ({ keyword, schemaCode }) => (0, codegen_1$k._) `{comparison: ${KWDs[keyword].okStr}, limit: ${schemaCode}}`,
};
const def$q = {
    keyword: Object.keys(KWDs),
    type: "number",
    schemaType: "number",
    $data: true,
    error: error$i,
    code(cxt) {
        const { keyword, data, schemaCode } = cxt;
        cxt.fail$data((0, codegen_1$k._) `${data} ${KWDs[keyword].fail} ${schemaCode} || isNaN(${data})`);
    },
};
limitNumber.default = def$q;

var multipleOf = {};

Object.defineProperty(multipleOf, "__esModule", { value: true });
const codegen_1$j = requireCodegen();
const error$h = {
    message: ({ schemaCode }) => (0, codegen_1$j.str) `must be multiple of ${schemaCode}`,
    params: ({ schemaCode }) => (0, codegen_1$j._) `{multipleOf: ${schemaCode}}`,
};
const def$p = {
    keyword: "multipleOf",
    type: "number",
    schemaType: "number",
    $data: true,
    error: error$h,
    code(cxt) {
        const { gen, data, schemaCode, it } = cxt;
        // const bdt = bad$DataType(schemaCode, <string>def.schemaType, $data)
        const prec = it.opts.multipleOfPrecision;
        const res = gen.let("res");
        const invalid = prec
            ? (0, codegen_1$j._) `Math.abs(Math.round(${res}) - ${res}) > 1e-${prec}`
            : (0, codegen_1$j._) `${res} !== parseInt(${res})`;
        cxt.fail$data((0, codegen_1$j._) `(${schemaCode} === 0 || (${res} = ${data}/${schemaCode}, ${invalid}))`);
    },
};
multipleOf.default = def$p;

var limitLength = {};

var ucs2length$1 = {};

Object.defineProperty(ucs2length$1, "__esModule", { value: true });
// https://mathiasbynens.be/notes/javascript-encoding
// https://github.com/bestiejs/punycode.js - punycode.ucs2.decode
function ucs2length(str) {
    const len = str.length;
    let length = 0;
    let pos = 0;
    let value;
    while (pos < len) {
        length++;
        value = str.charCodeAt(pos++);
        if (value >= 0xd800 && value <= 0xdbff && pos < len) {
            // high surrogate, and there is a next character
            value = str.charCodeAt(pos);
            if ((value & 0xfc00) === 0xdc00)
                pos++; // low surrogate
        }
    }
    return length;
}
ucs2length$1.default = ucs2length;
ucs2length.code = 'require("ajv/dist/runtime/ucs2length").default';

Object.defineProperty(limitLength, "__esModule", { value: true });
const codegen_1$i = requireCodegen();
const util_1$i = util$1;
const ucs2length_1 = ucs2length$1;
const error$g = {
    message({ keyword, schemaCode }) {
        const comp = keyword === "maxLength" ? "more" : "fewer";
        return (0, codegen_1$i.str) `must NOT have ${comp} than ${schemaCode} characters`;
    },
    params: ({ schemaCode }) => (0, codegen_1$i._) `{limit: ${schemaCode}}`,
};
const def$o = {
    keyword: ["maxLength", "minLength"],
    type: "string",
    schemaType: "number",
    $data: true,
    error: error$g,
    code(cxt) {
        const { keyword, data, schemaCode, it } = cxt;
        const op = keyword === "maxLength" ? codegen_1$i.operators.GT : codegen_1$i.operators.LT;
        const len = it.opts.unicode === false ? (0, codegen_1$i._) `${data}.length` : (0, codegen_1$i._) `${(0, util_1$i.useFunc)(cxt.gen, ucs2length_1.default)}(${data})`;
        cxt.fail$data((0, codegen_1$i._) `${len} ${op} ${schemaCode}`);
    },
};
limitLength.default = def$o;

var pattern = {};

Object.defineProperty(pattern, "__esModule", { value: true });
const code_1$7 = requireCode();
const codegen_1$h = requireCodegen();
const error$f = {
    message: ({ schemaCode }) => (0, codegen_1$h.str) `must match pattern "${schemaCode}"`,
    params: ({ schemaCode }) => (0, codegen_1$h._) `{pattern: ${schemaCode}}`,
};
const def$n = {
    keyword: "pattern",
    type: "string",
    schemaType: "string",
    $data: true,
    error: error$f,
    code(cxt) {
        const { data, $data, schema, schemaCode, it } = cxt;
        // TODO regexp should be wrapped in try/catchs
        const u = it.opts.unicodeRegExp ? "u" : "";
        const regExp = $data ? (0, codegen_1$h._) `(new RegExp(${schemaCode}, ${u}))` : (0, code_1$7.usePattern)(cxt, schema);
        cxt.fail$data((0, codegen_1$h._) `!${regExp}.test(${data})`);
    },
};
pattern.default = def$n;

var limitProperties = {};

Object.defineProperty(limitProperties, "__esModule", { value: true });
const codegen_1$g = requireCodegen();
const error$e = {
    message({ keyword, schemaCode }) {
        const comp = keyword === "maxProperties" ? "more" : "fewer";
        return (0, codegen_1$g.str) `must NOT have ${comp} than ${schemaCode} properties`;
    },
    params: ({ schemaCode }) => (0, codegen_1$g._) `{limit: ${schemaCode}}`,
};
const def$m = {
    keyword: ["maxProperties", "minProperties"],
    type: "object",
    schemaType: "number",
    $data: true,
    error: error$e,
    code(cxt) {
        const { keyword, data, schemaCode } = cxt;
        const op = keyword === "maxProperties" ? codegen_1$g.operators.GT : codegen_1$g.operators.LT;
        cxt.fail$data((0, codegen_1$g._) `Object.keys(${data}).length ${op} ${schemaCode}`);
    },
};
limitProperties.default = def$m;

var required = {};

Object.defineProperty(required, "__esModule", { value: true });
const code_1$6 = requireCode();
const codegen_1$f = requireCodegen();
const util_1$h = util$1;
const error$d = {
    message: ({ params: { missingProperty } }) => (0, codegen_1$f.str) `must have required property '${missingProperty}'`,
    params: ({ params: { missingProperty } }) => (0, codegen_1$f._) `{missingProperty: ${missingProperty}}`,
};
const def$l = {
    keyword: "required",
    type: "object",
    schemaType: "array",
    $data: true,
    error: error$d,
    code(cxt) {
        const { gen, schema, schemaCode, data, $data, it } = cxt;
        const { opts } = it;
        if (!$data && schema.length === 0)
            return;
        const useLoop = schema.length >= opts.loopRequired;
        if (it.allErrors)
            allErrorsMode();
        else
            exitOnErrorMode();
        if (opts.strictRequired) {
            const props = cxt.parentSchema.properties;
            const { definedProperties } = cxt.it;
            for (const requiredKey of schema) {
                if ((props === null || props === void 0 ? void 0 : props[requiredKey]) === undefined && !definedProperties.has(requiredKey)) {
                    const schemaPath = it.schemaEnv.baseId + it.errSchemaPath;
                    const msg = `required property "${requiredKey}" is not defined at "${schemaPath}" (strictRequired)`;
                    (0, util_1$h.checkStrictMode)(it, msg, it.opts.strictRequired);
                }
            }
        }
        function allErrorsMode() {
            if (useLoop || $data) {
                cxt.block$data(codegen_1$f.nil, loopAllRequired);
            }
            else {
                for (const prop of schema) {
                    (0, code_1$6.checkReportMissingProp)(cxt, prop);
                }
            }
        }
        function exitOnErrorMode() {
            const missing = gen.let("missing");
            if (useLoop || $data) {
                const valid = gen.let("valid", true);
                cxt.block$data(valid, () => loopUntilMissing(missing, valid));
                cxt.ok(valid);
            }
            else {
                gen.if((0, code_1$6.checkMissingProp)(cxt, schema, missing));
                (0, code_1$6.reportMissingProp)(cxt, missing);
                gen.else();
            }
        }
        function loopAllRequired() {
            gen.forOf("prop", schemaCode, (prop) => {
                cxt.setParams({ missingProperty: prop });
                gen.if((0, code_1$6.noPropertyInData)(gen, data, prop, opts.ownProperties), () => cxt.error());
            });
        }
        function loopUntilMissing(missing, valid) {
            cxt.setParams({ missingProperty: missing });
            gen.forOf(missing, schemaCode, () => {
                gen.assign(valid, (0, code_1$6.propertyInData)(gen, data, missing, opts.ownProperties));
                gen.if((0, codegen_1$f.not)(valid), () => {
                    cxt.error();
                    gen.break();
                });
            }, codegen_1$f.nil);
        }
    },
};
required.default = def$l;

var limitItems = {};

Object.defineProperty(limitItems, "__esModule", { value: true });
const codegen_1$e = requireCodegen();
const error$c = {
    message({ keyword, schemaCode }) {
        const comp = keyword === "maxItems" ? "more" : "fewer";
        return (0, codegen_1$e.str) `must NOT have ${comp} than ${schemaCode} items`;
    },
    params: ({ schemaCode }) => (0, codegen_1$e._) `{limit: ${schemaCode}}`,
};
const def$k = {
    keyword: ["maxItems", "minItems"],
    type: "array",
    schemaType: "number",
    $data: true,
    error: error$c,
    code(cxt) {
        const { keyword, data, schemaCode } = cxt;
        const op = keyword === "maxItems" ? codegen_1$e.operators.GT : codegen_1$e.operators.LT;
        cxt.fail$data((0, codegen_1$e._) `${data}.length ${op} ${schemaCode}`);
    },
};
limitItems.default = def$k;

var uniqueItems = {};

var equal$1 = {};

Object.defineProperty(equal$1, "__esModule", { value: true });
// https://github.com/ajv-validator/ajv/issues/889
const equal = fastDeepEqual;
equal.code = 'require("ajv/dist/runtime/equal").default';
equal$1.default = equal;

Object.defineProperty(uniqueItems, "__esModule", { value: true });
const dataType_1 = dataType;
const codegen_1$d = requireCodegen();
const util_1$g = util$1;
const equal_1$2 = equal$1;
const error$b = {
    message: ({ params: { i, j } }) => (0, codegen_1$d.str) `must NOT have duplicate items (items ## ${j} and ${i} are identical)`,
    params: ({ params: { i, j } }) => (0, codegen_1$d._) `{i: ${i}, j: ${j}}`,
};
const def$j = {
    keyword: "uniqueItems",
    type: "array",
    schemaType: "boolean",
    $data: true,
    error: error$b,
    code(cxt) {
        const { gen, data, $data, schema, parentSchema, schemaCode, it } = cxt;
        if (!$data && !schema)
            return;
        const valid = gen.let("valid");
        const itemTypes = parentSchema.items ? (0, dataType_1.getSchemaTypes)(parentSchema.items) : [];
        cxt.block$data(valid, validateUniqueItems, (0, codegen_1$d._) `${schemaCode} === false`);
        cxt.ok(valid);
        function validateUniqueItems() {
            const i = gen.let("i", (0, codegen_1$d._) `${data}.length`);
            const j = gen.let("j");
            cxt.setParams({ i, j });
            gen.assign(valid, true);
            gen.if((0, codegen_1$d._) `${i} > 1`, () => (canOptimize() ? loopN : loopN2)(i, j));
        }
        function canOptimize() {
            return itemTypes.length > 0 && !itemTypes.some((t) => t === "object" || t === "array");
        }
        function loopN(i, j) {
            const item = gen.name("item");
            const wrongType = (0, dataType_1.checkDataTypes)(itemTypes, item, it.opts.strictNumbers, dataType_1.DataType.Wrong);
            const indices = gen.const("indices", (0, codegen_1$d._) `{}`);
            gen.for((0, codegen_1$d._) `;${i}--;`, () => {
                gen.let(item, (0, codegen_1$d._) `${data}[${i}]`);
                gen.if(wrongType, (0, codegen_1$d._) `continue`);
                if (itemTypes.length > 1)
                    gen.if((0, codegen_1$d._) `typeof ${item} == "string"`, (0, codegen_1$d._) `${item} += "_"`);
                gen
                    .if((0, codegen_1$d._) `typeof ${indices}[${item}] == "number"`, () => {
                    gen.assign(j, (0, codegen_1$d._) `${indices}[${item}]`);
                    cxt.error();
                    gen.assign(valid, false).break();
                })
                    .code((0, codegen_1$d._) `${indices}[${item}] = ${i}`);
            });
        }
        function loopN2(i, j) {
            const eql = (0, util_1$g.useFunc)(gen, equal_1$2.default);
            const outer = gen.name("outer");
            gen.label(outer).for((0, codegen_1$d._) `;${i}--;`, () => gen.for((0, codegen_1$d._) `${j} = ${i}; ${j}--;`, () => gen.if((0, codegen_1$d._) `${eql}(${data}[${i}], ${data}[${j}])`, () => {
                cxt.error();
                gen.assign(valid, false).break(outer);
            })));
        }
    },
};
uniqueItems.default = def$j;

var _const = {};

Object.defineProperty(_const, "__esModule", { value: true });
const codegen_1$c = requireCodegen();
const util_1$f = util$1;
const equal_1$1 = equal$1;
const error$a = {
    message: "must be equal to constant",
    params: ({ schemaCode }) => (0, codegen_1$c._) `{allowedValue: ${schemaCode}}`,
};
const def$i = {
    keyword: "const",
    $data: true,
    error: error$a,
    code(cxt) {
        const { gen, data, $data, schemaCode, schema } = cxt;
        if ($data || (schema && typeof schema == "object")) {
            cxt.fail$data((0, codegen_1$c._) `!${(0, util_1$f.useFunc)(gen, equal_1$1.default)}(${data}, ${schemaCode})`);
        }
        else {
            cxt.fail((0, codegen_1$c._) `${schema} !== ${data}`);
        }
    },
};
_const.default = def$i;

var _enum = {};

Object.defineProperty(_enum, "__esModule", { value: true });
const codegen_1$b = requireCodegen();
const util_1$e = util$1;
const equal_1 = equal$1;
const error$9 = {
    message: "must be equal to one of the allowed values",
    params: ({ schemaCode }) => (0, codegen_1$b._) `{allowedValues: ${schemaCode}}`,
};
const def$h = {
    keyword: "enum",
    schemaType: "array",
    $data: true,
    error: error$9,
    code(cxt) {
        const { gen, data, $data, schema, schemaCode, it } = cxt;
        if (!$data && schema.length === 0)
            throw new Error("enum must have non-empty array");
        const useLoop = schema.length >= it.opts.loopEnum;
        let eql;
        const getEql = () => (eql !== null && eql !== void 0 ? eql : (eql = (0, util_1$e.useFunc)(gen, equal_1.default)));
        let valid;
        if (useLoop || $data) {
            valid = gen.let("valid");
            cxt.block$data(valid, loopEnum);
        }
        else {
            /* istanbul ignore if */
            if (!Array.isArray(schema))
                throw new Error("ajv implementation error");
            const vSchema = gen.const("vSchema", schemaCode);
            valid = (0, codegen_1$b.or)(...schema.map((_x, i) => equalCode(vSchema, i)));
        }
        cxt.pass(valid);
        function loopEnum() {
            gen.assign(valid, false);
            gen.forOf("v", schemaCode, (v) => gen.if((0, codegen_1$b._) `${getEql()}(${data}, ${v})`, () => gen.assign(valid, true).break()));
        }
        function equalCode(vSchema, i) {
            const sch = schema[i];
            return typeof sch === "object" && sch !== null
                ? (0, codegen_1$b._) `${getEql()}(${data}, ${vSchema}[${i}])`
                : (0, codegen_1$b._) `${data} === ${sch}`;
        }
    },
};
_enum.default = def$h;

Object.defineProperty(validation$1, "__esModule", { value: true });
const limitNumber_1 = limitNumber;
const multipleOf_1 = multipleOf;
const limitLength_1 = limitLength;
const pattern_1 = pattern;
const limitProperties_1 = limitProperties;
const required_1 = required;
const limitItems_1 = limitItems;
const uniqueItems_1 = uniqueItems;
const const_1 = _const;
const enum_1 = _enum;
const validation = [
    // number
    limitNumber_1.default,
    multipleOf_1.default,
    // string
    limitLength_1.default,
    pattern_1.default,
    // object
    limitProperties_1.default,
    required_1.default,
    // array
    limitItems_1.default,
    uniqueItems_1.default,
    // any
    { keyword: "type", schemaType: ["string", "array"] },
    { keyword: "nullable", schemaType: "boolean" },
    const_1.default,
    enum_1.default,
];
validation$1.default = validation;

var applicator = {};

var additionalItems = {};

Object.defineProperty(additionalItems, "__esModule", { value: true });
additionalItems.validateAdditionalItems = void 0;
const codegen_1$a = requireCodegen();
const util_1$d = util$1;
const error$8 = {
    message: ({ params: { len } }) => (0, codegen_1$a.str) `must NOT have more than ${len} items`,
    params: ({ params: { len } }) => (0, codegen_1$a._) `{limit: ${len}}`,
};
const def$g = {
    keyword: "additionalItems",
    type: "array",
    schemaType: ["boolean", "object"],
    before: "uniqueItems",
    error: error$8,
    code(cxt) {
        const { parentSchema, it } = cxt;
        const { items } = parentSchema;
        if (!Array.isArray(items)) {
            (0, util_1$d.checkStrictMode)(it, '"additionalItems" is ignored when "items" is not an array of schemas');
            return;
        }
        validateAdditionalItems(cxt, items);
    },
};
function validateAdditionalItems(cxt, items) {
    const { gen, schema, data, keyword, it } = cxt;
    it.items = true;
    const len = gen.const("len", (0, codegen_1$a._) `${data}.length`);
    if (schema === false) {
        cxt.setParams({ len: items.length });
        cxt.pass((0, codegen_1$a._) `${len} <= ${items.length}`);
    }
    else if (typeof schema == "object" && !(0, util_1$d.alwaysValidSchema)(it, schema)) {
        const valid = gen.var("valid", (0, codegen_1$a._) `${len} <= ${items.length}`); // TODO var
        gen.if((0, codegen_1$a.not)(valid), () => validateItems(valid));
        cxt.ok(valid);
    }
    function validateItems(valid) {
        gen.forRange("i", items.length, len, (i) => {
            cxt.subschema({ keyword, dataProp: i, dataPropType: util_1$d.Type.Num }, valid);
            if (!it.allErrors)
                gen.if((0, codegen_1$a.not)(valid), () => gen.break());
        });
    }
}
additionalItems.validateAdditionalItems = validateAdditionalItems;
additionalItems.default = def$g;

var prefixItems = {};

var items = {};

Object.defineProperty(items, "__esModule", { value: true });
items.validateTuple = void 0;
const codegen_1$9 = requireCodegen();
const util_1$c = util$1;
const code_1$5 = requireCode();
const def$f = {
    keyword: "items",
    type: "array",
    schemaType: ["object", "array", "boolean"],
    before: "uniqueItems",
    code(cxt) {
        const { schema, it } = cxt;
        if (Array.isArray(schema))
            return validateTuple(cxt, "additionalItems", schema);
        it.items = true;
        if ((0, util_1$c.alwaysValidSchema)(it, schema))
            return;
        cxt.ok((0, code_1$5.validateArray)(cxt));
    },
};
function validateTuple(cxt, extraItems, schArr = cxt.schema) {
    const { gen, parentSchema, data, keyword, it } = cxt;
    checkStrictTuple(parentSchema);
    if (it.opts.unevaluated && schArr.length && it.items !== true) {
        it.items = util_1$c.mergeEvaluated.items(gen, schArr.length, it.items);
    }
    const valid = gen.name("valid");
    const len = gen.const("len", (0, codegen_1$9._) `${data}.length`);
    schArr.forEach((sch, i) => {
        if ((0, util_1$c.alwaysValidSchema)(it, sch))
            return;
        gen.if((0, codegen_1$9._) `${len} > ${i}`, () => cxt.subschema({
            keyword,
            schemaProp: i,
            dataProp: i,
        }, valid));
        cxt.ok(valid);
    });
    function checkStrictTuple(sch) {
        const { opts, errSchemaPath } = it;
        const l = schArr.length;
        const fullTuple = l === sch.minItems && (l === sch.maxItems || sch[extraItems] === false);
        if (opts.strictTuples && !fullTuple) {
            const msg = `"${keyword}" is ${l}-tuple, but minItems or maxItems/${extraItems} are not specified or different at path "${errSchemaPath}"`;
            (0, util_1$c.checkStrictMode)(it, msg, opts.strictTuples);
        }
    }
}
items.validateTuple = validateTuple;
items.default = def$f;

Object.defineProperty(prefixItems, "__esModule", { value: true });
const items_1$1 = items;
const def$e = {
    keyword: "prefixItems",
    type: "array",
    schemaType: ["array"],
    before: "uniqueItems",
    code: (cxt) => (0, items_1$1.validateTuple)(cxt, "items"),
};
prefixItems.default = def$e;

var items2020 = {};

Object.defineProperty(items2020, "__esModule", { value: true });
const codegen_1$8 = requireCodegen();
const util_1$b = util$1;
const code_1$4 = requireCode();
const additionalItems_1$1 = additionalItems;
const error$7 = {
    message: ({ params: { len } }) => (0, codegen_1$8.str) `must NOT have more than ${len} items`,
    params: ({ params: { len } }) => (0, codegen_1$8._) `{limit: ${len}}`,
};
const def$d = {
    keyword: "items",
    type: "array",
    schemaType: ["object", "boolean"],
    before: "uniqueItems",
    error: error$7,
    code(cxt) {
        const { schema, parentSchema, it } = cxt;
        const { prefixItems } = parentSchema;
        it.items = true;
        if ((0, util_1$b.alwaysValidSchema)(it, schema))
            return;
        if (prefixItems)
            (0, additionalItems_1$1.validateAdditionalItems)(cxt, prefixItems);
        else
            cxt.ok((0, code_1$4.validateArray)(cxt));
    },
};
items2020.default = def$d;

var contains = {};

Object.defineProperty(contains, "__esModule", { value: true });
const codegen_1$7 = requireCodegen();
const util_1$a = util$1;
const error$6 = {
    message: ({ params: { min, max } }) => max === undefined
        ? (0, codegen_1$7.str) `must contain at least ${min} valid item(s)`
        : (0, codegen_1$7.str) `must contain at least ${min} and no more than ${max} valid item(s)`,
    params: ({ params: { min, max } }) => max === undefined ? (0, codegen_1$7._) `{minContains: ${min}}` : (0, codegen_1$7._) `{minContains: ${min}, maxContains: ${max}}`,
};
const def$c = {
    keyword: "contains",
    type: "array",
    schemaType: ["object", "boolean"],
    before: "uniqueItems",
    trackErrors: true,
    error: error$6,
    code(cxt) {
        const { gen, schema, parentSchema, data, it } = cxt;
        let min;
        let max;
        const { minContains, maxContains } = parentSchema;
        if (it.opts.next) {
            min = minContains === undefined ? 1 : minContains;
            max = maxContains;
        }
        else {
            min = 1;
        }
        const len = gen.const("len", (0, codegen_1$7._) `${data}.length`);
        cxt.setParams({ min, max });
        if (max === undefined && min === 0) {
            (0, util_1$a.checkStrictMode)(it, `"minContains" == 0 without "maxContains": "contains" keyword ignored`);
            return;
        }
        if (max !== undefined && min > max) {
            (0, util_1$a.checkStrictMode)(it, `"minContains" > "maxContains" is always invalid`);
            cxt.fail();
            return;
        }
        if ((0, util_1$a.alwaysValidSchema)(it, schema)) {
            let cond = (0, codegen_1$7._) `${len} >= ${min}`;
            if (max !== undefined)
                cond = (0, codegen_1$7._) `${cond} && ${len} <= ${max}`;
            cxt.pass(cond);
            return;
        }
        it.items = true;
        const valid = gen.name("valid");
        if (max === undefined && min === 1) {
            validateItems(valid, () => gen.if(valid, () => gen.break()));
        }
        else if (min === 0) {
            gen.let(valid, true);
            if (max !== undefined)
                gen.if((0, codegen_1$7._) `${data}.length > 0`, validateItemsWithCount);
        }
        else {
            gen.let(valid, false);
            validateItemsWithCount();
        }
        cxt.result(valid, () => cxt.reset());
        function validateItemsWithCount() {
            const schValid = gen.name("_valid");
            const count = gen.let("count", 0);
            validateItems(schValid, () => gen.if(schValid, () => checkLimits(count)));
        }
        function validateItems(_valid, block) {
            gen.forRange("i", 0, len, (i) => {
                cxt.subschema({
                    keyword: "contains",
                    dataProp: i,
                    dataPropType: util_1$a.Type.Num,
                    compositeRule: true,
                }, _valid);
                block();
            });
        }
        function checkLimits(count) {
            gen.code((0, codegen_1$7._) `${count}++`);
            if (max === undefined) {
                gen.if((0, codegen_1$7._) `${count} >= ${min}`, () => gen.assign(valid, true).break());
            }
            else {
                gen.if((0, codegen_1$7._) `${count} > ${max}`, () => gen.assign(valid, false).break());
                if (min === 1)
                    gen.assign(valid, true);
                else
                    gen.if((0, codegen_1$7._) `${count} >= ${min}`, () => gen.assign(valid, true));
            }
        }
    },
};
contains.default = def$c;

var dependencies = {};

(function (exports) {
	Object.defineProperty(exports, "__esModule", { value: true });
	exports.validateSchemaDeps = exports.validatePropertyDeps = exports.error = void 0;
	const codegen_1 = requireCodegen();
	const util_1 = util$1;
	const code_1 = requireCode();
	exports.error = {
	    message: ({ params: { property, depsCount, deps } }) => {
	        const property_ies = depsCount === 1 ? "property" : "properties";
	        return (0, codegen_1.str) `must have ${property_ies} ${deps} when property ${property} is present`;
	    },
	    params: ({ params: { property, depsCount, deps, missingProperty } }) => (0, codegen_1._) `{property: ${property},
    missingProperty: ${missingProperty},
    depsCount: ${depsCount},
    deps: ${deps}}`, // TODO change to reference
	};
	const def = {
	    keyword: "dependencies",
	    type: "object",
	    schemaType: "object",
	    error: exports.error,
	    code(cxt) {
	        const [propDeps, schDeps] = splitDependencies(cxt);
	        validatePropertyDeps(cxt, propDeps);
	        validateSchemaDeps(cxt, schDeps);
	    },
	};
	function splitDependencies({ schema }) {
	    const propertyDeps = {};
	    const schemaDeps = {};
	    for (const key in schema) {
	        if (key === "__proto__")
	            continue;
	        const deps = Array.isArray(schema[key]) ? propertyDeps : schemaDeps;
	        deps[key] = schema[key];
	    }
	    return [propertyDeps, schemaDeps];
	}
	function validatePropertyDeps(cxt, propertyDeps = cxt.schema) {
	    const { gen, data, it } = cxt;
	    if (Object.keys(propertyDeps).length === 0)
	        return;
	    const missing = gen.let("missing");
	    for (const prop in propertyDeps) {
	        const deps = propertyDeps[prop];
	        if (deps.length === 0)
	            continue;
	        const hasProperty = (0, code_1.propertyInData)(gen, data, prop, it.opts.ownProperties);
	        cxt.setParams({
	            property: prop,
	            depsCount: deps.length,
	            deps: deps.join(", "),
	        });
	        if (it.allErrors) {
	            gen.if(hasProperty, () => {
	                for (const depProp of deps) {
	                    (0, code_1.checkReportMissingProp)(cxt, depProp);
	                }
	            });
	        }
	        else {
	            gen.if((0, codegen_1._) `${hasProperty} && (${(0, code_1.checkMissingProp)(cxt, deps, missing)})`);
	            (0, code_1.reportMissingProp)(cxt, missing);
	            gen.else();
	        }
	    }
	}
	exports.validatePropertyDeps = validatePropertyDeps;
	function validateSchemaDeps(cxt, schemaDeps = cxt.schema) {
	    const { gen, data, keyword, it } = cxt;
	    const valid = gen.name("valid");
	    for (const prop in schemaDeps) {
	        if ((0, util_1.alwaysValidSchema)(it, schemaDeps[prop]))
	            continue;
	        gen.if((0, code_1.propertyInData)(gen, data, prop, it.opts.ownProperties), () => {
	            const schCxt = cxt.subschema({ keyword, schemaProp: prop }, valid);
	            cxt.mergeValidEvaluated(schCxt, valid);
	        }, () => gen.var(valid, true) // TODO var
	        );
	        cxt.ok(valid);
	    }
	}
	exports.validateSchemaDeps = validateSchemaDeps;
	exports.default = def;
	
} (dependencies));

var propertyNames = {};

Object.defineProperty(propertyNames, "__esModule", { value: true });
const codegen_1$6 = requireCodegen();
const util_1$9 = util$1;
const error$5 = {
    message: "property name must be valid",
    params: ({ params }) => (0, codegen_1$6._) `{propertyName: ${params.propertyName}}`,
};
const def$b = {
    keyword: "propertyNames",
    type: "object",
    schemaType: ["object", "boolean"],
    error: error$5,
    code(cxt) {
        const { gen, schema, data, it } = cxt;
        if ((0, util_1$9.alwaysValidSchema)(it, schema))
            return;
        const valid = gen.name("valid");
        gen.forIn("key", data, (key) => {
            cxt.setParams({ propertyName: key });
            cxt.subschema({
                keyword: "propertyNames",
                data: key,
                dataTypes: ["string"],
                propertyName: key,
                compositeRule: true,
            }, valid);
            gen.if((0, codegen_1$6.not)(valid), () => {
                cxt.error(true);
                if (!it.allErrors)
                    gen.break();
            });
        });
        cxt.ok(valid);
    },
};
propertyNames.default = def$b;

var additionalProperties = {};

Object.defineProperty(additionalProperties, "__esModule", { value: true });
const code_1$3 = requireCode();
const codegen_1$5 = requireCodegen();
const names_1 = requireNames();
const util_1$8 = util$1;
const error$4 = {
    message: "must NOT have additional properties",
    params: ({ params }) => (0, codegen_1$5._) `{additionalProperty: ${params.additionalProperty}}`,
};
const def$a = {
    keyword: "additionalProperties",
    type: ["object"],
    schemaType: ["boolean", "object"],
    allowUndefined: true,
    trackErrors: true,
    error: error$4,
    code(cxt) {
        const { gen, schema, parentSchema, data, errsCount, it } = cxt;
        /* istanbul ignore if */
        if (!errsCount)
            throw new Error("ajv implementation error");
        const { allErrors, opts } = it;
        it.props = true;
        if (opts.removeAdditional !== "all" && (0, util_1$8.alwaysValidSchema)(it, schema))
            return;
        const props = (0, code_1$3.allSchemaProperties)(parentSchema.properties);
        const patProps = (0, code_1$3.allSchemaProperties)(parentSchema.patternProperties);
        checkAdditionalProperties();
        cxt.ok((0, codegen_1$5._) `${errsCount} === ${names_1.default.errors}`);
        function checkAdditionalProperties() {
            gen.forIn("key", data, (key) => {
                if (!props.length && !patProps.length)
                    additionalPropertyCode(key);
                else
                    gen.if(isAdditional(key), () => additionalPropertyCode(key));
            });
        }
        function isAdditional(key) {
            let definedProp;
            if (props.length > 8) {
                // TODO maybe an option instead of hard-coded 8?
                const propsSchema = (0, util_1$8.schemaRefOrVal)(it, parentSchema.properties, "properties");
                definedProp = (0, code_1$3.isOwnProperty)(gen, propsSchema, key);
            }
            else if (props.length) {
                definedProp = (0, codegen_1$5.or)(...props.map((p) => (0, codegen_1$5._) `${key} === ${p}`));
            }
            else {
                definedProp = codegen_1$5.nil;
            }
            if (patProps.length) {
                definedProp = (0, codegen_1$5.or)(definedProp, ...patProps.map((p) => (0, codegen_1$5._) `${(0, code_1$3.usePattern)(cxt, p)}.test(${key})`));
            }
            return (0, codegen_1$5.not)(definedProp);
        }
        function deleteAdditional(key) {
            gen.code((0, codegen_1$5._) `delete ${data}[${key}]`);
        }
        function additionalPropertyCode(key) {
            if (opts.removeAdditional === "all" || (opts.removeAdditional && schema === false)) {
                deleteAdditional(key);
                return;
            }
            if (schema === false) {
                cxt.setParams({ additionalProperty: key });
                cxt.error();
                if (!allErrors)
                    gen.break();
                return;
            }
            if (typeof schema == "object" && !(0, util_1$8.alwaysValidSchema)(it, schema)) {
                const valid = gen.name("valid");
                if (opts.removeAdditional === "failing") {
                    applyAdditionalSchema(key, valid, false);
                    gen.if((0, codegen_1$5.not)(valid), () => {
                        cxt.reset();
                        deleteAdditional(key);
                    });
                }
                else {
                    applyAdditionalSchema(key, valid);
                    if (!allErrors)
                        gen.if((0, codegen_1$5.not)(valid), () => gen.break());
                }
            }
        }
        function applyAdditionalSchema(key, valid, errors) {
            const subschema = {
                keyword: "additionalProperties",
                dataProp: key,
                dataPropType: util_1$8.Type.Str,
            };
            if (errors === false) {
                Object.assign(subschema, {
                    compositeRule: true,
                    createErrors: false,
                    allErrors: false,
                });
            }
            cxt.subschema(subschema, valid);
        }
    },
};
additionalProperties.default = def$a;

var properties$1 = {};

Object.defineProperty(properties$1, "__esModule", { value: true });
const validate_1 = requireValidate();
const code_1$2 = requireCode();
const util_1$7 = util$1;
const additionalProperties_1$1 = additionalProperties;
const def$9 = {
    keyword: "properties",
    type: "object",
    schemaType: "object",
    code(cxt) {
        const { gen, schema, parentSchema, data, it } = cxt;
        if (it.opts.removeAdditional === "all" && parentSchema.additionalProperties === undefined) {
            additionalProperties_1$1.default.code(new validate_1.KeywordCxt(it, additionalProperties_1$1.default, "additionalProperties"));
        }
        const allProps = (0, code_1$2.allSchemaProperties)(schema);
        for (const prop of allProps) {
            it.definedProperties.add(prop);
        }
        if (it.opts.unevaluated && allProps.length && it.props !== true) {
            it.props = util_1$7.mergeEvaluated.props(gen, (0, util_1$7.toHash)(allProps), it.props);
        }
        const properties = allProps.filter((p) => !(0, util_1$7.alwaysValidSchema)(it, schema[p]));
        if (properties.length === 0)
            return;
        const valid = gen.name("valid");
        for (const prop of properties) {
            if (hasDefault(prop)) {
                applyPropertySchema(prop);
            }
            else {
                gen.if((0, code_1$2.propertyInData)(gen, data, prop, it.opts.ownProperties));
                applyPropertySchema(prop);
                if (!it.allErrors)
                    gen.else().var(valid, true);
                gen.endIf();
            }
            cxt.it.definedProperties.add(prop);
            cxt.ok(valid);
        }
        function hasDefault(prop) {
            return it.opts.useDefaults && !it.compositeRule && schema[prop].default !== undefined;
        }
        function applyPropertySchema(prop) {
            cxt.subschema({
                keyword: "properties",
                schemaProp: prop,
                dataProp: prop,
            }, valid);
        }
    },
};
properties$1.default = def$9;

var patternProperties = {};

Object.defineProperty(patternProperties, "__esModule", { value: true });
const code_1$1 = requireCode();
const codegen_1$4 = requireCodegen();
const util_1$6 = util$1;
const util_2 = util$1;
const def$8 = {
    keyword: "patternProperties",
    type: "object",
    schemaType: "object",
    code(cxt) {
        const { gen, schema, data, parentSchema, it } = cxt;
        const { opts } = it;
        const patterns = (0, code_1$1.allSchemaProperties)(schema);
        const alwaysValidPatterns = patterns.filter((p) => (0, util_1$6.alwaysValidSchema)(it, schema[p]));
        if (patterns.length === 0 ||
            (alwaysValidPatterns.length === patterns.length &&
                (!it.opts.unevaluated || it.props === true))) {
            return;
        }
        const checkProperties = opts.strictSchema && !opts.allowMatchingProperties && parentSchema.properties;
        const valid = gen.name("valid");
        if (it.props !== true && !(it.props instanceof codegen_1$4.Name)) {
            it.props = (0, util_2.evaluatedPropsToName)(gen, it.props);
        }
        const { props } = it;
        validatePatternProperties();
        function validatePatternProperties() {
            for (const pat of patterns) {
                if (checkProperties)
                    checkMatchingProperties(pat);
                if (it.allErrors) {
                    validateProperties(pat);
                }
                else {
                    gen.var(valid, true); // TODO var
                    validateProperties(pat);
                    gen.if(valid);
                }
            }
        }
        function checkMatchingProperties(pat) {
            for (const prop in checkProperties) {
                if (new RegExp(pat).test(prop)) {
                    (0, util_1$6.checkStrictMode)(it, `property ${prop} matches pattern ${pat} (use allowMatchingProperties)`);
                }
            }
        }
        function validateProperties(pat) {
            gen.forIn("key", data, (key) => {
                gen.if((0, codegen_1$4._) `${(0, code_1$1.usePattern)(cxt, pat)}.test(${key})`, () => {
                    const alwaysValid = alwaysValidPatterns.includes(pat);
                    if (!alwaysValid) {
                        cxt.subschema({
                            keyword: "patternProperties",
                            schemaProp: pat,
                            dataProp: key,
                            dataPropType: util_2.Type.Str,
                        }, valid);
                    }
                    if (it.opts.unevaluated && props !== true) {
                        gen.assign((0, codegen_1$4._) `${props}[${key}]`, true);
                    }
                    else if (!alwaysValid && !it.allErrors) {
                        // can short-circuit if `unevaluatedProperties` is not supported (opts.next === false)
                        // or if all properties were evaluated (props === true)
                        gen.if((0, codegen_1$4.not)(valid), () => gen.break());
                    }
                });
            });
        }
    },
};
patternProperties.default = def$8;

var not = {};

Object.defineProperty(not, "__esModule", { value: true });
const util_1$5 = util$1;
const def$7 = {
    keyword: "not",
    schemaType: ["object", "boolean"],
    trackErrors: true,
    code(cxt) {
        const { gen, schema, it } = cxt;
        if ((0, util_1$5.alwaysValidSchema)(it, schema)) {
            cxt.fail();
            return;
        }
        const valid = gen.name("valid");
        cxt.subschema({
            keyword: "not",
            compositeRule: true,
            createErrors: false,
            allErrors: false,
        }, valid);
        cxt.failResult(valid, () => cxt.reset(), () => cxt.error());
    },
    error: { message: "must NOT be valid" },
};
not.default = def$7;

var anyOf = {};

Object.defineProperty(anyOf, "__esModule", { value: true });
const code_1 = requireCode();
const def$6 = {
    keyword: "anyOf",
    schemaType: "array",
    trackErrors: true,
    code: code_1.validateUnion,
    error: { message: "must match a schema in anyOf" },
};
anyOf.default = def$6;

var oneOf = {};

Object.defineProperty(oneOf, "__esModule", { value: true });
const codegen_1$3 = requireCodegen();
const util_1$4 = util$1;
const error$3 = {
    message: "must match exactly one schema in oneOf",
    params: ({ params }) => (0, codegen_1$3._) `{passingSchemas: ${params.passing}}`,
};
const def$5 = {
    keyword: "oneOf",
    schemaType: "array",
    trackErrors: true,
    error: error$3,
    code(cxt) {
        const { gen, schema, parentSchema, it } = cxt;
        /* istanbul ignore if */
        if (!Array.isArray(schema))
            throw new Error("ajv implementation error");
        if (it.opts.discriminator && parentSchema.discriminator)
            return;
        const schArr = schema;
        const valid = gen.let("valid", false);
        const passing = gen.let("passing", null);
        const schValid = gen.name("_valid");
        cxt.setParams({ passing });
        // TODO possibly fail straight away (with warning or exception) if there are two empty always valid schemas
        gen.block(validateOneOf);
        cxt.result(valid, () => cxt.reset(), () => cxt.error(true));
        function validateOneOf() {
            schArr.forEach((sch, i) => {
                let schCxt;
                if ((0, util_1$4.alwaysValidSchema)(it, sch)) {
                    gen.var(schValid, true);
                }
                else {
                    schCxt = cxt.subschema({
                        keyword: "oneOf",
                        schemaProp: i,
                        compositeRule: true,
                    }, schValid);
                }
                if (i > 0) {
                    gen
                        .if((0, codegen_1$3._) `${schValid} && ${valid}`)
                        .assign(valid, false)
                        .assign(passing, (0, codegen_1$3._) `[${passing}, ${i}]`)
                        .else();
                }
                gen.if(schValid, () => {
                    gen.assign(valid, true);
                    gen.assign(passing, i);
                    if (schCxt)
                        cxt.mergeEvaluated(schCxt, codegen_1$3.Name);
                });
            });
        }
    },
};
oneOf.default = def$5;

var allOf = {};

Object.defineProperty(allOf, "__esModule", { value: true });
const util_1$3 = util$1;
const def$4 = {
    keyword: "allOf",
    schemaType: "array",
    code(cxt) {
        const { gen, schema, it } = cxt;
        /* istanbul ignore if */
        if (!Array.isArray(schema))
            throw new Error("ajv implementation error");
        const valid = gen.name("valid");
        schema.forEach((sch, i) => {
            if ((0, util_1$3.alwaysValidSchema)(it, sch))
                return;
            const schCxt = cxt.subschema({ keyword: "allOf", schemaProp: i }, valid);
            cxt.ok(valid);
            cxt.mergeEvaluated(schCxt);
        });
    },
};
allOf.default = def$4;

var _if = {};

Object.defineProperty(_if, "__esModule", { value: true });
const codegen_1$2 = requireCodegen();
const util_1$2 = util$1;
const error$2 = {
    message: ({ params }) => (0, codegen_1$2.str) `must match "${params.ifClause}" schema`,
    params: ({ params }) => (0, codegen_1$2._) `{failingKeyword: ${params.ifClause}}`,
};
const def$3 = {
    keyword: "if",
    schemaType: ["object", "boolean"],
    trackErrors: true,
    error: error$2,
    code(cxt) {
        const { gen, parentSchema, it } = cxt;
        if (parentSchema.then === undefined && parentSchema.else === undefined) {
            (0, util_1$2.checkStrictMode)(it, '"if" without "then" and "else" is ignored');
        }
        const hasThen = hasSchema(it, "then");
        const hasElse = hasSchema(it, "else");
        if (!hasThen && !hasElse)
            return;
        const valid = gen.let("valid", true);
        const schValid = gen.name("_valid");
        validateIf();
        cxt.reset();
        if (hasThen && hasElse) {
            const ifClause = gen.let("ifClause");
            cxt.setParams({ ifClause });
            gen.if(schValid, validateClause("then", ifClause), validateClause("else", ifClause));
        }
        else if (hasThen) {
            gen.if(schValid, validateClause("then"));
        }
        else {
            gen.if((0, codegen_1$2.not)(schValid), validateClause("else"));
        }
        cxt.pass(valid, () => cxt.error(true));
        function validateIf() {
            const schCxt = cxt.subschema({
                keyword: "if",
                compositeRule: true,
                createErrors: false,
                allErrors: false,
            }, schValid);
            cxt.mergeEvaluated(schCxt);
        }
        function validateClause(keyword, ifClause) {
            return () => {
                const schCxt = cxt.subschema({ keyword }, schValid);
                gen.assign(valid, schValid);
                cxt.mergeValidEvaluated(schCxt, valid);
                if (ifClause)
                    gen.assign(ifClause, (0, codegen_1$2._) `${keyword}`);
                else
                    cxt.setParams({ ifClause: keyword });
            };
        }
    },
};
function hasSchema(it, keyword) {
    const schema = it.schema[keyword];
    return schema !== undefined && !(0, util_1$2.alwaysValidSchema)(it, schema);
}
_if.default = def$3;

var thenElse = {};

Object.defineProperty(thenElse, "__esModule", { value: true });
const util_1$1 = util$1;
const def$2 = {
    keyword: ["then", "else"],
    schemaType: ["object", "boolean"],
    code({ keyword, parentSchema, it }) {
        if (parentSchema.if === undefined)
            (0, util_1$1.checkStrictMode)(it, `"${keyword}" without "if" is ignored`);
    },
};
thenElse.default = def$2;

Object.defineProperty(applicator, "__esModule", { value: true });
const additionalItems_1 = additionalItems;
const prefixItems_1 = prefixItems;
const items_1 = items;
const items2020_1 = items2020;
const contains_1 = contains;
const dependencies_1 = dependencies;
const propertyNames_1 = propertyNames;
const additionalProperties_1 = additionalProperties;
const properties_1 = properties$1;
const patternProperties_1 = patternProperties;
const not_1 = not;
const anyOf_1 = anyOf;
const oneOf_1 = oneOf;
const allOf_1 = allOf;
const if_1 = _if;
const thenElse_1 = thenElse;
function getApplicator(draft2020 = false) {
    const applicator = [
        // any
        not_1.default,
        anyOf_1.default,
        oneOf_1.default,
        allOf_1.default,
        if_1.default,
        thenElse_1.default,
        // object
        propertyNames_1.default,
        additionalProperties_1.default,
        dependencies_1.default,
        properties_1.default,
        patternProperties_1.default,
    ];
    // array
    if (draft2020)
        applicator.push(prefixItems_1.default, items2020_1.default);
    else
        applicator.push(additionalItems_1.default, items_1.default);
    applicator.push(contains_1.default);
    return applicator;
}
applicator.default = getApplicator;

var format$2 = {};

var format$1 = {};

Object.defineProperty(format$1, "__esModule", { value: true });
const codegen_1$1 = requireCodegen();
const error$1 = {
    message: ({ schemaCode }) => (0, codegen_1$1.str) `must match format "${schemaCode}"`,
    params: ({ schemaCode }) => (0, codegen_1$1._) `{format: ${schemaCode}}`,
};
const def$1 = {
    keyword: "format",
    type: ["number", "string"],
    schemaType: "string",
    $data: true,
    error: error$1,
    code(cxt, ruleType) {
        const { gen, data, $data, schema, schemaCode, it } = cxt;
        const { opts, errSchemaPath, schemaEnv, self } = it;
        if (!opts.validateFormats)
            return;
        if ($data)
            validate$DataFormat();
        else
            validateFormat();
        function validate$DataFormat() {
            const fmts = gen.scopeValue("formats", {
                ref: self.formats,
                code: opts.code.formats,
            });
            const fDef = gen.const("fDef", (0, codegen_1$1._) `${fmts}[${schemaCode}]`);
            const fType = gen.let("fType");
            const format = gen.let("format");
            // TODO simplify
            gen.if((0, codegen_1$1._) `typeof ${fDef} == "object" && !(${fDef} instanceof RegExp)`, () => gen.assign(fType, (0, codegen_1$1._) `${fDef}.type || "string"`).assign(format, (0, codegen_1$1._) `${fDef}.validate`), () => gen.assign(fType, (0, codegen_1$1._) `"string"`).assign(format, fDef));
            cxt.fail$data((0, codegen_1$1.or)(unknownFmt(), invalidFmt()));
            function unknownFmt() {
                if (opts.strictSchema === false)
                    return codegen_1$1.nil;
                return (0, codegen_1$1._) `${schemaCode} && !${format}`;
            }
            function invalidFmt() {
                const callFormat = schemaEnv.$async
                    ? (0, codegen_1$1._) `(${fDef}.async ? await ${format}(${data}) : ${format}(${data}))`
                    : (0, codegen_1$1._) `${format}(${data})`;
                const validData = (0, codegen_1$1._) `(typeof ${format} == "function" ? ${callFormat} : ${format}.test(${data}))`;
                return (0, codegen_1$1._) `${format} && ${format} !== true && ${fType} === ${ruleType} && !${validData}`;
            }
        }
        function validateFormat() {
            const formatDef = self.formats[schema];
            if (!formatDef) {
                unknownFormat();
                return;
            }
            if (formatDef === true)
                return;
            const [fmtType, format, fmtRef] = getFormat(formatDef);
            if (fmtType === ruleType)
                cxt.pass(validCondition());
            function unknownFormat() {
                if (opts.strictSchema === false) {
                    self.logger.warn(unknownMsg());
                    return;
                }
                throw new Error(unknownMsg());
                function unknownMsg() {
                    return `unknown format "${schema}" ignored in schema at path "${errSchemaPath}"`;
                }
            }
            function getFormat(fmtDef) {
                const code = fmtDef instanceof RegExp
                    ? (0, codegen_1$1.regexpCode)(fmtDef)
                    : opts.code.formats
                        ? (0, codegen_1$1._) `${opts.code.formats}${(0, codegen_1$1.getProperty)(schema)}`
                        : undefined;
                const fmt = gen.scopeValue("formats", { key: schema, ref: fmtDef, code });
                if (typeof fmtDef == "object" && !(fmtDef instanceof RegExp)) {
                    return [fmtDef.type || "string", fmtDef.validate, (0, codegen_1$1._) `${fmt}.validate`];
                }
                return ["string", fmtDef, fmt];
            }
            function validCondition() {
                if (typeof formatDef == "object" && !(formatDef instanceof RegExp) && formatDef.async) {
                    if (!schemaEnv.$async)
                        throw new Error("async format in sync schema");
                    return (0, codegen_1$1._) `await ${fmtRef}(${data})`;
                }
                return typeof format == "function" ? (0, codegen_1$1._) `${fmtRef}(${data})` : (0, codegen_1$1._) `${fmtRef}.test(${data})`;
            }
        }
    },
};
format$1.default = def$1;

Object.defineProperty(format$2, "__esModule", { value: true });
const format_1$1 = format$1;
const format = [format_1$1.default];
format$2.default = format;

var metadata = {};

Object.defineProperty(metadata, "__esModule", { value: true });
metadata.contentVocabulary = metadata.metadataVocabulary = void 0;
metadata.metadataVocabulary = [
    "title",
    "description",
    "default",
    "deprecated",
    "readOnly",
    "writeOnly",
    "examples",
];
metadata.contentVocabulary = [
    "contentMediaType",
    "contentEncoding",
    "contentSchema",
];

Object.defineProperty(draft7, "__esModule", { value: true });
const core_1 = core$1;
const validation_1 = validation$1;
const applicator_1 = applicator;
const format_1 = format$2;
const metadata_1 = metadata;
const draft7Vocabularies = [
    core_1.default,
    validation_1.default,
    (0, applicator_1.default)(),
    format_1.default,
    metadata_1.metadataVocabulary,
    metadata_1.contentVocabulary,
];
draft7.default = draft7Vocabularies;

var discriminator = {};

var types = {};

Object.defineProperty(types, "__esModule", { value: true });
types.DiscrError = void 0;
var DiscrError;
(function (DiscrError) {
    DiscrError["Tag"] = "tag";
    DiscrError["Mapping"] = "mapping";
})(DiscrError || (types.DiscrError = DiscrError = {}));

Object.defineProperty(discriminator, "__esModule", { value: true });
const codegen_1 = requireCodegen();
const types_1 = types;
const compile_1 = compile;
const ref_error_1 = requireRef_error();
const util_1 = util$1;
const error = {
    message: ({ params: { discrError, tagName } }) => discrError === types_1.DiscrError.Tag
        ? `tag "${tagName}" must be string`
        : `value of tag "${tagName}" must be in oneOf`,
    params: ({ params: { discrError, tag, tagName } }) => (0, codegen_1._) `{error: ${discrError}, tag: ${tagName}, tagValue: ${tag}}`,
};
const def = {
    keyword: "discriminator",
    type: "object",
    schemaType: "object",
    error,
    code(cxt) {
        const { gen, data, schema, parentSchema, it } = cxt;
        const { oneOf } = parentSchema;
        if (!it.opts.discriminator) {
            throw new Error("discriminator: requires discriminator option");
        }
        const tagName = schema.propertyName;
        if (typeof tagName != "string")
            throw new Error("discriminator: requires propertyName");
        if (schema.mapping)
            throw new Error("discriminator: mapping is not supported");
        if (!oneOf)
            throw new Error("discriminator: requires oneOf keyword");
        const valid = gen.let("valid", false);
        const tag = gen.const("tag", (0, codegen_1._) `${data}${(0, codegen_1.getProperty)(tagName)}`);
        gen.if((0, codegen_1._) `typeof ${tag} == "string"`, () => validateMapping(), () => cxt.error(false, { discrError: types_1.DiscrError.Tag, tag, tagName }));
        cxt.ok(valid);
        function validateMapping() {
            const mapping = getMapping();
            gen.if(false);
            for (const tagValue in mapping) {
                gen.elseIf((0, codegen_1._) `${tag} === ${tagValue}`);
                gen.assign(valid, applyTagSchema(mapping[tagValue]));
            }
            gen.else();
            cxt.error(false, { discrError: types_1.DiscrError.Mapping, tag, tagName });
            gen.endIf();
        }
        function applyTagSchema(schemaProp) {
            const _valid = gen.name("valid");
            const schCxt = cxt.subschema({ keyword: "oneOf", schemaProp }, _valid);
            cxt.mergeEvaluated(schCxt, codegen_1.Name);
            return _valid;
        }
        function getMapping() {
            var _a;
            const oneOfMapping = {};
            const topRequired = hasRequired(parentSchema);
            let tagRequired = true;
            for (let i = 0; i < oneOf.length; i++) {
                let sch = oneOf[i];
                if ((sch === null || sch === void 0 ? void 0 : sch.$ref) && !(0, util_1.schemaHasRulesButRef)(sch, it.self.RULES)) {
                    const ref = sch.$ref;
                    sch = compile_1.resolveRef.call(it.self, it.schemaEnv.root, it.baseId, ref);
                    if (sch instanceof compile_1.SchemaEnv)
                        sch = sch.schema;
                    if (sch === undefined)
                        throw new ref_error_1.default(it.opts.uriResolver, it.baseId, ref);
                }
                const propSch = (_a = sch === null || sch === void 0 ? void 0 : sch.properties) === null || _a === void 0 ? void 0 : _a[tagName];
                if (typeof propSch != "object") {
                    throw new Error(`discriminator: oneOf subschemas (or referenced schemas) must have "properties/${tagName}"`);
                }
                tagRequired = tagRequired && (topRequired || hasRequired(sch));
                addMappings(propSch, i);
            }
            if (!tagRequired)
                throw new Error(`discriminator: "${tagName}" must be required`);
            return oneOfMapping;
            function hasRequired({ required }) {
                return Array.isArray(required) && required.includes(tagName);
            }
            function addMappings(sch, i) {
                if (sch.const) {
                    addMapping(sch.const, i);
                }
                else if (sch.enum) {
                    for (const tagValue of sch.enum) {
                        addMapping(tagValue, i);
                    }
                }
                else {
                    throw new Error(`discriminator: "properties/${tagName}" must have "const" or "enum"`);
                }
            }
            function addMapping(tagValue, i) {
                if (typeof tagValue != "string" || tagValue in oneOfMapping) {
                    throw new Error(`discriminator: "${tagName}" values must be unique strings`);
                }
                oneOfMapping[tagValue] = i;
            }
        }
    },
};
discriminator.default = def;

var $schema = "http://json-schema.org/draft-07/schema#";
var $id = "http://json-schema.org/draft-07/schema#";
var title = "Core schema meta-schema";
var definitions = {
	schemaArray: {
		type: "array",
		minItems: 1,
		items: {
			$ref: "#"
		}
	},
	nonNegativeInteger: {
		type: "integer",
		minimum: 0
	},
	nonNegativeIntegerDefault0: {
		allOf: [
			{
				$ref: "#/definitions/nonNegativeInteger"
			},
			{
				"default": 0
			}
		]
	},
	simpleTypes: {
		"enum": [
			"array",
			"boolean",
			"integer",
			"null",
			"number",
			"object",
			"string"
		]
	},
	stringArray: {
		type: "array",
		items: {
			type: "string"
		},
		uniqueItems: true,
		"default": [
		]
	}
};
var type = [
	"object",
	"boolean"
];
var properties = {
	$id: {
		type: "string",
		format: "uri-reference"
	},
	$schema: {
		type: "string",
		format: "uri"
	},
	$ref: {
		type: "string",
		format: "uri-reference"
	},
	$comment: {
		type: "string"
	},
	title: {
		type: "string"
	},
	description: {
		type: "string"
	},
	"default": true,
	readOnly: {
		type: "boolean",
		"default": false
	},
	examples: {
		type: "array",
		items: true
	},
	multipleOf: {
		type: "number",
		exclusiveMinimum: 0
	},
	maximum: {
		type: "number"
	},
	exclusiveMaximum: {
		type: "number"
	},
	minimum: {
		type: "number"
	},
	exclusiveMinimum: {
		type: "number"
	},
	maxLength: {
		$ref: "#/definitions/nonNegativeInteger"
	},
	minLength: {
		$ref: "#/definitions/nonNegativeIntegerDefault0"
	},
	pattern: {
		type: "string",
		format: "regex"
	},
	additionalItems: {
		$ref: "#"
	},
	items: {
		anyOf: [
			{
				$ref: "#"
			},
			{
				$ref: "#/definitions/schemaArray"
			}
		],
		"default": true
	},
	maxItems: {
		$ref: "#/definitions/nonNegativeInteger"
	},
	minItems: {
		$ref: "#/definitions/nonNegativeIntegerDefault0"
	},
	uniqueItems: {
		type: "boolean",
		"default": false
	},
	contains: {
		$ref: "#"
	},
	maxProperties: {
		$ref: "#/definitions/nonNegativeInteger"
	},
	minProperties: {
		$ref: "#/definitions/nonNegativeIntegerDefault0"
	},
	required: {
		$ref: "#/definitions/stringArray"
	},
	additionalProperties: {
		$ref: "#"
	},
	definitions: {
		type: "object",
		additionalProperties: {
			$ref: "#"
		},
		"default": {
		}
	},
	properties: {
		type: "object",
		additionalProperties: {
			$ref: "#"
		},
		"default": {
		}
	},
	patternProperties: {
		type: "object",
		additionalProperties: {
			$ref: "#"
		},
		propertyNames: {
			format: "regex"
		},
		"default": {
		}
	},
	dependencies: {
		type: "object",
		additionalProperties: {
			anyOf: [
				{
					$ref: "#"
				},
				{
					$ref: "#/definitions/stringArray"
				}
			]
		}
	},
	propertyNames: {
		$ref: "#"
	},
	"const": true,
	"enum": {
		type: "array",
		items: true,
		minItems: 1,
		uniqueItems: true
	},
	type: {
		anyOf: [
			{
				$ref: "#/definitions/simpleTypes"
			},
			{
				type: "array",
				items: {
					$ref: "#/definitions/simpleTypes"
				},
				minItems: 1,
				uniqueItems: true
			}
		]
	},
	format: {
		type: "string"
	},
	contentMediaType: {
		type: "string"
	},
	contentEncoding: {
		type: "string"
	},
	"if": {
		$ref: "#"
	},
	then: {
		$ref: "#"
	},
	"else": {
		$ref: "#"
	},
	allOf: {
		$ref: "#/definitions/schemaArray"
	},
	anyOf: {
		$ref: "#/definitions/schemaArray"
	},
	oneOf: {
		$ref: "#/definitions/schemaArray"
	},
	not: {
		$ref: "#"
	}
};
var require$$3 = {
	$schema: $schema,
	$id: $id,
	title: title,
	definitions: definitions,
	type: type,
	properties: properties,
	"default": true
};

(function (module, exports) {
	Object.defineProperty(exports, "__esModule", { value: true });
	exports.MissingRefError = exports.ValidationError = exports.CodeGen = exports.Name = exports.nil = exports.stringify = exports.str = exports._ = exports.KeywordCxt = exports.Ajv = void 0;
	const core_1 = core$2;
	const draft7_1 = draft7;
	const discriminator_1 = discriminator;
	const draft7MetaSchema = require$$3;
	const META_SUPPORT_DATA = ["/properties"];
	const META_SCHEMA_ID = "http://json-schema.org/draft-07/schema";
	class Ajv extends core_1.default {
	    _addVocabularies() {
	        super._addVocabularies();
	        draft7_1.default.forEach((v) => this.addVocabulary(v));
	        if (this.opts.discriminator)
	            this.addKeyword(discriminator_1.default);
	    }
	    _addDefaultMetaSchema() {
	        super._addDefaultMetaSchema();
	        if (!this.opts.meta)
	            return;
	        const metaSchema = this.opts.$data
	            ? this.$dataMetaSchema(draft7MetaSchema, META_SUPPORT_DATA)
	            : draft7MetaSchema;
	        this.addMetaSchema(metaSchema, META_SCHEMA_ID, false);
	        this.refs["http://json-schema.org/schema"] = META_SCHEMA_ID;
	    }
	    defaultMeta() {
	        return (this.opts.defaultMeta =
	            super.defaultMeta() || (this.getSchema(META_SCHEMA_ID) ? META_SCHEMA_ID : undefined));
	    }
	}
	exports.Ajv = Ajv;
	module.exports = exports = Ajv;
	module.exports.Ajv = Ajv;
	Object.defineProperty(exports, "__esModule", { value: true });
	exports.default = Ajv;
	var validate_1 = requireValidate();
	Object.defineProperty(exports, "KeywordCxt", { enumerable: true, get: function () { return validate_1.KeywordCxt; } });
	var codegen_1 = requireCodegen();
	Object.defineProperty(exports, "_", { enumerable: true, get: function () { return codegen_1._; } });
	Object.defineProperty(exports, "str", { enumerable: true, get: function () { return codegen_1.str; } });
	Object.defineProperty(exports, "stringify", { enumerable: true, get: function () { return codegen_1.stringify; } });
	Object.defineProperty(exports, "nil", { enumerable: true, get: function () { return codegen_1.nil; } });
	Object.defineProperty(exports, "Name", { enumerable: true, get: function () { return codegen_1.Name; } });
	Object.defineProperty(exports, "CodeGen", { enumerable: true, get: function () { return codegen_1.CodeGen; } });
	var validation_error_1 = requireValidation_error();
	Object.defineProperty(exports, "ValidationError", { enumerable: true, get: function () { return validation_error_1.default; } });
	var ref_error_1 = requireRef_error();
	Object.defineProperty(exports, "MissingRefError", { enumerable: true, get: function () { return ref_error_1.default; } });
	
} (ajv, ajv.exports));

var ajvExports = ajv.exports;

const ALIAS = Symbol.for('yaml.alias');
const DOC = Symbol.for('yaml.document');
const MAP = Symbol.for('yaml.map');
const PAIR = Symbol.for('yaml.pair');
const SCALAR$1 = Symbol.for('yaml.scalar');
const SEQ = Symbol.for('yaml.seq');
const NODE_TYPE = Symbol.for('yaml.node.type');
const isAlias = (node) => !!node && typeof node === 'object' && node[NODE_TYPE] === ALIAS;
const isDocument = (node) => !!node && typeof node === 'object' && node[NODE_TYPE] === DOC;
const isMap = (node) => !!node && typeof node === 'object' && node[NODE_TYPE] === MAP;
const isPair = (node) => !!node && typeof node === 'object' && node[NODE_TYPE] === PAIR;
const isScalar = (node) => !!node && typeof node === 'object' && node[NODE_TYPE] === SCALAR$1;
const isSeq = (node) => !!node && typeof node === 'object' && node[NODE_TYPE] === SEQ;
function isCollection(node) {
    if (node && typeof node === 'object')
        switch (node[NODE_TYPE]) {
            case MAP:
            case SEQ:
                return true;
        }
    return false;
}
function isNode(node) {
    if (node && typeof node === 'object')
        switch (node[NODE_TYPE]) {
            case ALIAS:
            case MAP:
            case SCALAR$1:
            case SEQ:
                return true;
        }
    return false;
}
const hasAnchor = (node) => (isScalar(node) || isCollection(node)) && !!node.anchor;

const BREAK = Symbol('break visit');
const SKIP = Symbol('skip children');
const REMOVE = Symbol('remove node');
/**
 * Apply a visitor to an AST node or document.
 *
 * Walks through the tree (depth-first) starting from `node`, calling a
 * `visitor` function with three arguments:
 *   - `key`: For sequence values and map `Pair`, the node's index in the
 *     collection. Within a `Pair`, `'key'` or `'value'`, correspondingly.
 *     `null` for the root node.
 *   - `node`: The current node.
 *   - `path`: The ancestry of the current node.
 *
 * The return value of the visitor may be used to control the traversal:
 *   - `undefined` (default): Do nothing and continue
 *   - `visit.SKIP`: Do not visit the children of this node, continue with next
 *     sibling
 *   - `visit.BREAK`: Terminate traversal completely
 *   - `visit.REMOVE`: Remove the current node, then continue with the next one
 *   - `Node`: Replace the current node, then continue by visiting it
 *   - `number`: While iterating the items of a sequence or map, set the index
 *     of the next step. This is useful especially if the index of the current
 *     node has changed.
 *
 * If `visitor` is a single function, it will be called with all values
 * encountered in the tree, including e.g. `null` values. Alternatively,
 * separate visitor functions may be defined for each `Map`, `Pair`, `Seq`,
 * `Alias` and `Scalar` node. To define the same visitor function for more than
 * one node type, use the `Collection` (map and seq), `Value` (map, seq & scalar)
 * and `Node` (alias, map, seq & scalar) targets. Of all these, only the most
 * specific defined one will be used for each node.
 */
function visit(node, visitor) {
    const visitor_ = initVisitor(visitor);
    if (isDocument(node)) {
        const cd = visit_(null, node.contents, visitor_, Object.freeze([node]));
        if (cd === REMOVE)
            node.contents = null;
    }
    else
        visit_(null, node, visitor_, Object.freeze([]));
}
// Without the `as symbol` casts, TS declares these in the `visit`
// namespace using `var`, but then complains about that because
// `unique symbol` must be `const`.
/** Terminate visit traversal completely */
visit.BREAK = BREAK;
/** Do not visit the children of the current node */
visit.SKIP = SKIP;
/** Remove the current node */
visit.REMOVE = REMOVE;
function visit_(key, node, visitor, path) {
    const ctrl = callVisitor(key, node, visitor, path);
    if (isNode(ctrl) || isPair(ctrl)) {
        replaceNode(key, path, ctrl);
        return visit_(key, ctrl, visitor, path);
    }
    if (typeof ctrl !== 'symbol') {
        if (isCollection(node)) {
            path = Object.freeze(path.concat(node));
            for (let i = 0; i < node.items.length; ++i) {
                const ci = visit_(i, node.items[i], visitor, path);
                if (typeof ci === 'number')
                    i = ci - 1;
                else if (ci === BREAK)
                    return BREAK;
                else if (ci === REMOVE) {
                    node.items.splice(i, 1);
                    i -= 1;
                }
            }
        }
        else if (isPair(node)) {
            path = Object.freeze(path.concat(node));
            const ck = visit_('key', node.key, visitor, path);
            if (ck === BREAK)
                return BREAK;
            else if (ck === REMOVE)
                node.key = null;
            const cv = visit_('value', node.value, visitor, path);
            if (cv === BREAK)
                return BREAK;
            else if (cv === REMOVE)
                node.value = null;
        }
    }
    return ctrl;
}
function initVisitor(visitor) {
    if (typeof visitor === 'object' &&
        (visitor.Collection || visitor.Node || visitor.Value)) {
        return Object.assign({
            Alias: visitor.Node,
            Map: visitor.Node,
            Scalar: visitor.Node,
            Seq: visitor.Node
        }, visitor.Value && {
            Map: visitor.Value,
            Scalar: visitor.Value,
            Seq: visitor.Value
        }, visitor.Collection && {
            Map: visitor.Collection,
            Seq: visitor.Collection
        }, visitor);
    }
    return visitor;
}
function callVisitor(key, node, visitor, path) {
    if (typeof visitor === 'function')
        return visitor(key, node, path);
    if (isMap(node))
        return visitor.Map?.(key, node, path);
    if (isSeq(node))
        return visitor.Seq?.(key, node, path);
    if (isPair(node))
        return visitor.Pair?.(key, node, path);
    if (isScalar(node))
        return visitor.Scalar?.(key, node, path);
    if (isAlias(node))
        return visitor.Alias?.(key, node, path);
    return undefined;
}
function replaceNode(key, path, node) {
    const parent = path[path.length - 1];
    if (isCollection(parent)) {
        parent.items[key] = node;
    }
    else if (isPair(parent)) {
        if (key === 'key')
            parent.key = node;
        else
            parent.value = node;
    }
    else if (isDocument(parent)) {
        parent.contents = node;
    }
    else {
        const pt = isAlias(parent) ? 'alias' : 'scalar';
        throw new Error(`Cannot replace node with ${pt} parent`);
    }
}

const escapeChars = {
    '!': '%21',
    ',': '%2C',
    '[': '%5B',
    ']': '%5D',
    '{': '%7B',
    '}': '%7D'
};
const escapeTagName = (tn) => tn.replace(/[!,[\]{}]/g, ch => escapeChars[ch]);
class Directives {
    constructor(yaml, tags) {
        /**
         * The directives-end/doc-start marker `---`. If `null`, a marker may still be
         * included in the document's stringified representation.
         */
        this.docStart = null;
        /** The doc-end marker `...`.  */
        this.docEnd = false;
        this.yaml = Object.assign({}, Directives.defaultYaml, yaml);
        this.tags = Object.assign({}, Directives.defaultTags, tags);
    }
    clone() {
        const copy = new Directives(this.yaml, this.tags);
        copy.docStart = this.docStart;
        return copy;
    }
    /**
     * During parsing, get a Directives instance for the current document and
     * update the stream state according to the current version's spec.
     */
    atDocument() {
        const res = new Directives(this.yaml, this.tags);
        switch (this.yaml.version) {
            case '1.1':
                this.atNextDocument = true;
                break;
            case '1.2':
                this.atNextDocument = false;
                this.yaml = {
                    explicit: Directives.defaultYaml.explicit,
                    version: '1.2'
                };
                this.tags = Object.assign({}, Directives.defaultTags);
                break;
        }
        return res;
    }
    /**
     * @param onError - May be called even if the action was successful
     * @returns `true` on success
     */
    add(line, onError) {
        if (this.atNextDocument) {
            this.yaml = { explicit: Directives.defaultYaml.explicit, version: '1.1' };
            this.tags = Object.assign({}, Directives.defaultTags);
            this.atNextDocument = false;
        }
        const parts = line.trim().split(/[ \t]+/);
        const name = parts.shift();
        switch (name) {
            case '%TAG': {
                if (parts.length !== 2) {
                    onError(0, '%TAG directive should contain exactly two parts');
                    if (parts.length < 2)
                        return false;
                }
                const [handle, prefix] = parts;
                this.tags[handle] = prefix;
                return true;
            }
            case '%YAML': {
                this.yaml.explicit = true;
                if (parts.length !== 1) {
                    onError(0, '%YAML directive should contain exactly one part');
                    return false;
                }
                const [version] = parts;
                if (version === '1.1' || version === '1.2') {
                    this.yaml.version = version;
                    return true;
                }
                else {
                    const isValid = /^\d+\.\d+$/.test(version);
                    onError(6, `Unsupported YAML version ${version}`, isValid);
                    return false;
                }
            }
            default:
                onError(0, `Unknown directive ${name}`, true);
                return false;
        }
    }
    /**
     * Resolves a tag, matching handles to those defined in %TAG directives.
     *
     * @returns Resolved tag, which may also be the non-specific tag `'!'` or a
     *   `'!local'` tag, or `null` if unresolvable.
     */
    tagName(source, onError) {
        if (source === '!')
            return '!'; // non-specific tag
        if (source[0] !== '!') {
            onError(`Not a valid tag: ${source}`);
            return null;
        }
        if (source[1] === '<') {
            const verbatim = source.slice(2, -1);
            if (verbatim === '!' || verbatim === '!!') {
                onError(`Verbatim tags aren't resolved, so ${source} is invalid.`);
                return null;
            }
            if (source[source.length - 1] !== '>')
                onError('Verbatim tags must end with a >');
            return verbatim;
        }
        const [, handle, suffix] = source.match(/^(.*!)([^!]*)$/s);
        if (!suffix)
            onError(`The ${source} tag has no suffix`);
        const prefix = this.tags[handle];
        if (prefix) {
            try {
                return prefix + decodeURIComponent(suffix);
            }
            catch (error) {
                onError(String(error));
                return null;
            }
        }
        if (handle === '!')
            return source; // local tag
        onError(`Could not resolve tag: ${source}`);
        return null;
    }
    /**
     * Given a fully resolved tag, returns its printable string form,
     * taking into account current tag prefixes and defaults.
     */
    tagString(tag) {
        for (const [handle, prefix] of Object.entries(this.tags)) {
            if (tag.startsWith(prefix))
                return handle + escapeTagName(tag.substring(prefix.length));
        }
        return tag[0] === '!' ? tag : `!<${tag}>`;
    }
    toString(doc) {
        const lines = this.yaml.explicit
            ? [`%YAML ${this.yaml.version || '1.2'}`]
            : [];
        const tagEntries = Object.entries(this.tags);
        let tagNames;
        if (doc && tagEntries.length > 0 && isNode(doc.contents)) {
            const tags = {};
            visit(doc.contents, (_key, node) => {
                if (isNode(node) && node.tag)
                    tags[node.tag] = true;
            });
            tagNames = Object.keys(tags);
        }
        else
            tagNames = [];
        for (const [handle, prefix] of tagEntries) {
            if (handle === '!!' && prefix === 'tag:yaml.org,2002:')
                continue;
            if (!doc || tagNames.some(tn => tn.startsWith(prefix)))
                lines.push(`%TAG ${handle} ${prefix}`);
        }
        return lines.join('\n');
    }
}
Directives.defaultYaml = { explicit: false, version: '1.2' };
Directives.defaultTags = { '!!': 'tag:yaml.org,2002:' };

/**
 * Verify that the input string is a valid anchor.
 *
 * Will throw on errors.
 */
function anchorIsValid(anchor) {
    if (/[\x00-\x19\s,[\]{}]/.test(anchor)) {
        const sa = JSON.stringify(anchor);
        const msg = `Anchor must not contain whitespace or control characters: ${sa}`;
        throw new Error(msg);
    }
    return true;
}
function anchorNames(root) {
    const anchors = new Set();
    visit(root, {
        Value(_key, node) {
            if (node.anchor)
                anchors.add(node.anchor);
        }
    });
    return anchors;
}
/** Find a new anchor name with the given `prefix` and a one-indexed suffix. */
function findNewAnchor(prefix, exclude) {
    for (let i = 1; true; ++i) {
        const name = `${prefix}${i}`;
        if (!exclude.has(name))
            return name;
    }
}
function createNodeAnchors(doc, prefix) {
    const aliasObjects = [];
    const sourceObjects = new Map();
    let prevAnchors = null;
    return {
        onAnchor: (source) => {
            aliasObjects.push(source);
            if (!prevAnchors)
                prevAnchors = anchorNames(doc);
            const anchor = findNewAnchor(prefix, prevAnchors);
            prevAnchors.add(anchor);
            return anchor;
        },
        /**
         * With circular references, the source node is only resolved after all
         * of its child nodes are. This is why anchors are set only after all of
         * the nodes have been created.
         */
        setAnchors: () => {
            for (const source of aliasObjects) {
                const ref = sourceObjects.get(source);
                if (typeof ref === 'object' &&
                    ref.anchor &&
                    (isScalar(ref.node) || isCollection(ref.node))) {
                    ref.node.anchor = ref.anchor;
                }
                else {
                    const error = new Error('Failed to resolve repeated object (this should not happen)');
                    error.source = source;
                    throw error;
                }
            }
        },
        sourceObjects
    };
}

/**
 * Applies the JSON.parse reviver algorithm as defined in the ECMA-262 spec,
 * in section 24.5.1.1 "Runtime Semantics: InternalizeJSONProperty" of the
 * 2021 edition: https://tc39.es/ecma262/#sec-json.parse
 *
 * Includes extensions for handling Map and Set objects.
 */
function applyReviver(reviver, obj, key, val) {
    if (val && typeof val === 'object') {
        if (Array.isArray(val)) {
            for (let i = 0, len = val.length; i < len; ++i) {
                const v0 = val[i];
                const v1 = applyReviver(reviver, val, String(i), v0);
                if (v1 === undefined)
                    delete val[i];
                else if (v1 !== v0)
                    val[i] = v1;
            }
        }
        else if (val instanceof Map) {
            for (const k of Array.from(val.keys())) {
                const v0 = val.get(k);
                const v1 = applyReviver(reviver, val, k, v0);
                if (v1 === undefined)
                    val.delete(k);
                else if (v1 !== v0)
                    val.set(k, v1);
            }
        }
        else if (val instanceof Set) {
            for (const v0 of Array.from(val)) {
                const v1 = applyReviver(reviver, val, v0, v0);
                if (v1 === undefined)
                    val.delete(v0);
                else if (v1 !== v0) {
                    val.delete(v0);
                    val.add(v1);
                }
            }
        }
        else {
            for (const [k, v0] of Object.entries(val)) {
                const v1 = applyReviver(reviver, val, k, v0);
                if (v1 === undefined)
                    delete val[k];
                else if (v1 !== v0)
                    val[k] = v1;
            }
        }
    }
    return reviver.call(obj, key, val);
}

/**
 * Recursively convert any node or its contents to native JavaScript
 *
 * @param value - The input value
 * @param arg - If `value` defines a `toJSON()` method, use this
 *   as its first argument
 * @param ctx - Conversion context, originally set in Document#toJS(). If
 *   `{ keep: true }` is not set, output should be suitable for JSON
 *   stringification.
 */
function toJS(value, arg, ctx) {
    // eslint-disable-next-line @typescript-eslint/no-unsafe-return
    if (Array.isArray(value))
        return value.map((v, i) => toJS(v, String(i), ctx));
    if (value && typeof value.toJSON === 'function') {
        // eslint-disable-next-line @typescript-eslint/no-unsafe-call
        if (!ctx || !hasAnchor(value))
            return value.toJSON(arg, ctx);
        const data = { aliasCount: 0, count: 1, res: undefined };
        ctx.anchors.set(value, data);
        ctx.onCreate = res => {
            data.res = res;
            delete ctx.onCreate;
        };
        const res = value.toJSON(arg, ctx);
        if (ctx.onCreate)
            ctx.onCreate(res);
        return res;
    }
    if (typeof value === 'bigint' && !ctx?.keep)
        return Number(value);
    return value;
}

class NodeBase {
    constructor(type) {
        Object.defineProperty(this, NODE_TYPE, { value: type });
    }
    /** Create a copy of this node.  */
    clone() {
        const copy = Object.create(Object.getPrototypeOf(this), Object.getOwnPropertyDescriptors(this));
        if (this.range)
            copy.range = this.range.slice();
        return copy;
    }
    /** A plain JavaScript representation of this node. */
    toJS(doc, { mapAsMap, maxAliasCount, onAnchor, reviver } = {}) {
        if (!isDocument(doc))
            throw new TypeError('A document argument is required');
        const ctx = {
            anchors: new Map(),
            doc,
            keep: true,
            mapAsMap: mapAsMap === true,
            mapKeyWarned: false,
            maxAliasCount: typeof maxAliasCount === 'number' ? maxAliasCount : 100
        };
        const res = toJS(this, '', ctx);
        if (typeof onAnchor === 'function')
            for (const { count, res } of ctx.anchors.values())
                onAnchor(res, count);
        return typeof reviver === 'function'
            ? applyReviver(reviver, { '': res }, '', res)
            : res;
    }
}

class Alias extends NodeBase {
    constructor(source) {
        super(ALIAS);
        this.source = source;
        Object.defineProperty(this, 'tag', {
            set() {
                throw new Error('Alias nodes cannot have tags');
            }
        });
    }
    /**
     * Resolve the value of this alias within `doc`, finding the last
     * instance of the `source` anchor before this node.
     */
    resolve(doc) {
        let found = undefined;
        visit(doc, {
            Node: (_key, node) => {
                if (node === this)
                    return visit.BREAK;
                if (node.anchor === this.source)
                    found = node;
            }
        });
        return found;
    }
    toJSON(_arg, ctx) {
        if (!ctx)
            return { source: this.source };
        const { anchors, doc, maxAliasCount } = ctx;
        const source = this.resolve(doc);
        if (!source) {
            const msg = `Unresolved alias (the anchor must be set before the alias): ${this.source}`;
            throw new ReferenceError(msg);
        }
        let data = anchors.get(source);
        if (!data) {
            // Resolve anchors for Node.prototype.toJS()
            toJS(source, null, ctx);
            data = anchors.get(source);
        }
        /* istanbul ignore if */
        if (!data || data.res === undefined) {
            const msg = 'This should not happen: Alias anchor was not resolved?';
            throw new ReferenceError(msg);
        }
        if (maxAliasCount >= 0) {
            data.count += 1;
            if (data.aliasCount === 0)
                data.aliasCount = getAliasCount(doc, source, anchors);
            if (data.count * data.aliasCount > maxAliasCount) {
                const msg = 'Excessive alias count indicates a resource exhaustion attack';
                throw new ReferenceError(msg);
            }
        }
        return data.res;
    }
    toString(ctx, _onComment, _onChompKeep) {
        const src = `*${this.source}`;
        if (ctx) {
            anchorIsValid(this.source);
            if (ctx.options.verifyAliasOrder && !ctx.anchors.has(this.source)) {
                const msg = `Unresolved alias (the anchor must be set before the alias): ${this.source}`;
                throw new Error(msg);
            }
            if (ctx.implicitKey)
                return `${src} `;
        }
        return src;
    }
}
function getAliasCount(doc, node, anchors) {
    if (isAlias(node)) {
        const source = node.resolve(doc);
        const anchor = anchors && source && anchors.get(source);
        return anchor ? anchor.count * anchor.aliasCount : 0;
    }
    else if (isCollection(node)) {
        let count = 0;
        for (const item of node.items) {
            const c = getAliasCount(doc, item, anchors);
            if (c > count)
                count = c;
        }
        return count;
    }
    else if (isPair(node)) {
        const kc = getAliasCount(doc, node.key, anchors);
        const vc = getAliasCount(doc, node.value, anchors);
        return Math.max(kc, vc);
    }
    return 1;
}

const isScalarValue = (value) => !value || (typeof value !== 'function' && typeof value !== 'object');
class Scalar extends NodeBase {
    constructor(value) {
        super(SCALAR$1);
        this.value = value;
    }
    toJSON(arg, ctx) {
        return ctx?.keep ? this.value : toJS(this.value, arg, ctx);
    }
    toString() {
        return String(this.value);
    }
}
Scalar.BLOCK_FOLDED = 'BLOCK_FOLDED';
Scalar.BLOCK_LITERAL = 'BLOCK_LITERAL';
Scalar.PLAIN = 'PLAIN';
Scalar.QUOTE_DOUBLE = 'QUOTE_DOUBLE';
Scalar.QUOTE_SINGLE = 'QUOTE_SINGLE';

const defaultTagPrefix = 'tag:yaml.org,2002:';
function findTagObject(value, tagName, tags) {
    if (tagName) {
        const match = tags.filter(t => t.tag === tagName);
        const tagObj = match.find(t => !t.format) ?? match[0];
        if (!tagObj)
            throw new Error(`Tag ${tagName} not found`);
        return tagObj;
    }
    return tags.find(t => t.identify?.(value) && !t.format);
}
function createNode(value, tagName, ctx) {
    if (isDocument(value))
        value = value.contents;
    if (isNode(value))
        return value;
    if (isPair(value)) {
        const map = ctx.schema[MAP].createNode?.(ctx.schema, null, ctx);
        map.items.push(value);
        return map;
    }
    if (value instanceof String ||
        value instanceof Number ||
        value instanceof Boolean ||
        (typeof BigInt !== 'undefined' && value instanceof BigInt) // not supported everywhere
    ) {
        // https://tc39.es/ecma262/#sec-serializejsonproperty
        value = value.valueOf();
    }
    const { aliasDuplicateObjects, onAnchor, onTagObj, schema, sourceObjects } = ctx;
    // Detect duplicate references to the same object & use Alias nodes for all
    // after first. The `ref` wrapper allows for circular references to resolve.
    let ref = undefined;
    if (aliasDuplicateObjects && value && typeof value === 'object') {
        ref = sourceObjects.get(value);
        if (ref) {
            if (!ref.anchor)
                ref.anchor = onAnchor(value);
            return new Alias(ref.anchor);
        }
        else {
            ref = { anchor: null, node: null };
            sourceObjects.set(value, ref);
        }
    }
    if (tagName?.startsWith('!!'))
        tagName = defaultTagPrefix + tagName.slice(2);
    let tagObj = findTagObject(value, tagName, schema.tags);
    if (!tagObj) {
        if (value && typeof value.toJSON === 'function') {
            // eslint-disable-next-line @typescript-eslint/no-unsafe-call
            value = value.toJSON();
        }
        if (!value || typeof value !== 'object') {
            const node = new Scalar(value);
            if (ref)
                ref.node = node;
            return node;
        }
        tagObj =
            value instanceof Map
                ? schema[MAP]
                : Symbol.iterator in Object(value)
                    ? schema[SEQ]
                    : schema[MAP];
    }
    if (onTagObj) {
        onTagObj(tagObj);
        delete ctx.onTagObj;
    }
    const node = tagObj?.createNode
        ? tagObj.createNode(ctx.schema, value, ctx)
        : typeof tagObj?.nodeClass?.from === 'function'
            ? tagObj.nodeClass.from(ctx.schema, value, ctx)
            : new Scalar(value);
    if (tagName)
        node.tag = tagName;
    else if (!tagObj.default)
        node.tag = tagObj.tag;
    if (ref)
        ref.node = node;
    return node;
}

function collectionFromPath(schema, path, value) {
    let v = value;
    for (let i = path.length - 1; i >= 0; --i) {
        const k = path[i];
        if (typeof k === 'number' && Number.isInteger(k) && k >= 0) {
            const a = [];
            a[k] = v;
            v = a;
        }
        else {
            v = new Map([[k, v]]);
        }
    }
    return createNode(v, undefined, {
        aliasDuplicateObjects: false,
        keepUndefined: false,
        onAnchor: () => {
            throw new Error('This should not happen, please report a bug.');
        },
        schema,
        sourceObjects: new Map()
    });
}
// Type guard is intentionally a little wrong so as to be more useful,
// as it does not cover untypable empty non-string iterables (e.g. []).
const isEmptyPath = (path) => path == null ||
    (typeof path === 'object' && !!path[Symbol.iterator]().next().done);
class Collection extends NodeBase {
    constructor(type, schema) {
        super(type);
        Object.defineProperty(this, 'schema', {
            value: schema,
            configurable: true,
            enumerable: false,
            writable: true
        });
    }
    /**
     * Create a copy of this collection.
     *
     * @param schema - If defined, overwrites the original's schema
     */
    clone(schema) {
        const copy = Object.create(Object.getPrototypeOf(this), Object.getOwnPropertyDescriptors(this));
        if (schema)
            copy.schema = schema;
        copy.items = copy.items.map(it => isNode(it) || isPair(it) ? it.clone(schema) : it);
        if (this.range)
            copy.range = this.range.slice();
        return copy;
    }
    /**
     * Adds a value to the collection. For `!!map` and `!!omap` the value must
     * be a Pair instance or a `{ key, value }` object, which may not have a key
     * that already exists in the map.
     */
    addIn(path, value) {
        if (isEmptyPath(path))
            this.add(value);
        else {
            const [key, ...rest] = path;
            const node = this.get(key, true);
            if (isCollection(node))
                node.addIn(rest, value);
            else if (node === undefined && this.schema)
                this.set(key, collectionFromPath(this.schema, rest, value));
            else
                throw new Error(`Expected YAML collection at ${key}. Remaining path: ${rest}`);
        }
    }
    /**
     * Removes a value from the collection.
     * @returns `true` if the item was found and removed.
     */
    deleteIn(path) {
        const [key, ...rest] = path;
        if (rest.length === 0)
            return this.delete(key);
        const node = this.get(key, true);
        if (isCollection(node))
            return node.deleteIn(rest);
        else
            throw new Error(`Expected YAML collection at ${key}. Remaining path: ${rest}`);
    }
    /**
     * Returns item at `key`, or `undefined` if not found. By default unwraps
     * scalar values from their surrounding node; to disable set `keepScalar` to
     * `true` (collections are always returned intact).
     */
    getIn(path, keepScalar) {
        const [key, ...rest] = path;
        const node = this.get(key, true);
        if (rest.length === 0)
            return !keepScalar && isScalar(node) ? node.value : node;
        else
            return isCollection(node) ? node.getIn(rest, keepScalar) : undefined;
    }
    hasAllNullValues(allowScalar) {
        return this.items.every(node => {
            if (!isPair(node))
                return false;
            const n = node.value;
            return (n == null ||
                (allowScalar &&
                    isScalar(n) &&
                    n.value == null &&
                    !n.commentBefore &&
                    !n.comment &&
                    !n.tag));
        });
    }
    /**
     * Checks if the collection includes a value with the key `key`.
     */
    hasIn(path) {
        const [key, ...rest] = path;
        if (rest.length === 0)
            return this.has(key);
        const node = this.get(key, true);
        return isCollection(node) ? node.hasIn(rest) : false;
    }
    /**
     * Sets a value in this collection. For `!!set`, `value` needs to be a
     * boolean to add/remove the item from the set.
     */
    setIn(path, value) {
        const [key, ...rest] = path;
        if (rest.length === 0) {
            this.set(key, value);
        }
        else {
            const node = this.get(key, true);
            if (isCollection(node))
                node.setIn(rest, value);
            else if (node === undefined && this.schema)
                this.set(key, collectionFromPath(this.schema, rest, value));
            else
                throw new Error(`Expected YAML collection at ${key}. Remaining path: ${rest}`);
        }
    }
}
Collection.maxFlowStringSingleLineLength = 60;

/**
 * Stringifies a comment.
 *
 * Empty comment lines are left empty,
 * lines consisting of a single space are replaced by `#`,
 * and all other lines are prefixed with a `#`.
 */
const stringifyComment = (str) => str.replace(/^(?!$)(?: $)?/gm, '#');
function indentComment(comment, indent) {
    if (/^\n+$/.test(comment))
        return comment.substring(1);
    return indent ? comment.replace(/^(?! *$)/gm, indent) : comment;
}
const lineComment = (str, indent, comment) => str.endsWith('\n')
    ? indentComment(comment, indent)
    : comment.includes('\n')
        ? '\n' + indentComment(comment, indent)
        : (str.endsWith(' ') ? '' : ' ') + comment;

const FOLD_FLOW = 'flow';
const FOLD_BLOCK = 'block';
const FOLD_QUOTED = 'quoted';
/**
 * Tries to keep input at up to `lineWidth` characters, splitting only on spaces
 * not followed by newlines or spaces unless `mode` is `'quoted'`. Lines are
 * terminated with `\n` and started with `indent`.
 */
function foldFlowLines(text, indent, mode = 'flow', { indentAtStart, lineWidth = 80, minContentWidth = 20, onFold, onOverflow } = {}) {
    if (!lineWidth || lineWidth < 0)
        return text;
    const endStep = Math.max(1 + minContentWidth, 1 + lineWidth - indent.length);
    if (text.length <= endStep)
        return text;
    const folds = [];
    const escapedFolds = {};
    let end = lineWidth - indent.length;
    if (typeof indentAtStart === 'number') {
        if (indentAtStart > lineWidth - Math.max(2, minContentWidth))
            folds.push(0);
        else
            end = lineWidth - indentAtStart;
    }
    let split = undefined;
    let prev = undefined;
    let overflow = false;
    let i = -1;
    let escStart = -1;
    let escEnd = -1;
    if (mode === FOLD_BLOCK) {
        i = consumeMoreIndentedLines(text, i, indent.length);
        if (i !== -1)
            end = i + endStep;
    }
    for (let ch; (ch = text[(i += 1)]);) {
        if (mode === FOLD_QUOTED && ch === '\\') {
            escStart = i;
            switch (text[i + 1]) {
                case 'x':
                    i += 3;
                    break;
                case 'u':
                    i += 5;
                    break;
                case 'U':
                    i += 9;
                    break;
                default:
                    i += 1;
            }
            escEnd = i;
        }
        if (ch === '\n') {
            if (mode === FOLD_BLOCK)
                i = consumeMoreIndentedLines(text, i, indent.length);
            end = i + indent.length + endStep;
            split = undefined;
        }
        else {
            if (ch === ' ' &&
                prev &&
                prev !== ' ' &&
                prev !== '\n' &&
                prev !== '\t') {
                // space surrounded by non-space can be replaced with newline + indent
                const next = text[i + 1];
                if (next && next !== ' ' && next !== '\n' && next !== '\t')
                    split = i;
            }
            if (i >= end) {
                if (split) {
                    folds.push(split);
                    end = split + endStep;
                    split = undefined;
                }
                else if (mode === FOLD_QUOTED) {
                    // white-space collected at end may stretch past lineWidth
                    while (prev === ' ' || prev === '\t') {
                        prev = ch;
                        ch = text[(i += 1)];
                        overflow = true;
                    }
                    // Account for newline escape, but don't break preceding escape
                    const j = i > escEnd + 1 ? i - 2 : escStart - 1;
                    // Bail out if lineWidth & minContentWidth are shorter than an escape string
                    if (escapedFolds[j])
                        return text;
                    folds.push(j);
                    escapedFolds[j] = true;
                    end = j + endStep;
                    split = undefined;
                }
                else {
                    overflow = true;
                }
            }
        }
        prev = ch;
    }
    if (overflow && onOverflow)
        onOverflow();
    if (folds.length === 0)
        return text;
    if (onFold)
        onFold();
    let res = text.slice(0, folds[0]);
    for (let i = 0; i < folds.length; ++i) {
        const fold = folds[i];
        const end = folds[i + 1] || text.length;
        if (fold === 0)
            res = `\n${indent}${text.slice(0, end)}`;
        else {
            if (mode === FOLD_QUOTED && escapedFolds[fold])
                res += `${text[fold]}\\`;
            res += `\n${indent}${text.slice(fold + 1, end)}`;
        }
    }
    return res;
}
/**
 * Presumes `i + 1` is at the start of a line
 * @returns index of last newline in more-indented block
 */
function consumeMoreIndentedLines(text, i, indent) {
    let end = i;
    let start = i + 1;
    let ch = text[start];
    while (ch === ' ' || ch === '\t') {
        if (i < start + indent) {
            ch = text[++i];
        }
        else {
            do {
                ch = text[++i];
            } while (ch && ch !== '\n');
            end = i;
            start = i + 1;
            ch = text[start];
        }
    }
    return end;
}

const getFoldOptions = (ctx, isBlock) => ({
    indentAtStart: isBlock ? ctx.indent.length : ctx.indentAtStart,
    lineWidth: ctx.options.lineWidth,
    minContentWidth: ctx.options.minContentWidth
});
// Also checks for lines starting with %, as parsing the output as YAML 1.1 will
// presume that's starting a new document.
const containsDocumentMarker = (str) => /^(%|---|\.\.\.)/m.test(str);
function lineLengthOverLimit(str, lineWidth, indentLength) {
    if (!lineWidth || lineWidth < 0)
        return false;
    const limit = lineWidth - indentLength;
    const strLen = str.length;
    if (strLen <= limit)
        return false;
    for (let i = 0, start = 0; i < strLen; ++i) {
        if (str[i] === '\n') {
            if (i - start > limit)
                return true;
            start = i + 1;
            if (strLen - start <= limit)
                return false;
        }
    }
    return true;
}
function doubleQuotedString(value, ctx) {
    const json = JSON.stringify(value);
    if (ctx.options.doubleQuotedAsJSON)
        return json;
    const { implicitKey } = ctx;
    const minMultiLineLength = ctx.options.doubleQuotedMinMultiLineLength;
    const indent = ctx.indent || (containsDocumentMarker(value) ? '  ' : '');
    let str = '';
    let start = 0;
    for (let i = 0, ch = json[i]; ch; ch = json[++i]) {
        if (ch === ' ' && json[i + 1] === '\\' && json[i + 2] === 'n') {
            // space before newline needs to be escaped to not be folded
            str += json.slice(start, i) + '\\ ';
            i += 1;
            start = i;
            ch = '\\';
        }
        if (ch === '\\')
            switch (json[i + 1]) {
                case 'u':
                    {
                        str += json.slice(start, i);
                        const code = json.substr(i + 2, 4);
                        switch (code) {
                            case '0000':
                                str += '\\0';
                                break;
                            case '0007':
                                str += '\\a';
                                break;
                            case '000b':
                                str += '\\v';
                                break;
                            case '001b':
                                str += '\\e';
                                break;
                            case '0085':
                                str += '\\N';
                                break;
                            case '00a0':
                                str += '\\_';
                                break;
                            case '2028':
                                str += '\\L';
                                break;
                            case '2029':
                                str += '\\P';
                                break;
                            default:
                                if (code.substr(0, 2) === '00')
                                    str += '\\x' + code.substr(2);
                                else
                                    str += json.substr(i, 6);
                        }
                        i += 5;
                        start = i + 1;
                    }
                    break;
                case 'n':
                    if (implicitKey ||
                        json[i + 2] === '"' ||
                        json.length < minMultiLineLength) {
                        i += 1;
                    }
                    else {
                        // folding will eat first newline
                        str += json.slice(start, i) + '\n\n';
                        while (json[i + 2] === '\\' &&
                            json[i + 3] === 'n' &&
                            json[i + 4] !== '"') {
                            str += '\n';
                            i += 2;
                        }
                        str += indent;
                        // space after newline needs to be escaped to not be folded
                        if (json[i + 2] === ' ')
                            str += '\\';
                        i += 1;
                        start = i + 1;
                    }
                    break;
                default:
                    i += 1;
            }
    }
    str = start ? str + json.slice(start) : json;
    return implicitKey
        ? str
        : foldFlowLines(str, indent, FOLD_QUOTED, getFoldOptions(ctx, false));
}
function singleQuotedString(value, ctx) {
    if (ctx.options.singleQuote === false ||
        (ctx.implicitKey && value.includes('\n')) ||
        /[ \t]\n|\n[ \t]/.test(value) // single quoted string can't have leading or trailing whitespace around newline
    )
        return doubleQuotedString(value, ctx);
    const indent = ctx.indent || (containsDocumentMarker(value) ? '  ' : '');
    const res = "'" + value.replace(/'/g, "''").replace(/\n+/g, `$&\n${indent}`) + "'";
    return ctx.implicitKey
        ? res
        : foldFlowLines(res, indent, FOLD_FLOW, getFoldOptions(ctx, false));
}
function quotedString(value, ctx) {
    const { singleQuote } = ctx.options;
    let qs;
    if (singleQuote === false)
        qs = doubleQuotedString;
    else {
        const hasDouble = value.includes('"');
        const hasSingle = value.includes("'");
        if (hasDouble && !hasSingle)
            qs = singleQuotedString;
        else if (hasSingle && !hasDouble)
            qs = doubleQuotedString;
        else
            qs = singleQuote ? singleQuotedString : doubleQuotedString;
    }
    return qs(value, ctx);
}
// The negative lookbehind avoids a polynomial search,
// but isn't supported yet on Safari: https://caniuse.com/js-regexp-lookbehind
let blockEndNewlines;
try {
    blockEndNewlines = new RegExp('(^|(?<!\n))\n+(?!\n|$)', 'g');
}
catch {
    blockEndNewlines = /\n+(?!\n|$)/g;
}
function blockString({ comment, type, value }, ctx, onComment, onChompKeep) {
    const { blockQuote, commentString, lineWidth } = ctx.options;
    // 1. Block can't end in whitespace unless the last line is non-empty.
    // 2. Strings consisting of only whitespace are best rendered explicitly.
    if (!blockQuote || /\n[\t ]+$/.test(value) || /^\s*$/.test(value)) {
        return quotedString(value, ctx);
    }
    const indent = ctx.indent ||
        (ctx.forceBlockIndent || containsDocumentMarker(value) ? '  ' : '');
    const literal = blockQuote === 'literal'
        ? true
        : blockQuote === 'folded' || type === Scalar.BLOCK_FOLDED
            ? false
            : type === Scalar.BLOCK_LITERAL
                ? true
                : !lineLengthOverLimit(value, lineWidth, indent.length);
    if (!value)
        return literal ? '|\n' : '>\n';
    // determine chomping from whitespace at value end
    let chomp;
    let endStart;
    for (endStart = value.length; endStart > 0; --endStart) {
        const ch = value[endStart - 1];
        if (ch !== '\n' && ch !== '\t' && ch !== ' ')
            break;
    }
    let end = value.substring(endStart);
    const endNlPos = end.indexOf('\n');
    if (endNlPos === -1) {
        chomp = '-'; // strip
    }
    else if (value === end || endNlPos !== end.length - 1) {
        chomp = '+'; // keep
        if (onChompKeep)
            onChompKeep();
    }
    else {
        chomp = ''; // clip
    }
    if (end) {
        value = value.slice(0, -end.length);
        if (end[end.length - 1] === '\n')
            end = end.slice(0, -1);
        end = end.replace(blockEndNewlines, `$&${indent}`);
    }
    // determine indent indicator from whitespace at value start
    let startWithSpace = false;
    let startEnd;
    let startNlPos = -1;
    for (startEnd = 0; startEnd < value.length; ++startEnd) {
        const ch = value[startEnd];
        if (ch === ' ')
            startWithSpace = true;
        else if (ch === '\n')
            startNlPos = startEnd;
        else
            break;
    }
    let start = value.substring(0, startNlPos < startEnd ? startNlPos + 1 : startEnd);
    if (start) {
        value = value.substring(start.length);
        start = start.replace(/\n+/g, `$&${indent}`);
    }
    const indentSize = indent ? '2' : '1'; // root is at -1
    let header = (literal ? '|' : '>') + (startWithSpace ? indentSize : '') + chomp;
    if (comment) {
        header += ' ' + commentString(comment.replace(/ ?[\r\n]+/g, ' '));
        if (onComment)
            onComment();
    }
    if (literal) {
        value = value.replace(/\n+/g, `$&${indent}`);
        return `${header}\n${indent}${start}${value}${end}`;
    }
    value = value
        .replace(/\n+/g, '\n$&')
        .replace(/(?:^|\n)([\t ].*)(?:([\n\t ]*)\n(?![\n\t ]))?/g, '$1$2') // more-indented lines aren't folded
        //                ^ more-ind. ^ empty     ^ capture next empty lines only at end of indent
        .replace(/\n+/g, `$&${indent}`);
    const body = foldFlowLines(`${start}${value}${end}`, indent, FOLD_BLOCK, getFoldOptions(ctx, true));
    return `${header}\n${indent}${body}`;
}
function plainString(item, ctx, onComment, onChompKeep) {
    const { type, value } = item;
    const { actualString, implicitKey, indent, indentStep, inFlow } = ctx;
    if ((implicitKey && value.includes('\n')) ||
        (inFlow && /[[\]{},]/.test(value))) {
        return quotedString(value, ctx);
    }
    if (!value ||
        /^[\n\t ,[\]{}#&*!|>'"%@`]|^[?-]$|^[?-][ \t]|[\n:][ \t]|[ \t]\n|[\n\t ]#|[\n\t :]$/.test(value)) {
        // not allowed:
        // - empty string, '-' or '?'
        // - start with an indicator character (except [?:-]) or /[?-] /
        // - '\n ', ': ' or ' \n' anywhere
        // - '#' not preceded by a non-space char
        // - end with ' ' or ':'
        return implicitKey || inFlow || !value.includes('\n')
            ? quotedString(value, ctx)
            : blockString(item, ctx, onComment, onChompKeep);
    }
    if (!implicitKey &&
        !inFlow &&
        type !== Scalar.PLAIN &&
        value.includes('\n')) {
        // Where allowed & type not set explicitly, prefer block style for multiline strings
        return blockString(item, ctx, onComment, onChompKeep);
    }
    if (containsDocumentMarker(value)) {
        if (indent === '') {
            ctx.forceBlockIndent = true;
            return blockString(item, ctx, onComment, onChompKeep);
        }
        else if (implicitKey && indent === indentStep) {
            return quotedString(value, ctx);
        }
    }
    const str = value.replace(/\n+/g, `$&\n${indent}`);
    // Verify that output will be parsed as a string, as e.g. plain numbers and
    // booleans get parsed with those types in v1.2 (e.g. '42', 'true' & '0.9e-3'),
    // and others in v1.1.
    if (actualString) {
        const test = (tag) => tag.default && tag.tag !== 'tag:yaml.org,2002:str' && tag.test?.test(str);
        const { compat, tags } = ctx.doc.schema;
        if (tags.some(test) || compat?.some(test))
            return quotedString(value, ctx);
    }
    return implicitKey
        ? str
        : foldFlowLines(str, indent, FOLD_FLOW, getFoldOptions(ctx, false));
}
function stringifyString(item, ctx, onComment, onChompKeep) {
    const { implicitKey, inFlow } = ctx;
    const ss = typeof item.value === 'string'
        ? item
        : Object.assign({}, item, { value: String(item.value) });
    let { type } = item;
    if (type !== Scalar.QUOTE_DOUBLE) {
        // force double quotes on control characters & unpaired surrogates
        if (/[\x00-\x08\x0b-\x1f\x7f-\x9f\u{D800}-\u{DFFF}]/u.test(ss.value))
            type = Scalar.QUOTE_DOUBLE;
    }
    const _stringify = (_type) => {
        switch (_type) {
            case Scalar.BLOCK_FOLDED:
            case Scalar.BLOCK_LITERAL:
                return implicitKey || inFlow
                    ? quotedString(ss.value, ctx) // blocks are not valid inside flow containers
                    : blockString(ss, ctx, onComment, onChompKeep);
            case Scalar.QUOTE_DOUBLE:
                return doubleQuotedString(ss.value, ctx);
            case Scalar.QUOTE_SINGLE:
                return singleQuotedString(ss.value, ctx);
            case Scalar.PLAIN:
                return plainString(ss, ctx, onComment, onChompKeep);
            default:
                return null;
        }
    };
    let res = _stringify(type);
    if (res === null) {
        const { defaultKeyType, defaultStringType } = ctx.options;
        const t = (implicitKey && defaultKeyType) || defaultStringType;
        res = _stringify(t);
        if (res === null)
            throw new Error(`Unsupported default string type ${t}`);
    }
    return res;
}

function createStringifyContext(doc, options) {
    const opt = Object.assign({
        blockQuote: true,
        commentString: stringifyComment,
        defaultKeyType: null,
        defaultStringType: 'PLAIN',
        directives: null,
        doubleQuotedAsJSON: false,
        doubleQuotedMinMultiLineLength: 40,
        falseStr: 'false',
        flowCollectionPadding: true,
        indentSeq: true,
        lineWidth: 80,
        minContentWidth: 20,
        nullStr: 'null',
        simpleKeys: false,
        singleQuote: null,
        trueStr: 'true',
        verifyAliasOrder: true
    }, doc.schema.toStringOptions, options);
    let inFlow;
    switch (opt.collectionStyle) {
        case 'block':
            inFlow = false;
            break;
        case 'flow':
            inFlow = true;
            break;
        default:
            inFlow = null;
    }
    return {
        anchors: new Set(),
        doc,
        flowCollectionPadding: opt.flowCollectionPadding ? ' ' : '',
        indent: '',
        indentStep: typeof opt.indent === 'number' ? ' '.repeat(opt.indent) : '  ',
        inFlow,
        options: opt
    };
}
function getTagObject(tags, item) {
    if (item.tag) {
        const match = tags.filter(t => t.tag === item.tag);
        if (match.length > 0)
            return match.find(t => t.format === item.format) ?? match[0];
    }
    let tagObj = undefined;
    let obj;
    if (isScalar(item)) {
        obj = item.value;
        const match = tags.filter(t => t.identify?.(obj));
        tagObj =
            match.find(t => t.format === item.format) ?? match.find(t => !t.format);
    }
    else {
        obj = item;
        tagObj = tags.find(t => t.nodeClass && obj instanceof t.nodeClass);
    }
    if (!tagObj) {
        const name = obj?.constructor?.name ?? typeof obj;
        throw new Error(`Tag not resolved for ${name} value`);
    }
    return tagObj;
}
// needs to be called before value stringifier to allow for circular anchor refs
function stringifyProps(node, tagObj, { anchors, doc }) {
    if (!doc.directives)
        return '';
    const props = [];
    const anchor = (isScalar(node) || isCollection(node)) && node.anchor;
    if (anchor && anchorIsValid(anchor)) {
        anchors.add(anchor);
        props.push(`&${anchor}`);
    }
    const tag = node.tag ? node.tag : tagObj.default ? null : tagObj.tag;
    if (tag)
        props.push(doc.directives.tagString(tag));
    return props.join(' ');
}
function stringify$1(item, ctx, onComment, onChompKeep) {
    if (isPair(item))
        return item.toString(ctx, onComment, onChompKeep);
    if (isAlias(item)) {
        if (ctx.doc.directives)
            return item.toString(ctx);
        if (ctx.resolvedAliases?.has(item)) {
            throw new TypeError(`Cannot stringify circular structure without alias nodes`);
        }
        else {
            if (ctx.resolvedAliases)
                ctx.resolvedAliases.add(item);
            else
                ctx.resolvedAliases = new Set([item]);
            item = item.resolve(ctx.doc);
        }
    }
    let tagObj = undefined;
    const node = isNode(item)
        ? item
        : ctx.doc.createNode(item, { onTagObj: o => (tagObj = o) });
    if (!tagObj)
        tagObj = getTagObject(ctx.doc.schema.tags, node);
    const props = stringifyProps(node, tagObj, ctx);
    if (props.length > 0)
        ctx.indentAtStart = (ctx.indentAtStart ?? 0) + props.length + 1;
    const str = typeof tagObj.stringify === 'function'
        ? tagObj.stringify(node, ctx, onComment, onChompKeep)
        : isScalar(node)
            ? stringifyString(node, ctx, onComment, onChompKeep)
            : node.toString(ctx, onComment, onChompKeep);
    if (!props)
        return str;
    return isScalar(node) || str[0] === '{' || str[0] === '['
        ? `${props} ${str}`
        : `${props}\n${ctx.indent}${str}`;
}

function stringifyPair({ key, value }, ctx, onComment, onChompKeep) {
    const { allNullValues, doc, indent, indentStep, options: { commentString, indentSeq, simpleKeys } } = ctx;
    let keyComment = (isNode(key) && key.comment) || null;
    if (simpleKeys) {
        if (keyComment) {
            throw new Error('With simple keys, key nodes cannot have comments');
        }
        if (isCollection(key) || (!isNode(key) && typeof key === 'object')) {
            const msg = 'With simple keys, collection cannot be used as a key value';
            throw new Error(msg);
        }
    }
    let explicitKey = !simpleKeys &&
        (!key ||
            (keyComment && value == null && !ctx.inFlow) ||
            isCollection(key) ||
            (isScalar(key)
                ? key.type === Scalar.BLOCK_FOLDED || key.type === Scalar.BLOCK_LITERAL
                : typeof key === 'object'));
    ctx = Object.assign({}, ctx, {
        allNullValues: false,
        implicitKey: !explicitKey && (simpleKeys || !allNullValues),
        indent: indent + indentStep
    });
    let keyCommentDone = false;
    let chompKeep = false;
    let str = stringify$1(key, ctx, () => (keyCommentDone = true), () => (chompKeep = true));
    if (!explicitKey && !ctx.inFlow && str.length > 1024) {
        if (simpleKeys)
            throw new Error('With simple keys, single line scalar must not span more than 1024 characters');
        explicitKey = true;
    }
    if (ctx.inFlow) {
        if (allNullValues || value == null) {
            if (keyCommentDone && onComment)
                onComment();
            return str === '' ? '?' : explicitKey ? `? ${str}` : str;
        }
    }
    else if ((allNullValues && !simpleKeys) || (value == null && explicitKey)) {
        str = `? ${str}`;
        if (keyComment && !keyCommentDone) {
            str += lineComment(str, ctx.indent, commentString(keyComment));
        }
        else if (chompKeep && onChompKeep)
            onChompKeep();
        return str;
    }
    if (keyCommentDone)
        keyComment = null;
    if (explicitKey) {
        if (keyComment)
            str += lineComment(str, ctx.indent, commentString(keyComment));
        str = `? ${str}\n${indent}:`;
    }
    else {
        str = `${str}:`;
        if (keyComment)
            str += lineComment(str, ctx.indent, commentString(keyComment));
    }
    let vsb, vcb, valueComment;
    if (isNode(value)) {
        vsb = !!value.spaceBefore;
        vcb = value.commentBefore;
        valueComment = value.comment;
    }
    else {
        vsb = false;
        vcb = null;
        valueComment = null;
        if (value && typeof value === 'object')
            value = doc.createNode(value);
    }
    ctx.implicitKey = false;
    if (!explicitKey && !keyComment && isScalar(value))
        ctx.indentAtStart = str.length + 1;
    chompKeep = false;
    if (!indentSeq &&
        indentStep.length >= 2 &&
        !ctx.inFlow &&
        !explicitKey &&
        isSeq(value) &&
        !value.flow &&
        !value.tag &&
        !value.anchor) {
        // If indentSeq === false, consider '- ' as part of indentation where possible
        ctx.indent = ctx.indent.substring(2);
    }
    let valueCommentDone = false;
    const valueStr = stringify$1(value, ctx, () => (valueCommentDone = true), () => (chompKeep = true));
    let ws = ' ';
    if (keyComment || vsb || vcb) {
        ws = vsb ? '\n' : '';
        if (vcb) {
            const cs = commentString(vcb);
            ws += `\n${indentComment(cs, ctx.indent)}`;
        }
        if (valueStr === '' && !ctx.inFlow) {
            if (ws === '\n')
                ws = '\n\n';
        }
        else {
            ws += `\n${ctx.indent}`;
        }
    }
    else if (!explicitKey && isCollection(value)) {
        const vs0 = valueStr[0];
        const nl0 = valueStr.indexOf('\n');
        const hasNewline = nl0 !== -1;
        const flow = ctx.inFlow ?? value.flow ?? value.items.length === 0;
        if (hasNewline || !flow) {
            let hasPropsLine = false;
            if (hasNewline && (vs0 === '&' || vs0 === '!')) {
                let sp0 = valueStr.indexOf(' ');
                if (vs0 === '&' &&
                    sp0 !== -1 &&
                    sp0 < nl0 &&
                    valueStr[sp0 + 1] === '!') {
                    sp0 = valueStr.indexOf(' ', sp0 + 1);
                }
                if (sp0 === -1 || nl0 < sp0)
                    hasPropsLine = true;
            }
            if (!hasPropsLine)
                ws = `\n${ctx.indent}`;
        }
    }
    else if (valueStr === '' || valueStr[0] === '\n') {
        ws = '';
    }
    str += ws + valueStr;
    if (ctx.inFlow) {
        if (valueCommentDone && onComment)
            onComment();
    }
    else if (valueComment && !valueCommentDone) {
        str += lineComment(str, ctx.indent, commentString(valueComment));
    }
    else if (chompKeep && onChompKeep) {
        onChompKeep();
    }
    return str;
}

function warn(logLevel, warning) {
    if (logLevel === 'debug' || logLevel === 'warn') {
        // https://github.com/typescript-eslint/typescript-eslint/issues/7478
        // eslint-disable-next-line @typescript-eslint/prefer-optional-chain
        if (typeof process !== 'undefined' && process.emitWarning)
            process.emitWarning(warning);
        else
            console.warn(warning);
    }
}

const MERGE_KEY = '<<';
function addPairToJSMap(ctx, map, { key, value }) {
    if (ctx?.doc.schema.merge && isMergeKey(key)) {
        value = isAlias(value) ? value.resolve(ctx.doc) : value;
        if (isSeq(value))
            for (const it of value.items)
                mergeToJSMap(ctx, map, it);
        else if (Array.isArray(value))
            for (const it of value)
                mergeToJSMap(ctx, map, it);
        else
            mergeToJSMap(ctx, map, value);
    }
    else {
        const jsKey = toJS(key, '', ctx);
        if (map instanceof Map) {
            map.set(jsKey, toJS(value, jsKey, ctx));
        }
        else if (map instanceof Set) {
            map.add(jsKey);
        }
        else {
            const stringKey = stringifyKey(key, jsKey, ctx);
            const jsValue = toJS(value, stringKey, ctx);
            if (stringKey in map)
                Object.defineProperty(map, stringKey, {
                    value: jsValue,
                    writable: true,
                    enumerable: true,
                    configurable: true
                });
            else
                map[stringKey] = jsValue;
        }
    }
    return map;
}
const isMergeKey = (key) => key === MERGE_KEY ||
    (isScalar(key) &&
        key.value === MERGE_KEY &&
        (!key.type || key.type === Scalar.PLAIN));
// If the value associated with a merge key is a single mapping node, each of
// its key/value pairs is inserted into the current mapping, unless the key
// already exists in it. If the value associated with the merge key is a
// sequence, then this sequence is expected to contain mapping nodes and each
// of these nodes is merged in turn according to its order in the sequence.
// Keys in mapping nodes earlier in the sequence override keys specified in
// later mapping nodes. -- http://yaml.org/type/merge.html
function mergeToJSMap(ctx, map, value) {
    const source = ctx && isAlias(value) ? value.resolve(ctx.doc) : value;
    if (!isMap(source))
        throw new Error('Merge sources must be maps or map aliases');
    const srcMap = source.toJSON(null, ctx, Map);
    for (const [key, value] of srcMap) {
        if (map instanceof Map) {
            if (!map.has(key))
                map.set(key, value);
        }
        else if (map instanceof Set) {
            map.add(key);
        }
        else if (!Object.prototype.hasOwnProperty.call(map, key)) {
            Object.defineProperty(map, key, {
                value,
                writable: true,
                enumerable: true,
                configurable: true
            });
        }
    }
    return map;
}
function stringifyKey(key, jsKey, ctx) {
    if (jsKey === null)
        return '';
    if (typeof jsKey !== 'object')
        return String(jsKey);
    if (isNode(key) && ctx?.doc) {
        const strCtx = createStringifyContext(ctx.doc, {});
        strCtx.anchors = new Set();
        for (const node of ctx.anchors.keys())
            strCtx.anchors.add(node.anchor);
        strCtx.inFlow = true;
        strCtx.inStringifyKey = true;
        const strKey = key.toString(strCtx);
        if (!ctx.mapKeyWarned) {
            let jsonStr = JSON.stringify(strKey);
            if (jsonStr.length > 40)
                jsonStr = jsonStr.substring(0, 36) + '..."';
            warn(ctx.doc.options.logLevel, `Keys with collection values will be stringified due to JS Object restrictions: ${jsonStr}. Set mapAsMap: true to use object keys.`);
            ctx.mapKeyWarned = true;
        }
        return strKey;
    }
    return JSON.stringify(jsKey);
}

function createPair(key, value, ctx) {
    const k = createNode(key, undefined, ctx);
    const v = createNode(value, undefined, ctx);
    return new Pair(k, v);
}
class Pair {
    constructor(key, value = null) {
        Object.defineProperty(this, NODE_TYPE, { value: PAIR });
        this.key = key;
        this.value = value;
    }
    clone(schema) {
        let { key, value } = this;
        if (isNode(key))
            key = key.clone(schema);
        if (isNode(value))
            value = value.clone(schema);
        return new Pair(key, value);
    }
    toJSON(_, ctx) {
        const pair = ctx?.mapAsMap ? new Map() : {};
        return addPairToJSMap(ctx, pair, this);
    }
    toString(ctx, onComment, onChompKeep) {
        return ctx?.doc
            ? stringifyPair(this, ctx, onComment, onChompKeep)
            : JSON.stringify(this);
    }
}

function stringifyCollection(collection, ctx, options) {
    const flow = ctx.inFlow ?? collection.flow;
    const stringify = flow ? stringifyFlowCollection : stringifyBlockCollection;
    return stringify(collection, ctx, options);
}
function stringifyBlockCollection({ comment, items }, ctx, { blockItemPrefix, flowChars, itemIndent, onChompKeep, onComment }) {
    const { indent, options: { commentString } } = ctx;
    const itemCtx = Object.assign({}, ctx, { indent: itemIndent, type: null });
    let chompKeep = false; // flag for the preceding node's status
    const lines = [];
    for (let i = 0; i < items.length; ++i) {
        const item = items[i];
        let comment = null;
        if (isNode(item)) {
            if (!chompKeep && item.spaceBefore)
                lines.push('');
            addCommentBefore(ctx, lines, item.commentBefore, chompKeep);
            if (item.comment)
                comment = item.comment;
        }
        else if (isPair(item)) {
            const ik = isNode(item.key) ? item.key : null;
            if (ik) {
                if (!chompKeep && ik.spaceBefore)
                    lines.push('');
                addCommentBefore(ctx, lines, ik.commentBefore, chompKeep);
            }
        }
        chompKeep = false;
        let str = stringify$1(item, itemCtx, () => (comment = null), () => (chompKeep = true));
        if (comment)
            str += lineComment(str, itemIndent, commentString(comment));
        if (chompKeep && comment)
            chompKeep = false;
        lines.push(blockItemPrefix + str);
    }
    let str;
    if (lines.length === 0) {
        str = flowChars.start + flowChars.end;
    }
    else {
        str = lines[0];
        for (let i = 1; i < lines.length; ++i) {
            const line = lines[i];
            str += line ? `\n${indent}${line}` : '\n';
        }
    }
    if (comment) {
        str += '\n' + indentComment(commentString(comment), indent);
        if (onComment)
            onComment();
    }
    else if (chompKeep && onChompKeep)
        onChompKeep();
    return str;
}
function stringifyFlowCollection({ items }, ctx, { flowChars, itemIndent }) {
    const { indent, indentStep, flowCollectionPadding: fcPadding, options: { commentString } } = ctx;
    itemIndent += indentStep;
    const itemCtx = Object.assign({}, ctx, {
        indent: itemIndent,
        inFlow: true,
        type: null
    });
    let reqNewline = false;
    let linesAtValue = 0;
    const lines = [];
    for (let i = 0; i < items.length; ++i) {
        const item = items[i];
        let comment = null;
        if (isNode(item)) {
            if (item.spaceBefore)
                lines.push('');
            addCommentBefore(ctx, lines, item.commentBefore, false);
            if (item.comment)
                comment = item.comment;
        }
        else if (isPair(item)) {
            const ik = isNode(item.key) ? item.key : null;
            if (ik) {
                if (ik.spaceBefore)
                    lines.push('');
                addCommentBefore(ctx, lines, ik.commentBefore, false);
                if (ik.comment)
                    reqNewline = true;
            }
            const iv = isNode(item.value) ? item.value : null;
            if (iv) {
                if (iv.comment)
                    comment = iv.comment;
                if (iv.commentBefore)
                    reqNewline = true;
            }
            else if (item.value == null && ik?.comment) {
                comment = ik.comment;
            }
        }
        if (comment)
            reqNewline = true;
        let str = stringify$1(item, itemCtx, () => (comment = null));
        if (i < items.length - 1)
            str += ',';
        if (comment)
            str += lineComment(str, itemIndent, commentString(comment));
        if (!reqNewline && (lines.length > linesAtValue || str.includes('\n')))
            reqNewline = true;
        lines.push(str);
        linesAtValue = lines.length;
    }
    const { start, end } = flowChars;
    if (lines.length === 0) {
        return start + end;
    }
    else {
        if (!reqNewline) {
            const len = lines.reduce((sum, line) => sum + line.length + 2, 2);
            reqNewline = ctx.options.lineWidth > 0 && len > ctx.options.lineWidth;
        }
        if (reqNewline) {
            let str = start;
            for (const line of lines)
                str += line ? `\n${indentStep}${indent}${line}` : '\n';
            return `${str}\n${indent}${end}`;
        }
        else {
            return `${start}${fcPadding}${lines.join(' ')}${fcPadding}${end}`;
        }
    }
}
function addCommentBefore({ indent, options: { commentString } }, lines, comment, chompKeep) {
    if (comment && chompKeep)
        comment = comment.replace(/^\n+/, '');
    if (comment) {
        const ic = indentComment(commentString(comment), indent);
        lines.push(ic.trimStart()); // Avoid double indent on first line
    }
}

function findPair(items, key) {
    const k = isScalar(key) ? key.value : key;
    for (const it of items) {
        if (isPair(it)) {
            if (it.key === key || it.key === k)
                return it;
            if (isScalar(it.key) && it.key.value === k)
                return it;
        }
    }
    return undefined;
}
class YAMLMap extends Collection {
    static get tagName() {
        return 'tag:yaml.org,2002:map';
    }
    constructor(schema) {
        super(MAP, schema);
        this.items = [];
    }
    /**
     * A generic collection parsing method that can be extended
     * to other node classes that inherit from YAMLMap
     */
    static from(schema, obj, ctx) {
        const { keepUndefined, replacer } = ctx;
        const map = new this(schema);
        const add = (key, value) => {
            if (typeof replacer === 'function')
                value = replacer.call(obj, key, value);
            else if (Array.isArray(replacer) && !replacer.includes(key))
                return;
            if (value !== undefined || keepUndefined)
                map.items.push(createPair(key, value, ctx));
        };
        if (obj instanceof Map) {
            for (const [key, value] of obj)
                add(key, value);
        }
        else if (obj && typeof obj === 'object') {
            for (const key of Object.keys(obj))
                add(key, obj[key]);
        }
        if (typeof schema.sortMapEntries === 'function') {
            map.items.sort(schema.sortMapEntries);
        }
        return map;
    }
    /**
     * Adds a value to the collection.
     *
     * @param overwrite - If not set `true`, using a key that is already in the
     *   collection will throw. Otherwise, overwrites the previous value.
     */
    add(pair, overwrite) {
        let _pair;
        if (isPair(pair))
            _pair = pair;
        else if (!pair || typeof pair !== 'object' || !('key' in pair)) {
            // In TypeScript, this never happens.
            _pair = new Pair(pair, pair?.value);
        }
        else
            _pair = new Pair(pair.key, pair.value);
        const prev = findPair(this.items, _pair.key);
        const sortEntries = this.schema?.sortMapEntries;
        if (prev) {
            if (!overwrite)
                throw new Error(`Key ${_pair.key} already set`);
            // For scalars, keep the old node & its comments and anchors
            if (isScalar(prev.value) && isScalarValue(_pair.value))
                prev.value.value = _pair.value;
            else
                prev.value = _pair.value;
        }
        else if (sortEntries) {
            const i = this.items.findIndex(item => sortEntries(_pair, item) < 0);
            if (i === -1)
                this.items.push(_pair);
            else
                this.items.splice(i, 0, _pair);
        }
        else {
            this.items.push(_pair);
        }
    }
    delete(key) {
        const it = findPair(this.items, key);
        if (!it)
            return false;
        const del = this.items.splice(this.items.indexOf(it), 1);
        return del.length > 0;
    }
    get(key, keepScalar) {
        const it = findPair(this.items, key);
        const node = it?.value;
        return (!keepScalar && isScalar(node) ? node.value : node) ?? undefined;
    }
    has(key) {
        return !!findPair(this.items, key);
    }
    set(key, value) {
        this.add(new Pair(key, value), true);
    }
    /**
     * @param ctx - Conversion context, originally set in Document#toJS()
     * @param {Class} Type - If set, forces the returned collection type
     * @returns Instance of Type, Map, or Object
     */
    toJSON(_, ctx, Type) {
        const map = Type ? new Type() : ctx?.mapAsMap ? new Map() : {};
        if (ctx?.onCreate)
            ctx.onCreate(map);
        for (const item of this.items)
            addPairToJSMap(ctx, map, item);
        return map;
    }
    toString(ctx, onComment, onChompKeep) {
        if (!ctx)
            return JSON.stringify(this);
        for (const item of this.items) {
            if (!isPair(item))
                throw new Error(`Map items must all be pairs; found ${JSON.stringify(item)} instead`);
        }
        if (!ctx.allNullValues && this.hasAllNullValues(false))
            ctx = Object.assign({}, ctx, { allNullValues: true });
        return stringifyCollection(this, ctx, {
            blockItemPrefix: '',
            flowChars: { start: '{', end: '}' },
            itemIndent: ctx.indent || '',
            onChompKeep,
            onComment
        });
    }
}

class YAMLSeq extends Collection {
    static get tagName() {
        return 'tag:yaml.org,2002:seq';
    }
    constructor(schema) {
        super(SEQ, schema);
        this.items = [];
    }
    add(value) {
        this.items.push(value);
    }
    /**
     * Removes a value from the collection.
     *
     * `key` must contain a representation of an integer for this to succeed.
     * It may be wrapped in a `Scalar`.
     *
     * @returns `true` if the item was found and removed.
     */
    delete(key) {
        const idx = asItemIndex(key);
        if (typeof idx !== 'number')
            return false;
        const del = this.items.splice(idx, 1);
        return del.length > 0;
    }
    get(key, keepScalar) {
        const idx = asItemIndex(key);
        if (typeof idx !== 'number')
            return undefined;
        const it = this.items[idx];
        return !keepScalar && isScalar(it) ? it.value : it;
    }
    /**
     * Checks if the collection includes a value with the key `key`.
     *
     * `key` must contain a representation of an integer for this to succeed.
     * It may be wrapped in a `Scalar`.
     */
    has(key) {
        const idx = asItemIndex(key);
        return typeof idx === 'number' && idx < this.items.length;
    }
    /**
     * Sets a value in this collection. For `!!set`, `value` needs to be a
     * boolean to add/remove the item from the set.
     *
     * If `key` does not contain a representation of an integer, this will throw.
     * It may be wrapped in a `Scalar`.
     */
    set(key, value) {
        const idx = asItemIndex(key);
        if (typeof idx !== 'number')
            throw new Error(`Expected a valid index, not ${key}.`);
        const prev = this.items[idx];
        if (isScalar(prev) && isScalarValue(value))
            prev.value = value;
        else
            this.items[idx] = value;
    }
    toJSON(_, ctx) {
        const seq = [];
        if (ctx?.onCreate)
            ctx.onCreate(seq);
        let i = 0;
        for (const item of this.items)
            seq.push(toJS(item, String(i++), ctx));
        return seq;
    }
    toString(ctx, onComment, onChompKeep) {
        if (!ctx)
            return JSON.stringify(this);
        return stringifyCollection(this, ctx, {
            blockItemPrefix: '- ',
            flowChars: { start: '[', end: ']' },
            itemIndent: (ctx.indent || '') + '  ',
            onChompKeep,
            onComment
        });
    }
    static from(schema, obj, ctx) {
        const { replacer } = ctx;
        const seq = new this(schema);
        if (obj && Symbol.iterator in Object(obj)) {
            let i = 0;
            for (let it of obj) {
                if (typeof replacer === 'function') {
                    const key = obj instanceof Set ? it : String(i++);
                    it = replacer.call(obj, key, it);
                }
                seq.items.push(createNode(it, undefined, ctx));
            }
        }
        return seq;
    }
}
function asItemIndex(key) {
    let idx = isScalar(key) ? key.value : key;
    if (idx && typeof idx === 'string')
        idx = Number(idx);
    return typeof idx === 'number' && Number.isInteger(idx) && idx >= 0
        ? idx
        : null;
}

function resolvePairs(seq, onError) {
    if (isSeq(seq)) {
        for (let i = 0; i < seq.items.length; ++i) {
            let item = seq.items[i];
            if (isPair(item))
                continue;
            else if (isMap(item)) {
                if (item.items.length > 1)
                    onError('Each pair must have its own sequence indicator');
                const pair = item.items[0] || new Pair(new Scalar(null));
                if (item.commentBefore)
                    pair.key.commentBefore = pair.key.commentBefore
                        ? `${item.commentBefore}\n${pair.key.commentBefore}`
                        : item.commentBefore;
                if (item.comment) {
                    const cn = pair.value ?? pair.key;
                    cn.comment = cn.comment
                        ? `${item.comment}\n${cn.comment}`
                        : item.comment;
                }
                item = pair;
            }
            seq.items[i] = isPair(item) ? item : new Pair(item);
        }
    }
    else
        onError('Expected a sequence for this tag');
    return seq;
}
function createPairs(schema, iterable, ctx) {
    const { replacer } = ctx;
    const pairs = new YAMLSeq(schema);
    pairs.tag = 'tag:yaml.org,2002:pairs';
    let i = 0;
    if (iterable && Symbol.iterator in Object(iterable))
        for (let it of iterable) {
            if (typeof replacer === 'function')
                it = replacer.call(iterable, String(i++), it);
            let key, value;
            if (Array.isArray(it)) {
                if (it.length === 2) {
                    key = it[0];
                    value = it[1];
                }
                else
                    throw new TypeError(`Expected [key, value] tuple: ${it}`);
            }
            else if (it && it instanceof Object) {
                const keys = Object.keys(it);
                if (keys.length === 1) {
                    key = keys[0];
                    value = it[key];
                }
                else {
                    throw new TypeError(`Expected tuple with one key, not ${keys.length} keys`);
                }
            }
            else {
                key = it;
            }
            pairs.items.push(createPair(key, value, ctx));
        }
    return pairs;
}
const pairs = {
    collection: 'seq',
    default: false,
    tag: 'tag:yaml.org,2002:pairs',
    resolve: resolvePairs,
    createNode: createPairs
};

class YAMLOMap extends YAMLSeq {
    constructor() {
        super();
        this.add = YAMLMap.prototype.add.bind(this);
        this.delete = YAMLMap.prototype.delete.bind(this);
        this.get = YAMLMap.prototype.get.bind(this);
        this.has = YAMLMap.prototype.has.bind(this);
        this.set = YAMLMap.prototype.set.bind(this);
        this.tag = YAMLOMap.tag;
    }
    /**
     * If `ctx` is given, the return type is actually `Map<unknown, unknown>`,
     * but TypeScript won't allow widening the signature of a child method.
     */
    toJSON(_, ctx) {
        if (!ctx)
            return super.toJSON(_);
        const map = new Map();
        if (ctx?.onCreate)
            ctx.onCreate(map);
        for (const pair of this.items) {
            let key, value;
            if (isPair(pair)) {
                key = toJS(pair.key, '', ctx);
                value = toJS(pair.value, key, ctx);
            }
            else {
                key = toJS(pair, '', ctx);
            }
            if (map.has(key))
                throw new Error('Ordered maps must not include duplicate keys');
            map.set(key, value);
        }
        return map;
    }
    static from(schema, iterable, ctx) {
        const pairs = createPairs(schema, iterable, ctx);
        const omap = new this();
        omap.items = pairs.items;
        return omap;
    }
}
YAMLOMap.tag = 'tag:yaml.org,2002:omap';
const omap = {
    collection: 'seq',
    identify: value => value instanceof Map,
    nodeClass: YAMLOMap,
    default: false,
    tag: 'tag:yaml.org,2002:omap',
    resolve(seq, onError) {
        const pairs = resolvePairs(seq, onError);
        const seenKeys = [];
        for (const { key } of pairs.items) {
            if (isScalar(key)) {
                if (seenKeys.includes(key.value)) {
                    onError(`Ordered maps must not include duplicate keys: ${key.value}`);
                }
                else {
                    seenKeys.push(key.value);
                }
            }
        }
        return Object.assign(new YAMLOMap(), pairs);
    },
    createNode: (schema, iterable, ctx) => YAMLOMap.from(schema, iterable, ctx)
};

class YAMLSet extends YAMLMap {
    constructor(schema) {
        super(schema);
        this.tag = YAMLSet.tag;
    }
    add(key) {
        let pair;
        if (isPair(key))
            pair = key;
        else if (key &&
            typeof key === 'object' &&
            'key' in key &&
            'value' in key &&
            key.value === null)
            pair = new Pair(key.key, null);
        else
            pair = new Pair(key, null);
        const prev = findPair(this.items, pair.key);
        if (!prev)
            this.items.push(pair);
    }
    /**
     * If `keepPair` is `true`, returns the Pair matching `key`.
     * Otherwise, returns the value of that Pair's key.
     */
    get(key, keepPair) {
        const pair = findPair(this.items, key);
        return !keepPair && isPair(pair)
            ? isScalar(pair.key)
                ? pair.key.value
                : pair.key
            : pair;
    }
    set(key, value) {
        if (typeof value !== 'boolean')
            throw new Error(`Expected boolean value for set(key, value) in a YAML set, not ${typeof value}`);
        const prev = findPair(this.items, key);
        if (prev && !value) {
            this.items.splice(this.items.indexOf(prev), 1);
        }
        else if (!prev && value) {
            this.items.push(new Pair(key));
        }
    }
    toJSON(_, ctx) {
        return super.toJSON(_, ctx, Set);
    }
    toString(ctx, onComment, onChompKeep) {
        if (!ctx)
            return JSON.stringify(this);
        if (this.hasAllNullValues(true))
            return super.toString(Object.assign({}, ctx, { allNullValues: true }), onComment, onChompKeep);
        else
            throw new Error('Set items must all have null values');
    }
    static from(schema, iterable, ctx) {
        const { replacer } = ctx;
        const set = new this(schema);
        if (iterable && Symbol.iterator in Object(iterable))
            for (let value of iterable) {
                if (typeof replacer === 'function')
                    value = replacer.call(iterable, value, value);
                set.items.push(createPair(value, null, ctx));
            }
        return set;
    }
}
YAMLSet.tag = 'tag:yaml.org,2002:set';
const set = {
    collection: 'map',
    identify: value => value instanceof Set,
    nodeClass: YAMLSet,
    default: false,
    tag: 'tag:yaml.org,2002:set',
    createNode: (schema, iterable, ctx) => YAMLSet.from(schema, iterable, ctx),
    resolve(map, onError) {
        if (isMap(map)) {
            if (map.hasAllNullValues(true))
                return Object.assign(new YAMLSet(), map);
            else
                onError('Set items must all have null values');
        }
        else
            onError('Expected a mapping for this tag');
        return map;
    }
};

/** The byte order mark */
const BOM = '\u{FEFF}';
/** Start of doc-mode */
const DOCUMENT = '\x02'; // C0: Start of Text
/** Unexpected end of flow-mode */
const FLOW_END = '\x18'; // C0: Cancel
/** Next token is a scalar value */
const SCALAR = '\x1f'; // C0: Unit Separator
/** Identify the type of a lexer token. May return `null` for unknown tokens. */
function tokenType(source) {
    switch (source) {
        case BOM:
            return 'byte-order-mark';
        case DOCUMENT:
            return 'doc-mode';
        case FLOW_END:
            return 'flow-error-end';
        case SCALAR:
            return 'scalar';
        case '---':
            return 'doc-start';
        case '...':
            return 'doc-end';
        case '':
        case '\n':
        case '\r\n':
            return 'newline';
        case '-':
            return 'seq-item-ind';
        case '?':
            return 'explicit-key-ind';
        case ':':
            return 'map-value-ind';
        case '{':
            return 'flow-map-start';
        case '}':
            return 'flow-map-end';
        case '[':
            return 'flow-seq-start';
        case ']':
            return 'flow-seq-end';
        case ',':
            return 'comma';
    }
    switch (source[0]) {
        case ' ':
        case '\t':
            return 'space';
        case '#':
            return 'comment';
        case '%':
            return 'directive-line';
        case '*':
            return 'alias';
        case '&':
            return 'anchor';
        case '!':
            return 'tag';
        case "'":
            return 'single-quoted-scalar';
        case '"':
            return 'double-quoted-scalar';
        case '|':
        case '>':
            return 'block-scalar-header';
    }
    return null;
}

/*
START -> stream

stream
  directive -> line-end -> stream
  indent + line-end -> stream
  [else] -> line-start

line-end
  comment -> line-end
  newline -> .
  input-end -> END

line-start
  doc-start -> doc
  doc-end -> stream
  [else] -> indent -> block-start

block-start
  seq-item-start -> block-start
  explicit-key-start -> block-start
  map-value-start -> block-start
  [else] -> doc

doc
  line-end -> line-start
  spaces -> doc
  anchor -> doc
  tag -> doc
  flow-start -> flow -> doc
  flow-end -> error -> doc
  seq-item-start -> error -> doc
  explicit-key-start -> error -> doc
  map-value-start -> doc
  alias -> doc
  quote-start -> quoted-scalar -> doc
  block-scalar-header -> line-end -> block-scalar(min) -> line-start
  [else] -> plain-scalar(false, min) -> doc

flow
  line-end -> flow
  spaces -> flow
  anchor -> flow
  tag -> flow
  flow-start -> flow -> flow
  flow-end -> .
  seq-item-start -> error -> flow
  explicit-key-start -> flow
  map-value-start -> flow
  alias -> flow
  quote-start -> quoted-scalar -> flow
  comma -> flow
  [else] -> plain-scalar(true, 0) -> flow

quoted-scalar
  quote-end -> .
  [else] -> quoted-scalar

block-scalar(min)
  newline + peek(indent < min) -> .
  [else] -> block-scalar(min)

plain-scalar(is-flow, min)
  scalar-end(is-flow) -> .
  peek(newline + (indent < min)) -> .
  [else] -> plain-scalar(min)
*/
function isEmpty(ch) {
    switch (ch) {
        case undefined:
        case ' ':
        case '\n':
        case '\r':
        case '\t':
            return true;
        default:
            return false;
    }
}
const hexDigits = new Set('0123456789ABCDEFabcdef');
const tagChars = new Set("0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz-#;/?:@&=+$_.!~*'()");
const flowIndicatorChars = new Set(',[]{}');
const invalidAnchorChars = new Set(' ,[]{}\n\r\t');
const isNotAnchorChar = (ch) => !ch || invalidAnchorChars.has(ch);
/**
 * Splits an input string into lexical tokens, i.e. smaller strings that are
 * easily identifiable by `tokens.tokenType()`.
 *
 * Lexing starts always in a "stream" context. Incomplete input may be buffered
 * until a complete token can be emitted.
 *
 * In addition to slices of the original input, the following control characters
 * may also be emitted:
 *
 * - `\x02` (Start of Text): A document starts with the next token
 * - `\x18` (Cancel): Unexpected end of flow-mode (indicates an error)
 * - `\x1f` (Unit Separator): Next token is a scalar value
 * - `\u{FEFF}` (Byte order mark): Emitted separately outside documents
 */
class Lexer {
    constructor() {
        /**
         * Flag indicating whether the end of the current buffer marks the end of
         * all input
         */
        this.atEnd = false;
        /**
         * Explicit indent set in block scalar header, as an offset from the current
         * minimum indent, so e.g. set to 1 from a header `|2+`. Set to -1 if not
         * explicitly set.
         */
        this.blockScalarIndent = -1;
        /**
         * Block scalars that include a + (keep) chomping indicator in their header
         * include trailing empty lines, which are otherwise excluded from the
         * scalar's contents.
         */
        this.blockScalarKeep = false;
        /** Current input */
        this.buffer = '';
        /**
         * Flag noting whether the map value indicator : can immediately follow this
         * node within a flow context.
         */
        this.flowKey = false;
        /** Count of surrounding flow collection levels. */
        this.flowLevel = 0;
        /**
         * Minimum level of indentation required for next lines to be parsed as a
         * part of the current scalar value.
         */
        this.indentNext = 0;
        /** Indentation level of the current line. */
        this.indentValue = 0;
        /** Position of the next \n character. */
        this.lineEndPos = null;
        /** Stores the state of the lexer if reaching the end of incpomplete input */
        this.next = null;
        /** A pointer to `buffer`; the current position of the lexer. */
        this.pos = 0;
    }
    /**
     * Generate YAML tokens from the `source` string. If `incomplete`,
     * a part of the last line may be left as a buffer for the next call.
     *
     * @returns A generator of lexical tokens
     */
    *lex(source, incomplete = false) {
        if (source) {
            if (typeof source !== 'string')
                throw TypeError('source is not a string');
            this.buffer = this.buffer ? this.buffer + source : source;
            this.lineEndPos = null;
        }
        this.atEnd = !incomplete;
        let next = this.next ?? 'stream';
        while (next && (incomplete || this.hasChars(1)))
            next = yield* this.parseNext(next);
    }
    atLineEnd() {
        let i = this.pos;
        let ch = this.buffer[i];
        while (ch === ' ' || ch === '\t')
            ch = this.buffer[++i];
        if (!ch || ch === '#' || ch === '\n')
            return true;
        if (ch === '\r')
            return this.buffer[i + 1] === '\n';
        return false;
    }
    charAt(n) {
        return this.buffer[this.pos + n];
    }
    continueScalar(offset) {
        let ch = this.buffer[offset];
        if (this.indentNext > 0) {
            let indent = 0;
            while (ch === ' ')
                ch = this.buffer[++indent + offset];
            if (ch === '\r') {
                const next = this.buffer[indent + offset + 1];
                if (next === '\n' || (!next && !this.atEnd))
                    return offset + indent + 1;
            }
            return ch === '\n' || indent >= this.indentNext || (!ch && !this.atEnd)
                ? offset + indent
                : -1;
        }
        if (ch === '-' || ch === '.') {
            const dt = this.buffer.substr(offset, 3);
            if ((dt === '---' || dt === '...') && isEmpty(this.buffer[offset + 3]))
                return -1;
        }
        return offset;
    }
    getLine() {
        let end = this.lineEndPos;
        if (typeof end !== 'number' || (end !== -1 && end < this.pos)) {
            end = this.buffer.indexOf('\n', this.pos);
            this.lineEndPos = end;
        }
        if (end === -1)
            return this.atEnd ? this.buffer.substring(this.pos) : null;
        if (this.buffer[end - 1] === '\r')
            end -= 1;
        return this.buffer.substring(this.pos, end);
    }
    hasChars(n) {
        return this.pos + n <= this.buffer.length;
    }
    setNext(state) {
        this.buffer = this.buffer.substring(this.pos);
        this.pos = 0;
        this.lineEndPos = null;
        this.next = state;
        return null;
    }
    peek(n) {
        return this.buffer.substr(this.pos, n);
    }
    *parseNext(next) {
        switch (next) {
            case 'stream':
                return yield* this.parseStream();
            case 'line-start':
                return yield* this.parseLineStart();
            case 'block-start':
                return yield* this.parseBlockStart();
            case 'doc':
                return yield* this.parseDocument();
            case 'flow':
                return yield* this.parseFlowCollection();
            case 'quoted-scalar':
                return yield* this.parseQuotedScalar();
            case 'block-scalar':
                return yield* this.parseBlockScalar();
            case 'plain-scalar':
                return yield* this.parsePlainScalar();
        }
    }
    *parseStream() {
        let line = this.getLine();
        if (line === null)
            return this.setNext('stream');
        if (line[0] === BOM) {
            yield* this.pushCount(1);
            line = line.substring(1);
        }
        if (line[0] === '%') {
            let dirEnd = line.length;
            let cs = line.indexOf('#');
            while (cs !== -1) {
                const ch = line[cs - 1];
                if (ch === ' ' || ch === '\t') {
                    dirEnd = cs - 1;
                    break;
                }
                else {
                    cs = line.indexOf('#', cs + 1);
                }
            }
            while (true) {
                const ch = line[dirEnd - 1];
                if (ch === ' ' || ch === '\t')
                    dirEnd -= 1;
                else
                    break;
            }
            const n = (yield* this.pushCount(dirEnd)) + (yield* this.pushSpaces(true));
            yield* this.pushCount(line.length - n); // possible comment
            this.pushNewline();
            return 'stream';
        }
        if (this.atLineEnd()) {
            const sp = yield* this.pushSpaces(true);
            yield* this.pushCount(line.length - sp);
            yield* this.pushNewline();
            return 'stream';
        }
        yield DOCUMENT;
        return yield* this.parseLineStart();
    }
    *parseLineStart() {
        const ch = this.charAt(0);
        if (!ch && !this.atEnd)
            return this.setNext('line-start');
        if (ch === '-' || ch === '.') {
            if (!this.atEnd && !this.hasChars(4))
                return this.setNext('line-start');
            const s = this.peek(3);
            if (s === '---' && isEmpty(this.charAt(3))) {
                yield* this.pushCount(3);
                this.indentValue = 0;
                this.indentNext = 0;
                return 'doc';
            }
            else if (s === '...' && isEmpty(this.charAt(3))) {
                yield* this.pushCount(3);
                return 'stream';
            }
        }
        this.indentValue = yield* this.pushSpaces(false);
        if (this.indentNext > this.indentValue && !isEmpty(this.charAt(1)))
            this.indentNext = this.indentValue;
        return yield* this.parseBlockStart();
    }
    *parseBlockStart() {
        const [ch0, ch1] = this.peek(2);
        if (!ch1 && !this.atEnd)
            return this.setNext('block-start');
        if ((ch0 === '-' || ch0 === '?' || ch0 === ':') && isEmpty(ch1)) {
            const n = (yield* this.pushCount(1)) + (yield* this.pushSpaces(true));
            this.indentNext = this.indentValue + 1;
            this.indentValue += n;
            return yield* this.parseBlockStart();
        }
        return 'doc';
    }
    *parseDocument() {
        yield* this.pushSpaces(true);
        const line = this.getLine();
        if (line === null)
            return this.setNext('doc');
        let n = yield* this.pushIndicators();
        switch (line[n]) {
            case '#':
                yield* this.pushCount(line.length - n);
            // fallthrough
            case undefined:
                yield* this.pushNewline();
                return yield* this.parseLineStart();
            case '{':
            case '[':
                yield* this.pushCount(1);
                this.flowKey = false;
                this.flowLevel = 1;
                return 'flow';
            case '}':
            case ']':
                // this is an error
                yield* this.pushCount(1);
                return 'doc';
            case '*':
                yield* this.pushUntil(isNotAnchorChar);
                return 'doc';
            case '"':
            case "'":
                return yield* this.parseQuotedScalar();
            case '|':
            case '>':
                n += yield* this.parseBlockScalarHeader();
                n += yield* this.pushSpaces(true);
                yield* this.pushCount(line.length - n);
                yield* this.pushNewline();
                return yield* this.parseBlockScalar();
            default:
                return yield* this.parsePlainScalar();
        }
    }
    *parseFlowCollection() {
        let nl, sp;
        let indent = -1;
        do {
            nl = yield* this.pushNewline();
            if (nl > 0) {
                sp = yield* this.pushSpaces(false);
                this.indentValue = indent = sp;
            }
            else {
                sp = 0;
            }
            sp += yield* this.pushSpaces(true);
        } while (nl + sp > 0);
        const line = this.getLine();
        if (line === null)
            return this.setNext('flow');
        if ((indent !== -1 && indent < this.indentNext && line[0] !== '#') ||
            (indent === 0 &&
                (line.startsWith('---') || line.startsWith('...')) &&
                isEmpty(line[3]))) {
            // Allowing for the terminal ] or } at the same (rather than greater)
            // indent level as the initial [ or { is technically invalid, but
            // failing here would be surprising to users.
            const atFlowEndMarker = indent === this.indentNext - 1 &&
                this.flowLevel === 1 &&
                (line[0] === ']' || line[0] === '}');
            if (!atFlowEndMarker) {
                // this is an error
                this.flowLevel = 0;
                yield FLOW_END;
                return yield* this.parseLineStart();
            }
        }
        let n = 0;
        while (line[n] === ',') {
            n += yield* this.pushCount(1);
            n += yield* this.pushSpaces(true);
            this.flowKey = false;
        }
        n += yield* this.pushIndicators();
        switch (line[n]) {
            case undefined:
                return 'flow';
            case '#':
                yield* this.pushCount(line.length - n);
                return 'flow';
            case '{':
            case '[':
                yield* this.pushCount(1);
                this.flowKey = false;
                this.flowLevel += 1;
                return 'flow';
            case '}':
            case ']':
                yield* this.pushCount(1);
                this.flowKey = true;
                this.flowLevel -= 1;
                return this.flowLevel ? 'flow' : 'doc';
            case '*':
                yield* this.pushUntil(isNotAnchorChar);
                return 'flow';
            case '"':
            case "'":
                this.flowKey = true;
                return yield* this.parseQuotedScalar();
            case ':': {
                const next = this.charAt(1);
                if (this.flowKey || isEmpty(next) || next === ',') {
                    this.flowKey = false;
                    yield* this.pushCount(1);
                    yield* this.pushSpaces(true);
                    return 'flow';
                }
            }
            // fallthrough
            default:
                this.flowKey = false;
                return yield* this.parsePlainScalar();
        }
    }
    *parseQuotedScalar() {
        const quote = this.charAt(0);
        let end = this.buffer.indexOf(quote, this.pos + 1);
        if (quote === "'") {
            while (end !== -1 && this.buffer[end + 1] === "'")
                end = this.buffer.indexOf("'", end + 2);
        }
        else {
            // double-quote
            while (end !== -1) {
                let n = 0;
                while (this.buffer[end - 1 - n] === '\\')
                    n += 1;
                if (n % 2 === 0)
                    break;
                end = this.buffer.indexOf('"', end + 1);
            }
        }
        // Only looking for newlines within the quotes
        const qb = this.buffer.substring(0, end);
        let nl = qb.indexOf('\n', this.pos);
        if (nl !== -1) {
            while (nl !== -1) {
                const cs = this.continueScalar(nl + 1);
                if (cs === -1)
                    break;
                nl = qb.indexOf('\n', cs);
            }
            if (nl !== -1) {
                // this is an error caused by an unexpected unindent
                end = nl - (qb[nl - 1] === '\r' ? 2 : 1);
            }
        }
        if (end === -1) {
            if (!this.atEnd)
                return this.setNext('quoted-scalar');
            end = this.buffer.length;
        }
        yield* this.pushToIndex(end + 1, false);
        return this.flowLevel ? 'flow' : 'doc';
    }
    *parseBlockScalarHeader() {
        this.blockScalarIndent = -1;
        this.blockScalarKeep = false;
        let i = this.pos;
        while (true) {
            const ch = this.buffer[++i];
            if (ch === '+')
                this.blockScalarKeep = true;
            else if (ch > '0' && ch <= '9')
                this.blockScalarIndent = Number(ch) - 1;
            else if (ch !== '-')
                break;
        }
        return yield* this.pushUntil(ch => isEmpty(ch) || ch === '#');
    }
    *parseBlockScalar() {
        let nl = this.pos - 1; // may be -1 if this.pos === 0
        let indent = 0;
        let ch;
        loop: for (let i = this.pos; (ch = this.buffer[i]); ++i) {
            switch (ch) {
                case ' ':
                    indent += 1;
                    break;
                case '\n':
                    nl = i;
                    indent = 0;
                    break;
                case '\r': {
                    const next = this.buffer[i + 1];
                    if (!next && !this.atEnd)
                        return this.setNext('block-scalar');
                    if (next === '\n')
                        break;
                } // fallthrough
                default:
                    break loop;
            }
        }
        if (!ch && !this.atEnd)
            return this.setNext('block-scalar');
        if (indent >= this.indentNext) {
            if (this.blockScalarIndent === -1)
                this.indentNext = indent;
            else {
                this.indentNext =
                    this.blockScalarIndent + (this.indentNext === 0 ? 1 : this.indentNext);
            }
            do {
                const cs = this.continueScalar(nl + 1);
                if (cs === -1)
                    break;
                nl = this.buffer.indexOf('\n', cs);
            } while (nl !== -1);
            if (nl === -1) {
                if (!this.atEnd)
                    return this.setNext('block-scalar');
                nl = this.buffer.length;
            }
        }
        // Trailing insufficiently indented tabs are invalid.
        // To catch that during parsing, we include them in the block scalar value.
        let i = nl + 1;
        ch = this.buffer[i];
        while (ch === ' ')
            ch = this.buffer[++i];
        if (ch === '\t') {
            while (ch === '\t' || ch === ' ' || ch === '\r' || ch === '\n')
                ch = this.buffer[++i];
            nl = i - 1;
        }
        else if (!this.blockScalarKeep) {
            do {
                let i = nl - 1;
                let ch = this.buffer[i];
                if (ch === '\r')
                    ch = this.buffer[--i];
                const lastChar = i; // Drop the line if last char not more indented
                while (ch === ' ')
                    ch = this.buffer[--i];
                if (ch === '\n' && i >= this.pos && i + 1 + indent > lastChar)
                    nl = i;
                else
                    break;
            } while (true);
        }
        yield SCALAR;
        yield* this.pushToIndex(nl + 1, true);
        return yield* this.parseLineStart();
    }
    *parsePlainScalar() {
        const inFlow = this.flowLevel > 0;
        let end = this.pos - 1;
        let i = this.pos - 1;
        let ch;
        while ((ch = this.buffer[++i])) {
            if (ch === ':') {
                const next = this.buffer[i + 1];
                if (isEmpty(next) || (inFlow && flowIndicatorChars.has(next)))
                    break;
                end = i;
            }
            else if (isEmpty(ch)) {
                let next = this.buffer[i + 1];
                if (ch === '\r') {
                    if (next === '\n') {
                        i += 1;
                        ch = '\n';
                        next = this.buffer[i + 1];
                    }
                    else
                        end = i;
                }
                if (next === '#' || (inFlow && flowIndicatorChars.has(next)))
                    break;
                if (ch === '\n') {
                    const cs = this.continueScalar(i + 1);
                    if (cs === -1)
                        break;
                    i = Math.max(i, cs - 2); // to advance, but still account for ' #'
                }
            }
            else {
                if (inFlow && flowIndicatorChars.has(ch))
                    break;
                end = i;
            }
        }
        if (!ch && !this.atEnd)
            return this.setNext('plain-scalar');
        yield SCALAR;
        yield* this.pushToIndex(end + 1, true);
        return inFlow ? 'flow' : 'doc';
    }
    *pushCount(n) {
        if (n > 0) {
            yield this.buffer.substr(this.pos, n);
            this.pos += n;
            return n;
        }
        return 0;
    }
    *pushToIndex(i, allowEmpty) {
        const s = this.buffer.slice(this.pos, i);
        if (s) {
            yield s;
            this.pos += s.length;
            return s.length;
        }
        else if (allowEmpty)
            yield '';
        return 0;
    }
    *pushIndicators() {
        switch (this.charAt(0)) {
            case '!':
                return ((yield* this.pushTag()) +
                    (yield* this.pushSpaces(true)) +
                    (yield* this.pushIndicators()));
            case '&':
                return ((yield* this.pushUntil(isNotAnchorChar)) +
                    (yield* this.pushSpaces(true)) +
                    (yield* this.pushIndicators()));
            case '-': // this is an error
            case '?': // this is an error outside flow collections
            case ':': {
                const inFlow = this.flowLevel > 0;
                const ch1 = this.charAt(1);
                if (isEmpty(ch1) || (inFlow && flowIndicatorChars.has(ch1))) {
                    if (!inFlow)
                        this.indentNext = this.indentValue + 1;
                    else if (this.flowKey)
                        this.flowKey = false;
                    return ((yield* this.pushCount(1)) +
                        (yield* this.pushSpaces(true)) +
                        (yield* this.pushIndicators()));
                }
            }
        }
        return 0;
    }
    *pushTag() {
        if (this.charAt(1) === '<') {
            let i = this.pos + 2;
            let ch = this.buffer[i];
            while (!isEmpty(ch) && ch !== '>')
                ch = this.buffer[++i];
            return yield* this.pushToIndex(ch === '>' ? i + 1 : i, false);
        }
        else {
            let i = this.pos + 1;
            let ch = this.buffer[i];
            while (ch) {
                if (tagChars.has(ch))
                    ch = this.buffer[++i];
                else if (ch === '%' &&
                    hexDigits.has(this.buffer[i + 1]) &&
                    hexDigits.has(this.buffer[i + 2])) {
                    ch = this.buffer[(i += 3)];
                }
                else
                    break;
            }
            return yield* this.pushToIndex(i, false);
        }
    }
    *pushNewline() {
        const ch = this.buffer[this.pos];
        if (ch === '\n')
            return yield* this.pushCount(1);
        else if (ch === '\r' && this.charAt(1) === '\n')
            return yield* this.pushCount(2);
        else
            return 0;
    }
    *pushSpaces(allowTabs) {
        let i = this.pos - 1;
        let ch;
        do {
            ch = this.buffer[++i];
        } while (ch === ' ' || (allowTabs && ch === '\t'));
        const n = i - this.pos;
        if (n > 0) {
            yield this.buffer.substr(this.pos, n);
            this.pos = i;
        }
        return n;
    }
    *pushUntil(test) {
        let i = this.pos;
        let ch = this.buffer[i];
        while (!test(ch))
            ch = this.buffer[++i];
        return yield* this.pushToIndex(i, false);
    }
}

function getLocationInYamlScript(file, path, kind = "value") {
    const node = findYamlNode(file, path, kind);
    return {
        file: file.file,
        pos: node?.range?.[0] ?? 0,
        end: node?.range?.[1] ?? 0,
    };
}
function findYamlNode(file, path, kind = "value") {
    let current = file.doc.contents;
    for (let i = 0; i < path.length; i++) {
        const key = path[i];
        const isLast = i === path.length - 1;
        if (isScalar(current)) {
            return current;
        }
        else if (isCollection(current)) {
            if (isLast) {
                if (kind === "value" || !isMap(current)) {
                    return current.get(key, true);
                }
                else {
                    const pair = findPair(current.items, key);
                    if (kind === "key") {
                        return pair?.key;
                    }
                    else {
                        return pair;
                    }
                }
            }
            else {
                current = current.get(key, true);
            }
        }
        else {
            continue;
        }
    }
    return current ?? undefined;
}

// noop logger shouldn't be used in browser
function formatLog(log) {
    return JSON.stringify(log);
}

/**
 * Represents a failure while interpreting a projection.
 */
class ProjectionError extends Error {
    constructor(message) {
        super(message);
        this.name = "ProjectionError";
    }
}
function logDiagnostics(diagnostics, logger) {
    for (const diagnostic of diagnostics) {
        logger.log({
            level: diagnostic.severity,
            message: diagnostic.message,
            code: diagnostic.code,
            sourceLocation: getSourceLocation(diagnostic.target, { locateId: true }),
        });
    }
}
function formatDiagnostic(diagnostic) {
    return formatLog({
        code: diagnostic.code,
        level: diagnostic.severity,
        message: diagnostic.message,
        sourceLocation: getSourceLocation(diagnostic.target, { locateId: true }),
    });
}
function getSourceLocation(target, options = {}) {
    if (target === NoTarget || target === undefined) {
        return undefined;
    }
    if ("file" in target) {
        return target;
    }
    if (!("kind" in target) && !("valueKind" in target) && !("entityKind" in target)) {
        // symbol
        if (target.flags & 524288 /* SymbolFlags.Using */) {
            target = target.symbolSource;
        }
        if (!target.declarations[0]) {
            return createSyntheticSourceLocation();
        }
        return getSourceLocationOfNode(target.declarations[0], options);
    }
    else if ("kind" in target && typeof target.kind === "number") {
        // node
        return getSourceLocationOfNode(target, options);
    }
    else {
        // type
        const targetNode = target.node;
        if (targetNode) {
            return getSourceLocationOfNode(targetNode, options);
        }
        return createSyntheticSourceLocation();
    }
}
function createSyntheticSourceLocation(loc = "<unknown location>") {
    return {
        file: createSourceFile("", loc),
        pos: 0,
        end: 0,
        isSynthetic: true,
    };
}
function getSourceLocationOfNode(node, options) {
    let root = node;
    while (root.parent !== undefined) {
        root = root.parent;
    }
    if (root.kind !== SyntaxKind.TypeSpecScript && root.kind !== SyntaxKind.JsSourceFile) {
        return createSyntheticSourceLocation(node.flags & 8 /* NodeFlags.Synthetic */
            ? undefined
            : "<unknown location - cannot obtain source location of unbound node - file bug at https://github.com/microsoft/typespec>");
    }
    if (options.locateId && "id" in node && node.id !== undefined) {
        node = node.id;
    }
    return {
        file: root.file,
        pos: node.pos,
        end: node.end,
    };
}
/**
 * Verbose output is enabled by default for runs in mocha explorer in VS Code,
 * where the output is nicely associated with the individual test, and disabled
 * by default for command line runs where we don't want to spam the console.
 *
 * If the steps taken to produce the message are expensive, pass a callback
 * instead of producing the message then passing it here only to be dropped
 * when verbose output is disabled.
 */
function logVerboseTestOutput(messageOrCallback) {
    if (process.env.TYPESPEC_VERBOSE_TEST_OUTPUT) {
        if (typeof messageOrCallback === "string") {
            // eslint-disable-next-line no-console
            console.log(messageOrCallback);
        }
        else {
            // eslint-disable-next-line no-console
            messageOrCallback(console.log);
        }
    }
}
/**
 * Use this to report bugs in the compiler, and not errors in the source code
 * being compiled.
 *
 * @param condition Throw if this is not true.
 *
 * @param message Error message.
 *
 * @param target Optional location in source code that might give a clue about
 *               what got the compiler off track.
 */
function compilerAssert(condition, message, target) {
    if (condition) {
        return;
    }
    if (target) {
        let location;
        try {
            location = getSourceLocation(target);
        }
        catch (err) { }
        if (location) {
            const pos = location.file.getLineAndCharacterOfPosition(location.pos);
            const file = location.file.path;
            const line = pos.line + 1;
            const col = pos.character + 1;
            message += `\nOccurred while compiling code in ${file} near line ${line}, column ${col}`;
        }
    }
    throw new Error(message);
}
/**
 * Assert that the input type has one of the kinds provided
 */
function assertType(typeDescription, t, ...kinds) {
    if (kinds.indexOf(t.kind) === -1) {
        throw new ProjectionError(`Expected ${typeDescription} to be type ${kinds.join(", ")}`);
    }
}
/**
 * Report a deprecated diagnostic.
 * @param program TypeSpec Program.
 * @param message Message describing the deprecation.
 * @param target Target of the deprecation.
 */
function reportDeprecated(program, message, target) {
    program.reportDiagnostic({
        severity: "warning",
        code: "deprecated",
        message: `Deprecated: ${message}`,
        target,
    });
}
/**
 * Create a new instance of the @see DiagnosticCollector.
 */
function createDiagnosticCollector() {
    const diagnostics = [];
    return {
        diagnostics,
        add,
        pipe,
        wrap,
    };
    function add(diagnostic) {
        diagnostics.push(diagnostic);
    }
    function pipe(result) {
        const [value, diags] = result;
        for (const diag of diags) {
            diagnostics.push(diag);
        }
        return value;
    }
    function wrap(value) {
        return [value, diagnostics];
    }
}
/**
 * Ignore the diagnostics emitted by the diagnostic accessor pattern and just return the actual result.
 * @param result Accessor pattern tuple result including the actual result and the list of diagnostics.
 * @returns Actual result.
 */
function ignoreDiagnostics(result) {
    return result[0];
}
function defineCodeFix(fix) {
    return fix;
}

function createJSONSchemaValidator(schema, options = { strict: true }) {
    const ajv = new ajvExports.Ajv({
        strict: options.strict,
        coerceTypes: options.coerceTypes,
        allErrors: true,
    });
    ajv.addFormat("absolute-path", {
        type: "string",
        validate: (path) => {
            return !path.startsWith(".") && isPathAbsolute(path);
        },
    });
    return { validate };
    function validate(config, target) {
        const validate = ajv.compile(schema);
        const valid = validate(config);
        compilerAssert(!valid || !validate.errors, "There should be errors reported if the schema is not valid.");
        const diagnostics = [];
        for (const error of validate.errors ?? []) {
            const diagnostic = ajvErrorToDiagnostic(config, error, target);
            diagnostics.push(diagnostic);
        }
        return diagnostics;
    }
}
const IGNORED_AJV_PARAMS = new Set(["type", "errors"]);
function ajvErrorToDiagnostic(obj, error, target) {
    const tspTarget = resolveTarget(error, target);
    if (error.params.format === "absolute-path") {
        return createDiagnostic({
            code: "config-path-absolute",
            format: { path: getErrorValue(obj, error) },
            target: tspTarget,
        });
    }
    const messageLines = [`Schema violation: ${error.message} (${error.instancePath || "/"})`];
    for (const [name, value] of Object.entries(error.params).filter(([name]) => !IGNORED_AJV_PARAMS.has(name))) {
        const formattedValue = Array.isArray(value) ? [...new Set(value)].join(", ") : value;
        messageLines.push(`  ${name}: ${formattedValue}`);
    }
    const message = messageLines.join("\n");
    return {
        code: "invalid-schema",
        message,
        severity: "error",
        target: tspTarget,
    };
}
function resolveTarget(error, target) {
    if (target === NoTarget) {
        return NoTarget;
    }
    if (!("kind" in target)) {
        return { file: target, pos: 0, end: 0 };
    }
    switch (target.kind) {
        case "yaml-script":
            return getLocationInYamlScript(target, getErrorPath(error), "key");
        case "path-target":
            return getLocationInYamlScript(target.script, [...target.path, ...getErrorPath(error)], "key");
    }
}
function getErrorPath(error) {
    const instancePath = parseJsonPointer(error.instancePath);
    switch (error.keyword) {
        case "additionalProperties":
            return [...instancePath, error.params.additionalProperty];
        default:
            return instancePath;
    }
}
function getErrorValue(obj, error) {
    const path = getErrorPath(error);
    let current = obj;
    for (const segment of path) {
        current = current[segment];
    }
    return current;
}
/**
 * Converts a json pointer into a array of reference tokens
 */
function parseJsonPointer(pointer) {
    if (pointer === "") {
        return [];
    }
    if (pointer.charAt(0) !== "/") {
        compilerAssert(false, `Invalid JSON pointer: "${pointer}"`);
    }
    return pointer.substring(1).split(/\//).map(unescape);
}
/**
 * Unescape a reference token
 *
 * @param str
 * @returns {string}
 */
function unescape(str) {
    return str.replace(/~1/g, "/").replace(/~0/g, "~");
}

// Contains all intrinsic data setter or getter
// Anything that the TypeSpec check might should be here.
function createStateSymbol$1(name) {
    return Symbol.for(`TypeSpec.${name}`);
}
const stateKeys = {
    minValues: createStateSymbol$1("minValues"),
    maxValues: createStateSymbol$1("maxValues"),
    minValueExclusive: createStateSymbol$1("minValueExclusive"),
    maxValueExclusive: createStateSymbol$1("maxValueExclusive"),
    minLength: createStateSymbol$1("minLengthValues"),
    maxLength: createStateSymbol$1("maxLengthValues"),
    minItems: createStateSymbol$1("minItems"),
    maxItems: createStateSymbol$1("maxItems"),
    docs: createStateSymbol$1("docs"),
    returnDocs: createStateSymbol$1("returnsDocs"),
    errorsDocs: createStateSymbol$1("errorDocs"),
    discriminator: createStateSymbol$1("discriminator"),
};
// #region @minValue
function setMinValue(program, target, value) {
    program.stateMap(stateKeys.minValues).set(target, value);
}
function getMinValueAsNumeric(program, target) {
    return program.stateMap(stateKeys.minValues).get(target);
}
function getMinValue(program, target) {
    return getMinValueAsNumeric(program, target)?.asNumber() ?? undefined;
}
// #endregion @minValue
// #region @maxValue
function setMaxValue(program, target, value) {
    program.stateMap(stateKeys.maxValues).set(target, value);
}
function getMaxValueAsNumeric(program, target) {
    return program.stateMap(stateKeys.maxValues).get(target);
}
function getMaxValue(program, target) {
    return getMaxValueAsNumeric(program, target)?.asNumber() ?? undefined;
}
// #endregion @maxValue
// #region @minValueExclusive
function setMinValueExclusive(program, target, value) {
    program.stateMap(stateKeys.minValueExclusive).set(target, value);
}
function getMinValueExclusiveAsNumeric(program, target) {
    return program.stateMap(stateKeys.minValueExclusive).get(target);
}
function getMinValueExclusive(program, target) {
    return getMinValueExclusiveAsNumeric(program, target)?.asNumber() ?? undefined;
}
// #endregion @minValueExclusive
// #region @maxValueExclusive
function setMaxValueExclusive(program, target, value) {
    program.stateMap(stateKeys.maxValueExclusive).set(target, value);
}
function getMaxValueExclusiveAsNumeric(program, target) {
    return program.stateMap(stateKeys.maxValueExclusive).get(target);
}
function getMaxValueExclusive(program, target) {
    return getMaxValueExclusiveAsNumeric(program, target)?.asNumber() ?? undefined;
}
// #endregion @maxValueExclusive
// #region @minLength
function setMinLength(program, target, value) {
    program.stateMap(stateKeys.minLength).set(target, value);
}
/**
 * Get the minimum length of a string type as a {@link Numeric} value.
 * @param program Current program
 * @param target Type with the `@minLength` decorator
 */
function getMinLengthAsNumeric(program, target) {
    return program.stateMap(stateKeys.minLength).get(target);
}
function getMinLength(program, target) {
    return getMinLengthAsNumeric(program, target)?.asNumber() ?? undefined;
}
// #endregion @minLength
// #region @maxLength
function setMaxLength(program, target, value) {
    program.stateMap(stateKeys.maxLength).set(target, value);
}
/**
 * Get the minimum length of a string type as a {@link Numeric} value.
 * @param program Current program
 * @param target Type with the `@maxLength` decorator
 */
function getMaxLengthAsNumeric(program, target) {
    return program.stateMap(stateKeys.maxLength).get(target);
}
function getMaxLength(program, target) {
    return getMaxLengthAsNumeric(program, target)?.asNumber() ?? undefined;
}
// #endregion @maxLength
// #region @minItems
function setMinItems(program, target, value) {
    program.stateMap(stateKeys.minItems).set(target, value);
}
function getMinItemsAsNumeric(program, target) {
    return program.stateMap(stateKeys.minItems).get(target);
}
function getMinItems(program, target) {
    return getMinItemsAsNumeric(program, target)?.asNumber() ?? undefined;
}
// #endregion @minItems
// #region @minItems
function setMaxItems(program, target, value) {
    program.stateMap(stateKeys.maxItems).set(target, value);
}
function getMaxItemsAsNumeric(program, target) {
    return program.stateMap(stateKeys.maxItems).get(target);
}
function getMaxItems(program, target) {
    return getMaxItemsAsNumeric(program, target)?.asNumber() ?? undefined;
}
/** @internal */
function setDocData(program, target, key, data) {
    program.stateMap(getDocKey(key)).set(target, data);
}
function getDocKey(target) {
    switch (target) {
        case "self":
            return stateKeys.docs;
        case "returns":
            return stateKeys.returnDocs;
        case "errors":
            return stateKeys.errorsDocs;
    }
}
/**
 * @internal
 * Get the documentation information for the given type. In most cases you probably just want to use {@link getDoc}
 * @param program Program
 * @param target Type
 * @returns Doc data with source information.
 */
function getDocDataInternal(program, target, key) {
    return program.stateMap(getDocKey(key)).get(target);
}
/**
 * Get the documentation information for the given type. In most cases you probably just want to use {@link getDoc}
 * @param program Program
 * @param target Type
 * @returns Doc data with source information.
 */
function getDocData(program, target) {
    return getDocDataInternal(program, target, "self");
}
function setDiscriminator(program, entity, discriminator) {
    program.stateMap(stateKeys.discriminator).set(entity, discriminator);
}
function getDiscriminator(program, entity) {
    return program.stateMap(stateKeys.discriminator).get(entity);
}
function getDiscriminatedTypes(program) {
    return [...program.stateMap(stateKeys.discriminator).entries()];
}
// #endregion

const namespace = "TypeSpec";
const indexTypeKey = Symbol.for(`TypeSpec.index`);
const $indexer = (context, target, key, value) => {
    const indexer = { key, value };
    context.program.stateMap(indexTypeKey).set(target, indexer);
};
function getIndexer(program, target) {
    return program.stateMap(indexTypeKey).get(target);
}
/**
 * @internal to be used to set the `@doc` from doc comment.
 */
const $docFromComment = (context, target, key, text) => {
    setDocData(context.program, target, key, { value: text, source: "comment" });
};

var f0 = /*#__PURE__*/Object.freeze({
	__proto__: null,
	$docFromComment: $docFromComment,
	$indexer: $indexer,
	getIndexer: getIndexer,
	namespace: namespace
});

function getLocationContext(program, type) {
    const sourceLocation = getSourceLocation(type);
    if (sourceLocation.isSynthetic) {
        return { type: "synthetic" };
    }
    return program.getSourceFileLocationContext(sourceLocation.file);
}

//
// Generated by scripts/regen-nonascii-map.js
// on node v18.16.0 with unicode 15.0.
//
/**
 * @internal
 *
 * Map of non-ascii characters that are valid in an identifier. Each pair of
 * numbers represents an inclusive range of code points.
 */
//prettier-ignore
const nonAsciiIdentifierMap = [
    0xa0, 0x377,
    0x37a, 0x37f,
    0x384, 0x38a,
    0x38c, 0x38c,
    0x38e, 0x3a1,
    0x3a3, 0x52f,
    0x531, 0x556,
    0x559, 0x58a,
    0x58d, 0x58f,
    0x591, 0x5c7,
    0x5d0, 0x5ea,
    0x5ef, 0x5f4,
    0x600, 0x70d,
    0x70f, 0x74a,
    0x74d, 0x7b1,
    0x7c0, 0x7fa,
    0x7fd, 0x82d,
    0x830, 0x83e,
    0x840, 0x85b,
    0x85e, 0x85e,
    0x860, 0x86a,
    0x870, 0x88e,
    0x890, 0x891,
    0x898, 0x983,
    0x985, 0x98c,
    0x98f, 0x990,
    0x993, 0x9a8,
    0x9aa, 0x9b0,
    0x9b2, 0x9b2,
    0x9b6, 0x9b9,
    0x9bc, 0x9c4,
    0x9c7, 0x9c8,
    0x9cb, 0x9ce,
    0x9d7, 0x9d7,
    0x9dc, 0x9dd,
    0x9df, 0x9e3,
    0x9e6, 0x9fe,
    0xa01, 0xa03,
    0xa05, 0xa0a,
    0xa0f, 0xa10,
    0xa13, 0xa28,
    0xa2a, 0xa30,
    0xa32, 0xa33,
    0xa35, 0xa36,
    0xa38, 0xa39,
    0xa3c, 0xa3c,
    0xa3e, 0xa42,
    0xa47, 0xa48,
    0xa4b, 0xa4d,
    0xa51, 0xa51,
    0xa59, 0xa5c,
    0xa5e, 0xa5e,
    0xa66, 0xa76,
    0xa81, 0xa83,
    0xa85, 0xa8d,
    0xa8f, 0xa91,
    0xa93, 0xaa8,
    0xaaa, 0xab0,
    0xab2, 0xab3,
    0xab5, 0xab9,
    0xabc, 0xac5,
    0xac7, 0xac9,
    0xacb, 0xacd,
    0xad0, 0xad0,
    0xae0, 0xae3,
    0xae6, 0xaf1,
    0xaf9, 0xaff,
    0xb01, 0xb03,
    0xb05, 0xb0c,
    0xb0f, 0xb10,
    0xb13, 0xb28,
    0xb2a, 0xb30,
    0xb32, 0xb33,
    0xb35, 0xb39,
    0xb3c, 0xb44,
    0xb47, 0xb48,
    0xb4b, 0xb4d,
    0xb55, 0xb57,
    0xb5c, 0xb5d,
    0xb5f, 0xb63,
    0xb66, 0xb77,
    0xb82, 0xb83,
    0xb85, 0xb8a,
    0xb8e, 0xb90,
    0xb92, 0xb95,
    0xb99, 0xb9a,
    0xb9c, 0xb9c,
    0xb9e, 0xb9f,
    0xba3, 0xba4,
    0xba8, 0xbaa,
    0xbae, 0xbb9,
    0xbbe, 0xbc2,
    0xbc6, 0xbc8,
    0xbca, 0xbcd,
    0xbd0, 0xbd0,
    0xbd7, 0xbd7,
    0xbe6, 0xbfa,
    0xc00, 0xc0c,
    0xc0e, 0xc10,
    0xc12, 0xc28,
    0xc2a, 0xc39,
    0xc3c, 0xc44,
    0xc46, 0xc48,
    0xc4a, 0xc4d,
    0xc55, 0xc56,
    0xc58, 0xc5a,
    0xc5d, 0xc5d,
    0xc60, 0xc63,
    0xc66, 0xc6f,
    0xc77, 0xc8c,
    0xc8e, 0xc90,
    0xc92, 0xca8,
    0xcaa, 0xcb3,
    0xcb5, 0xcb9,
    0xcbc, 0xcc4,
    0xcc6, 0xcc8,
    0xcca, 0xccd,
    0xcd5, 0xcd6,
    0xcdd, 0xcde,
    0xce0, 0xce3,
    0xce6, 0xcef,
    0xcf1, 0xcf3,
    0xd00, 0xd0c,
    0xd0e, 0xd10,
    0xd12, 0xd44,
    0xd46, 0xd48,
    0xd4a, 0xd4f,
    0xd54, 0xd63,
    0xd66, 0xd7f,
    0xd81, 0xd83,
    0xd85, 0xd96,
    0xd9a, 0xdb1,
    0xdb3, 0xdbb,
    0xdbd, 0xdbd,
    0xdc0, 0xdc6,
    0xdca, 0xdca,
    0xdcf, 0xdd4,
    0xdd6, 0xdd6,
    0xdd8, 0xddf,
    0xde6, 0xdef,
    0xdf2, 0xdf4,
    0xe01, 0xe3a,
    0xe3f, 0xe5b,
    0xe81, 0xe82,
    0xe84, 0xe84,
    0xe86, 0xe8a,
    0xe8c, 0xea3,
    0xea5, 0xea5,
    0xea7, 0xebd,
    0xec0, 0xec4,
    0xec6, 0xec6,
    0xec8, 0xece,
    0xed0, 0xed9,
    0xedc, 0xedf,
    0xf00, 0xf47,
    0xf49, 0xf6c,
    0xf71, 0xf97,
    0xf99, 0xfbc,
    0xfbe, 0xfcc,
    0xfce, 0xfda,
    0x1000, 0x10c5,
    0x10c7, 0x10c7,
    0x10cd, 0x10cd,
    0x10d0, 0x1248,
    0x124a, 0x124d,
    0x1250, 0x1256,
    0x1258, 0x1258,
    0x125a, 0x125d,
    0x1260, 0x1288,
    0x128a, 0x128d,
    0x1290, 0x12b0,
    0x12b2, 0x12b5,
    0x12b8, 0x12be,
    0x12c0, 0x12c0,
    0x12c2, 0x12c5,
    0x12c8, 0x12d6,
    0x12d8, 0x1310,
    0x1312, 0x1315,
    0x1318, 0x135a,
    0x135d, 0x137c,
    0x1380, 0x1399,
    0x13a0, 0x13f5,
    0x13f8, 0x13fd,
    0x1400, 0x169c,
    0x16a0, 0x16f8,
    0x1700, 0x1715,
    0x171f, 0x1736,
    0x1740, 0x1753,
    0x1760, 0x176c,
    0x176e, 0x1770,
    0x1772, 0x1773,
    0x1780, 0x17dd,
    0x17e0, 0x17e9,
    0x17f0, 0x17f9,
    0x1800, 0x1819,
    0x1820, 0x1878,
    0x1880, 0x18aa,
    0x18b0, 0x18f5,
    0x1900, 0x191e,
    0x1920, 0x192b,
    0x1930, 0x193b,
    0x1940, 0x1940,
    0x1944, 0x196d,
    0x1970, 0x1974,
    0x1980, 0x19ab,
    0x19b0, 0x19c9,
    0x19d0, 0x19da,
    0x19de, 0x1a1b,
    0x1a1e, 0x1a5e,
    0x1a60, 0x1a7c,
    0x1a7f, 0x1a89,
    0x1a90, 0x1a99,
    0x1aa0, 0x1aad,
    0x1ab0, 0x1ace,
    0x1b00, 0x1b4c,
    0x1b50, 0x1b7e,
    0x1b80, 0x1bf3,
    0x1bfc, 0x1c37,
    0x1c3b, 0x1c49,
    0x1c4d, 0x1c88,
    0x1c90, 0x1cba,
    0x1cbd, 0x1cc7,
    0x1cd0, 0x1cfa,
    0x1d00, 0x1f15,
    0x1f18, 0x1f1d,
    0x1f20, 0x1f45,
    0x1f48, 0x1f4d,
    0x1f50, 0x1f57,
    0x1f59, 0x1f59,
    0x1f5b, 0x1f5b,
    0x1f5d, 0x1f5d,
    0x1f5f, 0x1f7d,
    0x1f80, 0x1fb4,
    0x1fb6, 0x1fc4,
    0x1fc6, 0x1fd3,
    0x1fd6, 0x1fdb,
    0x1fdd, 0x1fef,
    0x1ff2, 0x1ff4,
    0x1ff6, 0x1ffe,
    0x2000, 0x200d,
    0x2010, 0x2027,
    0x202a, 0x2064,
    0x2066, 0x2071,
    0x2074, 0x208e,
    0x2090, 0x209c,
    0x20a0, 0x20c0,
    0x20d0, 0x20f0,
    0x2100, 0x218b,
    0x2190, 0x2426,
    0x2440, 0x244a,
    0x2460, 0x2b73,
    0x2b76, 0x2b95,
    0x2b97, 0x2cf3,
    0x2cf9, 0x2d25,
    0x2d27, 0x2d27,
    0x2d2d, 0x2d2d,
    0x2d30, 0x2d67,
    0x2d6f, 0x2d70,
    0x2d7f, 0x2d96,
    0x2da0, 0x2da6,
    0x2da8, 0x2dae,
    0x2db0, 0x2db6,
    0x2db8, 0x2dbe,
    0x2dc0, 0x2dc6,
    0x2dc8, 0x2dce,
    0x2dd0, 0x2dd6,
    0x2dd8, 0x2dde,
    0x2de0, 0x2e5d,
    0x2e80, 0x2e99,
    0x2e9b, 0x2ef3,
    0x2f00, 0x2fd5,
    0x2ff0, 0x2ffb,
    0x3000, 0x303f,
    0x3041, 0x3096,
    0x3099, 0x30ff,
    0x3105, 0x312f,
    0x3131, 0x318e,
    0x3190, 0x31e3,
    0x31f0, 0x321e,
    0x3220, 0xa48c,
    0xa490, 0xa4c6,
    0xa4d0, 0xa62b,
    0xa640, 0xa6f7,
    0xa700, 0xa7ca,
    0xa7d0, 0xa7d1,
    0xa7d3, 0xa7d3,
    0xa7d5, 0xa7d9,
    0xa7f2, 0xa82c,
    0xa830, 0xa839,
    0xa840, 0xa877,
    0xa880, 0xa8c5,
    0xa8ce, 0xa8d9,
    0xa8e0, 0xa953,
    0xa95f, 0xa97c,
    0xa980, 0xa9cd,
    0xa9cf, 0xa9d9,
    0xa9de, 0xa9fe,
    0xaa00, 0xaa36,
    0xaa40, 0xaa4d,
    0xaa50, 0xaa59,
    0xaa5c, 0xaac2,
    0xaadb, 0xaaf6,
    0xab01, 0xab06,
    0xab09, 0xab0e,
    0xab11, 0xab16,
    0xab20, 0xab26,
    0xab28, 0xab2e,
    0xab30, 0xab6b,
    0xab70, 0xabed,
    0xabf0, 0xabf9,
    0xac00, 0xd7a3,
    0xd7b0, 0xd7c6,
    0xd7cb, 0xd7fb,
    0xf900, 0xfa6d,
    0xfa70, 0xfad9,
    0xfb00, 0xfb06,
    0xfb13, 0xfb17,
    0xfb1d, 0xfb36,
    0xfb38, 0xfb3c,
    0xfb3e, 0xfb3e,
    0xfb40, 0xfb41,
    0xfb43, 0xfb44,
    0xfb46, 0xfbc2,
    0xfbd3, 0xfd8f,
    0xfd92, 0xfdc7,
    0xfdcf, 0xfdcf,
    0xfdf0, 0xfe19,
    0xfe20, 0xfe52,
    0xfe54, 0xfe66,
    0xfe68, 0xfe6b,
    0xfe70, 0xfe74,
    0xfe76, 0xfefc,
    0xfeff, 0xfeff,
    0xff01, 0xffbe,
    0xffc2, 0xffc7,
    0xffca, 0xffcf,
    0xffd2, 0xffd7,
    0xffda, 0xffdc,
    0xffe0, 0xffe6,
    0xffe8, 0xffee,
    0xfff9, 0xfffc,
    0x10000, 0x1000b,
    0x1000d, 0x10026,
    0x10028, 0x1003a,
    0x1003c, 0x1003d,
    0x1003f, 0x1004d,
    0x10050, 0x1005d,
    0x10080, 0x100fa,
    0x10100, 0x10102,
    0x10107, 0x10133,
    0x10137, 0x1018e,
    0x10190, 0x1019c,
    0x101a0, 0x101a0,
    0x101d0, 0x101fd,
    0x10280, 0x1029c,
    0x102a0, 0x102d0,
    0x102e0, 0x102fb,
    0x10300, 0x10323,
    0x1032d, 0x1034a,
    0x10350, 0x1037a,
    0x10380, 0x1039d,
    0x1039f, 0x103c3,
    0x103c8, 0x103d5,
    0x10400, 0x1049d,
    0x104a0, 0x104a9,
    0x104b0, 0x104d3,
    0x104d8, 0x104fb,
    0x10500, 0x10527,
    0x10530, 0x10563,
    0x1056f, 0x1057a,
    0x1057c, 0x1058a,
    0x1058c, 0x10592,
    0x10594, 0x10595,
    0x10597, 0x105a1,
    0x105a3, 0x105b1,
    0x105b3, 0x105b9,
    0x105bb, 0x105bc,
    0x10600, 0x10736,
    0x10740, 0x10755,
    0x10760, 0x10767,
    0x10780, 0x10785,
    0x10787, 0x107b0,
    0x107b2, 0x107ba,
    0x10800, 0x10805,
    0x10808, 0x10808,
    0x1080a, 0x10835,
    0x10837, 0x10838,
    0x1083c, 0x1083c,
    0x1083f, 0x10855,
    0x10857, 0x1089e,
    0x108a7, 0x108af,
    0x108e0, 0x108f2,
    0x108f4, 0x108f5,
    0x108fb, 0x1091b,
    0x1091f, 0x10939,
    0x1093f, 0x1093f,
    0x10980, 0x109b7,
    0x109bc, 0x109cf,
    0x109d2, 0x10a03,
    0x10a05, 0x10a06,
    0x10a0c, 0x10a13,
    0x10a15, 0x10a17,
    0x10a19, 0x10a35,
    0x10a38, 0x10a3a,
    0x10a3f, 0x10a48,
    0x10a50, 0x10a58,
    0x10a60, 0x10a9f,
    0x10ac0, 0x10ae6,
    0x10aeb, 0x10af6,
    0x10b00, 0x10b35,
    0x10b39, 0x10b55,
    0x10b58, 0x10b72,
    0x10b78, 0x10b91,
    0x10b99, 0x10b9c,
    0x10ba9, 0x10baf,
    0x10c00, 0x10c48,
    0x10c80, 0x10cb2,
    0x10cc0, 0x10cf2,
    0x10cfa, 0x10d27,
    0x10d30, 0x10d39,
    0x10e60, 0x10e7e,
    0x10e80, 0x10ea9,
    0x10eab, 0x10ead,
    0x10eb0, 0x10eb1,
    0x10efd, 0x10f27,
    0x10f30, 0x10f59,
    0x10f70, 0x10f89,
    0x10fb0, 0x10fcb,
    0x10fe0, 0x10ff6,
    0x11000, 0x1104d,
    0x11052, 0x11075,
    0x1107f, 0x110c2,
    0x110cd, 0x110cd,
    0x110d0, 0x110e8,
    0x110f0, 0x110f9,
    0x11100, 0x11134,
    0x11136, 0x11147,
    0x11150, 0x11176,
    0x11180, 0x111df,
    0x111e1, 0x111f4,
    0x11200, 0x11211,
    0x11213, 0x11241,
    0x11280, 0x11286,
    0x11288, 0x11288,
    0x1128a, 0x1128d,
    0x1128f, 0x1129d,
    0x1129f, 0x112a9,
    0x112b0, 0x112ea,
    0x112f0, 0x112f9,
    0x11300, 0x11303,
    0x11305, 0x1130c,
    0x1130f, 0x11310,
    0x11313, 0x11328,
    0x1132a, 0x11330,
    0x11332, 0x11333,
    0x11335, 0x11339,
    0x1133b, 0x11344,
    0x11347, 0x11348,
    0x1134b, 0x1134d,
    0x11350, 0x11350,
    0x11357, 0x11357,
    0x1135d, 0x11363,
    0x11366, 0x1136c,
    0x11370, 0x11374,
    0x11400, 0x1145b,
    0x1145d, 0x11461,
    0x11480, 0x114c7,
    0x114d0, 0x114d9,
    0x11580, 0x115b5,
    0x115b8, 0x115dd,
    0x11600, 0x11644,
    0x11650, 0x11659,
    0x11660, 0x1166c,
    0x11680, 0x116b9,
    0x116c0, 0x116c9,
    0x11700, 0x1171a,
    0x1171d, 0x1172b,
    0x11730, 0x11746,
    0x11800, 0x1183b,
    0x118a0, 0x118f2,
    0x118ff, 0x11906,
    0x11909, 0x11909,
    0x1190c, 0x11913,
    0x11915, 0x11916,
    0x11918, 0x11935,
    0x11937, 0x11938,
    0x1193b, 0x11946,
    0x11950, 0x11959,
    0x119a0, 0x119a7,
    0x119aa, 0x119d7,
    0x119da, 0x119e4,
    0x11a00, 0x11a47,
    0x11a50, 0x11aa2,
    0x11ab0, 0x11af8,
    0x11b00, 0x11b09,
    0x11c00, 0x11c08,
    0x11c0a, 0x11c36,
    0x11c38, 0x11c45,
    0x11c50, 0x11c6c,
    0x11c70, 0x11c8f,
    0x11c92, 0x11ca7,
    0x11ca9, 0x11cb6,
    0x11d00, 0x11d06,
    0x11d08, 0x11d09,
    0x11d0b, 0x11d36,
    0x11d3a, 0x11d3a,
    0x11d3c, 0x11d3d,
    0x11d3f, 0x11d47,
    0x11d50, 0x11d59,
    0x11d60, 0x11d65,
    0x11d67, 0x11d68,
    0x11d6a, 0x11d8e,
    0x11d90, 0x11d91,
    0x11d93, 0x11d98,
    0x11da0, 0x11da9,
    0x11ee0, 0x11ef8,
    0x11f00, 0x11f10,
    0x11f12, 0x11f3a,
    0x11f3e, 0x11f59,
    0x11fb0, 0x11fb0,
    0x11fc0, 0x11ff1,
    0x11fff, 0x12399,
    0x12400, 0x1246e,
    0x12470, 0x12474,
    0x12480, 0x12543,
    0x12f90, 0x12ff2,
    0x13000, 0x13455,
    0x14400, 0x14646,
    0x16800, 0x16a38,
    0x16a40, 0x16a5e,
    0x16a60, 0x16a69,
    0x16a6e, 0x16abe,
    0x16ac0, 0x16ac9,
    0x16ad0, 0x16aed,
    0x16af0, 0x16af5,
    0x16b00, 0x16b45,
    0x16b50, 0x16b59,
    0x16b5b, 0x16b61,
    0x16b63, 0x16b77,
    0x16b7d, 0x16b8f,
    0x16e40, 0x16e9a,
    0x16f00, 0x16f4a,
    0x16f4f, 0x16f87,
    0x16f8f, 0x16f9f,
    0x16fe0, 0x16fe4,
    0x16ff0, 0x16ff1,
    0x17000, 0x187f7,
    0x18800, 0x18cd5,
    0x18d00, 0x18d08,
    0x1aff0, 0x1aff3,
    0x1aff5, 0x1affb,
    0x1affd, 0x1affe,
    0x1b000, 0x1b122,
    0x1b132, 0x1b132,
    0x1b150, 0x1b152,
    0x1b155, 0x1b155,
    0x1b164, 0x1b167,
    0x1b170, 0x1b2fb,
    0x1bc00, 0x1bc6a,
    0x1bc70, 0x1bc7c,
    0x1bc80, 0x1bc88,
    0x1bc90, 0x1bc99,
    0x1bc9c, 0x1bca3,
    0x1cf00, 0x1cf2d,
    0x1cf30, 0x1cf46,
    0x1cf50, 0x1cfc3,
    0x1d000, 0x1d0f5,
    0x1d100, 0x1d126,
    0x1d129, 0x1d1ea,
    0x1d200, 0x1d245,
    0x1d2c0, 0x1d2d3,
    0x1d2e0, 0x1d2f3,
    0x1d300, 0x1d356,
    0x1d360, 0x1d378,
    0x1d400, 0x1d454,
    0x1d456, 0x1d49c,
    0x1d49e, 0x1d49f,
    0x1d4a2, 0x1d4a2,
    0x1d4a5, 0x1d4a6,
    0x1d4a9, 0x1d4ac,
    0x1d4ae, 0x1d4b9,
    0x1d4bb, 0x1d4bb,
    0x1d4bd, 0x1d4c3,
    0x1d4c5, 0x1d505,
    0x1d507, 0x1d50a,
    0x1d50d, 0x1d514,
    0x1d516, 0x1d51c,
    0x1d51e, 0x1d539,
    0x1d53b, 0x1d53e,
    0x1d540, 0x1d544,
    0x1d546, 0x1d546,
    0x1d54a, 0x1d550,
    0x1d552, 0x1d6a5,
    0x1d6a8, 0x1d7cb,
    0x1d7ce, 0x1da8b,
    0x1da9b, 0x1da9f,
    0x1daa1, 0x1daaf,
    0x1df00, 0x1df1e,
    0x1df25, 0x1df2a,
    0x1e000, 0x1e006,
    0x1e008, 0x1e018,
    0x1e01b, 0x1e021,
    0x1e023, 0x1e024,
    0x1e026, 0x1e02a,
    0x1e030, 0x1e06d,
    0x1e08f, 0x1e08f,
    0x1e100, 0x1e12c,
    0x1e130, 0x1e13d,
    0x1e140, 0x1e149,
    0x1e14e, 0x1e14f,
    0x1e290, 0x1e2ae,
    0x1e2c0, 0x1e2f9,
    0x1e2ff, 0x1e2ff,
    0x1e4d0, 0x1e4f9,
    0x1e7e0, 0x1e7e6,
    0x1e7e8, 0x1e7eb,
    0x1e7ed, 0x1e7ee,
    0x1e7f0, 0x1e7fe,
    0x1e800, 0x1e8c4,
    0x1e8c7, 0x1e8d6,
    0x1e900, 0x1e94b,
    0x1e950, 0x1e959,
    0x1e95e, 0x1e95f,
    0x1ec71, 0x1ecb4,
    0x1ed01, 0x1ed3d,
    0x1ee00, 0x1ee03,
    0x1ee05, 0x1ee1f,
    0x1ee21, 0x1ee22,
    0x1ee24, 0x1ee24,
    0x1ee27, 0x1ee27,
    0x1ee29, 0x1ee32,
    0x1ee34, 0x1ee37,
    0x1ee39, 0x1ee39,
    0x1ee3b, 0x1ee3b,
    0x1ee42, 0x1ee42,
    0x1ee47, 0x1ee47,
    0x1ee49, 0x1ee49,
    0x1ee4b, 0x1ee4b,
    0x1ee4d, 0x1ee4f,
    0x1ee51, 0x1ee52,
    0x1ee54, 0x1ee54,
    0x1ee57, 0x1ee57,
    0x1ee59, 0x1ee59,
    0x1ee5b, 0x1ee5b,
    0x1ee5d, 0x1ee5d,
    0x1ee5f, 0x1ee5f,
    0x1ee61, 0x1ee62,
    0x1ee64, 0x1ee64,
    0x1ee67, 0x1ee6a,
    0x1ee6c, 0x1ee72,
    0x1ee74, 0x1ee77,
    0x1ee79, 0x1ee7c,
    0x1ee7e, 0x1ee7e,
    0x1ee80, 0x1ee89,
    0x1ee8b, 0x1ee9b,
    0x1eea1, 0x1eea3,
    0x1eea5, 0x1eea9,
    0x1eeab, 0x1eebb,
    0x1eef0, 0x1eef1,
    0x1f000, 0x1f02b,
    0x1f030, 0x1f093,
    0x1f0a0, 0x1f0ae,
    0x1f0b1, 0x1f0bf,
    0x1f0c1, 0x1f0cf,
    0x1f0d1, 0x1f0f5,
    0x1f100, 0x1f1ad,
    0x1f1e6, 0x1f202,
    0x1f210, 0x1f23b,
    0x1f240, 0x1f248,
    0x1f250, 0x1f251,
    0x1f260, 0x1f265,
    0x1f300, 0x1f6d7,
    0x1f6dc, 0x1f6ec,
    0x1f6f0, 0x1f6fc,
    0x1f700, 0x1f776,
    0x1f77b, 0x1f7d9,
    0x1f7e0, 0x1f7eb,
    0x1f7f0, 0x1f7f0,
    0x1f800, 0x1f80b,
    0x1f810, 0x1f847,
    0x1f850, 0x1f859,
    0x1f860, 0x1f887,
    0x1f890, 0x1f8ad,
    0x1f8b0, 0x1f8b1,
    0x1f900, 0x1fa53,
    0x1fa60, 0x1fa6d,
    0x1fa70, 0x1fa7c,
    0x1fa80, 0x1fa88,
    0x1fa90, 0x1fabd,
    0x1fabf, 0x1fac5,
    0x1face, 0x1fadb,
    0x1fae0, 0x1fae8,
    0x1faf0, 0x1faf8,
    0x1fb00, 0x1fb92,
    0x1fb94, 0x1fbca,
    0x1fbf0, 0x1fbf9,
    0x20000, 0x2a6df,
    0x2a700, 0x2b739,
    0x2b740, 0x2b81d,
    0x2b820, 0x2cea1,
    0x2ceb0, 0x2ebe0,
    0x2f800, 0x2fa1d,
    0x30000, 0x3134a,
    0x31350, 0x323af,
    0xe0001, 0xe0001,
    0xe0020, 0xe007f,
    0xe0100, 0xe01ef,
];

function utf16CodeUnits(codePoint) {
    return codePoint >= 0x10000 ? 2 : 1;
}
function isHighSurrogate(ch) {
    return ch >= 0xd800 && ch <= 0xdbff;
}
function isLowSurrogate(ch) {
    return ch >= 0xdc00 && ch <= 0xdfff;
}
function isLineBreak(ch) {
    return ch === 10 /* CharCode.LineFeed */ || ch === 13 /* CharCode.CarriageReturn */;
}
function isAsciiWhiteSpaceSingleLine(ch) {
    return (ch === 32 /* CharCode.Space */ ||
        ch === 9 /* CharCode.Tab */ ||
        ch === 11 /* CharCode.VerticalTab */ ||
        ch === 12 /* CharCode.FormFeed */);
}
function isNonAsciiWhiteSpaceSingleLine(ch) {
    return (ch === 133 /* CharCode.NextLine */ || // not considered a line break
        ch === 8206 /* CharCode.LeftToRightMark */ ||
        ch === 8207 /* CharCode.RightToLeftMark */ ||
        ch === 8232 /* CharCode.LineSeparator */ ||
        ch === 8233 /* CharCode.ParagraphSeparator */);
}
function isWhiteSpace(ch) {
    return isWhiteSpaceSingleLine(ch) || isLineBreak(ch);
}
function isWhiteSpaceSingleLine(ch) {
    return (isAsciiWhiteSpaceSingleLine(ch) ||
        (ch > 127 /* CharCode.MaxAscii */ && isNonAsciiWhiteSpaceSingleLine(ch)));
}
function trim$1(str) {
    let start = 0;
    let end = str.length - 1;
    if (!isWhiteSpace(str.charCodeAt(start)) && !isWhiteSpace(str.charCodeAt(end))) {
        return str;
    }
    while (isWhiteSpace(str.charCodeAt(start))) {
        start++;
    }
    while (isWhiteSpace(str.charCodeAt(end))) {
        end--;
    }
    return str.substring(start, end + 1);
}
function isDigit(ch) {
    return ch >= 48 /* CharCode._0 */ && ch <= 57 /* CharCode._9 */;
}
function isHexDigit(ch) {
    return (isDigit(ch) || (ch >= 65 /* CharCode.A */ && ch <= 70 /* CharCode.F */) || (ch >= 97 /* CharCode.a */ && ch <= 102 /* CharCode.f */));
}
function isBinaryDigit(ch) {
    return ch === 48 /* CharCode._0 */ || ch === 49 /* CharCode._1 */;
}
function isLowercaseAsciiLetter(ch) {
    return ch >= 97 /* CharCode.a */ && ch <= 122 /* CharCode.z */;
}
function isAsciiIdentifierStart(ch) {
    return ((ch >= 65 /* CharCode.A */ && ch <= 90 /* CharCode.Z */) ||
        (ch >= 97 /* CharCode.a */ && ch <= 122 /* CharCode.z */) ||
        ch === 36 /* CharCode.$ */ ||
        ch === 95 /* CharCode._ */);
}
function isAsciiIdentifierContinue(ch) {
    return ((ch >= 65 /* CharCode.A */ && ch <= 90 /* CharCode.Z */) ||
        (ch >= 97 /* CharCode.a */ && ch <= 122 /* CharCode.z */) ||
        (ch >= 48 /* CharCode._0 */ && ch <= 57 /* CharCode._9 */) ||
        ch === 36 /* CharCode.$ */ ||
        ch === 95 /* CharCode._ */);
}
function isIdentifierStart(codePoint) {
    return (isAsciiIdentifierStart(codePoint) ||
        (codePoint > 127 /* CharCode.MaxAscii */ && isNonAsciiIdentifierCharacter(codePoint)));
}
function isIdentifierContinue(codePoint) {
    return (isAsciiIdentifierContinue(codePoint) ||
        (codePoint > 127 /* CharCode.MaxAscii */ && isNonAsciiIdentifierCharacter(codePoint)));
}
function isNonAsciiIdentifierCharacter(codePoint) {
    return lookupInNonAsciiMap(codePoint, nonAsciiIdentifierMap);
}
function codePointBefore(text, pos) {
    if (pos <= 0 || pos > text.length) {
        return { char: undefined, size: 0 };
    }
    const ch = text.charCodeAt(pos - 1);
    if (!isLowSurrogate(ch) || !isHighSurrogate(text.charCodeAt(pos - 2))) {
        return { char: ch, size: 1 };
    }
    return { char: text.codePointAt(pos - 2), size: 2 };
}
function lookupInNonAsciiMap(codePoint, map) {
    // Perform binary search in one of the Unicode range maps
    let lo = 0;
    let hi = map.length;
    let mid;
    while (lo + 1 < hi) {
        mid = lo + (hi - lo) / 2;
        // mid has to be even to catch a range's beginning
        mid -= mid % 2;
        if (map[mid] <= codePoint && codePoint <= map[mid + 1]) {
            return true;
        }
        if (codePoint < map[mid]) {
            hi = mid;
        }
        else {
            lo = mid + 2;
        }
    }
    return false;
}

/**
 * Find the comment that is at given position, if any.
 *
 * A comment is at the given position if {@link Comment.pos} <= position <
 * {@link Comment.end}. Unlike {@link getNodeAtPosition}, the end node is
 * not included since comments can be adjacent to each other with no trivia
 * or punctuation between them.
 *
 * @internal
 */
function getCommentAtPosition(script, pos) {
    if (!script.parseOptions.comments) {
        // Not an assert since we might make this public and it would be external caller's responsibility.
        throw new Error("ParseOptions.comments must be enabled to use getCommentAtPosition.");
    }
    // Comments are ordered by increasing position, use binary search
    let low = 0;
    let high = script.comments.length - 1;
    while (low <= high) {
        const middle = low + ((high - low) >> 1);
        const candidate = script.comments[middle];
        if (pos >= candidate.end) {
            low = middle + 1;
        }
        else if (pos < candidate.pos) {
            high = middle - 1;
        }
        else {
            return candidate;
        }
    }
    return undefined;
}
/**
 * Adjust the given postion backwards before any trivia.
 */
function getPositionBeforeTrivia(script, pos) {
    if (!script.parseOptions.comments) {
        // Not an assert since we might make this public and it would be external caller's responsibility.
        throw new Error("ParseOptions.comments must be enabled to use getPositionBeforeTrivia.");
    }
    let comment;
    while (pos > 0) {
        if (isWhiteSpace(script.file.text.charCodeAt(pos - 1))) {
            do {
                pos--;
            } while (isWhiteSpace(script.file.text.charCodeAt(pos - 1)));
        }
        else if ((comment = getCommentAtPosition(script, pos - 1))) {
            pos = comment.pos;
        }
        else {
            // note at whitespace or comment
            break;
        }
    }
    return pos;
}

// All conflict markers consist of the same character repeated seven times.  If it is
// a <<<<<<< or >>>>>>> marker then it is also followed by a space.
const mergeConflictMarkerLength = 7;
var Token;
(function (Token) {
    Token[Token["None"] = 0] = "None";
    Token[Token["Invalid"] = 1] = "Invalid";
    Token[Token["EndOfFile"] = 2] = "EndOfFile";
    Token[Token["Identifier"] = 3] = "Identifier";
    Token[Token["NumericLiteral"] = 4] = "NumericLiteral";
    Token[Token["StringLiteral"] = 5] = "StringLiteral";
    Token[Token["StringTemplateHead"] = 6] = "StringTemplateHead";
    Token[Token["StringTemplateMiddle"] = 7] = "StringTemplateMiddle";
    Token[Token["StringTemplateTail"] = 8] = "StringTemplateTail";
    // Add new tokens above if they don't fit any of the categories below
    ///////////////////////////////////////////////////////////////
    // Trivia
    /** @internal */ Token[Token["__StartTrivia"] = 9] = "__StartTrivia";
    Token[Token["SingleLineComment"] = 9] = "SingleLineComment";
    Token[Token["MultiLineComment"] = 10] = "MultiLineComment";
    Token[Token["NewLine"] = 11] = "NewLine";
    Token[Token["Whitespace"] = 12] = "Whitespace";
    Token[Token["ConflictMarker"] = 13] = "ConflictMarker";
    // Add new trivia above
    /** @internal */ Token[Token["__EndTrivia"] = 14] = "__EndTrivia";
    ///////////////////////////////////////////////////////////////
    ///////////////////////////////////////////////////////////////
    // Doc comment content
    /** @internal */ Token[Token["__StartDocComment"] = 14] = "__StartDocComment";
    Token[Token["DocText"] = 14] = "DocText";
    Token[Token["DocCodeSpan"] = 15] = "DocCodeSpan";
    Token[Token["DocCodeFenceDelimiter"] = 16] = "DocCodeFenceDelimiter";
    /** @internal */ Token[Token["__EndDocComment"] = 17] = "__EndDocComment";
    ///////////////////////////////////////////////////////////////
    ///////////////////////////////////////////////////////////////
    // Punctuation
    /** @internal */ Token[Token["__StartPunctuation"] = 17] = "__StartPunctuation";
    Token[Token["OpenBrace"] = 17] = "OpenBrace";
    Token[Token["CloseBrace"] = 18] = "CloseBrace";
    Token[Token["OpenParen"] = 19] = "OpenParen";
    Token[Token["CloseParen"] = 20] = "CloseParen";
    Token[Token["OpenBracket"] = 21] = "OpenBracket";
    Token[Token["CloseBracket"] = 22] = "CloseBracket";
    Token[Token["Dot"] = 23] = "Dot";
    Token[Token["Ellipsis"] = 24] = "Ellipsis";
    Token[Token["Semicolon"] = 25] = "Semicolon";
    Token[Token["Comma"] = 26] = "Comma";
    Token[Token["LessThan"] = 27] = "LessThan";
    Token[Token["GreaterThan"] = 28] = "GreaterThan";
    Token[Token["Equals"] = 29] = "Equals";
    Token[Token["Ampersand"] = 30] = "Ampersand";
    Token[Token["Bar"] = 31] = "Bar";
    Token[Token["Question"] = 32] = "Question";
    Token[Token["Colon"] = 33] = "Colon";
    Token[Token["ColonColon"] = 34] = "ColonColon";
    Token[Token["At"] = 35] = "At";
    Token[Token["AtAt"] = 36] = "AtAt";
    Token[Token["Hash"] = 37] = "Hash";
    Token[Token["HashBrace"] = 38] = "HashBrace";
    Token[Token["HashBracket"] = 39] = "HashBracket";
    Token[Token["Star"] = 40] = "Star";
    Token[Token["ForwardSlash"] = 41] = "ForwardSlash";
    Token[Token["Plus"] = 42] = "Plus";
    Token[Token["Hyphen"] = 43] = "Hyphen";
    Token[Token["Exclamation"] = 44] = "Exclamation";
    Token[Token["LessThanEquals"] = 45] = "LessThanEquals";
    Token[Token["GreaterThanEquals"] = 46] = "GreaterThanEquals";
    Token[Token["AmpsersandAmpersand"] = 47] = "AmpsersandAmpersand";
    Token[Token["BarBar"] = 48] = "BarBar";
    Token[Token["EqualsEquals"] = 49] = "EqualsEquals";
    Token[Token["ExclamationEquals"] = 50] = "ExclamationEquals";
    Token[Token["EqualsGreaterThan"] = 51] = "EqualsGreaterThan";
    // Add new punctuation above
    /** @internal */ Token[Token["__EndPunctuation"] = 52] = "__EndPunctuation";
    ///////////////////////////////////////////////////////////////
    ///////////////////////////////////////////////////////////////
    // Statement keywords
    /** @internal */ Token[Token["__StartKeyword"] = 52] = "__StartKeyword";
    /** @internal */ Token[Token["__StartStatementKeyword"] = 52] = "__StartStatementKeyword";
    Token[Token["ImportKeyword"] = 52] = "ImportKeyword";
    Token[Token["ModelKeyword"] = 53] = "ModelKeyword";
    Token[Token["ScalarKeyword"] = 54] = "ScalarKeyword";
    Token[Token["NamespaceKeyword"] = 55] = "NamespaceKeyword";
    Token[Token["UsingKeyword"] = 56] = "UsingKeyword";
    Token[Token["OpKeyword"] = 57] = "OpKeyword";
    Token[Token["EnumKeyword"] = 58] = "EnumKeyword";
    Token[Token["AliasKeyword"] = 59] = "AliasKeyword";
    Token[Token["IsKeyword"] = 60] = "IsKeyword";
    Token[Token["InterfaceKeyword"] = 61] = "InterfaceKeyword";
    Token[Token["UnionKeyword"] = 62] = "UnionKeyword";
    Token[Token["ProjectionKeyword"] = 63] = "ProjectionKeyword";
    Token[Token["ElseKeyword"] = 64] = "ElseKeyword";
    Token[Token["IfKeyword"] = 65] = "IfKeyword";
    Token[Token["DecKeyword"] = 66] = "DecKeyword";
    Token[Token["FnKeyword"] = 67] = "FnKeyword";
    Token[Token["ConstKeyword"] = 68] = "ConstKeyword";
    Token[Token["InitKeyword"] = 69] = "InitKeyword";
    // Add new statement keyword above
    /** @internal */ Token[Token["__EndStatementKeyword"] = 70] = "__EndStatementKeyword";
    ///////////////////////////////////////////////////////////////
    ///////////////////////////////////////////////////////////////
    /** @internal */ Token[Token["__StartModifierKeyword"] = 70] = "__StartModifierKeyword";
    Token[Token["ExternKeyword"] = 70] = "ExternKeyword";
    /** @internal */ Token[Token["__EndModifierKeyword"] = 71] = "__EndModifierKeyword";
    ///////////////////////////////////////////////////////////////
    ///////////////////////////////////////////////////////////////
    // Other keywords
    Token[Token["ExtendsKeyword"] = 71] = "ExtendsKeyword";
    Token[Token["TrueKeyword"] = 72] = "TrueKeyword";
    Token[Token["FalseKeyword"] = 73] = "FalseKeyword";
    Token[Token["ReturnKeyword"] = 74] = "ReturnKeyword";
    Token[Token["VoidKeyword"] = 75] = "VoidKeyword";
    Token[Token["NeverKeyword"] = 76] = "NeverKeyword";
    Token[Token["UnknownKeyword"] = 77] = "UnknownKeyword";
    Token[Token["ValueOfKeyword"] = 78] = "ValueOfKeyword";
    Token[Token["TypeOfKeyword"] = 79] = "TypeOfKeyword";
    // Add new non-statement keyword above
    /** @internal */ Token[Token["__EndKeyword"] = 80] = "__EndKeyword";
    ///////////////////////////////////////////////////////////////
    /** @internal */ Token[Token["__Count"] = 80] = "__Count";
})(Token || (Token = {}));
/** @internal */
const TokenDisplay = getTokenDisplayTable([
    [Token.None, "none"],
    [Token.Invalid, "invalid"],
    [Token.EndOfFile, "end of file"],
    [Token.SingleLineComment, "single-line comment"],
    [Token.MultiLineComment, "multi-line comment"],
    [Token.ConflictMarker, "conflict marker"],
    [Token.NumericLiteral, "numeric literal"],
    [Token.StringLiteral, "string literal"],
    [Token.StringTemplateHead, "string template head"],
    [Token.StringTemplateMiddle, "string template middle"],
    [Token.StringTemplateTail, "string template tail"],
    [Token.NewLine, "newline"],
    [Token.Whitespace, "whitespace"],
    [Token.DocCodeFenceDelimiter, "doc code fence delimiter"],
    [Token.DocCodeSpan, "doc code span"],
    [Token.DocText, "doc text"],
    [Token.OpenBrace, "'{'"],
    [Token.CloseBrace, "'}'"],
    [Token.OpenParen, "'('"],
    [Token.CloseParen, "')'"],
    [Token.OpenBracket, "'['"],
    [Token.CloseBracket, "']'"],
    [Token.Dot, "'.'"],
    [Token.Ellipsis, "'...'"],
    [Token.Semicolon, "';'"],
    [Token.Comma, "','"],
    [Token.LessThan, "'<'"],
    [Token.GreaterThan, "'>'"],
    [Token.Equals, "'='"],
    [Token.Ampersand, "'&'"],
    [Token.Bar, "'|'"],
    [Token.Question, "'?'"],
    [Token.Colon, "':'"],
    [Token.ColonColon, "'::'"],
    [Token.At, "'@'"],
    [Token.AtAt, "'@@'"],
    [Token.Hash, "'#'"],
    [Token.HashBrace, "'#{'"],
    [Token.HashBracket, "'#['"],
    [Token.Star, "'*'"],
    [Token.ForwardSlash, "'/'"],
    [Token.Plus, "'+'"],
    [Token.Hyphen, "'-'"],
    [Token.Exclamation, "'!'"],
    [Token.LessThanEquals, "'<='"],
    [Token.GreaterThanEquals, "'>='"],
    [Token.AmpsersandAmpersand, "'&&'"],
    [Token.BarBar, "'||'"],
    [Token.EqualsEquals, "'=='"],
    [Token.ExclamationEquals, "'!='"],
    [Token.EqualsGreaterThan, "'=>'"],
    [Token.Identifier, "identifier"],
    [Token.ImportKeyword, "'import'"],
    [Token.ModelKeyword, "'model'"],
    [Token.ScalarKeyword, "'scalar'"],
    [Token.NamespaceKeyword, "'namespace'"],
    [Token.UsingKeyword, "'using'"],
    [Token.OpKeyword, "'op'"],
    [Token.EnumKeyword, "'enum'"],
    [Token.AliasKeyword, "'alias'"],
    [Token.IsKeyword, "'is'"],
    [Token.InterfaceKeyword, "'interface'"],
    [Token.UnionKeyword, "'union'"],
    [Token.ProjectionKeyword, "'projection'"],
    [Token.ElseKeyword, "'else'"],
    [Token.IfKeyword, "'if'"],
    [Token.DecKeyword, "'dec'"],
    [Token.FnKeyword, "'fn'"],
    [Token.ValueOfKeyword, "'valueof'"],
    [Token.TypeOfKeyword, "'typeof'"],
    [Token.ConstKeyword, "'const'"],
    [Token.InitKeyword, "'init'"],
    [Token.ExtendsKeyword, "'extends'"],
    [Token.TrueKeyword, "'true'"],
    [Token.FalseKeyword, "'false'"],
    [Token.ReturnKeyword, "'return'"],
    [Token.VoidKeyword, "'void'"],
    [Token.NeverKeyword, "'never'"],
    [Token.UnknownKeyword, "'unknown'"],
    [Token.ExternKeyword, "'extern'"],
]);
/** @internal */
const Keywords = new Map([
    ["import", Token.ImportKeyword],
    ["model", Token.ModelKeyword],
    ["scalar", Token.ScalarKeyword],
    ["namespace", Token.NamespaceKeyword],
    ["interface", Token.InterfaceKeyword],
    ["union", Token.UnionKeyword],
    ["if", Token.IfKeyword],
    ["else", Token.ElseKeyword],
    ["projection", Token.ProjectionKeyword],
    ["using", Token.UsingKeyword],
    ["op", Token.OpKeyword],
    ["extends", Token.ExtendsKeyword],
    ["is", Token.IsKeyword],
    ["enum", Token.EnumKeyword],
    ["alias", Token.AliasKeyword],
    ["dec", Token.DecKeyword],
    ["fn", Token.FnKeyword],
    ["valueof", Token.ValueOfKeyword],
    ["typeof", Token.TypeOfKeyword],
    ["const", Token.ConstKeyword],
    ["init", Token.InitKeyword],
    ["true", Token.TrueKeyword],
    ["false", Token.FalseKeyword],
    ["return", Token.ReturnKeyword],
    ["void", Token.VoidKeyword],
    ["never", Token.NeverKeyword],
    ["unknown", Token.UnknownKeyword],
    ["extern", Token.ExternKeyword],
]);
var TokenFlags;
(function (TokenFlags) {
    TokenFlags[TokenFlags["None"] = 0] = "None";
    TokenFlags[TokenFlags["Escaped"] = 1] = "Escaped";
    TokenFlags[TokenFlags["TripleQuoted"] = 2] = "TripleQuoted";
    TokenFlags[TokenFlags["Unterminated"] = 4] = "Unterminated";
    TokenFlags[TokenFlags["NonAscii"] = 8] = "NonAscii";
    TokenFlags[TokenFlags["DocComment"] = 16] = "DocComment";
    TokenFlags[TokenFlags["Backticked"] = 32] = "Backticked";
})(TokenFlags || (TokenFlags = {}));
function isTrivia(token) {
    return token >= Token.__StartTrivia && token < Token.__EndTrivia;
}
function isComment(token) {
    return token === Token.SingleLineComment || token === Token.MultiLineComment;
}
function isKeyword(token) {
    return token >= Token.__StartKeyword && token < Token.__EndKeyword;
}
function isPunctuation(token) {
    return token >= Token.__StartPunctuation && token < Token.__EndPunctuation;
}
function isModifier(token) {
    return token >= Token.__StartModifierKeyword && token < Token.__EndModifierKeyword;
}
function isStatementKeyword(token) {
    return token >= Token.__StartStatementKeyword && token < Token.__EndStatementKeyword;
}
function createScanner(source, diagnosticHandler) {
    const file = typeof source === "string" ? createSourceFile(source, "<anonymous file>") : source;
    const input = file.text;
    let position = 0;
    let endPosition = input.length;
    let token = Token.None;
    let tokenPosition = -1;
    let tokenFlags = TokenFlags.None;
    // Skip BOM
    if (position < endPosition && input.charCodeAt(position) === 65279 /* CharCode.ByteOrderMark */) {
        position++;
    }
    return {
        get position() {
            return position;
        },
        get token() {
            return token;
        },
        get tokenPosition() {
            return tokenPosition;
        },
        get tokenFlags() {
            return tokenFlags;
        },
        file,
        scan,
        scanRange,
        scanDoc,
        reScanStringTemplate,
        findTripleQuotedStringIndent,
        unindentAndUnescapeTripleQuotedString,
        eof,
        getTokenText,
        getTokenValue,
    };
    function eof() {
        return position >= endPosition;
    }
    function getTokenText() {
        return input.substring(tokenPosition, position);
    }
    function getTokenValue() {
        switch (token) {
            case Token.StringLiteral:
            case Token.StringTemplateHead:
            case Token.StringTemplateMiddle:
            case Token.StringTemplateTail:
                return getStringTokenValue(token, tokenFlags);
            case Token.Identifier:
                return getIdentifierTokenValue();
            case Token.DocText:
                return getDocTextValue();
            default:
                return getTokenText();
        }
    }
    function lookAhead(offset) {
        const p = position + offset;
        if (p >= endPosition) {
            return Number.NaN;
        }
        return input.charCodeAt(p);
    }
    function scan() {
        tokenPosition = position;
        tokenFlags = TokenFlags.None;
        if (!eof()) {
            const ch = input.charCodeAt(position);
            switch (ch) {
                case 13 /* CharCode.CarriageReturn */:
                    if (lookAhead(1) === 10 /* CharCode.LineFeed */) {
                        position++;
                    }
                // fallthrough
                case 10 /* CharCode.LineFeed */:
                    return next(Token.NewLine);
                case 32 /* CharCode.Space */:
                case 9 /* CharCode.Tab */:
                case 11 /* CharCode.VerticalTab */:
                case 12 /* CharCode.FormFeed */:
                    return scanWhitespace();
                case 40 /* CharCode.OpenParen */:
                    return next(Token.OpenParen);
                case 41 /* CharCode.CloseParen */:
                    return next(Token.CloseParen);
                case 44 /* CharCode.Comma */:
                    return next(Token.Comma);
                case 58 /* CharCode.Colon */:
                    return lookAhead(1) === 58 /* CharCode.Colon */ ? next(Token.ColonColon, 2) : next(Token.Colon);
                case 59 /* CharCode.Semicolon */:
                    return next(Token.Semicolon);
                case 91 /* CharCode.OpenBracket */:
                    return next(Token.OpenBracket);
                case 93 /* CharCode.CloseBracket */:
                    return next(Token.CloseBracket);
                case 123 /* CharCode.OpenBrace */:
                    return next(Token.OpenBrace);
                case 125 /* CharCode.CloseBrace */:
                    return next(Token.CloseBrace);
                case 64 /* CharCode.At */:
                    return lookAhead(1) === 64 /* CharCode.At */ ? next(Token.AtAt, 2) : next(Token.At);
                case 35 /* CharCode.Hash */:
                    const ahead = lookAhead(1);
                    switch (ahead) {
                        case 123 /* CharCode.OpenBrace */:
                            return next(Token.HashBrace, 2);
                        case 91 /* CharCode.OpenBracket */:
                            return next(Token.HashBracket, 2);
                        default:
                            return next(Token.Hash);
                    }
                case 43 /* CharCode.Plus */:
                    return isDigit(lookAhead(1)) ? scanSignedNumber() : next(Token.Plus);
                case 45 /* CharCode.Minus */:
                    return isDigit(lookAhead(1)) ? scanSignedNumber() : next(Token.Hyphen);
                case 42 /* CharCode.Asterisk */:
                    return next(Token.Star);
                case 63 /* CharCode.Question */:
                    return next(Token.Question);
                case 38 /* CharCode.Ampersand */:
                    return lookAhead(1) === 38 /* CharCode.Ampersand */
                        ? next(Token.AmpsersandAmpersand, 2)
                        : next(Token.Ampersand);
                case 46 /* CharCode.Dot */:
                    return lookAhead(1) === 46 /* CharCode.Dot */ && lookAhead(2) === 46 /* CharCode.Dot */
                        ? next(Token.Ellipsis, 3)
                        : next(Token.Dot);
                case 47 /* CharCode.Slash */:
                    switch (lookAhead(1)) {
                        case 47 /* CharCode.Slash */:
                            return scanSingleLineComment();
                        case 42 /* CharCode.Asterisk */:
                            return scanMultiLineComment();
                    }
                    return next(Token.ForwardSlash);
                case 48 /* CharCode._0 */:
                    switch (lookAhead(1)) {
                        case 120 /* CharCode.x */:
                            return scanHexNumber();
                        case 98 /* CharCode.b */:
                            return scanBinaryNumber();
                    }
                // fallthrough
                case 49 /* CharCode._1 */:
                case 50 /* CharCode._2 */:
                case 51 /* CharCode._3 */:
                case 52 /* CharCode._4 */:
                case 53 /* CharCode._5 */:
                case 54 /* CharCode._6 */:
                case 55 /* CharCode._7 */:
                case 56 /* CharCode._8 */:
                case 57 /* CharCode._9 */:
                    return scanNumber();
                case 60 /* CharCode.LessThan */:
                    if (atConflictMarker())
                        return scanConflictMarker();
                    return lookAhead(1) === 61 /* CharCode.Equals */
                        ? next(Token.LessThanEquals, 2)
                        : next(Token.LessThan);
                case 62 /* CharCode.GreaterThan */:
                    if (atConflictMarker())
                        return scanConflictMarker();
                    return lookAhead(1) === 61 /* CharCode.Equals */
                        ? next(Token.GreaterThanEquals, 2)
                        : next(Token.GreaterThan);
                case 61 /* CharCode.Equals */:
                    if (atConflictMarker())
                        return scanConflictMarker();
                    switch (lookAhead(1)) {
                        case 61 /* CharCode.Equals */:
                            return next(Token.EqualsEquals, 2);
                        case 62 /* CharCode.GreaterThan */:
                            return next(Token.EqualsGreaterThan, 2);
                    }
                    return next(Token.Equals);
                case 124 /* CharCode.Bar */:
                    if (atConflictMarker())
                        return scanConflictMarker();
                    return lookAhead(1) === 124 /* CharCode.Bar */ ? next(Token.BarBar, 2) : next(Token.Bar);
                case 34 /* CharCode.DoubleQuote */:
                    return lookAhead(1) === 34 /* CharCode.DoubleQuote */ && lookAhead(2) === 34 /* CharCode.DoubleQuote */
                        ? scanString(TokenFlags.TripleQuoted)
                        : scanString(TokenFlags.None);
                case 33 /* CharCode.Exclamation */:
                    return lookAhead(1) === 61 /* CharCode.Equals */
                        ? next(Token.ExclamationEquals, 2)
                        : next(Token.Exclamation);
                case 96 /* CharCode.Backtick */:
                    return scanBacktickedIdentifier();
                default:
                    if (isLowercaseAsciiLetter(ch)) {
                        return scanIdentifierOrKeyword();
                    }
                    if (isAsciiIdentifierStart(ch)) {
                        return scanIdentifier();
                    }
                    if (ch <= 127 /* CharCode.MaxAscii */) {
                        return scanInvalidCharacter();
                    }
                    return scanNonAsciiToken();
            }
        }
        return (token = Token.EndOfFile);
    }
    function scanDoc() {
        tokenPosition = position;
        tokenFlags = TokenFlags.None;
        if (!eof()) {
            const ch = input.charCodeAt(position);
            switch (ch) {
                case 13 /* CharCode.CarriageReturn */:
                    if (lookAhead(1) === 10 /* CharCode.LineFeed */) {
                        position++;
                    }
                // fallthrough
                case 10 /* CharCode.LineFeed */:
                    return next(Token.NewLine);
                case 92 /* CharCode.Backslash */:
                    tokenFlags |= TokenFlags.Escaped;
                    return position === endPosition - 1 ? next(Token.DocText) : next(Token.DocText, 2);
                case 32 /* CharCode.Space */:
                case 9 /* CharCode.Tab */:
                case 11 /* CharCode.VerticalTab */:
                case 12 /* CharCode.FormFeed */:
                    return scanWhitespace();
                case 125 /* CharCode.CloseBrace */:
                    return next(Token.CloseBrace);
                case 64 /* CharCode.At */:
                    return next(Token.At);
                case 42 /* CharCode.Asterisk */:
                    return next(Token.Star);
                case 96 /* CharCode.Backtick */:
                    return lookAhead(1) === 96 /* CharCode.Backtick */ && lookAhead(2) === 96 /* CharCode.Backtick */
                        ? next(Token.DocCodeFenceDelimiter, 3)
                        : scanDocCodeSpan();
                case 60 /* CharCode.LessThan */:
                case 62 /* CharCode.GreaterThan */:
                case 61 /* CharCode.Equals */:
                case 124 /* CharCode.Bar */:
                    if (atConflictMarker())
                        return scanConflictMarker();
                    return next(Token.DocText);
                case 45 /* CharCode.Minus */:
                    return next(Token.Hyphen);
            }
            if (isAsciiIdentifierStart(ch)) {
                return scanIdentifier();
            }
            if (ch <= 127 /* CharCode.MaxAscii */) {
                return next(Token.DocText);
            }
            const cp = input.codePointAt(position);
            if (isIdentifierStart(cp)) {
                return scanNonAsciiIdentifier(cp);
            }
            return scanUnknown(Token.DocText);
        }
        return (token = Token.EndOfFile);
    }
    function reScanStringTemplate(lastTokenFlags) {
        position = tokenPosition;
        tokenFlags = TokenFlags.None;
        return scanStringTemplateSpan(lastTokenFlags);
    }
    function scanRange(range, callback) {
        const savedPosition = position;
        const savedEndPosition = endPosition;
        const savedToken = token;
        const savedTokenPosition = tokenPosition;
        const savedTokenFlags = tokenFlags;
        position = range.pos;
        endPosition = range.end;
        token = Token.None;
        tokenPosition = -1;
        tokenFlags = TokenFlags.None;
        const result = callback();
        position = savedPosition;
        endPosition = savedEndPosition;
        token = savedToken;
        tokenPosition = savedTokenPosition;
        tokenFlags = savedTokenFlags;
        return result;
    }
    function next(t, count = 1) {
        position += count;
        return (token = t);
    }
    function unterminated(t) {
        tokenFlags |= TokenFlags.Unterminated;
        error({ code: "unterminated", format: { token: TokenDisplay[t] } });
        return (token = t);
    }
    function scanNonAsciiToken() {
        tokenFlags |= TokenFlags.NonAscii;
        const ch = input.charCodeAt(position);
        if (isNonAsciiWhiteSpaceSingleLine(ch)) {
            return scanWhitespace();
        }
        const cp = input.codePointAt(position);
        if (isNonAsciiIdentifierCharacter(cp)) {
            return scanNonAsciiIdentifier(cp);
        }
        return scanInvalidCharacter();
    }
    function scanInvalidCharacter() {
        token = scanUnknown(Token.Invalid);
        error({ code: "invalid-character" });
        return token;
    }
    function scanUnknown(t) {
        const codePoint = input.codePointAt(position);
        return (token = next(t, utf16CodeUnits(codePoint)));
    }
    function error(report, pos, end) {
        const diagnostic = createDiagnostic({
            ...report,
            target: { file, pos: pos ?? tokenPosition, end: end ?? position },
        });
        diagnosticHandler(diagnostic);
    }
    function scanWhitespace() {
        do {
            position++;
        } while (!eof() && isWhiteSpaceSingleLine(input.charCodeAt(position)));
        return (token = Token.Whitespace);
    }
    function scanSignedNumber() {
        position++; // consume '+/-'
        return scanNumber();
    }
    function scanNumber() {
        scanKnownDigits();
        if (!eof() && input.charCodeAt(position) === 46 /* CharCode.Dot */) {
            position++;
            scanRequiredDigits();
        }
        if (!eof() && input.charCodeAt(position) === 101 /* CharCode.e */) {
            position++;
            const ch = input.charCodeAt(position);
            if (ch === 43 /* CharCode.Plus */ || ch === 45 /* CharCode.Minus */) {
                position++;
            }
            scanRequiredDigits();
        }
        return (token = Token.NumericLiteral);
    }
    function scanKnownDigits() {
        do {
            position++;
        } while (!eof() && isDigit(input.charCodeAt(position)));
    }
    function scanRequiredDigits() {
        if (eof() || !isDigit(input.charCodeAt(position))) {
            error({ code: "digit-expected" });
            return;
        }
        scanKnownDigits();
    }
    function scanHexNumber() {
        position += 2; // consume '0x'
        if (eof() || !isHexDigit(input.charCodeAt(position))) {
            error({ code: "hex-digit-expected" });
            return (token = Token.NumericLiteral);
        }
        do {
            position++;
        } while (!eof() && isHexDigit(input.charCodeAt(position)));
        return (token = Token.NumericLiteral);
    }
    function scanBinaryNumber() {
        position += 2; // consume '0b'
        if (eof() || !isBinaryDigit(input.charCodeAt(position))) {
            error({ code: "binary-digit-expected" });
            return (token = Token.NumericLiteral);
        }
        do {
            position++;
        } while (!eof() && isBinaryDigit(input.charCodeAt(position)));
        return (token = Token.NumericLiteral);
    }
    function scanSingleLineComment() {
        position = skipSingleLineComment(input, position, endPosition);
        return (token = Token.SingleLineComment);
    }
    function scanMultiLineComment() {
        token = Token.MultiLineComment;
        if (lookAhead(2) === 42 /* CharCode.Asterisk */) {
            tokenFlags |= TokenFlags.DocComment;
        }
        const [newPosition, terminated] = skipMultiLineComment(input, position);
        position = newPosition;
        return terminated ? token : unterminated(token);
    }
    function scanDocCodeSpan() {
        position++; // consume '`'
        loop: for (; !eof(); position++) {
            const ch = input.charCodeAt(position);
            switch (ch) {
                case 96 /* CharCode.Backtick */:
                    position++;
                    return (token = Token.DocCodeSpan);
                case 13 /* CharCode.CarriageReturn */:
                case 10 /* CharCode.LineFeed */:
                    break loop;
            }
        }
        return unterminated(Token.DocCodeSpan);
    }
    function scanString(tokenFlags) {
        if (tokenFlags & TokenFlags.TripleQuoted) {
            position += 3; // consume '"""'
        }
        else {
            position++; // consume '"'
        }
        return scanStringLiteralLike(tokenFlags, Token.StringTemplateHead, Token.StringLiteral);
    }
    function scanStringTemplateSpan(tokenFlags) {
        position++; // consume '{'
        return scanStringLiteralLike(tokenFlags, Token.StringTemplateMiddle, Token.StringTemplateTail);
    }
    function scanStringLiteralLike(requestedTokenFlags, template, tail) {
        const multiLine = requestedTokenFlags & TokenFlags.TripleQuoted;
        tokenFlags = requestedTokenFlags;
        loop: for (; !eof(); position++) {
            const ch = input.charCodeAt(position);
            switch (ch) {
                case 92 /* CharCode.Backslash */:
                    tokenFlags |= TokenFlags.Escaped;
                    position++;
                    if (eof()) {
                        break loop;
                    }
                    continue;
                case 34 /* CharCode.DoubleQuote */:
                    if (multiLine) {
                        if (lookAhead(1) === 34 /* CharCode.DoubleQuote */ && lookAhead(2) === 34 /* CharCode.DoubleQuote */) {
                            position += 3;
                            token = tail;
                            return tail;
                        }
                        else {
                            continue;
                        }
                    }
                    else {
                        position++;
                        token = tail;
                        return tail;
                    }
                case 36 /* CharCode.$ */:
                    if (lookAhead(1) === 123 /* CharCode.OpenBrace */) {
                        position += 2;
                        token = template;
                        return template;
                    }
                    continue;
                case 13 /* CharCode.CarriageReturn */:
                case 10 /* CharCode.LineFeed */:
                    if (multiLine) {
                        continue;
                    }
                    else {
                        break loop;
                    }
            }
        }
        return unterminated(tail);
    }
    function getStringLiteralOffsetStart(token, tokenFlags) {
        switch (token) {
            case Token.StringLiteral:
            case Token.StringTemplateHead:
                return tokenFlags & TokenFlags.TripleQuoted ? 3 : 1; // """ or "
            default:
                return 1; // {
        }
    }
    function getStringLiteralOffsetEnd(token, tokenFlags) {
        switch (token) {
            case Token.StringLiteral:
            case Token.StringTemplateTail:
                return tokenFlags & TokenFlags.TripleQuoted ? 3 : 1; // """ or "
            default:
                return 2; // ${
        }
    }
    function getStringTokenValue(token, tokenFlags) {
        if (tokenFlags & TokenFlags.TripleQuoted) {
            const start = tokenPosition;
            const end = position;
            const [indentationStart, indentationEnd] = findTripleQuotedStringIndent(start, end);
            return unindentAndUnescapeTripleQuotedString(start, end, indentationStart, indentationEnd, token, tokenFlags);
        }
        const startOffset = getStringLiteralOffsetStart(token, tokenFlags);
        const endOffset = getStringLiteralOffsetEnd(token, tokenFlags);
        const start = tokenPosition + startOffset;
        const end = tokenFlags & TokenFlags.Unterminated ? position : position - endOffset;
        if (tokenFlags & TokenFlags.Escaped) {
            return unescapeString(start, end);
        }
        return input.substring(start, end);
    }
    function getIdentifierTokenValue() {
        const start = tokenFlags & TokenFlags.Backticked ? tokenPosition + 1 : tokenPosition;
        const end = tokenFlags & TokenFlags.Backticked && !(tokenFlags & TokenFlags.Unterminated)
            ? position - 1
            : position;
        const text = tokenFlags & TokenFlags.Escaped ? unescapeString(start, end) : input.substring(start, end);
        if (tokenFlags & TokenFlags.NonAscii) {
            return text.normalize("NFC");
        }
        return text;
    }
    function getDocTextValue() {
        if (tokenFlags & TokenFlags.Escaped) {
            let start = tokenPosition;
            const end = position;
            let result = "";
            let pos = start;
            while (pos < end) {
                const ch = input.charCodeAt(pos);
                if (ch !== 92 /* CharCode.Backslash */) {
                    pos++;
                    continue;
                }
                if (pos === end - 1) {
                    break;
                }
                result += input.substring(start, pos);
                switch (input.charCodeAt(pos + 1)) {
                    case 64 /* CharCode.At */:
                        result += "@";
                        break;
                    default:
                        result += input.substring(pos, pos + 2);
                }
                pos += 2;
                start = pos;
            }
            result += input.substring(start, end);
            return result;
        }
        else {
            return input.substring(tokenPosition, position);
        }
    }
    function findTripleQuotedStringIndent(start, end) {
        end = end - 3; // Remove the """
        // remove whitespace before closing delimiter and record it as required
        // indentation for all lines
        const indentationEnd = end;
        while (end > start && isWhiteSpaceSingleLine(input.charCodeAt(end - 1))) {
            end--;
        }
        const indentationStart = end;
        // remove required final line break
        if (isLineBreak(input.charCodeAt(end - 1))) {
            if (isCrlf(end - 2, 0, end)) {
                end--;
            }
            end--;
        }
        else {
            error({ code: "no-new-line-end-triple-quote" });
        }
        return [indentationStart, indentationEnd];
    }
    function unindentAndUnescapeTripleQuotedString(start, end, indentationStart, indentationEnd, token, tokenFlags) {
        const startOffset = getStringLiteralOffsetStart(token, tokenFlags);
        const endOffset = getStringLiteralOffsetEnd(token, tokenFlags);
        start = start + startOffset;
        end = tokenFlags & TokenFlags.Unterminated ? end : end - endOffset;
        if (token === Token.StringLiteral || token === Token.StringTemplateHead) {
            // ignore leading whitespace before required initial line break
            while (start < end && isWhiteSpaceSingleLine(input.charCodeAt(start))) {
                start++;
            }
            // remove required initial line break
            if (isLineBreak(input.charCodeAt(start))) {
                if (isCrlf(start, start, end)) {
                    start++;
                }
                start++;
            }
            else {
                error({ code: "no-new-line-start-triple-quote" });
            }
        }
        if (token === Token.StringLiteral || token === Token.StringTemplateTail) {
            while (end > start && isWhiteSpaceSingleLine(input.charCodeAt(end - 1))) {
                end--;
            }
            // remove required final line break
            if (isLineBreak(input.charCodeAt(end - 1))) {
                if (isCrlf(end - 2, start, end)) {
                    end--;
                }
                end--;
            }
            else {
                error({ code: "no-new-line-end-triple-quote" });
            }
        }
        let skipUnindentOnce = false;
        // We are resuming from the middle of a line so we want to keep text as it is from there.
        if (token === Token.StringTemplateMiddle || token === Token.StringTemplateTail) {
            skipUnindentOnce = true;
        }
        // remove required matching indentation from each line and unescape in the
        // process of doing so
        let result = "";
        let pos = start;
        while (pos < end) {
            if (skipUnindentOnce) {
                skipUnindentOnce = false;
            }
            else {
                // skip indentation at start of line
                start = skipMatchingIndentation(pos, end, indentationStart, indentationEnd);
            }
            let ch;
            while (pos < end && !isLineBreak((ch = input.charCodeAt(pos)))) {
                if (ch !== 92 /* CharCode.Backslash */) {
                    pos++;
                    continue;
                }
                result += input.substring(start, pos);
                if (pos === end - 1) {
                    error({ code: "invalid-escape-sequence" }, pos, pos);
                    pos++;
                }
                else {
                    result += unescapeOne(pos);
                    pos += 2;
                }
                start = pos;
            }
            if (pos < end) {
                if (isCrlf(pos, start, end)) {
                    // CRLF in multi-line string is normalized to LF in string value.
                    // This keeps program behavior unchanged by line-ending conversion.
                    result += input.substring(start, pos);
                    result += "\n";
                    pos += 2;
                }
                else {
                    pos++; // include non-CRLF newline
                    result += input.substring(start, pos);
                }
                start = pos;
            }
        }
        result += input.substring(start, pos);
        return result;
    }
    function isCrlf(pos, start, end) {
        return (pos >= start &&
            pos < end - 1 &&
            input.charCodeAt(pos) === 13 /* CharCode.CarriageReturn */ &&
            input.charCodeAt(pos + 1) === 10 /* CharCode.LineFeed */);
    }
    function skipMatchingIndentation(pos, end, indentationStart, indentationEnd) {
        let indentationPos = indentationStart;
        end = Math.min(end, pos + (indentationEnd - indentationStart));
        while (pos < end) {
            const ch = input.charCodeAt(pos);
            if (isLineBreak(ch)) {
                // allow subset of indentation if line has only whitespace
                break;
            }
            if (ch !== input.charCodeAt(indentationPos)) {
                error({ code: "triple-quote-indent" });
                break;
            }
            indentationPos++;
            pos++;
        }
        return pos;
    }
    function unescapeString(start, end) {
        let result = "";
        let pos = start;
        while (pos < end) {
            const ch = input.charCodeAt(pos);
            if (ch !== 92 /* CharCode.Backslash */) {
                pos++;
                continue;
            }
            if (pos === end - 1) {
                error({ code: "invalid-escape-sequence" }, pos, pos);
                break;
            }
            result += input.substring(start, pos);
            result += unescapeOne(pos);
            pos += 2;
            start = pos;
        }
        result += input.substring(start, pos);
        return result;
    }
    function unescapeOne(pos) {
        const ch = input.charCodeAt(pos + 1);
        switch (ch) {
            case 114 /* CharCode.r */:
                return "\r";
            case 110 /* CharCode.n */:
                return "\n";
            case 116 /* CharCode.t */:
                return "\t";
            case 34 /* CharCode.DoubleQuote */:
                return '"';
            case 92 /* CharCode.Backslash */:
                return "\\";
            case 36 /* CharCode.$ */:
                return "$";
            case 64 /* CharCode.At */:
                return "@";
            case 96 /* CharCode.Backtick */:
                return "`";
            default:
                error({ code: "invalid-escape-sequence" }, pos, pos + 2);
                return String.fromCharCode(ch);
        }
    }
    function scanIdentifierOrKeyword() {
        let count = 0;
        let ch = input.charCodeAt(position);
        while (true) {
            position++;
            count++;
            if (eof()) {
                break;
            }
            ch = input.charCodeAt(position);
            if (count < 10 /* KeywordLimit.MaxLength */ && isLowercaseAsciiLetter(ch)) {
                continue;
            }
            if (isAsciiIdentifierContinue(ch)) {
                return scanIdentifier();
            }
            if (ch > 127 /* CharCode.MaxAscii */) {
                const cp = input.codePointAt(position);
                if (isNonAsciiIdentifierCharacter(cp)) {
                    return scanNonAsciiIdentifier(cp);
                }
            }
            break;
        }
        if (count >= 2 /* KeywordLimit.MinLength */ && count <= 10 /* KeywordLimit.MaxLength */) {
            const keyword = Keywords.get(getTokenText());
            if (keyword) {
                return (token = keyword);
            }
        }
        return (token = Token.Identifier);
    }
    function scanIdentifier() {
        let ch;
        do {
            position++;
            if (eof()) {
                return (token = Token.Identifier);
            }
        } while (isAsciiIdentifierContinue((ch = input.charCodeAt(position))));
        if (ch > 127 /* CharCode.MaxAscii */) {
            const cp = input.codePointAt(position);
            if (isNonAsciiIdentifierCharacter(cp)) {
                return scanNonAsciiIdentifier(cp);
            }
        }
        return (token = Token.Identifier);
    }
    function scanBacktickedIdentifier() {
        position++; // consume '`'
        tokenFlags |= TokenFlags.Backticked;
        loop: for (; !eof(); position++) {
            const ch = input.charCodeAt(position);
            switch (ch) {
                case 92 /* CharCode.Backslash */:
                    position++;
                    tokenFlags |= TokenFlags.Escaped;
                    continue;
                case 96 /* CharCode.Backtick */:
                    position++;
                    return (token = Token.Identifier);
                case 13 /* CharCode.CarriageReturn */:
                case 10 /* CharCode.LineFeed */:
                    break loop;
                default:
                    if (ch > 127 /* CharCode.MaxAscii */) {
                        tokenFlags |= TokenFlags.NonAscii;
                    }
            }
        }
        return unterminated(Token.Identifier);
    }
    function scanNonAsciiIdentifier(startCodePoint) {
        tokenFlags |= TokenFlags.NonAscii;
        let cp = startCodePoint;
        do {
            position += utf16CodeUnits(cp);
        } while (!eof() && isIdentifierContinue((cp = input.codePointAt(position))));
        return (token = Token.Identifier);
    }
    function atConflictMarker() {
        return isConflictMarker(input, position, endPosition);
    }
    function scanConflictMarker() {
        const marker = input.charCodeAt(position);
        position += mergeConflictMarkerLength;
        error({ code: "conflict-marker" });
        if (marker === 60 /* CharCode.LessThan */ || marker === 62 /* CharCode.GreaterThan */) {
            // Consume everything from >>>>>>> or <<<<<<< to the end of the line.
            while (position < endPosition && !isLineBreak(input.charCodeAt(position))) {
                position++;
            }
        }
        else {
            // Consume everything from the start of a ||||||| or =======
            // marker to the start of the next ======= or >>>>>>> marker.
            while (position < endPosition) {
                const ch = input.charCodeAt(position);
                if ((ch === 61 /* CharCode.Equals */ || ch === 62 /* CharCode.GreaterThan */) &&
                    ch !== marker &&
                    isConflictMarker(input, position, endPosition)) {
                    break;
                }
                position++;
            }
        }
        return (token = Token.ConflictMarker);
    }
}
/**
 *
 * @param script
 * @param position
 * @param endPosition exclude
 * @returns return === endPosition (or -1) means not found non-trivia until endPosition + 1
 */
function skipTriviaBackward(script, position, endPosition = -1) {
    endPosition = endPosition < -1 ? -1 : endPosition;
    const input = script.file.text;
    if (position === input.length) {
        // it's possible if the pos is at the end of the file, just treat it as trivia
        position--;
    }
    else if (position > input.length) {
        compilerAssert(false, "position out of range");
    }
    while (position > endPosition) {
        const ch = input.charCodeAt(position);
        if (isWhiteSpace(ch)) {
            position--;
        }
        else {
            const comment = getCommentAtPosition(script, position);
            if (comment) {
                position = comment.pos - 1;
            }
            else {
                break;
            }
        }
    }
    return position;
}
/**
 *
 * @param input
 * @param position
 * @param endPosition exclude
 * @returns return === endPosition (or input.length) means not found non-trivia until endPosition - 1
 */
function skipTrivia(input, position, endPosition = input.length) {
    endPosition = endPosition > input.length ? input.length : endPosition;
    while (position < endPosition) {
        const ch = input.charCodeAt(position);
        if (isWhiteSpace(ch)) {
            position++;
            continue;
        }
        if (ch === 47 /* CharCode.Slash */) {
            switch (input.charCodeAt(position + 1)) {
                case 47 /* CharCode.Slash */:
                    position = skipSingleLineComment(input, position, endPosition);
                    continue;
                case 42 /* CharCode.Asterisk */:
                    position = skipMultiLineComment(input, position, endPosition)[0];
                    continue;
            }
        }
        break;
    }
    return position;
}
function skipWhiteSpace(input, position, endPosition = input.length) {
    while (position < endPosition) {
        const ch = input.charCodeAt(position);
        if (!isWhiteSpace(ch)) {
            break;
        }
        position++;
    }
    return position;
}
function skipSingleLineComment(input, position, endPosition = input.length) {
    position += 2; // consume '//'
    for (; position < endPosition; position++) {
        if (isLineBreak(input.charCodeAt(position))) {
            break;
        }
    }
    return position;
}
function skipMultiLineComment(input, position, endPosition = input.length) {
    position += 2; // consume '/*'
    for (; position < endPosition; position++) {
        if (input.charCodeAt(position) === 42 /* CharCode.Asterisk */ &&
            input.charCodeAt(position + 1) === 47 /* CharCode.Slash */) {
            return [position + 2, true];
        }
    }
    return [position, false];
}
function skipContinuousIdentifier(input, position, isBackward = false) {
    let cur = position;
    const direction = isBackward ? -1 : 1;
    const bar = isBackward ? (p) => p >= 0 : (p) => p < input.length;
    while (bar(cur)) {
        const { char: cp, size } = codePointBefore(input, cur);
        cur += direction * size;
        if (!cp || !isIdentifierContinue(cp)) {
            break;
        }
    }
    return cur;
}
function isConflictMarker(input, position, endPosition = input.length) {
    // Conflict markers must be at the start of a line.
    const ch = input.charCodeAt(position);
    if (position === 0 || isLineBreak(input.charCodeAt(position - 1))) {
        if (position + mergeConflictMarkerLength < endPosition) {
            for (let i = 0; i < mergeConflictMarkerLength; i++) {
                if (input.charCodeAt(position + i) !== ch) {
                    return false;
                }
            }
            return (ch === 61 /* CharCode.Equals */ ||
                input.charCodeAt(position + mergeConflictMarkerLength) === 32 /* CharCode.Space */);
        }
    }
    return false;
}
function getTokenDisplayTable(entries) {
    const table = new Array(entries.length);
    for (const [token, display] of entries) {
        compilerAssert(token >= 0 && token < Token.__Count, `Invalid entry in token display table, ${token}, ${Token[token]}, ${display}`);
        compilerAssert(!table[token], `Duplicate entry in token display table for: ${token}, ${Token[token]}, ${display}`);
        table[token] = display;
    }
    for (let token = 0; token < Token.__Count; token++) {
        compilerAssert(table[token], `Missing entry in token display table: ${token}, ${Token[token]}`);
    }
    return table;
}

/**
 * The fixed set of options for each of the kinds of delimited lists in TypeSpec.
 */
// eslint-disable-next-line @typescript-eslint/no-namespace
var ListKind;
(function (ListKind) {
    const PropertiesBase = {
        allowEmpty: true,
        toleratedDelimiterIsValid: true,
        trailingDelimiterIsValid: true,
        allowedStatementKeyword: Token.None,
    };
    ListKind.OperationParameters = {
        ...PropertiesBase,
        open: Token.OpenParen,
        close: Token.CloseParen,
        delimiter: Token.Comma,
        toleratedDelimiter: Token.Semicolon,
    };
    ListKind.DecoratorArguments = {
        ...ListKind.OperationParameters,
        invalidAnnotationTarget: "expression",
    };
    ListKind.FunctionArguments = {
        ...ListKind.OperationParameters,
        invalidAnnotationTarget: "expression",
    };
    ListKind.ModelProperties = {
        ...PropertiesBase,
        open: Token.OpenBrace,
        close: Token.CloseBrace,
        delimiter: Token.Semicolon,
        toleratedDelimiter: Token.Comma,
    };
    ListKind.ObjectLiteralProperties = {
        ...PropertiesBase,
        open: Token.HashBrace,
        close: Token.CloseBrace,
        delimiter: Token.Comma,
        toleratedDelimiter: Token.Comma,
    };
    ListKind.InterfaceMembers = {
        ...PropertiesBase,
        open: Token.OpenBrace,
        close: Token.CloseBrace,
        delimiter: Token.Semicolon,
        toleratedDelimiter: Token.Comma,
        toleratedDelimiterIsValid: false,
        allowedStatementKeyword: Token.OpKeyword,
    };
    ListKind.ScalarMembers = {
        ...PropertiesBase,
        open: Token.OpenBrace,
        close: Token.CloseBrace,
        delimiter: Token.Semicolon,
        toleratedDelimiter: Token.Comma,
        toleratedDelimiterIsValid: false,
        allowedStatementKeyword: Token.InitKeyword,
    };
    ListKind.UnionVariants = {
        ...PropertiesBase,
        open: Token.OpenBrace,
        close: Token.CloseBrace,
        delimiter: Token.Semicolon,
        toleratedDelimiter: Token.Comma,
        toleratedDelimiterIsValid: true,
    };
    ListKind.EnumMembers = {
        ...ListKind.ModelProperties,
    };
    const ExpresionsBase = {
        allowEmpty: true,
        delimiter: Token.Comma,
        toleratedDelimiter: Token.Semicolon,
        toleratedDelimiterIsValid: false,
        trailingDelimiterIsValid: false,
        invalidAnnotationTarget: "expression",
        allowedStatementKeyword: Token.None,
    };
    ListKind.TemplateParameters = {
        ...ExpresionsBase,
        allowEmpty: false,
        open: Token.LessThan,
        close: Token.GreaterThan,
        invalidAnnotationTarget: "template parameter",
    };
    ListKind.TemplateArguments = {
        ...ListKind.TemplateParameters,
    };
    ListKind.CallArguments = {
        ...ExpresionsBase,
        allowEmpty: true,
        open: Token.OpenParen,
        close: Token.CloseParen,
    };
    ListKind.Heritage = {
        ...ExpresionsBase,
        allowEmpty: false,
        open: Token.None,
        close: Token.None,
    };
    ListKind.Tuple = {
        ...ExpresionsBase,
        allowEmpty: true,
        open: Token.OpenBracket,
        close: Token.CloseBracket,
    };
    ListKind.ArrayLiteral = {
        ...ExpresionsBase,
        allowEmpty: true,
        open: Token.HashBracket,
        close: Token.CloseBracket,
    };
    ListKind.FunctionParameters = {
        ...ExpresionsBase,
        allowEmpty: true,
        open: Token.OpenParen,
        close: Token.CloseParen,
        invalidAnnotationTarget: "expression",
    };
    ListKind.ProjectionExpression = {
        ...ExpresionsBase,
        allowEmpty: true,
        open: Token.OpenParen,
        close: Token.CloseParen,
    };
    ListKind.ProjectionParameter = {
        ...ExpresionsBase,
        allowEmpty: true,
        open: Token.OpenParen,
        close: Token.CloseParen,
    };
})(ListKind || (ListKind = {}));
function parse$1(code, options = {}) {
    const parser = createParser(code, options);
    return parser.parseTypeSpecScript();
}
function parseStandaloneTypeReference(code) {
    const parser = createParser(code);
    const node = parser.parseStandaloneReferenceExpression();
    return [node, parser.parseDiagnostics];
}
function createParser(code, options = {}) {
    let parseErrorInNextFinishedNode = false;
    let previousTokenEnd = -1;
    let realPositionOfLastError = -1;
    let missingIdentifierCounter = 0;
    let treePrintable = true;
    let newLineIsTrivia = true;
    let currentMode = 0 /* ParseMode.Syntax */;
    const parseDiagnostics = [];
    const scanner = createScanner(code, reportDiagnostic);
    const comments = [];
    let docRanges = [];
    nextToken();
    return {
        parseDiagnostics,
        parseTypeSpecScript,
        parseStandaloneReferenceExpression,
    };
    function parseTypeSpecScript() {
        const statements = parseTypeSpecScriptItemList();
        return {
            kind: SyntaxKind.TypeSpecScript,
            statements,
            file: scanner.file,
            id: {
                kind: SyntaxKind.Identifier,
                sv: scanner.file.path,
                pos: 0,
                end: 0,
                flags: 8 /* NodeFlags.Synthetic */,
            },
            namespaces: [],
            usings: [],
            locals: undefined,
            inScopeNamespaces: [],
            parseDiagnostics,
            comments,
            printable: treePrintable,
            parseOptions: options,
            ...finishNode(0),
        };
    }
    /** Try to parse doc comments, directives and decorators in any order. */
    function parseAnnotations({ skipParsingDocNodes } = {}) {
        const directives = [];
        const decorators = [];
        const docs = [];
        let pos = tokenPos();
        if (!skipParsingDocNodes) {
            const [firstPos, addedDocs] = parseDocList();
            pos = firstPos;
            for (const doc of addedDocs) {
                docs.push(doc);
            }
        }
        while (token() === Token.Hash || token() === Token.At) {
            if (token() === Token.Hash) {
                directives.push(parseDirectiveExpression());
            }
            else if (token() === Token.At) {
                decorators.push(parseDecoratorExpression());
            }
            if (!skipParsingDocNodes) {
                const [_, addedDocs] = parseDocList();
                for (const doc of addedDocs) {
                    docs.push(doc);
                }
            }
        }
        return { pos, docs, directives, decorators };
    }
    function parseTypeSpecScriptItemList() {
        const stmts = [];
        let seenBlocklessNs = false;
        let seenDecl = false;
        let seenUsing = false;
        while (token() !== Token.EndOfFile) {
            const { pos, docs, directives, decorators } = parseAnnotations();
            const tok = token();
            let item;
            switch (tok) {
                case Token.AtAt:
                    reportInvalidDecorators(decorators, "augment decorator statement");
                    item = parseAugmentDecorator();
                    break;
                case Token.ImportKeyword:
                    reportInvalidDecorators(decorators, "import statement");
                    item = parseImportStatement();
                    break;
                case Token.ModelKeyword:
                    item = parseModelStatement(pos, decorators);
                    break;
                case Token.ScalarKeyword:
                    item = parseScalarStatement(pos, decorators);
                    break;
                case Token.NamespaceKeyword:
                    item = parseNamespaceStatement(pos, decorators, docs, directives);
                    break;
                case Token.InterfaceKeyword:
                    item = parseInterfaceStatement(pos, decorators);
                    break;
                case Token.UnionKeyword:
                    item = parseUnionStatement(pos, decorators);
                    break;
                case Token.OpKeyword:
                    item = parseOperationStatement(pos, decorators);
                    break;
                case Token.EnumKeyword:
                    item = parseEnumStatement(pos, decorators);
                    break;
                case Token.AliasKeyword:
                    reportInvalidDecorators(decorators, "alias statement");
                    item = parseAliasStatement(pos);
                    break;
                case Token.ConstKeyword:
                    reportInvalidDecorators(decorators, "const statement");
                    item = parseConstStatement(pos);
                    break;
                case Token.UsingKeyword:
                    reportInvalidDecorators(decorators, "using statement");
                    item = parseUsingStatement(pos);
                    break;
                case Token.ProjectionKeyword:
                    reportInvalidDecorators(decorators, "projection statement");
                    item = parseProjectionStatement(pos);
                    break;
                case Token.Semicolon:
                    reportInvalidDecorators(decorators, "empty statement");
                    item = parseEmptyStatement(pos);
                    break;
                // Start of declaration with modifiers
                case Token.ExternKeyword:
                case Token.FnKeyword:
                case Token.DecKeyword:
                    item = parseDeclaration(pos);
                    break;
                default:
                    item = parseInvalidStatement(pos, decorators);
                    break;
            }
            if (tok !== Token.NamespaceKeyword) {
                mutate(item).directives = directives;
                mutate(item).docs = docs;
            }
            if (isBlocklessNamespace(item)) {
                if (seenBlocklessNs) {
                    error({ code: "multiple-blockless-namespace", target: item });
                }
                if (seenDecl) {
                    error({ code: "blockless-namespace-first", target: item });
                }
                seenBlocklessNs = true;
            }
            else if (item.kind === SyntaxKind.ImportStatement) {
                if (seenDecl || seenBlocklessNs || seenUsing) {
                    error({ code: "import-first", target: item });
                }
            }
            else if (item.kind === SyntaxKind.UsingStatement) {
                seenUsing = true;
            }
            else {
                seenDecl = true;
            }
            stmts.push(item);
        }
        return stmts;
    }
    function parseStatementList() {
        const stmts = [];
        while (token() !== Token.CloseBrace) {
            const { pos, docs, directives, decorators } = parseAnnotations();
            const tok = token();
            let item;
            switch (tok) {
                case Token.AtAt:
                    reportInvalidDecorators(decorators, "augment decorator statement");
                    item = parseAugmentDecorator();
                    break;
                case Token.ImportKeyword:
                    reportInvalidDecorators(decorators, "import statement");
                    item = parseImportStatement();
                    error({ code: "import-first", messageId: "topLevel", target: item });
                    break;
                case Token.ModelKeyword:
                    item = parseModelStatement(pos, decorators);
                    break;
                case Token.ScalarKeyword:
                    item = parseScalarStatement(pos, decorators);
                    break;
                case Token.NamespaceKeyword:
                    const ns = parseNamespaceStatement(pos, decorators, docs, directives);
                    if (!Array.isArray(ns.statements)) {
                        error({ code: "blockless-namespace-first", messageId: "topLevel", target: ns });
                    }
                    item = ns;
                    break;
                case Token.InterfaceKeyword:
                    item = parseInterfaceStatement(pos, decorators);
                    break;
                case Token.UnionKeyword:
                    item = parseUnionStatement(pos, decorators);
                    break;
                case Token.OpKeyword:
                    item = parseOperationStatement(pos, decorators);
                    break;
                case Token.EnumKeyword:
                    item = parseEnumStatement(pos, decorators);
                    break;
                case Token.AliasKeyword:
                    reportInvalidDecorators(decorators, "alias statement");
                    item = parseAliasStatement(pos);
                    break;
                case Token.ConstKeyword:
                    reportInvalidDecorators(decorators, "const statement");
                    item = parseConstStatement(pos);
                    break;
                case Token.UsingKeyword:
                    reportInvalidDecorators(decorators, "using statement");
                    item = parseUsingStatement(pos);
                    break;
                case Token.ExternKeyword:
                case Token.FnKeyword:
                case Token.DecKeyword:
                    item = parseDeclaration(pos);
                    break;
                case Token.ProjectionKeyword:
                    reportInvalidDecorators(decorators, "project statement");
                    item = parseProjectionStatement(pos);
                    break;
                case Token.EndOfFile:
                    parseExpected(Token.CloseBrace);
                    return stmts;
                case Token.Semicolon:
                    reportInvalidDecorators(decorators, "empty statement");
                    item = parseEmptyStatement(pos);
                    break;
                default:
                    item = parseInvalidStatement(pos, decorators);
                    break;
            }
            mutate(item).directives = directives;
            if (tok !== Token.NamespaceKeyword) {
                mutate(item).docs = docs;
            }
            stmts.push(item);
        }
        return stmts;
    }
    function parseDecoratorList() {
        const decorators = [];
        while (token() === Token.At) {
            decorators.push(parseDecoratorExpression());
        }
        return decorators;
    }
    function parseDirectiveList() {
        const directives = [];
        while (token() === Token.Hash) {
            directives.push(parseDirectiveExpression());
        }
        return directives;
    }
    function parseNamespaceStatement(pos, decorators, docs, directives) {
        parseExpected(Token.NamespaceKeyword);
        let currentName = parseIdentifierOrMemberExpression();
        const nsSegments = [];
        while (currentName.kind !== SyntaxKind.Identifier) {
            nsSegments.push(currentName.id);
            currentName = currentName.base;
        }
        nsSegments.push(currentName);
        const nextTok = parseExpectedOneOf(Token.Semicolon, Token.OpenBrace);
        let statements;
        if (nextTok === Token.OpenBrace) {
            statements = parseStatementList();
            parseExpected(Token.CloseBrace);
        }
        let outerNs = {
            kind: SyntaxKind.NamespaceStatement,
            decorators,
            docs: docs,
            id: nsSegments[0],
            locals: undefined,
            statements,
            directives: directives,
            ...finishNode(pos),
        };
        for (let i = 1; i < nsSegments.length; i++) {
            outerNs = {
                kind: SyntaxKind.NamespaceStatement,
                decorators: [],
                directives: [],
                id: nsSegments[i],
                statements: outerNs,
                locals: undefined,
                ...finishNode(pos),
            };
        }
        return outerNs;
    }
    function parseInterfaceStatement(pos, decorators) {
        parseExpected(Token.InterfaceKeyword);
        const id = parseIdentifier();
        const { items: templateParameters, range: templateParametersRange } = parseTemplateParameterList();
        let extendList = createEmptyList();
        if (token() === Token.ExtendsKeyword) {
            nextToken();
            extendList = parseList(ListKind.Heritage, parseReferenceExpression);
        }
        else if (token() === Token.Identifier) {
            error({ code: "token-expected", format: { token: "'extends' or '{'" } });
            nextToken();
        }
        const { items: operations, range: bodyRange } = parseList(ListKind.InterfaceMembers, (pos, decorators) => parseOperationStatement(pos, decorators, true));
        return {
            kind: SyntaxKind.InterfaceStatement,
            id,
            templateParameters,
            templateParametersRange,
            operations,
            bodyRange,
            extends: extendList.items,
            decorators,
            ...finishNode(pos),
        };
    }
    function parseTemplateParameterList() {
        const detail = parseOptionalList(ListKind.TemplateParameters, parseTemplateParameter);
        let setDefault = false;
        for (const item of detail.items) {
            if (!item.default && setDefault) {
                error({ code: "default-required", target: item });
                continue;
            }
            if (item.default) {
                setDefault = true;
            }
        }
        return detail;
    }
    function parseUnionStatement(pos, decorators) {
        parseExpected(Token.UnionKeyword);
        const id = parseIdentifier();
        const { items: templateParameters, range: templateParametersRange } = parseTemplateParameterList();
        const { items: options } = parseList(ListKind.UnionVariants, parseUnionVariant);
        return {
            kind: SyntaxKind.UnionStatement,
            id,
            templateParameters,
            templateParametersRange,
            decorators,
            options,
            ...finishNode(pos),
        };
    }
    function parseUnionVariant(pos, decorators) {
        const idOrExpr = parseExpression();
        if (parseOptional(Token.Colon)) {
            let id = undefined;
            if (idOrExpr.kind !== SyntaxKind.TypeReference &&
                idOrExpr.kind !== SyntaxKind.StringLiteral) {
                error({ code: "token-expected", messageId: "identifier" });
            }
            else if (idOrExpr.kind === SyntaxKind.StringLiteral) {
                // convert string literal node to identifier node (back compat for string literal quoted properties)
                id = {
                    kind: SyntaxKind.Identifier,
                    sv: idOrExpr.value,
                    ...finishNode(idOrExpr.pos),
                };
            }
            else {
                const target = idOrExpr.target;
                if (target.kind === SyntaxKind.Identifier) {
                    id = target;
                }
                else {
                    error({ code: "token-expected", messageId: "identifier" });
                }
            }
            const value = parseExpression();
            return {
                kind: SyntaxKind.UnionVariant,
                id,
                value,
                decorators,
                ...finishNode(pos),
            };
        }
        return {
            kind: SyntaxKind.UnionVariant,
            id: undefined,
            value: idOrExpr,
            decorators,
            ...finishNode(pos),
        };
    }
    function parseUsingStatement(pos) {
        parseExpected(Token.UsingKeyword);
        const name = parseIdentifierOrMemberExpression(undefined, true);
        parseExpected(Token.Semicolon);
        return {
            kind: SyntaxKind.UsingStatement,
            name,
            ...finishNode(pos),
        };
    }
    function parseOperationStatement(pos, decorators, inInterface) {
        if (inInterface) {
            parseOptional(Token.OpKeyword);
        }
        else {
            parseExpected(Token.OpKeyword);
        }
        const id = parseIdentifier();
        const { items: templateParameters, range: templateParametersRange } = parseTemplateParameterList();
        // Make sure the next token is one that is expected
        const token = expectTokenIsOneOf(Token.OpenParen, Token.IsKeyword);
        // Check if we're parsing a declaration or reuse of another operation
        let signature;
        const signaturePos = tokenPos();
        if (token === Token.OpenParen) {
            const parameters = parseOperationParameters();
            parseExpected(Token.Colon);
            const returnType = parseExpression();
            signature = {
                kind: SyntaxKind.OperationSignatureDeclaration,
                parameters,
                returnType,
                ...finishNode(signaturePos),
            };
        }
        else {
            parseExpected(Token.IsKeyword);
            const opReference = parseReferenceExpression();
            signature = {
                kind: SyntaxKind.OperationSignatureReference,
                baseOperation: opReference,
                ...finishNode(signaturePos),
            };
        }
        // The interface parser handles semicolon parsing between statements
        if (!inInterface) {
            parseExpected(Token.Semicolon);
        }
        return {
            kind: SyntaxKind.OperationStatement,
            id,
            templateParameters,
            templateParametersRange,
            signature,
            decorators,
            ...finishNode(pos),
        };
    }
    function parseOperationParameters() {
        const pos = tokenPos();
        const { items: properties, range: bodyRange } = parseList(ListKind.OperationParameters, parseModelPropertyOrSpread);
        const parameters = {
            kind: SyntaxKind.ModelExpression,
            properties,
            bodyRange,
            ...finishNode(pos),
        };
        return parameters;
    }
    function parseModelStatement(pos, decorators) {
        parseExpected(Token.ModelKeyword);
        const id = parseIdentifier();
        const { items: templateParameters, range: templateParametersRange } = parseTemplateParameterList();
        expectTokenIsOneOf(Token.OpenBrace, Token.Equals, Token.ExtendsKeyword, Token.IsKeyword);
        const optionalExtends = parseOptionalModelExtends();
        const optionalIs = optionalExtends ? undefined : parseOptionalModelIs();
        let propDetail = createEmptyList();
        if (optionalIs) {
            const tok = expectTokenIsOneOf(Token.Semicolon, Token.OpenBrace);
            if (tok === Token.Semicolon) {
                nextToken();
            }
            else {
                propDetail = parseList(ListKind.ModelProperties, parseModelPropertyOrSpread);
            }
        }
        else {
            propDetail = parseList(ListKind.ModelProperties, parseModelPropertyOrSpread);
        }
        return {
            kind: SyntaxKind.ModelStatement,
            id,
            extends: optionalExtends,
            is: optionalIs,
            templateParameters,
            templateParametersRange,
            decorators,
            properties: propDetail.items,
            bodyRange: propDetail.range,
            ...finishNode(pos),
        };
    }
    function parseOptionalModelExtends() {
        if (parseOptional(Token.ExtendsKeyword)) {
            return parseExpression();
        }
        return undefined;
    }
    function parseOptionalModelIs() {
        if (parseOptional(Token.IsKeyword)) {
            return parseExpression();
        }
        return;
    }
    function parseTemplateParameter() {
        const pos = tokenPos();
        const id = parseIdentifier();
        let constraint;
        if (parseOptional(Token.ExtendsKeyword)) {
            constraint = parseMixedParameterConstraint();
        }
        let def;
        if (parseOptional(Token.Equals)) {
            def = parseExpression();
        }
        return {
            kind: SyntaxKind.TemplateParameterDeclaration,
            id,
            constraint,
            default: def,
            ...finishNode(pos),
        };
    }
    function parseValueOfExpressionOrIntersectionOrHigher() {
        if (token() === Token.ValueOfKeyword) {
            return parseValueOfExpression();
        }
        else if (parseOptional(Token.OpenParen)) {
            const expr = parseMixedParameterConstraint();
            parseExpected(Token.CloseParen);
            return expr;
        }
        return parseIntersectionExpressionOrHigher();
    }
    function parseMixedParameterConstraint() {
        const pos = tokenPos();
        parseOptional(Token.Bar);
        const node = parseValueOfExpressionOrIntersectionOrHigher();
        if (token() !== Token.Bar) {
            return node;
        }
        const options = [node];
        while (parseOptional(Token.Bar)) {
            const expr = parseValueOfExpressionOrIntersectionOrHigher();
            options.push(expr);
        }
        return {
            kind: SyntaxKind.UnionExpression,
            options,
            ...finishNode(pos),
        };
    }
    function parseModelPropertyOrSpread(pos, decorators) {
        return token() === Token.Ellipsis
            ? parseModelSpreadProperty(pos, decorators)
            : parseModelProperty(pos, decorators);
    }
    function parseModelSpreadProperty(pos, decorators) {
        parseExpected(Token.Ellipsis);
        reportInvalidDecorators(decorators, "spread property");
        // This could be broadened to allow any type expression
        const target = parseReferenceExpression();
        return {
            kind: SyntaxKind.ModelSpreadProperty,
            target,
            ...finishNode(pos),
        };
    }
    function parseModelProperty(pos, decorators) {
        const id = parseIdentifier({
            message: "property",
            allowStringLiteral: true,
        });
        const optional = parseOptional(Token.Question);
        parseExpected(Token.Colon);
        const value = parseExpression();
        const hasDefault = parseOptional(Token.Equals);
        const defaultValue = hasDefault ? parseExpression() : undefined;
        return {
            kind: SyntaxKind.ModelProperty,
            id,
            decorators,
            value,
            optional,
            default: defaultValue,
            ...finishNode(pos),
        };
    }
    function parseObjectLiteralPropertyOrSpread(pos, decorators) {
        reportInvalidDecorators(decorators, "object literal property");
        return token() === Token.Ellipsis
            ? parseObjectLiteralSpreadProperty(pos)
            : parseObjectLiteralProperty(pos);
    }
    function parseObjectLiteralSpreadProperty(pos) {
        parseExpected(Token.Ellipsis);
        // This could be broadened to allow any type expression
        const target = parseReferenceExpression();
        return {
            kind: SyntaxKind.ObjectLiteralSpreadProperty,
            target,
            ...finishNode(pos),
        };
    }
    function parseObjectLiteralProperty(pos) {
        const id = parseIdentifier({
            message: "property",
        });
        parseExpected(Token.Colon);
        const value = parseExpression();
        return {
            kind: SyntaxKind.ObjectLiteralProperty,
            id,
            value,
            ...finishNode(pos),
        };
    }
    function parseScalarStatement(pos, decorators) {
        parseExpected(Token.ScalarKeyword);
        const id = parseIdentifier();
        const { items: templateParameters, range: templateParametersRange } = parseTemplateParameterList();
        const optionalExtends = parseOptionalScalarExtends();
        const { items: members, range: bodyRange } = parseScalarMembers();
        return {
            kind: SyntaxKind.ScalarStatement,
            id,
            templateParameters,
            templateParametersRange,
            extends: optionalExtends,
            members,
            bodyRange,
            decorators,
            ...finishNode(pos),
        };
    }
    function parseOptionalScalarExtends() {
        if (parseOptional(Token.ExtendsKeyword)) {
            return parseReferenceExpression();
        }
        return undefined;
    }
    function parseScalarMembers() {
        if (token() === Token.Semicolon) {
            nextToken();
            return createEmptyList();
        }
        else {
            return parseList(ListKind.ScalarMembers, parseScalarMember);
        }
    }
    function parseScalarMember(pos, decorators) {
        reportInvalidDecorators(decorators, "scalar member");
        parseExpected(Token.InitKeyword);
        const id = parseIdentifier();
        const { items: parameters } = parseFunctionParameters();
        return {
            kind: SyntaxKind.ScalarConstructor,
            id,
            parameters,
            ...finishNode(pos),
        };
    }
    function parseEnumStatement(pos, decorators) {
        parseExpected(Token.EnumKeyword);
        const id = parseIdentifier();
        const { items: members } = parseList(ListKind.EnumMembers, parseEnumMemberOrSpread);
        return {
            kind: SyntaxKind.EnumStatement,
            id,
            decorators,
            members,
            ...finishNode(pos),
        };
    }
    function parseEnumMemberOrSpread(pos, decorators) {
        return token() === Token.Ellipsis
            ? parseEnumSpreadMember(pos, decorators)
            : parseEnumMember(pos, decorators);
    }
    function parseEnumSpreadMember(pos, decorators) {
        parseExpected(Token.Ellipsis);
        reportInvalidDecorators(decorators, "spread enum");
        const target = parseReferenceExpression();
        return {
            kind: SyntaxKind.EnumSpreadMember,
            target,
            ...finishNode(pos),
        };
    }
    function parseEnumMember(pos, decorators) {
        const id = parseIdentifier({
            message: "enumMember",
            allowStringLiteral: true,
        });
        let value;
        if (parseOptional(Token.Colon)) {
            const expr = parseExpression();
            if (expr.kind === SyntaxKind.StringLiteral || expr.kind === SyntaxKind.NumericLiteral) {
                value = expr;
            }
            else if (expr.kind === SyntaxKind.TypeReference &&
                expr.target.flags & 2 /* NodeFlags.ThisNodeHasError */) {
                parseErrorInNextFinishedNode = true;
            }
            else {
                error({ code: "token-expected", messageId: "numericOrStringLiteral", target: expr });
            }
        }
        return {
            kind: SyntaxKind.EnumMember,
            id,
            value,
            decorators,
            ...finishNode(pos),
        };
    }
    function parseAliasStatement(pos) {
        parseExpected(Token.AliasKeyword);
        const id = parseIdentifier();
        const { items: templateParameters, range: templateParametersRange } = parseTemplateParameterList();
        parseExpected(Token.Equals);
        const value = parseExpression();
        parseExpected(Token.Semicolon);
        return {
            kind: SyntaxKind.AliasStatement,
            id,
            templateParameters,
            templateParametersRange,
            value,
            ...finishNode(pos),
        };
    }
    function parseConstStatement(pos) {
        parseExpected(Token.ConstKeyword);
        const id = parseIdentifier();
        const type = parseOptionalTypeAnnotation();
        parseExpected(Token.Equals);
        const value = parseExpression();
        parseExpected(Token.Semicolon);
        return {
            kind: SyntaxKind.ConstStatement,
            id,
            value,
            type,
            ...finishNode(pos),
        };
    }
    function parseOptionalTypeAnnotation() {
        if (parseOptional(Token.Colon)) {
            return parseExpression();
        }
        return undefined;
    }
    function parseExpression() {
        return parseUnionExpressionOrHigher();
    }
    function parseUnionExpressionOrHigher() {
        const pos = tokenPos();
        parseOptional(Token.Bar);
        const node = parseIntersectionExpressionOrHigher();
        if (token() !== Token.Bar) {
            return node;
        }
        const options = [node];
        while (parseOptional(Token.Bar)) {
            const expr = parseIntersectionExpressionOrHigher();
            options.push(expr);
        }
        return {
            kind: SyntaxKind.UnionExpression,
            options,
            ...finishNode(pos),
        };
    }
    function parseIntersectionExpressionOrHigher() {
        const pos = tokenPos();
        parseOptional(Token.Ampersand);
        const node = parseArrayExpressionOrHigher();
        if (token() !== Token.Ampersand) {
            return node;
        }
        const options = [node];
        while (parseOptional(Token.Ampersand)) {
            const expr = parseArrayExpressionOrHigher();
            options.push(expr);
        }
        return {
            kind: SyntaxKind.IntersectionExpression,
            options,
            ...finishNode(pos),
        };
    }
    function parseArrayExpressionOrHigher() {
        const pos = tokenPos();
        let expr = parsePrimaryExpression();
        while (parseOptional(Token.OpenBracket)) {
            parseExpected(Token.CloseBracket);
            expr = {
                kind: SyntaxKind.ArrayExpression,
                elementType: expr,
                ...finishNode(pos),
            };
        }
        return expr;
    }
    function parseStandaloneReferenceExpression() {
        const expr = parseReferenceExpression();
        if (parseDiagnostics.length === 0 && token() !== Token.EndOfFile) {
            error({ code: "token-expected", messageId: "unexpected", format: { token: Token[token()] } });
        }
        return expr;
    }
    function parseValueOfExpression() {
        const pos = tokenPos();
        parseExpected(Token.ValueOfKeyword);
        const target = parseExpression();
        return {
            kind: SyntaxKind.ValueOfExpression,
            target,
            ...finishNode(pos),
        };
    }
    function parseTypeOfExpression() {
        const pos = tokenPos();
        parseExpected(Token.TypeOfKeyword);
        const target = parseTypeOfTarget();
        return {
            kind: SyntaxKind.TypeOfExpression,
            target,
            ...finishNode(pos),
        };
    }
    function parseTypeOfTarget() {
        while (true) {
            switch (token()) {
                case Token.TypeOfKeyword:
                    return parseTypeOfExpression();
                case Token.Identifier:
                    return parseCallOrReferenceExpression();
                case Token.StringLiteral:
                    return parseStringLiteral();
                case Token.StringTemplateHead:
                    return parseStringTemplateExpression();
                case Token.TrueKeyword:
                case Token.FalseKeyword:
                    return parseBooleanLiteral();
                case Token.NumericLiteral:
                    return parseNumericLiteral();
                case Token.OpenParen:
                    parseExpected(Token.OpenParen);
                    const target = parseTypeOfTarget();
                    parseExpected(Token.CloseParen);
                    return target;
                default:
                    return parseReferenceExpression("typeofTarget");
            }
        }
    }
    function parseReferenceExpression(message) {
        const pos = tokenPos();
        const target = parseIdentifierOrMemberExpression(message);
        return parseReferenceExpressionInternal(target, pos);
    }
    function parseCallOrReferenceExpression(message) {
        const pos = tokenPos();
        const target = parseIdentifierOrMemberExpression(message);
        if (token() === Token.OpenParen) {
            const { items: args } = parseList(ListKind.FunctionArguments, parseExpression);
            return {
                kind: SyntaxKind.CallExpression,
                target,
                arguments: args,
                ...finishNode(pos),
            };
        }
        return parseReferenceExpressionInternal(target, pos);
    }
    function parseReferenceExpressionInternal(target, pos) {
        const { items: args } = parseOptionalList(ListKind.TemplateArguments, parseTemplateArgument);
        return {
            kind: SyntaxKind.TypeReference,
            target,
            arguments: args,
            ...finishNode(pos),
        };
    }
    function parseTemplateArgument() {
        const pos = tokenPos();
        // Early error recovery for missing identifier followed by eq
        if (token() === Token.Equals) {
            error({ code: "token-expected", messageId: "identifier" });
            nextToken();
            return {
                kind: SyntaxKind.TemplateArgument,
                name: createMissingIdentifier(),
                argument: parseExpression(),
                ...finishNode(pos),
            };
        }
        const expr = parseExpression();
        const eq = parseOptional(Token.Equals);
        if (eq) {
            const isBareIdentifier = exprIsBareIdentifier(expr);
            if (!isBareIdentifier) {
                error({ code: "invalid-template-argument-name", target: expr });
            }
            return {
                kind: SyntaxKind.TemplateArgument,
                name: isBareIdentifier ? expr.target : createMissingIdentifier(),
                argument: parseExpression(),
                ...finishNode(pos),
            };
        }
        else {
            return {
                kind: SyntaxKind.TemplateArgument,
                argument: expr,
                ...finishNode(pos),
            };
        }
    }
    function parseAugmentDecorator() {
        const pos = tokenPos();
        parseExpected(Token.AtAt);
        // Error recovery: false arg here means don't treat a keyword as an
        // identifier. We want to parse `@ model Foo` as invalid decorator
        // `@<missing identifier>` applied to `model Foo`, and not as `@model`
        // applied to invalid statement `Foo`.
        const target = parseIdentifierOrMemberExpression(undefined, false);
        const { items: args } = parseOptionalList(ListKind.DecoratorArguments, parseExpression);
        if (args.length === 0) {
            error({ code: "augment-decorator-target" });
            const emptyList = createEmptyList();
            return {
                kind: SyntaxKind.AugmentDecoratorStatement,
                target,
                targetType: {
                    kind: SyntaxKind.TypeReference,
                    target: createMissingIdentifier(),
                    arguments: emptyList.items,
                    ...finishNode(pos),
                },
                arguments: args,
                ...finishNode(pos),
            };
        }
        let [targetEntity, ...decoratorArgs] = args;
        if (targetEntity.kind !== SyntaxKind.TypeReference) {
            error({ code: "augment-decorator-target", target: targetEntity });
            const emptyList = createEmptyList();
            targetEntity = {
                kind: SyntaxKind.TypeReference,
                target: createMissingIdentifier(),
                arguments: emptyList.items,
                ...finishNode(pos),
            };
        }
        parseExpected(Token.Semicolon);
        return {
            kind: SyntaxKind.AugmentDecoratorStatement,
            target,
            targetType: targetEntity,
            arguments: decoratorArgs,
            ...finishNode(pos),
        };
    }
    function parseImportStatement() {
        const pos = tokenPos();
        parseExpected(Token.ImportKeyword);
        const path = parseStringLiteral();
        parseExpected(Token.Semicolon);
        return {
            kind: SyntaxKind.ImportStatement,
            path,
            ...finishNode(pos),
        };
    }
    function parseDecoratorExpression() {
        const pos = tokenPos();
        parseExpected(Token.At);
        // Error recovery: false arg here means don't treat a keyword as an
        // identifier. We want to parse `@ model Foo` as invalid decorator
        // `@<missing identifier>` applied to `model Foo`, and not as `@model`
        // applied to invalid statement `Foo`.
        const target = parseIdentifierOrMemberExpression(undefined, false);
        const { items: args } = parseOptionalList(ListKind.DecoratorArguments, parseExpression);
        return {
            kind: SyntaxKind.DecoratorExpression,
            arguments: args,
            target,
            ...finishNode(pos),
        };
    }
    function parseDirectiveExpression() {
        const pos = tokenPos();
        parseExpected(Token.Hash);
        const target = parseIdentifier();
        if (target.sv !== "suppress" && target.sv !== "deprecated") {
            error({
                code: "unknown-directive",
                format: { id: target.sv },
                target: { pos, end: pos + target.sv.length },
                printable: true,
            });
        }
        // The newline will mark the end of the directive.
        newLineIsTrivia = false;
        const args = [];
        while (token() !== Token.NewLine && token() !== Token.EndOfFile) {
            const param = parseDirectiveParameter();
            if (param) {
                args.push(param);
            }
        }
        newLineIsTrivia = true;
        nextToken();
        return {
            kind: SyntaxKind.DirectiveExpression,
            arguments: args,
            target,
            ...finishNode(pos),
        };
    }
    function parseDirectiveParameter() {
        switch (token()) {
            case Token.Identifier:
                return parseIdentifier();
            case Token.StringLiteral:
                return parseStringLiteral();
            default:
                error({
                    code: "token-expected",
                    messageId: "unexpected",
                    format: { token: Token[token()] },
                });
                do {
                    nextToken();
                } while (!isStatementKeyword(token()) &&
                    token() !== Token.NewLine &&
                    token() !== Token.At &&
                    token() !== Token.Semicolon &&
                    token() !== Token.EndOfFile);
                return undefined;
        }
    }
    function parseIdentifierOrMemberExpression(message, recoverFromKeyword = true) {
        const pos = tokenPos();
        let base = parseIdentifier({
            message,
            recoverFromKeyword,
        });
        while (token() !== Token.EndOfFile) {
            if (parseOptional(Token.Dot)) {
                base = {
                    kind: SyntaxKind.MemberExpression,
                    base,
                    // Error recovery: false arg here means don't treat a keyword as an
                    // identifier after `.` in member expression. Otherwise we will
                    // parse `@Outer.<missing identifier> model M{}` as having decorator
                    // `@Outer.model` applied to invalid statement `M {}` instead of
                    // having incomplete decorator `@Outer.` applied to `model M {}`.
                    id: parseIdentifier({
                        recoverFromKeyword: false,
                    }),
                    selector: ".",
                    ...finishNode(pos),
                };
            }
            else if (parseOptional(Token.ColonColon)) {
                base = {
                    kind: SyntaxKind.MemberExpression,
                    base,
                    id: parseIdentifier(),
                    selector: "::",
                    ...finishNode(pos),
                };
            }
            else {
                break;
            }
        }
        return base;
    }
    function parsePrimaryExpression() {
        while (true) {
            switch (token()) {
                case Token.TypeOfKeyword:
                    return parseTypeOfExpression();
                case Token.Identifier:
                    return parseCallOrReferenceExpression();
                case Token.StringLiteral:
                    return parseStringLiteral();
                case Token.StringTemplateHead:
                    return parseStringTemplateExpression();
                case Token.TrueKeyword:
                case Token.FalseKeyword:
                    return parseBooleanLiteral();
                case Token.NumericLiteral:
                    return parseNumericLiteral();
                case Token.OpenBrace:
                    return parseModelExpression();
                case Token.OpenBracket:
                    return parseTupleExpression();
                case Token.OpenParen:
                    return parseParenthesizedExpression();
                case Token.At:
                    const decorators = parseDecoratorList();
                    reportInvalidDecorators(decorators, "expression");
                    continue;
                case Token.Hash:
                    const directives = parseDirectiveList();
                    reportInvalidDirective(directives, "expression");
                    continue;
                case Token.HashBrace:
                    return parseObjectLiteral();
                case Token.HashBracket:
                    return parseArrayLiteral();
                case Token.VoidKeyword:
                    return parseVoidKeyword();
                case Token.NeverKeyword:
                    return parseNeverKeyword();
                case Token.UnknownKeyword:
                    return parseUnknownKeyword();
                default:
                    return parseReferenceExpression("expression");
            }
        }
    }
    function parseExternKeyword() {
        const pos = tokenPos();
        parseExpected(Token.ExternKeyword);
        return {
            kind: SyntaxKind.ExternKeyword,
            ...finishNode(pos),
        };
    }
    function parseVoidKeyword() {
        const pos = tokenPos();
        parseExpected(Token.VoidKeyword);
        return {
            kind: SyntaxKind.VoidKeyword,
            ...finishNode(pos),
        };
    }
    function parseNeverKeyword() {
        const pos = tokenPos();
        parseExpected(Token.NeverKeyword);
        return {
            kind: SyntaxKind.NeverKeyword,
            ...finishNode(pos),
        };
    }
    function parseUnknownKeyword() {
        const pos = tokenPos();
        parseExpected(Token.UnknownKeyword);
        return {
            kind: SyntaxKind.UnknownKeyword,
            ...finishNode(pos),
        };
    }
    function parseParenthesizedExpression() {
        const pos = tokenPos();
        parseExpected(Token.OpenParen);
        const expr = parseExpression();
        parseExpected(Token.CloseParen);
        return { ...expr, ...finishNode(pos) };
    }
    function parseTupleExpression() {
        const pos = tokenPos();
        const { items: values } = parseList(ListKind.Tuple, parseExpression);
        return {
            kind: SyntaxKind.TupleExpression,
            values,
            ...finishNode(pos),
        };
    }
    function parseModelExpression() {
        const pos = tokenPos();
        const { items: properties, range: bodyRange } = parseList(ListKind.ModelProperties, parseModelPropertyOrSpread);
        return {
            kind: SyntaxKind.ModelExpression,
            properties,
            bodyRange,
            ...finishNode(pos),
        };
    }
    function parseObjectLiteral() {
        const pos = tokenPos();
        const { items: properties, range: bodyRange } = parseList(ListKind.ObjectLiteralProperties, parseObjectLiteralPropertyOrSpread);
        return {
            kind: SyntaxKind.ObjectLiteral,
            properties,
            bodyRange,
            ...finishNode(pos),
        };
    }
    function parseArrayLiteral() {
        const pos = tokenPos();
        const { items: values } = parseList(ListKind.ArrayLiteral, parseExpression);
        return {
            kind: SyntaxKind.ArrayLiteral,
            values,
            ...finishNode(pos),
        };
    }
    function parseStringLiteral() {
        const pos = tokenPos();
        const value = tokenValue();
        parseExpected(Token.StringLiteral);
        return {
            kind: SyntaxKind.StringLiteral,
            value,
            ...finishNode(pos),
        };
    }
    function parseStringTemplateExpression() {
        const pos = tokenPos();
        const head = parseStringTemplateHead();
        const spans = parseStringTemplateSpans(head.tokenFlags);
        const last = spans[spans.length - 1];
        if (head.tokenFlags & TokenFlags.TripleQuoted) {
            const [indentationsStart, indentationEnd] = scanner.findTripleQuotedStringIndent(last.literal.pos, last.literal.end);
            mutate(head).value = scanner.unindentAndUnescapeTripleQuotedString(head.pos, head.end, indentationsStart, indentationEnd, Token.StringTemplateHead, head.tokenFlags);
            for (const span of spans) {
                mutate(span.literal).value = scanner.unindentAndUnescapeTripleQuotedString(span.literal.pos, span.literal.end, indentationsStart, indentationEnd, span === last ? Token.StringTemplateTail : Token.StringTemplateMiddle, head.tokenFlags);
            }
        }
        return {
            kind: SyntaxKind.StringTemplateExpression,
            head,
            spans,
            ...finishNode(pos),
        };
    }
    function parseStringTemplateHead() {
        const pos = tokenPos();
        const flags = tokenFlags();
        const text = flags & TokenFlags.TripleQuoted ? "" : tokenValue();
        parseExpected(Token.StringTemplateHead);
        return {
            kind: SyntaxKind.StringTemplateHead,
            value: text,
            tokenFlags: flags,
            ...finishNode(pos),
        };
    }
    function parseStringTemplateSpans(tokenFlags) {
        const list = [];
        let node;
        do {
            node = parseTemplateTypeSpan(tokenFlags);
            list.push(node);
        } while (node.literal.kind === SyntaxKind.StringTemplateMiddle);
        return list;
    }
    function parseTemplateTypeSpan(tokenFlags) {
        const pos = tokenPos();
        const expression = parseExpression();
        const literal = parseLiteralOfTemplateSpan(tokenFlags);
        return {
            kind: SyntaxKind.StringTemplateSpan,
            literal,
            expression,
            ...finishNode(pos),
        };
    }
    function parseLiteralOfTemplateSpan(headTokenFlags) {
        const pos = tokenPos();
        const flags = tokenFlags();
        const text = flags & TokenFlags.TripleQuoted ? "" : tokenValue();
        if (token() === Token.CloseBrace) {
            nextStringTemplateToken(headTokenFlags);
            return parseTemplateMiddleOrTemplateTail();
        }
        else {
            parseExpected(Token.StringTemplateTail);
            return {
                kind: SyntaxKind.StringTemplateTail,
                value: text,
                tokenFlags: flags,
                ...finishNode(pos),
            };
        }
    }
    function parseTemplateMiddleOrTemplateTail() {
        const pos = tokenPos();
        const flags = tokenFlags();
        const text = flags & TokenFlags.TripleQuoted ? "" : tokenValue();
        const kind = token() === Token.StringTemplateMiddle
            ? SyntaxKind.StringTemplateMiddle
            : SyntaxKind.StringTemplateTail;
        nextToken();
        return {
            kind,
            value: text,
            tokenFlags: flags,
            ...finishNode(pos),
        };
    }
    function parseNumericLiteral() {
        const pos = tokenPos();
        const valueAsString = tokenValue();
        const value = Number(valueAsString);
        parseExpected(Token.NumericLiteral);
        return {
            kind: SyntaxKind.NumericLiteral,
            value,
            valueAsString,
            ...finishNode(pos),
        };
    }
    function parseBooleanLiteral() {
        const pos = tokenPos();
        const token = parseExpectedOneOf(Token.TrueKeyword, Token.FalseKeyword);
        const value = token === Token.TrueKeyword;
        return {
            kind: SyntaxKind.BooleanLiteral,
            value,
            ...finishNode(pos),
        };
    }
    function parseIdentifier(options) {
        if (options?.recoverFromKeyword !== false && isKeyword(token())) {
            error({ code: "reserved-identifier" });
        }
        else if (token() !== Token.Identifier &&
            (!options?.allowStringLiteral || token() !== Token.StringLiteral)) {
            // Error recovery: when we fail to parse an identifier or expression,
            // we insert a synthesized identifier with a unique name.
            error({ code: "token-expected", messageId: options?.message ?? "identifier" });
            return createMissingIdentifier();
        }
        const pos = tokenPos();
        const sv = tokenValue();
        nextToken();
        return {
            kind: SyntaxKind.Identifier,
            sv,
            ...finishNode(pos),
        };
    }
    function parseDeclaration(pos) {
        const modifiers = parseModifiers();
        switch (token()) {
            case Token.DecKeyword:
                return parseDecoratorDeclarationStatement(pos, modifiers);
            case Token.FnKeyword:
                return parseFunctionDeclarationStatement(pos, modifiers);
        }
        return parseInvalidStatement(pos, []);
    }
    function parseModifiers() {
        const modifiers = [];
        let modifier;
        while ((modifier = parseModifier())) {
            modifiers.push(modifier);
        }
        return modifiers;
    }
    function parseModifier() {
        switch (token()) {
            case Token.ExternKeyword:
                return parseExternKeyword();
            default:
                return undefined;
        }
    }
    function parseDecoratorDeclarationStatement(pos, modifiers) {
        const modifierFlags = modifiersToFlags(modifiers);
        parseExpected(Token.DecKeyword);
        const id = parseIdentifier();
        const allParamListDetail = parseFunctionParameters();
        let [target, ...parameters] = allParamListDetail.items;
        if (target === undefined) {
            error({ code: "decorator-decl-target", target: { pos, end: previousTokenEnd } });
            target = {
                kind: SyntaxKind.FunctionParameter,
                id: createMissingIdentifier(),
                type: createMissingTypeReference(),
                optional: false,
                rest: false,
                ...finishNode(pos),
            };
        }
        if (target.optional) {
            error({ code: "decorator-decl-target", messageId: "required" });
        }
        parseExpected(Token.Semicolon);
        return {
            kind: SyntaxKind.DecoratorDeclarationStatement,
            modifiers,
            modifierFlags,
            id,
            target,
            parameters,
            ...finishNode(pos),
        };
    }
    function parseFunctionDeclarationStatement(pos, modifiers) {
        const modifierFlags = modifiersToFlags(modifiers);
        parseExpected(Token.FnKeyword);
        const id = parseIdentifier();
        const { items: parameters } = parseFunctionParameters();
        let returnType;
        if (parseOptional(Token.Colon)) {
            returnType = parseExpression();
        }
        parseExpected(Token.Semicolon);
        return {
            kind: SyntaxKind.FunctionDeclarationStatement,
            modifiers,
            modifierFlags,
            id,
            parameters,
            returnType,
            ...finishNode(pos),
        };
    }
    function parseFunctionParameters() {
        const parameters = parseList(ListKind.FunctionParameters, parseFunctionParameter);
        let foundOptional = false;
        for (const [index, item] of parameters.items.entries()) {
            if (!item.optional && foundOptional) {
                error({ code: "required-parameter-first", target: item });
                continue;
            }
            if (item.optional) {
                foundOptional = true;
            }
            if (item.rest && item.optional) {
                error({ code: "rest-parameter-required", target: item });
            }
            if (item.rest && index !== parameters.items.length - 1) {
                error({ code: "rest-parameter-last", target: item });
            }
        }
        return parameters;
    }
    function parseFunctionParameter() {
        const pos = tokenPos();
        const rest = parseOptional(Token.Ellipsis);
        const id = parseIdentifier({ message: "property" });
        const optional = parseOptional(Token.Question);
        let type;
        if (parseOptional(Token.Colon)) {
            type = parseMixedParameterConstraint();
        }
        return {
            kind: SyntaxKind.FunctionParameter,
            id,
            type,
            optional,
            rest,
            ...finishNode(pos),
        };
    }
    function modifiersToFlags(modifiers) {
        let flags = 0 /* ModifierFlags.None */;
        for (const modifier of modifiers) {
            switch (modifier.kind) {
                case SyntaxKind.ExternKeyword:
                    flags |= 2 /* ModifierFlags.Extern */;
                    break;
            }
        }
        return flags;
    }
    function parseProjectionStatement(pos) {
        parseExpected(Token.ProjectionKeyword);
        const selector = parseProjectionSelector();
        parseExpected(Token.Hash);
        const id = parseIdentifier();
        parseExpected(Token.OpenBrace);
        const projectionMap = new Map();
        const projections = [];
        while (token() === Token.Identifier) {
            const projection = parseProjection();
            if (projection.direction !== "<error>") {
                if (projectionMap.has(projection.direction)) {
                    error({ code: "duplicate-symbol", target: projection, format: { name: "projection" } });
                }
                else {
                    projectionMap.set(projection.direction, projection);
                }
            }
            // NOTE: Don't drop projections with error in direction definition from the AST.
            projections.push(projection);
        }
        parseExpected(Token.CloseBrace);
        return {
            kind: SyntaxKind.ProjectionStatement,
            selector,
            projections,
            preTo: projectionMap.get("pre_to"),
            preFrom: projectionMap.get("pre_from"),
            from: projectionMap.get("from"),
            to: projectionMap.get("to"),
            id,
            ...finishNode(pos),
        };
    }
    function parseProjection() {
        const pos = tokenPos();
        let directionId = parseIdentifier({ message: "projectionDirection" });
        let direction;
        const modifierIds = [];
        let isPre = false;
        if (directionId.sv === "pre") {
            isPre = true;
            modifierIds.push(directionId);
            directionId = parseIdentifier({ message: "projectionDirection" });
        }
        if (directionId.sv !== "to" && directionId.sv !== "from") {
            error({ code: "token-expected", messageId: "projectionDirection" });
            direction = "<error>";
        }
        else if (isPre) {
            direction = directionId.sv === "to" ? "pre_to" : "pre_from";
        }
        else {
            direction = directionId.sv;
        }
        let parameters;
        if (token() === Token.OpenParen) {
            parameters = parseList(ListKind.ProjectionParameter, parseProjectionParameter).items;
        }
        else {
            parameters = [];
        }
        parseExpected(Token.OpenBrace);
        const body = parseProjectionStatementList();
        parseExpected(Token.CloseBrace);
        return {
            kind: SyntaxKind.Projection,
            body,
            direction,
            directionId,
            modifierIds,
            parameters,
            ...finishNode(pos),
        };
    }
    function parseProjectionParameter() {
        const pos = tokenPos();
        const id = parseIdentifier();
        return {
            kind: SyntaxKind.ProjectionParameterDeclaration,
            id,
            ...finishNode(pos),
        };
    }
    function parseProjectionStatementList() {
        const stmts = [];
        while (token() !== Token.CloseBrace) {
            const startPos = tokenPos();
            if (token() === Token.EndOfFile) {
                error({ code: "token-expected", messageId: "default", format: { token: "}" } });
                break;
            }
            const expr = parseProjectionExpressionStatement();
            stmts.push(expr);
            if (tokenPos() === startPos) {
                // we didn't manage to parse anything, so break out
                // and we'll report errors elsewhere.
                break;
            }
        }
        return stmts;
    }
    function parseProjectionExpressionStatement() {
        const pos = tokenPos();
        const expr = parseProjectionExpression();
        parseExpected(Token.Semicolon);
        return {
            kind: SyntaxKind.ProjectionExpressionStatement,
            expr,
            ...finishNode(pos),
        };
    }
    function parseProjectionExpression() {
        return parseProjectionReturnExpressionOrHigher();
    }
    function parseProjectionReturnExpressionOrHigher() {
        if (token() === Token.ReturnKeyword) {
            const pos = tokenPos();
            parseExpected(Token.ReturnKeyword);
            return {
                kind: SyntaxKind.Return,
                value: parseProjectionExpression(),
                ...finishNode(pos),
            };
        }
        return parseProjectionLogicalOrExpressionOrHigher();
    }
    function parseProjectionLogicalOrExpressionOrHigher() {
        let expr = parseProjectionLogicalAndExpressionOrHigher();
        while (token() !== Token.EndOfFile) {
            const pos = expr.pos;
            if (parseOptional(Token.BarBar)) {
                expr = {
                    kind: SyntaxKind.ProjectionLogicalExpression,
                    op: "||",
                    left: expr,
                    right: parseProjectionLogicalAndExpressionOrHigher(),
                    ...finishNode(pos),
                };
            }
            else {
                break;
            }
        }
        return expr;
    }
    function parseProjectionLogicalAndExpressionOrHigher() {
        let expr = parseProjectionEqualityExpressionOrHigher();
        while (token() !== Token.EndOfFile) {
            const pos = expr.pos;
            if (parseOptional(Token.AmpsersandAmpersand)) {
                expr = {
                    kind: SyntaxKind.ProjectionLogicalExpression,
                    op: "&&",
                    left: expr,
                    right: parseProjectionEqualityExpressionOrHigher(),
                    ...finishNode(pos),
                };
            }
            else {
                break;
            }
        }
        return expr;
    }
    function parseProjectionEqualityExpressionOrHigher() {
        let expr = parseProjectionRelationalExpressionOrHigher();
        while (token() !== Token.EndOfFile) {
            const pos = expr.pos;
            const tok = token();
            if (tok === Token.EqualsEquals || tok === Token.ExclamationEquals) {
                const op = tokenValue();
                nextToken();
                expr = {
                    kind: SyntaxKind.ProjectionEqualityExpression,
                    op,
                    left: expr,
                    right: parseProjectionRelationalExpressionOrHigher(),
                    ...finishNode(pos),
                };
            }
            else {
                break;
            }
        }
        return expr;
    }
    function parseProjectionRelationalExpressionOrHigher() {
        let expr = parseProjectionAdditiveExpressionOrHigher();
        while (token() !== Token.EndOfFile) {
            const pos = expr.pos;
            const tok = token();
            if (tok === Token.LessThan ||
                tok === Token.LessThanEquals ||
                tok === Token.GreaterThan ||
                tok === Token.GreaterThanEquals) {
                const op = tokenValue();
                nextToken();
                expr = {
                    kind: SyntaxKind.ProjectionRelationalExpression,
                    op,
                    left: expr,
                    right: parseProjectionAdditiveExpressionOrHigher(),
                    ...finishNode(pos),
                };
            }
            else {
                break;
            }
        }
        return expr;
    }
    function parseProjectionAdditiveExpressionOrHigher() {
        let expr = parseProjectionMultiplicativeExpressionOrHigher();
        while (token() !== Token.EndOfFile) {
            const pos = expr.pos;
            const tok = token();
            if (tok === Token.Plus || tok === Token.Hyphen) {
                const op = tokenValue();
                nextToken();
                expr = {
                    kind: SyntaxKind.ProjectionArithmeticExpression,
                    op,
                    left: expr,
                    right: parseProjectionMultiplicativeExpressionOrHigher(),
                    ...finishNode(pos),
                };
            }
            else {
                break;
            }
        }
        return expr;
    }
    function parseProjectionMultiplicativeExpressionOrHigher() {
        let expr = parseProjectionUnaryExpressionOrHigher();
        while (token() !== Token.EndOfFile) {
            const pos = expr.pos;
            const tok = token();
            if (tok === Token.ForwardSlash || tok === Token.Star) {
                const op = tokenValue();
                nextToken();
                expr = {
                    kind: SyntaxKind.ProjectionArithmeticExpression,
                    op,
                    left: expr,
                    right: parseProjectionUnaryExpressionOrHigher(),
                    ...finishNode(pos),
                };
            }
            else {
                break;
            }
        }
        return expr;
    }
    function parseProjectionUnaryExpressionOrHigher() {
        if (token() === Token.Exclamation) {
            const pos = tokenPos();
            nextToken();
            return {
                kind: SyntaxKind.ProjectionUnaryExpression,
                op: "!",
                target: parseProjectionUnaryExpressionOrHigher(),
                ...finishNode(pos),
            };
        }
        return parseProjectionCallExpressionOrHigher();
    }
    function parseProjectionCallExpressionOrHigher() {
        let expr = parseProjectionDecoratorReferenceExpressionOrHigher();
        while (token() !== Token.EndOfFile) {
            const pos = expr.pos;
            expr = parseProjectionMemberExpressionRest(expr, pos);
            if (token() === Token.OpenParen) {
                expr = {
                    kind: SyntaxKind.ProjectionCallExpression,
                    callKind: "method",
                    target: expr,
                    arguments: parseList(ListKind.CallArguments, parseProjectionExpression).items,
                    ...finishNode(pos),
                };
            }
            else {
                break;
            }
        }
        return expr;
    }
    function parseProjectionDecoratorReferenceExpressionOrHigher() {
        if (token() === Token.At) {
            const pos = tokenPos();
            nextToken();
            return {
                kind: SyntaxKind.ProjectionDecoratorReferenceExpression,
                target: parseIdentifierOrMemberExpression(undefined, true),
                ...finishNode(pos),
            };
        }
        return parseProjectionMemberExpressionOrHigher();
    }
    function parseProjectionMemberExpressionOrHigher() {
        const pos = tokenPos();
        let expr = parseProjectionPrimaryExpression();
        expr = parseProjectionMemberExpressionRest(expr, pos);
        return expr;
    }
    function parseProjectionMemberExpressionRest(expr, pos) {
        while (token() !== Token.EndOfFile) {
            if (parseOptional(Token.Dot)) {
                expr = {
                    kind: SyntaxKind.ProjectionMemberExpression,
                    base: expr,
                    id: parseIdentifier(),
                    selector: ".",
                    ...finishNode(pos),
                };
            }
            else if (parseOptional(Token.ColonColon)) {
                expr = {
                    kind: SyntaxKind.ProjectionMemberExpression,
                    base: expr,
                    id: parseIdentifier(),
                    selector: "::",
                    ...finishNode(pos),
                };
            }
            else {
                break;
            }
        }
        return expr;
    }
    function parseProjectionPrimaryExpression() {
        switch (token()) {
            case Token.IfKeyword:
                return parseProjectionIfExpression();
            case Token.NumericLiteral:
                return parseNumericLiteral();
            case Token.StringLiteral:
                return parseStringLiteral();
            case Token.TrueKeyword:
            case Token.FalseKeyword:
                return parseBooleanLiteral();
            case Token.OpenBracket:
                return parseProjectionTupleExpression();
            case Token.OpenBrace:
                return parseProjectionModelExpression();
            case Token.OpenParen:
                return parseProjectionLambdaOrParenthesizedExpression();
            case Token.VoidKeyword:
                return parseVoidKeyword();
            case Token.NeverKeyword:
                return parseNeverKeyword();
            case Token.UnknownKeyword:
                return parseUnknownKeyword();
            default:
                return parseIdentifier({ message: "expression" });
        }
    }
    function parseProjectionLambdaOrParenthesizedExpression() {
        const pos = tokenPos();
        const exprs = parseList(ListKind.ProjectionExpression, parseProjectionExpression).items;
        if (token() === Token.EqualsGreaterThan) {
            // unpack the exprs (which should be just identifiers) into a param list
            const params = [];
            for (const expr of exprs) {
                if (expr.kind === SyntaxKind.Identifier) {
                    params.push(withSymbol({
                        kind: SyntaxKind.ProjectionLambdaParameterDeclaration,
                        id: expr,
                        pos: expr.pos,
                        end: expr.end,
                        flags: 0 /* NodeFlags.None */,
                    }));
                }
                else {
                    error({ code: "token-expected", messageId: "identifier", target: expr });
                }
            }
            return parseProjectionLambdaExpressionRest(pos, params);
        }
        else {
            if (exprs.length === 0) {
                error({
                    code: "token-expected",
                    messageId: "expression",
                });
            }
            // verify we only have one entry
            for (let i = 1; i < exprs.length; i++) {
                error({
                    code: "token-expected",
                    messageId: "unexpected",
                    format: { token: "expression" },
                    target: exprs[i],
                });
            }
            return exprs[0];
        }
    }
    function parseProjectionLambdaExpressionRest(pos, parameters) {
        parseExpected(Token.EqualsGreaterThan);
        const body = parseProjectionBlockExpression();
        return {
            kind: SyntaxKind.ProjectionLambdaExpression,
            parameters,
            body,
            ...finishNode(pos),
        };
    }
    function parseProjectionModelExpression() {
        const pos = tokenPos();
        const { items: properties } = parseList(ListKind.ModelProperties, parseProjectionModelPropertyOrSpread);
        return {
            kind: SyntaxKind.ProjectionModelExpression,
            properties,
            ...finishNode(pos),
        };
    }
    function parseProjectionModelPropertyOrSpread(pos, decorators) {
        return token() === Token.Ellipsis
            ? parseProjectionModelSpreadProperty(pos, decorators)
            : parseProjectionModelProperty(pos, decorators);
    }
    function parseProjectionModelSpreadProperty(pos, decorators) {
        parseExpected(Token.Ellipsis);
        reportInvalidDecorators(decorators, "spread property");
        const target = parseProjectionExpression();
        return {
            kind: SyntaxKind.ProjectionModelSpreadProperty,
            target,
            ...finishNode(pos),
        };
    }
    function parseProjectionModelProperty(pos, decorators) {
        const id = parseIdentifier({ message: "property", allowStringLiteral: true });
        const optional = parseOptional(Token.Question);
        parseExpected(Token.Colon);
        const value = parseProjectionExpression();
        const hasDefault = parseOptional(Token.Equals);
        const defaultValue = hasDefault ? parseProjectionExpression() : undefined;
        return {
            kind: SyntaxKind.ProjectionModelProperty,
            id,
            decorators,
            value,
            optional,
            default: defaultValue,
            ...finishNode(pos),
        };
    }
    function parseProjectionIfExpression() {
        const pos = tokenPos();
        parseExpected(Token.IfKeyword);
        const test = parseProjectionExpression();
        const consequent = parseProjectionBlockExpression();
        let alternate = undefined;
        if (parseOptional(Token.ElseKeyword)) {
            if (token() === Token.IfKeyword) {
                alternate = parseProjectionIfExpression();
            }
            else {
                alternate = parseProjectionBlockExpression();
            }
        }
        return {
            kind: SyntaxKind.ProjectionIfExpression,
            test,
            consequent,
            alternate,
            ...finishNode(pos),
        };
    }
    function parseProjectionBlockExpression() {
        const pos = tokenPos();
        parseExpected(Token.OpenBrace);
        const statements = parseProjectionStatementList();
        parseExpected(Token.CloseBrace);
        return {
            kind: SyntaxKind.ProjectionBlockExpression,
            statements,
            ...finishNode(pos),
        };
    }
    function parseProjectionTupleExpression() {
        const pos = tokenPos();
        const { items: values } = parseList(ListKind.Tuple, parseProjectionExpression);
        return {
            kind: SyntaxKind.ProjectionTupleExpression,
            values,
            ...finishNode(pos),
        };
    }
    function parseProjectionSelector() {
        const pos = tokenPos();
        const selectorTok = expectTokenIsOneOf(Token.Identifier, Token.ModelKeyword, Token.OpKeyword, Token.InterfaceKeyword, Token.UnionKeyword, Token.EnumKeyword, Token.ScalarKeyword);
        switch (selectorTok) {
            case Token.Identifier:
                const id = parseIdentifierOrMemberExpression(undefined, true);
                if (id.kind === SyntaxKind.Identifier) {
                    switch (id.sv) {
                        case "modelproperty":
                            return {
                                kind: SyntaxKind.ProjectionModelPropertySelector,
                                ...finishNode(pos),
                            };
                        case "unionvariant":
                            return {
                                kind: SyntaxKind.ProjectionUnionVariantSelector,
                                ...finishNode(pos),
                            };
                        case "enummember":
                            return {
                                kind: SyntaxKind.ProjectionEnumMemberSelector,
                                ...finishNode(pos),
                            };
                    }
                }
                return id;
            case Token.ModelKeyword:
                nextToken();
                return {
                    kind: SyntaxKind.ProjectionModelSelector,
                    ...finishNode(pos),
                };
            case Token.OpKeyword:
                nextToken();
                return {
                    kind: SyntaxKind.ProjectionOperationSelector,
                    ...finishNode(pos),
                };
            case Token.InterfaceKeyword:
                nextToken();
                return {
                    kind: SyntaxKind.ProjectionInterfaceSelector,
                    ...finishNode(pos),
                };
            case Token.UnionKeyword:
                nextToken();
                return {
                    kind: SyntaxKind.ProjectionUnionSelector,
                    ...finishNode(pos),
                };
            case Token.EnumKeyword:
                nextToken();
                return {
                    kind: SyntaxKind.ProjectionEnumSelector,
                    ...finishNode(pos),
                };
            case Token.ScalarKeyword:
                nextToken();
                return {
                    kind: SyntaxKind.ProjectionScalarSelector,
                    ...finishNode(pos),
                };
            default:
                // recovery: return a missing identifier to use as the selector
                // we don't need to emit a diagnostic here as the `expectTokenOneOf` above
                // will have done so.
                return createMissingIdentifier();
        }
    }
    function parseRange(mode, range, callback) {
        const savedMode = currentMode;
        const result = scanner.scanRange(range, () => {
            currentMode = mode;
            nextToken();
            return callback();
        });
        currentMode = savedMode;
        return result;
    }
    /** Remove leading slash-star-star and trailing  star-slash (if terminated) from doc comment range. */
    function innerDocRange(range) {
        return {
            pos: range.pos + 3,
            end: tokenFlags() & TokenFlags.Unterminated ? range.end : range.end - 2,
        };
    }
    function parseDocList() {
        if (docRanges.length === 0 || options.docs === false) {
            return [tokenPos(), []];
        }
        const docs = [];
        for (const range of docRanges) {
            const doc = parseRange(1 /* ParseMode.Doc */, innerDocRange(range), () => parseDoc(range));
            docs.push(doc);
            if (range.comment) {
                mutate(range.comment).parsedAsDocs = true;
            }
        }
        return [docRanges[0].pos, docs];
    }
    function parseDoc(range) {
        const content = [];
        const tags = [];
        loop: while (true) {
            switch (token()) {
                case Token.EndOfFile:
                    break loop;
                case Token.At:
                    const tag = parseDocTag();
                    tags.push(tag);
                    break;
                default:
                    content.push(...parseDocContent());
                    break;
            }
        }
        return {
            kind: SyntaxKind.Doc,
            content,
            tags,
            ...finishNode(range.pos),
            end: range.end,
        };
    }
    function parseDocContent() {
        const parts = [];
        const source = scanner.file.text;
        const pos = tokenPos();
        let start = pos;
        let inCodeFence = false;
        loop: while (true) {
            switch (token()) {
                case Token.DocCodeFenceDelimiter:
                    inCodeFence = !inCodeFence;
                    nextToken();
                    break;
                case Token.NewLine:
                    parts.push(source.substring(start, tokenPos()));
                    parts.push("\n"); // normalize line endings
                    nextToken();
                    start = tokenPos();
                    while (parseOptional(Token.Whitespace))
                        ;
                    if (!parseOptional(Token.Star)) {
                        break;
                    }
                    if (!inCodeFence) {
                        parseOptional(Token.Whitespace);
                        start = tokenPos();
                        break;
                    }
                    // If we are in a code fence we want to preserve the leading whitespace
                    // except for the first space after the star which is used as indentation.
                    const whitespaceStart = tokenPos();
                    parseOptional(Token.Whitespace);
                    // This `min` handles the case when there is no whitespace after the
                    // star e.g. a case like this:
                    //
                    // /**
                    //  *```
                    //  *foo-bar
                    //  *```
                    //  */
                    //
                    // Not having space after the star isn't idiomatic, but we support this.
                    // `whitespaceStart + 1` strips the first space before `foo-bar` if there
                    // is a space after the star (the idiomatic case).
                    start = Math.min(whitespaceStart + 1, tokenPos());
                    break;
                case Token.EndOfFile:
                    break loop;
                case Token.At:
                    if (!inCodeFence) {
                        break loop;
                    }
                    nextToken();
                    break;
                case Token.DocText:
                    parts.push(source.substring(start, tokenPos()));
                    parts.push(tokenValue());
                    nextToken();
                    start = tokenPos();
                    break;
                default:
                    nextToken();
                    break;
            }
        }
        parts.push(source.substring(start, tokenPos()));
        const text = trim$1(parts.join(""));
        return [
            {
                kind: SyntaxKind.DocText,
                text,
                ...finishNode(pos),
            },
        ];
    }
    /**
     * Parses a documentation tag.
     *
     * @see <a href="https://typespec.io/docs/language-basics/documentation#doc-comments">TypeSpec documentation docs</a>
     */
    function parseDocTag() {
        const pos = tokenPos();
        parseExpected(Token.At);
        const tagName = parseDocIdentifier("tag");
        switch (tagName.sv) {
            case "param":
                return parseDocParamLikeTag(pos, tagName, SyntaxKind.DocParamTag, "param");
            case "template":
                return parseDocParamLikeTag(pos, tagName, SyntaxKind.DocTemplateTag, "templateParam");
            case "prop":
                return parseDocPropTag(pos, tagName);
            case "return":
            case "returns":
                return parseDocSimpleTag(pos, tagName, SyntaxKind.DocReturnsTag);
            case "errors":
                return parseDocSimpleTag(pos, tagName, SyntaxKind.DocErrorsTag);
            default:
                return parseDocSimpleTag(pos, tagName, SyntaxKind.DocUnknownTag);
        }
    }
    /**
     * Handles param-like documentation comment tags.
     * For example, `@param` and `@template`.
     */
    function parseDocParamLikeTag(pos, tagName, kind, messageId) {
        const { name, content } = parseDocParamLikeTagInternal(messageId);
        return {
            kind,
            tagName,
            paramName: name,
            content,
            ...finishNode(pos),
        };
    }
    function parseDocPropTag(pos, tagName) {
        const { name, content } = parseDocParamLikeTagInternal("prop");
        return {
            kind: SyntaxKind.DocPropTag,
            tagName,
            propName: name,
            content,
            ...finishNode(pos),
        };
    }
    function parseDocParamLikeTagInternal(messageId) {
        const name = parseDocIdentifier(messageId);
        parseOptionalHyphenDocParamLikeTag();
        const content = parseDocContent();
        return { name, content };
    }
    /**
     * Handles the optional hyphen in param-like documentation comment tags.
     *
     * TypeSpec recommends no hyphen, but supports a hyphen to match TSDoc.
     * (Original design discussion recorded in [2390].)
     *
     * [2390]: https://github.com/microsoft/typespec/issues/2390
     */
    function parseOptionalHyphenDocParamLikeTag() {
        while (parseOptional(Token.Whitespace))
            ; // Skip whitespace
        if (parseOptional(Token.Hyphen)) {
            // The doc content started with a hyphen, so skip subsequent whitespace
            // (The if statement already advanced past the hyphen itself.)
            while (parseOptional(Token.Whitespace))
                ;
        }
    }
    function parseDocSimpleTag(pos, tagName, kind) {
        const content = parseDocContent();
        return {
            kind,
            tagName,
            content,
            ...finishNode(pos),
        };
    }
    function parseDocIdentifier(messageId) {
        // We don't allow whitespace between @ and tag name, but allow
        // whitespace before all other identifiers.
        if (messageId !== "tag") {
            while (parseOptional(Token.Whitespace))
                ;
        }
        const pos = tokenPos();
        let sv;
        if (token() === Token.Identifier) {
            sv = tokenValue();
            nextToken();
        }
        else {
            sv = "";
            warning({ code: "doc-invalid-identifier", messageId });
        }
        return {
            kind: SyntaxKind.Identifier,
            sv,
            ...finishNode(pos),
        };
    }
    // utility functions
    function token() {
        return scanner.token;
    }
    function tokenFlags() {
        return scanner.tokenFlags;
    }
    function tokenValue() {
        return scanner.getTokenValue();
    }
    function tokenPos() {
        return scanner.tokenPosition;
    }
    function tokenEnd() {
        return scanner.position;
    }
    function nextToken() {
        // keep track of the previous token end separately from the current scanner
        // position as these will differ when the previous token had trailing
        // trivia, and we don't want to squiggle the trivia.
        previousTokenEnd = scanner.position;
        return currentMode === 0 /* ParseMode.Syntax */ ? nextSyntaxToken() : nextDocToken();
    }
    function nextSyntaxToken() {
        docRanges = [];
        for (;;) {
            scanner.scan();
            if (isTrivia(token())) {
                if (!newLineIsTrivia && token() === Token.NewLine) {
                    break;
                }
                let comment = undefined;
                if (options.comments && isComment(token())) {
                    comment = {
                        kind: token() === Token.SingleLineComment
                            ? SyntaxKind.LineComment
                            : SyntaxKind.BlockComment,
                        pos: tokenPos(),
                        end: tokenEnd(),
                    };
                    comments.push(comment);
                }
                if (tokenFlags() & TokenFlags.DocComment) {
                    docRanges.push({
                        pos: tokenPos(),
                        end: tokenEnd(),
                        comment: comment,
                    });
                }
            }
            else {
                break;
            }
        }
    }
    function nextDocToken() {
        // NOTE: trivia tokens are always significant in doc comments.
        scanner.scanDoc();
    }
    function nextStringTemplateToken(tokenFlags) {
        scanner.reScanStringTemplate(tokenFlags);
    }
    function createMissingIdentifier() {
        const pos = tokenPos();
        previousTokenEnd = pos;
        missingIdentifierCounter++;
        return {
            kind: SyntaxKind.Identifier,
            sv: "<missing identifier>" + missingIdentifierCounter,
            ...finishNode(pos),
        };
    }
    function createMissingTypeReference() {
        const pos = tokenPos();
        const { items: args } = createEmptyList();
        return {
            kind: SyntaxKind.TypeReference,
            target: createMissingIdentifier(),
            arguments: args,
            ...finishNode(pos),
        };
    }
    function finishNode(pos) {
        const flags = parseErrorInNextFinishedNode ? 2 /* NodeFlags.ThisNodeHasError */ : 0 /* NodeFlags.None */;
        parseErrorInNextFinishedNode = false;
        return withSymbol({ pos, end: previousTokenEnd, flags });
    }
    // pretend to add as symbol property, likely to a node that is being created.
    function withSymbol(obj) {
        return obj;
    }
    function createEmptyList(range = { pos: -1, end: -1 }) {
        return {
            items: [],
            range,
        };
    }
    /**
     * Parse a delimited list of elements, including the surrounding open and
     * close punctuation
     *
     * This shared driver function is used to share sensitive error recovery code.
     * In particular, error recovery by inserting tokens deemed missing is
     * susceptible to getting stalled in a loop iteration without making any
     * progress, and we guard against this in a shared place here.
     *
     * Note that statement and decorator lists do not have this issue. We always
     * consume at least a real '@' for a decorator and if the leading token of a
     * statement is not one of our statement keywords, ';', or '@', it is consumed
     * as part of a bad statement. As such, parsing of decorators and statements
     * do not go through here.
     */
    function parseList(kind, parseItem) {
        const r = createEmptyList();
        if (kind.open !== Token.None) {
            const t = tokenPos();
            if (parseExpected(kind.open)) {
                mutate(r.range).pos = t;
            }
        }
        if (kind.allowEmpty && parseOptional(kind.close)) {
            mutate(r.range).end = previousTokenEnd;
            return r;
        }
        while (true) {
            const startingPos = tokenPos();
            const { pos, docs, directives, decorators } = parseAnnotations({
                skipParsingDocNodes: Boolean(kind.invalidAnnotationTarget),
            });
            if (kind.invalidAnnotationTarget) {
                reportInvalidDecorators(decorators, kind.invalidAnnotationTarget);
                reportInvalidDirective(directives, kind.invalidAnnotationTarget);
            }
            if (directives.length === 0 && decorators.length === 0 && atEndOfListWithError(kind)) {
                // Error recovery: end surrounded list at statement keyword or end
                // of file. Note, however, that we must parse a missing element if
                // there were directives or decorators as we cannot drop those from
                // the tree.
                if (parseExpected(kind.close)) {
                    mutate(r.range).end = previousTokenEnd;
                }
                break;
            }
            let item;
            if (kind.invalidAnnotationTarget) {
                item = parseItem();
            }
            else {
                item = parseItem(pos, decorators);
                mutate(item).docs = docs;
                mutate(item).directives = directives;
            }
            r.items.push(item);
            const delimiter = token();
            const delimiterPos = tokenPos();
            if (parseOptionalDelimiter(kind)) {
                // Delimiter found: check if it's trailing.
                if (parseOptional(kind.close)) {
                    mutate(r.range).end = previousTokenEnd;
                    if (!kind.trailingDelimiterIsValid) {
                        error({
                            code: "trailing-token",
                            format: { token: TokenDisplay[delimiter] },
                            target: {
                                pos: delimiterPos,
                                end: delimiterPos + 1,
                            },
                        });
                    }
                    // It was trailing and we've consumed the close token.
                    break;
                }
                // Not trailing. We can safely skip the progress check below here
                // because we know that we consumed a real delimiter.
                continue;
            }
            else if (kind.close === Token.None) {
                // If a list is *not* surrounded by punctuation, then the list ends when
                // there's no delimiter after an item.
                break;
            }
            else if (parseOptional(kind.close)) {
                mutate(r.range).end = previousTokenEnd;
                // If a list *is* surrounded by punctuation, then the list ends when we
                // reach the close token.
                break;
            }
            else if (atEndOfListWithError(kind)) {
                // Error recovery: If a list *is* surrounded by punctuation, then
                // the list ends at statement keyword or end-of-file under the
                // assumption that the closing delimiter is missing. This check is
                // duplicated from above to preempt the parseExpected(delimeter)
                // below.
                if (parseExpected(kind.close)) {
                    mutate(r.range).end = previousTokenEnd;
                }
                break;
            }
            else {
                // Error recovery: if a list kind *is* surrounded by punctuation and we
                // find neither a delimiter nor a close token after an item, then we
                // assume there is a missing delimiter between items.
                //
                // Example: `model M { a: B <missing semicolon> c: D }
                parseExpected(kind.delimiter);
            }
            if (startingPos === tokenPos()) {
                // Error recovery: we've inserted everything during this loop iteration
                // and haven't made any progress. Assume that the current token is a bad
                // representation of the end of the the list that we're trying to get
                // through.
                //
                // Simple repro: `model M { ]` would loop forever without this check.
                //
                if (parseExpected(kind.close)) {
                    mutate(r.range).end = previousTokenEnd;
                }
                nextToken();
                // remove the item that was entirely inserted by error recovery.
                r.items.pop();
                break;
            }
        }
        return r;
    }
    /**
     * Parse a delimited list with surrounding open and close punctuation if the
     * open token is present. Otherwise, return an empty list.
     */
    function parseOptionalList(kind, parseItem) {
        return token() === kind.open ? parseList(kind, parseItem) : createEmptyList();
    }
    function parseOptionalDelimiter(kind) {
        if (parseOptional(kind.delimiter)) {
            return true;
        }
        if (token() === kind.toleratedDelimiter) {
            if (!kind.toleratedDelimiterIsValid) {
                parseExpected(kind.delimiter);
            }
            nextToken();
            return true;
        }
        return false;
    }
    function atEndOfListWithError(kind) {
        return (kind.close !== Token.None &&
            (isStatementKeyword(token()) || token() === Token.EndOfFile) &&
            token() !== kind.allowedStatementKeyword);
    }
    function parseEmptyStatement(pos) {
        parseExpected(Token.Semicolon);
        return { kind: SyntaxKind.EmptyStatement, ...finishNode(pos) };
    }
    function parseInvalidStatement(pos, decorators) {
        // Error recovery: avoid an avalanche of errors when we get cornered into
        // parsing statements where none exist. Skip until we find a statement
        // keyword or decorator and only report one error for a contiguous range of
        // neither.
        do {
            nextToken();
        } while (!isStatementKeyword(token()) &&
            token() !== Token.At &&
            token() !== Token.Semicolon &&
            token() !== Token.EndOfFile);
        error({
            code: "token-expected",
            messageId: "statement",
            target: { pos, end: previousTokenEnd },
        });
        return { kind: SyntaxKind.InvalidStatement, decorators, ...finishNode(pos) };
    }
    function error(report) {
        parseErrorInNextFinishedNode = true;
        const location = {
            file: scanner.file,
            pos: report.target?.pos ?? tokenPos(),
            end: report.target?.end ?? tokenEnd(),
        };
        if (!report.printable) {
            treePrintable = false;
        }
        // Error recovery: don't report more than 1 consecutive error at the same
        // position. The code path taken by error recovery after logging an error
        // can otherwise produce redundant and less decipherable errors, which this
        // suppresses.
        const realPos = report.target?.realPos ?? location.pos;
        if (realPositionOfLastError === realPos) {
            return;
        }
        realPositionOfLastError = realPos;
        const diagnostic = createDiagnostic({
            ...report,
            target: location,
        });
        assert(diagnostic.severity === "error", "This function is for reporting errors. Use warning() for warnings.");
        parseDiagnostics.push(diagnostic);
    }
    function warning(report) {
        const location = {
            file: scanner.file,
            pos: report.target?.pos ?? tokenPos(),
            end: report.target?.end ?? tokenEnd(),
        };
        const diagnostic = createDiagnostic({
            ...report,
            target: location,
        });
        assert(diagnostic.severity === "warning", "This function is for reporting warnings only. Use error() for errors.");
        parseDiagnostics.push(diagnostic);
    }
    function reportDiagnostic(diagnostic) {
        if (diagnostic.severity === "error") {
            parseErrorInNextFinishedNode = true;
            treePrintable = false;
        }
        parseDiagnostics.push(diagnostic);
    }
    function assert(condition, message) {
        const location = {
            file: scanner.file,
            pos: tokenPos(),
            end: tokenEnd(),
        };
        compilerAssert(condition, message, location);
    }
    function reportInvalidDecorators(decorators, nodeName) {
        for (const decorator of decorators) {
            error({ code: "invalid-decorator-location", format: { nodeName }, target: decorator });
        }
    }
    function reportInvalidDirective(directives, nodeName) {
        for (const directive of directives) {
            error({ code: "invalid-directive-location", format: { nodeName }, target: directive });
        }
    }
    function parseExpected(expectedToken) {
        if (token() === expectedToken) {
            nextToken();
            return true;
        }
        const location = getAdjustedDefaultLocation(expectedToken);
        error({
            code: "token-expected",
            format: { token: TokenDisplay[expectedToken] },
            target: location,
            printable: isPunctuation(expectedToken),
        });
        return false;
    }
    function expectTokenIsOneOf(...args) {
        const tok = token();
        for (const expected of args) {
            if (expected === Token.None) {
                continue;
            }
            if (tok === expected) {
                return tok;
            }
        }
        errorTokenIsNotOneOf(...args);
        return Token.None;
    }
    function parseExpectedOneOf(...args) {
        const tok = expectTokenIsOneOf(...args);
        if (tok !== Token.None) {
            nextToken();
        }
        return tok;
    }
    function errorTokenIsNotOneOf(...args) {
        const location = getAdjustedDefaultLocation(args[0]);
        const displayList = args.map((t, i) => {
            if (i === args.length - 1) {
                return `or ${TokenDisplay[t]}`;
            }
            return TokenDisplay[t];
        });
        error({ code: "token-expected", format: { token: displayList.join(", ") }, target: location });
    }
    function parseOptional(optionalToken) {
        if (token() === optionalToken) {
            nextToken();
            return true;
        }
        return false;
    }
    function getAdjustedDefaultLocation(token) {
        // Put the squiggly immediately after prior token when missing punctuation.
        // Avoids saying ';' is expected far away after a long comment, for example.
        // It's also confusing to squiggle the current token even if its nearby
        // in this case.
        return isPunctuation(token)
            ? { pos: previousTokenEnd, end: previousTokenEnd + 1, realPos: tokenPos() }
            : undefined;
    }
}
function exprIsBareIdentifier(expr) {
    return (expr.kind === SyntaxKind.TypeReference &&
        expr.target.kind === SyntaxKind.Identifier &&
        expr.arguments.length === 0);
}
function visitChildren(node, cb) {
    if (node.directives) {
        const result = visitEach(cb, node.directives);
        if (result)
            return result;
    }
    if (node.docs) {
        const result = visitEach(cb, node.docs);
        if (result)
            return result;
    }
    switch (node.kind) {
        case SyntaxKind.TypeSpecScript:
            return visitNode(cb, node.id) || visitEach(cb, node.statements);
        case SyntaxKind.ArrayExpression:
            return visitNode(cb, node.elementType);
        case SyntaxKind.AugmentDecoratorStatement:
            return (visitNode(cb, node.target) ||
                visitNode(cb, node.targetType) ||
                visitEach(cb, node.arguments));
        case SyntaxKind.DecoratorExpression:
            return visitNode(cb, node.target) || visitEach(cb, node.arguments);
        case SyntaxKind.CallExpression:
            return visitNode(cb, node.target) || visitEach(cb, node.arguments);
        case SyntaxKind.DirectiveExpression:
            return visitNode(cb, node.target) || visitEach(cb, node.arguments);
        case SyntaxKind.ImportStatement:
            return visitNode(cb, node.path);
        case SyntaxKind.OperationStatement:
            return (visitEach(cb, node.decorators) ||
                visitNode(cb, node.id) ||
                visitEach(cb, node.templateParameters) ||
                visitNode(cb, node.signature));
        case SyntaxKind.OperationSignatureDeclaration:
            return visitNode(cb, node.parameters) || visitNode(cb, node.returnType);
        case SyntaxKind.OperationSignatureReference:
            return visitNode(cb, node.baseOperation);
        case SyntaxKind.NamespaceStatement:
            return (visitEach(cb, node.decorators) ||
                visitNode(cb, node.id) ||
                (isArray(node.statements) ? visitEach(cb, node.statements) : visitNode(cb, node.statements)));
        case SyntaxKind.InterfaceStatement:
            return (visitEach(cb, node.decorators) ||
                visitNode(cb, node.id) ||
                visitEach(cb, node.templateParameters) ||
                visitEach(cb, node.extends) ||
                visitEach(cb, node.operations));
        case SyntaxKind.UsingStatement:
            return visitNode(cb, node.name);
        case SyntaxKind.IntersectionExpression:
            return visitEach(cb, node.options);
        case SyntaxKind.MemberExpression:
            return visitNode(cb, node.base) || visitNode(cb, node.id);
        case SyntaxKind.ModelExpression:
            return visitEach(cb, node.properties);
        case SyntaxKind.ModelProperty:
            return (visitEach(cb, node.decorators) ||
                visitNode(cb, node.id) ||
                visitNode(cb, node.value) ||
                visitNode(cb, node.default));
        case SyntaxKind.ModelSpreadProperty:
            return visitNode(cb, node.target);
        case SyntaxKind.ModelStatement:
            return (visitEach(cb, node.decorators) ||
                visitNode(cb, node.id) ||
                visitEach(cb, node.templateParameters) ||
                visitNode(cb, node.extends) ||
                visitNode(cb, node.is) ||
                visitEach(cb, node.properties));
        case SyntaxKind.ScalarStatement:
            return (visitEach(cb, node.decorators) ||
                visitNode(cb, node.id) ||
                visitEach(cb, node.templateParameters) ||
                visitEach(cb, node.members) ||
                visitNode(cb, node.extends));
        case SyntaxKind.ScalarConstructor:
            return visitNode(cb, node.id) || visitEach(cb, node.parameters);
        case SyntaxKind.UnionStatement:
            return (visitEach(cb, node.decorators) ||
                visitNode(cb, node.id) ||
                visitEach(cb, node.templateParameters) ||
                visitEach(cb, node.options));
        case SyntaxKind.UnionVariant:
            return visitEach(cb, node.decorators) || visitNode(cb, node.id) || visitNode(cb, node.value);
        case SyntaxKind.EnumStatement:
            return (visitEach(cb, node.decorators) || visitNode(cb, node.id) || visitEach(cb, node.members));
        case SyntaxKind.EnumMember:
            return visitEach(cb, node.decorators) || visitNode(cb, node.id) || visitNode(cb, node.value);
        case SyntaxKind.EnumSpreadMember:
            return visitNode(cb, node.target);
        case SyntaxKind.AliasStatement:
            return (visitNode(cb, node.id) ||
                visitEach(cb, node.templateParameters) ||
                visitNode(cb, node.value));
        case SyntaxKind.ConstStatement:
            return visitNode(cb, node.id) || visitNode(cb, node.value) || visitNode(cb, node.type);
        case SyntaxKind.DecoratorDeclarationStatement:
            return (visitEach(cb, node.modifiers) ||
                visitNode(cb, node.id) ||
                visitNode(cb, node.target) ||
                visitEach(cb, node.parameters));
        case SyntaxKind.FunctionDeclarationStatement:
            return (visitEach(cb, node.modifiers) ||
                visitNode(cb, node.id) ||
                visitEach(cb, node.parameters) ||
                visitNode(cb, node.returnType));
        case SyntaxKind.FunctionParameter:
            return visitNode(cb, node.id) || visitNode(cb, node.type);
        case SyntaxKind.TypeReference:
            return visitNode(cb, node.target) || visitEach(cb, node.arguments);
        case SyntaxKind.ValueOfExpression:
            return visitNode(cb, node.target);
        case SyntaxKind.TypeOfExpression:
            return visitNode(cb, node.target);
        case SyntaxKind.TupleExpression:
            return visitEach(cb, node.values);
        case SyntaxKind.UnionExpression:
            return visitEach(cb, node.options);
        case SyntaxKind.Projection:
            return (visitNode(cb, node.directionId) ||
                visitEach(cb, node.modifierIds) ||
                visitEach(cb, node.parameters) ||
                visitEach(cb, node.body));
        case SyntaxKind.ProjectionExpressionStatement:
            return visitNode(cb, node.expr);
        case SyntaxKind.ProjectionCallExpression:
            return visitNode(cb, node.target) || visitEach(cb, node.arguments);
        case SyntaxKind.ProjectionMemberExpression:
            return visitNode(cb, node.base) || visitNode(cb, node.id);
        // binops
        case SyntaxKind.ProjectionLogicalExpression:
        case SyntaxKind.ProjectionRelationalExpression:
        case SyntaxKind.ProjectionArithmeticExpression:
        case SyntaxKind.ProjectionEqualityExpression:
            return visitNode(cb, node.left) || visitNode(cb, node.right);
        case SyntaxKind.ProjectionUnaryExpression:
            return visitNode(cb, node.target);
        case SyntaxKind.ProjectionModelExpression:
            return visitEach(cb, node.properties);
        case SyntaxKind.ProjectionModelProperty:
            return (visitEach(cb, node.decorators) ||
                visitNode(cb, node.id) ||
                visitNode(cb, node.value) ||
                visitNode(cb, node.default));
        case SyntaxKind.ProjectionModelSpreadProperty:
            return visitNode(cb, node.target);
        case SyntaxKind.ProjectionTupleExpression:
            return visitEach(cb, node.values);
        case SyntaxKind.ProjectionBlockExpression:
            return visitEach(cb, node.statements);
        case SyntaxKind.ProjectionIfExpression:
            return (visitNode(cb, node.test) || visitNode(cb, node.consequent) || visitNode(cb, node.alternate));
        case SyntaxKind.ProjectionLambdaExpression:
            return visitEach(cb, node.parameters) || visitNode(cb, node.body);
        case SyntaxKind.ProjectionStatement:
            return (visitNode(cb, node.id) || visitNode(cb, node.selector) || visitEach(cb, node.projections));
        case SyntaxKind.ProjectionDecoratorReferenceExpression:
            return visitNode(cb, node.target);
        case SyntaxKind.Return:
            return visitNode(cb, node.value);
        case SyntaxKind.InvalidStatement:
            return visitEach(cb, node.decorators);
        case SyntaxKind.TemplateParameterDeclaration:
            return (visitNode(cb, node.id) || visitNode(cb, node.constraint) || visitNode(cb, node.default));
        case SyntaxKind.TemplateArgument:
            return (node.name && visitNode(cb, node.name)) || visitNode(cb, node.argument);
        case SyntaxKind.ProjectionLambdaParameterDeclaration:
            return visitNode(cb, node.id);
        case SyntaxKind.ProjectionParameterDeclaration:
            return visitNode(cb, node.id);
        case SyntaxKind.Doc:
            return visitEach(cb, node.content) || visitEach(cb, node.tags);
        case SyntaxKind.DocParamTag:
        case SyntaxKind.DocTemplateTag:
            return (visitNode(cb, node.tagName) || visitNode(cb, node.paramName) || visitEach(cb, node.content));
        case SyntaxKind.DocPropTag:
            return (visitNode(cb, node.tagName) || visitNode(cb, node.propName) || visitEach(cb, node.content));
        case SyntaxKind.DocReturnsTag:
        case SyntaxKind.DocErrorsTag:
        case SyntaxKind.DocUnknownTag:
            return visitNode(cb, node.tagName) || visitEach(cb, node.content);
        case SyntaxKind.StringTemplateExpression:
            return visitNode(cb, node.head) || visitEach(cb, node.spans);
        case SyntaxKind.StringTemplateSpan:
            return visitNode(cb, node.expression) || visitNode(cb, node.literal);
        case SyntaxKind.ObjectLiteral:
            return visitEach(cb, node.properties);
        case SyntaxKind.ObjectLiteralProperty:
            return visitNode(cb, node.id) || visitNode(cb, node.value);
        case SyntaxKind.ObjectLiteralSpreadProperty:
            return visitNode(cb, node.target);
        case SyntaxKind.ArrayLiteral:
            return visitEach(cb, node.values);
        // no children for the rest of these.
        case SyntaxKind.StringTemplateHead:
        case SyntaxKind.StringTemplateMiddle:
        case SyntaxKind.StringTemplateTail:
        case SyntaxKind.StringLiteral:
        case SyntaxKind.NumericLiteral:
        case SyntaxKind.BooleanLiteral:
        case SyntaxKind.Identifier:
        case SyntaxKind.EmptyStatement:
        case SyntaxKind.ProjectionModelSelector:
        case SyntaxKind.ProjectionModelPropertySelector:
        case SyntaxKind.ProjectionScalarSelector:
        case SyntaxKind.ProjectionUnionSelector:
        case SyntaxKind.ProjectionUnionVariantSelector:
        case SyntaxKind.ProjectionInterfaceSelector:
        case SyntaxKind.ProjectionOperationSelector:
        case SyntaxKind.ProjectionEnumSelector:
        case SyntaxKind.ProjectionEnumMemberSelector:
        case SyntaxKind.VoidKeyword:
        case SyntaxKind.NeverKeyword:
        case SyntaxKind.ExternKeyword:
        case SyntaxKind.UnknownKeyword:
        case SyntaxKind.JsSourceFile:
        case SyntaxKind.JsNamespaceDeclaration:
        case SyntaxKind.DocText:
            return;
        default:
            return;
    }
}
function visitNode(cb, node) {
    return node && cb(node);
}
function visitEach(cb, nodes) {
    if (!nodes) {
        return;
    }
    for (const node of nodes) {
        const result = cb(node);
        if (result) {
            return result;
        }
    }
    return;
}
/**
 * check whether a position belongs to a range (excluding the start and end pos)
 * i.e. <range.pos>{<start to return true>...<end to return true>}<range.end>
 *
 * remark: if range.pos is -1 means no start point found, so return false
 *         if range.end is -1 means no end point found, so return true if position is greater than range.pos
 */
function positionInRange(position, range) {
    return range.pos >= 0 && position > range.pos && (range.end === -1 || position < range.end);
}
function getNodeAtPositionDetail(script, position, filter = () => true) {
    const cur = getNodeAtPosition(script, position, (n) => filter(n, "cur"));
    const input = script.file.text;
    const char = input.charCodeAt(position);
    const preChar = position >= 0 ? input.charCodeAt(position - 1) : NaN;
    const nextChar = position < input.length ? input.charCodeAt(position + 1) : NaN;
    let inTrivia = false;
    let triviaStart;
    let triviaEnd;
    if (!cur || cur.kind !== SyntaxKind.StringLiteral) {
        const { char: cp } = codePointBefore(input, position);
        if (!cp || !isIdentifierContinue(cp)) {
            triviaEnd = skipTrivia(input, position);
            triviaStart = skipTriviaBackward(script, position) + 1;
            inTrivia = triviaEnd !== position;
        }
    }
    if (!inTrivia) {
        const beforeId = skipContinuousIdentifier(input, position, true /*isBackward*/);
        triviaStart = skipTriviaBackward(script, beforeId) + 1;
        const afterId = skipContinuousIdentifier(input, position, false /*isBackward*/);
        triviaEnd = skipTrivia(input, afterId);
    }
    if (triviaStart === undefined || triviaEnd === undefined) {
        compilerAssert(false, "unexpected, triviaStart and triviaEnd should be defined");
    }
    return {
        node: cur,
        char,
        preChar,
        nextChar,
        position,
        inTrivia,
        triviaStartPosition: triviaStart,
        triviaEndPosition: triviaEnd,
        getPositionDetailBeforeTrivia: () => {
            // getNodeAtPosition will also include the 'node.end' position which is the triviaStart pos
            return getNodeAtPositionDetail(script, triviaStart, (n) => filter(n, "pre"));
        },
        getPositionDetailAfterTrivia: () => {
            return getNodeAtPositionDetail(script, triviaEnd, (n) => filter(n, "post"));
        },
    };
}
function getNodeAtPosition(script, position, filter = (node) => true) {
    return visit(script);
    function visit(node) {
        // We deliberately include the end position here because we need to hit
        // nodes when the cursor is positioned immediately after an identifier.
        // This is especially vital for completion. It's also generally OK
        // because the language doesn't (and should never) have syntax where you
        // could place the cursor ambiguously between two adjacent,
        // non-punctuation, non-trivia tokens that have no punctuation or trivia
        // separating them.
        if (node.pos <= position && position <= node.end) {
            // We only need to recursively visit children of nodes that satisfied
            // the condition above and therefore contain the given position. If a
            // node does not contain a position, then neither do its children.
            const child = visitChildren(node, visit);
            // A child match here is better than a self-match below as we want the
            // deepest (most specific) node. In other words, the search is depth
            // first. For example, consider `A<B<C>>`: If the cursor is on `B`,
            // then prefer B<C> over A<B<C>>.
            if (child) {
                return child;
            }
            if (filter(node)) {
                return node;
            }
        }
        return undefined;
    }
}
function hasParseError(node) {
    if (node.flags & 2 /* NodeFlags.ThisNodeHasError */) {
        return true;
    }
    checkForDescendantErrors(node);
    return node.flags & 4 /* NodeFlags.DescendantHasError */;
}
function checkForDescendantErrors(node) {
    if (node.flags & 1 /* NodeFlags.DescendantErrorsExamined */) {
        return;
    }
    mutate(node).flags |= 1 /* NodeFlags.DescendantErrorsExamined */;
    visitChildren(node, (child) => {
        if (child.flags & 2 /* NodeFlags.ThisNodeHasError */) {
            mutate(node).flags |= 4 /* NodeFlags.DescendantHasError */ | 1 /* NodeFlags.DescendantErrorsExamined */;
            return true;
        }
        checkForDescendantErrors(child);
        if (child.flags & 4 /* NodeFlags.DescendantHasError */) {
            mutate(node).flags |= 4 /* NodeFlags.DescendantHasError */ | 1 /* NodeFlags.DescendantErrorsExamined */;
            return true;
        }
        mutate(child).flags |= 1 /* NodeFlags.DescendantErrorsExamined */;
        return false;
    });
}
function isImportStatement(node) {
    return node.kind === SyntaxKind.ImportStatement;
}
function isBlocklessNamespace(node) {
    if (node.kind !== SyntaxKind.NamespaceStatement) {
        return false;
    }
    while (!isArray(node.statements) && node.statements) {
        node = node.statements;
    }
    return node.statements === undefined;
}
function getFirstAncestor(node, test, includeSelf = false) {
    if (includeSelf && test(node)) {
        return node;
    }
    for (let n = node.parent; n; n = n.parent) {
        if (test(n)) {
            return n;
        }
    }
    return undefined;
}
function getIdentifierContext(id) {
    const node = getFirstAncestor(id, (n) => n.kind !== SyntaxKind.MemberExpression);
    compilerAssert(node, "Identifier with no non-member-expression ancestor.");
    let kind;
    switch (node.kind) {
        case SyntaxKind.TypeReference:
            kind = IdentifierKind.TypeReference;
            break;
        case SyntaxKind.AugmentDecoratorStatement:
        case SyntaxKind.DecoratorExpression:
            kind = IdentifierKind.Decorator;
            break;
        case SyntaxKind.ProjectionCallExpression:
            kind = IdentifierKind.Function;
            break;
        case SyntaxKind.UsingStatement:
            kind = IdentifierKind.Using;
            break;
        case SyntaxKind.TemplateArgument:
            kind = IdentifierKind.TemplateArgument;
            break;
        case SyntaxKind.ObjectLiteralProperty:
            kind = IdentifierKind.ObjectLiteralProperty;
            break;
        case SyntaxKind.ModelProperty:
            switch (node.parent?.kind) {
                case SyntaxKind.ModelExpression:
                    kind = IdentifierKind.ModelExpressionProperty;
                    break;
                case SyntaxKind.ModelStatement:
                    kind = IdentifierKind.ModelStatementProperty;
                    break;
                default:
                    compilerAssert("false", "ModelProperty with unexpected parent kind.");
                    kind =
                        id.parent.id === id
                            ? IdentifierKind.Declaration
                            : IdentifierKind.Other;
                    break;
            }
            break;
        default:
            kind =
                id.parent.id === id
                    ? IdentifierKind.Declaration
                    : IdentifierKind.Other;
            break;
    }
    return { node, kind };
}

// Use a regular expression to define the prefix for TypeSpec-exposed functions
// defined in JavaScript modules
const DecoratorFunctionPattern = /^\$/;
const SymbolTable = class extends Map {
    duplicates = new Map();
    constructor(source) {
        super();
        if (source) {
            for (const [key, value] of source) {
                // Note: shallow copy of value here so we can mutate flags on set.
                super.set(key, { ...value });
            }
            for (const [key, value] of source.duplicates) {
                this.duplicates.set(key, new Set(value));
            }
        }
    }
    // First set for a given key wins, but record all duplicates for diagnostics.
    set(key, value) {
        const existing = super.get(key);
        if (existing === undefined) {
            super.set(key, value);
        }
        else {
            if (existing.flags & 524288 /* SymbolFlags.Using */) {
                mutate(existing).flags |= 1048576 /* SymbolFlags.DuplicateUsing */;
            }
            const duplicateArray = this.duplicates.get(existing);
            if (duplicateArray) {
                duplicateArray.add(value);
            }
            else {
                this.duplicates.set(existing, new Set([existing, value]));
            }
        }
        return this;
    }
};
function createSymbolTable(source) {
    return new SymbolTable(source);
}
function createBinder(program) {
    let currentFile;
    let parentNode;
    let fileNamespace;
    let scope;
    // tracks which selectors were used with which projection symbols
    // for reporting duplicates
    const projectionSymbolSelectors = new Map();
    return {
        bindSourceFile,
        bindJsSourceFile,
        bindNode,
    };
    function isFunctionName(name) {
        return DecoratorFunctionPattern.test(name);
    }
    function getFunctionName(name) {
        return name.replace(DecoratorFunctionPattern, "");
    }
    function bindJsSourceFile(sourceFile) {
        // cast because it causes TS to make the type of .symbol never other
        if (sourceFile.symbol !== undefined) {
            return;
        }
        const tracer = program.tracer.sub("bind.js");
        fileNamespace = undefined;
        mutate(sourceFile).symbol = createSymbol(sourceFile, sourceFile.file.path, 2097152 /* SymbolFlags.SourceFile */);
        const rootNs = sourceFile.esmExports["namespace"];
        for (const [key, member] of Object.entries(sourceFile.esmExports)) {
            let name;
            let kind;
            let containerSymbol = sourceFile.symbol;
            if (key === "$flags") {
                const context = getLocationContext(program, sourceFile);
                if (context.type === "library" || context.type === "project") {
                    mutate(context).flags = member;
                }
            }
            else if (typeof member === "function") {
                // lots of 'any' casts here because control flow narrowing `member` to Function
                // isn't particularly useful it turns out.
                if (isFunctionName(key)) {
                    name = getFunctionName(key);
                    kind = "decorator";
                    if (name === "onValidate") {
                        const context = getLocationContext(program, sourceFile);
                        const metadata = context.type === "library"
                            ? context.metadata
                            : { type: "file" };
                        program.onValidate(member, metadata);
                        continue;
                    }
                    else if (name === "onEmit") {
                        // nothing to do here this is loaded as emitter.
                        continue;
                    }
                }
                else {
                    name = key;
                    kind = "function";
                }
                const nsParts = resolveJSMemberNamespaceParts(rootNs, member);
                for (const part of nsParts) {
                    const existingBinding = containerSymbol.exports.get(part);
                    const jsNamespaceNode = {
                        kind: SyntaxKind.JsNamespaceDeclaration,
                        id: {
                            kind: SyntaxKind.Identifier,
                            sv: part,
                            pos: 0,
                            end: 0,
                            flags: 0 /* NodeFlags.None */,
                            symbol: undefined,
                        },
                        pos: sourceFile.pos,
                        end: sourceFile.end,
                        parent: sourceFile,
                        flags: 0 /* NodeFlags.None */,
                        symbol: undefined,
                    };
                    const sym = createSymbol(jsNamespaceNode, part, 4096 /* SymbolFlags.Namespace */, containerSymbol);
                    mutate(jsNamespaceNode).symbol = sym;
                    if (existingBinding) {
                        if (existingBinding.flags & 4096 /* SymbolFlags.Namespace */) {
                            // since the namespace was "declared" as part of this source file,
                            // we can simply re-use it.
                            containerSymbol = existingBinding;
                        }
                        else {
                            // we have some conflict, lets report a duplicate binding error.
                            mutate(containerSymbol.exports).set(part, sym);
                        }
                    }
                    else {
                        mutate(sym).exports = createSymbolTable();
                        mutate(containerSymbol.exports).set(part, sym);
                        containerSymbol = sym;
                    }
                }
                let sym;
                if (kind === "decorator") {
                    tracer.trace("decorator", `Bound decorator "@${name}" in namespace "${nsParts.join(".")}".`);
                    sym = createSymbol(sourceFile, "@" + name, 16384 /* SymbolFlags.Decorator */ | 8388608 /* SymbolFlags.Implementation */, containerSymbol);
                }
                else {
                    tracer.trace("function", `Bound function "${name}" in namespace "${nsParts.join(".")}".`);
                    sym = createSymbol(sourceFile, name, 131072 /* SymbolFlags.Function */ | 8388608 /* SymbolFlags.Implementation */, containerSymbol);
                }
                mutate(sym).value = member;
                mutate(containerSymbol.exports).set(sym.name, sym);
            }
        }
    }
    function resolveJSMemberNamespaceParts(rootNs, member) {
        const memberNs = member.namespace;
        const nsParts = [];
        if (rootNs) {
            nsParts.push(...rootNs.split("."));
        }
        if (memberNs) {
            nsParts.push(...memberNs.split("."));
        }
        return nsParts;
    }
    function bindSourceFile(script) {
        if (script.locals !== undefined) {
            return;
        }
        mutate(script).locals = createSymbolTable();
        mutate(script).symbol = createSymbol(script, script.file.path, 2097152 /* SymbolFlags.SourceFile */);
        mutate(script.symbol).exports = createSymbolTable();
        fileNamespace = undefined;
        currentFile = script;
        scope = script;
        bindNode(script);
    }
    function bindNode(node) {
        if (!node)
            return;
        // set the node's parent since we're going for a walk anyway
        mutate(node).parent = parentNode;
        switch (node.kind) {
            case SyntaxKind.ModelStatement:
                bindModelStatement(node);
                break;
            case SyntaxKind.ModelExpression:
                bindModelExpression(node);
                break;
            case SyntaxKind.ScalarStatement:
                bindScalarStatement(node);
                break;
            case SyntaxKind.InterfaceStatement:
                bindInterfaceStatement(node);
                break;
            case SyntaxKind.UnionStatement:
                bindUnionStatement(node);
                break;
            case SyntaxKind.AliasStatement:
                bindAliasStatement(node);
                break;
            case SyntaxKind.ConstStatement:
                bindConstStatement(node);
                break;
            case SyntaxKind.EnumStatement:
                bindEnumStatement(node);
                break;
            case SyntaxKind.NamespaceStatement:
                bindNamespaceStatement(node);
                break;
            case SyntaxKind.OperationStatement:
                bindOperationStatement(node);
                break;
            case SyntaxKind.TemplateParameterDeclaration:
                bindTemplateParameterDeclaration(node);
                break;
            case SyntaxKind.UsingStatement:
                bindUsingStatement(node);
                break;
            case SyntaxKind.DecoratorDeclarationStatement:
                bindDecoratorDeclarationStatement(node);
                break;
            case SyntaxKind.FunctionDeclarationStatement:
                bindFunctionDeclarationStatement(node);
                break;
            case SyntaxKind.FunctionParameter:
                bindFunctionParameter(node);
                break;
            case SyntaxKind.Projection:
                bindProjection(node);
                break;
            case SyntaxKind.ProjectionStatement:
                bindProjectionStatement(node);
                break;
            case SyntaxKind.ProjectionParameterDeclaration:
                bindProjectionParameterDeclaration(node);
                break;
            case SyntaxKind.ProjectionLambdaParameterDeclaration:
                bindProjectionLambdaParameterDeclaration(node);
                break;
            case SyntaxKind.ProjectionLambdaExpression:
                bindProjectionLambdaExpression(node);
        }
        const prevParent = parentNode;
        // set parent node when we walk into children
        parentNode = node;
        if (hasScope(node)) {
            const prevScope = scope;
            scope = node;
            visitChildren(node, bindNode);
            if ("locals" in node) {
                program.reportDuplicateSymbols(node.locals);
            }
            scope = prevScope;
        }
        else {
            visitChildren(node, bindNode);
        }
        // restore parent node
        parentNode = prevParent;
    }
    function bindProjection(node) {
        mutate(node).locals = createSymbolTable();
    }
    /**
     * Binding projection statements is interesting because there may be
     * multiple declarations spread across various source files that all
     * contribute to the same symbol because they declare the same
     * projection on different selectors.
     *
     * There is presently an issue where we do not check for duplicate
     * projections when they're applied to a specific type. This could
     * be done with ease in the checker during evaluation, but could
     * probably instead be done in a post-bind phase - we just need
     * all the symbols in place so we know if a projection was declared
     * multiple times for the same symbol.
     *
     */
    function bindProjectionStatement(node) {
        const name = node.id.sv;
        const table = scope.symbol
            .exports;
        let sym;
        if (table.has(name)) {
            sym = table.get(name);
            if (!(sym.flags & 8192 /* SymbolFlags.Projection */)) {
                // clashing with some other decl, report duplicate symbol
                declareSymbol(node, 8192 /* SymbolFlags.Projection */);
                return;
            }
            mutate(sym.declarations).push(node);
        }
        else {
            sym = createSymbol(node, name, 8192 /* SymbolFlags.Projection */, scope.symbol);
            mutate(table).set(name, sym);
        }
        mutate(node).symbol = sym;
        if (node.selector.kind !== SyntaxKind.Identifier &&
            node.selector.kind !== SyntaxKind.MemberExpression) {
            let selectorString;
            switch (node.selector.kind) {
                case SyntaxKind.ProjectionModelSelector:
                    selectorString = "model";
                    break;
                case SyntaxKind.ProjectionModelPropertySelector:
                    selectorString = "modelproperty";
                    break;
                case SyntaxKind.ProjectionScalarSelector:
                    selectorString = "scalar";
                    break;
                case SyntaxKind.ProjectionOperationSelector:
                    selectorString = "op";
                    break;
                case SyntaxKind.ProjectionUnionSelector:
                    selectorString = "union";
                    break;
                case SyntaxKind.ProjectionUnionVariantSelector:
                    selectorString = "unionvariant";
                    break;
                case SyntaxKind.ProjectionEnumSelector:
                    selectorString = "enum";
                    break;
                case SyntaxKind.ProjectionEnumMemberSelector:
                    selectorString = "enummember";
                    break;
                case SyntaxKind.ProjectionInterfaceSelector:
                    selectorString = "interface";
                    break;
                default:
                    node.selector;
                    compilerAssert(false, "Unreachable");
            }
            let existingSelectors = projectionSymbolSelectors.get(sym);
            if (!existingSelectors) {
                existingSelectors = new Set();
                projectionSymbolSelectors.set(sym, existingSelectors);
            }
            if (existingSelectors.has(selectorString)) {
                // clashing with a like-named decl with this selector, so throw.
                declareSymbol(node, 8192 /* SymbolFlags.Projection */);
                return;
            }
            existingSelectors.add(selectorString);
        }
    }
    function bindProjectionParameterDeclaration(node) {
        declareSymbol(node, 65536 /* SymbolFlags.ProjectionParameter */);
    }
    function bindProjectionLambdaParameterDeclaration(node) {
        declareSymbol(node, 262144 /* SymbolFlags.FunctionParameter */);
    }
    function bindProjectionLambdaExpression(node) {
        mutate(node).locals = new SymbolTable();
    }
    function bindTemplateParameterDeclaration(node) {
        declareSymbol(node, 32768 /* SymbolFlags.TemplateParameter */);
    }
    function bindModelStatement(node) {
        declareSymbol(node, 2 /* SymbolFlags.Model */);
        // Initialize locals for type parameters
        mutate(node).locals = new SymbolTable();
    }
    function bindModelExpression(node) {
        bindSymbol(node, 2 /* SymbolFlags.Model */);
    }
    function bindScalarStatement(node) {
        declareSymbol(node, 8 /* SymbolFlags.Scalar */);
        // Initialize locals for type parameters
        mutate(node).locals = new SymbolTable();
    }
    function bindInterfaceStatement(node) {
        declareSymbol(node, 128 /* SymbolFlags.Interface */);
        mutate(node).locals = new SymbolTable();
    }
    function bindUnionStatement(node) {
        declareSymbol(node, 512 /* SymbolFlags.Union */);
        mutate(node).locals = new SymbolTable();
    }
    function bindAliasStatement(node) {
        declareSymbol(node, 2048 /* SymbolFlags.Alias */);
        // Initialize locals for type parameters
        mutate(node).locals = new SymbolTable();
    }
    function bindConstStatement(node) {
        declareSymbol(node, 16777216 /* SymbolFlags.Const */);
    }
    function bindEnumStatement(node) {
        declareSymbol(node, 32 /* SymbolFlags.Enum */);
    }
    function bindNamespaceStatement(statement) {
        // check if there's an existing symbol for this namespace
        const existingBinding = scope.symbol.exports.get(statement.id.sv);
        if (existingBinding && existingBinding.flags & 4096 /* SymbolFlags.Namespace */) {
            mutate(statement).symbol = existingBinding;
            // locals are never shared.
            mutate(statement).locals = createSymbolTable();
            mutate(existingBinding.declarations).push(statement);
        }
        else {
            // Initialize locals for non-exported symbols
            mutate(statement).locals = createSymbolTable();
            declareSymbol(statement, 4096 /* SymbolFlags.Namespace */);
        }
        currentFile.namespaces.push(statement);
        if (statement.statements === undefined) {
            fileNamespace = statement;
            let current = statement;
            while (current.kind !== SyntaxKind.TypeSpecScript) {
                currentFile.inScopeNamespaces.push(current);
                current = current.parent;
            }
        }
    }
    function bindUsingStatement(statement) {
        mutate(currentFile.usings).push(statement);
    }
    function bindOperationStatement(statement) {
        if (scope.kind !== SyntaxKind.InterfaceStatement) {
            declareSymbol(statement, 16 /* SymbolFlags.Operation */);
        }
        mutate(statement).locals = createSymbolTable();
    }
    function bindDecoratorDeclarationStatement(node) {
        declareSymbol(node, 16384 /* SymbolFlags.Decorator */ | 4194304 /* SymbolFlags.Declaration */, `@${node.id.sv}`);
    }
    function bindFunctionDeclarationStatement(node) {
        declareSymbol(node, 131072 /* SymbolFlags.Function */ | 4194304 /* SymbolFlags.Declaration */);
    }
    function bindFunctionParameter(node) {
        const symbol = createSymbol(node, node.id.sv, 262144 /* SymbolFlags.FunctionParameter */, scope.symbol);
        mutate(node).symbol = symbol;
    }
    /**
     * Declare a symbole for the given node in the current scope.
     * @param node Node
     * @param flags Symbol flags
     * @param name Optional symbol name, default to the node id.
     * @returns Created Symbol
     */
    function declareSymbol(node, flags, name) {
        switch (scope.kind) {
            case SyntaxKind.NamespaceStatement:
                return declareNamespaceMember(node, flags, name);
            case SyntaxKind.TypeSpecScript:
            case SyntaxKind.JsSourceFile:
                return declareScriptMember(node, flags, name);
            default:
                const key = name ?? node.id.sv;
                const symbol = createSymbol(node, key, flags, scope?.symbol);
                mutate(node).symbol = symbol;
                mutate(scope.locals).set(key, symbol);
                return symbol;
        }
    }
    function bindSymbol(node, flags) {
        const symbol = createSymbol(node, "-", flags, scope?.symbol);
        mutate(node).symbol = symbol;
        return symbol;
    }
    function declareNamespaceMember(node, flags, name) {
        if (flags & 4096 /* SymbolFlags.Namespace */ &&
            mergeNamespaceDeclarations(node, scope)) {
            return;
        }
        const key = name ?? node.id.sv;
        const symbol = createSymbol(node, key, flags, scope.symbol);
        mutate(node).symbol = symbol;
        mutate(scope.symbol.exports).set(key, symbol);
        return symbol;
    }
    function declareScriptMember(node, flags, name) {
        const effectiveScope = fileNamespace ?? scope;
        if (flags & 4096 /* SymbolFlags.Namespace */ &&
            mergeNamespaceDeclarations(node, effectiveScope)) {
            return;
        }
        const key = name ?? node.id.sv;
        const symbol = createSymbol(node, key, flags, fileNamespace?.symbol);
        mutate(node).symbol = symbol;
        mutate(effectiveScope.symbol.exports).set(key, symbol);
        return symbol;
    }
    function mergeNamespaceDeclarations(node, scope) {
        // we are declaring a namespace in either global scope, or a blockless namespace.
        const existingBinding = scope.symbol.exports.get(node.id.sv);
        if (existingBinding && existingBinding.flags & 4096 /* SymbolFlags.Namespace */) {
            // we have an existing binding, so just push this node to its declarations
            mutate(existingBinding.declarations).push(node);
            mutate(node).symbol = existingBinding;
            return true;
        }
        return false;
    }
}
function hasScope(node) {
    switch (node.kind) {
        case SyntaxKind.ModelStatement:
        case SyntaxKind.ScalarStatement:
        case SyntaxKind.ConstStatement:
        case SyntaxKind.AliasStatement:
        case SyntaxKind.TypeSpecScript:
        case SyntaxKind.InterfaceStatement:
        case SyntaxKind.OperationStatement:
        case SyntaxKind.UnionStatement:
        case SyntaxKind.Projection:
        case SyntaxKind.ProjectionLambdaExpression:
            return true;
        case SyntaxKind.NamespaceStatement:
            return node.statements !== undefined;
        default:
            return false;
    }
}
function createSymbol(node, name, flags, parent, value) {
    let exports;
    if (flags & 2101248 /* SymbolFlags.ExportContainer */) {
        exports = createSymbolTable();
    }
    let members;
    if (flags & 682 /* SymbolFlags.MemberContainer */) {
        members = createSymbolTable();
    }
    return {
        declarations: node ? [node] : [],
        name,
        exports,
        members,
        flags,
        value,
        parent,
        metatypeMembers: createSymbolTable(),
    };
}

function createChangeIdentifierCodeFix(node, newIdentifier) {
    return defineCodeFix({
        id: "change-identifier",
        label: `Change ${node.sv} to ${newIdentifier}`,
        fix: (context) => {
            const location = getSourceLocation(node);
            return context.replaceText(location, newIdentifier);
        },
    });
}

/**
 * Quick fix that convert a model expression to an object value.
 */
function createModelToObjectValueCodeFix(node) {
    return defineCodeFix({
        id: "model-to-object-value",
        label: `Convert to an object value \`#{}\``,
        fix: (context) => {
            const location = getSourceLocation(node);
            return context.prependText(location, "#");
        },
    });
}

/**
 * Quick fix that convert a tuple to an array value.
 */
function createTupleToArrayValueCodeFix(node) {
    return defineCodeFix({
        id: "tuple-to-array-value",
        label: `Convert to an array value \`#[]\``,
        fix: (context) => {
            const location = getSourceLocation(node);
            return context.prependText(location, "#");
        },
    });
}

function createStateSymbol(name) {
    return Symbol.for(`TypeSpec.${name}`);
}
const deprecatedKey = createStateSymbol("deprecated");
/**
 * Check if the given type is deprecated
 * @param program Program
 * @param type Type
 */
function isDeprecated(program, type) {
    return program.stateMap(deprecatedKey).has(type);
}
/**
 * Returns complete deprecation details for the given type or node
 * @param program Program
 * @param typeOrNode A Type or Node to check for deprecation
 */
function getDeprecationDetails(program, typeOrNode) {
    function isType(maybeType) {
        return typeof maybeType.kind === "string";
    }
    // If we're looking at a type, pull the deprecation details from the state map
    if (isType(typeOrNode)) {
        return program.stateMap(deprecatedKey).get(typeOrNode);
    }
    else {
        // Look at the node for a deprecation directive
        const deprecatedDirective = (typeOrNode.directives ?? []).find((directive) => directive.target.sv === "deprecated");
        if (deprecatedDirective?.arguments[0].kind === SyntaxKind.StringLiteral) {
            return {
                message: deprecatedDirective.arguments[0].value,
            };
        }
    }
    return undefined;
}
/**
 * Mark the given type as deprecated with the provided details.
 * @param program Program
 * @param type Type
 * @param details Details of the deprecation
 */
function markDeprecated(program, type, details) {
    program.stateMap(deprecatedKey).set(type, details);
}

function isErrorType(type) {
    return "kind" in type && type.kind === "Intrinsic" && type.name === "ErrorType";
}
function isVoidType(type) {
    return "kind" in type && type.kind === "Intrinsic" && type.name === "void";
}
function isNeverType(type) {
    return "kind" in type && type.kind === "Intrinsic" && type.name === "never";
}
function isUnknownType(type) {
    return "kind" in type && type.kind === "Intrinsic" && type.name === "unknown";
}
function isNullType(type) {
    return "kind" in type && type.kind === "Intrinsic" && type.name === "null";
}
function isType(entity) {
    return entity.entityKind === "Type";
}
function isValue(entity) {
    return entity.entityKind === "Value";
}
/**
 * @param type Model type
 */
function isArrayModelType(program, type) {
    return Boolean(type.indexer && type.indexer.key.name === "integer");
}
/**
 * Check if a model is an array type.
 * @param type Model type
 */
function isRecordModelType(program, type) {
    return Boolean(type.indexer && type.indexer.key.name === "string");
}
/**
 * Lookup and find the node
 * @param node Node
 * @returns Template Parent node if applicable
 */
function getParentTemplateNode(node) {
    switch (node.kind) {
        case SyntaxKind.ModelStatement:
        case SyntaxKind.ScalarStatement:
        case SyntaxKind.OperationStatement:
        case SyntaxKind.UnionStatement:
        case SyntaxKind.InterfaceStatement:
            return node.templateParameters.length > 0 ? node : undefined;
        case SyntaxKind.OperationSignatureDeclaration:
        case SyntaxKind.ModelProperty:
        case SyntaxKind.ModelExpression:
            return node.parent ? getParentTemplateNode(node.parent) : undefined;
        default:
            return undefined;
    }
}
/**
 * Check the given type is a finished template instance.
 */
function isTemplateInstance(type) {
    const maybeTemplateType = type;
    return (maybeTemplateType.templateMapper !== undefined &&
        !maybeTemplateType.templateMapper.partial &&
        maybeTemplateType.isFinished);
}
/**
 * Check if the type is a declared type. This include:
 * - non templated type
 * - template declaration
 */
function isDeclaredType(type) {
    if (type.node === undefined) {
        return false;
    }
    const node = type.node;
    return (node.templateParameters === undefined || type.templateMapper === undefined);
}
/**
 * Resolve if the type is a template type declaration(Non initialized template type).
 */
function isTemplateDeclaration(type) {
    if (type.node === undefined) {
        return false;
    }
    const node = type.node;
    return (node.templateParameters &&
        node.templateParameters.length > 0 &&
        type.templateMapper === undefined);
}
/**
 * Resolve if the type was created from a template type or is a template type declaration.
 */
function isTemplateDeclarationOrInstance(type) {
    if (type.node === undefined) {
        return false;
    }
    const node = type.node;
    return node.templateParameters && node.templateParameters.length > 0;
}
/**
 * Check if the given namespace is the global namespace
 * @param program Program
 * @param namespace Namespace
 * @returns {boolean}
 */
function isGlobalNamespace(program, namespace) {
    return program.getGlobalNamespaceType() === namespace;
}
/**
 * Check if the given type is declared in the specified namespace or, optionally, its child namespaces.
 * @param type Type
 * @param namespace Namespace
 * @returns {boolean}
 */
function isDeclaredInNamespace(type, namespace, options = { recursive: true }) {
    let candidateNs = type.namespace;
    while (candidateNs) {
        if (candidateNs === namespace) {
            return true;
        }
        // Operations can be defined inside of an interface that is defined in the
        // desired namespace
        if (type.kind === "Operation" && type.interface && type.interface.namespace === namespace) {
            return true;
        }
        // If we are allowed to check recursively, walk up the namespace hierarchy
        candidateNs = options.recursive ? candidateNs.namespace : undefined;
    }
    return false;
}
function getFullyQualifiedSymbolName(sym, options) {
    if (!sym)
        return "";
    if (sym.symbolSource)
        sym = sym.symbolSource;
    const parent = sym.parent && !(sym.parent.flags & 2097152 /* SymbolFlags.SourceFile */) ? sym.parent : undefined;
    const name = sym.flags & 16384 /* SymbolFlags.Decorator */ ? sym.name.slice(1) : sym.name;
    if (parent?.name) {
        return `${getFullyQualifiedSymbolName(parent)}.${name}`;
    }
    else if (options?.useGlobalPrefixAtTopLevel) {
        return `global.${name}`;
    }
    else {
        return name;
    }
}

function getDiscriminatedUnion(type, discriminator) {
    switch (type.kind) {
        case "Model":
            return getDiscriminatedUnionForModel(type, discriminator);
        case "Union":
            return getDiscriminatedUnionForUnion(type, discriminator);
    }
}
/**
 * Run the validation on all discriminated models to make sure the discriminator are valid.
 * This has to be done after the checker so we can have the full picture of all the dervied models.
 */
function validateInheritanceDiscriminatedUnions(program) {
    for (const [type, discriminator] of getDiscriminatedTypes(program)) {
        // Union would have already reported the issue.
        if (type.kind === "Model") {
            const [_, diagnostics] = getDiscriminatedUnionForModel(type, discriminator);
            program.reportDiagnostics(diagnostics);
        }
    }
}
function getDiscriminatedUnionForUnion(type, discriminator) {
    const variants = new Map();
    const diagnostics = [];
    const duplicates = new DuplicateTracker();
    for (const variant of type.variants.values()) {
        if (variant.type.kind !== "Model") {
            diagnostics.push(createDiagnostic({
                code: "invalid-discriminated-union-variant",
                format: { name: variant.name.toString() },
                target: variant,
            }));
            continue;
        }
        const prop = getDiscriminatorProperty(variant.type, discriminator, diagnostics);
        if (prop === undefined) {
            diagnostics.push(createDiagnostic({
                code: "invalid-discriminated-union-variant",
                messageId: "noDiscriminant",
                format: { name: variant.name.toString(), discriminant: discriminator.propertyName },
                target: variant,
            }));
            continue;
        }
        const key = getStringValue(prop.type);
        if (key) {
            duplicates.track(key, variant.type);
            variants.set(key, variant.type);
        }
        else {
            diagnostics.push(createDiagnostic({
                code: "invalid-discriminated-union-variant",
                messageId: "wrongDiscriminantType",
                format: { name: variant.name.toString(), discriminant: discriminator.propertyName },
                target: variant.type,
            }));
        }
    }
    reportDuplicateDiscriminatorValues(duplicates, diagnostics);
    const discriminatedUnion = {
        propertyName: discriminator.propertyName,
        variants,
    };
    return [discriminatedUnion, diagnostics];
}
function getDiscriminatedUnionForModel(type, discriminator) {
    const variants = new Map();
    const diagnostics = [];
    const duplicates = new DuplicateTracker();
    function checkForVariantsIn(current) {
        for (const derivedModel of current.derivedModels) {
            if (isTemplateDeclarationOrInstance(derivedModel)) {
                continue; // Skip template instances as they should be used with `model is`
            }
            const keys = getDiscriminatorValues(derivedModel, discriminator, diagnostics);
            if (keys === undefined) {
                if (derivedModel.derivedModels.length === 0) {
                    diagnostics.push(createDiagnostic({
                        code: "missing-discriminator-property",
                        format: { discriminator: discriminator.propertyName },
                        target: derivedModel,
                    }));
                }
                else {
                    checkForVariantsIn(derivedModel);
                }
            }
            else {
                for (const key of keys) {
                    duplicates.track(key, derivedModel);
                    variants.set(key, derivedModel);
                }
            }
        }
    }
    checkForVariantsIn(type);
    reportDuplicateDiscriminatorValues(duplicates, diagnostics);
    const discriminatedUnion = {
        propertyName: discriminator.propertyName,
        variants,
    };
    return [discriminatedUnion, diagnostics];
}
function reportDuplicateDiscriminatorValues(duplicates, diagnostics) {
    for (const [duplicateKey, models] of duplicates.entries()) {
        for (const model of models) {
            diagnostics.push(createDiagnostic({
                code: "invalid-discriminator-value",
                messageId: "duplicate",
                format: { discriminator: duplicateKey },
                target: model,
            }));
        }
    }
}
function getDiscriminatorProperty(model, discriminator, diagnostics) {
    const prop = model.properties.get(discriminator.propertyName);
    if (prop && prop.optional) {
        diagnostics.push(createDiagnostic({
            code: "invalid-discriminator-value",
            messageId: "required",
            target: prop,
        }));
    }
    return prop;
}
function getDiscriminatorValues(model, discriminator, diagnostics) {
    const prop = getDiscriminatorProperty(model, discriminator, diagnostics);
    if (!prop)
        return undefined;
    const keys = getStringValues(prop.type);
    if (keys.length === 0) {
        diagnostics.push(createDiagnostic({
            code: "invalid-discriminator-value",
            format: { kind: prop.type.kind },
            target: prop,
        }));
    }
    return keys;
}
function getStringValues(type) {
    switch (type.kind) {
        case "String":
            return [type.value];
        case "Union":
            return [...type.variants.values()].flatMap((x) => getStringValues(x.type)).filter(isDefined);
        case "EnumMember":
            return typeof type.value !== "number" ? [type.value ?? type.name] : [];
        case "UnionVariant":
            return getStringValues(type.type);
        default:
            return [];
    }
}
function getStringValue(type) {
    switch (type.kind) {
        case "String":
            return type.value;
        case "EnumMember":
            return typeof type.value !== "number" ? type.value ?? type.name : undefined;
        default:
            return undefined;
    }
}

/**
 * @deprecated use `{@link StringTemplate["stringValue"]} property on {@link StringTemplate} instead.
 */
function stringTemplateToString(stringTemplate) {
    if (stringTemplate.stringValue !== undefined) {
        return [stringTemplate.stringValue, []];
    }
    else {
        return ["", explainStringTemplateNotSerializable(stringTemplate)];
    }
}
function isStringTemplateSerializable(stringTemplate) {
    if (stringTemplate.stringValue !== undefined) {
        return [true, []];
    }
    else {
        return [false, explainStringTemplateNotSerializable(stringTemplate)];
    }
}
/**
 * get a list of diagnostic explaining why this string template cannot be converted to a string.
 */
function explainStringTemplateNotSerializable(stringTemplate) {
    const diagnostics = createDiagnosticCollector();
    for (const span of stringTemplate.spans) {
        if (span.isInterpolated) {
            switch (span.type.kind) {
                case "String":
                case "Number":
                case "Boolean":
                    break;
                case "StringTemplate":
                    diagnostics.pipe(isStringTemplateSerializable(span.type));
                    break;
                case "TemplateParameter":
                    if (span.type.constraint && span.type.constraint.valueType !== undefined) {
                        break; // Value types will be serializable in the template instance.
                    }
                // eslint-disable-next-line no-fallthrough
                default:
                    diagnostics.add(createDiagnostic({
                        code: "non-literal-string-template",
                        target: span.node,
                    }));
            }
        }
    }
    return diagnostics.diagnostics;
}

/**
 * Print a string as a TypeSpec identifier. If the string is a valid identifier, return it as is otherwise wrap it into backticks.
 * @param sv Identifier string value.
 * @returns Identifier string as it would be represented in a TypeSpec file.
 *
 * @example
 * ```ts
 * printIdentifier("foo") // foo
 * printIdentifier("foo bar") // `foo bar`
 * ```
 */
function printIdentifier$1(sv) {
    if (needBacktick(sv)) {
        const escapedString = sv
            .replace(/\\/g, "\\\\")
            .replace(/\n/g, "\\n")
            .replace(/\r/g, "\\r")
            .replace(/\t/g, "\\t")
            .replace(/`/g, "\\`");
        return `\`${escapedString}\``;
    }
    else {
        return sv;
    }
}
function needBacktick(sv) {
    if (sv.length === 0) {
        return false;
    }
    if (Keywords.has(sv)) {
        return true;
    }
    let cp = sv.codePointAt(0);
    if (!isIdentifierStart(cp)) {
        return true;
    }
    let pos = 0;
    do {
        pos += utf16CodeUnits(cp);
    } while (pos < sv.length && isIdentifierContinue((cp = sv.codePointAt(pos))));
    return pos < sv.length;
}

function getTypeName(type, options) {
    switch (type.kind) {
        case "Namespace":
            return getNamespaceFullName(type, options);
        case "TemplateParameter":
            return getIdentifierName(type.node.id.sv, options);
        case "Scalar":
            return getScalarName(type, options);
        case "Model":
            return getModelName(type, options);
        case "ModelProperty":
            return getModelPropertyName(type, options);
        case "Interface":
            return getInterfaceName(type, options);
        case "Operation":
            return getOperationName(type, options);
        case "Enum":
            return getEnumName(type, options);
        case "EnumMember":
            return `${getEnumName(type.enum, options)}.${getIdentifierName(type.name, options)}`;
        case "Union":
            return getUnionName(type, options);
        case "UnionVariant":
            return getTypeName(type.type, options);
        case "Tuple":
            return "[" + type.values.map((x) => getTypeName(x, options)).join(", ") + "]";
        case "StringTemplate":
            return getStringTemplateName(type);
        case "String":
            return `"${type.value}"`;
        case "Number":
            return type.valueAsString;
        case "Boolean":
            return type.value.toString();
        case "Intrinsic":
            return type.name;
        default:
            return `(unnamed type)`;
    }
}
function getValuePreview(value, options) {
    switch (value.valueKind) {
        case "ObjectValue":
            return `#{${[...value.properties.entries()].map(([name, value]) => `${name}: ${getValuePreview(value.value, options)}`).join(", ")}}`;
        case "ArrayValue":
            return `#[${value.values.map((x) => getValuePreview(x, options)).join(", ")}]`;
        case "StringValue":
            return `"${value.value}"`;
        case "BooleanValue":
            return `${value.value}`;
        case "NumericValue":
            return `${value.value.toString()}`;
        case "EnumValue":
            return getTypeName(value.value);
        case "NullValue":
            return "null";
        case "ScalarValue":
            return `${getTypeName(value.type, options)}.${value.value.name}(${value.value.args.map((x) => getValuePreview(x, options)).join(", ")}})`;
    }
}
function getEntityName(entity, options) {
    if (isValue(entity)) {
        return getValuePreview(entity, options);
    }
    else if (isType(entity)) {
        return getTypeName(entity, options);
    }
    else {
        switch (entity.entityKind) {
            case "MixedParameterConstraint":
                return [
                    entity.type && getEntityName(entity.type),
                    entity.valueType && `valueof ${getEntityName(entity.valueType)}`,
                ]
                    .filter(isDefined)
                    .join(" | ");
            case "Indeterminate":
                return getTypeName(entity.type, options);
        }
    }
}
function isStdNamespace(namespace) {
    return ((namespace.name === "TypeSpec" && namespace.namespace?.name === "") ||
        (namespace.name === "Reflection" &&
            namespace.namespace?.name === "TypeSpec" &&
            namespace.namespace?.namespace?.name === ""));
}
/**
 * Return the full name of the namespace(e.g. "Foo.Bar")
 * @param type namespace type
 * @param options
 * @returns
 */
function getNamespaceFullName(type, options) {
    const filter = options?.namespaceFilter;
    const segments = [];
    let current = type;
    while (current && current.name !== "") {
        if (filter && !filter(current)) {
            break;
        }
        segments.unshift(getIdentifierName(current.name, options));
        current = current.namespace;
    }
    return segments.join(".");
}
function getNamespacePrefix(type, options) {
    if (type === undefined || isStdNamespace(type)) {
        return "";
    }
    const namespaceFullName = getNamespaceFullName(type, options);
    return namespaceFullName !== "" ? namespaceFullName + "." : "";
}
function getEnumName(e, options) {
    return `${getNamespacePrefix(e.namespace, options)}${getIdentifierName(e.name, options)}`;
}
function getScalarName(scalar, options) {
    return `${getNamespacePrefix(scalar.namespace, options)}${getIdentifierName(scalar.name, options)}`;
}
function getModelName(model, options) {
    const nsPrefix = getNamespacePrefix(model.namespace, options);
    if (model.name === "" && model.properties.size === 0) {
        return "{}";
    }
    if (model.indexer && model.indexer.key.kind === "Scalar") {
        if (model.name === "Array" && isInTypeSpecNamespace(model)) {
            return `${getTypeName(model.indexer.value, options)}[]`;
        }
    }
    if (model.name === "") {
        return (nsPrefix +
            `{ ${[...model.properties.values()].map((prop) => `${prop.name}: ${getTypeName(prop.type, options)}`).join(", ")} }`);
    }
    const modelName = nsPrefix + getIdentifierName(model.name, options);
    if (isTemplateInstance(model)) {
        // template instantiation
        const args = model.templateMapper.args.map((x) => getEntityName(x, options));
        return `${modelName}<${args.join(", ")}>`;
    }
    else if (model.node?.templateParameters?.length > 0) {
        // template
        const params = model.node.templateParameters.map((t) => getIdentifierName(t.id.sv, options));
        return `${modelName}<${params.join(", ")}>`;
    }
    else {
        // regular old model.
        return modelName;
    }
}
function getUnionName(type, options) {
    const nsPrefix = getNamespacePrefix(type.namespace, options);
    const typeName = type.name
        ? getIdentifierName(type.name, options)
        : [...type.variants.values()].map((x) => getTypeName(x.type, options)).join(" | ");
    return nsPrefix + typeName;
}
/**
 * Check if the given namespace is the standard library `TypeSpec` namespace.
 */
function isTypeSpecNamespace(namespace) {
    return namespace.name === "TypeSpec" && namespace.namespace?.name === "";
}
/**
 * Check if the given type is defined right in the TypeSpec namespace.
 */
function isInTypeSpecNamespace(type) {
    return Boolean(type.namespace && isTypeSpecNamespace(type.namespace));
}
function getModelPropertyName(prop, options) {
    const modelName = prop.model ? getModelName(prop.model, options) : undefined;
    return `${modelName ?? "(anonymous model)"}.${prop.name}`;
}
function getInterfaceName(iface, options) {
    let interfaceName = getIdentifierName(iface.name, options);
    if (isTemplateInstance(iface)) {
        interfaceName += `<${iface.templateMapper.args
            .map((x) => getEntityName(x, options))
            .join(", ")}>`;
    }
    return `${getNamespacePrefix(iface.namespace, options)}${interfaceName}`;
}
function getOperationName(op, options) {
    let opName = getIdentifierName(op.name, options);
    if (op.node.templateParameters.length > 0) {
        // template
        const params = op.node.templateParameters.map((t) => getIdentifierName(t.id.sv, options));
        opName += `<${params.join(", ")}>`;
    }
    const prefix = op.interface
        ? getInterfaceName(op.interface, options) + "."
        : getNamespacePrefix(op.namespace, options);
    return `${prefix}${opName}`;
}
function getIdentifierName(name, options) {
    return options?.printable ? printIdentifier$1(name) : name;
}
function getStringTemplateName(type) {
    if (type.stringValue) {
        return `"${type.stringValue}"`;
    }
    return "string";
}

class InvalidNumericError extends Error {
    code = "InvalidNumeric";
}
/** @internal */
const InternalDataSym = Symbol.for("NumericInternalData");
/**
 * Check if the given arg is a Numeric
 */
function isNumeric(arg) {
    return typeof arg === "object" && arg !== null && InternalDataSym in arg;
}
/**
 * Represent any possible numeric value
 */
function Numeric(stringValue) {
    if (new.target) {
        throw new Error("Numeric is not a constructor");
    }
    const data = parse(stringValue);
    const isInteger = data.d === 0;
    const obj = {
        [InternalDataSym]: data,
        isInteger,
    };
    // We are explicitly not using a class here due to version mismatch between the compiler and the runtime that could happen and break instanceof checks.
    const numeric = setTypedProptotype(obj, NumericPrototype);
    return Object.freeze(numeric);
}
function setTypedProptotype(obj, prototype) {
    Object.setPrototypeOf(obj, prototype);
    return obj;
}
function parse(original) {
    let stringValue = original;
    let start = 0;
    let sign = 1;
    let n;
    let exp;
    let decimal;
    if (stringValue[0] === "-") {
        start = 1;
        sign = -1;
    }
    const second = stringValue[start + 1]?.toLowerCase();
    if (stringValue[start] === "0" && (second === "b" || second === "x" || second === "o")) {
        try {
            n = BigInt(stringValue.slice(start));
            exp = n.toString().length;
            decimal = 0;
        }
        catch {
            throw new InvalidNumericError(`Invalid numeric value: ${original}`);
        }
    }
    else {
        // Skip leading 0.
        while (stringValue[start] === "0") {
            start++;
        }
        const decimalPointIndex = stringValue.indexOf(".");
        const adjustedPointIndex = decimalPointIndex - start;
        // Decimal point?
        if (decimalPointIndex !== -1) {
            exp = adjustedPointIndex;
            stringValue = stringValue.replace(".", "");
        }
        let i;
        if ((i = stringValue.search(/e/i)) > 0) {
            // Determine exponent.
            if (exp === undefined) {
                exp = i - start;
            }
            exp += Number(stringValue.slice(i + 1));
            stringValue = stringValue.slice(start, i);
        }
        else if (exp === undefined) {
            // Integer.
            exp = stringValue.length - start;
            stringValue = stringValue.slice(start);
        }
        else {
            stringValue = stringValue.slice(start);
        }
        let end = stringValue.length;
        while (stringValue[end - 1] === "0" && end > adjustedPointIndex) {
            end--;
        }
        try {
            stringValue = stringValue.slice(0, end);
            stringValue = stringValue + "0".repeat(Math.max(exp - stringValue.length, 0)); // add remaining zeros for cases like 3e30
            n = BigInt(stringValue);
            decimal = n === 0n ? 0 : Math.max(stringValue.length - exp, 0);
        }
        catch {
            throw new InvalidNumericError(`Invalid numeric value: ${original}`);
        }
    }
    return { n, e: exp, s: sign, d: decimal };
}
function stringify(value) {
    const n = value.n.toString();
    const sign = value.s === -1 ? "-" : "";
    const decimal = value.e < n.length ? "." + n.slice(value.e) : "";
    return sign + n.slice(0, value.e) + decimal;
}
const equals = (a, b) => a.n === b.n && a.e === b.e;
const compare = (a, b) => {
    if (a.s < b.s) {
        return -1;
    }
    else if (a.s > b.s) {
        return 1;
    }
    const neg = a.s;
    if (a.e < b.e) {
        return (-1 * neg);
    }
    else if (a.e > b.e) {
        return (1 * neg);
    }
    let aN = a.n;
    let bN = b.n;
    if (a.d < b.d) {
        aN *= 10n ** BigInt(b.d - a.d);
    }
    else {
        bN *= 10n ** BigInt(a.d - b.d);
    }
    if (aN < bN)
        return (-1 * neg);
    if (aN > bN)
        return (1 * neg);
    return 0;
};
const NumericPrototype = {
    toString: function () {
        return stringify(this[InternalDataSym]);
    },
    asNumber: function () {
        const num = Number(stringify(this[InternalDataSym]));
        return equals(this[InternalDataSym], Numeric(num.toString())[InternalDataSym]) ? num : null;
    },
    asBigInt: function () {
        return this.isInteger ? this[InternalDataSym].n : null;
    },
    equals: function (other) {
        return equals(this[InternalDataSym], other[InternalDataSym]);
    },
    lt: function (other) {
        return compare(this[InternalDataSym], other[InternalDataSym]) === -1;
    },
    lte: function (other) {
        return compare(this[InternalDataSym], other[InternalDataSym]) <= 0;
    },
    gt: function (other) {
        return compare(this[InternalDataSym], other[InternalDataSym]) === 1;
    },
    gte: function (other) {
        return compare(this[InternalDataSym], other[InternalDataSym]) >= 0;
    },
};
NumericPrototype.toString = function () {
    return stringify(this[InternalDataSym]);
};

/**
 * Set of known numeric ranges
 */
const numericRanges = {
    int64: [
        Numeric("-9223372036854775808"),
        Numeric("9223372036854775807"),
        { int: true, isJsNumber: false },
    ],
    int32: [Numeric("-2147483648"), Numeric("2147483647"), { int: true, isJsNumber: true }],
    int16: [Numeric("-32768"), Numeric("32767"), { int: true, isJsNumber: true }],
    int8: [Numeric("-128"), Numeric("127"), { int: true, isJsNumber: true }],
    uint64: [Numeric("0"), Numeric("18446744073709551615"), { int: true, isJsNumber: false }],
    uint32: [Numeric("0"), Numeric("4294967295"), { int: true, isJsNumber: true }],
    uint16: [Numeric("0"), Numeric("65535"), { int: true, isJsNumber: true }],
    uint8: [Numeric("0"), Numeric("255"), { int: true, isJsNumber: true }],
    safeint: [
        Numeric(Number.MIN_SAFE_INTEGER.toString()),
        Numeric(Number.MAX_SAFE_INTEGER.toString()),
        { int: true, isJsNumber: true },
    ],
    float32: [Numeric("-3.4e38"), Numeric("3.4e38"), { int: false, isJsNumber: true }],
    float64: [
        Numeric(`${-Number.MAX_VALUE}`),
        Numeric(Number.MAX_VALUE.toString()),
        { int: false, isJsNumber: true },
    ],
};

/**
 * Legacy marshalling of values to replicate before 0.56.0 behavior
 *  - string value -> `string`
 *  - numeric value -> `number`
 *  - boolean value -> `boolean`
 *  - null value -> `NullType`
 */
function legacyMarshallTypeForJS(checker, value) {
    switch (value.valueKind) {
        case "BooleanValue":
        case "StringValue":
            return value.value;
        case "NumericValue":
            return Number(value.value.toString());
        case "ObjectValue":
            return objectValueToJs(value);
        case "ArrayValue":
            return arrayValueToJs(value);
        case "EnumValue":
            return value.value;
        case "NullValue":
            return checker.nullType;
        case "ScalarValue":
            return value;
    }
}
function marshallTypeForJS(value, valueConstraint) {
    switch (value.valueKind) {
        case "BooleanValue":
        case "StringValue":
            return value.value;
        case "NumericValue":
            return numericValueToJs(value, valueConstraint);
        case "ObjectValue":
            return objectValueToJs(value);
        case "ArrayValue":
            return arrayValueToJs(value);
        case "EnumValue":
            return value;
        case "NullValue":
            return null;
        case "ScalarValue":
            return value;
    }
}
function canNumericConstraintBeJsNumber(type) {
    if (type === undefined)
        return true;
    switch (type.kind) {
        case "Scalar":
            return numericRanges[type.name]?.[2].isJsNumber;
        case "Union":
            return [...type.variants.values()].every((x) => canNumericConstraintBeJsNumber(x.type));
        default:
            return true;
    }
}
function numericValueToJs(type, valueConstraint) {
    const canBeANumber = canNumericConstraintBeJsNumber(valueConstraint);
    if (canBeANumber) {
        const asNumber = type.value.asNumber();
        compilerAssert(asNumber !== null, `Numeric value '${type.value.toString()}' is not a able to convert to a number without loosing precision.`);
        return asNumber;
    }
    return type.value;
}
function objectValueToJs(type) {
    const result = {};
    for (const [key, value] of type.properties) {
        result[key] = marshallTypeForJS(value.value, undefined);
    }
    return result;
}
function arrayValueToJs(type) {
    return type.values.map((x) => marshallTypeForJS(x, undefined));
}

// Regexps involved with splitting words in various case formats.
const SPLIT_LOWER_UPPER_RE = /([\p{Ll}\d])(\p{Lu})/gu;
const SPLIT_UPPER_UPPER_RE = /(\p{Lu})([\p{Lu}][\p{Ll}])/gu;
// Used to iterate over the initial split result and separate numbers.
const SPLIT_SEPARATE_NUMBER_RE = /(\d)\p{Ll}|(\p{L})\d/u;
// Regexp involved with stripping non-word characters from the result.
const DEFAULT_STRIP_REGEXP = /[^\p{L}\d]+/giu;
// The replacement value for splits.
const SPLIT_REPLACE_VALUE = "$1\0$2";
// The default characters to keep after transforming case.
const DEFAULT_PREFIX_SUFFIX_CHARACTERS = "";
/**
 * Split any cased input strings into an array of words.
 */
function split(value) {
    let result = value.trim();
    result = result
        .replace(SPLIT_LOWER_UPPER_RE, SPLIT_REPLACE_VALUE)
        .replace(SPLIT_UPPER_UPPER_RE, SPLIT_REPLACE_VALUE);
    result = result.replace(DEFAULT_STRIP_REGEXP, "\0");
    let start = 0;
    let end = result.length;
    // Trim the delimiter from around the output string.
    while (result.charAt(start) === "\0")
        start++;
    if (start === end)
        return [];
    while (result.charAt(end - 1) === "\0")
        end--;
    return result.slice(start, end).split(/\0/g);
}
/**
 * Split the input string into an array of words, separating numbers.
 */
function splitSeparateNumbers(value) {
    const words = split(value);
    for (let i = 0; i < words.length; i++) {
        const word = words[i];
        const match = SPLIT_SEPARATE_NUMBER_RE.exec(word);
        if (match) {
            const offset = match.index + (match[1] ?? match[2]).length;
            words.splice(i, 1, word.slice(0, offset), word.slice(offset));
        }
    }
    return words;
}
/**
 * Convert a string to space separated lower case (`foo bar`).
 */
function noCase(input, options) {
    const [prefix, words, suffix] = splitPrefixSuffix(input, options);
    return (prefix +
        words.map(lowerFactory(options?.locale)).join(options?.delimiter ?? " ") +
        suffix);
}
/**
 * Convert a string to camel case (`fooBar`).
 */
function camelCase(input, options) {
    const [prefix, words, suffix] = splitPrefixSuffix(input, options);
    const lower = lowerFactory(options?.locale);
    const upper = upperFactory(options?.locale);
    const transform = pascalCaseTransformFactory(lower, upper);
    return (prefix +
        words
            .map((word, index) => {
            if (index === 0)
                return lower(word);
            return transform(word, index);
        })
            .join("") +
        suffix);
}
/**
 * Convert a string to pascal case (`FooBar`).
 */
function pascalCase(input, options) {
    const [prefix, words, suffix] = splitPrefixSuffix(input, options);
    const lower = lowerFactory(options?.locale);
    const upper = upperFactory(options?.locale);
    const transform = pascalCaseTransformFactory(lower, upper);
    return prefix + words.map(transform).join("") + suffix;
}
/**
 * Convert a string to kebab case (`foo-bar`).
 */
function kebabCase(input, options) {
    return noCase(input, { delimiter: "-", ...options });
}
/**
 * Convert a string to snake case (`foo_bar`).
 */
function snakeCase(input, options) {
    return noCase(input, { delimiter: "_", ...options });
}
function lowerFactory(locale) {
    return locale === false
        ? (input) => input.toLowerCase()
        : (input) => input.toLocaleLowerCase(locale);
}
function upperFactory(locale) {
    return (input) => input.toLocaleUpperCase(locale);
}
function pascalCaseTransformFactory(lower, upper) {
    return (word, index) => {
        const char0 = word[0];
        const initial = index > 0 && char0 >= "0" && char0 <= "9" ? "_" + char0 : upper(char0);
        return initial + lower(word.slice(1));
    };
}
function splitPrefixSuffix(input, options = {}) {
    const splitFn = options.split ?? (options.separateNumbers ? splitSeparateNumbers : split);
    const prefixCharacters = options.prefixCharacters ?? DEFAULT_PREFIX_SUFFIX_CHARACTERS;
    const suffixCharacters = options.suffixCharacters ?? DEFAULT_PREFIX_SUFFIX_CHARACTERS;
    let prefixIndex = 0;
    let suffixIndex = input.length;
    while (prefixIndex < input.length) {
        const char = input.charAt(prefixIndex);
        if (!prefixCharacters.includes(char))
            break;
        prefixIndex++;
    }
    while (suffixIndex > prefixIndex) {
        const index = suffixIndex - 1;
        const char = input.charAt(index);
        if (!suffixCharacters.includes(char))
            break;
        suffixIndex = index;
    }
    return [
        input.slice(0, prefixIndex),
        splitFn(input.slice(prefixIndex, suffixIndex)),
        input.slice(suffixIndex),
    ];
}

function createProjectionMembers(checker) {
    const { voidType, neverType, createType, createFunctionType, createLiteralType } = checker;
    function createBaseMembers() {
        return {
            projectionSource: (base) => base.projectionSource ?? voidType,
            projectionBase: (base) => base.projectionBase ?? voidType,
        };
    }
    function createNameableMembers() {
        return {
            name: (base) => (base.name ? createLiteralType(base.name) : voidType),
            rename: (base) => {
                return createFunctionType((newName) => {
                    assertType("new name", newName, "String");
                    base.name = newName.value;
                    return voidType;
                });
            },
        };
    }
    return {
        Model: {
            ...createBaseMembers(),
            ...createNameableMembers(),
            properties(base) {
                return createType({
                    kind: "Object",
                    properties: {
                        forEach: createFunctionType((block) => {
                            assertType("block", block, "Function");
                            const props = Array.from(base.properties.values());
                            props.forEach((p) => block.implementation(p));
                            return voidType;
                        }),
                    },
                });
            },
            renameProperty(base) {
                return createFunctionType((oldNameT, newNameT) => {
                    assertType("current property name", oldNameT, "String");
                    assertType("new property name", newNameT, "String");
                    const oldName = oldNameT.value;
                    const newName = newNameT.value;
                    const prop = base.properties.get(oldName);
                    if (!prop) {
                        throw new ProjectionError(`Property ${oldName} not found`);
                    }
                    prop.name = newName;
                    base.properties.rekey(oldName, newName);
                    return voidType;
                });
            },
            changePropertyType(base) {
                return createFunctionType((nameT, newType) => {
                    assertType("property name", nameT, "String");
                    const propertyName = nameT.value;
                    const prop = base.properties.get(propertyName);
                    if (!prop) {
                        throw new ProjectionError(`Property ${propertyName} not found`);
                    }
                    prop.type = newType;
                    return voidType;
                });
            },
            addProperty(base) {
                return createFunctionType((nameT, type, defaultT) => {
                    assertType("property", nameT, "String");
                    const name = nameT.value;
                    const prop = base.properties.get(name);
                    if (prop) {
                        throw new ProjectionError(`Property ${name} already exists`);
                    }
                    base.properties.set(name, createType({
                        kind: "ModelProperty",
                        name,
                        optional: false,
                        decorators: [],
                        node: undefined,
                        default: defaultT,
                        type,
                    }));
                    return voidType;
                });
            },
            deleteProperty(base) {
                return createFunctionType((nameT) => {
                    assertType("property", nameT, "String");
                    const name = nameT.value;
                    const prop = base.properties.get(name);
                    if (!prop) {
                        return voidType;
                    }
                    base.properties.delete(name);
                    return voidType;
                });
            },
        },
        ModelProperty: {
            ...createBaseMembers(),
            name(base) {
                return createLiteralType(base.name);
            },
            type(base) {
                return base.type;
            },
            setType(base) {
                return createFunctionType((t) => {
                    base.type = t;
                    return voidType;
                });
            },
            setOptional(base) {
                return createFunctionType((optional) => {
                    assertType("Optional", optional, "Boolean");
                    base.optional = optional.value;
                    return voidType;
                });
            },
        },
        Scalar: {
            ...createBaseMembers(),
            ...createNameableMembers(),
        },
        Union: {
            ...createBaseMembers(),
            ...createNameableMembers(),
            variants(base) {
                return createType({
                    kind: "Object",
                    properties: {
                        forEach: createFunctionType((block) => {
                            assertType("block", block, "Function");
                            const variants = Array.from(base.variants.values());
                            variants.forEach((p) => block.implementation(p));
                            return voidType;
                        }),
                    },
                });
            },
            renameVariant(base) {
                return createFunctionType((oldNameT, newNameT) => {
                    assertType("old variant name", oldNameT, "String");
                    assertType("new variant name", newNameT, "String");
                    const oldName = oldNameT.value;
                    const newName = newNameT.value;
                    const variant = base.variants.get(oldName);
                    if (!variant) {
                        throw new ProjectionError(`Couldn't find variant ${variant}`);
                    }
                    base.variants.rekey(oldName, newName);
                    variant.name = newName;
                    return voidType;
                });
            },
            addVariant(base) {
                return createFunctionType((nameT, type) => {
                    assertType("Variant name", nameT, "String");
                    const name = nameT.value;
                    const variantType = createType({
                        kind: "UnionVariant",
                        decorators: [],
                        name,
                        node: undefined,
                        type,
                        union: base,
                    });
                    base.variants.set(name, variantType);
                    return voidType;
                });
            },
            deleteVariant(base) {
                return createFunctionType((nameT) => {
                    assertType("Name", nameT, "String");
                    const name = nameT.value;
                    base.variants.delete(name);
                    return voidType;
                });
            },
        },
        UnionVariant: {
            ...createBaseMembers(),
            name(base) {
                if (typeof base.name === "string") {
                    return createLiteralType(base.name);
                }
                else {
                    throw new ProjectionError("Can't refer to name of anonymous union variant");
                }
            },
            setType(base) {
                return createFunctionType((type) => {
                    base.type = type;
                    return voidType;
                });
            },
            type(base) {
                return base.type;
            },
        },
        Operation: {
            ...createBaseMembers(),
            ...createNameableMembers(),
            parameters(base) {
                return base.parameters;
            },
            returnType(base) {
                return base.returnType;
            },
            changeReturnType(base) {
                return createFunctionType((newType) => {
                    base.returnType = newType;
                    return voidType;
                });
            },
        },
        Interface: {
            ...createBaseMembers(),
            ...createNameableMembers(),
            operations(base) {
                return createType({
                    kind: "Object",
                    properties: {
                        forEach: createFunctionType((block) => {
                            assertType("block", block, "Function");
                            const props = Array.from(base.operations.values());
                            props.forEach((p) => block.implementation(p));
                            return voidType;
                        }),
                    },
                });
            },
            renameOperation(base) {
                return createFunctionType((oldNameT, newNameT) => {
                    assertType("operation name", oldNameT, "String");
                    assertType("operation name", newNameT, "String");
                    const oldName = oldNameT.value;
                    const newName = newNameT.value;
                    const op = base.operations.get(oldName);
                    if (!op) {
                        throw new ProjectionError(`Couldn't find operation named ${oldName}`);
                    }
                    op.name = newName;
                    base.operations.rekey(oldName, newName);
                    return voidType;
                });
            },
            addOperation(base) {
                return createFunctionType((nameT, parameters, returnType) => {
                    assertType("operation name", nameT, "String");
                    assertType("parameters", parameters, "Model");
                    const name = nameT.value;
                    const prop = base.operations.get(name);
                    if (prop) {
                        throw new ProjectionError(`Operation named ${name} already exists`);
                    }
                    base.operations.set(name, createType({
                        kind: "Operation",
                        name,
                        node: undefined,
                        parameters,
                        returnType,
                        decorators: [],
                    }));
                    return voidType;
                });
            },
            deleteOperation(base) {
                return createFunctionType((nameT) => {
                    assertType("operation name", nameT, "String");
                    const name = nameT.value;
                    const prop = base.operations.get(name);
                    if (!prop) {
                        return voidType;
                    }
                    base.operations.delete(name);
                    return voidType;
                });
            },
        },
        Enum: {
            ...createBaseMembers(),
            ...createNameableMembers(),
            members(base) {
                return createType({
                    kind: "Object",
                    properties: {
                        forEach: createFunctionType((block) => {
                            assertType("parameter", block, "Function");
                            const props = Array.from(base.members.values());
                            props.forEach((p) => block.implementation(p));
                            return voidType;
                        }),
                    },
                });
            },
            name(base) {
                return createLiteralType(base.name);
            },
            addMember(base) {
                return createFunctionType((nameT, type) => {
                    assertType("enum member", nameT, "String");
                    type && assertType("enum type", type, "String", "Number");
                    const name = nameT.value;
                    const member = base.members.get(name);
                    if (member) {
                        throw new ProjectionError(`Enum already has a member named ${name}`);
                    }
                    if (type !== undefined && type.kind !== "Number" && type.kind !== "String") {
                        throw new ProjectionError(`Enum member types must be string or number`);
                    }
                    base.members.set(name, createType({
                        kind: "EnumMember",
                        enum: base,
                        name,
                        decorators: [],
                        node: undefined,
                        value: type ? type.value : undefined,
                    }));
                    return voidType;
                });
            },
            deleteMember(base) {
                return createFunctionType((nameT) => {
                    assertType("enum member", nameT, "String");
                    const name = nameT.value;
                    base.members.delete(name);
                    return voidType;
                });
            },
            renameMember(base) {
                return createFunctionType((oldNameT, newNameT) => {
                    assertType("enum member", oldNameT, "String");
                    assertType("enum member", newNameT, "String");
                    const oldName = oldNameT.value;
                    const newName = newNameT.value;
                    const member = base.members.get(oldName);
                    if (!member) {
                        throw new ProjectionError(`Enum doesn't have member ${oldName}`);
                    }
                    member.name = newName;
                    base.members.rekey(oldName, newName);
                    return voidType;
                });
            },
        },
        EnumMember: {
            ...createBaseMembers(),
            name(base) {
                return createLiteralType(base.name);
            },
            type(base) {
                return base.value ? createLiteralType(base.value) : neverType;
            },
        },
        String: {
            toCamelCase(base) {
                return createFunctionType(() => {
                    return createLiteralType(camelCase(base.value));
                });
            },
            toPascalCase(base) {
                return createFunctionType(() => {
                    return createLiteralType(pascalCase(base.value));
                });
            },
            toSnakeCase(base) {
                return createFunctionType(() => {
                    return createLiteralType(snakeCase(base.value));
                });
            },
            toKebabCase(base) {
                return createFunctionType(() => {
                    return createLiteralType(kebabCase(base.value));
                });
            },
        },
    };
}

/**
 * Maps type arguments to type instantiation.
 */
const TypeInstantiationMap = class extends MultiKeyMap {
};
let currentSymbolId = 0;
function createChecker(program) {
    const stdTypes = {};
    const symbolLinks = new Map();
    const mergedSymbols = new Map();
    const docFromCommentForSym = new Map();
    const augmentDecoratorsForSym = new Map();
    const augmentedSymbolTables = new Map();
    const referenceSymCache = new WeakMap();
    const valueExactTypes = new WeakMap();
    let onCheckerDiagnostic = (x) => {
        program.reportDiagnostic(x);
    };
    const typePrototype = {
        get projections() {
            return (projectionsByTypeKind.get(this.kind) || []).concat(projectionsByType.get(this) || []);
        },
        projectionsByName(name) {
            return this.projections.filter((p) => p.id.sv === name);
        },
    };
    const globalNamespaceNode = createGlobalNamespaceNode();
    const globalNamespaceType = createGlobalNamespaceType();
    // Caches the deprecation test of nodes in the program
    const nodeDeprecationMap = new Map();
    const errorType = createType({ kind: "Intrinsic", name: "ErrorType" });
    const voidType = createType({ kind: "Intrinsic", name: "void" });
    const neverType = createType({ kind: "Intrinsic", name: "never" });
    const unknownType = createType({ kind: "Intrinsic", name: "unknown" });
    const nullType = createType({ kind: "Intrinsic", name: "null" });
    const nullSym = createSymbol(undefined, "null", 0 /* SymbolFlags.None */);
    const projectionsByTypeKind = new Map([
        ["Model", []],
        ["ModelProperty", []],
        ["Scalar", []],
        ["Union", []],
        ["UnionVariant", []],
        ["Operation", []],
        ["Interface", []],
        ["Enum", []],
        ["EnumMember", []],
    ]);
    const projectionsByType = new Map();
    // whether we've checked this specific projection statement before
    // and added it to the various projection maps.
    const processedProjections = new Set();
    // interpreter state
    let currentProjectionDirection;
    /**
     * Set keeping track of node pending type resolution.
     * Key is the SymId of a node. It can be retrieved with getNodeSymId(node)
     */
    const pendingResolutions = new PendingResolutions();
    for (const file of program.jsSourceFiles.values()) {
        mergeSourceFile(file);
    }
    for (const file of program.sourceFiles.values()) {
        mergeSourceFile(file);
    }
    const typespecNamespaceBinding = globalNamespaceNode.symbol.exports.get("TypeSpec");
    if (typespecNamespaceBinding) {
        initializeTypeSpecIntrinsics();
        for (const file of program.sourceFiles.values()) {
            addUsingSymbols(typespecNamespaceBinding.exports, file.locals);
        }
    }
    for (const file of program.sourceFiles.values()) {
        setUsingsForFile(file);
    }
    let evalContext = undefined;
    const checker = {
        getTypeForNode,
        checkProgram,
        checkSourceFile,
        getLiteralType,
        getTypeName,
        getNamespaceString: getNamespaceFullName,
        getGlobalNamespaceType,
        getGlobalNamespaceNode,
        setUsingsForFile,
        getMergedSymbol,
        mergeSourceFile,
        cloneType,
        resolveIdentifier,
        resolveCompletions,
        evalProjection,
        project,
        neverType,
        errorType,
        nullType,
        anyType: unknownType,
        voidType,
        typePrototype,
        createType,
        createAndFinishType,
        createFunctionType,
        createLiteralType,
        finishType,
        isTypeAssignableTo,
        isStdType,
        getStdType,
        resolveTypeReference,
        getValueForNode,
        getTypeOrValueForNode,
        getValueExactType,
    };
    const projectionMembers = createProjectionMembers(checker);
    return checker;
    function reportCheckerDiagnostic(diagnostic) {
        onCheckerDiagnostic(diagnostic);
    }
    function reportCheckerDiagnostics(diagnostics) {
        diagnostics.forEach((x) => reportCheckerDiagnostic(x));
    }
    function initializeTypeSpecIntrinsics() {
        // a utility function to log strings or numbers
        mutate(typespecNamespaceBinding.exports).set("log", {
            flags: 131072 /* SymbolFlags.Function */,
            name: "log",
            value(p, ...strs) {
                program.trace("projection.log", strs.join(" "));
                return voidType;
            },
            declarations: [],
        });
        // Until we have an `unit` type for `null`
        mutate(typespecNamespaceBinding.exports).set("null", nullSym);
        mutate(nullSym).type = nullType;
        getSymbolLinks(nullSym).type = nullType;
    }
    function getStdType(name) {
        const type = stdTypes[name];
        if (type !== undefined) {
            return type;
        }
        const sym = typespecNamespaceBinding?.exports?.get(name);
        if (sym && sym.flags & 2 /* SymbolFlags.Model */) {
            checkModelStatement(sym.declarations[0], undefined);
        }
        else {
            checkScalar(sym.declarations[0], undefined);
        }
        const loadedType = stdTypes[name];
        compilerAssert(loadedType, `TypeSpec std type "${name}" should have been initalized before using array syntax.`);
        return loadedType;
    }
    function mergeSourceFile(file) {
        mergeSymbolTable(file.symbol.exports, mutate(globalNamespaceNode.symbol.exports));
    }
    function setUsingsForFile(file) {
        const usedUsing = new Set();
        for (const using of file.usings) {
            const parentNs = using.parent;
            const sym = resolveTypeReferenceSym(using.name, undefined);
            if (!sym) {
                continue;
            }
            if (!(sym.flags & 4096 /* SymbolFlags.Namespace */)) {
                reportCheckerDiagnostic(createDiagnostic({ code: "using-invalid-ref", target: using }));
                continue;
            }
            const namespaceSym = getMergedSymbol(sym);
            if (usedUsing.has(namespaceSym)) {
                reportCheckerDiagnostic(createDiagnostic({
                    code: "duplicate-using",
                    format: { usingName: memberExpressionToString(using.name) },
                    target: using,
                }));
                continue;
            }
            usedUsing.add(namespaceSym);
            addUsingSymbols(sym.exports, parentNs.locals);
        }
    }
    function applyAugmentDecorators(node) {
        if (!node.statements || !isArray(node.statements)) {
            return;
        }
        const augmentDecorators = node.statements.filter((x) => x.kind === SyntaxKind.AugmentDecoratorStatement);
        for (const decNode of augmentDecorators) {
            const ref = resolveTypeReferenceSym(decNode.targetType, undefined);
            if (ref) {
                let args = [];
                if (ref.declarations[0].kind === SyntaxKind.AliasStatement) {
                    const aliasNode = ref.declarations[0];
                    if (aliasNode.value.kind === SyntaxKind.TypeReference) {
                        args = aliasNode.value.arguments;
                    }
                }
                else {
                    args = decNode.targetType.arguments;
                }
                if (ref.flags & 4096 /* SymbolFlags.Namespace */) {
                    const links = getSymbolLinks(getMergedSymbol(ref));
                    const type = links.type;
                    const decApp = checkDecoratorApplication(type, decNode, undefined);
                    if (decApp) {
                        type.decorators.push(decApp);
                        applyDecoratorToType(program, decApp, type);
                    }
                }
                else if (args.length > 0 || ref.flags & 67108864 /* SymbolFlags.LateBound */) {
                    reportCheckerDiagnostic(createDiagnostic({
                        code: "augment-decorator-target",
                        messageId: "noInstance",
                        target: decNode.target,
                    }));
                }
                else {
                    let list = augmentDecoratorsForSym.get(ref);
                    if (list === undefined) {
                        list = [];
                        augmentDecoratorsForSym.set(ref, list);
                    }
                    list.unshift(decNode);
                }
            }
        }
    }
    function addUsingSymbols(source, destination) {
        const augmented = getOrCreateAugmentedSymbolTable(destination);
        for (const symbolSource of source.values()) {
            const sym = {
                flags: 524288 /* SymbolFlags.Using */,
                declarations: [],
                name: symbolSource.name,
                symbolSource: symbolSource,
            };
            augmented.set(sym.name, sym);
        }
    }
    /**
     * We cannot inject symbols into the symbol tables hanging off syntax tree nodes as
     * syntax tree nodes can be shared by other programs. This is called as a copy-on-write
     * to inject using and late-bound symbols, and then we use the copy when resolving
     * in the table.
     */
    function getOrCreateAugmentedSymbolTable(table) {
        let augmented = augmentedSymbolTables.get(table);
        if (!augmented) {
            augmented = createSymbolTable(table);
            augmentedSymbolTables.set(table, augmented);
        }
        return mutate(augmented);
    }
    /**
     * Create the link for the given type to the symbol links.
     * If currently instantiating a template it will link to the instantiations.
     * Else will link to the declaredType.
     * @param links Symbol link
     * @param type Type
     * @param mapper Type mapper if in an template instantiation
     */
    function linkType(links, type, mapper) {
        if (mapper === undefined) {
            links.declaredType = type;
            links.instantiations = new TypeInstantiationMap();
        }
        else if (links.instantiations) {
            links.instantiations.set(mapper.args, type);
        }
    }
    function linkMemberType(links, type, mapper) {
        if (mapper === undefined) {
            links.declaredType = type;
        }
    }
    /**
     * Check a member symbol.
     * @param sym Symbol binding a member node.
     * @param mapper Type mapper.
     * @returns Checked type for the given member symbol.
     */
    function checkMemberSym(sym, mapper) {
        const symbolLinks = getSymbolLinks(sym);
        const memberContainer = getTypeForNode(sym.parent.declarations[0], mapper);
        const type = symbolLinks.declaredType ?? symbolLinks.type;
        if (type) {
            return type;
        }
        else {
            return checkMember(sym.declarations[0], mapper, memberContainer);
        }
    }
    /**
     * Check a member node
     * @param node Member node to check
     * @param mapper Type mapper
     * @param containerType Member node container type(Interface, Model, Union, etc.)
     * @returns Checked member
     */
    function checkMember(node, mapper, containerType) {
        switch (node.kind) {
            case SyntaxKind.ModelProperty:
                return checkModelProperty(node, mapper);
            case SyntaxKind.EnumMember:
                return checkEnumMember(node, mapper, containerType);
            case SyntaxKind.OperationStatement:
                return checkOperation(node, mapper, containerType);
            case SyntaxKind.UnionVariant:
                return checkUnionVariant(node, mapper);
            case SyntaxKind.ScalarConstructor:
                return checkScalarConstructor(node, mapper, containerType);
        }
    }
    function getTypeForTypeOrIndeterminate(entity) {
        if (entity.entityKind === "Indeterminate") {
            return entity.type;
        }
        return entity;
    }
    function getTypeForNode(node, mapper) {
        const entity = checkNode(node, mapper);
        if (entity === null) {
            return errorType;
        }
        if (entity.entityKind === "Indeterminate") {
            return entity.type;
        }
        if (isValue(entity)) {
            reportCheckerDiagnostic(createDiagnostic({
                code: "value-in-type",
                target: node,
            }));
            return errorType;
        }
        if (entity.kind === "TemplateParameter") {
            if (entity.constraint?.valueType) {
                // means this template constraint will accept values
                reportCheckerDiagnostic(createDiagnostic({
                    code: "value-in-type",
                    messageId: "referenceTemplate",
                    target: node,
                }));
            }
        }
        return entity;
    }
    function getValueForNode(node, mapper, constraint, options = {}) {
        const initial = checkNode(node, mapper, constraint);
        if (initial === null) {
            return null;
        }
        let entity;
        if (initial.entityKind === "Indeterminate") {
            entity = getValueFromIndeterminate(initial.type, constraint, node);
        }
        else {
            entity = initial;
        }
        if (options.legacyTupleAndModelCast && entity !== null && isType(entity)) {
            entity = legacy_tryTypeToValueCast(entity, constraint, node);
        }
        if (entity === null) {
            return null;
        }
        if (isValue(entity)) {
            return constraint ? inferScalarsFromConstraints(entity, constraint.type) : entity;
        }
        reportExpectedValue(node, entity);
        return null;
    }
    function reportExpectedValue(target, type) {
        if (type.kind === "Model" && type.name === "" && target.kind === SyntaxKind.ModelExpression) {
            reportCheckerDiagnostic(createDiagnostic({
                code: "expect-value",
                messageId: "model",
                format: { name: getTypeName(type) },
                codefixes: [createModelToObjectValueCodeFix(target)],
                target,
            }));
        }
        else if (type.kind === "Tuple" && target.kind === SyntaxKind.TupleExpression) {
            reportCheckerDiagnostic(createDiagnostic({
                code: "expect-value",
                messageId: "tuple",
                format: { name: getTypeName(type) },
                codefixes: [createTupleToArrayValueCodeFix(target)],
                target,
            }));
        }
        else {
            reportCheckerDiagnostic(createDiagnostic({
                code: "expect-value",
                format: { name: getTypeName(type) },
                target,
            }));
        }
    }
    /** In certain context for types that can also be value if the constraint allows it we try to use it as a value instead of a type. */
    function getValueFromIndeterminate(type, constraint, node) {
        switch (type.kind) {
            case "String":
            case "StringTemplate":
                return checkStringValue(type, constraint, node);
            case "Number":
                return checkNumericValue(type, constraint, node);
            case "Boolean":
                return checkBooleanValue(type, constraint, node);
            case "EnumMember":
                return checkEnumValue(type, constraint, node);
            case "UnionVariant":
                return getValueFromIndeterminate(type.type, constraint, node);
            case "Intrinsic":
                switch (type.name) {
                    case "null":
                        return checkNullValue(type, constraint, node);
                }
                return type;
            default:
                return type;
        }
    }
    function legacy_tryTypeToValueCast(type, constraint, node) {
        switch (type.kind) {
            case "Tuple":
                return legacy_tryUsingTupleAsArrayValue(type, constraint?.type, node);
            case "Model":
                return legacy_tryUsingModelAsObjectValue(type, constraint?.type, node);
            default:
                return type;
        }
    }
    // Legacy behavior to smooth transition to object values.
    function legacy_tryUsingModelAsObjectValue(model, type, node) {
        if (model.node?.kind !== SyntaxKind.ModelExpression) {
            return model; // we only want to convert model expressions
        }
        reportCheckerDiagnostic(createDiagnostic({
            code: "deprecated",
            codefixes: [createModelToObjectValueCodeFix(model.node)],
            format: {
                message: "Using a model as a value is deprecated. Use an object value instead(with #{}).",
            },
            target: model.node,
        }));
        const value = {
            entityKind: "Value",
            valueKind: "ObjectValue",
            type: type ?? model,
            node: model.node,
            properties: new Map(),
        };
        for (const prop of model.properties.values()) {
            let propValue = getValueFromIndeterminate(prop.type, { kind: "assignment", type: prop.type }, node);
            if (propValue !== null && isType(propValue)) {
                propValue = legacy_tryTypeToValueCast(propValue, { kind: "assignment", type: prop.type }, node);
            }
            if (propValue == null) {
                return null;
            }
            else if (!isValue(propValue)) {
                return model;
            }
            value.properties.set(prop.name, {
                name: prop.name,
                value: propValue,
                node: prop.node,
            });
        }
        if (type !== undefined && !checkTypeAssignable(model, type, node)) {
            return null;
        }
        return value;
    }
    // Legacy behavior to smooth transition to array values.
    function legacy_tryUsingTupleAsArrayValue(tuple, type, node) {
        if (tuple.node.kind !== SyntaxKind.TupleExpression) {
            return tuple; // we won't convert dynamic tuples to array values
        }
        reportCheckerDiagnostic(createDiagnostic({
            code: "deprecated",
            codefixes: [createTupleToArrayValueCodeFix(tuple.node)],
            format: {
                message: "Using a tuple as a value is deprecated. Use an array value instead(with #[]).",
            },
            target: tuple.node,
        }));
        const values = [];
        for (const [index, item] of tuple.values.entries()) {
            const itemType = type?.kind === "Model" && isArrayModelType(program, type)
                ? type.indexer.value
                : type?.kind === "Tuple"
                    ? type.values[index]
                    : undefined;
            let value = getValueFromIndeterminate(item, itemType && { kind: "assignment", type: itemType }, node);
            if (value !== null && isType(value)) {
                value = legacy_tryTypeToValueCast(value, itemType && { kind: "assignment", type: itemType }, node);
            }
            if (value === null) {
                return null;
            }
            else if (!isValue(value)) {
                return tuple;
            }
            values.push(value);
        }
        if (type !== undefined && !checkTypeAssignable(tuple, type, node)) {
            return null;
        }
        return {
            entityKind: "Value",
            valueKind: "ArrayValue",
            type: type ?? tuple,
            node: tuple.node,
            values,
        };
    }
    function canTryLegacyCast(target, constraint) {
        return Boolean(constraint?.valueType &&
            !(constraint.type && ignoreDiagnostics(isTypeAssignableTo(target, constraint.type, target))));
    }
    /**
     * Gets a type or value depending on the node and current constraint.
     * For nodes that can be both type or values(e.g. string), the value will be returned if the constraint expect a value of that type even if the constrain also allows the type.
     * This means that if the constraint is `string | valueof string` passing `"abc"` will send the value `"abc"` and not the type `"abc"`.
     */
    function getTypeOrValueForNode(node, mapper, constraint) {
        const valueConstraint = extractValueOfConstraints(constraint);
        const entity = checkNode(node, mapper, valueConstraint);
        if (entity === null) {
            return entity;
        }
        else if (isType(entity)) {
            if (canTryLegacyCast(entity, constraint?.constraint)) {
                return legacy_tryTypeToValueCast(entity, valueConstraint, node);
            }
            else {
                return entity;
            }
        }
        else if (isValue(entity)) {
            return entity;
        }
        compilerAssert(entity.entityKind === "Indeterminate", "Expected indeterminate entity");
        if (valueConstraint) {
            const valueDiagnostics = [];
            const oldDiagnosticHook = onCheckerDiagnostic;
            onCheckerDiagnostic = (x) => valueDiagnostics.push(x);
            const result = getValueFromIndeterminate(entity.type, valueConstraint, node);
            onCheckerDiagnostic = oldDiagnosticHook;
            if (result) {
                // If there were diagnostic reported but we still got a value this means that the value might be invalid.
                reportCheckerDiagnostics(valueDiagnostics);
                return result;
            }
        }
        return entity.type;
    }
    /** Extact the type constraint a value should match. */
    function extractValueOfConstraints(constraint) {
        if (constraint?.constraint.valueType) {
            return { kind: constraint.kind, type: constraint.constraint.valueType };
        }
        else {
            return undefined;
        }
    }
    /**
     * Gets a type, value or indeterminate depending on the node and current constraint.
     * For nodes that can be both type or values(e.g. string literals), an indeterminate entity will be returned.
     * It is the job of of the consumer to decide if it should be a type or a value depending on the context.
     */
    function checkNode(node, mapper, valueConstraint) {
        switch (node.kind) {
            case SyntaxKind.ModelExpression:
                return checkModel(node, mapper);
            case SyntaxKind.ModelStatement:
                return checkModel(node, mapper);
            case SyntaxKind.ModelProperty:
                return checkModelProperty(node, mapper);
            case SyntaxKind.ScalarStatement:
                return checkScalar(node, mapper);
            case SyntaxKind.AliasStatement:
                return checkAlias(node, mapper);
            case SyntaxKind.EnumStatement:
                return checkEnum(node, mapper);
            case SyntaxKind.EnumMember:
                return checkEnumMember(node, mapper);
            case SyntaxKind.InterfaceStatement:
                return checkInterface(node, mapper);
            case SyntaxKind.UnionStatement:
                return checkUnion(node, mapper);
            case SyntaxKind.UnionVariant:
                return checkUnionVariant(node, mapper);
            case SyntaxKind.NamespaceStatement:
            case SyntaxKind.JsNamespaceDeclaration:
                return checkNamespace(node);
            case SyntaxKind.OperationStatement:
                return checkOperation(node, mapper);
            case SyntaxKind.NumericLiteral:
                return checkNumericLiteral(node);
            case SyntaxKind.BooleanLiteral:
                return checkBooleanLiteral(node);
            case SyntaxKind.StringLiteral:
                return checkStringLiteral(node);
            case SyntaxKind.TupleExpression:
                return checkTupleExpression(node, mapper);
            case SyntaxKind.StringTemplateExpression:
                return checkStringTemplateExpresion(node, mapper);
            case SyntaxKind.ArrayExpression:
                return checkArrayExpression(node, mapper);
            case SyntaxKind.UnionExpression:
                return checkUnionExpression(node, mapper);
            case SyntaxKind.IntersectionExpression:
                return checkIntersectionExpression(node, mapper);
            case SyntaxKind.DecoratorDeclarationStatement:
                return checkDecoratorDeclaration(node, mapper);
            case SyntaxKind.FunctionDeclarationStatement:
                return checkFunctionDeclaration(node, mapper);
            case SyntaxKind.TypeReference:
                return checkTypeOrValueReference(node, mapper);
            case SyntaxKind.TemplateArgument:
                return checkTemplateArgument(node, mapper);
            case SyntaxKind.TemplateParameterDeclaration:
                return checkTemplateParameterDeclaration(node, mapper);
            case SyntaxKind.ProjectionStatement:
                return checkProjectionDeclaration(node);
            case SyntaxKind.VoidKeyword:
                return voidType;
            case SyntaxKind.NeverKeyword:
                return neverType;
            case SyntaxKind.UnknownKeyword:
                return unknownType;
            case SyntaxKind.ObjectLiteral:
                return checkObjectValue(node, mapper, valueConstraint);
            case SyntaxKind.ArrayLiteral:
                return checkArrayValue(node, mapper, valueConstraint);
            case SyntaxKind.ConstStatement:
                return checkConst(node);
            case SyntaxKind.CallExpression:
                return checkCallExpression(node, mapper);
            case SyntaxKind.TypeOfExpression:
                return checkTypeOfExpression(node, mapper);
            default:
                return errorType;
        }
    }
    /**
     * Return a fully qualified id of node
     */
    function getNodeSymId(node) {
        const symbol = node.kind === SyntaxKind.OperationStatement &&
            node.parent?.kind === SyntaxKind.InterfaceStatement
            ? getSymbolForMember(node)
            : node.symbol;
        // eslint-disable-next-line @typescript-eslint/no-non-null-asserted-optional-chain
        return symbol?.id;
    }
    /**
     * Check if the given namespace is the standard library `TypeSpec` namespace.
     */
    function isTypeSpecNamespace(namespace) {
        return (namespace.name === "TypeSpec" &&
            (namespace.namespace === globalNamespaceType ||
                namespace.namespace?.projectionBase === globalNamespaceType));
    }
    /**
     * Check if the given type is defined right in the TypeSpec namespace.
     */
    function isInTypeSpecNamespace(type) {
        return Boolean(type.namespace && isTypeSpecNamespace(type.namespace));
    }
    function checkTemplateParameterDeclaration(node, mapper) {
        const parentNode = node.parent;
        const grandParentNode = parentNode.parent;
        const links = getSymbolLinks(node.symbol);
        if (pendingResolutions.has(getNodeSymId(node), ResolutionKind.Constraint)) {
            if (mapper === undefined) {
                reportCheckerDiagnostic(createDiagnostic({
                    code: "circular-constraint",
                    format: { typeName: node.id.sv },
                    target: node.constraint,
                }));
            }
            return errorType;
        }
        let type = links.declaredType;
        if (type === undefined) {
            if (grandParentNode) {
                if (grandParentNode.locals?.has(node.id.sv)) {
                    reportCheckerDiagnostic(createDiagnostic({
                        code: "shadow",
                        format: { name: node.id.sv },
                        target: node,
                    }));
                }
            }
            const index = parentNode.templateParameters.findIndex((v) => v === node);
            type = links.declaredType = createAndFinishType({
                kind: "TemplateParameter",
                node: node,
            });
            if (node.constraint) {
                pendingResolutions.start(getNodeSymId(node), ResolutionKind.Constraint);
                type.constraint = getParamConstraintEntityForNode(node.constraint);
                pendingResolutions.finish(getNodeSymId(node), ResolutionKind.Constraint);
            }
            if (node.default) {
                type.default = checkTemplateParameterDefault(node.default, parentNode.templateParameters, index, type.constraint);
            }
        }
        return mapper ? mapper.getMappedType(type) : type;
    }
    function getResolvedTypeParameterDefault(declaredType, node, mapper) {
        if (declaredType.default === undefined) {
            return undefined;
        }
        if ((isType(declaredType.default) && isErrorType(declaredType.default)) ||
            declaredType.default === null) {
            return declaredType.default;
        }
        return checkNode(node.default, mapper);
    }
    function checkTemplateParameterDefault(nodeDefault, templateParameters, index, constraint) {
        function visit(node) {
            const entity = checkNode(node);
            let hasError = false;
            if (entity !== null && "kind" in entity && entity.kind === "TemplateParameter") {
                for (let i = index; i < templateParameters.length; i++) {
                    if (entity.node.symbol === templateParameters[i].symbol) {
                        reportCheckerDiagnostic(createDiagnostic({ code: "invalid-template-default", target: node }));
                        return undefined;
                    }
                }
                return entity;
            }
            visitChildren(node, (x) => {
                const visited = visit(x);
                if (visited === undefined) {
                    hasError = true;
                }
            });
            return hasError ? undefined : entity;
        }
        const type = visit(nodeDefault) ?? errorType;
        if (!("kind" in type && isErrorType(type)) && constraint) {
            checkTypeAssignable(type, constraint, nodeDefault);
        }
        return type;
    }
    /**
     * Check and resolve a type for the given type reference node.
     * @param node Node.
     * @param mapper Type mapper for template instantiation context.
     * @param instantiateTemplate If templated type should be instantiated if they haven't yet.
     * @returns Resolved type.
     */
    function checkTypeReference(node, mapper, instantiateTemplate = true) {
        const sym = resolveTypeReferenceSym(node, mapper);
        if (!sym) {
            return errorType;
        }
        const type = checkTypeReferenceSymbol(sym, node, mapper, instantiateTemplate);
        return type;
    }
    /**
     * Check and resolve a type for the given type reference node.
     * @param node Node.
     * @param mapper Type mapper for template instantiation context.
     * @param instantiateTemplate If templated type should be instantiated if they haven't yet.
     * @returns Resolved type.
     */
    function checkTypeOrValueReference(node, mapper, instantiateTemplate = true) {
        const sym = resolveTypeReferenceSym(node, mapper);
        if (!sym) {
            return errorType;
        }
        return checkTypeOrValueReferenceSymbol(sym, node, mapper, instantiateTemplate) ?? errorType;
    }
    function checkTemplateArgument(node, mapper) {
        return checkNode(node.argument, mapper);
    }
    function resolveTypeReference(node) {
        const oldDiagnosticHook = onCheckerDiagnostic;
        const diagnostics = [];
        onCheckerDiagnostic = (x) => diagnostics.push(x);
        const type = checkTypeReference(node, undefined, false);
        onCheckerDiagnostic = oldDiagnosticHook;
        return [type === errorType ? undefined : type, diagnostics];
    }
    function copyDeprecation(sourceType, destType) {
        const deprecationDetails = getDeprecationDetails(program, sourceType);
        if (deprecationDetails) {
            markDeprecated(program, destType, deprecationDetails);
        }
    }
    function checkDeprecated(type, node, target) {
        if (node) {
            const deprecationDetails = getDeprecationDetails(program, node);
            if (deprecationDetails) {
                reportDeprecation(program, target, deprecationDetails.message, reportCheckerDiagnostic);
                return;
            }
        }
        const deprecationDetails = getDeprecationDetails(program, type);
        if (deprecationDetails) {
            reportDeprecation(program, target, deprecationDetails.message, reportCheckerDiagnostic);
        }
    }
    function isTypeReferenceContextDeprecated(node) {
        function checkDeprecatedNode(node) {
            // Perform a simple check if the parent node is deprecated.  We do this
            // out of band because `checkDirectives` usually gets called on the parent
            // type after child types have already been checked (including their
            // deprecations).
            if (!nodeDeprecationMap.has(node)) {
                nodeDeprecationMap.set(node, (node.directives ?? []).findIndex((d) => d.target.sv === "deprecated") >= 0);
            }
            return nodeDeprecationMap.get(node);
        }
        // Walk the parent hierarchy up to a node which might have a
        // deprecation which would mitigate the deprecation warning of the original
        // type reference. This is done to prevent multiple deprecation notices from
        // being raised when a parent context is already being deprecated.
        switch (node.kind) {
            case SyntaxKind.ModelStatement:
                return checkDeprecatedNode(node);
            case SyntaxKind.OperationStatement:
                return (checkDeprecatedNode(node) ||
                    (node.parent.kind === SyntaxKind.InterfaceStatement &&
                        isTypeReferenceContextDeprecated(node.parent)));
            case SyntaxKind.InterfaceStatement:
                return checkDeprecatedNode(node);
            case SyntaxKind.IntersectionExpression:
            case SyntaxKind.UnionExpression:
            case SyntaxKind.ModelProperty:
            case SyntaxKind.OperationSignatureDeclaration:
            case SyntaxKind.OperationSignatureReference:
                return isTypeReferenceContextDeprecated(node.parent);
            default:
                return false;
        }
    }
    function checkTemplateInstantiationArgs(node, args, decls, mapper) {
        const params = new Map();
        const positional = [];
        const initMap = new Map(decls.map((decl) => {
            const declaredType = checkTemplateParameterDeclaration(decl, undefined);
            positional.push(declaredType);
            params.set(decl.id.sv, declaredType);
            return [
                declaredType,
                {
                    decl,
                    checkArgument: null,
                },
            ];
        }));
        let named = false;
        for (const [arg, idx] of args.map((v, i) => [v, i])) {
            function deferredCheck() {
                return [arg, checkNode(arg.argument, mapper)];
            }
            if (arg.name) {
                named = true;
                const param = params.get(arg.name.sv);
                if (!param) {
                    reportCheckerDiagnostic(createDiagnostic({
                        code: "invalid-template-args",
                        messageId: "unknownName",
                        format: {
                            name: arg.name.sv,
                        },
                        target: arg,
                    }));
                    continue;
                }
                if (initMap.get(param).checkArgument !== null) {
                    reportCheckerDiagnostic(createDiagnostic({
                        code: "invalid-template-args",
                        messageId: "specifiedAgain",
                        format: {
                            name: arg.name.sv,
                        },
                        target: arg,
                    }));
                    continue;
                }
                initMap.get(param).checkArgument = deferredCheck;
            }
            else {
                if (named) {
                    reportCheckerDiagnostic(createDiagnostic({
                        code: "invalid-template-args",
                        messageId: "positionalAfterNamed",
                        target: arg,
                    }));
                    // we just throw this arg away. any missing args will be filled with ErrorType
                }
                if (idx >= positional.length) {
                    reportCheckerDiagnostic(createDiagnostic({
                        code: "invalid-template-args",
                        messageId: "tooMany",
                        target: node,
                    }));
                    continue;
                }
                const param = positional[idx];
                initMap.get(param).checkArgument ??= deferredCheck;
            }
        }
        const finalMap = initMap;
        const mapperParams = [];
        const mapperArgs = [];
        for (const [param, { decl, checkArgument: init }] of [...initMap]) {
            function commit(param, type) {
                finalMap.set(param, type);
                mapperParams.push(param);
                mapperArgs.push(type);
            }
            if (init === null) {
                const argumentMapper = createTypeMapper(mapperParams, mapperArgs);
                const defaultValue = getResolvedTypeParameterDefault(param, decl, argumentMapper);
                if (defaultValue) {
                    commit(param, defaultValue);
                }
                else {
                    reportCheckerDiagnostic(createDiagnostic({
                        code: "invalid-template-args",
                        messageId: "missing",
                        format: {
                            name: decl.id.sv,
                        },
                        target: node,
                    }));
                    // TODO-TIM check if we expose this below
                    commit(param, param.constraint?.type ?? unknownType);
                }
                continue;
            }
            const [argNode, type] = init();
            if (type === null) {
                commit(param, unknownType);
                continue;
            }
            if (param.constraint) {
                const constraint = param.constraint.type?.kind === "TemplateParameter"
                    ? finalMap.get(param.constraint.type)
                    : param.constraint;
                if (isType(type) && canTryLegacyCast(type, param.constraint)) {
                    const converted = legacy_tryTypeToValueCast(type, { kind: "argument", type: param.constraint.valueType }, argNode);
                    // If we manage to convert it means this might be convertable so we skip type checking.
                    // However we still return the original entity
                    if (converted !== type) {
                        commit(param, type);
                        continue;
                    }
                }
                if (param.constraint && !checkArgumentAssignable(type, constraint, argNode)) {
                    const effectiveType = param.constraint.type ?? unknownType;
                    commit(param, effectiveType);
                    continue;
                }
            }
            else if (isErrorType(type)) {
                // If we got an error type we don't want to keep passing it through so we reduce to unknown
                // Similar to the above where if the type is not assignable to the constraint we reduce to the constraint
                commit(param, unknownType);
                continue;
            }
            else if (isValue(type)) {
                reportCheckerDiagnostic(createDiagnostic({
                    code: "value-in-type",
                    messageId: "noTemplateConstraint",
                    target: argNode,
                }));
                commit(param, unknownType);
                continue;
            }
            commit(param, type);
        }
        return finalMap;
    }
    /**
     * Check and resolve the type for the given symbol + node.
     * @param sym Symbol
     * @param node Node
     * @param mapper Type mapper for template instantiation context.
     * @param instantiateTemplates If a templated type should be instantiated if not yet @default true
     * @returns resolved type.
     */
    function checkTypeReferenceSymbol(sym, node, mapper, instantiateTemplates = true) {
        const result = checkTypeOrValueReferenceSymbol(sym, node, mapper, instantiateTemplates);
        if (result === null || isValue(result)) {
            reportCheckerDiagnostic(createDiagnostic({ code: "value-in-type", target: node }));
            return errorType;
        }
        if (result.entityKind === "Indeterminate") {
            return result.type;
        }
        return result;
    }
    function checkTypeOrValueReferenceSymbol(sym, node, mapper, instantiateTemplates = true) {
        if (sym.flags & 16777216 /* SymbolFlags.Const */) {
            return getValueForNode(sym.declarations[0], mapper);
        }
        if (sym.flags & 16384 /* SymbolFlags.Decorator */) {
            reportCheckerDiagnostic(createDiagnostic({ code: "invalid-type-ref", messageId: "decorator", target: sym }));
            return errorType;
        }
        if (sym.flags & 131072 /* SymbolFlags.Function */) {
            reportCheckerDiagnostic(createDiagnostic({ code: "invalid-type-ref", messageId: "function", target: sym }));
            return errorType;
        }
        const argumentNodes = node.kind === SyntaxKind.TypeReference ? node.arguments : [];
        const symbolLinks = getSymbolLinks(sym);
        let baseType;
        if (sym.flags &
            (2 /* SymbolFlags.Model */ |
                8 /* SymbolFlags.Scalar */ |
                2048 /* SymbolFlags.Alias */ |
                128 /* SymbolFlags.Interface */ |
                16 /* SymbolFlags.Operation */ |
                512 /* SymbolFlags.Union */)) {
            const decl = sym.declarations[0];
            if (!isTemplatedNode(decl)) {
                if (argumentNodes.length > 0) {
                    reportCheckerDiagnostic(createDiagnostic({
                        code: "invalid-template-args",
                        messageId: "notTemplate",
                        target: node,
                    }));
                }
                if (sym.flags & 67108864 /* SymbolFlags.LateBound */) {
                    compilerAssert(sym.type, "Expected late bound symbol to have type");
                    return sym.type;
                }
                else if (symbolLinks.declaredType) {
                    baseType = symbolLinks.declaredType;
                }
                else if (sym.flags & 33555780 /* SymbolFlags.Member */) {
                    baseType = checkMemberSym(sym, mapper);
                }
                else {
                    baseType = checkDeclaredTypeOrIndeterminate(sym, decl, mapper);
                }
            }
            else {
                const declaredType = getOrCheckDeclaredType(sym, decl, mapper);
                const templateParameters = decl.templateParameters;
                const instantiation = checkTemplateInstantiationArgs(node, argumentNodes, templateParameters, mapper);
                baseType = getOrInstantiateTemplate(decl, [...instantiation.keys()], [...instantiation.values()], declaredType.templateMapper, instantiateTemplates);
            }
        }
        else {
            // some other kind of reference
            if (argumentNodes.length > 0) {
                reportCheckerDiagnostic(createDiagnostic({
                    code: "invalid-template-args",
                    messageId: "notTemplate",
                    target: node,
                }));
            }
            if (sym.flags & 67108864 /* SymbolFlags.LateBound */) {
                compilerAssert(sym.type, `Expected late bound symbol to have type`);
                return sym.type;
            }
            else if (sym.flags & 32768 /* SymbolFlags.TemplateParameter */) {
                const mapped = checkTemplateParameterDeclaration(sym.declarations[0], mapper);
                baseType = mapped;
            }
            else if (symbolLinks.type) {
                // Have a cached type for non-declarations
                baseType = symbolLinks.type;
            }
            else if (symbolLinks.declaredType) {
                baseType = symbolLinks.declaredType;
            }
            else {
                if (sym.flags & 33555780 /* SymbolFlags.Member */) {
                    baseType = checkMemberSym(sym, mapper);
                }
                else {
                    // don't have a cached type for this symbol, so go grab it and cache it
                    baseType = getTypeForNode(sym.declarations[0], mapper);
                    symbolLinks.type = baseType;
                }
            }
        }
        // Check for deprecations here, first on symbol, then on type.  However,
        // don't raise deprecation when the usage site is also a deprecated
        // declaration.
        const declarationNode = sym?.declarations[0];
        if (declarationNode && mapper === undefined && isType(baseType)) {
            if (!isTypeReferenceContextDeprecated(node.parent)) {
                checkDeprecated(baseType, declarationNode, node);
            }
        }
        // Elements that could be used as type or values depending on the context
        if ((isType(baseType) && (baseType.kind === "EnumMember" || baseType.kind === "UnionVariant")) ||
            isNullType(baseType)) {
            return createIndeterminateEntity(baseType);
        }
        return baseType;
    }
    /**
     * Get or check the declared type of a templatable node.
     * @param node Declaration node
     * @param sym Node Symbol
     * @param mapper Type mapper for template resolution
     * @returns The declared type for the given node.
     */
    function getOrCheckDeclaredType(sym, decl, mapper) {
        const symbolLinks = getSymbolLinks(sym);
        if (symbolLinks.declaredType) {
            return symbolLinks.declaredType;
        }
        if (sym.flags & 67108864 /* SymbolFlags.LateBound */) {
            compilerAssert(sym.type, "Expected late bound symbol to have type");
            return sym.type;
        }
        if (sym.flags & 33555780 /* SymbolFlags.Member */) {
            return checkMemberSym(sym, mapper);
        }
        else {
            return checkDeclaredType(sym, decl, mapper);
        }
    }
    /**
     * Check the declared type of a templatable node.
     * @param node Declaration node
     * @param sym Node Symbol
     * @param mapper Type mapper for template resolution
     * @returns The declared type for the given node.
     */
    function checkDeclaredTypeOrIndeterminate(sym, node, mapper) {
        const type = sym.flags & 2 /* SymbolFlags.Model */
            ? checkModelStatement(node, mapper)
            : sym.flags & 8 /* SymbolFlags.Scalar */
                ? checkScalar(node, mapper)
                : sym.flags & 2048 /* SymbolFlags.Alias */
                    ? checkAlias(node, mapper)
                    : sym.flags & 128 /* SymbolFlags.Interface */
                        ? checkInterface(node, mapper)
                        : sym.flags & 16 /* SymbolFlags.Operation */
                            ? checkOperation(node, mapper)
                            : checkUnion(node, mapper);
        return type;
    }
    function checkDeclaredType(sym, node, mapper) {
        return getTypeForTypeOrIndeterminate(checkDeclaredTypeOrIndeterminate(sym, node, mapper));
    }
    function getOrInstantiateTemplate(templateNode, params, args, parentMapper, instantiateTempalates = true) {
        const symbolLinks = templateNode.kind === SyntaxKind.OperationStatement &&
            templateNode.parent.kind === SyntaxKind.InterfaceStatement
            ? getSymbolLinksForMember(templateNode)
            : getSymbolLinks(templateNode.symbol);
        compilerAssert(symbolLinks, `Unexpected checker error. symbolLinks was not defined for ${SyntaxKind[templateNode.kind]}`);
        if (symbolLinks.instantiations === undefined) {
            const type = getTypeForNode(templateNode);
            if (isErrorType(type)) {
                return errorType;
            }
            else {
                compilerAssert(false, `Unexpected checker error. symbolLinks.instantiations was not defined for ${SyntaxKind[templateNode.kind]}`);
            }
        }
        const mapper = createTypeMapper(params, args, parentMapper);
        const cached = symbolLinks.instantiations?.get(mapper.args);
        if (cached) {
            return cached;
        }
        if (instantiateTempalates) {
            return instantiateTemplate(symbolLinks.instantiations, templateNode, params, mapper);
        }
        else {
            return errorType;
        }
    }
    /**
     * Builds a model type from a template and its template arguments.
     * Adds the template node to a set we can check when we bind template
     * parameters to access type type arguments.
     *
     * This will fall over if the same template is ever being instantiated
     * twice at the same time, or if template parameters from more than one template
     * are ever in scope at once.
     */
    function instantiateTemplate(instantiations, templateNode, params, mapper) {
        const type = getTypeForNode(templateNode, mapper);
        if (!instantiations.get(mapper.args)) {
            instantiations.set(mapper.args, type);
        }
        if (type.kind === "Model") {
            type.templateNode = templateNode;
        }
        return type;
    }
    /** Check a union expresion used in a parameter constraint, those allow the use of `valueof` as a variant. */
    function checkMixedParameterConstraintUnion(node, mapper) {
        const values = [];
        const types = [];
        for (const option of node.options) {
            const [kind, type] = getTypeOrValueOfTypeForNode(option, mapper);
            if (kind === "value") {
                values.push(type);
            }
            else {
                types.push(type);
            }
        }
        return {
            entityKind: "MixedParameterConstraint",
            node,
            valueType: values.length === 0
                ? undefined
                : values.length === 1
                    ? values[0]
                    : createConstraintUnion(node, values),
            type: types.length === 0
                ? undefined
                : types.length === 1
                    ? types[0]
                    : createConstraintUnion(node, types),
        };
    }
    function createConstraintUnion(node, options) {
        const variants = createRekeyableMap();
        const union = createAndFinishType({
            kind: "Union",
            node,
            options,
            decorators: [],
            variants,
            expression: true,
        });
        for (const option of options) {
            const name = Symbol("indexer-union-variant");
            variants.set(name, createAndFinishType({
                kind: "UnionVariant",
                node: undefined,
                type: option,
                name,
                union,
                decorators: [],
            }));
        }
        return union;
    }
    function checkUnionExpression(node, mapper) {
        const unionType = createAndFinishType({
            kind: "Union",
            node,
            get options() {
                return Array.from(this.variants.values()).map((v) => v.type);
            },
            expression: true,
            variants: createRekeyableMap(),
            decorators: [],
        });
        for (const o of node.options) {
            const type = getTypeForNode(o, mapper);
            // The type `A | never` is just `A`
            if (type === neverType) {
                continue;
            }
            if (type.kind === "Union" && type.expression) {
                for (const [name, variant] of type.variants) {
                    unionType.variants.set(name, variant);
                }
            }
            else {
                const variant = createType({
                    kind: "UnionVariant",
                    type,
                    name: Symbol("name"),
                    decorators: [],
                    node: undefined,
                    union: unionType,
                });
                unionType.variants.set(variant.name, variant);
            }
        }
        return unionType;
    }
    /**
     * Intersection produces a model type from the properties of its operands.
     * So this doesn't work if we don't have a known set of properties (e.g.
     * with unions). The resulting model is anonymous.
     */
    function checkIntersectionExpression(node, mapper) {
        const options = node.options.map((o) => [o, getTypeForNode(o, mapper)]);
        return mergeModelTypes(node, options, mapper);
    }
    function checkDecoratorDeclaration(node, mapper) {
        const symbol = getMergedSymbol(node.symbol);
        const links = getSymbolLinks(symbol);
        if (links.declaredType && mapper === undefined) {
            // we're not instantiating this operation and we've already checked it
            return links.declaredType;
        }
        const namespace = getParentNamespaceType(node);
        compilerAssert(namespace, `Decorator ${node.id.sv} should have resolved a namespace or found the global namespace.`);
        const name = node.id.sv;
        if (!(node.modifierFlags & 2 /* ModifierFlags.Extern */)) {
            reportCheckerDiagnostic(createDiagnostic({ code: "decorator-extern", target: node }));
        }
        const implementation = symbol.value;
        if (implementation === undefined) {
            reportCheckerDiagnostic(createDiagnostic({ code: "missing-implementation", target: node }));
        }
        const decoratorType = createType({
            kind: "Decorator",
            name: `@${name}`,
            namespace,
            node,
            target: checkFunctionParameter(node.target, mapper, true),
            parameters: node.parameters.map((x) => checkFunctionParameter(x, mapper, true)),
            implementation: implementation ?? (() => { }),
        });
        namespace.decoratorDeclarations.set(name, decoratorType);
        linkType(links, decoratorType, mapper);
        checkDecoratorLegacyMarshalling(decoratorType);
        return decoratorType;
    }
    function checkDecoratorLegacyMarshalling(decorator) {
        const marshalling = resolveDecoratorArgMarshalling(decorator);
        function reportDeprecatedLegacyMarshalling(param, message) {
            reportDeprecated(program, [
                `Parameter ${param.name} of decorator ${decorator.name} is using legacy marshalling but is accepting ${message}.`,
                `This will change in the future.`,
                'Add `export const $flags = {decoratorArgMarshalling: "new"}}` to your library to opt-in to the new marshalling behavior.',
            ].join("\n"), param.node);
        }
        if (marshalling === "legacy") {
            for (const param of decorator.parameters) {
                if (param.type.valueType) {
                    if (ignoreDiagnostics(isTypeAssignableTo(nullType, param.type.valueType, param.type))) {
                        reportDeprecatedLegacyMarshalling(param, "null as a type");
                    }
                    else if (param.type.valueType.kind === "Enum" ||
                        param.type.valueType.kind === "EnumMember" ||
                        (isReflectionType(param.type.valueType) && param.type.valueType.name === "EnumMember")) {
                        reportDeprecatedLegacyMarshalling(param, "enum members");
                    }
                    else if (ignoreDiagnostics(isTypeAssignableTo(param.type.valueType, getStdType("numeric"), param.type.valueType)) &&
                        !canNumericConstraintBeJsNumber(param.type.valueType)) {
                        reportDeprecatedLegacyMarshalling(param, "a numeric type that is not representable as a JS Number");
                    }
                }
            }
        }
    }
    function checkFunctionDeclaration(node, mapper) {
        const symbol = getMergedSymbol(node.symbol);
        const links = getSymbolLinks(symbol);
        if (links.declaredType && mapper === undefined) {
            // we're not instantiating this operation and we've already checked it
            return links.declaredType;
        }
        const namespace = getParentNamespaceType(node);
        compilerAssert(namespace, `Decorator ${node.id.sv} should have resolved a namespace or found the global namespace.`);
        const name = node.id.sv;
        if (!(node.modifierFlags & 2 /* ModifierFlags.Extern */)) {
            reportCheckerDiagnostic(createDiagnostic({ code: "function-extern", target: node }));
        }
        const implementation = symbol.value;
        if (implementation === undefined) {
            reportCheckerDiagnostic(createDiagnostic({ code: "missing-implementation", target: node }));
        }
        const functionType = createType({
            kind: "Function",
            name,
            namespace,
            node,
            parameters: node.parameters.map((x) => checkFunctionParameter(x, mapper, true)),
            returnType: node.returnType ? getTypeForNode(node.returnType, mapper) : unknownType,
            implementation: implementation ?? (() => { }),
        });
        namespace.functionDeclarations.set(name, functionType);
        linkType(links, functionType, mapper);
        return functionType;
    }
    function checkFunctionParameter(node, mapper, mixed) {
        const links = getSymbolLinks(node.symbol);
        if (links.declaredType) {
            return links.declaredType;
        }
        if (node.rest &&
            node.type &&
            !(node.type.kind === SyntaxKind.ArrayExpression ||
                (node.type.kind === SyntaxKind.ValueOfExpression &&
                    node.type.target.kind === SyntaxKind.ArrayExpression))) {
            reportCheckerDiagnostic(createDiagnostic({ code: "rest-parameter-array", target: node.type }));
        }
        const base = {
            kind: "FunctionParameter",
            node,
            name: node.id.sv,
            optional: node.optional,
            rest: node.rest,
            implementation: node.symbol.value,
        };
        let parameterType;
        if (mixed) {
            const type = node.type
                ? getParamConstraintEntityForNode(node.type)
                : {
                    entityKind: "MixedParameterConstraint",
                    type: unknownType,
                };
            parameterType = createType({
                ...base,
                type,
                mixed: true,
                implementation: node.symbol.value,
            });
        }
        else {
            parameterType = createType({
                ...base,
                mixed: false,
                type: node.type ? getTypeForNode(node.type) : unknownType,
                implementation: node.symbol.value,
            });
        }
        linkType(links, parameterType, mapper);
        return parameterType;
    }
    function getTypeOrValueOfTypeForNode(node, mapper) {
        switch (node.kind) {
            case SyntaxKind.ValueOfExpression:
                const target = getTypeForNode(node.target, mapper);
                return ["value", target];
            default:
                return ["type", getTypeForNode(node, mapper)];
        }
    }
    function getParamConstraintEntityForNode(node, mapper) {
        switch (node.kind) {
            case SyntaxKind.UnionExpression:
                return checkMixedParameterConstraintUnion(node, mapper);
            default:
                const [kind, entity] = getTypeOrValueOfTypeForNode(node, mapper);
                return {
                    entityKind: "MixedParameterConstraint",
                    node: node,
                    type: kind === "value" ? undefined : entity,
                    valueType: kind === "value" ? entity : undefined,
                };
        }
    }
    function mergeModelTypes(node, options, mapper) {
        const properties = createRekeyableMap();
        const intersection = createType({
            kind: "Model",
            node,
            name: "",
            namespace: getParentNamespaceType(node),
            properties: properties,
            decorators: [],
            derivedModels: [],
            sourceModels: [],
        });
        const indexers = [];
        const modelOptions = options.filter((entry) => {
            const [optionNode, option] = entry;
            if (option.kind === "TemplateParameter") {
                return false;
            }
            if (option.kind !== "Model") {
                reportCheckerDiagnostic(createDiagnostic({ code: "intersect-non-model", target: optionNode }));
                return false;
            }
            return true;
        });
        for (const [optionNode, option] of modelOptions) {
            if (option.indexer) {
                if (option.indexer.key.name === "integer") {
                    reportCheckerDiagnostic(createDiagnostic({
                        code: "intersect-invalid-index",
                        messageId: "array",
                        target: optionNode,
                    }));
                }
                else {
                    indexers.push(option.indexer);
                }
            }
        }
        for (const [_, option] of modelOptions) {
            intersection.sourceModels.push({ usage: "intersection", model: option });
            const allProps = walkPropertiesInherited(option);
            for (const prop of allProps) {
                if (properties.has(prop.name)) {
                    reportCheckerDiagnostic(createDiagnostic({
                        code: "intersect-duplicate-property",
                        format: { propName: prop.name },
                        target: node,
                    }));
                    continue;
                }
                const newPropType = cloneType(prop, {
                    sourceProperty: prop,
                    model: intersection,
                });
                properties.set(prop.name, newPropType);
                for (const indexer of indexers.filter((x) => x !== option.indexer)) {
                    checkPropertyCompatibleWithIndexer(indexer, prop, node);
                }
            }
        }
        if (indexers.length === 1) {
            intersection.indexer = indexers[0];
        }
        else if (indexers.length > 1) {
            intersection.indexer = {
                key: indexers[0].key,
                value: mergeModelTypes(node, indexers.map((x) => [x.value.node, x.value]), mapper),
            };
        }
        linkMapper(intersection, mapper);
        return finishType(intersection);
    }
    function checkArrayExpression(node, mapper) {
        const elementType = getTypeForNode(node.elementType, mapper);
        const arrayType = getStdType("Array");
        const arrayNode = arrayType.node;
        const param = getTypeForNode(arrayNode.templateParameters[0]);
        return getOrInstantiateTemplate(arrayNode, [param], [elementType], undefined);
    }
    function checkNamespace(node) {
        const links = getSymbolLinks(getMergedSymbol(node.symbol));
        let type = links.type;
        if (!type) {
            type = initializeTypeForNamespace(node);
        }
        if (node.kind === SyntaxKind.NamespaceStatement) {
            if (isArray(node.statements)) {
                node.statements.forEach((x) => checkNode(x));
            }
            else if (node.statements) {
                const subNs = checkNamespace(node.statements);
                type.namespaces.set(subNs.name, subNs);
            }
        }
        return type;
    }
    function initializeTypeForNamespace(node) {
        compilerAssert(node.symbol, "Namespace is unbound.", node);
        const mergedSymbol = getMergedSymbol(node.symbol);
        const symbolLinks = getSymbolLinks(mergedSymbol);
        if (!symbolLinks.type) {
            // haven't seen this namespace before
            const namespace = getParentNamespaceType(node);
            const name = node.id.sv;
            const type = createType({
                kind: "Namespace",
                name,
                namespace,
                node: node,
                models: new Map(),
                scalars: new Map(),
                operations: new Map(),
                namespaces: new Map(),
                interfaces: new Map(),
                unions: new Map(),
                enums: new Map(),
                decoratorDeclarations: new Map(),
                functionDeclarations: new Map(),
                decorators: [],
            });
            symbolLinks.type = type;
            for (const sourceNode of mergedSymbol.declarations) {
                // namespaces created from TypeSpec scripts don't have decorators
                if (sourceNode.kind !== SyntaxKind.NamespaceStatement)
                    continue;
                type.decorators = type.decorators.concat(checkDecorators(type, sourceNode, undefined));
            }
            finishType(type);
            namespace?.namespaces.set(name, type);
        }
        return symbolLinks.type;
    }
    function getParentNamespaceType(node) {
        if (node === globalNamespaceType.node)
            return undefined;
        if (node.kind === SyntaxKind.ModelExpression ||
            node.kind === SyntaxKind.IntersectionExpression) {
            let parent = node.parent;
            while (parent !== undefined) {
                if (parent.kind === SyntaxKind.ModelStatement ||
                    parent.kind === SyntaxKind.ScalarStatement ||
                    parent.kind === SyntaxKind.OperationStatement ||
                    parent.kind === SyntaxKind.EnumStatement ||
                    parent.kind === SyntaxKind.InterfaceStatement ||
                    parent.kind === SyntaxKind.UnionStatement ||
                    parent.kind === SyntaxKind.ModelExpression ||
                    parent.kind === SyntaxKind.IntersectionExpression) {
                    return getParentNamespaceType(parent);
                }
                else {
                    parent = parent.parent;
                }
            }
            return undefined;
        }
        if (node.kind === SyntaxKind.OperationStatement &&
            node.parent &&
            node.parent.kind === SyntaxKind.InterfaceStatement) {
            return getParentNamespaceType(node.parent);
        }
        if (!node.symbol.parent) {
            return globalNamespaceType;
        }
        if (node.symbol.parent.declarations[0].kind === SyntaxKind.TypeSpecScript ||
            node.symbol.parent.declarations[0].kind === SyntaxKind.JsSourceFile) {
            return globalNamespaceType;
        }
        const mergedSymbol = getMergedSymbol(node.symbol.parent);
        const symbolLinks = getSymbolLinks(mergedSymbol);
        if (!symbolLinks.type) {
            // in general namespaces should be typed before anything calls this function.
            // However, one case where this is not true is when a decorator on a namespace
            // refers to a model in another namespace. In this case, we need to evaluate
            // the namespace here.
            const namespaceNode = mergedSymbol.declarations.find((x) => x.kind === SyntaxKind.NamespaceStatement || x.kind === SyntaxKind.JsNamespaceDeclaration);
            compilerAssert(namespaceNode, "Can't find namespace declaration node.", node);
            symbolLinks.type = initializeTypeForNamespace(namespaceNode);
        }
        return symbolLinks.type;
    }
    function checkOperation(node, mapper, parentInterface) {
        const inInterface = node.parent?.kind === SyntaxKind.InterfaceStatement;
        const symbol = inInterface ? getSymbolForMember(node) : node.symbol;
        const links = symbol && getSymbolLinks(symbol);
        if (links) {
            if (links.declaredType && mapper === undefined) {
                // we're not instantiating this operation and we've already checked it
                return links.declaredType;
            }
        }
        if (mapper === undefined && inInterface) {
            compilerAssert(parentInterface, "Operation in interface should already have been checked.", node.parent);
        }
        checkTemplateDeclaration(node, mapper);
        // If we are instantating operation inside of interface
        if (isTemplatedNode(node) && mapper !== undefined && parentInterface) {
            mapper = { ...mapper, partial: true };
        }
        const namespace = getParentNamespaceType(node);
        const name = node.id.sv;
        let decorators = [];
        const parameterModelSym = getOrCreateAugmentedSymbolTable(symbol.metatypeMembers).get("parameters");
        if (parameterModelSym?.members) {
            const members = getOrCreateAugmentedSymbolTable(parameterModelSym.members);
            const paramDocs = extractParamDocs(node);
            for (const [name, memberSym] of members) {
                const doc = paramDocs.get(name);
                if (doc) {
                    docFromCommentForSym.set(memberSym, doc);
                }
            }
        }
        // Is this a definition or reference?
        let parameters, returnType, sourceOperation;
        if (node.signature.kind === SyntaxKind.OperationSignatureReference) {
            // Attempt to resolve the operation
            const baseOperation = checkOperationIs(node, node.signature.baseOperation, mapper);
            if (baseOperation) {
                sourceOperation = baseOperation;
                // Reference the same return type and create the parameters type
                const clone = initializeClone(baseOperation.parameters, {
                    properties: createRekeyableMap(),
                });
                clone.properties = createRekeyableMap(Array.from(baseOperation.parameters.properties.entries()).map(([key, prop]) => [
                    key,
                    cloneTypeForSymbol(getMemberSymbol(parameterModelSym, prop.name), prop, {
                        model: clone,
                        sourceProperty: prop,
                    }),
                ]));
                parameters = finishType(clone);
                returnType = baseOperation.returnType;
                // Copy decorators from the base operation, inserting the base decorators first
                decorators = [...baseOperation.decorators];
            }
            else {
                // If we can't resolve the signature we return an empty model.
                parameters = createAndFinishType({
                    kind: "Model",
                    name: "",
                    decorators: [],
                    properties: createRekeyableMap(),
                    derivedModels: [],
                    sourceModels: [],
                });
                returnType = voidType;
            }
        }
        else {
            parameters = getTypeForNode(node.signature.parameters, mapper);
            returnType = getTypeForNode(node.signature.returnType, mapper);
        }
        const operationType = createType({
            kind: "Operation",
            name,
            namespace,
            node,
            parameters,
            returnType,
            decorators,
            sourceOperation,
            interface: parentInterface,
        });
        if (links) {
            linkType(links, operationType, mapper);
        }
        decorators.push(...checkDecorators(operationType, node, mapper));
        operationType.parameters.namespace = namespace;
        const parent = node.parent;
        linkMapper(operationType, mapper);
        if (parent.kind === SyntaxKind.InterfaceStatement) {
            if (shouldCreateTypeForTemplate(parent, mapper) &&
                shouldCreateTypeForTemplate(node, mapper)) {
                finishType(operationType);
            }
        }
        else {
            if (shouldCreateTypeForTemplate(node, mapper)) {
                finishType(operationType);
            }
            if (mapper === undefined) {
                namespace?.operations.set(name, operationType);
            }
        }
        return operationType;
    }
    function checkOperationIs(operation, opReference, mapper) {
        if (!opReference)
            return undefined;
        // Ensure that we don't end up with a circular reference to the same operation
        const opSymId = getNodeSymId(operation);
        if (opSymId) {
            pendingResolutions.start(opSymId, ResolutionKind.BaseType);
        }
        const target = resolveTypeReferenceSym(opReference, mapper);
        if (target === undefined) {
            return undefined;
        }
        // Did we encounter a circular operation reference?
        if (pendingResolutions.has(getNodeSymId(target.declarations[0]), ResolutionKind.BaseType)) {
            if (mapper === undefined) {
                reportCheckerDiagnostic(createDiagnostic({
                    code: "circular-op-signature",
                    format: { typeName: target.declarations[0].id.sv },
                    target: opReference,
                }));
            }
            return undefined;
        }
        // Resolve the base operation type
        const baseOperation = checkTypeReferenceSymbol(target, opReference, mapper);
        if (opSymId) {
            pendingResolutions.finish(opSymId, ResolutionKind.BaseType);
        }
        if (isErrorType(baseOperation)) {
            return undefined;
        }
        // Was the wrong type referenced?
        if (baseOperation.kind !== "Operation") {
            reportCheckerDiagnostic(createDiagnostic({ code: "is-operation", target: opReference }));
            return;
        }
        return baseOperation;
    }
    function getGlobalNamespaceType() {
        return globalNamespaceType;
    }
    function getGlobalNamespaceNode() {
        return globalNamespaceNode;
    }
    function checkTupleExpression(node, mapper) {
        return createAndFinishType({
            kind: "Tuple",
            node: node,
            values: node.values.map((v) => getTypeForNode(v, mapper)),
        });
    }
    function getSymbolLinks(s) {
        const id = getSymbolId(s);
        if (symbolLinks.has(id)) {
            return symbolLinks.get(id);
        }
        const links = {};
        symbolLinks.set(id, links);
        return links;
    }
    function getSymbolId(s) {
        if (s.id === undefined) {
            mutate(s).id = currentSymbolId++;
        }
        return s.id;
    }
    function resolveIdentifierInTable(node, table, options) {
        if (!table) {
            return undefined;
        }
        table = augmentedSymbolTables.get(table) ?? table;
        let sym;
        if (options.resolveDecorators) {
            sym = table.get("@" + node.sv);
        }
        else {
            sym = table.get(node.sv);
        }
        if (!sym)
            return sym;
        if (sym.flags & 1048576 /* SymbolFlags.DuplicateUsing */) {
            reportAmbiguousIdentifier(node, [...(table.duplicates.get(sym) ?? [])]);
            return sym;
        }
        return getMergedSymbol(sym);
    }
    function reportAmbiguousIdentifier(node, symbols) {
        const duplicateNames = symbols.map((s) => getFullyQualifiedSymbolName(s, { useGlobalPrefixAtTopLevel: true }));
        reportCheckerDiagnostic(createDiagnostic({
            code: "ambiguous-symbol",
            format: { name: node.sv, duplicateNames: duplicateNames.join(", ") },
            target: node,
        }));
    }
    function resolveIdentifier(id, mapper) {
        let sym;
        const { node, kind } = getIdentifierContext(id);
        switch (kind) {
            case IdentifierKind.ModelExpressionProperty:
            case IdentifierKind.ObjectLiteralProperty:
                const model = getReferencedModel(node);
                if (model) {
                    sym = getMemberSymbol(model.node.symbol, id.sv);
                }
                else {
                    return undefined;
                }
                break;
            case IdentifierKind.ModelStatementProperty:
            case IdentifierKind.Declaration:
                if (node.symbol && (!isTemplatedNode(node) || mapper === undefined)) {
                    sym = getMergedSymbol(node.symbol);
                    break;
                }
                compilerAssert(node.parent, "Parent expected.");
                const containerType = getTypeOrValueForNode(node.parent, mapper);
                if (containerType === null || isValue(containerType)) {
                    return undefined;
                }
                if (isAnonymous(containerType)) {
                    return undefined; // member of anonymous type cannot be referenced.
                }
                lateBindMemberContainer(containerType);
                let container = node.parent.symbol;
                if (!container && "symbol" in containerType && containerType.symbol) {
                    container = containerType.symbol;
                }
                if (!container) {
                    return undefined;
                }
                lateBindMembers(containerType, container);
                sym = resolveIdentifierInTable(id, container.exports ?? container.members, defaultSymbolResolutionOptions);
                break;
            case IdentifierKind.Other:
                return undefined;
            case IdentifierKind.Decorator:
            case IdentifierKind.Function:
            case IdentifierKind.Using:
            case IdentifierKind.TypeReference:
                let ref = id;
                let resolveDecorator = kind === IdentifierKind.Decorator;
                if (id.parent?.kind === SyntaxKind.MemberExpression) {
                    if (id.parent.id === id) {
                        // If the identifier is Y in X.Y, then resolve (X.Y).
                        ref = id.parent;
                    }
                    else {
                        // If the identifier is X in X.Y then we are resolving a
                        // namespace, which is never a decorator.
                        resolveDecorator = false;
                    }
                }
                sym = resolveTypeReferenceSym(ref, mapper, resolveDecorator);
                break;
            case IdentifierKind.TemplateArgument:
                const templates = getTemplateDeclarationsForArgument(node, mapper);
                const firstMatchingParameter = templates
                    .flatMap((t) => t.templateParameters)
                    .find((p) => p.id.sv === id.sv);
                if (firstMatchingParameter) {
                    sym = getMergedSymbol(firstMatchingParameter.symbol);
                }
                break;
            default:
                compilerAssert(false, "Unreachable");
        }
        return sym?.symbolSource ?? sym;
    }
    function getTemplateDeclarationsForArgument(node, mapper) {
        const resolved = resolveTypeReferenceSym(node.parent, mapper, false);
        return (resolved?.declarations.filter((n) => isTemplatedNode(n)) ?? []);
    }
    function getReferencedModel(propertyNode) {
        const isModelOrArrayValue = (n) => n?.kind === SyntaxKind.ArrayLiteral || n?.kind === SyntaxKind.ObjectLiteral;
        const isModelOrArrayType = (n) => n?.kind === SyntaxKind.ModelExpression || n?.kind === SyntaxKind.TupleExpression;
        const isModelOrArray = (n) => isModelOrArrayValue(n) || isModelOrArrayType(n);
        const path = [];
        let preNode;
        const foundNode = getFirstAncestor(propertyNode, (n) => {
            pushToModelPath(n, preNode, path);
            preNode = n;
            return ((isModelOrArray(n) &&
                (n.parent?.kind === SyntaxKind.TemplateParameterDeclaration ||
                    n.parent?.kind === SyntaxKind.DecoratorExpression)) ||
                (isModelOrArrayValue(n) &&
                    (n.parent?.kind === SyntaxKind.CallExpression ||
                        n.parent?.kind === SyntaxKind.ConstStatement)));
        });
        let refType;
        switch (foundNode?.parent?.kind) {
            case SyntaxKind.TemplateParameterDeclaration:
                refType = getReferencedTypeFromTemplateDeclaration(foundNode);
                break;
            case SyntaxKind.DecoratorExpression:
                refType = getReferencedTypeFromDecoratorArgument(foundNode);
                break;
            case SyntaxKind.CallExpression:
                refType = getReferencedTypeFromScalarConstructor(foundNode);
                break;
            case SyntaxKind.ConstStatement:
                refType = getReferencedTypeFromConstAssignment(foundNode);
                break;
        }
        return refType?.kind === "Model" || refType?.kind === "Tuple"
            ? getNestedModel(refType, path)
            : undefined;
        function pushToModelPath(node, preNode, path) {
            if (node.kind === SyntaxKind.ArrayLiteral || node.kind === SyntaxKind.TupleExpression) {
                const index = node.values.findIndex((n) => n === preNode);
                if (index >= 0) {
                    path.unshift({ tupleIndex: index });
                }
                else {
                    compilerAssert(false, "not expected, can't find child from the parent?");
                }
            }
            if (node.kind === SyntaxKind.ModelProperty ||
                node.kind === SyntaxKind.ObjectLiteralProperty) {
                path.unshift({ propertyName: node.id.sv });
            }
        }
        function getNestedModel(modelOrTuple, path) {
            let cur = modelOrTuple;
            for (const seg of path) {
                switch (cur?.kind) {
                    case "Tuple":
                        if (seg.tupleIndex !== undefined &&
                            seg.tupleIndex >= 0 &&
                            seg.tupleIndex < cur.values.length) {
                            cur = cur.values[seg.tupleIndex];
                        }
                        else {
                            return undefined;
                        }
                        break;
                    case "Model":
                        if (cur.name === "Array" && seg.tupleIndex !== undefined) {
                            cur = cur.templateMapper?.args[0];
                        }
                        else if (cur.name !== "Array" && seg.propertyName) {
                            cur = cur.properties.get(seg.propertyName)?.type;
                        }
                        else {
                            return undefined;
                        }
                        break;
                    default:
                        return undefined;
                }
            }
            return cur?.kind === "Model" ? cur : undefined;
        }
        function getReferencedTypeFromTemplateDeclaration(dftNode) {
            const templateParmaeterDeclNode = dftNode?.parent;
            if (templateParmaeterDeclNode?.kind !== SyntaxKind.TemplateParameterDeclaration ||
                !templateParmaeterDeclNode.constraint ||
                !templateParmaeterDeclNode.default ||
                templateParmaeterDeclNode.default !== dftNode) {
                return undefined;
            }
            let constraintType;
            if (isModelOrArrayValue(dftNode) &&
                templateParmaeterDeclNode.constraint.kind === SyntaxKind.ValueOfExpression) {
                constraintType = program.checker.getTypeForNode(templateParmaeterDeclNode.constraint.target);
            }
            else if (isModelOrArrayType(dftNode) &&
                templateParmaeterDeclNode.constraint.kind !== SyntaxKind.ValueOfExpression) {
                constraintType = program.checker.getTypeForNode(templateParmaeterDeclNode.constraint);
            }
            return constraintType;
        }
        function getReferencedTypeFromScalarConstructor(argNode) {
            const callExpNode = argNode?.parent;
            if (callExpNode?.kind !== SyntaxKind.CallExpression) {
                return undefined;
            }
            const ctorType = checkCallExpressionTarget(callExpNode, undefined);
            if (ctorType?.kind !== "ScalarConstructor") {
                return undefined;
            }
            const argIndex = callExpNode.arguments.findIndex((n) => n === argNode);
            if (argIndex < 0 || argIndex >= ctorType.parameters.length) {
                return undefined;
            }
            const arg = ctorType.parameters[argIndex];
            return arg.type;
        }
        function getReferencedTypeFromConstAssignment(valueNode) {
            const constNode = valueNode?.parent;
            if (!constNode ||
                constNode.kind !== SyntaxKind.ConstStatement ||
                !constNode.type ||
                constNode.value !== valueNode) {
                return undefined;
            }
            return program.checker.getTypeForNode(constNode.type);
        }
        function getReferencedTypeFromDecoratorArgument(decArgNode) {
            const decNode = decArgNode?.parent;
            if (decNode?.kind !== SyntaxKind.DecoratorExpression) {
                return undefined;
            }
            const decSym = program.checker.resolveIdentifier(decNode.target.kind === SyntaxKind.MemberExpression ? decNode.target.id : decNode.target);
            if (!decSym) {
                return undefined;
            }
            const decDecl = decSym.declarations.find((x) => x.kind === SyntaxKind.DecoratorDeclarationStatement);
            if (!decDecl) {
                return undefined;
            }
            const decType = program.checker.getTypeForNode(decDecl);
            compilerAssert(decType.kind === "Decorator", "Expected type to be a Decorator.");
            const argIndex = decNode.arguments.findIndex((n) => n === decArgNode);
            if (argIndex < 0 || argIndex >= decType.parameters.length) {
                return undefined;
            }
            const decArg = decType.parameters[argIndex];
            let type;
            if (isModelOrArrayValue(decArgNode)) {
                type = decArg.type.valueType;
            }
            else if (isModelOrArrayType(decArgNode)) {
                type = decArg.type.type ?? decArg.type.valueType;
            }
            else {
                compilerAssert(false, "not expected node type to get reference model from decorator argument");
            }
            return type;
        }
    }
    function resolveCompletions(identifier) {
        const completions = new Map();
        const { kind, node: ancestor } = getIdentifierContext(identifier);
        switch (kind) {
            case IdentifierKind.Using:
            case IdentifierKind.Decorator:
            case IdentifierKind.Function:
            case IdentifierKind.TypeReference:
            case IdentifierKind.ModelExpressionProperty:
            case IdentifierKind.ModelStatementProperty:
            case IdentifierKind.ObjectLiteralProperty:
                break; // supported
            case IdentifierKind.Other:
                return completions; // not implemented
            case IdentifierKind.Declaration:
                return completions; // cannot complete, name can be chosen arbitrarily
            case IdentifierKind.TemplateArgument: {
                const templates = getTemplateDeclarationsForArgument(ancestor, undefined);
                for (const template of templates) {
                    for (const param of template.templateParameters) {
                        addCompletion(param.id.sv, param.symbol);
                    }
                }
                return completions;
            }
            default:
                compilerAssert(false, "Unreachable");
        }
        if (kind === IdentifierKind.ModelStatementProperty) {
            const model = ancestor.parent;
            const modelType = program.checker.getTypeForNode(model);
            const baseType = modelType.baseModel;
            const baseNode = baseType?.node;
            if (!baseNode) {
                return completions;
            }
            for (const prop of baseType.properties.values()) {
                if (identifier.sv === prop.name || !modelType.properties.has(prop.name)) {
                    const sym = getMemberSymbol(baseNode.symbol, prop.name);
                    if (sym) {
                        addCompletion(prop.name, sym);
                    }
                }
            }
        }
        else if (kind === IdentifierKind.ModelExpressionProperty ||
            kind === IdentifierKind.ObjectLiteralProperty) {
            const model = getReferencedModel(ancestor);
            if (!model) {
                return completions;
            }
            const curModelNode = ancestor.parent;
            for (const prop of walkPropertiesInherited(model)) {
                if (identifier.sv === prop.name ||
                    !curModelNode.properties.find((p) => (p.kind === SyntaxKind.ModelProperty ||
                        p.kind === SyntaxKind.ObjectLiteralProperty) &&
                        p.id.sv === prop.name)) {
                    const sym = getMemberSymbol(model.node.symbol, prop.name);
                    if (sym) {
                        addCompletion(prop.name, sym);
                    }
                }
            }
        }
        else if (identifier.parent && identifier.parent.kind === SyntaxKind.MemberExpression) {
            let base = resolveTypeReferenceSym(identifier.parent.base, undefined, false);
            if (base) {
                if (base.flags & 2048 /* SymbolFlags.Alias */) {
                    base = getAliasedSymbol(base, undefined, defaultSymbolResolutionOptions);
                }
                if (base) {
                    if (isTemplatedNode(base.declarations[0])) {
                        const type = base.type ?? getTypeForNode(base.declarations[0], undefined);
                        if (isTemplateInstance(type)) {
                            lateBindMemberContainer(type);
                            lateBindMembers(type, base);
                        }
                    }
                    addCompletions(base.exports ?? base.members);
                }
            }
        }
        else {
            // We will only add template arguments if the template isn't already named
            // to avoid completing the name of the argument again.
            if (kind === IdentifierKind.TypeReference &&
                exprIsBareIdentifier(ancestor) &&
                ancestor.parent?.kind === SyntaxKind.TemplateArgument &&
                ancestor.parent.name === undefined) {
                const templates = getTemplateDeclarationsForArgument(ancestor.parent, undefined);
                for (const template of templates) {
                    for (const param of template.templateParameters) {
                        addCompletion(param.id.sv, param.symbol, { suffix: " = " });
                    }
                }
            }
            let scope = identifier.parent;
            while (scope && scope.kind !== SyntaxKind.TypeSpecScript) {
                if (scope.symbol && scope.symbol.exports) {
                    const mergedSymbol = getMergedSymbol(scope.symbol);
                    addCompletions(mergedSymbol.exports);
                }
                if ("locals" in scope) {
                    addCompletions(scope.locals);
                }
                scope = scope.parent;
            }
            if (scope && scope.kind === SyntaxKind.TypeSpecScript) {
                // check any blockless namespace decls
                for (const ns of scope.inScopeNamespaces) {
                    const mergedSymbol = getMergedSymbol(ns.symbol);
                    addCompletions(mergedSymbol.exports);
                }
                // check "global scope" declarations
                addCompletions(globalNamespaceNode.symbol.exports);
                // check "global scope" usings
                addCompletions(scope.locals);
            }
        }
        return completions;
        function addCompletions(table) {
            if (!table) {
                return;
            }
            table = augmentedSymbolTables.get(table) ?? table;
            for (const [key, sym] of table) {
                if (sym.flags & 1048576 /* SymbolFlags.DuplicateUsing */) {
                    const duplicates = table.duplicates.get(sym);
                    for (const duplicate of duplicates) {
                        if (duplicate.flags & 524288 /* SymbolFlags.Using */) {
                            const fqn = getFullyQualifiedSymbolName(duplicate.symbolSource);
                            addCompletion(fqn, duplicate);
                        }
                    }
                }
                else {
                    addCompletion(key, sym);
                }
            }
        }
        function addCompletion(key, sym, options = {}) {
            if (sym.symbolSource) {
                sym = sym.symbolSource;
            }
            if (!shouldAddCompletion(sym)) {
                return;
            }
            if (key.startsWith("@")) {
                key = key.slice(1);
            }
            if (!completions.has(key)) {
                completions.set(key, { ...options, sym });
            }
        }
        function shouldAddCompletion(sym) {
            switch (kind) {
                case IdentifierKind.ModelExpressionProperty:
                case IdentifierKind.ModelStatementProperty:
                case IdentifierKind.ObjectLiteralProperty:
                    return !!(sym.flags & 4 /* SymbolFlags.ModelProperty */);
                case IdentifierKind.Decorator:
                    // Only return decorators and namespaces when completing decorator
                    return !!(sym.flags & (16384 /* SymbolFlags.Decorator */ | 4096 /* SymbolFlags.Namespace */));
                case IdentifierKind.Using:
                    // Only return namespaces when completing using
                    return !!(sym.flags & 4096 /* SymbolFlags.Namespace */);
                case IdentifierKind.TypeReference:
                    // Do not return functions or decorators when completing types
                    return !(sym.flags & (131072 /* SymbolFlags.Function */ | 16384 /* SymbolFlags.Decorator */));
                case IdentifierKind.TemplateArgument:
                    return !!(sym.flags & 32768 /* SymbolFlags.TemplateParameter */);
                default:
                    compilerAssert(false, "We should have bailed up-front on other kinds.");
            }
        }
    }
    function resolveIdentifierInScope(node, mapper, options) {
        compilerAssert(node.parent?.kind !== SyntaxKind.MemberExpression || node.parent.id !== node, "This function should not be used to resolve Y in member expression X.Y. Use resolveIdentifier() to resolve an arbitrary identifier.");
        if (hasParseError(node)) {
            // Don't report synthetic identifiers used for parser error recovery.
            // The parse error is the root cause and will already have been logged.
            return undefined;
        }
        let scope = node.parent;
        let binding;
        while (scope && scope.kind !== SyntaxKind.TypeSpecScript) {
            if (scope.symbol && "exports" in scope.symbol) {
                const mergedSymbol = getMergedSymbol(scope.symbol);
                binding = resolveIdentifierInTable(node, mergedSymbol.exports, options);
                if (binding)
                    return binding;
            }
            if ("locals" in scope) {
                binding = resolveIdentifierInTable(node, scope.locals, options);
                if (binding)
                    return binding;
            }
            scope = scope.parent;
        }
        if (!binding && scope && scope.kind === SyntaxKind.TypeSpecScript) {
            // check any blockless namespace decls
            for (const ns of scope.inScopeNamespaces) {
                const mergedSymbol = getMergedSymbol(ns.symbol);
                binding = resolveIdentifierInTable(node, mergedSymbol.exports, options);
                if (binding)
                    return binding;
            }
            // check "global scope" declarations
            const globalBinding = resolveIdentifierInTable(node, globalNamespaceNode.symbol.exports, options);
            // check using types
            const usingBinding = resolveIdentifierInTable(node, scope.locals, options);
            if (globalBinding && usingBinding) {
                reportAmbiguousIdentifier(node, [globalBinding, usingBinding]);
                return globalBinding;
            }
            else if (globalBinding) {
                return globalBinding;
            }
            else if (usingBinding) {
                return usingBinding.flags & 1048576 /* SymbolFlags.DuplicateUsing */ ? undefined : usingBinding;
            }
        }
        if (mapper === undefined) {
            reportCheckerDiagnostic(createDiagnostic({
                code: "unknown-identifier",
                format: { id: node.sv },
                target: node,
                codefixes: getCodefixesForUnknownIdentifier(node),
            }));
        }
        return undefined;
    }
    function getCodefixesForUnknownIdentifier(node) {
        switch (node.sv) {
            case "number":
                return [createChangeIdentifierCodeFix(node, "float64")];
            default:
                return undefined;
        }
    }
    function resolveTypeReferenceSym(node, mapper, options) {
        const resolvedOptions = typeof options === "boolean"
            ? { ...defaultSymbolResolutionOptions, resolveDecorators: options }
            : { ...defaultSymbolResolutionOptions, ...(options ?? {}) };
        if (mapper === undefined && resolvedOptions.checkTemplateTypes && referenceSymCache.has(node)) {
            return referenceSymCache.get(node);
        }
        const sym = resolveTypeReferenceSymInternal(node, mapper, resolvedOptions);
        if (resolvedOptions.checkTemplateTypes) {
            referenceSymCache.set(node, sym);
        }
        return sym;
    }
    function resolveTypeReferenceSymInternal(node, mapper, options) {
        if (hasParseError(node)) {
            // Don't report synthetic identifiers used for parser error recovery.
            // The parse error is the root cause and will already have been logged.
            return undefined;
        }
        if (node.kind === SyntaxKind.TypeReference) {
            return resolveTypeReferenceSym(node.target, mapper, options);
        }
        if (node.kind === SyntaxKind.MemberExpression) {
            let base = resolveTypeReferenceSym(node.base, mapper);
            if (!base) {
                return undefined;
            }
            // when resolving a type reference based on an alias, unwrap the alias.
            if (base.flags & 2048 /* SymbolFlags.Alias */) {
                const aliasedSym = getAliasedSymbol(base, mapper, options);
                if (!aliasedSym) {
                    reportCheckerDiagnostic(createDiagnostic({
                        code: "invalid-ref",
                        messageId: "node",
                        format: {
                            id: node.id.sv,
                            nodeName: base.declarations[0]
                                ? SyntaxKind[base.declarations[0].kind]
                                : "Unknown node",
                        },
                        target: node,
                    }));
                    return undefined;
                }
                base = aliasedSym;
            }
            if (node.selector === ".") {
                return resolveMemberInContainer(node, base, mapper, options);
            }
            else {
                return resolveMetaProperty(node, base);
            }
        }
        if (node.kind === SyntaxKind.Identifier) {
            const sym = resolveIdentifierInScope(node, mapper, options);
            if (!sym)
                return undefined;
            return sym.flags & 524288 /* SymbolFlags.Using */ ? sym.symbolSource : sym;
        }
        compilerAssert(false, `Unknown type reference kind "${SyntaxKind[node.kind]}"`, node);
    }
    function resolveMemberInContainer(node, base, mapper, options) {
        if (base.flags & 4096 /* SymbolFlags.Namespace */) {
            const symbol = resolveIdentifierInTable(node.id, base.exports, options);
            if (!symbol) {
                reportCheckerDiagnostic(createDiagnostic({
                    code: "invalid-ref",
                    messageId: "underNamespace",
                    format: {
                        namespace: getFullyQualifiedSymbolName(base),
                        id: node.id.sv,
                    },
                    target: node,
                }));
                return undefined;
            }
            return symbol;
        }
        else if (base.flags & 16384 /* SymbolFlags.Decorator */) {
            reportCheckerDiagnostic(createDiagnostic({
                code: "invalid-ref",
                messageId: "inDecorator",
                format: { id: node.id.sv },
                target: node,
            }));
            return undefined;
        }
        else if (base.flags & 131072 /* SymbolFlags.Function */) {
            reportCheckerDiagnostic(createDiagnostic({
                code: "invalid-ref",
                messageId: "node",
                format: { id: node.id.sv, nodeName: "function" },
                target: node,
            }));
            return undefined;
        }
        else if (base.flags & 682 /* SymbolFlags.MemberContainer */) {
            if (options.checkTemplateTypes && isTemplatedNode(base.declarations[0])) {
                const type = base.flags & 67108864 /* SymbolFlags.LateBound */
                    ? base.type
                    : getTypeForNode(base.declarations[0], mapper);
                if (isTemplateInstance(type)) {
                    lateBindMembers(type, base);
                }
            }
            const sym = resolveIdentifierInTable(node.id, base.members, options);
            if (!sym) {
                reportCheckerDiagnostic(createDiagnostic({
                    code: "invalid-ref",
                    messageId: "underContainer",
                    format: { kind: getMemberKindName(base.declarations[0]), id: node.id.sv },
                    target: node,
                }));
                return undefined;
            }
            return sym;
        }
        else {
            reportCheckerDiagnostic(createDiagnostic({
                code: "invalid-ref",
                messageId: "node",
                format: {
                    id: node.id.sv,
                    nodeName: base.declarations[0] ? SyntaxKind[base.declarations[0].kind] : "Unknown node",
                },
                target: node,
            }));
            return undefined;
        }
    }
    function resolveMetaProperty(node, base) {
        const resolved = resolveIdentifierInTable(node.id, base.metatypeMembers, {
            resolveDecorators: false,
            checkTemplateTypes: false,
        });
        if (!resolved) {
            reportCheckerDiagnostic(createDiagnostic({
                code: "invalid-ref",
                messageId: "metaProperty",
                format: { kind: getMemberKindName(base.declarations[0]), id: node.id.sv },
                target: node,
            }));
        }
        return resolved;
    }
    function getMemberKindName(node) {
        switch (node.kind) {
            case SyntaxKind.ModelStatement:
            case SyntaxKind.ModelExpression:
                return "Model";
            case SyntaxKind.ModelProperty:
                return "ModelProperty";
            case SyntaxKind.EnumStatement:
                return "Enum";
            case SyntaxKind.InterfaceStatement:
                return "Interface";
            case SyntaxKind.UnionStatement:
                return "Union";
            default:
                return "Type";
        }
    }
    /**
     * Return the symbol that is aliased by this alias declaration. If no such symbol is aliased,
     * return the symbol for the alias instead. For member containers which need to be late bound
     * (i.e. they contain symbols we don't know until we've instantiated the type and the type is an
     * instantiation) we late bind the container which creates the symbol that will hold its members.
     */
    function getAliasedSymbol(aliasSymbol, mapper, options) {
        let current = aliasSymbol;
        while (current.flags & 2048 /* SymbolFlags.Alias */) {
            const node = current.declarations[0];
            const targetNode = node.kind === SyntaxKind.AliasStatement ? node.value : node;
            if (targetNode.kind === SyntaxKind.TypeReference ||
                targetNode.kind === SyntaxKind.MemberExpression ||
                targetNode.kind === SyntaxKind.Identifier) {
                const sym = resolveTypeReferenceSymInternal(targetNode, mapper, options);
                if (sym === undefined) {
                    return undefined;
                }
                current = sym;
            }
            else {
                return undefined;
            }
        }
        const sym = current;
        const node = aliasSymbol.declarations[0];
        const resolvedTargetNode = sym.declarations[0];
        if (!options.checkTemplateTypes || !isTemplatedNode(resolvedTargetNode)) {
            return sym;
        }
        const aliasType = getTypeForNode(node, mapper);
        if (isErrorType(aliasType)) {
            return undefined;
        }
        switch (aliasType.kind) {
            case "Model":
            case "Interface":
            case "Union":
                if (isTemplateInstance(aliasType)) {
                    // this is an alias for some instantiation, so late-bind the instantiation
                    lateBindMemberContainer(aliasType);
                    return aliasType.symbol;
                }
            // fallthrough
            default:
                // get the symbol from the node aliased type's node, or just return the base
                // if it doesn't have a symbol (which will likely result in an error later on)
                return getMergedSymbol(aliasType.node.symbol) ?? aliasSymbol;
        }
    }
    function checkStringTemplateExpresion(node, mapper) {
        let hasType = false;
        let hasValue = false;
        const spanTypeOrValues = node.spans.map((span) => [span, checkNode(span.expression, mapper)]);
        for (const [_, typeOrValue] of spanTypeOrValues) {
            if (typeOrValue !== null) {
                if (isValue(typeOrValue)) {
                    hasValue = true;
                }
                else if ("kind" in typeOrValue && typeOrValue.kind === "TemplateParameter") {
                    if (typeOrValue.constraint) {
                        if (typeOrValue.constraint.valueType) {
                            hasValue = true;
                        }
                        if (typeOrValue.constraint.type) {
                            hasType = true;
                        }
                    }
                    else {
                        hasType = true;
                    }
                }
                else {
                    hasType = true;
                }
            }
        }
        if (hasType && hasValue) {
            reportCheckerDiagnostic(createDiagnostic({
                code: "mixed-string-template",
                target: node,
            }));
            return null;
        }
        if (hasValue) {
            let str = node.head.value;
            for (const [span, typeOrValue] of spanTypeOrValues) {
                if (typeOrValue !== null &&
                    (!("kind" in typeOrValue) || typeOrValue.kind !== "TemplateParameter")) {
                    compilerAssert(typeOrValue !== null && isValue(typeOrValue), "Expected value.");
                    str += stringifyValueForTemplate(typeOrValue);
                }
                str += span.literal.value;
            }
            return checkStringValue(createLiteralType(str), undefined, node);
        }
        else {
            let hasNonStringElement = false;
            let stringValue = node.head.value;
            const spans = [createTemplateSpanLiteral(node.head)];
            for (const [span, typeOrValue] of spanTypeOrValues) {
                compilerAssert(typeOrValue !== null && !isValue(typeOrValue), "Expected type.");
                const type = typeOrValue.entityKind === "Indeterminate" ? typeOrValue.type : typeOrValue;
                const spanValue = createTemplateSpanValue(span.expression, type);
                spans.push(spanValue);
                const spanValueAsString = stringifyTypeForTemplate(type);
                if (spanValueAsString) {
                    stringValue += spanValueAsString;
                }
                else {
                    hasNonStringElement = true;
                }
                spans.push(createTemplateSpanLiteral(span.literal));
                stringValue += span.literal.value;
            }
            return createIndeterminateEntity(createType({
                kind: "StringTemplate",
                node,
                spans,
                stringValue: hasNonStringElement ? undefined : stringValue,
            }));
        }
    }
    function createIndeterminateEntity(type) {
        return {
            entityKind: "Indeterminate",
            type,
        };
    }
    function stringifyTypeForTemplate(type) {
        switch (type.kind) {
            case "String":
            case "Number":
            case "Boolean":
                return String(type.value);
            case "StringTemplate":
                if (type.stringValue !== undefined) {
                    return type.stringValue;
                }
                return undefined;
            default:
                return undefined;
        }
    }
    function stringifyValueForTemplate(value) {
        switch (value.valueKind) {
            case "StringValue":
            case "NumericValue":
            case "BooleanValue":
                return value.value.toString();
            default:
                reportCheckerDiagnostic(createDiagnostic({
                    code: "non-literal-string-template",
                    target: value,
                }));
                return `[${value.valueKind}]`;
        }
    }
    function createTemplateSpanLiteral(node) {
        return createType({
            kind: "StringTemplateSpan",
            node: node,
            isInterpolated: false,
            type: getLiteralType(node),
        });
    }
    function createTemplateSpanValue(node, type) {
        return createType({
            kind: "StringTemplateSpan",
            node: node,
            isInterpolated: true,
            type: type,
        });
    }
    function checkStringLiteral(str) {
        return {
            entityKind: "Indeterminate",
            type: getLiteralType(str),
        };
    }
    function checkNumericLiteral(num) {
        return {
            entityKind: "Indeterminate",
            type: getLiteralType(num),
        };
    }
    function checkBooleanLiteral(bool) {
        return {
            entityKind: "Indeterminate",
            type: getLiteralType(bool),
        };
    }
    function checkProgram() {
        program.reportDuplicateSymbols(globalNamespaceNode.symbol.exports);
        for (const file of program.sourceFiles.values()) {
            bindAllMembers(file);
        }
        for (const file of program.sourceFiles.values()) {
            bindMetaTypes(file);
        }
        for (const file of program.sourceFiles.values()) {
            for (const ns of file.namespaces) {
                const exports = mergedSymbols.get(ns.symbol)?.exports ?? ns.symbol.exports;
                program.reportDuplicateSymbols(exports);
                initializeTypeForNamespace(ns);
            }
        }
        for (const file of program.sourceFiles.values()) {
            applyAugmentDecoratorsInScope(file);
        }
        for (const file of program.sourceFiles.values()) {
            checkSourceFile(file);
        }
        internalDecoratorValidation();
    }
    /**
     * Post checking validation for internal decorators.
     */
    function internalDecoratorValidation() {
        validateInheritanceDiscriminatedUnions(program);
    }
    function applyAugmentDecoratorsInScope(scope) {
        applyAugmentDecorators(scope);
        if (scope.statements === undefined) {
            return;
        }
        if (isArray(scope.statements)) {
            for (const statement of scope.statements) {
                if (statement.kind === SyntaxKind.NamespaceStatement) {
                    applyAugmentDecoratorsInScope(statement);
                }
            }
        }
        else {
            applyAugmentDecoratorsInScope(scope.statements);
        }
    }
    function checkSourceFile(file) {
        for (const statement of file.statements) {
            checkNode(statement, undefined);
        }
    }
    /**
     * Check that the given node template parameters are valid if applicable.
     * @param node Node with template parameters
     * @param mapper Type mapper, set if instantiating the template, undefined otherwise.
     */
    function checkTemplateDeclaration(node, mapper) {
        // If mapper is undefined it means we are checking the declaration of the template.
        if (mapper === undefined) {
            for (const templateParameter of node.templateParameters) {
                checkTemplateParameterDeclaration(templateParameter, undefined);
            }
        }
    }
    function checkModel(node, mapper) {
        if (node.kind === SyntaxKind.ModelStatement) {
            return checkModelStatement(node, mapper);
        }
        else {
            return checkModelExpression(node, mapper);
        }
    }
    function checkModelStatement(node, mapper) {
        const links = getSymbolLinks(node.symbol);
        if (links.declaredType && mapper === undefined) {
            // we're not instantiating this model and we've already checked it
            return links.declaredType;
        }
        checkTemplateDeclaration(node, mapper);
        const decorators = [];
        const type = createType({
            kind: "Model",
            name: node.id.sv,
            node: node,
            properties: createRekeyableMap(),
            namespace: getParentNamespaceType(node),
            decorators,
            sourceModels: [],
            derivedModels: [],
        });
        linkType(links, type, mapper);
        if (node.symbol.members) {
            const members = getOrCreateAugmentedSymbolTable(node.symbol.members);
            const propDocs = extractPropDocs(node);
            for (const [name, memberSym] of members) {
                const doc = propDocs.get(name);
                if (doc) {
                    docFromCommentForSym.set(memberSym, doc);
                }
            }
        }
        const isBase = checkModelIs(node, node.is, mapper);
        if (isBase) {
            type.sourceModel = isBase;
            type.sourceModels.push({ usage: "is", model: isBase });
            // copy decorators
            decorators.push(...isBase.decorators);
            if (isBase.indexer) {
                type.indexer = isBase.indexer;
            }
        }
        decorators.push(...checkDecorators(type, node, mapper));
        if (isBase) {
            for (const prop of isBase.properties.values()) {
                const memberSym = getMemberSymbol(node.symbol, prop.name);
                const newProp = cloneTypeForSymbol(memberSym, prop, {
                    sourceProperty: prop,
                    model: type,
                });
                linkIndirectMember(node, newProp, mapper);
                type.properties.set(prop.name, newProp);
            }
        }
        if (isBase) {
            type.baseModel = isBase.baseModel;
        }
        else if (node.extends) {
            type.baseModel = checkClassHeritage(node, node.extends, mapper);
            if (type.baseModel) {
                copyDeprecation(type.baseModel, type);
            }
        }
        if (type.baseModel) {
            type.baseModel.derivedModels.push(type);
        }
        // Hold on to the model type that's being defined so that it
        // can be referenced
        if (mapper === undefined) {
            type.namespace?.models.set(type.name, type);
        }
        // Evaluate the properties after
        checkModelProperties(node, type.properties, type, mapper);
        linkMapper(type, mapper);
        if (shouldCreateTypeForTemplate(node, mapper)) {
            finishType(type);
        }
        const indexer = getIndexer(program, type);
        if (type.name === "Array" && isInTypeSpecNamespace(type)) {
            stdTypes.Array = type;
        }
        else if (type.name === "Record" && isInTypeSpecNamespace(type)) {
            stdTypes.Record = type;
        }
        if (indexer) {
            type.indexer = indexer;
        }
        return type;
    }
    function shouldCreateTypeForTemplate(node, mapper) {
        // Node is not a template we should create the type.
        if (node.templateParameters.length === 0) {
            return true;
        }
        // There is no mapper so we shouldn't be instantiating the template.
        if (mapper === undefined) {
            return false;
        }
        // Some of the mapper args are still template parameter so we shouldn't create the type.
        return (!mapper.partial &&
            mapper.args.every((t) => isValue(t) || t.entityKind === "Indeterminate" || t.kind !== "TemplateParameter"));
    }
    function checkModelExpression(node, mapper) {
        const properties = createRekeyableMap();
        const type = createType({
            kind: "Model",
            name: "",
            node: node,
            properties,
            indexer: undefined,
            namespace: getParentNamespaceType(node),
            decorators: [],
            derivedModels: [],
            sourceModels: [],
        });
        checkModelProperties(node, properties, type, mapper);
        return finishType(type);
    }
    /** Find the indexer that applies to this model. Either defined on itself or from a base model */
    function findIndexer(model) {
        let current = model;
        while (current) {
            if (current.indexer) {
                return current.indexer;
            }
            current = current.baseModel;
        }
        return undefined;
    }
    function checkPropertyCompatibleWithModelIndexer(parentModel, property, diagnosticTarget) {
        const indexer = findIndexer(parentModel);
        if (indexer === undefined) {
            return;
        }
        return checkPropertyCompatibleWithIndexer(indexer, property, diagnosticTarget);
    }
    function checkPropertyCompatibleWithIndexer(indexer, property, diagnosticTarget) {
        if (indexer.key.name === "integer") {
            reportCheckerDiagnostics([
                createDiagnostic({
                    code: "no-array-properties",
                    target: diagnosticTarget,
                }),
            ]);
            return;
        }
        const [valid, diagnostics] = isTypeAssignableTo(property.type, indexer.value, diagnosticTarget);
        if (!valid)
            reportCheckerDiagnostic(createDiagnostic({
                code: "incompatible-indexer",
                format: { message: diagnostics.map((x) => `  ${x.message}`).join("\n") },
                target: diagnosticTarget.kind === SyntaxKind.ModelProperty
                    ? diagnosticTarget.value
                    : diagnosticTarget,
            }));
    }
    function checkModelProperties(node, properties, parentModel, mapper) {
        let spreadIndexers;
        for (const prop of node.properties) {
            if ("id" in prop) {
                const newProp = checkModelProperty(prop, mapper);
                newProp.model = parentModel;
                checkPropertyCompatibleWithModelIndexer(parentModel, newProp, prop);
                defineProperty(properties, newProp);
            }
            else {
                // spread property
                const [newProperties, additionalIndexer] = checkSpreadProperty(node.symbol, prop.target, parentModel, mapper);
                if (additionalIndexer) {
                    if (spreadIndexers) {
                        spreadIndexers.push(additionalIndexer);
                    }
                    else {
                        spreadIndexers = [additionalIndexer];
                    }
                }
                for (const newProp of newProperties) {
                    linkIndirectMember(node, newProp, mapper);
                    checkPropertyCompatibleWithModelIndexer(parentModel, newProp, prop);
                    defineProperty(properties, newProp, prop);
                }
            }
        }
        if (spreadIndexers) {
            const value = spreadIndexers.length === 1
                ? spreadIndexers[0].value
                : createUnion(spreadIndexers.map((i) => i.value));
            parentModel.indexer = {
                key: spreadIndexers[0].key,
                value: value,
            };
        }
    }
    function checkObjectValue(node, mapper, constraint) {
        const properties = checkObjectLiteralProperties(node, mapper);
        if (properties === null) {
            return null;
        }
        const preciseType = createTypeForObjectValue(node, properties);
        if (constraint && !checkTypeOfValueMatchConstraint(preciseType, constraint, node)) {
            return null;
        }
        return createValue({
            entityKind: "Value",
            valueKind: "ObjectValue",
            node: node,
            properties,
            type: constraint ? constraint.type : preciseType,
        }, preciseType);
    }
    function createTypeForObjectValue(node, properties) {
        const model = createType({
            kind: "Model",
            name: "",
            node,
            properties: createRekeyableMap(),
            decorators: [],
            derivedModels: [],
            sourceModels: [],
        });
        for (const prop of properties.values()) {
            model.properties.set(prop.name, createModelPropertyForObjectPropertyDescriptor(prop, model));
        }
        return finishType(model);
    }
    function createModelPropertyForObjectPropertyDescriptor(prop, parentModel) {
        return createAndFinishType({
            kind: "ModelProperty",
            node: prop.node,
            model: parentModel,
            optional: false,
            name: prop.name,
            type: prop.value.type,
            decorators: [],
        });
    }
    function checkObjectLiteralProperties(node, mapper) {
        const properties = new Map();
        let hasError = false;
        for (const prop of node.properties) {
            if ("id" in prop) {
                const value = getValueForNode(prop.value, mapper);
                if (value === null) {
                    hasError = true;
                }
                else {
                    properties.set(prop.id.sv, { name: prop.id.sv, value: value, node: prop });
                }
            }
            else {
                const targetType = checkObjectSpreadProperty(prop.target, mapper);
                if (targetType) {
                    for (const [name, value] of targetType.properties) {
                        properties.set(name, { ...value });
                    }
                }
            }
        }
        return hasError ? null : properties;
    }
    function checkObjectSpreadProperty(targetNode, mapper) {
        const value = getValueForNode(targetNode, mapper);
        if (value === null) {
            return null;
        }
        if (value.valueKind !== "ObjectValue") {
            reportCheckerDiagnostic(createDiagnostic({ code: "spread-object", target: targetNode }));
            return null;
        }
        return value;
    }
    function checkArrayValue(node, mapper, constraint) {
        let hasError = false;
        const values = node.values.map((itemNode) => {
            const value = getValueForNode(itemNode, mapper);
            if (value === null) {
                hasError = true;
            }
            return value;
        });
        if (hasError) {
            return null;
        }
        const preciseType = createTypeForArrayValue(node, values);
        if (constraint && !checkTypeOfValueMatchConstraint(preciseType, constraint, node)) {
            return null;
        }
        return createValue({
            entityKind: "Value",
            valueKind: "ArrayValue",
            node: node,
            values: values,
            type: constraint ? constraint.type : preciseType,
        }, preciseType);
    }
    function createValue(value, preciseType) {
        valueExactTypes.set(value, preciseType);
        return value;
    }
    function copyValue(value, overrides) {
        const newValue = { ...value, ...overrides };
        const preciseType = valueExactTypes.get(value);
        if (preciseType) {
            valueExactTypes.set(newValue, preciseType);
        }
        return newValue;
    }
    function createTypeForArrayValue(node, values) {
        return createAndFinishType({
            kind: "Tuple",
            node,
            values: values.map((x) => x.type),
        });
    }
    function inferScalarForPrimitiveValue(type, literalType) {
        if (type === undefined) {
            return undefined;
        }
        switch (type.kind) {
            case "Scalar":
                if (ignoreDiagnostics(isTypeAssignableTo(literalType, type, literalType))) {
                    return type;
                }
                return undefined;
            case "Union":
                let found = undefined;
                for (const variant of type.variants.values()) {
                    const scalar = inferScalarForPrimitiveValue(variant.type, literalType);
                    if (scalar) {
                        if (found) {
                            reportCheckerDiagnostic(createDiagnostic({
                                code: "ambiguous-scalar-type",
                                format: {
                                    value: getTypeName(literalType),
                                    types: [found, scalar].map((x) => x.name).join(", "),
                                    example: found.name,
                                },
                                target: literalType,
                            }));
                            return undefined;
                        }
                        else {
                            found = scalar;
                        }
                    }
                }
                return found;
            default:
                return undefined;
        }
    }
    function checkStringValue(literalType, constraint, node) {
        if (constraint && !checkTypeOfValueMatchConstraint(literalType, constraint, node)) {
            return null;
        }
        let value;
        if (literalType.kind === "StringTemplate") {
            if (literalType.stringValue) {
                value = literalType.stringValue;
            }
            else {
                reportCheckerDiagnostics(explainStringTemplateNotSerializable(literalType));
                return null;
            }
        }
        else {
            value = literalType.value;
        }
        const scalar = inferScalarForPrimitiveValue(constraint?.type, literalType);
        return createValue({
            entityKind: "Value",
            valueKind: "StringValue",
            value,
            type: constraint ? constraint.type : literalType,
            scalar,
        }, literalType);
    }
    function checkNumericValue(literalType, constraint, node) {
        if (constraint && !checkTypeOfValueMatchConstraint(literalType, constraint, node)) {
            return null;
        }
        const scalar = inferScalarForPrimitiveValue(constraint?.type, literalType);
        return createValue({
            entityKind: "Value",
            valueKind: "NumericValue",
            value: Numeric(literalType.valueAsString),
            type: constraint ? constraint.type : literalType,
            scalar,
        }, literalType);
    }
    function checkBooleanValue(literalType, constraint, node) {
        if (constraint && !checkTypeOfValueMatchConstraint(literalType, constraint, node)) {
            return null;
        }
        const scalar = inferScalarForPrimitiveValue(constraint?.type, literalType);
        return createValue({
            entityKind: "Value",
            valueKind: "BooleanValue",
            value: literalType.value,
            type: constraint ? constraint.type : literalType,
            scalar,
        }, literalType);
    }
    function checkNullValue(literalType, constraint, node) {
        if (constraint && !checkTypeOfValueMatchConstraint(literalType, constraint, node)) {
            return null;
        }
        return createValue({
            entityKind: "Value",
            valueKind: "NullValue",
            type: constraint ? constraint.type : literalType,
            value: null,
        }, literalType);
    }
    function checkEnumValue(literalType, constraint, node) {
        if (constraint && !checkTypeOfValueMatchConstraint(literalType, constraint, node)) {
            return null;
        }
        return createValue({
            entityKind: "Value",
            valueKind: "EnumValue",
            type: constraint ? constraint.type : literalType,
            value: literalType,
        }, literalType);
    }
    function checkCallExpressionTarget(node, mapper) {
        const target = checkTypeReference(node.target, mapper);
        if (target.kind === "Scalar" || target.kind === "ScalarConstructor") {
            return target;
        }
        else {
            reportCheckerDiagnostic(createDiagnostic({
                code: "non-callable",
                format: { type: target.kind },
                target: node.target,
            }));
            return null;
        }
    }
    /** Check the arguments of the call expression are a single value of the given syntax. */
    function checkPrimitiveArg(node, scalar, valueKind) {
        if (node.arguments.length !== 1) {
            reportCheckerDiagnostic(createDiagnostic({
                code: "invalid-primitive-init",
                target: node.target,
            }));
            return null;
        }
        const argNode = node.arguments[0];
        const value = getValueForNode(argNode, undefined);
        if (value === null) {
            return null; // error should already have been reported above.
        }
        if (value.valueKind !== valueKind) {
            reportCheckerDiagnostic(createDiagnostic({
                code: "invalid-primitive-init",
                messageId: "invalidArg",
                format: { actual: value.valueKind, expected: valueKind },
                target: argNode,
            }));
            return null;
        }
        if (!checkValueOfType(value, scalar, argNode)) {
            return null;
        }
        return copyValue(value, { scalar, type: scalar });
    }
    function createScalarValue(node, mapper, declaration) {
        let hasError = false;
        const minArgs = declaration.parameters.filter((x) => !x.optional && !x.rest).length ?? 0;
        const maxArgs = declaration.parameters[declaration.parameters.length - 1]?.rest
            ? undefined
            : declaration.parameters.length;
        if (node.arguments.length < minArgs ||
            (maxArgs !== undefined && node.arguments.length > maxArgs)) {
            // In the case we have too little args then this decorator is not applicable.
            // If there is too many args then we can still run the decorator as long as the args are valid.
            if (node.arguments.length < minArgs) {
                hasError = true;
            }
            if (maxArgs === undefined) {
                reportCheckerDiagnostic(createDiagnostic({
                    code: "invalid-argument-count",
                    messageId: "atLeast",
                    format: { actual: node.arguments.length.toString(), expected: minArgs.toString() },
                    target: node,
                }));
            }
            else {
                const expected = minArgs === maxArgs ? minArgs.toString() : `${minArgs}-${maxArgs}`;
                reportCheckerDiagnostic(createDiagnostic({
                    code: "invalid-argument-count",
                    format: { actual: node.arguments.length.toString(), expected },
                    target: node,
                }));
            }
        }
        const resolvedArgs = [];
        for (const [index, parameter] of declaration.parameters.entries()) {
            if (parameter.rest) {
                const restType = getIndexType(parameter.type);
                if (restType) {
                    for (let i = index; i < node.arguments.length; i++) {
                        const argNode = node.arguments[i];
                        if (argNode) {
                            const arg = getValueForNode(argNode, mapper, { kind: "argument", type: restType });
                            if (arg === null) {
                                hasError = true;
                                continue;
                            }
                            if (checkValueOfType(arg, restType, argNode)) {
                                resolvedArgs.push(arg);
                            }
                            else {
                                hasError = true;
                            }
                        }
                    }
                }
                break;
            }
            const argNode = node.arguments[index];
            if (argNode) {
                const arg = getValueForNode(argNode, mapper, {
                    kind: "argument",
                    type: parameter.type,
                });
                if (arg === null) {
                    hasError = true;
                    continue;
                }
                if (checkValueOfType(arg, parameter.type, argNode)) {
                    resolvedArgs.push(arg);
                }
                else {
                    hasError = true;
                }
            }
        }
        if (hasError) {
            return null;
        }
        return {
            entityKind: "Value",
            valueKind: "ScalarValue",
            value: {
                name: declaration.name,
                args: resolvedArgs,
            },
            scalar: declaration.scalar,
            type: declaration.scalar,
        };
    }
    function checkCallExpression(node, mapper) {
        const target = checkCallExpressionTarget(node, mapper);
        if (target === null) {
            return null;
        }
        if (target.kind === "ScalarConstructor") {
            return createScalarValue(node, mapper, target);
        }
        if (areScalarsRelated(target, getStdType("string"))) {
            return checkPrimitiveArg(node, target, "StringValue");
        }
        else if (areScalarsRelated(target, getStdType("numeric"))) {
            return checkPrimitiveArg(node, target, "NumericValue");
        }
        else if (areScalarsRelated(target, getStdType("boolean"))) {
            return checkPrimitiveArg(node, target, "BooleanValue");
        }
        else {
            reportCheckerDiagnostic(createDiagnostic({
                code: "named-init-required",
                format: { typeKind: target.kind },
                target: node.target,
            }));
            return null;
        }
    }
    function checkTypeOfExpression(node, mapper) {
        const entity = checkNode(node.target, mapper, undefined);
        if (entity === null) {
            // Shouldn't need to emit error as we assume null value already emitted error when produced
            return errorType;
        }
        if (entity.entityKind === "Indeterminate") {
            return entity.type;
        }
        if (isType(entity)) {
            if (entity.kind === "TemplateParameter") {
                if (entity.constraint === undefined || entity.constraint.type !== undefined) {
                    // means this template constraint will accept values
                    reportCheckerDiagnostic(createDiagnostic({
                        code: "expect-value",
                        messageId: "templateConstraint",
                        format: { name: getTypeName(entity) },
                        target: node.target,
                    }));
                    return errorType;
                }
                else if (entity.constraint.valueType) {
                    return entity.constraint.valueType;
                }
            }
            reportCheckerDiagnostic(createDiagnostic({
                code: "expect-value",
                format: { name: getTypeName(entity) },
                target: node.target,
            }));
            return entity;
        }
        return entity.type;
    }
    function createUnion(options) {
        const variants = createRekeyableMap();
        const union = createAndFinishType({
            kind: "Union",
            node: undefined,
            options,
            decorators: [],
            variants,
            expression: true,
        });
        for (const option of options) {
            const name = Symbol("indexer-union-variant");
            variants.set(name, createAndFinishType({
                kind: "UnionVariant",
                node: undefined,
                type: option,
                name,
                union,
                decorators: [],
            }));
        }
        return union;
    }
    function defineProperty(properties, newProp, diagnosticTarget) {
        if (properties.has(newProp.name)) {
            reportCheckerDiagnostic(createDiagnostic({
                code: "duplicate-property",
                format: { propName: newProp.name },
                target: diagnosticTarget ?? newProp,
            }));
            return;
        }
        const overriddenProp = getOverriddenProperty(newProp);
        if (overriddenProp) {
            const [isAssignable, _] = isTypeAssignableTo(newProp.type, overriddenProp.type, newProp);
            const parentType = getTypeName(overriddenProp.type);
            const newPropType = getTypeName(newProp.type);
            let invalid = false;
            if (!isAssignable) {
                reportCheckerDiagnostic(createDiagnostic({
                    code: "override-property-mismatch",
                    format: { propName: newProp.name, propType: newPropType, parentType: parentType },
                    target: diagnosticTarget ?? newProp,
                }));
                invalid = true;
            }
            if (!overriddenProp.optional && newProp.optional) {
                reportCheckerDiagnostic(createDiagnostic({
                    code: "override-property-mismatch",
                    messageId: "disallowedOptionalOverride",
                    format: { propName: overriddenProp.name },
                    target: diagnosticTarget ?? newProp,
                }));
                invalid = true;
            }
            if (invalid)
                return;
        }
        properties.set(newProp.name, newProp);
    }
    function bindAllMembers(node) {
        const bound = new Set();
        if (node.symbol) {
            bindMembers(node, node.symbol);
        }
        visitChildren(node, (child) => {
            bindAllMembers(child);
        });
        function bindMembers(node, containerSym) {
            if (bound.has(containerSym)) {
                return;
            }
            bound.add(containerSym);
            let containerMembers;
            switch (node.kind) {
                case SyntaxKind.ModelStatement:
                    if (node.extends && node.extends.kind === SyntaxKind.TypeReference) {
                        resolveAndCopyMembers(node.extends);
                    }
                    if (node.is && node.is.kind === SyntaxKind.TypeReference) {
                        resolveAndCopyMembers(node.is);
                    }
                    for (const prop of node.properties) {
                        if (prop.kind === SyntaxKind.ModelSpreadProperty) {
                            resolveAndCopyMembers(prop.target);
                        }
                        else {
                            const name = prop.id.sv;
                            bindMember(name, prop, 4 /* SymbolFlags.ModelProperty */);
                        }
                    }
                    break;
                case SyntaxKind.ScalarStatement:
                    if (node.extends && node.extends.kind === SyntaxKind.TypeReference) {
                        resolveAndCopyMembers(node.extends);
                    }
                    for (const member of node.members) {
                        const name = member.id.sv;
                        bindMember(name, member, 33554432 /* SymbolFlags.ScalarMember */);
                    }
                    break;
                case SyntaxKind.ModelExpression:
                    for (const prop of node.properties) {
                        if (prop.kind === SyntaxKind.ModelSpreadProperty) {
                            resolveAndCopyMembers(prop.target);
                        }
                        else {
                            const name = prop.id.sv;
                            bindMember(name, prop, 4 /* SymbolFlags.ModelProperty */);
                        }
                    }
                    break;
                case SyntaxKind.EnumStatement:
                    for (const member of node.members.values()) {
                        if (member.kind === SyntaxKind.EnumSpreadMember) {
                            resolveAndCopyMembers(member.target);
                        }
                        else {
                            const name = member.id.sv;
                            bindMember(name, member, 64 /* SymbolFlags.EnumMember */);
                        }
                    }
                    break;
                case SyntaxKind.InterfaceStatement:
                    for (const member of node.operations.values()) {
                        bindMember(member.id.sv, member, 256 /* SymbolFlags.InterfaceMember */ | 16 /* SymbolFlags.Operation */);
                    }
                    if (node.extends) {
                        for (const ext of node.extends) {
                            resolveAndCopyMembers(ext);
                        }
                    }
                    break;
                case SyntaxKind.UnionStatement:
                    for (const variant of node.options.values()) {
                        if (!variant.id) {
                            continue;
                        }
                        const name = variant.id.sv;
                        bindMember(name, variant, 1024 /* SymbolFlags.UnionVariant */);
                    }
                    break;
            }
            function resolveAndCopyMembers(node) {
                let ref = resolveTypeReferenceSym(node, undefined);
                if (ref && ref.flags & 2048 /* SymbolFlags.Alias */) {
                    ref = resolveAliasedSymbol(ref);
                }
                if (ref && ref.members) {
                    bindMembers(ref.declarations[0], ref);
                    copyMembers(ref.members);
                }
            }
            function resolveAliasedSymbol(ref) {
                const node = ref.declarations[0];
                switch (node.value.kind) {
                    case SyntaxKind.MemberExpression:
                    case SyntaxKind.TypeReference:
                        const resolvedSym = resolveTypeReferenceSym(node.value, undefined);
                        if (resolvedSym && resolvedSym.flags & 2048 /* SymbolFlags.Alias */) {
                            return resolveAliasedSymbol(resolvedSym);
                        }
                        return resolvedSym;
                    default:
                        return undefined;
                }
            }
            function copyMembers(table) {
                const members = augmentedSymbolTables.get(table) ?? table;
                for (const member of members.values()) {
                    bindMember(member.name, member.declarations[0], member.flags);
                }
            }
            function bindMember(name, node, kind) {
                const sym = createSymbol(node, name, kind, containerSym);
                compilerAssert(containerSym.members, "containerSym.members is undefined");
                containerMembers ??= getOrCreateAugmentedSymbolTable(containerSym.members);
                containerMembers.set(name, sym);
            }
        }
    }
    function copyMembersToContainer(targetContainerSym, table) {
        const members = augmentedSymbolTables.get(table) ?? table;
        compilerAssert(targetContainerSym.members, "containerSym.members is undefined");
        const containerMembers = getOrCreateAugmentedSymbolTable(targetContainerSym.members);
        for (const member of members.values()) {
            bindMemberToContainer(targetContainerSym, containerMembers, member.name, member.declarations[0], member.flags);
        }
    }
    function bindMemberToContainer(containerSym, containerMembers, name, node, kind) {
        const sym = createSymbol(node, name, kind, containerSym);
        compilerAssert(containerSym.members, "containerSym.members is undefined");
        containerMembers.set(name, sym);
    }
    function bindMetaTypes(node) {
        const visited = new Set();
        function visit(node, symbol) {
            if (visited.has(node)) {
                return;
            }
            visited.add(node);
            switch (node.kind) {
                case SyntaxKind.ModelProperty: {
                    const sym = getSymbolForMember(node);
                    if (sym) {
                        const table = getOrCreateAugmentedSymbolTable(sym.metatypeMembers);
                        table.set("type", node.value.kind === SyntaxKind.TypeReference
                            ? createSymbol(node.value, "", 2048 /* SymbolFlags.Alias */)
                            : node.value.symbol);
                    }
                    break;
                }
                case SyntaxKind.OperationStatement: {
                    const sym = symbol ?? node.symbol ?? getSymbolForMember(node);
                    const table = getOrCreateAugmentedSymbolTable(sym.metatypeMembers);
                    if (node.signature.kind === SyntaxKind.OperationSignatureDeclaration) {
                        table.set("parameters", node.signature.parameters.symbol);
                        table.set("returnType", node.signature.returnType.symbol);
                    }
                    else {
                        const sig = resolveTypeReferenceSym(node.signature.baseOperation, undefined, {
                            checkTemplateTypes: false,
                        });
                        if (sig) {
                            visit(sig.declarations[0], sig);
                            const sigTable = getOrCreateAugmentedSymbolTable(sig.metatypeMembers);
                            const sigParameterSym = sigTable.get("parameters");
                            if (sigParameterSym !== undefined) {
                                const parametersSym = createSymbol(sigParameterSym.declarations[0], "parameters", 2 /* SymbolFlags.Model */ & 682 /* SymbolFlags.MemberContainer */);
                                copyMembersToContainer(parametersSym, sigParameterSym.members);
                                table.set("parameters", parametersSym);
                                table.set("returnType", sigTable.get("returnType"));
                            }
                        }
                    }
                    break;
                }
            }
            visitChildren(node, (child) => {
                bindMetaTypes(child);
            });
        }
        visit(node);
    }
    /**
     * Initializes a late bound symbol for the type. This is generally necessary when attempting to
     * access a symbol for a type that is created during the check phase.
     */
    function lateBindMemberContainer(type) {
        if (type.symbol)
            return;
        switch (type.kind) {
            case "Model":
                type.symbol = createSymbol(type.node, type.name, 2 /* SymbolFlags.Model */ | 67108864 /* SymbolFlags.LateBound */);
                mutate(type.symbol).type = type;
                break;
            case "Interface":
                type.symbol = createSymbol(type.node, type.name, 128 /* SymbolFlags.Interface */ | 67108864 /* SymbolFlags.LateBound */);
                mutate(type.symbol).type = type;
                break;
            case "Union":
                if (!type.name)
                    return; // don't make a symbol for anonymous unions
                type.symbol = createSymbol(type.node, type.name, 512 /* SymbolFlags.Union */ | 67108864 /* SymbolFlags.LateBound */);
                mutate(type.symbol).type = type;
                break;
        }
    }
    function lateBindMembers(type, containerSym) {
        let containerMembers;
        switch (type.kind) {
            case "Model":
                for (const prop of walkPropertiesInherited(type)) {
                    lateBindMember(prop, 4 /* SymbolFlags.ModelProperty */);
                }
                break;
            case "Scalar":
                for (const member of type.constructors.values()) {
                    lateBindMember(member, 33555780 /* SymbolFlags.Member */);
                }
                break;
            case "Enum":
                for (const member of type.members.values()) {
                    lateBindMember(member, 64 /* SymbolFlags.EnumMember */);
                }
                break;
            case "Interface":
                for (const member of type.operations.values()) {
                    lateBindMember(member, 256 /* SymbolFlags.InterfaceMember */ | 16 /* SymbolFlags.Operation */);
                }
                break;
            case "Union":
                for (const variant of type.variants.values()) {
                    lateBindMember(variant, 1024 /* SymbolFlags.UnionVariant */);
                }
                break;
        }
        function lateBindMember(member, kind) {
            if (!member.node || typeof member.name !== "string") {
                // don't bind anything for union expressions
                return;
            }
            const sym = createSymbol(member.node, member.name, kind | 67108864 /* SymbolFlags.LateBound */, containerSym);
            mutate(sym).type = member;
            compilerAssert(containerSym.members, "containerSym.members is undefined");
            containerMembers ??= getOrCreateAugmentedSymbolTable(containerSym.members);
            containerMembers.set(member.name, sym);
        }
    }
    function checkClassHeritage(model, heritageRef, mapper) {
        if (heritageRef.kind === SyntaxKind.ModelExpression) {
            reportCheckerDiagnostic(createDiagnostic({
                code: "extend-model",
                messageId: "modelExpression",
                target: heritageRef,
            }));
            return undefined;
        }
        if (heritageRef.kind !== SyntaxKind.TypeReference) {
            reportCheckerDiagnostic(createDiagnostic({
                code: "extend-model",
                target: heritageRef,
            }));
            return undefined;
        }
        const modelSymId = getNodeSymId(model);
        pendingResolutions.start(modelSymId, ResolutionKind.BaseType);
        const target = resolveTypeReferenceSym(heritageRef, mapper);
        if (target === undefined) {
            return undefined;
        }
        if (pendingResolutions.has(getNodeSymId(target.declarations[0]), ResolutionKind.BaseType)) {
            if (mapper === undefined) {
                reportCheckerDiagnostic(createDiagnostic({
                    code: "circular-base-type",
                    format: { typeName: target.declarations[0].id.sv },
                    target: target,
                }));
            }
            return undefined;
        }
        const heritageType = checkTypeReferenceSymbol(target, heritageRef, mapper);
        pendingResolutions.finish(modelSymId, ResolutionKind.BaseType);
        if (isErrorType(heritageType)) {
            compilerAssert(program.hasError(), "Should already have reported an error.", heritageRef);
            return undefined;
        }
        if (heritageType.kind !== "Model") {
            reportCheckerDiagnostic(createDiagnostic({ code: "extend-model", target: heritageRef }));
            return undefined;
        }
        if (heritageType.name === "") {
            reportCheckerDiagnostic(createDiagnostic({
                code: "extend-model",
                messageId: "modelExpression",
                target: heritageRef,
            }));
        }
        return heritageType;
    }
    function checkModelIs(model, isExpr, mapper) {
        if (!isExpr)
            return undefined;
        const modelSymId = getNodeSymId(model);
        pendingResolutions.start(modelSymId, ResolutionKind.BaseType);
        let isType;
        if (isExpr.kind === SyntaxKind.ModelExpression) {
            reportCheckerDiagnostic(createDiagnostic({
                code: "is-model",
                messageId: "modelExpression",
                target: isExpr,
            }));
            return undefined;
        }
        else if (isExpr.kind === SyntaxKind.ArrayExpression) {
            isType = checkArrayExpression(isExpr, mapper);
        }
        else if (isExpr.kind === SyntaxKind.TypeReference) {
            const target = resolveTypeReferenceSym(isExpr, mapper);
            if (target === undefined) {
                return undefined;
            }
            if (pendingResolutions.has(getNodeSymId(target.declarations[0]), ResolutionKind.BaseType)) {
                if (mapper === undefined) {
                    reportCheckerDiagnostic(createDiagnostic({
                        code: "circular-base-type",
                        format: { typeName: target.declarations[0].id.sv },
                        target: target,
                    }));
                }
                return undefined;
            }
            isType = checkTypeReferenceSymbol(target, isExpr, mapper);
        }
        else {
            reportCheckerDiagnostic(createDiagnostic({ code: "is-model", target: isExpr }));
            return undefined;
        }
        pendingResolutions.finish(modelSymId, ResolutionKind.BaseType);
        if (isType.kind !== "Model") {
            reportCheckerDiagnostic(createDiagnostic({ code: "is-model", target: isExpr }));
            return;
        }
        if (isType.name === "") {
            reportCheckerDiagnostic(createDiagnostic({ code: "is-model", messageId: "modelExpression", target: isExpr }));
            return undefined;
        }
        return isType;
    }
    function checkSpreadProperty(parentModelSym, targetNode, parentModel, mapper) {
        const targetType = getTypeForNode(targetNode, mapper);
        if (targetType.kind === "TemplateParameter" || isErrorType(targetType)) {
            return [[], undefined];
        }
        if (targetType.kind !== "Model") {
            reportCheckerDiagnostic(createDiagnostic({ code: "spread-model", target: targetNode }));
            return [[], undefined];
        }
        if (isArrayModelType(program, targetType)) {
            reportCheckerDiagnostic(createDiagnostic({ code: "spread-model", target: targetNode }));
            return [[], undefined];
        }
        if (parentModel === targetType) {
            reportCheckerDiagnostic(createDiagnostic({
                code: "spread-model",
                messageId: "selfSpread",
                target: targetNode,
            }));
        }
        parentModel.sourceModels.push({ usage: "spread", model: targetType });
        const props = [];
        // copy each property
        for (const prop of walkPropertiesInherited(targetType)) {
            const memberSym = getMemberSymbol(parentModelSym, prop.name);
            props.push(cloneTypeForSymbol(memberSym, prop, {
                sourceProperty: prop,
                model: parentModel,
            }));
        }
        return [props, targetType.indexer];
    }
    /**
     * Link an indirect model property(included via spread or model is) to its model member symbols.
     * @param containerNode Model Node
     * @param member New Property
     * @param mapper Type Mapper.
     */
    function linkIndirectMember(containerNode, member, mapper) {
        if (mapper !== undefined) {
            return;
        }
        compilerAssert(typeof member.name === "string", "Cannot link unmapped unions");
        if (containerNode.symbol === undefined) {
            return;
        }
        compilerAssert(containerNode.symbol.members, `Expected container node ${SyntaxKind[containerNode.kind]} to have members.`);
        const memberSym = getOrCreateAugmentedSymbolTable(containerNode.symbol.members).get(member.name);
        if (memberSym) {
            const links = getSymbolLinks(memberSym);
            linkMemberType(links, member, mapper);
        }
    }
    function checkModelProperty(prop, mapper) {
        const sym = getSymbolForMember(prop);
        const symId = getSymbolId(sym);
        const links = getSymbolLinksForMember(prop);
        if (links && links.declaredType && mapper === undefined) {
            return links.declaredType;
        }
        const name = prop.id.sv;
        const type = createType({
            kind: "ModelProperty",
            name,
            node: prop,
            optional: prop.optional,
            type: undefined,
            decorators: [],
        });
        if (pendingResolutions.has(symId, ResolutionKind.Type) && mapper === undefined) {
            reportCheckerDiagnostic(createDiagnostic({
                code: "circular-prop",
                format: { propName: name },
                target: prop,
            }));
            type.type = errorType;
        }
        else {
            pendingResolutions.start(symId, ResolutionKind.Type);
            type.type = getTypeForNode(prop.value, mapper);
            if (prop.default) {
                const defaultValue = checkDefaultValue(prop.default, type.type);
                if (defaultValue !== null) {
                    type.defaultValue = defaultValue;
                    // eslint-disable-next-line deprecation/deprecation
                    type.default = checkLegacyDefault(prop.default);
                }
            }
            if (links) {
                linkType(links, type, mapper);
            }
        }
        type.decorators = checkDecorators(type, prop, mapper);
        const parentTemplate = getParentTemplateNode(prop);
        linkMapper(type, mapper);
        if (!parentTemplate || shouldCreateTypeForTemplate(parentTemplate, mapper)) {
            const docComment = docFromCommentForSym.get(sym);
            if (docComment) {
                type.decorators.unshift(createDocFromCommentDecorator("self", docComment));
            }
            finishType(type);
        }
        pendingResolutions.finish(symId, ResolutionKind.Type);
        return type;
    }
    function createDocFromCommentDecorator(key, doc) {
        return {
            decorator: $docFromComment,
            args: [
                { value: createLiteralType(key), jsValue: key },
                { value: createLiteralType(doc), jsValue: doc },
            ],
        };
    }
    function checkDefaultValue(defaultNode, type) {
        if (isErrorType(type)) {
            // if the prop type is an error we don't need to validate again.
            return null;
        }
        const defaultValue = getValueForNode(defaultNode, undefined, {
            kind: "assignment",
            type,
        }, { legacyTupleAndModelCast: true });
        if (defaultValue === null) {
            return null;
        }
        const [related, diagnostics] = isValueOfType(defaultValue, type, defaultNode);
        if (!related) {
            reportCheckerDiagnostics(diagnostics);
            return null;
        }
        else {
            return { ...defaultValue, type };
        }
    }
    /**
     * Fill in the legacy `.default` property.
     * We do do checking here we just keep existing behavior.
     */
    function checkLegacyDefault(defaultNode) {
        const resolved = checkNode(defaultNode, undefined);
        if (resolved === null || isValue(resolved)) {
            return undefined;
        }
        if (resolved.entityKind === "Indeterminate") {
            return resolved.type;
        }
        return resolved;
    }
    function checkDecoratorApplication(targetType, decNode, mapper) {
        const sym = resolveTypeReferenceSym(decNode.target, undefined, true);
        if (!sym) {
            reportCheckerDiagnostic(createDiagnostic({
                code: "unknown-decorator",
                target: decNode,
            }));
            return undefined;
        }
        if (!(sym.flags & 16384 /* SymbolFlags.Decorator */)) {
            reportCheckerDiagnostic(createDiagnostic({
                code: "invalid-decorator",
                format: { id: sym.name },
                target: decNode,
            }));
            return undefined;
        }
        const symbolLinks = getSymbolLinks(sym);
        let hasError = false;
        if (symbolLinks.declaredType === undefined) {
            const decoratorDeclNode = sym.declarations.find((x) => x.kind === SyntaxKind.DecoratorDeclarationStatement);
            if (decoratorDeclNode) {
                checkDecoratorDeclaration(decoratorDeclNode, undefined);
            }
        }
        if (symbolLinks.declaredType) {
            compilerAssert(symbolLinks.declaredType.kind === "Decorator", "Expected to find a decorator type.");
            if (!checkDecoratorTarget(targetType, symbolLinks.declaredType, decNode)) {
                hasError = true;
            }
        }
        const [argsHaveError, args] = checkDecoratorArguments(decNode, mapper, symbolLinks.declaredType);
        if (hasError || argsHaveError) {
            return undefined;
        }
        return {
            definition: symbolLinks.declaredType,
            decorator: sym.value ?? ((...args) => { }),
            node: decNode,
            args,
        };
    }
    function resolveDecoratorArgMarshalling(declaredType) {
        if (declaredType) {
            const location = getLocationContext(program, declaredType);
            if (location.type === "compiler") {
                return "new";
            }
            else if ((location.type === "library" || location.type === "project") &&
                location.flags?.decoratorArgMarshalling) {
                return location.flags.decoratorArgMarshalling;
            }
            else {
                return "legacy";
            }
        }
        return "new";
    }
    /** Check the decorator target is valid */
    function checkDecoratorTarget(targetType, declaration, decoratorNode) {
        const [targetValid] = isTypeAssignableTo(targetType, declaration.target.type, decoratorNode);
        if (!targetValid) {
            reportCheckerDiagnostic(createDiagnostic({
                code: "decorator-wrong-target",
                messageId: "withExpected",
                format: {
                    decorator: declaration.name,
                    to: getTypeName(targetType),
                    expected: getEntityName(declaration.target.type),
                },
                target: decoratorNode,
            }));
        }
        return targetValid;
    }
    function checkDecoratorArguments(node, mapper, declaration) {
        // if we don't have a declaration we can just return the types or values if
        if (declaration === undefined) {
            return [
                false,
                node.arguments.map((argNode) => {
                    let type = checkNode(argNode, mapper) ?? errorType;
                    if (type.entityKind === "Indeterminate") {
                        type = type.type;
                    }
                    return {
                        value: type,
                        jsValue: type,
                        node: argNode,
                    };
                }),
            ];
        }
        let hasError = false;
        const minArgs = declaration.parameters.filter((x) => !x.optional && !x.rest).length ?? 0;
        const maxArgs = declaration.parameters[declaration.parameters.length - 1]?.rest
            ? undefined
            : declaration.parameters.length;
        if (node.arguments.length < minArgs ||
            (maxArgs !== undefined && node.arguments.length > maxArgs)) {
            // In the case we have too little args then this decorator is not applicable.
            // If there is too many args then we can still run the decorator as long as the args are valid.
            if (node.arguments.length < minArgs) {
                hasError = true;
            }
            if (maxArgs === undefined) {
                reportCheckerDiagnostic(createDiagnostic({
                    code: "invalid-argument-count",
                    messageId: "atLeast",
                    format: { actual: node.arguments.length.toString(), expected: minArgs.toString() },
                    target: node,
                }));
            }
            else {
                const expected = minArgs === maxArgs ? minArgs.toString() : `${minArgs}-${maxArgs}`;
                reportCheckerDiagnostic(createDiagnostic({
                    code: "invalid-argument-count",
                    format: { actual: node.arguments.length.toString(), expected },
                    target: node,
                }));
            }
        }
        const resolvedArgs = [];
        const jsMarshalling = resolveDecoratorArgMarshalling(declaration);
        function resolveArg(argNode, perParamType) {
            const arg = getTypeOrValueForNode(argNode, mapper, {
                kind: "argument",
                constraint: perParamType,
            });
            if (arg !== null &&
                !(isType(arg) && isErrorType(arg)) &&
                checkArgumentAssignable(arg, perParamType, argNode)) {
                return {
                    value: arg,
                    node: argNode,
                    jsValue: resolveDecoratorArgJsValue(arg, extractValueOfConstraints({
                        kind: "argument",
                        constraint: perParamType,
                    }), jsMarshalling),
                };
            }
            else {
                return undefined;
            }
        }
        for (const [index, parameter] of declaration.parameters.entries()) {
            if (parameter.rest) {
                const restType = extractRestParamConstraint(parameter.type);
                if (restType) {
                    for (let i = index; i < node.arguments.length; i++) {
                        const argNode = node.arguments[i];
                        if (argNode) {
                            const arg = resolveArg(argNode, restType);
                            if (arg) {
                                resolvedArgs.push(arg);
                            }
                            else {
                                hasError = true;
                            }
                        }
                    }
                }
                break;
            }
            const argNode = node.arguments[index];
            if (argNode) {
                const arg = resolveArg(argNode, parameter.type);
                if (arg) {
                    resolvedArgs.push(arg);
                }
                else {
                    hasError = true;
                }
            }
        }
        return [hasError, resolvedArgs];
    }
    /** For a rest param of constraint T[] or valueof T[] return the T or valueof T */
    function extractRestParamConstraint(constraint) {
        let valueType;
        let type;
        if (constraint.valueType) {
            if (constraint.valueType.kind === "Model" &&
                isArrayModelType(program, constraint.valueType)) {
                valueType = constraint.valueType.indexer.value;
            }
            else {
                return undefined;
            }
        }
        if (constraint.type) {
            if (constraint.type.kind === "Model" && isArrayModelType(program, constraint.type)) {
                type = constraint.type.indexer.value;
            }
            else {
                return undefined;
            }
        }
        return {
            entityKind: "MixedParameterConstraint",
            type,
            valueType,
        };
    }
    function getIndexType(type) {
        return type.kind === "Model" ? type.indexer?.value : undefined;
    }
    function resolveDecoratorArgJsValue(value, valueConstraint, jsMarshalling) {
        if (valueConstraint !== undefined) {
            if (isValue(value)) {
                return jsMarshalling === "legacy"
                    ? legacyMarshallTypeForJS(checker, value)
                    : marshallTypeForJS(value, valueConstraint.type);
            }
            else {
                return value;
            }
        }
        return value;
    }
    function checkArgumentAssignable(argumentType, parameterType, diagnosticTarget) {
        const [valid] = isTypeAssignableTo(argumentType, parameterType, diagnosticTarget);
        if (!valid) {
            reportCheckerDiagnostic(createDiagnostic({
                code: "invalid-argument",
                format: {
                    value: getEntityName(argumentType),
                    expected: getEntityName(parameterType),
                },
                target: diagnosticTarget,
            }));
        }
        return valid;
    }
    function checkAugmentDecorators(sym, targetType, mapper) {
        const augmentDecoratorNodes = augmentDecoratorsForSym.get(sym) ?? [];
        const decorators = [];
        for (const decNode of augmentDecoratorNodes) {
            const decorator = checkDecoratorApplication(targetType, decNode, mapper);
            if (decorator) {
                decorators.unshift(decorator);
            }
        }
        return decorators;
    }
    function checkDecorators(targetType, node, mapper) {
        const sym = isMemberNode(node) ? getSymbolForMember(node) ?? node.symbol : node.symbol;
        const decorators = [];
        const augmentDecoratorNodes = augmentDecoratorsForSym.get(sym) ?? [];
        const decoratorNodes = [
            ...augmentDecoratorNodes, // the first decorator will be executed at last, so augmented decorator should be placed at first.
            ...node.decorators,
        ];
        for (const decNode of decoratorNodes) {
            const decorator = checkDecoratorApplication(targetType, decNode, mapper);
            if (decorator) {
                decorators.unshift(decorator);
            }
        }
        // Doc comment should always be the first decorator in case an explicit @doc must override it.
        const docComment = extractMainDoc(targetType);
        if (docComment) {
            decorators.unshift(createDocFromCommentDecorator("self", docComment));
        }
        if (targetType.kind === "Operation") {
            const returnTypesDocs = extractReturnsDocs(targetType);
            if (returnTypesDocs.returns) {
                decorators.unshift(createDocFromCommentDecorator("returns", returnTypesDocs.returns));
            }
            if (returnTypesDocs.errors) {
                decorators.unshift(createDocFromCommentDecorator("errors", returnTypesDocs.errors));
            }
        }
        else if (targetType.kind === "ModelProperty") ;
        return decorators;
    }
    function checkScalar(node, mapper) {
        const links = getSymbolLinks(node.symbol);
        if (links.declaredType && mapper === undefined) {
            // we're not instantiating this model and we've already checked it
            return links.declaredType;
        }
        checkTemplateDeclaration(node, mapper);
        const decorators = [];
        const type = createType({
            kind: "Scalar",
            name: node.id.sv,
            node: node,
            constructors: new Map(),
            namespace: getParentNamespaceType(node),
            decorators,
            derivedScalars: [],
        });
        linkType(links, type, mapper);
        if (node.extends) {
            type.baseScalar = checkScalarExtends(node, node.extends, mapper);
            if (type.baseScalar) {
                copyDeprecation(type.baseScalar, type);
                type.baseScalar.derivedScalars.push(type);
            }
        }
        checkScalarConstructors(type, node, type.constructors, mapper);
        decorators.push(...checkDecorators(type, node, mapper));
        if (mapper === undefined) {
            type.namespace?.scalars.set(type.name, type);
        }
        linkMapper(type, mapper);
        if (shouldCreateTypeForTemplate(node, mapper)) {
            finishType(type);
        }
        if (isInTypeSpecNamespace(type)) {
            stdTypes[type.name] = type;
        }
        return type;
    }
    function checkScalarExtends(scalar, extendsRef, mapper) {
        const symId = getNodeSymId(scalar);
        pendingResolutions.start(symId, ResolutionKind.BaseType);
        const target = resolveTypeReferenceSym(extendsRef, mapper);
        if (target === undefined) {
            return undefined;
        }
        if (pendingResolutions.has(getNodeSymId(target.declarations[0]), ResolutionKind.BaseType)) {
            if (mapper === undefined) {
                reportCheckerDiagnostic(createDiagnostic({
                    code: "circular-base-type",
                    format: { typeName: target.declarations[0].id.sv },
                    target: target,
                }));
            }
            return undefined;
        }
        const extendsType = checkTypeReferenceSymbol(target, extendsRef, mapper);
        pendingResolutions.finish(symId, ResolutionKind.BaseType);
        if (isErrorType(extendsType)) {
            compilerAssert(program.hasError(), "Should already have reported an error.", extendsRef);
            return undefined;
        }
        if (extendsType.kind !== "Scalar") {
            reportCheckerDiagnostic(createDiagnostic({ code: "extend-model", target: extendsRef }));
            return undefined;
        }
        return extendsType;
    }
    function checkScalarConstructors(parentScalar, node, constructors, mapper) {
        if (parentScalar.baseScalar) {
            for (const member of parentScalar.baseScalar.constructors.values()) {
                const newConstructor = cloneTypeForSymbol(getMemberSymbol(node.symbol, member.name), {
                    ...member,
                    scalar: parentScalar,
                });
                linkIndirectMember(node, newConstructor, mapper);
                constructors.set(member.name, newConstructor);
            }
        }
        for (const member of node.members) {
            const constructor = checkScalarConstructor(member, mapper, parentScalar);
            if (constructors.has(constructor.name)) {
                reportCheckerDiagnostic(createDiagnostic({
                    code: "constructor-duplicate",
                    format: { name: constructor.name.toString() },
                    target: member,
                }));
                continue;
            }
            constructors.set(constructor.name, constructor);
        }
    }
    function checkScalarConstructor(node, mapper, parentScalar) {
        const name = node.id.sv;
        const links = getSymbolLinksForMember(node);
        if (links && links.declaredType && mapper === undefined) {
            // we're not instantiating this scalar constructor and we've already checked it
            return links.declaredType;
        }
        const member = createType({
            kind: "ScalarConstructor",
            scalar: parentScalar,
            name,
            node,
            parameters: node.parameters.map((x) => checkFunctionParameter(x, mapper, false)),
        });
        linkMapper(member, mapper);
        if (shouldCreateTypeForTemplate(node.parent, mapper)) {
            finishType(member);
        }
        if (links) {
            linkType(links, member, mapper);
        }
        return finishType(member);
    }
    function checkAlias(node, mapper) {
        const links = getSymbolLinks(node.symbol);
        if (links.declaredType && mapper === undefined) {
            return links.declaredType;
        }
        checkTemplateDeclaration(node, mapper);
        const aliasSymId = getNodeSymId(node);
        if (pendingResolutions.has(aliasSymId, ResolutionKind.Type)) {
            if (mapper === undefined) {
                reportCheckerDiagnostic(createDiagnostic({
                    code: "circular-alias-type",
                    format: { typeName: node.id.sv },
                    target: node,
                }));
            }
            links.declaredType = errorType;
            return errorType;
        }
        pendingResolutions.start(aliasSymId, ResolutionKind.Type);
        const type = checkNode(node.value, mapper);
        if (type === null) {
            links.declaredType = errorType;
            return errorType;
        }
        if (isValue(type)) {
            reportCheckerDiagnostic(createDiagnostic({ code: "value-in-type", target: node.value }));
            links.declaredType = errorType;
            return errorType;
        }
        linkType(links, type, mapper);
        pendingResolutions.finish(aliasSymId, ResolutionKind.Type);
        return type;
    }
    function checkConst(node) {
        const links = getSymbolLinks(node.symbol);
        if (links.value !== undefined) {
            return links.value;
        }
        const type = node.type ? getTypeForNode(node.type, undefined) : undefined;
        const symId = getSymbolId(node.symbol);
        if (pendingResolutions.has(symId, ResolutionKind.Value)) {
            reportCheckerDiagnostic(createDiagnostic({
                code: "circular-const",
                format: { name: node.id.sv },
                target: node,
            }));
            return null;
        }
        pendingResolutions.start(symId, ResolutionKind.Value);
        const value = getValueForNode(node.value, undefined, type && { kind: "assignment", type });
        pendingResolutions.finish(symId, ResolutionKind.Value);
        if (value === null || (type && !checkValueOfType(value, type, node.id))) {
            links.value = null;
            return links.value;
        }
        links.value = type ? copyValue(value, { type }) : copyValue(value);
        return links.value;
    }
    function inferScalarsFromConstraints(value, type) {
        switch (value.valueKind) {
            case "BooleanValue":
            case "StringValue":
            case "NumericValue":
                if (value.scalar === undefined) {
                    const scalar = inferScalarForPrimitiveValue(type, value.type);
                    return copyValue(value, { scalar });
                }
                return value;
            case "ArrayValue":
            case "ObjectValue":
            case "EnumValue":
            case "NullValue":
            case "ScalarValue":
                return value;
        }
    }
    function checkEnum(node, mapper) {
        const links = getSymbolLinks(node.symbol);
        if (!links.type) {
            const enumType = (links.type = createType({
                kind: "Enum",
                name: node.id.sv,
                node,
                members: createRekeyableMap(),
                decorators: [],
            }));
            const memberNames = new Set();
            for (const member of node.members) {
                if (member.kind === SyntaxKind.EnumMember) {
                    const memberType = checkEnumMember(member, mapper, enumType);
                    if (memberNames.has(memberType.name)) {
                        reportCheckerDiagnostic(createDiagnostic({
                            code: "enum-member-duplicate",
                            format: { name: memberType.name },
                            target: node,
                        }));
                        continue;
                    }
                    memberNames.add(memberType.name);
                    enumType.members.set(memberType.name, memberType);
                }
                else {
                    const members = checkEnumSpreadMember(node.symbol, enumType, member.target, mapper, memberNames);
                    for (const memberType of members) {
                        linkIndirectMember(node, memberType, mapper);
                        enumType.members.set(memberType.name, memberType);
                    }
                }
            }
            const namespace = getParentNamespaceType(node);
            enumType.namespace = namespace;
            enumType.namespace?.enums.set(enumType.name, enumType);
            enumType.decorators = checkDecorators(enumType, node, mapper);
            linkMapper(enumType, mapper);
            finishType(enumType);
        }
        return links.type;
    }
    function checkInterface(node, mapper) {
        const links = getSymbolLinks(node.symbol);
        if (links.declaredType && mapper === undefined) {
            // we're not instantiating this interface and we've already checked it
            return links.declaredType;
        }
        checkTemplateDeclaration(node, mapper);
        const interfaceType = createType({
            kind: "Interface",
            decorators: [],
            node,
            namespace: getParentNamespaceType(node),
            sourceInterfaces: [],
            operations: createRekeyableMap(),
            name: node.id.sv,
        });
        linkType(links, interfaceType, mapper);
        interfaceType.decorators = checkDecorators(interfaceType, node, mapper);
        const ownMembers = checkInterfaceMembers(node, mapper, interfaceType);
        for (const extendsNode of node.extends) {
            const extendsType = getTypeForNode(extendsNode, mapper);
            if (extendsType.kind !== "Interface") {
                reportCheckerDiagnostic(createDiagnostic({ code: "extends-interface", target: extendsNode }));
                continue;
            }
            for (const member of extendsType.operations.values()) {
                if (interfaceType.operations.has(member.name)) {
                    reportCheckerDiagnostic(createDiagnostic({
                        code: "extends-interface-duplicate",
                        format: { name: member.name },
                        target: extendsNode,
                    }));
                }
                const newMember = cloneTypeForSymbol(getMemberSymbol(node.symbol, member.name), member, {
                    interface: interfaceType,
                });
                // Don't link it it is overritten
                if (!ownMembers.has(member.name)) {
                    linkIndirectMember(node, newMember, mapper);
                }
                // Clone deprecation information
                copyDeprecation(member, newMember);
                interfaceType.operations.set(newMember.name, newMember);
            }
            interfaceType.sourceInterfaces.push(extendsType);
        }
        for (const [key, value] of ownMembers) {
            interfaceType.operations.set(key, value);
        }
        linkMapper(interfaceType, mapper);
        if (shouldCreateTypeForTemplate(node, mapper)) {
            finishType(interfaceType);
        }
        if (mapper === undefined) {
            interfaceType.namespace?.interfaces.set(interfaceType.name, interfaceType);
        }
        return interfaceType;
    }
    function checkInterfaceMembers(node, mapper, interfaceType) {
        const ownMembers = new Map();
        for (const opNode of node.operations) {
            const opType = checkOperation(opNode, mapper, interfaceType);
            if (ownMembers.has(opType.name)) {
                reportCheckerDiagnostic(createDiagnostic({
                    code: "interface-duplicate",
                    format: { name: opType.name },
                    target: opNode,
                }));
                continue;
            }
            ownMembers.set(opType.name, opType);
        }
        return ownMembers;
    }
    function checkUnion(node, mapper) {
        const links = getSymbolLinks(node.symbol);
        if (links.declaredType && mapper === undefined) {
            // we're not instantiating this union and we've already checked it
            return links.declaredType;
        }
        checkTemplateDeclaration(node, mapper);
        const variants = createRekeyableMap();
        const unionType = createType({
            kind: "Union",
            decorators: [],
            node,
            namespace: getParentNamespaceType(node),
            name: node.id.sv,
            variants,
            get options() {
                return Array.from(this.variants.values()).map((v) => v.type);
            },
            expression: false,
        });
        linkType(links, unionType, mapper);
        unionType.decorators = checkDecorators(unionType, node, mapper);
        checkUnionVariants(unionType, node, variants, mapper);
        linkMapper(unionType, mapper);
        if (shouldCreateTypeForTemplate(node, mapper)) {
            finishType(unionType);
        }
        if (mapper === undefined) {
            unionType.namespace?.unions.set(unionType.name, unionType);
        }
        return unionType;
    }
    function checkUnionVariants(parentUnion, node, variants, mapper) {
        for (const variantNode of node.options) {
            const variantType = checkUnionVariant(variantNode, mapper);
            variantType.union = parentUnion;
            if (variants.has(variantType.name)) {
                reportCheckerDiagnostic(createDiagnostic({
                    code: "union-duplicate",
                    format: { name: variantType.name.toString() },
                    target: variantNode,
                }));
                continue;
            }
            variants.set(variantType.name, variantType);
        }
    }
    function checkUnionVariant(variantNode, mapper) {
        const links = getSymbolLinksForMember(variantNode);
        if (links && links.declaredType && mapper === undefined) {
            // we're not instantiating this union variant and we've already checked it
            return links.declaredType;
        }
        const name = variantNode.id ? variantNode.id.sv : Symbol("name");
        const type = getTypeForNode(variantNode.value, mapper);
        const variantType = createType({
            kind: "UnionVariant",
            name,
            node: variantNode,
            decorators: [],
            type,
            union: undefined,
        });
        variantType.decorators = checkDecorators(variantType, variantNode, mapper);
        linkMapper(variantType, mapper);
        if (shouldCreateTypeForTemplate(variantNode.parent, mapper)) {
            finishType(variantType);
        }
        if (links) {
            linkType(links, variantType, mapper);
        }
        return variantType;
    }
    function isMemberNode(node) {
        return (node.kind === SyntaxKind.ModelProperty ||
            node.kind === SyntaxKind.EnumMember ||
            node.kind === SyntaxKind.OperationStatement ||
            node.kind === SyntaxKind.UnionVariant);
    }
    function getMemberSymbol(parentSym, name) {
        return parentSym ? getOrCreateAugmentedSymbolTable(parentSym.members).get(name) : undefined;
    }
    function getSymbolForMember(node) {
        if (!node.id) {
            return undefined;
        }
        const name = node.id.sv;
        const parentSym = node.parent?.symbol;
        return parentSym ? getOrCreateAugmentedSymbolTable(parentSym.members).get(name) : undefined;
    }
    function getSymbolLinksForMember(node) {
        const sym = getSymbolForMember(node);
        return sym ? (sym.declarations[0] === node ? getSymbolLinks(sym) : undefined) : undefined;
    }
    function checkEnumMember(node, mapper, parentEnum) {
        const name = node.id.sv;
        const links = getSymbolLinksForMember(node);
        if (links?.type) {
            return links.type;
        }
        compilerAssert(parentEnum, "Enum member should already have been checked.");
        const value = node.value ? node.value.value : undefined;
        const member = createType({
            kind: "EnumMember",
            enum: parentEnum,
            name,
            node,
            value,
            decorators: [],
        });
        if (links) {
            links.type = member;
        }
        member.decorators = checkDecorators(member, node, mapper);
        return finishType(member);
    }
    function checkEnumSpreadMember(parentEnumSym, parentEnum, targetNode, mapper, existingMemberNames) {
        const members = [];
        const targetType = getTypeForNode(targetNode, mapper);
        if (!isErrorType(targetType)) {
            if (targetType.kind !== "Enum") {
                reportCheckerDiagnostic(createDiagnostic({ code: "spread-enum", target: targetNode }));
                return members;
            }
            for (const member of targetType.members.values()) {
                if (existingMemberNames.has(member.name)) {
                    reportCheckerDiagnostic(createDiagnostic({
                        code: "enum-member-duplicate",
                        format: { name: member.name },
                        target: targetNode,
                    }));
                }
                else {
                    existingMemberNames.add(member.name);
                    const memberSym = getMemberSymbol(parentEnumSym, member.name);
                    const clonedMember = cloneTypeForSymbol(memberSym, member, {
                        enum: parentEnum,
                        sourceMember: member,
                    });
                    if (clonedMember) {
                        members.push(clonedMember);
                    }
                }
            }
        }
        return members;
    }
    function checkDirectives(node, type) {
        let hasDeprecation = false;
        for (const directive of node.directives ?? []) {
            if (directive.target.sv === "deprecated") {
                const message = directive.arguments[0];
                if (message === undefined) {
                    reportCheckerDiagnostic(createDiagnostic({
                        code: "invalid-deprecation-argument",
                        messageId: "missing",
                        target: directive,
                    }));
                    continue;
                }
                let messageStr;
                if (message.kind !== SyntaxKind.StringLiteral) {
                    reportCheckerDiagnostic(createDiagnostic({
                        code: "invalid-deprecation-argument",
                        format: { kind: SyntaxKind[message.kind] },
                        target: directive.arguments[0],
                    }));
                    messageStr = "<missing message>";
                }
                else {
                    messageStr = message.value;
                }
                if (hasDeprecation === true) {
                    reportCheckerDiagnostic(createDiagnostic({ code: "duplicate-deprecation", target: node }));
                }
                else {
                    hasDeprecation = true;
                    markDeprecated(program, type, {
                        message: messageStr,
                    });
                }
            }
        }
    }
    // the types here aren't ideal and could probably be refactored.
    function createAndFinishType(typeDef) {
        createType(typeDef);
        return finishType(typeDef);
    }
    /**
     * Given the own-properties of a type, returns a fully-initialized type.
     * So far, that amounts to setting the prototype to typePrototype which
     * contains the `projections` getter.
     */
    function createType(typeDef) {
        Object.setPrototypeOf(typeDef, typePrototype);
        typeDef.isFinished = false;
        // If the type has an associated syntax node, check any directives that
        // might be attached.
        const createdType = typeDef;
        createdType.entityKind = "Type";
        if (createdType.node) {
            checkDirectives(createdType.node, createdType);
        }
        return createdType;
    }
    function finishType(typeDef) {
        return finishTypeForProgramAndChecker(program, typePrototype, typeDef);
    }
    function getLiteralType(node) {
        return createLiteralType(node.value, node);
    }
    function mergeSymbolTable(source, target) {
        for (const [sym, duplicates] of source.duplicates) {
            const targetSet = target.duplicates.get(sym);
            if (targetSet === undefined) {
                mutate(target.duplicates).set(sym, new Set([...duplicates]));
            }
            else {
                for (const duplicate of duplicates) {
                    mutate(targetSet).add(duplicate);
                }
            }
        }
        for (const [key, sourceBinding] of source) {
            if (sourceBinding.flags & 4096 /* SymbolFlags.Namespace */) {
                let targetBinding = target.get(key);
                if (!targetBinding) {
                    targetBinding = {
                        ...sourceBinding,
                        declarations: [],
                        exports: createSymbolTable(),
                    };
                    target.set(key, targetBinding);
                }
                if (targetBinding.flags & 4096 /* SymbolFlags.Namespace */) {
                    mergedSymbols.set(sourceBinding, targetBinding);
                    mutate(targetBinding.declarations).push(...sourceBinding.declarations);
                    mergeSymbolTable(sourceBinding.exports, mutate(targetBinding.exports));
                }
                else {
                    // this will set a duplicate error
                    target.set(key, sourceBinding);
                }
            }
            else if (sourceBinding.flags & 4194304 /* SymbolFlags.Declaration */ ||
                sourceBinding.flags & 8388608 /* SymbolFlags.Implementation */) {
                if (sourceBinding.flags & 16384 /* SymbolFlags.Decorator */) {
                    mergeDeclarationOrImplementation(key, sourceBinding, target, 16384 /* SymbolFlags.Decorator */);
                }
                else if (sourceBinding.flags & 131072 /* SymbolFlags.Function */) {
                    mergeDeclarationOrImplementation(key, sourceBinding, target, 131072 /* SymbolFlags.Function */);
                }
                else {
                    target.set(key, sourceBinding);
                }
            }
            else {
                target.set(key, sourceBinding);
            }
        }
    }
    function mergeDeclarationOrImplementation(key, sourceBinding, target, expectTargetFlags) {
        const targetBinding = target.get(key);
        if (!targetBinding || !(targetBinding.flags & expectTargetFlags)) {
            target.set(key, sourceBinding);
            return;
        }
        const isSourceDeclaration = sourceBinding.flags & 4194304 /* SymbolFlags.Declaration */;
        const isSourceImplementation = sourceBinding.flags & 8388608 /* SymbolFlags.Implementation */;
        const isTargetDeclaration = targetBinding.flags & 4194304 /* SymbolFlags.Declaration */;
        const isTargetImplementation = targetBinding.flags & 8388608 /* SymbolFlags.Implementation */;
        if (isTargetDeclaration && isTargetImplementation) {
            // If the target already has both a declration and implementation set the symbol which will mark it as duplicate
            target.set(key, sourceBinding);
        }
        else if (isTargetDeclaration && isSourceImplementation) {
            mergedSymbols.set(sourceBinding, targetBinding);
            mutate(targetBinding).value = sourceBinding.value;
            mutate(targetBinding).flags |= sourceBinding.flags;
            mutate(targetBinding.declarations).push(...sourceBinding.declarations);
        }
        else if (isTargetImplementation && isSourceDeclaration) {
            mergedSymbols.set(sourceBinding, targetBinding);
            mutate(targetBinding).flags |= sourceBinding.flags;
            mutate(targetBinding.declarations).unshift(...sourceBinding.declarations);
        }
        else {
            // this will set a duplicate error
            target.set(key, sourceBinding);
        }
    }
    function getMergedSymbol(sym) {
        if (!sym)
            return sym;
        return mergedSymbols.get(sym) || sym;
    }
    function createGlobalNamespaceNode() {
        const nsId = {
            kind: SyntaxKind.Identifier,
            pos: 0,
            end: 0,
            sv: "global",
            symbol: undefined,
            flags: 8 /* NodeFlags.Synthetic */,
        };
        const nsNode = {
            kind: SyntaxKind.NamespaceStatement,
            decorators: [],
            pos: 0,
            end: 0,
            id: nsId,
            symbol: undefined,
            locals: createSymbolTable(),
            flags: 8 /* NodeFlags.Synthetic */,
        };
        mutate(nsNode).symbol = createSymbol(nsNode, nsId.sv, 4096 /* SymbolFlags.Namespace */);
        mutate(nsNode.symbol.exports).set(nsId.sv, nsNode.symbol);
        return nsNode;
    }
    function createGlobalNamespaceType() {
        const type = createAndFinishType({
            kind: "Namespace",
            name: "",
            node: globalNamespaceNode,
            models: new Map(),
            scalars: new Map(),
            operations: new Map(),
            namespaces: new Map(),
            interfaces: new Map(),
            unions: new Map(),
            enums: new Map(),
            decoratorDeclarations: new Map(),
            functionDeclarations: new Map(),
            decorators: [],
        });
        getSymbolLinks(globalNamespaceNode.symbol).type = type;
        return type;
    }
    function initializeClone(type, additionalProps) {
        let clone;
        switch (type.kind) {
            case "Model":
                const newModel = createType({
                    ...type,
                    decorators: [...type.decorators],
                    properties: undefined,
                    ...additionalProps,
                });
                if (!("properties" in additionalProps)) {
                    newModel.properties = createRekeyableMap(Array.from(type.properties.entries()).map(([key, prop]) => [
                        key,
                        cloneType(prop, { model: newModel }),
                    ]));
                }
                clone = newModel;
                break;
            case "Union":
                const newUnion = createType({
                    ...type,
                    decorators: [...type.decorators],
                    variants: undefined,
                    get options() {
                        return Array.from(this.variants.values()).map((v) => v.type);
                    },
                    ...additionalProps,
                });
                if (!("variants" in additionalProps)) {
                    newUnion.variants = createRekeyableMap(Array.from(type.variants.entries()).map(([key, prop]) => [
                        key,
                        cloneType(prop, { union: newUnion }),
                    ]));
                }
                clone = newUnion;
                break;
            case "Interface":
                const newInterface = createType({
                    ...type,
                    decorators: [...type.decorators],
                    operations: undefined,
                    ...additionalProps,
                });
                if (!("operations" in additionalProps)) {
                    newInterface.operations = createRekeyableMap(Array.from(type.operations.entries()).map(([key, prop]) => [
                        key,
                        cloneType(prop, { interface: newInterface }),
                    ]));
                }
                clone = newInterface;
                break;
            case "Enum":
                const newEnum = createType({
                    ...type,
                    decorators: [...type.decorators],
                    members: undefined,
                    ...additionalProps,
                });
                if (!("members" in additionalProps)) {
                    newEnum.members = createRekeyableMap(Array.from(type.members.entries()).map(([key, prop]) => [
                        key,
                        cloneType(prop, { enum: newEnum }),
                    ]));
                }
                clone = newEnum;
                break;
            default:
                clone = createType({
                    ...type,
                    ...("decorators" in type ? { decorators: [...type.decorators] } : {}),
                    ...additionalProps,
                });
                break;
        }
        return clone;
    }
    /**
     * Clone a type, resulting in an identical type with all the same decorators
     * applied. Decorators are re-run on the clone to achieve this.
     *
     * Care is taken to clone nested data structures that are part of the type.
     * Any type with e.g. a map or an array property must recreate the map or array
     * so that clones don't share the same object.
     *
     * For types which have sub-types that are part of it, e.g. enums with members,
     * unions with variants, or models with properties, the sub-types are cloned
     * as well.
     *
     * If the entire type graph needs to be cloned, then cloneType must be called
     * recursively by the caller.
     */
    function cloneType(type, additionalProps = {}) {
        let clone = initializeClone(type, additionalProps);
        if (type.isFinished) {
            clone = finishType(clone);
        }
        const projection = projectionsByType.get(type);
        if (projection) {
            projectionsByType.set(clone, projection);
        }
        compilerAssert(clone.kind === type.kind, "cloneType must not change type kind");
        return clone;
    }
    /**
     * Clone a type linking to the given symbol.
     * @param sym Symbol which to associate the clone
     * @param type Type to clone
     * @param additionalProps Additional properties to set/override on the clone
     * @returns cloned type
     */
    function cloneTypeForSymbol(sym, type, additionalProps = {}) {
        let clone = initializeClone(type, additionalProps);
        if ("decorators" in clone) {
            const docComment = docFromCommentForSym.get(sym);
            if (docComment) {
                clone.decorators.push(createDocFromCommentDecorator("self", docComment));
            }
            for (const dec of checkAugmentDecorators(sym, clone, undefined)) {
                clone.decorators.push(dec);
            }
        }
        if (type.isFinished) {
            clone = finishType(clone);
        }
        compilerAssert(clone.kind === type.kind, "cloneType must not change type kind");
        return clone;
    }
    function checkProjectionDeclaration(node) {
        // todo: check for duplicate projection decls on individual types
        // right now you can declare the same projection on a specific type
        // this could maybe go in the binder? But right now we don't know
        // what an identifier resolves to until check time.
        const links = getSymbolLinks(node.symbol);
        if (processedProjections.has(node)) {
            return links.declaredType;
        }
        processedProjections.add(node);
        reportCheckerDiagnostic(createDiagnostic({ code: "projections-are-experimental", target: node }));
        let type;
        if (links.declaredType) {
            type = links.declaredType;
        }
        else {
            type = links.declaredType = createType({
                kind: "Projection",
                node: undefined,
                nodeByKind: new Map(),
                nodeByType: new Map(),
            });
        }
        switch (node.selector.kind) {
            case SyntaxKind.ProjectionModelSelector:
                projectionsByTypeKind.get("Model").push(node);
                type.nodeByKind.set("Model", node);
                break;
            case SyntaxKind.ProjectionModelPropertySelector:
                projectionsByTypeKind.get("ModelProperty").push(node);
                type.nodeByKind.set("ModelProperty", node);
                break;
            case SyntaxKind.ProjectionScalarSelector:
                projectionsByTypeKind.get("Scalar").push(node);
                type.nodeByKind.set("Scalar", node);
                break;
            case SyntaxKind.ProjectionOperationSelector:
                projectionsByTypeKind.get("Operation").push(node);
                type.nodeByKind.set("Operation", node);
                break;
            case SyntaxKind.ProjectionUnionSelector:
                projectionsByTypeKind.get("Union").push(node);
                type.nodeByKind.set("Union", node);
                break;
            case SyntaxKind.ProjectionUnionVariantSelector:
                projectionsByTypeKind.get("UnionVariant").push(node);
                type.nodeByKind.set("UnionVariant", node);
                break;
            case SyntaxKind.ProjectionInterfaceSelector:
                projectionsByTypeKind.get("Interface").push(node);
                type.nodeByKind.set("Interface", node);
                break;
            case SyntaxKind.ProjectionEnumSelector:
                projectionsByTypeKind.get("Enum").push(node);
                type.nodeByKind.set("Enum", node);
                break;
            case SyntaxKind.ProjectionEnumMemberSelector:
                projectionsByTypeKind.get("EnumMember").push(node);
                type.nodeByKind.set("EnumMember", node);
                break;
            default:
                const projected = checkTypeReference(node.selector, undefined);
                let current = projectionsByType.get(projected);
                if (!current) {
                    current = [];
                    projectionsByType.set(projected, current);
                }
                current.push(node);
                type.nodeByType.set(projected, node);
                break;
        }
        return type;
    }
    function evalProjectionNode(node) {
        switch (node.kind) {
            case SyntaxKind.ProjectionExpressionStatement:
                return evalProjectionExpressionStatement(node);
            case SyntaxKind.ProjectionCallExpression:
                return evalProjectionCallExpression(node);
            case SyntaxKind.ProjectionMemberExpression:
                return evalProjectionMemberExpression(node);
            case SyntaxKind.ProjectionDecoratorReferenceExpression:
                return evalProjectionDecoratorReference(node);
            case SyntaxKind.Identifier:
                return evalProjectionIdentifier(node);
            case SyntaxKind.ProjectionLambdaExpression:
                return evalProjectionLambdaExpression(node);
            case SyntaxKind.StringLiteral:
                return evalStringLiteral(node);
            case SyntaxKind.NumericLiteral:
                return evalNumericLiteral(node);
            case SyntaxKind.BooleanLiteral:
                return evalBooleanLiteral(node);
            case SyntaxKind.ProjectionBlockExpression:
                return evalProjectionBlockExpression(node);
            case SyntaxKind.ProjectionArithmeticExpression:
                return evalProjectionArithmeticExpression(node);
            case SyntaxKind.ProjectionIfExpression:
                return evalProjectionIfExpression(node);
            case SyntaxKind.ProjectionEqualityExpression:
                return evalProjectionEqualityExpression(node);
            case SyntaxKind.ProjectionUnaryExpression:
                return evalProjectionUnaryExpression(node);
            case SyntaxKind.ProjectionRelationalExpression:
                return evalProjectionRelationalExpression(node);
            case SyntaxKind.ProjectionModelExpression:
                return evalProjectionModelExpression(node);
            case SyntaxKind.VoidKeyword:
                return voidType;
            case SyntaxKind.NeverKeyword:
                return neverType;
            case SyntaxKind.UnknownKeyword:
                return unknownType;
            case SyntaxKind.Return:
                return evalReturnKeyword(node);
            default:
                compilerAssert(false, `Can't eval the node ${SyntaxKind[node.kind]}`);
        }
    }
    function evalReturnKeyword(node) {
        const value = evalProjectionNode(node.value);
        if (value.kind === "Return") {
            return value;
        }
        return {
            kind: "Return",
            value,
        };
    }
    function evalProjectionModelExpression(node) {
        const modelType = createType({
            kind: "Model",
            name: "",
            node: node,
            decorators: [],
            properties: createRekeyableMap(),
            derivedModels: [],
            sourceModels: [],
        });
        for (const propNode of node.properties) {
            if (propNode.kind === SyntaxKind.ProjectionModelProperty) {
                const prop = evalProjectionModelProperty(propNode, modelType);
                if (prop.kind === "Return") {
                    return prop;
                }
                modelType.properties.set(prop.name, prop);
            }
            else {
                const props = evalProjectionModelSpreadProperty(propNode);
                if (!Array.isArray(props)) {
                    // return record
                    return props;
                }
                for (const newProp of props) {
                    modelType.properties.set(newProp.name, newProp);
                }
            }
        }
        return modelType;
    }
    function evalProjectionModelProperty(node, model) {
        const type = evalProjectionNode(node.value);
        if (type.kind === "Return") {
            return type;
        }
        return createType({
            kind: "ModelProperty",
            name: node.id.sv,
            node: node,
            decorators: [],
            optional: node.optional,
            type,
            model,
        });
    }
    function evalProjectionModelSpreadProperty(node) {
        const target = evalProjectionNode(node.target);
        if (target.kind === "Return") {
            return target;
        }
        if (target.kind !== "Model") {
            throw new ProjectionError(`Can only spread models`);
        }
        const props = [];
        // copy each property
        for (const prop of walkPropertiesInherited(target)) {
            const newProp = cloneType(prop, { sourceProperty: prop });
            props.push(newProp);
        }
        return props;
    }
    function evalProjectionRelationalExpression(node) {
        const left = evalProjectionNode(node.left);
        if (left.kind === "Return") {
            return left;
        }
        else if (left.kind !== "Number" && left.kind !== "String") {
            throw new ProjectionError("Can only compare numbers or strings");
        }
        const right = evalProjectionNode(node.right);
        if (right.kind === "Return") {
            return right;
        }
        else if (right.kind !== "Number" && right.kind !== "String") {
            throw new ProjectionError("Can only compare numbers or strings");
        }
        if (left.kind !== right.kind) {
            throw new ProjectionError("Can't compare numbers and strings");
        }
        switch (node.op) {
            case "<":
                return createLiteralType(left.value < right.value);
            case "<=":
                return createLiteralType(left.value <= right.value);
            case ">":
                return createLiteralType(left.value > right.value);
            case ">=":
                return createLiteralType(left.value >= right.value);
        }
    }
    function evalProjectionUnaryExpression(node) {
        const target = evalProjectionNode(node.target);
        if (target.kind !== "Boolean") {
            throw new ProjectionError("Can't negate a non-boolean");
        }
        switch (node.op) {
            case "!":
                return createLiteralType(!target.value);
        }
    }
    function evalProjectionEqualityExpression(node) {
        const left = evalProjectionNode(node.left);
        if (left.kind === "Return") {
            return left;
        }
        else if (left.kind !== "Number" && left.kind !== "String") {
            throw new ProjectionError("Comparisons must be strings or numbers");
        }
        const right = evalProjectionNode(node.right);
        if (right.kind === "Return") {
            return right;
        }
        else if (right.kind !== "Number" && right.kind !== "String") {
            throw new ProjectionError("Comparisons must be strings or numbers");
        }
        if (right.kind !== left.kind) {
            throw new ProjectionError("Can't compare number and string");
        }
        switch (node.op) {
            case "==":
                return createLiteralType(left.value === right.value);
            case "!=":
                return createLiteralType(left.value !== right.value);
        }
    }
    function evalProjectionIfExpression(node) {
        let ifExpr = node;
        while (ifExpr) {
            const test = evalProjectionNode(ifExpr.test);
            if (test.kind === "Return") {
                return test;
            }
            if (typeIsTruthy(test)) {
                return evalProjectionBlockExpression(ifExpr.consequent);
            }
            else if (ifExpr.alternate &&
                ifExpr.alternate.kind === SyntaxKind.ProjectionBlockExpression) {
                return evalProjectionBlockExpression(ifExpr.alternate);
            }
            else {
                ifExpr = ifExpr.alternate;
            }
        }
        return voidType;
    }
    function typeIsTruthy(t) {
        switch (t.kind) {
            case "Boolean":
                return t.value;
            case "Number":
                return !!t.value;
            case "String":
                return !!t.value;
            default:
                return true;
        }
    }
    function createEvalContext(node, parent) {
        return {
            node,
            locals: new Map(),
            parent,
        };
    }
    function evalProjectionBlockExpression(node) {
        let lastVal = voidType;
        for (const stmt of node.statements) {
            const stmtValue = evalProjectionNode(stmt);
            if (stmtValue.kind === "Return") {
                return stmtValue;
            }
            lastVal = stmtValue;
        }
        return lastVal;
    }
    function evalProjectionArithmeticExpression(node) {
        const lhs = evalProjectionNode(node.left);
        if (lhs.kind === "Return") {
            return lhs;
        }
        if (lhs.kind !== "Number" && lhs.kind !== "String") {
            throw new ProjectionError(`Operator ${node.op} can only apply to strings or numbers`);
        }
        const rhs = evalProjectionNode(node.right);
        if (rhs.kind === "Return") {
            return rhs;
        }
        if (rhs.kind !== "Number" && rhs.kind !== "String") {
            throw new ProjectionError(`Operator ${node.op} can only apply to strings or numbers`);
        }
        if (rhs.kind !== lhs.kind) {
            throw new ProjectionError(`Operator ${node.op}'s operands need to be the same type`);
        }
        if (lhs.kind === "String") {
            return createLiteralType(lhs.value + rhs.value);
        }
        else {
            return createLiteralType(lhs.value + rhs.value);
        }
    }
    function evalProjection(node, target, args) {
        if (node.direction === "<error>") {
            throw new ProjectionError("Cannot evaluate projection with invalid direction.");
        }
        let topLevelProjection = false;
        if (!currentProjectionDirection) {
            topLevelProjection = true;
            currentProjectionDirection = node.direction;
        }
        if (currentProjectionDirection === "from" && !target.projectionSource) {
            // this model wasn't projected, so we'll just return the target
            return target;
        }
        const originalContext = evalContext;
        evalContext = createEvalContext(node);
        for (const [i, param] of node.parameters.entries()) {
            if (!args[i]) {
                throw new ProjectionError("need argument for parameter " + SyntaxKind[node.parameters[i].kind]);
            }
            const argVal = args[i];
            let typeVal;
            if (typeof argVal === "number" || typeof argVal === "string" || typeof argVal === "boolean") {
                typeVal = createLiteralType(argVal);
            }
            else {
                typeVal = argVal;
            }
            evalContext.locals.set(param.id.sv, typeVal);
        }
        evalContext.locals.set("self", target);
        let lastVal = voidType;
        for (const item of node.body) {
            lastVal = evalProjectionNode(item);
            if (lastVal.kind === "Return") {
                break;
            }
        }
        if (topLevelProjection) {
            currentProjectionDirection = undefined;
        }
        const selfResult = evalContext.locals.get("self");
        evalContext = originalContext;
        if (lastVal.kind === "Return") {
            return lastVal.value;
        }
        else {
            return selfResult;
        }
    }
    function evalProjectionExpressionStatement(node) {
        return evalProjectionNode(node.expr);
    }
    function evalProjectionCallExpression(node) {
        const target = evalProjectionNode(node.target);
        if (!target)
            throw new ProjectionError("target undefined");
        const args = [];
        for (const arg of node.arguments) {
            args.push(evalProjectionNode(arg));
        }
        if (target.kind !== "Function") {
            throw new ProjectionError("Can't call non-function, got type " + target.kind);
        }
        return target.implementation(...args);
    }
    function evalProjectionMemberExpression(node) {
        const base = evalProjectionNode(node.base);
        if (base.kind === "Return") {
            return base;
        }
        const member = node.id.sv;
        const selector = node.selector;
        if (selector === ".") {
            switch (base.kind) {
                case "Namespace":
                    const sym = base.node.symbol.exports.get(member);
                    if (sym) {
                        const links = getSymbolLinks(sym);
                        return links.declaredType || links.type || errorType;
                    }
                    else {
                        throw new ProjectionError(`Namespace doesn't have member ${member}`);
                    }
                case "Model":
                    const prop = base.properties.get(member);
                    if (!prop) {
                        throw new ProjectionError(`Model doesn't have property ${member}`);
                    }
                    return prop;
                case "Enum":
                    const enumMember = base.members.get(member);
                    if (!enumMember) {
                        throw new ProjectionError(`Enum doesn't have member ${member}`);
                    }
                    return enumMember;
                case "Union":
                    const variant = base.variants.get(member);
                    if (!variant) {
                        throw new ProjectionError(`Union doesn't have variant ${member}`);
                    }
                    return variant;
                default:
                    throw new ProjectionError(`Can't get member "${member}" of type ${base.kind} because it has no members. Did you mean to use "::" instead of "."?`);
            }
        }
        switch (base.kind) {
            case "Object":
                return base.properties[member] || errorType;
            default:
                const typeOps = projectionMembers[base.kind];
                if (!typeOps) {
                    throw new ProjectionError(`${base.kind} doesn't have an object model member named ${member}`);
                }
                // any cast needed to ensure we don't get a too complex union error on the call
                // to op further down.
                const op = typeOps[member];
                if (!op) {
                    throw new ProjectionError(`${base.kind} doesn't have an object model member named ${member}`);
                }
                return op(base);
        }
    }
    function createFunctionType(fn) {
        const parameters = [];
        return createType({
            kind: "Function",
            name: "",
            parameters,
            returnType: unknownType,
            implementation: fn,
        });
    }
    function createLiteralType(value, node) {
        if (program.literalTypes.has(value)) {
            return program.literalTypes.get(value);
        }
        let type;
        switch (typeof value) {
            case "string":
                type = createType({ kind: "String", value });
                break;
            case "boolean":
                type = createType({ kind: "Boolean", value });
                break;
            case "number":
                let valueAsString;
                if (node) {
                    compilerAssert(node.kind === SyntaxKind.NumericLiteral, "Must pass numeric literal node or undefined when creating a numeric literal type");
                    valueAsString = node.valueAsString;
                }
                else {
                    valueAsString = String(value);
                }
                type = createType({
                    kind: "Number",
                    value,
                    valueAsString,
                    numericValue: Numeric(valueAsString),
                });
                break;
        }
        program.literalTypes.set(value, type);
        return type;
    }
    function evalProjectionDecoratorReference(node) {
        const ref = resolveTypeReferenceSym(node.target, undefined, true);
        if (!ref)
            throw new ProjectionError("Can't find decorator.");
        compilerAssert(ref.flags & 16384 /* SymbolFlags.Decorator */, "should only resolve decorator symbols");
        return createFunctionType((...args) => {
            ref.value({ program }, ...args.map(unsafe_projectionArgumentMarshalForJS));
            return voidType;
        });
    }
    function evalProjectionIdentifier(node) {
        // first check the eval context
        let currentContext = evalContext;
        while (currentContext) {
            if (currentContext.locals.has(node.sv)) {
                return currentContext.locals.get(node.sv);
            }
            currentContext = currentContext.parent;
        }
        // next, resolve outside
        const ref = resolveTypeReferenceSym(node, undefined);
        if (!ref)
            throw new ProjectionError("Unknown identifier " + node.sv);
        if (ref.flags & 16384 /* SymbolFlags.Decorator */) {
            // shouldn't ever resolve a decorator symbol here (without passing
            // true to resolveTypeReference)
            return errorType;
        }
        else if (ref.flags & 131072 /* SymbolFlags.Function */) {
            // TODO: store this in a symbol link probably?
            const t = createFunctionType((...args) => {
                const retval = ref.value(program, ...args.map(unsafe_projectionArgumentMarshalForJS));
                return marshalProjectionReturn(retval, { functionName: node.sv });
            });
            return t;
        }
        else {
            const links = getSymbolLinks(ref);
            compilerAssert(links.declaredType, "Should have checked all types by now");
            return links.declaredType;
        }
    }
    function marshalProjectionReturn(value, options = {}) {
        if (typeof value === "boolean" || typeof value === "string" || typeof value === "number") {
            return createLiteralType(value);
        }
        if (typeof value === "object" && value !== null) {
            if ("kind" in value) {
                return value;
            }
            else {
                // this could probably be more robust
                return createType({
                    kind: "Object",
                    properties: value,
                });
            }
        }
        if (options.functionName) {
            throw new ProjectionError(`Can't marshal value "${value}" returned from JS function "${options.functionName}" into typespec`);
        }
        else {
            throw new ProjectionError(`Can't marshal value "${value}" into typespec`);
        }
    }
    function evalProjectionLambdaExpression(node) {
        return createFunctionType((...args) => {
            return callLambdaExpression(node, args);
        });
    }
    function callLambdaExpression(node, args) {
        const originalContext = evalContext;
        evalContext = createEvalContext(node, originalContext);
        for (const [i, param] of node.parameters.entries()) {
            evalContext.locals.set(param.id.sv, args[i]);
        }
        const retval = evalProjectionBlockExpression(node.body);
        evalContext = originalContext;
        if (retval.kind === "Return") {
            return retval.value;
        }
        return retval;
    }
    function evalStringLiteral(node) {
        return createLiteralType(node.value, node);
    }
    function evalNumericLiteral(node) {
        return createLiteralType(node.value, node);
    }
    function evalBooleanLiteral(node) {
        return createLiteralType(node.value, node);
    }
    function project(target, projection, args = []) {
        return evalProjection(projection, target, args.map((x) => marshalProjectionReturn(x)));
    }
    function memberExpressionToString(expr) {
        let current = expr;
        const parts = [];
        while (current.kind === SyntaxKind.MemberExpression) {
            parts.push(current.id.sv);
            current = current.base;
        }
        parts.push(current.sv);
        return parts.reverse().join(".");
    }
    /**
     * Check if the source type can be assigned to the target type and emit diagnostics
     * @param source Type of a value
     * @param constraint
     * @param diagnosticTarget Target for the diagnostic, unless something better can be inferred.
     */
    function checkTypeOfValueMatchConstraint(source, constraint, diagnosticTarget) {
        const [related, diagnostics] = isTypeAssignableTo(source, constraint.type, diagnosticTarget);
        if (!related) {
            if (constraint.kind === "argument") {
                reportCheckerDiagnostic(createDiagnostic({
                    code: "invalid-argument",
                    format: {
                        value: getEntityName(source),
                        expected: getEntityName(constraint.type),
                    },
                    target: diagnosticTarget,
                }));
            }
            else {
                reportCheckerDiagnostics(diagnostics);
            }
        }
        return related;
    }
    /**
     * Check if the source type can be assigned to the target type and emit diagnostics
     * @param source Source type
     * @param target Target type
     * @param diagnosticTarget Target for the diagnostic, unless something better can be inferred.
     */
    function checkTypeAssignable(source, target, diagnosticTarget) {
        const [related, diagnostics] = isTypeAssignableTo(source, target, diagnosticTarget);
        if (!related) {
            reportCheckerDiagnostics(diagnostics);
        }
        return related;
    }
    function checkValueOfType(source, target, diagnosticTarget) {
        const [related, diagnostics] = isValueOfType(source, target, diagnosticTarget);
        if (!related) {
            reportCheckerDiagnostics(diagnostics);
        }
        return related;
    }
    /**
     * Check if the source type can be assigned to the target type.
     * @param source Source type
     * @param target Target type
     * @param diagnosticTarget Target for the diagnostic, unless something better can be inferred.
     */
    function isTypeAssignableTo(source, target, diagnosticTarget) {
        const [related, diagnostics] = isTypeAssignableToInternal(source, target, diagnosticTarget, new MultiKeyMap());
        return [related === Related.true, diagnostics];
    }
    /**
     * Check if the given Value type is of the given type.
     * @param source Value
     * @param target Target type
     * @param diagnosticTarget Target for the diagnostic, unless something better can be inferred.
     */
    function isValueOfType(source, target, diagnosticTarget) {
        const [related, diagnostics] = isValueOfTypeInternal(source, target, diagnosticTarget, new MultiKeyMap());
        return [related === Related.true, diagnostics];
    }
    function isTypeAssignableToInternal(source, target, diagnosticTarget, relationCache) {
        const cached = relationCache.get([source, target]);
        if (cached !== undefined) {
            return [cached, []];
        }
        const [result, diagnostics] = isTypeAssignableToWorker(source, target, diagnosticTarget, new MultiKeyMap());
        relationCache.set([source, target], result);
        return [result, diagnostics];
    }
    function isTypeAssignableToWorker(source, target, diagnosticTarget, relationCache) {
        // BACKCOMPAT: Allow certain type to be accepted as values
        if ("kind" in source &&
            "entityKind" in target &&
            source.kind === "TemplateParameter" &&
            source.constraint?.type &&
            source.constraint.valueType === undefined &&
            target.entityKind === "MixedParameterConstraint" &&
            target.valueType) {
            const [assignable] = isTypeAssignableToInternal(source.constraint.type, target.valueType, diagnosticTarget, relationCache);
            if (assignable) {
                const constraint = getEntityName(source.constraint);
                reportDeprecated(program, `Template constrainted to '${constraint}' will not be assignable to '${getEntityName(target)}' in the future. Update the constraint to be 'valueof ${constraint}'`, diagnosticTarget);
                return [Related.true, []];
            }
        }
        if ("kind" in source && source.kind === "TemplateParameter") {
            source = source.constraint ?? unknownType;
        }
        if (target.entityKind === "Indeterminate") {
            target = target.type;
        }
        if (source === target)
            return [Related.true, []];
        if (isValue(target)) {
            return [Related.false, [createUnassignableDiagnostic(source, target, diagnosticTarget)]];
        }
        if (source.entityKind === "Indeterminate") {
            return isIndeterminateEntityAssignableTo(source, target, diagnosticTarget, relationCache);
        }
        if (target.entityKind === "MixedParameterConstraint") {
            return isAssignableToMixedParameterConstraint(source, target, diagnosticTarget, relationCache);
        }
        if (isValue(source) || (source.entityKind === "MixedParameterConstraint" && source.valueType)) {
            return [Related.false, [createUnassignableDiagnostic(source, target, diagnosticTarget)]];
        }
        if (source.entityKind === "MixedParameterConstraint") {
            return isTypeAssignableToInternal(source.type, target, diagnosticTarget, relationCache);
        }
        const isSimpleTypeRelated = isSimpleTypeAssignableTo(source, target);
        if (isSimpleTypeRelated === true) {
            return [Related.true, []];
        }
        else if (isSimpleTypeRelated === false) {
            return [Related.false, [createUnassignableDiagnostic(source, target, diagnosticTarget)]];
        }
        if (source.kind === "Union") {
            for (const variant of source.variants.values()) {
                const [variantAssignable] = isTypeAssignableToInternal(variant.type, target, diagnosticTarget, relationCache);
                if (!variantAssignable) {
                    return [Related.false, [createUnassignableDiagnostic(source, target, diagnosticTarget)]];
                }
            }
            return [Related.true, []];
        }
        if (target.kind === "Model" &&
            source.kind === "Model" &&
            target.name !== "object" &&
            target.indexer === undefined &&
            source.indexer &&
            source.indexer.key.name === "integer") {
            return [
                Related.false,
                [
                    createDiagnostic({
                        code: "missing-index",
                        format: {
                            indexType: getTypeName(source.indexer.key),
                            sourceType: getTypeName(target),
                        },
                        target: diagnosticTarget,
                    }),
                ],
            ];
        }
        else if (target.kind === "Model" &&
            isArrayModelType(program, target) &&
            source.kind === "Model") {
            if (isArrayModelType(program, source)) {
                return hasIndexAndIsAssignableTo(source, target, diagnosticTarget, relationCache);
            }
            else {
                // For other models just fallback to unassignable
                return [Related.false, [createUnassignableDiagnostic(source, target, diagnosticTarget)]];
            }
        }
        else if (target.kind === "Model" && source.kind === "Model") {
            return isModelRelatedTo(source, target, diagnosticTarget, relationCache);
        }
        else if (target.kind === "Model" &&
            isArrayModelType(program, target) &&
            source.kind === "Tuple") {
            return isTupleAssignableToArray(source, target, diagnosticTarget, relationCache);
        }
        else if (target.kind === "Tuple" && source.kind === "Tuple") {
            return isTupleAssignableToTuple(source, target, diagnosticTarget, relationCache);
        }
        else if (target.kind === "Union") {
            return isAssignableToUnion(source, target, diagnosticTarget, relationCache);
        }
        else if (target.kind === "Enum") {
            return isAssignableToEnum(source, target, diagnosticTarget);
        }
        return [Related.false, [createUnassignableDiagnostic(source, target, diagnosticTarget)]];
    }
    function isIndeterminateEntityAssignableTo(indeterminate, target, diagnosticTarget, relationCache) {
        const [typeRelated, typeDiagnostics] = isTypeAssignableToInternal(indeterminate.type, target, diagnosticTarget, relationCache);
        if (typeRelated) {
            return [Related.true, []];
        }
        if (target.entityKind === "MixedParameterConstraint" && target.valueType) {
            const [valueRelated] = isTypeAssignableToInternal(indeterminate.type, target.valueType, diagnosticTarget, relationCache);
            if (valueRelated) {
                return [Related.true, []];
            }
        }
        return [Related.false, typeDiagnostics];
    }
    function isAssignableToValueType(source, target, diagnosticTarget, relationCache) {
        if (!isValue(source)) {
            return [Related.false, [createUnassignableDiagnostic(source, target, diagnosticTarget)]];
        }
        return isValueOfTypeInternal(source, target, diagnosticTarget, relationCache);
    }
    function isAssignableToMixedParameterConstraint(source, target, diagnosticTarget, relationCache) {
        if ("entityKind" in source && source.entityKind === "MixedParameterConstraint") {
            if (source.type && target.type) {
                const [variantAssignable, diagnostics] = isTypeAssignableToInternal(source.type, target.type, diagnosticTarget, relationCache);
                if (variantAssignable === Related.false) {
                    return [Related.false, diagnostics];
                }
                return [Related.true, []];
            }
            if (source.valueType && target.valueType) {
                const [variantAssignable, diagnostics] = isTypeAssignableToInternal(source.valueType, target.valueType, diagnosticTarget, relationCache);
                if (variantAssignable === Related.false) {
                    return [Related.false, diagnostics];
                }
                return [Related.true, []];
            }
            return [Related.false, [createUnassignableDiagnostic(source, target, diagnosticTarget)]];
        }
        if (target.type) {
            const [related] = isTypeAssignableToInternal(source, target.type, diagnosticTarget, relationCache);
            if (related) {
                return [Related.true, []];
            }
        }
        if (target.valueType) {
            const [related] = isAssignableToValueType(source, target.valueType, diagnosticTarget, relationCache);
            if (related) {
                return [Related.true, []];
            }
        }
        return [Related.false, [createUnassignableDiagnostic(source, target, diagnosticTarget)]];
    }
    /** Check if the value is assignable to the given type. */
    function isValueOfTypeInternal(source, target, diagnosticTarget, relationCache) {
        return isTypeAssignableToInternal(source.type, target, diagnosticTarget, relationCache);
    }
    function isReflectionType(type) {
        return (type.kind === "Model" &&
            type.namespace?.name === "Reflection" &&
            type.namespace?.namespace?.name === "TypeSpec");
    }
    function isRelatedToScalar(source, target) {
        switch (source.kind) {
            case "Number":
                return isNumericLiteralRelatedTo(source, target);
            case "String":
            case "StringTemplate":
                return isStringLiteralRelatedTo(source, target);
            case "Boolean":
                return areScalarsRelated(target, getStdType("boolean"));
            case "Scalar":
                return areScalarsRelated(source, target);
            case "Union":
                return undefined;
            default:
                return false;
        }
    }
    function areScalarsRelated(source, target) {
        let current = source;
        while (current) {
            if (current === target) {
                return true;
            }
            current = current.baseScalar;
        }
        return false;
    }
    function isSimpleTypeAssignableTo(source, target) {
        if (isNeverType(source))
            return true;
        if (isVoidType(target))
            return false;
        if (isUnknownType(target))
            return true;
        if (isReflectionType(target)) {
            return source.kind === ReflectionNameToKind[target.name];
        }
        if (target.kind === "Scalar") {
            return isRelatedToScalar(source, target);
        }
        if (source.kind === "Scalar" && target.kind === "Model") {
            return false;
        }
        if (target.kind === "String") {
            return ((source.kind === "String" && source.value === target.value) ||
                (source.kind === "StringTemplate" && source.stringValue === target.value));
        }
        if (target.kind === "StringTemplate" && target.stringValue) {
            return ((source.kind === "String" && source.value === target.stringValue) ||
                (source.kind === "StringTemplate" && source.stringValue === target.stringValue));
        }
        if (target.kind === "Number") {
            return source.kind === "Number" && target.value === source.value;
        }
        return undefined;
    }
    function isNumericLiteralRelatedTo(source, target) {
        // First check that the source numeric literal is assignable to the target scalar
        if (!isNumericAssignableToNumericScalar(source.numericValue, target)) {
            return false;
        }
        const min = getMinValueAsNumeric(program, target);
        const max = getMaxValueAsNumeric(program, target);
        const minExclusive = getMinValueExclusiveAsNumeric(program, target);
        const maxExclusive = getMaxValueExclusiveAsNumeric(program, target);
        if (min && source.numericValue.lt(min)) {
            return false;
        }
        if (minExclusive && source.numericValue.lte(minExclusive)) {
            return false;
        }
        if (max && source.numericValue.gt(max)) {
            return false;
        }
        if (maxExclusive && source.numericValue.gte(maxExclusive)) {
            return false;
        }
        return true;
    }
    function isNumericAssignableToNumericScalar(source, target) {
        // if the target does not derive from numeric, then it can't be assigned a numeric literal
        if (!areScalarsRelated(target, getStdType("numeric"))) {
            return false;
        }
        // With respect to literal assignability a custom numeric scalar is
        // equivalent to its nearest TypeSpec.* base. Adjust target accordingly.
        while (!target.namespace || !isTypeSpecNamespace(target.namespace)) {
            compilerAssert(target.baseScalar, "Should not be possible to be derived from TypeSpec.numeric and not have a base when not in TypeSpec namespace.");
            target = target.baseScalar;
        }
        if (target.name === "numeric")
            return true;
        if (target.name === "decimal")
            return true;
        if (target.name === "decimal128")
            return true;
        const isInt = source.isInteger;
        if (target.name === "integer")
            return isInt;
        if (target.name === "float")
            return true;
        if (!(target.name in numericRanges))
            return false;
        const [low, high, options] = numericRanges[target.name];
        return source.gte(low) && source.lte(high) && (!options.int || isInt);
    }
    function isStringLiteralRelatedTo(source, target) {
        if (!areScalarsRelated(target, getStdType("string"))) {
            return false;
        }
        if (source.kind === "StringTemplate") {
            return true;
        }
        const len = source.value.length;
        const min = getMinLength(program, target);
        const max = getMaxLength(program, target);
        if (min && len < min) {
            return false;
        }
        if (max && len > max) {
            return false;
        }
        return true;
    }
    function isModelRelatedTo(source, target, diagnosticTarget, relationCache) {
        relationCache.set([source, target], Related.maybe);
        const diagnostics = [];
        const remainingProperties = new Map(source.properties);
        for (const prop of walkPropertiesInherited(target)) {
            const sourceProperty = getProperty(source, prop.name);
            if (sourceProperty === undefined) {
                if (!prop.optional) {
                    diagnostics.push(createDiagnostic({
                        code: "missing-property",
                        format: {
                            propertyName: prop.name,
                            sourceType: getTypeName(source),
                            targetType: getTypeName(target),
                        },
                        target: source,
                    }));
                }
            }
            else {
                remainingProperties.delete(prop.name);
                if (sourceProperty.optional && !prop.optional) {
                    diagnostics.push(createDiagnostic({
                        code: "property-required",
                        format: {
                            propName: prop.name,
                            targetType: getTypeName(target),
                        },
                        target: diagnosticTarget,
                    }));
                }
                const [related, propDiagnostics] = isTypeAssignableToInternal(sourceProperty.type, prop.type, diagnosticTarget, relationCache);
                if (!related) {
                    diagnostics.push(...propDiagnostics);
                }
            }
        }
        if (target.indexer) {
            const [_, indexerDiagnostics] = arePropertiesAssignableToIndexer(remainingProperties, target.indexer.value, diagnosticTarget, relationCache);
            diagnostics.push(...indexerDiagnostics);
            // For anonymous models we don't need an indexer
            if (source.name !== "" && target.indexer.key.name !== "integer") {
                const [related, indexDiagnostics] = hasIndexAndIsAssignableTo(source, target, diagnosticTarget, relationCache);
                if (!related) {
                    diagnostics.push(...indexDiagnostics);
                }
            }
        }
        else if (shouldCheckExcessProperties(source)) {
            for (const [propName, prop] of remainingProperties) {
                if (shouldCheckExcessProperty(prop)) {
                    diagnostics.push(createDiagnostic({
                        code: "unexpected-property",
                        format: {
                            propertyName: propName,
                            type: getEntityName(target),
                        },
                        target: prop,
                    }));
                }
            }
        }
        return [diagnostics.length === 0 ? Related.true : Related.false, diagnostics];
    }
    /** If we should check for excess properties on the given model. */
    function shouldCheckExcessProperties(model) {
        return model.node?.kind === SyntaxKind.ObjectLiteral;
    }
    /** If we should check for this specific property */
    function shouldCheckExcessProperty(prop) {
        return (prop.node?.kind === SyntaxKind.ObjectLiteralProperty && prop.node.parent === prop.model?.node);
    }
    function getProperty(model, name) {
        return (model.properties.get(name) ??
            (model.baseModel !== undefined ? getProperty(model.baseModel, name) : undefined));
    }
    function arePropertiesAssignableToIndexer(properties, indexerConstaint, diagnosticTarget, relationCache) {
        for (const prop of properties.values()) {
            const [related, diagnostics] = isTypeAssignableToInternal(prop.type, indexerConstaint, diagnosticTarget, relationCache);
            if (!related) {
                return [Related.false, diagnostics];
            }
        }
        return [Related.true, []];
    }
    /** Check that the source model has an index, the index key match and the value of the source index is assignable to the target index. */
    function hasIndexAndIsAssignableTo(source, target, diagnosticTarget, relationCache) {
        if (source.indexer === undefined || source.indexer.key !== target.indexer.key) {
            return [
                Related.false,
                [
                    createDiagnostic({
                        code: "missing-index",
                        format: {
                            indexType: getTypeName(target.indexer.key),
                            sourceType: getTypeName(source),
                        },
                        target: diagnosticTarget,
                    }),
                ],
            ];
        }
        return isTypeAssignableToInternal(source.indexer.value, target.indexer.value, diagnosticTarget, relationCache);
    }
    function isTupleAssignableToArray(source, target, diagnosticTarget, relationCache) {
        const minItems = getMinItems(program, target);
        const maxItems = getMaxItems(program, target);
        if (minItems !== undefined && source.values.length < minItems) {
            return [
                Related.false,
                [
                    createDiagnostic({
                        code: "unassignable",
                        messageId: "withDetails",
                        format: {
                            sourceType: getEntityName(source),
                            targetType: getTypeName(target),
                            details: `Source has ${source.values.length} element(s) but target requires ${minItems}.`,
                        },
                        target: diagnosticTarget,
                    }),
                ],
            ];
        }
        if (maxItems !== undefined && source.values.length > maxItems) {
            return [
                Related.false,
                [
                    createDiagnostic({
                        code: "unassignable",
                        messageId: "withDetails",
                        format: {
                            sourceType: getEntityName(source),
                            targetType: getTypeName(target),
                            details: `Source has ${source.values.length} element(s) but target only allows ${maxItems}.`,
                        },
                        target: diagnosticTarget,
                    }),
                ],
            ];
        }
        for (const item of source.values) {
            const [related, diagnostics] = isTypeAssignableToInternal(item, target.indexer.value, diagnosticTarget, relationCache);
            if (!related) {
                return [Related.false, diagnostics];
            }
        }
        return [Related.true, []];
    }
    function isTupleAssignableToTuple(source, target, diagnosticTarget, relationCache) {
        if (source.values.length !== target.values.length) {
            return [
                Related.false,
                [
                    createDiagnostic({
                        code: "unassignable",
                        messageId: "withDetails",
                        format: {
                            sourceType: getEntityName(source),
                            targetType: getTypeName(target),
                            details: `Source has ${source.values.length} element(s) but target requires ${target.values.length}.`,
                        },
                        target: diagnosticTarget,
                    }),
                ],
            ];
        }
        for (const [index, sourceItem] of source.values.entries()) {
            const targetItem = target.values[index];
            const [related, diagnostics] = isTypeAssignableToInternal(sourceItem, targetItem, diagnosticTarget, relationCache);
            if (!related) {
                return [Related.false, diagnostics];
            }
        }
        return [Related.true, []];
    }
    function isAssignableToUnion(source, target, diagnosticTarget, relationCache) {
        if (source.kind === "UnionVariant" && source.union === target) {
            return [Related.true, []];
        }
        for (const option of target.variants.values()) {
            const [related] = isTypeAssignableToInternal(source, option.type, diagnosticTarget, relationCache);
            if (related) {
                return [Related.true, []];
            }
        }
        return [Related.false, [createUnassignableDiagnostic(source, target, diagnosticTarget)]];
    }
    function isAssignableToEnum(source, target, diagnosticTarget) {
        switch (source.kind) {
            case "Enum":
                if (source === target) {
                    return [Related.true, []];
                }
                else {
                    return [Related.false, [createUnassignableDiagnostic(source, target, diagnosticTarget)]];
                }
            case "EnumMember":
                if (source.enum === target) {
                    return [Related.true, []];
                }
                else {
                    return [Related.false, [createUnassignableDiagnostic(source, target, diagnosticTarget)]];
                }
            default:
                return [Related.false, [createUnassignableDiagnostic(source, target, diagnosticTarget)]];
        }
    }
    function createUnassignableDiagnostic(source, target, diagnosticTarget) {
        return createDiagnostic({
            code: "unassignable",
            format: { targetType: getEntityName(target), value: getEntityName(source) },
            target: diagnosticTarget,
        });
    }
    function isStdType(type, stdType) {
        type = type.projectionBase ?? type;
        if ((type.kind !== "Model" && type.kind !== "Scalar") ||
            type.namespace === undefined ||
            !isTypeSpecNamespace(type.namespace))
            return false;
        if (type.kind === "Scalar")
            return stdType === undefined || stdType === type.name;
        if (stdType === "Array" && type === stdTypes["Array"])
            return true;
        if (stdType === "Record" && type === stdTypes["Record"])
            return true;
        if (type.kind === "Model")
            return stdType === undefined || stdType === type.name;
        return false;
    }
    function getValueExactType(value) {
        return valueExactTypes.get(value);
    }
}
function isAnonymous(type) {
    return !("name" in type) || typeof type.name !== "string" || !type.name;
}
/**
 * Find all named models that could have been the source of the given
 * property. This includes the named parents of all property sources in a
 * chain.
 */
function getNamedSourceModels(property) {
    if (!property.sourceProperty) {
        return undefined;
    }
    const set = new Set();
    for (let p = property; p; p = p.sourceProperty) {
        if (p.model?.name) {
            set.add(p.model);
        }
    }
    return set;
}
/**
 * Find derived types of `models` in `possiblyDerivedModels` and add them to
 * `models`.
 */
function addDerivedModels(models, possiblyDerivedModels) {
    for (const element of possiblyDerivedModels) {
        if (!models.has(element)) {
            for (let t = element.baseModel; t; t = t.baseModel) {
                if (models.has(t)) {
                    models.add(element);
                    break;
                }
            }
        }
    }
}
function createTypeMapper(parameters, args, parentMapper) {
    const map = new Map(parentMapper?.map ?? []);
    for (const [index, param] of parameters.entries()) {
        map.set(param, args[index]);
    }
    return {
        partial: false,
        args: [...(parentMapper?.args ?? []), ...args],
        getMappedType: (type) => {
            return map.get(type) ?? type;
        },
        map,
    };
}
/**
 * If the input is anonymous (or the provided filter removes properties)
 * and there exists a named model with the same set of properties
 * (ignoring filtered properties), then return that named model.
 * Otherwise, return the input unchanged.
 *
 * This can be used by emitters to find a better name for a set of
 * properties after filtering. For example, given `{ @metadata prop:
 * string} & SomeName`, and an emitter that wishes to discard properties
 * marked with `@metadata`, the emitter can use this to recover that the
 * best name for the remaining properties is `SomeName`.
 *
 * @param model The input model
 * @param filter An optional filter to apply to the input model's
 * properties.
 */
function getEffectiveModelType(program, model, filter) {
    if (filter) {
        model = filterModelProperties(program, model, filter);
    }
    if (model.name) {
        // named model
        return model;
    }
    // We would need to change the algorithm if this doesn't hold. We
    // assume model has no inherited properties below.
    compilerAssert(!model.baseModel, "Anonymous model with base model.");
    if (model.properties.size === 0) {
        // empty model
        return model;
    }
    // Find the candidate set of named model types that could have been the
    // source of every property in the model.
    let candidates;
    for (const property of model.properties.values()) {
        const sources = getNamedSourceModels(property);
        if (!sources) {
            // unsourced property: no possible match
            return model;
        }
        if (!candidates) {
            // first sourced property: initialize candidates to its sources
            candidates = sources;
            continue;
        }
        // Add derived sources as we encounter them. If a model is sourced from
        // a base property, then it can also be sourced from a derived model.
        //
        // (Unless it is overridden, but then the presence of the overridden
        // property will still cause the the base model to be excluded from the
        // candidates.)
        //
        // Note: We depend on the order of that spread and intersect source
        // properties here, which is that we see properties sourced from derived
        // types before properties sourced from their base types.
        addDerivedModels(sources, candidates);
        // remove candidates that are not common to this property.
        for (const candidate of candidates) {
            if (!sources.has(candidate)) {
                candidates.delete(candidate);
            }
        }
    }
    // Search for a candidate that has no additional properties (ignoring
    // filtered properties). If so, it is effectively the same type as the
    // input model. Consider a candidate that meets this test without
    // ignoring filtering as a better match than one that requires filtering
    // to meet this test.
    let match;
    for (const candidate of candidates ?? []) {
        if (model.properties.size === countPropertiesInherited(candidate)) {
            match = candidate;
            break; // exact match
        }
        if (filter && !match && model.properties.size === countPropertiesInherited(candidate, filter)) {
            match = candidate;
            continue; // match with filter: keep searching for exact match
        }
    }
    return match ?? model;
}
/**
 * Applies a filter to the properties of a given type. If no properties
 * are filtered out, then return the input unchanged. Otherwise, return
 * a new anonymous model with only the filtered properties.
 *
 * @param model The input model to filter.
 * @param filter The filter to apply. Properties are kept when this returns true.
 */
function filterModelProperties(program, model, filter) {
    let filtered = false;
    for (const property of walkPropertiesInherited(model)) {
        if (!filter(property)) {
            filtered = true;
            break;
        }
    }
    if (!filtered) {
        return model;
    }
    const properties = createRekeyableMap();
    const newModel = program.checker.createType({
        kind: "Model",
        node: undefined,
        name: "",
        indexer: undefined,
        properties,
        decorators: [],
        derivedModels: [],
        sourceModels: [{ usage: "spread", model }],
    });
    for (const property of walkPropertiesInherited(model)) {
        if (filter(property)) {
            const newProperty = program.checker.cloneType(property, {
                sourceProperty: property,
                model: newModel,
            });
            properties.set(property.name, newProperty);
        }
    }
    return finishTypeForProgram(program, newModel);
}
/**
 * Gets the property from the nearest base type that is overridden by the
 * given property, if any.
 */
function getOverriddenProperty(property) {
    compilerAssert(property.model, "Parent model must be set before overridden property can be found.");
    for (let current = property.model.baseModel; current; current = current.baseModel) {
        const overridden = current.properties.get(property.name);
        if (overridden) {
            return overridden;
        }
    }
    return undefined;
}
/**
 * Enumerates the properties declared by model or inherited from its base.
 *
 * Properties declared by more derived types are enumerated before properties
 * of less derived types.
 *
 * Properties that are overridden are not enumerated.
 */
function* walkPropertiesInherited(model) {
    const returned = new Set();
    for (let current = model; current; current = current.baseModel) {
        for (const property of current.properties.values()) {
            if (returned.has(property.name)) {
                // skip properties that have been overridden
                continue;
            }
            returned.add(property.name);
            yield property;
        }
    }
}
function countPropertiesInherited(model, filter) {
    let count = 0;
    for (const property of walkPropertiesInherited(model)) {
        if (!filter || filter(property)) {
            count++;
        }
    }
    return count;
}
function finishTypeForProgram(program, typeDef) {
    return finishTypeForProgramAndChecker(program, program.checker.typePrototype, typeDef);
}
function linkMapper(typeDef, mapper) {
    if (mapper) {
        compilerAssert(!typeDef.templateArguments, "Mapper provided but template arguments already set.");
        typeDef.templateMapper = mapper;
        typeDef.templateArguments = mapper.args;
    }
}
function extractMainDoc(type) {
    if (type.node?.docs === undefined) {
        return undefined;
    }
    let mainDoc = "";
    for (const doc of type.node.docs) {
        mainDoc += getDocContent(doc.content);
    }
    const trimmed = mainDoc.trim();
    return trimmed === "" ? undefined : trimmed;
}
function extractReturnsDocs(type) {
    const result = {
        returns: undefined,
        errors: undefined,
    };
    if (type.node?.docs === undefined) {
        return result;
    }
    for (const doc of type.node.docs) {
        for (const tag of doc.tags) {
            if (tag.kind === SyntaxKind.DocReturnsTag) {
                result.returns = getDocContent(tag.content);
            }
            if (tag.kind === SyntaxKind.DocErrorsTag) {
                result.errors = getDocContent(tag.content);
            }
        }
    }
    return result;
}
function extractParamDocs(node) {
    if (node.docs === undefined) {
        return new Map();
    }
    const paramDocs = new Map();
    for (const doc of node.docs) {
        for (const tag of doc.tags) {
            if (tag.kind === SyntaxKind.DocParamTag) {
                paramDocs.set(tag.paramName.sv, getDocContent(tag.content));
            }
        }
    }
    return paramDocs;
}
function extractPropDocs(node) {
    if (node.docs === undefined) {
        return new Map();
    }
    const propDocs = new Map();
    for (const doc of node.docs) {
        for (const tag of doc.tags) {
            if (tag.kind === SyntaxKind.DocPropTag) {
                propDocs.set(tag.propName.sv, getDocContent(tag.content));
            }
        }
    }
    return propDocs;
}
function getDocContent(content) {
    const docs = [];
    for (const node of content) {
        compilerAssert(node.kind === SyntaxKind.DocText, "No other doc content node kinds exist yet. Update this code appropriately when more are added.");
        docs.push(node.text);
    }
    return docs.join("");
}
function finishTypeForProgramAndChecker(program, typePrototype, typeDef) {
    if ("decorators" in typeDef) {
        for (const decApp of typeDef.decorators) {
            applyDecoratorToType(program, decApp, typeDef);
        }
    }
    Object.setPrototypeOf(typeDef, typePrototype);
    typeDef.isFinished = true;
    return typeDef;
}
function reportDeprecation(program, target, message, reportFunc) {
    if (program.compilerOptions.ignoreDeprecated !== true) {
        reportFunc(createDiagnostic({
            code: "deprecated",
            format: {
                message,
            },
            target,
        }));
    }
}
function applyDecoratorToType(program, decApp, target) {
    compilerAssert("decorators" in target, "Cannot apply decorator to non-decoratable type", target);
    for (const arg of decApp.args) {
        if (isType(arg.value) && isErrorType(arg.value)) {
            // If one of the decorator argument is an error don't run it.
            return;
        }
    }
    // Is the decorator definition deprecated?
    if (decApp.definition) {
        const deprecation = getDeprecationDetails(program, decApp.definition);
        if (deprecation !== undefined) {
            reportDeprecation(program, decApp.node ?? target, deprecation.message, program.reportDiagnostic);
        }
    }
    // peel `fn` off to avoid setting `this`.
    try {
        const args = decApp.args.map((x) => x.jsValue);
        const fn = decApp.decorator;
        const context = createDecoratorContext(program, decApp);
        fn(context, target, ...args);
    }
    catch (error) {
        // do not fail the language server for exceptions in decorators
        if (program.compilerOptions.designTimeBuild) {
            program.reportDiagnostic(createDiagnostic({
                code: "decorator-fail",
                format: { decoratorName: decApp.decorator.name, error: error.stack },
                target: decApp.node ?? target,
            }));
        }
        else {
            throw error;
        }
    }
}
function createDecoratorContext(program, decApp) {
    function createPassThruContext(program, decApp) {
        return {
            program,
            decoratorTarget: decApp.node,
            getArgumentTarget: () => decApp.node,
            call: (decorator, target, ...args) => {
                return decorator(createPassThruContext(program, decApp), target, ...args);
            },
        };
    }
    return {
        program,
        decoratorTarget: decApp.node,
        getArgumentTarget: (index) => {
            return decApp.args[index]?.node;
        },
        call: (decorator, target, ...args) => {
            return decorator(createPassThruContext(program, decApp), target, ...args);
        },
    };
}
function isTemplatedNode(node) {
    return "templateParameters" in node && node.templateParameters.length > 0;
}
/**
 * Mapping from the reflection models to Type["kind"] value
 */
const ReflectionNameToKind = {
    Enum: "Enum",
    EnumMember: "EnumMember",
    Interface: "Interface",
    Model: "Model",
    ModelProperty: "ModelProperty",
    Namespace: "Namespace",
    Operation: "Operation",
    Scalar: "Scalar",
    TemplateParameter: "TemplateParameter",
    Tuple: "Tuple",
    Union: "Union",
    UnionVariant: "UnionVariant",
};
var ResolutionKind;
(function (ResolutionKind) {
    ResolutionKind[ResolutionKind["Value"] = 0] = "Value";
    ResolutionKind[ResolutionKind["Type"] = 1] = "Type";
    ResolutionKind[ResolutionKind["BaseType"] = 2] = "BaseType";
    ResolutionKind[ResolutionKind["Constraint"] = 3] = "Constraint";
})(ResolutionKind || (ResolutionKind = {}));
class PendingResolutions {
    #data = new Map();
    start(symId, kind) {
        let existing = this.#data.get(symId);
        if (existing === undefined) {
            existing = new Set();
            this.#data.set(symId, existing);
        }
        existing.add(kind);
    }
    has(symId, kind) {
        return this.#data.get(symId)?.has(kind) ?? false;
    }
    finish(symId, kind) {
        const existing = this.#data.get(symId);
        if (existing === undefined) {
            return;
        }
        existing?.delete(kind);
        if (existing.size === 0) {
            this.#data.delete(symId);
        }
    }
}
var Related;
(function (Related) {
    Related[Related["false"] = 0] = "false";
    Related[Related["true"] = 1] = "true";
    Related[Related["maybe"] = 2] = "maybe";
})(Related || (Related = {}));
const defaultSymbolResolutionOptions = {
    resolveDecorators: false,
    checkTemplateTypes: true,
};
/**
 * Convert LEGACY for projection.
 * THIS IS BROKEN. Some decorators will not receive the correct type.
 * It has been broken since the introduction of valueof.
 * As projection as put on hold as long as versioning works we are in a good state.
 */
function unsafe_projectionArgumentMarshalForJS(arg) {
    if (arg.kind === "Boolean" || arg.kind === "String" || arg.kind === "Number") {
        return arg.value;
    }
    else if (arg.kind === "StringTemplate") {
        return arg.stringValue;
    }
    return arg;
}

/**
 * Helper to emit a file.
 * @param program TypeSpec Program
 * @param options File Emitter options
 */
async function emitFile(program, options) {
    // ensure path exists
    const outputFolder = getDirectoryPath(options.path);
    await program.host.mkdirp(outputFolder);
    const content = options.newLine && options.newLine === "crlf"
        ? options.content.replace(/(\r\n|\n|\r)/gm, "\r\n")
        : options.content;
    return await program.host.writeFile(options.path, content);
}

var yu=Object.create;var He=Object.defineProperty;var Au=Object.getOwnPropertyDescriptor;var Bu=Object.getOwnPropertyNames;var wu=Object.getPrototypeOf,xu=Object.prototype.hasOwnProperty;var sr=e=>{throw TypeError(e)};var _u=(e,t)=>()=>(e&&(t=e(e=0)),t);var At=(e,t)=>()=>(t||e((t={exports:{}}).exports,t),t.exports),We=(e,t)=>{for(var r in t)He(e,r,{get:t[r],enumerable:!0});},ar=(e,t,r,n)=>{if(t&&typeof t=="object"||typeof t=="function")for(let o of Bu(t))!xu.call(e,o)&&o!==r&&He(e,o,{get:()=>t[o],enumerable:!(n=Au(t,o))||n.enumerable});return e};var Me=(e,t,r)=>(r=e!=null?yu(wu(e)):{},ar(He(r,"default",{value:e,enumerable:!0}),e)),vu=e=>ar(He({},"__esModule",{value:!0}),e);var bu=(e,t,r)=>t.has(e)||sr("Cannot "+r);var Dr=(e,t,r)=>t.has(e)?sr("Cannot add the same private member more than once"):t instanceof WeakSet?t.add(e):t.set(e,r);var pe=(e,t,r)=>(bu(e,t,"access private method"),r);var it=At((ia,sn)=>{var on=new Proxy(String,{get:()=>on});sn.exports=on;});var Tn={};We(Tn,{default:()=>_o,shouldHighlight:()=>xo});var xo,_o,kn=_u(()=>{xo=()=>!1,_o=String;});var Pn=At((bD,Xt)=>{var g=String,Ln=function(){return {isColorSupported:!1,reset:g,bold:g,dim:g,italic:g,underline:g,inverse:g,hidden:g,strikethrough:g,black:g,red:g,green:g,yellow:g,blue:g,magenta:g,cyan:g,white:g,gray:g,bgBlack:g,bgRed:g,bgGreen:g,bgYellow:g,bgBlue:g,bgMagenta:g,bgCyan:g,bgWhite:g}};Xt.exports=Ln();Xt.exports.createColors=Ln;});var $n=At(Ct=>{Object.defineProperty(Ct,"__esModule",{value:!0});Ct.codeFrameColumns=Mn;Ct.default=To;var In=(kn(),vu(Tn)),Hn=vo(Pn(),!0);function Wn(e){if(typeof WeakMap!="function")return null;var t=new WeakMap,r=new WeakMap;return (Wn=function(n){return n?r:t})(e)}function vo(e,t){if(e===null||typeof e!="object"&&typeof e!="function")return {default:e};var r=Wn(t);if(r&&r.has(e))return r.get(e);var n={__proto__:null},o=Object.defineProperty&&Object.getOwnPropertyDescriptor;for(var u in e)if(u!=="default"&&{}.hasOwnProperty.call(e,u)){var i=o?Object.getOwnPropertyDescriptor(e,u):null;i&&(i.get||i.set)?Object.defineProperty(n,u,i):n[u]=e[u];}return n.default=e,r&&r.set(e,n),n}var bo=Hn.default,Rn=(e,t)=>r=>e(t(r)),Zt;function Oo(e){if(e){return (Zt)!=null||(Zt=(0, Hn.createColors)(!0)),Zt}return bo}var Yn=!1;function So(e){return {gutter:e.gray,marker:Rn(e.red,e.bold),message:Rn(e.red,e.bold)}}var jn=/\r\n|[\n\r\u2028\u2029]/;function No(e,t,r){let n=Object.assign({column:0,line:-1},e.start),o=Object.assign({},n,e.end),{linesAbove:u=2,linesBelow:i=3}=r||{},s=n.line,a=n.column,D=o.line,l=o.column,d=Math.max(s-(u+1),0),f=Math.min(t.length,D+i);s===-1&&(d=0),D===-1&&(f=t.length);let p=D-s,c={};if(p)for(let F=0;F<=p;F++){let m=F+s;if(!a)c[m]=!0;else if(F===0){let E=t[m-1].length;c[m]=[a,E-a+1];}else if(F===p)c[m]=[0,l];else {let E=t[m-F].length;c[m]=[0,E];}}else a===l?a?c[s]=[a,0]:c[s]=!0:c[s]=[a,l-a];return {start:d,end:f,markerLines:c}}function Mn(e,t,r={}){let n=(r.highlightCode||r.forceColor)&&(0, In.shouldHighlight)(r),o=Oo(r.forceColor),u=So(o),i=(F,m)=>n?F(m):m,s=e.split(jn),{start:a,end:D,markerLines:l}=No(t,s,r),d=t.start&&typeof t.start.column=="number",f=String(D).length,c=(n?(0, In.default)(e,r):e).split(jn,D).slice(a,D).map((F,m)=>{let E=a+1+m,w=` ${` ${E}`.slice(-f)} |`,h=l[E],C=!l[E+1];if(h){let k="";if(Array.isArray(h)){let v=F.slice(0,Math.max(h[0]-1,0)).replace(/[^\t]/g," "),$=h[1]||1;k=[`
 `,i(u.gutter,w.replace(/\d/g," "))," ",v,i(u.marker,"^").repeat($)].join(""),C&&r.message&&(k+=" "+i(u.message,r.message));}return [i(u.marker,">"),i(u.gutter,w),F.length>0?` ${F}`:"",k].join("")}else return ` ${i(u.gutter,w)}${F.length>0?` ${F}`:""}`}).join(`
`);return r.message&&!d&&(c=`${" ".repeat(f+1)}${r.message}
${c}`),n?o.reset(c):c}function To(e,t,r,n={}){if(!Yn){Yn=!0;let u="Passing lineNumber and colNumber is deprecated to @babel/code-frame. Please use `codeFrameColumns`.";{let i=new Error(u);i.name="DeprecationWarning",console.warn(new Error(u));}}return r=Math.max(r,0),Mn(e,{start:{column:r,line:t}},n)}});var ir={};We(ir,{__debug:()=>di,check:()=>fi,doc:()=>nr,format:()=>gu,formatWithCursor:()=>Cu,getSupportInfo:()=>pi,util:()=>or,version:()=>fu});var Ou=(e,t,r,n)=>{if(!(e&&t==null))return t.replaceAll?t.replaceAll(r,n):r.global?t.replace(r,n):t.split(r).join(n)},ne=Ou;function Z(){}Z.prototype={diff:function(t,r){var n,o=arguments.length>2&&arguments[2]!==void 0?arguments[2]:{},u=o.callback;typeof o=="function"&&(u=o,o={}),this.options=o;var i=this;function s(h){return u?(setTimeout(function(){u(void 0,h);},0),!0):h}t=this.castInput(t),r=this.castInput(r),t=this.removeEmpty(this.tokenize(t)),r=this.removeEmpty(this.tokenize(r));var a=r.length,D=t.length,l=1,d=a+D;o.maxEditLength&&(d=Math.min(d,o.maxEditLength));var f=(n=o.timeout)!==null&&n!==void 0?n:1/0,p=Date.now()+f,c=[{oldPos:-1,lastComponent:void 0}],F=this.extractCommon(c[0],r,t,0);if(c[0].oldPos+1>=D&&F+1>=a)return s([{value:this.join(r),count:r.length}]);var m=-1/0,E=1/0;function A(){for(var h=Math.max(m,-l);h<=Math.min(E,l);h+=2){var C=void 0,k=c[h-1],v=c[h+1];k&&(c[h-1]=void 0);var $=!1;if(v){var ye=v.oldPos-h;$=v&&0<=ye&&ye<a;}var yt=k&&k.oldPos+1<D;if(!$&&!yt){c[h]=void 0;continue}if(!yt||$&&k.oldPos+1<v.oldPos?C=i.addToPath(v,!0,void 0,0):C=i.addToPath(k,void 0,!0,1),F=i.extractCommon(C,r,t,h),C.oldPos+1>=D&&F+1>=a)return s(Su(i,C.lastComponent,r,t,i.useLongestToken));c[h]=C,C.oldPos+1>=D&&(E=Math.min(E,h-1)),F+1>=a&&(m=Math.max(m,h+1));}l++;}if(u)(function h(){setTimeout(function(){if(l>d||Date.now()>p)return u();A()||h();},0);})();else for(;l<=d&&Date.now()<=p;){var w=A();if(w)return w}},addToPath:function(t,r,n,o){var u=t.lastComponent;return u&&u.added===r&&u.removed===n?{oldPos:t.oldPos+o,lastComponent:{count:u.count+1,added:r,removed:n,previousComponent:u.previousComponent}}:{oldPos:t.oldPos+o,lastComponent:{count:1,added:r,removed:n,previousComponent:u}}},extractCommon:function(t,r,n,o){for(var u=r.length,i=n.length,s=t.oldPos,a=s-o,D=0;a+1<u&&s+1<i&&this.equals(r[a+1],n[s+1]);)a++,s++,D++;return D&&(t.lastComponent={count:D,previousComponent:t.lastComponent}),t.oldPos=s,a},equals:function(t,r){return this.options.comparator?this.options.comparator(t,r):t===r||this.options.ignoreCase&&t.toLowerCase()===r.toLowerCase()},removeEmpty:function(t){for(var r=[],n=0;n<t.length;n++)t[n]&&r.push(t[n]);return r},castInput:function(t){return t},tokenize:function(t){return t.split("")},join:function(t){return t.join("")}};function Su(e,t,r,n,o){for(var u=[],i;t;)u.push(t),i=t.previousComponent,delete t.previousComponent,t=i;u.reverse();for(var s=0,a=u.length,D=0,l=0;s<a;s++){var d=u[s];if(d.removed){if(d.value=e.join(n.slice(l,l+d.count)),l+=d.count,s&&u[s-1].added){var p=u[s-1];u[s-1]=u[s],u[s]=p;}}else {if(!d.added&&o){var f=r.slice(D,D+d.count);f=f.map(function(F,m){var E=n[l+m];return E.length>F.length?E:F}),d.value=e.join(f);}else d.value=e.join(r.slice(D,D+d.count));D+=d.count,d.added||(l+=d.count);}}var c=u[a-1];return a>1&&typeof c.value=="string"&&(c.added||c.removed)&&e.equals("",c.value)&&(u[a-2].value+=c.value,u.pop()),u}var lr=/^[A-Za-z\xC0-\u02C6\u02C8-\u02D7\u02DE-\u02FF\u1E00-\u1EFF]+$/,cr=/\S/,fr=new Z;fr.equals=function(e,t){return this.options.ignoreCase&&(e=e.toLowerCase(),t=t.toLowerCase()),e===t||this.options.ignoreWhitespace&&!cr.test(e)&&!cr.test(t)};fr.tokenize=function(e){for(var t=e.split(/([^\S\r\n]+|[()[\]{}'"\r\n]|\b)/),r=0;r<t.length-1;r++)!t[r+1]&&t[r+2]&&lr.test(t[r])&&lr.test(t[r+2])&&(t[r]+=t[r+2],t.splice(r+1,2),r--);return t};var pr=new Z;pr.tokenize=function(e){this.options.stripTrailingCr&&(e=e.replace(/\r\n/g,`
`));var t=[],r=e.split(/(\n|\r\n)/);r[r.length-1]||r.pop();for(var n=0;n<r.length;n++){var o=r[n];n%2&&!this.options.newlineIsToken?t[t.length-1]+=o:(this.options.ignoreWhitespace&&(o=o.trim()),t.push(o));}return t};var Nu=new Z;Nu.tokenize=function(e){return e.split(/(\S.+?[.!?])(?=\s+|$)/)};var Tu=new Z;Tu.tokenize=function(e){return e.split(/([{}:;,]|\s+)/)};function $e(e){"@babel/helpers - typeof";return typeof Symbol=="function"&&typeof Symbol.iterator=="symbol"?$e=function(t){return typeof t}:$e=function(t){return t&&typeof Symbol=="function"&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t},$e(e)}var ku=Object.prototype.toString,Ae=new Z;Ae.useLongestToken=!0;Ae.tokenize=pr.tokenize;Ae.castInput=function(e){var t=this.options,r=t.undefinedReplacement,n=t.stringifyReplacer,o=n===void 0?function(u,i){return typeof i>"u"?r:i}:n;return typeof e=="string"?e:JSON.stringify(Bt(e,null,null,o),o,"  ")};Ae.equals=function(e,t){return Z.prototype.equals.call(Ae,e.replace(/,([\r\n])/g,"$1"),t.replace(/,([\r\n])/g,"$1"))};function Bt(e,t,r,n,o){t=t||[],r=r||[],n&&(e=n(o,e));var u;for(u=0;u<t.length;u+=1)if(t[u]===e)return r[u];var i;if(ku.call(e)==="[object Array]"){for(t.push(e),i=new Array(e.length),r.push(i),u=0;u<e.length;u+=1)i[u]=Bt(e[u],t,r,n,o);return t.pop(),r.pop(),i}if(e&&e.toJSON&&(e=e.toJSON()),$e(e)==="object"&&e!==null){t.push(e),i={},r.push(i);var s=[],a;for(a in e)e.hasOwnProperty(a)&&s.push(a);for(s.sort(),u=0;u<s.length;u+=1)a=s[u],i[a]=Bt(e[a],t,r,n,a);t.pop(),r.pop();}else i=e;return i}var Ve=new Z;Ve.tokenize=function(e){return e.slice()};Ve.join=Ve.removeEmpty=function(e){return e};function dr(e,t,r){return Ve.diff(e,t,r)}function Fr(e){let t=e.indexOf("\r");return t>=0?e.charAt(t+1)===`
`?"crlf":"cr":"lf"}function Be(e){switch(e){case"cr":return "\r";case"crlf":return `\r
`;default:return `
`}}function wt(e,t){let r;switch(t){case`
`:r=/\n/gu;break;case"\r":r=/\r/gu;break;case`\r
`:r=/\r\n/gu;break;default:throw new Error(`Unexpected "eol" ${JSON.stringify(t)}.`)}let n=e.match(r);return n?n.length:0}function mr(e){return ne(!1,e,/\r\n?/gu,`
`)}var U="string",W="array",z="cursor",L="indent",P="align",I="trim",x="group",S="fill",_="if-break",R="indent-if-break",Y="line-suffix",j="line-suffix-boundary",B="line",N="label",b="break-parent",Ue=new Set([z,L,P,I,x,S,_,R,Y,j,B,N,b]);function Lu(e){if(typeof e=="string")return U;if(Array.isArray(e))return W;if(!e)return;let{type:t}=e;if(Ue.has(t))return t}var G=Lu;var Pu=e=>new Intl.ListFormat("en-US",{type:"disjunction"}).format(e);function Iu(e){let t=e===null?"null":typeof e;if(t!=="string"&&t!=="object")return `Unexpected doc '${t}', 
Expected it to be 'string' or 'object'.`;if(G(e))throw new Error("doc is valid.");let r=Object.prototype.toString.call(e);if(r!=="[object Object]")return `Unexpected doc '${r}'.`;let n=Pu([...Ue].map(o=>`'${o}'`));return `Unexpected doc.type '${e.type}'.
Expected it to be ${n}.`}var xt=class extends Error{name="InvalidDocError";constructor(t){super(Iu(t)),this.doc=t;}},Q=xt;var Er={};function Ru(e,t,r,n){let o=[e];for(;o.length>0;){let u=o.pop();if(u===Er){r(o.pop());continue}r&&o.push(u,Er);let i=G(u);if(!i)throw new Q(u);if((t==null?void 0:t(u))!==!1)switch(i){case W:case S:{let s=i===W?u:u.parts;for(let a=s.length,D=a-1;D>=0;--D)o.push(s[D]);break}case _:o.push(u.flatContents,u.breakContents);break;case x:if(n&&u.expandedStates)for(let s=u.expandedStates.length,a=s-1;a>=0;--a)o.push(u.expandedStates[a]);else o.push(u.contents);break;case P:case L:case R:case N:case Y:o.push(u.contents);break;case U:case z:case I:case j:case B:case b:break;default:throw new Q(u)}}}var we=Ru;var hr=()=>{},ze=hr;function De(e){return {type:L,contents:e}}function ae(e,t){return {type:P,contents:t,n:e}}function _t(e,t={}){return ze(t.expandedStates),{type:x,id:t.id,contents:e,break:!!t.shouldBreak,expandedStates:t.expandedStates}}function Cr(e){return ae(Number.NEGATIVE_INFINITY,e)}function gr(e){return ae({type:"root"},e)}function yr(e){return ae(-1,e)}function Ar(e,t){return _t(e[0],{...t,expandedStates:e})}function Ge(e){return {type:S,parts:e}}function Br(e,t="",r={}){return {type:_,breakContents:e,flatContents:t,groupId:r.groupId}}function wr(e,t){return {type:R,contents:e,groupId:t.groupId,negate:t.negate}}function xe(e){return {type:Y,contents:e}}var xr={type:j},de={type:b},_r={type:I},_e={type:B,hard:!0},vt={type:B,hard:!0,literal:!0},Ke={type:B},vr={type:B,soft:!0},q=[_e,de],qe=[vt,de],ve={type:z};function be(e,t){let r=[];for(let n=0;n<t.length;n++)n!==0&&r.push(e),r.push(t[n]);return r}function Je(e,t,r){let n=e;if(t>0){for(let o=0;o<Math.floor(t/r);++o)n=De(n);n=ae(t%r,n),n=ae(Number.NEGATIVE_INFINITY,n);}return n}function br(e,t){return e?{type:N,label:e,contents:t}:t}function ee(e){var t;if(!e)return "";if(Array.isArray(e)){let r=[];for(let n of e)if(Array.isArray(n))r.push(...ee(n));else {let o=ee(n);o!==""&&r.push(o);}return r}return e.type===_?{...e,breakContents:ee(e.breakContents),flatContents:ee(e.flatContents)}:e.type===x?{...e,contents:ee(e.contents),expandedStates:(t=e.expandedStates)==null?void 0:t.map(ee)}:e.type===S?{type:"fill",parts:e.parts.map(ee)}:e.contents?{...e,contents:ee(e.contents)}:e}function Or(e){let t=Object.create(null),r=new Set;return n(ee(e));function n(u,i,s){var a,D;if(typeof u=="string")return JSON.stringify(u);if(Array.isArray(u)){let l=u.map(n).filter(Boolean);return l.length===1?l[0]:`[${l.join(", ")}]`}if(u.type===B){let l=((a=s==null?void 0:s[i+1])==null?void 0:a.type)===b;return u.literal?l?"literalline":"literallineWithoutBreakParent":u.hard?l?"hardline":"hardlineWithoutBreakParent":u.soft?"softline":"line"}if(u.type===b)return ((D=s==null?void 0:s[i-1])==null?void 0:D.type)===B&&s[i-1].hard?void 0:"breakParent";if(u.type===I)return "trim";if(u.type===L)return "indent("+n(u.contents)+")";if(u.type===P)return u.n===Number.NEGATIVE_INFINITY?"dedentToRoot("+n(u.contents)+")":u.n<0?"dedent("+n(u.contents)+")":u.n.type==="root"?"markAsRoot("+n(u.contents)+")":"align("+JSON.stringify(u.n)+", "+n(u.contents)+")";if(u.type===_)return "ifBreak("+n(u.breakContents)+(u.flatContents?", "+n(u.flatContents):"")+(u.groupId?(u.flatContents?"":', ""')+`, { groupId: ${o(u.groupId)} }`:"")+")";if(u.type===R){let l=[];u.negate&&l.push("negate: true"),u.groupId&&l.push(`groupId: ${o(u.groupId)}`);let d=l.length>0?`, { ${l.join(", ")} }`:"";return `indentIfBreak(${n(u.contents)}${d})`}if(u.type===x){let l=[];u.break&&u.break!=="propagated"&&l.push("shouldBreak: true"),u.id&&l.push(`id: ${o(u.id)}`);let d=l.length>0?`, { ${l.join(", ")} }`:"";return u.expandedStates?`conditionalGroup([${u.expandedStates.map(f=>n(f)).join(",")}]${d})`:`group(${n(u.contents)}${d})`}if(u.type===S)return `fill([${u.parts.map(l=>n(l)).join(", ")}])`;if(u.type===Y)return "lineSuffix("+n(u.contents)+")";if(u.type===j)return "lineSuffixBoundary";if(u.type===N)return `label(${JSON.stringify(u.label)}, ${n(u.contents)})`;throw new Error("Unknown doc type "+u.type)}function o(u){if(typeof u!="symbol")return JSON.stringify(String(u));if(u in t)return t[u];let i=u.description||"symbol";for(let s=0;;s++){let a=i+(s>0?` #${s}`:"");if(!r.has(a))return r.add(a),t[u]=`Symbol.for(${JSON.stringify(a)})`}}}var Yu=(e,t,r)=>{if(!(e&&t==null))return Array.isArray(t)||typeof t=="string"?t[r<0?t.length+r:r]:t.at(r)},y=Yu;var Sr=()=>/[#*0-9]\uFE0F?\u20E3|[\xA9\xAE\u203C\u2049\u2122\u2139\u2194-\u2199\u21A9\u21AA\u231A\u231B\u2328\u23CF\u23ED-\u23EF\u23F1\u23F2\u23F8-\u23FA\u24C2\u25AA\u25AB\u25B6\u25C0\u25FB\u25FC\u25FE\u2600-\u2604\u260E\u2611\u2614\u2615\u2618\u2620\u2622\u2623\u2626\u262A\u262E\u262F\u2638-\u263A\u2640\u2642\u2648-\u2653\u265F\u2660\u2663\u2665\u2666\u2668\u267B\u267E\u267F\u2692\u2694-\u2697\u2699\u269B\u269C\u26A0\u26A7\u26AA\u26B0\u26B1\u26BD\u26BE\u26C4\u26C8\u26CF\u26D1\u26E9\u26F0-\u26F5\u26F7\u26F8\u26FA\u2702\u2708\u2709\u270F\u2712\u2714\u2716\u271D\u2721\u2733\u2734\u2744\u2747\u2757\u2763\u27A1\u2934\u2935\u2B05-\u2B07\u2B1B\u2B1C\u2B55\u3030\u303D\u3297\u3299]\uFE0F?|[\u261D\u270C\u270D](?:\uFE0F|\uD83C[\uDFFB-\uDFFF])?|[\u270A\u270B](?:\uD83C[\uDFFB-\uDFFF])?|[\u23E9-\u23EC\u23F0\u23F3\u25FD\u2693\u26A1\u26AB\u26C5\u26CE\u26D4\u26EA\u26FD\u2705\u2728\u274C\u274E\u2753-\u2755\u2795-\u2797\u27B0\u27BF\u2B50]|\u26D3\uFE0F?(?:\u200D\uD83D\uDCA5)?|\u26F9(?:\uFE0F|\uD83C[\uDFFB-\uDFFF])?(?:\u200D[\u2640\u2642]\uFE0F?)?|\u2764\uFE0F?(?:\u200D(?:\uD83D\uDD25|\uD83E\uDE79))?|\uD83C(?:[\uDC04\uDD70\uDD71\uDD7E\uDD7F\uDE02\uDE37\uDF21\uDF24-\uDF2C\uDF36\uDF7D\uDF96\uDF97\uDF99-\uDF9B\uDF9E\uDF9F\uDFCD\uDFCE\uDFD4-\uDFDF\uDFF5\uDFF7]\uFE0F?|[\uDF85\uDFC2\uDFC7](?:\uD83C[\uDFFB-\uDFFF])?|[\uDFC4\uDFCA](?:\uD83C[\uDFFB-\uDFFF])?(?:\u200D[\u2640\u2642]\uFE0F?)?|[\uDFCB\uDFCC](?:\uFE0F|\uD83C[\uDFFB-\uDFFF])?(?:\u200D[\u2640\u2642]\uFE0F?)?|[\uDCCF\uDD8E\uDD91-\uDD9A\uDE01\uDE1A\uDE2F\uDE32-\uDE36\uDE38-\uDE3A\uDE50\uDE51\uDF00-\uDF20\uDF2D-\uDF35\uDF37-\uDF43\uDF45-\uDF4A\uDF4C-\uDF7C\uDF7E-\uDF84\uDF86-\uDF93\uDFA0-\uDFC1\uDFC5\uDFC6\uDFC8\uDFC9\uDFCF-\uDFD3\uDFE0-\uDFF0\uDFF8-\uDFFF]|\uDDE6\uD83C[\uDDE8-\uDDEC\uDDEE\uDDF1\uDDF2\uDDF4\uDDF6-\uDDFA\uDDFC\uDDFD\uDDFF]|\uDDE7\uD83C[\uDDE6\uDDE7\uDDE9-\uDDEF\uDDF1-\uDDF4\uDDF6-\uDDF9\uDDFB\uDDFC\uDDFE\uDDFF]|\uDDE8\uD83C[\uDDE6\uDDE8\uDDE9\uDDEB-\uDDEE\uDDF0-\uDDF5\uDDF7\uDDFA-\uDDFF]|\uDDE9\uD83C[\uDDEA\uDDEC\uDDEF\uDDF0\uDDF2\uDDF4\uDDFF]|\uDDEA\uD83C[\uDDE6\uDDE8\uDDEA\uDDEC\uDDED\uDDF7-\uDDFA]|\uDDEB\uD83C[\uDDEE-\uDDF0\uDDF2\uDDF4\uDDF7]|\uDDEC\uD83C[\uDDE6\uDDE7\uDDE9-\uDDEE\uDDF1-\uDDF3\uDDF5-\uDDFA\uDDFC\uDDFE]|\uDDED\uD83C[\uDDF0\uDDF2\uDDF3\uDDF7\uDDF9\uDDFA]|\uDDEE\uD83C[\uDDE8-\uDDEA\uDDF1-\uDDF4\uDDF6-\uDDF9]|\uDDEF\uD83C[\uDDEA\uDDF2\uDDF4\uDDF5]|\uDDF0\uD83C[\uDDEA\uDDEC-\uDDEE\uDDF2\uDDF3\uDDF5\uDDF7\uDDFC\uDDFE\uDDFF]|\uDDF1\uD83C[\uDDE6-\uDDE8\uDDEE\uDDF0\uDDF7-\uDDFB\uDDFE]|\uDDF2\uD83C[\uDDE6\uDDE8-\uDDED\uDDF0-\uDDFF]|\uDDF3\uD83C[\uDDE6\uDDE8\uDDEA-\uDDEC\uDDEE\uDDF1\uDDF4\uDDF5\uDDF7\uDDFA\uDDFF]|\uDDF4\uD83C\uDDF2|\uDDF5\uD83C[\uDDE6\uDDEA-\uDDED\uDDF0-\uDDF3\uDDF7-\uDDF9\uDDFC\uDDFE]|\uDDF6\uD83C\uDDE6|\uDDF7\uD83C[\uDDEA\uDDF4\uDDF8\uDDFA\uDDFC]|\uDDF8\uD83C[\uDDE6-\uDDEA\uDDEC-\uDDF4\uDDF7-\uDDF9\uDDFB\uDDFD-\uDDFF]|\uDDF9\uD83C[\uDDE6\uDDE8\uDDE9\uDDEB-\uDDED\uDDEF-\uDDF4\uDDF7\uDDF9\uDDFB\uDDFC\uDDFF]|\uDDFA\uD83C[\uDDE6\uDDEC\uDDF2\uDDF3\uDDF8\uDDFE\uDDFF]|\uDDFB\uD83C[\uDDE6\uDDE8\uDDEA\uDDEC\uDDEE\uDDF3\uDDFA]|\uDDFC\uD83C[\uDDEB\uDDF8]|\uDDFD\uD83C\uDDF0|\uDDFE\uD83C[\uDDEA\uDDF9]|\uDDFF\uD83C[\uDDE6\uDDF2\uDDFC]|\uDF44(?:\u200D\uD83D\uDFEB)?|\uDF4B(?:\u200D\uD83D\uDFE9)?|\uDFC3(?:\uD83C[\uDFFB-\uDFFF])?(?:\u200D(?:[\u2640\u2642]\uFE0F?(?:\u200D\u27A1\uFE0F?)?|\u27A1\uFE0F?))?|\uDFF3\uFE0F?(?:\u200D(?:\u26A7\uFE0F?|\uD83C\uDF08))?|\uDFF4(?:\u200D\u2620\uFE0F?|\uDB40\uDC67\uDB40\uDC62\uDB40(?:\uDC65\uDB40\uDC6E\uDB40\uDC67|\uDC73\uDB40\uDC63\uDB40\uDC74|\uDC77\uDB40\uDC6C\uDB40\uDC73)\uDB40\uDC7F)?)|\uD83D(?:[\uDC3F\uDCFD\uDD49\uDD4A\uDD6F\uDD70\uDD73\uDD76-\uDD79\uDD87\uDD8A-\uDD8D\uDDA5\uDDA8\uDDB1\uDDB2\uDDBC\uDDC2-\uDDC4\uDDD1-\uDDD3\uDDDC-\uDDDE\uDDE1\uDDE3\uDDE8\uDDEF\uDDF3\uDDFA\uDECB\uDECD-\uDECF\uDEE0-\uDEE5\uDEE9\uDEF0\uDEF3]\uFE0F?|[\uDC42\uDC43\uDC46-\uDC50\uDC66\uDC67\uDC6B-\uDC6D\uDC72\uDC74-\uDC76\uDC78\uDC7C\uDC83\uDC85\uDC8F\uDC91\uDCAA\uDD7A\uDD95\uDD96\uDE4C\uDE4F\uDEC0\uDECC](?:\uD83C[\uDFFB-\uDFFF])?|[\uDC6E\uDC70\uDC71\uDC73\uDC77\uDC81\uDC82\uDC86\uDC87\uDE45-\uDE47\uDE4B\uDE4D\uDE4E\uDEA3\uDEB4\uDEB5](?:\uD83C[\uDFFB-\uDFFF])?(?:\u200D[\u2640\u2642]\uFE0F?)?|[\uDD74\uDD90](?:\uFE0F|\uD83C[\uDFFB-\uDFFF])?|[\uDC00-\uDC07\uDC09-\uDC14\uDC16-\uDC25\uDC27-\uDC3A\uDC3C-\uDC3E\uDC40\uDC44\uDC45\uDC51-\uDC65\uDC6A\uDC79-\uDC7B\uDC7D-\uDC80\uDC84\uDC88-\uDC8E\uDC90\uDC92-\uDCA9\uDCAB-\uDCFC\uDCFF-\uDD3D\uDD4B-\uDD4E\uDD50-\uDD67\uDDA4\uDDFB-\uDE2D\uDE2F-\uDE34\uDE37-\uDE41\uDE43\uDE44\uDE48-\uDE4A\uDE80-\uDEA2\uDEA4-\uDEB3\uDEB7-\uDEBF\uDEC1-\uDEC5\uDED0-\uDED2\uDED5-\uDED7\uDEDC-\uDEDF\uDEEB\uDEEC\uDEF4-\uDEFC\uDFE0-\uDFEB\uDFF0]|\uDC08(?:\u200D\u2B1B)?|\uDC15(?:\u200D\uD83E\uDDBA)?|\uDC26(?:\u200D(?:\u2B1B|\uD83D\uDD25))?|\uDC3B(?:\u200D\u2744\uFE0F?)?|\uDC41\uFE0F?(?:\u200D\uD83D\uDDE8\uFE0F?)?|\uDC68(?:\u200D(?:[\u2695\u2696\u2708]\uFE0F?|\u2764\uFE0F?\u200D\uD83D(?:\uDC8B\u200D\uD83D)?\uDC68|\uD83C[\uDF3E\uDF73\uDF7C\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D(?:[\uDC68\uDC69]\u200D\uD83D(?:\uDC66(?:\u200D\uD83D\uDC66)?|\uDC67(?:\u200D\uD83D[\uDC66\uDC67])?)|[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uDC66(?:\u200D\uD83D\uDC66)?|\uDC67(?:\u200D\uD83D[\uDC66\uDC67])?)|\uD83E(?:[\uDDAF\uDDBC\uDDBD](?:\u200D\u27A1\uFE0F?)?|[\uDDB0-\uDDB3]))|\uD83C(?:\uDFFB(?:\u200D(?:[\u2695\u2696\u2708]\uFE0F?|\u2764\uFE0F?\u200D\uD83D(?:\uDC8B\u200D\uD83D)?\uDC68\uD83C[\uDFFB-\uDFFF]|\uD83C[\uDF3E\uDF73\uDF7C\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E(?:[\uDDAF\uDDBC\uDDBD](?:\u200D\u27A1\uFE0F?)?|[\uDDB0-\uDDB3]|\uDD1D\u200D\uD83D\uDC68\uD83C[\uDFFC-\uDFFF])))?|\uDFFC(?:\u200D(?:[\u2695\u2696\u2708]\uFE0F?|\u2764\uFE0F?\u200D\uD83D(?:\uDC8B\u200D\uD83D)?\uDC68\uD83C[\uDFFB-\uDFFF]|\uD83C[\uDF3E\uDF73\uDF7C\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E(?:[\uDDAF\uDDBC\uDDBD](?:\u200D\u27A1\uFE0F?)?|[\uDDB0-\uDDB3]|\uDD1D\u200D\uD83D\uDC68\uD83C[\uDFFB\uDFFD-\uDFFF])))?|\uDFFD(?:\u200D(?:[\u2695\u2696\u2708]\uFE0F?|\u2764\uFE0F?\u200D\uD83D(?:\uDC8B\u200D\uD83D)?\uDC68\uD83C[\uDFFB-\uDFFF]|\uD83C[\uDF3E\uDF73\uDF7C\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E(?:[\uDDAF\uDDBC\uDDBD](?:\u200D\u27A1\uFE0F?)?|[\uDDB0-\uDDB3]|\uDD1D\u200D\uD83D\uDC68\uD83C[\uDFFB\uDFFC\uDFFE\uDFFF])))?|\uDFFE(?:\u200D(?:[\u2695\u2696\u2708]\uFE0F?|\u2764\uFE0F?\u200D\uD83D(?:\uDC8B\u200D\uD83D)?\uDC68\uD83C[\uDFFB-\uDFFF]|\uD83C[\uDF3E\uDF73\uDF7C\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E(?:[\uDDAF\uDDBC\uDDBD](?:\u200D\u27A1\uFE0F?)?|[\uDDB0-\uDDB3]|\uDD1D\u200D\uD83D\uDC68\uD83C[\uDFFB-\uDFFD\uDFFF])))?|\uDFFF(?:\u200D(?:[\u2695\u2696\u2708]\uFE0F?|\u2764\uFE0F?\u200D\uD83D(?:\uDC8B\u200D\uD83D)?\uDC68\uD83C[\uDFFB-\uDFFF]|\uD83C[\uDF3E\uDF73\uDF7C\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E(?:[\uDDAF\uDDBC\uDDBD](?:\u200D\u27A1\uFE0F?)?|[\uDDB0-\uDDB3]|\uDD1D\u200D\uD83D\uDC68\uD83C[\uDFFB-\uDFFE])))?))?|\uDC69(?:\u200D(?:[\u2695\u2696\u2708]\uFE0F?|\u2764\uFE0F?\u200D\uD83D(?:\uDC8B\u200D\uD83D)?[\uDC68\uDC69]|\uD83C[\uDF3E\uDF73\uDF7C\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D(?:[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uDC66(?:\u200D\uD83D\uDC66)?|\uDC67(?:\u200D\uD83D[\uDC66\uDC67])?|\uDC69\u200D\uD83D(?:\uDC66(?:\u200D\uD83D\uDC66)?|\uDC67(?:\u200D\uD83D[\uDC66\uDC67])?))|\uD83E(?:[\uDDAF\uDDBC\uDDBD](?:\u200D\u27A1\uFE0F?)?|[\uDDB0-\uDDB3]))|\uD83C(?:\uDFFB(?:\u200D(?:[\u2695\u2696\u2708]\uFE0F?|\u2764\uFE0F?\u200D\uD83D(?:[\uDC68\uDC69]|\uDC8B\u200D\uD83D[\uDC68\uDC69])\uD83C[\uDFFB-\uDFFF]|\uD83C[\uDF3E\uDF73\uDF7C\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E(?:[\uDDAF\uDDBC\uDDBD](?:\u200D\u27A1\uFE0F?)?|[\uDDB0-\uDDB3]|\uDD1D\u200D\uD83D[\uDC68\uDC69]\uD83C[\uDFFC-\uDFFF])))?|\uDFFC(?:\u200D(?:[\u2695\u2696\u2708]\uFE0F?|\u2764\uFE0F?\u200D\uD83D(?:[\uDC68\uDC69]|\uDC8B\u200D\uD83D[\uDC68\uDC69])\uD83C[\uDFFB-\uDFFF]|\uD83C[\uDF3E\uDF73\uDF7C\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E(?:[\uDDAF\uDDBC\uDDBD](?:\u200D\u27A1\uFE0F?)?|[\uDDB0-\uDDB3]|\uDD1D\u200D\uD83D[\uDC68\uDC69]\uD83C[\uDFFB\uDFFD-\uDFFF])))?|\uDFFD(?:\u200D(?:[\u2695\u2696\u2708]\uFE0F?|\u2764\uFE0F?\u200D\uD83D(?:[\uDC68\uDC69]|\uDC8B\u200D\uD83D[\uDC68\uDC69])\uD83C[\uDFFB-\uDFFF]|\uD83C[\uDF3E\uDF73\uDF7C\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E(?:[\uDDAF\uDDBC\uDDBD](?:\u200D\u27A1\uFE0F?)?|[\uDDB0-\uDDB3]|\uDD1D\u200D\uD83D[\uDC68\uDC69]\uD83C[\uDFFB\uDFFC\uDFFE\uDFFF])))?|\uDFFE(?:\u200D(?:[\u2695\u2696\u2708]\uFE0F?|\u2764\uFE0F?\u200D\uD83D(?:[\uDC68\uDC69]|\uDC8B\u200D\uD83D[\uDC68\uDC69])\uD83C[\uDFFB-\uDFFF]|\uD83C[\uDF3E\uDF73\uDF7C\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E(?:[\uDDAF\uDDBC\uDDBD](?:\u200D\u27A1\uFE0F?)?|[\uDDB0-\uDDB3]|\uDD1D\u200D\uD83D[\uDC68\uDC69]\uD83C[\uDFFB-\uDFFD\uDFFF])))?|\uDFFF(?:\u200D(?:[\u2695\u2696\u2708]\uFE0F?|\u2764\uFE0F?\u200D\uD83D(?:[\uDC68\uDC69]|\uDC8B\u200D\uD83D[\uDC68\uDC69])\uD83C[\uDFFB-\uDFFF]|\uD83C[\uDF3E\uDF73\uDF7C\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E(?:[\uDDAF\uDDBC\uDDBD](?:\u200D\u27A1\uFE0F?)?|[\uDDB0-\uDDB3]|\uDD1D\u200D\uD83D[\uDC68\uDC69]\uD83C[\uDFFB-\uDFFE])))?))?|\uDC6F(?:\u200D[\u2640\u2642]\uFE0F?)?|\uDD75(?:\uFE0F|\uD83C[\uDFFB-\uDFFF])?(?:\u200D[\u2640\u2642]\uFE0F?)?|\uDE2E(?:\u200D\uD83D\uDCA8)?|\uDE35(?:\u200D\uD83D\uDCAB)?|\uDE36(?:\u200D\uD83C\uDF2B\uFE0F?)?|\uDE42(?:\u200D[\u2194\u2195]\uFE0F?)?|\uDEB6(?:\uD83C[\uDFFB-\uDFFF])?(?:\u200D(?:[\u2640\u2642]\uFE0F?(?:\u200D\u27A1\uFE0F?)?|\u27A1\uFE0F?))?)|\uD83E(?:[\uDD0C\uDD0F\uDD18-\uDD1F\uDD30-\uDD34\uDD36\uDD77\uDDB5\uDDB6\uDDBB\uDDD2\uDDD3\uDDD5\uDEC3-\uDEC5\uDEF0\uDEF2-\uDEF8](?:\uD83C[\uDFFB-\uDFFF])?|[\uDD26\uDD35\uDD37-\uDD39\uDD3D\uDD3E\uDDB8\uDDB9\uDDCD\uDDCF\uDDD4\uDDD6-\uDDDD](?:\uD83C[\uDFFB-\uDFFF])?(?:\u200D[\u2640\u2642]\uFE0F?)?|[\uDDDE\uDDDF](?:\u200D[\u2640\u2642]\uFE0F?)?|[\uDD0D\uDD0E\uDD10-\uDD17\uDD20-\uDD25\uDD27-\uDD2F\uDD3A\uDD3F-\uDD45\uDD47-\uDD76\uDD78-\uDDB4\uDDB7\uDDBA\uDDBC-\uDDCC\uDDD0\uDDE0-\uDDFF\uDE70-\uDE7C\uDE80-\uDE88\uDE90-\uDEBD\uDEBF-\uDEC2\uDECE-\uDEDB\uDEE0-\uDEE8]|\uDD3C(?:\u200D[\u2640\u2642]\uFE0F?|\uD83C[\uDFFB-\uDFFF])?|\uDDCE(?:\uD83C[\uDFFB-\uDFFF])?(?:\u200D(?:[\u2640\u2642]\uFE0F?(?:\u200D\u27A1\uFE0F?)?|\u27A1\uFE0F?))?|\uDDD1(?:\u200D(?:[\u2695\u2696\u2708]\uFE0F?|\uD83C[\uDF3E\uDF73\uDF7C\uDF84\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E(?:[\uDDAF\uDDBC\uDDBD](?:\u200D\u27A1\uFE0F?)?|[\uDDB0-\uDDB3]|\uDD1D\u200D\uD83E\uDDD1|\uDDD1\u200D\uD83E\uDDD2(?:\u200D\uD83E\uDDD2)?|\uDDD2(?:\u200D\uD83E\uDDD2)?))|\uD83C(?:\uDFFB(?:\u200D(?:[\u2695\u2696\u2708]\uFE0F?|\u2764\uFE0F?\u200D(?:\uD83D\uDC8B\u200D)?\uD83E\uDDD1\uD83C[\uDFFC-\uDFFF]|\uD83C[\uDF3E\uDF73\uDF7C\uDF84\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E(?:[\uDDAF\uDDBC\uDDBD](?:\u200D\u27A1\uFE0F?)?|[\uDDB0-\uDDB3]|\uDD1D\u200D\uD83E\uDDD1\uD83C[\uDFFB-\uDFFF])))?|\uDFFC(?:\u200D(?:[\u2695\u2696\u2708]\uFE0F?|\u2764\uFE0F?\u200D(?:\uD83D\uDC8B\u200D)?\uD83E\uDDD1\uD83C[\uDFFB\uDFFD-\uDFFF]|\uD83C[\uDF3E\uDF73\uDF7C\uDF84\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E(?:[\uDDAF\uDDBC\uDDBD](?:\u200D\u27A1\uFE0F?)?|[\uDDB0-\uDDB3]|\uDD1D\u200D\uD83E\uDDD1\uD83C[\uDFFB-\uDFFF])))?|\uDFFD(?:\u200D(?:[\u2695\u2696\u2708]\uFE0F?|\u2764\uFE0F?\u200D(?:\uD83D\uDC8B\u200D)?\uD83E\uDDD1\uD83C[\uDFFB\uDFFC\uDFFE\uDFFF]|\uD83C[\uDF3E\uDF73\uDF7C\uDF84\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E(?:[\uDDAF\uDDBC\uDDBD](?:\u200D\u27A1\uFE0F?)?|[\uDDB0-\uDDB3]|\uDD1D\u200D\uD83E\uDDD1\uD83C[\uDFFB-\uDFFF])))?|\uDFFE(?:\u200D(?:[\u2695\u2696\u2708]\uFE0F?|\u2764\uFE0F?\u200D(?:\uD83D\uDC8B\u200D)?\uD83E\uDDD1\uD83C[\uDFFB-\uDFFD\uDFFF]|\uD83C[\uDF3E\uDF73\uDF7C\uDF84\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E(?:[\uDDAF\uDDBC\uDDBD](?:\u200D\u27A1\uFE0F?)?|[\uDDB0-\uDDB3]|\uDD1D\u200D\uD83E\uDDD1\uD83C[\uDFFB-\uDFFF])))?|\uDFFF(?:\u200D(?:[\u2695\u2696\u2708]\uFE0F?|\u2764\uFE0F?\u200D(?:\uD83D\uDC8B\u200D)?\uD83E\uDDD1\uD83C[\uDFFB-\uDFFE]|\uD83C[\uDF3E\uDF73\uDF7C\uDF84\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E(?:[\uDDAF\uDDBC\uDDBD](?:\u200D\u27A1\uFE0F?)?|[\uDDB0-\uDDB3]|\uDD1D\u200D\uD83E\uDDD1\uD83C[\uDFFB-\uDFFF])))?))?|\uDEF1(?:\uD83C(?:\uDFFB(?:\u200D\uD83E\uDEF2\uD83C[\uDFFC-\uDFFF])?|\uDFFC(?:\u200D\uD83E\uDEF2\uD83C[\uDFFB\uDFFD-\uDFFF])?|\uDFFD(?:\u200D\uD83E\uDEF2\uD83C[\uDFFB\uDFFC\uDFFE\uDFFF])?|\uDFFE(?:\u200D\uD83E\uDEF2\uD83C[\uDFFB-\uDFFD\uDFFF])?|\uDFFF(?:\u200D\uD83E\uDEF2\uD83C[\uDFFB-\uDFFE])?))?)/g;function Nr(e){return e===12288||e>=65281&&e<=65376||e>=65504&&e<=65510}function Tr(e){return e>=4352&&e<=4447||e===8986||e===8987||e===9001||e===9002||e>=9193&&e<=9196||e===9200||e===9203||e===9725||e===9726||e===9748||e===9749||e>=9800&&e<=9811||e===9855||e===9875||e===9889||e===9898||e===9899||e===9917||e===9918||e===9924||e===9925||e===9934||e===9940||e===9962||e===9970||e===9971||e===9973||e===9978||e===9981||e===9989||e===9994||e===9995||e===10024||e===10060||e===10062||e>=10067&&e<=10069||e===10071||e>=10133&&e<=10135||e===10160||e===10175||e===11035||e===11036||e===11088||e===11093||e>=11904&&e<=11929||e>=11931&&e<=12019||e>=12032&&e<=12245||e>=12272&&e<=12287||e>=12289&&e<=12350||e>=12353&&e<=12438||e>=12441&&e<=12543||e>=12549&&e<=12591||e>=12593&&e<=12686||e>=12688&&e<=12771||e>=12783&&e<=12830||e>=12832&&e<=12871||e>=12880&&e<=19903||e>=19968&&e<=42124||e>=42128&&e<=42182||e>=43360&&e<=43388||e>=44032&&e<=55203||e>=63744&&e<=64255||e>=65040&&e<=65049||e>=65072&&e<=65106||e>=65108&&e<=65126||e>=65128&&e<=65131||e>=94176&&e<=94180||e===94192||e===94193||e>=94208&&e<=100343||e>=100352&&e<=101589||e>=101632&&e<=101640||e>=110576&&e<=110579||e>=110581&&e<=110587||e===110589||e===110590||e>=110592&&e<=110882||e===110898||e>=110928&&e<=110930||e===110933||e>=110948&&e<=110951||e>=110960&&e<=111355||e===126980||e===127183||e===127374||e>=127377&&e<=127386||e>=127488&&e<=127490||e>=127504&&e<=127547||e>=127552&&e<=127560||e===127568||e===127569||e>=127584&&e<=127589||e>=127744&&e<=127776||e>=127789&&e<=127797||e>=127799&&e<=127868||e>=127870&&e<=127891||e>=127904&&e<=127946||e>=127951&&e<=127955||e>=127968&&e<=127984||e===127988||e>=127992&&e<=128062||e===128064||e>=128066&&e<=128252||e>=128255&&e<=128317||e>=128331&&e<=128334||e>=128336&&e<=128359||e===128378||e===128405||e===128406||e===128420||e>=128507&&e<=128591||e>=128640&&e<=128709||e===128716||e>=128720&&e<=128722||e>=128725&&e<=128727||e>=128732&&e<=128735||e===128747||e===128748||e>=128756&&e<=128764||e>=128992&&e<=129003||e===129008||e>=129292&&e<=129338||e>=129340&&e<=129349||e>=129351&&e<=129535||e>=129648&&e<=129660||e>=129664&&e<=129672||e>=129680&&e<=129725||e>=129727&&e<=129733||e>=129742&&e<=129755||e>=129760&&e<=129768||e>=129776&&e<=129784||e>=131072&&e<=196605||e>=196608&&e<=262141}var kr=e=>!(Nr(e)||Tr(e));var ju=/[^\x20-\x7F]/u;function Hu(e){if(!e)return 0;if(!ju.test(e))return e.length;e=e.replace(Sr(),"  ");let t=0;for(let r of e){let n=r.codePointAt(0);n<=31||n>=127&&n<=159||n>=768&&n<=879||(t+=kr(n)?1:2);}return t}var Oe=Hu;function Ne(e,t){if(typeof e=="string")return t(e);let r=new Map;return n(e);function n(u){if(r.has(u))return r.get(u);let i=o(u);return r.set(u,i),i}function o(u){switch(G(u)){case W:return t(u.map(n));case S:return t({...u,parts:u.parts.map(n)});case _:return t({...u,breakContents:n(u.breakContents),flatContents:n(u.flatContents)});case x:{let{expandedStates:i,contents:s}=u;return i?(i=i.map(n),s=i[0]):s=n(s),t({...u,contents:s,expandedStates:i})}case P:case L:case R:case N:case Y:return t({...u,contents:n(u.contents)});case U:case z:case I:case j:case B:case b:return t(u);default:throw new Q(u)}}}function Xe(e,t,r){let n=r,o=!1;function u(i){if(o)return !1;let s=t(i);s!==void 0&&(o=!0,n=s);}return we(e,u),n}function Wu(e){if(e.type===x&&e.break||e.type===B&&e.hard||e.type===b)return !0}function Ir(e){return Xe(e,Wu,!1)}function Lr(e){if(e.length>0){let t=y(!1,e,-1);!t.expandedStates&&!t.break&&(t.break="propagated");}return null}function Rr(e){let t=new Set,r=[];function n(u){if(u.type===b&&Lr(r),u.type===x){if(r.push(u),t.has(u))return !1;t.add(u);}}function o(u){u.type===x&&r.pop().break&&Lr(r);}we(e,n,o,!0);}function Mu(e){return e.type===B&&!e.hard?e.soft?"":" ":e.type===_?e.flatContents:e}function Yr(e){return Ne(e,Mu)}function Pr(e){for(e=[...e];e.length>=2&&y(!1,e,-2).type===B&&y(!1,e,-1).type===b;)e.length-=2;if(e.length>0){let t=Se(y(!1,e,-1));e[e.length-1]=t;}return e}function Se(e){switch(G(e)){case L:case R:case x:case Y:case N:{let t=Se(e.contents);return {...e,contents:t}}case _:return {...e,breakContents:Se(e.breakContents),flatContents:Se(e.flatContents)};case S:return {...e,parts:Pr(e.parts)};case W:return Pr(e);case U:return e.replace(/[\n\r]*$/u,"");case P:case z:case I:case j:case B:case b:break;default:throw new Q(e)}return e}function Ze(e){return Se(Vu(e))}function $u(e){switch(G(e)){case S:if(e.parts.every(t=>t===""))return "";break;case x:if(!e.contents&&!e.id&&!e.break&&!e.expandedStates)return "";if(e.contents.type===x&&e.contents.id===e.id&&e.contents.break===e.break&&e.contents.expandedStates===e.expandedStates)return e.contents;break;case P:case L:case R:case Y:if(!e.contents)return "";break;case _:if(!e.flatContents&&!e.breakContents)return "";break;case W:{let t=[];for(let r of e){if(!r)continue;let[n,...o]=Array.isArray(r)?r:[r];typeof n=="string"&&typeof y(!1,t,-1)=="string"?t[t.length-1]+=n:t.push(n),t.push(...o);}return t.length===0?"":t.length===1?t[0]:t}case U:case z:case I:case j:case B:case N:case b:break;default:throw new Q(e)}return e}function Vu(e){return Ne(e,t=>$u(t))}function jr(e,t=qe){return Ne(e,r=>typeof r=="string"?be(t,r.split(`
`)):r)}function Uu(e){if(e.type===B)return !0}function Hr(e){return Xe(e,Uu,!1)}function Qe(e,t){return e.type===N?{...e,contents:t(e.contents)}:t(e)}var H=Symbol("MODE_BREAK"),J=Symbol("MODE_FLAT"),Te=Symbol("cursor");function Wr(){return {value:"",length:0,queue:[]}}function zu(e,t){return bt(e,{type:"indent"},t)}function Gu(e,t,r){return t===Number.NEGATIVE_INFINITY?e.root||Wr():t<0?bt(e,{type:"dedent"},r):t?t.type==="root"?{...e,root:e}:bt(e,{type:typeof t=="string"?"stringAlign":"numberAlign",n:t},r):e}function bt(e,t,r){let n=t.type==="dedent"?e.queue.slice(0,-1):[...e.queue,t],o="",u=0,i=0,s=0;for(let c of n)switch(c.type){case"indent":l(),r.useTabs?a(1):D(r.tabWidth);break;case"stringAlign":l(),o+=c.n,u+=c.n.length;break;case"numberAlign":i+=1,s+=c.n;break;default:throw new Error(`Unexpected type '${c.type}'`)}return f(),{...e,value:o,length:u,queue:n};function a(c){o+="	".repeat(c),u+=r.tabWidth*c;}function D(c){o+=" ".repeat(c),u+=c;}function l(){r.useTabs?d():f();}function d(){i>0&&a(i),p();}function f(){s>0&&D(s),p();}function p(){i=0,s=0;}}function Ot(e){let t=0,r=0,n=e.length;e:for(;n--;){let o=e[n];if(o===Te){r++;continue}for(let u=o.length-1;u>=0;u--){let i=o[u];if(i===" "||i==="	")t++;else {e[n]=o.slice(0,u+1);break e}}}if(t>0||r>0)for(e.length=n+1;r-- >0;)e.push(Te);return t}function et(e,t,r,n,o,u){if(r===Number.POSITIVE_INFINITY)return !0;let i=t.length,s=[e],a=[];for(;r>=0;){if(s.length===0){if(i===0)return !0;s.push(t[--i]);continue}let{mode:D,doc:l}=s.pop(),d=G(l);switch(d){case U:a.push(l),r-=Oe(l);break;case W:case S:{let f=d===W?l:l.parts;for(let p=f.length-1;p>=0;p--)s.push({mode:D,doc:f[p]});break}case L:case P:case R:case N:s.push({mode:D,doc:l.contents});break;case I:r+=Ot(a);break;case x:{if(u&&l.break)return !1;let f=l.break?H:D,p=l.expandedStates&&f===H?y(!1,l.expandedStates,-1):l.contents;s.push({mode:f,doc:p});break}case _:{let p=(l.groupId?o[l.groupId]||J:D)===H?l.breakContents:l.flatContents;p&&s.push({mode:D,doc:p});break}case B:if(D===H||l.hard)return !0;l.soft||(a.push(" "),r--);break;case Y:n=!0;break;case j:if(n)return !1;break}}return !1}function Fe(e,t){let r={},n=t.printWidth,o=Be(t.endOfLine),u=0,i=[{ind:Wr(),mode:H,doc:e}],s=[],a=!1,D=[],l=0;for(Rr(e);i.length>0;){let{ind:f,mode:p,doc:c}=i.pop();switch(G(c)){case U:{let F=o!==`
`?ne(!1,c,`
`,o):c;s.push(F),i.length>0&&(u+=Oe(F));break}case W:for(let F=c.length-1;F>=0;F--)i.push({ind:f,mode:p,doc:c[F]});break;case z:if(l>=2)throw new Error("There are too many 'cursor' in doc.");s.push(Te),l++;break;case L:i.push({ind:zu(f,t),mode:p,doc:c.contents});break;case P:i.push({ind:Gu(f,c.n,t),mode:p,doc:c.contents});break;case I:u-=Ot(s);break;case x:switch(p){case J:if(!a){i.push({ind:f,mode:c.break?H:J,doc:c.contents});break}case H:{a=!1;let F={ind:f,mode:J,doc:c.contents},m=n-u,E=D.length>0;if(!c.break&&et(F,i,m,E,r))i.push(F);else if(c.expandedStates){let A=y(!1,c.expandedStates,-1);if(c.break){i.push({ind:f,mode:H,doc:A});break}else for(let w=1;w<c.expandedStates.length+1;w++)if(w>=c.expandedStates.length){i.push({ind:f,mode:H,doc:A});break}else {let h=c.expandedStates[w],C={ind:f,mode:J,doc:h};if(et(C,i,m,E,r)){i.push(C);break}}}else i.push({ind:f,mode:H,doc:c.contents});break}}c.id&&(r[c.id]=y(!1,i,-1).mode);break;case S:{let F=n-u,{parts:m}=c;if(m.length===0)break;let[E,A]=m,w={ind:f,mode:J,doc:E},h={ind:f,mode:H,doc:E},C=et(w,[],F,D.length>0,r,!0);if(m.length===1){C?i.push(w):i.push(h);break}let k={ind:f,mode:J,doc:A},v={ind:f,mode:H,doc:A};if(m.length===2){C?i.push(k,w):i.push(v,h);break}m.splice(0,2);let $={ind:f,mode:p,doc:Ge(m)},ye=m[0];et({ind:f,mode:J,doc:[E,A,ye]},[],F,D.length>0,r,!0)?i.push($,k,w):C?i.push($,v,w):i.push($,v,h);break}case _:case R:{let F=c.groupId?r[c.groupId]:p;if(F===H){let m=c.type===_?c.breakContents:c.negate?c.contents:De(c.contents);m&&i.push({ind:f,mode:p,doc:m});}if(F===J){let m=c.type===_?c.flatContents:c.negate?De(c.contents):c.contents;m&&i.push({ind:f,mode:p,doc:m});}break}case Y:D.push({ind:f,mode:p,doc:c.contents});break;case j:D.length>0&&i.push({ind:f,mode:p,doc:_e});break;case B:switch(p){case J:if(c.hard)a=!0;else {c.soft||(s.push(" "),u+=1);break}case H:if(D.length>0){i.push({ind:f,mode:p,doc:c},...D.reverse()),D.length=0;break}c.literal?f.root?(s.push(o,f.root.value),u=f.root.length):(s.push(o),u=0):(u-=Ot(s),s.push(o+f.value),u=f.length);break}break;case N:i.push({ind:f,mode:p,doc:c.contents});break;case b:break;default:throw new Q(c)}i.length===0&&D.length>0&&(i.push(...D.reverse()),D.length=0);}let d=s.indexOf(Te);if(d!==-1){let f=s.indexOf(Te,d+1),p=s.slice(0,d).join(""),c=s.slice(d+1,f).join(""),F=s.slice(f+1).join("");return {formatted:p+c+F,cursorNodeStart:p.length,cursorNodeText:c}}return {formatted:s.join("")}}function Ku(e,t,r=0){let n=0;for(let o=r;o<e.length;++o)e[o]==="	"?n=n+t-n%t:n++;return n}var me=Ku;var te,Nt,tt,St=class{constructor(t){Dr(this,te);this.stack=[t];}get key(){let{stack:t,siblings:r}=this;return y(!1,t,r===null?-2:-4)??null}get index(){return this.siblings===null?null:y(!1,this.stack,-2)}get node(){return y(!1,this.stack,-1)}get parent(){return this.getNode(1)}get grandparent(){return this.getNode(2)}get isInArray(){return this.siblings!==null}get siblings(){let{stack:t}=this,r=y(!1,t,-3);return Array.isArray(r)?r:null}get next(){let{siblings:t}=this;return t===null?null:t[this.index+1]}get previous(){let{siblings:t}=this;return t===null?null:t[this.index-1]}get isFirst(){return this.index===0}get isLast(){let{siblings:t,index:r}=this;return t!==null&&r===t.length-1}get isRoot(){return this.stack.length===1}get root(){return this.stack[0]}get ancestors(){return [...pe(this,te,tt).call(this)]}getName(){let{stack:t}=this,{length:r}=t;return r>1?y(!1,t,-2):null}getValue(){return y(!1,this.stack,-1)}getNode(t=0){let r=pe(this,te,Nt).call(this,t);return r===-1?null:this.stack[r]}getParentNode(t=0){return this.getNode(t+1)}call(t,...r){let{stack:n}=this,{length:o}=n,u=y(!1,n,-1);for(let i of r)u=u[i],n.push(i,u);try{return t(this)}finally{n.length=o;}}callParent(t,r=0){let n=pe(this,te,Nt).call(this,r+1),o=this.stack.splice(n+1);try{return t(this)}finally{this.stack.push(...o);}}each(t,...r){let{stack:n}=this,{length:o}=n,u=y(!1,n,-1);for(let i of r)u=u[i],n.push(i,u);try{for(let i=0;i<u.length;++i)n.push(i,u[i]),t(this,i,u),n.length-=2;}finally{n.length=o;}}map(t,...r){let n=[];return this.each((o,u,i)=>{n[u]=t(o,u,i);},...r),n}match(...t){let r=this.stack.length-1,n=null,o=this.stack[r--];for(let u of t){if(o===void 0)return !1;let i=null;if(typeof n=="number"&&(i=n,n=this.stack[r--],o=this.stack[r--]),u&&!u(o,n,i))return !1;n=this.stack[r--],o=this.stack[r--];}return !0}findAncestor(t){for(let r of pe(this,te,tt).call(this))if(t(r))return r}hasAncestor(t){for(let r of pe(this,te,tt).call(this))if(t(r))return !0;return !1}};te=new WeakSet,Nt=function(t){let{stack:r}=this;for(let n=r.length-1;n>=0;n-=2)if(!Array.isArray(r[n])&&--t<0)return n;return -1},tt=function*(){let{stack:t}=this;for(let r=t.length-3;r>=0;r-=2){let n=t[r];Array.isArray(n)||(yield n);}};var Mr=St;var $r=new Proxy(()=>{},{get:()=>$r}),ke=$r;function qu(e){return e!==null&&typeof e=="object"}var Vr=qu;function*Tt(e,t){let{getVisitorKeys:r,filter:n=()=>!0}=t,o=u=>Vr(u)&&n(u);for(let u of r(e)){let i=e[u];if(Array.isArray(i))for(let s of i)o(s)&&(yield s);else o(i)&&(yield i);}}function*Ur(e,t){let r=[e];for(let n=0;n<r.length;n++){let o=r[n];for(let u of Tt(o,t))yield u,r.push(u);}}function Ee(e){return (t,r,n)=>{let o=!!(n!=null&&n.backwards);if(r===!1)return !1;let{length:u}=t,i=r;for(;i>=0&&i<u;){let s=t.charAt(i);if(e instanceof RegExp){if(!e.test(s))return i}else if(!e.includes(s))return i;o?i--:i++;}return i===-1||i===u?i:!1}}var zr=Ee(/\s/u),T=Ee(" 	"),rt=Ee(",; 	"),nt=Ee(/[^\n\r]/u);function Ju(e,t,r){let n=!!(r!=null&&r.backwards);if(t===!1)return !1;let o=e.charAt(t);if(n){if(e.charAt(t-1)==="\r"&&o===`
`)return t-2;if(o===`
`||o==="\r"||o==="\u2028"||o==="\u2029")return t-1}else {if(o==="\r"&&e.charAt(t+1)===`
`)return t+2;if(o===`
`||o==="\r"||o==="\u2028"||o==="\u2029")return t+1}return t}var M=Ju;function Xu(e,t,r={}){let n=T(e,r.backwards?t-1:t,r),o=M(e,n,r);return n!==o}var V=Xu;function Zu(e){return Array.isArray(e)&&e.length>0}var kt=Zu;var Gr=new Set(["tokens","comments","parent","enclosingNode","precedingNode","followingNode"]),Qu=e=>Object.keys(e).filter(t=>!Gr.has(t));function eo(e){return e?t=>e(t,Gr):Qu}var X=eo;function to(e){let t=e.type||e.kind||"(unknown type)",r=String(e.name||e.id&&(typeof e.id=="object"?e.id.name:e.id)||e.key&&(typeof e.key=="object"?e.key.name:e.key)||e.value&&(typeof e.value=="object"?"":String(e.value))||e.operator||"");return r.length>20&&(r=r.slice(0,19)+"\u2026"),t+(r?" "+r:"")}function Lt(e,t){(e.comments??(e.comments=[])).push(t),t.printed=!1,t.nodeDescription=to(e);}function ue(e,t){t.leading=!0,t.trailing=!1,Lt(e,t);}function re(e,t,r){t.leading=!1,t.trailing=!1,r&&(t.marker=r),Lt(e,t);}function oe(e,t){t.leading=!1,t.trailing=!0,Lt(e,t);}var Pt=new WeakMap;function ut(e,t){if(Pt.has(e))return Pt.get(e);let{printer:{getCommentChildNodes:r,canAttachComment:n,getVisitorKeys:o},locStart:u,locEnd:i}=t;if(!n)return [];let s=((r==null?void 0:r(e,t))??[...Tt(e,{getVisitorKeys:X(o)})]).flatMap(a=>n(a)?[a]:ut(a,t));return s.sort((a,D)=>u(a)-u(D)||i(a)-i(D)),Pt.set(e,s),s}function qr(e,t,r,n){let{locStart:o,locEnd:u}=r,i=o(t),s=u(t),a=ut(e,r),D,l,d=0,f=a.length;for(;d<f;){let p=d+f>>1,c=a[p],F=o(c),m=u(c);if(F<=i&&s<=m)return qr(c,t,r,c);if(m<=i){D=c,d=p+1;continue}if(s<=F){l=c,f=p;continue}throw new Error("Comment location overlaps with node location")}if((n==null?void 0:n.type)==="TemplateLiteral"){let{quasis:p}=n,c=Rt(p,t,r);D&&Rt(p,D,r)!==c&&(D=null),l&&Rt(p,l,r)!==c&&(l=null);}return {enclosingNode:n,precedingNode:D,followingNode:l}}var It=()=>!1;function Jr(e,t){let{comments:r}=e;if(delete e.comments,!kt(r)||!t.printer.canAttachComment)return;let n=[],{locStart:o,locEnd:u,printer:{experimentalFeatures:{avoidAstMutation:i=!1}={},handleComments:s={}},originalText:a}=t,{ownLine:D=It,endOfLine:l=It,remaining:d=It}=s,f=r.map((p,c)=>({...qr(e,p,t),comment:p,text:a,options:t,ast:e,isLastComment:r.length-1===c}));for(let[p,c]of f.entries()){let{comment:F,precedingNode:m,enclosingNode:E,followingNode:A,text:w,options:h,ast:C,isLastComment:k}=c;if(h.parser==="json"||h.parser==="json5"||h.parser==="jsonc"||h.parser==="__js_expression"||h.parser==="__ts_expression"||h.parser==="__vue_expression"||h.parser==="__vue_ts_expression"){if(o(F)-o(C)<=0){ue(C,F);continue}if(u(F)-u(C)>=0){oe(C,F);continue}}let v;if(i?v=[c]:(F.enclosingNode=E,F.precedingNode=m,F.followingNode=A,v=[F,w,h,C,k]),ro(w,h,f,p))F.placement="ownLine",D(...v)||(A?ue(A,F):m?oe(m,F):E?re(E,F):re(C,F));else if(no(w,h,f,p))F.placement="endOfLine",l(...v)||(m?oe(m,F):A?ue(A,F):E?re(E,F):re(C,F));else if(F.placement="remaining",!d(...v))if(m&&A){let $=n.length;$>0&&n[$-1].followingNode!==A&&Kr(n,h),n.push(c);}else m?oe(m,F):A?ue(A,F):E?re(E,F):re(C,F);}if(Kr(n,t),!i)for(let p of r)delete p.precedingNode,delete p.enclosingNode,delete p.followingNode;}var Xr=e=>!/[\S\n\u2028\u2029]/u.test(e);function ro(e,t,r,n){let{comment:o,precedingNode:u}=r[n],{locStart:i,locEnd:s}=t,a=i(o);if(u)for(let D=n-1;D>=0;D--){let{comment:l,precedingNode:d}=r[D];if(d!==u||!Xr(e.slice(s(l),a)))break;a=i(l);}return V(e,a,{backwards:!0})}function no(e,t,r,n){let{comment:o,followingNode:u}=r[n],{locStart:i,locEnd:s}=t,a=s(o);if(u)for(let D=n+1;D<r.length;D++){let{comment:l,followingNode:d}=r[D];if(d!==u||!Xr(e.slice(a,i(l))))break;a=s(l);}return V(e,a)}function Kr(e,t){var s,a;let r=e.length;if(r===0)return;let{precedingNode:n,followingNode:o}=e[0],u=t.locStart(o),i;for(i=r;i>0;--i){let{comment:D,precedingNode:l,followingNode:d}=e[i-1];ke.strictEqual(l,n),ke.strictEqual(d,o);let f=t.originalText.slice(t.locEnd(D),u);if(((a=(s=t.printer).isGap)==null?void 0:a.call(s,f,t))??/^[\s(]*$/u.test(f))u=t.locStart(D);else break}for(let[D,{comment:l}]of e.entries())D<i?oe(n,l):ue(o,l);for(let D of [n,o])D.comments&&D.comments.length>1&&D.comments.sort((l,d)=>t.locStart(l)-t.locStart(d));e.length=0;}function Rt(e,t,r){let n=r.locStart(t)-1;for(let o=1;o<e.length;++o)if(n<r.locStart(e[o]))return o-1;return 0}function uo(e,t){let r=t-1;r=T(e,r,{backwards:!0}),r=M(e,r,{backwards:!0}),r=T(e,r,{backwards:!0});let n=M(e,r,{backwards:!0});return r!==n}var Le=uo;function Zr(e,t){let r=e.node;return r.printed=!0,t.printer.printComment(e,t)}function oo(e,t){var l;let r=e.node,n=[Zr(e,t)],{printer:o,originalText:u,locStart:i,locEnd:s}=t;if((l=o.isBlockComment)==null?void 0:l.call(o,r)){let d=V(u,s(r))?V(u,i(r),{backwards:!0})?q:Ke:" ";n.push(d);}else n.push(q);let D=M(u,T(u,s(r)));return D!==!1&&V(u,D)&&n.push(q),n}function io(e,t,r){var D;let n=e.node,o=Zr(e,t),{printer:u,originalText:i,locStart:s}=t,a=(D=u.isBlockComment)==null?void 0:D.call(u,n);if(r!=null&&r.hasLineSuffix&&!(r!=null&&r.isBlock)||V(i,s(n),{backwards:!0})){let l=Le(i,s(n));return {doc:xe([q,l?q:"",o]),isBlock:a,hasLineSuffix:!0}}return !a||r!=null&&r.hasLineSuffix?{doc:[xe([" ",o]),de],isBlock:a,hasLineSuffix:!0}:{doc:[" ",o],isBlock:a,hasLineSuffix:!1}}function so(e,t){let r=e.node;if(!r)return {};let n=t[Symbol.for("printedComments")];if((r.comments||[]).filter(a=>!n.has(a)).length===0)return {leading:"",trailing:""};let u=[],i=[],s;return e.each(()=>{let a=e.node;if(n!=null&&n.has(a))return;let{leading:D,trailing:l}=a;D?u.push(oo(e,t)):l&&(s=io(e,t,s),i.push(s.doc));},"comments"),{leading:u,trailing:i}}function Qr(e,t,r){let{leading:n,trailing:o}=so(e,r);return !n&&!o?t:Qe(t,u=>[n,u,o])}function en(e){let{[Symbol.for("comments")]:t,[Symbol.for("printedComments")]:r}=e;for(let n of t){if(!n.printed&&!r.has(n))throw new Error('Comment "'+n.value.trim()+'" was not printed. Please report this error!');delete n.printed;}}var Pe=class extends Error{name="ConfigError"},Ie=class extends Error{name="UndefinedParserError"};var rn={cursorOffset:{category:"Special",type:"int",default:-1,range:{start:-1,end:1/0,step:1},description:"Print (to stderr) where a cursor at the given position would move to after formatting.",cliCategory:"Editor"},endOfLine:{category:"Global",type:"choice",default:"lf",description:"Which end of line characters to apply.",choices:[{value:"lf",description:"Line Feed only (\\n), common on Linux and macOS as well as inside git repos"},{value:"crlf",description:"Carriage Return + Line Feed characters (\\r\\n), common on Windows"},{value:"cr",description:"Carriage Return character only (\\r), used very rarely"},{value:"auto",description:`Maintain existing
(mixed values within one file are normalised by looking at what's used after the first line)`}]},filepath:{category:"Special",type:"path",description:"Specify the input filepath. This will be used to do parser inference.",cliName:"stdin-filepath",cliCategory:"Other",cliDescription:"Path to the file to pretend that stdin comes from."},insertPragma:{category:"Special",type:"boolean",default:!1,description:"Insert @format pragma into file's first docblock comment.",cliCategory:"Other"},parser:{category:"Global",type:"choice",default:void 0,description:"Which parser to use.",exception:e=>typeof e=="string"||typeof e=="function",choices:[{value:"flow",description:"Flow"},{value:"babel",description:"JavaScript"},{value:"babel-flow",description:"Flow"},{value:"babel-ts",description:"TypeScript"},{value:"typescript",description:"TypeScript"},{value:"acorn",description:"JavaScript"},{value:"espree",description:"JavaScript"},{value:"meriyah",description:"JavaScript"},{value:"css",description:"CSS"},{value:"less",description:"Less"},{value:"scss",description:"SCSS"},{value:"json",description:"JSON"},{value:"json5",description:"JSON5"},{value:"jsonc",description:"JSON with Comments"},{value:"json-stringify",description:"JSON.stringify"},{value:"graphql",description:"GraphQL"},{value:"markdown",description:"Markdown"},{value:"mdx",description:"MDX"},{value:"vue",description:"Vue"},{value:"yaml",description:"YAML"},{value:"glimmer",description:"Ember / Handlebars"},{value:"html",description:"HTML"},{value:"angular",description:"Angular"},{value:"lwc",description:"Lightning Web Components"}]},plugins:{type:"path",array:!0,default:[{value:[]}],category:"Global",description:"Add a plugin. Multiple plugins can be passed as separate `--plugin`s.",exception:e=>typeof e=="string"||typeof e=="object",cliName:"plugin",cliCategory:"Config"},printWidth:{category:"Global",type:"int",default:80,description:"The line length where Prettier will try wrap.",range:{start:0,end:1/0,step:1}},rangeEnd:{category:"Special",type:"int",default:1/0,range:{start:0,end:1/0,step:1},description:`Format code ending at a given character offset (exclusive).
The range will extend forwards to the end of the selected statement.`,cliCategory:"Editor"},rangeStart:{category:"Special",type:"int",default:0,range:{start:0,end:1/0,step:1},description:`Format code starting at a given character offset.
The range will extend backwards to the start of the first line containing the selected statement.`,cliCategory:"Editor"},requirePragma:{category:"Special",type:"boolean",default:!1,description:`Require either '@prettier' or '@format' to be present in the file's first docblock comment
in order for it to be formatted.`,cliCategory:"Other"},tabWidth:{type:"int",category:"Global",default:2,description:"Number of spaces per indentation level.",range:{start:0,end:1/0,step:1}},useTabs:{category:"Global",type:"boolean",default:!1,description:"Indent with tabs instead of spaces."},embeddedLanguageFormatting:{category:"Global",type:"choice",default:"auto",description:"Control how Prettier formats quoted code embedded in the file.",choices:[{value:"auto",description:"Format embedded code if Prettier can automatically identify it."},{value:"off",description:"Never automatically format embedded code."}]}};function ot({plugins:e=[],showDeprecated:t=!1}={}){let r=e.flatMap(o=>o.languages??[]),n=[];for(let o of lo(Object.assign({},...e.map(({options:u})=>u),rn)))!t&&o.deprecated||(Array.isArray(o.choices)&&(t||(o.choices=o.choices.filter(u=>!u.deprecated)),o.name==="parser"&&(o.choices=[...o.choices,...Do(o.choices,r,e)])),o.pluginDefaults=Object.fromEntries(e.filter(u=>{var i;return ((i=u.defaultOptions)==null?void 0:i[o.name])!==void 0}).map(u=>[u.name,u.defaultOptions[o.name]])),n.push(o));return {languages:r,options:n}}function*Do(e,t,r){let n=new Set(e.map(o=>o.value));for(let o of t)if(o.parsers){for(let u of o.parsers)if(!n.has(u)){n.add(u);let i=r.find(a=>a.parsers&&Object.prototype.hasOwnProperty.call(a.parsers,u)),s=o.name;i!=null&&i.name&&(s+=` (plugin: ${i.name})`),yield {value:u,description:s};}}}function lo(e){let t=[];for(let[r,n]of Object.entries(e)){let o={name:r,...n};Array.isArray(o.default)&&(o.default=y(!1,o.default,-1).value),t.push(o);}return t}var co=e=>String(e).split(/[/\\]/u).pop();function nn(e,t){if(!t)return;let r=co(t).toLowerCase();return e.find(({filenames:n})=>n==null?void 0:n.some(o=>o.toLowerCase()===r))??e.find(({extensions:n})=>n==null?void 0:n.some(o=>r.endsWith(o)))}function fo(e,t){if(t)return e.find(({name:r})=>r.toLowerCase()===t)??e.find(({aliases:r})=>r==null?void 0:r.includes(t))??e.find(({extensions:r})=>r==null?void 0:r.includes(`.${t}`))}function po(e,t){let r=e.plugins.flatMap(o=>o.languages??[]),n=fo(r,t.language)??nn(r,t.physicalFile)??nn(r,t.file)??(t.physicalFile,void 0);return n==null?void 0:n.parsers[0]}var un=po;var ie={key:e=>/^[$_a-zA-Z][$_a-zA-Z0-9]*$/.test(e)?e:JSON.stringify(e),value(e){if(e===null||typeof e!="object")return JSON.stringify(e);if(Array.isArray(e))return `[${e.map(r=>ie.value(r)).join(", ")}]`;let t=Object.keys(e);return t.length===0?"{}":`{ ${t.map(r=>`${ie.key(r)}: ${ie.value(e[r])}`).join(", ")} }`},pair:({key:e,value:t})=>ie.value({[e]:t})};var Yt=Me(it()),an=(e,t,{descriptor:r})=>{let n=[`${Yt.default.yellow(typeof e=="string"?r.key(e):r.pair(e))} is deprecated`];return t&&n.push(`we now treat it as ${Yt.default.blue(typeof t=="string"?r.key(t):r.pair(t))}`),n.join("; ")+"."};var le=Me(it());var st=Symbol.for("vnopts.VALUE_NOT_EXIST"),he=Symbol.for("vnopts.VALUE_UNCHANGED");var Dn=" ".repeat(2),cn=(e,t,r)=>{let{text:n,list:o}=r.normalizeExpectedResult(r.schemas[e].expected(r)),u=[];return n&&u.push(ln(e,t,n,r.descriptor)),o&&u.push([ln(e,t,o.title,r.descriptor)].concat(o.values.map(i=>fn(i,r.loggerPrintWidth))).join(`
`)),pn(u,r.loggerPrintWidth)};function ln(e,t,r,n){return [`Invalid ${le.default.red(n.key(e))} value.`,`Expected ${le.default.blue(r)},`,`but received ${t===st?le.default.gray("nothing"):le.default.red(n.value(t))}.`].join(" ")}function fn({text:e,list:t},r){let n=[];return e&&n.push(`- ${le.default.blue(e)}`),t&&n.push([`- ${le.default.blue(t.title)}:`].concat(t.values.map(o=>fn(o,r-Dn.length).replace(/^|\n/g,`$&${Dn}`))).join(`
`)),pn(n,r)}function pn(e,t){if(e.length===1)return e[0];let[r,n]=e,[o,u]=e.map(i=>i.split(`
`,1)[0].length);return o>t&&o>u?n:r}var Wt=Me(it());var jt=[],dn=[];function Ht(e,t){if(e===t)return 0;let r=e;e.length>t.length&&(e=t,t=r);let n=e.length,o=t.length;for(;n>0&&e.charCodeAt(~-n)===t.charCodeAt(~-o);)n--,o--;let u=0;for(;u<n&&e.charCodeAt(u)===t.charCodeAt(u);)u++;if(n-=u,o-=u,n===0)return o;let i,s,a,D,l=0,d=0;for(;l<n;)dn[l]=e.charCodeAt(u+l),jt[l]=++l;for(;d<o;)for(i=t.charCodeAt(u+d),a=d++,s=d,l=0;l<n;l++)D=i===dn[l]?a:a+1,a=jt[l],s=jt[l]=a>s?D>s?s+1:D:D>a?a+1:D;return s}var at$1=(e,t,{descriptor:r,logger:n,schemas:o})=>{let u=[`Ignored unknown option ${Wt.default.yellow(r.pair({key:e,value:t}))}.`],i=Object.keys(o).sort().find(s=>Ht(e,s)<3);i&&u.push(`Did you mean ${Wt.default.blue(r.key(i))}?`),n.warn(u.join(" "));};var Fo=["default","expected","validate","deprecated","forward","redirect","overlap","preprocess","postprocess"];function mo(e,t){let r=new e(t),n=Object.create(r);for(let o of Fo)o in t&&(n[o]=Eo(t[o],r,O.prototype[o].length));return n}var O=class{static create(t){return mo(this,t)}constructor(t){this.name=t.name;}default(t){}expected(t){return "nothing"}validate(t,r){return !1}deprecated(t,r){return !1}forward(t,r){}redirect(t,r){}overlap(t,r,n){return t}preprocess(t,r){return t}postprocess(t,r){return he}};function Eo(e,t,r){return typeof e=="function"?(...n)=>e(...n.slice(0,r-1),t,...n.slice(r-1)):()=>e}var Dt=class extends O{constructor(t){super(t),this._sourceName=t.sourceName;}expected(t){return t.schemas[this._sourceName].expected(t)}validate(t,r){return r.schemas[this._sourceName].validate(t,r)}redirect(t,r){return this._sourceName}};var lt=class extends O{expected(){return "anything"}validate(){return !0}};var ct=class extends O{constructor({valueSchema:t,name:r=t.name,...n}){super({...n,name:r}),this._valueSchema=t;}expected(t){let{text:r,list:n}=t.normalizeExpectedResult(this._valueSchema.expected(t));return {text:r&&`an array of ${r}`,list:n&&{title:"an array of the following values",values:[{list:n}]}}}validate(t,r){if(!Array.isArray(t))return !1;let n=[];for(let o of t){let u=r.normalizeValidateResult(this._valueSchema.validate(o,r),o);u!==!0&&n.push(u.value);}return n.length===0?!0:{value:n}}deprecated(t,r){let n=[];for(let o of t){let u=r.normalizeDeprecatedResult(this._valueSchema.deprecated(o,r),o);u!==!1&&n.push(...u.map(({value:i})=>({value:[i]})));}return n}forward(t,r){let n=[];for(let o of t){let u=r.normalizeForwardResult(this._valueSchema.forward(o,r),o);n.push(...u.map(Fn));}return n}redirect(t,r){let n=[],o=[];for(let u of t){let i=r.normalizeRedirectResult(this._valueSchema.redirect(u,r),u);"remain"in i&&n.push(i.remain),o.push(...i.redirect.map(Fn));}return n.length===0?{redirect:o}:{redirect:o,remain:n}}overlap(t,r){return t.concat(r)}};function Fn({from:e,to:t}){return {from:[e],to:t}}var ft=class extends O{expected(){return "true or false"}validate(t){return typeof t=="boolean"}};function En(e,t){let r=Object.create(null);for(let n of e){let o=n[t];if(r[o])throw new Error(`Duplicate ${t} ${JSON.stringify(o)}`);r[o]=n;}return r}function hn(e,t){let r=new Map;for(let n of e){let o=n[t];if(r.has(o))throw new Error(`Duplicate ${t} ${JSON.stringify(o)}`);r.set(o,n);}return r}function Cn(){let e=Object.create(null);return t=>{let r=JSON.stringify(t);return e[r]?!0:(e[r]=!0,!1)}}function gn(e,t){let r=[],n=[];for(let o of e)t(o)?r.push(o):n.push(o);return [r,n]}function yn(e){return e===Math.floor(e)}function An(e,t){if(e===t)return 0;let r=typeof e,n=typeof t,o=["undefined","object","boolean","number","string"];return r!==n?o.indexOf(r)-o.indexOf(n):r!=="string"?Number(e)-Number(t):e.localeCompare(t)}function Bn(e){return (...t)=>{let r=e(...t);return typeof r=="string"?new Error(r):r}}function Mt(e){return e===void 0?{}:e}function $t(e){if(typeof e=="string")return {text:e};let{text:t,list:r}=e;return ho((t||r)!==void 0,"Unexpected `expected` result, there should be at least one field."),r?{text:t,list:{title:r.title,values:r.values.map($t)}}:{text:t}}function Vt(e,t){return e===!0?!0:e===!1?{value:t}:e}function Ut(e,t,r=!1){return e===!1?!1:e===!0?r?!0:[{value:t}]:"value"in e?[e]:e.length===0?!1:e}function mn(e,t){return typeof e=="string"||"key"in e?{from:t,to:e}:"from"in e?{from:e.from,to:e.to}:{from:t,to:e.to}}function pt(e,t){return e===void 0?[]:Array.isArray(e)?e.map(r=>mn(r,t)):[mn(e,t)]}function zt(e,t){let r=pt(typeof e=="object"&&"redirect"in e?e.redirect:e,t);return r.length===0?{remain:t,redirect:r}:typeof e=="object"&&"remain"in e?{remain:e.remain,redirect:r}:{redirect:r}}function ho(e,t){if(!e)throw new Error(t)}var dt=class extends O{constructor(t){super(t),this._choices=hn(t.choices.map(r=>r&&typeof r=="object"?r:{value:r}),"value");}expected({descriptor:t}){let r=Array.from(this._choices.keys()).map(i=>this._choices.get(i)).filter(({hidden:i})=>!i).map(i=>i.value).sort(An).map(t.value),n=r.slice(0,-2),o=r.slice(-2);return {text:n.concat(o.join(" or ")).join(", "),list:{title:"one of the following values",values:r}}}validate(t){return this._choices.has(t)}deprecated(t){let r=this._choices.get(t);return r&&r.deprecated?{value:t}:!1}forward(t){let r=this._choices.get(t);return r?r.forward:void 0}redirect(t){let r=this._choices.get(t);return r?r.redirect:void 0}};var Ft=class extends O{expected(){return "a number"}validate(t,r){return typeof t=="number"}};var mt=class extends Ft{expected(){return "an integer"}validate(t,r){return r.normalizeValidateResult(super.validate(t,r),t)===!0&&yn(t)}};var Re=class extends O{expected(){return "a string"}validate(t){return typeof t=="string"}};var wn=ie,xn=at$1,_n=cn,vn=an;var Et=class{constructor(t,r){let{logger:n=console,loggerPrintWidth:o=80,descriptor:u=wn,unknown:i=xn,invalid:s=_n,deprecated:a=vn,missing:D=()=>!1,required:l=()=>!1,preprocess:d=p=>p,postprocess:f=()=>he}=r||{};this._utils={descriptor:u,logger:n||{warn:()=>{}},loggerPrintWidth:o,schemas:En(t,"name"),normalizeDefaultResult:Mt,normalizeExpectedResult:$t,normalizeDeprecatedResult:Ut,normalizeForwardResult:pt,normalizeRedirectResult:zt,normalizeValidateResult:Vt},this._unknownHandler=i,this._invalidHandler=Bn(s),this._deprecatedHandler=a,this._identifyMissing=(p,c)=>!(p in c)||D(p,c),this._identifyRequired=l,this._preprocess=d,this._postprocess=f,this.cleanHistory();}cleanHistory(){this._hasDeprecationWarned=Cn();}normalize(t){let r={},o=[this._preprocess(t,this._utils)],u=()=>{for(;o.length!==0;){let i=o.shift(),s=this._applyNormalization(i,r);o.push(...s);}};u();for(let i of Object.keys(this._utils.schemas)){let s=this._utils.schemas[i];if(!(i in r)){let a=Mt(s.default(this._utils));"value"in a&&o.push({[i]:a.value});}}u();for(let i of Object.keys(this._utils.schemas)){if(!(i in r))continue;let s=this._utils.schemas[i],a=r[i],D=s.postprocess(a,this._utils);D!==he&&(this._applyValidation(D,i,s),r[i]=D);}return this._applyPostprocess(r),this._applyRequiredCheck(r),r}_applyNormalization(t,r){let n=[],{knownKeys:o,unknownKeys:u}=this._partitionOptionKeys(t);for(let i of o){let s=this._utils.schemas[i],a=s.preprocess(t[i],this._utils);this._applyValidation(a,i,s);let D=({from:p,to:c})=>{n.push(typeof c=="string"?{[c]:p}:{[c.key]:c.value});},l=({value:p,redirectTo:c})=>{let F=Ut(s.deprecated(p,this._utils),a,!0);if(F!==!1)if(F===!0)this._hasDeprecationWarned(i)||this._utils.logger.warn(this._deprecatedHandler(i,c,this._utils));else for(let{value:m}of F){let E={key:i,value:m};if(!this._hasDeprecationWarned(E)){let A=typeof c=="string"?{key:c,value:m}:c;this._utils.logger.warn(this._deprecatedHandler(E,A,this._utils));}}};pt(s.forward(a,this._utils),a).forEach(D);let f=zt(s.redirect(a,this._utils),a);if(f.redirect.forEach(D),"remain"in f){let p=f.remain;r[i]=i in r?s.overlap(r[i],p,this._utils):p,l({value:p});}for(let{from:p,to:c}of f.redirect)l({value:p,redirectTo:c});}for(let i of u){let s=t[i];this._applyUnknownHandler(i,s,r,(a,D)=>{n.push({[a]:D});});}return n}_applyRequiredCheck(t){for(let r of Object.keys(this._utils.schemas))if(this._identifyMissing(r,t)&&this._identifyRequired(r))throw this._invalidHandler(r,st,this._utils)}_partitionOptionKeys(t){let[r,n]=gn(Object.keys(t).filter(o=>!this._identifyMissing(o,t)),o=>o in this._utils.schemas);return {knownKeys:r,unknownKeys:n}}_applyValidation(t,r,n){let o=Vt(n.validate(t,this._utils),t);if(o!==!0)throw this._invalidHandler(r,o.value,this._utils)}_applyUnknownHandler(t,r,n,o){let u=this._unknownHandler(t,r,this._utils);if(u)for(let i of Object.keys(u)){if(this._identifyMissing(i,u))continue;let s=u[i];i in this._utils.schemas?o(i,s):n[i]=s;}}_applyPostprocess(t){let r=this._postprocess(t,this._utils);if(r!==he){if(r.delete)for(let n of r.delete)delete t[n];if(r.override){let{knownKeys:n,unknownKeys:o}=this._partitionOptionKeys(r.override);for(let u of n){let i=r.override[u];this._applyValidation(i,u,this._utils.schemas[u]),t[u]=i;}for(let u of o){let i=r.override[u];this._applyUnknownHandler(u,i,t,(s,a)=>{let D=this._utils.schemas[s];this._applyValidation(a,s,D),t[s]=a;});}}}}};var Gt;function go(e,t,{logger:r=!1,isCLI:n=!1,passThrough:o=!1,FlagSchema:u,descriptor:i}={}){if(n){if(!u)throw new Error("'FlagSchema' option is required.");if(!i)throw new Error("'descriptor' option is required.")}else i=ie;let s=o?Array.isArray(o)?(f,p)=>o.includes(f)?{[f]:p}:void 0:(f,p)=>({[f]:p}):(f,p,c)=>{let{_:F,...m}=c.schemas;return at$1(f,p,{...c,schemas:m})},a=yo(t,{isCLI:n,FlagSchema:u}),D=new Et(a,{logger:r,unknown:s,descriptor:i}),l=r!==!1;l&&Gt&&(D._hasDeprecationWarned=Gt);let d=D.normalize(e);return l&&(Gt=D._hasDeprecationWarned),d}function yo(e,{isCLI:t,FlagSchema:r}){let n=[];t&&n.push(lt.create({name:"_"}));for(let o of e)n.push(Ao(o,{isCLI:t,optionInfos:e,FlagSchema:r})),o.alias&&t&&n.push(Dt.create({name:o.alias,sourceName:o.name}));return n}function Ao(e,{isCLI:t,optionInfos:r,FlagSchema:n}){let{name:o}=e,u={name:o},i,s={};switch(e.type){case"int":i=mt,t&&(u.preprocess=Number);break;case"string":i=Re;break;case"choice":i=dt,u.choices=e.choices.map(a=>a!=null&&a.redirect?{...a,redirect:{to:{key:e.name,value:a.redirect}}}:a);break;case"boolean":i=ft;break;case"flag":i=n,u.flags=r.flatMap(a=>[a.alias,a.description&&a.name,a.oppositeDescription&&`no-${a.name}`].filter(Boolean));break;case"path":i=Re;break;default:throw new Error(`Unexpected type ${e.type}`)}if(e.exception?u.validate=(a,D,l)=>e.exception(a)||D.validate(a,l):u.validate=(a,D,l)=>a===void 0||D.validate(a,l),e.redirect&&(s.redirect=a=>a?{to:typeof e.redirect=="string"?e.redirect:{key:e.redirect.option,value:e.redirect.value}}:void 0),e.deprecated&&(s.deprecated=!0),t&&!e.array){let a=u.preprocess||(D=>D);u.preprocess=(D,l,d)=>l.preprocess(a(Array.isArray(D)?y(!1,D,-1):D),d);}return e.array?ct.create({...t?{preprocess:a=>Array.isArray(a)?a:[a]}:{},...s,valueSchema:i.create(u)}):i.create({...u,...s})}var bn=go;var Bo=(e,t,r)=>{if(!(e&&t==null)){if(t.findLast)return t.findLast(r);for(let n=t.length-1;n>=0;n--){let o=t[n];if(r(o,n,t))return o}}},Kt=Bo;function qt(e,t){if(!t)throw new Error("parserName is required.");let r=Kt(!1,e,o=>o.parsers&&Object.prototype.hasOwnProperty.call(o.parsers,t));if(r)return r;let n=`Couldn't resolve parser "${t}".`;throw n+=" Plugins must be explicitly added to the standalone bundle.",new Pe(n)}function On(e,t){if(!t)throw new Error("astFormat is required.");let r=Kt(!1,e,o=>o.printers&&Object.prototype.hasOwnProperty.call(o.printers,t));if(r)return r;let n=`Couldn't find plugin for AST format "${t}".`;throw n+=" Plugins must be explicitly added to the standalone bundle.",new Pe(n)}function ht({plugins:e,parser:t}){let r=qt(e,t);return Jt(r,t)}function Jt(e,t){let r=e.parsers[t];return typeof r=="function"?r():r}function Sn(e,t){let r=e.printers[t];return typeof r=="function"?r():r}var Nn={astFormat:"estree",printer:{},originalText:void 0,locStart:null,locEnd:null};async function wo(e,t={}){var d;let r={...e};if(!r.parser)if(r.filepath){if(r.parser=un(r,{physicalFile:r.filepath}),!r.parser)throw new Ie(`No parser could be inferred for file "${r.filepath}".`)}else throw new Ie("No parser and no file path given, couldn't infer a parser.");let n=ot({plugins:e.plugins,showDeprecated:!0}).options,o={...Nn,...Object.fromEntries(n.filter(f=>f.default!==void 0).map(f=>[f.name,f.default]))},u=qt(r.plugins,r.parser),i=await Jt(u,r.parser);r.astFormat=i.astFormat,r.locEnd=i.locEnd,r.locStart=i.locStart;let s=(d=u.printers)!=null&&d[i.astFormat]?u:On(r.plugins,i.astFormat),a=await Sn(s,i.astFormat);r.printer=a;let D=s.defaultOptions?Object.fromEntries(Object.entries(s.defaultOptions).filter(([,f])=>f!==void 0)):{},l={...o,...D};for(let[f,p]of Object.entries(l))(r[f]===null||r[f]===void 0)&&(r[f]=p);return r.parser==="json"&&(r.trailingComma="none"),bn(r,n,{passThrough:Object.keys(Nn),...t})}var se=wo;var Vn=Me($n());async function ko(e,t){let r=await ht(t),n=r.preprocess?r.preprocess(e,t):e;t.originalText=n;let o;try{o=await r.parse(n,t,t);}catch(u){Lo(u,e);}return {text:n,ast:o}}function Lo(e,t){let{loc:r}=e;if(r){let n=(0, Vn.codeFrameColumns)(t,r,{highlightCode:!0});throw e.message+=`
`+n,e.codeFrame=n,e}throw e}var ce=ko;async function Un(e,t,r,n,o){let{embeddedLanguageFormatting:u,printer:{embed:i,hasPrettierIgnore:s=()=>!1,getVisitorKeys:a}}=r;if(!i||u!=="auto")return;if(i.length>2)throw new Error("printer.embed has too many parameters. The API changed in Prettier v3. Please update your plugin. See https://prettier.io/docs/en/plugins.html#optional-embed");let D=X(i.getVisitorKeys??a),l=[];p();let d=e.stack;for(let{print:c,node:F,pathStack:m}of l)try{e.stack=m;let E=await c(f,t,e,r);E&&o.set(F,E);}catch(E){if(globalThis.PRETTIER_DEBUG)throw E}e.stack=d;function f(c,F){return Po(c,F,r,n)}function p(){let{node:c}=e;if(c===null||typeof c!="object"||s(e))return;for(let m of D(c))Array.isArray(c[m])?e.each(p,m):e.call(p,m);let F=i(e,r);if(F){if(typeof F=="function"){l.push({print:F,node:c,pathStack:[...e.stack]});return}o.set(c,F);}}}async function Po(e,t,r,n){let o=await se({...r,...t,parentParser:r.parser,originalText:e},{passThrough:!0}),{ast:u}=await ce(e,o),i=await n(u,o);return Ze(i)}function Io(e,t){let{originalText:r,[Symbol.for("comments")]:n,locStart:o,locEnd:u,[Symbol.for("printedComments")]:i}=t,{node:s}=e,a=o(s),D=u(s);for(let l of n)o(l)>=a&&u(l)<=D&&i.add(l);return r.slice(a,D)}var zn=Io;async function Ye(e,t){({ast:e}=await Qt(e,t));let r=new Map,n=new Mr(e),u=new Map;await Un(n,s,t,Ye,u);let i=await Gn(n,t,s,void 0,u);return en(t),i;function s(D,l){return D===void 0||D===n?a(l):Array.isArray(D)?n.call(()=>a(l),...D):n.call(()=>a(l),D)}function a(D){let l=n.node;if(l==null)return "";let d=l&&typeof l=="object"&&D===void 0;if(d&&r.has(l))return r.get(l);let f=Gn(n,t,s,D,u);return d&&r.set(l,f),f}}function Gn(e,t,r,n,o){var a;let{node:u}=e,{printer:i}=t,s;return (a=i.hasPrettierIgnore)!=null&&a.call(i,e)?s=zn(e,t):o.has(u)?s=o.get(u):s=i.print(e,t,r,n),u===t.cursorNode&&(s=Qe(s,D=>[ve,D,ve])),i.printComment&&(!i.willPrintOwnComments||!i.willPrintOwnComments(e,t))&&(s=Qr(e,s,t)),s}async function Qt(e,t){let r=e.comments??[];t[Symbol.for("comments")]=r,t[Symbol.for("tokens")]=e.tokens??[],t[Symbol.for("printedComments")]=new Set,Jr(e,t);let{printer:{preprocess:n}}=t;return e=n?await n(e,t):e,{ast:e,comments:r}}function Ro(e,t){let{cursorOffset:r,locStart:n,locEnd:o}=t,u=X(t.printer.getVisitorKeys),i=a=>n(a)<=r&&o(a)>=r,s=e;for(let a of Ur(e,{getVisitorKeys:u,filter:i}))s=a;return s}var Kn=Ro;function Yo(e,t){let{printer:{massageAstNode:r,getVisitorKeys:n}}=t;if(!r)return e;let o=X(n),u=r.ignoredProperties??new Set;return i(e);function i(s,a){if(!(s!==null&&typeof s=="object"))return s;if(Array.isArray(s))return s.map(f=>i(f,a)).filter(Boolean);let D={},l=new Set(o(s));for(let f in s)!Object.prototype.hasOwnProperty.call(s,f)||u.has(f)||(l.has(f)?D[f]=i(s[f],s):D[f]=s[f]);let d=r(s,D,a);if(d!==null)return d??D}}var qn=Yo;var jo=(e,t,r)=>{if(!(e&&t==null)){if(t.findLastIndex)return t.findLastIndex(r);for(let n=t.length-1;n>=0;n--){let o=t[n];if(r(o,n,t))return n}return -1}},Jn=jo;var Ho=({parser:e})=>e==="json"||e==="json5"||e==="jsonc"||e==="json-stringify";function Wo(e,t){let r=[e.node,...e.parentNodes],n=new Set([t.node,...t.parentNodes]);return r.find(o=>Qn.has(o.type)&&n.has(o))}function Xn(e){let t=Jn(!1,e,r=>r.type!=="Program"&&r.type!=="File");return t===-1?e:e.slice(0,t+1)}function Mo(e,t,{locStart:r,locEnd:n}){let o=e.node,u=t.node;if(o===u)return {startNode:o,endNode:u};let i=r(e.node);for(let a of Xn(t.parentNodes))if(r(a)>=i)u=a;else break;let s=n(t.node);for(let a of Xn(e.parentNodes)){if(n(a)<=s)o=a;else break;if(o===u)break}return {startNode:o,endNode:u}}function er(e,t,r,n,o=[],u){let{locStart:i,locEnd:s}=r,a=i(e),D=s(e);if(!(t>D||t<a||u==="rangeEnd"&&t===a||u==="rangeStart"&&t===D)){for(let l of ut(e,r)){let d=er(l,t,r,n,[e,...o],u);if(d)return d}if(!n||n(e,o[0]))return {node:e,parentNodes:o}}}function $o(e,t){return t!=="DeclareExportDeclaration"&&e!=="TypeParameterDeclaration"&&(e==="Directive"||e==="TypeAlias"||e==="TSExportAssignment"||e.startsWith("Declare")||e.startsWith("TSDeclare")||e.endsWith("Statement")||e.endsWith("Declaration"))}var Qn=new Set(["JsonRoot","ObjectExpression","ArrayExpression","StringLiteral","NumericLiteral","BooleanLiteral","NullLiteral","UnaryExpression","TemplateLiteral"]),Vo=new Set(["OperationDefinition","FragmentDefinition","VariableDefinition","TypeExtensionDefinition","ObjectTypeDefinition","FieldDefinition","DirectiveDefinition","EnumTypeDefinition","EnumValueDefinition","InputValueDefinition","InputObjectTypeDefinition","SchemaDefinition","OperationTypeDefinition","InterfaceTypeDefinition","UnionTypeDefinition","ScalarTypeDefinition"]);function Zn(e,t,r){if(!t)return !1;switch(e.parser){case"flow":case"babel":case"babel-flow":case"babel-ts":case"typescript":case"acorn":case"espree":case"meriyah":case"__babel_estree":return $o(t.type,r==null?void 0:r.type);case"json":case"json5":case"jsonc":case"json-stringify":return Qn.has(t.type);case"graphql":return Vo.has(t.kind);case"vue":return t.tag!=="root"}return !1}function eu(e,t,r){let{rangeStart:n,rangeEnd:o,locStart:u,locEnd:i}=t;ke.ok(o>n);let s=e.slice(n,o).search(/\S/u),a=s===-1;if(!a)for(n+=s;o>n&&!/\S/u.test(e[o-1]);--o);let D=er(r,n,t,(p,c)=>Zn(t,p,c),[],"rangeStart"),l=a?D:er(r,o,t,p=>Zn(t,p),[],"rangeEnd");if(!D||!l)return {rangeStart:0,rangeEnd:0};let d,f;if(Ho(t)){let p=Wo(D,l);d=p,f=p;}else ({startNode:d,endNode:f}=Mo(D,l,t));return {rangeStart:Math.min(u(d),u(f)),rangeEnd:Math.max(i(d),i(f))}}var uu="\uFEFF",tu=Symbol("cursor");async function ou(e,t,r=0){if(!e||e.trim().length===0)return {formatted:"",cursorOffset:-1,comments:[]};let{ast:n,text:o}=await ce(e,t);t.cursorOffset>=0&&(t.cursorNode=Kn(n,t));let u=await Ye(n,t);r>0&&(u=Je([q,u],r,t.tabWidth));let i=Fe(u,t);if(r>0){let a=i.formatted.trim();i.cursorNodeStart!==void 0&&(i.cursorNodeStart-=i.formatted.indexOf(a)),i.formatted=a+Be(t.endOfLine);}let s=t[Symbol.for("comments")];if(t.cursorOffset>=0){let a,D,l,d,f;if(t.cursorNode&&i.cursorNodeText?(a=t.locStart(t.cursorNode),D=o.slice(a,t.locEnd(t.cursorNode)),l=t.cursorOffset-a,d=i.cursorNodeStart,f=i.cursorNodeText):(a=0,D=o,l=t.cursorOffset,d=0,f=i.formatted),D===f)return {formatted:i.formatted,cursorOffset:d+l,comments:s};let p=D.split("");p.splice(l,0,tu);let c=f.split(""),F=dr(p,c),m=d;for(let E of F)if(E.removed){if(E.value.includes(tu))break}else m+=E.count;return {formatted:i.formatted,cursorOffset:m,comments:s}}return {formatted:i.formatted,cursorOffset:-1,comments:s}}async function Uo(e,t){let{ast:r,text:n}=await ce(e,t),{rangeStart:o,rangeEnd:u}=eu(n,t,r),i=n.slice(o,u),s=Math.min(o,n.lastIndexOf(`
`,o)+1),a=n.slice(s,o).match(/^\s*/u)[0],D=me(a,t.tabWidth),l=await ou(i,{...t,rangeStart:0,rangeEnd:Number.POSITIVE_INFINITY,cursorOffset:t.cursorOffset>o&&t.cursorOffset<=u?t.cursorOffset-o:-1,endOfLine:"lf"},D),d=l.formatted.trimEnd(),{cursorOffset:f}=t;f>u?f+=d.length-i.length:l.cursorOffset>=0&&(f=l.cursorOffset+o);let p=n.slice(0,o)+d+n.slice(u);if(t.endOfLine!=="lf"){let c=Be(t.endOfLine);f>=0&&c===`\r
`&&(f+=wt(p.slice(0,f),`
`)),p=ne(!1,p,`
`,c);}return {formatted:p,cursorOffset:f,comments:l.comments}}function tr(e,t,r){return typeof t!="number"||Number.isNaN(t)||t<0||t>e.length?r:t}function ru(e,t){let{cursorOffset:r,rangeStart:n,rangeEnd:o}=t;return r=tr(e,r,-1),n=tr(e,n,0),o=tr(e,o,e.length),{...t,cursorOffset:r,rangeStart:n,rangeEnd:o}}function iu(e,t){let{cursorOffset:r,rangeStart:n,rangeEnd:o,endOfLine:u}=ru(e,t),i=e.charAt(0)===uu;if(i&&(e=e.slice(1),r--,n--,o--),u==="auto"&&(u=Fr(e)),e.includes("\r")){let s=a=>wt(e.slice(0,Math.max(a,0)),`\r
`);r-=s(r),n-=s(n),o-=s(o),e=mr(e);}return {hasBOM:i,text:e,options:ru(e,{...t,cursorOffset:r,rangeStart:n,rangeEnd:o,endOfLine:u})}}async function nu(e,t){let r=await ht(t);return !r.hasPragma||r.hasPragma(e)}async function rr(e,t){let{hasBOM:r,text:n,options:o}=iu(e,await se(t));if(o.rangeStart>=o.rangeEnd&&n!==""||o.requirePragma&&!await nu(n,o))return {formatted:e,cursorOffset:t.cursorOffset,comments:[]};let u;return o.rangeStart>0||o.rangeEnd<n.length?u=await Uo(n,o):(!o.requirePragma&&o.insertPragma&&o.printer.insertPragma&&!await nu(n,o)&&(n=o.printer.insertPragma(n)),u=await ou(n,o)),r&&(u.formatted=uu+u.formatted,u.cursorOffset>=0&&u.cursorOffset++),u}async function su(e,t,r){let{text:n,options:o}=iu(e,await se(t)),u=await ce(n,o);return r&&(r.preprocessForPrint&&(u.ast=await Qt(u.ast,o)),r.massage&&(u.ast=qn(u.ast,o))),u}async function au(e,t){t=await se(t);let r=await Ye(e,t);return Fe(r,t)}async function Du(e,t){let r=Or(e),{formatted:n}=await rr(r,{...t,parser:"__js_expression"});return n}async function lu(e,t){t=await se(t);let{ast:r}=await ce(e,t);return Ye(r,t)}async function cu(e,t){return Fe(e,await se(t))}var nr={};We(nr,{builders:()=>Go,printer:()=>Ko,utils:()=>qo});var Go={join:be,line:Ke,softline:vr,hardline:q,literalline:qe,group:_t,conditionalGroup:Ar,fill:Ge,lineSuffix:xe,lineSuffixBoundary:xr,cursor:ve,breakParent:de,ifBreak:Br,trim:_r,indent:De,indentIfBreak:wr,align:ae,addAlignmentToDoc:Je,markAsRoot:gr,dedentToRoot:Cr,dedent:yr,hardlineWithoutBreakParent:_e,literallineWithoutBreakParent:vt,label:br,concat:e=>e},Ko={printDocToString:Fe},qo={willBreak:Ir,traverseDoc:we,findInDoc:Xe,mapDoc:Ne,removeLines:Yr,stripTrailingHardline:Ze,replaceEndOfLine:jr,canBreak:Hr};var fu="3.3.3";var or={};We(or,{addDanglingComment:()=>re,addLeadingComment:()=>ue,addTrailingComment:()=>oe,getAlignmentSize:()=>me,getIndentSize:()=>pu,getMaxContinuousCount:()=>du,getNextNonSpaceNonCommentCharacter:()=>Fu,getNextNonSpaceNonCommentCharacterIndex:()=>si,getStringWidth:()=>Oe,hasNewline:()=>V,hasNewlineInRange:()=>mu,hasSpaces:()=>Eu,isNextLineEmpty:()=>ci,isNextLineEmptyAfterIndex:()=>gt,isPreviousLineEmpty:()=>Di,makeString:()=>hu,skip:()=>Ee,skipEverythingButNewLine:()=>nt,skipInlineComment:()=>Ce,skipNewline:()=>M,skipSpaces:()=>T,skipToLineEnd:()=>rt,skipTrailingComment:()=>ge,skipWhitespace:()=>zr});function Jo(e,t){if(t===!1)return !1;if(e.charAt(t)==="/"&&e.charAt(t+1)==="*"){for(let r=t+2;r<e.length;++r)if(e.charAt(r)==="*"&&e.charAt(r+1)==="/")return r+2}return t}var Ce=Jo;function Xo(e,t){return t===!1?!1:e.charAt(t)==="/"&&e.charAt(t+1)==="/"?nt(e,t):t}var ge=Xo;function Zo(e,t){let r=null,n=t;for(;n!==r;)r=n,n=T(e,n),n=Ce(e,n),n=ge(e,n),n=M(e,n);return n}var je=Zo;function Qo(e,t){let r=null,n=t;for(;n!==r;)r=n,n=rt(e,n),n=Ce(e,n),n=T(e,n);return n=ge(e,n),n=M(e,n),n!==!1&&V(e,n)}var gt=Qo;function ei(e,t){let r=e.lastIndexOf(`
`);return r===-1?0:me(e.slice(r+1).match(/^[\t ]*/u)[0],t)}var pu=ei;function ur(e){if(typeof e!="string")throw new TypeError("Expected a string");return e.replace(/[|\\{}()[\]^$+*?.]/g,"\\$&").replace(/-/g,"\\x2d")}function ti(e,t){let r=e.match(new RegExp(`(${ur(t)})+`,"gu"));return r===null?0:r.reduce((n,o)=>Math.max(n,o.length/t.length),0)}var du=ti;function ri(e,t){let r=je(e,t);return r===!1?"":e.charAt(r)}var Fu=ri;function ni(e,t,r){for(let n=t;n<r;++n)if(e.charAt(n)===`
`)return !0;return !1}var mu=ni;function ui(e,t,r={}){return T(e,r.backwards?t-1:t,r)!==t}var Eu=ui;function oi(e,t,r){let n=t==='"'?"'":'"',u=ne(!1,e,/\\(.)|(["'])/gsu,(i,s,a)=>s===n?s:a===t?"\\"+a:a||(r&&/^[^\n\r"'0-7\\bfnrt-vx\u2028\u2029]$/u.test(s)?s:"\\"+s));return t+u+t}var hu=oi;function ii(e,t,r){return je(e,r(t))}function si(e,t){return arguments.length===2||typeof t=="number"?je(e,t):ii(...arguments)}function ai(e,t,r){return Le(e,r(t))}function Di(e,t){return arguments.length===2||typeof t=="number"?Le(e,t):ai(...arguments)}function li(e,t,r){return gt(e,r(t))}function ci(e,t){return arguments.length===2||typeof t=="number"?gt(e,t):li(...arguments)}function fe(e,t=1){return async(...r)=>{let n=r[t]??{},o=n.plugins??[];return r[t]={...n,plugins:Array.isArray(o)?o:Object.values(o)},e(...r)}}var Cu=fe(rr);async function gu(e,t){let{formatted:r}=await Cu(e,{...t,cursorOffset:-1});return r}async function fi(e,t){return await gu(e,t)===e}var pi=fe(ot,0),di={parse:fe(su),formatAST:fe(au),formatDoc:fe(Du),printToDoc:fe(lu),printDocToString:fe(cu)};

var __defProp = Object.defineProperty;
var __export = (target, all) => {
  for (var name in all)
    __defProp(target, name, { get: all[name], enumerable: true });
};

// src/document/public.js
var public_exports = {};
__export(public_exports, {
  builders: () => builders,
  printer: () => printer,
  utils: () => utils
});

// src/document/constants.js
var DOC_TYPE_STRING = "string";
var DOC_TYPE_ARRAY = "array";
var DOC_TYPE_CURSOR = "cursor";
var DOC_TYPE_INDENT = "indent";
var DOC_TYPE_ALIGN = "align";
var DOC_TYPE_TRIM = "trim";
var DOC_TYPE_GROUP = "group";
var DOC_TYPE_FILL = "fill";
var DOC_TYPE_IF_BREAK = "if-break";
var DOC_TYPE_INDENT_IF_BREAK = "indent-if-break";
var DOC_TYPE_LINE_SUFFIX = "line-suffix";
var DOC_TYPE_LINE_SUFFIX_BOUNDARY = "line-suffix-boundary";
var DOC_TYPE_LINE = "line";
var DOC_TYPE_LABEL = "label";
var DOC_TYPE_BREAK_PARENT = "break-parent";
var VALID_OBJECT_DOC_TYPES = /* @__PURE__ */ new Set([
  DOC_TYPE_CURSOR,
  DOC_TYPE_INDENT,
  DOC_TYPE_ALIGN,
  DOC_TYPE_TRIM,
  DOC_TYPE_GROUP,
  DOC_TYPE_FILL,
  DOC_TYPE_IF_BREAK,
  DOC_TYPE_INDENT_IF_BREAK,
  DOC_TYPE_LINE_SUFFIX,
  DOC_TYPE_LINE_SUFFIX_BOUNDARY,
  DOC_TYPE_LINE,
  DOC_TYPE_LABEL,
  DOC_TYPE_BREAK_PARENT
]);

// src/document/utils/get-doc-type.js
function getDocType(doc) {
  if (typeof doc === "string") {
    return DOC_TYPE_STRING;
  }
  if (Array.isArray(doc)) {
    return DOC_TYPE_ARRAY;
  }
  if (!doc) {
    return;
  }
  const { type } = doc;
  if (VALID_OBJECT_DOC_TYPES.has(type)) {
    return type;
  }
}
var get_doc_type_default = getDocType;

// src/document/invalid-doc-error.js
var disjunctionListFormat = (list) => new Intl.ListFormat("en-US", { type: "disjunction" }).format(list);
function getDocErrorMessage(doc) {
  const type = doc === null ? "null" : typeof doc;
  if (type !== "string" && type !== "object") {
    return `Unexpected doc '${type}', 
Expected it to be 'string' or 'object'.`;
  }
  if (get_doc_type_default(doc)) {
    throw new Error("doc is valid.");
  }
  const objectType = Object.prototype.toString.call(doc);
  if (objectType !== "[object Object]") {
    return `Unexpected doc '${objectType}'.`;
  }
  const EXPECTED_TYPE_VALUES = disjunctionListFormat(
    [...VALID_OBJECT_DOC_TYPES].map((type2) => `'${type2}'`)
  );
  return `Unexpected doc.type '${doc.type}'.
Expected it to be ${EXPECTED_TYPE_VALUES}.`;
}
var InvalidDocError = class extends Error {
  name = "InvalidDocError";
  constructor(doc) {
    super(getDocErrorMessage(doc));
    this.doc = doc;
  }
};
var invalid_doc_error_default = InvalidDocError;

// src/document/utils/traverse-doc.js
var traverseDocOnExitStackMarker = {};
function traverseDoc(doc, onEnter, onExit, shouldTraverseConditionalGroups) {
  const docsStack = [doc];
  while (docsStack.length > 0) {
    const doc2 = docsStack.pop();
    if (doc2 === traverseDocOnExitStackMarker) {
      onExit(docsStack.pop());
      continue;
    }
    if (onExit) {
      docsStack.push(doc2, traverseDocOnExitStackMarker);
    }
    const docType = get_doc_type_default(doc2);
    if (!docType) {
      throw new invalid_doc_error_default(doc2);
    }
    if ((onEnter == null ? void 0 : onEnter(doc2)) === false) {
      continue;
    }
    switch (docType) {
      case DOC_TYPE_ARRAY:
      case DOC_TYPE_FILL: {
        const parts = docType === DOC_TYPE_ARRAY ? doc2 : doc2.parts;
        for (let ic = parts.length, i = ic - 1; i >= 0; --i) {
          docsStack.push(parts[i]);
        }
        break;
      }
      case DOC_TYPE_IF_BREAK:
        docsStack.push(doc2.flatContents, doc2.breakContents);
        break;
      case DOC_TYPE_GROUP:
        if (shouldTraverseConditionalGroups && doc2.expandedStates) {
          for (let ic = doc2.expandedStates.length, i = ic - 1; i >= 0; --i) {
            docsStack.push(doc2.expandedStates[i]);
          }
        } else {
          docsStack.push(doc2.contents);
        }
        break;
      case DOC_TYPE_ALIGN:
      case DOC_TYPE_INDENT:
      case DOC_TYPE_INDENT_IF_BREAK:
      case DOC_TYPE_LABEL:
      case DOC_TYPE_LINE_SUFFIX:
        docsStack.push(doc2.contents);
        break;
      case DOC_TYPE_STRING:
      case DOC_TYPE_CURSOR:
      case DOC_TYPE_TRIM:
      case DOC_TYPE_LINE_SUFFIX_BOUNDARY:
      case DOC_TYPE_LINE:
      case DOC_TYPE_BREAK_PARENT:
        break;
      default:
        throw new invalid_doc_error_default(doc2);
    }
  }
}
var traverse_doc_default = traverseDoc;

// src/document/utils/assert-doc.js
var noop = () => {
};
var assertDocArray = noop ;

// src/document/builders.js
function indent$1(contents) {
  return { type: DOC_TYPE_INDENT, contents };
}
function align$1(widthOrString, contents) {
  return { type: DOC_TYPE_ALIGN, contents, n: widthOrString };
}
function group$1(contents, opts = {}) {
  assertDocArray(
    opts.expandedStates);
  return {
    type: DOC_TYPE_GROUP,
    id: opts.id,
    contents,
    break: Boolean(opts.shouldBreak),
    expandedStates: opts.expandedStates
  };
}
function dedentToRoot(contents) {
  return align$1(Number.NEGATIVE_INFINITY, contents);
}
function markAsRoot$1(contents) {
  return align$1({ type: "root" }, contents);
}
function dedent(contents) {
  return align$1(-1, contents);
}
function conditionalGroup(states, opts) {
  return group$1(states[0], { ...opts, expandedStates: states });
}
function fill(parts) {
  return { type: DOC_TYPE_FILL, parts };
}
function ifBreak$1(breakContents, flatContents = "", opts = {}) {
  return {
    type: DOC_TYPE_IF_BREAK,
    breakContents,
    flatContents,
    groupId: opts.groupId
  };
}
function indentIfBreak(contents, opts) {
  return {
    type: DOC_TYPE_INDENT_IF_BREAK,
    contents,
    groupId: opts.groupId,
    negate: opts.negate
  };
}
function lineSuffix(contents) {
  return { type: DOC_TYPE_LINE_SUFFIX, contents };
}
var lineSuffixBoundary = { type: DOC_TYPE_LINE_SUFFIX_BOUNDARY };
var breakParent$1 = { type: DOC_TYPE_BREAK_PARENT };
var trim = { type: DOC_TYPE_TRIM };
var hardlineWithoutBreakParent = { type: DOC_TYPE_LINE, hard: true };
var literallineWithoutBreakParent = {
  type: DOC_TYPE_LINE,
  hard: true,
  literal: true
};
var line$1 = { type: DOC_TYPE_LINE };
var softline$1 = { type: DOC_TYPE_LINE, soft: true };
var hardline$1 = [hardlineWithoutBreakParent, breakParent$1];
var literalline$1 = [literallineWithoutBreakParent, breakParent$1];
var cursor = { type: DOC_TYPE_CURSOR };
function join$1(separator, docs) {
  const parts = [];
  for (let i = 0; i < docs.length; i++) {
    if (i !== 0) {
      parts.push(separator);
    }
    parts.push(docs[i]);
  }
  return parts;
}
function addAlignmentToDoc(doc, size, tabWidth) {
  let aligned = doc;
  if (size > 0) {
    for (let i = 0; i < Math.floor(size / tabWidth); ++i) {
      aligned = indent$1(aligned);
    }
    aligned = align$1(size % tabWidth, aligned);
    aligned = align$1(Number.NEGATIVE_INFINITY, aligned);
  }
  return aligned;
}
function label(label2, contents) {
  return label2 ? { type: DOC_TYPE_LABEL, label: label2, contents } : contents;
}

// scripts/build/shims/at.js
var at = (isOptionalObject, object, index) => {
  if (isOptionalObject && (object === void 0 || object === null)) {
    return;
  }
  if (Array.isArray(object) || typeof object === "string") {
    return object[index < 0 ? object.length + index : index];
  }
  return object.at(index);
};
var at_default = at;

// scripts/build/shims/string-replace-all.js
var stringReplaceAll = (isOptionalObject, original, pattern, replacement) => {
  if (isOptionalObject && (original === void 0 || original === null)) {
    return;
  }
  if (original.replaceAll) {
    return original.replaceAll(pattern, replacement);
  }
  if (pattern.global) {
    return original.replace(pattern, replacement);
  }
  return original.split(pattern).join(replacement);
};
var string_replace_all_default = stringReplaceAll;

// src/common/end-of-line.js
function convertEndOfLineToChars(value) {
  switch (value) {
    case "cr":
      return "\r";
    case "crlf":
      return "\r\n";
    default:
      return "\n";
  }
}

// node_modules/emoji-regex/index.mjs
var emoji_regex_default = () => {
  return /[#*0-9]\uFE0F?\u20E3|[\xA9\xAE\u203C\u2049\u2122\u2139\u2194-\u2199\u21A9\u21AA\u231A\u231B\u2328\u23CF\u23ED-\u23EF\u23F1\u23F2\u23F8-\u23FA\u24C2\u25AA\u25AB\u25B6\u25C0\u25FB\u25FC\u25FE\u2600-\u2604\u260E\u2611\u2614\u2615\u2618\u2620\u2622\u2623\u2626\u262A\u262E\u262F\u2638-\u263A\u2640\u2642\u2648-\u2653\u265F\u2660\u2663\u2665\u2666\u2668\u267B\u267E\u267F\u2692\u2694-\u2697\u2699\u269B\u269C\u26A0\u26A7\u26AA\u26B0\u26B1\u26BD\u26BE\u26C4\u26C8\u26CF\u26D1\u26E9\u26F0-\u26F5\u26F7\u26F8\u26FA\u2702\u2708\u2709\u270F\u2712\u2714\u2716\u271D\u2721\u2733\u2734\u2744\u2747\u2757\u2763\u27A1\u2934\u2935\u2B05-\u2B07\u2B1B\u2B1C\u2B55\u3030\u303D\u3297\u3299]\uFE0F?|[\u261D\u270C\u270D](?:\uFE0F|\uD83C[\uDFFB-\uDFFF])?|[\u270A\u270B](?:\uD83C[\uDFFB-\uDFFF])?|[\u23E9-\u23EC\u23F0\u23F3\u25FD\u2693\u26A1\u26AB\u26C5\u26CE\u26D4\u26EA\u26FD\u2705\u2728\u274C\u274E\u2753-\u2755\u2795-\u2797\u27B0\u27BF\u2B50]|\u26D3\uFE0F?(?:\u200D\uD83D\uDCA5)?|\u26F9(?:\uFE0F|\uD83C[\uDFFB-\uDFFF])?(?:\u200D[\u2640\u2642]\uFE0F?)?|\u2764\uFE0F?(?:\u200D(?:\uD83D\uDD25|\uD83E\uDE79))?|\uD83C(?:[\uDC04\uDD70\uDD71\uDD7E\uDD7F\uDE02\uDE37\uDF21\uDF24-\uDF2C\uDF36\uDF7D\uDF96\uDF97\uDF99-\uDF9B\uDF9E\uDF9F\uDFCD\uDFCE\uDFD4-\uDFDF\uDFF5\uDFF7]\uFE0F?|[\uDF85\uDFC2\uDFC7](?:\uD83C[\uDFFB-\uDFFF])?|[\uDFC4\uDFCA](?:\uD83C[\uDFFB-\uDFFF])?(?:\u200D[\u2640\u2642]\uFE0F?)?|[\uDFCB\uDFCC](?:\uFE0F|\uD83C[\uDFFB-\uDFFF])?(?:\u200D[\u2640\u2642]\uFE0F?)?|[\uDCCF\uDD8E\uDD91-\uDD9A\uDE01\uDE1A\uDE2F\uDE32-\uDE36\uDE38-\uDE3A\uDE50\uDE51\uDF00-\uDF20\uDF2D-\uDF35\uDF37-\uDF43\uDF45-\uDF4A\uDF4C-\uDF7C\uDF7E-\uDF84\uDF86-\uDF93\uDFA0-\uDFC1\uDFC5\uDFC6\uDFC8\uDFC9\uDFCF-\uDFD3\uDFE0-\uDFF0\uDFF8-\uDFFF]|\uDDE6\uD83C[\uDDE8-\uDDEC\uDDEE\uDDF1\uDDF2\uDDF4\uDDF6-\uDDFA\uDDFC\uDDFD\uDDFF]|\uDDE7\uD83C[\uDDE6\uDDE7\uDDE9-\uDDEF\uDDF1-\uDDF4\uDDF6-\uDDF9\uDDFB\uDDFC\uDDFE\uDDFF]|\uDDE8\uD83C[\uDDE6\uDDE8\uDDE9\uDDEB-\uDDEE\uDDF0-\uDDF5\uDDF7\uDDFA-\uDDFF]|\uDDE9\uD83C[\uDDEA\uDDEC\uDDEF\uDDF0\uDDF2\uDDF4\uDDFF]|\uDDEA\uD83C[\uDDE6\uDDE8\uDDEA\uDDEC\uDDED\uDDF7-\uDDFA]|\uDDEB\uD83C[\uDDEE-\uDDF0\uDDF2\uDDF4\uDDF7]|\uDDEC\uD83C[\uDDE6\uDDE7\uDDE9-\uDDEE\uDDF1-\uDDF3\uDDF5-\uDDFA\uDDFC\uDDFE]|\uDDED\uD83C[\uDDF0\uDDF2\uDDF3\uDDF7\uDDF9\uDDFA]|\uDDEE\uD83C[\uDDE8-\uDDEA\uDDF1-\uDDF4\uDDF6-\uDDF9]|\uDDEF\uD83C[\uDDEA\uDDF2\uDDF4\uDDF5]|\uDDF0\uD83C[\uDDEA\uDDEC-\uDDEE\uDDF2\uDDF3\uDDF5\uDDF7\uDDFC\uDDFE\uDDFF]|\uDDF1\uD83C[\uDDE6-\uDDE8\uDDEE\uDDF0\uDDF7-\uDDFB\uDDFE]|\uDDF2\uD83C[\uDDE6\uDDE8-\uDDED\uDDF0-\uDDFF]|\uDDF3\uD83C[\uDDE6\uDDE8\uDDEA-\uDDEC\uDDEE\uDDF1\uDDF4\uDDF5\uDDF7\uDDFA\uDDFF]|\uDDF4\uD83C\uDDF2|\uDDF5\uD83C[\uDDE6\uDDEA-\uDDED\uDDF0-\uDDF3\uDDF7-\uDDF9\uDDFC\uDDFE]|\uDDF6\uD83C\uDDE6|\uDDF7\uD83C[\uDDEA\uDDF4\uDDF8\uDDFA\uDDFC]|\uDDF8\uD83C[\uDDE6-\uDDEA\uDDEC-\uDDF4\uDDF7-\uDDF9\uDDFB\uDDFD-\uDDFF]|\uDDF9\uD83C[\uDDE6\uDDE8\uDDE9\uDDEB-\uDDED\uDDEF-\uDDF4\uDDF7\uDDF9\uDDFB\uDDFC\uDDFF]|\uDDFA\uD83C[\uDDE6\uDDEC\uDDF2\uDDF3\uDDF8\uDDFE\uDDFF]|\uDDFB\uD83C[\uDDE6\uDDE8\uDDEA\uDDEC\uDDEE\uDDF3\uDDFA]|\uDDFC\uD83C[\uDDEB\uDDF8]|\uDDFD\uD83C\uDDF0|\uDDFE\uD83C[\uDDEA\uDDF9]|\uDDFF\uD83C[\uDDE6\uDDF2\uDDFC]|\uDF44(?:\u200D\uD83D\uDFEB)?|\uDF4B(?:\u200D\uD83D\uDFE9)?|\uDFC3(?:\uD83C[\uDFFB-\uDFFF])?(?:\u200D(?:[\u2640\u2642]\uFE0F?(?:\u200D\u27A1\uFE0F?)?|\u27A1\uFE0F?))?|\uDFF3\uFE0F?(?:\u200D(?:\u26A7\uFE0F?|\uD83C\uDF08))?|\uDFF4(?:\u200D\u2620\uFE0F?|\uDB40\uDC67\uDB40\uDC62\uDB40(?:\uDC65\uDB40\uDC6E\uDB40\uDC67|\uDC73\uDB40\uDC63\uDB40\uDC74|\uDC77\uDB40\uDC6C\uDB40\uDC73)\uDB40\uDC7F)?)|\uD83D(?:[\uDC3F\uDCFD\uDD49\uDD4A\uDD6F\uDD70\uDD73\uDD76-\uDD79\uDD87\uDD8A-\uDD8D\uDDA5\uDDA8\uDDB1\uDDB2\uDDBC\uDDC2-\uDDC4\uDDD1-\uDDD3\uDDDC-\uDDDE\uDDE1\uDDE3\uDDE8\uDDEF\uDDF3\uDDFA\uDECB\uDECD-\uDECF\uDEE0-\uDEE5\uDEE9\uDEF0\uDEF3]\uFE0F?|[\uDC42\uDC43\uDC46-\uDC50\uDC66\uDC67\uDC6B-\uDC6D\uDC72\uDC74-\uDC76\uDC78\uDC7C\uDC83\uDC85\uDC8F\uDC91\uDCAA\uDD7A\uDD95\uDD96\uDE4C\uDE4F\uDEC0\uDECC](?:\uD83C[\uDFFB-\uDFFF])?|[\uDC6E\uDC70\uDC71\uDC73\uDC77\uDC81\uDC82\uDC86\uDC87\uDE45-\uDE47\uDE4B\uDE4D\uDE4E\uDEA3\uDEB4\uDEB5](?:\uD83C[\uDFFB-\uDFFF])?(?:\u200D[\u2640\u2642]\uFE0F?)?|[\uDD74\uDD90](?:\uFE0F|\uD83C[\uDFFB-\uDFFF])?|[\uDC00-\uDC07\uDC09-\uDC14\uDC16-\uDC25\uDC27-\uDC3A\uDC3C-\uDC3E\uDC40\uDC44\uDC45\uDC51-\uDC65\uDC6A\uDC79-\uDC7B\uDC7D-\uDC80\uDC84\uDC88-\uDC8E\uDC90\uDC92-\uDCA9\uDCAB-\uDCFC\uDCFF-\uDD3D\uDD4B-\uDD4E\uDD50-\uDD67\uDDA4\uDDFB-\uDE2D\uDE2F-\uDE34\uDE37-\uDE41\uDE43\uDE44\uDE48-\uDE4A\uDE80-\uDEA2\uDEA4-\uDEB3\uDEB7-\uDEBF\uDEC1-\uDEC5\uDED0-\uDED2\uDED5-\uDED7\uDEDC-\uDEDF\uDEEB\uDEEC\uDEF4-\uDEFC\uDFE0-\uDFEB\uDFF0]|\uDC08(?:\u200D\u2B1B)?|\uDC15(?:\u200D\uD83E\uDDBA)?|\uDC26(?:\u200D(?:\u2B1B|\uD83D\uDD25))?|\uDC3B(?:\u200D\u2744\uFE0F?)?|\uDC41\uFE0F?(?:\u200D\uD83D\uDDE8\uFE0F?)?|\uDC68(?:\u200D(?:[\u2695\u2696\u2708]\uFE0F?|\u2764\uFE0F?\u200D\uD83D(?:\uDC8B\u200D\uD83D)?\uDC68|\uD83C[\uDF3E\uDF73\uDF7C\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D(?:[\uDC68\uDC69]\u200D\uD83D(?:\uDC66(?:\u200D\uD83D\uDC66)?|\uDC67(?:\u200D\uD83D[\uDC66\uDC67])?)|[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uDC66(?:\u200D\uD83D\uDC66)?|\uDC67(?:\u200D\uD83D[\uDC66\uDC67])?)|\uD83E(?:[\uDDAF\uDDBC\uDDBD](?:\u200D\u27A1\uFE0F?)?|[\uDDB0-\uDDB3]))|\uD83C(?:\uDFFB(?:\u200D(?:[\u2695\u2696\u2708]\uFE0F?|\u2764\uFE0F?\u200D\uD83D(?:\uDC8B\u200D\uD83D)?\uDC68\uD83C[\uDFFB-\uDFFF]|\uD83C[\uDF3E\uDF73\uDF7C\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E(?:[\uDDAF\uDDBC\uDDBD](?:\u200D\u27A1\uFE0F?)?|[\uDDB0-\uDDB3]|\uDD1D\u200D\uD83D\uDC68\uD83C[\uDFFC-\uDFFF])))?|\uDFFC(?:\u200D(?:[\u2695\u2696\u2708]\uFE0F?|\u2764\uFE0F?\u200D\uD83D(?:\uDC8B\u200D\uD83D)?\uDC68\uD83C[\uDFFB-\uDFFF]|\uD83C[\uDF3E\uDF73\uDF7C\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E(?:[\uDDAF\uDDBC\uDDBD](?:\u200D\u27A1\uFE0F?)?|[\uDDB0-\uDDB3]|\uDD1D\u200D\uD83D\uDC68\uD83C[\uDFFB\uDFFD-\uDFFF])))?|\uDFFD(?:\u200D(?:[\u2695\u2696\u2708]\uFE0F?|\u2764\uFE0F?\u200D\uD83D(?:\uDC8B\u200D\uD83D)?\uDC68\uD83C[\uDFFB-\uDFFF]|\uD83C[\uDF3E\uDF73\uDF7C\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E(?:[\uDDAF\uDDBC\uDDBD](?:\u200D\u27A1\uFE0F?)?|[\uDDB0-\uDDB3]|\uDD1D\u200D\uD83D\uDC68\uD83C[\uDFFB\uDFFC\uDFFE\uDFFF])))?|\uDFFE(?:\u200D(?:[\u2695\u2696\u2708]\uFE0F?|\u2764\uFE0F?\u200D\uD83D(?:\uDC8B\u200D\uD83D)?\uDC68\uD83C[\uDFFB-\uDFFF]|\uD83C[\uDF3E\uDF73\uDF7C\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E(?:[\uDDAF\uDDBC\uDDBD](?:\u200D\u27A1\uFE0F?)?|[\uDDB0-\uDDB3]|\uDD1D\u200D\uD83D\uDC68\uD83C[\uDFFB-\uDFFD\uDFFF])))?|\uDFFF(?:\u200D(?:[\u2695\u2696\u2708]\uFE0F?|\u2764\uFE0F?\u200D\uD83D(?:\uDC8B\u200D\uD83D)?\uDC68\uD83C[\uDFFB-\uDFFF]|\uD83C[\uDF3E\uDF73\uDF7C\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E(?:[\uDDAF\uDDBC\uDDBD](?:\u200D\u27A1\uFE0F?)?|[\uDDB0-\uDDB3]|\uDD1D\u200D\uD83D\uDC68\uD83C[\uDFFB-\uDFFE])))?))?|\uDC69(?:\u200D(?:[\u2695\u2696\u2708]\uFE0F?|\u2764\uFE0F?\u200D\uD83D(?:\uDC8B\u200D\uD83D)?[\uDC68\uDC69]|\uD83C[\uDF3E\uDF73\uDF7C\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D(?:[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uDC66(?:\u200D\uD83D\uDC66)?|\uDC67(?:\u200D\uD83D[\uDC66\uDC67])?|\uDC69\u200D\uD83D(?:\uDC66(?:\u200D\uD83D\uDC66)?|\uDC67(?:\u200D\uD83D[\uDC66\uDC67])?))|\uD83E(?:[\uDDAF\uDDBC\uDDBD](?:\u200D\u27A1\uFE0F?)?|[\uDDB0-\uDDB3]))|\uD83C(?:\uDFFB(?:\u200D(?:[\u2695\u2696\u2708]\uFE0F?|\u2764\uFE0F?\u200D\uD83D(?:[\uDC68\uDC69]|\uDC8B\u200D\uD83D[\uDC68\uDC69])\uD83C[\uDFFB-\uDFFF]|\uD83C[\uDF3E\uDF73\uDF7C\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E(?:[\uDDAF\uDDBC\uDDBD](?:\u200D\u27A1\uFE0F?)?|[\uDDB0-\uDDB3]|\uDD1D\u200D\uD83D[\uDC68\uDC69]\uD83C[\uDFFC-\uDFFF])))?|\uDFFC(?:\u200D(?:[\u2695\u2696\u2708]\uFE0F?|\u2764\uFE0F?\u200D\uD83D(?:[\uDC68\uDC69]|\uDC8B\u200D\uD83D[\uDC68\uDC69])\uD83C[\uDFFB-\uDFFF]|\uD83C[\uDF3E\uDF73\uDF7C\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E(?:[\uDDAF\uDDBC\uDDBD](?:\u200D\u27A1\uFE0F?)?|[\uDDB0-\uDDB3]|\uDD1D\u200D\uD83D[\uDC68\uDC69]\uD83C[\uDFFB\uDFFD-\uDFFF])))?|\uDFFD(?:\u200D(?:[\u2695\u2696\u2708]\uFE0F?|\u2764\uFE0F?\u200D\uD83D(?:[\uDC68\uDC69]|\uDC8B\u200D\uD83D[\uDC68\uDC69])\uD83C[\uDFFB-\uDFFF]|\uD83C[\uDF3E\uDF73\uDF7C\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E(?:[\uDDAF\uDDBC\uDDBD](?:\u200D\u27A1\uFE0F?)?|[\uDDB0-\uDDB3]|\uDD1D\u200D\uD83D[\uDC68\uDC69]\uD83C[\uDFFB\uDFFC\uDFFE\uDFFF])))?|\uDFFE(?:\u200D(?:[\u2695\u2696\u2708]\uFE0F?|\u2764\uFE0F?\u200D\uD83D(?:[\uDC68\uDC69]|\uDC8B\u200D\uD83D[\uDC68\uDC69])\uD83C[\uDFFB-\uDFFF]|\uD83C[\uDF3E\uDF73\uDF7C\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E(?:[\uDDAF\uDDBC\uDDBD](?:\u200D\u27A1\uFE0F?)?|[\uDDB0-\uDDB3]|\uDD1D\u200D\uD83D[\uDC68\uDC69]\uD83C[\uDFFB-\uDFFD\uDFFF])))?|\uDFFF(?:\u200D(?:[\u2695\u2696\u2708]\uFE0F?|\u2764\uFE0F?\u200D\uD83D(?:[\uDC68\uDC69]|\uDC8B\u200D\uD83D[\uDC68\uDC69])\uD83C[\uDFFB-\uDFFF]|\uD83C[\uDF3E\uDF73\uDF7C\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E(?:[\uDDAF\uDDBC\uDDBD](?:\u200D\u27A1\uFE0F?)?|[\uDDB0-\uDDB3]|\uDD1D\u200D\uD83D[\uDC68\uDC69]\uD83C[\uDFFB-\uDFFE])))?))?|\uDC6F(?:\u200D[\u2640\u2642]\uFE0F?)?|\uDD75(?:\uFE0F|\uD83C[\uDFFB-\uDFFF])?(?:\u200D[\u2640\u2642]\uFE0F?)?|\uDE2E(?:\u200D\uD83D\uDCA8)?|\uDE35(?:\u200D\uD83D\uDCAB)?|\uDE36(?:\u200D\uD83C\uDF2B\uFE0F?)?|\uDE42(?:\u200D[\u2194\u2195]\uFE0F?)?|\uDEB6(?:\uD83C[\uDFFB-\uDFFF])?(?:\u200D(?:[\u2640\u2642]\uFE0F?(?:\u200D\u27A1\uFE0F?)?|\u27A1\uFE0F?))?)|\uD83E(?:[\uDD0C\uDD0F\uDD18-\uDD1F\uDD30-\uDD34\uDD36\uDD77\uDDB5\uDDB6\uDDBB\uDDD2\uDDD3\uDDD5\uDEC3-\uDEC5\uDEF0\uDEF2-\uDEF8](?:\uD83C[\uDFFB-\uDFFF])?|[\uDD26\uDD35\uDD37-\uDD39\uDD3D\uDD3E\uDDB8\uDDB9\uDDCD\uDDCF\uDDD4\uDDD6-\uDDDD](?:\uD83C[\uDFFB-\uDFFF])?(?:\u200D[\u2640\u2642]\uFE0F?)?|[\uDDDE\uDDDF](?:\u200D[\u2640\u2642]\uFE0F?)?|[\uDD0D\uDD0E\uDD10-\uDD17\uDD20-\uDD25\uDD27-\uDD2F\uDD3A\uDD3F-\uDD45\uDD47-\uDD76\uDD78-\uDDB4\uDDB7\uDDBA\uDDBC-\uDDCC\uDDD0\uDDE0-\uDDFF\uDE70-\uDE7C\uDE80-\uDE88\uDE90-\uDEBD\uDEBF-\uDEC2\uDECE-\uDEDB\uDEE0-\uDEE8]|\uDD3C(?:\u200D[\u2640\u2642]\uFE0F?|\uD83C[\uDFFB-\uDFFF])?|\uDDCE(?:\uD83C[\uDFFB-\uDFFF])?(?:\u200D(?:[\u2640\u2642]\uFE0F?(?:\u200D\u27A1\uFE0F?)?|\u27A1\uFE0F?))?|\uDDD1(?:\u200D(?:[\u2695\u2696\u2708]\uFE0F?|\uD83C[\uDF3E\uDF73\uDF7C\uDF84\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E(?:[\uDDAF\uDDBC\uDDBD](?:\u200D\u27A1\uFE0F?)?|[\uDDB0-\uDDB3]|\uDD1D\u200D\uD83E\uDDD1|\uDDD1\u200D\uD83E\uDDD2(?:\u200D\uD83E\uDDD2)?|\uDDD2(?:\u200D\uD83E\uDDD2)?))|\uD83C(?:\uDFFB(?:\u200D(?:[\u2695\u2696\u2708]\uFE0F?|\u2764\uFE0F?\u200D(?:\uD83D\uDC8B\u200D)?\uD83E\uDDD1\uD83C[\uDFFC-\uDFFF]|\uD83C[\uDF3E\uDF73\uDF7C\uDF84\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E(?:[\uDDAF\uDDBC\uDDBD](?:\u200D\u27A1\uFE0F?)?|[\uDDB0-\uDDB3]|\uDD1D\u200D\uD83E\uDDD1\uD83C[\uDFFB-\uDFFF])))?|\uDFFC(?:\u200D(?:[\u2695\u2696\u2708]\uFE0F?|\u2764\uFE0F?\u200D(?:\uD83D\uDC8B\u200D)?\uD83E\uDDD1\uD83C[\uDFFB\uDFFD-\uDFFF]|\uD83C[\uDF3E\uDF73\uDF7C\uDF84\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E(?:[\uDDAF\uDDBC\uDDBD](?:\u200D\u27A1\uFE0F?)?|[\uDDB0-\uDDB3]|\uDD1D\u200D\uD83E\uDDD1\uD83C[\uDFFB-\uDFFF])))?|\uDFFD(?:\u200D(?:[\u2695\u2696\u2708]\uFE0F?|\u2764\uFE0F?\u200D(?:\uD83D\uDC8B\u200D)?\uD83E\uDDD1\uD83C[\uDFFB\uDFFC\uDFFE\uDFFF]|\uD83C[\uDF3E\uDF73\uDF7C\uDF84\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E(?:[\uDDAF\uDDBC\uDDBD](?:\u200D\u27A1\uFE0F?)?|[\uDDB0-\uDDB3]|\uDD1D\u200D\uD83E\uDDD1\uD83C[\uDFFB-\uDFFF])))?|\uDFFE(?:\u200D(?:[\u2695\u2696\u2708]\uFE0F?|\u2764\uFE0F?\u200D(?:\uD83D\uDC8B\u200D)?\uD83E\uDDD1\uD83C[\uDFFB-\uDFFD\uDFFF]|\uD83C[\uDF3E\uDF73\uDF7C\uDF84\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E(?:[\uDDAF\uDDBC\uDDBD](?:\u200D\u27A1\uFE0F?)?|[\uDDB0-\uDDB3]|\uDD1D\u200D\uD83E\uDDD1\uD83C[\uDFFB-\uDFFF])))?|\uDFFF(?:\u200D(?:[\u2695\u2696\u2708]\uFE0F?|\u2764\uFE0F?\u200D(?:\uD83D\uDC8B\u200D)?\uD83E\uDDD1\uD83C[\uDFFB-\uDFFE]|\uD83C[\uDF3E\uDF73\uDF7C\uDF84\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E(?:[\uDDAF\uDDBC\uDDBD](?:\u200D\u27A1\uFE0F?)?|[\uDDB0-\uDDB3]|\uDD1D\u200D\uD83E\uDDD1\uD83C[\uDFFB-\uDFFF])))?))?|\uDEF1(?:\uD83C(?:\uDFFB(?:\u200D\uD83E\uDEF2\uD83C[\uDFFC-\uDFFF])?|\uDFFC(?:\u200D\uD83E\uDEF2\uD83C[\uDFFB\uDFFD-\uDFFF])?|\uDFFD(?:\u200D\uD83E\uDEF2\uD83C[\uDFFB\uDFFC\uDFFE\uDFFF])?|\uDFFE(?:\u200D\uD83E\uDEF2\uD83C[\uDFFB-\uDFFD\uDFFF])?|\uDFFF(?:\u200D\uD83E\uDEF2\uD83C[\uDFFB-\uDFFE])?))?)/g;
};

// node_modules/get-east-asian-width/lookup.js
function isFullWidth(x) {
  return x === 12288 || x >= 65281 && x <= 65376 || x >= 65504 && x <= 65510;
}
function isWide(x) {
  return x >= 4352 && x <= 4447 || x === 8986 || x === 8987 || x === 9001 || x === 9002 || x >= 9193 && x <= 9196 || x === 9200 || x === 9203 || x === 9725 || x === 9726 || x === 9748 || x === 9749 || x >= 9800 && x <= 9811 || x === 9855 || x === 9875 || x === 9889 || x === 9898 || x === 9899 || x === 9917 || x === 9918 || x === 9924 || x === 9925 || x === 9934 || x === 9940 || x === 9962 || x === 9970 || x === 9971 || x === 9973 || x === 9978 || x === 9981 || x === 9989 || x === 9994 || x === 9995 || x === 10024 || x === 10060 || x === 10062 || x >= 10067 && x <= 10069 || x === 10071 || x >= 10133 && x <= 10135 || x === 10160 || x === 10175 || x === 11035 || x === 11036 || x === 11088 || x === 11093 || x >= 11904 && x <= 11929 || x >= 11931 && x <= 12019 || x >= 12032 && x <= 12245 || x >= 12272 && x <= 12287 || x >= 12289 && x <= 12350 || x >= 12353 && x <= 12438 || x >= 12441 && x <= 12543 || x >= 12549 && x <= 12591 || x >= 12593 && x <= 12686 || x >= 12688 && x <= 12771 || x >= 12783 && x <= 12830 || x >= 12832 && x <= 12871 || x >= 12880 && x <= 19903 || x >= 19968 && x <= 42124 || x >= 42128 && x <= 42182 || x >= 43360 && x <= 43388 || x >= 44032 && x <= 55203 || x >= 63744 && x <= 64255 || x >= 65040 && x <= 65049 || x >= 65072 && x <= 65106 || x >= 65108 && x <= 65126 || x >= 65128 && x <= 65131 || x >= 94176 && x <= 94180 || x === 94192 || x === 94193 || x >= 94208 && x <= 100343 || x >= 100352 && x <= 101589 || x >= 101632 && x <= 101640 || x >= 110576 && x <= 110579 || x >= 110581 && x <= 110587 || x === 110589 || x === 110590 || x >= 110592 && x <= 110882 || x === 110898 || x >= 110928 && x <= 110930 || x === 110933 || x >= 110948 && x <= 110951 || x >= 110960 && x <= 111355 || x === 126980 || x === 127183 || x === 127374 || x >= 127377 && x <= 127386 || x >= 127488 && x <= 127490 || x >= 127504 && x <= 127547 || x >= 127552 && x <= 127560 || x === 127568 || x === 127569 || x >= 127584 && x <= 127589 || x >= 127744 && x <= 127776 || x >= 127789 && x <= 127797 || x >= 127799 && x <= 127868 || x >= 127870 && x <= 127891 || x >= 127904 && x <= 127946 || x >= 127951 && x <= 127955 || x >= 127968 && x <= 127984 || x === 127988 || x >= 127992 && x <= 128062 || x === 128064 || x >= 128066 && x <= 128252 || x >= 128255 && x <= 128317 || x >= 128331 && x <= 128334 || x >= 128336 && x <= 128359 || x === 128378 || x === 128405 || x === 128406 || x === 128420 || x >= 128507 && x <= 128591 || x >= 128640 && x <= 128709 || x === 128716 || x >= 128720 && x <= 128722 || x >= 128725 && x <= 128727 || x >= 128732 && x <= 128735 || x === 128747 || x === 128748 || x >= 128756 && x <= 128764 || x >= 128992 && x <= 129003 || x === 129008 || x >= 129292 && x <= 129338 || x >= 129340 && x <= 129349 || x >= 129351 && x <= 129535 || x >= 129648 && x <= 129660 || x >= 129664 && x <= 129672 || x >= 129680 && x <= 129725 || x >= 129727 && x <= 129733 || x >= 129742 && x <= 129755 || x >= 129760 && x <= 129768 || x >= 129776 && x <= 129784 || x >= 131072 && x <= 196605 || x >= 196608 && x <= 262141;
}

// node_modules/get-east-asian-width/index.js
var _isNarrowWidth = (codePoint) => !(isFullWidth(codePoint) || isWide(codePoint));

// src/utils/get-string-width.js
var notAsciiRegex = /[^\x20-\x7F]/u;
function getStringWidth(text) {
  if (!text) {
    return 0;
  }
  if (!notAsciiRegex.test(text)) {
    return text.length;
  }
  text = text.replace(emoji_regex_default(), "  ");
  let width = 0;
  for (const character of text) {
    const codePoint = character.codePointAt(0);
    if (codePoint <= 31 || codePoint >= 127 && codePoint <= 159) {
      continue;
    }
    if (codePoint >= 768 && codePoint <= 879) {
      continue;
    }
    width += _isNarrowWidth(codePoint) ? 1 : 2;
  }
  return width;
}
var get_string_width_default = getStringWidth;

// src/document/utils.js
function mapDoc(doc, cb) {
  if (typeof doc === "string") {
    return cb(doc);
  }
  const mapped = /* @__PURE__ */ new Map();
  return rec(doc);
  function rec(doc2) {
    if (mapped.has(doc2)) {
      return mapped.get(doc2);
    }
    const result = process2(doc2);
    mapped.set(doc2, result);
    return result;
  }
  function process2(doc2) {
    switch (get_doc_type_default(doc2)) {
      case DOC_TYPE_ARRAY:
        return cb(doc2.map(rec));
      case DOC_TYPE_FILL:
        return cb({
          ...doc2,
          parts: doc2.parts.map(rec)
        });
      case DOC_TYPE_IF_BREAK:
        return cb({
          ...doc2,
          breakContents: rec(doc2.breakContents),
          flatContents: rec(doc2.flatContents)
        });
      case DOC_TYPE_GROUP: {
        let {
          expandedStates,
          contents
        } = doc2;
        if (expandedStates) {
          expandedStates = expandedStates.map(rec);
          contents = expandedStates[0];
        } else {
          contents = rec(contents);
        }
        return cb({
          ...doc2,
          contents,
          expandedStates
        });
      }
      case DOC_TYPE_ALIGN:
      case DOC_TYPE_INDENT:
      case DOC_TYPE_INDENT_IF_BREAK:
      case DOC_TYPE_LABEL:
      case DOC_TYPE_LINE_SUFFIX:
        return cb({
          ...doc2,
          contents: rec(doc2.contents)
        });
      case DOC_TYPE_STRING:
      case DOC_TYPE_CURSOR:
      case DOC_TYPE_TRIM:
      case DOC_TYPE_LINE_SUFFIX_BOUNDARY:
      case DOC_TYPE_LINE:
      case DOC_TYPE_BREAK_PARENT:
        return cb(doc2);
      default:
        throw new invalid_doc_error_default(doc2);
    }
  }
}
function findInDoc(doc, fn, defaultValue) {
  let result = defaultValue;
  let shouldSkipFurtherProcessing = false;
  function findInDocOnEnterFn(doc2) {
    if (shouldSkipFurtherProcessing) {
      return false;
    }
    const maybeResult = fn(doc2);
    if (maybeResult !== void 0) {
      shouldSkipFurtherProcessing = true;
      result = maybeResult;
    }
  }
  traverse_doc_default(doc, findInDocOnEnterFn);
  return result;
}
function willBreakFn(doc) {
  if (doc.type === DOC_TYPE_GROUP && doc.break) {
    return true;
  }
  if (doc.type === DOC_TYPE_LINE && doc.hard) {
    return true;
  }
  if (doc.type === DOC_TYPE_BREAK_PARENT) {
    return true;
  }
}
function willBreak(doc) {
  return findInDoc(doc, willBreakFn, false);
}
function breakParentGroup(groupStack) {
  if (groupStack.length > 0) {
    const parentGroup = at_default(
      /* isOptionalObject */
      false,
      groupStack,
      -1
    );
    if (!parentGroup.expandedStates && !parentGroup.break) {
      parentGroup.break = "propagated";
    }
  }
  return null;
}
function propagateBreaks(doc) {
  const alreadyVisitedSet = /* @__PURE__ */ new Set();
  const groupStack = [];
  function propagateBreaksOnEnterFn(doc2) {
    if (doc2.type === DOC_TYPE_BREAK_PARENT) {
      breakParentGroup(groupStack);
    }
    if (doc2.type === DOC_TYPE_GROUP) {
      groupStack.push(doc2);
      if (alreadyVisitedSet.has(doc2)) {
        return false;
      }
      alreadyVisitedSet.add(doc2);
    }
  }
  function propagateBreaksOnExitFn(doc2) {
    if (doc2.type === DOC_TYPE_GROUP) {
      const group2 = groupStack.pop();
      if (group2.break) {
        breakParentGroup(groupStack);
      }
    }
  }
  traverse_doc_default(
    doc,
    propagateBreaksOnEnterFn,
    propagateBreaksOnExitFn,
    /* shouldTraverseConditionalGroups */
    true
  );
}
function removeLinesFn(doc) {
  if (doc.type === DOC_TYPE_LINE && !doc.hard) {
    return doc.soft ? "" : " ";
  }
  if (doc.type === DOC_TYPE_IF_BREAK) {
    return doc.flatContents;
  }
  return doc;
}
function removeLines(doc) {
  return mapDoc(doc, removeLinesFn);
}
function stripTrailingHardlineFromParts(parts) {
  parts = [...parts];
  while (parts.length >= 2 && at_default(
    /* isOptionalObject */
    false,
    parts,
    -2
  ).type === DOC_TYPE_LINE && at_default(
    /* isOptionalObject */
    false,
    parts,
    -1
  ).type === DOC_TYPE_BREAK_PARENT) {
    parts.length -= 2;
  }
  if (parts.length > 0) {
    const lastPart = stripTrailingHardlineFromDoc(at_default(
      /* isOptionalObject */
      false,
      parts,
      -1
    ));
    parts[parts.length - 1] = lastPart;
  }
  return parts;
}
function stripTrailingHardlineFromDoc(doc) {
  switch (get_doc_type_default(doc)) {
    case DOC_TYPE_INDENT:
    case DOC_TYPE_INDENT_IF_BREAK:
    case DOC_TYPE_GROUP:
    case DOC_TYPE_LINE_SUFFIX:
    case DOC_TYPE_LABEL: {
      const contents = stripTrailingHardlineFromDoc(doc.contents);
      return {
        ...doc,
        contents
      };
    }
    case DOC_TYPE_IF_BREAK:
      return {
        ...doc,
        breakContents: stripTrailingHardlineFromDoc(doc.breakContents),
        flatContents: stripTrailingHardlineFromDoc(doc.flatContents)
      };
    case DOC_TYPE_FILL:
      return {
        ...doc,
        parts: stripTrailingHardlineFromParts(doc.parts)
      };
    case DOC_TYPE_ARRAY:
      return stripTrailingHardlineFromParts(doc);
    case DOC_TYPE_STRING:
      return doc.replace(/[\n\r]*$/u, "");
    case DOC_TYPE_ALIGN:
    case DOC_TYPE_CURSOR:
    case DOC_TYPE_TRIM:
    case DOC_TYPE_LINE_SUFFIX_BOUNDARY:
    case DOC_TYPE_LINE:
    case DOC_TYPE_BREAK_PARENT:
      break;
    default:
      throw new invalid_doc_error_default(doc);
  }
  return doc;
}
function stripTrailingHardline(doc) {
  return stripTrailingHardlineFromDoc(cleanDoc(doc));
}
function cleanDocFn(doc) {
  switch (get_doc_type_default(doc)) {
    case DOC_TYPE_FILL:
      if (doc.parts.every((part) => part === "")) {
        return "";
      }
      break;
    case DOC_TYPE_GROUP:
      if (!doc.contents && !doc.id && !doc.break && !doc.expandedStates) {
        return "";
      }
      if (doc.contents.type === DOC_TYPE_GROUP && doc.contents.id === doc.id && doc.contents.break === doc.break && doc.contents.expandedStates === doc.expandedStates) {
        return doc.contents;
      }
      break;
    case DOC_TYPE_ALIGN:
    case DOC_TYPE_INDENT:
    case DOC_TYPE_INDENT_IF_BREAK:
    case DOC_TYPE_LINE_SUFFIX:
      if (!doc.contents) {
        return "";
      }
      break;
    case DOC_TYPE_IF_BREAK:
      if (!doc.flatContents && !doc.breakContents) {
        return "";
      }
      break;
    case DOC_TYPE_ARRAY: {
      const parts = [];
      for (const part of doc) {
        if (!part) {
          continue;
        }
        const [currentPart, ...restParts] = Array.isArray(part) ? part : [part];
        if (typeof currentPart === "string" && typeof at_default(
          /* isOptionalObject */
          false,
          parts,
          -1
        ) === "string") {
          parts[parts.length - 1] += currentPart;
        } else {
          parts.push(currentPart);
        }
        parts.push(...restParts);
      }
      if (parts.length === 0) {
        return "";
      }
      if (parts.length === 1) {
        return parts[0];
      }
      return parts;
    }
    case DOC_TYPE_STRING:
    case DOC_TYPE_CURSOR:
    case DOC_TYPE_TRIM:
    case DOC_TYPE_LINE_SUFFIX_BOUNDARY:
    case DOC_TYPE_LINE:
    case DOC_TYPE_LABEL:
    case DOC_TYPE_BREAK_PARENT:
      break;
    default:
      throw new invalid_doc_error_default(doc);
  }
  return doc;
}
function cleanDoc(doc) {
  return mapDoc(doc, (currentDoc) => cleanDocFn(currentDoc));
}
function replaceEndOfLine(doc, replacement = literalline$1) {
  return mapDoc(doc, (currentDoc) => typeof currentDoc === "string" ? join$1(replacement, currentDoc.split("\n")) : currentDoc);
}
function canBreakFn(doc) {
  if (doc.type === DOC_TYPE_LINE) {
    return true;
  }
}
function canBreak(doc) {
  return findInDoc(doc, canBreakFn, false);
}

// src/document/printer.js
var MODE_BREAK = Symbol("MODE_BREAK");
var MODE_FLAT = Symbol("MODE_FLAT");
var CURSOR_PLACEHOLDER = Symbol("cursor");
function rootIndent() {
  return {
    value: "",
    length: 0,
    queue: []
  };
}
function makeIndent(ind, options) {
  return generateInd(ind, {
    type: "indent"
  }, options);
}
function makeAlign(indent2, widthOrDoc, options) {
  if (widthOrDoc === Number.NEGATIVE_INFINITY) {
    return indent2.root || rootIndent();
  }
  if (widthOrDoc < 0) {
    return generateInd(indent2, {
      type: "dedent"
    }, options);
  }
  if (!widthOrDoc) {
    return indent2;
  }
  if (widthOrDoc.type === "root") {
    return {
      ...indent2,
      root: indent2
    };
  }
  const alignType = typeof widthOrDoc === "string" ? "stringAlign" : "numberAlign";
  return generateInd(indent2, {
    type: alignType,
    n: widthOrDoc
  }, options);
}
function generateInd(ind, newPart, options) {
  const queue = newPart.type === "dedent" ? ind.queue.slice(0, -1) : [...ind.queue, newPart];
  let value = "";
  let length = 0;
  let lastTabs = 0;
  let lastSpaces = 0;
  for (const part of queue) {
    switch (part.type) {
      case "indent":
        flush();
        if (options.useTabs) {
          addTabs(1);
        } else {
          addSpaces(options.tabWidth);
        }
        break;
      case "stringAlign":
        flush();
        value += part.n;
        length += part.n.length;
        break;
      case "numberAlign":
        lastTabs += 1;
        lastSpaces += part.n;
        break;
      default:
        throw new Error(`Unexpected type '${part.type}'`);
    }
  }
  flushSpaces();
  return {
    ...ind,
    value,
    length,
    queue
  };
  function addTabs(count) {
    value += "	".repeat(count);
    length += options.tabWidth * count;
  }
  function addSpaces(count) {
    value += " ".repeat(count);
    length += count;
  }
  function flush() {
    if (options.useTabs) {
      flushTabs();
    } else {
      flushSpaces();
    }
  }
  function flushTabs() {
    if (lastTabs > 0) {
      addTabs(lastTabs);
    }
    resetLast();
  }
  function flushSpaces() {
    if (lastSpaces > 0) {
      addSpaces(lastSpaces);
    }
    resetLast();
  }
  function resetLast() {
    lastTabs = 0;
    lastSpaces = 0;
  }
}
function trim2(out) {
  let trimCount = 0;
  let cursorCount = 0;
  let outIndex = out.length;
  outer: while (outIndex--) {
    const last = out[outIndex];
    if (last === CURSOR_PLACEHOLDER) {
      cursorCount++;
      continue;
    }
    for (let charIndex = last.length - 1; charIndex >= 0; charIndex--) {
      const char = last[charIndex];
      if (char === " " || char === "	") {
        trimCount++;
      } else {
        out[outIndex] = last.slice(0, charIndex + 1);
        break outer;
      }
    }
  }
  if (trimCount > 0 || cursorCount > 0) {
    out.length = outIndex + 1;
    while (cursorCount-- > 0) {
      out.push(CURSOR_PLACEHOLDER);
    }
  }
  return trimCount;
}
function fits(next, restCommands, width, hasLineSuffix, groupModeMap, mustBeFlat) {
  if (width === Number.POSITIVE_INFINITY) {
    return true;
  }
  let restIdx = restCommands.length;
  const cmds = [next];
  const out = [];
  while (width >= 0) {
    if (cmds.length === 0) {
      if (restIdx === 0) {
        return true;
      }
      cmds.push(restCommands[--restIdx]);
      continue;
    }
    const {
      mode,
      doc
    } = cmds.pop();
    const docType = get_doc_type_default(doc);
    switch (docType) {
      case DOC_TYPE_STRING:
        out.push(doc);
        width -= get_string_width_default(doc);
        break;
      case DOC_TYPE_ARRAY:
      case DOC_TYPE_FILL: {
        const parts = docType === DOC_TYPE_ARRAY ? doc : doc.parts;
        for (let i = parts.length - 1; i >= 0; i--) {
          cmds.push({
            mode,
            doc: parts[i]
          });
        }
        break;
      }
      case DOC_TYPE_INDENT:
      case DOC_TYPE_ALIGN:
      case DOC_TYPE_INDENT_IF_BREAK:
      case DOC_TYPE_LABEL:
        cmds.push({
          mode,
          doc: doc.contents
        });
        break;
      case DOC_TYPE_TRIM:
        width += trim2(out);
        break;
      case DOC_TYPE_GROUP: {
        if (mustBeFlat && doc.break) {
          return false;
        }
        const groupMode = doc.break ? MODE_BREAK : mode;
        const contents = doc.expandedStates && groupMode === MODE_BREAK ? at_default(
          /* isOptionalObject */
          false,
          doc.expandedStates,
          -1
        ) : doc.contents;
        cmds.push({
          mode: groupMode,
          doc: contents
        });
        break;
      }
      case DOC_TYPE_IF_BREAK: {
        const groupMode = doc.groupId ? groupModeMap[doc.groupId] || MODE_FLAT : mode;
        const contents = groupMode === MODE_BREAK ? doc.breakContents : doc.flatContents;
        if (contents) {
          cmds.push({
            mode,
            doc: contents
          });
        }
        break;
      }
      case DOC_TYPE_LINE:
        if (mode === MODE_BREAK || doc.hard) {
          return true;
        }
        if (!doc.soft) {
          out.push(" ");
          width--;
        }
        break;
      case DOC_TYPE_LINE_SUFFIX:
        hasLineSuffix = true;
        break;
      case DOC_TYPE_LINE_SUFFIX_BOUNDARY:
        if (hasLineSuffix) {
          return false;
        }
        break;
    }
  }
  return false;
}
function printDocToString(doc, options) {
  const groupModeMap = {};
  const width = options.printWidth;
  const newLine = convertEndOfLineToChars(options.endOfLine);
  let pos = 0;
  const cmds = [{
    ind: rootIndent(),
    mode: MODE_BREAK,
    doc
  }];
  const out = [];
  let shouldRemeasure = false;
  const lineSuffix2 = [];
  let printedCursorCount = 0;
  propagateBreaks(doc);
  while (cmds.length > 0) {
    const {
      ind,
      mode,
      doc: doc2
    } = cmds.pop();
    switch (get_doc_type_default(doc2)) {
      case DOC_TYPE_STRING: {
        const formatted = newLine !== "\n" ? string_replace_all_default(
          /* isOptionalObject */
          false,
          doc2,
          "\n",
          newLine
        ) : doc2;
        out.push(formatted);
        if (cmds.length > 0) {
          pos += get_string_width_default(formatted);
        }
        break;
      }
      case DOC_TYPE_ARRAY:
        for (let i = doc2.length - 1; i >= 0; i--) {
          cmds.push({
            ind,
            mode,
            doc: doc2[i]
          });
        }
        break;
      case DOC_TYPE_CURSOR:
        if (printedCursorCount >= 2) {
          throw new Error("There are too many 'cursor' in doc.");
        }
        out.push(CURSOR_PLACEHOLDER);
        printedCursorCount++;
        break;
      case DOC_TYPE_INDENT:
        cmds.push({
          ind: makeIndent(ind, options),
          mode,
          doc: doc2.contents
        });
        break;
      case DOC_TYPE_ALIGN:
        cmds.push({
          ind: makeAlign(ind, doc2.n, options),
          mode,
          doc: doc2.contents
        });
        break;
      case DOC_TYPE_TRIM:
        pos -= trim2(out);
        break;
      case DOC_TYPE_GROUP:
        switch (mode) {
          case MODE_FLAT:
            if (!shouldRemeasure) {
              cmds.push({
                ind,
                mode: doc2.break ? MODE_BREAK : MODE_FLAT,
                doc: doc2.contents
              });
              break;
            }
          case MODE_BREAK: {
            shouldRemeasure = false;
            const next = {
              ind,
              mode: MODE_FLAT,
              doc: doc2.contents
            };
            const rem = width - pos;
            const hasLineSuffix = lineSuffix2.length > 0;
            if (!doc2.break && fits(next, cmds, rem, hasLineSuffix, groupModeMap)) {
              cmds.push(next);
            } else {
              if (doc2.expandedStates) {
                const mostExpanded = at_default(
                  /* isOptionalObject */
                  false,
                  doc2.expandedStates,
                  -1
                );
                if (doc2.break) {
                  cmds.push({
                    ind,
                    mode: MODE_BREAK,
                    doc: mostExpanded
                  });
                  break;
                } else {
                  for (let i = 1; i < doc2.expandedStates.length + 1; i++) {
                    if (i >= doc2.expandedStates.length) {
                      cmds.push({
                        ind,
                        mode: MODE_BREAK,
                        doc: mostExpanded
                      });
                      break;
                    } else {
                      const state = doc2.expandedStates[i];
                      const cmd = {
                        ind,
                        mode: MODE_FLAT,
                        doc: state
                      };
                      if (fits(cmd, cmds, rem, hasLineSuffix, groupModeMap)) {
                        cmds.push(cmd);
                        break;
                      }
                    }
                  }
                }
              } else {
                cmds.push({
                  ind,
                  mode: MODE_BREAK,
                  doc: doc2.contents
                });
              }
            }
            break;
          }
        }
        if (doc2.id) {
          groupModeMap[doc2.id] = at_default(
            /* isOptionalObject */
            false,
            cmds,
            -1
          ).mode;
        }
        break;
      case DOC_TYPE_FILL: {
        const rem = width - pos;
        const {
          parts
        } = doc2;
        if (parts.length === 0) {
          break;
        }
        const [content, whitespace] = parts;
        const contentFlatCmd = {
          ind,
          mode: MODE_FLAT,
          doc: content
        };
        const contentBreakCmd = {
          ind,
          mode: MODE_BREAK,
          doc: content
        };
        const contentFits = fits(contentFlatCmd, [], rem, lineSuffix2.length > 0, groupModeMap, true);
        if (parts.length === 1) {
          if (contentFits) {
            cmds.push(contentFlatCmd);
          } else {
            cmds.push(contentBreakCmd);
          }
          break;
        }
        const whitespaceFlatCmd = {
          ind,
          mode: MODE_FLAT,
          doc: whitespace
        };
        const whitespaceBreakCmd = {
          ind,
          mode: MODE_BREAK,
          doc: whitespace
        };
        if (parts.length === 2) {
          if (contentFits) {
            cmds.push(whitespaceFlatCmd, contentFlatCmd);
          } else {
            cmds.push(whitespaceBreakCmd, contentBreakCmd);
          }
          break;
        }
        parts.splice(0, 2);
        const remainingCmd = {
          ind,
          mode,
          doc: fill(parts)
        };
        const secondContent = parts[0];
        const firstAndSecondContentFlatCmd = {
          ind,
          mode: MODE_FLAT,
          doc: [content, whitespace, secondContent]
        };
        const firstAndSecondContentFits = fits(firstAndSecondContentFlatCmd, [], rem, lineSuffix2.length > 0, groupModeMap, true);
        if (firstAndSecondContentFits) {
          cmds.push(remainingCmd, whitespaceFlatCmd, contentFlatCmd);
        } else if (contentFits) {
          cmds.push(remainingCmd, whitespaceBreakCmd, contentFlatCmd);
        } else {
          cmds.push(remainingCmd, whitespaceBreakCmd, contentBreakCmd);
        }
        break;
      }
      case DOC_TYPE_IF_BREAK:
      case DOC_TYPE_INDENT_IF_BREAK: {
        const groupMode = doc2.groupId ? groupModeMap[doc2.groupId] : mode;
        if (groupMode === MODE_BREAK) {
          const breakContents = doc2.type === DOC_TYPE_IF_BREAK ? doc2.breakContents : doc2.negate ? doc2.contents : indent$1(doc2.contents);
          if (breakContents) {
            cmds.push({
              ind,
              mode,
              doc: breakContents
            });
          }
        }
        if (groupMode === MODE_FLAT) {
          const flatContents = doc2.type === DOC_TYPE_IF_BREAK ? doc2.flatContents : doc2.negate ? indent$1(doc2.contents) : doc2.contents;
          if (flatContents) {
            cmds.push({
              ind,
              mode,
              doc: flatContents
            });
          }
        }
        break;
      }
      case DOC_TYPE_LINE_SUFFIX:
        lineSuffix2.push({
          ind,
          mode,
          doc: doc2.contents
        });
        break;
      case DOC_TYPE_LINE_SUFFIX_BOUNDARY:
        if (lineSuffix2.length > 0) {
          cmds.push({
            ind,
            mode,
            doc: hardlineWithoutBreakParent
          });
        }
        break;
      case DOC_TYPE_LINE:
        switch (mode) {
          case MODE_FLAT:
            if (!doc2.hard) {
              if (!doc2.soft) {
                out.push(" ");
                pos += 1;
              }
              break;
            } else {
              shouldRemeasure = true;
            }
          case MODE_BREAK:
            if (lineSuffix2.length > 0) {
              cmds.push({
                ind,
                mode,
                doc: doc2
              }, ...lineSuffix2.reverse());
              lineSuffix2.length = 0;
              break;
            }
            if (doc2.literal) {
              if (ind.root) {
                out.push(newLine, ind.root.value);
                pos = ind.root.length;
              } else {
                out.push(newLine);
                pos = 0;
              }
            } else {
              pos -= trim2(out);
              out.push(newLine + ind.value);
              pos = ind.length;
            }
            break;
        }
        break;
      case DOC_TYPE_LABEL:
        cmds.push({
          ind,
          mode,
          doc: doc2.contents
        });
        break;
      case DOC_TYPE_BREAK_PARENT:
        break;
      default:
        throw new invalid_doc_error_default(doc2);
    }
    if (cmds.length === 0 && lineSuffix2.length > 0) {
      cmds.push(...lineSuffix2.reverse());
      lineSuffix2.length = 0;
    }
  }
  const cursorPlaceholderIndex = out.indexOf(CURSOR_PLACEHOLDER);
  if (cursorPlaceholderIndex !== -1) {
    const otherCursorPlaceholderIndex = out.indexOf(CURSOR_PLACEHOLDER, cursorPlaceholderIndex + 1);
    const beforeCursor = out.slice(0, cursorPlaceholderIndex).join("");
    const aroundCursor = out.slice(cursorPlaceholderIndex + 1, otherCursorPlaceholderIndex).join("");
    const afterCursor = out.slice(otherCursorPlaceholderIndex + 1).join("");
    return {
      formatted: beforeCursor + aroundCursor + afterCursor,
      cursorNodeStart: beforeCursor.length,
      cursorNodeText: aroundCursor
    };
  }
  return {
    formatted: out.join("")
  };
}

// src/document/public.js
var builders = {
  join: join$1,
  line: line$1,
  softline: softline$1,
  hardline: hardline$1,
  literalline: literalline$1,
  group: group$1,
  conditionalGroup,
  fill,
  lineSuffix,
  lineSuffixBoundary,
  cursor,
  breakParent: breakParent$1,
  ifBreak: ifBreak$1,
  trim,
  indent: indent$1,
  indentIfBreak,
  align: align$1,
  addAlignmentToDoc,
  markAsRoot: markAsRoot$1,
  dedentToRoot,
  dedent,
  hardlineWithoutBreakParent,
  literallineWithoutBreakParent,
  label,
  // TODO: Remove this in v4
  concat: (parts) => parts
};
var printer = { printDocToString };
var utils = {
  willBreak,
  traverseDoc: traverse_doc_default,
  findInDoc,
  mapDoc,
  removeLines,
  stripTrailingHardline,
  replaceEndOfLine,
  canBreak
};

const util = or;

/**
 * Override the default behavior to attach comments to syntax node.
 */
const commentHandler = {
    ownLine: (comment, text, options, ast, isLastComment) => [
        addEmptyInterfaceComment,
        addEmptyModelComment,
        addEmptyScalarComment,
        addCommentBetweenAnnotationsAndNode,
        handleOnlyComments,
    ].some((x) => x({ comment, text, options, ast: ast, isLastComment })),
    remaining: (comment, text, options, ast, isLastComment) => [handleOnlyComments].some((x) => x({ comment, text, options, ast: ast, isLastComment })),
    endOfLine: (comment, text, options, ast, isLastComment) => [handleOnlyComments].some((x) => x({ comment, text, options, ast: ast, isLastComment })),
};
/**
 * When a comment is on an empty interface make sure it gets added as a dangling comment on it and not on the identifier.
 *
 * @example
 *
 * interface Foo {
 *   // My comment
 * }
 */
function addEmptyInterfaceComment({ comment, ast }) {
    const { precedingNode, enclosingNode } = comment;
    if (enclosingNode &&
        enclosingNode.kind === SyntaxKind.InterfaceStatement &&
        enclosingNode.operations.length === 0 &&
        precedingNode &&
        precedingNode.kind === SyntaxKind.Identifier) {
        util.addDanglingComment(enclosingNode, comment, undefined);
        return true;
    }
    return false;
}
/**
 * When a comment is in between a node and its annotations(Decorator, directives, doc comments).
 *
 * @example
 *
 * @foo
 * // My comment
 * @bar
 * model Foo {
 * }
 */
function addCommentBetweenAnnotationsAndNode({ comment }) {
    const { enclosingNode, precedingNode } = comment;
    if (precedingNode &&
        (precedingNode.kind === SyntaxKind.DecoratorExpression ||
            precedingNode.kind === SyntaxKind.DirectiveExpression ||
            precedingNode.kind === SyntaxKind.Doc) &&
        enclosingNode &&
        (enclosingNode.kind === SyntaxKind.NamespaceStatement ||
            enclosingNode.kind === SyntaxKind.ModelStatement ||
            enclosingNode.kind === SyntaxKind.EnumStatement ||
            enclosingNode.kind === SyntaxKind.OperationStatement ||
            enclosingNode.kind === SyntaxKind.ScalarStatement ||
            enclosingNode.kind === SyntaxKind.InterfaceStatement ||
            enclosingNode.kind === SyntaxKind.ModelProperty ||
            enclosingNode.kind === SyntaxKind.EnumMember ||
            enclosingNode.kind === SyntaxKind.UnionStatement)) {
        util.addTrailingComment(precedingNode, comment);
        return true;
    }
    return false;
}
/**
 * When a comment is on an empty model make sure it gets added as a dangling comment on it and not on the identifier.
 *
 * @example
 *
 * model Foo {
 *   // My comment
 * }
 */
function addEmptyModelComment({ comment }) {
    const { precedingNode, enclosingNode } = comment;
    if (enclosingNode &&
        enclosingNode.kind === SyntaxKind.ModelStatement &&
        enclosingNode.properties.length === 0 &&
        precedingNode &&
        (precedingNode === enclosingNode.is ||
            precedingNode === enclosingNode.id ||
            precedingNode === enclosingNode.extends)) {
        util.addDanglingComment(enclosingNode, comment, undefined);
        return true;
    }
    return false;
}
/**
 * When a comment is on an empty scalar make sure it gets added as a dangling comment on it and not on the identifier.
 *
 * @example
 *
 * scalar foo {
 *   // My comment
 * }
 */
function addEmptyScalarComment({ comment }) {
    const { precedingNode, enclosingNode } = comment;
    if (enclosingNode &&
        enclosingNode.kind === SyntaxKind.ScalarStatement &&
        enclosingNode.members.length === 0 &&
        precedingNode &&
        (precedingNode === enclosingNode.id || precedingNode === enclosingNode.extends)) {
        util.addDanglingComment(enclosingNode, comment, undefined);
        return true;
    }
    return false;
}
function handleOnlyComments({ comment, ast, isLastComment }) {
    const { enclosingNode } = comment;
    if (ast?.statements?.length === 0) {
        if (isLastComment) {
            util.addDanglingComment(ast, comment, undefined);
        }
        else {
            util.addLeadingComment(ast, comment);
        }
        return true;
    }
    if (enclosingNode?.kind === SyntaxKind.TypeSpecScript &&
        enclosingNode.statements.length === 0 &&
        enclosingNode.directives?.length === 0) {
        if (isLastComment) {
            util.addDanglingComment(enclosingNode, comment, undefined);
        }
        else {
            util.addLeadingComment(enclosingNode, comment);
        }
        return true;
    }
    return false;
}

/**
 * Check if the current path should be wrapped in parentheses
 * @param path Prettier print path.
 * @param options Prettier options
 */
function needsParens(path, options) {
    const parent = path.getParentNode();
    if (!parent) {
        return false;
    }
    const node = path.node;
    switch (node.kind) {
        case SyntaxKind.ValueOfExpression:
            return (parent.kind === SyntaxKind.UnionExpression ||
                parent.kind === SyntaxKind.ArrayExpression ||
                parent.kind === SyntaxKind.IntersectionExpression);
        case SyntaxKind.IntersectionExpression:
            return (parent.kind === SyntaxKind.UnionExpression || parent.kind === SyntaxKind.ArrayExpression);
        case SyntaxKind.UnionExpression:
            return (parent.kind === SyntaxKind.IntersectionExpression ||
                parent.kind === SyntaxKind.ArrayExpression);
        case SyntaxKind.ProjectionLogicalExpression:
            return parent.kind === SyntaxKind.ProjectionLogicalExpression;
        case SyntaxKind.ProjectionArithmeticExpression:
            return parent.kind === SyntaxKind.ProjectionArithmeticExpression;
        default:
            return false;
    }
}

const { align, breakParent, group, hardline, ifBreak, indent, join, line, softline, literalline, markAsRoot, } = builders;
const { isNextLineEmpty } = util;
/**
 * If the decorators for that node should try to be kept inline.
 */
const DecoratorsTryInline = {
    modelProperty: true,
    enumMember: true,
    unionVariant: true,
};
const typespecPrinter = {
    print: printTypeSpec,
    isBlockComment: (node) => isBlockComment(node),
    canAttachComment: canAttachComment,
    printComment: printComment,
    handleComments: commentHandler,
};
function printTypeSpec(
// Path to the AST node to print
path, options, print) {
    const node = path.node;
    const docs = printDocComments(path, options, print);
    const directives = shouldPrintDirective(node) ? printDirectives(path, options, print) : "";
    const printedNode = printNode(path, options, print);
    const value = needsParens(path) ? ["(", printedNode, ")"] : printedNode;
    const parts = [docs, directives, value];
    if (node.kind === SyntaxKind.TypeSpecScript) {
        // For TypeSpecScript(root of TypeSpec document) we had a new line at the end.
        // This must be done here so the hardline entry can be the last item of the doc array returned by the printer
        // so the markdown(and other embedded formatter) can omit that extra line.
        parts.push(hardline);
    }
    return parts;
}
function shouldPrintDirective(node) {
    // Model property handle printing directive itself.
    return node.kind !== SyntaxKind.ModelProperty;
}
function printNode(
// Path to the AST node to print
path, options, print) {
    const node = path.node;
    switch (node.kind) {
        // Root
        case SyntaxKind.TypeSpecScript:
            return printTypeSpecScript(path, options, print);
        // Statements
        case SyntaxKind.ImportStatement:
            return [`import "${node.path.value}";`];
        case SyntaxKind.UsingStatement:
            return [`using `, path.call(print, "name"), `;`];
        case SyntaxKind.OperationStatement:
            return printOperationStatement(path, options, print);
        case SyntaxKind.OperationSignatureDeclaration:
            return printOperationSignatureDeclaration(path, options, print);
        case SyntaxKind.OperationSignatureReference:
            return printOperationSignatureReference(path, options, print);
        case SyntaxKind.NamespaceStatement:
            return printNamespaceStatement(path, options, print);
        case SyntaxKind.ModelStatement:
            return printModelStatement(path, options, print);
        case SyntaxKind.ScalarStatement:
            return printScalarStatement(path, options, print);
        case SyntaxKind.ScalarConstructor:
            return printScalarConstructor(path, options, print);
        case SyntaxKind.AliasStatement:
            return printAliasStatement(path, options, print);
        case SyntaxKind.EnumStatement:
            return printEnumStatement(path, options, print);
        case SyntaxKind.UnionStatement:
            return printUnionStatement(path, options, print);
        case SyntaxKind.InterfaceStatement:
            return printInterfaceStatement(path, options, print);
        // Others.
        case SyntaxKind.Identifier:
            return printIdentifier(node);
        case SyntaxKind.StringLiteral:
            return printStringLiteral(path, options);
        case SyntaxKind.NumericLiteral:
            return printNumberLiteral(path, options);
        case SyntaxKind.BooleanLiteral:
            return printBooleanLiteral(path);
        case SyntaxKind.ModelExpression:
            return printModelExpression(path, options, print);
        case SyntaxKind.ModelProperty:
            return printModelProperty(path, options, print);
        case SyntaxKind.DecoratorExpression:
            return printDecorator(path, options, print);
        case SyntaxKind.AugmentDecoratorStatement:
            return printAugmentDecorator(path, options, print);
        case SyntaxKind.DirectiveExpression:
            return printDirective(path, options, print);
        case SyntaxKind.UnionExpression:
            return printUnion(path, options, print);
        case SyntaxKind.IntersectionExpression:
            return printIntersection(path, options, print);
        case SyntaxKind.ArrayExpression:
            return printArray(path, options, print);
        case SyntaxKind.TupleExpression:
            return printTuple(path, options, print);
        case SyntaxKind.MemberExpression:
            return printMemberExpression(path, options, print);
        case SyntaxKind.EnumMember:
            return printEnumMember(path, options, print);
        case SyntaxKind.EnumSpreadMember:
            return printEnumSpreadMember(path, options, print);
        case SyntaxKind.UnionVariant:
            return printUnionVariant(path, options, print);
        case SyntaxKind.TypeReference:
            return printTypeReference(path, options, print);
        case SyntaxKind.TemplateArgument:
            return printTemplateArgument(path, options, print);
        case SyntaxKind.ValueOfExpression:
            return printValueOfExpression(path, options, print);
        case SyntaxKind.TypeOfExpression:
            return printTypeOfExpression(path, options, print);
        case SyntaxKind.TemplateParameterDeclaration:
            return printTemplateParameterDeclaration(path, options, print);
        case SyntaxKind.ModelSpreadProperty:
            return printModelSpread(path, options, print);
        case SyntaxKind.DecoratorDeclarationStatement:
            return printDecoratorDeclarationStatement(path, options, print);
        case SyntaxKind.FunctionDeclarationStatement:
            return printFunctionDeclarationStatement(path, options, print);
        case SyntaxKind.FunctionParameter:
            return printFunctionParameterDeclaration(path, options, print);
        case SyntaxKind.ExternKeyword:
            return "extern";
        case SyntaxKind.VoidKeyword:
            return "void";
        case SyntaxKind.NeverKeyword:
            return "never";
        case SyntaxKind.UnknownKeyword:
            return "unknown";
        case SyntaxKind.ProjectionStatement:
            return printProjectionStatement(path, options, print);
        case SyntaxKind.ProjectionModelSelector:
            return "model";
        case SyntaxKind.ProjectionModelPropertySelector:
            return "modelproperty";
        case SyntaxKind.ProjectionScalarSelector:
            return "scalar";
        case SyntaxKind.ProjectionOperationSelector:
            return "op";
        case SyntaxKind.ProjectionUnionSelector:
            return "union";
        case SyntaxKind.ProjectionUnionVariantSelector:
            return "unionvariant";
        case SyntaxKind.ProjectionInterfaceSelector:
            return "interface";
        case SyntaxKind.ProjectionEnumSelector:
            return "enum";
        case SyntaxKind.ProjectionEnumMemberSelector:
            return "enummember";
        case SyntaxKind.Projection:
            return printProjection(path, options, print);
        case SyntaxKind.ProjectionParameterDeclaration:
            return printProjectionParameterDeclaration(path, options, print);
        case SyntaxKind.ProjectionExpressionStatement:
            return printProjectionExpressionStatement(path, options, print);
        case SyntaxKind.ProjectionIfExpression:
            return printProjectionIfExpressionNode(path, options, print);
        case SyntaxKind.ProjectionBlockExpression:
            return printProjectionBlockExpressionNode(path, options, print);
        case SyntaxKind.ProjectionMemberExpression:
            return printProjectionMemberExpression(path, options, print);
        case SyntaxKind.ProjectionLogicalExpression:
        case SyntaxKind.ProjectionEqualityExpression:
        case SyntaxKind.ProjectionRelationalExpression:
        case SyntaxKind.ProjectionArithmeticExpression:
            return printProjectionLeftRightExpression(path, options, print);
        case SyntaxKind.ProjectionUnaryExpression:
            return printProjectionUnaryExpression(path, options, print);
        case SyntaxKind.ProjectionCallExpression:
            return printProjectionCallExpression(path, options, print);
        case SyntaxKind.ProjectionLambdaExpression:
            return printProjectionLambdaExpression(path, options, print);
        case SyntaxKind.ProjectionLambdaParameterDeclaration:
            return printProjectionLambdaParameterDeclaration(path, options, print);
        case SyntaxKind.ProjectionModelExpression:
            return printModelExpression(path, options, print);
        case SyntaxKind.ProjectionModelProperty:
            return printModelProperty(path, options, print);
        case SyntaxKind.ProjectionModelSpreadProperty:
            return printModelSpread(path, options, print);
        case SyntaxKind.ProjectionTupleExpression:
            return printTuple(path, options, print);
        case SyntaxKind.ProjectionDecoratorReferenceExpression:
            return path.call(print, "target");
        case SyntaxKind.Return:
            return printReturnExpression(path, options, print);
        case SyntaxKind.Doc:
            return printDoc(path, options);
        case SyntaxKind.DocText:
        case SyntaxKind.DocParamTag:
        case SyntaxKind.DocPropTag:
        case SyntaxKind.DocTemplateTag:
        case SyntaxKind.DocReturnsTag:
        case SyntaxKind.DocErrorsTag:
        case SyntaxKind.DocUnknownTag:
            // https://github.com/microsoft/typespec/issues/1319 Tracks pretty-printing doc comments.
            compilerAssert(false, "Currently, doc comments are only handled as regular comments and we do not opt in to parsing them so we shouldn't reach here.");
            return "";
        case SyntaxKind.EmptyStatement:
            return "";
        case SyntaxKind.StringTemplateExpression:
            return printStringTemplateExpression(path, options, print);
        case SyntaxKind.ObjectLiteral:
            return printObjectLiteral(path, options, print);
        case SyntaxKind.ObjectLiteralProperty:
            return printObjectLiteralProperty(path, options, print);
        case SyntaxKind.ObjectLiteralSpreadProperty:
            return printObjectLiteralSpreadProperty(path, options, print);
        case SyntaxKind.ArrayLiteral:
            return printArrayLiteral(path, options, print);
        case SyntaxKind.ConstStatement:
            return printConstStatement(path, options, print);
        case SyntaxKind.CallExpression:
            return printCallExpression(path, options, print);
        case SyntaxKind.StringTemplateSpan:
        case SyntaxKind.StringTemplateHead:
        case SyntaxKind.StringTemplateMiddle:
        case SyntaxKind.StringTemplateTail:
        case SyntaxKind.JsSourceFile:
        case SyntaxKind.JsNamespaceDeclaration:
        case SyntaxKind.InvalidStatement:
            return getRawText(node, options);
        default:
            return getRawText(node, options);
    }
}
function printTypeSpecScript(path, options, print) {
    const node = path.node;
    const nodeHasComments = hasComments(node, CommentCheckFlags.Dangling);
    const body = [];
    if (nodeHasComments) {
        body.push(printDanglingComments(path, options, { sameIndent: true }));
    }
    body.push(printStatementSequence(path, options, print, "statements"));
    return body;
}
function printAliasStatement(path, options, print) {
    const id = path.call(print, "id");
    const template = printTemplateParameters(path, options, print, "templateParameters");
    return ["alias ", id, template, " = ", path.call(print, "value"), ";"];
}
function printConstStatement(path, options, print) {
    const node = path.node;
    const id = path.call(print, "id");
    const type = node.type ? [": ", path.call(print, "type")] : "";
    return ["const ", id, type, " = ", path.call(print, "value"), ";"];
}
function printCallExpression(path, options, print) {
    const args = printCallLikeArgs(path, options, print);
    return [path.call(print, "target"), args];
}
function printTemplateParameters(path, options, print, propertyName) {
    const node = path.node;
    const args = node[propertyName];
    if (args.length === 0) {
        return "";
    }
    const shouldHug = args.length === 1;
    if (shouldHug) {
        return ["<", join(", ", path.map(print, propertyName)), ">"];
    }
    else {
        const body = indent([softline, join([", ", softline], path.map(print, propertyName))]);
        return group(["<", body, softline, ">"]);
    }
}
function canAttachComment(node) {
    const kind = node.kind;
    return Boolean(kind &&
        kind !== SyntaxKind.LineComment &&
        kind !== SyntaxKind.BlockComment &&
        kind !== SyntaxKind.EmptyStatement &&
        kind !== SyntaxKind.DocParamTag &&
        kind !== SyntaxKind.DocReturnsTag &&
        kind !== SyntaxKind.DocTemplateTag &&
        kind !== SyntaxKind.DocText &&
        kind !== SyntaxKind.DocUnknownTag &&
        !(node.flags & 8 /* NodeFlags.Synthetic */));
}
function printComment(commentPath, options) {
    const comment = commentPath.node;
    comment.printed = true;
    switch (comment.kind) {
        case SyntaxKind.BlockComment:
            return printBlockComment(commentPath, options);
        case SyntaxKind.LineComment:
            return `${options.originalText.slice(comment.pos, comment.end).trimEnd()}`;
        default:
            throw new Error(`Not a comment: ${JSON.stringify(comment)}`);
    }
}
function printBlockComment(commentPath, options) {
    const comment = commentPath.node;
    const rawComment = options.originalText.slice(comment.pos + 2, comment.end - 2);
    const printed = isIndentableBlockComment(rawComment)
        ? printIndentableBlockCommentContent(rawComment)
        : rawComment;
    return ["/*", printed, "*/"];
}
function isIndentableBlockComment(rawComment) {
    // If the comment has multiple lines and every line starts with a star
    // we can fix the indentation of each line. The stars in the `/*` and
    // `*/` delimiters are not included in the comment value, so add them
    // back first.
    const lines = `*${rawComment}*`.split("\n");
    return lines.length > 1 && lines.every((line) => line.trim()[0] === "*");
}
function printIndentableBlockCommentContent(rawComment) {
    const lines = rawComment.split("\n");
    return [
        join(hardline, lines.map((line, index) => index === 0
            ? line.trimEnd()
            : " " + (index < lines.length - 1 ? line.trim() : line.trimStart()))),
    ];
}
/** Print a doc comment. */
function printDoc(path, options, print) {
    const node = path.node;
    const rawComment = options.originalText.slice(node.pos + 3, node.end - 2);
    const printed = isIndentableBlockComment(rawComment)
        ? printIndentableBlockCommentContent(rawComment)
        : rawComment.includes("\n")
            ? rawComment
            : ` ${rawComment.trim()} `;
    return ["/**", printed, "*/"];
}
function printDecorators(path, options, print, { tryInline }) {
    const node = path.node;
    if (node.decorators.length === 0) {
        return { decorators: "", multiline: false };
    }
    const shouldBreak = shouldDecoratorBreakLine(path, options, { tryInline });
    const decorators = path.map((x) => [print(x), ifBreak(line, " ")], "decorators");
    return {
        decorators: group([shouldBreak ? breakParent : "", decorators]),
        multiline: shouldBreak,
    };
}
/** Check if the decorators of the given node should be broken in sparate line */
function shouldDecoratorBreakLine(path, options, { tryInline }) {
    const node = path.node;
    return (!tryInline || node.decorators.length >= 3 || hasNewlineBetweenOrAfterDecorators(node, options));
}
/**
 * Check if there is already new lines in between the decorators of the node.
 */
function hasNewlineBetweenOrAfterDecorators(node, options) {
    return node.decorators.some((decorator) => util.hasNewline(options.originalText, decorator.end));
}
function printDecorator(path, options, print) {
    const args = printDecoratorArgs(path, options, print);
    return ["@", path.call(print, "target"), args];
}
function printAugmentDecorator(path, options, print) {
    const args = printAugmentDecoratorArgs(path, options, print);
    return ["@@", path.call(print, "target"), args, ";"];
}
function printAugmentDecoratorArgs(path, options, print) {
    return [
        "(",
        group([
            indent(join(", ", [
                path.call(print, "targetType"),
                ...path.map((arg) => [softline, print(arg)], "arguments"),
            ])),
            softline,
        ]),
        ")",
    ];
}
function printDocComments(path, options, print) {
    const node = path.node;
    if (node.docs === undefined || node.docs.length === 0) {
        return "";
    }
    const docs = path.map((x) => [print(x), line], "docs");
    return group([...docs, breakParent]);
}
function printDirectives(path, options, print) {
    const node = path.node;
    if (node.directives === undefined || node.directives.length === 0) {
        return "";
    }
    const directives = path.map((x) => [print(x), line], "directives");
    return group([...directives, breakParent]);
}
function printDirective(path, options, print) {
    const args = printDirectiveArgs(path, options, print);
    return ["#", path.call(print, "target"), " ", args];
}
function printDecoratorArgs(path, options, print) {
    const node = path.node;
    if (node.arguments.length === 0) {
        return "";
    }
    return printCallLikeArgs(path, options, print);
}
function printCallLikeArgs(path, options, print) {
    const node = path.node;
    // So that decorator with single object arguments have ( and { hugging.
    // @deco(#{
    //   value: "foo"
    // })
    const shouldHug = node.arguments.length === 1 &&
        (node.arguments[0].kind === SyntaxKind.ModelExpression ||
            node.arguments[0].kind === SyntaxKind.ObjectLiteral ||
            node.arguments[0].kind === SyntaxKind.ArrayLiteral ||
            node.arguments[0].kind === SyntaxKind.StringLiteral ||
            node.arguments[0].kind === SyntaxKind.StringTemplateExpression);
    if (shouldHug) {
        return [
            "(",
            join(", ", path.map((arg) => [print(arg)], "arguments")),
            ")",
        ];
    }
    return [
        "(",
        group([
            indent(join(", ", path.map((arg) => [softline, print(arg)], "arguments"))),
            softline,
        ]),
        ")",
    ];
}
function printDirectiveArgs(path, options, print) {
    const node = path.node;
    if (node.arguments.length === 0) {
        return "";
    }
    return join(" ", path.map((arg) => [print(arg)], "arguments"));
}
function printEnumStatement(path, options, print) {
    const { decorators } = printDecorators(path, options, print, { tryInline: false });
    const id = path.call(print, "id");
    return [decorators, "enum ", id, " ", printEnumBlock(path, options, print)];
}
function printEnumBlock(path, options, print) {
    const node = path.node;
    if (node.members.length === 0) {
        return "{}";
    }
    const body = joinMembersInBlock(path, "members", options, print, ",", hardline);
    return group(["{", indent(body), hardline, "}"]);
}
function printEnumMember(path, options, print) {
    const node = path.node;
    const id = path.call(print, "id");
    const value = node.value ? [": ", path.call(print, "value")] : "";
    const { decorators } = printDecorators(path, options, print, {
        tryInline: DecoratorsTryInline.enumMember,
    });
    return [decorators, id, value];
}
function printEnumSpreadMember(path, options, print) {
    return ["...", path.call(print, "target")];
}
function printUnionStatement(path, options, print) {
    const id = path.call(print, "id");
    const { decorators } = printDecorators(path, options, print, { tryInline: false });
    const generic = printTemplateParameters(path, options, print, "templateParameters");
    return [decorators, "union ", id, generic, " ", printUnionVariantsBlock(path, options, print)];
}
function printUnionVariantsBlock(path, options, print) {
    const node = path.node;
    if (node.options.length === 0) {
        return "{}";
    }
    const body = joinMembersInBlock(path, "options", options, print, ",", hardline);
    return group(["{", indent(body), hardline, "}"]);
}
function printUnionVariant(path, options, print) {
    const id = path.node.id === undefined ? "" : [path.call(print, "id"), ": "];
    const { decorators } = printDecorators(path, options, print, {
        tryInline: DecoratorsTryInline.unionVariant,
    });
    return [decorators, id, path.call(print, "value")];
}
function printInterfaceStatement(path, options, print) {
    const id = path.call(print, "id");
    const { decorators } = printDecorators(path, options, print, { tryInline: false });
    const generic = printTemplateParameters(path, options, print, "templateParameters");
    const extendList = printInterfaceExtends(path, options, print);
    return [
        decorators,
        "interface ",
        id,
        generic,
        extendList,
        " ",
        printInterfaceMembers(path, options, print),
    ];
}
function printInterfaceExtends(path, options, print) {
    const node = path.node;
    if (node.extends.length === 0) {
        return "";
    }
    const keyword = "extends ";
    return [group(indent([line, keyword, indent(join([",", line], path.map(print, "extends")))]))];
}
function printInterfaceMembers(path, options, print) {
    const node = path.node;
    const hasOperations = node.operations.length > 0;
    const nodeHasComments = hasComments(node, CommentCheckFlags.Dangling);
    if (!hasOperations && !nodeHasComments) {
        return "{}";
    }
    const lastOperation = node.operations[node.operations.length - 1];
    const parts = [];
    path.each((operationPath) => {
        const node = operationPath.node;
        const printed = print(operationPath);
        parts.push(printed);
        if (node !== lastOperation) {
            parts.push(hardline);
            if (isNextLineEmpty(options.originalText, node, options.locEnd)) {
                parts.push(hardline);
            }
        }
    }, "operations");
    const body = [hardline, parts];
    if (nodeHasComments) {
        body.push(printDanglingComments(path, options, { sameIndent: true }));
    }
    return group(["{", indent(body), hardline, "}"]);
}
function printDanglingComments(path, options, { sameIndent }) {
    const node = path.node;
    const parts = [];
    if (!node || !node.comments) {
        return "";
    }
    path.each((commentPath) => {
        const comment = commentPath.node;
        if (!comment.leading && !comment.trailing) {
            parts.push(printComment(path, options));
        }
    }, "comments");
    if (parts.length === 0) {
        return "";
    }
    if (sameIndent) {
        return join(hardline, parts);
    }
    return indent([hardline, join(hardline, parts)]);
}
/**
 * Handle printing an intersection node.
 * @example `Foo & Bar` or `{foo: string} & {bar: string}`
 *
 * @param path Prettier AST Path.
 * @param options Prettier options
 * @param print Prettier child print callback.
 * @returns Prettier document.
 */
function printIntersection(path, options, print) {
    const node = path.node;
    const types = path.map(print, "options");
    const result = [];
    let wasIndented = false;
    for (let i = 0; i < types.length; ++i) {
        if (i === 0) {
            result.push(types[i]);
        }
        else if (isModelNode(node.options[i - 1]) && isModelNode(node.options[i])) {
            // If both are objects, don't indent
            result.push([" & ", wasIndented ? indent(types[i]) : types[i]]);
        }
        else if (!isModelNode(node.options[i - 1]) && !isModelNode(node.options[i])) {
            // If no object is involved, go to the next line if it breaks
            result.push(indent([" &", line, types[i]]));
        }
        else {
            // If you go from object to non-object or vis-versa, then inline it
            if (i > 1) {
                wasIndented = true;
            }
            result.push(" & ", i > 1 ? indent(types[i]) : types[i]);
        }
    }
    return group(result);
}
function isModelNode(node) {
    return node.kind === SyntaxKind.ModelExpression;
}
function printArray(path, options, print) {
    return [path.call(print, "elementType"), "[]"];
}
function printTuple(path, options, print) {
    return group([
        "[",
        indent(join(", ", path.map((arg) => [softline, print(arg)], "values"))),
        softline,
        "]",
    ]);
}
function printMemberExpression(path, options, print) {
    const node = path.node;
    return [node.base ? [path.call(print, "base"), node.selector] : "", path.call(print, "id")];
}
function printModelExpression(path, options, print) {
    const inBlock = isModelExpressionInBlock(path);
    const node = path.node;
    if (inBlock) {
        return group(printModelPropertiesBlock(path, options, print));
    }
    else {
        const properties = node.properties.length === 0
            ? ""
            : indent(joinMembersInBlock(path, "properties", options, print, ifBreak(",", ", "), softline));
        return group([properties, softline]);
    }
}
function printObjectLiteral(path, options, print) {
    const node = path.node;
    const hasProperties = node.properties && node.properties.length > 0;
    const nodeHasComments = hasComments(node, CommentCheckFlags.Dangling);
    if (!hasProperties && !nodeHasComments) {
        return "#{}";
    }
    const lineDoc = softline;
    const body = [
        joinMembersInBlock(path, "properties", options, print, ifBreak(",", ", "), softline),
    ];
    if (nodeHasComments) {
        body.push(printDanglingComments(path, options, { sameIndent: true }));
    }
    return group(["#{", ifBreak("", " "), indent(body), lineDoc, ifBreak("", " "), "}"]);
}
function printObjectLiteralProperty(path, options, print) {
    const node = path.node;
    const id = printIdentifier(node.id);
    return [printDirectives(path, options, print), id, ": ", path.call(print, "value")];
}
function printObjectLiteralSpreadProperty(path, options, print) {
    return [printDirectives(path, options, print), "...", path.call(print, "target")];
}
function printArrayLiteral(path, options, print) {
    return group([
        "#[",
        indent(join(", ", path.map((arg) => [softline, print(arg)], "values"))),
        softline,
        "]",
    ]);
}
function printModelStatement(path, options, print) {
    const node = path.node;
    const id = path.call(print, "id");
    const heritage = node.extends
        ? [ifBreak(line, " "), "extends ", path.call(print, "extends")]
        : "";
    const isBase = node.is ? [ifBreak(line, " "), "is ", path.call(print, "is")] : "";
    const generic = printTemplateParameters(path, options, print, "templateParameters");
    const nodeHasComments = hasComments(node, CommentCheckFlags.Dangling);
    const shouldPrintBody = nodeHasComments || !(node.properties.length === 0 && node.is);
    const body = shouldPrintBody ? [" ", printModelPropertiesBlock(path, options, print)] : ";";
    return [
        printDecorators(path, options, print, { tryInline: false }).decorators,
        "model ",
        id,
        generic,
        group(indent(["", heritage, isBase])),
        body,
    ];
}
function printModelPropertiesBlock(path, options, print) {
    const node = path.node;
    const hasProperties = node.properties && node.properties.length > 0;
    const nodeHasComments = hasComments(node, CommentCheckFlags.Dangling);
    if (!hasProperties && !nodeHasComments) {
        return "{}";
    }
    const tryInline = path.getParentNode()?.kind === SyntaxKind.TemplateParameterDeclaration;
    const lineDoc = tryInline ? softline : hardline;
    const seperator = isModelAValue(path) ? "," : ";";
    const body = [joinMembersInBlock(path, "properties", options, print, seperator, lineDoc)];
    if (nodeHasComments) {
        body.push(printDanglingComments(path, options, { sameIndent: true }));
    }
    return group(["{", indent(body), lineDoc, "}"]);
}
/**
 * Join members nodes that are in a block by adding extra new lines when needed.(e.g. when there are decorators or doc comments )
 * @param path Prettier AST Path.
 * @param options Prettier options
 * @param print Prettier print callback
 * @param separator Separator
 * @param regularLine What line to use when we should split lines
 * @returns
 */
function joinMembersInBlock(path, member, options, print, separator, regularLine = hardline) {
    const doc = [regularLine];
    const propertyContainerNode = path.node;
    let newLineBeforeNextProp = false;
    path.each((item, propertyIndex) => {
        const isFirst = propertyIndex === 0;
        const isLast = propertyIndex === propertyContainerNode[member].length - 1;
        const shouldWrapInNewLines = shouldWrapMemberInNewLines(item, options);
        if ((newLineBeforeNextProp || shouldWrapInNewLines) && !isFirst) {
            doc.push(hardline);
            newLineBeforeNextProp = false;
        }
        doc.push(print(item));
        if (isLast) {
            doc.push(ifBreak(separator));
        }
        else {
            doc.push(separator);
            doc.push(regularLine);
            if (shouldWrapInNewLines) {
                newLineBeforeNextProp = true;
            }
        }
    }, member);
    return doc;
}
/**
 * Check if property item (PropertyNode, SpreadProperty) should be wrapped in new lines.
 * It can be wrapped for the following reasons:
 * - has decorators on lines above
 * - has leading comments
 */
function shouldWrapMemberInNewLines(path, options) {
    const node = path.node;
    return ((node.kind !== SyntaxKind.ModelSpreadProperty &&
        node.kind !== SyntaxKind.ProjectionModelSpreadProperty &&
        node.kind !== SyntaxKind.EnumSpreadMember &&
        node.kind !== SyntaxKind.ScalarConstructor &&
        node.kind !== SyntaxKind.ObjectLiteralProperty &&
        node.kind !== SyntaxKind.ObjectLiteralSpreadProperty &&
        shouldDecoratorBreakLine(path, options, {
            tryInline: DecoratorsTryInline.modelProperty,
        })) ||
        hasComments(node, CommentCheckFlags.Leading) ||
        (node.docs && node.docs?.length > 0));
}
/**
 * Figure out if this model is being used as a definition or value.
 * @returns true if the model is used as a value(e.g. decorator value), false if it is used as a model definition.
 */
function isModelAValue(path) {
    let count = 0;
    let node = path.node;
    do {
        switch (node.kind) {
            case SyntaxKind.ModelStatement:
            case SyntaxKind.AliasStatement:
            case SyntaxKind.OperationStatement:
                return false;
            case SyntaxKind.DecoratorExpression:
                return true;
        }
    } while ((node = path.getParentNode(count++)));
    return true;
}
function printModelProperty(path, options, print) {
    const node = path.node;
    const { decorators } = printDecorators(path, options, print, {
        tryInline: DecoratorsTryInline.modelProperty,
    });
    const id = printIdentifier(node.id);
    return [
        printDirectives(path, options, print),
        decorators,
        id,
        node.optional ? "?: " : ": ",
        path.call(print, "value"),
        node.default ? [" = ", path.call(print, "default")] : "",
    ];
}
function printIdentifier(id, options) {
    return printIdentifier$1(id.sv);
}
function isModelExpressionInBlock(path) {
    const parent = path.getParentNode();
    switch (parent?.kind) {
        case SyntaxKind.OperationSignatureDeclaration:
            return parent.parameters !== path.getNode();
        default:
            return true;
    }
}
function printScalarStatement(path, options, print) {
    const node = path.node;
    const id = path.call(print, "id");
    const template = printTemplateParameters(path, options, print, "templateParameters");
    const heritage = node.extends
        ? [ifBreak(line, " "), "extends ", path.call(print, "extends")]
        : "";
    const nodeHasComments = hasComments(node, CommentCheckFlags.Dangling);
    const shouldPrintBody = nodeHasComments || !(node.members.length === 0);
    const members = shouldPrintBody ? [" ", printScalarBody(path, options, print)] : ";";
    return [
        printDecorators(path, options, print, { tryInline: false }).decorators,
        "scalar ",
        id,
        template,
        group(indent(["", heritage])),
        members,
    ];
}
function printScalarBody(path, options, print) {
    const node = path.node;
    const hasProperties = node.members && node.members.length > 0;
    const nodeHasComments = hasComments(node, CommentCheckFlags.Dangling);
    if (!hasProperties && !nodeHasComments) {
        return "{}";
    }
    const body = [joinMembersInBlock(path, "members", options, print, ";", hardline)];
    if (nodeHasComments) {
        body.push(printDanglingComments(path, options, { sameIndent: true }));
    }
    return group(["{", indent(body), hardline, "}"]);
}
function printScalarConstructor(path, options, print) {
    const id = path.call(print, "id");
    const parameters = [
        group([
            indent(join(", ", path.map((arg) => [softline, print(arg)], "parameters"))),
            softline,
        ]),
    ];
    return ["init ", id, "(", parameters, ")"];
}
function printNamespaceStatement(path, options, print) {
    const names = path.map(print, "ids");
    const currentNode = path.getNode();
    const suffix = currentNode?.statements === undefined
        ? ";"
        : [
            " {",
            indent([hardline, printStatementSequence(path, options, print, "statements")]),
            hardline,
            "}",
        ];
    const { decorators } = printDecorators(path, options, print, { tryInline: false });
    return [decorators, `namespace `, join(".", names), suffix];
}
function printOperationSignatureDeclaration(path, options, print) {
    return ["(", path.call(print, "parameters"), "): ", path.call(print, "returnType")];
}
function printOperationSignatureReference(path, options, print) {
    return [" is ", path.call(print, "baseOperation")];
}
function printOperationStatement(path, options, print) {
    const inInterface = path.getParentNode()?.kind === SyntaxKind.InterfaceStatement;
    const templateParams = printTemplateParameters(path, options, print, "templateParameters");
    const { decorators } = printDecorators(path, options, print, {
        tryInline: true,
    });
    return [
        decorators,
        inInterface ? "" : "op ",
        path.call(print, "id"),
        templateParams,
        path.call(print, "signature"),
        `;`,
    ];
}
function printStatementSequence(path, options, print, property) {
    const node = path.node;
    const parts = [];
    const lastStatement = getLastStatement(node[property]);
    path.each((statementPath) => {
        const node = path.node;
        if (node.kind === SyntaxKind.EmptyStatement) {
            return;
        }
        const printed = print(statementPath);
        parts.push(printed);
        if (node !== lastStatement) {
            parts.push(hardline);
            if (isNextLineEmpty(options.originalText, node, options.locEnd)) {
                parts.push(hardline);
            }
        }
    }, property);
    return parts;
}
function getLastStatement(statements) {
    for (let i = statements.length - 1; i >= 0; i--) {
        const statement = statements[i];
        if (statement.kind !== SyntaxKind.EmptyStatement) {
            return statement;
        }
    }
    return undefined;
}
function printUnion(path, options, print) {
    const node = path.node;
    const shouldHug = shouldHugType(node);
    const types = path.map((typePath) => {
        let printedType = print(typePath);
        if (!shouldHug) {
            printedType = align(2, printedType);
        }
        return printedType;
    }, "options");
    if (shouldHug) {
        return join(" | ", types);
    }
    const code = [ifBreak([line , "| "], ""), join([line, "| "], types)];
    return group(indent(code));
}
function shouldHugType(node) {
    if (node.kind === SyntaxKind.UnionExpression || node.kind === SyntaxKind.IntersectionExpression) {
        return node.options.length < 4;
    }
    return false;
}
function printTypeReference(path, options, print) {
    const type = path.call(print, "target");
    const template = printTemplateParameters(path, options, print, "arguments");
    return [type, template];
}
function printTemplateArgument(path, _options, print) {
    if (path.node.name !== undefined) {
        const name = path.call(print, "name");
        const argument = path.call(print, "argument");
        return group([name, " = ", argument]);
    }
    else {
        return path.call(print, "argument");
    }
}
function printValueOfExpression(path, options, print) {
    const type = path.call(print, "target");
    return ["valueof ", type];
}
function printTypeOfExpression(path, options, print) {
    const type = path.call(print, "target");
    return ["typeof ", type];
}
function printTemplateParameterDeclaration(path, options, print) {
    const node = path.node;
    return [
        path.call(print, "id"),
        node.constraint ? [" extends ", path.call(print, "constraint")] : "",
        node.default ? [" = ", path.call(print, "default")] : "",
    ];
}
function printModelSpread(path, options, print) {
    return ["...", path.call(print, "target")];
}
function printDecoratorDeclarationStatement(path, options, print) {
    const id = path.call(print, "id");
    const parameters = [
        group([
            indent(join(", ", [
                [softline, path.call(print, "target")],
                ...path.map((arg) => [softline, print(arg)], "parameters"),
            ])),
            softline,
        ]),
    ];
    return [printModifiers(path, options, print), "dec ", id, "(", parameters, ")", ";"];
}
function printFunctionDeclarationStatement(path, options, print) {
    const node = path.node;
    const id = path.call(print, "id");
    const parameters = [
        group([
            indent(join(", ", path.map((arg) => [softline, print(arg)], "parameters"))),
            softline,
        ]),
    ];
    const returnType = node.returnType ? [": ", path.call(print, "returnType")] : "";
    return [printModifiers(path, options, print), "fn ", id, "(", parameters, ")", returnType, ";"];
}
function printFunctionParameterDeclaration(path, options, print) {
    const node = path.node;
    const id = path.call(print, "id");
    const type = node.type ? [": ", path.call(print, "type")] : "";
    return [
        node.rest ? "..." : "",
        printDirectives(path, options, print),
        id,
        node.optional ? "?" : "",
        type,
    ];
}
function printModifiers(path, options, print) {
    const node = path.node;
    if (node.modifiers.length === 0) {
        return "";
    }
    return path.map((x) => [print(x), " "], "modifiers");
}
function printStringLiteral(path, options) {
    const node = path.node;
    const multiline = isMultiline(node, options);
    const raw = getRawText(node, options);
    if (multiline) {
        const lines = splitLines(raw.slice(3));
        const whitespaceIndent = lines[lines.length - 1].length - 3;
        const newLines = trimMultilineString(lines, whitespaceIndent);
        return [`"""`, indent(markAsRoot(newLines))];
    }
    else {
        return raw;
    }
}
function isMultiline(node, options) {
    return (options.originalText[node.pos] &&
        options.originalText[node.pos + 1] === `"` &&
        options.originalText[node.pos + 2] === `"`);
}
function printNumberLiteral(path, options) {
    const node = path.node;
    return getRawText(node, options);
}
function printBooleanLiteral(path, options) {
    const node = path.node;
    return node.value ? "true" : "false";
}
function printProjectionStatement(path, options, print) {
    const selector = path.call(print, "selector");
    const id = path.call(print, "id");
    const projections = path.map(print, "projections").flatMap((x) => [hardline, x]);
    return [
        "projection ",
        selector,
        "#",
        id,
        " {",
        indent(projections),
        projections.length > 0 ? hardline : "",
        "}",
    ];
}
function printProjection(path, options, print) {
    const node = path.node;
    const params = printProjectionParameters(path, options, print);
    const body = printProjectionExpressionStatements(path, options, print, "body");
    return [
        ...node.modifierIds.flatMap((i) => [i.sv, " "]),
        node.directionId.sv,
        params,
        " {",
        indent(body),
        hardline,
        "}",
    ];
}
function printProjectionParameters(path, options, print) {
    const node = path.node;
    const params = node.parameters;
    if (params.length === 0) {
        return "";
    }
    const shouldHug = params.length === 1;
    if (shouldHug) {
        return ["(", printItemList(path, options, print, "parameters"), ")"];
    }
    else {
        const body = indent([softline, join([", ", softline], path.map(print, "parameters"))]);
        return group(["(", body, softline, ")"]);
    }
}
function printProjectionExpressionStatements(path, options, print, key) {
    const parts = [hardline];
    const lastIndex = path.node[key].length - 1;
    path.each((statementPath, index) => {
        const node = path.node;
        if (node.kind === SyntaxKind.EmptyStatement) {
            return;
        }
        const printed = print(statementPath);
        parts.push(printed);
        parts.push(";");
        if (index < lastIndex) {
            parts.push(hardline);
            if (isNextLineEmpty(options.originalText, node, options.locEnd)) {
                parts.push(hardline);
            }
        }
    }, key);
    return parts;
}
function printProjectionParameterDeclaration(path, options, print) {
    return path.call(print, "id");
}
function printProjectionExpressionStatement(path, options, print) {
    return path.call(print, "expr");
}
function printProjectionIfExpressionNode(path, options, print) {
    const node = path.node;
    const test = path.call(print, "test");
    const consequent = path.call(print, "consequent");
    const alternate = node.alternate ? [" else ", path.call(print, "alternate")] : "";
    return ["if ", test, " ", consequent, alternate];
}
function printProjectionBlockExpressionNode(path, options, print) {
    const node = path.node;
    if (node.statements.length === 0) {
        return "{}";
    }
    return [
        "{",
        indent(printProjectionExpressionStatements(path, options, print, "statements")),
        hardline,
        "}",
    ];
}
function printProjectionMemberExpression(path, options, print) {
    const node = path.node;
    return [path.call(print, "base"), node.selector, path.call(print, "id")];
}
function printProjectionLeftRightExpression(path, options, print) {
    const node = path.node;
    return [path.call(print, "left"), " ", node.op, " ", path.call(print, "right")];
}
function printProjectionUnaryExpression(path, options, print) {
    return ["!", path.call(print, "target")];
}
function printProjectionCallExpression(path, options, print) {
    const node = path.node;
    const target = path.call(print, "target");
    const params = printItemList(path, options, print, "arguments");
    if (node.callKind === "method") {
        return [target, "(", params, ")"];
    }
    else {
        return [target, "<", params, ">"];
    }
}
function printProjectionLambdaExpression(path, options, print) {
    return [
        "(",
        printItemList(path, options, print, "parameters"),
        ")",
        " => ",
        path.call(print, "body"),
    ];
}
function printProjectionLambdaParameterDeclaration(path, options, print) {
    return path.call(print, "id");
}
function printReturnExpression(path, options, print) {
    return ["return ", path.call(print, "value")];
}
function printStringTemplateExpression(path, options, print) {
    const node = path.node;
    const multiline = isMultiline(node, options);
    const rawHead = getRawText(node.head, options);
    if (multiline) {
        const lastSpan = node.spans[node.spans.length - 1];
        const lastLines = splitLines(getRawText(lastSpan.literal, options));
        const whitespaceIndent = lastLines[lastLines.length - 1].length - 3;
        const content = [
            trimMultilineString(splitLines(rawHead.slice(3)), whitespaceIndent),
            path.map((span) => {
                const expression = span.call(print, "expression");
                const spanRawText = getRawText(span.node.literal, options);
                const spanLines = splitLines(spanRawText);
                return [
                    expression,
                    spanLines[0],
                    literalline,
                    trimMultilineString(spanLines.slice(1), whitespaceIndent),
                ];
            }, "spans"),
        ];
        return [`"""`, indent(markAsRoot([content]))];
    }
    else {
        const content = [
            rawHead,
            path.map((span) => {
                const expression = span.call(print, "expression");
                return [expression, getRawText(span.node.literal, options)];
            }, "spans"),
        ];
        return content;
    }
}
function splitLines(text) {
    const lines = [];
    let start = 0;
    let pos = 0;
    while (pos < text.length) {
        const ch = text.charCodeAt(pos);
        switch (ch) {
            case 13 /* CharCode.CarriageReturn */:
                if (text.charCodeAt(pos + 1) === 10 /* CharCode.LineFeed */) {
                    lines.push(text.slice(start, pos));
                    start = pos;
                    pos++;
                }
                else {
                    lines.push(text.slice(start, pos));
                    start = pos;
                }
                break;
            case 10 /* CharCode.LineFeed */:
                lines.push(text.slice(start, pos));
                start = pos;
                break;
        }
        pos++;
    }
    lines.push(text.slice(start));
    return lines;
}
function trimMultilineString(lines, whitespaceIndent) {
    const newLines = [];
    for (let i = 0; i < lines.length; i++) {
        newLines.push(lines[i].slice(whitespaceIndent));
        if (i < lines.length - 1) {
            newLines.push(literalline);
        }
    }
    return newLines;
}
function printItemList(path, options, print, key) {
    return join(", ", path.map(print, key));
}
/**
 * @param node Node that has postition information.
 * @param options Prettier options
 * @returns Raw text in the file for the given node.
 */
function getRawText(node, options) {
    return options.originalText.slice(node.pos, node.end);
}
function hasComments(node, flags) {
    if (!node.comments || node.comments.length === 0) {
        return false;
    }
    const test = getCommentTestFunction(flags);
    return test ? node.comments.some(test) : true;
}
var CommentCheckFlags;
(function (CommentCheckFlags) {
    /** Check comment is a leading comment */
    CommentCheckFlags[CommentCheckFlags["Leading"] = 2] = "Leading";
    /** Check comment is a trailing comment */
    CommentCheckFlags[CommentCheckFlags["Trailing"] = 4] = "Trailing";
    /** Check comment is a dangling comment */
    CommentCheckFlags[CommentCheckFlags["Dangling"] = 8] = "Dangling";
    /** Check comment is a block comment */
    CommentCheckFlags[CommentCheckFlags["Block"] = 16] = "Block";
    /** Check comment is a line comment */
    CommentCheckFlags[CommentCheckFlags["Line"] = 32] = "Line";
    /** Check comment is a `prettier-ignore` comment */
    CommentCheckFlags[CommentCheckFlags["PrettierIgnore"] = 64] = "PrettierIgnore";
    /** Check comment is the first attached comment */
    CommentCheckFlags[CommentCheckFlags["First"] = 128] = "First";
    /** Check comment is the last attached comment */
    CommentCheckFlags[CommentCheckFlags["Last"] = 256] = "Last";
})(CommentCheckFlags || (CommentCheckFlags = {}));
function getCommentTestFunction(flags) {
    if (flags) {
        return (comment, index, comments) => !((flags & CommentCheckFlags.Leading && !comment.leading) ||
            (flags & CommentCheckFlags.Trailing && !comment.trailing) ||
            (flags & CommentCheckFlags.Dangling && (comment.leading || comment.trailing)) ||
            (flags & CommentCheckFlags.Block && !isBlockComment(comment)) ||
            (flags & CommentCheckFlags.Line && !isLineComment(comment)) ||
            (flags & CommentCheckFlags.First && index !== 0) ||
            (flags & CommentCheckFlags.Last && index !== comments.length - 1));
    }
    return undefined;
}
function isBlockComment(comment) {
    return comment.kind === SyntaxKind.BlockComment;
}
function isLineComment(comment) {
    return comment.kind === SyntaxKind.BlockComment;
}

/**
 * This is a map type that allows providing a custom keyer function. The keyer
 * function returns a string that is used to look up in the map. This is useful
 * for implementing maps that look up based on an arbitrary number of keys.
 *
 * For example, to look up in a map with a [ObjA, ObjB)] tuple, such that tuples
 * with identical values (but not necessarily identical tuples!) create an
 * object keyer for each of the objects:
 *
 *     const aKeyer = CustomKeyMap.objectKeyer();
 *     const bKeyer = CUstomKeyMap.objectKeyer();
 *
 * And compose these into a tuple keyer to use when instantiating the custom key
 * map:
 *
 *     const tupleKeyer = ([a, b]) => `${aKeyer.getKey(a)}-${bKeyer.getKey(b)}`;
 *     const map = new CustomKeyMap(tupleKeyer);
 *
 */
class CustomKeyMap {
    #items = new Map();
    #keyer;
    constructor(keyer) {
        this.#keyer = keyer;
    }
    get(items) {
        return this.#items.get(this.#keyer(items));
    }
    set(items, value) {
        const key = this.#keyer(items);
        this.#items.set(key, value);
    }
    static objectKeyer() {
        const knownKeys = new WeakMap();
        let count = 0;
        return {
            getKey(o) {
                if (knownKeys.has(o)) {
                    return knownKeys.get(o);
                }
                const key = count;
                count++;
                knownKeys.set(o, key);
                return key;
            },
        };
    }
}

/**
 * Keeps track of a value we don't know yet because of a circular reference. Use
 * the `onValue` method to provide a callback with how to handle the
 * placeholder's value becoming available. Generally the callback will replace
 * this placeholder with the value in whatever references the placeholder.
 */
class Placeholder {
    #listeners = [];
    setValue(value) {
        for (const listener of this.#listeners) {
            listener(value);
        }
    }
    onValue(cb) {
        this.#listeners.push(cb);
    }
}

function scopeChain(scope) {
    const chain = [];
    while (scope) {
        chain.unshift(scope);
        scope = scope.parentScope;
    }
    return chain;
}
/**
 * Resolve relative scopes between the current scope and the target declaration.
 * @param target The target declaration
 * @param currentScope Current scope
 * @returns
 */
function resolveDeclarationReferenceScope(target, currentScope) {
    const targetScope = target.scope;
    const targetChain = scopeChain(targetScope);
    const currentChain = scopeChain(currentScope);
    let diffStart = 0;
    while (targetChain[diffStart] &&
        currentChain[diffStart] &&
        targetChain[diffStart] === currentChain[diffStart]) {
        diffStart++;
    }
    const pathUp = currentChain.slice(diffStart);
    const pathDown = targetChain.slice(diffStart);
    const commonScope = targetChain[diffStart - 1] ?? null;
    return { pathUp, pathDown, commonScope };
}

/**
 * Represent a reference cycle.
 * The cycle entries will always start with a declaration if there is one in the cycle.
 */
class ReferenceCycle {
    /**
     * If this cycle contains a declaration.
     */
    containsDeclaration;
    #entries;
    constructor(entries) {
        const firstDeclarationIndex = entries.findIndex((entry) => entry.entity.kind === "declaration");
        this.containsDeclaration = firstDeclarationIndex !== -1;
        this.#entries = this.containsDeclaration
            ? [...entries.slice(firstDeclarationIndex), ...entries.slice(0, firstDeclarationIndex)]
            : entries;
    }
    get first() {
        return this.#entries[0];
    }
    [Symbol.iterator]() {
        return this.#entries[Symbol.iterator]();
    }
    [Symbol.toStringTag]() {
        return [...this.#entries, this.#entries[0]].map((x) => getTypeName(x.type)).join(" -> ");
    }
    toString() {
        return this[Symbol.toStringTag]();
    }
}

class EmitterResult {
}
class Declaration extends EmitterResult {
    name;
    scope;
    value;
    kind = "declaration";
    meta = {};
    constructor(name, scope, value) {
        if (value instanceof Placeholder) {
            value.onValue((v) => (this.value = v));
        }
        super();
        this.name = name;
        this.scope = scope;
        this.value = value;
    }
}
class RawCode extends EmitterResult {
    value;
    kind = "code";
    constructor(value) {
        if (value instanceof Placeholder) {
            value.onValue((v) => (this.value = v));
        }
        super();
        this.value = value;
    }
}
class NoEmit extends EmitterResult {
    kind = "none";
}
class CircularEmit extends EmitterResult {
    emitEntityKey;
    kind = "circular";
    constructor(emitEntityKey) {
        super();
        this.emitEntityKey = emitEntityKey;
    }
}

function createAssetEmitter(program, TypeEmitterClass, emitContext) {
    const sourceFiles = [];
    const options = {
        noEmit: program.compilerOptions.noEmit ?? false,
        emitterOutputDir: emitContext.emitterOutputDir,
        ...emitContext.options,
    };
    const typeId = CustomKeyMap.objectKeyer();
    const contextId = CustomKeyMap.objectKeyer();
    const entryId = CustomKeyMap.objectKeyer();
    // This is effectively a seen set, ensuring that we don't emit the same
    // type with the same context twice. So the map stores a triple of:
    //
    // 1. the method of TypeEmitter we would call
    // 2. the tsp type we're emitting.
    // 3. the current context.
    //
    // Note that in order for this to work, context needs to be interned so
    // contexts with the same values inside are treated as identical in the
    // map. See createInterner for more details.
    const typeToEmitEntity = new CustomKeyMap(([method, type, context]) => {
        return `${method}-${typeId.getKey(type)}-${contextId.getKey(context)}`;
    });
    // When we encounter a circular reference, this map will hold a callback
    // that should be called when the circularly referenced type has completed
    // its emit.
    const waitingCircularRefs = new CustomKeyMap(([method, type, context]) => {
        return `${method}-${typeId.getKey(type)}-${contextId.getKey(context)}`;
    });
    // Similar to `typeToEmitEntity`, this ensures we don't recompute context
    // for types that we already have context for. Note that context is
    // dependent on the context of the context call, e.g. if a model is
    // referenced with reference context set we need to get its declaration
    // context again. So we use the context's context as a key. Context must
    // be interned, see createInterner for more details.
    const knownContexts = new CustomKeyMap(([entry, context]) => {
        return `${entryId.getKey(entry)}-${contextId.getKey(context)}`;
    });
    // The stack of types that the currently emitted type is lexically
    // contained in. This gets pushed to when we visit a type that is
    // lexically contained in the current type, and is reset when we jump via
    // reference to another type in a different lexical context. Note that
    // this does not correspond to tsp's lexical nesting, e.g. in the case of
    // an alias to a model expression, the alias is lexically outside the
    // model, but in the type graph we will consider it to be lexically inside
    // whatever references the alias.
    let lexicalTypeStack = [];
    let referenceTypeChain = [];
    // Internally, context is is split between lexicalContext and
    // referenceContext because when a reference is made, we carry over
    // referenceContext but leave lexical context behind. When context is
    // accessed by the user, they are merged by getContext().
    let context = {
        lexicalContext: {},
        referenceContext: {},
    };
    let programContext = null;
    // Incoming reference context is reference context that comes from emitting a
    // type reference. Incoming reference context is only set on the
    // incomingReferenceContextTarget and types lexically contained within it. For
    // example, when referencing a model with reference context set, we may need
    // to get context from the referenced model's namespaces, and such namespaces
    // will not see the reference context. However, the reference context will be
    // available for the model, its properties, and any types nested within it
    // (e.g. anonymous models).
    let incomingReferenceContext = null;
    let incomingReferenceContextTarget = null;
    const stateInterner = createInterner();
    const stackEntryInterner = createInterner();
    const assetEmitter = {
        getContext() {
            return {
                ...context.lexicalContext,
                ...context.referenceContext,
            };
        },
        getOptions() {
            return options;
        },
        getProgram() {
            return program;
        },
        result: {
            declaration(name, value) {
                const scope = currentScope();
                compilerAssert(scope, "Emit context must have a scope set in order to create declarations. Consider setting scope to a new source file's global scope in the `programContext` method of `TypeEmitter`.");
                return new Declaration(name, scope, value);
            },
            rawCode(value) {
                return new RawCode(value);
            },
            none() {
                return new NoEmit();
            },
        },
        createScope(block, name, parentScope = null) {
            let newScope;
            if (!parentScope) {
                // create source file scope
                newScope = {
                    kind: "sourceFile",
                    name,
                    sourceFile: block,
                    parentScope,
                    childScopes: [],
                    declarations: [],
                };
            }
            else {
                newScope = {
                    kind: "namespace",
                    name,
                    namespace: block,
                    childScopes: [],
                    declarations: [],
                    parentScope,
                };
            }
            parentScope?.childScopes.push(newScope);
            return newScope; // the overload of createScope causes type weirdness
        },
        createSourceFile(path) {
            const basePath = options.emitterOutputDir;
            const sourceFile = {
                globalScope: undefined,
                path: joinPaths(basePath, path),
                imports: new Map(),
                meta: {},
            };
            sourceFile.globalScope = this.createScope(sourceFile, "");
            sourceFiles.push(sourceFile);
            return sourceFile;
        },
        emitTypeReference(target, options) {
            return withPatchedReferenceContext(options?.referenceContext, () => {
                const oldIncomingReferenceContext = incomingReferenceContext;
                const oldIncomingReferenceContextTarget = incomingReferenceContextTarget;
                incomingReferenceContext = context.referenceContext ?? null;
                incomingReferenceContextTarget = incomingReferenceContext ? target : null;
                let result;
                if (target.kind === "ModelProperty") {
                    result = invokeTypeEmitter("modelPropertyReference", target);
                }
                else if (target.kind === "EnumMember") {
                    result = invokeTypeEmitter("enumMemberReference", target);
                }
                if (result) {
                    incomingReferenceContext = oldIncomingReferenceContext;
                    incomingReferenceContextTarget = oldIncomingReferenceContextTarget;
                    return result;
                }
                const entity = this.emitType(target);
                incomingReferenceContext = oldIncomingReferenceContext;
                incomingReferenceContextTarget = oldIncomingReferenceContextTarget;
                let placeholder = null;
                if (entity.kind === "circular") {
                    let waiting = waitingCircularRefs.get(entity.emitEntityKey);
                    if (!waiting) {
                        waiting = [];
                        waitingCircularRefs.set(entity.emitEntityKey, waiting);
                    }
                    const typeChainSnapshot = referenceTypeChain;
                    waiting.push({
                        state: {
                            lexicalTypeStack,
                            context,
                        },
                        cb: (resolvedEntity) => invokeReference(this, resolvedEntity, true, resolveReferenceCycle(typeChainSnapshot, entity, typeToEmitEntity)),
                    });
                    placeholder = new Placeholder();
                    return this.result.rawCode(placeholder);
                }
                else {
                    return invokeReference(this, entity, false);
                }
                function invokeReference(assetEmitter, entity, circular, cycle) {
                    let ref;
                    const scope = currentScope();
                    if (circular) {
                        ref = typeEmitter.circularReference(entity, scope, cycle);
                    }
                    else {
                        if (entity.kind !== "declaration") {
                            return entity;
                        }
                        compilerAssert(scope, "Emit context must have a scope set in order to create references to declarations.");
                        const { pathUp, pathDown, commonScope } = resolveDeclarationReferenceScope(entity, scope);
                        ref = typeEmitter.reference(entity, pathUp, pathDown, commonScope);
                    }
                    if (!(ref instanceof EmitterResult)) {
                        ref = assetEmitter.result.rawCode(ref);
                    }
                    if (placeholder) {
                        // this should never happen as this function shouldn't be called until
                        // the target declaration is finished being emitted.
                        compilerAssert(ref.kind !== "circular", "TypeEmitter `reference` returned circular emit");
                        // this could presumably be allowed if we want.
                        compilerAssert(ref.kind === "none" || !(ref.value instanceof Placeholder), "TypeEmitter's `reference` method cannot return a placeholder.");
                        switch (ref.kind) {
                            case "code":
                            case "declaration":
                                placeholder.setValue(ref.value);
                                break;
                            case "none":
                                // this cast is incorrect, think about what should happen
                                // if reference returns noEmit...
                                placeholder.setValue("");
                                break;
                        }
                    }
                    return ref;
                }
            });
        },
        emitDeclarationName(type) {
            return typeEmitter.declarationName(type);
        },
        async writeOutput() {
            return typeEmitter.writeOutput(sourceFiles);
        },
        getSourceFiles() {
            return sourceFiles;
        },
        emitType(type, context) {
            if (context?.referenceContext) {
                incomingReferenceContext = context?.referenceContext ?? incomingReferenceContext;
                incomingReferenceContextTarget = type ?? incomingReferenceContextTarget;
            }
            const declName = isDeclaration(type) && type.kind !== "Namespace" ? typeEmitter.declarationName(type) : null;
            const key = typeEmitterKey(type);
            let args;
            switch (key) {
                case "scalarDeclaration":
                case "scalarInstantiation":
                case "modelDeclaration":
                case "modelInstantiation":
                case "operationDeclaration":
                case "interfaceDeclaration":
                case "interfaceOperationDeclaration":
                case "enumDeclaration":
                case "unionDeclaration":
                case "unionInstantiation":
                    args = [declName];
                    break;
                case "arrayDeclaration":
                    const arrayDeclElement = type.indexer.value;
                    args = [declName, arrayDeclElement];
                    break;
                case "arrayLiteral":
                    const arrayLiteralElement = type.indexer.value;
                    args = [arrayLiteralElement];
                    break;
                case "intrinsic":
                    args = [declName];
                    break;
                default:
                    args = [];
            }
            const result = invokeTypeEmitter(key, type, ...args);
            return result;
        },
        emitProgram(options) {
            const namespace = program.getGlobalNamespaceType();
            if (options?.emitGlobalNamespace) {
                this.emitType(namespace);
                return;
            }
            for (const ns of namespace.namespaces.values()) {
                if (ns.name === "TypeSpec" && !options?.emitTypeSpecNamespace)
                    continue;
                this.emitType(ns);
            }
            for (const model of namespace.models.values()) {
                if (!isTemplateDeclaration(model)) {
                    this.emitType(model);
                }
            }
            for (const operation of namespace.operations.values()) {
                if (!isTemplateDeclaration(operation)) {
                    this.emitType(operation);
                }
            }
            for (const enumeration of namespace.enums.values()) {
                this.emitType(enumeration);
            }
            for (const union of namespace.unions.values()) {
                if (!isTemplateDeclaration(union)) {
                    this.emitType(union);
                }
            }
            for (const iface of namespace.interfaces.values()) {
                if (!isTemplateDeclaration(iface)) {
                    this.emitType(iface);
                }
            }
            for (const scalar of namespace.scalars.values()) {
                this.emitType(scalar);
            }
        },
        emitModelProperties(model) {
            const res = invokeTypeEmitter("modelProperties", model);
            if (res instanceof EmitterResult) {
                return res;
            }
            else {
                return this.result.rawCode(res);
            }
        },
        emitModelProperty(property) {
            return invokeTypeEmitter("modelPropertyLiteral", property);
        },
        emitOperationParameters(operation) {
            return invokeTypeEmitter("operationParameters", operation, operation.parameters);
        },
        emitOperationReturnType(operation) {
            return invokeTypeEmitter("operationReturnType", operation, operation.returnType);
        },
        emitInterfaceOperations(iface) {
            return invokeTypeEmitter("interfaceDeclarationOperations", iface);
        },
        emitInterfaceOperation(operation) {
            const name = typeEmitter.declarationName(operation);
            if (name === undefined) {
                // the general approach of invoking the expression form doesn't work here
                // because TypeSpec doesn't have operation expressions.
                compilerAssert(false, "Unnamed operations are not supported");
            }
            return invokeTypeEmitter("interfaceOperationDeclaration", operation, name);
        },
        emitEnumMembers(en) {
            return invokeTypeEmitter("enumMembers", en);
        },
        emitUnionVariants(union) {
            return invokeTypeEmitter("unionVariants", union);
        },
        emitTupleLiteralValues(tuple) {
            return invokeTypeEmitter("tupleLiteralValues", tuple);
        },
        async emitSourceFile(sourceFile) {
            return await typeEmitter.sourceFile(sourceFile);
        },
    };
    const typeEmitter = new TypeEmitterClass(assetEmitter);
    return assetEmitter;
    /**
     * This function takes care of calling a method on the TypeEmitter to
     * convert it to some emitted output. It will return a cached type if we
     * have seen it before (and the context is the same). It will establish
     * the emit context by calling the appropriate methods before getting the
     * emit result. Also if a type emitter returns just a T or a
     * Placeholder<T>, it will convert that to a RawCode result.
     */
    function invokeTypeEmitter(method, ...args) {
        const type = args[0];
        let entity;
        let emitEntityKey;
        let cached = false;
        withTypeContext(method, args, () => {
            emitEntityKey = [method, type, context];
            const seenEmitEntity = typeToEmitEntity.get(emitEntityKey);
            if (seenEmitEntity) {
                entity = seenEmitEntity;
                cached = true;
                return;
            }
            typeToEmitEntity.set(emitEntityKey, new CircularEmit(emitEntityKey));
            compilerAssert(typeEmitter[method], `TypeEmitter doesn't have a method named ${method}.`);
            entity = liftToRawCode(typeEmitter[method](...args));
        });
        if (cached) {
            return entity;
        }
        if (entity instanceof Placeholder) {
            entity.onValue((v) => handleCompletedEntity(v));
            return entity;
        }
        handleCompletedEntity(entity);
        return entity;
        function handleCompletedEntity(entity) {
            typeToEmitEntity.set(emitEntityKey, entity);
            const waitingRefCbs = waitingCircularRefs.get(emitEntityKey);
            if (waitingRefCbs) {
                for (const record of waitingRefCbs) {
                    withContext(record.state, () => {
                        record.cb(entity);
                    });
                }
                waitingCircularRefs.set(emitEntityKey, []);
            }
            if (entity.kind === "declaration") {
                entity.scope.declarations.push(entity);
            }
        }
        function liftToRawCode(value) {
            if (value instanceof EmitterResult) {
                return value;
            }
            return assetEmitter.result.rawCode(value);
        }
    }
    function isInternalMethod(method) {
        return (method === "interfaceDeclarationOperations" ||
            method === "interfaceOperationDeclaration" ||
            method === "operationParameters" ||
            method === "operationReturnType" ||
            method === "modelProperties" ||
            method === "enumMembers" ||
            method === "tupleLiteralValues" ||
            method === "unionVariants");
    }
    /**
     * This helper takes a type and sets the `context` state to what it should
     * be in order to invoke the type emitter method for that type. This needs
     * to take into account the current context and any incoming reference
     * context.
     */
    function setContextForType(method, args) {
        const type = args[0];
        let newTypeStack;
        // if we've walked into a new declaration, reset the lexical type stack
        // to the lexical containers of the current type.
        if (isDeclaration(type) && type.kind !== "Intrinsic" && !isInternalMethod(method)) {
            newTypeStack = [stackEntryInterner.intern({ method, args: stackEntryInterner.intern(args) })];
            let ns = type.namespace;
            while (ns) {
                if (ns.name === "")
                    break;
                newTypeStack.unshift(stackEntryInterner.intern({ method: "namespace", args: stackEntryInterner.intern([ns]) }));
                ns = ns.namespace;
            }
        }
        else {
            newTypeStack = [
                ...lexicalTypeStack,
                stackEntryInterner.intern({ method, args: stackEntryInterner.intern(args) }),
            ];
        }
        lexicalTypeStack = newTypeStack;
        if (!programContext) {
            programContext = stateInterner.intern({
                lexicalContext: typeEmitter.programContext(program),
                referenceContext: stateInterner.intern({}),
            });
        }
        // Establish our context by starting from program and walking up the type stack
        // and merging in context for each of the lexical containers.
        context = programContext;
        for (const entry of lexicalTypeStack) {
            if (incomingReferenceContext && entry.args[0] === incomingReferenceContextTarget) {
                // bring in any reference context so it is available for any types nested beneath this type.
                context = stateInterner.intern({
                    lexicalContext: context.lexicalContext,
                    referenceContext: stateInterner.intern({
                        ...context.referenceContext,
                        ...incomingReferenceContext,
                    }),
                });
            }
            const seenContext = knownContexts.get([entry, context]);
            if (seenContext) {
                context = seenContext;
                continue;
            }
            const lexicalKey = entry.method + "Context";
            const referenceKey = entry.method + "ReferenceContext";
            if (keyHasContext(entry.method)) {
                compilerAssert(typeEmitter[lexicalKey], `TypeEmitter doesn't have a method named ${lexicalKey}`);
            }
            if (keyHasReferenceContext(entry.method)) {
                compilerAssert(typeEmitter[referenceKey], `TypeEmitter doesn't have a method named ${referenceKey}`);
            }
            const newContext = keyHasContext(entry.method)
                ? typeEmitter[lexicalKey](...entry.args)
                : {};
            const newReferenceContext = keyHasReferenceContext(entry.method)
                ? typeEmitter[referenceKey](...entry.args)
                : {};
            // assemble our new reference and lexical contexts.
            const newContextState = stateInterner.intern({
                lexicalContext: stateInterner.intern({
                    ...context.lexicalContext,
                    ...newContext,
                }),
                referenceContext: stateInterner.intern({
                    ...context.referenceContext,
                    ...newReferenceContext,
                }),
            });
            knownContexts.set([entry, context], newContextState);
            context = newContextState;
        }
        if (!isInternalMethod(method)) {
            referenceTypeChain = [
                ...referenceTypeChain,
                stackEntryInterner.intern({
                    method,
                    type,
                    context,
                }),
            ];
        }
    }
    /**
     * Invoke the callback with the proper context for a given type.
     */
    function withTypeContext(method, args, cb) {
        const oldContext = context;
        const oldTypeStack = lexicalTypeStack;
        const oldRefTypeStack = referenceTypeChain;
        setContextForType(method, args);
        cb();
        context = oldContext;
        lexicalTypeStack = oldTypeStack;
        referenceTypeChain = oldRefTypeStack;
    }
    function withPatchedReferenceContext(referenceContext, cb) {
        if (referenceContext !== undefined) {
            const oldContext = context;
            context = stateInterner.intern({
                lexicalContext: context.lexicalContext,
                referenceContext: stateInterner.intern({
                    ...context.referenceContext,
                    ...referenceContext,
                }),
            });
            const result = cb();
            context = oldContext;
            return result;
        }
        else {
            return cb();
        }
    }
    /**
     * Invoke the callback with the given context.
     */
    function withContext(newContext, cb) {
        const oldContext = context;
        const oldTypeStack = lexicalTypeStack;
        context = newContext.context;
        lexicalTypeStack = newContext.lexicalTypeStack;
        cb();
        context = oldContext;
        lexicalTypeStack = oldTypeStack;
    }
    function typeEmitterKey(type) {
        switch (type.kind) {
            case "Model":
                if (program.checker.isStdType(type) && type.name === "Array") {
                    // likely an array literal, though could be a bare reference to Array maybe?
                    return "arrayLiteral";
                }
                if (type.name === "") {
                    return "modelLiteral";
                }
                if (type.templateMapper) {
                    return "modelInstantiation";
                }
                if (type.indexer && type.indexer.key.name === "integer") {
                    return "arrayDeclaration";
                }
                return "modelDeclaration";
            case "Namespace":
                return "namespace";
            case "ModelProperty":
                return "modelPropertyLiteral";
            case "StringTemplate":
                return "stringTemplate";
            case "Boolean":
                return "booleanLiteral";
            case "String":
                return "stringLiteral";
            case "Number":
                return "numericLiteral";
            case "Operation":
                if (type.interface) {
                    return "interfaceOperationDeclaration";
                }
                else {
                    return "operationDeclaration";
                }
            case "Interface":
                return "interfaceDeclaration";
            case "Enum":
                return "enumDeclaration";
            case "EnumMember":
                return "enumMember";
            case "Union":
                if (!type.name) {
                    return "unionLiteral";
                }
                if (type.templateMapper) {
                    return "unionInstantiation";
                }
                return "unionDeclaration";
            case "UnionVariant":
                return "unionVariant";
            case "Tuple":
                return "tupleLiteral";
            case "Scalar":
                if (type.templateMapper) {
                    return "scalarInstantiation";
                }
                else {
                    return "scalarDeclaration";
                }
            case "Intrinsic":
                return "intrinsic";
            default:
                compilerAssert(false, `Encountered type ${type.kind} which we don't know how to emit.`);
        }
    }
    function currentScope() {
        return context.referenceContext?.scope ?? context.lexicalContext?.scope ?? null;
    }
}
/**
 * Returns true if the given type is a declaration or an instantiation of a declaration.
 * @param type
 * @returns
 */
function isDeclaration(type) {
    switch (type.kind) {
        case "Namespace":
        case "Interface":
        case "Enum":
        case "Operation":
        case "Scalar":
        case "Intrinsic":
            return true;
        case "Model":
            return type.name ? type.name !== "" && type.name !== "Array" : false;
        case "Union":
            return type.name ? type.name !== "" : false;
        default:
            return false;
    }
}
/**
 * An interner takes an object and returns either that same object, or a
 * previously seen object that has the identical shape.
 *
 * This implementation is EXTREMELY non-optimal (O(n*m) where n = number of unique
 * state objects and m = the number of properties a state object contains). This
 * will very quickly be a bottleneck. That said, the common case is no state at
 * all, and also this is essentially implementing records and tuples, so could
 * probably adopt those when they are released. That that said, the records and
 * tuples are presently facing headwinds due to implementations facing exactly
 * these performance characteristics. Regardless, there are optimizations we
 * could consider.
 */
function createInterner() {
    const emptyObject = {};
    const knownObjects = new Set();
    return {
        intern(object) {
            const keyLen = Object.keys(object).length;
            if (keyLen === 0)
                return emptyObject;
            for (const ko of knownObjects) {
                const entries = Object.entries(ko);
                if (entries.length !== keyLen)
                    continue;
                let found = true;
                for (const [key, value] of entries) {
                    if (object[key] !== value) {
                        found = false;
                        break;
                    }
                }
                if (found) {
                    return ko;
                }
            }
            knownObjects.add(object);
            return object;
        },
    };
}
const noContext = new Set(["modelPropertyReference", "enumMemberReference"]);
function keyHasContext(key) {
    return !noContext.has(key);
}
const noReferenceContext = new Set([
    ...noContext,
    "booleanLiteral",
    "stringTemplate",
    "stringLiteral",
    "numericLiteral",
    "scalarInstantiation",
    "enumMember",
    "enumMembers",
    "intrinsic",
]);
function keyHasReferenceContext(key) {
    return !noReferenceContext.has(key);
}
function resolveReferenceCycle(stack, entity, typeToEmitEntity) {
    for (let i = stack.length - 1; i >= 0; i--) {
        if (stack[i].type === entity.emitEntityKey[1]) {
            return new ReferenceCycle(stack.slice(i).map((x) => {
                return {
                    type: x.type,
                    entity: typeToEmitEntity.get([x.method, x.type, x.context]),
                };
            }));
        }
    }
    throw new Error(`Couldn't resolve the circular reference stack for ${getTypeName(entity.emitEntityKey[1])}`);
}

const globalLibraryUrlsLoadedSym = Symbol.for("TYPESPEC_LIBRARY_URLS_LOADED");
if (globalThis[globalLibraryUrlsLoadedSym] === undefined) {
    globalThis[globalLibraryUrlsLoadedSym] = new Set();
}
const loadedUrls = globalThis[globalLibraryUrlsLoadedSym];
/**
 * @internal List of urls that used `createTypeSpecLibrary`. Used to keep track of the loaded version of library and make sure they are compatible.
 */
function getLibraryUrlsLoaded() {
    return loadedUrls;
}
/** @deprecated use createTypeSpecLibrary */
const createCadlLibrary = createTypeSpecLibrary;
function createStateKeys(libName, state) {
    const result = {};
    for (const key of Object.keys(state ?? {})) {
        result[key] = Symbol.for(`${libName}/${key}`);
    }
    return result;
}
/**
 * Create a new TypeSpec library definition.
 * @param lib Library definition.
 * @returns Library with utility functions.
 *
 *
 * @tutorial Create the lib object with `as const` to get the full typing.
 *
 * @example
 * const libDef = {
 *   name: "myLib",
 *   diagnostics: {
 *    "my-code": {serverity: "error", messages: {default: "Foo bar"}}
 *   },
 * } as const;
 *
 * const lib = createTypeSpecLibrary(libDef);
 */
function createTypeSpecLibrary(lib) {
    let emitterOptionValidator;
    const { reportDiagnostic, createDiagnostic } = createDiagnosticCreator(lib.diagnostics, lib.name);
    function createStateSymbol(name) {
        return Symbol.for(`${lib.name}.${name}`);
    }
    const caller = getCaller();
    if (caller) {
        loadedUrls.add(caller);
    }
    return {
        ...lib,
        diagnostics: lib.diagnostics,
        stateKeys: createStateKeys(lib.name, lib.state),
        reportDiagnostic,
        createDiagnostic,
        createStateSymbol,
        get emitterOptionValidator() {
            if (!emitterOptionValidator && lib.emitter?.options) {
                emitterOptionValidator = createJSONSchemaValidator(lib.emitter.options, {
                    coerceTypes: true,
                });
            }
            return emitterOptionValidator;
        },
        getTracer,
    };
    function getTracer(program) {
        return program.tracer.sub(lib.name);
    }
}
function definePackageFlags(flags) {
    return flags;
}
function defineLinter(def) {
    return def;
}
/** Create a new linter rule. */
function createLinterRule(definition) {
    compilerAssert(!definition.name.includes("/"), "Rule name cannot contain a '/'.");
    return definition;
}
/** @deprecated use setTypeSpecNamespace */
const setCadlNamespace = setTypeSpecNamespace;
/**
 * Set the TypeSpec namespace for that function.
 * @param namespace Namespace string (e.g. "Foo.Bar")
 * @param functions Functions
 */
function setTypeSpecNamespace(namespace, ...functions) {
    functions.forEach((c) => (c.namespace = namespace));
}
function getCaller() {
    const caller = getCallStack()[2];
    return typeof caller === "object" && "getFileName" in caller ? caller.getFileName() : undefined;
}
function getCallStack() {
    const _prepareStackTrace = Error.prepareStackTrace;
    Error.prepareStackTrace = (_, stack) => stack;
    const stack = new Error().stack.slice(1); // eslint-disable-line unicorn/error-message
    Error.prepareStackTrace = _prepareStackTrace;
    return stack;
}

// prettier-ignore
var UsageFlags;
(function (UsageFlags) {
    UsageFlags[UsageFlags["None"] = 0] = "None";
    UsageFlags[UsageFlags["Input"] = 2] = "Input";
    UsageFlags[UsageFlags["Output"] = 4] = "Output";
})(UsageFlags || (UsageFlags = {}));
/**
 * Resolve usage(input, output or both) of various types in the given namespace.
 * Will recursively scan all namespace, interfaces and operations contained inside the namespace.
 * @param types Entrypoint(s) namespace, interface or operations to get usage from.
 * @returns Map of types to usage.
 */
function resolveUsages(types) {
    const usages = new Map();
    if (isArray(types)) {
        for (const item of types) {
            addUsagesInContainer(item, usages);
        }
    }
    else {
        addUsagesInContainer(types, usages);
    }
    return {
        types: [...usages.keys()],
        isUsedAs: (type, usage) => {
            const used = usages.get(type);
            if (used === undefined) {
                return false;
            }
            return Boolean(used & usage);
        },
    };
}
function addUsagesInContainer(type, usages) {
    switch (type.kind) {
        case "Namespace":
            addUsagesInNamespace(type, usages);
            break;
        case "Interface":
            addUsagesInInterface(type, usages);
            break;
        case "Operation":
            addUsagesInOperation(type, usages);
            break;
    }
}
function trackUsage(usages, type, usage) {
    const existingFlag = usages.get(type) ?? UsageFlags.None;
    usages.set(type, existingFlag | usage);
}
function addUsagesInNamespace(namespace, usages) {
    for (const subNamespace of namespace.namespaces.values()) {
        addUsagesInNamespace(subNamespace, usages);
    }
    for (const Interface of namespace.interfaces.values()) {
        addUsagesInInterface(Interface, usages);
    }
    for (const operation of namespace.operations.values()) {
        addUsagesInOperation(operation, usages);
    }
}
function addUsagesInInterface(Interface, usages) {
    for (const operation of Interface.operations.values()) {
        addUsagesInOperation(operation, usages);
    }
}
function addUsagesInOperation(operation, usages) {
    navigateReferencedTypes(operation.parameters, (type) => trackUsage(usages, type, UsageFlags.Input));
    navigateReferencedTypes(operation.returnType, (type) => trackUsage(usages, type, UsageFlags.Output));
}
function navigateReferencedTypes(type, callback, visited = new Set()) {
    if (visited.has(type)) {
        return;
    }
    visited.add(type);
    switch (type.kind) {
        case "Model":
            callback(type);
            navigateIterable(type.properties, callback, visited);
            navigateIterable(type.derivedModels, callback, visited);
            type.indexer?.value && navigateReferencedTypes(type.indexer.value, callback, visited);
            break;
        case "ModelProperty":
            navigateReferencedTypes(type.type, callback, visited);
            break;
        case "Union":
            callback(type);
            navigateIterable(type.variants, callback, visited);
            break;
        case "UnionVariant":
            navigateReferencedTypes(type.type, callback, visited);
            break;
        case "Enum":
        case "Tuple":
            callback(type);
            break;
    }
}
function navigateIterable(map, callback, visited = new Set()) {
    for (const type of map.values()) {
        navigateReferencedTypes(type, callback, visited);
    }
}

export { visitChildren as $, Alias as A, isCollection as B, CircularEmit as C, Declaration as D, EmitterResult as E, Pair as F, isEmptyPath as G, isScalar as H, collectionFromPath as I, toJS as J, applyReviver as K, createNodeAnchors as L, MAP as M, NoEmit as N, isPair as O, Placeholder as P, Lexer as Q, ReferenceCycle as R, Scalar as S, tokenType as T, createDiagnosticCollector as U, createJSONSchemaValidator as V, getLocationInYamlScript as W, ignoreDiagnostics as X, YAMLMap as Y, getTypeName as Z, parse$1 as _, createAssetEmitter as a, f0 as a$, getSourceLocation as a0, typespecPrinter as a1, gu as a2, fi as a3, isTemplateDeclarationOrInstance as a4, defineCodeFix as a5, isWhiteSpace as a6, getLocationContext as a7, isValue as a8, finishTypeForProgram as a9, setMinValueExclusive as aA, setMaxValueExclusive as aB, markDeprecated as aC, getDeprecationDetails as aD, getDiscriminatedUnion as aE, setDiscriminator as aF, commonjsGlobal as aG, getAugmentedNamespace as aH, createScanner as aI, Token as aJ, TokenFlags as aK, isKeyword as aL, isPunctuation as aM, formatDiagnostic as aN, printIdentifier$1 as aO, getEntityName as aP, getFullyQualifiedSymbolName as aQ, isStdNamespace as aR, isType as aS, getDocData as aT, getFirstAncestor as aU, positionInRange as aV, skipWhiteSpace as aW, skipTrivia as aX, getNodeAtPosition as aY, getPositionBeforeTrivia as aZ, getNodeAtPositionDetail as a_, isNeverType as aa, getParentTemplateNode as ab, isTemplateInstance as ac, createChecker as ad, getLibraryUrlsLoaded as ae, isImportStatement as af, parseStandaloneTypeReference as ag, createBinder as ah, reportDeprecated as ai, setDocData as aj, getDocDataInternal as ak, getMaxLengthAsNumeric as al, setMinLength as am, getMinLengthAsNumeric as an, setMaxLength as ao, isArrayModelType as ap, getMaxItemsAsNumeric as aq, setMinItems as ar, getMinItemsAsNumeric as as, setMaxItems as at, getMaxValueAsNumeric as au, getMaxValueExclusiveAsNumeric as av, setMinValue as aw, getMinValueAsNumeric as ax, getMinValueExclusiveAsNumeric as ay, setMaxValue as az, RawCode as b, getDiscriminatedTypes as b0, getDiscriminator as b1, getMaxItems as b2, getMaxLength as b3, getMaxValue as b4, getMaxValueExclusive as b5, getMinItems as b6, getMinLength as b7, getMinValue as b8, getMinValueExclusive as b9, TokenDisplay as bA, Keywords as bB, isTrivia as bC, isComment as bD, isModifier as bE, isStatementKeyword as bF, skipTriviaBackward as bG, skipContinuousIdentifier as bH, isErrorType as bI, isVoidType as bJ, isUnknownType as bK, isNullType as bL, isRecordModelType as bM, isDeclaredType as bN, isGlobalNamespace as bO, isDeclaredInNamespace as bP, createCadlLibrary as ba, createLinterRule as bb, createTypeSpecLibrary as bc, defineLinter as bd, definePackageFlags as be, setCadlNamespace as bf, setTypeSpecNamespace as bg, Numeric as bh, isNumeric as bi, getEffectiveModelType as bj, filterModelProperties as bk, getOverriddenProperty as bl, walkPropertiesInherited as bm, isDeprecated as bn, ProjectionError as bo, logDiagnostics as bp, logVerboseTestOutput as bq, assertType as br, explainStringTemplateNotSerializable as bs, stringTemplateToString as bt, getNamespaceFullName as bu, UsageFlags as bv, resolveUsages as bw, exprIsBareIdentifier as bx, hasParseError as by, getIdentifierContext as bz, compilerAssert as c, isMap as d, emitFile as e, YAMLSeq as f, isSeq as g, set as h, isTemplateDeclaration as i, SCALAR$1 as j, SEQ as k, createStringifyContext as l, indentComment as m, isNode as n, omap as o, pairs as p, stringify$1 as q, resolveDeclarationReferenceScope as r, stringifyString as s, lineComment as t, NODE_TYPE as u, DOC as v, Directives as w, anchorNames as x, findNewAnchor as y, createNode as z };
