Skip to content

Commit 096c435

Browse files
authored
feat: support incremental build when composite is true (#416)
1 parent d3c1c16 commit 096c435

File tree

21 files changed

+361
-26
lines changed

21 files changed

+361
-26
lines changed

packages/plugin-dts/src/tsc.ts

Lines changed: 80 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,43 @@ export type EmitDtsOptions = {
1818
footer?: string;
1919
};
2020

21+
async function handleDiagnosticsAndProcessFiles(
22+
diagnostics: readonly ts.Diagnostic[],
23+
configPath: string,
24+
host: ts.CompilerHost,
25+
bundle: boolean,
26+
declarationDir: string,
27+
dtsExtension: string,
28+
banner?: string,
29+
footer?: string,
30+
name?: string,
31+
): Promise<void> {
32+
const diagnosticMessages: string[] = [];
33+
34+
for (const diagnostic of diagnostics) {
35+
const fileLoc = getFileLoc(diagnostic, configPath);
36+
const message = `${fileLoc} - ${color.red('error')} ${color.gray(`TS${diagnostic.code}:`)} ${ts.flattenDiagnosticMessageText(
37+
diagnostic.messageText,
38+
host.getNewLine(),
39+
)}`;
40+
diagnosticMessages.push(message);
41+
}
42+
43+
await processDtsFiles(bundle, declarationDir, dtsExtension, banner, footer);
44+
45+
if (diagnosticMessages.length) {
46+
logger.error(
47+
`Failed to emit declaration files. ${color.gray(`(${name})`)}`,
48+
);
49+
50+
for (const message of diagnosticMessages) {
51+
logger.error(message);
52+
}
53+
54+
throw new Error('DTS generation failed');
55+
}
56+
}
57+
2158
export async function emitDts(
2259
options: EmitDtsOptions,
2360
onComplete: (isSuccess: boolean) => void,
@@ -37,6 +74,7 @@ export async function emitDts(
3774

3875
const compilerOptions = {
3976
...rawCompilerOptions,
77+
configFilePath: configPath,
4078
noEmit: false,
4179
declaration: true,
4280
declarationDir,
@@ -111,9 +149,10 @@ export async function emitDts(
111149

112150
const system = { ...ts.sys };
113151

152+
// build mode
114153
if (!isWatch) {
115-
// build mode
116-
if (!build) {
154+
// normal build - npx tsc
155+
if (!build && !compilerOptions.composite) {
117156
const host: ts.CompilerHost = ts.createCompilerHost(compilerOptions);
118157

119158
const program: ts.Program = ts.createProgram({
@@ -132,38 +171,53 @@ export async function emitDts(
132171
.getPreEmitDiagnostics(program)
133172
.concat(emitResult.diagnostics);
134173

135-
const diagnosticMessages: string[] = [];
136-
137-
for (const diagnostic of allDiagnostics) {
138-
const fileLoc = getFileLoc(diagnostic, configPath);
139-
const message = `${fileLoc} - ${color.red('error')} ${color.gray(`TS${diagnostic.code}:`)} ${ts.flattenDiagnosticMessageText(
140-
diagnostic.messageText,
141-
host.getNewLine(),
142-
)}`;
143-
diagnosticMessages.push(message);
144-
}
145-
146-
await processDtsFiles(
174+
await handleDiagnosticsAndProcessFiles(
175+
allDiagnostics,
176+
configPath,
177+
host,
147178
bundle,
148179
declarationDir,
149180
dtsExtension,
150181
banner,
151182
footer,
183+
name,
152184
);
185+
} else if (!build && compilerOptions.composite) {
186+
// incremental build with composite true - npx tsc
187+
const host: ts.CompilerHost =
188+
ts.createIncrementalCompilerHost(compilerOptions);
153189

154-
if (diagnosticMessages.length) {
155-
logger.error(
156-
`Failed to emit declaration files. ${color.gray(`(${name})`)}`,
157-
);
190+
const program = ts.createIncrementalProgram({
191+
rootNames: fileNames,
192+
options: compilerOptions,
193+
configFileParsingDiagnostics: ts.getConfigFileParsingDiagnostics(
194+
configFileParseResult,
195+
),
196+
projectReferences,
197+
host,
198+
createProgram,
199+
});
158200

159-
for (const message of diagnosticMessages) {
160-
logger.error(message);
161-
}
201+
program.emit();
162202

163-
throw new Error('DTS generation failed');
164-
}
203+
const allDiagnostics = program
204+
.getSemanticDiagnostics()
205+
.concat(program.getConfigFileParsingDiagnostics());
206+
207+
await handleDiagnosticsAndProcessFiles(
208+
allDiagnostics,
209+
configPath,
210+
host,
211+
bundle,
212+
declarationDir,
213+
dtsExtension,
214+
banner,
215+
footer,
216+
name,
217+
);
165218
} else {
166-
// incremental build with project references
219+
// incremental build with build project references
220+
// The equivalent of the `--build` flag for the tsc command.
167221
let errorNumber = 0;
168222
const reportErrorSummary = (errorCount: number) => {
169223
errorNumber = errorCount;
@@ -206,7 +260,7 @@ export async function emitDts(
206260
`DTS generated in ${getTimeCost(start)} ${color.gray(`(${name})`)}`,
207261
);
208262
} else {
209-
// watch mode
263+
// watch mode, can also deal with incremental build
210264
if (!build) {
211265
const host = ts.createWatchCompilerHost(
212266
configPath,
@@ -219,7 +273,7 @@ export async function emitDts(
219273

220274
ts.createWatchProgram(host);
221275
} else {
222-
// incremental build with project references
276+
// incremental build watcher with build project references
223277
const host = ts.createSolutionBuilderWithWatchHost(
224278
system,
225279
createProgram,

pnpm-lock.yaml

Lines changed: 8 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
export * from './utils/numbers';
2+
export * from './utils/strings';
3+
export * from './sum';
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
import { num1, num2, num3 } from './utils/numbers';
2+
import { str1, str2, str3 } from './utils/strings';
3+
4+
export const numSum = num1 + num2 + num3;
5+
export const strSum = str1 + str2 + str3;
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
export const num1 = 1;
2+
export const num2 = 2;
3+
export const num3 = 3;
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
export const str1 = 'str1';
2+
export const str2 = 'str2';
3+
export const str3 = 'str3';
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
{
2+
"name": "dts-composite-abort-on-error-test",
3+
"version": "1.0.0",
4+
"private": true,
5+
"type": "module"
6+
}
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
import { defineConfig } from '@rslib/core';
2+
import { generateBundleEsmConfig } from 'test-helper';
3+
4+
export default defineConfig({
5+
lib: [
6+
generateBundleEsmConfig({
7+
bundle: false,
8+
dts: {
9+
bundle: false,
10+
abortOnError: false,
11+
},
12+
}),
13+
],
14+
source: {
15+
entry: {
16+
index: ['./src/**'],
17+
},
18+
},
19+
});
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
export interface A {
2+
a: number;
3+
}
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
import type { A } from './const';
2+
3+
export const getA = (item: A) => {
4+
item.a = '0';
5+
return item;
6+
};

0 commit comments

Comments
 (0)