"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    var desc = Object.getOwnPropertyDescriptor(m, k);
    if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
      desc = { enumerable: true, get: function() { return m[k]; } };
    }
    Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
    Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
    o["default"] = v;
});
var __importStar = (this && this.__importStar) || (function () {
    var ownKeys = function(o) {
        ownKeys = Object.getOwnPropertyNames || function (o) {
            var ar = [];
            for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
            return ar;
        };
        return ownKeys(o);
    };
    return function (mod) {
        if (mod && mod.__esModule) return mod;
        var result = {};
        if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
        __setModuleDefault(result, mod);
        return result;
    };
})();
Object.defineProperty(exports, "__esModule", { value: true });
exports.generateInterpolation = generateInterpolation;
const shared_1 = require("@vue/shared");
const collectBindings_1 = require("../../utils/collectBindings");
const shared_2 = require("../../utils/shared");
const codeFeatures_1 = require("../codeFeatures");
const names = __importStar(require("../names"));
const utils_1 = require("../utils");
// https://github.com/vuejs/core/blob/fb0c3ca519f1fccf52049cd6b8db3a67a669afe9/packages/compiler-core/src/transforms/transformExpression.ts#L47
const isLiteralWhitelisted = /*@__PURE__*/ (0, shared_1.makeMap)('true,false,null,this');
function* generateInterpolation({ typescript, setupRefs }, ctx, block, data, code, start, prefix = '', suffix = '') {
    for (const segment of forEachInterpolationSegment(typescript, setupRefs, ctx, block, code, start, prefix, suffix)) {
        if (typeof segment === 'string') {
            yield segment;
            continue;
        }
        let [section, offset, type] = segment;
        offset -= prefix.length;
        let addSuffix = '';
        const overLength = offset + section.length - code.length;
        if (overLength > 0) {
            addSuffix = section.slice(section.length - overLength);
            section = section.slice(0, -overLength);
        }
        if (offset < 0) {
            yield section.slice(0, -offset);
            section = section.slice(-offset);
            offset = 0;
        }
        const shouldSkip = section.length === 0 && type === 'startEnd';
        if (!shouldSkip) {
            yield [
                section,
                block.name,
                start + offset,
                type === 'errorMappingOnly'
                    ? codeFeatures_1.codeFeatures.verification
                    : type === 'shorthand'
                        ? { ...data, __shorthandExpression: 'js' }
                        : data,
            ];
        }
        yield addSuffix;
    }
}
function* forEachInterpolationSegment(ts, setupRefs, ctx, block, originalCode, start, prefix, suffix) {
    const code = prefix + originalCode + suffix;
    let prevEnd = 0;
    for (const [name, offset, isShorthand] of forEachIdentifiers(ts, ctx, block, originalCode, code, prefix)) {
        if (isShorthand) {
            yield [code.slice(prevEnd, offset + name.length), prevEnd];
            yield `: `;
        }
        else {
            yield [code.slice(prevEnd, offset), prevEnd, prevEnd > 0 ? undefined : 'startEnd'];
        }
        if (setupRefs.has(name)) {
            yield [name, offset];
            yield `.value`;
        }
        else {
            yield ['', offset, 'errorMappingOnly']; // #1205, #1264
            if (ctx.dollarVars.has(name)) {
                yield names.dollars;
            }
            else {
                ctx.recordComponentAccess(block.name, name, start - prefix.length + offset);
                yield names.ctx;
            }
            yield `.`;
            yield [name, offset, isShorthand ? 'shorthand' : undefined];
        }
        prevEnd = offset + name.length;
    }
    if (prevEnd < code.length) {
        yield [code.slice(prevEnd), prevEnd, 'startEnd'];
    }
}
function* forEachIdentifiers(ts, ctx, block, originalCode, code, prefix) {
    if (utils_1.identifierRegex.test(originalCode) && !shouldIdentifierSkipped(ctx, originalCode)) {
        yield [originalCode, prefix.length, false];
        return;
    }
    const endScope = ctx.startScope();
    const ast = (0, utils_1.getTypeScriptAST)(ts, block, code);
    for (const [id, isShorthand] of forEachDeclarations(ts, ast, ast, ctx)) {
        const text = (0, shared_2.getNodeText)(ts, id, ast);
        if (shouldIdentifierSkipped(ctx, text)) {
            continue;
        }
        yield [text, (0, shared_2.getStartEnd)(ts, id, ast).start, isShorthand];
    }
    endScope();
}
function* forEachDeclarations(ts, node, ast, ctx) {
    if (ts.isIdentifier(node)) {
        yield [node, false];
    }
    else if (ts.isShorthandPropertyAssignment(node)) {
        yield [node.name, true];
    }
    else if (ts.isPropertyAccessExpression(node)) {
        yield* forEachDeclarations(ts, node.expression, ast, ctx);
    }
    else if (ts.isVariableDeclaration(node)) {
        ctx.declare(...(0, collectBindings_1.collectBindingNames)(ts, node.name, ast));
        yield* forEachDeclarationsInBinding(ts, node, ast, ctx);
    }
    else if (ts.isArrayBindingPattern(node) || ts.isObjectBindingPattern(node)) {
        for (const element of node.elements) {
            if (ts.isBindingElement(element)) {
                yield* forEachDeclarationsInBinding(ts, element, ast, ctx);
            }
        }
    }
    else if (ts.isArrowFunction(node) || ts.isFunctionExpression(node)) {
        yield* forEachDeclarationsInFunction(ts, node, ast, ctx);
    }
    else if (ts.isObjectLiteralExpression(node)) {
        for (const prop of node.properties) {
            if (ts.isPropertyAssignment(prop)) {
                // fix https://github.com/vuejs/language-tools/issues/1176
                if (ts.isComputedPropertyName(prop.name)) {
                    yield* forEachDeclarations(ts, prop.name.expression, ast, ctx);
                }
                yield* forEachDeclarations(ts, prop.initializer, ast, ctx);
            }
            // fix https://github.com/vuejs/language-tools/issues/1156
            else if (ts.isShorthandPropertyAssignment(prop)) {
                yield* forEachDeclarations(ts, prop, ast, ctx);
            }
            // fix https://github.com/vuejs/language-tools/issues/1148#issuecomment-1094378126
            else if (ts.isSpreadAssignment(prop)) {
                // TODO: cannot report "Spread types may only be created from object types.ts(2698)"
                yield* forEachDeclarations(ts, prop.expression, ast, ctx);
            }
            // fix https://github.com/vuejs/language-tools/issues/4604
            else if (ts.isFunctionLike(prop) && prop.body) {
                yield* forEachDeclarationsInFunction(ts, prop, ast, ctx);
            }
        }
    }
    // fix https://github.com/vuejs/language-tools/issues/1422
    else if (ts.isTypeNode(node)) {
        yield* forEachDeclarationsInTypeNode(ts, node);
    }
    else if (ts.isBlock(node)) {
        const endScope = ctx.startScope();
        for (const child of (0, utils_1.forEachNode)(ts, node)) {
            yield* forEachDeclarations(ts, child, ast, ctx);
        }
        endScope();
    }
    else {
        for (const child of (0, utils_1.forEachNode)(ts, node)) {
            yield* forEachDeclarations(ts, child, ast, ctx);
        }
    }
}
function* forEachDeclarationsInBinding(ts, node, ast, ctx) {
    if ('type' in node && node.type) {
        yield* forEachDeclarationsInTypeNode(ts, node.type);
    }
    if (!ts.isIdentifier(node.name)) {
        yield* forEachDeclarations(ts, node.name, ast, ctx);
    }
    if (node.initializer) {
        yield* forEachDeclarations(ts, node.initializer, ast, ctx);
    }
}
function* forEachDeclarationsInFunction(ts, node, ast, ctx) {
    const endScope = ctx.startScope();
    for (const param of node.parameters) {
        ctx.declare(...(0, collectBindings_1.collectBindingNames)(ts, param.name, ast));
        yield* forEachDeclarationsInBinding(ts, param, ast, ctx);
    }
    if (node.body) {
        yield* forEachDeclarations(ts, node.body, ast, ctx);
    }
    endScope();
}
function* forEachDeclarationsInTypeNode(ts, node) {
    if (ts.isTypeQueryNode(node)) {
        let id = node.exprName;
        while (!ts.isIdentifier(id)) {
            id = id.left;
        }
        yield [id, false];
    }
    else {
        for (const child of (0, utils_1.forEachNode)(ts, node)) {
            yield* forEachDeclarationsInTypeNode(ts, child);
        }
    }
}
function shouldIdentifierSkipped(ctx, text) {
    return ctx.scopes.some(scope => scope.has(text))
        // https://github.com/vuejs/core/blob/245230e135152900189f13a4281302de45fdcfaa/packages/compiler-core/src/transforms/transformExpression.ts#L342-L352
        || (0, shared_1.isGloballyAllowed)(text)
        || isLiteralWhitelisted(text)
        || text === 'require'
        || text.startsWith('__VLS_');
}
//# sourceMappingURL=interpolation.js.map