1
1
import type { RawSourceMap } from '@ampproject/remapping'
2
2
import type { File , Task , TaskResultPack , TaskState } from '@vitest/runner'
3
3
import type { ParsedStack } from '@vitest/utils'
4
+ import type { EachMapping } from '@vitest/utils/source-map'
4
5
import type { ChildProcess } from 'node:child_process'
5
6
import type { Vitest } from '../node/core'
6
7
import type { TestProject } from '../node/project'
@@ -10,7 +11,7 @@ import type { TscErrorInfo } from './types'
10
11
import { rm } from 'node:fs/promises'
11
12
import { performance } from 'node:perf_hooks'
12
13
import { getTasks } from '@vitest/runner/utils'
13
- import { generatedPositionFor , TraceMap } from '@vitest/utils/source-map'
14
+ import { eachMapping , generatedPositionFor , TraceMap } from '@vitest/utils/source-map'
14
15
import { basename , extname , resolve } from 'pathe'
15
16
import { x } from 'tinyexec'
16
17
import { collectTests } from './collect'
@@ -161,7 +162,7 @@ export class Typechecker {
161
162
}
162
163
errors . forEach ( ( { error, originalError } ) => {
163
164
const processedPos = traceMap
164
- ? generatedPositionFor ( traceMap , {
165
+ ? findGeneratedPosition ( traceMap , {
165
166
line : originalError . line ,
166
167
column : originalError . column ,
167
168
source : basename ( path ) ,
@@ -364,3 +365,40 @@ export class Typechecker {
364
365
. map < TaskResultPack > ( i => [ i . id , i . result , { typecheck : true } ] )
365
366
}
366
367
}
368
+
369
+ function findGeneratedPosition ( traceMap : TraceMap , { line, column, source } : { line : number ; column : number ; source : string } ) {
370
+ const found = generatedPositionFor ( traceMap , {
371
+ line,
372
+ column,
373
+ source,
374
+ } )
375
+ if ( found . line !== null ) {
376
+ return found
377
+ }
378
+ // find the next source token position when the exact error position doesn't exist in source map.
379
+ // this can happen, for example, when the type error is in the comment "// @ts-expect-error"
380
+ // and comments are stripped away in the generated code.
381
+ const mappings : ( EachMapping & { originalLine : number } ) [ ] = [ ]
382
+ eachMapping ( traceMap , ( m ) => {
383
+ if (
384
+ m . source === source
385
+ && m . originalLine !== null
386
+ && m . originalColumn !== null
387
+ && ( line === m . originalLine ? column < m . originalColumn : line < m . originalLine )
388
+ ) {
389
+ mappings . push ( m )
390
+ }
391
+ } )
392
+ const next = mappings
393
+ . sort ( ( a , b ) =>
394
+ a . originalLine === b . originalLine ? a . originalColumn - b . originalColumn : a . originalLine - b . originalLine ,
395
+ )
396
+ . at ( 0 )
397
+ if ( next ) {
398
+ return {
399
+ line : next . generatedLine ,
400
+ column : next . generatedColumn ,
401
+ }
402
+ }
403
+ return { line : null , column : null }
404
+ }
0 commit comments