1namespace ts { 2 describe("unittests:: tsbuild:: Public API with custom transformers when passed to build", () => { 3 let sys: TscCompileSystem; 4 before(() => { 5 const inputFs = loadProjectFromFiles({ 6 "/src/tsconfig.json": JSON.stringify({ 7 references: [ 8 { path: "./shared/tsconfig.json" }, 9 { path: "./webpack/tsconfig.json" } 10 ], 11 files: [] 12 }), 13 "/src/shared/tsconfig.json": JSON.stringify({ 14 compilerOptions: { composite: true }, 15 }), 16 "/src/shared/index.ts": `export function f1() { } 17export class c { } 18export enum e { } 19// leading 20export function f2() { } // trailing`, 21 "/src/webpack/tsconfig.json": JSON.stringify({ 22 compilerOptions: { 23 composite: true, 24 }, 25 references: [{ path: "../shared/tsconfig.json" }] 26 }), 27 "/src/webpack/index.ts": `export function f2() { } 28export class c2 { } 29export enum e2 { } 30// leading 31export function f22() { } // trailing`, 32 }).makeReadonly(); 33 const fs = inputFs.shadow(); 34 35 // Create system 36 sys = new fakes.System(fs, { executingFilePath: "/lib/tsc" }) as TscCompileSystem; 37 fakes.patchHostForBuildInfoReadWrite(sys); 38 const commandLineArgs = ["--b", "/src/tsconfig.json"]; 39 sys.write(`${sys.getExecutingFilePath()} ${commandLineArgs.join(" ")}\n`); 40 sys.exit = exitCode => sys.exitCode = exitCode; 41 const writtenFiles = sys.writtenFiles = new Set(); 42 const originalWriteFile = sys.writeFile; 43 sys.writeFile = (fileName, content, writeByteOrderMark) => { 44 const path = toPathWithSystem(sys, fileName); 45 assert.isFalse(writtenFiles.has(path)); 46 writtenFiles.add(path); 47 return originalWriteFile.call(sys, fileName, content, writeByteOrderMark); 48 }; 49 const { cb, getPrograms } = commandLineCallbacks(sys, /*originalReadCall*/ undefined); 50 const buildHost = createSolutionBuilderHost( 51 sys, 52 /*createProgram*/ undefined, 53 createDiagnosticReporter(sys, /*pretty*/ true), 54 createBuilderStatusReporter(sys, /*pretty*/ true), 55 (errorCount, filesInError) => sys.write(getErrorSummaryText(errorCount, filesInError, sys.newLine, sys)) 56 ); 57 buildHost.afterProgramEmitAndDiagnostics = cb; 58 buildHost.afterEmitBundle = cb; 59 const builder = createSolutionBuilder(buildHost, [commandLineArgs[1]], { verbose: true }); 60 const exitStatus = builder.build(/*project*/ undefined, /*cancellationToken*/ undefined, /*writeFile*/ undefined, getCustomTransformers); 61 sys.exit(exitStatus); 62 sys.write(`exitCode:: ExitStatus.${ExitStatus[sys.exitCode as ExitStatus]}\n`); 63 const baseline: string[] = []; 64 tscWatch.baselinePrograms(baseline, getPrograms, emptyArray, /*baselineDependencies*/ false); 65 sys.write(baseline.join("\n")); 66 fs.makeReadonly(); 67 sys.baseLine = () => { 68 const baseFsPatch = inputFs.diff(/*base*/ undefined, { baseIsNotShadowRoot: true }); 69 const patch = fs.diff(inputFs, { includeChangedFileWithSameContent: true }); 70 return { 71 file: `tsbuild/publicAPI/build-with-custom-transformers.js`, 72 text: `Input:: 73${baseFsPatch ? vfs.formatPatch(baseFsPatch) : ""} 74 75Output:: 76${sys.output.join("")} 77 78${patch ? vfs.formatPatch(patch) : ""}` 79 }; 80 }; 81 82 function getCustomTransformers(project: string): CustomTransformers { 83 const before: TransformerFactory<SourceFile> = context => { 84 return file => visitEachChild(file, visit, context); 85 function visit(node: Node): VisitResult<Node> { 86 switch (node.kind) { 87 case SyntaxKind.FunctionDeclaration: 88 return visitFunction(node as FunctionDeclaration); 89 default: 90 return visitEachChild(node, visit, context); 91 } 92 } 93 function visitFunction(node: FunctionDeclaration) { 94 addSyntheticLeadingComment(node, SyntaxKind.MultiLineCommentTrivia, `@before${project}`, /*hasTrailingNewLine*/ true); 95 return node; 96 } 97 }; 98 99 const after: TransformerFactory<SourceFile> = context => { 100 return file => visitEachChild(file, visit, context); 101 function visit(node: Node): VisitResult<Node> { 102 switch (node.kind) { 103 case SyntaxKind.VariableStatement: 104 return visitVariableStatement(node as VariableStatement); 105 default: 106 return visitEachChild(node, visit, context); 107 } 108 } 109 function visitVariableStatement(node: VariableStatement) { 110 addSyntheticLeadingComment(node, SyntaxKind.SingleLineCommentTrivia, `@after${project}`); 111 return node; 112 } 113 }; 114 return { before: [before], after: [after] }; 115 } 116 }); 117 after(() => { 118 sys = undefined!; 119 }); 120 verifyTscBaseline(() => sys); 121 }); 122} 123