📄 node-utils.ts
¶
📊 Analysis Summary¶
Metric | Count |
---|---|
🔧 Functions | 48 |
🧱 Classes | 1 |
📦 Imports | 7 |
📊 Variables & Constants | 15 |
📐 Interfaces | 1 |
📑 Type Aliases | 5 |
📚 Table of Contents¶
🛠️ File Location:¶
📂 packages/typescript-estree/src/node-utils.ts
📦 Imports¶
Name | Source |
---|---|
TSESTree |
./ts-estree |
TSNode |
./ts-estree |
getModifiers |
./getModifiers |
xhtmlEntities |
./jsx/xhtml-entities |
AST_NODE_TYPES |
./ts-estree |
AST_TOKEN_TYPES |
./ts-estree |
typescriptVersionIsAtLeast |
./version-check |
Variables & Constants¶
Name | Type | Kind | Value | Exported |
---|---|---|---|---|
isAtLeast50 |
boolean |
const | typescriptVersionIsAtLeast['5.0'] |
✗ |
SyntaxKind |
any |
const | ts.SyntaxKind |
✗ |
LOGICAL_OPERATORS |
ReadonlySet<LogicalOperatorKind> |
const | `new Set([ | |
SyntaxKind.AmpersandAmpersandToken, | ||||
SyntaxKind.BarBarToken, | ||||
SyntaxKind.QuestionQuestionToken, | ||||
])` | ✗ | |||
ASSIGNMENT_OPERATORS |
ReadonlySet<AssignmentOperatorKind> |
const | `new Set([ | |
ts.SyntaxKind.AmpersandAmpersandEqualsToken, | ||||
ts.SyntaxKind.AmpersandEqualsToken, | ||||
ts.SyntaxKind.AsteriskAsteriskEqualsToken, | ||||
ts.SyntaxKind.AsteriskEqualsToken, | ||||
ts.SyntaxKind.BarBarEqualsToken, | ||||
ts.SyntaxKind.BarEqualsToken, | ||||
ts.SyntaxKind.CaretEqualsToken, | ||||
ts.SyntaxKind.EqualsToken, | ||||
ts.SyntaxKind.GreaterThanGreaterThanEqualsToken, | ||||
ts.SyntaxKind.GreaterThanGreaterThanGreaterThanEqualsToken, | ||||
ts.SyntaxKind.LessThanLessThanEqualsToken, | ||||
ts.SyntaxKind.MinusEqualsToken, | ||||
ts.SyntaxKind.PercentEqualsToken, | ||||
ts.SyntaxKind.PlusEqualsToken, | ||||
ts.SyntaxKind.QuestionQuestionEqualsToken, | ||||
ts.SyntaxKind.SlashEqualsToken, | ||||
])` | ✗ | |||
BINARY_OPERATORS |
ReadonlySet<BinaryOperatorKind> |
const | `new Set([ | |
SyntaxKind.AmpersandAmpersandToken, | ||||
SyntaxKind.AmpersandToken, | ||||
SyntaxKind.AsteriskAsteriskToken, | ||||
SyntaxKind.AsteriskToken, | ||||
SyntaxKind.BarBarToken, | ||||
SyntaxKind.BarToken, | ||||
SyntaxKind.CaretToken, | ||||
SyntaxKind.EqualsEqualsEqualsToken, | ||||
SyntaxKind.EqualsEqualsToken, | ||||
SyntaxKind.ExclamationEqualsEqualsToken, | ||||
SyntaxKind.ExclamationEqualsToken, | ||||
SyntaxKind.GreaterThanEqualsToken, | ||||
SyntaxKind.GreaterThanGreaterThanGreaterThanToken, | ||||
SyntaxKind.GreaterThanGreaterThanToken, | ||||
SyntaxKind.GreaterThanToken, | ||||
SyntaxKind.InKeyword, | ||||
SyntaxKind.InstanceOfKeyword, | ||||
SyntaxKind.LessThanEqualsToken, | ||||
SyntaxKind.LessThanLessThanToken, | ||||
SyntaxKind.LessThanToken, | ||||
SyntaxKind.MinusToken, | ||||
SyntaxKind.PercentToken, | ||||
SyntaxKind.PlusToken, | ||||
SyntaxKind.SlashToken, | ||||
])` | ✗ | |||
shouldDiveInChildNode |
boolean |
const | `(child.pos <= previousToken.pos && child.end > previousToken.end) | |
// previous token ends exactly at the beginning of child | ||||
child.pos === previousToken.end` | ✗ | |||
current |
ts.Node | undefined |
let/var | node |
✗ |
codePoint |
number |
const | `item[1] === 'x' | |
? parseInt(item.slice(2), 16) | ||||
: parseInt(item.slice(1), 10)` | ✗ | |||
keywordKind |
ts.SyntaxKind | undefined |
let/var | *not shown* |
✗ |
start |
any |
const | `token.kind === SyntaxKind.JsxText | |
? token.getFullStart() | ||||
: token.getStart(ast)` | ✗ | |||
range |
TSESTree.Range |
const | [start, end] |
✗ |
result |
TSESTree.Token[] |
const | [] |
✗ |
thisParameter |
any |
const | signature.parameters[0] |
✗ |
grandparent |
any |
const | parent.parent |
✗ |
moduleDeclaration |
ts.ModuleDeclaration |
let/var | node |
✗ |
Functions¶
isAssignmentOperator(operator: ts.BinaryOperatorToken): operator is ts.Token<AssignmentOperatorKind>
¶
Code
-
JSDoc:
-
Parameters:
operator: ts.BinaryOperatorToken
- Return Type:
operator is ts.Token<AssignmentOperatorKind>
- Calls:
(ASSIGNMENT_OPERATORS as ReadonlySet<ts.SyntaxKind>).has
isLogicalOperator(operator: ts.BinaryOperatorToken): operator is ts.Token<LogicalOperatorKind>
¶
Code
-
JSDoc:
-
Parameters:
operator: ts.BinaryOperatorToken
- Return Type:
operator is ts.Token<LogicalOperatorKind>
- Calls:
(LOGICAL_OPERATORS as ReadonlySet<ts.SyntaxKind>).has
isESTreeBinaryOperator(operator: ts.BinaryOperatorToken): operator is ts.Token<BinaryOperatorKind>
¶
Code
- Parameters:
operator: ts.BinaryOperatorToken
- Return Type:
operator is ts.Token<BinaryOperatorKind>
- Calls:
(BINARY_OPERATORS as ReadonlySet<ts.SyntaxKind>).has
getTextForTokenKind(kind: T): TokenForTokenKind<T>
¶
Code
-
JSDoc:
-
Parameters:
kind: T
- Return Type:
TokenForTokenKind<T>
- Calls:
ts.tokenToString
isESTreeClassMember(node: ts.Node): boolean
¶
Code
-
JSDoc:
-
Parameters:
node: ts.Node
- Return Type:
boolean
hasModifier(modifierKind: ts.KeywordSyntaxKind, node: ts.Node): boolean
¶
Code
-
JSDoc:
-
Parameters:
modifierKind: ts.KeywordSyntaxKind
node: ts.Node
- Return Type:
boolean
- Calls:
getModifiers (from ./getModifiers)
modifiers?.some
getLastModifier(node: ts.Node): ts.Modifier | null
¶
Code
-
JSDoc:
-
Parameters:
node: ts.Node
- Return Type:
ts.Modifier | null
- Calls:
getModifiers (from ./getModifiers)
isComma(token: ts.Node): token is ts.Token<ts.SyntaxKind.CommaToken>
¶
Code
-
JSDoc:
-
Parameters:
token: ts.Node
- Return Type:
token is ts.Token<ts.SyntaxKind.CommaToken>
isComment(node: ts.Node): boolean
¶
Code
-
JSDoc:
-
Parameters:
node: ts.Node
- Return Type:
boolean
isJSDocComment(node: ts.Node): node is ts.JSDoc
¶
Code
-
JSDoc:
-
Parameters:
node: ts.Node
- Return Type:
node is ts.JSDoc
- Internal Comments:
`getBinaryExpressionType(operator: ts.BinaryOperatorToken): | {¶
operator: TokenForTokenKind<AssignmentOperatorKind>;
type: AST_NODE_TYPES.AssignmentExpression;
}
| {
operator: TokenForTokenKind
Code
export function getBinaryExpressionType(operator: ts.BinaryOperatorToken):
| {
operator: TokenForTokenKind<AssignmentOperatorKind>;
type: AST_NODE_TYPES.AssignmentExpression;
}
| {
operator: TokenForTokenKind<BinaryOperatorKind>;
type: AST_NODE_TYPES.BinaryExpression;
}
| {
operator: TokenForTokenKind<LogicalOperatorKind>;
type: AST_NODE_TYPES.LogicalExpression;
} {
if (isAssignmentOperator(operator)) {
return {
type: AST_NODE_TYPES.AssignmentExpression,
operator: getTextForTokenKind(operator.kind),
};
}
if (isLogicalOperator(operator)) {
return {
type: AST_NODE_TYPES.LogicalExpression,
operator: getTextForTokenKind(operator.kind),
};
}
if (isESTreeBinaryOperator(operator)) {
return {
type: AST_NODE_TYPES.BinaryExpression,
operator: getTextForTokenKind(operator.kind),
};
}
throw new Error(
`Unexpected binary operator ${ts.tokenToString(operator.kind)}`,
);
}
-
JSDoc:
-
Parameters:
operator: ts.BinaryOperatorToken
- Return Type:
| { operator: TokenForTokenKind<AssignmentOperatorKind>; type: AST_NODE_TYPES.AssignmentExpression; } | { operator: TokenForTokenKind<BinaryOperatorKind>; type: AST_NODE_TYPES.BinaryExpression; } | { operator: TokenForTokenKind<LogicalOperatorKind>; type: AST_NODE_TYPES.LogicalExpression; }
- Calls:
isAssignmentOperator
getTextForTokenKind
isLogicalOperator
isESTreeBinaryOperator
ts.tokenToString
getLineAndCharacterFor(pos: number, ast: ts.SourceFile): TSESTree.Position
¶
Code
-
JSDoc:
-
Parameters:
pos: number
ast: ts.SourceFile
- Return Type:
TSESTree.Position
- Calls:
ast.getLineAndCharacterOfPosition
getLocFor(range: TSESTree.Range, ast: ts.SourceFile): TSESTree.SourceLocation
¶
Code
-
JSDoc:
-
Parameters:
range: TSESTree.Range
ast: ts.SourceFile
- Return Type:
TSESTree.SourceLocation
- Calls:
range.map
getLineAndCharacterFor
`canContainDirective(node: | ts.Block¶
| ts.ClassStaticBlockDeclaration
| ts.ModuleBlock
| ts.SourceFile): boolean`
Code
export function canContainDirective(
node:
| ts.Block
| ts.ClassStaticBlockDeclaration
| ts.ModuleBlock
| ts.SourceFile,
): boolean {
if (node.kind === ts.SyntaxKind.Block) {
switch (node.parent.kind) {
case ts.SyntaxKind.Constructor:
case ts.SyntaxKind.GetAccessor:
case ts.SyntaxKind.SetAccessor:
case ts.SyntaxKind.ArrowFunction:
case ts.SyntaxKind.FunctionExpression:
case ts.SyntaxKind.FunctionDeclaration:
case ts.SyntaxKind.MethodDeclaration:
return true;
default:
return false;
}
}
return true;
}
-
JSDoc:
-
Parameters:
node: | ts.Block | ts.ClassStaticBlockDeclaration | ts.ModuleBlock | ts.SourceFile
- Return Type:
boolean
getRange(node: Pick<ts.Node, 'getEnd' | 'getStart'>, ast: ts.SourceFile): [number, number]
¶
Code
-
JSDoc:
-
Parameters:
node: Pick<ts.Node, 'getEnd' | 'getStart'>
ast: ts.SourceFile
- Return Type:
[number, number]
- Calls:
node.getStart
node.getEnd
isToken(node: ts.Node): node is ts.Token<ts.TokenSyntaxKind>
¶
Code
-
JSDoc:
-
Parameters:
node: ts.Node
- Return Type:
node is ts.Token<ts.TokenSyntaxKind>
isJSXToken(node: ts.Node): boolean
¶
Code
-
JSDoc:
-
Parameters:
node: ts.Node
- Return Type:
boolean
getDeclarationKind(node: ts.VariableDeclarationList): DeclarationKind
¶
Code
export function getDeclarationKind(
node: ts.VariableDeclarationList,
): DeclarationKind {
if (node.flags & ts.NodeFlags.Let) {
return 'let';
}
// eslint-disable-next-line @typescript-eslint/no-unsafe-enum-comparison
if ((node.flags & ts.NodeFlags.AwaitUsing) === ts.NodeFlags.AwaitUsing) {
return 'await using';
}
if (node.flags & ts.NodeFlags.Const) {
return 'const';
}
if (node.flags & ts.NodeFlags.Using) {
return 'using';
}
return 'var';
}
-
JSDoc:
-
Parameters:
node: ts.VariableDeclarationList
- Return Type:
DeclarationKind
- Internal Comments:
getTSNodeAccessibility(node: ts.Node): 'private' | 'protected' | 'public' | undefined
¶
Code
export function getTSNodeAccessibility(
node: ts.Node,
): 'private' | 'protected' | 'public' | undefined {
const modifiers = getModifiers(node);
if (modifiers == null) {
return undefined;
}
for (const modifier of modifiers) {
switch (modifier.kind) {
case SyntaxKind.PublicKeyword:
return 'public';
case SyntaxKind.ProtectedKeyword:
return 'protected';
case SyntaxKind.PrivateKeyword:
return 'private';
default:
break;
}
}
return undefined;
}
-
JSDoc:
-
Parameters:
node: ts.Node
- Return Type:
'private' | 'protected' | 'public' | undefined
- Calls:
getModifiers (from ./getModifiers)
findNextToken(previousToken: ts.TextRange, parent: ts.Node, ast: ts.SourceFile): ts.Node | undefined
¶
Code
export function findNextToken(
previousToken: ts.TextRange,
parent: ts.Node,
ast: ts.SourceFile,
): ts.Node | undefined {
return find(parent);
function find(n: ts.Node): ts.Node | undefined {
if (ts.isToken(n) && n.pos === previousToken.end) {
// this is token that starts at the end of previous token - return it
return n;
}
return firstDefined(n.getChildren(ast), (child: ts.Node) => {
const shouldDiveInChildNode =
// previous token is enclosed somewhere in the child
(child.pos <= previousToken.pos && child.end > previousToken.end) ||
// previous token ends exactly at the beginning of child
child.pos === previousToken.end;
return shouldDiveInChildNode && nodeHasTokens(child, ast)
? find(child)
: undefined;
});
}
}
-
JSDoc:
-
Parameters:
previousToken: ts.TextRange
parent: ts.Node
ast: ts.SourceFile
- Return Type:
ts.Node | undefined
- Calls:
find
ts.isToken
firstDefined
n.getChildren
nodeHasTokens
- Internal Comments:
find(n: ts.Node): ts.Node | undefined
¶
Code
function find(n: ts.Node): ts.Node | undefined {
if (ts.isToken(n) && n.pos === previousToken.end) {
// this is token that starts at the end of previous token - return it
return n;
}
return firstDefined(n.getChildren(ast), (child: ts.Node) => {
const shouldDiveInChildNode =
// previous token is enclosed somewhere in the child
(child.pos <= previousToken.pos && child.end > previousToken.end) ||
// previous token ends exactly at the beginning of child
child.pos === previousToken.end;
return shouldDiveInChildNode && nodeHasTokens(child, ast)
? find(child)
: undefined;
});
}
- Parameters:
n: ts.Node
- Return Type:
ts.Node | undefined
- Calls:
ts.isToken
firstDefined
n.getChildren
nodeHasTokens
find
- Internal Comments:
findFirstMatchingAncestor(node: ts.Node, predicate: (node: ts.Node) => boolean): ts.Node | undefined
¶
Code
-
JSDoc:
-
Parameters:
node: ts.Node
predicate: (node: ts.Node) => boolean
- Return Type:
ts.Node | undefined
- Calls:
predicate
hasJSXAncestor(node: ts.Node): boolean
¶
Code
-
JSDoc:
-
Parameters:
node: ts.Node
- Return Type:
boolean
- Calls:
findFirstMatchingAncestor
unescapeStringLiteralText(text: string): string
¶
Code
export function unescapeStringLiteralText(text: string): string {
return text.replaceAll(/&(?:#\d+|#x[\da-fA-F]+|[0-9a-zA-Z]+);/g, entity => {
const item = entity.slice(1, -1);
if (item[0] === '#') {
const codePoint =
item[1] === 'x'
? parseInt(item.slice(2), 16)
: parseInt(item.slice(1), 10);
return codePoint > 0x10ffff // RangeError: Invalid code point
? entity
: String.fromCodePoint(codePoint);
}
return xhtmlEntities[item] || entity;
});
}
-
JSDoc:
-
Parameters:
text: string
- Return Type:
string
- Calls:
text.replaceAll
entity.slice
parseInt
item.slice
String.fromCodePoint
isComputedProperty(node: ts.Node): node is ts.ComputedPropertyName
¶
Code
-
JSDoc:
-
Parameters:
node: ts.Node
- Return Type:
node is ts.ComputedPropertyName
`isOptional(node: {¶
questionToken?: ts.QuestionToken; }): boolean`
Code
-
JSDoc:
-
Parameters:
node: { questionToken?: ts.QuestionToken; }
- Return Type:
boolean
isChainExpression(node: TSESTree.Node): node is TSESTree.ChainExpression
¶
Code
-
JSDoc:
-
Parameters:
node: TSESTree.Node
- Return Type:
node is TSESTree.ChainExpression
`isChildUnwrappableOptionalChain(node: | ts.CallExpression¶
| ts.ElementAccessExpression
| ts.NonNullExpression
| ts.PropertyAccessExpression, child: TSESTree.Node): boolean`
Code
export function isChildUnwrappableOptionalChain(
node:
| ts.CallExpression
| ts.ElementAccessExpression
| ts.NonNullExpression
| ts.PropertyAccessExpression,
child: TSESTree.Node,
): boolean {
return (
isChainExpression(child) &&
// (x?.y).z is semantically different, and as such .z is no longer optional
node.expression.kind !== ts.SyntaxKind.ParenthesizedExpression
);
}
-
JSDoc:
-
Parameters:
node: | ts.CallExpression | ts.ElementAccessExpression | ts.NonNullExpression | ts.PropertyAccessExpression
child: TSESTree.Node
- Return Type:
boolean
- Calls:
isChainExpression
- Internal Comments:
getTokenType(token: ts.Identifier | ts.Token<ts.SyntaxKind>): Exclude<AST_TOKEN_TYPES, AST_TOKEN_TYPES.Block | AST_TOKEN_TYPES.Line>
¶
Code
export function getTokenType(
token: ts.Identifier | ts.Token<ts.SyntaxKind>,
): Exclude<AST_TOKEN_TYPES, AST_TOKEN_TYPES.Block | AST_TOKEN_TYPES.Line> {
let keywordKind: ts.SyntaxKind | undefined;
if (isAtLeast50 && token.kind === SyntaxKind.Identifier) {
keywordKind = ts.identifierToKeywordKind(token as ts.Identifier);
} else if ('originalKeywordKind' in token) {
// @ts-expect-error -- intentional fallback for older TS versions <=4.9
keywordKind = token.originalKeywordKind;
}
if (keywordKind) {
if (keywordKind === SyntaxKind.NullKeyword) {
return AST_TOKEN_TYPES.Null;
}
if (
keywordKind >= SyntaxKind.FirstFutureReservedWord &&
keywordKind <= SyntaxKind.LastKeyword
) {
return AST_TOKEN_TYPES.Identifier;
}
return AST_TOKEN_TYPES.Keyword;
}
if (
token.kind >= SyntaxKind.FirstKeyword &&
token.kind <= SyntaxKind.LastFutureReservedWord
) {
if (
token.kind === SyntaxKind.FalseKeyword ||
token.kind === SyntaxKind.TrueKeyword
) {
return AST_TOKEN_TYPES.Boolean;
}
return AST_TOKEN_TYPES.Keyword;
}
if (
token.kind >= SyntaxKind.FirstPunctuation &&
token.kind <= SyntaxKind.LastPunctuation
) {
return AST_TOKEN_TYPES.Punctuator;
}
if (
token.kind >= SyntaxKind.NoSubstitutionTemplateLiteral &&
token.kind <= SyntaxKind.TemplateTail
) {
return AST_TOKEN_TYPES.Template;
}
switch (token.kind) {
case SyntaxKind.NumericLiteral:
case SyntaxKind.BigIntLiteral:
return AST_TOKEN_TYPES.Numeric;
case SyntaxKind.PrivateIdentifier:
return AST_TOKEN_TYPES.PrivateIdentifier;
case SyntaxKind.JsxText:
return AST_TOKEN_TYPES.JSXText;
case SyntaxKind.StringLiteral:
// A TypeScript-StringLiteral token with a TypeScript-JsxAttribute or TypeScript-JsxElement parent,
// must actually be an ESTree-JSXText token
if (
token.parent.kind === SyntaxKind.JsxAttribute ||
token.parent.kind === SyntaxKind.JsxElement
) {
return AST_TOKEN_TYPES.JSXText;
}
return AST_TOKEN_TYPES.String;
case SyntaxKind.RegularExpressionLiteral:
return AST_TOKEN_TYPES.RegularExpression;
case SyntaxKind.Identifier:
case SyntaxKind.ConstructorKeyword:
case SyntaxKind.GetKeyword:
case SyntaxKind.SetKeyword:
// intentional fallthrough
default:
}
// Some JSX tokens have to be determined based on their parent
if (token.kind === SyntaxKind.Identifier) {
if (isJSXToken(token.parent)) {
return AST_TOKEN_TYPES.JSXIdentifier;
}
if (
token.parent.kind === SyntaxKind.PropertyAccessExpression &&
hasJSXAncestor(token)
) {
return AST_TOKEN_TYPES.JSXIdentifier;
}
}
return AST_TOKEN_TYPES.Identifier;
}
-
JSDoc:
-
Parameters:
token: ts.Identifier | ts.Token<ts.SyntaxKind>
- Return Type:
Exclude<AST_TOKEN_TYPES, AST_TOKEN_TYPES.Block | AST_TOKEN_TYPES.Line>
- Calls:
ts.identifierToKeywordKind
isJSXToken
hasJSXAncestor
- Internal Comments:
// @ts-expect-error -- intentional fallback for older TS versions <=4.9 (x3) // A TypeScript-StringLiteral token with a TypeScript-JsxAttribute or TypeScript-JsxElement parent, // must actually be an ESTree-JSXText token // intentional fallthrough // Some JSX tokens have to be determined based on their parent
convertToken(token: ts.Token<ts.TokenSyntaxKind>, ast: ts.SourceFile): TSESTree.Token
¶
Code
export function convertToken(
token: ts.Token<ts.TokenSyntaxKind>,
ast: ts.SourceFile,
): TSESTree.Token {
const start =
token.kind === SyntaxKind.JsxText
? token.getFullStart()
: token.getStart(ast);
const end = token.getEnd();
const value = ast.text.slice(start, end);
const tokenType = getTokenType(token);
const range: TSESTree.Range = [start, end];
const loc = getLocFor(range, ast);
if (tokenType === AST_TOKEN_TYPES.RegularExpression) {
return {
type: tokenType,
loc,
range,
regex: {
flags: value.slice(value.lastIndexOf('/') + 1),
pattern: value.slice(1, value.lastIndexOf('/')),
},
value,
};
}
if (tokenType === AST_TOKEN_TYPES.PrivateIdentifier) {
return {
type: tokenType,
loc,
range,
value: value.slice(1),
};
}
// @ts-expect-error TS is complaining about `value` not being the correct
// type but it is
return {
type: tokenType,
loc,
range,
value,
};
}
-
JSDoc:
-
Parameters:
token: ts.Token<ts.TokenSyntaxKind>
ast: ts.SourceFile
- Return Type:
TSESTree.Token
- Calls:
token.getFullStart
token.getStart
token.getEnd
ast.text.slice
getTokenType
getLocFor
value.slice
value.lastIndexOf
- Internal Comments:
convertTokens(ast: ts.SourceFile): TSESTree.Token[]
¶
Code
export function convertTokens(ast: ts.SourceFile): TSESTree.Token[] {
const result: TSESTree.Token[] = [];
/**
* @param node the ts.Node
*/
function walk(node: ts.Node): void {
// TypeScript generates tokens for types in JSDoc blocks. Comment tokens
// and their children should not be walked or added to the resulting tokens list.
if (isComment(node) || isJSDocComment(node)) {
return;
}
if (isToken(node) && node.kind !== SyntaxKind.EndOfFileToken) {
result.push(convertToken(node, ast));
} else {
node.getChildren(ast).forEach(walk);
}
}
walk(ast);
return result;
}
-
JSDoc:
-
Parameters:
ast: ts.SourceFile
- Return Type:
TSESTree.Token[]
- Calls:
isComment
isJSDocComment
isToken
result.push
convertToken
node.getChildren(ast).forEach
walk
- Internal Comments:
walk(node: ts.Node): void
¶
Code
function walk(node: ts.Node): void {
// TypeScript generates tokens for types in JSDoc blocks. Comment tokens
// and their children should not be walked or added to the resulting tokens list.
if (isComment(node) || isJSDocComment(node)) {
return;
}
if (isToken(node) && node.kind !== SyntaxKind.EndOfFileToken) {
result.push(convertToken(node, ast));
} else {
node.getChildren(ast).forEach(walk);
}
}
-
JSDoc:
-
Parameters:
node: ts.Node
- Return Type:
void
- Calls:
isComment
isJSDocComment
isToken
result.push
convertToken
node.getChildren(ast).forEach
- Internal Comments:
createError(message: string, ast: ts.SourceFile, startIndex: number, endIndex: number): TSError
¶
Code
export function createError(
message: string,
ast: ts.SourceFile,
startIndex: number,
endIndex: number = startIndex,
): TSError {
const [start, end] = [startIndex, endIndex].map(offset => {
const { character: column, line } =
ast.getLineAndCharacterOfPosition(offset);
return { column, line: line + 1, offset };
});
return new TSError(message, ast.fileName, { end, start });
}
- Parameters:
message: string
ast: ts.SourceFile
startIndex: number
endIndex: number
- Return Type:
TSError
- Calls:
[startIndex, endIndex].map
ast.getLineAndCharacterOfPosition
nodeHasIllegalDecorators(node: ts.Node): node is { illegalDecorators: ts.Node[] } & ts.Node
¶
Code
- Parameters:
node: ts.Node
- Return Type:
node is { illegalDecorators: ts.Node[] } & ts.Node
nodeHasTokens(n: ts.Node, ast: ts.SourceFile): boolean
¶
Code
export function nodeHasTokens(n: ts.Node, ast: ts.SourceFile): boolean {
// If we have a token or node that has a non-zero width, it must have tokens.
// Note: getWidth() does not take trivia into account.
return n.kind === SyntaxKind.EndOfFileToken
? !!(n as ts.JSDocContainer).jsDoc
: n.getWidth(ast) !== 0;
}
- Parameters:
n: ts.Node
ast: ts.SourceFile
- Return Type:
boolean
- Calls:
n.getWidth
- Internal Comments:
firstDefined(array: readonly T[] | undefined, callback: (element: T, index: number) => U | undefined): U | undefined
¶
Code
export function firstDefined<T, U>(
array: readonly T[] | undefined,
callback: (element: T, index: number) => U | undefined,
): U | undefined {
// eslint-disable-next-line @typescript-eslint/internal/eqeq-nullish
if (array === undefined) {
return undefined;
}
for (let i = 0; i < array.length; i++) {
const result = callback(array[i], i);
// eslint-disable-next-line @typescript-eslint/internal/eqeq-nullish
if (result !== undefined) {
return result;
}
}
return undefined;
}
-
JSDoc:
-
Parameters:
array: readonly T[] | undefined
callback: (element: T, index: number) => U | undefined
- Return Type:
U | undefined
- Calls:
callback
- Internal Comments:
identifierIsThisKeyword(id: ts.Identifier): boolean
¶
Code
- Parameters:
id: ts.Identifier
- Return Type:
boolean
- Calls:
ts.identifierToKeywordKind
isThisIdentifier(node: ts.Node | undefined): node is ts.Identifier
¶
Code
- Parameters:
node: ts.Node | undefined
- Return Type:
node is ts.Identifier
- Calls:
identifierIsThisKeyword
isThisInTypeQuery(node: ts.Node): boolean
¶
Code
- Parameters:
node: ts.Node
- Return Type:
boolean
- Calls:
isThisIdentifier
ts.isQualifiedName
nodeIsMissing(node: ts.Node | undefined): boolean
¶
Code
- Parameters:
node: ts.Node | undefined
- Return Type:
boolean
nodeIsPresent(node: ts.Node | undefined): node is ts.Node
¶
Code
- Parameters:
node: ts.Node | undefined
- Return Type:
node is ts.Node
- Calls:
nodeIsMissing
getContainingFunction(node: ts.Node): ts.SignatureDeclaration | undefined
¶
Code
- Parameters:
node: ts.Node
- Return Type:
ts.SignatureDeclaration | undefined
- Calls:
ts.findAncestor
hasAbstractModifier(node: ts.Node): boolean
¶
Code
- Parameters:
node: ts.Node
- Return Type:
boolean
- Calls:
hasModifier
getThisParameter(signature: ts.SignatureDeclaration): ts.ParameterDeclaration | null
¶
Code
function getThisParameter(
signature: ts.SignatureDeclaration,
): ts.ParameterDeclaration | null {
if (signature.parameters.length && !ts.isJSDocSignature(signature)) {
const thisParameter = signature.parameters[0];
if (parameterIsThisKeyword(thisParameter)) {
return thisParameter;
}
}
return null;
}
- Parameters:
signature: ts.SignatureDeclaration
- Return Type:
ts.ParameterDeclaration | null
- Calls:
ts.isJSDocSignature
parameterIsThisKeyword
parameterIsThisKeyword(parameter: ts.ParameterDeclaration): boolean
¶
Code
- Parameters:
parameter: ts.ParameterDeclaration
- Return Type:
boolean
- Calls:
isThisIdentifier
nodeCanBeDecorated(node: TSNode): boolean
¶
Code
export function nodeCanBeDecorated(node: TSNode): boolean {
switch (node.kind) {
case SyntaxKind.ClassDeclaration:
return true;
case SyntaxKind.ClassExpression:
// `ts.nodeCanBeDecorated` returns `false` if `useLegacyDecorators: true`
return true;
case SyntaxKind.PropertyDeclaration: {
const { parent } = node;
// `ts.nodeCanBeDecorated` uses this if `useLegacyDecorators: true`
if (ts.isClassDeclaration(parent)) {
return true;
}
// `ts.nodeCanBeDecorated` uses this if `useLegacyDecorators: false`
if (ts.isClassLike(parent) && !hasAbstractModifier(node)) {
return true;
}
return false;
}
case SyntaxKind.GetAccessor:
case SyntaxKind.SetAccessor:
case SyntaxKind.MethodDeclaration: {
const { parent } = node;
// In `ts.nodeCanBeDecorated`
// when `useLegacyDecorators: true` uses `ts.isClassDeclaration`
// when `useLegacyDecorators: true` uses `ts.isClassLike`
return (
Boolean(node.body) &&
(ts.isClassDeclaration(parent) || ts.isClassLike(parent))
);
}
case SyntaxKind.Parameter: {
// `ts.nodeCanBeDecorated` returns `false` if `useLegacyDecorators: false`
const { parent } = node;
const grandparent = parent.parent;
return (
Boolean(parent) &&
'body' in parent &&
Boolean(parent.body) &&
(parent.kind === SyntaxKind.Constructor ||
parent.kind === SyntaxKind.MethodDeclaration ||
parent.kind === SyntaxKind.SetAccessor) &&
getThisParameter(parent) !== node &&
Boolean(grandparent) &&
grandparent.kind === SyntaxKind.ClassDeclaration
);
}
}
return false;
}
- Parameters:
node: TSNode
- Return Type:
boolean
- Calls:
ts.isClassDeclaration
ts.isClassLike
hasAbstractModifier
Boolean
getThisParameter
- Internal Comments:
// `ts.nodeCanBeDecorated` returns `false` if `useLegacyDecorators: true` // `ts.nodeCanBeDecorated` uses this if `useLegacyDecorators: true` // `ts.nodeCanBeDecorated` uses this if `useLegacyDecorators: false` // In `ts.nodeCanBeDecorated` // when `useLegacyDecorators: true` uses `ts.isClassDeclaration` // when `useLegacyDecorators: true` uses `ts.isClassLike` // `ts.nodeCanBeDecorated` returns `false` if `useLegacyDecorators: false` (x2)
isValidAssignmentTarget(node: ts.Node): boolean
¶
Code
export function isValidAssignmentTarget(node: ts.Node): boolean {
switch (node.kind) {
case SyntaxKind.Identifier:
return true;
case SyntaxKind.PropertyAccessExpression:
case SyntaxKind.ElementAccessExpression:
if (node.flags & ts.NodeFlags.OptionalChain) {
return false;
}
return true;
case SyntaxKind.ParenthesizedExpression:
case SyntaxKind.TypeAssertionExpression:
case SyntaxKind.AsExpression:
case SyntaxKind.SatisfiesExpression:
case SyntaxKind.ExpressionWithTypeArguments:
case SyntaxKind.NonNullExpression:
return isValidAssignmentTarget(
(
node as
| ts.AssertionExpression
| ts.ExpressionWithTypeArguments
| ts.NonNullExpression
| ts.ParenthesizedExpression
| ts.SatisfiesExpression
).expression,
);
default:
return false;
}
}
- Parameters:
node: ts.Node
- Return Type:
boolean
- Calls:
isValidAssignmentTarget
getNamespaceModifiers(node: ts.ModuleDeclaration): ts.Modifier[] | undefined
¶
Code
export function getNamespaceModifiers(
node: ts.ModuleDeclaration,
): ts.Modifier[] | undefined {
// For following nested namespaces, use modifiers given to the topmost namespace
// export declare namespace foo.bar.baz {}
let modifiers = getModifiers(node);
let moduleDeclaration = node;
while (
(!modifiers || modifiers.length === 0) &&
ts.isModuleDeclaration(moduleDeclaration.parent)
) {
const parentModifiers = getModifiers(moduleDeclaration.parent);
if (parentModifiers?.length) {
modifiers = parentModifiers;
}
moduleDeclaration = moduleDeclaration.parent;
}
return modifiers;
}
- Parameters:
node: ts.ModuleDeclaration
- Return Type:
ts.Modifier[] | undefined
- Calls:
getModifiers (from ./getModifiers)
ts.isModuleDeclaration
- Internal Comments:
Classes¶
TSError
¶
Class Code
export class TSError extends Error {
constructor(
message: string,
public readonly fileName: string,
public readonly location: {
end: {
column: number;
line: number;
offset: number;
};
start: {
column: number;
line: number;
offset: number;
};
},
) {
super(message);
Object.defineProperty(this, 'name', {
configurable: true,
enumerable: false,
value: new.target.name,
});
}
// For old version of ESLint https://github.com/typescript-eslint/typescript-eslint/pull/6556#discussion_r1123237311
get index(): number {
return this.location.start.offset;
}
// https://github.com/eslint/eslint/blob/b09a512107249a4eb19ef5a37b0bd672266eafdb/lib/linter/linter.js#L853
get lineNumber(): number {
return this.location.start.line;
}
// https://github.com/eslint/eslint/blob/b09a512107249a4eb19ef5a37b0bd672266eafdb/lib/linter/linter.js#L854
get column(): number {
return this.location.start.column;
}
}
Interfaces¶
TokenToText
¶
Interface Code
Properties¶
Name | Type | Optional | Description |
---|---|---|---|
[SyntaxKind.ImportKeyword] |
'import' |
✗ | |
[SyntaxKind.KeyOfKeyword] |
'keyof' |
✗ | |
[SyntaxKind.NewKeyword] |
'new' |
✗ | |
[SyntaxKind.ReadonlyKeyword] |
'readonly' |
✗ | |
[SyntaxKind.UniqueKeyword] |
'unique' |
✗ |
Type Aliases¶
LogicalOperatorKind
¶
type LogicalOperatorKind = | ts.SyntaxKind.AmpersandAmpersandToken
| ts.SyntaxKind.BarBarToken
| ts.SyntaxKind.QuestionQuestionToken;
AssignmentOperatorKind
¶
BinaryOperatorKind
¶
DeclarationKind
¶
TokenForTokenKind<T extends ts.SyntaxKind extends ts.SyntaxKind>
¶
type TokenForTokenKind<T extends ts.SyntaxKind extends ts.SyntaxKind> = T extends keyof TokenToText
? TokenToText[T]
: string | undefined;