ts-simple-ast
Version:
TypeScript compiler wrapper for static analysis and code manipulation.
458 lines (457 loc) • 25 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
var tslib_1 = require("tslib");
var errors = require("../../../errors");
var manipulation_1 = require("../../../manipulation");
var typescript_1 = require("../../../typescript");
var utils_1 = require("../../../utils");
var callBaseSet_1 = require("../callBaseSet");
function StatementedNode(Base) {
return /** @class */ (function (_super) {
tslib_1.__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) {
// explicit type arg necessary in ts 3.0 for some reason
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 " + utils_1.getSyntaxKindName(kind) + ".");
};
class_1.prototype.addStatements = function (textOrWriterFunction) {
return this.insertStatements(this.getCompilerStatements().length, textOrWriterFunction);
};
class_1.prototype.insertStatements = function (index, textOrWriterFunction) {
addBodyIfNotExists(this);
return getChildSyntaxList.call(this).insertChildText(index, textOrWriterFunction);
function getChildSyntaxList() {
var childSyntaxList = this.getChildSyntaxListOrThrow();
// case and default clauses can optionally have blocks
if (utils_1.TypeGuards.isCaseClause(this) || utils_1.TypeGuards.isDefaultClause(this)) {
var block = childSyntaxList.getFirstChildIfKind(typescript_1.SyntaxKind.Block);
if (block != null)
return block.getChildSyntaxListOrThrow();
}
return childSyntaxList;
}
};
class_1.prototype.removeStatement = function (index) {
index = manipulation_1.verifyAndGetIndex(index, this.getCompilerStatements().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.getCompilerStatements().length, structures);
};
class_1.prototype.insertClass = function (index, structure) {
return this.insertClasses(index, [structure])[0];
};
class_1.prototype.insertClasses = function (index, structures) {
var _this = this;
return this._insertChildren({
expectedKind: typescript_1.SyntaxKind.ClassDeclaration,
index: index,
structures: structures,
write: function (writer, info) {
_this._standardWrite(writer, info, function () {
_this._context.structurePrinterFactory.forClassDeclaration({ isAmbient: utils_1.isNodeAmbientOrInAmbientContext(_this) }).printTexts(writer, structures);
});
}
});
};
class_1.prototype.getClasses = function () {
var childSyntaxList = this.getChildSyntaxList();
if (childSyntaxList == null)
return []; // no body
return childSyntaxList.getChildrenOfKind(typescript_1.SyntaxKind.ClassDeclaration);
};
class_1.prototype.getClass = function (nameOrFindFunction) {
return utils_1.getNodeByNameOrFindFunction(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.getCompilerStatements().length, structures);
};
class_1.prototype.insertEnum = function (index, structure) {
return this.insertEnums(index, [structure])[0];
};
class_1.prototype.insertEnums = function (index, structures) {
var _this = this;
return this._insertChildren({
expectedKind: typescript_1.SyntaxKind.EnumDeclaration,
index: index,
structures: structures,
write: function (writer, info) {
_this._standardWrite(writer, info, function () {
_this._context.structurePrinterFactory.forEnumDeclaration().printTexts(writer, structures);
});
}
});
};
class_1.prototype.getEnums = function () {
var childSyntaxList = this.getChildSyntaxList();
if (childSyntaxList == null)
return []; // no body
return childSyntaxList.getChildrenOfKind(typescript_1.SyntaxKind.EnumDeclaration);
};
class_1.prototype.getEnum = function (nameOrFindFunction) {
return utils_1.getNodeByNameOrFindFunction(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.getCompilerStatements().length, structures);
};
class_1.prototype.insertFunction = function (index, structure) {
return this.insertFunctions(index, [structure])[0];
};
class_1.prototype.insertFunctions = function (index, structures) {
var _this = this;
return this._insertChildren({
expectedKind: typescript_1.SyntaxKind.FunctionDeclaration,
index: index,
structures: structures,
write: function (writer, info) {
_this._standardWrite(writer, info, function () {
_this._context.structurePrinterFactory.forFunctionDeclaration({
isAmbient: utils_1.isNodeAmbientOrInAmbientContext(_this)
}).printTexts(writer, structures);
}, {
previousNewLine: function (previousMember) {
return structures[0].hasDeclareKeyword === true && utils_1.TypeGuards.isFunctionDeclaration(previousMember) && previousMember.getBody() == null;
},
nextNewLine: function (nextMember) {
return structures[structures.length - 1].hasDeclareKeyword === true && utils_1.TypeGuards.isFunctionDeclaration(nextMember) && nextMember.getBody() == null;
}
});
}
});
};
class_1.prototype.getFunctions = function () {
var childSyntaxList = this.getChildSyntaxList();
if (childSyntaxList == null)
return []; // no body
return (childSyntaxList.getChildrenOfKind(typescript_1.SyntaxKind.FunctionDeclaration))
.filter(function (f) { return f.isAmbient() || f.isImplementation(); });
};
class_1.prototype.getFunction = function (nameOrFindFunction) {
return utils_1.getNodeByNameOrFindFunction(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.getCompilerStatements().length, structures);
};
class_1.prototype.insertInterface = function (index, structure) {
return this.insertInterfaces(index, [structure])[0];
};
class_1.prototype.insertInterfaces = function (index, structures) {
var _this = this;
return this._insertChildren({
expectedKind: typescript_1.SyntaxKind.InterfaceDeclaration,
index: index,
structures: structures,
write: function (writer, info) {
_this._standardWrite(writer, info, function () {
_this._context.structurePrinterFactory.forInterfaceDeclaration().printTexts(writer, structures);
});
}
});
};
class_1.prototype.getInterfaces = function () {
var childSyntaxList = this.getChildSyntaxList();
if (childSyntaxList == null)
return []; // no body
return childSyntaxList.getChildrenOfKind(typescript_1.SyntaxKind.InterfaceDeclaration);
};
class_1.prototype.getInterface = function (nameOrFindFunction) {
return utils_1.getNodeByNameOrFindFunction(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.getCompilerStatements().length, structures);
};
class_1.prototype.insertNamespace = function (index, structure) {
return this.insertNamespaces(index, [structure])[0];
};
class_1.prototype.insertNamespaces = function (index, structures) {
var _this = this;
return this._insertChildren({
expectedKind: typescript_1.SyntaxKind.ModuleDeclaration,
index: index,
structures: structures,
write: function (writer, info) {
_this._standardWrite(writer, info, function () {
_this._context.structurePrinterFactory.forNamespaceDeclaration({ isAmbient: utils_1.isNodeAmbientOrInAmbientContext(_this) }).printTexts(writer, structures);
});
}
});
};
class_1.prototype.getNamespaces = function () {
var childSyntaxList = this.getChildSyntaxList();
if (childSyntaxList == null)
return []; // no body
return childSyntaxList.getChildrenOfKind(typescript_1.SyntaxKind.ModuleDeclaration);
};
class_1.prototype.getNamespace = function (nameOrFindFunction) {
return utils_1.getNodeByNameOrFindFunction(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.getCompilerStatements().length, structures);
};
class_1.prototype.insertTypeAlias = function (index, structure) {
return this.insertTypeAliases(index, [structure])[0];
};
class_1.prototype.insertTypeAliases = function (index, structures) {
var _this = this;
return this._insertChildren({
expectedKind: typescript_1.SyntaxKind.TypeAliasDeclaration,
index: index,
structures: structures,
write: function (writer, info) {
_this._standardWrite(writer, info, function () {
_this._context.structurePrinterFactory.forTypeAliasDeclaration().printTexts(writer, structures);
}, {
previousNewLine: function (previousMember) { return utils_1.TypeGuards.isTypeAliasDeclaration(previousMember); },
nextNewLine: function (nextMember) { return utils_1.TypeGuards.isTypeAliasDeclaration(nextMember); }
});
}
});
};
class_1.prototype.getTypeAliases = function () {
var childSyntaxList = this.getChildSyntaxList();
if (childSyntaxList == null)
return []; // no body
return childSyntaxList.getChildrenOfKind(typescript_1.SyntaxKind.TypeAliasDeclaration);
};
class_1.prototype.getTypeAlias = function (nameOrFindFunction) {
return utils_1.getNodeByNameOrFindFunction(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 () {
var childSyntaxList = this.getChildSyntaxList();
if (childSyntaxList == null)
return []; // no body
return childSyntaxList.getChildrenOfKind(typescript_1.SyntaxKind.VariableStatement);
};
class_1.prototype.getVariableStatement = function (nameOrFindFunction) {
return utils_1.ArrayUtils.find(this.getVariableStatements(), getFindFunction());
function getFindFunction() {
if (typeof nameOrFindFunction === "string")
return function (statement) { return statement.getDeclarations().some(function (d) { return utils_1.nodeHasName(d, nameOrFindFunction); }); };
return nameOrFindFunction;
}
};
class_1.prototype.getVariableStatementOrThrow = function (nameOrFindFunction) {
return errors.throwIfNullOrUndefined(this.getVariableStatement(nameOrFindFunction), "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.getCompilerStatements().length, structures);
};
class_1.prototype.insertVariableStatement = function (index, structure) {
return this.insertVariableStatements(index, [structure])[0];
};
class_1.prototype.insertVariableStatements = function (index, structures) {
var _this = this;
return this._insertChildren({
expectedKind: typescript_1.SyntaxKind.VariableStatement,
index: index,
structures: structures,
write: function (writer, info) {
_this._standardWrite(writer, info, function () {
_this._context.structurePrinterFactory.forVariableStatement().printTexts(writer, structures);
}, {
previousNewLine: function (previousMember) { return utils_1.TypeGuards.isVariableStatement(previousMember); },
nextNewLine: function (nextMember) { return utils_1.TypeGuards.isVariableStatement(nextMember); }
});
}
});
};
/* Variable declarations */
class_1.prototype.getVariableDeclarations = function () {
var e_1, _a;
var variables = [];
try {
for (var _b = tslib_1.__values(this.getVariableStatements()), _c = _b.next(); !_c.done; _c = _b.next()) {
var list = _c.value;
variables.push.apply(variables, tslib_1.__spread(list.getDeclarations()));
}
}
catch (e_1_1) { e_1 = { error: e_1_1 }; }
finally {
try {
if (_c && !_c.done && (_a = _b.return)) _a.call(_b);
}
finally { if (e_1) throw e_1.error; }
}
return variables;
};
class_1.prototype.getVariableDeclaration = function (nameOrFindFunction) {
return utils_1.getNodeByNameOrFindFunction(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.set = function (structure) {
var _this = this;
var structureCopy = tslib_1.__assign({}, structure);
// remove the body text first if necessary
var bodyText = structureCopy.bodyText;
if (utils_1.TypeGuards.isBodiedNode(this) || utils_1.TypeGuards.isBodyableNode(this)) {
if (structureCopy.bodyText != null) {
var statementCount = this.getCompilerStatements().length;
if (statementCount > 0)
this.removeStatements([0, statementCount - 1]);
}
else if (utils_1.TypeGuards.isBodyableNode(this) && structureCopy.hasOwnProperty("bodyText"))
this.removeBody();
}
delete structureCopy.bodyText; // do not set this in BodiedNode or BodyableNode, set it below
callBaseSet_1.callBaseSet(Base.prototype, this, structureCopy);
if (structure.classes != null) {
this.getClasses().forEach(function (c) { return c.remove(); });
this.addClasses(structure.classes);
}
if (structure.enums != null) {
this.getEnums().forEach(function (e) { return e.remove(); });
this.addEnums(structure.enums);
}
if (structure.functions != null) {
this.getFunctions().forEach(function (i) { return i.remove(); });
this.addFunctions(structure.functions);
}
if (structure.interfaces != null) {
this.getInterfaces().forEach(function (i) { return i.remove(); });
this.addInterfaces(structure.interfaces);
}
if (structure.namespaces != null) {
this.getNamespaces().forEach(function (n) { return n.remove(); });
this.addNamespaces(structure.namespaces);
}
if (structure.typeAliases != null) {
this.getTypeAliases().forEach(function (t) { return t.remove(); });
this.addTypeAliases(structure.typeAliases);
}
// set the body text after adding everything else
if (utils_1.TypeGuards.isBodiedNode(this) || utils_1.TypeGuards.isBodyableNode(this)) {
if (bodyText != null)
this.addStatements(function (writer) {
writer.conditionalNewLine(_this.getCompilerStatements().length > 0);
utils_1.printTextFromStringOrWriter(writer, bodyText);
});
}
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
return this._getInnerBody().compilerNode.statements;
}
else if (utils_1.TypeGuards.isBodyableNode(this)) {
var body = this.getBody();
if (body == null)
return [];
return body.compilerNode.statements;
}
else if (utils_1.TypeGuards.isBodiedNode(this)) {
return this.getBody().compilerNode.statements;
}
else if (utils_1.TypeGuards.isBlock(this))
return this.compilerNode.statements;
else
throw new errors.NotImplementedError("Could not find the statements for node kind: " + this.getKindName() + ", text: " + this.getText());
};
class_1.prototype._insertChildren = function (opts) {
var _this = this;
addBodyIfNotExists(this);
return manipulation_1.insertIntoBracesOrSourceFileWithGetChildren({
expectedKind: opts.expectedKind,
getIndexedChildren: function () { return _this.getStatements(); },
index: opts.index,
parent: this,
structures: opts.structures,
write: function (writer, info) { return opts.write(writer, info); }
});
};
class_1.prototype._standardWrite = function (writer, info, writeStructures, opts) {
if (opts === void 0) { opts = {}; }
if (info.previousMember != null && (opts.previousNewLine == null || !opts.previousNewLine(info.previousMember)))
writer.blankLine();
else if (!info.isStartOfFile)
writer.newLine();
writeStructures();
if (info.nextMember != null && (opts.nextNewLine == null || !opts.nextNewLine(info.nextMember)))
writer.blankLine();
else
writer.newLine();
};
return class_1;
}(Base));
}
exports.StatementedNode = StatementedNode;
function addBodyIfNotExists(node) {
if (utils_1.TypeGuards.isBodyableNode(node) && !node.hasBody())
node.addBody();
}