diff --git a/packages/typescript-estree/src/convert-comments.ts b/packages/typescript-estree/src/convert-comments.ts index d4dd9f124a79..89071b709f76 100644 --- a/packages/typescript-estree/src/convert-comments.ts +++ b/packages/typescript-estree/src/convert-comments.ts @@ -26,7 +26,6 @@ export function convertComments( ? AST_TOKEN_TYPES.Line : AST_TOKEN_TYPES.Block; const range: TSESTree.Range = [comment.pos, comment.end]; - const loc = getLocFor(range[0], range[1], ast); // both comments start with 2 characters - /* or // const textStart = range[0] + 2; @@ -40,7 +39,7 @@ export function convertComments( type, value: code.slice(textStart, textStart + textEnd), range, - loc, + loc: getLocFor(range[0], range[1], ast), }); }, ast, diff --git a/packages/typescript-estree/src/convert.ts b/packages/typescript-estree/src/convert.ts index 4f7a89d97c14..908b6cff7f5d 100644 --- a/packages/typescript-estree/src/convert.ts +++ b/packages/typescript-estree/src/convert.ts @@ -3,7 +3,7 @@ import * as ts from 'typescript'; import { getDecorators, getModifiers } from './getModifiers'; -import type { TSError } from './node-utils'; +import type { OptionalRangeAndLoc, TSError } from './node-utils'; import { canContainDirective, createError, @@ -251,7 +251,7 @@ export class Converter { private createNode( node: TSESTreeToTSNode, - data: TSESTree.OptionalRangeAndLoc, + data: OptionalRangeAndLoc, ): T { const result = data; if (!result.range) { @@ -2820,7 +2820,7 @@ export class Converter { id, body, global: true, - } satisfies TSESTree.OptionalRangeAndLoc< + } satisfies OptionalRangeAndLoc< Omit >; } else if (node.flags & ts.NodeFlags.Namespace) { @@ -2834,7 +2834,7 @@ export class Converter { kind: 'namespace', id, body, - } satisfies TSESTree.OptionalRangeAndLoc< + } satisfies OptionalRangeAndLoc< Omit >; } else { @@ -2842,7 +2842,7 @@ export class Converter { kind: 'module', id, ...(body != null ? { body } : {}), - } satisfies TSESTree.OptionalRangeAndLoc< + } satisfies OptionalRangeAndLoc< Omit >; } diff --git a/packages/typescript-estree/src/node-utils.ts b/packages/typescript-estree/src/node-utils.ts index 2b7351b0408f..fd6b032c11ca 100644 --- a/packages/typescript-estree/src/node-utils.ts +++ b/packages/typescript-estree/src/node-utils.ts @@ -181,9 +181,27 @@ export function getLocFor( end: number, ast: ts.SourceFile, ): TSESTree.SourceLocation { + let locStart: TSESTree.Position | null = null; + let locEnd: TSESTree.Position | null = null; return { - start: getLineAndCharacterFor(start, ast), - end: getLineAndCharacterFor(end, ast), + get start(): TSESTree.Position { + if (locStart == null) { + locStart = getLineAndCharacterFor(start, ast); + } + return locStart; + }, + set start(val: TSESTree.Position) { + locStart = val; + }, + get end(): TSESTree.Position { + if (locEnd == null) { + locEnd = getLineAndCharacterFor(end, ast); + } + return locEnd; + }, + set end(val: TSESTree.Position) { + locEnd = val; + }, }; } @@ -522,6 +540,17 @@ export function getTokenType( return AST_TOKEN_TYPES.Identifier; } +export type OptionalLoc = Pick> & { + loc?: TSESTree.SourceLocation; +}; +export type OptionalRangeAndLoc = Pick< + T, + Exclude +> & { + range?: TSESTree.Range; + loc?: TSESTree.SourceLocation; +}; + /** * Extends and formats a given ts.Token, for a given AST * @param token the ts.Token @@ -541,26 +570,27 @@ export function convertToken( const tokenType = getTokenType(token); if (tokenType === AST_TOKEN_TYPES.RegularExpression) { - return { - type: tokenType, + const newToken: TSESTree.RegularExpressionToken = { + type: AST_TOKEN_TYPES.RegularExpression, value, range: [start, end], - loc: getLocFor(start, end, ast), regex: { pattern: value.slice(1, value.lastIndexOf('/')), flags: value.slice(value.lastIndexOf('/') + 1), }, - }; - } else { - // @ts-expect-error TS is complaining about `value` not being the correct - // type but it is - return { - type: tokenType, - value, - range: [start, end], loc: getLocFor(start, end, ast), }; + return newToken; } + + // @ts-expect-error TS is complaining about `value` not being the correct type but it is + const newToken: Exclude = { + type: tokenType, + value, + range: [start, end], + loc: getLocFor(start, end, ast), + }; + return newToken; } /** diff --git a/packages/typescript-estree/src/simple-traverse.ts b/packages/typescript-estree/src/simple-traverse.ts index 2d51cdbe4fa1..c1edaf68c180 100644 --- a/packages/typescript-estree/src/simple-traverse.ts +++ b/packages/typescript-estree/src/simple-traverse.ts @@ -13,7 +13,8 @@ function getVisitorKeysForNode( node: TSESTree.Node, ): readonly (keyof TSESTree.Node)[] { const keys = allVisitorKeys[node.type]; - return (keys ?? []) as never; + // @ts-expect-error -- keys will provably be of the correct type - it's just not possible to type + return keys ?? []; } type SimpleTraverseOptions =