UNPKG

ts-simple-ast

Version:

TypeScript compiler wrapper for static analysis and code manipulation.

480 lines (479 loc) 27.6 kB
"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); }