typescript-to-lua
Version:
A generic TypeScript to Lua transpiler. Write your code in TypeScript and publish Lua!
79 lines • 4.01 kB
JavaScript
;
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