UNPKG

typescript-to-lua

Version:

A generic TypeScript to Lua transpiler. Write your code in TypeScript and publish Lua!

79 lines 4.01 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.validateAssignment = validateAssignment; const ts = require("typescript"); const utils_1 = require("../../utils"); const diagnostics_1 = require("./diagnostics"); const function_context_1 = require("./function-context"); // TODO: Clear if types are reused between compilations const typeValidationCache = new WeakMap(); function validateAssignment(context, node, fromType, toType, toName) { var _a, _b; if (toType === fromType) { return; } if ((toType.flags & ts.TypeFlags.Any) !== 0) { // Assigning to un-typed variable return; } // Use cache to avoid repeating check for same types (protects against infinite loop in recursive types) const fromTypeCache = (0, utils_1.getOrUpdate)(typeValidationCache, fromType, () => new Set()); if (fromTypeCache.has(toType)) return; fromTypeCache.add(toType); validateFunctionAssignment(context, node, fromType, toType, toName); const checker = context.checker; if ((checker.isTupleType(toType) || checker.isArrayType(toType)) && (checker.isTupleType(fromType) || checker.isArrayType(fromType))) { // Recurse into arrays/tuples const fromTypeArguments = fromType.typeArguments; const toTypeArguments = toType.typeArguments; if (fromTypeArguments === undefined || toTypeArguments === undefined) { return; } const count = Math.min(fromTypeArguments.length, toTypeArguments.length); for (let i = 0; i < count; ++i) { validateAssignment(context, node, fromTypeArguments[i], toTypeArguments[i], toName); } } const fromMembers = (_a = fromType.symbol) === null || _a === void 0 ? void 0 : _a.members; const toMembers = (_b = toType.symbol) === null || _b === void 0 ? void 0 : _b.members; if (fromMembers && toMembers) { // Recurse into interfaces if (toMembers.size < fromMembers.size) { toMembers.forEach((toMember, escapedMemberName) => { const fromMember = fromMembers.get(escapedMemberName); if (fromMember) { validateMember(toMember, fromMember, escapedMemberName); } }); } else { fromMembers.forEach((fromMember, escapedMemberName) => { const toMember = toMembers.get(escapedMemberName); if (toMember) { validateMember(toMember, fromMember, escapedMemberName); } }); } } function validateMember(toMember, fromMember, escapedMemberName) { const toMemberType = context.checker.getTypeOfSymbolAtLocation(toMember, node); const fromMemberType = context.checker.getTypeOfSymbolAtLocation(fromMember, node); const memberName = ts.unescapeLeadingUnderscores(escapedMemberName); validateAssignment(context, node, fromMemberType, toMemberType, toName ? `${toName}.${memberName}` : memberName); } } function validateFunctionAssignment(context, node, fromType, toType, toName) { const fromContext = (0, function_context_1.getFunctionContextType)(context, fromType); const toContext = (0, function_context_1.getFunctionContextType)(context, toType); if (fromContext === function_context_1.ContextType.Mixed || toContext === function_context_1.ContextType.Mixed) { context.diagnostics.push((0, diagnostics_1.unsupportedOverloadAssignment)(node, toName)); } else if (fromContext !== toContext && fromContext !== function_context_1.ContextType.None && toContext !== function_context_1.ContextType.None) { context.diagnostics.push(toContext === function_context_1.ContextType.Void ? (0, diagnostics_1.unsupportedNoSelfFunctionConversion)(node, toName) : (0, diagnostics_1.unsupportedSelfFunctionConversion)(node, toName)); } } //# sourceMappingURL=assignment-validation.js.map