1namespace ts { 2 describe("unittests:: tsc:: incremental::", () => { 3 verifyTscSerializedIncrementalEdits({ 4 scenario: "incremental", 5 subScenario: "when passing filename for buildinfo on commandline", 6 fs: () => loadProjectFromFiles({ 7 "/src/project/src/main.ts": "export const x = 10;", 8 "/src/project/tsconfig.json": Utils.dedent` 9 { 10 "compilerOptions": { 11 "target": "es5", 12 "module": "commonjs", 13 }, 14 "include": [ 15 "src/**/*.ts" 16 ] 17 }`, 18 }), 19 commandLineArgs: ["--incremental", "--p", "src/project", "--tsBuildInfoFile", "src/project/.tsbuildinfo", "--explainFiles"], 20 incrementalScenarios: noChangeOnlyRuns 21 }); 22 23 verifyTscSerializedIncrementalEdits({ 24 scenario: "incremental", 25 subScenario: "when passing rootDir from commandline", 26 fs: () => loadProjectFromFiles({ 27 "/src/project/src/main.ts": "export const x = 10;", 28 "/src/project/tsconfig.json": Utils.dedent` 29 { 30 "compilerOptions": { 31 "incremental": true, 32 "outDir": "dist", 33 }, 34 }`, 35 }), 36 commandLineArgs: ["--p", "src/project", "--rootDir", "src/project/src"], 37 incrementalScenarios: noChangeOnlyRuns 38 }); 39 40 verifyTscSerializedIncrementalEdits({ 41 scenario: "incremental", 42 subScenario: "with only dts files", 43 fs: () => loadProjectFromFiles({ 44 "/src/project/src/main.d.ts": "export const x = 10;", 45 "/src/project/src/another.d.ts": "export const y = 10;", 46 "/src/project/tsconfig.json": "{}", 47 }), 48 commandLineArgs: ["--incremental", "--p", "src/project"], 49 incrementalScenarios: [ 50 noChangeRun, 51 { 52 buildKind: BuildKind.IncrementalDtsUnchanged, 53 modifyFs: fs => appendText(fs, "/src/project/src/main.d.ts", "export const xy = 100;") 54 } 55 ] 56 }); 57 58 verifyTscSerializedIncrementalEdits({ 59 scenario: "incremental", 60 subScenario: "when passing rootDir is in the tsconfig", 61 fs: () => loadProjectFromFiles({ 62 "/src/project/src/main.ts": "export const x = 10;", 63 "/src/project/tsconfig.json": Utils.dedent` 64 { 65 "compilerOptions": { 66 "incremental": true, 67 "outDir": "./built", 68 "rootDir": "./" 69 }, 70 }`, 71 }), 72 commandLineArgs: ["--p", "src/project"], 73 incrementalScenarios: noChangeOnlyRuns 74 }); 75 76 describe("with noEmitOnError", () => { 77 let projFs: vfs.FileSystem; 78 before(() => { 79 projFs = loadProjectFromDisk("tests/projects/noEmitOnError"); 80 }); 81 after(() => { 82 projFs = undefined!; 83 }); 84 85 function verifyNoEmitOnError(subScenario: string, fixModifyFs: TscIncremental["modifyFs"], modifyFs?: TscIncremental["modifyFs"]) { 86 verifyTscSerializedIncrementalEdits({ 87 scenario: "incremental", 88 subScenario, 89 fs: () => projFs, 90 commandLineArgs: ["--incremental", "-p", "src"], 91 modifyFs, 92 incrementalScenarios: [ 93 noChangeRun, 94 { 95 buildKind: BuildKind.IncrementalDtsUnchanged, 96 modifyFs: fixModifyFs 97 }, 98 noChangeRun, 99 ], 100 baselinePrograms: true 101 }); 102 } 103 verifyNoEmitOnError( 104 "with noEmitOnError syntax errors", 105 fs => fs.writeFileSync("/src/src/main.ts", `import { A } from "../shared/types/db"; 106const a = { 107 lastName: 'sdsd' 108};`, "utf-8") 109 ); 110 111 verifyNoEmitOnError( 112 "with noEmitOnError semantic errors", 113 fs => fs.writeFileSync("/src/src/main.ts", `import { A } from "../shared/types/db"; 114const a: string = "hello";`, "utf-8"), 115 fs => fs.writeFileSync("/src/src/main.ts", `import { A } from "../shared/types/db"; 116const a: string = 10;`, "utf-8"), 117 ); 118 }); 119 120 describe("when noEmit changes between compilation", () => { 121 verifyNoEmitChanges({ incremental: true }); 122 verifyNoEmitChanges({ incremental: true, declaration: true }); 123 verifyNoEmitChanges({ composite: true }); 124 125 function verifyNoEmitChanges(compilerOptions: CompilerOptions) { 126 const noChangeRunWithNoEmit: TscIncremental = { 127 subScenario: "No Change run with noEmit", 128 commandLineArgs: ["--p", "src/project", "--noEmit"], 129 ...noChangeRun, 130 }; 131 const noChangeRunWithEmit: TscIncremental = { 132 subScenario: "No Change run with emit", 133 commandLineArgs: ["--p", "src/project"], 134 ...noChangeRun, 135 }; 136 let optionsString = ""; 137 for (const key in compilerOptions) { 138 if (hasProperty(compilerOptions, key)) { 139 optionsString += ` ${key}`; 140 } 141 } 142 143 verifyTscSerializedIncrementalEdits({ 144 scenario: "incremental", 145 subScenario: `noEmit changes${optionsString}`, 146 commandLineArgs: ["--p", "src/project"], 147 fs, 148 incrementalScenarios: [ 149 noChangeRunWithNoEmit, 150 noChangeRunWithNoEmit, 151 { 152 subScenario: "Introduce error but still noEmit", 153 commandLineArgs: ["--p", "src/project", "--noEmit"], 154 modifyFs: fs => replaceText(fs, "/src/project/src/class.ts", "prop", "prop1"), 155 buildKind: BuildKind.IncrementalDtsChange 156 }, 157 { 158 subScenario: "Fix error and emit", 159 modifyFs: fs => replaceText(fs, "/src/project/src/class.ts", "prop1", "prop"), 160 buildKind: BuildKind.IncrementalDtsChange 161 }, 162 noChangeRunWithEmit, 163 noChangeRunWithNoEmit, 164 noChangeRunWithNoEmit, 165 noChangeRunWithEmit, 166 { 167 subScenario: "Introduce error and emit", 168 modifyFs: fs => replaceText(fs, "/src/project/src/class.ts", "prop", "prop1"), 169 buildKind: BuildKind.IncrementalDtsChange 170 }, 171 noChangeRunWithEmit, 172 noChangeRunWithNoEmit, 173 noChangeRunWithNoEmit, 174 noChangeRunWithEmit, 175 { 176 subScenario: "Fix error and no emit", 177 commandLineArgs: ["--p", "src/project", "--noEmit"], 178 modifyFs: fs => replaceText(fs, "/src/project/src/class.ts", "prop1", "prop"), 179 buildKind: BuildKind.IncrementalDtsChange 180 }, 181 noChangeRunWithEmit, 182 noChangeRunWithNoEmit, 183 noChangeRunWithNoEmit, 184 noChangeRunWithEmit, 185 ], 186 }); 187 188 verifyTscSerializedIncrementalEdits({ 189 scenario: "incremental", 190 subScenario: `noEmit changes with initial noEmit${optionsString}`, 191 commandLineArgs: ["--p", "src/project", "--noEmit"], 192 fs, 193 incrementalScenarios: [ 194 noChangeRunWithEmit, 195 { 196 subScenario: "Introduce error with emit", 197 commandLineArgs: ["--p", "src/project"], 198 modifyFs: fs => replaceText(fs, "/src/project/src/class.ts", "prop", "prop1"), 199 buildKind: BuildKind.IncrementalDtsChange 200 }, 201 { 202 subScenario: "Fix error and no emit", 203 modifyFs: fs => replaceText(fs, "/src/project/src/class.ts", "prop1", "prop"), 204 buildKind: BuildKind.IncrementalDtsChange 205 }, 206 noChangeRunWithEmit, 207 ], 208 }); 209 210 function fs() { 211 return loadProjectFromFiles({ 212 "/src/project/src/class.ts": Utils.dedent` 213 export class classC { 214 prop = 1; 215 }`, 216 "/src/project/src/indirectClass.ts": Utils.dedent` 217 import { classC } from './class'; 218 export class indirectClass { 219 classC = new classC(); 220 }`, 221 "/src/project/src/directUse.ts": Utils.dedent` 222 import { indirectClass } from './indirectClass'; 223 new indirectClass().classC.prop;`, 224 "/src/project/src/indirectUse.ts": Utils.dedent` 225 import { indirectClass } from './indirectClass'; 226 new indirectClass().classC.prop;`, 227 "/src/project/src/noChangeFile.ts": Utils.dedent` 228 export function writeLog(s: string) { 229 }`, 230 "/src/project/src/noChangeFileWithEmitSpecificError.ts": Utils.dedent` 231 function someFunc(arguments: boolean, ...rest: any[]) { 232 }`, 233 "/src/project/tsconfig.json": JSON.stringify({ compilerOptions }), 234 }); 235 } 236 } 237 }); 238 239 const jsxLibraryContent = ` 240export {}; 241declare global { 242 namespace JSX { 243 interface Element {} 244 interface IntrinsicElements { 245 div: { 246 propA?: boolean; 247 }; 248 } 249 } 250}`; 251 252 verifyTsc({ 253 scenario: "react-jsx-emit-mode", 254 subScenario: "with no backing types found doesn't crash", 255 fs: () => loadProjectFromFiles({ 256 "/src/project/node_modules/react/jsx-runtime.js": "export {}", // js needs to be present so there's a resolution result 257 "/src/project/node_modules/@types/react/index.d.ts": jsxLibraryContent, // doesn't contain a jsx-runtime definition 258 "/src/project/src/index.tsx": `export const App = () => <div propA={true}></div>;`, 259 "/src/project/tsconfig.json": JSON.stringify({ compilerOptions: { module: "commonjs", jsx: "react-jsx", incremental: true, jsxImportSource: "react" } }) 260 }), 261 commandLineArgs: ["--p", "src/project"] 262 }); 263 264 verifyTsc({ 265 scenario: "react-jsx-emit-mode", 266 subScenario: "with no backing types found doesn't crash under --strict", 267 fs: () => loadProjectFromFiles({ 268 "/src/project/node_modules/react/jsx-runtime.js": "export {}", // js needs to be present so there's a resolution result 269 "/src/project/node_modules/@types/react/index.d.ts": jsxLibraryContent, // doesn't contain a jsx-runtime definition 270 "/src/project/src/index.tsx": `export const App = () => <div propA={true}></div>;`, 271 "/src/project/tsconfig.json": JSON.stringify({ compilerOptions: { module: "commonjs", jsx: "react-jsx", incremental: true, jsxImportSource: "react" } }) 272 }), 273 commandLineArgs: ["--p", "src/project", "--strict"] 274 }); 275 }); 276} 277