@ttsc/lint 0.13.0 → 0.14.0-dev.20260528

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 (467) hide show
  1. package/README.md +948 -69
  2. package/lib/defaultFormat.d.ts +9 -6
  3. package/lib/defaultFormat.js +9 -6
  4. package/lib/defaultFormat.js.map +1 -1
  5. package/lib/index.d.ts +46 -0
  6. package/lib/index.js +60 -37
  7. package/lib/index.js.map +1 -1
  8. package/lib/structures/ITtscLintConfig.d.ts +12 -6
  9. package/lib/structures/{ITtscLintFormatConfig.d.ts → ITtscLintFormat.d.ts} +2 -2
  10. package/lib/structures/{TtscLintRuleMap.js → ITtscLintFormat.js} +1 -1
  11. package/lib/structures/ITtscLintFormat.js.map +1 -0
  12. package/lib/structures/TtscLintRuleSetting.d.ts +49 -0
  13. package/lib/structures/{TtscLintRuleOptions.js → TtscLintRuleSetting.js} +1 -1
  14. package/lib/structures/TtscLintRuleSetting.js.map +1 -0
  15. package/lib/structures/index.d.ts +3 -4
  16. package/lib/structures/index.js +3 -4
  17. package/lib/structures/index.js.map +1 -1
  18. package/lib/structures/rules/ITtscLintBoundariesRuleOptions.d.ts +104 -0
  19. package/lib/structures/rules/ITtscLintBoundariesRuleOptions.js +14 -0
  20. package/lib/structures/rules/ITtscLintBoundariesRuleOptions.js.map +1 -0
  21. package/lib/structures/rules/ITtscLintBoundariesRules.d.ts +79 -0
  22. package/lib/structures/rules/ITtscLintBoundariesRules.js +3 -0
  23. package/lib/structures/rules/ITtscLintBoundariesRules.js.map +1 -0
  24. package/lib/structures/rules/ITtscLintContributorRules.d.ts +17 -0
  25. package/lib/structures/rules/ITtscLintContributorRules.js +3 -0
  26. package/lib/structures/rules/ITtscLintContributorRules.js.map +1 -0
  27. package/lib/structures/rules/ITtscLintCoreRules.d.ts +1257 -0
  28. package/lib/structures/{ITtscLintFormatConfig.js → rules/ITtscLintCoreRules.js} +1 -1
  29. package/lib/structures/rules/ITtscLintCoreRules.js.map +1 -0
  30. package/lib/structures/rules/ITtscLintCypressRuleOptions.d.ts +17 -0
  31. package/lib/structures/rules/ITtscLintCypressRuleOptions.js +10 -0
  32. package/lib/structures/rules/ITtscLintCypressRuleOptions.js.map +1 -0
  33. package/lib/structures/rules/ITtscLintCypressRules.d.ts +129 -0
  34. package/lib/structures/rules/ITtscLintCypressRules.js +3 -0
  35. package/lib/structures/rules/ITtscLintCypressRules.js.map +1 -0
  36. package/lib/structures/rules/ITtscLintFunctionalRuleOptions.d.ts +157 -0
  37. package/lib/structures/rules/ITtscLintFunctionalRuleOptions.js +13 -0
  38. package/lib/structures/rules/ITtscLintFunctionalRuleOptions.js.map +1 -0
  39. package/lib/structures/rules/ITtscLintFunctionalRules.d.ts +167 -0
  40. package/lib/structures/rules/ITtscLintFunctionalRules.js +3 -0
  41. package/lib/structures/rules/ITtscLintFunctionalRules.js.map +1 -0
  42. package/lib/structures/rules/ITtscLintJestRules.d.ts +201 -0
  43. package/lib/structures/rules/ITtscLintJestRules.js +3 -0
  44. package/lib/structures/rules/ITtscLintJestRules.js.map +1 -0
  45. package/lib/structures/rules/ITtscLintJsdocRules.d.ts +140 -0
  46. package/lib/structures/rules/ITtscLintJsdocRules.js +3 -0
  47. package/lib/structures/rules/ITtscLintJsdocRules.js.map +1 -0
  48. package/lib/structures/rules/ITtscLintJsxA11yRules.d.ts +302 -0
  49. package/lib/structures/rules/ITtscLintJsxA11yRules.js +3 -0
  50. package/lib/structures/rules/ITtscLintJsxA11yRules.js.map +1 -0
  51. package/lib/structures/rules/ITtscLintNextjsRules.d.ts +185 -0
  52. package/lib/structures/rules/ITtscLintNextjsRules.js +3 -0
  53. package/lib/structures/rules/ITtscLintNextjsRules.js.map +1 -0
  54. package/lib/structures/rules/ITtscLintPlaywrightRules.d.ts +330 -0
  55. package/lib/structures/rules/ITtscLintPlaywrightRules.js +3 -0
  56. package/lib/structures/rules/ITtscLintPlaywrightRules.js.map +1 -0
  57. package/lib/structures/rules/ITtscLintPromiseRules.d.ts +188 -0
  58. package/lib/structures/rules/ITtscLintPromiseRules.js +3 -0
  59. package/lib/structures/rules/ITtscLintPromiseRules.js.map +1 -0
  60. package/lib/structures/rules/ITtscLintReactPerfRuleOptions.d.ts +18 -0
  61. package/lib/structures/rules/ITtscLintReactPerfRuleOptions.js +8 -0
  62. package/lib/structures/rules/ITtscLintReactPerfRuleOptions.js.map +1 -0
  63. package/lib/structures/rules/ITtscLintReactPerfRules.d.ts +51 -0
  64. package/lib/structures/rules/ITtscLintReactPerfRules.js +3 -0
  65. package/lib/structures/rules/ITtscLintReactPerfRules.js.map +1 -0
  66. package/lib/structures/rules/ITtscLintReactRuleOptions.d.ts +39 -0
  67. package/lib/structures/rules/ITtscLintReactRuleOptions.js +12 -0
  68. package/lib/structures/rules/ITtscLintReactRuleOptions.js.map +1 -0
  69. package/lib/structures/rules/ITtscLintReactRules.d.ts +289 -0
  70. package/lib/structures/rules/ITtscLintReactRules.js +3 -0
  71. package/lib/structures/rules/ITtscLintReactRules.js.map +1 -0
  72. package/lib/structures/rules/ITtscLintRegexpRules.d.ts +190 -0
  73. package/lib/structures/rules/ITtscLintRegexpRules.js +3 -0
  74. package/lib/structures/rules/ITtscLintRegexpRules.js.map +1 -0
  75. package/lib/structures/rules/ITtscLintRuleOptionsMap.d.ts +66 -0
  76. package/lib/structures/rules/ITtscLintRuleOptionsMap.js +3 -0
  77. package/lib/structures/rules/ITtscLintRuleOptionsMap.js.map +1 -0
  78. package/lib/structures/rules/ITtscLintRules.d.ts +55 -0
  79. package/lib/structures/{TtscLintRule.js → rules/ITtscLintRules.js} +1 -1
  80. package/lib/structures/rules/ITtscLintRules.js.map +1 -0
  81. package/lib/structures/rules/ITtscLintSecurityRules.d.ts +148 -0
  82. package/lib/structures/rules/ITtscLintSecurityRules.js +3 -0
  83. package/lib/structures/rules/ITtscLintSecurityRules.js.map +1 -0
  84. package/lib/structures/rules/ITtscLintSolidRules.d.ts +181 -0
  85. package/lib/structures/rules/ITtscLintSolidRules.js +3 -0
  86. package/lib/structures/rules/ITtscLintSolidRules.js.map +1 -0
  87. package/lib/structures/rules/ITtscLintStorybookRuleOptions.d.ts +21 -0
  88. package/lib/structures/rules/ITtscLintStorybookRuleOptions.js +9 -0
  89. package/lib/structures/rules/ITtscLintStorybookRuleOptions.js.map +1 -0
  90. package/lib/structures/rules/ITtscLintStorybookRules.d.ts +174 -0
  91. package/lib/structures/rules/ITtscLintStorybookRules.js +3 -0
  92. package/lib/structures/rules/ITtscLintStorybookRules.js.map +1 -0
  93. package/lib/structures/rules/ITtscLintTanstackQueryRules.d.ts +94 -0
  94. package/lib/structures/rules/ITtscLintTanstackQueryRules.js +3 -0
  95. package/lib/structures/rules/ITtscLintTanstackQueryRules.js.map +1 -0
  96. package/lib/structures/rules/ITtscLintTestingLibraryRuleOptions.d.ts +22 -0
  97. package/lib/structures/rules/ITtscLintTestingLibraryRuleOptions.js +10 -0
  98. package/lib/structures/rules/ITtscLintTestingLibraryRuleOptions.js.map +1 -0
  99. package/lib/structures/rules/ITtscLintTestingLibraryRules.d.ts +310 -0
  100. package/lib/structures/rules/ITtscLintTestingLibraryRules.js +3 -0
  101. package/lib/structures/rules/ITtscLintTestingLibraryRules.js.map +1 -0
  102. package/lib/structures/rules/ITtscLintTypeScriptRules.d.ts +1132 -0
  103. package/lib/structures/rules/ITtscLintTypeScriptRules.js +3 -0
  104. package/lib/structures/rules/ITtscLintTypeScriptRules.js.map +1 -0
  105. package/lib/structures/rules/ITtscLintUnicornRules.d.ts +997 -0
  106. package/lib/structures/rules/ITtscLintUnicornRules.js +3 -0
  107. package/lib/structures/rules/ITtscLintUnicornRules.js.map +1 -0
  108. package/lib/structures/rules/ITtscLintVitestRules.d.ts +141 -0
  109. package/lib/structures/rules/ITtscLintVitestRules.js +3 -0
  110. package/lib/structures/rules/ITtscLintVitestRules.js.map +1 -0
  111. package/lib/structures/rules/index.d.ts +31 -0
  112. package/lib/structures/rules/index.js +48 -0
  113. package/lib/structures/rules/index.js.map +1 -0
  114. package/linthost/ast_helpers.go +30 -5
  115. package/linthost/compile.go +33 -2
  116. package/linthost/config.go +48 -17
  117. package/linthost/config_format.go +9 -9
  118. package/linthost/directives.go +67 -25
  119. package/linthost/dispatch.go +14 -3
  120. package/linthost/engine.go +160 -40
  121. package/linthost/fix.go +2 -2
  122. package/linthost/flags_gen.go +17 -15
  123. package/linthost/host.go +40 -3
  124. package/linthost/lsp.go +747 -0
  125. package/linthost/print_dispatch.go +2 -2
  126. package/linthost/print_nodes_function.go +2 -2
  127. package/linthost/print_nodes_object.go +1 -1
  128. package/linthost/rule_names.go +14 -0
  129. package/linthost/rules_arrays.go +2 -2
  130. package/linthost/rules_boundaries.go +532 -0
  131. package/linthost/rules_camelcase.go +133 -0
  132. package/linthost/rules_complexity.go +94 -0
  133. package/linthost/rules_consistent_return.go +130 -0
  134. package/linthost/rules_console.go +1 -1
  135. package/linthost/rules_core_extra.go +739 -0
  136. package/linthost/rules_curly.go +70 -0
  137. package/linthost/rules_cypress.go +608 -0
  138. package/linthost/rules_debugger.go +2 -2
  139. package/linthost/rules_default_case.go +39 -0
  140. package/linthost/rules_default_case_last.go +46 -0
  141. package/linthost/rules_dupes.go +3 -3
  142. package/linthost/rules_empty.go +3 -3
  143. package/linthost/rules_escape.go +44 -24
  144. package/linthost/rules_eval.go +2 -2
  145. package/linthost/rules_finally.go +2 -2
  146. package/linthost/rules_format_jsdoc.go +1 -1
  147. package/linthost/rules_format_print_width.go +9 -9
  148. package/linthost/rules_format_quotes.go +1 -1
  149. package/linthost/rules_format_semi.go +1 -1
  150. package/linthost/rules_format_sort_imports.go +1 -1
  151. package/linthost/rules_format_trailing_comma.go +1 -1
  152. package/linthost/rules_functional.go +967 -0
  153. package/linthost/rules_gap.go +24 -45
  154. package/linthost/rules_grouped_accessor_pairs.go +87 -0
  155. package/linthost/rules_guard_for_in.go +198 -0
  156. package/linthost/rules_id_length.go +77 -0
  157. package/linthost/rules_imports.go +70 -2
  158. package/linthost/rules_init_declarations.go +53 -0
  159. package/linthost/rules_jest.go +618 -0
  160. package/linthost/rules_jsdoc.go +502 -0
  161. package/linthost/rules_jsx_a11y.go +1264 -0
  162. package/linthost/rules_logic.go +12 -12
  163. package/linthost/rules_loops.go +1 -1
  164. package/linthost/rules_max_classes_per_file.go +58 -0
  165. package/linthost/rules_max_depth.go +83 -0
  166. package/linthost/rules_max_lines.go +101 -0
  167. package/linthost/rules_max_lines_per_function.go +57 -0
  168. package/linthost/rules_max_nested_callbacks.go +61 -0
  169. package/linthost/rules_max_params.go +49 -0
  170. package/linthost/rules_max_statements.go +59 -0
  171. package/linthost/rules_misc.go +1 -1
  172. package/linthost/rules_nextjs.go +697 -0
  173. package/linthost/rules_no_else_return.go +75 -0
  174. package/linthost/rules_no_empty_named_blocks.go +91 -0
  175. package/linthost/rules_no_extend_native.go +51 -0
  176. package/linthost/rules_no_import_assign.go +140 -0
  177. package/linthost/rules_no_invalid_this.go +52 -0
  178. package/linthost/rules_no_loop_func.go +85 -0
  179. package/linthost/rules_no_magic_numbers.go +123 -0
  180. package/linthost/rules_no_mixed_operators.go +80 -0
  181. package/linthost/rules_no_param_reassign.go +98 -0
  182. package/linthost/rules_no_redeclare.go +270 -0
  183. package/linthost/rules_no_restricted_imports.go +105 -0
  184. package/linthost/rules_no_restricted_syntax.go +49 -0
  185. package/linthost/rules_no_shadow.go +147 -0
  186. package/linthost/rules_no_unreachable.go +77 -0
  187. package/linthost/rules_no_useless_assignment.go +120 -0
  188. package/linthost/rules_no_useless_constructor.go +245 -0
  189. package/linthost/rules_no_useless_return.go +51 -0
  190. package/linthost/rules_params.go +1 -1
  191. package/linthost/rules_playwright.go +788 -0
  192. package/linthost/rules_prefer_arrow_callback.go +124 -0
  193. package/linthost/rules_prefer_destructuring.go +98 -0
  194. package/linthost/rules_prefer_named_capture_group.go +129 -0
  195. package/linthost/rules_prefer_rest_params.go +94 -0
  196. package/linthost/rules_problems.go +41 -30
  197. package/linthost/rules_promise.go +1128 -73
  198. package/linthost/rules_protos.go +2 -2
  199. package/linthost/rules_react.go +773 -0
  200. package/linthost/rules_react_extras.go +227 -0
  201. package/linthost/rules_react_hooks.go +848 -0
  202. package/linthost/rules_react_perf.go +293 -0
  203. package/linthost/rules_react_refresh.go +583 -0
  204. package/linthost/rules_regexp.go +410 -0
  205. package/linthost/rules_security.go +830 -0
  206. package/linthost/rules_self.go +2 -2
  207. package/linthost/rules_solid.go +1073 -0
  208. package/linthost/rules_sort_imports.go +69 -0
  209. package/linthost/rules_sort_keys.go +134 -0
  210. package/linthost/rules_storybook.go +1176 -0
  211. package/linthost/rules_strings.go +4 -4
  212. package/linthost/rules_suggestions.go +38 -38
  213. package/linthost/rules_tanstack_query.go +844 -0
  214. package/linthost/rules_testing_library.go +1204 -0
  215. package/linthost/rules_throw.go +1 -1
  216. package/linthost/rules_ts.go +19 -19
  217. package/linthost/rules_ts_async.go +399 -0
  218. package/linthost/rules_ts_class_literal_property_style.go +115 -0
  219. package/linthost/rules_ts_consistent_type_exports.go +256 -0
  220. package/linthost/rules_ts_explicit_function_return_type.go +67 -0
  221. package/linthost/rules_ts_extra.go +155 -36
  222. package/linthost/rules_ts_no_base_to_string.go +218 -0
  223. package/linthost/rules_ts_no_confusing_void.go +72 -0
  224. package/linthost/rules_ts_no_deprecated.go +195 -0
  225. package/linthost/rules_ts_no_for_in_array.go +84 -0
  226. package/linthost/rules_ts_no_magic_numbers.go +124 -0
  227. package/linthost/rules_ts_no_meaningless_void_operator.go +84 -0
  228. package/linthost/rules_ts_no_misused_spread.go +104 -0
  229. package/linthost/rules_ts_no_redundant_type_constituents.go +113 -0
  230. package/linthost/rules_ts_no_restricted_types.go +62 -0
  231. package/linthost/rules_ts_no_unnecessary_boolean_literal_compare.go +129 -0
  232. package/linthost/rules_ts_no_unnecessary_condition.go +250 -0
  233. package/linthost/rules_ts_no_unnecessary_qualifier.go +118 -0
  234. package/linthost/rules_ts_no_unnecessary_template_expression.go +178 -0
  235. package/linthost/rules_ts_no_unnecessary_type_arguments.go +234 -0
  236. package/linthost/rules_ts_no_unnecessary_type_assertion.go +157 -0
  237. package/linthost/rules_ts_no_unsafe_argument.go +82 -0
  238. package/linthost/rules_ts_no_unsafe_assignment.go +102 -0
  239. package/linthost/rules_ts_no_unsafe_call.go +82 -0
  240. package/linthost/rules_ts_no_unsafe_enum_comparison.go +235 -0
  241. package/linthost/rules_ts_no_unsafe_member_access.go +58 -0
  242. package/linthost/rules_ts_no_unsafe_return.go +126 -0
  243. package/linthost/rules_ts_no_unsafe_unary_minus.go +81 -0
  244. package/linthost/rules_ts_no_useless_constructor.go +52 -0
  245. package/linthost/rules_ts_non_nullable_type_assertion_style.go +108 -0
  246. package/linthost/rules_ts_parameter_properties.go +38 -0
  247. package/linthost/rules_ts_prefer_find.go +178 -0
  248. package/linthost/rules_ts_prefer_includes.go +255 -0
  249. package/linthost/rules_ts_prefer_nullish_coalescing.go +104 -0
  250. package/linthost/rules_ts_prefer_optional_chain.go +228 -0
  251. package/linthost/rules_ts_prefer_promise_reject_errors.go +176 -0
  252. package/linthost/rules_ts_prefer_readonly.go +73 -0
  253. package/linthost/rules_ts_prefer_reduce_type_parameter.go +116 -0
  254. package/linthost/rules_ts_prefer_regexp_exec.go +122 -0
  255. package/linthost/rules_ts_prefer_return_this_type.go +135 -0
  256. package/linthost/rules_ts_prefer_string_starts_ends_with.go +360 -0
  257. package/linthost/rules_ts_promise_function_async.go +77 -0
  258. package/linthost/rules_ts_related_getter_setter_pairs.go +113 -0
  259. package/linthost/rules_ts_require_array_sort_compare.go +96 -0
  260. package/linthost/rules_ts_restrict_plus_operands.go +127 -0
  261. package/linthost/rules_ts_restrict_template_expressions.go +95 -0
  262. package/linthost/rules_ts_simple.go +387 -0
  263. package/linthost/rules_ts_sort_type_constituents.go +144 -0
  264. package/linthost/rules_ts_strict_boolean_expressions.go +157 -0
  265. package/linthost/rules_ts_switch_exhaustiveness_check.go +147 -0
  266. package/linthost/rules_ts_unbound_method.go +126 -0
  267. package/linthost/rules_tsdoc.go +136 -0
  268. package/linthost/rules_unicorn_better_regex.go +27 -0
  269. package/linthost/rules_unicorn_catch_error_name.go +46 -0
  270. package/linthost/rules_unicorn_consistent_assert.go +47 -0
  271. package/linthost/rules_unicorn_consistent_date_clone.go +54 -0
  272. package/linthost/rules_unicorn_consistent_destructuring.go +25 -0
  273. package/linthost/rules_unicorn_consistent_empty_array_spread.go +62 -0
  274. package/linthost/rules_unicorn_consistent_existence_index_check.go +80 -0
  275. package/linthost/rules_unicorn_consistent_function_scoping.go +25 -0
  276. package/linthost/rules_unicorn_consistent_template_literal_escape.go +25 -0
  277. package/linthost/rules_unicorn_custom_error_definition.go +138 -0
  278. package/linthost/rules_unicorn_empty_brace_spaces.go +73 -0
  279. package/linthost/rules_unicorn_error_message.go +64 -0
  280. package/linthost/rules_unicorn_escape_case.go +51 -0
  281. package/linthost/rules_unicorn_expiring_todo_comments.go +78 -0
  282. package/linthost/rules_unicorn_explicit_length_check.go +88 -0
  283. package/linthost/rules_unicorn_filename_case.go +29 -0
  284. package/linthost/rules_unicorn_import_style.go +28 -0
  285. package/linthost/rules_unicorn_isolated_functions.go +29 -0
  286. package/linthost/rules_unicorn_new_for_builtins.go +87 -0
  287. package/linthost/rules_unicorn_no_abusive_eslint_disable.go +63 -0
  288. package/linthost/rules_unicorn_no_accessor_recursion.go +115 -0
  289. package/linthost/rules_unicorn_no_anonymous_default_export.go +74 -0
  290. package/linthost/rules_unicorn_no_array_callback_reference.go +65 -0
  291. package/linthost/rules_unicorn_no_array_for_each.go +40 -0
  292. package/linthost/rules_unicorn_no_array_method_this_argument.go +61 -0
  293. package/linthost/rules_unicorn_no_array_reduce.go +41 -0
  294. package/linthost/rules_unicorn_no_array_reverse.go +44 -0
  295. package/linthost/rules_unicorn_no_array_sort.go +43 -0
  296. package/linthost/rules_unicorn_no_await_expression_member.go +40 -0
  297. package/linthost/rules_unicorn_no_await_in_promise_methods.go +69 -0
  298. package/linthost/rules_unicorn_no_console_spaces.go +61 -0
  299. package/linthost/rules_unicorn_no_document_cookie.go +41 -0
  300. package/linthost/rules_unicorn_no_empty_file.go +44 -0
  301. package/linthost/rules_unicorn_no_for_loop.go +102 -0
  302. package/linthost/rules_unicorn_no_hex_escape.go +42 -0
  303. package/linthost/rules_unicorn_no_immediate_mutation.go +90 -0
  304. package/linthost/rules_unicorn_no_instanceof_builtins.go +66 -0
  305. package/linthost/rules_unicorn_no_invalid_fetch_options.go +79 -0
  306. package/linthost/rules_unicorn_no_invalid_remove_event_listener.go +51 -0
  307. package/linthost/rules_unicorn_no_keyword_prefix.go +101 -0
  308. package/linthost/rules_unicorn_no_lonely_if.go +44 -0
  309. package/linthost/rules_unicorn_no_magic_array_flat_depth.go +51 -0
  310. package/linthost/rules_unicorn_no_named_default.go +54 -0
  311. package/linthost/rules_unicorn_no_negated_condition.go +85 -0
  312. package/linthost/rules_unicorn_no_negation_in_equality_check.go +50 -0
  313. package/linthost/rules_unicorn_no_nested_ternary.go +43 -0
  314. package/linthost/rules_unicorn_no_new_array.go +30 -0
  315. package/linthost/rules_unicorn_no_new_buffer.go +31 -0
  316. package/linthost/rules_unicorn_no_null.go +24 -0
  317. package/linthost/rules_unicorn_no_object_as_default_parameter.go +48 -0
  318. package/linthost/rules_unicorn_no_process_exit.go +43 -0
  319. package/linthost/rules_unicorn_no_single_promise_in_promise_methods.go +59 -0
  320. package/linthost/rules_unicorn_no_static_only_class.go +56 -0
  321. package/linthost/rules_unicorn_no_thenable.go +74 -0
  322. package/linthost/rules_unicorn_no_this_assignment.go +35 -0
  323. package/linthost/rules_unicorn_no_typeof_undefined.go +58 -0
  324. package/linthost/rules_unicorn_no_unnecessary_array_flat_depth.go +49 -0
  325. package/linthost/rules_unicorn_no_unnecessary_array_splice_count.go +70 -0
  326. package/linthost/rules_unicorn_no_unnecessary_await.go +51 -0
  327. package/linthost/rules_unicorn_no_unnecessary_polyfills.go +32 -0
  328. package/linthost/rules_unicorn_no_unnecessary_slice_end.go +48 -0
  329. package/linthost/rules_unicorn_no_unreadable_array_destructuring.go +115 -0
  330. package/linthost/rules_unicorn_no_unreadable_iife.go +50 -0
  331. package/linthost/rules_unicorn_no_unused_properties.go +30 -0
  332. package/linthost/rules_unicorn_no_useless_collection_argument.go +63 -0
  333. package/linthost/rules_unicorn_no_useless_error_capture_stack_trace.go +46 -0
  334. package/linthost/rules_unicorn_no_useless_fallback_in_spread.go +81 -0
  335. package/linthost/rules_unicorn_no_useless_iterator_to_array.go +72 -0
  336. package/linthost/rules_unicorn_no_useless_length_check.go +144 -0
  337. package/linthost/rules_unicorn_no_useless_promise_resolve_reject.go +81 -0
  338. package/linthost/rules_unicorn_no_useless_spread.go +67 -0
  339. package/linthost/rules_unicorn_no_useless_switch_case.go +55 -0
  340. package/linthost/rules_unicorn_no_useless_undefined.go +55 -0
  341. package/linthost/rules_unicorn_no_zero_fractions.go +52 -0
  342. package/linthost/rules_unicorn_number_literal_case.go +69 -0
  343. package/linthost/rules_unicorn_numeric_separators_style.go +75 -0
  344. package/linthost/rules_unicorn_prefer_add_event_listener.go +66 -0
  345. package/linthost/rules_unicorn_prefer_array_find.go +51 -0
  346. package/linthost/rules_unicorn_prefer_array_flat.go +52 -0
  347. package/linthost/rules_unicorn_prefer_array_flat_map.go +63 -0
  348. package/linthost/rules_unicorn_prefer_array_index_of.go +147 -0
  349. package/linthost/rules_unicorn_prefer_array_some.go +67 -0
  350. package/linthost/rules_unicorn_prefer_at.go +77 -0
  351. package/linthost/rules_unicorn_prefer_bigint_literals.go +77 -0
  352. package/linthost/rules_unicorn_prefer_blob_reading_methods.go +44 -0
  353. package/linthost/rules_unicorn_prefer_class_fields.go +93 -0
  354. package/linthost/rules_unicorn_prefer_classlist_toggle.go +120 -0
  355. package/linthost/rules_unicorn_prefer_code_point.go +49 -0
  356. package/linthost/rules_unicorn_prefer_date_now.go +78 -0
  357. package/linthost/rules_unicorn_prefer_default_parameters.go +144 -0
  358. package/linthost/rules_unicorn_prefer_dom_node_append.go +40 -0
  359. package/linthost/rules_unicorn_prefer_dom_node_dataset.go +55 -0
  360. package/linthost/rules_unicorn_prefer_dom_node_remove.go +41 -0
  361. package/linthost/rules_unicorn_prefer_dom_node_text_content.go +37 -0
  362. package/linthost/rules_unicorn_prefer_event_target.go +36 -0
  363. package/linthost/rules_unicorn_prefer_export_from.go +129 -0
  364. package/linthost/rules_unicorn_prefer_global_this.go +127 -0
  365. package/linthost/rules_unicorn_prefer_import_meta_properties.go +66 -0
  366. package/linthost/rules_unicorn_prefer_includes.go +149 -0
  367. package/linthost/rules_unicorn_prefer_json_parse_buffer.go +65 -0
  368. package/linthost/rules_unicorn_prefer_keyboard_event_key.go +38 -0
  369. package/linthost/rules_unicorn_prefer_logical_operator_over_ternary.go +48 -0
  370. package/linthost/rules_unicorn_prefer_math_min_max.go +60 -0
  371. package/linthost/rules_unicorn_prefer_math_trunc.go +62 -0
  372. package/linthost/rules_unicorn_prefer_modern_dom_apis.go +47 -0
  373. package/linthost/rules_unicorn_prefer_modern_math_apis.go +70 -0
  374. package/linthost/rules_unicorn_prefer_module.go +50 -0
  375. package/linthost/rules_unicorn_prefer_native_coercion_functions.go +114 -0
  376. package/linthost/rules_unicorn_prefer_negative_index.go +74 -0
  377. package/linthost/rules_unicorn_prefer_node_protocol.go +122 -0
  378. package/linthost/rules_unicorn_prefer_number_properties.go +88 -0
  379. package/linthost/rules_unicorn_prefer_object_from_entries.go +55 -0
  380. package/linthost/rules_unicorn_prefer_optional_catch_binding.go +62 -0
  381. package/linthost/rules_unicorn_prefer_prototype_methods.go +54 -0
  382. package/linthost/rules_unicorn_prefer_query_selector.go +56 -0
  383. package/linthost/rules_unicorn_prefer_reflect_apply.go +36 -0
  384. package/linthost/rules_unicorn_prefer_regexp_test_rule.go +80 -0
  385. package/linthost/rules_unicorn_prefer_response_static_json.go +53 -0
  386. package/linthost/rules_unicorn_prefer_set_has.go +42 -0
  387. package/linthost/rules_unicorn_prefer_set_size.go +48 -0
  388. package/linthost/rules_unicorn_prefer_simple_condition_first.go +34 -0
  389. package/linthost/rules_unicorn_prefer_single_call.go +96 -0
  390. package/linthost/rules_unicorn_prefer_spread.go +51 -0
  391. package/linthost/rules_unicorn_prefer_string_raw.go +43 -0
  392. package/linthost/rules_unicorn_prefer_string_replace_all.go +95 -0
  393. package/linthost/rules_unicorn_prefer_string_slice.go +43 -0
  394. package/linthost/rules_unicorn_prefer_string_starts_ends_with.go +148 -0
  395. package/linthost/rules_unicorn_prefer_string_trim_start_end.go +48 -0
  396. package/linthost/rules_unicorn_prefer_structured_clone.go +71 -0
  397. package/linthost/rules_unicorn_prefer_switch.go +103 -0
  398. package/linthost/rules_unicorn_prefer_ternary.go +71 -0
  399. package/linthost/rules_unicorn_prefer_top_level_await.go +72 -0
  400. package/linthost/rules_unicorn_prefer_type_error.go +127 -0
  401. package/linthost/rules_unicorn_prevent_abbreviations.go +127 -0
  402. package/linthost/rules_unicorn_relative_url_style.go +49 -0
  403. package/linthost/rules_unicorn_require_array_join_separator.go +45 -0
  404. package/linthost/rules_unicorn_require_module_attributes.go +54 -0
  405. package/linthost/rules_unicorn_require_module_specifiers.go +55 -0
  406. package/linthost/rules_unicorn_require_number_to_fixed_digits_argument.go +43 -0
  407. package/linthost/rules_unicorn_require_post_message_target_origin.go +44 -0
  408. package/linthost/rules_unicorn_string_content.go +27 -0
  409. package/linthost/rules_unicorn_switch_case_braces.go +42 -0
  410. package/linthost/rules_unicorn_switch_case_break_position.go +31 -0
  411. package/linthost/rules_unicorn_template_indent.go +28 -0
  412. package/linthost/rules_unicorn_text_encoding_identifier_case.go +72 -0
  413. package/linthost/rules_unicorn_throw_new_error.go +61 -0
  414. package/linthost/rules_var.go +10 -4
  415. package/linthost/rules_vitest.go +568 -0
  416. package/package.json +3 -3
  417. package/plugin/main.go +49 -3
  418. package/rule/astutil/astutil.go +10 -3
  419. package/rule/rule.go +12 -10
  420. package/src/defaultFormat.ts +11 -8
  421. package/src/index.ts +65 -43
  422. package/src/structures/ITtscLintConfig.ts +12 -6
  423. package/src/structures/{ITtscLintFormatConfig.ts → ITtscLintFormat.ts} +2 -2
  424. package/src/structures/TtscLintRuleSetting.ts +55 -0
  425. package/src/structures/index.ts +3 -4
  426. package/src/structures/rules/ITtscLintBoundariesRuleOptions.ts +128 -0
  427. package/src/structures/rules/ITtscLintBoundariesRules.ts +95 -0
  428. package/src/structures/rules/ITtscLintContributorRules.ts +21 -0
  429. package/src/structures/rules/ITtscLintCoreRules.ts +1406 -0
  430. package/src/structures/rules/ITtscLintCypressRuleOptions.ts +18 -0
  431. package/src/structures/rules/ITtscLintCypressRules.ts +145 -0
  432. package/src/structures/rules/ITtscLintFunctionalRuleOptions.ts +213 -0
  433. package/src/structures/rules/ITtscLintFunctionalRules.ts +202 -0
  434. package/src/structures/rules/ITtscLintJestRules.ts +220 -0
  435. package/src/structures/rules/ITtscLintJsdocRules.ts +153 -0
  436. package/src/structures/rules/ITtscLintJsxA11yRules.ts +339 -0
  437. package/src/structures/rules/ITtscLintNextjsRules.ts +206 -0
  438. package/src/structures/rules/ITtscLintPlaywrightRules.ts +361 -0
  439. package/src/structures/rules/ITtscLintPromiseRules.ts +205 -0
  440. package/src/structures/rules/ITtscLintReactPerfRuleOptions.ts +19 -0
  441. package/src/structures/rules/ITtscLintReactPerfRules.ts +55 -0
  442. package/src/structures/rules/ITtscLintReactRuleOptions.ts +43 -0
  443. package/src/structures/rules/ITtscLintReactRules.ts +321 -0
  444. package/src/structures/rules/ITtscLintRegexpRules.ts +212 -0
  445. package/src/structures/rules/ITtscLintRuleOptionsMap.ts +89 -0
  446. package/src/structures/rules/ITtscLintRules.ts +77 -0
  447. package/src/structures/rules/ITtscLintSecurityRules.ts +162 -0
  448. package/src/structures/rules/ITtscLintSolidRules.ts +202 -0
  449. package/src/structures/rules/ITtscLintStorybookRuleOptions.ts +23 -0
  450. package/src/structures/rules/ITtscLintStorybookRules.ts +193 -0
  451. package/src/structures/rules/ITtscLintTanstackQueryRules.ts +102 -0
  452. package/src/structures/rules/ITtscLintTestingLibraryRuleOptions.ts +24 -0
  453. package/src/structures/rules/ITtscLintTestingLibraryRules.ts +342 -0
  454. package/src/structures/rules/ITtscLintTypeScriptRules.ts +1230 -0
  455. package/src/structures/rules/ITtscLintUnicornRules.ts +1143 -0
  456. package/src/structures/rules/ITtscLintVitestRules.ts +154 -0
  457. package/src/structures/rules/index.ts +31 -0
  458. package/lib/structures/ITtscLintFormatConfig.js.map +0 -1
  459. package/lib/structures/TtscLintRule.d.ts +0 -17
  460. package/lib/structures/TtscLintRule.js.map +0 -1
  461. package/lib/structures/TtscLintRuleMap.d.ts +0 -46
  462. package/lib/structures/TtscLintRuleMap.js.map +0 -1
  463. package/lib/structures/TtscLintRuleOptions.d.ts +0 -137
  464. package/lib/structures/TtscLintRuleOptions.js.map +0 -1
  465. package/src/structures/TtscLintRule.ts +0 -160
  466. package/src/structures/TtscLintRuleMap.ts +0 -55
  467. package/src/structures/TtscLintRuleOptions.ts +0 -151
@@ -0,0 +1,1073 @@
1
+ package linthost
2
+
3
+ import (
4
+ "strings"
5
+
6
+ shimast "github.com/microsoft/typescript-go/shim/ast"
7
+ )
8
+
9
+ type solidRule struct {
10
+ name string
11
+ }
12
+
13
+ func (r solidRule) Name() string { return "solid/" + r.name }
14
+ func (r solidRule) Visits() []shimast.Kind {
15
+ return []shimast.Kind{shimast.KindSourceFile}
16
+ }
17
+ func (r solidRule) Check(ctx *Context, node *shimast.Node) {
18
+ if r.name == "jsx-uses-vars" {
19
+ return
20
+ }
21
+ state := collectSolidState(ctx)
22
+ if !state.hasSolid && r.name != "jsx-no-undef" {
23
+ return
24
+ }
25
+ switch r.name {
26
+ case "components-return-once":
27
+ state.reportComponentsReturnOnce(ctx)
28
+ case "event-handlers":
29
+ state.reportEventHandlers(ctx)
30
+ case "imports":
31
+ state.reportImports(ctx)
32
+ case "jsx-no-duplicate-props":
33
+ state.reportDuplicateProps(ctx)
34
+ case "jsx-no-script-url":
35
+ state.reportScriptURLs(ctx)
36
+ case "jsx-no-undef":
37
+ state.reportJSXNoUndef(ctx)
38
+ case "no-array-handlers":
39
+ state.reportArrayHandlers(ctx)
40
+ case "no-destructure":
41
+ state.reportNoDestructure(ctx)
42
+ case "no-innerhtml":
43
+ state.reportInnerHTML(ctx)
44
+ case "no-proxy-apis":
45
+ state.reportProxyAPIs(ctx)
46
+ case "no-react-deps":
47
+ state.reportReactDeps(ctx)
48
+ case "no-react-specific-props":
49
+ state.reportReactSpecificProps(ctx)
50
+ case "no-unknown-namespaces":
51
+ state.reportUnknownNamespaces(ctx)
52
+ case "prefer-classlist":
53
+ state.reportPreferClassList(ctx)
54
+ case "prefer-for":
55
+ state.reportPreferFor(ctx)
56
+ case "prefer-show":
57
+ state.reportPreferShow(ctx)
58
+ case "reactivity":
59
+ state.reportReactivity(ctx)
60
+ case "self-closing-comp":
61
+ state.reportSelfClosing(ctx)
62
+ case "style-prop":
63
+ state.reportStyleProp(ctx)
64
+ case "validate-jsx-nesting":
65
+ state.reportValidateJSXNesting(ctx)
66
+ }
67
+ }
68
+
69
+ type solidState struct {
70
+ hasSolid bool
71
+
72
+ imports []*shimast.Node
73
+ calls []*shimast.Node
74
+ newExprs []*shimast.Node
75
+ variables []*shimast.Node
76
+ functions []*shimast.Node
77
+ returns []*shimast.Node
78
+ jsxAttrs []*shimast.Node
79
+ jsxOpenings []*shimast.Node
80
+ jsxElements []*shimast.Node
81
+ jsxExprs []*shimast.Node
82
+ jsxSpreads []*shimast.Node
83
+ declared map[string]bool
84
+ importedFrom map[string]string
85
+ solidImport map[string]string
86
+ signals map[string]bool
87
+ }
88
+
89
+ func collectSolidState(ctx *Context) *solidState {
90
+ state := &solidState{
91
+ declared: map[string]bool{},
92
+ importedFrom: map[string]string{},
93
+ solidImport: map[string]string{},
94
+ signals: map[string]bool{},
95
+ }
96
+ if ctx == nil || ctx.File == nil {
97
+ return state
98
+ }
99
+ for _, stmt := range ctx.File.Statements.Nodes {
100
+ if stmt == nil || stmt.Kind != shimast.KindImportDeclaration {
101
+ continue
102
+ }
103
+ state.imports = append(state.imports, stmt)
104
+ state.collectImport(stmt)
105
+ }
106
+ walkDescendants(ctx.File.AsNode(), func(child *shimast.Node) {
107
+ if child == nil {
108
+ return
109
+ }
110
+ switch child.Kind {
111
+ case shimast.KindCallExpression:
112
+ state.calls = append(state.calls, child)
113
+ case shimast.KindNewExpression:
114
+ state.newExprs = append(state.newExprs, child)
115
+ case shimast.KindVariableDeclaration:
116
+ state.variables = append(state.variables, child)
117
+ state.collectVariable(child)
118
+ case shimast.KindFunctionDeclaration, shimast.KindFunctionExpression, shimast.KindArrowFunction:
119
+ state.functions = append(state.functions, child)
120
+ state.collectFunction(child)
121
+ case shimast.KindReturnStatement:
122
+ state.returns = append(state.returns, child)
123
+ case shimast.KindJsxAttribute:
124
+ state.jsxAttrs = append(state.jsxAttrs, child)
125
+ case shimast.KindJsxOpeningElement, shimast.KindJsxSelfClosingElement:
126
+ state.jsxOpenings = append(state.jsxOpenings, child)
127
+ case shimast.KindJsxElement:
128
+ state.jsxElements = append(state.jsxElements, child)
129
+ case shimast.KindJsxExpression:
130
+ state.jsxExprs = append(state.jsxExprs, child)
131
+ case shimast.KindJsxSpreadAttribute:
132
+ state.jsxSpreads = append(state.jsxSpreads, child)
133
+ }
134
+ })
135
+ return state
136
+ }
137
+
138
+ func (s *solidState) collectImport(node *shimast.Node) {
139
+ decl := node.AsImportDeclaration()
140
+ if decl == nil {
141
+ return
142
+ }
143
+ source := stringLiteralText(decl.ModuleSpecifier)
144
+ if strings.HasPrefix(source, "solid-js") {
145
+ s.hasSolid = true
146
+ }
147
+ if decl.ImportClause == nil {
148
+ return
149
+ }
150
+ clause := decl.ImportClause.AsImportClause()
151
+ if clause == nil {
152
+ return
153
+ }
154
+ if name := identifierText(clause.Name()); name != "" {
155
+ s.declared[name] = true
156
+ s.importedFrom[name] = source
157
+ }
158
+ bindings := clause.NamedBindings
159
+ if bindings == nil || bindings.Kind != shimast.KindNamedImports {
160
+ return
161
+ }
162
+ named := bindings.AsNamedImports()
163
+ if named == nil || named.Elements == nil {
164
+ return
165
+ }
166
+ for _, specNode := range named.Elements.Nodes {
167
+ spec := specNode.AsImportSpecifier()
168
+ if spec == nil {
169
+ continue
170
+ }
171
+ imported := solidImportName(spec.PropertyName)
172
+ local := identifierText(spec.Name())
173
+ if imported == "" {
174
+ imported = local
175
+ }
176
+ if local == "" {
177
+ continue
178
+ }
179
+ s.declared[local] = true
180
+ s.importedFrom[local] = source
181
+ if strings.HasPrefix(source, "solid-js") {
182
+ s.solidImport[local] = imported
183
+ }
184
+ }
185
+ }
186
+
187
+ func (s *solidState) collectVariable(node *shimast.Node) {
188
+ decl := node.AsVariableDeclaration()
189
+ if decl == nil {
190
+ return
191
+ }
192
+ collectSolidBindingNames(decl.Name(), s.declared)
193
+ init := stripParens(decl.Initializer)
194
+ if init == nil {
195
+ return
196
+ }
197
+ initCall := init.AsCallExpression()
198
+ if initCall == nil || s.callName(initCall) != "createSignal" {
199
+ return
200
+ }
201
+ name := decl.Name()
202
+ if name == nil || name.Kind != shimast.KindArrayBindingPattern {
203
+ return
204
+ }
205
+ binding := name.AsBindingPattern()
206
+ if binding == nil || binding.Elements == nil || len(binding.Elements.Nodes) == 0 {
207
+ return
208
+ }
209
+ first := binding.Elements.Nodes[0].AsBindingElement()
210
+ if first == nil {
211
+ return
212
+ }
213
+ if local := identifierText(first.Name()); local != "" {
214
+ s.signals[local] = true
215
+ }
216
+ }
217
+
218
+ func (s *solidState) collectFunction(node *shimast.Node) {
219
+ if name := solidFunctionName(node); name != "" {
220
+ s.declared[name] = true
221
+ }
222
+ for _, param := range node.Parameters() {
223
+ decl := param.AsParameterDeclaration()
224
+ if decl != nil {
225
+ collectSolidBindingNames(decl.Name(), s.declared)
226
+ }
227
+ }
228
+ }
229
+
230
+ func (s *solidState) reportImports(ctx *Context) {
231
+ for _, node := range s.imports {
232
+ decl := node.AsImportDeclaration()
233
+ if decl == nil || decl.ImportClause == nil {
234
+ continue
235
+ }
236
+ source := stringLiteralText(decl.ModuleSpecifier)
237
+ if !isSolidSource(source) {
238
+ continue
239
+ }
240
+ clause := decl.ImportClause.AsImportClause()
241
+ if clause == nil || clause.NamedBindings == nil || clause.NamedBindings.Kind != shimast.KindNamedImports {
242
+ continue
243
+ }
244
+ named := clause.NamedBindings.AsNamedImports()
245
+ if named == nil || named.Elements == nil {
246
+ continue
247
+ }
248
+ for _, specNode := range named.Elements.Nodes {
249
+ spec := specNode.AsImportSpecifier()
250
+ imported := ""
251
+ if spec != nil {
252
+ imported = solidImportName(spec.PropertyName)
253
+ if imported == "" {
254
+ imported = identifierText(spec.Name())
255
+ }
256
+ }
257
+ if correct := solidPreferredSource(imported); correct != "" && correct != source {
258
+ ctx.Report(specNode, "Import Solid API from its canonical module.")
259
+ }
260
+ }
261
+ }
262
+ }
263
+
264
+ func (s *solidState) reportNoDestructure(ctx *Context) {
265
+ for _, fn := range s.functions {
266
+ if !solidFunctionHasJSX(fn) || functionIsInsideJSX(fn) || len(fn.Parameters()) != 1 {
267
+ continue
268
+ }
269
+ param := fn.Parameters()[0].AsParameterDeclaration()
270
+ if param != nil && param.Name() != nil && param.Name().Kind == shimast.KindObjectBindingPattern {
271
+ ctx.Report(param.Name(), "Destructuring component props breaks Solid reactivity; use property access instead.")
272
+ }
273
+ }
274
+ }
275
+
276
+ func (s *solidState) reportComponentsReturnOnce(ctx *Context) {
277
+ for _, fn := range s.functions {
278
+ if !solidFunctionHasJSX(fn) || functionIsInsideJSX(fn) || !solidFunctionLooksComponent(fn) {
279
+ continue
280
+ }
281
+ returns := solidReturnsInFunction(fn)
282
+ if len(returns) <= 1 {
283
+ continue
284
+ }
285
+ for _, ret := range returns[:len(returns)-1] {
286
+ ctx.Report(ret, "Solid components run once; move early return conditions inside JSX.")
287
+ }
288
+ last := returns[len(returns)-1].AsReturnStatement()
289
+ if last != nil && solidIsConditional(last.Expression) {
290
+ ctx.Report(last.Expression, "Move conditional component returns inside JSX.")
291
+ }
292
+ }
293
+ }
294
+
295
+ func (s *solidState) reportInnerHTML(ctx *Context) {
296
+ for _, attr := range s.jsxAttrs {
297
+ name := solidJSXAttrName(attr)
298
+ if name == "innerHTML" || name == "dangerouslySetInnerHTML" {
299
+ ctx.Report(attr, "Avoid innerHTML in Solid JSX.")
300
+ }
301
+ }
302
+ }
303
+
304
+ func (s *solidState) reportEventHandlers(ctx *Context) {
305
+ for _, attr := range s.jsxAttrs {
306
+ if !solidAttrOnDOM(attr) {
307
+ continue
308
+ }
309
+ name := solidJSXAttrName(attr)
310
+ if len(name) > 2 && strings.HasPrefix(name, "on") && name[2] >= 'a' && name[2] <= 'z' {
311
+ ctx.Report(attr, "Use Solid event handler casing such as onClick or the on: namespace.")
312
+ }
313
+ }
314
+ }
315
+
316
+ func (s *solidState) reportArrayHandlers(ctx *Context) {
317
+ for _, attr := range s.jsxAttrs {
318
+ if !solidAttrOnDOM(attr) {
319
+ continue
320
+ }
321
+ name := solidJSXAttrName(attr)
322
+ if !(strings.HasPrefix(name, "on") || strings.HasPrefix(name, "on:")) {
323
+ continue
324
+ }
325
+ expr := solidJSXAttrExpression(attr)
326
+ if expr != nil && expr.Kind == shimast.KindArrayLiteralExpression {
327
+ ctx.Report(attr, "Passing an array as an event handler is type-unsafe.")
328
+ }
329
+ }
330
+ }
331
+
332
+ func (s *solidState) reportJSXNoUndef(ctx *Context) {
333
+ if !s.hasSolid {
334
+ return
335
+ }
336
+ for _, opening := range s.jsxOpenings {
337
+ tag := solidJSXOpeningTag(opening)
338
+ if tag == "" || solidIsDOMTag(tag) || strings.Contains(tag, ".") {
339
+ continue
340
+ }
341
+ if !s.declared[tag] {
342
+ ctx.Report(opening, "JSX component is not defined.")
343
+ }
344
+ }
345
+ }
346
+
347
+ func (s *solidState) reportDuplicateProps(ctx *Context) {
348
+ for _, opening := range s.jsxOpenings {
349
+ attrs := solidOpeningAttributes(opening)
350
+ seen := map[string]*shimast.Node{}
351
+ for _, attr := range attrs {
352
+ name := solidJSXAttrName(attr)
353
+ if name == "" {
354
+ continue
355
+ }
356
+ key := strings.ToLower(strings.TrimPrefix(strings.TrimPrefix(name, "attr:"), "prop:"))
357
+ if prev := seen[key]; prev != nil {
358
+ ctx.Report(attr, "Duplicate JSX props are not allowed.")
359
+ }
360
+ seen[key] = attr
361
+ }
362
+ }
363
+ }
364
+
365
+ func (s *solidState) reportScriptURLs(ctx *Context) {
366
+ for _, attr := range s.jsxAttrs {
367
+ value := solidJSXAttrString(attr)
368
+ if value == "" {
369
+ continue
370
+ }
371
+ normalized := strings.ToLower(strings.TrimLeft(value, " \t\r\n"))
372
+ normalized = strings.ReplaceAll(normalized, "\n", "")
373
+ normalized = strings.ReplaceAll(normalized, "\r", "")
374
+ normalized = strings.ReplaceAll(normalized, "\t", "")
375
+ if strings.HasPrefix(normalized, "javascript:") {
376
+ ctx.Report(attr, "Do not use javascript: URLs in JSX.")
377
+ }
378
+ }
379
+ }
380
+
381
+ func (s *solidState) reportReactSpecificProps(ctx *Context) {
382
+ for _, attr := range s.jsxAttrs {
383
+ if !solidAttrOnDOM(attr) {
384
+ continue
385
+ }
386
+ switch solidJSXAttrName(attr) {
387
+ case "className":
388
+ ctx.Report(attr, "Use Solid's `class` prop instead of `className`.")
389
+ case "htmlFor":
390
+ ctx.Report(attr, "Use Solid's `for` prop instead of `htmlFor`.")
391
+ case "key":
392
+ ctx.Report(attr, "DOM elements in Solid do not need React-style `key` props.")
393
+ }
394
+ }
395
+ }
396
+
397
+ func (s *solidState) reportUnknownNamespaces(ctx *Context) {
398
+ for _, attr := range s.jsxAttrs {
399
+ name := solidJSXAttrName(attr)
400
+ idx := strings.IndexByte(name, ':')
401
+ if idx < 0 {
402
+ continue
403
+ }
404
+ namespace := name[:idx]
405
+ if !solidAttrOnDOM(attr) {
406
+ ctx.Report(attr, "Namespaced props have no effect on Solid components.")
407
+ continue
408
+ }
409
+ if !solidKnownNamespace(namespace) {
410
+ ctx.Report(attr, "Unknown Solid JSX namespace.")
411
+ }
412
+ }
413
+ }
414
+
415
+ func (s *solidState) reportReactDeps(ctx *Context) {
416
+ for _, node := range s.calls {
417
+ call := node.AsCallExpression()
418
+ if call == nil || call.Arguments == nil || len(call.Arguments.Nodes) != 2 {
419
+ continue
420
+ }
421
+ name := s.callName(call)
422
+ if name != "createEffect" && name != "createMemo" {
423
+ continue
424
+ }
425
+ first := stripParens(call.Arguments.Nodes[0])
426
+ second := stripParens(call.Arguments.Nodes[1])
427
+ if solidIsFunction(first) && len(first.Parameters()) == 0 && second != nil && second.Kind == shimast.KindArrayLiteralExpression {
428
+ ctx.Report(second, "Solid automatically tracks dependencies; remove React-style dependency arrays.")
429
+ }
430
+ }
431
+ }
432
+
433
+ func (s *solidState) reportProxyAPIs(ctx *Context) {
434
+ for _, node := range s.imports {
435
+ decl := node.AsImportDeclaration()
436
+ if decl != nil && stringLiteralText(decl.ModuleSpecifier) == "solid-js/store" {
437
+ ctx.Report(node, "Solid store APIs use Proxies.")
438
+ }
439
+ }
440
+ for _, node := range s.newExprs {
441
+ expr := node.AsNewExpression()
442
+ if expr != nil && identifierText(stripParens(expr.Expression)) == "Proxy" {
443
+ ctx.Report(node, "Proxy is incompatible with proxy-free Solid targets.")
444
+ }
445
+ }
446
+ for _, node := range s.calls {
447
+ call := node.AsCallExpression()
448
+ if call == nil {
449
+ continue
450
+ }
451
+ if isMatchingPropertyAccess(call.Expression, "Proxy", "revocable") || s.callName(call) == "mergeProps" {
452
+ ctx.Report(node, "Avoid Proxy-based Solid APIs.")
453
+ }
454
+ }
455
+ }
456
+
457
+ func (s *solidState) reportPreferClassList(ctx *Context) {
458
+ for _, attr := range s.jsxAttrs {
459
+ name := solidJSXAttrName(attr)
460
+ if name != "class" && name != "className" {
461
+ continue
462
+ }
463
+ if solidOpeningHasAttr(attr.Parent, "classList") {
464
+ continue
465
+ }
466
+ expr := solidJSXAttrExpression(attr)
467
+ if expr == nil {
468
+ continue
469
+ }
470
+ call := expr.AsCallExpression()
471
+ if call == nil || call.Arguments == nil || len(call.Arguments.Nodes) != 1 {
472
+ continue
473
+ }
474
+ callee := identifierText(stripParens(call.Expression))
475
+ arg := stripParens(call.Arguments.Nodes[0])
476
+ if (callee == "cn" || callee == "clsx" || callee == "classnames") && arg != nil && arg.Kind == shimast.KindObjectLiteralExpression {
477
+ ctx.Report(attr, "Use Solid's classList prop instead of a classnames helper.")
478
+ }
479
+ }
480
+ }
481
+
482
+ func (s *solidState) reportPreferFor(ctx *Context) {
483
+ for _, node := range s.calls {
484
+ call := node.AsCallExpression()
485
+ if call == nil || call.Arguments == nil || len(call.Arguments.Nodes) != 1 {
486
+ continue
487
+ }
488
+ if !solidCallPropertyName(call, "map") || !solidInsideJSXExpression(node) || !solidIsFunction(stripParens(call.Arguments.Nodes[0])) {
489
+ continue
490
+ }
491
+ ctx.Report(node, "Use Solid's <For> component for rendering lists.")
492
+ }
493
+ }
494
+
495
+ func (s *solidState) reportPreferShow(ctx *Context) {
496
+ for _, node := range s.jsxExprs {
497
+ expr := node.AsJsxExpression()
498
+ if expr == nil || expr.Expression == nil {
499
+ continue
500
+ }
501
+ inner := stripParens(expr.Expression)
502
+ if inner != nil && solidIsConditional(inner) {
503
+ ctx.Report(inner, "Use Solid's <Show> component for conditional JSX.")
504
+ }
505
+ }
506
+ }
507
+
508
+ func (s *solidState) reportReactivity(ctx *Context) {
509
+ for _, node := range s.calls {
510
+ call := node.AsCallExpression()
511
+ if call == nil || call.Arguments == nil || len(call.Arguments.Nodes) == 0 {
512
+ continue
513
+ }
514
+ name := s.callName(call)
515
+ if (name == "createEffect" || name == "createMemo" || name == "createComputed") && solidIsAsyncFunction(stripParens(call.Arguments.Nodes[0])) {
516
+ ctx.Report(call.Arguments.Nodes[0], "Solid tracked scopes should not be async.")
517
+ }
518
+ }
519
+ for _, node := range s.variables {
520
+ decl := node.AsVariableDeclaration()
521
+ if decl != nil && decl.Name() != nil && decl.Name().Kind == shimast.KindObjectBindingPattern && identifierText(stripParens(decl.Initializer)) == "props" {
522
+ ctx.Report(decl.Name(), "Destructuring props breaks Solid reactivity.")
523
+ }
524
+ }
525
+ for _, jsxExpr := range s.jsxExprs {
526
+ expr := jsxExpr.AsJsxExpression()
527
+ if expr == nil || expr.Expression == nil {
528
+ continue
529
+ }
530
+ name := identifierText(stripParens(expr.Expression))
531
+ if s.signals[name] {
532
+ ctx.Report(expr.Expression, "Call Solid signal accessors inside JSX so updates are tracked.")
533
+ }
534
+ }
535
+ }
536
+
537
+ func (s *solidState) reportSelfClosing(ctx *Context) {
538
+ for _, node := range s.jsxElements {
539
+ elem := node.AsJsxElement()
540
+ if elem == nil || elem.OpeningElement == nil || elem.Children == nil {
541
+ continue
542
+ }
543
+ if solidJSXChildrenEmpty(ctx.File, elem.Children.Nodes) {
544
+ ctx.Report(elem.OpeningElement, "Empty Solid JSX elements should be self-closing.")
545
+ }
546
+ }
547
+ }
548
+
549
+ func (s *solidState) reportStyleProp(ctx *Context) {
550
+ for _, attr := range s.jsxAttrs {
551
+ if solidJSXAttrName(attr) != "style" {
552
+ continue
553
+ }
554
+ value := solidJSXAttrString(attr)
555
+ if value != "" {
556
+ ctx.Report(attr, "Use an object for Solid style props instead of a string.")
557
+ continue
558
+ }
559
+ expr := solidJSXAttrExpression(attr)
560
+ if expr == nil || expr.Kind != shimast.KindObjectLiteralExpression {
561
+ continue
562
+ }
563
+ obj := expr.AsObjectLiteralExpression()
564
+ if obj == nil || obj.Properties == nil {
565
+ continue
566
+ }
567
+ for _, propNode := range obj.Properties.Nodes {
568
+ prop := propNode.AsPropertyAssignment()
569
+ if prop == nil {
570
+ continue
571
+ }
572
+ name := solidPropertyName(prop.Name())
573
+ if strings.ContainsAny(name, "ABCDEFGHIJKLMNOPQRSTUVWXYZ") {
574
+ ctx.Report(prop.Name(), "Use kebab-case CSS property names in Solid style objects.")
575
+ }
576
+ if solidNumericLiteralNonZero(prop.Initializer) && solidLengthStyleName(name) {
577
+ ctx.Report(prop.Initializer, "Numeric Solid style values need explicit units.")
578
+ }
579
+ }
580
+ }
581
+ }
582
+
583
+ // reportValidateJSXNesting flags JSX elements nested in HTML-illegal ways.
584
+ //
585
+ // The HTML parsing algorithm aborts certain nestings (a `<p>` inside another
586
+ // `<p>`, a `<div>` inside `<p>`, an anchor inside an anchor, an interactive
587
+ // inside `<button>`) and silently restructures the DOM at runtime, so the
588
+ // rendered tree never matches the JSX. The baseline subset matches the
589
+ // upstream `solid/validate-jsx-nesting` rule's HTML5 phrasing-content and
590
+ // interactive-content checks; anything more nuanced (transparent content
591
+ // models, table-section sequencing) is left to the upstream rule.
592
+ //
593
+ // For each container element of interest the rule scans descendants until it
594
+ // crosses into another function boundary, and reports each forbidden child at
595
+ // the offending element so the diagnostic points at the inner tag rather than
596
+ // the outer container.
597
+ func (s *solidState) reportValidateJSXNesting(ctx *Context) {
598
+ for _, opening := range s.jsxOpenings {
599
+ parentTag := strings.ToLower(solidJSXOpeningTag(opening))
600
+ forbidden := solidJSXForbiddenChildren(parentTag)
601
+ if len(forbidden) == 0 {
602
+ continue
603
+ }
604
+ container := opening.Parent
605
+ if container == nil || container.Kind != shimast.KindJsxElement {
606
+ continue
607
+ }
608
+ elem := container.AsJsxElement()
609
+ if elem == nil || elem.Children == nil {
610
+ continue
611
+ }
612
+ for _, child := range elem.Children.Nodes {
613
+ solidWalkJSXChildren(child, func(child *shimast.Node) {
614
+ childOpening := solidJSXChildOpening(child)
615
+ if childOpening == nil {
616
+ return
617
+ }
618
+ childTag := strings.ToLower(solidJSXOpeningTag(childOpening))
619
+ if !forbidden[childTag] {
620
+ return
621
+ }
622
+ ctx.Report(childOpening, "JSX <"+childTag+"> cannot be nested inside <"+parentTag+">.")
623
+ })
624
+ }
625
+ }
626
+ }
627
+
628
+ // solidJSXForbiddenChildren returns the set of HTML tag names that may not
629
+ // appear as descendants of the given container tag. Tag names are lower-case
630
+ // because HTML element nesting is case-insensitive.
631
+ func solidJSXForbiddenChildren(parent string) map[string]bool {
632
+ switch parent {
633
+ case "p":
634
+ return map[string]bool{
635
+ "div": true, "p": true, "table": true, "form": true,
636
+ "ul": true, "ol": true, "dl": true, "hr": true,
637
+ "pre": true, "blockquote": true,
638
+ }
639
+ case "a":
640
+ return map[string]bool{"a": true}
641
+ case "button":
642
+ return map[string]bool{
643
+ "button": true, "input": true,
644
+ "select": true, "textarea": true,
645
+ }
646
+ }
647
+ return nil
648
+ }
649
+
650
+ // solidJSXChildOpening returns the opening node of a JSX child if the child
651
+ // is itself a JSX element. Self-closing elements are their own opening node;
652
+ // element/fragment containers expose the opening through `OpeningElement`.
653
+ func solidJSXChildOpening(node *shimast.Node) *shimast.Node {
654
+ if node == nil {
655
+ return nil
656
+ }
657
+ switch node.Kind {
658
+ case shimast.KindJsxElement:
659
+ elem := node.AsJsxElement()
660
+ if elem == nil {
661
+ return nil
662
+ }
663
+ return elem.OpeningElement
664
+ case shimast.KindJsxSelfClosingElement:
665
+ return node
666
+ }
667
+ return nil
668
+ }
669
+
670
+ // solidWalkJSXChildren visits every JSX-descendant of node, stopping at
671
+ // function boundaries so the outer container does not own JSX rendered inside
672
+ // a nested component. JSX expression containers are entered so JSX returned
673
+ // from `{cond ? <a /> : <b />}` is still inspected.
674
+ func solidWalkJSXChildren(node *shimast.Node, visit func(*shimast.Node)) {
675
+ if node == nil {
676
+ return
677
+ }
678
+ visit(node)
679
+ if solidIsFunction(node) {
680
+ return
681
+ }
682
+ node.ForEachChild(func(child *shimast.Node) bool {
683
+ solidWalkJSXChildren(child, visit)
684
+ return false
685
+ })
686
+ }
687
+
688
+ func (s *solidState) callName(call *shimast.CallExpression) string {
689
+ if call == nil {
690
+ return ""
691
+ }
692
+ expr := stripParens(call.Expression)
693
+ if expr == nil {
694
+ return ""
695
+ }
696
+ if name := identifierText(expr); name != "" {
697
+ if imported := s.solidImport[name]; imported != "" {
698
+ return imported
699
+ }
700
+ return name
701
+ }
702
+ if expr.Kind == shimast.KindPropertyAccessExpression {
703
+ access := expr.AsPropertyAccessExpression()
704
+ return identifierText(access.Name())
705
+ }
706
+ return ""
707
+ }
708
+
709
+ func solidImportName(node *shimast.Node) string {
710
+ if node == nil {
711
+ return ""
712
+ }
713
+ if name := identifierText(node); name != "" {
714
+ return name
715
+ }
716
+ return stringLiteralText(node)
717
+ }
718
+
719
+ func collectSolidBindingNames(node *shimast.Node, out map[string]bool) {
720
+ if node == nil {
721
+ return
722
+ }
723
+ if name := identifierText(node); name != "" {
724
+ out[name] = true
725
+ return
726
+ }
727
+ switch node.Kind {
728
+ case shimast.KindObjectBindingPattern, shimast.KindArrayBindingPattern:
729
+ pattern := node.AsBindingPattern()
730
+ if pattern == nil || pattern.Elements == nil {
731
+ return
732
+ }
733
+ for _, elementNode := range pattern.Elements.Nodes {
734
+ el := elementNode.AsBindingElement()
735
+ if el != nil {
736
+ collectSolidBindingNames(el.Name(), out)
737
+ }
738
+ }
739
+ }
740
+ }
741
+
742
+ func solidFunctionName(node *shimast.Node) string {
743
+ if node == nil {
744
+ return ""
745
+ }
746
+ switch node.Kind {
747
+ case shimast.KindFunctionDeclaration:
748
+ decl := node.AsFunctionDeclaration()
749
+ if decl != nil {
750
+ return identifierText(decl.Name())
751
+ }
752
+ case shimast.KindFunctionExpression:
753
+ expr := node.AsFunctionExpression()
754
+ if expr != nil {
755
+ return identifierText(expr.Name())
756
+ }
757
+ }
758
+ if node.Parent != nil && node.Parent.Kind == shimast.KindVariableDeclaration {
759
+ return identifierText(node.Parent.AsVariableDeclaration().Name())
760
+ }
761
+ return ""
762
+ }
763
+
764
+ func solidFunctionLooksComponent(node *shimast.Node) bool {
765
+ name := solidFunctionName(node)
766
+ return name != "" && name[0] >= 'A' && name[0] <= 'Z'
767
+ }
768
+
769
+ func solidFunctionHasJSX(node *shimast.Node) bool {
770
+ found := false
771
+ walkDescendants(node, func(child *shimast.Node) {
772
+ if child != nil && (child.Kind == shimast.KindJsxElement || child.Kind == shimast.KindJsxSelfClosingElement || child.Kind == shimast.KindJsxFragment) {
773
+ found = true
774
+ }
775
+ })
776
+ return found
777
+ }
778
+
779
+ func functionIsInsideJSX(node *shimast.Node) bool {
780
+ for cur := node.Parent; cur != nil; cur = cur.Parent {
781
+ if cur.Kind == shimast.KindJsxExpression {
782
+ return true
783
+ }
784
+ }
785
+ return false
786
+ }
787
+
788
+ func solidReturnsInFunction(node *shimast.Node) []*shimast.Node {
789
+ body := node.Body()
790
+ if body == nil {
791
+ return nil
792
+ }
793
+ returns := []*shimast.Node{}
794
+ walkDescendants(body, func(child *shimast.Node) {
795
+ if child == nil || child.Kind != shimast.KindReturnStatement {
796
+ return
797
+ }
798
+ for cur := child.Parent; cur != nil && cur != body; cur = cur.Parent {
799
+ if solidIsFunction(cur) {
800
+ return
801
+ }
802
+ }
803
+ returns = append(returns, child)
804
+ })
805
+ return returns
806
+ }
807
+
808
+ func solidIsFunction(node *shimast.Node) bool {
809
+ if node == nil {
810
+ return false
811
+ }
812
+ switch node.Kind {
813
+ case shimast.KindFunctionDeclaration, shimast.KindFunctionExpression, shimast.KindArrowFunction:
814
+ return true
815
+ }
816
+ return false
817
+ }
818
+
819
+ func solidIsAsyncFunction(node *shimast.Node) bool {
820
+ if !solidIsFunction(node) {
821
+ return false
822
+ }
823
+ return hasModifier(node, shimast.KindAsyncKeyword)
824
+ }
825
+
826
+ func solidIsConditional(node *shimast.Node) bool {
827
+ if node == nil {
828
+ return false
829
+ }
830
+ if node.Kind == shimast.KindConditionalExpression {
831
+ return true
832
+ }
833
+ if node.Kind == shimast.KindBinaryExpression {
834
+ expr := node.AsBinaryExpression()
835
+ return expr != nil && expr.OperatorToken != nil &&
836
+ (expr.OperatorToken.Kind == shimast.KindAmpersandAmpersandToken || expr.OperatorToken.Kind == shimast.KindBarBarToken)
837
+ }
838
+ return false
839
+ }
840
+
841
+ func solidJSXOpeningTag(node *shimast.Node) string {
842
+ if node == nil {
843
+ return ""
844
+ }
845
+ switch node.Kind {
846
+ case shimast.KindJsxOpeningElement:
847
+ open := node.AsJsxOpeningElement()
848
+ if open != nil {
849
+ return solidJSXNameText(open.TagName)
850
+ }
851
+ case shimast.KindJsxSelfClosingElement:
852
+ open := node.AsJsxSelfClosingElement()
853
+ if open != nil {
854
+ return solidJSXNameText(open.TagName)
855
+ }
856
+ }
857
+ return ""
858
+ }
859
+
860
+ func solidJSXNameText(node *shimast.Node) string {
861
+ if node == nil {
862
+ return ""
863
+ }
864
+ if name := identifierText(node); name != "" {
865
+ return name
866
+ }
867
+ if node.Kind == shimast.KindPropertyAccessExpression {
868
+ access := node.AsPropertyAccessExpression()
869
+ left := solidJSXNameText(access.Expression)
870
+ right := identifierText(access.Name())
871
+ if left != "" && right != "" {
872
+ return left + "." + right
873
+ }
874
+ }
875
+ if node.Kind == shimast.KindJsxNamespacedName {
876
+ ns := node.AsJsxNamespacedName()
877
+ return identifierText(ns.Namespace) + ":" + identifierText(ns.Name())
878
+ }
879
+ return ""
880
+ }
881
+
882
+ func solidJSXAttrName(node *shimast.Node) string {
883
+ attr := node.AsJsxAttribute()
884
+ if attr == nil {
885
+ return ""
886
+ }
887
+ return solidJSXNameText(attr.Name())
888
+ }
889
+
890
+ func solidOpeningAttributes(opening *shimast.Node) []*shimast.Node {
891
+ if opening == nil {
892
+ return nil
893
+ }
894
+ var attrs *shimast.Node
895
+ if opening.Kind == shimast.KindJsxOpeningElement {
896
+ attrs = opening.AsJsxOpeningElement().Attributes
897
+ } else if opening.Kind == shimast.KindJsxSelfClosingElement {
898
+ attrs = opening.AsJsxSelfClosingElement().Attributes
899
+ }
900
+ if attrs == nil {
901
+ return nil
902
+ }
903
+ jsxAttrs := attrs.AsJsxAttributes()
904
+ if jsxAttrs == nil || jsxAttrs.Properties == nil {
905
+ return nil
906
+ }
907
+ out := []*shimast.Node{}
908
+ for _, prop := range jsxAttrs.Properties.Nodes {
909
+ if prop != nil && prop.Kind == shimast.KindJsxAttribute {
910
+ out = append(out, prop)
911
+ }
912
+ }
913
+ return out
914
+ }
915
+
916
+ func solidOpeningHasAttr(opening *shimast.Node, name string) bool {
917
+ for _, attr := range solidOpeningAttributes(opening) {
918
+ if solidJSXAttrName(attr) == name {
919
+ return true
920
+ }
921
+ }
922
+ return false
923
+ }
924
+
925
+ func solidAttrOnDOM(attr *shimast.Node) bool {
926
+ for cur := attr.Parent; cur != nil; cur = cur.Parent {
927
+ if cur.Kind == shimast.KindJsxOpeningElement || cur.Kind == shimast.KindJsxSelfClosingElement {
928
+ return solidIsDOMTag(solidJSXOpeningTag(cur))
929
+ }
930
+ }
931
+ return false
932
+ }
933
+
934
+ func solidJSXAttrExpression(attrNode *shimast.Node) *shimast.Node {
935
+ attr := attrNode.AsJsxAttribute()
936
+ if attr == nil || attr.Initializer == nil {
937
+ return nil
938
+ }
939
+ if attr.Initializer.Kind == shimast.KindJsxExpression {
940
+ expr := attr.Initializer.AsJsxExpression()
941
+ if expr != nil {
942
+ return stripParens(expr.Expression)
943
+ }
944
+ }
945
+ return stripParens(attr.Initializer)
946
+ }
947
+
948
+ func solidJSXAttrString(attrNode *shimast.Node) string {
949
+ attr := attrNode.AsJsxAttribute()
950
+ if attr == nil || attr.Initializer == nil {
951
+ return ""
952
+ }
953
+ return stringLiteralText(attr.Initializer)
954
+ }
955
+
956
+ func solidInsideJSXExpression(node *shimast.Node) bool {
957
+ for cur := node.Parent; cur != nil; cur = cur.Parent {
958
+ if cur.Kind == shimast.KindJsxExpression {
959
+ return true
960
+ }
961
+ }
962
+ return false
963
+ }
964
+
965
+ func solidCallPropertyName(call *shimast.CallExpression, name string) bool {
966
+ if call == nil || call.Expression == nil || call.Expression.Kind != shimast.KindPropertyAccessExpression {
967
+ return false
968
+ }
969
+ return identifierText(call.Expression.AsPropertyAccessExpression().Name()) == name
970
+ }
971
+
972
+ func solidJSXChildrenEmpty(file *shimast.SourceFile, children []*shimast.Node) bool {
973
+ for _, child := range children {
974
+ if child == nil {
975
+ continue
976
+ }
977
+ if child.Kind == shimast.KindJsxText && strings.TrimSpace(nodeText(file, child)) == "" {
978
+ continue
979
+ }
980
+ return false
981
+ }
982
+ return true
983
+ }
984
+
985
+ func solidPropertyName(node *shimast.Node) string {
986
+ if name := identifierText(node); name != "" {
987
+ return name
988
+ }
989
+ return stringLiteralText(node)
990
+ }
991
+
992
+ func solidNumericLiteralNonZero(node *shimast.Node) bool {
993
+ if node == nil || node.Kind != shimast.KindNumericLiteral {
994
+ return false
995
+ }
996
+ text := numericLiteralText(node)
997
+ return text != "" && text != "0"
998
+ }
999
+
1000
+ func solidLengthStyleName(name string) bool {
1001
+ switch strings.ToLower(name) {
1002
+ case "width", "height", "margin", "padding", "border-width", "font-size":
1003
+ return true
1004
+ }
1005
+ return false
1006
+ }
1007
+
1008
+ func solidIsSolidComponentName(name string) bool {
1009
+ switch name {
1010
+ case "For", "Show", "Switch", "Match", "Index", "Portal", "Dynamic", "ErrorBoundary", "Suspense", "SuspenseList":
1011
+ return true
1012
+ }
1013
+ return false
1014
+ }
1015
+
1016
+ func solidPreferredSource(name string) string {
1017
+ switch name {
1018
+ case "Portal", "render", "hydrate", "renderToString", "renderToStream", "isServer", "renderToStringAsync", "generateHydrationScript", "HydrationScript", "Dynamic":
1019
+ return "solid-js/web"
1020
+ case "createStore", "produce", "reconcile", "unwrap", "createMutable", "modifyMutable":
1021
+ return "solid-js/store"
1022
+ case "createSignal", "createEffect", "createMemo", "createResource", "onMount", "onCleanup", "onError", "untrack", "batch", "on", "createRoot", "getOwner", "runWithOwner", "mergeProps", "splitProps", "useTransition", "observable", "from", "mapArray", "indexArray", "createContext", "useContext", "children", "lazy", "createUniqueId", "createDeferred", "createRenderEffect", "createComputed", "createReaction", "createSelector", "DEV", "For", "Show", "Switch", "Match", "Index", "ErrorBoundary", "Suspense", "SuspenseList":
1023
+ return "solid-js"
1024
+ }
1025
+ return ""
1026
+ }
1027
+
1028
+ func isSolidSource(source string) bool {
1029
+ return source == "solid-js" || source == "solid-js/web" || source == "solid-js/store"
1030
+ }
1031
+
1032
+ func solidIsDOMTag(name string) bool {
1033
+ if name == "" {
1034
+ return false
1035
+ }
1036
+ return name[0] >= 'a' && name[0] <= 'z'
1037
+ }
1038
+
1039
+ func solidKnownNamespace(namespace string) bool {
1040
+ switch namespace {
1041
+ case "on", "oncapture", "use", "prop", "attr", "bool", "xmlns", "xlink":
1042
+ return true
1043
+ }
1044
+ return false
1045
+ }
1046
+
1047
+ func init() {
1048
+ for _, name := range []string{
1049
+ "components-return-once",
1050
+ "event-handlers",
1051
+ "imports",
1052
+ "jsx-no-duplicate-props",
1053
+ "jsx-no-script-url",
1054
+ "jsx-no-undef",
1055
+ "jsx-uses-vars",
1056
+ "no-array-handlers",
1057
+ "no-destructure",
1058
+ "no-innerhtml",
1059
+ "no-proxy-apis",
1060
+ "no-react-deps",
1061
+ "no-react-specific-props",
1062
+ "no-unknown-namespaces",
1063
+ "prefer-classlist",
1064
+ "prefer-for",
1065
+ "prefer-show",
1066
+ "reactivity",
1067
+ "self-closing-comp",
1068
+ "style-prop",
1069
+ "validate-jsx-nesting",
1070
+ } {
1071
+ Register(solidRule{name: name})
1072
+ }
1073
+ }