ts-budgie
Version:
Converts TypeScript code to Budgie.
124 lines • 6.89 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
var tsutils = require("tsutils");
var ts = require("typescript");
var flags_1 = require("../flags");
var types_1 = require("../types");
var arrayLiteralExpressionAliaser_1 = require("./arrayLiteralExpressionAliaser");
var elementAccessExpressionAliaser_1 = require("./elementAccessExpressionAliaser");
var newExpressionAliaser_1 = require("./newExpressionAliaser");
var numericAliaser_1 = require("./numericAliaser");
var propertyOrVariableDeclarationAliaser_1 = require("./propertyOrVariableDeclarationAliaser");
var typeLiteralAliaser_1 = require("./typeLiteralAliaser");
var typeNameAliaser_1 = require("./typeNameAliaser");
var createChildGetter = function (index) {
if (index === void 0) { index = 0; }
return function (node) { return node.getChildren()[index]; };
};
var recursiveFriendlyValueDeclarationTypes = new Set([
ts.SyntaxKind.Parameter,
ts.SyntaxKind.PropertyDeclaration,
ts.SyntaxKind.VariableDeclaration,
]);
var RootAliaser = /** @class */ (function () {
function RootAliaser(sourceFile, typeChecker) {
var _this = this;
this.getFriendlyTypeName = function (node) {
var knownTypeNameConverter = _this.typesWithKnownTypeNames.get(node.kind);
if (knownTypeNameConverter !== undefined) {
var typeNameConverted = knownTypeNameConverter.getFriendlyTypeName(node);
if (typeNameConverted !== undefined) {
return typeNameConverted;
}
}
var passThroughType = _this.passThroughTypes.get(node.kind);
if (passThroughType !== undefined) {
return _this.getFriendlyTypeName(passThroughType(node));
}
// We use the real type checker last because our checks can know the difference
// between seemingly identical types, such as "float" or "int" within "number"
var typeAtLocation = _this.typeChecker.getTypeAtLocation(node);
var resolvedFlagType = _this.flagResolver.resolve(typeAtLocation.flags);
if (resolvedFlagType !== undefined) {
return resolvedFlagType;
}
// TypeScript won't give up expression nodes' types, but if they have a type symbol
// we can use it to find their value declaration
var symbol = _this.typeChecker.getSymbolAtLocation(node);
if (symbol !== undefined && symbol.valueDeclaration !== undefined) {
var valueDeclaration = symbol.valueDeclaration;
if (recursiveFriendlyValueDeclarationTypes.has(valueDeclaration.kind)) {
return _this.getFriendlyTypeName(valueDeclaration);
}
}
// By now, this is probably a node with a non-primitive type, such as a class instance.
if (ts.isParameter(node) || ts.isPropertyDeclaration(node) || ts.isVariableDeclaration(node)) {
if (node.type !== undefined) {
return _this.getFriendlyTypeName(node.type);
}
}
if (ts.isTypeNode(node)) {
return types_1.parseRawTypeToBudgie(node.getText());
}
// This seems to sometimes succeed when directly calling getSymbolAtLocation doesn't
var typeSymbol = typeAtLocation.symbol;
if (typeSymbol !== undefined && typeSymbol.name !== "unknown") {
return typeSymbol.name;
}
return undefined;
};
this.flagResolver = new flags_1.TypeFlagsResolver();
this.sourceFile = sourceFile;
this.typeChecker = typeChecker;
this.passThroughTypes = new Map([
[ts.SyntaxKind.ExpressionStatement, createChildGetter()],
[ts.SyntaxKind.ParenthesizedExpression, createChildGetter()],
[ts.SyntaxKind.ParenthesizedType, createChildGetter()],
[ts.SyntaxKind.SyntaxList, createChildGetter()],
]);
this.typesWithKnownTypeNames = new Map([
[ts.SyntaxKind.ArrayLiteralExpression, new arrayLiteralExpressionAliaser_1.ArrayLiteralExpressionAliaser(typeChecker, this.getFriendlyTypeName)],
[ts.SyntaxKind.BooleanKeyword, new typeNameAliaser_1.TypeNameAliaser("boolean")],
[ts.SyntaxKind.ElementAccessExpression, new elementAccessExpressionAliaser_1.ElementAccessExpressionAliaser(typeChecker, this.getFriendlyTypeName)],
[ts.SyntaxKind.FalseKeyword, new typeNameAliaser_1.TypeNameAliaser("boolean")],
[ts.SyntaxKind.NewExpression, new newExpressionAliaser_1.NewExpressionAliaser(this.sourceFile)],
[ts.SyntaxKind.NumericLiteral, new numericAliaser_1.NumericAliaser(this.sourceFile)],
[ts.SyntaxKind.TrueKeyword, new typeNameAliaser_1.TypeNameAliaser("boolean")],
[ts.SyntaxKind.TypeLiteral, new typeLiteralAliaser_1.TypeLiteralAliaser(typeChecker, this.getFriendlyTypeName)],
[ts.SyntaxKind.StringKeyword, new typeNameAliaser_1.TypeNameAliaser("string")],
[ts.SyntaxKind.StringLiteral, new typeNameAliaser_1.TypeNameAliaser("string")],
[ts.SyntaxKind.VariableDeclaration, new propertyOrVariableDeclarationAliaser_1.PropertyOrVariableDeclarationAliaser(typeChecker, this.getFriendlyTypeName)],
]);
}
RootAliaser.prototype.getFriendlyPrivacyName = function (node) {
if (tsutils.hasModifier(node.modifiers, ts.SyntaxKind.PrivateKeyword)) {
return "private";
}
if (tsutils.hasModifier(node.modifiers, ts.SyntaxKind.ProtectedKeyword)) {
return "protected";
}
return "public";
};
RootAliaser.prototype.getFriendlyReturnTypeName = function (node) {
// If the node explicitly mentions a return type, use that
if (node.type !== undefined) {
return this.getFriendlyTypeName(node.type);
}
// The rest of this logic attempts to use the type checker to get a computed type symbol
var typeAtLocation = this.typeChecker.getTypeAtLocation(node);
var signaturesOfType = this.typeChecker.getSignaturesOfType(typeAtLocation, ts.SignatureKind.Call);
if (signaturesOfType.length !== 1) {
return undefined;
}
var signatureOfType = signaturesOfType[0];
var signatureReturnType = signatureOfType.getReturnType();
var symbol = signatureReturnType.getSymbol();
if (symbol !== undefined) {
return symbol.getName();
}
return signatureReturnType.intrinsicName;
};
return RootAliaser;
}());
exports.RootAliaser = RootAliaser;
//# sourceMappingURL=rootAliaser.js.map