UNPKG

typescript-to-lua

Version:

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

239 lines 11.1 kB
"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.ContextType = void 0; exports.getCallContextType = getCallContextType; exports.getFunctionContextType = getFunctionContextType; const ts = __importStar(require("typescript")); const annotations_1 = require("./annotations"); const typescript_1 = require("./typescript"); var ContextType; (function (ContextType) { ContextType[ContextType["None"] = 0] = "None"; ContextType[ContextType["Void"] = 1] = "Void"; ContextType[ContextType["NonVoid"] = 2] = "NonVoid"; ContextType[ContextType["Mixed"] = 3] = "Mixed"; })(ContextType || (exports.ContextType = ContextType = {})); function hasNoSelfAncestor(declaration) { const scopeDeclaration = (0, typescript_1.findFirstNodeAbove)(declaration, (node) => ts.isSourceFile(node) || ts.isModuleDeclaration(node)); if (!scopeDeclaration) { return false; } else if (ts.isSourceFile(scopeDeclaration)) { return (0, annotations_1.getFileAnnotations)(scopeDeclaration).has(annotations_1.AnnotationKind.NoSelfInFile); } else if ((0, annotations_1.getNodeAnnotations)(scopeDeclaration).has(annotations_1.AnnotationKind.NoSelf)) { return true; } else { return hasNoSelfAncestor(scopeDeclaration); } } function getExplicitThisParameter(signatureDeclaration) { const param = signatureDeclaration.parameters[0]; if (param && ts.isIdentifier(param.name) && ts.identifierToKeywordKind(param.name) === ts.SyntaxKind.ThisKeyword) { return param; } } const callContextTypes = new WeakMap(); function getCallContextType(context, callExpression) { const known = callContextTypes.get(callExpression); if (known !== undefined) return known; const signature = context.checker.getResolvedSignature(callExpression); const signatureDeclaration = signature === null || signature === void 0 ? void 0 : signature.getDeclaration(); let contextType = ContextType.None; if (signatureDeclaration) { contextType = computeDeclarationContextType(context, signatureDeclaration); } else { // No signature declaration could be resolved, so instead try to see if the declaration is in a // noSelfInFile file const declarations = findRootDeclarations(context, callExpression); contextType = declarations.some(d => (0, annotations_1.getFileAnnotations)(d.getSourceFile()).has(annotations_1.AnnotationKind.NoSelfInFile)) ? ContextType.Void : context.options.noImplicitSelf ? ContextType.Void : ContextType.NonVoid; } callContextTypes.set(callExpression, contextType); return contextType; } const signatureDeclarationContextTypes = new WeakMap(); function getSignatureContextType(context, signatureDeclaration) { const known = signatureDeclarationContextTypes.get(signatureDeclaration); if (known !== undefined) return known; const contextType = computeDeclarationContextType(context, signatureDeclaration); signatureDeclarationContextTypes.set(signatureDeclaration, contextType); return contextType; } function findRootDeclarations(context, callExpression) { var _a, _b; const calledExpression = ts.isTaggedTemplateExpression(callExpression) ? callExpression.tag : ts.isJsxSelfClosingElement(callExpression) ? callExpression.tagName : ts.isJsxOpeningElement(callExpression) ? callExpression.tagName : ts.isCallExpression(callExpression) ? callExpression.expression : undefined; if (!calledExpression) return []; const calledSymbol = context.checker.getSymbolAtLocation(calledExpression); if (calledSymbol === undefined) return []; return ((_b = (_a = calledSymbol.getDeclarations()) === null || _a === void 0 ? void 0 : _a.flatMap(d => { var _a; if (ts.isImportSpecifier(d)) { const aliasSymbol = context.checker.getAliasedSymbol(calledSymbol); return (_a = aliasSymbol.getDeclarations()) !== null && _a !== void 0 ? _a : []; } else { return [d]; } })) !== null && _b !== void 0 ? _b : []); } function computeDeclarationContextType(context, signatureDeclaration) { var _a; const thisParameter = getExplicitThisParameter(signatureDeclaration); if (thisParameter) { // Explicit 'this' return ((_a = thisParameter.type) === null || _a === void 0 ? void 0 : _a.kind) === ts.SyntaxKind.VoidKeyword ? ContextType.Void : ContextType.NonVoid; } // noSelf declaration on function signature if ((0, annotations_1.getNodeAnnotations)(signatureDeclaration).has(annotations_1.AnnotationKind.NoSelf)) { return ContextType.Void; } if (ts.isMethodSignature(signatureDeclaration) || ts.isMethodDeclaration(signatureDeclaration) || ts.isConstructSignatureDeclaration(signatureDeclaration) || ts.isConstructorDeclaration(signatureDeclaration) || (signatureDeclaration.parent && ts.isPropertyDeclaration(signatureDeclaration.parent)) || (signatureDeclaration.parent && ts.isPropertySignature(signatureDeclaration.parent)) || (signatureDeclaration.parent && ts.isIndexSignatureDeclaration(signatureDeclaration.parent))) { // Class/interface methods only respect @noSelf on their parent const scopeDeclaration = (0, typescript_1.findFirstNodeAbove)(signatureDeclaration, (n) => ts.isClassDeclaration(n) || ts.isClassExpression(n) || ts.isInterfaceDeclaration(n)); if (scopeDeclaration !== undefined && (0, annotations_1.getNodeAnnotations)(scopeDeclaration).has(annotations_1.AnnotationKind.NoSelf)) { return ContextType.Void; } return ContextType.NonVoid; } if (signatureDeclaration.parent && ts.isTypeParameterDeclaration(signatureDeclaration.parent)) { return ContextType.NonVoid; } // Call signature inside a class or interface respects @noSelf on the enclosing class/interface if (ts.isCallSignatureDeclaration(signatureDeclaration)) { const scopeDeclaration = (0, typescript_1.findFirstNodeAbove)(signatureDeclaration, (n) => ts.isClassDeclaration(n) || ts.isClassExpression(n) || ts.isInterfaceDeclaration(n)); if (scopeDeclaration !== undefined && (0, annotations_1.getNodeAnnotations)(scopeDeclaration).has(annotations_1.AnnotationKind.NoSelf)) { return ContextType.Void; } } // When using --noImplicitSelf and the signature is defined in a file targeted by the program apply the @noSelf rule. const program = context.program; const options = program.getCompilerOptions(); if (options.noImplicitSelf) { const sourceFile = program.getSourceFile(signatureDeclaration.getSourceFile().fileName); if (sourceFile !== undefined && !program.isSourceFileDefaultLibrary(sourceFile) && !program.isSourceFileFromExternalLibrary(sourceFile)) { return ContextType.Void; } } // Walk up to find @noSelf or @noSelfInFile if (hasNoSelfAncestor(signatureDeclaration)) { return ContextType.Void; } return ContextType.NonVoid; } function reduceContextTypes(contexts) { let type = ContextType.None; for (const context of contexts) { type |= context; if (type === ContextType.Mixed) break; } return type; } function getSignatureDeclarations(context, signature) { if (signature.compositeSignatures) { return signature.compositeSignatures.flatMap(s => getSignatureDeclarations(context, s)); } const signatureDeclaration = signature.getDeclaration(); if (signatureDeclaration === undefined) { return []; } let inferredType; if (ts.isMethodDeclaration(signatureDeclaration) && ts.isObjectLiteralExpression(signatureDeclaration.parent) && !getExplicitThisParameter(signatureDeclaration)) { inferredType = context.checker.getContextualTypeForObjectLiteralElement(signatureDeclaration); } else if ((ts.isFunctionExpression(signatureDeclaration) || ts.isArrowFunction(signatureDeclaration)) && !getExplicitThisParameter(signatureDeclaration)) { // Infer type of function expressions/arrow functions inferredType = (0, typescript_1.inferAssignedType)(context, signatureDeclaration); } if (inferredType) { const inferredSignatures = (0, typescript_1.getAllCallSignatures)(inferredType); if (inferredSignatures.length > 0) { return inferredSignatures.map(s => s.getDeclaration()); } } return [signatureDeclaration]; } const typeContextTypes = new WeakMap(); function getFunctionContextType(context, type) { const known = typeContextTypes.get(type); if (known !== undefined) return known; const contextType = computeFunctionContextType(context, type); typeContextTypes.set(type, contextType); return contextType; } function computeFunctionContextType(context, type) { if (type.isTypeParameter()) { const constraint = type.getConstraint(); if (constraint) return getFunctionContextType(context, constraint); } const signatures = context.checker.getSignaturesOfType(type, ts.SignatureKind.Call); if (signatures.length === 0) { return ContextType.None; } return reduceContextTypes(signatures.flatMap(s => getSignatureDeclarations(context, s)).map(s => getSignatureContextType(context, s))); } //# sourceMappingURL=function-context.js.map