react-carousel-query
Version:
A infinite carousel component made with react that handles the pagination for you.
1,067 lines (1,066 loc) • 79.1 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
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;
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;
const ts = require("typescript");
const node_1 = require("../typeguard/node");
const _3_2_1 = require("../typeguard/3.2");
const type_1 = require("./type");
function getChildOfKind(node, kind, sourceFile) {
for (const child of node.getChildren(sourceFile))
if (child.kind === kind)
return child;
}
exports.getChildOfKind = getChildOfKind;
function isTokenKind(kind) {
return kind >= ts.SyntaxKind.FirstToken && kind <= ts.SyntaxKind.LastToken;
}
exports.isTokenKind = isTokenKind;
function isNodeKind(kind) {
return kind >= ts.SyntaxKind.FirstNode;
}
exports.isNodeKind = isNodeKind;
function isAssignmentKind(kind) {
return kind >= ts.SyntaxKind.FirstAssignment && kind <= ts.SyntaxKind.LastAssignment;
}
exports.isAssignmentKind = isAssignmentKind;
function isTypeNodeKind(kind) {
return kind >= ts.SyntaxKind.FirstTypeNode && kind <= ts.SyntaxKind.LastTypeNode;
}
exports.isTypeNodeKind = isTypeNodeKind;
function isJsDocKind(kind) {
return kind >= ts.SyntaxKind.FirstJSDocNode && kind <= ts.SyntaxKind.LastJSDocNode;
}
exports.isJsDocKind = isJsDocKind;
function isKeywordKind(kind) {
return kind >= ts.SyntaxKind.FirstKeyword && kind <= ts.SyntaxKind.LastKeyword;
}
exports.isKeywordKind = isKeywordKind;
function isThisParameter(parameter) {
return parameter.name.kind === ts.SyntaxKind.Identifier && parameter.name.originalKeywordKind === ts.SyntaxKind.ThisKeyword;
}
exports.isThisParameter = isThisParameter;
function getModifier(node, kind) {
if (node.modifiers !== undefined)
for (const modifier of node.modifiers)
if (modifier.kind === kind)
return modifier;
}
exports.getModifier = getModifier;
function hasModifier(modifiers, ...kinds) {
if (modifiers === undefined)
return false;
for (const modifier of modifiers)
if (kinds.includes(modifier.kind))
return true;
return false;
}
exports.hasModifier = hasModifier;
function isParameterProperty(node) {
return hasModifier(node.modifiers, ts.SyntaxKind.PublicKeyword, ts.SyntaxKind.ProtectedKeyword, ts.SyntaxKind.PrivateKeyword, ts.SyntaxKind.ReadonlyKeyword);
}
exports.isParameterProperty = isParameterProperty;
function hasAccessModifier(node) {
return isModifierFlagSet(node, ts.ModifierFlags.AccessibilityModifier);
}
exports.hasAccessModifier = hasAccessModifier;
function isFlagSet(obj, flag) {
return (obj.flags & flag) !== 0;
}
exports.isNodeFlagSet = isFlagSet;
exports.isTypeFlagSet = isFlagSet;
exports.isSymbolFlagSet = isFlagSet;
function isObjectFlagSet(objectType, flag) {
return (objectType.objectFlags & flag) !== 0;
}
exports.isObjectFlagSet = isObjectFlagSet;
function isModifierFlagSet(node, flag) {
return (ts.getCombinedModifierFlags(node) & flag) !== 0;
}
exports.isModifierFlagSet = isModifierFlagSet;
function getPreviousStatement(statement) {
const parent = statement.parent;
if (node_1.isBlockLike(parent)) {
const index = parent.statements.indexOf(statement);
if (index > 0)
return parent.statements[index - 1];
}
}
exports.getPreviousStatement = getPreviousStatement;
function getNextStatement(statement) {
const parent = statement.parent;
if (node_1.isBlockLike(parent)) {
const index = parent.statements.indexOf(statement);
if (index < parent.statements.length)
return parent.statements[index + 1];
}
}
exports.getNextStatement = getNextStatement;
/** Returns the token before the start of `node` or `undefined` if there is none. */
function getPreviousToken(node, sourceFile) {
const { pos } = node;
if (pos === 0)
return;
do
node = node.parent;
while (node.pos === pos);
return getTokenAtPositionWorker(node, pos - 1, sourceFile !== null && sourceFile !== void 0 ? sourceFile : node.getSourceFile(), false);
}
exports.getPreviousToken = getPreviousToken;
/** Returns the next token that begins after the end of `node`. Returns `undefined` for SourceFile and EndOfFileToken */
function getNextToken(node, sourceFile) {
if (node.kind === ts.SyntaxKind.SourceFile || node.kind === ts.SyntaxKind.EndOfFileToken)
return;
const end = node.end;
node = node.parent;
while (node.end === end) {
if (node.parent === undefined)
return node.endOfFileToken;
node = node.parent;
}
return getTokenAtPositionWorker(node, end, sourceFile !== null && sourceFile !== void 0 ? sourceFile : node.getSourceFile(), false);
}
exports.getNextToken = getNextToken;
/** Returns the token at or following the specified position or undefined if none is found inside `parent`. */
function getTokenAtPosition(parent, pos, sourceFile, allowJsDoc) {
if (pos < parent.pos || pos >= parent.end)
return;
if (isTokenKind(parent.kind))
return parent;
return getTokenAtPositionWorker(parent, pos, sourceFile !== null && sourceFile !== void 0 ? sourceFile : parent.getSourceFile(), allowJsDoc === true);
}
exports.getTokenAtPosition = getTokenAtPosition;
function getTokenAtPositionWorker(node, pos, sourceFile, allowJsDoc) {
if (!allowJsDoc) {
// if we are not interested in JSDoc, we can skip to the deepest AST node at the given position
node = getAstNodeAtPosition(node, pos);
if (isTokenKind(node.kind))
return node;
}
outer: while (true) {
for (const child of node.getChildren(sourceFile)) {
if (child.end > pos && (allowJsDoc || child.kind !== ts.SyntaxKind.JSDocComment)) {
if (isTokenKind(child.kind))
return child;
// next token is nested in another node
node = child;
continue outer;
}
}
return;
}
}
/**
* Return the comment at the specified position.
* You can pass an optional `parent` to avoid some work finding the corresponding token starting at `sourceFile`.
* If the `parent` parameter is passed, `pos` must be between `parent.pos` and `parent.end`.
*/
function getCommentAtPosition(sourceFile, pos, parent = sourceFile) {
const token = getTokenAtPosition(parent, pos, sourceFile);
if (token === undefined || token.kind === ts.SyntaxKind.JsxText || pos >= token.end - (ts.tokenToString(token.kind) || '').length)
return;
const startPos = token.pos === 0
? (ts.getShebang(sourceFile.text) || '').length
: token.pos;
return startPos !== 0 && ts.forEachTrailingCommentRange(sourceFile.text, startPos, commentAtPositionCallback, pos) ||
ts.forEachLeadingCommentRange(sourceFile.text, startPos, commentAtPositionCallback, pos);
}
exports.getCommentAtPosition = getCommentAtPosition;
function commentAtPositionCallback(pos, end, kind, _nl, at) {
return at >= pos && at < end ? { pos, end, kind } : undefined;
}
/**
* Returns whether the specified position is inside a comment.
* You can pass an optional `parent` to avoid some work finding the corresponding token starting at `sourceFile`.
* If the `parent` parameter is passed, `pos` must be between `parent.pos` and `parent.end`.
*/
function isPositionInComment(sourceFile, pos, parent) {
return getCommentAtPosition(sourceFile, pos, parent) !== undefined;
}
exports.isPositionInComment = isPositionInComment;
function commentText(sourceText, comment) {
return sourceText.substring(comment.pos + 2, comment.kind === ts.SyntaxKind.SingleLineCommentTrivia ? comment.end : comment.end - 2);
}
exports.commentText = commentText;
/** Returns the deepest AST Node at `pos`. Returns undefined if `pos` is outside of the range of `node` */
function getAstNodeAtPosition(node, pos) {
if (node.pos > pos || node.end <= pos)
return;
while (isNodeKind(node.kind)) {
const nested = ts.forEachChild(node, (child) => child.pos <= pos && child.end > pos ? child : undefined);
if (nested === undefined)
break;
node = nested;
}
return node;
}
exports.getAstNodeAtPosition = getAstNodeAtPosition;
/**
* Returns the NodeWrap of deepest AST node that contains `pos` between its `pos` and `end`.
* Only returns undefined if pos is outside of `wrap`
*/
function getWrappedNodeAtPosition(wrap, pos) {
if (wrap.node.pos > pos || wrap.node.end <= pos)
return;
outer: while (true) {
for (const child of wrap.children) {
if (child.node.pos > pos)
return wrap;
if (child.node.end > pos) {
wrap = child;
continue outer;
}
}
return wrap;
}
}
exports.getWrappedNodeAtPosition = getWrappedNodeAtPosition;
function getPropertyName(propertyName) {
if (propertyName.kind === ts.SyntaxKind.ComputedPropertyName) {
const expression = unwrapParentheses(propertyName.expression);
if (node_1.isPrefixUnaryExpression(expression)) {
let negate = false;
switch (expression.operator) {
case ts.SyntaxKind.MinusToken:
negate = true;
// falls through
case ts.SyntaxKind.PlusToken:
return node_1.isNumericLiteral(expression.operand)
? `${negate ? '-' : ''}${expression.operand.text}`
: _3_2_1.isBigIntLiteral(expression.operand)
? `${negate ? '-' : ''}${expression.operand.text.slice(0, -1)}`
: undefined;
default:
return;
}
}
if (_3_2_1.isBigIntLiteral(expression))
// handle BigInt, even though TypeScript doesn't allow BigInt as computed property name
return expression.text.slice(0, -1);
if (node_1.isNumericOrStringLikeLiteral(expression))
return expression.text;
return;
}
return propertyName.kind === ts.SyntaxKind.PrivateIdentifier ? undefined : propertyName.text;
}
exports.getPropertyName = getPropertyName;
function forEachDestructuringIdentifier(pattern, fn) {
for (const element of pattern.elements) {
if (element.kind !== ts.SyntaxKind.BindingElement)
continue;
let result;
if (element.name.kind === ts.SyntaxKind.Identifier) {
result = fn(element);
}
else {
result = forEachDestructuringIdentifier(element.name, fn);
}
if (result)
return result;
}
}
exports.forEachDestructuringIdentifier = forEachDestructuringIdentifier;
function forEachDeclaredVariable(declarationList, cb) {
for (const declaration of declarationList.declarations) {
let result;
if (declaration.name.kind === ts.SyntaxKind.Identifier) {
result = cb(declaration);
}
else {
result = forEachDestructuringIdentifier(declaration.name, cb);
}
if (result)
return result;
}
}
exports.forEachDeclaredVariable = forEachDeclaredVariable;
var VariableDeclarationKind;
(function (VariableDeclarationKind) {
VariableDeclarationKind[VariableDeclarationKind["Var"] = 0] = "Var";
VariableDeclarationKind[VariableDeclarationKind["Let"] = 1] = "Let";
VariableDeclarationKind[VariableDeclarationKind["Const"] = 2] = "Const";
})(VariableDeclarationKind = exports.VariableDeclarationKind || (exports.VariableDeclarationKind = {}));
function getVariableDeclarationKind(declarationList) {
if (declarationList.flags & ts.NodeFlags.Let)
return 1 /* Let */;
if (declarationList.flags & ts.NodeFlags.Const)
return 2 /* Const */;
return 0 /* Var */;
}
exports.getVariableDeclarationKind = getVariableDeclarationKind;
function isBlockScopedVariableDeclarationList(declarationList) {
return (declarationList.flags & ts.NodeFlags.BlockScoped) !== 0;
}
exports.isBlockScopedVariableDeclarationList = isBlockScopedVariableDeclarationList;
function isBlockScopedVariableDeclaration(declaration) {
const parent = declaration.parent;
return parent.kind === ts.SyntaxKind.CatchClause ||
isBlockScopedVariableDeclarationList(parent);
}
exports.isBlockScopedVariableDeclaration = isBlockScopedVariableDeclaration;
function isBlockScopedDeclarationStatement(statement) {
switch (statement.kind) {
case ts.SyntaxKind.VariableStatement:
return isBlockScopedVariableDeclarationList(statement.declarationList);
case ts.SyntaxKind.ClassDeclaration:
case ts.SyntaxKind.EnumDeclaration:
case ts.SyntaxKind.InterfaceDeclaration:
case ts.SyntaxKind.TypeAliasDeclaration:
return true;
default:
return false;
}
}
exports.isBlockScopedDeclarationStatement = isBlockScopedDeclarationStatement;
function isInSingleStatementContext(statement) {
switch (statement.parent.kind) {
case ts.SyntaxKind.ForStatement:
case ts.SyntaxKind.ForInStatement:
case ts.SyntaxKind.ForOfStatement:
case ts.SyntaxKind.WhileStatement:
case ts.SyntaxKind.DoStatement:
case ts.SyntaxKind.IfStatement:
case ts.SyntaxKind.WithStatement:
case ts.SyntaxKind.LabeledStatement:
return true;
default:
return false;
}
}
exports.isInSingleStatementContext = isInSingleStatementContext;
var ScopeBoundary;
(function (ScopeBoundary) {
ScopeBoundary[ScopeBoundary["None"] = 0] = "None";
ScopeBoundary[ScopeBoundary["Function"] = 1] = "Function";
ScopeBoundary[ScopeBoundary["Block"] = 2] = "Block";
ScopeBoundary[ScopeBoundary["Type"] = 4] = "Type";
ScopeBoundary[ScopeBoundary["ConditionalType"] = 8] = "ConditionalType";
})(ScopeBoundary = exports.ScopeBoundary || (exports.ScopeBoundary = {}));
var ScopeBoundarySelector;
(function (ScopeBoundarySelector) {
ScopeBoundarySelector[ScopeBoundarySelector["Function"] = 1] = "Function";
ScopeBoundarySelector[ScopeBoundarySelector["Block"] = 3] = "Block";
ScopeBoundarySelector[ScopeBoundarySelector["Type"] = 7] = "Type";
ScopeBoundarySelector[ScopeBoundarySelector["InferType"] = 8] = "InferType";
})(ScopeBoundarySelector = exports.ScopeBoundarySelector || (exports.ScopeBoundarySelector = {}));
function isScopeBoundary(node) {
return isFunctionScopeBoundary(node) || isBlockScopeBoundary(node) || isTypeScopeBoundary(node);
}
exports.isScopeBoundary = isScopeBoundary;
function isTypeScopeBoundary(node) {
switch (node.kind) {
case ts.SyntaxKind.InterfaceDeclaration:
case ts.SyntaxKind.TypeAliasDeclaration:
case ts.SyntaxKind.MappedType:
return 4 /* Type */;
case ts.SyntaxKind.ConditionalType:
return 8 /* ConditionalType */;
default:
return 0 /* None */;
}
}
exports.isTypeScopeBoundary = isTypeScopeBoundary;
function isFunctionScopeBoundary(node) {
switch (node.kind) {
case ts.SyntaxKind.FunctionExpression:
case ts.SyntaxKind.ArrowFunction:
case ts.SyntaxKind.Constructor:
case ts.SyntaxKind.ModuleDeclaration:
case ts.SyntaxKind.ClassDeclaration:
case ts.SyntaxKind.ClassExpression:
case ts.SyntaxKind.EnumDeclaration:
case ts.SyntaxKind.MethodDeclaration:
case ts.SyntaxKind.FunctionDeclaration:
case ts.SyntaxKind.GetAccessor:
case ts.SyntaxKind.SetAccessor:
case ts.SyntaxKind.MethodSignature:
case ts.SyntaxKind.CallSignature:
case ts.SyntaxKind.ConstructSignature:
case ts.SyntaxKind.ConstructorType:
case ts.SyntaxKind.FunctionType:
return 1 /* Function */;
case ts.SyntaxKind.SourceFile:
// if SourceFile is no module, it contributes to the global scope and is therefore no scope boundary
return ts.isExternalModule(node) ? 1 /* Function */ : 0 /* None */;
default:
return 0 /* None */;
}
}
exports.isFunctionScopeBoundary = isFunctionScopeBoundary;
function isBlockScopeBoundary(node) {
switch (node.kind) {
case ts.SyntaxKind.Block:
const parent = node.parent;
return parent.kind !== ts.SyntaxKind.CatchClause &&
// blocks inside SourceFile are block scope boundaries
(parent.kind === ts.SyntaxKind.SourceFile ||
// blocks that are direct children of a function scope boundary are no scope boundary
// for example the FunctionBlock is part of the function scope of the containing function
!isFunctionScopeBoundary(parent))
? 2 /* Block */
: 0 /* None */;
case ts.SyntaxKind.ForStatement:
case ts.SyntaxKind.ForInStatement:
case ts.SyntaxKind.ForOfStatement:
case ts.SyntaxKind.CaseBlock:
case ts.SyntaxKind.CatchClause:
case ts.SyntaxKind.WithStatement:
return 2 /* Block */;
default:
return 0 /* None */;
}
}
exports.isBlockScopeBoundary = isBlockScopeBoundary;
/** Returns true for scope boundaries that have their own `this` reference instead of inheriting it from the containing scope */
function hasOwnThisReference(node) {
switch (node.kind) {
case ts.SyntaxKind.ClassDeclaration:
case ts.SyntaxKind.ClassExpression:
case ts.SyntaxKind.FunctionExpression:
return true;
case ts.SyntaxKind.FunctionDeclaration:
return node.body !== undefined;
case ts.SyntaxKind.MethodDeclaration:
case ts.SyntaxKind.GetAccessor:
case ts.SyntaxKind.SetAccessor:
return node.parent.kind === ts.SyntaxKind.ObjectLiteralExpression;
default:
return false;
}
}
exports.hasOwnThisReference = hasOwnThisReference;
function isFunctionWithBody(node) {
switch (node.kind) {
case ts.SyntaxKind.GetAccessor:
case ts.SyntaxKind.SetAccessor:
case ts.SyntaxKind.FunctionDeclaration:
case ts.SyntaxKind.MethodDeclaration:
case ts.SyntaxKind.Constructor:
return node.body !== undefined;
case ts.SyntaxKind.FunctionExpression:
case ts.SyntaxKind.ArrowFunction:
return true;
default:
return false;
}
}
exports.isFunctionWithBody = isFunctionWithBody;
/**
* Iterate over all tokens of `node`
*
* @param node The node whose tokens should be visited
* @param cb Is called for every token contained in `node`
*/
function forEachToken(node, cb, sourceFile = node.getSourceFile()) {
const queue = [];
while (true) {
if (isTokenKind(node.kind)) {
cb(node);
}
else if (node.kind !== ts.SyntaxKind.JSDocComment) {
const children = node.getChildren(sourceFile);
if (children.length === 1) {
node = children[0];
continue;
}
for (let i = children.length - 1; i >= 0; --i)
queue.push(children[i]); // add children in reverse order, when we pop the next element from the queue, it's the first child
}
if (queue.length === 0)
break;
node = queue.pop();
}
}
exports.forEachToken = forEachToken;
/**
* Iterate over all tokens and trivia of `node`
*
* @description JsDoc comments are treated like regular comments
*
* @param node The node whose tokens should be visited
* @param cb Is called for every token contained in `node` and trivia before the token
*/
function forEachTokenWithTrivia(node, cb, sourceFile = node.getSourceFile()) {
const fullText = sourceFile.text;
const scanner = ts.createScanner(sourceFile.languageVersion, false, sourceFile.languageVariant, fullText);
return forEachToken(node, (token) => {
const tokenStart = token.kind === ts.SyntaxKind.JsxText || token.pos === token.end ? token.pos : token.getStart(sourceFile);
if (tokenStart !== token.pos) {
// we only have to handle trivia before each token. whitespace at the end of the file is followed by EndOfFileToken
scanner.setTextPos(token.pos);
let kind = scanner.scan();
let pos = scanner.getTokenPos();
while (pos < tokenStart) {
const textPos = scanner.getTextPos();
cb(fullText, kind, { pos, end: textPos }, token.parent);
if (textPos === tokenStart)
break;
kind = scanner.scan();
pos = scanner.getTokenPos();
}
}
return cb(fullText, token.kind, { end: token.end, pos: tokenStart }, token.parent);
}, sourceFile);
}
exports.forEachTokenWithTrivia = forEachTokenWithTrivia;
/** Iterate over all comments owned by `node` or its children */
function forEachComment(node, cb, sourceFile = node.getSourceFile()) {
/* Visit all tokens and skip trivia.
Comment ranges between tokens are parsed without the need of a scanner.
forEachTokenWithWhitespace does intentionally not pay attention to the correct comment ownership of nodes as it always
scans all trivia before each token, which could include trailing comments of the previous token.
Comment onwership is done right in this function*/
const fullText = sourceFile.text;
const notJsx = sourceFile.languageVariant !== ts.LanguageVariant.JSX;
return forEachToken(node, (token) => {
if (token.pos === token.end)
return;
if (token.kind !== ts.SyntaxKind.JsxText)
ts.forEachLeadingCommentRange(fullText,
// skip shebang at position 0
token.pos === 0 ? (ts.getShebang(fullText) || '').length : token.pos, commentCallback);
if (notJsx || canHaveTrailingTrivia(token))
return ts.forEachTrailingCommentRange(fullText, token.end, commentCallback);
}, sourceFile);
function commentCallback(pos, end, kind) {
cb(fullText, { pos, end, kind });
}
}
exports.forEachComment = forEachComment;
/** Exclude trailing positions that would lead to scanning for trivia inside JsxText */
function canHaveTrailingTrivia(token) {
switch (token.kind) {
case ts.SyntaxKind.CloseBraceToken:
// after a JsxExpression inside a JsxElement's body can only be other JsxChild, but no trivia
return token.parent.kind !== ts.SyntaxKind.JsxExpression || !isJsxElementOrFragment(token.parent.parent);
case ts.SyntaxKind.GreaterThanToken:
switch (token.parent.kind) {
case ts.SyntaxKind.JsxOpeningElement:
// if end is not equal, this is part of the type arguments list. in all other cases it would be inside the element body
return token.end !== token.parent.end;
case ts.SyntaxKind.JsxOpeningFragment:
return false; // would be inside the fragment
case ts.SyntaxKind.JsxSelfClosingElement:
return token.end !== token.parent.end || // if end is not equal, this is part of the type arguments list
!isJsxElementOrFragment(token.parent.parent); // there's only trailing trivia if it's the end of the top element
case ts.SyntaxKind.JsxClosingElement:
case ts.SyntaxKind.JsxClosingFragment:
// there's only trailing trivia if it's the end of the top element
return !isJsxElementOrFragment(token.parent.parent.parent);
}
}
return true;
}
function isJsxElementOrFragment(node) {
return node.kind === ts.SyntaxKind.JsxElement || node.kind === ts.SyntaxKind.JsxFragment;
}
function getLineRanges(sourceFile) {
const lineStarts = sourceFile.getLineStarts();
const result = [];
const length = lineStarts.length;
const sourceText = sourceFile.text;
let pos = 0;
for (let i = 1; i < length; ++i) {
const end = lineStarts[i];
let lineEnd = end;
for (; lineEnd > pos; --lineEnd)
if (!ts.isLineBreak(sourceText.charCodeAt(lineEnd - 1)))
break;
result.push({
pos,
end,
contentLength: lineEnd - pos,
});
pos = end;
}
result.push({
pos,
end: sourceFile.end,
contentLength: sourceFile.end - pos,
});
return result;
}
exports.getLineRanges = getLineRanges;
/** Get the line break style used in sourceFile. This function only looks at the first line break. If there is none, \n is assumed. */
function getLineBreakStyle(sourceFile) {
const lineStarts = sourceFile.getLineStarts();
return lineStarts.length === 1 || lineStarts[1] < 2 || sourceFile.text[lineStarts[1] - 2] !== '\r'
? '\n'
: '\r\n';
}
exports.getLineBreakStyle = getLineBreakStyle;
let cachedScanner;
function scanToken(text, languageVersion) {
if (cachedScanner === undefined) {
// cache scanner
cachedScanner = ts.createScanner(languageVersion, false, undefined, text);
}
else {
cachedScanner.setScriptTarget(languageVersion);
cachedScanner.setText(text);
}
cachedScanner.scan();
return cachedScanner;
}
/**
* Determines whether the given text parses as a standalone identifier.
* This is not a guarantee that it works in every context. The property name in PropertyAccessExpressions for example allows reserved words.
* Depending on the context it could be parsed as contextual keyword or TypeScript keyword.
*/
function isValidIdentifier(text, languageVersion = ts.ScriptTarget.Latest) {
const scan = scanToken(text, languageVersion);
return scan.isIdentifier() && scan.getTextPos() === text.length && scan.getTokenPos() === 0;
}
exports.isValidIdentifier = isValidIdentifier;
function charSize(ch) {
return ch >= 0x10000 ? 2 : 1;
}
/**
* Determines whether the given text can be used to access a property with a PropertyAccessExpression while preserving the property's name.
*/
function isValidPropertyAccess(text, languageVersion = ts.ScriptTarget.Latest) {
if (text.length === 0)
return false;
let ch = text.codePointAt(0);
if (!ts.isIdentifierStart(ch, languageVersion))
return false;
for (let i = charSize(ch); i < text.length; i += charSize(ch)) {
ch = text.codePointAt(i);
if (!ts.isIdentifierPart(ch, languageVersion))
return false;
}
return true;
}
exports.isValidPropertyAccess = isValidPropertyAccess;
/**
* Determines whether the given text can be used as unquoted name of a property declaration while preserving the property's name.
*/
function isValidPropertyName(text, languageVersion = ts.ScriptTarget.Latest) {
if (isValidPropertyAccess(text, languageVersion))
return true;
const scan = scanToken(text, languageVersion);
return scan.getTextPos() === text.length &&
scan.getToken() === ts.SyntaxKind.NumericLiteral && scan.getTokenValue() === text; // ensure stringified number equals literal
}
exports.isValidPropertyName = isValidPropertyName;
/**
* Determines whether the given text can be parsed as a numeric literal.
*/
function isValidNumericLiteral(text, languageVersion = ts.ScriptTarget.Latest) {
const scan = scanToken(text, languageVersion);
return scan.getToken() === ts.SyntaxKind.NumericLiteral && scan.getTextPos() === text.length && scan.getTokenPos() === 0;
}
exports.isValidNumericLiteral = isValidNumericLiteral;
/**
* Determines whether the given text can be used as JSX tag or attribute name while preserving the exact name.
*/
function isValidJsxIdentifier(text, languageVersion = ts.ScriptTarget.Latest) {
if (text.length === 0)
return false;
let seenNamespaceSeparator = false;
let ch = text.codePointAt(0);
if (!ts.isIdentifierStart(ch, languageVersion))
return false;
for (let i = charSize(ch); i < text.length; i += charSize(ch)) {
ch = text.codePointAt(i);
if (!ts.isIdentifierPart(ch, languageVersion) && ch !== 45 /* minus */) {
if (!seenNamespaceSeparator && ch === 58 /* colon */ && i + charSize(ch) !== text.length) {
seenNamespaceSeparator = true;
}
else {
return false;
}
}
}
return true;
}
exports.isValidJsxIdentifier = isValidJsxIdentifier;
function isNumericPropertyName(name) {
return String(+name) === name;
}
exports.isNumericPropertyName = isNumericPropertyName;
function isSameLine(sourceFile, pos1, pos2) {
return ts.getLineAndCharacterOfPosition(sourceFile, pos1).line === ts.getLineAndCharacterOfPosition(sourceFile, pos2).line;
}
exports.isSameLine = isSameLine;
var SideEffectOptions;
(function (SideEffectOptions) {
SideEffectOptions[SideEffectOptions["None"] = 0] = "None";
SideEffectOptions[SideEffectOptions["TaggedTemplate"] = 1] = "TaggedTemplate";
SideEffectOptions[SideEffectOptions["Constructor"] = 2] = "Constructor";
SideEffectOptions[SideEffectOptions["JsxElement"] = 4] = "JsxElement";
})(SideEffectOptions = exports.SideEffectOptions || (exports.SideEffectOptions = {}));
function hasSideEffects(node, options) {
var _a, _b;
const queue = [];
while (true) {
switch (node.kind) {
case ts.SyntaxKind.CallExpression:
case ts.SyntaxKind.PostfixUnaryExpression:
case ts.SyntaxKind.AwaitExpression:
case ts.SyntaxKind.YieldExpression:
case ts.SyntaxKind.DeleteExpression:
return true;
case ts.SyntaxKind.TypeAssertionExpression:
case ts.SyntaxKind.AsExpression:
case ts.SyntaxKind.ParenthesizedExpression:
case ts.SyntaxKind.NonNullExpression:
case ts.SyntaxKind.VoidExpression:
case ts.SyntaxKind.TypeOfExpression:
case ts.SyntaxKind.PropertyAccessExpression:
case ts.SyntaxKind.SpreadElement:
case ts.SyntaxKind.PartiallyEmittedExpression:
node = node.expression;
continue;
case ts.SyntaxKind.BinaryExpression:
if (isAssignmentKind(node.operatorToken.kind))
return true;
queue.push(node.right);
node = node.left;
continue;
case ts.SyntaxKind.PrefixUnaryExpression:
switch (node.operator) {
case ts.SyntaxKind.PlusPlusToken:
case ts.SyntaxKind.MinusMinusToken:
return true;
default:
node = node.operand;
continue;
}
case ts.SyntaxKind.ElementAccessExpression:
if (node.argumentExpression !== undefined) // for compatibility with typescript@<2.9.0
queue.push(node.argumentExpression);
node = node.expression;
continue;
case ts.SyntaxKind.ConditionalExpression:
queue.push(node.whenTrue, node.whenFalse);
node = node.condition;
continue;
case ts.SyntaxKind.NewExpression:
if (options & 2 /* Constructor */)
return true;
if (node.arguments !== undefined)
queue.push(...node.arguments);
node = node.expression;
continue;
case ts.SyntaxKind.TaggedTemplateExpression:
if (options & 1 /* TaggedTemplate */)
return true;
queue.push(node.tag);
node = node.template;
if (node.kind === ts.SyntaxKind.NoSubstitutionTemplateLiteral)
break;
// falls through
case ts.SyntaxKind.TemplateExpression:
for (const child of node.templateSpans)
queue.push(child.expression);
break;
case ts.SyntaxKind.ClassExpression: {
if (node.decorators !== undefined)
return true;
for (const child of node.members) {
if (child.decorators !== undefined)
return true;
if (!hasModifier(child.modifiers, ts.SyntaxKind.DeclareKeyword)) {
if (((_a = child.name) === null || _a === void 0 ? void 0 : _a.kind) === ts.SyntaxKind.ComputedPropertyName)
queue.push(child.name.expression);
if (node_1.isMethodDeclaration(child)) {
for (const p of child.parameters)
if (p.decorators !== undefined)
return true;
}
else if (node_1.isPropertyDeclaration(child) &&
child.initializer !== undefined &&
hasModifier(child.modifiers, ts.SyntaxKind.StaticKeyword)) {
queue.push(child.initializer);
}
}
}
const base = getBaseOfClassLikeExpression(node);
if (base === undefined)
break;
node = base.expression;
continue;
}
case ts.SyntaxKind.ArrayLiteralExpression:
queue.push(...node.elements);
break;
case ts.SyntaxKind.ObjectLiteralExpression:
for (const child of node.properties) {
if (((_b = child.name) === null || _b === void 0 ? void 0 : _b.kind) === ts.SyntaxKind.ComputedPropertyName)
queue.push(child.name.expression);
switch (child.kind) {
case ts.SyntaxKind.PropertyAssignment:
queue.push(child.initializer);
break;
case ts.SyntaxKind.SpreadAssignment:
queue.push(child.expression);
}
}
break;
case ts.SyntaxKind.JsxExpression:
if (node.expression === undefined)
break;
node = node.expression;
continue;
case ts.SyntaxKind.JsxElement:
case ts.SyntaxKind.JsxFragment:
for (const child of node.children)
if (child.kind !== ts.SyntaxKind.JsxText)
queue.push(child);
if (node.kind === ts.SyntaxKind.JsxFragment)
break;
node = node.openingElement;
// falls through
case ts.SyntaxKind.JsxSelfClosingElement:
case ts.SyntaxKind.JsxOpeningElement:
if (options & 4 /* JsxElement */)
return true;
for (const child of node.attributes.properties) {
if (child.kind === ts.SyntaxKind.JsxSpreadAttribute) {
queue.push(child.expression);
}
else if (child.initializer !== undefined) {
queue.push(child.initializer);
}
}
break;
case ts.SyntaxKind.CommaListExpression:
queue.push(...node.elements);
}
if (queue.length === 0)
return false;
node = queue.pop();
}
}
exports.hasSideEffects = hasSideEffects;
/** Returns the VariableDeclaration or ParameterDeclaration that contains the BindingElement */
function getDeclarationOfBindingElement(node) {
let parent = node.parent.parent;
while (parent.kind === ts.SyntaxKind.BindingElement)
parent = parent.parent.parent;
return parent;
}
exports.getDeclarationOfBindingElement = getDeclarationOfBindingElement;
function isExpressionValueUsed(node) {
while (true) {
const parent = node.parent;
switch (parent.kind) {
case ts.SyntaxKind.CallExpression:
case ts.SyntaxKind.NewExpression:
case ts.SyntaxKind.ElementAccessExpression:
case ts.SyntaxKind.WhileStatement:
case ts.SyntaxKind.DoStatement:
case ts.SyntaxKind.WithStatement:
case ts.SyntaxKind.ThrowStatement:
case ts.SyntaxKind.ReturnStatement:
case ts.SyntaxKind.JsxExpression:
case ts.SyntaxKind.JsxSpreadAttribute:
case ts.SyntaxKind.JsxElement:
case ts.SyntaxKind.JsxFragment:
case ts.SyntaxKind.JsxSelfClosingElement:
case ts.SyntaxKind.ComputedPropertyName:
case ts.SyntaxKind.ArrowFunction:
case ts.SyntaxKind.ExportSpecifier:
case ts.SyntaxKind.ExportAssignment:
case ts.SyntaxKind.ImportDeclaration:
case ts.SyntaxKind.ExternalModuleReference:
case ts.SyntaxKind.Decorator:
case ts.SyntaxKind.TaggedTemplateExpression:
case ts.SyntaxKind.TemplateSpan:
case ts.SyntaxKind.ExpressionWithTypeArguments:
case ts.SyntaxKind.TypeOfExpression:
case ts.SyntaxKind.AwaitExpression:
case ts.SyntaxKind.YieldExpression:
case ts.SyntaxKind.LiteralType:
case ts.SyntaxKind.JsxAttributes:
case ts.SyntaxKind.JsxOpeningElement:
case ts.SyntaxKind.JsxClosingElement:
case ts.SyntaxKind.IfStatement:
case ts.SyntaxKind.CaseClause:
case ts.SyntaxKind.SwitchStatement:
return true;
case ts.SyntaxKind.PropertyAccessExpression:
return parent.expression === node;
case ts.SyntaxKind.QualifiedName:
return parent.left === node;
case ts.SyntaxKind.ShorthandPropertyAssignment:
return parent.objectAssignmentInitializer === node ||
!isInDestructuringAssignment(parent);
case ts.SyntaxKind.PropertyAssignment:
return parent.initializer === node && !isInDestructuringAssignment(parent);
case ts.SyntaxKind.SpreadAssignment:
case ts.SyntaxKind.SpreadElement:
case ts.SyntaxKind.ArrayLiteralExpression:
return !isInDestructuringAssignment(parent);
case ts.SyntaxKind.ParenthesizedExpression:
case ts.SyntaxKind.AsExpression:
case ts.SyntaxKind.TypeAssertionExpression:
case ts.SyntaxKind.PostfixUnaryExpression:
case ts.SyntaxKind.PrefixUnaryExpression:
case ts.SyntaxKind.NonNullExpression:
node = parent;
continue;
case ts.SyntaxKind.ForStatement:
return parent.condition === node;
case ts.SyntaxKind.ForInStatement:
case ts.SyntaxKind.ForOfStatement:
return parent.expression === node;
case ts.SyntaxKind.ConditionalExpression:
if (parent.condition === node)
return true;
node = parent;
break;
case ts.SyntaxKind.PropertyDeclaration:
case ts.SyntaxKind.BindingElement:
case ts.SyntaxKind.VariableDeclaration:
case ts.SyntaxKind.Parameter:
case ts.SyntaxKind.EnumMember:
return parent.initializer === node;
case ts.SyntaxKind.ImportEqualsDeclaration:
return parent.moduleReference === node;
case ts.SyntaxKind.CommaListExpression:
if (parent.elements[parent.elements.length - 1] !== node)
return false;
node = parent;
break;
case ts.SyntaxKind.BinaryExpression:
if (parent.right === node) {
if (parent.operatorToken.kind === ts.SyntaxKind.CommaToken) {
node = parent;
break;
}
return true;
}
switch (parent.operatorToken.kind) {
case ts.SyntaxKind.CommaToken:
case ts.SyntaxKind.EqualsToken:
return false;
case ts.SyntaxKind.EqualsEqualsEqualsToken:
case ts.SyntaxKind.EqualsEqualsToken:
case ts.SyntaxKind.ExclamationEqualsEqualsToken:
case ts.SyntaxKind.ExclamationEqualsToken:
case ts.SyntaxKind.InstanceOfKeyword:
case ts.SyntaxKind.PlusToken:
case ts.SyntaxKind.MinusToken:
case ts.SyntaxKind.AsteriskToken:
case ts.SyntaxKind.SlashToken:
case ts.SyntaxKind.PercentToken:
case ts.SyntaxKind.AsteriskAsteriskToken:
case ts.SyntaxKind.GreaterThanToken:
case ts.SyntaxKind.GreaterThanGreaterThanToken:
case ts.SyntaxKind.GreaterThanGreaterThanGreaterThanToken:
case ts.SyntaxKind.GreaterThanEqualsToken:
case ts.SyntaxKind.LessThanToken:
case ts.SyntaxKind.LessThanLessThanToken:
case ts.SyntaxKind.LessThanEqualsToken:
case ts.SyntaxKind.AmpersandToken:
case ts.SyntaxKind.BarToken:
case ts.SyntaxKind.CaretToken:
case ts.SyntaxKind.BarBarToken:
case ts.SyntaxKind.AmpersandAmpersandToken:
case ts.SyntaxKind.QuestionQuestionToken:
case ts.SyntaxKind.InKeyword:
case ts.SyntaxKind.QuestionQuestionEqualsToken:
case ts.SyntaxKind.AmpersandAmpersandEqualsToken:
case ts.SyntaxKind.BarBarEqualsToken:
return true;
default:
node = parent;
}
break;
default:
return false;
}
}
}
exports.isExpressionValueUsed = isExpressionValueUsed;
function isInDestructuringAssignment(node) {
switch (node.kind) {
case ts.SyntaxKind.ShorthandPropertyAssignment:
if (node.objectAssignmentInitializer !== undefined)
return true;
// falls through
case ts.SyntaxKind.PropertyAssignment:
case ts.SyntaxKind.SpreadAssignment:
node = node.parent;
break;
case ts.SyntaxKind.SpreadElement:
if (node.parent.kind !== ts.SyntaxKind.ArrayLiteralExpression)
return false;
node = node.parent;
}
while (true) {
switch (node.parent.kind) {
case ts.SyntaxKind.BinaryExpression:
return node.parent.left === node &&
node.parent.operatorToken.kind === ts.SyntaxKind.EqualsToken;
case ts.SyntaxKind.ForOfStatement:
return node.parent.initializer === node;
case ts.SyntaxKind.ArrayLiteralExpression:
case ts.SyntaxKind.ObjectLiteralExpression:
node = node.parent;
break;
case ts.SyntaxKind.SpreadAssignment:
case ts.SyntaxKind.PropertyAssignment:
node = node.parent.parent;
break;
case ts.SyntaxKind.SpreadElement:
if (node.parent.parent.kind !== ts.SyntaxKind.ArrayLiteralExpression)
return false;
node = node.parent.parent;
break;
default:
return false;
}
}
}
var AccessKind;
(function (AccessKind) {
AccessKind[AccessKind["None"] = 0] = "None";
AccessKind[AccessKind["Read"] = 1] = "Read";
AccessKind[AccessKind["Write"] = 2] = "Write";
AccessKind[AccessKind["Delete"] = 4] = "Delete";
AccessKind[AccessKind["ReadWrite"] = 3] = "ReadWrite";
AccessKind[AccessKind["Modification"] = 6] = "Modification";
})(AccessKind = exports.AccessKind || (exports.AccessKind = {}));
function getAccessKind(node) {
const parent = node.parent;
switch (parent.kind) {
case ts.SyntaxKind.DeleteExpression:
return 4 /* Delete */;
case ts.SyntaxKind.PostfixUnaryExpression:
return 3 /* ReadWrite */;
case ts.SyntaxKind.PrefixUnaryExpression:
return parent.operator === ts.SyntaxKind.PlusPlusToken ||
parent.operator === ts.SyntaxKind.MinusMinusToken
? 3 /* ReadWrite */
: 1 /* Read */;
case ts.SyntaxKind.BinaryExpression:
return parent.right === node
? 1 /* Read */
: !isAssignmentKind(parent.operatorToken.kind)
? 1 /* Read */
: parent.operatorToken.kind === ts.SyntaxKind.EqualsToken
? 2 /* Write */
: 3 /* ReadWrite */;
case ts.SyntaxKind.ShorthandPropertyAssignment:
return parent.objectAssignmentInitializer === node
? 1 /* Read */
: isInDestructuringAssignment(parent)
? 2 /* Write */
: 1 /* Read */;
case ts.SyntaxKind.PropertyAssignment:
return parent.name === node
? 0 /* None */
: isInDestructuringAssignment(parent)
? 2 /* Write */
: 1 /* Read */;
case ts.SyntaxKind.ArrayLiteralExpression:
case ts.SyntaxKind.SpreadElement:
case ts.SyntaxKind.SpreadAssignment:
return isInDestructuringAssignment(parent)
? 2 /* Write */
: 1 /* Read */;
case ts.SyntaxKind.ParenthesizedExpression:
case ts.SyntaxKind.NonNullExpression: