@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,1217 @@
|
|
|
1
|
+
import ts from 'typescript';
|
|
2
|
+
|
|
3
|
+
export interface AnnotationTextRange {
|
|
4
|
+
readonly end: number;
|
|
5
|
+
readonly start: number;
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
export interface ParsedAnnotationIdentifierValue {
|
|
9
|
+
readonly kind: 'identifier';
|
|
10
|
+
readonly name: string;
|
|
11
|
+
readonly text: string;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export interface ParsedAnnotationStringValue {
|
|
15
|
+
readonly kind: 'string';
|
|
16
|
+
readonly text: string;
|
|
17
|
+
readonly value: string;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export interface ParsedAnnotationNumberValue {
|
|
21
|
+
readonly kind: 'number';
|
|
22
|
+
readonly text: string;
|
|
23
|
+
readonly value: number;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export interface ParsedAnnotationBooleanValue {
|
|
27
|
+
readonly kind: 'boolean';
|
|
28
|
+
readonly text: string;
|
|
29
|
+
readonly value: boolean;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export interface ParsedAnnotationArrayValue {
|
|
33
|
+
readonly elements: readonly ParsedAnnotationValue[];
|
|
34
|
+
readonly kind: 'array';
|
|
35
|
+
readonly text: string;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
export interface ParsedAnnotationObjectProperty {
|
|
39
|
+
readonly name: string;
|
|
40
|
+
readonly text: string;
|
|
41
|
+
readonly value: ParsedAnnotationValue;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
export interface ParsedAnnotationObjectValue {
|
|
45
|
+
readonly kind: 'object';
|
|
46
|
+
readonly properties: readonly ParsedAnnotationObjectProperty[];
|
|
47
|
+
readonly text: string;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
export type ParsedAnnotationValue =
|
|
51
|
+
| ParsedAnnotationArrayValue
|
|
52
|
+
| ParsedAnnotationBooleanValue
|
|
53
|
+
| ParsedAnnotationIdentifierValue
|
|
54
|
+
| ParsedAnnotationNumberValue
|
|
55
|
+
| ParsedAnnotationObjectValue
|
|
56
|
+
| ParsedAnnotationStringValue;
|
|
57
|
+
|
|
58
|
+
export type ParsedAnnotationArgument =
|
|
59
|
+
| {
|
|
60
|
+
readonly kind: 'named';
|
|
61
|
+
readonly name: string;
|
|
62
|
+
readonly text: string;
|
|
63
|
+
readonly value: ParsedAnnotationValue;
|
|
64
|
+
}
|
|
65
|
+
| {
|
|
66
|
+
readonly kind: 'positional';
|
|
67
|
+
readonly text: string;
|
|
68
|
+
readonly value: ParsedAnnotationValue;
|
|
69
|
+
};
|
|
70
|
+
|
|
71
|
+
export interface ParsedAnnotationSyntax {
|
|
72
|
+
readonly arguments?: readonly ParsedAnnotationArgument[];
|
|
73
|
+
readonly argumentsText?: string;
|
|
74
|
+
readonly nameRange?: AnnotationTextRange;
|
|
75
|
+
readonly name: string;
|
|
76
|
+
readonly range?: AnnotationTextRange;
|
|
77
|
+
readonly text: string;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
export type ParsedAnnotation = ParsedAnnotationSyntax;
|
|
81
|
+
|
|
82
|
+
export interface ParsedAnnotationComment {
|
|
83
|
+
readonly annotations: readonly ParsedAnnotation[];
|
|
84
|
+
readonly kind: 'annotation';
|
|
85
|
+
readonly line: number;
|
|
86
|
+
readonly range?: AnnotationTextRange;
|
|
87
|
+
readonly text: string;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
export interface ParsedAnnotationParseError {
|
|
91
|
+
readonly kind: 'annotation-parse-error';
|
|
92
|
+
readonly line: number;
|
|
93
|
+
readonly message: string;
|
|
94
|
+
readonly text: string;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
export interface ParsedTypeScriptPragma {
|
|
98
|
+
readonly kind: 'banned-ts-pragma';
|
|
99
|
+
readonly line: number;
|
|
100
|
+
readonly text: string;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
export type ParsedAnnotationEntry =
|
|
104
|
+
| ParsedAnnotationComment
|
|
105
|
+
| ParsedAnnotationParseError
|
|
106
|
+
| ParsedTypeScriptPragma;
|
|
107
|
+
|
|
108
|
+
export interface ParsedAnnotationBlock {
|
|
109
|
+
readonly annotations: readonly ParsedAnnotation[];
|
|
110
|
+
readonly endLine: number;
|
|
111
|
+
readonly range: AnnotationTextRange;
|
|
112
|
+
readonly startLine: number;
|
|
113
|
+
readonly targetNode?: ts.Node;
|
|
114
|
+
readonly text: string;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
export interface AnnotationLookup {
|
|
118
|
+
getAttachedAnnotationBlock(node: ts.Node): ParsedAnnotationBlock | undefined;
|
|
119
|
+
getAttachedAnnotations(node: ts.Node): readonly ParsedAnnotation[];
|
|
120
|
+
getBlocks(): readonly ParsedAnnotationBlock[];
|
|
121
|
+
getEntries(): readonly ParsedAnnotationEntry[];
|
|
122
|
+
getEntriesForLine(line: number): readonly ParsedAnnotationEntry[];
|
|
123
|
+
hasAttachedAnnotation(node: ts.Node, name: string): boolean;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
const ANNOTATION_COMMENT_PATTERN = /^\/\/\s*#\[/u;
|
|
127
|
+
export const BUILTIN_DIRECTIVE_NAMES: ReadonlySet<string> = new Set([
|
|
128
|
+
'extern',
|
|
129
|
+
'interop',
|
|
130
|
+
'newtype',
|
|
131
|
+
'unsafe',
|
|
132
|
+
'value',
|
|
133
|
+
'variance',
|
|
134
|
+
]);
|
|
135
|
+
|
|
136
|
+
function isIdentifierStart(character: string | undefined): boolean {
|
|
137
|
+
return character !== undefined && /[\p{ID_Start}_$]/u.test(character);
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
function isIdentifierPart(character: string | undefined): boolean {
|
|
141
|
+
return character !== undefined && /[\p{ID_Continue}_$\u200C\u200D-]/u.test(character);
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
function isDigit(character: string | undefined): boolean {
|
|
145
|
+
return character !== undefined && /[0-9]/u.test(character);
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
function trimRange(
|
|
149
|
+
text: string,
|
|
150
|
+
start: number,
|
|
151
|
+
end: number,
|
|
152
|
+
): { end: number; start: number; text: string } {
|
|
153
|
+
let nextStart = start;
|
|
154
|
+
let nextEnd = end;
|
|
155
|
+
while (nextStart < nextEnd && /\s/u.test(text[nextStart] ?? '')) {
|
|
156
|
+
nextStart += 1;
|
|
157
|
+
}
|
|
158
|
+
while (nextEnd > nextStart && /\s/u.test(text[nextEnd - 1] ?? '')) {
|
|
159
|
+
nextEnd -= 1;
|
|
160
|
+
}
|
|
161
|
+
return {
|
|
162
|
+
end: nextEnd,
|
|
163
|
+
start: nextStart,
|
|
164
|
+
text: text.slice(nextStart, nextEnd),
|
|
165
|
+
};
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
function skipWhitespace(text: string, index: number): number {
|
|
169
|
+
let nextIndex = index;
|
|
170
|
+
while (nextIndex < text.length && /\s/u.test(text[nextIndex] ?? '')) {
|
|
171
|
+
nextIndex += 1;
|
|
172
|
+
}
|
|
173
|
+
return nextIndex;
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
function readStringLiteral(text: string, start: number): number | string {
|
|
177
|
+
const quote = text[start];
|
|
178
|
+
if (quote !== '"' && quote !== "'") {
|
|
179
|
+
return 'Expected a string literal.';
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
let index = start + 1;
|
|
183
|
+
while (index < text.length) {
|
|
184
|
+
const character = text[index];
|
|
185
|
+
if (character === '\\') {
|
|
186
|
+
index += 2;
|
|
187
|
+
continue;
|
|
188
|
+
}
|
|
189
|
+
if (character === quote) {
|
|
190
|
+
return index + 1;
|
|
191
|
+
}
|
|
192
|
+
index += 1;
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
return 'String literals in annotation arguments must terminate before the annotation closes.';
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
function parseIdentifierName(
|
|
199
|
+
text: string,
|
|
200
|
+
start: number,
|
|
201
|
+
allowDots: boolean,
|
|
202
|
+
): { end: number; name: string } | string {
|
|
203
|
+
if (!isIdentifierStart(text[start])) {
|
|
204
|
+
return 'Annotation names must use identifier-like segments such as `unsafe`, `variance`, or `_hkt_`.';
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
let index = start + 1;
|
|
208
|
+
while (isIdentifierPart(text[index])) {
|
|
209
|
+
index += 1;
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
while (allowDots && text[index] === '.') {
|
|
213
|
+
const segmentStart = index + 1;
|
|
214
|
+
if (!isIdentifierStart(text[segmentStart])) {
|
|
215
|
+
return 'Annotation names must use identifier-like dotted segments such as `layout.value`.';
|
|
216
|
+
}
|
|
217
|
+
index = segmentStart + 1;
|
|
218
|
+
while (isIdentifierPart(text[index])) {
|
|
219
|
+
index += 1;
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
return {
|
|
224
|
+
end: index,
|
|
225
|
+
name: text.slice(start, index),
|
|
226
|
+
};
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
class AnnotationValueParser {
|
|
230
|
+
#index = 0;
|
|
231
|
+
|
|
232
|
+
constructor(private readonly text: string) {}
|
|
233
|
+
|
|
234
|
+
parseArguments(): readonly ParsedAnnotationArgument[] | string {
|
|
235
|
+
const args: ParsedAnnotationArgument[] = [];
|
|
236
|
+
this.#index = skipWhitespace(this.text, this.#index);
|
|
237
|
+
if (this.#index >= this.text.length) {
|
|
238
|
+
return args;
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
while (this.#index < this.text.length) {
|
|
242
|
+
const argument = this.parseArgument();
|
|
243
|
+
if (typeof argument === 'string') {
|
|
244
|
+
return argument;
|
|
245
|
+
}
|
|
246
|
+
args.push(argument);
|
|
247
|
+
this.#index = skipWhitespace(this.text, this.#index);
|
|
248
|
+
if (this.#index >= this.text.length) {
|
|
249
|
+
return args;
|
|
250
|
+
}
|
|
251
|
+
if (this.text[this.#index] !== ',') {
|
|
252
|
+
return 'Annotation argument lists must separate items with commas.';
|
|
253
|
+
}
|
|
254
|
+
this.#index += 1;
|
|
255
|
+
this.#index = skipWhitespace(this.text, this.#index);
|
|
256
|
+
if (this.#index >= this.text.length) {
|
|
257
|
+
return 'Annotation argument lists do not allow trailing commas.';
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
return args;
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
parseValue(): ParsedAnnotationValue | string {
|
|
265
|
+
return this.parseValueAtCurrentIndex();
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
private parseArgument(): ParsedAnnotationArgument | string {
|
|
269
|
+
const start = this.#index;
|
|
270
|
+
const namedArgument = this.tryParseNamedArgument();
|
|
271
|
+
if (typeof namedArgument !== 'string' || this.#index !== start) {
|
|
272
|
+
return namedArgument;
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
const value = this.parseValueAtCurrentIndex();
|
|
276
|
+
if (typeof value === 'string') {
|
|
277
|
+
return value;
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
return {
|
|
281
|
+
kind: 'positional',
|
|
282
|
+
text: this.text.slice(start, this.#index),
|
|
283
|
+
value,
|
|
284
|
+
};
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
private parseArrayValue(): ParsedAnnotationArrayValue | string {
|
|
288
|
+
const start = this.#index;
|
|
289
|
+
if (this.text[this.#index] !== '[') {
|
|
290
|
+
return 'Expected an array literal.';
|
|
291
|
+
}
|
|
292
|
+
this.#index += 1;
|
|
293
|
+
this.#index = skipWhitespace(this.text, this.#index);
|
|
294
|
+
const elements: ParsedAnnotationValue[] = [];
|
|
295
|
+
|
|
296
|
+
if (this.text[this.#index] === ']') {
|
|
297
|
+
this.#index += 1;
|
|
298
|
+
return {
|
|
299
|
+
elements,
|
|
300
|
+
kind: 'array',
|
|
301
|
+
text: this.text.slice(start, this.#index),
|
|
302
|
+
};
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
while (this.#index < this.text.length) {
|
|
306
|
+
const value = this.parseValueAtCurrentIndex();
|
|
307
|
+
if (typeof value === 'string') {
|
|
308
|
+
return value;
|
|
309
|
+
}
|
|
310
|
+
elements.push(value);
|
|
311
|
+
this.#index = skipWhitespace(this.text, this.#index);
|
|
312
|
+
if (this.text[this.#index] === ']') {
|
|
313
|
+
this.#index += 1;
|
|
314
|
+
return {
|
|
315
|
+
elements,
|
|
316
|
+
kind: 'array',
|
|
317
|
+
text: this.text.slice(start, this.#index),
|
|
318
|
+
};
|
|
319
|
+
}
|
|
320
|
+
if (this.text[this.#index] !== ',') {
|
|
321
|
+
return 'Array literals in annotation arguments must separate elements with commas.';
|
|
322
|
+
}
|
|
323
|
+
this.#index += 1;
|
|
324
|
+
this.#index = skipWhitespace(this.text, this.#index);
|
|
325
|
+
if (this.text[this.#index] === ']') {
|
|
326
|
+
return 'Array literals in annotation arguments do not allow trailing commas.';
|
|
327
|
+
}
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
return 'Array literals in annotation arguments must close with `]`.';
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
private parseBooleanOrIdentifierValue():
|
|
334
|
+
| ParsedAnnotationBooleanValue
|
|
335
|
+
| ParsedAnnotationIdentifierValue
|
|
336
|
+
| string {
|
|
337
|
+
const parsedName = parseIdentifierName(this.text, this.#index, true);
|
|
338
|
+
if (typeof parsedName === 'string') {
|
|
339
|
+
return parsedName;
|
|
340
|
+
}
|
|
341
|
+
this.#index = parsedName.end;
|
|
342
|
+
if (parsedName.name === 'true' || parsedName.name === 'false') {
|
|
343
|
+
return {
|
|
344
|
+
kind: 'boolean',
|
|
345
|
+
text: parsedName.name,
|
|
346
|
+
value: parsedName.name === 'true',
|
|
347
|
+
};
|
|
348
|
+
}
|
|
349
|
+
return {
|
|
350
|
+
kind: 'identifier',
|
|
351
|
+
name: parsedName.name,
|
|
352
|
+
text: parsedName.name,
|
|
353
|
+
};
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
private parseNumberValue(): ParsedAnnotationNumberValue | string {
|
|
357
|
+
const remaining = this.text.slice(this.#index);
|
|
358
|
+
const match = /^-?(?:0|[1-9][0-9]*)(?:\.[0-9]+)?/u.exec(remaining);
|
|
359
|
+
if (!match) {
|
|
360
|
+
return 'Expected a number literal.';
|
|
361
|
+
}
|
|
362
|
+
const numberText = match[0] ?? '';
|
|
363
|
+
this.#index += numberText.length;
|
|
364
|
+
return {
|
|
365
|
+
kind: 'number',
|
|
366
|
+
text: numberText,
|
|
367
|
+
value: Number(numberText),
|
|
368
|
+
};
|
|
369
|
+
}
|
|
370
|
+
|
|
371
|
+
private parseObjectValue(): ParsedAnnotationObjectValue | string {
|
|
372
|
+
const start = this.#index;
|
|
373
|
+
if (this.text[this.#index] !== '{') {
|
|
374
|
+
return 'Expected an object literal.';
|
|
375
|
+
}
|
|
376
|
+
this.#index += 1;
|
|
377
|
+
this.#index = skipWhitespace(this.text, this.#index);
|
|
378
|
+
const properties: ParsedAnnotationObjectProperty[] = [];
|
|
379
|
+
|
|
380
|
+
if (this.text[this.#index] === '}') {
|
|
381
|
+
this.#index += 1;
|
|
382
|
+
return {
|
|
383
|
+
kind: 'object',
|
|
384
|
+
properties,
|
|
385
|
+
text: this.text.slice(start, this.#index),
|
|
386
|
+
};
|
|
387
|
+
}
|
|
388
|
+
|
|
389
|
+
while (this.#index < this.text.length) {
|
|
390
|
+
const propertyStart = this.#index;
|
|
391
|
+
const parsedName = parseIdentifierName(this.text, this.#index, false);
|
|
392
|
+
if (typeof parsedName === 'string') {
|
|
393
|
+
return 'Object literals in annotation arguments require identifier property names.';
|
|
394
|
+
}
|
|
395
|
+
this.#index = parsedName.end;
|
|
396
|
+
this.#index = skipWhitespace(this.text, this.#index);
|
|
397
|
+
if (this.text[this.#index] !== ':') {
|
|
398
|
+
return `Object literal property \`${parsedName.name}\` must use \`name: value\` syntax.`;
|
|
399
|
+
}
|
|
400
|
+
this.#index += 1;
|
|
401
|
+
this.#index = skipWhitespace(this.text, this.#index);
|
|
402
|
+
const value = this.parseValueAtCurrentIndex();
|
|
403
|
+
if (typeof value === 'string') {
|
|
404
|
+
return value;
|
|
405
|
+
}
|
|
406
|
+
properties.push({
|
|
407
|
+
name: parsedName.name,
|
|
408
|
+
text: this.text.slice(propertyStart, this.#index),
|
|
409
|
+
value,
|
|
410
|
+
});
|
|
411
|
+
this.#index = skipWhitespace(this.text, this.#index);
|
|
412
|
+
if (this.text[this.#index] === '}') {
|
|
413
|
+
this.#index += 1;
|
|
414
|
+
return {
|
|
415
|
+
kind: 'object',
|
|
416
|
+
properties,
|
|
417
|
+
text: this.text.slice(start, this.#index),
|
|
418
|
+
};
|
|
419
|
+
}
|
|
420
|
+
if (this.text[this.#index] !== ',') {
|
|
421
|
+
return 'Object literals in annotation arguments must separate properties with commas.';
|
|
422
|
+
}
|
|
423
|
+
this.#index += 1;
|
|
424
|
+
this.#index = skipWhitespace(this.text, this.#index);
|
|
425
|
+
if (this.text[this.#index] === '}') {
|
|
426
|
+
return 'Object literals in annotation arguments do not allow trailing commas.';
|
|
427
|
+
}
|
|
428
|
+
}
|
|
429
|
+
|
|
430
|
+
return 'Object literals in annotation arguments must close with `}`.';
|
|
431
|
+
}
|
|
432
|
+
|
|
433
|
+
private parseStringValue(): ParsedAnnotationStringValue | string {
|
|
434
|
+
const start = this.#index;
|
|
435
|
+
const end = readStringLiteral(this.text, start);
|
|
436
|
+
if (typeof end === 'string') {
|
|
437
|
+
return end;
|
|
438
|
+
}
|
|
439
|
+
|
|
440
|
+
const literalText = this.text.slice(start, end);
|
|
441
|
+
this.#index = end;
|
|
442
|
+
try {
|
|
443
|
+
return {
|
|
444
|
+
kind: 'string',
|
|
445
|
+
text: literalText,
|
|
446
|
+
value: JSON.parse(literalText.replace(/^'/u, '"').replace(/'$/u, '"')),
|
|
447
|
+
};
|
|
448
|
+
} catch {
|
|
449
|
+
const quote = literalText[0];
|
|
450
|
+
const innerText = literalText.slice(1, -1);
|
|
451
|
+
const normalized = quote === "'"
|
|
452
|
+
? `"${innerText.replace(/\\/gu, '\\\\').replace(/"/gu, '\\"')}"`
|
|
453
|
+
: literalText;
|
|
454
|
+
return {
|
|
455
|
+
kind: 'string',
|
|
456
|
+
text: literalText,
|
|
457
|
+
value: JSON.parse(normalized),
|
|
458
|
+
};
|
|
459
|
+
}
|
|
460
|
+
}
|
|
461
|
+
|
|
462
|
+
private parseValueAtCurrentIndex(): ParsedAnnotationValue | string {
|
|
463
|
+
this.#index = skipWhitespace(this.text, this.#index);
|
|
464
|
+
const character = this.text[this.#index];
|
|
465
|
+
if (character === '"' || character === "'") {
|
|
466
|
+
return this.parseStringValue();
|
|
467
|
+
}
|
|
468
|
+
if (character === '[') {
|
|
469
|
+
return this.parseArrayValue();
|
|
470
|
+
}
|
|
471
|
+
if (character === '{') {
|
|
472
|
+
return this.parseObjectValue();
|
|
473
|
+
}
|
|
474
|
+
if (character === '-' || isDigit(character)) {
|
|
475
|
+
return this.parseNumberValue();
|
|
476
|
+
}
|
|
477
|
+
if (isIdentifierStart(character)) {
|
|
478
|
+
return this.parseBooleanOrIdentifierValue();
|
|
479
|
+
}
|
|
480
|
+
return 'Annotation arguments must use identifiers, strings, numbers, booleans, arrays, or objects.';
|
|
481
|
+
}
|
|
482
|
+
|
|
483
|
+
private tryParseNamedArgument(): ParsedAnnotationArgument | string {
|
|
484
|
+
const start = this.#index;
|
|
485
|
+
const parsedName = parseIdentifierName(this.text, this.#index, false);
|
|
486
|
+
if (typeof parsedName === 'string') {
|
|
487
|
+
return parsedName;
|
|
488
|
+
}
|
|
489
|
+
|
|
490
|
+
this.#index = parsedName.end;
|
|
491
|
+
const afterName = skipWhitespace(this.text, this.#index);
|
|
492
|
+
if (this.text[afterName] !== ':') {
|
|
493
|
+
this.#index = start;
|
|
494
|
+
return 'not-a-named-argument';
|
|
495
|
+
}
|
|
496
|
+
|
|
497
|
+
this.#index = skipWhitespace(this.text, afterName + 1);
|
|
498
|
+
const value = this.parseValueAtCurrentIndex();
|
|
499
|
+
if (typeof value === 'string') {
|
|
500
|
+
return value;
|
|
501
|
+
}
|
|
502
|
+
|
|
503
|
+
return {
|
|
504
|
+
kind: 'named',
|
|
505
|
+
name: parsedName.name,
|
|
506
|
+
text: this.text.slice(start, this.#index),
|
|
507
|
+
value,
|
|
508
|
+
};
|
|
509
|
+
}
|
|
510
|
+
}
|
|
511
|
+
|
|
512
|
+
function splitAnnotationItems(
|
|
513
|
+
innerText: string,
|
|
514
|
+
): readonly { end: number; start: number; text: string }[] | string {
|
|
515
|
+
const items: Array<{ end: number; start: number; text: string }> = [];
|
|
516
|
+
let itemStart = 0;
|
|
517
|
+
let parenDepth = 0;
|
|
518
|
+
let bracketDepth = 0;
|
|
519
|
+
let braceDepth = 0;
|
|
520
|
+
|
|
521
|
+
for (let index = 0; index < innerText.length; index += 1) {
|
|
522
|
+
const character = innerText[index];
|
|
523
|
+
if (character === '"' || character === "'") {
|
|
524
|
+
const stringEnd = readStringLiteral(innerText, index);
|
|
525
|
+
if (typeof stringEnd === 'string') {
|
|
526
|
+
return stringEnd;
|
|
527
|
+
}
|
|
528
|
+
index = stringEnd - 1;
|
|
529
|
+
continue;
|
|
530
|
+
}
|
|
531
|
+
|
|
532
|
+
if (character === '(') {
|
|
533
|
+
parenDepth += 1;
|
|
534
|
+
continue;
|
|
535
|
+
}
|
|
536
|
+
if (character === ')') {
|
|
537
|
+
if (parenDepth === 0) {
|
|
538
|
+
return 'Annotation arguments contain an unexpected closing parenthesis.';
|
|
539
|
+
}
|
|
540
|
+
parenDepth -= 1;
|
|
541
|
+
continue;
|
|
542
|
+
}
|
|
543
|
+
if (character === '[') {
|
|
544
|
+
bracketDepth += 1;
|
|
545
|
+
continue;
|
|
546
|
+
}
|
|
547
|
+
if (character === ']') {
|
|
548
|
+
if (bracketDepth === 0) {
|
|
549
|
+
return 'Annotation arguments contain an unexpected closing bracket.';
|
|
550
|
+
}
|
|
551
|
+
bracketDepth -= 1;
|
|
552
|
+
continue;
|
|
553
|
+
}
|
|
554
|
+
if (character === '{') {
|
|
555
|
+
braceDepth += 1;
|
|
556
|
+
continue;
|
|
557
|
+
}
|
|
558
|
+
if (character === '}') {
|
|
559
|
+
if (braceDepth === 0) {
|
|
560
|
+
return 'Annotation arguments contain an unexpected closing brace.';
|
|
561
|
+
}
|
|
562
|
+
braceDepth -= 1;
|
|
563
|
+
continue;
|
|
564
|
+
}
|
|
565
|
+
if (character === ',' && parenDepth === 0 && bracketDepth === 0 && braceDepth === 0) {
|
|
566
|
+
const trimmed = trimRange(innerText, itemStart, index);
|
|
567
|
+
if (trimmed.text.length === 0) {
|
|
568
|
+
return 'Annotation lists do not allow empty items.';
|
|
569
|
+
}
|
|
570
|
+
items.push(trimmed);
|
|
571
|
+
itemStart = index + 1;
|
|
572
|
+
}
|
|
573
|
+
}
|
|
574
|
+
|
|
575
|
+
if (parenDepth !== 0) {
|
|
576
|
+
return 'Annotation arguments must use balanced parentheses.';
|
|
577
|
+
}
|
|
578
|
+
if (bracketDepth !== 0) {
|
|
579
|
+
return 'Annotation arguments must use balanced brackets.';
|
|
580
|
+
}
|
|
581
|
+
if (braceDepth !== 0) {
|
|
582
|
+
return 'Annotation arguments must use balanced braces.';
|
|
583
|
+
}
|
|
584
|
+
|
|
585
|
+
const trimmed = trimRange(innerText, itemStart, innerText.length);
|
|
586
|
+
if (trimmed.text.length === 0) {
|
|
587
|
+
return 'Annotation lists do not allow empty items.';
|
|
588
|
+
}
|
|
589
|
+
items.push(trimmed);
|
|
590
|
+
return items;
|
|
591
|
+
}
|
|
592
|
+
|
|
593
|
+
export function parseAnnotationArgumentsText(
|
|
594
|
+
argumentsText: string,
|
|
595
|
+
): readonly ParsedAnnotationArgument[] | string {
|
|
596
|
+
return new AnnotationValueParser(argumentsText).parseArguments();
|
|
597
|
+
}
|
|
598
|
+
|
|
599
|
+
export function parseAnnotationItemText(
|
|
600
|
+
itemText: string,
|
|
601
|
+
): ParsedAnnotationSyntax | string {
|
|
602
|
+
const trimmed = itemText.trim();
|
|
603
|
+
const parsedName = parseIdentifierName(trimmed, 0, true);
|
|
604
|
+
if (typeof parsedName === 'string') {
|
|
605
|
+
return parsedName;
|
|
606
|
+
}
|
|
607
|
+
|
|
608
|
+
let index = skipWhitespace(trimmed, parsedName.end);
|
|
609
|
+
if (index >= trimmed.length) {
|
|
610
|
+
return {
|
|
611
|
+
name: parsedName.name,
|
|
612
|
+
text: trimmed,
|
|
613
|
+
};
|
|
614
|
+
}
|
|
615
|
+
|
|
616
|
+
if (trimmed[index] !== '(') {
|
|
617
|
+
return 'Annotation items may only contain a name and an optional argument list.';
|
|
618
|
+
}
|
|
619
|
+
|
|
620
|
+
const argumentsStart = index + 1;
|
|
621
|
+
let parenDepth = 1;
|
|
622
|
+
let bracketDepth = 0;
|
|
623
|
+
let braceDepth = 0;
|
|
624
|
+
index += 1;
|
|
625
|
+
while (index < trimmed.length) {
|
|
626
|
+
const character = trimmed[index];
|
|
627
|
+
if (character === '"' || character === "'") {
|
|
628
|
+
const stringEnd = readStringLiteral(trimmed, index);
|
|
629
|
+
if (typeof stringEnd === 'string') {
|
|
630
|
+
return stringEnd;
|
|
631
|
+
}
|
|
632
|
+
index = stringEnd;
|
|
633
|
+
continue;
|
|
634
|
+
}
|
|
635
|
+
if (character === '(') {
|
|
636
|
+
parenDepth += 1;
|
|
637
|
+
index += 1;
|
|
638
|
+
continue;
|
|
639
|
+
}
|
|
640
|
+
if (character === ')') {
|
|
641
|
+
parenDepth -= 1;
|
|
642
|
+
if (parenDepth === 0) {
|
|
643
|
+
break;
|
|
644
|
+
}
|
|
645
|
+
if (parenDepth < 0) {
|
|
646
|
+
return 'Annotation arguments contain an unexpected closing parenthesis.';
|
|
647
|
+
}
|
|
648
|
+
index += 1;
|
|
649
|
+
continue;
|
|
650
|
+
}
|
|
651
|
+
if (character === '[') {
|
|
652
|
+
bracketDepth += 1;
|
|
653
|
+
index += 1;
|
|
654
|
+
continue;
|
|
655
|
+
}
|
|
656
|
+
if (character === ']') {
|
|
657
|
+
if (bracketDepth === 0) {
|
|
658
|
+
return 'Annotation arguments contain an unexpected closing bracket.';
|
|
659
|
+
}
|
|
660
|
+
bracketDepth -= 1;
|
|
661
|
+
index += 1;
|
|
662
|
+
continue;
|
|
663
|
+
}
|
|
664
|
+
if (character === '{') {
|
|
665
|
+
braceDepth += 1;
|
|
666
|
+
index += 1;
|
|
667
|
+
continue;
|
|
668
|
+
}
|
|
669
|
+
if (character === '}') {
|
|
670
|
+
if (braceDepth === 0) {
|
|
671
|
+
return 'Annotation arguments contain an unexpected closing brace.';
|
|
672
|
+
}
|
|
673
|
+
braceDepth -= 1;
|
|
674
|
+
index += 1;
|
|
675
|
+
continue;
|
|
676
|
+
}
|
|
677
|
+
index += 1;
|
|
678
|
+
}
|
|
679
|
+
|
|
680
|
+
if (index >= trimmed.length || parenDepth !== 0) {
|
|
681
|
+
return 'Annotation arguments must use balanced parentheses.';
|
|
682
|
+
}
|
|
683
|
+
if (bracketDepth !== 0) {
|
|
684
|
+
return 'Annotation arguments must use balanced brackets.';
|
|
685
|
+
}
|
|
686
|
+
if (braceDepth !== 0) {
|
|
687
|
+
return 'Annotation arguments must use balanced braces.';
|
|
688
|
+
}
|
|
689
|
+
if (trimmed.slice(index + 1).trim().length > 0) {
|
|
690
|
+
return 'Annotation items may only contain a name and an optional argument list.';
|
|
691
|
+
}
|
|
692
|
+
|
|
693
|
+
const argumentsText = trimmed.slice(argumentsStart, index).trim();
|
|
694
|
+
const parsedArguments = parseAnnotationArgumentsText(argumentsText);
|
|
695
|
+
if (typeof parsedArguments === 'string') {
|
|
696
|
+
return parsedArguments;
|
|
697
|
+
}
|
|
698
|
+
|
|
699
|
+
return {
|
|
700
|
+
arguments: parsedArguments.length === 0 ? [] : parsedArguments,
|
|
701
|
+
argumentsText,
|
|
702
|
+
name: parsedName.name,
|
|
703
|
+
text: trimmed,
|
|
704
|
+
};
|
|
705
|
+
}
|
|
706
|
+
|
|
707
|
+
export function parseAnnotationCommentText(
|
|
708
|
+
commentText: string,
|
|
709
|
+
): { annotations: readonly ParsedAnnotationSyntax[]; text: string } | string | null {
|
|
710
|
+
if (!ANNOTATION_COMMENT_PATTERN.test(commentText)) {
|
|
711
|
+
return null;
|
|
712
|
+
}
|
|
713
|
+
|
|
714
|
+
const openMarkerText = commentText.match(ANNOTATION_COMMENT_PATTERN)?.[0];
|
|
715
|
+
if (!openMarkerText) {
|
|
716
|
+
return null;
|
|
717
|
+
}
|
|
718
|
+
|
|
719
|
+
const bodyStart = openMarkerText.length;
|
|
720
|
+
let closingBracketIndex = -1;
|
|
721
|
+
let parenDepth = 0;
|
|
722
|
+
let bracketDepth = 0;
|
|
723
|
+
let braceDepth = 0;
|
|
724
|
+
|
|
725
|
+
for (let index = bodyStart; index < commentText.length; index += 1) {
|
|
726
|
+
const character = commentText[index];
|
|
727
|
+
if (character === '"' || character === "'") {
|
|
728
|
+
const stringEnd = readStringLiteral(commentText, index);
|
|
729
|
+
if (typeof stringEnd === 'string') {
|
|
730
|
+
return stringEnd;
|
|
731
|
+
}
|
|
732
|
+
index = stringEnd - 1;
|
|
733
|
+
continue;
|
|
734
|
+
}
|
|
735
|
+
|
|
736
|
+
if (character === '(') {
|
|
737
|
+
parenDepth += 1;
|
|
738
|
+
continue;
|
|
739
|
+
}
|
|
740
|
+
if (character === ')') {
|
|
741
|
+
if (parenDepth === 0) {
|
|
742
|
+
return 'Annotation arguments contain an unexpected closing parenthesis.';
|
|
743
|
+
}
|
|
744
|
+
parenDepth -= 1;
|
|
745
|
+
continue;
|
|
746
|
+
}
|
|
747
|
+
if (character === '[') {
|
|
748
|
+
bracketDepth += 1;
|
|
749
|
+
continue;
|
|
750
|
+
}
|
|
751
|
+
if (character === ']') {
|
|
752
|
+
if (parenDepth === 0 && bracketDepth === 0 && braceDepth === 0) {
|
|
753
|
+
closingBracketIndex = index;
|
|
754
|
+
break;
|
|
755
|
+
}
|
|
756
|
+
if (bracketDepth === 0) {
|
|
757
|
+
return 'Annotation arguments contain an unexpected closing bracket.';
|
|
758
|
+
}
|
|
759
|
+
bracketDepth -= 1;
|
|
760
|
+
continue;
|
|
761
|
+
}
|
|
762
|
+
if (character === '{') {
|
|
763
|
+
braceDepth += 1;
|
|
764
|
+
continue;
|
|
765
|
+
}
|
|
766
|
+
if (character === '}') {
|
|
767
|
+
if (braceDepth === 0) {
|
|
768
|
+
return 'Annotation arguments contain an unexpected closing brace.';
|
|
769
|
+
}
|
|
770
|
+
braceDepth -= 1;
|
|
771
|
+
continue;
|
|
772
|
+
}
|
|
773
|
+
}
|
|
774
|
+
|
|
775
|
+
if (closingBracketIndex === -1) {
|
|
776
|
+
return 'Annotation comments must close with `]`.';
|
|
777
|
+
}
|
|
778
|
+
if (parenDepth !== 0) {
|
|
779
|
+
return 'Annotation arguments must use balanced parentheses.';
|
|
780
|
+
}
|
|
781
|
+
if (bracketDepth !== 0) {
|
|
782
|
+
return 'Annotation arguments must use balanced brackets.';
|
|
783
|
+
}
|
|
784
|
+
if (braceDepth !== 0) {
|
|
785
|
+
return 'Annotation arguments must use balanced braces.';
|
|
786
|
+
}
|
|
787
|
+
|
|
788
|
+
const trimmedBody = trimRange(commentText, bodyStart, closingBracketIndex);
|
|
789
|
+
const innerText = trimmedBody.text;
|
|
790
|
+
if (innerText.length === 0) {
|
|
791
|
+
return 'Annotation comments must contain at least one annotation item.';
|
|
792
|
+
}
|
|
793
|
+
|
|
794
|
+
const splitItems = splitAnnotationItems(innerText);
|
|
795
|
+
if (typeof splitItems === 'string') {
|
|
796
|
+
return splitItems;
|
|
797
|
+
}
|
|
798
|
+
|
|
799
|
+
const annotations: ParsedAnnotationSyntax[] = [];
|
|
800
|
+
for (const item of splitItems) {
|
|
801
|
+
const parsedAnnotation = parseAnnotationItemText(item.text);
|
|
802
|
+
if (typeof parsedAnnotation === 'string') {
|
|
803
|
+
return parsedAnnotation;
|
|
804
|
+
}
|
|
805
|
+
const parsedName = parseIdentifierName(item.text, 0, true);
|
|
806
|
+
if (typeof parsedName === 'string') {
|
|
807
|
+
return parsedName;
|
|
808
|
+
}
|
|
809
|
+
const absoluteStart = trimmedBody.start + item.start;
|
|
810
|
+
annotations.push({
|
|
811
|
+
...parsedAnnotation,
|
|
812
|
+
nameRange: {
|
|
813
|
+
start: absoluteStart,
|
|
814
|
+
end: absoluteStart + parsedName.end,
|
|
815
|
+
},
|
|
816
|
+
range: {
|
|
817
|
+
start: absoluteStart,
|
|
818
|
+
end: trimmedBody.start + item.end,
|
|
819
|
+
},
|
|
820
|
+
});
|
|
821
|
+
}
|
|
822
|
+
|
|
823
|
+
return {
|
|
824
|
+
annotations,
|
|
825
|
+
text: commentText.trim(),
|
|
826
|
+
};
|
|
827
|
+
}
|
|
828
|
+
|
|
829
|
+
interface ScannedComment {
|
|
830
|
+
readonly endLine: number;
|
|
831
|
+
readonly entry?: ParsedAnnotationEntry;
|
|
832
|
+
readonly kind: 'annotation' | 'annotation-parse-error' | 'banned-ts-pragma' | 'other-comment';
|
|
833
|
+
readonly range: AnnotationTextRange;
|
|
834
|
+
readonly standalone: boolean;
|
|
835
|
+
readonly startLine: number;
|
|
836
|
+
}
|
|
837
|
+
|
|
838
|
+
function isAnnotationTargetNode(node: ts.Node): boolean {
|
|
839
|
+
return ts.isStatement(node) ||
|
|
840
|
+
ts.isBindingElement(node) ||
|
|
841
|
+
ts.isClassDeclaration(node) ||
|
|
842
|
+
ts.isClassElement(node) ||
|
|
843
|
+
ts.isEnumDeclaration(node) ||
|
|
844
|
+
ts.isEnumMember(node) ||
|
|
845
|
+
ts.isFunctionDeclaration(node) ||
|
|
846
|
+
ts.isImportClause(node) ||
|
|
847
|
+
ts.isInterfaceDeclaration(node) ||
|
|
848
|
+
ts.isModuleDeclaration(node) ||
|
|
849
|
+
ts.isParameter(node) ||
|
|
850
|
+
ts.isPropertyAssignment(node) ||
|
|
851
|
+
ts.isShorthandPropertyAssignment(node) ||
|
|
852
|
+
ts.isTypeAliasDeclaration(node) ||
|
|
853
|
+
ts.isTypeElement(node);
|
|
854
|
+
}
|
|
855
|
+
|
|
856
|
+
function getNodeStartLine(node: ts.Node): number {
|
|
857
|
+
const sourceFile = node.getSourceFile();
|
|
858
|
+
return sourceFile.getLineAndCharacterOfPosition(node.getStart(sourceFile)).line + 1;
|
|
859
|
+
}
|
|
860
|
+
|
|
861
|
+
function parseTypeScriptPragma(commentText: string): string | undefined {
|
|
862
|
+
if (commentText.startsWith('//')) {
|
|
863
|
+
const match = commentText.match(/^\/\/\s*(@ts-[a-z-]+)\b/u);
|
|
864
|
+
return match?.[1];
|
|
865
|
+
}
|
|
866
|
+
|
|
867
|
+
if (!commentText.startsWith('/*')) {
|
|
868
|
+
return undefined;
|
|
869
|
+
}
|
|
870
|
+
|
|
871
|
+
const withoutOpen = commentText.replace(/^\/\*+\s?/u, '');
|
|
872
|
+
const withoutClose = withoutOpen.replace(/\*\/\s*$/u, '');
|
|
873
|
+
|
|
874
|
+
for (const rawLine of withoutClose.split(/\r?\n/u)) {
|
|
875
|
+
const line = rawLine.trimStart().replace(/^\*\s?/u, '');
|
|
876
|
+
if (line.length === 0) {
|
|
877
|
+
continue;
|
|
878
|
+
}
|
|
879
|
+
|
|
880
|
+
const match = line.match(/^(@ts-[a-z-]+)\b/u);
|
|
881
|
+
return match?.[1];
|
|
882
|
+
}
|
|
883
|
+
|
|
884
|
+
return undefined;
|
|
885
|
+
}
|
|
886
|
+
|
|
887
|
+
function createAnnotationParseError(
|
|
888
|
+
line: number,
|
|
889
|
+
text: string,
|
|
890
|
+
message: string,
|
|
891
|
+
): ParsedAnnotationParseError {
|
|
892
|
+
return {
|
|
893
|
+
kind: 'annotation-parse-error',
|
|
894
|
+
line,
|
|
895
|
+
message,
|
|
896
|
+
text,
|
|
897
|
+
};
|
|
898
|
+
}
|
|
899
|
+
|
|
900
|
+
function absolutizeAnnotationComment(
|
|
901
|
+
comment: { annotations: readonly ParsedAnnotationSyntax[]; text: string },
|
|
902
|
+
absoluteStart: number,
|
|
903
|
+
line: number,
|
|
904
|
+
range: AnnotationTextRange,
|
|
905
|
+
): ParsedAnnotationComment {
|
|
906
|
+
return {
|
|
907
|
+
annotations: comment.annotations.map((annotation) => ({
|
|
908
|
+
...annotation,
|
|
909
|
+
nameRange: annotation.nameRange
|
|
910
|
+
? {
|
|
911
|
+
start: absoluteStart + annotation.nameRange.start,
|
|
912
|
+
end: absoluteStart + annotation.nameRange.end,
|
|
913
|
+
}
|
|
914
|
+
: undefined,
|
|
915
|
+
range: annotation.range
|
|
916
|
+
? {
|
|
917
|
+
start: absoluteStart + annotation.range.start,
|
|
918
|
+
end: absoluteStart + annotation.range.end,
|
|
919
|
+
}
|
|
920
|
+
: undefined,
|
|
921
|
+
})),
|
|
922
|
+
kind: 'annotation',
|
|
923
|
+
line,
|
|
924
|
+
range,
|
|
925
|
+
text: comment.text,
|
|
926
|
+
};
|
|
927
|
+
}
|
|
928
|
+
|
|
929
|
+
function parseAnnotationEntry(
|
|
930
|
+
commentText: string,
|
|
931
|
+
line: number,
|
|
932
|
+
standalone: boolean,
|
|
933
|
+
absoluteStart: number,
|
|
934
|
+
range: AnnotationTextRange,
|
|
935
|
+
): ParsedAnnotationEntry | undefined {
|
|
936
|
+
if (ANNOTATION_COMMENT_PATTERN.test(commentText)) {
|
|
937
|
+
if (!standalone) {
|
|
938
|
+
return createAnnotationParseError(
|
|
939
|
+
line,
|
|
940
|
+
commentText.trim(),
|
|
941
|
+
'Annotation comments must appear on their own line.',
|
|
942
|
+
);
|
|
943
|
+
}
|
|
944
|
+
|
|
945
|
+
const parsedComment = parseAnnotationCommentText(commentText);
|
|
946
|
+
if (typeof parsedComment === 'string') {
|
|
947
|
+
return createAnnotationParseError(line, commentText.trim(), parsedComment);
|
|
948
|
+
}
|
|
949
|
+
if (parsedComment) {
|
|
950
|
+
return absolutizeAnnotationComment(parsedComment, absoluteStart, line, range);
|
|
951
|
+
}
|
|
952
|
+
}
|
|
953
|
+
|
|
954
|
+
const tsPragmaText = parseTypeScriptPragma(commentText);
|
|
955
|
+
if (tsPragmaText) {
|
|
956
|
+
return {
|
|
957
|
+
kind: 'banned-ts-pragma',
|
|
958
|
+
line,
|
|
959
|
+
text: tsPragmaText,
|
|
960
|
+
};
|
|
961
|
+
}
|
|
962
|
+
|
|
963
|
+
return undefined;
|
|
964
|
+
}
|
|
965
|
+
|
|
966
|
+
function traverseNode(node: ts.Node, visitor: (node: ts.Node) => void): void {
|
|
967
|
+
visitor(node);
|
|
968
|
+
ts.forEachChild(node, (child) => traverseNode(child, visitor));
|
|
969
|
+
}
|
|
970
|
+
|
|
971
|
+
export function createAnnotationLookup(sourceFile: ts.SourceFile): AnnotationLookup {
|
|
972
|
+
const entriesByLine = new Map<number, ParsedAnnotationEntry[]>();
|
|
973
|
+
const entries: ParsedAnnotationEntry[] = [];
|
|
974
|
+
const scannedComments: ScannedComment[] = [];
|
|
975
|
+
const candidateNodesByStartLine = new Map<number, ts.Node[]>();
|
|
976
|
+
const blocksByTargetNode = new WeakMap<ts.Node, ParsedAnnotationBlock>();
|
|
977
|
+
const scanner = ts.createScanner(
|
|
978
|
+
ts.ScriptTarget.Latest,
|
|
979
|
+
false,
|
|
980
|
+
sourceFile.languageVariant,
|
|
981
|
+
sourceFile.text,
|
|
982
|
+
);
|
|
983
|
+
const lineStarts = sourceFile.getLineStarts();
|
|
984
|
+
|
|
985
|
+
traverseNode(sourceFile, (node) => {
|
|
986
|
+
if (!isAnnotationTargetNode(node)) {
|
|
987
|
+
return;
|
|
988
|
+
}
|
|
989
|
+
|
|
990
|
+
const startLine = getNodeStartLine(node);
|
|
991
|
+
const lineNodes = candidateNodesByStartLine.get(startLine);
|
|
992
|
+
if (lineNodes) {
|
|
993
|
+
lineNodes.push(node);
|
|
994
|
+
} else {
|
|
995
|
+
candidateNodesByStartLine.set(startLine, [node]);
|
|
996
|
+
}
|
|
997
|
+
});
|
|
998
|
+
|
|
999
|
+
if (sourceFile.isDeclarationFile) {
|
|
1000
|
+
const sourceLines = sourceFile.text.split(/\r?\n/u);
|
|
1001
|
+
let absoluteLineStart = 0;
|
|
1002
|
+
for (let lineIndex = 0; lineIndex < sourceLines.length; lineIndex += 1) {
|
|
1003
|
+
const rawLine = sourceLines[lineIndex] ?? '';
|
|
1004
|
+
const trimmedStart = rawLine.trimStart();
|
|
1005
|
+
if (!trimmedStart.startsWith('//')) {
|
|
1006
|
+
absoluteLineStart += rawLine.length + 1;
|
|
1007
|
+
continue;
|
|
1008
|
+
}
|
|
1009
|
+
|
|
1010
|
+
const trimmedOffset = rawLine.indexOf(trimmedStart);
|
|
1011
|
+
const start = absoluteLineStart + Math.max(trimmedOffset, 0);
|
|
1012
|
+
const end = absoluteLineStart + rawLine.length;
|
|
1013
|
+
const line = lineIndex + 1;
|
|
1014
|
+
const range = { start, end };
|
|
1015
|
+
const entry = parseAnnotationEntry(trimmedStart, line, true, start, range);
|
|
1016
|
+
scannedComments.push({
|
|
1017
|
+
endLine: line,
|
|
1018
|
+
entry,
|
|
1019
|
+
kind: entry?.kind ?? 'other-comment',
|
|
1020
|
+
range,
|
|
1021
|
+
standalone: true,
|
|
1022
|
+
startLine: line,
|
|
1023
|
+
});
|
|
1024
|
+
|
|
1025
|
+
if (entry) {
|
|
1026
|
+
const lineEntries = entriesByLine.get(line);
|
|
1027
|
+
if (lineEntries) {
|
|
1028
|
+
lineEntries.push(entry);
|
|
1029
|
+
} else {
|
|
1030
|
+
entriesByLine.set(line, [entry]);
|
|
1031
|
+
}
|
|
1032
|
+
entries.push(entry);
|
|
1033
|
+
}
|
|
1034
|
+
|
|
1035
|
+
absoluteLineStart += rawLine.length + 1;
|
|
1036
|
+
}
|
|
1037
|
+
}
|
|
1038
|
+
|
|
1039
|
+
while (true) {
|
|
1040
|
+
const token = scanner.scan();
|
|
1041
|
+
if (token === ts.SyntaxKind.EndOfFileToken) {
|
|
1042
|
+
break;
|
|
1043
|
+
}
|
|
1044
|
+
|
|
1045
|
+
if (
|
|
1046
|
+
token !== ts.SyntaxKind.MultiLineCommentTrivia &&
|
|
1047
|
+
!(token === ts.SyntaxKind.SingleLineCommentTrivia && !sourceFile.isDeclarationFile)
|
|
1048
|
+
) {
|
|
1049
|
+
continue;
|
|
1050
|
+
}
|
|
1051
|
+
|
|
1052
|
+
const tokenStart = scanner.getTokenPos();
|
|
1053
|
+
const tokenText = scanner.getTokenText();
|
|
1054
|
+
const tokenEnd = tokenStart + tokenText.length;
|
|
1055
|
+
const startLineInfo = sourceFile.getLineAndCharacterOfPosition(tokenStart);
|
|
1056
|
+
const endLineInfo = sourceFile.getLineAndCharacterOfPosition(tokenEnd);
|
|
1057
|
+
const line = startLineInfo.line + 1;
|
|
1058
|
+
const endLine = endLineInfo.line + 1;
|
|
1059
|
+
const lineStart = lineStarts[startLineInfo.line] ?? tokenStart;
|
|
1060
|
+
const standalone = sourceFile.text.slice(lineStart, tokenStart).trim().length === 0;
|
|
1061
|
+
const range = { start: tokenStart, end: tokenEnd };
|
|
1062
|
+
const entry = parseAnnotationEntry(tokenText, line, standalone, tokenStart, range);
|
|
1063
|
+
|
|
1064
|
+
scannedComments.push({
|
|
1065
|
+
endLine,
|
|
1066
|
+
entry,
|
|
1067
|
+
kind: entry?.kind ?? 'other-comment',
|
|
1068
|
+
range,
|
|
1069
|
+
standalone,
|
|
1070
|
+
startLine: line,
|
|
1071
|
+
});
|
|
1072
|
+
|
|
1073
|
+
if (!entry) {
|
|
1074
|
+
continue;
|
|
1075
|
+
}
|
|
1076
|
+
|
|
1077
|
+
const lineEntries = entriesByLine.get(line);
|
|
1078
|
+
if (lineEntries) {
|
|
1079
|
+
lineEntries.push(entry);
|
|
1080
|
+
} else {
|
|
1081
|
+
entriesByLine.set(line, [entry]);
|
|
1082
|
+
}
|
|
1083
|
+
entries.push(entry);
|
|
1084
|
+
}
|
|
1085
|
+
|
|
1086
|
+
if (sourceFile.languageVariant === ts.LanguageVariant.JSX) {
|
|
1087
|
+
const existingCommentRanges = new Set(
|
|
1088
|
+
scannedComments.map((comment) => `${comment.range.start}:${comment.range.end}`),
|
|
1089
|
+
);
|
|
1090
|
+
const sourceLines = sourceFile.text.split(/\r?\n/u);
|
|
1091
|
+
let absoluteLineStart = 0;
|
|
1092
|
+
for (let lineIndex = 0; lineIndex < sourceLines.length; lineIndex += 1) {
|
|
1093
|
+
const rawLine = sourceLines[lineIndex] ?? '';
|
|
1094
|
+
const trimmedStart = rawLine.trimStart();
|
|
1095
|
+
if (!trimmedStart.startsWith('//')) {
|
|
1096
|
+
absoluteLineStart += rawLine.length + 1;
|
|
1097
|
+
continue;
|
|
1098
|
+
}
|
|
1099
|
+
|
|
1100
|
+
const trimmedOffset = rawLine.indexOf(trimmedStart);
|
|
1101
|
+
const start = absoluteLineStart + Math.max(trimmedOffset, 0);
|
|
1102
|
+
const end = absoluteLineStart + rawLine.length;
|
|
1103
|
+
const rangeKey = `${start}:${end}`;
|
|
1104
|
+
if (existingCommentRanges.has(rangeKey)) {
|
|
1105
|
+
absoluteLineStart += rawLine.length + 1;
|
|
1106
|
+
continue;
|
|
1107
|
+
}
|
|
1108
|
+
|
|
1109
|
+
const line = lineIndex + 1;
|
|
1110
|
+
const range = { start, end };
|
|
1111
|
+
const entry = parseAnnotationEntry(trimmedStart, line, true, start, range);
|
|
1112
|
+
scannedComments.push({
|
|
1113
|
+
endLine: line,
|
|
1114
|
+
entry,
|
|
1115
|
+
kind: entry?.kind ?? 'other-comment',
|
|
1116
|
+
range,
|
|
1117
|
+
standalone: true,
|
|
1118
|
+
startLine: line,
|
|
1119
|
+
});
|
|
1120
|
+
|
|
1121
|
+
if (entry) {
|
|
1122
|
+
const lineEntries = entriesByLine.get(line);
|
|
1123
|
+
if (lineEntries) {
|
|
1124
|
+
lineEntries.push(entry);
|
|
1125
|
+
} else {
|
|
1126
|
+
entriesByLine.set(line, [entry]);
|
|
1127
|
+
}
|
|
1128
|
+
entries.push(entry);
|
|
1129
|
+
}
|
|
1130
|
+
|
|
1131
|
+
absoluteLineStart += rawLine.length + 1;
|
|
1132
|
+
}
|
|
1133
|
+
|
|
1134
|
+
scannedComments.sort((left, right) => left.range.start - right.range.start);
|
|
1135
|
+
}
|
|
1136
|
+
|
|
1137
|
+
const annotationBlocks: ParsedAnnotationBlock[] = [];
|
|
1138
|
+
for (let index = 0; index < scannedComments.length; index += 1) {
|
|
1139
|
+
const scannedComment = scannedComments[index];
|
|
1140
|
+
if (scannedComment.kind !== 'annotation' || !scannedComment.standalone) {
|
|
1141
|
+
continue;
|
|
1142
|
+
}
|
|
1143
|
+
|
|
1144
|
+
const previousComment = scannedComments[index - 1];
|
|
1145
|
+
if (
|
|
1146
|
+
previousComment &&
|
|
1147
|
+
previousComment.kind === 'annotation' &&
|
|
1148
|
+
previousComment.standalone &&
|
|
1149
|
+
previousComment.endLine + 1 === scannedComment.startLine
|
|
1150
|
+
) {
|
|
1151
|
+
continue;
|
|
1152
|
+
}
|
|
1153
|
+
|
|
1154
|
+
const blockComments: ScannedComment[] = [scannedComment];
|
|
1155
|
+
let currentIndex = index + 1;
|
|
1156
|
+
while (currentIndex < scannedComments.length) {
|
|
1157
|
+
const candidate = scannedComments[currentIndex];
|
|
1158
|
+
const previousBlockComment = blockComments[blockComments.length - 1];
|
|
1159
|
+
if (
|
|
1160
|
+
candidate.kind !== 'annotation' ||
|
|
1161
|
+
!candidate.standalone ||
|
|
1162
|
+
previousBlockComment.endLine + 1 !== candidate.startLine
|
|
1163
|
+
) {
|
|
1164
|
+
break;
|
|
1165
|
+
}
|
|
1166
|
+
|
|
1167
|
+
blockComments.push(candidate);
|
|
1168
|
+
currentIndex += 1;
|
|
1169
|
+
}
|
|
1170
|
+
|
|
1171
|
+
const annotations = blockComments.flatMap((comment) =>
|
|
1172
|
+
comment.entry?.kind === 'annotation' ? comment.entry.annotations : []
|
|
1173
|
+
);
|
|
1174
|
+
const startLine = blockComments[0]?.startLine ?? scannedComment.startLine;
|
|
1175
|
+
const endLine = blockComments[blockComments.length - 1]?.endLine ?? scannedComment.endLine;
|
|
1176
|
+
const targetNode = candidateNodesByStartLine.get(endLine + 1)?.[0];
|
|
1177
|
+
const block: ParsedAnnotationBlock = {
|
|
1178
|
+
annotations,
|
|
1179
|
+
endLine,
|
|
1180
|
+
range: {
|
|
1181
|
+
start: blockComments[0]?.range.start ?? scannedComment.range.start,
|
|
1182
|
+
end: blockComments[blockComments.length - 1]?.range.end ?? scannedComment.range.end,
|
|
1183
|
+
},
|
|
1184
|
+
startLine,
|
|
1185
|
+
targetNode,
|
|
1186
|
+
text: blockComments.map((comment) => comment.entry?.text ?? '').join('\n'),
|
|
1187
|
+
};
|
|
1188
|
+
annotationBlocks.push(block);
|
|
1189
|
+
if (targetNode) {
|
|
1190
|
+
blocksByTargetNode.set(targetNode, block);
|
|
1191
|
+
}
|
|
1192
|
+
}
|
|
1193
|
+
|
|
1194
|
+
return {
|
|
1195
|
+
getAttachedAnnotationBlock(node: ts.Node): ParsedAnnotationBlock | undefined {
|
|
1196
|
+
return blocksByTargetNode.get(node);
|
|
1197
|
+
},
|
|
1198
|
+
getAttachedAnnotations(node: ts.Node): readonly ParsedAnnotation[] {
|
|
1199
|
+
return blocksByTargetNode.get(node)?.annotations ?? [];
|
|
1200
|
+
},
|
|
1201
|
+
getBlocks(): readonly ParsedAnnotationBlock[] {
|
|
1202
|
+
return annotationBlocks;
|
|
1203
|
+
},
|
|
1204
|
+
getEntries(): readonly ParsedAnnotationEntry[] {
|
|
1205
|
+
return entries;
|
|
1206
|
+
},
|
|
1207
|
+
getEntriesForLine(line: number): readonly ParsedAnnotationEntry[] {
|
|
1208
|
+
return entriesByLine.get(line) ?? [];
|
|
1209
|
+
},
|
|
1210
|
+
hasAttachedAnnotation(node: ts.Node, name: string): boolean {
|
|
1211
|
+
return blocksByTargetNode.get(node)?.annotations.some((annotation) =>
|
|
1212
|
+
annotation.name === name
|
|
1213
|
+
) ??
|
|
1214
|
+
false;
|
|
1215
|
+
},
|
|
1216
|
+
};
|
|
1217
|
+
}
|