ts-simple-ast
Version:
TypeScript compiler wrapper for static analysis and code manipulation.
480 lines (479 loc) • 27.6 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
var tslib_1 = require("tslib");
var typescript_1 = require("../../../../typescript");
var errors = require("../../../../errors");
var manipulation_1 = require("../../../../manipulation");
var utils_1 = require("../../../../utils");
var base_1 = require("../../base");
var function_1 = require("../../function");
var _1 = require(".");
var MethodDeclaration_1 = require("../MethodDeclaration");
function ClassLikeDeclarationBase(Base) {
return ClassLikeDeclarationBaseSpecific(base_1.NameableNode(base_1.TextInsertableNode(base_1.ImplementsClauseableNode(base_1.HeritageClauseableNode(_1.AbstractableNode(base_1.JSDocableNode(base_1.TypeParameteredNode(base_1.DecoratableNode(base_1.ModifierableNode(Base))))))))));
}
exports.ClassLikeDeclarationBase = ClassLikeDeclarationBase;
function ClassLikeDeclarationBaseSpecific(Base) {
return /** @class */ (function (_super) {
tslib_1.__extends(class_1, _super);
function class_1() {
return _super !== null && _super.apply(this, arguments) || this;
}
class_1.prototype.setExtends = function (text) {
text = this._getTextWithQueuedChildIndentation(text);
if (utils_1.StringUtils.isNullOrWhitespace(text))
return this.removeExtends();
var extendsClause = this.getHeritageClauseByKind(typescript_1.SyntaxKind.ExtendsKeyword);
if (extendsClause != null) {
var childSyntaxList = extendsClause.getFirstChildByKindOrThrow(typescript_1.SyntaxKind.SyntaxList);
var childSyntaxListStart = childSyntaxList.getStart();
manipulation_1.insertIntoParentTextRange({
parent: extendsClause,
newText: text,
insertPos: childSyntaxListStart,
replacing: {
textLength: childSyntaxList.getEnd() - childSyntaxListStart
}
});
}
else {
var implementsClause = this.getHeritageClauseByKind(typescript_1.SyntaxKind.ImplementsKeyword);
var insertPos = void 0;
if (implementsClause != null)
insertPos = implementsClause.getStart();
else
insertPos = this.getFirstChildByKindOrThrow(typescript_1.SyntaxKind.OpenBraceToken).getStart();
var isLastSpace = /\s/.test(this.getSourceFile().getFullText()[insertPos - 1]);
var newText = "extends " + text + " ";
if (!isLastSpace)
newText = " " + newText;
manipulation_1.insertIntoParentTextRange({
parent: implementsClause == null ? this : implementsClause.getParentSyntaxListOrThrow(),
insertPos: insertPos,
newText: newText
});
}
return this;
};
class_1.prototype.removeExtends = function () {
var extendsClause = this.getHeritageClauseByKind(typescript_1.SyntaxKind.ExtendsKeyword);
if (extendsClause == null)
return this;
extendsClause.removeExpression(0);
return this;
};
class_1.prototype.getExtendsOrThrow = function () {
return errors.throwIfNullOrUndefined(this.getExtends(), "Expected to find the extends expression for the class " + this.getName() + ".");
};
class_1.prototype.getExtends = function () {
var extendsClause = this.getHeritageClauseByKind(typescript_1.SyntaxKind.ExtendsKeyword);
if (extendsClause == null)
return undefined;
var types = extendsClause.getTypeNodes();
return types.length === 0 ? undefined : types[0];
};
class_1.prototype.addConstructor = function (structure) {
if (structure === void 0) { structure = {}; }
return this.insertConstructor(manipulation_1.getEndIndexFromArray(this.getMembers()), structure);
};
class_1.prototype.addConstructors = function (structures) {
return this.insertConstructors(manipulation_1.getEndIndexFromArray(this.getMembers()), structures);
};
class_1.prototype.insertConstructor = function (index, structure) {
if (structure === void 0) { structure = {}; }
return this.insertConstructors(index, [structure])[0];
};
class_1.prototype.insertConstructors = function (index, structures) {
var _this = this;
var isAmbient = utils_1.TypeGuards.isAmbientableNode(this) && this.isAmbient();
return manipulation_1.insertIntoBracesOrSourceFileWithGetChildren({
getIndexedChildren: function () { return _this.getMembers(); },
parent: this,
index: index,
structures: structures,
expectedKind: typescript_1.SyntaxKind.Constructor,
write: function (writer, info) {
if (!isAmbient && info.previousMember != null)
writer.blankLineIfLastNot();
else
writer.newLineIfLastNot();
_this._context.structurePrinterFactory.forConstructorDeclaration({ isAmbient: isAmbient }).printTexts(writer, structures);
if (!isAmbient && info.nextMember != null)
writer.blankLineIfLastNot();
else
writer.newLineIfLastNot();
}
});
};
class_1.prototype.getConstructors = function () {
return this.getMembers().filter(function (m) { return utils_1.TypeGuards.isConstructorDeclaration(m); });
};
class_1.prototype.addGetAccessor = function (structure) {
return this.addGetAccessors([structure])[0];
};
class_1.prototype.addGetAccessors = function (structures) {
return this.insertGetAccessors(manipulation_1.getEndIndexFromArray(this.getMembers()), structures);
};
class_1.prototype.insertGetAccessor = function (index, structure) {
return this.insertGetAccessors(index, [structure])[0];
};
class_1.prototype.insertGetAccessors = function (index, structures) {
var _this = this;
return manipulation_1.insertIntoBracesOrSourceFileWithGetChildren({
getIndexedChildren: function () { return _this.getMembers(); },
parent: this,
index: index,
structures: structures,
expectedKind: typescript_1.SyntaxKind.GetAccessor,
write: function (writer, info) {
if (info.previousMember != null)
writer.blankLineIfLastNot();
else
writer.newLineIfLastNot();
_this._context.structurePrinterFactory.forGetAccessorDeclaration({
isAmbient: utils_1.TypeGuards.isAmbientableNode(_this) && _this.isAmbient()
}).printTexts(writer, structures);
if (info.nextMember != null)
writer.blankLineIfLastNot();
else
writer.newLineIfLastNot();
}
});
};
class_1.prototype.addSetAccessor = function (structure) {
return this.addSetAccessors([structure])[0];
};
class_1.prototype.addSetAccessors = function (structures) {
return this.insertSetAccessors(manipulation_1.getEndIndexFromArray(this.getMembers()), structures);
};
class_1.prototype.insertSetAccessor = function (index, structure) {
return this.insertSetAccessors(index, [structure])[0];
};
class_1.prototype.insertSetAccessors = function (index, structures) {
var _this = this;
return manipulation_1.insertIntoBracesOrSourceFileWithGetChildren({
getIndexedChildren: function () { return _this.getMembers(); },
parent: this,
index: index,
structures: structures,
expectedKind: typescript_1.SyntaxKind.SetAccessor,
write: function (writer, info) {
if (info.previousMember != null)
writer.blankLineIfLastNot();
else
writer.newLineIfLastNot();
_this._context.structurePrinterFactory.forSetAccessorDeclaration({
isAmbient: utils_1.TypeGuards.isAmbientableNode(_this) && _this.isAmbient()
}).printTexts(writer, structures);
if (info.nextMember != null)
writer.blankLineIfLastNot();
else
writer.newLineIfLastNot();
}
});
};
class_1.prototype.addProperty = function (structure) {
return this.addProperties([structure])[0];
};
class_1.prototype.addProperties = function (structures) {
return this.insertProperties(manipulation_1.getEndIndexFromArray(this.getMembers()), structures);
};
class_1.prototype.insertProperty = function (index, structure) {
return this.insertProperties(index, [structure])[0];
};
class_1.prototype.insertProperties = function (index, structures) {
var _this = this;
return manipulation_1.insertIntoBracesOrSourceFileWithGetChildren({
getIndexedChildren: function () { return _this.getMembers(); },
parent: this,
index: index,
structures: structures,
expectedKind: typescript_1.SyntaxKind.PropertyDeclaration,
write: function (writer, info) {
if (info.previousMember != null && utils_1.TypeGuards.hasBody(info.previousMember))
writer.blankLineIfLastNot();
else
writer.newLineIfLastNot();
_this._context.structurePrinterFactory.forPropertyDeclaration().printTexts(writer, structures);
if (info.nextMember != null && utils_1.TypeGuards.hasBody(info.nextMember))
writer.blankLineIfLastNot();
else
writer.newLineIfLastNot();
}
});
};
class_1.prototype.getInstanceProperty = function (nameOrFindFunction) {
return utils_1.getNodeByNameOrFindFunction(this.getInstanceProperties(), nameOrFindFunction);
};
class_1.prototype.getInstancePropertyOrThrow = function (nameOrFindFunction) {
return errors.throwIfNullOrUndefined(this.getInstanceProperty(nameOrFindFunction), function () { return utils_1.getNotFoundErrorMessageForNameOrFindFunction("class instance property", nameOrFindFunction); });
};
class_1.prototype.getInstanceProperties = function () {
return this.getInstanceMembers()
.filter(function (m) { return isClassPropertyType(m); });
};
class_1.prototype.getStaticProperty = function (nameOrFindFunction) {
return utils_1.getNodeByNameOrFindFunction(this.getStaticProperties(), nameOrFindFunction);
};
class_1.prototype.getStaticPropertyOrThrow = function (nameOrFindFunction) {
return errors.throwIfNullOrUndefined(this.getStaticProperty(nameOrFindFunction), function () { return utils_1.getNotFoundErrorMessageForNameOrFindFunction("class static property", nameOrFindFunction); });
};
class_1.prototype.getStaticProperties = function () {
return this.getStaticMembers()
.filter(function (m) { return isClassPropertyType(m); });
};
class_1.prototype.getProperty = function (nameOrFindFunction) {
return utils_1.getNodeByNameOrFindFunction(this.getProperties(), nameOrFindFunction);
};
class_1.prototype.getPropertyOrThrow = function (nameOrFindFunction) {
return errors.throwIfNullOrUndefined(this.getProperty(nameOrFindFunction), function () { return utils_1.getNotFoundErrorMessageForNameOrFindFunction("class property declaration", nameOrFindFunction); });
};
class_1.prototype.getProperties = function () {
return this.getMembers()
.filter(function (m) { return utils_1.TypeGuards.isPropertyDeclaration(m); });
};
class_1.prototype.getGetAccessor = function (nameOrFindFunction) {
return utils_1.getNodeByNameOrFindFunction(this.getGetAccessors(), nameOrFindFunction);
};
class_1.prototype.getGetAccessorOrThrow = function (nameOrFindFunction) {
return errors.throwIfNullOrUndefined(this.getGetAccessor(nameOrFindFunction), function () { return utils_1.getNotFoundErrorMessageForNameOrFindFunction("class getAccessor declaration", nameOrFindFunction); });
};
class_1.prototype.getGetAccessors = function () {
return this.getMembers()
.filter(function (m) { return utils_1.TypeGuards.isGetAccessorDeclaration(m); });
};
class_1.prototype.getSetAccessor = function (nameOrFindFunction) {
return utils_1.getNodeByNameOrFindFunction(this.getSetAccessors(), nameOrFindFunction);
};
class_1.prototype.getSetAccessorOrThrow = function (nameOrFindFunction) {
return errors.throwIfNullOrUndefined(this.getSetAccessor(nameOrFindFunction), function () { return utils_1.getNotFoundErrorMessageForNameOrFindFunction("class setAccessor declaration", nameOrFindFunction); });
};
class_1.prototype.getSetAccessors = function () {
return this.getMembers()
.filter(function (m) { return utils_1.TypeGuards.isSetAccessorDeclaration(m); });
};
class_1.prototype.addMethod = function (structure) {
return this.addMethods([structure])[0];
};
class_1.prototype.addMethods = function (structures) {
return this.insertMethods(manipulation_1.getEndIndexFromArray(this.getMembers()), structures);
};
class_1.prototype.insertMethod = function (index, structure) {
return this.insertMethods(index, [structure])[0];
};
class_1.prototype.insertMethods = function (index, structures) {
var _this = this;
var isAmbient = utils_1.TypeGuards.isAmbientableNode(this) && this.isAmbient();
structures = structures.map(function (s) { return (tslib_1.__assign({}, s)); });
// insert, fill, and get created nodes
return manipulation_1.insertIntoBracesOrSourceFileWithGetChildren({
parent: this,
index: index,
getIndexedChildren: function () { return _this.getMembers(); },
write: function (writer, info) {
if (!isAmbient && info.previousMember != null)
writer.blankLineIfLastNot();
else
writer.newLineIfLastNot();
_this._context.structurePrinterFactory.forMethodDeclaration({ isAmbient: isAmbient }).printTexts(writer, structures);
if (!isAmbient && info.nextMember != null)
writer.blankLineIfLastNot();
else
writer.newLineIfLastNot();
},
structures: structures,
expectedKind: typescript_1.SyntaxKind.MethodDeclaration
});
};
class_1.prototype.getMethod = function (nameOrFindFunction) {
return utils_1.getNodeByNameOrFindFunction(this.getMethods(), nameOrFindFunction);
};
class_1.prototype.getMethodOrThrow = function (nameOrFindFunction) {
return errors.throwIfNullOrUndefined(this.getMethod(nameOrFindFunction), function () { return utils_1.getNotFoundErrorMessageForNameOrFindFunction("class method declaration", nameOrFindFunction); });
};
class_1.prototype.getMethods = function () {
return this.getMembers()
.filter(function (m) { return utils_1.TypeGuards.isMethodDeclaration(m); });
};
class_1.prototype.getInstanceMethod = function (nameOrFindFunction) {
return utils_1.getNodeByNameOrFindFunction(this.getInstanceMethods(), nameOrFindFunction);
};
class_1.prototype.getInstanceMethodOrThrow = function (nameOrFindFunction) {
return errors.throwIfNullOrUndefined(this.getInstanceMethod(nameOrFindFunction), function () { return utils_1.getNotFoundErrorMessageForNameOrFindFunction("class instance method", nameOrFindFunction); });
};
class_1.prototype.getInstanceMethods = function () {
return this.getInstanceMembers().filter(function (m) { return m instanceof MethodDeclaration_1.MethodDeclaration; });
};
class_1.prototype.getStaticMethod = function (nameOrFindFunction) {
return utils_1.getNodeByNameOrFindFunction(this.getStaticMethods(), nameOrFindFunction);
};
class_1.prototype.getStaticMethodOrThrow = function (nameOrFindFunction) {
return errors.throwIfNullOrUndefined(this.getStaticMethod(nameOrFindFunction), function () { return utils_1.getNotFoundErrorMessageForNameOrFindFunction("class static method", nameOrFindFunction); });
};
class_1.prototype.getStaticMethods = function () {
return this.getStaticMembers().filter(function (m) { return m instanceof MethodDeclaration_1.MethodDeclaration; });
};
class_1.prototype.getInstanceMember = function (nameOrFindFunction) {
return utils_1.getNodeByNameOrFindFunction(this.getInstanceMembers(), nameOrFindFunction);
};
class_1.prototype.getInstanceMemberOrThrow = function (nameOrFindFunction) {
return errors.throwIfNullOrUndefined(this.getInstanceMember(nameOrFindFunction), function () { return utils_1.getNotFoundErrorMessageForNameOrFindFunction("class instance member", nameOrFindFunction); });
};
class_1.prototype.getInstanceMembers = function () {
return this.getMembersWithParameterProperties()
.filter(function (m) { return !utils_1.TypeGuards.isConstructorDeclaration(m) && (utils_1.TypeGuards.isParameterDeclaration(m) || !m.isStatic()); });
};
class_1.prototype.getStaticMember = function (nameOrFindFunction) {
return utils_1.getNodeByNameOrFindFunction(this.getStaticMembers(), nameOrFindFunction);
};
class_1.prototype.getStaticMemberOrThrow = function (nameOrFindFunction) {
return errors.throwIfNullOrUndefined(this.getStaticMember(nameOrFindFunction), function () { return utils_1.getNotFoundErrorMessageForNameOrFindFunction("class static member", nameOrFindFunction); });
};
class_1.prototype.getStaticMembers = function () {
return this.getMembers().filter(function (m) { return !utils_1.TypeGuards.isConstructorDeclaration(m) && !(m instanceof function_1.ParameterDeclaration) && m.isStatic(); });
};
class_1.prototype.getMembersWithParameterProperties = function () {
var e_1, _a, e_2, _b;
var members = this.getMembers();
var implementationCtors = members.filter(function (c) { return utils_1.TypeGuards.isConstructorDeclaration(c) && c.isImplementation(); });
try {
for (var implementationCtors_1 = tslib_1.__values(implementationCtors), implementationCtors_1_1 = implementationCtors_1.next(); !implementationCtors_1_1.done; implementationCtors_1_1 = implementationCtors_1.next()) {
var ctor = implementationCtors_1_1.value;
// insert after the constructor
var insertIndex = members.indexOf(ctor) + 1;
try {
for (var _c = tslib_1.__values(ctor.getParameters()), _d = _c.next(); !_d.done; _d = _c.next()) {
var param = _d.value;
if (param.isParameterProperty()) {
members.splice(insertIndex, 0, param);
insertIndex++;
}
}
}
catch (e_2_1) { e_2 = { error: e_2_1 }; }
finally {
try {
if (_d && !_d.done && (_b = _c.return)) _b.call(_c);
}
finally { if (e_2) throw e_2.error; }
}
}
}
catch (e_1_1) { e_1 = { error: e_1_1 }; }
finally {
try {
if (implementationCtors_1_1 && !implementationCtors_1_1.done && (_a = implementationCtors_1.return)) _a.call(implementationCtors_1);
}
finally { if (e_1) throw e_1.error; }
}
return members;
};
class_1.prototype.getMembers = function () {
return getAllMembers(this).filter(function (m) { return isSupportedClassMember(m); });
function getAllMembers(classDec) {
var members = classDec.compilerNode.members.map(function (m) { return classDec._getNodeFromCompilerNode(m); });
var isAmbient = utils_1.TypeGuards.isAmbientableNode(classDec) && classDec.isAmbient();
// filter out the method declarations or constructor declarations without a body if not ambient
return isAmbient ? members : members.filter(function (m) {
if (!(utils_1.TypeGuards.isConstructorDeclaration(m) || utils_1.TypeGuards.isMethodDeclaration(m)))
return true;
if (utils_1.TypeGuards.isMethodDeclaration(m) && m.isAbstract())
return true;
return m.isImplementation();
});
}
};
class_1.prototype.getMember = function (nameOrFindFunction) {
return utils_1.getNodeByNameOrFindFunction(this.getMembers(), nameOrFindFunction);
};
class_1.prototype.getMemberOrThrow = function (nameOrFindFunction) {
return errors.throwIfNullOrUndefined(this.getMember(nameOrFindFunction), function () { return utils_1.getNotFoundErrorMessageForNameOrFindFunction("class member", nameOrFindFunction); });
};
class_1.prototype.getBaseTypes = function () {
return this.getType().getBaseTypes();
};
class_1.prototype.getBaseClassOrThrow = function () {
return errors.throwIfNullOrUndefined(this.getBaseClass(), "Expected to find the base class of " + this.getName() + ".");
};
class_1.prototype.getBaseClass = function () {
var baseTypes = utils_1.ArrayUtils.flatten(this.getBaseTypes().map(function (t) { return t.isIntersection() ? t.getIntersectionTypes() : [t]; }));
var declarations = baseTypes
.map(function (t) { return t.getSymbol(); })
.filter(function (s) { return s != null; })
.map(function (s) { return s.getDeclarations(); })
.reduce(function (a, b) { return a.concat(b); }, [])
.filter(function (d) { return d.getKind() === typescript_1.SyntaxKind.ClassDeclaration; });
if (declarations.length !== 1)
return undefined;
return declarations[0];
};
class_1.prototype.getDerivedClasses = function () {
var e_3, _a;
var classes = getImmediateDerivedClasses(this);
for (var i = 0; i < classes.length; i++) {
var derivedClasses = getImmediateDerivedClasses(classes[i]);
try {
for (var derivedClasses_1 = tslib_1.__values(derivedClasses), derivedClasses_1_1 = derivedClasses_1.next(); !derivedClasses_1_1.done; derivedClasses_1_1 = derivedClasses_1.next()) {
var derivedClass = derivedClasses_1_1.value;
// don't allow circular references
if (derivedClass !== this && classes.indexOf(derivedClass) === -1)
classes.push(derivedClass);
}
}
catch (e_3_1) { e_3 = { error: e_3_1 }; }
finally {
try {
if (derivedClasses_1_1 && !derivedClasses_1_1.done && (_a = derivedClasses_1.return)) _a.call(derivedClasses_1);
}
finally { if (e_3) throw e_3.error; }
}
}
return classes;
};
return class_1;
}(Base));
}
exports.ClassLikeDeclarationBaseSpecific = ClassLikeDeclarationBaseSpecific;
function getImmediateDerivedClasses(classDec) {
var e_4, _a;
var classes = [];
var nameNode = classDec.getNameNode();
if (nameNode == null)
return classes;
try {
for (var _b = tslib_1.__values(nameNode.findReferencesAsNodes()), _c = _b.next(); !_c.done; _c = _b.next()) {
var node = _c.value;
var nodeParent = node.getParentIfKind(typescript_1.SyntaxKind.ExpressionWithTypeArguments);
if (nodeParent == null)
continue;
var heritageClause = nodeParent.getParentIfKind(typescript_1.SyntaxKind.HeritageClause);
if (heritageClause == null || heritageClause.getToken() !== typescript_1.SyntaxKind.ExtendsKeyword)
continue;
var derivedClass = heritageClause.getParentIfKind(typescript_1.SyntaxKind.ClassDeclaration);
if (derivedClass == null)
continue;
classes.push(derivedClass);
}
}
catch (e_4_1) { e_4 = { error: e_4_1 }; }
finally {
try {
if (_c && !_c.done && (_a = _b.return)) _a.call(_b);
}
finally { if (e_4) throw e_4.error; }
}
return classes;
}
function isClassPropertyType(m) {
return utils_1.TypeGuards.isPropertyDeclaration(m)
|| utils_1.TypeGuards.isSetAccessorDeclaration(m)
|| utils_1.TypeGuards.isGetAccessorDeclaration(m)
|| utils_1.TypeGuards.isParameterDeclaration(m);
}
function isSupportedClassMember(m) {
return utils_1.TypeGuards.isMethodDeclaration(m)
|| utils_1.TypeGuards.isPropertyDeclaration(m)
|| utils_1.TypeGuards.isGetAccessorDeclaration(m)
|| utils_1.TypeGuards.isSetAccessorDeclaration(m)
|| utils_1.TypeGuards.isConstructorDeclaration(m);
}