Skip to content

Skip typechecking file when generating declaraiton to get d.ts signature for incremental build #58592

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 7 commits into from
May 21, 2024
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions src/compiler/checker.ts
Original file line number Diff line number Diff line change
@@ -2428,10 +2428,10 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
return visitEachChild(node, markAsSynthetic, /*context*/ undefined);
}

function getEmitResolver(sourceFile: SourceFile, cancellationToken: CancellationToken) {
function getEmitResolver(sourceFile: SourceFile, cancellationToken: CancellationToken, skipDiagnostics?: boolean) {
// 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);
if (!skipDiagnostics) getDiagnostics(sourceFile, cancellationToken);
return emitResolver;
}

11 changes: 10 additions & 1 deletion src/compiler/emitter.ts
Original file line number Diff line number Diff line change
@@ -717,6 +717,11 @@ export function getFirstProjectOutput(configFile: ParsedCommandLine, ignoreCase:
return Debug.fail(`project ${configFile.options.configFilePath} expected to have at least one output`);
}

/** @internal */
export function emitResolverSkipsTypeChecking(emitOnly: boolean | EmitOnly | undefined, forceDtsEmit: boolean | undefined) {
return !!forceDtsEmit && !!emitOnly;
}

/** @internal */
// targetSourceFile is when users only want one file in entire project to be emitted. This is used in compileOnSave feature
export function emitFiles(resolver: EmitResolver, host: EmitHost, targetSourceFile: SourceFile | undefined, { scriptTransformers, declarationTransformers }: EmitTransformers, emitOnly?: boolean | EmitOnly, onlyBuildInfo?: boolean, forceDtsEmit?: boolean): EmitResult {
@@ -848,7 +853,11 @@ 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) {
if (
(emitOnly && !getEmitDeclarations(compilerOptions)) ||
compilerOptions.noCheck ||
emitResolverSkipsTypeChecking(emitOnly, forceDtsEmit)
) {
// 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);
28 changes: 19 additions & 9 deletions src/compiler/program.ts
Original file line number Diff line number Diff line change
@@ -68,6 +68,7 @@ import {
EmitHost,
emitModuleKindIsNonNodeESM,
EmitOnly,
emitResolverSkipsTypeChecking,
EmitResult,
emptyArray,
ensureTrailingDirectorySeparator,
@@ -2870,18 +2871,27 @@ 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);
const typeChecker = getTypeChecker();
const emitResolver = typeChecker.getEmitResolver(
options.outFile ? undefined : sourceFile,
cancellationToken,
emitResolverSkipsTypeChecking(emitOnly, forceDtsEmit),
);

performance.mark("beforeEmit");

const emitResult = emitFiles(
emitResolver,
getEmitHost(writeFileCallback),
sourceFile,
getTransformers(options, customTransformers, emitOnly),
emitOnly,
/*onlyBuildInfo*/ false,
forceDtsEmit,
const emitResult = typeChecker.runWithCancellationToken(
cancellationToken,
() =>
emitFiles(
emitResolver,
getEmitHost(writeFileCallback),
sourceFile,
getTransformers(options, customTransformers, emitOnly),
emitOnly,
/*onlyBuildInfo*/ false,
forceDtsEmit,
),
);

performance.mark("afterEmit");
4 changes: 3 additions & 1 deletion src/compiler/types.ts
Original file line number Diff line number Diff line change
@@ -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): EmitResolver;
/** @internal */ getEmitResolver(sourceFile?: SourceFile, cancellationToken?: CancellationToken, forceDts?: boolean): EmitResolver;

/** @internal */ getNodeCount(): number;
/** @internal */ getIdentifierCount(): number;
@@ -5354,6 +5354,8 @@ export interface TypeChecker {
* and the operation is cancelled, then it should be discarded, otherwise it is safe to keep.
*/
runWithCancellationToken<T>(token: CancellationToken, cb: (checker: TypeChecker) => T): T;
/**@internal */
runWithCancellationToken<T>(token: CancellationToken | undefined, cb: (checker: TypeChecker) => T): T; // eslint-disable-line @typescript-eslint/unified-signatures

/** @internal */ getLocalTypeParametersOfClassOrInterfaceOrTypeAlias(symbol: Symbol): readonly TypeParameter[] | undefined;
/** @internal */ isDeclarationVisible(node: Declaration | AnyImportSyntax): boolean;
6 changes: 3 additions & 3 deletions src/testRunner/unittests/tsc/cancellationToken.ts
Original file line number Diff line number Diff line change
@@ -17,7 +17,7 @@ import {
libFile,
} from "../helpers/virtualFileSystemWithWatch.js";

describe("unittests:: tsc:: builder cancellationToken", () => {
describe("unittests:: tsc:: builder cancellationToken::", () => {
verifyCancellation(/*useBuildInfo*/ true, "when emitting buildInfo");
verifyCancellation(/*useBuildInfo*/ false, "when using state");
function verifyCancellation(useBuildInfo: boolean, scenario: string) {
@@ -41,9 +41,9 @@ describe("unittests:: tsc:: builder cancellationToken", () => {
const cFile: File = {
path: `/user/username/projects/myproject/c.ts`,
content: Utils.dedent`
export class C {
export var C = class CReal {
d = 1;
}`,
};`,
};
const dFile: File = {
path: `/user/username/projects/myproject/d.ts`,
Loading