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:
Sheetal Nandi
2021-06-07 15:32:39 -07:00
committed by GitHub
parent be2fec1386
commit dab2ffc45a
6 changed files with 505 additions and 3 deletions
+4 -3
View File
@@ -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)) {
+1
View File
@@ -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] };
}
});
}