From 1b91a7dad98c043bbb1617b96ac722d6214c5079 Mon Sep 17 00:00:00 2001 From: Kirigaya <1193466151@qq.com> Date: Fri, 6 Sep 2024 15:29:46 +0800 Subject: [PATCH] first commit --- .gitignore | 13 + Cargo.lock | 1705 +++++++ Cargo.toml | 27 + LICENSE | 21 + README.md | 2 + rustfmt.toml | 2 + src/completion.rs | 781 +++ src/completion/keyword.rs | 466 ++ src/definition.rs | 499 ++ src/definition/def_types.rs | 965 ++++ src/definition/extract_defs.rs | 2314 +++++++++ src/diagnostics.rs | 496 ++ src/format.rs | 173 + src/lib.rs | 9 + src/main.rs | 35 + src/server.rs | 385 ++ src/sources.rs | 629 +++ src/support.rs | 3 + test/client/src/.gitignore | 4 + test/client/src/.vscodeignore | 8 + test/client/src/README.md | 6 + test/client/src/extension.ts | 56 + test/client/src/package-lock.json | 4368 +++++++++++++++++ test/client/src/package.json | 96 + test/client/src/tsconfig.json | 12 + .../syntaxes/systemverilog.tmLanguage.json | 1051 ++++ 26 files changed, 14126 insertions(+) create mode 100644 .gitignore create mode 100644 Cargo.lock create mode 100644 Cargo.toml create mode 100644 LICENSE create mode 100644 README.md create mode 100644 rustfmt.toml create mode 100644 src/completion.rs create mode 100644 src/completion/keyword.rs create mode 100644 src/definition.rs create mode 100644 src/definition/def_types.rs create mode 100644 src/definition/extract_defs.rs create mode 100644 src/diagnostics.rs create mode 100644 src/format.rs create mode 100644 src/lib.rs create mode 100644 src/main.rs create mode 100644 src/server.rs create mode 100644 src/sources.rs create mode 100644 src/support.rs create mode 100644 test/client/src/.gitignore create mode 100644 test/client/src/.vscodeignore create mode 100644 test/client/src/README.md create mode 100644 test/client/src/extension.ts create mode 100644 test/client/src/package-lock.json create mode 100644 test/client/src/package.json create mode 100644 test/client/src/tsconfig.json create mode 100644 test/client/syntaxes/systemverilog.tmLanguage.json diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..32559d2 --- /dev/null +++ b/.gitignore @@ -0,0 +1,13 @@ +# Generated by Cargo +# will have compiled files and executables +debug/ +target/ + +# These are backup files generated by rustfmt +**/*.rs.bk + +tests_rtl +log_files +test.txt + +.vscode/ \ No newline at end of file diff --git a/Cargo.lock b/Cargo.lock new file mode 100644 index 0000000..b81685f --- /dev/null +++ b/Cargo.lock @@ -0,0 +1,1705 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "addr2line" +version = "0.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a76fd60b23679b7d19bd066031410fb7e458ccc5e958eb5c325888ce4baedc97" +dependencies = [ + "gimli", +] + +[[package]] +name = "adler" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" + +[[package]] +name = "aho-corasick" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "43f6cb1bf222025340178f382c426f13757b2960e89779dfcb319c32542a5a41" +dependencies = [ + "memchr", +] + +[[package]] +name = "android-tzdata" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e999941b234f3131b00bc13c22d06e8c5ff726d1b6318ac7eb276997bbb4fef0" + +[[package]] +name = "android_system_properties" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311" +dependencies = [ + "libc", +] + +[[package]] +name = "ansi_term" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d52a9bb7ec0cf484c551830a7ce27bd20d67eac647e1befb56b0be4ee39a55d2" +dependencies = [ + "winapi", +] + +[[package]] +name = "anyhow" +version = "1.0.72" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3b13c32d80ecc7ab747b80c3784bce54ee8a7a0cc4fbda9bf4cda2cf6fe90854" + +[[package]] +name = "arrayvec" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "23b62fc65de8e4e7f52534fb52b0f3ed04746ae267519eef2a83941e8085068b" + +[[package]] +name = "async-trait" +version = "0.1.72" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cc6dde6e4ed435a4c1ee4e73592f5ba9da2151af10076cc04858746af9352d09" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.28", +] + +[[package]] +name = "atty" +version = "0.2.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" +dependencies = [ + "hermit-abi 0.1.19", + "libc", + "winapi", +] + +[[package]] +name = "auto_impl" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fee3da8ef1276b0bee5dd1c7258010d8fffd31801447323115a25560e1327b89" +dependencies = [ + "proc-macro-error", + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "autocfg" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" + +[[package]] +name = "backtrace" +version = "0.3.67" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "233d376d6d185f2a3093e58f283f60f880315b6c60075b01f36b3b85154564ca" +dependencies = [ + "addr2line", + "cc", + "cfg-if", + "libc", + "miniz_oxide", + "object", + "rustc-demangle", +] + +[[package]] +name = "bitflags" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" + +[[package]] +name = "bitflags" +version = "2.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed570934406eb16438a4e976b1b4500774099c13b8cb96eec99f620f05090ddf" + +[[package]] +name = "bumpalo" +version = "3.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c" + +[[package]] +name = "bytecount" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f861d9ce359f56dbcb6e0c2a1cb84e52ad732cadb57b806adeb3c7668caccbd8" + +[[package]] +name = "bytecount" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2c676a478f63e9fa2dd5368a42f28bba0d6c560b775f38583c8bbaa7fcd67c9c" + +[[package]] +name = "bytes" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "89b2fd2a0dcf38d7971e2194b6b6eebab45ae01067456a7fd93d5547a61b70be" + +[[package]] +name = "cc" +version = "1.0.79" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "50d30906286121d95be3d479533b458f87493b30a4b5f79a607db8f5d11aa91f" + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[package]] +name = "chrono" +version = "0.4.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec837a71355b28f6556dbd569b37b3f363091c0bd4b2e735674521b4c5fd9bc5" +dependencies = [ + "android-tzdata", + "iana-time-zone", + "num-traits", + "winapi", +] + +[[package]] +name = "clap" +version = "2.34.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a0610544180c38b88101fecf2dd634b174a62eef6946f84dfc6a7127512b381c" +dependencies = [ + "ansi_term", + "atty", + "bitflags 1.3.2", + "strsim", + "textwrap", + "unicode-width", + "vec_map", +] + +[[package]] +name = "core-foundation-sys" +version = "0.8.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06ea2b9bc92be3c2baa9334a323ebca2d6f074ff852cd1d7b11064035cd3868f" + +[[package]] +name = "dashmap" +version = "5.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6943ae99c34386c84a470c499d3414f66502a41340aa895406e0d2e4a207b91d" +dependencies = [ + "cfg-if", + "hashbrown", + "lock_api", + "once_cell", + "parking_lot_core", +] + +[[package]] +name = "either" +version = "1.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a26ae43d7bcc3b814de94796a5e736d4029efb0ee900c12e2d54c993ad1a1e07" + +[[package]] +name = "equivalent" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" + +[[package]] +name = "errno" +version = "0.3.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a258e46cdc063eb8519c00b9fc845fc47bcfca4130e2f08e88665ceda8474245" +dependencies = [ + "libc", + "windows-sys 0.52.0", +] + +[[package]] +name = "flexi_logger" +version = "0.27.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "469e584c031833564840fb0cdbce99bdfe946fd45480a188545e73a76f45461c" +dependencies = [ + "chrono", + "glob", + "is-terminal", + "lazy_static", + "log", + "nu-ansi-term", + "regex", + "thiserror", +] + +[[package]] +name = "form_urlencoded" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a62bc1cf6f830c2ec14a513a9fb124d0a213a629668a4186f329db21fe045652" +dependencies = [ + "percent-encoding", +] + +[[package]] +name = "fuchsia-cprng" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a06f77d526c1a601b7c4cdd98f54b5eaabffc14d5f2f0296febdc7f357c6d3ba" + +[[package]] +name = "futures" +version = "0.3.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "23342abe12aba583913b2e62f22225ff9c950774065e4bfb61a19cd9770fec40" +dependencies = [ + "futures-channel", + "futures-core", + "futures-io", + "futures-sink", + "futures-task", + "futures-util", +] + +[[package]] +name = "futures-channel" +version = "0.3.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "955518d47e09b25bbebc7a18df10b81f0c766eaf4c4f1cccef2fca5f2a4fb5f2" +dependencies = [ + "futures-core", + "futures-sink", +] + +[[package]] +name = "futures-core" +version = "0.3.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4bca583b7e26f571124fe5b7561d49cb2868d79116cfa0eefce955557c6fee8c" + +[[package]] +name = "futures-io" +version = "0.3.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4fff74096e71ed47f8e023204cfd0aa1289cd54ae5430a9523be060cdb849964" + +[[package]] +name = "futures-macro" +version = "0.3.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "89ca545a94061b6365f2c7355b4b32bd20df3ff95f02da9329b34ccc3bd6ee72" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.28", +] + +[[package]] +name = "futures-sink" +version = "0.3.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f43be4fe21a13b9781a69afa4985b0f6ee0e1afab2c6f454a8cf30e2b2237b6e" + +[[package]] +name = "futures-task" +version = "0.3.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "76d3d132be6c0e6aa1534069c705a74a5997a356c0dc2f86a47765e5617c5b65" + +[[package]] +name = "futures-util" +version = "0.3.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26b01e40b772d54cf6c6d721c1d1abd0647a0106a12ecaa1c186273392a69533" +dependencies = [ + "futures-channel", + "futures-core", + "futures-io", + "futures-macro", + "futures-sink", + "futures-task", + "memchr", + "pin-project-lite", + "pin-utils", + "slab", +] + +[[package]] +name = "gimli" +version = "0.27.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ad0a93d233ebf96623465aad4046a8d3aa4da22d4f4beba5388838c8a434bbb4" + +[[package]] +name = "glob" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b" + +[[package]] +name = "hashbrown" +version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2c6201b9ff9fd90a5a3bac2e56a830d0caa509576f0e503818ee82c181b3437a" + +[[package]] +name = "heck" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6d621efb26863f0e9924c6ac577e8275e5e6b77455db64ffa6c65c904e9e132c" +dependencies = [ + "unicode-segmentation", +] + +[[package]] +name = "heck" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" + +[[package]] +name = "hermit-abi" +version = "0.1.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33" +dependencies = [ + "libc", +] + +[[package]] +name = "hermit-abi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024" + +[[package]] +name = "home" +version = "0.5.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3d1354bf6b7235cb4a0576c2619fd4ed18183f689b12b006a0ee7329eeff9a5" +dependencies = [ + "windows-sys 0.52.0", +] + +[[package]] +name = "httparse" +version = "1.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d897f394bad6a705d5f4104762e116a75639e470d80901eed05a860a95cb1904" + +[[package]] +name = "iana-time-zone" +version = "0.1.57" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2fad5b825842d2b38bd206f3e81d6957625fd7f0a361e345c30e01a0ae2dd613" +dependencies = [ + "android_system_properties", + "core-foundation-sys", + "iana-time-zone-haiku", + "js-sys", + "wasm-bindgen", + "windows", +] + +[[package]] +name = "iana-time-zone-haiku" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f31827a206f56af32e590ba56d5d2d085f558508192593743f16b2306495269f" +dependencies = [ + "cc", +] + +[[package]] +name = "idna" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7d20d6b07bfbc108882d88ed8e37d39636dcc260e15e30c45e6ba089610b917c" +dependencies = [ + "unicode-bidi", + "unicode-normalization", +] + +[[package]] +name = "indexmap" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d5477fe2230a79769d8dc68e0eabf5437907c0457a5614a9e8dddb67f65eb65d" +dependencies = [ + "equivalent", + "hashbrown", +] + +[[package]] +name = "is-terminal" +version = "0.4.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb0889898416213fab133e1d33a0e5858a48177452750691bde3666d0fdbaf8b" +dependencies = [ + "hermit-abi 0.3.9", + "rustix", + "windows-sys 0.48.0", +] + +[[package]] +name = "itoa" +version = "1.0.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "af150ab688ff2122fcef229be89cb50dd66af9e01a4ff320cc137eecc9bacc38" + +[[package]] +name = "js-sys" +version = "0.3.64" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c5f195fe497f702db0f318b07fdd68edb16955aed830df8363d837542f8f935a" +dependencies = [ + "wasm-bindgen", +] + +[[package]] +name = "lazy_static" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" + +[[package]] +name = "lexical-core" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6607c62aa161d23d17a9072cc5da0be67cdfc89d3afb1e8d9c842bebc2525ffe" +dependencies = [ + "arrayvec", + "bitflags 1.3.2", + "cfg-if", + "ryu", + "static_assertions", +] + +[[package]] +name = "libc" +version = "0.2.152" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13e3bf6590cbc649f4d1a3eefc9d5d6eb746f5200ffb04e5e142700b8faa56e7" + +[[package]] +name = "linux-raw-sys" +version = "0.4.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "01cda141df6706de531b6c46c3a33ecca755538219bd484262fa09410c13539c" + +[[package]] +name = "lock_api" +version = "0.4.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c1cc9717a20b1bb222f333e6a92fd32f7d8a18ddc5a3191a11af45dcbf4dcd16" +dependencies = [ + "autocfg", + "scopeguard", +] + +[[package]] +name = "log" +version = "0.4.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b06a4cde4c0f271a446782e3eff8de789548ce57dbc8eca9292c27f4a42004b4" + +[[package]] +name = "lsp-types" +version = "0.94.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c66bfd44a06ae10647fe3f8214762e9369fd4248df1350924b4ef9e770a85ea1" +dependencies = [ + "bitflags 1.3.2", + "serde", + "serde_json", + "serde_repr", + "url", +] + +[[package]] +name = "memchr" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d" + +[[package]] +name = "miniz_oxide" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b275950c28b37e794e8c55d88aeb5e139d0ce23fdbbeda68f8d7174abdf9e8fa" +dependencies = [ + "adler", +] + +[[package]] +name = "nom" +version = "5.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08959a387a676302eebf4ddbcbc611da04285579f76f88ee0506c63b1a61dd4b" +dependencies = [ + "lexical-core", + "memchr", + "version_check", +] + +[[package]] +name = "nom-greedyerror" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "005188fda7f3ea919ee32f9c71e99a0aff25031c7403a2e1b40210627602b180" +dependencies = [ + "nom", + "nom_locate 1.0.0", + "nom_locate 2.1.0", +] + +[[package]] +name = "nom-packrat" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3ec62525e98be79d646fda5144d70afc71bee2375ab847a3d78ffe5eaeb8260" +dependencies = [ + "nom-packrat-macros", + "nom_locate 1.0.0", + "nom_locate 2.1.0", +] + +[[package]] +name = "nom-packrat-macros" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4a845d4abd19861ab38dd485e90daf0a29a4f7bdc675c4fcce4be7af788140c2" +dependencies = [ + "quote", + "syn 1.0.109", +] + +[[package]] +name = "nom-recursive" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b12e0cf53f6ea38a53a6a4b10e7b170ea1cc56166dcb4fcab9a53c4890b205b2" +dependencies = [ + "nom-recursive-macros", + "nom_locate 1.0.0", + "nom_locate 2.1.0", +] + +[[package]] +name = "nom-recursive-macros" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2d69ac6bb21fb4ffc328bcec8cea7b1a07114e1a9ed10d5a630feb7e2a243dbe" +dependencies = [ + "quote", + "syn 1.0.109", +] + +[[package]] +name = "nom-tracable" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1875762c6bd471741e093a85fd66f6b9b93b14203b592b66ec7b41b31f553559" +dependencies = [ + "nom", + "nom-tracable-macros", + "nom_locate 1.0.0", + "nom_locate 2.1.0", +] + +[[package]] +name = "nom-tracable-macros" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8b4ba141c87dc4f398331f8772b629d546dc25fb469999ee0ed0c63145c13fb" +dependencies = [ + "quote", + "syn 1.0.109", +] + +[[package]] +name = "nom_locate" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f932834fd8e391fc7710e2ba17e8f9f8645d846b55aa63207e17e110a1e1ce35" +dependencies = [ + "bytecount 0.3.2", + "memchr", + "nom", +] + +[[package]] +name = "nom_locate" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a67484adf5711f94f2f28b653bf231bff8e438be33bf5b0f35935a0db4f618a2" +dependencies = [ + "bytecount 0.6.3", + "memchr", + "nom", +] + +[[package]] +name = "nu-ansi-term" +version = "0.49.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c073d3c1930d0751774acf49e66653acecb416c3a54c6ec095a9b11caddb5a68" +dependencies = [ + "windows-sys 0.48.0", +] + +[[package]] +name = "num-traits" +version = "0.2.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f30b0abd723be7e2ffca1272140fac1a2f084c77ec3e123c192b66af1ee9e6c2" +dependencies = [ + "autocfg", +] + +[[package]] +name = "num_cpus" +version = "1.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43" +dependencies = [ + "hermit-abi 0.3.9", + "libc", +] + +[[package]] +name = "object" +version = "0.30.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ea86265d3d3dcb6a27fc51bd29a4bf387fae9d2986b823079d4986af253eb439" +dependencies = [ + "memchr", +] + +[[package]] +name = "once_cell" +version = "1.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d" + +[[package]] +name = "parking_lot_core" +version = "0.9.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93f00c865fe7cabf650081affecd3871070f26767e7b2070a3ffae14c654b447" +dependencies = [ + "cfg-if", + "libc", + "redox_syscall", + "smallvec", + "windows-targets 0.48.5", +] + +[[package]] +name = "path-clean" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "17359afc20d7ab31fdb42bb844c8b3bb1dabd7dcf7e68428492da7f16966fcef" + +[[package]] +name = "pathdiff" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8835116a5c179084a830efb3adc117ab007512b535bc1a21c991d3b32a6b44dd" + +[[package]] +name = "percent-encoding" +version = "2.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b2a4787296e9989611394c33f193f676704af1686e70b8f8033ab5ba9a35a94" + +[[package]] +name = "pin-project" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "030ad2bc4db10a8944cb0d837f158bdfec4d4a4873ab701a95046770d11f8842" +dependencies = [ + "pin-project-internal", +] + +[[package]] +name = "pin-project-internal" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec2e072ecce94ec471b13398d5402c188e76ac03cf74dd1a975161b23a3f6d9c" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.28", +] + +[[package]] +name = "pin-project-lite" +version = "0.2.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c40d25201921e5ff0c862a505c6557ea88568a4e3ace775ab55e93f2f4f9d57" + +[[package]] +name = "pin-utils" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" + +[[package]] +name = "proc-macro-error" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c" +dependencies = [ + "proc-macro-error-attr", + "proc-macro2", + "quote", + "syn 1.0.109", + "version_check", +] + +[[package]] +name = "proc-macro-error-attr" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869" +dependencies = [ + "proc-macro2", + "quote", + "version_check", +] + +[[package]] +name = "proc-macro2" +version = "1.0.66" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "18fb31db3f9bddb2ea821cde30a9f70117e3f119938b5ee630b7403aa6e2ead9" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quote" +version = "1.0.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "50f3b39ccfb720540debaa0164757101c08ecb8d326b15358ce76a62c7e85965" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "rand" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "552840b97013b1a26992c11eac34bdd778e464601a4c2054b5f0bff7c6761293" +dependencies = [ + "fuchsia-cprng", + "libc", + "rand_core 0.3.1", + "rdrand", + "winapi", +] + +[[package]] +name = "rand_core" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a6fdeb83b075e8266dcc8762c22776f6877a63111121f5f8c7411e5be7eed4b" +dependencies = [ + "rand_core 0.4.2", +] + +[[package]] +name = "rand_core" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c33a3c44ca05fa6f1807d8e6743f3824e8509beca625669633be0acbdf509dc" + +[[package]] +name = "rdrand" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "678054eb77286b51581ba43620cc911abf02758c91f93f479767aed0f90458b2" +dependencies = [ + "rand_core 0.3.1", +] + +[[package]] +name = "redox_syscall" +version = "0.3.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "567664f262709473930a4bf9e51bf2ebf3348f2e748ccc50dea20646858f8f29" +dependencies = [ + "bitflags 1.3.2", +] + +[[package]] +name = "regex" +version = "1.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b2eae68fc220f7cf2532e4494aded17545fce192d59cd996e0fe7887f4ceb575" +dependencies = [ + "aho-corasick", + "memchr", + "regex-automata", + "regex-syntax", +] + +[[package]] +name = "regex-automata" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b7b6d6190b7594385f61bd3911cd1be99dfddcfc365a4160cc2ab5bff4aed294" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax", +] + +[[package]] +name = "regex-syntax" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e5ea92a5b6195c6ef2a0295ea818b312502c6fc94dde986c5553242e18fd4ce2" + +[[package]] +name = "remove_dir_all" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3acd125665422973a33ac9d3dd2df85edad0f4ae9b00dafb1a05e43a9f5ef8e7" +dependencies = [ + "winapi", +] + +[[package]] +name = "ropey" +version = "1.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "53ce7a2c43a32e50d666e33c5a80251b31147bb4b49024bcab11fb6f20c671ed" +dependencies = [ + "smallvec", + "str_indices", +] + +[[package]] +name = "rustc-demangle" +version = "0.1.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76" + +[[package]] +name = "rustix" +version = "0.38.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "322394588aaf33c24007e8bb3238ee3e4c5c09c084ab32bc73890b99ff326bca" +dependencies = [ + "bitflags 2.4.2", + "errno", + "libc", + "linux-raw-sys", + "windows-sys 0.52.0", +] + +[[package]] +name = "rustversion" +version = "1.0.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ffc183a10b4478d04cbbbfc96d0873219d962dd5accaff2ffbd4ceb7df837f4" + +[[package]] +name = "ryu" +version = "1.0.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ad4cc8da4ef723ed60bced201181d83791ad433213d8c24efffda1eec85d741" + +[[package]] +name = "same-file" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502" +dependencies = [ + "winapi-util", +] + +[[package]] +name = "scopeguard" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" + +[[package]] +name = "serde" +version = "1.0.179" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0a5bf42b8d227d4abf38a1ddb08602e229108a517cd4e5bb28f9c7eaafdce5c0" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.179" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "741e124f5485c7e60c03b043f79f320bff3527f4bbf12cf3831750dc46a0ec2c" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.28", +] + +[[package]] +name = "serde_json" +version = "1.0.104" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "076066c5f1078eac5b722a31827a8832fe108bed65dfa75e233c89f8206e976c" +dependencies = [ + "itoa", + "ryu", + "serde", +] + +[[package]] +name = "serde_repr" +version = "0.1.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8725e1dfadb3a50f7e5ce0b1a540466f6ed3fe7a0fca2ac2b8b831d31316bd00" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.28", +] + +[[package]] +name = "serde_yaml" +version = "0.9.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a49e178e4452f45cb61d0cd8cebc1b0fafd3e41929e996cef79aa3aca91f574" +dependencies = [ + "indexmap", + "itoa", + "ryu", + "serde", + "unsafe-libyaml", +] + +[[package]] +name = "slab" +version = "0.4.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6528351c9bc8ab22353f9d776db39a20288e8d6c37ef8cfe3317cf875eecfc2d" +dependencies = [ + "autocfg", +] + +[[package]] +name = "smallvec" +version = "1.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" + +[[package]] +name = "static_assertions" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" + +[[package]] +name = "str-concat" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3468939e48401c4fe3cdf5e5cef50951c2808ed549d1467fde249f1fcb602634" + +[[package]] +name = "str_indices" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f026164926842ec52deb1938fae44f83dfdb82d0a5b0270c5bd5935ab74d6dd" + +[[package]] +name = "strsim" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a" + +[[package]] +name = "structopt" +version = "0.3.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c6b5c64445ba8094a6ab0c3cd2ad323e07171012d9c98b0b15651daf1787a10" +dependencies = [ + "clap", + "lazy_static", + "structopt-derive", +] + +[[package]] +name = "structopt-derive" +version = "0.4.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dcb5ae327f9cc13b68763b5749770cb9e048a99bd9dfdfa58d0cf05d5f64afe0" +dependencies = [ + "heck 0.3.3", + "proc-macro-error", + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "strum" +version = "0.26.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "723b93e8addf9aa965ebe2d11da6d7540fa2283fcea14b3371ff055f7ba13f5f" + +[[package]] +name = "strum_macros" +version = "0.26.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a3417fc93d76740d974a01654a09777cb500428cc874ca9f45edfe0c4d4cd18" +dependencies = [ + "heck 0.4.1", + "proc-macro2", + "quote", + "rustversion", + "syn 2.0.28", +] + +[[package]] +name = "sv-parser" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5febd467eca0820285e6d8dc7f794430c56d446f01638f320d6122931808d4ae" +dependencies = [ + "nom", + "nom-greedyerror", + "sv-parser-error", + "sv-parser-parser", + "sv-parser-pp", + "sv-parser-syntaxtree", +] + +[[package]] +name = "sv-parser-error" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8d4783f356ec80fb2a3f3003d9b9c743376a86069c5809dff8cd506f91d9cf30" +dependencies = [ + "thiserror", +] + +[[package]] +name = "sv-parser-macros" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1c5d18eaf59472f37a75e9f9c5b056df280eb5ffdd2aca9f677a5e34b8c31753" +dependencies = [ + "quote", + "syn 1.0.109", +] + +[[package]] +name = "sv-parser-parser" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cbc24d617443cda9daadd80fb60e139a1584e4e3726f2b68df50b9bfddbecb71" +dependencies = [ + "nom", + "nom-greedyerror", + "nom-packrat", + "nom-recursive", + "nom-tracable", + "nom_locate 2.1.0", + "str-concat", + "sv-parser-macros", + "sv-parser-syntaxtree", +] + +[[package]] +name = "sv-parser-pp" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2e1cb4ac6171b99c04e3504867c25018cbf425fe72e088e599df2c9dbe0c2a48" +dependencies = [ + "nom", + "nom-greedyerror", + "sv-parser-error", + "sv-parser-parser", + "sv-parser-syntaxtree", +] + +[[package]] +name = "sv-parser-syntaxtree" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a100af4bf3ce8e6650349c7f020ca715c9918d2dfd27dfac00d6148173e66670" +dependencies = [ + "regex", + "sv-parser-macros", + "walkdir", +] + +[[package]] +name = "syn" +version = "1.0.109" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "syn" +version = "2.0.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "04361975b3f5e348b2189d8dc55bc942f278b2d482a6a0365de5bdd62d351567" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "tempdir" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "15f2b5fb00ccdf689e0149d1b1b3c03fead81c2b37735d812fa8bddbbf41b6d8" +dependencies = [ + "rand", + "remove_dir_all", +] + +[[package]] +name = "textwrap" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060" +dependencies = [ + "unicode-width", +] + +[[package]] +name = "thiserror" +version = "1.0.44" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "611040a08a0439f8248d1990b111c95baa9c704c805fa1f62104b39655fd7f90" +dependencies = [ + "thiserror-impl", +] + +[[package]] +name = "thiserror-impl" +version = "1.0.44" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "090198534930841fab3a5d1bb637cde49e339654e606195f8d9c76eeb081dc96" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.28", +] + +[[package]] +name = "tinyvec" +version = "1.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87cc5ceb3875bb20c2890005a4e226a4651264a5c75edb2421b52861a0a0cb50" +dependencies = [ + "tinyvec_macros", +] + +[[package]] +name = "tinyvec_macros" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" + +[[package]] +name = "tokio" +version = "1.29.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "532826ff75199d5833b9d2c5fe410f29235e25704ee5f0ef599fb51c21f4a4da" +dependencies = [ + "autocfg", + "backtrace", + "num_cpus", + "pin-project-lite", + "tokio-macros", +] + +[[package]] +name = "tokio-macros" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "630bdcf245f78637c13ec01ffae6187cca34625e8c63150d424b59e55af2675e" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.28", +] + +[[package]] +name = "tokio-util" +version = "0.7.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "806fe8c2c87eccc8b3267cbae29ed3ab2d0bd37fca70ab622e46aaa9375ddb7d" +dependencies = [ + "bytes", + "futures-core", + "futures-sink", + "pin-project-lite", + "tokio", + "tracing", +] + +[[package]] +name = "tower" +version = "0.4.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8fa9be0de6cf49e536ce1851f987bd21a43b771b09473c3549a6c853db37c1c" +dependencies = [ + "futures-core", + "futures-util", + "pin-project", + "pin-project-lite", + "tower-layer", + "tower-service", +] + +[[package]] +name = "tower-layer" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c20c8dbed6283a09604c3e69b4b7eeb54e298b8a600d4d5ecb5ad39de609f1d0" + +[[package]] +name = "tower-lsp" +version = "0.20.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d4ba052b54a6627628d9b3c34c176e7eda8359b7da9acd497b9f20998d118508" +dependencies = [ + "async-trait", + "auto_impl", + "bytes", + "dashmap", + "futures", + "httparse", + "lsp-types", + "memchr", + "serde", + "serde_json", + "tokio", + "tokio-util", + "tower", + "tower-lsp-macros", + "tracing", +] + +[[package]] +name = "tower-lsp-macros" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "84fd902d4e0b9a4b27f2f440108dc034e1758628a9b702f8ec61ad66355422fa" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.28", +] + +[[package]] +name = "tower-service" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6bc1c9ce2b5135ac7f93c72918fc37feb872bdc6a5533a8b85eb4b86bfdae52" + +[[package]] +name = "tracing" +version = "0.1.37" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ce8c33a8d48bd45d624a6e523445fd21ec13d3653cd51f681abf67418f54eb8" +dependencies = [ + "cfg-if", + "pin-project-lite", + "tracing-attributes", + "tracing-core", +] + +[[package]] +name = "tracing-attributes" +version = "0.1.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f4f31f56159e98206da9efd823404b79b6ef3143b4a7ab76e67b1751b25a4ab" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.28", +] + +[[package]] +name = "tracing-core" +version = "0.1.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0955b8137a1df6f1a2e9a37d8a6656291ff0297c1a97c24e0d8425fe2312f79a" +dependencies = [ + "once_cell", +] + +[[package]] +name = "unicode-bidi" +version = "0.3.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "92888ba5573ff080736b3648696b70cafad7d250551175acbaa4e0385b3e1460" + +[[package]] +name = "unicode-ident" +version = "1.0.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "301abaae475aa91687eb82514b328ab47a211a533026cb25fc3e519b86adfc3c" + +[[package]] +name = "unicode-normalization" +version = "0.1.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c5713f0fc4b5db668a2ac63cdb7bb4469d8c9fed047b1d0292cc7b0ce2ba921" +dependencies = [ + "tinyvec", +] + +[[package]] +name = "unicode-segmentation" +version = "1.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1dd624098567895118886609431a7c3b8f516e41d30e0643f03d94592a147e36" + +[[package]] +name = "unicode-width" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c0edd1e5b14653f783770bce4a4dabb4a5108a5370a5f5d8cfe8710c361f6c8b" + +[[package]] +name = "unsafe-libyaml" +version = "0.2.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f28467d3e1d3c6586d8f25fa243f544f5800fec42d97032474e17222c2b75cfa" + +[[package]] +name = "url" +version = "2.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "50bff7831e19200a85b17131d085c25d7811bc4e186efdaf54bbd132994a88cb" +dependencies = [ + "form_urlencoded", + "idna", + "percent-encoding", + "serde", +] + +[[package]] +name = "vec_map" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1bddf1187be692e79c5ffeab891132dfb0f236ed36a43c7ed39f1165ee20191" + +[[package]] +name = "veridian" +version = "0.1.0" +dependencies = [ + "anyhow", + "flexi_logger", + "log", + "path-clean", + "pathdiff", + "regex", + "ropey", + "serde", + "serde_yaml", + "structopt", + "strum", + "strum_macros", + "sv-parser", + "tempdir", + "tokio", + "tower-lsp", + "walkdir", + "which", +] + +[[package]] +name = "version_check" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" + +[[package]] +name = "walkdir" +version = "2.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "36df944cda56c7d8d8b7496af378e6b16de9284591917d307c9b4d313c44e698" +dependencies = [ + "same-file", + "winapi-util", +] + +[[package]] +name = "wasm-bindgen" +version = "0.2.87" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7706a72ab36d8cb1f80ffbf0e071533974a60d0a308d01a5d0375bf60499a342" +dependencies = [ + "cfg-if", + "wasm-bindgen-macro", +] + +[[package]] +name = "wasm-bindgen-backend" +version = "0.2.87" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5ef2b6d3c510e9625e5fe6f509ab07d66a760f0885d858736483c32ed7809abd" +dependencies = [ + "bumpalo", + "log", + "once_cell", + "proc-macro2", + "quote", + "syn 2.0.28", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-macro" +version = "0.2.87" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dee495e55982a3bd48105a7b947fd2a9b4a8ae3010041b9e0faab3f9cd028f1d" +dependencies = [ + "quote", + "wasm-bindgen-macro-support", +] + +[[package]] +name = "wasm-bindgen-macro-support" +version = "0.2.87" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "54681b18a46765f095758388f2d0cf16eb8d4169b639ab575a8f5693af210c7b" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.28", + "wasm-bindgen-backend", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-shared" +version = "0.2.87" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ca6ad05a4870b2bf5fe995117d3728437bd27d7cd5f06f13c17443ef369775a1" + +[[package]] +name = "which" +version = "6.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7fa5e0c10bf77f44aac573e498d1a82d5fbd5e91f6fc0a99e7be4b38e85e101c" +dependencies = [ + "either", + "home", + "once_cell", + "rustix", + "windows-sys 0.52.0", +] + +[[package]] +name = "winapi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" +dependencies = [ + "winapi-i686-pc-windows-gnu", + "winapi-x86_64-pc-windows-gnu", +] + +[[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" + +[[package]] +name = "winapi-util" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178" +dependencies = [ + "winapi", +] + +[[package]] +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" + +[[package]] +name = "windows" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e686886bc078bc1b0b600cac0147aadb815089b6e4da64016cbd754b6342700f" +dependencies = [ + "windows-targets 0.48.5", +] + +[[package]] +name = "windows-sys" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" +dependencies = [ + "windows-targets 0.48.5", +] + +[[package]] +name = "windows-sys" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" +dependencies = [ + "windows-targets 0.52.5", +] + +[[package]] +name = "windows-targets" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" +dependencies = [ + "windows_aarch64_gnullvm 0.48.5", + "windows_aarch64_msvc 0.48.5", + "windows_i686_gnu 0.48.5", + "windows_i686_msvc 0.48.5", + "windows_x86_64_gnu 0.48.5", + "windows_x86_64_gnullvm 0.48.5", + "windows_x86_64_msvc 0.48.5", +] + +[[package]] +name = "windows-targets" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6f0713a46559409d202e70e28227288446bf7841d3211583a4b53e3f6d96e7eb" +dependencies = [ + "windows_aarch64_gnullvm 0.52.5", + "windows_aarch64_msvc 0.52.5", + "windows_i686_gnu 0.52.5", + "windows_i686_gnullvm", + "windows_i686_msvc 0.52.5", + "windows_x86_64_gnu 0.52.5", + "windows_x86_64_gnullvm 0.52.5", + "windows_x86_64_msvc 0.52.5", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7088eed71e8b8dda258ecc8bac5fb1153c5cffaf2578fc8ff5d61e23578d3263" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9985fd1504e250c615ca5f281c3f7a6da76213ebd5ccc9561496568a2752afb6" + +[[package]] +name = "windows_i686_gnu" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" + +[[package]] +name = "windows_i686_gnu" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "88ba073cf16d5372720ec942a8ccbf61626074c6d4dd2e745299726ce8b89670" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87f4261229030a858f36b459e748ae97545d6f1ec60e5e0d6a3d32e0dc232ee9" + +[[package]] +name = "windows_i686_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" + +[[package]] +name = "windows_i686_msvc" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db3c2bf3d13d5b658be73463284eaf12830ac9a26a90c717b7f771dfe97487bf" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4e4246f76bdeff09eb48875a0fd3e2af6aada79d409d33011886d3e1581517d9" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "852298e482cd67c356ddd9570386e2862b5673c85bd5f88df9ab6802b334c596" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bec47e5bfd1bff0eeaf6d8b485cc1074891a197ab4225d504cb7a1ab88b02bf0" diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 0000000..a3084f2 --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,27 @@ +[package] +name = "veridian" +version = "0.1.0" +authors = ["Vivek Malneedi "] +edition = "2018" + +[dependencies] +sv-parser = "0.8.2" +log = "0.4.19" +tower-lsp = "0.20.0" +flexi_logger = "0.27.4" +ropey = "1.6.0" +tokio = { version = "1.29.1", features = ["macros", "io-std", "rt-multi-thread"] } +path-clean = "1.0.1" +pathdiff = "0.2.1" +walkdir = "2.3.3" +serde_yaml = "0.9.25" +anyhow = "1.0.72" +serde = "1.0.179" +which = "6.0.0" +regex = "1.9.1" +structopt = "0.3.26" +strum = "0.26.1" +strum_macros = "0.26.1" + +[dev-dependencies] +tempdir = "0.3.7" diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..99cc768 --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2021 Vivek Malneedi + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/README.md b/README.md new file mode 100644 index 0000000..c9fa1d2 --- /dev/null +++ b/README.md @@ -0,0 +1,2 @@ +转为 Digital IDE 设计的 lsp server + diff --git a/rustfmt.toml b/rustfmt.toml new file mode 100644 index 0000000..c94de51 --- /dev/null +++ b/rustfmt.toml @@ -0,0 +1,2 @@ +edition = "2018" +max_width = 100 diff --git a/src/completion.rs b/src/completion.rs new file mode 100644 index 0000000..64418f5 --- /dev/null +++ b/src/completion.rs @@ -0,0 +1,781 @@ +use crate::server::LSPServer; +use crate::sources::LSPSupport; +use log::{debug, trace}; +use ropey::{Rope, RopeSlice}; +use std::time::Instant; +use tower_lsp::lsp_types::*; + +pub mod keyword; + +impl LSPServer { + pub fn completion(&self, params: CompletionParams) -> Option { + debug!("completion requested"); + trace!("{:#?}", ¶ms); + let now = Instant::now(); + let doc = params.text_document_position; + let file_id = self.srcs.get_id(&doc.text_document.uri).to_owned(); + self.srcs.wait_parse_ready(file_id, false); + trace!("comp wait parse: {}", now.elapsed().as_millis()); + let file = self.srcs.get_file(file_id)?; + let file = file.read().ok()?; + trace!("comp read: {}", now.elapsed().as_millis()); + let token = get_completion_token( + &file.text, + file.text.line(doc.position.line as usize), + doc.position, + ); + let response = match params.context { + Some(context) => match context.trigger_kind { + CompletionTriggerKind::TRIGGER_CHARACTER => { + debug!( + "trigger char completion: {}", + context.trigger_character.clone()?.as_str() + ); + match context.trigger_character?.as_str() { + "." => Some(self.srcs.get_dot_completions( + token.trim_end_matches('.'), + file.text.pos_to_byte(&doc.position), + &doc.text_document.uri, + )?), + "$" => Some(CompletionList { + is_incomplete: false, + items: self.sys_tasks.clone(), + }), + "`" => Some(CompletionList { + is_incomplete: false, + items: self.directives.clone(), + }), + _ => None, + } + } + CompletionTriggerKind::TRIGGER_FOR_INCOMPLETE_COMPLETIONS => None, + CompletionTriggerKind::INVOKED => { + debug!("Invoked Completion"); + let mut comps = self.srcs.get_completions( + &token, + file.text.pos_to_byte(&doc.position), + &doc.text_document.uri, + )?; + // complete keywords + comps.items.extend::>( + self.key_comps + .iter() + .filter(|x| x.label.starts_with(&token)) + .cloned() + .collect(), + ); + Some(comps) + } + _ => None, + }, + None => { + let trigger = prev_char(&file.text, &doc.position); + match trigger { + '.' => Some(self.srcs.get_dot_completions( + token.trim_end_matches('.'), + file.text.pos_to_byte(&doc.position), + &doc.text_document.uri, + )?), + '$' => Some(CompletionList { + is_incomplete: false, + items: self.sys_tasks.clone(), + }), + '`' => Some(CompletionList { + is_incomplete: false, + items: self.directives.clone(), + }), + _ => { + let mut comps = self.srcs.get_completions( + &token, + file.text.pos_to_byte(&doc.position), + &doc.text_document.uri, + )?; + comps.items.extend::>( + self.key_comps + .iter() + .filter(|x| x.label.starts_with(&token)) + .cloned() + .collect(), + ); + Some(comps) + } + } + } + }; + // eprintln!("comp response: {}", now.elapsed().as_millis()); + Some(CompletionResponse::List(response?)) + } +} + +/// get the previous non-whitespace character +fn prev_char(text: &Rope, pos: &Position) -> char { + let char_idx = text.pos_to_char(pos); + if char_idx > 0 { + for i in (0..char_idx).rev() { + let res = text.char(i); + if !res.is_whitespace() { + return res; + } + } + ' ' + } else { + ' ' + } +} + +/// attempt to get the token the user was trying to complete, by +/// filtering out characters unneeded for name resolution +fn get_completion_token(text: &Rope, line: RopeSlice, pos: Position) -> String { + let mut token = String::new(); + let mut line_iter = line.chars(); + for _ in 0..(line.utf16_cu_to_char(pos.character as usize)) { + line_iter.next(); + } + let mut c = line_iter.prev(); + //TODO: make this a regex + while c.is_some() + && (c.unwrap().is_alphanumeric() + || c.unwrap() == '_' + || c.unwrap() == '.' + || c.unwrap() == '[' + || c.unwrap() == ']') + { + token.push(c.unwrap()); + c = line_iter.prev(); + } + let mut result: String = token.chars().rev().collect(); + if result.contains('[') { + let l_bracket_offset = result.find('[').unwrap_or(result.len()); + result.replace_range(l_bracket_offset.., ""); + } + if &result == "." { + // probably a instantiation, the token should be what we're instatiating + let mut char_iter = text.chars(); + let mut token = String::new(); + for _ in 0..text.pos_to_char(&pos) { + char_iter.next(); + } + let mut c = char_iter.prev(); + + // go to the last semicolon + while c.is_some() && (c.unwrap() != ';') { + c = char_iter.prev(); + } + // go the the start of the next symbol + while c.is_some() && !(c.unwrap().is_alphanumeric() || c.unwrap() == '_') { + c = char_iter.next(); + } + // then extract the next symbol + while c.is_some() && (c.unwrap().is_alphanumeric() || c.unwrap() == '_') { + token.push(c.unwrap()); + c = char_iter.next(); + } + token + } else { + result + } +} + +#[cfg(test)] +mod tests { + use super::*; + use crate::definition::def_types::Scope; + use crate::definition::get_scopes; + use crate::sources::{parse, LSPSupport}; + use crate::support::test_init; + use ropey::Rope; + + #[test] + fn test_get_completion_token() { + test_init(); + let text = Rope::from_str("abc abc.cba de_fg cde[4]"); + let mut result = get_completion_token( + &text, + text.line(0), + Position { + line: 0, + character: 3, + }, + ); + assert_eq!(&result, "abc"); + result = get_completion_token( + &text, + text.line(0), + Position { + line: 0, + character: 11, + }, + ); + assert_eq!(&result, "abc.cba"); + result = get_completion_token( + &text, + text.line(0), + Position { + line: 0, + character: 16, + }, + ); + assert_eq!(&result, "de_f"); + result = get_completion_token( + &text, + text.line(0), + Position { + line: 0, + character: 23, + }, + ); + assert_eq!(&result, "cde"); + } + + #[test] + fn test_completion() { + test_init(); + let server = LSPServer::new(None); + let uri = Url::parse("file:///test.sv").unwrap(); + let text = r#"module test; + logic abc; + logic abcd; + +endmodule +"#; + let open_params = DidOpenTextDocumentParams { + text_document: TextDocumentItem { + uri: uri.clone(), + language_id: "systemverilog".to_owned(), + version: 0, + text: text.to_owned(), + }, + }; + server.did_open(open_params); + let fid = server.srcs.get_id(&uri); + server.srcs.wait_parse_ready(fid, true); + + let change_params = DidChangeTextDocumentParams { + text_document: VersionedTextDocumentIdentifier { + uri: uri.clone(), + version: 3, + }, + content_changes: vec![ + TextDocumentContentChangeEvent { + range: Some(Range { + start: Position { + line: 3, + character: 0, + }, + end: Position { + line: 3, + character: 0, + }, + }), + range_length: None, + text: "\n".to_owned(), + }, + TextDocumentContentChangeEvent { + range: Some(Range { + start: Position { + line: 4, + character: 0, + }, + end: Position { + line: 4, + character: 0, + }, + }), + range_length: None, + text: " ".to_owned(), + }, + TextDocumentContentChangeEvent { + range: Some(Range { + start: Position { + line: 4, + character: 2, + }, + end: Position { + line: 4, + character: 2, + }, + }), + range_length: None, + text: "a".to_owned(), + }, + ], + }; + server.did_change(change_params); + server.srcs.wait_parse_ready(fid, true); + + let completion_params = CompletionParams { + text_document_position: TextDocumentPositionParams { + text_document: TextDocumentIdentifier { uri }, + position: Position { + line: 4, + character: 3, + }, + }, + work_done_progress_params: WorkDoneProgressParams::default(), + partial_result_params: PartialResultParams::default(), + context: Some(CompletionContext { + trigger_kind: CompletionTriggerKind::INVOKED, + trigger_character: None, + }), + }; + let response: CompletionResponse = server.completion(completion_params).unwrap(); + let item1 = CompletionItem { + label: "abc".to_owned(), + kind: Some(CompletionItemKind::VARIABLE), + detail: Some("logic".to_string()), + ..CompletionItem::default() + }; + let item2 = CompletionItem { + label: "abcd".to_owned(), + kind: Some(CompletionItemKind::VARIABLE), + detail: Some("logic".to_string()), + ..CompletionItem::default() + }; + if let CompletionResponse::List(item) = response { + assert!(item.items.contains(&item1)); + assert!(item.items.contains(&item2)); + } else { + panic!(); + } + } + + #[test] + fn test_nested_completion() { + test_init(); + let server = LSPServer::new(None); + let uri = Url::parse("file:///test.sv").unwrap(); + let text = r#"module test; + logic aouter; + function func1(); + logic abc; + func1 = abc; + endfunction + function func2(); + logic abcd; + func2 = abcd; + endfunction +endmodule +"#; + let open_params = DidOpenTextDocumentParams { + text_document: TextDocumentItem { + uri: uri.clone(), + language_id: "systemverilog".to_owned(), + version: 0, + text: text.to_owned(), + }, + }; + server.did_open(open_params); + let fid = server.srcs.get_id(&uri); + server.srcs.wait_parse_ready(fid, true); + + let change_params = DidChangeTextDocumentParams { + text_document: VersionedTextDocumentIdentifier { + uri: uri.clone(), + version: 3, + }, + content_changes: vec![ + TextDocumentContentChangeEvent { + range: Some(Range { + start: Position { + line: 4, + character: 0, + }, + end: Position { + line: 4, + character: 0, + }, + }), + range_length: None, + text: "\n".to_owned(), + }, + TextDocumentContentChangeEvent { + range: Some(Range { + start: Position { + line: 4, + character: 0, + }, + end: Position { + line: 4, + character: 0, + }, + }), + range_length: None, + text: " ".to_owned(), + }, + TextDocumentContentChangeEvent { + range: Some(Range { + start: Position { + line: 4, + character: 2, + }, + end: Position { + line: 4, + character: 2, + }, + }), + range_length: None, + text: "a".to_owned(), + }, + ], + }; + server.did_change(change_params); + server.srcs.wait_parse_ready(fid, true); + + let completion_params = CompletionParams { + text_document_position: TextDocumentPositionParams { + text_document: TextDocumentIdentifier { uri }, + position: Position { + line: 4, + character: 3, + }, + }, + work_done_progress_params: WorkDoneProgressParams::default(), + partial_result_params: PartialResultParams::default(), + context: Some(CompletionContext { + trigger_kind: CompletionTriggerKind::INVOKED, + trigger_character: None, + }), + }; + let response: CompletionResponse = server.completion(completion_params).unwrap(); + let item1 = CompletionItem { + label: "abc".to_owned(), + kind: Some(CompletionItemKind::VARIABLE), + detail: Some("logic".to_string()), + ..CompletionItem::default() + }; + let item3 = CompletionItem { + label: "aouter".to_owned(), + kind: Some(CompletionItemKind::VARIABLE), + detail: Some("logic".to_string()), + ..CompletionItem::default() + }; + if let CompletionResponse::List(item) = response { + eprintln!("{:#?}", item); + assert!(item.items.contains(&item1)); + for comp in &item.items { + assert!(comp.label != "abcd"); + } + assert!(item.items.contains(&item3)); + } else { + panic!(); + } + } + + #[test] + fn test_dot_completion() { + test_init(); + let server = LSPServer::new(None); + let uri = Url::parse("file:///test.sv").unwrap(); + let text = r#"interface test_inter; + wire abcd; +endinterface +module test( + test_inter abc +); + abc. + test_inter. +endmodule +"#; + let open_params = DidOpenTextDocumentParams { + text_document: TextDocumentItem { + uri: uri.clone(), + language_id: "systemverilog".to_owned(), + version: 0, + text: text.to_owned(), + }, + }; + server.did_open(open_params); + let fid = server.srcs.get_id(&uri); + server.srcs.wait_parse_ready(fid, true); + let file = server.srcs.get_file(fid).unwrap(); + let file = file.read().unwrap(); + eprintln!("{}", file.syntax_tree.as_ref().unwrap()); + eprintln!( + "{:#?}", + server.srcs.scope_tree.read().unwrap().as_ref().unwrap() + ); + + let completion_params = CompletionParams { + text_document_position: TextDocumentPositionParams { + text_document: TextDocumentIdentifier { uri: uri.clone() }, + position: Position { + line: 6, + character: 8, + }, + }, + work_done_progress_params: WorkDoneProgressParams::default(), + partial_result_params: PartialResultParams::default(), + context: Some(CompletionContext { + trigger_kind: CompletionTriggerKind::TRIGGER_CHARACTER, + trigger_character: Some(".".to_string()), + }), + }; + let response: CompletionResponse = server.completion(completion_params).unwrap(); + dbg!(&response); + let item1 = CompletionItem { + label: "abcd".to_owned(), + kind: Some(CompletionItemKind::VARIABLE), + detail: Some("wire".to_string()), + ..CompletionItem::default() + }; + if let CompletionResponse::List(item) = response { + eprintln!("{:#?}", item); + assert!(item.items.contains(&item1)); + assert!(item.items.len() == 1); + } else { + panic!(); + } + let completion_params = CompletionParams { + text_document_position: TextDocumentPositionParams { + text_document: TextDocumentIdentifier { uri }, + position: Position { + line: 7, + character: 14, + }, + }, + work_done_progress_params: WorkDoneProgressParams::default(), + partial_result_params: PartialResultParams::default(), + context: Some(CompletionContext { + trigger_kind: CompletionTriggerKind::TRIGGER_CHARACTER, + trigger_character: Some(".".to_string()), + }), + }; + let response: CompletionResponse = server.completion(completion_params).unwrap(); + if let CompletionResponse::List(item) = response { + eprintln!("{:#?}", item); + assert!(item.items.contains(&item1)); + assert!(item.items.len() == 1); + } else { + panic!(); + } + } + + #[test] + fn test_trigger_dot_nocontext() { + test_init(); + let server = LSPServer::new(None); + let uri = Url::parse("file:///test.sv").unwrap(); + let text = r#"interface test_inter; + wire abcd; +endinterface +module test( + test_inter abc +); + abc. + test_inter. +endmodule +"#; + let open_params = DidOpenTextDocumentParams { + text_document: TextDocumentItem { + uri: uri.clone(), + language_id: "systemverilog".to_owned(), + version: 0, + text: text.to_owned(), + }, + }; + server.did_open(open_params); + let fid = server.srcs.get_id(&uri); + server.srcs.wait_parse_ready(fid, true); + let file = server.srcs.get_file(fid).unwrap(); + let file = file.read().unwrap(); + eprintln!("{}", file.syntax_tree.as_ref().unwrap()); + eprintln!( + "{:#?}", + server.srcs.scope_tree.read().unwrap().as_ref().unwrap() + ); + + let completion_params = CompletionParams { + text_document_position: TextDocumentPositionParams { + text_document: TextDocumentIdentifier { uri: uri.clone() }, + position: Position { + line: 6, + character: 8, + }, + }, + work_done_progress_params: WorkDoneProgressParams::default(), + partial_result_params: PartialResultParams::default(), + context: None, + }; + let response: CompletionResponse = server.completion(completion_params).unwrap(); + dbg!(&response); + let item1 = CompletionItem { + label: "abcd".to_owned(), + kind: Some(CompletionItemKind::VARIABLE), + detail: Some("wire".to_string()), + ..CompletionItem::default() + }; + if let CompletionResponse::List(item) = response { + eprintln!("{:#?}", item); + assert!(item.items.contains(&item1)); + assert!(item.items.len() == 1); + } else { + panic!(); + } + let completion_params = CompletionParams { + text_document_position: TextDocumentPositionParams { + text_document: TextDocumentIdentifier { uri }, + position: Position { + line: 7, + character: 14, + }, + }, + work_done_progress_params: WorkDoneProgressParams::default(), + partial_result_params: PartialResultParams::default(), + context: Some(CompletionContext { + trigger_kind: CompletionTriggerKind::TRIGGER_CHARACTER, + trigger_character: Some(".".to_string()), + }), + }; + let response: CompletionResponse = server.completion(completion_params).unwrap(); + if let CompletionResponse::List(item) = response { + eprintln!("{:#?}", item); + assert!(item.items.contains(&item1)); + assert!(item.items.len() == 1); + } else { + panic!(); + } + } + + #[test] + fn test_dot_completion_instantiation() { + test_init(); + let text = r#"interface test_inter; + wire wrong; + logic clk; +endinterface +module test; + logic clk; + test_inter2 t ( + .clk(clk), + . + ) +endmodule +interface test_inter2; + wire abcd; + logic clk; +endinterface +"#; + + let doc = Rope::from_str(&text); + let url = Url::parse("file:///test.sv").unwrap(); + let syntax_tree = parse(&doc, &url, &None, &Vec::new()).unwrap(); + let scope_tree = get_scopes(&syntax_tree, &url).unwrap(); + let pos = Position::new(8, 9); + let token = get_completion_token(&doc, doc.line(pos.line as usize), pos); + let completions = scope_tree.get_dot_completion( + token.trim_end_matches('.'), + doc.pos_to_byte(&pos), + &url, + &scope_tree, + ); + let labels: Vec = completions.iter().map(|x| x.label.clone()).collect(); + assert_eq!(labels, vec!["abcd", "clk"]); + } + + /* + #[test] + fn test_package_completion() { + test_init(); + let text = r#"package p; + struct {int x;} s1; + struct {int x;} s2; + function void f(); + int x; + endfunction + endpackage + module m; + import p::*; + if (1) begin : s1 + initial begin + s1.x = 1; + f.x = 1; + end + int x; + end + endmodule + "#; + + let doc = Rope::from_str(&text); + let url = Url::parse("file:///test.sv").unwrap(); + let syntax_tree = parse(&doc, &url, &None, &Vec::new()).unwrap(); + let scope_tree = get_scopes(&syntax_tree, &url).unwrap(); + dbg!(&scope_tree); + /* + let pos = Position::new(8, 9); + let token = get_completion_token(&doc, doc.line(pos.line as usize), pos); + let completions = scope_tree.get_dot_completion( + token.trim_end_matches('.'), + doc.pos_to_byte(&pos), + &url, + &scope_tree, + ); + let labels: Vec = completions.iter().map(|x| x.label.clone()).collect(); + assert_eq!(labels, vec!["abcd", "clk"]); + */ + panic!(); + } + */ + + #[test] + fn test_inter_file_completion() { + test_init(); + let server = LSPServer::new(None); + let uri = Url::parse("file:///test.sv").unwrap(); + let uri2 = Url::parse("file:///test2.sv").unwrap(); + let text = r#"module test; + s +endmodule +"#; + let text2 = r#"interface simple_bus; + logic clk; +endinterface"#; + let open_params = DidOpenTextDocumentParams { + text_document: TextDocumentItem { + uri: uri.clone(), + language_id: "systemverilog".to_owned(), + version: 0, + text: text.to_owned(), + }, + }; + let open_params2 = DidOpenTextDocumentParams { + text_document: TextDocumentItem { + uri: uri2.clone(), + language_id: "systemverilog".to_owned(), + version: 0, + text: text2.to_owned(), + }, + }; + server.did_open(open_params); + server.did_open(open_params2); + let fid = server.srcs.get_id(&uri); + let fid2 = server.srcs.get_id(&uri2); + server.srcs.wait_parse_ready(fid, true); + server.srcs.wait_parse_ready(fid2, true); + + let completion_params = CompletionParams { + text_document_position: TextDocumentPositionParams { + text_document: TextDocumentIdentifier { uri }, + position: Position { + line: 1, + character: 5, + }, + }, + work_done_progress_params: WorkDoneProgressParams::default(), + partial_result_params: PartialResultParams::default(), + context: Some(CompletionContext { + trigger_kind: CompletionTriggerKind::INVOKED, + trigger_character: None, + }), + }; + let response: CompletionResponse = server.completion(completion_params).unwrap(); + let scope_tree = server.srcs.scope_tree.read().unwrap(); + dbg!(scope_tree.as_ref().unwrap()); + if let CompletionResponse::List(item) = response { + // eprintln!("{:#?}", item); + let names: Vec<&String> = item.items.iter().map(|x| &x.label).collect(); + assert!(names.contains(&&"simple_bus".to_string())); + } else { + panic!(); + } + } +} diff --git a/src/completion/keyword.rs b/src/completion/keyword.rs new file mode 100644 index 0000000..c277790 --- /dev/null +++ b/src/completion/keyword.rs @@ -0,0 +1,466 @@ +use tower_lsp::lsp_types::*; + +pub fn keyword_completions(keywords: &[(&str, &str)]) -> Vec { + let mut items: Vec = Vec::new(); + for key in keywords { + if key.1.is_empty() { + items.push(CompletionItem { + label: key.0.to_string(), + kind: Some(CompletionItemKind::KEYWORD), + ..CompletionItem::default() + }); + } else { + items.push(CompletionItem { + label: key.0.to_string(), + kind: Some(CompletionItemKind::KEYWORD), + insert_text: Some(key.1.to_string()), + insert_text_format: Some(InsertTextFormat::SNIPPET), + ..CompletionItem::default() + }) + } + } + items +} + +pub fn other_completions(tasks: &[&str]) -> Vec { + tasks + .iter() + .map(|x| CompletionItem { + label: x.to_string(), + kind: Some(CompletionItemKind::FUNCTION), + ..CompletionItem::default() + }) + .collect() +} + +pub const KEYWORDS: &[(&str, &str)] = &[ + ("accept_on", ""), + ("alias", ""), + ("always", "always @($1) begin\nend"), + ("always_comb", "always_comb begin\n\t$1\nend"), + ("always_ff", "always_ff @($1) begin\nend"), + ("always_latch", "always_latch begin\n\t$1\nend"), + ("and", ""), + ("assert", ""), + ("assign", ""), + ("assume", ""), + ("automatic", ""), + ("before", ""), + ("begin", "begin\n\t$1\nend"), + ("bind", ""), + ("bins", ""), + ("binsof", ""), + ("bit", ""), + ("break", ""), + ("buf", ""), + ("bufif0", ""), + ("bufif1", ""), + ("byte", ""), + ("case", "case $1;\nendcase"), + ("casex", "casex $1;\nendcase"), + ("casez", "casez $1;\nendcase"), + ("cell", ""), + ("chandle", ""), + ("checker", "checker $1;\nendchecker"), + ("class", "class $1;\nendclass"), + ("clocking", "clocking $1;\nendclocking"), + ("cmos", ""), + ("config", "config $1;\nendconfig"), + ("const", ""), + ("constraint", ""), + ("context", ""), + ("continue", ""), + ("cover", ""), + ("covergroup", ""), + ("coverpoint", ""), + ("cross", ""), + ("deassign", ""), + ("default", ""), + ("defparam", ""), + ("design", ""), + ("disable", ""), + ("dist", ""), + ("do", ""), + ("edge", ""), + ("else", ""), + ("end", ""), + ("endcase", ""), + ("endchecker", ""), + ("endclass", ""), + ("endclocking", ""), + ("endconfig", ""), + ("endfunction", ""), + ("endgenerate", ""), + ("endgroup", ""), + ("endinterface", ""), + ("endmodule", ""), + ("endpackage", ""), + ("endprimitive", ""), + ("endprogram", ""), + ("endproperty", ""), + ("endspecify", ""), + ("endsequence", ""), + ("endtable", ""), + ("endtask", ""), + ("enum", ""), + ("event", ""), + ("eventually", ""), + ("expect", ""), + ("export", ""), + ("extends", ""), + ("extern", ""), + ("final", ""), + ("first_match", ""), + ("for", ""), + ("force", ""), + ("foreach", ""), + ("forever", ""), + ("fork", ""), + ("forkjoin", ""), + ("function", "function $1;\nendfunction"), + ("generate", "generate\n\t$1\nendgenerate"), + ("genvar", ""), + ("global", ""), + ("highz0", ""), + ("highz1", ""), + ("if", ""), + ("iff", ""), + ("ifnone", ""), + ("ignore_bins", ""), + ("illegal_bins", ""), + ("implements", ""), + ("implies", ""), + ("import", ""), + ("incdir", ""), + ("include", ""), + ("initial", ""), + ("inout", ""), + ("input", ""), + ("inside", ""), + ("instance", ""), + ("int", ""), + ("integer", ""), + ("interconnect", ""), + ("interface", "interface $1;\nendinterface"), + ("intersect", ""), + ("join", ""), + ("join_any", ""), + ("join_none", ""), + ("large", ""), + ("let", ""), + ("liblist", ""), + ("library", ""), + ("local", ""), + ("localparam", ""), + ("logic", ""), + ("longint", ""), + ("macromodule", ""), + ("matches", ""), + ("medium", ""), + ("modport", ""), + ("module", "module $1 ($2);\nendmodule"), + ("nand", ""), + ("negedge", ""), + ("nettype", ""), + ("new", ""), + ("nexttime", ""), + ("nmos", ""), + ("nor", ""), + ("noshowcancelled", ""), + ("not", ""), + ("notif0", ""), + ("notif1", ""), + ("null", ""), + ("or", ""), + ("output", ""), + ("package", "package $1;\nendpackage"), + ("packed", ""), + ("parameter", ""), + ("pmos", ""), + ("posedge", ""), + ("primitive", "primitive $1;\nendprimitive"), + ("priority", ""), + ("program", "program $1;\nendprogram"), + ("property", "property $1;\nendproperty"), + ("protected", ""), + ("pull0", ""), + ("pull1", ""), + ("pulldown", ""), + ("pullup", ""), + ("pulsestyle_ondetect", ""), + ("pulsestyle_onevent", ""), + ("pure", ""), + ("rand", ""), + ("randc", ""), + ("randcase", ""), + ("randsequence", ""), + ("rcmos", ""), + ("real", ""), + ("realtime", ""), + ("ref", ""), + ("reg", ""), + ("reject_on", ""), + ("release", ""), + ("repeat", ""), + ("restrict", ""), + ("return", ""), + ("rnmos", ""), + ("rpmos", ""), + ("rtran", ""), + ("rtranif0", ""), + ("rtranif1", ""), + ("s_always", ""), + ("s_eventually", ""), + ("s_nexttime", ""), + ("s_until", ""), + ("s_until_with", ""), + ("scalared", ""), + ("sequence", "sequence $1;\nendsequence"), + ("shortint", ""), + ("shortreal", ""), + ("showcancelled", ""), + ("signed", ""), + ("small", ""), + ("soft", ""), + ("solve", ""), + ("specify", "specify $1;\nendspecify"), + ("specparam", ""), + ("static", ""), + ("string", ""), + ("strong", ""), + ("strong0", ""), + ("strong1", ""), + ("struct", ""), + ("super", ""), + ("supply0", ""), + ("supply1", ""), + ("sync_accept_on", ""), + ("sync_reject_on", ""), + ("table", "table $1;\nendtable"), + ("tagged", ""), + ("task", "task $1;\nendtask"), + ("this", ""), + ("throughout", ""), + ("time", ""), + ("timeprecision", ""), + ("timeunit", ""), + ("tran", ""), + ("tranif0", ""), + ("tranif1", ""), + ("tri", ""), + ("tri0", ""), + ("tri1", ""), + ("triand", ""), + ("trior", ""), + ("trireg", ""), + ("type", ""), + ("typedef", ""), + ("union", ""), + ("unique", ""), + ("unique0", ""), + ("unsigned", ""), + ("until", ""), + ("until_with", ""), + ("untyped", ""), + ("use", ""), + ("uwire", ""), + ("var", ""), + ("vectored", ""), + ("virtual", ""), + ("void", ""), + ("wait", ""), + ("wait_order", ""), + ("wand", ""), + ("weak", ""), + ("weak0", ""), + ("weak1", ""), + ("while", ""), + ("wildcard", ""), + ("wire", ""), + ("with", ""), + ("within", ""), + ("wor", ""), + ("xnor", ""), + ("xor", ""), +]; + +pub const SYS_TASKS: &[&str] = &[ + "finish", + "exit", + "fatal", + "warning", + "stop", + "error", + "info", + "realtime", + "time", + "asserton", + "assertkill", + "assertpasson", + "assertfailon", + "assertnonvacuouson", + "stime", + "printtimescale", + "timeformat", + "bitstoreal", + "bitstoshortreal", + "itor", + "signed", + "cast", + "realtobits", + "shortrealtobits", + "rtoi", + "unsigned", + "sampled", + "fell", + "changed", + "past_gclk", + "fell_gclk", + "changed_gclk", + "rising_gclk", + "steady_gclk", + "bits", + "typename", + "isunbounded", + "coverage_control", + "coverage_get", + "coverage_save", + "set_coverage_db_name", + "dimensions", + "right", + "high", + "size", + "random", + "dist_erlang", + "dist_normal", + "dist_t", + "asin", + "acos", + "atan", + "atan2", + "hypot", + "sinh", + "cosh", + "tanh", + "asinh", + "acosh", + "atanh", + "q_initialize", + "q_remove", + "q_exam", + "q_add", + "q_full", + "async$and$array", + "async$nand$array", + "async$or$array", + "async$nor$array", + "sync$and$array", + "sync$nand$array", + "sync$or$array", + "sync$nor$array", + "countones", + "onehot0", + "fatal", + "warning", + "dist_chi_square", + "dist_exponential", + "dist_poisson", + "dist_uniform", + "countbits", + "onehot", + "isunknown", + "coverage_get_max", + "coverage_merge", + "get_coverage", + "load_coverage_db", + "clog2", + "ln", + "log10", + "exp", + "sqrt", + "pow", + "floor", + "ceil", + "sin", + "cos", + "tan", + "rose", + "stable", + "past", + "rose_gclk", + "stable_gclk", + "future_gclk", + "falling_gclk", + "changing_gclk", + "unpacked_dimensions", + "left", + "low", + "increment", + "assertoff", + "assertcontrol", + "assertpassoff", + "assertfailoff", + "assertvacuousoff", + "error", + "info", + "async$and$plane", + "async$nand$plane", + "async$or$plane", + "async$nor$plane", + "sync$and$plane", + "sync$nand$plane", + "sync$or$plane", + "sync$nor$plane", + "system", + "countdrivers", + "getpattern", + "incsave", + "input", + "key", + "list", + "log", + "nokey", + "nolog", + "reset", + "reset_count", + "reset_value", + "restart", + "save", + "scale", + "scope", + "showscopes", + "showvars", + "sreadmemb", + "sreadmemh", +]; + +pub const DIRECTIVES: &[&str] = &[ + "__FILE__", + "__LINE__", + "begin_keywords", + "celldefine", + "default_nettype", + "define", + "else", + "elsif", + "end_keywords", + "endcelldefine", + "endif", + "ifdef", + "ifndef", + "include", + "line", + "nounconnected_drive", + "pragma", + "resetall", + "timescale", + "unconnected_drive", + "undef", + "undefineall", + "default_decay_time", + "default_trireg_strength", + "delay_mode_distributed", + "delay_mode_path", + "delay_mode_unit", + "delay_mode_zero", +]; diff --git a/src/definition.rs b/src/definition.rs new file mode 100644 index 0000000..4a76a37 --- /dev/null +++ b/src/definition.rs @@ -0,0 +1,499 @@ +use crate::definition::extract_defs::get_ident; +use crate::server::LSPServer; +use crate::sources::LSPSupport; +use log::{debug, trace}; +use ropey::{Rope, RopeSlice}; +use sv_parser::*; +use tower_lsp::lsp_types::*; + +pub mod def_types; +pub use def_types::*; + +mod extract_defs; +use extract_defs::*; + +impl LSPServer { + pub fn goto_definition(&self, params: GotoDefinitionParams) -> Option { + let doc = params.text_document_position_params.text_document.uri; + let pos = params.text_document_position_params.position; + let file_id = self.srcs.get_id(&doc).to_owned(); + self.srcs.wait_parse_ready(file_id, false); + let file = self.srcs.get_file(file_id)?; + let file = file.read().ok()?; + let token = get_definition_token(file.text.line(pos.line as usize), pos); + debug!("goto definition, token: {}", &token); + let scope_tree = self.srcs.scope_tree.read().ok()?; + trace!("{:#?}", scope_tree.as_ref()?); + let def = scope_tree + .as_ref()? + .get_definition(&token, file.text.pos_to_byte(&pos), &doc)?; + let def_pos = file.text.byte_to_pos(def.byte_idx()); + debug!("def: {:?}", def_pos); + Some(GotoDefinitionResponse::Scalar(Location::new( + def.url(), + Range::new(def_pos, def_pos), + ))) + } + + pub fn hover(&self, params: HoverParams) -> Option { + let doc = params.text_document_position_params.text_document.uri; + let pos = params.text_document_position_params.position; + let file_id = self.srcs.get_id(&doc).to_owned(); + self.srcs.wait_parse_ready(file_id, false); + let file = self.srcs.get_file(file_id)?; + let file = file.read().ok()?; + let token = get_definition_token(file.text.line(pos.line as usize), pos); + debug!("hover, token: {}", &token); + let scope_tree = self.srcs.scope_tree.read().ok()?; + let def = scope_tree + .as_ref()? + .get_definition(&token, file.text.pos_to_byte(&pos), &doc)?; + let def_line = file.text.byte_to_line(def.byte_idx()); + Some(Hover { + contents: HoverContents::Scalar(MarkedString::LanguageString(LanguageString { + language: "systemverilog".to_owned(), + value: get_hover(&file.text, def_line), + })), + range: None, + }) + } + + pub fn document_symbol(&self, params: DocumentSymbolParams) -> Option { + let uri = params.text_document.uri; + let file_id = self.srcs.get_id(&uri).to_owned(); + self.srcs.wait_parse_ready(file_id, false); + let file = self.srcs.get_file(file_id)?; + let file = file.read().ok()?; + let scope_tree = self.srcs.scope_tree.read().ok()?; + Some(DocumentSymbolResponse::Nested( + scope_tree.as_ref()?.document_symbols(&uri, &file.text), + )) + } + + pub fn document_highlight( + &self, + params: DocumentHighlightParams, + ) -> Option> { + let uri = params.text_document_position_params.text_document.uri; + let pos = params.text_document_position_params.position; + let file_id = self.srcs.get_id(&uri).to_owned(); + self.srcs.wait_parse_ready(file_id, false); + let file = self.srcs.get_file(file_id)?; + let file = file.read().ok()?; + let token = get_definition_token(file.text.line(pos.line as usize), pos); + let scope_tree = self.srcs.scope_tree.read().ok()?; + // use the byte_idx of the definition if possible, otherwise use the cursor + let byte_idx = + match scope_tree + .as_ref()? + .get_definition(&token, file.text.pos_to_byte(&pos), &uri) + { + Some(def) => def.byte_idx, + None => file.text.pos_to_byte(&pos), + }; + let syntax_tree = file.syntax_tree.as_ref()?; + let references = all_identifiers(syntax_tree, &token); + Some( + scope_tree + .as_ref()? + .document_highlights(&uri, &file.text, references, byte_idx), + ) + } +} + +/// return all identifiers in a syntax tree matching a given token +fn all_identifiers(syntax_tree: &SyntaxTree, token: &str) -> Vec<(String, usize)> { + let mut idents: Vec<(String, usize)> = Vec::new(); + for node in syntax_tree { + if let RefNode::Identifier(_) = node { + let (ident, byte_idx) = get_ident(syntax_tree, node); + if ident == token { + idents.push((ident, byte_idx)); + } + } + } + idents +} + +/// retrieve the token the user invoked goto definition or hover on +fn get_definition_token(line: RopeSlice, pos: Position) -> String { + let mut token = String::new(); + let mut line_iter = line.chars(); + for _ in 0..(line.utf16_cu_to_char(pos.character as usize)) { + line_iter.next(); + } + let mut c = line_iter.prev(); + while c.is_some() && (c.unwrap().is_alphanumeric() || c.unwrap() == '_') { + token.push(c.unwrap()); + c = line_iter.prev(); + } + token = token.chars().rev().collect(); + line_iter = line.chars(); + for _ in 0..(line.utf16_cu_to_char(pos.character as usize)) { + line_iter.next(); + } + let mut c = line_iter.next(); + while c.is_some() && (c.unwrap().is_alphanumeric() || c.unwrap() == '_') { + token.push(c.unwrap()); + c = line_iter.next(); + } + token +} + +type ScopesAndDefs = Option<(Vec>, Vec>)>; + +/// Take a given syntax node from a sv-parser syntax tree and extract out the definition/scope at +/// that point. +pub fn match_definitions( + syntax_tree: &SyntaxTree, + event_iter: &mut EventIter, + node: RefNode, + url: &Url, +) -> ScopesAndDefs { + let mut definitions: Vec> = Vec::new(); + let mut scopes: Vec> = Vec::new(); + match node { + RefNode::ModuleDeclaration(n) => { + let module = module_dec(syntax_tree, n, event_iter, url); + if module.is_some() { + scopes.push(Box::new(module?)); + } + } + RefNode::InterfaceDeclaration(n) => { + let interface = interface_dec(syntax_tree, n, event_iter, url); + if interface.is_some() { + scopes.push(Box::new(interface?)); + } + } + RefNode::UdpDeclaration(n) => { + let dec = udp_dec(syntax_tree, n, event_iter, url); + if dec.is_some() { + scopes.push(Box::new(dec?)); + } + } + RefNode::ProgramDeclaration(n) => { + let dec = program_dec(syntax_tree, n, event_iter, url); + if dec.is_some() { + scopes.push(Box::new(dec?)); + } + } + RefNode::PackageDeclaration(n) => { + let dec = package_dec(syntax_tree, n, event_iter, url); + if dec.is_some() { + scopes.push(Box::new(dec?)); + } + } + RefNode::ConfigDeclaration(n) => { + let dec = config_dec(syntax_tree, n, event_iter, url); + if dec.is_some() { + scopes.push(Box::new(dec?)); + } + } + RefNode::ClassDeclaration(n) => { + let dec = class_dec(syntax_tree, n, event_iter, url); + if dec.is_some() { + scopes.push(Box::new(dec?)); + } + } + RefNode::PortDeclaration(n) => { + let ports = port_dec_non_ansi(syntax_tree, n, event_iter, url); + if ports.is_some() { + for port in ports? { + definitions.push(Box::new(port)); + } + } + } + RefNode::NetDeclaration(n) => { + let nets = net_dec(syntax_tree, n, event_iter, url); + if nets.is_some() { + for net in nets? { + definitions.push(Box::new(net)); + } + } + } + RefNode::DataDeclaration(n) => { + let vars = data_dec(syntax_tree, n, event_iter, url); + if let Some(vars) = vars { + for var in vars { + match var { + Declaration::Dec(dec) => definitions.push(Box::new(dec)), + Declaration::Import(dec) => definitions.push(Box::new(dec)), + Declaration::Scope(scope) => scopes.push(Box::new(scope)), + } + } + } + } + RefNode::ParameterDeclaration(n) => { + let vars = param_dec(syntax_tree, n, event_iter, url); + if vars.is_some() { + for var in vars? { + definitions.push(Box::new(var)); + } + } + } + RefNode::LocalParameterDeclaration(n) => { + let vars = localparam_dec(syntax_tree, n, event_iter, url); + if vars.is_some() { + for var in vars? { + definitions.push(Box::new(var)); + } + } + } + RefNode::FunctionDeclaration(n) => { + let dec = function_dec(syntax_tree, n, event_iter, url); + if dec.is_some() { + scopes.push(Box::new(dec?)); + } + } + RefNode::TaskDeclaration(n) => { + let dec = task_dec(syntax_tree, n, event_iter, url); + if dec.is_some() { + scopes.push(Box::new(dec?)); + } + } + RefNode::ModportDeclaration(n) => { + let decs = modport_dec(syntax_tree, n, event_iter, url); + if decs.is_some() { + for dec in decs? { + definitions.push(Box::new(dec)); + } + } + } + RefNode::ModuleInstantiation(n) => { + let decs = module_inst(syntax_tree, n, event_iter, url); + if decs.is_some() { + for dec in decs? { + definitions.push(Box::new(dec)); + } + } + } + RefNode::TextMacroDefinition(n) => { + let dec = text_macro_def(syntax_tree, n, event_iter, url); + if dec.is_some() { + definitions.push(Box::new(dec?)); + } + } + _ => (), + } + Some((scopes, definitions)) +} + +/// convert the syntax tree to a scope tree +/// the root node is the global scope +pub fn get_scopes(syntax_tree: &SyntaxTree, url: &Url) -> Option { + trace!("{}", syntax_tree); + let mut scopes: Vec> = Vec::new(); + let mut global_scope: GenericScope = GenericScope::new(url); + global_scope.ident = "global".to_string(); + let mut event_iter = syntax_tree.into_iter().event(); + // iterate over each enter event and extract out any scopes or definitions + // match_definitions is recursively called so we get a tree in the end + while let Some(event) = event_iter.next() { + match event { + NodeEvent::Enter(node) => { + let mut result = match_definitions(syntax_tree, &mut event_iter, node, url)?; + global_scope.defs.append(&mut result.1); + scopes.append(&mut result.0); + } + NodeEvent::Leave(_) => (), + } + } + global_scope.scopes.append(&mut scopes); + Some(global_scope) +} + +/// get the hover information +fn get_hover(doc: &Rope, line: usize) -> String { + if line == 0 { + return doc.line(line).to_string(); + } + let mut hover: Vec = Vec::new(); + let mut multiline: bool = false; + let mut valid: bool = true; + let mut current: String = doc.line(line).to_string(); + let ltrim: String = " ".repeat(current.len() - current.trim_start().len()); + let mut line_idx = line; + + // iterate upwards from the definition, and grab the comments + while valid { + hover.push(current.clone()); + line_idx -= 1; + valid = false; + if line_idx > 0 { + current = doc.line(line_idx).to_string(); + let currentl = current.clone().trim_start().to_owned(); + let currentr = current.clone().trim_end().to_owned(); + if currentl.starts_with("/*") && currentr.ends_with("*/") { + valid = true; + } else if currentr.ends_with("*/") { + multiline = true; + valid = true; + } else if currentl.starts_with("/*") { + multiline = false; + valid = true; + } else { + valid = currentl.starts_with("//") || multiline; + } + } + } + hover.reverse(); + let mut result: Vec = Vec::new(); + for i in hover { + if let Some(stripped) = i.strip_prefix(<rim) { + result.push(stripped.to_owned()); + } else { + result.push(i); + } + } + result.join("").trim_end().to_owned() +} + +#[cfg(test)] +mod tests { + use super::*; + use crate::sources::{parse, LSPSupport}; + use crate::support::test_init; + use ropey::Rope; + use std::fs::read_to_string; + use std::path::PathBuf; + + #[test] + fn test_definition_token() { + test_init(); + let line = Rope::from_str("assign ab_c[2:0] = 3'b000;"); + let token = get_definition_token(line.line(0), Position::new(0, 10)); + assert_eq!(token, "ab_c".to_owned()); + } + + #[test] + fn test_get_definition() { + test_init(); + let mut d = PathBuf::from(env!("CARGO_MANIFEST_DIR")); + d.push("test_data/definition_test.sv"); + let text = read_to_string(d).unwrap(); + let doc = Rope::from_str(&text); + let url = Url::parse("file:///test_data/definition_test.sv").unwrap(); + let syntax_tree = parse(&doc, &url, &None, &Vec::new()).unwrap(); + trace!("{}", &syntax_tree); + let scope_tree = get_scopes(&syntax_tree, &url).unwrap(); + trace!("{:#?}", &scope_tree); + for def in &scope_tree.defs { + trace!("{:?} {:?}", def, doc.byte_to_pos(def.byte_idx())); + } + let token = get_definition_token(doc.line(3), Position::new(3, 13)); + for def in scope_tree.defs { + if token == def.ident() { + assert_eq!(doc.byte_to_pos(def.byte_idx()), Position::new(3, 9)) + } + } + } + + #[test] + fn test_hover() { + test_init(); + let text = r#" +// module test +// test module +module test; + /* a */ + logic a; + /** + * b + */ + logic b; + endmodule"#; + let doc = Rope::from_str(text); + eprintln!("{}", get_hover(&doc, 2)); + assert_eq!( + get_hover(&doc, 3), + r#"// module test +// test module +module test;"# + .to_owned() + ); + assert_eq!( + get_hover(&doc, 9), + r#"/** + * b +*/ +logic b;"# + .to_owned() + ); + } + + #[test] + fn test_symbols() { + test_init(); + let text = r#" +module test; + logic a; + logic b; +endmodule"#; + let doc = Rope::from_str(&text); + let url = Url::parse("file:///test.sv").unwrap(); + let syntax_tree = parse(&doc, &url, &None, &Vec::new()).unwrap(); + let scope_tree = get_scopes(&syntax_tree, &url).unwrap(); + let symbol = scope_tree.document_symbols(&url, &doc); + let symbol = symbol.get(0).unwrap(); + assert_eq!(&symbol.name, "test"); + let names: Vec = symbol + .children + .as_ref() + .unwrap() + .iter() + .map(|x| x.name.clone()) + .collect(); + assert!(names.contains(&"a".to_string())); + assert!(names.contains(&"b".to_string())); + } + + #[test] + fn test_highlight() { + test_init(); + let text = r#" +module test; + logic clk; + assign clk = 1'b1; +endmodule"#; + let doc = Rope::from_str(&text); + let url = Url::parse("file:///test.sv").unwrap(); + let syntax_tree = parse(&doc, &url, &None, &Vec::new()).unwrap(); + let scope_tree = get_scopes(&syntax_tree, &url).unwrap(); + let references = all_identifiers(&syntax_tree, "clk"); + let highlights = scope_tree.document_highlights( + &url, + &doc, + references, + doc.pos_to_byte(&Position::new(2, 8)), + ); + let expected = vec![ + DocumentHighlight { + range: Range { + start: Position { + line: 2, + character: 8, + }, + end: Position { + line: 2, + character: 11, + }, + }, + kind: None, + }, + DocumentHighlight { + range: Range { + start: Position { + line: 3, + character: 9, + }, + end: Position { + line: 3, + character: 12, + }, + }, + kind: None, + }, + ]; + assert_eq!(highlights, expected) + } +} diff --git a/src/definition/def_types.rs b/src/definition/def_types.rs new file mode 100644 index 0000000..1bc6683 --- /dev/null +++ b/src/definition/def_types.rs @@ -0,0 +1,965 @@ +use crate::sources::LSPSupport; +use log::trace; +use ropey::Rope; +use tower_lsp::lsp_types::*; + +/// cleanup the text of a definition so it can be included in completions +pub fn clean_type_str(type_str: &str, ident: &str) -> String { + let endings: &[_] = &[';', ',']; + // remove anything after an equals sign + let eq_offset = type_str.find('=').unwrap_or(type_str.len()); + let mut result = type_str.to_string(); + result.replace_range(eq_offset.., ""); + result + .trim_start() + .trim_end() + .trim_end_matches(endings) + .trim_end_matches(ident) + .split_whitespace() + .collect::>() + .join(" ") + .replace("[ ", "[") + .replace(" ]", "]") + .replace(" : ", ":") +} + +pub fn copy_defs(defs: &[Box]) -> Vec> { + let mut decs: Vec> = Vec::new(); + for def in defs { + decs.push(Box::new(GenericDec { + ident: def.ident(), + byte_idx: def.byte_idx(), + url: def.url(), + type_str: def.type_str(), + completion_kind: def.completion_kind(), + symbol_kind: def.symbol_kind(), + def_type: def.def_type(), + })) + } + decs +} + +pub fn copy_scopes(scopes: &[Box]) -> Vec> { + let mut scope_decs: Vec> = Vec::new(); + for scope in scopes { + let mut scope_copy = GenericScope { + ident: scope.ident(), + byte_idx: scope.byte_idx(), + start: scope.start(), + end: scope.end(), + url: scope.url(), + type_str: scope.type_str(), + completion_kind: scope.completion_kind(), + symbol_kind: scope.symbol_kind(), + def_type: scope.def_type(), + defs: Vec::new(), + scopes: Vec::new(), + }; + scope_copy.defs.extend(copy_defs(scope.defs())); + scope_copy.scopes.extend(copy_scopes(scope.scopes())); + scope_decs.push(Box::new(scope_copy)) + } + scope_decs +} + +/// A definition of any SystemVerilog variable or construct +pub trait Definition: std::fmt::Debug + Sync + Send { + // identifier + fn ident(&self) -> String; + // byte index in file of definition + fn byte_idx(&self) -> usize; + // url pointing to the file the definition is in + fn url(&self) -> Url; + // cleaned up text of the definition + fn type_str(&self) -> String; + // the kind of this definition, for use in completions + fn completion_kind(&self) -> CompletionItemKind; + // the kind of this definition, for use in showing document symbols + // for some reason this kind is different than CompletionItemKind + fn symbol_kind(&self) -> SymbolKind; + // the kind of this definition, simplified for internal use + fn def_type(&self) -> DefinitionType; + // whether the definition identifier starts with the given token + fn starts_with(&self, token: &str) -> bool; + // constructs the completion for this definition + fn completion(&self) -> CompletionItem; + fn dot_completion(&self, scope_tree: &GenericScope) -> Vec; +} + +pub trait Scope: std::fmt::Debug + Definition + Sync + Send { + // the start byte of this scope + fn start(&self) -> usize; + // the end byte of this scope + fn end(&self) -> usize; + // all the within this scope + fn defs(&self) -> &Vec>; + // all the scopes within this scope, ex. task inside a module + fn scopes(&self) -> &Vec>; + // the definition of this scope + fn definition(&self) -> GenericDec { + GenericDec { + ident: self.ident(), + byte_idx: self.byte_idx(), + url: self.url(), + type_str: self.type_str(), + completion_kind: self.completion_kind(), + symbol_kind: self.symbol_kind(), + def_type: DefinitionType::GenericScope, + } + } + /// return a completion from the scope tree, this function should be called on the global scope + fn get_completion(&self, token: &str, byte_idx: usize, url: &Url) -> Vec { + let mut completions: Vec = Vec::new(); + // first we need to go down the scope tree, to the scope the user is invoking a completion + // in + for scope in self.scopes() { + if &scope.url() == url && scope.start() <= byte_idx && byte_idx <= scope.end() { + completions = scope.get_completion(token, byte_idx, url); + break; + } + } + // now that we are in the users scope, we can attempt to find a relevant completion + // we proceed back upwards through the scope tree, adding any definitions that match + // the users token + let completion_idents: Vec = completions.iter().map(|x| x.label.clone()).collect(); + for def in self.defs() { + if !completion_idents.contains(&def.ident()) && def.starts_with(token) { + completions.push(def.completion()); + } + } + for scope in self.scopes() { + if scope.starts_with(token) { + completions.push(scope.completion()); + } + } + completions + } + + /// return a dot completion from the scope tree, this function should be called on the global + /// scope + fn get_dot_completion( + &self, + token: &str, + byte_idx: usize, + url: &Url, + scope_tree: &GenericScope, + ) -> Vec { + trace!("dot entering: {}, token: {}", self.ident(), token); + trace!("{:?}", self.scopes()); + // first we need to go down the scope tree, to the scope the user is invoking a completion + // in + for scope in self.scopes() { + trace!( + "{}, {}, {}, {}", + scope.ident(), + byte_idx, + scope.start(), + scope.end() + ); + if &scope.url() == url && scope.start() <= byte_idx && byte_idx <= scope.end() { + eprintln!("checking dot completion: {}", scope.ident()); + let result = scope.get_dot_completion(token, byte_idx, url, scope_tree); + if !result.is_empty() { + return result; + } + } + } + // now that we are in the users scope, we can attempt to find the relevant definition + // we proceed back upwards through the scope tree, and if a definition matches our token, + // we invoke dot completion on that definition and pass it the syntax tree + for def in self.defs() { + trace!("def: {:?}", def); + if def.starts_with(token) { + trace!("complete def: {:?}", def); + return def.dot_completion(scope_tree); + } + } + for scope in self.scopes() { + if scope.starts_with(token) { + trace!("found dot-completion scope: {}", scope.ident()); + return scope.dot_completion(scope_tree); + } + } + Vec::new() + } + + /// return a definition from the scope tree, this function should be called on the global + /// scope + fn get_definition(&self, token: &str, byte_idx: usize, url: &Url) -> Option { + let mut definition: Option = None; + for scope in self.scopes() { + if &scope.url() == url && scope.start() <= byte_idx && byte_idx <= scope.end() { + definition = scope.get_definition(token, byte_idx, url); + break; + } + } + if definition.is_none() { + for def in self.defs() { + if def.ident() == token { + return Some(GenericDec { + ident: def.ident(), + byte_idx: def.byte_idx(), + url: def.url(), + type_str: def.type_str(), + completion_kind: def.completion_kind(), + symbol_kind: def.symbol_kind(), + def_type: DefinitionType::Net, + }); + } + } + for scope in self.scopes() { + if scope.ident() == token { + return Some(scope.definition()); + } + } + } + definition + } + /// returns all symbols in a document + fn document_symbols(&self, uri: &Url, doc: &Rope) -> Vec { + let mut symbols: Vec = Vec::new(); + for scope in self.scopes() { + if &scope.url() == uri { + #[allow(deprecated)] + symbols.push(DocumentSymbol { + name: scope.ident(), + detail: Some(scope.type_str()), + kind: scope.symbol_kind(), + deprecated: None, + range: Range::new(doc.byte_to_pos(scope.start()), doc.byte_to_pos(scope.end())), + selection_range: Range::new( + doc.byte_to_pos(scope.byte_idx()), + doc.byte_to_pos(scope.byte_idx() + scope.ident().len()), + ), + children: Some(scope.document_symbols(uri, doc)), + tags: None, + }) + } + } + for def in self.defs() { + #[allow(deprecated)] + symbols.push(DocumentSymbol { + name: def.ident(), + detail: Some(def.type_str()), + kind: def.symbol_kind(), + deprecated: None, + range: Range::new( + doc.byte_to_pos(def.byte_idx()), + doc.byte_to_pos(def.byte_idx() + def.ident().len()), + ), + selection_range: Range::new( + doc.byte_to_pos(def.byte_idx()), + doc.byte_to_pos(def.byte_idx() + def.ident().len()), + ), + children: None, + tags: None, + }) + } + symbols + } + + /// highlight all references of a symbol + fn document_highlights( + &self, + uri: &Url, + doc: &Rope, + // all references in the doc's syntax tree + references: Vec<(String, usize)>, + // byte_idx of symbol definition + byte_idx: usize, + ) -> Vec { + // to find references we need to grab references from locations downward from the + // definition + for scope in self.scopes() { + if &scope.url() == uri && scope.start() <= byte_idx && byte_idx <= scope.end() { + return scope.document_highlights(uri, doc, references, byte_idx); + } + } + // we should now be in the scope of the definition, so we can grab all references + // in this scope. This also grabs references below this scope. + references + .iter() + .filter(|x| self.start() <= x.1 && x.1 <= self.end()) + .map(|x| DocumentHighlight { + range: Range::new(doc.byte_to_pos(x.1), doc.byte_to_pos(x.1 + x.0.len())), + kind: None, + }) + .collect() + } +} + +#[derive(Debug, Clone, Copy)] +pub enum DefinitionType { + Port, + Net, + Data, + Modport, + Subroutine, + ModuleInstantiation, + GenericScope, + Class, +} + +#[derive(Debug)] +pub struct PortDec { + pub ident: String, + pub byte_idx: usize, + pub url: Url, + pub type_str: String, + pub completion_kind: CompletionItemKind, + pub symbol_kind: SymbolKind, + pub def_type: DefinitionType, + pub interface: Option, + pub modport: Option, +} + +impl PortDec { + pub fn new(url: &Url) -> Self { + Self { + ident: String::new(), + byte_idx: 0, + type_str: String::new(), + completion_kind: CompletionItemKind::PROPERTY, + symbol_kind: SymbolKind::PROPERTY, + def_type: DefinitionType::Port, + interface: None, + modport: None, + url: url.clone(), + } + } +} + +impl Definition for PortDec { + fn ident(&self) -> String { + self.ident.clone() + } + fn byte_idx(&self) -> usize { + self.byte_idx + } + fn url(&self) -> Url { + self.url.clone() + } + fn type_str(&self) -> String { + self.type_str.clone() + } + fn completion_kind(&self) -> CompletionItemKind { + self.completion_kind + } + fn symbol_kind(&self) -> SymbolKind { + self.symbol_kind + } + fn def_type(&self) -> DefinitionType { + self.def_type + } + fn starts_with(&self, token: &str) -> bool { + self.ident.starts_with(token) + } + fn completion(&self) -> CompletionItem { + CompletionItem { + label: self.ident.clone(), + detail: Some(clean_type_str(&self.type_str, &self.ident)), + kind: Some(self.completion_kind), + ..CompletionItem::default() + } + } + fn dot_completion(&self, scope_tree: &GenericScope) -> Vec { + for scope in &scope_tree.scopes { + if let Some(interface) = &self.interface { + if &scope.ident() == interface { + return match &self.modport { + Some(modport) => { + for def in scope.defs() { + if def.starts_with(modport) { + return def.dot_completion(scope_tree); + } + } + Vec::new() + } + None => scope + .defs() + .iter() + .filter(|x| !x.starts_with(&scope.ident())) + .map(|x| x.completion()) + .collect(), + }; + } + } + } + Vec::new() + } +} + +#[derive(Debug)] +pub struct GenericDec { + pub ident: String, + pub byte_idx: usize, + pub url: Url, + pub type_str: String, + pub completion_kind: CompletionItemKind, + pub symbol_kind: SymbolKind, + pub def_type: DefinitionType, +} + +impl GenericDec { + pub fn new(url: &Url) -> Self { + Self { + ident: String::new(), + byte_idx: 0, + url: url.clone(), + type_str: String::new(), + completion_kind: CompletionItemKind::VARIABLE, + // FIXME: check if this replacement is correct + symbol_kind: SymbolKind::NULL, + def_type: DefinitionType::Net, + } + } +} + +impl Definition for GenericDec { + fn ident(&self) -> String { + self.ident.clone() + } + fn byte_idx(&self) -> usize { + self.byte_idx + } + fn url(&self) -> Url { + self.url.clone() + } + fn type_str(&self) -> String { + self.type_str.clone() + } + fn completion_kind(&self) -> CompletionItemKind { + self.completion_kind + } + fn symbol_kind(&self) -> SymbolKind { + self.symbol_kind + } + fn def_type(&self) -> DefinitionType { + self.def_type + } + fn starts_with(&self, token: &str) -> bool { + self.ident.starts_with(token) + } + fn completion(&self) -> CompletionItem { + CompletionItem { + label: self.ident.clone(), + detail: Some(clean_type_str(&self.type_str, &self.ident)), + kind: Some(self.completion_kind), + ..CompletionItem::default() + } + } + fn dot_completion(&self, _: &GenericScope) -> Vec { + Vec::new() + } +} + +#[derive(Debug)] +pub struct PackageImport { + pub ident: String, + pub byte_idx: usize, + pub url: Url, + pub type_str: String, + pub completion_kind: CompletionItemKind, + pub symbol_kind: SymbolKind, + pub def_type: DefinitionType, + pub asterisk: bool, + pub import_ident: Option, +} + +impl PackageImport { + pub fn new(url: &Url) -> Self { + Self { + ident: String::new(), + byte_idx: 0, + url: url.clone(), + type_str: String::new(), + completion_kind: CompletionItemKind::TEXT, + symbol_kind: SymbolKind::NAMESPACE, + def_type: DefinitionType::Data, + asterisk: false, + import_ident: None, + } + } +} + +impl Definition for PackageImport { + fn ident(&self) -> String { + self.ident.clone() + } + fn byte_idx(&self) -> usize { + self.byte_idx + } + fn url(&self) -> Url { + self.url.clone() + } + fn type_str(&self) -> String { + self.type_str.clone() + } + fn completion_kind(&self) -> CompletionItemKind { + self.completion_kind + } + fn symbol_kind(&self) -> SymbolKind { + self.symbol_kind + } + fn def_type(&self) -> DefinitionType { + self.def_type + } + fn starts_with(&self, token: &str) -> bool { + self.ident.starts_with(token) + } + fn completion(&self) -> CompletionItem { + CompletionItem { + label: self.ident.clone(), + detail: Some(clean_type_str(&self.type_str, &self.ident.clone())), + kind: Some(self.completion_kind), + ..CompletionItem::default() + } + } + fn dot_completion(&self, _: &GenericScope) -> Vec { + Vec::new() + } +} + +#[derive(Debug)] +pub struct SubDec { + pub ident: String, + pub byte_idx: usize, + pub url: Url, + pub type_str: String, + pub completion_kind: CompletionItemKind, + pub symbol_kind: SymbolKind, + pub def_type: DefinitionType, + pub start: usize, + pub end: usize, + pub defs: Vec>, + pub scopes: Vec>, +} + +impl SubDec { + pub fn new(url: &Url) -> Self { + Self { + ident: String::new(), + byte_idx: 0, + url: url.clone(), + type_str: String::new(), + completion_kind: CompletionItemKind::FUNCTION, + symbol_kind: SymbolKind::FUNCTION, + def_type: DefinitionType::Subroutine, + start: 0, + end: 0, + defs: Vec::new(), + scopes: Vec::new(), + } + } +} + +impl Definition for SubDec { + fn ident(&self) -> String { + self.ident.clone() + } + fn byte_idx(&self) -> usize { + self.byte_idx + } + fn url(&self) -> Url { + self.url.clone() + } + fn type_str(&self) -> String { + self.type_str.clone() + } + fn completion_kind(&self) -> CompletionItemKind { + self.completion_kind + } + fn symbol_kind(&self) -> SymbolKind { + self.symbol_kind + } + fn def_type(&self) -> DefinitionType { + self.def_type + } + fn starts_with(&self, token: &str) -> bool { + self.ident.starts_with(token) + } + fn completion(&self) -> CompletionItem { + CompletionItem { + label: self.ident.clone(), + detail: Some(clean_type_str(&self.type_str, &self.ident)), + kind: Some(self.completion_kind), + ..CompletionItem::default() + } + } + fn dot_completion(&self, _: &GenericScope) -> Vec { + Vec::new() + } +} + +impl Scope for SubDec { + fn start(&self) -> usize { + self.start + } + + fn end(&self) -> usize { + self.end + } + fn defs(&self) -> &Vec> { + &self.defs + } + + fn scopes(&self) -> &Vec> { + &self.scopes + } +} + +#[derive(Debug)] +pub struct ModportDec { + pub ident: String, + pub byte_idx: usize, + pub url: Url, + pub type_str: String, + pub completion_kind: CompletionItemKind, + pub symbol_kind: SymbolKind, + pub def_type: DefinitionType, + pub ports: Vec>, +} + +impl ModportDec { + pub fn new(url: &Url) -> Self { + Self { + ident: String::new(), + byte_idx: 0, + url: url.clone(), + type_str: String::new(), + completion_kind: CompletionItemKind::INTERFACE, + symbol_kind: SymbolKind::INTERFACE, + def_type: DefinitionType::Modport, + ports: Vec::new(), + } + } +} + +impl Definition for ModportDec { + fn ident(&self) -> String { + self.ident.clone() + } + fn byte_idx(&self) -> usize { + self.byte_idx + } + fn url(&self) -> Url { + self.url.clone() + } + fn type_str(&self) -> String { + self.type_str.clone() + } + fn completion_kind(&self) -> CompletionItemKind { + self.completion_kind + } + fn symbol_kind(&self) -> SymbolKind { + self.symbol_kind + } + fn def_type(&self) -> DefinitionType { + self.def_type + } + fn starts_with(&self, token: &str) -> bool { + self.ident.starts_with(token) + } + fn completion(&self) -> CompletionItem { + CompletionItem { + label: self.ident.clone(), + detail: Some(clean_type_str(&self.type_str, &self.ident)), + kind: Some(self.completion_kind), + ..CompletionItem::default() + } + } + fn dot_completion(&self, _: &GenericScope) -> Vec { + self.ports.iter().map(|x| x.completion()).collect() + } +} + +#[derive(Debug)] +pub struct ModInst { + pub ident: String, + pub byte_idx: usize, + pub url: Url, + pub type_str: String, + pub completion_kind: CompletionItemKind, + pub symbol_kind: SymbolKind, + pub def_type: DefinitionType, + pub mod_ident: String, +} + +impl ModInst { + pub fn new(url: &Url) -> Self { + Self { + ident: String::new(), + byte_idx: 0, + url: url.clone(), + type_str: String::new(), + completion_kind: CompletionItemKind::MODULE, + symbol_kind: SymbolKind::MODULE, + def_type: DefinitionType::ModuleInstantiation, + mod_ident: String::new(), + } + } +} + +impl Definition for ModInst { + fn ident(&self) -> String { + self.ident.clone() + } + fn byte_idx(&self) -> usize { + self.byte_idx + } + fn url(&self) -> Url { + self.url.clone() + } + fn type_str(&self) -> String { + self.type_str.clone() + } + fn completion_kind(&self) -> CompletionItemKind { + self.completion_kind + } + fn symbol_kind(&self) -> SymbolKind { + self.symbol_kind + } + fn def_type(&self) -> DefinitionType { + self.def_type + } + fn starts_with(&self, token: &str) -> bool { + self.ident.starts_with(token) + } + fn completion(&self) -> CompletionItem { + CompletionItem { + label: self.ident.clone(), + detail: Some(clean_type_str(&self.type_str, &self.ident)), + kind: Some(self.completion_kind), + ..CompletionItem::default() + } + } + fn dot_completion(&self, scope_tree: &GenericScope) -> Vec { + for scope in &scope_tree.scopes { + if scope.ident() == self.mod_ident { + return scope + .defs() + .iter() + .filter(|x| !x.starts_with(&scope.ident())) + .map(|x| x.completion()) + .collect(); + } + } + Vec::new() + } +} + +#[derive(Debug)] +pub struct GenericScope { + pub ident: String, + pub byte_idx: usize, + pub start: usize, + pub end: usize, + pub url: Url, + pub type_str: String, + pub completion_kind: CompletionItemKind, + pub symbol_kind: SymbolKind, + pub def_type: DefinitionType, + pub defs: Vec>, + pub scopes: Vec>, +} + +impl GenericScope { + pub fn new(url: &Url) -> Self { + Self { + ident: String::new(), + byte_idx: 0, + start: 0, + end: 0, + url: url.clone(), + type_str: String::new(), + completion_kind: CompletionItemKind::MODULE, + symbol_kind: SymbolKind::MODULE, + def_type: DefinitionType::GenericScope, + defs: Vec::new(), + scopes: Vec::new(), + } + } + + #[cfg(test)] + pub fn contains_scope(&self, scope_ident: &str) -> bool { + for scope in &self.scopes { + if scope.starts_with(scope_ident) { + return true; + } + } + false + } +} + +impl Definition for GenericScope { + fn ident(&self) -> String { + self.ident.clone() + } + fn byte_idx(&self) -> usize { + self.byte_idx + } + fn url(&self) -> Url { + self.url.clone() + } + fn type_str(&self) -> String { + self.type_str.clone() + } + fn completion_kind(&self) -> CompletionItemKind { + self.completion_kind + } + fn symbol_kind(&self) -> SymbolKind { + self.symbol_kind + } + fn def_type(&self) -> DefinitionType { + self.def_type + } + fn starts_with(&self, token: &str) -> bool { + self.ident.starts_with(token) + } + fn completion(&self) -> CompletionItem { + CompletionItem { + label: self.ident.clone(), + detail: Some(clean_type_str(&self.type_str, &self.ident)), + kind: Some(self.completion_kind), + ..CompletionItem::default() + } + } + fn dot_completion(&self, scope_tree: &GenericScope) -> Vec { + for scope in scope_tree.scopes() { + if scope.ident() == self.ident { + return scope + .defs() + .iter() + .filter(|x| !x.starts_with(&scope.ident())) + .map(|x| x.completion()) + .collect(); + } + } + Vec::new() + } +} + +impl Scope for GenericScope { + fn start(&self) -> usize { + self.start + } + + fn end(&self) -> usize { + self.end + } + + fn defs(&self) -> &Vec> { + &self.defs + } + + fn scopes(&self) -> &Vec> { + &self.scopes + } +} + +#[derive(Debug)] +pub struct ClassDec { + pub ident: String, + pub byte_idx: usize, + pub start: usize, + pub end: usize, + pub url: Url, + pub type_str: String, + pub completion_kind: CompletionItemKind, + pub symbol_kind: SymbolKind, + pub def_type: DefinitionType, + pub defs: Vec>, + pub scopes: Vec>, + // class, package + pub extends: (Vec, Option), + // class, package + pub implements: Vec<(String, Option)>, + pub interface: bool, +} + +impl ClassDec { + pub fn new(url: &Url) -> Self { + Self { + ident: String::new(), + byte_idx: 0, + start: 0, + end: 0, + url: url.clone(), + type_str: String::new(), + completion_kind: CompletionItemKind::CLASS, + symbol_kind: SymbolKind::CLASS, + def_type: DefinitionType::Class, + defs: Vec::new(), + scopes: Vec::new(), + extends: (Vec::new(), None), + implements: Vec::new(), + interface: false, + } + } +} + +impl Definition for ClassDec { + fn ident(&self) -> String { + self.ident.clone() + } + fn byte_idx(&self) -> usize { + self.byte_idx + } + fn url(&self) -> Url { + self.url.clone() + } + fn type_str(&self) -> String { + self.type_str.clone() + } + fn completion_kind(&self) -> CompletionItemKind { + self.completion_kind + } + fn symbol_kind(&self) -> SymbolKind { + self.symbol_kind + } + fn def_type(&self) -> DefinitionType { + self.def_type + } + fn starts_with(&self, token: &str) -> bool { + self.ident.starts_with(token) + } + fn completion(&self) -> CompletionItem { + CompletionItem { + label: self.ident.clone(), + detail: Some(clean_type_str(&self.type_str, &self.ident)), + kind: Some(self.completion_kind), + ..CompletionItem::default() + } + } + fn dot_completion(&self, scope_tree: &GenericScope) -> Vec { + for scope in scope_tree.scopes() { + if scope.ident() == self.ident { + return scope + .defs() + .iter() + .filter(|x| !x.starts_with(&scope.ident())) + .map(|x| x.completion()) + .collect(); + } + } + Vec::new() + } +} + +impl Scope for ClassDec { + fn start(&self) -> usize { + self.start + } + + fn end(&self) -> usize { + self.end + } + + fn defs(&self) -> &Vec> { + &self.defs + } + + fn scopes(&self) -> &Vec> { + &self.scopes + } +} diff --git a/src/definition/extract_defs.rs b/src/definition/extract_defs.rs new file mode 100644 index 0000000..9749ec9 --- /dev/null +++ b/src/definition/extract_defs.rs @@ -0,0 +1,2314 @@ +use crate::definition::def_types::*; +use crate::definition::match_definitions; +use sv_parser::*; +use tower_lsp::lsp_types::*; + +pub fn get_ident(tree: &SyntaxTree, node: RefNode) -> (String, usize) { + let loc = unwrap_locate!(node).unwrap(); + let ident_str = tree.get_str(loc).unwrap().to_string(); + let byte_idx = tree.get_origin(loc).unwrap().1; + (ident_str, byte_idx) +} + +fn get_loc(tree: &SyntaxTree, node: RefNode) -> usize { + let loc = unwrap_locate!(node).unwrap(); + tree.get_origin(loc).unwrap().1 +} + +macro_rules! advance_until_leave { + ($tokens:ident, $tree:ident, $event_iter:ident, $node:path) => {{ + let mut result: Option = None; + while let Some(event) = $event_iter.next() { + match event { + NodeEvent::Leave(x) => match x { + $node(node) => { + result = Some($node(node)); + break; + } + RefNode::Locate(node) => { + $tokens.push(' '); + $tokens.push_str($tree.get_str(node)?); + } + _ => (), + }, + NodeEvent::Enter(_) => (), + } + } + result + }}; +} + +macro_rules! advance_until_enter { + ($tokens:ident, $tree:ident, $event_iter:ident, $node:path, $type:ty) => {{ + let mut result: Option<$type> = None; + while let Some(event) = $event_iter.next() { + match event { + NodeEvent::Enter(x) => match x { + $node(node) => { + result = Some(node); + break; + } + RefNode::Locate(node) => { + $tokens.push(' '); + $tokens.push_str($tree.get_str(node)?); + } + _ => (), + }, + NodeEvent::Leave(_) => (), + } + } + result + }}; +} + +macro_rules! skip_until_enter { + ($tree:ident, $event_iter:ident, $node:path, $type:ty) => {{ + let mut result: Option<$type> = None; + while let Some(event) = $event_iter.next() { + match event { + NodeEvent::Enter(x) => match x { + $node(node) => { + result = Some(node); + break; + } + _ => (), + }, + NodeEvent::Leave(_) => (), + } + } + result + }}; +} + +macro_rules! skip_until_leave { + ($tree:ident, $event_iter:ident, $node:path) => { + while let Some(event) = $event_iter.next() { + match event { + NodeEvent::Enter(_) => (), + NodeEvent::Leave(x) => match x { + $node(_) => { + break; + } + _ => (), + }, + } + } + }; +} + +macro_rules! match_until_leave { + ($tree:ident, $event_iter:ident, $url:ident, $node:path) => {{ + let mut scopes: Vec> = Vec::new(); + let mut definitions: Vec> = Vec::new(); + let mut global_scope: GenericScope = GenericScope::new($url); + global_scope.ident = "global".to_string(); + while let Some(event) = $event_iter.next() { + match event { + NodeEvent::Enter(node) => { + let mut result = match_definitions($tree, $event_iter, node, $url)?; + definitions.append(&mut result.1); + scopes.append(&mut result.0); + } + NodeEvent::Leave(node) => match node { + $node(_) => { + break; + } + _ => {} + }, + } + } + Some((scopes, definitions)) + }}; +} + +pub fn port_dec_ansi( + tree: &SyntaxTree, + node: &AnsiPortDeclaration, + event_iter: &mut EventIter, + url: &Url, +) -> Option { + let mut port = PortDec::new(url); + let mut tokens = String::new(); + match node { + AnsiPortDeclaration::Net(x) => { + let ident = get_ident(tree, RefNode::PortIdentifier(&x.nodes.1)); + port.ident = ident.0; + port.byte_idx = ident.1; + if let Some(NetPortHeaderOrInterfacePortHeader::InterfacePortHeader(z)) = &x.nodes.0 { + match &**z { + InterfacePortHeader::Identifier(node) => { + port.interface = + Some(get_ident(tree, RefNode::InterfaceIdentifier(&node.nodes.0)).0); + match &node.nodes.1 { + Some((_, mod_ident)) => { + port.modport = + Some(get_ident(tree, RefNode::ModportIdentifier(mod_ident)).0); + } + None => (), + } + } + InterfacePortHeader::Interface(node) => { + port.interface = Some("interface".to_string()); + match &node.nodes.1 { + Some((_, mod_ident)) => { + port.modport = + Some(get_ident(tree, RefNode::ModportIdentifier(mod_ident)).0); + } + None => (), + } + } + } + } + } + AnsiPortDeclaration::Variable(x) => { + let ident = get_ident(tree, RefNode::PortIdentifier(&x.nodes.1)); + port.ident = ident.0; + port.byte_idx = ident.1; + } + AnsiPortDeclaration::Paren(x) => { + let ident = get_ident(tree, RefNode::PortIdentifier(&x.nodes.2)); + port.ident = ident.0; + port.byte_idx = ident.1; + } + } + advance_until_leave!(tokens, tree, event_iter, RefNode::AnsiPortDeclaration); + port.type_str = clean_type_str(&tokens, &port.ident); + Some(port) +} + +pub fn list_port_idents( + tree: &SyntaxTree, + node: &ListOfPortIdentifiers, + event_iter: &mut EventIter, + url: &Url, +) -> Option> { + let mut ports: Vec = Vec::new(); + for port_def in node.nodes.0.contents() { + let mut port = PortDec::new(url); + let ident = get_ident(tree, RefNode::PortIdentifier(&port_def.0)); + port.ident = ident.0; + port.byte_idx = ident.1; + for _ in &port_def.1 { + let tokens = &mut port.type_str; + advance_until_leave!(tokens, tree, event_iter, RefNode::UnpackedDimension); + } + ports.push(port); + } + Some(ports) +} + +pub fn list_interface_idents( + tree: &SyntaxTree, + node: &ListOfInterfaceIdentifiers, + event_iter: &mut EventIter, + url: &Url, +) -> Option> { + let mut ports: Vec = Vec::new(); + for port_def in node.nodes.0.contents() { + let mut port = PortDec::new(url); + let ident = get_ident(tree, RefNode::InterfaceIdentifier(&port_def.0)); + port.ident = ident.0; + port.byte_idx = ident.1; + for _ in &port_def.1 { + let tokens = &mut port.type_str; + advance_until_leave!(tokens, tree, event_iter, RefNode::UnpackedDimension); + } + ports.push(port); + } + Some(ports) +} + +pub fn list_variable_idents( + tree: &SyntaxTree, + node: &ListOfVariableIdentifiers, + event_iter: &mut EventIter, + url: &Url, +) -> Option> { + let mut ports: Vec = Vec::new(); + for port_def in node.nodes.0.contents() { + let mut port = PortDec::new(url); + let ident = get_ident(tree, RefNode::VariableIdentifier(&port_def.0)); + port.ident = ident.0; + port.byte_idx = ident.1; + for _ in &port_def.1 { + let tokens = &mut port.type_str; + advance_until_leave!(tokens, tree, event_iter, RefNode::VariableDimension); + } + ports.push(port); + } + Some(ports) +} + +pub fn port_dec_non_ansi( + tree: &SyntaxTree, + node: &PortDeclaration, + event_iter: &mut EventIter, + url: &Url, +) -> Option> { + let mut ports: Vec; + let mut common = String::new(); + match node { + PortDeclaration::Inout(_) => { + let port_list = advance_until_enter!( + common, + tree, + event_iter, + RefNode::ListOfPortIdentifiers, + &ListOfPortIdentifiers + )?; + ports = list_port_idents(tree, port_list, event_iter, url)?; + } + PortDeclaration::Input(x) => match &x.nodes.1 { + InputDeclaration::Net(_) => { + let port_list = advance_until_enter!( + common, + tree, + event_iter, + RefNode::ListOfPortIdentifiers, + &ListOfPortIdentifiers + )?; + ports = list_port_idents(tree, port_list, event_iter, url)?; + } + InputDeclaration::Variable(_) => { + let port_list = advance_until_enter!( + common, + tree, + event_iter, + RefNode::ListOfVariableIdentifiers, + &ListOfVariableIdentifiers + )?; + ports = list_variable_idents(tree, port_list, event_iter, url)?; + } + }, + PortDeclaration::Output(x) => match &x.nodes.1 { + OutputDeclaration::Net(_) => { + let port_list = advance_until_enter!( + common, + tree, + event_iter, + RefNode::ListOfPortIdentifiers, + &ListOfPortIdentifiers + )?; + ports = list_port_idents(tree, port_list, event_iter, url)?; + } + OutputDeclaration::Variable(_) => { + let port_list = advance_until_enter!( + common, + tree, + event_iter, + RefNode::ListOfVariableIdentifiers, + &ListOfVariableIdentifiers + )?; + ports = list_variable_idents(tree, port_list, event_iter, url)?; + } + }, + PortDeclaration::Ref(_) => { + let port_list = advance_until_enter!( + common, + tree, + event_iter, + RefNode::ListOfVariableIdentifiers, + &ListOfVariableIdentifiers + )?; + ports = list_variable_idents(tree, port_list, event_iter, url)?; + } + PortDeclaration::Interface(x) => { + let interface = + Some(get_ident(tree, RefNode::InterfaceIdentifier(&x.nodes.1.nodes.0)).0); + let modport = x + .nodes + .1 + .nodes + .1 + .as_ref() + .map(|(_, mod_ident)| get_ident(tree, RefNode::ModportIdentifier(mod_ident)).0); + let port_list = advance_until_enter!( + common, + tree, + event_iter, + RefNode::ListOfInterfaceIdentifiers, + &ListOfInterfaceIdentifiers + )?; + ports = list_interface_idents(tree, port_list, event_iter, url)?; + for port in &mut ports { + port.interface = interface.clone(); + port.modport = modport.clone(); + } + } + } + for port in &mut ports { + port.type_str = format!("{} {}", common, port.type_str); + } + Some(ports) +} + +pub fn list_net_decl( + tree: &SyntaxTree, + node: &ListOfNetDeclAssignments, + event_iter: &mut EventIter, + url: &Url, +) -> Option> { + let mut nets: Vec = Vec::new(); + for net_def in node.nodes.0.contents() { + let mut net = GenericDec::new(url); + let ident = get_ident(tree, RefNode::NetIdentifier(&net_def.nodes.0)); + net.ident = ident.0; + net.byte_idx = ident.1; + for _ in &net_def.nodes.1 { + let tokens = &mut net.type_str; + advance_until_leave!(tokens, tree, event_iter, RefNode::UnpackedDimension); + } + nets.push(net); + } + Some(nets) +} + +pub fn net_dec( + tree: &SyntaxTree, + node: &NetDeclaration, + event_iter: &mut EventIter, + url: &Url, +) -> Option> { + let mut nets: Vec; + let mut common = String::new(); + match node { + NetDeclaration::NetType(_) => { + let net_list = advance_until_enter!( + common, + tree, + event_iter, + RefNode::ListOfNetDeclAssignments, + &ListOfNetDeclAssignments + )?; + nets = list_net_decl(tree, net_list, event_iter, url)?; + } + NetDeclaration::NetTypeIdentifier(_) => { + let net_list = advance_until_enter!( + common, + tree, + event_iter, + RefNode::ListOfNetDeclAssignments, + &ListOfNetDeclAssignments + )?; + nets = list_net_decl(tree, net_list, event_iter, url)?; + } + NetDeclaration::Interconnect(x) => { + let mut net = GenericDec::new(url); + let ident = get_ident(tree, RefNode::NetIdentifier(&x.nodes.3)); + net.ident = ident.0; + net.byte_idx = ident.1; + advance_until_enter!( + common, + tree, + event_iter, + RefNode::NetIdentifier, + &NetIdentifier + ); + for _ in &x.nodes.4 { + advance_until_leave!(common, tree, event_iter, RefNode::UnpackedDimension); + } + nets = vec![net]; + } + } + for net in &mut nets { + net.completion_kind = CompletionItemKind::VARIABLE; + net.symbol_kind = SymbolKind::VARIABLE; + net.type_str = format!("{} {}", common, net.type_str); + } + Some(nets) +} + +pub fn list_var_decl( + tree: &SyntaxTree, + node: &ListOfVariableDeclAssignments, + event_iter: &mut EventIter, + url: &Url, +) -> Option> { + let mut vars: Vec = Vec::new(); + for var_def in node.nodes.0.contents() { + let mut var = GenericDec::new(url); + match &var_def { + VariableDeclAssignment::Variable(node) => { + let ident = get_ident(tree, RefNode::VariableIdentifier(&node.nodes.0)); + var.ident = ident.0; + var.byte_idx = ident.1; + for _ in &node.nodes.1 { + let tokens = &mut var.type_str; + advance_until_leave!(tokens, tree, event_iter, RefNode::VariableDimension); + } + } + VariableDeclAssignment::DynamicArray(node) => { + let ident = get_ident(tree, RefNode::DynamicArrayVariableIdentifier(&node.nodes.0)); + var.ident = ident.0; + var.byte_idx = ident.1; + for _ in &node.nodes.2 { + let tokens = &mut var.type_str; + advance_until_leave!(tokens, tree, event_iter, RefNode::VariableDimension); + } + } + VariableDeclAssignment::Class(node) => { + let ident = get_ident(tree, RefNode::ClassVariableIdentifier(&node.nodes.0)); + var.ident = ident.0; + var.byte_idx = ident.1; + } + } + vars.push(var); + } + Some(vars) +} + +pub fn package_import( + tree: &SyntaxTree, + node: &PackageImportDeclaration, + _: &mut EventIter, + url: &Url, +) -> Option> { + let mut imports = Vec::new(); + for import_def in node.nodes.1.contents() { + let mut import = PackageImport::new(url); + match import_def { + PackageImportItem::Identifier(y) => { + let ident = get_ident(tree, RefNode::PackageIdentifier(&y.nodes.0)); + import.ident = ident.0; + import.byte_idx = ident.1; + let import_loc = match &y.nodes.2 { + Identifier::SimpleIdentifier(id) => id.nodes.0, + Identifier::EscapedIdentifier(id) => id.nodes.0, + }; + import.import_ident = Some(tree.get_str(&import_loc)?.to_string()); + } + PackageImportItem::Asterisk(y) => { + let ident = get_ident(tree, RefNode::PackageIdentifier(&y.nodes.0)); + import.ident = ident.0; + import.byte_idx = ident.1; + import.asterisk = true; + } + } + imports.push(import); + } + Some(imports) +} + +fn struct_union( + tree: &SyntaxTree, + node: &DataTypeStructUnion, + event_iter: &mut EventIter, + url: &Url, +) -> Option { + let mut scope = GenericScope::new(url); + scope.start = get_loc(tree, RefNode::StructUnion(&node.nodes.0)); + scope.end = get_loc(tree, RefNode::Symbol(&node.nodes.2.nodes.2)); + scope.completion_kind = CompletionItemKind::STRUCT; + scope.symbol_kind = SymbolKind::STRUCT; + let type_str = &mut scope.type_str; + advance_until_leave!(type_str, tree, event_iter, RefNode::Symbol)?; + let mut members = vec![&(node.nodes.2.nodes.1).0]; + for member_def in &(node.nodes.2.nodes.1).1 { + members.push(member_def); + } + for member_def in members { + match member_def.nodes.2 { + DataTypeOrVoid::DataType(_) => { + let mut common = String::new(); + let datatype = + advance_until_enter!(common, tree, event_iter, RefNode::DataType, &DataType)?; + let dec = data_type(tree, datatype, event_iter, url)?; + match dec { + Declaration::Dec(x) => { + let var_list = advance_until_enter!( + common, + tree, + event_iter, + RefNode::ListOfVariableDeclAssignments, + &ListOfVariableDeclAssignments + )?; + let mut decs = list_var_decl(tree, var_list, event_iter, url)?; + advance_until_leave!(common, tree, event_iter, RefNode::StructUnionMember); + for var in &mut decs { + var.type_str = format!("{} {} {}", common, x.type_str, var.type_str); + var.completion_kind = CompletionItemKind::VARIABLE; + var.symbol_kind = SymbolKind::VARIABLE; + } + for var in decs { + scope.defs.push(Box::new(var)); + } + } + Declaration::Scope(x) => { + let var_list = advance_until_enter!( + common, + tree, + event_iter, + RefNode::ListOfVariableDeclAssignments, + &ListOfVariableDeclAssignments + )?; + let mut decs = list_var_decl(tree, var_list, event_iter, url)?; + advance_until_leave!(common, tree, event_iter, RefNode::StructUnionMember); + for var in &mut decs { + var.type_str = format!("{} {} {}", common, x.type_str, var.type_str); + var.completion_kind = CompletionItemKind::VARIABLE; + var.symbol_kind = SymbolKind::VARIABLE; + } + for var in decs { + let mut member_scope = GenericScope::new(url); + member_scope.start = x.start; + member_scope.end = x.end; + member_scope.defs = copy_defs(&x.defs); + member_scope.scopes = copy_scopes(&x.scopes); + member_scope.ident = var.ident; + member_scope.byte_idx = var.byte_idx; + scope.scopes.push(Box::new(member_scope)); + } + } + Declaration::Import(_) => { + // datatype should not return import + unreachable!() + } + } + } + DataTypeOrVoid::Void(_) => { + let mut common = String::new(); + let var_list = advance_until_enter!( + common, + tree, + event_iter, + RefNode::ListOfVariableDeclAssignments, + &ListOfVariableDeclAssignments + )?; + let mut decs = list_var_decl(tree, var_list, event_iter, url)?; + advance_until_leave!(common, tree, event_iter, RefNode::StructUnionMember); + for var in &mut decs { + var.type_str = format!("{} {}", common, var.type_str); + var.completion_kind = CompletionItemKind::VARIABLE; + var.symbol_kind = SymbolKind::VARIABLE; + } + for var in decs { + scope.defs.push(Box::new(var)); + } + } + } + } + skip_until_leave!(tree, event_iter, RefNode::DataTypeStructUnion); + Some(scope) +} + +pub enum Declaration { + Dec(GenericDec), + Scope(GenericScope), + Import(PackageImport), +} + +// this isn't enough for a definition +fn data_type( + tree: &SyntaxTree, + node: &DataType, + event_iter: &mut EventIter, + url: &Url, +) -> Option { + let mut common = String::new(); + match node { + DataType::Vector(_) + | DataType::Atom(_) + | DataType::NonIntegerType(_) + // TODO: set completion_kind and symbol_kind for string and others + | DataType::String(_) + | DataType::Chandle(_) + // TODO: properly handle the following types + | DataType::Virtual(_) + | DataType::Type(_) + | DataType::ClassType(_) + | DataType::Event(_) + | DataType::PsCovergroupIdentifier(_) => { + advance_until_leave!(common, tree, event_iter, RefNode::DataType)?; + let mut dec = GenericDec::new(url); + dec.type_str = common; + Some(Declaration::Dec(dec)) + } + DataType::StructUnion(_) => { + let struct_union_def = advance_until_enter!( + common, + tree, + event_iter, + RefNode::DataTypeStructUnion, + &DataTypeStructUnion + )?; + let def = struct_union( + tree, + struct_union_def, + event_iter, + url, + )?; + advance_until_leave!(common, tree, event_iter, RefNode::DataType)?; + Some(Declaration::Scope(def)) + } + DataType::Enum(node) => { + let mut scope = GenericScope::new(url); + scope.start = get_loc(tree, RefNode::Symbol(&node.nodes.2.nodes.0)); + scope.end = get_loc(tree, RefNode::Symbol(&node.nodes.2.nodes.2)); + scope.completion_kind = CompletionItemKind::ENUM; + scope.symbol_kind = SymbolKind::ENUM; + let mut decs: Vec = Vec::new(); + for emem in node.nodes.2.nodes.1.contents() { + let mut dec = GenericDec::new(url); + let ident = get_ident(tree, RefNode::EnumIdentifier(&emem.nodes.0)); + dec.ident = ident.0; + dec.byte_idx = ident.1; + dec.completion_kind = CompletionItemKind::ENUM_MEMBER; + dec.symbol_kind = SymbolKind::ENUM_MEMBER; + let tokens = &mut dec.type_str; + advance_until_leave!(tokens, tree, event_iter, RefNode::EnumNameDeclaration); + decs.push(dec); + } + advance_until_leave!(common, tree, event_iter, RefNode::DataType)?; + Some(Declaration::Scope(scope)) + } + DataType::TypeReference(node) => { + match **node{ + TypeReference::Expression(_) => { + advance_until_leave!(common, tree, event_iter, RefNode::DataType)?; + let mut dec = GenericDec::new(url); + dec.type_str = common; + Some(Declaration::Dec(dec)) + } + TypeReference::DataType(_) => { + let data_type_node = advance_until_enter!(common, tree, event_iter, RefNode::DataType, &DataType)?; + let data_type_def = data_type(tree, data_type_node, event_iter, url); + advance_until_leave!(common, tree, event_iter, RefNode::DataType)?; + data_type_def + } + } + } + } +} + +pub fn data_dec( + tree: &SyntaxTree, + node: &DataDeclaration, + event_iter: &mut EventIter, + url: &Url, +) -> Option> { + let mut common = String::new(); + let mut data: Vec = Vec::new(); + match node { + DataDeclaration::Variable(x) => match &x.nodes.3 { + DataTypeOrImplicit::DataType(_) => { + let mut common = String::new(); + let datatype = + advance_until_enter!(common, tree, event_iter, RefNode::DataType, &DataType)?; + let dec = data_type(tree, datatype, event_iter, url)?; + match dec { + Declaration::Dec(x) => { + let var_list = advance_until_enter!( + common, + tree, + event_iter, + RefNode::ListOfVariableDeclAssignments, + &ListOfVariableDeclAssignments + )?; + let mut decs = list_var_decl(tree, var_list, event_iter, url)?; + for var in &mut decs { + var.type_str = format!("{} {} {}", common, x.type_str, var.type_str); + var.completion_kind = CompletionItemKind::VARIABLE; + var.symbol_kind = SymbolKind::VARIABLE; + } + for var in decs { + data.push(Declaration::Dec(var)); + } + } + Declaration::Scope(x) => { + let var_list = advance_until_enter!( + common, + tree, + event_iter, + RefNode::ListOfVariableDeclAssignments, + &ListOfVariableDeclAssignments + )?; + let mut decs = list_var_decl(tree, var_list, event_iter, url)?; + for var in &mut decs { + var.type_str = format!("{} {} {}", common, x.type_str, var.type_str); + var.completion_kind = CompletionItemKind::VARIABLE; + var.symbol_kind = SymbolKind::VARIABLE; + } + for var in decs { + data.push(Declaration::Scope(GenericScope { + ident: var.ident, + byte_idx: var.byte_idx, + start: x.start, + end: x.end, + url: url.clone(), + type_str: var.type_str, + completion_kind: x.completion_kind, + symbol_kind: x.symbol_kind, + def_type: x.def_type, + defs: copy_defs(&x.defs), + scopes: copy_scopes(&x.scopes), + })); + } + } + Declaration::Import(_) => { + // datatype should not return import + unreachable!() + } + } + } + DataTypeOrImplicit::ImplicitDataType(_) => { + let var_list = advance_until_enter!( + common, + tree, + event_iter, + RefNode::ListOfVariableDeclAssignments, + &ListOfVariableDeclAssignments + )?; + let mut decs = list_var_decl(tree, var_list, event_iter, url)?; + data = Vec::new(); + for var in &mut decs { + var.type_str = format!("{} {}", common, var.type_str); + var.completion_kind = CompletionItemKind::VARIABLE; + var.symbol_kind = SymbolKind::VARIABLE; + } + for var in decs { + data.push(Declaration::Dec(var)); + } + } + }, + DataDeclaration::TypeDeclaration(x) => match &**x { + TypeDeclaration::DataType(y) => { + let mut common = String::new(); + let datatype = + advance_until_enter!(common, tree, event_iter, RefNode::DataType, &DataType)?; + let dec = data_type(tree, datatype, event_iter, url)?; + match dec { + Declaration::Dec(mut def) => { + let ident = get_ident(tree, RefNode::TypeIdentifier(&y.nodes.2)); + def.ident = ident.0; + def.byte_idx = ident.1; + for _ in &y.nodes.3 { + let tokens = &mut def.type_str; + advance_until_leave!( + tokens, + tree, + event_iter, + RefNode::VariableDimension + ); + } + def.type_str = format!("{} {}", common, def.type_str); + data = vec![Declaration::Dec(def)]; + } + Declaration::Scope(mut def) => { + let ident = get_ident(tree, RefNode::TypeIdentifier(&y.nodes.2)); + def.ident = ident.0; + def.byte_idx = ident.1; + for _ in &y.nodes.3 { + let tokens = &mut def.type_str; + advance_until_leave!( + tokens, + tree, + event_iter, + RefNode::VariableDimension + ); + } + def.type_str = format!("{} {}", common, def.type_str); + data = vec![Declaration::Scope(def)]; + } + Declaration::Import(_) => unreachable!(), + } + } + TypeDeclaration::Interface(y) => { + let mut var = GenericDec::new(url); + let ident = get_ident(tree, RefNode::TypeIdentifier(&y.nodes.5)); + var.ident = ident.0; + var.byte_idx = ident.1; + let mut tokens = String::new(); + advance_until_enter!( + tokens, + tree, + event_iter, + RefNode::TypeIdentifier, + &TypeIdentifier + ); + advance_until_enter!( + tokens, + tree, + event_iter, + RefNode::TypeIdentifier, + &TypeIdentifier + ); + var.type_str = tokens; + var.type_str = format!("{} {}", common, var.type_str); + var.completion_kind = CompletionItemKind::INTERFACE; + var.symbol_kind = SymbolKind::INTERFACE; + data = vec![Declaration::Dec(var)]; + } + TypeDeclaration::Reserved(y) => { + let mut var = GenericDec::new(url); + let ident = get_ident(tree, RefNode::TypeIdentifier(&y.nodes.2)); + var.ident = ident.0; + var.byte_idx = ident.1; + let mut tokens = String::new(); + advance_until_enter!( + tokens, + tree, + event_iter, + RefNode::TypeIdentifier, + &TypeIdentifier + ); + var.type_str = tokens; + var.type_str = format!("{} {}", common, var.type_str); + var.completion_kind = CompletionItemKind::VARIABLE; + var.symbol_kind = SymbolKind::VARIABLE; + data = vec![Declaration::Dec(var)]; + } + }, + DataDeclaration::PackageImportDeclaration(x) => { + data = Vec::new(); + let imports = package_import(tree, x, event_iter, url)?; + for import in imports { + data.push(Declaration::Import(import)); + } + } + DataDeclaration::NetTypeDeclaration(x) => match &**x { + NetTypeDeclaration::DataType(y) => { + let mut common = String::new(); + let datatype = + advance_until_enter!(common, tree, event_iter, RefNode::DataType, &DataType)?; + let dec = data_type(tree, datatype, event_iter, url)?; + match dec { + Declaration::Dec(mut def) => { + let ident = get_ident(tree, RefNode::NetTypeIdentifier(&y.nodes.2)); + def.ident = ident.0; + def.byte_idx = ident.1; + let mut tokens = String::new(); + advance_until_enter!( + tokens, + tree, + event_iter, + RefNode::NetTypeIdentifier, + &NetTypeIdentifier + ); + def.type_str = tokens; + def.type_str = format!("{} {}", common, def.type_str); + data = vec![Declaration::Dec(def)]; + } + Declaration::Scope(mut def) => { + let ident = get_ident(tree, RefNode::NetTypeIdentifier(&y.nodes.2)); + def.ident = ident.0; + def.byte_idx = ident.1; + let mut tokens = String::new(); + advance_until_enter!( + tokens, + tree, + event_iter, + RefNode::NetTypeIdentifier, + &NetTypeIdentifier + ); + def.type_str = tokens; + def.type_str = format!("{} {}", common, def.type_str); + data = vec![Declaration::Scope(def)]; + } + Declaration::Import(_) => unreachable!(), + } + } + NetTypeDeclaration::NetType(y) => { + let mut var = GenericDec::new(url); + let ident = get_ident(tree, RefNode::NetTypeIdentifier(&y.nodes.2)); + var.ident = ident.0; + var.byte_idx = ident.1; + let mut tokens = String::new(); + advance_until_leave!(tokens, tree, event_iter, RefNode::NetTypeIdentifier); + var.type_str = tokens; + var.type_str = format!("{} {}", common, var.type_str); + var.completion_kind = CompletionItemKind::VARIABLE; + var.symbol_kind = SymbolKind::VARIABLE; + data = vec![Declaration::Dec(var)]; + } + }, + } + Some(data) +} + +pub fn tfport_list( + tree: &SyntaxTree, + node: &TfPortList, + event_iter: &mut EventIter, + url: &Url, +) -> Option> { + let mut tfports: Vec = Vec::new(); + for tfports_def in node.nodes.0.contents() { + match &tfports_def.nodes.4 { + Some(def) => { + let mut tfport = PortDec::new(url); + let ident = get_ident(tree, RefNode::PortIdentifier(&def.0)); + tfport.ident = ident.0; + tfport.byte_idx = ident.1; + for _ in &def.1 { + let tokens = &mut tfport.type_str; + advance_until_leave!(tokens, tree, event_iter, RefNode::UnpackedDimension); + } + tfports.push(tfport); + } + None => (), + } + } + Some(tfports) +} + +pub fn function_dec( + tree: &SyntaxTree, + node: &FunctionDeclaration, + event_iter: &mut EventIter, + url: &Url, +) -> Option { + let mut func: SubDec = SubDec::new(url); + func.start = get_loc(tree, RefNode::Keyword(&node.nodes.0)); + match &node.nodes.2 { + FunctionBodyDeclaration::WithoutPort(x) => { + func.end = get_loc(tree, RefNode::Keyword(&x.nodes.6)); + let ident = get_ident(tree, RefNode::FunctionIdentifier(&x.nodes.2)); + func.ident = ident.0; + func.byte_idx = ident.1; + let mut tokens = String::new(); + advance_until_enter!( + tokens, + tree, + event_iter, + RefNode::FunctionIdentifier, + &FunctionIdentifier + ); + func.type_str = tokens; + } + FunctionBodyDeclaration::WithPort(x) => { + func.end = get_loc(tree, RefNode::Keyword(&x.nodes.7)); + let ident = get_ident(tree, RefNode::FunctionIdentifier(&x.nodes.2)); + func.ident = ident.0; + func.byte_idx = ident.1; + let mut tokens = String::new(); + advance_until_enter!( + tokens, + tree, + event_iter, + RefNode::FunctionIdentifier, + &FunctionIdentifier + ); + func.type_str = tokens; + match &x.nodes.3.nodes.1 { + Some(tfports) => { + skip_until_enter!(tree, event_iter, RefNode::TfPortList, &TfPortList); + let ports = tfport_list(tree, tfports, event_iter, url)?; + for port in ports { + func.defs.push(Box::new(port)); + } + } + None => (), + } + } + } + let (scopes, mut defs) = + match_until_leave!(tree, event_iter, url, RefNode::FunctionDeclaration)?; + func.scopes = scopes; + func.defs.append(&mut defs); + Some(func) +} + +pub fn task_dec( + tree: &SyntaxTree, + node: &TaskDeclaration, + event_iter: &mut EventIter, + url: &Url, +) -> Option { + let mut task = SubDec::new(url); + task.start = get_loc(tree, RefNode::Keyword(&node.nodes.0)); + match &node.nodes.2 { + TaskBodyDeclaration::WithoutPort(x) => { + task.end = get_loc(tree, RefNode::Keyword(&x.nodes.5)); + let ident = get_ident(tree, RefNode::TaskIdentifier(&x.nodes.1)); + task.ident = ident.0; + task.byte_idx = ident.1; + let mut tokens = String::new(); + advance_until_enter!( + tokens, + tree, + event_iter, + RefNode::TaskIdentifier, + &TaskIdentifier + ); + task.type_str = tokens; + } + TaskBodyDeclaration::WithPort(x) => { + task.end = get_loc(tree, RefNode::Keyword(&x.nodes.6)); + let mut task = SubDec::new(url); + let ident = get_ident(tree, RefNode::TaskIdentifier(&x.nodes.1)); + task.ident = ident.0; + task.byte_idx = ident.1; + let mut tokens = String::new(); + advance_until_enter!( + tokens, + tree, + event_iter, + RefNode::TaskIdentifier, + &TaskIdentifier + ); + task.type_str = tokens; + match &x.nodes.2.nodes.1 { + Some(tfports) => { + skip_until_enter!(tree, event_iter, RefNode::TfPortList, &TfPortList); + let ports = tfport_list(tree, tfports, event_iter, url)?; + for port in ports { + task.defs.push(Box::new(port)); + } + } + None => (), + } + } + } + let (scopes, mut defs) = match_until_leave!(tree, event_iter, url, RefNode::TaskDeclaration)?; + task.scopes = scopes; + task.defs.append(&mut defs); + Some(task) +} + +pub fn modport_dec( + tree: &SyntaxTree, + node: &ModportDeclaration, + event_iter: &mut EventIter, + url: &Url, +) -> Option> { + let mut modports: Vec = Vec::new(); + let mut common = String::new(); + advance_until_enter!(common, tree, event_iter, RefNode::ModportItem, &ModportItem); + for modport_def in node.nodes.1.contents() { + let mut modport = ModportDec::new(url); + let ident = get_ident(tree, RefNode::ModportIdentifier(&modport_def.nodes.0)); + modport.ident = ident.0; + modport.byte_idx = ident.1; + modport.type_str = common.clone(); + + for mp_port_dec in modport_def.nodes.1.nodes.1.contents() { + match mp_port_dec { + ModportPortsDeclaration::Simple(x) => { + skip_until_enter!( + tree, + event_iter, + RefNode::ModportPortsDeclarationSimple, + &ModportPortsDeclarationSimple + ); + let mut prepend = String::new(); + advance_until_enter!( + prepend, + tree, + event_iter, + RefNode::ModportSimplePort, + &ModportSimplePort + ); + for mp_simple_def in x.nodes.1.nodes.1.contents() { + match mp_simple_def { + ModportSimplePort::Ordered(y) => { + let mut port = PortDec::new(url); + let ident = get_ident(tree, RefNode::PortIdentifier(&y.nodes.0)); + port.ident = ident.0; + port.byte_idx = ident.1; + port.type_str = prepend.clone(); + modport.ports.push(Box::new(port)); + } + ModportSimplePort::Named(_) => { + let port_ident = skip_until_enter!( + tree, + event_iter, + RefNode::PortIdentifier, + &PortIdentifier + )?; + let mut port = PortDec::new(url); + let ident = get_ident(tree, RefNode::PortIdentifier(port_ident)); + port.ident = ident.0; + port.byte_idx = ident.1; + let mut append = String::new(); + advance_until_leave!( + append, + tree, + event_iter, + RefNode::ModportSimplePortNamed + ); + port.type_str = format!("{} {}", prepend, append); + modport.ports.push(Box::new(port)); + } + } + } + } + ModportPortsDeclaration::Tf(_) => { + skip_until_enter!( + tree, + event_iter, + RefNode::ModportPortsDeclarationTf, + &ModportPortsDeclarationTf + ); + let mut prepend = String::new(); + let mp_tf_ports_dec = advance_until_enter!( + prepend, + tree, + event_iter, + RefNode::ModportTfPortsDeclaration, + &ModportTfPortsDeclaration + )?; + for mp_tf_port in mp_tf_ports_dec.nodes.1.contents() { + match mp_tf_port { + ModportTfPort::MethodPrototype(y) => match &**y { + MethodPrototype::TaskPrototype(z) => { + let mut port = SubDec::new(url); + let ident = + get_ident(tree, RefNode::TaskIdentifier(&z.nodes.1)); + port.ident = ident.0; + port.byte_idx = ident.1; + skip_until_enter!( + tree, + event_iter, + RefNode::TaskPrototype, + &TaskPrototype + ); + let tokens = &mut port.type_str; + advance_until_leave!( + tokens, + tree, + event_iter, + RefNode::TaskPrototype + ); + modport.ports.push(Box::new(port)); + } + MethodPrototype::FunctionPrototype(z) => { + let mut port = SubDec::new(url); + let ident = + get_ident(tree, RefNode::FunctionIdentifier(&z.nodes.2)); + port.ident = ident.0; + port.byte_idx = ident.1; + skip_until_enter!( + tree, + event_iter, + RefNode::FunctionPrototype, + &FunctionPrototype + ); + let tokens = &mut port.type_str; + advance_until_leave!( + tokens, + tree, + event_iter, + RefNode::FunctionIdentifier + ); + modport.ports.push(Box::new(port)); + } + }, + ModportTfPort::TfIdentifier(y) => { + let mut port = SubDec::new(url); + let ident = get_ident(tree, RefNode::TfIdentifier(y)); + port.ident = ident.0; + port.byte_idx = ident.1; + port.type_str = prepend.clone(); + modport.ports.push(Box::new(port)); + } + } + } + } + ModportPortsDeclaration::Clocking(_) => { + skip_until_enter!( + tree, + event_iter, + RefNode::ModportPortsDeclarationClocking, + &ModportPortsDeclarationClocking + ); + let mut tokens = String::new(); + let clock_ident = advance_until_enter!( + tokens, + tree, + event_iter, + RefNode::ClockingIdentifier, + &ClockingIdentifier + )?; + let ident = get_ident(tree, RefNode::ClockingIdentifier(clock_ident)); + let mut port = PortDec::new(url); + port.ident = ident.0; + port.byte_idx = ident.1; + port.type_str = tokens; + modport.ports.push(Box::new(port)); + } + } + } + + modports.push(modport); + } + Some(modports) +} + +pub fn module_inst( + tree: &SyntaxTree, + node: &ModuleInstantiation, + event_iter: &mut EventIter, + url: &Url, +) -> Option> { + let mut defs: Vec = Vec::new(); + let mod_ident = get_ident(tree, RefNode::ModuleIdentifier(&node.nodes.0)).0; + for _ in node.nodes.2.contents() { + let hinst = skip_until_enter!( + tree, + event_iter, + RefNode::HierarchicalInstance, + &HierarchicalInstance + )?; + let mut instance = ModInst::new(url); + let ident = get_ident(tree, RefNode::InstanceIdentifier(&hinst.nodes.0.nodes.0)); + instance.ident = ident.0; + instance.byte_idx = ident.1; + instance.type_str = mod_ident.clone(); + instance.mod_ident = mod_ident.clone(); + let type_str = &mut instance.type_str; + for _ in &hinst.nodes.0.nodes.1 { + advance_until_leave!(type_str, tree, event_iter, RefNode::UnpackedDimension); + } + defs.push(instance); + } + Some(defs) +} + +fn param_assignment( + tree: &SyntaxTree, + _: &ParamAssignment, + event_iter: &mut EventIter, + url: &Url, +) -> Option { + let param_assign = + skip_until_enter!(tree, event_iter, RefNode::ParamAssignment, &ParamAssignment)?; + let mut def = GenericDec::new(url); + let ident = get_ident(tree, RefNode::ParameterIdentifier(¶m_assign.nodes.0)); + def.ident = ident.0; + def.byte_idx = ident.1; + let type_str = &mut def.type_str; + def.completion_kind = CompletionItemKind::TYPE_PARAMETER; + def.symbol_kind = SymbolKind::TYPE_PARAMETER; + advance_until_leave!(type_str, tree, event_iter, RefNode::ParamAssignment); + Some(def) +} + +fn list_param_assignment( + tree: &SyntaxTree, + _: &ListOfParamAssignments, + event_iter: &mut EventIter, + url: &Url, +) -> Option> { + let mut defs: Vec = Vec::new(); + let p_a_list = skip_until_enter!( + tree, + event_iter, + RefNode::ListOfParamAssignments, + &ListOfParamAssignments + )?; + for param_assign in p_a_list.nodes.0.contents() { + defs.push(param_assignment(tree, param_assign, event_iter, url)?); + } + Some(defs) +} + +fn type_assignment( + tree: &SyntaxTree, + _: &TypeAssignment, + event_iter: &mut EventIter, + url: &Url, +) -> Option { + let type_assign = + skip_until_enter!(tree, event_iter, RefNode::TypeAssignment, &TypeAssignment)?; + let mut def = GenericDec::new(url); + let ident = get_ident(tree, RefNode::TypeIdentifier(&type_assign.nodes.0)); + def.ident = ident.0; + def.byte_idx = ident.1; + def.completion_kind = CompletionItemKind::TYPE_PARAMETER; + def.symbol_kind = SymbolKind::TYPE_PARAMETER; + let type_str = &mut def.type_str; + advance_until_leave!(type_str, tree, event_iter, RefNode::TypeAssignment); + Some(def) +} + +fn list_type_assignment( + tree: &SyntaxTree, + _: &ListOfTypeAssignments, + event_iter: &mut EventIter, + url: &Url, +) -> Option> { + let mut defs: Vec = Vec::new(); + let p_a_list = skip_until_enter!( + tree, + event_iter, + RefNode::ListOfTypeAssignments, + &ListOfTypeAssignments + )?; + for type_assign in p_a_list.nodes.0.contents() { + defs.push(type_assignment(tree, type_assign, event_iter, url)?); + } + Some(defs) +} + +pub fn param_dec( + tree: &SyntaxTree, + param_dec: &ParameterDeclaration, + event_iter: &mut EventIter, + url: &Url, +) -> Option> { + match param_dec { + ParameterDeclaration::Param(x) => { + let mut prepend = String::new(); + advance_until_leave!(prepend, tree, event_iter, RefNode::DataTypeOrImplicit); + let mut defs = list_param_assignment(tree, &x.nodes.2, event_iter, url)?; + for def in &mut defs { + def.type_str = format!("{} {}", prepend, def.type_str); + def.completion_kind = CompletionItemKind::TYPE_PARAMETER; + def.symbol_kind = SymbolKind::TYPE_PARAMETER; + } + Some(defs) + } + ParameterDeclaration::Type(x) => { + let mut prepend = String::new(); + advance_until_leave!(prepend, tree, event_iter, RefNode::Keyword); + advance_until_leave!(prepend, tree, event_iter, RefNode::Keyword); + let mut defs = list_type_assignment(tree, &x.nodes.2, event_iter, url)?; + for def in &mut defs { + def.type_str = format!("{} {}", prepend, def.type_str); + def.completion_kind = CompletionItemKind::TYPE_PARAMETER; + def.symbol_kind = SymbolKind::TYPE_PARAMETER; + } + Some(defs) + } + } +} + +pub fn localparam_dec( + tree: &SyntaxTree, + localparam_dec: &LocalParameterDeclaration, + event_iter: &mut EventIter, + url: &Url, +) -> Option> { + match localparam_dec { + LocalParameterDeclaration::Param(x) => { + let mut prepend = String::new(); + advance_until_leave!(prepend, tree, event_iter, RefNode::DataTypeOrImplicit); + let mut defs = list_param_assignment(tree, &x.nodes.2, event_iter, url)?; + for def in &mut defs { + def.type_str = format!("{} {}", prepend, def.type_str); + def.completion_kind = CompletionItemKind::TYPE_PARAMETER; + def.symbol_kind = SymbolKind::TYPE_PARAMETER; + } + Some(defs) + } + LocalParameterDeclaration::Type(x) => { + let mut prepend = String::new(); + advance_until_leave!(prepend, tree, event_iter, RefNode::Keyword); + advance_until_leave!(prepend, tree, event_iter, RefNode::Keyword); + let mut defs = list_type_assignment(tree, &x.nodes.2, event_iter, url)?; + for def in &mut defs { + def.type_str = format!("{} {}", prepend, def.type_str); + def.completion_kind = CompletionItemKind::TYPE_PARAMETER; + def.symbol_kind = SymbolKind::TYPE_PARAMETER; + } + Some(defs) + } + } +} + +fn param_port_dec( + tree: &SyntaxTree, + node: &ParameterPortDeclaration, + event_iter: &mut EventIter, + url: &Url, +) -> Option> { + match node { + ParameterPortDeclaration::ParameterDeclaration(_) => { + let param = skip_until_enter!( + tree, + event_iter, + RefNode::ParameterDeclaration, + &ParameterDeclaration + )?; + param_dec(tree, param, event_iter, url) + } + ParameterPortDeclaration::LocalParameterDeclaration(_) => { + let localparam = skip_until_enter!( + tree, + event_iter, + RefNode::LocalParameterDeclaration, + &LocalParameterDeclaration + )?; + localparam_dec(tree, localparam, event_iter, url) + } + ParameterPortDeclaration::ParamList(x) => { + let mut prepend = String::new(); + advance_until_leave!(prepend, tree, event_iter, RefNode::DataType); + let mut defs = list_param_assignment(tree, &x.nodes.1, event_iter, url)?; + for def in &mut defs { + def.type_str = format!("{} {}", prepend, def.type_str); + def.completion_kind = CompletionItemKind::TYPE_PARAMETER; + def.symbol_kind = SymbolKind::TYPE_PARAMETER; + } + Some(defs) + } + ParameterPortDeclaration::TypeList(x) => { + let mut prepend = String::new(); + advance_until_leave!(prepend, tree, event_iter, RefNode::Keyword); + let mut defs = list_type_assignment(tree, &x.nodes.1, event_iter, url)?; + for def in &mut defs { + def.type_str = format!("{} {}", prepend, def.type_str); + def.completion_kind = CompletionItemKind::TYPE_PARAMETER; + def.symbol_kind = SymbolKind::TYPE_PARAMETER; + } + Some(defs) + } + } +} + +pub fn param_port_list( + tree: &SyntaxTree, + node: &ParameterPortList, + event_iter: &mut EventIter, + url: &Url, +) -> Option> { + let mut defs: Vec = Vec::new(); + match node { + ParameterPortList::Assignment(x) => { + defs.append(&mut list_param_assignment( + tree, + &(x.nodes.1.nodes.1).0, + event_iter, + url, + )?); + for port_dec in &(x.nodes.1.nodes.1).1 { + defs.append(&mut param_port_dec(tree, &port_dec.1, event_iter, url)?); + } + } + ParameterPortList::Declaration(x) => { + let mut param_port_decs = vec![&x.nodes.1.nodes.1.nodes.0]; + for param_port_dec in &x.nodes.1.nodes.1.nodes.1 { + param_port_decs.push(¶m_port_dec.1); + } + for port_dec in param_port_decs { + defs.append(&mut param_port_dec(tree, port_dec, event_iter, url)?); + } + } + ParameterPortList::Empty(_) => {} + } + Some(defs) +} + +pub fn module_dec( + tree: &SyntaxTree, + node: &ModuleDeclaration, + event_iter: &mut EventIter, + url: &Url, +) -> Option { + let mut scope: GenericScope = GenericScope::new(url); + match node { + ModuleDeclaration::Nonansi(x) => { + scope.start = get_loc(tree, RefNode::ModuleKeyword(&x.nodes.0.nodes.1)); + scope.end = get_loc(tree, RefNode::Keyword(&x.nodes.3)); + let ident = get_ident(tree, RefNode::ModuleIdentifier(&x.nodes.0.nodes.3)); + scope.ident = ident.0; + scope.byte_idx = ident.1; + let type_str = &mut scope.type_str; + advance_until_leave!(type_str, tree, event_iter, RefNode::ModuleIdentifier); + for import_dec in &x.nodes.0.nodes.4 { + let imports = package_import(tree, import_dec, event_iter, url)?; + for import in imports { + scope.defs.push(Box::new(import)); + } + } + if let Some(pport_list) = &x.nodes.0.nodes.5 { + let pports = param_port_list(tree, pport_list, event_iter, url)?; + for pport in pports { + scope.defs.push(Box::new(pport)); + } + } + } + ModuleDeclaration::Ansi(x) => { + scope.start = get_loc(tree, RefNode::ModuleKeyword(&x.nodes.0.nodes.1)); + scope.end = get_loc(tree, RefNode::Keyword(&x.nodes.3)); + let ident = get_ident(tree, RefNode::ModuleIdentifier(&x.nodes.0.nodes.3)); + scope.ident = ident.0; + scope.byte_idx = ident.1; + let type_str = &mut scope.type_str; + advance_until_leave!(type_str, tree, event_iter, RefNode::ModuleIdentifier); + for import_dec in &x.nodes.0.nodes.4 { + let imports = package_import(tree, import_dec, event_iter, url)?; + for import in imports { + scope.defs.push(Box::new(import)); + } + } + if let Some(pport_list) = &x.nodes.0.nodes.5 { + let pports = param_port_list(tree, pport_list, event_iter, url)?; + for pport in pports { + scope.defs.push(Box::new(pport)); + } + } + if let Some(list_port_decs) = &x.nodes.0.nodes.6 { + if let Some(port_decs) = &list_port_decs.nodes.0.nodes.1 { + let mut prev_type_str = String::new(); + for _ in port_decs.contents() { + let ansi_dec = skip_until_enter!( + tree, + event_iter, + RefNode::AnsiPortDeclaration, + &AnsiPortDeclaration + )?; + // propogate type str for multi-port declaration + let mut port_dec = port_dec_ansi(tree, ansi_dec, event_iter, url)?; + if port_dec.type_str.is_empty() && !prev_type_str.is_empty() { + port_dec.type_str = prev_type_str.clone(); + } else { + prev_type_str = port_dec.type_str.clone(); + } + scope.defs.push(Box::new(port_dec)) + } + } + } + } + ModuleDeclaration::Wildcard(x) => { + scope.start = get_loc(tree, RefNode::ModuleKeyword(&x.nodes.1)); + scope.end = get_loc(tree, RefNode::Keyword(&x.nodes.8)); + let ident = get_ident(tree, RefNode::ModuleIdentifier(&x.nodes.3)); + scope.ident = ident.0; + scope.byte_idx = ident.1; + let type_str = &mut scope.type_str; + advance_until_leave!(type_str, tree, event_iter, RefNode::ModuleIdentifier); + } + ModuleDeclaration::ExternNonansi(x) => { + scope.start = get_loc(tree, RefNode::Keyword(&x.nodes.0)); + scope.end = get_loc(tree, RefNode::Symbol(&x.nodes.1.nodes.7)); + let ident = get_ident(tree, RefNode::ModuleIdentifier(&x.nodes.1.nodes.3)); + scope.ident = ident.0; + scope.byte_idx = ident.1; + let type_str = &mut scope.type_str; + advance_until_leave!(type_str, tree, event_iter, RefNode::ModuleIdentifier); + for import_dec in &x.nodes.1.nodes.4 { + let imports = package_import(tree, import_dec, event_iter, url)?; + for import in imports { + scope.defs.push(Box::new(import)); + } + } + if let Some(pport_list) = &x.nodes.1.nodes.5 { + let pports = param_port_list(tree, pport_list, event_iter, url)?; + for pport in pports { + scope.defs.push(Box::new(pport)); + } + } + } + ModuleDeclaration::ExternAnsi(x) => { + scope.start = get_loc(tree, RefNode::Keyword(&x.nodes.0)); + scope.end = get_loc(tree, RefNode::Symbol(&x.nodes.1.nodes.7)); + let ident = get_ident(tree, RefNode::ModuleIdentifier(&x.nodes.1.nodes.3)); + scope.ident = ident.0; + scope.byte_idx = ident.1; + let type_str = &mut scope.type_str; + advance_until_leave!(type_str, tree, event_iter, RefNode::ModuleIdentifier); + for import_dec in &x.nodes.1.nodes.4 { + let imports = package_import(tree, import_dec, event_iter, url)?; + for import in imports { + scope.defs.push(Box::new(import)); + } + } + if let Some(pport_list) = &x.nodes.1.nodes.5 { + let pports = param_port_list(tree, pport_list, event_iter, url)?; + for pport in pports { + scope.defs.push(Box::new(pport)); + } + } + if let Some(list_port_decs) = &x.nodes.1.nodes.6 { + if let Some(port_decs) = &list_port_decs.nodes.0.nodes.1 { + for _ in port_decs.contents() { + let ansi_dec = skip_until_enter!( + tree, + event_iter, + RefNode::AnsiPortDeclaration, + &AnsiPortDeclaration + )?; + scope + .defs + .push(Box::new(port_dec_ansi(tree, ansi_dec, event_iter, url)?)) + } + } + } + } + } + let (scopes, mut defs) = match_until_leave!(tree, event_iter, url, RefNode::ModuleDeclaration)?; + scope.scopes = scopes; + scope.defs.append(&mut defs); + scope.completion_kind = CompletionItemKind::MODULE; + scope.symbol_kind = SymbolKind::MODULE; + Some(scope) +} + +pub fn interface_dec( + tree: &SyntaxTree, + node: &InterfaceDeclaration, + event_iter: &mut EventIter, + url: &Url, +) -> Option { + let mut scope: GenericScope = GenericScope::new(url); + match node { + InterfaceDeclaration::Nonansi(x) => { + scope.start = get_loc(tree, RefNode::Keyword(&x.nodes.0.nodes.1)); + scope.end = get_loc(tree, RefNode::Keyword(&x.nodes.3)); + let ident = get_ident(tree, RefNode::InterfaceIdentifier(&x.nodes.0.nodes.3)); + scope.ident = ident.0; + scope.byte_idx = ident.1; + let type_str = &mut scope.type_str; + advance_until_leave!(type_str, tree, event_iter, RefNode::InterfaceIdentifier); + for import_dec in &x.nodes.0.nodes.4 { + let imports = package_import(tree, import_dec, event_iter, url)?; + for import in imports { + scope.defs.push(Box::new(import)); + } + } + if let Some(pport_list) = &x.nodes.0.nodes.5 { + let pports = param_port_list(tree, pport_list, event_iter, url)?; + for pport in pports { + scope.defs.push(Box::new(pport)); + } + } + } + InterfaceDeclaration::Ansi(x) => { + scope.start = get_loc(tree, RefNode::Keyword(&x.nodes.0.nodes.1)); + scope.end = get_loc(tree, RefNode::Keyword(&x.nodes.3)); + let ident = get_ident(tree, RefNode::InterfaceIdentifier(&x.nodes.0.nodes.3)); + scope.ident = ident.0; + scope.byte_idx = ident.1; + let type_str = &mut scope.type_str; + advance_until_leave!(type_str, tree, event_iter, RefNode::InterfaceIdentifier); + for import_dec in &x.nodes.0.nodes.4 { + let imports = package_import(tree, import_dec, event_iter, url)?; + for import in imports { + scope.defs.push(Box::new(import)); + } + } + if let Some(pport_list) = &x.nodes.0.nodes.5 { + let pports = param_port_list(tree, pport_list, event_iter, url)?; + for pport in pports { + scope.defs.push(Box::new(pport)); + } + } + if let Some(list_port_decs) = &x.nodes.0.nodes.6 { + if let Some(port_decs) = &list_port_decs.nodes.0.nodes.1 { + for _ in port_decs.contents() { + let ansi_dec = skip_until_enter!( + tree, + event_iter, + RefNode::AnsiPortDeclaration, + &AnsiPortDeclaration + )?; + scope + .defs + .push(Box::new(port_dec_ansi(tree, ansi_dec, event_iter, url)?)) + } + } + } + } + InterfaceDeclaration::Wildcard(x) => { + scope.start = get_loc(tree, RefNode::Keyword(&x.nodes.1)); + scope.end = get_loc(tree, RefNode::Keyword(&x.nodes.8)); + let ident = get_ident(tree, RefNode::InterfaceIdentifier(&x.nodes.3)); + scope.ident = ident.0; + scope.byte_idx = ident.1; + let type_str = &mut scope.type_str; + advance_until_leave!(type_str, tree, event_iter, RefNode::InterfaceIdentifier); + } + InterfaceDeclaration::ExternNonansi(x) => { + scope.start = get_loc(tree, RefNode::Keyword(&x.nodes.0)); + scope.end = get_loc(tree, RefNode::Symbol(&x.nodes.1.nodes.7)); + let ident = get_ident(tree, RefNode::InterfaceIdentifier(&x.nodes.1.nodes.3)); + scope.ident = ident.0; + scope.byte_idx = ident.1; + let type_str = &mut scope.type_str; + advance_until_leave!(type_str, tree, event_iter, RefNode::InterfaceIdentifier); + for import_dec in &x.nodes.1.nodes.4 { + let imports = package_import(tree, import_dec, event_iter, url)?; + for import in imports { + scope.defs.push(Box::new(import)); + } + } + if let Some(pport_list) = &x.nodes.1.nodes.5 { + let pports = param_port_list(tree, pport_list, event_iter, url)?; + for pport in pports { + scope.defs.push(Box::new(pport)); + } + } + } + InterfaceDeclaration::ExternAnsi(x) => { + scope.start = get_loc(tree, RefNode::Keyword(&x.nodes.0)); + scope.end = get_loc(tree, RefNode::Symbol(&x.nodes.1.nodes.7)); + let ident = get_ident(tree, RefNode::InterfaceIdentifier(&x.nodes.1.nodes.3)); + scope.ident = ident.0; + scope.byte_idx = ident.1; + let type_str = &mut scope.type_str; + advance_until_leave!(type_str, tree, event_iter, RefNode::InterfaceIdentifier); + for import_dec in &x.nodes.1.nodes.4 { + let imports = package_import(tree, import_dec, event_iter, url)?; + for import in imports { + scope.defs.push(Box::new(import)); + } + } + if let Some(pport_list) = &x.nodes.1.nodes.5 { + let pports = param_port_list(tree, pport_list, event_iter, url)?; + for pport in pports { + scope.defs.push(Box::new(pport)); + } + } + if let Some(list_port_decs) = &x.nodes.1.nodes.6 { + if let Some(port_decs) = &list_port_decs.nodes.0.nodes.1 { + for _ in port_decs.contents() { + let ansi_dec = skip_until_enter!( + tree, + event_iter, + RefNode::AnsiPortDeclaration, + &AnsiPortDeclaration + )?; + scope + .defs + .push(Box::new(port_dec_ansi(tree, ansi_dec, event_iter, url)?)) + } + } + } + } + } + let (scopes, mut defs) = + match_until_leave!(tree, event_iter, url, RefNode::InterfaceDeclaration)?; + scope.scopes = scopes; + scope.defs.append(&mut defs); + scope.completion_kind = CompletionItemKind::INTERFACE; + scope.symbol_kind = SymbolKind::INTERFACE; + Some(scope) +} + +fn list_udp_port_idents( + tree: &SyntaxTree, + node: &ListOfUdpPortIdentifiers, + _: &mut EventIter, + url: &Url, +) -> Vec { + let mut ports: Vec = Vec::new(); + for port_def in node.nodes.0.contents() { + let mut port = PortDec::new(url); + let ident = get_ident(tree, RefNode::PortIdentifier(port_def)); + port.ident = ident.0; + port.byte_idx = ident.1; + ports.push(port); + } + ports +} + +//non-ansi udp ports +fn udp_port_dec( + tree: &SyntaxTree, + node: &UdpPortDeclaration, + event_iter: &mut EventIter, + url: &Url, +) -> Option> { + match node { + UdpPortDeclaration::UdpOutputDeclaration(x) => match &x.0 { + UdpOutputDeclaration::Nonreg(x) => { + let mut port = PortDec::new(url); + let ident = get_ident(tree, RefNode::PortIdentifier(&x.nodes.2)); + port.ident = ident.0; + port.byte_idx = ident.1; + skip_until_enter!( + tree, + event_iter, + RefNode::UdpOutputDeclarationNonreg, + &UdpOutputDeclarationNonreg + ); + let type_str = &mut port.type_str; + advance_until_leave!( + type_str, + tree, + event_iter, + RefNode::UdpOutputDeclarationNonreg + ); + Some(vec![port]) + } + UdpOutputDeclaration::Reg(x) => { + let mut port = PortDec::new(url); + let ident = get_ident(tree, RefNode::PortIdentifier(&x.nodes.3)); + port.ident = ident.0; + port.byte_idx = ident.1; + skip_until_enter!( + tree, + event_iter, + RefNode::UdpOutputDeclarationReg, + &UdpOutputDeclarationReg + ); + let type_str = &mut port.type_str; + advance_until_leave!(type_str, tree, event_iter, RefNode::UdpOutputDeclarationReg); + Some(vec![port]) + } + }, + UdpPortDeclaration::UdpInputDeclaration(_) => { + skip_until_enter!( + tree, + event_iter, + RefNode::UdpInputDeclaration, + &UdpInputDeclaration + ); + let mut type_str = String::new(); + let list_udp_ports = advance_until_enter!( + type_str, + tree, + event_iter, + RefNode::ListOfUdpPortIdentifiers, + &ListOfUdpPortIdentifiers + )?; + let mut ports = list_udp_port_idents(tree, list_udp_ports, event_iter, url); + for port in &mut ports { + port.type_str = type_str.clone(); + } + Some(ports) + } + UdpPortDeclaration::UdpRegDeclaration(_) => { + let udp_reg_dec = skip_until_enter!( + tree, + event_iter, + RefNode::UdpRegDeclaration, + &UdpRegDeclaration + )?; + let mut port = PortDec::new(url); + let type_str = &mut port.type_str; + advance_until_leave!(type_str, tree, event_iter, RefNode::Keyword); + let ident = get_ident(tree, RefNode::VariableIdentifier(&udp_reg_dec.nodes.2)); + port.ident = ident.0; + port.byte_idx = ident.1; + Some(vec![port]) + } + } +} + +//ansi udp ports +fn udp_port_list( + tree: &SyntaxTree, + node: &UdpDeclarationPortList, + event_iter: &mut EventIter, + url: &Url, +) -> Option> { + let mut ports: Vec = Vec::new(); + match &node.nodes.0 { + UdpOutputDeclaration::Nonreg(x) => { + let mut port = PortDec::new(url); + let ident = get_ident(tree, RefNode::PortIdentifier(&x.nodes.2)); + port.ident = ident.0; + port.byte_idx = ident.1; + skip_until_enter!( + tree, + event_iter, + RefNode::UdpOutputDeclarationNonreg, + &UdpOutputDeclarationNonreg + ); + let type_str = &mut port.type_str; + advance_until_leave!( + type_str, + tree, + event_iter, + RefNode::UdpOutputDeclarationNonreg + ); + ports.push(port); + } + UdpOutputDeclaration::Reg(x) => { + let mut port = PortDec::new(url); + let ident = get_ident(tree, RefNode::PortIdentifier(&x.nodes.3)); + port.ident = ident.0; + port.byte_idx = ident.1; + skip_until_enter!( + tree, + event_iter, + RefNode::UdpOutputDeclarationReg, + &UdpOutputDeclarationReg + ); + let type_str = &mut port.type_str; + advance_until_leave!(type_str, tree, event_iter, RefNode::UdpOutputDeclarationReg); + ports.push(port); + } + } + for _port_def in node.nodes.2.contents() { + skip_until_enter!( + tree, + event_iter, + RefNode::UdpInputDeclaration, + &UdpInputDeclaration + ); + let mut type_str = String::new(); + let list_udp_ports = advance_until_enter!( + type_str, + tree, + event_iter, + RefNode::ListOfUdpPortIdentifiers, + &ListOfUdpPortIdentifiers + )?; + let mut port_decs = list_udp_port_idents(tree, list_udp_ports, event_iter, url); + for port in &mut port_decs { + port.type_str = type_str.clone(); + } + ports.append(&mut port_decs); + } + Some(ports) +} + +pub fn udp_dec( + tree: &SyntaxTree, + node: &UdpDeclaration, + event_iter: &mut EventIter, + url: &Url, +) -> Option { + let mut scope: GenericScope = GenericScope::new(url); + match node { + UdpDeclaration::Nonansi(x) => { + scope.start = get_loc(tree, RefNode::Keyword(&x.nodes.0.nodes.1)); + scope.end = get_loc(tree, RefNode::Keyword(&x.nodes.4)); + let ident = get_ident(tree, RefNode::UdpIdentifier(&x.nodes.0.nodes.2)); + scope.ident = ident.0; + scope.byte_idx = ident.1; + let type_str = &mut scope.type_str; + advance_until_leave!(type_str, tree, event_iter, RefNode::UdpIdentifier); + let mut port_decs = vec![&x.nodes.1]; + for port_dec in &x.nodes.2 { + port_decs.push(port_dec); + } + for port in port_decs { + let ports = udp_port_dec(tree, port, event_iter, url)?; + for port_dec in ports { + scope.defs.push(Box::new(port_dec)); + } + } + } + UdpDeclaration::Ansi(x) => { + scope.start = get_loc(tree, RefNode::Keyword(&x.nodes.0.nodes.1)); + scope.end = get_loc(tree, RefNode::Keyword(&x.nodes.2)); + let ident = get_ident(tree, RefNode::UdpIdentifier(&x.nodes.0.nodes.2)); + scope.ident = ident.0; + scope.byte_idx = ident.1; + let type_str = &mut scope.type_str; + advance_until_leave!(type_str, tree, event_iter, RefNode::UdpIdentifier); + let ports = udp_port_list(tree, &x.nodes.0.nodes.3.nodes.1, event_iter, url)?; + for port_dec in ports { + scope.defs.push(Box::new(port_dec)); + } + } + UdpDeclaration::ExternNonansi(x) => { + scope.start = get_loc(tree, RefNode::Keyword(&x.nodes.0)); + scope.end = get_loc(tree, RefNode::Symbol(&x.nodes.1.nodes.4)); + let ident = get_ident(tree, RefNode::UdpIdentifier(&x.nodes.1.nodes.2)); + scope.ident = ident.0; + scope.byte_idx = ident.1; + let type_str = &mut scope.type_str; + advance_until_leave!(type_str, tree, event_iter, RefNode::UdpIdentifier); + } + UdpDeclaration::ExternAnsi(x) => { + scope.start = get_loc(tree, RefNode::Keyword(&x.nodes.0)); + scope.end = get_loc(tree, RefNode::Symbol(&x.nodes.1.nodes.4)); + let ident = get_ident(tree, RefNode::UdpIdentifier(&x.nodes.1.nodes.2)); + scope.ident = ident.0; + scope.byte_idx = ident.1; + let type_str = &mut scope.type_str; + advance_until_leave!(type_str, tree, event_iter, RefNode::UdpIdentifier); + let ports = udp_port_list(tree, &x.nodes.1.nodes.3.nodes.1, event_iter, url)?; + for port_dec in ports { + scope.defs.push(Box::new(port_dec)); + } + } + UdpDeclaration::Wildcard(x) => { + scope.start = get_loc(tree, RefNode::Keyword(&x.nodes.1)); + scope.end = get_loc(tree, RefNode::Keyword(&x.nodes.7)); + let ident = get_ident(tree, RefNode::UdpIdentifier(&x.nodes.2)); + scope.ident = ident.0; + scope.byte_idx = ident.1; + let type_str = &mut scope.type_str; + advance_until_leave!(type_str, tree, event_iter, RefNode::UdpIdentifier); + for port_dec in &x.nodes.5 { + let ports = udp_port_dec(tree, port_dec, event_iter, url)?; + for port in ports { + scope.defs.push(Box::new(port)); + } + } + } + } + + let (scopes, mut defs) = match_until_leave!(tree, event_iter, url, RefNode::UdpDeclaration)?; + scope.scopes = scopes; + scope.defs.append(&mut defs); + scope.completion_kind = CompletionItemKind::MODULE; + scope.symbol_kind = SymbolKind::MODULE; + Some(scope) +} + +pub fn program_dec( + tree: &SyntaxTree, + node: &ProgramDeclaration, + event_iter: &mut EventIter, + url: &Url, +) -> Option { + let mut scope: GenericScope = GenericScope::new(url); + match node { + ProgramDeclaration::Nonansi(x) => { + scope.start = get_loc(tree, RefNode::Keyword(&x.nodes.0.nodes.1)); + scope.end = get_loc(tree, RefNode::Keyword(&x.nodes.3)); + let ident = get_ident(tree, RefNode::ProgramIdentifier(&x.nodes.0.nodes.3)); + scope.ident = ident.0; + scope.byte_idx = ident.1; + let type_str = &mut scope.type_str; + advance_until_leave!(type_str, tree, event_iter, RefNode::InterfaceIdentifier); + for import_dec in &x.nodes.0.nodes.4 { + let imports = package_import(tree, import_dec, event_iter, url)?; + for import in imports { + scope.defs.push(Box::new(import)); + } + } + if let Some(pport_list) = &x.nodes.0.nodes.5 { + let pports = param_port_list(tree, pport_list, event_iter, url)?; + for pport in pports { + scope.defs.push(Box::new(pport)); + } + } + } + + ProgramDeclaration::Ansi(x) => { + scope.start = get_loc(tree, RefNode::Keyword(&x.nodes.0.nodes.1)); + scope.end = get_loc(tree, RefNode::Keyword(&x.nodes.3)); + let ident = get_ident(tree, RefNode::ProgramIdentifier(&x.nodes.0.nodes.3)); + scope.ident = ident.0; + scope.byte_idx = ident.1; + let type_str = &mut scope.type_str; + advance_until_leave!(type_str, tree, event_iter, RefNode::ProgramIdentifier); + for import_dec in &x.nodes.0.nodes.4 { + let imports = package_import(tree, import_dec, event_iter, url)?; + for import in imports { + scope.defs.push(Box::new(import)); + } + } + if let Some(pport_list) = &x.nodes.0.nodes.5 { + let pports = param_port_list(tree, pport_list, event_iter, url)?; + for pport in pports { + scope.defs.push(Box::new(pport)); + } + } + if let Some(list_port_decs) = &x.nodes.0.nodes.6 { + if let Some(port_decs) = &list_port_decs.nodes.0.nodes.1 { + for _ in port_decs.contents() { + let ansi_dec = skip_until_enter!( + tree, + event_iter, + RefNode::AnsiPortDeclaration, + &AnsiPortDeclaration + )?; + scope + .defs + .push(Box::new(port_dec_ansi(tree, ansi_dec, event_iter, url)?)) + } + } + } + } + ProgramDeclaration::Wildcard(x) => { + scope.start = get_loc(tree, RefNode::Keyword(&x.nodes.1)); + scope.end = get_loc(tree, RefNode::Keyword(&x.nodes.7)); + let ident = get_ident(tree, RefNode::ProgramIdentifier(&x.nodes.2)); + scope.ident = ident.0; + scope.byte_idx = ident.1; + let type_str = &mut scope.type_str; + advance_until_leave!(type_str, tree, event_iter, RefNode::ProgramIdentifier); + } + ProgramDeclaration::ExternNonansi(x) => { + scope.start = get_loc(tree, RefNode::Keyword(&x.nodes.0)); + scope.end = get_loc(tree, RefNode::Symbol(&x.nodes.1.nodes.7)); + let ident = get_ident(tree, RefNode::ProgramIdentifier(&x.nodes.1.nodes.3)); + scope.ident = ident.0; + scope.byte_idx = ident.1; + let type_str = &mut scope.type_str; + advance_until_leave!(type_str, tree, event_iter, RefNode::ProgramIdentifier); + for import_dec in &x.nodes.1.nodes.4 { + let imports = package_import(tree, import_dec, event_iter, url)?; + for import in imports { + scope.defs.push(Box::new(import)); + } + } + if let Some(pport_list) = &x.nodes.1.nodes.5 { + let pports = param_port_list(tree, pport_list, event_iter, url)?; + for pport in pports { + scope.defs.push(Box::new(pport)); + } + } + } + ProgramDeclaration::ExternAnsi(x) => { + scope.start = get_loc(tree, RefNode::Keyword(&x.nodes.0)); + scope.end = get_loc(tree, RefNode::Symbol(&x.nodes.1.nodes.7)); + let ident = get_ident(tree, RefNode::ProgramIdentifier(&x.nodes.1.nodes.3)); + scope.ident = ident.0; + scope.byte_idx = ident.1; + let type_str = &mut scope.type_str; + advance_until_leave!(type_str, tree, event_iter, RefNode::ProgramIdentifier); + for import_dec in &x.nodes.1.nodes.4 { + let imports = package_import(tree, import_dec, event_iter, url)?; + for import in imports { + scope.defs.push(Box::new(import)); + } + } + if let Some(pport_list) = &x.nodes.1.nodes.5 { + let pports = param_port_list(tree, pport_list, event_iter, url)?; + for pport in pports { + scope.defs.push(Box::new(pport)); + } + } + if let Some(list_port_decs) = &x.nodes.1.nodes.6 { + if let Some(port_decs) = &list_port_decs.nodes.0.nodes.1 { + for _ in port_decs.contents() { + let ansi_dec = skip_until_enter!( + tree, + event_iter, + RefNode::AnsiPortDeclaration, + &AnsiPortDeclaration + )?; + scope + .defs + .push(Box::new(port_dec_ansi(tree, ansi_dec, event_iter, url)?)) + } + } + } + } + } + + let (scopes, mut defs) = + match_until_leave!(tree, event_iter, url, RefNode::ProgramDeclaration)?; + scope.scopes = scopes; + scope.defs.append(&mut defs); + scope.completion_kind = CompletionItemKind::MODULE; + scope.symbol_kind = SymbolKind::MODULE; + Some(scope) +} + +pub fn package_dec( + tree: &SyntaxTree, + node: &PackageDeclaration, + event_iter: &mut EventIter, + url: &Url, +) -> Option { + let mut scope: GenericScope = GenericScope::new(url); + scope.start = get_loc(tree, RefNode::Keyword(&node.nodes.1)); + scope.end = get_loc(tree, RefNode::Keyword(&node.nodes.7)); + let ident = get_ident(tree, RefNode::PackageIdentifier(&node.nodes.3)); + scope.ident = ident.0; + scope.byte_idx = ident.1; + let type_str = &mut scope.type_str; + advance_until_leave!(type_str, tree, event_iter, RefNode::PackageIdentifier); + + let (scopes, mut defs) = + match_until_leave!(tree, event_iter, url, RefNode::PackageDeclaration)?; + scope.scopes = scopes; + scope.defs.append(&mut defs); + scope.completion_kind = CompletionItemKind::MODULE; + scope.symbol_kind = SymbolKind::PACKAGE; + Some(scope) +} + +pub fn config_dec( + tree: &SyntaxTree, + node: &ConfigDeclaration, + event_iter: &mut EventIter, + url: &Url, +) -> Option { + let mut scope: GenericScope = GenericScope::new(url); + scope.start = get_loc(tree, RefNode::Keyword(&node.nodes.0)); + scope.end = get_loc(tree, RefNode::Keyword(&node.nodes.6)); + let ident = get_ident(tree, RefNode::ConfigIdentifier(&node.nodes.1)); + scope.ident = ident.0; + scope.byte_idx = ident.1; + let type_str = &mut scope.type_str; + advance_until_leave!(type_str, tree, event_iter, RefNode::ConfigIdentifier); + for localparam in &node.nodes.3 { + let params = localparam_dec(tree, &localparam.0, event_iter, url)?; + for param in params { + scope.defs.push(Box::new(param)); + } + } + + let (scopes, mut defs) = match_until_leave!(tree, event_iter, url, RefNode::ConfigDeclaration)?; + scope.scopes = scopes; + scope.defs.append(&mut defs); + scope.completion_kind = CompletionItemKind::MODULE; + scope.symbol_kind = SymbolKind::MODULE; + Some(scope) +} + +pub fn class_dec( + tree: &SyntaxTree, + node: &ClassDeclaration, + event_iter: &mut EventIter, + url: &Url, +) -> Option { + let mut scope: ClassDec = ClassDec::new(url); + scope.start = get_loc(tree, RefNode::Keyword(&node.nodes.1)); + scope.end = get_loc(tree, RefNode::Keyword(&node.nodes.9)); + let ident = get_ident(tree, RefNode::ClassIdentifier(&node.nodes.3)); + scope.ident = ident.0; + scope.byte_idx = ident.1; + let type_str = &mut scope.type_str; + advance_until_leave!(type_str, tree, event_iter, RefNode::ClassIdentifier); + if let Some(pport_list) = &node.nodes.4 { + let pports = param_port_list(tree, pport_list, event_iter, url)?; + for pport in pports { + scope.defs.push(Box::new(pport)); + } + } + if let Some(extend) = &node.nodes.5 { + if let Some(package_scope) = &extend.1.nodes.0.nodes.0 { + match package_scope { + PackageScope::Package(x) => { + let ident = get_ident(tree, RefNode::PackageIdentifier(&x.nodes.0)); + scope.extends.1 = Some(ident.0); + } + PackageScope::Unit(_) => {} + } + } + let ident = get_ident(tree, RefNode::ClassIdentifier(&extend.1.nodes.0.nodes.1)); + scope.extends.0.push(ident.0); + for class in &extend.1.nodes.2 { + let ident = get_ident(tree, RefNode::ClassIdentifier(&class.1)); + scope.extends.0.push(ident.0); + } + } + if let Some(interfaces) = &node.nodes.6 { + for idec in interfaces.1.contents() { + let ident = get_ident(tree, RefNode::ClassIdentifier(&idec.nodes.0.nodes.1)); + let mut interface: (String, Option) = (ident.0, None); + if let Some(package_scope) = &idec.nodes.0.nodes.0 { + match package_scope { + PackageScope::Package(x) => { + let ident = get_ident(tree, RefNode::PackageIdentifier(&x.nodes.0)); + interface.1 = Some(ident.0); + } + PackageScope::Unit(_) => {} + } + } + scope.implements.push(interface); + } + } + + let (scopes, mut defs) = match_until_leave!(tree, event_iter, url, RefNode::ClassDeclaration)?; + scope.scopes = scopes; + scope.defs.append(&mut defs); + Some(scope) +} + +// `define definition +pub fn text_macro_def( + tree: &SyntaxTree, + node: &TextMacroDefinition, + event_iter: &mut EventIter, + url: &Url, +) -> Option { + let mut text_macro = GenericDec::new(url); + let ident = get_ident(tree, RefNode::TextMacroIdentifier(&node.nodes.2.nodes.0)); + text_macro.ident = ident.0; + text_macro.byte_idx = ident.1; + let type_str = &mut text_macro.type_str; + advance_until_enter!( + type_str, + tree, + event_iter, + RefNode::TextMacroIdentifier, + &TextMacroIdentifier + ); + text_macro.completion_kind = CompletionItemKind::FUNCTION; + text_macro.symbol_kind = SymbolKind::FUNCTION; + Some(text_macro) +} diff --git a/src/diagnostics.rs b/src/diagnostics.rs new file mode 100644 index 0000000..dc1d870 --- /dev/null +++ b/src/diagnostics.rs @@ -0,0 +1,496 @@ +use crate::server::ProjectConfig; +#[cfg(feature = "slang")] +use path_clean::PathClean; +use regex::Regex; +use ropey::Rope; +#[cfg(feature = "slang")] +use std::env::current_dir; +#[cfg(feature = "slang")] +use std::path::Path; +use std::path::PathBuf; +use std::process::{Command, Stdio}; +use tower_lsp::lsp_types::*; +#[cfg(feature = "slang")] +use veridian_slang::slang_compile; +use walkdir::DirEntry; +#[cfg(feature = "slang")] +use walkdir::WalkDir; + +#[cfg(feature = "slang")] +pub fn get_diagnostics( + uri: Url, + rope: &Rope, + files: Vec, + conf: &ProjectConfig, +) -> PublishDiagnosticsParams { + if !(cfg!(test) && (uri.to_string().starts_with("file:///test"))) { + let paths = get_paths(files, conf.auto_search_workdir); + let mut diagnostics = { + if conf.verilator.syntax.enabled { + if let Ok(path) = uri.to_file_path() { + match verilator_syntax( + rope, + path, + &conf.verilator.syntax.path, + &conf.verilator.syntax.args, + ) { + Some(diags) => diags, + None => Vec::new(), + } + } else { + Vec::new() + } + } else if conf.verible.syntax.enabled { + match verible_syntax(rope, &conf.verible.syntax.path, &conf.verible.syntax.args) { + Some(diags) => diags, + None => Vec::new(), + } + } else { + Vec::new() + } + }; + diagnostics.append(&mut parse_report( + uri.clone(), + slang_compile(paths).unwrap(), + )); + PublishDiagnosticsParams { + uri, + diagnostics, + version: None, + } + } else { + PublishDiagnosticsParams { + uri, + diagnostics: Vec::new(), + version: None, + } + } +} + +#[cfg(not(feature = "slang"))] +pub fn get_diagnostics( + uri: Url, + rope: &Rope, + #[allow(unused_variables)] files: Vec, + conf: &ProjectConfig, +) -> PublishDiagnosticsParams { + if !(cfg!(test) && (uri.to_string().starts_with("file:///test"))) { + let diagnostics = { + if conf.verilator.syntax.enabled { + if let Ok(path) = uri.to_file_path() { + match verilator_syntax( + rope, + path, + &conf.verilator.syntax.path, + &conf.verilator.syntax.args, + ) { + Some(diags) => diags, + None => Vec::new(), + } + } else { + Vec::new() + } + } else if conf.verible.syntax.enabled { + match verible_syntax(rope, &conf.verible.syntax.path, &conf.verible.syntax.args) { + Some(diags) => diags, + None => Vec::new(), + } + } else { + Vec::new() + } + }; + PublishDiagnosticsParams { + uri, + diagnostics, + version: None, + } + } else { + PublishDiagnosticsParams { + uri, + diagnostics: Vec::new(), + version: None, + } + } +} + +/// recursively find source file paths from working directory +/// and open files +#[cfg(feature = "slang")] +fn get_paths(files: Vec, search_workdir: bool) -> Vec { + // check recursively from working dir for source files + let mut paths: Vec = Vec::new(); + if search_workdir { + let walker = WalkDir::new(".").into_iter(); + for entry in walker.filter_entry(|e| !is_hidden(e)) { + let entry = entry.unwrap(); + if entry.file_type().is_file() { + let extension = entry.path().extension().unwrap(); + + if extension == "sv" || extension == "svh" || extension == "v" || extension == "vh" + { + paths.push(entry.path().to_path_buf()); + } + } + } + } + + // check recursively from opened files for source files + for file in files { + if let Ok(path) = file.to_file_path() { + if !paths.contains(&path) { + let walker = WalkDir::new(path.parent().unwrap()).into_iter(); + for entry in walker.filter_entry(|e| !is_hidden(e)).flatten() { + if entry.file_type().is_file() && entry.path().extension().is_some() { + let extension = entry.path().extension().unwrap(); + + if extension == "sv" + || extension == "svh" + || extension == "v" + || extension == "vh" + { + let entry_path = entry.path().to_path_buf(); + if !paths.contains(&entry_path) { + paths.push(entry_path); + } + } + } + } + } + } + } + paths +} + +pub fn is_hidden(entry: &DirEntry) -> bool { + entry + .file_name() + .to_str() + .map(|s| s.starts_with('.')) + .unwrap_or(false) +} + +#[cfg(feature = "slang")] +/// parse a report from slang +fn parse_report(uri: Url, report: String) -> Vec { + let mut diagnostics: Vec = Vec::new(); + for line in report.lines() { + let diag: Vec<&str> = line.splitn(5, ':').collect(); + if absolute_path(diag.first().unwrap()) == uri.to_file_path().unwrap().as_os_str() { + let pos = Position::new( + diag.get(1).unwrap().parse::().unwrap() - 1, + diag.get(2).unwrap().parse::().unwrap() - 1, + ); + diagnostics.push(Diagnostic::new( + Range::new(pos, pos), + slang_severity(diag.get(3).unwrap()), + None, + Some("slang".to_owned()), + (*diag.get(4).unwrap()).to_owned(), + None, + None, + )) + } + } + diagnostics +} + +#[cfg(feature = "slang")] +fn slang_severity(severity: &str) -> Option { + match severity { + " error" => Some(DiagnosticSeverity::ERROR), + " warning" => Some(DiagnosticSeverity::WARNING), + " note" => Some(DiagnosticSeverity::INFORMATION), + _ => None, + } +} + +#[cfg(feature = "slang")] +// convert relative path to absolute +fn absolute_path(path_str: &str) -> PathBuf { + let path = Path::new(path_str); + current_dir().unwrap().join(path).clean() +} + +/// convert captured severity string to DiagnosticSeverity +fn verilator_severity(severity: &str) -> Option { + match severity { + "Error" => Some(DiagnosticSeverity::ERROR), + s if s.starts_with("Warning") => Some(DiagnosticSeverity::WARNING), + // NOTE: afaik, verilator doesn't have an info or hint severity + _ => Some(DiagnosticSeverity::INFORMATION), + } +} + +/// syntax checking using verilator --lint-only +fn verilator_syntax( + rope: &Rope, + file_path: PathBuf, + verilator_syntax_path: &str, + verilator_syntax_args: &[String], +) -> Option> { + let mut child = Command::new(verilator_syntax_path) + .stdin(Stdio::piped()) + .stderr(Stdio::piped()) + .stdout(Stdio::piped()) + .args(verilator_syntax_args) + .arg(file_path.to_str()?) + .spawn() + .ok()?; + + static RE: std::sync::OnceLock = std::sync::OnceLock::new(); + let re = RE.get_or_init(|| { + Regex::new( + r"%(?PError|Warning)(-(?P[A-Z0-9_]+))?: (?P[^:]+):(?P\d+):((?P\d+):)? ?(?P.*)", + ) + .unwrap() + }); + // write file to stdin, read output from stdout + rope.write_to(child.stdin.as_mut()?).ok()?; + let output = child.wait_with_output().ok()?; + if !output.status.success() { + let mut diags: Vec = Vec::new(); + let raw_output = String::from_utf8(output.stderr).ok()?; + let filtered_output = raw_output + .lines() + .filter(|line| line.starts_with('%')) + .collect::>(); + for error in filtered_output { + let caps = match re.captures(error) { + Some(caps) => caps, + None => continue, + }; + + // check if diagnostic is for this file, since verilator can provide diagnostics for + // included files + if caps.name("filepath")?.as_str() != file_path.to_str().unwrap_or("") { + continue; + } + let severity = verilator_severity(caps.name("severity")?.as_str()); + let line: u32 = caps.name("line")?.as_str().to_string().parse().ok()?; + let col: u32 = caps.name("col").map_or("1", |m| m.as_str()).parse().ok()?; + let pos = Position::new(line - 1, col - 1); + let msg = match severity { + Some(DiagnosticSeverity::ERROR) => caps.name("message")?.as_str().to_string(), + Some(DiagnosticSeverity::WARNING) => format!( + "{}: {}", + caps.name("warning_type")?.as_str(), + caps.name("message")?.as_str() + ), + _ => "".to_string(), + }; + diags.push(Diagnostic::new( + Range::new(pos, pos), + severity, + None, + Some("verilator".to_string()), + msg, + None, + None, + )); + } + Some(diags) + } else { + None + } +} + +/// syntax checking using verible-verilog-syntax +fn verible_syntax( + rope: &Rope, + verible_syntax_path: &str, + verible_syntax_args: &[String], +) -> Option> { + let mut child = Command::new(verible_syntax_path) + .stdin(Stdio::piped()) + .stderr(Stdio::piped()) + .stdout(Stdio::piped()) + .args(verible_syntax_args) + .arg("-") + .spawn() + .ok()?; + + static RE: std::sync::OnceLock = std::sync::OnceLock::new(); + let re = RE.get_or_init(|| { + Regex::new( + r"^.+:(?P\d*):(?P\d*)(?:-(?P\d*))?:\s(?P.*)\s.*$", + ) + .unwrap() + }); + // write file to stdin, read output from stdout + rope.write_to(child.stdin.as_mut()?).ok()?; + let output = child.wait_with_output().ok()?; + if !output.status.success() { + let mut diags: Vec = Vec::new(); + let raw_output = String::from_utf8(output.stdout).ok()?; + for error in raw_output.lines() { + let caps = re.captures(error)?; + let line: u32 = caps.name("line")?.as_str().parse().ok()?; + let startcol: u32 = caps.name("startcol")?.as_str().parse().ok()?; + let endcol: Option = match caps.name("endcol").map(|e| e.as_str().parse()) { + Some(Ok(e)) => Some(e), + None => None, + Some(Err(_)) => return None, + }; + let start_pos = Position::new(line - 1, startcol - 1); + let end_pos = Position::new(line - 1, endcol.unwrap_or(startcol) - 1); + diags.push(Diagnostic::new( + Range::new(start_pos, end_pos), + Some(DiagnosticSeverity::ERROR), + None, + Some("verible".to_string()), + caps.name("message")?.as_str().to_string(), + None, + None, + )); + } + Some(diags) + } else { + None + } +} + +#[cfg(test)] +mod tests { + use super::*; + use crate::support::test_init; + use std::fs::File; + use std::io::Write; + use tempdir::TempDir; + + #[test] + #[cfg(feature = "slang")] + fn test_diagnostics() { + test_init(); + let uri = Url::from_file_path(absolute_path("test_data/diag/diag_test.sv")).unwrap(); + let expected = PublishDiagnosticsParams::new( + uri.clone(), + vec![Diagnostic::new( + Range::new(Position::new(3, 13), Position::new(3, 13)), + Some(DiagnosticSeverity::WARNING), + None, + Some("slang".to_owned()), + " cannot refer to element 2 of \'logic[1:0]\' [-Windex-oob]".to_owned(), + None, + None, + )], + None, + ); + let diag = get_diagnostics( + uri.clone(), + &Rope::default(), + vec![uri], + &ProjectConfig::default(), + ); + assert_eq!(diag.uri, expected.uri); + assert_eq!(diag.version, expected.version); + assert_eq!(diag.diagnostics.last(), expected.diagnostics.last()); + } + + #[test] + fn test_unsaved_file() { + test_init(); + let uri = Url::parse("file://test.sv").unwrap(); + get_diagnostics( + uri.clone(), + &Rope::default(), + vec![uri], + &ProjectConfig::default(), + ); + } + + #[test] + fn test_verible_syntax() { + let text = r#"module test; + logic abc; + logic abcd; + + a +endmodule +"#; + let doc = Rope::from_str(text); + let errors = verible_syntax(&doc, "verible-verilog-syntax", &[]) + .expect("verible-verilog-syntax not found, test can not run"); + let expected: Vec = vec![Diagnostic { + range: Range { + start: Position { + line: 5, + character: 0, + }, + end: Position { + line: 5, + character: 8, + }, + }, + severity: Some(DiagnosticSeverity::ERROR), + code: None, + source: Some("verible".to_string()), + message: "syntax error at token".to_string(), + related_information: None, + tags: None, + code_description: None, + data: None, + }]; + assert_eq!(errors, expected); + } + + #[test] + fn test_verilator_syntax() { + let text = r#"module test; + logic abc; + logic abcd; + + a +endmodule +"#; + let doc = Rope::from_str(text); + + // verilator can't read from stdin so we must create a temp dir to place our + // test file + let dir = TempDir::new("verilator_test").unwrap(); + let file_path_1 = dir.path().join("test.sv"); + let mut f = File::create(&file_path_1).unwrap(); + f.write_all(text.as_bytes()).unwrap(); + f.sync_all().unwrap(); + + let errors = verilator_syntax( + &doc, + file_path_1, + "verilator", + &[ + "--lint-only".to_string(), + "--sv".to_string(), + "-Wall".to_string(), + ], + ) + .expect("verilator not found, test can not run"); + + drop(f); + dir.close().unwrap(); + + let expected: Vec = vec![Diagnostic { + range: Range { + start: Position { + line: 5, + character: 0, + }, + end: Position { + line: 5, + character: 0, + }, + }, + severity: Some(DiagnosticSeverity::ERROR), + code: None, + source: Some("verilator".to_string()), + message: "syntax error, unexpected endmodule, expecting IDENTIFIER or randomize" + .to_string(), + related_information: None, + tags: None, + code_description: None, + data: None, + }]; + assert_eq!(errors[0].severity, expected[0].severity); + assert_eq!(errors[0].range.start.line, expected[0].range.start.line); + assert_eq!(errors[0].range.end.line, expected[0].range.end.line); + assert!(errors[0].message.contains("syntax error")); + } +} diff --git a/src/format.rs b/src/format.rs new file mode 100644 index 0000000..9796f35 --- /dev/null +++ b/src/format.rs @@ -0,0 +1,173 @@ +use crate::server::LSPServer; +use crate::sources::LSPSupport; +use log::info; +use ropey::Rope; +use std::process::{Command, Stdio}; +use tower_lsp::lsp_types::*; + +impl LSPServer { + pub fn formatting(&self, params: DocumentFormattingParams) -> Option> { + let uri = params.text_document.uri; + info!("formatting {}", &uri); + let file_id = self.srcs.get_id(&uri).to_owned(); + self.srcs.wait_parse_ready(file_id, false); + let file = self.srcs.get_file(file_id)?; + let file = file.read().ok()?; + + let conf = self.conf.read().unwrap(); + if conf.verible.format.enabled { + Some(vec![TextEdit::new( + Range::new( + file.text.char_to_pos(0), + file.text.char_to_pos(file.text.len_chars()), + ), + format_document( + &file.text, + None, + &conf.verible.format.path, + &conf.verible.format.args, + )?, + )]) + } else { + None + } + } + + pub fn range_formatting(&self, params: DocumentRangeFormattingParams) -> Option> { + let uri = params.text_document.uri; + info!("range formatting {}", &uri); + let file_id = self.srcs.get_id(&uri).to_owned(); + self.srcs.wait_parse_ready(file_id, false); + let file = self.srcs.get_file(file_id)?; + let file = file.read().ok()?; + + let conf = self.conf.read().unwrap(); + if conf.verible.format.enabled { + Some(vec![TextEdit::new( + file.text.char_range_to_range(0..file.text.len_chars()), + format_document( + &file.text, + Some(params.range), + &conf.verible.format.path, + &conf.verible.format.args, + )?, + )]) + } else { + None + } + } +} + +/// format the document using verible-verilog-format +pub fn format_document( + rope: &Rope, + range: Option, + verible_format_path: &str, + verible_format_args: &[String], +) -> Option { + let mut child = Command::new(verible_format_path); + child + .stdin(Stdio::piped()) + .stderr(Stdio::piped()) + .stdout(Stdio::piped()) + .args(verible_format_args); + // rangeFormatting + if let Some(r) = range { + child + .arg("--lines") + .arg(format!("{}-{}", r.start.line + 1, r.end.line + 1)); + } + let mut child = child.arg("-").spawn().ok()?; + + // write file to stdin, read output from stdout + rope.write_to(child.stdin.as_mut()?).ok()?; + let output = child.wait_with_output().ok()?; + if output.status.success() { + info!("formatting succeeded"); + let raw_output = String::from_utf8(output.stdout).ok()?; + Some(raw_output) + } else { + None + } +} + +#[cfg(test)] +mod tests { + use super::*; + use crate::server::ProjectConfig; + use crate::support::test_init; + use which::which; + + #[test] + fn test_formatting() { + test_init(); + let text = r#" +module test; + logic a; + logic b; +endmodule"#; + let text_fixed = r#" +module test; + logic a; + logic b; +endmodule +"#; + let doc = Rope::from_str(&text); + if which("verible-verilog-format").is_ok() { + assert_eq!( + format_document( + &doc, + None, + &ProjectConfig::default().verible.format.path, + &[] + ) + .unwrap(), + text_fixed.to_string() + ); + } + } + + #[test] + fn test_range_formatting() { + test_init(); + let text = r#"module t1; + logic a; + logic b; + logic c; +endmodule + + +module t2; + logic a; + logic b; + logic c; +endmodule"#; + + let text_fixed = r#"module t1; + logic a; + logic b; + logic c; +endmodule + + +module t2; + logic a; + logic b; + logic c; +endmodule +"#; + let doc = Rope::from_str(&text); + if which("verible-verilog-format").is_ok() { + assert_eq!( + format_document( + &doc, + Some(Range::new(Position::new(0, 0), Position::new(4, 9))), + &ProjectConfig::default().verible.format.path, + &[] + ) + .unwrap(), + text_fixed.to_string() + ); + } + } +} diff --git a/src/lib.rs b/src/lib.rs new file mode 100644 index 0000000..999d875 --- /dev/null +++ b/src/lib.rs @@ -0,0 +1,9 @@ +#![recursion_limit = "256"] + +pub mod completion; +pub mod definition; +pub mod diagnostics; +pub mod format; +pub mod server; +pub mod sources; +pub mod support; diff --git a/src/main.rs b/src/main.rs new file mode 100644 index 0000000..7a2a8e2 --- /dev/null +++ b/src/main.rs @@ -0,0 +1,35 @@ +#![recursion_limit = "256"] + +use log::info; +use std::sync::Arc; +use structopt::StructOpt; +use tower_lsp::{LspService, Server}; + +mod completion; +mod definition; +mod diagnostics; +mod format; +mod server; +mod sources; +#[cfg(test)] +mod support; +use server::Backend; + +#[derive(StructOpt, Debug)] +#[structopt(name = "veridian", about = "A SystemVerilog/Verilog Language Server")] +struct Opt {} + +#[tokio::main] +async fn main() { + let _ = Opt::from_args(); + let log_handle = flexi_logger::Logger::with(flexi_logger::LogSpecification::info()) + .start() + .unwrap(); + info!("starting veridian..."); + + let stdin = tokio::io::stdin(); + let stdout = tokio::io::stdout(); + + let (service, messages) = LspService::new(|client| Arc::new(Backend::new(client, log_handle))); + Server::new(stdin, stdout, messages).serve(service).await; +} diff --git a/src/server.rs b/src/server.rs new file mode 100644 index 0000000..e67d577 --- /dev/null +++ b/src/server.rs @@ -0,0 +1,385 @@ +use crate::sources::*; + +use crate::completion::keyword::*; +use flexi_logger::LoggerHandle; +use log::{debug, info, warn}; +use path_clean::PathClean; +use serde::{Deserialize, Serialize}; +use std::env::current_dir; +use std::fs::File; +use std::io::Read; +use std::path::PathBuf; +use std::string::ToString; +use std::sync::{Mutex, RwLock}; +use tower_lsp::jsonrpc::{Error, ErrorCode, Result}; +use tower_lsp::lsp_types::*; +use tower_lsp::{Client, LanguageServer}; +use which::which; + +pub struct LSPServer { + pub srcs: Sources, + pub key_comps: Vec, + pub sys_tasks: Vec, + pub directives: Vec, + pub conf: RwLock, + pub log_handle: Mutex>, +} + +impl LSPServer { + pub fn new(log_handle: Option) -> LSPServer { + LSPServer { + srcs: Sources::new(), + key_comps: keyword_completions(KEYWORDS), + sys_tasks: other_completions(SYS_TASKS), + directives: other_completions(DIRECTIVES), + conf: RwLock::new(ProjectConfig::default()), + log_handle: Mutex::new(log_handle), + } + } +} + +pub struct Backend { + client: Client, + server: LSPServer, +} + +impl Backend { + pub fn new(client: Client, log_handle: LoggerHandle) -> Backend { + Backend { + client, + server: LSPServer::new(Some(log_handle)), + } + } +} + +#[derive(strum_macros::Display, Debug, Serialize, Deserialize)] +pub enum LogLevel { + #[strum(serialize = "error")] + Error, + #[strum(serialize = "warn")] + Warn, + #[strum(serialize = "info")] + Info, + #[strum(serialize = "debug")] + Debug, + #[strum(serialize = "trace")] + Trace, +} + +#[derive(Debug, Serialize, Deserialize)] +#[serde(default)] +pub struct ProjectConfig { + // if true, recursively search the working directory for files to run diagnostics on + pub auto_search_workdir: bool, + // list of directories with header files + pub include_dirs: Vec, + // list of directories to recursively search for SystemVerilog/Verilog sources + pub source_dirs: Vec, + // config options for verible tools + pub verible: Verible, + // config options for verilator tools + pub verilator: Verilator, + // log level + pub log_level: LogLevel, +} + +impl Default for ProjectConfig { + fn default() -> Self { + ProjectConfig { + auto_search_workdir: true, + include_dirs: Vec::new(), + source_dirs: Vec::new(), + verible: Verible::default(), + verilator: Verilator::default(), + log_level: LogLevel::Info, + } + } +} + +#[derive(Default, Debug, Serialize, Deserialize)] +#[serde(default)] +pub struct Verible { + pub syntax: VeribleSyntax, + pub format: VeribleFormat, +} + +#[derive(Debug, Serialize, Deserialize)] +#[serde(default)] +pub struct VeribleSyntax { + pub enabled: bool, + pub path: String, + pub args: Vec, +} + +impl Default for VeribleSyntax { + fn default() -> Self { + Self { + enabled: true, + path: "verible-verilog-syntax".to_string(), + args: Vec::new(), + } + } +} + +#[derive(Debug, Default, Serialize, Deserialize)] +#[serde(default)] +pub struct Verilator { + pub syntax: VerilatorSyntax, +} + +#[derive(Debug, Serialize, Deserialize)] +#[serde(default)] +pub struct VerilatorSyntax { + pub enabled: bool, + pub path: String, + pub args: Vec, +} + +impl Default for VerilatorSyntax { + fn default() -> Self { + Self { + enabled: true, + path: "verilator".to_string(), + args: vec![ + "--lint-only".to_string(), + "--sv".to_string(), + "-Wall".to_string(), + ], + } + } +} + +#[derive(Debug, Serialize, Deserialize)] +#[serde(default)] +pub struct VeribleFormat { + pub enabled: bool, + pub path: String, + pub args: Vec, +} + +impl Default for VeribleFormat { + fn default() -> Self { + Self { + enabled: true, + path: "verible-verilog-format".to_string(), + args: Vec::new(), + } + } +} + +fn read_config(root_uri: Option) -> anyhow::Result { + let path = root_uri + .ok_or_else(|| anyhow::anyhow!("couldn't resolve workdir path"))? + .to_file_path() + .map_err(|_| anyhow::anyhow!("couldn't resolve workdir path"))?; + let mut config: Option = None; + for dir in path.ancestors() { + let config_path = dir.join("veridian.yaml"); + if config_path.exists() { + info!("found config: veridian.yaml"); + config = Some(config_path); + break; + } + let config_path = dir.join("veridian.yml"); + if config_path.exists() { + info!("found config: veridian.yml"); + config = Some(config_path); + break; + } + } + let mut contents = String::new(); + File::open(config.ok_or_else(|| anyhow::anyhow!("unable to read config file"))?)? + .read_to_string(&mut contents)?; + info!("reading config file"); + Ok(serde_yaml::from_str(&contents)?) +} + +// convert string path to absolute path +fn absolute_path(path_str: &str) -> Option { + let path = PathBuf::from(path_str); + if !path.exists() { + return None; + } + if !path.has_root() { + Some(current_dir().unwrap().join(path).clean()) + } else { + Some(path) + } +} + +#[tower_lsp::async_trait] +impl LanguageServer for Backend { + async fn initialize(&self, params: InitializeParams) -> Result { + // grab include dirs and source dirs from config, and convert to abs path + let mut inc_dirs = self.server.srcs.include_dirs.write().unwrap(); + let mut src_dirs = self.server.srcs.source_dirs.write().unwrap(); + match read_config(params.root_uri) { + Ok(conf) => { + inc_dirs.extend(conf.include_dirs.iter().filter_map(|x| absolute_path(x))); + debug!("{:#?}", inc_dirs); + src_dirs.extend(conf.source_dirs.iter().filter_map(|x| absolute_path(x))); + debug!("{:#?}", src_dirs); + let mut log_handle = self.server.log_handle.lock().unwrap(); + let log_handle = log_handle.as_mut(); + if let Some(handle) = log_handle { + handle + .parse_and_push_temp_spec(&conf.log_level.to_string()) + .map_err(|e| Error { + code: ErrorCode::InvalidParams, + message: e.to_string().into(), + data: None, + })?; + } + *self.server.conf.write().unwrap() = conf; + } + Err(e) => { + warn!("found errors in config file: {:#?}", e); + } + } + let mut conf = self.server.conf.write().unwrap(); + conf.verible.syntax.enabled = which(&conf.verible.syntax.path).is_ok(); + if cfg!(feature = "slang") { + info!("enabled linting with slang"); + } + if conf.verilator.syntax.enabled { + info!("enabled linting with verilator") + } else if conf.verible.syntax.enabled { + info!("enabled linting with verible-verilog-syntax") + } + conf.verible.format.enabled = which(&conf.verible.format.path).is_ok(); + if conf.verible.format.enabled { + info!("enabled formatting with verible-verilog-format"); + } else { + info!("formatting unavailable"); + } + drop(inc_dirs); + drop(src_dirs); + // parse all source files found from walking source dirs and include dirs + self.server.srcs.init(); + Ok(InitializeResult { + server_info: None, + capabilities: ServerCapabilities { + text_document_sync: Some(TextDocumentSyncCapability::Options( + TextDocumentSyncOptions { + open_close: Some(true), + change: Some(TextDocumentSyncKind::INCREMENTAL), + will_save: None, + will_save_wait_until: None, + save: Some(TextDocumentSyncSaveOptions::SaveOptions(SaveOptions { + include_text: None, + })), + }, + )), + completion_provider: Some(CompletionOptions { + resolve_provider: Some(false), + trigger_characters: Some(vec![ + ".".to_string(), + "$".to_string(), + "`".to_string(), + ]), + work_done_progress_options: WorkDoneProgressOptions { + work_done_progress: None, + }, + all_commit_characters: None, + //TODO: check if corect + completion_item: None, + }), + definition_provider: Some(OneOf::Left(true)), + hover_provider: Some(HoverProviderCapability::Simple(true)), + document_symbol_provider: Some(OneOf::Left(true)), + document_formatting_provider: Some(OneOf::Left(conf.verible.format.enabled)), + document_range_formatting_provider: Some(OneOf::Left(conf.verible.format.enabled)), + document_highlight_provider: Some(OneOf::Left(true)), + ..ServerCapabilities::default() + }, + }) + } + async fn initialized(&self, _: InitializedParams) { + self.client + .log_message(MessageType::INFO, "veridian initialized!") + .await; + } + async fn shutdown(&self) -> Result<()> { + Ok(()) + } + async fn did_open(&self, params: DidOpenTextDocumentParams) { + let diagnostics = self.server.did_open(params); + self.client + .publish_diagnostics( + diagnostics.uri, + diagnostics.diagnostics, + diagnostics.version, + ) + .await; + } + async fn did_change(&self, params: DidChangeTextDocumentParams) { + self.server.did_change(params); + } + async fn did_save(&self, params: DidSaveTextDocumentParams) { + let diagnostics = self.server.did_save(params); + self.client + .publish_diagnostics( + diagnostics.uri, + diagnostics.diagnostics, + diagnostics.version, + ) + .await; + } + async fn completion(&self, params: CompletionParams) -> Result> { + Ok(self.server.completion(params)) + } + async fn goto_definition( + &self, + params: GotoDefinitionParams, + ) -> Result> { + Ok(self.server.goto_definition(params)) + } + async fn hover(&self, params: HoverParams) -> Result> { + Ok(self.server.hover(params)) + } + async fn document_symbol( + &self, + params: DocumentSymbolParams, + ) -> Result> { + Ok(self.server.document_symbol(params)) + } + async fn formatting(&self, params: DocumentFormattingParams) -> Result>> { + Ok(self.server.formatting(params)) + } + async fn range_formatting( + &self, + params: DocumentRangeFormattingParams, + ) -> Result>> { + Ok(self.server.range_formatting(params)) + } + async fn document_highlight( + &self, + params: DocumentHighlightParams, + ) -> Result>> { + Ok(self.server.document_highlight(params)) + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_config() { + let config = r#" +auto_search_workdir: false +format: true +verible: + syntax: + enabled: true + path: "verible-verilog-syntax" + format: + args: + - --net_variable_alignment=align +log_level: Info +"#; + let config = serde_yaml::from_str::(config); + dbg!(&config); + assert!(config.is_ok()); + } +} diff --git a/src/sources.rs b/src/sources.rs new file mode 100644 index 0000000..06f021c --- /dev/null +++ b/src/sources.rs @@ -0,0 +1,629 @@ +use crate::definition::def_types::*; +use crate::definition::get_scopes; +use crate::diagnostics::{get_diagnostics, is_hidden}; +use crate::server::LSPServer; +use log::{debug, error, trace}; +use pathdiff::diff_paths; +use ropey::{Rope, RopeSlice}; +use std::cmp::min; +use std::collections::HashMap; +use std::env::current_dir; +use std::fs; +use std::ops::Range as StdRange; +use std::path::PathBuf; +use std::sync::{Arc, Condvar, Mutex, RwLock}; +use std::thread; +use std::time::Instant; +use sv_parser::*; +use thread::JoinHandle; +use tower_lsp::lsp_types::*; +use walkdir::WalkDir; + +impl LSPServer { + pub fn did_open(&self, params: DidOpenTextDocumentParams) -> PublishDiagnosticsParams { + let document: TextDocumentItem = params.text_document; + let uri = document.uri.clone(); + debug!("did_open: {}", &uri); + // check if doc is already added + if self.srcs.names.read().unwrap().contains_key(&document.uri) { + // convert to a did_change that replace the entire text + self.did_change(DidChangeTextDocumentParams { + text_document: VersionedTextDocumentIdentifier::new(document.uri, document.version), + content_changes: vec![TextDocumentContentChangeEvent { + range: None, + range_length: None, + text: document.text, + }], + }); + } else { + self.srcs.add(document); + } + // diagnostics + let urls = self.srcs.names.read().unwrap().keys().cloned().collect(); + let file_id = self.srcs.get_id(&uri); + let file = self.srcs.get_file(file_id).unwrap(); + let file = file.read().unwrap(); + get_diagnostics(uri, &file.text, urls, &self.conf.read().unwrap()) + } + + pub fn did_change(&self, params: DidChangeTextDocumentParams) { + debug!("did_change: {}", ¶ms.text_document.uri); + let file_id = self.srcs.get_id(¶ms.text_document.uri); + let file = self.srcs.get_file(file_id).unwrap(); + let mut file = file.write().unwrap(); + // loop through changes and apply + for change in params.content_changes { + if change.range.is_none() { + file.text = Rope::from_str(&change.text); + } else { + file.text.apply_change(&change); + } + file.last_change_range = change.range; + } + file.version = params.text_document.version; + drop(file); + + // invalidate syntaxtree and wake parse thread + let meta_data = self.srcs.get_meta_data(file_id).unwrap(); + let (lock, cvar) = &*meta_data.read().unwrap().valid_parse; + let mut valid = lock.lock().unwrap(); + *valid = false; + cvar.notify_all(); + } + + pub fn did_save(&self, params: DidSaveTextDocumentParams) -> PublishDiagnosticsParams { + let urls = self.srcs.names.read().unwrap().keys().cloned().collect(); + let file_id = self.srcs.get_id(¶ms.text_document.uri); + let file = self.srcs.get_file(file_id).unwrap(); + let file = file.read().unwrap(); + get_diagnostics( + params.text_document.uri, + &file.text, + urls, + &self.conf.read().unwrap(), + ) + } +} + +/// The Source struct holds all file specific information +pub struct Source { + pub id: usize, + pub uri: Url, + pub text: Rope, + pub version: i32, + pub syntax_tree: Option, + // if there is a parse error, we can remove the last change + pub last_change_range: Option, +} + +/// file metadata, including whether or not the syntax tree is up to date +pub struct SourceMeta { + pub id: usize, + pub valid_parse: Arc<(Mutex, Condvar)>, + pub parse_handle: JoinHandle<()>, +} + +/// find SystemVerilog/Verilog sources recursively from opened files +fn find_src_paths(dirs: &[PathBuf]) -> Vec { + let mut paths: Vec = Vec::new(); + + for dir in dirs { + let walker = WalkDir::new(dir).into_iter(); + for entry in walker.filter_entry(|e| !is_hidden(e)) { + let entry = entry.unwrap(); + if entry.file_type().is_file() && entry.path().extension().is_some() { + let extension = entry.path().extension().unwrap(); + + if extension == "sv" || extension == "svh" || extension == "v" || extension == "vh" + { + let entry_path = entry.path().to_path_buf(); + if !paths.contains(&entry_path) { + paths.push(entry_path); + } + } + } + } + } + paths +} + +/// The Sources struct manages all source files +pub struct Sources { + // all files + pub files: Arc>>>>, + // map file urls to id + pub names: Arc>>, + // file metadata + pub meta: Arc>>>>, + // all source files are indexed into this tree, which can then + // be used for completion, name resolution + pub scope_tree: Arc>>, + // include directories, passed to parser to resolve `include + pub include_dirs: Arc>>, + // source directories + pub source_dirs: Arc>>, +} + +impl std::default::Default for Sources { + fn default() -> Self { + Self::new() + } +} + +impl Sources { + pub fn new() -> Self { + Self { + files: Arc::new(RwLock::new(Vec::new())), + names: Arc::new(RwLock::new(HashMap::new())), + meta: Arc::new(RwLock::new(Vec::new())), + scope_tree: Arc::new(RwLock::new(None)), + include_dirs: Arc::new(RwLock::new(Vec::new())), + source_dirs: Arc::new(RwLock::new(Vec::new())), + } + } + pub fn init(&self) { + let mut paths: Vec = Vec::new(); + for path in &*self.include_dirs.read().unwrap() { + paths.push(path.clone()); + } + for path in &*self.source_dirs.read().unwrap() { + paths.push(path.clone()); + } + // find and add all source/header files recursively from configured include and source directories + let src_paths = find_src_paths(&paths); + for path in src_paths { + if let Ok(url) = Url::from_file_path(&path) { + if let Ok(text) = fs::read_to_string(&path) { + self.add(TextDocumentItem::new( + url, + "systemverilog".to_string(), + -1, + text, + )); + } + } + } + } + + /// add a source file, creating a parse thread for that file + pub fn add(&self, doc: TextDocumentItem) { + // use a condvar to synchronize the parse thread + // the valid bool decides whether or not the file + // needs to be re-parsed + #[allow(clippy::mutex_atomic)] // https://github.com/rust-lang/rust-clippy/issues/1516 + let valid_parse = Arc::new((Mutex::new(false), Condvar::new())); + let valid_parse2 = valid_parse.clone(); + let mut files = self.files.write().unwrap(); + let source = Arc::new(RwLock::new(Source { + id: files.len(), + uri: doc.uri.clone(), + text: Rope::from_str(&doc.text), + version: doc.version, + syntax_tree: None, + last_change_range: None, + })); + let source_handle = source.clone(); + let scope_handle = self.scope_tree.clone(); + let inc_dirs = self.include_dirs.clone(); + + // spawn parse thread + let parse_handle = thread::spawn(move || { + let (lock, cvar) = &*valid_parse2; + loop { + let now = Instant::now(); + let file = source_handle.read().unwrap(); + let text = file.text.clone(); + let uri = &file.uri.clone(); + let range = &file.last_change_range.clone(); + drop(file); + trace!("{}, parse read: {}", uri, now.elapsed().as_millis()); + let syntax_tree = parse(&text, uri, range, &inc_dirs.read().unwrap()); + let mut scope_tree = match &syntax_tree { + Some(tree) => get_scopes(tree, uri), + None => None, + }; + trace!( + "{}, parse read complete: {}", + uri, + now.elapsed().as_millis() + ); + let mut file = source_handle.write().unwrap(); + trace!("{}, parse write: {}", uri, now.elapsed().as_millis()); + file.syntax_tree = syntax_tree; + drop(file); + debug!("try write global scope"); + let mut global_scope = scope_handle.write().unwrap(); + match &mut *global_scope { + Some(scope) => match &mut scope_tree { + Some(tree) => { + scope.defs.retain(|x| &x.url() != uri); + scope.scopes.retain(|x| &x.url() != uri); + scope.defs.append(&mut tree.defs); + scope.scopes.append(&mut tree.scopes); + } + None => (), + }, + None => *global_scope = scope_tree, + } + // eprintln!("{:#?}", *global_scope); + drop(global_scope); + trace!("{}, write global scope", uri); + trace!( + "{}, parse write complete: {}", + uri, + now.elapsed().as_millis() + ); + let mut valid = lock.lock().unwrap(); + *valid = true; + cvar.notify_all(); + while *valid { + valid = cvar.wait(valid).unwrap(); + } + } + }); + files.push(source); + let fid = files.len() - 1; + self.meta + .write() + .unwrap() + .push(Arc::new(RwLock::new(SourceMeta { + id: fid, + valid_parse, + parse_handle, + }))); + debug!("added {}", &doc.uri); + self.names.write().unwrap().insert(doc.uri, fid); + } + + /// get file by id + pub fn get_file(&self, id: usize) -> Option>> { + let files = self.files.read().ok()?; + for file in files.iter() { + let source = file.read().ok()?; + if source.id == id { + return Some(file.clone()); + } + } + None + } + + /// get metadata by file id + pub fn get_meta_data(&self, id: usize) -> Option>> { + let meta = self.meta.read().ok()?; + for data in meta.iter() { + let i = data.read().ok()?; + if i.id == id { + return Some(data.clone()); + } + } + None + } + + /// wait for a valid parse + pub fn wait_parse_ready(&self, id: usize, wait_valid: bool) { + let file = self.get_file(id).unwrap(); + let file = file.read().unwrap(); + if file.syntax_tree.is_none() || wait_valid { + drop(file); + let meta_data = self.get_meta_data(id).unwrap(); + let (lock, cvar) = &*meta_data.read().unwrap().valid_parse; + let mut valid = lock.lock().unwrap(); + while !*valid { + valid = cvar.wait(valid).unwrap(); + } + } + } + + /// get file id from url + pub fn get_id(&self, uri: &Url) -> usize { + *self.names.read().unwrap().get(uri).unwrap() + } + + /// compute identifier completions + pub fn get_completions( + &self, + token: &str, + byte_idx: usize, + url: &Url, + ) -> Option { + debug!("retrieving identifier completion for token: {}", &token); + Some(CompletionList { + is_incomplete: false, + items: self + .scope_tree + .read() + .ok()? + .as_ref()? + .get_completion(token, byte_idx, url), + }) + } + + /// compute dot completions + pub fn get_dot_completions( + &self, + token: &str, + byte_idx: usize, + url: &Url, + ) -> Option { + debug!("retrieving dot completion for token: {}", &token); + let tree = self.scope_tree.read().ok()?; + Some(CompletionList { + is_incomplete: false, + items: tree + .as_ref()? + .get_dot_completion(token, byte_idx, url, tree.as_ref()?), + }) + } +} + +//TODO: show all unrecoverable parse errors to user +/// parse the file using sv-parser, attempt to recover if the parse fails +pub fn parse( + doc: &Rope, + uri: &Url, + last_change_range: &Option, + inc_paths: &[PathBuf], +) -> Option { + let mut parse_iterations = 1; + let mut i = 0; + let mut includes: Vec = inc_paths.to_vec(); + let mut reverted_change = false; + let mut text = doc.clone(); + + while i < parse_iterations { + i += 1; + match parse_sv_str( + &text.to_string(), + uri.to_file_path().unwrap(), + &HashMap::new(), + &includes, + false, + ) { + Ok((syntax_tree, _)) => { + debug!("parse complete of {}", uri); + trace!("{}", syntax_tree.to_string()); + return Some(syntax_tree); + } + Err(err) => { + match err { + // syntax error + sv_parser::Error::Parse(trace) => match trace { + Some((_, bpos)) => { + let mut line_start = text.byte_to_line(bpos); + let mut line_end = text.byte_to_line(bpos) + 1; + if !reverted_change { + if let Some(range) = last_change_range { + line_start = range.start.line as usize; + line_end = range.end.line as usize + 1; + reverted_change = true; + } + } + for line_idx in line_start..line_end { + let line = text.line(line_idx); + let start_char = text.line_to_char(line_idx); + let line_length = line.len_chars(); + text.remove(start_char..(start_char + line_length - 1)); + text.insert(start_char, &" ".to_owned().repeat(line_length)); + } + parse_iterations += 1; + } + None => return None, + }, + // include error, take the include path from the error message and + // add it as an include dir for the next parser invocation + sv_parser::Error::Include { source: x } => { + if let sv_parser::Error::File { source: _, path: z } = *x { + // Include paths have to be relative to the working directory + // so we have to convert a source file relative path to a working directory + // relative path. This should have been handled by sv-parser + let mut inc_path_given = z.clone(); + let mut uri_path = uri.to_file_path().unwrap(); + uri_path.pop(); + let rel_path = diff_paths(uri_path, current_dir().unwrap()).unwrap(); + inc_path_given.pop(); + let inc_path = rel_path.join(inc_path_given); + if !includes.contains(&inc_path) { + includes.push(inc_path); + } else { + error!("parser: include error: {:?}", z); + break; + } + parse_iterations += 1; + } + } + _ => error!("parse error, {:?}", err), + }; + } + } + } + None +} + +//TODO: add bounds checking for utf8<->utf16 conversions +/// This trait defines some helper functions to convert between lsp types +/// and char/byte positions +pub trait LSPSupport { + fn pos_to_byte(&self, pos: &Position) -> usize; + fn pos_to_char(&self, pos: &Position) -> usize; + fn byte_to_pos(&self, byte_idx: usize) -> Position; + fn char_to_pos(&self, char_idx: usize) -> Position; + fn range_to_char_range(&self, range: &Range) -> StdRange; + fn char_range_to_range(&self, range: StdRange) -> Range; + fn apply_change(&mut self, change: &TextDocumentContentChangeEvent); +} + +/// Extend ropey's Rope type with lsp convenience functions +impl LSPSupport for Rope { + fn pos_to_byte(&self, pos: &Position) -> usize { + self.char_to_byte(self.pos_to_char(pos)) + } + fn pos_to_char(&self, pos: &Position) -> usize { + let line_slice = self.line(pos.line as usize); + self.line_to_char(pos.line as usize) + line_slice.utf16_cu_to_char(pos.character as usize) + } + fn byte_to_pos(&self, byte_idx: usize) -> Position { + self.char_to_pos(self.byte_to_char(min(byte_idx, self.len_bytes() - 1))) + } + fn char_to_pos(&self, char_idx: usize) -> Position { + let line = self.char_to_line(char_idx); + let line_slice = self.line(line); + Position { + line: line as u32, + character: line_slice.char_to_utf16_cu(char_idx - self.line_to_char(line)) as u32, + } + } + fn range_to_char_range(&self, range: &Range) -> StdRange { + self.pos_to_char(&range.start)..self.pos_to_char(&range.end) + } + fn char_range_to_range(&self, range: StdRange) -> Range { + Range { + start: self.char_to_pos(range.start), + end: self.char_to_pos(range.end), + } + } + fn apply_change(&mut self, change: &TextDocumentContentChangeEvent) { + if let Some(range) = change.range { + let char_range = self.range_to_char_range(&range); + self.remove(char_range.clone()); + if !change.text.is_empty() { + self.insert(char_range.start, &change.text); + } + } + } +} + +impl<'a> LSPSupport for RopeSlice<'a> { + fn pos_to_byte(&self, pos: &Position) -> usize { + self.char_to_byte(self.pos_to_char(pos)) + } + fn pos_to_char(&self, pos: &Position) -> usize { + let line_slice = self.line(pos.line as usize); + self.line_to_char(pos.line as usize) + line_slice.utf16_cu_to_char(pos.character as usize) + } + fn byte_to_pos(&self, byte_idx: usize) -> Position { + self.char_to_pos(self.byte_to_char(min(byte_idx, self.len_bytes() - 1))) + } + fn char_to_pos(&self, char_idx: usize) -> Position { + let line = self.char_to_line(char_idx); + let line_slice = self.line(line); + Position { + line: line as u32, + character: line_slice.char_to_utf16_cu(char_idx - self.line_to_char(line)) as u32, + } + } + fn range_to_char_range(&self, range: &Range) -> StdRange { + self.pos_to_char(&range.start)..self.pos_to_char(&range.end) + } + fn char_range_to_range(&self, range: StdRange) -> Range { + Range { + start: self.char_to_pos(range.start), + end: self.char_to_pos(range.end), + } + } + fn apply_change(&mut self, _: &TextDocumentContentChangeEvent) { + panic!("can't edit a rope slice"); + } +} + +#[cfg(test)] +mod tests { + use super::*; + use crate::support::test_init; + use std::fs::read_to_string; + + #[test] + fn test_open_and_change() { + test_init(); + let server = LSPServer::new(None); + let uri = Url::parse("file:///test.sv").unwrap(); + let text = r#"module test; + logic abc; +endmodule"#; + + let open_params = DidOpenTextDocumentParams { + text_document: TextDocumentItem { + uri: uri.clone(), + language_id: "systemverilog".to_owned(), + version: 0, + text: text.to_owned(), + }, + }; + server.did_open(open_params); + let fid = server.srcs.get_id(&uri); + let file = server.srcs.get_file(fid).unwrap(); + let file = file.read().unwrap(); + assert_eq!(file.text.to_string(), text.to_owned()); + drop(file); + + let change_params = DidChangeTextDocumentParams { + text_document: VersionedTextDocumentIdentifier { uri, version: 1 }, + content_changes: vec![TextDocumentContentChangeEvent { + range: Some(Range { + start: Position { + line: 1, + character: 8, + }, + end: Position { + line: 1, + character: 11, + }, + }), + range_length: None, + text: "var1".to_owned(), + }], + }; + server.did_change(change_params); + let file = server.srcs.get_file(fid).unwrap(); + let file = file.read().unwrap(); + assert_eq!( + file.text.to_string(), + r#"module test; + logic var1; +endmodule"# + .to_owned() + ); + assert_eq!(file.version, 1); + } + + #[test] + fn test_fault_tolerance() { + test_init(); + let server = LSPServer::new(None); + let uri = Url::parse("file:///test.sv").unwrap(); + let text = r#"module test; + logic abc +endmodule"#; + let open_params = DidOpenTextDocumentParams { + text_document: TextDocumentItem { + uri: uri.clone(), + language_id: "systemverilog".to_owned(), + version: 0, + text: text.to_owned(), + }, + }; + server.did_open(open_params); + let fid = server.srcs.get_id(&uri); + + server.srcs.wait_parse_ready(fid, true); + + assert!(server + .srcs + .scope_tree + .read() + .unwrap() + .as_ref() + .unwrap() + .contains_scope("test")); + } + + #[test] + fn test_header() { + test_init(); + let mut d = PathBuf::from(env!("CARGO_MANIFEST_DIR")); + d.push("test_data/top_inc.sv"); + let text = read_to_string(&d).unwrap(); + let doc = Rope::from_str(&text); + assert!(parse(&doc, &Url::from_file_path(d).unwrap(), &None, &Vec::new()).is_some(),); + // TODO: add missing header test + } +} diff --git a/src/support.rs b/src/support.rs new file mode 100644 index 0000000..1b2df28 --- /dev/null +++ b/src/support.rs @@ -0,0 +1,3 @@ +pub fn test_init() { + let _ = flexi_logger::Logger::with(flexi_logger::LogSpecification::info()).start(); +} diff --git a/test/client/src/.gitignore b/test/client/src/.gitignore new file mode 100644 index 0000000..1ce0a74 --- /dev/null +++ b/test/client/src/.gitignore @@ -0,0 +1,4 @@ +out +node_modules +.vscode-test +*.vsix diff --git a/test/client/src/.vscodeignore b/test/client/src/.vscodeignore new file mode 100644 index 0000000..58d828c --- /dev/null +++ b/test/client/src/.vscodeignore @@ -0,0 +1,8 @@ +.vscode/** +**/*.ts +**/*.map +.gitignore +**/tsconfig.json +**/tsconfig.base.json +contributing.md +.travis.yml diff --git a/test/client/src/README.md b/test/client/src/README.md new file mode 100644 index 0000000..65c95a5 --- /dev/null +++ b/test/client/src/README.md @@ -0,0 +1,6 @@ +# veridian + +a vscode client extension for the veridian language server. + +- veridian must be installed seperately, see https://github.com/vivekmalneedi/veridian for details +- provides syntax highlighting, the grammar for which is borrowed from https://github.com/TheClams/SystemVerilog and is under the Apache 2.0 License diff --git a/test/client/src/extension.ts b/test/client/src/extension.ts new file mode 100644 index 0000000..098f125 --- /dev/null +++ b/test/client/src/extension.ts @@ -0,0 +1,56 @@ +/* -------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + * ------------------------------------------------------------------------------------------ */ + +import { workspace, ExtensionContext } from "vscode"; + +import { + LanguageClient, + LanguageClientOptions, + ServerOptions, + Executable, +} from "vscode-languageclient/node"; + +let client: LanguageClient; +const workSpaceFolder = workspace.workspaceFolders?.[0]; +let cwd: string = workSpaceFolder.uri.fsPath; +const serverPath: string = workspace.getConfiguration().get("veridian.serverPath"); + +export function activate(context: ExtensionContext) { + const run: Executable = { + command: serverPath, + // options: { cwd }, + }; + + // If the extension is launched in debug mode then the debug server options are used + // Otherwise the run options are used + let serverOptions: ServerOptions = { + run, + debug: run, + }; + + // Options to control the language client + let clientOptions: LanguageClientOptions = { + // Register the server for plain text documents + documentSelector: [{ scheme: "file", language: "systemverilog" }], + }; + + // Create the language client and start the client. + client = new LanguageClient( + "veridian", + "veridian", + serverOptions, + clientOptions + ); + + // Start the client. This will also launch the server + client.start(); +} + +export function deactivate(): Thenable | undefined { + if (!client) { + return undefined; + } + return client.stop(); +} diff --git a/test/client/src/package-lock.json b/test/client/src/package-lock.json new file mode 100644 index 0000000..e1fa1d1 --- /dev/null +++ b/test/client/src/package-lock.json @@ -0,0 +1,4368 @@ +{ + "name": "veridian", + "version": "0.1.0", + "lockfileVersion": 2, + "requires": true, + "packages": { + "": { + "name": "veridian", + "version": "0.1.0", + "license": "MIT", + "dependencies": { + "vscode-languageclient": "^7.0.0" + }, + "devDependencies": { + "@types/mocha": "^8.2.2", + "@types/node": "^15.12.1", + "@types/vscode": "1.56.0", + "@typescript-eslint/parser": "^4.26.0", + "eslint": "^7.28.0", + "mocha": "^8.4.0", + "typescript": "^4.3.2", + "vscode-test": "^1.5.2" + }, + "engines": { + "vscode": "^1.52.0" + } + }, + "node_modules/@babel/code-frame": { + "version": "7.12.11", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.12.11.tgz", + "integrity": "sha512-Zt1yodBx1UcyiePMSkWnU4hPqhwq7hGi2nFL1LeA3EUl+q2LQx16MISgJ0+z7dnmgvP9QtIleuETGOiOH1RcIw==", + "dev": true, + "dependencies": { + "@babel/highlight": "^7.10.4" + } + }, + "node_modules/@babel/helper-validator-identifier": { + "version": "7.14.0", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.14.0.tgz", + "integrity": "sha512-V3ts7zMSu5lfiwWDVWzRDGIN+lnCEUdaXgtVHJgLb1rGaA6jMrtB9EmE7L18foXJIE8Un/A/h6NJfGQp/e1J4A==", + "dev": true + }, + "node_modules/@babel/highlight": { + "version": "7.14.0", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.14.0.tgz", + "integrity": "sha512-YSCOwxvTYEIMSGaBQb5kDDsCopDdiUGsqpatp3fOlI4+2HQSkTmEVWnVuySdAC5EWCqSWWTv0ib63RjR7dTBdg==", + "dev": true, + "dependencies": { + "@babel/helper-validator-identifier": "^7.14.0", + "chalk": "^2.0.0", + "js-tokens": "^4.0.0" + } + }, + "node_modules/@babel/highlight/node_modules/ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "dependencies": { + "color-convert": "^1.9.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/highlight/node_modules/chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "dependencies": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/highlight/node_modules/color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "dependencies": { + "color-name": "1.1.3" + } + }, + "node_modules/@babel/highlight/node_modules/color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", + "dev": true + }, + "node_modules/@babel/highlight/node_modules/escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", + "dev": true, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/@babel/highlight/node_modules/has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/highlight/node_modules/supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@eslint/eslintrc": { + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-0.4.2.tgz", + "integrity": "sha512-8nmGq/4ycLpIwzvhI4tNDmQztZ8sp+hI7cyG8i1nQDhkAbRzHpXPidRAHlNvCZQpJTKw5ItIpMw9RSToGF00mg==", + "dev": true, + "dependencies": { + "ajv": "^6.12.4", + "debug": "^4.1.1", + "espree": "^7.3.0", + "globals": "^13.9.0", + "ignore": "^4.0.6", + "import-fresh": "^3.2.1", + "js-yaml": "^3.13.1", + "minimatch": "^3.0.4", + "strip-json-comments": "^3.1.1" + }, + "engines": { + "node": "^10.12.0 || >=12.0.0" + } + }, + "node_modules/@nodelib/fs.scandir": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", + "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", + "dev": true, + "dependencies": { + "@nodelib/fs.stat": "2.0.5", + "run-parallel": "^1.1.9" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.stat": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", + "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", + "dev": true, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.walk": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.7.tgz", + "integrity": "sha512-BTIhocbPBSrRmHxOAJFtR18oLhxTtAFDAvL8hY1S3iU8k+E60W/YFs4jrixGzQjMpF4qPXxIQHcjVD9dz1C2QA==", + "dev": true, + "dependencies": { + "@nodelib/fs.scandir": "2.1.5", + "fastq": "^1.6.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@tootallnate/once": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-1.1.2.tgz", + "integrity": "sha512-RbzJvlNzmRq5c3O09UipeuXno4tA1FE6ikOjxZK0tuxVv3412l64l5t1W5pj4+rJq9vpkm/kwiR07aZXnsKPxw==", + "dev": true, + "engines": { + "node": ">= 6" + } + }, + "node_modules/@types/mocha": { + "version": "8.2.2", + "resolved": "https://registry.npmjs.org/@types/mocha/-/mocha-8.2.2.tgz", + "integrity": "sha512-Lwh0lzzqT5Pqh6z61P3c3P5nm6fzQK/MMHl9UKeneAeInVflBSz1O2EkX6gM6xfJd7FBXBY5purtLx7fUiZ7Hw==", + "dev": true + }, + "node_modules/@types/node": { + "version": "15.12.1", + "resolved": "https://registry.npmjs.org/@types/node/-/node-15.12.1.tgz", + "integrity": "sha512-zyxJM8I1c9q5sRMtVF+zdd13Jt6RU4r4qfhTd7lQubyThvLfx6yYekWSQjGCGV2Tkecgxnlpl/DNlb6Hg+dmEw==", + "dev": true + }, + "node_modules/@types/vscode": { + "version": "1.56.0", + "resolved": "https://registry.npmjs.org/@types/vscode/-/vscode-1.56.0.tgz", + "integrity": "sha512-Q5VmQxOx+L1Y6lIJiGcJzwcyV3pQo/eiW8P+7sNLhFI16tJCwtua2DLjHRcpjbCLNVYpQM73kzfFo1Z0HyP9eQ==", + "dev": true + }, + "node_modules/@typescript-eslint/parser": { + "version": "4.26.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-4.26.0.tgz", + "integrity": "sha512-b4jekVJG9FfmjUfmM4VoOItQhPlnt6MPOBUL0AQbiTmm+SSpSdhHYlwayOm4IW9KLI/4/cRKtQCmDl1oE2OlPg==", + "dev": true, + "dependencies": { + "@typescript-eslint/scope-manager": "4.26.0", + "@typescript-eslint/types": "4.26.0", + "@typescript-eslint/typescript-estree": "4.26.0", + "debug": "^4.3.1" + }, + "engines": { + "node": "^10.12.0 || >=12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^5.0.0 || ^6.0.0 || ^7.0.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/scope-manager": { + "version": "4.26.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-4.26.0.tgz", + "integrity": "sha512-G6xB6mMo4xVxwMt5lEsNTz3x4qGDt0NSGmTBNBPJxNsrTXJSm21c6raeYroS2OwQsOyIXqKZv266L/Gln1BWqg==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "4.26.0", + "@typescript-eslint/visitor-keys": "4.26.0" + }, + "engines": { + "node": "^8.10.0 || ^10.13.0 || >=11.10.1" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/types": { + "version": "4.26.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-4.26.0.tgz", + "integrity": "sha512-rADNgXl1kS/EKnDr3G+m7fB9yeJNnR9kF7xMiXL6mSIWpr3Wg5MhxyfEXy/IlYthsqwBqHOr22boFbf/u6O88A==", + "dev": true, + "engines": { + "node": "^8.10.0 || ^10.13.0 || >=11.10.1" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/typescript-estree": { + "version": "4.26.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-4.26.0.tgz", + "integrity": "sha512-GHUgahPcm9GfBuy3TzdsizCcPjKOAauG9xkz9TR8kOdssz2Iz9jRCSQm6+aVFa23d5NcSpo1GdHGSQKe0tlcbg==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "4.26.0", + "@typescript-eslint/visitor-keys": "4.26.0", + "debug": "^4.3.1", + "globby": "^11.0.3", + "is-glob": "^4.0.1", + "semver": "^7.3.5", + "tsutils": "^3.21.0" + }, + "engines": { + "node": "^10.12.0 || >=12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/visitor-keys": { + "version": "4.26.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-4.26.0.tgz", + "integrity": "sha512-cw4j8lH38V1ycGBbF+aFiLUls9Z0Bw8QschP3mkth50BbWzgFS33ISIgBzUMuQ2IdahoEv/rXstr8Zhlz4B1Zg==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "4.26.0", + "eslint-visitor-keys": "^2.0.0" + }, + "engines": { + "node": "^8.10.0 || ^10.13.0 || >=11.10.1" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@ungap/promise-all-settled": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@ungap/promise-all-settled/-/promise-all-settled-1.1.2.tgz", + "integrity": "sha512-sL/cEvJWAnClXw0wHk85/2L0G6Sj8UB0Ctc1TEMbKSsmpRosqhwj9gWgFRZSrBr2f9tiXISwNhCPmlfqUqyb9Q==", + "dev": true + }, + "node_modules/acorn": { + "version": "7.4.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz", + "integrity": "sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==", + "dev": true, + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/acorn-jsx": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.1.tgz", + "integrity": "sha512-K0Ptm/47OKfQRpNQ2J/oIN/3QYiK6FwW+eJbILhsdxh2WTLdl+30o8aGdTbm5JbffpFFAg/g+zi1E+jvJha5ng==", + "dev": true, + "peerDependencies": { + "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" + } + }, + "node_modules/agent-base": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", + "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", + "dev": true, + "dependencies": { + "debug": "4" + }, + "engines": { + "node": ">= 6.0.0" + } + }, + "node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/ansi-colors": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.1.tgz", + "integrity": "sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/ansi-regex": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", + "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/anymatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.2.tgz", + "integrity": "sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==", + "dev": true, + "dependencies": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "dev": true, + "dependencies": { + "sprintf-js": "~1.0.2" + } + }, + "node_modules/array-union": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", + "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/astral-regex": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-2.0.0.tgz", + "integrity": "sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" + }, + "node_modules/big-integer": { + "version": "1.6.48", + "resolved": "https://registry.npmjs.org/big-integer/-/big-integer-1.6.48.tgz", + "integrity": "sha512-j51egjPa7/i+RdiRuJbPdJ2FIUYYPhvYLjzoYbcMMm62ooO6F94fETG4MTs46zPAF9Brs04OajboA/qTGuz78w==", + "dev": true, + "engines": { + "node": ">=0.6" + } + }, + "node_modules/binary": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/binary/-/binary-0.3.0.tgz", + "integrity": "sha1-n2BVO8XOjDOG87VTz/R0Yq3sqnk=", + "dev": true, + "dependencies": { + "buffers": "~0.1.1", + "chainsaw": "~0.1.0" + } + }, + "node_modules/binary-extensions": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", + "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/bluebird": { + "version": "3.4.7", + "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.4.7.tgz", + "integrity": "sha1-9y12C+Cbf3bQjtj66Ysomo0F+rM=", + "dev": true + }, + "node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/braces": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", + "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "dev": true, + "dependencies": { + "fill-range": "^7.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/browser-stdout": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.1.tgz", + "integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==", + "dev": true + }, + "node_modules/buffer-indexof-polyfill": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/buffer-indexof-polyfill/-/buffer-indexof-polyfill-1.0.2.tgz", + "integrity": "sha512-I7wzHwA3t1/lwXQh+A5PbNvJxgfo5r3xulgpYDB5zckTu/Z9oUK9biouBKQUjEqzaz3HnAT6TYoovmE+GqSf7A==", + "dev": true, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/buffers": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/buffers/-/buffers-0.1.1.tgz", + "integrity": "sha1-skV5w77U1tOWru5tmorn9Ugqt7s=", + "dev": true, + "engines": { + "node": ">=0.2.0" + } + }, + "node_modules/callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/camelcase": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.2.0.tgz", + "integrity": "sha512-c7wVvbw3f37nuobQNtgsgG9POC9qMbNuMQmTCqZv23b6MIz0fcYpBiOlv9gEN/hdLdnZTDQhg6e9Dq5M1vKvfg==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/chainsaw": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/chainsaw/-/chainsaw-0.1.0.tgz", + "integrity": "sha1-XqtQsor+WAdNDVgpE4iCi15fvJg=", + "dev": true, + "dependencies": { + "traverse": ">=0.3.0 <0.4" + } + }, + "node_modules/chalk": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.1.tgz", + "integrity": "sha512-diHzdDKxcU+bAsUboHLPEDQiw0qEe0qd7SYUn3HgcFlWgbDcfLGswOHYeGrHKzG9z6UYf01d9VFMfZxPM1xZSg==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/chokidar": { + "version": "3.5.1", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.1.tgz", + "integrity": "sha512-9+s+Od+W0VJJzawDma/gvBNQqkTiqYTWLuZoyAsivsI4AaWTCzHG06/TMjsf1cYe9Cb97UCEhjz7HvnPk2p/tw==", + "dev": true, + "dependencies": { + "anymatch": "~3.1.1", + "braces": "~3.0.2", + "glob-parent": "~5.1.0", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.5.0" + }, + "engines": { + "node": ">= 8.10.0" + }, + "optionalDependencies": { + "fsevents": "~2.3.1" + } + }, + "node_modules/cliui": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", + "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", + "dev": true, + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0", + "wrap-ansi": "^7.0.0" + } + }, + "node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" + }, + "node_modules/core-util-is": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=", + "dev": true + }, + "node_modules/cross-spawn": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", + "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "dev": true, + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/debug": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz", + "integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==", + "dev": true, + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/decamelize": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-4.0.0.tgz", + "integrity": "sha512-9iE1PgSik9HeIIw2JO94IidnE3eBoQrFJ3w7sFuzSX4DpmZ3v5sZpUiV5Swcf6mQEF+Y0ru8Neo+p+nyh2J+hQ==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/deep-is": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz", + "integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=", + "dev": true + }, + "node_modules/diff": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/diff/-/diff-5.0.0.tgz", + "integrity": "sha512-/VTCrvm5Z0JGty/BWHljh+BAiw3IK+2j87NGMu8Nwc/f48WoDAC395uomO9ZD117ZOBaHmkX1oyLvkVM/aIT3w==", + "dev": true, + "engines": { + "node": ">=0.3.1" + } + }, + "node_modules/dir-glob": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", + "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", + "dev": true, + "dependencies": { + "path-type": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/doctrine": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", + "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", + "dev": true, + "dependencies": { + "esutils": "^2.0.2" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/duplexer2": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/duplexer2/-/duplexer2-0.1.4.tgz", + "integrity": "sha1-ixLauHjA1p4+eJEFFmKjL8a93ME=", + "dev": true, + "dependencies": { + "readable-stream": "^2.0.2" + } + }, + "node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true + }, + "node_modules/enquirer": { + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/enquirer/-/enquirer-2.3.6.tgz", + "integrity": "sha512-yjNnPr315/FjS4zIsUxYguYUPP2e1NK4d7E7ZOLiyYCcbFBiTMyID+2wvm2w6+pZ/odMA7cRkjhsPbltwBOrLg==", + "dev": true, + "dependencies": { + "ansi-colors": "^4.1.1" + }, + "engines": { + "node": ">=8.6" + } + }, + "node_modules/escalade": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", + "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint": { + "version": "7.28.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-7.28.0.tgz", + "integrity": "sha512-UMfH0VSjP0G4p3EWirscJEQ/cHqnT/iuH6oNZOB94nBjWbMnhGEPxsZm1eyIW0C/9jLI0Fow4W5DXLjEI7mn1g==", + "dev": true, + "dependencies": { + "@babel/code-frame": "7.12.11", + "@eslint/eslintrc": "^0.4.2", + "ajv": "^6.10.0", + "chalk": "^4.0.0", + "cross-spawn": "^7.0.2", + "debug": "^4.0.1", + "doctrine": "^3.0.0", + "enquirer": "^2.3.5", + "escape-string-regexp": "^4.0.0", + "eslint-scope": "^5.1.1", + "eslint-utils": "^2.1.0", + "eslint-visitor-keys": "^2.0.0", + "espree": "^7.3.1", + "esquery": "^1.4.0", + "esutils": "^2.0.2", + "fast-deep-equal": "^3.1.3", + "file-entry-cache": "^6.0.1", + "functional-red-black-tree": "^1.0.1", + "glob-parent": "^5.1.2", + "globals": "^13.6.0", + "ignore": "^4.0.6", + "import-fresh": "^3.0.0", + "imurmurhash": "^0.1.4", + "is-glob": "^4.0.0", + "js-yaml": "^3.13.1", + "json-stable-stringify-without-jsonify": "^1.0.1", + "levn": "^0.4.1", + "lodash.merge": "^4.6.2", + "minimatch": "^3.0.4", + "natural-compare": "^1.4.0", + "optionator": "^0.9.1", + "progress": "^2.0.0", + "regexpp": "^3.1.0", + "semver": "^7.2.1", + "strip-ansi": "^6.0.0", + "strip-json-comments": "^3.1.0", + "table": "^6.0.9", + "text-table": "^0.2.0", + "v8-compile-cache": "^2.0.3" + }, + "bin": { + "eslint": "bin/eslint.js" + }, + "engines": { + "node": "^10.12.0 || >=12.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint-scope": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", + "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", + "dev": true, + "dependencies": { + "esrecurse": "^4.3.0", + "estraverse": "^4.1.1" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/eslint-utils": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-2.1.0.tgz", + "integrity": "sha512-w94dQYoauyvlDc43XnGB8lU3Zt713vNChgt4EWwhXAP2XkBvndfxF0AgIqKOOasjPIPzj9JqgwkwbCYD0/V3Zg==", + "dev": true, + "dependencies": { + "eslint-visitor-keys": "^1.1.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/mysticatea" + } + }, + "node_modules/eslint-utils/node_modules/eslint-visitor-keys": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz", + "integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/eslint-visitor-keys": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz", + "integrity": "sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==", + "dev": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/espree": { + "version": "7.3.1", + "resolved": "https://registry.npmjs.org/espree/-/espree-7.3.1.tgz", + "integrity": "sha512-v3JCNCE64umkFpmkFGqzVKsOT0tN1Zr+ueqLZfpV1Ob8e+CEgPWa+OxCoGH3tnhimMKIaBm4m/vaRpJ/krRz2g==", + "dev": true, + "dependencies": { + "acorn": "^7.4.0", + "acorn-jsx": "^5.3.1", + "eslint-visitor-keys": "^1.3.0" + }, + "engines": { + "node": "^10.12.0 || >=12.0.0" + } + }, + "node_modules/espree/node_modules/eslint-visitor-keys": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz", + "integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/esprima": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", + "dev": true, + "bin": { + "esparse": "bin/esparse.js", + "esvalidate": "bin/esvalidate.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/esquery": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.4.0.tgz", + "integrity": "sha512-cCDispWt5vHHtwMY2YrAQ4ibFkAL8RbH5YGBnZBc90MolvvfkkQcJro/aZiAQUlQ3qgrYS6D6v8Gc5G5CQsc9w==", + "dev": true, + "dependencies": { + "estraverse": "^5.1.0" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/esquery/node_modules/estraverse": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.2.0.tgz", + "integrity": "sha512-BxbNGGNm0RyRYvUdHpIwv9IWzeM9XClbOxwoATuFdOE7ZE6wHL+HQ5T8hoPM+zHvmKzzsEqhgy0GrQ5X13afiQ==", + "dev": true, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/esrecurse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", + "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", + "dev": true, + "dependencies": { + "estraverse": "^5.2.0" + }, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/esrecurse/node_modules/estraverse": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.2.0.tgz", + "integrity": "sha512-BxbNGGNm0RyRYvUdHpIwv9IWzeM9XClbOxwoATuFdOE7ZE6wHL+HQ5T8hoPM+zHvmKzzsEqhgy0GrQ5X13afiQ==", + "dev": true, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/estraverse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", + "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", + "dev": true, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "dev": true + }, + "node_modules/fast-glob": { + "version": "3.2.5", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.5.tgz", + "integrity": "sha512-2DtFcgT68wiTTiwZ2hNdJfcHNke9XOfnwmBRWXhmeKM8rF0TGwmC/Qto3S7RoZKp5cilZbxzO5iTNTQsJ+EeDg==", + "dev": true, + "dependencies": { + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.0", + "merge2": "^1.3.0", + "micromatch": "^4.0.2", + "picomatch": "^2.2.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", + "dev": true + }, + "node_modules/fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=", + "dev": true + }, + "node_modules/fastq": { + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.11.0.tgz", + "integrity": "sha512-7Eczs8gIPDrVzT+EksYBcupqMyxSHXXrHOLRRxU2/DicV8789MRBRR8+Hc2uWzUupOs4YS4JzBmBxjjCVBxD/g==", + "dev": true, + "dependencies": { + "reusify": "^1.0.4" + } + }, + "node_modules/file-entry-cache": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", + "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", + "dev": true, + "dependencies": { + "flat-cache": "^3.0.4" + }, + "engines": { + "node": "^10.12.0 || >=12.0.0" + } + }, + "node_modules/fill-range": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", + "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "dev": true, + "dependencies": { + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/find-up": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "dev": true, + "dependencies": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/flat": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/flat/-/flat-5.0.2.tgz", + "integrity": "sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==", + "dev": true, + "bin": { + "flat": "cli.js" + } + }, + "node_modules/flat-cache": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.0.4.tgz", + "integrity": "sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg==", + "dev": true, + "dependencies": { + "flatted": "^3.1.0", + "rimraf": "^3.0.2" + }, + "engines": { + "node": "^10.12.0 || >=12.0.0" + } + }, + "node_modules/flatted": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.1.1.tgz", + "integrity": "sha512-zAoAQiudy+r5SvnSw3KJy5os/oRJYHzrzja/tBDqrZtNhUw8bt6y8OBzMWcjWr+8liV8Eb6yOhw8WZ7VFZ5ZzA==", + "dev": true + }, + "node_modules/fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", + "dev": true + }, + "node_modules/fsevents": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", + "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", + "dev": true, + "hasInstallScript": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/fstream": { + "version": "1.0.12", + "resolved": "https://registry.npmjs.org/fstream/-/fstream-1.0.12.tgz", + "integrity": "sha512-WvJ193OHa0GHPEL+AycEJgxvBEwyfRkN1vhjca23OaPVMCaLCXTd5qAu82AjTcgP1UJmytkOKb63Ypde7raDIg==", + "dev": true, + "dependencies": { + "graceful-fs": "^4.1.2", + "inherits": "~2.0.0", + "mkdirp": ">=0.5 0", + "rimraf": "2" + }, + "engines": { + "node": ">=0.6" + } + }, + "node_modules/fstream/node_modules/rimraf": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", + "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", + "dev": true, + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + } + }, + "node_modules/functional-red-black-tree": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz", + "integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=", + "dev": true + }, + "node_modules/get-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "dev": true, + "engines": { + "node": "6.* || 8.* || >= 10.*" + } + }, + "node_modules/glob": { + "version": "7.1.6", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", + "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", + "dev": true, + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/globals": { + "version": "13.9.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.9.0.tgz", + "integrity": "sha512-74/FduwI/JaIrr1H8e71UbDE+5x7pIPs1C2rrwC52SszOo043CsWOZEMW7o2Y58xwm9b+0RBKDxY5n2sUpEFxA==", + "dev": true, + "dependencies": { + "type-fest": "^0.20.2" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/globby": { + "version": "11.0.3", + "resolved": "https://registry.npmjs.org/globby/-/globby-11.0.3.tgz", + "integrity": "sha512-ffdmosjA807y7+lA1NM0jELARVmYul/715xiILEjo3hBLPTcirgQNnXECn5g3mtR8TOLCVbkfua1Hpen25/Xcg==", + "dev": true, + "dependencies": { + "array-union": "^2.1.0", + "dir-glob": "^3.0.1", + "fast-glob": "^3.1.1", + "ignore": "^5.1.4", + "merge2": "^1.3.0", + "slash": "^3.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/globby/node_modules/ignore": { + "version": "5.1.8", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.1.8.tgz", + "integrity": "sha512-BMpfD7PpiETpBl/A6S498BaIJ6Y/ABT93ETbby2fP00v4EbvPBXWEoaR1UBPKs3iR53pJY7EtZk5KACI57i1Uw==", + "dev": true, + "engines": { + "node": ">= 4" + } + }, + "node_modules/graceful-fs": { + "version": "4.2.6", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.6.tgz", + "integrity": "sha512-nTnJ528pbqxYanhpDYsi4Rd8MAeaBA67+RZ10CM1m3bTAVFEDcd5AuA4a6W5YkGZ1iNXHzZz8T6TBKLeBuNriQ==", + "dev": true + }, + "node_modules/growl": { + "version": "1.10.5", + "resolved": "https://registry.npmjs.org/growl/-/growl-1.10.5.tgz", + "integrity": "sha512-qBr4OuELkhPenW6goKVXiv47US3clb3/IbuWF9KNKEijAy9oeHxU9IgzjvJhHkUzhaj7rOUD7+YGWqUjLp5oSA==", + "dev": true, + "engines": { + "node": ">=4.x" + } + }, + "node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/he": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", + "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", + "dev": true, + "bin": { + "he": "bin/he" + } + }, + "node_modules/http-proxy-agent": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-4.0.1.tgz", + "integrity": "sha512-k0zdNgqWTGA6aeIRVpvfVob4fL52dTfaehylg0Y4UvSySvOq/Y+BOyPrgpUrA7HylqvU8vIZGsRuXmspskV0Tg==", + "dev": true, + "dependencies": { + "@tootallnate/once": "1", + "agent-base": "6", + "debug": "4" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/https-proxy-agent": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.0.tgz", + "integrity": "sha512-EkYm5BcKUGiduxzSt3Eppko+PiNWNEpa4ySk9vTC6wDsQJW9rHSa+UhGNJoRYp7bz6Ht1eaRIa6QaJqO5rCFbA==", + "dev": true, + "dependencies": { + "agent-base": "6", + "debug": "4" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/ignore": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz", + "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==", + "dev": true, + "engines": { + "node": ">= 4" + } + }, + "node_modules/import-fresh": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", + "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", + "dev": true, + "dependencies": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=", + "dev": true, + "engines": { + "node": ">=0.8.19" + } + }, + "node_modules/inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", + "dev": true, + "dependencies": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "dev": true + }, + "node_modules/is-binary-path": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", + "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "dev": true, + "dependencies": { + "binary-extensions": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-glob": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz", + "integrity": "sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg==", + "dev": true, + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true, + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/is-plain-obj": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-2.1.0.tgz", + "integrity": "sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + }, + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", + "dev": true + }, + "node_modules/js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "dev": true + }, + "node_modules/js-yaml": { + "version": "3.14.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", + "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", + "dev": true, + "dependencies": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true + }, + "node_modules/json-stable-stringify-without-jsonify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", + "integrity": "sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=", + "dev": true + }, + "node_modules/levn": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", + "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", + "dev": true, + "dependencies": { + "prelude-ls": "^1.2.1", + "type-check": "~0.4.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/listenercount": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/listenercount/-/listenercount-1.0.1.tgz", + "integrity": "sha1-hMinKrWcRyUyFIDJdeZQg0LnCTc=", + "dev": true + }, + "node_modules/locate-path": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "dev": true, + "dependencies": { + "p-locate": "^5.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/lodash.clonedeep": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz", + "integrity": "sha1-4j8/nE+Pvd6HJSnBBxhXoIblzO8=", + "dev": true + }, + "node_modules/lodash.merge": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", + "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", + "dev": true + }, + "node_modules/lodash.truncate": { + "version": "4.4.2", + "resolved": "https://registry.npmjs.org/lodash.truncate/-/lodash.truncate-4.4.2.tgz", + "integrity": "sha1-WjUNoLERO4N+z//VgSy+WNbq4ZM=", + "dev": true + }, + "node_modules/log-symbols": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.0.0.tgz", + "integrity": "sha512-FN8JBzLx6CzeMrB0tg6pqlGU1wCrXW+ZXGH481kfsBqer0hToTIiHdjH4Mq8xJUbvATujKCvaREGWpGUionraA==", + "dev": true, + "dependencies": { + "chalk": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/merge2": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", + "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", + "dev": true, + "engines": { + "node": ">= 8" + } + }, + "node_modules/micromatch": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.4.tgz", + "integrity": "sha512-pRmzw/XUcwXGpD9aI9q/0XOwLNygjETJ8y0ao0wdqprrzDa4YnxLcz7fQRZr8voh8V10kGhABbNcHVk5wHgWwg==", + "dev": true, + "dependencies": { + "braces": "^3.0.1", + "picomatch": "^2.2.3" + }, + "engines": { + "node": ">=8.6" + } + }, + "node_modules/minimatch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/minimist": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", + "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==", + "dev": true + }, + "node_modules/mkdirp": { + "version": "0.5.5", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", + "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==", + "dev": true, + "dependencies": { + "minimist": "^1.2.5" + }, + "bin": { + "mkdirp": "bin/cmd.js" + } + }, + "node_modules/mocha": { + "version": "8.4.0", + "resolved": "https://registry.npmjs.org/mocha/-/mocha-8.4.0.tgz", + "integrity": "sha512-hJaO0mwDXmZS4ghXsvPVriOhsxQ7ofcpQdm8dE+jISUOKopitvnXFQmpRR7jd2K6VBG6E26gU3IAbXXGIbu4sQ==", + "dev": true, + "dependencies": { + "@ungap/promise-all-settled": "1.1.2", + "ansi-colors": "4.1.1", + "browser-stdout": "1.3.1", + "chokidar": "3.5.1", + "debug": "4.3.1", + "diff": "5.0.0", + "escape-string-regexp": "4.0.0", + "find-up": "5.0.0", + "glob": "7.1.6", + "growl": "1.10.5", + "he": "1.2.0", + "js-yaml": "4.0.0", + "log-symbols": "4.0.0", + "minimatch": "3.0.4", + "ms": "2.1.3", + "nanoid": "3.1.20", + "serialize-javascript": "5.0.1", + "strip-json-comments": "3.1.1", + "supports-color": "8.1.1", + "which": "2.0.2", + "wide-align": "1.1.3", + "workerpool": "6.1.0", + "yargs": "16.2.0", + "yargs-parser": "20.2.4", + "yargs-unparser": "2.0.0" + }, + "bin": { + "_mocha": "bin/_mocha", + "mocha": "bin/mocha" + }, + "engines": { + "node": ">= 10.12.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/mochajs" + } + }, + "node_modules/mocha/node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "dev": true + }, + "node_modules/mocha/node_modules/js-yaml": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.0.0.tgz", + "integrity": "sha512-pqon0s+4ScYUvX30wxQi3PogGFAlUyH0awepWvwkj4jD4v+ova3RiYw8bmA6x2rDrEaj8i/oWKoRxpVNW+Re8Q==", + "dev": true, + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/mocha/node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true + }, + "node_modules/mocha/node_modules/supports-color": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/supports-color?sponsor=1" + } + }, + "node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "node_modules/nanoid": { + "version": "3.1.20", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.1.20.tgz", + "integrity": "sha512-a1cQNyczgKbLX9jwbS/+d7W8fX/RfgYR7lVWwWOGIPNgK2m0MWvrGF6/m4kk6U3QcFMnZf3RIhL0v2Jgh/0Uxw==", + "dev": true, + "bin": { + "nanoid": "bin/nanoid.cjs" + }, + "engines": { + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" + } + }, + "node_modules/natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=", + "dev": true + }, + "node_modules/normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "dev": true, + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/optionator": { + "version": "0.9.1", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.1.tgz", + "integrity": "sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw==", + "dev": true, + "dependencies": { + "deep-is": "^0.1.3", + "fast-levenshtein": "^2.0.6", + "levn": "^0.4.1", + "prelude-ls": "^1.2.1", + "type-check": "^0.4.0", + "word-wrap": "^1.2.3" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "dev": true, + "dependencies": { + "yocto-queue": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-locate": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "dev": true, + "dependencies": { + "p-limit": "^3.0.2" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/parent-module": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", + "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", + "dev": true, + "dependencies": { + "callsites": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/path-type": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", + "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/picomatch": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.0.tgz", + "integrity": "sha512-lY1Q/PiJGC2zOv/z391WOTD+Z02bCgsFfvxoXXf6h7kv9o+WmsmzYqrAwY63sNgOxE4xEdq0WyUnXfKeBrSvYw==", + "dev": true, + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/prelude-ls": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", + "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", + "dev": true, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/process-nextick-args": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", + "dev": true + }, + "node_modules/progress": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz", + "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==", + "dev": true, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/punycode": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", + "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/queue-microtask": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", + "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/randombytes": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", + "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", + "dev": true, + "dependencies": { + "safe-buffer": "^5.1.0" + } + }, + "node_modules/readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "dev": true, + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/readable-stream/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + }, + "node_modules/readdirp": { + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.5.0.tgz", + "integrity": "sha512-cMhu7c/8rdhkHXWsY+osBhfSy0JikwpHK/5+imo+LpeasTF8ouErHrlYkwT0++njiyuDvc7OFY5T3ukvZ8qmFQ==", + "dev": true, + "dependencies": { + "picomatch": "^2.2.1" + }, + "engines": { + "node": ">=8.10.0" + } + }, + "node_modules/regexpp": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-3.1.0.tgz", + "integrity": "sha512-ZOIzd8yVsQQA7j8GCSlPGXwg5PfmA1mrq0JP4nGhh54LaKN3xdai/vHUDu74pKwV8OxseMS65u2NImosQcSD0Q==", + "dev": true, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/mysticatea" + } + }, + "node_modules/require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/require-from-string": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", + "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/reusify": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", + "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", + "dev": true, + "engines": { + "iojs": ">=1.0.0", + "node": ">=0.10.0" + } + }, + "node_modules/rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "dev": true, + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/run-parallel": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", + "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "dependencies": { + "queue-microtask": "^1.2.2" + } + }, + "node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/semver": { + "version": "7.3.5", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", + "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/serialize-javascript": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-5.0.1.tgz", + "integrity": "sha512-SaaNal9imEO737H2c05Og0/8LUXG7EnsZyMa8MzkmuHoELfT6txuj0cMqRj6zfPKnmQ1yasR4PCJc8x+M4JSPA==", + "dev": true, + "dependencies": { + "randombytes": "^2.1.0" + } + }, + "node_modules/setimmediate": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz", + "integrity": "sha1-KQy7Iy4waULX1+qbg3Mqt4VvgoU=", + "dev": true + }, + "node_modules/shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dev": true, + "dependencies": { + "shebang-regex": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/slash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", + "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/slice-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-4.0.0.tgz", + "integrity": "sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.0.0", + "astral-regex": "^2.0.0", + "is-fullwidth-code-point": "^3.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/slice-ansi?sponsor=1" + } + }, + "node_modules/sprintf-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", + "dev": true + }, + "node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, + "node_modules/string_decoder/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + }, + "node_modules/string-width": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.2.tgz", + "integrity": "sha512-XBJbT3N4JhVumXE0eoLU9DCjcaF92KLNqTmFCnG1pf8duUxFGwtP6AD6nkjw9a3IdiRtL3E2w3JDiE/xi3vOeA==", + "dev": true, + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-ansi": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", + "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==", + "dev": true, + "dependencies": { + "ansi-regex": "^5.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-json-comments": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "dev": true, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/table": { + "version": "6.7.1", + "resolved": "https://registry.npmjs.org/table/-/table-6.7.1.tgz", + "integrity": "sha512-ZGum47Yi6KOOFDE8m223td53ath2enHcYLgOCjGr5ngu8bdIARQk6mN/wRMv4yMRcHnCSnHbCEha4sobQx5yWg==", + "dev": true, + "dependencies": { + "ajv": "^8.0.1", + "lodash.clonedeep": "^4.5.0", + "lodash.truncate": "^4.4.2", + "slice-ansi": "^4.0.0", + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/table/node_modules/ajv": { + "version": "8.5.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.5.0.tgz", + "integrity": "sha512-Y2l399Tt1AguU3BPRP9Fn4eN+Or+StUGWCUpbnFyXSo8NZ9S4uj+AG2pjs5apK+ZMOwYOz1+a+VKvKH7CudXgQ==", + "dev": true, + "dependencies": { + "fast-deep-equal": "^3.1.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/table/node_modules/json-schema-traverse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", + "dev": true + }, + "node_modules/text-table": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", + "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=", + "dev": true + }, + "node_modules/to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dev": true, + "dependencies": { + "is-number": "^7.0.0" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/traverse": { + "version": "0.3.9", + "resolved": "https://registry.npmjs.org/traverse/-/traverse-0.3.9.tgz", + "integrity": "sha1-cXuPIgzAu3tE5AUUwisui7xw2Lk=", + "dev": true + }, + "node_modules/tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", + "dev": true + }, + "node_modules/tsutils": { + "version": "3.21.0", + "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.21.0.tgz", + "integrity": "sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==", + "dev": true, + "dependencies": { + "tslib": "^1.8.1" + }, + "engines": { + "node": ">= 6" + }, + "peerDependencies": { + "typescript": ">=2.8.0 || >= 3.2.0-dev || >= 3.3.0-dev || >= 3.4.0-dev || >= 3.5.0-dev || >= 3.6.0-dev || >= 3.6.0-beta || >= 3.7.0-dev || >= 3.7.0-beta" + } + }, + "node_modules/type-check": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", + "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", + "dev": true, + "dependencies": { + "prelude-ls": "^1.2.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/type-fest": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", + "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/typescript": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.3.2.tgz", + "integrity": "sha512-zZ4hShnmnoVnAHpVHWpTcxdv7dWP60S2FsydQLV8V5PbS3FifjWFFRiHSWpDJahly88PRyV5teTSLoq4eG7mKw==", + "dev": true, + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=4.2.0" + } + }, + "node_modules/unzipper": { + "version": "0.10.11", + "resolved": "https://registry.npmjs.org/unzipper/-/unzipper-0.10.11.tgz", + "integrity": "sha512-+BrAq2oFqWod5IESRjL3S8baohbevGcVA+teAIOYWM3pDVdseogqbzhhvvmiyQrUNKFUnDMtELW3X8ykbyDCJw==", + "dev": true, + "dependencies": { + "big-integer": "^1.6.17", + "binary": "~0.3.0", + "bluebird": "~3.4.1", + "buffer-indexof-polyfill": "~1.0.0", + "duplexer2": "~0.1.4", + "fstream": "^1.0.12", + "graceful-fs": "^4.2.2", + "listenercount": "~1.0.1", + "readable-stream": "~2.3.6", + "setimmediate": "~1.0.4" + } + }, + "node_modules/uri-js": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "dev": true, + "dependencies": { + "punycode": "^2.1.0" + } + }, + "node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", + "dev": true + }, + "node_modules/v8-compile-cache": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.3.0.tgz", + "integrity": "sha512-l8lCEmLcLYZh4nbunNZvQCJc5pv7+RCwa8q/LdUx8u7lsWvPDKmpodJAJNwkAhJC//dFY48KuIEmjtd4RViDrA==", + "dev": true + }, + "node_modules/vscode-jsonrpc": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/vscode-jsonrpc/-/vscode-jsonrpc-6.0.0.tgz", + "integrity": "sha512-wnJA4BnEjOSyFMvjZdpiOwhSq9uDoK8e/kpRJDTaMYzwlkrhG1fwDIZI94CLsLzlCK5cIbMMtFlJlfR57Lavmg==", + "engines": { + "node": ">=8.0.0 || >=10.0.0" + } + }, + "node_modules/vscode-languageclient": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/vscode-languageclient/-/vscode-languageclient-7.0.0.tgz", + "integrity": "sha512-P9AXdAPlsCgslpP9pRxYPqkNYV7Xq8300/aZDpO35j1fJm/ncize8iGswzYlcvFw5DQUx4eVk+KvfXdL0rehNg==", + "dependencies": { + "minimatch": "^3.0.4", + "semver": "^7.3.4", + "vscode-languageserver-protocol": "3.16.0" + }, + "engines": { + "vscode": "^1.52.0" + } + }, + "node_modules/vscode-languageserver-protocol": { + "version": "3.16.0", + "resolved": "https://registry.npmjs.org/vscode-languageserver-protocol/-/vscode-languageserver-protocol-3.16.0.tgz", + "integrity": "sha512-sdeUoAawceQdgIfTI+sdcwkiK2KU+2cbEYA0agzM2uqaUy2UpnnGHtWTHVEtS0ES4zHU0eMFRGN+oQgDxlD66A==", + "dependencies": { + "vscode-jsonrpc": "6.0.0", + "vscode-languageserver-types": "3.16.0" + } + }, + "node_modules/vscode-languageserver-types": { + "version": "3.16.0", + "resolved": "https://registry.npmjs.org/vscode-languageserver-types/-/vscode-languageserver-types-3.16.0.tgz", + "integrity": "sha512-k8luDIWJWyenLc5ToFQQMaSrqCHiLwyKPHKPQZ5zz21vM+vIVUSvsRpcbiECH4WR88K2XZqc4ScRcZ7nk/jbeA==" + }, + "node_modules/vscode-test": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/vscode-test/-/vscode-test-1.5.2.tgz", + "integrity": "sha512-x9PVfKxF6EInH9iSFGQi0V8H5zIW1fC7RAer6yNQR6sy3WyOwlWkuT3I+wf75xW/cO53hxMi1aj/EvqQfDFOAg==", + "dev": true, + "dependencies": { + "http-proxy-agent": "^4.0.1", + "https-proxy-agent": "^5.0.0", + "rimraf": "^3.0.2", + "unzipper": "^0.10.11" + }, + "engines": { + "node": ">=8.9.3" + } + }, + "node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/wide-align": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.3.tgz", + "integrity": "sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA==", + "dev": true, + "dependencies": { + "string-width": "^1.0.2 || 2" + } + }, + "node_modules/wide-align/node_modules/ansi-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/wide-align/node_modules/is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/wide-align/node_modules/string-width": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", + "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", + "dev": true, + "dependencies": { + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^4.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/wide-align/node_modules/strip-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", + "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "dev": true, + "dependencies": { + "ansi-regex": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/word-wrap": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz", + "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/workerpool": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/workerpool/-/workerpool-6.1.0.tgz", + "integrity": "sha512-toV7q9rWNYha963Pl/qyeZ6wG+3nnsyvolaNUS8+R5Wtw6qJPTxIlOP1ZSvcGhEJw+l3HMMmtiNo9Gl61G4GVg==", + "dev": true + }, + "node_modules/wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", + "dev": true + }, + "node_modules/y18n": { + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", + "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", + "dev": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + }, + "node_modules/yargs": { + "version": "16.2.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", + "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", + "dev": true, + "dependencies": { + "cliui": "^7.0.2", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.0", + "y18n": "^5.0.5", + "yargs-parser": "^20.2.2" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/yargs-parser": { + "version": "20.2.4", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.4.tgz", + "integrity": "sha512-WOkpgNhPTlE73h4VFAFsOnomJVaovO8VqLDzy5saChRBFQFBoMYirowyW+Q9HB4HFF4Z7VZTiG3iSzJJA29yRA==", + "dev": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/yargs-unparser": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/yargs-unparser/-/yargs-unparser-2.0.0.tgz", + "integrity": "sha512-7pRTIA9Qc1caZ0bZ6RYRGbHJthJWuakf+WmHK0rVeLkNrrGhfoabBNdue6kdINI6r4if7ocq9aD/n7xwKOdzOA==", + "dev": true, + "dependencies": { + "camelcase": "^6.0.0", + "decamelize": "^4.0.0", + "flat": "^5.0.2", + "is-plain-obj": "^2.1.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/yocto-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", + "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + } + }, + "dependencies": { + "@babel/code-frame": { + "version": "7.12.11", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.12.11.tgz", + "integrity": "sha512-Zt1yodBx1UcyiePMSkWnU4hPqhwq7hGi2nFL1LeA3EUl+q2LQx16MISgJ0+z7dnmgvP9QtIleuETGOiOH1RcIw==", + "dev": true, + "requires": { + "@babel/highlight": "^7.10.4" + } + }, + "@babel/helper-validator-identifier": { + "version": "7.14.0", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.14.0.tgz", + "integrity": "sha512-V3ts7zMSu5lfiwWDVWzRDGIN+lnCEUdaXgtVHJgLb1rGaA6jMrtB9EmE7L18foXJIE8Un/A/h6NJfGQp/e1J4A==", + "dev": true + }, + "@babel/highlight": { + "version": "7.14.0", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.14.0.tgz", + "integrity": "sha512-YSCOwxvTYEIMSGaBQb5kDDsCopDdiUGsqpatp3fOlI4+2HQSkTmEVWnVuySdAC5EWCqSWWTv0ib63RjR7dTBdg==", + "dev": true, + "requires": { + "@babel/helper-validator-identifier": "^7.14.0", + "chalk": "^2.0.0", + "js-tokens": "^4.0.0" + }, + "dependencies": { + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "^1.9.0" + } + }, + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "requires": { + "color-name": "1.1.3" + } + }, + "color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", + "dev": true + }, + "escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", + "dev": true + }, + "has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", + "dev": true + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + } + } + }, + "@eslint/eslintrc": { + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-0.4.2.tgz", + "integrity": "sha512-8nmGq/4ycLpIwzvhI4tNDmQztZ8sp+hI7cyG8i1nQDhkAbRzHpXPidRAHlNvCZQpJTKw5ItIpMw9RSToGF00mg==", + "dev": true, + "requires": { + "ajv": "^6.12.4", + "debug": "^4.1.1", + "espree": "^7.3.0", + "globals": "^13.9.0", + "ignore": "^4.0.6", + "import-fresh": "^3.2.1", + "js-yaml": "^3.13.1", + "minimatch": "^3.0.4", + "strip-json-comments": "^3.1.1" + } + }, + "@nodelib/fs.scandir": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", + "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", + "dev": true, + "requires": { + "@nodelib/fs.stat": "2.0.5", + "run-parallel": "^1.1.9" + } + }, + "@nodelib/fs.stat": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", + "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", + "dev": true + }, + "@nodelib/fs.walk": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.7.tgz", + "integrity": "sha512-BTIhocbPBSrRmHxOAJFtR18oLhxTtAFDAvL8hY1S3iU8k+E60W/YFs4jrixGzQjMpF4qPXxIQHcjVD9dz1C2QA==", + "dev": true, + "requires": { + "@nodelib/fs.scandir": "2.1.5", + "fastq": "^1.6.0" + } + }, + "@tootallnate/once": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-1.1.2.tgz", + "integrity": "sha512-RbzJvlNzmRq5c3O09UipeuXno4tA1FE6ikOjxZK0tuxVv3412l64l5t1W5pj4+rJq9vpkm/kwiR07aZXnsKPxw==", + "dev": true + }, + "@types/mocha": { + "version": "8.2.2", + "resolved": "https://registry.npmjs.org/@types/mocha/-/mocha-8.2.2.tgz", + "integrity": "sha512-Lwh0lzzqT5Pqh6z61P3c3P5nm6fzQK/MMHl9UKeneAeInVflBSz1O2EkX6gM6xfJd7FBXBY5purtLx7fUiZ7Hw==", + "dev": true + }, + "@types/node": { + "version": "15.12.1", + "resolved": "https://registry.npmjs.org/@types/node/-/node-15.12.1.tgz", + "integrity": "sha512-zyxJM8I1c9q5sRMtVF+zdd13Jt6RU4r4qfhTd7lQubyThvLfx6yYekWSQjGCGV2Tkecgxnlpl/DNlb6Hg+dmEw==", + "dev": true + }, + "@types/vscode": { + "version": "1.56.0", + "resolved": "https://registry.npmjs.org/@types/vscode/-/vscode-1.56.0.tgz", + "integrity": "sha512-Q5VmQxOx+L1Y6lIJiGcJzwcyV3pQo/eiW8P+7sNLhFI16tJCwtua2DLjHRcpjbCLNVYpQM73kzfFo1Z0HyP9eQ==", + "dev": true + }, + "@typescript-eslint/parser": { + "version": "4.26.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-4.26.0.tgz", + "integrity": "sha512-b4jekVJG9FfmjUfmM4VoOItQhPlnt6MPOBUL0AQbiTmm+SSpSdhHYlwayOm4IW9KLI/4/cRKtQCmDl1oE2OlPg==", + "dev": true, + "requires": { + "@typescript-eslint/scope-manager": "4.26.0", + "@typescript-eslint/types": "4.26.0", + "@typescript-eslint/typescript-estree": "4.26.0", + "debug": "^4.3.1" + } + }, + "@typescript-eslint/scope-manager": { + "version": "4.26.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-4.26.0.tgz", + "integrity": "sha512-G6xB6mMo4xVxwMt5lEsNTz3x4qGDt0NSGmTBNBPJxNsrTXJSm21c6raeYroS2OwQsOyIXqKZv266L/Gln1BWqg==", + "dev": true, + "requires": { + "@typescript-eslint/types": "4.26.0", + "@typescript-eslint/visitor-keys": "4.26.0" + } + }, + "@typescript-eslint/types": { + "version": "4.26.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-4.26.0.tgz", + "integrity": "sha512-rADNgXl1kS/EKnDr3G+m7fB9yeJNnR9kF7xMiXL6mSIWpr3Wg5MhxyfEXy/IlYthsqwBqHOr22boFbf/u6O88A==", + "dev": true + }, + "@typescript-eslint/typescript-estree": { + "version": "4.26.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-4.26.0.tgz", + "integrity": "sha512-GHUgahPcm9GfBuy3TzdsizCcPjKOAauG9xkz9TR8kOdssz2Iz9jRCSQm6+aVFa23d5NcSpo1GdHGSQKe0tlcbg==", + "dev": true, + "requires": { + "@typescript-eslint/types": "4.26.0", + "@typescript-eslint/visitor-keys": "4.26.0", + "debug": "^4.3.1", + "globby": "^11.0.3", + "is-glob": "^4.0.1", + "semver": "^7.3.5", + "tsutils": "^3.21.0" + } + }, + "@typescript-eslint/visitor-keys": { + "version": "4.26.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-4.26.0.tgz", + "integrity": "sha512-cw4j8lH38V1ycGBbF+aFiLUls9Z0Bw8QschP3mkth50BbWzgFS33ISIgBzUMuQ2IdahoEv/rXstr8Zhlz4B1Zg==", + "dev": true, + "requires": { + "@typescript-eslint/types": "4.26.0", + "eslint-visitor-keys": "^2.0.0" + } + }, + "@ungap/promise-all-settled": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@ungap/promise-all-settled/-/promise-all-settled-1.1.2.tgz", + "integrity": "sha512-sL/cEvJWAnClXw0wHk85/2L0G6Sj8UB0Ctc1TEMbKSsmpRosqhwj9gWgFRZSrBr2f9tiXISwNhCPmlfqUqyb9Q==", + "dev": true + }, + "acorn": { + "version": "7.4.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz", + "integrity": "sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==", + "dev": true + }, + "acorn-jsx": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.1.tgz", + "integrity": "sha512-K0Ptm/47OKfQRpNQ2J/oIN/3QYiK6FwW+eJbILhsdxh2WTLdl+30o8aGdTbm5JbffpFFAg/g+zi1E+jvJha5ng==", + "dev": true, + "requires": {} + }, + "agent-base": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", + "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", + "dev": true, + "requires": { + "debug": "4" + } + }, + "ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, + "requires": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + } + }, + "ansi-colors": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.1.tgz", + "integrity": "sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==", + "dev": true + }, + "ansi-regex": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", + "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==", + "dev": true + }, + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "anymatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.2.tgz", + "integrity": "sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==", + "dev": true, + "requires": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + } + }, + "argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "dev": true, + "requires": { + "sprintf-js": "~1.0.2" + } + }, + "array-union": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", + "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", + "dev": true + }, + "astral-regex": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-2.0.0.tgz", + "integrity": "sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==", + "dev": true + }, + "balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" + }, + "big-integer": { + "version": "1.6.48", + "resolved": "https://registry.npmjs.org/big-integer/-/big-integer-1.6.48.tgz", + "integrity": "sha512-j51egjPa7/i+RdiRuJbPdJ2FIUYYPhvYLjzoYbcMMm62ooO6F94fETG4MTs46zPAF9Brs04OajboA/qTGuz78w==", + "dev": true + }, + "binary": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/binary/-/binary-0.3.0.tgz", + "integrity": "sha1-n2BVO8XOjDOG87VTz/R0Yq3sqnk=", + "dev": true, + "requires": { + "buffers": "~0.1.1", + "chainsaw": "~0.1.0" + } + }, + "binary-extensions": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", + "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", + "dev": true + }, + "bluebird": { + "version": "3.4.7", + "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.4.7.tgz", + "integrity": "sha1-9y12C+Cbf3bQjtj66Ysomo0F+rM=", + "dev": true + }, + "brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "requires": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "braces": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", + "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "dev": true, + "requires": { + "fill-range": "^7.0.1" + } + }, + "browser-stdout": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.1.tgz", + "integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==", + "dev": true + }, + "buffer-indexof-polyfill": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/buffer-indexof-polyfill/-/buffer-indexof-polyfill-1.0.2.tgz", + "integrity": "sha512-I7wzHwA3t1/lwXQh+A5PbNvJxgfo5r3xulgpYDB5zckTu/Z9oUK9biouBKQUjEqzaz3HnAT6TYoovmE+GqSf7A==", + "dev": true + }, + "buffers": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/buffers/-/buffers-0.1.1.tgz", + "integrity": "sha1-skV5w77U1tOWru5tmorn9Ugqt7s=", + "dev": true + }, + "callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "dev": true + }, + "camelcase": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.2.0.tgz", + "integrity": "sha512-c7wVvbw3f37nuobQNtgsgG9POC9qMbNuMQmTCqZv23b6MIz0fcYpBiOlv9gEN/hdLdnZTDQhg6e9Dq5M1vKvfg==", + "dev": true + }, + "chainsaw": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/chainsaw/-/chainsaw-0.1.0.tgz", + "integrity": "sha1-XqtQsor+WAdNDVgpE4iCi15fvJg=", + "dev": true, + "requires": { + "traverse": ">=0.3.0 <0.4" + } + }, + "chalk": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.1.tgz", + "integrity": "sha512-diHzdDKxcU+bAsUboHLPEDQiw0qEe0qd7SYUn3HgcFlWgbDcfLGswOHYeGrHKzG9z6UYf01d9VFMfZxPM1xZSg==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "chokidar": { + "version": "3.5.1", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.1.tgz", + "integrity": "sha512-9+s+Od+W0VJJzawDma/gvBNQqkTiqYTWLuZoyAsivsI4AaWTCzHG06/TMjsf1cYe9Cb97UCEhjz7HvnPk2p/tw==", + "dev": true, + "requires": { + "anymatch": "~3.1.1", + "braces": "~3.0.2", + "fsevents": "~2.3.1", + "glob-parent": "~5.1.0", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.5.0" + } + }, + "cliui": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", + "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", + "dev": true, + "requires": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0", + "wrap-ansi": "^7.0.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" + }, + "core-util-is": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=", + "dev": true + }, + "cross-spawn": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", + "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "dev": true, + "requires": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + } + }, + "debug": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz", + "integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==", + "dev": true, + "requires": { + "ms": "2.1.2" + } + }, + "decamelize": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-4.0.0.tgz", + "integrity": "sha512-9iE1PgSik9HeIIw2JO94IidnE3eBoQrFJ3w7sFuzSX4DpmZ3v5sZpUiV5Swcf6mQEF+Y0ru8Neo+p+nyh2J+hQ==", + "dev": true + }, + "deep-is": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz", + "integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=", + "dev": true + }, + "diff": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/diff/-/diff-5.0.0.tgz", + "integrity": "sha512-/VTCrvm5Z0JGty/BWHljh+BAiw3IK+2j87NGMu8Nwc/f48WoDAC395uomO9ZD117ZOBaHmkX1oyLvkVM/aIT3w==", + "dev": true + }, + "dir-glob": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", + "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", + "dev": true, + "requires": { + "path-type": "^4.0.0" + } + }, + "doctrine": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", + "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", + "dev": true, + "requires": { + "esutils": "^2.0.2" + } + }, + "duplexer2": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/duplexer2/-/duplexer2-0.1.4.tgz", + "integrity": "sha1-ixLauHjA1p4+eJEFFmKjL8a93ME=", + "dev": true, + "requires": { + "readable-stream": "^2.0.2" + } + }, + "emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true + }, + "enquirer": { + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/enquirer/-/enquirer-2.3.6.tgz", + "integrity": "sha512-yjNnPr315/FjS4zIsUxYguYUPP2e1NK4d7E7ZOLiyYCcbFBiTMyID+2wvm2w6+pZ/odMA7cRkjhsPbltwBOrLg==", + "dev": true, + "requires": { + "ansi-colors": "^4.1.1" + } + }, + "escalade": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", + "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", + "dev": true + }, + "escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "dev": true + }, + "eslint": { + "version": "7.28.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-7.28.0.tgz", + "integrity": "sha512-UMfH0VSjP0G4p3EWirscJEQ/cHqnT/iuH6oNZOB94nBjWbMnhGEPxsZm1eyIW0C/9jLI0Fow4W5DXLjEI7mn1g==", + "dev": true, + "requires": { + "@babel/code-frame": "7.12.11", + "@eslint/eslintrc": "^0.4.2", + "ajv": "^6.10.0", + "chalk": "^4.0.0", + "cross-spawn": "^7.0.2", + "debug": "^4.0.1", + "doctrine": "^3.0.0", + "enquirer": "^2.3.5", + "escape-string-regexp": "^4.0.0", + "eslint-scope": "^5.1.1", + "eslint-utils": "^2.1.0", + "eslint-visitor-keys": "^2.0.0", + "espree": "^7.3.1", + "esquery": "^1.4.0", + "esutils": "^2.0.2", + "fast-deep-equal": "^3.1.3", + "file-entry-cache": "^6.0.1", + "functional-red-black-tree": "^1.0.1", + "glob-parent": "^5.1.2", + "globals": "^13.6.0", + "ignore": "^4.0.6", + "import-fresh": "^3.0.0", + "imurmurhash": "^0.1.4", + "is-glob": "^4.0.0", + "js-yaml": "^3.13.1", + "json-stable-stringify-without-jsonify": "^1.0.1", + "levn": "^0.4.1", + "lodash.merge": "^4.6.2", + "minimatch": "^3.0.4", + "natural-compare": "^1.4.0", + "optionator": "^0.9.1", + "progress": "^2.0.0", + "regexpp": "^3.1.0", + "semver": "^7.2.1", + "strip-ansi": "^6.0.0", + "strip-json-comments": "^3.1.0", + "table": "^6.0.9", + "text-table": "^0.2.0", + "v8-compile-cache": "^2.0.3" + } + }, + "eslint-scope": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", + "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", + "dev": true, + "requires": { + "esrecurse": "^4.3.0", + "estraverse": "^4.1.1" + } + }, + "eslint-utils": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-2.1.0.tgz", + "integrity": "sha512-w94dQYoauyvlDc43XnGB8lU3Zt713vNChgt4EWwhXAP2XkBvndfxF0AgIqKOOasjPIPzj9JqgwkwbCYD0/V3Zg==", + "dev": true, + "requires": { + "eslint-visitor-keys": "^1.1.0" + }, + "dependencies": { + "eslint-visitor-keys": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz", + "integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==", + "dev": true + } + } + }, + "eslint-visitor-keys": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz", + "integrity": "sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==", + "dev": true + }, + "espree": { + "version": "7.3.1", + "resolved": "https://registry.npmjs.org/espree/-/espree-7.3.1.tgz", + "integrity": "sha512-v3JCNCE64umkFpmkFGqzVKsOT0tN1Zr+ueqLZfpV1Ob8e+CEgPWa+OxCoGH3tnhimMKIaBm4m/vaRpJ/krRz2g==", + "dev": true, + "requires": { + "acorn": "^7.4.0", + "acorn-jsx": "^5.3.1", + "eslint-visitor-keys": "^1.3.0" + }, + "dependencies": { + "eslint-visitor-keys": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz", + "integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==", + "dev": true + } + } + }, + "esprima": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", + "dev": true + }, + "esquery": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.4.0.tgz", + "integrity": "sha512-cCDispWt5vHHtwMY2YrAQ4ibFkAL8RbH5YGBnZBc90MolvvfkkQcJro/aZiAQUlQ3qgrYS6D6v8Gc5G5CQsc9w==", + "dev": true, + "requires": { + "estraverse": "^5.1.0" + }, + "dependencies": { + "estraverse": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.2.0.tgz", + "integrity": "sha512-BxbNGGNm0RyRYvUdHpIwv9IWzeM9XClbOxwoATuFdOE7ZE6wHL+HQ5T8hoPM+zHvmKzzsEqhgy0GrQ5X13afiQ==", + "dev": true + } + } + }, + "esrecurse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", + "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", + "dev": true, + "requires": { + "estraverse": "^5.2.0" + }, + "dependencies": { + "estraverse": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.2.0.tgz", + "integrity": "sha512-BxbNGGNm0RyRYvUdHpIwv9IWzeM9XClbOxwoATuFdOE7ZE6wHL+HQ5T8hoPM+zHvmKzzsEqhgy0GrQ5X13afiQ==", + "dev": true + } + } + }, + "estraverse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", + "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", + "dev": true + }, + "esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "dev": true + }, + "fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "dev": true + }, + "fast-glob": { + "version": "3.2.5", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.5.tgz", + "integrity": "sha512-2DtFcgT68wiTTiwZ2hNdJfcHNke9XOfnwmBRWXhmeKM8rF0TGwmC/Qto3S7RoZKp5cilZbxzO5iTNTQsJ+EeDg==", + "dev": true, + "requires": { + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.0", + "merge2": "^1.3.0", + "micromatch": "^4.0.2", + "picomatch": "^2.2.1" + } + }, + "fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", + "dev": true + }, + "fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=", + "dev": true + }, + "fastq": { + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.11.0.tgz", + "integrity": "sha512-7Eczs8gIPDrVzT+EksYBcupqMyxSHXXrHOLRRxU2/DicV8789MRBRR8+Hc2uWzUupOs4YS4JzBmBxjjCVBxD/g==", + "dev": true, + "requires": { + "reusify": "^1.0.4" + } + }, + "file-entry-cache": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", + "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", + "dev": true, + "requires": { + "flat-cache": "^3.0.4" + } + }, + "fill-range": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", + "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "dev": true, + "requires": { + "to-regex-range": "^5.0.1" + } + }, + "find-up": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "dev": true, + "requires": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + } + }, + "flat": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/flat/-/flat-5.0.2.tgz", + "integrity": "sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==", + "dev": true + }, + "flat-cache": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.0.4.tgz", + "integrity": "sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg==", + "dev": true, + "requires": { + "flatted": "^3.1.0", + "rimraf": "^3.0.2" + } + }, + "flatted": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.1.1.tgz", + "integrity": "sha512-zAoAQiudy+r5SvnSw3KJy5os/oRJYHzrzja/tBDqrZtNhUw8bt6y8OBzMWcjWr+8liV8Eb6yOhw8WZ7VFZ5ZzA==", + "dev": true + }, + "fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", + "dev": true + }, + "fsevents": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", + "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", + "dev": true, + "optional": true + }, + "fstream": { + "version": "1.0.12", + "resolved": "https://registry.npmjs.org/fstream/-/fstream-1.0.12.tgz", + "integrity": "sha512-WvJ193OHa0GHPEL+AycEJgxvBEwyfRkN1vhjca23OaPVMCaLCXTd5qAu82AjTcgP1UJmytkOKb63Ypde7raDIg==", + "dev": true, + "requires": { + "graceful-fs": "^4.1.2", + "inherits": "~2.0.0", + "mkdirp": ">=0.5 0", + "rimraf": "2" + }, + "dependencies": { + "rimraf": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", + "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", + "dev": true, + "requires": { + "glob": "^7.1.3" + } + } + } + }, + "functional-red-black-tree": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz", + "integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=", + "dev": true + }, + "get-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "dev": true + }, + "glob": { + "version": "7.1.6", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", + "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", + "dev": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "requires": { + "is-glob": "^4.0.1" + } + }, + "globals": { + "version": "13.9.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.9.0.tgz", + "integrity": "sha512-74/FduwI/JaIrr1H8e71UbDE+5x7pIPs1C2rrwC52SszOo043CsWOZEMW7o2Y58xwm9b+0RBKDxY5n2sUpEFxA==", + "dev": true, + "requires": { + "type-fest": "^0.20.2" + } + }, + "globby": { + "version": "11.0.3", + "resolved": "https://registry.npmjs.org/globby/-/globby-11.0.3.tgz", + "integrity": "sha512-ffdmosjA807y7+lA1NM0jELARVmYul/715xiILEjo3hBLPTcirgQNnXECn5g3mtR8TOLCVbkfua1Hpen25/Xcg==", + "dev": true, + "requires": { + "array-union": "^2.1.0", + "dir-glob": "^3.0.1", + "fast-glob": "^3.1.1", + "ignore": "^5.1.4", + "merge2": "^1.3.0", + "slash": "^3.0.0" + }, + "dependencies": { + "ignore": { + "version": "5.1.8", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.1.8.tgz", + "integrity": "sha512-BMpfD7PpiETpBl/A6S498BaIJ6Y/ABT93ETbby2fP00v4EbvPBXWEoaR1UBPKs3iR53pJY7EtZk5KACI57i1Uw==", + "dev": true + } + } + }, + "graceful-fs": { + "version": "4.2.6", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.6.tgz", + "integrity": "sha512-nTnJ528pbqxYanhpDYsi4Rd8MAeaBA67+RZ10CM1m3bTAVFEDcd5AuA4a6W5YkGZ1iNXHzZz8T6TBKLeBuNriQ==", + "dev": true + }, + "growl": { + "version": "1.10.5", + "resolved": "https://registry.npmjs.org/growl/-/growl-1.10.5.tgz", + "integrity": "sha512-qBr4OuELkhPenW6goKVXiv47US3clb3/IbuWF9KNKEijAy9oeHxU9IgzjvJhHkUzhaj7rOUD7+YGWqUjLp5oSA==", + "dev": true + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "he": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", + "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", + "dev": true + }, + "http-proxy-agent": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-4.0.1.tgz", + "integrity": "sha512-k0zdNgqWTGA6aeIRVpvfVob4fL52dTfaehylg0Y4UvSySvOq/Y+BOyPrgpUrA7HylqvU8vIZGsRuXmspskV0Tg==", + "dev": true, + "requires": { + "@tootallnate/once": "1", + "agent-base": "6", + "debug": "4" + } + }, + "https-proxy-agent": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.0.tgz", + "integrity": "sha512-EkYm5BcKUGiduxzSt3Eppko+PiNWNEpa4ySk9vTC6wDsQJW9rHSa+UhGNJoRYp7bz6Ht1eaRIa6QaJqO5rCFbA==", + "dev": true, + "requires": { + "agent-base": "6", + "debug": "4" + } + }, + "ignore": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz", + "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==", + "dev": true + }, + "import-fresh": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", + "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", + "dev": true, + "requires": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + } + }, + "imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=", + "dev": true + }, + "inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", + "dev": true, + "requires": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "dev": true + }, + "is-binary-path": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", + "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "dev": true, + "requires": { + "binary-extensions": "^2.0.0" + } + }, + "is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", + "dev": true + }, + "is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true + }, + "is-glob": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz", + "integrity": "sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg==", + "dev": true, + "requires": { + "is-extglob": "^2.1.1" + } + }, + "is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true + }, + "is-plain-obj": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-2.1.0.tgz", + "integrity": "sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==", + "dev": true + }, + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + }, + "isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", + "dev": true + }, + "js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "dev": true + }, + "js-yaml": { + "version": "3.14.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", + "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", + "dev": true, + "requires": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + } + }, + "json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true + }, + "json-stable-stringify-without-jsonify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", + "integrity": "sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=", + "dev": true + }, + "levn": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", + "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", + "dev": true, + "requires": { + "prelude-ls": "^1.2.1", + "type-check": "~0.4.0" + } + }, + "listenercount": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/listenercount/-/listenercount-1.0.1.tgz", + "integrity": "sha1-hMinKrWcRyUyFIDJdeZQg0LnCTc=", + "dev": true + }, + "locate-path": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "dev": true, + "requires": { + "p-locate": "^5.0.0" + } + }, + "lodash.clonedeep": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz", + "integrity": "sha1-4j8/nE+Pvd6HJSnBBxhXoIblzO8=", + "dev": true + }, + "lodash.merge": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", + "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", + "dev": true + }, + "lodash.truncate": { + "version": "4.4.2", + "resolved": "https://registry.npmjs.org/lodash.truncate/-/lodash.truncate-4.4.2.tgz", + "integrity": "sha1-WjUNoLERO4N+z//VgSy+WNbq4ZM=", + "dev": true + }, + "log-symbols": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.0.0.tgz", + "integrity": "sha512-FN8JBzLx6CzeMrB0tg6pqlGU1wCrXW+ZXGH481kfsBqer0hToTIiHdjH4Mq8xJUbvATujKCvaREGWpGUionraA==", + "dev": true, + "requires": { + "chalk": "^4.0.0" + } + }, + "lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "requires": { + "yallist": "^4.0.0" + } + }, + "merge2": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", + "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", + "dev": true + }, + "micromatch": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.4.tgz", + "integrity": "sha512-pRmzw/XUcwXGpD9aI9q/0XOwLNygjETJ8y0ao0wdqprrzDa4YnxLcz7fQRZr8voh8V10kGhABbNcHVk5wHgWwg==", + "dev": true, + "requires": { + "braces": "^3.0.1", + "picomatch": "^2.2.3" + } + }, + "minimatch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "requires": { + "brace-expansion": "^1.1.7" + } + }, + "minimist": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", + "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==", + "dev": true + }, + "mkdirp": { + "version": "0.5.5", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", + "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==", + "dev": true, + "requires": { + "minimist": "^1.2.5" + } + }, + "mocha": { + "version": "8.4.0", + "resolved": "https://registry.npmjs.org/mocha/-/mocha-8.4.0.tgz", + "integrity": "sha512-hJaO0mwDXmZS4ghXsvPVriOhsxQ7ofcpQdm8dE+jISUOKopitvnXFQmpRR7jd2K6VBG6E26gU3IAbXXGIbu4sQ==", + "dev": true, + "requires": { + "@ungap/promise-all-settled": "1.1.2", + "ansi-colors": "4.1.1", + "browser-stdout": "1.3.1", + "chokidar": "3.5.1", + "debug": "4.3.1", + "diff": "5.0.0", + "escape-string-regexp": "4.0.0", + "find-up": "5.0.0", + "glob": "7.1.6", + "growl": "1.10.5", + "he": "1.2.0", + "js-yaml": "4.0.0", + "log-symbols": "4.0.0", + "minimatch": "3.0.4", + "ms": "2.1.3", + "nanoid": "3.1.20", + "serialize-javascript": "5.0.1", + "strip-json-comments": "3.1.1", + "supports-color": "8.1.1", + "which": "2.0.2", + "wide-align": "1.1.3", + "workerpool": "6.1.0", + "yargs": "16.2.0", + "yargs-parser": "20.2.4", + "yargs-unparser": "2.0.0" + }, + "dependencies": { + "argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "dev": true + }, + "js-yaml": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.0.0.tgz", + "integrity": "sha512-pqon0s+4ScYUvX30wxQi3PogGFAlUyH0awepWvwkj4jD4v+ova3RiYw8bmA6x2rDrEaj8i/oWKoRxpVNW+Re8Q==", + "dev": true, + "requires": { + "argparse": "^2.0.1" + } + }, + "ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true + }, + "supports-color": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "nanoid": { + "version": "3.1.20", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.1.20.tgz", + "integrity": "sha512-a1cQNyczgKbLX9jwbS/+d7W8fX/RfgYR7lVWwWOGIPNgK2m0MWvrGF6/m4kk6U3QcFMnZf3RIhL0v2Jgh/0Uxw==", + "dev": true + }, + "natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=", + "dev": true + }, + "normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "dev": true + }, + "once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "dev": true, + "requires": { + "wrappy": "1" + } + }, + "optionator": { + "version": "0.9.1", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.1.tgz", + "integrity": "sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw==", + "dev": true, + "requires": { + "deep-is": "^0.1.3", + "fast-levenshtein": "^2.0.6", + "levn": "^0.4.1", + "prelude-ls": "^1.2.1", + "type-check": "^0.4.0", + "word-wrap": "^1.2.3" + } + }, + "p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "dev": true, + "requires": { + "yocto-queue": "^0.1.0" + } + }, + "p-locate": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "dev": true, + "requires": { + "p-limit": "^3.0.2" + } + }, + "parent-module": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", + "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", + "dev": true, + "requires": { + "callsites": "^3.0.0" + } + }, + "path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true + }, + "path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", + "dev": true + }, + "path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true + }, + "path-type": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", + "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", + "dev": true + }, + "picomatch": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.0.tgz", + "integrity": "sha512-lY1Q/PiJGC2zOv/z391WOTD+Z02bCgsFfvxoXXf6h7kv9o+WmsmzYqrAwY63sNgOxE4xEdq0WyUnXfKeBrSvYw==", + "dev": true + }, + "prelude-ls": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", + "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", + "dev": true + }, + "process-nextick-args": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", + "dev": true + }, + "progress": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz", + "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==", + "dev": true + }, + "punycode": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", + "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", + "dev": true + }, + "queue-microtask": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", + "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", + "dev": true + }, + "randombytes": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", + "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", + "dev": true, + "requires": { + "safe-buffer": "^5.1.0" + } + }, + "readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "dev": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + }, + "dependencies": { + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + } + } + }, + "readdirp": { + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.5.0.tgz", + "integrity": "sha512-cMhu7c/8rdhkHXWsY+osBhfSy0JikwpHK/5+imo+LpeasTF8ouErHrlYkwT0++njiyuDvc7OFY5T3ukvZ8qmFQ==", + "dev": true, + "requires": { + "picomatch": "^2.2.1" + } + }, + "regexpp": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-3.1.0.tgz", + "integrity": "sha512-ZOIzd8yVsQQA7j8GCSlPGXwg5PfmA1mrq0JP4nGhh54LaKN3xdai/vHUDu74pKwV8OxseMS65u2NImosQcSD0Q==", + "dev": true + }, + "require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=", + "dev": true + }, + "require-from-string": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", + "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", + "dev": true + }, + "resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "dev": true + }, + "reusify": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", + "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", + "dev": true + }, + "rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "dev": true, + "requires": { + "glob": "^7.1.3" + } + }, + "run-parallel": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", + "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", + "dev": true, + "requires": { + "queue-microtask": "^1.2.2" + } + }, + "safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "dev": true + }, + "semver": { + "version": "7.3.5", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", + "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", + "requires": { + "lru-cache": "^6.0.0" + } + }, + "serialize-javascript": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-5.0.1.tgz", + "integrity": "sha512-SaaNal9imEO737H2c05Og0/8LUXG7EnsZyMa8MzkmuHoELfT6txuj0cMqRj6zfPKnmQ1yasR4PCJc8x+M4JSPA==", + "dev": true, + "requires": { + "randombytes": "^2.1.0" + } + }, + "setimmediate": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz", + "integrity": "sha1-KQy7Iy4waULX1+qbg3Mqt4VvgoU=", + "dev": true + }, + "shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dev": true, + "requires": { + "shebang-regex": "^3.0.0" + } + }, + "shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "dev": true + }, + "slash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", + "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", + "dev": true + }, + "slice-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-4.0.0.tgz", + "integrity": "sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ==", + "dev": true, + "requires": { + "ansi-styles": "^4.0.0", + "astral-regex": "^2.0.0", + "is-fullwidth-code-point": "^3.0.0" + } + }, + "sprintf-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", + "dev": true + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "requires": { + "safe-buffer": "~5.1.0" + }, + "dependencies": { + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + } + } + }, + "string-width": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.2.tgz", + "integrity": "sha512-XBJbT3N4JhVumXE0eoLU9DCjcaF92KLNqTmFCnG1pf8duUxFGwtP6AD6nkjw9a3IdiRtL3E2w3JDiE/xi3vOeA==", + "dev": true, + "requires": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.0" + } + }, + "strip-ansi": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", + "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==", + "dev": true, + "requires": { + "ansi-regex": "^5.0.0" + } + }, + "strip-json-comments": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "dev": true + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + }, + "table": { + "version": "6.7.1", + "resolved": "https://registry.npmjs.org/table/-/table-6.7.1.tgz", + "integrity": "sha512-ZGum47Yi6KOOFDE8m223td53ath2enHcYLgOCjGr5ngu8bdIARQk6mN/wRMv4yMRcHnCSnHbCEha4sobQx5yWg==", + "dev": true, + "requires": { + "ajv": "^8.0.1", + "lodash.clonedeep": "^4.5.0", + "lodash.truncate": "^4.4.2", + "slice-ansi": "^4.0.0", + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0" + }, + "dependencies": { + "ajv": { + "version": "8.5.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.5.0.tgz", + "integrity": "sha512-Y2l399Tt1AguU3BPRP9Fn4eN+Or+StUGWCUpbnFyXSo8NZ9S4uj+AG2pjs5apK+ZMOwYOz1+a+VKvKH7CudXgQ==", + "dev": true, + "requires": { + "fast-deep-equal": "^3.1.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2", + "uri-js": "^4.2.2" + } + }, + "json-schema-traverse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", + "dev": true + } + } + }, + "text-table": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", + "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=", + "dev": true + }, + "to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dev": true, + "requires": { + "is-number": "^7.0.0" + } + }, + "traverse": { + "version": "0.3.9", + "resolved": "https://registry.npmjs.org/traverse/-/traverse-0.3.9.tgz", + "integrity": "sha1-cXuPIgzAu3tE5AUUwisui7xw2Lk=", + "dev": true + }, + "tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", + "dev": true + }, + "tsutils": { + "version": "3.21.0", + "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.21.0.tgz", + "integrity": "sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==", + "dev": true, + "requires": { + "tslib": "^1.8.1" + } + }, + "type-check": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", + "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", + "dev": true, + "requires": { + "prelude-ls": "^1.2.1" + } + }, + "type-fest": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", + "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", + "dev": true + }, + "typescript": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.3.2.tgz", + "integrity": "sha512-zZ4hShnmnoVnAHpVHWpTcxdv7dWP60S2FsydQLV8V5PbS3FifjWFFRiHSWpDJahly88PRyV5teTSLoq4eG7mKw==", + "dev": true + }, + "unzipper": { + "version": "0.10.11", + "resolved": "https://registry.npmjs.org/unzipper/-/unzipper-0.10.11.tgz", + "integrity": "sha512-+BrAq2oFqWod5IESRjL3S8baohbevGcVA+teAIOYWM3pDVdseogqbzhhvvmiyQrUNKFUnDMtELW3X8ykbyDCJw==", + "dev": true, + "requires": { + "big-integer": "^1.6.17", + "binary": "~0.3.0", + "bluebird": "~3.4.1", + "buffer-indexof-polyfill": "~1.0.0", + "duplexer2": "~0.1.4", + "fstream": "^1.0.12", + "graceful-fs": "^4.2.2", + "listenercount": "~1.0.1", + "readable-stream": "~2.3.6", + "setimmediate": "~1.0.4" + } + }, + "uri-js": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "dev": true, + "requires": { + "punycode": "^2.1.0" + } + }, + "util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", + "dev": true + }, + "v8-compile-cache": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.3.0.tgz", + "integrity": "sha512-l8lCEmLcLYZh4nbunNZvQCJc5pv7+RCwa8q/LdUx8u7lsWvPDKmpodJAJNwkAhJC//dFY48KuIEmjtd4RViDrA==", + "dev": true + }, + "vscode-jsonrpc": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/vscode-jsonrpc/-/vscode-jsonrpc-6.0.0.tgz", + "integrity": "sha512-wnJA4BnEjOSyFMvjZdpiOwhSq9uDoK8e/kpRJDTaMYzwlkrhG1fwDIZI94CLsLzlCK5cIbMMtFlJlfR57Lavmg==" + }, + "vscode-languageclient": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/vscode-languageclient/-/vscode-languageclient-7.0.0.tgz", + "integrity": "sha512-P9AXdAPlsCgslpP9pRxYPqkNYV7Xq8300/aZDpO35j1fJm/ncize8iGswzYlcvFw5DQUx4eVk+KvfXdL0rehNg==", + "requires": { + "minimatch": "^3.0.4", + "semver": "^7.3.4", + "vscode-languageserver-protocol": "3.16.0" + } + }, + "vscode-languageserver-protocol": { + "version": "3.16.0", + "resolved": "https://registry.npmjs.org/vscode-languageserver-protocol/-/vscode-languageserver-protocol-3.16.0.tgz", + "integrity": "sha512-sdeUoAawceQdgIfTI+sdcwkiK2KU+2cbEYA0agzM2uqaUy2UpnnGHtWTHVEtS0ES4zHU0eMFRGN+oQgDxlD66A==", + "requires": { + "vscode-jsonrpc": "6.0.0", + "vscode-languageserver-types": "3.16.0" + } + }, + "vscode-languageserver-types": { + "version": "3.16.0", + "resolved": "https://registry.npmjs.org/vscode-languageserver-types/-/vscode-languageserver-types-3.16.0.tgz", + "integrity": "sha512-k8luDIWJWyenLc5ToFQQMaSrqCHiLwyKPHKPQZ5zz21vM+vIVUSvsRpcbiECH4WR88K2XZqc4ScRcZ7nk/jbeA==" + }, + "vscode-test": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/vscode-test/-/vscode-test-1.5.2.tgz", + "integrity": "sha512-x9PVfKxF6EInH9iSFGQi0V8H5zIW1fC7RAer6yNQR6sy3WyOwlWkuT3I+wf75xW/cO53hxMi1aj/EvqQfDFOAg==", + "dev": true, + "requires": { + "http-proxy-agent": "^4.0.1", + "https-proxy-agent": "^5.0.0", + "rimraf": "^3.0.2", + "unzipper": "^0.10.11" + } + }, + "which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "requires": { + "isexe": "^2.0.0" + } + }, + "wide-align": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.3.tgz", + "integrity": "sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA==", + "dev": true, + "requires": { + "string-width": "^1.0.2 || 2" + }, + "dependencies": { + "ansi-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", + "dev": true + }, + "is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", + "dev": true + }, + "string-width": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", + "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", + "dev": true, + "requires": { + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^4.0.0" + } + }, + "strip-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", + "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "dev": true, + "requires": { + "ansi-regex": "^3.0.0" + } + } + } + }, + "word-wrap": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz", + "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==", + "dev": true + }, + "workerpool": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/workerpool/-/workerpool-6.1.0.tgz", + "integrity": "sha512-toV7q9rWNYha963Pl/qyeZ6wG+3nnsyvolaNUS8+R5Wtw6qJPTxIlOP1ZSvcGhEJw+l3HMMmtiNo9Gl61G4GVg==", + "dev": true + }, + "wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dev": true, + "requires": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + } + }, + "wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", + "dev": true + }, + "y18n": { + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", + "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", + "dev": true + }, + "yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + }, + "yargs": { + "version": "16.2.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", + "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", + "dev": true, + "requires": { + "cliui": "^7.0.2", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.0", + "y18n": "^5.0.5", + "yargs-parser": "^20.2.2" + } + }, + "yargs-parser": { + "version": "20.2.4", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.4.tgz", + "integrity": "sha512-WOkpgNhPTlE73h4VFAFsOnomJVaovO8VqLDzy5saChRBFQFBoMYirowyW+Q9HB4HFF4Z7VZTiG3iSzJJA29yRA==", + "dev": true + }, + "yargs-unparser": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/yargs-unparser/-/yargs-unparser-2.0.0.tgz", + "integrity": "sha512-7pRTIA9Qc1caZ0bZ6RYRGbHJthJWuakf+WmHK0rVeLkNrrGhfoabBNdue6kdINI6r4if7ocq9aD/n7xwKOdzOA==", + "dev": true, + "requires": { + "camelcase": "^6.0.0", + "decamelize": "^4.0.0", + "flat": "^5.0.2", + "is-plain-obj": "^2.1.0" + } + }, + "yocto-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", + "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", + "dev": true + } + } +} diff --git a/test/client/src/package.json b/test/client/src/package.json new file mode 100644 index 0000000..b3a18fe --- /dev/null +++ b/test/client/src/package.json @@ -0,0 +1,96 @@ +{ + "name": "veridian", + "description": "A client for the Veridian Language Server for SystemVerilog/Verilog", + "author": "Vivek Malneedi", + "publisher": "vivekmalneedi", + "license": "MIT", + "version": "0.1.0", + "categories": [ + "Programming Languages", + "Snippets", + "Linters" + ], + "keywords": [ + "SystemVerilog", + "Verilog" + ], + "repository": { + "type": "git", + "url": "https://github.com/vivekmalneedi/veridian" + }, + "activationEvents": [ + "onLanguage:systemverilog", + "onLanguage:verilog" + ], + "main": "./out/extension", + "scripts": { + "vscode:prepublish": "npm run compile", + "compile": "tsc -b", + "watch": "tsc -b -w" + }, + "contributes": { + "languages": [ + { + "id": "systemverilog", + "extensions": [ + ".sv", + ".svh", + ".v", + ".vh", + ".verilog" + ], + "aliases": [ + "SystemVerilog", + "verilog", + "Verilog" + ] + } + ], + "grammars": [ + { + "language": "systemverilog", + "scopeName": "source.systemverilog", + "path": "./syntaxes/systemverilog.tmLanguage.json" + } + ], + "configuration": { + "type": "object", + "title": "veridian", + "properties": { + "veridian.serverPath": { + "scope": "window", + "type": "string", + "default": "veridian", + "description": "path of the veridian binary" + }, + "veridian.trace.server": { + "scope": "window", + "type": "string", + "enum": [ + "off", + "messages", + "verbose" + ], + "default": "off", + "description": "Traces the communication between VS Code and the language server." + } + } + } + }, + "engines": { + "vscode": "^1.56.0" + }, + "dependencies": { + "vscode-languageclient": "^7.0.0" + }, + "devDependencies": { + "@types/vscode": "^1.56.0", + "vscode-test": "^1.5.2", + "@types/mocha": "^8.2.2", + "mocha": "^8.4.0", + "@types/node": "^15.12.1", + "eslint": "^7.28.0", + "@typescript-eslint/parser": "^4.26.0", + "typescript": "^4.3.2" + } +} diff --git a/test/client/src/tsconfig.json b/test/client/src/tsconfig.json new file mode 100644 index 0000000..c526fc9 --- /dev/null +++ b/test/client/src/tsconfig.json @@ -0,0 +1,12 @@ +{ + "compilerOptions": { + "module": "commonjs", + "target": "es2019", + "lib": ["ES2019"], + "outDir": "out", + "rootDir": "src", + "sourceMap": true + }, + "include": ["src"], + "exclude": ["node_modules", ".vscode-test"] +} diff --git a/test/client/syntaxes/systemverilog.tmLanguage.json b/test/client/syntaxes/systemverilog.tmLanguage.json new file mode 100644 index 0000000..f9f3c4b --- /dev/null +++ b/test/client/syntaxes/systemverilog.tmLanguage.json @@ -0,0 +1,1051 @@ +{ + "$schema": "https://raw.githubusercontent.com/martinring/tmlanguage/master/tmlanguage.json", + "fileTypes": [ + "sv", + "SV", + "v", + "V", + "svh", + "SVH", + "vh", + "VH" + ], + "hidden": true, + "foldingStartMarker": "(begin)\\s*(//.*)?$", + "foldingStopMarker": "^\\s*(begin)$", + "name": "systemverilog", + "patterns": [ + { + "begin": "\\s*\\b(function|task)\\b(\\s+automatic)?", + "beginCaptures": { + "1": { + "name": "keyword.control.systemverilog" + }, + "2": { + "name": "keyword.control.systemverilog" + } + }, + "end": ";", + "patterns": [ + { + "match": "\\b([a-zA-Z_][a-zA-Z0-9_]*\\s+)?([a-zA-Z_][a-zA-Z0-9_:]*)\\s*(?=\\(|;)", + "captures": { + "1": { + "name": "storage.type.systemverilog" + }, + "2": { + "name": "entity.name.function.systemverilog" + } + } + }, + { + "include": "#port-dir" + }, + { + "include": "#base-grammar" + } + ], + "name": "meta.function.systemverilog" + }, + { + "match": "\\s*\\b(task)\\s+(automatic)?\\s*(\\w+)\\s*;", + "captures": { + "1": { + "name": "keyword.control.systemverilog" + }, + "2": { + "name": "keyword.control.systemverilog" + }, + "3": { + "name": "entity.name.function.systemverilog" + } + }, + "name": "meta.task.simple.systemverilog" + }, + { + "begin": "\\s*\\b(typedef\\s+(struct|enum|union)\\b)\\s*(packed)?\\s*([a-zA-Z_][a-zA-Z0-9_]*)?", + "beginCaptures": { + "1": { + "name": "keyword.control.systemverilog" + }, + "2": { + "name": "keyword.control.systemverilog" + }, + "3": { + "name": "keyword.control.systemverilog" + }, + "4": { + "name": "storage.type.systemverilog" + } + }, + "end": "(})\\s*([a-zA-Z_][a-zA-Z0-9_]*)\\s*;", + "endCaptures": { + "1": { + "name": "keyword.operator.other.systemverilog" + }, + "2": { + "name": "entity.name.function.systemverilog" + } + }, + "patterns": [ + { + "include": "#struct-anonymous" + }, + { + "include": "#base-grammar" + } + ], + "name": "meta.typedef.struct.systemverilog" + }, + { + "match": "\\s*\\b(typedef\\s+class)\\s+([a-zA-Z_][a-zA-Z0-9_]*)\\s*;", + "captures": { + "1": { + "name": "keyword.control.systemverilog" + }, + "2": { + "name": "entity.name.declaration.systemverilog" + } + }, + "name": "meta.typedef.class.systemverilog" + }, + { + "begin": "\\s*\\b(typedef)\\b", + "beginCaptures": { + "1": { + "name": "keyword.control.systemverilog" + } + }, + "end": "([a-zA-Z_][a-zA-Z0-9_]*)\\s*(?=(\\[[a-zA-Z0-9_:\\$\\-\\+]*\\])?;)", + "endCaptures": { + "1": { + "name": "entity.name.function.systemverilog" + } + }, + "patterns": [ + { + "match": "\\b([a-zA-Z_]\\w*)\\s*(#)\\(", + "captures": { + "1": { + "name": "storage.type.userdefined.systemverilog" + }, + "2": { + "name": "keyword.operator.param.systemverilog" + } + }, + "name": "meta.typedef.class.systemverilog" + }, + { + "include": "#base-grammar" + }, + { + "include": "#module-binding" + } + ], + "name": "meta.typedef.simple.systemverilog" + }, + { + "begin": "\\s*(module)\\s+\\b([a-zA-Z_][a-zA-Z0-9_]*)\\b", + "beginCaptures": { + "1": { + "name": "keyword.control.systemverilog" + }, + "2": { + "name": "entity.name.type.module.systemverilog" + } + }, + "end": ";", + "endCaptures": { + "1": { + "name": "entity.name.function.systemverilog" + } + }, + "patterns": [ + { + "include": "#port-dir" + }, + { + "match": "\\s*(parameter)", + "name": "keyword.other.systemverilog" + }, + { + "include": "#base-grammar" + }, + { + "include": "#ifmodport" + } + ], + "name": "meta.module.systemverilog" + }, + { + "captures": { + "1": { + "name": "keyword.control.systemverilog" + }, + "2": { + "name": "entity.name.function.systemverilog" + } + }, + "match": "\\b(sequence)\\s+([a-zA-Z_][a-zA-Z0-9_]*)", + "name": "meta.sequence.systemverilog" + }, + { + "match": "\\b(bind)\\s+([a-zA-Z_][a-zA-Z0-9_\\.]*)\\b", + "captures": { + "1": { + "name": "keyword.control.systemverilog" + } + } + }, + { + "captures": { + "0": { + "name": "meta.section.begin.systemverilog" + }, + "1": { + "name": "keyword.other.block.systemverilog" + }, + "3": { + "name": "keyword.operator.systemverilog" + }, + "4": { + "name": "entity.name.section.systemverilog" + } + }, + "match": "\\s*(begin|fork)\\s*((:)\\s*([a-zA-Z_][a-zA-Z0-9_]*))\\b", + "name": "meta.definition.systemverilog" + }, + { + "match": "\\b(property)\\s+(\\w+)", + "captures": { + "1": { + "name": "keyword.sva.systemverilog" + }, + "2": { + "name": "entity.name.sva.systemverilog" + } + } + }, + { + "match": "\\b(\\w+)\\s*(:)\\s*(assert)\\b", + "captures": { + "1": { + "name": "entity.name.sva.systemverilog" + }, + "2": { + "name": "keyword.operator.systemverilog" + }, + "3": { + "name": "keyword.sva.systemverilog" + } + } + }, + { + "begin": "\\s*(//)\\s*(psl)\\s+((\\w+)\\s*(:))?\\s*(default|assert|assume)", + "beginCaptures": { + "0": { + "name": "meta.psl.systemverilog" + }, + "1": { + "name": "comment.line.double-slash.systemverilog" + }, + "2": { + "name": "keyword.psl.systemverilog" + }, + "4": { + "name": "entity.psl.name.systemverilog" + }, + "5": { + "name": "keyword.operator.systemverilog" + }, + "6": { + "name": "keyword.psl.systemverilog" + } + }, + "end": ";", + "patterns": [ + { + "match": "\\b(never|always|default|clock|within|rose|fell|stable|until|before|next|eventually|abort|posedge)\\b", + "name": "keyword.psl.systemverilog" + }, + { + "include": "#operators" + }, + { + "include": "#functions" + }, + { + "include": "#constants" + } + ], + "name": "meta.psl.systemverilog" + }, + { + "begin": "\\s*(/\\*)\\s*(psl)", + "beginCaptures": { + "0": { + "name": "meta.psl.systemverilog" + }, + "1": { + "name": "comment.block.systemverilog" + }, + "2": { + "name": "keyword.psl.systemverilog" + } + }, + "end": "(\\*/)", + "endCaptures": { + "1": { + "name": "comment.block.systemverilog" + } + }, + "patterns": [ + { + "match": "^\\s*((\\w+)\\s*(:))?\\s*(default|assert|assume)", + "captures": { + "0": { + "name": "meta.psl.systemverilog" + }, + "2": { + "name": "entity.psl.name.systemverilog" + }, + "3": { + "name": "keyword.operator.systemverilog" + }, + "4": { + "name": "keyword.psl.systemverilog" + } + } + }, + { + "match": "\\b(property)\\s+(\\w+)", + "captures": { + "1": { + "name": "keyword.psl.systemverilog" + }, + "2": { + "name": "entity.psl.name.systemverilog" + } + } + }, + { + "match": "\\b(never|always|default|clock|within|rose|fell|stable|until|before|next|eventually|abort|posedge|negedge)\\b", + "name": "keyword.psl.systemverilog" + }, + { + "include": "#operators" + }, + { + "include": "#functions" + }, + { + "include": "#constants" + } + ], + "name": "meta.psl.systemverilog" + }, + { + "match": "\\s*\\b(automatic|cell|config|deassign|defparam|design|disable|edge|endconfig|endgenerate|endspecify|endtable|event|generate|genvar|ifnone|incdir|instance|liblist|library|macromodule|negedge|noshowcancelled|posedge|pulsestyle_onevent|pulsestyle_ondetect|scalared|showcancelled|specify|specparam|table|use|vectored)\\b", + "captures": { + "1": { + "name": "keyword.other.systemverilog" + } + } + }, + { + "match": "\\s*\\b(initial|always|wait|force|release|assign|always_comb|always_ff|always_latch|forever|repeat|while|for|if|iff|else|case|casex|casez|default|endcase|return|break|continue|do|foreach|with|inside|dist|clocking|cover|coverpoint|property|bins|binsof|illegal_bins|ignore_bins|randcase|modport|matches|solve|static|assert|assume|before|expect|cross|ref|first_match|srandom|struct|packed|final|chandle|alias|tagged|extern|throughout|timeprecision|timeunit|priority|type|union|uwire|wait_order|triggered|randsequence|import|export|context|pure|intersect|wildcard|within|new|typedef|enum|this|super|begin|fork|forkjoin|unique|unique0|priority)\\b", + "captures": { + "1": { + "name": "keyword.control.systemverilog" + } + } + }, + { + "match": "\\s*\\b(end|endtask|endmodule|endfunction|endprimitive|endclass|endpackage|endsequence|endprogram|endclocking|endproperty|endgroup|endinterface|join|join_any|join_none)\\b(\\s*(:)\\s*(\\w+))?", + "captures": { + "1": { + "name": "keyword.control.systemverilog" + }, + "3": { + "name": "keyword.operator.systemverilog" + }, + "4": { + "name": "entity.label.systemverilog" + } + }, + "name": "meta.object.end.systemverilog" + }, + { + "match": "\\b(std)\\b::", + "name": "support.class.systemverilog" + }, + { + "captures": { + "1": { + "name": "constant.other.define.systemverilog" + }, + "2": { + "name": "entity.name.type.define.systemverilog" + } + }, + "match": "^\\s*(`define)\\s+([a-zA-Z_][a-zA-Z0-9_]*)", + "name": "meta.define.systemverilog" + }, + { + "include": "#comments" + }, + { + "captures": { + "1": { + "name": "keyword.control.systemverilog" + }, + "2": { + "name": "entity.name.type.class.systemverilog" + } + }, + "match": "\\s*(primitive|package|constraint|interface|covergroup|program)\\s+\\b([a-zA-Z_][a-zA-Z0-9_]*)\\b", + "name": "meta.definition.systemverilog" + }, + { + "captures": { + "2": { + "name": "entity.name.type.class.systemverilog" + }, + "3": { + "name": "keyword.operator.other.systemverilog" + }, + "4": { + "name": "keyword.control.systemverilog" + } + }, + "match": "(([a-zA-Z_][a-zA-Z0-9_]*)\\s*(:))?\\s*(coverpoint|cross)\\s+([a-zA-Z_][a-zA-Z0-9_]*)", + "name": "meta.definition.systemverilog" + }, + { + "captures": { + "1": { + "name": "keyword.control.systemverilog" + }, + "2": { + "name": "keyword.control.systemverilog" + }, + "3": { + "name": "entity.name.type.class.systemverilog" + } + }, + "match": "\\b(virtual\\s+)?(class)\\s+\\b([a-zA-Z_][a-zA-Z0-9_]*)\\b", + "name": "meta.definition.class.systemverilog" + }, + { + "captures": { + "1": { + "name": "keyword.control.systemverilog" + }, + "2": { + "name": "entity.other.inherited-class.systemverilog" + } + }, + "match": "\\b(extends)\\s+([a-zA-Z_][a-zA-Z0-9_]*)\\b", + "name": "meta.definition.systemverilog" + }, + { + "include": "#all-types" + }, + { + "include": "#operators" + }, + { + "include": "#port-dir" + }, + { + "match": "\\b(and|nand|nor|or|xor|xnor|buf|not|bufif[01]|notif[01]|r?[npc]mos|tran|r?tranif[01]|pullup|pulldown)\\b", + "name": "support.type.systemverilog" + }, + { + "include": "#strings" + }, + { + "match": "\\$\\b([a-zA-Z_][a-zA-Z0-9_]*)\\b", + "name": "support.function.systemverilog" + }, + { + "match": "\\b([a-zA-Z_][a-zA-Z0-9_]*)(')(?=\\()", + "name": "meta.cast.systemverilog", + "captures": { + "1": { + "name": "storage.type.systemverilog" + }, + "2": { + "name": "keyword.operator.cast.systemverilog" + } + } + }, + { + "match": "^\\s*(localparam|parameter)\\s+([A-Z_][A-Z0-9_]*)\\b\\s*(?=(=))", + "name": "meta.param.systemverilog", + "captures": { + "1": { + "name": "keyword.other.systemverilog" + }, + "2": { + "name": "constant.other.systemverilog" + } + } + }, + { + "match": "^\\s*(localparam|parameter)\\s+([a-zA-Z_][a-zA-Z0-9_]*)\\b\\s*(?=(=))", + "name": "meta.param.systemverilog", + "captures": { + "1": { + "name": "keyword.other.systemverilog" + } + } + }, + { + "match": "^\\s*(local\\s+|protected\\s+|localparam\\s+|parameter\\s+)?(const\\s+|virtual\\s+)?(rand\\s+|randc\\s+)?(([a-zA-Z_][a-zA-Z0-9_]*)(::))?([a-zA-Z_][a-zA-Z0-9_]*)\\b\\s*(?=(#\\s*\\([\\w,]+\\)\\s*)?([a-zA-Z][a-zA-Z0-9_\\s\\[\\]']*)(;|,|=|'\\{))", + "name": "meta.userdefined.systemverilog", + "captures": { + "1": { + "name": "keyword.other.systemverilog" + }, + "2": { + "name": "keyword.other.systemverilog" + }, + "3": { + "name": "storage.type.rand.systemverilog" + }, + "5": { + "name": "support.type.scope.systemverilog" + }, + "6": { + "name": "keyword.operator.scope.systemverilog" + }, + "7": { + "name": "storage.type.userdefined.systemverilog" + } + } + }, + { + "match": "\\s*\\b(option)\\.", + "captures": { + "1": { + "name": "keyword.cover.systemverilog" + } + } + }, + { + "match": "\\s*\\b(local|const|protected|virtual|localparam|parameter)\\b", + "captures": { + "1": { + "name": "keyword.other.systemverilog" + } + } + }, + { + "match": "\\s*\\b(rand|randc)\\b", + "name": "storage.type.rand.systemverilog" + }, + { + "begin": "^(\\s*(bind)\\s+([a-zA-Z_][\\w\\.]*))?\\s*([a-zA-Z_][a-zA-Z0-9_]*)\\s*(?=#[^#])", + "beginCaptures": { + "2": { + "name": "keyword.control.systemverilog" + }, + "4": { + "name": "storage.module.systemverilog" + } + }, + "end": "(?=;|=|:)", + "patterns": [ + { + "include": "#module-binding" + }, + { + "include": "#module-param" + }, + { + "include": "#comments" + }, + { + "include": "#operators" + }, + { + "include": "#constants" + }, + { + "include": "#strings" + }, + { + "match": "\\b([a-zA-Z_][a-zA-Z0-9_]*)\\b(?=\\s*(\\(|$))", + "name": "entity.name.type.module.systemverilog" + } + ], + "name": "meta.module.inst.param.systemverilog" + }, + { + "begin": "\\b([a-zA-Z_][a-zA-Z0-9_]*)\\s+(?!intersect|and|or|throughout|within)([a-zA-Z_][a-zA-Z0-9_]*)\\s*(\\[(\\d+)(\\:(\\d+))?\\])?\\s*(\\(|$)", + "beginCaptures": { + "1": { + "name": "storage.module.systemverilog" + }, + "2": { + "name": "entity.name.type.module.systemverilog" + }, + "4": { + "name": "constant.numeric.systemverilog" + }, + "6": { + "name": "constant.numeric.systemverilog" + } + }, + "end": ";", + "patterns": [ + { + "include": "#module-binding" + }, + { + "include": "#comments" + }, + { + "include": "#strings" + }, + { + "include": "#operators" + }, + { + "include": "#constants" + } + ], + "name": "meta.module.inst.systemverilog" + }, + { + "name": "meta.struct.assign.systemverilog", + "begin": "\\b\\s+(=|<|>)", + "name": "keyword.operator.comparison.systemverilog" + }, + { + "match": "(\\-|\\+|\\*|\\/|%)", + "name": "keyword.operator.arithmetic.systemverilog" + }, + { + "match": "(!|&&|\\|\\||\\bor\\b)", + "name": "keyword.operator.logical.systemverilog" + }, + { + "match": "(&|\\||\\^|~|{|'{|}|<<|>>|\\?|:)", + "name": "keyword.operator.bitwise.systemverilog" + }, + { + "match": "(#|@)", + "name": "keyword.operator.other.systemverilog" + } + ] + }, + "comments": { + "patterns": [ + { + "begin": "/\\*", + "captures": { + "0": { + "name": "punctuation.definition.comment.systemverilog" + } + }, + "end": "\\*/", + "name": "comment.block.systemverilog" + }, + { + "captures": { + "1": { + "name": "punctuation.definition.comment.systemverilog" + } + }, + "match": "(//).*$\\n?", + "name": "comment.line.double-slash.systemverilog" + } + ] + }, + "port-dir": { + "patterns": [ + { + "match": "\\s*\\b(output|input|inout|ref)\\s+(([a-zA-Z_][a-zA-Z0-9_]*)(::))?([a-zA-Z_][a-zA-Z0-9_]*)?\\s+(?=\\[[a-zA-Z0-9_\\-\\+]*:[a-zA-Z0-9_\\-\\+]*\\]\\s+[a-zA-Z_][a-zA-Z0-9_\\s]*)", + "captures": { + "1": { + "name": "support.type.systemverilog" + }, + "3": { + "name": "support.type.scope.systemverilog" + }, + "4": { + "name": "keyword.operator.scope.systemverilog" + }, + "5": { + "name": "storage.type.interface.systemverilog" + } + } + }, + { + "match": "\\s*\\b(output|input|inout|ref)\\s+(([a-zA-Z_][a-zA-Z0-9_]*)(::))?([a-zA-Z_][a-zA-Z0-9_]*)?\\s+(?=[a-zA-Z_][a-zA-Z0-9_\\s]*)", + "captures": { + "1": { + "name": "support.type.systemverilog" + }, + "3": { + "name": "support.type.scope.systemverilog" + }, + "4": { + "name": "keyword.operator.scope.systemverilog" + }, + "5": { + "name": "storage.type.interface.systemverilog" + } + } + }, + { + "match": "\\s*\\b(output|input|inout|ref)\\b", + "name": "support.type.systemverilog" + } + ] + }, + "base-grammar": { + "patterns": [ + { + "include": "#all-types" + }, + { + "include": "#comments" + }, + { + "include": "#operators" + }, + { + "include": "#constants" + }, + { + "include": "#strings" + }, + { + "match": "^\\s*([a-zA-Z_][a-zA-Z0-9_]*)\\s+[a-zA-Z_][a-zA-Z0-9_,=\\s]*", + "captures": { + "1": { + "name": "storage.type.interface.systemverilog" + } + } + }, + { + "include": "#storage-scope-systemverilog" + } + ] + }, + "storage-type-systemverilog": { + "patterns": [ + { + "match": "\\s*\\b(var|wire|tri|tri[01]|supply[01]|wand|triand|wor|trior|trireg|reg|integer|int|longint|shortint|logic|bit|byte|shortreal|string|time|realtime|real|process|void)\\b", + "name": "storage.type.systemverilog" + }, + { + "match": "\\s*\\b(uvm_transaction|uvm_component|uvm_monitor|uvm_driver|uvm_test|uvm_env|uvm_object|uvm_agent|uvm_sequence_base|uvm_sequence|uvm_sequence_item|uvm_sequence_state|uvm_sequencer|uvm_sequencer_base|uvm_component_registry|uvm_analysis_imp|uvm_analysis_port|uvm_analysis_export|uvm_config_db|uvm_active_passive_enum|uvm_phase|uvm_verbosity|uvm_tlm_analysis_fifo|uvm_tlm_fifo|uvm_report_server|uvm_objection|uvm_recorder|uvm_domain|uvm_reg_field|uvm_reg|uvm_reg_block|uvm_bitstream_t|uvm_radix_enum|uvm_printer|uvm_packer|uvm_comparer|uvm_scope_stack)\\b", + "name": "storage.type.uvm.systemverilog" + } + ] + }, + "storage-scope-systemverilog": { + "match": "\\b([a-zA-Z_][a-zA-Z0-9_]*)(::)", + "captures": { + "1": { + "name": "support.type.systemverilog" + }, + "2": { + "name": "keyword.operator.scope.systemverilog" + } + }, + "name": "meta.scope.systemverilog" + }, + "storage-modifier-systemverilog": { + "match": "\\b(signed|unsigned|small|medium|large|supply[01]|strong[01]|pull[01]|weak[01]|highz[01])\\b", + "name": "storage.modifier.systemverilog" + }, + "ifmodport": { + "match": "\\b([a-zA-Z_][a-zA-Z0-9_]*)\\.([a-zA-Z_][a-zA-Z0-9_]*)\\s+([a-zA-Z_][a-zA-Z0-9_]*)\\b", + "captures": { + "1": { + "name": "storage.type.interface.systemverilog" + }, + "2": { + "name": "support.modport.systemverilog" + } + } + }, + "strings": { + "patterns": [ + { + "begin": "\"", + "beginCaptures": { + "0": { + "name": "punctuation.definition.string.begin.systemverilog" + } + }, + "end": "\"", + "endCaptures": { + "0": { + "name": "punctuation.definition.string.end.systemverilog" + } + }, + "name": "string.quoted.double.systemverilog", + "patterns": [ + { + "match": "\\\\.", + "name": "constant.character.escape.systemverilog" + }, + { + "match": "(?x)%\n\t\t\t\t\t\t\t\t\t\t(\\d+\\$)? # field (argument #)\n\t\t\t\t\t\t\t\t\t\t[#0\\- +']* # flags\n\t\t\t\t\t\t\t\t\t\t[,;:_]? # separator character (AltiVec)\n\t\t\t\t\t\t\t\t\t\t((-?\\d+)|\\*(-?\\d+\\$)?)? # minimum field width\n\t\t\t\t\t\t\t\t\t\t(\\.((-?\\d+)|\\*(-?\\d+\\$)?)?)? # precision\n\t\t\t\t\t\t\t\t\t\t(hh|h|ll|l|j|t|z|q|L|vh|vl|v|hv|hl)? # length modifier\n\t\t\t\t\t\t\t\t\t\t[bdiouxXhHDOUeEfFgGaACcSspnmt%] # conversion type\n\t\t\t\t\t\t\t\t\t", + "name": "constant.other.placeholder.systemverilog" + }, + { + "match": "%", + "name": "invalid.illegal.placeholder.systemverilog" + } + ] + } + ] + }, + "module-binding": { + "begin": "\\.([a-zA-Z_][a-zA-Z0-9_]*)\\s*\\(", + "beginCaptures": { + "1": { + "name": "support.function.port.systemverilog" + } + }, + "end": "\\)", + "patterns": [ + { + "include": "#constants" + }, + { + "include": "#comments" + }, + { + "include": "#operators" + }, + { + "include": "#strings" + }, + { + "include": "#constants" + }, + { + "match": "\\b([a-zA-Z_]\\w*)(::)", + "captures": { + "1": { + "name": "support.type.scope.systemverilog" + }, + "2": { + "name": "keyword.operator.scope.systemverilog" + } + } + }, + { + "match": "\\b([a-zA-Z_]\\w*)(')", + "captures": { + "1": { + "name": "storage.type.interface.systemverilog" + }, + "2": { + "name": "keyword.operator.cast.systemverilog" + } + } + }, + { + "match": "\\$\\b([a-zA-Z_][a-zA-Z0-9_]*)\\b", + "name": "support.function.systemverilog" + }, + { + "match": "\\b(virtual)\\b", + "name": "keyword.control.systemverilog" + } + ], + "match": "\\.([a-zA-Z_][a-zA-Z0-9_]*)\\s*", + "captures": { + "1": { + "name": "support.function.port.implicit.systemverilog" + } + } + }, + "module-param": { + "name": "meta.module-param.systemverilog", + "begin": "(#)\\s*\\(", + "beginCaptures": { + "1": { + "name": "keyword.operator.param.systemverilog" + } + }, + "end": "\\)", + "patterns": [ + { + "include": "#comments" + }, + { + "include": "#constants" + }, + { + "include": "#operators" + }, + { + "include": "#strings" + }, + { + "include": "#module-binding" + }, + { + "match": "\\b(virtual)\\b", + "name": "keyword.control.systemverilog" + } + ] + }, + "struct-anonymous": { + "begin": "\\s*\\b(struct|union)\\s*(packed)?\\s*", + "beginCaptures": { + "1": { + "name": "keyword.control.systemverilog" + }, + "2": { + "name": "keyword.control.systemverilog" + } + }, + "end": "(})\\s*([a-zA-Z_]\\w*)\\s*;", + "endCaptures": { + "1": { + "name": "keyword.operator.other.systemverilog" + } + }, + "patterns": [ + { + "include": "#base-grammar" + } + ], + "name": "meta.struct.anonymous.systemverilog" + } + }, + "scopeName": "source.systemverilog", + "uuid": "789be04c-8b74-352e-8f37-63d336001277" +} \ No newline at end of file