1- import { spawnSync } from 'node:child_process' ;
21import {
32 existsSync ,
43 mkdtempSync ,
@@ -16,7 +15,6 @@ import {
1615 getVitestTestsByProject ,
1716 VITEST_PROJECT_NAMES ,
1817} from './discover-test-files.mjs' ;
19- import { resolvePackageBin } from './resolve-package-bin.mjs' ;
2018import { resolveTypeRoots } from './resolve-type-roots.mjs' ;
2119import {
2220 findVitestIsolationOptOuts ,
@@ -221,6 +219,41 @@ function getTypecheckConfigPath( testFile ) {
221219 return path . join ( ROOT_DIR , 'tools/monorepo/tsconfig/tsconfig.base.json' ) ;
222220}
223221
222+ const diagnosticsHost = {
223+ getCanonicalFileName : ( fileName ) => fileName ,
224+ getCurrentDirectory : ( ) => ROOT_DIR ,
225+ getNewLine : ( ) => '\n' ,
226+ } ;
227+
228+ function runTypecheck ( configPath ) {
229+ const config = typescript . getParsedCommandLineOfConfigFile (
230+ configPath ,
231+ { } ,
232+ {
233+ ...typescript . sys ,
234+ onUnRecoverableConfigFileDiagnostic : ( diagnostic ) => {
235+ throw new Error (
236+ typescript . formatDiagnostics (
237+ [ diagnostic ] ,
238+ diagnosticsHost
239+ )
240+ ) ;
241+ } ,
242+ }
243+ ) ;
244+ const host = typescript . createCompilerHost ( config . options ) ;
245+ // Match the CLI's parsing mode for a typecheck without editor tooling.
246+ host . jsDocParsingMode = typescript . JSDocParsingMode . ParseForTypeErrors ;
247+ const program = typescript . createProgram ( {
248+ rootNames : config . fileNames ,
249+ options : config . options ,
250+ projectReferences : config . projectReferences ,
251+ configFileParsingDiagnostics : config . errors ,
252+ host,
253+ } ) ;
254+ return typescript . getPreEmitDiagnostics ( program ) ;
255+ }
256+
224257let typescriptTestCount = 0 ;
225258
226259for ( const projectName of VITEST_PROJECT_NAMES ) {
@@ -339,38 +372,27 @@ for ( const projectName of VITEST_PROJECT_NAMES ) {
339372 "declare module 'deep-freeze' { export default function deepFreeze<T>(value: T): T; }" ,
340373 ] . join ( '\n' )
341374 ) ;
342- const typecheckArguments = [
343- resolvePackageBin ( 'typescript' , 'tsc6' ) ,
344- '--project' ,
345- configPath ,
346- '--pretty' ,
347- 'false' ,
348- ] ;
349- const runTypecheck = ( ) =>
350- spawnSync ( process . execPath , typecheckArguments , {
351- cwd : ROOT_DIR ,
352- encoding : 'utf8' ,
353- } ) ;
354375 writeFileSync ( configPath , JSON . stringify ( typecheckConfig ) ) ;
355- let result = runTypecheck ( ) ;
376+ let diagnostics = runTypecheck ( configPath ) ;
356377
357- const output = `${ result . stdout ?? '' } ${ result . stderr ?? '' } ` ;
358- if ( result . status !== 0 && / T S 6 3 (?: 0 5 | 1 0 ) / . test ( output ) ) {
378+ if (
379+ diagnostics . some (
380+ ( { code } ) => code === 6305 || code === 6310
381+ )
382+ ) {
359383 // A dependency cycle can make TypeScript treat routed tests as
360384 // source files owned by a referenced package project. The package
361385 // declarations were built before this check, so fall back to normal
362386 // module resolution when that project-ownership check fails.
363387 typecheckConfig . references = [ ] ;
364388 writeFileSync ( configPath , JSON . stringify ( typecheckConfig ) ) ;
365- result = runTypecheck ( ) ;
389+ diagnostics = runTypecheck ( configPath ) ;
366390 }
367391
368- if ( result . error ) {
369- throw result . error ;
370- }
371- if ( result . status !== 0 ) {
372- process . stderr . write ( result . stdout ?? '' ) ;
373- process . stderr . write ( result . stderr ?? '' ) ;
392+ if ( diagnostics . length ) {
393+ process . stderr . write (
394+ typescript . formatDiagnostics ( diagnostics , diagnosticsHost )
395+ ) ;
374396 throw new Error ( 'TypeScript test graph validation failed.' ) ;
375397 }
376398 } finally {
0 commit comments