tsc-ts 0.0.4 → 0.0.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (584) hide show
  1. package/README.md +33 -1
  2. package/dist/api/compiler/ast-utilities.d.ts +82 -0
  3. package/dist/api/compiler/ast-utilities.js +462 -0
  4. package/dist/api/compiler/ast.d.ts +2350 -0
  5. package/dist/api/compiler/ast.js +11206 -0
  6. package/dist/api/compiler/astnav.d.ts +37 -0
  7. package/dist/api/compiler/astnav.js +767 -0
  8. package/dist/api/compiler/binder-utilities.d.ts +182 -0
  9. package/dist/api/compiler/binder-utilities.js +1240 -0
  10. package/dist/api/compiler/binder.d.ts +33 -0
  11. package/dist/api/compiler/binder.js +2358 -0
  12. package/dist/api/compiler/character-codes.d.ts +161 -0
  13. package/dist/api/compiler/character-codes.js +160 -0
  14. package/dist/api/compiler/checker-calls.d.ts +46 -0
  15. package/dist/api/compiler/checker-calls.js +1640 -0
  16. package/dist/api/compiler/checker-classes.d.ts +30 -0
  17. package/dist/api/compiler/checker-classes.js +582 -0
  18. package/dist/api/compiler/checker-contextual.d.ts +77 -0
  19. package/dist/api/compiler/checker-contextual.js +1136 -0
  20. package/dist/api/compiler/checker-declaration-order.d.ts +12 -0
  21. package/dist/api/compiler/checker-declaration-order.js +356 -0
  22. package/dist/api/compiler/checker-declarations.d.ts +33 -0
  23. package/dist/api/compiler/checker-declarations.js +888 -0
  24. package/dist/api/compiler/checker-declared-types.d.ts +48 -0
  25. package/dist/api/compiler/checker-declared-types.js +787 -0
  26. package/dist/api/compiler/checker-decorators.d.ts +26 -0
  27. package/dist/api/compiler/checker-decorators.js +562 -0
  28. package/dist/api/compiler/checker-deprecation.d.ts +33 -0
  29. package/dist/api/compiler/checker-deprecation.js +315 -0
  30. package/dist/api/compiler/checker-destructuring.d.ts +34 -0
  31. package/dist/api/compiler/checker-destructuring.js +584 -0
  32. package/dist/api/compiler/checker-elaboration.d.ts +15 -0
  33. package/dist/api/compiler/checker-elaboration.js +290 -0
  34. package/dist/api/compiler/checker-emit-helpers.d.ts +58 -0
  35. package/dist/api/compiler/checker-emit-helpers.js +154 -0
  36. package/dist/api/compiler/checker-emit-resolver.d.ts +75 -0
  37. package/dist/api/compiler/checker-emit-resolver.js +579 -0
  38. package/dist/api/compiler/checker-evaluator.d.ts +27 -0
  39. package/dist/api/compiler/checker-evaluator.js +188 -0
  40. package/dist/api/compiler/checker-expressions.d.ts +67 -0
  41. package/dist/api/compiler/checker-expressions.js +1351 -0
  42. package/dist/api/compiler/checker-features.d.ts +6 -0
  43. package/dist/api/compiler/checker-features.js +354 -0
  44. package/dist/api/compiler/checker-flow.d.ts +86 -0
  45. package/dist/api/compiler/checker-flow.js +169 -0
  46. package/dist/api/compiler/checker-functions.d.ts +43 -0
  47. package/dist/api/compiler/checker-functions.js +1002 -0
  48. package/dist/api/compiler/checker-generated-code.d.ts +25 -0
  49. package/dist/api/compiler/checker-generated-code.js +168 -0
  50. package/dist/api/compiler/checker-globals.d.ts +14 -0
  51. package/dist/api/compiler/checker-globals.js +37 -0
  52. package/dist/api/compiler/checker-grammar.d.ts +35 -0
  53. package/dist/api/compiler/checker-grammar.js +2573 -0
  54. package/dist/api/compiler/checker-heritage.d.ts +28 -0
  55. package/dist/api/compiler/checker-heritage.js +900 -0
  56. package/dist/api/compiler/checker-inference.d.ts +179 -0
  57. package/dist/api/compiler/checker-inference.js +2105 -0
  58. package/dist/api/compiler/checker-iteration.d.ts +115 -0
  59. package/dist/api/compiler/checker-iteration.js +857 -0
  60. package/dist/api/compiler/checker-javascript.d.ts +42 -0
  61. package/dist/api/compiler/checker-javascript.js +441 -0
  62. package/dist/api/compiler/checker-jsdoc.d.ts +30 -0
  63. package/dist/api/compiler/checker-jsdoc.js +320 -0
  64. package/dist/api/compiler/checker-jsx.d.ts +94 -0
  65. package/dist/api/compiler/checker-jsx.js +1433 -0
  66. package/dist/api/compiler/checker-literals.d.ts +6 -0
  67. package/dist/api/compiler/checker-literals.js +43 -0
  68. package/dist/api/compiler/checker-members.d.ts +198 -0
  69. package/dist/api/compiler/checker-members.js +2126 -0
  70. package/dist/api/compiler/checker-modules.d.ts +85 -0
  71. package/dist/api/compiler/checker-modules.js +2141 -0
  72. package/dist/api/compiler/checker-narrowing.d.ts +120 -0
  73. package/dist/api/compiler/checker-narrowing.js +2797 -0
  74. package/dist/api/compiler/checker-object-literals.d.ts +14 -0
  75. package/dist/api/compiler/checker-object-literals.js +479 -0
  76. package/dist/api/compiler/checker-operators.d.ts +33 -0
  77. package/dist/api/compiler/checker-operators.js +1040 -0
  78. package/dist/api/compiler/checker-overloads.d.ts +7 -0
  79. package/dist/api/compiler/checker-overloads.js +270 -0
  80. package/dist/api/compiler/checker-property-access.d.ts +34 -0
  81. package/dist/api/compiler/checker-property-access.js +672 -0
  82. package/dist/api/compiler/checker-services.d.ts +49 -0
  83. package/dist/api/compiler/checker-services.js +995 -0
  84. package/dist/api/compiler/checker-signatures.d.ts +55 -0
  85. package/dist/api/compiler/checker-signatures.js +788 -0
  86. package/dist/api/compiler/checker-source-file.d.ts +27 -0
  87. package/dist/api/compiler/checker-source-file.js +619 -0
  88. package/dist/api/compiler/checker-statements.d.ts +18 -0
  89. package/dist/api/compiler/checker-statements.js +226 -0
  90. package/dist/api/compiler/checker-super.d.ts +13 -0
  91. package/dist/api/compiler/checker-super.js +241 -0
  92. package/dist/api/compiler/checker-symbol-types.d.ts +67 -0
  93. package/dist/api/compiler/checker-symbol-types.js +1885 -0
  94. package/dist/api/compiler/checker-symbols.d.ts +181 -0
  95. package/dist/api/compiler/checker-symbols.js +1782 -0
  96. package/dist/api/compiler/checker-type-factory.d.ts +142 -0
  97. package/dist/api/compiler/checker-type-factory.js +2501 -0
  98. package/dist/api/compiler/checker-type-nodes.d.ts +26 -0
  99. package/dist/api/compiler/checker-type-nodes.js +828 -0
  100. package/dist/api/compiler/checker-type-operators.d.ts +109 -0
  101. package/dist/api/compiler/checker-type-operators.js +1842 -0
  102. package/dist/api/compiler/checker-types.d.ts +1027 -0
  103. package/dist/api/compiler/checker-types.js +1697 -0
  104. package/dist/api/compiler/checker-unused.d.ts +19 -0
  105. package/dist/api/compiler/checker-unused.js +524 -0
  106. package/dist/api/compiler/checker-utilities.d.ts +33 -0
  107. package/dist/api/compiler/checker-utilities.js +141 -0
  108. package/dist/api/compiler/checker.d.ts +491 -0
  109. package/dist/api/compiler/checker.js +912 -0
  110. package/dist/api/compiler/command-line.d.ts +32 -0
  111. package/dist/api/compiler/command-line.js +383 -0
  112. package/dist/api/compiler/compile-program.d.ts +118 -0
  113. package/dist/api/compiler/compile-program.js +384 -0
  114. package/dist/api/compiler/diagnostic-locales.d.ts +22 -0
  115. package/dist/api/compiler/diagnostic-locales.js +64 -0
  116. package/dist/api/compiler/diagnostic-messages.d.ts +2166 -0
  117. package/dist/api/compiler/diagnostic-messages.js +184 -0
  118. package/dist/api/compiler/diagnostics.d.ts +167 -0
  119. package/dist/api/compiler/diagnostics.js +820 -0
  120. package/dist/api/compiler/emitter.d.ts +71 -0
  121. package/dist/api/compiler/emitter.js +327 -0
  122. package/dist/api/compiler/file-include.d.ts +117 -0
  123. package/dist/api/compiler/file-include.js +536 -0
  124. package/dist/api/compiler/file-loader.d.ts +261 -0
  125. package/dist/api/compiler/file-loader.js +1257 -0
  126. package/dist/api/compiler/file-system.d.ts +51 -0
  127. package/dist/api/compiler/file-system.js +132 -0
  128. package/dist/api/compiler/flow.d.ts +60 -0
  129. package/dist/api/compiler/flow.js +45 -0
  130. package/dist/api/compiler/instantiation.d.ts +74 -0
  131. package/dist/api/compiler/instantiation.js +799 -0
  132. package/dist/api/compiler/jsdoc.d.ts +75 -0
  133. package/dist/api/compiler/jsdoc.js +1229 -0
  134. package/dist/api/compiler/link-tables.d.ts +36 -0
  135. package/dist/api/compiler/link-tables.js +83 -0
  136. package/dist/api/compiler/locale-data.d.ts +24 -0
  137. package/dist/api/compiler/locale-data.js +183 -0
  138. package/dist/api/compiler/locale.d.ts +4 -0
  139. package/dist/api/compiler/locale.js +317 -0
  140. package/dist/api/compiler/locales/cs-CZ.d.ts +2 -0
  141. package/dist/api/compiler/locales/cs-CZ.js +3 -0
  142. package/dist/api/compiler/locales/de-DE.d.ts +2 -0
  143. package/dist/api/compiler/locales/de-DE.js +3 -0
  144. package/dist/api/compiler/locales/es-ES.d.ts +2 -0
  145. package/dist/api/compiler/locales/es-ES.js +3 -0
  146. package/dist/api/compiler/locales/fr-FR.d.ts +2 -0
  147. package/dist/api/compiler/locales/fr-FR.js +3 -0
  148. package/dist/api/compiler/locales/it-IT.d.ts +2 -0
  149. package/dist/api/compiler/locales/it-IT.js +3 -0
  150. package/dist/api/compiler/locales/ja-JP.d.ts +2 -0
  151. package/dist/api/compiler/locales/ja-JP.js +3 -0
  152. package/dist/api/compiler/locales/ko-KR.d.ts +2 -0
  153. package/dist/api/compiler/locales/ko-KR.js +3 -0
  154. package/dist/api/compiler/locales/pl-PL.d.ts +2 -0
  155. package/dist/api/compiler/locales/pl-PL.js +3 -0
  156. package/dist/api/compiler/locales/pt-BR.d.ts +2 -0
  157. package/dist/api/compiler/locales/pt-BR.js +3 -0
  158. package/dist/api/compiler/locales/ru-RU.d.ts +2 -0
  159. package/dist/api/compiler/locales/ru-RU.js +3 -0
  160. package/dist/api/compiler/locales/tr-TR.d.ts +2 -0
  161. package/dist/api/compiler/locales/tr-TR.js +3 -0
  162. package/dist/api/compiler/locales/zh-CN.d.ts +2 -0
  163. package/dist/api/compiler/locales/zh-CN.js +3 -0
  164. package/dist/api/compiler/locales/zh-TW.d.ts +2 -0
  165. package/dist/api/compiler/locales/zh-TW.js +3 -0
  166. package/dist/api/compiler/module-resolution-types.d.ts +83 -0
  167. package/dist/api/compiler/module-resolution-types.js +176 -0
  168. package/dist/api/compiler/module-resolution.d.ts +71 -0
  169. package/dist/api/compiler/module-resolution.js +1598 -0
  170. package/dist/api/compiler/module-specifiers.d.ts +64 -0
  171. package/dist/api/compiler/module-specifiers.js +1101 -0
  172. package/dist/api/compiler/name-resolver.d.ts +43 -0
  173. package/dist/api/compiler/name-resolver.js +509 -0
  174. package/dist/api/compiler/node-builder-names.d.ts +32 -0
  175. package/dist/api/compiler/node-builder-names.js +854 -0
  176. package/dist/api/compiler/node-builder-pseudo.d.ts +36 -0
  177. package/dist/api/compiler/node-builder-pseudo.js +744 -0
  178. package/dist/api/compiler/node-builder-reuse.d.ts +4 -0
  179. package/dist/api/compiler/node-builder-reuse.js +647 -0
  180. package/dist/api/compiler/node-builder.d.ts +270 -0
  181. package/dist/api/compiler/node-builder.js +2645 -0
  182. package/dist/api/compiler/option-declarations.d.ts +90 -0
  183. package/dist/api/compiler/option-declarations.js +1460 -0
  184. package/dist/api/compiler/options.d.ts +289 -0
  185. package/dist/api/compiler/options.js +1197 -0
  186. package/dist/api/compiler/output-paths.d.ts +42 -0
  187. package/dist/api/compiler/output-paths.js +195 -0
  188. package/dist/api/compiler/package-json.d.ts +175 -0
  189. package/dist/api/compiler/package-json.js +1015 -0
  190. package/dist/api/compiler/parallel-parse.d.ts +219 -0
  191. package/dist/api/compiler/parallel-parse.js +537 -0
  192. package/dist/api/compiler/parser.d.ts +587 -0
  193. package/dist/api/compiler/parser.js +6407 -0
  194. package/dist/api/compiler/path.d.ts +91 -0
  195. package/dist/api/compiler/path.js +705 -0
  196. package/dist/api/compiler/printer/async-helpers.d.ts +22 -0
  197. package/dist/api/compiler/printer/async-helpers.js +91 -0
  198. package/dist/api/compiler/printer/auto-generate.d.ts +13 -0
  199. package/dist/api/compiler/printer/auto-generate.js +20 -0
  200. package/dist/api/compiler/printer/decorator-helpers.d.ts +24 -0
  201. package/dist/api/compiler/printer/decorator-helpers.js +118 -0
  202. package/dist/api/compiler/printer/emit-context.d.ts +154 -0
  203. package/dist/api/compiler/printer/emit-context.js +576 -0
  204. package/dist/api/compiler/printer/emit-flags.d.ts +60 -0
  205. package/dist/api/compiler/printer/emit-flags.js +2 -0
  206. package/dist/api/compiler/printer/factory-base.d.ts +171 -0
  207. package/dist/api/compiler/printer/factory-base.js +1505 -0
  208. package/dist/api/compiler/printer/factory.d.ts +147 -0
  209. package/dist/api/compiler/printer/factory.js +542 -0
  210. package/dist/api/compiler/printer/helpers.d.ts +27 -0
  211. package/dist/api/compiler/printer/helpers.js +164 -0
  212. package/dist/api/compiler/printer/name-generator.d.ts +41 -0
  213. package/dist/api/compiler/printer/name-generator.js +283 -0
  214. package/dist/api/compiler/printer/printer.d.ts +411 -0
  215. package/dist/api/compiler/printer/printer.js +4517 -0
  216. package/dist/api/compiler/printer/text-writer.d.ts +46 -0
  217. package/dist/api/compiler/printer/text-writer.js +172 -0
  218. package/dist/api/compiler/printer/utilities.d.ts +82 -0
  219. package/dist/api/compiler/printer/utilities.js +817 -0
  220. package/dist/api/compiler/program-checker.d.ts +156 -0
  221. package/dist/api/compiler/program-checker.js +526 -0
  222. package/dist/api/compiler/program-utilities.d.ts +52 -0
  223. package/dist/api/compiler/program-utilities.js +365 -0
  224. package/dist/api/compiler/program.d.ts +180 -0
  225. package/dist/api/compiler/program.js +1011 -0
  226. package/dist/api/compiler/pseudo-bigint.d.ts +5 -0
  227. package/dist/api/compiler/pseudo-bigint.js +61 -0
  228. package/dist/api/compiler/regexp-checker.d.ts +38 -0
  229. package/dist/api/compiler/regexp-checker.js +942 -0
  230. package/dist/api/compiler/relations.d.ts +263 -0
  231. package/dist/api/compiler/relations.js +4002 -0
  232. package/dist/api/compiler/reparser.d.ts +48 -0
  233. package/dist/api/compiler/reparser.js +1323 -0
  234. package/dist/api/compiler/scanner.d.ts +256 -0
  235. package/dist/api/compiler/scanner.js +2853 -0
  236. package/dist/api/compiler/side-state.d.ts +16 -0
  237. package/dist/api/compiler/side-state.js +89 -0
  238. package/dist/api/compiler/sourcemap.d.ts +55 -0
  239. package/dist/api/compiler/sourcemap.js +340 -0
  240. package/dist/api/compiler/spelling.d.ts +14 -0
  241. package/dist/api/compiler/spelling.js +128 -0
  242. package/dist/api/compiler/symbol-accessibility.d.ts +57 -0
  243. package/dist/api/compiler/symbol-accessibility.js +894 -0
  244. package/dist/api/compiler/symbol.d.ts +240 -0
  245. package/dist/api/compiler/symbol.js +228 -0
  246. package/dist/api/compiler/symlinks.d.ts +32 -0
  247. package/dist/api/compiler/symlinks.js +114 -0
  248. package/dist/api/compiler/syntax-kind.d.ts +389 -0
  249. package/dist/api/compiler/syntax-kind.js +2 -0
  250. package/dist/api/compiler/timeline.d.ts +9 -0
  251. package/dist/api/compiler/timeline.js +54 -0
  252. package/dist/api/compiler/transformers/alias-references.d.ts +39 -0
  253. package/dist/api/compiler/transformers/alias-references.js +676 -0
  254. package/dist/api/compiler/transformers/async-utilities.d.ts +51 -0
  255. package/dist/api/compiler/transformers/async-utilities.js +260 -0
  256. package/dist/api/compiler/transformers/async.d.ts +53 -0
  257. package/dist/api/compiler/transformers/async.js +645 -0
  258. package/dist/api/compiler/transformers/class-fields.d.ts +206 -0
  259. package/dist/api/compiler/transformers/class-fields.js +2418 -0
  260. package/dist/api/compiler/transformers/class-utilities.d.ts +46 -0
  261. package/dist/api/compiler/transformers/class-utilities.js +261 -0
  262. package/dist/api/compiler/transformers/commonjs-module.d.ts +103 -0
  263. package/dist/api/compiler/transformers/commonjs-module.js +1180 -0
  264. package/dist/api/compiler/transformers/const-enum-inliner.d.ts +11 -0
  265. package/dist/api/compiler/transformers/const-enum-inliner.js +36 -0
  266. package/dist/api/compiler/transformers/declarations-diagnostics.d.ts +52 -0
  267. package/dist/api/compiler/transformers/declarations-diagnostics.js +538 -0
  268. package/dist/api/compiler/transformers/declarations-pseudo.d.ts +160 -0
  269. package/dist/api/compiler/transformers/declarations-pseudo.js +797 -0
  270. package/dist/api/compiler/transformers/declarations-resolver.d.ts +152 -0
  271. package/dist/api/compiler/transformers/declarations-resolver.js +35 -0
  272. package/dist/api/compiler/transformers/declarations-syntactic.d.ts +119 -0
  273. package/dist/api/compiler/transformers/declarations-syntactic.js +1582 -0
  274. package/dist/api/compiler/transformers/declarations-tracker.d.ts +46 -0
  275. package/dist/api/compiler/transformers/declarations-tracker.js +197 -0
  276. package/dist/api/compiler/transformers/declarations.d.ts +175 -0
  277. package/dist/api/compiler/transformers/declarations.js +2380 -0
  278. package/dist/api/compiler/transformers/decorator-metadata.d.ts +54 -0
  279. package/dist/api/compiler/transformers/decorator-metadata.js +554 -0
  280. package/dist/api/compiler/transformers/decorator-utilities.d.ts +38 -0
  281. package/dist/api/compiler/transformers/decorator-utilities.js +238 -0
  282. package/dist/api/compiler/transformers/destructuring.d.ts +25 -0
  283. package/dist/api/compiler/transformers/destructuring.js +626 -0
  284. package/dist/api/compiler/transformers/downlevel.d.ts +6 -0
  285. package/dist/api/compiler/transformers/downlevel.js +45 -0
  286. package/dist/api/compiler/transformers/emit-resolver.d.ts +61 -0
  287. package/dist/api/compiler/transformers/emit-resolver.js +197 -0
  288. package/dist/api/compiler/transformers/es-decorators.d.ts +118 -0
  289. package/dist/api/compiler/transformers/es-decorators.js +1901 -0
  290. package/dist/api/compiler/transformers/exponentiation.d.ts +11 -0
  291. package/dist/api/compiler/transformers/exponentiation.js +76 -0
  292. package/dist/api/compiler/transformers/external-module-info.d.ts +35 -0
  293. package/dist/api/compiler/transformers/external-module-info.js +351 -0
  294. package/dist/api/compiler/transformers/for-await.d.ts +43 -0
  295. package/dist/api/compiler/transformers/for-await.js +469 -0
  296. package/dist/api/compiler/transformers/import-elision.d.ts +16 -0
  297. package/dist/api/compiler/transformers/import-elision.js +124 -0
  298. package/dist/api/compiler/transformers/jsx-entities.d.ts +1 -0
  299. package/dist/api/compiler/transformers/jsx-entities.js +256 -0
  300. package/dist/api/compiler/transformers/jsx.d.ts +71 -0
  301. package/dist/api/compiler/transformers/jsx.js +700 -0
  302. package/dist/api/compiler/transformers/legacy-decorators.d.ts +56 -0
  303. package/dist/api/compiler/transformers/legacy-decorators.js +564 -0
  304. package/dist/api/compiler/transformers/logical-assignment.d.ts +14 -0
  305. package/dist/api/compiler/transformers/logical-assignment.js +62 -0
  306. package/dist/api/compiler/transformers/module-utilities.d.ts +9 -0
  307. package/dist/api/compiler/transformers/module-utilities.js +36 -0
  308. package/dist/api/compiler/transformers/module.d.ts +49 -0
  309. package/dist/api/compiler/transformers/module.js +296 -0
  310. package/dist/api/compiler/transformers/named-evaluation.d.ts +26 -0
  311. package/dist/api/compiler/transformers/named-evaluation.js +266 -0
  312. package/dist/api/compiler/transformers/nullish-coalescing.d.ts +9 -0
  313. package/dist/api/compiler/transformers/nullish-coalescing.js +26 -0
  314. package/dist/api/compiler/transformers/object-rest-spread.d.ts +34 -0
  315. package/dist/api/compiler/transformers/object-rest-spread.js +411 -0
  316. package/dist/api/compiler/transformers/optional-catch.d.ts +9 -0
  317. package/dist/api/compiler/transformers/optional-catch.js +20 -0
  318. package/dist/api/compiler/transformers/optional-chain.d.ts +14 -0
  319. package/dist/api/compiler/transformers/optional-chain.js +188 -0
  320. package/dist/api/compiler/transformers/reference-resolver.d.ts +128 -0
  321. package/dist/api/compiler/transformers/reference-resolver.js +1155 -0
  322. package/dist/api/compiler/transformers/runtime-syntax.d.ts +71 -0
  323. package/dist/api/compiler/transformers/runtime-syntax.js +753 -0
  324. package/dist/api/compiler/transformers/subtree-facts.d.ts +9 -0
  325. package/dist/api/compiler/transformers/subtree-facts.js +203 -0
  326. package/dist/api/compiler/transformers/syntax-facts.d.ts +51 -0
  327. package/dist/api/compiler/transformers/syntax-facts.js +254 -0
  328. package/dist/api/compiler/transformers/tagged-template.d.ts +17 -0
  329. package/dist/api/compiler/transformers/tagged-template.js +148 -0
  330. package/dist/api/compiler/transformers/transformer.d.ts +17 -0
  331. package/dist/api/compiler/transformers/transformer.js +54 -0
  332. package/dist/api/compiler/transformers/type-eraser.d.ts +21 -0
  333. package/dist/api/compiler/transformers/type-eraser.js +346 -0
  334. package/dist/api/compiler/transformers/type-serialization.d.ts +20 -0
  335. package/dist/api/compiler/transformers/type-serialization.js +347 -0
  336. package/dist/api/compiler/transformers/using.d.ts +56 -0
  337. package/dist/api/compiler/transformers/using.js +453 -0
  338. package/dist/api/compiler/transformers/utilities.d.ts +50 -0
  339. package/dist/api/compiler/transformers/utilities.js +347 -0
  340. package/dist/api/compiler/transformers/visitor-base.d.ts +6 -0
  341. package/dist/api/compiler/transformers/visitor-base.js +817 -0
  342. package/dist/api/compiler/transformers/visitor-hooks.d.ts +29 -0
  343. package/dist/api/compiler/transformers/visitor-hooks.js +189 -0
  344. package/dist/api/compiler/tsconfig.d.ts +177 -0
  345. package/dist/api/compiler/tsconfig.js +1311 -0
  346. package/dist/api/compiler/type-printer.d.ts +15 -0
  347. package/dist/api/compiler/type-printer.js +74 -0
  348. package/dist/api/compiler/types.d.ts +87 -0
  349. package/dist/api/compiler/types.js +23 -0
  350. package/dist/api/compiler/unicode-identifiers.d.ts +2 -0
  351. package/dist/api/compiler/unicode-identifiers.js +209 -0
  352. package/dist/api/compiler/unicode-properties.d.ts +8 -0
  353. package/dist/api/compiler/unicode-properties.js +531 -0
  354. package/dist/api/compiler/vfs-match.d.ts +24 -0
  355. package/dist/api/compiler/vfs-match.js +587 -0
  356. package/dist/api/library/ast.d.ts +3 -2
  357. package/dist/api/library/ast.generated.d.ts +127 -139
  358. package/dist/api/library/checker.d.ts +51 -0
  359. package/dist/api/library/checker.js +318 -0
  360. package/dist/api/library/diagnostics.d.ts +13 -0
  361. package/dist/api/library/diagnostics.js +50 -0
  362. package/dist/api/library/disk.d.ts +13 -0
  363. package/dist/api/library/disk.js +66 -0
  364. package/dist/api/library/errors.d.ts +13 -0
  365. package/dist/api/library/errors.js +24 -0
  366. package/dist/api/library/host.d.ts +24 -0
  367. package/dist/api/library/host.js +52 -0
  368. package/dist/api/library/index.d.ts +5 -1
  369. package/dist/api/library/index.js +4 -0
  370. package/dist/api/library/nodes.d.ts +51 -0
  371. package/dist/api/library/nodes.js +196 -0
  372. package/dist/api/library/options.d.ts +144 -0
  373. package/dist/api/library/options.js +308 -0
  374. package/dist/api/library/parse.d.ts +19 -0
  375. package/dist/api/library/parse.js +41 -0
  376. package/dist/api/library/program.d.ts +21 -0
  377. package/dist/api/library/program.js +234 -0
  378. package/dist/api/library/types.d.ts +14 -1
  379. package/package.json +12 -8
  380. package/src/compiler/ast-utilities.ts +548 -0
  381. package/src/compiler/ast.ts +12862 -0
  382. package/src/compiler/astnav.ts +799 -0
  383. package/src/compiler/binder-utilities.ts +1392 -0
  384. package/src/compiler/binder.ts +2703 -0
  385. package/src/compiler/build-info.ts +1197 -0
  386. package/src/compiler/character-codes.ts +323 -0
  387. package/src/compiler/checker-calls.ts +2155 -0
  388. package/src/compiler/checker-classes.ts +706 -0
  389. package/src/compiler/checker-contextual.ts +1457 -0
  390. package/src/compiler/checker-declaration-order.ts +438 -0
  391. package/src/compiler/checker-declarations.ts +1194 -0
  392. package/src/compiler/checker-declared-types.ts +919 -0
  393. package/src/compiler/checker-decorators.ts +694 -0
  394. package/src/compiler/checker-deprecation.ts +359 -0
  395. package/src/compiler/checker-destructuring.ts +805 -0
  396. package/src/compiler/checker-elaboration.ts +477 -0
  397. package/src/compiler/checker-emit-helpers.ts +224 -0
  398. package/src/compiler/checker-emit-resolver.ts +769 -0
  399. package/src/compiler/checker-evaluator.ts +243 -0
  400. package/src/compiler/checker-expressions.ts +1831 -0
  401. package/src/compiler/checker-features.ts +361 -0
  402. package/src/compiler/checker-flow.ts +394 -0
  403. package/src/compiler/checker-functions.ts +1296 -0
  404. package/src/compiler/checker-generated-code.ts +227 -0
  405. package/src/compiler/checker-globals.ts +52 -0
  406. package/src/compiler/checker-grammar.ts +3584 -0
  407. package/src/compiler/checker-heritage.ts +1233 -0
  408. package/src/compiler/checker-inference.ts +2576 -0
  409. package/src/compiler/checker-iteration.ts +1206 -0
  410. package/src/compiler/checker-javascript.ts +502 -0
  411. package/src/compiler/checker-jsdoc.ts +360 -0
  412. package/src/compiler/checker-jsx.ts +1924 -0
  413. package/src/compiler/checker-literals.ts +61 -0
  414. package/src/compiler/checker-members.ts +2436 -0
  415. package/src/compiler/checker-modules.ts +2886 -0
  416. package/src/compiler/checker-narrowing.ts +3230 -0
  417. package/src/compiler/checker-object-literals.ts +575 -0
  418. package/src/compiler/checker-operators.ts +1422 -0
  419. package/src/compiler/checker-overloads.ts +328 -0
  420. package/src/compiler/checker-property-access.ts +906 -0
  421. package/src/compiler/checker-services.ts +1149 -0
  422. package/src/compiler/checker-signatures.ts +1032 -0
  423. package/src/compiler/checker-source-file.ts +732 -0
  424. package/src/compiler/checker-statements.ts +292 -0
  425. package/src/compiler/checker-super.ts +261 -0
  426. package/src/compiler/checker-symbol-types.ts +2107 -0
  427. package/src/compiler/checker-symbols.ts +2150 -0
  428. package/src/compiler/checker-type-factory.ts +2579 -0
  429. package/src/compiler/checker-type-nodes.ts +1033 -0
  430. package/src/compiler/checker-type-operators.ts +2502 -0
  431. package/src/compiler/checker-types.ts +2340 -0
  432. package/src/compiler/checker-unused.ts +642 -0
  433. package/src/compiler/checker-utilities.ts +161 -0
  434. package/src/compiler/checker.ts +1116 -0
  435. package/src/compiler/command-line.ts +436 -0
  436. package/src/compiler/compile-program.ts +439 -0
  437. package/src/compiler/decoder.ts +1209 -0
  438. package/src/compiler/diagnostic-locales.ts +86 -0
  439. package/src/compiler/diagnostic-messages.ts +2349 -0
  440. package/src/compiler/diagnostics.ts +897 -0
  441. package/src/compiler/emitter.ts +434 -0
  442. package/src/compiler/encoder.ts +1945 -0
  443. package/src/compiler/file-include.ts +673 -0
  444. package/src/compiler/file-loader.ts +1528 -0
  445. package/src/compiler/file-system.ts +143 -0
  446. package/src/compiler/flow.ts +89 -0
  447. package/src/compiler/help.ts +473 -0
  448. package/src/compiler/incremental.ts +2784 -0
  449. package/src/compiler/init.ts +141 -0
  450. package/src/compiler/instantiation.ts +894 -0
  451. package/src/compiler/jsdoc.ts +1386 -0
  452. package/src/compiler/link-tables.ts +98 -0
  453. package/src/compiler/locale-data.ts +203 -0
  454. package/src/compiler/locale.ts +307 -0
  455. package/src/compiler/locales/cs-CZ.ts +5 -0
  456. package/src/compiler/locales/de-DE.ts +5 -0
  457. package/src/compiler/locales/es-ES.ts +5 -0
  458. package/src/compiler/locales/fr-FR.ts +5 -0
  459. package/src/compiler/locales/it-IT.ts +5 -0
  460. package/src/compiler/locales/ja-JP.ts +5 -0
  461. package/src/compiler/locales/ko-KR.ts +5 -0
  462. package/src/compiler/locales/pl-PL.ts +5 -0
  463. package/src/compiler/locales/pt-BR.ts +5 -0
  464. package/src/compiler/locales/ru-RU.ts +5 -0
  465. package/src/compiler/locales/tr-TR.ts +5 -0
  466. package/src/compiler/locales/zh-CN.ts +5 -0
  467. package/src/compiler/locales/zh-TW.ts +5 -0
  468. package/src/compiler/module-resolution-types.ts +243 -0
  469. package/src/compiler/module-resolution.ts +2072 -0
  470. package/src/compiler/module-specifiers.ts +1491 -0
  471. package/src/compiler/name-resolver.ts +646 -0
  472. package/src/compiler/node-builder-names.ts +1069 -0
  473. package/src/compiler/node-builder-pseudo.ts +892 -0
  474. package/src/compiler/node-builder-reuse.ts +764 -0
  475. package/src/compiler/node-builder.ts +3425 -0
  476. package/src/compiler/option-declarations.ts +1560 -0
  477. package/src/compiler/options.ts +1576 -0
  478. package/src/compiler/output-paths.ts +334 -0
  479. package/src/compiler/package-json.ts +1083 -0
  480. package/src/compiler/parallel-check.ts +1951 -0
  481. package/src/compiler/parallel-parse.ts +590 -0
  482. package/src/compiler/parse-thread.ts +140 -0
  483. package/src/compiler/parser.ts +7716 -0
  484. package/src/compiler/path.ts +717 -0
  485. package/src/compiler/printer/async-helpers.ts +183 -0
  486. package/src/compiler/printer/auto-generate.ts +27 -0
  487. package/src/compiler/printer/decorator-helpers.ts +218 -0
  488. package/src/compiler/printer/emit-context.ts +679 -0
  489. package/src/compiler/printer/emit-flags.ts +64 -0
  490. package/src/compiler/printer/factory-base.ts +2577 -0
  491. package/src/compiler/printer/factory.ts +764 -0
  492. package/src/compiler/printer/helpers.ts +291 -0
  493. package/src/compiler/printer/name-generator.ts +372 -0
  494. package/src/compiler/printer/printer.ts +5072 -0
  495. package/src/compiler/printer/text-writer.ts +183 -0
  496. package/src/compiler/printer/utilities.ts +884 -0
  497. package/src/compiler/program-checker.ts +592 -0
  498. package/src/compiler/program-utilities.ts +435 -0
  499. package/src/compiler/program.ts +1419 -0
  500. package/src/compiler/pseudo-bigint.ts +62 -0
  501. package/src/compiler/regexp-checker.ts +1142 -0
  502. package/src/compiler/relations.ts +5149 -0
  503. package/src/compiler/reparser.ts +1566 -0
  504. package/src/compiler/scanner.ts +2951 -0
  505. package/src/compiler/show-config.ts +239 -0
  506. package/src/compiler/side-state.ts +125 -0
  507. package/src/compiler/sourcemap.ts +366 -0
  508. package/src/compiler/spelling.ts +122 -0
  509. package/src/compiler/symbol-accessibility.ts +1071 -0
  510. package/src/compiler/symbol.ts +439 -0
  511. package/src/compiler/symlinks.ts +137 -0
  512. package/src/compiler/syntax-kind.ts +391 -0
  513. package/src/compiler/thread-entry.ts +191 -0
  514. package/src/compiler/timeline.ts +53 -0
  515. package/src/compiler/transformers/alias-references.ts +757 -0
  516. package/src/compiler/transformers/async-utilities.ts +335 -0
  517. package/src/compiler/transformers/async.ts +838 -0
  518. package/src/compiler/transformers/class-fields.ts +2967 -0
  519. package/src/compiler/transformers/class-utilities.ts +324 -0
  520. package/src/compiler/transformers/commonjs-module.ts +1621 -0
  521. package/src/compiler/transformers/const-enum-inliner.ts +50 -0
  522. package/src/compiler/transformers/declarations-diagnostics.ts +832 -0
  523. package/src/compiler/transformers/declarations-pseudo.ts +966 -0
  524. package/src/compiler/transformers/declarations-resolver.ts +249 -0
  525. package/src/compiler/transformers/declarations-syntactic.ts +1859 -0
  526. package/src/compiler/transformers/declarations-tracker.ts +269 -0
  527. package/src/compiler/transformers/declarations.ts +3120 -0
  528. package/src/compiler/transformers/decorator-metadata.ts +697 -0
  529. package/src/compiler/transformers/decorator-utilities.ts +283 -0
  530. package/src/compiler/transformers/destructuring.ts +708 -0
  531. package/src/compiler/transformers/downlevel.ts +50 -0
  532. package/src/compiler/transformers/emit-resolver.ts +258 -0
  533. package/src/compiler/transformers/es-decorators.ts +2682 -0
  534. package/src/compiler/transformers/exponentiation.ts +80 -0
  535. package/src/compiler/transformers/external-module-info.ts +412 -0
  536. package/src/compiler/transformers/for-await.ts +687 -0
  537. package/src/compiler/transformers/import-elision.ts +152 -0
  538. package/src/compiler/transformers/jsx-entities.ts +256 -0
  539. package/src/compiler/transformers/jsx.ts +824 -0
  540. package/src/compiler/transformers/legacy-decorators.ts +726 -0
  541. package/src/compiler/transformers/logical-assignment.ts +75 -0
  542. package/src/compiler/transformers/module-utilities.ts +42 -0
  543. package/src/compiler/transformers/module.ts +474 -0
  544. package/src/compiler/transformers/named-evaluation.ts +389 -0
  545. package/src/compiler/transformers/nullish-coalescing.ts +35 -0
  546. package/src/compiler/transformers/object-rest-spread.ts +577 -0
  547. package/src/compiler/transformers/optional-catch.ts +29 -0
  548. package/src/compiler/transformers/optional-chain.ts +246 -0
  549. package/src/compiler/transformers/reference-resolver.ts +1201 -0
  550. package/src/compiler/transformers/runtime-syntax.ts +942 -0
  551. package/src/compiler/transformers/subtree-facts.ts +245 -0
  552. package/src/compiler/transformers/syntax-facts.ts +353 -0
  553. package/src/compiler/transformers/tagged-template.ts +167 -0
  554. package/src/compiler/transformers/transformer.ts +56 -0
  555. package/src/compiler/transformers/type-eraser.ts +520 -0
  556. package/src/compiler/transformers/type-serialization.ts +374 -0
  557. package/src/compiler/transformers/using.ts +613 -0
  558. package/src/compiler/transformers/utilities.ts +419 -0
  559. package/src/compiler/transformers/visitor-base.ts +1601 -0
  560. package/src/compiler/transformers/visitor-hooks.ts +252 -0
  561. package/src/compiler/tsc-build.ts +1418 -0
  562. package/src/compiler/tsc-cli.ts +666 -0
  563. package/src/compiler/tsc-compile.ts +437 -0
  564. package/src/compiler/tsc-watch.ts +854 -0
  565. package/src/compiler/tsconfig.ts +1574 -0
  566. package/src/compiler/type-printer.ts +110 -0
  567. package/src/compiler/types.ts +115 -0
  568. package/src/compiler/unicode-identifiers.ts +212 -0
  569. package/src/compiler/unicode-properties.ts +537 -0
  570. package/src/compiler/vfs-match.ts +597 -0
  571. package/src/compiler/xxh3.ts +650 -0
  572. package/src/library/ast.generated.ts +141 -167
  573. package/src/library/ast.ts +4 -1
  574. package/src/library/checker.ts +384 -0
  575. package/src/library/diagnostics.ts +72 -0
  576. package/src/library/disk.ts +73 -0
  577. package/src/library/errors.ts +26 -0
  578. package/src/library/host.ts +63 -0
  579. package/src/library/index.ts +21 -0
  580. package/src/library/nodes.ts +232 -0
  581. package/src/library/options.ts +449 -0
  582. package/src/library/parse.ts +63 -0
  583. package/src/library/program.ts +293 -0
  584. package/src/library/types.ts +14 -1
@@ -0,0 +1,2784 @@
1
+ /**
2
+ * Incremental compilation: the state of a program between builds (file versions and shape
3
+ * signatures, references, cached diagnostics and pending emit), what a change affects, and the
4
+ * `.tsbuildinfo` that stores it, like tsgo's `incremental` package.
5
+ *
6
+ * ```ts
7
+ * const old = readBuildInfoProgram(config, reader, defaultLibraryPath);
8
+ * const program = new IncrementalProgram(checked, times, old, host);
9
+ * ```
10
+ */
11
+ import { publish } from '@scriptc/threads';
12
+ import { lastNodeIdValue, type Node, type SourceFile } from './ast.js';
13
+ import { SyntaxKind } from './syntax-kind.js';
14
+ import { isAmbientModule, isGlobalScopeAugmentation } from './ast-utilities.js';
15
+ import { getSourceFileOfNode, isExternalOrCommonJSModule, isJsonSourceFile } from './binder-utilities.js';
16
+ import {
17
+ BuildInfo,
18
+ BuildInfoDiagnostic,
19
+ BuildInfoDiagnosticsOfFile,
20
+ BuildInfoEmitSignature,
21
+ BuildInfoFileInfo,
22
+ BuildInfoFilePendingEmit,
23
+ BuildInfoOption,
24
+ BuildInfoReference,
25
+ BuildInfoResolvedRoot,
26
+ BuildInfoRoot,
27
+ BuildInfoSemanticDiagnostic,
28
+ buildInfoToJson,
29
+ compilerOptionDeclarationsInFieldOrder,
30
+ compilerOptionValue,
31
+ FileEmitKind,
32
+ FileInfoForm,
33
+ getFileEmitKind,
34
+ getPendingEmitKind,
35
+ getPendingEmitKindWithOptions,
36
+ isBuildInfoFileNameDefaultLibrary,
37
+ parseBuildInfo,
38
+ } from './build-info.js';
39
+ import {
40
+ type DiagnosticDetails,
41
+ modeMismatchDetails,
42
+ moduleNotFoundDetails,
43
+ resolveExternalModuleName,
44
+ } from './checker-modules.js';
45
+ import { getSymbolAtLocation } from './checker-services.js';
46
+ import { resolveAlias } from './checker-symbols.js';
47
+ import {
48
+ CompilerProgram,
49
+ CompileTimes,
50
+ combineEmitResults,
51
+ declarationDiagnosticsOfFile,
52
+ handleNoEmitOnError,
53
+ OutputWriter,
54
+ ProgramEmitter,
55
+ writeHeldOutputs,
56
+ } from './compile-program.js';
57
+ import {
58
+ categoryName,
59
+ createCompilerDiagnostic,
60
+ Diagnostic,
61
+ Diagnostics,
62
+ messageForKey,
63
+ messageKey,
64
+ RepopulateKind,
65
+ type RepopulateInfo,
66
+ } from './diagnostics.js';
67
+ import { EmitOnly, EmitResult, skippedWrite, sourceFileMayBeEmitted } from './emitter.js';
68
+ import type { FileSystem } from './file-system.js';
69
+ import { version } from './help.js';
70
+ import { Affects, type OptionDeclaration } from './option-declarations.js';
71
+ import {
72
+ getAllowJS,
73
+ getEmitDeclarations,
74
+ getStrictOptionValue,
75
+ isIncremental,
76
+ ModuleKind,
77
+ type CompilerOptions,
78
+ type CompilerOptionValue,
79
+ } from './options.js';
80
+ import type { Program } from './program.js';
81
+ import { CheckedProgram, ProgramCheckerHost } from './program-checker.js';
82
+ import {
83
+ combinePaths,
84
+ ensurePathIsNonModuleName,
85
+ getDirectoryPath,
86
+ getNormalizedAbsolutePath,
87
+ getRelativePathFromDirectory,
88
+ getRootLength,
89
+ isDeclarationFileName,
90
+ toPath,
91
+ } from './path.js';
92
+ import { lastSymbolIdValue, SymbolFlags, type Symbol } from './symbol.js';
93
+ import type { ParsedCommandLine } from './tsconfig.js';
94
+ import { hash128String, toHex } from './xxh3.js';
95
+ import { preparedVersion } from './parallel-parse.js';
96
+
97
+ /** The hash of file text that build info records as a version or signature. */
98
+ export function computeHash(text: string): string {
99
+ return toHex(hash128String(text));
100
+ }
101
+
102
+ export class FileInfo {
103
+ constructor(
104
+ readonly version: string,
105
+ public signature: string,
106
+ readonly affectsGlobalScope: boolean,
107
+ readonly impliedNodeFormat: number,
108
+ ) {}
109
+ }
110
+
111
+ /** The file info a build info records; `undefined` stays `undefined`. */
112
+ export function fileInfoFromBuildInfo(info: BuildInfoFileInfo): FileInfo {
113
+ switch (info.form) {
114
+ case FileInfoForm.Short:
115
+ return new FileInfo(info.version, info.version, false, ModuleKind.CommonJS);
116
+ case FileInfoForm.NoSignature:
117
+ return new FileInfo(info.version, '', info.affectsGlobalScope, info.impliedNodeFormat);
118
+ default:
119
+ return new FileInfo(
120
+ info.version,
121
+ info.signature === '' ? info.version : info.signature,
122
+ info.affectsGlobalScope,
123
+ info.impliedNodeFormat,
124
+ );
125
+ }
126
+ }
127
+
128
+ function toBuildInfoFileInfo(info: FileInfo): BuildInfoFileInfo {
129
+ if (info.version === info.signature) {
130
+ if (!info.affectsGlobalScope && info.impliedNodeFormat === ModuleKind.CommonJS) {
131
+ return new BuildInfoFileInfo(FileInfoForm.Short, info.signature, info.signature, false, ModuleKind.CommonJS);
132
+ }
133
+ } else if (info.signature === '') {
134
+ return new BuildInfoFileInfo(
135
+ FileInfoForm.NoSignature,
136
+ info.version,
137
+ '',
138
+ info.affectsGlobalScope,
139
+ info.impliedNodeFormat,
140
+ );
141
+ }
142
+ return new BuildInfoFileInfo(
143
+ FileInfoForm.Full,
144
+ info.version,
145
+ info.signature === info.version ? '' : info.signature,
146
+ info.affectsGlobalScope,
147
+ info.impliedNodeFormat,
148
+ );
149
+ }
150
+
151
+ /** The hash of a declaration file, recorded for composite projects to tell whether it changed. */
152
+ class EmitSignature {
153
+ constructor(
154
+ /** `''` when emitted with different `declarationMap`. */
155
+ readonly signature: string,
156
+ /** The signature when emitted with different `declarationMap`, else `undefined`. */
157
+ readonly signatureWithDifferentOptions: string | undefined,
158
+ ) {}
159
+
160
+ /** This signature as seen with `newOptions`: the forms swap when `declarationMap` changed. */
161
+ getNewEmitSignature(oldOptions: CompilerOptions, newOptions: CompilerOptions): EmitSignature {
162
+ if ((oldOptions.declarationMap === true) === (newOptions.declarationMap === true)) return this;
163
+ const different = this.signatureWithDifferentOptions;
164
+ if (different === undefined) return new EmitSignature('', this.signature);
165
+ return new EmitSignature(different, undefined);
166
+ }
167
+ }
168
+
169
+ /** A diagnostic read from build info, resolved against the program when needed. */
170
+ class StoredDiagnostic {
171
+ constructor(
172
+ /** Path of the file if not the one it is stored for. */
173
+ readonly file: string,
174
+ readonly stored: BuildInfoDiagnostic,
175
+ readonly messageChain: StoredDiagnostic[],
176
+ readonly relatedInformation: StoredDiagnostic[],
177
+ ) {}
178
+
179
+ toDiagnostic(program: Program, file: SourceFile | undefined): Diagnostic | undefined {
180
+ let fileForDiagnostic: SourceFile | undefined = undefined;
181
+ if (this.file !== '') fileForDiagnostic = program.getSourceFileByPath(this.file);
182
+ else if (!this.stored.noFile) fileForDiagnostic = file;
183
+ const d = this.stored;
184
+ const repopulate = d.repopulateInfo;
185
+ if (repopulate !== undefined && fileForDiagnostic !== undefined) {
186
+ const details = repopulatedDetails(program, fileForDiagnostic, repopulate);
187
+ if (details !== undefined) {
188
+ // The entry as the program now has it, with the rest of the chain as stored.
189
+ const diagnosticFile = fileForDiagnostic.diagnosticFile();
190
+ const result = new Diagnostic(
191
+ diagnosticFile,
192
+ diagnosticFile.fromUtf8Offset(d.pos),
193
+ diagnosticFile.fromUtf8Offset(d.end),
194
+ details.message,
195
+ details.args,
196
+ );
197
+ for (const chain of this.messageChain) result.addMessageChain(chain.toDiagnostic(program, fileForDiagnostic));
198
+ return result;
199
+ }
200
+ }
201
+ const message = messageForKey(d.messageKey);
202
+ if (message === undefined) return undefined;
203
+ const diagnosticFile = fileForDiagnostic === undefined ? undefined : fileForDiagnostic.diagnosticFile();
204
+ const result = new Diagnostic(
205
+ diagnosticFile,
206
+ diagnosticFile === undefined ? d.pos : diagnosticFile.fromUtf8Offset(d.pos),
207
+ diagnosticFile === undefined ? d.end : diagnosticFile.fromUtf8Offset(d.end),
208
+ message,
209
+ d.messageArgs,
210
+ );
211
+ result.code = d.code;
212
+ result.category = d.category;
213
+ result.skippedOnNoEmit = d.skippedOnNoEmit;
214
+ for (const chain of this.messageChain) result.addMessageChain(chain.toDiagnostic(program, fileForDiagnostic));
215
+ for (const related of this.relatedInformation) {
216
+ result.addRelatedInfo(related.toDiagnostic(program, fileForDiagnostic));
217
+ }
218
+ return result;
219
+ }
220
+ }
221
+
222
+ /**
223
+ * The message and arguments of a message chain entry of `file` that depends on the program, as the
224
+ * program now has them (tsgo's `repopulateDiagnosticChain`); `undefined` for an unknown kind.
225
+ */
226
+ function repopulatedDetails(program: Program, file: SourceFile, info: RepopulateInfo): DiagnosticDetails | undefined {
227
+ const host = new ProgramCheckerHost(program);
228
+ switch (info.kind) {
229
+ case RepopulateKind.ModeMismatch:
230
+ return modeMismatchDetails(host, file);
231
+ case RepopulateKind.ModuleNotFound:
232
+ return moduleNotFoundDetails(
233
+ host,
234
+ file,
235
+ info.moduleReference,
236
+ info.mode,
237
+ info.packageName === '' ? info.moduleReference : info.packageName,
238
+ );
239
+ }
240
+ return undefined;
241
+ }
242
+
243
+ /**
244
+ * The computed diagnostics of `file` from the previous state, with the message chain entries that
245
+ * depend on the program recomputed (tsgo's `repopulateDiagnosticsOfFile`). Diagnostics as read from
246
+ * build info are recomputed when they are converted (`StoredDiagnostic.toDiagnostic`).
247
+ */
248
+ function repopulateFileDiagnostics(diagnostics: FileDiagnostics, program: Program, file: SourceFile): FileDiagnostics {
249
+ const computed = diagnostics.computed;
250
+ if (computed === undefined) return diagnostics;
251
+ let changed = false;
252
+ const result: Diagnostic[] = [];
253
+ for (const d of computed) {
254
+ const chain = repopulateChain(d.messageChain, program, file);
255
+ if (chain === undefined) result.push(d);
256
+ else {
257
+ const copy = d.clone();
258
+ copy.messageChain = chain;
259
+ result.push(copy);
260
+ changed = true;
261
+ }
262
+ }
263
+ return changed ? FileDiagnostics.of(result) : diagnostics;
264
+ }
265
+
266
+ /** `chain` with the entries that depend on the program recomputed; `undefined` if none do. */
267
+ function repopulateChain(chain: readonly Diagnostic[], program: Program, file: SourceFile): Diagnostic[] | undefined {
268
+ let changed = false;
269
+ const result: Diagnostic[] = [];
270
+ for (const entry of chain) {
271
+ if (entry.repopulateInfo !== undefined) {
272
+ result.push(repopulatedEntry(entry, program, file));
273
+ changed = true;
274
+ continue;
275
+ }
276
+ const nested = repopulateChain(entry.messageChain, program, file);
277
+ if (nested === undefined) result.push(entry);
278
+ else {
279
+ const copy = entry.clone();
280
+ copy.messageChain = nested;
281
+ result.push(copy);
282
+ changed = true;
283
+ }
284
+ }
285
+ return changed ? result : undefined;
286
+ }
287
+
288
+ /**
289
+ * A message chain entry of `file` as tsgo recomputes it: the program's message for an entry that
290
+ * depends on it, and only the location, message and chain of the entries below.
291
+ */
292
+ function repopulatedEntry(entry: Diagnostic, program: Program, file: SourceFile): Diagnostic {
293
+ const info = entry.repopulateInfo;
294
+ const details = info === undefined ? undefined : repopulatedDetails(program, file, info);
295
+ const result =
296
+ details === undefined
297
+ ? new Diagnostic(file.diagnosticFile(), entry.pos, entry.end, entry.message, entry.args)
298
+ : new Diagnostic(file.diagnosticFile(), entry.pos, entry.end, details.message, details.args);
299
+ if (details === undefined) {
300
+ result.code = entry.code;
301
+ result.category = entry.category;
302
+ }
303
+ for (const nested of entry.messageChain) result.addMessageChain(repopulatedEntry(nested, program, file));
304
+ return result;
305
+ }
306
+
307
+ /** Diagnostics of a file: computed, or still as read from build info. */
308
+ class FileDiagnostics {
309
+ constructor(
310
+ private diagnostics: Diagnostic[] | undefined,
311
+ readonly stored: StoredDiagnostic[] | undefined,
312
+ ) {}
313
+
314
+ static of(diagnostics: Diagnostic[]): FileDiagnostics {
315
+ return new FileDiagnostics(diagnostics, undefined);
316
+ }
317
+
318
+ get computed(): Diagnostic[] | undefined {
319
+ return this.diagnostics;
320
+ }
321
+
322
+ isEmpty(): boolean {
323
+ const diagnostics = this.diagnostics;
324
+ if (diagnostics !== undefined) return diagnostics.length === 0;
325
+ const stored = this.stored;
326
+ return stored === undefined || stored.length === 0;
327
+ }
328
+
329
+ getDiagnostics(program: Program, file: SourceFile): Diagnostic[] {
330
+ const existing = this.diagnostics;
331
+ if (existing !== undefined) return existing;
332
+ const result: Diagnostic[] = [];
333
+ const stored = this.stored;
334
+ if (stored !== undefined) {
335
+ for (const d of stored) {
336
+ const diagnostic = d.toDiagnostic(program, file);
337
+ if (diagnostic !== undefined) result.push(diagnostic);
338
+ }
339
+ }
340
+ this.diagnostics = result;
341
+ return result;
342
+ }
343
+ }
344
+
345
+ /** Files and the files they reference, for finding what a change affects. */
346
+ class ReferenceMap {
347
+ readonly references = new Map<string, Set<string>>();
348
+ private referencedBy: Map<string, Set<string>> | undefined = undefined;
349
+ /** The number of references in `references`, once computed (`getReferencedBy`). */
350
+ private referenceCount = -1;
351
+ /** The number of sets `getReferencedBy` looked into before building `referencedBy`. */
352
+ private setsScanned = 0;
353
+
354
+ /**
355
+ * The files that reference `path`, in the order of `references`. The first queries look into each
356
+ * set; once those have looked into as many sets as there are references, the inverse map is built.
357
+ */
358
+ getReferencedBy(path: string): string[] {
359
+ let referencedBy = this.referencedBy;
360
+ if (referencedBy === undefined) {
361
+ if (this.referenceCount < 0) {
362
+ let count = 0;
363
+ for (const references of this.references.values()) count += references.size;
364
+ this.referenceCount = count;
365
+ }
366
+ if (this.setsScanned + this.references.size <= this.referenceCount) {
367
+ this.setsScanned += this.references.size;
368
+ const result: string[] = [];
369
+ for (const [key, references] of this.references) if (references.has(path)) result.push(key);
370
+ return result;
371
+ }
372
+ referencedBy = new Map();
373
+ for (const [key, references] of this.references) {
374
+ for (const reference of references) {
375
+ let set = referencedBy.get(reference);
376
+ if (set === undefined) {
377
+ set = new Set();
378
+ referencedBy.set(reference, set);
379
+ }
380
+ set.add(key);
381
+ }
382
+ }
383
+ this.referencedBy = referencedBy;
384
+ }
385
+ const result = referencedBy.get(path);
386
+ return result === undefined ? [] : [...result];
387
+ }
388
+ }
389
+
390
+ /**
391
+ * The `fileIdsList` of a build info that was read: the paths of its file ids, the set of paths the
392
+ * snapshot read from it has for each list, and the list of each file of its referenced map.
393
+ */
394
+ class FileIdLists {
395
+ readonly listOfFile = new Map<string, number>();
396
+ /** `hashOfIds` of each list. */
397
+ readonly hashes: number[] = [];
398
+ /** The last id of each list whose ids are ascending from 1 (0 for an empty list), and -1 for the others. */
399
+ readonly lastIds: number[] = [];
400
+ /**
401
+ * The ids of every list, one after another, and where each list starts in them (with the end of the
402
+ * last list after the last start), in shared memory that reference threads read
403
+ * (`compareReferencesOnThreads`).
404
+ */
405
+ readonly listStarts: Int32Array;
406
+ readonly listIds: Int32Array;
407
+ private readonly pathIndexes = new Map<string, number>();
408
+
409
+ constructor(
410
+ readonly filePaths: readonly string[],
411
+ readonly ids: readonly number[][],
412
+ readonly sets: readonly ReadonlySet<string>[],
413
+ /** The ids of each list joined with commas, as read (`BuildInfo.fileIdsListText`), or empty. */
414
+ readonly texts: readonly string[],
415
+ ) {
416
+ let total = 0;
417
+ for (const list of ids) {
418
+ this.hashes.push(hashOfIds(list));
419
+ let previous = 0;
420
+ for (const id of list) {
421
+ if (id <= previous) {
422
+ previous = -1;
423
+ break;
424
+ }
425
+ previous = id;
426
+ }
427
+ this.lastIds.push(previous);
428
+ total += list.length;
429
+ }
430
+ const starts = new Int32Array(new SharedArrayBuffer(4 * (ids.length + 1)));
431
+ const all = new Int32Array(new SharedArrayBuffer(4 * total));
432
+ this.listStarts = starts;
433
+ this.listIds = all;
434
+ let at = 0;
435
+ for (let k = 0; k < ids.length; k++) {
436
+ starts[k] = at;
437
+ // An id with no path is 0, as is one outside of the int32 range.
438
+ for (const id of ids[k]) all[at++] = id >= 1 && id <= filePaths.length ? id : 0;
439
+ }
440
+ starts[ids.length] = at;
441
+ for (let i = 0; i < filePaths.length; i++) this.pathIndexes.set(filePaths[i], i);
442
+ }
443
+
444
+ /** The index in `filePaths` of each path; `undefined` where two file ids have the same path. */
445
+ indexOfPath(): Map<string, number> | undefined {
446
+ return this.pathIndexes.size === this.filePaths.length ? this.pathIndexes : undefined;
447
+ }
448
+
449
+ /** The index of the list whose set is `references`, the old references of the file at `path`; -1 if none or empty. */
450
+ listOf(path: string, references: ReadonlySet<string> | undefined): number {
451
+ const index = this.listOfFile.get(path);
452
+ if (index === undefined || references === undefined || references.size === 0) return -1;
453
+ return this.sets[index] === references ? index : -1;
454
+ }
455
+ }
456
+
457
+ /**
458
+ * Compares the references of files (`getReferencedFiles`) with their lists of file ids in the build
459
+ * info read (`FileIdLists`) by the indexes of the paths, without collecting each file's references
460
+ * into a set. Every file references the files that declare ambient modules: those of a list are
461
+ * counted as the list is read. Reference threads compare with their own comparer of the same lists
462
+ * (`compareReferencesOnThreads`).
463
+ */
464
+ class ReferenceListComparer {
465
+ /** For each index, the comparison whose list has it. */
466
+ private readonly listed: Int32Array;
467
+ /** For each index, 1 where its file is in the old state and not in the program, 2 where not, 0 if not known yet. */
468
+ private readonly missing: Uint8Array;
469
+ private comparison = 0;
470
+
471
+ constructor(
472
+ /** The number of file ids. */
473
+ readonly count: number,
474
+ /** `FileIdLists.listStarts` and `FileIdLists.listIds`. */
475
+ readonly listStarts: Int32Array,
476
+ readonly listIds: Int32Array,
477
+ readonly indexOfPath: ReadonlyMap<string, number>,
478
+ /** 1 at the index of each file that declares ambient modules, in shared memory. */
479
+ readonly declaresAmbientModules: Uint8Array,
480
+ readonly ambientModuleFileCount: number,
481
+ /** Whether a file that declares ambient modules has no file id. */
482
+ readonly ambientModuleFileNotListed: boolean,
483
+ ) {
484
+ this.listed = new Int32Array(count);
485
+ this.missing = new Uint8Array(count);
486
+ }
487
+
488
+ /** The comparer of `lists` for a program whose files that declare ambient modules are `ambientModuleFiles`. */
489
+ static of(
490
+ lists: FileIdLists,
491
+ indexOfPath: ReadonlyMap<string, number>,
492
+ ambientModuleFiles: readonly string[],
493
+ ): ReferenceListComparer {
494
+ const count = lists.filePaths.length;
495
+ const declaresAmbientModules = new Uint8Array(new SharedArrayBuffer(count));
496
+ let ambientModuleFileCount = 0;
497
+ let ambientModuleFileNotListed = false;
498
+ for (const path of ambientModuleFiles) {
499
+ const index = indexOfPath.get(path);
500
+ if (index === undefined) ambientModuleFileNotListed = true;
501
+ else {
502
+ declaresAmbientModules[index] = 1;
503
+ ambientModuleFileCount++;
504
+ }
505
+ }
506
+ return new ReferenceListComparer(
507
+ count,
508
+ lists.listStarts,
509
+ lists.listIds,
510
+ indexOfPath,
511
+ declaresAmbientModules,
512
+ ambientModuleFileCount,
513
+ ambientModuleFileNotListed,
514
+ );
515
+ }
516
+
517
+ /**
518
+ * Whether the references of `file` are the paths of the list at `listIndex`. `undefined` where the
519
+ * list has an id with no path, whose set has the path '', or where `file` has no file id.
520
+ */
521
+ sameReferences(checked: CheckedProgram, file: SourceFile, listIndex: number): boolean | undefined {
522
+ const selfIndex = this.indexOfPath.get(file.path);
523
+ if (selfIndex === undefined) return undefined;
524
+ // A file that declares ambient modules and has no file id is not in the list, and is not `file`.
525
+ if (this.ambientModuleFileNotListed) return false;
526
+ const count = this.count;
527
+ const listed = this.listed;
528
+ const listIds = this.listIds;
529
+ const declaresAmbientModules = this.declaresAmbientModules;
530
+ const comparison = ++this.comparison;
531
+ let listedCount = 0;
532
+ let listedAmbientModuleFiles = 0;
533
+ const end = this.listStarts[listIndex + 1];
534
+ for (let k = this.listStarts[listIndex]; k < end; k++) {
535
+ const id = listIds[k];
536
+ if (id < 1 || id > count) return undefined;
537
+ const index = id - 1;
538
+ if (listed[index] !== comparison) {
539
+ listed[index] = comparison;
540
+ listedCount++;
541
+ if (declaresAmbientModules[index] === 1 && index !== selfIndex) listedAmbientModuleFiles++;
542
+ }
543
+ }
544
+ // Each file that declares ambient modules, other than `file`, is in the list.
545
+ const ambientModuleFiles = this.ambientModuleFileCount - declaresAmbientModules[selfIndex];
546
+ if (listedAmbientModuleFiles !== ambientModuleFiles) return false;
547
+ // Each of the other references is in the list, and the list has no more paths.
548
+ let otherReferences = 0;
549
+ const ownReferences = new Set<string>();
550
+ addOwnReferencedFiles(checked, file, ownReferences);
551
+ for (const path of ownReferences) {
552
+ const index = this.indexOfPath.get(path);
553
+ if (index === undefined || listed[index] !== comparison) return false;
554
+ if (declaresAmbientModules[index] === 0 || index === selfIndex) otherReferences++;
555
+ }
556
+ return listedCount === ambientModuleFiles + otherReferences;
557
+ }
558
+
559
+ /**
560
+ * Whether a file of the list at `listIndex` of `lists` is not in `program` and is in `oldSnapshot`,
561
+ * as for the references of a file that are the list's paths.
562
+ */
563
+ hasMissingFile(listIndex: number, lists: FileIdLists, program: Program, oldSnapshot: Snapshot): boolean {
564
+ const filePaths = lists.filePaths;
565
+ const missing = this.missing;
566
+ const listIds = this.listIds;
567
+ const end = this.listStarts[listIndex + 1];
568
+ for (let k = this.listStarts[listIndex]; k < end; k++) {
569
+ const index = listIds[k] - 1;
570
+ let state = missing[index];
571
+ if (state === 0) {
572
+ const path = filePaths[index];
573
+ state = program.getSourceFileByPath(path) === undefined && oldSnapshot.fileInfos.has(path) ? 1 : 2;
574
+ missing[index] = state;
575
+ }
576
+ if (state === 1) return true;
577
+ }
578
+ return false;
579
+ }
580
+ }
581
+
582
+ // ---- Reference threads
583
+
584
+ /**
585
+ * What a reference thread reads (`compareReferencesOfThread`): the shared, published program, where its
586
+ * ids continue (above `nodeIds` and `symbolIds`), the comparer's lists (`ReferenceListComparer`), the list
587
+ * of each program file by file index (-1 for none), the shared counter of the chunks taken and the index
588
+ * of the file the main thread is at, and where it writes the verdict of each file (`ReferenceVerdict`).
589
+ */
590
+ export type ReferenceJob = {
591
+ readonly program: Program;
592
+ readonly index: number;
593
+ readonly nodeIds: number;
594
+ readonly symbolIds: number;
595
+ readonly count: number;
596
+ readonly listStarts: SharedArrayBuffer;
597
+ readonly listIds: SharedArrayBuffer;
598
+ readonly paths: PathIndexes;
599
+ readonly declaresAmbientModules: SharedArrayBuffer;
600
+ readonly ambientModuleFileCount: number;
601
+ readonly lists: SharedArrayBuffer;
602
+ readonly verdicts: SharedArrayBuffer;
603
+ readonly counter: SharedArrayBuffer;
604
+ readonly progress: SharedArrayBuffer;
605
+ };
606
+
607
+ /** `FileIdLists.indexOfPath`, published for reference threads (a published map alone is not sent). */
608
+ class PathIndexes {
609
+ constructor(readonly indexOfPath: ReadonlyMap<string, number>) {}
610
+ }
611
+
612
+ /** Starts a reference thread with `job` (main.ts owns the worker entry point). */
613
+ export type ReferenceSpawn = (job: ReferenceJob) => void;
614
+
615
+ export class ReferenceThreads {
616
+ /** Set where reference threads can be started: in scriptc builds, which share the program with threads. */
617
+ spawn: ReferenceSpawn | undefined = undefined;
618
+ }
619
+
620
+ export const referenceThreads = new ReferenceThreads();
621
+
622
+ /** The result of `ReferenceListComparer.sameReferences` for a file, by file index. */
623
+ const enum ReferenceVerdict {
624
+ NotCompared,
625
+ Same,
626
+ Different,
627
+ Unknown,
628
+ }
629
+
630
+ /** The files a thread takes at a time. */
631
+ const referenceChunk = 32;
632
+
633
+ /**
634
+ * The fewest files compared per reference thread, unless the number of checkers was given
635
+ * (`--checkers`): starting a thread takes about as long as comparing that many files.
636
+ */
637
+ const filesPerReferenceThread = 256;
638
+
639
+ /**
640
+ * The lists of the files of a program (`FileIdLists.listOf`) and the verdicts of reference threads, by
641
+ * file index, and the index of the file this thread is at.
642
+ */
643
+ class ReferenceVerdicts {
644
+ constructor(
645
+ readonly lists: Int32Array,
646
+ readonly verdicts: Int32Array,
647
+ private readonly progress: Int32Array,
648
+ ) {}
649
+
650
+ /**
651
+ * `ReferenceListComparer.sameReferences` of the file at `index` with the list at `listIndex`, as a
652
+ * thread found it, or as `comparer` finds it if no thread has yet. Threads skip the files before
653
+ * `index` from then on.
654
+ */
655
+ sameReferences(
656
+ comparer: ReferenceListComparer,
657
+ checked: CheckedProgram,
658
+ file: SourceFile,
659
+ index: number,
660
+ listIndex: number,
661
+ ): boolean | undefined {
662
+ Atomics.store(this.progress, 0, index + 1);
663
+ const verdict = Atomics.load(this.verdicts, index);
664
+ if (verdict === ReferenceVerdict.Same) return true;
665
+ if (verdict === ReferenceVerdict.Different) return false;
666
+ if (verdict === ReferenceVerdict.Unknown) return undefined;
667
+ return comparer.sameReferences(checked, file, listIndex);
668
+ }
669
+
670
+ /** Stops the threads once this thread has compared every file it needs to. */
671
+ done(): void {
672
+ Atomics.store(this.progress, 0, this.lists.length);
673
+ }
674
+ }
675
+
676
+ /**
677
+ * A reference thread: compares the references of the files of `job` with their lists with its own
678
+ * checker, a chunk of files at a time from the last file back, and writes each verdict, until it reaches
679
+ * the files the main thread compared (`ReferenceVerdicts.sameReferences`).
680
+ */
681
+ export function compareReferencesOfThread(program: Program, job: ReferenceJob): void {
682
+ const comparer = new ReferenceListComparer(
683
+ job.count,
684
+ new Int32Array(job.listStarts),
685
+ new Int32Array(job.listIds),
686
+ job.paths.indexOfPath,
687
+ new Uint8Array(job.declaresAmbientModules),
688
+ job.ambientModuleFileCount,
689
+ false,
690
+ );
691
+ const checked = new CheckedProgram(program);
692
+ const lists = new Int32Array(job.lists);
693
+ const verdicts = new Int32Array(job.verdicts);
694
+ const counter = new Int32Array(job.counter);
695
+ const progress = new Int32Array(job.progress);
696
+ const files = program.getSourceFiles();
697
+ for (;;) {
698
+ const end = files.length - Atomics.add(counter, 0, 1) * referenceChunk;
699
+ if (end <= Atomics.load(progress, 0)) return;
700
+ const start = Math.max(end - referenceChunk, 0);
701
+ for (let i = start; i < end; i++) {
702
+ const listIndex = lists[i];
703
+ if (listIndex < 0) continue;
704
+ const same = comparer.sameReferences(checked, files[i]!, listIndex);
705
+ Atomics.store(
706
+ verdicts,
707
+ i,
708
+ same === undefined ? ReferenceVerdict.Unknown : same ? ReferenceVerdict.Same : ReferenceVerdict.Different,
709
+ );
710
+ }
711
+ }
712
+ }
713
+
714
+ /**
715
+ * Where the program of `checked` is shared with threads (`CheckedProgram.referenceThreads`), starts
716
+ * reference threads that compare the references of its files with their lists of file ids in
717
+ * `oldSnapshot`, from the last file back, while this thread compares them from the first file
718
+ * (`ReferenceVerdicts.sameReferences`) until it reaches those the threads compared. `undefined` where no
719
+ * threads start: without them, or with too few files to compare (`filesPerReferenceThread`).
720
+ */
721
+ function compareReferencesOnThreads(
722
+ checked: CheckedProgram,
723
+ comparer: ReferenceListComparer,
724
+ lists: FileIdLists,
725
+ oldSnapshot: Snapshot,
726
+ ): ReferenceVerdicts | undefined {
727
+ const spawn = referenceThreads.spawn;
728
+ const available = checked.referenceThreads - 1;
729
+ if (spawn === undefined || available < 1 || !checked.sharedWithCheckers || comparer.ambientModuleFileNotListed)
730
+ return undefined;
731
+ const program = checked.program;
732
+ const files = program.getSourceFiles();
733
+ const listsBuffer = new SharedArrayBuffer(4 * files.length);
734
+ const listOfFiles = new Int32Array(listsBuffer);
735
+ let compared = 0;
736
+ for (let i = 0; i < files.length; i++) {
737
+ const path = files[i]!.path;
738
+ const listIndex = lists.listOf(path, oldSnapshot.referencedMap.references.get(path));
739
+ listOfFiles[i] = listIndex;
740
+ if (listIndex >= 0) compared++;
741
+ }
742
+ const threads = Math.min(
743
+ available,
744
+ program.options.checkers !== undefined
745
+ ? Math.ceil(compared / referenceChunk)
746
+ : Math.floor(compared / filesPerReferenceThread),
747
+ );
748
+ if (threads < 1) return undefined;
749
+ const paths = publish(new PathIndexes(comparer.indexOfPath));
750
+ const verdictsBuffer = new SharedArrayBuffer(4 * files.length);
751
+ const counterBuffer = new SharedArrayBuffer(4);
752
+ const progressBuffer = new SharedArrayBuffer(4);
753
+ for (let index = 1; index <= threads; index++)
754
+ spawn({
755
+ program,
756
+ index,
757
+ nodeIds: lastNodeIdValue(),
758
+ symbolIds: lastSymbolIdValue(),
759
+ count: comparer.count,
760
+ listStarts: comparer.listStarts.buffer as SharedArrayBuffer,
761
+ listIds: comparer.listIds.buffer as SharedArrayBuffer,
762
+ paths,
763
+ declaresAmbientModules: comparer.declaresAmbientModules.buffer as SharedArrayBuffer,
764
+ ambientModuleFileCount: comparer.ambientModuleFileCount,
765
+ lists: listsBuffer,
766
+ verdicts: verdictsBuffer,
767
+ counter: counterBuffer,
768
+ progress: progressBuffer,
769
+ });
770
+ return new ReferenceVerdicts(listOfFiles, new Int32Array(verdictsBuffer), new Int32Array(progressBuffer));
771
+ }
772
+
773
+ /** A hash of `ids`, for finding lists of file ids with the same ids. */
774
+ function hashOfIds(ids: readonly number[]): number {
775
+ let hash = 0x811c9dc5 ^ ids.length;
776
+ for (const id of ids) hash = Math.imul(hash ^ id, 0x01000193);
777
+ return hash;
778
+ }
779
+
780
+ function sameIds(a: readonly number[], b: readonly number[]): boolean {
781
+ if (a.length !== b.length) return false;
782
+ for (let i = 0; i < a.length; i++) if (a[i] !== b[i]) return false;
783
+ return true;
784
+ }
785
+
786
+ function sameSet(a: ReadonlySet<string> | undefined, b: ReadonlySet<string> | undefined): boolean {
787
+ if (a === undefined || b === undefined) return a === b;
788
+ if (a.size !== b.size) return false;
789
+ for (const value of a) if (!b.has(value)) return false;
790
+ return true;
791
+ }
792
+
793
+ /** Whether `path` is `..` or a sequence of `../` up from a directory. */
794
+ function isParentDirectoryPath(path: string): boolean {
795
+ for (let i = 0; i < path.length; i += 3) {
796
+ if (!path.startsWith('..', i) || (i + 2 < path.length && path[i + 2] !== '/')) return false;
797
+ }
798
+ return true;
799
+ }
800
+
801
+ function compareStrings(a: string, b: string): number {
802
+ return a < b ? -1 : a > b ? 1 : 0;
803
+ }
804
+
805
+ /** True, false or not computed yet. */
806
+ const enum Tristate {
807
+ Unknown,
808
+ False,
809
+ True,
810
+ }
811
+
812
+ /** The state of an incremental program. */
813
+ export class Snapshot {
814
+ readonly fileInfos = new Map<string, FileInfo>();
815
+ options: CompilerOptions;
816
+ readonly referencedMap = new ReferenceMap();
817
+ /**
818
+ * The lists of file ids of the build info read last, whose sets of paths the referenced map keeps
819
+ * for files whose references did not change.
820
+ */
821
+ fileIdLists: FileIdLists | undefined = undefined;
822
+ readonly semanticDiagnosticsPerFile = new Map<string, FileDiagnostics>();
823
+ readonly emitDiagnosticsPerFile = new Map<string, FileDiagnostics>();
824
+ changedFilesSet = new Set<string>();
825
+ readonly affectedFilesPendingEmit = new Map<string, number>();
826
+ latestChangedDtsFile = '';
827
+ readonly emitSignatures = new Map<string, EmitSignature>();
828
+ hasErrors = Tristate.Unknown;
829
+ hasSemanticErrors = false;
830
+ checkPending = false;
831
+ packageJsons: string[] | undefined = undefined;
832
+ missingPackageJsons: string[] = [];
833
+
834
+ buildInfoEmitPending = false;
835
+ hasErrorsFromOldState = Tristate.Unknown;
836
+ hasSemanticErrorsFromOldState = false;
837
+ packageJsonsFromOldState: string[] = [];
838
+ missingPackageJsonsFromOldState: string[] = [];
839
+ private allFilesExcludingDefaultLibraryFile: SourceFile[] | undefined = undefined;
840
+ hasChangedDtsFile = false;
841
+ hasEmitDiagnostics = false;
842
+ /**
843
+ * The version (`computeHash` of the text) of each source file of the program, by file: a watch
844
+ * rebuild reuses the files that did not change, and takes their versions from here.
845
+ */
846
+ readonly versionsByFile = new Map<SourceFile, string>();
847
+
848
+ constructor(options: CompilerOptions) {
849
+ this.options = options;
850
+ }
851
+
852
+ addFileToChangeSet(path: string): void {
853
+ this.changedFilesSet.add(path);
854
+ this.buildInfoEmitPending = true;
855
+ }
856
+
857
+ addFileToAffectedFilesPendingEmit(path: string, emitKind: number): void {
858
+ const existing = this.affectedFilesPendingEmit.get(path) ?? 0;
859
+ this.affectedFilesPendingEmit.set(path, existing | emitKind);
860
+ if ((emitKind & FileEmitKind.DtsErrors) !== 0) this.emitDiagnosticsPerFile.delete(path);
861
+ this.buildInfoEmitPending = true;
862
+ }
863
+
864
+ getAllFilesExcludingDefaultLibraryFile(program: Program, firstSourceFile: SourceFile | undefined): SourceFile[] {
865
+ let result = this.allFilesExcludingDefaultLibraryFile;
866
+ if (result === undefined) {
867
+ result = [];
868
+ if (firstSourceFile !== undefined && !program.isSourceFileDefaultLibrary(firstSourceFile.path)) {
869
+ result.push(firstSourceFile);
870
+ }
871
+ for (const file of program.getSourceFiles()) {
872
+ if (file !== firstSourceFile && !program.isSourceFileDefaultLibrary(file.path)) result.push(file);
873
+ }
874
+ this.allFilesExcludingDefaultLibraryFile = result;
875
+ }
876
+ return result;
877
+ }
878
+
879
+ /** Without `incremental`, `tsc -b` only records whether there were errors. */
880
+ canUseIncrementalState(): boolean {
881
+ return isIncremental(this.options) || this.options.build !== true;
882
+ }
883
+ }
884
+
885
+ /**
886
+ * Gives each file of `paths` whose signature in `snapshot` is its version the signature of its text in
887
+ * `last`, the program of the build that made `snapshot`, from its declaration file. A build without build
888
+ * info (a watch without `incremental`) leaves versions as the signatures of the files it computed none for,
889
+ * the first build's among them. A build on `snapshot` then compares a changed file's new signature with the
890
+ * last one, as for files whose signatures were computed, and rechecks the importers only when the
891
+ * declaration file changed. Files that forced declaration emit doesn't write keep their versions.
892
+ */
893
+ export function computeLastSignatures(snapshot: Snapshot, last: CheckedProgram, paths: readonly string[]): void {
894
+ if (isIncremental(snapshot.options)) return;
895
+ const options = last.program.options;
896
+ let emitter: ProgramEmitter | undefined = undefined;
897
+ for (const path of paths) {
898
+ const info = snapshot.fileInfos.get(path);
899
+ if (info === undefined || info.signature !== info.version) continue;
900
+ const file = last.program.getSourceFileByPath(path);
901
+ if (file === undefined || file.isDeclarationFile || !sourceFileMayBeEmitted(file, options)) continue;
902
+ emitter ??= new ProgramEmitter(last);
903
+ const signature = declarationSignature(emitter, file, options);
904
+ if (signature !== '') info.signature = signature;
905
+ }
906
+ }
907
+
908
+ /**
909
+ * The shape signature of `file` from its forced declaration emit (`updateShapeSignature`), or `''` where
910
+ * nothing is written, for which the file's version is the signature.
911
+ */
912
+ export function declarationSignature(emitter: ProgramEmitter, file: SourceFile, options: CompilerOptions): string {
913
+ const emitted = emitter.forcedDeclaration(file);
914
+ // A file without declarations, such as a script of statements, has an empty declaration file and a signature.
915
+ if (!emitted.written) return '';
916
+ return computeSignatureWithDiagnostics(file, emitted.text, emitted.diagnostics, options);
917
+ }
918
+
919
+ /** The signature of a declaration emit: its text up to the source map comment, and its errors. */
920
+ function computeSignatureWithDiagnostics(
921
+ file: SourceFile,
922
+ text: string,
923
+ diagnostics: readonly Diagnostic[],
924
+ options: CompilerOptions,
925
+ ): string {
926
+ let result = getTextHandlingSourceMapForSignature(text, options);
927
+ for (const d of diagnostics) result += diagnosticToString(d, file);
928
+ return computeHash(result);
929
+ }
930
+
931
+ function getTextHandlingSourceMapForSignature(text: string, options: CompilerOptions): string {
932
+ if (options.declarationMap !== true) return text;
933
+ const pos = text.lastIndexOf('//# sourceMappingURL=');
934
+ return pos < 0 ? text : text.slice(0, pos);
935
+ }
936
+
937
+ function diagnosticToString(d: Diagnostic, file: SourceFile): string {
938
+ let result = '\n';
939
+ const diagnosticFile = d.file;
940
+ if (diagnosticFile !== undefined && diagnosticFile !== file.diagnosticFile()) {
941
+ result += ensurePathIsNonModuleName(
942
+ getRelativePathFromDirectory(getDirectoryPath(file.path), diagnosticFile.fileName, true),
943
+ );
944
+ }
945
+ if (diagnosticFile !== undefined) {
946
+ // UTF-8 offsets, like tsgo's.
947
+ const pos = diagnosticFile.toUtf8Offset(d.pos);
948
+ result += `(${pos},${diagnosticFile.toUtf8Offset(d.end) - pos}): `;
949
+ }
950
+ result += categoryName(d.category) + String(d.code) + ': ' + messageKey(d.message) + '\n';
951
+ for (const arg of d.args) result += arg + '\n';
952
+ for (const chain of d.messageChain) result += diagnosticToString(chain, file);
953
+ for (const related of d.relatedInformation) result += diagnosticToString(related, file);
954
+ return result;
955
+ }
956
+
957
+ // ---- Option comparisons
958
+
959
+ function optionValuesEqual(a: CompilerOptionValue | undefined, b: CompilerOptionValue | undefined): boolean {
960
+ if (Array.isArray(a) || Array.isArray(b)) {
961
+ if (!Array.isArray(a) || !Array.isArray(b) || a.length !== b.length) return false;
962
+ for (let i = 0; i < a.length; i++) if (a[i] !== b[i]) return false;
963
+ return true;
964
+ }
965
+ return a === b;
966
+ }
967
+
968
+ function pathsEqual(a: CompilerOptions, b: CompilerOptions): boolean {
969
+ const x = a.paths;
970
+ const y = b.paths;
971
+ if (x === undefined || y === undefined) return x === y;
972
+ if (x.size !== y.size) return false;
973
+ const keysX = [...x.keys()];
974
+ const keysY = [...y.keys()];
975
+ for (let i = 0; i < keysX.length; i++) {
976
+ if (keysX[i] !== keysY[i]) return false;
977
+ const valueX = x.get(keysX[i]);
978
+ const valueY = y.get(keysY[i]);
979
+ if (valueX === undefined || valueY === undefined) {
980
+ if (valueX !== valueY) return false;
981
+ } else if (!optionValuesEqual(valueX, valueY)) return false;
982
+ }
983
+ return true;
984
+ }
985
+
986
+ function optionsHaveChanges(oldOptions: CompilerOptions, newOptions: CompilerOptions, affects: Affects): boolean {
987
+ if (oldOptions === newOptions) return false;
988
+ for (const option of compilerOptionDeclarationsInFieldOrder()) {
989
+ if (((option.affects ?? 0) & affects) === 0) continue;
990
+ if (option.strictFlag === true) {
991
+ const oldValue = compilerOptionValue(oldOptions, option.name);
992
+ const newValue = compilerOptionValue(newOptions, option.name);
993
+ if (
994
+ getStrictOptionValue(oldOptions, typeof oldValue === 'boolean' ? oldValue : undefined) !==
995
+ getStrictOptionValue(newOptions, typeof newValue === 'boolean' ? newValue : undefined)
996
+ ) {
997
+ return true;
998
+ }
999
+ continue;
1000
+ }
1001
+ if (option.allowJsFlag === true) {
1002
+ if (getAllowJS(oldOptions) !== getAllowJS(newOptions)) return true;
1003
+ continue;
1004
+ }
1005
+ if (option.name === 'paths') {
1006
+ if (!pathsEqual(oldOptions, newOptions)) return true;
1007
+ continue;
1008
+ }
1009
+ if (
1010
+ !optionValuesEqual(compilerOptionValue(oldOptions, option.name), compilerOptionValue(newOptions, option.name))
1011
+ ) {
1012
+ return true;
1013
+ }
1014
+ }
1015
+ return false;
1016
+ }
1017
+
1018
+ export function compilerOptionsAffectSemanticDiagnostics(a: CompilerOptions, b: CompilerOptions): boolean {
1019
+ return optionsHaveChanges(a, b, Affects.SemanticDiagnostics);
1020
+ }
1021
+
1022
+ export function compilerOptionsAffectDeclarationPath(a: CompilerOptions, b: CompilerOptions): boolean {
1023
+ return optionsHaveChanges(a, b, Affects.DeclarationPath);
1024
+ }
1025
+
1026
+ export function compilerOptionsAffectEmit(a: CompilerOptions, b: CompilerOptions): boolean {
1027
+ return optionsHaveChanges(a, b, Affects.Emit);
1028
+ }
1029
+
1030
+ // ---- Reading build info
1031
+
1032
+ /** Reads the build info of a project. */
1033
+ export abstract class BuildInfoReader {
1034
+ abstract readBuildInfo(config: ParsedCommandLine): BuildInfo | undefined;
1035
+ }
1036
+
1037
+ /** Reads build info files from a file system. */
1038
+ export class FileBuildInfoReader extends BuildInfoReader {
1039
+ constructor(private readonly fs: FileSystem) {
1040
+ super();
1041
+ }
1042
+
1043
+ readBuildInfo(config: ParsedCommandLine): BuildInfo | undefined {
1044
+ const fileName = config.buildInfoFileName();
1045
+ if (fileName === '') return undefined;
1046
+ const text = this.fs.readFile(fileName);
1047
+ return text === undefined ? undefined : parseBuildInfo(text);
1048
+ }
1049
+ }
1050
+
1051
+ /** The state recorded by the previous build, if it can be used. */
1052
+ export function readBuildInfoProgram(
1053
+ config: ParsedCommandLine,
1054
+ reader: BuildInfoReader,
1055
+ defaultLibraryPath: string,
1056
+ currentDirectory: string,
1057
+ ): Snapshot | undefined {
1058
+ const buildInfo = reader.readBuildInfo(config);
1059
+ if (buildInfo === undefined || !buildInfo.isValidVersion() || !buildInfo.isIncremental()) return undefined;
1060
+ return buildInfoToSnapshot(buildInfo, config, defaultLibraryPath, currentDirectory);
1061
+ }
1062
+
1063
+ function storedDiagnostics(
1064
+ diagnostics: readonly BuildInfoDiagnostic[],
1065
+ filePaths: readonly string[],
1066
+ ): StoredDiagnostic[] {
1067
+ return diagnostics.map(
1068
+ (d) =>
1069
+ new StoredDiagnostic(
1070
+ d.file !== 0 && d.file <= filePaths.length ? filePaths[d.file - 1] : '',
1071
+ d,
1072
+ storedDiagnostics(d.messageChain, filePaths),
1073
+ storedDiagnostics(d.relatedInformation, filePaths),
1074
+ ),
1075
+ );
1076
+ }
1077
+
1078
+ function buildInfoToSnapshot(
1079
+ buildInfo: BuildInfo,
1080
+ config: ParsedCommandLine,
1081
+ defaultLibraryPath: string,
1082
+ currentDirectory: string,
1083
+ ): Snapshot {
1084
+ const useCaseSensitiveFileNames = config.useCaseSensitiveFileNames;
1085
+ const buildInfoDirectory = getDirectoryPath(getNormalizedAbsolutePath(config.buildInfoFileName(), currentDirectory));
1086
+ const filePaths = buildInfo.fileNames.map((fileName) =>
1087
+ isBuildInfoFileNameDefaultLibrary(fileName)
1088
+ ? toPath(combinePaths(defaultLibraryPath, fileName), currentDirectory, useCaseSensitiveFileNames)
1089
+ : toPath(fileName, buildInfoDirectory, useCaseSensitiveFileNames),
1090
+ );
1091
+ const filePath = (fileId: number): string => (fileId >= 1 && fileId <= filePaths.length ? filePaths[fileId - 1] : '');
1092
+ const fileSets = buildInfo.fileIdsList.map((ids) => {
1093
+ const set = new Set<string>();
1094
+ for (const id of ids) set.add(filePath(id));
1095
+ return set;
1096
+ });
1097
+ const snapshot = new Snapshot(buildInfo.getCompilerOptions(buildInfoDirectory));
1098
+
1099
+ const isComposite = snapshot.options.composite === true;
1100
+ for (let i = 0; i < buildInfo.fileInfos.length; i++) {
1101
+ const path = filePath(i + 1);
1102
+ const info = fileInfoFromBuildInfo(buildInfo.fileInfos[i]);
1103
+ snapshot.fileInfos.set(path, info);
1104
+ if (info.signature !== '' && isComposite)
1105
+ snapshot.emitSignatures.set(path, new EmitSignature(info.signature, undefined));
1106
+ }
1107
+ for (const value of buildInfo.emitSignatures) {
1108
+ const path = filePath(value.fileId);
1109
+ if (value.noEmitSignature()) snapshot.emitSignatures.delete(path);
1110
+ else if (value.differsOnlyInDtsMap) {
1111
+ const existing = snapshot.emitSignatures.get(path);
1112
+ snapshot.emitSignatures.set(path, new EmitSignature('', existing === undefined ? '' : existing.signature));
1113
+ } else if (value.differsInOptions) snapshot.emitSignatures.set(path, new EmitSignature('', value.signature));
1114
+ else snapshot.emitSignatures.set(path, new EmitSignature(value.signature, undefined));
1115
+ }
1116
+ const fileIdLists = new FileIdLists(
1117
+ filePaths,
1118
+ buildInfo.fileIdsList,
1119
+ fileSets,
1120
+ buildInfo.fileIdsListText.length === buildInfo.fileIdsList.length ? buildInfo.fileIdsListText : [],
1121
+ );
1122
+ for (const entry of buildInfo.referencedMap) {
1123
+ const set =
1124
+ entry.fileIdListId >= 1 && entry.fileIdListId <= fileSets.length ? fileSets[entry.fileIdListId - 1] : undefined;
1125
+ if (set !== undefined) {
1126
+ const path = filePath(entry.fileId);
1127
+ snapshot.referencedMap.references.set(path, set);
1128
+ fileIdLists.listOfFile.set(path, entry.fileIdListId - 1);
1129
+ }
1130
+ }
1131
+ snapshot.fileIdLists = fileIdLists;
1132
+ for (const fileId of buildInfo.changeFileSet) snapshot.changedFilesSet.add(filePath(fileId));
1133
+ for (const path of snapshot.fileInfos.keys()) {
1134
+ if (!snapshot.changedFilesSet.has(path)) snapshot.semanticDiagnosticsPerFile.set(path, FileDiagnostics.of([]));
1135
+ }
1136
+ for (const diagnostic of buildInfo.semanticDiagnosticsPerFile) {
1137
+ const ofFile = diagnostic.diagnostics;
1138
+ if (ofFile === undefined) snapshot.semanticDiagnosticsPerFile.delete(filePath(diagnostic.fileId));
1139
+ else {
1140
+ snapshot.semanticDiagnosticsPerFile.set(
1141
+ filePath(ofFile.fileId),
1142
+ new FileDiagnostics(undefined, storedDiagnostics(ofFile.diagnostics, filePaths)),
1143
+ );
1144
+ }
1145
+ }
1146
+ for (const ofFile of buildInfo.emitDiagnosticsPerFile) {
1147
+ snapshot.emitDiagnosticsPerFile.set(
1148
+ filePath(ofFile.fileId),
1149
+ new FileDiagnostics(undefined, storedDiagnostics(ofFile.diagnostics, filePaths)),
1150
+ );
1151
+ }
1152
+ if (buildInfo.affectedFilesPendingEmit.length > 0) {
1153
+ const ownOptionsEmitKind = getFileEmitKind(snapshot.options);
1154
+ for (const pending of buildInfo.affectedFilesPendingEmit) {
1155
+ snapshot.affectedFilesPendingEmit.set(
1156
+ filePath(pending.fileId),
1157
+ pending.emitKind === 0 ? ownOptionsEmitKind : pending.emitKind,
1158
+ );
1159
+ }
1160
+ }
1161
+ if (buildInfo.latestChangedDtsFile !== '') {
1162
+ snapshot.latestChangedDtsFile = getNormalizedAbsolutePath(buildInfo.latestChangedDtsFile, buildInfoDirectory);
1163
+ }
1164
+ snapshot.hasErrors = buildInfo.errors ? Tristate.True : Tristate.False;
1165
+ snapshot.hasSemanticErrors = buildInfo.semanticErrors;
1166
+ snapshot.checkPending = buildInfo.checkPending;
1167
+ snapshot.packageJsons = buildInfo.packageJsons.map((p) => getNormalizedAbsolutePath(p, buildInfoDirectory));
1168
+ snapshot.missingPackageJsons = buildInfo.missingPackageJsons.map((p) =>
1169
+ getNormalizedAbsolutePath(p, buildInfoDirectory),
1170
+ );
1171
+ return snapshot;
1172
+ }
1173
+
1174
+ // ---- The new state from the program and the old state
1175
+
1176
+ function fileAffectsGlobalScope(file: SourceFile): boolean {
1177
+ for (const augmentation of file.moduleAugmentations) {
1178
+ const parent = augmentation.parent;
1179
+ if (parent !== undefined && isGlobalScopeAugmentation(parent)) return true;
1180
+ }
1181
+ if (isExternalOrCommonJSModule(file) || isJsonSourceFile(file)) return false;
1182
+ for (const statement of file.statements.nodes) {
1183
+ if (!isModuleWithStringLiteralName(statement)) return true;
1184
+ }
1185
+ return false;
1186
+ }
1187
+
1188
+ function isModuleWithStringLiteralName(node: Node): boolean {
1189
+ return node.kind === SyntaxKind.ModuleDeclaration && isAmbientModule(node) && !isGlobalScopeAugmentation(node);
1190
+ }
1191
+
1192
+ function addReferencedFilesFromSymbol(file: SourceFile, referenced: Set<string>, symbol: Symbol | undefined): void {
1193
+ if (symbol === undefined) return;
1194
+ for (const declaration of symbol.declarations) {
1195
+ const declarationFile = getSourceFileOfNode(declaration);
1196
+ if (declarationFile !== file) referenced.add(declarationFile.path);
1197
+ }
1198
+ }
1199
+
1200
+ function addReferencedFileFromFileName(
1201
+ program: Program,
1202
+ fileName: string,
1203
+ referenced: Set<string>,
1204
+ sourceFileDirectory: string,
1205
+ ): void {
1206
+ const redirect = program.getParseFileRedirect(fileName);
1207
+ if (redirect !== '') referenced.add(toPath(redirect, program.currentDirectory, program.useCaseSensitiveFileNames));
1208
+ else referenced.add(toPath(fileName, sourceFileDirectory, program.useCaseSensitiveFileNames));
1209
+ }
1210
+
1211
+ /**
1212
+ * The files `file` depends on: imports, references, type references, augmentations, and the files that
1213
+ * declare ambient modules (`getAmbientModuleFiles`).
1214
+ */
1215
+ function getReferencedFiles(
1216
+ checked: CheckedProgram,
1217
+ file: SourceFile,
1218
+ ambientModuleFiles: readonly string[],
1219
+ ): Set<string> | undefined {
1220
+ const referenced = new Set<string>();
1221
+ addOwnReferencedFiles(checked, file, referenced);
1222
+ for (const path of ambientModuleFiles) if (path !== file.path) referenced.add(path);
1223
+ return referenced.size > 0 ? referenced : undefined;
1224
+ }
1225
+
1226
+ /** Adds to `referenced` the files `file` depends on (`getReferencedFiles`) other than those that declare ambient modules. */
1227
+ function addOwnReferencedFiles(checked: CheckedProgram, file: SourceFile, referenced: Set<string>): void {
1228
+ const program = checked.program;
1229
+ const checker = checked.checker;
1230
+ // Every import is resolved. tsgo takes the symbol at each import name, which is undefined for a JavaScript `require`
1231
+ // call that does not initialize a variable (`exports.a = require("./a").a`), so its build info leaves out that
1232
+ // module and its incremental builds keep outputs that depend on it.
1233
+ for (const importName of file.imports) {
1234
+ addReferencedFilesFromSymbol(file, referenced, resolveExternalModuleName(checker, importName, importName, true));
1235
+ }
1236
+ const sourceFileDirectory = getDirectoryPath(file.fileName);
1237
+ for (const reference of file.referencedFiles) {
1238
+ addReferencedFileFromFileName(program, reference.fileName, referenced, sourceFileDirectory);
1239
+ }
1240
+ for (const resolved of program.getResolvedTypeReferenceDirectiveFiles(file.path)) {
1241
+ addReferencedFileFromFileName(program, resolved, referenced, sourceFileDirectory);
1242
+ }
1243
+ // The symbol of an augmentation's name is the symbol the augmentation is merged into (the module, or the
1244
+ // target of its `export =`), which has the declarations of every augmentation of the module.
1245
+ for (const moduleName of file.moduleAugmentations) {
1246
+ if (moduleName.kind !== SyntaxKind.StringLiteral) continue;
1247
+ addReferencedFilesFromSymbol(file, referenced, getSymbolAtLocation(checker, moduleName));
1248
+ }
1249
+ }
1250
+
1251
+ /**
1252
+ * The files that declare the program's ambient modules (`declare module "x"`), as stored in the
1253
+ * checker's globals, in the order of their modules and declarations. When a module file augments an
1254
+ * ambient module declared in one file, the augmentation is merged into a copy of the symbol, so the
1255
+ * augmenting file is not among these declarations. Every file references all of them; listed once
1256
+ * here, the files are not found again from each declaration of every file's ambient modules.
1257
+ */
1258
+ function getAmbientModuleFiles(checked: CheckedProgram): string[] {
1259
+ const result = new Set<string>();
1260
+ for (const [name, symbol] of checked.checker.globals) {
1261
+ if (name.length >= 2 && name.charCodeAt(0) === 0x22 && name.charCodeAt(name.length - 1) === 0x22) {
1262
+ for (const declaration of symbol.declarations) result.add(getSourceFileOfNode(declaration).path);
1263
+ }
1264
+ }
1265
+ return [...result];
1266
+ }
1267
+
1268
+ function programToSnapshot(checked: CheckedProgram, oldSnapshot: Snapshot | undefined): Snapshot {
1269
+ const program = checked.program;
1270
+ const options = program.options;
1271
+ const snapshot = new Snapshot(options);
1272
+ snapshot.checkPending = options.noCheck === true;
1273
+ if (!snapshot.canUseIncrementalState()) return snapshot;
1274
+
1275
+ // Reuse from the old state.
1276
+ if (oldSnapshot !== undefined) {
1277
+ if (options.composite === true) snapshot.latestChangedDtsFile = oldSnapshot.latestChangedDtsFile;
1278
+ for (const path of oldSnapshot.changedFilesSet) snapshot.changedFilesSet.add(path);
1279
+ for (const [path, kind] of oldSnapshot.affectedFilesPendingEmit) snapshot.affectedFilesPendingEmit.set(path, kind);
1280
+ snapshot.buildInfoEmitPending = oldSnapshot.buildInfoEmitPending;
1281
+ snapshot.hasErrorsFromOldState = oldSnapshot.hasErrors;
1282
+ snapshot.hasSemanticErrorsFromOldState = oldSnapshot.hasSemanticErrors;
1283
+ const oldPackageJsons = oldSnapshot.packageJsons;
1284
+ if (oldPackageJsons !== undefined) snapshot.packageJsonsFromOldState = oldPackageJsons;
1285
+ snapshot.missingPackageJsonsFromOldState = oldSnapshot.missingPackageJsons;
1286
+ snapshot.fileIdLists = oldSnapshot.fileIdLists;
1287
+ } else {
1288
+ snapshot.buildInfoEmitPending = isIncremental(options);
1289
+ }
1290
+
1291
+ // Changes of files.
1292
+ const canCopySemanticDiagnostics =
1293
+ oldSnapshot !== undefined && !compilerOptionsAffectSemanticDiagnostics(oldSnapshot.options, options);
1294
+ const canCopyEmitSignatures =
1295
+ options.composite === true &&
1296
+ oldSnapshot !== undefined &&
1297
+ !compilerOptionsAffectDeclarationPath(oldSnapshot.options, options);
1298
+ const copyDeclarationFileDiagnostics =
1299
+ canCopySemanticDiagnostics &&
1300
+ oldSnapshot !== undefined &&
1301
+ (options.skipLibCheck === true) === (oldSnapshot.options.skipLibCheck === true);
1302
+ const copyLibFileDiagnostics =
1303
+ copyDeclarationFileDiagnostics &&
1304
+ oldSnapshot !== undefined &&
1305
+ (options.skipDefaultLibCheck === true) === (oldSnapshot.options.skipDefaultLibCheck === true);
1306
+
1307
+ const ambientModuleFiles = getAmbientModuleFiles(checked);
1308
+ const lists = oldSnapshot === undefined ? undefined : oldSnapshot.fileIdLists;
1309
+ const indexOfPath = lists === undefined ? undefined : lists.indexOfPath();
1310
+ const comparer =
1311
+ lists === undefined || indexOfPath === undefined
1312
+ ? undefined
1313
+ : ReferenceListComparer.of(lists, indexOfPath, ambientModuleFiles);
1314
+ const verdicts =
1315
+ comparer === undefined || lists === undefined || oldSnapshot === undefined
1316
+ ? undefined
1317
+ : compareReferencesOnThreads(checked, comparer, lists, oldSnapshot);
1318
+ // Whether a file of the old state is not in the program: if not, no list has one (`hasMissingFile`).
1319
+ let oldFileMissing = false;
1320
+ if (comparer !== undefined && oldSnapshot !== undefined) {
1321
+ for (const path of oldSnapshot.fileInfos.keys()) {
1322
+ if (program.getSourceFileByPath(path) === undefined) {
1323
+ oldFileMissing = true;
1324
+ break;
1325
+ }
1326
+ }
1327
+ }
1328
+ const files = program.getSourceFiles();
1329
+ for (let fileIndex = 0; fileIndex < files.length; fileIndex++) {
1330
+ const file = files[fileIndex]!;
1331
+ const path = file.path;
1332
+ const prepared = preparedVersion(file);
1333
+ const reused = prepared !== '' ? prepared : (oldSnapshot?.versionsByFile.get(file) ?? '');
1334
+ const version = reused !== '' ? reused : computeHash(file.text);
1335
+ snapshot.versionsByFile.set(file, version);
1336
+ const impliedNodeFormat: number = program.sourceFileMetadata(path).impliedNodeFormat;
1337
+ const affectsGlobalScope = fileAffectsGlobalScope(file);
1338
+ let signature = '';
1339
+ // An unchanged file whose old references are the set of its list of file ids in the build info read
1340
+ // is compared with the list, and keeps the set if its references are the list's paths.
1341
+ let listIndex = -1;
1342
+ let sameAsList: boolean | undefined = undefined;
1343
+ if (comparer !== undefined && oldSnapshot !== undefined) {
1344
+ const oldInfo = oldSnapshot.fileInfos.get(path);
1345
+ if (
1346
+ lists !== undefined &&
1347
+ oldInfo !== undefined &&
1348
+ oldInfo.version === version &&
1349
+ oldInfo.affectsGlobalScope === affectsGlobalScope &&
1350
+ oldInfo.impliedNodeFormat === impliedNodeFormat
1351
+ ) {
1352
+ if (verdicts !== undefined) {
1353
+ listIndex = verdicts.lists[fileIndex];
1354
+ if (listIndex >= 0) sameAsList = verdicts.sameReferences(comparer, checked, file, fileIndex, listIndex);
1355
+ } else {
1356
+ listIndex = lists.listOf(path, oldSnapshot.referencedMap.references.get(path));
1357
+ if (listIndex >= 0) sameAsList = comparer.sameReferences(checked, file, listIndex);
1358
+ }
1359
+ }
1360
+ }
1361
+ const newReferences = sameAsList === true ? undefined : getReferencedFiles(checked, file, ambientModuleFiles);
1362
+ if (newReferences !== undefined) snapshot.referencedMap.references.set(path, newReferences);
1363
+ if (oldSnapshot !== undefined) {
1364
+ const oldInfo = oldSnapshot.fileInfos.get(path);
1365
+ if (oldInfo !== undefined) {
1366
+ signature = oldInfo.signature;
1367
+ if (
1368
+ oldInfo.version !== version ||
1369
+ oldInfo.affectsGlobalScope !== affectsGlobalScope ||
1370
+ oldInfo.impliedNodeFormat !== impliedNodeFormat
1371
+ ) {
1372
+ snapshot.addFileToChangeSet(path);
1373
+ } else if (comparer !== undefined && sameAsList === true) {
1374
+ const oldReferences = oldSnapshot.referencedMap.references.get(path);
1375
+ if (oldReferences !== undefined) snapshot.referencedMap.references.set(path, oldReferences);
1376
+ if (oldFileMissing && comparer.hasMissingFile(listIndex, lists!, program, oldSnapshot))
1377
+ snapshot.addFileToChangeSet(path);
1378
+ } else {
1379
+ const oldReferences = oldSnapshot.referencedMap.references.get(path);
1380
+ if (sameAsList === false || !sameSet(newReferences, oldReferences)) snapshot.addFileToChangeSet(path);
1381
+ else if (newReferences !== undefined && oldReferences !== undefined) {
1382
+ // The old set, which can be of a list of file ids the build info writes again (`FileIdLists`).
1383
+ snapshot.referencedMap.references.set(path, oldReferences);
1384
+ for (const reference of newReferences) {
1385
+ if (program.getSourceFileByPath(reference) === undefined && oldSnapshot.fileInfos.has(reference)) {
1386
+ snapshot.addFileToChangeSet(path);
1387
+ break;
1388
+ }
1389
+ }
1390
+ }
1391
+ }
1392
+ } else snapshot.addFileToChangeSet(path);
1393
+ if (!snapshot.changedFilesSet.has(path)) {
1394
+ const emitDiagnostics = oldSnapshot.emitDiagnosticsPerFile.get(path);
1395
+ if (emitDiagnostics !== undefined) {
1396
+ snapshot.emitDiagnosticsPerFile.set(path, repopulateFileDiagnostics(emitDiagnostics, program, file));
1397
+ }
1398
+ if (
1399
+ canCopySemanticDiagnostics &&
1400
+ (!file.isDeclarationFile || copyDeclarationFileDiagnostics) &&
1401
+ (!program.isSourceFileDefaultLibrary(path) || copyLibFileDiagnostics)
1402
+ ) {
1403
+ const diagnostics = oldSnapshot.semanticDiagnosticsPerFile.get(path);
1404
+ if (diagnostics !== undefined) {
1405
+ snapshot.semanticDiagnosticsPerFile.set(path, repopulateFileDiagnostics(diagnostics, program, file));
1406
+ }
1407
+ }
1408
+ }
1409
+ if (canCopyEmitSignatures) {
1410
+ const oldEmitSignature = oldSnapshot.emitSignatures.get(path);
1411
+ if (oldEmitSignature !== undefined) {
1412
+ snapshot.emitSignatures.set(path, oldEmitSignature.getNewEmitSignature(oldSnapshot.options, options));
1413
+ }
1414
+ }
1415
+ } else {
1416
+ snapshot.addFileToAffectedFilesPendingEmit(path, getFileEmitKind(options));
1417
+ signature = version;
1418
+ }
1419
+ snapshot.fileInfos.set(path, new FileInfo(version, signature, affectsGlobalScope, impliedNodeFormat));
1420
+ }
1421
+ verdicts?.done();
1422
+
1423
+ // Deleted files.
1424
+ let globalFileRemoved = false;
1425
+ if (oldSnapshot !== undefined) {
1426
+ for (const [path, oldInfo] of oldSnapshot.fileInfos) {
1427
+ if (snapshot.fileInfos.has(path)) continue;
1428
+ if (oldInfo.affectsGlobalScope) {
1429
+ for (const file of snapshot.getAllFilesExcludingDefaultLibraryFile(program, undefined)) {
1430
+ snapshot.addFileToChangeSet(file.path);
1431
+ }
1432
+ globalFileRemoved = true;
1433
+ } else snapshot.buildInfoEmitPending = true;
1434
+ break;
1435
+ }
1436
+ }
1437
+
1438
+ // Pending emit from changed options.
1439
+ if (oldSnapshot !== undefined && !globalFileRemoved) {
1440
+ const pendingEmitKind = compilerOptionsAffectEmit(oldSnapshot.options, options)
1441
+ ? getFileEmitKind(options)
1442
+ : getPendingEmitKindWithOptions(options, oldSnapshot.options);
1443
+ if (pendingEmitKind !== FileEmitKind.None) {
1444
+ for (const file of program.getSourceFiles()) {
1445
+ if (!snapshot.changedFilesSet.has(file.path))
1446
+ snapshot.addFileToAffectedFilesPendingEmit(file.path, pendingEmitKind);
1447
+ }
1448
+ snapshot.buildInfoEmitPending = true;
1449
+ }
1450
+ }
1451
+
1452
+ // Pending check.
1453
+ if (
1454
+ oldSnapshot !== undefined &&
1455
+ snapshot.semanticDiagnosticsPerFile.size !== program.getSourceFiles().length &&
1456
+ oldSnapshot.checkPending !== snapshot.checkPending
1457
+ ) {
1458
+ snapshot.buildInfoEmitPending = true;
1459
+ }
1460
+ return snapshot;
1461
+ }
1462
+
1463
+ // ---- Affected files
1464
+
1465
+ class AffectedFilesHandler {
1466
+ private hasAllFilesExcludingDefaultLibraryFile = false;
1467
+ private readonly updatedSignatures = new Map<string, string>();
1468
+ private readonly dtsMayChange: Map<string, number>[] = [];
1469
+ private readonly filesToRemoveDiagnostics = new Set<string>();
1470
+ private cleanedDiagnosticsOfLibFiles = false;
1471
+ private readonly seenFileAndReferences = new Map<string, boolean>();
1472
+
1473
+ constructor(private readonly incremental: IncrementalProgram) {}
1474
+
1475
+ private get snapshot(): Snapshot {
1476
+ return this.incremental.snapshot;
1477
+ }
1478
+
1479
+ private get program(): Program {
1480
+ return this.incremental.program;
1481
+ }
1482
+
1483
+ getDtsMayChange(affectedFilePath: string, emitKind: number): Map<string, number> {
1484
+ const result = new Map<string, number>();
1485
+ result.set(affectedFilePath, emitKind);
1486
+ this.dtsMayChange.push(result);
1487
+ return result;
1488
+ }
1489
+
1490
+ private isChangedSignature(path: string): boolean {
1491
+ const newSignature = this.updatedSignatures.get(path);
1492
+ const oldInfo = this.snapshot.fileInfos.get(path);
1493
+ return newSignature !== (oldInfo === undefined ? undefined : oldInfo.signature);
1494
+ }
1495
+
1496
+ private removeSemanticDiagnosticsOf(path: string): void {
1497
+ this.filesToRemoveDiagnostics.add(path);
1498
+ }
1499
+
1500
+ private removeDiagnosticsOfLibraryFiles(): void {
1501
+ if (this.cleanedDiagnosticsOfLibFiles) return;
1502
+ this.cleanedDiagnosticsOfLibFiles = true;
1503
+ for (const file of this.program.getSourceFiles()) {
1504
+ if (this.program.isSourceFileDefaultLibrary(file.path) && !this.incremental.checked.skipTypeChecking(file)) {
1505
+ this.removeSemanticDiagnosticsOf(file.path);
1506
+ }
1507
+ }
1508
+ }
1509
+
1510
+ private computeDtsSignature(file: SourceFile): string {
1511
+ const known = this.incremental.signatures.get(file.path);
1512
+ if (known !== undefined) return known;
1513
+ return declarationSignature(this.incremental.emitter, file, this.snapshot.options);
1514
+ }
1515
+
1516
+ updateShapeSignature(file: SourceFile, useFileVersionAsSignature: boolean): boolean {
1517
+ if (this.updatedSignatures.has(file.path)) return false;
1518
+ const info = this.snapshot.fileInfos.get(file.path);
1519
+ if (info === undefined) return false;
1520
+ const previous = info.signature;
1521
+ let signature = '';
1522
+ if (!file.isDeclarationFile && !useFileVersionAsSignature) signature = this.computeDtsSignature(file);
1523
+ if (signature === '') signature = info.version;
1524
+ this.updatedSignatures.set(file.path, signature);
1525
+ return signature !== previous;
1526
+ }
1527
+
1528
+ /**
1529
+ * Whether `file`, unchanged, has a signature no build computed. A program without build info (a watch
1530
+ * without `incremental`) takes each file's version as its signature in its first build. A signature
1531
+ * computed from the file's declaration file differs from the version, so an importer with such a
1532
+ * signature is not given one: it keeps its version, as without declaration emit, until a change of the
1533
+ * file itself computes its signature (`getFilesAffectedBy`). Files that forced declaration emit doesn't
1534
+ * write are excluded: their versions are their signatures.
1535
+ */
1536
+ private hasUncomputedSignature(file: SourceFile): boolean {
1537
+ const options = this.snapshot.options;
1538
+ if (isIncremental(options) || this.updatedSignatures.has(file.path)) return false;
1539
+ if (!sourceFileMayBeEmitted(file, options)) return false;
1540
+ if (this.program.isSourceFileFromExternalLibrary(file)) return false;
1541
+ const info = this.snapshot.fileInfos.get(file.path);
1542
+ return info !== undefined && info.signature === info.version;
1543
+ }
1544
+
1545
+ getFilesAffectedBy(path: string): SourceFile[] {
1546
+ const file = this.program.getSourceFileByPath(path);
1547
+ if (file === undefined) return [];
1548
+ if (!this.updateShapeSignature(file, false)) return [file];
1549
+ const info = this.snapshot.fileInfos.get(file.path);
1550
+ if (info !== undefined && info.affectsGlobalScope) {
1551
+ this.hasAllFilesExcludingDefaultLibraryFile = true;
1552
+ this.snapshot.getAllFilesExcludingDefaultLibraryFile(this.program, file);
1553
+ }
1554
+ if (this.snapshot.options.isolatedModules === true) return [file];
1555
+ const seen = this.forEachFileReferencedBy(file, (currentFile) => {
1556
+ if (currentFile === undefined) return 0;
1557
+ // As a file whose version is its signature: the changed file's importers are rechecked through
1558
+ // `handleDtsMayChangeOfAffectedFile`.
1559
+ if (this.hasUncomputedSignature(currentFile)) return 0;
1560
+ return this.updateShapeSignature(currentFile, false) ? 1 : 0;
1561
+ });
1562
+ const result: SourceFile[] = [];
1563
+ for (const value of seen.values()) if (value !== undefined) result.push(value);
1564
+ return result;
1565
+ }
1566
+
1567
+ /** Walks the files referencing `file`; `visit` returns 1 to walk on from a file, 2 to stop. */
1568
+ private forEachFileReferencedBy(
1569
+ file: SourceFile,
1570
+ visit: (currentFile: SourceFile | undefined, currentPath: string) => number,
1571
+ ): Map<string, SourceFile | undefined> {
1572
+ const seen = new Map<string, SourceFile | undefined>();
1573
+ seen.set(file.path, file);
1574
+ const queue = this.snapshot.referencedMap.getReferencedBy(file.path);
1575
+ while (queue.length > 0) {
1576
+ const currentPath = queue.pop();
1577
+ if (currentPath === undefined) break;
1578
+ if (seen.has(currentPath)) continue;
1579
+ const currentFile = this.program.getSourceFileByPath(currentPath);
1580
+ seen.set(currentPath, currentFile);
1581
+ const result = visit(currentFile, currentPath);
1582
+ if (result === 2) return seen;
1583
+ if (result === 1 && currentFile !== undefined) {
1584
+ for (const reference of this.snapshot.referencedMap.getReferencedBy(currentFile.path)) queue.push(reference);
1585
+ }
1586
+ }
1587
+ return seen;
1588
+ }
1589
+
1590
+ handleDtsMayChangeOfAffectedFile(dtsMayChange: Map<string, number>, affectedFile: SourceFile): void {
1591
+ this.removeSemanticDiagnosticsOf(affectedFile.path);
1592
+ if (this.hasAllFilesExcludingDefaultLibraryFile) {
1593
+ this.removeDiagnosticsOfLibraryFiles();
1594
+ if (!this.hasUncomputedSignature(affectedFile)) this.updateShapeSignature(affectedFile, false);
1595
+ return;
1596
+ }
1597
+ const options = this.snapshot.options;
1598
+ if (options.assumeChangesOnlyAffectDirectDependencies === true) return;
1599
+ if (!this.snapshot.changedFilesSet.has(affectedFile.path) || !this.isChangedSignature(affectedFile.path)) return;
1600
+
1601
+ if (options.isolatedModules === true) {
1602
+ this.forEachFileReferencedBy(affectedFile, (_currentFile, currentPath) => {
1603
+ if (this.handleDtsMayChangeOfGlobalScope(dtsMayChange, currentPath, false)) return 2;
1604
+ this.handleDtsMayChangeOf(dtsMayChange, currentPath, false);
1605
+ return this.isChangedSignature(currentPath) ? 1 : 0;
1606
+ });
1607
+ }
1608
+
1609
+ let invalidateJsFiles = false;
1610
+ const symbol = affectedFile.symbol;
1611
+ const exports = symbol === undefined ? undefined : symbol.exports;
1612
+ if (exports !== undefined) {
1613
+ const checker = this.incremental.checked.checker;
1614
+ for (const exported of exports.values()) {
1615
+ if ((exported.flags & SymbolFlags.ConstEnum) !== 0) {
1616
+ invalidateJsFiles = true;
1617
+ break;
1618
+ }
1619
+ if ((exported.flags & SymbolFlags.Alias) === 0) continue;
1620
+ const aliased = resolveAlias(checker, exported);
1621
+ if (aliased === exported) continue;
1622
+ if ((aliased.flags & SymbolFlags.ConstEnum) !== 0) {
1623
+ if (aliased.declarations.some((d) => getSourceFileOfNode(d) === affectedFile)) {
1624
+ invalidateJsFiles = true;
1625
+ break;
1626
+ }
1627
+ }
1628
+ }
1629
+ }
1630
+
1631
+ for (const fileReferencingChangedFile of this.snapshot.referencedMap.getReferencedBy(affectedFile.path)) {
1632
+ if (this.handleDtsMayChangeOfGlobalScope(dtsMayChange, fileReferencingChangedFile, invalidateJsFiles)) return;
1633
+ for (const fileReferencingAffectedFile of this.snapshot.referencedMap.getReferencedBy(
1634
+ fileReferencingChangedFile,
1635
+ )) {
1636
+ if (this.handleDtsMayChangeOfFileAndReferences(dtsMayChange, fileReferencingAffectedFile, invalidateJsFiles)) {
1637
+ return;
1638
+ }
1639
+ }
1640
+ }
1641
+ }
1642
+
1643
+ private handleDtsMayChangeOfFileAndReferences(
1644
+ dtsMayChange: Map<string, number>,
1645
+ path: string,
1646
+ invalidateJsFiles: boolean,
1647
+ ): boolean {
1648
+ const existing = this.seenFileAndReferences.get(path);
1649
+ if (existing !== undefined && (existing || !invalidateJsFiles)) return false;
1650
+ this.seenFileAndReferences.set(path, invalidateJsFiles);
1651
+ if (this.handleDtsMayChangeOfGlobalScope(dtsMayChange, path, invalidateJsFiles)) return true;
1652
+ this.handleDtsMayChangeOf(dtsMayChange, path, invalidateJsFiles);
1653
+ for (const referencingFilePath of this.snapshot.referencedMap.getReferencedBy(path)) {
1654
+ if (this.handleDtsMayChangeOfFileAndReferences(dtsMayChange, referencingFilePath, invalidateJsFiles)) return true;
1655
+ }
1656
+ return false;
1657
+ }
1658
+
1659
+ private handleDtsMayChangeOfGlobalScope(
1660
+ dtsMayChange: Map<string, number>,
1661
+ path: string,
1662
+ invalidateJsFiles: boolean,
1663
+ ): boolean {
1664
+ const info = this.snapshot.fileInfos.get(path);
1665
+ if (info === undefined || !info.affectsGlobalScope) return false;
1666
+ for (const file of this.snapshot.getAllFilesExcludingDefaultLibraryFile(this.program, undefined)) {
1667
+ this.handleDtsMayChangeOf(dtsMayChange, file.path, invalidateJsFiles);
1668
+ }
1669
+ this.removeDiagnosticsOfLibraryFiles();
1670
+ return true;
1671
+ }
1672
+
1673
+ private handleDtsMayChangeOf(dtsMayChange: Map<string, number>, path: string, invalidateJsFiles: boolean): void {
1674
+ if (this.snapshot.changedFilesSet.has(path)) return;
1675
+ const file = this.program.getSourceFileByPath(path);
1676
+ if (file === undefined) return;
1677
+ this.removeSemanticDiagnosticsOf(path);
1678
+ this.updateShapeSignature(file, true);
1679
+ const options = this.snapshot.options;
1680
+ if (invalidateJsFiles) dtsMayChange.set(path, getFileEmitKind(options));
1681
+ else if (getEmitDeclarations(options)) {
1682
+ dtsMayChange.set(path, options.declarationMap === true ? FileEmitKind.AllDts : FileEmitKind.Dts);
1683
+ }
1684
+ }
1685
+
1686
+ updateSnapshot(): void {
1687
+ const snapshot = this.snapshot;
1688
+ for (const [path, signature] of this.updatedSignatures) {
1689
+ const info = snapshot.fileInfos.get(path);
1690
+ if (info !== undefined) info.signature = signature;
1691
+ }
1692
+ for (const path of this.filesToRemoveDiagnostics) snapshot.semanticDiagnosticsPerFile.delete(path);
1693
+ for (const change of this.dtsMayChange) {
1694
+ for (const [path, emitKind] of change) snapshot.addFileToAffectedFilesPendingEmit(path, emitKind);
1695
+ }
1696
+ snapshot.changedFilesSet = new Set();
1697
+ snapshot.buildInfoEmitPending = true;
1698
+ }
1699
+ }
1700
+
1701
+ function collectAllAffectedFiles(program: IncrementalProgram): void {
1702
+ const snapshot = program.snapshot;
1703
+ if (snapshot.changedFilesSet.size === 0) return;
1704
+ const handler = new AffectedFilesHandler(program);
1705
+ const affected = new Set<SourceFile>();
1706
+ for (const path of snapshot.changedFilesSet) {
1707
+ for (const file of handler.getFilesAffectedBy(path)) affected.add(file);
1708
+ }
1709
+ const emitKind = getFileEmitKind(snapshot.options);
1710
+ for (const file of affected) {
1711
+ handler.handleDtsMayChangeOfAffectedFile(handler.getDtsMayChange(file.path, emitKind), file);
1712
+ }
1713
+ handler.updateSnapshot();
1714
+ }
1715
+
1716
+ // ---- Emit
1717
+
1718
+ /** Writes declaration files, recording their signatures and skipping unchanged ones of composite projects. */
1719
+ class SignatureRecordingWriter extends OutputWriter {
1720
+ file: SourceFile | undefined = undefined;
1721
+
1722
+ constructor(
1723
+ private readonly handler: EmitFilesHandler,
1724
+ private readonly writer: OutputWriter,
1725
+ ) {
1726
+ super();
1727
+ }
1728
+
1729
+ write(fileName: string, text: string, declarationDiagnostics: readonly Diagnostic[]): string {
1730
+ const file = this.file;
1731
+ let differsOnlyInMap = false;
1732
+ if (
1733
+ file !== undefined &&
1734
+ isDeclarationFileName(fileName) &&
1735
+ this.handler.program.snapshot.canUseIncrementalState()
1736
+ ) {
1737
+ const snapshot = this.handler.program.snapshot;
1738
+ let emitSignature = '';
1739
+ const info = snapshot.fileInfos.get(file.path);
1740
+ if (info !== undefined && info.signature === info.version) {
1741
+ const signature = computeSignatureWithDiagnostics(file, text, declarationDiagnostics, snapshot.options);
1742
+ if (declarationDiagnostics.length === 0) emitSignature = signature;
1743
+ if (signature !== info.version) this.handler.signatures.set(file.path, signature);
1744
+ }
1745
+ const skip = this.handler.skipDtsOutputOfComposite(file, fileName, text, emitSignature);
1746
+ if (skip === 1) return skippedWrite;
1747
+ differsOnlyInMap = skip === 2;
1748
+ }
1749
+ const mtime = differsOnlyInMap ? this.handler.program.host.getMTime(fileName) : undefined;
1750
+ const error = this.writer.write(fileName, text, declarationDiagnostics);
1751
+ if (error === '' && mtime !== undefined) this.handler.program.host.setMTime(fileName, mtime);
1752
+ return error;
1753
+ }
1754
+ }
1755
+
1756
+ /**
1757
+ * Writes the outputs a checker thread held for a file of a composite program as `SignatureRecordingWriter` writes
1758
+ * them here: `skips` holds `skipDtsOutputOfComposite`'s answer for each of its declaration files, which is left
1759
+ * unwritten when unchanged, and keeps its time stamp when only its map changed.
1760
+ */
1761
+ class HeldDeclarationWriter extends OutputWriter {
1762
+ constructor(
1763
+ private readonly writer: OutputWriter,
1764
+ private readonly skips: ReadonlyMap<string, number>,
1765
+ private readonly host: TimeStampHost,
1766
+ ) {
1767
+ super();
1768
+ }
1769
+
1770
+ write(fileName: string, text: string, declarationDiagnostics: readonly Diagnostic[]): string {
1771
+ const skip = this.skips.get(fileName) ?? 0;
1772
+ if (skip === 1) return skippedWrite;
1773
+ const mtime = skip === 2 ? this.host.getMTime(fileName) : undefined;
1774
+ const error = this.writer.write(fileName, text, declarationDiagnostics);
1775
+ if (error === '' && mtime !== undefined) this.host.setMTime(fileName, mtime);
1776
+ return error;
1777
+ }
1778
+ }
1779
+
1780
+ /**
1781
+ * Writes outputs with `writer` and keeps, for each declaration file, its name, its signature and the
1782
+ * signature compared for composite projects, as `SignatureRecordingWriter` computes them: for checker
1783
+ * threads that emit the files of an incremental program, whose main thread records them
1784
+ * (`EmitFilesHandler.recordDeclarationSignatures`).
1785
+ */
1786
+ export class DeclarationSignatureWriter extends OutputWriter {
1787
+ /** The file being emitted. */
1788
+ file: SourceFile | undefined = undefined;
1789
+ private signatures: string[] = [];
1790
+
1791
+ constructor(
1792
+ private readonly writer: OutputWriter,
1793
+ private readonly options: CompilerOptions,
1794
+ ) {
1795
+ super();
1796
+ }
1797
+
1798
+ write(fileName: string, text: string, declarationDiagnostics: readonly Diagnostic[]): string {
1799
+ const file = this.file;
1800
+ if (file !== undefined && isDeclarationFileName(fileName)) {
1801
+ const signature = computeSignatureWithDiagnostics(file, text, declarationDiagnostics, this.options);
1802
+ const compositeSignature =
1803
+ declarationDiagnostics.length === 0
1804
+ ? signature
1805
+ : computeHash(getTextHandlingSourceMapForSignature(text, this.options));
1806
+ this.signatures.push(fileName, signature, compositeSignature);
1807
+ }
1808
+ return this.writer.write(fileName, text, declarationDiagnostics);
1809
+ }
1810
+
1811
+ /** The signatures kept since the last call. */
1812
+ take(): string[] {
1813
+ const signatures = this.signatures;
1814
+ this.signatures = [];
1815
+ return signatures;
1816
+ }
1817
+ }
1818
+
1819
+ /** What emitting a file with the pending emit `pendingKind` (not 0) includes. */
1820
+ function emitOnlyOfPendingKind(pendingKind: number): EmitOnly {
1821
+ const js = (pendingKind & FileEmitKind.AllJs) !== 0;
1822
+ const dts = (pendingKind & FileEmitKind.AllDts) !== 0;
1823
+ if (js && !dts) return EmitOnly.Js;
1824
+ if (dts && !js) return EmitOnly.Dts;
1825
+ return EmitOnly.All;
1826
+ }
1827
+
1828
+ class EmitUpdate {
1829
+ constructor(
1830
+ readonly pendingKind: number,
1831
+ readonly result: EmitResult | undefined,
1832
+ readonly dtsErrorsFromCache: boolean,
1833
+ ) {}
1834
+ }
1835
+
1836
+ class EmitFilesHandler {
1837
+ readonly signatures = new Map<string, string>();
1838
+ private readonly emitSignatures = new Map<string, EmitSignature>();
1839
+ private readonly latestChangedDtsFiles = new Map<string, string>();
1840
+ private readonly deletedPendingKinds = new Set<string>();
1841
+ private readonly emitUpdates = new Map<string, EmitUpdate>();
1842
+ hasEmitDiagnostics = false;
1843
+
1844
+ constructor(
1845
+ readonly program: IncrementalProgram,
1846
+ private readonly isForDtsErrors: boolean,
1847
+ ) {}
1848
+
1849
+ private updateHasEmitDiagnostics(result: EmitResult): void {
1850
+ if (result.diagnostics.length !== 0) this.hasEmitDiagnostics = true;
1851
+ }
1852
+
1853
+ emitAllAffectedFiles(writer: OutputWriter): EmitResult {
1854
+ const program = this.program;
1855
+ const snapshot = program.snapshot;
1856
+ if (snapshot.canUseIncrementalState()) {
1857
+ const results = this.emitFilesIncremental(writer);
1858
+ for (const result of results) this.updateHasEmitDiagnostics(result);
1859
+ const result = combineEmitResults(results);
1860
+ if (!this.isForDtsErrors) this.emitBuildInfo(writer, result);
1861
+ return result;
1862
+ }
1863
+ if (!this.isForDtsErrors) {
1864
+ const files = program.program.getSourceFiles();
1865
+ const emittedOnCheckers = this.emittedOnCheckers();
1866
+ const wrapped = this.wrap(writer);
1867
+ const result =
1868
+ emittedOnCheckers.size === 0
1869
+ ? program.emitter.emit(files, EmitOnly.All, wrapped)
1870
+ : combineEmitResults(
1871
+ files.map((file) => {
1872
+ const emitted = emittedOnCheckers.get(file);
1873
+ return emitted !== undefined
1874
+ ? writeHeldOutputs(emitted, writer)
1875
+ : program.emitter.emit([file], EmitOnly.All, wrapped);
1876
+ }),
1877
+ );
1878
+ this.updateHasEmitDiagnostics(result);
1879
+ this.updateSnapshot();
1880
+ this.emitBuildInfo(writer, result);
1881
+ return result;
1882
+ }
1883
+ const result = new EmitResult();
1884
+ result.emitSkipped = true;
1885
+ for (const d of program.emitDeclarationDiagnostics(program.program.getSourceFiles())) result.diagnostics.push(d);
1886
+ if (result.diagnostics.length !== 0) {
1887
+ this.updateHasEmitDiagnostics(result);
1888
+ snapshot.hasEmitDiagnostics = true;
1889
+ }
1890
+ return result;
1891
+ }
1892
+
1893
+ private emitBuildInfo(writer: OutputWriter, result: EmitResult): void {
1894
+ const buildInfoResult = this.program.emitBuildInfo(writer);
1895
+ if (buildInfoResult !== undefined) {
1896
+ for (const d of buildInfoResult.diagnostics) result.diagnostics.push(d);
1897
+ for (const f of buildInfoResult.emittedFiles) result.emittedFiles.push(f);
1898
+ }
1899
+ }
1900
+
1901
+ /**
1902
+ * The emit results of the files checker threads emitted right after checking them (parallel-check.ts),
1903
+ * which are not emitted again here. Checker threads emit every file of a program without old build
1904
+ * info, with the outputs its options select, as its pending emit asks.
1905
+ */
1906
+ private emittedOnCheckers(): Map<SourceFile, EmitResult> {
1907
+ const result = new Map<SourceFile, EmitResult>();
1908
+ const emitted = this.program.checked.emittedInParallel;
1909
+ if (emitted === undefined) return result;
1910
+ const files = this.program.program.getSourceFiles();
1911
+ for (let i = 0; i < files.length; i++) {
1912
+ const fileResult = emitted[i];
1913
+ if (fileResult !== undefined) result.set(files[i]!, fileResult);
1914
+ }
1915
+ return result;
1916
+ }
1917
+
1918
+ /** Records declaration signatures when declarations are emitted. */
1919
+ private wrap(writer: OutputWriter): OutputWriter {
1920
+ return getEmitDeclarations(this.program.snapshot.options) ? new SignatureRecordingWriter(this, writer) : writer;
1921
+ }
1922
+
1923
+ private emitFilesIncremental(writer: OutputWriter): EmitResult[] {
1924
+ const program = this.program;
1925
+ const snapshot = program.snapshot;
1926
+ collectAllAffectedFiles(program);
1927
+ const wrapped = this.wrap(writer);
1928
+ const emittedOnCheckers = this.emittedOnCheckers();
1929
+ for (const [path, emitKind] of snapshot.affectedFilesPendingEmit) {
1930
+ const affectedFile = program.program.getSourceFileByPath(path);
1931
+ if (affectedFile === undefined || !program.program.sourceFileMayBeEmitted(affectedFile, false)) {
1932
+ this.deletedPendingKinds.add(path);
1933
+ continue;
1934
+ }
1935
+ let pendingKind = getPendingEmitKind(emitKind, 0);
1936
+ if (this.isForDtsErrors) pendingKind &= FileEmitKind.DtsErrors;
1937
+ if (pendingKind === 0) continue;
1938
+ let result: EmitResult;
1939
+ if (!this.isForDtsErrors) {
1940
+ const emitOnly = emitOnlyOfPendingKind(pendingKind);
1941
+ const emitted = emittedOnCheckers.get(affectedFile);
1942
+ if (emitted !== undefined) {
1943
+ const skips = this.recordDeclarationSignatures(affectedFile, emitted.declarationSignatures);
1944
+ result = writeHeldOutputs(
1945
+ emitted,
1946
+ skips === undefined ? writer : new HeldDeclarationWriter(writer, skips, program.host),
1947
+ );
1948
+ } else {
1949
+ if (wrapped instanceof SignatureRecordingWriter) wrapped.file = affectedFile;
1950
+ result = program.emitter.emit([affectedFile], emitOnly, wrapped);
1951
+ }
1952
+ } else {
1953
+ result = new EmitResult();
1954
+ result.emitSkipped = true;
1955
+ for (const d of program.emitDeclarationDiagnostics([affectedFile])) result.diagnostics.push(d);
1956
+ }
1957
+ this.updateHasEmitDiagnostics(result);
1958
+ this.emitUpdates.set(path, new EmitUpdate(getPendingEmitKind(emitKind, pendingKind), result, false));
1959
+ }
1960
+
1961
+ // Errors of files not emitted now, from the cache.
1962
+ for (const [path, diagnostics] of snapshot.emitDiagnosticsPerFile) {
1963
+ if (this.emitUpdates.has(path)) continue;
1964
+ const affectedFile = program.program.getSourceFileByPath(path);
1965
+ if (affectedFile === undefined || !program.program.sourceFileMayBeEmitted(affectedFile, false)) {
1966
+ this.deletedPendingKinds.add(path);
1967
+ continue;
1968
+ }
1969
+ const result = new EmitResult();
1970
+ result.emitSkipped = true;
1971
+ for (const d of diagnostics.getDiagnostics(program.program, affectedFile)) result.diagnostics.push(d);
1972
+ this.emitUpdates.set(path, new EmitUpdate(snapshot.affectedFilesPendingEmit.get(path) ?? 0, result, true));
1973
+ }
1974
+ return this.updateSnapshot();
1975
+ }
1976
+
1977
+ /** 1 to skip writing an unchanged declaration file, 2 to keep its time stamp, 0 to write it. */
1978
+ skipDtsOutputOfComposite(file: SourceFile, outputFileName: string, text: string, newSignature: string): number {
1979
+ const snapshot = this.program.snapshot;
1980
+ if (snapshot.options.composite !== true) return 0;
1981
+ const signature =
1982
+ newSignature !== '' ? newSignature : computeHash(getTextHandlingSourceMapForSignature(text, snapshot.options));
1983
+ return this.skipDtsOutputWithSignature(file, outputFileName, signature);
1984
+ }
1985
+
1986
+ /** `skipDtsOutputOfComposite` with the declaration file's signature computed. */
1987
+ private skipDtsOutputWithSignature(file: SourceFile, outputFileName: string, signature: string): number {
1988
+ const snapshot = this.program.snapshot;
1989
+ let oldSignature = '';
1990
+ const oldSignatureFormat = snapshot.emitSignatures.get(file.path);
1991
+ if (oldSignatureFormat !== undefined) {
1992
+ oldSignature =
1993
+ oldSignatureFormat.signature !== ''
1994
+ ? oldSignatureFormat.signature
1995
+ : (oldSignatureFormat.signatureWithDifferentOptions ?? '');
1996
+ }
1997
+ let result = 0;
1998
+ if (signature === oldSignature) {
1999
+ if (oldSignatureFormat !== undefined && oldSignatureFormat.signature === oldSignature) return 1;
2000
+ if (snapshot.options.build === true) result = 2;
2001
+ } else this.latestChangedDtsFiles.set(file.path, outputFileName);
2002
+ this.emitSignatures.set(file.path, new EmitSignature(signature, undefined));
2003
+ return result;
2004
+ }
2005
+
2006
+ /**
2007
+ * Records the declaration files a checker thread emitted for `file` (`EmitResult.declarationSignatures`),
2008
+ * as `SignatureRecordingWriter` records the ones written here. For a composite program, returns what
2009
+ * `skipDtsOutputOfComposite` answers for each declaration file, by file name: on a rebuild the thread held
2010
+ * its outputs (parallel-check.ts) for `HeldDeclarationWriter` to write. A program without old build info
2011
+ * has no old emit signatures, so its threads wrote their outputs, none of which was to be skipped.
2012
+ */
2013
+ private recordDeclarationSignatures(
2014
+ file: SourceFile,
2015
+ signatures: readonly string[],
2016
+ ): Map<string, number> | undefined {
2017
+ const snapshot = this.program.snapshot;
2018
+ if (!snapshot.canUseIncrementalState()) return undefined;
2019
+ let skips: Map<string, number> | undefined = undefined;
2020
+ for (let i = 0; i + 2 < signatures.length; i += 3) {
2021
+ const info = snapshot.fileInfos.get(file.path);
2022
+ if (info !== undefined && info.signature === info.version) {
2023
+ const signature = signatures[i + 1]!;
2024
+ if (signature !== info.version) this.signatures.set(file.path, signature);
2025
+ }
2026
+ if (snapshot.options.composite === true) {
2027
+ if (skips === undefined) skips = new Map<string, number>();
2028
+ skips.set(signatures[i]!, this.skipDtsOutputWithSignature(file, signatures[i]!, signatures[i + 2]!));
2029
+ }
2030
+ }
2031
+ return skips;
2032
+ }
2033
+
2034
+ private updateSnapshot(): EmitResult[] {
2035
+ const program = this.program;
2036
+ const snapshot = program.snapshot;
2037
+ const results: EmitResult[] = [];
2038
+ if (snapshot.canUseIncrementalState()) {
2039
+ for (const [path, signature] of this.signatures) {
2040
+ const info = snapshot.fileInfos.get(path);
2041
+ if (info !== undefined) info.signature = signature;
2042
+ snapshot.buildInfoEmitPending = true;
2043
+ }
2044
+ for (const [path, signature] of this.emitSignatures) {
2045
+ snapshot.emitSignatures.set(path, signature);
2046
+ snapshot.buildInfoEmitPending = true;
2047
+ }
2048
+ for (const path of this.deletedPendingKinds) {
2049
+ snapshot.affectedFilesPendingEmit.delete(path);
2050
+ snapshot.buildInfoEmitPending = true;
2051
+ }
2052
+ for (const file of program.program.getSourceFiles()) {
2053
+ const latest = this.latestChangedDtsFiles.get(file.path);
2054
+ if (latest !== undefined) {
2055
+ snapshot.latestChangedDtsFile = latest;
2056
+ snapshot.buildInfoEmitPending = true;
2057
+ snapshot.hasChangedDtsFile = true;
2058
+ }
2059
+ const update = this.emitUpdates.get(file.path);
2060
+ if (update === undefined) continue;
2061
+ if (!update.dtsErrorsFromCache) {
2062
+ if (update.pendingKind === 0) snapshot.affectedFilesPendingEmit.delete(file.path);
2063
+ else snapshot.affectedFilesPendingEmit.set(file.path, update.pendingKind);
2064
+ snapshot.buildInfoEmitPending = true;
2065
+ }
2066
+ const result = update.result;
2067
+ if (result !== undefined) {
2068
+ results.push(result);
2069
+ if (result.diagnostics.length !== 0) {
2070
+ snapshot.emitDiagnosticsPerFile.set(file.path, FileDiagnostics.of(result.diagnostics.slice()));
2071
+ }
2072
+ }
2073
+ }
2074
+ } else if (this.hasEmitDiagnostics) snapshot.hasEmitDiagnostics = true;
2075
+ return results;
2076
+ }
2077
+ }
2078
+
2079
+ // ---- Writing build info
2080
+
2081
+ class ToBuildInfo {
2082
+ readonly buildInfo = new BuildInfo();
2083
+ private readonly buildInfoDirectory: string;
2084
+ private readonly fileNameToFileId = new Map<string, number>();
2085
+ /** The ids of the lists of file ids so far, by `hashOfIds` of their ids. */
2086
+ private readonly fileIdListIdsOfHash = new Map<number, number[]>();
2087
+ private readonly roots = new Map<SourceFile, string>();
2088
+ /** `relativePath` of the directories of the paths so far. */
2089
+ private readonly relativeDirectories = new Map<string, string>();
2090
+ /** The path of each file id so far. */
2091
+ private readonly fileIdPaths: string[] = [];
2092
+ /**
2093
+ * How many of the first file ids here are of the same paths as in the snapshot's `fileIdLists`, once
2094
+ * computed.
2095
+ */
2096
+ private sameFileIds = -1;
2097
+ /** The id here of each list of the snapshot's `fileIdLists` written so far. */
2098
+ private readonly listIdOfOldList = new Map<number, number>();
2099
+
2100
+ constructor(
2101
+ private readonly snapshot: Snapshot,
2102
+ private readonly program: Program,
2103
+ buildInfoFileName: string,
2104
+ ) {
2105
+ this.buildInfoDirectory = getDirectoryPath(buildInfoFileName);
2106
+ }
2107
+
2108
+ private relativeToBuildInfo(path: string): string {
2109
+ return ensurePathIsNonModuleName(this.relativePath(path));
2110
+ }
2111
+
2112
+ /**
2113
+ * The path of `path` relative to the build info's directory: that of its directory and its name,
2114
+ * unless the directory is the build info's directory or one above it, where the name could be a
2115
+ * component of the build info's directory.
2116
+ */
2117
+ private relativePath(path: string): string {
2118
+ const slash = path.lastIndexOf('/');
2119
+ const name = path.slice(slash + 1);
2120
+ if (slash > getRootLength(path) && name !== '' && name !== '.' && name !== '..' && !path.includes('\\')) {
2121
+ const directory = path.slice(0, slash);
2122
+ let relative = this.relativeDirectories.get(directory);
2123
+ if (relative === undefined) {
2124
+ relative = this.relativePath(directory);
2125
+ this.relativeDirectories.set(directory, relative);
2126
+ }
2127
+ if (relative !== '' && !isParentDirectoryPath(relative)) return relative + '/' + name;
2128
+ }
2129
+ return getRelativePathFromDirectory(
2130
+ this.buildInfoDirectory,
2131
+ path,
2132
+ this.program.useCaseSensitiveFileNames,
2133
+ this.program.currentDirectory,
2134
+ );
2135
+ }
2136
+
2137
+ /** The path tsgo orders a file by, where bundled libraries have `bundled:///libs/` paths. */
2138
+ private orderPath(path: string): string {
2139
+ const libFile = this.program.getDefaultLibFile(path);
2140
+ return libFile !== undefined && !libFile.replaced ? 'bundled:///libs/' + libFile.name : path;
2141
+ }
2142
+
2143
+ /** Orders paths as tsgo does (`orderPath`). */
2144
+ private readonly comparePaths = (a: string, b: string): number =>
2145
+ compareStrings(this.orderPath(a), this.orderPath(b));
2146
+
2147
+ private toFileId(path: string): number {
2148
+ let fileId = this.fileNameToFileId.get(path);
2149
+ if (fileId === undefined) {
2150
+ const libFile = this.program.getDefaultLibFile(path);
2151
+ if (libFile !== undefined && !libFile.replaced) this.buildInfo.fileNames.push(libFile.name);
2152
+ else this.buildInfo.fileNames.push(this.relativeToBuildInfo(path));
2153
+ this.fileIdPaths.push(path);
2154
+ fileId = this.buildInfo.fileNames.length;
2155
+ this.fileNameToFileId.set(path, fileId);
2156
+ }
2157
+ return fileId;
2158
+ }
2159
+
2160
+ /** The id of the list of the ids of `set`, the references of the file at `path`. */
2161
+ private toFileIdListId(path: string, set: ReadonlySet<string>): number {
2162
+ // A set read from the old build info has the ids it was read from, where those are the same here.
2163
+ const lists = this.snapshot.fileIdLists;
2164
+ let oldIndex = lists?.listOfFile.get(path);
2165
+ if (oldIndex !== undefined && lists?.sets[oldIndex] !== set) oldIndex = undefined;
2166
+ // The index of the list taken as read, or -1.
2167
+ let readIndex = -1;
2168
+ if (lists !== undefined && oldIndex !== undefined) {
2169
+ const known = this.listIdOfOldList.get(oldIndex);
2170
+ if (known !== undefined) return known;
2171
+ if (this.hasSameFileIds(oldIndex, lists)) readIndex = oldIndex;
2172
+ }
2173
+ let fileIds: number[];
2174
+ let hash: number;
2175
+ if (lists !== undefined && readIndex >= 0) {
2176
+ fileIds = lists.ids[readIndex];
2177
+ hash = lists.hashes[readIndex];
2178
+ } else {
2179
+ fileIds = [];
2180
+ for (const reference of set) fileIds.push(this.toFileId(reference));
2181
+ fileIds.sort((a, b) => a - b);
2182
+ hash = hashOfIds(fileIds);
2183
+ }
2184
+ let listIds = this.fileIdListIdsOfHash.get(hash);
2185
+ if (listIds === undefined) {
2186
+ listIds = [];
2187
+ this.fileIdListIdsOfHash.set(hash, listIds);
2188
+ }
2189
+ let id = 0;
2190
+ for (const listId of listIds) {
2191
+ if (sameIds(this.buildInfo.fileIdsList[listId - 1], fileIds)) {
2192
+ id = listId;
2193
+ break;
2194
+ }
2195
+ }
2196
+ if (id === 0) {
2197
+ // A list taken as read has the text it was read from.
2198
+ const text =
2199
+ lists !== undefined && readIndex >= 0 && readIndex < lists.texts.length
2200
+ ? lists.texts[readIndex]
2201
+ : fileIds.join(',');
2202
+ this.buildInfo.fileIdsList.push(fileIds);
2203
+ this.buildInfo.fileIdsListText.push(text);
2204
+ id = this.buildInfo.fileIdsList.length;
2205
+ listIds.push(id);
2206
+ }
2207
+ if (readIndex >= 0) this.listIdOfOldList.set(readIndex, id);
2208
+ return id;
2209
+ }
2210
+
2211
+ /**
2212
+ * Whether the list at `index` of `lists` has ascending ids that are of the same paths here, as the ids of
2213
+ * the program's files, which come first, are where the program has the same files in the same order.
2214
+ */
2215
+ private hasSameFileIds(index: number, lists: FileIdLists): boolean {
2216
+ if (this.sameFileIds < 0) {
2217
+ const paths = this.fileIdPaths;
2218
+ const oldPaths = lists.filePaths;
2219
+ const length = Math.min(paths.length, oldPaths.length);
2220
+ let same = 0;
2221
+ while (same < length && paths[same] === oldPaths[same]) same++;
2222
+ this.sameFileIds = same;
2223
+ }
2224
+ const last = lists.lastIds[index];
2225
+ return last >= 0 && last <= this.sameFileIds;
2226
+ }
2227
+
2228
+ private toBuildInfoDiagnostics(filePath: string, diagnostics: readonly Diagnostic[]): BuildInfoDiagnostic[] {
2229
+ return diagnostics.map((d) => {
2230
+ const result = new BuildInfoDiagnostic();
2231
+ const file = d.file;
2232
+ if (file === undefined) result.noFile = true;
2233
+ else {
2234
+ const path = toPath(file.fileName, this.program.currentDirectory, this.program.useCaseSensitiveFileNames);
2235
+ if (path !== filePath) result.file = this.toFileId(path);
2236
+ }
2237
+ // Build info positions are UTF-8 offsets, like tsgo's.
2238
+ result.pos = file === undefined ? d.pos : file.toUtf8Offset(d.pos);
2239
+ result.end = file === undefined ? d.end : file.toUtf8Offset(d.end);
2240
+ result.code = d.code;
2241
+ result.category = d.category;
2242
+ result.messageKey = messageKey(d.message);
2243
+ result.messageArgs = d.args.slice();
2244
+ result.messageChain = this.toBuildInfoDiagnostics(filePath, d.messageChain);
2245
+ result.relatedInformation = this.toBuildInfoDiagnostics(filePath, d.relatedInformation);
2246
+ result.reportsUnnecessary = d.reportsUnnecessary;
2247
+ result.reportsDeprecated = d.reportsDeprecated;
2248
+ result.skippedOnNoEmit = d.skippedOnNoEmit;
2249
+ result.repopulateInfo = d.repopulateInfo;
2250
+ return result;
2251
+ });
2252
+ }
2253
+
2254
+ private storedToBuildInfoDiagnostics(diagnostics: readonly StoredDiagnostic[]): BuildInfoDiagnostic[] {
2255
+ return diagnostics.map((d) => {
2256
+ const result = new BuildInfoDiagnostic();
2257
+ const stored = d.stored;
2258
+ result.file = d.file !== '' ? this.toFileId(d.file) : 0;
2259
+ result.noFile = stored.noFile;
2260
+ result.pos = stored.pos;
2261
+ result.end = stored.end;
2262
+ result.code = stored.code;
2263
+ result.category = stored.category;
2264
+ result.messageKey = stored.messageKey;
2265
+ result.messageArgs = stored.messageArgs;
2266
+ result.messageChain = this.storedToBuildInfoDiagnostics(d.messageChain);
2267
+ result.relatedInformation = this.storedToBuildInfoDiagnostics(d.relatedInformation);
2268
+ result.reportsUnnecessary = stored.reportsUnnecessary;
2269
+ result.reportsDeprecated = stored.reportsDeprecated;
2270
+ result.skippedOnNoEmit = stored.skippedOnNoEmit;
2271
+ result.repopulateInfo = stored.repopulateInfo;
2272
+ return result;
2273
+ });
2274
+ }
2275
+
2276
+ private toDiagnosticsOfFile(path: string, diagnostics: FileDiagnostics): BuildInfoDiagnosticsOfFile | undefined {
2277
+ const computed = diagnostics.computed;
2278
+ if (computed !== undefined && computed.length > 0) {
2279
+ return new BuildInfoDiagnosticsOfFile(this.toFileId(path), this.toBuildInfoDiagnostics(path, computed));
2280
+ }
2281
+ const stored = diagnostics.stored;
2282
+ if (computed === undefined && stored !== undefined && stored.length > 0) {
2283
+ return new BuildInfoDiagnosticsOfFile(this.toFileId(path), this.storedToBuildInfoDiagnostics(stored));
2284
+ }
2285
+ return undefined;
2286
+ }
2287
+
2288
+ build(): BuildInfo {
2289
+ const snapshot = this.snapshot;
2290
+ const buildInfo = this.buildInfo;
2291
+ const program = this.program;
2292
+ buildInfo.version = version;
2293
+ if (isIncremental(snapshot.options)) {
2294
+ this.collectRootFiles();
2295
+ this.setFileInfoAndEmitSignatures();
2296
+ this.setRootOfIncrementalProgram();
2297
+ this.setCompilerOptions();
2298
+ this.setReferencedMap();
2299
+ const changed = [...snapshot.changedFilesSet].sort(this.comparePaths);
2300
+ buildInfo.changeFileSet = changed.map((path) => this.toFileId(path));
2301
+ this.setSemanticDiagnostics();
2302
+ const emitDiagnostics = [...snapshot.emitDiagnosticsPerFile.keys()].sort(this.comparePaths);
2303
+ for (const path of emitDiagnostics) {
2304
+ const diagnostics = snapshot.emitDiagnosticsPerFile.get(path);
2305
+ if (diagnostics === undefined) continue;
2306
+ const ofFile = this.toDiagnosticsOfFile(path, diagnostics);
2307
+ if (ofFile !== undefined) buildInfo.emitDiagnosticsPerFile.push(ofFile);
2308
+ }
2309
+ this.setAffectedFilesPendingEmit();
2310
+ if (snapshot.latestChangedDtsFile !== '') {
2311
+ buildInfo.latestChangedDtsFile = this.relativeToBuildInfo(snapshot.latestChangedDtsFile);
2312
+ }
2313
+ } else {
2314
+ for (const fileName of program.commandLine.fileNames) {
2315
+ buildInfo.root.push(
2316
+ new BuildInfoRoot(
2317
+ 0,
2318
+ 0,
2319
+ this.relativeToBuildInfo(toPath(fileName, program.currentDirectory, program.useCaseSensitiveFileNames)),
2320
+ ),
2321
+ );
2322
+ }
2323
+ }
2324
+ buildInfo.errors = snapshot.hasErrors === Tristate.True;
2325
+ buildInfo.semanticErrors = snapshot.hasSemanticErrors;
2326
+ buildInfo.checkPending = snapshot.checkPending;
2327
+ const packageJsons = snapshot.packageJsons;
2328
+ if (packageJsons !== undefined) buildInfo.packageJsons = packageJsons.map((p) => this.relativeToBuildInfo(p));
2329
+ buildInfo.missingPackageJsons = snapshot.missingPackageJsons.map((p) => this.relativeToBuildInfo(p));
2330
+ return buildInfo;
2331
+ }
2332
+
2333
+ private collectRootFiles(): void {
2334
+ const program = this.program;
2335
+ for (const fileName of program.commandLine.fileNames) {
2336
+ const path = program.toPath(fileName);
2337
+ const redirect = program.getParseFileRedirect(fileName);
2338
+ const file = redirect !== '' ? program.getSourceFile(redirect) : program.getSourceFileByPath(path);
2339
+ if (file !== undefined) this.roots.set(file, path);
2340
+ }
2341
+ }
2342
+
2343
+ private setFileInfoAndEmitSignatures(): void {
2344
+ const snapshot = this.snapshot;
2345
+ const program = this.program;
2346
+ for (const file of program.getSourceFiles()) {
2347
+ const info = snapshot.fileInfos.get(file.path);
2348
+ const fileId = this.toFileId(file.path);
2349
+ if (info === undefined) continue;
2350
+ if (
2351
+ snapshot.options.composite === true &&
2352
+ !isJsonSourceFile(file) &&
2353
+ program.sourceFileMayBeEmitted(file, false)
2354
+ ) {
2355
+ const emitSignature = snapshot.emitSignatures.get(file.path);
2356
+ if (emitSignature === undefined) {
2357
+ this.buildInfo.emitSignatures.push(new BuildInfoEmitSignature(fileId, '', false, false));
2358
+ } else if (emitSignature.signature !== info.signature) {
2359
+ if (emitSignature.signature !== '') {
2360
+ this.buildInfo.emitSignatures.push(
2361
+ new BuildInfoEmitSignature(fileId, emitSignature.signature, false, false),
2362
+ );
2363
+ } else if (emitSignature.signatureWithDifferentOptions === info.signature) {
2364
+ this.buildInfo.emitSignatures.push(new BuildInfoEmitSignature(fileId, '', true, false));
2365
+ } else {
2366
+ this.buildInfo.emitSignatures.push(
2367
+ new BuildInfoEmitSignature(fileId, emitSignature.signatureWithDifferentOptions ?? '', false, true),
2368
+ );
2369
+ }
2370
+ }
2371
+ }
2372
+ this.buildInfo.fileInfos.push(toBuildInfoFileInfo(info));
2373
+ }
2374
+ }
2375
+
2376
+ private setRootOfIncrementalProgram(): void {
2377
+ // The files in the order of their ids, each looked up once.
2378
+ const files = [...this.roots.keys()];
2379
+ const ids: number[] = [];
2380
+ const order: number[] = [];
2381
+ for (let i = 0; i < files.length; i++) {
2382
+ ids.push(this.toFileId(files[i].path));
2383
+ order.push(i);
2384
+ }
2385
+ order.sort((a, b) => ids[a] - ids[b]);
2386
+ const roots = this.buildInfo.root;
2387
+ for (const i of order) {
2388
+ const file = files[i];
2389
+ const rootPath = this.roots.get(file);
2390
+ if (rootPath === undefined) continue;
2391
+ const root = this.toFileId(rootPath);
2392
+ const resolved = ids[i];
2393
+ const last = roots.length > 0 ? roots[roots.length - 1] : undefined;
2394
+ if (last === undefined) roots.push(new BuildInfoRoot(resolved, 0, ''));
2395
+ else if (last.end === resolved - 1) last.end = resolved;
2396
+ else if (last.end === 0 && last.start === resolved - 1) last.end = resolved;
2397
+ else roots.push(new BuildInfoRoot(resolved, 0, ''));
2398
+ if (root !== resolved) this.buildInfo.resolvedRoot.push(new BuildInfoResolvedRoot(resolved, root));
2399
+ }
2400
+ }
2401
+
2402
+ private setCompilerOptions(): void {
2403
+ const options = this.snapshot.options;
2404
+ let result: BuildInfoOption[] | undefined = undefined;
2405
+ for (const option of compilerOptionDeclarationsInFieldOrder()) {
2406
+ if (((option.affects ?? 0) & Affects.BuildInfo) === 0) continue;
2407
+ const value = compilerOptionValue(options, option.name);
2408
+ if (value === undefined || value === '' || value === 0) continue;
2409
+ if (result === undefined) result = [];
2410
+ result.push(new BuildInfoOption(option.name, this.relativeOptionValue(option, value)));
2411
+ }
2412
+ this.buildInfo.options = result;
2413
+ }
2414
+
2415
+ private relativeOptionValue(option: OptionDeclaration, value: CompilerOptionValue): CompilerOptionValue {
2416
+ if (option.kind === 'list') {
2417
+ if (option.element?.isFilePath === true && Array.isArray(value)) {
2418
+ return value.map((v) => this.relativeToBuildInfo(v));
2419
+ }
2420
+ } else if (option.isFilePath === true && typeof value === 'string' && value !== '') {
2421
+ return this.relativeToBuildInfo(value);
2422
+ }
2423
+ return value;
2424
+ }
2425
+
2426
+ private setReferencedMap(): void {
2427
+ const references = this.snapshot.referencedMap.references;
2428
+ const keys = [...references.keys()].sort(this.comparePaths);
2429
+ for (const path of keys) {
2430
+ const set = references.get(path);
2431
+ if (set === undefined) continue;
2432
+ this.buildInfo.referencedMap.push(new BuildInfoReference(this.toFileId(path), this.toFileIdListId(path, set)));
2433
+ }
2434
+ }
2435
+
2436
+ private setSemanticDiagnostics(): void {
2437
+ const snapshot = this.snapshot;
2438
+ for (const file of this.program.getSourceFiles()) {
2439
+ const value = snapshot.semanticDiagnosticsPerFile.get(file.path);
2440
+ if (value === undefined) {
2441
+ if (!snapshot.changedFilesSet.has(file.path)) {
2442
+ this.buildInfo.semanticDiagnosticsPerFile.push(
2443
+ new BuildInfoSemanticDiagnostic(this.toFileId(file.path), undefined),
2444
+ );
2445
+ }
2446
+ } else {
2447
+ const diagnostics = this.toDiagnosticsOfFile(file.path, value);
2448
+ if (diagnostics !== undefined) {
2449
+ this.buildInfo.semanticDiagnosticsPerFile.push(new BuildInfoSemanticDiagnostic(0, diagnostics));
2450
+ }
2451
+ }
2452
+ }
2453
+ }
2454
+
2455
+ private setAffectedFilesPendingEmit(): void {
2456
+ const snapshot = this.snapshot;
2457
+ const files = [...snapshot.affectedFilesPendingEmit.keys()].sort(this.comparePaths);
2458
+ const fullEmitKind = getFileEmitKind(snapshot.options);
2459
+ for (const path of files) {
2460
+ const file = this.program.getSourceFileByPath(path);
2461
+ if (file === undefined || !this.program.sourceFileMayBeEmitted(file, false)) continue;
2462
+ const pending = snapshot.affectedFilesPendingEmit.get(path) ?? 0;
2463
+ this.buildInfo.affectedFilesPendingEmit.push(
2464
+ new BuildInfoFilePendingEmit(this.toFileId(path), pending === fullEmitKind ? 0 : pending),
2465
+ );
2466
+ }
2467
+ }
2468
+ }
2469
+
2470
+ // ---- The incremental program
2471
+
2472
+ /** File time stamps, for `--build`'s up-to-date checks. */
2473
+ export abstract class TimeStampHost {
2474
+ /** Modification time in milliseconds, or `undefined` if the file doesn't exist. */
2475
+ abstract getMTime(fileName: string): number | undefined;
2476
+ abstract setMTime(fileName: string, time: number): void;
2477
+ }
2478
+
2479
+ export class IncrementalProgram extends CompilerProgram {
2480
+ readonly snapshot: Snapshot;
2481
+
2482
+ /**
2483
+ * `signatures`: the shape signatures (`declarationSignature`) of files of this program that were
2484
+ * computed before it, by path, which the affected files take instead of emitting the files again.
2485
+ */
2486
+ constructor(
2487
+ checked: CheckedProgram,
2488
+ times: CompileTimes,
2489
+ oldSnapshot: Snapshot | undefined,
2490
+ readonly host: TimeStampHost,
2491
+ readonly signatures: ReadonlyMap<string, string> = new Map(),
2492
+ ) {
2493
+ super(checked, times);
2494
+ this.snapshot = programToSnapshot(checked, oldSnapshot);
2495
+ }
2496
+
2497
+ get hasChangedDtsFile(): boolean {
2498
+ return this.snapshot.hasChangedDtsFile;
2499
+ }
2500
+
2501
+ /**
2502
+ * The global diagnostics found before `filesToCheck` computed the affected files, which the program
2503
+ * reports before its semantic diagnostics (`getGlobalDiagnostics(false)`), as when they are computed
2504
+ * while checking.
2505
+ */
2506
+ private globalDiagnosticsBeforeChecking: Diagnostic[] | undefined = undefined;
2507
+
2508
+ getGlobalDiagnostics(withCheckerThreads = true): Diagnostic[] {
2509
+ const before = this.globalDiagnosticsBeforeChecking;
2510
+ if (!withCheckerThreads && before !== undefined) return before;
2511
+ return super.getGlobalDiagnostics(withCheckerThreads);
2512
+ }
2513
+
2514
+ /**
2515
+ * The files `getSemanticDiagnostics` checks: once the affected files are known
2516
+ * (`collectAllAffectedFiles`), those the build info has no semantic diagnostics for. Called before
2517
+ * reporting, so that checker threads can check them (tsc-compile.ts).
2518
+ */
2519
+ filesToCheck(): SourceFile[] {
2520
+ const snapshot = this.snapshot;
2521
+ if (snapshot.options.noCheck === true) return [];
2522
+ this.globalDiagnosticsBeforeChecking = super.getGlobalDiagnostics(false);
2523
+ if (snapshot.canUseIncrementalState()) collectAllAffectedFiles(this);
2524
+ const result: SourceFile[] = [];
2525
+ for (const file of this.program.getSourceFiles())
2526
+ if (!snapshot.semanticDiagnosticsPerFile.has(file.path) && !this.checked.skipTypeChecking(file))
2527
+ result.push(file);
2528
+ return result;
2529
+ }
2530
+
2531
+ /**
2532
+ * For checker threads that check `files` (from `filesToCheck`) and emit them, what the emit of each
2533
+ * file includes, by file index: its pending emit (`EmitFilesHandler.emitFilesIncremental`), or -1.
2534
+ * The incremental program's emit then takes what the threads emitted.
2535
+ */
2536
+ emitKindsOnCheckers(files: readonly SourceFile[]): number[] {
2537
+ const program = this.program;
2538
+ const all = program.getSourceFiles();
2539
+ const index = new Map<SourceFile, number>();
2540
+ for (let i = 0; i < all.length; i++) index.set(all[i]!, i);
2541
+ const result: number[] = [];
2542
+ for (let i = 0; i < all.length; i++) result.push(-1);
2543
+ const checking = new Set(files);
2544
+ for (const [path, emitKind] of this.snapshot.affectedFilesPendingEmit) {
2545
+ const file = program.getSourceFileByPath(path);
2546
+ if (file === undefined || !checking.has(file) || !program.sourceFileMayBeEmitted(file, false)) continue;
2547
+ const pendingKind = getPendingEmitKind(emitKind, 0);
2548
+ if (pendingKind !== 0) result[index.get(file)!] = emitOnlyOfPendingKind(pendingKind);
2549
+ }
2550
+ return result;
2551
+ }
2552
+
2553
+ getSemanticDiagnostics(): Diagnostic[] {
2554
+ const options = this.snapshot.options;
2555
+ if (options.noCheck === true) return [];
2556
+ this.collectSemanticDiagnosticsOfAffectedFiles();
2557
+ const result: Diagnostic[] = [];
2558
+ for (const file of this.program.getSourceFiles()) {
2559
+ for (const d of this.getSemanticDiagnosticsOfFile(file)) result.push(d);
2560
+ }
2561
+ return result;
2562
+ }
2563
+
2564
+ private getSemanticDiagnosticsOfFile(file: SourceFile): Diagnostic[] {
2565
+ const cached = this.snapshot.semanticDiagnosticsPerFile.get(file.path);
2566
+ const result: Diagnostic[] = [];
2567
+ if (cached !== undefined) {
2568
+ const noEmit = this.snapshot.options.noEmit === true;
2569
+ for (const d of cached.getDiagnostics(this.program, file)) if (!noEmit || !d.skippedOnNoEmit) result.push(d);
2570
+ }
2571
+ for (const d of this.checked.getIncludeProcessorDiagnostics(file)) result.push(d);
2572
+ return result;
2573
+ }
2574
+
2575
+ getDeclarationDiagnostics(): Diagnostic[] {
2576
+ return new EmitFilesHandler(this, true).emitAllAffectedFiles(new DiscardWriter()).diagnostics;
2577
+ }
2578
+
2579
+ /**
2580
+ * Declaration emit errors of `files`, without writing. Declaration emit is per file: those checker
2581
+ * threads computed under `noEmit` (`declarationsInParallel`), the others here, in order.
2582
+ */
2583
+ emitDeclarationDiagnostics(files: readonly SourceFile[]): Diagnostic[] {
2584
+ const checked = this.checked;
2585
+ if (checked.declarationsInParallel === undefined)
2586
+ return this.emitter.emit(files, EmitOnly.ForcedDts, new DiscardWriter()).diagnostics;
2587
+ const result: Diagnostic[] = [];
2588
+ for (const file of files) {
2589
+ const diagnostics =
2590
+ checked.declarationDiagnosticsInParallel(file) ?? declarationDiagnosticsOfFile(this.emitter, file);
2591
+ for (const d of diagnostics) result.push(d);
2592
+ }
2593
+ return result;
2594
+ }
2595
+
2596
+ emit(writer: OutputWriter): EmitResult {
2597
+ const options = this.snapshot.options;
2598
+ let result: EmitResult | undefined;
2599
+ if (options.noEmit === true) {
2600
+ result = new EmitResult();
2601
+ result.emitSkipped = true;
2602
+ } else result = handleNoEmitOnError(this);
2603
+ if (result !== undefined) {
2604
+ const buildInfoResult = this.emitBuildInfo(writer);
2605
+ if (buildInfoResult !== undefined) {
2606
+ for (const d of buildInfoResult.diagnostics) result.diagnostics.push(d);
2607
+ for (const f of buildInfoResult.emittedFiles) result.emittedFiles.push(f);
2608
+ }
2609
+ return result;
2610
+ }
2611
+ return new EmitFilesHandler(this, false).emitAllAffectedFiles(writer);
2612
+ }
2613
+
2614
+ private collectSemanticDiagnosticsOfAffectedFiles(): void {
2615
+ const snapshot = this.snapshot;
2616
+ const files = this.program.getSourceFiles();
2617
+ if (snapshot.canUseIncrementalState()) {
2618
+ collectAllAffectedFiles(this);
2619
+ if (snapshot.semanticDiagnosticsPerFile.size === files.length) return;
2620
+ }
2621
+ for (const file of files) {
2622
+ if (snapshot.semanticDiagnosticsPerFile.has(file.path)) continue;
2623
+ snapshot.semanticDiagnosticsPerFile.set(
2624
+ file.path,
2625
+ FileDiagnostics.of(this.checked.getSemanticDiagnosticsWithoutNoEmitFiltering(file)),
2626
+ );
2627
+ }
2628
+ if (
2629
+ snapshot.semanticDiagnosticsPerFile.size === files.length &&
2630
+ snapshot.checkPending &&
2631
+ snapshot.options.noCheck !== true
2632
+ ) {
2633
+ snapshot.checkPending = false;
2634
+ }
2635
+ snapshot.buildInfoEmitPending = true;
2636
+ }
2637
+
2638
+ /** Writes the build info if it changed; `undefined` if nothing was written. */
2639
+ emitBuildInfo(writer: OutputWriter): EmitResult | undefined {
2640
+ const snapshot = this.snapshot;
2641
+ const program = this.program;
2642
+ const buildInfoFileName = program.commandLine.buildInfoFileName();
2643
+ if (buildInfoFileName === '' || program.isEmitBlocked(buildInfoFileName)) return undefined;
2644
+ if (snapshot.hasErrors === Tristate.Unknown) {
2645
+ this.ensureHasErrorsForState();
2646
+ if (
2647
+ snapshot.hasErrors !== snapshot.hasErrorsFromOldState ||
2648
+ snapshot.hasSemanticErrors !== snapshot.hasSemanticErrorsFromOldState
2649
+ ) {
2650
+ snapshot.buildInfoEmitPending = true;
2651
+ }
2652
+ }
2653
+ if (snapshot.packageJsons === undefined) {
2654
+ this.ensurePackageJsonsForState();
2655
+ if (
2656
+ !sameList(snapshot.packageJsons ?? noStrings, snapshot.packageJsonsFromOldState) ||
2657
+ !sameList(snapshot.missingPackageJsons, snapshot.missingPackageJsonsFromOldState)
2658
+ ) {
2659
+ snapshot.buildInfoEmitPending = true;
2660
+ }
2661
+ }
2662
+ if (!snapshot.buildInfoEmitPending) return undefined;
2663
+ const absolute = getNormalizedAbsolutePath(buildInfoFileName, program.currentDirectory);
2664
+ const buildInfo = new ToBuildInfo(snapshot, program, absolute).build();
2665
+ const text = buildInfoToJson(buildInfo);
2666
+ const error = writer.write(buildInfoFileName, text, []);
2667
+ const result = new EmitResult();
2668
+ if (error !== '' && error !== skippedWrite) {
2669
+ result.emitSkipped = true;
2670
+ result.diagnostics.push(
2671
+ createCompilerDiagnostic(Diagnostics.Could_not_write_file_0_Colon_1, buildInfoFileName, error),
2672
+ );
2673
+ return result;
2674
+ }
2675
+ this.lastBuildInfo = buildInfo;
2676
+ snapshot.buildInfoEmitPending = false;
2677
+ result.emittedFiles.push(buildInfoFileName);
2678
+ return result;
2679
+ }
2680
+
2681
+ /** The build info written last, for `--build`. */
2682
+ lastBuildInfo: BuildInfo | undefined = undefined;
2683
+
2684
+ private ensureHasErrorsForState(): void {
2685
+ const snapshot = this.snapshot;
2686
+ const program = this.program;
2687
+ const checked = this.checked;
2688
+ const files = program.getSourceFiles();
2689
+ let hasEmitDiagnostics = false;
2690
+ // Without the files whose checking is skipped, and filtered by comment directives, as when reported.
2691
+ let hasIncludeProcessingDiagnostics = false;
2692
+ if (snapshot.canUseIncrementalState()) {
2693
+ for (const file of files) {
2694
+ if (snapshot.emitDiagnosticsPerFile.has(file.path)) {
2695
+ hasEmitDiagnostics = true;
2696
+ break;
2697
+ }
2698
+ if (!hasIncludeProcessingDiagnostics && checked.getIncludeProcessorDiagnostics(file).length > 0) {
2699
+ hasIncludeProcessingDiagnostics = true;
2700
+ }
2701
+ }
2702
+ } else {
2703
+ hasEmitDiagnostics = snapshot.hasEmitDiagnostics;
2704
+ hasIncludeProcessingDiagnostics = files.some((file) => checked.getIncludeProcessorDiagnostics(file).length > 0);
2705
+ }
2706
+ if (hasEmitDiagnostics) {
2707
+ snapshot.hasErrors = isIncremental(snapshot.options) ? Tristate.False : Tristate.True;
2708
+ snapshot.hasSemanticErrors = false;
2709
+ return;
2710
+ }
2711
+ if (
2712
+ hasIncludeProcessingDiagnostics ||
2713
+ program.getConfigFileParsingDiagnostics().length > 0 ||
2714
+ program.getSyntacticDiagnostics().length > 0 ||
2715
+ program.getProgramDiagnostics().length > 0 ||
2716
+ this.checked.getGlobalDiagnostics().length > 0
2717
+ ) {
2718
+ snapshot.hasErrors = Tristate.True;
2719
+ snapshot.hasSemanticErrors = false;
2720
+ return;
2721
+ }
2722
+ snapshot.hasErrors = Tristate.False;
2723
+ const incremental = isIncremental(snapshot.options);
2724
+ for (const file of files) {
2725
+ const diagnostics = snapshot.semanticDiagnosticsPerFile.get(file.path);
2726
+ if (diagnostics === undefined ? incremental : !diagnostics.isEmpty()) {
2727
+ snapshot.hasSemanticErrors = !incremental;
2728
+ break;
2729
+ }
2730
+ }
2731
+ }
2732
+
2733
+ private ensurePackageJsonsForState(): void {
2734
+ const snapshot = this.snapshot;
2735
+ const program = this.program;
2736
+ const packageJsons: string[] = [];
2737
+ const missing: string[] = [];
2738
+ if (program.commandLine.configName !== '') {
2739
+ for (const info of program.packageJsonLookups()) {
2740
+ let packageJson = combinePaths(info.packageDirectory, 'package.json');
2741
+ const exists = info.exists;
2742
+ if (exists || info.directoryExists) packageJson = program.host.fs.realpath(packageJson);
2743
+ if (exists) packageJsons.push(packageJson);
2744
+ else if (packageJson.includes('/node_modules/')) missing.push(packageJson);
2745
+ }
2746
+ }
2747
+ snapshot.packageJsons = normalizePackageJsons(packageJsons);
2748
+ snapshot.missingPackageJsons = normalizePackageJsons(missing);
2749
+ }
2750
+
2751
+ /** The `package.json` files module resolution looked up, for watching. */
2752
+ packageJsonLookupPaths(): string[] {
2753
+ const program = this.program;
2754
+ if (program.commandLine.configName === '') return [];
2755
+ const result: string[] = [];
2756
+ for (const info of program.packageJsonLookups()) {
2757
+ let packageJson = combinePaths(info.packageDirectory, 'package.json');
2758
+ if (info.exists || info.directoryExists) packageJson = program.host.fs.realpath(packageJson);
2759
+ result.push(packageJson);
2760
+ }
2761
+ return normalizePackageJsons(result);
2762
+ }
2763
+ }
2764
+
2765
+ class DiscardWriter extends OutputWriter {
2766
+ write(_fileName: string, _text: string, _declarationDiagnostics: readonly Diagnostic[]): string {
2767
+ return skippedWrite;
2768
+ }
2769
+ }
2770
+
2771
+ const noStrings: string[] = [];
2772
+
2773
+ function normalizePackageJsons(packageJsons: string[]): string[] {
2774
+ packageJsons.sort(compareStrings);
2775
+ const result: string[] = [];
2776
+ for (const p of packageJsons) if (result.length === 0 || result[result.length - 1] !== p) result.push(p);
2777
+ return result;
2778
+ }
2779
+
2780
+ function sameList(a: readonly string[], b: readonly string[]): boolean {
2781
+ if (a.length !== b.length) return false;
2782
+ for (let i = 0; i < a.length; i++) if (a[i] !== b[i]) return false;
2783
+ return true;
2784
+ }