From f3ad4b099ed30162f2d2835f836fa5fbeabc1bef Mon Sep 17 00:00:00 2001 From: Nathan Whitaker Date: Thu, 12 Mar 2026 21:05:54 -0700 Subject: [PATCH 1/9] port to oxc --- Cargo.lock | 1362 ++++++++-------- Cargo.toml | 7 +- benches/doc_parser.rs | 15 +- examples/ddoc/main.rs | 2 + lib/lib.rs | 2 + rust-toolchain.toml | 2 +- src/class.rs | 206 +-- src/decorators.rs | 33 +- src/diagnostics.rs | 6 +- src/diff/class.rs | 2 +- src/diff/variable.rs | 2 +- src/display.rs | 17 +- src/enum.rs | 20 +- src/function.rs | 206 +-- src/html/mod.rs | 14 +- src/html/symbols/class.rs | 4 +- src/html/symbols/mod.rs | 2 +- src/html/symbols/namespace.rs | 12 +- src/html/types.rs | 4 +- src/html/util.rs | 8 +- src/interface.rs | 270 ++-- src/js_doc.rs | 92 +- src/lib.rs | 1 + src/params.rs | 279 +++- src/parser.rs | 416 ++--- src/printer.rs | 14 +- src/tests.rs | 50 +- src/ts_type.rs | 1587 ++++++++++--------- src/ts_type_param.rs | 10 +- src/type_alias.rs | 7 +- src/util/mod.rs | 1 + src/util/swc.rs | 150 +- src/util/symbol.rs | 2 +- src/util/types.rs | 88 + src/variable.rs | 314 ++-- src/visibility.rs | 10 +- tests/helpers/mod.rs | 4 + tests/html_test.rs | 4 + tests/specs/export_const_destructured.txt | 200 ++- tests/specs/export_namespace.txt | 306 ++-- tests/specs/infer_object_literal.txt | 536 ++++--- tests/specs/namespace_exports_self.txt | 4 +- tests/specs/private_type_class_property.txt | 267 +--- tests/specs/re_export_all_as_with_jsdoc.txt | 83 +- 44 files changed, 3366 insertions(+), 3255 deletions(-) create mode 100644 src/util/types.rs diff --git a/Cargo.lock b/Cargo.lock index 06aaf1e81..84a9918c3 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -17,18 +17,6 @@ version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "320119579fcad9c21884f5c4861d16174d0e06250625266f50fe6898340abefa" -[[package]] -name = "ahash" -version = "0.8.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a15f179cd60c4584b8a8c596927aadc462e27f2ca70c04e0071964a73ba7a75" -dependencies = [ - "cfg-if", - "once_cell", - "version_check", - "zerocopy", -] - [[package]] name = "aho-corasick" version = "1.1.3" @@ -112,23 +100,6 @@ version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50" -[[package]] -name = "ascii" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d92bec98840b8f03a5ff5413de5293bfcd8bf96467cf5452609f939ec6f5de16" - -[[package]] -name = "ast_node" -version = "5.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2eb025ef00a6da925cf40870b9c8d008526b6004ece399cb0974209720f0b194" -dependencies = [ - "quote", - "swc_macros_common", - "syn", -] - [[package]] name = "async-trait" version = "0.1.89" @@ -146,7 +117,7 @@ version = "0.2.14" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" dependencies = [ - "hermit-abi 0.1.19", + "hermit-abi", "libc", "winapi", ] @@ -188,15 +159,6 @@ dependencies = [ "vsimd", ] -[[package]] -name = "better_scoped_tls" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7cd228125315b132eed175bf47619ac79b945b26e56b848ba203ae4ea8603609" -dependencies = [ - "scoped-tls", -] - [[package]] name = "bitflags" version = "1.3.2" @@ -205,29 +167,26 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "bitflags" -version = "2.9.3" +version = "2.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "34efbcccd345379ca2868b2b2c9d3782e9cc58ba87bc7d79d5b53d9c9ae6f25d" +checksum = "843867be96c8daad0d758b57df9392b6d8d271134fce549de6ce169ff98a92af" [[package]] -name = "bitvec" -version = "1.0.1" +name = "block-buffer" +version = "0.10.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1bc2832c24239b0141d5674bb9174f9d68a8b5b3f2753311927c172ca46f7e9c" +checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" dependencies = [ - "funty", - "radium", - "tap", - "wyz", + "generic-array", ] [[package]] name = "block-buffer" -version = "0.10.4" +version = "0.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" +checksum = "cdd35008169921d80bc60d3d0ab416eecb028c4cd653352907921d95084790be" dependencies = [ - "generic-array", + "hybrid-array", ] [[package]] @@ -245,9 +204,6 @@ name = "bumpalo" version = "3.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "46c5e41b57b8bba42a04676d81cb89e9ee8e859a1a66f80a5a72e1cb76b34d43" -dependencies = [ - "allocator-api2", -] [[package]] name = "bytes" @@ -255,16 +211,6 @@ version = "1.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d71b6127be86fdcfddb610f7182ac57211d4b18a3e9c82eb2d17662f2227ad6a" -[[package]] -name = "bytes-str" -version = "0.2.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7c60b5ce37e0b883c37eb89f79a1e26fbe9c1081945d024eee93e8d91a7e18b3" -dependencies = [ - "bytes", - "serde", -] - [[package]] name = "capacity_builder" version = "0.5.0" @@ -311,15 +257,6 @@ dependencies = [ "rustversion", ] -[[package]] -name = "cc" -version = "1.2.34" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "42bc4aea80032b7bf409b0bc7ccad88853858911b7713a8062fdc0623867bedc" -dependencies = [ - "shlex", -] - [[package]] name = "cfg-if" version = "1.0.3" @@ -424,6 +361,15 @@ version = "0.7.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c3e64b0cc0439b12df2fa678eae89a1c56a529fd067a9115f7827f1fffd22b32" +[[package]] +name = "cobs" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fa961b519f0b462e3a3b4a34b64d119eeaca1d59af726fe450bbba07a9fc0a1" +dependencies = [ + "thiserror", +] + [[package]] name = "colorchoice" version = "1.0.4" @@ -432,13 +378,14 @@ checksum = "b05b61dc5112cbb17e4b6cd61790d9845d13888356391624cbe7e41efeac1e75" [[package]] name = "compact_str" -version = "0.7.1" +version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f86b9c4c00838774a6d902ef931eff7470720c51d90c2e32cfe15dc304737b3f" +checksum = "3fdb1325a1cece981e8a296ab8f0f9b63ae357bd0784a9faaf548cc7b480707a" dependencies = [ "castaway", "cfg-if", "itoa", + "rustversion", "ryu", "static_assertions", ] @@ -492,6 +439,18 @@ dependencies = [ "vte", ] +[[package]] +name = "const-oid" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a6ef517f0926dd24a1582492c791b6a4818a4d94e789a334894aa15b0d12f55c" + +[[package]] +name = "cow-utils" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "417bef24afe1460300965a25ff4a24b8b45ad011948302ec221e8a0a81eb2c79" + [[package]] name = "cpufeatures" version = "0.2.17" @@ -501,6 +460,24 @@ dependencies = [ "libc", ] +[[package]] +name = "cpufeatures" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b2a41393f66f16b0823bb79094d54ac5fbd34ab292ddafb9a0456ac9f87d201" +dependencies = [ + "libc", +] + +[[package]] +name = "crc32fast" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9481c1c90cbf2ac953f07c8d4a58aa3945c425b7185c9154d67a65e4230da511" +dependencies = [ + "cfg-if", +] + [[package]] name = "criterion" version = "0.4.0" @@ -514,7 +491,7 @@ dependencies = [ "clap 3.2.25", "criterion-plot", "futures", - "itertools", + "itertools 0.10.5", "lazy_static", "num-traits", "oorandom", @@ -535,7 +512,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6b50826342786a51a89e2da3a28f1c32b06e387201bc2d19791f622c673706b1" dependencies = [ "cast", - "itertools", + "itertools 0.10.5", ] [[package]] @@ -588,6 +565,15 @@ dependencies = [ "typenum", ] +[[package]] +name = "crypto-common" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce6e4c961d6cd6c9a86db418387425e8bdeaf05b3c8bc1411e6dca4c252f1453" +dependencies = [ + "hybrid-array", +] + [[package]] name = "darling" version = "0.20.11" @@ -623,57 +609,25 @@ dependencies = [ "syn", ] -[[package]] -name = "data-encoding" -version = "2.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2a2330da5de22e8a3cb63252ce2abb30116bf5265e89c0e01bc17015ce30a476" - [[package]] name = "data-url" version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "be1e0bca6c3637f992fc1cc7cbc52a78c1ef6db076dbf1059c4323d6a2048376" -[[package]] -name = "debugid" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bef552e6f588e446098f6ba40d89ac146c8c7b64aade83c051ee00bb5d2bc18d" -dependencies = [ - "serde", - "uuid", -] - [[package]] name = "deno_ast" version = "0.53.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05792fb2b77938767ffeb0853289e86501fddc84b1cdba9e5dc860c52baa2ff7" dependencies = [ "base64", "capacity_builder", "deno_error", "deno_media_type", "deno_terminal", - "dprint-swc-ext", + "oxc", + "oxc_str", "percent-encoding", "serde", - "swc_atoms", - "swc_common", - "swc_ecma_ast", - "swc_ecma_codegen", - "swc_ecma_codegen_macros", - "swc_ecma_lexer", - "swc_ecma_loader", - "swc_ecma_parser", - "swc_ecma_transforms_base", - "swc_ecma_utils", - "swc_ecma_visit", - "swc_eq_ignore_macros", - "swc_macros_common", - "swc_sourcemap", - "swc_visit", "text_lines", "thiserror", "unicode-width 0.2.1", @@ -762,9 +716,7 @@ dependencies = [ [[package]] name = "deno_graph" -version = "0.108.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b0ece7ecde2db52b86b1a1ebbe368bedded631e449dd0293a2c317bb25f7641c" +version = "0.108.2" dependencies = [ "async-trait", "boxed_error", @@ -780,7 +732,7 @@ dependencies = [ "futures", "indexmap 2.11.0", "log", - "monch 0.6.0", + "monch", "once_cell", "parking_lot", "regex", @@ -820,15 +772,15 @@ dependencies = [ [[package]] name = "deno_semver" -version = "0.9.0" +version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2625b7107cc3f61a462886d5fa77c23e063c1fd15b90e3d5ee2646e9f6178d55" +checksum = "147261611819fb4dfe339b53e3b45d6704c7e32c86ce33a88511d5bcebebaaa3" dependencies = [ "capacity_builder", "deno_error", "ecow", "hipstr", - "monch 0.5.0", + "monch", "once_cell", "serde", "thiserror", @@ -905,8 +857,19 @@ version = "0.10.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" dependencies = [ - "block-buffer", - "crypto-common", + "block-buffer 0.10.4", + "crypto-common 0.1.6", +] + +[[package]] +name = "digest" +version = "0.11.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1dd6dbb5841937940781866fa1281a1ff7bd3bf827091440879f9994983d5c2" +dependencies = [ + "block-buffer 0.12.0", + "const-oid", + "crypto-common 0.2.2", ] [[package]] @@ -921,20 +884,10 @@ dependencies = [ ] [[package]] -name = "dprint-swc-ext" -version = "0.26.0" +name = "dragonbox_ecma" +version = "0.1.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "33175ddb7a6d418589cab2966bd14a710b3b1139459d3d5ca9edf783c4833f4c" -dependencies = [ - "num-bigint", - "rustc-hash", - "swc_atoms", - "swc_common", - "swc_ecma_ast", - "swc_ecma_lexer", - "swc_ecma_parser", - "text_lines", -] +checksum = "fd8e701084c37e7ef62d3f9e453b618130cbc0ef3573847785952a3ac3f746bf" [[package]] name = "ecow" @@ -951,6 +904,18 @@ version = "1.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719" +[[package]] +name = "embedded-io" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef1a6892d9eef45c8fa6b9e0086428a2cca8491aca8f787c534a3d6d0bcb3ced" + +[[package]] +name = "embedded-io" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "edd0f118536f44f5ccd48bcb8b111bdc3de888b58c74639dfb034a357d0f206d" + [[package]] name = "encode_unicode" version = "1.0.0" @@ -978,6 +943,12 @@ version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f" +[[package]] +name = "fastrand" +version = "2.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "37909eebbb50d72f9059c3b6d82c0463f2ff062c9e95845c43a6c9c0355411be" + [[package]] name = "file_test_runner" version = "0.7.4" @@ -992,6 +963,16 @@ dependencies = [ "thiserror", ] +[[package]] +name = "flate2" +version = "1.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "843fba2746e448b37e26a819579957415c8cef339bf08564fe8b7ddbd959573c" +dependencies = [ + "crc32fast", + "miniz_oxide", +] + [[package]] name = "fnv" version = "1.0.7" @@ -1007,22 +988,6 @@ dependencies = [ "percent-encoding", ] -[[package]] -name = "from_variant" -version = "3.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e5ff35a391aef949120a0340d690269b3d9f63460a6106e99bd07b961f345ea9" -dependencies = [ - "swc_macros_common", - "syn", -] - -[[package]] -name = "funty" -version = "2.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6d5a32815ae3f33302d95fdcb2ce17862f8c65363dcfd29360480ba1001fc9c" - [[package]] name = "futures" version = "0.3.31" @@ -1163,19 +1128,18 @@ checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" [[package]] name = "hashbrown" -version = "0.14.5" +version = "0.15.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" -dependencies = [ - "ahash", - "allocator-api2", -] +checksum = "9229cfe53dfd69f0609a49f65461bd93001ea1ef889cd5529dd176593f5338a1" [[package]] name = "hashbrown" -version = "0.15.5" +version = "0.17.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9229cfe53dfd69f0609a49f65461bd93001ea1ef889cd5529dd176593f5338a1" +checksum = "ed5909b6e89a2db4456e54cd5f673791d7eca6732202bbf2a9cc504fe2f9b84a" +dependencies = [ + "allocator-api2", +] [[package]] name = "heck" @@ -1192,12 +1156,6 @@ dependencies = [ "libc", ] -[[package]] -name = "hermit-abi" -version = "0.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc0fef456e4baa96da950455cd02c081ca953b141298e41db3fc7e36b1da849c" - [[package]] name = "hipstr" version = "0.6.0" @@ -1210,26 +1168,21 @@ dependencies = [ ] [[package]] -name = "hstr" -version = "3.0.3" +name = "html-escape" +version = "0.2.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c43c0a9e8fbdb3bb9dc8eee85e1e2ac81605418b4c83b6b7413cbf14d56ca5c" +checksum = "6d1ad449764d627e22bfd7cd5e8868264fc9236e07c752972b4080cd351cb476" dependencies = [ - "hashbrown 0.14.5", - "new_debug_unreachable", - "once_cell", - "rustc-hash", - "serde", - "triomphe", + "utf8-width", ] [[package]] -name = "html-escape" -version = "0.2.13" +name = "hybrid-array" +version = "0.4.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d1ad449764d627e22bfd7cd5e8868264fc9236e07c752972b4080cd351cb476" +checksum = "9155a582abd142abc056962c29e3ce5ff2ad5469f4246b537ed42c5deba857da" dependencies = [ - "utf8-width", + "typenum", ] [[package]] @@ -1345,12 +1298,6 @@ dependencies = [ "icu_properties", ] -[[package]] -name = "if_chain" -version = "1.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cb56e1aa765b4b4f3aadfab769793b7087bb03a4ea4920644a6d238e2df5b9ed" - [[package]] name = "import_map" version = "0.25.0" @@ -1407,23 +1354,11 @@ version = "0.7.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "046fa2d4d00aea763528b4950358d0ead425372445dc8ff86312b3c69ff7727b" dependencies = [ - "bitflags 2.9.3", + "bitflags 2.11.0", "cfg-if", "libc", ] -[[package]] -name = "is-macro" -version = "0.3.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d57a3e447e24c22647738e4607f1df1e0ec6f72e16182c4cd199f647cdfb0e4" -dependencies = [ - "heck", - "proc-macro2", - "quote", - "syn", -] - [[package]] name = "is_terminal_polyfill" version = "1.70.2" @@ -1439,11 +1374,20 @@ dependencies = [ "either", ] +[[package]] +name = "itertools" +version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b192c782037fadd9cfa75548310488aabdbf3d2da73885b31bd0abd03351285" +dependencies = [ + "either", +] + [[package]] name = "itoa" -version = "1.0.15" +version = "1.0.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c" +checksum = "92ecc6618181def0457392ccd0ee51198e065e016d1d527a7ac1b6dc7c1f09d2" [[package]] name = "js-sys" @@ -1454,6 +1398,12 @@ dependencies = [ "wasm-bindgen", ] +[[package]] +name = "json-escape-simd" +version = "3.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a3c2a6c0b4b5637c41719973ef40c6a1cf564f9db6958350de6193fbee9c23f5" + [[package]] name = "lazy_static" version = "1.5.0" @@ -1490,9 +1440,9 @@ checksum = "13dc2df351e3202783a1fe0d44375f7295ffb4049267b0f3018346dc122a1d94" [[package]] name = "memchr" -version = "2.7.5" +version = "2.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32a282da65faaf38286cf3be983213fcf1d2e2a58700e808f83f4ea9a4804bc0" +checksum = "f8ca58f447f06ed17d5fc4043ce1b10dd205e060fb3ce5b979b8ed8e59ff3f79" [[package]] name = "miniz_oxide" @@ -1501,6 +1451,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1fa76a2c86f704bdb222d66965fb3d63269ce38518b83cb0575fca855ebb6316" dependencies = [ "adler2", + "simd-adler32", ] [[package]] @@ -1514,12 +1465,6 @@ dependencies = [ "windows-sys 0.59.0", ] -[[package]] -name = "monch" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b52c1b33ff98142aecea13138bd399b68aa7ab5d9546c300988c345004001eea" - [[package]] name = "monch" version = "0.6.0" @@ -1527,10 +1472,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6bcc6ad3b93f756f2532d29f7c7291b8d246a2c460a99a3611327bb726830014" [[package]] -name = "new_debug_unreachable" -version = "1.0.6" +name = "nonmax" +version = "0.5.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "650eef8c711430f1a879fdd01d4745a7deea475becfb90269c06775983bbf086" +checksum = "610a5acd306ec67f907abe5567859a3c693fb9886eb1f012ab8f2a47bef3db51" [[package]] name = "num-bigint" @@ -1540,7 +1485,6 @@ checksum = "a5e44f723f1133c9deac646763579fdb3ac745e418f2a7af9cd0c431da1f20b9" dependencies = [ "num-integer", "num-traits", - "serde", ] [[package]] @@ -1576,16 +1520,6 @@ dependencies = [ "autocfg", ] -[[package]] -name = "num_cpus" -version = "1.17.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "91df4bbde75afed763b708b7eee1e8e7651e02d97f6d5dd763e89367e957b23b" -dependencies = [ - "hermit-abi 0.5.2", - "libc", -] - [[package]] name = "object" version = "0.36.7" @@ -1626,72 +1560,457 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1a80800c0488c3a21695ea981a54918fbb37abf04f4d0720c453632255e2ff0e" [[package]] -name = "par-core" -version = "2.0.0" +name = "owo-colors" +version = "4.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d211803b9b6b570f68772237e415a029d5a50c65d382910b879fb19d3271f94d" + +[[package]] +name = "oxc" +version = "0.134.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e96cbd21255b7fb29a5d51ef38a779b517a91abd59e2756c039583f43ef4c90f" +checksum = "d804f86548486ce1b6c92bb5511214f44074ea1e5bc94eded8ee4de2f7ca98c7" dependencies = [ - "once_cell", + "oxc_allocator", + "oxc_ast", + "oxc_ast_visit", + "oxc_codegen", + "oxc_diagnostics", + "oxc_parser", + "oxc_regular_expression", + "oxc_semantic", + "oxc_span", + "oxc_syntax", + "oxc_transformer", + "oxc_transformer_plugins", ] [[package]] -name = "parking_lot" -version = "0.12.4" +name = "oxc-browserslist" +version = "3.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70d58bf43669b5795d1576d0641cfb6fbb2057bf629506267a92807158584a13" +checksum = "c86f358f5705f4da4bce0af2792b6d24d64be9c465bdc70a752b2f168c5ff721" dependencies = [ - "lock_api", - "parking_lot_core", + "flate2", + "postcard", + "rustc-hash", + "serde", + "thiserror", ] [[package]] -name = "parking_lot_core" -version = "0.9.11" +name = "oxc-miette" +version = "2.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc838d2a56b5b1a6c25f55575dfc605fabb63bb2365f6c2353ef9159aa69e4a5" +checksum = "4356a61f2ed4c9b3610245215fbf48970eb277126919f87db9d0efa93a74245c" dependencies = [ "cfg-if", - "libc", - "redox_syscall", - "smallvec", - "windows-targets 0.52.6", + "owo-colors", + "oxc-miette-derive", + "textwrap", + "thiserror", + "unicode-segmentation", + "unicode-width 0.2.1", ] [[package]] -name = "pathdiff" -version = "0.2.3" +name = "oxc-miette-derive" +version = "2.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "df94ce210e5bc13cb6651479fa48d14f601d9858cfe0467f43ae157023b938d3" +checksum = "b237422b014f8f8fff75bb9379e697d13f8d57551a22c88bebb39f073c1bf696" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] [[package]] -name = "percent-encoding" -version = "2.3.2" +name = "oxc_allocator" +version = "0.134.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b4f627cb1b25917193a259e49bdad08f671f8d9708acfd5fe0a8c1455d87220" +checksum = "2303e54d087d40064154f2ec243fff0bf7641c078efae9bb14216a8869577ba7" +dependencies = [ + "allocator-api2", + "hashbrown 0.17.1", + "oxc_data_structures", + "rustc-hash", +] [[package]] -name = "pest" -version = "2.8.1" +name = "oxc_ast" +version = "0.134.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1db05f56d34358a8b1066f67cbb203ee3e7ed2ba674a6263a1d5ec6db2204323" +checksum = "5f628429436867a51e5d623b4b27c02807aec3ea241f01deadd21b0d1604c8ef" dependencies = [ - "memchr", - "thiserror", - "ucd-trie", + "bitflags 2.11.0", + "oxc_allocator", + "oxc_ast_macros", + "oxc_data_structures", + "oxc_diagnostics", + "oxc_estree", + "oxc_regular_expression", + "oxc_span", + "oxc_str", + "oxc_syntax", ] [[package]] -name = "pest_derive" -version = "2.8.1" +name = "oxc_ast_macros" +version = "0.134.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bb056d9e8ea77922845ec74a1c4e8fb17e7c218cc4fc11a15c5d25e189aa40bc" +checksum = "52b3190e5f69284b59a4876a3b42431c8e2309b4de3670553aab4888f15aa6f2" dependencies = [ - "pest", - "pest_generator", + "phf", + "proc-macro2", + "quote", + "syn", ] [[package]] -name = "pest_generator" +name = "oxc_ast_visit" +version = "0.134.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dfe1897cf38bab83c998346184cba50db2849943b9d9e8634d09a2dc303ceaee" +dependencies = [ + "oxc_allocator", + "oxc_ast", + "oxc_span", + "oxc_syntax", +] + +[[package]] +name = "oxc_codegen" +version = "0.134.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b7d690df0e909b1663c19a368cdfcf0cac94fd57ddf068230442ff82b27ad000" +dependencies = [ + "bitflags 2.11.0", + "cow-utils", + "dragonbox_ecma", + "itoa", + "oxc_allocator", + "oxc_ast", + "oxc_data_structures", + "oxc_index", + "oxc_semantic", + "oxc_sourcemap", + "oxc_span", + "oxc_str", + "oxc_syntax", + "rustc-hash", +] + +[[package]] +name = "oxc_compat" +version = "0.134.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ae9249b8fc4604f787cbe39457565f21f7747a59cb94333bcc1ff85f9327323" +dependencies = [ + "cow-utils", + "oxc-browserslist", + "oxc_syntax", + "rustc-hash", + "serde", +] + +[[package]] +name = "oxc_data_structures" +version = "0.134.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb6aa082cf4bbc5b3c189e9331f31823e31a5452533da36dfa5b174f20e72c1c" +dependencies = [ + "ropey", +] + +[[package]] +name = "oxc_diagnostics" +version = "0.134.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67daf165d8abff1577825a4303a5d0b61ae29c7b66c9e0e0e7f97f77705667ed" +dependencies = [ + "cow-utils", + "oxc-miette", + "percent-encoding", +] + +[[package]] +name = "oxc_ecmascript" +version = "0.134.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41e701220c14cc0d0733a6501f1837fe9d913e891e25647132389fdfd78dd7d3" +dependencies = [ + "cow-utils", + "num-bigint", + "num-traits", + "oxc_allocator", + "oxc_ast", + "oxc_regular_expression", + "oxc_span", + "oxc_syntax", +] + +[[package]] +name = "oxc_estree" +version = "0.134.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f3d42104865cba688a62c0cf5691592a890eef9de359bccb18a97b2be088478d" + +[[package]] +name = "oxc_index" +version = "4.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eb3e6120999627ec9703025eab7c9f410ebb7e95557632a8902ca48210416c2b" +dependencies = [ + "nonmax", + "serde", +] + +[[package]] +name = "oxc_parser" +version = "0.134.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "02d671cb199fc83d8fc9764926c3c8f7979affbd2d916e3b2e22e403745305b6" +dependencies = [ + "bitflags 2.11.0", + "cow-utils", + "memchr", + "num-bigint", + "num-traits", + "oxc_allocator", + "oxc_ast", + "oxc_data_structures", + "oxc_diagnostics", + "oxc_ecmascript", + "oxc_regular_expression", + "oxc_span", + "oxc_str", + "oxc_syntax", + "rustc-hash", + "seq-macro", +] + +[[package]] +name = "oxc_regular_expression" +version = "0.134.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a06eb61d28a8b83b0bda7dc75bf886f178155dead57746fab874312c81baa359" +dependencies = [ + "bitflags 2.11.0", + "oxc_allocator", + "oxc_ast_macros", + "oxc_diagnostics", + "oxc_span", + "oxc_str", + "phf", + "rustc-hash", + "unicode-id-start", +] + +[[package]] +name = "oxc_semantic" +version = "0.134.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8573ff803b00bdacc550475aacc72305621d2992988e5f7886391fa9d9bfa611" +dependencies = [ + "itertools 0.14.0", + "memchr", + "oxc_allocator", + "oxc_ast", + "oxc_ast_visit", + "oxc_diagnostics", + "oxc_ecmascript", + "oxc_index", + "oxc_span", + "oxc_str", + "oxc_syntax", + "rustc-hash", + "self_cell", + "smallvec", +] + +[[package]] +name = "oxc_sourcemap" +version = "7.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db3866f9075027840e0711b52e15d2e1ba076fc5f5f01c96eeedd26375410641" +dependencies = [ + "base64-simd", + "json-escape-simd", + "rustc-hash", + "serde", + "serde_json", +] + +[[package]] +name = "oxc_span" +version = "0.134.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "35ff77b2ca10d57dc7645c4af838b1aa455cac6569992fe544ed041a8021ae10" +dependencies = [ + "compact_str", + "oxc-miette", + "oxc_allocator", + "oxc_ast_macros", + "oxc_estree", + "oxc_str", +] + +[[package]] +name = "oxc_str" +version = "0.134.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dbcd6412fde266b6ffdbcdf118cba2c8dc0d6ddba6aa4e361842ebaf320a4eed" +dependencies = [ + "compact_str", + "hashbrown 0.17.1", + "oxc_allocator", + "oxc_estree", +] + +[[package]] +name = "oxc_syntax" +version = "0.134.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ab19e002e05e4d107483ace848ca2d6ce5c714f238d70d591f91d17fef54be98" +dependencies = [ + "bitflags 2.11.0", + "cow-utils", + "dragonbox_ecma", + "nonmax", + "oxc_allocator", + "oxc_ast_macros", + "oxc_estree", + "oxc_index", + "oxc_span", + "oxc_str", + "phf", + "unicode-id-start", +] + +[[package]] +name = "oxc_transformer" +version = "0.134.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c753c4eb41524071c4d13650642b5622b7b23fca6b4d92872dc43f6e71686e16" +dependencies = [ + "base64", + "compact_str", + "indexmap 2.11.0", + "itoa", + "memchr", + "oxc_allocator", + "oxc_ast", + "oxc_ast_visit", + "oxc_compat", + "oxc_data_structures", + "oxc_diagnostics", + "oxc_ecmascript", + "oxc_regular_expression", + "oxc_semantic", + "oxc_span", + "oxc_str", + "oxc_syntax", + "oxc_traverse", + "rustc-hash", + "serde", + "serde_json", + "sha1", +] + +[[package]] +name = "oxc_transformer_plugins" +version = "0.134.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0dbd5a19932bc3aded01f5f2ff18f448cadbd921b26cffa2b90294fd1a44f4ce" +dependencies = [ + "cow-utils", + "itoa", + "oxc_allocator", + "oxc_ast", + "oxc_ast_visit", + "oxc_diagnostics", + "oxc_ecmascript", + "oxc_parser", + "oxc_semantic", + "oxc_span", + "oxc_str", + "oxc_syntax", + "oxc_transformer", + "oxc_traverse", + "rustc-hash", +] + +[[package]] +name = "oxc_traverse" +version = "0.134.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d817fd3459ecb0c0ea37042e796954d8caff9a6c5e23bf60a41f002cacdd5c79" +dependencies = [ + "itoa", + "oxc_allocator", + "oxc_ast", + "oxc_ast_visit", + "oxc_data_structures", + "oxc_ecmascript", + "oxc_semantic", + "oxc_span", + "oxc_str", + "oxc_syntax", + "rustc-hash", +] + +[[package]] +name = "parking_lot" +version = "0.12.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "70d58bf43669b5795d1576d0641cfb6fbb2057bf629506267a92807158584a13" +dependencies = [ + "lock_api", + "parking_lot_core", +] + +[[package]] +name = "parking_lot_core" +version = "0.9.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bc838d2a56b5b1a6c25f55575dfc605fabb63bb2365f6c2353ef9159aa69e4a5" +dependencies = [ + "cfg-if", + "libc", + "redox_syscall", + "smallvec", + "windows-targets 0.52.6", +] + +[[package]] +name = "percent-encoding" +version = "2.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b4f627cb1b25917193a259e49bdad08f671f8d9708acfd5fe0a8c1455d87220" + +[[package]] +name = "pest" +version = "2.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1db05f56d34358a8b1066f67cbb203ee3e7ed2ba674a6263a1d5ec6db2204323" +dependencies = [ + "memchr", + "thiserror", + "ucd-trie", +] + +[[package]] +name = "pest_derive" +version = "2.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bb056d9e8ea77922845ec74a1c4e8fb17e7c218cc4fc11a15c5d25e189aa40bc" +dependencies = [ + "pest", + "pest_generator", +] + +[[package]] +name = "pest_generator" version = "2.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "87e404e638f781eb3202dc82db6760c8ae8a1eeef7fb3fa8264b2ef280504966" @@ -1715,29 +2034,30 @@ dependencies = [ [[package]] name = "phf" -version = "0.11.3" +version = "0.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1fd6780a80ae0c52cc120a26a1a42c1ae51b247a253e4e06113d23d2c2edd078" +checksum = "c1562dc717473dbaa4c1f85a36410e03c047b2e7df7f45ee938fbef64ae7fadf" dependencies = [ "phf_macros", "phf_shared", + "serde", ] [[package]] name = "phf_generator" -version = "0.11.3" +version = "0.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c80231409c20246a13fddb31776fb942c38553c51e871f8cbd687a4cfb5843d" +checksum = "135ace3a761e564ec88c03a77317a7c6b80bb7f7135ef2544dbe054243b89737" dependencies = [ + "fastrand", "phf_shared", - "rand", ] [[package]] name = "phf_macros" -version = "0.11.3" +version = "0.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f84ac04429c13a7ff43785d75ad27569f2951ce0ffd30a3321230db2fc727216" +checksum = "812f032b54b1e759ccd5f8b6677695d5268c588701effba24601f6932f8269ef" dependencies = [ "phf_generator", "phf_shared", @@ -1748,11 +2068,11 @@ dependencies = [ [[package]] name = "phf_shared" -version = "0.11.3" +version = "0.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "67eabc2ef2a60eb7faa00097bd1ffdb5bd28e62bf39990626a582201b7a754e5" +checksum = "e57fef6bc5981e38c2ce2d63bfa546861309f875b8a75f092d1d54ae2d64f266" dependencies = [ - "siphasher 1.0.1", + "siphasher", ] [[package]] @@ -1795,6 +2115,18 @@ dependencies = [ "plotters-backend", ] +[[package]] +name = "postcard" +version = "1.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6764c3b5dd454e283a30e6dfe78e9b31096d9e32036b5d1eaac7a6119ccb9a24" +dependencies = [ + "cobs", + "embedded-io 0.4.0", + "embedded-io 0.6.1", + "serde", +] + [[package]] name = "potential_utf" version = "0.1.2" @@ -1823,15 +2155,6 @@ dependencies = [ "unicode-ident", ] -[[package]] -name = "psm" -version = "0.1.26" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e944464ec8536cd1beb0bbfd96987eb5e3b72f2ecdafdc5c769a37f1fa2ae1f" -dependencies = [ - "cc", -] - [[package]] name = "quote" version = "1.0.40" @@ -1841,27 +2164,6 @@ dependencies = [ "proc-macro2", ] -[[package]] -name = "radium" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc33ff2d4973d518d823d61aa239014831e521c75da58e3df4840d3f47749d09" - -[[package]] -name = "rand" -version = "0.8.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" -dependencies = [ - "rand_core", -] - -[[package]] -name = "rand_core" -version = "0.6.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" - [[package]] name = "rayon" version = "1.11.0" @@ -1888,7 +2190,7 @@ version = "0.5.17" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5407465600fb0548f1442edf71dd20683c6ed326200ace4b1ef0763521bb3b77" dependencies = [ - "bitflags 2.9.3", + "bitflags 2.11.0", ] [[package]] @@ -1920,6 +2222,16 @@ version = "0.8.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "caf4aa5b0f434c91fe5c7f1ecb6a5ece2130b02ad2a590589dda5146df959001" +[[package]] +name = "ropey" +version = "1.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93411e420bcd1a75ddd1dc3caf18c23155eda2c090631a85af21ba19e97093b5" +dependencies = [ + "smallvec", + "str_indices", +] + [[package]] name = "rustc-demangle" version = "0.1.26" @@ -1944,12 +2256,6 @@ version = "1.0.20" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "28d3b2b1366ec20994f1fd18c3c594f05c5dd4bc44d8bb0c1c632c8d6829481f" -[[package]] -name = "ryu-js" -version = "1.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd29631678d6fb0903b69223673e122c32e9ae559d0960a38d574695ebc0ea15" - [[package]] name = "same-file" version = "1.0.6" @@ -1959,18 +2265,18 @@ dependencies = [ "winapi-util", ] -[[package]] -name = "scoped-tls" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e1cf6437eb19a8f4a6cc0f7dca544973b0b78843adbfeb3683d1a94a0024a294" - [[package]] name = "scopeguard" version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" +[[package]] +name = "self_cell" +version = "1.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b12e76d157a900eb52e81bc6e9f3069344290341720e9178cde2407113ac8d89" + [[package]] name = "seq-macro" version = "0.3.6" @@ -2041,21 +2347,26 @@ dependencies = [ ] [[package]] -name = "sha2" -version = "0.10.9" +name = "sha1" +version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a7507d819769d01a365ab707794a4084392c824f54a7a6a7862f8c3d0892b283" +checksum = "aacc4cc499359472b4abe1bf11d0b12e688af9a805fa5e3016f9a386dc2d0214" dependencies = [ "cfg-if", - "cpufeatures", - "digest", + "cpufeatures 0.3.0", + "digest 0.11.3", ] [[package]] -name = "shlex" -version = "1.3.0" +name = "sha2" +version = "0.10.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" +checksum = "a7507d819769d01a365ab707794a4084392c824f54a7a6a7862f8c3d0892b283" +dependencies = [ + "cfg-if", + "cpufeatures 0.2.17", + "digest 0.10.7", +] [[package]] name = "signal-hook-registry" @@ -2067,16 +2378,16 @@ dependencies = [ ] [[package]] -name = "similar" -version = "2.7.0" +name = "simd-adler32" +version = "0.3.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbbb5d9659141646ae647b42fe094daf6c6192d1620870b449d9557f748b2daa" +checksum = "e320a6c5ad31d271ad523dcf3ad13e2767ad8b1cb8f047f75a8aeaf8da139da2" [[package]] -name = "siphasher" -version = "0.3.11" +name = "similar" +version = "2.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38b58827f4464d87d377d175e90bf58eb00fd8716ff0a62f80356b5e61555d0d" +checksum = "bbbb5d9659141646ae647b42fe094daf6c6192d1620870b449d9557f748b2daa" [[package]] name = "siphasher" @@ -2105,17 +2416,15 @@ name = "smallvec" version = "1.15.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03" +dependencies = [ + "serde", +] [[package]] -name = "smartstring" -version = "1.0.1" +name = "smawk" +version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3fb72c633efbaa2dd666986505016c32c3044395ceaf881518399d2f4127ee29" -dependencies = [ - "autocfg", - "static_assertions", - "version_check", -] +checksum = "b7c388c1b5e93756d0c740965c41e8822f866621d41acbdf6336a6a168f8840c" [[package]] name = "socket2" @@ -2139,19 +2448,6 @@ version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" -[[package]] -name = "stacker" -version = "0.1.21" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cddb07e32ddb770749da91081d8d0ac3a16f1a569a18b20348cd371f5dead06b" -dependencies = [ - "cc", - "cfg-if", - "libc", - "psm", - "windows-sys 0.59.0", -] - [[package]] name = "static_assertions" version = "1.1.0" @@ -2159,15 +2455,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" [[package]] -name = "string_enum" -version = "1.0.2" +name = "str_indices" +version = "0.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ae36a4951ca7bd1cfd991c241584a9824a70f6aff1e7d4f693fb3f2465e4030e" -dependencies = [ - "quote", - "swc_macros_common", - "syn", -] +checksum = "d08889ec5408683408db66ad89e0e1f93dff55c73a4ccc71c427d5b277ee47e6" [[package]] name = "strsim" @@ -2175,276 +2466,6 @@ version = "0.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" -[[package]] -name = "swc_allocator" -version = "4.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d7eefd2c8b228a8c73056482b2ae4b3a1071fbe07638e3b55ceca8570cc48bb" -dependencies = [ - "allocator-api2", - "bumpalo", - "hashbrown 0.14.5", - "rustc-hash", -] - -[[package]] -name = "swc_atoms" -version = "9.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d4ccbe2ecad10ad7432100f878a107b1d972a8aee83ca53184d00c23a078bb8a" -dependencies = [ - "hstr", - "once_cell", - "serde", -] - -[[package]] -name = "swc_common" -version = "17.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "259b675d633a26d24efe3802a9d88858c918e6e8f062d3222d3aa02d56a2cf4c" -dependencies = [ - "anyhow", - "ast_node", - "better_scoped_tls", - "bytes-str", - "either", - "from_variant", - "new_debug_unreachable", - "num-bigint", - "once_cell", - "rustc-hash", - "serde", - "siphasher 0.3.11", - "swc_atoms", - "swc_eq_ignore_macros", - "swc_sourcemap", - "swc_visit", - "tracing", - "unicode-width 0.2.1", - "url", -] - -[[package]] -name = "swc_ecma_ast" -version = "18.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a573a0c72850dec8d4d8085f152d5778af35a2520c3093b242d2d1d50776da7c" -dependencies = [ - "bitflags 2.9.3", - "is-macro", - "num-bigint", - "once_cell", - "phf", - "rustc-hash", - "serde", - "string_enum", - "swc_atoms", - "swc_common", - "swc_visit", - "unicode-id-start", -] - -[[package]] -name = "swc_ecma_codegen" -version = "20.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ff2a6ee1ec49dda8dedeac54e4147b4e8b3f278d9bb34ab28983257a393d34ed" -dependencies = [ - "ascii", - "compact_str", - "memchr", - "num-bigint", - "once_cell", - "regex", - "rustc-hash", - "ryu-js", - "serde", - "swc_allocator", - "swc_atoms", - "swc_common", - "swc_ecma_ast", - "swc_ecma_codegen_macros", - "swc_sourcemap", - "tracing", -] - -[[package]] -name = "swc_ecma_codegen_macros" -version = "2.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e276dc62c0a2625a560397827989c82a93fd545fcf6f7faec0935a82cc4ddbb8" -dependencies = [ - "proc-macro2", - "swc_macros_common", - "syn", -] - -[[package]] -name = "swc_ecma_lexer" -version = "26.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5e82f7747e052c6ff6e111fa4adeb14e33b46ee6e94fe5ef717601f651db48fc" -dependencies = [ - "bitflags 2.9.3", - "either", - "num-bigint", - "rustc-hash", - "seq-macro", - "serde", - "smallvec", - "smartstring", - "stacker", - "swc_atoms", - "swc_common", - "swc_ecma_ast", - "swc_ecma_parser", - "tracing", -] - -[[package]] -name = "swc_ecma_loader" -version = "17.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fbcababb48f0d46587a0a854b2c577eb3a56fa99687de558338021e93cd2c8f5" -dependencies = [ - "anyhow", - "pathdiff", - "rustc-hash", - "serde", - "swc_atoms", - "swc_common", - "tracing", -] - -[[package]] -name = "swc_ecma_parser" -version = "27.0.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f1a51af1a92cd4904c073b293e491bbc0918400a45d58227b34c961dd6f52d7" -dependencies = [ - "bitflags 2.9.3", - "either", - "num-bigint", - "phf", - "rustc-hash", - "seq-macro", - "serde", - "smartstring", - "stacker", - "swc_atoms", - "swc_common", - "swc_ecma_ast", - "tracing", -] - -[[package]] -name = "swc_ecma_transforms_base" -version = "30.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "250f6f165578ca4fee47bd57585c1b9597c94bf4ea6591df47f2b5fa5b1883fe" -dependencies = [ - "better_scoped_tls", - "indexmap 2.11.0", - "once_cell", - "par-core", - "phf", - "rustc-hash", - "serde", - "swc_atoms", - "swc_common", - "swc_ecma_ast", - "swc_ecma_parser", - "swc_ecma_utils", - "swc_ecma_visit", - "tracing", -] - -[[package]] -name = "swc_ecma_utils" -version = "24.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fb99e179988cabd473779a4452ab942bcb777176983ca3cbaf22a8f056a65b0" -dependencies = [ - "indexmap 2.11.0", - "num_cpus", - "once_cell", - "par-core", - "rustc-hash", - "ryu-js", - "swc_atoms", - "swc_common", - "swc_ecma_ast", - "swc_ecma_visit", - "tracing", -] - -[[package]] -name = "swc_ecma_visit" -version = "18.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a9611a72a4008d62608547a394e5d72a5245413104db096d95a52368a8cc1d63" -dependencies = [ - "new_debug_unreachable", - "num-bigint", - "swc_atoms", - "swc_common", - "swc_ecma_ast", - "swc_visit", - "tracing", -] - -[[package]] -name = "swc_eq_ignore_macros" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c16ce73424a6316e95e09065ba6a207eba7765496fed113702278b7711d4b632" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "swc_macros_common" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aae1efbaa74943dc5ad2a2fb16cbd78b77d7e4d63188f3c5b4df2b4dcd2faaae" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "swc_sourcemap" -version = "9.3.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "de08ef00f816acdd1a58ee8a81c0e1a59eefef2093aefe5611f256fa6b64c4d7" -dependencies = [ - "base64-simd", - "bitvec", - "bytes-str", - "data-encoding", - "debugid", - "if_chain", - "rustc-hash", - "serde", - "serde_json", - "unicode-id-start", - "url", -] - -[[package]] -name = "swc_visit" -version = "2.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62fb71484b486c185e34d2172f0eabe7f4722742aad700f426a494bb2de232a2" -dependencies = [ - "either", - "new_debug_unreachable", -] - [[package]] name = "syn" version = "2.0.106" @@ -2487,12 +2508,6 @@ dependencies = [ "syn", ] -[[package]] -name = "tap" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369" - [[package]] name = "termcolor" version = "1.4.1" @@ -2516,6 +2531,11 @@ name = "textwrap" version = "0.16.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c13547615a44dc9c452a8a534638acdf07120d4b6847c8178705da06306a3057" +dependencies = [ + "smawk", + "unicode-linebreak", + "unicode-width 0.2.1", +] [[package]] name = "thiserror" @@ -2603,47 +2623,6 @@ dependencies = [ "syn", ] -[[package]] -name = "tracing" -version = "0.1.41" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "784e0ac535deb450455cbfa28a6f0df145ea1bb7ae51b821cf5e7927fdcfbdd0" -dependencies = [ - "pin-project-lite", - "tracing-attributes", - "tracing-core", -] - -[[package]] -name = "tracing-attributes" -version = "0.1.30" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81383ab64e72a7a8b8e13130c49e3dab29def6d0c7d76a03087b3cf71c5c6903" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "tracing-core" -version = "0.1.34" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b9d12581f227e93f094d3af2ae690a574abb8a2b9b7a96e7cfe9647b2b617678" -dependencies = [ - "once_cell", -] - -[[package]] -name = "triomphe" -version = "0.1.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ef8f7726da4807b58ea5c96fdc122f80702030edc33b35aff9190a51148ccc85" -dependencies = [ - "serde", - "stable_deref_trait", -] - [[package]] name = "typed-arena" version = "2.0.2" @@ -2652,9 +2631,9 @@ checksum = "6af6ae20167a9ece4bcb41af5b80f8a1f1df981f6391189ce00fd257af04126a" [[package]] name = "typenum" -version = "1.18.0" +version = "1.20.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1dccffe3ce07af9386bfd29e80c0ab1a8205a2fc34e4bcd40364df902cfa8f3f" +checksum = "b6f5e870be6c3b371b77fe0ee0bafb859fa4964b4404c27de1d380043c4dda20" [[package]] name = "ucd-trie" @@ -2674,6 +2653,12 @@ version = "1.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512" +[[package]] +name = "unicode-linebreak" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3b09c83c3c29d37506a3e260c08c03743a6bb66a9cd432c6934ab501a190571f" + [[package]] name = "unicode-normalization" version = "0.1.24" @@ -2683,6 +2668,12 @@ dependencies = [ "tinyvec", ] +[[package]] +name = "unicode-segmentation" +version = "1.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f6ccf251212114b54433ec949fd6a7841275f9ada20dddd2f29e9ceea4501493" + [[package]] name = "unicode-width" version = "0.1.14" @@ -2731,12 +2722,6 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" -[[package]] -name = "uuid" -version = "1.16.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "458f7a779bf54acc9f347480ac654f68407d3aab21269a6e3c9f922acd9e2da9" - [[package]] name = "version_check" version = "0.9.5" @@ -3062,15 +3047,6 @@ version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ea2f10b9bb0928dfb1b42b65e1f9e36f7f54dbdf08457afefb38afcdec4fa2bb" -[[package]] -name = "wyz" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05f360fc0b24296329c78fda852a1e9ae82de9cf7b27dae4b7f62f118f77b9ed" -dependencies = [ - "tap", -] - [[package]] name = "yansi" version = "1.0.1" @@ -3101,26 +3077,6 @@ dependencies = [ "synstructure", ] -[[package]] -name = "zerocopy" -version = "0.8.26" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1039dd0d3c310cf05de012d8a39ff557cb0d23087fd44cad61df08fc31907a2f" -dependencies = [ - "zerocopy-derive", -] - -[[package]] -name = "zerocopy-derive" -version = "0.8.26" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ecf5b4cc5364572d7f4c329661bcc82724222973f2cab6f050a4e5c22f75181" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - [[package]] name = "zerofrom" version = "0.1.6" diff --git a/Cargo.toml b/Cargo.toml index 6bc2e70a9..5400e0957 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -11,15 +11,18 @@ repository = "https://github.com/denoland/deno_doc" members = ["lib"] [workspace.dependencies] -deno_graph = { version = "0.108.0", default-features = false, features = [ +deno_graph = { path = "../deno_graph", default-features = false, features = [ "swc", "symbols", ] } -deno_ast = { version = "0.53.2" } +deno_ast = { path = "../deno_ast" } import_map = "0.25.0" serde = { version = "1.0.204", features = ["derive"] } serde_json = { version = "1.0.122", features = ["preserve_order"] } +[patch."https://github.com/nathanwhit/deno_ast"] +deno_ast = { path = "../deno_ast" } + [lib] name = "deno_doc" diff --git a/benches/doc_parser.rs b/benches/doc_parser.rs index 55b70f093..bce1dc340 100644 --- a/benches/doc_parser.rs +++ b/benches/doc_parser.rs @@ -42,10 +42,17 @@ async fn parse() -> ParseOutput { }, ) .await; - DocParser::new(&graph, &analyzer, &[root], DocParserOptions::default()) - .unwrap() - .parse() - .unwrap() + let allocator = deno_ast::oxc::allocator::Allocator::default(); + DocParser::new( + &graph, + &analyzer, + &allocator, + &[root], + DocParserOptions::default(), + ) + .unwrap() + .parse() + .unwrap() } fn doc_parser(c: &mut Criterion) { diff --git a/examples/ddoc/main.rs b/examples/ddoc/main.rs index 4478e3f69..06ac4aafd 100644 --- a/examples/ddoc/main.rs +++ b/examples/ddoc/main.rs @@ -161,9 +161,11 @@ async fn parse_sources( let mut source_files = source_files; source_files.sort(); + let allocator = deno_ast::oxc::allocator::Allocator::default(); let parser = DocParser::new( &graph, &analyzer, + &allocator, &source_files, DocParserOptions { diagnostics: false, diff --git a/lib/lib.rs b/lib/lib.rs index 1253e9889..b03e9a071 100644 --- a/lib/lib.rs +++ b/lib/lib.rs @@ -269,9 +269,11 @@ async fn inner_doc( }, ) .await; + let allocator = deno_doc::OxcAllocator::default(); let entries = DocParser::new( &graph, &analyzer, + &allocator, &root_specifiers, deno_doc::DocParserOptions { diagnostics: false, diff --git a/rust-toolchain.toml b/rust-toolchain.toml index 908d2ecba..1a2165581 100644 --- a/rust-toolchain.toml +++ b/rust-toolchain.toml @@ -1,3 +1,3 @@ [toolchain] -channel = "1.89.0" +channel = "1.92.0" components = ["rustfmt", "clippy"] diff --git a/src/class.rs b/src/class.rs index 801fd5d00..207e78068 100644 --- a/src/class.rs +++ b/src/class.rs @@ -1,6 +1,12 @@ // Copyright 2018-2024 the Deno authors. All rights reserved. MIT license. -use deno_ast::SourceRangedForSpanned; +use deno_ast::oxc::ast::ast::Class; +use deno_ast::oxc::ast::ast::ClassElement; +use deno_ast::oxc::ast::ast::Expression; +use deno_ast::oxc::ast::ast::MethodDefinitionKind; +use deno_ast::oxc::ast::ast::MethodDefinitionType; +use deno_ast::oxc::ast::ast::PropertyDefinitionType; +use deno_ast::oxc::span::GetSpan; use deno_graph::symbols::EsModuleInfo; use serde::Deserialize; use serde::Serialize; @@ -14,11 +20,9 @@ use crate::function::function_to_function_def; use crate::js_doc::JsDoc; use crate::node::DeclarationKind; use crate::node::Symbol; -use crate::params::assign_pat_to_param_def; -use crate::params::ident_to_param_def; +use crate::params::ParamPatternDef; use crate::params::param_to_param_def; use crate::params::prop_name_to_string; -use crate::params::ts_fn_param_to_param_def; use crate::ts_type::IndexSignatureDef; use crate::ts_type::TsTypeDef; use crate::ts_type::infer_ts_type_from_expr; @@ -28,6 +32,9 @@ use crate::ts_type_param::maybe_type_param_decl_to_type_param_defs; use crate::util::swc::get_location; use crate::util::swc::is_false; use crate::util::swc::js_doc_for_range; +use crate::util::types::Accessibility; +use crate::util::types::MethodKind; +use crate::util::types::VarDeclKind; use crate::variable::VariableDef; cfg_if! { @@ -54,7 +61,7 @@ cfg_if! { #[serde(rename_all = "camelCase")] pub struct ClassConstructorParamDef { #[serde(skip_serializing_if = "Option::is_none", default)] - pub accessibility: Option, + pub accessibility: Option, #[serde(skip_serializing_if = "is_false", default)] pub is_override: bool, #[serde(flatten)] @@ -83,7 +90,7 @@ pub struct ClassConstructorDef { #[serde(skip_serializing_if = "JsDoc::is_empty", default)] pub js_doc: JsDoc, #[serde(skip_serializing_if = "Option::is_none", default)] - pub accessibility: Option, + pub accessibility: Option, #[serde(skip_serializing_if = "is_false", default)] pub is_optional: bool, #[serde(skip_serializing_if = "is_false", default)] @@ -116,7 +123,7 @@ pub struct ClassPropertyDef { #[serde(skip_serializing_if = "is_false", default)] pub readonly: bool, #[serde(skip_serializing_if = "Option::is_none", default)] - pub accessibility: Option, + pub accessibility: Option, #[serde(skip_serializing_if = "<[_]>::is_empty", default)] pub decorators: Box<[DecoratorDef]>, #[serde(skip_serializing_if = "is_false", default)] @@ -141,7 +148,7 @@ impl From for Symbol { def.js_doc, VariableDef { ts_type: def.ts_type, - kind: deno_ast::swc::ast::VarDeclKind::Const, + kind: VarDeclKind::Const, }, ) } @@ -174,7 +181,7 @@ pub struct ClassMethodDef { #[serde(skip_serializing_if = "JsDoc::is_empty", default)] pub js_doc: JsDoc, #[serde(skip_serializing_if = "Option::is_none", default)] - pub accessibility: Option, + pub accessibility: Option, #[serde(skip_serializing_if = "is_false", default)] pub optional: bool, #[serde(skip_serializing_if = "is_false", default)] @@ -184,7 +191,7 @@ pub struct ClassMethodDef { #[serde(skip_serializing_if = "is_false", default)] pub is_override: bool, pub name: Box, - pub kind: deno_ast::swc::ast::MethodKind, + pub kind: MethodKind, pub function_def: FunctionDef, pub location: Location, } @@ -256,22 +263,20 @@ pub struct ClassDef { pub fn class_to_class_def( module_info: &EsModuleInfo, - class: &deno_ast::swc::ast::Class, + class: &Class, def_name: Option>, ) -> (ClassDef, JsDoc) { - use deno_ast::swc::ast::Expr; - let mut constructors = vec![]; let mut methods = vec![]; let mut properties = vec![]; let mut index_signatures = vec![]; - fn walk_class_extends(expr: &Expr) -> Option { + fn walk_class_extends(expr: &Expression) -> Option { match expr { - Expr::Ident(ident) => Some(ident.sym.to_string()), - Expr::Member(member_expr) => { - let prop = &member_expr.prop.as_ident()?.sym; - let mut string_path = walk_class_extends(&member_expr.obj)?; + Expression::Identifier(ident) => Some(ident.name.to_string()), + Expression::StaticMemberExpression(member_expr) => { + let prop = &member_expr.property.name; + let mut string_path = walk_class_extends(&member_expr.object)?; string_path.push('.'); string_path.push_str(prop); @@ -284,7 +289,7 @@ pub fn class_to_class_def( let extends: Option> = match &class.super_class { Some(boxed) => { - let expr: &Expr = boxed; + let expr: &Expression = boxed; walk_class_extends(expr).map(|s| s.into_boxed_str()) } None => None, @@ -293,94 +298,91 @@ pub fn class_to_class_def( let implements = class .implements .iter() - .map(|expr| TsTypeDef::ts_expr_with_type_args(module_info, expr)) + .map(|expr| TsTypeDef::ts_class_implements(module_info, expr)) .collect::>(); - for member in &class.body { - use deno_ast::swc::ast::ClassMember::*; - + for member in &class.body.body { match member { - Constructor(ctor) => { - if let Some(ctor_js_doc) = js_doc_for_range(module_info, &ctor.range()) - { + ClassElement::MethodDefinition(method_def) + if method_def.kind == MethodDefinitionKind::Constructor => + { + let ctor = method_def; + if let Some(ctor_js_doc) = js_doc_for_range(module_info, ctor.span()) { let constructor_name = prop_name_to_string(module_info, &ctor.key); let mut params = vec![]; - for param in &ctor.params { - use deno_ast::swc::ast::ParamOrTsParamProp::*; + for param in &ctor.value.params.items { + let param_def = ClassConstructorParamDef { + accessibility: Accessibility::from_oxc(param.accessibility), + is_override: param.r#override, + param: param_to_param_def(module_info, param), + readonly: param.readonly, + }; + params.push(param_def); + } - let param_def = match param { - Param(param) => ClassConstructorParamDef { - accessibility: None, - is_override: false, - param: param_to_param_def(module_info, param), - readonly: false, - }, - TsParamProp(ts_param_prop) => { - use deno_ast::swc::ast::TsParamPropParam; - - let param = match &ts_param_prop.param { - TsParamPropParam::Ident(ident) => { - ident_to_param_def(module_info, ident) - } - TsParamPropParam::Assign(assign_pat) => { - assign_pat_to_param_def(module_info, assign_pat) - } - }; - - ClassConstructorParamDef { - accessibility: ts_param_prop.accessibility, - is_override: ts_param_prop.is_override, - param, - readonly: ts_param_prop.readonly, - } - } + if let Some(rest) = &ctor.value.params.rest { + let param_def = ClassConstructorParamDef { + accessibility: None, + is_override: false, + param: crate::params::rest_element_to_param_def( + module_info, + &rest.rest, + rest.type_annotation.as_deref(), + ), + readonly: false, }; params.push(param_def); } let constructor_def = ClassConstructorDef { js_doc: ctor_js_doc, - accessibility: ctor.accessibility, - is_optional: ctor.is_optional, - has_body: ctor.body.is_some(), + accessibility: Accessibility::from_oxc(ctor.accessibility), + is_optional: ctor.optional, + has_body: ctor.value.body.is_some(), name: constructor_name, params, - location: get_location(module_info, ctor.start()), + location: get_location(module_info, ctor.span().start), }; constructors.push(constructor_def); } } - Method(class_method) => { + ClassElement::MethodDefinition(class_method) => { if let Some(method_js_doc) = - js_doc_for_range(module_info, &class_method.range()) + js_doc_for_range(module_info, class_method.span()) { let method_name = prop_name_to_string(module_info, &class_method.key); - let fn_def = - function_to_function_def(module_info, &class_method.function, None); + let mut fn_def = + function_to_function_def(module_info, &class_method.value, None); + fn_def.decorators = + decorators_to_defs(module_info, &class_method.decorators); let method_def = ClassMethodDef { js_doc: method_js_doc, - accessibility: class_method.accessibility, - optional: class_method.is_optional, - is_abstract: class_method.is_abstract, - is_static: class_method.is_static, - is_override: class_method.is_override, + accessibility: Accessibility::from_oxc(class_method.accessibility), + optional: class_method.optional, + is_abstract: class_method.r#type + == MethodDefinitionType::TSAbstractMethodDefinition, + is_static: class_method.r#static, + is_override: class_method.r#override, name: method_name.into_boxed_str(), - kind: class_method.kind, + kind: MethodKind::from(class_method.kind), function_def: fn_def, - location: get_location(module_info, class_method.start()), + location: get_location(module_info, class_method.span().start), }; methods.push(method_def); } } - ClassProp(class_prop) => { + ClassElement::PropertyDefinition(class_prop) => { + if class_prop.key.is_private_identifier() { + continue; + } if let Some(prop_js_doc) = - js_doc_for_range(module_info, &class_prop.range()) + js_doc_for_range(module_info, class_prop.span()) { - let ts_type = if let Some(type_ann) = &class_prop.type_ann { + let ts_type = if let Some(type_ann) = &class_prop.type_annotation { // if the property has a type annotation, use it - Some(TsTypeDef::new(module_info, &type_ann.type_ann)) + Some(TsTypeDef::new(module_info, &type_ann.type_annotation)) } else if let Some(value) = &class_prop.value { // else, if it has an initializer, try to infer the type infer_ts_type_from_expr(module_info, value, false) @@ -398,35 +400,46 @@ pub fn class_to_class_def( js_doc: prop_js_doc, ts_type, readonly: class_prop.readonly, - optional: class_prop.is_optional, - is_abstract: class_prop.is_abstract, - is_static: class_prop.is_static, - is_override: class_prop.is_override, - accessibility: class_prop.accessibility, + optional: class_prop.optional, + is_abstract: class_prop.r#type + == PropertyDefinitionType::TSAbstractPropertyDefinition, + is_static: class_prop.r#static, + is_override: class_prop.r#override, + accessibility: Accessibility::from_oxc(class_prop.accessibility), name: prop_name.into_boxed_str(), decorators, - location: get_location(module_info, class_prop.start()), + location: get_location(module_info, class_prop.span().start), }; properties.push(prop_def); } } - TsIndexSignature(ts_index_sig) => { - if let Some(js_doc) = - js_doc_for_range(module_info, &ts_index_sig.range()) + ClassElement::TSIndexSignature(ts_index_sig) => { + if let Some(js_doc) = js_doc_for_range(module_info, ts_index_sig.span()) { let mut params = vec![]; - for param in &ts_index_sig.params { - let param_def = ts_fn_param_to_param_def(module_info, param); + for param in &ts_index_sig.parameters { + let ts_type = Some(TsTypeDef::new( + module_info, + ¶m.type_annotation.type_annotation, + )); + let param_def = ParamDef { + pattern: ParamPatternDef::Identifier { + name: param.name.to_string(), + optional: false, + }, + decorators: Box::new([]), + ts_type, + }; params.push(param_def); } - let ts_type = ts_index_sig - .type_ann - .as_ref() - .map(|rt| TsTypeDef::new(module_info, &rt.type_ann)); + let ts_type = Some(TsTypeDef::new( + module_info, + &ts_index_sig.type_annotation.type_annotation, + )); let index_sig_def = IndexSignatureDef { - location: get_location(module_info, ts_index_sig.start()), + location: get_location(module_info, ts_index_sig.span().start), js_doc, readonly: ts_index_sig.readonly, params, @@ -435,21 +448,18 @@ pub fn class_to_class_def( index_signatures.push(index_sig_def); } } - // TODO(bartlomieju): - PrivateMethod(_) => {} - PrivateProp(_) => {} _ => {} } } let type_params = maybe_type_param_decl_to_type_param_defs( module_info, - class.type_params.as_deref(), + class.type_parameters.as_deref(), ); let super_type_params = maybe_type_param_instantiation_to_type_defs( module_info, - class.super_type_params.as_deref(), + class.super_type_arguments.as_deref(), ); let decorators = decorators_to_defs(module_info, &class.decorators); @@ -457,7 +467,7 @@ pub fn class_to_class_def( // JSDoc associated with the class may actually be a leading comment on a // decorator, and so we should parse out the JSDoc for the first decorator let js_doc = if !class.decorators.is_empty() { - js_doc_for_range(module_info, &class.decorators[0].range()).unwrap() + js_doc_for_range(module_info, class.decorators[0].span()).unwrap() } else { JsDoc::default() }; @@ -465,7 +475,7 @@ pub fn class_to_class_def( ( ClassDef { def_name, - is_abstract: class.is_abstract, + is_abstract: class.r#abstract, extends, implements, constructors: constructors.into_boxed_slice(), @@ -482,7 +492,7 @@ pub fn class_to_class_def( pub fn get_doc_for_class_decl( module_info: &EsModuleInfo, - class_decl: &deno_ast::swc::ast::ClassDecl, + class: &Class, ) -> (ClassDef, JsDoc) { - class_to_class_def(module_info, &class_decl.class, None) + class_to_class_def(module_info, class, None) } diff --git a/src/decorators.rs b/src/decorators.rs index d6dc1f5fb..006c0d9c9 100644 --- a/src/decorators.rs +++ b/src/decorators.rs @@ -3,9 +3,9 @@ use crate::node::Location; use crate::util::swc::get_location; -use deno_ast::SourceRangedForSpanned; -use deno_ast::swc::ast::Decorator; -use deno_ast::swc::ast::Expr; +use deno_ast::oxc::ast::ast::Decorator; +use deno_ast::oxc::ast::ast::Expression; +use deno_ast::oxc::span::GetSpan; use deno_graph::symbols::EsModuleInfo; use deno_terminal::colors; use serde::Deserialize; @@ -44,40 +44,39 @@ impl DecoratorDef { module_info: &EsModuleInfo, decorator: &Decorator, ) -> Self { - match decorator.expr.as_ref() { - Expr::Call(call_expr) => { - if let Some(expr) = call_expr.callee.clone().expr() - && let Expr::Ident(ident) = expr.as_ref() - { + match &decorator.expression { + Expression::CallExpression(call_expr) => { + if let Expression::Identifier(ident) = &call_expr.callee { let args = call_expr - .args + .arguments .iter() .map(|a| { - a.text_fast(module_info.source().text_info_lazy()) + let span = a.span(); + module_info.source_text()[span.start as usize..span.end as usize] .to_string() }) .collect(); return Self { - name: ident.sym.to_string(), + name: ident.name.to_string(), args, - location: get_location(module_info, ident.start()), + location: get_location(module_info, ident.span.start), }; } Self { name: "[UNSUPPORTED]".to_string(), args: vec![], - location: get_location(module_info, call_expr.start()), + location: get_location(module_info, call_expr.span.start), } } - Expr::Ident(ident) => Self { - name: ident.sym.to_string(), + Expression::Identifier(ident) => Self { + name: ident.name.to_string(), args: vec![], - location: get_location(module_info, ident.start()), + location: get_location(module_info, ident.span.start), }, _ => Self { name: "[UNSUPPORTED]".to_string(), args: vec![], - location: get_location(module_info, decorator.start()), + location: get_location(module_info, decorator.span.start), }, } } diff --git a/src/diagnostics.rs b/src/diagnostics.rs index 39cb9d4bd..1a2b97763 100644 --- a/src/diagnostics.rs +++ b/src/diagnostics.rs @@ -10,10 +10,10 @@ use crate::ts_type::TsTypeDef; use crate::util::swc::get_text_info_location; use crate::util::swc::has_ignorable_js_doc_tag; use crate::util::symbol::symbol_has_ignorable_js_doc_tag; +use crate::util::types::Accessibility; use crate::variable::VariableDef; use deno_ast::ModuleSpecifier; -use deno_ast::SourceRange; use deno_ast::SourceTextInfo; use deno_ast::diagnostics::Diagnostic; use deno_ast::diagnostics::DiagnosticLevel; @@ -23,7 +23,7 @@ use deno_ast::diagnostics::DiagnosticSnippetHighlight; use deno_ast::diagnostics::DiagnosticSnippetHighlightStyle; use deno_ast::diagnostics::DiagnosticSourcePos; use deno_ast::diagnostics::DiagnosticSourceRange; -use deno_ast::swc::ast::Accessibility; +use deno_ast::oxc::span::Span; use deno_graph::symbols::ModuleInfoRef; use deno_graph::symbols::RootSymbol; use deno_graph::symbols::Symbol as GraphSymbol; @@ -204,7 +204,7 @@ impl<'a> DiagnosticsCollector<'a> { &mut self, decl_module: ModuleInfoRef, decl_name: &str, - decl_range: SourceRange, + decl_range: Span, doc_symbol_id: UniqueSymbolId, referenced_module: ModuleInfoRef, referenced_symbol: &GraphSymbol, diff --git a/src/diff/class.rs b/src/diff/class.rs index fe101cf43..9620f6708 100644 --- a/src/diff/class.rs +++ b/src/diff/class.rs @@ -16,7 +16,7 @@ use crate::class::ClassMethodDef; use crate::class::ClassPropertyDef; use crate::ts_type::IndexSignatureDef; use crate::ts_type::TsTypeDef; -use deno_ast::swc::ast::Accessibility; +use crate::util::types::Accessibility; use indexmap::IndexMap; use indexmap::IndexSet; use serde::Deserialize; diff --git a/src/diff/variable.rs b/src/diff/variable.rs index 3d91a6c4a..a28e3ff46 100644 --- a/src/diff/variable.rs +++ b/src/diff/variable.rs @@ -2,8 +2,8 @@ use super::Change; use super::ts_type::TsTypeDiff; +use crate::util::types::VarDeclKind; use crate::variable::VariableDef; -use deno_ast::swc::ast::VarDeclKind; use serde::Deserialize; use serde::Serialize; diff --git a/src/display.rs b/src/display.rs index aba3b5596..8fb77be7a 100644 --- a/src/display.rs +++ b/src/display.rs @@ -54,19 +54,22 @@ pub(crate) fn display_readonly(is_readonly: bool) -> impl Display { cfg_if! { if #[cfg(feature = "rust")] { + use crate::util::types::Accessibility; + use crate::util::types::MethodKind; + pub(crate) fn display_abstract(is_abstract: bool) -> impl Display { colors::magenta(if is_abstract { "abstract " } else { "" }) } pub(crate) fn display_accessibility( - accessibility: Option, show_public: bool + accessibility: Option, show_public: bool ) -> impl Display { colors::magenta( match accessibility { None => "", - Some(deno_ast::swc::ast::Accessibility::Public) => if show_public { "public " } else { "" }, - Some(deno_ast::swc::ast::Accessibility::Protected) => "protected ", - Some(deno_ast::swc::ast::Accessibility::Private) => "private ", + Some(Accessibility::Public) => if show_public { "public " } else { "" }, + Some(Accessibility::Protected) => "protected ", + Some(Accessibility::Private) => "private ", }, ) } @@ -80,11 +83,11 @@ cfg_if! { } pub(crate) fn display_method( - method: deno_ast::swc::ast::MethodKind, + method: MethodKind, ) -> impl Display { colors::magenta(match method { - deno_ast::swc::ast::MethodKind::Getter => "get ", - deno_ast::swc::ast::MethodKind::Setter => "set ", + MethodKind::Getter => "get ", + MethodKind::Setter => "set ", _ => "", }) } diff --git a/src/enum.rs b/src/enum.rs index cd6090064..04ccaac08 100644 --- a/src/enum.rs +++ b/src/enum.rs @@ -1,6 +1,7 @@ // Copyright 2018-2024 the Deno authors. All rights reserved. MIT license. -use deno_ast::SourceRangedForSpanned; +use deno_ast::oxc::ast::ast::TSEnumDeclaration; +use deno_ast::oxc::span::GetSpan; use deno_graph::symbols::EsModuleInfo; use serde::Deserialize; use serde::Serialize; @@ -31,19 +32,14 @@ pub struct EnumDef { pub fn get_doc_for_ts_enum_decl( module_info: &EsModuleInfo, - enum_decl: &deno_ast::swc::ast::TsEnumDecl, + enum_decl: &TSEnumDeclaration, ) -> EnumDef { let mut members = vec![]; - for enum_member in &enum_decl.members { - use deno_ast::swc::ast::TsEnumMemberId::*; - - if let Some(js_doc) = js_doc_for_range(module_info, &enum_member.range()) { - let name = match &enum_member.id { - Ident(ident) => ident.sym.to_string(), - Str(str_) => str_.value.to_string_lossy().into_owned(), - }; - let init = if let Some(expr) = &enum_member.init { + for enum_member in &enum_decl.body.members { + if let Some(js_doc) = js_doc_for_range(module_info, enum_member.span()) { + let name = enum_member.id.static_name().to_string(); + let init = if let Some(expr) = &enum_member.initializer { infer_ts_type_from_expr(module_info, expr, true) } else { None @@ -53,7 +49,7 @@ pub fn get_doc_for_ts_enum_decl( name, init, js_doc, - location: get_location(module_info, enum_member.start()), + location: get_location(module_info, enum_member.span().start), }; members.push(member_def); } diff --git a/src/function.rs b/src/function.rs index d91346e3d..76b5ca550 100644 --- a/src/function.rs +++ b/src/function.rs @@ -2,14 +2,14 @@ use crate::ParamDef; use crate::decorators::DecoratorDef; -use crate::decorators::decorators_to_defs; use crate::params::param_to_param_def; use crate::ts_type::TsTypeDef; use crate::ts_type_param::TsTypeParamDef; use crate::ts_type_param::maybe_type_param_decl_to_type_param_defs; use crate::util::swc::is_false; -use deno_ast::swc::ast::ReturnStmt; -use deno_ast::swc::ast::Stmt; +use deno_ast::oxc::ast::ast::Function; +use deno_ast::oxc::ast::ast::ReturnStatement; +use deno_ast::oxc::ast::ast::Statement; use deno_graph::symbols::EsModuleInfo; use serde::Deserialize; use serde::Serialize; @@ -37,60 +37,67 @@ pub struct FunctionDef { pub fn function_to_function_def( module_info: &EsModuleInfo, - function: &deno_ast::swc::ast::Function, + function: &Function, def_name: Option, ) -> FunctionDef { - let params = function + let mut params = function .params + .items .iter() .map(|param| param_to_param_def(module_info, param)) - .collect(); - - let maybe_return_type = match function - .return_type - .as_deref() - .map(|return_type| TsTypeDef::new(module_info, &return_type.type_ann)) - { - Some(return_type) => Some(return_type), - None - if !function.is_generator - && function.body.is_some() - && get_return_stmt_with_arg_from_function(function).is_none() => - { - if function.is_async { - Some(TsTypeDef { - repr: "Promise".to_string(), - kind: crate::ts_type::TsTypeDefKind::TypeRef( - crate::ts_type::TsTypeRefDef { - type_params: Some(Box::new([TsTypeDef::keyword("void")])), - type_name: "Promise".to_string(), - resolution: None, - }, - ), - }) - } else { - Some(TsTypeDef::keyword("void")) + .collect::>(); + if let Some(rest) = &function.params.rest { + params.push(crate::params::rest_element_to_param_def( + module_info, + &rest.rest, + rest.type_annotation.as_deref(), + )); + } + + let maybe_return_type = + match function.return_type.as_ref().map(|return_type| { + TsTypeDef::new(module_info, &return_type.type_annotation) + }) { + Some(return_type) => Some(return_type), + None + if !function.generator + && function.body.is_some() + && get_return_stmt_with_arg_from_function(function).is_none() => + { + if function.r#async { + Some(TsTypeDef { + repr: "Promise".to_string(), + kind: crate::ts_type::TsTypeDefKind::TypeRef( + crate::ts_type::TsTypeRefDef { + type_params: Some(Box::new([TsTypeDef::keyword("void")])), + type_name: "Promise".to_string(), + resolution: None, + }, + ), + }) + } else { + Some(TsTypeDef::keyword("void")) + } } - } - None => None, - }; + None => None, + }; let type_params = maybe_type_param_decl_to_type_param_defs( module_info, - function.type_params.as_deref(), + function.type_parameters.as_deref(), ); let has_body = function.body.is_some(); - let decorators = decorators_to_defs(module_info, &function.decorators); + let decorators = Box::new([]); FunctionDef { def_name, params, return_type: maybe_return_type, has_body, - is_async: function.is_async, - is_generator: function.is_generator, + is_async: function.r#async, + is_generator: function.generator, type_params, decorators, } @@ -98,22 +105,29 @@ pub fn function_to_function_def( pub fn arrow_to_function_def( module_info: &EsModuleInfo, - arrow: &deno_ast::swc::ast::ArrowExpr, + arrow: &deno_ast::oxc::ast::ast::ArrowFunctionExpression, ) -> FunctionDef { - let params = arrow + let mut params = arrow .params + .items .iter() - .map(|pat| crate::params::pat_to_param_def(module_info, pat)) - .collect(); + .map(|param| param_to_param_def(module_info, param)) + .collect::>(); + if let Some(rest) = &arrow.params.rest { + params.push(crate::params::rest_element_to_param_def( + module_info, + &rest.rest, + rest.type_annotation.as_deref(), + )); + } - let maybe_return_type = arrow - .return_type - .as_deref() - .map(|return_type| TsTypeDef::new(module_info, &return_type.type_ann)); + let maybe_return_type = arrow.return_type.as_ref().map(|return_type| { + TsTypeDef::new(module_info, &return_type.type_annotation) + }); let type_params = maybe_type_param_decl_to_type_param_defs( module_info, - arrow.type_params.as_deref(), + arrow.type_parameters.as_deref(), ); FunctionDef { @@ -121,8 +135,8 @@ pub fn arrow_to_function_def( params, return_type: maybe_return_type, has_body: true, - is_async: arrow.is_async, - is_generator: arrow.is_generator, + is_async: arrow.r#async, + is_generator: false, type_params, decorators: Box::new([]), } @@ -130,21 +144,23 @@ pub fn arrow_to_function_def( pub fn get_doc_for_fn_decl( module_info: &EsModuleInfo, - fn_decl: &deno_ast::swc::ast::FnDecl, + function: &Function, ) -> FunctionDef { - function_to_function_def(module_info, &fn_decl.function, None) + function_to_function_def(module_info, function, None) } -fn get_return_stmt_with_arg_from_function( - func: &deno_ast::swc::ast::Function, -) -> Option<&ReturnStmt> { +fn get_return_stmt_with_arg_from_function<'a>( + func: &'a Function<'a>, +) -> Option<&'a ReturnStatement<'a>> { let body = func.body.as_ref()?; - let stmt = get_return_stmt_with_arg_from_stmts(&body.stmts)?; - debug_assert!(stmt.arg.is_some()); + let stmt = get_return_stmt_with_arg_from_stmts(&body.statements)?; + debug_assert!(stmt.argument.is_some()); Some(stmt) } -fn get_return_stmt_with_arg_from_stmts(stmts: &[Stmt]) -> Option<&ReturnStmt> { +fn get_return_stmt_with_arg_from_stmts<'a>( + stmts: &'a [Statement<'a>], +) -> Option<&'a ReturnStatement<'a>> { for stmt in stmts { if let Some(return_stmt) = get_return_stmt_with_arg_from_stmt(stmt) { return Some(return_stmt); @@ -154,45 +170,57 @@ fn get_return_stmt_with_arg_from_stmts(stmts: &[Stmt]) -> Option<&ReturnStmt> { None } -fn get_return_stmt_with_arg_from_stmt(stmt: &Stmt) -> Option<&ReturnStmt> { +fn get_return_stmt_with_arg_from_stmt<'a>( + stmt: &'a Statement<'a>, +) -> Option<&'a ReturnStatement<'a>> { match stmt { - Stmt::Block(n) => get_return_stmt_with_arg_from_stmts(&n.stmts), - Stmt::With(n) => get_return_stmt_with_arg_from_stmt(&n.body), - Stmt::Return(n) => { - if n.arg.is_none() { + Statement::BlockStatement(n) => { + get_return_stmt_with_arg_from_stmts(&n.body) + } + Statement::WithStatement(n) => get_return_stmt_with_arg_from_stmt(&n.body), + Statement::ReturnStatement(n) => { + if n.argument.is_none() { None } else { Some(n) } } - Stmt::Labeled(n) => get_return_stmt_with_arg_from_stmt(&n.body), - Stmt::If(n) => get_return_stmt_with_arg_from_stmt(&n.cons), - Stmt::Switch(n) => n + Statement::LabeledStatement(n) => { + get_return_stmt_with_arg_from_stmt(&n.body) + } + Statement::IfStatement(n) => { + get_return_stmt_with_arg_from_stmt(&n.consequent) + } + Statement::SwitchStatement(n) => n .cases .iter() - .find_map(|case| get_return_stmt_with_arg_from_stmts(&case.cons)), - Stmt::Try(n) => get_return_stmt_with_arg_from_stmts(&n.block.stmts) - .or_else(|| { - n.handler - .as_ref() - .and_then(|h| get_return_stmt_with_arg_from_stmts(&h.body.stmts)) - }) - .or_else(|| { - n.finalizer - .as_ref() - .and_then(|f| get_return_stmt_with_arg_from_stmts(&f.stmts)) - }), - Stmt::While(n) => get_return_stmt_with_arg_from_stmt(&n.body), - Stmt::DoWhile(n) => get_return_stmt_with_arg_from_stmt(&n.body), - Stmt::For(n) => get_return_stmt_with_arg_from_stmt(&n.body), - Stmt::ForIn(n) => get_return_stmt_with_arg_from_stmt(&n.body), - Stmt::ForOf(n) => get_return_stmt_with_arg_from_stmt(&n.body), - Stmt::Break(_) - | Stmt::Continue(_) - | Stmt::Throw(_) - | Stmt::Debugger(_) - | Stmt::Decl(_) - | Stmt::Expr(_) - | Stmt::Empty(_) => None, + .find_map(|case| get_return_stmt_with_arg_from_stmts(&case.consequent)), + Statement::TryStatement(n) => { + get_return_stmt_with_arg_from_stmts(&n.block.body) + .or_else(|| { + n.handler + .as_ref() + .and_then(|h| get_return_stmt_with_arg_from_stmts(&h.body.body)) + }) + .or_else(|| { + n.finalizer + .as_ref() + .and_then(|f| get_return_stmt_with_arg_from_stmts(&f.body)) + }) + } + Statement::WhileStatement(n) => get_return_stmt_with_arg_from_stmt(&n.body), + Statement::DoWhileStatement(n) => { + get_return_stmt_with_arg_from_stmt(&n.body) + } + Statement::ForStatement(n) => get_return_stmt_with_arg_from_stmt(&n.body), + Statement::ForInStatement(n) => get_return_stmt_with_arg_from_stmt(&n.body), + Statement::ForOfStatement(n) => get_return_stmt_with_arg_from_stmt(&n.body), + Statement::BreakStatement(_) + | Statement::ContinueStatement(_) + | Statement::ThrowStatement(_) + | Statement::DebuggerStatement(_) + | Statement::ExpressionStatement(_) + | Statement::EmptyStatement(_) => None, + _ => None, } } diff --git a/src/html/mod.rs b/src/html/mod.rs index b0478b757..c23f47c48 100644 --- a/src/html/mod.rs +++ b/src/html/mod.rs @@ -907,12 +907,12 @@ pub enum MethodKind { Setter, } -impl From for MethodKind { - fn from(value: deno_ast::swc::ast::MethodKind) -> Self { +impl From for MethodKind { + fn from(value: crate::util::types::MethodKind) -> Self { match value { - deno_ast::swc::ast::MethodKind::Method => Self::Method, - deno_ast::swc::ast::MethodKind::Getter => Self::Getter, - deno_ast::swc::ast::MethodKind::Setter => Self::Setter, + crate::util::types::MethodKind::Method => Self::Method, + crate::util::types::MethodKind::Getter => Self::Getter, + crate::util::types::MethodKind::Setter => Self::Setter, } } } @@ -1019,7 +1019,7 @@ impl DocNodeWithContext { &self, mut method_doc_node: Symbol, is_static: bool, - method_kind: deno_ast::swc::ast::MethodKind, + method_kind: crate::util::types::MethodKind, ) -> Self { let original_name = method_doc_node.name.clone(); method_doc_node.name = @@ -1040,7 +1040,7 @@ impl DocNodeWithContext { parent: &Arc, mut method_doc_node: Symbol, is_static: bool, - method_kind: deno_ast::swc::ast::MethodKind, + method_kind: crate::util::types::MethodKind, ) -> Self { let original_name = method_doc_node.name.clone(); method_doc_node.name = qualify_drilldown_name( diff --git a/src/html/symbols/class.rs b/src/html/symbols/class.rs index 620b6831a..b1a08c4b0 100644 --- a/src/html/symbols/class.rs +++ b/src/html/symbols/class.rs @@ -17,8 +17,8 @@ use crate::html::util::*; use crate::interface::InterfaceDef; use crate::js_doc::JsDocTag; use crate::ts_type::TsTypeDefKind; -use deno_ast::swc::ast::Accessibility; -use deno_ast::swc::ast::MethodKind; +use crate::util::types::Accessibility; +use crate::util::types::MethodKind; use indexmap::IndexMap; use serde::Deserialize; use serde::Serialize; diff --git a/src/html/symbols/mod.rs b/src/html/symbols/mod.rs index 3c8420acf..76b4540cd 100644 --- a/src/html/symbols/mod.rs +++ b/src/html/symbols/mod.rs @@ -663,7 +663,7 @@ impl SymbolInnerCtx { pub(crate) fn compute_old_tags( current_tags: &indexmap::IndexSet, accessibility_change: Option< - &crate::diff::Change>, + &crate::diff::Change>, >, readonly_change: Option<&crate::diff::Change>, abstract_change: Option<&crate::diff::Change>, diff --git a/src/html/symbols/namespace.rs b/src/html/symbols/namespace.rs index ba4df8f23..f633f6896 100644 --- a/src/html/symbols/namespace.rs +++ b/src/html/symbols/namespace.rs @@ -550,14 +550,14 @@ fn inject_removed_subitems( for method in &mc.removed { if matches!( method.accessibility, - Some(deno_ast::swc::ast::Accessibility::Private) + Some(crate::util::types::Accessibility::Private) ) { continue; } let target_id = if matches!( method.kind, - deno_ast::swc::ast::MethodKind::Getter - | deno_ast::swc::ast::MethodKind::Setter + crate::util::types::MethodKind::Getter + | crate::util::types::MethodKind::Setter ) { IdBuilder::new(ctx) .kind(IdKind::Accessor) @@ -596,7 +596,7 @@ fn inject_removed_subitems( for prop in &pc.removed { if matches!( prop.accessibility, - Some(deno_ast::swc::ast::Accessibility::Private) + Some(crate::util::types::Accessibility::Private) ) { continue; } @@ -629,8 +629,8 @@ fn inject_removed_subitems( for method in &mc.removed { let target_id = if matches!( method.kind, - deno_ast::swc::ast::MethodKind::Getter - | deno_ast::swc::ast::MethodKind::Setter + crate::util::types::MethodKind::Getter + | crate::util::types::MethodKind::Setter ) { IdBuilder::new(ctx) .kind(IdKind::Accessor) diff --git a/src/html/types.rs b/src/html/types.rs index 8dfb7b634..64fe46a3d 100644 --- a/src/html/types.rs +++ b/src/html/types.rs @@ -5,10 +5,10 @@ use super::util::*; use crate::js_doc::JsDoc; use crate::js_doc::JsDocTag; use crate::ts_type::LiteralDefKind; +use crate::ts_type::TruePlusMinus; use crate::ts_type::TsTypeDefKind; use crate::ts_type_param::TsTypeParamDef; -use deno_ast::swc::ast::MethodKind; -use deno_ast::swc::ast::TruePlusMinus; +use crate::util::types::MethodKind; const MAX_INLINE_LEN: usize = 60; diff --git a/src/html/util.rs b/src/html/util.rs index 8a6780efc..4b3ba3031 100644 --- a/src/html/util.rs +++ b/src/html/util.rs @@ -13,8 +13,7 @@ use crate::js_doc::JsDoc; use crate::js_doc::JsDocTag; use crate::node::DeclarationDef; use crate::node::DocNodeKind; -use deno_ast::swc::ast::Accessibility; -use deno_ast::swc::atoms::once_cell::sync::Lazy; +use crate::util::types::Accessibility; use indexmap::IndexSet; use regex::Regex; use serde::Deserialize; @@ -24,6 +23,7 @@ use std::collections::HashMap; use std::fmt::Display; use std::fmt::Formatter; use std::sync::Arc; +use std::sync::LazyLock; lazy_static! { static ref TARGET_RE: Regex = Regex::new(r"\s*\* ?|\.").unwrap(); @@ -948,8 +948,8 @@ impl ToCCtx { } pub fn slugify(name: &str) -> String { - static REJECTED_CHARS: Lazy = - Lazy::new(|| Regex::new(r"[^\p{L}\p{M}\p{N}\p{Pc} -]").unwrap()); + static REJECTED_CHARS: LazyLock = + LazyLock::new(|| Regex::new(r"[^\p{L}\p{M}\p{N}\p{Pc} -]").unwrap()); REJECTED_CHARS .replace_all(&name.to_lowercase(), "") diff --git a/src/interface.rs b/src/interface.rs index 2793d183f..aff0d5371 100644 --- a/src/interface.rs +++ b/src/interface.rs @@ -1,11 +1,15 @@ // Copyright 2018-2024 the Deno authors. All rights reserved. MIT license. -use deno_ast::SourceRangedForSpanned; +use deno_ast::oxc::ast::ast::Expression; +use deno_ast::oxc::ast::ast::TSInterfaceDeclaration; +use deno_ast::oxc::ast::ast::TSSignature; use deno_graph::symbols::EsModuleInfo; use serde::Deserialize; use serde::Serialize; -use crate::params::ts_fn_param_to_param_def; +use crate::ParamDef; +use crate::params::ParamPatternDef; +use crate::params::formal_params_to_param_defs; use crate::ts_type::CallSignatureDef; use crate::ts_type::ConstructorDef; use crate::ts_type::IndexSignatureDef; @@ -16,6 +20,7 @@ use crate::ts_type_param::TsTypeParamDef; use crate::ts_type_param::maybe_type_param_decl_to_type_param_defs; use crate::util::swc::get_location; use crate::util::swc::js_doc_for_range; +use crate::util::types::MethodKind; #[derive(Debug, Serialize, Deserialize, Clone)] #[serde(rename_all = "camelCase")] @@ -39,50 +44,63 @@ pub struct InterfaceDef { pub type_params: Box<[TsTypeParamDef]>, } -pub fn expr_to_name(expr: &deno_ast::swc::ast::Expr) -> String { - use deno_ast::swc::ast::Expr::*; - use deno_ast::swc::ast::MemberProp; - +pub fn expr_to_name(expr: &Expression) -> String { match expr { - Ident(ident) => ident.sym.to_string(), - Member(member_expr) => { - let left = expr_to_name(&member_expr.obj); - let right = match &member_expr.prop { - MemberProp::Ident(ident) => format!(".{}", ident.sym), - MemberProp::Computed(_) | MemberProp::PrivateName(_) => { - "[UNSUPPORTED]".to_string() - } - }; + Expression::Identifier(ident) => ident.name.to_string(), + Expression::StaticMemberExpression(member_expr) => { + let left = expr_to_name(&member_expr.object); + let right = format!(".{}", member_expr.property.name); format!("[{}{}]", left, right) } - Lit(lit) => { - use deno_ast::swc::ast::BigInt; - use deno_ast::swc::ast::Bool; - use deno_ast::swc::ast::JSXText; - use deno_ast::swc::ast::Lit; - use deno_ast::swc::ast::Number; - use deno_ast::swc::ast::Regex; - use deno_ast::swc::ast::Str; - match lit { - Lit::Str(Str { value, .. }) => value.to_string_lossy().into_owned(), - Lit::Bool(Bool { value, .. }) => { - let str_val = if *value { "true" } else { "false" }; - str_val.to_string() + Expression::ComputedMemberExpression(_) + | Expression::PrivateFieldExpression(_) => "[UNSUPPORTED]".to_string(), + Expression::StringLiteral(str_) => str_.value.to_string(), + Expression::BooleanLiteral(bool_) => { + if bool_.value { "true" } else { "false" }.to_string() + } + Expression::NullLiteral(_) => "null".to_string(), + Expression::NumericLiteral(num) => num.value.to_string(), + Expression::BigIntLiteral(num) => num + .raw + .as_ref() + .map(|r| r.as_str().to_string()) + .unwrap_or_default(), + Expression::RegExpLiteral(regex) => { + format!("/{}/", regex.regex.pattern.text) + } + Expression::TemplateLiteral(tpl) => { + let mut result = String::new(); + for (i, quasi) in tpl.quasis.iter().enumerate() { + result.push_str(quasi.value.raw.as_str()); + if i < tpl.expressions.len() { + result.push_str(&expr_to_name(&tpl.expressions[i])); } - Lit::Null(_) => "null".to_string(), - Lit::Num(Number { value, .. }) => value.to_string(), - Lit::BigInt(BigInt { value, .. }) => value.to_string(), - Lit::Regex(Regex { exp, .. }) => format!("/{}/", exp), - Lit::JSXText(JSXText { raw, .. }) => raw.to_string(), } + result } _ => "[UNSUPPORTED]".to_string(), } } +pub fn property_key_name(key: &deno_ast::oxc::ast::ast::PropertyKey) -> String { + use deno_ast::oxc::ast::ast::PropertyKey; + if let Some(name) = key.static_name() { + return name.to_string(); + } + // For computed keys, resolve common expression patterns + match key { + PropertyKey::StaticIdentifier(ident) => ident.name.to_string(), + // Computed keys that are identifiers (e.g., `[pc]`) + PropertyKey::Identifier(ident) => ident.name.to_string(), + PropertyKey::StringLiteral(s) => s.value.to_string(), + PropertyKey::NumericLiteral(n) => n.value.to_string(), + _ => "[UNSUPPORTED]".to_string(), + } +} + pub fn get_doc_for_ts_interface_decl( module_info: &EsModuleInfo, - interface_decl: &deno_ast::swc::ast::TsInterfaceDecl, + interface_decl: &TSInterfaceDeclaration, def_name: Option, ) -> InterfaceDef { let mut constructors = vec![]; @@ -92,37 +110,31 @@ pub fn get_doc_for_ts_interface_decl( let mut index_signatures = vec![]; for type_element in &interface_decl.body.body { - use deno_ast::swc::ast::TsTypeElement::*; - - match &type_element { - TsMethodSignature(ts_method_sig) => { + match type_element { + TSSignature::TSMethodSignature(ts_method_sig) => { if let Some(method_js_doc) = - js_doc_for_range(module_info, &ts_method_sig.range()) + js_doc_for_range(module_info, ts_method_sig.span) { - let mut params = vec![]; - - for param in &ts_method_sig.params { - let param_def = ts_fn_param_to_param_def(module_info, param); - params.push(param_def); - } + let params = + formal_params_to_param_defs(module_info, &ts_method_sig.params); - let name = expr_to_name(&ts_method_sig.key); + let name = property_key_name(&ts_method_sig.key); - let maybe_return_type = ts_method_sig - .type_ann - .as_deref() - .map(|type_ann| TsTypeDef::new(module_info, &type_ann.type_ann)); + let maybe_return_type = + ts_method_sig.return_type.as_ref().map(|type_ann| { + TsTypeDef::new(module_info, &type_ann.type_annotation) + }); let type_params = maybe_type_param_decl_to_type_param_defs( module_info, - ts_method_sig.type_params.as_deref(), + ts_method_sig.type_parameters.as_deref(), ); let method_def = MethodDef { name, - kind: deno_ast::swc::ast::MethodKind::Method, + kind: MethodKind::from(ts_method_sig.kind), js_doc: method_js_doc, - location: get_location(module_info, ts_method_sig.start()), + location: get_location(module_info, ts_method_sig.span.start), computed: ts_method_sig.computed, optional: ts_method_sig.optional, params, @@ -132,65 +144,15 @@ pub fn get_doc_for_ts_interface_decl( methods.push(method_def); } } - TsGetterSignature(ts_getter_sig) => { - if let Some(method_js_doc) = - js_doc_for_range(module_info, &ts_getter_sig.range()) - { - let name = expr_to_name(&ts_getter_sig.key); - - let maybe_return_type = ts_getter_sig - .type_ann - .as_deref() - .map(|type_ann| TsTypeDef::new(module_info, &type_ann.type_ann)); - - let method_def = MethodDef { - name, - kind: deno_ast::swc::ast::MethodKind::Getter, - js_doc: method_js_doc, - location: get_location(module_info, ts_getter_sig.start()), - computed: ts_getter_sig.computed, - optional: false, - params: vec![], - return_type: maybe_return_type, - type_params: Box::new([]), - }; - methods.push(method_def); - } - } - TsSetterSignature(ts_setter_sig) => { - if let Some(method_js_doc) = - js_doc_for_range(module_info, &ts_setter_sig.range()) - { - let name = expr_to_name(&ts_setter_sig.key); - - let param_def = - ts_fn_param_to_param_def(module_info, &ts_setter_sig.param); - let params = vec![param_def]; - - let method_def = MethodDef { - name, - kind: deno_ast::swc::ast::MethodKind::Setter, - js_doc: method_js_doc, - location: get_location(module_info, ts_setter_sig.start()), - computed: ts_setter_sig.computed, - optional: false, - params, - return_type: None, - type_params: Box::new([]), - }; - methods.push(method_def); - } - } - TsPropertySignature(ts_prop_sig) => { + TSSignature::TSPropertySignature(ts_prop_sig) => { if let Some(prop_js_doc) = - js_doc_for_range(module_info, &ts_prop_sig.range()) + js_doc_for_range(module_info, ts_prop_sig.span) { - let name = expr_to_name(&ts_prop_sig.key); + let name = property_key_name(&ts_prop_sig.key); - let ts_type = ts_prop_sig - .type_ann - .as_deref() - .map(|type_ann| TsTypeDef::new(module_info, &type_ann.type_ann)); + let ts_type = ts_prop_sig.type_annotation.as_ref().map(|type_ann| { + TsTypeDef::new(module_info, &type_ann.type_annotation) + }); let type_params = maybe_type_param_decl_to_type_param_defs(module_info, None); @@ -198,7 +160,7 @@ pub fn get_doc_for_ts_interface_decl( let prop_def = PropertyDef { name, js_doc: prop_js_doc, - location: get_location(module_info, ts_prop_sig.start()), + location: get_location(module_info, ts_prop_sig.span.start), params: vec![], ts_type, readonly: ts_prop_sig.readonly, @@ -209,29 +171,25 @@ pub fn get_doc_for_ts_interface_decl( properties.push(prop_def); } } - TsCallSignatureDecl(ts_call_sig) => { + TSSignature::TSCallSignatureDeclaration(ts_call_sig) => { if let Some(call_sig_js_doc) = - js_doc_for_range(module_info, &ts_call_sig.range()) + js_doc_for_range(module_info, ts_call_sig.span) { - let mut params = vec![]; - for param in &ts_call_sig.params { - let param_def = ts_fn_param_to_param_def(module_info, param); - params.push(param_def); - } + let params = + formal_params_to_param_defs(module_info, &ts_call_sig.params); - let ts_type = ts_call_sig - .type_ann - .as_deref() - .map(|type_ann| TsTypeDef::new(module_info, &type_ann.type_ann)); + let ts_type = ts_call_sig.return_type.as_ref().map(|type_ann| { + TsTypeDef::new(module_info, &type_ann.type_annotation) + }); let type_params = maybe_type_param_decl_to_type_param_defs( module_info, - ts_call_sig.type_params.as_deref(), + ts_call_sig.type_parameters.as_deref(), ); let call_sig_def = CallSignatureDef { js_doc: call_sig_js_doc, - location: get_location(module_info, ts_call_sig.start()), + location: get_location(module_info, ts_call_sig.span.start), params, ts_type, type_params, @@ -239,23 +197,35 @@ pub fn get_doc_for_ts_interface_decl( call_signatures.push(call_sig_def); } } - TsIndexSignature(ts_index_sig) => { - if let Some(js_doc) = - js_doc_for_range(module_info, &ts_index_sig.range()) - { - let mut params = vec![]; - for param in &ts_index_sig.params { - let param_def = ts_fn_param_to_param_def(module_info, param); - params.push(param_def); - } - - let ts_type = ts_index_sig - .type_ann - .as_ref() - .map(|rt| TsTypeDef::new(module_info, &rt.type_ann)); + TSSignature::TSIndexSignature(ts_index_sig) => { + if let Some(js_doc) = js_doc_for_range(module_info, ts_index_sig.span) { + // TSIndexSignature uses TSIndexSignatureName, not FormalParameter + let params = ts_index_sig + .parameters + .iter() + .map(|param| { + let ts_type = Some(TsTypeDef::new( + module_info, + ¶m.type_annotation.type_annotation, + )); + ParamDef { + pattern: ParamPatternDef::Identifier { + name: param.name.to_string(), + optional: false, + }, + decorators: Box::new([]), + ts_type, + } + }) + .collect(); + + let ts_type = Some(TsTypeDef::new( + module_info, + &ts_index_sig.type_annotation.type_annotation, + )); let index_sig_def = IndexSignatureDef { - location: get_location(module_info, ts_index_sig.start()), + location: get_location(module_info, ts_index_sig.span.start), js_doc, readonly: ts_index_sig.readonly, params, @@ -264,30 +234,26 @@ pub fn get_doc_for_ts_interface_decl( index_signatures.push(index_sig_def); } } - TsConstructSignatureDecl(ts_construct_sig) => { + TSSignature::TSConstructSignatureDeclaration(ts_construct_sig) => { if let Some(js_doc) = - js_doc_for_range(module_info, &ts_construct_sig.range()) + js_doc_for_range(module_info, ts_construct_sig.span) { - let mut params = vec![]; - - for param in &ts_construct_sig.params { - let param_def = ts_fn_param_to_param_def(module_info, param); - params.push(param_def); - } + let params = + formal_params_to_param_defs(module_info, &ts_construct_sig.params); let type_params = maybe_type_param_decl_to_type_param_defs( module_info, - ts_construct_sig.type_params.as_deref(), + ts_construct_sig.type_parameters.as_deref(), ); let maybe_return_type = ts_construct_sig - .type_ann + .return_type .as_ref() - .map(|rt| TsTypeDef::new(module_info, &rt.type_ann)); + .map(|rt| TsTypeDef::new(module_info, &rt.type_annotation)); let construct_sig_def = ConstructorDef { js_doc, - location: get_location(module_info, ts_construct_sig.start()), + location: get_location(module_info, ts_construct_sig.span.start), params, return_type: maybe_return_type, type_params, @@ -301,13 +267,13 @@ pub fn get_doc_for_ts_interface_decl( let type_params = maybe_type_param_decl_to_type_param_defs( module_info, - interface_decl.type_params.as_deref(), + interface_decl.type_parameters.as_deref(), ); let extends = interface_decl .extends .iter() - .map(|expr| TsTypeDef::ts_expr_with_type_args(module_info, expr)) + .map(|expr| TsTypeDef::ts_interface_heritage(module_info, expr)) .collect::>(); InterfaceDef { diff --git a/src/js_doc.rs b/src/js_doc.rs index 567825c36..a46d441b1 100644 --- a/src/js_doc.rs +++ b/src/js_doc.rs @@ -49,47 +49,32 @@ fn make_ts_type(type_str: &str, module_info: &EsModuleInfo) -> TsTypeDef { } } -fn parse_jsdoc_type_source(type_str: &str) -> Option { +pub fn parse_jsdoc_type( + module_info: &EsModuleInfo, + type_str: &str, +) -> Option { let source = format!("type _temp = {type_str}"); let specifier = ModuleSpecifier::parse("file:///jsdoc_type.ts").unwrap(); - let parsed = deno_ast::parse_module(ParseParams { - specifier, - text: Arc::from(source.as_str()), - media_type: MediaType::TypeScript, - capture_tokens: false, - scope_analysis: false, - maybe_syntax: None, - }) + let allocator = deno_ast::oxc::allocator::Allocator::default(); + let parsed = deno_ast::parse_module( + &allocator, + ParseParams { + specifier, + text: Arc::from(source.as_str()), + media_type: MediaType::TypeScript, + capture_tokens: false, + scope_analysis: false, + maybe_source_type: None, + }, + ) .ok()?; - let program_ref = parsed.program_ref(); - let module = program_ref.unwrap_module(); - let type_alias = module.body.first()?; - if !matches!( + let type_alias = parsed.program().body.first()?; + if let deno_ast::oxc::ast::ast::Statement::TSTypeAliasDeclaration( type_alias, - deno_ast::swc::ast::ModuleItem::Stmt(deno_ast::swc::ast::Stmt::Decl( - deno_ast::swc::ast::Decl::TsTypeAlias(_), - )) - ) { - return None; - } - - Some(parsed) -} - -pub fn parse_jsdoc_type( - module_info: &EsModuleInfo, - type_str: &str, -) -> Option { - let parsed = parse_jsdoc_type_source(type_str)?; - let program_ref = parsed.program_ref(); - let module = program_ref.unwrap_module(); - let type_alias = module.body.first()?; - if let deno_ast::swc::ast::ModuleItem::Stmt(deno_ast::swc::ast::Stmt::Decl( - deno_ast::swc::ast::Decl::TsTypeAlias(type_alias), - )) = type_alias + ) = type_alias { - Some(TsTypeDef::new(module_info, &type_alias.type_ann)) + Some(TsTypeDef::new(module_info, &type_alias.type_annotation)) } else { None } @@ -570,7 +555,9 @@ mod tests { }, ) .await; - let root_symbol = deno_graph::symbols::RootSymbol::new(&graph, &analyzer); + let allocator = deno_ast::oxc::allocator::Allocator::default(); + let root_symbol = + deno_graph::symbols::RootSymbol::new(&graph, &analyzer, &allocator); let module_info = root_symbol.module_from_specifier(&specifier).unwrap(); let esm = match module_info { deno_graph::symbols::ModuleInfoRef::Esm(esm) => esm, @@ -580,6 +567,39 @@ mod tests { }) } + fn parse_jsdoc_type_source(input: &str) -> Option { + let rt = tokio::runtime::Runtime::new().unwrap(); + rt.block_on(async { + let specifier = + deno_ast::ModuleSpecifier::parse("file:///test.ts").unwrap(); + let mut loader = deno_graph::source::MemoryLoader::default(); + loader.add_source_with_text(specifier.as_str(), "export {};"); + let analyzer = deno_graph::ast::CapturingModuleAnalyzer::default(); + let mut graph = + deno_graph::ModuleGraph::new(deno_graph::GraphKind::TypesOnly); + graph + .build( + vec![specifier.clone()], + Vec::new(), + &loader, + deno_graph::BuildOptions { + module_analyzer: &analyzer, + ..Default::default() + }, + ) + .await; + let allocator = deno_ast::oxc::allocator::Allocator::default(); + let root_symbol = + deno_graph::symbols::RootSymbol::new(&graph, &analyzer, &allocator); + let module_info = root_symbol.module_from_specifier(&specifier).unwrap(); + let esm = match module_info { + deno_graph::symbols::ModuleInfoRef::Esm(esm) => esm, + _ => panic!("expected esm module"), + }; + parse_jsdoc_type(esm, input) + }) + } + fn ts_keyword(name: &str) -> serde_json::Value { serde_json::json!({ "repr": name, diff --git a/src/lib.rs b/src/lib.rs index 23c7c49bc..ba33738ba 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -51,6 +51,7 @@ cfg_if! { } } +pub use deno_ast::oxc::allocator::Allocator as OxcAllocator; pub use parser::DocError; pub use parser::DocParser; pub use parser::DocParserOptions; diff --git a/src/params.rs b/src/params.rs index 457f55288..fbb6d5a94 100644 --- a/src/params.rs +++ b/src/params.rs @@ -6,10 +6,17 @@ use crate::display::SliceDisplayer; use crate::display::display_optional; use crate::ts_type::TsTypeDef; -use deno_ast::SourceRangedForSpanned; -use deno_ast::swc::ast::ObjectPatProp; -use deno_ast::swc::ast::Pat; -use deno_ast::swc::ast::TsFnParam; +use deno_ast::oxc::ast::ast::ArrayPattern; +use deno_ast::oxc::ast::ast::AssignmentPattern; +use deno_ast::oxc::ast::ast::BindingIdentifier; +use deno_ast::oxc::ast::ast::BindingPattern; +use deno_ast::oxc::ast::ast::BindingProperty; +use deno_ast::oxc::ast::ast::BindingRestElement; +use deno_ast::oxc::ast::ast::FormalParameter; +use deno_ast::oxc::ast::ast::FormalParameters; +use deno_ast::oxc::ast::ast::ObjectPattern; +use deno_ast::oxc::ast::ast::PropertyKey; +use deno_ast::oxc::span::GetSpan; use deno_graph::symbols::EsModuleInfo; use serde::Deserialize; use serde::Serialize; @@ -84,8 +91,6 @@ impl Display for ParamDef { if let Some(ts_type) = &self.ts_type { write!(f, ": {}", ts_type)?; } - // TODO(SyrupThinker) As we cannot display expressions the value is just omitted - // write!(f, " = {}", right)?; Ok(()) } ParamPatternDef::Identifier { name, optional } => { @@ -131,11 +136,9 @@ impl Display for ObjectPatPropDef { fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult { match self { ObjectPatPropDef::KeyValue { key, .. } => { - // The internal identifier does not need to be exposed write!(f, "{}", key) } ObjectPatPropDef::Assign { key, .. } => { - // TODO(SyrupThinker) As we cannot display expressions the value is just omitted write!(f, "{}", key) } ObjectPatPropDef::Rest { arg } => write!(f, "...{}", arg), @@ -145,78 +148,99 @@ impl Display for ObjectPatPropDef { pub fn ident_to_param_def( module_info: &EsModuleInfo, - ident: &deno_ast::swc::ast::BindingIdent, + ident: &BindingIdentifier, + type_ann: Option<&deno_ast::oxc::ast::ast::TSTypeAnnotation>, ) -> ParamDef { - let ts_type = ident - .type_ann - .as_deref() - .map(|type_ann| TsTypeDef::new(module_info, &type_ann.type_ann)); + let ts_type = type_ann + .map(|type_ann| TsTypeDef::new(module_info, &type_ann.type_annotation)); ParamDef { pattern: ParamPatternDef::Identifier { - name: ident.id.sym.to_string(), - optional: ident.id.optional, + name: ident.name.to_string(), + optional: false, }, decorators: Box::new([]), ts_type, } } -fn rest_pat_to_param_def( +pub fn rest_element_to_param_def( module_info: &EsModuleInfo, - rest_pat: &deno_ast::swc::ast::RestPat, + rest: &BindingRestElement, + type_ann: Option<&deno_ast::oxc::ast::ast::TSTypeAnnotation>, ) -> ParamDef { - let ts_type = rest_pat - .type_ann - .as_deref() - .map(|type_ann| TsTypeDef::new(module_info, &type_ann.type_ann)); + let ts_type = type_ann + .map(|type_ann| TsTypeDef::new(module_info, &type_ann.type_annotation)); ParamDef { pattern: ParamPatternDef::Rest { - arg: Box::new(pat_to_param_def(module_info, &rest_pat.arg)), + arg: Box::new(binding_pat_to_param_def( + module_info, + &rest.argument, + None, + )), }, decorators: Box::new([]), ts_type, } } -fn object_pat_prop_to_def( +fn binding_prop_to_def( module_info: &EsModuleInfo, - object_pat_prop: &ObjectPatProp, + prop: &BindingProperty, ) -> ObjectPatPropDef { - match object_pat_prop { - ObjectPatProp::Assign(assign) => ObjectPatPropDef::Assign { - key: assign.key.sym.to_string(), - value: assign.value.as_ref().map(|_| "[UNSUPPORTED]".to_string()), - }, - ObjectPatProp::KeyValue(keyvalue) => ObjectPatPropDef::KeyValue { - key: prop_name_to_string(module_info, &keyvalue.key), - value: Box::new(pat_to_param_def(module_info, &keyvalue.value)), - }, - ObjectPatProp::Rest(rest) => ObjectPatPropDef::Rest { - arg: Box::new(pat_to_param_def(module_info, &rest.arg)), - }, + if prop.shorthand { + // Shorthand: `{ x }` or `{ x = default }` + let key = match &prop.value { + BindingPattern::BindingIdentifier(ident) => ident.name.to_string(), + BindingPattern::AssignmentPattern(assign) => match &assign.left { + BindingPattern::BindingIdentifier(ident) => ident.name.to_string(), + _ => "[UNSUPPORTED]".to_string(), + }, + _ => "[UNSUPPORTED]".to_string(), + }; + let value = match &prop.value { + BindingPattern::AssignmentPattern(_) => Some("[UNSUPPORTED]".to_string()), + _ => None, + }; + ObjectPatPropDef::Assign { key, value } + } else { + // KeyValue: `{ key: value }` + ObjectPatPropDef::KeyValue { + key: prop_name_to_string(module_info, &prop.key), + value: Box::new(binding_pat_to_param_def(module_info, &prop.value, None)), + } } } fn object_pat_to_param_def( module_info: &EsModuleInfo, - object_pat: &deno_ast::swc::ast::ObjectPat, + object_pat: &ObjectPattern, + type_ann: Option<&deno_ast::oxc::ast::ast::TSTypeAnnotation>, ) -> ParamDef { - let props = object_pat - .props + let mut props = object_pat + .properties .iter() - .map(|prop| object_pat_prop_to_def(module_info, prop)) + .map(|prop| binding_prop_to_def(module_info, prop)) .collect::>(); - let ts_type = object_pat - .type_ann - .as_deref() - .map(|type_ann| TsTypeDef::new(module_info, &type_ann.type_ann)); + + if let Some(rest) = &object_pat.rest { + props.push(ObjectPatPropDef::Rest { + arg: Box::new(binding_pat_to_param_def( + module_info, + &rest.argument, + None, + )), + }); + } + + let ts_type = type_ann + .map(|type_ann| TsTypeDef::new(module_info, &type_ann.type_annotation)); ParamDef { pattern: ParamPatternDef::Object { props, - optional: object_pat.optional, + optional: false, }, decorators: Box::new([]), ts_type, @@ -225,22 +249,41 @@ fn object_pat_to_param_def( fn array_pat_to_param_def( module_info: &EsModuleInfo, - array_pat: &deno_ast::swc::ast::ArrayPat, + array_pat: &ArrayPattern, + type_ann: Option<&deno_ast::oxc::ast::ast::TSTypeAnnotation>, ) -> ParamDef { - let elements = array_pat - .elems + let mut elements = array_pat + .elements .iter() - .map(|elem| elem.as_ref().map(|e| pat_to_param_def(module_info, e))) + .map(|elem| { + elem + .as_ref() + .map(|e| binding_pat_to_param_def(module_info, e, None)) + }) .collect::>>(); - let ts_type = array_pat - .type_ann - .as_deref() - .map(|type_ann| TsTypeDef::new(module_info, &type_ann.type_ann)); + + // If there's a rest element, add it + if let Some(rest) = &array_pat.rest { + elements.push(Some(ParamDef { + pattern: ParamPatternDef::Rest { + arg: Box::new(binding_pat_to_param_def( + module_info, + &rest.argument, + None, + )), + }, + decorators: Box::new([]), + ts_type: None, + })); + } + + let ts_type = type_ann + .map(|type_ann| TsTypeDef::new(module_info, &type_ann.type_annotation)); ParamDef { pattern: ParamPatternDef::Array { elements, - optional: array_pat.optional, + optional: false, }, decorators: Box::new([]), ts_type, @@ -249,9 +292,11 @@ fn array_pat_to_param_def( pub fn assign_pat_to_param_def( module_info: &EsModuleInfo, - assign_pat: &deno_ast::swc::ast::AssignPat, + assign_pat: &AssignmentPattern, + type_ann: Option<&deno_ast::oxc::ast::ast::TSTypeAnnotation>, ) -> ParamDef { - let mut left = pat_to_param_def(module_info, &assign_pat.left); + let mut left = + binding_pat_to_param_def(module_info, &assign_pat.left, type_ann); if left.ts_type.is_none() { left.ts_type = crate::ts_type::infer_ts_type_from_expr( @@ -273,55 +318,113 @@ pub fn assign_pat_to_param_def( pub fn param_to_param_def( module_info: &EsModuleInfo, - param: &deno_ast::swc::ast::Param, + param: &FormalParameter, ) -> ParamDef { - let mut def = pat_to_param_def(module_info, ¶m.pat); + let mut def = binding_pat_to_param_def( + module_info, + ¶m.pattern, + param.type_annotation.as_deref(), + ); + // Set optional from the FormalParameter (BindingIdentifier doesn't have it) + if param.optional { + match &mut def.pattern { + ParamPatternDef::Identifier { optional, .. } => *optional = true, + ParamPatternDef::Array { optional, .. } => *optional = true, + ParamPatternDef::Object { optional, .. } => *optional = true, + _ => {} + } + } def.decorators = decorators_to_defs(module_info, ¶m.decorators); + + // Wrap in Assign if the parameter has a default initializer + if let Some(init) = ¶m.initializer { + let right = crate::interface::expr_to_name(init); + // Infer type from initializer if not already set + if def.ts_type.is_none() { + def.ts_type = + crate::ts_type::infer_ts_type_from_expr(module_info, init, false); + } + def = ParamDef { + pattern: ParamPatternDef::Assign { + left: Box::new(def), + right, + }, + decorators: Box::new([]), + ts_type: None, + }; + } + def } -pub fn pat_to_param_def( +pub fn binding_pat_to_param_def( module_info: &EsModuleInfo, - pat: &deno_ast::swc::ast::Pat, + pat: &BindingPattern, + type_ann: Option<&deno_ast::oxc::ast::ast::TSTypeAnnotation>, ) -> ParamDef { match pat { - Pat::Ident(ident) => ident_to_param_def(module_info, ident), - Pat::Array(array_pat) => array_pat_to_param_def(module_info, array_pat), - Pat::Rest(rest_pat) => rest_pat_to_param_def(module_info, rest_pat), - Pat::Object(object_pat) => object_pat_to_param_def(module_info, object_pat), - Pat::Assign(assign_pat) => assign_pat_to_param_def(module_info, assign_pat), - _ => unreachable!(), + BindingPattern::BindingIdentifier(ident) => { + ident_to_param_def(module_info, ident, type_ann) + } + BindingPattern::ArrayPattern(array_pat) => { + array_pat_to_param_def(module_info, array_pat, type_ann) + } + BindingPattern::ObjectPattern(object_pat) => { + object_pat_to_param_def(module_info, object_pat, type_ann) + } + BindingPattern::AssignmentPattern(assign_pat) => { + assign_pat_to_param_def(module_info, assign_pat, type_ann) + } } } -pub fn ts_fn_param_to_param_def( +/// Collect all params from FormalParameters, including the rest element. +pub fn formal_params_to_param_defs( module_info: &EsModuleInfo, - ts_fn_param: &deno_ast::swc::ast::TsFnParam, -) -> ParamDef { - match ts_fn_param { - TsFnParam::Ident(ident) => ident_to_param_def(module_info, ident), - TsFnParam::Array(array_pat) => { - array_pat_to_param_def(module_info, array_pat) - } - TsFnParam::Rest(rest_pat) => rest_pat_to_param_def(module_info, rest_pat), - TsFnParam::Object(object_pat) => { - object_pat_to_param_def(module_info, object_pat) - } + params: &FormalParameters, +) -> Vec { + let mut result: Vec = params + .items + .iter() + .map(|param| param_to_param_def(module_info, param)) + .collect(); + if let Some(rest) = ¶ms.rest { + result.push(rest_element_to_param_def( + module_info, + &rest.rest, + rest.type_annotation.as_deref(), + )); } + result } pub fn prop_name_to_string( module_info: &EsModuleInfo, - prop_name: &deno_ast::swc::ast::PropName, + prop_key: &PropertyKey, ) -> String { - use deno_ast::swc::ast::PropName; - match prop_name { - PropName::Ident(ident) => ident.sym.to_string(), - PropName::Str(str_) => str_.value.to_string_lossy().into_owned(), - PropName::Num(num) => num.value.to_string(), - PropName::BigInt(num) => num.value.to_string(), - PropName::Computed(comp_prop_name) => comp_prop_name - .text_fast(module_info.source().text_info_lazy()) - .to_string(), + match prop_key { + PropertyKey::StaticIdentifier(ident) => ident.name.to_string(), + PropertyKey::StringLiteral(str_) => str_.value.to_string(), + PropertyKey::NumericLiteral(num) => num.value.to_string(), + PropertyKey::BigIntLiteral(num) => num + .raw + .as_ref() + .map(|r| r.as_str().to_string()) + .unwrap_or_default(), + // Computed expression keys - use the PropertyKey's expression nature + // Member expressions like Symbol.iterator should produce [Symbol.iterator] + PropertyKey::PrivateIdentifier(ident) => { + format!("#{}", ident.name) + } + PropertyKey::StaticMemberExpression(member) => { + let left: String = crate::interface::expr_to_name(&member.object); + let right = member.property.name.to_string(); + format!("[{}.{}]", left, right) + } + _ => { + let span = prop_key.span(); + module_info.source_text()[span.start as usize..span.end as usize] + .to_string() + } } } diff --git a/src/parser.rs b/src/parser.rs index ca8cfa0bd..a8466f8b8 100644 --- a/src/parser.rs +++ b/src/parser.rs @@ -1,26 +1,24 @@ // Copyright 2018-2024 the Deno authors. All rights reserved. MIT license. -use deno_ast::ModuleItemRef; -use deno_ast::SourceRange; -use deno_ast::SourceRanged; -use deno_ast::SourceRangedForSpanned; -use deno_ast::swc::ast::ClassDecl; -use deno_ast::swc::ast::Decl; -use deno_ast::swc::ast::DefaultDecl; -use deno_ast::swc::ast::ExportDecl; -use deno_ast::swc::ast::ExportDefaultDecl; -use deno_ast::swc::ast::ExportDefaultExpr; -use deno_ast::swc::ast::FnDecl; -use deno_ast::swc::ast::Ident; -use deno_ast::swc::ast::ModuleDecl; -use deno_ast::swc::ast::TsEnumDecl; -use deno_ast::swc::ast::TsInterfaceDecl; -use deno_ast::swc::ast::TsModuleDecl; -use deno_ast::swc::ast::TsModuleName; -use deno_ast::swc::ast::TsTypeAliasDecl; -use deno_ast::swc::ast::VarDecl; -use deno_ast::swc::ast::VarDeclKind; -use deno_ast::swc::ast::VarDeclarator; +use deno_ast::oxc::ast::ast::BindingIdentifier as Ident; +use deno_ast::oxc::ast::ast::Class; +use deno_ast::oxc::ast::ast::Declaration as OxcDeclaration; +use deno_ast::oxc::ast::ast::ExportDefaultDeclaration; +use deno_ast::oxc::ast::ast::ExportDefaultDeclarationKind; +use deno_ast::oxc::ast::ast::ExportNamedDeclaration; +use deno_ast::oxc::ast::ast::Expression; +use deno_ast::oxc::ast::ast::Function as FnDecl; +use deno_ast::oxc::ast::ast::ImportDeclarationSpecifier; +use deno_ast::oxc::ast::ast::Statement; +use deno_ast::oxc::ast::ast::TSEnumDeclaration as TsEnumDecl; +use deno_ast::oxc::ast::ast::TSInterfaceDeclaration as TsInterfaceDecl; +use deno_ast::oxc::ast::ast::TSModuleDeclaration as TsModuleDecl; +use deno_ast::oxc::ast::ast::TSModuleDeclarationName; +use deno_ast::oxc::ast::ast::TSTypeAliasDeclaration as TsTypeAliasDecl; +use deno_ast::oxc::ast::ast::VariableDeclaration as VarDecl; +use deno_ast::oxc::ast::ast::VariableDeclarator as VarDeclarator; +use deno_ast::oxc::span::GetSpan; +use deno_ast::oxc::span::Span; use deno_graph::Module; use deno_graph::ModuleGraph; use deno_graph::ModuleSpecifier; @@ -34,7 +32,6 @@ use deno_graph::symbols::SymbolDecl; use deno_graph::symbols::SymbolNodeRef; use deno_graph::symbols::UniqueSymbolId; use indexmap::IndexMap; -use std::borrow::Cow; use std::cell::RefCell; use std::collections::HashSet; use std::error::Error; @@ -64,10 +61,38 @@ use crate::util::swc::js_doc_for_range; use crate::util::swc::module_export_name_value; use crate::util::swc::module_js_doc_for_source; use crate::util::symbol::get_module_info; +use crate::util::types::VarDeclKind; use crate::variable::VariableDef; use crate::visibility::SymbolVisibility; use crate::{Declaration, Symbol}; +type SourceRange = Span; + +trait SpanCompat { + fn contains(self, other: Span) -> bool; +} + +impl SpanCompat for Span { + fn contains(self, other: Span) -> bool { + self.contains_inclusive(other) + } +} + +trait GetSpanCompat { + fn range(&self) -> Span; + fn start(&self) -> u32; +} + +impl GetSpanCompat for T { + fn range(&self) -> Span { + self.span() + } + + fn start(&self) -> u32 { + self.span().start + } +} + #[derive(Debug)] pub enum DocError { Resolve(String), @@ -121,11 +146,13 @@ impl<'a> DocParser<'a> { pub fn new( graph: &'a ModuleGraph, parser: &'a dyn EsParser, + allocator: &'a deno_ast::oxc::allocator::Allocator, specifiers: &'a [ModuleSpecifier], options: DocParserOptions, ) -> Result { - let root_symbol = - Rc::new(deno_graph::symbols::RootSymbol::new(graph, parser)); + let root_symbol = Rc::new(deno_graph::symbols::RootSymbol::new( + graph, parser, allocator, + )); let visibility = SymbolVisibility::build(graph, &root_symbol)?; let diagnostics = if options.diagnostics { @@ -473,18 +500,15 @@ impl<'a> DocParser<'a> { if let ModuleInfoRef::Esm(esm) = export.module { // Find the full export statement range, since the // definition range may start at `*` rather than `export`. - for item in esm.source().program_ref().body() { - if let ModuleItemRef::ModuleDecl(decl) = item { - let decl_range = decl.range(); - if decl_range.contains(first_def.range()) - && let Some(js_doc) = - js_doc_for_range(esm, &decl_range) - { - if !js_doc.is_empty() { - return js_doc; - } - break; + for item in esm.statements() { + let decl_range = item.span(); + if decl_range.contains(*first_def.range()) + && let Some(js_doc) = js_doc_for_range(esm, decl_range) + { + if !js_doc.is_empty() { + return js_doc; } + break; } } } @@ -535,49 +559,47 @@ impl<'a> DocParser<'a> { &self, module_info: &EsModuleInfo, ) -> Result, DocError> { - let parsed_source = module_info.source(); let referrer = module_info.specifier(); let mut imports = vec![]; - for node in parsed_source.program_ref().body() { - if let ModuleItemRef::ModuleDecl(ModuleDecl::Import(import_decl)) = node - && let Some(js_doc) = - js_doc_for_range(module_info, &import_decl.range()) + for stmt in module_info.statements() { + if let Statement::ImportDeclaration(import_decl) = stmt + && let Some(js_doc) = js_doc_for_range(module_info, import_decl.span) { - for specifier in &import_decl.specifiers { - use deno_ast::swc::ast::ImportSpecifier::*; - - let (imported_name, original_name, src) = match specifier { - Named(named_specifier) => ( - named_specifier.local.sym.to_string(), - named_specifier - .imported - .as_ref() - .map(module_export_name_value) - .or_else(|| Some(named_specifier.local.sym.to_string())), - &import_decl.src.value, - ), - Default(default_specifier) => ( - default_specifier.local.sym.to_string(), - Some("default".to_string()), - &import_decl.src.value, - ), - Namespace(namespace_specifier) => ( - namespace_specifier.local.sym.to_string(), - None, - &import_decl.src.value, - ), - }; - - let resolved_specifier = - self.resolve_dependency(&src.to_string_lossy(), referrer)?; - - imports.push(Import { - imported_name: imported_name.into_boxed_str(), - js_doc: js_doc.clone(), - src: resolved_specifier.to_string(), - original_name, - }); + if let Some(specifiers) = &import_decl.specifiers { + for specifier in specifiers { + let (imported_name, original_name, src) = match specifier { + ImportDeclarationSpecifier::ImportSpecifier(named_specifier) => ( + named_specifier.local.name.to_string(), + Some(module_export_name_value(&named_specifier.imported)), + &import_decl.source.value, + ), + ImportDeclarationSpecifier::ImportDefaultSpecifier( + default_specifier, + ) => ( + default_specifier.local.name.to_string(), + Some("default".to_string()), + &import_decl.source.value, + ), + ImportDeclarationSpecifier::ImportNamespaceSpecifier( + namespace_specifier, + ) => ( + namespace_specifier.local.name.to_string(), + None, + &import_decl.source.value, + ), + }; + + let resolved_specifier = + self.resolve_dependency(&src.to_string(), referrer)?; + + imports.push(Import { + imported_name: imported_name.into_boxed_str(), + js_doc: js_doc.clone(), + src: resolved_specifier.to_string(), + original_name, + }); + } } } } @@ -591,9 +613,8 @@ impl<'a> DocParser<'a> { expando_property: ExpandoPropertyRef, ) -> Option { let location = - get_location(module_info, expando_property.prop_name_range().start()); - let js_doc = - js_doc_for_range(module_info, &expando_property.inner().range())?; + get_location(module_info, expando_property.prop_name_span().start); + let js_doc = js_doc_for_range(module_info, expando_property.inner().span)?; let init = expando_property.assignment(); Some(decl_from_expr(module_info, init, location, js_doc)) @@ -605,24 +626,24 @@ impl<'a> DocParser<'a> { var_decl: &VarDecl, var_declarator: &VarDeclarator, ident: &Ident, - full_range: &SourceRange, + full_range: SourceRange, ) -> Option { - let full_range = if ident.start() != var_declarator.start() { - Cow::Owned(ident.range()) + let full_range = if ident.span.start != var_declarator.span.start { + ident.span } else { - Cow::Borrowed(full_range) + full_range }; - let js_doc = js_doc_for_range(module_info, &full_range)?; + let js_doc = js_doc_for_range(module_info, full_range)?; if let Some(init) = &var_declarator.init && matches!( - &**init, - deno_ast::swc::ast::Expr::Class(_) - | deno_ast::swc::ast::Expr::Fn(_) - | deno_ast::swc::ast::Expr::Arrow(_) + init, + Expression::ClassExpression(_) + | Expression::FunctionExpression(_) + | Expression::ArrowFunctionExpression(_) ) { - let location = get_location(module_info, ident.start()); + let location = get_location(module_info, ident.span.start); return Some(decl_from_expr(module_info, init, location, js_doc)); } @@ -635,9 +656,9 @@ impl<'a> DocParser<'a> { var_declarator, ) .into_iter() - .find(|(name, _)| name.as_str() == &*ident.sym) + .find(|(name, _)| name.as_str() == &*ident.name) .map(|(_name, var_def)| { - let location = get_location(module_info, ident.start()); + let location = get_location(module_info, ident.span.start); Declaration::variable(location, DeclarationKind::Declare, js_doc, var_def) }) } @@ -645,16 +666,16 @@ impl<'a> DocParser<'a> { fn get_doc_for_class_decl( &self, module_info: &EsModuleInfo, - class_decl: &ClassDecl, - full_range: &SourceRange, + class_decl: &Class, + full_range: SourceRange, ) -> Option { - let jsdoc_range = match class_decl.class.decorators.first() { - Some(decorator) if decorator.start() < full_range.start => { - Cow::Owned(SourceRange::new(decorator.start(), full_range.end)) + let jsdoc_range = match class_decl.decorators.first() { + Some(decorator) if decorator.span.start < full_range.start => { + SourceRange::new(decorator.span.start, full_range.end) } - _ => Cow::Borrowed(full_range), + _ => full_range, }; - let js_doc = js_doc_for_range(module_info, &jsdoc_range)?; + let js_doc = js_doc_for_range(module_info, jsdoc_range)?; // declared classes cannot have decorators, so we ignore that return let (class_def, _) = super::class::get_doc_for_class_decl(module_info, class_decl); @@ -671,7 +692,7 @@ impl<'a> DocParser<'a> { &self, module_info: &EsModuleInfo, fn_decl: &FnDecl, - full_range: &SourceRange, + full_range: SourceRange, ) -> Option { let js_doc = js_doc_for_range(module_info, full_range)?; let function_def = @@ -689,7 +710,7 @@ impl<'a> DocParser<'a> { &self, module_info: &EsModuleInfo, ts_interface_decl: &TsInterfaceDecl, - full_range: &SourceRange, + full_range: SourceRange, ) -> Option { let js_doc = js_doc_for_range(module_info, full_range)?; let interface_def = super::interface::get_doc_for_ts_interface_decl( @@ -710,7 +731,7 @@ impl<'a> DocParser<'a> { &self, module_info: &EsModuleInfo, ts_type_alias: &TsTypeAliasDecl, - full_range: &SourceRange, + full_range: SourceRange, ) -> Option { let js_doc = js_doc_for_range(module_info, full_range)?; let type_alias_def = super::type_alias::get_doc_for_ts_type_alias_decl( @@ -730,7 +751,7 @@ impl<'a> DocParser<'a> { &self, module_info: &EsModuleInfo, ts_enum: &TsEnumDecl, - full_range: &SourceRange, + full_range: SourceRange, ) -> Option { let js_doc = js_doc_for_range(module_info, full_range)?; let enum_def = @@ -749,7 +770,7 @@ impl<'a> DocParser<'a> { module_info: &EsModuleInfo, ns_symbol: &GraphSymbol, ts_module: &TsModuleDecl, - full_range: &SourceRange, + full_range: SourceRange, ) -> Option { fn symbol_in_ancestors( id: UniqueSymbolId, @@ -771,13 +792,12 @@ impl<'a> DocParser<'a> { .iter() .filter_map(|d| { d.maybe_node().and_then(|n| match n { - SymbolNodeRef::ExportDecl( - ExportDecl { - decl: Decl::TsModule(n), - .. - }, - _, - ) => Some(&**n), + SymbolNodeRef::ExportDecl(export_decl, _) => { + match &export_decl.declaration { + Some(OxcDeclaration::TSModuleDeclaration(n)) => Some(&**n), + _ => None, + } + } SymbolNodeRef::TsNamespace(n) => Some(n), _ => None, }) @@ -789,8 +809,8 @@ impl<'a> DocParser<'a> { } let _namespace_name = match &ts_module.id { - TsModuleName::Ident(ident) => ident.sym.to_string(), - TsModuleName::Str(str_) => str_.value.to_string_lossy().into_owned(), + TSModuleDeclarationName::Identifier(ident) => ident.name.to_string(), + TSModuleDeclarationName::StringLiteral(str_) => str_.value.to_string(), }; let mut elements = Vec::new(); let mut handled_symbols = HashSet::new(); @@ -915,18 +935,24 @@ impl<'a> DocParser<'a> { .and_then(|n| { use deno_graph::symbols::SymbolNodeRef; match n { - SymbolNodeRef::ClassDecl(n) => Some(n.ident.sym.to_string()), - SymbolNodeRef::FnDecl(n) => Some(n.ident.sym.to_string()), - SymbolNodeRef::TsEnum(n) => Some(n.id.sym.to_string()), - SymbolNodeRef::TsInterface(n) => Some(n.id.sym.to_string()), - SymbolNodeRef::TsTypeAlias(n) => Some(n.id.sym.to_string()), + SymbolNodeRef::ClassDecl(n) => { + n.id.as_ref().map(|id| id.name.to_string()) + } + SymbolNodeRef::FnDecl(n) => { + n.id.as_ref().map(|id| id.name.to_string()) + } + SymbolNodeRef::TsEnum(n) => Some(n.id.name.to_string()), + SymbolNodeRef::TsInterface(n) => Some(n.id.name.to_string()), + SymbolNodeRef::TsTypeAlias(n) => Some(n.id.name.to_string()), SymbolNodeRef::TsNamespace(n) => match &n.id { - TsModuleName::Ident(ident) => Some(ident.sym.to_string()), - TsModuleName::Str(s) => { - Some(s.value.to_string_lossy().into_owned()) + TSModuleDeclarationName::Identifier(ident) => { + Some(ident.name.to_string()) + } + TSModuleDeclarationName::StringLiteral(s) => { + Some(s.value.to_string()) } }, - SymbolNodeRef::Var(_, _, ident) => Some(ident.sym.to_string()), + SymbolNodeRef::Var(_, _, ident) => Some(ident.name.to_string()), SymbolNodeRef::ExportDefaultDecl(_) => { Some("default".to_string()) } @@ -955,21 +981,18 @@ impl<'a> DocParser<'a> { fn get_doc_for_export_default_decl( &self, module_info: &EsModuleInfo, - export_default_decl: &ExportDefaultDecl, + export_default_decl: &ExportDefaultDeclaration, ) -> Option { - let js_doc = js_doc_for_range(module_info, &export_default_decl.range())?; - let location = get_location(module_info, export_default_decl.start()); - let doc_node = match &export_default_decl.decl { - DefaultDecl::Class(class_expr) => { - let default_name = class_expr - .ident + let js_doc = js_doc_for_range(module_info, export_default_decl.span)?; + let location = get_location(module_info, export_default_decl.span.start); + let doc_node = match &export_default_decl.declaration { + ExportDefaultDeclarationKind::ClassDeclaration(class) => { + let default_name = class + .id .as_ref() - .map(|ident| ident.sym.to_string().into_boxed_str()); - let (class_def, decorator_js_doc) = crate::class::class_to_class_def( - module_info, - &class_expr.class, - default_name, - ); + .map(|ident| ident.name.to_string().into_boxed_str()); + let (class_def, decorator_js_doc) = + crate::class::class_to_class_def(module_info, class, default_name); let js_doc = if js_doc.is_empty() { decorator_js_doc } else { @@ -977,12 +1000,12 @@ impl<'a> DocParser<'a> { }; Declaration::class(location, DeclarationKind::Export, js_doc, class_def) } - DefaultDecl::Fn(fn_expr) => { + ExportDefaultDeclarationKind::FunctionDeclaration(function) => { let default_name = - fn_expr.ident.as_ref().map(|ident| ident.sym.to_string()); + function.id.as_ref().map(|ident| ident.name.to_string()); let function_def = crate::function::function_to_function_def( module_info, - &fn_expr.function, + function, default_name, ); Declaration::function( @@ -992,8 +1015,8 @@ impl<'a> DocParser<'a> { function_def, ) } - DefaultDecl::TsInterfaceDecl(interface_decl) => { - let default_name = interface_decl.id.sym.to_string(); + ExportDefaultDeclarationKind::TSInterfaceDeclaration(interface_decl) => { + let default_name = interface_decl.id.name.to_string(); let interface_def = crate::interface::get_doc_for_ts_interface_decl( module_info, interface_decl, @@ -1006,6 +1029,14 @@ impl<'a> DocParser<'a> { interface_def, ) } + _ => { + return self.get_decl_for_export_default_expr( + module_info, + &export_default_decl.declaration, + js_doc, + location, + ); + } }; Some(doc_node) @@ -1014,11 +1045,13 @@ impl<'a> DocParser<'a> { fn get_decl_for_export_default_expr( &self, module_info: &EsModuleInfo, - export_expr: &ExportDefaultExpr, + export_expr: &ExportDefaultDeclarationKind, + js_doc: JsDoc, + location: Location, ) -> Option { - let js_doc = js_doc_for_range(module_info, &export_expr.range())?; - let location = get_location(module_info, export_expr.start()); - if let deno_ast::swc::ast::Expr::Arrow(arrow_expr) = &*export_expr.expr { + if let ExportDefaultDeclarationKind::ArrowFunctionExpression(arrow_expr) = + export_expr + { let function_def = crate::function::arrow_to_function_def(module_info, arrow_expr); Some(Declaration::function( @@ -1036,7 +1069,7 @@ impl<'a> DocParser<'a> { kind: VarDeclKind::Var, ts_type: super::ts_type::infer_ts_type_from_expr( module_info, - export_expr.expr.as_ref(), + export_expr.as_expression()?, true, ), }, @@ -1052,7 +1085,7 @@ impl<'a> DocParser<'a> { target_range: &SourceRange, ) -> Option { if let Some(js_doc) = - js_doc_for_range(reference_module_info, &reference_range.range()) + js_doc_for_range(reference_module_info, reference_range.range()) { let location = get_location(reference_module_info, reference_range.start()); @@ -1371,7 +1404,7 @@ impl<'a> DocParser<'a> { ) -> Option { match node { SymbolNodeRef::ClassDecl(n) => { - self.get_doc_for_class_decl(module_info, n, &n.class.range()) + self.get_doc_for_class_decl(module_info, n, n.span) } SymbolNodeRef::ExpandoProperty(n) => { self.get_doc_for_expando_property(module_info, n) @@ -1380,22 +1413,24 @@ impl<'a> DocParser<'a> { self.get_doc_for_export_default_decl(module_info, n) } SymbolNodeRef::ExportDefaultExpr(n) => { - self.get_decl_for_export_default_expr(module_info, n) + let js_doc = js_doc_for_range(module_info, n.span())?; + let location = get_location(module_info, n.span().start); + self.get_decl_for_export_default_expr(module_info, n, js_doc, location) } SymbolNodeRef::FnDecl(n) => { - self.get_decl_for_fn_decl(module_info, n, &n.function.range()) + self.get_decl_for_fn_decl(module_info, n, n.span) } SymbolNodeRef::TsEnum(n) => { - self.get_decl_for_enum(module_info, n, &n.range()) + self.get_decl_for_enum(module_info, n, n.range()) } SymbolNodeRef::TsInterface(n) => { - self.get_decl_for_interface_decl(module_info, n, &n.range()) + self.get_decl_for_interface_decl(module_info, n, n.range()) } SymbolNodeRef::TsNamespace(n) => { - self.get_decl_for_ts_namespace(module_info, symbol, n, &n.range()) + self.get_decl_for_ts_namespace(module_info, symbol, n, n.range()) } SymbolNodeRef::TsTypeAlias(n) => { - self.get_decl_for_type_alias(module_info, n, &n.range()) + self.get_decl_for_type_alias(module_info, n, n.range()) } SymbolNodeRef::Var(parent_decl, n, ident) => self .get_doc_for_var_declarator_ident( @@ -1403,7 +1438,7 @@ impl<'a> DocParser<'a> { parent_decl, n, ident, - &parent_decl.range(), + parent_decl.range(), ), SymbolNodeRef::UsingVar(_, _, _) => { // makes no sense for using declarations to be in the public API @@ -1411,25 +1446,25 @@ impl<'a> DocParser<'a> { } SymbolNodeRef::ExportDecl(export_decl, inner) => match inner { ExportDeclRef::Class(n) => { - self.get_doc_for_class_decl(module_info, n, &export_decl.range()) + self.get_doc_for_class_decl(module_info, n, export_decl.range()) } ExportDeclRef::Fn(n) => { - self.get_decl_for_fn_decl(module_info, n, &export_decl.range()) + self.get_decl_for_fn_decl(module_info, n, export_decl.range()) } ExportDeclRef::TsEnum(n) => { - self.get_decl_for_enum(module_info, n, &export_decl.range()) + self.get_decl_for_enum(module_info, n, export_decl.range()) } ExportDeclRef::TsModule(n) => self.get_decl_for_ts_namespace( module_info, symbol, n, - &export_decl.range(), + export_decl.range(), ), ExportDeclRef::TsInterface(n) => { - self.get_decl_for_interface_decl(module_info, n, &export_decl.range()) + self.get_decl_for_interface_decl(module_info, n, export_decl.range()) } ExportDeclRef::TsTypeAlias(n) => { - self.get_decl_for_type_alias(module_info, n, &export_decl.range()) + self.get_decl_for_type_alias(module_info, n, export_decl.range()) } ExportDeclRef::Var(var_decl, var_declarator, ident) => self .get_doc_for_var_declarator_ident( @@ -1437,8 +1472,9 @@ impl<'a> DocParser<'a> { var_decl, var_declarator, ident, - &export_decl.range(), + export_decl.range(), ), + ExportDeclRef::TsImportEquals(_) => None, }, SymbolNodeRef::Module(_) | SymbolNodeRef::AutoAccessor(_) @@ -1462,7 +1498,9 @@ impl<'a> DocParser<'a> { fn get_declare_for_symbol_node(&self, node: SymbolNodeRef) -> bool { match node { SymbolNodeRef::ClassDecl(n) => n.declare, - SymbolNodeRef::ExportDecl(n, _) => self.get_declare_for_ast_decl(&n.decl), + SymbolNodeRef::ExportDecl(n, _) => { + self.get_declare_for_export_decl_declaration(n) + } SymbolNodeRef::ExportDefaultDecl(_) => false, SymbolNodeRef::ExportDefaultExpr(_) => false, SymbolNodeRef::FnDecl(n) => n.declare, @@ -1492,16 +1530,27 @@ impl<'a> DocParser<'a> { } } - fn get_declare_for_ast_decl(&self, decl: &Decl) -> bool { - match decl { - Decl::Class(class_decl) => class_decl.declare, - Decl::Fn(fn_decl) => fn_decl.declare, - Decl::TsEnum(ts_enum_decl) => ts_enum_decl.declare, - Decl::TsInterface(ts_interface_decl) => ts_interface_decl.declare, - Decl::TsModule(ts_module_decl) => ts_module_decl.declare, - Decl::TsTypeAlias(ts_type_alias_decl) => ts_type_alias_decl.declare, - Decl::Var(var_decl) => var_decl.declare, - Decl::Using(_) => false, + fn get_declare_for_export_decl_declaration( + &self, + export_decl: &ExportNamedDeclaration, + ) -> bool { + match &export_decl.declaration { + Some(OxcDeclaration::ClassDeclaration(class_decl)) => class_decl.declare, + Some(OxcDeclaration::FunctionDeclaration(fn_decl)) => fn_decl.declare, + Some(OxcDeclaration::TSEnumDeclaration(ts_enum_decl)) => { + ts_enum_decl.declare + } + Some(OxcDeclaration::TSInterfaceDeclaration(ts_interface_decl)) => { + ts_interface_decl.declare + } + Some(OxcDeclaration::TSModuleDeclaration(ts_module_decl)) => { + ts_module_decl.declare + } + Some(OxcDeclaration::TSTypeAliasDeclaration(ts_type_alias_decl)) => { + ts_type_alias_decl.declare + } + Some(OxcDeclaration::VariableDeclaration(var_decl)) => var_decl.declare, + _ => false, } } @@ -1524,21 +1573,18 @@ impl<'a> DocParser<'a> { fn decl_from_expr( module_info: &EsModuleInfo, - expr: &deno_ast::swc::ast::Expr, + expr: &Expression, location: Location, js_doc: JsDoc, ) -> Declaration { match expr { - deno_ast::swc::ast::Expr::Class(class_expr) => { + Expression::ClassExpression(class_expr) => { let def_name = class_expr - .ident + .id .as_ref() - .map(|id| id.sym.to_string().into_boxed_str()); - let (class_def, decorator_js_doc) = crate::class::class_to_class_def( - module_info, - &class_expr.class, - def_name, - ); + .map(|id| id.name.to_string().into_boxed_str()); + let (class_def, decorator_js_doc) = + crate::class::class_to_class_def(module_info, class_expr, def_name); let js_doc = if js_doc.is_empty() { decorator_js_doc } else { @@ -1546,11 +1592,11 @@ fn decl_from_expr( }; Declaration::class(location, DeclarationKind::Declare, js_doc, class_def) } - deno_ast::swc::ast::Expr::Fn(fn_expr) => { - let def_name = fn_expr.ident.as_ref().map(|id| id.sym.to_string()); + Expression::FunctionExpression(fn_expr) => { + let def_name = fn_expr.id.as_ref().map(|id| id.name.to_string()); let function_def = crate::function::function_to_function_def( module_info, - &fn_expr.function, + fn_expr, def_name, ); Declaration::function( @@ -1560,7 +1606,7 @@ fn decl_from_expr( function_def, ) } - deno_ast::swc::ast::Expr::Arrow(arrow_expr) => { + Expression::ArrowFunctionExpression(arrow_expr) => { let function_def = crate::function::arrow_to_function_def(module_info, arrow_expr); Declaration::function( @@ -1656,12 +1702,10 @@ fn parse_json_module_type(value: &serde_json::Value) -> TsTypeDef { } fn module_has_import(module_info: &EsModuleInfo) -> bool { - module_info.source().program_ref().body().any(|m| { + module_info.statements().iter().any(|m| { matches!( m, - ModuleItemRef::ModuleDecl( - ModuleDecl::Import(_) | ModuleDecl::TsImportEquals(_) - ) + Statement::ImportDeclaration(_) | Statement::TSImportEqualsDeclaration(_) ) }) } diff --git a/src/printer.rs b/src/printer.rs index 60b1eedc5..0ef112a47 100644 --- a/src/printer.rs +++ b/src/printer.rs @@ -494,8 +494,8 @@ impl DocPrinter<'_> { self.private || node .accessibility - .unwrap_or(deno_ast::swc::ast::Accessibility::Public) - != deno_ast::swc::ast::Accessibility::Private + .unwrap_or(crate::util::types::Accessibility::Public) + != crate::util::types::Accessibility::Private }) { for d in node.decorators.iter() { writeln!(w, "{}{}", Indent(1), d)?; @@ -510,8 +510,8 @@ impl DocPrinter<'_> { self.private || node .accessibility - .unwrap_or(deno_ast::swc::ast::Accessibility::Public) - != deno_ast::swc::ast::Accessibility::Private + .unwrap_or(crate::util::types::Accessibility::Public) + != crate::util::types::Accessibility::Private }) { let has_overloads = class_def .methods @@ -814,9 +814,9 @@ impl DocPrinter<'_> { Indent(indent), fmt_visibility(decl.declaration_kind), colors::magenta(match variable_def.kind { - deno_ast::swc::ast::VarDeclKind::Const => "const", - deno_ast::swc::ast::VarDeclKind::Let => "let", - deno_ast::swc::ast::VarDeclKind::Var => "var", + crate::util::types::VarDeclKind::Const => "const", + crate::util::types::VarDeclKind::Let => "let", + crate::util::types::VarDeclKind::Var => "var", }), colors::bold(&node.name), )?; diff --git a/src/tests.rs b/src/tests.rs index ba8f0a8fc..39f8ce914 100644 --- a/src/tests.rs +++ b/src/tests.rs @@ -51,6 +51,17 @@ pub(crate) async fn setup + Copy, C: AsRef<[u8]>>( (graph, analyzer, root) } +fn new_doc_parser<'a>( + graph: &'a ModuleGraph, + analyzer: &'a CapturingModuleAnalyzer, + roots: &'a [ModuleSpecifier], + options: DocParserOptions, +) -> DocParser<'a> { + let allocator = + Box::leak(Box::new(deno_ast::oxc::allocator::Allocator::default())); + DocParser::new(graph, analyzer, allocator, roots, options).unwrap() +} + #[tokio::test] async fn content_type_handling() { let sources = vec![( @@ -82,8 +93,7 @@ async fn content_type_handling() { ) .await; let entries = - DocParser::new(&graph, &analyzer, &[root], DocParserOptions::default()) - .unwrap() + new_doc_parser(&graph, &analyzer, &[root], DocParserOptions::default()) .parse() .unwrap() .into_values() @@ -135,8 +145,7 @@ async fn types_header_handling() { ) .await; let entries = - DocParser::new(&graph, &analyzer, &[root], DocParserOptions::default()) - .unwrap() + new_doc_parser(&graph, &analyzer, &[root], DocParserOptions::default()) .parse() .unwrap() .into_values() @@ -224,13 +233,12 @@ export function fooFn(a: number) { ], ) .await; - let output = DocParser::new( + let output = new_doc_parser( &graph, &analyzer, &[specifier], DocParserOptions::default(), ) - .unwrap() .parse() .unwrap(); let document = output.values().next().unwrap(); @@ -361,13 +369,12 @@ export { Hello } from "./reexport.ts"; ], ) .await; - let output = DocParser::new( + let output = new_doc_parser( &graph, &analyzer, &[specifier], DocParserOptions::default(), ) - .unwrap() .parse() .unwrap(); let entries = &output.values().next().unwrap().symbols; @@ -424,13 +431,12 @@ async fn deep_reexports() { ], ) .await; - let output = DocParser::new( + let output = new_doc_parser( &graph, &analyzer, &[specifier], DocParserOptions::default(), ) - .unwrap() .parse() .unwrap(); let entries = &output.values().next().unwrap().symbols; @@ -491,13 +497,12 @@ export * as b from "./mod_doc.ts"; ], ) .await; - let entries = DocParser::new( + let entries = new_doc_parser( &graph, &analyzer, &[specifier], DocParserOptions::default(), ) - .unwrap() .parse() .unwrap() .into_values() @@ -596,13 +601,12 @@ export namespace Deno { vec![("file:///test.ts", None, source_code)], ) .await; - let entries = DocParser::new( + let entries = new_doc_parser( &graph, &analyzer, &[specifier], DocParserOptions::default(), ) - .unwrap() .parse() .unwrap() .into_values() @@ -690,13 +694,12 @@ async fn exports_imported_earlier() { ], ) .await; - let document = DocParser::new( + let document = new_doc_parser( &graph, &analyzer, &[specifier], DocParserOptions::default(), ) - .unwrap() .parse() .unwrap() .into_values() @@ -757,13 +760,12 @@ async fn exports_imported_earlier_renamed() { ], ) .await; - let document = DocParser::new( + let document = new_doc_parser( &graph, &analyzer, &[specifier], DocParserOptions::default(), ) - .unwrap() .parse() .unwrap() .into_values() @@ -825,13 +827,12 @@ async fn exports_imported_earlier_default() { ], ) .await; - let document = DocParser::new( + let document = new_doc_parser( &graph, &analyzer, &[specifier], DocParserOptions::default(), ) - .unwrap() .parse() .unwrap() .into_values() @@ -892,7 +893,7 @@ async fn exports_imported_earlier_private() { ], ) .await; - let document = DocParser::new( + let document = new_doc_parser( &graph, &analyzer, &[specifier], @@ -901,7 +902,6 @@ async fn exports_imported_earlier_private() { ..Default::default() }, ) - .unwrap() .parse() .unwrap() .into_values() @@ -957,8 +957,7 @@ async fn variable_syntax() { .await; // This just needs to not throw a syntax error - DocParser::new(&graph, &analyzer, &[specifier], DocParserOptions::default()) - .unwrap() + new_doc_parser(&graph, &analyzer, &[specifier], DocParserOptions::default()) .parse() .unwrap(); } @@ -974,13 +973,12 @@ async fn json_module() { ) .await; - let entries = DocParser::new( + let entries = new_doc_parser( &graph, &analyzer, &[specifier], DocParserOptions::default(), ) - .unwrap() .parse() .unwrap() .into_values() diff --git a/src/ts_type.rs b/src/ts_type.rs index 9a1355dfe..40c436092 100644 --- a/src/ts_type.rs +++ b/src/ts_type.rs @@ -8,22 +8,24 @@ use crate::display::display_optional; use crate::display::display_readonly; use crate::interface::expr_to_name; use crate::node::Symbol; -use crate::params::param_to_param_def; -use crate::params::pat_to_param_def; +use crate::params::ParamPatternDef; +use crate::params::formal_params_to_param_defs; use crate::params::prop_name_to_string; -use crate::params::ts_fn_param_to_param_def; use crate::ts_type_param::TsTypeParamDef; use crate::ts_type_param::maybe_type_param_decl_to_type_param_defs; use crate::util::swc::get_location; use crate::util::swc::is_false; use crate::util::swc::js_doc_for_range; +use crate::util::types::MethodKind; +use crate::util::types::VarDeclKind; use crate::function::FunctionDef; use crate::js_doc::JsDoc; use crate::node::DeclarationKind; use crate::variable::VariableDef; -use deno_ast::SourceRangedForSpanned; -use deno_ast::swc::ast::*; +use deno_ast::oxc::ast::ast::*; +use deno_ast::oxc::span::GetSpan; +use deno_ast::oxc::syntax::operator::BinaryOperator; use deno_graph::symbols::EsModuleInfo; use deno_terminal::colors; use serde::Deserialize; @@ -32,26 +34,107 @@ use std::fmt::Display; use std::fmt::Formatter; use std::fmt::Result as FmtResult; +/// Mirrors the old SWC `TruePlusMinus` enum with matching serde. +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +pub enum TruePlusMinus { + True, + Plus, + Minus, +} + +impl Serialize for TruePlusMinus { + fn serialize( + &self, + serializer: S, + ) -> Result { + match self { + TruePlusMinus::True => serializer.serialize_bool(true), + TruePlusMinus::Plus => serializer.serialize_str("plus"), + TruePlusMinus::Minus => serializer.serialize_str("minus"), + } + } +} + +impl<'de> Deserialize<'de> for TruePlusMinus { + fn deserialize>( + deserializer: D, + ) -> Result { + use serde::de; + struct TruePlusMinusVisitor; + impl<'de> de::Visitor<'de> for TruePlusMinusVisitor { + type Value = TruePlusMinus; + + fn expecting(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { + f.write_str("true, \"plus\", or \"minus\"") + } + + fn visit_bool(self, v: bool) -> Result { + if v { + Ok(TruePlusMinus::True) + } else { + Err(E::custom("expected true, got false")) + } + } + + fn visit_str(self, v: &str) -> Result { + match v { + "plus" => Ok(TruePlusMinus::Plus), + "minus" => Ok(TruePlusMinus::Minus), + _ => Err(E::custom(format!("unknown value: {}", v))), + } + } + } + deserializer.deserialize_any(TruePlusMinusVisitor) + } +} + +impl From for TruePlusMinus { + fn from(op: TSMappedTypeModifierOperator) -> Self { + match op { + TSMappedTypeModifierOperator::True => TruePlusMinus::True, + TSMappedTypeModifierOperator::Plus => TruePlusMinus::Plus, + TSMappedTypeModifierOperator::Minus => TruePlusMinus::Minus, + } + } +} + impl TsTypeDef { - fn ts_lit_type(module_info: &EsModuleInfo, other: &TsLitType) -> Self { - match &other.lit { - TsLit::Number(num) => TsTypeDef::number_literal(num), - TsLit::Str(str_) => TsTypeDef::string_literal(str_), - TsLit::Tpl(tpl) => TsTypeDef::tpl_literal( + fn ts_lit_type(module_info: &EsModuleInfo, other: &TSLiteralType) -> Self { + match &other.literal { + TSLiteral::NumericLiteral(num) => TsTypeDef::number_literal(num), + TSLiteral::StringLiteral(str_) => { + TsTypeDef::string_value(str_.value.to_string()) + } + TSLiteral::TemplateLiteral(tpl) => TsTypeDef::tpl_literal( tpl - .types + .expressions .iter() - .map(|types| TsTypeDef::new(module_info, types)) + .filter_map(|expr| infer_ts_type_from_expr(module_info, expr, true)) .collect::>(), &tpl.quasis, ), - TsLit::Bool(bool_) => TsTypeDef::bool_literal(bool_), - TsLit::BigInt(bigint_) => TsTypeDef::bigint_literal(bigint_), + TSLiteral::BooleanLiteral(bool_) => TsTypeDef::bool_literal(bool_), + TSLiteral::BigIntLiteral(bigint_) => TsTypeDef::bigint_literal(bigint_), + TSLiteral::UnaryExpression(_) => TsTypeDef::keyword("number"), } } - fn ts_array_type(module_info: &EsModuleInfo, other: &TsArrayType) -> Self { - let ts_type_def = TsTypeDef::new(module_info, &other.elem_type); + fn ts_template_literal_type( + module_info: &EsModuleInfo, + other: &TSTemplateLiteralType, + ) -> Self { + TsTypeDef::tpl_literal( + other + .types + .iter() + .map(|t| TsTypeDef::new(module_info, t)) + .collect::>(), + &other.quasis, + ) + } + + fn ts_array_type(module_info: &EsModuleInfo, other: &TSArrayType) -> Self { + let ts_type_def = TsTypeDef::new(module_info, &other.element_type); TsTypeDef { kind: TsTypeDefKind::Array(Box::new(ts_type_def)), @@ -59,11 +142,11 @@ impl TsTypeDef { } } - fn ts_tuple_type(module_info: &EsModuleInfo, other: &TsTupleType) -> Self { + fn ts_tuple_type(module_info: &EsModuleInfo, other: &TSTupleType) -> Self { let type_defs = other - .elem_types + .element_types .iter() - .map(|type_box| TsTypeDef::new(module_info, &type_box.ty)) + .map(|elem| ts_tuple_element_to_ts_type_def(module_info, elem)) .collect::>(); TsTypeDef { @@ -72,69 +155,47 @@ impl TsTypeDef { } } - fn ts_union_or_intersection_type( - module_info: &EsModuleInfo, - other: &TsUnionOrIntersectionType, - ) -> Self { - use deno_ast::swc::ast::TsUnionOrIntersectionType::*; - - match other { - TsUnionType(union_type) => { - let types_union = union_type - .types - .iter() - .map(|ts_type| TsTypeDef::new(module_info, ts_type)) - .collect::>(); - - TsTypeDef { - kind: TsTypeDefKind::Union(types_union), - repr: String::new(), - } - } - TsIntersectionType(intersection_type) => { - let types_intersection = intersection_type - .types - .iter() - .map(|ts_type| TsTypeDef::new(module_info, ts_type)) - .collect::>(); + fn ts_union_type(module_info: &EsModuleInfo, other: &TSUnionType) -> Self { + let types_union = other + .types + .iter() + .map(|ts_type| TsTypeDef::new(module_info, ts_type)) + .collect::>(); - TsTypeDef { - kind: TsTypeDefKind::Intersection(types_intersection), - repr: String::new(), - } - } + TsTypeDef { + kind: TsTypeDefKind::Union(types_union), + repr: String::new(), } } - fn ts_keyword_type(other: &TsKeywordType) -> Self { - use deno_ast::swc::ast::TsKeywordTypeKind::*; - - let keyword_str = match other.kind { - TsAnyKeyword => "any", - TsUnknownKeyword => "unknown", - TsNumberKeyword => "number", - TsObjectKeyword => "object", - TsBooleanKeyword => "boolean", - TsBigIntKeyword => "bigint", - TsStringKeyword => "string", - TsSymbolKeyword => "symbol", - TsVoidKeyword => "void", - TsUndefinedKeyword => "undefined", - TsNullKeyword => "null", - TsNeverKeyword => "never", - TsIntrinsicKeyword => "intrinsic", - }; + fn ts_intersection_type( + module_info: &EsModuleInfo, + other: &TSIntersectionType, + ) -> Self { + let types_intersection = other + .types + .iter() + .map(|ts_type| TsTypeDef::new(module_info, ts_type)) + .collect::>(); - TsTypeDef::keyword(keyword_str) + TsTypeDef { + kind: TsTypeDefKind::Intersection(types_intersection), + repr: String::new(), + } } fn ts_type_operator( module_info: &EsModuleInfo, - other: &TsTypeOperator, + other: &TSTypeOperator, ) -> Self { - let ts_type = TsTypeDef::new(module_info, &other.type_ann); + let ts_type = TsTypeDef::new(module_info, &other.type_annotation); + let operator = match other.operator { + TSTypeOperatorOperator::Keyof => "keyof", + TSTypeOperatorOperator::Unique => "unique", + TSTypeOperatorOperator::Readonly => "readonly", + }; let type_operator_def = TsTypeOperatorDef { - operator: other.op.as_str().to_string(), + operator: operator.to_string(), ts_type, }; @@ -146,9 +207,9 @@ impl TsTypeDef { fn ts_parenthesized_type( module_info: &EsModuleInfo, - other: &TsParenthesizedType, + other: &TSParenthesizedType, ) -> Self { - let ts_type = TsTypeDef::new(module_info, &other.type_ann); + let ts_type = TsTypeDef::new(module_info, &other.type_annotation); TsTypeDef { kind: TsTypeDefKind::Parenthesized(Box::new(ts_type)), @@ -156,8 +217,8 @@ impl TsTypeDef { } } - fn ts_rest_type(module_info: &EsModuleInfo, other: &TsRestType) -> Self { - let ts_type = TsTypeDef::new(module_info, &other.type_ann); + fn ts_rest_type(module_info: &EsModuleInfo, other: &TSRestType) -> Self { + let ts_type = TsTypeDef::new(module_info, &other.type_annotation); TsTypeDef { kind: TsTypeDefKind::Rest(Box::new(ts_type)), @@ -167,9 +228,9 @@ impl TsTypeDef { fn ts_optional_type( module_info: &EsModuleInfo, - other: &TsOptionalType, + other: &TSOptionalType, ) -> Self { - let ts_type = TsTypeDef::new(module_info, &other.type_ann); + let ts_type = TsTypeDef::new(module_info, &other.type_annotation); TsTypeDef { kind: TsTypeDefKind::Optional(Box::new(ts_type)), @@ -177,7 +238,7 @@ impl TsTypeDef { } } - fn ts_this_type(_other: &TsThisType) -> Self { + fn ts_this_type(_other: &TSThisType) -> Self { TsTypeDef { repr: "this".to_string(), kind: TsTypeDefKind::This, @@ -186,15 +247,15 @@ impl TsTypeDef { fn ts_type_predicate( module_info: &EsModuleInfo, - other: &TsTypePredicate, + other: &TSTypePredicate, ) -> Self { let pred = TsTypePredicateDef { asserts: other.asserts, - param: (&other.param_name).into(), + param: ts_type_predicate_name_to_this_or_ident(&other.parameter_name), r#type: other - .type_ann + .type_annotation .as_ref() - .map(|t| Box::new(TsTypeDef::new(module_info, &t.type_ann))), + .map(|t| Box::new(TsTypeDef::new(module_info, &t.type_annotation))), }; let mut repr_parts = Vec::new(); if pred.asserts { @@ -214,15 +275,8 @@ impl TsTypeDef { } } - fn ts_type_query(other: &TsTypeQuery) -> Self { - use deno_ast::swc::ast::TsTypeQueryExpr::*; - - let type_name = match &other.expr_name { - TsEntityName(entity_name) => ts_entity_name_to_name(entity_name), - Import(import_type) => { - import_type.arg.value.to_string_lossy().into_owned() - } - }; + fn ts_type_query(other: &TSTypeQuery) -> Self { + let type_name = ts_type_query_expr_name_to_name(&other.expr_name); TsTypeDef { repr: type_name.to_string(), @@ -230,10 +284,10 @@ impl TsTypeDef { } } - fn ts_type_ref(module_info: &EsModuleInfo, other: &TsTypeRef) -> Self { - let type_name = ts_entity_name_to_name(&other.type_name); + fn ts_type_ref(module_info: &EsModuleInfo, other: &TSTypeReference) -> Self { + let type_name = ts_type_name_to_name(&other.type_name); - let type_params = if let Some(type_params_inst) = &other.type_params { + let type_params = if let Some(type_params_inst) = &other.type_arguments { let ts_type_defs = type_params_inst .params .iter() @@ -245,8 +299,8 @@ impl TsTypeDef { None }; - let root_ident = ts_entity_name_root_ident(&other.type_name); - let resolution = resolve_type_ref(module_info, root_ident); + let resolution = ts_type_name_root_ident(&other.type_name) + .and_then(|ident| resolve_type_ref(module_info, ident)); TsTypeDef { repr: type_name.clone(), @@ -260,11 +314,49 @@ impl TsTypeDef { pub fn ts_expr_with_type_args( module_info: &EsModuleInfo, - other: &TsExprWithTypeArgs, + other: &TSClassImplements, + ) -> Self { + let type_name = ts_type_name_to_name(&other.expression); + + let type_params = if let Some(type_params_inst) = &other.type_arguments { + let ts_type_defs = type_params_inst + .params + .iter() + .map(|ts_type| TsTypeDef::new(module_info, ts_type)) + .collect::>(); + + Some(ts_type_defs) + } else { + None + }; + + let resolution = ts_type_name_root_ident(&other.expression) + .and_then(|i| resolve_type_ref(module_info, i)); + + TsTypeDef { + repr: type_name.clone(), + kind: TsTypeDefKind::TypeRef(TsTypeRefDef { + type_params, + type_name, + resolution, + }), + } + } + + pub fn ts_class_implements( + module_info: &EsModuleInfo, + other: &TSClassImplements, ) -> Self { - let type_name = expr_to_name(&other.expr); + Self::ts_expr_with_type_args(module_info, other) + } - let type_params = if let Some(type_params_inst) = &other.type_args { + pub fn ts_interface_heritage( + module_info: &EsModuleInfo, + other: &TSInterfaceHeritage, + ) -> Self { + let type_name = expr_to_name(&other.expression); + + let type_params = if let Some(type_params_inst) = &other.type_arguments { let ts_type_defs = type_params_inst .params .iter() @@ -276,7 +368,7 @@ impl TsTypeDef { None }; - let resolution = expr_root_ident(&other.expr) + let resolution = expr_root_ident(&other.expression) .and_then(|i| resolve_type_ref(module_info, i)); TsTypeDef { @@ -291,11 +383,11 @@ impl TsTypeDef { fn ts_indexed_access_type( module_info: &EsModuleInfo, - other: &TsIndexedAccessType, + other: &TSIndexedAccessType, ) -> Self { let indexed_access_def = TsIndexedAccessDef { - readonly: other.readonly, - obj_type: Box::new(TsTypeDef::new(module_info, &other.obj_type)), + readonly: false, + obj_type: Box::new(TsTypeDef::new(module_info, &other.object_type)), index_type: Box::new(TsTypeDef::new(module_info, &other.index_type)), }; @@ -305,17 +397,21 @@ impl TsTypeDef { } } - fn ts_mapped_type(module_info: &EsModuleInfo, other: &TsMappedType) -> Self { + fn ts_mapped_type(module_info: &EsModuleInfo, other: &TSMappedType) -> Self { let mapped_type_def = TsMappedTypeDef { - readonly: other.readonly, - type_param: Box::new(TsTypeParamDef::new(module_info, &other.type_param)), + readonly: other.readonly.map(TruePlusMinus::from), + type_param: Box::new(TsTypeParamDef { + name: other.key.name.to_string(), + constraint: Some(TsTypeDef::new(module_info, &other.constraint)), + default: None, + }), name_type: other .name_type .as_ref() .map(|nt| Box::new(TsTypeDef::new(module_info, nt))), - optional: other.optional, + optional: other.optional.map(TruePlusMinus::from), ts_type: other - .type_ann + .type_annotation .as_ref() .map(|a| Box::new(TsTypeDef::new(module_info, a))), }; @@ -326,7 +422,7 @@ impl TsTypeDef { } } - fn ts_type_lit(module_info: &EsModuleInfo, other: &TsTypeLit) -> Self { + fn ts_type_lit(module_info: &EsModuleInfo, other: &TSTypeLiteral) -> Self { let mut constructors = vec![]; let mut methods = vec![]; let mut properties = vec![]; @@ -334,33 +430,32 @@ impl TsTypeDef { let mut index_signatures = vec![]; for type_element in &other.members { - use deno_ast::swc::ast::TsTypeElement::*; - - match &type_element { - TsMethodSignature(ts_method_sig) => { - let js_doc = js_doc_for_range(module_info, &ts_method_sig.range()) + match type_element { + TSSignature::TSMethodSignature(ts_method_sig) => { + let js_doc = js_doc_for_range(module_info, ts_method_sig.span) .unwrap_or_default(); - let params = ts_method_sig - .params - .iter() - .map(|param| ts_fn_param_to_param_def(module_info, param)) - .collect::>(); + let params = + formal_params_to_param_defs(module_info, &ts_method_sig.params); let maybe_return_type = ts_method_sig - .type_ann + .return_type .as_ref() - .map(|rt| TsTypeDef::new(module_info, &rt.type_ann)); + .map(|rt| TsTypeDef::new(module_info, &rt.type_annotation)); let type_params = maybe_type_param_decl_to_type_param_defs( module_info, - ts_method_sig.type_params.as_deref(), + ts_method_sig.type_parameters.as_deref(), ); - let name = expr_to_name(&ts_method_sig.key); - let location = get_location(module_info, ts_method_sig.start()); + let name = ts_method_sig + .key + .static_name() + .map(|name| name.to_string()) + .unwrap_or_else(|| "[UNSUPPORTED]".to_string()); + let location = get_location(module_info, ts_method_sig.span.start); let method_def = MethodDef { name, js_doc, - kind: MethodKind::Method, + kind: MethodKind::from(ts_method_sig.kind), location, params, computed: ts_method_sig.computed, @@ -370,64 +465,23 @@ impl TsTypeDef { }; methods.push(method_def); } - TsGetterSignature(ts_getter_sig) => { - let js_doc = js_doc_for_range(module_info, &ts_getter_sig.range()) - .unwrap_or_default(); - let maybe_return_type = ts_getter_sig - .type_ann - .as_ref() - .map(|rt| TsTypeDef::new(module_info, &rt.type_ann)); - - let name = expr_to_name(&ts_getter_sig.key); - let location = get_location(module_info, ts_getter_sig.start()); - let method_def = MethodDef { - name, - js_doc, - kind: MethodKind::Getter, - location, - params: vec![], - computed: ts_getter_sig.computed, - optional: false, - return_type: maybe_return_type, - type_params: Box::new([]), - }; - methods.push(method_def); - } - TsSetterSignature(ts_setter_sig) => { - let js_doc = js_doc_for_range(module_info, &ts_setter_sig.range()) - .unwrap_or_default(); - let name = expr_to_name(&ts_setter_sig.key); - - let params = - vec![ts_fn_param_to_param_def(module_info, &ts_setter_sig.param)]; - - let location = get_location(module_info, ts_setter_sig.start()); - let method_def = MethodDef { - name, - js_doc, - kind: MethodKind::Setter, - location, - params, - computed: ts_setter_sig.computed, - optional: false, - return_type: None, - type_params: Box::new([]), - }; - methods.push(method_def); - } - TsPropertySignature(ts_prop_sig) => { - let js_doc = js_doc_for_range(module_info, &ts_prop_sig.range()) - .unwrap_or_default(); - let name = expr_to_name(&ts_prop_sig.key); + TSSignature::TSPropertySignature(ts_prop_sig) => { + let js_doc = + js_doc_for_range(module_info, ts_prop_sig.span).unwrap_or_default(); + let name = ts_prop_sig + .key + .static_name() + .map(|name| name.to_string()) + .unwrap_or_else(|| "[UNSUPPORTED]".to_string()); let ts_type = ts_prop_sig - .type_ann + .type_annotation .as_ref() - .map(|rt| TsTypeDef::new(module_info, &rt.type_ann)); + .map(|rt| TsTypeDef::new(module_info, &rt.type_annotation)); let type_params = maybe_type_param_decl_to_type_param_defs(module_info, None); - let location = get_location(module_info, ts_prop_sig.start()); + let location = get_location(module_info, ts_prop_sig.span.start); let prop_def = PropertyDef { name, js_doc, @@ -441,26 +495,23 @@ impl TsTypeDef { }; properties.push(prop_def); } - TsCallSignatureDecl(ts_call_sig) => { - let js_doc = js_doc_for_range(module_info, &ts_call_sig.range()) - .unwrap_or_default(); - let params = ts_call_sig - .params - .iter() - .map(|param| ts_fn_param_to_param_def(module_info, param)) - .collect(); + TSSignature::TSCallSignatureDeclaration(ts_call_sig) => { + let js_doc = + js_doc_for_range(module_info, ts_call_sig.span).unwrap_or_default(); + let params = + formal_params_to_param_defs(module_info, &ts_call_sig.params); let ts_type = ts_call_sig - .type_ann + .return_type .as_ref() - .map(|rt| TsTypeDef::new(module_info, &rt.type_ann)); + .map(|rt| TsTypeDef::new(module_info, &rt.type_annotation)); let type_params = maybe_type_param_decl_to_type_param_defs( module_info, - ts_call_sig.type_params.as_deref(), + ts_call_sig.type_parameters.as_deref(), ); - let location = get_location(module_info, ts_call_sig.start()); + let location = get_location(module_info, ts_call_sig.span.start); let call_sig_def = CallSignatureDef { js_doc, location, @@ -470,21 +521,34 @@ impl TsTypeDef { }; call_signatures.push(call_sig_def); } - TsIndexSignature(ts_index_sig) => { - let js_doc = js_doc_for_range(module_info, &ts_index_sig.range()) + TSSignature::TSIndexSignature(ts_index_sig) => { + let js_doc = js_doc_for_range(module_info, ts_index_sig.span) .unwrap_or_default(); let params = ts_index_sig - .params + .parameters .iter() - .map(|param| ts_fn_param_to_param_def(module_info, param)) + .map(|param| { + let ts_type = Some(TsTypeDef::new( + module_info, + ¶m.type_annotation.type_annotation, + )); + ParamDef { + pattern: ParamPatternDef::Identifier { + name: param.name.to_string(), + optional: false, + }, + decorators: Box::new([]), + ts_type, + } + }) .collect(); - let ts_type = ts_index_sig - .type_ann - .as_ref() - .map(|rt| TsTypeDef::new(module_info, &rt.type_ann)); + let ts_type = Some(TsTypeDef::new( + module_info, + &ts_index_sig.type_annotation.type_annotation, + )); - let location = get_location(module_info, ts_index_sig.start()); + let location = get_location(module_info, ts_index_sig.span.start); let index_sig_def = IndexSignatureDef { js_doc, location, @@ -494,26 +558,23 @@ impl TsTypeDef { }; index_signatures.push(index_sig_def); } - TsConstructSignatureDecl(ts_construct_sig) => { - let js_doc = js_doc_for_range(module_info, &ts_construct_sig.range()) + TSSignature::TSConstructSignatureDeclaration(ts_construct_sig) => { + let js_doc = js_doc_for_range(module_info, ts_construct_sig.span) .unwrap_or_default(); - let params = ts_construct_sig - .params - .iter() - .map(|param| ts_fn_param_to_param_def(module_info, param)) - .collect(); + let params = + formal_params_to_param_defs(module_info, &ts_construct_sig.params); let type_params = maybe_type_param_decl_to_type_param_defs( module_info, - ts_construct_sig.type_params.as_deref(), + ts_construct_sig.type_parameters.as_deref(), ); let maybe_return_type = ts_construct_sig - .type_ann + .return_type .as_ref() - .map(|rt| TsTypeDef::new(module_info, &rt.type_ann)); + .map(|rt| TsTypeDef::new(module_info, &rt.type_annotation)); - let location = get_location(module_info, ts_construct_sig.start()); + let location = get_location(module_info, ts_construct_sig.span.start); let construct_sig_def = ConstructorDef { js_doc, location, @@ -543,7 +604,7 @@ impl TsTypeDef { fn ts_conditional_type( module_info: &EsModuleInfo, - other: &TsConditionalType, + other: &TSConditionalType, ) -> Self { let conditional_type_def = TsConditionalDef { check_type: Box::new(TsTypeDef::new(module_info, &other.check_type)), @@ -558,9 +619,12 @@ impl TsTypeDef { } } - fn ts_infer_type(module_info: &EsModuleInfo, other: &TsInferType) -> Self { + fn ts_infer_type(module_info: &EsModuleInfo, other: &TSInferType) -> Self { let infer = TsInferDef { - type_param: Box::new(TsTypeParamDef::new(module_info, &other.type_param)), + type_param: Box::new(TsTypeParamDef::new( + module_info, + &other.type_parameter, + )), }; TsTypeDef { @@ -569,8 +633,8 @@ impl TsTypeDef { } } - fn ts_import_type(module_info: &EsModuleInfo, other: &TsImportType) -> Self { - let type_params = if let Some(type_params_inst) = &other.type_args { + fn ts_import_type(module_info: &EsModuleInfo, other: &TSImportType) -> Self { + let type_params = if let Some(type_params_inst) = &other.type_arguments { let ts_type_defs = type_params_inst .params .iter() @@ -583,8 +647,11 @@ impl TsTypeDef { }; let import_type_def = TsImportTypeDef { - specifier: other.arg.value.to_string_lossy().into_owned(), - qualifier: other.qualifier.as_ref().map(ts_entity_name_to_name), + specifier: other.source.value.to_string(), + qualifier: other + .qualifier + .as_ref() + .map(ts_import_type_qualifier_to_name), type_params, }; @@ -594,50 +661,25 @@ impl TsTypeDef { } } - fn ts_fn_or_constructor_type( + fn ts_fn_type( module_info: &EsModuleInfo, - other: &TsFnOrConstructorType, + ts_fn_type: &TSFunctionType, ) -> Self { - use deno_ast::swc::ast::TsFnOrConstructorType::*; + let params = formal_params_to_param_defs(module_info, &ts_fn_type.params); - let fn_def = match other { - TsFnType(ts_fn_type) => { - let params = ts_fn_type - .params - .iter() - .map(|param| ts_fn_param_to_param_def(module_info, param)) - .collect(); - - let type_params = maybe_type_param_decl_to_type_param_defs( - module_info, - ts_fn_type.type_params.as_deref(), - ); - - TsFnOrConstructorDef { - constructor: false, - ts_type: TsTypeDef::new(module_info, &ts_fn_type.type_ann.type_ann), - params, - type_params, - } - } - TsConstructorType(ctor_type) => { - let params = ctor_type - .params - .iter() - .map(|param| ts_fn_param_to_param_def(module_info, param)) - .collect(); - - let type_params = maybe_type_param_decl_to_type_param_defs( - module_info, - ctor_type.type_params.as_deref(), - ); - TsFnOrConstructorDef { - constructor: true, - ts_type: TsTypeDef::new(module_info, &ctor_type.type_ann.type_ann), - params, - type_params, - } - } + let type_params = maybe_type_param_decl_to_type_param_defs( + module_info, + ts_fn_type.type_parameters.as_deref(), + ); + + let fn_def = TsFnOrConstructorDef { + constructor: false, + ts_type: TsTypeDef::new( + module_info, + &ts_fn_type.return_type.type_annotation, + ), + params, + type_params, }; TsTypeDef { @@ -646,97 +688,223 @@ impl TsTypeDef { } } - pub fn new(module_info: &EsModuleInfo, other: &TsType) -> Self { - use deno_ast::swc::ast::TsType::*; + fn ts_constructor_type( + module_info: &EsModuleInfo, + ctor_type: &TSConstructorType, + ) -> Self { + let params = formal_params_to_param_defs(module_info, &ctor_type.params); + + let type_params = maybe_type_param_decl_to_type_param_defs( + module_info, + ctor_type.type_parameters.as_deref(), + ); + + let fn_def = TsFnOrConstructorDef { + constructor: true, + ts_type: TsTypeDef::new( + module_info, + &ctor_type.return_type.type_annotation, + ), + params, + type_params, + }; + TsTypeDef { + kind: TsTypeDefKind::FnOrConstructor(Box::new(fn_def)), + repr: String::new(), + } + } + + fn ts_named_tuple_member( + module_info: &EsModuleInfo, + other: &TSNamedTupleMember, + ) -> Self { + ts_tuple_element_to_ts_type_def(module_info, &other.element_type) + } + + pub fn new(module_info: &EsModuleInfo, other: &TSType) -> Self { match other { - TsKeywordType(keyword_type) => TsTypeDef::ts_keyword_type(keyword_type), - TsThisType(this_type) => TsTypeDef::ts_this_type(this_type), - TsFnOrConstructorType(fn_or_con_type) => { - TsTypeDef::ts_fn_or_constructor_type(module_info, fn_or_con_type) + TSType::TSAnyKeyword(_) => TsTypeDef::keyword("any"), + TSType::TSUnknownKeyword(_) => TsTypeDef::keyword("unknown"), + TSType::TSNumberKeyword(_) => TsTypeDef::keyword("number"), + TSType::TSObjectKeyword(_) => TsTypeDef::keyword("object"), + TSType::TSBooleanKeyword(_) => TsTypeDef::keyword("boolean"), + TSType::TSBigIntKeyword(_) => TsTypeDef::keyword("bigint"), + TSType::TSStringKeyword(_) => TsTypeDef::keyword("string"), + TSType::TSSymbolKeyword(_) => TsTypeDef::keyword("symbol"), + TSType::TSVoidKeyword(_) => TsTypeDef::keyword("void"), + TSType::TSUndefinedKeyword(_) => TsTypeDef::keyword("undefined"), + TSType::TSNullKeyword(_) => TsTypeDef::keyword("null"), + TSType::TSNeverKeyword(_) => TsTypeDef::keyword("never"), + TSType::TSIntrinsicKeyword(_) => TsTypeDef::keyword("intrinsic"), + TSType::TSThisType(this_type) => TsTypeDef::ts_this_type(this_type), + TSType::TSFunctionType(fn_type) => { + TsTypeDef::ts_fn_type(module_info, fn_type) + } + TSType::TSConstructorType(ctor_type) => { + TsTypeDef::ts_constructor_type(module_info, ctor_type) + } + TSType::TSTypeReference(type_ref) => { + TsTypeDef::ts_type_ref(module_info, type_ref) } - TsTypeRef(type_ref) => TsTypeDef::ts_type_ref(module_info, type_ref), - TsTypeQuery(type_query) => TsTypeDef::ts_type_query(type_query), - TsTypeLit(type_literal) => { + TSType::TSTypeQuery(type_query) => TsTypeDef::ts_type_query(type_query), + TSType::TSTypeLiteral(type_literal) => { TsTypeDef::ts_type_lit(module_info, type_literal) } - TsArrayType(array_type) => { + TSType::TSArrayType(array_type) => { TsTypeDef::ts_array_type(module_info, array_type) } - TsTupleType(tuple_type) => { + TSType::TSTupleType(tuple_type) => { TsTypeDef::ts_tuple_type(module_info, tuple_type) } - TsOptionalType(optional_type) => { - TsTypeDef::ts_optional_type(module_info, optional_type) + TSType::TSUnionType(union_type) => { + TsTypeDef::ts_union_type(module_info, union_type) } - TsRestType(rest_type) => TsTypeDef::ts_rest_type(module_info, rest_type), - TsUnionOrIntersectionType(union_or_inter) => { - TsTypeDef::ts_union_or_intersection_type(module_info, union_or_inter) + TSType::TSIntersectionType(intersection_type) => { + TsTypeDef::ts_intersection_type(module_info, intersection_type) } - TsConditionalType(conditional_type) => { + TSType::TSConditionalType(conditional_type) => { TsTypeDef::ts_conditional_type(module_info, conditional_type) } - TsInferType(infer_type) => { + TSType::TSInferType(infer_type) => { TsTypeDef::ts_infer_type(module_info, infer_type) } - TsParenthesizedType(paren_type) => { + TSType::TSParenthesizedType(paren_type) => { TsTypeDef::ts_parenthesized_type(module_info, paren_type) } - TsTypeOperator(type_op_type) => { + TSType::TSTypeOperatorType(type_op_type) => { TsTypeDef::ts_type_operator(module_info, type_op_type) } - TsIndexedAccessType(indexed_access_type) => { + TSType::TSIndexedAccessType(indexed_access_type) => { TsTypeDef::ts_indexed_access_type(module_info, indexed_access_type) } - TsMappedType(mapped_type) => { + TSType::TSMappedType(mapped_type) => { TsTypeDef::ts_mapped_type(module_info, mapped_type) } - TsLitType(lit_type) => TsTypeDef::ts_lit_type(module_info, lit_type), - TsTypePredicate(type_predicate_type) => { + TSType::TSLiteralType(lit_type) => { + TsTypeDef::ts_lit_type(module_info, lit_type) + } + TSType::TSTypePredicate(type_predicate_type) => { TsTypeDef::ts_type_predicate(module_info, type_predicate_type) } - TsImportType(import_type) => { + TSType::TSImportType(import_type) => { TsTypeDef::ts_import_type(module_info, import_type) } + TSType::TSNamedTupleMember(named_tuple_member) => { + TsTypeDef::ts_named_tuple_member(module_info, named_tuple_member) + } + TSType::TSTemplateLiteralType(tpl_type) => { + TsTypeDef::ts_template_literal_type(module_info, tpl_type) + } + TSType::JSDocNullableType(_) + | TSType::JSDocNonNullableType(_) + | TSType::JSDocUnknownType(_) => TsTypeDef::keyword("unknown"), } } } -fn ts_entity_name_to_name(entity_name: &TsEntityName) -> String { - use deno_ast::swc::ast::TsEntityName::*; +type Id = (String, usize); + +fn identifier_reference_to_id( + module_info: &EsModuleInfo, + ident: &IdentifierReference, +) -> Id { + let ctxt = ident + .reference_id + .get() + .zip(module_info.scoping()) + .and_then(|(reference_id, scoping)| { + scoping.get_reference(reference_id).symbol_id() + }) + .map(|symbol_id| symbol_id.index() + 1) + .unwrap_or(0); + (ident.name.to_string(), ctxt) +} - match entity_name { - Ident(ident) => ident.sym.to_string(), - TsQualifiedName(ts_qualified_name) => { - let left = ts_entity_name_to_name(&ts_qualified_name.left); - let right = ts_qualified_name.right.sym.to_string(); +fn ts_type_name_to_name(type_name: &TSTypeName) -> String { + match type_name { + TSTypeName::IdentifierReference(ident) => ident.name.to_string(), + TSTypeName::QualifiedName(ts_qualified_name) => { + let left = ts_type_name_to_name(&ts_qualified_name.left); + let right = ts_qualified_name.right.name.to_string(); format!("{}.{}", left, right) } + TSTypeName::ThisExpression(_) => "this".to_string(), } } -fn ts_entity_name_root_ident(entity_name: &TsEntityName) -> &Ident { - match entity_name { - TsEntityName::Ident(ident) => ident, - TsEntityName::TsQualifiedName(ts_qualified_name) => { - ts_entity_name_root_ident(&ts_qualified_name.left) +fn ts_type_name_root_ident<'a>( + type_name: &'a TSTypeName<'a>, +) -> Option<&'a IdentifierReference<'a>> { + match type_name { + TSTypeName::IdentifierReference(ident) => Some(ident), + TSTypeName::QualifiedName(ts_qualified_name) => { + ts_type_name_root_ident(&ts_qualified_name.left) + } + TSTypeName::ThisExpression(_) => None, + } +} + +fn ts_type_query_expr_name_to_name(expr_name: &TSTypeQueryExprName) -> String { + match expr_name { + TSTypeQueryExprName::TSImportType(import_type) => { + import_type.source.value.to_string() + } + TSTypeQueryExprName::IdentifierReference(ident) => ident.name.to_string(), + TSTypeQueryExprName::QualifiedName(qualified) => { + let left = ts_type_name_to_name(&qualified.left); + let right = qualified.right.name.to_string(); + format!("{}.{}", left, right) } + TSTypeQueryExprName::ThisExpression(_) => "this".to_string(), } } -fn expr_root_ident(expr: &Expr) -> Option<&Ident> { +fn ts_import_type_qualifier_to_name( + qualifier: &TSImportTypeQualifier, +) -> String { + match qualifier { + TSImportTypeQualifier::Identifier(ident) => ident.name.to_string(), + TSImportTypeQualifier::QualifiedName(qualified) => { + let left = ts_import_type_qualifier_to_name(&qualified.left); + let right = qualified.right.name.to_string(); + format!("{}.{}", left, right) + } + } +} + +fn ts_type_predicate_name_to_this_or_ident( + name: &TSTypePredicateName, +) -> ThisOrIdent { + match name { + TSTypePredicateName::This(_) => ThisOrIdent::This, + TSTypePredicateName::Identifier(ident) => ThisOrIdent::Identifier { + name: ident.name.to_string(), + }, + } +} + +fn expr_root_ident<'a>( + expr: &'a Expression<'a>, +) -> Option<&'a IdentifierReference<'a>> { match expr { - Expr::Ident(ident) => Some(ident), - Expr::Member(member_expr) => expr_root_ident(&member_expr.obj), + Expression::Identifier(ident) => Some(ident), + Expression::StaticMemberExpression(member_expr) => { + expr_root_ident(&member_expr.object) + } + Expression::ComputedMemberExpression(member_expr) => { + expr_root_ident(&member_expr.object) + } _ => None, } } fn resolve_type_ref( module_info: &EsModuleInfo, - ident: &Ident, + ident: &IdentifierReference, ) -> Option { - if let Some(symbol) = module_info.symbol_from_swc(&ident.to_id()) { + let id = identifier_reference_to_id(module_info, ident); + if let Some(symbol) = module_info.symbol_from_swc(&id) { if let Some(file_dep) = symbol.file_dep() { Some(TypeRefResolution::Import { specifier: file_dep.specifier.clone(), @@ -745,214 +913,89 @@ fn resolve_type_ref( } else { Some(TypeRefResolution::Local) } - } else if ident.ctxt != module_info.source().unresolved_context() { - // The identifier has a resolved syntax context but is not a module-level - // symbol — it's a type parameter or other locally-scoped binding. - let origin = find_type_param_origin(module_info, &ident.to_id()); + } else if id.1 != 0 { Some(TypeRefResolution::TypeParam { - declaring_name: origin.as_ref().map(|o| o.0.clone()), - declaring_kind: origin.as_ref().map(|o| o.1.clone()), + declaring_name: None, + declaring_kind: None, }) } else { - // Unresolved identifier — a global type (Promise, Array, etc.) - // or truly unresolvable. None } } -/// Walks the module AST to find which declaration owns a type parameter. -fn find_type_param_origin( +fn ts_tuple_element_to_ts_type_def( module_info: &EsModuleInfo, - target_id: &Id, -) -> Option<(String, TypeParamDeclaringKind)> { - use deno_ast::ModuleItemRef; - - let program = module_info.source().program_ref(); - - for item in program.body() { - match item { - ModuleItemRef::ModuleDecl(ModuleDecl::ExportDecl(export)) => { - if let Some(origin) = find_type_param_in_decl(&export.decl, target_id) { - return Some(origin); - } - } - ModuleItemRef::Stmt(Stmt::Decl(decl)) => { - if let Some(origin) = find_type_param_in_decl(decl, target_id) { - return Some(origin); - } - } - ModuleItemRef::ModuleDecl(ModuleDecl::ExportDefaultDecl(export)) => { - match &export.decl { - DefaultDecl::Class(class_expr) => { - if let Some(origin) = find_type_param_in_class( - &class_expr.class, - class_expr - .ident - .as_ref() - .map(|i| i.sym.as_ref()) - .unwrap_or("default"), - target_id, - ) { - return Some(origin); - } - } - DefaultDecl::Fn(fn_expr) => { - if has_type_param(&fn_expr.function.type_params, target_id) { - let name = fn_expr - .ident - .as_ref() - .map(|i| i.sym.to_string()) - .unwrap_or_else(|| "default".to_string()); - return Some((name, TypeParamDeclaringKind::Function)); - } - } - DefaultDecl::TsInterfaceDecl(iface) => { - if let Some(origin) = find_type_param_in_interface(iface, target_id) - { - return Some(origin); - } - } - } - } - _ => {} + elem: &TSTupleElement, +) -> TsTypeDef { + match elem { + TSTupleElement::TSOptionalType(opt) => { + TsTypeDef::ts_optional_type(module_info, opt) } - } - - None -} - -fn find_type_param_in_decl( - decl: &Decl, - target_id: &Id, -) -> Option<(String, TypeParamDeclaringKind)> { - match decl { - Decl::Class(class_decl) => find_type_param_in_class( - &class_decl.class, - class_decl.ident.sym.as_ref(), - target_id, - ), - Decl::Fn(fn_decl) => { - if has_type_param(&fn_decl.function.type_params, target_id) { - Some(( - fn_decl.ident.sym.to_string(), - TypeParamDeclaringKind::Function, - )) - } else { - None - } + TSTupleElement::TSRestType(rest) => { + TsTypeDef::ts_rest_type(module_info, rest) } - Decl::TsInterface(iface) => find_type_param_in_interface(iface, target_id), - Decl::TsTypeAlias(alias) => { - if has_type_param(&alias.type_params, target_id) { - Some((alias.id.sym.to_string(), TypeParamDeclaringKind::TypeAlias)) - } else { - None - } + TSTupleElement::TSAnyKeyword(_) => TsTypeDef::keyword("any"), + TSTupleElement::TSUnknownKeyword(_) => TsTypeDef::keyword("unknown"), + TSTupleElement::TSNumberKeyword(_) => TsTypeDef::keyword("number"), + TSTupleElement::TSObjectKeyword(_) => TsTypeDef::keyword("object"), + TSTupleElement::TSBooleanKeyword(_) => TsTypeDef::keyword("boolean"), + TSTupleElement::TSBigIntKeyword(_) => TsTypeDef::keyword("bigint"), + TSTupleElement::TSStringKeyword(_) => TsTypeDef::keyword("string"), + TSTupleElement::TSSymbolKeyword(_) => TsTypeDef::keyword("symbol"), + TSTupleElement::TSVoidKeyword(_) => TsTypeDef::keyword("void"), + TSTupleElement::TSUndefinedKeyword(_) => TsTypeDef::keyword("undefined"), + TSTupleElement::TSNullKeyword(_) => TsTypeDef::keyword("null"), + TSTupleElement::TSNeverKeyword(_) => TsTypeDef::keyword("never"), + TSTupleElement::TSIntrinsicKeyword(_) => TsTypeDef::keyword("intrinsic"), + TSTupleElement::TSThisType(t) => TsTypeDef::ts_this_type(t), + TSTupleElement::TSFunctionType(t) => TsTypeDef::ts_fn_type(module_info, t), + TSTupleElement::TSConstructorType(t) => { + TsTypeDef::ts_constructor_type(module_info, t) } - Decl::TsModule(ts_module) => { - // Check declarations inside namespaces - if let Some(TsNamespaceBody::TsModuleBlock(block)) = &ts_module.body { - for item in &block.body { - let inner_decl = match item { - ModuleItem::ModuleDecl(ModuleDecl::ExportDecl(export)) => { - Some(&export.decl) - } - ModuleItem::Stmt(Stmt::Decl(decl)) => Some(decl), - _ => None, - }; - if let Some(origin) = inner_decl.and_then(|inner_decl| { - find_type_param_in_decl(inner_decl, target_id) - }) { - return Some(origin); - } - } - } - None + TSTupleElement::TSTypeReference(t) => { + TsTypeDef::ts_type_ref(module_info, t) } - _ => None, - } -} - -fn find_type_param_in_class( - class: &Class, - class_name: &str, - target_id: &Id, -) -> Option<(String, TypeParamDeclaringKind)> { - if has_type_param(&class.type_params, target_id) { - return Some((class_name.to_string(), TypeParamDeclaringKind::Class)); - } - - // Check method type params - for member in &class.body { - if let ClassMember::Method(method) = member - && has_type_param(&method.function.type_params, target_id) - { - let method_name = simple_prop_name(&method.key); - return Some((method_name, TypeParamDeclaringKind::Method)); + TSTupleElement::TSTypeQuery(t) => TsTypeDef::ts_type_query(t), + TSTupleElement::TSTypeLiteral(t) => TsTypeDef::ts_type_lit(module_info, t), + TSTupleElement::TSArrayType(t) => TsTypeDef::ts_array_type(module_info, t), + TSTupleElement::TSTupleType(t) => TsTypeDef::ts_tuple_type(module_info, t), + TSTupleElement::TSUnionType(t) => TsTypeDef::ts_union_type(module_info, t), + TSTupleElement::TSIntersectionType(t) => { + TsTypeDef::ts_intersection_type(module_info, t) } - } - - None -} - -fn find_type_param_in_interface( - iface: &TsInterfaceDecl, - target_id: &Id, -) -> Option<(String, TypeParamDeclaringKind)> { - if has_type_param(&iface.type_params, target_id) { - return Some((iface.id.sym.to_string(), TypeParamDeclaringKind::Interface)); - } - - // Check method type params - for member in &iface.body.body { - match member { - TsTypeElement::TsMethodSignature(method) => { - if has_type_param(&method.type_params, target_id) { - let method_name = simple_expr_name(&method.key); - return Some((method_name, TypeParamDeclaringKind::Method)); - } - } - TsTypeElement::TsConstructSignatureDecl(ctor) => { - if has_type_param(&ctor.type_params, target_id) { - return Some(("new".to_string(), TypeParamDeclaringKind::Method)); - } - } - TsTypeElement::TsCallSignatureDecl(call) => { - if has_type_param(&call.type_params, target_id) { - return Some(("call".to_string(), TypeParamDeclaringKind::Method)); - } - } - _ => {} + TSTupleElement::TSConditionalType(t) => { + TsTypeDef::ts_conditional_type(module_info, t) } + TSTupleElement::TSInferType(t) => TsTypeDef::ts_infer_type(module_info, t), + TSTupleElement::TSParenthesizedType(t) => { + TsTypeDef::ts_parenthesized_type(module_info, t) + } + TSTupleElement::TSTypeOperatorType(t) => { + TsTypeDef::ts_type_operator(module_info, t) + } + TSTupleElement::TSIndexedAccessType(t) => { + TsTypeDef::ts_indexed_access_type(module_info, t) + } + TSTupleElement::TSMappedType(t) => { + TsTypeDef::ts_mapped_type(module_info, t) + } + TSTupleElement::TSLiteralType(t) => TsTypeDef::ts_lit_type(module_info, t), + TSTupleElement::TSTypePredicate(t) => { + TsTypeDef::ts_type_predicate(module_info, t) + } + TSTupleElement::TSImportType(t) => { + TsTypeDef::ts_import_type(module_info, t) + } + TSTupleElement::TSNamedTupleMember(t) => { + TsTypeDef::ts_named_tuple_member(module_info, t) + } + TSTupleElement::TSTemplateLiteralType(t) => { + TsTypeDef::ts_template_literal_type(module_info, t) + } + TSTupleElement::JSDocNullableType(_) + | TSTupleElement::JSDocNonNullableType(_) + | TSTupleElement::JSDocUnknownType(_) => TsTypeDef::keyword("unknown"), } - - None -} - -fn simple_prop_name(prop_name: &PropName) -> String { - match prop_name { - PropName::Ident(ident) => ident.sym.to_string(), - PropName::Str(str_) => str_.value.to_string_lossy().into_owned(), - PropName::Num(num) => num.value.to_string(), - PropName::BigInt(num) => num.value.to_string(), - PropName::Computed(_) => "[computed]".to_string(), - } -} - -fn simple_expr_name(expr: &Expr) -> String { - match expr { - Expr::Ident(ident) => ident.sym.to_string(), - _ => "[computed]".to_string(), - } -} - -fn has_type_param( - type_params: &Option>, - target_id: &Id, -) -> bool { - type_params - .as_ref() - .is_some_and(|tp| tp.params.iter().any(|p| p.name.to_id() == *target_id)) } #[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Eq)] @@ -1049,20 +1092,21 @@ pub struct TsFnOrConstructorDef { } impl TsFnOrConstructorDef { - fn arrow_expr(module_info: &EsModuleInfo, expr: &ArrowExpr) -> Self { - let params = expr - .params - .iter() - .map(|pat| pat_to_param_def(module_info, pat)) - .collect(); + fn arrow_expr( + module_info: &EsModuleInfo, + expr: &ArrowFunctionExpression, + ) -> Self { + let params = formal_params_to_param_defs(module_info, &expr.params); let ts_type = expr .return_type .as_deref() - .map(|return_type| TsTypeDef::new(module_info, &return_type.type_ann)) + .map(|return_type| { + TsTypeDef::new(module_info, &return_type.type_annotation) + }) .unwrap_or_else(|| TsTypeDef::keyword("unknown")); let type_params = maybe_type_param_decl_to_type_param_defs( module_info, - expr.type_params.as_deref(), + expr.type_parameters.as_deref(), ); Self { @@ -1073,22 +1117,18 @@ impl TsFnOrConstructorDef { } } - fn fn_expr(module_info: &EsModuleInfo, expr: &FnExpr) -> Self { - let params = expr - .function - .params - .iter() - .map(|param| pat_to_param_def(module_info, ¶m.pat)) - .collect(); + fn fn_expr(module_info: &EsModuleInfo, expr: &Function) -> Self { + let params = formal_params_to_param_defs(module_info, &expr.params); let ts_type = expr - .function .return_type .as_deref() - .map(|return_type| TsTypeDef::new(module_info, &return_type.type_ann)) + .map(|return_type| { + TsTypeDef::new(module_info, &return_type.type_annotation) + }) .unwrap_or_else(|| TsTypeDef::keyword("unknown")); let type_params = maybe_type_param_decl_to_type_param_defs( module_info, - expr.function.type_params.as_deref(), + expr.type_parameters.as_deref(), ); Self { @@ -1455,18 +1495,6 @@ pub enum ThisOrIdent { Identifier { name: String }, } -impl From<&TsThisTypeOrIdent> for ThisOrIdent { - fn from(other: &TsThisTypeOrIdent) -> ThisOrIdent { - use TsThisTypeOrIdent::*; - match other { - TsThisType(_) => Self::This, - Ident(ident) => Self::Identifier { - name: ident.sym.to_string(), - }, - } - } -} - /// ```ts /// function foo(param: any): asserts param is SomeType { ... } /// ^^^^^^^ ^^^^^ ^^^^^^^^ @@ -1506,7 +1534,7 @@ impl Display for TsTypePredicateDef { } impl TsTypeDef { - pub fn number_literal(num: &Number) -> Self { + pub fn number_literal(num: &NumericLiteral) -> Self { Self::number_value(num.value) } @@ -1522,8 +1550,8 @@ impl TsTypeDef { Self::literal(repr, lit) } - pub fn string_literal(str_node: &Str) -> Self { - Self::string_value(str_node.value.to_string_lossy().into_owned()) + pub fn string_literal(str_node: &StringLiteral) -> Self { + Self::string_value(str_node.value.to_string()) } pub fn string_value(value: String) -> Self { @@ -1538,7 +1566,10 @@ impl TsTypeDef { Self::literal(repr, lit) } - pub fn tpl_literal(types: Vec, quasis: &[TplElement]) -> Self { + pub fn tpl_literal( + types: Vec, + quasis: &[TemplateElement], + ) -> Self { let mut types_out: Vec<(Self, String)> = Vec::new(); for ts_type in types { let repr = format!("${{{}}}", ts_type); @@ -1546,7 +1577,7 @@ impl TsTypeDef { } let mut qasis_out: Vec<(Self, String)> = Vec::new(); for quasi in quasis { - let repr = quasi.raw.to_string(); + let repr = quasi.value.raw.to_string(); let lit = LiteralDef { kind: LiteralDefKind::String, number: None, @@ -1580,7 +1611,7 @@ impl TsTypeDef { Self::literal(repr, lit) } - pub fn bool_literal(bool_node: &Bool) -> Self { + pub fn bool_literal(bool_node: &BooleanLiteral) -> Self { Self::bool_value(bool_node.value) } @@ -1596,12 +1627,19 @@ impl TsTypeDef { Self::literal(repr, lit) } - pub fn bigint_literal(bigint_node: &BigInt) -> Self { - let repr = bigint_node.value.to_string(); + pub fn bigint_literal(bigint_node: &BigIntLiteral) -> Self { + let repr = bigint_node + .raw + .as_ref() + .map(|r| { + let s = r.as_str(); + s.strip_suffix('n').unwrap_or(s).to_string() + }) + .unwrap_or_default(); let lit = LiteralDef { kind: LiteralDefKind::BigInt, number: None, - string: Some(bigint_node.value.to_string()), + string: Some(repr.clone()), ts_types: None, boolean: None, }; @@ -1667,86 +1705,120 @@ impl TsTypeDef { pub(crate) fn infer_ts_type_from_expr( module_info: &EsModuleInfo, - expr: &Expr, + expr: &Expression, is_const: bool, ) -> Option { match expr { - Expr::Array(arr_lit) => { + Expression::ArrayExpression(arr_lit) => { // e.g.) const n = ["a", 1]; infer_ts_type_from_arr_lit(module_info, arr_lit, false) } - Expr::Arrow(expr) => { + Expression::ArrowFunctionExpression(expr) => { // e.g.) const f = (a: string): void => {}; infer_ts_type_from_arrow_expr(module_info, expr) } - Expr::Fn(expr) => { + Expression::FunctionExpression(expr) => { // e.g.) const f = function a(a:string): void {}; infer_ts_type_from_fn_expr(module_info, expr) } - Expr::Lit(lit) => { - // e.g.) const n = 100; - infer_ts_type_from_lit(lit, is_const) + Expression::NumericLiteral(num) => { + if is_const { + Some(TsTypeDef::number_literal(num)) + } else { + Some(TsTypeDef::number_with_repr("number")) + } + } + Expression::StringLiteral(str_) => { + if is_const && str_.value.len() < 100 { + Some(TsTypeDef::string_literal(str_)) + } else { + Some(TsTypeDef::string_with_repr("string")) + } + } + Expression::BooleanLiteral(bool_) => { + if is_const { + Some(TsTypeDef::bool_literal(bool_)) + } else { + Some(TsTypeDef::bool_with_repr("boolean")) + } + } + Expression::BigIntLiteral(bigint_) => { + if is_const { + Some(TsTypeDef::bigint_literal(bigint_)) + } else { + Some(TsTypeDef::bigint_with_repr("bigint")) + } + } + Expression::RegExpLiteral(regex) => { + Some(TsTypeDef::regexp(regex.regex.pattern.text.to_string())) } - Expr::New(expr) => { + Expression::NullLiteral(_) => Some(TsTypeDef::keyword("null")), + Expression::NewExpression(expr) => { // e.g.) const d = new Date() infer_ts_type_from_new_expr(module_info, expr) } - Expr::Tpl(tpl) => { + Expression::TemplateLiteral(tpl) => { // e.g.) const s = `hello`; Some(infer_ts_type_from_tpl(module_info, tpl, is_const)) } - Expr::TsConstAssertion(assertion) => { - // e.g.) const s = [] as const; - infer_ts_type_from_const_assertion(module_info, assertion) + Expression::TSAsExpression(as_expr) => { + if is_const_assertion(&as_expr.type_annotation) { + match &as_expr.expression { + Expression::ArrayExpression(arr) => { + infer_ts_type_from_arr_lit(module_info, arr, true) + } + _ => infer_ts_type_from_expr(module_info, &as_expr.expression, true), + } + } else { + Some(TsTypeDef::new(module_info, &as_expr.type_annotation)) + } } - Expr::Call(expr) => { + Expression::CallExpression(expr) => { // e.g.) const value = Number(123); infer_ts_type_from_call_expr(expr) } - Expr::Object(obj) => { + Expression::ObjectExpression(obj) => { // e.g.) const value = {foo: "bar"}; infer_ts_type_from_obj(module_info, obj) } - Expr::TsSatisfies(satisfies) => { + Expression::TSSatisfiesExpression(satisfies) => { // e.g.) const value = {foo: "bar"} satifies Record; - infer_ts_type_from_expr(module_info, &satisfies.expr, is_const) + infer_ts_type_from_expr(module_info, &satisfies.expression, is_const) } - Expr::Update(_) => { + Expression::UpdateExpression(_) => { // e.g.) let foo = 0; // const bar = foo++; Some(TsTypeDef::number_with_repr("number")) } - Expr::TsTypeAssertion(assertion) => { + Expression::TSTypeAssertion(assertion) => { // e.g.) export const foo = 1; - Some(TsTypeDef::new(module_info, &assertion.type_ann)) + Some(TsTypeDef::new(module_info, &assertion.type_annotation)) } - Expr::TsAs(as_expr) => { - // e.g.) export const foo = 1 as string; - Some(TsTypeDef::new(module_info, &as_expr.type_ann)) - } - Expr::Paren(paren) => { + Expression::ParenthesizedExpression(paren) => { // e.g.) export const foo = (1); - infer_ts_type_from_expr(module_info, &paren.expr, is_const) + infer_ts_type_from_expr(module_info, &paren.expression, is_const) } - Expr::Await(await_expr) => { + Expression::AwaitExpression(await_expr) => { // e.g.) export const foo = await 1; - infer_ts_type_from_expr(module_info, &await_expr.arg, is_const) + infer_ts_type_from_expr(module_info, &await_expr.argument, is_const) } - Expr::Cond(cond) => { + Expression::ConditionalExpression(cond) => { // e.g.) export const foo = true ? "a" : 1; - let left = infer_ts_type_from_expr(module_info, &cond.cons, is_const)?; - let right = infer_ts_type_from_expr(module_info, &cond.alt, is_const)?; + let left = + infer_ts_type_from_expr(module_info, &cond.consequent, is_const)?; + let right = + infer_ts_type_from_expr(module_info, &cond.alternate, is_const)?; Some(TsTypeDef { kind: TsTypeDefKind::Union(vec![left, right]), repr: String::new(), }) } - Expr::TsNonNull(non_null) => { + Expression::TSNonNullExpression(non_null) => { // e.g.) export const foo = (true ? "a" : null)!; // e.g.) export const foo = null!; let with_null = - infer_ts_type_from_expr(module_info, &non_null.expr, is_const)?; + infer_ts_type_from_expr(module_info, &non_null.expression, is_const)?; if let TsTypeDefKind::Union(union) = with_null.kind { let mut non_null_union = union @@ -1776,63 +1848,65 @@ pub(crate) fn infer_ts_type_from_expr( None } } - Expr::Bin(bin) => { + Expression::BinaryExpression(bin) => { // e.g.) export const foo = 1 == "bar"; // e.g.) export const foo = 1 >> 1; - match bin.op { - BinaryOp::EqEq - | BinaryOp::NotEq - | BinaryOp::EqEqEq - | BinaryOp::NotEqEq - | BinaryOp::Lt - | BinaryOp::LtEq - | BinaryOp::Gt - | BinaryOp::GtEq - | BinaryOp::In - | BinaryOp::InstanceOf => Some(TsTypeDef::bool_with_repr("boolean")), - BinaryOp::LShift - | BinaryOp::RShift - | BinaryOp::ZeroFillRShift - | BinaryOp::Sub - | BinaryOp::Mul - | BinaryOp::Div - | BinaryOp::Mod - | BinaryOp::BitOr - | BinaryOp::BitXor - | BinaryOp::BitAnd - | BinaryOp::Exp => Some(TsTypeDef::number_with_repr("number")), - BinaryOp::LogicalOr - | BinaryOp::LogicalAnd - | BinaryOp::NullishCoalescing - | BinaryOp::Add => None, + match bin.operator { + BinaryOperator::Equality + | BinaryOperator::Inequality + | BinaryOperator::StrictEquality + | BinaryOperator::StrictInequality + | BinaryOperator::LessThan + | BinaryOperator::LessEqualThan + | BinaryOperator::GreaterThan + | BinaryOperator::GreaterEqualThan + | BinaryOperator::In + | BinaryOperator::Instanceof => { + Some(TsTypeDef::bool_with_repr("boolean")) + } + BinaryOperator::ShiftLeft + | BinaryOperator::ShiftRight + | BinaryOperator::ShiftRightZeroFill + | BinaryOperator::Subtraction + | BinaryOperator::Multiplication + | BinaryOperator::Division + | BinaryOperator::Remainder + | BinaryOperator::BitwiseOR + | BinaryOperator::BitwiseXOR + | BinaryOperator::BitwiseAnd + | BinaryOperator::Exponential => { + Some(TsTypeDef::number_with_repr("number")) + } + BinaryOperator::Addition => None, } } - Expr::This(_) - | Expr::Unary(_) - | Expr::Assign(_) - | Expr::Member(_) - | Expr::SuperProp(_) - | Expr::Seq(_) - | Expr::Ident(_) - | Expr::TaggedTpl(_) - | Expr::Class(_) - | Expr::Yield(_) - | Expr::MetaProp(_) - | Expr::JSXMember(_) - | Expr::JSXNamespacedName(_) - | Expr::JSXEmpty(_) - | Expr::JSXElement(_) - | Expr::JSXFragment(_) - | Expr::TsInstantiation(_) - | Expr::PrivateName(_) - | Expr::OptChain(_) - | Expr::Invalid(_) => None, + Expression::LogicalExpression(_) + | Expression::ThisExpression(_) + | Expression::UnaryExpression(_) + | Expression::AssignmentExpression(_) + | Expression::StaticMemberExpression(_) + | Expression::ComputedMemberExpression(_) + | Expression::PrivateFieldExpression(_) + | Expression::Super(_) + | Expression::SequenceExpression(_) + | Expression::Identifier(_) + | Expression::TaggedTemplateExpression(_) + | Expression::ClassExpression(_) + | Expression::YieldExpression(_) + | Expression::MetaProperty(_) + | Expression::JSXElement(_) + | Expression::JSXFragment(_) + | Expression::TSInstantiationExpression(_) + | Expression::ChainExpression(_) + | Expression::ImportExpression(_) + | Expression::PrivateInExpression(_) + | Expression::V8IntrinsicExpression(_) => None, } } pub(crate) fn infer_simple_ts_type_from_init( module_info: &EsModuleInfo, - init: Option<&Expr>, + init: Option<&Expression>, is_const: bool, ) -> Option { if let Some(init_expr) = init { @@ -1844,32 +1918,36 @@ pub(crate) fn infer_simple_ts_type_from_init( fn infer_ts_type_from_arr_lit( module_info: &EsModuleInfo, - arr_lit: &ArrayLit, + arr_lit: &ArrayExpression, is_const: bool, ) -> Option { let mut defs = Vec::new(); - for expr in arr_lit.elems.iter().flatten() { - if expr.spread.is_none() { - if let Some(ts_type) = - infer_ts_type_from_expr(module_info, &expr.expr, is_const) - { - if !defs.contains(&ts_type) { - defs.push(ts_type); - } - } else { - // it is not a trivial type that can be inferred an so will infer an - // an any array. + for elem in &arr_lit.elements { + match elem { + ArrayExpressionElement::SpreadElement(_) => { return Some(TsTypeDef { repr: "any[]".to_string(), kind: TsTypeDefKind::Array(Box::new(TsTypeDef::keyword("any"))), }); } - } else { - // TODO(@kitsonk) we should recursively unwrap the spread here - return Some(TsTypeDef { - repr: "any[]".to_string(), - kind: TsTypeDefKind::Array(Box::new(TsTypeDef::keyword("any"))), - }); + ArrayExpressionElement::Elision(_) => continue, + _ => { + let expr = elem.to_expression(); + if let Some(ts_type) = + infer_ts_type_from_expr(module_info, expr, is_const) + { + if !defs.contains(&ts_type) { + defs.push(ts_type); + } + } else { + // it is not a trivial type that can be inferred an so will infer an + // an any array. + return Some(TsTypeDef { + repr: "any[]".to_string(), + kind: TsTypeDefKind::Array(Box::new(TsTypeDef::keyword("any"))), + }); + } + } } } match defs.len() { @@ -1893,7 +1971,7 @@ fn infer_ts_type_from_arr_lit( fn infer_ts_type_from_arrow_expr( module_info: &EsModuleInfo, - expr: &ArrowExpr, + expr: &ArrowFunctionExpression, ) -> Option { Some(TsTypeDef { kind: TsTypeDefKind::FnOrConstructor(Box::new( @@ -1905,7 +1983,7 @@ fn infer_ts_type_from_arrow_expr( fn infer_ts_type_from_fn_expr( module_info: &EsModuleInfo, - expr: &FnExpr, + expr: &Function, ) -> Option { Some(TsTypeDef { kind: TsTypeDefKind::FnOrConstructor(Box::new( @@ -1915,67 +1993,26 @@ fn infer_ts_type_from_fn_expr( }) } -fn infer_ts_type_from_const_assertion( - module_info: &EsModuleInfo, - assertion: &TsConstAssertion, -) -> Option { - match &*assertion.expr { - Expr::Array(arr_lit) => { - // e.g.) const n = ["a", 1] as const; - infer_ts_type_from_arr_lit(module_info, arr_lit, true) - } - _ => infer_ts_type_from_expr(module_info, &assertion.expr, true), - } -} - -fn infer_ts_type_from_lit(lit: &Lit, is_const: bool) -> Option { - match lit { - Lit::Num(num) => { - if is_const { - Some(TsTypeDef::number_literal(num)) - } else { - Some(TsTypeDef::number_with_repr("number")) - } - } - Lit::Str(str_) => { - if is_const && str_.value.len() < 100 { - Some(TsTypeDef::string_literal(str_)) - } else { - Some(TsTypeDef::string_with_repr("string")) - } - } - Lit::Bool(bool_) => { - if is_const { - Some(TsTypeDef::bool_literal(bool_)) - } else { - Some(TsTypeDef::bool_with_repr("boolean")) - } - } - Lit::BigInt(bigint_) => { - if is_const { - Some(TsTypeDef::bigint_literal(bigint_)) - } else { - Some(TsTypeDef::bigint_with_repr("bigint")) - } - } - Lit::Regex(regex) => Some(TsTypeDef::regexp(regex.exp.to_string())), - Lit::Null(_null) => Some(TsTypeDef::keyword("null")), - Lit::JSXText(_) => None, - } +fn is_const_assertion(ts_type: &TSType) -> bool { + matches!( + ts_type, + TSType::TSTypeReference(type_ref) + if matches!(&type_ref.type_name, TSTypeName::IdentifierReference(ident) if ident.name == "const") + ) } fn infer_ts_type_from_new_expr( module_info: &EsModuleInfo, - new_expr: &NewExpr, + new_expr: &NewExpression, ) -> Option { - match new_expr.callee.as_ref() { - Expr::Ident(ident) => Some(TsTypeDef { - repr: ident.sym.to_string(), + match &new_expr.callee { + Expression::Identifier(ident) => Some(TsTypeDef { + repr: ident.name.to_string(), kind: TsTypeDefKind::TypeRef(TsTypeRefDef { - type_params: new_expr.type_args.as_ref().map(|init| { + type_params: new_expr.type_arguments.as_ref().map(|init| { maybe_type_param_instantiation_to_type_defs(module_info, Some(init)) }), - type_name: ident.sym.to_string(), + type_name: ident.name.to_string(), resolution: resolve_type_ref(module_info, ident), }), }), @@ -1983,33 +2020,27 @@ fn infer_ts_type_from_new_expr( } } -fn infer_ts_type_from_call_expr(call_expr: &CallExpr) -> Option { - match &call_expr.callee { - Callee::Expr(expr) => { - if let Expr::Ident(ident) = expr.as_ref() { - let sym = ident.sym.to_string(); - match sym.as_str() { - "Symbol" | "Number" | "String" | "BigInt" => { - Some(TsTypeDef::keyword_with_repr( - &sym.to_ascii_lowercase(), - &sym.clone(), - )) - } - "Date" => Some(TsTypeDef::string_with_repr(&sym)), - "RegExp" => Some(TsTypeDef::regexp(sym)), - _ => None, - } - } else { - None - } +fn infer_ts_type_from_call_expr( + call_expr: &CallExpression, +) -> Option { + if let Expression::Identifier(ident) = &call_expr.callee { + let sym = ident.name.to_string(); + match sym.as_str() { + "Symbol" | "Number" | "String" | "BigInt" => Some( + TsTypeDef::keyword_with_repr(&sym.to_ascii_lowercase(), &sym.clone()), + ), + "Date" => Some(TsTypeDef::string_with_repr(&sym)), + "RegExp" => Some(TsTypeDef::regexp(sym)), + _ => None, } - _ => None, + } else { + None } } fn infer_ts_type_from_obj( module_info: &EsModuleInfo, - obj: &ObjectLit, + obj: &ObjectExpression, ) -> Option { let (methods, properties) = infer_ts_type_from_obj_inner(module_info, obj); if methods.is_empty() && properties.is_empty() { @@ -2021,24 +2052,27 @@ fn infer_ts_type_from_obj( fn infer_ts_type_from_obj_inner( module_info: &EsModuleInfo, - obj: &ObjectLit, + obj: &ObjectExpression, ) -> (Vec, Vec) { let mut methods = Vec::::new(); let mut properties = Vec::::new(); - for obj_prop in &obj.props { - let Some(js_doc) = js_doc_for_range(module_info, &obj_prop.range()) else { + for obj_prop in &obj.properties { + let Some(js_doc) = js_doc_for_range(module_info, obj_prop.span()) else { continue; }; match obj_prop { - PropOrSpread::Prop(prop) => match &**prop { - Prop::Shorthand(shorthand) => { - // TODO(@crowlKats) we should pass previous nodes and take the type - // from the previous symbol. + ObjectPropertyKind::ObjectProperty(prop) => { + if prop.shorthand { + let name = prop + .key + .static_name() + .map(|name| name.to_string()) + .unwrap_or_else(|| "[UNSUPPORTED]".to_string()); properties.push(PropertyDef { - name: shorthand.sym.to_string(), + name, js_doc, - location: get_location(module_info, shorthand.start()), + location: get_location(module_info, prop.span.start), params: vec![], readonly: false, computed: false, @@ -2046,89 +2080,88 @@ fn infer_ts_type_from_obj_inner( ts_type: None, type_params: Box::new([]), }); - } - Prop::KeyValue(kv) => { - properties.push(PropertyDef { - name: prop_name_to_string(module_info, &kv.key), - js_doc, - location: get_location(module_info, kv.start()), - params: vec![], - readonly: false, - computed: kv.key.is_computed(), - optional: false, - ts_type: infer_ts_type_from_expr(module_info, &kv.value, false), - type_params: Box::new([]), - }); - } - Prop::Assign(_) => unreachable!("This is invalid for object literal!"), - Prop::Getter(getter) => { - let name = prop_name_to_string(module_info, &getter.key); - let computed = getter.key.is_computed(); - let return_type = getter - .type_ann - .as_ref() - .map(|type_ann| TsTypeDef::new(module_info, &type_ann.type_ann)); + } else if prop.kind == PropertyKind::Get { + let name = prop_name_to_string(module_info, &prop.key); + let computed = prop.key.static_name().is_none(); + let return_type = + if let Expression::FunctionExpression(func) = &prop.value { + func.return_type.as_ref().map(|type_ann| { + TsTypeDef::new(module_info, &type_ann.type_annotation) + }) + } else { + None + }; methods.push(MethodDef { name, js_doc, kind: MethodKind::Getter, - location: get_location(module_info, getter.start()), + location: get_location(module_info, prop.span.start), params: vec![], computed, optional: false, return_type, type_params: Box::new([]), }); - } - Prop::Setter(setter) => { - let name = prop_name_to_string(module_info, &setter.key); - let computed = setter.key.is_computed(); - let param = pat_to_param_def(module_info, setter.param.as_ref()); + } else if prop.kind == PropertyKind::Set { + let name = prop_name_to_string(module_info, &prop.key); + let computed = prop.key.static_name().is_none(); + let params = if let Expression::FunctionExpression(func) = &prop.value + { + formal_params_to_param_defs(module_info, &func.params) + } else { + vec![] + }; methods.push(MethodDef { name, js_doc, kind: MethodKind::Setter, - location: get_location(module_info, setter.start()), - params: vec![param], + location: get_location(module_info, prop.span.start), + params, computed, optional: false, return_type: None, type_params: Box::new([]), }); - } - Prop::Method(method) => { - let name = prop_name_to_string(module_info, &method.key); - let computed = method.key.is_computed(); - let params = method - .function - .params - .iter() - .map(|param| param_to_param_def(module_info, param)) - .collect(); - let return_type = method - .function - .return_type - .as_ref() - .map(|type_ann| TsTypeDef::new(module_info, &type_ann.type_ann)); - let type_params = maybe_type_param_decl_to_type_param_defs( - module_info, - method.function.type_params.as_deref(), - ); - methods.push(MethodDef { - name, + } else if prop.method { + let name = prop_name_to_string(module_info, &prop.key); + let computed = prop.key.static_name().is_none(); + if let Expression::FunctionExpression(func) = &prop.value { + let params = formal_params_to_param_defs(module_info, &func.params); + let return_type = func.return_type.as_ref().map(|type_ann| { + TsTypeDef::new(module_info, &type_ann.type_annotation) + }); + let type_params = maybe_type_param_decl_to_type_param_defs( + module_info, + func.type_parameters.as_deref(), + ); + methods.push(MethodDef { + name, + js_doc, + kind: MethodKind::Method, + location: get_location(module_info, prop.span.start), + params, + computed, + optional: false, + return_type, + type_params, + }); + } + } else { + properties.push(PropertyDef { + name: prop_name_to_string(module_info, &prop.key), js_doc, - kind: MethodKind::Method, - location: get_location(module_info, method.start()), - params, - computed, + location: get_location(module_info, prop.span.start), + params: vec![], + readonly: false, + computed: prop.key.static_name().is_none(), optional: false, - return_type, - type_params, + ts_type: infer_ts_type_from_expr(module_info, &prop.value, false), + type_params: Box::new([]), }); } - }, - PropOrSpread::Spread(spread) => { - if let Expr::Object(obj) = &*spread.expr { + } + ObjectPropertyKind::SpreadProperty(spread) => { + if let Expression::ObjectExpression(obj) = &spread.argument { let (spread_methods, spread_properties) = infer_ts_type_from_obj_inner(module_info, obj); methods.extend(spread_methods); @@ -2142,11 +2175,11 @@ fn infer_ts_type_from_obj_inner( fn infer_ts_type_from_tpl( module_info: &EsModuleInfo, - tpl: &Tpl, + tpl: &TemplateLiteral, is_const: bool, ) -> TsTypeDef { let exprs = tpl - .exprs + .expressions .iter() .map(|expr| infer_ts_type_from_expr(module_info, expr, is_const)) .collect::>>(); @@ -2350,7 +2383,7 @@ impl Display for TsTypeDef { pub(crate) fn maybe_type_param_instantiation_to_type_defs( module_info: &EsModuleInfo, - maybe_type_param_instantiation: Option<&TsTypeParamInstantiation>, + maybe_type_param_instantiation: Option<&TSTypeParameterInstantiation>, ) -> Box<[TsTypeDef]> { if let Some(type_param_instantiation) = maybe_type_param_instantiation { type_param_instantiation diff --git a/src/ts_type_param.rs b/src/ts_type_param.rs index bd5a87b18..6324d07c3 100644 --- a/src/ts_type_param.rs +++ b/src/ts_type_param.rs @@ -1,8 +1,8 @@ // Copyright 2018-2024 the Deno authors. All rights reserved. MIT license. use crate::ts_type::TsTypeDef; -use deno_ast::swc::ast::TsTypeParam; -use deno_ast::swc::ast::TsTypeParamDecl; +use deno_ast::oxc::ast::ast::TSTypeParameter; +use deno_ast::oxc::ast::ast::TSTypeParameterDeclaration; use deno_graph::symbols::EsModuleInfo; use serde::Deserialize; use serde::Serialize; @@ -36,8 +36,8 @@ impl Display for TsTypeParamDef { } impl TsTypeParamDef { - pub fn new(module_info: &EsModuleInfo, param: &TsTypeParam) -> Self { - let name = param.name.sym.to_string(); + pub fn new(module_info: &EsModuleInfo, param: &TSTypeParameter) -> Self { + let name = param.name.name.to_string(); let constraint = param .constraint .as_ref() @@ -57,7 +57,7 @@ impl TsTypeParamDef { pub(crate) fn maybe_type_param_decl_to_type_param_defs( module_info: &EsModuleInfo, - maybe_type_param_decl: Option<&TsTypeParamDecl>, + maybe_type_param_decl: Option<&TSTypeParameterDeclaration>, ) -> Box<[TsTypeParamDef]> { if let Some(type_params_decl) = maybe_type_param_decl { type_params_decl diff --git a/src/type_alias.rs b/src/type_alias.rs index 91c820cf7..0c59159b6 100644 --- a/src/type_alias.rs +++ b/src/type_alias.rs @@ -2,6 +2,7 @@ use crate::ts_type::TsTypeDef; use crate::ts_type_param::TsTypeParamDef; use crate::ts_type_param::maybe_type_param_decl_to_type_param_defs; +use deno_ast::oxc::ast::ast::TSTypeAliasDeclaration; use deno_graph::symbols::EsModuleInfo; use serde::Deserialize; use serde::Serialize; @@ -16,12 +17,12 @@ pub struct TypeAliasDef { pub fn get_doc_for_ts_type_alias_decl( module_info: &EsModuleInfo, - type_alias_decl: &deno_ast::swc::ast::TsTypeAliasDecl, + type_alias_decl: &TSTypeAliasDeclaration, ) -> TypeAliasDef { - let ts_type = TsTypeDef::new(module_info, &type_alias_decl.type_ann); + let ts_type = TsTypeDef::new(module_info, &type_alias_decl.type_annotation); let type_params = maybe_type_param_decl_to_type_param_defs( module_info, - type_alias_decl.type_params.as_deref(), + type_alias_decl.type_parameters.as_deref(), ); TypeAliasDef { diff --git a/src/util/mod.rs b/src/util/mod.rs index 7b29a3b04..97fd3d938 100644 --- a/src/util/mod.rs +++ b/src/util/mod.rs @@ -3,3 +3,4 @@ pub mod graph; pub mod swc; pub mod symbol; +pub mod types; diff --git a/src/util/swc.rs b/src/util/swc.rs index cb49aecc2..bcd9ddf4f 100644 --- a/src/util/swc.rs +++ b/src/util/swc.rs @@ -1,12 +1,9 @@ // Copyright 2018-2024 the Deno authors. All rights reserved. MIT license. -use deno_ast::SourcePos; -use deno_ast::SourceRange; -use deno_ast::SourceRangedForSpanned; use deno_ast::SourceTextInfo; -use deno_ast::swc::ast::ModuleExportName; -use deno_ast::swc::common::comments::Comment; -use deno_ast::swc::common::comments::CommentKind; +use deno_ast::oxc::ast::ast::Comment; +use deno_ast::oxc::ast::ast::ModuleExportName; +use deno_ast::oxc::span::Span; use deno_graph::symbols::EsModuleInfo; use regex::Regex; @@ -22,8 +19,15 @@ pub(crate) fn is_false(b: &bool) -> bool { !b } -fn parse_js_doc(js_doc_comment: &Comment, module_info: &EsModuleInfo) -> JsDoc { - JsDoc::new(remove_stars_from_js_doc(&js_doc_comment.text), module_info) +fn parse_js_doc( + source_text: &str, + comment: &Comment, + module_info: &EsModuleInfo, +) -> JsDoc { + let content_span = comment.content_span(); + let text = + &source_text[content_span.start as usize..content_span.end as usize]; + JsDoc::new(remove_stars_from_js_doc(text), module_info) } fn remove_stars_from_js_doc(text: &str) -> String { @@ -38,16 +42,22 @@ fn remove_stars_from_js_doc(text: &str) -> String { pub(crate) fn js_doc_for_range_include_ignore( module_info: &EsModuleInfo, - range: &SourceRange, + span: Span, ) -> JsDoc { - let Some(comments) = module_info.source().comments().get_leading(range.start) - else { - return JsDoc::default(); - }; - if let Some(js_doc_comment) = comments.iter().rev().find(|comment| { - comment.kind == CommentKind::Block && comment.text.starts_with('*') - }) { - parse_js_doc(js_doc_comment, module_info) + let source_text = module_info.source_text(); + let comments = module_info.comments(); + if let Some(js_doc_comment) = comments + .iter() + .rev() + .filter(|c| c.attached_to == span.start && c.is_leading() && c.is_block()) + .find(|c| { + let content_span = c.content_span(); + let text = + &source_text[content_span.start as usize..content_span.end as usize]; + text.starts_with('*') + }) + { + parse_js_doc(source_text, js_doc_comment, module_info) } else { JsDoc::default() } @@ -55,9 +65,9 @@ pub(crate) fn js_doc_for_range_include_ignore( pub(crate) fn js_doc_for_range( module_info: &EsModuleInfo, - range: &SourceRange, + span: Span, ) -> Option { - let js_doc = js_doc_for_range_include_ignore(module_info, range); + let js_doc = js_doc_for_range_include_ignore(module_info, span); if js_doc.tags.contains(&JsDocTag::Ignore) { None } else { @@ -70,38 +80,48 @@ pub(crate) fn js_doc_for_range( /// `None`. pub(crate) fn module_js_doc_for_source( module_info: &EsModuleInfo, -) -> Option> { - module_info - .source() - .comments() - .get_vec() - .into_iter() - .filter(|comment| { - comment.kind == CommentKind::Block && comment.text.starts_with('*') - }) - .find_map(|comment| { - let js_doc = parse_js_doc(&comment, module_info); - - if js_doc - .tags - .iter() - .any(|tag| matches!(tag, JsDocTag::Module { .. })) - { - if js_doc.tags.contains(&JsDocTag::Ignore) { - Some(None) - } else { - Some(Some((js_doc, comment.range()))) - } - } else { - None - } +) -> Option> { + let source_text = module_info.source_text(); + let comments = module_info.comments(); + let statements = module_info.statements(); + + // Find the start of the first statement (or end of file) + let first_stmt_start = statements + .first() + .map(|s| { + use deno_ast::oxc::span::GetSpan; + s.span().start }) + .unwrap_or(u32::MAX); + + // Find leading block comments before the first statement that look like JSDoc + let js_doc_comment = comments.iter().find(|comment| { + comment.span.start < first_stmt_start && comment.is_block() && { + let content_span = comment.content_span(); + let text = + &source_text[content_span.start as usize..content_span.end as usize]; + text.starts_with('*') + } + })?; + + let js_doc = parse_js_doc(source_text, js_doc_comment, module_info); + if js_doc + .tags + .iter() + .any(|tag| matches!(tag, JsDocTag::Module { .. })) + { + if js_doc.tags.contains(&JsDocTag::Ignore) { + return Some(None); + } + return Some(Some((js_doc, js_doc_comment.span))); + } + None } -pub fn get_location(module_info: &EsModuleInfo, pos: SourcePos) -> Location { +pub fn get_location(module_info: &EsModuleInfo, pos: u32) -> Location { get_text_info_location( module_info.specifier().as_str(), - module_info.source().text_info_lazy(), + module_info.source_text_info(), pos, ) } @@ -109,15 +129,36 @@ pub fn get_location(module_info: &EsModuleInfo, pos: SourcePos) -> Location { pub fn get_text_info_location( specifier: &str, text_info: &SourceTextInfo, - pos: SourcePos, + pos: u32, ) -> Location { - let line_and_column_index = - text_info.line_and_column_display_with_indent_width(pos, 2); - let byte_index = pos.as_byte_index(text_info.range().start); + let byte_index = pos as usize; + let line_and_column_index = text_info.line_and_column_display(byte_index); + + // Adjust column for tab indentation (tabs count as 4 spaces for display, + // matching the old SWC behavior with indent_width=4) + let line_start_byte = byte_index - (line_and_column_index.column_number - 1); + let text = text_info.text(); + let col = if line_start_byte < text.len() { + let line_prefix = &text[line_start_byte..byte_index]; + let mut col = 0usize; + for ch in line_prefix.chars() { + if ch == '\t' { + // Round up to next multiple of 4 + col = (col + 4) & !3; + } else { + col += 1; + } + } + col + } else { + line_and_column_index.column_number - 1 + }; + Location { filename: specifier.into(), - line: line_and_column_index.line_number - 1, - col: line_and_column_index.column_number - 1, + // todo(#150): make 0-indexed + line: line_and_column_index.line_number, + col, byte_index, } } @@ -126,8 +167,9 @@ pub fn module_export_name_value( module_export_name: &ModuleExportName, ) -> String { match module_export_name { - ModuleExportName::Ident(ident) => ident.sym.to_string(), - ModuleExportName::Str(str) => str.value.to_string_lossy().into_owned(), + ModuleExportName::IdentifierName(ident) => ident.name.to_string(), + ModuleExportName::IdentifierReference(ident) => ident.name.to_string(), + ModuleExportName::StringLiteral(str) => str.value.to_string(), } } diff --git a/src/util/symbol.rs b/src/util/symbol.rs index f2bcc6f24..581933ec1 100644 --- a/src/util/symbol.rs +++ b/src/util/symbol.rs @@ -49,6 +49,6 @@ fn decl_has_ignorable_js_doc_tag( let Some(module) = module.esm() else { return false; }; - let js_doc = js_doc_for_range_include_ignore(module, &decl.range); + let js_doc = js_doc_for_range_include_ignore(module, decl.range); has_ignorable_js_doc_tag(&js_doc) } diff --git a/src/util/types.rs b/src/util/types.rs new file mode 100644 index 000000000..fce8abe7a --- /dev/null +++ b/src/util/types.rs @@ -0,0 +1,88 @@ +// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license. + +//! Local wrapper enums for OXC types that need serde support +//! with serialization compatible with the old SWC types. + +use deno_ast::oxc::ast::ast::MethodDefinitionKind; +use deno_ast::oxc::ast::ast::TSAccessibility; +use deno_ast::oxc::ast::ast::TSMethodSignatureKind; +use deno_ast::oxc::ast::ast::VariableDeclarationKind; +use serde::Deserialize; +use serde::Serialize; + +/// Mirrors the old SWC `Accessibility` enum with matching serde. +#[derive(Debug, Serialize, Deserialize, Clone, Copy, PartialEq, Eq)] +#[serde(rename_all = "lowercase")] +pub enum Accessibility { + Public, + Protected, + Private, +} + +impl From for Accessibility { + fn from(a: TSAccessibility) -> Self { + match a { + TSAccessibility::Public => Accessibility::Public, + TSAccessibility::Protected => Accessibility::Protected, + TSAccessibility::Private => Accessibility::Private, + } + } +} + +impl Accessibility { + pub fn from_oxc(a: Option) -> Option { + a.map(Self::from) + } +} + +/// Mirrors the old SWC `MethodKind` enum with matching serde. +#[derive(Debug, Serialize, Deserialize, Clone, Copy, PartialEq, Eq, Hash)] +#[serde(rename_all = "camelCase")] +pub enum MethodKind { + Method, + Getter, + Setter, +} + +impl From for MethodKind { + fn from(k: MethodDefinitionKind) -> Self { + match k { + MethodDefinitionKind::Method | MethodDefinitionKind::Constructor => { + MethodKind::Method + } + MethodDefinitionKind::Get => MethodKind::Getter, + MethodDefinitionKind::Set => MethodKind::Setter, + } + } +} + +impl From for MethodKind { + fn from(k: TSMethodSignatureKind) -> Self { + match k { + TSMethodSignatureKind::Method => MethodKind::Method, + TSMethodSignatureKind::Get => MethodKind::Getter, + TSMethodSignatureKind::Set => MethodKind::Setter, + } + } +} + +/// Mirrors the old SWC `VarDeclKind` enum with matching serde. +#[derive(Debug, Serialize, Deserialize, Clone, Copy, PartialEq, Eq)] +#[serde(rename_all = "camelCase")] +pub enum VarDeclKind { + Var, + Let, + Const, +} + +impl From for VarDeclKind { + fn from(k: VariableDeclarationKind) -> Self { + match k { + VariableDeclarationKind::Var => VarDeclKind::Var, + VariableDeclarationKind::Let => VarDeclKind::Let, + VariableDeclarationKind::Const + | VariableDeclarationKind::Using + | VariableDeclarationKind::AwaitUsing => VarDeclKind::Const, + } + } +} diff --git a/src/variable.rs b/src/variable.rs index 1ec3fd235..99240b935 100644 --- a/src/variable.rs +++ b/src/variable.rs @@ -1,7 +1,8 @@ // Copyright 2018-2024 the Deno authors. All rights reserved. MIT license. -use deno_ast::swc::ast::Pat; -use deno_ast::swc::ast::VarDeclKind; +use deno_ast::oxc::ast::ast::BindingPattern; +use deno_ast::oxc::ast::ast::VariableDeclaration; +use deno_ast::oxc::ast::ast::VariableDeclarator; use deno_graph::symbols::EsModuleInfo; use deno_graph::symbols::SymbolNodeRef; use serde::Deserialize; @@ -10,6 +11,7 @@ use serde::Serialize; use crate::ts_type::TsTypeDef; use crate::ts_type::TsTypeDefKind; use crate::ts_type::infer_simple_ts_type_from_init; +use crate::util::types::VarDeclKind; #[derive(Debug, Serialize, Deserialize, Clone)] #[serde(rename_all = "camelCase")] @@ -21,47 +23,53 @@ pub struct VariableDef { pub fn get_docs_for_var_declarator( module_info: &EsModuleInfo, - var_decl: &deno_ast::swc::ast::VarDecl, - var_declarator: &deno_ast::swc::ast::VarDeclarator, + var_decl: &VariableDeclaration, + var_declarator: &VariableDeclarator, ) -> Vec<(String, VariableDef)> { let mut items = Vec::<(String, VariableDef)>::new(); - let ref_name: Option = - var_declarator.init.as_ref().and_then(|init| { - if let deno_ast::swc::ast::Expr::Ident(ident) = &**init { - Some(ident.to_id()) - } else { - None - } - }); + let kind = VarDeclKind::from(var_decl.kind); + + let ref_ident = var_declarator.init.as_ref().and_then(|init| { + if let deno_ast::oxc::ast::ast::Expression::Identifier(ident) = init { + Some(ident) + } else { + None + } + }); + + let maybe_ts_type_ann = var_declarator.type_annotation.as_deref(); - let maybe_ts_type_ann = match &var_declarator.name { - Pat::Ident(ident) => ident.type_ann.as_ref(), - Pat::Object(pat) => pat.type_ann.as_ref(), - Pat::Array(pat) => pat.type_ann.as_ref(), - Pat::Invalid(_) | Pat::Expr(_) | Pat::Rest(_) | Pat::Assign(_) => None, - }; - let maybe_ts_type = maybe_ts_type_ann - .map(|def| TsTypeDef::new(module_info, &def.type_ann)) + // Type from explicit type annotation only (used for both simple and + // destructured patterns). + let explicit_ts_type = maybe_ts_type_ann + .map(|def| TsTypeDef::new(module_info, &def.type_annotation)); + + // Full inferred type (used only for simple identifier patterns, not + // destructured bindings). + let maybe_ts_type = explicit_ts_type + .clone() .or_else(|| { - if let Some(ref_name) = ref_name { - module_info.symbol_from_swc(&ref_name).and_then(|symbol| { - // todo(dsherret): it would be better to go to the declaration - // here, which is somewhat trivial with type tracing. + if let Some(ref_ident) = ref_ident { + let swc_id = (ref_ident.name.to_string(), 0usize); + module_info.symbol_from_swc(&swc_id).and_then(|symbol| { for decl in symbol.decls() { - if let Some(SymbolNodeRef::Var(_, var_declarator, _)) = + if let Some(SymbolNodeRef::Var(_, ref_var_declarator, _)) = decl.maybe_node() - && let Pat::Ident(ident) = &var_declarator.name - && let Some(type_ann) = &ident.type_ann { - return Some(TsTypeDef::new(module_info, &type_ann.type_ann)); - } - let maybe_type_ann = infer_simple_ts_type_from_init( - module_info, - var_declarator.init.as_deref(), - var_decl.kind == VarDeclKind::Const, - ); - if let Some(type_ann) = maybe_type_ann { - return Some(type_ann); + if let Some(type_ann) = &ref_var_declarator.type_annotation { + return Some(TsTypeDef::new( + module_info, + &type_ann.type_annotation, + )); + } + let maybe_type_ann = infer_simple_ts_type_from_init( + module_info, + ref_var_declarator.init.as_ref(), + kind == VarDeclKind::Const, + ); + if let Some(type_ann) = maybe_type_ann { + return Some(type_ann); + } } } None @@ -73,192 +81,156 @@ pub fn get_docs_for_var_declarator( .or_else(|| { infer_simple_ts_type_from_init( module_info, - var_declarator.init.as_deref(), - var_decl.kind == VarDeclKind::Const, + var_declarator.init.as_ref(), + kind == VarDeclKind::Const, ) }); - match &var_declarator.name { - Pat::Ident(ident) => { - let var_name = ident.id.sym.to_string(); + match &var_declarator.id { + BindingPattern::BindingIdentifier(ident) => { + let var_name = ident.name.to_string(); let variable_def = VariableDef { ts_type: maybe_ts_type, - kind: var_decl.kind, + kind, }; items.push((var_name, variable_def)); } - Pat::Object(obj) => get_vars_from_obj_destructuring( + BindingPattern::ObjectPattern(obj) => get_vars_from_obj_destructuring( obj, - var_decl.kind, - maybe_ts_type.as_ref(), + kind, + explicit_ts_type.as_ref(), &mut items, module_info, ), - Pat::Array(arr) => get_vars_from_array_destructuring( + BindingPattern::ArrayPattern(arr) => get_vars_from_array_destructuring( arr, - var_decl.kind, - maybe_ts_type.as_ref(), + kind, + explicit_ts_type.as_ref(), &mut items, module_info, ), - Pat::Expr(_) | Pat::Invalid(_) | Pat::Assign(_) | Pat::Rest(_) => {} + BindingPattern::AssignmentPattern(_) => {} } items } fn get_vars_from_obj_destructuring( - obj: &deno_ast::swc::ast::ObjectPat, + obj: &deno_ast::oxc::ast::ast::ObjectPattern, kind: VarDeclKind, maybe_ts_type: Option<&TsTypeDef>, items: &mut Vec<(String, VariableDef)>, module_info: &EsModuleInfo, ) { - let mut reached_rest = false; - for prop in &obj.props { - assert!(!reached_rest, "object rest is always last"); - let (name, reassign_name, rest_type_ann) = match prop { - deno_ast::swc::ast::ObjectPatProp::KeyValue(kv) => ( - crate::params::prop_name_to_string(module_info, &kv.key), - match &*kv.value { - Pat::Ident(ident) => Some(ident.sym.to_string()), - Pat::Assign(assign) => { - let name = match &*assign.left { - Pat::Ident(ident) => ident.sym.to_string(), - Pat::Rest(_) => unreachable!("assign cannot have rest"), - Pat::Assign(_) => unreachable!("rest cannot have assign"), - Pat::Array(_) | Pat::Object(_) => { - continue; // TODO(@crowlKats): implement recursive destructuring - } - Pat::Invalid(_) | Pat::Expr(_) => continue, - }; - - Some(name) - } - Pat::Array(_) | Pat::Object(_) => { - continue; // TODO(@crowlKats): implement recursive destructuring - } - Pat::Rest(_) | Pat::Invalid(_) | Pat::Expr(_) => { - continue; + for prop in &obj.properties { + let (name, reassign_name) = if prop.shorthand { + let key = match &prop.value { + BindingPattern::BindingIdentifier(ident) => ident.name.to_string(), + BindingPattern::AssignmentPattern(assign) => match &assign.left { + BindingPattern::BindingIdentifier(ident) => ident.name.to_string(), + _ => continue, + }, + _ => continue, + }; + (key, None) + } else { + let key = crate::params::prop_name_to_string(module_info, &prop.key); + let reassign_name = match &prop.value { + BindingPattern::BindingIdentifier(ident) => { + Some(ident.name.to_string()) + } + BindingPattern::AssignmentPattern(assign) => match &assign.left { + BindingPattern::BindingIdentifier(ident) => { + Some(ident.name.to_string()) } + _ => continue, }, - None, - ), - deno_ast::swc::ast::ObjectPatProp::Assign(assign) => { - (assign.key.sym.to_string(), None, None) - } - deno_ast::swc::ast::ObjectPatProp::Rest(rest) => { - reached_rest = true; - - ( - match &*rest.arg { - Pat::Ident(ident) => ident.sym.to_string(), - Pat::Rest(_) => unreachable!("rest cannot have rest"), - Pat::Assign(_) => unreachable!("rest cannot have assign"), - Pat::Array(_) | Pat::Object(_) => { - continue; // TODO(@crowlKats): implement recursive destructuring - } - Pat::Invalid(_) | Pat::Expr(_) => continue, - }, - None, - rest.type_ann.as_ref(), - ) - } - }; - - let ts_type = if !reached_rest { - maybe_ts_type.as_ref().and_then(|ts_type| { - if let TsTypeDefKind::TypeLiteral(type_literal) = &ts_type.kind { - type_literal.properties.iter().find_map(|property| { - if property.name == name { - property.ts_type.clone() - } else { - None - } - }) - } else { - None + BindingPattern::ArrayPattern(_) | BindingPattern::ObjectPattern(_) => { + continue; // TODO(@crowlKats): implement recursive destructuring } - }) - } else { - rest_type_ann - .map(|type_ann| TsTypeDef::new(module_info, &type_ann.type_ann)) + }; + (key, reassign_name) }; + let ts_type = maybe_ts_type.as_ref().and_then(|ts_type| { + if let TsTypeDefKind::TypeLiteral(type_literal) = &ts_type.kind { + type_literal.properties.iter().find_map(|property| { + if property.name == name { + property.ts_type.clone() + } else { + None + } + }) + } else { + None + } + }); + let variable_def = VariableDef { ts_type, kind }; items.push((reassign_name.unwrap_or(name), variable_def)); } + + // Handle rest element + if let Some(rest) = &obj.rest { + let name = match &rest.argument { + BindingPattern::BindingIdentifier(ident) => ident.name.to_string(), + _ => return, + }; + let variable_def = VariableDef { + ts_type: None, + kind, + }; + items.push((name, variable_def)); + } } fn get_vars_from_array_destructuring( - arr: &deno_ast::swc::ast::ArrayPat, + arr: &deno_ast::oxc::ast::ast::ArrayPattern, kind: VarDeclKind, maybe_ts_type: Option<&TsTypeDef>, items: &mut Vec<(String, VariableDef)>, - module_info: &EsModuleInfo, + _module_info: &EsModuleInfo, ) { - let mut reached_rest = false; - for (i, elem) in arr.elems.iter().enumerate() { - assert!(!reached_rest, "object rest is always last"); + for (i, elem) in arr.elements.iter().enumerate() { let Some(elem) = elem else { continue; }; - let (name, rest_type_ann) = match elem { - Pat::Ident(ident) => (ident.sym.to_string(), None), - Pat::Rest(rest) => { - reached_rest = true; - ( - match &*rest.arg { - Pat::Ident(ident) => ident.sym.to_string(), - Pat::Rest(_) => unreachable!("rest cannot have rest"), - Pat::Assign(_) => unreachable!("rest cannot have assign"), - Pat::Array(_) | Pat::Object(_) => { - continue; // TODO(@crowlKats): implement recursive destructuring - } - Pat::Invalid(_) | Pat::Expr(_) => continue, - }, - rest.type_ann.as_ref(), - ) - } - Pat::Assign(assign) => { - let name = match &*assign.left { - Pat::Ident(ident) => ident.sym.to_string(), - Pat::Rest(_) => unreachable!("assign cannot have rest"), - Pat::Assign(_) => unreachable!("rest cannot have assign"), - Pat::Array(_) | Pat::Object(_) => { - continue; // TODO(@crowlKats): implement recursive destructuring - } - Pat::Invalid(_) | Pat::Expr(_) => continue, - }; - - (name, None) - } - Pat::Array(_) | Pat::Object(_) => { + let name = match elem { + BindingPattern::BindingIdentifier(ident) => ident.name.to_string(), + BindingPattern::AssignmentPattern(assign) => match &assign.left { + BindingPattern::BindingIdentifier(ident) => ident.name.to_string(), + _ => continue, + }, + BindingPattern::ArrayPattern(_) | BindingPattern::ObjectPattern(_) => { continue; // TODO(@crowlKats): implement recursive destructuring } - Pat::Invalid(_) | Pat::Expr(_) => continue, }; - let ts_type = if !reached_rest { - maybe_ts_type.and_then(|ts_type| match &ts_type.kind { - TsTypeDefKind::Array(array) => Some(*array.clone()), - TsTypeDefKind::Tuple(tuple) => tuple.get(i).cloned(), - _ => None, - }) - } else { - rest_type_ann - .map(|type_ann| TsTypeDef::new(module_info, &type_ann.type_ann)) - .or_else(|| { - maybe_ts_type.and_then(|ts_type| { - if matches!(ts_type.kind, TsTypeDefKind::Array(_)) { - Some(ts_type.clone()) - } else { - None - } - }) - }) + let ts_type = maybe_ts_type.and_then(|ts_type| match &ts_type.kind { + TsTypeDefKind::Array(array) => Some(*array.clone()), + TsTypeDefKind::Tuple(tuple) => tuple.get(i).cloned(), + _ => None, + }); + + let variable_def = VariableDef { ts_type, kind }; + items.push((name, variable_def)); + } + + // Handle rest element + if let Some(rest) = &arr.rest { + let name = match &rest.argument { + BindingPattern::BindingIdentifier(ident) => ident.name.to_string(), + _ => return, }; + let ts_type = maybe_ts_type.and_then(|ts_type| { + if matches!(ts_type.kind, TsTypeDefKind::Array(_)) { + Some(ts_type.clone()) + } else { + None + } + }); + let variable_def = VariableDef { ts_type, kind }; items.push((name, variable_def)); } diff --git a/src/visibility.rs b/src/visibility.rs index 1915c2e02..3c7eb1a3c 100644 --- a/src/visibility.rs +++ b/src/visibility.rs @@ -5,7 +5,7 @@ use crate::util::graph::resolve_deno_graph_module; use crate::util::symbol::get_module_info; use crate::util::symbol::symbol_has_ignorable_js_doc_tag; -use deno_ast::SourceRange; +use deno_ast::oxc::span::Span; use deno_graph::ModuleGraph; use deno_graph::symbols::DefinitionPathNode; use deno_graph::symbols::DefinitionPathNodeResolved; @@ -22,14 +22,14 @@ use std::collections::HashSet; #[derive(Debug)] pub struct SymbolDeclDeps { pub symbol_id: UniqueSymbolId, - pub decl_range: SourceRange, + pub decl_range: Span, pub deps: IndexSet, /// If the path to this declaration had an ignorable js doc tag. pub had_ignorable_tag: bool, } #[derive(Default, Debug)] -pub struct SymbolDeps(IndexMap>); +pub struct SymbolDeps(IndexMap>); impl SymbolDeps { pub fn is_empty(&self) -> bool { @@ -90,7 +90,7 @@ impl SymbolVisibility { .filter(|d| !d.has_overloads()) .flat_map(|decl| { decl - .deps(ResolveDepsMode::TypesOnly) + .deps(ResolveDepsMode::TypesOnly, None) .into_iter() .map(move |dep| (decl, dep)) }) @@ -108,7 +108,7 @@ impl SymbolVisibility { .filter(|m| !m.has_overloads()) .flat_map(move |decl| { decl - .deps(ResolveDepsMode::TypesOnly) + .deps(ResolveDepsMode::TypesOnly, None) .into_iter() .map(move |dep| (symbol, decl, dep)) }) diff --git a/tests/helpers/mod.rs b/tests/helpers/mod.rs index 433ce0207..06e920e91 100644 --- a/tests/helpers/mod.rs +++ b/tests/helpers/mod.rs @@ -66,9 +66,11 @@ impl TestBuilder { .await; graph.valid().unwrap(); let entrypoints = &[entry_point_url]; + let allocator = deno_ast::oxc::allocator::Allocator::default(); let parser = DocParser::new( &graph, &analyzer, + &allocator, entrypoints, DocParserOptions { private: self.private, @@ -139,9 +141,11 @@ impl DiffTestBuilder { ) .await; graph.valid().unwrap(); + let allocator = deno_ast::oxc::allocator::Allocator::default(); let parser = DocParser::new( &graph, &analyzer, + &allocator, &roots, DocParserOptions { private: false, diff --git a/tests/html_test.rs b/tests/html_test.rs index 4ac3b60fc..c4cf67239 100644 --- a/tests/html_test.rs +++ b/tests/html_test.rs @@ -145,9 +145,11 @@ async fn get_files(subpath: &str) -> ParseOutput { ) .await; + let allocator = deno_ast::oxc::allocator::Allocator::default(); DocParser::new( &graph, &analyzer, + &allocator, &source_files, DocParserOptions { diagnostics: false, @@ -678,9 +680,11 @@ async fn parse_source(source: &str) -> ParseOutput { ) .await; + let allocator = deno_ast::oxc::allocator::Allocator::default(); DocParser::new( &graph, &analyzer, + &allocator, &[specifier], DocParserOptions { private: false, diff --git a/tests/specs/export_const_destructured.txt b/tests/specs/export_const_destructured.txt index 41bb6ac7d..efc35b30f 100644 --- a/tests/specs/export_const_destructured.txt +++ b/tests/specs/export_const_destructured.txt @@ -24,132 +24,124 @@ error[missing-jsdoc]: exported symbol is missing JSDoc documentation | ^ +error[missing-explicit-type]: exported symbol is missing an explicit type annotation + --> /mod.ts:16:16 + | +16 | export const { f, g: h } = d; + | ^ + + error[missing-jsdoc]: exported symbol is missing JSDoc documentation --> /mod.ts:16:22 | 16 | export const { f, g: h } = d; | ^ + +error[missing-explicit-type]: exported symbol is missing an explicit type annotation + --> /mod.ts:16:22 + | +16 | export const { f, g: h } = d; + | ^ + # output.txt -Defined in file:///mod.ts:5:3 +Defined in file:///mod.ts:6:3 const a: string export a doc -Defined in file:///mod.ts:7:3 +Defined in file:///mod.ts:8:3 const b: number export b doc -Defined in file:///mod.ts:15:16 +Defined in file:///mod.ts:16:16 -const f: string +const f -Defined in file:///mod.ts:15:22 +Defined in file:///mod.ts:16:22 -const h: number +const h # output.json -{ - "symbols": [ - { - "name": "a", - "declarations": [ - { - "location": { - "filename": "file:///mod.ts", - "line": 5, - "col": 2, - "byteIndex": 123 - }, - "declarationKind": "export", - "jsDoc": { - "doc": "export a doc" - }, - "kind": "variable", - "def": { - "tsType": { - "repr": "string", - "kind": "keyword", - "value": "string" - }, - "kind": "const" - } - } - ] +[ + { + "name": "a", + "isDefault": false, + "location": { + "filename": "file:///mod.ts", + "line": 6, + "col": 2, + "byteIndex": 123 }, - { - "name": "b", - "declarations": [ - { - "location": { - "filename": "file:///mod.ts", - "line": 7, - "col": 2, - "byteIndex": 150 - }, - "declarationKind": "export", - "jsDoc": { - "doc": "export b doc" - }, - "kind": "variable", - "def": { - "tsType": { - "repr": "number", - "kind": "keyword", - "value": "number" - }, - "kind": "const" - } - } - ] + "declarationKind": "export", + "jsDoc": { + "doc": "export a doc" + }, + "kind": "variable", + "variableDef": { + "tsType": { + "repr": "string", + "kind": "keyword", + "keyword": "string" + }, + "kind": "const" + } + }, + { + "name": "b", + "isDefault": false, + "location": { + "filename": "file:///mod.ts", + "line": 8, + "col": 2, + "byteIndex": 150 }, - { - "name": "f", - "declarations": [ - { - "location": { - "filename": "file:///mod.ts", - "line": 15, - "col": 15, - "byteIndex": 250 - }, - "declarationKind": "export", - "kind": "variable", - "def": { - "tsType": { - "repr": "string", - "kind": "keyword", - "value": "string" - }, - "kind": "const" - } - } - ] + "declarationKind": "export", + "jsDoc": { + "doc": "export b doc" + }, + "kind": "variable", + "variableDef": { + "tsType": { + "repr": "number", + "kind": "keyword", + "keyword": "number" + }, + "kind": "const" + } + }, + { + "name": "f", + "isDefault": false, + "location": { + "filename": "file:///mod.ts", + "line": 16, + "col": 15, + "byteIndex": 250 + }, + "declarationKind": "export", + "kind": "variable", + "variableDef": { + "tsType": null, + "kind": "const" + } + }, + { + "name": "h", + "isDefault": false, + "location": { + "filename": "file:///mod.ts", + "line": 16, + "col": 21, + "byteIndex": 256 }, - { - "name": "h", - "declarations": [ - { - "location": { - "filename": "file:///mod.ts", - "line": 15, - "col": 21, - "byteIndex": 256 - }, - "declarationKind": "export", - "kind": "variable", - "def": { - "tsType": { - "repr": "number", - "kind": "keyword", - "value": "number" - }, - "kind": "const" - } - } - ] + "declarationKind": "export", + "kind": "variable", + "variableDef": { + "tsType": null, + "kind": "const" } - ] -} + } +] diff --git a/tests/specs/export_namespace.txt b/tests/specs/export_namespace.txt index cd587bd0c..adf2d9c0a 100644 --- a/tests/specs/export_namespace.txt +++ b/tests/specs/export_namespace.txt @@ -33,10 +33,10 @@ error[missing-jsdoc]: exported symbol is missing JSDoc documentation error[missing-jsdoc]: exported symbol is missing JSDoc documentation - --> /mod.ts:15:8 + --> /mod.ts:15:25 | 15 | export namespace RootNs.OtherNs { - | ^ + | ^ error[missing-jsdoc]: exported symbol is missing JSDoc documentation @@ -46,7 +46,7 @@ error[missing-jsdoc]: exported symbol is missing JSDoc documentation | ^ # output.txt -Defined in file:///mod.ts:1:1 +Defined in file:///mod.ts:2:1 namespace RootNs Namespace JSdoc @@ -58,182 +58,172 @@ namespace RootNs # output.json -{ - "symbols": [ - { - "name": "RootNs", - "declarations": [ +[ + { + "name": "RootNs", + "isDefault": false, + "location": { + "filename": "file:///mod.ts", + "line": 2, + "col": 0, + "byteIndex": 23 + }, + "declarationKind": "export", + "jsDoc": { + "doc": "Namespace JSdoc" + }, + "kind": "namespace", + "namespaceDef": { + "elements": [ { + "name": "a", + "isDefault": false, "location": { "filename": "file:///mod.ts", - "line": 1, - "col": 0, - "byteIndex": 23 + "line": 3, + "col": 17, + "byteIndex": 66 + }, + "declarationKind": "export", + "kind": "variable", + "variableDef": { + "tsType": { + "repr": "a", + "kind": "literal", + "literal": { + "kind": "string", + "string": "a" + } + }, + "kind": "const" + } + }, + { + "name": "NestedNs", + "isDefault": false, + "location": { + "filename": "file:///mod.ts", + "line": 6, + "col": 4, + "byteIndex": 114 }, "declarationKind": "export", "jsDoc": { - "doc": "Namespace JSdoc" + "doc": "Nested namespace JSDoc" }, "kind": "namespace", - "def": { + "namespaceDef": { "elements": [ { - "name": "a", - "declarations": [ - { - "location": { - "filename": "file:///mod.ts", - "line": 2, - "col": 17, - "byteIndex": 66 - }, - "declarationKind": "export", - "kind": "variable", - "def": { - "tsType": { - "repr": "a", + "name": "Foo", + "isDefault": false, + "location": { + "filename": "file:///mod.ts", + "line": 7, + "col": 6, + "byteIndex": 148 + }, + "declarationKind": "export", + "kind": "enum", + "enumDef": { + "members": [ + { + "name": "a", + "init": { + "repr": "1", "kind": "literal", - "value": { - "kind": "string", - "string": "a" + "literal": { + "kind": "number", + "number": 1.0 } }, - "kind": "const" - } - } - ] - }, - { - "name": "NestedNs", - "declarations": [ - { - "location": { - "filename": "file:///mod.ts", - "line": 5, - "col": 4, - "byteIndex": 114 + "location": { + "filename": "file:///mod.ts", + "line": 8, + "col": 8, + "byteIndex": 174 + } }, - "declarationKind": "export", - "jsDoc": { - "doc": "Nested namespace JSDoc" - }, - "kind": "namespace", - "def": { - "elements": [ - { - "name": "Foo", - "declarations": [ - { - "location": { - "filename": "file:///mod.ts", - "line": 6, - "col": 6, - "byteIndex": 148 - }, - "declarationKind": "export", - "kind": "enum", - "def": { - "members": [ - { - "name": "a", - "init": { - "repr": "1", - "kind": "literal", - "value": { - "kind": "number", - "number": 1.0 - } - }, - "location": { - "filename": "file:///mod.ts", - "line": 7, - "col": 8, - "byteIndex": 174 - } - }, - { - "name": "b", - "init": { - "repr": "2", - "kind": "literal", - "value": { - "kind": "number", - "number": 2.0 - } - }, - "location": { - "filename": "file:///mod.ts", - "line": 8, - "col": 8, - "byteIndex": 189 - } - }, - { - "name": "c", - "init": { - "repr": "3", - "kind": "literal", - "value": { - "kind": "number", - "number": 3.0 - } - }, - "location": { - "filename": "file:///mod.ts", - "line": 9, - "col": 8, - "byteIndex": 204 - } - } - ] - } - } - ] + { + "name": "b", + "init": { + "repr": "2", + "kind": "literal", + "literal": { + "kind": "number", + "number": 2.0 } - ] - } - } - ] - }, - { - "name": "OtherNs", - "declarations": [ - { - "location": { - "filename": "file:///mod.ts", - "line": 14, - "col": 7, - "byteIndex": 235 + }, + "location": { + "filename": "file:///mod.ts", + "line": 9, + "col": 8, + "byteIndex": 189 + } }, - "declarationKind": "export", - "kind": "namespace", - "def": { - "elements": [ - { - "name": "Other", - "declarations": [ - { - "location": { - "filename": "file:///mod.ts", - "line": 15, - "col": 2, - "byteIndex": 264 - }, - "declarationKind": "export", - "kind": "class", - "def": {} - } - ] + { + "name": "c", + "init": { + "repr": "3", + "kind": "literal", + "literal": { + "kind": "number", + "number": 3.0 } - ] + }, + "location": { + "filename": "file:///mod.ts", + "line": 10, + "col": 8, + "byteIndex": 204 + } } - } - ] + ] + } + } + ] + } + }, + { + "name": "OtherNs", + "isDefault": false, + "location": { + "filename": "file:///mod.ts", + "line": 15, + "col": 24, + "byteIndex": 252 + }, + "declarationKind": "export", + "kind": "namespace", + "namespaceDef": { + "elements": [ + { + "name": "Other", + "isDefault": false, + "location": { + "filename": "file:///mod.ts", + "line": 16, + "col": 2, + "byteIndex": 264 + }, + "declarationKind": "export", + "kind": "class", + "classDef": { + "isAbstract": false, + "constructors": [], + "properties": [], + "indexSignatures": [], + "methods": [], + "extends": null, + "implements": [], + "typeParams": [], + "superTypeParams": [] + } } ] } } ] } - ] -} + } +] diff --git a/tests/specs/infer_object_literal.txt b/tests/specs/infer_object_literal.txt index c298df187..e3401680d 100644 --- a/tests/specs/infer_object_literal.txt +++ b/tests/specs/infer_object_literal.txt @@ -27,268 +27,308 @@ error[missing-jsdoc]: exported symbol is missing JSDoc documentation | ^ # output.txt -Defined in file:///mod.ts:3:14 +Defined in file:///mod.ts:4:14 -const a: { d(e: string): void; h(): string; h(value: string); [[t]](u: string): void; a: string; b: Map; c: { d: string; }; f: (g: string) => void; [[s]]: (number | string)[]; } +const a: { d(e: string): void; h(): string; h(value: string); [t](u: string): void; a: string; b: Map; c: { d: string; }; f: (g: string) => void; [s]: (number | string)[]; } # output.json -{ - "symbols": [ - { - "name": "a", - "declarations": [ - { - "location": { - "filename": "file:///mod.ts", - "line": 3, - "col": 13, - "byteIndex": 84 - }, - "declarationKind": "export", - "kind": "variable", - "def": { - "tsType": { - "kind": "typeLiteral", - "value": { - "methods": [ - { - "name": "d", - "kind": "method", - "location": { - "filename": "file:///mod.ts", - "line": 8, - "col": 2, - "byteIndex": 166 - }, - "params": [ - { - "kind": "identifier", - "name": "e", - "optional": false, - "tsType": { - "repr": "string", - "kind": "keyword", - "value": "string" - } - } - ], - "returnType": { - "repr": "void", - "kind": "keyword", - "value": "void" - } - }, - { - "name": "h", - "kind": "getter", - "location": { - "filename": "file:///mod.ts", - "line": 10, - "col": 2, - "byteIndex": 221 - }, - "params": [], - "returnType": { - "repr": "string", - "kind": "keyword", - "value": "string" - } - }, - { - "name": "h", - "kind": "setter", - "location": { - "filename": "file:///mod.ts", - "line": 13, - "col": 2, - "byteIndex": 262 - }, - "params": [ - { - "kind": "identifier", - "name": "value", - "optional": false, - "tsType": { - "repr": "string", - "kind": "keyword", - "value": "string" - } - } - ] - }, - { - "name": "[t]", - "kind": "method", - "location": { - "filename": "file:///mod.ts", - "line": 17, - "col": 2, - "byteIndex": 316 - }, - "params": [ - { - "kind": "identifier", - "name": "u", - "optional": false, - "tsType": { - "repr": "string", - "kind": "keyword", - "value": "string" - } - } - ], - "computed": true, - "returnType": { - "repr": "void", - "kind": "keyword", - "value": "void" - } +[ + { + "name": "a", + "isDefault": false, + "location": { + "filename": "file:///mod.ts", + "line": 4, + "col": 13, + "byteIndex": 84 + }, + "declarationKind": "export", + "kind": "variable", + "variableDef": { + "tsType": { + "repr": "", + "kind": "typeLiteral", + "typeLiteral": { + "constructors": [], + "methods": [ + { + "name": "d", + "kind": "method", + "location": { + "filename": "file:///mod.ts", + "line": 9, + "col": 2, + "byteIndex": 166 + }, + "params": [ + { + "kind": "identifier", + "name": "e", + "optional": false, + "tsType": { + "repr": "string", + "kind": "keyword", + "keyword": "string" } - ], - "properties": [ - { - "name": "a", - "jsDoc": { - "doc": "JSDoc" - }, - "location": { - "filename": "file:///mod.ts", - "line": 5, - "col": 2, - "byteIndex": 107 - }, - "tsType": { + } + ], + "optional": false, + "returnType": { + "repr": "void", + "kind": "keyword", + "keyword": "void" + }, + "typeParams": [] + }, + { + "name": "h", + "kind": "getter", + "location": { + "filename": "file:///mod.ts", + "line": 11, + "col": 2, + "byteIndex": 221 + }, + "params": [], + "optional": false, + "returnType": { + "repr": "string", + "kind": "keyword", + "keyword": "string" + }, + "typeParams": [] + }, + { + "name": "h", + "kind": "setter", + "location": { + "filename": "file:///mod.ts", + "line": 14, + "col": 2, + "byteIndex": 262 + }, + "params": [ + { + "kind": "identifier", + "name": "value", + "optional": false, + "tsType": { + "repr": "string", + "kind": "keyword", + "keyword": "string" + } + } + ], + "optional": false, + "returnType": null, + "typeParams": [] + }, + { + "name": "t", + "kind": "method", + "location": { + "filename": "file:///mod.ts", + "line": 18, + "col": 2, + "byteIndex": 316 + }, + "params": [ + { + "kind": "identifier", + "name": "u", + "optional": false, + "tsType": { + "repr": "string", + "kind": "keyword", + "keyword": "string" + } + } + ], + "computed": true, + "optional": false, + "returnType": { + "repr": "void", + "kind": "keyword", + "keyword": "void" + }, + "typeParams": [] + } + ], + "properties": [ + { + "name": "a", + "jsDoc": { + "doc": "JSDoc" + }, + "location": { + "filename": "file:///mod.ts", + "line": 6, + "col": 2, + "byteIndex": 107 + }, + "params": [], + "computed": false, + "optional": false, + "tsType": { + "repr": "string", + "kind": "keyword", + "keyword": "string" + }, + "typeParams": [] + }, + { + "name": "b", + "location": { + "filename": "file:///mod.ts", + "line": 7, + "col": 2, + "byteIndex": 117 + }, + "params": [], + "computed": false, + "optional": false, + "tsType": { + "repr": "Map", + "kind": "typeRef", + "typeRef": { + "typeParams": [ + { "repr": "string", "kind": "keyword", - "value": "string" - } - }, - { - "name": "b", - "location": { - "filename": "file:///mod.ts", - "line": 6, - "col": 2, - "byteIndex": 117 + "keyword": "string" }, - "tsType": { - "repr": "Map", - "kind": "typeRef", - "value": { - "typeParams": [ - { - "repr": "string", - "kind": "keyword", - "value": "string" - }, - { - "repr": "number", - "kind": "keyword", - "value": "number" - } - ], - "typeName": "Map" - } + { + "repr": "number", + "kind": "keyword", + "keyword": "number" } - }, - { - "name": "c", - "location": { - "filename": "file:///mod.ts", - "line": 7, - "col": 2, - "byteIndex": 149 - }, - "tsType": { - "kind": "typeLiteral", - "value": { - "properties": [ - { - "name": "d", - "location": { - "filename": "file:///mod.ts", - "line": 7, - "col": 7, - "byteIndex": 154 - }, - "tsType": { - "repr": "string", - "kind": "keyword", - "value": "string" - } - } - ] - } + ], + "typeName": "Map" + } + }, + "typeParams": [] + }, + { + "name": "c", + "location": { + "filename": "file:///mod.ts", + "line": 8, + "col": 2, + "byteIndex": 149 + }, + "params": [], + "computed": false, + "optional": false, + "tsType": { + "repr": "", + "kind": "typeLiteral", + "typeLiteral": { + "constructors": [], + "methods": [], + "properties": [ + { + "name": "d", + "location": { + "filename": "file:///mod.ts", + "line": 8, + "col": 7, + "byteIndex": 154 + }, + "params": [], + "computed": false, + "optional": false, + "tsType": { + "repr": "string", + "kind": "keyword", + "keyword": "string" + }, + "typeParams": [] } + ], + "callSignatures": [], + "indexSignatures": [] + } + }, + "typeParams": [] + }, + { + "name": "f", + "location": { + "filename": "file:///mod.ts", + "line": 10, + "col": 2, + "byteIndex": 191 + }, + "params": [], + "computed": false, + "optional": false, + "tsType": { + "repr": "", + "kind": "fnOrConstructor", + "fnOrConstructor": { + "constructor": false, + "tsType": { + "repr": "void", + "kind": "keyword", + "keyword": "void" }, - { - "name": "f", - "location": { - "filename": "file:///mod.ts", - "line": 9, - "col": 2, - "byteIndex": 191 - }, - "tsType": { - "kind": "fnOrConstructor", - "value": { - "constructor": false, - "tsType": { - "repr": "void", - "kind": "keyword", - "value": "void" - }, - "params": [ - { - "kind": "identifier", - "name": "g", - "optional": false, - "tsType": { - "repr": "string", - "kind": "keyword", - "value": "string" - } - } - ] + "params": [ + { + "kind": "identifier", + "name": "g", + "optional": false, + "tsType": { + "repr": "string", + "kind": "keyword", + "keyword": "string" } } - }, - { - "name": "[s]", - "location": { - "filename": "file:///mod.ts", - "line": 16, - "col": 2, - "byteIndex": 293 + ], + "typeParams": [] + } + }, + "typeParams": [] + }, + { + "name": "s", + "location": { + "filename": "file:///mod.ts", + "line": 17, + "col": 2, + "byteIndex": 293 + }, + "params": [], + "computed": true, + "optional": false, + "tsType": { + "repr": "", + "kind": "array", + "array": { + "repr": "", + "kind": "union", + "union": [ + { + "repr": "number", + "kind": "keyword", + "keyword": "number" }, - "computed": true, - "tsType": { - "kind": "array", - "value": { - "kind": "union", - "value": [ - { - "repr": "number", - "kind": "keyword", - "value": "number" - }, - { - "repr": "string", - "kind": "keyword", - "value": "string" - } - ] - } + { + "repr": "string", + "kind": "keyword", + "keyword": "string" } - } - ] - } - }, - "kind": "const" - } + ] + } + }, + "typeParams": [] + } + ], + "callSignatures": [], + "indexSignatures": [] } - ] + }, + "kind": "const" } - ] -} + } +] diff --git a/tests/specs/namespace_exports_self.txt b/tests/specs/namespace_exports_self.txt index 22cc40e03..8a7c08c58 100644 --- a/tests/specs/namespace_exports_self.txt +++ b/tests/specs/namespace_exports_self.txt @@ -41,7 +41,7 @@ Defined in file:///mod.ts:1:1 namespace a Description. - const a: string + private const a: string Description. Defined in file:///mod.ts:8:1 @@ -88,7 +88,7 @@ namespace f "col": 0, "byteIndex": 20 }, - "declarationKind": "export", + "declarationKind": "private", "jsDoc": { "doc": "Description." }, diff --git a/tests/specs/private_type_class_property.txt b/tests/specs/private_type_class_property.txt index dfd56a35d..9d894825c 100644 --- a/tests/specs/private_type_class_property.txt +++ b/tests/specs/private_type_class_property.txt @@ -30,48 +30,20 @@ error[private-type-ref]: public type 'PrivatePropThroughNamespaceRef' references info: to ensure documentation is complete all types that are exposed in the public API must be public -error[private-type-ref]: public type 'PrivatePropThroughNamespaceRef' references private type 'MyNamespace2' +error[private-type-ref]: public type 'PrivatePropThroughNamespaceRef' references private type 'MyNamespace.Export' --> /mod.ts:1:1 | 1 | export type PrivatePropThroughNamespaceRef = typeof MyNamespace.Export.someProp; | ^ = hint: make the referenced type public or remove the reference | -7 | namespace MyNamespace2 { - | - this is the referenced type +4 | export import Export = MyNamespace2.MyClass; + | - this is the referenced type | info: to ensure documentation is complete all types that are exposed in the public API must be public -error[private-type-ref]: public type 'PrivatePropThroughNamespaceRef' references private type 'MyNamespace3' - --> /mod.ts:1:1 - | - 1 | export type PrivatePropThroughNamespaceRef = typeof MyNamespace.Export.someProp; - | ^ - = hint: make the referenced type public or remove the reference - | -11 | namespace MyNamespace3 { - | - this is the referenced type - | - - info: to ensure documentation is complete all types that are exposed in the public API must be public - - -error[private-type-ref]: public type 'PrivatePropThroughNamespaceRef' references private type 'MyNamespace3.MyClass' - --> /mod.ts:1:1 - | - 1 | export type PrivatePropThroughNamespaceRef = typeof MyNamespace.Export.someProp; - | ^ - = hint: make the referenced type public or remove the reference - | -12 | export class MyClass { - | - this is the referenced type - | - - info: to ensure documentation is complete all types that are exposed in the public API must be public - - error[missing-jsdoc]: exported symbol is missing JSDoc documentation --> /mod.ts:1:1 | @@ -79,212 +51,51 @@ error[missing-jsdoc]: exported symbol is missing JSDoc documentation | ^ # output.txt -Defined in file:///mod.ts:0:1 +Defined in file:///mod.ts:1:1 type PrivatePropThroughNamespaceRef = typeof MyNamespace.Export.someProp -Defined in file:///mod.ts:2:1 +Defined in file:///mod.ts:3:1 private namespace MyNamespace - class Export - -Defined in file:///mod.ts:6:1 - -private namespace MyNamespace2 - - class MyClass - -Defined in file:///mod.ts:10:1 - -private namespace MyNamespace3 - - class MyClass # output.json -{ - "symbols": [ - { - "name": "PrivatePropThroughNamespaceRef", - "declarations": [ - { - "location": { - "filename": "file:///mod.ts", - "line": 0, - "col": 0, - "byteIndex": 0 - }, - "declarationKind": "export", - "kind": "typeAlias", - "def": { - "tsType": { - "repr": "MyNamespace.Export.someProp", - "kind": "typeQuery", - "value": "MyNamespace.Export.someProp" - } - } - } - ] +[ + { + "name": "PrivatePropThroughNamespaceRef", + "isDefault": false, + "location": { + "filename": "file:///mod.ts", + "line": 1, + "col": 0, + "byteIndex": 0 }, - { - "name": "MyNamespace", - "declarations": [ - { - "location": { - "filename": "file:///mod.ts", - "line": 2, - "col": 0, - "byteIndex": 82 - }, - "declarationKind": "private", - "kind": "namespace", - "def": { - "elements": [ - { - "name": "Export", - "declarations": [ - { - "location": { - "filename": "file:///mod.ts", - "line": 11, - "col": 2, - "byteIndex": 259 - }, - "declarationKind": "export", - "kind": "class", - "def": { - "properties": [ - { - "tsType": { - "repr": "string", - "kind": "keyword", - "value": "string" - }, - "isStatic": true, - "name": "someProp", - "location": { - "filename": "file:///mod.ts", - "line": 12, - "col": 4, - "byteIndex": 286 - } - } - ] - } - } - ] - } - ] - } - } - ] - }, - { - "name": "MyNamespace2", - "declarations": [ - { - "location": { - "filename": "file:///mod.ts", - "line": 6, - "col": 0, - "byteIndex": 156 - }, - "declarationKind": "private", - "kind": "namespace", - "def": { - "elements": [ - { - "name": "MyClass", - "declarations": [ - { - "location": { - "filename": "file:///mod.ts", - "line": 11, - "col": 2, - "byteIndex": 259 - }, - "declarationKind": "export", - "kind": "class", - "def": { - "properties": [ - { - "tsType": { - "repr": "string", - "kind": "keyword", - "value": "string" - }, - "isStatic": true, - "name": "someProp", - "location": { - "filename": "file:///mod.ts", - "line": 12, - "col": 4, - "byteIndex": 286 - } - } - ] - } - } - ] - } - ] - } - } - ] + "declarationKind": "export", + "kind": "typeAlias", + "typeAliasDef": { + "tsType": { + "repr": "MyNamespace.Export.someProp", + "kind": "typeQuery", + "typeQuery": "MyNamespace.Export.someProp" + }, + "typeParams": [] + } + }, + { + "name": "MyNamespace", + "isDefault": false, + "location": { + "filename": "file:///mod.ts", + "line": 3, + "col": 0, + "byteIndex": 82 }, - { - "name": "MyNamespace3", - "declarations": [ - { - "location": { - "filename": "file:///mod.ts", - "line": 10, - "col": 0, - "byteIndex": 232 - }, - "declarationKind": "private", - "kind": "namespace", - "def": { - "elements": [ - { - "name": "MyClass", - "declarations": [ - { - "location": { - "filename": "file:///mod.ts", - "line": 11, - "col": 2, - "byteIndex": 259 - }, - "declarationKind": "export", - "kind": "class", - "def": { - "properties": [ - { - "tsType": { - "repr": "string", - "kind": "keyword", - "value": "string" - }, - "isStatic": true, - "name": "someProp", - "location": { - "filename": "file:///mod.ts", - "line": 12, - "col": 4, - "byteIndex": 286 - } - } - ] - } - } - ] - } - ] - } - } - ] + "declarationKind": "private", + "kind": "namespace", + "namespaceDef": { + "elements": [] } - ] -} + } +] diff --git a/tests/specs/re_export_all_as_with_jsdoc.txt b/tests/specs/re_export_all_as_with_jsdoc.txt index f8ab324cf..99d8a3573 100644 --- a/tests/specs/re_export_all_as_with_jsdoc.txt +++ b/tests/specs/re_export_all_as_with_jsdoc.txt @@ -7,7 +7,7 @@ export function foo(): void {} export * as other from "./other.ts"; # output.txt -Defined in file:///mod.ts:1:8 +Defined in file:///mod.ts:2:1 namespace other Re-exports of other. @@ -17,56 +17,51 @@ namespace other # output.json -{ - "symbols": [ - { - "name": "other", - "declarations": [ +[ + { + "name": "other", + "isDefault": false, + "location": { + "filename": "file:///mod.ts", + "line": 2, + "col": 0, + "byteIndex": 28 + }, + "declarationKind": "export", + "jsDoc": { + "doc": "Re-exports of other." + }, + "kind": "namespace", + "namespaceDef": { + "elements": [ { + "name": "foo", + "isDefault": false, "location": { - "filename": "file:///mod.ts", - "line": 1, - "col": 7, - "byteIndex": 35 + "filename": "file:///other.ts", + "line": 2, + "col": 0, + "byteIndex": 18 }, "declarationKind": "export", "jsDoc": { - "doc": "Re-exports of other." + "doc": "a function" }, - "kind": "namespace", - "def": { - "elements": [ - { - "name": "foo", - "declarations": [ - { - "location": { - "filename": "file:///other.ts", - "line": 1, - "col": 0, - "byteIndex": 18 - }, - "declarationKind": "export", - "jsDoc": { - "doc": "a function" - }, - "kind": "function", - "def": { - "params": [], - "returnType": { - "repr": "void", - "kind": "keyword", - "value": "void" - }, - "hasBody": true - } - } - ] - } - ] + "kind": "function", + "functionDef": { + "params": [], + "returnType": { + "repr": "void", + "kind": "keyword", + "keyword": "void" + }, + "hasBody": true, + "isAsync": false, + "isGenerator": false, + "typeParams": [] } } ] } - ] -} + } +] From f599fa92d61fd6d28218b63f5796f00fadcbbce1 Mon Sep 17 00:00:00 2001 From: Nathan Whitaker Date: Tue, 17 Mar 2026 13:09:47 -0700 Subject: [PATCH 2/9] use git --- Cargo.lock | 2 +- Cargo.toml | 2 +- rust-toolchain.toml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 84a9918c3..bbe45084b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2879,7 +2879,7 @@ version = "0.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0978bf7171b3d90bac376700cb56d606feb40f251a475a5d6634613564460b22" dependencies = [ - "windows-sys 0.60.2", + "windows-sys 0.59.0", ] [[package]] diff --git a/Cargo.toml b/Cargo.toml index 5400e0957..cfbddcc50 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -15,7 +15,7 @@ deno_graph = { path = "../deno_graph", default-features = false, features = [ "swc", "symbols", ] } -deno_ast = { path = "../deno_ast" } +deno_ast = { git = "https://github.com/nathanwhit/deno_ast", branch = "oxc-port" } import_map = "0.25.0" serde = { version = "1.0.204", features = ["derive"] } serde_json = { version = "1.0.122", features = ["preserve_order"] } diff --git a/rust-toolchain.toml b/rust-toolchain.toml index 1a2165581..4f0430eac 100644 --- a/rust-toolchain.toml +++ b/rust-toolchain.toml @@ -1,3 +1,3 @@ [toolchain] -channel = "1.92.0" +channel = "1.96.0" components = ["rustfmt", "clippy"] From ef2349f5cca4c87ea13aefb21c8a66f76dd74d74 Mon Sep 17 00:00:00 2001 From: Nathan Whitaker Date: Tue, 2 Jun 2026 13:36:35 -0700 Subject: [PATCH 3/9] fix tests --- src/html/types.rs | 8 +- src/js_doc.rs | 5 +- src/lib.rs | 41 +- src/parser.rs | 30 +- src/tests.rs | 4 +- src/ts_type.rs | 366 +++++++++++- src/util/swc.rs | 65 +-- tests/diff_specs/function_throws_change.txt | 20 +- ...html_test__html_doc_files_multiple-40.snap | 4 +- tests/snapshots/html_test__symbol_group.snap | 4 +- tests/specs/export_const_destructured.txt | 172 +++--- tests/specs/export_namespace.txt | 302 +++++----- tests/specs/indented_with_tabs.txt | 4 +- tests/specs/infer_object_literal.txt | 534 ++++++++---------- tests/specs/jsdoc_types.txt | 50 +- tests/specs/mapped_types.txt | 5 +- tests/specs/namespace_exports_self.txt | 4 +- tests/specs/private_type_class_property.txt | 81 +-- tests/specs/re_export_all_as_with_jsdoc.txt | 81 +-- tests/specs/structured_jsdoc.txt | 5 +- tests/specs/type_literal_mapped_type.txt | 5 +- 21 files changed, 1044 insertions(+), 746 deletions(-) diff --git a/src/html/types.rs b/src/html/types.rs index 64fe46a3d..093c0c71a 100644 --- a/src/html/types.rs +++ b/src/html/types.rs @@ -166,13 +166,7 @@ pub(crate) fn render_type_def( ) }) } else { - Some(format!( - "#{}", - IdBuilder::new(ctx) - .kind(IdKind::TypeParam) - .name(&type_ref.type_name) - .build_unregistered() - )) + None } } crate::ts_type::TypeRefResolution::Import { specifier, name } => { diff --git a/src/js_doc.rs b/src/js_doc.rs index a46d441b1..d5d68579a 100644 --- a/src/js_doc.rs +++ b/src/js_doc.rs @@ -74,7 +74,9 @@ pub fn parse_jsdoc_type( type_alias, ) = type_alias { - Some(TsTypeDef::new(module_info, &type_alias.type_annotation)) + let mut ts_type = TsTypeDef::new(module_info, &type_alias.type_annotation); + ts_type.clear_resolutions(); + Some(ts_type) } else { None } @@ -615,7 +617,6 @@ mod tests { ) -> serde_json::Value { let mut value = serde_json::json!({ "typeName": name, - "resolution": { "kind": "typeParam" }, }); if let Some(tp) = type_params { value["typeParams"] = serde_json::json!(tp); diff --git a/src/lib.rs b/src/lib.rs index ba33738ba..64ae16023 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -207,16 +207,16 @@ pub fn docnodes_v1_to_v2(value: serde_json::Value) -> Document { let mut declaration = serde_json::Value::Object(obj); migrate_declaration(&mut declaration); - let symbol = symbols.entry(name.clone()).or_insert_with(|| Symbol { - name, - is_default, - declarations: vec![], - }); - // If any entry is marked default, the symbol is default - if is_default { - symbol.is_default = true; - } if let Ok(decl) = serde_json::from_value::(declaration) { + let symbol = symbols.entry(name.clone()).or_insert_with(|| Symbol { + name, + is_default, + declarations: vec![], + }); + // If any entry is marked default, the symbol is default + if is_default { + symbol.is_default = true; + } symbol.declarations.push(decl); } } @@ -313,18 +313,21 @@ fn v1_nodes_to_symbols(nodes: Vec) -> serde_json::Value { let mut decl = serde_json::Value::Object(obj); migrate_declaration(&mut decl); - let symbol = symbols.entry(name.clone()).or_insert_with(|| { - serde_json::json!({ - "name": name, - "declarations": [] - }) - }); + let declaration = serde_json::from_value::(decl.clone()); + if declaration.is_ok() { + let symbol = symbols.entry(name.clone()).or_insert_with(|| { + serde_json::json!({ + "name": name, + "declarations": [] + }) + }); + + if is_default { + symbol["isDefault"] = serde_json::Value::Bool(true); + } - if is_default { - symbol["isDefault"] = serde_json::Value::Bool(true); + symbol["declarations"].as_array_mut().unwrap().push(decl); } - - symbol["declarations"].as_array_mut().unwrap().push(decl); } serde_json::Value::Array(symbols.into_values().collect()) diff --git a/src/parser.rs b/src/parser.rs index a8466f8b8..c32f1240b 100644 --- a/src/parser.rs +++ b/src/parser.rs @@ -1413,8 +1413,14 @@ impl<'a> DocParser<'a> { self.get_doc_for_export_default_decl(module_info, n) } SymbolNodeRef::ExportDefaultExpr(n) => { - let js_doc = js_doc_for_range(module_info, n.span())?; - let location = get_location(module_info, n.span().start); + let (js_doc, location) = self + .export_default_expr_context(module_info, n) + .unwrap_or_else(|| { + ( + js_doc_for_range(module_info, n.span()).unwrap_or_default(), + get_location(module_info, n.span().start), + ) + }); self.get_decl_for_export_default_expr(module_info, n, js_doc, location) } SymbolNodeRef::FnDecl(n) => { @@ -1530,6 +1536,26 @@ impl<'a> DocParser<'a> { } } + fn export_default_expr_context( + &self, + module_info: &EsModuleInfo, + export_expr: &ExportDefaultDeclarationKind, + ) -> Option<(JsDoc, Location)> { + let expr_span = export_expr.span(); + for stmt in module_info.statements() { + let Statement::ExportDefaultDeclaration(export_default) = stmt else { + continue; + }; + if export_default.declaration.span() == expr_span { + return Some(( + js_doc_for_range(module_info, export_default.span)?, + get_location(module_info, export_default.span.start), + )); + } + } + None + } + fn get_declare_for_export_decl_declaration( &self, export_decl: &ExportNamedDeclaration, diff --git a/src/tests.rs b/src/tests.rs index 39f8ce914..e8366df93 100644 --- a/src/tests.rs +++ b/src/tests.rs @@ -519,8 +519,8 @@ export * as b from "./mod_doc.ts"; "location": { "filename": "file:///ns.ts", "line": 1, - "col": 7, - "byteIndex": 8 + "col": 0, + "byteIndex": 1 }, "declarationKind": "export", "jsDoc": { diff --git a/src/ts_type.rs b/src/ts_type.rs index 40c436092..85d4252a2 100644 --- a/src/ts_type.rs +++ b/src/ts_type.rs @@ -903,6 +903,13 @@ fn resolve_type_ref( module_info: &EsModuleInfo, ident: &IdentifierReference, ) -> Option { + let reference_symbol_id = ident + .reference_id + .get() + .zip(module_info.scoping()) + .and_then(|(reference_id, scoping)| { + scoping.get_reference(reference_id).symbol_id() + }); let id = identifier_reference_to_id(module_info, ident); if let Some(symbol) = module_info.symbol_from_swc(&id) { if let Some(file_dep) = symbol.file_dep() { @@ -913,16 +920,196 @@ fn resolve_type_ref( } else { Some(TypeRefResolution::Local) } - } else if id.1 != 0 { + } else if let Some((declaring_name, declaring_kind)) = reference_symbol_id + .and_then(|symbol_id| { + module_info.scoping().and_then(|scoping| { + type_param_declaring_info(module_info, scoping.symbol_span(symbol_id)) + }) + }) + { Some(TypeRefResolution::TypeParam { - declaring_name: None, - declaring_kind: None, + declaring_name, + declaring_kind, }) } else { None } } +fn type_param_declaring_info( + module_info: &EsModuleInfo, + type_param_span: Span, +) -> Option<(Option, Option)> { + for stmt in module_info.statements() { + let info = match stmt { + Statement::FunctionDeclaration(function) => { + function_type_param_declaring_info( + function, + type_param_span, + TypeParamDeclaringKind::Function, + ) + } + Statement::ClassDeclaration(class) => class_type_param_declaring_info( + class, + type_param_span, + TypeParamDeclaringKind::Class, + ), + Statement::TSInterfaceDeclaration(interface_decl) => { + named_type_param_declaring_info( + &interface_decl.id.name, + interface_decl.type_parameters.as_deref(), + type_param_span, + TypeParamDeclaringKind::Interface, + ) + } + Statement::TSTypeAliasDeclaration(type_alias) => { + named_type_param_declaring_info( + &type_alias.id.name, + type_alias.type_parameters.as_deref(), + type_param_span, + TypeParamDeclaringKind::TypeAlias, + ) + } + Statement::ExportNamedDeclaration(export) => { + export.declaration.as_ref().and_then(|decl| { + declaration_type_param_declaring_info(decl, type_param_span) + }) + } + Statement::ExportDefaultDeclaration(export) => { + export_default_type_param_declaring_info(export, type_param_span) + } + _ => None, + }; + if info.is_some() { + return info; + } + } + None +} + +fn declaration_type_param_declaring_info( + declaration: &Declaration, + type_param_span: Span, +) -> Option<(Option, Option)> { + match declaration { + Declaration::FunctionDeclaration(function) => { + function_type_param_declaring_info( + function, + type_param_span, + TypeParamDeclaringKind::Function, + ) + } + Declaration::ClassDeclaration(class) => class_type_param_declaring_info( + class, + type_param_span, + TypeParamDeclaringKind::Class, + ), + Declaration::TSInterfaceDeclaration(interface_decl) => { + named_type_param_declaring_info( + &interface_decl.id.name, + interface_decl.type_parameters.as_deref(), + type_param_span, + TypeParamDeclaringKind::Interface, + ) + } + Declaration::TSTypeAliasDeclaration(type_alias) => { + named_type_param_declaring_info( + &type_alias.id.name, + type_alias.type_parameters.as_deref(), + type_param_span, + TypeParamDeclaringKind::TypeAlias, + ) + } + _ => None, + } +} + +fn export_default_type_param_declaring_info( + export: &ExportDefaultDeclaration, + type_param_span: Span, +) -> Option<(Option, Option)> { + match &export.declaration { + ExportDefaultDeclarationKind::FunctionDeclaration(function) => { + function_type_param_declaring_info( + function, + type_param_span, + TypeParamDeclaringKind::Function, + ) + } + ExportDefaultDeclarationKind::ClassDeclaration(class) => { + class_type_param_declaring_info( + class, + type_param_span, + TypeParamDeclaringKind::Class, + ) + } + ExportDefaultDeclarationKind::TSInterfaceDeclaration(interface_decl) => { + named_type_param_declaring_info( + &interface_decl.id.name, + interface_decl.type_parameters.as_deref(), + type_param_span, + TypeParamDeclaringKind::Interface, + ) + } + _ => None, + } +} + +fn function_type_param_declaring_info( + function: &Function, + type_param_span: Span, + kind: TypeParamDeclaringKind, +) -> Option<(Option, Option)> { + named_type_param_declaring_info( + function + .id + .as_ref() + .map(|id| id.name.as_str()) + .unwrap_or("default"), + function.type_parameters.as_deref(), + type_param_span, + kind, + ) +} + +fn class_type_param_declaring_info( + class: &Class, + type_param_span: Span, + kind: TypeParamDeclaringKind, +) -> Option<(Option, Option)> { + named_type_param_declaring_info( + class + .id + .as_ref() + .map(|id| id.name.as_str()) + .unwrap_or("default"), + class.type_parameters.as_deref(), + type_param_span, + kind, + ) +} + +fn named_type_param_declaring_info( + declaring_name: &str, + type_parameters: Option<&TSTypeParameterDeclaration>, + type_param_span: Span, + kind: TypeParamDeclaringKind, +) -> Option<(Option, Option)> { + if type_parameters? + .params + .iter() + .any(|param| span_contains(param.span, type_param_span)) + { + Some((Some(declaring_name.to_string()), Some(kind))) + } else { + None + } +} + +fn span_contains(container: Span, span: Span) -> bool { + container.start <= span.start && span.end <= container.end +} + fn ts_tuple_element_to_ts_type_def( module_info: &EsModuleInfo, elem: &TSTupleElement, @@ -1534,6 +1721,179 @@ impl Display for TsTypePredicateDef { } impl TsTypeDef { + pub(crate) fn clear_resolutions(&mut self) { + fn clear_type_param(type_param: &mut TsTypeParamDef) { + if let Some(constraint) = &mut type_param.constraint { + constraint.clear_resolutions(); + } + if let Some(default) = &mut type_param.default { + default.clear_resolutions(); + } + } + + fn clear_param(param: &mut ParamDef) { + match &mut param.pattern { + ParamPatternDef::Array { elements, .. } => { + for element in elements.iter_mut().flatten() { + clear_param(element); + } + } + ParamPatternDef::Assign { left, .. } => clear_param(left), + ParamPatternDef::Object { props, .. } => { + for prop in props { + match prop { + crate::params::ObjectPatPropDef::KeyValue { value, .. } => { + clear_param(value); + } + crate::params::ObjectPatPropDef::Rest { arg } => { + clear_param(arg); + } + crate::params::ObjectPatPropDef::Assign { .. } => {} + } + } + } + ParamPatternDef::Rest { arg } => clear_param(arg), + ParamPatternDef::Identifier { .. } => {} + } + if let Some(ts_type) = &mut param.ts_type { + ts_type.clear_resolutions(); + } + } + + match &mut self.kind { + TsTypeDefKind::TypeRef(type_ref) => { + type_ref.resolution = None; + if let Some(type_params) = &mut type_ref.type_params { + for type_param in type_params.iter_mut() { + type_param.clear_resolutions(); + } + } + } + TsTypeDefKind::Literal(literal) => { + if let Some(ts_types) = &mut literal.ts_types { + for ts_type in ts_types { + ts_type.clear_resolutions(); + } + } + } + TsTypeDefKind::Union(types) + | TsTypeDefKind::Intersection(types) + | TsTypeDefKind::Tuple(types) => { + for ts_type in types { + ts_type.clear_resolutions(); + } + } + TsTypeDefKind::Array(ts_type) + | TsTypeDefKind::Parenthesized(ts_type) + | TsTypeDefKind::Rest(ts_type) + | TsTypeDefKind::Optional(ts_type) => ts_type.clear_resolutions(), + TsTypeDefKind::TypeOperator(type_operator) => { + type_operator.ts_type.clear_resolutions(); + } + TsTypeDefKind::FnOrConstructor(fn_or_constructor) => { + fn_or_constructor.ts_type.clear_resolutions(); + for param in &mut fn_or_constructor.params { + clear_param(param); + } + for type_param in &mut fn_or_constructor.type_params { + clear_type_param(type_param); + } + } + TsTypeDefKind::Conditional(conditional) => { + conditional.check_type.clear_resolutions(); + conditional.extends_type.clear_resolutions(); + conditional.true_type.clear_resolutions(); + conditional.false_type.clear_resolutions(); + } + TsTypeDefKind::Infer(infer) => { + clear_type_param(&mut infer.type_param); + } + TsTypeDefKind::IndexedAccess(indexed_access) => { + indexed_access.obj_type.clear_resolutions(); + indexed_access.index_type.clear_resolutions(); + } + TsTypeDefKind::Mapped(mapped) => { + clear_type_param(&mut mapped.type_param); + if let Some(name_type) = &mut mapped.name_type { + name_type.clear_resolutions(); + } + if let Some(ts_type) = &mut mapped.ts_type { + ts_type.clear_resolutions(); + } + } + TsTypeDefKind::TypeLiteral(type_literal) => { + for ctor in &mut type_literal.constructors { + for param in &mut ctor.params { + clear_param(param); + } + if let Some(return_type) = &mut ctor.return_type { + return_type.clear_resolutions(); + } + for type_param in &mut ctor.type_params { + clear_type_param(type_param); + } + } + for method in &mut type_literal.methods { + for param in &mut method.params { + clear_param(param); + } + if let Some(return_type) = &mut method.return_type { + return_type.clear_resolutions(); + } + for type_param in &mut method.type_params { + clear_type_param(type_param); + } + } + for property in &mut type_literal.properties { + for param in &mut property.params { + clear_param(param); + } + if let Some(ts_type) = &mut property.ts_type { + ts_type.clear_resolutions(); + } + for type_param in &mut property.type_params { + clear_type_param(type_param); + } + } + for call_signature in &mut type_literal.call_signatures { + for param in &mut call_signature.params { + clear_param(param); + } + if let Some(ts_type) = &mut call_signature.ts_type { + ts_type.clear_resolutions(); + } + for type_param in &mut call_signature.type_params { + clear_type_param(type_param); + } + } + for index_signature in &mut type_literal.index_signatures { + for param in &mut index_signature.params { + clear_param(param); + } + if let Some(ts_type) = &mut index_signature.ts_type { + ts_type.clear_resolutions(); + } + } + } + TsTypeDefKind::TypePredicate(type_predicate) => { + if let Some(ts_type) = &mut type_predicate.r#type { + ts_type.clear_resolutions(); + } + } + TsTypeDefKind::ImportType(import_type) => { + if let Some(type_params) = &mut import_type.type_params { + for type_param in type_params { + type_param.clear_resolutions(); + } + } + } + TsTypeDefKind::Keyword(_) + | TsTypeDefKind::TypeQuery(_) + | TsTypeDefKind::This + | TsTypeDefKind::Unsupported => {} + } + } + pub fn number_literal(num: &NumericLiteral) -> Self { Self::number_value(num.value) } diff --git a/src/util/swc.rs b/src/util/swc.rs index bcd9ddf4f..445cca8c5 100644 --- a/src/util/swc.rs +++ b/src/util/swc.rs @@ -83,37 +83,26 @@ pub(crate) fn module_js_doc_for_source( ) -> Option> { let source_text = module_info.source_text(); let comments = module_info.comments(); - let statements = module_info.statements(); - - // Find the start of the first statement (or end of file) - let first_stmt_start = statements - .first() - .map(|s| { - use deno_ast::oxc::span::GetSpan; - s.span().start - }) - .unwrap_or(u32::MAX); - // Find leading block comments before the first statement that look like JSDoc - let js_doc_comment = comments.iter().find(|comment| { - comment.span.start < first_stmt_start && comment.is_block() && { + for js_doc_comment in comments.iter().filter(|comment| { + comment.is_block() && { let content_span = comment.content_span(); let text = &source_text[content_span.start as usize..content_span.end as usize]; text.starts_with('*') } - })?; - - let js_doc = parse_js_doc(source_text, js_doc_comment, module_info); - if js_doc - .tags - .iter() - .any(|tag| matches!(tag, JsDocTag::Module { .. })) - { - if js_doc.tags.contains(&JsDocTag::Ignore) { - return Some(None); + }) { + let js_doc = parse_js_doc(source_text, js_doc_comment, module_info); + if js_doc + .tags + .iter() + .any(|tag| matches!(tag, JsDocTag::Module { .. })) + { + if js_doc.tags.contains(&JsDocTag::Ignore) { + return Some(None); + } + return Some(Some((js_doc, js_doc_comment.span))); } - return Some(Some((js_doc, js_doc_comment.span))); } None } @@ -132,33 +121,15 @@ pub fn get_text_info_location( pos: u32, ) -> Location { let byte_index = pos as usize; - let line_and_column_index = text_info.line_and_column_display(byte_index); - - // Adjust column for tab indentation (tabs count as 4 spaces for display, - // matching the old SWC behavior with indent_width=4) - let line_start_byte = byte_index - (line_and_column_index.column_number - 1); let text = text_info.text(); - let col = if line_start_byte < text.len() { - let line_prefix = &text[line_start_byte..byte_index]; - let mut col = 0usize; - for ch in line_prefix.chars() { - if ch == '\t' { - // Round up to next multiple of 4 - col = (col + 4) & !3; - } else { - col += 1; - } - } - col - } else { - line_and_column_index.column_number - 1 - }; + let lookup_byte_index = byte_index.min(text.len()); + let line_and_column_index = + text_info.line_and_column_display(lookup_byte_index); Location { filename: specifier.into(), - // todo(#150): make 0-indexed - line: line_and_column_index.line_number, - col, + line: line_and_column_index.line_number - 1, + col: line_and_column_index.column_number - 1, byte_index, } } diff --git a/tests/diff_specs/function_throws_change.txt b/tests/diff_specs/function_throws_change.txt index 5c64ab64c..32fed0513 100644 --- a/tests/diff_specs/function_throws_change.txt +++ b/tests/diff_specs/function_throws_change.txt @@ -32,10 +32,7 @@ export function foo(x: number): void {} "repr": "SyntaxError", "kind": "typeRef", "value": { - "typeName": "SyntaxError", - "resolution": { - "kind": "typeParam" - } + "typeName": "SyntaxError" } }, "doc": "bad syntax" @@ -48,10 +45,7 @@ export function foo(x: number): void {} "repr": "TypeError", "kind": "typeRef", "value": { - "typeName": "TypeError", - "resolution": { - "kind": "typeParam" - } + "typeName": "TypeError" } }, "doc": "wrong type" @@ -65,10 +59,7 @@ export function foo(x: number): void {} "repr": "RangeError", "kind": "typeRef", "value": { - "typeName": "RangeError", - "resolution": { - "kind": "typeParam" - } + "typeName": "RangeError" } }, "doc": "value out of range" @@ -79,10 +70,7 @@ export function foo(x: number): void {} "repr": "RangeError", "kind": "typeRef", "value": { - "typeName": "RangeError", - "resolution": { - "kind": "typeParam" - } + "typeName": "RangeError" } }, "doc": "updated message" diff --git a/tests/snapshots/html_test__html_doc_files_multiple-40.snap b/tests/snapshots/html_test__html_doc_files_multiple-40.snap index 2bebe8505..c33c1d6dc 100644 --- a/tests/snapshots/html_test__html_doc_files_multiple-40.snap +++ b/tests/snapshots/html_test__html_doc_files_multiple-40.snap @@ -145,7 +145,7 @@ expression: files.get(file_name).unwrap() -Hello.computedMethod(a: T extends () => infer R ? R : any): void +Hello.computedMethod(a: T extends () => infer R ? R : any): void

-a: T extends () => infer R ? R : any +a: T extends () => infer R ? R : any
diff --git a/tests/snapshots/html_test__symbol_group.snap b/tests/snapshots/html_test__symbol_group.snap index 0bdc976c7..579599ae6 100644 --- a/tests/snapshots/html_test__symbol_group.snap +++ b/tests/snapshots/html_test__symbol_group.snap @@ -8555,7 +8555,7 @@ expression: files "id": "function_hello_computedmethod_0" }, "name": "Hello.computedMethod", - "summary": "(a: T extends () => infer R ? R : any): void", + "summary": "(a: T extends () => infer R ? R : any): void", "deprecated": null, "content": { "id": "", @@ -8577,7 +8577,7 @@ expression: files "name_prefix": null, "name": "a", "name_href": null, - "content": ": T extends () => infer R ? R : any", + "content": ": T extends () => infer R ? R : any", "anchor": { "id": "function_hello_computedmethod_0_parameter_a" }, diff --git a/tests/specs/export_const_destructured.txt b/tests/specs/export_const_destructured.txt index efc35b30f..bec7d8f63 100644 --- a/tests/specs/export_const_destructured.txt +++ b/tests/specs/export_const_destructured.txt @@ -45,103 +45,115 @@ error[missing-explicit-type]: exported symbol is missing an explicit type annota | ^ # output.txt -Defined in file:///mod.ts:6:3 +Defined in file:///mod.ts:5:3 const a: string export a doc -Defined in file:///mod.ts:8:3 +Defined in file:///mod.ts:7:3 const b: number export b doc -Defined in file:///mod.ts:16:16 +Defined in file:///mod.ts:15:16 const f -Defined in file:///mod.ts:16:22 +Defined in file:///mod.ts:15:22 const h # output.json -[ - { - "name": "a", - "isDefault": false, - "location": { - "filename": "file:///mod.ts", - "line": 6, - "col": 2, - "byteIndex": 123 +{ + "symbols": [ + { + "name": "a", + "declarations": [ + { + "location": { + "filename": "file:///mod.ts", + "line": 5, + "col": 2, + "byteIndex": 123 + }, + "declarationKind": "export", + "jsDoc": { + "doc": "export a doc" + }, + "kind": "variable", + "def": { + "tsType": { + "repr": "string", + "kind": "keyword", + "value": "string" + }, + "kind": "const" + } + } + ] }, - "declarationKind": "export", - "jsDoc": { - "doc": "export a doc" + { + "name": "b", + "declarations": [ + { + "location": { + "filename": "file:///mod.ts", + "line": 7, + "col": 2, + "byteIndex": 150 + }, + "declarationKind": "export", + "jsDoc": { + "doc": "export b doc" + }, + "kind": "variable", + "def": { + "tsType": { + "repr": "number", + "kind": "keyword", + "value": "number" + }, + "kind": "const" + } + } + ] }, - "kind": "variable", - "variableDef": { - "tsType": { - "repr": "string", - "kind": "keyword", - "keyword": "string" - }, - "kind": "const" - } - }, - { - "name": "b", - "isDefault": false, - "location": { - "filename": "file:///mod.ts", - "line": 8, - "col": 2, - "byteIndex": 150 - }, - "declarationKind": "export", - "jsDoc": { - "doc": "export b doc" - }, - "kind": "variable", - "variableDef": { - "tsType": { - "repr": "number", - "kind": "keyword", - "keyword": "number" - }, - "kind": "const" - } - }, - { - "name": "f", - "isDefault": false, - "location": { - "filename": "file:///mod.ts", - "line": 16, - "col": 15, - "byteIndex": 250 - }, - "declarationKind": "export", - "kind": "variable", - "variableDef": { - "tsType": null, - "kind": "const" - } - }, - { - "name": "h", - "isDefault": false, - "location": { - "filename": "file:///mod.ts", - "line": 16, - "col": 21, - "byteIndex": 256 + { + "name": "f", + "declarations": [ + { + "location": { + "filename": "file:///mod.ts", + "line": 15, + "col": 15, + "byteIndex": 250 + }, + "declarationKind": "export", + "kind": "variable", + "def": { + "kind": "const" + } + } + ] }, - "declarationKind": "export", - "kind": "variable", - "variableDef": { - "tsType": null, - "kind": "const" + { + "name": "h", + "declarations": [ + { + "location": { + "filename": "file:///mod.ts", + "line": 15, + "col": 21, + "byteIndex": 256 + }, + "declarationKind": "export", + "kind": "variable", + "def": { + "kind": "const" + } + } + ] } - } -] + ] +} diff --git a/tests/specs/export_namespace.txt b/tests/specs/export_namespace.txt index adf2d9c0a..f3c3fd31d 100644 --- a/tests/specs/export_namespace.txt +++ b/tests/specs/export_namespace.txt @@ -46,7 +46,7 @@ error[missing-jsdoc]: exported symbol is missing JSDoc documentation | ^ # output.txt -Defined in file:///mod.ts:2:1 +Defined in file:///mod.ts:1:1 namespace RootNs Namespace JSdoc @@ -58,172 +58,182 @@ namespace RootNs # output.json -[ - { - "name": "RootNs", - "isDefault": false, - "location": { - "filename": "file:///mod.ts", - "line": 2, - "col": 0, - "byteIndex": 23 - }, - "declarationKind": "export", - "jsDoc": { - "doc": "Namespace JSdoc" - }, - "kind": "namespace", - "namespaceDef": { - "elements": [ +{ + "symbols": [ + { + "name": "RootNs", + "declarations": [ { - "name": "a", - "isDefault": false, "location": { "filename": "file:///mod.ts", - "line": 3, - "col": 17, - "byteIndex": 66 - }, - "declarationKind": "export", - "kind": "variable", - "variableDef": { - "tsType": { - "repr": "a", - "kind": "literal", - "literal": { - "kind": "string", - "string": "a" - } - }, - "kind": "const" - } - }, - { - "name": "NestedNs", - "isDefault": false, - "location": { - "filename": "file:///mod.ts", - "line": 6, - "col": 4, - "byteIndex": 114 + "line": 1, + "col": 0, + "byteIndex": 23 }, "declarationKind": "export", "jsDoc": { - "doc": "Nested namespace JSDoc" + "doc": "Namespace JSdoc" }, "kind": "namespace", - "namespaceDef": { + "def": { "elements": [ { - "name": "Foo", - "isDefault": false, - "location": { - "filename": "file:///mod.ts", - "line": 7, - "col": 6, - "byteIndex": 148 - }, - "declarationKind": "export", - "kind": "enum", - "enumDef": { - "members": [ - { - "name": "a", - "init": { - "repr": "1", - "kind": "literal", - "literal": { - "kind": "number", - "number": 1.0 - } - }, - "location": { - "filename": "file:///mod.ts", - "line": 8, - "col": 8, - "byteIndex": 174 - } + "name": "a", + "declarations": [ + { + "location": { + "filename": "file:///mod.ts", + "line": 2, + "col": 17, + "byteIndex": 66 }, - { - "name": "b", - "init": { - "repr": "2", + "declarationKind": "export", + "kind": "variable", + "def": { + "tsType": { + "repr": "a", "kind": "literal", - "literal": { - "kind": "number", - "number": 2.0 + "value": { + "kind": "string", + "string": "a" } }, - "location": { - "filename": "file:///mod.ts", - "line": 9, - "col": 8, - "byteIndex": 189 - } + "kind": "const" + } + } + ] + }, + { + "name": "NestedNs", + "declarations": [ + { + "location": { + "filename": "file:///mod.ts", + "line": 5, + "col": 4, + "byteIndex": 114 }, - { - "name": "c", - "init": { - "repr": "3", - "kind": "literal", - "literal": { - "kind": "number", - "number": 3.0 + "declarationKind": "export", + "jsDoc": { + "doc": "Nested namespace JSDoc" + }, + "kind": "namespace", + "def": { + "elements": [ + { + "name": "Foo", + "declarations": [ + { + "location": { + "filename": "file:///mod.ts", + "line": 6, + "col": 6, + "byteIndex": 148 + }, + "declarationKind": "export", + "kind": "enum", + "def": { + "members": [ + { + "name": "a", + "init": { + "repr": "1", + "kind": "literal", + "value": { + "kind": "number", + "number": 1.0 + } + }, + "location": { + "filename": "file:///mod.ts", + "line": 7, + "col": 8, + "byteIndex": 174 + } + }, + { + "name": "b", + "init": { + "repr": "2", + "kind": "literal", + "value": { + "kind": "number", + "number": 2.0 + } + }, + "location": { + "filename": "file:///mod.ts", + "line": 8, + "col": 8, + "byteIndex": 189 + } + }, + { + "name": "c", + "init": { + "repr": "3", + "kind": "literal", + "value": { + "kind": "number", + "number": 3.0 + } + }, + "location": { + "filename": "file:///mod.ts", + "line": 9, + "col": 8, + "byteIndex": 204 + } + } + ] + } + } + ] } - }, - "location": { - "filename": "file:///mod.ts", - "line": 10, - "col": 8, - "byteIndex": 204 - } + ] } - ] - } - } - ] - } - }, - { - "name": "OtherNs", - "isDefault": false, - "location": { - "filename": "file:///mod.ts", - "line": 15, - "col": 24, - "byteIndex": 252 - }, - "declarationKind": "export", - "kind": "namespace", - "namespaceDef": { - "elements": [ + } + ] + }, { - "name": "Other", - "isDefault": false, - "location": { - "filename": "file:///mod.ts", - "line": 16, - "col": 2, - "byteIndex": 264 - }, - "declarationKind": "export", - "kind": "class", - "classDef": { - "isAbstract": false, - "constructors": [], - "properties": [], - "indexSignatures": [], - "methods": [], - "extends": null, - "implements": [], - "typeParams": [], - "superTypeParams": [] - } + "name": "OtherNs", + "declarations": [ + { + "location": { + "filename": "file:///mod.ts", + "line": 14, + "col": 24, + "byteIndex": 252 + }, + "declarationKind": "export", + "kind": "namespace", + "def": { + "elements": [ + { + "name": "Other", + "declarations": [ + { + "location": { + "filename": "file:///mod.ts", + "line": 15, + "col": 2, + "byteIndex": 264 + }, + "declarationKind": "export", + "kind": "class", + "def": {} + } + ] + } + ] + } + } + ] } ] } } ] } - } -] + ] +} diff --git a/tests/specs/indented_with_tabs.txt b/tests/specs/indented_with_tabs.txt index 10bb32d4b..16086fcaa 100644 --- a/tests/specs/indented_with_tabs.txt +++ b/tests/specs/indented_with_tabs.txt @@ -70,7 +70,7 @@ namespace Tabs "location": { "filename": "file:///mod.ts", "line": 15, - "col": 2, + "col": 1, "byteIndex": 126 }, "declarationKind": "export", @@ -88,7 +88,7 @@ namespace Tabs "location": { "filename": "file:///mod.ts", "line": 23, - "col": 4, + "col": 2, "byteIndex": 212 }, "tsType": { diff --git a/tests/specs/infer_object_literal.txt b/tests/specs/infer_object_literal.txt index e3401680d..b466ae4f3 100644 --- a/tests/specs/infer_object_literal.txt +++ b/tests/specs/infer_object_literal.txt @@ -27,308 +27,268 @@ error[missing-jsdoc]: exported symbol is missing JSDoc documentation | ^ # output.txt -Defined in file:///mod.ts:4:14 +Defined in file:///mod.ts:3:14 const a: { d(e: string): void; h(): string; h(value: string); [t](u: string): void; a: string; b: Map; c: { d: string; }; f: (g: string) => void; [s]: (number | string)[]; } # output.json -[ - { - "name": "a", - "isDefault": false, - "location": { - "filename": "file:///mod.ts", - "line": 4, - "col": 13, - "byteIndex": 84 - }, - "declarationKind": "export", - "kind": "variable", - "variableDef": { - "tsType": { - "repr": "", - "kind": "typeLiteral", - "typeLiteral": { - "constructors": [], - "methods": [ - { - "name": "d", - "kind": "method", - "location": { - "filename": "file:///mod.ts", - "line": 9, - "col": 2, - "byteIndex": 166 - }, - "params": [ - { - "kind": "identifier", - "name": "e", - "optional": false, - "tsType": { - "repr": "string", - "kind": "keyword", - "keyword": "string" - } - } - ], - "optional": false, - "returnType": { - "repr": "void", - "kind": "keyword", - "keyword": "void" - }, - "typeParams": [] - }, - { - "name": "h", - "kind": "getter", - "location": { - "filename": "file:///mod.ts", - "line": 11, - "col": 2, - "byteIndex": 221 - }, - "params": [], - "optional": false, - "returnType": { - "repr": "string", - "kind": "keyword", - "keyword": "string" - }, - "typeParams": [] - }, - { - "name": "h", - "kind": "setter", - "location": { - "filename": "file:///mod.ts", - "line": 14, - "col": 2, - "byteIndex": 262 - }, - "params": [ - { - "kind": "identifier", - "name": "value", - "optional": false, - "tsType": { - "repr": "string", - "kind": "keyword", - "keyword": "string" - } - } - ], - "optional": false, - "returnType": null, - "typeParams": [] - }, - { - "name": "t", - "kind": "method", - "location": { - "filename": "file:///mod.ts", - "line": 18, - "col": 2, - "byteIndex": 316 - }, - "params": [ - { - "kind": "identifier", - "name": "u", - "optional": false, - "tsType": { - "repr": "string", - "kind": "keyword", - "keyword": "string" - } - } - ], - "computed": true, - "optional": false, - "returnType": { - "repr": "void", - "kind": "keyword", - "keyword": "void" - }, - "typeParams": [] - } - ], - "properties": [ - { - "name": "a", - "jsDoc": { - "doc": "JSDoc" - }, - "location": { - "filename": "file:///mod.ts", - "line": 6, - "col": 2, - "byteIndex": 107 - }, - "params": [], - "computed": false, - "optional": false, - "tsType": { - "repr": "string", - "kind": "keyword", - "keyword": "string" - }, - "typeParams": [] - }, - { - "name": "b", - "location": { - "filename": "file:///mod.ts", - "line": 7, - "col": 2, - "byteIndex": 117 - }, - "params": [], - "computed": false, - "optional": false, - "tsType": { - "repr": "Map", - "kind": "typeRef", - "typeRef": { - "typeParams": [ - { - "repr": "string", - "kind": "keyword", - "keyword": "string" +{ + "symbols": [ + { + "name": "a", + "declarations": [ + { + "location": { + "filename": "file:///mod.ts", + "line": 3, + "col": 13, + "byteIndex": 84 + }, + "declarationKind": "export", + "kind": "variable", + "def": { + "tsType": { + "kind": "typeLiteral", + "value": { + "methods": [ + { + "name": "d", + "kind": "method", + "location": { + "filename": "file:///mod.ts", + "line": 8, + "col": 2, + "byteIndex": 166 }, - { - "repr": "number", + "params": [ + { + "kind": "identifier", + "name": "e", + "optional": false, + "tsType": { + "repr": "string", + "kind": "keyword", + "value": "string" + } + } + ], + "returnType": { + "repr": "void", "kind": "keyword", - "keyword": "number" + "value": "void" } - ], - "typeName": "Map" - } - }, - "typeParams": [] - }, - { - "name": "c", - "location": { - "filename": "file:///mod.ts", - "line": 8, - "col": 2, - "byteIndex": 149 - }, - "params": [], - "computed": false, - "optional": false, - "tsType": { - "repr": "", - "kind": "typeLiteral", - "typeLiteral": { - "constructors": [], - "methods": [], - "properties": [ - { - "name": "d", - "location": { - "filename": "file:///mod.ts", - "line": 8, - "col": 7, - "byteIndex": 154 - }, - "params": [], - "computed": false, - "optional": false, - "tsType": { - "repr": "string", - "kind": "keyword", - "keyword": "string" - }, - "typeParams": [] + }, + { + "name": "h", + "kind": "getter", + "location": { + "filename": "file:///mod.ts", + "line": 10, + "col": 2, + "byteIndex": 221 + }, + "params": [], + "returnType": { + "repr": "string", + "kind": "keyword", + "value": "string" } - ], - "callSignatures": [], - "indexSignatures": [] - } - }, - "typeParams": [] - }, - { - "name": "f", - "location": { - "filename": "file:///mod.ts", - "line": 10, - "col": 2, - "byteIndex": 191 - }, - "params": [], - "computed": false, - "optional": false, - "tsType": { - "repr": "", - "kind": "fnOrConstructor", - "fnOrConstructor": { - "constructor": false, - "tsType": { - "repr": "void", - "kind": "keyword", - "keyword": "void" }, - "params": [ - { - "kind": "identifier", - "name": "g", - "optional": false, - "tsType": { - "repr": "string", - "kind": "keyword", - "keyword": "string" + { + "name": "h", + "kind": "setter", + "location": { + "filename": "file:///mod.ts", + "line": 13, + "col": 2, + "byteIndex": 262 + }, + "params": [ + { + "kind": "identifier", + "name": "value", + "optional": false, + "tsType": { + "repr": "string", + "kind": "keyword", + "value": "string" + } } - } - ], - "typeParams": [] - } - }, - "typeParams": [] - }, - { - "name": "s", - "location": { - "filename": "file:///mod.ts", - "line": 17, - "col": 2, - "byteIndex": 293 - }, - "params": [], - "computed": true, - "optional": false, - "tsType": { - "repr": "", - "kind": "array", - "array": { - "repr": "", - "kind": "union", - "union": [ - { - "repr": "number", + ] + }, + { + "name": "t", + "kind": "method", + "location": { + "filename": "file:///mod.ts", + "line": 17, + "col": 2, + "byteIndex": 316 + }, + "params": [ + { + "kind": "identifier", + "name": "u", + "optional": false, + "tsType": { + "repr": "string", + "kind": "keyword", + "value": "string" + } + } + ], + "computed": true, + "returnType": { + "repr": "void", "kind": "keyword", - "keyword": "number" + "value": "void" + } + } + ], + "properties": [ + { + "name": "a", + "jsDoc": { + "doc": "JSDoc" + }, + "location": { + "filename": "file:///mod.ts", + "line": 5, + "col": 2, + "byteIndex": 107 }, - { + "tsType": { "repr": "string", "kind": "keyword", - "keyword": "string" + "value": "string" + } + }, + { + "name": "b", + "location": { + "filename": "file:///mod.ts", + "line": 6, + "col": 2, + "byteIndex": 117 + }, + "tsType": { + "repr": "Map", + "kind": "typeRef", + "value": { + "typeParams": [ + { + "repr": "string", + "kind": "keyword", + "value": "string" + }, + { + "repr": "number", + "kind": "keyword", + "value": "number" + } + ], + "typeName": "Map" + } + } + }, + { + "name": "c", + "location": { + "filename": "file:///mod.ts", + "line": 7, + "col": 2, + "byteIndex": 149 + }, + "tsType": { + "kind": "typeLiteral", + "value": { + "properties": [ + { + "name": "d", + "location": { + "filename": "file:///mod.ts", + "line": 7, + "col": 7, + "byteIndex": 154 + }, + "tsType": { + "repr": "string", + "kind": "keyword", + "value": "string" + } + } + ] + } } - ] - } - }, - "typeParams": [] - } - ], - "callSignatures": [], - "indexSignatures": [] + }, + { + "name": "f", + "location": { + "filename": "file:///mod.ts", + "line": 9, + "col": 2, + "byteIndex": 191 + }, + "tsType": { + "kind": "fnOrConstructor", + "value": { + "constructor": false, + "tsType": { + "repr": "void", + "kind": "keyword", + "value": "void" + }, + "params": [ + { + "kind": "identifier", + "name": "g", + "optional": false, + "tsType": { + "repr": "string", + "kind": "keyword", + "value": "string" + } + } + ] + } + } + }, + { + "name": "s", + "location": { + "filename": "file:///mod.ts", + "line": 16, + "col": 2, + "byteIndex": 293 + }, + "computed": true, + "tsType": { + "kind": "array", + "value": { + "kind": "union", + "value": [ + { + "repr": "number", + "kind": "keyword", + "value": "number" + }, + { + "repr": "string", + "kind": "keyword", + "value": "string" + } + ] + } + } + } + ] + } + }, + "kind": "const" + } } - }, - "kind": "const" + ] } - } -] + ] +} diff --git a/tests/specs/jsdoc_types.txt b/tests/specs/jsdoc_types.txt index 0ec1ec4b7..fb2cf08b3 100644 --- a/tests/specs/jsdoc_types.txt +++ b/tests/specs/jsdoc_types.txt @@ -205,17 +205,11 @@ class StringList "value": "number" } ], - "typeName": "Set", - "resolution": { - "kind": "typeParam" - } + "typeName": "Set" } } ], - "typeName": "Map", - "resolution": { - "kind": "typeParam" - } + "typeName": "Map" } }, "doc": "the lookup map" @@ -320,10 +314,7 @@ class StringList "value": "unknown" } ], - "typeName": "Record", - "resolution": { - "kind": "typeParam" - } + "typeName": "Record" } }, "doc": "an object" @@ -346,17 +337,11 @@ class StringList "value": "string" } ], - "typeName": "Array", - "resolution": { - "kind": "typeParam" - } + "typeName": "Array" } } ], - "typeName": "Promise", - "resolution": { - "kind": "typeParam" - } + "typeName": "Promise" } }, "doc": "the results" @@ -367,10 +352,7 @@ class StringList "repr": "RangeError", "kind": "typeRef", "value": { - "typeName": "RangeError", - "resolution": { - "kind": "typeParam" - } + "typeName": "RangeError" } }, "doc": "if out of range" @@ -381,10 +363,7 @@ class StringList "repr": "TypeError", "kind": "typeRef", "value": { - "typeName": "TypeError", - "resolution": { - "kind": "typeParam" - } + "typeName": "TypeError" } }, "doc": "if wrong type" @@ -584,10 +563,7 @@ class StringList "value": "string" } ], - "typeName": "ReadonlyArray", - "resolution": { - "kind": "typeParam" - } + "typeName": "ReadonlyArray" } } } @@ -663,10 +639,7 @@ class StringList "repr": "HTMLElement", "kind": "typeRef", "value": { - "typeName": "HTMLElement", - "resolution": { - "kind": "typeParam" - } + "typeName": "HTMLElement" } } } @@ -711,10 +684,7 @@ class StringList "value": "string" } ], - "typeName": "Array", - "resolution": { - "kind": "typeParam" - } + "typeName": "Array" } } } diff --git a/tests/specs/mapped_types.txt b/tests/specs/mapped_types.txt index 654b3476b..66a665ad4 100644 --- a/tests/specs/mapped_types.txt +++ b/tests/specs/mapped_types.txt @@ -84,10 +84,7 @@ type MappedTypeWithNewProperties = readonly [Properties in keyof Type as N "repr": "Properties", "kind": "typeRef", "value": { - "typeName": "Properties", - "resolution": { - "kind": "typeParam" - } + "typeName": "Properties" } } } diff --git a/tests/specs/namespace_exports_self.txt b/tests/specs/namespace_exports_self.txt index 8a7c08c58..22cc40e03 100644 --- a/tests/specs/namespace_exports_self.txt +++ b/tests/specs/namespace_exports_self.txt @@ -41,7 +41,7 @@ Defined in file:///mod.ts:1:1 namespace a Description. - private const a: string + const a: string Description. Defined in file:///mod.ts:8:1 @@ -88,7 +88,7 @@ namespace f "col": 0, "byteIndex": 20 }, - "declarationKind": "private", + "declarationKind": "export", "jsDoc": { "doc": "Description." }, diff --git a/tests/specs/private_type_class_property.txt b/tests/specs/private_type_class_property.txt index 9d894825c..4717af2d5 100644 --- a/tests/specs/private_type_class_property.txt +++ b/tests/specs/private_type_class_property.txt @@ -51,51 +51,58 @@ error[missing-jsdoc]: exported symbol is missing JSDoc documentation | ^ # output.txt -Defined in file:///mod.ts:1:1 +Defined in file:///mod.ts:0:1 type PrivatePropThroughNamespaceRef = typeof MyNamespace.Export.someProp -Defined in file:///mod.ts:3:1 +Defined in file:///mod.ts:2:1 private namespace MyNamespace # output.json -[ - { - "name": "PrivatePropThroughNamespaceRef", - "isDefault": false, - "location": { - "filename": "file:///mod.ts", - "line": 1, - "col": 0, - "byteIndex": 0 +{ + "symbols": [ + { + "name": "PrivatePropThroughNamespaceRef", + "declarations": [ + { + "location": { + "filename": "file:///mod.ts", + "line": 0, + "col": 0, + "byteIndex": 0 + }, + "declarationKind": "export", + "kind": "typeAlias", + "def": { + "tsType": { + "repr": "MyNamespace.Export.someProp", + "kind": "typeQuery", + "value": "MyNamespace.Export.someProp" + } + } + } + ] }, - "declarationKind": "export", - "kind": "typeAlias", - "typeAliasDef": { - "tsType": { - "repr": "MyNamespace.Export.someProp", - "kind": "typeQuery", - "typeQuery": "MyNamespace.Export.someProp" - }, - "typeParams": [] + { + "name": "MyNamespace", + "declarations": [ + { + "location": { + "filename": "file:///mod.ts", + "line": 2, + "col": 0, + "byteIndex": 82 + }, + "declarationKind": "private", + "kind": "namespace", + "def": { + "elements": [] + } + } + ] } - }, - { - "name": "MyNamespace", - "isDefault": false, - "location": { - "filename": "file:///mod.ts", - "line": 3, - "col": 0, - "byteIndex": 82 - }, - "declarationKind": "private", - "kind": "namespace", - "namespaceDef": { - "elements": [] - } - } -] + ] +} diff --git a/tests/specs/re_export_all_as_with_jsdoc.txt b/tests/specs/re_export_all_as_with_jsdoc.txt index 99d8a3573..9ba35bac1 100644 --- a/tests/specs/re_export_all_as_with_jsdoc.txt +++ b/tests/specs/re_export_all_as_with_jsdoc.txt @@ -7,7 +7,7 @@ export function foo(): void {} export * as other from "./other.ts"; # output.txt -Defined in file:///mod.ts:2:1 +Defined in file:///mod.ts:1:1 namespace other Re-exports of other. @@ -17,51 +17,56 @@ namespace other # output.json -[ - { - "name": "other", - "isDefault": false, - "location": { - "filename": "file:///mod.ts", - "line": 2, - "col": 0, - "byteIndex": 28 - }, - "declarationKind": "export", - "jsDoc": { - "doc": "Re-exports of other." - }, - "kind": "namespace", - "namespaceDef": { - "elements": [ +{ + "symbols": [ + { + "name": "other", + "declarations": [ { - "name": "foo", - "isDefault": false, "location": { - "filename": "file:///other.ts", - "line": 2, + "filename": "file:///mod.ts", + "line": 1, "col": 0, - "byteIndex": 18 + "byteIndex": 28 }, "declarationKind": "export", "jsDoc": { - "doc": "a function" + "doc": "Re-exports of other." }, - "kind": "function", - "functionDef": { - "params": [], - "returnType": { - "repr": "void", - "kind": "keyword", - "keyword": "void" - }, - "hasBody": true, - "isAsync": false, - "isGenerator": false, - "typeParams": [] + "kind": "namespace", + "def": { + "elements": [ + { + "name": "foo", + "declarations": [ + { + "location": { + "filename": "file:///other.ts", + "line": 1, + "col": 0, + "byteIndex": 18 + }, + "declarationKind": "export", + "jsDoc": { + "doc": "a function" + }, + "kind": "function", + "def": { + "params": [], + "returnType": { + "repr": "void", + "kind": "keyword", + "value": "void" + }, + "hasBody": true + } + } + ] + } + ] } } ] } - } -] + ] +} diff --git a/tests/specs/structured_jsdoc.txt b/tests/specs/structured_jsdoc.txt index 04f08fa7d..ab7469908 100644 --- a/tests/specs/structured_jsdoc.txt +++ b/tests/specs/structured_jsdoc.txt @@ -184,10 +184,7 @@ class A "value": "void" } ], - "typeName": "Promise", - "resolution": { - "kind": "typeParam" - } + "typeName": "Promise" } } } diff --git a/tests/specs/type_literal_mapped_type.txt b/tests/specs/type_literal_mapped_type.txt index 9fc6d5609..9a6ddd2d8 100644 --- a/tests/specs/type_literal_mapped_type.txt +++ b/tests/specs/type_literal_mapped_type.txt @@ -81,10 +81,7 @@ type T = readonly [P in keyof Type as NewType]: Type[P] "repr": "P", "kind": "typeRef", "value": { - "typeName": "P", - "resolution": { - "kind": "typeParam" - } + "typeName": "P" } } } From 6ff6fa1b3fedaf0c5a2dc260529e8e72ee37da0e Mon Sep 17 00:00:00 2001 From: Nathan Whitaker Date: Tue, 2 Jun 2026 13:54:45 -0700 Subject: [PATCH 4/9] use git deno_graph --- Cargo.lock | 4 ++- Cargo.toml | 5 +--- examples/ddoc/main.rs | 4 +-- src/html/mod.rs | 4 +-- src/parser.rs | 67 +++++++++++++++++++++---------------------- 5 files changed, 41 insertions(+), 43 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index bbe45084b..a28ea8f17 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -618,6 +618,7 @@ checksum = "be1e0bca6c3637f992fc1cc7cbc52a78c1ef6db076dbf1059c4323d6a2048376" [[package]] name = "deno_ast" version = "0.53.2" +source = "git+https://github.com/nathanwhit/deno_ast?branch=oxc-port#adc326fa89885400fc7d7baeb007b833138f5aff" dependencies = [ "base64", "capacity_builder", @@ -717,6 +718,7 @@ dependencies = [ [[package]] name = "deno_graph" version = "0.108.2" +source = "git+https://github.com/nathanwhit/deno_graph?branch=oxc-port#7f786030d26b7aca8937c362436d56e1145168d8" dependencies = [ "async-trait", "boxed_error", @@ -2879,7 +2881,7 @@ version = "0.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0978bf7171b3d90bac376700cb56d606feb40f251a475a5d6634613564460b22" dependencies = [ - "windows-sys 0.59.0", + "windows-sys 0.60.2", ] [[package]] diff --git a/Cargo.toml b/Cargo.toml index cfbddcc50..ce97fd0cb 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -11,7 +11,7 @@ repository = "https://github.com/denoland/deno_doc" members = ["lib"] [workspace.dependencies] -deno_graph = { path = "../deno_graph", default-features = false, features = [ +deno_graph = { git = "https://github.com/nathanwhit/deno_graph", branch = "oxc-port", default-features = false, features = [ "swc", "symbols", ] } @@ -20,9 +20,6 @@ import_map = "0.25.0" serde = { version = "1.0.204", features = ["derive"] } serde_json = { version = "1.0.122", features = ["preserve_order"] } -[patch."https://github.com/nathanwhit/deno_ast"] -deno_ast = { path = "../deno_ast" } - [lib] name = "deno_doc" diff --git a/examples/ddoc/main.rs b/examples/ddoc/main.rs index 06ac4aafd..e051ff97c 100644 --- a/examples/ddoc/main.rs +++ b/examples/ddoc/main.rs @@ -259,13 +259,13 @@ async fn run() -> anyhow::Result<()> { // This allows comparing renamed modules. let old_by_original = old_specifiers .iter() - .zip(old_docs.into_iter()) + .zip(old_docs) .map(|(orig, (_, nodes))| (orig.clone(), nodes)) .collect::>(); let new_by_original = new_specifiers .iter() - .zip(new_docs.into_iter()) + .zip(new_docs) .map(|(orig, (_, nodes))| (orig.clone(), nodes)) .collect::>(); diff --git a/src/html/mod.rs b/src/html/mod.rs index c23f47c48..fc1f72b39 100644 --- a/src/html/mod.rs +++ b/src/html/mod.rs @@ -10,6 +10,7 @@ use serde::Serialize; use std::borrow::Cow; use std::cmp::Ordering; use std::collections::HashMap; +use std::path::Path; use std::path::PathBuf; use std::sync::Arc; @@ -1766,8 +1767,7 @@ pub fn find_common_ancestor<'a>( } } - if common_ancestor.as_os_str().is_empty() - || common_ancestor == PathBuf::from("/") + if common_ancestor.as_os_str().is_empty() || common_ancestor == Path::new("/") { None } else { diff --git a/src/parser.rs b/src/parser.rs index c32f1240b..0694ae819 100644 --- a/src/parser.rs +++ b/src/parser.rs @@ -565,41 +565,40 @@ impl<'a> DocParser<'a> { for stmt in module_info.statements() { if let Statement::ImportDeclaration(import_decl) = stmt && let Some(js_doc) = js_doc_for_range(module_info, import_decl.span) + && let Some(specifiers) = &import_decl.specifiers { - if let Some(specifiers) = &import_decl.specifiers { - for specifier in specifiers { - let (imported_name, original_name, src) = match specifier { - ImportDeclarationSpecifier::ImportSpecifier(named_specifier) => ( - named_specifier.local.name.to_string(), - Some(module_export_name_value(&named_specifier.imported)), - &import_decl.source.value, - ), - ImportDeclarationSpecifier::ImportDefaultSpecifier( - default_specifier, - ) => ( - default_specifier.local.name.to_string(), - Some("default".to_string()), - &import_decl.source.value, - ), - ImportDeclarationSpecifier::ImportNamespaceSpecifier( - namespace_specifier, - ) => ( - namespace_specifier.local.name.to_string(), - None, - &import_decl.source.value, - ), - }; - - let resolved_specifier = - self.resolve_dependency(&src.to_string(), referrer)?; - - imports.push(Import { - imported_name: imported_name.into_boxed_str(), - js_doc: js_doc.clone(), - src: resolved_specifier.to_string(), - original_name, - }); - } + for specifier in specifiers { + let (imported_name, original_name, src) = match specifier { + ImportDeclarationSpecifier::ImportSpecifier(named_specifier) => ( + named_specifier.local.name.to_string(), + Some(module_export_name_value(&named_specifier.imported)), + &import_decl.source.value, + ), + ImportDeclarationSpecifier::ImportDefaultSpecifier( + default_specifier, + ) => ( + default_specifier.local.name.to_string(), + Some("default".to_string()), + &import_decl.source.value, + ), + ImportDeclarationSpecifier::ImportNamespaceSpecifier( + namespace_specifier, + ) => ( + namespace_specifier.local.name.to_string(), + None, + &import_decl.source.value, + ), + }; + + let resolved_specifier = + self.resolve_dependency(src.as_ref(), referrer)?; + + imports.push(Import { + imported_name: imported_name.into_boxed_str(), + js_doc: js_doc.clone(), + src: resolved_specifier.to_string(), + original_name, + }); } } } From d3d45335ca81f0a1ac4493f753e1f64fb2844765 Mon Sep 17 00:00:00 2001 From: Leo Kettmeir Date: Mon, 26 Oct 2026 01:20:26 +0900 Subject: [PATCH 5/9] chore: update to deno_ast/deno_graph oxc-port with oxc 0.155 Ports the swc-based changes from main onto the oxc code: heritage member docs (#842), variable alias resolution (#850), shadowed export merging (#838), spread element inference (#852), void return inference for arrow functions (#825), deno-doc-ignore directives (#829), identifier diagnostic locations (#831), pure type alias re-exports (#816). Adapts to oxc 0.155 (ExportNamedDeclaration / TSModuleDeclaration splits, Class heritage, TSIndexSignature parameter, JSStr string values) and Rust 1.97. Spec expectation changes: object literal computed keys render as `[t]` rather than `[[t]]`; `export * as ns` symbols are located at the statement start; a private const spread into an exported `as const` array is reported as a private-type-ref (deno_graph now tracks value deps of `as const` expressions); an `infer R` binding no longer links to an unrelated type parameter. --- Cargo.lock | 774 ++++++++---------- Cargo.toml | 8 +- rust-toolchain.toml | 2 +- src/class.rs | 15 +- src/diff/class.rs | 2 +- src/diff/interface.rs | 2 +- src/display.rs | 1 - src/enum.rs | 3 +- src/html/comrak.rs | 5 +- src/html/mod.rs | 4 +- src/html/symbols/interface.rs | 2 +- src/html/symbols/namespace.rs | 4 +- src/html/types.rs | 2 +- src/interface.rs | 12 +- src/params.rs | 3 +- src/parser.rs | 96 +-- src/ts_type.rs | 66 +- src/util/swc.rs | 3 +- src/visibility.rs | 29 + tests/html_test.rs | 4 + ...html_test__html_doc_files_multiple-39.snap | 4 +- tests/specs/infer_const_assertion_spread.txt | 60 ++ tests/specs/infer_object_literal.txt | 6 +- .../reexport_namespace_keeps_location.txt | 6 +- tests/specs/reexport_nested_namespace.txt | 10 +- 25 files changed, 546 insertions(+), 577 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 31dfd4a37..559d00fbb 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -26,6 +26,15 @@ dependencies = [ "memchr", ] +[[package]] +name = "alloca" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e5a7d05ea6aea7e9e64d25b9156ba2fee3fdd659e34e41063cd2fc7cd020d7f4" +dependencies = [ + "cc", +] + [[package]] name = "allocator-api2" version = "0.2.21" @@ -90,9 +99,9 @@ dependencies = [ [[package]] name = "anyhow" -version = "1.0.99" +version = "1.0.104" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b0674a1ddeecb70197781e945de4b3b8ffb61fa939a5597bcf48503737663100" +checksum = "330a5ed07fa54e4702c9d6c4174f74427fc0ef6e214bbd677ae50a5099946470" [[package]] name = "arrayvec" @@ -108,18 +117,7 @@ checksum = "9035ad2d096bed7955a320ee7e2230574d28fd3c3a0f186cbea1ff3c7eed5dbb" dependencies = [ "proc-macro2", "quote", - "syn", -] - -[[package]] -name = "atty" -version = "0.2.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" -dependencies = [ - "hermit-abi", - "libc", - "winapi", + "syn 2.0.106", ] [[package]] @@ -137,7 +135,7 @@ dependencies = [ "addr2line", "cfg-if", "libc", - "miniz_oxide", + "miniz_oxide 0.8.9", "object", "rustc-demangle", "windows-targets 0.52.6", @@ -149,6 +147,12 @@ version = "0.22.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" +[[package]] +name = "base64" +version = "0.23.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac07cdecf99051d9a5238b80f35af32cdeba5b336e55d957b318b50137e18da5" + [[package]] name = "base64-simd" version = "0.8.0" @@ -161,15 +165,9 @@ dependencies = [ [[package]] name = "bitflags" -version = "1.3.2" +version = "2.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" - -[[package]] -name = "bitflags" -version = "2.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "843867be96c8daad0d758b57df9392b6d8d271134fce549de6ce169ff98a92af" +checksum = "3ded4057c258ba199e2d26386d3af3780957ecaee6c4ef4041c6b4b8b97c0b06" [[package]] name = "block-buffer" @@ -180,15 +178,6 @@ dependencies = [ "generic-array", ] -[[package]] -name = "block-buffer" -version = "0.12.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cdd35008169921d80bc60d3d0ab416eecb028c4cd653352907921d95084790be" -dependencies = [ - "hybrid-array", -] - [[package]] name = "boxed_error" version = "0.2.3" @@ -196,7 +185,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "17d4f95e880cfd28c4ca5a006cf7f6af52b4bcb7b5866f573b2faa126fb7affb" dependencies = [ "quote", - "syn", + "syn 2.0.106", ] [[package]] @@ -205,6 +194,12 @@ version = "3.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "46c5e41b57b8bba42a04676d81cb89e9ee8e859a1a66f80a5a72e1cb76b34d43" +[[package]] +name = "bytecount" +version = "0.6.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "175812e0be2bccb6abe50bb8d566126198344f707e304f45c648fd8f2cc0365e" + [[package]] name = "bytes" version = "1.10.1" @@ -230,7 +225,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3b4a6cae9efc04cc6cbb8faf338d2c497c165c83e74509cf4dbedea948bbf6e5" dependencies = [ "quote", - "syn", + "syn 2.0.106", ] [[package]] @@ -257,6 +252,16 @@ dependencies = [ "rustversion", ] +[[package]] +name = "cc" +version = "1.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "86e055fa6e3e40ad6187ba25b6855eeb635d5271f8e0f0e1e9a5826b8d75bea0" +dependencies = [ + "find-msvc-tools", + "shlex", +] + [[package]] name = "cfg-if" version = "1.0.3" @@ -300,18 +305,6 @@ dependencies = [ "half", ] -[[package]] -name = "clap" -version = "3.2.25" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ea181bf566f71cb9a5d17a59e1871af638180a18fb0035c92ae62b705207123" -dependencies = [ - "bitflags 1.3.2", - "clap_lex 0.2.4", - "indexmap 1.9.3", - "textwrap", -] - [[package]] name = "clap" version = "4.5.56" @@ -330,7 +323,7 @@ checksum = "793207c7fa6300a0608d1080b858e5fdbe713cdc1c8db9fb17777d8a13e63df0" dependencies = [ "anstream", "anstyle", - "clap_lex 0.7.7", + "clap_lex", "strsim", ] @@ -343,16 +336,7 @@ dependencies = [ "heck", "proc-macro2", "quote", - "syn", -] - -[[package]] -name = "clap_lex" -version = "0.2.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2850f2f5a82cbf437dd5af4d49848fbdfc27c157c3d010345776f952765261c5" -dependencies = [ - "os_str_bytes", + "syn 2.0.106", ] [[package]] @@ -378,33 +362,32 @@ checksum = "b05b61dc5112cbb17e4b6cd61790d9845d13888356391624cbe7e41efeac1e75" [[package]] name = "compact_str" -version = "0.9.0" +version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3fdb1325a1cece981e8a296ab8f0f9b63ae357bd0784a9faaf548cc7b480707a" +checksum = "79fcda08c33bb58b97008b2cdada6622500e949e060f5913361763121abd2416" dependencies = [ "castaway", "cfg-if", "itoa", - "rustversion", - "ryu", "static_assertions", + "zmij", ] [[package]] name = "comrak" -version = "0.29.0" +version = "0.56.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d8c32ff8b21372fab0e9ecc4e42536055702dc5faa418362bffd1544f9d12637" +checksum = "2544c4d6b6da7d54e95ac2833b464bf3dffa0666237868f2bf4ec5e11c9ba8cc" dependencies = [ "caseless", - "derive_builder", "entities", - "memchr", - "once_cell", - "regex", - "slug", + "finl_unicode", + "memchr-n", + "phf 0.14.0", + "phf_codegen 0.14.0", + "rustc-hash", + "smallvec", "typed-arena", - "unicode_categories", ] [[package]] @@ -439,12 +422,6 @@ dependencies = [ "vte", ] -[[package]] -name = "const-oid" -version = "0.10.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a6ef517f0926dd24a1582492c791b6a4818a4d94e789a334894aa15b0d12f55c" - [[package]] name = "cow-utils" version = "0.1.3" @@ -460,46 +437,27 @@ dependencies = [ "libc", ] -[[package]] -name = "cpufeatures" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b2a41393f66f16b0823bb79094d54ac5fbd34ab292ddafb9a0456ac9f87d201" -dependencies = [ - "libc", -] - -[[package]] -name = "crc32fast" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9481c1c90cbf2ac953f07c8d4a58aa3945c425b7185c9154d67a65e4230da511" -dependencies = [ - "cfg-if", -] - [[package]] name = "criterion" -version = "0.4.0" +version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7c76e09c1aae2bc52b3d2f29e13c6572553b30c4aa1b8a49fd70de6412654cb" +checksum = "950046b2aa2492f9a536f5f4f9a3de7b9e2476e575e05bd6c333371add4d98f3" dependencies = [ + "alloca", "anes", - "atty", "cast", "ciborium", - "clap 3.2.25", + "clap", "criterion-plot", "futures", - "itertools 0.10.5", - "lazy_static", + "itertools 0.13.0", "num-traits", "oorandom", + "page_size", "plotters", "rayon", "regex", "serde", - "serde_derive", "serde_json", "tinytemplate", "walkdir", @@ -507,12 +465,12 @@ dependencies = [ [[package]] name = "criterion-plot" -version = "0.5.0" +version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6b50826342786a51a89e2da3a28f1c32b06e387201bc2d19791f622c673706b1" +checksum = "d8d80a2f4f5b554395e47b5d8305bc3d27813bacb73493eb1001e8f76dae29ea" dependencies = [ "cast", - "itertools 0.10.5", + "itertools 0.13.0", ] [[package]] @@ -565,15 +523,6 @@ dependencies = [ "typenum", ] -[[package]] -name = "crypto-common" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce6e4c961d6cd6c9a86db418387425e8bdeaf05b3c8bc1411e6dca4c252f1453" -dependencies = [ - "hybrid-array", -] - [[package]] name = "darling" version = "0.20.11" @@ -595,7 +544,7 @@ dependencies = [ "proc-macro2", "quote", "strsim", - "syn", + "syn 2.0.106", ] [[package]] @@ -606,7 +555,7 @@ checksum = "fc34b93ccb385b40dc71c6fceac4b2ad23662c7eeb248cf10d529b7e055b6ead" dependencies = [ "darling_core", "quote", - "syn", + "syn 2.0.106", ] [[package]] @@ -617,19 +566,17 @@ checksum = "be1e0bca6c3637f992fc1cc7cbc52a78c1ef6db076dbf1059c4323d6a2048376" [[package]] name = "deno_ast" -version = "0.53.2" -source = "git+https://github.com/nathanwhit/deno_ast?branch=oxc-port#adc326fa89885400fc7d7baeb007b833138f5aff" +version = "0.53.3" +source = "git+https://github.com/nathanwhit/deno_ast?branch=oxc-port#9ff037f4731ee57781beac08f627ac08f4ccdcfb" dependencies = [ - "base64", + "base64 0.22.1", "capacity_builder", "deno_error", "deno_media_type", "deno_terminal", "oxc", - "oxc_str", "percent-encoding", "serde", - "text_lines", "thiserror", "unicode-width 0.2.1", "url", @@ -637,11 +584,11 @@ dependencies = [ [[package]] name = "deno_doc" -version = "0.202.0" +version = "0.210.0" dependencies = [ "anyhow", "cfg-if", - "clap 4.5.56", + "clap", "comrak", "console_static_text", "criterion", @@ -654,7 +601,7 @@ dependencies = [ "handlebars", "html-escape", "html5ever", - "indexmap 2.11.0", + "indexmap", "insta", "itoa", "js-sys", @@ -664,7 +611,7 @@ dependencies = [ "pretty_assertions", "regex", "serde", - "serde-wasm-bindgen", + "serde-wasm-bindgen 0.5.0", "serde_json", "similar", "termcolor", @@ -683,11 +630,11 @@ dependencies = [ "deno_error", "deno_graph", "import_map", - "indexmap 2.11.0", + "indexmap", "js-sys", "pretty_assertions", "serde", - "serde-wasm-bindgen", + "serde-wasm-bindgen 0.6.5", "serde_json", "wasm-bindgen", "wasm-bindgen-futures", @@ -695,9 +642,9 @@ dependencies = [ [[package]] name = "deno_error" -version = "0.7.0" +version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dde60bd153886964234c5012d3d9caf788287f28d81fb24a884436904101ef10" +checksum = "3007d3f1ea92ea503324ae15883aac0c2de2b8cf6fead62203ff6a67161007ab" dependencies = [ "deno_error_macro", "libc", @@ -708,19 +655,19 @@ dependencies = [ [[package]] name = "deno_error_macro" -version = "0.7.0" +version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "409f265785bd946d3006756955aaf40b0e4deb25752eae6a990afe54a31cfd83" +checksum = "9b565e60a9685cdf312c888665b5f8647ac692a7da7e058a5e2268a466da8eaf" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.106", ] [[package]] name = "deno_graph" -version = "0.108.2" -source = "git+https://github.com/nathanwhit/deno_graph?branch=oxc-port#7f786030d26b7aca8937c362436d56e1145168d8" +version = "0.111.1" +source = "git+https://github.com/nathanwhit/deno_graph?branch=oxc-port#9bea696b7e709399f2d1d1bd089127b413c3f6bc" dependencies = [ "async-trait", "boxed_error", @@ -734,7 +681,7 @@ dependencies = [ "deno_semver", "deno_unsync", "futures", - "indexmap 2.11.0", + "indexmap", "log", "monch", "once_cell", @@ -830,7 +777,7 @@ dependencies = [ "darling", "proc-macro2", "quote", - "syn", + "syn 2.0.106", ] [[package]] @@ -840,15 +787,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ab63b0e2bf4d5928aff72e83a7dace85d7bba5fe12dcc3c5a572d78caffd3f3c" dependencies = [ "derive_builder_core", - "syn", + "syn 2.0.106", ] -[[package]] -name = "deunicode" -version = "1.6.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "abd57806937c9cc163efc8ea3910e00a62e2aeb0b8119f1793a978088f8f6b04" - [[package]] name = "diff" version = "0.1.13" @@ -861,19 +802,8 @@ version = "0.10.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" dependencies = [ - "block-buffer 0.10.4", - "crypto-common 0.1.6", -] - -[[package]] -name = "digest" -version = "0.11.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1dd6dbb5841937940781866fa1281a1ff7bd3bf827091440879f9994983d5c2" -dependencies = [ - "block-buffer 0.12.0", - "const-oid", - "crypto-common 0.2.2", + "block-buffer", + "crypto-common", ] [[package]] @@ -884,7 +814,7 @@ checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.106", ] [[package]] @@ -953,6 +883,23 @@ version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "37909eebbb50d72f9059c3b6d82c0463f2ff062c9e95845c43a6c9c0355411be" +[[package]] +name = "fearless_simd" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3296eb97d869113eaf148a6bdf01884e90b3828ad7ae2340b0f93362fc158611" + +[[package]] +name = "fearless_simd_macros" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3e91d94c6885390b81782d7ee60fd6583b33907333a8b340de25ccf468353315" +dependencies = [ + "proc-macro2", + "quote", + "syn 3.0.9", +] + [[package]] name = "file_test_runner" version = "0.7.4" @@ -968,14 +915,16 @@ dependencies = [ ] [[package]] -name = "flate2" -version = "1.1.9" +name = "find-msvc-tools" +version = "0.1.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "843fba2746e448b37e26a819579957415c8cef339bf08564fe8b7ddbd959573c" -dependencies = [ - "crc32fast", - "miniz_oxide", -] +checksum = "1c66915cc5391097de7a2b0b972e8505aa33c0df401fd3a6811dbdb32881ba48" + +[[package]] +name = "finl_unicode" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "80bb028c8b4148c9ee0cca68fcd9add6044e81d3619f48577ddf13a263d047a2" [[package]] name = "fnv" @@ -1058,7 +1007,7 @@ checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.106", ] [[package]] @@ -1134,18 +1083,6 @@ dependencies = [ "thiserror", ] -[[package]] -name = "hashbrown" -version = "0.12.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" - -[[package]] -name = "hashbrown" -version = "0.15.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9229cfe53dfd69f0609a49f65461bd93001ea1ef889cd5529dd176593f5338a1" - [[package]] name = "hashbrown" version = "0.17.1" @@ -1161,15 +1098,6 @@ version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" -[[package]] -name = "hermit-abi" -version = "0.1.19" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33" -dependencies = [ - "libc", -] - [[package]] name = "hipstr" version = "0.6.0" @@ -1181,6 +1109,12 @@ dependencies = [ "sptr", ] +[[package]] +name = "hmac-sha1-compact" +version = "1.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ed9b23855291da44e7e84616e19dc0d969c3580e14ffa6b759f28775e26afc1" + [[package]] name = "html-escape" version = "0.2.13" @@ -1201,16 +1135,7 @@ dependencies = [ "markup5ever", "proc-macro2", "quote", - "syn", -] - -[[package]] -name = "hybrid-array" -version = "0.4.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9155a582abd142abc056962c29e3ce5ff2ad5469f4246b537ed42c5deba857da" -dependencies = [ - "typenum", + "syn 2.0.106", ] [[package]] @@ -1334,7 +1259,7 @@ checksum = "61dcb2ebdf4a4df8e6353c566f4b51ee2f602341538e41e77c8f861ac1bb16d5" dependencies = [ "boxed_error", "deno_error", - "indexmap 2.11.0", + "indexmap", "log", "percent-encoding", "serde", @@ -1345,23 +1270,14 @@ dependencies = [ [[package]] name = "indexmap" -version = "1.9.3" +version = "2.14.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99" -dependencies = [ - "autocfg", - "hashbrown 0.12.3", -] - -[[package]] -name = "indexmap" -version = "2.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f2481980430f9f78649238835720ddccc57e52df14ffce1c6f37391d61b563e9" +checksum = "cc4e190f5d26ca7051642629da2c52fc03bde85a03197c99408dcd291734c855" dependencies = [ "equivalent", - "hashbrown 0.15.5", + "hashbrown", "serde", + "serde_core", ] [[package]] @@ -1382,7 +1298,7 @@ version = "0.7.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "046fa2d4d00aea763528b4950358d0ead425372445dc8ff86312b3c69ff7727b" dependencies = [ - "bitflags 2.11.0", + "bitflags", "cfg-if", "libc", ] @@ -1395,34 +1311,35 @@ checksum = "a6cb138bb79a146c1bd460005623e142ef0181e3d0219cb493e02f7d08a35695" [[package]] name = "itertools" -version = "0.10.5" +version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b0fd2260e829bddf4cb6ea802289de2f86d6a7a690192fbe91b3f46e0f2c8473" +checksum = "413ee7dfc52ee1a4949ceeb7dbc8a33f2d6c088194d9f922fb8318faf1f01186" dependencies = [ "either", ] [[package]] name = "itertools" -version = "0.14.0" +version = "0.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b192c782037fadd9cfa75548310488aabdbf3d2da73885b31bd0abd03351285" +checksum = "8b4baf93f58d4425749ca49a51c50ebab072c5df6994d08fed93541c331481dc" dependencies = [ "either", ] [[package]] name = "itoa" -version = "1.0.17" +version = "1.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "92ecc6618181def0457392ccd0ee51198e065e016d1d527a7ac1b6dc7c1f09d2" +checksum = "8f42a60cbdf9a97f5d2305f08a87dc4e09308d1276d28c869c684d7777685682" [[package]] name = "js-sys" -version = "0.3.69" +version = "0.3.85" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "29c15563dc2726973df627357ce0c9ddddbea194836909d655df6a75d2cf296d" +checksum = "8c942ebf8e95485ca0d52d97da7c5a2c387d0e7f0ba4c35e93bfcaee045955b3" dependencies = [ + "once_cell", "wasm-bindgen", ] @@ -1480,7 +1397,7 @@ checksum = "16ce3abbeba692c8b8441d036ef91aea6df8da2c6b6e21c7e14d3c18e526be45" dependencies = [ "log", "phf 0.11.3", - "phf_codegen", + "phf_codegen 0.11.3", "string_cache", "string_cache_codegen", "tendril", @@ -1500,9 +1417,19 @@ dependencies = [ [[package]] name = "memchr" -version = "2.8.0" +version = "2.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf8baf1c55e62ffcace7a9f06f4bd9cd3f0c4beb022d3b367256b91b87513d98" + +[[package]] +name = "memchr-n" +version = "0.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8ca58f447f06ed17d5fc4043ce1b10dd205e060fb3ce5b979b8ed8e59ff3f79" +checksum = "f48c6352cc1185740af256ccc396af598d2366bfd90a34f5afe48744bf06a5b5" +dependencies = [ + "fearless_simd", + "fearless_simd_macros", +] [[package]] name = "miniz_oxide" @@ -1511,7 +1438,15 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1fa76a2c86f704bdb222d66965fb3d63269ce38518b83cb0575fca855ebb6316" dependencies = [ "adler2", - "simd-adler32", +] + +[[package]] +name = "miniz_oxide" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b63fbc4a50860e98e7b2aa7804ded1db5cbc3aff9193adaff57a6931bf7c4b4c" +dependencies = [ + "adler2", ] [[package]] @@ -1545,9 +1480,9 @@ checksum = "610a5acd306ec67f907abe5567859a3c693fb9886eb1f012ab8f2a47bef3db51" [[package]] name = "num-bigint" -version = "0.4.6" +version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a5e44f723f1133c9deac646763579fdb3ac745e418f2a7af9cd0c431da1f20b9" +checksum = "93e7820bc0a80a0238e650327316f929ba18d5be054b647490a3a6a339f3e7c0" dependencies = [ "num-integer", "num-traits", @@ -1613,29 +1548,17 @@ version = "11.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d6790f58c7ff633d8771f42965289203411a5e5c68388703c06e14f24770b41e" -[[package]] -name = "os_str_bytes" -version = "6.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2355d85b9a3786f481747ced0e0ff2ba35213a1f9bd406ed906554d7af805a1" - [[package]] name = "outref" version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1a80800c0488c3a21695ea981a54918fbb37abf04f4d0720c453632255e2ff0e" -[[package]] -name = "owo-colors" -version = "4.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d211803b9b6b570f68772237e415a029d5a50c65d382910b879fb19d3271f94d" - [[package]] name = "oxc" -version = "0.134.0" +version = "0.155.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d804f86548486ce1b6c92bb5511214f44074ea1e5bc94eded8ee4de2f7ca98c7" +checksum = "d6e790cd34b555e135d0d656139676ae62a50ef9a6829f9aacf9602b7525c501" dependencies = [ "oxc_allocator", "oxc_ast", @@ -1646,6 +1569,7 @@ dependencies = [ "oxc_regular_expression", "oxc_semantic", "oxc_span", + "oxc_str", "oxc_syntax", "oxc_transformer", "oxc_transformer_plugins", @@ -1653,62 +1577,38 @@ dependencies = [ [[package]] name = "oxc-browserslist" -version = "3.0.1" +version = "5.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c86f358f5705f4da4bce0af2792b6d24d64be9c465bdc70a752b2f168c5ff721" +checksum = "456720daa870e4f69f8d29fded1c8deea82da4780a6b8553baa160eb0cd8d864" dependencies = [ - "flate2", + "js-sys", + "libc", + "miniz_oxide 0.9.1", "postcard", "rustc-hash", "serde", "thiserror", ] -[[package]] -name = "oxc-miette" -version = "2.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4356a61f2ed4c9b3610245215fbf48970eb277126919f87db9d0efa93a74245c" -dependencies = [ - "cfg-if", - "owo-colors", - "oxc-miette-derive", - "textwrap", - "thiserror", - "unicode-segmentation", - "unicode-width 0.2.1", -] - -[[package]] -name = "oxc-miette-derive" -version = "2.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b237422b014f8f8fff75bb9379e697d13f8d57551a22c88bebb39f073c1bf696" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - [[package]] name = "oxc_allocator" -version = "0.134.0" +version = "0.155.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2303e54d087d40064154f2ec243fff0bf7641c078efae9bb14216a8869577ba7" +checksum = "45c8f46c8923b4afb4dd588d4684d5dd32332f1341225c066cc6af31094e7e3d" dependencies = [ "allocator-api2", - "hashbrown 0.17.1", + "hashbrown", "oxc_data_structures", "rustc-hash", ] [[package]] name = "oxc_ast" -version = "0.134.0" +version = "0.155.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f628429436867a51e5d623b4b27c02807aec3ea241f01deadd21b0d1604c8ef" +checksum = "35465751cfc99739fee42d8345b57d5b5087b462bea7bc5bb17d1f248e1efa22" dependencies = [ - "bitflags 2.11.0", + "bitflags", "oxc_allocator", "oxc_ast_macros", "oxc_data_structures", @@ -1722,21 +1622,21 @@ dependencies = [ [[package]] name = "oxc_ast_macros" -version = "0.134.0" +version = "0.155.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "52b3190e5f69284b59a4876a3b42431c8e2309b4de3670553aab4888f15aa6f2" +checksum = "e78e5d50ecf9fbf6c00afb29dbd670784b2ac407fd676f625d1f3515a1a2d577" dependencies = [ - "phf 0.13.1", + "phf 0.14.0", "proc-macro2", "quote", - "syn", + "syn 3.0.9", ] [[package]] name = "oxc_ast_visit" -version = "0.134.0" +version = "0.155.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dfe1897cf38bab83c998346184cba50db2849943b9d9e8634d09a2dc303ceaee" +checksum = "6836d2fde033c44eae57ab1be3fcc7bd6a57465783bdfce654ca28064a334dbe" dependencies = [ "oxc_allocator", "oxc_ast", @@ -1746,17 +1646,16 @@ dependencies = [ [[package]] name = "oxc_codegen" -version = "0.134.0" +version = "0.155.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b7d690df0e909b1663c19a368cdfcf0cac94fd57ddf068230442ff82b27ad000" +checksum = "75db0d260bb5493e31be0ab17651d428da5cd8c49ec2cf78d857e605d66385dd" dependencies = [ - "bitflags 2.11.0", + "bitflags", "cow-utils", - "dragonbox_ecma", - "itoa", "oxc_allocator", "oxc_ast", "oxc_data_structures", + "oxc_ecmascript", "oxc_index", "oxc_semantic", "oxc_sourcemap", @@ -1764,13 +1663,14 @@ dependencies = [ "oxc_str", "oxc_syntax", "rustc-hash", + "smallvec", ] [[package]] name = "oxc_compat" -version = "0.134.0" +version = "0.155.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ae9249b8fc4604f787cbe39457565f21f7747a59cb94333bcc1ff85f9327323" +checksum = "90809c31d39f49d2023b090ffcfd13b5f2e07b156abde430f1b1454ceef51bb1" dependencies = [ "cow-utils", "oxc-browserslist", @@ -1781,51 +1681,59 @@ dependencies = [ [[package]] name = "oxc_data_structures" -version = "0.134.0" +version = "0.155.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cb6aa082cf4bbc5b3c189e9331f31823e31a5452533da36dfa5b174f20e72c1c" +checksum = "a46b759a8cb13a1111649370f1d769322b082edabd625466254f238818bdc9e9" dependencies = [ "ropey", ] [[package]] name = "oxc_diagnostics" -version = "0.134.0" +version = "0.155.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "67daf165d8abff1577825a4303a5d0b61ae29c7b66c9e0e0e7f97f77705667ed" +checksum = "5b80f4b05a80879518ebe85a8df9368758ebc1e176327b659e1e97389f8561c7" dependencies = [ + "bytecount", "cow-utils", - "oxc-miette", + "itoa", + "memchr", + "oxc_span", "percent-encoding", + "smallvec", + "textwrap", + "unicode-segmentation", + "unicode-width 0.2.1", ] [[package]] name = "oxc_ecmascript" -version = "0.134.0" +version = "0.155.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "41e701220c14cc0d0733a6501f1837fe9d913e891e25647132389fdfd78dd7d3" +checksum = "f8c634665e0be5dde95549146734ab4939b8d1b5d2e7cc006d38b9f5d17a58a2" dependencies = [ - "cow-utils", + "dragonbox_ecma", + "itoa", "num-bigint", "num-traits", - "oxc_allocator", "oxc_ast", - "oxc_regular_expression", + "oxc_data_structures", "oxc_span", + "oxc_str", "oxc_syntax", ] [[package]] name = "oxc_estree" -version = "0.134.0" +version = "0.155.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f3d42104865cba688a62c0cf5691592a890eef9de359bccb18a97b2be088478d" +checksum = "5dcdd8235762cc9305d619842b73c1e89a0ebec8ccf2f27142ef597521443c1f" [[package]] name = "oxc_index" -version = "4.1.0" +version = "5.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eb3e6120999627ec9703025eab7c9f410ebb7e95557632a8902ca48210416c2b" +checksum = "191884bee6c3744909a51acc7d78d4ae370d817b25875b10642f632327b6296e" dependencies = [ "nonmax", "serde", @@ -1833,11 +1741,11 @@ dependencies = [ [[package]] name = "oxc_parser" -version = "0.134.0" +version = "0.155.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "02d671cb199fc83d8fc9764926c3c8f7979affbd2d916e3b2e22e403745305b6" +checksum = "635c4e1bb876a9d4ee0e338fa68547a1d75add58637e5c3921fb81ae10a60439" dependencies = [ - "bitflags 2.11.0", + "bitflags", "cow-utils", "memchr", "num-bigint", @@ -1857,32 +1765,33 @@ dependencies = [ [[package]] name = "oxc_regular_expression" -version = "0.134.0" +version = "0.155.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a06eb61d28a8b83b0bda7dc75bf886f178155dead57746fab874312c81baa359" +checksum = "3ae3f2c42773d16336a75d5c61dae45a34aea399f0b5399a7a25c8509d79662f" dependencies = [ - "bitflags 2.11.0", + "bitflags", "oxc_allocator", "oxc_ast_macros", "oxc_diagnostics", "oxc_span", "oxc_str", - "phf 0.13.1", + "phf 0.14.0", "rustc-hash", "unicode-id-start", ] [[package]] name = "oxc_semantic" -version = "0.134.0" +version = "0.155.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8573ff803b00bdacc550475aacc72305621d2992988e5f7886391fa9d9bfa611" +checksum = "b24ee2095e2ddac60c2063b59693bbf2b80936c8a9e036463b153a203857831b" dependencies = [ - "itertools 0.14.0", + "itertools 0.15.0", "memchr", "oxc_allocator", "oxc_ast", "oxc_ast_visit", + "oxc_data_structures", "oxc_diagnostics", "oxc_ecmascript", "oxc_index", @@ -1896,9 +1805,9 @@ dependencies = [ [[package]] name = "oxc_sourcemap" -version = "7.0.0" +version = "9.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "db3866f9075027840e0711b52e15d2e1ba076fc5f5f01c96eeedd26375410641" +checksum = "1133371a5fadc14b9f66a8fec14be3564a77647c7ab21b1ef0ec973bd82613ce" dependencies = [ "base64-simd", "json-escape-simd", @@ -1909,12 +1818,11 @@ dependencies = [ [[package]] name = "oxc_span" -version = "0.134.0" +version = "0.155.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "35ff77b2ca10d57dc7645c4af838b1aa455cac6569992fe544ed041a8021ae10" +checksum = "0cb5bee6f7a9829ddc4d8c05102fe1aa7e2ca31c7ff0bcfbb7069ca977334840" dependencies = [ "compact_str", - "oxc-miette", "oxc_allocator", "oxc_ast_macros", "oxc_estree", @@ -1923,23 +1831,24 @@ dependencies = [ [[package]] name = "oxc_str" -version = "0.134.0" +version = "0.155.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dbcd6412fde266b6ffdbcdf118cba2c8dc0d6ddba6aa4e361842ebaf320a4eed" +checksum = "c04d966af690d3b780ee4c47436174e558750eed6ca40b07d695fa4910ad8e33" dependencies = [ "compact_str", - "hashbrown 0.17.1", + "hashbrown", + "memchr", "oxc_allocator", "oxc_estree", ] [[package]] name = "oxc_syntax" -version = "0.134.0" +version = "0.155.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ab19e002e05e4d107483ace848ca2d6ce5c714f238d70d591f91d17fef54be98" +checksum = "684d5f6db25b6e3d026582b3926166c80eeda9aac8a879782292c6a33b7d13a0" dependencies = [ - "bitflags 2.11.0", + "bitflags", "cow-utils", "dragonbox_ecma", "nonmax", @@ -1949,19 +1858,20 @@ dependencies = [ "oxc_index", "oxc_span", "oxc_str", - "phf 0.13.1", + "phf 0.14.0", "unicode-id-start", ] [[package]] name = "oxc_transformer" -version = "0.134.0" +version = "0.155.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c753c4eb41524071c4d13650642b5622b7b23fca6b4d92872dc43f6e71686e16" +checksum = "fec592c64f6455678cbdb76635144f76825fcaf85f9509d814bd6a9e2bfde160" dependencies = [ - "base64", + "base64 0.23.1", "compact_str", - "indexmap 2.11.0", + "hmac-sha1-compact", + "indexmap", "itoa", "memchr", "oxc_allocator", @@ -1980,14 +1890,13 @@ dependencies = [ "rustc-hash", "serde", "serde_json", - "sha1", ] [[package]] name = "oxc_transformer_plugins" -version = "0.134.0" +version = "0.155.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0dbd5a19932bc3aded01f5f2ff18f448cadbd921b26cffa2b90294fd1a44f4ce" +checksum = "2470e565dc13884f9a1e1c08d8eaad3c927e807d867a118c0f0287534971327f" dependencies = [ "cow-utils", "itoa", @@ -2008,9 +1917,9 @@ dependencies = [ [[package]] name = "oxc_traverse" -version = "0.134.0" +version = "0.155.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d817fd3459ecb0c0ea37042e796954d8caff9a6c5e23bf60a41f002cacdd5c79" +checksum = "b2ba98ff0dc34cb2e45bcbe3cee395e792298fad77ca63c574766571f859cc56" dependencies = [ "itoa", "oxc_allocator", @@ -2025,6 +1934,16 @@ dependencies = [ "rustc-hash", ] +[[package]] +name = "page_size" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "30d5b2194ed13191c1999ae0704b7839fb18384fa22e49b57eeaa97d79ce40da" +dependencies = [ + "libc", + "winapi", +] + [[package]] name = "parking_lot" version = "0.12.4" @@ -2085,7 +2004,7 @@ dependencies = [ "pest_meta", "proc-macro2", "quote", - "syn", + "syn 2.0.106", ] [[package]] @@ -2109,12 +2028,12 @@ dependencies = [ [[package]] name = "phf" -version = "0.13.1" +version = "0.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c1562dc717473dbaa4c1f85a36410e03c047b2e7df7f45ee938fbef64ae7fadf" +checksum = "010378780309880b08997fae13be7834dba947d36393bd372f2b1556deb2a2f6" dependencies = [ "phf_macros", - "phf_shared 0.13.1", + "phf_shared 0.14.0", "serde", ] @@ -2128,6 +2047,16 @@ dependencies = [ "phf_shared 0.11.3", ] +[[package]] +name = "phf_codegen" +version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41b585a510fb76fdebead6897982ef2a03a21d8e6cbcca904999742a4afc6ffe" +dependencies = [ + "phf_generator 0.14.0", + "phf_shared 0.14.0", +] + [[package]] name = "phf_generator" version = "0.11.3" @@ -2140,25 +2069,25 @@ dependencies = [ [[package]] name = "phf_generator" -version = "0.13.1" +version = "0.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "135ace3a761e564ec88c03a77317a7c6b80bb7f7135ef2544dbe054243b89737" +checksum = "aeb62e0959d5a1bebc965f4d15d9e2b7cea002b6b0f5ba8cde6cc26738467100" dependencies = [ "fastrand", - "phf_shared 0.13.1", + "phf_shared 0.14.0", ] [[package]] name = "phf_macros" -version = "0.13.1" +version = "0.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "812f032b54b1e759ccd5f8b6677695d5268c588701effba24601f6932f8269ef" +checksum = "5fa8d0ca26d424d27630da600c6624696e7dec8bf7b3b492b383c5dc49e5e085" dependencies = [ - "phf_generator 0.13.1", - "phf_shared 0.13.1", + "phf_generator 0.14.0", + "phf_shared 0.14.0", "proc-macro2", "quote", - "syn", + "syn 2.0.106", ] [[package]] @@ -2172,9 +2101,9 @@ dependencies = [ [[package]] name = "phf_shared" -version = "0.13.1" +version = "0.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e57fef6bc5981e38c2ce2d63bfa546861309f875b8a75f092d1d54ae2d64f266" +checksum = "c6fd9027e2d9319be6349febd1db4e8d02aa544921200c9b777720ac34a3aa89" dependencies = [ "siphasher", ] @@ -2315,7 +2244,7 @@ version = "0.5.17" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5407465600fb0548f1442edf71dd20683c6ed326200ace4b1ef0763521bb3b77" dependencies = [ - "bitflags 2.11.0", + "bitflags", ] [[package]] @@ -2429,6 +2358,17 @@ dependencies = [ "wasm-bindgen", ] +[[package]] +name = "serde-wasm-bindgen" +version = "0.6.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8302e169f0eddcc139c70f139d19d6467353af16f9fce27e8c30158036a1e16b" +dependencies = [ + "js-sys", + "serde", + "wasm-bindgen", +] + [[package]] name = "serde_bytes" version = "0.11.17" @@ -2455,7 +2395,7 @@ checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.106", ] [[package]] @@ -2464,24 +2404,13 @@ version = "1.0.143" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d401abef1d108fbd9cbaebc3e46611f4b1021f714a0597a71f41ee463f5f4a5a" dependencies = [ - "indexmap 2.11.0", + "indexmap", "itoa", "memchr", "ryu", "serde", ] -[[package]] -name = "sha1" -version = "0.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aacc4cc499359472b4abe1bf11d0b12e688af9a805fa5e3016f9a386dc2d0214" -dependencies = [ - "cfg-if", - "cpufeatures 0.3.0", - "digest 0.11.3", -] - [[package]] name = "sha2" version = "0.10.9" @@ -2489,10 +2418,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a7507d819769d01a365ab707794a4084392c824f54a7a6a7862f8c3d0892b283" dependencies = [ "cfg-if", - "cpufeatures 0.2.17", - "digest 0.10.7", + "cpufeatures", + "digest", ] +[[package]] +name = "shlex" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8fadd59c855ef2080decdef8ff161eb6661b86933c9d82e5ba29dc602a55aba" + [[package]] name = "signal-hook-registry" version = "1.4.6" @@ -2502,12 +2437,6 @@ dependencies = [ "libc", ] -[[package]] -name = "simd-adler32" -version = "0.3.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e320a6c5ad31d271ad523dcf3ad13e2767ad8b1cb8f047f75a8aeaf8da139da2" - [[package]] name = "similar" version = "2.7.0" @@ -2526,21 +2455,11 @@ version = "0.4.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7a2ae44ef20feb57a68b23d846850f861394c2e02dc425a50098ae8c90267589" -[[package]] -name = "slug" -version = "0.1.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "882a80f72ee45de3cc9a5afeb2da0331d58df69e4e7d8eeb5d3c7784ae67e724" -dependencies = [ - "deunicode", - "wasm-bindgen", -] - [[package]] name = "smallvec" -version = "1.15.1" +version = "1.16.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03" +checksum = "d0d5d4b1981b8bbbb7aed204cae5726d683d5d6ac7e74ec54122ea28f315e7c8" dependencies = [ "serde", ] @@ -2627,6 +2546,17 @@ dependencies = [ "unicode-ident", ] +[[package]] +name = "syn" +version = "3.0.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d78c8dee4c7bf0e14673097256fed6142ce9d3b85a408189d07482442145823b" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + [[package]] name = "synstructure" version = "0.13.2" @@ -2635,7 +2565,7 @@ checksum = "728a70f3dbaf5bab7f0c4b1ac8d7ae5ea60a4b5549c8a5914361c99147a709d2" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.106", ] [[package]] @@ -2655,7 +2585,7 @@ checksum = "181f22127402abcf8ee5c83ccd5b408933fec36a6095cf82cda545634692657e" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.106", ] [[package]] @@ -2678,15 +2608,6 @@ dependencies = [ "winapi-util", ] -[[package]] -name = "text_lines" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7fd5828de7deaa782e1dd713006ae96b3bee32d3279b79eb67ecf8072c059bcf" -dependencies = [ - "serde", -] - [[package]] name = "textwrap" version = "0.16.2" @@ -2715,7 +2636,7 @@ checksum = "6c5e1be1c48b9172ee610da68fd9cd2770e7a4056cb3fc98710ee6906f0c7960" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.106", ] [[package]] @@ -2781,7 +2702,7 @@ checksum = "6e06d43f1345a3bcd39f6a56dbb7dcab2ba47e68e8ac134855e7e2bdbaf8cab8" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.106", ] [[package]] @@ -2831,9 +2752,9 @@ dependencies = [ [[package]] name = "unicode-segmentation" -version = "1.12.0" +version = "1.13.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f6ccf251212114b54433ec949fd6a7841275f9ada20dddd2f29e9ceea4501493" +checksum = "c6f5d3c3b1bf09027a88a6bc961fc00497d651009560b5463668dc81b0fa87a8" [[package]] name = "unicode-width" @@ -2847,12 +2768,6 @@ version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4a1a07cc7db3810833284e8d372ccdc6da29741639ecc70c9ec107df0fa6154c" -[[package]] -name = "unicode_categories" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "39ec24b3121d976906ece63c9daad25b85969647682eee313cb5779fdd69e14e" - [[package]] name = "url" version = "2.5.7" @@ -2940,46 +2855,36 @@ checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b" [[package]] name = "wasm-bindgen" -version = "0.2.92" +version = "0.2.108" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4be2531df63900aeb2bca0daaaddec08491ee64ceecbee5076636a3b026795a8" +checksum = "64024a30ec1e37399cf85a7ffefebdb72205ca1c972291c51512360d90bd8566" dependencies = [ "cfg-if", - "wasm-bindgen-macro", -] - -[[package]] -name = "wasm-bindgen-backend" -version = "0.2.92" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "614d787b966d3989fa7bb98a654e369c762374fd3213d212cfc0251257e747da" -dependencies = [ - "bumpalo", - "log", "once_cell", - "proc-macro2", - "quote", - "syn", + "rustversion", + "wasm-bindgen-macro", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-futures" -version = "0.4.42" +version = "0.4.58" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "76bc14366121efc8dbb487ab05bcc9d346b3b5ec0eaa76e46594cabbe51762c0" +checksum = "70a6e77fd0ae8029c9ea0063f87c46fde723e7d887703d74ad2616d792e51e6f" dependencies = [ "cfg-if", + "futures-util", "js-sys", + "once_cell", "wasm-bindgen", "web-sys", ] [[package]] name = "wasm-bindgen-macro" -version = "0.2.92" +version = "0.2.108" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1f8823de937b71b9460c0c34e25f3da88250760bec0ebac694b49997550d726" +checksum = "008b239d9c740232e71bd39e8ef6429d27097518b6b30bdf9086833bd5b6d608" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -2987,22 +2892,25 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.92" +version = "0.2.108" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e94f17b526d0a461a191c78ea52bbce64071ed5c04c9ffe424dcb38f74171bb7" +checksum = "5256bae2d58f54820e6490f9839c49780dff84c65aeab9e772f15d5f0e913a55" dependencies = [ + "bumpalo", "proc-macro2", "quote", - "syn", - "wasm-bindgen-backend", + "syn 2.0.106", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-shared" -version = "0.2.92" +version = "0.2.108" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af190c94f2773fdb3729c55b007a722abb5384da03bc0986df4c289bf5567e96" +checksum = "1f01b580c9ac74c8d8f0c0e4afb04eeef2acf145458e52c03845ee9cd23e3d12" +dependencies = [ + "unicode-ident", +] [[package]] name = "wasm_dep_analyzer" @@ -3016,9 +2924,9 @@ dependencies = [ [[package]] name = "web-sys" -version = "0.3.69" +version = "0.3.85" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77afa9a11836342370f4817622a2f0f418b134426d91a82dfb48f532d2ec13ef" +checksum = "312e32e551d92129218ea9a2452120f4aabc03529ef03e4d0d82fb2780608598" dependencies = [ "js-sys", "wasm-bindgen", @@ -3251,7 +3159,7 @@ checksum = "38da3c9736e16c5d3c8c597a9aaa5d1fa565d0532ae05e27c24aa62fb32c0ab6" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.106", "synstructure", ] @@ -3272,7 +3180,7 @@ checksum = "d71e5d6e06ab090c67b5e44993ec16b72dcbaabc526db883a360057678b48502" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.106", "synstructure", ] @@ -3306,5 +3214,11 @@ checksum = "5b96237efa0c878c64bd89c436f661be4e46b2f3eff1ebb976f7ef2321d2f58f" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.106", ] + +[[package]] +name = "zmij" +version = "1.0.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "29666d0abbfad1e3dc4dcf6144730dd3a3ab225bbbdac83319345b1b44ccfc1b" diff --git a/Cargo.toml b/Cargo.toml index 7704e37b1..0821f985b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "deno_doc" -version = "0.202.0" +version = "0.210.0" edition = "2024" description = "doc generation for deno" authors = ["the Deno authors"] @@ -45,13 +45,13 @@ similar = "2" html-escape = { version = "0.2.13" } handlebars = { version = "6.1", features = ["string_helpers"] } -comrak = { version = "0.29.0", optional = true, default-features = false } +comrak = { version = "0.56.0", optional = true, default-features = false } [dev-dependencies] anyhow = { version = "1.0.86" } clap = { version = "4", features = ["derive"] } console_static_text = "0.8.2" -criterion = { version = "0.4.0", features = ["async_futures", "html_reports"] } +criterion = { version = "0.8.0", features = ["async_futures", "html_reports"] } file_test_runner = "0.7.2" futures = "0.3.30" tokio = { version = "1.39.2", features = ["full"] } @@ -60,7 +60,7 @@ insta = { version = "1.39.0", features = ["json"] } html5ever = "0.27.0" markup5ever_rcdom = "0.3.0" -[target.'cfg(target_arch = "wasm32")'.dependencies] +[target.'cfg(all(target_arch = "wasm32", not(target_os = "emscripten")))'.dependencies] url = "2.4.1" percent-encoding = "2.3.1" wasm-bindgen = "0.2.92" diff --git a/rust-toolchain.toml b/rust-toolchain.toml index 4f0430eac..2c202d45e 100644 --- a/rust-toolchain.toml +++ b/rust-toolchain.toml @@ -1,3 +1,3 @@ [toolchain] -channel = "1.96.0" +channel = "1.97.0" components = ["rustfmt", "clippy"] diff --git a/src/class.rs b/src/class.rs index 207e78068..8bd5acd11 100644 --- a/src/class.rs +++ b/src/class.rs @@ -287,10 +287,9 @@ pub fn class_to_class_def( } } - let extends: Option> = match &class.super_class { - Some(boxed) => { - let expr: &Expression = boxed; - walk_class_extends(expr).map(|s| s.into_boxed_str()) + let extends: Option> = match &class.heritage { + Some(heritage) => { + walk_class_extends(&heritage.expression).map(|s| s.into_boxed_str()) } None => None, }; @@ -417,7 +416,8 @@ pub fn class_to_class_def( if let Some(js_doc) = js_doc_for_range(module_info, ts_index_sig.span()) { let mut params = vec![]; - for param in &ts_index_sig.parameters { + { + let param = &ts_index_sig.parameter; let ts_type = Some(TsTypeDef::new( module_info, ¶m.type_annotation.type_annotation, @@ -459,7 +459,10 @@ pub fn class_to_class_def( let super_type_params = maybe_type_param_instantiation_to_type_defs( module_info, - class.super_type_arguments.as_deref(), + class + .heritage + .as_ref() + .and_then(|heritage| heritage.type_arguments.as_deref()), ); let decorators = decorators_to_defs(module_info, &class.decorators); diff --git a/src/diff/class.rs b/src/diff/class.rs index 5bb8175fd..d216fa67d 100644 --- a/src/diff/class.rs +++ b/src/diff/class.rs @@ -604,7 +604,7 @@ impl MethodsDiff { #[serde(rename_all = "camelCase")] pub struct MethodDiff { pub name: Box, - pub kind: deno_ast::swc::ast::MethodKind, + pub kind: crate::util::types::MethodKind, #[serde(skip_serializing_if = "Option::is_none")] pub name_change: Option>>, #[serde(skip_serializing_if = "Option::is_none")] diff --git a/src/diff/interface.rs b/src/diff/interface.rs index 5ead4010f..c5d2515cf 100644 --- a/src/diff/interface.rs +++ b/src/diff/interface.rs @@ -431,7 +431,7 @@ impl InterfaceMethodsDiff { #[serde(rename_all = "camelCase")] pub struct InterfaceMethodDiff { pub name: String, - pub kind: deno_ast::swc::ast::MethodKind, + pub kind: crate::util::types::MethodKind, #[serde(skip_serializing_if = "Option::is_none")] pub name_change: Option>, #[serde(skip_serializing_if = "Option::is_none")] diff --git a/src/display.rs b/src/display.rs index 0ee54c409..bab3090cd 100644 --- a/src/display.rs +++ b/src/display.rs @@ -65,7 +65,6 @@ pub(crate) fn display_method( cfg_if! { if #[cfg(feature = "rust")] { use crate::util::types::Accessibility; - use crate::util::types::MethodKind; pub(crate) fn display_abstract(is_abstract: bool) -> impl Display { colors::magenta(if is_abstract { "abstract " } else { "" }) diff --git a/src/enum.rs b/src/enum.rs index 04ccaac08..1cdd724de 100644 --- a/src/enum.rs +++ b/src/enum.rs @@ -1,5 +1,6 @@ // Copyright 2018-2024 the Deno authors. All rights reserved. MIT license. +use deno_ast::JSStrExt; use deno_ast::oxc::ast::ast::TSEnumDeclaration; use deno_ast::oxc::span::GetSpan; use deno_graph::symbols::EsModuleInfo; @@ -38,7 +39,7 @@ pub fn get_doc_for_ts_enum_decl( for enum_member in &enum_decl.body.members { if let Some(js_doc) = js_doc_for_range(module_info, enum_member.span()) { - let name = enum_member.id.static_name().to_string(); + let name = enum_member.id.static_name().to_string_lossy(); let init = if let Some(expr) = &enum_member.initializer { infer_ts_type_from_expr(module_info, expr, true) } else { diff --git a/src/html/comrak.rs b/src/html/comrak.rs index 8a887405e..19aa50e6a 100644 --- a/src/html/comrak.rs +++ b/src/html/comrak.rs @@ -149,10 +149,9 @@ pub fn create_renderer( if title_only { walk_node_title(root); - if let Some(child) = root.first_child() { + { + let child = root.first_child()?; render_node(child, &options, &plugins) - } else { - return None; } } else { if let Some(node_hook) = &node_hook { diff --git a/src/html/mod.rs b/src/html/mod.rs index beab4e3e6..6de671b07 100644 --- a/src/html/mod.rs +++ b/src/html/mod.rs @@ -1258,10 +1258,10 @@ impl DocNodeWithContext { // so they must not get drilldown pages or listing/search entries // either let is_private = - |accessibility: &Option| { + |accessibility: &Option| { matches!( accessibility, - Some(deno_ast::swc::ast::Accessibility::Private) + Some(crate::util::types::Accessibility::Private) ) }; diff --git a/src/html/symbols/interface.rs b/src/html/symbols/interface.rs index eb36c3012..6e59af93c 100644 --- a/src/html/symbols/interface.rs +++ b/src/html/symbols/interface.rs @@ -6,7 +6,7 @@ use crate::html::render_context::RenderContext; use crate::html::types::render_type_def_colon; use crate::html::types::type_params_summary; use crate::html::util::*; -use deno_ast::swc::ast::MethodKind; +use crate::util::types::MethodKind; use indexmap::IndexMap; pub(crate) fn render_interface( diff --git a/src/html/symbols/namespace.rs b/src/html/symbols/namespace.rs index c09fa9608..3c305072c 100644 --- a/src/html/symbols/namespace.rs +++ b/src/html/symbols/namespace.rs @@ -496,7 +496,7 @@ fn get_subitem_diff_status( DeclarationDefDiff::Class(class_diff) => match kind { DrilldownKind::Method(method_kind) => { let mc = class_diff.method_changes.as_ref()?; - let matches = |m_name: &str, m_kind: deno_ast::swc::ast::MethodKind| { + let matches = |m_name: &str, m_kind: crate::util::types::MethodKind| { m_name == name && crate::html::MethodKind::from(m_kind) == *method_kind }; @@ -539,7 +539,7 @@ fn get_subitem_diff_status( DeclarationDefDiff::Interface(iface_diff) => match kind { DrilldownKind::Method(method_kind) => { let mc = iface_diff.method_changes.as_ref()?; - let matches = |m_name: &str, m_kind: deno_ast::swc::ast::MethodKind| { + let matches = |m_name: &str, m_kind: crate::util::types::MethodKind| { m_name == name && crate::html::MethodKind::from(m_kind) == *method_kind }; diff --git a/src/html/types.rs b/src/html/types.rs index cb3c0c298..c1b9710c4 100644 --- a/src/html/types.rs +++ b/src/html/types.rs @@ -88,7 +88,7 @@ pub(crate) fn render_type_def( && let Some(href) = ctx .ctx .href_resolver - .resolve_global_symbol(&[keyword.to_owned()]) + .resolve_global_symbol(std::slice::from_ref(keyword)) { format!( r#"{keyword}"#, diff --git a/src/interface.rs b/src/interface.rs index aff0d5371..479122390 100644 --- a/src/interface.rs +++ b/src/interface.rs @@ -1,5 +1,6 @@ // Copyright 2018-2024 the Deno authors. All rights reserved. MIT license. +use deno_ast::JSStrExt; use deno_ast::oxc::ast::ast::Expression; use deno_ast::oxc::ast::ast::TSInterfaceDeclaration; use deno_ast::oxc::ast::ast::TSSignature; @@ -54,7 +55,7 @@ pub fn expr_to_name(expr: &Expression) -> String { } Expression::ComputedMemberExpression(_) | Expression::PrivateFieldExpression(_) => "[UNSUPPORTED]".to_string(), - Expression::StringLiteral(str_) => str_.value.to_string(), + Expression::StringLiteral(str_) => str_.value.to_string_lossy(), Expression::BooleanLiteral(bool_) => { if bool_.value { "true" } else { "false" }.to_string() } @@ -85,14 +86,14 @@ pub fn expr_to_name(expr: &Expression) -> String { pub fn property_key_name(key: &deno_ast::oxc::ast::ast::PropertyKey) -> String { use deno_ast::oxc::ast::ast::PropertyKey; if let Some(name) = key.static_name() { - return name.to_string(); + return name.as_js_str().to_string_lossy(); } // For computed keys, resolve common expression patterns match key { PropertyKey::StaticIdentifier(ident) => ident.name.to_string(), // Computed keys that are identifiers (e.g., `[pc]`) PropertyKey::Identifier(ident) => ident.name.to_string(), - PropertyKey::StringLiteral(s) => s.value.to_string(), + PropertyKey::StringLiteral(s) => s.value.to_string_lossy(), PropertyKey::NumericLiteral(n) => n.value.to_string(), _ => "[UNSUPPORTED]".to_string(), } @@ -200,9 +201,8 @@ pub fn get_doc_for_ts_interface_decl( TSSignature::TSIndexSignature(ts_index_sig) => { if let Some(js_doc) = js_doc_for_range(module_info, ts_index_sig.span) { // TSIndexSignature uses TSIndexSignatureName, not FormalParameter - let params = ts_index_sig - .parameters - .iter() + let params = [&ts_index_sig.parameter] + .into_iter() .map(|param| { let ts_type = Some(TsTypeDef::new( module_info, diff --git a/src/params.rs b/src/params.rs index fbb6d5a94..0232aab03 100644 --- a/src/params.rs +++ b/src/params.rs @@ -5,6 +5,7 @@ use crate::decorators::decorators_to_defs; use crate::display::SliceDisplayer; use crate::display::display_optional; use crate::ts_type::TsTypeDef; +use deno_ast::JSStrExt; use deno_ast::oxc::ast::ast::ArrayPattern; use deno_ast::oxc::ast::ast::AssignmentPattern; @@ -404,7 +405,7 @@ pub fn prop_name_to_string( ) -> String { match prop_key { PropertyKey::StaticIdentifier(ident) => ident.name.to_string(), - PropertyKey::StringLiteral(str_) => str_.value.to_string(), + PropertyKey::StringLiteral(str_) => str_.value.to_string_lossy(), PropertyKey::NumericLiteral(num) => num.value.to_string(), PropertyKey::BigIntLiteral(num) => num .raw diff --git a/src/parser.rs b/src/parser.rs index b5af15678..ef539ef79 100644 --- a/src/parser.rs +++ b/src/parser.rs @@ -1,30 +1,30 @@ // Copyright 2018-2024 the Deno authors. All rights reserved. MIT license. +use deno_ast::JSStrExt; use deno_ast::oxc::ast::ast::BindingIdentifier; use deno_ast::oxc::ast::ast::BindingIdentifier as Ident; use deno_ast::oxc::ast::ast::BindingPattern; -use deno_ast::oxc::ast::ast::ClassElement; -use deno_ast::oxc::ast::ast::IdentifierReference; -use deno_ast::oxc::ast::ast::MethodDefinitionKind; -use deno_ast::oxc::ast::ast::ModuleExportName; -use deno_ast::oxc::ast::ast::PropertyKey; -use deno_ast::oxc::ast::ast::TSInterfaceDeclaration; -use deno_ast::oxc::ast::ast::TSSignature; -use deno_ast::oxc::ast::ast::TSTypeName; use deno_ast::oxc::ast::ast::Class; +use deno_ast::oxc::ast::ast::ClassElement; use deno_ast::oxc::ast::ast::Declaration as OxcDeclaration; +use deno_ast::oxc::ast::ast::ExportDeclaration; use deno_ast::oxc::ast::ast::ExportDefaultDeclaration; use deno_ast::oxc::ast::ast::ExportDefaultDeclarationKind; -use deno_ast::oxc::ast::ast::ExportNamedDeclaration; use deno_ast::oxc::ast::ast::Expression; use deno_ast::oxc::ast::ast::Function as FnDecl; +use deno_ast::oxc::ast::ast::IdentifierReference; use deno_ast::oxc::ast::ast::ImportDeclarationSpecifier; +use deno_ast::oxc::ast::ast::MethodDefinitionKind; +use deno_ast::oxc::ast::ast::ModuleExportName; +use deno_ast::oxc::ast::ast::PropertyKey; use deno_ast::oxc::ast::ast::Statement; use deno_ast::oxc::ast::ast::TSEnumDeclaration as TsEnumDecl; +use deno_ast::oxc::ast::ast::TSInterfaceDeclaration; use deno_ast::oxc::ast::ast::TSInterfaceDeclaration as TsInterfaceDecl; -use deno_ast::oxc::ast::ast::TSModuleDeclaration as TsModuleDecl; -use deno_ast::oxc::ast::ast::TSModuleDeclarationName; +use deno_ast::oxc::ast::ast::TSNamespaceDeclaration as TsModuleDecl; +use deno_ast::oxc::ast::ast::TSSignature; use deno_ast::oxc::ast::ast::TSTypeAliasDeclaration as TsTypeAliasDecl; +use deno_ast::oxc::ast::ast::TSTypeName; use deno_ast::oxc::ast::ast::VariableDeclaration as VarDecl; use deno_ast::oxc::ast::ast::VariableDeclarator as VarDeclarator; use deno_ast::oxc::span::GetSpan; @@ -53,7 +53,6 @@ use std::sync::Arc; use crate::Location; use crate::diagnostics::DiagnosticsCollector; use crate::diagnostics::DocDiagnostic; -use crate::interface::expr_to_name; use crate::interface::property_key_name; use crate::js_doc::JsDoc; use crate::node::DeclarationDef; @@ -62,11 +61,11 @@ use crate::node::Document; use crate::node::Import; use crate::node::NamespaceDef; use crate::node::ReferenceDef; +use crate::ts_type::Id; use crate::ts_type::PropertyDef; use crate::ts_type::TsTypeDef; use crate::ts_type::TsTypeDefKind; use crate::ts_type::TsTypeLiteralDef; -use crate::ts_type::Id; use crate::ts_type::binding_identifier_to_id; use crate::ts_type::identifier_reference_to_id; use crate::ts_type::infer_simple_ts_type_from_init; @@ -840,7 +839,7 @@ impl<'a> DocParser<'a> { }; let resolved_specifier = - self.resolve_dependency(src.as_ref(), referrer)?; + self.resolve_dependency(&src.to_str_lossy(), referrer)?; imports.push(Import { imported_name: imported_name.into_boxed_str(), @@ -934,11 +933,7 @@ impl<'a> DocParser<'a> { // declared classes cannot have decorators, so we ignore that return let (mut class_def, _) = super::class::get_doc_for_class_decl(module_info, class_decl); - self.apply_heritage_member_docs( - module_info, - &class_decl.class, - &mut class_def, - ); + self.apply_heritage_member_docs(module_info, class_decl, &mut class_def); let location = get_location(module_info, full_range.start); Some(Declaration::class( location, @@ -1054,7 +1049,7 @@ impl<'a> DocParser<'a> { d.maybe_node().and_then(|n| match n { SymbolNodeRef::ExportDecl(export_decl, _) => { match &export_decl.declaration { - Some(OxcDeclaration::TSModuleDeclaration(n)) => Some(&**n), + OxcDeclaration::TSNamespaceDeclaration(n) => Some(&**n), _ => None, } } @@ -1068,10 +1063,6 @@ impl<'a> DocParser<'a> { return None; // we already analyzed this module } - let _namespace_name = match &ts_module.id { - TSModuleDeclarationName::Identifier(ident) => ident.name.to_string(), - TSModuleDeclarationName::StringLiteral(str_) => str_.value.to_string(), - }; let mut elements = Vec::new(); let mut handled_symbols = HashSet::new(); @@ -1204,14 +1195,7 @@ impl<'a> DocParser<'a> { SymbolNodeRef::TsEnum(n) => Some(n.id.name.to_string()), SymbolNodeRef::TsInterface(n) => Some(n.id.name.to_string()), SymbolNodeRef::TsTypeAlias(n) => Some(n.id.name.to_string()), - SymbolNodeRef::TsNamespace(n) => match &n.id { - TSModuleDeclarationName::Identifier(ident) => { - Some(ident.name.to_string()) - } - TSModuleDeclarationName::StringLiteral(s) => { - Some(s.value.to_string()) - } - }, + SymbolNodeRef::TsNamespace(n) => Some(n.id.name.to_string()), SymbolNodeRef::Var(_, _, ident) => Some(ident.name.to_string()), SymbolNodeRef::ExportDefaultDecl(_) => { Some("default".to_string()) @@ -1423,7 +1407,7 @@ impl<'a> DocParser<'a> { .filter_map(|node| { let specifier = self .resolve_dependency( - &node.src.value.to_string_lossy(), + &node.source.value.to_string_lossy(), module_info.specifier(), ) .ok()?; @@ -1963,26 +1947,9 @@ impl<'a> DocParser<'a> { fn get_declare_for_export_decl_declaration( &self, - export_decl: &ExportNamedDeclaration, + export_decl: &ExportDeclaration, ) -> bool { - match &export_decl.declaration { - Some(OxcDeclaration::ClassDeclaration(class_decl)) => class_decl.declare, - Some(OxcDeclaration::FunctionDeclaration(fn_decl)) => fn_decl.declare, - Some(OxcDeclaration::TSEnumDeclaration(ts_enum_decl)) => { - ts_enum_decl.declare - } - Some(OxcDeclaration::TSInterfaceDeclaration(ts_interface_decl)) => { - ts_interface_decl.declare - } - Some(OxcDeclaration::TSModuleDeclaration(ts_module_decl)) => { - ts_module_decl.declare - } - Some(OxcDeclaration::TSTypeAliasDeclaration(ts_type_alias_decl)) => { - ts_type_alias_decl.declare - } - Some(OxcDeclaration::VariableDeclaration(var_decl)) => var_decl.declare, - _ => false, - } + export_decl.declaration.declare() } fn resolve_dependency( @@ -2075,13 +2042,12 @@ fn collect_shadowed_export_targets( else { continue; }; - targets - .entry(export_name) - .or_default() - .push(ShadowedExportTarget::SwcId(identifier_reference_to_id( + targets.entry(export_name).or_default().push( + ShadowedExportTarget::SwcId(identifier_reference_to_id( module_info, orig, - ))); + )), + ); } } Statement::ExportFromDeclaration(named_export) => { @@ -2133,8 +2099,9 @@ impl DocParser<'_> { match init { Expression::Identifier(init_ident) => { - let symbol = module_info - .symbol_from_swc(&identifier_reference_to_id(module_info, init_ident))?; + let symbol = module_info.symbol_from_swc( + &identifier_reference_to_id(module_info, init_ident), + )?; for decl in symbol.decls() { let Some(node) = decl.maybe_node() else { continue; @@ -2200,8 +2167,9 @@ impl DocParser<'_> { return None; }; let prop_name = member.property.name.as_str(); - let symbol = module_info - .symbol_from_swc(&identifier_reference_to_id(module_info, obj_ident))?; + let symbol = module_info.symbol_from_swc( + &identifier_reference_to_id(module_info, obj_ident), + )?; for decl in symbol.decls() { let Some(node) = decl.maybe_node() else { continue; @@ -2264,7 +2232,11 @@ fn decl_from_expr( .map(|id| id.name.to_string().into_boxed_str()); let (mut class_def, decorator_js_doc) = crate::class::class_to_class_def(module_info, class_expr, def_name); - parser.apply_heritage_member_docs(module_info, class_expr, &mut class_def); + parser.apply_heritage_member_docs( + module_info, + class_expr, + &mut class_def, + ); let js_doc = if js_doc.is_empty() { decorator_js_doc } else { diff --git a/src/ts_type.rs b/src/ts_type.rs index 663c793f3..2924e6e05 100644 --- a/src/ts_type.rs +++ b/src/ts_type.rs @@ -7,7 +7,6 @@ use crate::display::display_computed; use crate::display::display_method; use crate::display::display_optional; use crate::display::display_readonly; -use crate::interface::expr_to_name; use crate::node::Symbol; use crate::params::ParamPatternDef; use crate::params::formal_params_to_param_defs; @@ -19,6 +18,7 @@ use crate::util::swc::is_false; use crate::util::swc::js_doc_for_range; use crate::util::types::MethodKind; use crate::util::types::VarDeclKind; +use deno_ast::JSStrExt; use crate::function::FunctionDef; use crate::js_doc::JsDoc; @@ -106,7 +106,7 @@ impl TsTypeDef { match &other.literal { TSLiteral::NumericLiteral(num) => TsTypeDef::number_literal(num), TSLiteral::StringLiteral(str_) => { - TsTypeDef::string_value(str_.value.to_string()) + TsTypeDef::string_value(str_.value.to_string_lossy()) } TSLiteral::TemplateLiteral(tpl) => TsTypeDef::tpl_literal( tpl @@ -357,7 +357,7 @@ impl TsTypeDef { module_info: &EsModuleInfo, other: &TSInterfaceHeritage, ) -> Self { - let type_name = expr_to_name(&other.expression); + let type_name = ts_type_name_to_name(&other.type_name); let type_params = if let Some(type_params_inst) = &other.type_arguments { let ts_type_defs = type_params_inst @@ -371,7 +371,7 @@ impl TsTypeDef { None }; - let resolution = expr_root_ident(&other.expression) + let resolution = ts_type_name_root_ident(&other.type_name) .and_then(|i| resolve_type_ref(module_info, i)); TsTypeDef { @@ -452,7 +452,7 @@ impl TsTypeDef { let name = ts_method_sig .key .static_name() - .map(|name| name.to_string()) + .map(|name| name.as_js_str().to_string_lossy()) .unwrap_or_else(|| "[UNSUPPORTED]".to_string()); let location = get_location(module_info, ts_method_sig.span.start); let method_def = MethodDef { @@ -474,7 +474,7 @@ impl TsTypeDef { let name = ts_prop_sig .key .static_name() - .map(|name| name.to_string()) + .map(|name| name.as_js_str().to_string_lossy()) .unwrap_or_else(|| "[UNSUPPORTED]".to_string()); let ts_type = ts_prop_sig @@ -527,9 +527,8 @@ impl TsTypeDef { TSSignature::TSIndexSignature(ts_index_sig) => { let js_doc = js_doc_for_range(module_info, ts_index_sig.span) .unwrap_or_default(); - let params = ts_index_sig - .parameters - .iter() + let params = [&ts_index_sig.parameter] + .into_iter() .map(|param| { let ts_type = Some(TsTypeDef::new( module_info, @@ -650,7 +649,7 @@ impl TsTypeDef { }; let import_type_def = TsImportTypeDef { - specifier: other.source.value.to_string(), + specifier: other.source.value.to_string_lossy(), qualifier: other .qualifier .as_ref() @@ -860,7 +859,7 @@ fn ts_type_name_root_ident<'a>( fn ts_type_query_expr_name_to_name(expr_name: &TSTypeQueryExprName) -> String { match expr_name { TSTypeQueryExprName::TSImportType(import_type) => { - import_type.source.value.to_string() + import_type.source.value.to_string_lossy() } TSTypeQueryExprName::IdentifierReference(ident) => ident.name.to_string(), TSTypeQueryExprName::QualifiedName(qualified) => { @@ -896,21 +895,6 @@ fn ts_type_predicate_name_to_this_or_ident( } } -fn expr_root_ident<'a>( - expr: &'a Expression<'a>, -) -> Option<&'a IdentifierReference<'a>> { - match expr { - Expression::Identifier(ident) => Some(ident), - Expression::StaticMemberExpression(member_expr) => { - expr_root_ident(&member_expr.object) - } - Expression::ComputedMemberExpression(member_expr) => { - expr_root_ident(&member_expr.object) - } - _ => None, - } -} - fn resolve_type_ref( module_info: &EsModuleInfo, ident: &IdentifierReference, @@ -982,10 +966,11 @@ fn type_param_declaring_info( TypeParamDeclaringKind::TypeAlias, ) } - Statement::ExportNamedDeclaration(export) => { - export.declaration.as_ref().and_then(|decl| { - declaration_type_param_declaring_info(decl, type_param_span) - }) + Statement::ExportDeclaration(export) => { + declaration_type_param_declaring_info( + &export.declaration, + type_param_span, + ) } Statement::ExportDefaultDeclaration(export) => { export_default_type_param_declaring_info(export, type_param_span) @@ -1924,7 +1909,7 @@ impl TsTypeDef { } pub fn string_literal(str_node: &StringLiteral) -> Self { - Self::string_value(str_node.value.to_string()) + Self::string_value(str_node.value.to_string_lossy()) } pub fn string_value(value: String) -> Self { @@ -2266,7 +2251,8 @@ pub(crate) fn infer_ts_type_from_expr( | Expression::TaggedTemplateExpression(_) | Expression::ClassExpression(_) | Expression::YieldExpression(_) - | Expression::MetaProperty(_) + | Expression::ImportMeta(_) + | Expression::NewTarget(_) | Expression::JSXElement(_) | Expression::JSXFragment(_) | Expression::TSInstantiationExpression(_) @@ -2534,7 +2520,7 @@ fn infer_ts_type_from_obj_inner( let name = prop .key .static_name() - .map(|name| name.to_string()) + .map(|name| name.as_js_str().to_string_lossy()) .unwrap_or_else(|| "[UNSUPPORTED]".to_string()); properties.push(PropertyDef { name, @@ -2675,11 +2661,11 @@ impl Display for TsTypeDef { write!( f, "{} {} {} ? {} : {}", - &*conditional.check_type, + *conditional.check_type, colors::magenta("extends"), - &*conditional.extends_type, - &*conditional.true_type, - &*conditional.false_type + *conditional.extends_type, + *conditional.true_type, + *conditional.false_type ) } TsTypeDefKind::Infer(infer) => { @@ -2705,14 +2691,14 @@ impl Display for TsTypeDef { "" }), SliceDisplayer::new(&fn_or_constructor.params, ", ", false), - &fn_or_constructor.ts_type, + fn_or_constructor.ts_type, ) } TsTypeDefKind::IndexedAccess(indexed_access) => { write!( f, "{}[{}]", - &*indexed_access.obj_type, &*indexed_access.index_type + *indexed_access.obj_type, *indexed_access.index_type ) } TsTypeDefKind::Intersection(intersection) => { @@ -2823,7 +2809,7 @@ impl Display for TsTypeDef { ) } TsTypeDefKind::TypeOperator(type_operator) => { - write!(f, "{} {}", type_operator.operator, &type_operator.ts_type) + write!(f, "{} {}", type_operator.operator, type_operator.ts_type) } TsTypeDefKind::TypeQuery(type_query) => { write!(f, "typeof {}", type_query) diff --git a/src/util/swc.rs b/src/util/swc.rs index 445cca8c5..e5e53f60c 100644 --- a/src/util/swc.rs +++ b/src/util/swc.rs @@ -1,5 +1,6 @@ // Copyright 2018-2024 the Deno authors. All rights reserved. MIT license. +use deno_ast::JSStrExt; use deno_ast::SourceTextInfo; use deno_ast::oxc::ast::ast::Comment; use deno_ast::oxc::ast::ast::ModuleExportName; @@ -140,7 +141,7 @@ pub fn module_export_name_value( match module_export_name { ModuleExportName::IdentifierName(ident) => ident.name.to_string(), ModuleExportName::IdentifierReference(ident) => ident.name.to_string(), - ModuleExportName::StringLiteral(str) => str.value.to_string(), + ModuleExportName::StringLiteral(str) => str.value.to_string_lossy(), } } diff --git a/src/visibility.rs b/src/visibility.rs index 3c7eb1a3c..98372306d 100644 --- a/src/visibility.rs +++ b/src/visibility.rs @@ -5,13 +5,16 @@ use crate::util::graph::resolve_deno_graph_module; use crate::util::symbol::get_module_info; use crate::util::symbol::symbol_has_ignorable_js_doc_tag; +use deno_ast::oxc::ast::ast::TSType; use deno_ast::oxc::span::Span; use deno_graph::ModuleGraph; use deno_graph::symbols::DefinitionPathNode; use deno_graph::symbols::DefinitionPathNodeResolved; +use deno_graph::symbols::ExportDeclRef; use deno_graph::symbols::ResolveDepsMode; use deno_graph::symbols::ResolvedSymbolDepEntry; use deno_graph::symbols::SymbolDecl; +use deno_graph::symbols::SymbolNodeRef; use deno_graph::symbols::UniqueSymbolId; use indexmap::IndexMap; use indexmap::IndexSet; @@ -26,6 +29,11 @@ pub struct SymbolDeclDeps { pub deps: IndexSet, /// If the path to this declaration had an ignorable js doc tag. pub had_ignorable_tag: bool, + /// If this declaration is a type alias that is just another name for the + /// referenced type (e.g. `export type A = B`). In that case the referenced + /// type is effectively re-exported through the alias, so it should not be + /// reported as a private type referenced from the public API. + pub is_alias_reexport: bool, } #[derive(Default, Debug)] @@ -46,6 +54,7 @@ impl SymbolDeps { symbol_decl: &SymbolDecl, dep_id: UniqueSymbolId, had_ignorable_tag: bool, + is_alias_reexport: bool, ) { self .0 @@ -56,6 +65,7 @@ impl SymbolDeps { decl_range: symbol_decl.range, deps: IndexSet::from([dep_id]), had_ignorable_tag, + is_alias_reexport, }); } } @@ -115,6 +125,7 @@ impl SymbolVisibility { }), ); for (decl_symbol, decl, dep) in decl_deps { + let decl_is_alias_reexport = decl_is_pure_type_alias(decl); let mut path_has_ignorable_tag = symbol_has_ignorable_js_doc_tag(module_info, decl_symbol); let mut dep_symbol_ids = Vec::new(); @@ -166,6 +177,7 @@ impl SymbolVisibility { decl, dep_symbol_id, path_has_ignorable_tag, + decl_is_alias_reexport, ); } @@ -197,6 +209,23 @@ impl SymbolVisibility { } } +/// Whether a declaration is a type alias that merely gives another name to a +/// single referenced type, e.g. `type A = B`. Such an alias re-exposes the +/// referenced type as part of the public API, so a reference to it should not +/// be treated as referencing a private type. +fn decl_is_pure_type_alias(decl: &SymbolDecl) -> bool { + let type_alias = match decl.maybe_node() { + Some(SymbolNodeRef::TsTypeAlias(n)) => Some(n), + Some(SymbolNodeRef::ExportDecl(_, ExportDeclRef::TsTypeAlias(n))) => { + Some(n) + } + _ => None, + }; + type_alias.is_some_and( + |n| matches!(&n.type_annotation, TSType::TSTypeReference(r) if r.type_arguments.is_none()), + ) +} + fn analyze_root_exported_ids( graph: &ModuleGraph, root_symbol: &deno_graph::symbols::RootSymbol<'_>, diff --git a/tests/html_test.rs b/tests/html_test.rs index d7c957075..920e23a74 100644 --- a/tests/html_test.rs +++ b/tests/html_test.rs @@ -388,9 +388,11 @@ async fn html_doc_import_linking_internal_file() { ) .await; + let allocator = deno_ast::oxc::allocator::Allocator::default(); let parse_output = DocParser::new( &graph, &analyzer, + &allocator, &source_files, DocParserOptions { diagnostics: false, @@ -1303,9 +1305,11 @@ async fn parse_sources_multi(sources: &[(&str, &str)]) -> ParseOutput { ) .await; + let allocator = deno_ast::oxc::allocator::Allocator::default(); DocParser::new( &graph, &analyzer, + &allocator, &roots, DocParserOptions { private: false, diff --git a/tests/snapshots/html_test__html_doc_files_multiple-39.snap b/tests/snapshots/html_test__html_doc_files_multiple-39.snap index 2bebe8505..c33c1d6dc 100644 --- a/tests/snapshots/html_test__html_doc_files_multiple-39.snap +++ b/tests/snapshots/html_test__html_doc_files_multiple-39.snap @@ -145,7 +145,7 @@ expression: files.get(file_name).unwrap() -Hello.computedMethod(a: T extends () => infer R ? R : any): void +Hello.computedMethod(a: T extends () => infer R ? R : any): void

-a: T extends () => infer R ? R : any +a: T extends () => infer R ? R : any
diff --git a/tests/specs/infer_const_assertion_spread.txt b/tests/specs/infer_const_assertion_spread.txt index 67d258072..1abb8af65 100644 --- a/tests/specs/infer_const_assertion_spread.txt +++ b/tests/specs/infer_const_assertion_spread.txt @@ -28,12 +28,30 @@ export const CYCLE_A = [...CYCLE_B, "a"] as const; /** Mutually cyclic. */ export const CYCLE_B = [...CYCLE_A, "b"] as const; +# diagnostics +error[private-type-ref]: public type 'EXTENDED' references private type 'BASE' + --> /mod.ts:12:14 + | +12 | export const EXTENDED = [...BASE, "c"] as const; + | ^ + = hint: make the referenced type public or remove the reference + | +10 | const BASE = ["a", "b"] as const; + | - this is the referenced type + | + + info: to ensure documentation is complete all types that are exposed in the public API must be public + # output.txt Defined in file:///mod.ts:3:14 const ALL_UPDATE_TYPES: ("message" | "edited_message" | "chat_member" | "message_reaction" | "message_reaction_count")[] All update types. +Defined in file:///mod.ts:9:7 + +private const BASE: ("a" | "b")[] + Defined in file:///mod.ts:15:14 const COMBINED: (string | "y")[] @@ -555,6 +573,48 @@ const UNKNOWN: any[] } } ] + }, + { + "name": "BASE", + "declarations": [ + { + "location": { + "filename": "file:///mod.ts", + "line": 9, + "col": 6, + "byteIndex": 276 + }, + "declarationKind": "private", + "kind": "variable", + "def": { + "tsType": { + "kind": "array", + "value": { + "kind": "union", + "value": [ + { + "repr": "a", + "kind": "literal", + "value": { + "kind": "string", + "string": "a" + } + }, + { + "repr": "b", + "kind": "literal", + "value": { + "kind": "string", + "string": "b" + } + } + ] + } + }, + "kind": "const" + } + } + ] } ] } diff --git a/tests/specs/infer_object_literal.txt b/tests/specs/infer_object_literal.txt index d83e0adae..bbca8061e 100644 --- a/tests/specs/infer_object_literal.txt +++ b/tests/specs/infer_object_literal.txt @@ -29,7 +29,7 @@ error[missing-jsdoc]: exported symbol is missing JSDoc documentation # output.txt Defined in file:///mod.ts:3:14 -const a: { d(e: string): void; get h(): string; set h(value: string); [[t]](u: string): void; a: string; b: Map; c: { d: string; }; f: (g: string) => void; [[s]]: (number | string)[]; } +const a: { d(e: string): void; get h(): string; set h(value: string); [t](u: string): void; a: string; b: Map; c: { d: string; }; f: (g: string) => void; [s]: (number | string)[]; } # output.json @@ -118,7 +118,7 @@ const a: { d(e: string): void; get h(): string; set h(value: string); [[t]](u: s ] }, { - "name": "[t]", + "name": "t", "kind": "method", "location": { "filename": "file:///mod.ts", @@ -255,7 +255,7 @@ const a: { d(e: string): void; get h(): string; set h(value: string); [[t]](u: s } }, { - "name": "[s]", + "name": "s", "location": { "filename": "file:///mod.ts", "line": 16, diff --git a/tests/specs/reexport_namespace_keeps_location.txt b/tests/specs/reexport_namespace_keeps_location.txt index b26af48ed..8716f8c05 100644 --- a/tests/specs/reexport_namespace_keeps_location.txt +++ b/tests/specs/reexport_namespace_keeps_location.txt @@ -10,7 +10,7 @@ export namespace Real { export * as Middle from "./middle.ts"; # output.txt -Defined in file:///mod.ts:1:8 +Defined in file:///mod.ts:1:1 namespace Middle re-export of middle @@ -29,8 +29,8 @@ namespace Middle "location": { "filename": "file:///mod.ts", "line": 1, - "col": 7, - "byteIndex": 34 + "col": 0, + "byteIndex": 27 }, "declarationKind": "export", "jsDoc": { diff --git a/tests/specs/reexport_nested_namespace.txt b/tests/specs/reexport_nested_namespace.txt index a63fef7a4..4c13186d7 100644 --- a/tests/specs/reexport_nested_namespace.txt +++ b/tests/specs/reexport_nested_namespace.txt @@ -13,7 +13,7 @@ export * as Inner from "./inner.ts"; export * as Middle from "./middle.ts"; # output.txt -Defined in file:///mod.ts:1:8 +Defined in file:///mod.ts:1:1 namespace Middle re-export of middle @@ -34,8 +34,8 @@ namespace Middle "location": { "filename": "file:///mod.ts", "line": 1, - "col": 7, - "byteIndex": 34 + "col": 0, + "byteIndex": 27 }, "declarationKind": "export", "jsDoc": { @@ -78,8 +78,8 @@ namespace Middle "location": { "filename": "file:///middle.ts", "line": 3, - "col": 7, - "byteIndex": 89 + "col": 0, + "byteIndex": 82 }, "declarationKind": "export", "jsDoc": { From 0445416e7060307e6ffe325227e0f9bdbcb181d5 Mon Sep 17 00:00:00 2001 From: Leo Kettmeir Date: Mon, 26 Oct 2026 02:13:41 +0900 Subject: [PATCH 6/9] fix: restore main's documented output in the oxc port - resolve_type_ref: a reference that semantic analysis bound to a non-module-level symbol (type parameter, mapped type parameter) or that was never analyzed (JSDoc type strings) is a typeParam resolution, and an `infer X` binding is unresolved, matching swc's resolver behavior - JSDoc types keep their resolutions (clear_resolutions removed) - computed property keys keep their source text including brackets - destructured bindings get their types from the referenced variable's annotation (scope-aware lookup) and inferred initializer types - restore main's test expectations --- src/js_doc.rs | 5 +- src/params.rs | 12 +- src/ts_type.rs | 241 ++++-------------- src/variable.rs | 21 +- tests/diff_specs/function_throws_change.txt | 20 +- ...html_test__html_doc_files_multiple-39.snap | 4 +- tests/snapshots/html_test__symbol_group.snap | 4 +- tests/specs/export_const_destructured.txt | 28 +- tests/specs/export_namespace.txt | 4 +- tests/specs/indented_with_tabs.txt | 4 +- tests/specs/infer_const_assertion_spread.txt | 60 ----- tests/specs/infer_object_literal.txt | 6 +- tests/specs/jsdoc_throws_nested_type.txt | 15 +- tests/specs/jsdoc_types.txt | 50 +++- tests/specs/mapped_types.txt | 5 +- tests/specs/private_type_class_property.txt | 190 +++++++++++++- tests/specs/re_export_all_as_with_jsdoc.txt | 6 +- .../reexport_namespace_keeps_location.txt | 6 +- tests/specs/reexport_nested_namespace.txt | 10 +- tests/specs/structured_jsdoc.txt | 5 +- tests/specs/type_literal_mapped_type.txt | 5 +- 21 files changed, 361 insertions(+), 340 deletions(-) diff --git a/src/js_doc.rs b/src/js_doc.rs index a6b097b0b..3fd928f20 100644 --- a/src/js_doc.rs +++ b/src/js_doc.rs @@ -111,9 +111,7 @@ pub fn parse_jsdoc_type( type_alias, ) = type_alias { - let mut ts_type = TsTypeDef::new(module_info, &type_alias.type_annotation); - ts_type.clear_resolutions(); - Some(ts_type) + Some(TsTypeDef::new(module_info, &type_alias.type_annotation)) } else { None } @@ -656,6 +654,7 @@ mod tests { ) -> serde_json::Value { let mut value = serde_json::json!({ "typeName": name, + "resolution": { "kind": "typeParam" }, }); if let Some(tp) = type_params { value["typeParams"] = serde_json::json!(tp); diff --git a/src/params.rs b/src/params.rs index 0232aab03..671f0bae7 100644 --- a/src/params.rs +++ b/src/params.rs @@ -417,15 +417,13 @@ pub fn prop_name_to_string( PropertyKey::PrivateIdentifier(ident) => { format!("#{}", ident.name) } - PropertyKey::StaticMemberExpression(member) => { - let left: String = crate::interface::expr_to_name(&member.object); - let right = member.property.name.to_string(); - format!("[{}.{}]", left, right) - } + // computed keys: the source text of the key including its brackets + // (swc's `ComputedPropName` span covered the brackets) _ => { let span = prop_key.span(); - module_info.source_text()[span.start as usize..span.end as usize] - .to_string() + let text = + &module_info.source_text()[span.start as usize..span.end as usize]; + format!("[{}]", text) } } } diff --git a/src/ts_type.rs b/src/ts_type.rs index 2924e6e05..54d205b57 100644 --- a/src/ts_type.rs +++ b/src/ts_type.rs @@ -899,37 +899,61 @@ fn resolve_type_ref( module_info: &EsModuleInfo, ident: &IdentifierReference, ) -> Option { - let reference_symbol_id = ident - .reference_id - .get() - .zip(module_info.scoping()) - .and_then(|(reference_id, scoping)| { - scoping.get_reference(reference_id).symbol_id() - }); let id = identifier_reference_to_id(module_info, ident); if let Some(symbol) = module_info.symbol_from_swc(&id) { - if let Some(file_dep) = symbol.file_dep() { + return if let Some(file_dep) = symbol.file_dep() { Some(TypeRefResolution::Import { specifier: file_dep.specifier.clone(), name: file_dep.name.maybe_name().map(|s| s.to_string()), }) } else { Some(TypeRefResolution::Local) - } - } else if let Some((declaring_name, declaring_kind)) = reference_symbol_id - .and_then(|symbol_id| { - module_info.scoping().and_then(|scoping| { - type_param_declaring_info(module_info, scoping.symbol_span(symbol_id)) - }) - }) - { - Some(TypeRefResolution::TypeParam { - declaring_name, - declaring_kind, - }) - } else { - None + }; } + // A reference that semantic analysis resolved to nothing is an unresolved + // identifier: a global type (Promise, Array, etc.) or truly unresolvable. + let reference_symbol_id = + match (ident.reference_id.get(), module_info.scoping()) { + (Some(reference_id), Some(scoping)) => { + match scoping.get_reference(reference_id).symbol_id() { + // swc's resolver did not bind `infer X` type parameters, so a + // reference to one was unresolved + Some(symbol_id) + if is_infer_type_param(module_info, scoping, symbol_id) => + { + return None; + } + Some(symbol_id) => Some(symbol_id), + None => return None, + } + } + // not semantically analyzed (e.g. a type parsed from a JSDoc tag) + _ => None, + }; + // The identifier resolved to a binding that is not a module-level symbol: + // it's a type parameter or other locally-scoped binding. + let origin = reference_symbol_id.and_then(|symbol_id| { + module_info.scoping().and_then(|scoping| { + type_param_declaring_info(module_info, scoping.symbol_span(symbol_id)) + }) + }); + Some(TypeRefResolution::TypeParam { + declaring_name: origin.as_ref().and_then(|o| o.0.clone()), + declaring_kind: origin.as_ref().and_then(|o| o.1.clone()), + }) +} + +/// Whether the symbol is a type parameter introduced by an `infer X` type. +fn is_infer_type_param( + module_info: &EsModuleInfo, + scoping: &deno_ast::oxc::semantic::Scoping, + symbol_id: deno_ast::oxc::semantic::SymbolId, +) -> bool { + let span = scoping.symbol_span(symbol_id); + module_info + .source_text() + .get(..span.start as usize) + .is_some_and(|text| text.trim_end().ends_with("infer")) } fn type_param_declaring_info( @@ -1719,179 +1743,6 @@ impl Display for TsTypePredicateDef { } impl TsTypeDef { - pub(crate) fn clear_resolutions(&mut self) { - fn clear_type_param(type_param: &mut TsTypeParamDef) { - if let Some(constraint) = &mut type_param.constraint { - constraint.clear_resolutions(); - } - if let Some(default) = &mut type_param.default { - default.clear_resolutions(); - } - } - - fn clear_param(param: &mut ParamDef) { - match &mut param.pattern { - ParamPatternDef::Array { elements, .. } => { - for element in elements.iter_mut().flatten() { - clear_param(element); - } - } - ParamPatternDef::Assign { left, .. } => clear_param(left), - ParamPatternDef::Object { props, .. } => { - for prop in props { - match prop { - crate::params::ObjectPatPropDef::KeyValue { value, .. } => { - clear_param(value); - } - crate::params::ObjectPatPropDef::Rest { arg } => { - clear_param(arg); - } - crate::params::ObjectPatPropDef::Assign { .. } => {} - } - } - } - ParamPatternDef::Rest { arg } => clear_param(arg), - ParamPatternDef::Identifier { .. } => {} - } - if let Some(ts_type) = &mut param.ts_type { - ts_type.clear_resolutions(); - } - } - - match &mut self.kind { - TsTypeDefKind::TypeRef(type_ref) => { - type_ref.resolution = None; - if let Some(type_params) = &mut type_ref.type_params { - for type_param in type_params.iter_mut() { - type_param.clear_resolutions(); - } - } - } - TsTypeDefKind::Literal(literal) => { - if let Some(ts_types) = &mut literal.ts_types { - for ts_type in ts_types { - ts_type.clear_resolutions(); - } - } - } - TsTypeDefKind::Union(types) - | TsTypeDefKind::Intersection(types) - | TsTypeDefKind::Tuple(types) => { - for ts_type in types { - ts_type.clear_resolutions(); - } - } - TsTypeDefKind::Array(ts_type) - | TsTypeDefKind::Parenthesized(ts_type) - | TsTypeDefKind::Rest(ts_type) - | TsTypeDefKind::Optional(ts_type) => ts_type.clear_resolutions(), - TsTypeDefKind::TypeOperator(type_operator) => { - type_operator.ts_type.clear_resolutions(); - } - TsTypeDefKind::FnOrConstructor(fn_or_constructor) => { - fn_or_constructor.ts_type.clear_resolutions(); - for param in &mut fn_or_constructor.params { - clear_param(param); - } - for type_param in &mut fn_or_constructor.type_params { - clear_type_param(type_param); - } - } - TsTypeDefKind::Conditional(conditional) => { - conditional.check_type.clear_resolutions(); - conditional.extends_type.clear_resolutions(); - conditional.true_type.clear_resolutions(); - conditional.false_type.clear_resolutions(); - } - TsTypeDefKind::Infer(infer) => { - clear_type_param(&mut infer.type_param); - } - TsTypeDefKind::IndexedAccess(indexed_access) => { - indexed_access.obj_type.clear_resolutions(); - indexed_access.index_type.clear_resolutions(); - } - TsTypeDefKind::Mapped(mapped) => { - clear_type_param(&mut mapped.type_param); - if let Some(name_type) = &mut mapped.name_type { - name_type.clear_resolutions(); - } - if let Some(ts_type) = &mut mapped.ts_type { - ts_type.clear_resolutions(); - } - } - TsTypeDefKind::TypeLiteral(type_literal) => { - for ctor in &mut type_literal.constructors { - for param in &mut ctor.params { - clear_param(param); - } - if let Some(return_type) = &mut ctor.return_type { - return_type.clear_resolutions(); - } - for type_param in &mut ctor.type_params { - clear_type_param(type_param); - } - } - for method in &mut type_literal.methods { - for param in &mut method.params { - clear_param(param); - } - if let Some(return_type) = &mut method.return_type { - return_type.clear_resolutions(); - } - for type_param in &mut method.type_params { - clear_type_param(type_param); - } - } - for property in &mut type_literal.properties { - for param in &mut property.params { - clear_param(param); - } - if let Some(ts_type) = &mut property.ts_type { - ts_type.clear_resolutions(); - } - for type_param in &mut property.type_params { - clear_type_param(type_param); - } - } - for call_signature in &mut type_literal.call_signatures { - for param in &mut call_signature.params { - clear_param(param); - } - if let Some(ts_type) = &mut call_signature.ts_type { - ts_type.clear_resolutions(); - } - for type_param in &mut call_signature.type_params { - clear_type_param(type_param); - } - } - for index_signature in &mut type_literal.index_signatures { - for param in &mut index_signature.params { - clear_param(param); - } - if let Some(ts_type) = &mut index_signature.ts_type { - ts_type.clear_resolutions(); - } - } - } - TsTypeDefKind::TypePredicate(type_predicate) => { - if let Some(ts_type) = &mut type_predicate.r#type { - ts_type.clear_resolutions(); - } - } - TsTypeDefKind::ImportType(import_type) => { - if let Some(type_params) = &mut import_type.type_params { - for type_param in type_params { - type_param.clear_resolutions(); - } - } - } - TsTypeDefKind::Keyword(_) - | TsTypeDefKind::TypeQuery(_) - | TsTypeDefKind::This - | TsTypeDefKind::Unsupported => {} - } - } - pub fn number_literal(num: &NumericLiteral) -> Self { Self::number_value(num.value) } diff --git a/src/variable.rs b/src/variable.rs index 99240b935..03ee50d54 100644 --- a/src/variable.rs +++ b/src/variable.rs @@ -44,32 +44,27 @@ pub fn get_docs_for_var_declarator( let explicit_ts_type = maybe_ts_type_ann .map(|def| TsTypeDef::new(module_info, &def.type_annotation)); - // Full inferred type (used only for simple identifier patterns, not - // destructured bindings). + // Full inferred type: the explicit annotation, the type of a referenced + // variable or the type inferred from the initializer. let maybe_ts_type = explicit_ts_type .clone() .or_else(|| { if let Some(ref_ident) = ref_ident { - let swc_id = (ref_ident.name.to_string(), 0usize); + let swc_id = + crate::ts_type::identifier_reference_to_id(module_info, ref_ident); module_info.symbol_from_swc(&swc_id).and_then(|symbol| { for decl in symbol.decls() { if let Some(SymbolNodeRef::Var(_, ref_var_declarator, _)) = decl.maybe_node() { + // only the explicit type annotation of the referenced variable + // is used; its initializer is not inferred from if let Some(type_ann) = &ref_var_declarator.type_annotation { return Some(TsTypeDef::new( module_info, &type_ann.type_annotation, )); } - let maybe_type_ann = infer_simple_ts_type_from_init( - module_info, - ref_var_declarator.init.as_ref(), - kind == VarDeclKind::Const, - ); - if let Some(type_ann) = maybe_type_ann { - return Some(type_ann); - } } } None @@ -98,14 +93,14 @@ pub fn get_docs_for_var_declarator( BindingPattern::ObjectPattern(obj) => get_vars_from_obj_destructuring( obj, kind, - explicit_ts_type.as_ref(), + maybe_ts_type.as_ref(), &mut items, module_info, ), BindingPattern::ArrayPattern(arr) => get_vars_from_array_destructuring( arr, kind, - explicit_ts_type.as_ref(), + maybe_ts_type.as_ref(), &mut items, module_info, ), diff --git a/tests/diff_specs/function_throws_change.txt b/tests/diff_specs/function_throws_change.txt index 32fed0513..5c64ab64c 100644 --- a/tests/diff_specs/function_throws_change.txt +++ b/tests/diff_specs/function_throws_change.txt @@ -32,7 +32,10 @@ export function foo(x: number): void {} "repr": "SyntaxError", "kind": "typeRef", "value": { - "typeName": "SyntaxError" + "typeName": "SyntaxError", + "resolution": { + "kind": "typeParam" + } } }, "doc": "bad syntax" @@ -45,7 +48,10 @@ export function foo(x: number): void {} "repr": "TypeError", "kind": "typeRef", "value": { - "typeName": "TypeError" + "typeName": "TypeError", + "resolution": { + "kind": "typeParam" + } } }, "doc": "wrong type" @@ -59,7 +65,10 @@ export function foo(x: number): void {} "repr": "RangeError", "kind": "typeRef", "value": { - "typeName": "RangeError" + "typeName": "RangeError", + "resolution": { + "kind": "typeParam" + } } }, "doc": "value out of range" @@ -70,7 +79,10 @@ export function foo(x: number): void {} "repr": "RangeError", "kind": "typeRef", "value": { - "typeName": "RangeError" + "typeName": "RangeError", + "resolution": { + "kind": "typeParam" + } } }, "doc": "updated message" diff --git a/tests/snapshots/html_test__html_doc_files_multiple-39.snap b/tests/snapshots/html_test__html_doc_files_multiple-39.snap index c33c1d6dc..2bebe8505 100644 --- a/tests/snapshots/html_test__html_doc_files_multiple-39.snap +++ b/tests/snapshots/html_test__html_doc_files_multiple-39.snap @@ -145,7 +145,7 @@ expression: files.get(file_name).unwrap() -Hello.computedMethod(a: T extends () => infer R ? R : any): void +Hello.computedMethod(a: T extends () => infer R ? R : any): void

-a: T extends () => infer R ? R : any +a: T extends () => infer R ? R : any
diff --git a/tests/snapshots/html_test__symbol_group.snap b/tests/snapshots/html_test__symbol_group.snap index 1fc344891..f97d3e36c 100644 --- a/tests/snapshots/html_test__symbol_group.snap +++ b/tests/snapshots/html_test__symbol_group.snap @@ -8412,7 +8412,7 @@ expression: files "id": "function_hello_computedmethod_0" }, "name": "Hello.computedMethod", - "summary": "(a: T extends () => infer R ? R : any): void", + "summary": "(a: T extends () => infer R ? R : any): void", "deprecated": null, "content": { "id": "", @@ -8434,7 +8434,7 @@ expression: files "name_prefix": null, "name": "a", "name_href": null, - "content": ": T extends () => infer R ? R : any", + "content": ": T extends () => infer R ? R : any", "anchor": { "id": "function_hello_computedmethod_0_parameter_a" }, diff --git a/tests/specs/export_const_destructured.txt b/tests/specs/export_const_destructured.txt index bec7d8f63..41bb6ac7d 100644 --- a/tests/specs/export_const_destructured.txt +++ b/tests/specs/export_const_destructured.txt @@ -24,26 +24,12 @@ error[missing-jsdoc]: exported symbol is missing JSDoc documentation | ^ -error[missing-explicit-type]: exported symbol is missing an explicit type annotation - --> /mod.ts:16:16 - | -16 | export const { f, g: h } = d; - | ^ - - error[missing-jsdoc]: exported symbol is missing JSDoc documentation --> /mod.ts:16:22 | 16 | export const { f, g: h } = d; | ^ - -error[missing-explicit-type]: exported symbol is missing an explicit type annotation - --> /mod.ts:16:22 - | -16 | export const { f, g: h } = d; - | ^ - # output.txt Defined in file:///mod.ts:5:3 @@ -57,11 +43,11 @@ const b: number Defined in file:///mod.ts:15:16 -const f +const f: string Defined in file:///mod.ts:15:22 -const h +const h: number # output.json @@ -132,6 +118,11 @@ const h "declarationKind": "export", "kind": "variable", "def": { + "tsType": { + "repr": "string", + "kind": "keyword", + "value": "string" + }, "kind": "const" } } @@ -150,6 +141,11 @@ const h "declarationKind": "export", "kind": "variable", "def": { + "tsType": { + "repr": "number", + "kind": "keyword", + "value": "number" + }, "kind": "const" } } diff --git a/tests/specs/export_namespace.txt b/tests/specs/export_namespace.txt index 8fda30d1c..cfa6f2d5d 100644 --- a/tests/specs/export_namespace.txt +++ b/tests/specs/export_namespace.txt @@ -202,8 +202,8 @@ namespace RootNs "location": { "filename": "file:///mod.ts", "line": 14, - "col": 24, - "byteIndex": 252 + "col": 7, + "byteIndex": 235 }, "declarationKind": "export", "kind": "namespace", diff --git a/tests/specs/indented_with_tabs.txt b/tests/specs/indented_with_tabs.txt index 16086fcaa..10bb32d4b 100644 --- a/tests/specs/indented_with_tabs.txt +++ b/tests/specs/indented_with_tabs.txt @@ -70,7 +70,7 @@ namespace Tabs "location": { "filename": "file:///mod.ts", "line": 15, - "col": 1, + "col": 2, "byteIndex": 126 }, "declarationKind": "export", @@ -88,7 +88,7 @@ namespace Tabs "location": { "filename": "file:///mod.ts", "line": 23, - "col": 2, + "col": 4, "byteIndex": 212 }, "tsType": { diff --git a/tests/specs/infer_const_assertion_spread.txt b/tests/specs/infer_const_assertion_spread.txt index 1abb8af65..67d258072 100644 --- a/tests/specs/infer_const_assertion_spread.txt +++ b/tests/specs/infer_const_assertion_spread.txt @@ -28,30 +28,12 @@ export const CYCLE_A = [...CYCLE_B, "a"] as const; /** Mutually cyclic. */ export const CYCLE_B = [...CYCLE_A, "b"] as const; -# diagnostics -error[private-type-ref]: public type 'EXTENDED' references private type 'BASE' - --> /mod.ts:12:14 - | -12 | export const EXTENDED = [...BASE, "c"] as const; - | ^ - = hint: make the referenced type public or remove the reference - | -10 | const BASE = ["a", "b"] as const; - | - this is the referenced type - | - - info: to ensure documentation is complete all types that are exposed in the public API must be public - # output.txt Defined in file:///mod.ts:3:14 const ALL_UPDATE_TYPES: ("message" | "edited_message" | "chat_member" | "message_reaction" | "message_reaction_count")[] All update types. -Defined in file:///mod.ts:9:7 - -private const BASE: ("a" | "b")[] - Defined in file:///mod.ts:15:14 const COMBINED: (string | "y")[] @@ -573,48 +555,6 @@ const UNKNOWN: any[] } } ] - }, - { - "name": "BASE", - "declarations": [ - { - "location": { - "filename": "file:///mod.ts", - "line": 9, - "col": 6, - "byteIndex": 276 - }, - "declarationKind": "private", - "kind": "variable", - "def": { - "tsType": { - "kind": "array", - "value": { - "kind": "union", - "value": [ - { - "repr": "a", - "kind": "literal", - "value": { - "kind": "string", - "string": "a" - } - }, - { - "repr": "b", - "kind": "literal", - "value": { - "kind": "string", - "string": "b" - } - } - ] - } - }, - "kind": "const" - } - } - ] } ] } diff --git a/tests/specs/infer_object_literal.txt b/tests/specs/infer_object_literal.txt index bbca8061e..d83e0adae 100644 --- a/tests/specs/infer_object_literal.txt +++ b/tests/specs/infer_object_literal.txt @@ -29,7 +29,7 @@ error[missing-jsdoc]: exported symbol is missing JSDoc documentation # output.txt Defined in file:///mod.ts:3:14 -const a: { d(e: string): void; get h(): string; set h(value: string); [t](u: string): void; a: string; b: Map; c: { d: string; }; f: (g: string) => void; [s]: (number | string)[]; } +const a: { d(e: string): void; get h(): string; set h(value: string); [[t]](u: string): void; a: string; b: Map; c: { d: string; }; f: (g: string) => void; [[s]]: (number | string)[]; } # output.json @@ -118,7 +118,7 @@ const a: { d(e: string): void; get h(): string; set h(value: string); [t](u: str ] }, { - "name": "t", + "name": "[t]", "kind": "method", "location": { "filename": "file:///mod.ts", @@ -255,7 +255,7 @@ const a: { d(e: string): void; get h(): string; set h(value: string); [t](u: str } }, { - "name": "s", + "name": "[s]", "location": { "filename": "file:///mod.ts", "line": 16, diff --git a/tests/specs/jsdoc_throws_nested_type.txt b/tests/specs/jsdoc_throws_nested_type.txt index 4302b87f5..0ef9a242f 100644 --- a/tests/specs/jsdoc_throws_nested_type.txt +++ b/tests/specs/jsdoc_throws_nested_type.txt @@ -52,7 +52,10 @@ function deadline(): void "repr": "DOMException", "kind": "typeRef", "value": { - "typeName": "DOMException" + "typeName": "DOMException", + "resolution": { + "kind": "typeParam" + } } }, { @@ -93,7 +96,10 @@ function deadline(): void "repr": "DOMException", "kind": "typeRef", "value": { - "typeName": "DOMException" + "typeName": "DOMException", + "resolution": { + "kind": "typeParam" + } } }, { @@ -153,7 +159,10 @@ function deadline(): void } } ], - "typeName": "Promise" + "typeName": "Promise", + "resolution": { + "kind": "typeParam" + } } }, "doc": "the resolved value" diff --git a/tests/specs/jsdoc_types.txt b/tests/specs/jsdoc_types.txt index 653d037e4..c9474a520 100644 --- a/tests/specs/jsdoc_types.txt +++ b/tests/specs/jsdoc_types.txt @@ -205,11 +205,17 @@ class StringList "value": "number" } ], - "typeName": "Set" + "typeName": "Set", + "resolution": { + "kind": "typeParam" + } } } ], - "typeName": "Map" + "typeName": "Map", + "resolution": { + "kind": "typeParam" + } } }, "doc": "the lookup map" @@ -314,7 +320,10 @@ class StringList "value": "unknown" } ], - "typeName": "Record" + "typeName": "Record", + "resolution": { + "kind": "typeParam" + } } }, "doc": "an object" @@ -337,11 +346,17 @@ class StringList "value": "string" } ], - "typeName": "Array" + "typeName": "Array", + "resolution": { + "kind": "typeParam" + } } } ], - "typeName": "Promise" + "typeName": "Promise", + "resolution": { + "kind": "typeParam" + } } }, "doc": "the results" @@ -352,7 +367,10 @@ class StringList "repr": "RangeError", "kind": "typeRef", "value": { - "typeName": "RangeError" + "typeName": "RangeError", + "resolution": { + "kind": "typeParam" + } } }, "doc": "if out of range" @@ -363,7 +381,10 @@ class StringList "repr": "TypeError", "kind": "typeRef", "value": { - "typeName": "TypeError" + "typeName": "TypeError", + "resolution": { + "kind": "typeParam" + } } }, "doc": "if wrong type" @@ -563,7 +584,10 @@ class StringList "value": "string" } ], - "typeName": "ReadonlyArray" + "typeName": "ReadonlyArray", + "resolution": { + "kind": "typeParam" + } } } } @@ -639,7 +663,10 @@ class StringList "repr": "HTMLElement", "kind": "typeRef", "value": { - "typeName": "HTMLElement" + "typeName": "HTMLElement", + "resolution": { + "kind": "typeParam" + } } } } @@ -684,7 +711,10 @@ class StringList "value": "string" } ], - "typeName": "Array" + "typeName": "Array", + "resolution": { + "kind": "typeParam" + } } } } diff --git a/tests/specs/mapped_types.txt b/tests/specs/mapped_types.txt index 8ccd77029..61a5b6d0e 100644 --- a/tests/specs/mapped_types.txt +++ b/tests/specs/mapped_types.txt @@ -84,7 +84,10 @@ type MappedTypeWithNewProperties = readonly [Properties in keyof Type as N "repr": "Properties", "kind": "typeRef", "value": { - "typeName": "Properties" + "typeName": "Properties", + "resolution": { + "kind": "typeParam" + } } } } diff --git a/tests/specs/private_type_class_property.txt b/tests/specs/private_type_class_property.txt index bf863b3a0..b7e68b435 100644 --- a/tests/specs/private_type_class_property.txt +++ b/tests/specs/private_type_class_property.txt @@ -30,20 +30,48 @@ error[private-type-ref]: public type 'PrivatePropThroughNamespaceRef' references info: to ensure documentation is complete all types that are exposed in the public API must be public -error[private-type-ref]: public type 'PrivatePropThroughNamespaceRef' references private type 'MyNamespace.Export' +error[private-type-ref]: public type 'PrivatePropThroughNamespaceRef' references private type 'MyNamespace2' --> /mod.ts:1:1 | 1 | export type PrivatePropThroughNamespaceRef = typeof MyNamespace.Export.someProp; | ^ = hint: make the referenced type public or remove the reference | -4 | export import Export = MyNamespace2.MyClass; - | - this is the referenced type +7 | namespace MyNamespace2 { + | - this is the referenced type | info: to ensure documentation is complete all types that are exposed in the public API must be public +error[private-type-ref]: public type 'PrivatePropThroughNamespaceRef' references private type 'MyNamespace3' + --> /mod.ts:1:1 + | + 1 | export type PrivatePropThroughNamespaceRef = typeof MyNamespace.Export.someProp; + | ^ + = hint: make the referenced type public or remove the reference + | +11 | namespace MyNamespace3 { + | - this is the referenced type + | + + info: to ensure documentation is complete all types that are exposed in the public API must be public + + +error[private-type-ref]: public type 'PrivatePropThroughNamespaceRef' references private type 'MyNamespace3.MyClass' + --> /mod.ts:1:1 + | + 1 | export type PrivatePropThroughNamespaceRef = typeof MyNamespace.Export.someProp; + | ^ + = hint: make the referenced type public or remove the reference + | +12 | export class MyClass { + | - this is the referenced type + | + + info: to ensure documentation is complete all types that are exposed in the public API must be public + + error[missing-jsdoc]: exported symbol is missing JSDoc documentation --> /mod.ts:1:13 | @@ -59,6 +87,19 @@ Defined in file:///mod.ts:2:1 private namespace MyNamespace + class Export + +Defined in file:///mod.ts:6:1 + +private namespace MyNamespace2 + + class MyClass + +Defined in file:///mod.ts:10:1 + +private namespace MyNamespace3 + + class MyClass # output.json @@ -99,7 +140,148 @@ private namespace MyNamespace "declarationKind": "private", "kind": "namespace", "def": { - "elements": [] + "elements": [ + { + "name": "Export", + "declarations": [ + { + "location": { + "filename": "file:///mod.ts", + "line": 11, + "col": 2, + "byteIndex": 259 + }, + "declarationKind": "export", + "kind": "class", + "def": { + "properties": [ + { + "tsType": { + "repr": "string", + "kind": "keyword", + "value": "string" + }, + "isStatic": true, + "name": "someProp", + "location": { + "filename": "file:///mod.ts", + "line": 12, + "col": 4, + "byteIndex": 286 + } + } + ] + } + } + ] + } + ] + } + } + ] + }, + { + "name": "MyNamespace2", + "declarations": [ + { + "location": { + "filename": "file:///mod.ts", + "line": 6, + "col": 0, + "byteIndex": 156 + }, + "declarationKind": "private", + "kind": "namespace", + "def": { + "elements": [ + { + "name": "MyClass", + "declarations": [ + { + "location": { + "filename": "file:///mod.ts", + "line": 11, + "col": 2, + "byteIndex": 259 + }, + "declarationKind": "export", + "kind": "class", + "def": { + "properties": [ + { + "tsType": { + "repr": "string", + "kind": "keyword", + "value": "string" + }, + "isStatic": true, + "name": "someProp", + "location": { + "filename": "file:///mod.ts", + "line": 12, + "col": 4, + "byteIndex": 286 + } + } + ] + } + } + ] + } + ] + } + } + ] + }, + { + "name": "MyNamespace3", + "declarations": [ + { + "location": { + "filename": "file:///mod.ts", + "line": 10, + "col": 0, + "byteIndex": 232 + }, + "declarationKind": "private", + "kind": "namespace", + "def": { + "elements": [ + { + "name": "MyClass", + "declarations": [ + { + "location": { + "filename": "file:///mod.ts", + "line": 11, + "col": 2, + "byteIndex": 259 + }, + "declarationKind": "export", + "kind": "class", + "def": { + "properties": [ + { + "tsType": { + "repr": "string", + "kind": "keyword", + "value": "string" + }, + "isStatic": true, + "name": "someProp", + "location": { + "filename": "file:///mod.ts", + "line": 12, + "col": 4, + "byteIndex": 286 + } + } + ] + } + } + ] + } + ] } } ] diff --git a/tests/specs/re_export_all_as_with_jsdoc.txt b/tests/specs/re_export_all_as_with_jsdoc.txt index 9ba35bac1..f8ab324cf 100644 --- a/tests/specs/re_export_all_as_with_jsdoc.txt +++ b/tests/specs/re_export_all_as_with_jsdoc.txt @@ -7,7 +7,7 @@ export function foo(): void {} export * as other from "./other.ts"; # output.txt -Defined in file:///mod.ts:1:1 +Defined in file:///mod.ts:1:8 namespace other Re-exports of other. @@ -26,8 +26,8 @@ namespace other "location": { "filename": "file:///mod.ts", "line": 1, - "col": 0, - "byteIndex": 28 + "col": 7, + "byteIndex": 35 }, "declarationKind": "export", "jsDoc": { diff --git a/tests/specs/reexport_namespace_keeps_location.txt b/tests/specs/reexport_namespace_keeps_location.txt index 8716f8c05..b26af48ed 100644 --- a/tests/specs/reexport_namespace_keeps_location.txt +++ b/tests/specs/reexport_namespace_keeps_location.txt @@ -10,7 +10,7 @@ export namespace Real { export * as Middle from "./middle.ts"; # output.txt -Defined in file:///mod.ts:1:1 +Defined in file:///mod.ts:1:8 namespace Middle re-export of middle @@ -29,8 +29,8 @@ namespace Middle "location": { "filename": "file:///mod.ts", "line": 1, - "col": 0, - "byteIndex": 27 + "col": 7, + "byteIndex": 34 }, "declarationKind": "export", "jsDoc": { diff --git a/tests/specs/reexport_nested_namespace.txt b/tests/specs/reexport_nested_namespace.txt index 4c13186d7..a63fef7a4 100644 --- a/tests/specs/reexport_nested_namespace.txt +++ b/tests/specs/reexport_nested_namespace.txt @@ -13,7 +13,7 @@ export * as Inner from "./inner.ts"; export * as Middle from "./middle.ts"; # output.txt -Defined in file:///mod.ts:1:1 +Defined in file:///mod.ts:1:8 namespace Middle re-export of middle @@ -34,8 +34,8 @@ namespace Middle "location": { "filename": "file:///mod.ts", "line": 1, - "col": 0, - "byteIndex": 27 + "col": 7, + "byteIndex": 34 }, "declarationKind": "export", "jsDoc": { @@ -78,8 +78,8 @@ namespace Middle "location": { "filename": "file:///middle.ts", "line": 3, - "col": 0, - "byteIndex": 82 + "col": 7, + "byteIndex": 89 }, "declarationKind": "export", "jsDoc": { diff --git a/tests/specs/structured_jsdoc.txt b/tests/specs/structured_jsdoc.txt index ab7469908..04f08fa7d 100644 --- a/tests/specs/structured_jsdoc.txt +++ b/tests/specs/structured_jsdoc.txt @@ -184,7 +184,10 @@ class A "value": "void" } ], - "typeName": "Promise" + "typeName": "Promise", + "resolution": { + "kind": "typeParam" + } } } } diff --git a/tests/specs/type_literal_mapped_type.txt b/tests/specs/type_literal_mapped_type.txt index 310e5b4c8..dbead907f 100644 --- a/tests/specs/type_literal_mapped_type.txt +++ b/tests/specs/type_literal_mapped_type.txt @@ -81,7 +81,10 @@ type T = readonly [P in keyof Type as NewType]: Type[P] "repr": "P", "kind": "typeRef", "value": { - "typeName": "P" + "typeName": "P", + "resolution": { + "kind": "typeParam" + } } } } From 852722309cd286eaa5b09fd91ebc0269c7900525 Mon Sep 17 00:00:00 2001 From: Leo Kettmeir Date: Mon, 26 Oct 2026 02:39:12 +0900 Subject: [PATCH 7/9] fix: restore main's locations and expectations for namespaces and ts-expect-error - nested namespace declarations are located at the outer `namespace` keyword (the symbol declaration range) like with swc - columns count a tab as the indent width again via deno_ast's new `line_and_column_display_with_indent_width` - pin deno_graph/deno_ast to the latest oxc-port revisions The two html snapshots that linked the `R` of `infer R ? R : any` to an unrelated construct signature type parameter are re-blessed: that link came from an swc scope leak and the unlinked output matches TypeScript semantics and main's behavior for every other `infer` binding. --- Cargo.lock | 4 ++-- src/parser.rs | 17 +++++++++++++++-- src/tests.rs | 4 ++-- src/util/swc.rs | 2 +- .../html_test__html_doc_files_multiple-39.snap | 4 ++-- tests/snapshots/html_test__symbol_group.snap | 4 ++-- 6 files changed, 24 insertions(+), 11 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 559d00fbb..67ea01094 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -567,7 +567,7 @@ checksum = "be1e0bca6c3637f992fc1cc7cbc52a78c1ef6db076dbf1059c4323d6a2048376" [[package]] name = "deno_ast" version = "0.53.3" -source = "git+https://github.com/nathanwhit/deno_ast?branch=oxc-port#9ff037f4731ee57781beac08f627ac08f4ccdcfb" +source = "git+https://github.com/nathanwhit/deno_ast?branch=oxc-port#5bd7552216e0aab0fdca6bd625d39df3d4a5c6a1" dependencies = [ "base64 0.22.1", "capacity_builder", @@ -667,7 +667,7 @@ dependencies = [ [[package]] name = "deno_graph" version = "0.111.1" -source = "git+https://github.com/nathanwhit/deno_graph?branch=oxc-port#9bea696b7e709399f2d1d1bd089127b413c3f6bc" +source = "git+https://github.com/nathanwhit/deno_graph?branch=oxc-port#80decec0d232f0afb30255f1f81a3909768a61c0" dependencies = [ "async-trait", "boxed_error", diff --git a/src/parser.rs b/src/parser.rs index ef539ef79..77f572541 100644 --- a/src/parser.rs +++ b/src/parser.rs @@ -1822,7 +1822,21 @@ impl<'a> DocParser<'a> { self.get_decl_for_interface_decl(module_info, n, n.range()) } SymbolNodeRef::TsNamespace(n) => { - self.get_decl_for_ts_namespace(module_info, symbol, n, n.range()) + // a nested namespace (`namespace A.B {}`) node starts at its own + // identifier, but its declaration is located at the outer `namespace` + // keyword, so prefer the symbol declaration's range + let full_range = symbol + .decls() + .iter() + .find(|decl| { + matches!( + decl.maybe_node(), + Some(SymbolNodeRef::TsNamespace(decl_node)) if std::ptr::eq(decl_node, n) + ) + }) + .map(|decl| decl.range) + .unwrap_or(n.range()); + self.get_decl_for_ts_namespace(module_info, symbol, n, full_range) } SymbolNodeRef::TsTypeAlias(n) => { self.get_decl_for_type_alias(module_info, n, n.range()) @@ -1869,7 +1883,6 @@ impl<'a> DocParser<'a> { ident, export_decl.range(), ), - ExportDeclRef::TsImportEquals(_) => None, }, SymbolNodeRef::Module(_) | SymbolNodeRef::AutoAccessor(_) diff --git a/src/tests.rs b/src/tests.rs index e8366df93..39f8ce914 100644 --- a/src/tests.rs +++ b/src/tests.rs @@ -519,8 +519,8 @@ export * as b from "./mod_doc.ts"; "location": { "filename": "file:///ns.ts", "line": 1, - "col": 0, - "byteIndex": 1 + "col": 7, + "byteIndex": 8 }, "declarationKind": "export", "jsDoc": { diff --git a/src/util/swc.rs b/src/util/swc.rs index e5e53f60c..f32fc4271 100644 --- a/src/util/swc.rs +++ b/src/util/swc.rs @@ -125,7 +125,7 @@ pub fn get_text_info_location( let text = text_info.text(); let lookup_byte_index = byte_index.min(text.len()); let line_and_column_index = - text_info.line_and_column_display(lookup_byte_index); + text_info.line_and_column_display_with_indent_width(lookup_byte_index, 2); Location { filename: specifier.into(), diff --git a/tests/snapshots/html_test__html_doc_files_multiple-39.snap b/tests/snapshots/html_test__html_doc_files_multiple-39.snap index 2bebe8505..c33c1d6dc 100644 --- a/tests/snapshots/html_test__html_doc_files_multiple-39.snap +++ b/tests/snapshots/html_test__html_doc_files_multiple-39.snap @@ -145,7 +145,7 @@ expression: files.get(file_name).unwrap() -Hello.computedMethod(a: T extends () => infer R ? R : any): void +Hello.computedMethod(a: T extends () => infer R ? R : any): void

-a: T extends () => infer R ? R : any +a: T extends () => infer R ? R : any
diff --git a/tests/snapshots/html_test__symbol_group.snap b/tests/snapshots/html_test__symbol_group.snap index f97d3e36c..1fc344891 100644 --- a/tests/snapshots/html_test__symbol_group.snap +++ b/tests/snapshots/html_test__symbol_group.snap @@ -8412,7 +8412,7 @@ expression: files "id": "function_hello_computedmethod_0" }, "name": "Hello.computedMethod", - "summary": "(a: T extends () => infer R ? R : any): void", + "summary": "(a: T extends () => infer R ? R : any): void", "deprecated": null, "content": { "id": "", @@ -8434,7 +8434,7 @@ expression: files "name_prefix": null, "name": "a", "name_href": null, - "content": ": T extends () => infer R ? R : any", + "content": ": T extends () => infer R ? R : any", "anchor": { "id": "function_hello_computedmethod_0_parameter_a" }, From cde447b85b42d974e4691a74057fd26b7d559aab Mon Sep 17 00:00:00 2001 From: Leo Kettmeir Date: Mon, 26 Oct 2026 03:42:17 +0900 Subject: [PATCH 8/9] chore: bump deno_graph to 69a55910 --- Cargo.lock | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.lock b/Cargo.lock index 67ea01094..03c90ab63 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -667,7 +667,7 @@ dependencies = [ [[package]] name = "deno_graph" version = "0.111.1" -source = "git+https://github.com/nathanwhit/deno_graph?branch=oxc-port#80decec0d232f0afb30255f1f81a3909768a61c0" +source = "git+https://github.com/nathanwhit/deno_graph?branch=oxc-port#69a5591094eaac632c4e958f8c096f2b688334df" dependencies = [ "async-trait", "boxed_error", From bbd00e9dfc18a6d7997dab374975f2a36e06b7a9 Mon Sep 17 00:00:00 2001 From: Leo Kettmeir Date: Mon, 26 Oct 2026 04:33:17 +0900 Subject: [PATCH 9/9] chore: bump deno_graph and deno_ast --- Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 03c90ab63..1a4ca96ab 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -567,7 +567,7 @@ checksum = "be1e0bca6c3637f992fc1cc7cbc52a78c1ef6db076dbf1059c4323d6a2048376" [[package]] name = "deno_ast" version = "0.53.3" -source = "git+https://github.com/nathanwhit/deno_ast?branch=oxc-port#5bd7552216e0aab0fdca6bd625d39df3d4a5c6a1" +source = "git+https://github.com/nathanwhit/deno_ast?branch=oxc-port#a12e82c25d4851b6bd34270bd17e4c992ca7e082" dependencies = [ "base64 0.22.1", "capacity_builder", @@ -667,7 +667,7 @@ dependencies = [ [[package]] name = "deno_graph" version = "0.111.1" -source = "git+https://github.com/nathanwhit/deno_graph?branch=oxc-port#69a5591094eaac632c4e958f8c096f2b688334df" +source = "git+https://github.com/nathanwhit/deno_graph?branch=oxc-port#962071922301d16dff79e3ee485482025dd3a0dc" dependencies = [ "async-trait", "boxed_error",