Skip to content

Commit

Permalink
fix(typecheck): fix error test case mapping for @ts-expect-error (#…
Browse files Browse the repository at this point in the history
  • Loading branch information
hi-ogawa authored Dec 27, 2024
1 parent 6957182 commit 27d340a
Show file tree
Hide file tree
Showing 5 changed files with 62 additions and 7 deletions.
2 changes: 2 additions & 0 deletions packages/utils/src/source-map.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ import { resolve } from 'pathe'
import { isPrimitive, notNullish } from './helpers'

export {
eachMapping,
type EachMapping,
generatedPositionFor,
originalPositionFor,
TraceMap,
Expand Down
42 changes: 40 additions & 2 deletions packages/vitest/src/typecheck/typechecker.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import type { RawSourceMap } from '@ampproject/remapping'
import type { File, Task, TaskResultPack, TaskState } from '@vitest/runner'
import type { ParsedStack } from '@vitest/utils'
import type { EachMapping } from '@vitest/utils/source-map'
import type { ChildProcess } from 'node:child_process'
import type { Vitest } from '../node/core'
import type { TestProject } from '../node/project'
Expand All @@ -10,7 +11,7 @@ import type { TscErrorInfo } from './types'
import { rm } from 'node:fs/promises'
import { performance } from 'node:perf_hooks'
import { getTasks } from '@vitest/runner/utils'
import { generatedPositionFor, TraceMap } from '@vitest/utils/source-map'
import { eachMapping, generatedPositionFor, TraceMap } from '@vitest/utils/source-map'
import { basename, extname, resolve } from 'pathe'
import { x } from 'tinyexec'
import { collectTests } from './collect'
Expand Down Expand Up @@ -161,7 +162,7 @@ export class Typechecker {
}
errors.forEach(({ error, originalError }) => {
const processedPos = traceMap
? generatedPositionFor(traceMap, {
? findGeneratedPosition(traceMap, {
line: originalError.line,
column: originalError.column,
source: basename(path),
Expand Down Expand Up @@ -364,3 +365,40 @@ export class Typechecker {
.map<TaskResultPack>(i => [i.id, i.result, { typecheck: true }])
}
}

function findGeneratedPosition(traceMap: TraceMap, { line, column, source }: { line: number; column: number; source: string }) {
const found = generatedPositionFor(traceMap, {
line,
column,
source,
})
if (found.line !== null) {
return found
}
// find the next source token position when the exact error position doesn't exist in source map.
// this can happen, for example, when the type error is in the comment "// @ts-expect-error"
// and comments are stripped away in the generated code.
const mappings: (EachMapping & { originalLine: number })[] = []
eachMapping(traceMap, (m) => {
if (
m.source === source
&& m.originalLine !== null
&& m.originalColumn !== null
&& (line === m.originalLine ? column < m.originalColumn : line < m.originalLine)
) {
mappings.push(m)
}
})
const next = mappings
.sort((a, b) =>
a.originalLine === b.originalLine ? a.originalColumn - b.originalColumn : a.originalLine - b.originalLine,
)
.at(0)
if (next) {
return {
line: next.generatedLine,
column: next.generatedColumn,
}
}
return { line: null, column: null }
}
1 change: 1 addition & 0 deletions test/typescript/failing/expect-error.test-d.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { expectTypeOf, test } from 'vitest'

//
test('failing test with expect-error', () => {
// @ts-expect-error expect nothing
expectTypeOf(1).toEqualTypeOf<number>()
Expand Down
10 changes: 5 additions & 5 deletions test/typescript/test/__snapshots__/runner.test.ts.snap
Original file line number Diff line number Diff line change
Expand Up @@ -24,12 +24,12 @@ TypeCheckError: This expression is not callable. Type 'ExpectVoid<number>' has n
exports[`should fail > typecheck files 3`] = `
" FAIL expect-error.test-d.ts > failing test with expect-error
TypeCheckError: Unused '@ts-expect-error' directive.
❯ expect-error.test-d.ts:4:3
2|
3| test('failing test with expect-error', () => {
4| // @ts-expect-error expect nothing
❯ expect-error.test-d.ts:5:3
3| //
4| test('failing test with expect-error', () => {
5| // @ts-expect-error expect nothing
| ^
5| expectTypeOf(1).toEqualTypeOf<number>()"
6| expectTypeOf(1).toEqualTypeOf<number>()"
`;
exports[`should fail > typecheck files 4`] = `
Expand Down
14 changes: 14 additions & 0 deletions test/typescript/vitest.config.fails.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import { defineConfig } from 'vitest/config'

// pnpm -C test/typescript test -- -c vitest.config.fails.ts
export default defineConfig({
test: {
dir: './failing',
typecheck: {
enabled: true,
allowJs: true,
include: ['**/*.test-d.*'],
tsconfig: './tsconfig.fails.json',
},
},
})

0 comments on commit 27d340a

Please sign in to comment.