@typecad/cuttlefish 0.1.0-alpha.1

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 (377) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +79 -0
  3. package/dist/api/board-types.d.ts +1 -0
  4. package/dist/api/board-types.js +4 -0
  5. package/dist/api/capabilities.d.ts +12 -0
  6. package/dist/api/capabilities.js +1 -0
  7. package/dist/api/config.d.ts +120 -0
  8. package/dist/api/config.js +7 -0
  9. package/dist/api/index.d.ts +5 -0
  10. package/dist/api/index.js +2 -0
  11. package/dist/api/schema/builder.d.ts +14 -0
  12. package/dist/api/schema/builder.js +15 -0
  13. package/dist/api/schema/index.d.ts +2 -0
  14. package/dist/api/schema/index.js +1 -0
  15. package/dist/api/schema/types.d.ts +257 -0
  16. package/dist/api/schema/types.js +4 -0
  17. package/dist/api/shared/async-runtime-static.d.ts +8 -0
  18. package/dist/api/shared/async-runtime-static.js +201 -0
  19. package/dist/api/shared/async-types.d.ts +42 -0
  20. package/dist/api/shared/async-types.js +8 -0
  21. package/dist/api/shared/board-resolver.d.ts +12 -0
  22. package/dist/api/shared/board-resolver.js +7 -0
  23. package/dist/api/shared/cpp-type-ir.d.ts +229 -0
  24. package/dist/api/shared/cpp-type-ir.js +672 -0
  25. package/dist/api/shared/display-adapter.d.ts +12 -0
  26. package/dist/api/shared/display-adapter.js +145 -0
  27. package/dist/api/shared/display-adapters/eink-mono.d.ts +2 -0
  28. package/dist/api/shared/display-adapters/eink-mono.js +53 -0
  29. package/dist/api/shared/display-adapters/sdl.d.ts +2 -0
  30. package/dist/api/shared/display-adapters/sdl.js +452 -0
  31. package/dist/api/shared/display-adapters/ssd1309.d.ts +2 -0
  32. package/dist/api/shared/display-adapters/ssd1309.js +136 -0
  33. package/dist/api/shared/display-adapters/st7796.d.ts +2 -0
  34. package/dist/api/shared/display-adapters/st7796.js +132 -0
  35. package/dist/api/shared/display-capabilities.d.ts +45 -0
  36. package/dist/api/shared/display-capabilities.js +54 -0
  37. package/dist/api/shared/display-op-ir.d.ts +62 -0
  38. package/dist/api/shared/display-op-ir.js +19 -0
  39. package/dist/api/shared/display-profile.d.ts +265 -0
  40. package/dist/api/shared/display-profile.js +338 -0
  41. package/dist/api/shared/graphics-strategy.d.ts +29 -0
  42. package/dist/api/shared/graphics-strategy.js +11 -0
  43. package/dist/api/shared/hal-op-ir.d.ts +393 -0
  44. package/dist/api/shared/hal-op-ir.js +18 -0
  45. package/dist/api/shared/index.d.ts +26 -0
  46. package/dist/api/shared/index.js +21 -0
  47. package/dist/api/shared/ir-core.d.ts +363 -0
  48. package/dist/api/shared/ir-core.js +8 -0
  49. package/dist/api/shared/ir-declarations.d.ts +201 -0
  50. package/dist/api/shared/ir-declarations.js +26 -0
  51. package/dist/api/shared/ir.d.ts +85 -0
  52. package/dist/api/shared/ir.js +13 -0
  53. package/dist/api/shared/platform-strategy.d.ts +402 -0
  54. package/dist/api/shared/platform-strategy.js +14 -0
  55. package/dist/api/shared/polyfill-helper-registry.d.ts +11 -0
  56. package/dist/api/shared/polyfill-helper-registry.js +86 -0
  57. package/dist/api/shared/polyfill-types.d.ts +33 -0
  58. package/dist/api/shared/polyfill-types.js +76 -0
  59. package/dist/api/shared/promise-runtime.d.ts +10 -0
  60. package/dist/api/shared/promise-runtime.js +244 -0
  61. package/dist/api/shared/snprintf-types.d.ts +29 -0
  62. package/dist/api/shared/snprintf-types.js +8 -0
  63. package/dist/api/shared/string-method-registry.d.ts +53 -0
  64. package/dist/api/shared/string-method-registry.js +168 -0
  65. package/dist/api/shared/toolchain-types.d.ts +63 -0
  66. package/dist/api/shared/toolchain-types.js +71 -0
  67. package/dist/api/shared/types.d.ts +50 -0
  68. package/dist/api/shared/types.js +6 -0
  69. package/dist/ast/parse.d.ts +2 -0
  70. package/dist/ast/parse.js +4 -0
  71. package/dist/cache.d.ts +26 -0
  72. package/dist/cache.js +95 -0
  73. package/dist/cli-utils.d.ts +37 -0
  74. package/dist/cli-utils.js +250 -0
  75. package/dist/cli.d.ts +2 -0
  76. package/dist/cli.js +635 -0
  77. package/dist/config-loader.d.ts +78 -0
  78. package/dist/config-loader.js +508 -0
  79. package/dist/config-schema.d.ts +233 -0
  80. package/dist/config-schema.js +83 -0
  81. package/dist/create/board-checklist.d.ts +2 -0
  82. package/dist/create/board-checklist.js +52 -0
  83. package/dist/create/board-codegen.d.ts +9 -0
  84. package/dist/create/board-codegen.js +238 -0
  85. package/dist/create/board-generators.d.ts +12 -0
  86. package/dist/create/board-generators.js +652 -0
  87. package/dist/create/board-spec.d.ts +640 -0
  88. package/dist/create/board-spec.js +215 -0
  89. package/dist/create/eslint-rules-template.d.ts +2 -0
  90. package/dist/create/eslint-rules-template.js +672 -0
  91. package/dist/create/index.d.ts +11 -0
  92. package/dist/create/index.js +8 -0
  93. package/dist/create/init-scaffold.d.ts +27 -0
  94. package/dist/create/init-scaffold.js +150 -0
  95. package/dist/create/init-templates.d.ts +24 -0
  96. package/dist/create/init-templates.js +379 -0
  97. package/dist/create/init-wizard.d.ts +8 -0
  98. package/dist/create/init-wizard.js +168 -0
  99. package/dist/debug/breakpoint-loader.d.ts +24 -0
  100. package/dist/debug/breakpoint-loader.js +137 -0
  101. package/dist/debug/index.d.ts +3 -0
  102. package/dist/debug/index.js +7 -0
  103. package/dist/debug/preprocessor.d.ts +9 -0
  104. package/dist/debug/preprocessor.js +214 -0
  105. package/dist/debug/types.d.ts +32 -0
  106. package/dist/debug/types.js +6 -0
  107. package/dist/diagnostics/diagnostics-report.d.ts +51 -0
  108. package/dist/diagnostics/diagnostics-report.js +333 -0
  109. package/dist/diagnostics/json-schema.d.ts +138 -0
  110. package/dist/diagnostics/json-schema.js +27 -0
  111. package/dist/diagnostics/md-writer.d.ts +10 -0
  112. package/dist/diagnostics/md-writer.js +336 -0
  113. package/dist/diagnostics/mermaid-builder.d.ts +65 -0
  114. package/dist/diagnostics/mermaid-builder.js +681 -0
  115. package/dist/emit/cpp-emitter.d.ts +6 -0
  116. package/dist/emit/cpp-emitter.js +48 -0
  117. package/dist/emit/emitters/class-emitter.d.ts +2 -0
  118. package/dist/emit/emitters/class-emitter.js +523 -0
  119. package/dist/emit/emitters/emitter-context.d.ts +174 -0
  120. package/dist/emit/emitters/emitter-context.js +1 -0
  121. package/dist/emit/emitters/entrypoint-synthesizer.d.ts +2 -0
  122. package/dist/emit/emitters/entrypoint-synthesizer.js +175 -0
  123. package/dist/emit/emitters/function-emitter-impl.d.ts +19 -0
  124. package/dist/emit/emitters/function-emitter-impl.js +428 -0
  125. package/dist/emit/emitters/line-appender.d.ts +15 -0
  126. package/dist/emit/emitters/line-appender.js +344 -0
  127. package/dist/emit/emitters/namespace-emitter.d.ts +2 -0
  128. package/dist/emit/emitters/namespace-emitter.js +324 -0
  129. package/dist/emit/emitters/output-finalizer.d.ts +4 -0
  130. package/dist/emit/emitters/output-finalizer.js +267 -0
  131. package/dist/emit/emitters/setup.d.ts +3 -0
  132. package/dist/emit/emitters/setup.js +851 -0
  133. package/dist/emit/emitters/top-level-prep.d.ts +2 -0
  134. package/dist/emit/emitters/top-level-prep.js +706 -0
  135. package/dist/emit/emitters/type-decl-emitter.d.ts +2 -0
  136. package/dist/emit/emitters/type-decl-emitter.js +251 -0
  137. package/dist/emit/emitters/ui-emitter.d.ts +21 -0
  138. package/dist/emit/emitters/ui-emitter.js +564 -0
  139. package/dist/emit/enum-emitter.d.ts +1 -0
  140. package/dist/emit/enum-emitter.js +1 -0
  141. package/dist/emit/expression-renderer.d.ts +283 -0
  142. package/dist/emit/expression-renderer.js +1477 -0
  143. package/dist/emit/native-helpers-emitter.d.ts +11 -0
  144. package/dist/emit/native-helpers-emitter.js +34 -0
  145. package/dist/emit/route-hal-op.d.ts +5 -0
  146. package/dist/emit/route-hal-op.js +13 -0
  147. package/dist/emit/snprintf-helpers.d.ts +17 -0
  148. package/dist/emit/snprintf-helpers.js +462 -0
  149. package/dist/emit/statement-renderer.d.ts +189 -0
  150. package/dist/emit/statement-renderer.js +948 -0
  151. package/dist/emit/utils/async-state-machine.d.ts +42 -0
  152. package/dist/emit/utils/async-state-machine.js +343 -0
  153. package/dist/emit/utils/comment-helpers.d.ts +20 -0
  154. package/dist/emit/utils/comment-helpers.js +31 -0
  155. package/dist/emit/utils/cpp-helpers.d.ts +47 -0
  156. package/dist/emit/utils/cpp-helpers.js +85 -0
  157. package/dist/emit/utils/include-resolver.d.ts +58 -0
  158. package/dist/emit/utils/include-resolver.js +155 -0
  159. package/dist/emit/utils/index.d.ts +8 -0
  160. package/dist/emit/utils/index.js +12 -0
  161. package/dist/emit/utils/type-inference.d.ts +159 -0
  162. package/dist/emit/utils/type-inference.js +559 -0
  163. package/dist/eslint-check.d.ts +10 -0
  164. package/dist/eslint-check.js +102 -0
  165. package/dist/framework-package.d.ts +10 -0
  166. package/dist/framework-package.js +58 -0
  167. package/dist/framework-registry.d.ts +39 -0
  168. package/dist/framework-registry.js +30 -0
  169. package/dist/incremental-cache.d.ts +116 -0
  170. package/dist/incremental-cache.js +335 -0
  171. package/dist/ir/adc-range-validation.d.ts +11 -0
  172. package/dist/ir/adc-range-validation.js +250 -0
  173. package/dist/ir/ast-node-utils.d.ts +8 -0
  174. package/dist/ir/ast-node-utils.js +32 -0
  175. package/dist/ir/board-pin-utils.d.ts +13 -0
  176. package/dist/ir/board-pin-utils.js +65 -0
  177. package/dist/ir/board-resolver.d.ts +36 -0
  178. package/dist/ir/board-resolver.js +437 -0
  179. package/dist/ir/build-ir-state.d.ts +167 -0
  180. package/dist/ir/build-ir-state.js +306 -0
  181. package/dist/ir/build-ir.d.ts +2 -0
  182. package/dist/ir/build-ir.js +808 -0
  183. package/dist/ir/call-graph.d.ts +35 -0
  184. package/dist/ir/call-graph.js +194 -0
  185. package/dist/ir/compile-time-only.d.ts +2 -0
  186. package/dist/ir/compile-time-only.js +16 -0
  187. package/dist/ir/declaration-builders.d.ts +9 -0
  188. package/dist/ir/declaration-builders.js +608 -0
  189. package/dist/ir/entry-points.d.ts +30 -0
  190. package/dist/ir/entry-points.js +191 -0
  191. package/dist/ir/expression-to-ir.d.ts +5 -0
  192. package/dist/ir/expression-to-ir.js +2249 -0
  193. package/dist/ir/extract-property-chain.d.ts +10 -0
  194. package/dist/ir/extract-property-chain.js +30 -0
  195. package/dist/ir/feature-prescan.d.ts +3 -0
  196. package/dist/ir/feature-prescan.js +43 -0
  197. package/dist/ir/feature-registry.d.ts +30 -0
  198. package/dist/ir/feature-registry.js +816 -0
  199. package/dist/ir/filter.d.ts +7 -0
  200. package/dist/ir/filter.js +85 -0
  201. package/dist/ir/function-builder.d.ts +19 -0
  202. package/dist/ir/function-builder.js +670 -0
  203. package/dist/ir/hal/hal-emitter.d.ts +62 -0
  204. package/dist/ir/hal/hal-emitter.js +735 -0
  205. package/dist/ir/hal/hal-parser.d.ts +61 -0
  206. package/dist/ir/hal/hal-parser.js +473 -0
  207. package/dist/ir/hal/hal-plugins.d.ts +34 -0
  208. package/dist/ir/hal/hal-plugins.js +706 -0
  209. package/dist/ir/hal-resolver.d.ts +5 -0
  210. package/dist/ir/hal-resolver.js +5 -0
  211. package/dist/ir/heap-analysis.d.ts +8 -0
  212. package/dist/ir/heap-analysis.js +350 -0
  213. package/dist/ir/heap-array-validation.d.ts +24 -0
  214. package/dist/ir/heap-array-validation.js +29 -0
  215. package/dist/ir/identifier-collector.d.ts +18 -0
  216. package/dist/ir/identifier-collector.js +439 -0
  217. package/dist/ir/interrupt-analysis.d.ts +39 -0
  218. package/dist/ir/interrupt-analysis.js +467 -0
  219. package/dist/ir/memory-budget-validation.d.ts +10 -0
  220. package/dist/ir/memory-budget-validation.js +86 -0
  221. package/dist/ir/namespace-builder.d.ts +7 -0
  222. package/dist/ir/namespace-builder.js +152 -0
  223. package/dist/ir/ownership-analysis.d.ts +9 -0
  224. package/dist/ir/ownership-analysis.js +1207 -0
  225. package/dist/ir/peripheral-ownership.d.ts +3 -0
  226. package/dist/ir/peripheral-ownership.js +152 -0
  227. package/dist/ir/peripheral-symbols.d.ts +7 -0
  228. package/dist/ir/peripheral-symbols.js +57 -0
  229. package/dist/ir/peripheral-usage.d.ts +54 -0
  230. package/dist/ir/peripheral-usage.js +691 -0
  231. package/dist/ir/peripheral-validation.d.ts +8 -0
  232. package/dist/ir/peripheral-validation.js +77 -0
  233. package/dist/ir/pin-alias-conflict.d.ts +4 -0
  234. package/dist/ir/pin-alias-conflict.js +34 -0
  235. package/dist/ir/pin-capability-validation.d.ts +6 -0
  236. package/dist/ir/pin-capability-validation.js +413 -0
  237. package/dist/ir/pin-mode-validation.d.ts +10 -0
  238. package/dist/ir/pin-mode-validation.js +301 -0
  239. package/dist/ir/pin-safety.d.ts +11 -0
  240. package/dist/ir/pin-safety.js +58 -0
  241. package/dist/ir/program-analysis.d.ts +44 -0
  242. package/dist/ir/program-analysis.js +589 -0
  243. package/dist/ir/pulldown-validation.d.ts +7 -0
  244. package/dist/ir/pulldown-validation.js +49 -0
  245. package/dist/ir/pwm-timer-sharing.d.ts +4 -0
  246. package/dist/ir/pwm-timer-sharing.js +93 -0
  247. package/dist/ir/reachability.d.ts +68 -0
  248. package/dist/ir/reachability.js +224 -0
  249. package/dist/ir/register-decorators.d.ts +6 -0
  250. package/dist/ir/register-decorators.js +49 -0
  251. package/dist/ir/render-expr.d.ts +4 -0
  252. package/dist/ir/render-expr.js +127 -0
  253. package/dist/ir/resource-analysis.d.ts +19 -0
  254. package/dist/ir/resource-analysis.js +153 -0
  255. package/dist/ir/statement-to-ir.d.ts +23 -0
  256. package/dist/ir/statement-to-ir.js +349 -0
  257. package/dist/ir/symbol-table.d.ts +68 -0
  258. package/dist/ir/symbol-table.js +179 -0
  259. package/dist/ir/symbol-types.d.ts +56 -0
  260. package/dist/ir/symbol-types.js +107 -0
  261. package/dist/ir/timer0-pwm-timing-conflict.d.ts +4 -0
  262. package/dist/ir/timer0-pwm-timing-conflict.js +71 -0
  263. package/dist/ir/timing-validation.d.ts +7 -0
  264. package/dist/ir/timing-validation.js +95 -0
  265. package/dist/ir/transformers/array-methods.d.ts +8 -0
  266. package/dist/ir/transformers/array-methods.js +493 -0
  267. package/dist/ir/transformers/call-statement.d.ts +5 -0
  268. package/dist/ir/transformers/call-statement.js +758 -0
  269. package/dist/ir/transformers/callback-context-registry.d.ts +20 -0
  270. package/dist/ir/transformers/callback-context-registry.js +55 -0
  271. package/dist/ir/transformers/canvas-lowering.d.ts +42 -0
  272. package/dist/ir/transformers/canvas-lowering.js +249 -0
  273. package/dist/ir/transformers/control-flow.d.ts +8 -0
  274. package/dist/ir/transformers/control-flow.js +508 -0
  275. package/dist/ir/transformers/expressions.d.ts +7 -0
  276. package/dist/ir/transformers/expressions.js +406 -0
  277. package/dist/ir/transformers/hal-call-resolver.d.ts +29 -0
  278. package/dist/ir/transformers/hal-call-resolver.js +274 -0
  279. package/dist/ir/transformers/hal-emit-helpers.d.ts +14 -0
  280. package/dist/ir/transformers/hal-emit-helpers.js +63 -0
  281. package/dist/ir/transformers/namespace-methods.d.ts +20 -0
  282. package/dist/ir/transformers/namespace-methods.js +110 -0
  283. package/dist/ir/transformers/register-assignment.d.ts +5 -0
  284. package/dist/ir/transformers/register-assignment.js +56 -0
  285. package/dist/ir/transformers/ui-call-resolver.d.ts +149 -0
  286. package/dist/ir/transformers/ui-call-resolver.js +1136 -0
  287. package/dist/ir/transformers/ui-callback-lowering.d.ts +62 -0
  288. package/dist/ir/transformers/ui-callback-lowering.js +623 -0
  289. package/dist/ir/transformers/ui-mount.d.ts +20 -0
  290. package/dist/ir/transformers/ui-mount.js +35 -0
  291. package/dist/ir/transformers/ui-reactive.d.ts +68 -0
  292. package/dist/ir/transformers/ui-reactive.js +129 -0
  293. package/dist/ir/transformers/variables.d.ts +14 -0
  294. package/dist/ir/transformers/variables.js +1045 -0
  295. package/dist/ir/try-catch-validation.d.ts +26 -0
  296. package/dist/ir/try-catch-validation.js +128 -0
  297. package/dist/ir/type-resolution.d.ts +31 -0
  298. package/dist/ir/type-resolution.js +977 -0
  299. package/dist/ir/ui-element-auto-wire.d.ts +50 -0
  300. package/dist/ir/ui-element-auto-wire.js +218 -0
  301. package/dist/ir/unit-suspicion-validation.d.ts +12 -0
  302. package/dist/ir/unit-suspicion-validation.js +296 -0
  303. package/dist/ir/utils/walk-ir.d.ts +6 -0
  304. package/dist/ir/utils/walk-ir.js +162 -0
  305. package/dist/ir/validation-orchestrator.d.ts +4 -0
  306. package/dist/ir/validation-orchestrator.js +45 -0
  307. package/dist/libdef/base-class-resolver.d.ts +23 -0
  308. package/dist/libdef/base-class-resolver.js +50 -0
  309. package/dist/libdef/cpp-to-decl.d.ts +34 -0
  310. package/dist/libdef/cpp-to-decl.js +584 -0
  311. package/dist/libdef/header-parser.d.ts +53 -0
  312. package/dist/libdef/header-parser.js +269 -0
  313. package/dist/libdef/registry.d.ts +10 -0
  314. package/dist/libdef/registry.js +142 -0
  315. package/dist/mapping/peripheral-names.d.ts +23 -0
  316. package/dist/mapping/peripheral-names.js +63 -0
  317. package/dist/mapping/source-map.d.ts +46 -0
  318. package/dist/mapping/source-map.js +207 -0
  319. package/dist/orchestrator/dts-generator.d.ts +17 -0
  320. package/dist/orchestrator/dts-generator.js +83 -0
  321. package/dist/orchestrator/graph-builder.d.ts +18 -0
  322. package/dist/orchestrator/graph-builder.js +218 -0
  323. package/dist/orchestrator/semantic-facts-verifier.d.ts +38 -0
  324. package/dist/orchestrator/semantic-facts-verifier.js +121 -0
  325. package/dist/orchestrator/semantic-facts.d.ts +141 -0
  326. package/dist/orchestrator/semantic-facts.js +652 -0
  327. package/dist/orchestrator/type-checker.d.ts +39 -0
  328. package/dist/orchestrator/type-checker.js +760 -0
  329. package/dist/platform/async-runtime.d.ts +8 -0
  330. package/dist/platform/async-runtime.js +26 -0
  331. package/dist/platform/generic-strategy.d.ts +101 -0
  332. package/dist/platform/generic-strategy.js +289 -0
  333. package/dist/platform/index.d.ts +4 -0
  334. package/dist/platform/index.js +9 -0
  335. package/dist/platform/registry.d.ts +21 -0
  336. package/dist/platform/registry.js +42 -0
  337. package/dist/platform/toolchain.d.ts +4 -0
  338. package/dist/platform/toolchain.js +43 -0
  339. package/dist/preview/client.d.ts +1 -0
  340. package/dist/preview/client.js +137 -0
  341. package/dist/preview/server.d.ts +5 -0
  342. package/dist/preview/server.js +199 -0
  343. package/dist/profiler/index.d.ts +28 -0
  344. package/dist/profiler/index.js +28 -0
  345. package/dist/profiler/profiler.d.ts +95 -0
  346. package/dist/profiler/profiler.js +338 -0
  347. package/dist/profiler/types.d.ts +87 -0
  348. package/dist/profiler/types.js +12 -0
  349. package/dist/stores/display-profile-store.d.ts +16 -0
  350. package/dist/stores/display-profile-store.js +48 -0
  351. package/dist/stores/theme-store.d.ts +13 -0
  352. package/dist/stores/theme-store.js +30 -0
  353. package/dist/testing.d.ts +45 -0
  354. package/dist/testing.js +47 -0
  355. package/dist/transpile/resolution.d.ts +29 -0
  356. package/dist/transpile/resolution.js +282 -0
  357. package/dist/transpile.d.ts +3 -0
  358. package/dist/transpile.js +722 -0
  359. package/dist/types.d.ts +217 -0
  360. package/dist/types.js +1 -0
  361. package/dist/ui/ui-bridge.d.ts +4 -0
  362. package/dist/ui/ui-bridge.js +34 -0
  363. package/dist/ui-hook.d.ts +84 -0
  364. package/dist/ui-hook.js +45 -0
  365. package/dist/utils/cli.d.ts +3 -0
  366. package/dist/utils/cli.js +463 -0
  367. package/dist/utils/fs.d.ts +4 -0
  368. package/dist/utils/fs.js +23 -0
  369. package/dist/utils/logger.d.ts +2 -0
  370. package/dist/utils/logger.js +8 -0
  371. package/dist/utils/strings.d.ts +35 -0
  372. package/dist/utils/strings.js +142 -0
  373. package/dist/utils/ui.d.ts +66 -0
  374. package/dist/utils/ui.js +149 -0
  375. package/dist/watch.d.ts +35 -0
  376. package/dist/watch.js +111 -0
  377. package/package.json +127 -0
@@ -0,0 +1,559 @@
1
+ /**
2
+ * Type inference utilities for C++ code emission.
3
+ * Pure functions with no side effects - extracted from cpp-emitter.ts
4
+ */
5
+ import { parsedIsPointer } from "../../api/shared/cpp-type-ir.js";
6
+ /**
7
+ * Infers the C++ type for an object field based on its initializer value.
8
+ *
9
+ * @param value The expression to infer type for
10
+ * @param pointerVarTypes Map of variable names to their pointer types (e.g., "sensor" -> "Sensor*")
11
+ * @param knownFunctionReturnTypes Map of function names to their return types
12
+ * @param knownObjectTypes Map of object names to their types
13
+ * @param knownObjectFieldTypes Map of object names to their field type maps
14
+ * @param largeEnumNames Set of enum names with values outside 16-bit int range
15
+ * @param resolvePinType Optional callback to resolve pin types from the platform strategy
16
+ * @returns The inferred C++ type string
17
+ */
18
+ export function inferObjectFieldType(value, pointerVarTypes, knownFunctionReturnTypes, knownObjectTypes, knownObjectFieldTypes, largeEnumNames, parentName, fieldName, defaultIntType = "int", resolvePinType) {
19
+ if (value.kind === "number") {
20
+ if (value.cppType === "float" || value.cppType === "double" || !Number.isInteger(value.value)) {
21
+ return value.cppType === "double" ? "double" : "float";
22
+ }
23
+ if (value.value > 32767 || value.value < -32768) {
24
+ return "long";
25
+ }
26
+ return defaultIntType;
27
+ }
28
+ if (value.kind === "boolean") {
29
+ return "bool";
30
+ }
31
+ if (value.kind === "string") {
32
+ return "const char*";
33
+ }
34
+ if (value.kind === "identifier") {
35
+ if (knownObjectTypes && knownObjectTypes.has(value.value)) {
36
+ return knownObjectTypes.get(value.value);
37
+ }
38
+ if (value.value === "Pins") {
39
+ return "_Pins_t";
40
+ }
41
+ // Check if this identifier is a known pointer variable
42
+ if (pointerVarTypes && pointerVarTypes.has(value.value)) {
43
+ return pointerVarTypes.get(value.value);
44
+ }
45
+ // Default to the defaultIntType for unknown identifiers
46
+ // This will be overridden if knownVariableTypes is provided
47
+ return defaultIntType;
48
+ }
49
+ // For enum member access (e.g. I2CSpeed.STANDARD), return `long` if the
50
+ // enum has values outside the 16-bit int range, otherwise `int`.
51
+ if (value.kind === "property-access" && value.object.kind === "identifier") {
52
+ const enumName = value.object.value;
53
+ return largeEnumNames?.has(enumName) ? "long" : defaultIntType;
54
+ }
55
+ if (value.kind === "raw") {
56
+ const memberAccessMatch = value.value.match(/^([A-Za-z_][A-Za-z0-9_]*)\.([A-Za-z_][A-Za-z0-9_]*)$/);
57
+ if (memberAccessMatch && knownObjectFieldTypes) {
58
+ const objectName = memberAccessMatch[1];
59
+ const fieldName = memberAccessMatch[2];
60
+ const fields = knownObjectFieldTypes.get(objectName);
61
+ if (fields?.has(fieldName)) {
62
+ return fields.get(fieldName);
63
+ }
64
+ if (objectName === "Pins" && resolvePinType) {
65
+ const resolved = resolvePinType(objectName, fieldName);
66
+ if (resolved)
67
+ return resolved;
68
+ }
69
+ }
70
+ const newMatch = value.value.match(/^new\s+([A-Za-z_][A-Za-z0-9_]*)\s*\(/);
71
+ if (newMatch) {
72
+ return `${newMatch[1]}*`;
73
+ }
74
+ const callMatch = value.value.match(/^([A-Za-z_][A-Za-z0-9_]*)\s*\(/);
75
+ if (callMatch && knownFunctionReturnTypes) {
76
+ const inferred = knownFunctionReturnTypes.get(callMatch[1]);
77
+ if (inferred) {
78
+ return inferred;
79
+ }
80
+ }
81
+ }
82
+ if (value.kind === "array") {
83
+ const elementKinds = value.elements.map((element) => element.kind);
84
+ let elementType = defaultIntType;
85
+ if (elementKinds.includes("string")) {
86
+ elementType = "const char*";
87
+ }
88
+ else if (value.elements.some((element) => element.kind === "number" && !Number.isInteger(element.value))) {
89
+ elementType = "float";
90
+ }
91
+ else if (elementKinds.includes("boolean") && !elementKinds.includes("number")) {
92
+ elementType = "bool";
93
+ }
94
+ return `std::vector<${elementType}>`;
95
+ }
96
+ // Nested object literal — generate a struct type name
97
+ if (value.kind === "object") {
98
+ if (parentName && fieldName) {
99
+ return `_${parentName}_${fieldName}_t`;
100
+ }
101
+ return defaultIntType;
102
+ }
103
+ return defaultIntType;
104
+ }
105
+ /**
106
+ * Recursively collects nested struct definitions from an object ExpressionIR.
107
+ * Returns an array of struct definitions ordered from deepest to shallowest,
108
+ * so that inner structs are defined before outer structs that reference them.
109
+ *
110
+ * @param objExpr The object ExpressionIR to scan for nested objects
111
+ * @param parentName The variable/struct name prefix for generating struct type names
112
+ * @param pointerVarTypes Optional pointer variable type map
113
+ * @param knownFunctionReturnTypes Optional function return type map
114
+ * @param knownObjectTypes Optional object type map
115
+ * @param knownObjectFieldTypes Optional object field type map
116
+ * @param largeEnumNames Optional large enum names set
117
+ */
118
+ export function collectNestedStructDefs(objExpr, parentName, pointerVarTypes, knownFunctionReturnTypes, knownObjectTypes, knownObjectFieldTypes, largeEnumNames) {
119
+ const result = [];
120
+ for (const field of objExpr.fields) {
121
+ if (field.value.kind === "object") {
122
+ const nestedObj = field.value;
123
+ const nestedStructName = `_${parentName}_${field.name}_t`;
124
+ // Recursively collect deeper nested structs first
125
+ const deeper = collectNestedStructDefs(nestedObj, `${parentName}_${field.name}`, pointerVarTypes, knownFunctionReturnTypes, knownObjectTypes, knownObjectFieldTypes, largeEnumNames);
126
+ result.push(...deeper);
127
+ // Collect this nested struct's fields
128
+ const nestedFields = nestedObj.fields.map((f) => ({
129
+ type: inferObjectFieldType(f.value, pointerVarTypes, knownFunctionReturnTypes, knownObjectTypes, knownObjectFieldTypes, largeEnumNames, `${parentName}_${field.name}`, f.name),
130
+ name: f.name,
131
+ }));
132
+ result.push({ structName: nestedStructName, fields: nestedFields });
133
+ }
134
+ }
135
+ return result;
136
+ }
137
+ /**
138
+ * Checks if a program contains array literals inside object literals.
139
+ * This affects whether std::vector needs to be included.
140
+ *
141
+ * @param program The program IR to analyze
142
+ * @returns true if arrays in object literals are found
143
+ */
144
+ export function hasArrayInObjectLiteral(program) {
145
+ const hasArray = (expr) => {
146
+ if (expr.kind === "array") {
147
+ return true;
148
+ }
149
+ if (expr.kind === "object") {
150
+ return expr.fields.some((field) => hasArray(field.value));
151
+ }
152
+ if (expr.kind === "ternary") {
153
+ return hasArray(expr.condition) || hasArray(expr.whenTrue) || hasArray(expr.whenFalse);
154
+ }
155
+ return false;
156
+ };
157
+ const hasArrayInStatement = (statement) => {
158
+ if (statement.kind === "var_decl" && statement.initializer) {
159
+ return hasArray(statement.initializer);
160
+ }
161
+ if (statement.kind === "assign") {
162
+ return hasArray(statement.value);
163
+ }
164
+ if (statement.kind === "return" && statement.value) {
165
+ return hasArray(statement.value);
166
+ }
167
+ if (statement.kind === "call") {
168
+ return statement.args.some((arg) => hasArray(arg));
169
+ }
170
+ return false;
171
+ };
172
+ if (program.topLevelStatements.some((statement) => hasArrayInStatement(statement))) {
173
+ return true;
174
+ }
175
+ for (const fn of program.functions) {
176
+ if (fn.statements.some((statement) => hasArrayInStatement(statement))) {
177
+ return true;
178
+ }
179
+ }
180
+ for (const classDef of program.classes) {
181
+ if (classDef.fields.some((field) => field.initializer ? hasArray(field.initializer) : false)) {
182
+ return true;
183
+ }
184
+ for (const method of classDef.methods) {
185
+ if (method.statements.some((statement) => hasArrayInStatement(statement))) {
186
+ return true;
187
+ }
188
+ }
189
+ if (classDef.constructor && classDef.constructor.statements.some((statement) => hasArrayInStatement(statement))) {
190
+ return true;
191
+ }
192
+ }
193
+ return false;
194
+ }
195
+ /**
196
+ * Checks if a program contains throw statements.
197
+ * This affects whether <stdexcept> needs to be included.
198
+ *
199
+ * @param program The program IR to analyze
200
+ * @returns true if throw statements are found
201
+ */
202
+ export function hasThrowStatements(program) {
203
+ const statementHasThrow = (statement) => {
204
+ if (statement.kind === "throw") {
205
+ return true;
206
+ }
207
+ if (statement.kind === "while" || statement.kind === "do_while") {
208
+ return statement.body.some(statementHasThrow);
209
+ }
210
+ if (statement.kind === "for" || statement.kind === "for_of" || statement.kind === "for_in") {
211
+ return statement.body.some(statementHasThrow);
212
+ }
213
+ if (statement.kind === "if") {
214
+ return statement.thenBranch.some(statementHasThrow) || (statement.elseBranch?.some(statementHasThrow) ?? false);
215
+ }
216
+ if (statement.kind === "switch") {
217
+ return statement.cases.some((caseClause) => caseClause.body.some(statementHasThrow));
218
+ }
219
+ if (statement.kind === "try") {
220
+ return statement.tryBlock.some(statementHasThrow) || (statement.catchBlock?.some(statementHasThrow) ?? false);
221
+ }
222
+ return false;
223
+ };
224
+ if (program.topLevelStatements.some(statementHasThrow)) {
225
+ return true;
226
+ }
227
+ for (const fn of program.functions) {
228
+ if (fn.statements.some(statementHasThrow)) {
229
+ return true;
230
+ }
231
+ }
232
+ for (const classDef of program.classes) {
233
+ if (classDef.methods.some((method) => method.statements.some(statementHasThrow))) {
234
+ return true;
235
+ }
236
+ if (classDef.constructor && classDef.constructor.statements.some(statementHasThrow)) {
237
+ return true;
238
+ }
239
+ }
240
+ return false;
241
+ }
242
+ /**
243
+ * Checks if a program contains std::math function calls.
244
+ * This affects whether <cmath> or <math.h> needs to be included.
245
+ *
246
+ * @param program The program IR to analyze
247
+ * @returns true if math calls are found
248
+ */
249
+ export function hasStdMathCalls(program) {
250
+ const mathPattern = /\bstd::(floor|ceil|round|trunc|sqrt|pow|sin|cos|tan|asin|acos|atan|abs|max|min)\b/;
251
+ const expressionHasMath = (expr) => {
252
+ if (expr.kind === "raw") {
253
+ return mathPattern.test(expr.value);
254
+ }
255
+ if (expr.kind === "await") {
256
+ return expressionHasMath(expr.value);
257
+ }
258
+ if (expr.kind === "ternary") {
259
+ return expressionHasMath(expr.condition) || expressionHasMath(expr.whenTrue) || expressionHasMath(expr.whenFalse);
260
+ }
261
+ if (expr.kind === "array") {
262
+ return expr.elements.some(expressionHasMath);
263
+ }
264
+ if (expr.kind === "object") {
265
+ return expr.fields.some((field) => expressionHasMath(field.value));
266
+ }
267
+ if (expr.kind === "instanceof") {
268
+ return expressionHasMath(expr.object);
269
+ }
270
+ if (expr.kind === "spread_array") {
271
+ return expressionHasMath(expr.spreadExpr) || expr.additionalElements.some(expressionHasMath);
272
+ }
273
+ return false;
274
+ };
275
+ const statementHasMath = (statement) => {
276
+ if (statement.kind === "call") {
277
+ return statement.args.some(expressionHasMath);
278
+ }
279
+ if (statement.kind === "var_decl") {
280
+ return statement.initializer ? expressionHasMath(statement.initializer) : false;
281
+ }
282
+ if (statement.kind === "assign") {
283
+ return expressionHasMath(statement.value);
284
+ }
285
+ if (statement.kind === "return") {
286
+ return statement.value ? expressionHasMath(statement.value) : false;
287
+ }
288
+ if (statement.kind === "while" || statement.kind === "do_while") {
289
+ return expressionHasMath(statement.condition) || statement.body.some(statementHasMath);
290
+ }
291
+ if (statement.kind === "if") {
292
+ return expressionHasMath(statement.condition) || statement.thenBranch.some(statementHasMath) || (statement.elseBranch?.some(statementHasMath) ?? false);
293
+ }
294
+ if (statement.kind === "for") {
295
+ return (statement.initializer ? statementHasMath(statement.initializer) : false)
296
+ || (statement.condition ? expressionHasMath(statement.condition) : false)
297
+ || (statement.increment ? statementHasMath(statement.increment) : false)
298
+ || statement.body.some(statementHasMath);
299
+ }
300
+ if (statement.kind === "for_of") {
301
+ return statementHasMath(statement.variable) || expressionHasMath(statement.iterable) || statement.body.some(statementHasMath);
302
+ }
303
+ if (statement.kind === "for_in") {
304
+ return statementHasMath(statement.variable) || expressionHasMath(statement.object) || statement.body.some(statementHasMath);
305
+ }
306
+ if (statement.kind === "switch") {
307
+ return expressionHasMath(statement.expression) || statement.cases.some((caseClause) => (caseClause.value ? expressionHasMath(caseClause.value) : false) || caseClause.body.some(statementHasMath));
308
+ }
309
+ if (statement.kind === "try") {
310
+ return statement.tryBlock.some(statementHasMath) || (statement.catchBlock?.some(statementHasMath) ?? false);
311
+ }
312
+ if (statement.kind === "throw") {
313
+ return expressionHasMath(statement.value);
314
+ }
315
+ return false;
316
+ };
317
+ if (program.topLevelStatements.some(statementHasMath)) {
318
+ return true;
319
+ }
320
+ if (program.functions.some((fn) => fn.statements.some(statementHasMath))) {
321
+ return true;
322
+ }
323
+ for (const classDef of program.classes) {
324
+ if (classDef.methods.some((method) => method.statements.some(statementHasMath))) {
325
+ return true;
326
+ }
327
+ if (classDef.constructor && classDef.constructor.statements.some(statementHasMath)) {
328
+ return true;
329
+ }
330
+ }
331
+ return false;
332
+ }
333
+ /**
334
+ * Checks if a program contains console.* calls (console.log, console.error, etc.)
335
+ *
336
+ * @param program The program IR to analyze
337
+ * @returns true if console calls are found
338
+ */
339
+ export function hasConsoleCalls(program, strategy) {
340
+ const checkStatements = (statements) => {
341
+ for (const stmt of statements) {
342
+ if (stmt.kind === "call" && isConsoleCall(stmt.callee, strategy)) {
343
+ return true;
344
+ }
345
+ // Check nested statements in control flow
346
+ if ("body" in stmt && Array.isArray(stmt.body)) {
347
+ if (checkStatements(stmt.body))
348
+ return true;
349
+ }
350
+ if ("thenBranch" in stmt && Array.isArray(stmt.thenBranch)) {
351
+ if (checkStatements(stmt.thenBranch))
352
+ return true;
353
+ }
354
+ if ("elseBranch" in stmt && Array.isArray(stmt.elseBranch)) {
355
+ if (checkStatements(stmt.elseBranch))
356
+ return true;
357
+ }
358
+ if ("cases" in stmt && Array.isArray(stmt.cases)) {
359
+ for (const c of stmt.cases) {
360
+ if (checkStatements(c.body))
361
+ return true;
362
+ }
363
+ }
364
+ if ("tryBlock" in stmt && Array.isArray(stmt.tryBlock)) {
365
+ if (checkStatements(stmt.tryBlock))
366
+ return true;
367
+ }
368
+ if ("catchBlock" in stmt && Array.isArray(stmt.catchBlock)) {
369
+ if (checkStatements(stmt.catchBlock))
370
+ return true;
371
+ }
372
+ }
373
+ return false;
374
+ };
375
+ // Check all functions
376
+ for (const fn of program.functions) {
377
+ if (checkStatements(fn.statements))
378
+ return true;
379
+ }
380
+ // Check top-level statements
381
+ if (checkStatements(program.topLevelStatements))
382
+ return true;
383
+ // Check class methods
384
+ for (const cls of program.classes) {
385
+ for (const method of cls.methods) {
386
+ if (checkStatements(method.statements))
387
+ return true;
388
+ }
389
+ if (cls.constructor && checkStatements(cls.constructor.statements))
390
+ return true;
391
+ }
392
+ return false;
393
+ }
394
+ /**
395
+ * Checks if a callee is a console method call (e.g., "console.log", "console.error")
396
+ */
397
+ export function isConsoleCall(callee, strategy) {
398
+ if (strategy)
399
+ return strategy.isConsoleCall(callee);
400
+ return callee.startsWith("console.");
401
+ }
402
+ /**
403
+ * Gets the console method name from a callee (e.g., "log" from "console.log")
404
+ */
405
+ export function getConsoleMethod(callee) {
406
+ return callee.slice("console.".length);
407
+ }
408
+ /**
409
+ * Checks if an expression requires runtime execution (cannot be evaluated at global scope in C++).
410
+ * Compile-time expressions can be placed at global scope; runtime expressions must go in setup()/main().
411
+ *
412
+ * @param expr The expression to check
413
+ * @returns true if the expression requires runtime execution
414
+ */
415
+ export function collectExpressionIdentifiers(expr) {
416
+ const names = new Set();
417
+ function scan(e) {
418
+ if (!e || typeof e !== 'object' || !e.kind)
419
+ return;
420
+ if (e.kind === "identifier") {
421
+ names.add(e.value);
422
+ return;
423
+ }
424
+ for (const key of Object.keys(e)) {
425
+ if (key === "kind" || key === "loc" || key === "range" || key === "sourceSpan")
426
+ continue;
427
+ const val = e[key];
428
+ if (Array.isArray(val)) {
429
+ for (const item of val) {
430
+ if (item && typeof item === 'object' && item.kind)
431
+ scan(item);
432
+ }
433
+ }
434
+ else if (val && typeof val === 'object' && val.kind) {
435
+ scan(val);
436
+ }
437
+ }
438
+ }
439
+ scan(expr);
440
+ return names;
441
+ }
442
+ export function isRuntimeExpression(expr) {
443
+ // Safety check
444
+ if (!expr || typeof expr !== 'object' || !expr.kind) {
445
+ return false;
446
+ }
447
+ switch (expr.kind) {
448
+ case "number":
449
+ case "string":
450
+ case "boolean":
451
+ // Literals are compile-time constants
452
+ return false;
453
+ case "identifier":
454
+ // Simple identifiers might be compile-time constants, but could also be
455
+ // runtime values. We'll be conservative and allow them at global scope
456
+ // since they might reference constants.
457
+ return false;
458
+ case "array":
459
+ // Arrays are okay at global scope if all elements are compile-time
460
+ return expr.elements.some((e) => isRuntimeExpression(e));
461
+ case "object":
462
+ // Plain object literals can stay at global scope as long as all their
463
+ // field initializers are themselves compile-time-safe.
464
+ return expr.fields.some((f) => isRuntimeExpression(f.value));
465
+ case "raw":
466
+ // Raw expressions might contain method calls - check for common patterns
467
+ // Look for function/method call patterns: identifier(...) or ...(...)
468
+ const rawValue = expr.value;
469
+ // Check for call patterns: ends with ) and contains ( not at start
470
+ if (rawValue.includes("(") && rawValue.includes(")")) {
471
+ // Has function call syntax - likely runtime
472
+ return true;
473
+ }
474
+ // Check for 'new' keyword
475
+ if (rawValue.startsWith("new ") || rawValue.includes(" new ")) {
476
+ return true;
477
+ }
478
+ return false;
479
+ case "await":
480
+ // Await expressions are definitely runtime
481
+ return true;
482
+ case "ternary":
483
+ // Ternary expressions are runtime if any part is runtime
484
+ return (isRuntimeExpression(expr.condition) ||
485
+ isRuntimeExpression(expr.whenTrue) ||
486
+ isRuntimeExpression(expr.whenFalse));
487
+ case "binary":
488
+ return isRuntimeExpression(expr.left) || isRuntimeExpression(expr.right);
489
+ case "unary":
490
+ return isRuntimeExpression(expr.operand);
491
+ case "method-call":
492
+ return true;
493
+ case "instanceof":
494
+ // instanceof requires RTTI and runtime evaluation
495
+ return true;
496
+ case "spread_array":
497
+ // Spread operations are runtime
498
+ return true;
499
+ case "property-access":
500
+ // An enum member access (Mode.Run → Mode::Run) is a compile-time
501
+ // constant, NOT a runtime expression. Without this, a top-level
502
+ // `const currentMode: Mode = Mode.Run` was classified as runtime
503
+ // (the default returns true) and emitted as a local inside setup()
504
+ // instead of a file-scope global, making it invisible to functions
505
+ // (enum stress test Finding B). Only consider it compile-time when
506
+ // it's a static/enum access (no runtime object receiver).
507
+ return false;
508
+ default:
509
+ // Unknown expression types - be conservative
510
+ return true;
511
+ }
512
+ }
513
+ /**
514
+ * Checks if a statement requires runtime execution.
515
+ *
516
+ * @param statement The statement to check
517
+ * @returns true if the statement requires runtime execution
518
+ */
519
+ export function statementRequiresRuntime(statement) {
520
+ if (statement.kind === "var_decl") {
521
+ // Variable declaration requires runtime if its initializer does
522
+ return statement.initializer ? isRuntimeExpression(statement.initializer) : false;
523
+ }
524
+ // All other statement types (calls, assignments, etc.) are runtime
525
+ return true;
526
+ }
527
+ /**
528
+ * Collects pointer variable types from program statements.
529
+ * Variables initialized with 'new ClassName()' get type 'ClassName*'.
530
+ *
531
+ * @param statements The statements to analyze
532
+ * @param classNameMap Optional map for transforming simple class names to fully qualified names
533
+ * @returns Map of variable names to their pointer types
534
+ */
535
+ export function collectPointerVarTypes(statements, classNameMap) {
536
+ const pointerVarTypes = new Map();
537
+ for (const statement of statements) {
538
+ if (statement.kind === "var_decl" && statement.initializer) {
539
+ const declaredType = statement.cppType;
540
+ if (parsedIsPointer(declaredType)) {
541
+ pointerVarTypes.set(statement.name, declaredType);
542
+ continue;
543
+ }
544
+ const init = statement.initializer;
545
+ // Check for raw expression containing 'new'
546
+ if (init.kind === "raw" && init.value.startsWith("new ")) {
547
+ // Extract class name from 'new ClassName(...)'
548
+ const match = init.value.match(/^new\s+(\w+)/);
549
+ if (match) {
550
+ const simpleName = match[1];
551
+ // Use fully qualified name if available (for namespaced classes)
552
+ const fullName = classNameMap?.get(simpleName) ?? simpleName;
553
+ pointerVarTypes.set(statement.name, `${fullName}*`);
554
+ }
555
+ }
556
+ }
557
+ }
558
+ return pointerVarTypes;
559
+ }
@@ -0,0 +1,10 @@
1
+ export interface ESLintError {
2
+ filePath: string;
3
+ line: number;
4
+ column: number;
5
+ message: string;
6
+ ruleId: string;
7
+ sourceLine: string;
8
+ }
9
+ export declare function runEslintCheck(projectRoot: string): Promise<ESLintError[]>;
10
+ export declare function printEslintErrors(errors: ESLintError[]): void;
@@ -0,0 +1,102 @@
1
+ import path from "node:path";
2
+ import fs from "node:fs";
3
+ import { createRequire } from "node:module";
4
+ import { pathToFileURL } from "node:url";
5
+ import chalk from "chalk";
6
+ const selfRequire = createRequire(import.meta.url);
7
+ export async function runEslintCheck(projectRoot) {
8
+ // Look for eslint config in .cuttlefish/ (new layout) or project root (legacy)
9
+ const cuttlefishConfig = path.join(projectRoot, ".cuttlefish", "eslint.config.mjs");
10
+ const rootConfigNames = ["eslint.config.mjs", "eslint.config.js", "eslint.config.cjs"];
11
+ const rootConfig = rootConfigNames.find(name => fs.existsSync(path.join(projectRoot, name)));
12
+ let overrideConfigFile;
13
+ if (fs.existsSync(cuttlefishConfig)) {
14
+ overrideConfigFile = cuttlefishConfig;
15
+ }
16
+ else if (rootConfig) {
17
+ // Legacy: config at project root (existing demo projects)
18
+ overrideConfigFile = path.join(projectRoot, rootConfig);
19
+ }
20
+ else {
21
+ return [];
22
+ }
23
+ let ESLintCls;
24
+ try {
25
+ // Prefer the user project's own eslint install (handles pinned versions),
26
+ // then fall back to the cuttlefish package's install (monorepo / global).
27
+ let eslintPath;
28
+ try {
29
+ const projectRequire = createRequire(path.join(projectRoot, "package.json"));
30
+ eslintPath = projectRequire.resolve("eslint");
31
+ }
32
+ catch {
33
+ eslintPath = selfRequire.resolve("eslint");
34
+ }
35
+ const eslintModule = await import(pathToFileURL(eslintPath).href);
36
+ ESLintCls = eslintModule.ESLint;
37
+ }
38
+ catch {
39
+ return [];
40
+ }
41
+ if (!ESLintCls)
42
+ return [];
43
+ const eslint = new ESLintCls({ cwd: projectRoot, overrideConfigFile });
44
+ const srcDir = path.join(projectRoot, "src");
45
+ if (!fs.existsSync(srcDir))
46
+ return [];
47
+ let results;
48
+ try {
49
+ results = await eslint.lintFiles([srcDir]);
50
+ }
51
+ catch (err) {
52
+ const detail = err instanceof Error ? err.message : String(err);
53
+ // "All files matched by ... are ignored" is raised when src/ contains no
54
+ // lintable .ts files (e.g. a pure-.ui entry). That is a legitimate no-op,
55
+ // not a config-load failure — return [] so the build proceeds.
56
+ if (/all files matched/i.test(detail) && /ignored/i.test(detail)) {
57
+ return [];
58
+ }
59
+ // A config that exists but cannot be loaded (broken import, bad parser
60
+ // reference, etc.) means linting silently no-ops — the exact regression
61
+ // this gate exists to prevent. Surface it instead of returning [].
62
+ throw new Error(`ESLint config could not be loaded from ${overrideConfigFile}:\n${detail}\n\n` +
63
+ `Fix the config so linting runs, or remove it to skip the ESLint gate.`);
64
+ }
65
+ const errors = [];
66
+ for (const result of results) {
67
+ if (result.errorCount === 0)
68
+ continue;
69
+ const sourceLines = result.source
70
+ ? result.source.split("\n")
71
+ : fs.existsSync(result.filePath)
72
+ ? fs.readFileSync(result.filePath, "utf-8").split("\n")
73
+ : [];
74
+ for (const msg of result.messages) {
75
+ if (msg.severity !== 2)
76
+ continue;
77
+ errors.push({
78
+ filePath: path.relative(projectRoot, result.filePath),
79
+ line: msg.line,
80
+ column: msg.column,
81
+ message: msg.message,
82
+ ruleId: msg.ruleId ?? "unknown",
83
+ sourceLine: sourceLines[msg.line - 1] ?? "",
84
+ });
85
+ }
86
+ }
87
+ return errors;
88
+ }
89
+ export function printEslintErrors(errors) {
90
+ for (const err of errors) {
91
+ const location = `${err.filePath}(${err.line},${err.column})`;
92
+ const rule = chalk.gray(`[${err.ruleId}]`);
93
+ console.error(`${chalk.red.bold("error")} ${location} ${rule}: ${chalk.white(err.message)}`);
94
+ if (err.sourceLine) {
95
+ const prefix = " ";
96
+ console.error(prefix + err.sourceLine);
97
+ console.error(chalk.gray(prefix + " ".repeat(Math.max(0, err.column - 1)) + "^"));
98
+ }
99
+ }
100
+ console.error("");
101
+ console.error(chalk.red(`✖ ${errors.length} ESLint error${errors.length === 1 ? "" : "s"} — build stopped`));
102
+ }
@@ -0,0 +1,10 @@
1
+ /**
2
+ * Load a framework package and populate the LoadedFramework registry.
3
+ *
4
+ * The loaded module is expected to export at minimum `FrameworkStrategy`.
5
+ * Optional exports include `Toolchain`, `SYMBOL_KINDS`, library resolver,
6
+ * class name map builder, and lib declaration generator.
7
+ *
8
+ * Returns the raw module for backward compatibility.
9
+ */
10
+ export declare function loadFrameworkPackage(packageName: string, fromDir?: string): any;