UNPKG

ts-budgie

Version:

Converts TypeScript code to Budgie.

140 lines 6.94 kB
"use strict"; var __extends = (this && this.__extends) || (function () { var extendStatics = function (d, b) { extendStatics = Object.setPrototypeOf || ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; return extendStatics(d, b); }; return function (d, b) { extendStatics(d, b); function __() { this.constructor = d; } d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); }; })(); var __spreadArrays = (this && this.__spreadArrays) || function () { for (var s = 0, i = 0, il = arguments.length; i < il; i++) s += arguments[i].length; for (var r = Array(s), k = 0, i = 0; i < il; i++) for (var a = arguments[i], j = 0, jl = a.length; j < jl; j++, k++) r[k] = a[j]; return r; }; Object.defineProperty(exports, "__esModule", { value: true }); var budgie_1 = require("budgie"); var budgieLine_1 = require("../../output/budgieLine"); var transformation_1 = require("../../output/transformation"); var unsupported_1 = require("../../output/unsupported"); var types_1 = require("../adjustments/types"); var visitor_1 = require("../visitor"); /** * For very obvious types, we allow direct typeChecker usage to get simple names. */ var allowedIntrinsicNames = new Set([budgie_1.KeywordNames.String, "boolean", "number", "string"]); /** * Command names that indicate a variable needs to start and end with separate commands. */ var multilineInitializerTypes = new Set([budgie_1.CommandNames.DictionaryNewStart]); /** * @returns Whether a variable declaration is of a type that has a Start and corresponding End. */ var isInitializerMultilineNecessary = function (initializerType) { if (!(initializerType instanceof budgieLine_1.BudgieLine)) { return false; } return multilineInitializerTypes.has(initializerType.command); }; var VariableDeclarationVisitor = /** @class */ (function (_super) { __extends(VariableDeclarationVisitor, _super); function VariableDeclarationVisitor() { var _this = _super !== null && _super.apply(this, arguments) || this; /** * Tries to find more specific types for variable declarations. */ _this.typeAdjuster = new types_1.TypeAdjuster(); return _this; } VariableDeclarationVisitor.prototype.visit = function (node) { return [transformation_1.Transformation.fromNode(node, this.sourceFile, this.getTransformationContents(node))]; }; VariableDeclarationVisitor.prototype.getTransformationContents = function (node) { var name = node.name.getText(this.sourceFile); var interpretedType = this.aliaser.getFriendlyTypeName(node); // If we have a type, tell the value parser to use it // This is necessary for some commands, such as lists if (interpretedType !== undefined) { this.context.setTypeCoercion(interpretedType); } // A value may indicate to us better typing info than what we already have var aliasedValue = this.getAliasedValue(node); // After recursing into the node, see if we've found a more specific type (coercion) var typeModified = this.context.exitTypeCoercion(); if (typeModified !== undefined) { interpretedType = typeModified; } // Some values may request a more specific intepreted type, // such as length commands switching from "float" to "int" var manualTypeAdjustment = this.typeAdjuster.attempt({ originalType: interpretedType, actualValue: aliasedValue, node: node, }); if (manualTypeAdjustment !== undefined) { interpretedType = manualTypeAdjustment; } // By now, we've finished doing fancy checks, but the type checker might just directly know if (interpretedType === undefined) { interpretedType = this.getFriendlyTypeAtLocation(node); } // As a last ditch effort, it may be that we're seeing the result of a Budgie line // If it's a command that we explicitly know to return a type, we can use that if (interpretedType === undefined && aliasedValue instanceof budgieLine_1.BudgieLine) { interpretedType = this.typeAdjuster.getKnownTypeOfBudgieLine(aliasedValue); } // If we don't know the interpreted type by now, just give up if (interpretedType === undefined) { return [unsupported_1.createUnsupportedTypeBudgieLine()]; } var firstResultsLineArgs = [name, interpretedType]; if (aliasedValue !== undefined) { firstResultsLineArgs.push(aliasedValue); } var lines = []; var command = isInitializerMultilineNecessary(firstResultsLineArgs[2]) ? budgie_1.CommandNames.VariableStart : budgie_1.CommandNames.Variable; if (command === budgie_1.CommandNames.VariableStart) { var fullValue = this.getFullValue(node); if (fullValue !== undefined) { this.appendFullValueToLines(fullValue, lines); } } lines.unshift(new (budgieLine_1.BudgieLine.bind.apply(budgieLine_1.BudgieLine, __spreadArrays([void 0, command], firstResultsLineArgs)))()); return lines; }; VariableDeclarationVisitor.prototype.getAliasedValue = function (node) { if (node.initializer === undefined) { return undefined; } return this.router.recurseIntoValue(node.initializer); }; VariableDeclarationVisitor.prototype.getFullValue = function (node) { if (node.initializer === undefined) { return undefined; } return this.router.recurseIntoNode(node.initializer); }; VariableDeclarationVisitor.prototype.getFriendlyTypeAtLocation = function (node) { var intrinsicName = this.typeChecker.getTypeAtLocation(node).intrinsicName; return allowedIntrinsicNames.has(intrinsicName) ? intrinsicName : undefined; }; VariableDeclarationVisitor.prototype.appendFullValueToLines = function (fullValue, lines) { // Full values start with "dictionary new start" or similar commands. // This filters them out. if (fullValue.length === 1 && fullValue[0] instanceof transformation_1.Transformation) { this.appendFullValueToLines(fullValue[0].output, lines); return; } lines.push.apply(lines, fullValue.slice(1)); }; return VariableDeclarationVisitor; }(visitor_1.NodeVisitor)); exports.VariableDeclarationVisitor = VariableDeclarationVisitor; //# sourceMappingURL=variableDeclarationVisitor.js.map