source: frontend/node_modules/tsutils/util/util.js

Last change on this file was 9af201e, checked in by MBK <marija.karapandzova@…>, 11 days ago

Fix frontend appearance

  • Property mode set to 100644
File size: 75.6 KB
Line 
1"use strict";
2Object.defineProperty(exports, "__esModule", { value: true });
3exports.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;
4exports.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;
5const ts = require("typescript");
6const node_1 = require("../typeguard/node");
7const _3_2_1 = require("../typeguard/3.2");
8const type_1 = require("./type");
9function getChildOfKind(node, kind, sourceFile) {
10 for (const child of node.getChildren(sourceFile))
11 if (child.kind === kind)
12 return child;
13}
14exports.getChildOfKind = getChildOfKind;
15function isTokenKind(kind) {
16 return kind >= ts.SyntaxKind.FirstToken && kind <= ts.SyntaxKind.LastToken;
17}
18exports.isTokenKind = isTokenKind;
19function isNodeKind(kind) {
20 return kind >= ts.SyntaxKind.FirstNode;
21}
22exports.isNodeKind = isNodeKind;
23function isAssignmentKind(kind) {
24 return kind >= ts.SyntaxKind.FirstAssignment && kind <= ts.SyntaxKind.LastAssignment;
25}
26exports.isAssignmentKind = isAssignmentKind;
27function isTypeNodeKind(kind) {
28 return kind >= ts.SyntaxKind.FirstTypeNode && kind <= ts.SyntaxKind.LastTypeNode;
29}
30exports.isTypeNodeKind = isTypeNodeKind;
31function isJsDocKind(kind) {
32 return kind >= ts.SyntaxKind.FirstJSDocNode && kind <= ts.SyntaxKind.LastJSDocNode;
33}
34exports.isJsDocKind = isJsDocKind;
35function isKeywordKind(kind) {
36 return kind >= ts.SyntaxKind.FirstKeyword && kind <= ts.SyntaxKind.LastKeyword;
37}
38exports.isKeywordKind = isKeywordKind;
39function isThisParameter(parameter) {
40 return parameter.name.kind === ts.SyntaxKind.Identifier && parameter.name.originalKeywordKind === ts.SyntaxKind.ThisKeyword;
41}
42exports.isThisParameter = isThisParameter;
43function getModifier(node, kind) {
44 if (node.modifiers !== undefined)
45 for (const modifier of node.modifiers)
46 if (modifier.kind === kind)
47 return modifier;
48}
49exports.getModifier = getModifier;
50function 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}
58exports.hasModifier = hasModifier;
59function isParameterProperty(node) {
60 return hasModifier(node.modifiers, ts.SyntaxKind.PublicKeyword, ts.SyntaxKind.ProtectedKeyword, ts.SyntaxKind.PrivateKeyword, ts.SyntaxKind.ReadonlyKeyword);
61}
62exports.isParameterProperty = isParameterProperty;
63function hasAccessModifier(node) {
64 return isModifierFlagSet(node, ts.ModifierFlags.AccessibilityModifier);
65}
66exports.hasAccessModifier = hasAccessModifier;
67function isFlagSet(obj, flag) {
68 return (obj.flags & flag) !== 0;
69}
70exports.isNodeFlagSet = isFlagSet;
71exports.isTypeFlagSet = isFlagSet;
72exports.isSymbolFlagSet = isFlagSet;
73function isObjectFlagSet(objectType, flag) {
74 return (objectType.objectFlags & flag) !== 0;
75}
76exports.isObjectFlagSet = isObjectFlagSet;
77function isModifierFlagSet(node, flag) {
78 return (ts.getCombinedModifierFlags(node) & flag) !== 0;
79}
80exports.isModifierFlagSet = isModifierFlagSet;
81function 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}
89exports.getPreviousStatement = getPreviousStatement;
90function 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}
98exports.getNextStatement = getNextStatement;
99/** Returns the token before the start of `node` or `undefined` if there is none. */
100function 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}
109exports.getPreviousToken = getPreviousToken;
110/** Returns the next token that begins after the end of `node`. Returns `undefined` for SourceFile and EndOfFileToken */
111function 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}
123exports.getNextToken = getNextToken;
124/** Returns the token at or following the specified position or undefined if none is found inside `parent`. */
125function 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}
132exports.getTokenAtPosition = getTokenAtPosition;
133function 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*/
158function 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}
168exports.getCommentAtPosition = getCommentAtPosition;
169function 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 */
177function isPositionInComment(sourceFile, pos, parent) {
178 return getCommentAtPosition(sourceFile, pos, parent) !== undefined;
179}
180exports.isPositionInComment = isPositionInComment;
181function commentText(sourceText, comment) {
182 return sourceText.substring(comment.pos + 2, comment.kind === ts.SyntaxKind.SingleLineCommentTrivia ? comment.end : comment.end - 2);
183}
184exports.commentText = commentText;
185/** Returns the deepest AST Node at `pos`. Returns undefined if `pos` is outside of the range of `node` */
186function 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}
197exports.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 */
202function 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}
217exports.getWrappedNodeAtPosition = getWrappedNodeAtPosition;
218function 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}
246exports.getPropertyName = getPropertyName;
247function 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}
262exports.forEachDestructuringIdentifier = forEachDestructuringIdentifier;
263function 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}
276exports.forEachDeclaredVariable = forEachDeclaredVariable;
277var 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 = {}));
283function 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}
290exports.getVariableDeclarationKind = getVariableDeclarationKind;
291function isBlockScopedVariableDeclarationList(declarationList) {
292 return (declarationList.flags & ts.NodeFlags.BlockScoped) !== 0;
293}
294exports.isBlockScopedVariableDeclarationList = isBlockScopedVariableDeclarationList;
295function isBlockScopedVariableDeclaration(declaration) {
296 const parent = declaration.parent;
297 return parent.kind === ts.SyntaxKind.CatchClause ||
298 isBlockScopedVariableDeclarationList(parent);
299}
300exports.isBlockScopedVariableDeclaration = isBlockScopedVariableDeclaration;
301function 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}
314exports.isBlockScopedDeclarationStatement = isBlockScopedDeclarationStatement;
315function 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}
330exports.isInSingleStatementContext = isInSingleStatementContext;
331var 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 = {}));
339var 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 = {}));
346function isScopeBoundary(node) {
347 return isFunctionScopeBoundary(node) || isBlockScopeBoundary(node) || isTypeScopeBoundary(node);
348}
349exports.isScopeBoundary = isScopeBoundary;
350function 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}
362exports.isTypeScopeBoundary = isTypeScopeBoundary;
363function 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}
389exports.isFunctionScopeBoundary = isFunctionScopeBoundary;
390function 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}
413exports.isBlockScopeBoundary = isBlockScopeBoundary;
414/** Returns true for scope boundaries that have their own `this` reference instead of inheriting it from the containing scope */
415function 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}
431exports.hasOwnThisReference = hasOwnThisReference;
432function 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}
447exports.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 */
454function 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}
474exports.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 */
483function 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}
505exports.forEachTokenWithTrivia = forEachTokenWithTrivia;
506/** Iterate over all comments owned by `node` or its children */
507function 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}
529exports.forEachComment = forEachComment;
530/** Exclude trailing positions that would lead to scanning for trivia inside JsxText */
531function 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}
554function isJsxElementOrFragment(node) {
555 return node.kind === ts.SyntaxKind.JsxElement || node.kind === ts.SyntaxKind.JsxFragment;
556}
557function 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}
583exports.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. */
585function 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}
591exports.getLineBreakStyle = getLineBreakStyle;
592let cachedScanner;
593function 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 */
610function isValidIdentifier(text, languageVersion = ts.ScriptTarget.Latest) {
611 const scan = scanToken(text, languageVersion);
612 return scan.isIdentifier() && scan.getTextPos() === text.length && scan.getTokenPos() === 0;
613}
614exports.isValidIdentifier = isValidIdentifier;
615function 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 */
621function 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}
634exports.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 */
638function 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}
645exports.isValidPropertyName = isValidPropertyName;
646/**
647 * Determines whether the given text can be parsed as a numeric literal.
648 */
649function 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}
653exports.isValidNumericLiteral = isValidNumericLiteral;
654/**
655 * Determines whether the given text can be used as JSX tag or attribute name while preserving the exact name.
656 */
657function 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}
677exports.isValidJsxIdentifier = isValidJsxIdentifier;
678function isNumericPropertyName(name) {
679 return String(+name) === name;
680}
681exports.isNumericPropertyName = isNumericPropertyName;
682function isSameLine(sourceFile, pos1, pos2) {
683 return ts.getLineAndCharacterOfPosition(sourceFile, pos1).line === ts.getLineAndCharacterOfPosition(sourceFile, pos2).line;
684}
685exports.isSameLine = isSameLine;
686var 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 = {}));
693function 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}
836exports.hasSideEffects = hasSideEffects;
837/** Returns the VariableDeclaration or ParameterDeclaration that contains the BindingElement */
838function getDeclarationOfBindingElement(node) {
839 let parent = node.parent.parent;
840 while (parent.kind === ts.SyntaxKind.BindingElement)
841 parent = parent.parent.parent;
842 return parent;
843}
844exports.getDeclarationOfBindingElement = getDeclarationOfBindingElement;
845function 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}
977exports.isExpressionValueUsed = isExpressionValueUsed;
978function 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}
1018var 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 = {}));
1027function 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}
1133exports.getAccessKind = getAccessKind;
1134function isReassignmentTarget(node) {
1135 return (getAccessKind(node) & 2 /* Write */) !== 0;
1136}
1137exports.isReassignmentTarget = isReassignmentTarget;
1138function 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}
1184exports.canHaveJsDoc = canHaveJsDoc;
1185/** Gets the JSDoc of a node. For performance reasons this function should only be called when `canHaveJsDoc` returns true. */
1186function 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}
1195exports.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 */
1202function 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}
1210exports.parseJsDocOfNode = parseJsDocOfNode;
1211function 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}
1238var 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 = {}));
1256function 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}
1286exports.findImports = findImports;
1287function findImportLikeNodes(sourceFile, kinds, ignoreFileName = true) {
1288 return new ImportFinder(sourceFile, kinds, ignoreFileName).find();
1289}
1290exports.findImportLikeNodes = findImportLikeNodes;
1291class 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 */
1382function 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}
1387exports.isStatementInAmbientContext = isStatementInAmbientContext;
1388/** Includes `declare namespace`, `declare module` and `declare global` and namespace nested in one of the aforementioned. */
1389function 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}
1400exports.isAmbientModuleBlock = isAmbientModuleBlock;
1401function 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}
1407exports.getIIFE = getIIFE;
1408function isStrictCompilerOptionEnabled(options, option) {
1409 return (options.strict ? options[option] !== false : options[option] === true) &&
1410 (option !== 'strictPropertyInitialization' || isStrictCompilerOptionEnabled(options, 'strictNullChecks'));
1411}
1412exports.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 */
1420function 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}
1453exports.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 */
1459function isAmbientModule(node) {
1460 return node.name.kind === ts.SyntaxKind.StringLiteral || (node.flags & ts.NodeFlags.GlobalAugmentation) !== 0;
1461}
1462exports.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 */
1467function getCheckJsDirective(source) {
1468 return getTsCheckDirective(source);
1469}
1470exports.getCheckJsDirective = getCheckJsDirective;
1471/** @returns the last `// @ts-check` or `// @ts-nocheck` directive in the given file. */
1472function 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}
1485exports.getTsCheckDirective = getTsCheckDirective;
1486function isConstAssertion(node) {
1487 return node_1.isTypeReferenceNode(node.type) &&
1488 node.type.typeName.kind === ts.SyntaxKind.Identifier &&
1489 node.type.typeName.escapedText === 'const';
1490}
1491exports.isConstAssertion = isConstAssertion;
1492/** Detects whether an expression is affected by an enclosing 'as const' assertion and therefore treated literally. */
1493function 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}
1531exports.isInConstContext = isInConstContext;
1532/** Returns true for `Object.defineProperty(o, 'prop', {value, writable: false})` and `Object.defineProperty(o, 'prop', {get: () => 1})`*/
1533function 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}
1547exports.isReadonlyAssignmentDeclaration = isReadonlyAssignmentDeclaration;
1548/** Determines whether a call to `Object.defineProperty` is statically analyzable. */
1549function 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}
1558exports.isBindableObjectDefinePropertyCall = isBindableObjectDefinePropertyCall;
1559function isWellKnownSymbolLiterally(node) {
1560 return ts.isPropertyAccessExpression(node) &&
1561 ts.isIdentifier(node.expression) &&
1562 node.expression.escapedText === 'Symbol';
1563}
1564exports.isWellKnownSymbolLiterally = isWellKnownSymbolLiterally;
1565/** @deprecated typescript 4.3 removed the concept of literal well known symbols. Use `getPropertyNameFromType` instead. */
1566function getPropertyNameOfWellKnownSymbol(node) {
1567 return {
1568 displayName: `[Symbol.${node.name.text}]`,
1569 symbolName: ('__@' + node.name.text),
1570 };
1571}
1572exports.getPropertyNameOfWellKnownSymbol = getPropertyNameOfWellKnownSymbol;
1573const isTsBefore43 = (([major, minor]) => major < '4' || major === '4' && minor < '3')(ts.versionMajorMinor.split('.'));
1574function 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}
1597exports.getLateBoundPropertyNames = getLateBoundPropertyNames;
1598function 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}
1606exports.getLateBoundPropertyNamesOfPropertyName = getLateBoundPropertyNamesOfPropertyName;
1607/** Most declarations demand there to be only one statically known name, e.g. class members with computed name. */
1608function 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}
1619exports.getSingleLateBoundPropertyNameOfPropertyName = getSingleLateBoundPropertyNameOfPropertyName;
1620function unwrapParentheses(node) {
1621 while (node.kind === ts.SyntaxKind.ParenthesizedExpression)
1622 node = node.expression;
1623 return node;
1624}
1625exports.unwrapParentheses = unwrapParentheses;
1626function formatPseudoBigInt(v) {
1627 return `${v.negative ? '-' : ''}${v.base10Value}n`;
1628}
1629exports.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 */
1636function 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}
1661exports.hasExhaustiveCaseClauses = hasExhaustiveCaseClauses;
1662function 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}
1680function 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}
1685exports.getBaseOfClassLikeExpression = getBaseOfClassLikeExpression;
1686//# sourceMappingURL=util.js.map
Note: See TracBrowser for help on using the repository browser.