@ttsc/lint 0.14.0-dev.20260529.2 → 0.14.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (380) hide show
  1. package/README.md +23 -25
  2. package/lib/defaultFormat.d.ts +10 -6
  3. package/lib/defaultFormat.js +10 -6
  4. package/lib/defaultFormat.js.map +1 -1
  5. package/lib/structures/ITtscLintConfig.d.ts +5 -5
  6. package/lib/structures/TtscLintRuleSetting.d.ts +19 -19
  7. package/lib/structures/{ITtscLintFormat.d.ts → format/ITtscLintFormat.d.ts} +45 -70
  8. package/lib/structures/format/ITtscLintFormat.js.map +1 -0
  9. package/lib/structures/format/ITtscLintFormatJsDoc.d.ts +15 -0
  10. package/lib/structures/format/ITtscLintFormatJsDoc.js +3 -0
  11. package/lib/structures/format/ITtscLintFormatJsDoc.js.map +1 -0
  12. package/lib/structures/format/ITtscLintFormatSortImports.d.ts +54 -0
  13. package/lib/structures/format/ITtscLintFormatSortImports.js +3 -0
  14. package/lib/structures/format/ITtscLintFormatSortImports.js.map +1 -0
  15. package/lib/structures/format/index.d.ts +3 -0
  16. package/lib/structures/format/index.js +20 -0
  17. package/lib/structures/format/index.js.map +1 -0
  18. package/lib/structures/index.d.ts +1 -1
  19. package/lib/structures/index.js +1 -1
  20. package/lib/structures/index.js.map +1 -1
  21. package/lib/structures/rules/ITtscLintBoundariesRuleOptions.d.ts +18 -27
  22. package/lib/structures/rules/ITtscLintBoundariesRuleOptions.js +4 -5
  23. package/lib/structures/rules/ITtscLintBoundariesRuleOptions.js.map +1 -1
  24. package/lib/structures/rules/ITtscLintBoundariesRules.d.ts +29 -33
  25. package/lib/structures/rules/ITtscLintContributorRules.d.ts +6 -7
  26. package/lib/structures/rules/ITtscLintCoreRules.d.ts +380 -408
  27. package/lib/structures/rules/ITtscLintCypressRuleOptions.d.ts +5 -5
  28. package/lib/structures/rules/ITtscLintCypressRuleOptions.js +2 -2
  29. package/lib/structures/rules/ITtscLintCypressRules.d.ts +34 -38
  30. package/lib/structures/rules/ITtscLintFunctionalRuleOptions.d.ts +21 -24
  31. package/lib/structures/rules/ITtscLintFunctionalRuleOptions.js +2 -2
  32. package/lib/structures/rules/ITtscLintFunctionalRules.d.ts +51 -56
  33. package/lib/structures/rules/ITtscLintJestRules.d.ts +63 -74
  34. package/lib/structures/rules/ITtscLintJsdocRules.d.ts +47 -54
  35. package/lib/structures/rules/ITtscLintJsxA11yRules.d.ts +94 -102
  36. package/lib/structures/rules/ITtscLintNextjsRules.d.ts +50 -55
  37. package/lib/structures/rules/ITtscLintPlaywrightRules.d.ts +104 -122
  38. package/lib/structures/rules/ITtscLintPromiseRules.d.ts +62 -71
  39. package/lib/structures/rules/ITtscLintReactPerfRuleOptions.d.ts +4 -4
  40. package/lib/structures/rules/ITtscLintReactPerfRules.d.ts +17 -19
  41. package/lib/structures/rules/ITtscLintReactRuleOptions.d.ts +8 -10
  42. package/lib/structures/rules/ITtscLintReactRuleOptions.js +1 -2
  43. package/lib/structures/rules/ITtscLintReactRuleOptions.js.map +1 -1
  44. package/lib/structures/rules/ITtscLintReactRules.d.ts +91 -104
  45. package/lib/structures/rules/ITtscLintRegexpRules.d.ts +46 -54
  46. package/lib/structures/rules/ITtscLintRuleOptionsMap.d.ts +7 -8
  47. package/lib/structures/rules/ITtscLintSecurityRules.d.ts +45 -52
  48. package/lib/structures/rules/ITtscLintSolidRules.d.ts +53 -56
  49. package/lib/structures/rules/ITtscLintStorybookRuleOptions.d.ts +3 -4
  50. package/lib/structures/rules/ITtscLintStorybookRules.d.ts +60 -69
  51. package/lib/structures/rules/ITtscLintTanstackQueryRules.d.ts +31 -37
  52. package/lib/structures/rules/ITtscLintTestingLibraryRuleOptions.d.ts +2 -3
  53. package/lib/structures/rules/ITtscLintTestingLibraryRules.d.ts +102 -119
  54. package/lib/structures/rules/ITtscLintTypeScriptRules.d.ts +460 -518
  55. package/lib/structures/rules/ITtscLintVitestRules.d.ts +43 -51
  56. package/linthost/config.go +89 -72
  57. package/linthost/config_format.go +265 -99
  58. package/linthost/directives.go +5 -1
  59. package/linthost/display_width.go +72 -0
  60. package/linthost/fix.go +26 -1
  61. package/linthost/format.go +222 -25
  62. package/linthost/format_editor_settings.go +262 -0
  63. package/linthost/lsp.go +8 -4
  64. package/linthost/print_dispatch.go +3 -0
  65. package/linthost/print_doc.go +13 -0
  66. package/linthost/print_engine.go +68 -11
  67. package/linthost/print_nodes_array.go +167 -5
  68. package/linthost/print_nodes_call.go +786 -77
  69. package/linthost/print_nodes_function.go +43 -0
  70. package/linthost/print_nodes_imports.go +64 -14
  71. package/linthost/print_nodes_list.go +214 -8
  72. package/linthost/print_nodes_object.go +14 -6
  73. package/linthost/print_nodes_ternary.go +147 -0
  74. package/linthost/rules_boundaries.go +400 -400
  75. package/linthost/rules_camelcase.go +81 -81
  76. package/linthost/rules_complexity.go +52 -51
  77. package/linthost/rules_consistent_return.go +81 -81
  78. package/linthost/rules_core_extra.go +472 -472
  79. package/linthost/rules_curly.go +43 -43
  80. package/linthost/rules_default_case.go +15 -15
  81. package/linthost/rules_default_case_last.go +22 -22
  82. package/linthost/rules_format_arrow_parens.go +213 -0
  83. package/linthost/rules_format_bracket_spacing.go +117 -0
  84. package/linthost/rules_format_clause_join.go +179 -0
  85. package/linthost/rules_format_declaration_header.go +664 -0
  86. package/linthost/rules_format_indent.go +616 -0
  87. package/linthost/rules_format_jsdoc.go +4 -4
  88. package/linthost/rules_format_orphan_semi.go +106 -0
  89. package/linthost/rules_format_parameter_properties.go +175 -0
  90. package/linthost/rules_format_print_width.go +180 -69
  91. package/linthost/rules_format_quote_props.go +169 -0
  92. package/linthost/rules_format_quotes.go +75 -29
  93. package/linthost/rules_format_semi.go +185 -10
  94. package/linthost/rules_format_sort_imports.go +517 -121
  95. package/linthost/rules_format_statement_split.go +368 -0
  96. package/linthost/rules_format_ternary_nullish_parens.go +77 -0
  97. package/linthost/rules_format_trailing_comma.go +21 -2
  98. package/linthost/rules_format_whitespace.go +336 -0
  99. package/linthost/rules_functional.go +688 -688
  100. package/linthost/rules_gap.go +146 -11
  101. package/linthost/rules_grouped_accessor_pairs.go +60 -60
  102. package/linthost/rules_guard_for_in.go +122 -122
  103. package/linthost/rules_id_length.go +44 -44
  104. package/linthost/rules_imports.go +11 -3
  105. package/linthost/rules_init_declarations.go +25 -25
  106. package/linthost/rules_jsx_a11y.go +844 -844
  107. package/linthost/rules_max_classes_per_file.go +24 -24
  108. package/linthost/rules_max_depth.go +43 -43
  109. package/linthost/rules_max_lines.go +53 -53
  110. package/linthost/rules_max_lines_per_function.go +28 -28
  111. package/linthost/rules_max_nested_callbacks.go +26 -26
  112. package/linthost/rules_max_params.go +20 -20
  113. package/linthost/rules_max_statements.go +29 -29
  114. package/linthost/rules_nextjs.go +5 -5
  115. package/linthost/rules_no_else_return.go +38 -38
  116. package/linthost/rules_no_empty_named_blocks.go +45 -45
  117. package/linthost/rules_no_import_assign.go +96 -96
  118. package/linthost/rules_no_invalid_this.go +19 -19
  119. package/linthost/rules_no_loop_func.go +43 -43
  120. package/linthost/rules_no_magic_numbers.go +60 -60
  121. package/linthost/rules_no_mixed_operators.go +44 -44
  122. package/linthost/rules_no_param_reassign.go +64 -64
  123. package/linthost/rules_no_restricted_imports.go +45 -45
  124. package/linthost/rules_no_restricted_syntax.go +17 -17
  125. package/linthost/rules_no_shadow.go +112 -112
  126. package/linthost/rules_no_unreachable.go +36 -36
  127. package/linthost/rules_no_useless_assignment.go +79 -79
  128. package/linthost/rules_no_useless_constructor.go +167 -167
  129. package/linthost/rules_no_useless_return.go +28 -28
  130. package/linthost/rules_prefer_arrow_callback.go +74 -74
  131. package/linthost/rules_prefer_destructuring.go +61 -61
  132. package/linthost/rules_prefer_named_capture_group.go +87 -87
  133. package/linthost/rules_prefer_rest_params.go +61 -61
  134. package/linthost/rules_promise.go +800 -800
  135. package/linthost/rules_react.go +600 -600
  136. package/linthost/rules_react_extras.go +162 -162
  137. package/linthost/rules_react_hooks.go +2 -2
  138. package/linthost/rules_react_perf.go +231 -231
  139. package/linthost/rules_regexp.go +293 -293
  140. package/linthost/rules_security.go +613 -613
  141. package/linthost/rules_sort_imports.go +37 -37
  142. package/linthost/rules_sort_keys.go +88 -88
  143. package/linthost/rules_suggestions.go +13 -0
  144. package/linthost/rules_ts.go +2 -2
  145. package/linthost/rules_ts_async.go +247 -247
  146. package/linthost/rules_ts_class_literal_property_style.go +64 -64
  147. package/linthost/rules_ts_consistent_type_exports.go +209 -209
  148. package/linthost/rules_ts_explicit_function_return_type.go +35 -35
  149. package/linthost/rules_ts_extra.go +6 -2
  150. package/linthost/rules_ts_no_base_to_string.go +140 -140
  151. package/linthost/rules_ts_no_confusing_void.go +28 -28
  152. package/linthost/rules_ts_no_deprecated.go +110 -110
  153. package/linthost/rules_ts_no_for_in_array.go +45 -45
  154. package/linthost/rules_ts_no_magic_numbers.go +67 -67
  155. package/linthost/rules_ts_no_meaningless_void_operator.go +44 -44
  156. package/linthost/rules_ts_no_misused_spread.go +64 -64
  157. package/linthost/rules_ts_no_redundant_type_constituents.go +72 -72
  158. package/linthost/rules_ts_no_restricted_types.go +28 -28
  159. package/linthost/rules_ts_no_unnecessary_boolean_literal_compare.go +87 -87
  160. package/linthost/rules_ts_no_unnecessary_condition.go +184 -184
  161. package/linthost/rules_ts_no_unnecessary_qualifier.go +72 -72
  162. package/linthost/rules_ts_no_unnecessary_template_expression.go +120 -120
  163. package/linthost/rules_ts_no_unnecessary_type_arguments.go +171 -171
  164. package/linthost/rules_ts_no_unnecessary_type_assertion.go +90 -90
  165. package/linthost/rules_ts_no_unsafe_argument.go +50 -50
  166. package/linthost/rules_ts_no_unsafe_assignment.go +60 -60
  167. package/linthost/rules_ts_no_unsafe_call.go +40 -40
  168. package/linthost/rules_ts_no_unsafe_enum_comparison.go +147 -147
  169. package/linthost/rules_ts_no_unsafe_member_access.go +29 -29
  170. package/linthost/rules_ts_no_unsafe_return.go +64 -64
  171. package/linthost/rules_ts_no_unsafe_unary_minus.go +42 -42
  172. package/linthost/rules_ts_no_useless_constructor.go +20 -20
  173. package/linthost/rules_ts_non_nullable_type_assertion_style.go +60 -60
  174. package/linthost/rules_ts_parameter_properties.go +10 -10
  175. package/linthost/rules_ts_prefer_find.go +116 -116
  176. package/linthost/rules_ts_prefer_includes.go +173 -173
  177. package/linthost/rules_ts_prefer_nullish_coalescing.go +54 -54
  178. package/linthost/rules_ts_prefer_optional_chain.go +156 -156
  179. package/linthost/rules_ts_prefer_promise_reject_errors.go +104 -104
  180. package/linthost/rules_ts_prefer_readonly.go +31 -31
  181. package/linthost/rules_ts_prefer_reduce_type_parameter.go +74 -74
  182. package/linthost/rules_ts_prefer_regexp_exec.go +69 -69
  183. package/linthost/rules_ts_prefer_return_this_type.go +79 -79
  184. package/linthost/rules_ts_prefer_string_starts_ends_with.go +237 -237
  185. package/linthost/rules_ts_promise_function_async.go +41 -41
  186. package/linthost/rules_ts_related_getter_setter_pairs.go +61 -61
  187. package/linthost/rules_ts_require_array_sort_compare.go +58 -58
  188. package/linthost/rules_ts_restrict_plus_operands.go +82 -82
  189. package/linthost/rules_ts_restrict_template_expressions.go +50 -50
  190. package/linthost/rules_ts_simple.go +249 -249
  191. package/linthost/rules_ts_sort_type_constituents.go +88 -88
  192. package/linthost/rules_ts_strict_boolean_expressions.go +103 -103
  193. package/linthost/rules_ts_switch_exhaustiveness_check.go +90 -90
  194. package/linthost/rules_ts_unbound_method.go +65 -65
  195. package/linthost/rules_tsdoc.go +88 -88
  196. package/linthost/rules_unicorn_better_regex.go +1 -1
  197. package/linthost/rules_unicorn_catch_error_name.go +19 -19
  198. package/linthost/rules_unicorn_consistent_assert.go +20 -20
  199. package/linthost/rules_unicorn_consistent_date_clone.go +27 -27
  200. package/linthost/rules_unicorn_consistent_destructuring.go +3 -3
  201. package/linthost/rules_unicorn_consistent_empty_array_spread.go +34 -34
  202. package/linthost/rules_unicorn_consistent_existence_index_check.go +42 -42
  203. package/linthost/rules_unicorn_consistent_function_scoping.go +3 -3
  204. package/linthost/rules_unicorn_consistent_template_literal_escape.go +3 -3
  205. package/linthost/rules_unicorn_custom_error_definition.go +92 -92
  206. package/linthost/rules_unicorn_empty_brace_spaces.go +47 -47
  207. package/linthost/rules_unicorn_error_message.go +34 -34
  208. package/linthost/rules_unicorn_escape_case.go +14 -14
  209. package/linthost/rules_unicorn_expiring_todo_comments.go +36 -36
  210. package/linthost/rules_unicorn_explicit_length_check.go +51 -51
  211. package/linthost/rules_unicorn_filename_case.go +1 -1
  212. package/linthost/rules_unicorn_import_style.go +1 -1
  213. package/linthost/rules_unicorn_isolated_functions.go +2 -2
  214. package/linthost/rules_unicorn_new_for_builtins.go +49 -49
  215. package/linthost/rules_unicorn_no_abusive_eslint_disable.go +31 -31
  216. package/linthost/rules_unicorn_no_accessor_recursion.go +69 -69
  217. package/linthost/rules_unicorn_no_anonymous_default_export.go +40 -40
  218. package/linthost/rules_unicorn_no_array_callback_reference.go +33 -33
  219. package/linthost/rules_unicorn_no_array_for_each.go +14 -14
  220. package/linthost/rules_unicorn_no_array_method_this_argument.go +29 -29
  221. package/linthost/rules_unicorn_no_array_reduce.go +15 -15
  222. package/linthost/rules_unicorn_no_array_reverse.go +17 -17
  223. package/linthost/rules_unicorn_no_array_sort.go +17 -17
  224. package/linthost/rules_unicorn_no_await_expression_member.go +12 -12
  225. package/linthost/rules_unicorn_no_await_in_promise_methods.go +38 -38
  226. package/linthost/rules_unicorn_no_console_spaces.go +30 -30
  227. package/linthost/rules_unicorn_no_document_cookie.go +13 -13
  228. package/linthost/rules_unicorn_no_empty_file.go +16 -16
  229. package/linthost/rules_unicorn_no_for_loop.go +58 -58
  230. package/linthost/rules_unicorn_no_hex_escape.go +11 -11
  231. package/linthost/rules_unicorn_no_immediate_mutation.go +55 -55
  232. package/linthost/rules_unicorn_no_instanceof_builtins.go +34 -34
  233. package/linthost/rules_unicorn_no_invalid_fetch_options.go +52 -52
  234. package/linthost/rules_unicorn_no_invalid_remove_event_listener.go +25 -25
  235. package/linthost/rules_unicorn_no_keyword_prefix.go +56 -56
  236. package/linthost/rules_unicorn_no_lonely_if.go +21 -21
  237. package/linthost/rules_unicorn_no_magic_array_flat_depth.go +22 -22
  238. package/linthost/rules_unicorn_no_named_default.go +25 -25
  239. package/linthost/rules_unicorn_no_negated_condition.go +54 -54
  240. package/linthost/rules_unicorn_no_negation_in_equality_check.go +23 -23
  241. package/linthost/rules_unicorn_no_nested_ternary.go +15 -15
  242. package/linthost/rules_unicorn_no_new_array.go +5 -5
  243. package/linthost/rules_unicorn_no_new_buffer.go +5 -5
  244. package/linthost/rules_unicorn_no_null.go +2 -2
  245. package/linthost/rules_unicorn_no_object_as_default_parameter.go +19 -19
  246. package/linthost/rules_unicorn_no_process_exit.go +17 -17
  247. package/linthost/rules_unicorn_no_single_promise_in_promise_methods.go +29 -29
  248. package/linthost/rules_unicorn_no_static_only_class.go +27 -27
  249. package/linthost/rules_unicorn_no_thenable.go +47 -47
  250. package/linthost/rules_unicorn_no_this_assignment.go +10 -10
  251. package/linthost/rules_unicorn_no_typeof_undefined.go +31 -31
  252. package/linthost/rules_unicorn_no_unnecessary_array_flat_depth.go +23 -23
  253. package/linthost/rules_unicorn_no_unnecessary_array_splice_count.go +37 -37
  254. package/linthost/rules_unicorn_no_unnecessary_await.go +24 -24
  255. package/linthost/rules_unicorn_no_unnecessary_slice_end.go +22 -22
  256. package/linthost/rules_unicorn_no_unreadable_array_destructuring.go +67 -67
  257. package/linthost/rules_unicorn_no_unreadable_iife.go +22 -22
  258. package/linthost/rules_unicorn_no_useless_collection_argument.go +34 -34
  259. package/linthost/rules_unicorn_no_useless_error_capture_stack_trace.go +18 -18
  260. package/linthost/rules_unicorn_no_useless_fallback_in_spread.go +49 -49
  261. package/linthost/rules_unicorn_no_useless_iterator_to_array.go +41 -41
  262. package/linthost/rules_unicorn_no_useless_length_check.go +82 -82
  263. package/linthost/rules_unicorn_no_useless_promise_resolve_reject.go +42 -42
  264. package/linthost/rules_unicorn_no_useless_spread.go +38 -38
  265. package/linthost/rules_unicorn_no_useless_switch_case.go +29 -29
  266. package/linthost/rules_unicorn_no_useless_undefined.go +25 -25
  267. package/linthost/rules_unicorn_no_zero_fractions.go +17 -17
  268. package/linthost/rules_unicorn_number_literal_case.go +33 -33
  269. package/linthost/rules_unicorn_numeric_separators_style.go +36 -36
  270. package/linthost/rules_unicorn_prefer_add_event_listener.go +30 -30
  271. package/linthost/rules_unicorn_prefer_array_find.go +27 -27
  272. package/linthost/rules_unicorn_prefer_array_flat.go +25 -25
  273. package/linthost/rules_unicorn_prefer_array_flat_map.go +37 -37
  274. package/linthost/rules_unicorn_prefer_array_index_of.go +108 -108
  275. package/linthost/rules_unicorn_prefer_array_some.go +43 -43
  276. package/linthost/rules_unicorn_prefer_at.go +42 -42
  277. package/linthost/rules_unicorn_prefer_bigint_literals.go +42 -42
  278. package/linthost/rules_unicorn_prefer_blob_reading_methods.go +15 -15
  279. package/linthost/rules_unicorn_prefer_class_fields.go +57 -57
  280. package/linthost/rules_unicorn_prefer_classlist_toggle.go +76 -76
  281. package/linthost/rules_unicorn_prefer_code_point.go +21 -21
  282. package/linthost/rules_unicorn_prefer_date_now.go +47 -47
  283. package/linthost/rules_unicorn_prefer_default_parameters.go +96 -96
  284. package/linthost/rules_unicorn_prefer_dom_node_append.go +14 -14
  285. package/linthost/rules_unicorn_prefer_dom_node_dataset.go +27 -27
  286. package/linthost/rules_unicorn_prefer_dom_node_remove.go +17 -17
  287. package/linthost/rules_unicorn_prefer_dom_node_text_content.go +11 -11
  288. package/linthost/rules_unicorn_prefer_event_target.go +10 -10
  289. package/linthost/rules_unicorn_prefer_export_from.go +99 -99
  290. package/linthost/rules_unicorn_prefer_global_this.go +91 -91
  291. package/linthost/rules_unicorn_prefer_import_meta_properties.go +38 -38
  292. package/linthost/rules_unicorn_prefer_includes.go +108 -108
  293. package/linthost/rules_unicorn_prefer_json_parse_buffer.go +37 -37
  294. package/linthost/rules_unicorn_prefer_keyboard_event_key.go +10 -10
  295. package/linthost/rules_unicorn_prefer_logical_operator_over_ternary.go +20 -20
  296. package/linthost/rules_unicorn_prefer_math_min_max.go +33 -33
  297. package/linthost/rules_unicorn_prefer_math_trunc.go +32 -32
  298. package/linthost/rules_unicorn_prefer_modern_dom_apis.go +18 -18
  299. package/linthost/rules_unicorn_prefer_modern_math_apis.go +38 -38
  300. package/linthost/rules_unicorn_prefer_module.go +22 -22
  301. package/linthost/rules_unicorn_prefer_native_coercion_functions.go +73 -73
  302. package/linthost/rules_unicorn_prefer_negative_index.go +46 -46
  303. package/linthost/rules_unicorn_prefer_node_protocol.go +90 -90
  304. package/linthost/rules_unicorn_prefer_number_properties.go +57 -57
  305. package/linthost/rules_unicorn_prefer_object_from_entries.go +26 -26
  306. package/linthost/rules_unicorn_prefer_optional_catch_binding.go +24 -24
  307. package/linthost/rules_unicorn_prefer_prototype_methods.go +25 -25
  308. package/linthost/rules_unicorn_prefer_query_selector.go +25 -25
  309. package/linthost/rules_unicorn_prefer_reflect_apply.go +10 -10
  310. package/linthost/rules_unicorn_prefer_regexp_test_rule.go +47 -47
  311. package/linthost/rules_unicorn_prefer_response_static_json.go +26 -26
  312. package/linthost/rules_unicorn_prefer_set_has.go +16 -16
  313. package/linthost/rules_unicorn_prefer_set_size.go +22 -22
  314. package/linthost/rules_unicorn_prefer_simple_condition_first.go +3 -3
  315. package/linthost/rules_unicorn_prefer_single_call.go +59 -59
  316. package/linthost/rules_unicorn_prefer_spread.go +24 -24
  317. package/linthost/rules_unicorn_prefer_string_raw.go +12 -12
  318. package/linthost/rules_unicorn_prefer_string_replace_all.go +46 -46
  319. package/linthost/rules_unicorn_prefer_string_slice.go +17 -17
  320. package/linthost/rules_unicorn_prefer_string_starts_ends_with.go +104 -104
  321. package/linthost/rules_unicorn_prefer_string_trim_start_end.go +21 -21
  322. package/linthost/rules_unicorn_prefer_structured_clone.go +36 -36
  323. package/linthost/rules_unicorn_prefer_switch.go +65 -65
  324. package/linthost/rules_unicorn_prefer_ternary.go +35 -35
  325. package/linthost/rules_unicorn_prefer_top_level_await.go +34 -34
  326. package/linthost/rules_unicorn_prefer_type_error.go +84 -84
  327. package/linthost/rules_unicorn_prevent_abbreviations.go +68 -68
  328. package/linthost/rules_unicorn_relative_url_style.go +19 -19
  329. package/linthost/rules_unicorn_require_array_join_separator.go +18 -18
  330. package/linthost/rules_unicorn_require_module_attributes.go +25 -25
  331. package/linthost/rules_unicorn_require_module_specifiers.go +28 -28
  332. package/linthost/rules_unicorn_require_number_to_fixed_digits_argument.go +18 -18
  333. package/linthost/rules_unicorn_require_post_message_target_origin.go +18 -18
  334. package/linthost/rules_unicorn_string_content.go +1 -1
  335. package/linthost/rules_unicorn_switch_case_braces.go +16 -16
  336. package/linthost/rules_unicorn_switch_case_break_position.go +3 -3
  337. package/linthost/rules_unicorn_template_indent.go +1 -1
  338. package/linthost/rules_unicorn_text_encoding_identifier_case.go +36 -36
  339. package/linthost/rules_unicorn_throw_new_error.go +30 -30
  340. package/linthost/rules_var.go +273 -3
  341. package/package.json +3 -3
  342. package/src/defaultFormat.ts +11 -7
  343. package/src/structures/ITtscLintConfig.ts +5 -5
  344. package/src/structures/TtscLintRuleSetting.ts +19 -19
  345. package/src/structures/{ITtscLintFormat.ts → format/ITtscLintFormat.ts} +48 -75
  346. package/src/structures/format/ITtscLintFormatJsDoc.ts +16 -0
  347. package/src/structures/format/ITtscLintFormatSortImports.ts +62 -0
  348. package/src/structures/format/index.ts +3 -0
  349. package/src/structures/index.ts +1 -1
  350. package/src/structures/rules/ITtscLintBoundariesRuleOptions.ts +20 -31
  351. package/src/structures/rules/ITtscLintBoundariesRules.ts +32 -36
  352. package/src/structures/rules/ITtscLintContributorRules.ts +6 -7
  353. package/src/structures/rules/ITtscLintCoreRules.ts +380 -408
  354. package/src/structures/rules/ITtscLintCypressRuleOptions.ts +5 -5
  355. package/src/structures/rules/ITtscLintCypressRules.ts +34 -38
  356. package/src/structures/rules/ITtscLintFunctionalRuleOptions.ts +28 -41
  357. package/src/structures/rules/ITtscLintFunctionalRules.ts +51 -56
  358. package/src/structures/rules/ITtscLintJestRules.ts +63 -74
  359. package/src/structures/rules/ITtscLintJsdocRules.ts +47 -54
  360. package/src/structures/rules/ITtscLintJsxA11yRules.ts +94 -102
  361. package/src/structures/rules/ITtscLintNextjsRules.ts +50 -55
  362. package/src/structures/rules/ITtscLintPlaywrightRules.ts +104 -122
  363. package/src/structures/rules/ITtscLintPromiseRules.ts +62 -71
  364. package/src/structures/rules/ITtscLintReactPerfRuleOptions.ts +4 -4
  365. package/src/structures/rules/ITtscLintReactPerfRules.ts +17 -19
  366. package/src/structures/rules/ITtscLintReactRuleOptions.ts +8 -10
  367. package/src/structures/rules/ITtscLintReactRules.ts +91 -104
  368. package/src/structures/rules/ITtscLintRegexpRules.ts +46 -54
  369. package/src/structures/rules/ITtscLintRuleOptionsMap.ts +7 -8
  370. package/src/structures/rules/ITtscLintSecurityRules.ts +45 -52
  371. package/src/structures/rules/ITtscLintSolidRules.ts +53 -56
  372. package/src/structures/rules/ITtscLintStorybookRuleOptions.ts +3 -4
  373. package/src/structures/rules/ITtscLintStorybookRules.ts +60 -69
  374. package/src/structures/rules/ITtscLintTanstackQueryRules.ts +31 -37
  375. package/src/structures/rules/ITtscLintTestingLibraryRuleOptions.ts +2 -3
  376. package/src/structures/rules/ITtscLintTestingLibraryRules.ts +102 -119
  377. package/src/structures/rules/ITtscLintTypeScriptRules.ts +460 -518
  378. package/src/structures/rules/ITtscLintVitestRules.ts +43 -51
  379. package/lib/structures/ITtscLintFormat.js.map +0 -1
  380. /package/lib/structures/{ITtscLintFormat.js → format/ITtscLintFormat.js} +0 -0
@@ -1,8 +1,8 @@
1
1
  package linthost
2
2
 
3
3
  import (
4
- shimast "github.com/microsoft/typescript-go/shim/ast"
5
- shimchecker "github.com/microsoft/typescript-go/shim/checker"
4
+ shimast "github.com/microsoft/typescript-go/shim/ast"
5
+ shimchecker "github.com/microsoft/typescript-go/shim/checker"
6
6
  )
7
7
 
8
8
  const promiseRulePrefix = "promise/"
@@ -22,42 +22,42 @@ type awaitThenable struct{}
22
22
 
23
23
  func (awaitThenable) Name() string { return "typescript/await-thenable" }
24
24
  func (awaitThenable) NeedsTypeChecker() bool {
25
- return true
25
+ return true
26
26
  }
27
27
  func (awaitThenable) Visits() []shimast.Kind {
28
- return []shimast.Kind{shimast.KindAwaitExpression}
28
+ return []shimast.Kind{shimast.KindAwaitExpression}
29
29
  }
30
30
  func (awaitThenable) Check(ctx *Context, node *shimast.Node) {
31
- if ctx.Checker == nil {
32
- return
33
- }
34
- expr := node.AsAwaitExpression()
35
- if expr == nil || expr.Expression == nil {
36
- return
37
- }
38
- operandType := ctx.Checker.GetTypeAtLocation(expr.Expression)
39
- if operandType == nil {
40
- return
41
- }
42
- if isAwaitable(ctx.Checker, operandType) {
43
- return
44
- }
45
- message := "Unexpected `await` of a non-Promise (non-thenable) value."
46
- // Fix: drop the `await ` keyword and the following whitespace by
47
- // replacing [node.Pos(), expr.Expression.Pos()) with empty text.
48
- // `node.Pos()` may include leading trivia; use tokenRange to anchor
49
- // the start at the actual `await` token.
50
- startPos, _ := tokenRange(ctx.File, node)
51
- operandStart := expr.Expression.Pos()
52
- if startPos < 0 || operandStart <= startPos {
53
- ctx.Report(node, message)
54
- return
55
- }
56
- ctx.ReportFix(
57
- node,
58
- message,
59
- TextEdit{Pos: startPos, End: operandStart, Text: ""},
60
- )
31
+ if ctx.Checker == nil {
32
+ return
33
+ }
34
+ expr := node.AsAwaitExpression()
35
+ if expr == nil || expr.Expression == nil {
36
+ return
37
+ }
38
+ operandType := ctx.Checker.GetTypeAtLocation(expr.Expression)
39
+ if operandType == nil {
40
+ return
41
+ }
42
+ if isAwaitable(ctx.Checker, operandType) {
43
+ return
44
+ }
45
+ message := "Unexpected `await` of a non-Promise (non-thenable) value."
46
+ // Fix: drop the `await ` keyword and the following whitespace by
47
+ // replacing [node.Pos(), expr.Expression.Pos()) with empty text.
48
+ // `node.Pos()` may include leading trivia; use tokenRange to anchor
49
+ // the start at the actual `await` token.
50
+ startPos, _ := tokenRange(ctx.File, node)
51
+ operandStart := expr.Expression.Pos()
52
+ if startPos < 0 || operandStart <= startPos {
53
+ ctx.Report(node, message)
54
+ return
55
+ }
56
+ ctx.ReportFix(
57
+ node,
58
+ message,
59
+ TextEdit{Pos: startPos, End: operandStart, Text: ""},
60
+ )
61
61
  }
62
62
 
63
63
  // isAwaitable reports whether `t` is safe to `await`. A type is awaitable
@@ -79,48 +79,48 @@ func (awaitThenable) Check(ctx *Context, node *shimast.Node) {
79
79
  // necessary because GetPromisedTypeOfPromise returns nil on composite types
80
80
  // like `Promise<X> | number` even though the expression can legally be awaited.
81
81
  func isAwaitable(checker *shimchecker.Checker, t *shimchecker.Type) bool {
82
- if checker == nil || t == nil {
83
- return false
84
- }
85
- flags := t.Flags()
86
- if flags&shimchecker.TypeFlagsAny != 0 ||
87
- flags&shimchecker.TypeFlagsUnknown != 0 ||
88
- flags&shimchecker.TypeFlagsNever != 0 {
89
- return true
90
- }
91
- if flags&(shimchecker.TypeFlagsUnion|shimchecker.TypeFlagsIntersection) != 0 {
92
- for _, part := range t.Types() {
93
- if part == nil {
94
- continue
95
- }
96
- if isAwaitable(checker, part) {
97
- return true
98
- }
99
- }
100
- return false
101
- }
102
- if checker.GetPromisedTypeOfPromise(t) != nil {
103
- return true
104
- }
105
- return isThenableType(checker, t)
82
+ if checker == nil || t == nil {
83
+ return false
84
+ }
85
+ flags := t.Flags()
86
+ if flags&shimchecker.TypeFlagsAny != 0 ||
87
+ flags&shimchecker.TypeFlagsUnknown != 0 ||
88
+ flags&shimchecker.TypeFlagsNever != 0 {
89
+ return true
90
+ }
91
+ if flags&(shimchecker.TypeFlagsUnion|shimchecker.TypeFlagsIntersection) != 0 {
92
+ for _, part := range t.Types() {
93
+ if part == nil {
94
+ continue
95
+ }
96
+ if isAwaitable(checker, part) {
97
+ return true
98
+ }
99
+ }
100
+ return false
101
+ }
102
+ if checker.GetPromisedTypeOfPromise(t) != nil {
103
+ return true
104
+ }
105
+ return isThenableType(checker, t)
106
106
  }
107
107
 
108
108
  // isThenableType reports whether t has a callable `then` property, which is
109
109
  // the runtime-observable contract for "thenable" in the ES spec. The check
110
110
  // intentionally mirrors what the JS engine uses at await-time.
111
111
  func isThenableType(checker *shimchecker.Checker, t *shimchecker.Type) bool {
112
- if checker == nil || t == nil {
113
- return false
114
- }
115
- prop := checker.GetPropertyOfType(t, "then")
116
- if prop == nil {
117
- return false
118
- }
119
- propType := checker.GetTypeOfSymbol(prop)
120
- if propType == nil {
121
- return false
122
- }
123
- return len(checker.GetSignaturesOfType(propType, shimchecker.SignatureKindCall)) > 0
112
+ if checker == nil || t == nil {
113
+ return false
114
+ }
115
+ prop := checker.GetPropertyOfType(t, "then")
116
+ if prop == nil {
117
+ return false
118
+ }
119
+ propType := checker.GetTypeOfSymbol(prop)
120
+ if propType == nil {
121
+ return false
122
+ }
123
+ return len(checker.GetSignaturesOfType(propType, shimchecker.SignatureKindCall)) > 0
124
124
  }
125
125
 
126
126
  // noFloatingPromises: an `ExpressionStatement` whose value is a Promise but
@@ -140,37 +140,37 @@ type noFloatingPromises struct{}
140
140
 
141
141
  func (noFloatingPromises) Name() string { return "typescript/no-floating-promises" }
142
142
  func (noFloatingPromises) NeedsTypeChecker() bool {
143
- return true
143
+ return true
144
144
  }
145
145
  func (noFloatingPromises) Visits() []shimast.Kind {
146
- return []shimast.Kind{shimast.KindExpressionStatement}
146
+ return []shimast.Kind{shimast.KindExpressionStatement}
147
147
  }
148
148
  func (noFloatingPromises) Check(ctx *Context, node *shimast.Node) {
149
- if ctx.Checker == nil {
150
- return
151
- }
152
- stmt := node.AsExpressionStatement()
153
- if stmt == nil || stmt.Expression == nil {
154
- return
155
- }
156
- expr := stripParens(stmt.Expression)
157
- if expr == nil {
158
- return
159
- }
160
- // Syntactic discharges short-circuit the Checker call: any of these
161
- // expression shapes already signals that the author opted out of the
162
- // "discarded" reading, so the rule never needs to walk the type system.
163
- if isPromiseHandledExpression(expr) {
164
- return
165
- }
166
- t := ctx.Checker.GetTypeAtLocation(expr)
167
- if t == nil {
168
- return
169
- }
170
- if !isPromiseTypedExpression(ctx.Checker, t) {
171
- return
172
- }
173
- ctx.Report(node, "Promises must be awaited, end with a call to .catch, end with a call to .then with a rejection handler, or be explicitly marked as ignored with the `void` operator.")
149
+ if ctx.Checker == nil {
150
+ return
151
+ }
152
+ stmt := node.AsExpressionStatement()
153
+ if stmt == nil || stmt.Expression == nil {
154
+ return
155
+ }
156
+ expr := stripParens(stmt.Expression)
157
+ if expr == nil {
158
+ return
159
+ }
160
+ // Syntactic discharges short-circuit the Checker call: any of these
161
+ // expression shapes already signals that the author opted out of the
162
+ // "discarded" reading, so the rule never needs to walk the type system.
163
+ if isPromiseHandledExpression(expr) {
164
+ return
165
+ }
166
+ t := ctx.Checker.GetTypeAtLocation(expr)
167
+ if t == nil {
168
+ return
169
+ }
170
+ if !isPromiseTypedExpression(ctx.Checker, t) {
171
+ return
172
+ }
173
+ ctx.Report(node, "Promises must be awaited, end with a call to .catch, end with a call to .then with a rejection handler, or be explicitly marked as ignored with the `void` operator.")
174
174
  }
175
175
 
176
176
  // isPromiseHandledExpression reports whether the expression is syntactically
@@ -180,29 +180,29 @@ func (noFloatingPromises) Check(ctx *Context, node *shimast.Node) {
180
180
  // `then` only defuses it when an explicit rejection handler is supplied as the
181
181
  // second argument.
182
182
  func isPromiseHandledExpression(expr *shimast.Node) bool {
183
- if expr == nil {
184
- return false
185
- }
186
- switch expr.Kind {
187
- case shimast.KindAwaitExpression, shimast.KindVoidExpression:
188
- return true
189
- case shimast.KindCallExpression:
190
- call := expr.AsCallExpression()
191
- if call == nil {
192
- return false
193
- }
194
- method, ok := promiseMethodCallName(call)
195
- if !ok {
196
- return false
197
- }
198
- switch method {
199
- case "catch", "finally":
200
- return true
201
- case "then":
202
- return call.Arguments != nil && len(call.Arguments.Nodes) >= 2
203
- }
204
- }
205
- return false
183
+ if expr == nil {
184
+ return false
185
+ }
186
+ switch expr.Kind {
187
+ case shimast.KindAwaitExpression, shimast.KindVoidExpression:
188
+ return true
189
+ case shimast.KindCallExpression:
190
+ call := expr.AsCallExpression()
191
+ if call == nil {
192
+ return false
193
+ }
194
+ method, ok := promiseMethodCallName(call)
195
+ if !ok {
196
+ return false
197
+ }
198
+ switch method {
199
+ case "catch", "finally":
200
+ return true
201
+ case "then":
202
+ return call.Arguments != nil && len(call.Arguments.Nodes) >= 2
203
+ }
204
+ }
205
+ return false
206
206
  }
207
207
 
208
208
  // promiseMethodCallName returns the trailing property name when the call's
@@ -213,14 +213,14 @@ func isPromiseHandledExpression(expr *shimast.Node) bool {
213
213
  // constraint would otherwise reject legitimate handlers on user-typed
214
214
  // objects such as `repo.users.findById(id).catch(reportError)`.
215
215
  func promiseMethodCallName(call *shimast.CallExpression) (string, bool) {
216
- if call == nil || call.Expression == nil {
217
- return "", false
218
- }
219
- _, method, ok := promisePropertyAccessParts(call.Expression)
220
- if !ok {
221
- return "", false
222
- }
223
- return method, true
216
+ if call == nil || call.Expression == nil {
217
+ return "", false
218
+ }
219
+ _, method, ok := promisePropertyAccessParts(call.Expression)
220
+ if !ok {
221
+ return "", false
222
+ }
223
+ return method, true
224
224
  }
225
225
 
226
226
  // isPromiseTypedExpression reports whether `t` represents a Promise (or thenable)
@@ -229,28 +229,28 @@ func promiseMethodCallName(call *shimast.CallExpression) (string, bool) {
229
229
  // generic-helper boundaries; `never` is also skipped because a function whose
230
230
  // return type is `never` cannot float a real Promise.
231
231
  func isPromiseTypedExpression(checker *shimchecker.Checker, t *shimchecker.Type) bool {
232
- if checker == nil || t == nil {
233
- return false
234
- }
235
- flags := t.Flags()
236
- if flags&(shimchecker.TypeFlagsAny|shimchecker.TypeFlagsUnknown|shimchecker.TypeFlagsNever) != 0 {
237
- return false
238
- }
239
- if flags&(shimchecker.TypeFlagsUnion|shimchecker.TypeFlagsIntersection) != 0 {
240
- for _, part := range t.Types() {
241
- if part == nil {
242
- continue
243
- }
244
- if isPromiseTypedExpression(checker, part) {
245
- return true
246
- }
247
- }
248
- return false
249
- }
250
- if checker.GetPromisedTypeOfPromise(t) != nil {
251
- return true
252
- }
253
- return isThenableType(checker, t)
232
+ if checker == nil || t == nil {
233
+ return false
234
+ }
235
+ flags := t.Flags()
236
+ if flags&(shimchecker.TypeFlagsAny|shimchecker.TypeFlagsUnknown|shimchecker.TypeFlagsNever) != 0 {
237
+ return false
238
+ }
239
+ if flags&(shimchecker.TypeFlagsUnion|shimchecker.TypeFlagsIntersection) != 0 {
240
+ for _, part := range t.Types() {
241
+ if part == nil {
242
+ continue
243
+ }
244
+ if isPromiseTypedExpression(checker, part) {
245
+ return true
246
+ }
247
+ }
248
+ return false
249
+ }
250
+ if checker.GetPromisedTypeOfPromise(t) != nil {
251
+ return true
252
+ }
253
+ return isThenableType(checker, t)
254
254
  }
255
255
 
256
256
  // returnAwait: `return promise;` inside try/catch/finally lets the rejection
@@ -276,38 +276,38 @@ type returnAwait struct{}
276
276
 
277
277
  func (returnAwait) Name() string { return "typescript/return-await" }
278
278
  func (returnAwait) NeedsTypeChecker() bool {
279
- return true
279
+ return true
280
280
  }
281
281
  func (returnAwait) Visits() []shimast.Kind {
282
- return []shimast.Kind{shimast.KindReturnStatement}
282
+ return []shimast.Kind{shimast.KindReturnStatement}
283
283
  }
284
284
  func (returnAwait) Check(ctx *Context, node *shimast.Node) {
285
- if ctx.Checker == nil {
286
- return
287
- }
288
- ret := node.AsReturnStatement()
289
- if ret == nil || ret.Expression == nil {
290
- return
291
- }
292
- expr := stripParens(ret.Expression)
293
- if expr == nil {
294
- return
295
- }
296
- // Already `return await promise;` — author opted in.
297
- if expr.Kind == shimast.KindAwaitExpression {
298
- return
299
- }
300
- if !returnAwaitInsideHandler(node) {
301
- return
302
- }
303
- t := ctx.Checker.GetTypeAtLocation(expr)
304
- if t == nil {
305
- return
306
- }
307
- if ctx.Checker.GetPromisedTypeOfPromise(t) == nil {
308
- return
309
- }
310
- ctx.Report(node, "Returning a Promise from a try/catch/finally block requires `await` so the surrounding handler observes the rejection.")
285
+ if ctx.Checker == nil {
286
+ return
287
+ }
288
+ ret := node.AsReturnStatement()
289
+ if ret == nil || ret.Expression == nil {
290
+ return
291
+ }
292
+ expr := stripParens(ret.Expression)
293
+ if expr == nil {
294
+ return
295
+ }
296
+ // Already `return await promise;` — author opted in.
297
+ if expr.Kind == shimast.KindAwaitExpression {
298
+ return
299
+ }
300
+ if !returnAwaitInsideHandler(node) {
301
+ return
302
+ }
303
+ t := ctx.Checker.GetTypeAtLocation(expr)
304
+ if t == nil {
305
+ return
306
+ }
307
+ if ctx.Checker.GetPromisedTypeOfPromise(t) == nil {
308
+ return
309
+ }
310
+ ctx.Report(node, "Returning a Promise from a try/catch/finally block requires `await` so the surrounding handler observes the rejection.")
311
311
  }
312
312
 
313
313
  // returnAwaitInsideHandler walks the parent chain from `node` upward, stops at
@@ -319,35 +319,35 @@ func (returnAwait) Check(ctx *Context, node *shimast.Node) {
319
319
  // inside a nested function targets that inner function, so it cannot escape
320
320
  // the outer try/catch/finally and must not trip the rule.
321
321
  func returnAwaitInsideHandler(node *shimast.Node) bool {
322
- cur := node.Parent
323
- for cur != nil {
324
- if isFunctionLikeKind(cur) || cur.Kind == shimast.KindSourceFile {
325
- return false
326
- }
327
- if cur.Kind == shimast.KindBlock {
328
- grand := cur.Parent
329
- if grand != nil && grand.Kind == shimast.KindTryStatement {
330
- try := grand.AsTryStatement()
331
- if try != nil {
332
- if try.TryBlock == cur {
333
- return true
334
- }
335
- if try.FinallyBlock == cur {
336
- return true
337
- }
338
- }
339
- }
340
- }
341
- if cur.Kind == shimast.KindCatchClause {
342
- // Inside a catch: only fires when another try/catch/finally
343
- // wraps this one so the rejection can be re-observed.
344
- if hasEnclosingTryContext(cur.Parent) {
345
- return true
346
- }
347
- }
348
- cur = cur.Parent
349
- }
350
- return false
322
+ cur := node.Parent
323
+ for cur != nil {
324
+ if isFunctionLikeKind(cur) || cur.Kind == shimast.KindSourceFile {
325
+ return false
326
+ }
327
+ if cur.Kind == shimast.KindBlock {
328
+ grand := cur.Parent
329
+ if grand != nil && grand.Kind == shimast.KindTryStatement {
330
+ try := grand.AsTryStatement()
331
+ if try != nil {
332
+ if try.TryBlock == cur {
333
+ return true
334
+ }
335
+ if try.FinallyBlock == cur {
336
+ return true
337
+ }
338
+ }
339
+ }
340
+ }
341
+ if cur.Kind == shimast.KindCatchClause {
342
+ // Inside a catch: only fires when another try/catch/finally
343
+ // wraps this one so the rejection can be re-observed.
344
+ if hasEnclosingTryContext(cur.Parent) {
345
+ return true
346
+ }
347
+ }
348
+ cur = cur.Parent
349
+ }
350
+ return false
351
351
  }
352
352
 
353
353
  // hasEnclosingTryContext walks upward from `node` and reports whether the path
@@ -355,24 +355,24 @@ func returnAwaitInsideHandler(node *shimast.Node) bool {
355
355
  // finally block. Used by the catch-clause arm of returnAwaitInsideHandler to
356
356
  // decide whether the catch is itself wrapped by another handler.
357
357
  func hasEnclosingTryContext(node *shimast.Node) bool {
358
- for cur := node; cur != nil; cur = cur.Parent {
359
- if isFunctionLikeKind(cur) || cur.Kind == shimast.KindSourceFile {
360
- return false
361
- }
362
- if cur.Kind == shimast.KindBlock {
363
- grand := cur.Parent
364
- if grand != nil && grand.Kind == shimast.KindTryStatement {
365
- try := grand.AsTryStatement()
366
- if try != nil && (try.TryBlock == cur || try.FinallyBlock == cur) {
367
- return true
368
- }
369
- }
370
- }
371
- if cur.Kind == shimast.KindCatchClause {
372
- return true
373
- }
374
- }
375
- return false
358
+ for cur := node; cur != nil; cur = cur.Parent {
359
+ if isFunctionLikeKind(cur) || cur.Kind == shimast.KindSourceFile {
360
+ return false
361
+ }
362
+ if cur.Kind == shimast.KindBlock {
363
+ grand := cur.Parent
364
+ if grand != nil && grand.Kind == shimast.KindTryStatement {
365
+ try := grand.AsTryStatement()
366
+ if try != nil && (try.TryBlock == cur || try.FinallyBlock == cur) {
367
+ return true
368
+ }
369
+ }
370
+ }
371
+ if cur.Kind == shimast.KindCatchClause {
372
+ return true
373
+ }
374
+ }
375
+ return false
376
376
  }
377
377
 
378
378
  // promise/param-names mirrors eslint-plugin-promise's constructor convention:
@@ -382,800 +382,800 @@ type promiseParamNames struct{}
382
382
 
383
383
  func (promiseParamNames) Name() string { return promiseRulePrefix + "param-names" }
384
384
  func (promiseParamNames) Visits() []shimast.Kind {
385
- return []shimast.Kind{shimast.KindNewExpression}
385
+ return []shimast.Kind{shimast.KindNewExpression}
386
386
  }
387
387
  func (promiseParamNames) Check(ctx *Context, node *shimast.Node) {
388
- executor := promiseExecutor(node)
389
- if executor == nil {
390
- return
391
- }
392
- params := executor.Parameters()
393
- if len(params) > 0 {
394
- name := parameterIdentifierName(params[0])
395
- if name != "" && name != "resolve" && name != "_resolve" {
396
- ctx.Report(params[0], "Promise constructor first parameter should be named resolve.")
397
- }
398
- }
399
- if len(params) > 1 {
400
- name := parameterIdentifierName(params[1])
401
- if name != "" && name != "reject" && name != "_reject" {
402
- ctx.Report(params[1], "Promise constructor second parameter should be named reject.")
403
- }
404
- }
388
+ executor := promiseExecutor(node)
389
+ if executor == nil {
390
+ return
391
+ }
392
+ params := executor.Parameters()
393
+ if len(params) > 0 {
394
+ name := parameterIdentifierName(params[0])
395
+ if name != "" && name != "resolve" && name != "_resolve" {
396
+ ctx.Report(params[0], "Promise constructor first parameter should be named resolve.")
397
+ }
398
+ }
399
+ if len(params) > 1 {
400
+ name := parameterIdentifierName(params[1])
401
+ if name != "" && name != "reject" && name != "_reject" {
402
+ ctx.Report(params[1], "Promise constructor second parameter should be named reject.")
403
+ }
404
+ }
405
405
  }
406
406
 
407
407
  type promiseAvoidNew struct{}
408
408
 
409
409
  func (promiseAvoidNew) Name() string { return promiseRulePrefix + "avoid-new" }
410
410
  func (promiseAvoidNew) Visits() []shimast.Kind {
411
- return []shimast.Kind{shimast.KindNewExpression}
411
+ return []shimast.Kind{shimast.KindNewExpression}
412
412
  }
413
413
  func (promiseAvoidNew) Check(ctx *Context, node *shimast.Node) {
414
- ne := node.AsNewExpression()
415
- if ne != nil && identifierText(ne.Expression) == "Promise" {
416
- ctx.Report(node, "Avoid creating new promises directly.")
417
- }
414
+ ne := node.AsNewExpression()
415
+ if ne != nil && identifierText(ne.Expression) == "Promise" {
416
+ ctx.Report(node, "Avoid creating new promises directly.")
417
+ }
418
418
  }
419
419
 
420
420
  type promiseNoNewStatics struct{}
421
421
 
422
422
  func (promiseNoNewStatics) Name() string { return promiseRulePrefix + "no-new-statics" }
423
423
  func (promiseNoNewStatics) Visits() []shimast.Kind {
424
- return []shimast.Kind{shimast.KindNewExpression}
424
+ return []shimast.Kind{shimast.KindNewExpression}
425
425
  }
426
426
  func (promiseNoNewStatics) Check(ctx *Context, node *shimast.Node) {
427
- ne := node.AsNewExpression()
428
- if ne == nil {
429
- return
430
- }
431
- method, ok := promiseStaticMethod(ne.Expression)
432
- if ok {
433
- ctx.Report(node, "Avoid calling new on Promise."+method+"().")
434
- }
427
+ ne := node.AsNewExpression()
428
+ if ne == nil {
429
+ return
430
+ }
431
+ method, ok := promiseStaticMethod(ne.Expression)
432
+ if ok {
433
+ ctx.Report(node, "Avoid calling new on Promise."+method+"().")
434
+ }
435
435
  }
436
436
 
437
437
  type promiseValidParams struct{}
438
438
 
439
439
  func (promiseValidParams) Name() string { return promiseRulePrefix + "valid-params" }
440
440
  func (promiseValidParams) Visits() []shimast.Kind {
441
- return []shimast.Kind{shimast.KindCallExpression}
441
+ return []shimast.Kind{shimast.KindCallExpression}
442
442
  }
443
443
  func (promiseValidParams) Check(ctx *Context, node *shimast.Node) {
444
- call := node.AsCallExpression()
445
- if call == nil || call.Arguments == nil {
446
- return
447
- }
448
- _, method, ok := promiseCallMethod(call)
449
- if !ok {
450
- return
451
- }
452
- count := len(call.Arguments.Nodes)
453
- switch method {
454
- case "resolve", "reject":
455
- if count > 1 {
456
- ctx.Report(node, "Promise."+method+"() accepts at most one argument.")
457
- }
458
- case "then":
459
- if count < 1 || count > 2 {
460
- ctx.Report(node, "Promise then() expects one or two arguments.")
461
- }
462
- case "race", "all", "allSettled", "any", "catch", "finally":
463
- if count != 1 {
464
- ctx.Report(node, "Promise "+method+"() expects exactly one argument.")
465
- }
466
- }
444
+ call := node.AsCallExpression()
445
+ if call == nil || call.Arguments == nil {
446
+ return
447
+ }
448
+ _, method, ok := promiseCallMethod(call)
449
+ if !ok {
450
+ return
451
+ }
452
+ count := len(call.Arguments.Nodes)
453
+ switch method {
454
+ case "resolve", "reject":
455
+ if count > 1 {
456
+ ctx.Report(node, "Promise."+method+"() accepts at most one argument.")
457
+ }
458
+ case "then":
459
+ if count < 1 || count > 2 {
460
+ ctx.Report(node, "Promise then() expects one or two arguments.")
461
+ }
462
+ case "race", "all", "allSettled", "any", "catch", "finally":
463
+ if count != 1 {
464
+ ctx.Report(node, "Promise "+method+"() expects exactly one argument.")
465
+ }
466
+ }
467
467
  }
468
468
 
469
469
  type promiseSpecOnly struct{}
470
470
 
471
471
  func (promiseSpecOnly) Name() string { return promiseRulePrefix + "spec-only" }
472
472
  func (promiseSpecOnly) Visits() []shimast.Kind {
473
- return []shimast.Kind{shimast.KindPropertyAccessExpression}
473
+ return []shimast.Kind{shimast.KindPropertyAccessExpression}
474
474
  }
475
475
  func (promiseSpecOnly) Check(ctx *Context, node *shimast.Node) {
476
- obj, prop, ok := promisePropertyAccessParts(node)
477
- if !ok {
478
- return
479
- }
480
- if identifierText(obj) == "Promise" {
481
- if prop == "prototype" {
482
- return
483
- }
484
- if !isPromiseStaticMethod(prop) {
485
- ctx.Report(node, "Avoid using non-standard Promise."+prop+".")
486
- }
487
- return
488
- }
489
- base, baseProp, baseOK := promisePropertyAccessParts(obj)
490
- if baseOK && identifierText(base) == "Promise" && baseProp == "prototype" && !isPromiseInstanceMethod(prop) {
491
- ctx.Report(node, "Avoid using non-standard Promise.prototype."+prop+".")
492
- }
476
+ obj, prop, ok := promisePropertyAccessParts(node)
477
+ if !ok {
478
+ return
479
+ }
480
+ if identifierText(obj) == "Promise" {
481
+ if prop == "prototype" {
482
+ return
483
+ }
484
+ if !isPromiseStaticMethod(prop) {
485
+ ctx.Report(node, "Avoid using non-standard Promise."+prop+".")
486
+ }
487
+ return
488
+ }
489
+ base, baseProp, baseOK := promisePropertyAccessParts(obj)
490
+ if baseOK && identifierText(base) == "Promise" && baseProp == "prototype" && !isPromiseInstanceMethod(prop) {
491
+ ctx.Report(node, "Avoid using non-standard Promise.prototype."+prop+".")
492
+ }
493
493
  }
494
494
 
495
495
  type promiseNoNative struct{}
496
496
 
497
497
  func (promiseNoNative) Name() string { return promiseRulePrefix + "no-native" }
498
498
  func (promiseNoNative) Visits() []shimast.Kind {
499
- return []shimast.Kind{shimast.KindSourceFile}
499
+ return []shimast.Kind{shimast.KindSourceFile}
500
500
  }
501
501
  func (promiseNoNative) Check(ctx *Context, node *shimast.Node) {
502
- if ctx.File == nil || fileDeclaresPromise(node) {
503
- return
504
- }
505
- reported := false
506
- walkDescendants(node, func(child *shimast.Node) {
507
- if reported || child == nil {
508
- return
509
- }
510
- switch child.Kind {
511
- case shimast.KindNewExpression:
512
- ne := child.AsNewExpression()
513
- if ne != nil && identifierText(ne.Expression) == "Promise" {
514
- reported = true
515
- ctx.Report(ne.Expression, "\"Promise\" is not defined in ES5 environments.")
516
- }
517
- case shimast.KindPropertyAccessExpression:
518
- obj, _, ok := promisePropertyAccessParts(child)
519
- if ok && identifierText(obj) == "Promise" {
520
- reported = true
521
- ctx.Report(obj, "\"Promise\" is not defined in ES5 environments.")
522
- }
523
- }
524
- })
502
+ if ctx.File == nil || fileDeclaresPromise(node) {
503
+ return
504
+ }
505
+ reported := false
506
+ walkDescendants(node, func(child *shimast.Node) {
507
+ if reported || child == nil {
508
+ return
509
+ }
510
+ switch child.Kind {
511
+ case shimast.KindNewExpression:
512
+ ne := child.AsNewExpression()
513
+ if ne != nil && identifierText(ne.Expression) == "Promise" {
514
+ reported = true
515
+ ctx.Report(ne.Expression, "\"Promise\" is not defined in ES5 environments.")
516
+ }
517
+ case shimast.KindPropertyAccessExpression:
518
+ obj, _, ok := promisePropertyAccessParts(child)
519
+ if ok && identifierText(obj) == "Promise" {
520
+ reported = true
521
+ ctx.Report(obj, "\"Promise\" is not defined in ES5 environments.")
522
+ }
523
+ }
524
+ })
525
525
  }
526
526
 
527
527
  type promisePreferAwaitToThen struct{}
528
528
 
529
529
  func (promisePreferAwaitToThen) Name() string { return promiseRulePrefix + "prefer-await-to-then" }
530
530
  func (promisePreferAwaitToThen) Visits() []shimast.Kind {
531
- return []shimast.Kind{shimast.KindCallExpression}
531
+ return []shimast.Kind{shimast.KindCallExpression}
532
532
  }
533
533
  func (promisePreferAwaitToThen) Check(ctx *Context, node *shimast.Node) {
534
- call := node.AsCallExpression()
535
- _, method, ok := promiseCallMethod(call)
536
- if ok && isPromiseInstanceMethod(method) {
537
- ctx.Report(node, "Prefer async/await to promise "+method+"() chains.")
538
- }
534
+ call := node.AsCallExpression()
535
+ _, method, ok := promiseCallMethod(call)
536
+ if ok && isPromiseInstanceMethod(method) {
537
+ ctx.Report(node, "Prefer async/await to promise "+method+"() chains.")
538
+ }
539
539
  }
540
540
 
541
541
  type promisePreferCatch struct{}
542
542
 
543
543
  func (promisePreferCatch) Name() string { return promiseRulePrefix + "prefer-catch" }
544
544
  func (promisePreferCatch) Visits() []shimast.Kind {
545
- return []shimast.Kind{shimast.KindCallExpression}
545
+ return []shimast.Kind{shimast.KindCallExpression}
546
546
  }
547
547
  func (promisePreferCatch) Check(ctx *Context, node *shimast.Node) {
548
- call := node.AsCallExpression()
549
- _, method, ok := promiseCallMethod(call)
550
- if !ok || method != "then" || call.Arguments == nil || len(call.Arguments.Nodes) < 2 {
551
- return
552
- }
553
- ctx.Report(call.Arguments.Nodes[1], "Prefer catch() to passing a rejection handler to then().")
548
+ call := node.AsCallExpression()
549
+ _, method, ok := promiseCallMethod(call)
550
+ if !ok || method != "then" || call.Arguments == nil || len(call.Arguments.Nodes) < 2 {
551
+ return
552
+ }
553
+ ctx.Report(call.Arguments.Nodes[1], "Prefer catch() to passing a rejection handler to then().")
554
554
  }
555
555
 
556
556
  type promiseCatchOrReturn struct{}
557
557
 
558
558
  func (promiseCatchOrReturn) Name() string { return promiseRulePrefix + "catch-or-return" }
559
559
  func (promiseCatchOrReturn) Visits() []shimast.Kind {
560
- return []shimast.Kind{shimast.KindExpressionStatement}
560
+ return []shimast.Kind{shimast.KindExpressionStatement}
561
561
  }
562
562
  func (promiseCatchOrReturn) Check(ctx *Context, node *shimast.Node) {
563
- stmt := node.AsExpressionStatement()
564
- if stmt == nil || stmt.Expression == nil {
565
- return
566
- }
567
- if promiseChainHasMethod(stmt.Expression, "then") && !promiseChainHasMethod(stmt.Expression, "catch") {
568
- ctx.Report(node, "Promise chains should be returned or terminated with catch().")
569
- }
563
+ stmt := node.AsExpressionStatement()
564
+ if stmt == nil || stmt.Expression == nil {
565
+ return
566
+ }
567
+ if promiseChainHasMethod(stmt.Expression, "then") && !promiseChainHasMethod(stmt.Expression, "catch") {
568
+ ctx.Report(node, "Promise chains should be returned or terminated with catch().")
569
+ }
570
570
  }
571
571
 
572
572
  type promiseAlwaysReturn struct{}
573
573
 
574
574
  func (promiseAlwaysReturn) Name() string { return promiseRulePrefix + "always-return" }
575
575
  func (promiseAlwaysReturn) Visits() []shimast.Kind {
576
- return []shimast.Kind{shimast.KindCallExpression}
576
+ return []shimast.Kind{shimast.KindCallExpression}
577
577
  }
578
578
  func (promiseAlwaysReturn) Check(ctx *Context, node *shimast.Node) {
579
- call := node.AsCallExpression()
580
- _, method, ok := promiseCallMethod(call)
581
- if !ok || method != "then" || call.Arguments == nil || len(call.Arguments.Nodes) == 0 {
582
- return
583
- }
584
- callback := stripParens(call.Arguments.Nodes[0])
585
- if callback == nil || !isFunctionLikeKind(callback) {
586
- return
587
- }
588
- body := callback.Body()
589
- if body == nil || body.Kind != shimast.KindBlock {
590
- return
591
- }
592
- if !blockReturnsOrThrows(body) {
593
- ctx.Report(callback, "Each then() callback should return a value or throw.")
594
- }
579
+ call := node.AsCallExpression()
580
+ _, method, ok := promiseCallMethod(call)
581
+ if !ok || method != "then" || call.Arguments == nil || len(call.Arguments.Nodes) == 0 {
582
+ return
583
+ }
584
+ callback := stripParens(call.Arguments.Nodes[0])
585
+ if callback == nil || !isFunctionLikeKind(callback) {
586
+ return
587
+ }
588
+ body := callback.Body()
589
+ if body == nil || body.Kind != shimast.KindBlock {
590
+ return
591
+ }
592
+ if !blockReturnsOrThrows(body) {
593
+ ctx.Report(callback, "Each then() callback should return a value or throw.")
594
+ }
595
595
  }
596
596
 
597
597
  type promiseNoReturnWrap struct{}
598
598
 
599
599
  func (promiseNoReturnWrap) Name() string { return promiseRulePrefix + "no-return-wrap" }
600
600
  func (promiseNoReturnWrap) Visits() []shimast.Kind {
601
- return []shimast.Kind{shimast.KindReturnStatement, shimast.KindArrowFunction}
601
+ return []shimast.Kind{shimast.KindReturnStatement, shimast.KindArrowFunction}
602
602
  }
603
603
  func (promiseNoReturnWrap) Check(ctx *Context, node *shimast.Node) {
604
- switch node.Kind {
605
- case shimast.KindReturnStatement:
606
- ret := node.AsReturnStatement()
607
- if ret == nil || ret.Expression == nil || !isInsidePromiseCallbackFunction(node) {
608
- return
609
- }
610
- if method, ok := promiseResolveRejectCall(ret.Expression); ok {
611
- ctx.Report(ret.Expression, "Avoid wrapping return values in Promise."+method+"().")
612
- }
613
- case shimast.KindArrowFunction:
614
- arrow := node.AsArrowFunction()
615
- if arrow == nil || arrow.Body == nil || arrow.Body.Kind == shimast.KindBlock || !isPromiseCallbackFunction(node) {
616
- return
617
- }
618
- if method, ok := promiseResolveRejectCall(arrow.Body); ok {
619
- ctx.Report(arrow.Body, "Avoid wrapping return values in Promise."+method+"().")
620
- }
621
- }
604
+ switch node.Kind {
605
+ case shimast.KindReturnStatement:
606
+ ret := node.AsReturnStatement()
607
+ if ret == nil || ret.Expression == nil || !isInsidePromiseCallbackFunction(node) {
608
+ return
609
+ }
610
+ if method, ok := promiseResolveRejectCall(ret.Expression); ok {
611
+ ctx.Report(ret.Expression, "Avoid wrapping return values in Promise."+method+"().")
612
+ }
613
+ case shimast.KindArrowFunction:
614
+ arrow := node.AsArrowFunction()
615
+ if arrow == nil || arrow.Body == nil || arrow.Body.Kind == shimast.KindBlock || !isPromiseCallbackFunction(node) {
616
+ return
617
+ }
618
+ if method, ok := promiseResolveRejectCall(arrow.Body); ok {
619
+ ctx.Report(arrow.Body, "Avoid wrapping return values in Promise."+method+"().")
620
+ }
621
+ }
622
622
  }
623
623
 
624
624
  type promiseNoReturnInFinally struct{}
625
625
 
626
626
  func (promiseNoReturnInFinally) Name() string { return promiseRulePrefix + "no-return-in-finally" }
627
627
  func (promiseNoReturnInFinally) Visits() []shimast.Kind {
628
- return []shimast.Kind{shimast.KindReturnStatement}
628
+ return []shimast.Kind{shimast.KindReturnStatement}
629
629
  }
630
630
  func (promiseNoReturnInFinally) Check(ctx *Context, node *shimast.Node) {
631
- if fn := nearestFunctionLike(node); fn != nil && isPromiseCallbackFunctionFor(fn, "finally") {
632
- ctx.Report(node, "Do not return from a Promise finally() callback.")
633
- }
631
+ if fn := nearestFunctionLike(node); fn != nil && isPromiseCallbackFunctionFor(fn, "finally") {
632
+ ctx.Report(node, "Do not return from a Promise finally() callback.")
633
+ }
634
634
  }
635
635
 
636
636
  type promiseNoNesting struct{}
637
637
 
638
638
  func (promiseNoNesting) Name() string { return promiseRulePrefix + "no-nesting" }
639
639
  func (promiseNoNesting) Visits() []shimast.Kind {
640
- return []shimast.Kind{shimast.KindCallExpression}
640
+ return []shimast.Kind{shimast.KindCallExpression}
641
641
  }
642
642
  func (promiseNoNesting) Check(ctx *Context, node *shimast.Node) {
643
- call := node.AsCallExpression()
644
- _, method, ok := promiseCallMethod(call)
645
- if !ok || (method != "then" && method != "catch") {
646
- return
647
- }
648
- if fn := nearestFunctionLike(node); fn != nil && isPromiseCallbackFunction(fn) {
649
- ctx.Report(node, "Avoid nesting promise callbacks.")
650
- }
643
+ call := node.AsCallExpression()
644
+ _, method, ok := promiseCallMethod(call)
645
+ if !ok || (method != "then" && method != "catch") {
646
+ return
647
+ }
648
+ if fn := nearestFunctionLike(node); fn != nil && isPromiseCallbackFunction(fn) {
649
+ ctx.Report(node, "Avoid nesting promise callbacks.")
650
+ }
651
651
  }
652
652
 
653
653
  type promiseNoCallbackInPromise struct{}
654
654
 
655
655
  func (promiseNoCallbackInPromise) Name() string { return promiseRulePrefix + "no-callback-in-promise" }
656
656
  func (promiseNoCallbackInPromise) Visits() []shimast.Kind {
657
- return []shimast.Kind{shimast.KindCallExpression}
657
+ return []shimast.Kind{shimast.KindCallExpression}
658
658
  }
659
659
  func (promiseNoCallbackInPromise) Check(ctx *Context, node *shimast.Node) {
660
- call := node.AsCallExpression()
661
- if call == nil {
662
- return
663
- }
664
- if isCallbackCall(call) {
665
- if fn := nearestFunctionLike(node); fn != nil && isPromiseCallbackFunction(fn) {
666
- ctx.Report(node, "Avoid calling callbacks inside promise callbacks.")
667
- }
668
- return
669
- }
670
- _, method, ok := promiseCallMethod(call)
671
- if !ok || (method != "then" && method != "catch") || call.Arguments == nil || len(call.Arguments.Nodes) == 0 {
672
- return
673
- }
674
- first := stripParens(call.Arguments.Nodes[0])
675
- if first != nil && first.Kind == shimast.KindIdentifier && isCallbackName(identifierText(first)) {
676
- ctx.Report(first, "Avoid passing callbacks into promise chains.")
677
- }
660
+ call := node.AsCallExpression()
661
+ if call == nil {
662
+ return
663
+ }
664
+ if isCallbackCall(call) {
665
+ if fn := nearestFunctionLike(node); fn != nil && isPromiseCallbackFunction(fn) {
666
+ ctx.Report(node, "Avoid calling callbacks inside promise callbacks.")
667
+ }
668
+ return
669
+ }
670
+ _, method, ok := promiseCallMethod(call)
671
+ if !ok || (method != "then" && method != "catch") || call.Arguments == nil || len(call.Arguments.Nodes) == 0 {
672
+ return
673
+ }
674
+ first := stripParens(call.Arguments.Nodes[0])
675
+ if first != nil && first.Kind == shimast.KindIdentifier && isCallbackName(identifierText(first)) {
676
+ ctx.Report(first, "Avoid passing callbacks into promise chains.")
677
+ }
678
678
  }
679
679
 
680
680
  type promiseNoPromiseInCallback struct{}
681
681
 
682
682
  func (promiseNoPromiseInCallback) Name() string { return promiseRulePrefix + "no-promise-in-callback" }
683
683
  func (promiseNoPromiseInCallback) Visits() []shimast.Kind {
684
- return []shimast.Kind{shimast.KindCallExpression}
684
+ return []shimast.Kind{shimast.KindCallExpression}
685
685
  }
686
686
  func (promiseNoPromiseInCallback) Check(ctx *Context, node *shimast.Node) {
687
- call := node.AsCallExpression()
688
- if call == nil || !isPromiseLikeCall(call) || isDirectReturnValue(node) {
689
- return
690
- }
691
- if fn := nearestFunctionLike(node); fn != nil && isErrorFirstCallback(fn) {
692
- ctx.Report(call.Expression, "Avoid using promises inside callbacks.")
693
- }
687
+ call := node.AsCallExpression()
688
+ if call == nil || !isPromiseLikeCall(call) || isDirectReturnValue(node) {
689
+ return
690
+ }
691
+ if fn := nearestFunctionLike(node); fn != nil && isErrorFirstCallback(fn) {
692
+ ctx.Report(call.Expression, "Avoid using promises inside callbacks.")
693
+ }
694
694
  }
695
695
 
696
696
  type promisePreferAwaitToCallbacks struct{}
697
697
 
698
698
  func (promisePreferAwaitToCallbacks) Name() string {
699
- return promiseRulePrefix + "prefer-await-to-callbacks"
699
+ return promiseRulePrefix + "prefer-await-to-callbacks"
700
700
  }
701
701
  func (promisePreferAwaitToCallbacks) Visits() []shimast.Kind {
702
- return []shimast.Kind{
703
- shimast.KindCallExpression,
704
- shimast.KindFunctionDeclaration,
705
- shimast.KindFunctionExpression,
706
- shimast.KindArrowFunction,
707
- }
702
+ return []shimast.Kind{
703
+ shimast.KindCallExpression,
704
+ shimast.KindFunctionDeclaration,
705
+ shimast.KindFunctionExpression,
706
+ shimast.KindArrowFunction,
707
+ }
708
708
  }
709
709
  func (promisePreferAwaitToCallbacks) Check(ctx *Context, node *shimast.Node) {
710
- switch node.Kind {
711
- case shimast.KindCallExpression:
712
- call := node.AsCallExpression()
713
- if call == nil {
714
- return
715
- }
716
- if isCallbackCall(call) {
717
- ctx.Report(node, "Avoid callbacks. Prefer async/await.")
718
- return
719
- }
720
- if hasErrorFirstCallbackArgument(call) && !isInsideAwaitOrYield(node) {
721
- ctx.Report(node, "Avoid callbacks. Prefer async/await.")
722
- }
723
- default:
724
- params := node.Parameters()
725
- if len(params) == 0 {
726
- return
727
- }
728
- lastName := parameterIdentifierName(params[len(params)-1])
729
- if lastName == "callback" || lastName == "cb" {
730
- ctx.Report(params[len(params)-1], "Avoid callbacks. Prefer async/await.")
731
- }
732
- }
710
+ switch node.Kind {
711
+ case shimast.KindCallExpression:
712
+ call := node.AsCallExpression()
713
+ if call == nil {
714
+ return
715
+ }
716
+ if isCallbackCall(call) {
717
+ ctx.Report(node, "Avoid callbacks. Prefer async/await.")
718
+ return
719
+ }
720
+ if hasErrorFirstCallbackArgument(call) && !isInsideAwaitOrYield(node) {
721
+ ctx.Report(node, "Avoid callbacks. Prefer async/await.")
722
+ }
723
+ default:
724
+ params := node.Parameters()
725
+ if len(params) == 0 {
726
+ return
727
+ }
728
+ lastName := parameterIdentifierName(params[len(params)-1])
729
+ if lastName == "callback" || lastName == "cb" {
730
+ ctx.Report(params[len(params)-1], "Avoid callbacks. Prefer async/await.")
731
+ }
732
+ }
733
733
  }
734
734
 
735
735
  type promiseNoMultipleResolved struct{}
736
736
 
737
737
  func (promiseNoMultipleResolved) Name() string { return promiseRulePrefix + "no-multiple-resolved" }
738
738
  func (promiseNoMultipleResolved) Visits() []shimast.Kind {
739
- return []shimast.Kind{shimast.KindNewExpression}
739
+ return []shimast.Kind{shimast.KindNewExpression}
740
740
  }
741
741
  func (promiseNoMultipleResolved) Check(ctx *Context, node *shimast.Node) {
742
- executor := promiseExecutor(node)
743
- if executor == nil {
744
- return
745
- }
746
- params := executor.Parameters()
747
- resolverNames := map[string]bool{}
748
- for i := 0; i < len(params) && i < 2; i++ {
749
- if name := parameterIdentifierName(params[i]); name != "" {
750
- resolverNames[name] = true
751
- }
752
- }
753
- if len(resolverNames) == 0 {
754
- return
755
- }
756
- count := 0
757
- walkFunctionBody(executor, func(child *shimast.Node) {
758
- if child == nil || child.Kind != shimast.KindCallExpression {
759
- return
760
- }
761
- call := child.AsCallExpression()
762
- if call == nil || !resolverNames[callCalleeName(call)] {
763
- return
764
- }
765
- count++
766
- if count > 1 {
767
- ctx.Report(child, "Promise should not be resolved multiple times.")
768
- }
769
- })
742
+ executor := promiseExecutor(node)
743
+ if executor == nil {
744
+ return
745
+ }
746
+ params := executor.Parameters()
747
+ resolverNames := map[string]bool{}
748
+ for i := 0; i < len(params) && i < 2; i++ {
749
+ if name := parameterIdentifierName(params[i]); name != "" {
750
+ resolverNames[name] = true
751
+ }
752
+ }
753
+ if len(resolverNames) == 0 {
754
+ return
755
+ }
756
+ count := 0
757
+ walkFunctionBody(executor, func(child *shimast.Node) {
758
+ if child == nil || child.Kind != shimast.KindCallExpression {
759
+ return
760
+ }
761
+ call := child.AsCallExpression()
762
+ if call == nil || !resolverNames[callCalleeName(call)] {
763
+ return
764
+ }
765
+ count++
766
+ if count > 1 {
767
+ ctx.Report(child, "Promise should not be resolved multiple times.")
768
+ }
769
+ })
770
770
  }
771
771
 
772
772
  func promiseExecutor(node *shimast.Node) *shimast.Node {
773
- ne := node.AsNewExpression()
774
- if ne == nil || identifierText(ne.Expression) != "Promise" || ne.Arguments == nil || len(ne.Arguments.Nodes) == 0 {
775
- return nil
776
- }
777
- executor := stripParens(ne.Arguments.Nodes[0])
778
- if executor == nil || !isFunctionLikeKind(executor) {
779
- return nil
780
- }
781
- return executor
773
+ ne := node.AsNewExpression()
774
+ if ne == nil || identifierText(ne.Expression) != "Promise" || ne.Arguments == nil || len(ne.Arguments.Nodes) == 0 {
775
+ return nil
776
+ }
777
+ executor := stripParens(ne.Arguments.Nodes[0])
778
+ if executor == nil || !isFunctionLikeKind(executor) {
779
+ return nil
780
+ }
781
+ return executor
782
782
  }
783
783
 
784
784
  func parameterIdentifierName(node *shimast.Node) string {
785
- if node == nil {
786
- return ""
787
- }
788
- param := node.AsParameterDeclaration()
789
- if param == nil {
790
- return ""
791
- }
792
- return identifierText(param.Name())
785
+ if node == nil {
786
+ return ""
787
+ }
788
+ param := node.AsParameterDeclaration()
789
+ if param == nil {
790
+ return ""
791
+ }
792
+ return identifierText(param.Name())
793
793
  }
794
794
 
795
795
  func promisePropertyAccessParts(node *shimast.Node) (*shimast.Node, string, bool) {
796
- node = stripParens(node)
797
- if node == nil || node.Kind != shimast.KindPropertyAccessExpression {
798
- return nil, "", false
799
- }
800
- access := node.AsPropertyAccessExpression()
801
- if access == nil {
802
- return nil, "", false
803
- }
804
- prop := identifierText(access.Name())
805
- return access.Expression, prop, prop != ""
796
+ node = stripParens(node)
797
+ if node == nil || node.Kind != shimast.KindPropertyAccessExpression {
798
+ return nil, "", false
799
+ }
800
+ access := node.AsPropertyAccessExpression()
801
+ if access == nil {
802
+ return nil, "", false
803
+ }
804
+ prop := identifierText(access.Name())
805
+ return access.Expression, prop, prop != ""
806
806
  }
807
807
 
808
808
  func promiseCallMethod(call *shimast.CallExpression) (*shimast.Node, string, bool) {
809
- if call == nil || call.Expression == nil {
810
- return nil, "", false
811
- }
812
- object, method, ok := promisePropertyAccessParts(call.Expression)
813
- if !ok {
814
- return nil, "", false
815
- }
816
- if identifierText(object) == "Promise" && !isPromiseStaticMethod(method) {
817
- return nil, "", false
818
- }
819
- return object, method, true
809
+ if call == nil || call.Expression == nil {
810
+ return nil, "", false
811
+ }
812
+ object, method, ok := promisePropertyAccessParts(call.Expression)
813
+ if !ok {
814
+ return nil, "", false
815
+ }
816
+ if identifierText(object) == "Promise" && !isPromiseStaticMethod(method) {
817
+ return nil, "", false
818
+ }
819
+ return object, method, true
820
820
  }
821
821
 
822
822
  func promiseStaticMethod(node *shimast.Node) (string, bool) {
823
- object, method, ok := promisePropertyAccessParts(node)
824
- if !ok || identifierText(object) != "Promise" || !isPromiseStaticMethod(method) {
825
- return "", false
826
- }
827
- return method, true
823
+ object, method, ok := promisePropertyAccessParts(node)
824
+ if !ok || identifierText(object) != "Promise" || !isPromiseStaticMethod(method) {
825
+ return "", false
826
+ }
827
+ return method, true
828
828
  }
829
829
 
830
830
  func isPromiseStaticMethod(method string) bool {
831
- switch method {
832
- case "all", "allSettled", "any", "race", "reject", "resolve", "withResolvers":
833
- return true
834
- }
835
- return false
831
+ switch method {
832
+ case "all", "allSettled", "any", "race", "reject", "resolve", "withResolvers":
833
+ return true
834
+ }
835
+ return false
836
836
  }
837
837
 
838
838
  func isPromiseInstanceMethod(method string) bool {
839
- switch method {
840
- case "then", "catch", "finally":
841
- return true
842
- }
843
- return false
839
+ switch method {
840
+ case "then", "catch", "finally":
841
+ return true
842
+ }
843
+ return false
844
844
  }
845
845
 
846
846
  func isPromiseLikeCall(call *shimast.CallExpression) bool {
847
- object, method, ok := promiseCallMethod(call)
848
- if !ok {
849
- return false
850
- }
851
- if isPromiseInstanceMethod(method) {
852
- return true
853
- }
854
- return identifierText(object) == "Promise" && isPromiseStaticMethod(method)
847
+ object, method, ok := promiseCallMethod(call)
848
+ if !ok {
849
+ return false
850
+ }
851
+ if isPromiseInstanceMethod(method) {
852
+ return true
853
+ }
854
+ return identifierText(object) == "Promise" && isPromiseStaticMethod(method)
855
855
  }
856
856
 
857
857
  func promiseChainHasMethod(node *shimast.Node, want string) bool {
858
- node = stripParens(node)
859
- for node != nil && node.Kind == shimast.KindCallExpression {
860
- call := node.AsCallExpression()
861
- object, method, ok := promiseCallMethod(call)
862
- if !ok {
863
- return false
864
- }
865
- if method == want {
866
- return true
867
- }
868
- node = object
869
- }
870
- return false
858
+ node = stripParens(node)
859
+ for node != nil && node.Kind == shimast.KindCallExpression {
860
+ call := node.AsCallExpression()
861
+ object, method, ok := promiseCallMethod(call)
862
+ if !ok {
863
+ return false
864
+ }
865
+ if method == want {
866
+ return true
867
+ }
868
+ node = object
869
+ }
870
+ return false
871
871
  }
872
872
 
873
873
  func promiseResolveRejectCall(node *shimast.Node) (string, bool) {
874
- node = stripParens(node)
875
- if node == nil || node.Kind != shimast.KindCallExpression {
876
- return "", false
877
- }
878
- call := node.AsCallExpression()
879
- object, method, ok := promiseCallMethod(call)
880
- if !ok || identifierText(object) != "Promise" || (method != "resolve" && method != "reject") {
881
- return "", false
882
- }
883
- return method, true
874
+ node = stripParens(node)
875
+ if node == nil || node.Kind != shimast.KindCallExpression {
876
+ return "", false
877
+ }
878
+ call := node.AsCallExpression()
879
+ object, method, ok := promiseCallMethod(call)
880
+ if !ok || identifierText(object) != "Promise" || (method != "resolve" && method != "reject") {
881
+ return "", false
882
+ }
883
+ return method, true
884
884
  }
885
885
 
886
886
  func nearestFunctionLike(node *shimast.Node) *shimast.Node {
887
- for cur := node.Parent; cur != nil; cur = cur.Parent {
888
- if isFunctionLikeKind(cur) {
889
- return cur
890
- }
891
- }
892
- return nil
887
+ for cur := node.Parent; cur != nil; cur = cur.Parent {
888
+ if isFunctionLikeKind(cur) {
889
+ return cur
890
+ }
891
+ }
892
+ return nil
893
893
  }
894
894
 
895
895
  func isInsidePromiseCallbackFunction(node *shimast.Node) bool {
896
- if fn := nearestFunctionLike(node); fn != nil {
897
- return isPromiseCallbackFunction(fn)
898
- }
899
- return false
896
+ if fn := nearestFunctionLike(node); fn != nil {
897
+ return isPromiseCallbackFunction(fn)
898
+ }
899
+ return false
900
900
  }
901
901
 
902
902
  func isPromiseCallbackFunction(fn *shimast.Node) bool {
903
- return isPromiseCallbackFunctionFor(fn, "then") ||
904
- isPromiseCallbackFunctionFor(fn, "catch") ||
905
- isPromiseCallbackFunctionFor(fn, "finally")
903
+ return isPromiseCallbackFunctionFor(fn, "then") ||
904
+ isPromiseCallbackFunctionFor(fn, "catch") ||
905
+ isPromiseCallbackFunctionFor(fn, "finally")
906
906
  }
907
907
 
908
908
  func isPromiseCallbackFunctionFor(fn *shimast.Node, method string) bool {
909
- if fn == nil || !isFunctionLikeKind(fn) {
910
- return false
911
- }
912
- for parent := fn.Parent; parent != nil && parent.Kind == shimast.KindParenthesizedExpression; parent = parent.Parent {
913
- fn = parent
914
- }
915
- callNode := fn.Parent
916
- if callNode == nil || callNode.Kind != shimast.KindCallExpression {
917
- return false
918
- }
919
- call := callNode.AsCallExpression()
920
- if call == nil || call.Arguments == nil {
921
- return false
922
- }
923
- found := false
924
- for _, arg := range call.Arguments.Nodes {
925
- if stripParens(arg) == fn {
926
- found = true
927
- break
928
- }
929
- }
930
- if !found {
931
- return false
932
- }
933
- _, actual, ok := promiseCallMethod(call)
934
- return ok && actual == method
909
+ if fn == nil || !isFunctionLikeKind(fn) {
910
+ return false
911
+ }
912
+ for parent := fn.Parent; parent != nil && parent.Kind == shimast.KindParenthesizedExpression; parent = parent.Parent {
913
+ fn = parent
914
+ }
915
+ callNode := fn.Parent
916
+ if callNode == nil || callNode.Kind != shimast.KindCallExpression {
917
+ return false
918
+ }
919
+ call := callNode.AsCallExpression()
920
+ if call == nil || call.Arguments == nil {
921
+ return false
922
+ }
923
+ found := false
924
+ for _, arg := range call.Arguments.Nodes {
925
+ if stripParens(arg) == fn {
926
+ found = true
927
+ break
928
+ }
929
+ }
930
+ if !found {
931
+ return false
932
+ }
933
+ _, actual, ok := promiseCallMethod(call)
934
+ return ok && actual == method
935
935
  }
936
936
 
937
937
  func blockReturnsOrThrows(block *shimast.Node) bool {
938
- if block == nil || block.Kind != shimast.KindBlock {
939
- return false
940
- }
941
- return statementsReturnOrThrow(block.Statements())
938
+ if block == nil || block.Kind != shimast.KindBlock {
939
+ return false
940
+ }
941
+ return statementsReturnOrThrow(block.Statements())
942
942
  }
943
943
 
944
944
  func statementsReturnOrThrow(statements []*shimast.Node) bool {
945
- for _, stmt := range statements {
946
- if statementReturnsOrThrows(stmt) {
947
- return true
948
- }
949
- }
950
- return false
945
+ for _, stmt := range statements {
946
+ if statementReturnsOrThrows(stmt) {
947
+ return true
948
+ }
949
+ }
950
+ return false
951
951
  }
952
952
 
953
953
  func statementReturnsOrThrows(stmt *shimast.Node) bool {
954
- if stmt == nil {
955
- return false
956
- }
957
- switch stmt.Kind {
958
- case shimast.KindReturnStatement, shimast.KindThrowStatement:
959
- return true
960
- case shimast.KindBlock:
961
- return statementsReturnOrThrow(stmt.Statements())
962
- case shimast.KindIfStatement:
963
- ifStmt := stmt.AsIfStatement()
964
- if ifStmt == nil || ifStmt.ThenStatement == nil || ifStmt.ElseStatement == nil {
965
- return false
966
- }
967
- return statementReturnsOrThrows(ifStmt.ThenStatement) &&
968
- statementReturnsOrThrows(ifStmt.ElseStatement)
969
- case shimast.KindTryStatement:
970
- return tryStatementReturnsOrThrows(stmt)
971
- case shimast.KindSwitchStatement:
972
- return switchStatementReturnsOrThrows(stmt)
973
- case shimast.KindLabeledStatement:
974
- labeled := stmt.AsLabeledStatement()
975
- return labeled != nil && statementReturnsOrThrows(labeled.Statement)
976
- }
977
- return false
954
+ if stmt == nil {
955
+ return false
956
+ }
957
+ switch stmt.Kind {
958
+ case shimast.KindReturnStatement, shimast.KindThrowStatement:
959
+ return true
960
+ case shimast.KindBlock:
961
+ return statementsReturnOrThrow(stmt.Statements())
962
+ case shimast.KindIfStatement:
963
+ ifStmt := stmt.AsIfStatement()
964
+ if ifStmt == nil || ifStmt.ThenStatement == nil || ifStmt.ElseStatement == nil {
965
+ return false
966
+ }
967
+ return statementReturnsOrThrows(ifStmt.ThenStatement) &&
968
+ statementReturnsOrThrows(ifStmt.ElseStatement)
969
+ case shimast.KindTryStatement:
970
+ return tryStatementReturnsOrThrows(stmt)
971
+ case shimast.KindSwitchStatement:
972
+ return switchStatementReturnsOrThrows(stmt)
973
+ case shimast.KindLabeledStatement:
974
+ labeled := stmt.AsLabeledStatement()
975
+ return labeled != nil && statementReturnsOrThrows(labeled.Statement)
976
+ }
977
+ return false
978
978
  }
979
979
 
980
980
  func tryStatementReturnsOrThrows(stmt *shimast.Node) bool {
981
- tryStmt := stmt.AsTryStatement()
982
- if tryStmt == nil {
983
- return false
984
- }
985
- if tryStmt.FinallyBlock != nil && statementsReturnOrThrow(tryStmt.FinallyBlock.Statements()) {
986
- return true
987
- }
988
- if tryStmt.TryBlock == nil || !statementsReturnOrThrow(tryStmt.TryBlock.Statements()) {
989
- return false
990
- }
991
- if tryStmt.CatchClause == nil {
992
- return true
993
- }
994
- catchClause := tryStmt.CatchClause.AsCatchClause()
995
- return catchClause != nil &&
996
- catchClause.Block != nil &&
997
- statementsReturnOrThrow(catchClause.Block.Statements())
981
+ tryStmt := stmt.AsTryStatement()
982
+ if tryStmt == nil {
983
+ return false
984
+ }
985
+ if tryStmt.FinallyBlock != nil && statementsReturnOrThrow(tryStmt.FinallyBlock.Statements()) {
986
+ return true
987
+ }
988
+ if tryStmt.TryBlock == nil || !statementsReturnOrThrow(tryStmt.TryBlock.Statements()) {
989
+ return false
990
+ }
991
+ if tryStmt.CatchClause == nil {
992
+ return true
993
+ }
994
+ catchClause := tryStmt.CatchClause.AsCatchClause()
995
+ return catchClause != nil &&
996
+ catchClause.Block != nil &&
997
+ statementsReturnOrThrow(catchClause.Block.Statements())
998
998
  }
999
999
 
1000
1000
  func switchStatementReturnsOrThrows(stmt *shimast.Node) bool {
1001
- switchStmt := stmt.AsSwitchStatement()
1002
- if switchStmt == nil || switchStmt.CaseBlock == nil {
1003
- return false
1004
- }
1005
- caseBlock := switchStmt.CaseBlock.AsCaseBlock()
1006
- if caseBlock == nil || caseBlock.Clauses == nil {
1007
- return false
1008
- }
1009
- clauses := caseBlock.Clauses.Nodes
1010
- hasDefault := false
1011
- for index, clauseNode := range clauses {
1012
- if clauseNode == nil {
1013
- return false
1014
- }
1015
- if clauseNode.Kind == shimast.KindDefaultClause {
1016
- hasDefault = true
1017
- }
1018
- if !switchClauseEntryReturnsOrThrows(clauses[index:]) {
1019
- return false
1020
- }
1021
- }
1022
- return hasDefault
1001
+ switchStmt := stmt.AsSwitchStatement()
1002
+ if switchStmt == nil || switchStmt.CaseBlock == nil {
1003
+ return false
1004
+ }
1005
+ caseBlock := switchStmt.CaseBlock.AsCaseBlock()
1006
+ if caseBlock == nil || caseBlock.Clauses == nil {
1007
+ return false
1008
+ }
1009
+ clauses := caseBlock.Clauses.Nodes
1010
+ hasDefault := false
1011
+ for index, clauseNode := range clauses {
1012
+ if clauseNode == nil {
1013
+ return false
1014
+ }
1015
+ if clauseNode.Kind == shimast.KindDefaultClause {
1016
+ hasDefault = true
1017
+ }
1018
+ if !switchClauseEntryReturnsOrThrows(clauses[index:]) {
1019
+ return false
1020
+ }
1021
+ }
1022
+ return hasDefault
1023
1023
  }
1024
1024
 
1025
1025
  func switchClauseEntryReturnsOrThrows(clauses []*shimast.Node) bool {
1026
- for _, clauseNode := range clauses {
1027
- clause := clauseNode.AsCaseOrDefaultClause()
1028
- if clause == nil || clause.Statements == nil {
1029
- return false
1030
- }
1031
- if statementsReturnOrThrow(clause.Statements.Nodes) {
1032
- return true
1033
- }
1034
- }
1035
- return false
1026
+ for _, clauseNode := range clauses {
1027
+ clause := clauseNode.AsCaseOrDefaultClause()
1028
+ if clause == nil || clause.Statements == nil {
1029
+ return false
1030
+ }
1031
+ if statementsReturnOrThrow(clause.Statements.Nodes) {
1032
+ return true
1033
+ }
1034
+ }
1035
+ return false
1036
1036
  }
1037
1037
 
1038
1038
  func walkFunctionBody(root *shimast.Node, visit func(*shimast.Node)) {
1039
- if root == nil {
1040
- return
1041
- }
1042
- var walk func(*shimast.Node)
1043
- walk = func(node *shimast.Node) {
1044
- if node == nil {
1045
- return
1046
- }
1047
- if node != root && isFunctionLikeKind(node) {
1048
- return
1049
- }
1050
- visit(node)
1051
- node.ForEachChild(func(child *shimast.Node) bool {
1052
- walk(child)
1053
- return false
1054
- })
1055
- }
1056
- walk(root)
1039
+ if root == nil {
1040
+ return
1041
+ }
1042
+ var walk func(*shimast.Node)
1043
+ walk = func(node *shimast.Node) {
1044
+ if node == nil {
1045
+ return
1046
+ }
1047
+ if node != root && isFunctionLikeKind(node) {
1048
+ return
1049
+ }
1050
+ visit(node)
1051
+ node.ForEachChild(func(child *shimast.Node) bool {
1052
+ walk(child)
1053
+ return false
1054
+ })
1055
+ }
1056
+ walk(root)
1057
1057
  }
1058
1058
 
1059
1059
  func isCallbackName(name string) bool {
1060
- switch name {
1061
- case "callback", "cb", "next", "done":
1062
- return true
1063
- }
1064
- return false
1060
+ switch name {
1061
+ case "callback", "cb", "next", "done":
1062
+ return true
1063
+ }
1064
+ return false
1065
1065
  }
1066
1066
 
1067
1067
  func isCallbackCall(call *shimast.CallExpression) bool {
1068
- if call == nil {
1069
- return false
1070
- }
1071
- if isCallbackName(callCalleeName(call)) {
1072
- return true
1073
- }
1074
- return false
1068
+ if call == nil {
1069
+ return false
1070
+ }
1071
+ if isCallbackName(callCalleeName(call)) {
1072
+ return true
1073
+ }
1074
+ return false
1075
1075
  }
1076
1076
 
1077
1077
  func isErrorFirstCallback(fn *shimast.Node) bool {
1078
- if fn == nil || !isFunctionLikeKind(fn) || isPromiseCallbackFunction(fn) {
1079
- return false
1080
- }
1081
- params := fn.Parameters()
1082
- if len(params) == 0 {
1083
- return false
1084
- }
1085
- switch parameterIdentifierName(params[0]) {
1086
- case "err", "error":
1087
- return true
1088
- }
1089
- return false
1078
+ if fn == nil || !isFunctionLikeKind(fn) || isPromiseCallbackFunction(fn) {
1079
+ return false
1080
+ }
1081
+ params := fn.Parameters()
1082
+ if len(params) == 0 {
1083
+ return false
1084
+ }
1085
+ switch parameterIdentifierName(params[0]) {
1086
+ case "err", "error":
1087
+ return true
1088
+ }
1089
+ return false
1090
1090
  }
1091
1091
 
1092
1092
  func hasErrorFirstCallbackArgument(call *shimast.CallExpression) bool {
1093
- if call == nil || call.Arguments == nil || len(call.Arguments.Nodes) == 0 {
1094
- return false
1095
- }
1096
- last := stripParens(call.Arguments.Nodes[len(call.Arguments.Nodes)-1])
1097
- if last == nil || !isFunctionLikeKind(last) || isArrayIterationCallback(call) {
1098
- return false
1099
- }
1100
- params := last.Parameters()
1101
- return len(params) > 0 && (parameterIdentifierName(params[0]) == "err" || parameterIdentifierName(params[0]) == "error")
1093
+ if call == nil || call.Arguments == nil || len(call.Arguments.Nodes) == 0 {
1094
+ return false
1095
+ }
1096
+ last := stripParens(call.Arguments.Nodes[len(call.Arguments.Nodes)-1])
1097
+ if last == nil || !isFunctionLikeKind(last) || isArrayIterationCallback(call) {
1098
+ return false
1099
+ }
1100
+ params := last.Parameters()
1101
+ return len(params) > 0 && (parameterIdentifierName(params[0]) == "err" || parameterIdentifierName(params[0]) == "error")
1102
1102
  }
1103
1103
 
1104
1104
  func isArrayIterationCallback(call *shimast.CallExpression) bool {
1105
- _, method, ok := promiseCallMethod(call)
1106
- if !ok {
1107
- return false
1108
- }
1109
- switch method {
1110
- case "map", "every", "forEach", "some", "find", "filter", "on", "once":
1111
- return true
1112
- }
1113
- return false
1105
+ _, method, ok := promiseCallMethod(call)
1106
+ if !ok {
1107
+ return false
1108
+ }
1109
+ switch method {
1110
+ case "map", "every", "forEach", "some", "find", "filter", "on", "once":
1111
+ return true
1112
+ }
1113
+ return false
1114
1114
  }
1115
1115
 
1116
1116
  func isInsideAwaitOrYield(node *shimast.Node) bool {
1117
- for cur := node.Parent; cur != nil; cur = cur.Parent {
1118
- if cur.Kind == shimast.KindAwaitExpression || cur.Kind == shimast.KindYieldExpression {
1119
- return true
1120
- }
1121
- }
1122
- return false
1117
+ for cur := node.Parent; cur != nil; cur = cur.Parent {
1118
+ if cur.Kind == shimast.KindAwaitExpression || cur.Kind == shimast.KindYieldExpression {
1119
+ return true
1120
+ }
1121
+ }
1122
+ return false
1123
1123
  }
1124
1124
 
1125
1125
  func isDirectReturnValue(node *shimast.Node) bool {
1126
- parent := node.Parent
1127
- if parent == nil {
1128
- return false
1129
- }
1130
- if parent.Kind == shimast.KindReturnStatement {
1131
- return true
1132
- }
1133
- if parent.Kind == shimast.KindArrowFunction {
1134
- arrow := parent.AsArrowFunction()
1135
- return arrow != nil && arrow.Body == node
1136
- }
1137
- return false
1126
+ parent := node.Parent
1127
+ if parent == nil {
1128
+ return false
1129
+ }
1130
+ if parent.Kind == shimast.KindReturnStatement {
1131
+ return true
1132
+ }
1133
+ if parent.Kind == shimast.KindArrowFunction {
1134
+ arrow := parent.AsArrowFunction()
1135
+ return arrow != nil && arrow.Body == node
1136
+ }
1137
+ return false
1138
1138
  }
1139
1139
 
1140
1140
  func fileDeclaresPromise(file *shimast.Node) bool {
1141
- declared := false
1142
- walkDescendants(file, func(node *shimast.Node) {
1143
- if declared || node == nil {
1144
- return
1145
- }
1146
- switch node.Kind {
1147
- case shimast.KindImportClause, shimast.KindImportSpecifier, shimast.KindNamespaceImport:
1148
- if node.Name() != nil && identifierText(node.Name()) == "Promise" {
1149
- declared = true
1150
- }
1151
- case shimast.KindVariableDeclaration, shimast.KindFunctionDeclaration, shimast.KindClassDeclaration, shimast.KindInterfaceDeclaration, shimast.KindTypeAliasDeclaration:
1152
- if node.Name() != nil && identifierText(node.Name()) == "Promise" {
1153
- declared = true
1154
- }
1155
- }
1156
- })
1157
- return declared
1141
+ declared := false
1142
+ walkDescendants(file, func(node *shimast.Node) {
1143
+ if declared || node == nil {
1144
+ return
1145
+ }
1146
+ switch node.Kind {
1147
+ case shimast.KindImportClause, shimast.KindImportSpecifier, shimast.KindNamespaceImport:
1148
+ if node.Name() != nil && identifierText(node.Name()) == "Promise" {
1149
+ declared = true
1150
+ }
1151
+ case shimast.KindVariableDeclaration, shimast.KindFunctionDeclaration, shimast.KindClassDeclaration, shimast.KindInterfaceDeclaration, shimast.KindTypeAliasDeclaration:
1152
+ if node.Name() != nil && identifierText(node.Name()) == "Promise" {
1153
+ declared = true
1154
+ }
1155
+ }
1156
+ })
1157
+ return declared
1158
1158
  }
1159
1159
 
1160
1160
  func init() {
1161
- Register(awaitThenable{})
1162
- Register(noFloatingPromises{})
1163
- Register(returnAwait{})
1164
- Register(promiseAlwaysReturn{})
1165
- Register(promiseAvoidNew{})
1166
- Register(promiseCatchOrReturn{})
1167
- Register(promiseNoCallbackInPromise{})
1168
- Register(promiseNoMultipleResolved{})
1169
- Register(promiseNoNative{})
1170
- Register(promiseNoNesting{})
1171
- Register(promiseNoNewStatics{})
1172
- Register(promiseNoPromiseInCallback{})
1173
- Register(promiseNoReturnInFinally{})
1174
- Register(promiseNoReturnWrap{})
1175
- Register(promiseParamNames{})
1176
- Register(promisePreferAwaitToCallbacks{})
1177
- Register(promisePreferAwaitToThen{})
1178
- Register(promisePreferCatch{})
1179
- Register(promiseSpecOnly{})
1180
- Register(promiseValidParams{})
1161
+ Register(awaitThenable{})
1162
+ Register(noFloatingPromises{})
1163
+ Register(returnAwait{})
1164
+ Register(promiseAlwaysReturn{})
1165
+ Register(promiseAvoidNew{})
1166
+ Register(promiseCatchOrReturn{})
1167
+ Register(promiseNoCallbackInPromise{})
1168
+ Register(promiseNoMultipleResolved{})
1169
+ Register(promiseNoNative{})
1170
+ Register(promiseNoNesting{})
1171
+ Register(promiseNoNewStatics{})
1172
+ Register(promiseNoPromiseInCallback{})
1173
+ Register(promiseNoReturnInFinally{})
1174
+ Register(promiseNoReturnWrap{})
1175
+ Register(promiseParamNames{})
1176
+ Register(promisePreferAwaitToCallbacks{})
1177
+ Register(promisePreferAwaitToThen{})
1178
+ Register(promisePreferCatch{})
1179
+ Register(promiseSpecOnly{})
1180
+ Register(promiseValidParams{})
1181
1181
  }