UNPKG

ts-simple-ast

Version:

TypeScript compiler wrapper for static analysis and code manipulation.

413 lines (412 loc) 18.6 kB
"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 statement_1 = require("../statement"); var callBaseGetStructure_1 = require("../callBaseGetStructure"); var callBaseSet_1 = require("../callBaseSet"); exports.ImportDeclarationBase = statement_1.Statement; var ImportDeclaration = /** @class */ (function (_super) { tslib_1.__extends(ImportDeclaration, _super); function ImportDeclaration() { return _super !== null && _super.apply(this, arguments) || this; } ImportDeclaration.prototype.setModuleSpecifier = function (textOrSourceFile) { var text = typeof textOrSourceFile === "string" ? textOrSourceFile : this._sourceFile.getRelativePathAsModuleSpecifierTo(textOrSourceFile); this.getModuleSpecifier().setLiteralValue(text); return this; }; /** * Gets the module specifier. */ ImportDeclaration.prototype.getModuleSpecifier = function () { var moduleSpecifier = this._getNodeFromCompilerNode(this.compilerNode.moduleSpecifier); if (!utils_1.TypeGuards.isStringLiteral(moduleSpecifier)) throw new errors.InvalidOperationError("Expected the module specifier to be a string literal."); return moduleSpecifier; }; /** * Gets the module specifier string literal value. */ ImportDeclaration.prototype.getModuleSpecifierValue = function () { return this.getModuleSpecifier().getLiteralValue(); }; /** * Gets the source file referenced in the module specifier or throws if it can't find it. */ ImportDeclaration.prototype.getModuleSpecifierSourceFileOrThrow = function () { return errors.throwIfNullOrUndefined(this.getModuleSpecifierSourceFile(), "A module specifier source file was expected."); }; /** * Gets the source file referenced in the module specifier or returns undefined if it can't find it. */ ImportDeclaration.prototype.getModuleSpecifierSourceFile = function () { var symbol = this.getModuleSpecifier().getSymbol(); if (symbol == null) return undefined; return utils_1.ModuleUtils.getReferencedSourceFileFromSymbol(symbol); }; /** * Gets if the module specifier starts with `./` or `../`. */ ImportDeclaration.prototype.isModuleSpecifierRelative = function () { return utils_1.ModuleUtils.isModuleSpecifierRelative(this.getModuleSpecifierValue()); }; /** * Sets the default import. * @param text - Text to set as the default import. * @remarks Use renameDefaultImport to rename. */ ImportDeclaration.prototype.setDefaultImport = function (text) { if (utils_1.StringUtils.isNullOrWhitespace(text)) return this.removeDefaultImport(); var defaultImport = this.getDefaultImport(); if (defaultImport != null) { defaultImport.replaceWithText(text); return this; } var importKeyword = this.getFirstChildByKindOrThrow(typescript_1.SyntaxKind.ImportKeyword); var importClause = this.getImportClause(); if (importClause == null) { manipulation_1.insertIntoParentTextRange({ insertPos: importKeyword.getEnd(), parent: this, newText: " " + text + " from" }); return this; } // a namespace import or named import must exist... insert it beforehand manipulation_1.insertIntoParentTextRange({ insertPos: importKeyword.getEnd(), parent: importClause, newText: " " + text + "," }); return this; }; /** * Renames or sets the provided default import. * @param text - Text to set or rename the default import with. */ ImportDeclaration.prototype.renameDefaultImport = function (text) { if (utils_1.StringUtils.isNullOrWhitespace(text)) return this.removeDefaultImport(); var defaultImport = this.getDefaultImport(); if (defaultImport != null) { defaultImport.rename(text); return this; } this.setDefaultImport(text); return this; }; /** * Gets the default import or throws if it doesn't exit. */ ImportDeclaration.prototype.getDefaultImportOrThrow = function () { return errors.throwIfNullOrUndefined(this.getDefaultImport(), "Expected to find a default import."); }; /** * Gets the default import or returns undefined if it doesn't exist. */ ImportDeclaration.prototype.getDefaultImport = function () { var importClause = this.getImportClause(); if (importClause == null) return undefined; return importClause.getDefaultImport(); }; /** * Sets the namespace import. * @param text - Text to set as the namespace import. * @throws - InvalidOperationError if a named import exists. */ ImportDeclaration.prototype.setNamespaceImport = function (text) { if (utils_1.StringUtils.isNullOrWhitespace(text)) return this.removeNamespaceImport(); var namespaceImport = this.getNamespaceImport(); if (namespaceImport != null) { namespaceImport.rename(text); return this; } if (this.getNamedImports().length > 0) throw new errors.InvalidOperationError("Cannot add a namespace import to an import declaration that has named imports."); var defaultImport = this.getDefaultImport(); if (defaultImport != null) { manipulation_1.insertIntoParentTextRange({ insertPos: defaultImport.getEnd(), parent: this.getImportClause(), newText: ", * as " + text }); return this; } manipulation_1.insertIntoParentTextRange({ insertPos: this.getFirstChildByKindOrThrow(typescript_1.SyntaxKind.ImportKeyword).getEnd(), parent: this, newText: " * as " + text + " from" }); return this; }; /** * Removes the namespace import. */ ImportDeclaration.prototype.removeNamespaceImport = function () { var namespaceImport = this.getNamespaceImport(); if (namespaceImport == null) return this; manipulation_1.removeChildren({ children: getChildrenToRemove.call(this), removePrecedingSpaces: true, removePrecedingNewLines: true }); return this; function getChildrenToRemove() { var defaultImport = this.getDefaultImport(); if (defaultImport == null) return [this.getImportClauseOrThrow(), this.getLastChildByKindOrThrow(typescript_1.SyntaxKind.FromKeyword)]; else return [defaultImport.getNextSiblingIfKindOrThrow(typescript_1.SyntaxKind.CommaToken), namespaceImport]; } }; /** * Removes the default import. */ ImportDeclaration.prototype.removeDefaultImport = function () { var importClause = this.getImportClause(); if (importClause == null) return this; var defaultImport = importClause.getDefaultImport(); if (defaultImport == null) return this; var hasOnlyDefaultImport = importClause.getChildCount() === 1; if (hasOnlyDefaultImport) manipulation_1.removeChildren({ children: [importClause, importClause.getNextSiblingIfKindOrThrow(typescript_1.SyntaxKind.FromKeyword)], removePrecedingSpaces: true, removePrecedingNewLines: true }); else manipulation_1.removeChildren({ children: [defaultImport, defaultImport.getNextSiblingIfKindOrThrow(typescript_1.SyntaxKind.CommaToken)], removePrecedingSpaces: true, removePrecedingNewLines: true }); return this; }; /** * Gets the namespace import if it exists or throws. */ ImportDeclaration.prototype.getNamespaceImportOrThrow = function () { return errors.throwIfNullOrUndefined(this.getNamespaceImport(), "Expected to find a namespace import."); }; /** * Gets the namespace import identifier, if it exists. */ ImportDeclaration.prototype.getNamespaceImport = function () { var importClause = this.getImportClause(); if (importClause == null) return undefined; return importClause.getNamespaceImport(); }; /** * Adds a named import. * @param namedImport - Name, structure, or writer to write the named import with. */ ImportDeclaration.prototype.addNamedImport = function (namedImport) { return this.addNamedImports([namedImport])[0]; }; /** * Adds named imports. * @param namedImport - Structures, names, or writer function to write the named import with. */ ImportDeclaration.prototype.addNamedImports = function (namedImports) { return this.insertNamedImports(this.getNamedImports().length, namedImports); }; /** * Inserts a named import. * @param index - Child index to insert at. * @param namedImport - Structure, name, or writer function to write the named import with. */ ImportDeclaration.prototype.insertNamedImport = function (index, namedImport) { return this.insertNamedImports(index, [namedImport])[0]; }; /** * Inserts named imports into the import declaration. * @param index - Child index to insert at. * @param namedImports - Structures, names, or writer function to write the named import with. */ ImportDeclaration.prototype.insertNamedImports = function (index, namedImports) { if (!(namedImports instanceof Function) && utils_1.ArrayUtils.isNullOrEmpty(namedImports)) return []; var originalNamedImports = this.getNamedImports(); var writer = this._getWriterWithQueuedIndentation(); var namedImportStructurePrinter = this._context.structurePrinterFactory.forNamedImportExportSpecifier(); var importClause = this.getImportClause(); index = manipulation_1.verifyAndGetIndex(index, originalNamedImports.length); if (originalNamedImports.length === 0) { namedImportStructurePrinter.printTextsWithBraces(writer, namedImports); if (importClause == null) manipulation_1.insertIntoParentTextRange({ insertPos: this.getFirstChildByKindOrThrow(typescript_1.SyntaxKind.ImportKeyword).getEnd(), parent: this, newText: " " + writer.toString() + " from" }); else if (this.getNamespaceImport() != null) throw getErrorWhenNamespaceImportsExist(); else if (importClause.getNamedBindings() != null) { var namedBindings = importClause.getNamedBindingsOrThrow(); manipulation_1.insertIntoParentTextRange({ insertPos: namedBindings.getStart(), replacing: { textLength: namedBindings.getWidth() }, parent: importClause, newText: writer.toString() }); } else manipulation_1.insertIntoParentTextRange({ insertPos: this.getDefaultImport().getEnd(), parent: importClause, newText: ", " + writer.toString() }); } else { if (importClause == null) throw new errors.NotImplementedError("Expected to have an import clause."); namedImportStructurePrinter.printTexts(writer, namedImports); manipulation_1.insertIntoCommaSeparatedNodes({ parent: importClause.getFirstChildByKindOrThrow(typescript_1.SyntaxKind.NamedImports).getFirstChildByKindOrThrow(typescript_1.SyntaxKind.SyntaxList), currentNodes: originalNamedImports, insertIndex: index, newText: writer.toString(), surroundWithSpaces: this._context.getFormatCodeSettings().insertSpaceAfterOpeningAndBeforeClosingNonemptyBraces }); } var newNamedImports = this.getNamedImports(); return manipulation_1.getNodesToReturn(newNamedImports, index, newNamedImports.length - originalNamedImports.length); }; /** * Gets the named imports. */ ImportDeclaration.prototype.getNamedImports = function () { var importClause = this.getImportClause(); if (importClause == null) return []; return importClause.getNamedImports(); }; /** * Removes all the named imports. */ ImportDeclaration.prototype.removeNamedImports = function () { var importClause = this.getImportClause(); if (importClause == null) return this; var namedImportsNode = importClause.getNamedBindings(); if (namedImportsNode == null || namedImportsNode.getKind() !== typescript_1.SyntaxKind.NamedImports) return this; // ex. import defaultExport, { Export1 } from "module-name"; var defaultImport = this.getDefaultImport(); if (defaultImport != null) { var commaToken = defaultImport.getNextSiblingIfKindOrThrow(typescript_1.SyntaxKind.CommaToken); manipulation_1.removeChildren({ children: [commaToken, namedImportsNode] }); return this; } // ex. import { Export1 } from "module-name"; var fromKeyword = importClause.getNextSiblingIfKindOrThrow(typescript_1.SyntaxKind.FromKeyword); manipulation_1.removeChildren({ children: [importClause, fromKeyword], removePrecedingSpaces: true }); return this; }; /** * Gets the import clause or throws if it doesn't exist. */ ImportDeclaration.prototype.getImportClauseOrThrow = function () { return errors.throwIfNullOrUndefined(this.getImportClause(), "Expected to find an import clause."); }; /** * Gets the import clause or returns undefined if it doesn't exist. */ ImportDeclaration.prototype.getImportClause = function () { return this._getNodeFromCompilerNodeIfExists(this.compilerNode.importClause); }; /** * Sets the node from a structure. * @param structure - Structure to set the node with. */ ImportDeclaration.prototype.set = function (structure) { callBaseSet_1.callBaseSet(exports.ImportDeclarationBase.prototype, this, structure); if (structure.defaultImport != null) this.setDefaultImport(structure.defaultImport); else if (structure.hasOwnProperty("defaultImport")) this.removeDefaultImport(); if (structure.hasOwnProperty("namedImports")) this.removeNamedImports(); if (structure.namespaceImport != null) this.setNamespaceImport(structure.namespaceImport); else if (structure.hasOwnProperty("namespaceImport")) this.removeNamespaceImport(); if (structure.namedImports != null) { setEmptyNamedImport(this); this.addNamedImports(structure.namedImports); } if (structure.moduleSpecifier != null) this.setModuleSpecifier(structure.moduleSpecifier); return this; }; /** * Gets the structure equivalent to this node. */ ImportDeclaration.prototype.getStructure = function () { var namespaceImport = this.getNamespaceImport(); var defaultImport = this.getDefaultImport(); return callBaseGetStructure_1.callBaseGetStructure(exports.ImportDeclarationBase.prototype, this, { defaultImport: defaultImport ? defaultImport.getText() : undefined, moduleSpecifier: this.getModuleSpecifier().getLiteralText(), namedImports: this.getNamedImports().map(function (node) { return node.getStructure(); }), namespaceImport: namespaceImport ? namespaceImport.getText() : undefined }); }; return ImportDeclaration; }(exports.ImportDeclarationBase)); exports.ImportDeclaration = ImportDeclaration; function setEmptyNamedImport(node) { var importClause = node.getNodeProperty("importClause"); var writer = node._getWriterWithQueuedChildIndentation(); var namedImportStructurePrinter = node._context.structurePrinterFactory.forNamedImportExportSpecifier(); namedImportStructurePrinter.printTextsWithBraces(writer, []); var emptyBracesText = writer.toString(); if (node.getNamespaceImport() != null) throw getErrorWhenNamespaceImportsExist(); if (importClause == null) { manipulation_1.insertIntoParentTextRange({ insertPos: node.getFirstChildByKindOrThrow(typescript_1.SyntaxKind.ImportKeyword).getEnd(), parent: node, newText: " " + emptyBracesText + " from" }); return; } var replaceNode = importClause.getNamedBindings(); if (replaceNode != null) { manipulation_1.insertIntoParentTextRange({ parent: importClause, newText: emptyBracesText, insertPos: replaceNode.getStart(), replacing: { textLength: replaceNode.getWidth() } }); return; } var defaultImport = importClause.getDefaultImport(); if (defaultImport != null) { manipulation_1.insertIntoParentTextRange({ insertPos: defaultImport.getEnd(), parent: importClause, newText: ", " + emptyBracesText }); return; } } function getErrorWhenNamespaceImportsExist() { return new errors.InvalidOperationError("Cannot add a named import to an import declaration that has a namespace import."); }