@scriptc/compiler 0.1.1 → 0.1.2

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 (209) hide show
  1. package/ambient/scriptc-node-fallback.d.ts +45 -17
  2. package/ambient/scriptc.d.ts +2 -1
  3. package/dist/backend/build-cache.js.map +1 -1
  4. package/dist/backend/c/async.js +24 -2
  5. package/dist/backend/c/async.js.map +1 -1
  6. package/dist/backend/c/c-emitter.d.ts +22 -10
  7. package/dist/backend/c/c-emitter.js +60 -15
  8. package/dist/backend/c/c-emitter.js.map +1 -1
  9. package/dist/backend/c/exprs.js +220 -10
  10. package/dist/backend/c/exprs.js.map +1 -1
  11. package/dist/backend/c/island.js.map +1 -1
  12. package/dist/backend/c/may-throw.js.map +1 -1
  13. package/dist/backend/c/stmts.d.ts +3 -5
  14. package/dist/backend/c/stmts.js +58 -17
  15. package/dist/backend/c/stmts.js.map +1 -1
  16. package/dist/backend/c/types.js.map +1 -1
  17. package/dist/backend/c/walkers.js +31 -5
  18. package/dist/backend/c/walkers.js.map +1 -1
  19. package/dist/backend/external-c.js.map +1 -1
  20. package/dist/backend/linker.js.map +1 -1
  21. package/dist/backend/llvm/blocks.js.map +1 -1
  22. package/dist/backend/llvm/dyn.js +56 -3
  23. package/dist/backend/llvm/dyn.js.map +1 -1
  24. package/dist/backend/llvm/emitter.js +98 -19
  25. package/dist/backend/llvm/emitter.js.map +1 -1
  26. package/dist/backend/llvm/expr-async.js +85 -3
  27. package/dist/backend/llvm/expr-async.js.map +1 -1
  28. package/dist/backend/llvm/expr-bytes.js.map +1 -1
  29. package/dist/backend/llvm/expr-calls.js.map +1 -1
  30. package/dist/backend/llvm/expr-containers.js.map +1 -1
  31. package/dist/backend/llvm/expr-context.d.ts +1 -0
  32. package/dist/backend/llvm/expr-control.js.map +1 -1
  33. package/dist/backend/llvm/expr-dispatch.js.map +1 -1
  34. package/dist/backend/llvm/expr-dynamic.js +6 -3
  35. package/dist/backend/llvm/expr-dynamic.js.map +1 -1
  36. package/dist/backend/llvm/expr-island.js.map +1 -1
  37. package/dist/backend/llvm/expr-primitives.js.map +1 -1
  38. package/dist/backend/llvm/expr-records.js.map +1 -1
  39. package/dist/backend/llvm/expr-stream-bridges.js +220 -9
  40. package/dist/backend/llvm/expr-stream-bridges.js.map +1 -1
  41. package/dist/backend/llvm/lib-dispatch.js +2 -0
  42. package/dist/backend/llvm/lib-dispatch.js.map +1 -1
  43. package/dist/backend/llvm/lib-shared.js +18 -0
  44. package/dist/backend/llvm/lib-shared.js.map +1 -1
  45. package/dist/backend/llvm/lib-stream.js +6 -3
  46. package/dist/backend/llvm/lib-stream.js.map +1 -1
  47. package/dist/backend/llvm/split.js.map +1 -1
  48. package/dist/backend/llvm/unsupported.js.map +1 -1
  49. package/dist/backend/llvm/walkers.js.map +1 -1
  50. package/dist/backend/native-codegen.js.map +1 -1
  51. package/dist/backend/native-codegen.test.js +2 -0
  52. package/dist/backend/native-codegen.test.js.map +1 -1
  53. package/dist/backend/native-toolchain.js.map +1 -1
  54. package/dist/backend/native-toolchain.test.js.map +1 -1
  55. package/dist/backend/runtime-pack.js.map +1 -1
  56. package/dist/backend/targets.js.map +1 -1
  57. package/dist/backend/vendor-archives.js.map +1 -1
  58. package/dist/compat/fetch-profile.js +4 -2
  59. package/dist/compat/fetch-profile.js.map +1 -1
  60. package/dist/coverage/report.js.map +1 -1
  61. package/dist/coverage/surface-manifest.js +12 -0
  62. package/dist/coverage/surface-manifest.js.map +1 -1
  63. package/dist/diagnostics/diagnostic.d.ts +6 -5
  64. package/dist/diagnostics/diagnostic.js +7 -6
  65. package/dist/diagnostics/diagnostic.js.map +1 -1
  66. package/dist/diagnostics/render.js.map +1 -1
  67. package/dist/ffi/ffi-manifest.js.map +1 -1
  68. package/dist/frontend/cjs-lexer.js.map +1 -1
  69. package/dist/frontend/dts-paths.js.map +1 -1
  70. package/dist/frontend/input-tracker.d.ts +10 -0
  71. package/dist/frontend/input-tracker.js +26 -3
  72. package/dist/frontend/input-tracker.js.map +1 -1
  73. package/dist/frontend/input-tracker.test.js +8 -1
  74. package/dist/frontend/input-tracker.test.js.map +1 -1
  75. package/dist/frontend/lib-contract.js.map +1 -1
  76. package/dist/frontend/lowering/array-values.d.ts +4 -0
  77. package/dist/frontend/lowering/array-values.js +18 -2
  78. package/dist/frontend/lowering/array-values.js.map +1 -1
  79. package/dist/frontend/lowering/callback-arg.js.map +1 -1
  80. package/dist/frontend/lowering/containers/bytes.d.ts +35 -0
  81. package/dist/frontend/lowering/containers/bytes.js +1021 -0
  82. package/dist/frontend/lowering/containers/bytes.js.map +1 -0
  83. package/dist/frontend/lowering/containers/string-and-regexp.d.ts +17 -0
  84. package/dist/frontend/lowering/containers/string-and-regexp.js +345 -0
  85. package/dist/frontend/lowering/containers/string-and-regexp.js.map +1 -0
  86. package/dist/frontend/lowering/expressions/evaluation-safety.d.ts +13 -0
  87. package/dist/frontend/lowering/expressions/evaluation-safety.js +76 -0
  88. package/dist/frontend/lowering/expressions/evaluation-safety.js.map +1 -0
  89. package/dist/frontend/lowering/expressions/object-literals.d.ts +44 -0
  90. package/dist/frontend/lowering/expressions/object-literals.js +1815 -0
  91. package/dist/frontend/lowering/expressions/object-literals.js.map +1 -0
  92. package/dist/frontend/lowering/expressions/optional-chains.d.ts +31 -0
  93. package/dist/frontend/lowering/expressions/optional-chains.js +382 -0
  94. package/dist/frontend/lowering/expressions/optional-chains.js.map +1 -0
  95. package/dist/frontend/lowering/expressions/try-lower-expression.d.ts +7 -0
  96. package/dist/frontend/lowering/expressions/try-lower-expression.js +26 -0
  97. package/dist/frontend/lowering/expressions/try-lower-expression.js.map +1 -0
  98. package/dist/frontend/lowering/lib-boundary.js +7 -2
  99. package/dist/frontend/lowering/lib-boundary.js.map +1 -1
  100. package/dist/frontend/lowering/lower-assert.js.map +1 -1
  101. package/dist/frontend/lowering/lower-async-iteration.d.ts +7 -0
  102. package/dist/frontend/lowering/lower-async-iteration.js +657 -0
  103. package/dist/frontend/lowering/lower-async-iteration.js.map +1 -0
  104. package/dist/frontend/lowering/lower-builtins.d.ts +18 -0
  105. package/dist/frontend/lowering/lower-builtins.js +219 -48
  106. package/dist/frontend/lowering/lower-builtins.js.map +1 -1
  107. package/dist/frontend/lowering/lower-calls.d.ts +13 -4
  108. package/dist/frontend/lowering/lower-calls.js +407 -64
  109. package/dist/frontend/lowering/lower-calls.js.map +1 -1
  110. package/dist/frontend/lowering/lower-classes.d.ts +7 -13
  111. package/dist/frontend/lowering/lower-classes.js +128 -35
  112. package/dist/frontend/lowering/lower-classes.js.map +1 -1
  113. package/dist/frontend/lowering/lower-comptime.js.map +1 -1
  114. package/dist/frontend/lowering/lower-containers.d.ts +1 -47
  115. package/dist/frontend/lowering/lower-containers.js +135 -1467
  116. package/dist/frontend/lowering/lower-containers.js.map +1 -1
  117. package/dist/frontend/lowering/lower-event-emitter.js +51 -5
  118. package/dist/frontend/lowering/lower-event-emitter.js.map +1 -1
  119. package/dist/frontend/lowering/lower-exprs.d.ts +0 -78
  120. package/dist/frontend/lowering/lower-exprs.js +402 -2351
  121. package/dist/frontend/lowering/lower-exprs.js.map +1 -1
  122. package/dist/frontend/lowering/lower-generators.d.ts +18 -3
  123. package/dist/frontend/lowering/lower-generators.js +145 -9
  124. package/dist/frontend/lowering/lower-generators.js.map +1 -1
  125. package/dist/frontend/lowering/lower-inspect.js +3 -3
  126. package/dist/frontend/lowering/lower-inspect.js.map +1 -1
  127. package/dist/frontend/lowering/lower-island.d.ts +6 -0
  128. package/dist/frontend/lowering/lower-island.js +37 -5
  129. package/dist/frontend/lowering/lower-island.js.map +1 -1
  130. package/dist/frontend/lowering/lower-modules.js +52 -15
  131. package/dist/frontend/lowering/lower-modules.js.map +1 -1
  132. package/dist/frontend/lowering/lower-node-module.d.ts +18 -0
  133. package/dist/frontend/lowering/lower-node-module.js +302 -0
  134. package/dist/frontend/lowering/lower-node-module.js.map +1 -0
  135. package/dist/frontend/lowering/lower-server.js +1 -1
  136. package/dist/frontend/lowering/lower-server.js.map +1 -1
  137. package/dist/frontend/lowering/lower-stmts.d.ts +5 -24
  138. package/dist/frontend/lowering/lower-stmts.js +519 -253
  139. package/dist/frontend/lowering/lower-stmts.js.map +1 -1
  140. package/dist/frontend/lowering/lower-stream.js +4 -4
  141. package/dist/frontend/lowering/lower-stream.js.map +1 -1
  142. package/dist/frontend/lowering/lowerer.d.ts +37 -34
  143. package/dist/frontend/lowering/lowerer.js +143 -57
  144. package/dist/frontend/lowering/lowerer.js.map +1 -1
  145. package/dist/frontend/lowering/optional-arguments.d.ts +9 -0
  146. package/dist/frontend/lowering/optional-arguments.js +57 -0
  147. package/dist/frontend/lowering/optional-arguments.js.map +1 -0
  148. package/dist/frontend/npm-static-declarations.d.ts +35 -0
  149. package/dist/frontend/npm-static-declarations.js +506 -0
  150. package/dist/frontend/npm-static-declarations.js.map +1 -0
  151. package/dist/frontend/npm-static-declarations.test.d.ts +1 -0
  152. package/dist/frontend/npm-static-declarations.test.js +122 -0
  153. package/dist/frontend/npm-static-declarations.test.js.map +1 -0
  154. package/dist/frontend/npm-static.d.ts +2 -0
  155. package/dist/frontend/npm-static.js +26 -10
  156. package/dist/frontend/npm-static.js.map +1 -1
  157. package/dist/frontend/npm.d.ts +60 -0
  158. package/dist/frontend/npm.js +38 -4
  159. package/dist/frontend/npm.js.map +1 -1
  160. package/dist/frontend/npm.test.d.ts +1 -0
  161. package/dist/frontend/npm.test.js +50 -0
  162. package/dist/frontend/npm.test.js.map +1 -0
  163. package/dist/frontend/program.d.ts +3 -2
  164. package/dist/frontend/program.js +495 -68
  165. package/dist/frontend/program.js.map +1 -1
  166. package/dist/frontend/resolve.d.ts +10 -2
  167. package/dist/frontend/resolve.js +90 -14
  168. package/dist/frontend/resolve.js.map +1 -1
  169. package/dist/frontend/resolve.test.js +4 -1
  170. package/dist/frontend/resolve.test.js.map +1 -1
  171. package/dist/frontend/runtime-resolve.d.ts +22 -0
  172. package/dist/frontend/runtime-resolve.js +101 -0
  173. package/dist/frontend/runtime-resolve.js.map +1 -0
  174. package/dist/frontend/runtime-resolve.test.d.ts +1 -0
  175. package/dist/frontend/runtime-resolve.test.js +18 -0
  176. package/dist/frontend/runtime-resolve.test.js.map +1 -0
  177. package/dist/frontend/ts7/adapter.js +12 -13
  178. package/dist/frontend/ts7/adapter.js.map +1 -1
  179. package/dist/frontend/ts7/ast.js.map +1 -1
  180. package/dist/frontend/ts7/census-check.js +3 -3
  181. package/dist/frontend/ts7/census-check.js.map +1 -1
  182. package/dist/frontend/ts7/checker.d.ts +3 -0
  183. package/dist/frontend/ts7/checker.js +12 -3
  184. package/dist/frontend/ts7/checker.js.map +1 -1
  185. package/dist/frontend/ts7/enums.js.map +1 -1
  186. package/dist/frontend/ts7/program-adapter.js +42 -3
  187. package/dist/frontend/ts7/program-adapter.js.map +1 -1
  188. package/dist/frontend/type-mapper.js +120 -7
  189. package/dist/frontend/type-mapper.js.map +1 -1
  190. package/dist/index.js +5 -5
  191. package/dist/index.js.map +1 -1
  192. package/dist/ir/analysis.js.map +1 -1
  193. package/dist/ir/ir.d.ts +60 -30
  194. package/dist/ir/ir.js +57 -6
  195. package/dist/ir/ir.js.map +1 -1
  196. package/dist/ir/validate.js +44 -59
  197. package/dist/ir/validate.js.map +1 -1
  198. package/dist/library/cache-primitives.js.map +1 -1
  199. package/dist/library/cache-reset.test.js.map +1 -1
  200. package/dist/library/compiler-self-identity.js.map +1 -1
  201. package/dist/library/int-infer.js.map +1 -1
  202. package/dist/library/int-infer.test.js.map +1 -1
  203. package/dist/library/library-profile.js.map +1 -1
  204. package/dist/library/sidecar-validate.js.map +1 -1
  205. package/dist/library/sidecar.js.map +1 -1
  206. package/dist/startup-cache.js.map +1 -1
  207. package/dist/wasi-paths.js.map +1 -1
  208. package/package.json +18 -18
  209. package/surface-manifest.json +60 -4
@@ -0,0 +1,9 @@
1
+ import * as ts from "../ts7/adapter.js";
2
+ import type { IrExpr, IrType } from "../../ir/ir.js";
3
+ import type { Lowerer } from "./lowerer.js";
4
+ /** Lower an expression whose checker type is statically `undefined`/`void`. */
5
+ export declare function lowerStaticallyUndefinedArgument(lowerer: Lowerer, node: ts.Expression): IrExpr | null;
6
+ /** Preserve an explicitly undefined argument's effects, then use its default. */
7
+ export declare function defaultAfterUndefined(value: IrExpr, defaultValue: IrExpr): IrExpr;
8
+ /** Lower an optional argument, applying its default only to the undefined arm. */
9
+ export declare function lowerOptionalArgument(lowerer: Lowerer, node: ts.Expression, expected: IrType, defaultValue: IrExpr): IrExpr;
@@ -0,0 +1,57 @@
1
+ import * as ts from "../ts7/adapter.js";
2
+ import { typeEquals } from "../../ir/ir.js";
3
+ import { isSafeToDiscard } from "./expressions/evaluation-safety.js";
4
+ /** Lower an expression whose checker type is statically `undefined`/`void`. */
5
+ export function lowerStaticallyUndefinedArgument(lowerer, node) {
6
+ const peelErasableWrappers = (value) => {
7
+ let expr = value;
8
+ while (ts.isParenthesizedExpression(expr) ||
9
+ ts.isAsExpression(expr) ||
10
+ ts.isTypeAssertion(expr) ||
11
+ ts.isSatisfiesExpression(expr)) {
12
+ expr = expr.expression;
13
+ }
14
+ return expr;
15
+ };
16
+ let expr = node;
17
+ while (ts.isParenthesizedExpression(expr))
18
+ expr = expr.expression;
19
+ if ((lowerer.typeOf(expr).flags & (ts.TypeFlags.Undefined | ts.TypeFlags.Void)) === 0)
20
+ return null;
21
+ expr = peelErasableWrappers(expr);
22
+ let sawVoid = false;
23
+ while (ts.isVoidExpression(expr)) {
24
+ sawVoid = true;
25
+ expr = peelErasableWrappers(expr.expression);
26
+ }
27
+ return sawVoid ? lowerer.lowerExpr(expr) : lowerer.lowerExpr(node);
28
+ }
29
+ /** Preserve an explicitly undefined argument's effects, then use its default. */
30
+ export function defaultAfterUndefined(value, defaultValue) {
31
+ if (isSafeToDiscard(value))
32
+ return defaultValue;
33
+ return {
34
+ kind: "seqExpr",
35
+ stmts: [{ kind: "exprStmt", expr: value, loc: value.loc }],
36
+ result: defaultValue,
37
+ type: defaultValue.type,
38
+ loc: value.loc,
39
+ };
40
+ }
41
+ /** Lower an optional argument, applying its default only to the undefined arm. */
42
+ export function lowerOptionalArgument(lowerer, node, expected, defaultValue) {
43
+ const undefinedArg = lowerStaticallyUndefinedArgument(lowerer, node);
44
+ if (undefinedArg)
45
+ return defaultAfterUndefined(undefinedArg, defaultValue);
46
+ const value = lowerer.lowerExpr(node);
47
+ if (value.type.kind === "union") {
48
+ const def = lowerer.unions.get(value.type.unionId);
49
+ if (def?.arms.length === 2 &&
50
+ def.arms.some((arm) => arm.kind === "undefinedT") &&
51
+ def.arms.some((arm) => typeEquals(arm, expected))) {
52
+ return { kind: "nullish", left: value, right: defaultValue, type: expected, loc: value.loc };
53
+ }
54
+ }
55
+ return lowerer.coerceInto(node, value, expected);
56
+ }
57
+ //# sourceMappingURL=optional-arguments.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"optional-arguments.js","sourceRoot":"","sources":["../../../src/frontend/lowering/optional-arguments.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,mBAAmB,CAAC;AAExC,OAAO,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AAE5C,OAAO,EAAE,eAAe,EAAE,MAAM,oCAAoC,CAAC;AAErE,+EAA+E;AAC/E,MAAM,UAAU,gCAAgC,CAAC,OAAgB,EAAE,IAAmB;IACpF,MAAM,oBAAoB,GAAG,CAAC,KAAoB,EAAiB,EAAE;QACnE,IAAI,IAAI,GAAG,KAAK,CAAC;QACjB,OACE,EAAE,CAAC,yBAAyB,CAAC,IAAI,CAAC;YAClC,EAAE,CAAC,cAAc,CAAC,IAAI,CAAC;YACvB,EAAE,CAAC,eAAe,CAAC,IAAI,CAAC;YACxB,EAAE,CAAC,qBAAqB,CAAC,IAAI,CAAC,EAC9B,CAAC;YACD,IAAI,GAAG,IAAI,CAAC,UAAU,CAAC;QACzB,CAAC;QACD,OAAO,IAAI,CAAC;IACd,CAAC,CAAC;IACF,IAAI,IAAI,GAAG,IAAI,CAAC;IAChB,OAAO,EAAE,CAAC,yBAAyB,CAAC,IAAI,CAAC;QAAE,IAAI,GAAG,IAAI,CAAC,UAAU,CAAC;IAClE,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,KAAK,GAAG,CAAC,EAAE,CAAC,SAAS,CAAC,SAAS,GAAG,EAAE,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,KAAK,CAAC;QAAE,OAAO,IAAI,CAAC;IACnG,IAAI,GAAG,oBAAoB,CAAC,IAAI,CAAC,CAAC;IAClC,IAAI,OAAO,GAAG,KAAK,CAAC;IACpB,OAAO,EAAE,CAAC,gBAAgB,CAAC,IAAI,CAAC,EAAE,CAAC;QACjC,OAAO,GAAG,IAAI,CAAC;QACf,IAAI,GAAG,oBAAoB,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;IAC/C,CAAC;IACD,OAAO,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC;AACrE,CAAC;AAED,iFAAiF;AACjF,MAAM,UAAU,qBAAqB,CAAC,KAAa,EAAE,YAAoB;IACvE,IAAI,eAAe,CAAC,KAAK,CAAC;QAAE,OAAO,YAAY,CAAC;IAChD,OAAO;QACL,IAAI,EAAE,SAAS;QACf,KAAK,EAAE,CAAC,EAAE,IAAI,EAAE,UAAU,EAAE,IAAI,EAAE,KAAK,EAAE,GAAG,EAAE,KAAK,CAAC,GAAG,EAAE,CAAC;QAC1D,MAAM,EAAE,YAAY;QACpB,IAAI,EAAE,YAAY,CAAC,IAAI;QACvB,GAAG,EAAE,KAAK,CAAC,GAAG;KACf,CAAC;AACJ,CAAC;AAED,kFAAkF;AAClF,MAAM,UAAU,qBAAqB,CACnC,OAAgB,EAChB,IAAmB,EACnB,QAAgB,EAChB,YAAoB;IAEpB,MAAM,YAAY,GAAG,gCAAgC,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC;IACrE,IAAI,YAAY;QAAE,OAAO,qBAAqB,CAAC,YAAY,EAAE,YAAY,CAAC,CAAC;IAC3E,MAAM,KAAK,GAAG,OAAO,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC;IACtC,IAAI,KAAK,CAAC,IAAI,CAAC,IAAI,KAAK,OAAO,EAAE,CAAC;QAChC,MAAM,GAAG,GAAG,OAAO,CAAC,MAAM,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QACnD,IACE,GAAG,EAAE,IAAI,CAAC,MAAM,KAAK,CAAC;YACtB,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,IAAI,KAAK,YAAY,CAAC;YACjD,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,UAAU,CAAC,GAAG,EAAE,QAAQ,CAAC,CAAC,EACjD,CAAC;YACD,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,KAAK,EAAE,YAAY,EAAE,IAAI,EAAE,QAAQ,EAAE,GAAG,EAAE,KAAK,CAAC,GAAG,EAAE,CAAC;QAC/F,CAAC;IACH,CAAC;IACD,OAAO,OAAO,CAAC,UAAU,CAAC,IAAI,EAAE,KAAK,EAAE,QAAQ,CAAC,CAAC;AACnD,CAAC"}
@@ -0,0 +1,35 @@
1
+ export interface NpmStaticOverloadParameter {
2
+ name: string;
3
+ type: string;
4
+ optional: boolean;
5
+ }
6
+ export interface NpmStaticOverloadSignature {
7
+ parameters: readonly NpmStaticOverloadParameter[];
8
+ returnType: string;
9
+ }
10
+ export type NpmStaticDeclarationOverloads = ReadonlyMap<string, ReadonlyMap<string, readonly NpmStaticOverloadSignature[]>>;
11
+ export type NpmStaticDeclarationProperties = ReadonlyMap<string, ReadonlyMap<string, string>>;
12
+ export interface NpmStaticOverloadRewrite {
13
+ text: string;
14
+ insertions: readonly {
15
+ offset: number;
16
+ length: number;
17
+ }[];
18
+ }
19
+ /** Extracts complete safe overload groups from exported non-generic classes. */
20
+ export declare function parseNpmStaticDeclarationOverloads(declarationPath: string, source: string): NpmStaticDeclarationOverloads;
21
+ /** Extracts the first declaration-backed field slice: nullable self links. */
22
+ export declare function parseNpmStaticDeclarationProperties(declarationPath: string, source: string): NpmStaticDeclarationProperties;
23
+ /** Relative declaration-barrel edges whose target stays subject to the
24
+ * caller's package-bounded resolution. Bare type dependencies deliberately
25
+ * do not inherit the opted package's declaration trust. */
26
+ export declare function npmStaticDeclarationReexports(declarationPath: string, source: string): readonly string[];
27
+ /** Maps declaration class names to their implementation edge from one
28
+ * runtime package entry. Null means the class is declared in the entry;
29
+ * a string is a relative re-export target. Multi-hop and aliased class
30
+ * re-exports stay out of the first safe slice. */
31
+ export declare function npmStaticRuntimeClassTargets(sourcePath: string, source: string, classNames: ReadonlySet<string>): ReadonlyMap<string, string | null>;
32
+ /** Injects declaration overload JSDoc into matching exported JS classes. */
33
+ export declare function applyNpmStaticDeclarationOverloads(sourcePath: string, source: string, declarations: NpmStaticDeclarationOverloads): NpmStaticOverloadRewrite | null;
34
+ /** Injects nullable-self property JSDoc at matching constructor writes. */
35
+ export declare function applyNpmStaticDeclarationProperties(sourcePath: string, source: string, declarations: NpmStaticDeclarationProperties): NpmStaticOverloadRewrite | null;
@@ -0,0 +1,506 @@
1
+ /* Declaration-overload projection for --npm-static. The runtime program
2
+ * still resolves to and compiles package JavaScript, but an authored .d.ts
3
+ * can carry overloads inference cannot reproduce (the common getter/setter
4
+ * shape `name(): string` / `name(value): this`). This string-bounded
5
+ * TypeScript 5 parser island extracts only complete, representation-safe
6
+ * groups and respells them as JSDoc immediately before the matching
7
+ * exported JavaScript class method. TypeScript 7 then checks and lowers one
8
+ * world: implementation bodies remain the runtime truth, while overload
9
+ * calls get the package author's more precise signature. */
10
+ import ts from "typescript5";
11
+ const SAFE_KEYWORD_TYPES = new Set([
12
+ ts.SyntaxKind.BooleanKeyword,
13
+ ts.SyntaxKind.NeverKeyword,
14
+ ts.SyntaxKind.NullKeyword,
15
+ ts.SyntaxKind.NumberKeyword,
16
+ ts.SyntaxKind.StringKeyword,
17
+ ts.SyntaxKind.UndefinedKeyword,
18
+ ts.SyntaxKind.VoidKeyword,
19
+ ]);
20
+ function hasModifier(node, kind) {
21
+ return ts.canHaveModifiers(node) && (ts.getModifiers(node) ?? []).some((modifier) => modifier.kind === kind);
22
+ }
23
+ function safeTypeText(node, sourceFile, className) {
24
+ if (SAFE_KEYWORD_TYPES.has(node.kind) || ts.isThisTypeNode(node))
25
+ return node.getText(sourceFile);
26
+ if (ts.isLiteralTypeNode(node) && node.literal.kind === ts.SyntaxKind.NullKeyword)
27
+ return "null";
28
+ if (ts.isParenthesizedTypeNode(node)) {
29
+ const inner = safeTypeText(node.type, sourceFile, className);
30
+ return inner === null ? null : `(${inner})`;
31
+ }
32
+ if (ts.isArrayTypeNode(node)) {
33
+ const element = safeTypeText(node.elementType, sourceFile, className);
34
+ return element === null ? null : `${element}[]`;
35
+ }
36
+ if (ts.isTypeOperatorNode(node) && node.operator === ts.SyntaxKind.ReadonlyKeyword) {
37
+ return safeTypeText(node.type, sourceFile, className);
38
+ }
39
+ if (ts.isUnionTypeNode(node)) {
40
+ const arms = node.types.map((type) => safeTypeText(type, sourceFile, className));
41
+ return arms.some((arm) => arm === null) ? null : arms.join(" | ");
42
+ }
43
+ return ts.isTypeReferenceNode(node) &&
44
+ ts.isIdentifier(node.typeName) &&
45
+ node.typeName.text === className &&
46
+ (node.typeArguments?.length ?? 0) === 0
47
+ ? className
48
+ : null;
49
+ }
50
+ function overloadSignature(sourceFile, className, method) {
51
+ if (!ts.isIdentifier(method.name) ||
52
+ method.type === undefined ||
53
+ (method.typeParameters?.length ?? 0) !== 0 ||
54
+ hasModifier(method, ts.SyntaxKind.StaticKeyword) ||
55
+ hasModifier(method, ts.SyntaxKind.PrivateKeyword) ||
56
+ hasModifier(method, ts.SyntaxKind.ProtectedKeyword)) {
57
+ return null;
58
+ }
59
+ const returnType = safeTypeText(method.type, sourceFile, className);
60
+ if (returnType === null)
61
+ return null;
62
+ const parameters = [];
63
+ for (const parameter of method.parameters) {
64
+ if (!ts.isIdentifier(parameter.name) ||
65
+ parameter.name.text === "this" ||
66
+ parameter.type === undefined ||
67
+ parameter.initializer !== undefined ||
68
+ parameter.dotDotDotToken !== undefined) {
69
+ return null;
70
+ }
71
+ const type = safeTypeText(parameter.type, sourceFile, className);
72
+ if (type === null)
73
+ return null;
74
+ parameters.push({
75
+ name: parameter.name.text,
76
+ type,
77
+ optional: parameter.questionToken !== undefined,
78
+ });
79
+ }
80
+ return { parameters, returnType };
81
+ }
82
+ /** Extracts complete safe overload groups from exported non-generic classes. */
83
+ export function parseNpmStaticDeclarationOverloads(declarationPath, source) {
84
+ const sourceFile = ts.createSourceFile(declarationPath, source, ts.ScriptTarget.Latest, true, ts.ScriptKind.TS);
85
+ const classes = new Map();
86
+ for (const statement of sourceFile.statements) {
87
+ if (!ts.isClassDeclaration(statement) ||
88
+ statement.name === undefined ||
89
+ (statement.typeParameters?.length ?? 0) !== 0 ||
90
+ !hasModifier(statement, ts.SyntaxKind.ExportKeyword) ||
91
+ hasModifier(statement, ts.SyntaxKind.DefaultKeyword)) {
92
+ continue;
93
+ }
94
+ const className = statement.name.text;
95
+ const groups = new Map();
96
+ for (const member of statement.members) {
97
+ if (!ts.isMethodDeclaration(member) || !ts.isIdentifier(member.name))
98
+ continue;
99
+ const group = groups.get(member.name.text) ?? [];
100
+ group.push(member);
101
+ groups.set(member.name.text, group);
102
+ }
103
+ const overloads = new Map();
104
+ for (const [name, methods] of groups) {
105
+ const signatures = methods.map((method) => overloadSignature(sourceFile, className, method));
106
+ // A partial set could select the wrong branch. Keep inference when
107
+ // any authored signature is outside the projection's safe grammar.
108
+ if (signatures.some((signature) => signature === null))
109
+ continue;
110
+ if (signatures.length === 1 && !signatures[0].parameters.some((parameter) => parameter.optional))
111
+ continue;
112
+ overloads.set(name, signatures);
113
+ }
114
+ if (overloads.size > 0)
115
+ classes.set(className, overloads);
116
+ }
117
+ return classes;
118
+ }
119
+ function nullableSelfType(node, sourceFile, className) {
120
+ if (!ts.isUnionTypeNode(node) || node.types.length !== 2)
121
+ return null;
122
+ const arms = node.types.map((type) => safeTypeText(type, sourceFile, className));
123
+ return arms.includes(className) && arms.includes("null") ? `${className} | null` : null;
124
+ }
125
+ /** Extracts the first declaration-backed field slice: nullable self links. */
126
+ export function parseNpmStaticDeclarationProperties(declarationPath, source) {
127
+ const sourceFile = ts.createSourceFile(declarationPath, source, ts.ScriptTarget.Latest, true, ts.ScriptKind.TS);
128
+ const classes = new Map();
129
+ for (const statement of sourceFile.statements) {
130
+ if (!ts.isClassDeclaration(statement) ||
131
+ statement.name === undefined ||
132
+ (statement.typeParameters?.length ?? 0) !== 0 ||
133
+ !hasModifier(statement, ts.SyntaxKind.ExportKeyword) ||
134
+ hasModifier(statement, ts.SyntaxKind.DefaultKeyword)) {
135
+ continue;
136
+ }
137
+ const className = statement.name.text;
138
+ const properties = new Map();
139
+ for (const member of statement.members) {
140
+ if (!ts.isPropertyDeclaration(member) ||
141
+ !ts.isIdentifier(member.name) ||
142
+ member.type === undefined ||
143
+ member.questionToken !== undefined ||
144
+ hasModifier(member, ts.SyntaxKind.StaticKeyword) ||
145
+ hasModifier(member, ts.SyntaxKind.PrivateKeyword) ||
146
+ hasModifier(member, ts.SyntaxKind.ProtectedKeyword)) {
147
+ continue;
148
+ }
149
+ const type = nullableSelfType(member.type, sourceFile, className);
150
+ if (type !== null)
151
+ properties.set(member.name.text, type);
152
+ }
153
+ if (properties.size > 0)
154
+ classes.set(className, properties);
155
+ }
156
+ return classes;
157
+ }
158
+ /** Relative declaration-barrel edges whose target stays subject to the
159
+ * caller's package-bounded resolution. Bare type dependencies deliberately
160
+ * do not inherit the opted package's declaration trust. */
161
+ export function npmStaticDeclarationReexports(declarationPath, source) {
162
+ const sourceFile = ts.createSourceFile(declarationPath, source, ts.ScriptTarget.Latest, true, ts.ScriptKind.TS);
163
+ return sourceFile.statements.flatMap((statement) => ts.isExportDeclaration(statement) &&
164
+ statement.moduleSpecifier !== undefined &&
165
+ ts.isStringLiteral(statement.moduleSpecifier) &&
166
+ statement.moduleSpecifier.text.startsWith(".")
167
+ ? [statement.moduleSpecifier.text]
168
+ : []);
169
+ }
170
+ function requireSpecifier(expression) {
171
+ const argument = expression !== undefined && ts.isCallExpression(expression) ? expression.arguments[0] : undefined;
172
+ return expression !== undefined &&
173
+ ts.isCallExpression(expression) &&
174
+ ts.isIdentifier(expression.expression) &&
175
+ expression.expression.text === "require" &&
176
+ expression.arguments.length === 1 &&
177
+ argument !== undefined &&
178
+ ts.isStringLiteralLike(argument)
179
+ ? argument.text
180
+ : null;
181
+ }
182
+ /** Maps declaration class names to their implementation edge from one
183
+ * runtime package entry. Null means the class is declared in the entry;
184
+ * a string is a relative re-export target. Multi-hop and aliased class
185
+ * re-exports stay out of the first safe slice. */
186
+ export function npmStaticRuntimeClassTargets(sourcePath, source, classNames) {
187
+ const sourceFile = ts.createSourceFile(sourcePath, source, ts.ScriptTarget.Latest, true, ts.ScriptKind.JS);
188
+ const localClasses = new Set(sourceFile.statements.flatMap((statement) => ts.isClassDeclaration(statement) && statement.name !== undefined ? [statement.name.text] : []));
189
+ const required = new Map();
190
+ for (const statement of sourceFile.statements) {
191
+ if (!ts.isVariableStatement(statement))
192
+ continue;
193
+ for (const declaration of statement.declarationList.declarations) {
194
+ const specifier = requireSpecifier(declaration.initializer);
195
+ if (specifier === null || !specifier.startsWith(".") || !ts.isObjectBindingPattern(declaration.name))
196
+ continue;
197
+ for (const element of declaration.name.elements) {
198
+ if (element.dotDotDotToken !== undefined || !ts.isIdentifier(element.name))
199
+ continue;
200
+ const imported = element.propertyName !== undefined && ts.isIdentifier(element.propertyName)
201
+ ? element.propertyName.text
202
+ : element.name.text;
203
+ required.set(element.name.text, { imported, specifier });
204
+ }
205
+ }
206
+ }
207
+ const targets = new Map();
208
+ const record = (exported, local, specifier) => {
209
+ if (!classNames.has(exported) || exported !== local || targets.has(exported))
210
+ return;
211
+ if (specifier !== undefined) {
212
+ targets.set(exported, specifier);
213
+ return;
214
+ }
215
+ const imported = required.get(local);
216
+ if (imported !== undefined && imported.imported === exported)
217
+ targets.set(exported, imported.specifier);
218
+ else if (localClasses.has(local))
219
+ targets.set(exported, null);
220
+ };
221
+ for (const statement of sourceFile.statements) {
222
+ if (ts.isClassDeclaration(statement) &&
223
+ statement.name !== undefined &&
224
+ hasModifier(statement, ts.SyntaxKind.ExportKeyword)) {
225
+ record(statement.name.text, statement.name.text);
226
+ continue;
227
+ }
228
+ if (ts.isExportDeclaration(statement) && statement.exportClause !== undefined && ts.isNamedExports(statement.exportClause)) {
229
+ const specifier = statement.moduleSpecifier !== undefined && ts.isStringLiteral(statement.moduleSpecifier)
230
+ ? statement.moduleSpecifier.text
231
+ : undefined;
232
+ if (specifier !== undefined && !specifier.startsWith("."))
233
+ continue;
234
+ for (const element of statement.exportClause.elements) {
235
+ record(element.name.text, element.propertyName?.text ?? element.name.text, specifier);
236
+ }
237
+ continue;
238
+ }
239
+ if (!ts.isExpressionStatement(statement) || !ts.isBinaryExpression(statement.expression))
240
+ continue;
241
+ const { left, right, operatorToken } = statement.expression;
242
+ if (operatorToken.kind !== ts.SyntaxKind.EqualsToken)
243
+ continue;
244
+ if (ts.isPropertyAccessExpression(left) &&
245
+ ts.isIdentifier(right) &&
246
+ ((ts.isIdentifier(left.expression) && left.expression.text === "exports") ||
247
+ (ts.isPropertyAccessExpression(left.expression) &&
248
+ ts.isIdentifier(left.expression.expression) &&
249
+ left.expression.expression.text === "module" &&
250
+ left.expression.name.text === "exports"))) {
251
+ record(left.name.text, right.text);
252
+ continue;
253
+ }
254
+ if (ts.isPropertyAccessExpression(left) &&
255
+ ts.isIdentifier(left.expression) &&
256
+ left.expression.text === "module" &&
257
+ left.name.text === "exports" &&
258
+ ts.isObjectLiteralExpression(right)) {
259
+ for (const property of right.properties) {
260
+ if (ts.isShorthandPropertyAssignment(property))
261
+ record(property.name.text, property.name.text);
262
+ else if (ts.isPropertyAssignment(property) &&
263
+ ts.isIdentifier(property.name) &&
264
+ ts.isIdentifier(property.initializer)) {
265
+ record(property.name.text, property.initializer.text);
266
+ }
267
+ }
268
+ }
269
+ }
270
+ return targets;
271
+ }
272
+ function exportedClassNames(sourceFile) {
273
+ const names = new Set();
274
+ for (const statement of sourceFile.statements) {
275
+ if (ts.isClassDeclaration(statement) &&
276
+ statement.name !== undefined &&
277
+ hasModifier(statement, ts.SyntaxKind.ExportKeyword)) {
278
+ names.add(statement.name.text);
279
+ continue;
280
+ }
281
+ if (ts.isExportDeclaration(statement) && statement.exportClause !== undefined && ts.isNamedExports(statement.exportClause)) {
282
+ for (const element of statement.exportClause.elements)
283
+ names.add(element.propertyName?.text ?? element.name.text);
284
+ continue;
285
+ }
286
+ if (!ts.isExpressionStatement(statement) || !ts.isBinaryExpression(statement.expression))
287
+ continue;
288
+ const { left, right, operatorToken } = statement.expression;
289
+ if (operatorToken.kind !== ts.SyntaxKind.EqualsToken)
290
+ continue;
291
+ if (ts.isPropertyAccessExpression(left) &&
292
+ ts.isIdentifier(right) &&
293
+ ((ts.isIdentifier(left.expression) && left.expression.text === "exports") ||
294
+ (ts.isPropertyAccessExpression(left.expression) &&
295
+ ts.isIdentifier(left.expression.expression) &&
296
+ left.expression.expression.text === "module" &&
297
+ left.expression.name.text === "exports")) &&
298
+ left.name.text === right.text) {
299
+ names.add(right.text);
300
+ continue;
301
+ }
302
+ if (ts.isPropertyAccessExpression(left) &&
303
+ ts.isIdentifier(left.expression) &&
304
+ left.expression.text === "module" &&
305
+ left.name.text === "exports" &&
306
+ ts.isObjectLiteralExpression(right)) {
307
+ for (const property of right.properties) {
308
+ if (ts.isShorthandPropertyAssignment(property))
309
+ names.add(property.name.text);
310
+ else if (ts.isPropertyAssignment(property) &&
311
+ ts.isIdentifier(property.name) &&
312
+ ts.isIdentifier(property.initializer) &&
313
+ property.name.text === property.initializer.text) {
314
+ names.add(property.name.text);
315
+ }
316
+ }
317
+ }
318
+ }
319
+ return names;
320
+ }
321
+ function overloadComment(signature) {
322
+ const params = signature.parameters.map((parameter) => `@param {${parameter.type}} ${parameter.optional ? `[${parameter.name}]` : parameter.name}`);
323
+ return `/** @overload ${params.join(" ")} @returns {${signature.returnType}} */`;
324
+ }
325
+ function implementationComment(className, method, signatures) {
326
+ if (method.parameters.some((parameter) => !ts.isIdentifier(parameter.name) || parameter.dotDotDotToken !== undefined))
327
+ return null;
328
+ const maxParams = Math.max(...signatures.map((signature) => signature.parameters.length));
329
+ if (method.parameters.length !== maxParams)
330
+ return null;
331
+ const params = [];
332
+ for (let index = 0; index < maxParams; index++) {
333
+ const types = [...new Set(signatures.flatMap((signature) => signature.parameters[index]?.type ?? []))];
334
+ if (types.length === 0)
335
+ return null;
336
+ const parameter = method.parameters[index];
337
+ if (parameter === undefined || !ts.isIdentifier(parameter.name))
338
+ return null;
339
+ const name = parameter.name.text;
340
+ const optional = signatures.some((signature) => {
341
+ const candidate = signature.parameters[index];
342
+ return candidate === undefined || candidate.optional;
343
+ });
344
+ params.push(`@param {${types.join(" | ")}} ${optional ? `[${name}]` : name}`);
345
+ }
346
+ const returns = [...new Set(signatures.map((signature) => signature.returnType.replace(/\bthis\b/g, className)))];
347
+ return `/** ${params.join(" ")} @returns {${returns.join(" | ")}} */`;
348
+ }
349
+ function directReturn(statement) {
350
+ if (ts.isReturnStatement(statement))
351
+ return statement;
352
+ return ts.isBlock(statement) && statement.statements.length === 1 && ts.isReturnStatement(statement.statements[0])
353
+ ? statement.statements[0]
354
+ : null;
355
+ }
356
+ function undefinedParameterTest(expression, parameter) {
357
+ if (!ts.isBinaryExpression(expression) || expression.operatorToken.kind !== ts.SyntaxKind.EqualsEqualsEqualsToken)
358
+ return false;
359
+ const matches = (left, right) => ts.isIdentifier(left) && left.text === parameter && ts.isIdentifier(right) && right.text === "undefined";
360
+ return matches(expression.left, expression.right) || matches(expression.right, expression.left);
361
+ }
362
+ function overloadArrayBackingField(method, signatures) {
363
+ if (method.body === undefined || method.parameters.length !== 1 || !ts.isIdentifier(method.parameters[0].name))
364
+ return null;
365
+ const getters = signatures.filter((signature) => signature.parameters.length === 0 && signature.returnType.endsWith("[]"));
366
+ if (getters.length !== 1)
367
+ return null;
368
+ const parameter = method.parameters[0].name.text;
369
+ for (const statement of method.body.statements) {
370
+ if (!ts.isIfStatement(statement) || !undefinedParameterTest(statement.expression, parameter))
371
+ continue;
372
+ const returned = directReturn(statement.thenStatement);
373
+ const expression = returned?.expression;
374
+ if (expression !== undefined &&
375
+ ts.isPropertyAccessExpression(expression) &&
376
+ expression.expression.kind === ts.SyntaxKind.ThisKeyword) {
377
+ return { field: expression.name.text, type: getters[0].returnType };
378
+ }
379
+ }
380
+ return null;
381
+ }
382
+ /** Injects declaration overload JSDoc into matching exported JS classes. */
383
+ export function applyNpmStaticDeclarationOverloads(sourcePath, source, declarations) {
384
+ if (declarations.size === 0)
385
+ return null;
386
+ const sourceFile = ts.createSourceFile(sourcePath, source, ts.ScriptTarget.Latest, true, ts.ScriptKind.JS);
387
+ const exported = exportedClassNames(sourceFile);
388
+ const inserts = [];
389
+ for (const statement of sourceFile.statements) {
390
+ if (!ts.isClassDeclaration(statement) || statement.name === undefined || !exported.has(statement.name.text))
391
+ continue;
392
+ const classOverloads = declarations.get(statement.name.text);
393
+ if (classOverloads === undefined)
394
+ continue;
395
+ const constructor = statement.members.find((member) => ts.isConstructorDeclaration(member) && member.body !== undefined);
396
+ const projectedFields = new Set();
397
+ for (const member of statement.members) {
398
+ if (!ts.isMethodDeclaration(member) || !ts.isIdentifier(member.name) || member.body === undefined)
399
+ continue;
400
+ const signatures = classOverloads.get(member.name.text);
401
+ if (signatures === undefined)
402
+ continue;
403
+ const backing = overloadArrayBackingField(member, signatures);
404
+ if (backing !== null && constructor?.body !== undefined && !projectedFields.has(backing.field)) {
405
+ for (const bodyStatement of constructor.body.statements) {
406
+ if (!ts.isExpressionStatement(bodyStatement) || !ts.isBinaryExpression(bodyStatement.expression))
407
+ continue;
408
+ const { left, right, operatorToken } = bodyStatement.expression;
409
+ if (operatorToken.kind !== ts.SyntaxKind.EqualsToken ||
410
+ !ts.isArrayLiteralExpression(right) || right.elements.length !== 0 ||
411
+ !ts.isPropertyAccessExpression(left) ||
412
+ left.expression.kind !== ts.SyntaxKind.ThisKeyword ||
413
+ left.name.text !== backing.field) {
414
+ continue;
415
+ }
416
+ const leading = source.slice(bodyStatement.getFullStart(), bodyStatement.getStart(sourceFile));
417
+ if (!leading.includes("@type")) {
418
+ inserts.push({ offset: bodyStatement.getStart(sourceFile), text: `/** @type {${backing.type}} */ ` });
419
+ }
420
+ projectedFields.add(backing.field);
421
+ break;
422
+ }
423
+ }
424
+ const jsDocs = member.jsDoc ?? [];
425
+ if (jsDocs.some((doc) => source.slice(doc.pos, doc.end).includes("@overload")))
426
+ continue;
427
+ if (signatures.length === 1) {
428
+ const implementation = implementationComment(statement.name.text, member, signatures);
429
+ if (implementation !== null) {
430
+ const existing = jsDocs.map((doc) => source.slice(doc.pos, doc.end)).join("\n");
431
+ const missingOptional = signatures[0].parameters.some((parameter) => parameter.optional && !existing.includes(`[${parameter.name}]`));
432
+ if (missingOptional)
433
+ inserts.push({ offset: member.getStart(sourceFile), text: `${implementation} ` });
434
+ }
435
+ continue;
436
+ }
437
+ const implementation = jsDocs.length === 0 ? implementationComment(statement.name.text, member, signatures) : null;
438
+ if (jsDocs.length === 0 && implementation === null)
439
+ continue;
440
+ const offset = jsDocs[0]?.getStart(sourceFile) ?? member.getStart(sourceFile);
441
+ const text = `${signatures.map(overloadComment).join(" ")} ${implementation === null ? "" : implementation + " "}`;
442
+ inserts.push({ offset, text });
443
+ }
444
+ }
445
+ if (inserts.length === 0)
446
+ return null;
447
+ let text = source;
448
+ for (const insert of [...inserts].sort((a, b) => b.offset - a.offset)) {
449
+ text = text.slice(0, insert.offset) + insert.text + text.slice(insert.offset);
450
+ }
451
+ return {
452
+ text,
453
+ insertions: inserts
454
+ .sort((a, b) => a.offset - b.offset)
455
+ .map((insert) => ({ offset: insert.offset, length: insert.text.length })),
456
+ };
457
+ }
458
+ /** Injects nullable-self property JSDoc at matching constructor writes. */
459
+ export function applyNpmStaticDeclarationProperties(sourcePath, source, declarations) {
460
+ if (declarations.size === 0)
461
+ return null;
462
+ const sourceFile = ts.createSourceFile(sourcePath, source, ts.ScriptTarget.Latest, true, ts.ScriptKind.JS);
463
+ const exported = exportedClassNames(sourceFile);
464
+ const inserts = [];
465
+ for (const statement of sourceFile.statements) {
466
+ if (!ts.isClassDeclaration(statement) || statement.name === undefined || !exported.has(statement.name.text))
467
+ continue;
468
+ const properties = declarations.get(statement.name.text);
469
+ if (properties === undefined)
470
+ continue;
471
+ const constructor = statement.members.find((member) => ts.isConstructorDeclaration(member) && member.body !== undefined);
472
+ if (constructor?.body === undefined)
473
+ continue;
474
+ for (const bodyStatement of constructor.body.statements) {
475
+ if (!ts.isExpressionStatement(bodyStatement) || !ts.isBinaryExpression(bodyStatement.expression))
476
+ continue;
477
+ const { left, right, operatorToken } = bodyStatement.expression;
478
+ if (operatorToken.kind !== ts.SyntaxKind.EqualsToken ||
479
+ right.kind !== ts.SyntaxKind.NullKeyword ||
480
+ !ts.isPropertyAccessExpression(left) ||
481
+ left.expression.kind !== ts.SyntaxKind.ThisKeyword) {
482
+ continue;
483
+ }
484
+ const type = properties.get(left.name.text);
485
+ if (type === undefined)
486
+ continue;
487
+ const leading = source.slice(bodyStatement.getFullStart(), bodyStatement.getStart(sourceFile));
488
+ if (leading.includes("@type"))
489
+ continue;
490
+ inserts.push({ offset: bodyStatement.getStart(sourceFile), text: `/** @type {${type}} */ ` });
491
+ }
492
+ }
493
+ if (inserts.length === 0)
494
+ return null;
495
+ let text = source;
496
+ for (const insert of [...inserts].sort((a, b) => b.offset - a.offset)) {
497
+ text = text.slice(0, insert.offset) + insert.text + text.slice(insert.offset);
498
+ }
499
+ return {
500
+ text,
501
+ insertions: inserts
502
+ .sort((a, b) => a.offset - b.offset)
503
+ .map((insert) => ({ offset: insert.offset, length: insert.text.length })),
504
+ };
505
+ }
506
+ //# sourceMappingURL=npm-static-declarations.js.map