| 1 | "use strict";
|
|---|
| 2 | Object.defineProperty(exports, "__esModule", { value: true });
|
|---|
| 3 | exports.isValidIdentifier = exports.getLineBreakStyle = exports.getLineRanges = exports.forEachComment = exports.forEachTokenWithTrivia = exports.forEachToken = exports.isFunctionWithBody = exports.hasOwnThisReference = exports.isBlockScopeBoundary = exports.isFunctionScopeBoundary = exports.isTypeScopeBoundary = exports.isScopeBoundary = exports.ScopeBoundarySelector = exports.ScopeBoundary = exports.isInSingleStatementContext = exports.isBlockScopedDeclarationStatement = exports.isBlockScopedVariableDeclaration = exports.isBlockScopedVariableDeclarationList = exports.getVariableDeclarationKind = exports.VariableDeclarationKind = exports.forEachDeclaredVariable = exports.forEachDestructuringIdentifier = exports.getPropertyName = exports.getWrappedNodeAtPosition = exports.getAstNodeAtPosition = exports.commentText = exports.isPositionInComment = exports.getCommentAtPosition = exports.getTokenAtPosition = exports.getNextToken = exports.getPreviousToken = exports.getNextStatement = exports.getPreviousStatement = exports.isModifierFlagSet = exports.isObjectFlagSet = exports.isSymbolFlagSet = exports.isTypeFlagSet = exports.isNodeFlagSet = exports.hasAccessModifier = exports.isParameterProperty = exports.hasModifier = exports.getModifier = exports.isThisParameter = exports.isKeywordKind = exports.isJsDocKind = exports.isTypeNodeKind = exports.isAssignmentKind = exports.isNodeKind = exports.isTokenKind = exports.getChildOfKind = void 0;
|
|---|
| 4 | exports.getBaseOfClassLikeExpression = exports.hasExhaustiveCaseClauses = exports.formatPseudoBigInt = exports.unwrapParentheses = exports.getSingleLateBoundPropertyNameOfPropertyName = exports.getLateBoundPropertyNamesOfPropertyName = exports.getLateBoundPropertyNames = exports.getPropertyNameOfWellKnownSymbol = exports.isWellKnownSymbolLiterally = exports.isBindableObjectDefinePropertyCall = exports.isReadonlyAssignmentDeclaration = exports.isInConstContext = exports.isConstAssertion = exports.getTsCheckDirective = exports.getCheckJsDirective = exports.isAmbientModule = exports.isCompilerOptionEnabled = exports.isStrictCompilerOptionEnabled = exports.getIIFE = exports.isAmbientModuleBlock = exports.isStatementInAmbientContext = exports.findImportLikeNodes = exports.findImports = exports.ImportKind = exports.parseJsDocOfNode = exports.getJsDoc = exports.canHaveJsDoc = exports.isReassignmentTarget = exports.getAccessKind = exports.AccessKind = exports.isExpressionValueUsed = exports.getDeclarationOfBindingElement = exports.hasSideEffects = exports.SideEffectOptions = exports.isSameLine = exports.isNumericPropertyName = exports.isValidJsxIdentifier = exports.isValidNumericLiteral = exports.isValidPropertyName = exports.isValidPropertyAccess = void 0;
|
|---|
| 5 | const ts = require("typescript");
|
|---|
| 6 | const node_1 = require("../typeguard/node");
|
|---|
| 7 | const _3_2_1 = require("../typeguard/3.2");
|
|---|
| 8 | const type_1 = require("./type");
|
|---|
| 9 | function getChildOfKind(node, kind, sourceFile) {
|
|---|
| 10 | for (const child of node.getChildren(sourceFile))
|
|---|
| 11 | if (child.kind === kind)
|
|---|
| 12 | return child;
|
|---|
| 13 | }
|
|---|
| 14 | exports.getChildOfKind = getChildOfKind;
|
|---|
| 15 | function isTokenKind(kind) {
|
|---|
| 16 | return kind >= ts.SyntaxKind.FirstToken && kind <= ts.SyntaxKind.LastToken;
|
|---|
| 17 | }
|
|---|
| 18 | exports.isTokenKind = isTokenKind;
|
|---|
| 19 | function isNodeKind(kind) {
|
|---|
| 20 | return kind >= ts.SyntaxKind.FirstNode;
|
|---|
| 21 | }
|
|---|
| 22 | exports.isNodeKind = isNodeKind;
|
|---|
| 23 | function isAssignmentKind(kind) {
|
|---|
| 24 | return kind >= ts.SyntaxKind.FirstAssignment && kind <= ts.SyntaxKind.LastAssignment;
|
|---|
| 25 | }
|
|---|
| 26 | exports.isAssignmentKind = isAssignmentKind;
|
|---|
| 27 | function isTypeNodeKind(kind) {
|
|---|
| 28 | return kind >= ts.SyntaxKind.FirstTypeNode && kind <= ts.SyntaxKind.LastTypeNode;
|
|---|
| 29 | }
|
|---|
| 30 | exports.isTypeNodeKind = isTypeNodeKind;
|
|---|
| 31 | function isJsDocKind(kind) {
|
|---|
| 32 | return kind >= ts.SyntaxKind.FirstJSDocNode && kind <= ts.SyntaxKind.LastJSDocNode;
|
|---|
| 33 | }
|
|---|
| 34 | exports.isJsDocKind = isJsDocKind;
|
|---|
| 35 | function isKeywordKind(kind) {
|
|---|
| 36 | return kind >= ts.SyntaxKind.FirstKeyword && kind <= ts.SyntaxKind.LastKeyword;
|
|---|
| 37 | }
|
|---|
| 38 | exports.isKeywordKind = isKeywordKind;
|
|---|
| 39 | function isThisParameter(parameter) {
|
|---|
| 40 | return parameter.name.kind === ts.SyntaxKind.Identifier && parameter.name.originalKeywordKind === ts.SyntaxKind.ThisKeyword;
|
|---|
| 41 | }
|
|---|
| 42 | exports.isThisParameter = isThisParameter;
|
|---|
| 43 | function getModifier(node, kind) {
|
|---|
| 44 | if (node.modifiers !== undefined)
|
|---|
| 45 | for (const modifier of node.modifiers)
|
|---|
| 46 | if (modifier.kind === kind)
|
|---|
| 47 | return modifier;
|
|---|
| 48 | }
|
|---|
| 49 | exports.getModifier = getModifier;
|
|---|
| 50 | function hasModifier(modifiers, ...kinds) {
|
|---|
| 51 | if (modifiers === undefined)
|
|---|
| 52 | return false;
|
|---|
| 53 | for (const modifier of modifiers)
|
|---|
| 54 | if (kinds.includes(modifier.kind))
|
|---|
| 55 | return true;
|
|---|
| 56 | return false;
|
|---|
| 57 | }
|
|---|
| 58 | exports.hasModifier = hasModifier;
|
|---|
| 59 | function isParameterProperty(node) {
|
|---|
| 60 | return hasModifier(node.modifiers, ts.SyntaxKind.PublicKeyword, ts.SyntaxKind.ProtectedKeyword, ts.SyntaxKind.PrivateKeyword, ts.SyntaxKind.ReadonlyKeyword);
|
|---|
| 61 | }
|
|---|
| 62 | exports.isParameterProperty = isParameterProperty;
|
|---|
| 63 | function hasAccessModifier(node) {
|
|---|
| 64 | return isModifierFlagSet(node, ts.ModifierFlags.AccessibilityModifier);
|
|---|
| 65 | }
|
|---|
| 66 | exports.hasAccessModifier = hasAccessModifier;
|
|---|
| 67 | function isFlagSet(obj, flag) {
|
|---|
| 68 | return (obj.flags & flag) !== 0;
|
|---|
| 69 | }
|
|---|
| 70 | exports.isNodeFlagSet = isFlagSet;
|
|---|
| 71 | exports.isTypeFlagSet = isFlagSet;
|
|---|
| 72 | exports.isSymbolFlagSet = isFlagSet;
|
|---|
| 73 | function isObjectFlagSet(objectType, flag) {
|
|---|
| 74 | return (objectType.objectFlags & flag) !== 0;
|
|---|
| 75 | }
|
|---|
| 76 | exports.isObjectFlagSet = isObjectFlagSet;
|
|---|
| 77 | function isModifierFlagSet(node, flag) {
|
|---|
| 78 | return (ts.getCombinedModifierFlags(node) & flag) !== 0;
|
|---|
| 79 | }
|
|---|
| 80 | exports.isModifierFlagSet = isModifierFlagSet;
|
|---|
| 81 | function getPreviousStatement(statement) {
|
|---|
| 82 | const parent = statement.parent;
|
|---|
| 83 | if (node_1.isBlockLike(parent)) {
|
|---|
| 84 | const index = parent.statements.indexOf(statement);
|
|---|
| 85 | if (index > 0)
|
|---|
| 86 | return parent.statements[index - 1];
|
|---|
| 87 | }
|
|---|
| 88 | }
|
|---|
| 89 | exports.getPreviousStatement = getPreviousStatement;
|
|---|
| 90 | function getNextStatement(statement) {
|
|---|
| 91 | const parent = statement.parent;
|
|---|
| 92 | if (node_1.isBlockLike(parent)) {
|
|---|
| 93 | const index = parent.statements.indexOf(statement);
|
|---|
| 94 | if (index < parent.statements.length)
|
|---|
| 95 | return parent.statements[index + 1];
|
|---|
| 96 | }
|
|---|
| 97 | }
|
|---|
| 98 | exports.getNextStatement = getNextStatement;
|
|---|
| 99 | /** Returns the token before the start of `node` or `undefined` if there is none. */
|
|---|
| 100 | function getPreviousToken(node, sourceFile) {
|
|---|
| 101 | const { pos } = node;
|
|---|
| 102 | if (pos === 0)
|
|---|
| 103 | return;
|
|---|
| 104 | do
|
|---|
| 105 | node = node.parent;
|
|---|
| 106 | while (node.pos === pos);
|
|---|
| 107 | return getTokenAtPositionWorker(node, pos - 1, sourceFile !== null && sourceFile !== void 0 ? sourceFile : node.getSourceFile(), false);
|
|---|
| 108 | }
|
|---|
| 109 | exports.getPreviousToken = getPreviousToken;
|
|---|
| 110 | /** Returns the next token that begins after the end of `node`. Returns `undefined` for SourceFile and EndOfFileToken */
|
|---|
| 111 | function getNextToken(node, sourceFile) {
|
|---|
| 112 | if (node.kind === ts.SyntaxKind.SourceFile || node.kind === ts.SyntaxKind.EndOfFileToken)
|
|---|
| 113 | return;
|
|---|
| 114 | const end = node.end;
|
|---|
| 115 | node = node.parent;
|
|---|
| 116 | while (node.end === end) {
|
|---|
| 117 | if (node.parent === undefined)
|
|---|
| 118 | return node.endOfFileToken;
|
|---|
| 119 | node = node.parent;
|
|---|
| 120 | }
|
|---|
| 121 | return getTokenAtPositionWorker(node, end, sourceFile !== null && sourceFile !== void 0 ? sourceFile : node.getSourceFile(), false);
|
|---|
| 122 | }
|
|---|
| 123 | exports.getNextToken = getNextToken;
|
|---|
| 124 | /** Returns the token at or following the specified position or undefined if none is found inside `parent`. */
|
|---|
| 125 | function getTokenAtPosition(parent, pos, sourceFile, allowJsDoc) {
|
|---|
| 126 | if (pos < parent.pos || pos >= parent.end)
|
|---|
| 127 | return;
|
|---|
| 128 | if (isTokenKind(parent.kind))
|
|---|
| 129 | return parent;
|
|---|
| 130 | return getTokenAtPositionWorker(parent, pos, sourceFile !== null && sourceFile !== void 0 ? sourceFile : parent.getSourceFile(), allowJsDoc === true);
|
|---|
| 131 | }
|
|---|
| 132 | exports.getTokenAtPosition = getTokenAtPosition;
|
|---|
| 133 | function getTokenAtPositionWorker(node, pos, sourceFile, allowJsDoc) {
|
|---|
| 134 | if (!allowJsDoc) {
|
|---|
| 135 | // if we are not interested in JSDoc, we can skip to the deepest AST node at the given position
|
|---|
| 136 | node = getAstNodeAtPosition(node, pos);
|
|---|
| 137 | if (isTokenKind(node.kind))
|
|---|
| 138 | return node;
|
|---|
| 139 | }
|
|---|
| 140 | outer: while (true) {
|
|---|
| 141 | for (const child of node.getChildren(sourceFile)) {
|
|---|
| 142 | if (child.end > pos && (allowJsDoc || child.kind !== ts.SyntaxKind.JSDocComment)) {
|
|---|
| 143 | if (isTokenKind(child.kind))
|
|---|
| 144 | return child;
|
|---|
| 145 | // next token is nested in another node
|
|---|
| 146 | node = child;
|
|---|
| 147 | continue outer;
|
|---|
| 148 | }
|
|---|
| 149 | }
|
|---|
| 150 | return;
|
|---|
| 151 | }
|
|---|
| 152 | }
|
|---|
| 153 | /**
|
|---|
| 154 | * Return the comment at the specified position.
|
|---|
| 155 | * You can pass an optional `parent` to avoid some work finding the corresponding token starting at `sourceFile`.
|
|---|
| 156 | * If the `parent` parameter is passed, `pos` must be between `parent.pos` and `parent.end`.
|
|---|
| 157 | */
|
|---|
| 158 | function getCommentAtPosition(sourceFile, pos, parent = sourceFile) {
|
|---|
| 159 | const token = getTokenAtPosition(parent, pos, sourceFile);
|
|---|
| 160 | if (token === undefined || token.kind === ts.SyntaxKind.JsxText || pos >= token.end - (ts.tokenToString(token.kind) || '').length)
|
|---|
| 161 | return;
|
|---|
| 162 | const startPos = token.pos === 0
|
|---|
| 163 | ? (ts.getShebang(sourceFile.text) || '').length
|
|---|
| 164 | : token.pos;
|
|---|
| 165 | return startPos !== 0 && ts.forEachTrailingCommentRange(sourceFile.text, startPos, commentAtPositionCallback, pos) ||
|
|---|
| 166 | ts.forEachLeadingCommentRange(sourceFile.text, startPos, commentAtPositionCallback, pos);
|
|---|
| 167 | }
|
|---|
| 168 | exports.getCommentAtPosition = getCommentAtPosition;
|
|---|
| 169 | function commentAtPositionCallback(pos, end, kind, _nl, at) {
|
|---|
| 170 | return at >= pos && at < end ? { pos, end, kind } : undefined;
|
|---|
| 171 | }
|
|---|
| 172 | /**
|
|---|
| 173 | * Returns whether the specified position is inside a comment.
|
|---|
| 174 | * You can pass an optional `parent` to avoid some work finding the corresponding token starting at `sourceFile`.
|
|---|
| 175 | * If the `parent` parameter is passed, `pos` must be between `parent.pos` and `parent.end`.
|
|---|
| 176 | */
|
|---|
| 177 | function isPositionInComment(sourceFile, pos, parent) {
|
|---|
| 178 | return getCommentAtPosition(sourceFile, pos, parent) !== undefined;
|
|---|
| 179 | }
|
|---|
| 180 | exports.isPositionInComment = isPositionInComment;
|
|---|
| 181 | function commentText(sourceText, comment) {
|
|---|
| 182 | return sourceText.substring(comment.pos + 2, comment.kind === ts.SyntaxKind.SingleLineCommentTrivia ? comment.end : comment.end - 2);
|
|---|
| 183 | }
|
|---|
| 184 | exports.commentText = commentText;
|
|---|
| 185 | /** Returns the deepest AST Node at `pos`. Returns undefined if `pos` is outside of the range of `node` */
|
|---|
| 186 | function getAstNodeAtPosition(node, pos) {
|
|---|
| 187 | if (node.pos > pos || node.end <= pos)
|
|---|
| 188 | return;
|
|---|
| 189 | while (isNodeKind(node.kind)) {
|
|---|
| 190 | const nested = ts.forEachChild(node, (child) => child.pos <= pos && child.end > pos ? child : undefined);
|
|---|
| 191 | if (nested === undefined)
|
|---|
| 192 | break;
|
|---|
| 193 | node = nested;
|
|---|
| 194 | }
|
|---|
| 195 | return node;
|
|---|
| 196 | }
|
|---|
| 197 | exports.getAstNodeAtPosition = getAstNodeAtPosition;
|
|---|
| 198 | /**
|
|---|
| 199 | * Returns the NodeWrap of deepest AST node that contains `pos` between its `pos` and `end`.
|
|---|
| 200 | * Only returns undefined if pos is outside of `wrap`
|
|---|
| 201 | */
|
|---|
| 202 | function getWrappedNodeAtPosition(wrap, pos) {
|
|---|
| 203 | if (wrap.node.pos > pos || wrap.node.end <= pos)
|
|---|
| 204 | return;
|
|---|
| 205 | outer: while (true) {
|
|---|
| 206 | for (const child of wrap.children) {
|
|---|
| 207 | if (child.node.pos > pos)
|
|---|
| 208 | return wrap;
|
|---|
| 209 | if (child.node.end > pos) {
|
|---|
| 210 | wrap = child;
|
|---|
| 211 | continue outer;
|
|---|
| 212 | }
|
|---|
| 213 | }
|
|---|
| 214 | return wrap;
|
|---|
| 215 | }
|
|---|
| 216 | }
|
|---|
| 217 | exports.getWrappedNodeAtPosition = getWrappedNodeAtPosition;
|
|---|
| 218 | function getPropertyName(propertyName) {
|
|---|
| 219 | if (propertyName.kind === ts.SyntaxKind.ComputedPropertyName) {
|
|---|
| 220 | const expression = unwrapParentheses(propertyName.expression);
|
|---|
| 221 | if (node_1.isPrefixUnaryExpression(expression)) {
|
|---|
| 222 | let negate = false;
|
|---|
| 223 | switch (expression.operator) {
|
|---|
| 224 | case ts.SyntaxKind.MinusToken:
|
|---|
| 225 | negate = true;
|
|---|
| 226 | // falls through
|
|---|
| 227 | case ts.SyntaxKind.PlusToken:
|
|---|
| 228 | return node_1.isNumericLiteral(expression.operand)
|
|---|
| 229 | ? `${negate ? '-' : ''}${expression.operand.text}`
|
|---|
| 230 | : _3_2_1.isBigIntLiteral(expression.operand)
|
|---|
| 231 | ? `${negate ? '-' : ''}${expression.operand.text.slice(0, -1)}`
|
|---|
| 232 | : undefined;
|
|---|
| 233 | default:
|
|---|
| 234 | return;
|
|---|
| 235 | }
|
|---|
| 236 | }
|
|---|
| 237 | if (_3_2_1.isBigIntLiteral(expression))
|
|---|
| 238 | // handle BigInt, even though TypeScript doesn't allow BigInt as computed property name
|
|---|
| 239 | return expression.text.slice(0, -1);
|
|---|
| 240 | if (node_1.isNumericOrStringLikeLiteral(expression))
|
|---|
| 241 | return expression.text;
|
|---|
| 242 | return;
|
|---|
| 243 | }
|
|---|
| 244 | return propertyName.kind === ts.SyntaxKind.PrivateIdentifier ? undefined : propertyName.text;
|
|---|
| 245 | }
|
|---|
| 246 | exports.getPropertyName = getPropertyName;
|
|---|
| 247 | function forEachDestructuringIdentifier(pattern, fn) {
|
|---|
| 248 | for (const element of pattern.elements) {
|
|---|
| 249 | if (element.kind !== ts.SyntaxKind.BindingElement)
|
|---|
| 250 | continue;
|
|---|
| 251 | let result;
|
|---|
| 252 | if (element.name.kind === ts.SyntaxKind.Identifier) {
|
|---|
| 253 | result = fn(element);
|
|---|
| 254 | }
|
|---|
| 255 | else {
|
|---|
| 256 | result = forEachDestructuringIdentifier(element.name, fn);
|
|---|
| 257 | }
|
|---|
| 258 | if (result)
|
|---|
| 259 | return result;
|
|---|
| 260 | }
|
|---|
| 261 | }
|
|---|
| 262 | exports.forEachDestructuringIdentifier = forEachDestructuringIdentifier;
|
|---|
| 263 | function forEachDeclaredVariable(declarationList, cb) {
|
|---|
| 264 | for (const declaration of declarationList.declarations) {
|
|---|
| 265 | let result;
|
|---|
| 266 | if (declaration.name.kind === ts.SyntaxKind.Identifier) {
|
|---|
| 267 | result = cb(declaration);
|
|---|
| 268 | }
|
|---|
| 269 | else {
|
|---|
| 270 | result = forEachDestructuringIdentifier(declaration.name, cb);
|
|---|
| 271 | }
|
|---|
| 272 | if (result)
|
|---|
| 273 | return result;
|
|---|
| 274 | }
|
|---|
| 275 | }
|
|---|
| 276 | exports.forEachDeclaredVariable = forEachDeclaredVariable;
|
|---|
| 277 | var VariableDeclarationKind;
|
|---|
| 278 | (function (VariableDeclarationKind) {
|
|---|
| 279 | VariableDeclarationKind[VariableDeclarationKind["Var"] = 0] = "Var";
|
|---|
| 280 | VariableDeclarationKind[VariableDeclarationKind["Let"] = 1] = "Let";
|
|---|
| 281 | VariableDeclarationKind[VariableDeclarationKind["Const"] = 2] = "Const";
|
|---|
| 282 | })(VariableDeclarationKind = exports.VariableDeclarationKind || (exports.VariableDeclarationKind = {}));
|
|---|
| 283 | function getVariableDeclarationKind(declarationList) {
|
|---|
| 284 | if (declarationList.flags & ts.NodeFlags.Let)
|
|---|
| 285 | return 1 /* Let */;
|
|---|
| 286 | if (declarationList.flags & ts.NodeFlags.Const)
|
|---|
| 287 | return 2 /* Const */;
|
|---|
| 288 | return 0 /* Var */;
|
|---|
| 289 | }
|
|---|
| 290 | exports.getVariableDeclarationKind = getVariableDeclarationKind;
|
|---|
| 291 | function isBlockScopedVariableDeclarationList(declarationList) {
|
|---|
| 292 | return (declarationList.flags & ts.NodeFlags.BlockScoped) !== 0;
|
|---|
| 293 | }
|
|---|
| 294 | exports.isBlockScopedVariableDeclarationList = isBlockScopedVariableDeclarationList;
|
|---|
| 295 | function isBlockScopedVariableDeclaration(declaration) {
|
|---|
| 296 | const parent = declaration.parent;
|
|---|
| 297 | return parent.kind === ts.SyntaxKind.CatchClause ||
|
|---|
| 298 | isBlockScopedVariableDeclarationList(parent);
|
|---|
| 299 | }
|
|---|
| 300 | exports.isBlockScopedVariableDeclaration = isBlockScopedVariableDeclaration;
|
|---|
| 301 | function isBlockScopedDeclarationStatement(statement) {
|
|---|
| 302 | switch (statement.kind) {
|
|---|
| 303 | case ts.SyntaxKind.VariableStatement:
|
|---|
| 304 | return isBlockScopedVariableDeclarationList(statement.declarationList);
|
|---|
| 305 | case ts.SyntaxKind.ClassDeclaration:
|
|---|
| 306 | case ts.SyntaxKind.EnumDeclaration:
|
|---|
| 307 | case ts.SyntaxKind.InterfaceDeclaration:
|
|---|
| 308 | case ts.SyntaxKind.TypeAliasDeclaration:
|
|---|
| 309 | return true;
|
|---|
| 310 | default:
|
|---|
| 311 | return false;
|
|---|
| 312 | }
|
|---|
| 313 | }
|
|---|
| 314 | exports.isBlockScopedDeclarationStatement = isBlockScopedDeclarationStatement;
|
|---|
| 315 | function isInSingleStatementContext(statement) {
|
|---|
| 316 | switch (statement.parent.kind) {
|
|---|
| 317 | case ts.SyntaxKind.ForStatement:
|
|---|
| 318 | case ts.SyntaxKind.ForInStatement:
|
|---|
| 319 | case ts.SyntaxKind.ForOfStatement:
|
|---|
| 320 | case ts.SyntaxKind.WhileStatement:
|
|---|
| 321 | case ts.SyntaxKind.DoStatement:
|
|---|
| 322 | case ts.SyntaxKind.IfStatement:
|
|---|
| 323 | case ts.SyntaxKind.WithStatement:
|
|---|
| 324 | case ts.SyntaxKind.LabeledStatement:
|
|---|
| 325 | return true;
|
|---|
| 326 | default:
|
|---|
| 327 | return false;
|
|---|
| 328 | }
|
|---|
| 329 | }
|
|---|
| 330 | exports.isInSingleStatementContext = isInSingleStatementContext;
|
|---|
| 331 | var ScopeBoundary;
|
|---|
| 332 | (function (ScopeBoundary) {
|
|---|
| 333 | ScopeBoundary[ScopeBoundary["None"] = 0] = "None";
|
|---|
| 334 | ScopeBoundary[ScopeBoundary["Function"] = 1] = "Function";
|
|---|
| 335 | ScopeBoundary[ScopeBoundary["Block"] = 2] = "Block";
|
|---|
| 336 | ScopeBoundary[ScopeBoundary["Type"] = 4] = "Type";
|
|---|
| 337 | ScopeBoundary[ScopeBoundary["ConditionalType"] = 8] = "ConditionalType";
|
|---|
| 338 | })(ScopeBoundary = exports.ScopeBoundary || (exports.ScopeBoundary = {}));
|
|---|
| 339 | var ScopeBoundarySelector;
|
|---|
| 340 | (function (ScopeBoundarySelector) {
|
|---|
| 341 | ScopeBoundarySelector[ScopeBoundarySelector["Function"] = 1] = "Function";
|
|---|
| 342 | ScopeBoundarySelector[ScopeBoundarySelector["Block"] = 3] = "Block";
|
|---|
| 343 | ScopeBoundarySelector[ScopeBoundarySelector["Type"] = 7] = "Type";
|
|---|
| 344 | ScopeBoundarySelector[ScopeBoundarySelector["InferType"] = 8] = "InferType";
|
|---|
| 345 | })(ScopeBoundarySelector = exports.ScopeBoundarySelector || (exports.ScopeBoundarySelector = {}));
|
|---|
| 346 | function isScopeBoundary(node) {
|
|---|
| 347 | return isFunctionScopeBoundary(node) || isBlockScopeBoundary(node) || isTypeScopeBoundary(node);
|
|---|
| 348 | }
|
|---|
| 349 | exports.isScopeBoundary = isScopeBoundary;
|
|---|
| 350 | function isTypeScopeBoundary(node) {
|
|---|
| 351 | switch (node.kind) {
|
|---|
| 352 | case ts.SyntaxKind.InterfaceDeclaration:
|
|---|
| 353 | case ts.SyntaxKind.TypeAliasDeclaration:
|
|---|
| 354 | case ts.SyntaxKind.MappedType:
|
|---|
| 355 | return 4 /* Type */;
|
|---|
| 356 | case ts.SyntaxKind.ConditionalType:
|
|---|
| 357 | return 8 /* ConditionalType */;
|
|---|
| 358 | default:
|
|---|
| 359 | return 0 /* None */;
|
|---|
| 360 | }
|
|---|
| 361 | }
|
|---|
| 362 | exports.isTypeScopeBoundary = isTypeScopeBoundary;
|
|---|
| 363 | function isFunctionScopeBoundary(node) {
|
|---|
| 364 | switch (node.kind) {
|
|---|
| 365 | case ts.SyntaxKind.FunctionExpression:
|
|---|
| 366 | case ts.SyntaxKind.ArrowFunction:
|
|---|
| 367 | case ts.SyntaxKind.Constructor:
|
|---|
| 368 | case ts.SyntaxKind.ModuleDeclaration:
|
|---|
| 369 | case ts.SyntaxKind.ClassDeclaration:
|
|---|
| 370 | case ts.SyntaxKind.ClassExpression:
|
|---|
| 371 | case ts.SyntaxKind.EnumDeclaration:
|
|---|
| 372 | case ts.SyntaxKind.MethodDeclaration:
|
|---|
| 373 | case ts.SyntaxKind.FunctionDeclaration:
|
|---|
| 374 | case ts.SyntaxKind.GetAccessor:
|
|---|
| 375 | case ts.SyntaxKind.SetAccessor:
|
|---|
| 376 | case ts.SyntaxKind.MethodSignature:
|
|---|
| 377 | case ts.SyntaxKind.CallSignature:
|
|---|
| 378 | case ts.SyntaxKind.ConstructSignature:
|
|---|
| 379 | case ts.SyntaxKind.ConstructorType:
|
|---|
| 380 | case ts.SyntaxKind.FunctionType:
|
|---|
| 381 | return 1 /* Function */;
|
|---|
| 382 | case ts.SyntaxKind.SourceFile:
|
|---|
| 383 | // if SourceFile is no module, it contributes to the global scope and is therefore no scope boundary
|
|---|
| 384 | return ts.isExternalModule(node) ? 1 /* Function */ : 0 /* None */;
|
|---|
| 385 | default:
|
|---|
| 386 | return 0 /* None */;
|
|---|
| 387 | }
|
|---|
| 388 | }
|
|---|
| 389 | exports.isFunctionScopeBoundary = isFunctionScopeBoundary;
|
|---|
| 390 | function isBlockScopeBoundary(node) {
|
|---|
| 391 | switch (node.kind) {
|
|---|
| 392 | case ts.SyntaxKind.Block:
|
|---|
| 393 | const parent = node.parent;
|
|---|
| 394 | return parent.kind !== ts.SyntaxKind.CatchClause &&
|
|---|
| 395 | // blocks inside SourceFile are block scope boundaries
|
|---|
| 396 | (parent.kind === ts.SyntaxKind.SourceFile ||
|
|---|
| 397 | // blocks that are direct children of a function scope boundary are no scope boundary
|
|---|
| 398 | // for example the FunctionBlock is part of the function scope of the containing function
|
|---|
| 399 | !isFunctionScopeBoundary(parent))
|
|---|
| 400 | ? 2 /* Block */
|
|---|
| 401 | : 0 /* None */;
|
|---|
| 402 | case ts.SyntaxKind.ForStatement:
|
|---|
| 403 | case ts.SyntaxKind.ForInStatement:
|
|---|
| 404 | case ts.SyntaxKind.ForOfStatement:
|
|---|
| 405 | case ts.SyntaxKind.CaseBlock:
|
|---|
| 406 | case ts.SyntaxKind.CatchClause:
|
|---|
| 407 | case ts.SyntaxKind.WithStatement:
|
|---|
| 408 | return 2 /* Block */;
|
|---|
| 409 | default:
|
|---|
| 410 | return 0 /* None */;
|
|---|
| 411 | }
|
|---|
| 412 | }
|
|---|
| 413 | exports.isBlockScopeBoundary = isBlockScopeBoundary;
|
|---|
| 414 | /** Returns true for scope boundaries that have their own `this` reference instead of inheriting it from the containing scope */
|
|---|
| 415 | function hasOwnThisReference(node) {
|
|---|
| 416 | switch (node.kind) {
|
|---|
| 417 | case ts.SyntaxKind.ClassDeclaration:
|
|---|
| 418 | case ts.SyntaxKind.ClassExpression:
|
|---|
| 419 | case ts.SyntaxKind.FunctionExpression:
|
|---|
| 420 | return true;
|
|---|
| 421 | case ts.SyntaxKind.FunctionDeclaration:
|
|---|
| 422 | return node.body !== undefined;
|
|---|
| 423 | case ts.SyntaxKind.MethodDeclaration:
|
|---|
| 424 | case ts.SyntaxKind.GetAccessor:
|
|---|
| 425 | case ts.SyntaxKind.SetAccessor:
|
|---|
| 426 | return node.parent.kind === ts.SyntaxKind.ObjectLiteralExpression;
|
|---|
| 427 | default:
|
|---|
| 428 | return false;
|
|---|
| 429 | }
|
|---|
| 430 | }
|
|---|
| 431 | exports.hasOwnThisReference = hasOwnThisReference;
|
|---|
| 432 | function isFunctionWithBody(node) {
|
|---|
| 433 | switch (node.kind) {
|
|---|
| 434 | case ts.SyntaxKind.GetAccessor:
|
|---|
| 435 | case ts.SyntaxKind.SetAccessor:
|
|---|
| 436 | case ts.SyntaxKind.FunctionDeclaration:
|
|---|
| 437 | case ts.SyntaxKind.MethodDeclaration:
|
|---|
| 438 | case ts.SyntaxKind.Constructor:
|
|---|
| 439 | return node.body !== undefined;
|
|---|
| 440 | case ts.SyntaxKind.FunctionExpression:
|
|---|
| 441 | case ts.SyntaxKind.ArrowFunction:
|
|---|
| 442 | return true;
|
|---|
| 443 | default:
|
|---|
| 444 | return false;
|
|---|
| 445 | }
|
|---|
| 446 | }
|
|---|
| 447 | exports.isFunctionWithBody = isFunctionWithBody;
|
|---|
| 448 | /**
|
|---|
| 449 | * Iterate over all tokens of `node`
|
|---|
| 450 | *
|
|---|
| 451 | * @param node The node whose tokens should be visited
|
|---|
| 452 | * @param cb Is called for every token contained in `node`
|
|---|
| 453 | */
|
|---|
| 454 | function forEachToken(node, cb, sourceFile = node.getSourceFile()) {
|
|---|
| 455 | const queue = [];
|
|---|
| 456 | while (true) {
|
|---|
| 457 | if (isTokenKind(node.kind)) {
|
|---|
| 458 | cb(node);
|
|---|
| 459 | }
|
|---|
| 460 | else if (node.kind !== ts.SyntaxKind.JSDocComment) {
|
|---|
| 461 | const children = node.getChildren(sourceFile);
|
|---|
| 462 | if (children.length === 1) {
|
|---|
| 463 | node = children[0];
|
|---|
| 464 | continue;
|
|---|
| 465 | }
|
|---|
| 466 | for (let i = children.length - 1; i >= 0; --i)
|
|---|
| 467 | queue.push(children[i]); // add children in reverse order, when we pop the next element from the queue, it's the first child
|
|---|
| 468 | }
|
|---|
| 469 | if (queue.length === 0)
|
|---|
| 470 | break;
|
|---|
| 471 | node = queue.pop();
|
|---|
| 472 | }
|
|---|
| 473 | }
|
|---|
| 474 | exports.forEachToken = forEachToken;
|
|---|
| 475 | /**
|
|---|
| 476 | * Iterate over all tokens and trivia of `node`
|
|---|
| 477 | *
|
|---|
| 478 | * @description JsDoc comments are treated like regular comments
|
|---|
| 479 | *
|
|---|
| 480 | * @param node The node whose tokens should be visited
|
|---|
| 481 | * @param cb Is called for every token contained in `node` and trivia before the token
|
|---|
| 482 | */
|
|---|
| 483 | function forEachTokenWithTrivia(node, cb, sourceFile = node.getSourceFile()) {
|
|---|
| 484 | const fullText = sourceFile.text;
|
|---|
| 485 | const scanner = ts.createScanner(sourceFile.languageVersion, false, sourceFile.languageVariant, fullText);
|
|---|
| 486 | return forEachToken(node, (token) => {
|
|---|
| 487 | const tokenStart = token.kind === ts.SyntaxKind.JsxText || token.pos === token.end ? token.pos : token.getStart(sourceFile);
|
|---|
| 488 | if (tokenStart !== token.pos) {
|
|---|
| 489 | // we only have to handle trivia before each token. whitespace at the end of the file is followed by EndOfFileToken
|
|---|
| 490 | scanner.setTextPos(token.pos);
|
|---|
| 491 | let kind = scanner.scan();
|
|---|
| 492 | let pos = scanner.getTokenPos();
|
|---|
| 493 | while (pos < tokenStart) {
|
|---|
| 494 | const textPos = scanner.getTextPos();
|
|---|
| 495 | cb(fullText, kind, { pos, end: textPos }, token.parent);
|
|---|
| 496 | if (textPos === tokenStart)
|
|---|
| 497 | break;
|
|---|
| 498 | kind = scanner.scan();
|
|---|
| 499 | pos = scanner.getTokenPos();
|
|---|
| 500 | }
|
|---|
| 501 | }
|
|---|
| 502 | return cb(fullText, token.kind, { end: token.end, pos: tokenStart }, token.parent);
|
|---|
| 503 | }, sourceFile);
|
|---|
| 504 | }
|
|---|
| 505 | exports.forEachTokenWithTrivia = forEachTokenWithTrivia;
|
|---|
| 506 | /** Iterate over all comments owned by `node` or its children */
|
|---|
| 507 | function forEachComment(node, cb, sourceFile = node.getSourceFile()) {
|
|---|
| 508 | /* Visit all tokens and skip trivia.
|
|---|
| 509 | Comment ranges between tokens are parsed without the need of a scanner.
|
|---|
| 510 | forEachTokenWithWhitespace does intentionally not pay attention to the correct comment ownership of nodes as it always
|
|---|
| 511 | scans all trivia before each token, which could include trailing comments of the previous token.
|
|---|
| 512 | Comment onwership is done right in this function*/
|
|---|
| 513 | const fullText = sourceFile.text;
|
|---|
| 514 | const notJsx = sourceFile.languageVariant !== ts.LanguageVariant.JSX;
|
|---|
| 515 | return forEachToken(node, (token) => {
|
|---|
| 516 | if (token.pos === token.end)
|
|---|
| 517 | return;
|
|---|
| 518 | if (token.kind !== ts.SyntaxKind.JsxText)
|
|---|
| 519 | ts.forEachLeadingCommentRange(fullText,
|
|---|
| 520 | // skip shebang at position 0
|
|---|
| 521 | token.pos === 0 ? (ts.getShebang(fullText) || '').length : token.pos, commentCallback);
|
|---|
| 522 | if (notJsx || canHaveTrailingTrivia(token))
|
|---|
| 523 | return ts.forEachTrailingCommentRange(fullText, token.end, commentCallback);
|
|---|
| 524 | }, sourceFile);
|
|---|
| 525 | function commentCallback(pos, end, kind) {
|
|---|
| 526 | cb(fullText, { pos, end, kind });
|
|---|
| 527 | }
|
|---|
| 528 | }
|
|---|
| 529 | exports.forEachComment = forEachComment;
|
|---|
| 530 | /** Exclude trailing positions that would lead to scanning for trivia inside JsxText */
|
|---|
| 531 | function canHaveTrailingTrivia(token) {
|
|---|
| 532 | switch (token.kind) {
|
|---|
| 533 | case ts.SyntaxKind.CloseBraceToken:
|
|---|
| 534 | // after a JsxExpression inside a JsxElement's body can only be other JsxChild, but no trivia
|
|---|
| 535 | return token.parent.kind !== ts.SyntaxKind.JsxExpression || !isJsxElementOrFragment(token.parent.parent);
|
|---|
| 536 | case ts.SyntaxKind.GreaterThanToken:
|
|---|
| 537 | switch (token.parent.kind) {
|
|---|
| 538 | case ts.SyntaxKind.JsxOpeningElement:
|
|---|
| 539 | // if end is not equal, this is part of the type arguments list. in all other cases it would be inside the element body
|
|---|
| 540 | return token.end !== token.parent.end;
|
|---|
| 541 | case ts.SyntaxKind.JsxOpeningFragment:
|
|---|
| 542 | return false; // would be inside the fragment
|
|---|
| 543 | case ts.SyntaxKind.JsxSelfClosingElement:
|
|---|
| 544 | return token.end !== token.parent.end || // if end is not equal, this is part of the type arguments list
|
|---|
| 545 | !isJsxElementOrFragment(token.parent.parent); // there's only trailing trivia if it's the end of the top element
|
|---|
| 546 | case ts.SyntaxKind.JsxClosingElement:
|
|---|
| 547 | case ts.SyntaxKind.JsxClosingFragment:
|
|---|
| 548 | // there's only trailing trivia if it's the end of the top element
|
|---|
| 549 | return !isJsxElementOrFragment(token.parent.parent.parent);
|
|---|
| 550 | }
|
|---|
| 551 | }
|
|---|
| 552 | return true;
|
|---|
| 553 | }
|
|---|
| 554 | function isJsxElementOrFragment(node) {
|
|---|
| 555 | return node.kind === ts.SyntaxKind.JsxElement || node.kind === ts.SyntaxKind.JsxFragment;
|
|---|
| 556 | }
|
|---|
| 557 | function getLineRanges(sourceFile) {
|
|---|
| 558 | const lineStarts = sourceFile.getLineStarts();
|
|---|
| 559 | const result = [];
|
|---|
| 560 | const length = lineStarts.length;
|
|---|
| 561 | const sourceText = sourceFile.text;
|
|---|
| 562 | let pos = 0;
|
|---|
| 563 | for (let i = 1; i < length; ++i) {
|
|---|
| 564 | const end = lineStarts[i];
|
|---|
| 565 | let lineEnd = end;
|
|---|
| 566 | for (; lineEnd > pos; --lineEnd)
|
|---|
| 567 | if (!ts.isLineBreak(sourceText.charCodeAt(lineEnd - 1)))
|
|---|
| 568 | break;
|
|---|
| 569 | result.push({
|
|---|
| 570 | pos,
|
|---|
| 571 | end,
|
|---|
| 572 | contentLength: lineEnd - pos,
|
|---|
| 573 | });
|
|---|
| 574 | pos = end;
|
|---|
| 575 | }
|
|---|
| 576 | result.push({
|
|---|
| 577 | pos,
|
|---|
| 578 | end: sourceFile.end,
|
|---|
| 579 | contentLength: sourceFile.end - pos,
|
|---|
| 580 | });
|
|---|
| 581 | return result;
|
|---|
| 582 | }
|
|---|
| 583 | exports.getLineRanges = getLineRanges;
|
|---|
| 584 | /** Get the line break style used in sourceFile. This function only looks at the first line break. If there is none, \n is assumed. */
|
|---|
| 585 | function getLineBreakStyle(sourceFile) {
|
|---|
| 586 | const lineStarts = sourceFile.getLineStarts();
|
|---|
| 587 | return lineStarts.length === 1 || lineStarts[1] < 2 || sourceFile.text[lineStarts[1] - 2] !== '\r'
|
|---|
| 588 | ? '\n'
|
|---|
| 589 | : '\r\n';
|
|---|
| 590 | }
|
|---|
| 591 | exports.getLineBreakStyle = getLineBreakStyle;
|
|---|
| 592 | let cachedScanner;
|
|---|
| 593 | function scanToken(text, languageVersion) {
|
|---|
| 594 | if (cachedScanner === undefined) {
|
|---|
| 595 | // cache scanner
|
|---|
| 596 | cachedScanner = ts.createScanner(languageVersion, false, undefined, text);
|
|---|
| 597 | }
|
|---|
| 598 | else {
|
|---|
| 599 | cachedScanner.setScriptTarget(languageVersion);
|
|---|
| 600 | cachedScanner.setText(text);
|
|---|
| 601 | }
|
|---|
| 602 | cachedScanner.scan();
|
|---|
| 603 | return cachedScanner;
|
|---|
| 604 | }
|
|---|
| 605 | /**
|
|---|
| 606 | * Determines whether the given text parses as a standalone identifier.
|
|---|
| 607 | * This is not a guarantee that it works in every context. The property name in PropertyAccessExpressions for example allows reserved words.
|
|---|
| 608 | * Depending on the context it could be parsed as contextual keyword or TypeScript keyword.
|
|---|
| 609 | */
|
|---|
| 610 | function isValidIdentifier(text, languageVersion = ts.ScriptTarget.Latest) {
|
|---|
| 611 | const scan = scanToken(text, languageVersion);
|
|---|
| 612 | return scan.isIdentifier() && scan.getTextPos() === text.length && scan.getTokenPos() === 0;
|
|---|
| 613 | }
|
|---|
| 614 | exports.isValidIdentifier = isValidIdentifier;
|
|---|
| 615 | function charSize(ch) {
|
|---|
| 616 | return ch >= 0x10000 ? 2 : 1;
|
|---|
| 617 | }
|
|---|
| 618 | /**
|
|---|
| 619 | * Determines whether the given text can be used to access a property with a PropertyAccessExpression while preserving the property's name.
|
|---|
| 620 | */
|
|---|
| 621 | function isValidPropertyAccess(text, languageVersion = ts.ScriptTarget.Latest) {
|
|---|
| 622 | if (text.length === 0)
|
|---|
| 623 | return false;
|
|---|
| 624 | let ch = text.codePointAt(0);
|
|---|
| 625 | if (!ts.isIdentifierStart(ch, languageVersion))
|
|---|
| 626 | return false;
|
|---|
| 627 | for (let i = charSize(ch); i < text.length; i += charSize(ch)) {
|
|---|
| 628 | ch = text.codePointAt(i);
|
|---|
| 629 | if (!ts.isIdentifierPart(ch, languageVersion))
|
|---|
| 630 | return false;
|
|---|
| 631 | }
|
|---|
| 632 | return true;
|
|---|
| 633 | }
|
|---|
| 634 | exports.isValidPropertyAccess = isValidPropertyAccess;
|
|---|
| 635 | /**
|
|---|
| 636 | * Determines whether the given text can be used as unquoted name of a property declaration while preserving the property's name.
|
|---|
| 637 | */
|
|---|
| 638 | function isValidPropertyName(text, languageVersion = ts.ScriptTarget.Latest) {
|
|---|
| 639 | if (isValidPropertyAccess(text, languageVersion))
|
|---|
| 640 | return true;
|
|---|
| 641 | const scan = scanToken(text, languageVersion);
|
|---|
| 642 | return scan.getTextPos() === text.length &&
|
|---|
| 643 | scan.getToken() === ts.SyntaxKind.NumericLiteral && scan.getTokenValue() === text; // ensure stringified number equals literal
|
|---|
| 644 | }
|
|---|
| 645 | exports.isValidPropertyName = isValidPropertyName;
|
|---|
| 646 | /**
|
|---|
| 647 | * Determines whether the given text can be parsed as a numeric literal.
|
|---|
| 648 | */
|
|---|
| 649 | function isValidNumericLiteral(text, languageVersion = ts.ScriptTarget.Latest) {
|
|---|
| 650 | const scan = scanToken(text, languageVersion);
|
|---|
| 651 | return scan.getToken() === ts.SyntaxKind.NumericLiteral && scan.getTextPos() === text.length && scan.getTokenPos() === 0;
|
|---|
| 652 | }
|
|---|
| 653 | exports.isValidNumericLiteral = isValidNumericLiteral;
|
|---|
| 654 | /**
|
|---|
| 655 | * Determines whether the given text can be used as JSX tag or attribute name while preserving the exact name.
|
|---|
| 656 | */
|
|---|
| 657 | function isValidJsxIdentifier(text, languageVersion = ts.ScriptTarget.Latest) {
|
|---|
| 658 | if (text.length === 0)
|
|---|
| 659 | return false;
|
|---|
| 660 | let seenNamespaceSeparator = false;
|
|---|
| 661 | let ch = text.codePointAt(0);
|
|---|
| 662 | if (!ts.isIdentifierStart(ch, languageVersion))
|
|---|
| 663 | return false;
|
|---|
| 664 | for (let i = charSize(ch); i < text.length; i += charSize(ch)) {
|
|---|
| 665 | ch = text.codePointAt(i);
|
|---|
| 666 | if (!ts.isIdentifierPart(ch, languageVersion) && ch !== 45 /* minus */) {
|
|---|
| 667 | if (!seenNamespaceSeparator && ch === 58 /* colon */ && i + charSize(ch) !== text.length) {
|
|---|
| 668 | seenNamespaceSeparator = true;
|
|---|
| 669 | }
|
|---|
| 670 | else {
|
|---|
| 671 | return false;
|
|---|
| 672 | }
|
|---|
| 673 | }
|
|---|
| 674 | }
|
|---|
| 675 | return true;
|
|---|
| 676 | }
|
|---|
| 677 | exports.isValidJsxIdentifier = isValidJsxIdentifier;
|
|---|
| 678 | function isNumericPropertyName(name) {
|
|---|
| 679 | return String(+name) === name;
|
|---|
| 680 | }
|
|---|
| 681 | exports.isNumericPropertyName = isNumericPropertyName;
|
|---|
| 682 | function isSameLine(sourceFile, pos1, pos2) {
|
|---|
| 683 | return ts.getLineAndCharacterOfPosition(sourceFile, pos1).line === ts.getLineAndCharacterOfPosition(sourceFile, pos2).line;
|
|---|
| 684 | }
|
|---|
| 685 | exports.isSameLine = isSameLine;
|
|---|
| 686 | var SideEffectOptions;
|
|---|
| 687 | (function (SideEffectOptions) {
|
|---|
| 688 | SideEffectOptions[SideEffectOptions["None"] = 0] = "None";
|
|---|
| 689 | SideEffectOptions[SideEffectOptions["TaggedTemplate"] = 1] = "TaggedTemplate";
|
|---|
| 690 | SideEffectOptions[SideEffectOptions["Constructor"] = 2] = "Constructor";
|
|---|
| 691 | SideEffectOptions[SideEffectOptions["JsxElement"] = 4] = "JsxElement";
|
|---|
| 692 | })(SideEffectOptions = exports.SideEffectOptions || (exports.SideEffectOptions = {}));
|
|---|
| 693 | function hasSideEffects(node, options) {
|
|---|
| 694 | var _a, _b;
|
|---|
| 695 | const queue = [];
|
|---|
| 696 | while (true) {
|
|---|
| 697 | switch (node.kind) {
|
|---|
| 698 | case ts.SyntaxKind.CallExpression:
|
|---|
| 699 | case ts.SyntaxKind.PostfixUnaryExpression:
|
|---|
| 700 | case ts.SyntaxKind.AwaitExpression:
|
|---|
| 701 | case ts.SyntaxKind.YieldExpression:
|
|---|
| 702 | case ts.SyntaxKind.DeleteExpression:
|
|---|
| 703 | return true;
|
|---|
| 704 | case ts.SyntaxKind.TypeAssertionExpression:
|
|---|
| 705 | case ts.SyntaxKind.AsExpression:
|
|---|
| 706 | case ts.SyntaxKind.ParenthesizedExpression:
|
|---|
| 707 | case ts.SyntaxKind.NonNullExpression:
|
|---|
| 708 | case ts.SyntaxKind.VoidExpression:
|
|---|
| 709 | case ts.SyntaxKind.TypeOfExpression:
|
|---|
| 710 | case ts.SyntaxKind.PropertyAccessExpression:
|
|---|
| 711 | case ts.SyntaxKind.SpreadElement:
|
|---|
| 712 | case ts.SyntaxKind.PartiallyEmittedExpression:
|
|---|
| 713 | node = node.expression;
|
|---|
| 714 | continue;
|
|---|
| 715 | case ts.SyntaxKind.BinaryExpression:
|
|---|
| 716 | if (isAssignmentKind(node.operatorToken.kind))
|
|---|
| 717 | return true;
|
|---|
| 718 | queue.push(node.right);
|
|---|
| 719 | node = node.left;
|
|---|
| 720 | continue;
|
|---|
| 721 | case ts.SyntaxKind.PrefixUnaryExpression:
|
|---|
| 722 | switch (node.operator) {
|
|---|
| 723 | case ts.SyntaxKind.PlusPlusToken:
|
|---|
| 724 | case ts.SyntaxKind.MinusMinusToken:
|
|---|
| 725 | return true;
|
|---|
| 726 | default:
|
|---|
| 727 | node = node.operand;
|
|---|
| 728 | continue;
|
|---|
| 729 | }
|
|---|
| 730 | case ts.SyntaxKind.ElementAccessExpression:
|
|---|
| 731 | if (node.argumentExpression !== undefined) // for compatibility with typescript@<2.9.0
|
|---|
| 732 | queue.push(node.argumentExpression);
|
|---|
| 733 | node = node.expression;
|
|---|
| 734 | continue;
|
|---|
| 735 | case ts.SyntaxKind.ConditionalExpression:
|
|---|
| 736 | queue.push(node.whenTrue, node.whenFalse);
|
|---|
| 737 | node = node.condition;
|
|---|
| 738 | continue;
|
|---|
| 739 | case ts.SyntaxKind.NewExpression:
|
|---|
| 740 | if (options & 2 /* Constructor */)
|
|---|
| 741 | return true;
|
|---|
| 742 | if (node.arguments !== undefined)
|
|---|
| 743 | queue.push(...node.arguments);
|
|---|
| 744 | node = node.expression;
|
|---|
| 745 | continue;
|
|---|
| 746 | case ts.SyntaxKind.TaggedTemplateExpression:
|
|---|
| 747 | if (options & 1 /* TaggedTemplate */)
|
|---|
| 748 | return true;
|
|---|
| 749 | queue.push(node.tag);
|
|---|
| 750 | node = node.template;
|
|---|
| 751 | if (node.kind === ts.SyntaxKind.NoSubstitutionTemplateLiteral)
|
|---|
| 752 | break;
|
|---|
| 753 | // falls through
|
|---|
| 754 | case ts.SyntaxKind.TemplateExpression:
|
|---|
| 755 | for (const child of node.templateSpans)
|
|---|
| 756 | queue.push(child.expression);
|
|---|
| 757 | break;
|
|---|
| 758 | case ts.SyntaxKind.ClassExpression: {
|
|---|
| 759 | if (node.decorators !== undefined)
|
|---|
| 760 | return true;
|
|---|
| 761 | for (const child of node.members) {
|
|---|
| 762 | if (child.decorators !== undefined)
|
|---|
| 763 | return true;
|
|---|
| 764 | if (!hasModifier(child.modifiers, ts.SyntaxKind.DeclareKeyword)) {
|
|---|
| 765 | if (((_a = child.name) === null || _a === void 0 ? void 0 : _a.kind) === ts.SyntaxKind.ComputedPropertyName)
|
|---|
| 766 | queue.push(child.name.expression);
|
|---|
| 767 | if (node_1.isMethodDeclaration(child)) {
|
|---|
| 768 | for (const p of child.parameters)
|
|---|
| 769 | if (p.decorators !== undefined)
|
|---|
| 770 | return true;
|
|---|
| 771 | }
|
|---|
| 772 | else if (node_1.isPropertyDeclaration(child) &&
|
|---|
| 773 | child.initializer !== undefined &&
|
|---|
| 774 | hasModifier(child.modifiers, ts.SyntaxKind.StaticKeyword)) {
|
|---|
| 775 | queue.push(child.initializer);
|
|---|
| 776 | }
|
|---|
| 777 | }
|
|---|
| 778 | }
|
|---|
| 779 | const base = getBaseOfClassLikeExpression(node);
|
|---|
| 780 | if (base === undefined)
|
|---|
| 781 | break;
|
|---|
| 782 | node = base.expression;
|
|---|
| 783 | continue;
|
|---|
| 784 | }
|
|---|
| 785 | case ts.SyntaxKind.ArrayLiteralExpression:
|
|---|
| 786 | queue.push(...node.elements);
|
|---|
| 787 | break;
|
|---|
| 788 | case ts.SyntaxKind.ObjectLiteralExpression:
|
|---|
| 789 | for (const child of node.properties) {
|
|---|
| 790 | if (((_b = child.name) === null || _b === void 0 ? void 0 : _b.kind) === ts.SyntaxKind.ComputedPropertyName)
|
|---|
| 791 | queue.push(child.name.expression);
|
|---|
| 792 | switch (child.kind) {
|
|---|
| 793 | case ts.SyntaxKind.PropertyAssignment:
|
|---|
| 794 | queue.push(child.initializer);
|
|---|
| 795 | break;
|
|---|
| 796 | case ts.SyntaxKind.SpreadAssignment:
|
|---|
| 797 | queue.push(child.expression);
|
|---|
| 798 | }
|
|---|
| 799 | }
|
|---|
| 800 | break;
|
|---|
| 801 | case ts.SyntaxKind.JsxExpression:
|
|---|
| 802 | if (node.expression === undefined)
|
|---|
| 803 | break;
|
|---|
| 804 | node = node.expression;
|
|---|
| 805 | continue;
|
|---|
| 806 | case ts.SyntaxKind.JsxElement:
|
|---|
| 807 | case ts.SyntaxKind.JsxFragment:
|
|---|
| 808 | for (const child of node.children)
|
|---|
| 809 | if (child.kind !== ts.SyntaxKind.JsxText)
|
|---|
| 810 | queue.push(child);
|
|---|
| 811 | if (node.kind === ts.SyntaxKind.JsxFragment)
|
|---|
| 812 | break;
|
|---|
| 813 | node = node.openingElement;
|
|---|
| 814 | // falls through
|
|---|
| 815 | case ts.SyntaxKind.JsxSelfClosingElement:
|
|---|
| 816 | case ts.SyntaxKind.JsxOpeningElement:
|
|---|
| 817 | if (options & 4 /* JsxElement */)
|
|---|
| 818 | return true;
|
|---|
| 819 | for (const child of node.attributes.properties) {
|
|---|
| 820 | if (child.kind === ts.SyntaxKind.JsxSpreadAttribute) {
|
|---|
| 821 | queue.push(child.expression);
|
|---|
| 822 | }
|
|---|
| 823 | else if (child.initializer !== undefined) {
|
|---|
| 824 | queue.push(child.initializer);
|
|---|
| 825 | }
|
|---|
| 826 | }
|
|---|
| 827 | break;
|
|---|
| 828 | case ts.SyntaxKind.CommaListExpression:
|
|---|
| 829 | queue.push(...node.elements);
|
|---|
| 830 | }
|
|---|
| 831 | if (queue.length === 0)
|
|---|
| 832 | return false;
|
|---|
| 833 | node = queue.pop();
|
|---|
| 834 | }
|
|---|
| 835 | }
|
|---|
| 836 | exports.hasSideEffects = hasSideEffects;
|
|---|
| 837 | /** Returns the VariableDeclaration or ParameterDeclaration that contains the BindingElement */
|
|---|
| 838 | function getDeclarationOfBindingElement(node) {
|
|---|
| 839 | let parent = node.parent.parent;
|
|---|
| 840 | while (parent.kind === ts.SyntaxKind.BindingElement)
|
|---|
| 841 | parent = parent.parent.parent;
|
|---|
| 842 | return parent;
|
|---|
| 843 | }
|
|---|
| 844 | exports.getDeclarationOfBindingElement = getDeclarationOfBindingElement;
|
|---|
| 845 | function isExpressionValueUsed(node) {
|
|---|
| 846 | while (true) {
|
|---|
| 847 | const parent = node.parent;
|
|---|
| 848 | switch (parent.kind) {
|
|---|
| 849 | case ts.SyntaxKind.CallExpression:
|
|---|
| 850 | case ts.SyntaxKind.NewExpression:
|
|---|
| 851 | case ts.SyntaxKind.ElementAccessExpression:
|
|---|
| 852 | case ts.SyntaxKind.WhileStatement:
|
|---|
| 853 | case ts.SyntaxKind.DoStatement:
|
|---|
| 854 | case ts.SyntaxKind.WithStatement:
|
|---|
| 855 | case ts.SyntaxKind.ThrowStatement:
|
|---|
| 856 | case ts.SyntaxKind.ReturnStatement:
|
|---|
| 857 | case ts.SyntaxKind.JsxExpression:
|
|---|
| 858 | case ts.SyntaxKind.JsxSpreadAttribute:
|
|---|
| 859 | case ts.SyntaxKind.JsxElement:
|
|---|
| 860 | case ts.SyntaxKind.JsxFragment:
|
|---|
| 861 | case ts.SyntaxKind.JsxSelfClosingElement:
|
|---|
| 862 | case ts.SyntaxKind.ComputedPropertyName:
|
|---|
| 863 | case ts.SyntaxKind.ArrowFunction:
|
|---|
| 864 | case ts.SyntaxKind.ExportSpecifier:
|
|---|
| 865 | case ts.SyntaxKind.ExportAssignment:
|
|---|
| 866 | case ts.SyntaxKind.ImportDeclaration:
|
|---|
| 867 | case ts.SyntaxKind.ExternalModuleReference:
|
|---|
| 868 | case ts.SyntaxKind.Decorator:
|
|---|
| 869 | case ts.SyntaxKind.TaggedTemplateExpression:
|
|---|
| 870 | case ts.SyntaxKind.TemplateSpan:
|
|---|
| 871 | case ts.SyntaxKind.ExpressionWithTypeArguments:
|
|---|
| 872 | case ts.SyntaxKind.TypeOfExpression:
|
|---|
| 873 | case ts.SyntaxKind.AwaitExpression:
|
|---|
| 874 | case ts.SyntaxKind.YieldExpression:
|
|---|
| 875 | case ts.SyntaxKind.LiteralType:
|
|---|
| 876 | case ts.SyntaxKind.JsxAttributes:
|
|---|
| 877 | case ts.SyntaxKind.JsxOpeningElement:
|
|---|
| 878 | case ts.SyntaxKind.JsxClosingElement:
|
|---|
| 879 | case ts.SyntaxKind.IfStatement:
|
|---|
| 880 | case ts.SyntaxKind.CaseClause:
|
|---|
| 881 | case ts.SyntaxKind.SwitchStatement:
|
|---|
| 882 | return true;
|
|---|
| 883 | case ts.SyntaxKind.PropertyAccessExpression:
|
|---|
| 884 | return parent.expression === node;
|
|---|
| 885 | case ts.SyntaxKind.QualifiedName:
|
|---|
| 886 | return parent.left === node;
|
|---|
| 887 | case ts.SyntaxKind.ShorthandPropertyAssignment:
|
|---|
| 888 | return parent.objectAssignmentInitializer === node ||
|
|---|
| 889 | !isInDestructuringAssignment(parent);
|
|---|
| 890 | case ts.SyntaxKind.PropertyAssignment:
|
|---|
| 891 | return parent.initializer === node && !isInDestructuringAssignment(parent);
|
|---|
| 892 | case ts.SyntaxKind.SpreadAssignment:
|
|---|
| 893 | case ts.SyntaxKind.SpreadElement:
|
|---|
| 894 | case ts.SyntaxKind.ArrayLiteralExpression:
|
|---|
| 895 | return !isInDestructuringAssignment(parent);
|
|---|
| 896 | case ts.SyntaxKind.ParenthesizedExpression:
|
|---|
| 897 | case ts.SyntaxKind.AsExpression:
|
|---|
| 898 | case ts.SyntaxKind.TypeAssertionExpression:
|
|---|
| 899 | case ts.SyntaxKind.PostfixUnaryExpression:
|
|---|
| 900 | case ts.SyntaxKind.PrefixUnaryExpression:
|
|---|
| 901 | case ts.SyntaxKind.NonNullExpression:
|
|---|
| 902 | node = parent;
|
|---|
| 903 | continue;
|
|---|
| 904 | case ts.SyntaxKind.ForStatement:
|
|---|
| 905 | return parent.condition === node;
|
|---|
| 906 | case ts.SyntaxKind.ForInStatement:
|
|---|
| 907 | case ts.SyntaxKind.ForOfStatement:
|
|---|
| 908 | return parent.expression === node;
|
|---|
| 909 | case ts.SyntaxKind.ConditionalExpression:
|
|---|
| 910 | if (parent.condition === node)
|
|---|
| 911 | return true;
|
|---|
| 912 | node = parent;
|
|---|
| 913 | break;
|
|---|
| 914 | case ts.SyntaxKind.PropertyDeclaration:
|
|---|
| 915 | case ts.SyntaxKind.BindingElement:
|
|---|
| 916 | case ts.SyntaxKind.VariableDeclaration:
|
|---|
| 917 | case ts.SyntaxKind.Parameter:
|
|---|
| 918 | case ts.SyntaxKind.EnumMember:
|
|---|
| 919 | return parent.initializer === node;
|
|---|
| 920 | case ts.SyntaxKind.ImportEqualsDeclaration:
|
|---|
| 921 | return parent.moduleReference === node;
|
|---|
| 922 | case ts.SyntaxKind.CommaListExpression:
|
|---|
| 923 | if (parent.elements[parent.elements.length - 1] !== node)
|
|---|
| 924 | return false;
|
|---|
| 925 | node = parent;
|
|---|
| 926 | break;
|
|---|
| 927 | case ts.SyntaxKind.BinaryExpression:
|
|---|
| 928 | if (parent.right === node) {
|
|---|
| 929 | if (parent.operatorToken.kind === ts.SyntaxKind.CommaToken) {
|
|---|
| 930 | node = parent;
|
|---|
| 931 | break;
|
|---|
| 932 | }
|
|---|
| 933 | return true;
|
|---|
| 934 | }
|
|---|
| 935 | switch (parent.operatorToken.kind) {
|
|---|
| 936 | case ts.SyntaxKind.CommaToken:
|
|---|
| 937 | case ts.SyntaxKind.EqualsToken:
|
|---|
| 938 | return false;
|
|---|
| 939 | case ts.SyntaxKind.EqualsEqualsEqualsToken:
|
|---|
| 940 | case ts.SyntaxKind.EqualsEqualsToken:
|
|---|
| 941 | case ts.SyntaxKind.ExclamationEqualsEqualsToken:
|
|---|
| 942 | case ts.SyntaxKind.ExclamationEqualsToken:
|
|---|
| 943 | case ts.SyntaxKind.InstanceOfKeyword:
|
|---|
| 944 | case ts.SyntaxKind.PlusToken:
|
|---|
| 945 | case ts.SyntaxKind.MinusToken:
|
|---|
| 946 | case ts.SyntaxKind.AsteriskToken:
|
|---|
| 947 | case ts.SyntaxKind.SlashToken:
|
|---|
| 948 | case ts.SyntaxKind.PercentToken:
|
|---|
| 949 | case ts.SyntaxKind.AsteriskAsteriskToken:
|
|---|
| 950 | case ts.SyntaxKind.GreaterThanToken:
|
|---|
| 951 | case ts.SyntaxKind.GreaterThanGreaterThanToken:
|
|---|
| 952 | case ts.SyntaxKind.GreaterThanGreaterThanGreaterThanToken:
|
|---|
| 953 | case ts.SyntaxKind.GreaterThanEqualsToken:
|
|---|
| 954 | case ts.SyntaxKind.LessThanToken:
|
|---|
| 955 | case ts.SyntaxKind.LessThanLessThanToken:
|
|---|
| 956 | case ts.SyntaxKind.LessThanEqualsToken:
|
|---|
| 957 | case ts.SyntaxKind.AmpersandToken:
|
|---|
| 958 | case ts.SyntaxKind.BarToken:
|
|---|
| 959 | case ts.SyntaxKind.CaretToken:
|
|---|
| 960 | case ts.SyntaxKind.BarBarToken:
|
|---|
| 961 | case ts.SyntaxKind.AmpersandAmpersandToken:
|
|---|
| 962 | case ts.SyntaxKind.QuestionQuestionToken:
|
|---|
| 963 | case ts.SyntaxKind.InKeyword:
|
|---|
| 964 | case ts.SyntaxKind.QuestionQuestionEqualsToken:
|
|---|
| 965 | case ts.SyntaxKind.AmpersandAmpersandEqualsToken:
|
|---|
| 966 | case ts.SyntaxKind.BarBarEqualsToken:
|
|---|
| 967 | return true;
|
|---|
| 968 | default:
|
|---|
| 969 | node = parent;
|
|---|
| 970 | }
|
|---|
| 971 | break;
|
|---|
| 972 | default:
|
|---|
| 973 | return false;
|
|---|
| 974 | }
|
|---|
| 975 | }
|
|---|
| 976 | }
|
|---|
| 977 | exports.isExpressionValueUsed = isExpressionValueUsed;
|
|---|
| 978 | function isInDestructuringAssignment(node) {
|
|---|
| 979 | switch (node.kind) {
|
|---|
| 980 | case ts.SyntaxKind.ShorthandPropertyAssignment:
|
|---|
| 981 | if (node.objectAssignmentInitializer !== undefined)
|
|---|
| 982 | return true;
|
|---|
| 983 | // falls through
|
|---|
| 984 | case ts.SyntaxKind.PropertyAssignment:
|
|---|
| 985 | case ts.SyntaxKind.SpreadAssignment:
|
|---|
| 986 | node = node.parent;
|
|---|
| 987 | break;
|
|---|
| 988 | case ts.SyntaxKind.SpreadElement:
|
|---|
| 989 | if (node.parent.kind !== ts.SyntaxKind.ArrayLiteralExpression)
|
|---|
| 990 | return false;
|
|---|
| 991 | node = node.parent;
|
|---|
| 992 | }
|
|---|
| 993 | while (true) {
|
|---|
| 994 | switch (node.parent.kind) {
|
|---|
| 995 | case ts.SyntaxKind.BinaryExpression:
|
|---|
| 996 | return node.parent.left === node &&
|
|---|
| 997 | node.parent.operatorToken.kind === ts.SyntaxKind.EqualsToken;
|
|---|
| 998 | case ts.SyntaxKind.ForOfStatement:
|
|---|
| 999 | return node.parent.initializer === node;
|
|---|
| 1000 | case ts.SyntaxKind.ArrayLiteralExpression:
|
|---|
| 1001 | case ts.SyntaxKind.ObjectLiteralExpression:
|
|---|
| 1002 | node = node.parent;
|
|---|
| 1003 | break;
|
|---|
| 1004 | case ts.SyntaxKind.SpreadAssignment:
|
|---|
| 1005 | case ts.SyntaxKind.PropertyAssignment:
|
|---|
| 1006 | node = node.parent.parent;
|
|---|
| 1007 | break;
|
|---|
| 1008 | case ts.SyntaxKind.SpreadElement:
|
|---|
| 1009 | if (node.parent.parent.kind !== ts.SyntaxKind.ArrayLiteralExpression)
|
|---|
| 1010 | return false;
|
|---|
| 1011 | node = node.parent.parent;
|
|---|
| 1012 | break;
|
|---|
| 1013 | default:
|
|---|
| 1014 | return false;
|
|---|
| 1015 | }
|
|---|
| 1016 | }
|
|---|
| 1017 | }
|
|---|
| 1018 | var AccessKind;
|
|---|
| 1019 | (function (AccessKind) {
|
|---|
| 1020 | AccessKind[AccessKind["None"] = 0] = "None";
|
|---|
| 1021 | AccessKind[AccessKind["Read"] = 1] = "Read";
|
|---|
| 1022 | AccessKind[AccessKind["Write"] = 2] = "Write";
|
|---|
| 1023 | AccessKind[AccessKind["Delete"] = 4] = "Delete";
|
|---|
| 1024 | AccessKind[AccessKind["ReadWrite"] = 3] = "ReadWrite";
|
|---|
| 1025 | AccessKind[AccessKind["Modification"] = 6] = "Modification";
|
|---|
| 1026 | })(AccessKind = exports.AccessKind || (exports.AccessKind = {}));
|
|---|
| 1027 | function getAccessKind(node) {
|
|---|
| 1028 | const parent = node.parent;
|
|---|
| 1029 | switch (parent.kind) {
|
|---|
| 1030 | case ts.SyntaxKind.DeleteExpression:
|
|---|
| 1031 | return 4 /* Delete */;
|
|---|
| 1032 | case ts.SyntaxKind.PostfixUnaryExpression:
|
|---|
| 1033 | return 3 /* ReadWrite */;
|
|---|
| 1034 | case ts.SyntaxKind.PrefixUnaryExpression:
|
|---|
| 1035 | return parent.operator === ts.SyntaxKind.PlusPlusToken ||
|
|---|
| 1036 | parent.operator === ts.SyntaxKind.MinusMinusToken
|
|---|
| 1037 | ? 3 /* ReadWrite */
|
|---|
| 1038 | : 1 /* Read */;
|
|---|
| 1039 | case ts.SyntaxKind.BinaryExpression:
|
|---|
| 1040 | return parent.right === node
|
|---|
| 1041 | ? 1 /* Read */
|
|---|
| 1042 | : !isAssignmentKind(parent.operatorToken.kind)
|
|---|
| 1043 | ? 1 /* Read */
|
|---|
| 1044 | : parent.operatorToken.kind === ts.SyntaxKind.EqualsToken
|
|---|
| 1045 | ? 2 /* Write */
|
|---|
| 1046 | : 3 /* ReadWrite */;
|
|---|
| 1047 | case ts.SyntaxKind.ShorthandPropertyAssignment:
|
|---|
| 1048 | return parent.objectAssignmentInitializer === node
|
|---|
| 1049 | ? 1 /* Read */
|
|---|
| 1050 | : isInDestructuringAssignment(parent)
|
|---|
| 1051 | ? 2 /* Write */
|
|---|
| 1052 | : 1 /* Read */;
|
|---|
| 1053 | case ts.SyntaxKind.PropertyAssignment:
|
|---|
| 1054 | return parent.name === node
|
|---|
| 1055 | ? 0 /* None */
|
|---|
| 1056 | : isInDestructuringAssignment(parent)
|
|---|
| 1057 | ? 2 /* Write */
|
|---|
| 1058 | : 1 /* Read */;
|
|---|
| 1059 | case ts.SyntaxKind.ArrayLiteralExpression:
|
|---|
| 1060 | case ts.SyntaxKind.SpreadElement:
|
|---|
| 1061 | case ts.SyntaxKind.SpreadAssignment:
|
|---|
| 1062 | return isInDestructuringAssignment(parent)
|
|---|
| 1063 | ? 2 /* Write */
|
|---|
| 1064 | : 1 /* Read */;
|
|---|
| 1065 | case ts.SyntaxKind.ParenthesizedExpression:
|
|---|
| 1066 | case ts.SyntaxKind.NonNullExpression:
|
|---|
| 1067 | case ts.SyntaxKind.TypeAssertionExpression:
|
|---|
| 1068 | case ts.SyntaxKind.AsExpression:
|
|---|
| 1069 | // (<number>foo! as {})++
|
|---|
| 1070 | return getAccessKind(parent);
|
|---|
| 1071 | case ts.SyntaxKind.ForOfStatement:
|
|---|
| 1072 | case ts.SyntaxKind.ForInStatement:
|
|---|
| 1073 | return parent.initializer === node
|
|---|
| 1074 | ? 2 /* Write */
|
|---|
| 1075 | : 1 /* Read */;
|
|---|
| 1076 | case ts.SyntaxKind.ExpressionWithTypeArguments:
|
|---|
| 1077 | return parent.parent.token === ts.SyntaxKind.ExtendsKeyword &&
|
|---|
| 1078 | parent.parent.parent.kind !== ts.SyntaxKind.InterfaceDeclaration
|
|---|
| 1079 | ? 1 /* Read */
|
|---|
| 1080 | : 0 /* None */;
|
|---|
| 1081 | case ts.SyntaxKind.ComputedPropertyName:
|
|---|
| 1082 | case ts.SyntaxKind.ExpressionStatement:
|
|---|
| 1083 | case ts.SyntaxKind.TypeOfExpression:
|
|---|
| 1084 | case ts.SyntaxKind.ElementAccessExpression:
|
|---|
| 1085 | case ts.SyntaxKind.ForStatement:
|
|---|
| 1086 | case ts.SyntaxKind.IfStatement:
|
|---|
| 1087 | case ts.SyntaxKind.DoStatement:
|
|---|
| 1088 | case ts.SyntaxKind.WhileStatement:
|
|---|
| 1089 | case ts.SyntaxKind.SwitchStatement:
|
|---|
| 1090 | case ts.SyntaxKind.WithStatement:
|
|---|
| 1091 | case ts.SyntaxKind.ThrowStatement:
|
|---|
| 1092 | case ts.SyntaxKind.CallExpression:
|
|---|
| 1093 | case ts.SyntaxKind.NewExpression:
|
|---|
| 1094 | case ts.SyntaxKind.TaggedTemplateExpression:
|
|---|
| 1095 | case ts.SyntaxKind.JsxExpression:
|
|---|
| 1096 | case ts.SyntaxKind.Decorator:
|
|---|
| 1097 | case ts.SyntaxKind.TemplateSpan:
|
|---|
| 1098 | case ts.SyntaxKind.JsxOpeningElement:
|
|---|
| 1099 | case ts.SyntaxKind.JsxSelfClosingElement:
|
|---|
| 1100 | case ts.SyntaxKind.JsxSpreadAttribute:
|
|---|
| 1101 | case ts.SyntaxKind.VoidExpression:
|
|---|
| 1102 | case ts.SyntaxKind.ReturnStatement:
|
|---|
| 1103 | case ts.SyntaxKind.AwaitExpression:
|
|---|
| 1104 | case ts.SyntaxKind.YieldExpression:
|
|---|
| 1105 | case ts.SyntaxKind.ConditionalExpression:
|
|---|
| 1106 | case ts.SyntaxKind.CaseClause:
|
|---|
| 1107 | case ts.SyntaxKind.JsxElement:
|
|---|
| 1108 | return 1 /* Read */;
|
|---|
| 1109 | case ts.SyntaxKind.ArrowFunction:
|
|---|
| 1110 | return parent.body === node
|
|---|
| 1111 | ? 1 /* Read */
|
|---|
| 1112 | : 2 /* Write */;
|
|---|
| 1113 | case ts.SyntaxKind.PropertyDeclaration:
|
|---|
| 1114 | case ts.SyntaxKind.VariableDeclaration:
|
|---|
| 1115 | case ts.SyntaxKind.Parameter:
|
|---|
| 1116 | case ts.SyntaxKind.EnumMember:
|
|---|
| 1117 | case ts.SyntaxKind.BindingElement:
|
|---|
| 1118 | case ts.SyntaxKind.JsxAttribute:
|
|---|
| 1119 | return parent.initializer === node
|
|---|
| 1120 | ? 1 /* Read */
|
|---|
| 1121 | : 0 /* None */;
|
|---|
| 1122 | case ts.SyntaxKind.PropertyAccessExpression:
|
|---|
| 1123 | return parent.expression === node
|
|---|
| 1124 | ? 1 /* Read */
|
|---|
| 1125 | : 0 /* None */;
|
|---|
| 1126 | case ts.SyntaxKind.ExportAssignment:
|
|---|
| 1127 | return parent.isExportEquals
|
|---|
| 1128 | ? 1 /* Read */
|
|---|
| 1129 | : 0 /* None */;
|
|---|
| 1130 | }
|
|---|
| 1131 | return 0 /* None */;
|
|---|
| 1132 | }
|
|---|
| 1133 | exports.getAccessKind = getAccessKind;
|
|---|
| 1134 | function isReassignmentTarget(node) {
|
|---|
| 1135 | return (getAccessKind(node) & 2 /* Write */) !== 0;
|
|---|
| 1136 | }
|
|---|
| 1137 | exports.isReassignmentTarget = isReassignmentTarget;
|
|---|
| 1138 | function canHaveJsDoc(node) {
|
|---|
| 1139 | const kind = node.kind;
|
|---|
| 1140 | switch (kind) {
|
|---|
| 1141 | case ts.SyntaxKind.Parameter:
|
|---|
| 1142 | case ts.SyntaxKind.CallSignature:
|
|---|
| 1143 | case ts.SyntaxKind.ConstructSignature:
|
|---|
| 1144 | case ts.SyntaxKind.MethodSignature:
|
|---|
| 1145 | case ts.SyntaxKind.PropertySignature:
|
|---|
| 1146 | case ts.SyntaxKind.ArrowFunction:
|
|---|
| 1147 | case ts.SyntaxKind.ParenthesizedExpression:
|
|---|
| 1148 | case ts.SyntaxKind.SpreadAssignment:
|
|---|
| 1149 | case ts.SyntaxKind.ShorthandPropertyAssignment:
|
|---|
| 1150 | case ts.SyntaxKind.PropertyAssignment:
|
|---|
| 1151 | case ts.SyntaxKind.FunctionExpression:
|
|---|
| 1152 | case ts.SyntaxKind.LabeledStatement:
|
|---|
| 1153 | case ts.SyntaxKind.ExpressionStatement:
|
|---|
| 1154 | case ts.SyntaxKind.VariableStatement:
|
|---|
| 1155 | case ts.SyntaxKind.FunctionDeclaration:
|
|---|
| 1156 | case ts.SyntaxKind.Constructor:
|
|---|
| 1157 | case ts.SyntaxKind.MethodDeclaration:
|
|---|
| 1158 | case ts.SyntaxKind.PropertyDeclaration:
|
|---|
| 1159 | case ts.SyntaxKind.GetAccessor:
|
|---|
| 1160 | case ts.SyntaxKind.SetAccessor:
|
|---|
| 1161 | case ts.SyntaxKind.ClassDeclaration:
|
|---|
| 1162 | case ts.SyntaxKind.ClassExpression:
|
|---|
| 1163 | case ts.SyntaxKind.InterfaceDeclaration:
|
|---|
| 1164 | case ts.SyntaxKind.TypeAliasDeclaration:
|
|---|
| 1165 | case ts.SyntaxKind.EnumMember:
|
|---|
| 1166 | case ts.SyntaxKind.EnumDeclaration:
|
|---|
| 1167 | case ts.SyntaxKind.ModuleDeclaration:
|
|---|
| 1168 | case ts.SyntaxKind.ImportEqualsDeclaration:
|
|---|
| 1169 | case ts.SyntaxKind.ImportDeclaration:
|
|---|
| 1170 | case ts.SyntaxKind.NamespaceExportDeclaration:
|
|---|
| 1171 | case ts.SyntaxKind.ExportAssignment:
|
|---|
| 1172 | case ts.SyntaxKind.IndexSignature:
|
|---|
| 1173 | case ts.SyntaxKind.FunctionType:
|
|---|
| 1174 | case ts.SyntaxKind.ConstructorType:
|
|---|
| 1175 | case ts.SyntaxKind.JSDocFunctionType:
|
|---|
| 1176 | case ts.SyntaxKind.ExportDeclaration:
|
|---|
| 1177 | case ts.SyntaxKind.NamedTupleMember:
|
|---|
| 1178 | case ts.SyntaxKind.EndOfFileToken:
|
|---|
| 1179 | return true;
|
|---|
| 1180 | default:
|
|---|
| 1181 | return false;
|
|---|
| 1182 | }
|
|---|
| 1183 | }
|
|---|
| 1184 | exports.canHaveJsDoc = canHaveJsDoc;
|
|---|
| 1185 | /** Gets the JSDoc of a node. For performance reasons this function should only be called when `canHaveJsDoc` returns true. */
|
|---|
| 1186 | function getJsDoc(node, sourceFile) {
|
|---|
| 1187 | const result = [];
|
|---|
| 1188 | for (const child of node.getChildren(sourceFile)) {
|
|---|
| 1189 | if (!node_1.isJsDoc(child))
|
|---|
| 1190 | break;
|
|---|
| 1191 | result.push(child);
|
|---|
| 1192 | }
|
|---|
| 1193 | return result;
|
|---|
| 1194 | }
|
|---|
| 1195 | exports.getJsDoc = getJsDoc;
|
|---|
| 1196 | /**
|
|---|
| 1197 | * Parses the JsDoc of any node. This function is made for nodes that don't get their JsDoc parsed by the TypeScript parser.
|
|---|
| 1198 | *
|
|---|
| 1199 | * @param considerTrailingComments When set to `true` this function uses the trailing comments if the node starts on the same line
|
|---|
| 1200 | * as the previous node ends.
|
|---|
| 1201 | */
|
|---|
| 1202 | function parseJsDocOfNode(node, considerTrailingComments, sourceFile = node.getSourceFile()) {
|
|---|
| 1203 | if (canHaveJsDoc(node) && node.kind !== ts.SyntaxKind.EndOfFileToken) {
|
|---|
| 1204 | const result = getJsDoc(node, sourceFile);
|
|---|
| 1205 | if (result.length !== 0 || !considerTrailingComments)
|
|---|
| 1206 | return result;
|
|---|
| 1207 | }
|
|---|
| 1208 | return parseJsDocWorker(node, node.getStart(sourceFile), sourceFile, considerTrailingComments);
|
|---|
| 1209 | }
|
|---|
| 1210 | exports.parseJsDocOfNode = parseJsDocOfNode;
|
|---|
| 1211 | function parseJsDocWorker(node, nodeStart, sourceFile, considerTrailingComments) {
|
|---|
| 1212 | const start = ts[considerTrailingComments && isSameLine(sourceFile, node.pos, nodeStart)
|
|---|
| 1213 | ? 'forEachTrailingCommentRange'
|
|---|
| 1214 | : 'forEachLeadingCommentRange'](sourceFile.text, node.pos,
|
|---|
| 1215 | // return object to make `0` a truthy value
|
|---|
| 1216 | (pos, _end, kind) => kind === ts.SyntaxKind.MultiLineCommentTrivia && sourceFile.text[pos + 2] === '*' ? { pos } : undefined);
|
|---|
| 1217 | if (start === undefined)
|
|---|
| 1218 | return [];
|
|---|
| 1219 | const startPos = start.pos;
|
|---|
| 1220 | const text = sourceFile.text.slice(startPos, nodeStart);
|
|---|
| 1221 | const newSourceFile = ts.createSourceFile('jsdoc.ts', `${text}var a;`, sourceFile.languageVersion);
|
|---|
| 1222 | const result = getJsDoc(newSourceFile.statements[0], newSourceFile);
|
|---|
| 1223 | for (const doc of result)
|
|---|
| 1224 | updateNode(doc, node);
|
|---|
| 1225 | return result;
|
|---|
| 1226 | function updateNode(n, parent) {
|
|---|
| 1227 | n.pos += startPos;
|
|---|
| 1228 | n.end += startPos;
|
|---|
| 1229 | n.parent = parent;
|
|---|
| 1230 | return ts.forEachChild(n, (child) => updateNode(child, n), (children) => {
|
|---|
| 1231 | children.pos += startPos;
|
|---|
| 1232 | children.end += startPos;
|
|---|
| 1233 | for (const child of children)
|
|---|
| 1234 | updateNode(child, n);
|
|---|
| 1235 | });
|
|---|
| 1236 | }
|
|---|
| 1237 | }
|
|---|
| 1238 | var ImportKind;
|
|---|
| 1239 | (function (ImportKind) {
|
|---|
| 1240 | ImportKind[ImportKind["ImportDeclaration"] = 1] = "ImportDeclaration";
|
|---|
| 1241 | ImportKind[ImportKind["ImportEquals"] = 2] = "ImportEquals";
|
|---|
| 1242 | ImportKind[ImportKind["ExportFrom"] = 4] = "ExportFrom";
|
|---|
| 1243 | ImportKind[ImportKind["DynamicImport"] = 8] = "DynamicImport";
|
|---|
| 1244 | ImportKind[ImportKind["Require"] = 16] = "Require";
|
|---|
| 1245 | ImportKind[ImportKind["ImportType"] = 32] = "ImportType";
|
|---|
| 1246 | ImportKind[ImportKind["All"] = 63] = "All";
|
|---|
| 1247 | ImportKind[ImportKind["AllImports"] = 59] = "AllImports";
|
|---|
| 1248 | ImportKind[ImportKind["AllStaticImports"] = 3] = "AllStaticImports";
|
|---|
| 1249 | ImportKind[ImportKind["AllImportExpressions"] = 24] = "AllImportExpressions";
|
|---|
| 1250 | ImportKind[ImportKind["AllRequireLike"] = 18] = "AllRequireLike";
|
|---|
| 1251 | // @internal
|
|---|
| 1252 | ImportKind[ImportKind["AllNestedImports"] = 56] = "AllNestedImports";
|
|---|
| 1253 | // @internal
|
|---|
| 1254 | ImportKind[ImportKind["AllTopLevelImports"] = 7] = "AllTopLevelImports";
|
|---|
| 1255 | })(ImportKind = exports.ImportKind || (exports.ImportKind = {}));
|
|---|
| 1256 | function findImports(sourceFile, kinds, ignoreFileName = true) {
|
|---|
| 1257 | const result = [];
|
|---|
| 1258 | for (const node of findImportLikeNodes(sourceFile, kinds, ignoreFileName)) {
|
|---|
| 1259 | switch (node.kind) {
|
|---|
| 1260 | case ts.SyntaxKind.ImportDeclaration:
|
|---|
| 1261 | addIfTextualLiteral(node.moduleSpecifier);
|
|---|
| 1262 | break;
|
|---|
| 1263 | case ts.SyntaxKind.ImportEqualsDeclaration:
|
|---|
| 1264 | addIfTextualLiteral(node.moduleReference.expression);
|
|---|
| 1265 | break;
|
|---|
| 1266 | case ts.SyntaxKind.ExportDeclaration:
|
|---|
| 1267 | addIfTextualLiteral(node.moduleSpecifier);
|
|---|
| 1268 | break;
|
|---|
| 1269 | case ts.SyntaxKind.CallExpression:
|
|---|
| 1270 | addIfTextualLiteral(node.arguments[0]);
|
|---|
| 1271 | break;
|
|---|
| 1272 | case ts.SyntaxKind.ImportType:
|
|---|
| 1273 | if (node_1.isLiteralTypeNode(node.argument))
|
|---|
| 1274 | addIfTextualLiteral(node.argument.literal);
|
|---|
| 1275 | break;
|
|---|
| 1276 | default:
|
|---|
| 1277 | throw new Error('unexpected node');
|
|---|
| 1278 | }
|
|---|
| 1279 | }
|
|---|
| 1280 | return result;
|
|---|
| 1281 | function addIfTextualLiteral(node) {
|
|---|
| 1282 | if (node_1.isTextualLiteral(node))
|
|---|
| 1283 | result.push(node);
|
|---|
| 1284 | }
|
|---|
| 1285 | }
|
|---|
| 1286 | exports.findImports = findImports;
|
|---|
| 1287 | function findImportLikeNodes(sourceFile, kinds, ignoreFileName = true) {
|
|---|
| 1288 | return new ImportFinder(sourceFile, kinds, ignoreFileName).find();
|
|---|
| 1289 | }
|
|---|
| 1290 | exports.findImportLikeNodes = findImportLikeNodes;
|
|---|
| 1291 | class ImportFinder {
|
|---|
| 1292 | constructor(_sourceFile, _options, _ignoreFileName) {
|
|---|
| 1293 | this._sourceFile = _sourceFile;
|
|---|
| 1294 | this._options = _options;
|
|---|
| 1295 | this._ignoreFileName = _ignoreFileName;
|
|---|
| 1296 | this._result = [];
|
|---|
| 1297 | }
|
|---|
| 1298 | find() {
|
|---|
| 1299 | if (this._sourceFile.isDeclarationFile)
|
|---|
| 1300 | this._options &= ~24 /* AllImportExpressions */;
|
|---|
| 1301 | if (this._options & 7 /* AllTopLevelImports */)
|
|---|
| 1302 | this._findImports(this._sourceFile.statements);
|
|---|
| 1303 | if (this._options & 56 /* AllNestedImports */)
|
|---|
| 1304 | this._findNestedImports();
|
|---|
| 1305 | return this._result;
|
|---|
| 1306 | }
|
|---|
| 1307 | _findImports(statements) {
|
|---|
| 1308 | for (const statement of statements) {
|
|---|
| 1309 | if (node_1.isImportDeclaration(statement)) {
|
|---|
| 1310 | if (this._options & 1 /* ImportDeclaration */)
|
|---|
| 1311 | this._result.push(statement);
|
|---|
| 1312 | }
|
|---|
| 1313 | else if (node_1.isImportEqualsDeclaration(statement)) {
|
|---|
| 1314 | if (this._options & 2 /* ImportEquals */ &&
|
|---|
| 1315 | statement.moduleReference.kind === ts.SyntaxKind.ExternalModuleReference)
|
|---|
| 1316 | this._result.push(statement);
|
|---|
| 1317 | }
|
|---|
| 1318 | else if (node_1.isExportDeclaration(statement)) {
|
|---|
| 1319 | if (statement.moduleSpecifier !== undefined && this._options & 4 /* ExportFrom */)
|
|---|
| 1320 | this._result.push(statement);
|
|---|
| 1321 | }
|
|---|
| 1322 | else if (node_1.isModuleDeclaration(statement)) {
|
|---|
| 1323 | this._findImportsInModule(statement);
|
|---|
| 1324 | }
|
|---|
| 1325 | }
|
|---|
| 1326 | }
|
|---|
| 1327 | _findImportsInModule(declaration) {
|
|---|
| 1328 | if (declaration.body === undefined)
|
|---|
| 1329 | return;
|
|---|
| 1330 | if (declaration.body.kind === ts.SyntaxKind.ModuleDeclaration)
|
|---|
| 1331 | return this._findImportsInModule(declaration.body);
|
|---|
| 1332 | this._findImports(declaration.body.statements);
|
|---|
| 1333 | }
|
|---|
| 1334 | _findNestedImports() {
|
|---|
| 1335 | const isJavaScriptFile = this._ignoreFileName || (this._sourceFile.flags & ts.NodeFlags.JavaScriptFile) !== 0;
|
|---|
| 1336 | let re;
|
|---|
| 1337 | let includeJsDoc;
|
|---|
| 1338 | if ((this._options & 56 /* AllNestedImports */) === 16 /* Require */) {
|
|---|
| 1339 | if (!isJavaScriptFile)
|
|---|
| 1340 | return; // don't look for 'require' in TS files
|
|---|
| 1341 | re = /\brequire\s*[</(]/g;
|
|---|
| 1342 | includeJsDoc = false;
|
|---|
| 1343 | }
|
|---|
| 1344 | else if (this._options & 16 /* Require */ && isJavaScriptFile) {
|
|---|
| 1345 | re = /\b(?:import|require)\s*[</(]/g;
|
|---|
| 1346 | includeJsDoc = (this._options & 32 /* ImportType */) !== 0;
|
|---|
| 1347 | }
|
|---|
| 1348 | else {
|
|---|
| 1349 | re = /\bimport\s*[</(]/g;
|
|---|
| 1350 | includeJsDoc = isJavaScriptFile && (this._options & 32 /* ImportType */) !== 0;
|
|---|
| 1351 | }
|
|---|
| 1352 | for (let match = re.exec(this._sourceFile.text); match !== null; match = re.exec(this._sourceFile.text)) {
|
|---|
| 1353 | const token = getTokenAtPositionWorker(this._sourceFile, match.index, this._sourceFile,
|
|---|
| 1354 | // only look for ImportTypeNode within JSDoc in JS files
|
|---|
| 1355 | match[0][0] === 'i' && includeJsDoc);
|
|---|
| 1356 | if (token.kind === ts.SyntaxKind.ImportKeyword) {
|
|---|
| 1357 | if (token.end - 'import'.length !== match.index)
|
|---|
| 1358 | continue;
|
|---|
| 1359 | switch (token.parent.kind) {
|
|---|
| 1360 | case ts.SyntaxKind.ImportType:
|
|---|
| 1361 | this._result.push(token.parent);
|
|---|
| 1362 | break;
|
|---|
| 1363 | case ts.SyntaxKind.CallExpression:
|
|---|
| 1364 | if (token.parent.arguments.length > 1)
|
|---|
| 1365 | this._result.push(token.parent);
|
|---|
| 1366 | }
|
|---|
| 1367 | }
|
|---|
| 1368 | else if (token.kind === ts.SyntaxKind.Identifier &&
|
|---|
| 1369 | token.end - 'require'.length === match.index &&
|
|---|
| 1370 | token.parent.kind === ts.SyntaxKind.CallExpression &&
|
|---|
| 1371 | token.parent.expression === token &&
|
|---|
| 1372 | token.parent.arguments.length === 1) {
|
|---|
| 1373 | this._result.push(token.parent);
|
|---|
| 1374 | }
|
|---|
| 1375 | }
|
|---|
| 1376 | }
|
|---|
| 1377 | }
|
|---|
| 1378 | /**
|
|---|
| 1379 | * Ambient context means the statement itself has the `declare` keyword
|
|---|
| 1380 | * or is inside a `declare namespace`, `delcare module` or `declare global`.
|
|---|
| 1381 | */
|
|---|
| 1382 | function isStatementInAmbientContext(node) {
|
|---|
| 1383 | while (node.flags & ts.NodeFlags.NestedNamespace)
|
|---|
| 1384 | node = node.parent;
|
|---|
| 1385 | return hasModifier(node.modifiers, ts.SyntaxKind.DeclareKeyword) || isAmbientModuleBlock(node.parent);
|
|---|
| 1386 | }
|
|---|
| 1387 | exports.isStatementInAmbientContext = isStatementInAmbientContext;
|
|---|
| 1388 | /** Includes `declare namespace`, `declare module` and `declare global` and namespace nested in one of the aforementioned. */
|
|---|
| 1389 | function isAmbientModuleBlock(node) {
|
|---|
| 1390 | while (node.kind === ts.SyntaxKind.ModuleBlock) {
|
|---|
| 1391 | do
|
|---|
| 1392 | node = node.parent;
|
|---|
| 1393 | while (node.flags & ts.NodeFlags.NestedNamespace);
|
|---|
| 1394 | if (hasModifier(node.modifiers, ts.SyntaxKind.DeclareKeyword))
|
|---|
| 1395 | return true;
|
|---|
| 1396 | node = node.parent;
|
|---|
| 1397 | }
|
|---|
| 1398 | return false;
|
|---|
| 1399 | }
|
|---|
| 1400 | exports.isAmbientModuleBlock = isAmbientModuleBlock;
|
|---|
| 1401 | function getIIFE(func) {
|
|---|
| 1402 | let node = func.parent;
|
|---|
| 1403 | while (node.kind === ts.SyntaxKind.ParenthesizedExpression)
|
|---|
| 1404 | node = node.parent;
|
|---|
| 1405 | return node_1.isCallExpression(node) && func.end <= node.expression.end ? node : undefined;
|
|---|
| 1406 | }
|
|---|
| 1407 | exports.getIIFE = getIIFE;
|
|---|
| 1408 | function isStrictCompilerOptionEnabled(options, option) {
|
|---|
| 1409 | return (options.strict ? options[option] !== false : options[option] === true) &&
|
|---|
| 1410 | (option !== 'strictPropertyInitialization' || isStrictCompilerOptionEnabled(options, 'strictNullChecks'));
|
|---|
| 1411 | }
|
|---|
| 1412 | exports.isStrictCompilerOptionEnabled = isStrictCompilerOptionEnabled;
|
|---|
| 1413 | // https://github.com/ajafff/tslint-consistent-codestyle/issues/85
|
|---|
| 1414 | /**
|
|---|
| 1415 | * Checks if a given compiler option is enabled.
|
|---|
| 1416 | * It handles dependencies of options, e.g. `declaration` is implicitly enabled by `composite` or `strictNullChecks` is enabled by `strict`.
|
|---|
| 1417 | * However, it does not check dependencies that are already checked and reported as errors, e.g. `checkJs` without `allowJs`.
|
|---|
| 1418 | * This function only handles boolean flags.
|
|---|
| 1419 | */
|
|---|
| 1420 | function isCompilerOptionEnabled(options, option) {
|
|---|
| 1421 | switch (option) {
|
|---|
| 1422 | case 'stripInternal':
|
|---|
| 1423 | case 'declarationMap':
|
|---|
| 1424 | case 'emitDeclarationOnly':
|
|---|
| 1425 | return options[option] === true && isCompilerOptionEnabled(options, 'declaration');
|
|---|
| 1426 | case 'declaration':
|
|---|
| 1427 | return options.declaration || isCompilerOptionEnabled(options, 'composite');
|
|---|
| 1428 | case 'incremental':
|
|---|
| 1429 | return options.incremental === undefined ? isCompilerOptionEnabled(options, 'composite') : options.incremental;
|
|---|
| 1430 | case 'skipDefaultLibCheck':
|
|---|
| 1431 | return options.skipDefaultLibCheck || isCompilerOptionEnabled(options, 'skipLibCheck');
|
|---|
| 1432 | case 'suppressImplicitAnyIndexErrors':
|
|---|
| 1433 | return options.suppressImplicitAnyIndexErrors === true && isCompilerOptionEnabled(options, 'noImplicitAny');
|
|---|
| 1434 | case 'allowSyntheticDefaultImports':
|
|---|
| 1435 | return options.allowSyntheticDefaultImports !== undefined
|
|---|
| 1436 | ? options.allowSyntheticDefaultImports
|
|---|
| 1437 | : isCompilerOptionEnabled(options, 'esModuleInterop') || options.module === ts.ModuleKind.System;
|
|---|
| 1438 | case 'noUncheckedIndexedAccess':
|
|---|
| 1439 | return options.noUncheckedIndexedAccess === true && isCompilerOptionEnabled(options, 'strictNullChecks');
|
|---|
| 1440 | case 'allowJs':
|
|---|
| 1441 | return options.allowJs === undefined ? isCompilerOptionEnabled(options, 'checkJs') : options.allowJs;
|
|---|
| 1442 | case 'noImplicitAny':
|
|---|
| 1443 | case 'noImplicitThis':
|
|---|
| 1444 | case 'strictNullChecks':
|
|---|
| 1445 | case 'strictFunctionTypes':
|
|---|
| 1446 | case 'strictPropertyInitialization':
|
|---|
| 1447 | case 'alwaysStrict':
|
|---|
| 1448 | case 'strictBindCallApply':
|
|---|
| 1449 | return isStrictCompilerOptionEnabled(options, option);
|
|---|
| 1450 | }
|
|---|
| 1451 | return options[option] === true;
|
|---|
| 1452 | }
|
|---|
| 1453 | exports.isCompilerOptionEnabled = isCompilerOptionEnabled;
|
|---|
| 1454 | /**
|
|---|
| 1455 | * Has nothing to do with `isAmbientModuleBlock`.
|
|---|
| 1456 | *
|
|---|
| 1457 | * @returns `true` if it's a global augmentation or has a string name.
|
|---|
| 1458 | */
|
|---|
| 1459 | function isAmbientModule(node) {
|
|---|
| 1460 | return node.name.kind === ts.SyntaxKind.StringLiteral || (node.flags & ts.NodeFlags.GlobalAugmentation) !== 0;
|
|---|
| 1461 | }
|
|---|
| 1462 | exports.isAmbientModule = isAmbientModule;
|
|---|
| 1463 | /**
|
|---|
| 1464 | * @deprecated use `getTsCheckDirective` instead since `// @ts-nocheck` is no longer restricted to JS files.
|
|---|
| 1465 | * @returns the last `// @ts-check` or `// @ts-nocheck` directive in the given file.
|
|---|
| 1466 | */
|
|---|
| 1467 | function getCheckJsDirective(source) {
|
|---|
| 1468 | return getTsCheckDirective(source);
|
|---|
| 1469 | }
|
|---|
| 1470 | exports.getCheckJsDirective = getCheckJsDirective;
|
|---|
| 1471 | /** @returns the last `// @ts-check` or `// @ts-nocheck` directive in the given file. */
|
|---|
| 1472 | function getTsCheckDirective(source) {
|
|---|
| 1473 | let directive;
|
|---|
| 1474 | // needs to work around a shebang issue until https://github.com/Microsoft/TypeScript/issues/28477 is resolved
|
|---|
| 1475 | ts.forEachLeadingCommentRange(source, (ts.getShebang(source) || '').length, (pos, end, kind) => {
|
|---|
| 1476 | if (kind === ts.SyntaxKind.SingleLineCommentTrivia) {
|
|---|
| 1477 | const text = source.slice(pos, end);
|
|---|
| 1478 | const match = /^\/{2,3}\s*@ts-(no)?check(?:\s|$)/i.exec(text);
|
|---|
| 1479 | if (match !== null)
|
|---|
| 1480 | directive = { pos, end, enabled: match[1] === undefined };
|
|---|
| 1481 | }
|
|---|
| 1482 | });
|
|---|
| 1483 | return directive;
|
|---|
| 1484 | }
|
|---|
| 1485 | exports.getTsCheckDirective = getTsCheckDirective;
|
|---|
| 1486 | function isConstAssertion(node) {
|
|---|
| 1487 | return node_1.isTypeReferenceNode(node.type) &&
|
|---|
| 1488 | node.type.typeName.kind === ts.SyntaxKind.Identifier &&
|
|---|
| 1489 | node.type.typeName.escapedText === 'const';
|
|---|
| 1490 | }
|
|---|
| 1491 | exports.isConstAssertion = isConstAssertion;
|
|---|
| 1492 | /** Detects whether an expression is affected by an enclosing 'as const' assertion and therefore treated literally. */
|
|---|
| 1493 | function isInConstContext(node) {
|
|---|
| 1494 | let current = node;
|
|---|
| 1495 | while (true) {
|
|---|
| 1496 | const parent = current.parent;
|
|---|
| 1497 | outer: switch (parent.kind) {
|
|---|
| 1498 | case ts.SyntaxKind.TypeAssertionExpression:
|
|---|
| 1499 | case ts.SyntaxKind.AsExpression:
|
|---|
| 1500 | return isConstAssertion(parent);
|
|---|
| 1501 | case ts.SyntaxKind.PrefixUnaryExpression:
|
|---|
| 1502 | if (current.kind !== ts.SyntaxKind.NumericLiteral)
|
|---|
| 1503 | return false;
|
|---|
| 1504 | switch (parent.operator) {
|
|---|
| 1505 | case ts.SyntaxKind.PlusToken:
|
|---|
| 1506 | case ts.SyntaxKind.MinusToken:
|
|---|
| 1507 | current = parent;
|
|---|
| 1508 | break outer;
|
|---|
| 1509 | default:
|
|---|
| 1510 | return false;
|
|---|
| 1511 | }
|
|---|
| 1512 | case ts.SyntaxKind.PropertyAssignment:
|
|---|
| 1513 | if (parent.initializer !== current)
|
|---|
| 1514 | return false;
|
|---|
| 1515 | current = parent.parent;
|
|---|
| 1516 | break;
|
|---|
| 1517 | case ts.SyntaxKind.ShorthandPropertyAssignment:
|
|---|
| 1518 | current = parent.parent;
|
|---|
| 1519 | break;
|
|---|
| 1520 | case ts.SyntaxKind.ParenthesizedExpression:
|
|---|
| 1521 | case ts.SyntaxKind.ArrayLiteralExpression:
|
|---|
| 1522 | case ts.SyntaxKind.ObjectLiteralExpression:
|
|---|
| 1523 | case ts.SyntaxKind.TemplateExpression:
|
|---|
| 1524 | current = parent;
|
|---|
| 1525 | break;
|
|---|
| 1526 | default:
|
|---|
| 1527 | return false;
|
|---|
| 1528 | }
|
|---|
| 1529 | }
|
|---|
| 1530 | }
|
|---|
| 1531 | exports.isInConstContext = isInConstContext;
|
|---|
| 1532 | /** Returns true for `Object.defineProperty(o, 'prop', {value, writable: false})` and `Object.defineProperty(o, 'prop', {get: () => 1})`*/
|
|---|
| 1533 | function isReadonlyAssignmentDeclaration(node, checker) {
|
|---|
| 1534 | if (!isBindableObjectDefinePropertyCall(node))
|
|---|
| 1535 | return false;
|
|---|
| 1536 | const descriptorType = checker.getTypeAtLocation(node.arguments[2]);
|
|---|
| 1537 | if (descriptorType.getProperty('value') === undefined)
|
|---|
| 1538 | return descriptorType.getProperty('set') === undefined;
|
|---|
| 1539 | const writableProp = descriptorType.getProperty('writable');
|
|---|
| 1540 | if (writableProp === undefined)
|
|---|
| 1541 | return false;
|
|---|
| 1542 | const writableType = writableProp.valueDeclaration !== undefined && node_1.isPropertyAssignment(writableProp.valueDeclaration)
|
|---|
| 1543 | ? checker.getTypeAtLocation(writableProp.valueDeclaration.initializer)
|
|---|
| 1544 | : checker.getTypeOfSymbolAtLocation(writableProp, node.arguments[2]);
|
|---|
| 1545 | return type_1.isBooleanLiteralType(writableType, false);
|
|---|
| 1546 | }
|
|---|
| 1547 | exports.isReadonlyAssignmentDeclaration = isReadonlyAssignmentDeclaration;
|
|---|
| 1548 | /** Determines whether a call to `Object.defineProperty` is statically analyzable. */
|
|---|
| 1549 | function isBindableObjectDefinePropertyCall(node) {
|
|---|
| 1550 | return node.arguments.length === 3 &&
|
|---|
| 1551 | node_1.isEntityNameExpression(node.arguments[0]) &&
|
|---|
| 1552 | node_1.isNumericOrStringLikeLiteral(node.arguments[1]) &&
|
|---|
| 1553 | node_1.isPropertyAccessExpression(node.expression) &&
|
|---|
| 1554 | node.expression.name.escapedText === 'defineProperty' &&
|
|---|
| 1555 | node_1.isIdentifier(node.expression.expression) &&
|
|---|
| 1556 | node.expression.expression.escapedText === 'Object';
|
|---|
| 1557 | }
|
|---|
| 1558 | exports.isBindableObjectDefinePropertyCall = isBindableObjectDefinePropertyCall;
|
|---|
| 1559 | function isWellKnownSymbolLiterally(node) {
|
|---|
| 1560 | return ts.isPropertyAccessExpression(node) &&
|
|---|
| 1561 | ts.isIdentifier(node.expression) &&
|
|---|
| 1562 | node.expression.escapedText === 'Symbol';
|
|---|
| 1563 | }
|
|---|
| 1564 | exports.isWellKnownSymbolLiterally = isWellKnownSymbolLiterally;
|
|---|
| 1565 | /** @deprecated typescript 4.3 removed the concept of literal well known symbols. Use `getPropertyNameFromType` instead. */
|
|---|
| 1566 | function getPropertyNameOfWellKnownSymbol(node) {
|
|---|
| 1567 | return {
|
|---|
| 1568 | displayName: `[Symbol.${node.name.text}]`,
|
|---|
| 1569 | symbolName: ('__@' + node.name.text),
|
|---|
| 1570 | };
|
|---|
| 1571 | }
|
|---|
| 1572 | exports.getPropertyNameOfWellKnownSymbol = getPropertyNameOfWellKnownSymbol;
|
|---|
| 1573 | const isTsBefore43 = (([major, minor]) => major < '4' || major === '4' && minor < '3')(ts.versionMajorMinor.split('.'));
|
|---|
| 1574 | function getLateBoundPropertyNames(node, checker) {
|
|---|
| 1575 | const result = {
|
|---|
| 1576 | known: true,
|
|---|
| 1577 | names: [],
|
|---|
| 1578 | };
|
|---|
| 1579 | node = unwrapParentheses(node);
|
|---|
| 1580 | if (isTsBefore43 && isWellKnownSymbolLiterally(node)) {
|
|---|
| 1581 | result.names.push(getPropertyNameOfWellKnownSymbol(node)); // wotan-disable-line no-unstable-api-use
|
|---|
| 1582 | }
|
|---|
| 1583 | else {
|
|---|
| 1584 | const type = checker.getTypeAtLocation(node);
|
|---|
| 1585 | for (const key of type_1.unionTypeParts(checker.getBaseConstraintOfType(type) || type)) {
|
|---|
| 1586 | const propertyName = type_1.getPropertyNameFromType(key);
|
|---|
| 1587 | if (propertyName) {
|
|---|
| 1588 | result.names.push(propertyName);
|
|---|
| 1589 | }
|
|---|
| 1590 | else {
|
|---|
| 1591 | result.known = false;
|
|---|
| 1592 | }
|
|---|
| 1593 | }
|
|---|
| 1594 | }
|
|---|
| 1595 | return result;
|
|---|
| 1596 | }
|
|---|
| 1597 | exports.getLateBoundPropertyNames = getLateBoundPropertyNames;
|
|---|
| 1598 | function getLateBoundPropertyNamesOfPropertyName(node, checker) {
|
|---|
| 1599 | const staticName = getPropertyName(node);
|
|---|
| 1600 | return staticName !== undefined
|
|---|
| 1601 | ? { known: true, names: [{ displayName: staticName, symbolName: ts.escapeLeadingUnderscores(staticName) }] }
|
|---|
| 1602 | : node.kind === ts.SyntaxKind.PrivateIdentifier
|
|---|
| 1603 | ? { known: true, names: [{ displayName: node.text, symbolName: checker.getSymbolAtLocation(node).escapedName }] }
|
|---|
| 1604 | : getLateBoundPropertyNames(node.expression, checker);
|
|---|
| 1605 | }
|
|---|
| 1606 | exports.getLateBoundPropertyNamesOfPropertyName = getLateBoundPropertyNamesOfPropertyName;
|
|---|
| 1607 | /** Most declarations demand there to be only one statically known name, e.g. class members with computed name. */
|
|---|
| 1608 | function getSingleLateBoundPropertyNameOfPropertyName(node, checker) {
|
|---|
| 1609 | const staticName = getPropertyName(node);
|
|---|
| 1610 | if (staticName !== undefined)
|
|---|
| 1611 | return { displayName: staticName, symbolName: ts.escapeLeadingUnderscores(staticName) };
|
|---|
| 1612 | if (node.kind === ts.SyntaxKind.PrivateIdentifier)
|
|---|
| 1613 | return { displayName: node.text, symbolName: checker.getSymbolAtLocation(node).escapedName };
|
|---|
| 1614 | const { expression } = node;
|
|---|
| 1615 | return isTsBefore43 && isWellKnownSymbolLiterally(expression)
|
|---|
| 1616 | ? getPropertyNameOfWellKnownSymbol(expression) // wotan-disable-line no-unstable-api-use
|
|---|
| 1617 | : type_1.getPropertyNameFromType(checker.getTypeAtLocation(expression));
|
|---|
| 1618 | }
|
|---|
| 1619 | exports.getSingleLateBoundPropertyNameOfPropertyName = getSingleLateBoundPropertyNameOfPropertyName;
|
|---|
| 1620 | function unwrapParentheses(node) {
|
|---|
| 1621 | while (node.kind === ts.SyntaxKind.ParenthesizedExpression)
|
|---|
| 1622 | node = node.expression;
|
|---|
| 1623 | return node;
|
|---|
| 1624 | }
|
|---|
| 1625 | exports.unwrapParentheses = unwrapParentheses;
|
|---|
| 1626 | function formatPseudoBigInt(v) {
|
|---|
| 1627 | return `${v.negative ? '-' : ''}${v.base10Value}n`;
|
|---|
| 1628 | }
|
|---|
| 1629 | exports.formatPseudoBigInt = formatPseudoBigInt;
|
|---|
| 1630 | /**
|
|---|
| 1631 | * Determines whether the given `SwitchStatement`'s `case` clauses cover every possible value of the switched expression.
|
|---|
| 1632 | * The logic is the same as TypeScript's control flow analysis.
|
|---|
| 1633 | * This does **not** check whether all `case` clauses do a certain action like assign a variable or return a value.
|
|---|
| 1634 | * This function ignores the `default` clause if present.
|
|---|
| 1635 | */
|
|---|
| 1636 | function hasExhaustiveCaseClauses(node, checker) {
|
|---|
| 1637 | const caseClauses = node.caseBlock.clauses.filter(node_1.isCaseClause);
|
|---|
| 1638 | if (caseClauses.length === 0)
|
|---|
| 1639 | return false;
|
|---|
| 1640 | const typeParts = type_1.unionTypeParts(checker.getTypeAtLocation(node.expression));
|
|---|
| 1641 | if (typeParts.length > caseClauses.length)
|
|---|
| 1642 | return false;
|
|---|
| 1643 | const types = new Set(typeParts.map(getPrimitiveLiteralFromType));
|
|---|
| 1644 | if (types.has(undefined))
|
|---|
| 1645 | return false;
|
|---|
| 1646 | const seen = new Set();
|
|---|
| 1647 | for (const clause of caseClauses) {
|
|---|
| 1648 | const expressionType = checker.getTypeAtLocation(clause.expression);
|
|---|
| 1649 | if (exports.isTypeFlagSet(expressionType, ts.TypeFlags.Never))
|
|---|
| 1650 | continue; // additional case clause with 'never' is always allowed
|
|---|
| 1651 | const type = getPrimitiveLiteralFromType(expressionType);
|
|---|
| 1652 | if (types.has(type)) {
|
|---|
| 1653 | seen.add(type);
|
|---|
| 1654 | }
|
|---|
| 1655 | else if (type !== 'null' && type !== 'undefined') { // additional case clauses with 'null' and 'undefined' are always allowed
|
|---|
| 1656 | return false;
|
|---|
| 1657 | }
|
|---|
| 1658 | }
|
|---|
| 1659 | return types.size === seen.size;
|
|---|
| 1660 | }
|
|---|
| 1661 | exports.hasExhaustiveCaseClauses = hasExhaustiveCaseClauses;
|
|---|
| 1662 | function getPrimitiveLiteralFromType(t) {
|
|---|
| 1663 | if (exports.isTypeFlagSet(t, ts.TypeFlags.Null))
|
|---|
| 1664 | return 'null';
|
|---|
| 1665 | if (exports.isTypeFlagSet(t, ts.TypeFlags.Undefined))
|
|---|
| 1666 | return 'undefined';
|
|---|
| 1667 | if (exports.isTypeFlagSet(t, ts.TypeFlags.NumberLiteral))
|
|---|
| 1668 | return `${exports.isTypeFlagSet(t, ts.TypeFlags.EnumLiteral) ? 'enum:' : ''}${t.value}`;
|
|---|
| 1669 | if (exports.isTypeFlagSet(t, ts.TypeFlags.StringLiteral))
|
|---|
| 1670 | return `${exports.isTypeFlagSet(t, ts.TypeFlags.EnumLiteral) ? 'enum:' : ''}string:${t.value}`;
|
|---|
| 1671 | if (exports.isTypeFlagSet(t, ts.TypeFlags.BigIntLiteral))
|
|---|
| 1672 | return formatPseudoBigInt(t.value);
|
|---|
| 1673 | if (_3_2_1.isUniqueESSymbolType(t))
|
|---|
| 1674 | return t.escapedName;
|
|---|
| 1675 | if (type_1.isBooleanLiteralType(t, true))
|
|---|
| 1676 | return 'true';
|
|---|
| 1677 | if (type_1.isBooleanLiteralType(t, false))
|
|---|
| 1678 | return 'false';
|
|---|
| 1679 | }
|
|---|
| 1680 | function getBaseOfClassLikeExpression(node) {
|
|---|
| 1681 | var _a;
|
|---|
| 1682 | if (((_a = node.heritageClauses) === null || _a === void 0 ? void 0 : _a[0].token) === ts.SyntaxKind.ExtendsKeyword)
|
|---|
| 1683 | return node.heritageClauses[0].types[0];
|
|---|
| 1684 | }
|
|---|
| 1685 | exports.getBaseOfClassLikeExpression = getBaseOfClassLikeExpression;
|
|---|
| 1686 | //# sourceMappingURL=util.js.map |
|---|