ts-simple-ast
Version:
TypeScript compiler wrapper for AST navigation and code generation.
453 lines (452 loc) • 24.7 kB
JavaScript
"use strict";
var __extends = (this && this.__extends)/* istanbul ignore next */ || (function () {
var 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 function (d, b) {
extendStatics(d, b);
function __() { this.constructor = d; }
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
};
})();
var __assign = (this && this.__assign)/* istanbul ignore next */ || Object.assign || function(t) {
for (var s, i = 1, n = arguments.length; i < n; i++) {
s = arguments[i];
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
t[p] = s[p];
}
return t;
};
var __values = (this && this.__values)/* istanbul ignore next */ || function (o) {
var m = typeof Symbol === "function" && o[Symbol.iterator], i = 0;
if (m) return m.call(o);
return {
next: function () {
if (o && i >= o.length) o = void 0;
return { value: o && o[i++], done: !o };
}
};
};
var __read = (this && this.__read)/* istanbul ignore next */ || function (o, n) {
var m = typeof Symbol === "function" && o[Symbol.iterator];
if (!m) return o;
var i = m.call(o), r, ar = [], e;
try {
while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value);
}
catch (error) { e = { error: error }; }
finally {
try {
if (r && !r.done && (m = i["return"])) m.call(i);
}
finally { if (e) throw e.error; }
}
return ar;
};
var __spread = (this && this.__spread)/* istanbul ignore next */ || function () {
for (var ar = [], i = 0; i < arguments.length; i++) ar = ar.concat(__read(arguments[i]));
return ar;
};
Object.defineProperty(exports, "__esModule", { value: true });
var typescript_1 = require("./../../typescript");
var errors = require("./../../errors");
var structureToTexts = require("./../../structureToTexts");
var manipulation_1 = require("./../../manipulation");
var utils_1 = require("./../../utils");
var callBaseFill_1 = require("./../callBaseFill");
function StatementedNode(Base) {
return /** @class */ (function (_super) {
__extends(class_1, _super);
function class_1() {
return _super !== null && _super.apply(this, arguments) || this;
}
/* General */
class_1.prototype.getStatements = function () {
var _this = this;
return this.getCompilerStatements().map(function (s) { return _this.getNodeFromCompilerNode(s); });
};
class_1.prototype.getStatement = function (findFunction) {
return utils_1.ArrayUtils.find(this.getStatements(), findFunction);
};
class_1.prototype.getStatementOrThrow = function (findFunction) {
return errors.throwIfNullOrUndefined(this.getStatement(findFunction), "Expected to find a statement matching the provided condition.");
};
class_1.prototype.getStatementByKind = function (kind) {
var statement = utils_1.ArrayUtils.find(this.getCompilerStatements(), function (s) { return s.kind === kind; });
return this.getNodeFromCompilerNodeIfExists(statement);
};
class_1.prototype.getStatementByKindOrThrow = function (kind) {
return errors.throwIfNullOrUndefined(this.getStatementByKind(kind), "Expected to find a statement with syntax kind " + typescript_1.SyntaxKind[kind] + ".");
};
class_1.prototype.addStatements = function (textOrWriterFunction) {
var childSyntaxList = this.getChildSyntaxListOrThrow();
return this.insertStatements(childSyntaxList.getChildCount(), textOrWriterFunction);
};
class_1.prototype.insertStatements = function (index, textOrWriterFunction) {
return this.getChildSyntaxListOrThrow().insertChildText(index, textOrWriterFunction);
};
class_1.prototype.removeStatement = function (index) {
index = manipulation_1.verifyAndGetIndex(index, this.getStatements().length - 1);
return this.removeStatements([index, index]);
};
class_1.prototype.removeStatements = function (indexRange) {
var statements = this.getStatements();
errors.throwIfRangeOutOfRange(indexRange, [0, statements.length], "indexRange");
manipulation_1.removeStatementedNodeChildren(statements.slice(indexRange[0], indexRange[1] + 1));
return this;
};
/* Classes */
class_1.prototype.addClass = function (structure) {
return this.addClasses([structure])[0];
};
class_1.prototype.addClasses = function (structures) {
return this.insertClasses(this.getChildSyntaxListOrThrow().getChildCount(), structures);
};
class_1.prototype.insertClass = function (index, structure) {
return this.insertClasses(index, [structure])[0];
};
class_1.prototype.insertClasses = function (index, structures) {
var _this = this;
var texts = structures.map(function (s) {
// todo: pass in the StructureToText to the function below
var writer = _this.getWriterWithChildIndentation();
var structureToText = new structureToTexts.ClassDeclarationStructureToText(writer);
structureToText.writeText(s);
return writer.toString();
});
var newChildren = this._insertMainChildren(index, texts, structures, typescript_1.SyntaxKind.ClassDeclaration, function (child, i) {
child.fill(structures[i]);
});
return newChildren;
};
class_1.prototype.getClasses = function () {
// todo: remove type assertion
return this.getChildSyntaxListOrThrow().getChildrenOfKind(typescript_1.SyntaxKind.ClassDeclaration);
};
class_1.prototype.getClass = function (nameOrFindFunction) {
return utils_1.getNamedNodeByNameOrFindFunction(this.getClasses(), nameOrFindFunction);
};
class_1.prototype.getClassOrThrow = function (nameOrFindFunction) {
return errors.throwIfNullOrUndefined(this.getClass(nameOrFindFunction), function () { return utils_1.getNotFoundErrorMessageForNameOrFindFunction("class", nameOrFindFunction); });
};
/* Enums */
class_1.prototype.addEnum = function (structure) {
return this.addEnums([structure])[0];
};
class_1.prototype.addEnums = function (structures) {
return this.insertEnums(this.getChildSyntaxListOrThrow().getChildCount(), structures);
};
class_1.prototype.insertEnum = function (index, structure) {
return this.insertEnums(index, [structure])[0];
};
class_1.prototype.insertEnums = function (index, structures) {
var _this = this;
var texts = structures.map(function (s) {
// todo: pass in the StructureToText to the function below
var writer = _this.getWriterWithChildIndentation();
var structureToText = new structureToTexts.EnumDeclarationStructureToText(writer);
structureToText.writeText(s);
return writer.toString();
});
var newChildren = this._insertMainChildren(index, texts, structures, typescript_1.SyntaxKind.EnumDeclaration, function (child, i) {
child.fill(structures[i]);
});
return newChildren;
};
class_1.prototype.getEnums = function () {
// todo: remove type assertion
return this.getChildSyntaxListOrThrow().getChildrenOfKind(typescript_1.SyntaxKind.EnumDeclaration);
};
class_1.prototype.getEnum = function (nameOrFindFunction) {
return utils_1.getNamedNodeByNameOrFindFunction(this.getEnums(), nameOrFindFunction);
};
class_1.prototype.getEnumOrThrow = function (nameOrFindFunction) {
return errors.throwIfNullOrUndefined(this.getEnum(nameOrFindFunction), function () { return utils_1.getNotFoundErrorMessageForNameOrFindFunction("enum", nameOrFindFunction); });
};
/* Functions */
class_1.prototype.addFunction = function (structure) {
return this.addFunctions([structure])[0];
};
class_1.prototype.addFunctions = function (structures) {
return this.insertFunctions(this.getChildSyntaxListOrThrow().getChildCount(), structures);
};
class_1.prototype.insertFunction = function (index, structure) {
return this.insertFunctions(index, [structure])[0];
};
class_1.prototype.insertFunctions = function (index, structures) {
var _this = this;
var texts = structures.map(function (s) {
// todo: pass in the StructureToText to the function below
var writer = _this.getWriterWithChildIndentation();
var structureToText = new structureToTexts.FunctionDeclarationStructureToText(writer);
structureToText.writeText(s);
return writer.toString();
});
var newChildren = this._insertMainChildren(index, texts, structures, typescript_1.SyntaxKind.FunctionDeclaration, function (child, i) {
// todo: remove filling when writing
var params = structures[i].parameters;
delete structures[i].parameters;
child.fill(structures[i]);
if (params != null)
child.getParameters().forEach(function (p, j) { return p.fill(params[j]); });
});
return newChildren;
};
class_1.prototype.getFunctions = function () {
// todo: remove type assertion
return this.getChildSyntaxListOrThrow().getChildrenOfKind(typescript_1.SyntaxKind.FunctionDeclaration)
.filter(function (f) { return f.isAmbient() || f.isImplementation(); });
};
class_1.prototype.getFunction = function (nameOrFindFunction) {
return utils_1.getNamedNodeByNameOrFindFunction(this.getFunctions(), nameOrFindFunction);
};
class_1.prototype.getFunctionOrThrow = function (nameOrFindFunction) {
return errors.throwIfNullOrUndefined(this.getFunction(nameOrFindFunction), function () { return utils_1.getNotFoundErrorMessageForNameOrFindFunction("function", nameOrFindFunction); });
};
/* Interfaces */
class_1.prototype.addInterface = function (structure) {
return this.addInterfaces([structure])[0];
};
class_1.prototype.addInterfaces = function (structures) {
return this.insertInterfaces(this.getChildSyntaxListOrThrow().getChildCount(), structures);
};
class_1.prototype.insertInterface = function (index, structure) {
return this.insertInterfaces(index, [structure])[0];
};
class_1.prototype.insertInterfaces = function (index, structures) {
var _this = this;
var texts = structures.map(function (s) {
// todo: pass in the StructureToText to the function below
var writer = _this.getWriterWithChildIndentation();
var structureToText = new structureToTexts.InterfaceDeclarationStructureToText(writer);
structureToText.writeText(s);
return writer.toString();
});
var newChildren = this._insertMainChildren(index, texts, structures, typescript_1.SyntaxKind.InterfaceDeclaration, function (child, i) {
child.fill(structures[i]);
});
return newChildren;
};
class_1.prototype.getInterfaces = function () {
// todo: remove type assertion
return this.getChildSyntaxListOrThrow().getChildrenOfKind(typescript_1.SyntaxKind.InterfaceDeclaration);
};
class_1.prototype.getInterface = function (nameOrFindFunction) {
return utils_1.getNamedNodeByNameOrFindFunction(this.getInterfaces(), nameOrFindFunction);
};
class_1.prototype.getInterfaceOrThrow = function (nameOrFindFunction) {
return errors.throwIfNullOrUndefined(this.getInterface(nameOrFindFunction), function () { return utils_1.getNotFoundErrorMessageForNameOrFindFunction("interface", nameOrFindFunction); });
};
/* Namespaces */
class_1.prototype.addNamespace = function (structure) {
return this.addNamespaces([structure])[0];
};
class_1.prototype.addNamespaces = function (structures) {
return this.insertNamespaces(this.getChildSyntaxListOrThrow().getChildCount(), structures);
};
class_1.prototype.insertNamespace = function (index, structure) {
return this.insertNamespaces(index, [structure])[0];
};
class_1.prototype.insertNamespaces = function (index, structures) {
var _this = this;
var texts = structures.map(function (s) {
// todo: pass in the StructureToText to the function below
var writer = _this.getWriterWithChildIndentation();
var structureToText = new structureToTexts.NamespaceDeclarationStructureToText(writer);
structureToText.writeText(s);
return writer.toString();
});
var newChildren = this._insertMainChildren(index, texts, structures, typescript_1.SyntaxKind.ModuleDeclaration, function (child, i) {
child.fill(structures[i]);
});
return newChildren;
};
class_1.prototype.getNamespaces = function () {
return this.getChildSyntaxListOrThrow().getChildrenOfKind(typescript_1.SyntaxKind.ModuleDeclaration);
};
class_1.prototype.getNamespace = function (nameOrFindFunction) {
return utils_1.getNamedNodeByNameOrFindFunction(this.getNamespaces(), nameOrFindFunction);
};
class_1.prototype.getNamespaceOrThrow = function (nameOrFindFunction) {
return errors.throwIfNullOrUndefined(this.getNamespace(nameOrFindFunction), function () { return utils_1.getNotFoundErrorMessageForNameOrFindFunction("namespace", nameOrFindFunction); });
};
/* Type aliases */
class_1.prototype.addTypeAlias = function (structure) {
return this.addTypeAliases([structure])[0];
};
class_1.prototype.addTypeAliases = function (structures) {
return this.insertTypeAliases(this.getChildSyntaxListOrThrow().getChildCount(), structures);
};
class_1.prototype.insertTypeAlias = function (index, structure) {
return this.insertTypeAliases(index, [structure])[0];
};
class_1.prototype.insertTypeAliases = function (index, structures) {
var _this = this;
var texts = structures.map(function (s) {
// todo: pass in the StructureToText to the function below
var writer = _this.getWriterWithChildIndentation();
var structureToText = new structureToTexts.TypeAliasDeclarationStructureToText(writer);
structureToText.writeText(s);
return writer.toString();
});
var newChildren = this._insertMainChildren(index, texts, structures, typescript_1.SyntaxKind.TypeAliasDeclaration, function (child, i) {
child.fill(structures[i]);
}, {
previousBlanklineWhen: function (previousMember) { return !utils_1.TypeGuards.isTypeAliasDeclaration(previousMember); },
separatorNewlineWhen: function () { return false; },
nextBlanklineWhen: function (nextMember) { return !utils_1.TypeGuards.isTypeAliasDeclaration(nextMember); }
});
return newChildren;
};
class_1.prototype.getTypeAliases = function () {
// todo: remove type assertion
return this.getChildSyntaxListOrThrow().getChildrenOfKind(typescript_1.SyntaxKind.TypeAliasDeclaration);
};
class_1.prototype.getTypeAlias = function (nameOrFindFunction) {
return utils_1.getNamedNodeByNameOrFindFunction(this.getTypeAliases(), nameOrFindFunction);
};
class_1.prototype.getTypeAliasOrThrow = function (nameOrFindFunction) {
return errors.throwIfNullOrUndefined(this.getTypeAlias(nameOrFindFunction), function () { return utils_1.getNotFoundErrorMessageForNameOrFindFunction("type alias", nameOrFindFunction); });
};
/* Variable statements */
class_1.prototype.getVariableStatements = function () {
return this.getChildSyntaxListOrThrow().getChildrenOfKind(typescript_1.SyntaxKind.VariableStatement);
};
class_1.prototype.getVariableStatement = function (findFunction) {
return utils_1.ArrayUtils.find(this.getVariableStatements(), findFunction);
};
class_1.prototype.getVariableStatementOrThrow = function (findFunction) {
return errors.throwIfNullOrUndefined(this.getVariableStatement(findFunction), "Expected to find a variable statement that matched the provided condition.");
};
class_1.prototype.addVariableStatement = function (structure) {
return this.addVariableStatements([structure])[0];
};
class_1.prototype.addVariableStatements = function (structures) {
return this.insertVariableStatements(this.getChildSyntaxListOrThrow().getChildCount(), structures);
};
class_1.prototype.insertVariableStatement = function (index, structure) {
return this.insertVariableStatements(index, [structure])[0];
};
class_1.prototype.insertVariableStatements = function (index, structures) {
var _this = this;
var texts = structures.map(function (s) {
// todo: pass in the StructureToText to the function below
var writer = _this.getWriterWithChildIndentation();
var structureToText = new structureToTexts.VariableStatementStructureToText(writer);
structureToText.writeText(s);
return writer.toString();
});
var newChildren = this._insertMainChildren(index, texts, structures, typescript_1.SyntaxKind.VariableStatement, function (child, i) {
var structure = __assign({}, structures[i]);
delete structure.declarations;
delete structure.declarationType;
child.fill(structure);
}, {
previousBlanklineWhen: function (previousMember) { return !utils_1.TypeGuards.isVariableStatement(previousMember); },
separatorNewlineWhen: function () { return false; },
nextBlanklineWhen: function (nextMember) { return !utils_1.TypeGuards.isVariableStatement(nextMember); }
});
return newChildren;
};
/* Variable declarations */
class_1.prototype.getVariableDeclarations = function () {
var variables = [];
try {
for (var _a = __values(this.getVariableStatements()), _b = _a.next(); !_b.done; _b = _a.next()) {
var list = _b.value;
variables.push.apply(variables, __spread(list.getDeclarations()));
}
}
catch (e_1_1) { e_1 = { error: e_1_1 }; }
finally {
try {
if (_b && !_b.done && (_c = _a.return)) _c.call(_a);
}
finally { if (e_1) throw e_1.error; }
}
return variables;
var e_1, _c;
};
class_1.prototype.getVariableDeclaration = function (nameOrFindFunction) {
return utils_1.getNamedNodeByNameOrFindFunction(this.getVariableDeclarations(), nameOrFindFunction);
};
class_1.prototype.getVariableDeclarationOrThrow = function (nameOrFindFunction) {
return errors.throwIfNullOrUndefined(this.getVariableDeclaration(nameOrFindFunction), function () { return utils_1.getNotFoundErrorMessageForNameOrFindFunction("variable declaration", nameOrFindFunction); });
};
class_1.prototype.fill = function (structure) {
callBaseFill_1.callBaseFill(Base.prototype, this, structure);
if (structure.classes != null && structure.classes.length > 0)
this.addClasses(structure.classes);
if (structure.enums != null && structure.enums.length > 0)
this.addEnums(structure.enums);
if (structure.functions != null && structure.functions.length > 0)
this.addFunctions(structure.functions);
if (structure.interfaces != null && structure.interfaces.length > 0)
this.addInterfaces(structure.interfaces);
if (structure.namespaces != null && structure.namespaces.length > 0)
this.addNamespaces(structure.namespaces);
if (structure.typeAliases != null && structure.typeAliases.length > 0)
this.addTypeAliases(structure.typeAliases);
return this;
};
/**
* @internal
*/
class_1.prototype.getCompilerStatements = function () {
if (utils_1.TypeGuards.isSourceFile(this) || utils_1.TypeGuards.isCaseClause(this) || utils_1.TypeGuards.isDefaultClause(this))
return this.compilerNode.statements;
else if (utils_1.TypeGuards.isNamespaceDeclaration(this)) {
// need to get the inner-most body for namespaces
var node = this;
while (utils_1.TypeGuards.isBodiedNode(node) && node.compilerNode.statements == null) {
node = node.getBody();
}
return node.compilerNode.statements;
}
else if (utils_1.TypeGuards.isBodyableNode(this))
return this.getBodyOrThrow().compilerNode.statements;
else if (utils_1.TypeGuards.isBodiedNode(this))
return this.getBody().compilerNode.statements;
else
throw new errors.NotImplementedError("Could not find the statements for the node: " + this.getText());
};
// todo: make this passed an object
/**
* @internal
*/
class_1.prototype._insertMainChildren = function (index, childCodes, structures, expectedSyntaxKind, withEachChild, opts) {
if (opts === void 0) { opts = {}; }
var syntaxList = this.getChildSyntaxListOrThrow();
var mainChildren = syntaxList.getChildren();
var newLineChar = this.global.manipulationSettings.getNewLineKindAsString();
index = manipulation_1.verifyAndGetIndex(index, mainChildren.length);
// insert into a temp file
var finalChildCodes = [];
for (var i = 0; i < childCodes.length; i++) {
var tempSourceFile = this.global.compilerFactory.createTempSourceFileFromText(childCodes[i], { createLanguageService: true });
if (withEachChild != null) {
var tempSyntaxList = tempSourceFile.getChildSyntaxListOrThrow();
withEachChild(tempSyntaxList.getChildren()[0], i);
}
finalChildCodes.push(tempSourceFile.getFullText());
}
// insert
var doBlankLine = function () { return true; };
manipulation_1.insertIntoBracesOrSourceFile({
parent: this,
children: mainChildren,
index: index,
childCodes: finalChildCodes,
structures: structures,
separator: newLineChar,
previousBlanklineWhen: opts.previousBlanklineWhen || doBlankLine,
separatorNewlineWhen: opts.separatorNewlineWhen || doBlankLine,
nextBlanklineWhen: opts.nextBlanklineWhen || doBlankLine
});
// get children
return manipulation_1.getRangeFromArray(syntaxList.getChildren(), index, childCodes.length, expectedSyntaxKind);
};
return class_1;
}(Base));
}
exports.StatementedNode = StatementedNode;