From ca1ff15a8e0d7db51db1fe3cb49a7ff383a42e93 Mon Sep 17 00:00:00 2001 From: Sheetal Nandi Date: Mon, 20 May 2024 15:51:22 -0700 Subject: [PATCH] Try adding ts-noCheck checks to skipTypeChecking --- src/compiler/checker.ts | 26 +++++++++++++------------- src/compiler/emitter.ts | 18 +++++++++++++----- src/compiler/program.ts | 27 ++++----------------------- src/compiler/types.ts | 2 +- src/compiler/utilities.ts | 22 +++++++++++++++++++++- 5 files changed, 52 insertions(+), 43 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 2201ad4822c38..a4020504f9c07 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -2428,10 +2428,10 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { return visitEachChild(node, markAsSynthetic, /*context*/ undefined); } - function getEmitResolver(sourceFile: SourceFile, cancellationToken: CancellationToken, skipCheck?: boolean) { + function getEmitResolver(sourceFile: SourceFile, cancellationToken: CancellationToken) { // Ensure we have all the type information in place for this file so that all the // emitter questions of this resolver will return the right information. - getDiagnostics(sourceFile, cancellationToken, skipCheck); + getDiagnostics(sourceFile, cancellationToken); return emitResolver; } @@ -47483,10 +47483,10 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { tracing?.pop(); } - function checkSourceFile(node: SourceFile, skipCheck: boolean | undefined) { + function checkSourceFile(node: SourceFile) { tracing?.push(tracing.Phase.Check, "checkSourceFile", { path: node.path }, /*separateBeginAndEnd*/ true); performance.mark("beforeCheck"); - checkSourceFileWorker(node, skipCheck); + checkSourceFileWorker(node); performance.mark("afterCheck"); performance.measure("Check", "beforeCheck", "afterCheck"); tracing?.pop(); @@ -47511,10 +47511,10 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } // Fully type check a source file and collect the relevant diagnostics. - function checkSourceFileWorker(node: SourceFile, skipCheck: boolean | undefined) { + function checkSourceFileWorker(node: SourceFile) { const links = getNodeLinks(node); if (!(links.flags & NodeCheckFlags.TypeChecked)) { - if (skipCheck || skipTypeChecking(node, compilerOptions, host)) { + if (skipTypeChecking(node, compilerOptions, host)) { return; } @@ -47578,13 +47578,13 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } } - function getDiagnostics(sourceFile: SourceFile, ct: CancellationToken, skipCheck?: boolean): Diagnostic[] { + function getDiagnostics(sourceFile: SourceFile, ct: CancellationToken): Diagnostic[] { try { // Record the cancellation token so it can be checked later on during checkSourceElement. // Do this in a finally block so we can ensure that it gets reset back to nothing after // this call is done. cancellationToken = ct; - return getDiagnosticsWorker(sourceFile, skipCheck); + return getDiagnosticsWorker(sourceFile); } finally { cancellationToken = undefined; @@ -47599,7 +47599,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { deferredDiagnosticsCallbacks = []; } - function checkSourceFileWithEagerDiagnostics(sourceFile: SourceFile, skipCheck?: boolean) { + function checkSourceFileWithEagerDiagnostics(sourceFile: SourceFile) { ensurePendingDiagnosticWorkComplete(); // then setup diagnostics for immediate invocation (as we are about to collect them, and // this avoids the overhead of longer-lived callbacks we don't need to allocate) @@ -47608,11 +47608,11 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { // thus much more likely retaining the same union ordering as before we had lazy diagnostics) const oldAddLazyDiagnostics = addLazyDiagnostic; addLazyDiagnostic = cb => cb(); - checkSourceFile(sourceFile, skipCheck); + checkSourceFile(sourceFile); addLazyDiagnostic = oldAddLazyDiagnostics; } - function getDiagnosticsWorker(sourceFile: SourceFile, skipCheck: boolean | undefined): Diagnostic[] { + function getDiagnosticsWorker(sourceFile: SourceFile): Diagnostic[] { if (sourceFile) { ensurePendingDiagnosticWorkComplete(); // Some global diagnostics are deferred until they are needed and @@ -47621,7 +47621,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { const previousGlobalDiagnostics = diagnostics.getGlobalDiagnostics(); const previousGlobalDiagnosticsSize = previousGlobalDiagnostics.length; - checkSourceFileWithEagerDiagnostics(sourceFile, skipCheck); + checkSourceFileWithEagerDiagnostics(sourceFile); const semanticDiagnostics = diagnostics.getDiagnostics(sourceFile.fileName); const currentGlobalDiagnostics = diagnostics.getGlobalDiagnostics(); @@ -47642,7 +47642,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { // Global diagnostics are always added when a file is not provided to // getDiagnostics - forEach(host.getSourceFiles(), sourceFile => checkSourceFileWithEagerDiagnostics(sourceFile, skipCheck)); + forEach(host.getSourceFiles(), checkSourceFileWithEagerDiagnostics); return diagnostics.getDiagnostics(); } diff --git a/src/compiler/emitter.ts b/src/compiler/emitter.ts index 03fe0e5e3859e..55c4cb9387450 100644 --- a/src/compiler/emitter.ts +++ b/src/compiler/emitter.ts @@ -21,6 +21,7 @@ import { CallExpression, CallSignatureDeclaration, canHaveLocals, + canIncludeBindAndCheckDiagnsotics, CaseBlock, CaseClause, CaseOrDefaultClause, @@ -848,11 +849,18 @@ export function emitFiles(resolver: EmitResolver, host: EmitHost, targetSourceFi const filesForEmit = forceDtsEmit ? sourceFiles : filter(sourceFiles, isSourceFileNotJson); // Setup and perform the transformation to retrieve declarations from the input files const inputListOrBundle = compilerOptions.outFile ? [factory.createBundle(filesForEmit)] : filesForEmit; - if ((emitOnly && !getEmitDeclarations(compilerOptions)) || compilerOptions.noCheck) { - // Checker wont collect the linked aliases since thats only done when declaration is enabled and checking is performed. - // Do that here when emitting only dts files - filesForEmit.forEach(collectLinkedAliases); - } + // Checker wont collect the linked aliases since thats only done when declaration is enabled and checking is performed. + // Do that here when emitting only dts files + filesForEmit.forEach(sourceFile => { + if ( + (emitOnly && !getEmitDeclarations(compilerOptions)) || + compilerOptions.noCheck || + !canIncludeBindAndCheckDiagnsotics(sourceFile, compilerOptions) + ) { + collectLinkedAliases(sourceFile); + } + }); + const declarationTransform = transformNodes(resolver, host, factory, compilerOptions, inputListOrBundle, declarationTransformers, /*allowDtsFiles*/ false); if (length(declarationTransform.diagnostics)) { for (const diagnostic of declarationTransform.diagnostics!) { diff --git a/src/compiler/program.ts b/src/compiler/program.ts index 9f8ba091c0fb5..c862a3cb70cd4 100644 --- a/src/compiler/program.ts +++ b/src/compiler/program.ts @@ -2870,11 +2870,7 @@ export function createProgram(rootNamesOrOptions: readonly string[] | CreateProg // This is because in the -out scenario all files need to be emitted, and therefore all // files need to be type checked. And the way to specify that all files need to be type // checked is to not pass the file to getEmitResolver. - const emitResolver = getTypeChecker().getEmitResolver( - options.outFile ? undefined : sourceFile, - cancellationToken, - forceDtsEmit && sourceFile && !canIncludeBindAndCheckDiagnsotics(sourceFile), - ); + const emitResolver = getTypeChecker().getEmitResolver(options.outFile ? undefined : sourceFile, cancellationToken); performance.mark("beforeEmit"); @@ -3015,32 +3011,17 @@ export function createProgram(rootNamesOrOptions: readonly string[] | CreateProg // - plain JS: .js files with no // ts-check and checkJs: undefined // - check JS: .js files with either // ts-check or checkJs: true // - external: files that are added by plugins - const includeBindAndCheckDiagnostics = canIncludeBindAndCheckDiagnsotics(sourceFile); - let bindDiagnostics: readonly Diagnostic[] = includeBindAndCheckDiagnostics ? sourceFile.bindDiagnostics : emptyArray; - let checkDiagnostics = includeBindAndCheckDiagnostics ? typeChecker.getDiagnostics(sourceFile, cancellationToken) : emptyArray; + let bindDiagnostics = sourceFile.bindDiagnostics; + let checkDiagnostics = typeChecker.getDiagnostics(sourceFile, cancellationToken); if (isPlainJs) { bindDiagnostics = filter(bindDiagnostics, d => plainJSErrors.has(d.code)); checkDiagnostics = filter(checkDiagnostics, d => plainJSErrors.has(d.code)); } // skip ts-expect-error errors in plain JS files, and skip JSDoc errors except in checked JS - return getMergedBindAndCheckDiagnostics(sourceFile, includeBindAndCheckDiagnostics && !isPlainJs, bindDiagnostics, checkDiagnostics, isCheckJs ? sourceFile.jsDocDiagnostics : undefined); + return getMergedBindAndCheckDiagnostics(sourceFile, !isPlainJs, bindDiagnostics, checkDiagnostics, isCheckJs ? sourceFile.jsDocDiagnostics : undefined); }); } - function canIncludeBindAndCheckDiagnsotics(sourceFile: SourceFile) { - const isJs = sourceFile.scriptKind === ScriptKind.JS || sourceFile.scriptKind === ScriptKind.JSX; - const isCheckJs = isJs && isCheckJsEnabledForFile(sourceFile, options); - const isPlainJs = isPlainJsFile(sourceFile, options.checkJs); - const isTsNoCheck = !!sourceFile.checkJsDirective && sourceFile.checkJsDirective.enabled === false; - - // By default, only type-check .ts, .tsx, Deferred, plain JS, checked JS and External - // - plain JS: .js files with no // ts-check and checkJs: undefined - // - check JS: .js files with either // ts-check or checkJs: true - // - external: files that are added by plugins - return !isTsNoCheck && (sourceFile.scriptKind === ScriptKind.TS || sourceFile.scriptKind === ScriptKind.TSX - || sourceFile.scriptKind === ScriptKind.External || isPlainJs || isCheckJs || sourceFile.scriptKind === ScriptKind.Deferred); - } - function getMergedBindAndCheckDiagnostics(sourceFile: SourceFile, includeBindAndCheckDiagnostics: boolean, ...allDiagnostics: (readonly Diagnostic[] | undefined)[]) { const flatDiagnostics = flatten(allDiagnostics); if (!includeBindAndCheckDiagnostics || !sourceFile.commentDirectives?.length) { diff --git a/src/compiler/types.ts b/src/compiler/types.ts index 573b6846d682a..aae7c5494a17d 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -5264,7 +5264,7 @@ export interface TypeChecker { // Should not be called directly. Should only be accessed through the Program instance. /** @internal */ getDiagnostics(sourceFile?: SourceFile, cancellationToken?: CancellationToken): Diagnostic[]; /** @internal */ getGlobalDiagnostics(): Diagnostic[]; - /** @internal */ getEmitResolver(sourceFile?: SourceFile, cancellationToken?: CancellationToken, skipCheck?: boolean): EmitResolver; + /** @internal */ getEmitResolver(sourceFile?: SourceFile, cancellationToken?: CancellationToken): EmitResolver; /** @internal */ getNodeCount(): number; /** @internal */ getIdentifierCount(): number; diff --git a/src/compiler/utilities.ts b/src/compiler/utilities.ts index 4cf5f0082cd20..76656ef4554e6 100644 --- a/src/compiler/utilities.ts +++ b/src/compiler/utilities.ts @@ -10082,7 +10082,27 @@ export function skipTypeChecking(sourceFile: SourceFile, options: CompilerOption return (options.skipLibCheck && sourceFile.isDeclarationFile || options.skipDefaultLibCheck && sourceFile.hasNoDefaultLib) || options.noCheck || - host.isSourceOfProjectReferenceRedirect(sourceFile.fileName); + host.isSourceOfProjectReferenceRedirect(sourceFile.fileName) || + !canIncludeBindAndCheckDiagnsotics(sourceFile, options); +} + +export function canIncludeBindAndCheckDiagnsotics(sourceFile: SourceFile, options: CompilerOptions) { + if (!!sourceFile.checkJsDirective && sourceFile.checkJsDirective.enabled === false) return false; + if ( + sourceFile.scriptKind === ScriptKind.TS || + sourceFile.scriptKind === ScriptKind.TSX || + sourceFile.scriptKind === ScriptKind.External + ) return true; + + const isJs = sourceFile.scriptKind === ScriptKind.JS || sourceFile.scriptKind === ScriptKind.JSX; + const isCheckJs = isJs && isCheckJsEnabledForFile(sourceFile, options); + const isPlainJs = isPlainJsFile(sourceFile, options.checkJs); + + // By default, only type-check .ts, .tsx, Deferred, plain JS, checked JS and External + // - plain JS: .js files with no // ts-check and checkJs: undefined + // - check JS: .js files with either // ts-check or checkJs: true + // - external: files that are added by plugins + return isPlainJs || isCheckJs || sourceFile.scriptKind === ScriptKind.Deferred; } /** @internal */