@soundscript/soundscript 0.1.12 → 0.1.15
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.
- package/package.json +15 -6
- package/project-transform/index.js +2 -0
- package/project-transform/index.ts +8 -0
- package/project-transform/src/annotation_syntax.js +948 -0
- package/project-transform/src/annotation_syntax.ts +1217 -0
- package/project-transform/src/build_package.js +475 -0
- package/project-transform/src/build_package.ts +683 -0
- package/project-transform/src/bundled/portable-web-globals.d.ts +153 -0
- package/project-transform/src/bundled/runtime_externs.js +220 -0
- package/project-transform/src/bundled/runtime_externs.ts +237 -0
- package/project-transform/src/bundled/sound-libs/lib.decorators.d.ts +385 -0
- package/project-transform/src/bundled/sound-libs/lib.decorators.legacy.d.ts +22 -0
- package/project-transform/src/bundled/sound-libs/lib.dom.asynciterable.d.ts +42 -0
- package/project-transform/src/bundled/sound-libs/lib.dom.d.ts +39440 -0
- package/project-transform/src/bundled/sound-libs/lib.es2015.collection.d.ts +149 -0
- package/project-transform/src/bundled/sound-libs/lib.es2015.core.d.ts +657 -0
- package/project-transform/src/bundled/sound-libs/lib.es2015.d.ts +28 -0
- package/project-transform/src/bundled/sound-libs/lib.es2015.generator.d.ts +77 -0
- package/project-transform/src/bundled/sound-libs/lib.es2015.iterable.d.ts +616 -0
- package/project-transform/src/bundled/sound-libs/lib.es2015.promise.d.ts +80 -0
- package/project-transform/src/bundled/sound-libs/lib.es2015.proxy.d.ts +128 -0
- package/project-transform/src/bundled/sound-libs/lib.es2015.reflect.d.ts +144 -0
- package/project-transform/src/bundled/sound-libs/lib.es2015.symbol.d.ts +46 -0
- package/project-transform/src/bundled/sound-libs/lib.es2015.symbol.wellknown.d.ts +170 -0
- package/project-transform/src/bundled/sound-libs/lib.es2016.array.include.d.ts +116 -0
- package/project-transform/src/bundled/sound-libs/lib.es2016.d.ts +21 -0
- package/project-transform/src/bundled/sound-libs/lib.es2017.arraybuffer.d.ts +21 -0
- package/project-transform/src/bundled/sound-libs/lib.es2017.d.ts +26 -0
- package/project-transform/src/bundled/sound-libs/lib.es2017.date.d.ts +31 -0
- package/project-transform/src/bundled/sound-libs/lib.es2017.object.d.ts +49 -0
- package/project-transform/src/bundled/sound-libs/lib.es2017.string.d.ts +45 -0
- package/project-transform/src/bundled/sound-libs/lib.es2017.typedarrays.d.ts +53 -0
- package/project-transform/src/bundled/sound-libs/lib.es2018.asyncgenerator.d.ts +77 -0
- package/project-transform/src/bundled/sound-libs/lib.es2018.asynciterable.d.ts +57 -0
- package/project-transform/src/bundled/sound-libs/lib.es2018.d.ts +24 -0
- package/project-transform/src/bundled/sound-libs/lib.es2018.promise.d.ts +30 -0
- package/project-transform/src/bundled/sound-libs/lib.es2018.regexp.d.ts +37 -0
- package/project-transform/src/bundled/sound-libs/lib.es2019.array.d.ts +79 -0
- package/project-transform/src/bundled/sound-libs/lib.es2019.d.ts +24 -0
- package/project-transform/src/bundled/sound-libs/lib.es2019.object.d.ts +47 -0
- package/project-transform/src/bundled/sound-libs/lib.es2019.string.d.ts +37 -0
- package/project-transform/src/bundled/sound-libs/lib.es2019.symbol.d.ts +24 -0
- package/project-transform/src/bundled/sound-libs/lib.es2020.bigint.d.ts +765 -0
- package/project-transform/src/bundled/sound-libs/lib.es2020.d.ts +27 -0
- package/project-transform/src/bundled/sound-libs/lib.es2020.date.d.ts +42 -0
- package/project-transform/src/bundled/sound-libs/lib.es2020.number.d.ts +28 -0
- package/project-transform/src/bundled/sound-libs/lib.es2020.promise.d.ts +49 -0
- package/project-transform/src/bundled/sound-libs/lib.es2020.string.d.ts +44 -0
- package/project-transform/src/bundled/sound-libs/lib.es2020.symbol.wellknown.d.ts +41 -0
- package/project-transform/src/bundled/sound-libs/lib.es2021.d.ts +23 -0
- package/project-transform/src/bundled/sound-libs/lib.es2021.promise.d.ts +48 -0
- package/project-transform/src/bundled/sound-libs/lib.es2021.string.d.ts +33 -0
- package/project-transform/src/bundled/sound-libs/lib.es2021.weakref.d.ts +78 -0
- package/project-transform/src/bundled/sound-libs/lib.es2022.array.d.ts +121 -0
- package/project-transform/src/bundled/sound-libs/lib.es2022.d.ts +25 -0
- package/project-transform/src/bundled/sound-libs/lib.es2022.error.d.ts +75 -0
- package/project-transform/src/bundled/sound-libs/lib.es2022.object.d.ts +26 -0
- package/project-transform/src/bundled/sound-libs/lib.es2022.regexp.d.ts +39 -0
- package/project-transform/src/bundled/sound-libs/lib.es2022.string.d.ts +25 -0
- package/project-transform/src/bundled/sound-libs/lib.es2023.array.d.ts +924 -0
- package/project-transform/src/bundled/sound-libs/lib.es2023.collection.d.ts +21 -0
- package/project-transform/src/bundled/sound-libs/lib.es2023.d.ts +22 -0
- package/project-transform/src/bundled/sound-libs/lib.es2024.arraybuffer.d.ts +65 -0
- package/project-transform/src/bundled/sound-libs/lib.es2024.collection.d.ts +29 -0
- package/project-transform/src/bundled/sound-libs/lib.es2024.d.ts +26 -0
- package/project-transform/src/bundled/sound-libs/lib.es2024.object.d.ts +33 -0
- package/project-transform/src/bundled/sound-libs/lib.es2024.promise.d.ts +35 -0
- package/project-transform/src/bundled/sound-libs/lib.es2024.regexp.d.ts +25 -0
- package/project-transform/src/bundled/sound-libs/lib.es2024.string.d.ts +29 -0
- package/project-transform/src/bundled/sound-libs/lib.es5.d.ts +4924 -0
- package/project-transform/src/bundled/sound_stdlib.js +142 -0
- package/project-transform/src/bundled/sound_stdlib.ts +180 -0
- package/project-transform/src/checker/analyze_project.js +1361 -0
- package/project-transform/src/checker/analyze_project.ts +2246 -0
- package/project-transform/src/checker/diagnostics.js +112 -0
- package/project-transform/src/checker/diagnostics.ts +222 -0
- package/project-transform/src/checker/engine/context.js +235 -0
- package/project-transform/src/checker/engine/context.ts +340 -0
- package/project-transform/src/checker/engine/diagnostic_codes.js +72 -0
- package/project-transform/src/checker/engine/diagnostic_codes.ts +95 -0
- package/project-transform/src/checker/engine/facts.js +35 -0
- package/project-transform/src/checker/engine/facts.ts +48 -0
- package/project-transform/src/checker/engine/types.js +1 -0
- package/project-transform/src/checker/engine/types.ts +485 -0
- package/project-transform/src/checker/proof_escape_hatch_diagnostics.js +104 -0
- package/project-transform/src/checker/proof_escape_hatch_diagnostics.ts +173 -0
- package/project-transform/src/checker/rules/async_surface.js +231 -0
- package/project-transform/src/checker/rules/async_surface.ts +335 -0
- package/project-transform/src/checker/rules/class_lifecycle.js +798 -0
- package/project-transform/src/checker/rules/class_lifecycle.ts +1276 -0
- package/project-transform/src/checker/rules/directive_validation.js +571 -0
- package/project-transform/src/checker/rules/directive_validation.ts +938 -0
- package/project-transform/src/checker/rules/directives.js +23 -0
- package/project-transform/src/checker/rules/directives.ts +25 -0
- package/project-transform/src/checker/rules/flow.js +202 -0
- package/project-transform/src/checker/rules/flow.ts +333 -0
- package/project-transform/src/checker/rules/flow_facts.js +601 -0
- package/project-transform/src/checker/rules/flow_facts.ts +978 -0
- package/project-transform/src/checker/rules/flow_invalidation.js +1119 -0
- package/project-transform/src/checker/rules/flow_invalidation.ts +2150 -0
- package/project-transform/src/checker/rules/flow_shared.js +2822 -0
- package/project-transform/src/checker/rules/flow_shared.ts +4383 -0
- package/project-transform/src/checker/rules/foreign_boundary.js +120 -0
- package/project-transform/src/checker/rules/foreign_boundary.ts +196 -0
- package/project-transform/src/checker/rules/foreign_projection.js +279 -0
- package/project-transform/src/checker/rules/foreign_projection.ts +425 -0
- package/project-transform/src/checker/rules/generated_helpers.js +13 -0
- package/project-transform/src/checker/rules/generated_helpers.ts +18 -0
- package/project-transform/src/checker/rules/index.js +35 -0
- package/project-transform/src/checker/rules/index.ts +49 -0
- package/project-transform/src/checker/rules/namespace_object.js +845 -0
- package/project-transform/src/checker/rules/namespace_object.ts +1224 -0
- package/project-transform/src/checker/rules/non_ordinary_recovery.js +1328 -0
- package/project-transform/src/checker/rules/non_ordinary_recovery.ts +2391 -0
- package/project-transform/src/checker/rules/null_prototype.js +3 -0
- package/project-transform/src/checker/rules/null_prototype.ts +6 -0
- package/project-transform/src/checker/rules/overloads.js +181 -0
- package/project-transform/src/checker/rules/overloads.ts +317 -0
- package/project-transform/src/checker/rules/predicate_verification.js +691 -0
- package/project-transform/src/checker/rules/predicate_verification.ts +1088 -0
- package/project-transform/src/checker/rules/prototype_hardening.js +237 -0
- package/project-transform/src/checker/rules/prototype_hardening.ts +343 -0
- package/project-transform/src/checker/rules/receiver_discipline.js +263 -0
- package/project-transform/src/checker/rules/receiver_discipline.ts +356 -0
- package/project-transform/src/checker/rules/relations.js +6861 -0
- package/project-transform/src/checker/rules/relations.ts +12158 -0
- package/project-transform/src/checker/rules/resolved_builtins.js +274 -0
- package/project-transform/src/checker/rules/resolved_builtins.ts +438 -0
- package/project-transform/src/checker/rules/trust.js +217 -0
- package/project-transform/src/checker/rules/trust.ts +301 -0
- package/project-transform/src/checker/rules/type_guards.js +173 -0
- package/project-transform/src/checker/rules/type_guards.ts +257 -0
- package/project-transform/src/checker/rules/universal.js +17 -0
- package/project-transform/src/checker/rules/universal.ts +22 -0
- package/project-transform/src/checker/rules/unsafe_value_origin.js +80 -0
- package/project-transform/src/checker/rules/unsafe_value_origin.ts +125 -0
- package/project-transform/src/checker/rules/unsound_imports.js +218 -0
- package/project-transform/src/checker/rules/unsound_imports.ts +301 -0
- package/project-transform/src/checker/rules/unsound_syntax.js +1695 -0
- package/project-transform/src/checker/rules/unsound_syntax.ts +2540 -0
- package/project-transform/src/checker/rules/value_types.js +206 -0
- package/project-transform/src/checker/rules/value_types.ts +407 -0
- package/project-transform/src/checker/timing.js +43 -0
- package/project-transform/src/checker/timing.ts +78 -0
- package/project-transform/src/checker/unsupported_feature_messages.js +337 -0
- package/project-transform/src/checker/unsupported_feature_messages.ts +531 -0
- package/project-transform/src/cli.js +892 -0
- package/project-transform/src/cli.ts +1476 -0
- package/project-transform/src/compiler/compile_project.js +319 -0
- package/project-transform/src/compiler/compile_project.ts +508 -0
- package/project-transform/src/compiler/errors.js +10 -0
- package/project-transform/src/compiler/errors.ts +29 -0
- package/project-transform/src/compiler/ir.js +1 -0
- package/project-transform/src/compiler/ir.ts +1526 -0
- package/project-transform/src/compiler/lower.js +30550 -0
- package/project-transform/src/compiler/lower.ts +43645 -0
- package/project-transform/src/compiler/lower_arrays.js +140 -0
- package/project-transform/src/compiler/lower_arrays.ts +190 -0
- package/project-transform/src/compiler/lower_strings.js +121 -0
- package/project-transform/src/compiler/lower_strings.ts +198 -0
- package/project-transform/src/compiler/lower_tagged.js +329 -0
- package/project-transform/src/compiler/lower_tagged.ts +427 -0
- package/project-transform/src/compiler/lower_views.js +171 -0
- package/project-transform/src/compiler/lower_views.ts +251 -0
- package/project-transform/src/compiler/object_keys.js +25 -0
- package/project-transform/src/compiler/object_keys.ts +35 -0
- package/project-transform/src/compiler/runtime_ir.js +30 -0
- package/project-transform/src/compiler/runtime_ir.ts +727 -0
- package/project-transform/src/compiler/tagged_boundary.js +18 -0
- package/project-transform/src/compiler/tagged_boundary.ts +37 -0
- package/project-transform/src/compiler/toolchain.js +170 -0
- package/project-transform/src/compiler/toolchain.ts +229 -0
- package/project-transform/src/compiler/unicode_case_data.js +2102 -0
- package/project-transform/src/compiler/unicode_case_data.ts +2112 -0
- package/project-transform/src/compiler/wasm_js_host_runtime.js +656 -0
- package/project-transform/src/compiler/wasm_js_host_runtime.ts +762 -0
- package/project-transform/src/compiler/wat_arrays.js +3132 -0
- package/project-transform/src/compiler/wat_arrays.ts +3768 -0
- package/project-transform/src/compiler/wat_emitter.js +17952 -0
- package/project-transform/src/compiler/wat_emitter.ts +22812 -0
- package/project-transform/src/compiler/wat_strings.js +129 -0
- package/project-transform/src/compiler/wat_strings.ts +187 -0
- package/project-transform/src/compiler/wat_tagged.js +548 -0
- package/project-transform/src/compiler/wat_tagged.ts +674 -0
- package/project-transform/src/compiler_generator_runner.js +153 -0
- package/project-transform/src/compiler_generator_runner.ts +171 -0
- package/project-transform/src/compiler_object_test_helpers.js +69 -0
- package/project-transform/src/compiler_object_test_helpers.ts +96 -0
- package/project-transform/src/compiler_promise_runner.js +2116 -0
- package/project-transform/src/compiler_promise_runner.ts +2184 -0
- package/project-transform/src/compiler_test_helpers.js +854 -0
- package/project-transform/src/compiler_test_helpers.ts +1087 -0
- package/project-transform/src/config.js +568 -0
- package/project-transform/src/config.ts +892 -0
- package/project-transform/src/diagnostic_metadata.js +67 -0
- package/project-transform/src/diagnostic_metadata.ts +99 -0
- package/project-transform/src/diagnostic_reference.js +1368 -0
- package/project-transform/src/diagnostic_reference.ts +1523 -0
- package/project-transform/src/editor_diagnostics_worker.js +176 -0
- package/project-transform/src/editor_diagnostics_worker.ts +250 -0
- package/project-transform/src/editor_projection.js +224 -0
- package/project-transform/src/editor_projection.ts +421 -0
- package/project-transform/src/frontend/builtin_expanded_program_test_cleanup.js +47 -0
- package/project-transform/src/frontend/builtin_expanded_program_test_cleanup.ts +72 -0
- package/project-transform/src/frontend/builtin_macro_support.js +842 -0
- package/project-transform/src/frontend/builtin_macro_support.ts +1386 -0
- package/project-transform/src/frontend/builtin_macros.js +409 -0
- package/project-transform/src/frontend/builtin_macros.ts +542 -0
- package/project-transform/src/frontend/component_poc_runtime.js +279 -0
- package/project-transform/src/frontend/component_poc_runtime.ts +372 -0
- package/project-transform/src/frontend/css_macro.js +148 -0
- package/project-transform/src/frontend/css_macro.ts +222 -0
- package/project-transform/src/frontend/derive_macros.js +2072 -0
- package/project-transform/src/frontend/derive_macros.ts +3188 -0
- package/project-transform/src/frontend/embedded_fragment_support.js +106 -0
- package/project-transform/src/frontend/embedded_fragment_support.ts +172 -0
- package/project-transform/src/frontend/error_normalization.js +403 -0
- package/project-transform/src/frontend/error_normalization.ts +832 -0
- package/project-transform/src/frontend/error_stdlib_support.js +1 -0
- package/project-transform/src/frontend/error_stdlib_support.ts +6 -0
- package/project-transform/src/frontend/expand_project.js +169 -0
- package/project-transform/src/frontend/expand_project.ts +248 -0
- package/project-transform/src/frontend/format_soundscript.js +297 -0
- package/project-transform/src/frontend/format_soundscript.ts +582 -0
- package/project-transform/src/frontend/graphql_macro.js +174 -0
- package/project-transform/src/frontend/graphql_macro.ts +253 -0
- package/project-transform/src/frontend/hash_context.js +83 -0
- package/project-transform/src/frontend/hash_context.ts +113 -0
- package/project-transform/src/frontend/hkt_macro.js +448 -0
- package/project-transform/src/frontend/hkt_macro.ts +897 -0
- package/project-transform/src/frontend/import_binding_usage.js +190 -0
- package/project-transform/src/frontend/import_binding_usage.ts +277 -0
- package/project-transform/src/frontend/macro_advanced_backend_adapter.js +58 -0
- package/project-transform/src/frontend/macro_advanced_backend_adapter.ts +123 -0
- package/project-transform/src/frontend/macro_advanced_context.js +826 -0
- package/project-transform/src/frontend/macro_advanced_context.ts +1102 -0
- package/project-transform/src/frontend/macro_advanced_output.js +21 -0
- package/project-transform/src/frontend/macro_advanced_output.ts +41 -0
- package/project-transform/src/frontend/macro_api.js +353 -0
- package/project-transform/src/frontend/macro_api.ts +1722 -0
- package/project-transform/src/frontend/macro_api_internal.js +35 -0
- package/project-transform/src/frontend/macro_api_internal.ts +80 -0
- package/project-transform/src/frontend/macro_api_module_support.js +39 -0
- package/project-transform/src/frontend/macro_api_module_support.ts +65 -0
- package/project-transform/src/frontend/macro_backend_adapter.js +272 -0
- package/project-transform/src/frontend/macro_backend_adapter.ts +420 -0
- package/project-transform/src/frontend/macro_context.js +816 -0
- package/project-transform/src/frontend/macro_context.ts +1105 -0
- package/project-transform/src/frontend/macro_debug.js +99 -0
- package/project-transform/src/frontend/macro_debug.ts +157 -0
- package/project-transform/src/frontend/macro_definition_support.js +28 -0
- package/project-transform/src/frontend/macro_definition_support.ts +73 -0
- package/project-transform/src/frontend/macro_errors.js +40 -0
- package/project-transform/src/frontend/macro_errors.ts +70 -0
- package/project-transform/src/frontend/macro_expander.js +919 -0
- package/project-transform/src/frontend/macro_expander.ts +1611 -0
- package/project-transform/src/frontend/macro_factory_support.js +176 -0
- package/project-transform/src/frontend/macro_factory_support.ts +263 -0
- package/project-transform/src/frontend/macro_host_ast_internal.js +64 -0
- package/project-transform/src/frontend/macro_host_ast_internal.ts +109 -0
- package/project-transform/src/frontend/macro_index.js +27 -0
- package/project-transform/src/frontend/macro_index.ts +50 -0
- package/project-transform/src/frontend/macro_loader.js +281 -0
- package/project-transform/src/frontend/macro_loader.ts +506 -0
- package/project-transform/src/frontend/macro_operand_semantics.js +838 -0
- package/project-transform/src/frontend/macro_operand_semantics.ts +1489 -0
- package/project-transform/src/frontend/macro_output.js +54 -0
- package/project-transform/src/frontend/macro_output.ts +123 -0
- package/project-transform/src/frontend/macro_parser.js +611 -0
- package/project-transform/src/frontend/macro_parser.ts +832 -0
- package/project-transform/src/frontend/macro_resolver.js +69 -0
- package/project-transform/src/frontend/macro_resolver.ts +125 -0
- package/project-transform/src/frontend/macro_rewrite.js +285 -0
- package/project-transform/src/frontend/macro_rewrite.ts +442 -0
- package/project-transform/src/frontend/macro_runtime_support.js +232 -0
- package/project-transform/src/frontend/macro_runtime_support.ts +324 -0
- package/project-transform/src/frontend/macro_scanner.js +393 -0
- package/project-transform/src/frontend/macro_scanner.ts +455 -0
- package/project-transform/src/frontend/macro_semantic_backend_adapter.js +87 -0
- package/project-transform/src/frontend/macro_semantic_backend_adapter.ts +166 -0
- package/project-transform/src/frontend/macro_semantic_context.js +5 -0
- package/project-transform/src/frontend/macro_semantic_context.ts +12 -0
- package/project-transform/src/frontend/macro_semantic_output.js +24 -0
- package/project-transform/src/frontend/macro_semantic_output.ts +47 -0
- package/project-transform/src/frontend/macro_semantic_types.js +1 -0
- package/project-transform/src/frontend/macro_semantic_types.ts +98 -0
- package/project-transform/src/frontend/macro_semantics.js +1172 -0
- package/project-transform/src/frontend/macro_semantics.ts +1502 -0
- package/project-transform/src/frontend/macro_site_kind_support.js +164 -0
- package/project-transform/src/frontend/macro_site_kind_support.ts +255 -0
- package/project-transform/src/frontend/macro_syntax_internal.js +1950 -0
- package/project-transform/src/frontend/macro_syntax_internal.ts +3338 -0
- package/project-transform/src/frontend/macro_templates.js +57 -0
- package/project-transform/src/frontend/macro_templates.ts +143 -0
- package/project-transform/src/frontend/macro_test_helpers.js +82 -0
- package/project-transform/src/frontend/macro_test_helpers.ts +136 -0
- package/project-transform/src/frontend/macro_types.js +1 -0
- package/project-transform/src/frontend/macro_types.ts +103 -0
- package/project-transform/src/frontend/macro_vm.js +39 -0
- package/project-transform/src/frontend/macro_vm.ts +113 -0
- package/project-transform/src/frontend/match_macro.js +885 -0
- package/project-transform/src/frontend/match_macro.ts +1220 -0
- package/project-transform/src/frontend/numeric_normalization.js +824 -0
- package/project-transform/src/frontend/numeric_normalization.ts +1380 -0
- package/project-transform/src/frontend/numeric_prelude.js +278 -0
- package/project-transform/src/frontend/numeric_prelude.ts +370 -0
- package/project-transform/src/frontend/project_frontend.js +2396 -0
- package/project-transform/src/frontend/project_frontend.ts +3776 -0
- package/project-transform/src/frontend/project_macro_support.js +1401 -0
- package/project-transform/src/frontend/project_macro_support.ts +2137 -0
- package/project-transform/src/frontend/sql_macro.js +175 -0
- package/project-transform/src/frontend/sql_macro.ts +254 -0
- package/project-transform/src/frontend/sql_stdlib_support.js +1 -0
- package/project-transform/src/frontend/sql_stdlib_support.ts +6 -0
- package/project-transform/src/frontend/std_package_support.js +228 -0
- package/project-transform/src/frontend/std_package_support.ts +400 -0
- package/project-transform/src/frontend/value_normalization.js +306 -0
- package/project-transform/src/frontend/value_normalization.ts +599 -0
- package/project-transform/src/lsp/project_service.js +4771 -0
- package/project-transform/src/lsp/project_service.ts +7580 -0
- package/project-transform/src/lsp/protocol.js +9 -0
- package/project-transform/src/lsp/protocol.ts +38 -0
- package/project-transform/src/lsp/server.js +355 -0
- package/project-transform/src/lsp/server.ts +671 -0
- package/project-transform/src/lsp/session.js +49 -0
- package/project-transform/src/lsp/session.ts +48 -0
- package/project-transform/src/lsp/timing.js +43 -0
- package/project-transform/src/lsp/timing.ts +76 -0
- package/project-transform/src/lsp/transport.js +205 -0
- package/project-transform/src/lsp/transport.ts +253 -0
- package/project-transform/src/lsp_main.js +5 -0
- package/project-transform/src/lsp_main.ts +7 -0
- package/project-transform/src/macros.d.ts +1 -0
- package/project-transform/src/macros.js +1 -0
- package/project-transform/src/macros.ts +1 -0
- package/project-transform/src/main.js +24 -0
- package/project-transform/src/main.ts +28 -0
- package/project-transform/src/platform/host.js +264 -0
- package/project-transform/src/platform/host.ts +343 -0
- package/project-transform/src/platform/path.js +8 -0
- package/project-transform/src/platform/path.ts +20 -0
- package/project-transform/src/public_macro_api/macro_api.d.ts +1054 -0
- package/project-transform/src/public_macro_api/macro_semantic_types.d.ts +66 -0
- package/project-transform/src/public_macro_api/macro_types.d.ts +70 -0
- package/project-transform/src/run_program.js +14 -0
- package/project-transform/src/run_program.ts +33 -0
- package/project-transform/src/runtime/materialize.js +371 -0
- package/project-transform/src/runtime/materialize.ts +502 -0
- package/project-transform/src/runtime/on_demand.js +203 -0
- package/project-transform/src/runtime/on_demand.ts +305 -0
- package/project-transform/src/runtime/source_maps.js +205 -0
- package/project-transform/src/runtime/source_maps.ts +297 -0
- package/project-transform/src/runtime/transform.js +148 -0
- package/project-transform/src/runtime/transform.ts +295 -0
- package/project-transform/src/service/types.js +1 -0
- package/project-transform/src/service/types.ts +22 -0
- package/project-transform/src/soundscript_packages.js +477 -0
- package/project-transform/src/soundscript_packages.ts +754 -0
- package/project-transform/src/soundscript_runtime_specifiers.js +88 -0
- package/project-transform/src/soundscript_runtime_specifiers.ts +96 -0
- package/project-transform/src/stdlib/async.d.ts +81 -0
- package/project-transform/src/stdlib/async.js +213 -0
- package/project-transform/src/stdlib/async.ts +315 -0
- package/project-transform/src/stdlib/codec.d.ts +32 -0
- package/project-transform/src/stdlib/codec.js +30 -0
- package/project-transform/src/stdlib/codec.ts +76 -0
- package/project-transform/src/stdlib/compare.d.ts +28 -0
- package/project-transform/src/stdlib/compare.js +115 -0
- package/project-transform/src/stdlib/compare.ts +151 -0
- package/project-transform/src/stdlib/css.d.ts +16 -0
- package/project-transform/src/stdlib/css.js +9 -0
- package/project-transform/src/stdlib/css.ts +28 -0
- package/project-transform/src/stdlib/debug.d.ts +2 -0
- package/project-transform/src/stdlib/debug.js +9 -0
- package/project-transform/src/stdlib/debug.ts +10 -0
- package/project-transform/src/stdlib/decode.d.ts +86 -0
- package/project-transform/src/stdlib/decode.js +254 -0
- package/project-transform/src/stdlib/decode.ts +390 -0
- package/project-transform/src/stdlib/derive.d.ts +6 -0
- package/project-transform/src/stdlib/derive.js +7 -0
- package/project-transform/src/stdlib/derive.ts +7 -0
- package/project-transform/src/stdlib/encode.d.ts +100 -0
- package/project-transform/src/stdlib/encode.js +130 -0
- package/project-transform/src/stdlib/encode.ts +259 -0
- package/project-transform/src/stdlib/failures.d.ts +23 -0
- package/project-transform/src/stdlib/failures.js +41 -0
- package/project-transform/src/stdlib/failures.ts +64 -0
- package/project-transform/src/stdlib/fetch.d.ts +67 -0
- package/project-transform/src/stdlib/fetch.js +5 -0
- package/project-transform/src/stdlib/fetch.ts +11 -0
- package/project-transform/src/stdlib/graphql.d.ts +16 -0
- package/project-transform/src/stdlib/graphql.js +9 -0
- package/project-transform/src/stdlib/graphql.ts +28 -0
- package/project-transform/src/stdlib/hash.d.ts +34 -0
- package/project-transform/src/stdlib/hash.js +110 -0
- package/project-transform/src/stdlib/hash.ts +188 -0
- package/project-transform/src/stdlib/hkt.d.ts +40 -0
- package/project-transform/src/stdlib/hkt.js +3 -0
- package/project-transform/src/stdlib/hkt.ts +41 -0
- package/project-transform/src/stdlib/index.d.ts +9 -0
- package/project-transform/src/stdlib/index.js +15 -0
- package/project-transform/src/stdlib/index.ts +23 -0
- package/project-transform/src/stdlib/json.d.ts +125 -0
- package/project-transform/src/stdlib/json.js +764 -0
- package/project-transform/src/stdlib/json.ts +1034 -0
- package/project-transform/src/stdlib/match.d.ts +11 -0
- package/project-transform/src/stdlib/match.js +13 -0
- package/project-transform/src/stdlib/match.ts +26 -0
- package/project-transform/src/stdlib/numerics.d.ts +523 -0
- package/project-transform/src/stdlib/numerics.js +1356 -0
- package/project-transform/src/stdlib/numerics.ts +1937 -0
- package/project-transform/src/stdlib/random.d.ts +19 -0
- package/project-transform/src/stdlib/random.js +3 -0
- package/project-transform/src/stdlib/random.ts +5 -0
- package/project-transform/src/stdlib/result.d.ts +68 -0
- package/project-transform/src/stdlib/result.js +139 -0
- package/project-transform/src/stdlib/result.ts +248 -0
- package/project-transform/src/stdlib/sql.d.ts +22 -0
- package/project-transform/src/stdlib/sql.js +23 -0
- package/project-transform/src/stdlib/sql.ts +53 -0
- package/project-transform/src/stdlib/text.d.ts +24 -0
- package/project-transform/src/stdlib/text.js +3 -0
- package/project-transform/src/stdlib/text.ts +4 -0
- package/project-transform/src/stdlib/thunk.d.ts +2 -0
- package/project-transform/src/stdlib/thunk.js +9 -0
- package/project-transform/src/stdlib/thunk.ts +15 -0
- package/project-transform/src/stdlib/typeclasses.d.ts +57 -0
- package/project-transform/src/stdlib/typeclasses.js +78 -0
- package/project-transform/src/stdlib/typeclasses.ts +173 -0
- package/project-transform/src/stdlib/url.d.ts +37 -0
- package/project-transform/src/stdlib/url.js +3 -0
- package/project-transform/src/stdlib/url.ts +4 -0
- package/project-transform/src/stdlib/value.d.ts +9 -0
- package/project-transform/src/stdlib/value.js +104 -0
- package/project-transform/src/stdlib/value.ts +133 -0
- package/project-transform/src/test_installed_stdlib.js +147 -0
- package/project-transform/src/test_installed_stdlib.ts +245 -0
- package/project-transform/src/test_macro_package_fixture.js +50 -0
- package/project-transform/src/test_macro_package_fixture.ts +68 -0
- package/project-transform/src/value_deep_safe.js +191 -0
- package/project-transform/src/value_deep_safe.ts +273 -0
|
@@ -0,0 +1,2391 @@
|
|
|
1
|
+
import ts from 'typescript';
|
|
2
|
+
|
|
3
|
+
import type {
|
|
4
|
+
AnalysisContext,
|
|
5
|
+
ExportCallableHelperWrapperEntry,
|
|
6
|
+
ExportedNonOrdinaryFamily,
|
|
7
|
+
ExportSummary,
|
|
8
|
+
ExportSummaryRecoveryPathSegment,
|
|
9
|
+
} from '../engine/types.ts';
|
|
10
|
+
import { getResolvedBuiltinSignatureInfo } from './resolved_builtins.ts';
|
|
11
|
+
|
|
12
|
+
export type LocalFunctionLikeWithBody =
|
|
13
|
+
| ts.ArrowFunction
|
|
14
|
+
| ts.FunctionDeclaration
|
|
15
|
+
| ts.FunctionExpression
|
|
16
|
+
| ts.MethodDeclaration;
|
|
17
|
+
|
|
18
|
+
export interface NonOrdinaryRecoverySpec<Family extends ExportedNonOrdinaryFamily> {
|
|
19
|
+
getDirectFamily(
|
|
20
|
+
context: AnalysisContext,
|
|
21
|
+
expression: ts.Expression,
|
|
22
|
+
): Family | undefined;
|
|
23
|
+
isSupportedFamily(
|
|
24
|
+
family: ExportedNonOrdinaryFamily,
|
|
25
|
+
): family is Family;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export function isLocalFunctionLikeWithBody(node: ts.Node): node is LocalFunctionLikeWithBody {
|
|
29
|
+
return (ts.isArrowFunction(node) ||
|
|
30
|
+
ts.isFunctionDeclaration(node) ||
|
|
31
|
+
ts.isFunctionExpression(node) ||
|
|
32
|
+
ts.isMethodDeclaration(node)) &&
|
|
33
|
+
node.body !== undefined;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
function isConstVariableDeclaration(node: ts.VariableDeclaration): boolean {
|
|
37
|
+
return ts.isVariableDeclarationList(node.parent) &&
|
|
38
|
+
(node.parent.flags & ts.NodeFlags.Const) !== 0;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
function hasDefaultModifier(node: ts.Node): boolean {
|
|
42
|
+
return ts.canHaveModifiers(node) &&
|
|
43
|
+
(ts.getModifiers(node)?.some((modifier) => modifier.kind === ts.SyntaxKind.DefaultKeyword) ??
|
|
44
|
+
false);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
function getDefaultExportSymbol(
|
|
48
|
+
context: AnalysisContext,
|
|
49
|
+
sourceFile: ts.SourceFile,
|
|
50
|
+
): ts.Symbol | undefined {
|
|
51
|
+
const moduleSymbol = context.checker.getSymbolAtLocation(sourceFile);
|
|
52
|
+
if (!moduleSymbol) {
|
|
53
|
+
return undefined;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
return context.checker.getExportsOfModule(moduleSymbol).find((symbol) =>
|
|
57
|
+
symbol.name === ts.InternalSymbolName.Default
|
|
58
|
+
);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
function getFunctionLikeSummarySymbol(
|
|
62
|
+
context: AnalysisContext,
|
|
63
|
+
node: LocalFunctionLikeWithBody,
|
|
64
|
+
): ts.Symbol | undefined {
|
|
65
|
+
if (ts.isFunctionDeclaration(node)) {
|
|
66
|
+
if (node.name) {
|
|
67
|
+
return context.checker.getSymbolAtLocation(node.name);
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
return hasDefaultModifier(node)
|
|
71
|
+
? getDefaultExportSymbol(context, node.getSourceFile())
|
|
72
|
+
: undefined;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
if (ts.isMethodDeclaration(node)) {
|
|
76
|
+
return context.checker.getSymbolAtLocation(node.name);
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
if (
|
|
80
|
+
(ts.isArrowFunction(node) || ts.isFunctionExpression(node)) &&
|
|
81
|
+
ts.isVariableDeclaration(node.parent) &&
|
|
82
|
+
ts.isIdentifier(node.parent.name)
|
|
83
|
+
) {
|
|
84
|
+
return context.checker.getSymbolAtLocation(node.parent.name);
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
if (
|
|
88
|
+
(ts.isArrowFunction(node) || ts.isFunctionExpression(node)) &&
|
|
89
|
+
ts.isExportAssignment(node.parent) &&
|
|
90
|
+
!node.parent.isExportEquals
|
|
91
|
+
) {
|
|
92
|
+
return getDefaultExportSymbol(context, node.getSourceFile());
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
return ts.isFunctionExpression(node) && node.name
|
|
96
|
+
? context.checker.getSymbolAtLocation(node.name)
|
|
97
|
+
: undefined;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
function getDirectReturnExpression(node: LocalFunctionLikeWithBody): ts.Expression | undefined {
|
|
101
|
+
if (!node.body) {
|
|
102
|
+
return undefined;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
if (!ts.isBlock(node.body)) {
|
|
106
|
+
return node.body;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
if (node.body.statements.length !== 1) {
|
|
110
|
+
return undefined;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
const [statement] = node.body.statements;
|
|
114
|
+
return ts.isReturnStatement(statement) ? statement.expression : undefined;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
function getReturnedParameterIndex(
|
|
118
|
+
context: AnalysisContext,
|
|
119
|
+
node: LocalFunctionLikeWithBody,
|
|
120
|
+
expression: ts.Expression,
|
|
121
|
+
): number | undefined {
|
|
122
|
+
const current = getUnwrappedExpression(expression);
|
|
123
|
+
if (!ts.isIdentifier(current)) {
|
|
124
|
+
return undefined;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
const returnedSymbol = context.checker.getSymbolAtLocation(current);
|
|
128
|
+
if (!returnedSymbol) {
|
|
129
|
+
return undefined;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
return getParameterIndexForSymbol(context, node, returnedSymbol);
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
function getParameterIndexForSymbol(
|
|
136
|
+
context: AnalysisContext,
|
|
137
|
+
node: LocalFunctionLikeWithBody,
|
|
138
|
+
symbol: ts.Symbol,
|
|
139
|
+
): number | undefined {
|
|
140
|
+
for (const [index, parameter] of node.parameters.entries()) {
|
|
141
|
+
if (!ts.isIdentifier(parameter.name)) {
|
|
142
|
+
continue;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
const parameterSymbol = context.checker.getSymbolAtLocation(parameter.name);
|
|
146
|
+
if (parameterSymbol === symbol) {
|
|
147
|
+
return index;
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
return undefined;
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
function summarizeReturnedParameter(
|
|
155
|
+
context: AnalysisContext,
|
|
156
|
+
node: LocalFunctionLikeWithBody,
|
|
157
|
+
): number | undefined {
|
|
158
|
+
const returnExpression = getDirectReturnExpression(node);
|
|
159
|
+
return returnExpression ? getReturnedParameterIndex(context, node, returnExpression) : undefined;
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
export function getUnwrappedExpression(expression: ts.Expression): ts.Expression {
|
|
163
|
+
if (ts.isParenthesizedExpression(expression)) {
|
|
164
|
+
return getUnwrappedExpression(expression.expression);
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
if (ts.isSatisfiesExpression(expression)) {
|
|
168
|
+
return getUnwrappedExpression(expression.expression);
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
if (ts.isAwaitExpression(expression)) {
|
|
172
|
+
return getUnwrappedExpression(expression.expression);
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
return expression;
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
function getCallExpressionCalleeSymbol(
|
|
179
|
+
context: AnalysisContext,
|
|
180
|
+
node: ts.CallExpression,
|
|
181
|
+
): ts.Symbol | undefined {
|
|
182
|
+
if (ts.isIdentifier(node.expression)) {
|
|
183
|
+
return context.checker.getSymbolAtLocation(node.expression);
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
if (ts.isPropertyAccessExpression(node.expression)) {
|
|
187
|
+
return context.checker.getSymbolAtLocation(node.expression.name);
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
return undefined;
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
function getThenCallTargetExpression(
|
|
194
|
+
context: AnalysisContext,
|
|
195
|
+
node: ts.CallExpression,
|
|
196
|
+
): ts.Expression | undefined {
|
|
197
|
+
return getPromiseMethodTargetExpression(context, node, 'then');
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
function getCatchCallTargetExpression(
|
|
201
|
+
context: AnalysisContext,
|
|
202
|
+
node: ts.CallExpression,
|
|
203
|
+
): ts.Expression | undefined {
|
|
204
|
+
return getPromiseMethodTargetExpression(context, node, 'catch');
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
function getFinallyCallTargetExpression(
|
|
208
|
+
context: AnalysisContext,
|
|
209
|
+
node: ts.CallExpression,
|
|
210
|
+
): ts.Expression | undefined {
|
|
211
|
+
return getPromiseMethodTargetExpression(context, node, 'finally');
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
function getPromiseMethodTargetExpression(
|
|
215
|
+
context: AnalysisContext,
|
|
216
|
+
node: ts.CallExpression,
|
|
217
|
+
methodName: 'catch' | 'finally' | 'then',
|
|
218
|
+
): ts.Expression | undefined {
|
|
219
|
+
const info = getResolvedBuiltinSignatureInfo(context, node);
|
|
220
|
+
if (
|
|
221
|
+
!info ||
|
|
222
|
+
(info.ownerName !== 'Promise' && info.ownerName !== 'PromiseLike') ||
|
|
223
|
+
info.memberName !== methodName
|
|
224
|
+
) {
|
|
225
|
+
return undefined;
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
if (ts.isPropertyAccessExpression(node.expression) && node.expression.name.text === methodName) {
|
|
229
|
+
return node.expression.expression;
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
if (
|
|
233
|
+
ts.isElementAccessExpression(node.expression) &&
|
|
234
|
+
node.expression.argumentExpression &&
|
|
235
|
+
(
|
|
236
|
+
ts.isStringLiteral(node.expression.argumentExpression) ||
|
|
237
|
+
ts.isNoSubstitutionTemplateLiteral(node.expression.argumentExpression)
|
|
238
|
+
) &&
|
|
239
|
+
node.expression.argumentExpression.text === methodName
|
|
240
|
+
) {
|
|
241
|
+
return node.expression.expression;
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
return undefined;
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
function getPromisePassthroughTargetExpression(
|
|
248
|
+
context: AnalysisContext,
|
|
249
|
+
node: ts.CallExpression,
|
|
250
|
+
): ts.Expression | undefined {
|
|
251
|
+
return getFinallyCallTargetExpression(context, node) ??
|
|
252
|
+
getCatchCallTargetExpression(context, node);
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
function getPromiseResolveWrappedExpression(
|
|
256
|
+
context: AnalysisContext,
|
|
257
|
+
node: ts.CallExpression,
|
|
258
|
+
): ts.Expression | undefined {
|
|
259
|
+
const info = getResolvedBuiltinSignatureInfo(context, node);
|
|
260
|
+
if (!info || info.ownerName !== 'PromiseConstructor' || info.memberName !== 'resolve') {
|
|
261
|
+
return undefined;
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
return node.arguments[0];
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
function getThenCallback(node: ts.CallExpression): LocalFunctionLikeWithBody | undefined {
|
|
268
|
+
const callback = node.arguments[0];
|
|
269
|
+
return callback && isLocalFunctionLikeWithBody(callback) ? callback : undefined;
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
type ParameterBindings = Map<ts.Symbol, ts.Expression>;
|
|
273
|
+
|
|
274
|
+
function getLocalFunctionLikeFromSymbol(symbol: ts.Symbol): LocalFunctionLikeWithBody | undefined {
|
|
275
|
+
for (const declaration of symbol.getDeclarations() ?? []) {
|
|
276
|
+
if (isLocalFunctionLikeWithBody(declaration)) {
|
|
277
|
+
return declaration;
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
if (
|
|
281
|
+
ts.isVariableDeclaration(declaration) &&
|
|
282
|
+
declaration.initializer &&
|
|
283
|
+
isLocalFunctionLikeWithBody(declaration.initializer)
|
|
284
|
+
) {
|
|
285
|
+
return declaration.initializer;
|
|
286
|
+
}
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
return undefined;
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
function getDirectReturnLocalCall(
|
|
293
|
+
context: AnalysisContext,
|
|
294
|
+
callExpression: ts.CallExpression,
|
|
295
|
+
): { declaration: LocalFunctionLikeWithBody; returnExpression: ts.Expression } | undefined {
|
|
296
|
+
const calleeSymbol = getCallExpressionCalleeSymbol(context, callExpression);
|
|
297
|
+
if (!calleeSymbol) {
|
|
298
|
+
return undefined;
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
const declaration = getLocalFunctionLikeFromSymbol(calleeSymbol);
|
|
302
|
+
if (!declaration) {
|
|
303
|
+
return undefined;
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
const returnExpression = getDirectReturnExpression(declaration);
|
|
307
|
+
return returnExpression ? { declaration, returnExpression } : undefined;
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
function mergeParameterBindings(
|
|
311
|
+
baseBindings: ParameterBindings,
|
|
312
|
+
extraBindings: ParameterBindings,
|
|
313
|
+
): ParameterBindings {
|
|
314
|
+
const merged = new Map(baseBindings);
|
|
315
|
+
for (const [symbol, expression] of extraBindings) {
|
|
316
|
+
merged.set(symbol, expression);
|
|
317
|
+
}
|
|
318
|
+
return merged;
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
function resolveBoundExpression(
|
|
322
|
+
context: AnalysisContext,
|
|
323
|
+
expression: ts.Expression,
|
|
324
|
+
bindings: ParameterBindings,
|
|
325
|
+
): ts.Expression {
|
|
326
|
+
const current = getUnwrappedExpression(expression);
|
|
327
|
+
if (!ts.isIdentifier(current)) {
|
|
328
|
+
return expression;
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
const symbol = context.checker.getSymbolAtLocation(current);
|
|
332
|
+
const boundExpression = symbol ? bindings.get(symbol) : undefined;
|
|
333
|
+
return boundExpression ? resolveBoundExpression(context, boundExpression, bindings) : expression;
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
function createParameterBindings(
|
|
337
|
+
context: AnalysisContext,
|
|
338
|
+
declaration: LocalFunctionLikeWithBody,
|
|
339
|
+
argumentsList: readonly ts.Expression[],
|
|
340
|
+
outerBindings: ParameterBindings,
|
|
341
|
+
): ParameterBindings {
|
|
342
|
+
const bindings = new Map<ts.Symbol, ts.Expression>();
|
|
343
|
+
|
|
344
|
+
declaration.parameters.forEach((parameter, index) => {
|
|
345
|
+
if (!ts.isIdentifier(parameter.name)) {
|
|
346
|
+
return;
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
const parameterSymbol = context.checker.getSymbolAtLocation(parameter.name);
|
|
350
|
+
const argument = argumentsList[index];
|
|
351
|
+
if (!parameterSymbol || !argument) {
|
|
352
|
+
return;
|
|
353
|
+
}
|
|
354
|
+
|
|
355
|
+
bindings.set(parameterSymbol, resolveBoundExpression(context, argument, outerBindings));
|
|
356
|
+
});
|
|
357
|
+
|
|
358
|
+
return bindings;
|
|
359
|
+
}
|
|
360
|
+
|
|
361
|
+
interface PromiseRecoveryContinuation {
|
|
362
|
+
bindings: ParameterBindings;
|
|
363
|
+
expression: ts.Expression;
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
type RecoveryPathSegment = ExportSummaryRecoveryPathSegment;
|
|
367
|
+
|
|
368
|
+
type FreshArrayExtractionMethod = 'at' | 'filter' | 'find' | 'flatMap';
|
|
369
|
+
type PromiseContainerCombinator = 'all' | 'allSettled' | 'any' | 'race';
|
|
370
|
+
|
|
371
|
+
function getEquivalentRecoveryExpressions(
|
|
372
|
+
expression: ts.Expression,
|
|
373
|
+
): readonly ts.Expression[] | undefined {
|
|
374
|
+
const current = getUnwrappedExpression(expression);
|
|
375
|
+
|
|
376
|
+
if (ts.isConditionalExpression(current)) {
|
|
377
|
+
return [current.whenTrue, current.whenFalse];
|
|
378
|
+
}
|
|
379
|
+
|
|
380
|
+
if (
|
|
381
|
+
ts.isBinaryExpression(current) &&
|
|
382
|
+
current.operatorToken.kind === ts.SyntaxKind.QuestionQuestionToken
|
|
383
|
+
) {
|
|
384
|
+
return [current.left, current.right];
|
|
385
|
+
}
|
|
386
|
+
|
|
387
|
+
return undefined;
|
|
388
|
+
}
|
|
389
|
+
|
|
390
|
+
function doesRecoveryPathStartWith(
|
|
391
|
+
path: readonly RecoveryPathSegment[],
|
|
392
|
+
prefix: readonly RecoveryPathSegment[],
|
|
393
|
+
): boolean {
|
|
394
|
+
return prefix.length <= path.length &&
|
|
395
|
+
prefix.every((segment, index) => {
|
|
396
|
+
const candidate = path[index];
|
|
397
|
+
if (!candidate || candidate.kind !== segment.kind) {
|
|
398
|
+
return false;
|
|
399
|
+
}
|
|
400
|
+
|
|
401
|
+
if (segment.kind === 'property') {
|
|
402
|
+
if (candidate.kind !== 'property') {
|
|
403
|
+
return false;
|
|
404
|
+
}
|
|
405
|
+
return segment.name === candidate.name;
|
|
406
|
+
}
|
|
407
|
+
|
|
408
|
+
if (candidate.kind !== 'index') {
|
|
409
|
+
return false;
|
|
410
|
+
}
|
|
411
|
+
return segment.index === candidate.index;
|
|
412
|
+
});
|
|
413
|
+
}
|
|
414
|
+
|
|
415
|
+
function serializeRecoveryPath(path: readonly RecoveryPathSegment[]): string {
|
|
416
|
+
return path.map((segment) =>
|
|
417
|
+
segment.kind === 'property' ? `p:${segment.name}` : `i:${segment.index}`
|
|
418
|
+
).join('/');
|
|
419
|
+
}
|
|
420
|
+
|
|
421
|
+
function getRecoveryAccessSegment(
|
|
422
|
+
expression: ts.Expression,
|
|
423
|
+
): { base: ts.Expression; segment: RecoveryPathSegment } | undefined {
|
|
424
|
+
const current = getUnwrappedExpression(expression);
|
|
425
|
+
|
|
426
|
+
if (ts.isPropertyAccessExpression(current)) {
|
|
427
|
+
return {
|
|
428
|
+
base: current.expression,
|
|
429
|
+
segment: { kind: 'property', name: current.name.text },
|
|
430
|
+
};
|
|
431
|
+
}
|
|
432
|
+
|
|
433
|
+
if (
|
|
434
|
+
ts.isElementAccessExpression(current) &&
|
|
435
|
+
current.argumentExpression &&
|
|
436
|
+
(ts.isStringLiteral(current.argumentExpression) ||
|
|
437
|
+
ts.isNumericLiteral(current.argumentExpression))
|
|
438
|
+
) {
|
|
439
|
+
return ts.isNumericLiteral(current.argumentExpression)
|
|
440
|
+
? {
|
|
441
|
+
base: current.expression,
|
|
442
|
+
segment: { kind: 'index', index: Number(current.argumentExpression.text) },
|
|
443
|
+
}
|
|
444
|
+
: {
|
|
445
|
+
base: current.expression,
|
|
446
|
+
segment: { kind: 'property', name: current.argumentExpression.text },
|
|
447
|
+
};
|
|
448
|
+
}
|
|
449
|
+
|
|
450
|
+
return undefined;
|
|
451
|
+
}
|
|
452
|
+
|
|
453
|
+
function getBindingPatternRecoveryPath(
|
|
454
|
+
context: AnalysisContext,
|
|
455
|
+
bindingName: ts.BindingName,
|
|
456
|
+
targetSymbol: ts.Symbol,
|
|
457
|
+
currentPath: readonly RecoveryPathSegment[] = [],
|
|
458
|
+
): readonly RecoveryPathSegment[] | undefined {
|
|
459
|
+
if (ts.isIdentifier(bindingName)) {
|
|
460
|
+
const bindingSymbol = context.checker.getSymbolAtLocation(bindingName);
|
|
461
|
+
return bindingSymbol === targetSymbol ? currentPath : undefined;
|
|
462
|
+
}
|
|
463
|
+
|
|
464
|
+
if (ts.isArrayBindingPattern(bindingName)) {
|
|
465
|
+
for (const [index, element] of bindingName.elements.entries()) {
|
|
466
|
+
if (ts.isOmittedExpression(element) || element.dotDotDotToken) {
|
|
467
|
+
continue;
|
|
468
|
+
}
|
|
469
|
+
|
|
470
|
+
const path = getBindingPatternRecoveryPath(
|
|
471
|
+
context,
|
|
472
|
+
element.name,
|
|
473
|
+
targetSymbol,
|
|
474
|
+
[...currentPath, { kind: 'index', index }],
|
|
475
|
+
);
|
|
476
|
+
if (path) {
|
|
477
|
+
return path;
|
|
478
|
+
}
|
|
479
|
+
}
|
|
480
|
+
|
|
481
|
+
return undefined;
|
|
482
|
+
}
|
|
483
|
+
|
|
484
|
+
for (const element of bindingName.elements) {
|
|
485
|
+
if (element.dotDotDotToken) {
|
|
486
|
+
continue;
|
|
487
|
+
}
|
|
488
|
+
|
|
489
|
+
const propertyName = element.propertyName
|
|
490
|
+
? getObjectLiteralPropertyNameText(element.propertyName)
|
|
491
|
+
: ts.isIdentifier(element.name)
|
|
492
|
+
? element.name.text
|
|
493
|
+
: undefined;
|
|
494
|
+
if (!propertyName) {
|
|
495
|
+
continue;
|
|
496
|
+
}
|
|
497
|
+
|
|
498
|
+
const path = getBindingPatternRecoveryPath(
|
|
499
|
+
context,
|
|
500
|
+
element.name,
|
|
501
|
+
targetSymbol,
|
|
502
|
+
[...currentPath, { kind: 'property', name: propertyName }],
|
|
503
|
+
);
|
|
504
|
+
if (path) {
|
|
505
|
+
return path;
|
|
506
|
+
}
|
|
507
|
+
}
|
|
508
|
+
|
|
509
|
+
return undefined;
|
|
510
|
+
}
|
|
511
|
+
|
|
512
|
+
function getEnclosingConstBindingInitializer(
|
|
513
|
+
declaration: ts.BindingElement,
|
|
514
|
+
): { bindingName: ts.BindingName; initializer: ts.Expression } | undefined {
|
|
515
|
+
let current: ts.Node = declaration;
|
|
516
|
+
|
|
517
|
+
while (current.parent) {
|
|
518
|
+
current = current.parent;
|
|
519
|
+
|
|
520
|
+
if (ts.isVariableDeclaration(current)) {
|
|
521
|
+
return current.initializer && isConstVariableDeclaration(current)
|
|
522
|
+
? { bindingName: current.name, initializer: current.initializer }
|
|
523
|
+
: undefined;
|
|
524
|
+
}
|
|
525
|
+
}
|
|
526
|
+
|
|
527
|
+
return undefined;
|
|
528
|
+
}
|
|
529
|
+
|
|
530
|
+
function getPromiseStaticMethodName(
|
|
531
|
+
context: AnalysisContext,
|
|
532
|
+
node: ts.CallExpression,
|
|
533
|
+
): PromiseContainerCombinator | 'resolve' | undefined {
|
|
534
|
+
const info = getResolvedBuiltinSignatureInfo(context, node);
|
|
535
|
+
if (!info || info.ownerName !== 'PromiseConstructor') {
|
|
536
|
+
return undefined;
|
|
537
|
+
}
|
|
538
|
+
|
|
539
|
+
switch (info.memberName) {
|
|
540
|
+
case 'all':
|
|
541
|
+
case 'allSettled':
|
|
542
|
+
case 'any':
|
|
543
|
+
case 'race':
|
|
544
|
+
case 'resolve':
|
|
545
|
+
return info.memberName;
|
|
546
|
+
default:
|
|
547
|
+
return undefined;
|
|
548
|
+
}
|
|
549
|
+
}
|
|
550
|
+
|
|
551
|
+
function getFreshArrayExtractionMethodName(
|
|
552
|
+
node: ts.CallExpression,
|
|
553
|
+
): FreshArrayExtractionMethod | undefined {
|
|
554
|
+
if (ts.isPropertyAccessExpression(node.expression)) {
|
|
555
|
+
switch (node.expression.name.text) {
|
|
556
|
+
case 'at':
|
|
557
|
+
case 'filter':
|
|
558
|
+
case 'find':
|
|
559
|
+
case 'flatMap':
|
|
560
|
+
return node.expression.name.text;
|
|
561
|
+
}
|
|
562
|
+
}
|
|
563
|
+
|
|
564
|
+
if (
|
|
565
|
+
ts.isElementAccessExpression(node.expression) &&
|
|
566
|
+
node.expression.argumentExpression &&
|
|
567
|
+
(
|
|
568
|
+
ts.isStringLiteral(node.expression.argumentExpression) ||
|
|
569
|
+
ts.isNoSubstitutionTemplateLiteral(node.expression.argumentExpression)
|
|
570
|
+
)
|
|
571
|
+
) {
|
|
572
|
+
switch (node.expression.argumentExpression.text) {
|
|
573
|
+
case 'at':
|
|
574
|
+
case 'filter':
|
|
575
|
+
case 'find':
|
|
576
|
+
case 'flatMap':
|
|
577
|
+
return node.expression.argumentExpression.text;
|
|
578
|
+
}
|
|
579
|
+
}
|
|
580
|
+
|
|
581
|
+
return undefined;
|
|
582
|
+
}
|
|
583
|
+
|
|
584
|
+
function getFreshArrayExtractionTargetExpression(
|
|
585
|
+
node: ts.CallExpression,
|
|
586
|
+
): ts.Expression | undefined {
|
|
587
|
+
const methodName = getFreshArrayExtractionMethodName(node);
|
|
588
|
+
if (!methodName) {
|
|
589
|
+
return undefined;
|
|
590
|
+
}
|
|
591
|
+
|
|
592
|
+
if (ts.isPropertyAccessExpression(node.expression)) {
|
|
593
|
+
return node.expression.expression;
|
|
594
|
+
}
|
|
595
|
+
|
|
596
|
+
if (ts.isElementAccessExpression(node.expression)) {
|
|
597
|
+
return node.expression.expression;
|
|
598
|
+
}
|
|
599
|
+
|
|
600
|
+
return undefined;
|
|
601
|
+
}
|
|
602
|
+
|
|
603
|
+
function getFreshArrayMethodInputs(
|
|
604
|
+
context: AnalysisContext,
|
|
605
|
+
callExpression: ts.CallExpression,
|
|
606
|
+
bindings: ParameterBindings,
|
|
607
|
+
seenSymbols: Set<ts.Symbol>,
|
|
608
|
+
): readonly ts.Expression[] | undefined {
|
|
609
|
+
const targetExpression = getFreshArrayExtractionTargetExpression(callExpression);
|
|
610
|
+
if (!targetExpression) {
|
|
611
|
+
return undefined;
|
|
612
|
+
}
|
|
613
|
+
|
|
614
|
+
const arrayLiteral = getArrayLiteralFromExpression(context, targetExpression, bindings, seenSymbols);
|
|
615
|
+
return arrayLiteral?.elements.filter((element): element is ts.Expression =>
|
|
616
|
+
!ts.isOmittedExpression(element)
|
|
617
|
+
);
|
|
618
|
+
}
|
|
619
|
+
|
|
620
|
+
function getIntegerArgumentValue(expression: ts.Expression | undefined): number | undefined {
|
|
621
|
+
if (!expression) {
|
|
622
|
+
return undefined;
|
|
623
|
+
}
|
|
624
|
+
|
|
625
|
+
const current = getUnwrappedExpression(expression);
|
|
626
|
+
if (ts.isNumericLiteral(current)) {
|
|
627
|
+
const value = Number(current.text);
|
|
628
|
+
return Number.isInteger(value) ? value : undefined;
|
|
629
|
+
}
|
|
630
|
+
|
|
631
|
+
if (
|
|
632
|
+
ts.isPrefixUnaryExpression(current) &&
|
|
633
|
+
current.operator === ts.SyntaxKind.MinusToken &&
|
|
634
|
+
ts.isNumericLiteral(current.operand)
|
|
635
|
+
) {
|
|
636
|
+
const value = Number(current.operand.text);
|
|
637
|
+
return Number.isInteger(value) ? -value : undefined;
|
|
638
|
+
}
|
|
639
|
+
|
|
640
|
+
return undefined;
|
|
641
|
+
}
|
|
642
|
+
|
|
643
|
+
function getFreshArrayAtIndex(
|
|
644
|
+
callExpression: ts.CallExpression,
|
|
645
|
+
inputCount: number,
|
|
646
|
+
): number | undefined {
|
|
647
|
+
const index = getIntegerArgumentValue(callExpression.arguments[0]);
|
|
648
|
+
if (index === undefined) {
|
|
649
|
+
return undefined;
|
|
650
|
+
}
|
|
651
|
+
|
|
652
|
+
const normalizedIndex = index >= 0 ? index : inputCount + index;
|
|
653
|
+
return normalizedIndex >= 0 && normalizedIndex < inputCount ? normalizedIndex : undefined;
|
|
654
|
+
}
|
|
655
|
+
|
|
656
|
+
function getLocalFunctionLikeFromExpression(
|
|
657
|
+
context: AnalysisContext,
|
|
658
|
+
expression: ts.Expression | undefined,
|
|
659
|
+
): LocalFunctionLikeWithBody | undefined {
|
|
660
|
+
if (!expression) {
|
|
661
|
+
return undefined;
|
|
662
|
+
}
|
|
663
|
+
|
|
664
|
+
const current = getUnwrappedExpression(expression);
|
|
665
|
+
if (isLocalFunctionLikeWithBody(current)) {
|
|
666
|
+
return current;
|
|
667
|
+
}
|
|
668
|
+
|
|
669
|
+
if (!ts.isIdentifier(current)) {
|
|
670
|
+
return undefined;
|
|
671
|
+
}
|
|
672
|
+
|
|
673
|
+
const symbol = context.checker.getSymbolAtLocation(current);
|
|
674
|
+
return symbol ? getLocalFunctionLikeFromSymbol(symbol) : undefined;
|
|
675
|
+
}
|
|
676
|
+
|
|
677
|
+
function getFreshArrayFlatMapReturnInfo(
|
|
678
|
+
context: AnalysisContext,
|
|
679
|
+
callExpression: ts.CallExpression,
|
|
680
|
+
): { callback: LocalFunctionLikeWithBody; returnExpression: ts.Expression } | undefined {
|
|
681
|
+
if (getFreshArrayExtractionMethodName(callExpression) !== 'flatMap') {
|
|
682
|
+
return undefined;
|
|
683
|
+
}
|
|
684
|
+
|
|
685
|
+
const callback = getLocalFunctionLikeFromExpression(context, callExpression.arguments[0]);
|
|
686
|
+
const returnExpression = callback ? getDirectReturnExpression(callback) : undefined;
|
|
687
|
+
return callback && returnExpression ? { callback, returnExpression } : undefined;
|
|
688
|
+
}
|
|
689
|
+
|
|
690
|
+
function getFlatMapElementCandidatePaths(
|
|
691
|
+
path: readonly RecoveryPathSegment[],
|
|
692
|
+
): readonly (readonly RecoveryPathSegment[])[] | undefined {
|
|
693
|
+
const [segment, ...restPath] = path;
|
|
694
|
+
if (!segment || segment.kind !== 'index') {
|
|
695
|
+
return undefined;
|
|
696
|
+
}
|
|
697
|
+
|
|
698
|
+
return [restPath, path];
|
|
699
|
+
}
|
|
700
|
+
|
|
701
|
+
function getArrayLiteralFromExpression(
|
|
702
|
+
context: AnalysisContext,
|
|
703
|
+
expression: ts.Expression,
|
|
704
|
+
bindings: ParameterBindings,
|
|
705
|
+
seenSymbols: Set<ts.Symbol>,
|
|
706
|
+
): ts.ArrayLiteralExpression | undefined {
|
|
707
|
+
const resolvedExpression = resolveBoundExpression(context, expression, bindings);
|
|
708
|
+
const current = getUnwrappedExpression(resolvedExpression);
|
|
709
|
+
|
|
710
|
+
if (ts.isArrayLiteralExpression(current)) {
|
|
711
|
+
return current;
|
|
712
|
+
}
|
|
713
|
+
|
|
714
|
+
if (ts.isIdentifier(current)) {
|
|
715
|
+
const symbol = context.checker.getSymbolAtLocation(current);
|
|
716
|
+
if (!symbol || seenSymbols.has(symbol)) {
|
|
717
|
+
return undefined;
|
|
718
|
+
}
|
|
719
|
+
seenSymbols.add(symbol);
|
|
720
|
+
|
|
721
|
+
for (const declaration of symbol.getDeclarations() ?? []) {
|
|
722
|
+
if (
|
|
723
|
+
ts.isVariableDeclaration(declaration) &&
|
|
724
|
+
declaration.initializer &&
|
|
725
|
+
isConstVariableDeclaration(declaration)
|
|
726
|
+
) {
|
|
727
|
+
return getArrayLiteralFromExpression(
|
|
728
|
+
context,
|
|
729
|
+
declaration.initializer,
|
|
730
|
+
bindings,
|
|
731
|
+
seenSymbols,
|
|
732
|
+
);
|
|
733
|
+
}
|
|
734
|
+
}
|
|
735
|
+
|
|
736
|
+
return undefined;
|
|
737
|
+
}
|
|
738
|
+
|
|
739
|
+
const equivalentExpressions = getEquivalentRecoveryExpressions(resolvedExpression);
|
|
740
|
+
if (equivalentExpressions) {
|
|
741
|
+
for (const equivalentExpression of equivalentExpressions) {
|
|
742
|
+
const arrayLiteral = getArrayLiteralFromExpression(
|
|
743
|
+
context,
|
|
744
|
+
equivalentExpression,
|
|
745
|
+
bindings,
|
|
746
|
+
seenSymbols,
|
|
747
|
+
);
|
|
748
|
+
if (arrayLiteral) {
|
|
749
|
+
return arrayLiteral;
|
|
750
|
+
}
|
|
751
|
+
}
|
|
752
|
+
|
|
753
|
+
return undefined;
|
|
754
|
+
}
|
|
755
|
+
|
|
756
|
+
if (!ts.isCallExpression(current)) {
|
|
757
|
+
return undefined;
|
|
758
|
+
}
|
|
759
|
+
|
|
760
|
+
const promiseContinuation = getPromiseRecoveryContinuation(context, current, bindings);
|
|
761
|
+
if (promiseContinuation) {
|
|
762
|
+
return getArrayLiteralFromExpression(
|
|
763
|
+
context,
|
|
764
|
+
promiseContinuation.expression,
|
|
765
|
+
promiseContinuation.bindings,
|
|
766
|
+
seenSymbols,
|
|
767
|
+
);
|
|
768
|
+
}
|
|
769
|
+
|
|
770
|
+
const localDirectReturn = getDirectReturnLocalCall(context, current);
|
|
771
|
+
if (!localDirectReturn) {
|
|
772
|
+
return undefined;
|
|
773
|
+
}
|
|
774
|
+
|
|
775
|
+
const localBindings = mergeParameterBindings(
|
|
776
|
+
bindings,
|
|
777
|
+
createParameterBindings(context, localDirectReturn.declaration, current.arguments, bindings),
|
|
778
|
+
);
|
|
779
|
+
return getArrayLiteralFromExpression(
|
|
780
|
+
context,
|
|
781
|
+
localDirectReturn.returnExpression,
|
|
782
|
+
localBindings,
|
|
783
|
+
seenSymbols,
|
|
784
|
+
);
|
|
785
|
+
}
|
|
786
|
+
|
|
787
|
+
function getPromiseCombinatorInputs(
|
|
788
|
+
context: AnalysisContext,
|
|
789
|
+
callExpression: ts.CallExpression,
|
|
790
|
+
bindings: ParameterBindings,
|
|
791
|
+
seenSymbols: Set<ts.Symbol>,
|
|
792
|
+
): readonly ts.Expression[] | undefined {
|
|
793
|
+
const methodName = getPromiseStaticMethodName(context, callExpression);
|
|
794
|
+
if (
|
|
795
|
+
methodName !== 'all' &&
|
|
796
|
+
methodName !== 'allSettled' &&
|
|
797
|
+
methodName !== 'any' &&
|
|
798
|
+
methodName !== 'race'
|
|
799
|
+
) {
|
|
800
|
+
return undefined;
|
|
801
|
+
}
|
|
802
|
+
|
|
803
|
+
const arrayLiteral = callExpression.arguments[0]
|
|
804
|
+
? getArrayLiteralFromExpression(context, callExpression.arguments[0], bindings, seenSymbols)
|
|
805
|
+
: undefined;
|
|
806
|
+
return arrayLiteral?.elements.filter((element): element is ts.Expression =>
|
|
807
|
+
!ts.isOmittedExpression(element)
|
|
808
|
+
);
|
|
809
|
+
}
|
|
810
|
+
|
|
811
|
+
function getPromiseRecoveryContinuation(
|
|
812
|
+
context: AnalysisContext,
|
|
813
|
+
callExpression: ts.CallExpression,
|
|
814
|
+
bindings: ParameterBindings,
|
|
815
|
+
): PromiseRecoveryContinuation | undefined {
|
|
816
|
+
const thenTarget = getThenCallTargetExpression(context, callExpression);
|
|
817
|
+
const thenCallback = getThenCallback(callExpression);
|
|
818
|
+
const thenReturnExpression = thenCallback ? getDirectReturnExpression(thenCallback) : undefined;
|
|
819
|
+
if (thenTarget && thenCallback && thenReturnExpression) {
|
|
820
|
+
return {
|
|
821
|
+
bindings: mergeParameterBindings(
|
|
822
|
+
bindings,
|
|
823
|
+
createParameterBindings(context, thenCallback, [thenTarget], bindings),
|
|
824
|
+
),
|
|
825
|
+
expression: thenReturnExpression,
|
|
826
|
+
};
|
|
827
|
+
}
|
|
828
|
+
|
|
829
|
+
const passthroughTarget = getPromisePassthroughTargetExpression(context, callExpression);
|
|
830
|
+
if (passthroughTarget) {
|
|
831
|
+
return { bindings, expression: passthroughTarget };
|
|
832
|
+
}
|
|
833
|
+
|
|
834
|
+
const resolvedPromiseValue = getPromiseResolveWrappedExpression(context, callExpression);
|
|
835
|
+
if (resolvedPromiseValue) {
|
|
836
|
+
return { bindings, expression: resolvedPromiseValue };
|
|
837
|
+
}
|
|
838
|
+
|
|
839
|
+
return undefined;
|
|
840
|
+
}
|
|
841
|
+
|
|
842
|
+
function getObjectLiteralPropertyNameText(name: ts.PropertyName): string | undefined {
|
|
843
|
+
if (
|
|
844
|
+
ts.isIdentifier(name) ||
|
|
845
|
+
ts.isStringLiteral(name) ||
|
|
846
|
+
ts.isNumericLiteral(name) ||
|
|
847
|
+
ts.isNoSubstitutionTemplateLiteral(name)
|
|
848
|
+
) {
|
|
849
|
+
return name.text;
|
|
850
|
+
}
|
|
851
|
+
|
|
852
|
+
if (
|
|
853
|
+
ts.isComputedPropertyName(name) &&
|
|
854
|
+
(ts.isStringLiteral(name.expression) || ts.isNumericLiteral(name.expression))
|
|
855
|
+
) {
|
|
856
|
+
return name.expression.text;
|
|
857
|
+
}
|
|
858
|
+
|
|
859
|
+
return undefined;
|
|
860
|
+
}
|
|
861
|
+
|
|
862
|
+
function dedupeHelperWrapperEntries(
|
|
863
|
+
entries: readonly ExportCallableHelperWrapperEntry[],
|
|
864
|
+
): readonly ExportCallableHelperWrapperEntry[] | undefined {
|
|
865
|
+
const seenPaths = new Set<string>();
|
|
866
|
+
|
|
867
|
+
for (const entry of entries) {
|
|
868
|
+
const pathKey = serializeRecoveryPath(entry.recoveryPath);
|
|
869
|
+
if (seenPaths.has(pathKey)) {
|
|
870
|
+
return undefined;
|
|
871
|
+
}
|
|
872
|
+
seenPaths.add(pathKey);
|
|
873
|
+
}
|
|
874
|
+
|
|
875
|
+
return entries;
|
|
876
|
+
}
|
|
877
|
+
|
|
878
|
+
function collectHelperWrapperEntries(
|
|
879
|
+
context: AnalysisContext,
|
|
880
|
+
node: LocalFunctionLikeWithBody,
|
|
881
|
+
expression: ts.Expression,
|
|
882
|
+
currentPath: readonly RecoveryPathSegment[] = [],
|
|
883
|
+
): readonly ExportCallableHelperWrapperEntry[] | undefined {
|
|
884
|
+
const current = getUnwrappedExpression(expression);
|
|
885
|
+
const returnedParameterIndex = getReturnedParameterIndex(context, node, current);
|
|
886
|
+
if (returnedParameterIndex !== undefined) {
|
|
887
|
+
return [{ parameterIndex: returnedParameterIndex, recoveryPath: currentPath }];
|
|
888
|
+
}
|
|
889
|
+
|
|
890
|
+
if (ts.isObjectLiteralExpression(current)) {
|
|
891
|
+
const entries: ExportCallableHelperWrapperEntry[] = [];
|
|
892
|
+
const seenPropertyNames = new Set<string>();
|
|
893
|
+
|
|
894
|
+
for (const property of current.properties) {
|
|
895
|
+
if (ts.isSpreadAssignment(property)) {
|
|
896
|
+
return undefined;
|
|
897
|
+
}
|
|
898
|
+
|
|
899
|
+
if (ts.isPropertyAssignment(property)) {
|
|
900
|
+
const propertyName = getObjectLiteralPropertyNameText(property.name);
|
|
901
|
+
if (!propertyName || seenPropertyNames.has(propertyName)) {
|
|
902
|
+
return undefined;
|
|
903
|
+
}
|
|
904
|
+
|
|
905
|
+
seenPropertyNames.add(propertyName);
|
|
906
|
+
const propertyEntries = collectHelperWrapperEntries(
|
|
907
|
+
context,
|
|
908
|
+
node,
|
|
909
|
+
property.initializer,
|
|
910
|
+
[...currentPath, { kind: 'property', name: propertyName }],
|
|
911
|
+
);
|
|
912
|
+
if (!propertyEntries) {
|
|
913
|
+
return undefined;
|
|
914
|
+
}
|
|
915
|
+
|
|
916
|
+
entries.push(...propertyEntries);
|
|
917
|
+
continue;
|
|
918
|
+
}
|
|
919
|
+
|
|
920
|
+
if (ts.isShorthandPropertyAssignment(property)) {
|
|
921
|
+
const propertyName = property.name.text;
|
|
922
|
+
if (seenPropertyNames.has(propertyName)) {
|
|
923
|
+
return undefined;
|
|
924
|
+
}
|
|
925
|
+
|
|
926
|
+
seenPropertyNames.add(propertyName);
|
|
927
|
+
const valueSymbol = context.checker.getShorthandAssignmentValueSymbol(property);
|
|
928
|
+
const parameterIndex = valueSymbol
|
|
929
|
+
? getParameterIndexForSymbol(context, node, valueSymbol)
|
|
930
|
+
: undefined;
|
|
931
|
+
if (parameterIndex !== undefined) {
|
|
932
|
+
entries.push({
|
|
933
|
+
parameterIndex,
|
|
934
|
+
recoveryPath: [...currentPath, { kind: 'property', name: propertyName }],
|
|
935
|
+
});
|
|
936
|
+
}
|
|
937
|
+
continue;
|
|
938
|
+
}
|
|
939
|
+
|
|
940
|
+
return undefined;
|
|
941
|
+
}
|
|
942
|
+
|
|
943
|
+
return dedupeHelperWrapperEntries(entries);
|
|
944
|
+
}
|
|
945
|
+
|
|
946
|
+
if (ts.isArrayLiteralExpression(current)) {
|
|
947
|
+
const entries: ExportCallableHelperWrapperEntry[] = [];
|
|
948
|
+
|
|
949
|
+
for (const [index, element] of current.elements.entries()) {
|
|
950
|
+
if (!ts.isExpression(element) || ts.isSpreadElement(element)) {
|
|
951
|
+
return undefined;
|
|
952
|
+
}
|
|
953
|
+
|
|
954
|
+
const elementEntries = collectHelperWrapperEntries(
|
|
955
|
+
context,
|
|
956
|
+
node,
|
|
957
|
+
element,
|
|
958
|
+
[...currentPath, { kind: 'index', index }],
|
|
959
|
+
);
|
|
960
|
+
if (!elementEntries) {
|
|
961
|
+
return undefined;
|
|
962
|
+
}
|
|
963
|
+
|
|
964
|
+
entries.push(...elementEntries);
|
|
965
|
+
}
|
|
966
|
+
|
|
967
|
+
return dedupeHelperWrapperEntries(entries);
|
|
968
|
+
}
|
|
969
|
+
|
|
970
|
+
return [];
|
|
971
|
+
}
|
|
972
|
+
|
|
973
|
+
function getArrayLiteralElementValue(
|
|
974
|
+
arrayLiteral: ts.ArrayLiteralExpression,
|
|
975
|
+
index: number,
|
|
976
|
+
): ts.Expression | undefined {
|
|
977
|
+
const element = arrayLiteral.elements[index];
|
|
978
|
+
return element && !ts.isOmittedExpression(element) ? element : undefined;
|
|
979
|
+
}
|
|
980
|
+
|
|
981
|
+
function getObjectLiteralPropertyFamilyAtPathWithBindings<Family extends ExportedNonOrdinaryFamily>(
|
|
982
|
+
context: AnalysisContext,
|
|
983
|
+
objectLiteral: ts.ObjectLiteralExpression,
|
|
984
|
+
propertyName: string,
|
|
985
|
+
restPath: readonly RecoveryPathSegment[],
|
|
986
|
+
spec: NonOrdinaryRecoverySpec<Family>,
|
|
987
|
+
seenSymbols: Set<ts.Symbol>,
|
|
988
|
+
bindings: ParameterBindings,
|
|
989
|
+
): Family | undefined {
|
|
990
|
+
for (const property of objectLiteral.properties) {
|
|
991
|
+
if (
|
|
992
|
+
ts.isPropertyAssignment(property) &&
|
|
993
|
+
getObjectLiteralPropertyNameText(property.name) === propertyName
|
|
994
|
+
) {
|
|
995
|
+
return getFamilyAtRecoveryPathWithBindings(
|
|
996
|
+
context,
|
|
997
|
+
property.initializer,
|
|
998
|
+
restPath,
|
|
999
|
+
spec,
|
|
1000
|
+
seenSymbols,
|
|
1001
|
+
bindings,
|
|
1002
|
+
);
|
|
1003
|
+
}
|
|
1004
|
+
|
|
1005
|
+
if (
|
|
1006
|
+
ts.isShorthandPropertyAssignment(property) &&
|
|
1007
|
+
property.name.text === propertyName
|
|
1008
|
+
) {
|
|
1009
|
+
const valueSymbol = context.checker.getShorthandAssignmentValueSymbol(property);
|
|
1010
|
+
if (!valueSymbol) {
|
|
1011
|
+
return undefined;
|
|
1012
|
+
}
|
|
1013
|
+
|
|
1014
|
+
const boundExpression = bindings.get(valueSymbol);
|
|
1015
|
+
if (boundExpression) {
|
|
1016
|
+
return getFamilyAtRecoveryPathWithBindings(
|
|
1017
|
+
context,
|
|
1018
|
+
boundExpression,
|
|
1019
|
+
restPath,
|
|
1020
|
+
spec,
|
|
1021
|
+
seenSymbols,
|
|
1022
|
+
bindings,
|
|
1023
|
+
);
|
|
1024
|
+
}
|
|
1025
|
+
|
|
1026
|
+
return getAliasedKnownNonOrdinaryFamily(
|
|
1027
|
+
context,
|
|
1028
|
+
valueSymbol,
|
|
1029
|
+
restPath,
|
|
1030
|
+
spec,
|
|
1031
|
+
seenSymbols,
|
|
1032
|
+
);
|
|
1033
|
+
}
|
|
1034
|
+
}
|
|
1035
|
+
|
|
1036
|
+
return undefined;
|
|
1037
|
+
}
|
|
1038
|
+
|
|
1039
|
+
function getPromiseCombinatorFamilyAtPathWithBindings<Family extends ExportedNonOrdinaryFamily>(
|
|
1040
|
+
context: AnalysisContext,
|
|
1041
|
+
callExpression: ts.CallExpression,
|
|
1042
|
+
path: readonly RecoveryPathSegment[],
|
|
1043
|
+
spec: NonOrdinaryRecoverySpec<Family>,
|
|
1044
|
+
seenSymbols: Set<ts.Symbol>,
|
|
1045
|
+
bindings: ParameterBindings,
|
|
1046
|
+
): Family | undefined {
|
|
1047
|
+
const methodName = getPromiseStaticMethodName(context, callExpression);
|
|
1048
|
+
if (
|
|
1049
|
+
methodName !== 'all' &&
|
|
1050
|
+
methodName !== 'allSettled' &&
|
|
1051
|
+
methodName !== 'any' &&
|
|
1052
|
+
methodName !== 'race'
|
|
1053
|
+
) {
|
|
1054
|
+
return undefined;
|
|
1055
|
+
}
|
|
1056
|
+
|
|
1057
|
+
const inputs = getPromiseCombinatorInputs(context, callExpression, bindings, seenSymbols);
|
|
1058
|
+
if (!inputs) {
|
|
1059
|
+
return undefined;
|
|
1060
|
+
}
|
|
1061
|
+
|
|
1062
|
+
if (methodName === 'all') {
|
|
1063
|
+
const [segment, ...restPath] = path;
|
|
1064
|
+
if (!segment || segment.kind !== 'index') {
|
|
1065
|
+
return undefined;
|
|
1066
|
+
}
|
|
1067
|
+
|
|
1068
|
+
const inputExpression = inputs[segment.index];
|
|
1069
|
+
return inputExpression
|
|
1070
|
+
? getFamilyAtRecoveryPathWithBindings(
|
|
1071
|
+
context,
|
|
1072
|
+
inputExpression,
|
|
1073
|
+
restPath,
|
|
1074
|
+
spec,
|
|
1075
|
+
seenSymbols,
|
|
1076
|
+
bindings,
|
|
1077
|
+
)
|
|
1078
|
+
: undefined;
|
|
1079
|
+
}
|
|
1080
|
+
|
|
1081
|
+
if (methodName === 'allSettled') {
|
|
1082
|
+
const [indexSegment, valueSegment, ...restPath] = path;
|
|
1083
|
+
if (
|
|
1084
|
+
!indexSegment ||
|
|
1085
|
+
indexSegment.kind !== 'index' ||
|
|
1086
|
+
!valueSegment ||
|
|
1087
|
+
valueSegment.kind !== 'property' ||
|
|
1088
|
+
valueSegment.name !== 'value'
|
|
1089
|
+
) {
|
|
1090
|
+
return undefined;
|
|
1091
|
+
}
|
|
1092
|
+
|
|
1093
|
+
const inputExpression = inputs[indexSegment.index];
|
|
1094
|
+
return inputExpression
|
|
1095
|
+
? getFamilyAtRecoveryPathWithBindings(
|
|
1096
|
+
context,
|
|
1097
|
+
inputExpression,
|
|
1098
|
+
restPath,
|
|
1099
|
+
spec,
|
|
1100
|
+
seenSymbols,
|
|
1101
|
+
bindings,
|
|
1102
|
+
)
|
|
1103
|
+
: undefined;
|
|
1104
|
+
}
|
|
1105
|
+
|
|
1106
|
+
for (const inputExpression of inputs) {
|
|
1107
|
+
const family = getFamilyAtRecoveryPathWithBindings(
|
|
1108
|
+
context,
|
|
1109
|
+
inputExpression,
|
|
1110
|
+
path,
|
|
1111
|
+
spec,
|
|
1112
|
+
seenSymbols,
|
|
1113
|
+
bindings,
|
|
1114
|
+
);
|
|
1115
|
+
if (family) {
|
|
1116
|
+
return family;
|
|
1117
|
+
}
|
|
1118
|
+
}
|
|
1119
|
+
|
|
1120
|
+
return undefined;
|
|
1121
|
+
}
|
|
1122
|
+
|
|
1123
|
+
function getFreshArrayExtractionFamilyAtPathWithBindings<Family extends ExportedNonOrdinaryFamily>(
|
|
1124
|
+
context: AnalysisContext,
|
|
1125
|
+
callExpression: ts.CallExpression,
|
|
1126
|
+
path: readonly RecoveryPathSegment[],
|
|
1127
|
+
spec: NonOrdinaryRecoverySpec<Family>,
|
|
1128
|
+
seenSymbols: Set<ts.Symbol>,
|
|
1129
|
+
bindings: ParameterBindings,
|
|
1130
|
+
): Family | undefined {
|
|
1131
|
+
const methodName = getFreshArrayExtractionMethodName(callExpression);
|
|
1132
|
+
if (!methodName) {
|
|
1133
|
+
return undefined;
|
|
1134
|
+
}
|
|
1135
|
+
|
|
1136
|
+
const inputs = getFreshArrayMethodInputs(context, callExpression, bindings, seenSymbols);
|
|
1137
|
+
if (!inputs) {
|
|
1138
|
+
return undefined;
|
|
1139
|
+
}
|
|
1140
|
+
|
|
1141
|
+
switch (methodName) {
|
|
1142
|
+
case 'at': {
|
|
1143
|
+
const index = getFreshArrayAtIndex(callExpression, inputs.length);
|
|
1144
|
+
if (index === undefined) {
|
|
1145
|
+
return undefined;
|
|
1146
|
+
}
|
|
1147
|
+
|
|
1148
|
+
const inputExpression = inputs[index];
|
|
1149
|
+
return inputExpression
|
|
1150
|
+
? getFamilyAtRecoveryPathWithBindings(
|
|
1151
|
+
context,
|
|
1152
|
+
inputExpression,
|
|
1153
|
+
path,
|
|
1154
|
+
spec,
|
|
1155
|
+
seenSymbols,
|
|
1156
|
+
bindings,
|
|
1157
|
+
)
|
|
1158
|
+
: undefined;
|
|
1159
|
+
}
|
|
1160
|
+
case 'find':
|
|
1161
|
+
for (const inputExpression of inputs) {
|
|
1162
|
+
const family = getFamilyAtRecoveryPathWithBindings(
|
|
1163
|
+
context,
|
|
1164
|
+
inputExpression,
|
|
1165
|
+
path,
|
|
1166
|
+
spec,
|
|
1167
|
+
seenSymbols,
|
|
1168
|
+
bindings,
|
|
1169
|
+
);
|
|
1170
|
+
if (family) {
|
|
1171
|
+
return family;
|
|
1172
|
+
}
|
|
1173
|
+
}
|
|
1174
|
+
return undefined;
|
|
1175
|
+
case 'filter': {
|
|
1176
|
+
const [segment, ...restPath] = path;
|
|
1177
|
+
if (!segment || segment.kind !== 'index') {
|
|
1178
|
+
return undefined;
|
|
1179
|
+
}
|
|
1180
|
+
|
|
1181
|
+
for (const inputExpression of inputs) {
|
|
1182
|
+
const family = getFamilyAtRecoveryPathWithBindings(
|
|
1183
|
+
context,
|
|
1184
|
+
inputExpression,
|
|
1185
|
+
restPath,
|
|
1186
|
+
spec,
|
|
1187
|
+
seenSymbols,
|
|
1188
|
+
bindings,
|
|
1189
|
+
);
|
|
1190
|
+
if (family) {
|
|
1191
|
+
return family;
|
|
1192
|
+
}
|
|
1193
|
+
}
|
|
1194
|
+
return undefined;
|
|
1195
|
+
}
|
|
1196
|
+
case 'flatMap': {
|
|
1197
|
+
const flatMapReturn = getFreshArrayFlatMapReturnInfo(context, callExpression);
|
|
1198
|
+
const candidatePaths = getFlatMapElementCandidatePaths(path);
|
|
1199
|
+
if (!flatMapReturn || !candidatePaths) {
|
|
1200
|
+
return undefined;
|
|
1201
|
+
}
|
|
1202
|
+
|
|
1203
|
+
for (const inputExpression of inputs) {
|
|
1204
|
+
const callbackBindings = mergeParameterBindings(
|
|
1205
|
+
bindings,
|
|
1206
|
+
createParameterBindings(
|
|
1207
|
+
context,
|
|
1208
|
+
flatMapReturn.callback,
|
|
1209
|
+
[inputExpression],
|
|
1210
|
+
bindings,
|
|
1211
|
+
),
|
|
1212
|
+
);
|
|
1213
|
+
for (const candidatePath of candidatePaths) {
|
|
1214
|
+
const family = getFamilyAtRecoveryPathWithBindings(
|
|
1215
|
+
context,
|
|
1216
|
+
flatMapReturn.returnExpression,
|
|
1217
|
+
candidatePath,
|
|
1218
|
+
spec,
|
|
1219
|
+
seenSymbols,
|
|
1220
|
+
callbackBindings,
|
|
1221
|
+
);
|
|
1222
|
+
if (family) {
|
|
1223
|
+
return family;
|
|
1224
|
+
}
|
|
1225
|
+
}
|
|
1226
|
+
}
|
|
1227
|
+
return undefined;
|
|
1228
|
+
}
|
|
1229
|
+
}
|
|
1230
|
+
}
|
|
1231
|
+
|
|
1232
|
+
function getFamilyAtRecoveryPathWithBindings<Family extends ExportedNonOrdinaryFamily>(
|
|
1233
|
+
context: AnalysisContext,
|
|
1234
|
+
expression: ts.Expression,
|
|
1235
|
+
path: readonly RecoveryPathSegment[],
|
|
1236
|
+
spec: NonOrdinaryRecoverySpec<Family>,
|
|
1237
|
+
seenSymbols: Set<ts.Symbol>,
|
|
1238
|
+
bindings: ParameterBindings,
|
|
1239
|
+
): Family | undefined {
|
|
1240
|
+
const resolvedExpression = resolveBoundExpression(context, expression, bindings);
|
|
1241
|
+
const accessSegment = getRecoveryAccessSegment(resolvedExpression);
|
|
1242
|
+
if (accessSegment) {
|
|
1243
|
+
return getFamilyAtRecoveryPathWithBindings(
|
|
1244
|
+
context,
|
|
1245
|
+
accessSegment.base,
|
|
1246
|
+
[accessSegment.segment, ...path],
|
|
1247
|
+
spec,
|
|
1248
|
+
seenSymbols,
|
|
1249
|
+
bindings,
|
|
1250
|
+
);
|
|
1251
|
+
}
|
|
1252
|
+
|
|
1253
|
+
if (path.length === 0) {
|
|
1254
|
+
const directFamily = spec.getDirectFamily(context, resolvedExpression);
|
|
1255
|
+
if (directFamily) {
|
|
1256
|
+
return directFamily;
|
|
1257
|
+
}
|
|
1258
|
+
}
|
|
1259
|
+
|
|
1260
|
+
const current = getUnwrappedExpression(resolvedExpression);
|
|
1261
|
+
|
|
1262
|
+
if (ts.isIdentifier(current)) {
|
|
1263
|
+
const symbol = context.checker.getSymbolAtLocation(current);
|
|
1264
|
+
return symbol
|
|
1265
|
+
? getAliasedKnownNonOrdinaryFamily(context, symbol, path, spec, seenSymbols)
|
|
1266
|
+
: undefined;
|
|
1267
|
+
}
|
|
1268
|
+
|
|
1269
|
+
const [segment, ...restPath] = path;
|
|
1270
|
+
if (ts.isObjectLiteralExpression(current)) {
|
|
1271
|
+
if (!segment || segment.kind !== 'property') {
|
|
1272
|
+
return undefined;
|
|
1273
|
+
}
|
|
1274
|
+
|
|
1275
|
+
return getObjectLiteralPropertyFamilyAtPathWithBindings(
|
|
1276
|
+
context,
|
|
1277
|
+
current,
|
|
1278
|
+
segment.name,
|
|
1279
|
+
restPath,
|
|
1280
|
+
spec,
|
|
1281
|
+
seenSymbols,
|
|
1282
|
+
bindings,
|
|
1283
|
+
);
|
|
1284
|
+
}
|
|
1285
|
+
|
|
1286
|
+
if (ts.isArrayLiteralExpression(current)) {
|
|
1287
|
+
if (!segment || segment.kind !== 'index') {
|
|
1288
|
+
return undefined;
|
|
1289
|
+
}
|
|
1290
|
+
|
|
1291
|
+
const element = getArrayLiteralElementValue(current, segment.index);
|
|
1292
|
+
return element
|
|
1293
|
+
? getFamilyAtRecoveryPathWithBindings(
|
|
1294
|
+
context,
|
|
1295
|
+
element,
|
|
1296
|
+
restPath,
|
|
1297
|
+
spec,
|
|
1298
|
+
seenSymbols,
|
|
1299
|
+
bindings,
|
|
1300
|
+
)
|
|
1301
|
+
: undefined;
|
|
1302
|
+
}
|
|
1303
|
+
|
|
1304
|
+
const equivalentExpressions = getEquivalentRecoveryExpressions(resolvedExpression);
|
|
1305
|
+
if (equivalentExpressions) {
|
|
1306
|
+
for (const equivalentExpression of equivalentExpressions) {
|
|
1307
|
+
const equivalentFamily = getFamilyAtRecoveryPathWithBindings(
|
|
1308
|
+
context,
|
|
1309
|
+
equivalentExpression,
|
|
1310
|
+
path,
|
|
1311
|
+
spec,
|
|
1312
|
+
seenSymbols,
|
|
1313
|
+
bindings,
|
|
1314
|
+
);
|
|
1315
|
+
if (equivalentFamily) {
|
|
1316
|
+
return equivalentFamily;
|
|
1317
|
+
}
|
|
1318
|
+
}
|
|
1319
|
+
return undefined;
|
|
1320
|
+
}
|
|
1321
|
+
|
|
1322
|
+
if (!ts.isCallExpression(current)) {
|
|
1323
|
+
return undefined;
|
|
1324
|
+
}
|
|
1325
|
+
|
|
1326
|
+
const promiseContinuation = getPromiseRecoveryContinuation(context, current, bindings);
|
|
1327
|
+
if (promiseContinuation) {
|
|
1328
|
+
return getFamilyAtRecoveryPathWithBindings(
|
|
1329
|
+
context,
|
|
1330
|
+
promiseContinuation.expression,
|
|
1331
|
+
path,
|
|
1332
|
+
spec,
|
|
1333
|
+
seenSymbols,
|
|
1334
|
+
promiseContinuation.bindings,
|
|
1335
|
+
);
|
|
1336
|
+
}
|
|
1337
|
+
|
|
1338
|
+
const promiseCombinatorFamily = getPromiseCombinatorFamilyAtPathWithBindings(
|
|
1339
|
+
context,
|
|
1340
|
+
current,
|
|
1341
|
+
path,
|
|
1342
|
+
spec,
|
|
1343
|
+
seenSymbols,
|
|
1344
|
+
bindings,
|
|
1345
|
+
);
|
|
1346
|
+
if (promiseCombinatorFamily) {
|
|
1347
|
+
return promiseCombinatorFamily;
|
|
1348
|
+
}
|
|
1349
|
+
|
|
1350
|
+
const freshArrayExtractionFamily = getFreshArrayExtractionFamilyAtPathWithBindings(
|
|
1351
|
+
context,
|
|
1352
|
+
current,
|
|
1353
|
+
path,
|
|
1354
|
+
spec,
|
|
1355
|
+
seenSymbols,
|
|
1356
|
+
bindings,
|
|
1357
|
+
);
|
|
1358
|
+
if (freshArrayExtractionFamily) {
|
|
1359
|
+
return freshArrayExtractionFamily;
|
|
1360
|
+
}
|
|
1361
|
+
|
|
1362
|
+
const localDirectReturn = getDirectReturnLocalCall(context, current);
|
|
1363
|
+
if (localDirectReturn) {
|
|
1364
|
+
const localBindings = mergeParameterBindings(
|
|
1365
|
+
bindings,
|
|
1366
|
+
createParameterBindings(context, localDirectReturn.declaration, current.arguments, bindings),
|
|
1367
|
+
);
|
|
1368
|
+
return getFamilyAtRecoveryPathWithBindings(
|
|
1369
|
+
context,
|
|
1370
|
+
localDirectReturn.returnExpression,
|
|
1371
|
+
path,
|
|
1372
|
+
spec,
|
|
1373
|
+
seenSymbols,
|
|
1374
|
+
localBindings,
|
|
1375
|
+
);
|
|
1376
|
+
}
|
|
1377
|
+
|
|
1378
|
+
const calleeSymbol = getCallExpressionCalleeSymbol(context, current);
|
|
1379
|
+
if (!calleeSymbol) {
|
|
1380
|
+
return undefined;
|
|
1381
|
+
}
|
|
1382
|
+
|
|
1383
|
+
const summary = context.exportSummaries.get(calleeSymbol);
|
|
1384
|
+
if (!summary) {
|
|
1385
|
+
return undefined;
|
|
1386
|
+
}
|
|
1387
|
+
|
|
1388
|
+
if (summary.kind === 'callableReturnedParameter') {
|
|
1389
|
+
const forwardedArgument = current.arguments[summary.parameterIndex];
|
|
1390
|
+
return forwardedArgument
|
|
1391
|
+
? getFamilyAtRecoveryPathWithBindings(
|
|
1392
|
+
context,
|
|
1393
|
+
forwardedArgument,
|
|
1394
|
+
path,
|
|
1395
|
+
spec,
|
|
1396
|
+
seenSymbols,
|
|
1397
|
+
bindings,
|
|
1398
|
+
)
|
|
1399
|
+
: undefined;
|
|
1400
|
+
}
|
|
1401
|
+
|
|
1402
|
+
if (summary.kind === 'callableHelperWrapper') {
|
|
1403
|
+
for (const entry of summary.entries) {
|
|
1404
|
+
if (!doesRecoveryPathStartWith(path, entry.recoveryPath)) {
|
|
1405
|
+
continue;
|
|
1406
|
+
}
|
|
1407
|
+
|
|
1408
|
+
const wrappedArgument = current.arguments[entry.parameterIndex];
|
|
1409
|
+
if (!wrappedArgument) {
|
|
1410
|
+
continue;
|
|
1411
|
+
}
|
|
1412
|
+
|
|
1413
|
+
const restPath = path.slice(entry.recoveryPath.length);
|
|
1414
|
+
const family = getFamilyAtRecoveryPathWithBindings(
|
|
1415
|
+
context,
|
|
1416
|
+
wrappedArgument,
|
|
1417
|
+
restPath,
|
|
1418
|
+
spec,
|
|
1419
|
+
seenSymbols,
|
|
1420
|
+
bindings,
|
|
1421
|
+
);
|
|
1422
|
+
if (family) {
|
|
1423
|
+
return family;
|
|
1424
|
+
}
|
|
1425
|
+
}
|
|
1426
|
+
|
|
1427
|
+
return undefined;
|
|
1428
|
+
}
|
|
1429
|
+
|
|
1430
|
+
if (path.length > 0) {
|
|
1431
|
+
return undefined;
|
|
1432
|
+
}
|
|
1433
|
+
|
|
1434
|
+
return getSupportedSummaryFamily(summary, spec);
|
|
1435
|
+
}
|
|
1436
|
+
|
|
1437
|
+
function getObjectLiteralCarriedFamilyAtPathWithBindings<Family extends ExportedNonOrdinaryFamily>(
|
|
1438
|
+
context: AnalysisContext,
|
|
1439
|
+
objectLiteral: ts.ObjectLiteralExpression,
|
|
1440
|
+
path: readonly RecoveryPathSegment[],
|
|
1441
|
+
spec: NonOrdinaryRecoverySpec<Family>,
|
|
1442
|
+
seenSymbols: Set<ts.Symbol>,
|
|
1443
|
+
bindings: ParameterBindings,
|
|
1444
|
+
): Family | undefined {
|
|
1445
|
+
const [segment, ...restPath] = path;
|
|
1446
|
+
|
|
1447
|
+
if (segment) {
|
|
1448
|
+
if (segment.kind !== 'property') {
|
|
1449
|
+
return undefined;
|
|
1450
|
+
}
|
|
1451
|
+
|
|
1452
|
+
return getObjectLiteralPropertyFamilyAtPathWithBindings(
|
|
1453
|
+
context,
|
|
1454
|
+
objectLiteral,
|
|
1455
|
+
segment.name,
|
|
1456
|
+
restPath,
|
|
1457
|
+
spec,
|
|
1458
|
+
seenSymbols,
|
|
1459
|
+
bindings,
|
|
1460
|
+
);
|
|
1461
|
+
}
|
|
1462
|
+
|
|
1463
|
+
for (const property of objectLiteral.properties) {
|
|
1464
|
+
if (ts.isPropertyAssignment(property)) {
|
|
1465
|
+
const carriedFamily = getCarriedFamilyAtRecoveryPathWithBindings(
|
|
1466
|
+
context,
|
|
1467
|
+
property.initializer,
|
|
1468
|
+
[],
|
|
1469
|
+
spec,
|
|
1470
|
+
seenSymbols,
|
|
1471
|
+
bindings,
|
|
1472
|
+
);
|
|
1473
|
+
if (carriedFamily) {
|
|
1474
|
+
return carriedFamily;
|
|
1475
|
+
}
|
|
1476
|
+
continue;
|
|
1477
|
+
}
|
|
1478
|
+
|
|
1479
|
+
if (ts.isShorthandPropertyAssignment(property)) {
|
|
1480
|
+
const valueSymbol = context.checker.getShorthandAssignmentValueSymbol(property);
|
|
1481
|
+
if (!valueSymbol) {
|
|
1482
|
+
continue;
|
|
1483
|
+
}
|
|
1484
|
+
|
|
1485
|
+
const boundExpression = bindings.get(valueSymbol);
|
|
1486
|
+
const carriedFamily = boundExpression
|
|
1487
|
+
? getCarriedFamilyAtRecoveryPathWithBindings(
|
|
1488
|
+
context,
|
|
1489
|
+
boundExpression,
|
|
1490
|
+
[],
|
|
1491
|
+
spec,
|
|
1492
|
+
seenSymbols,
|
|
1493
|
+
bindings,
|
|
1494
|
+
)
|
|
1495
|
+
: getAliasedKnownCarriedNonOrdinaryFamily(
|
|
1496
|
+
context,
|
|
1497
|
+
valueSymbol,
|
|
1498
|
+
[],
|
|
1499
|
+
spec,
|
|
1500
|
+
seenSymbols,
|
|
1501
|
+
);
|
|
1502
|
+
if (carriedFamily) {
|
|
1503
|
+
return carriedFamily;
|
|
1504
|
+
}
|
|
1505
|
+
}
|
|
1506
|
+
}
|
|
1507
|
+
|
|
1508
|
+
return undefined;
|
|
1509
|
+
}
|
|
1510
|
+
|
|
1511
|
+
function getArrayLiteralCarriedFamilyAtPathWithBindings<Family extends ExportedNonOrdinaryFamily>(
|
|
1512
|
+
context: AnalysisContext,
|
|
1513
|
+
arrayLiteral: ts.ArrayLiteralExpression,
|
|
1514
|
+
path: readonly RecoveryPathSegment[],
|
|
1515
|
+
spec: NonOrdinaryRecoverySpec<Family>,
|
|
1516
|
+
seenSymbols: Set<ts.Symbol>,
|
|
1517
|
+
bindings: ParameterBindings,
|
|
1518
|
+
): Family | undefined {
|
|
1519
|
+
const [segment, ...restPath] = path;
|
|
1520
|
+
|
|
1521
|
+
if (segment) {
|
|
1522
|
+
if (segment.kind !== 'index') {
|
|
1523
|
+
return undefined;
|
|
1524
|
+
}
|
|
1525
|
+
|
|
1526
|
+
const element = getArrayLiteralElementValue(arrayLiteral, segment.index);
|
|
1527
|
+
return element
|
|
1528
|
+
? getCarriedFamilyAtRecoveryPathWithBindings(
|
|
1529
|
+
context,
|
|
1530
|
+
element,
|
|
1531
|
+
restPath,
|
|
1532
|
+
spec,
|
|
1533
|
+
seenSymbols,
|
|
1534
|
+
bindings,
|
|
1535
|
+
)
|
|
1536
|
+
: undefined;
|
|
1537
|
+
}
|
|
1538
|
+
|
|
1539
|
+
for (const element of arrayLiteral.elements) {
|
|
1540
|
+
if (!ts.isExpression(element)) {
|
|
1541
|
+
continue;
|
|
1542
|
+
}
|
|
1543
|
+
|
|
1544
|
+
const carriedFamily = getCarriedFamilyAtRecoveryPathWithBindings(
|
|
1545
|
+
context,
|
|
1546
|
+
element,
|
|
1547
|
+
[],
|
|
1548
|
+
spec,
|
|
1549
|
+
seenSymbols,
|
|
1550
|
+
bindings,
|
|
1551
|
+
);
|
|
1552
|
+
if (carriedFamily) {
|
|
1553
|
+
return carriedFamily;
|
|
1554
|
+
}
|
|
1555
|
+
}
|
|
1556
|
+
|
|
1557
|
+
return undefined;
|
|
1558
|
+
}
|
|
1559
|
+
|
|
1560
|
+
function getPromiseCombinatorCarriedFamilyAtPathWithBindings<
|
|
1561
|
+
Family extends ExportedNonOrdinaryFamily,
|
|
1562
|
+
>(
|
|
1563
|
+
context: AnalysisContext,
|
|
1564
|
+
callExpression: ts.CallExpression,
|
|
1565
|
+
path: readonly RecoveryPathSegment[],
|
|
1566
|
+
spec: NonOrdinaryRecoverySpec<Family>,
|
|
1567
|
+
seenSymbols: Set<ts.Symbol>,
|
|
1568
|
+
bindings: ParameterBindings,
|
|
1569
|
+
): Family | undefined {
|
|
1570
|
+
const methodName = getPromiseStaticMethodName(context, callExpression);
|
|
1571
|
+
if (
|
|
1572
|
+
methodName !== 'all' &&
|
|
1573
|
+
methodName !== 'allSettled' &&
|
|
1574
|
+
methodName !== 'any' &&
|
|
1575
|
+
methodName !== 'race'
|
|
1576
|
+
) {
|
|
1577
|
+
return undefined;
|
|
1578
|
+
}
|
|
1579
|
+
|
|
1580
|
+
const inputs = getPromiseCombinatorInputs(context, callExpression, bindings, seenSymbols);
|
|
1581
|
+
if (!inputs) {
|
|
1582
|
+
return undefined;
|
|
1583
|
+
}
|
|
1584
|
+
|
|
1585
|
+
if (methodName === 'all') {
|
|
1586
|
+
if (path.length === 0) {
|
|
1587
|
+
for (const inputExpression of inputs) {
|
|
1588
|
+
const carriedFamily = getCarriedFamilyAtRecoveryPathWithBindings(
|
|
1589
|
+
context,
|
|
1590
|
+
inputExpression,
|
|
1591
|
+
[],
|
|
1592
|
+
spec,
|
|
1593
|
+
seenSymbols,
|
|
1594
|
+
bindings,
|
|
1595
|
+
);
|
|
1596
|
+
if (carriedFamily) {
|
|
1597
|
+
return carriedFamily;
|
|
1598
|
+
}
|
|
1599
|
+
}
|
|
1600
|
+
return undefined;
|
|
1601
|
+
}
|
|
1602
|
+
|
|
1603
|
+
const [segment, ...restPath] = path;
|
|
1604
|
+
if (!segment || segment.kind !== 'index') {
|
|
1605
|
+
return undefined;
|
|
1606
|
+
}
|
|
1607
|
+
|
|
1608
|
+
const inputExpression = inputs[segment.index];
|
|
1609
|
+
return inputExpression
|
|
1610
|
+
? getCarriedFamilyAtRecoveryPathWithBindings(
|
|
1611
|
+
context,
|
|
1612
|
+
inputExpression,
|
|
1613
|
+
restPath,
|
|
1614
|
+
spec,
|
|
1615
|
+
seenSymbols,
|
|
1616
|
+
bindings,
|
|
1617
|
+
)
|
|
1618
|
+
: undefined;
|
|
1619
|
+
}
|
|
1620
|
+
|
|
1621
|
+
if (methodName === 'allSettled') {
|
|
1622
|
+
if (path.length === 0) {
|
|
1623
|
+
for (const inputExpression of inputs) {
|
|
1624
|
+
const carriedFamily = getCarriedFamilyAtRecoveryPathWithBindings(
|
|
1625
|
+
context,
|
|
1626
|
+
inputExpression,
|
|
1627
|
+
[],
|
|
1628
|
+
spec,
|
|
1629
|
+
seenSymbols,
|
|
1630
|
+
bindings,
|
|
1631
|
+
);
|
|
1632
|
+
if (carriedFamily) {
|
|
1633
|
+
return carriedFamily;
|
|
1634
|
+
}
|
|
1635
|
+
}
|
|
1636
|
+
return undefined;
|
|
1637
|
+
}
|
|
1638
|
+
|
|
1639
|
+
const [indexSegment, valueSegment, ...restPath] = path;
|
|
1640
|
+
if (
|
|
1641
|
+
!indexSegment ||
|
|
1642
|
+
indexSegment.kind !== 'index' ||
|
|
1643
|
+
!valueSegment ||
|
|
1644
|
+
valueSegment.kind !== 'property' ||
|
|
1645
|
+
valueSegment.name !== 'value'
|
|
1646
|
+
) {
|
|
1647
|
+
return undefined;
|
|
1648
|
+
}
|
|
1649
|
+
|
|
1650
|
+
const inputExpression = inputs[indexSegment.index];
|
|
1651
|
+
return inputExpression
|
|
1652
|
+
? getCarriedFamilyAtRecoveryPathWithBindings(
|
|
1653
|
+
context,
|
|
1654
|
+
inputExpression,
|
|
1655
|
+
restPath,
|
|
1656
|
+
spec,
|
|
1657
|
+
seenSymbols,
|
|
1658
|
+
bindings,
|
|
1659
|
+
)
|
|
1660
|
+
: undefined;
|
|
1661
|
+
}
|
|
1662
|
+
|
|
1663
|
+
for (const inputExpression of inputs) {
|
|
1664
|
+
const carriedFamily = getCarriedFamilyAtRecoveryPathWithBindings(
|
|
1665
|
+
context,
|
|
1666
|
+
inputExpression,
|
|
1667
|
+
path,
|
|
1668
|
+
spec,
|
|
1669
|
+
seenSymbols,
|
|
1670
|
+
bindings,
|
|
1671
|
+
);
|
|
1672
|
+
if (carriedFamily) {
|
|
1673
|
+
return carriedFamily;
|
|
1674
|
+
}
|
|
1675
|
+
}
|
|
1676
|
+
|
|
1677
|
+
return undefined;
|
|
1678
|
+
}
|
|
1679
|
+
|
|
1680
|
+
function getFreshArrayExtractionCarriedFamilyAtPathWithBindings<
|
|
1681
|
+
Family extends ExportedNonOrdinaryFamily,
|
|
1682
|
+
>(
|
|
1683
|
+
context: AnalysisContext,
|
|
1684
|
+
callExpression: ts.CallExpression,
|
|
1685
|
+
path: readonly RecoveryPathSegment[],
|
|
1686
|
+
spec: NonOrdinaryRecoverySpec<Family>,
|
|
1687
|
+
seenSymbols: Set<ts.Symbol>,
|
|
1688
|
+
bindings: ParameterBindings,
|
|
1689
|
+
): Family | undefined {
|
|
1690
|
+
const methodName = getFreshArrayExtractionMethodName(callExpression);
|
|
1691
|
+
if (!methodName) {
|
|
1692
|
+
return undefined;
|
|
1693
|
+
}
|
|
1694
|
+
|
|
1695
|
+
const inputs = getFreshArrayMethodInputs(context, callExpression, bindings, seenSymbols);
|
|
1696
|
+
if (!inputs) {
|
|
1697
|
+
return undefined;
|
|
1698
|
+
}
|
|
1699
|
+
|
|
1700
|
+
switch (methodName) {
|
|
1701
|
+
case 'at': {
|
|
1702
|
+
const index = getFreshArrayAtIndex(callExpression, inputs.length);
|
|
1703
|
+
if (index === undefined) {
|
|
1704
|
+
return undefined;
|
|
1705
|
+
}
|
|
1706
|
+
|
|
1707
|
+
const inputExpression = inputs[index];
|
|
1708
|
+
return inputExpression
|
|
1709
|
+
? getCarriedFamilyAtRecoveryPathWithBindings(
|
|
1710
|
+
context,
|
|
1711
|
+
inputExpression,
|
|
1712
|
+
path,
|
|
1713
|
+
spec,
|
|
1714
|
+
seenSymbols,
|
|
1715
|
+
bindings,
|
|
1716
|
+
)
|
|
1717
|
+
: undefined;
|
|
1718
|
+
}
|
|
1719
|
+
case 'find':
|
|
1720
|
+
for (const inputExpression of inputs) {
|
|
1721
|
+
const family = getCarriedFamilyAtRecoveryPathWithBindings(
|
|
1722
|
+
context,
|
|
1723
|
+
inputExpression,
|
|
1724
|
+
path,
|
|
1725
|
+
spec,
|
|
1726
|
+
seenSymbols,
|
|
1727
|
+
bindings,
|
|
1728
|
+
);
|
|
1729
|
+
if (family) {
|
|
1730
|
+
return family;
|
|
1731
|
+
}
|
|
1732
|
+
}
|
|
1733
|
+
return undefined;
|
|
1734
|
+
case 'filter': {
|
|
1735
|
+
if (path.length === 0) {
|
|
1736
|
+
for (const inputExpression of inputs) {
|
|
1737
|
+
const family = getCarriedFamilyAtRecoveryPathWithBindings(
|
|
1738
|
+
context,
|
|
1739
|
+
inputExpression,
|
|
1740
|
+
[],
|
|
1741
|
+
spec,
|
|
1742
|
+
seenSymbols,
|
|
1743
|
+
bindings,
|
|
1744
|
+
);
|
|
1745
|
+
if (family) {
|
|
1746
|
+
return family;
|
|
1747
|
+
}
|
|
1748
|
+
}
|
|
1749
|
+
return undefined;
|
|
1750
|
+
}
|
|
1751
|
+
|
|
1752
|
+
const [segment, ...restPath] = path;
|
|
1753
|
+
if (segment.kind !== 'index') {
|
|
1754
|
+
return undefined;
|
|
1755
|
+
}
|
|
1756
|
+
|
|
1757
|
+
for (const inputExpression of inputs) {
|
|
1758
|
+
const family = getCarriedFamilyAtRecoveryPathWithBindings(
|
|
1759
|
+
context,
|
|
1760
|
+
inputExpression,
|
|
1761
|
+
restPath,
|
|
1762
|
+
spec,
|
|
1763
|
+
seenSymbols,
|
|
1764
|
+
bindings,
|
|
1765
|
+
);
|
|
1766
|
+
if (family) {
|
|
1767
|
+
return family;
|
|
1768
|
+
}
|
|
1769
|
+
}
|
|
1770
|
+
return undefined;
|
|
1771
|
+
}
|
|
1772
|
+
case 'flatMap': {
|
|
1773
|
+
const flatMapReturn = getFreshArrayFlatMapReturnInfo(context, callExpression);
|
|
1774
|
+
if (!flatMapReturn) {
|
|
1775
|
+
return undefined;
|
|
1776
|
+
}
|
|
1777
|
+
|
|
1778
|
+
const candidatePaths = path.length === 0 ? [[]] : getFlatMapElementCandidatePaths(path);
|
|
1779
|
+
if (!candidatePaths) {
|
|
1780
|
+
return undefined;
|
|
1781
|
+
}
|
|
1782
|
+
|
|
1783
|
+
for (const inputExpression of inputs) {
|
|
1784
|
+
const callbackBindings = mergeParameterBindings(
|
|
1785
|
+
bindings,
|
|
1786
|
+
createParameterBindings(
|
|
1787
|
+
context,
|
|
1788
|
+
flatMapReturn.callback,
|
|
1789
|
+
[inputExpression],
|
|
1790
|
+
bindings,
|
|
1791
|
+
),
|
|
1792
|
+
);
|
|
1793
|
+
for (const candidatePath of candidatePaths) {
|
|
1794
|
+
const family = getCarriedFamilyAtRecoveryPathWithBindings(
|
|
1795
|
+
context,
|
|
1796
|
+
flatMapReturn.returnExpression,
|
|
1797
|
+
candidatePath,
|
|
1798
|
+
spec,
|
|
1799
|
+
seenSymbols,
|
|
1800
|
+
callbackBindings,
|
|
1801
|
+
);
|
|
1802
|
+
if (family) {
|
|
1803
|
+
return family;
|
|
1804
|
+
}
|
|
1805
|
+
}
|
|
1806
|
+
}
|
|
1807
|
+
return undefined;
|
|
1808
|
+
}
|
|
1809
|
+
}
|
|
1810
|
+
}
|
|
1811
|
+
|
|
1812
|
+
function getAliasedKnownCarriedNonOrdinaryFamily<Family extends ExportedNonOrdinaryFamily>(
|
|
1813
|
+
context: AnalysisContext,
|
|
1814
|
+
symbol: ts.Symbol,
|
|
1815
|
+
path: readonly RecoveryPathSegment[],
|
|
1816
|
+
spec: NonOrdinaryRecoverySpec<Family>,
|
|
1817
|
+
seenSymbols: Set<ts.Symbol>,
|
|
1818
|
+
): Family | undefined {
|
|
1819
|
+
if (seenSymbols.has(symbol)) {
|
|
1820
|
+
return undefined;
|
|
1821
|
+
}
|
|
1822
|
+
seenSymbols.add(symbol);
|
|
1823
|
+
|
|
1824
|
+
const summary = context.exportSummaries.get(symbol);
|
|
1825
|
+
if (summary) {
|
|
1826
|
+
if (path.length === 0) {
|
|
1827
|
+
return summary.kind === 'value' ? getSupportedSummaryFamily(summary, spec) : undefined;
|
|
1828
|
+
}
|
|
1829
|
+
|
|
1830
|
+
return undefined;
|
|
1831
|
+
}
|
|
1832
|
+
|
|
1833
|
+
for (const declaration of symbol.getDeclarations() ?? []) {
|
|
1834
|
+
if (
|
|
1835
|
+
ts.isVariableDeclaration(declaration) &&
|
|
1836
|
+
isConstVariableDeclaration(declaration) &&
|
|
1837
|
+
declaration.initializer
|
|
1838
|
+
) {
|
|
1839
|
+
if (ts.isIdentifier(declaration.name)) {
|
|
1840
|
+
return getCarriedFamilyAtRecoveryPathWithBindings(
|
|
1841
|
+
context,
|
|
1842
|
+
declaration.initializer,
|
|
1843
|
+
path,
|
|
1844
|
+
spec,
|
|
1845
|
+
seenSymbols,
|
|
1846
|
+
new Map(),
|
|
1847
|
+
);
|
|
1848
|
+
}
|
|
1849
|
+
|
|
1850
|
+
const bindingPath = getBindingPatternRecoveryPath(context, declaration.name, symbol);
|
|
1851
|
+
if (bindingPath) {
|
|
1852
|
+
return getCarriedFamilyAtRecoveryPathWithBindings(
|
|
1853
|
+
context,
|
|
1854
|
+
declaration.initializer,
|
|
1855
|
+
[...bindingPath, ...path],
|
|
1856
|
+
spec,
|
|
1857
|
+
seenSymbols,
|
|
1858
|
+
new Map(),
|
|
1859
|
+
);
|
|
1860
|
+
}
|
|
1861
|
+
}
|
|
1862
|
+
|
|
1863
|
+
if (ts.isBindingElement(declaration)) {
|
|
1864
|
+
const bindingRoot = getEnclosingConstBindingInitializer(declaration);
|
|
1865
|
+
if (!bindingRoot) {
|
|
1866
|
+
continue;
|
|
1867
|
+
}
|
|
1868
|
+
|
|
1869
|
+
const bindingPath = getBindingPatternRecoveryPath(context, bindingRoot.bindingName, symbol);
|
|
1870
|
+
if (bindingPath) {
|
|
1871
|
+
return getCarriedFamilyAtRecoveryPathWithBindings(
|
|
1872
|
+
context,
|
|
1873
|
+
bindingRoot.initializer,
|
|
1874
|
+
[...bindingPath, ...path],
|
|
1875
|
+
spec,
|
|
1876
|
+
seenSymbols,
|
|
1877
|
+
new Map(),
|
|
1878
|
+
);
|
|
1879
|
+
}
|
|
1880
|
+
}
|
|
1881
|
+
}
|
|
1882
|
+
|
|
1883
|
+
return undefined;
|
|
1884
|
+
}
|
|
1885
|
+
|
|
1886
|
+
function getCarriedFamilyAtRecoveryPathWithBindings<Family extends ExportedNonOrdinaryFamily>(
|
|
1887
|
+
context: AnalysisContext,
|
|
1888
|
+
expression: ts.Expression,
|
|
1889
|
+
path: readonly RecoveryPathSegment[],
|
|
1890
|
+
spec: NonOrdinaryRecoverySpec<Family>,
|
|
1891
|
+
seenSymbols: Set<ts.Symbol>,
|
|
1892
|
+
bindings: ParameterBindings,
|
|
1893
|
+
): Family | undefined {
|
|
1894
|
+
const exactFamily = getFamilyAtRecoveryPathWithBindings(
|
|
1895
|
+
context,
|
|
1896
|
+
expression,
|
|
1897
|
+
path,
|
|
1898
|
+
spec,
|
|
1899
|
+
new Set(seenSymbols),
|
|
1900
|
+
bindings,
|
|
1901
|
+
);
|
|
1902
|
+
if (exactFamily) {
|
|
1903
|
+
return exactFamily;
|
|
1904
|
+
}
|
|
1905
|
+
|
|
1906
|
+
const resolvedExpression = resolveBoundExpression(context, expression, bindings);
|
|
1907
|
+
const accessSegment = getRecoveryAccessSegment(resolvedExpression);
|
|
1908
|
+
if (accessSegment) {
|
|
1909
|
+
return getCarriedFamilyAtRecoveryPathWithBindings(
|
|
1910
|
+
context,
|
|
1911
|
+
accessSegment.base,
|
|
1912
|
+
[accessSegment.segment, ...path],
|
|
1913
|
+
spec,
|
|
1914
|
+
seenSymbols,
|
|
1915
|
+
bindings,
|
|
1916
|
+
);
|
|
1917
|
+
}
|
|
1918
|
+
|
|
1919
|
+
const current = getUnwrappedExpression(resolvedExpression);
|
|
1920
|
+
|
|
1921
|
+
if (ts.isIdentifier(current)) {
|
|
1922
|
+
const symbol = context.checker.getSymbolAtLocation(current);
|
|
1923
|
+
return symbol
|
|
1924
|
+
? getAliasedKnownCarriedNonOrdinaryFamily(context, symbol, path, spec, seenSymbols)
|
|
1925
|
+
: undefined;
|
|
1926
|
+
}
|
|
1927
|
+
|
|
1928
|
+
if (ts.isObjectLiteralExpression(current)) {
|
|
1929
|
+
return getObjectLiteralCarriedFamilyAtPathWithBindings(
|
|
1930
|
+
context,
|
|
1931
|
+
current,
|
|
1932
|
+
path,
|
|
1933
|
+
spec,
|
|
1934
|
+
seenSymbols,
|
|
1935
|
+
bindings,
|
|
1936
|
+
);
|
|
1937
|
+
}
|
|
1938
|
+
|
|
1939
|
+
if (ts.isArrayLiteralExpression(current)) {
|
|
1940
|
+
return getArrayLiteralCarriedFamilyAtPathWithBindings(
|
|
1941
|
+
context,
|
|
1942
|
+
current,
|
|
1943
|
+
path,
|
|
1944
|
+
spec,
|
|
1945
|
+
seenSymbols,
|
|
1946
|
+
bindings,
|
|
1947
|
+
);
|
|
1948
|
+
}
|
|
1949
|
+
|
|
1950
|
+
const equivalentExpressions = getEquivalentRecoveryExpressions(resolvedExpression);
|
|
1951
|
+
if (equivalentExpressions) {
|
|
1952
|
+
for (const equivalentExpression of equivalentExpressions) {
|
|
1953
|
+
const equivalentFamily = getCarriedFamilyAtRecoveryPathWithBindings(
|
|
1954
|
+
context,
|
|
1955
|
+
equivalentExpression,
|
|
1956
|
+
path,
|
|
1957
|
+
spec,
|
|
1958
|
+
seenSymbols,
|
|
1959
|
+
bindings,
|
|
1960
|
+
);
|
|
1961
|
+
if (equivalentFamily) {
|
|
1962
|
+
return equivalentFamily;
|
|
1963
|
+
}
|
|
1964
|
+
}
|
|
1965
|
+
return undefined;
|
|
1966
|
+
}
|
|
1967
|
+
|
|
1968
|
+
if (!ts.isCallExpression(current)) {
|
|
1969
|
+
return undefined;
|
|
1970
|
+
}
|
|
1971
|
+
|
|
1972
|
+
const promiseContinuation = getPromiseRecoveryContinuation(context, current, bindings);
|
|
1973
|
+
if (promiseContinuation) {
|
|
1974
|
+
return getCarriedFamilyAtRecoveryPathWithBindings(
|
|
1975
|
+
context,
|
|
1976
|
+
promiseContinuation.expression,
|
|
1977
|
+
path,
|
|
1978
|
+
spec,
|
|
1979
|
+
seenSymbols,
|
|
1980
|
+
promiseContinuation.bindings,
|
|
1981
|
+
);
|
|
1982
|
+
}
|
|
1983
|
+
|
|
1984
|
+
const promiseCombinatorFamily = getPromiseCombinatorCarriedFamilyAtPathWithBindings(
|
|
1985
|
+
context,
|
|
1986
|
+
current,
|
|
1987
|
+
path,
|
|
1988
|
+
spec,
|
|
1989
|
+
seenSymbols,
|
|
1990
|
+
bindings,
|
|
1991
|
+
);
|
|
1992
|
+
if (promiseCombinatorFamily) {
|
|
1993
|
+
return promiseCombinatorFamily;
|
|
1994
|
+
}
|
|
1995
|
+
|
|
1996
|
+
const freshArrayExtractionFamily = getFreshArrayExtractionCarriedFamilyAtPathWithBindings(
|
|
1997
|
+
context,
|
|
1998
|
+
current,
|
|
1999
|
+
path,
|
|
2000
|
+
spec,
|
|
2001
|
+
seenSymbols,
|
|
2002
|
+
bindings,
|
|
2003
|
+
);
|
|
2004
|
+
if (freshArrayExtractionFamily) {
|
|
2005
|
+
return freshArrayExtractionFamily;
|
|
2006
|
+
}
|
|
2007
|
+
|
|
2008
|
+
const localDirectReturn = getDirectReturnLocalCall(context, current);
|
|
2009
|
+
if (localDirectReturn) {
|
|
2010
|
+
const localBindings = mergeParameterBindings(
|
|
2011
|
+
bindings,
|
|
2012
|
+
createParameterBindings(context, localDirectReturn.declaration, current.arguments, bindings),
|
|
2013
|
+
);
|
|
2014
|
+
return getCarriedFamilyAtRecoveryPathWithBindings(
|
|
2015
|
+
context,
|
|
2016
|
+
localDirectReturn.returnExpression,
|
|
2017
|
+
path,
|
|
2018
|
+
spec,
|
|
2019
|
+
seenSymbols,
|
|
2020
|
+
localBindings,
|
|
2021
|
+
);
|
|
2022
|
+
}
|
|
2023
|
+
|
|
2024
|
+
const calleeSymbol = getCallExpressionCalleeSymbol(context, current);
|
|
2025
|
+
if (!calleeSymbol) {
|
|
2026
|
+
return undefined;
|
|
2027
|
+
}
|
|
2028
|
+
|
|
2029
|
+
const summary = context.exportSummaries.get(calleeSymbol);
|
|
2030
|
+
if (!summary) {
|
|
2031
|
+
return undefined;
|
|
2032
|
+
}
|
|
2033
|
+
|
|
2034
|
+
if (summary.kind === 'callableReturnedParameter') {
|
|
2035
|
+
const forwardedArgument = current.arguments[summary.parameterIndex];
|
|
2036
|
+
return forwardedArgument
|
|
2037
|
+
? getCarriedFamilyAtRecoveryPathWithBindings(
|
|
2038
|
+
context,
|
|
2039
|
+
forwardedArgument,
|
|
2040
|
+
path,
|
|
2041
|
+
spec,
|
|
2042
|
+
seenSymbols,
|
|
2043
|
+
bindings,
|
|
2044
|
+
)
|
|
2045
|
+
: undefined;
|
|
2046
|
+
}
|
|
2047
|
+
|
|
2048
|
+
if (summary.kind === 'callableHelperWrapper') {
|
|
2049
|
+
for (const entry of summary.entries) {
|
|
2050
|
+
if (!doesRecoveryPathStartWith(path, entry.recoveryPath)) {
|
|
2051
|
+
continue;
|
|
2052
|
+
}
|
|
2053
|
+
|
|
2054
|
+
const wrappedArgument = current.arguments[entry.parameterIndex];
|
|
2055
|
+
if (!wrappedArgument) {
|
|
2056
|
+
continue;
|
|
2057
|
+
}
|
|
2058
|
+
|
|
2059
|
+
const restPath = path.slice(entry.recoveryPath.length);
|
|
2060
|
+
const family = getCarriedFamilyAtRecoveryPathWithBindings(
|
|
2061
|
+
context,
|
|
2062
|
+
wrappedArgument,
|
|
2063
|
+
restPath,
|
|
2064
|
+
spec,
|
|
2065
|
+
seenSymbols,
|
|
2066
|
+
bindings,
|
|
2067
|
+
);
|
|
2068
|
+
if (family) {
|
|
2069
|
+
return family;
|
|
2070
|
+
}
|
|
2071
|
+
}
|
|
2072
|
+
|
|
2073
|
+
return undefined;
|
|
2074
|
+
}
|
|
2075
|
+
|
|
2076
|
+
if (path.length === 0) {
|
|
2077
|
+
return getSupportedSummaryFamily(summary, spec);
|
|
2078
|
+
}
|
|
2079
|
+
|
|
2080
|
+
return undefined;
|
|
2081
|
+
}
|
|
2082
|
+
|
|
2083
|
+
function getSupportedSummaryFamily<Family extends ExportedNonOrdinaryFamily>(
|
|
2084
|
+
summary: ExportSummary,
|
|
2085
|
+
spec: NonOrdinaryRecoverySpec<Family>,
|
|
2086
|
+
): Family | undefined {
|
|
2087
|
+
switch (summary.kind) {
|
|
2088
|
+
case 'callableDirectReturn':
|
|
2089
|
+
case 'value':
|
|
2090
|
+
return spec.isSupportedFamily(summary.fact.family) ? summary.fact.family : undefined;
|
|
2091
|
+
case 'callableHelperWrapper':
|
|
2092
|
+
case 'callableReturnedParameter':
|
|
2093
|
+
return undefined;
|
|
2094
|
+
default: {
|
|
2095
|
+
const exhaustiveCheck: never = summary;
|
|
2096
|
+
return exhaustiveCheck;
|
|
2097
|
+
}
|
|
2098
|
+
}
|
|
2099
|
+
}
|
|
2100
|
+
|
|
2101
|
+
function getAliasedKnownNonOrdinaryFamily<Family extends ExportedNonOrdinaryFamily>(
|
|
2102
|
+
context: AnalysisContext,
|
|
2103
|
+
symbol: ts.Symbol,
|
|
2104
|
+
path: readonly RecoveryPathSegment[],
|
|
2105
|
+
spec: NonOrdinaryRecoverySpec<Family>,
|
|
2106
|
+
seenSymbols: Set<ts.Symbol>,
|
|
2107
|
+
): Family | undefined {
|
|
2108
|
+
if (seenSymbols.has(symbol)) {
|
|
2109
|
+
return undefined;
|
|
2110
|
+
}
|
|
2111
|
+
seenSymbols.add(symbol);
|
|
2112
|
+
|
|
2113
|
+
const summary = context.exportSummaries.get(symbol);
|
|
2114
|
+
if (summary) {
|
|
2115
|
+
return path.length === 0 && summary.kind === 'value'
|
|
2116
|
+
? getSupportedSummaryFamily(summary, spec)
|
|
2117
|
+
: undefined;
|
|
2118
|
+
}
|
|
2119
|
+
|
|
2120
|
+
for (const declaration of symbol.getDeclarations() ?? []) {
|
|
2121
|
+
if (
|
|
2122
|
+
ts.isVariableDeclaration(declaration) &&
|
|
2123
|
+
isConstVariableDeclaration(declaration) &&
|
|
2124
|
+
declaration.initializer
|
|
2125
|
+
) {
|
|
2126
|
+
if (ts.isIdentifier(declaration.name)) {
|
|
2127
|
+
return getFamilyAtRecoveryPathWithBindings(
|
|
2128
|
+
context,
|
|
2129
|
+
declaration.initializer,
|
|
2130
|
+
path,
|
|
2131
|
+
spec,
|
|
2132
|
+
seenSymbols,
|
|
2133
|
+
new Map(),
|
|
2134
|
+
);
|
|
2135
|
+
}
|
|
2136
|
+
|
|
2137
|
+
const bindingPath = getBindingPatternRecoveryPath(context, declaration.name, symbol);
|
|
2138
|
+
if (bindingPath) {
|
|
2139
|
+
return getFamilyAtRecoveryPathWithBindings(
|
|
2140
|
+
context,
|
|
2141
|
+
declaration.initializer,
|
|
2142
|
+
[...bindingPath, ...path],
|
|
2143
|
+
spec,
|
|
2144
|
+
seenSymbols,
|
|
2145
|
+
new Map(),
|
|
2146
|
+
);
|
|
2147
|
+
}
|
|
2148
|
+
}
|
|
2149
|
+
|
|
2150
|
+
if (ts.isBindingElement(declaration)) {
|
|
2151
|
+
const bindingRoot = getEnclosingConstBindingInitializer(declaration);
|
|
2152
|
+
if (!bindingRoot) {
|
|
2153
|
+
continue;
|
|
2154
|
+
}
|
|
2155
|
+
|
|
2156
|
+
const bindingPath = getBindingPatternRecoveryPath(context, bindingRoot.bindingName, symbol);
|
|
2157
|
+
if (bindingPath) {
|
|
2158
|
+
return getFamilyAtRecoveryPathWithBindings(
|
|
2159
|
+
context,
|
|
2160
|
+
bindingRoot.initializer,
|
|
2161
|
+
[...bindingPath, ...path],
|
|
2162
|
+
spec,
|
|
2163
|
+
seenSymbols,
|
|
2164
|
+
new Map(),
|
|
2165
|
+
);
|
|
2166
|
+
}
|
|
2167
|
+
}
|
|
2168
|
+
}
|
|
2169
|
+
|
|
2170
|
+
return undefined;
|
|
2171
|
+
}
|
|
2172
|
+
|
|
2173
|
+
export function getKnownRecoveredNonOrdinaryFamily<Family extends ExportedNonOrdinaryFamily>(
|
|
2174
|
+
context: AnalysisContext,
|
|
2175
|
+
expression: ts.Expression,
|
|
2176
|
+
spec: NonOrdinaryRecoverySpec<Family>,
|
|
2177
|
+
seenSymbols = new Set<ts.Symbol>(),
|
|
2178
|
+
): Family | undefined {
|
|
2179
|
+
if (seenSymbols.size === 0) {
|
|
2180
|
+
let computedFamily: Family | undefined;
|
|
2181
|
+
const recovery = context.facts.getNonOrdinaryRecovery(
|
|
2182
|
+
expression,
|
|
2183
|
+
spec.getDirectFamily(context, expression) ?? inferRecoveryFactFamily(spec),
|
|
2184
|
+
() => ({
|
|
2185
|
+
family: computedFamily = getKnownRecoveredNonOrdinaryFamilyInternal(
|
|
2186
|
+
context,
|
|
2187
|
+
expression,
|
|
2188
|
+
spec,
|
|
2189
|
+
new Set<ts.Symbol>(),
|
|
2190
|
+
),
|
|
2191
|
+
}),
|
|
2192
|
+
);
|
|
2193
|
+
|
|
2194
|
+
return computedFamily ?? (recovery.family as Family | undefined);
|
|
2195
|
+
}
|
|
2196
|
+
|
|
2197
|
+
return getKnownRecoveredNonOrdinaryFamilyInternal(context, expression, spec, seenSymbols);
|
|
2198
|
+
}
|
|
2199
|
+
|
|
2200
|
+
export function getKnownCarriedNonOrdinaryFamily<Family extends ExportedNonOrdinaryFamily>(
|
|
2201
|
+
context: AnalysisContext,
|
|
2202
|
+
expression: ts.Expression,
|
|
2203
|
+
spec: NonOrdinaryRecoverySpec<Family>,
|
|
2204
|
+
seenSymbols = new Set<ts.Symbol>(),
|
|
2205
|
+
): Family | undefined {
|
|
2206
|
+
return getCarriedFamilyAtRecoveryPathWithBindings(
|
|
2207
|
+
context,
|
|
2208
|
+
expression,
|
|
2209
|
+
[],
|
|
2210
|
+
spec,
|
|
2211
|
+
seenSymbols,
|
|
2212
|
+
new Map(),
|
|
2213
|
+
);
|
|
2214
|
+
}
|
|
2215
|
+
|
|
2216
|
+
function getKnownRecoveredNonOrdinaryFamilyInternal<Family extends ExportedNonOrdinaryFamily>(
|
|
2217
|
+
context: AnalysisContext,
|
|
2218
|
+
expression: ts.Expression,
|
|
2219
|
+
spec: NonOrdinaryRecoverySpec<Family>,
|
|
2220
|
+
seenSymbols: Set<ts.Symbol>,
|
|
2221
|
+
): Family | undefined {
|
|
2222
|
+
return getFamilyAtRecoveryPathWithBindings(
|
|
2223
|
+
context,
|
|
2224
|
+
expression,
|
|
2225
|
+
[],
|
|
2226
|
+
spec,
|
|
2227
|
+
seenSymbols,
|
|
2228
|
+
new Map(),
|
|
2229
|
+
);
|
|
2230
|
+
}
|
|
2231
|
+
|
|
2232
|
+
function inferRecoveryFactFamily<Family extends ExportedNonOrdinaryFamily>(
|
|
2233
|
+
spec: NonOrdinaryRecoverySpec<Family>,
|
|
2234
|
+
): Family {
|
|
2235
|
+
const knownFamilies: readonly ExportedNonOrdinaryFamily[] = [
|
|
2236
|
+
'moduleNamespace',
|
|
2237
|
+
'nullPrototype',
|
|
2238
|
+
];
|
|
2239
|
+
|
|
2240
|
+
for (const family of knownFamilies) {
|
|
2241
|
+
if (spec.isSupportedFamily(family)) {
|
|
2242
|
+
return family;
|
|
2243
|
+
}
|
|
2244
|
+
}
|
|
2245
|
+
|
|
2246
|
+
throw new Error('Unsupported non-ordinary recovery spec family');
|
|
2247
|
+
}
|
|
2248
|
+
|
|
2249
|
+
export function collectLocalFunctionLikes(context: AnalysisContext): LocalFunctionLikeWithBody[] {
|
|
2250
|
+
const functionLikes: LocalFunctionLikeWithBody[] = [];
|
|
2251
|
+
|
|
2252
|
+
function visit(node: ts.Node): void {
|
|
2253
|
+
if (isLocalFunctionLikeWithBody(node)) {
|
|
2254
|
+
functionLikes.push(node);
|
|
2255
|
+
}
|
|
2256
|
+
ts.forEachChild(node, visit);
|
|
2257
|
+
}
|
|
2258
|
+
|
|
2259
|
+
context.forEachSourceFile((sourceFile) => visit(sourceFile));
|
|
2260
|
+
return functionLikes;
|
|
2261
|
+
}
|
|
2262
|
+
|
|
2263
|
+
export function collectExportedSymbolsBySourceFile(
|
|
2264
|
+
context: AnalysisContext,
|
|
2265
|
+
): Map<ts.SourceFile, Set<ts.Symbol>> {
|
|
2266
|
+
const exportedSymbolsBySourceFile = new Map<ts.SourceFile, Set<ts.Symbol>>();
|
|
2267
|
+
|
|
2268
|
+
context.forEachSourceFile((sourceFile) => {
|
|
2269
|
+
const moduleSymbol = context.checker.getSymbolAtLocation(sourceFile);
|
|
2270
|
+
if (!moduleSymbol) {
|
|
2271
|
+
return;
|
|
2272
|
+
}
|
|
2273
|
+
|
|
2274
|
+
const exportedSymbols = new Set<ts.Symbol>();
|
|
2275
|
+
for (const exportSymbol of context.checker.getExportsOfModule(moduleSymbol)) {
|
|
2276
|
+
exportedSymbols.add(context.exportSummaries.canonicalizeSymbol(exportSymbol));
|
|
2277
|
+
}
|
|
2278
|
+
exportedSymbolsBySourceFile.set(sourceFile, exportedSymbols);
|
|
2279
|
+
});
|
|
2280
|
+
|
|
2281
|
+
return exportedSymbolsBySourceFile;
|
|
2282
|
+
}
|
|
2283
|
+
|
|
2284
|
+
export function populateDirectExportValueSummaries<Family extends ExportedNonOrdinaryFamily>(
|
|
2285
|
+
context: AnalysisContext,
|
|
2286
|
+
exportedSymbolsBySourceFile: Map<ts.SourceFile, Set<ts.Symbol>>,
|
|
2287
|
+
spec: NonOrdinaryRecoverySpec<Family>,
|
|
2288
|
+
): void {
|
|
2289
|
+
context.forEachSourceFile((sourceFile) => {
|
|
2290
|
+
const exportedSymbols = exportedSymbolsBySourceFile.get(sourceFile);
|
|
2291
|
+
if (!exportedSymbols) {
|
|
2292
|
+
return;
|
|
2293
|
+
}
|
|
2294
|
+
|
|
2295
|
+
context.traverse(sourceFile, (node) => {
|
|
2296
|
+
let symbol: ts.Symbol | undefined;
|
|
2297
|
+
let initializer: ts.Expression | undefined;
|
|
2298
|
+
|
|
2299
|
+
if (
|
|
2300
|
+
ts.isVariableDeclaration(node) &&
|
|
2301
|
+
isConstVariableDeclaration(node) &&
|
|
2302
|
+
node.initializer &&
|
|
2303
|
+
ts.isIdentifier(node.name)
|
|
2304
|
+
) {
|
|
2305
|
+
symbol = context.checker.getSymbolAtLocation(node.name);
|
|
2306
|
+
initializer = node.initializer;
|
|
2307
|
+
} else if (ts.isExportAssignment(node) && !node.isExportEquals) {
|
|
2308
|
+
symbol = getDefaultExportSymbol(context, sourceFile);
|
|
2309
|
+
initializer = node.expression;
|
|
2310
|
+
} else {
|
|
2311
|
+
return;
|
|
2312
|
+
}
|
|
2313
|
+
|
|
2314
|
+
if (!symbol || !initializer) {
|
|
2315
|
+
return;
|
|
2316
|
+
}
|
|
2317
|
+
|
|
2318
|
+
if (!exportedSymbols.has(context.exportSummaries.canonicalizeSymbol(symbol))) {
|
|
2319
|
+
return;
|
|
2320
|
+
}
|
|
2321
|
+
|
|
2322
|
+
const family = spec.getDirectFamily(context, initializer);
|
|
2323
|
+
if (!family) {
|
|
2324
|
+
return;
|
|
2325
|
+
}
|
|
2326
|
+
|
|
2327
|
+
context.exportSummaries.set(symbol, {
|
|
2328
|
+
kind: 'value',
|
|
2329
|
+
fact: { family },
|
|
2330
|
+
});
|
|
2331
|
+
});
|
|
2332
|
+
});
|
|
2333
|
+
}
|
|
2334
|
+
|
|
2335
|
+
export function populateFunctionLikeNonOrdinarySummaries<
|
|
2336
|
+
Family extends ExportedNonOrdinaryFamily,
|
|
2337
|
+
>(
|
|
2338
|
+
context: AnalysisContext,
|
|
2339
|
+
exportedSymbolsBySourceFile: Map<ts.SourceFile, Set<ts.Symbol>>,
|
|
2340
|
+
spec: NonOrdinaryRecoverySpec<Family>,
|
|
2341
|
+
): void {
|
|
2342
|
+
for (const functionLike of collectLocalFunctionLikes(context)) {
|
|
2343
|
+
const symbol = getFunctionLikeSummarySymbol(context, functionLike);
|
|
2344
|
+
if (!symbol) {
|
|
2345
|
+
continue;
|
|
2346
|
+
}
|
|
2347
|
+
|
|
2348
|
+
const exportedSymbols = exportedSymbolsBySourceFile.get(functionLike.getSourceFile());
|
|
2349
|
+
if (!exportedSymbols?.has(context.exportSummaries.canonicalizeSymbol(symbol))) {
|
|
2350
|
+
continue;
|
|
2351
|
+
}
|
|
2352
|
+
|
|
2353
|
+
const returnExpression = getDirectReturnExpression(functionLike);
|
|
2354
|
+
const family = returnExpression
|
|
2355
|
+
? (
|
|
2356
|
+
spec.getDirectFamily(context, returnExpression) ??
|
|
2357
|
+
getKnownRecoveredNonOrdinaryFamily(context, returnExpression, spec)
|
|
2358
|
+
)
|
|
2359
|
+
: undefined;
|
|
2360
|
+
if (family) {
|
|
2361
|
+
context.exportSummaries.set(symbol, {
|
|
2362
|
+
kind: 'callableDirectReturn',
|
|
2363
|
+
fact: { family },
|
|
2364
|
+
});
|
|
2365
|
+
continue;
|
|
2366
|
+
}
|
|
2367
|
+
|
|
2368
|
+
const returnedParameterIndex = summarizeReturnedParameter(context, functionLike);
|
|
2369
|
+
if (returnedParameterIndex !== undefined) {
|
|
2370
|
+
context.exportSummaries.set(symbol, {
|
|
2371
|
+
kind: 'callableReturnedParameter',
|
|
2372
|
+
parameterIndex: returnedParameterIndex,
|
|
2373
|
+
});
|
|
2374
|
+
continue;
|
|
2375
|
+
}
|
|
2376
|
+
|
|
2377
|
+
if (!returnExpression) {
|
|
2378
|
+
continue;
|
|
2379
|
+
}
|
|
2380
|
+
|
|
2381
|
+
const helperWrapperEntries = collectHelperWrapperEntries(context, functionLike, returnExpression);
|
|
2382
|
+
if (!helperWrapperEntries || helperWrapperEntries.length === 0) {
|
|
2383
|
+
continue;
|
|
2384
|
+
}
|
|
2385
|
+
|
|
2386
|
+
context.exportSummaries.set(symbol, {
|
|
2387
|
+
kind: 'callableHelperWrapper',
|
|
2388
|
+
entries: helperWrapperEntries,
|
|
2389
|
+
});
|
|
2390
|
+
}
|
|
2391
|
+
}
|