@memberjunction/react-linter 0.0.1 → 5.38.0

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 (330) hide show
  1. package/dist/component-linter.d.ts +77 -0
  2. package/dist/component-linter.d.ts.map +1 -0
  3. package/dist/component-linter.js +1206 -0
  4. package/dist/component-linter.js.map +1 -0
  5. package/dist/control-flow-analyzer.d.ts +184 -0
  6. package/dist/control-flow-analyzer.d.ts.map +1 -0
  7. package/dist/control-flow-analyzer.js +798 -0
  8. package/dist/control-flow-analyzer.js.map +1 -0
  9. package/dist/index.d.ts +6 -0
  10. package/dist/index.d.ts.map +1 -0
  11. package/dist/index.js +8 -0
  12. package/dist/index.js.map +1 -0
  13. package/dist/library-lint-cache.d.ts +50 -0
  14. package/dist/library-lint-cache.d.ts.map +1 -0
  15. package/dist/library-lint-cache.js +173 -0
  16. package/dist/library-lint-cache.js.map +1 -0
  17. package/dist/lint-rule.d.ts +70 -0
  18. package/dist/lint-rule.d.ts.map +1 -0
  19. package/dist/lint-rule.js +30 -0
  20. package/dist/lint-rule.js.map +1 -0
  21. package/dist/lint-utils.d.ts +131 -0
  22. package/dist/lint-utils.d.ts.map +1 -0
  23. package/dist/lint-utils.js +358 -0
  24. package/dist/lint-utils.js.map +1 -0
  25. package/dist/linter-options.d.ts +51 -0
  26. package/dist/linter-options.d.ts.map +1 -0
  27. package/dist/linter-options.js +2 -0
  28. package/dist/linter-options.js.map +1 -0
  29. package/dist/prop-value-extractor.d.ts +147 -0
  30. package/dist/prop-value-extractor.d.ts.map +1 -0
  31. package/dist/prop-value-extractor.js +472 -0
  32. package/dist/prop-value-extractor.js.map +1 -0
  33. package/dist/runtime-rules/ai-tools-availability-check.d.ts +9 -0
  34. package/dist/runtime-rules/ai-tools-availability-check.d.ts.map +1 -0
  35. package/dist/runtime-rules/ai-tools-availability-check.js +223 -0
  36. package/dist/runtime-rules/ai-tools-availability-check.js.map +1 -0
  37. package/dist/runtime-rules/callback-event-validation.d.ts +22 -0
  38. package/dist/runtime-rules/callback-event-validation.d.ts.map +1 -0
  39. package/dist/runtime-rules/callback-event-validation.js +561 -0
  40. package/dist/runtime-rules/callback-event-validation.js.map +1 -0
  41. package/dist/runtime-rules/chart-field-validation.d.ts +10 -0
  42. package/dist/runtime-rules/chart-field-validation.d.ts.map +1 -0
  43. package/dist/runtime-rules/chart-field-validation.js +270 -0
  44. package/dist/runtime-rules/chart-field-validation.js.map +1 -0
  45. package/dist/runtime-rules/child-component-prop-validation.d.ts +11 -0
  46. package/dist/runtime-rules/child-component-prop-validation.d.ts.map +1 -0
  47. package/dist/runtime-rules/child-component-prop-validation.js +443 -0
  48. package/dist/runtime-rules/child-component-prop-validation.js.map +1 -0
  49. package/dist/runtime-rules/component-name-mismatch.d.ts +19 -0
  50. package/dist/runtime-rules/component-name-mismatch.d.ts.map +1 -0
  51. package/dist/runtime-rules/component-name-mismatch.js +82 -0
  52. package/dist/runtime-rules/component-name-mismatch.js.map +1 -0
  53. package/dist/runtime-rules/component-not-in-dependencies.d.ts +20 -0
  54. package/dist/runtime-rules/component-not-in-dependencies.d.ts.map +1 -0
  55. package/dist/runtime-rules/component-not-in-dependencies.js +92 -0
  56. package/dist/runtime-rules/component-not-in-dependencies.js.map +1 -0
  57. package/dist/runtime-rules/component-props-validation.d.ts +25 -0
  58. package/dist/runtime-rules/component-props-validation.d.ts.map +1 -0
  59. package/dist/runtime-rules/component-props-validation.js +228 -0
  60. package/dist/runtime-rules/component-props-validation.js.map +1 -0
  61. package/dist/runtime-rules/component-usage-without-destructuring.d.ts +20 -0
  62. package/dist/runtime-rules/component-usage-without-destructuring.d.ts.map +1 -0
  63. package/dist/runtime-rules/component-usage-without-destructuring.js +124 -0
  64. package/dist/runtime-rules/component-usage-without-destructuring.js.map +1 -0
  65. package/dist/runtime-rules/data-result-validation.d.ts +9 -0
  66. package/dist/runtime-rules/data-result-validation.d.ts.map +1 -0
  67. package/dist/runtime-rules/data-result-validation.js +763 -0
  68. package/dist/runtime-rules/data-result-validation.js.map +1 -0
  69. package/dist/runtime-rules/datagrid-field-validation.d.ts +10 -0
  70. package/dist/runtime-rules/datagrid-field-validation.d.ts.map +1 -0
  71. package/dist/runtime-rules/datagrid-field-validation.js +249 -0
  72. package/dist/runtime-rules/datagrid-field-validation.js.map +1 -0
  73. package/dist/runtime-rules/dependency-shadowing.d.ts +20 -0
  74. package/dist/runtime-rules/dependency-shadowing.d.ts.map +1 -0
  75. package/dist/runtime-rules/dependency-shadowing.js +147 -0
  76. package/dist/runtime-rules/dependency-shadowing.js.map +1 -0
  77. package/dist/runtime-rules/entity-field-access-validation.d.ts +12 -0
  78. package/dist/runtime-rules/entity-field-access-validation.d.ts.map +1 -0
  79. package/dist/runtime-rules/entity-field-access-validation.js +304 -0
  80. package/dist/runtime-rules/entity-field-access-validation.js.map +1 -0
  81. package/dist/runtime-rules/event-parameter-validation.d.ts +22 -0
  82. package/dist/runtime-rules/event-parameter-validation.d.ts.map +1 -0
  83. package/dist/runtime-rules/event-parameter-validation.js +406 -0
  84. package/dist/runtime-rules/event-parameter-validation.js.map +1 -0
  85. package/dist/runtime-rules/index.d.ts +61 -0
  86. package/dist/runtime-rules/index.d.ts.map +1 -0
  87. package/dist/runtime-rules/index.js +62 -0
  88. package/dist/runtime-rules/index.js.map +1 -0
  89. package/dist/runtime-rules/library-variable-names.d.ts +24 -0
  90. package/dist/runtime-rules/library-variable-names.d.ts.map +1 -0
  91. package/dist/runtime-rules/library-variable-names.js +88 -0
  92. package/dist/runtime-rules/library-variable-names.js.map +1 -0
  93. package/dist/runtime-rules/no-child-implementation.d.ts +18 -0
  94. package/dist/runtime-rules/no-child-implementation.d.ts.map +1 -0
  95. package/dist/runtime-rules/no-child-implementation.js +57 -0
  96. package/dist/runtime-rules/no-child-implementation.js.map +1 -0
  97. package/dist/runtime-rules/no-data-prop.d.ts +22 -0
  98. package/dist/runtime-rules/no-data-prop.d.ts.map +1 -0
  99. package/dist/runtime-rules/no-data-prop.js +111 -0
  100. package/dist/runtime-rules/no-data-prop.js.map +1 -0
  101. package/dist/runtime-rules/no-export-statements.d.ts +18 -0
  102. package/dist/runtime-rules/no-export-statements.d.ts.map +1 -0
  103. package/dist/runtime-rules/no-export-statements.js +143 -0
  104. package/dist/runtime-rules/no-export-statements.js.map +1 -0
  105. package/dist/runtime-rules/no-iife-wrapper.d.ts +18 -0
  106. package/dist/runtime-rules/no-iife-wrapper.d.ts.map +1 -0
  107. package/dist/runtime-rules/no-iife-wrapper.js +217 -0
  108. package/dist/runtime-rules/no-iife-wrapper.js.map +1 -0
  109. package/dist/runtime-rules/no-import-statements.d.ts +18 -0
  110. package/dist/runtime-rules/no-import-statements.d.ts.map +1 -0
  111. package/dist/runtime-rules/no-import-statements.js +65 -0
  112. package/dist/runtime-rules/no-import-statements.js.map +1 -0
  113. package/dist/runtime-rules/no-react-destructuring.d.ts +18 -0
  114. package/dist/runtime-rules/no-react-destructuring.d.ts.map +1 -0
  115. package/dist/runtime-rules/no-react-destructuring.js +60 -0
  116. package/dist/runtime-rules/no-react-destructuring.js.map +1 -0
  117. package/dist/runtime-rules/no-require-statements.d.ts +18 -0
  118. package/dist/runtime-rules/no-require-statements.d.ts.map +1 -0
  119. package/dist/runtime-rules/no-require-statements.js +109 -0
  120. package/dist/runtime-rules/no-require-statements.js.map +1 -0
  121. package/dist/runtime-rules/no-return-component.d.ts +18 -0
  122. package/dist/runtime-rules/no-return-component.d.ts.map +1 -0
  123. package/dist/runtime-rules/no-return-component.js +106 -0
  124. package/dist/runtime-rules/no-return-component.js.map +1 -0
  125. package/dist/runtime-rules/no-unwrap-utility-libs.d.ts +20 -0
  126. package/dist/runtime-rules/no-unwrap-utility-libs.d.ts.map +1 -0
  127. package/dist/runtime-rules/no-unwrap-utility-libs.js +75 -0
  128. package/dist/runtime-rules/no-unwrap-utility-libs.js.map +1 -0
  129. package/dist/runtime-rules/no-use-reducer.d.ts +19 -0
  130. package/dist/runtime-rules/no-use-reducer.d.ts.map +1 -0
  131. package/dist/runtime-rules/no-use-reducer.js +78 -0
  132. package/dist/runtime-rules/no-use-reducer.js.map +1 -0
  133. package/dist/runtime-rules/no-window-access.d.ts +23 -0
  134. package/dist/runtime-rules/no-window-access.d.ts.map +1 -0
  135. package/dist/runtime-rules/no-window-access.js +136 -0
  136. package/dist/runtime-rules/no-window-access.js.map +1 -0
  137. package/dist/runtime-rules/noisy-settings-updates.d.ts +18 -0
  138. package/dist/runtime-rules/noisy-settings-updates.d.ts.map +1 -0
  139. package/dist/runtime-rules/noisy-settings-updates.js +110 -0
  140. package/dist/runtime-rules/noisy-settings-updates.js.map +1 -0
  141. package/dist/runtime-rules/overflow-hidden-on-layout-container.d.ts +30 -0
  142. package/dist/runtime-rules/overflow-hidden-on-layout-container.d.ts.map +1 -0
  143. package/dist/runtime-rules/overflow-hidden-on-layout-container.js +220 -0
  144. package/dist/runtime-rules/overflow-hidden-on-layout-container.js.map +1 -0
  145. package/dist/runtime-rules/pass-standard-props.d.ts +19 -0
  146. package/dist/runtime-rules/pass-standard-props.d.ts.map +1 -0
  147. package/dist/runtime-rules/pass-standard-props.js +82 -0
  148. package/dist/runtime-rules/pass-standard-props.js.map +1 -0
  149. package/dist/runtime-rules/prefer-async-await.d.ts +17 -0
  150. package/dist/runtime-rules/prefer-async-await.d.ts.map +1 -0
  151. package/dist/runtime-rules/prefer-async-await.js +52 -0
  152. package/dist/runtime-rules/prefer-async-await.js.map +1 -0
  153. package/dist/runtime-rules/prefer-jsx-syntax.d.ts +17 -0
  154. package/dist/runtime-rules/prefer-jsx-syntax.d.ts.map +1 -0
  155. package/dist/runtime-rules/prefer-jsx-syntax.js +51 -0
  156. package/dist/runtime-rules/prefer-jsx-syntax.js.map +1 -0
  157. package/dist/runtime-rules/prop-state-sync.d.ts +19 -0
  158. package/dist/runtime-rules/prop-state-sync.d.ts.map +1 -0
  159. package/dist/runtime-rules/prop-state-sync.js +76 -0
  160. package/dist/runtime-rules/prop-state-sync.js.map +1 -0
  161. package/dist/runtime-rules/property-name-consistency.d.ts +20 -0
  162. package/dist/runtime-rules/property-name-consistency.d.ts.map +1 -0
  163. package/dist/runtime-rules/property-name-consistency.js +172 -0
  164. package/dist/runtime-rules/property-name-consistency.js.map +1 -0
  165. package/dist/runtime-rules/query-result-field-access-validation.d.ts +10 -0
  166. package/dist/runtime-rules/query-result-field-access-validation.d.ts.map +1 -0
  167. package/dist/runtime-rules/query-result-field-access-validation.js +304 -0
  168. package/dist/runtime-rules/query-result-field-access-validation.js.map +1 -0
  169. package/dist/runtime-rules/react-component-naming.d.ts +19 -0
  170. package/dist/runtime-rules/react-component-naming.d.ts.map +1 -0
  171. package/dist/runtime-rules/react-component-naming.js +72 -0
  172. package/dist/runtime-rules/react-component-naming.js.map +1 -0
  173. package/dist/runtime-rules/react-hooks-rules.d.ts +27 -0
  174. package/dist/runtime-rules/react-hooks-rules.d.ts.map +1 -0
  175. package/dist/runtime-rules/react-hooks-rules.js +223 -0
  176. package/dist/runtime-rules/react-hooks-rules.js.map +1 -0
  177. package/dist/runtime-rules/required-queries-not-called.d.ts +19 -0
  178. package/dist/runtime-rules/required-queries-not-called.d.ts.map +1 -0
  179. package/dist/runtime-rules/required-queries-not-called.js +146 -0
  180. package/dist/runtime-rules/required-queries-not-called.js.map +1 -0
  181. package/dist/runtime-rules/runquery-call-validation.d.ts +11 -0
  182. package/dist/runtime-rules/runquery-call-validation.d.ts.map +1 -0
  183. package/dist/runtime-rules/runquery-call-validation.js +886 -0
  184. package/dist/runtime-rules/runquery-call-validation.js.map +1 -0
  185. package/dist/runtime-rules/runview-call-validation.d.ts +10 -0
  186. package/dist/runtime-rules/runview-call-validation.d.ts.map +1 -0
  187. package/dist/runtime-rules/runview-call-validation.js +336 -0
  188. package/dist/runtime-rules/runview-call-validation.js.map +1 -0
  189. package/dist/runtime-rules/saved-user-settings-pattern.d.ts +19 -0
  190. package/dist/runtime-rules/saved-user-settings-pattern.d.ts.map +1 -0
  191. package/dist/runtime-rules/saved-user-settings-pattern.js +90 -0
  192. package/dist/runtime-rules/saved-user-settings-pattern.js.map +1 -0
  193. package/dist/runtime-rules/search-availability-check.d.ts +9 -0
  194. package/dist/runtime-rules/search-availability-check.d.ts.map +1 -0
  195. package/dist/runtime-rules/search-availability-check.js +220 -0
  196. package/dist/runtime-rules/search-availability-check.js.map +1 -0
  197. package/dist/runtime-rules/search-call-validation.d.ts +9 -0
  198. package/dist/runtime-rules/search-call-validation.d.ts.map +1 -0
  199. package/dist/runtime-rules/search-call-validation.js +336 -0
  200. package/dist/runtime-rules/search-call-validation.js.map +1 -0
  201. package/dist/runtime-rules/server-reload-on-client-operation.d.ts +18 -0
  202. package/dist/runtime-rules/server-reload-on-client-operation.d.ts.map +1 -0
  203. package/dist/runtime-rules/server-reload-on-client-operation.js +107 -0
  204. package/dist/runtime-rules/server-reload-on-client-operation.js.map +1 -0
  205. package/dist/runtime-rules/single-function-only.d.ts +18 -0
  206. package/dist/runtime-rules/single-function-only.d.ts.map +1 -0
  207. package/dist/runtime-rules/single-function-only.js +103 -0
  208. package/dist/runtime-rules/single-function-only.js.map +1 -0
  209. package/dist/runtime-rules/string-replace-all-occurrences.d.ts +19 -0
  210. package/dist/runtime-rules/string-replace-all-occurrences.d.ts.map +1 -0
  211. package/dist/runtime-rules/string-replace-all-occurrences.js +109 -0
  212. package/dist/runtime-rules/string-replace-all-occurrences.js.map +1 -0
  213. package/dist/runtime-rules/string-template-validation.d.ts +22 -0
  214. package/dist/runtime-rules/string-template-validation.d.ts.map +1 -0
  215. package/dist/runtime-rules/string-template-validation.js +163 -0
  216. package/dist/runtime-rules/string-template-validation.js.map +1 -0
  217. package/dist/runtime-rules/styles-validation.d.ts +10 -0
  218. package/dist/runtime-rules/styles-validation.d.ts.map +1 -0
  219. package/dist/runtime-rules/styles-validation.js +153 -0
  220. package/dist/runtime-rules/styles-validation.js.map +1 -0
  221. package/dist/runtime-rules/type-inference-errors.d.ts +23 -0
  222. package/dist/runtime-rules/type-inference-errors.d.ts.map +1 -0
  223. package/dist/runtime-rules/type-inference-errors.js +53 -0
  224. package/dist/runtime-rules/type-inference-errors.js.map +1 -0
  225. package/dist/runtime-rules/type-mismatch-operation.d.ts +23 -0
  226. package/dist/runtime-rules/type-mismatch-operation.d.ts.map +1 -0
  227. package/dist/runtime-rules/type-mismatch-operation.js +145 -0
  228. package/dist/runtime-rules/type-mismatch-operation.js.map +1 -0
  229. package/dist/runtime-rules/undefined-component-usage.d.ts +20 -0
  230. package/dist/runtime-rules/undefined-component-usage.d.ts.map +1 -0
  231. package/dist/runtime-rules/undefined-component-usage.js +138 -0
  232. package/dist/runtime-rules/undefined-component-usage.js.map +1 -0
  233. package/dist/runtime-rules/undefined-jsx-component.d.ts +25 -0
  234. package/dist/runtime-rules/undefined-jsx-component.d.ts.map +1 -0
  235. package/dist/runtime-rules/undefined-jsx-component.js +269 -0
  236. package/dist/runtime-rules/undefined-jsx-component.js.map +1 -0
  237. package/dist/runtime-rules/unsafe-array-operations.d.ts +25 -0
  238. package/dist/runtime-rules/unsafe-array-operations.d.ts.map +1 -0
  239. package/dist/runtime-rules/unsafe-array-operations.js +347 -0
  240. package/dist/runtime-rules/unsafe-array-operations.js.map +1 -0
  241. package/dist/runtime-rules/unsafe-formatting-methods.d.ts +24 -0
  242. package/dist/runtime-rules/unsafe-formatting-methods.d.ts.map +1 -0
  243. package/dist/runtime-rules/unsafe-formatting-methods.js +277 -0
  244. package/dist/runtime-rules/unsafe-formatting-methods.js.map +1 -0
  245. package/dist/runtime-rules/unused-component-dependencies.d.ts +19 -0
  246. package/dist/runtime-rules/unused-component-dependencies.d.ts.map +1 -0
  247. package/dist/runtime-rules/unused-component-dependencies.js +90 -0
  248. package/dist/runtime-rules/unused-component-dependencies.js.map +1 -0
  249. package/dist/runtime-rules/unused-libraries.d.ts +19 -0
  250. package/dist/runtime-rules/unused-libraries.d.ts.map +1 -0
  251. package/dist/runtime-rules/unused-libraries.js +127 -0
  252. package/dist/runtime-rules/unused-libraries.js.map +1 -0
  253. package/dist/runtime-rules/use-function-declaration.d.ts +18 -0
  254. package/dist/runtime-rules/use-function-declaration.d.ts.map +1 -0
  255. package/dist/runtime-rules/use-function-declaration.js +127 -0
  256. package/dist/runtime-rules/use-function-declaration.js.map +1 -0
  257. package/dist/runtime-rules/use-unwrap-components.d.ts +19 -0
  258. package/dist/runtime-rules/use-unwrap-components.d.ts.map +1 -0
  259. package/dist/runtime-rules/use-unwrap-components.js +84 -0
  260. package/dist/runtime-rules/use-unwrap-components.js.map +1 -0
  261. package/dist/runtime-rules/useeffect-unstable-dependencies.d.ts +23 -0
  262. package/dist/runtime-rules/useeffect-unstable-dependencies.d.ts.map +1 -0
  263. package/dist/runtime-rules/useeffect-unstable-dependencies.js +215 -0
  264. package/dist/runtime-rules/useeffect-unstable-dependencies.js.map +1 -0
  265. package/dist/runtime-rules/utilities-api-validation.d.ts +24 -0
  266. package/dist/runtime-rules/utilities-api-validation.d.ts.map +1 -0
  267. package/dist/runtime-rules/utilities-api-validation.js +121 -0
  268. package/dist/runtime-rules/utilities-api-validation.js.map +1 -0
  269. package/dist/runtime-rules/utilities-no-direct-instantiation.d.ts +20 -0
  270. package/dist/runtime-rules/utilities-no-direct-instantiation.d.ts.map +1 -0
  271. package/dist/runtime-rules/utilities-no-direct-instantiation.js +58 -0
  272. package/dist/runtime-rules/utilities-no-direct-instantiation.js.map +1 -0
  273. package/dist/runtime-rules/validate-component-references.d.ts +19 -0
  274. package/dist/runtime-rules/validate-component-references.d.ts.map +1 -0
  275. package/dist/runtime-rules/validate-component-references.js +255 -0
  276. package/dist/runtime-rules/validate-component-references.js.map +1 -0
  277. package/dist/schema-validation/component-prop-rule.d.ts +131 -0
  278. package/dist/schema-validation/component-prop-rule.d.ts.map +1 -0
  279. package/dist/schema-validation/component-prop-rule.js +625 -0
  280. package/dist/schema-validation/component-prop-rule.js.map +1 -0
  281. package/dist/schema-validation/index.d.ts +26 -0
  282. package/dist/schema-validation/index.d.ts.map +1 -0
  283. package/dist/schema-validation/index.js +26 -0
  284. package/dist/schema-validation/index.js.map +1 -0
  285. package/dist/schema-validation/semantic-validators/index.d.ts +23 -0
  286. package/dist/schema-validation/semantic-validators/index.d.ts.map +1 -0
  287. package/dist/schema-validation/semantic-validators/index.js +23 -0
  288. package/dist/schema-validation/semantic-validators/index.js.map +1 -0
  289. package/dist/schema-validation/semantic-validators/required-when-validator.d.ts +43 -0
  290. package/dist/schema-validation/semantic-validators/required-when-validator.d.ts.map +1 -0
  291. package/dist/schema-validation/semantic-validators/required-when-validator.js +94 -0
  292. package/dist/schema-validation/semantic-validators/required-when-validator.js.map +1 -0
  293. package/dist/schema-validation/semantic-validators/semantic-validator-registry.d.ts +122 -0
  294. package/dist/schema-validation/semantic-validators/semantic-validator-registry.d.ts.map +1 -0
  295. package/dist/schema-validation/semantic-validators/semantic-validator-registry.js +166 -0
  296. package/dist/schema-validation/semantic-validators/semantic-validator-registry.js.map +1 -0
  297. package/dist/schema-validation/semantic-validators/semantic-validator.d.ts +260 -0
  298. package/dist/schema-validation/semantic-validators/semantic-validator.d.ts.map +1 -0
  299. package/dist/schema-validation/semantic-validators/semantic-validator.js +301 -0
  300. package/dist/schema-validation/semantic-validators/semantic-validator.js.map +1 -0
  301. package/dist/schema-validation/semantic-validators/sql-where-clause-validator.d.ts +115 -0
  302. package/dist/schema-validation/semantic-validators/sql-where-clause-validator.d.ts.map +1 -0
  303. package/dist/schema-validation/semantic-validators/sql-where-clause-validator.js +381 -0
  304. package/dist/schema-validation/semantic-validators/sql-where-clause-validator.js.map +1 -0
  305. package/dist/schema-validation/semantic-validators/subset-of-entity-fields-validator.d.ts +60 -0
  306. package/dist/schema-validation/semantic-validators/subset-of-entity-fields-validator.d.ts.map +1 -0
  307. package/dist/schema-validation/semantic-validators/subset-of-entity-fields-validator.js +195 -0
  308. package/dist/schema-validation/semantic-validators/subset-of-entity-fields-validator.js.map +1 -0
  309. package/dist/schema-validation/semantic-validators/validation-context.d.ts +335 -0
  310. package/dist/schema-validation/semantic-validators/validation-context.d.ts.map +1 -0
  311. package/dist/schema-validation/semantic-validators/validation-context.js +13 -0
  312. package/dist/schema-validation/semantic-validators/validation-context.js.map +1 -0
  313. package/dist/styles-type-analyzer.d.ts +64 -0
  314. package/dist/styles-type-analyzer.d.ts.map +1 -0
  315. package/dist/styles-type-analyzer.js +242 -0
  316. package/dist/styles-type-analyzer.js.map +1 -0
  317. package/dist/type-context.d.ts +184 -0
  318. package/dist/type-context.d.ts.map +1 -0
  319. package/dist/type-context.js +415 -0
  320. package/dist/type-context.js.map +1 -0
  321. package/dist/type-inference-engine.d.ts +181 -0
  322. package/dist/type-inference-engine.d.ts.map +1 -0
  323. package/dist/type-inference-engine.js +1151 -0
  324. package/dist/type-inference-engine.js.map +1 -0
  325. package/dist/type-rules/type-compatibility-rule.d.ts +85 -0
  326. package/dist/type-rules/type-compatibility-rule.d.ts.map +1 -0
  327. package/dist/type-rules/type-compatibility-rule.js +211 -0
  328. package/dist/type-rules/type-compatibility-rule.js.map +1 -0
  329. package/package.json +35 -7
  330. package/README.md +0 -45
@@ -0,0 +1,1151 @@
1
+ /**
2
+ * Type Inference Engine - AST-based type inference for component linting
3
+ *
4
+ * This module analyzes JavaScript AST to infer and track types throughout
5
+ * component code. It integrates with TypeContext to provide comprehensive
6
+ * type information for validation rules.
7
+ */
8
+ import _traverse from '@babel/traverse';
9
+ import * as t from '@babel/types';
10
+ const traverse = ((_traverse.default) ?? _traverse);
11
+ import { TypeContext, StandardTypes, mapSQLTypeToJSType, areTypesCompatible } from './type-context.js';
12
+ /**
13
+ * TypeInferenceEngine - Analyzes AST to infer and track types
14
+ */
15
+ export class TypeInferenceEngine {
16
+ constructor(componentSpec, contextUser) {
17
+ this.errors = [];
18
+ this.functionReturnTypes = new Map();
19
+ /** Maps setState setter names to their corresponding state variable names */
20
+ this.stateSetterMap = new Map();
21
+ this.componentSpec = componentSpec;
22
+ this.contextUser = contextUser;
23
+ this.typeContext = new TypeContext(componentSpec);
24
+ }
25
+ /**
26
+ * Analyze an AST and build type context
27
+ */
28
+ async analyze(ast) {
29
+ this.errors = [];
30
+ // First pass: collect all variable declarations and their types
31
+ await this.collectVariableTypes(ast);
32
+ // Return the result
33
+ return {
34
+ typeContext: this.typeContext,
35
+ errors: this.errors
36
+ };
37
+ }
38
+ /**
39
+ * Get the type context after analysis
40
+ */
41
+ getTypeContext() {
42
+ return this.typeContext;
43
+ }
44
+ /**
45
+ * Get type inference errors found during analysis
46
+ */
47
+ getErrors() {
48
+ return this.errors;
49
+ }
50
+ /**
51
+ * First pass: collect variable types from declarations and assignments
52
+ */
53
+ async collectVariableTypes(ast) {
54
+ const self = this;
55
+ let functionCounter = 0; // Counter for anonymous functions
56
+ traverse(ast, {
57
+ // Track variable declarations
58
+ VariableDeclarator(path) {
59
+ self.inferDeclaratorType(path);
60
+ // Also check if it's a function expression assignment
61
+ // const calculateMetrics = () => { return {...} }
62
+ const node = path.node;
63
+ if (t.isIdentifier(node.id) &&
64
+ (t.isArrowFunctionExpression(node.init) || t.isFunctionExpression(node.init))) {
65
+ self.trackFunctionReturnType(node.id.name, node.init);
66
+ }
67
+ },
68
+ // Track assignments to existing variables
69
+ AssignmentExpression(path) {
70
+ self.inferAssignmentType(path);
71
+ },
72
+ // Track setState calls to update state variable types
73
+ CallExpression(path) {
74
+ if (t.isIdentifier(path.node.callee)) {
75
+ const setterName = path.node.callee.name;
76
+ const stateVarName = self.stateSetterMap.get(setterName);
77
+ if (stateVarName && path.node.arguments.length > 0) {
78
+ const argType = self.inferExpressionType(path.node.arguments[0], path);
79
+ // Only update if we inferred a meaningful type (not unknown)
80
+ if (argType.type !== 'unknown') {
81
+ self.typeContext.setVariableType(stateVarName, argType);
82
+ }
83
+ }
84
+ }
85
+ },
86
+ // Track function parameters and return types with scoping
87
+ FunctionDeclaration: {
88
+ enter(path) {
89
+ const functionName = path.node.id?.name || `anon_func_${functionCounter++}`;
90
+ self.typeContext.enterScope(functionName);
91
+ self.inferFunctionParameterTypes(path);
92
+ // Track return type of named functions
93
+ if (path.node.id) {
94
+ self.trackFunctionReturnType(path.node.id.name, path.node);
95
+ }
96
+ },
97
+ exit(path) {
98
+ self.typeContext.exitScope();
99
+ }
100
+ },
101
+ // Track arrow function scoping
102
+ ArrowFunctionExpression: {
103
+ enter(path) {
104
+ // Find the function name from parent if it's a variable declarator
105
+ let functionName = `anon_arrow_${functionCounter++}`;
106
+ const parent = path.parent;
107
+ if (t.isVariableDeclarator(parent) && t.isIdentifier(parent.id)) {
108
+ functionName = parent.id.name;
109
+ }
110
+ self.typeContext.enterScope(functionName);
111
+ // Try to infer callback parameter types from array method context first
112
+ const inferredFromCallback = self.inferCallbackParameterTypes(path);
113
+ if (!inferredFromCallback) {
114
+ self.inferArrowFunctionParameterTypes(path);
115
+ }
116
+ },
117
+ exit(path) {
118
+ self.typeContext.exitScope();
119
+ }
120
+ },
121
+ // Track function expression scoping
122
+ FunctionExpression: {
123
+ enter(path) {
124
+ const functionName = path.node.id?.name || `anon_func_expr_${functionCounter++}`;
125
+ self.typeContext.enterScope(functionName);
126
+ },
127
+ exit(path) {
128
+ self.typeContext.exitScope();
129
+ }
130
+ }
131
+ });
132
+ }
133
+ /**
134
+ * Infer type from a variable declarator
135
+ */
136
+ inferDeclaratorType(path) {
137
+ const node = path.node;
138
+ // Get variable name(s)
139
+ if (t.isIdentifier(node.id)) {
140
+ const varName = node.id.name;
141
+ if (node.init) {
142
+ const type = this.inferExpressionType(node.init, path);
143
+ this.typeContext.setVariableType(varName, type);
144
+ }
145
+ else {
146
+ // Declared but not initialized
147
+ this.typeContext.setVariableType(varName, { type: 'undefined', nullable: true });
148
+ }
149
+ }
150
+ else if (t.isObjectPattern(node.id) && node.init) {
151
+ // Destructuring: const { a, b } = obj
152
+ this.inferDestructuringTypes(node.id, node.init, path);
153
+ }
154
+ else if (t.isArrayPattern(node.id) && node.init) {
155
+ // Array destructuring: const [a, b] = arr
156
+ this.inferArrayDestructuringTypes(node.id, node.init, path);
157
+ }
158
+ }
159
+ /**
160
+ * Infer type from an assignment expression
161
+ */
162
+ inferAssignmentType(path) {
163
+ const node = path.node;
164
+ if (t.isIdentifier(node.left)) {
165
+ const varName = node.left.name;
166
+ const type = this.inferExpressionType(node.right, path);
167
+ this.typeContext.setVariableType(varName, type);
168
+ }
169
+ }
170
+ /**
171
+ * Infer types for function parameters (component props)
172
+ */
173
+ inferFunctionParameterTypes(path) {
174
+ const params = path.node.params;
175
+ for (const param of params) {
176
+ if (t.isIdentifier(param)) {
177
+ // Simple parameter - unknown type
178
+ this.typeContext.setVariableType(param.name, StandardTypes.unknown);
179
+ }
180
+ else if (t.isObjectPattern(param)) {
181
+ // Destructured props - this is the common component pattern
182
+ this.inferComponentPropsTypes(param);
183
+ }
184
+ }
185
+ }
186
+ /**
187
+ * Infer callback parameter types from array method context.
188
+ * When an arrow function is a callback to .map(), .filter(), .reduce(), etc.,
189
+ * the first parameter inherits the array's element type.
190
+ *
191
+ * Example: results.map(m => m.Salary)
192
+ * → `results` is array of entity-row(Members) → `m` is entity-row(Members)
193
+ *
194
+ * Returns true if callback parameters were inferred, false if not applicable.
195
+ */
196
+ inferCallbackParameterTypes(path) {
197
+ const parent = path.parent;
198
+ // Check if this arrow function is the first argument to a method call
199
+ // Pattern: someArray.method(callback) or someArray?.method(callback)
200
+ if (!t.isCallExpression(parent) && !t.isOptionalCallExpression(parent))
201
+ return false;
202
+ if (parent.arguments[0] !== path.node && parent.arguments[1] !== path.node)
203
+ return false;
204
+ const callee = parent.callee;
205
+ if ((!t.isMemberExpression(callee) && !t.isOptionalMemberExpression(callee)) || !t.isIdentifier(callee.property))
206
+ return false;
207
+ const methodName = callee.property.name;
208
+ const arrayIterMethods = ['map', 'filter', 'forEach', 'find', 'some', 'every', 'flatMap', 'sort'];
209
+ const isReduce = methodName === 'reduce';
210
+ if (!arrayIterMethods.includes(methodName) && !isReduce)
211
+ return false;
212
+ // Infer the type of the array being iterated
213
+ const arrayType = this.inferExpressionType(callee.object, path.parentPath ?? undefined);
214
+ if (arrayType.type !== 'array' || !arrayType.arrayElementType)
215
+ return false;
216
+ const elementType = arrayType.arrayElementType;
217
+ const params = path.node.params;
218
+ if (isReduce) {
219
+ // reduce((accumulator, currentValue, index, array) => ...)
220
+ // First param is accumulator (unknown type), second param is the element
221
+ if (params.length >= 1 && t.isIdentifier(params[0])) {
222
+ this.typeContext.setVariableType(params[0].name, StandardTypes.unknown);
223
+ }
224
+ if (params.length >= 2 && t.isIdentifier(params[1])) {
225
+ this.typeContext.setVariableType(params[1].name, elementType);
226
+ }
227
+ }
228
+ else if (methodName === 'sort') {
229
+ // sort((a, b) => ...) — both params are elements
230
+ if (params.length >= 1 && t.isIdentifier(params[0])) {
231
+ this.typeContext.setVariableType(params[0].name, elementType);
232
+ }
233
+ if (params.length >= 2 && t.isIdentifier(params[1])) {
234
+ this.typeContext.setVariableType(params[1].name, elementType);
235
+ }
236
+ }
237
+ else {
238
+ // map/filter/forEach/find/some/every/flatMap: (element, index, array) => ...
239
+ if (params.length >= 1 && t.isIdentifier(params[0])) {
240
+ this.typeContext.setVariableType(params[0].name, elementType);
241
+ }
242
+ if (params.length >= 2 && t.isIdentifier(params[1])) {
243
+ this.typeContext.setVariableType(params[1].name, StandardTypes.number); // index
244
+ }
245
+ }
246
+ // Handle remaining params as unknown
247
+ for (let i = 2; i < params.length; i++) {
248
+ const param = params[i];
249
+ if (t.isIdentifier(param)) {
250
+ this.typeContext.setVariableType(param.name, StandardTypes.unknown);
251
+ }
252
+ }
253
+ return true;
254
+ }
255
+ /**
256
+ * Infer types for arrow function parameters
257
+ */
258
+ inferArrowFunctionParameterTypes(path) {
259
+ const params = path.node.params;
260
+ for (const param of params) {
261
+ if (t.isIdentifier(param)) {
262
+ this.typeContext.setVariableType(param.name, StandardTypes.unknown);
263
+ }
264
+ else if (t.isObjectPattern(param)) {
265
+ this.inferComponentPropsTypes(param);
266
+ }
267
+ }
268
+ }
269
+ /**
270
+ * Infer types for component props from destructuring pattern
271
+ */
272
+ inferComponentPropsTypes(pattern) {
273
+ for (const prop of pattern.properties) {
274
+ if (t.isObjectProperty(prop) && t.isIdentifier(prop.key)) {
275
+ const propName = prop.key.name;
276
+ // Known standard props
277
+ switch (propName) {
278
+ case 'utilities':
279
+ this.typeContext.setVariableType(propName, {
280
+ type: 'object',
281
+ fields: new Map([
282
+ ['rv', { type: 'object', fromMetadata: true }], // RunView service
283
+ ['rq', { type: 'object', fromMetadata: true }], // RunQuery service
284
+ ['md', { type: 'object', fromMetadata: true }] // Metadata
285
+ ])
286
+ });
287
+ break;
288
+ case 'styles':
289
+ this.typeContext.setVariableType(propName, { type: 'object' });
290
+ break;
291
+ case 'components':
292
+ this.typeContext.setVariableType(propName, { type: 'object' });
293
+ break;
294
+ case 'callbacks':
295
+ this.typeContext.setVariableType(propName, { type: 'object' });
296
+ break;
297
+ case 'savedUserSettings':
298
+ this.typeContext.setVariableType(propName, { type: 'object', nullable: true });
299
+ break;
300
+ case 'onSavedUserSettingsChange':
301
+ case 'onSaveUserSettings':
302
+ this.typeContext.setVariableType(propName, { type: 'function' });
303
+ break;
304
+ default:
305
+ // Check if it's a prop defined in the component spec
306
+ if (this.componentSpec?.properties) {
307
+ const specProp = this.componentSpec.properties.find(p => p.name === propName);
308
+ if (specProp) {
309
+ this.typeContext.setVariableType(propName, {
310
+ type: this.mapSpecTypeToJSType(specProp.type),
311
+ nullable: !specProp.required
312
+ });
313
+ break;
314
+ }
315
+ }
316
+ // Check if it's an event (on* prefix)
317
+ if (propName.startsWith('on')) {
318
+ this.typeContext.setVariableType(propName, { type: 'function', nullable: true });
319
+ }
320
+ else {
321
+ this.typeContext.setVariableType(propName, StandardTypes.unknown);
322
+ }
323
+ }
324
+ }
325
+ }
326
+ }
327
+ /**
328
+ * Track function return type by analyzing its body
329
+ */
330
+ trackFunctionReturnType(functionName, func) {
331
+ const body = func.body;
332
+ // Arrow function with expression body: () => ({...})
333
+ if (t.isExpression(body)) {
334
+ const returnType = this.inferExpressionType(body);
335
+ this.functionReturnTypes.set(functionName, returnType);
336
+ return;
337
+ }
338
+ // Function with block body - find return statements
339
+ if (t.isBlockStatement(body)) {
340
+ // Try to analyze the function body for object building patterns
341
+ const returnType = this.analyzeObjectBuildingPattern(body);
342
+ if (returnType) {
343
+ this.functionReturnTypes.set(functionName, returnType);
344
+ return;
345
+ }
346
+ // Fallback: Find the first return statement
347
+ for (const stmt of body.body) {
348
+ if (t.isReturnStatement(stmt) && stmt.argument) {
349
+ const inferredType = this.inferExpressionType(stmt.argument);
350
+ this.functionReturnTypes.set(functionName, inferredType);
351
+ return;
352
+ }
353
+ }
354
+ }
355
+ // No return statement found or void function
356
+ this.functionReturnTypes.set(functionName, StandardTypes.unknown);
357
+ }
358
+ /**
359
+ * Analyze common object-building patterns in function bodies
360
+ * Pattern: const obj = {}; forEach(...) { obj[key] = { prop: value } }; return obj;
361
+ */
362
+ analyzeObjectBuildingPattern(body) {
363
+ let objectVarName = null;
364
+ let objectElementType = null;
365
+ const debugEnabled = false;
366
+ // Look for: const obj = {}; ... obj[key] = { ... }; ... return obj;
367
+ for (const stmt of body.body) {
368
+ // Find variable declaration: const obj = {};
369
+ if (t.isVariableDeclaration(stmt)) {
370
+ for (const decl of stmt.declarations) {
371
+ if (t.isIdentifier(decl.id) && t.isObjectExpression(decl.init) && decl.init.properties.length === 0) {
372
+ objectVarName = decl.id.name;
373
+ if (debugEnabled)
374
+ console.log('[TypeInference] Found empty object declaration:', objectVarName);
375
+ }
376
+ }
377
+ }
378
+ // Look for forEach or for loops that populate the object
379
+ if (objectVarName && t.isExpressionStatement(stmt) && t.isCallExpression(stmt.expression)) {
380
+ const call = stmt.expression;
381
+ if (t.isMemberExpression(call.callee) &&
382
+ t.isIdentifier(call.callee.property) &&
383
+ call.callee.property.name === 'forEach' &&
384
+ call.arguments.length > 0) {
385
+ const callback = call.arguments[0];
386
+ if ((t.isArrowFunctionExpression(callback) || t.isFunctionExpression(callback)) &&
387
+ t.isBlockStatement(callback.body)) {
388
+ // Look for obj[something] = { ... } pattern inside forEach
389
+ for (const innerStmt of callback.body.body) {
390
+ if (t.isExpressionStatement(innerStmt) &&
391
+ t.isAssignmentExpression(innerStmt.expression) &&
392
+ innerStmt.expression.operator === '=') {
393
+ const left = innerStmt.expression.left;
394
+ const right = innerStmt.expression.right;
395
+ // Check if left is obj[...] and right is object literal
396
+ if (t.isMemberExpression(left) &&
397
+ left.computed &&
398
+ t.isIdentifier(left.object) &&
399
+ left.object.name === objectVarName &&
400
+ t.isObjectExpression(right)) {
401
+ // Infer the type of the object literal
402
+ objectElementType = this.inferObjectType(right);
403
+ if (debugEnabled)
404
+ console.log('[TypeInference] Found object literal assignment, inferred type:', objectElementType);
405
+ break;
406
+ }
407
+ }
408
+ }
409
+ }
410
+ }
411
+ }
412
+ // Check if this function returns the object
413
+ if (objectVarName && objectElementType && t.isReturnStatement(stmt)) {
414
+ if (t.isIdentifier(stmt.argument) && stmt.argument.name === objectVarName) {
415
+ // Function returns an object whose values are of the element type
416
+ const result = {
417
+ type: 'object',
418
+ fields: new Map(), // Dictionary, not structured object
419
+ objectValueType: objectElementType
420
+ };
421
+ if (debugEnabled)
422
+ console.log('[TypeInference] Returning object building pattern type:', result);
423
+ return result;
424
+ }
425
+ }
426
+ }
427
+ if (debugEnabled && objectVarName && objectElementType) {
428
+ console.log('[TypeInference] Had object and element type but no return statement matched');
429
+ }
430
+ return null;
431
+ }
432
+ /**
433
+ * Map component spec type to JavaScript type
434
+ */
435
+ mapSpecTypeToJSType(specType) {
436
+ if (!specType)
437
+ return 'unknown';
438
+ const type = specType.toLowerCase();
439
+ if (type === 'string')
440
+ return 'string';
441
+ if (type === 'number' || type === 'int' || type === 'integer' || type === 'float' || type === 'decimal')
442
+ return 'number';
443
+ if (type === 'boolean' || type === 'bool')
444
+ return 'boolean';
445
+ if (type.startsWith('array') || type.endsWith('[]'))
446
+ return 'array';
447
+ if (type === 'object')
448
+ return 'object';
449
+ if (type === 'function')
450
+ return 'function';
451
+ return 'unknown';
452
+ }
453
+ /**
454
+ * Infer types from object destructuring
455
+ */
456
+ inferDestructuringTypes(pattern, init, path) {
457
+ const sourceType = this.inferExpressionType(init, path);
458
+ for (const prop of pattern.properties) {
459
+ if (t.isObjectProperty(prop) && t.isIdentifier(prop.key)) {
460
+ const propName = prop.key.name;
461
+ const varName = t.isIdentifier(prop.value) ? prop.value.name : propName;
462
+ // Try to get the property type from the source
463
+ if (sourceType.fields?.has(propName)) {
464
+ const fieldType = sourceType.fields.get(propName);
465
+ this.typeContext.setVariableType(varName, { type: fieldType.type, nullable: fieldType.nullable });
466
+ }
467
+ else {
468
+ this.typeContext.setVariableType(varName, StandardTypes.unknown);
469
+ }
470
+ }
471
+ else if (t.isRestElement(prop) && t.isIdentifier(prop.argument)) {
472
+ // Rest element: const { a, ...rest } = obj
473
+ this.typeContext.setVariableType(prop.argument.name, { type: 'object' });
474
+ }
475
+ }
476
+ }
477
+ /**
478
+ * Infer types from array destructuring
479
+ */
480
+ inferArrayDestructuringTypes(pattern, init, path) {
481
+ const sourceType = this.inferExpressionType(init, path);
482
+ // Detect useState pattern: const [state, setState] = useState(initialValue)
483
+ const isUseState = t.isCallExpression(init) &&
484
+ t.isIdentifier(init.callee) && init.callee.name === 'useState';
485
+ for (let i = 0; i < pattern.elements.length; i++) {
486
+ const element = pattern.elements[i];
487
+ if (t.isIdentifier(element)) {
488
+ if (isUseState && i === 1) {
489
+ // Second element is the setter function — register the state/setter pair
490
+ this.typeContext.setVariableType(element.name, StandardTypes.function);
491
+ const stateVar = pattern.elements[0];
492
+ if (t.isIdentifier(stateVar)) {
493
+ this.stateSetterMap.set(element.name, stateVar.name);
494
+ }
495
+ }
496
+ else if (sourceType.arrayElementType) {
497
+ this.typeContext.setVariableType(element.name, sourceType.arrayElementType);
498
+ }
499
+ else {
500
+ this.typeContext.setVariableType(element.name, StandardTypes.unknown);
501
+ }
502
+ }
503
+ else if (t.isRestElement(element) && t.isIdentifier(element.argument)) {
504
+ // Rest element: const [a, ...rest] = arr
505
+ this.typeContext.setVariableType(element.argument.name, {
506
+ type: 'array',
507
+ arrayElementType: sourceType.arrayElementType
508
+ });
509
+ }
510
+ }
511
+ }
512
+ /**
513
+ * Infer the type of an expression
514
+ */
515
+ inferExpressionType(node, path) {
516
+ // Literals - now track actual values for constant analysis
517
+ if (t.isStringLiteral(node)) {
518
+ return { ...StandardTypes.string, literalValue: node.value };
519
+ }
520
+ if (t.isTemplateLiteral(node)) {
521
+ // For template literals, we can't always know the final value
522
+ return StandardTypes.string;
523
+ }
524
+ if (t.isNumericLiteral(node)) {
525
+ return { ...StandardTypes.number, literalValue: node.value };
526
+ }
527
+ if (t.isBooleanLiteral(node)) {
528
+ return { ...StandardTypes.boolean, literalValue: node.value };
529
+ }
530
+ if (t.isNullLiteral(node)) {
531
+ return { ...StandardTypes.null, literalValue: null };
532
+ }
533
+ if (t.isArrayExpression(node)) {
534
+ return this.inferArrayType(node, path);
535
+ }
536
+ if (t.isObjectExpression(node)) {
537
+ return this.inferObjectType(node, path);
538
+ }
539
+ // Identifiers (variable references)
540
+ if (t.isIdentifier(node)) {
541
+ return this.typeContext.getVariableType(node.name) || StandardTypes.unknown;
542
+ }
543
+ // Function expressions
544
+ if (t.isFunctionExpression(node) || t.isArrowFunctionExpression(node)) {
545
+ return StandardTypes.function;
546
+ }
547
+ // Call expressions (including optional: a?.b())
548
+ if (t.isCallExpression(node) || t.isOptionalCallExpression(node)) {
549
+ return this.inferCallExpressionType(node, path);
550
+ }
551
+ // New expressions (constructor calls like new Date())
552
+ if (t.isNewExpression(node)) {
553
+ return this.inferNewExpressionType(node, path);
554
+ }
555
+ // Member expressions (including optional chaining: a?.b, a?.[0])
556
+ if (t.isMemberExpression(node) || t.isOptionalMemberExpression(node)) {
557
+ return this.inferMemberExpressionType(node, path);
558
+ }
559
+ // Binary expressions
560
+ if (t.isBinaryExpression(node)) {
561
+ return this.inferBinaryExpressionType(node, path);
562
+ }
563
+ // Unary expressions
564
+ if (t.isUnaryExpression(node)) {
565
+ return this.inferUnaryExpressionType(node);
566
+ }
567
+ // Conditional (ternary) expressions
568
+ if (t.isConditionalExpression(node)) {
569
+ // Return the type of the consequent (or alternate if different, return unknown)
570
+ const consequentType = this.inferExpressionType(node.consequent, path);
571
+ const alternateType = this.inferExpressionType(node.alternate, path);
572
+ if (areTypesCompatible(consequentType, alternateType)) {
573
+ return consequentType;
574
+ }
575
+ return StandardTypes.unknown;
576
+ }
577
+ // Logical expressions (&&, ||, ??)
578
+ if (t.isLogicalExpression(node)) {
579
+ // For ||, the result is the first truthy value
580
+ // For &&, the result is the first falsy or last value
581
+ // For ??, the result is the first non-nullish value
582
+ return this.inferExpressionType(node.right, path);
583
+ }
584
+ // Await expressions
585
+ if (t.isAwaitExpression(node)) {
586
+ return this.inferExpressionType(node.argument, path);
587
+ }
588
+ return StandardTypes.unknown;
589
+ }
590
+ /**
591
+ * Infer type for array expressions
592
+ */
593
+ inferArrayType(node, path) {
594
+ if (node.elements.length === 0) {
595
+ return { type: 'array', arrayElementType: StandardTypes.unknown };
596
+ }
597
+ // Try to infer element type from first element
598
+ const firstElement = node.elements[0];
599
+ if (firstElement && !t.isSpreadElement(firstElement)) {
600
+ const elementType = this.inferExpressionType(firstElement, path);
601
+ return { type: 'array', arrayElementType: elementType };
602
+ }
603
+ return { type: 'array', arrayElementType: StandardTypes.unknown };
604
+ }
605
+ /**
606
+ * Infer type for object expressions
607
+ */
608
+ inferObjectType(node, path) {
609
+ const fields = new Map();
610
+ for (const prop of node.properties) {
611
+ // Handle spread elements: { ...otherObject, newProp: value }
612
+ if (t.isSpreadElement(prop)) {
613
+ const spreadType = this.inferExpressionType(prop.argument, path);
614
+ // If spreading an object, merge its fields into our fields map
615
+ if (spreadType.type === 'object' && spreadType.fields) {
616
+ for (const [fieldName, fieldInfo] of spreadType.fields.entries()) {
617
+ // Only add if not already present (later properties override spread)
618
+ if (!fields.has(fieldName)) {
619
+ fields.set(fieldName, fieldInfo);
620
+ }
621
+ }
622
+ }
623
+ }
624
+ // Handle regular object properties
625
+ else if (t.isObjectProperty(prop) && t.isIdentifier(prop.key)) {
626
+ const propName = prop.key.name;
627
+ const propType = this.inferExpressionType(prop.value, path);
628
+ fields.set(propName, {
629
+ type: propType.type,
630
+ fromMetadata: false,
631
+ nullable: propType.nullable
632
+ });
633
+ }
634
+ }
635
+ return { type: 'object', fields };
636
+ }
637
+ /**
638
+ * Infer type for call expressions
639
+ */
640
+ inferCallExpressionType(node, path) {
641
+ // Check for user-defined function calls
642
+ if (t.isIdentifier(node.callee)) {
643
+ const functionName = node.callee.name;
644
+ // Check if we've tracked this function's return type
645
+ const returnType = this.functionReturnTypes.get(functionName);
646
+ if (returnType) {
647
+ return returnType;
648
+ }
649
+ // Check for React hooks that return computed values
650
+ // useMemo(() => { return {...} }, [deps]) - returns the memoized value
651
+ if (functionName === 'useMemo' && node.arguments.length > 0) {
652
+ const callback = node.arguments[0];
653
+ // Extract the return type from the callback
654
+ if (t.isArrowFunctionExpression(callback) || t.isFunctionExpression(callback)) {
655
+ const body = callback.body;
656
+ // Arrow function with expression body: useMemo(() => ({...}))
657
+ if (t.isExpression(body)) {
658
+ return this.inferExpressionType(body, path);
659
+ }
660
+ // Arrow function with block body: useMemo(() => { return {...} })
661
+ if (t.isBlockStatement(body)) {
662
+ // Find return statement
663
+ for (const stmt of body.body) {
664
+ if (t.isReturnStatement(stmt) && stmt.argument) {
665
+ return this.inferExpressionType(stmt.argument, path);
666
+ }
667
+ }
668
+ }
669
+ }
670
+ }
671
+ // useCallback returns a function
672
+ if (functionName === 'useCallback') {
673
+ return StandardTypes.function;
674
+ }
675
+ // useState(initialValue) — return the type of the initial value so that
676
+ // array destructuring `const [state, setState] = useState(X)` propagates X's type to `state`
677
+ if (functionName === 'useState') {
678
+ if (node.arguments.length > 0) {
679
+ const initType = this.inferExpressionType(node.arguments[0], path);
680
+ // For null/undefined initializers, use unknown+nullable to avoid false positives
681
+ // (the actual type will be set by setState calls later)
682
+ if (initType.type === 'null' || initType.type === 'undefined') {
683
+ return { type: 'array', arrayElementType: { ...StandardTypes.unknown, nullable: true } };
684
+ }
685
+ return { type: 'array', arrayElementType: initType };
686
+ }
687
+ // useState() with no argument — state is undefined/nullable
688
+ return { type: 'array', arrayElementType: { ...StandardTypes.unknown, nullable: true } };
689
+ }
690
+ }
691
+ // Check for RunView/RunQuery calls
692
+ if (t.isMemberExpression(node.callee) || t.isOptionalMemberExpression(node.callee)) {
693
+ const calleeObj = node.callee.object;
694
+ const calleeProp = node.callee.property;
695
+ // utilities.rv.RunView or utilities.rv.RunViews
696
+ if ((t.isMemberExpression(calleeObj) || t.isOptionalMemberExpression(calleeObj)) &&
697
+ t.isIdentifier(calleeObj.property) &&
698
+ t.isIdentifier(calleeProp)) {
699
+ const serviceName = calleeObj.property.name;
700
+ const methodName = calleeProp.name;
701
+ if (serviceName === 'rv' && (methodName === 'RunView' || methodName === 'RunViews')) {
702
+ return this.inferRunViewResultType(node);
703
+ }
704
+ if (serviceName === 'rq' && methodName === 'RunQuery') {
705
+ return this.inferRunQueryResultType(node);
706
+ }
707
+ }
708
+ }
709
+ // Object.values() - returns array of object's values
710
+ if ((t.isMemberExpression(node.callee) || t.isOptionalMemberExpression(node.callee)) &&
711
+ t.isIdentifier(node.callee.object) &&
712
+ node.callee.object.name === 'Object' &&
713
+ t.isIdentifier(node.callee.property) &&
714
+ node.callee.property.name === 'values' &&
715
+ node.arguments.length === 1) {
716
+ const objectType = this.inferExpressionType(node.arguments[0], path);
717
+ if (objectType.type === 'object' && objectType.objectValueType) {
718
+ // Return array of the object's value type
719
+ return {
720
+ type: 'array',
721
+ arrayElementType: objectType.objectValueType
722
+ };
723
+ }
724
+ // Fallback: unknown array
725
+ return { type: 'array', arrayElementType: StandardTypes.unknown };
726
+ }
727
+ // Array methods that return arrays
728
+ if ((t.isMemberExpression(node.callee) || t.isOptionalMemberExpression(node.callee)) && t.isIdentifier(node.callee.property)) {
729
+ const methodName = node.callee.property.name;
730
+ const arrayMethods = ['filter', 'map', 'slice', 'concat', 'flat', 'flatMap', 'sort', 'reverse'];
731
+ if (arrayMethods.includes(methodName)) {
732
+ const arrayType = this.inferExpressionType(node.callee.object, path);
733
+ if (arrayType.type === 'array') {
734
+ // For map, the element type might change
735
+ if (methodName === 'map') {
736
+ return { type: 'array', arrayElementType: StandardTypes.unknown };
737
+ }
738
+ return arrayType;
739
+ }
740
+ }
741
+ // Array methods that return elements
742
+ if (methodName === 'find') {
743
+ const arrayType = this.inferExpressionType(node.callee.object, path);
744
+ if (arrayType.arrayElementType) {
745
+ return { ...arrayType.arrayElementType, nullable: true };
746
+ }
747
+ }
748
+ // Methods that return numbers
749
+ if (['indexOf', 'findIndex', 'length'].includes(methodName)) {
750
+ return StandardTypes.number;
751
+ }
752
+ // Methods that return booleans
753
+ if (['includes', 'some', 'every'].includes(methodName)) {
754
+ return StandardTypes.boolean;
755
+ }
756
+ }
757
+ return StandardTypes.unknown;
758
+ }
759
+ /**
760
+ * Infer type for new expressions (constructor calls)
761
+ */
762
+ inferNewExpressionType(node, path) {
763
+ // Check for common constructors
764
+ if (t.isIdentifier(node.callee)) {
765
+ const constructorName = node.callee.name;
766
+ // Date constructor
767
+ if (constructorName === 'Date') {
768
+ return { type: 'Date', fromMetadata: false };
769
+ }
770
+ // Array constructor
771
+ if (constructorName === 'Array') {
772
+ return { type: 'array', arrayElementType: StandardTypes.unknown };
773
+ }
774
+ // Object constructor
775
+ if (constructorName === 'Object') {
776
+ return { type: 'object', fields: new Map() };
777
+ }
778
+ // Map constructor
779
+ if (constructorName === 'Map') {
780
+ return { type: 'Map', fromMetadata: false };
781
+ }
782
+ // Set constructor
783
+ if (constructorName === 'Set') {
784
+ return { type: 'Set', fromMetadata: false };
785
+ }
786
+ // RegExp constructor
787
+ if (constructorName === 'RegExp') {
788
+ return { type: 'RegExp', fromMetadata: false };
789
+ }
790
+ // Error and related constructors
791
+ if (['Error', 'TypeError', 'RangeError', 'ReferenceError', 'SyntaxError'].includes(constructorName)) {
792
+ return { type: 'Error', fromMetadata: false };
793
+ }
794
+ }
795
+ return StandardTypes.unknown;
796
+ }
797
+ /**
798
+ * Infer type for RunView result
799
+ */
800
+ inferRunViewResultType(node) {
801
+ // Try to extract EntityName from the arguments
802
+ let entityName;
803
+ if (node.arguments.length > 0 && t.isObjectExpression(node.arguments[0])) {
804
+ for (const prop of node.arguments[0].properties) {
805
+ if (t.isObjectProperty(prop) &&
806
+ t.isIdentifier(prop.key) &&
807
+ prop.key.name === 'EntityName' &&
808
+ t.isStringLiteral(prop.value)) {
809
+ entityName = prop.value.value;
810
+ break;
811
+ }
812
+ }
813
+ }
814
+ return this.typeContext.createRunViewResultType(entityName || 'unknown');
815
+ }
816
+ /**
817
+ * Infer type for RunQuery result
818
+ */
819
+ inferRunQueryResultType(node) {
820
+ // Try to extract QueryName and Parameters from the arguments
821
+ let queryName;
822
+ let parametersNode;
823
+ if (node.arguments.length > 0 && t.isObjectExpression(node.arguments[0])) {
824
+ for (const prop of node.arguments[0].properties) {
825
+ if (t.isObjectProperty(prop) && t.isIdentifier(prop.key)) {
826
+ if (prop.key.name === 'QueryName' && t.isStringLiteral(prop.value)) {
827
+ queryName = prop.value.value;
828
+ }
829
+ else if (prop.key.name === 'Parameters' && t.isObjectExpression(prop.value)) {
830
+ parametersNode = prop.value;
831
+ }
832
+ }
833
+ }
834
+ }
835
+ // Validate query parameters if we have both queryName and parameters
836
+ if (queryName && parametersNode) {
837
+ this.validateQueryParameters(queryName, parametersNode);
838
+ }
839
+ return this.typeContext.createRunQueryResultType(queryName || 'unknown');
840
+ }
841
+ /**
842
+ * Validate query parameters, especially date parameters
843
+ */
844
+ validateQueryParameters(queryName, parametersNode) {
845
+ // Get the query definition from component spec
846
+ const query = this.componentSpec?.dataRequirements?.queries?.find(q => q.name === queryName);
847
+ if (!query?.parameters) {
848
+ return;
849
+ }
850
+ // Build a map of parameter types with isRequired flag
851
+ const paramTypeMap = new Map();
852
+ for (const param of query.parameters) {
853
+ const extParam = param;
854
+ if (extParam.type) {
855
+ paramTypeMap.set(param.name.toLowerCase(), {
856
+ type: mapSQLTypeToJSType(extParam.type),
857
+ sqlType: extParam.type,
858
+ isRequired: extParam.isRequired === true
859
+ });
860
+ }
861
+ }
862
+ // Validate each parameter value
863
+ for (const prop of parametersNode.properties) {
864
+ if (t.isObjectProperty(prop) && t.isIdentifier(prop.key)) {
865
+ const paramName = prop.key.name;
866
+ const paramTypeInfo = paramTypeMap.get(paramName.toLowerCase());
867
+ if (!paramTypeInfo) {
868
+ continue;
869
+ }
870
+ // Check for date/datetime types
871
+ const isDateType = ['date', 'datetime', 'datetime2', 'smalldatetime', 'datetimeoffset']
872
+ .includes(paramTypeInfo.sqlType.toLowerCase());
873
+ if (isDateType) {
874
+ // Handle string literals: StartDate: '2024-01-01'
875
+ if (t.isStringLiteral(prop.value)) {
876
+ this.validateDateParameter(paramName, prop.value.value, paramTypeInfo.isRequired, prop.loc);
877
+ }
878
+ // Handle variables: StartDate: effectiveStartDate
879
+ else if (t.isIdentifier(prop.value)) {
880
+ this.validateDateVariable(paramName, prop.value.name, paramTypeInfo.isRequired, prop.loc);
881
+ }
882
+ // Handle logical expressions: StartDate: startDate || appliedStartDate
883
+ else if (t.isLogicalExpression(prop.value)) {
884
+ // For logical expressions, check each operand
885
+ this.validateDateLogicalExpression(paramName, prop.value, paramTypeInfo.isRequired, prop.loc);
886
+ }
887
+ }
888
+ }
889
+ }
890
+ }
891
+ /**
892
+ * Validate a date variable used as a parameter
893
+ */
894
+ validateDateVariable(paramName, variableName, isRequired, loc) {
895
+ // Look up the variable type in the type context
896
+ const varType = this.typeContext.getVariableType(variableName);
897
+ if (!varType) {
898
+ // Variable type unknown - could be a function parameter with no type info
899
+ // We'll allow this for now (no warning)
900
+ return;
901
+ }
902
+ // Handle 'unknown' type - common with React useState(null)
903
+ if (varType.type === 'unknown') {
904
+ // For optional parameters, unknown is acceptable (likely React state)
905
+ // For required parameters, emit a warning suggesting validation
906
+ if (isRequired) {
907
+ this.errors.push({
908
+ type: 'warning',
909
+ message: `Parameter "${paramName}" is required but variable "${variableName}" has unknown type. If "${variableName}" comes from React state (useState), ensure it's validated before calling RunQuery. Add a guard: if (!${variableName}) { return; }`,
910
+ line: loc?.start.line || 0,
911
+ column: loc?.start.column || 0,
912
+ code: `// Add validation before RunQuery:\nif (!${variableName}) {\n return; // or show error to user\n}`
913
+ });
914
+ }
915
+ // For optional parameters with unknown type, allow silently
916
+ return;
917
+ }
918
+ // Check if the variable is typed as string (dates are passed as ISO strings)
919
+ if (varType.type !== 'string') {
920
+ this.errors.push({
921
+ type: 'error',
922
+ message: `Parameter "${paramName}" expects a date string, but variable "${variableName}" has type "${varType.type}". Date parameters must be ISO date strings (e.g., '2024-01-01').`,
923
+ line: loc?.start.line || 0,
924
+ column: loc?.start.column || 0,
925
+ code: `// Ensure ${variableName} contains a valid ISO date string`
926
+ });
927
+ return; // Stop further validation if type is wrong
928
+ }
929
+ // If we know the literal value (constant), validate it as a date string
930
+ if (varType.literalValue !== undefined && typeof varType.literalValue === 'string') {
931
+ this.validateDateParameter(paramName, varType.literalValue, isRequired, loc);
932
+ return; // Already validated the literal value
933
+ }
934
+ // If the variable is nullable and the parameter is required, flag it
935
+ if (isRequired && varType.nullable) {
936
+ this.errors.push({
937
+ type: 'error',
938
+ message: `Parameter "${paramName}" is required but variable "${variableName}" may be null/undefined. Ensure "${variableName}" always has a valid date value before calling RunQuery.`,
939
+ line: loc?.start.line || 0,
940
+ column: loc?.start.column || 0,
941
+ code: `// Add validation:\nif (!${variableName}) {\n throw new Error('${paramName} is required');\n}`
942
+ });
943
+ }
944
+ }
945
+ /**
946
+ * Validate a logical expression (e.g., startDate || appliedStartDate)
947
+ */
948
+ validateDateLogicalExpression(paramName, node, isRequired, loc) {
949
+ // For || (OR) expressions, validate that at least one operand provides a valid date
950
+ // For && (AND) expressions, validate the right operand (result of the expression)
951
+ // For ?? (nullish coalescing), validate the right operand (fallback value)
952
+ const operator = node.operator;
953
+ if (operator === '||' || operator === '??') {
954
+ // Validate both sides - if left is null/undefined, right will be used
955
+ if (t.isIdentifier(node.left)) {
956
+ this.validateDateVariable(paramName, node.left.name, false, loc); // Left can be nullable
957
+ }
958
+ else if (t.isStringLiteral(node.left)) {
959
+ this.validateDateParameter(paramName, node.left.value, false, loc);
960
+ }
961
+ if (t.isIdentifier(node.right)) {
962
+ this.validateDateVariable(paramName, node.right.name, isRequired, loc); // Right inherits requirement
963
+ }
964
+ else if (t.isStringLiteral(node.right)) {
965
+ this.validateDateParameter(paramName, node.right.value, isRequired, loc);
966
+ }
967
+ }
968
+ else if (operator === '&&') {
969
+ // For AND, only the right side matters as the result
970
+ if (t.isIdentifier(node.right)) {
971
+ this.validateDateVariable(paramName, node.right.name, isRequired, loc);
972
+ }
973
+ else if (t.isStringLiteral(node.right)) {
974
+ this.validateDateParameter(paramName, node.right.value, isRequired, loc);
975
+ }
976
+ }
977
+ }
978
+ /**
979
+ * Validate a date parameter value
980
+ */
981
+ validateDateParameter(paramName, value, isRequired, loc) {
982
+ // Empty strings are invalid for date parameters
983
+ if (value === '') {
984
+ let message;
985
+ let code;
986
+ if (isRequired) {
987
+ message = `Parameter "${paramName}" is required and must have a valid ISO date value (e.g., '2024-01-01'). Empty strings are not allowed.`;
988
+ code = `${paramName}: '2024-01-01' // Required parameter`;
989
+ }
990
+ else {
991
+ message = `Parameter "${paramName}" is an optional date parameter but has an empty string value. Either provide a valid ISO date (e.g., '2024-01-01') or omit the parameter entirely from the Parameters object.`;
992
+ code = `// Option 1: Provide valid date\n${paramName}: '2024-01-01'\n\n// Option 2: Remove parameter entirely\nParameters: {\n // ${paramName}: <omitted>\n}`;
993
+ }
994
+ this.errors.push({
995
+ type: 'error',
996
+ message,
997
+ line: loc?.start.line || 0,
998
+ column: loc?.start.column || 0,
999
+ code
1000
+ });
1001
+ return;
1002
+ }
1003
+ // Validate ISO date format: YYYY-MM-DD or YYYY-MM-DDTHH:MM:SS
1004
+ const isoDatePattern = /^\d{4}-\d{2}-\d{2}(T\d{2}:\d{2}:\d{2}(\.\d{3})?(Z|[+-]\d{2}:\d{2})?)?$/;
1005
+ if (!isoDatePattern.test(value)) {
1006
+ this.errors.push({
1007
+ type: 'error',
1008
+ message: `Parameter "${paramName}" is a date parameter but value '${value}' is not a valid ISO date format. Use YYYY-MM-DD or YYYY-MM-DDTHH:MM:SS format.`,
1009
+ line: loc?.start.line || 0,
1010
+ column: loc?.start.column || 0,
1011
+ code: `${paramName}: '2024-01-01' // or '2024-01-01T00:00:00'`
1012
+ });
1013
+ return;
1014
+ }
1015
+ // Validate that it's an actual valid date (not 2024-13-45)
1016
+ const parsedDate = new Date(value);
1017
+ if (isNaN(parsedDate.getTime())) {
1018
+ this.errors.push({
1019
+ type: 'error',
1020
+ message: `Parameter "${paramName}" has an invalid date value '${value}'. The date format is correct but the date itself is invalid (e.g., month > 12, day > 31).`,
1021
+ line: loc?.start.line || 0,
1022
+ column: loc?.start.column || 0,
1023
+ code: `${paramName}: '2024-01-01' // Use a valid date`
1024
+ });
1025
+ }
1026
+ }
1027
+ /**
1028
+ * Infer type for member expressions
1029
+ */
1030
+ inferMemberExpressionType(node, path) {
1031
+ const objectType = this.inferExpressionType(node.object, path);
1032
+ // Array index access
1033
+ if (node.computed && t.isNumericLiteral(node.property)) {
1034
+ if (objectType.arrayElementType) {
1035
+ return objectType.arrayElementType;
1036
+ }
1037
+ }
1038
+ // Property access
1039
+ if (t.isIdentifier(node.property)) {
1040
+ const propName = node.property.name;
1041
+ // Special case: .Results property on RunView/RunQuery result
1042
+ // Must be checked BEFORE generic field lookup, because FieldTypeInfo
1043
+ // can't carry arrayElementType (it's a simplified type), so the generic
1044
+ // lookup would return bare { type: 'array' } without entity-row info.
1045
+ if (propName === 'Results' && objectType.type === 'object') {
1046
+ if (objectType.entityName) {
1047
+ const entityFields = this.typeContext.getEntityFieldTypesSync(objectType.entityName);
1048
+ return {
1049
+ type: 'array',
1050
+ arrayElementType: {
1051
+ type: 'entity-row',
1052
+ entityName: objectType.entityName,
1053
+ fields: entityFields.size > 0 ? entityFields : undefined
1054
+ }
1055
+ };
1056
+ }
1057
+ if (objectType.queryName) {
1058
+ const queryFields = this.typeContext.getQueryFieldTypes(objectType.queryName);
1059
+ return {
1060
+ type: 'array',
1061
+ arrayElementType: {
1062
+ type: 'query-row',
1063
+ queryName: objectType.queryName,
1064
+ fields: queryFields ?? undefined
1065
+ }
1066
+ };
1067
+ }
1068
+ }
1069
+ // Check if the object has known fields
1070
+ if (objectType.fields?.has(propName)) {
1071
+ const field = objectType.fields.get(propName);
1072
+ return { type: field.type, nullable: field.nullable };
1073
+ }
1074
+ // Array length
1075
+ if (propName === 'length' && objectType.type === 'array') {
1076
+ return StandardTypes.number;
1077
+ }
1078
+ }
1079
+ return StandardTypes.unknown;
1080
+ }
1081
+ /**
1082
+ * Infer type for binary expressions
1083
+ */
1084
+ inferBinaryExpressionType(node, path) {
1085
+ const operator = node.operator;
1086
+ // Comparison operators always return boolean
1087
+ if (['==', '!=', '===', '!==', '<', '<=', '>', '>=', 'in', 'instanceof'].includes(operator)) {
1088
+ return StandardTypes.boolean;
1089
+ }
1090
+ // Arithmetic operators return number
1091
+ if (['-', '*', '/', '%', '**', '|', '&', '^', '<<', '>>', '>>>'].includes(operator)) {
1092
+ return StandardTypes.number;
1093
+ }
1094
+ // + can be string or number
1095
+ if (operator === '+') {
1096
+ // node.left can be PrivateName in some cases, skip type inference for those
1097
+ if (t.isPrivateName(node.left)) {
1098
+ return StandardTypes.unknown;
1099
+ }
1100
+ const leftType = this.inferExpressionType(node.left, path);
1101
+ const rightType = this.inferExpressionType(node.right, path);
1102
+ if (leftType.type === 'string' || rightType.type === 'string') {
1103
+ return StandardTypes.string;
1104
+ }
1105
+ if (leftType.type === 'number' && rightType.type === 'number') {
1106
+ return StandardTypes.number;
1107
+ }
1108
+ }
1109
+ return StandardTypes.unknown;
1110
+ }
1111
+ /**
1112
+ * Infer type for unary expressions
1113
+ */
1114
+ inferUnaryExpressionType(node) {
1115
+ const operator = node.operator;
1116
+ if (operator === '!') {
1117
+ return StandardTypes.boolean;
1118
+ }
1119
+ if (operator === 'typeof') {
1120
+ return StandardTypes.string;
1121
+ }
1122
+ if (['+', '-', '~'].includes(operator)) {
1123
+ return StandardTypes.number;
1124
+ }
1125
+ if (operator === 'void') {
1126
+ return StandardTypes.undefined;
1127
+ }
1128
+ return StandardTypes.unknown;
1129
+ }
1130
+ /**
1131
+ * Get inferred type for a variable by name
1132
+ */
1133
+ getVariableType(name) {
1134
+ return this.typeContext.getVariableType(name);
1135
+ }
1136
+ /**
1137
+ * Check if an expression is a specific type
1138
+ */
1139
+ isType(node, expectedType, path) {
1140
+ const actualType = this.inferExpressionType(node, path);
1141
+ return actualType.type === expectedType;
1142
+ }
1143
+ }
1144
+ /**
1145
+ * Convenience function to analyze an AST and return type context
1146
+ */
1147
+ export async function analyzeTypes(ast, componentSpec, contextUser) {
1148
+ const engine = new TypeInferenceEngine(componentSpec, contextUser);
1149
+ return engine.analyze(ast);
1150
+ }
1151
+ //# sourceMappingURL=type-inference-engine.js.map