mirror of
https://github.com/microsoft/TypeScript.git
synced 2025-11-18 17:21:48 +00:00
Add SolutionBuilderHostBase.getCustomTransformers to be used when emitting. (#44489)
This allows not having to specify the transformers during normal watch scneario Builds on top of #43984
This commit is contained in:
@@ -85,6 +85,7 @@ namespace ts {
|
||||
* writeFileCallback
|
||||
*/
|
||||
writeFile?(path: string, data: string, writeByteOrderMark?: boolean): void;
|
||||
getCustomTransformers?: (project: string) => CustomTransformers | undefined;
|
||||
|
||||
getModifiedTime(fileName: string): Date | undefined;
|
||||
setModifiedTime(fileName: string, date: Date): void;
|
||||
@@ -785,7 +786,7 @@ namespace ts {
|
||||
emit: (targetSourceFile, writeFile, cancellationToken, emitOnlyDtsFiles, customTransformers) => {
|
||||
if (targetSourceFile || emitOnlyDtsFiles) {
|
||||
return withProgramOrUndefined(
|
||||
program => program.emit(targetSourceFile, writeFile, cancellationToken, emitOnlyDtsFiles, customTransformers)
|
||||
program => program.emit(targetSourceFile, writeFile, cancellationToken, emitOnlyDtsFiles, customTransformers || state.host.getCustomTransformers?.(project))
|
||||
);
|
||||
}
|
||||
executeSteps(BuildStep.SemanticDiagnostics, cancellationToken);
|
||||
@@ -921,7 +922,7 @@ namespace ts {
|
||||
(name, text, writeByteOrderMark) => outputFiles.push({ name, text, writeByteOrderMark }),
|
||||
cancellationToken,
|
||||
/*emitOnlyDts*/ false,
|
||||
customTransformers
|
||||
customTransformers || state.host.getCustomTransformers?.(project)
|
||||
);
|
||||
// Don't emit .d.ts if there are decl file errors
|
||||
if (declDiagnostics) {
|
||||
@@ -1060,7 +1061,7 @@ namespace ts {
|
||||
const refName = resolveProjectName(state, ref.path);
|
||||
return parseConfigFile(state, refName, toResolvedConfigFilePath(state, refName));
|
||||
},
|
||||
customTransformers
|
||||
customTransformers || state.host.getCustomTransformers?.(project)
|
||||
);
|
||||
|
||||
if (isString(outputFiles)) {
|
||||
|
||||
@@ -141,6 +141,7 @@
|
||||
"unittests/tsbuildWatch/noEmit.ts",
|
||||
"unittests/tsbuildWatch/noEmitOnError.ts",
|
||||
"unittests/tsbuildWatch/programUpdates.ts",
|
||||
"unittests/tsbuildWatch/publicApi.ts",
|
||||
"unittests/tsbuildWatch/reexport.ts",
|
||||
"unittests/tsbuildWatch/watchEnvironment.ts",
|
||||
"unittests/tsc/composite.ts",
|
||||
|
||||
@@ -0,0 +1,115 @@
|
||||
namespace ts.tscWatch {
|
||||
it("unittests:: tsbuildWatch:: watchMode:: Public API with custom transformers", () => {
|
||||
const solution: File = {
|
||||
path: `${projectRoot}/tsconfig.json`,
|
||||
content: JSON.stringify({
|
||||
references: [
|
||||
{ path: "./shared/tsconfig.json" },
|
||||
{ path: "./webpack/tsconfig.json" }
|
||||
],
|
||||
files: []
|
||||
})
|
||||
};
|
||||
const sharedConfig: File = {
|
||||
path: `${projectRoot}/shared/tsconfig.json`,
|
||||
content: JSON.stringify({
|
||||
compilerOptions: { composite: true },
|
||||
})
|
||||
};
|
||||
const sharedIndex: File = {
|
||||
path: `${projectRoot}/shared/index.ts`,
|
||||
content: `export function f1() { }
|
||||
export class c { }
|
||||
export enum e { }
|
||||
// leading
|
||||
export function f2() { } // trailing`
|
||||
};
|
||||
const webpackConfig: File = {
|
||||
path: `${projectRoot}/webpack/tsconfig.json`,
|
||||
content: JSON.stringify({
|
||||
compilerOptions: { composite: true, },
|
||||
references: [{ path: "../shared/tsconfig.json" }]
|
||||
})
|
||||
};
|
||||
const webpackIndex: File = {
|
||||
path: `${projectRoot}/webpack/index.ts`,
|
||||
content: `export function f2() { }
|
||||
export class c2 { }
|
||||
export enum e2 { }
|
||||
// leading
|
||||
export function f22() { } // trailing`
|
||||
};
|
||||
const commandLineArgs = ["--b", "--w"];
|
||||
const { sys, baseline, oldSnap } = createBaseline(createWatchedSystem([libFile, solution, sharedConfig, sharedIndex, webpackConfig, webpackIndex], { currentDirectory: projectRoot }));
|
||||
const { cb, getPrograms } = commandLineCallbacks(sys);
|
||||
const buildHost = createSolutionBuilderWithWatchHost(
|
||||
sys,
|
||||
/*createProgram*/ undefined,
|
||||
createDiagnosticReporter(sys, /*pretty*/ true),
|
||||
createBuilderStatusReporter(sys, /*pretty*/ true),
|
||||
createWatchStatusReporter(sys, /*pretty*/ true)
|
||||
);
|
||||
buildHost.afterProgramEmitAndDiagnostics = cb;
|
||||
buildHost.afterEmitBundle = cb;
|
||||
buildHost.getCustomTransformers = getCustomTransformers;
|
||||
const builder = createSolutionBuilderWithWatch(buildHost, [solution.path], { verbose: true });
|
||||
builder.build();
|
||||
runWatchBaseline({
|
||||
scenario: "publicApi",
|
||||
subScenario: "with custom transformers",
|
||||
commandLineArgs,
|
||||
sys,
|
||||
baseline,
|
||||
oldSnap,
|
||||
getPrograms,
|
||||
changes: [
|
||||
{
|
||||
caption: "change to shared",
|
||||
change: sys => sys.prependFile(sharedIndex.path, "export function fooBar() {}"),
|
||||
timeouts: sys => {
|
||||
sys.checkTimeoutQueueLengthAndRun(1); // Shared
|
||||
sys.checkTimeoutQueueLengthAndRun(1); // webpack
|
||||
sys.checkTimeoutQueueLengthAndRun(1); // solution
|
||||
sys.checkTimeoutQueueLength(0);
|
||||
}
|
||||
}
|
||||
],
|
||||
watchOrSolution: builder
|
||||
});
|
||||
|
||||
function getCustomTransformers(project: string): CustomTransformers {
|
||||
const before: TransformerFactory<SourceFile> = context => {
|
||||
return file => visitEachChild(file, visit, context);
|
||||
function visit(node: Node): VisitResult<Node> {
|
||||
switch (node.kind) {
|
||||
case SyntaxKind.FunctionDeclaration:
|
||||
return visitFunction(node as FunctionDeclaration);
|
||||
default:
|
||||
return visitEachChild(node, visit, context);
|
||||
}
|
||||
}
|
||||
function visitFunction(node: FunctionDeclaration) {
|
||||
addSyntheticLeadingComment(node, SyntaxKind.MultiLineCommentTrivia, `@before${project}`, /*hasTrailingNewLine*/ true);
|
||||
return node;
|
||||
}
|
||||
};
|
||||
|
||||
const after: TransformerFactory<SourceFile> = context => {
|
||||
return file => visitEachChild(file, visit, context);
|
||||
function visit(node: Node): VisitResult<Node> {
|
||||
switch (node.kind) {
|
||||
case SyntaxKind.VariableStatement:
|
||||
return visitVariableStatement(node as VariableStatement);
|
||||
default:
|
||||
return visitEachChild(node, visit, context);
|
||||
}
|
||||
}
|
||||
function visitVariableStatement(node: VariableStatement) {
|
||||
addSyntheticLeadingComment(node, SyntaxKind.SingleLineCommentTrivia, `@after${project}`);
|
||||
return node;
|
||||
}
|
||||
};
|
||||
return { before: [before], after: [after] };
|
||||
}
|
||||
});
|
||||
}
|
||||
Reference in New Issue
Block a user