From a9ad3ae1860da314211dbe29ef6171325ce5968c Mon Sep 17 00:00:00 2001 From: DaniPopes <57450786+DaniPopes@users.noreply.github.com> Date: Tue, 18 Apr 2023 09:40:36 +0200 Subject: [PATCH] chore: update solang-parser (#4661) * wip update solang * remove Chisel check * update patch section * bump * update patch * update patch to git * bump ethers * add repro * add tracing and move tests to tests/it/ * cargo update * add CodeLocationExt * patch --------- Co-authored-by: Matthias Seitz --- Cargo.lock | 665 ++++++++++++------------- Cargo.toml | 12 +- chisel/Cargo.toml | 2 +- chisel/src/executor.rs | 2 +- chisel/src/solidity_helper.rs | 15 +- cli/Cargo.toml | 2 +- cli/src/cmd/forge/geiger/visitor.rs | 2 +- doc/Cargo.toml | 2 +- doc/src/lib.rs | 2 +- doc/src/writer/as_doc.rs | 4 +- doc/src/writer/as_string.rs | 242 --------- doc/src/writer/buf_writer.rs | 4 +- doc/src/writer/mod.rs | 2 - fmt/Cargo.toml | 4 +- fmt/src/buffer.rs | 4 +- fmt/src/comments.rs | 5 +- fmt/src/formatter.rs | 412 +++++---------- fmt/src/helpers.rs | 7 +- fmt/src/lib.rs | 3 + fmt/src/solang_ext/ast_eq.rs | 30 +- fmt/src/solang_ext/attr_sort_key.rs | 64 --- fmt/src/solang_ext/is_empty.rs | 25 - fmt/src/solang_ext/loc.rs | 553 ++++---------------- fmt/src/solang_ext/mod.rs | 33 +- fmt/src/solang_ext/operator.rs | 242 --------- fmt/src/solang_ext/safe_unwrap.rs | 54 +- fmt/src/visit.rs | 15 +- fmt/testdata/IfStatement/fmt.sol | 4 +- fmt/testdata/IfStatement2/fmt.sol | 7 + fmt/testdata/IfStatement2/original.sol | 10 + fmt/tests/it/formatter.rs | 202 ++++++++ fmt/tests/it/main.rs | 1 + 32 files changed, 900 insertions(+), 1731 deletions(-) delete mode 100644 doc/src/writer/as_string.rs delete mode 100644 fmt/src/solang_ext/attr_sort_key.rs delete mode 100644 fmt/src/solang_ext/is_empty.rs delete mode 100644 fmt/src/solang_ext/operator.rs create mode 100644 fmt/testdata/IfStatement2/fmt.sol create mode 100644 fmt/testdata/IfStatement2/original.sol create mode 100644 fmt/tests/it/formatter.rs create mode 100644 fmt/tests/it/main.rs diff --git a/Cargo.lock b/Cargo.lock index 574320f9a7dc..58a7628a794a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -56,7 +56,7 @@ version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fcb51a0695d8f838b1ee009b3fbf66bda078cd64590202a864a8f3e8c4315c47" dependencies = [ - "getrandom 0.2.8", + "getrandom 0.2.9", "once_cell", "version_check", ] @@ -111,42 +111,51 @@ checksum = "4b46cbb362ab8752921c97e041f5e366ee6297bd428a31275b9fcf1e380f7299" [[package]] name = "anstream" -version = "0.2.6" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "342258dd14006105c2b75ab1bd7543a03bdf0cfc94383303ac212a04939dff6f" +checksum = "9e579a7752471abc2a8268df8b20005e3eadd975f585398f17efcfd8d4927371" dependencies = [ "anstyle", "anstyle-parse", + "anstyle-query", "anstyle-wincon", - "concolor-override", - "concolor-query", + "colorchoice", "is-terminal", "utf8parse", ] [[package]] name = "anstyle" -version = "0.3.5" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "23ea9e81bd02e310c216d080f6223c179012256e5151c41db88d12c88a1684d2" +checksum = "41ed9a86bf92ae6580e0a31281f65a1b1d867c0cc68d5346e2ae128dddfa6a7d" [[package]] name = "anstyle-parse" -version = "0.1.1" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a7d1bb534e9efed14f3e5f44e7dd1a4f709384023a4165199a4241e18dff0116" +checksum = "e765fd216e48e067936442276d1d57399e37bce53c264d6fefbe298080cb57ee" dependencies = [ "utf8parse", ] +[[package]] +name = "anstyle-query" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5ca11d4be1bab0c8bc8734a9aa7bf4ee8316d462a08c6ac5052f888fef5b494b" +dependencies = [ + "windows-sys 0.48.0", +] + [[package]] name = "anstyle-wincon" -version = "0.2.0" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3127af6145b149f3287bb9a0d10ad9c5692dba8c53ad48285e5bec4063834fa" +checksum = "4bcd8291a340dd8ac70e18878bc4501dd7b4ff970cfa21c207d36ece51ea88fd" dependencies = [ "anstyle", - "windows-sys 0.45.0", + "windows-sys 0.48.0", ] [[package]] @@ -161,7 +170,7 @@ dependencies = [ "axum", "bytes", "chrono", - "clap 4.2.1", + "clap 4.2.2", "clap_complete", "clap_complete_fig", "crc 3.0.1", @@ -230,7 +239,7 @@ dependencies = [ "async-trait", "axum", "bytes", - "clap 4.2.1", + "clap 4.2.2", "futures", "hyper", "parity-tokio-ipc", @@ -304,7 +313,7 @@ checksum = "0e97ce7de6cf12de5d7226c73f5ba9811622f4db3a5b91b55c53e987e5f91cba" dependencies = [ "proc-macro2", "quote", - "syn 2.0.11", + "syn 2.0.15", ] [[package]] @@ -315,7 +324,7 @@ checksum = "b9ccdd8f2a161be9bd5c023df56f1b2a0bd1d83872ae53b71a84a12c9bf6e842" dependencies = [ "proc-macro2", "quote", - "syn 2.0.11", + "syn 2.0.15", ] [[package]] @@ -648,9 +657,9 @@ dependencies = [ [[package]] name = "cargo_metadata" -version = "0.15.3" +version = "0.15.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08a1ec454bc3eead8719cb56e15dbbfecdbc14e4b3a3ae4936cc6e31f5fc0d07" +checksum = "eee4243f1f26fc7a42710e7439c149e2b10b05472f88090acce52632f231a73a" dependencies = [ "camino", "cargo-platform", @@ -722,7 +731,7 @@ name = "chisel" version = "0.1.1" dependencies = [ "bytes", - "clap 4.2.1", + "clap 4.2.2", "criterion", "dirs 5.0.0", "ethers", @@ -832,9 +841,9 @@ dependencies = [ [[package]] name = "clap" -version = "4.2.1" +version = "4.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "046ae530c528f252094e4a77886ee1374437744b2bff1497aa898bbddbbb29b3" +checksum = "9b802d85aaf3a1cdb02b224ba472ebdea62014fccfcb269b95a4d76443b5ee5a" dependencies = [ "clap_builder", "clap_derive 4.2.0", @@ -843,9 +852,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.2.1" +version = "4.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "223163f58c9a40c3b0a43e1c4b50a9ce09f007ea2cb1ec258a687945b4b7929f" +checksum = "14a1a858f532119338887a4b8e1af9c60de8249cd7bafd68036a489e261e37b6" dependencies = [ "anstream", "anstyle", @@ -853,7 +862,7 @@ dependencies = [ "clap_lex 0.4.1", "once_cell", "strsim", - "terminal_size 0.2.5", + "terminal_size 0.2.6", "unicase", "unicode-width", ] @@ -864,7 +873,7 @@ version = "4.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "01c22dcfb410883764b29953103d9ef7bb8fe21b3fa1158bc99986c2067294bd" dependencies = [ - "clap 4.2.1", + "clap 4.2.2", ] [[package]] @@ -873,7 +882,7 @@ version = "4.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f3af28956330989baa428ed4d3471b853715d445c62de21b67292e22cf8a41fa" dependencies = [ - "clap 4.2.1", + "clap 4.2.2", "clap_complete", ] @@ -899,7 +908,7 @@ dependencies = [ "heck", "proc-macro2", "quote", - "syn 2.0.11", + "syn 2.0.15", ] [[package]] @@ -919,9 +928,9 @@ checksum = "8a2dd5a6fe8c6e3502f568a6353e5273bbb15193ad9a89e457b9970798efbea1" [[package]] name = "clearscreen" -version = "2.0.0" +version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "41aa24cc5e1d6b3fc49ad4cd540b522fedcbe88bc6f259ff16e20e7010b6f8c7" +checksum = "72f3f22f1a586604e62efd23f78218f3ccdecf7a33c4500db2d37d85a24fe994" dependencies = [ "nix", "terminfo", @@ -961,9 +970,9 @@ dependencies = [ "bs58", "coins-core", "digest 0.10.6", - "getrandom 0.2.8", + "getrandom 0.2.9", "hmac 0.12.1", - "k256 0.13.0", + "k256 0.13.1", "lazy_static", "serde", "sha2 0.10.6", @@ -972,21 +981,19 @@ dependencies = [ [[package]] name = "coins-bip39" -version = "0.8.3" +version = "0.8.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "efb68f3b6c3fee83828ecd8d463f360a397c32aaeb35bd931c01e5ddf5631c69" +checksum = "84f4d04ee18e58356accd644896aeb2094ddeafb6a713e056cef0c0a8e468c15" dependencies = [ "bitvec 0.17.4", "coins-bip32", - "getrandom 0.2.8", - "hex", + "getrandom 0.2.9", "hmac 0.12.1", "once_cell", "pbkdf2 0.12.1", "rand 0.8.5", "sha2 0.10.6", "thiserror", - "tracing", ] [[package]] @@ -1062,6 +1069,12 @@ dependencies = [ "tracing-error", ] +[[package]] +name = "colorchoice" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "acbf1af155f9b9ef647e42cdc158db4b64a1b61f743629225fde6f3e0be2a7c7" + [[package]] name = "comfy-table" version = "6.1.4" @@ -1086,21 +1099,6 @@ dependencies = [ "winapi", ] -[[package]] -name = "concolor-override" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a855d4a1978dc52fb0536a04d384c2c0c1aa273597f08b77c8c4d3b2eec6037f" - -[[package]] -name = "concolor-query" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "88d11d52c3d7ca2e6d0040212be9e4dbbcd78b6447f535b6b561f449427944cf" -dependencies = [ - "windows-sys 0.45.0", -] - [[package]] name = "console" version = "0.14.1" @@ -1147,15 +1145,6 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6245d59a3e82a7fc217c5828a6692dbc6dfb63a0c8c90495621f7b9d79704a0e" -[[package]] -name = "convert_case" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec182b0ca2f35d8fc196cf3404988fd8b8c739a4d270ff118a398feb0cbec1ca" -dependencies = [ - "unicode-segmentation", -] - [[package]] name = "core-foundation" version = "0.9.3" @@ -1168,9 +1157,9 @@ dependencies = [ [[package]] name = "core-foundation-sys" -version = "0.8.3" +version = "0.8.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5827cebf4670468b8772dd191856768aedcb1b0278a04f989f7766351917b9dc" +checksum = "e496a50fda8aacccc86d7529e2c1e0892dbd0f898a6b5645b5561b89c3210efa" [[package]] name = "cpufeatures" @@ -1254,9 +1243,9 @@ dependencies = [ [[package]] name = "crossbeam-channel" -version = "0.5.7" +version = "0.5.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf2b3e8478797446514c91ef04bafcb59faba183e621ad488df88983cc14128c" +checksum = "a33c2bf77f2df06183c3aa30d1e96c0695a313d4f9c453cc3762a6db39f99200" dependencies = [ "cfg-if", "crossbeam-utils", @@ -1467,7 +1456,7 @@ dependencies = [ "proc-macro2", "quote", "scratch", - "syn 2.0.11", + "syn 2.0.15", ] [[package]] @@ -1484,7 +1473,7 @@ checksum = "2345488264226bf682893e25de0769f3360aac9957980ec49361b083ddaa5bc5" dependencies = [ "proc-macro2", "quote", - "syn 2.0.11", + "syn 2.0.15", ] [[package]] @@ -1511,9 +1500,9 @@ dependencies = [ [[package]] name = "der" -version = "0.7.1" +version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc906908ea6458456e5eaa160a9c08543ec3d1e6f71e2235cedd660cb65f9df0" +checksum = "82b10af9f9f9f2134a42d3f8aa74658660f2e0234b0eb81bd171df8aa32779ed" dependencies = [ "const-oid", "zeroize", @@ -1525,7 +1514,7 @@ version = "0.99.17" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4fb810d30a7c1953f91334de7244731fc3f3c10d7fe163338a35b9f640960321" dependencies = [ - "convert_case 0.4.0", + "convert_case", "proc-macro2", "quote", "rustc_version", @@ -1546,9 +1535,9 @@ dependencies = [ [[package]] name = "dialoguer" -version = "0.10.3" +version = "0.10.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af3c796f3b0b408d9fd581611b47fa850821fcb84aa640b83a3c1a5be2d691f2" +checksum = "59c6f2989294b9a498d3ad5491a79c6deb604617378e1cdc4bfc1c1361fe2f87" dependencies = [ "console 0.15.5", "shell-words", @@ -1576,6 +1565,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8168378f4e5023e7218c89c891c0fd8ecdb5e5e4f18cb78f38cf245dd021e76f" dependencies = [ "block-buffer 0.10.4", + "const-oid", "crypto-common", "subtle", ] @@ -1667,14 +1657,15 @@ dependencies = [ [[package]] name = "ecdsa" -version = "0.16.2" +version = "0.16.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "644d3b8674a5fc5b929ae435bca85c2323d85ccb013a5509c2ac9ee11a6284ba" +checksum = "a48e5d537b8a30c0b023116d981b16334be1485af7ca68db3a2b7024cbc957fd" dependencies = [ - "der 0.7.1", - "elliptic-curve 0.13.2", + "der 0.7.3", + "digest 0.10.6", + "elliptic-curve 0.13.4", "rfc6979 0.4.0", - "signature 2.0.0", + "signature 2.1.0", ] [[package]] @@ -1716,9 +1707,9 @@ dependencies = [ [[package]] name = "elliptic-curve" -version = "0.13.2" +version = "0.13.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ea5a92946e8614bb585254898bb7dd1ddad241ace60c52149e3765e34cc039d" +checksum = "75c71eaa367f2e5d556414a8eea812bc62985c879748d6403edabd9cb03f16e7" dependencies = [ "base16ct 0.2.0", "crypto-bigint 0.5.1", @@ -1728,7 +1719,7 @@ dependencies = [ "group 0.13.0", "pkcs8", "rand_core 0.6.4", - "sec1 0.7.1", + "sec1 0.7.2", "subtle", "zeroize", ] @@ -1772,7 +1763,7 @@ dependencies = [ "base64 0.13.1", "bytes", "hex", - "k256 0.13.0", + "k256 0.13.1", "log", "rand 0.8.5", "rlp", @@ -1796,24 +1787,13 @@ dependencies = [ [[package]] name = "errno" -version = "0.2.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f639046355ee4f37944e44f60642c6f3a7efa3cf6b78c78a0d989a8ce6c396a1" -dependencies = [ - "errno-dragonfly", - "libc", - "winapi", -] - -[[package]] -name = "errno" -version = "0.3.0" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "50d6a0976c999d473fe89ad888d5a284e55366d9dc9038b1ba2aa15128c4afa0" +checksum = "4bcfec3a70f97c962c307b2d2c56e358cf1d00b558d74262b5f929ee8cc7e73a" dependencies = [ "errno-dragonfly", "libc", - "windows-sys 0.45.0", + "windows-sys 0.48.0", ] [[package]] @@ -1921,9 +1901,9 @@ dependencies = [ [[package]] name = "ethers" -version = "2.0.2" +version = "2.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "697aba1bec98cb86e7bebd69f9bb365218871464137af9e93e7a72bd6dc421d0" +checksum = "356eaf2e3947efa975c3f953e33f73193e5e21b9d8bab26c3ca532676931696f" dependencies = [ "ethers-addressbook", "ethers-contract", @@ -1937,9 +1917,9 @@ dependencies = [ [[package]] name = "ethers-addressbook" -version = "2.0.2" +version = "2.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0b603812e5e4d63521c691cbc1f34743879e96a1ee96c6594639d7fa0cf6fbc" +checksum = "d56f1c92cb7c406794c8324158da4caf9e54018e28b776df8155085e1d06db75" dependencies = [ "ethers-core", "once_cell", @@ -1949,9 +1929,9 @@ dependencies = [ [[package]] name = "ethers-contract" -version = "2.0.2" +version = "2.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b4e8ed7c2b2a22e07b65ae0eb426c948a7448f1be15c66e4813e02c423751fc9" +checksum = "2a328cb42014ac0ac577a8dac32eb658ee0f32b5a9a5317a0329ac1d4201f1c6" dependencies = [ "ethers-contract-abigen", "ethers-contract-derive", @@ -1968,16 +1948,16 @@ dependencies = [ [[package]] name = "ethers-contract-abigen" -version = "2.0.2" +version = "2.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bf0984f4ec4e267fd27b7c9fa2f73e72c5c98491a73f777290654154d104f723" +checksum = "d96813e4b58b6c6b817367380db900dddbd67bfe27610ec89fd3263778d5a4aa" dependencies = [ "Inflector", "dunce", "ethers-core", "ethers-etherscan", "eyre", - "getrandom 0.2.8", + "getrandom 0.2.9", "hex", "prettyplease", "proc-macro2", @@ -1986,7 +1966,7 @@ dependencies = [ "reqwest", "serde", "serde_json", - "syn 1.0.109", + "syn 2.0.15", "tokio", "toml 0.7.3", "url", @@ -1995,45 +1975,45 @@ dependencies = [ [[package]] name = "ethers-contract-derive" -version = "2.0.2" +version = "2.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "914e9211077a1b590af1ee6b8dfbd54515c808119546c95da69479908dc3d4de" +checksum = "373068bb24b4dea8fe0d1758aadab2dd4ec9de1d2c28316439cadcda3ed48eae" dependencies = [ + "Inflector", "ethers-contract-abigen", "ethers-core", "hex", "proc-macro2", "quote", - "syn 1.0.109", + "serde_json", + "syn 2.0.15", ] [[package]] name = "ethers-core" -version = "2.0.2" +version = "2.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "40bf114f1017ace0f622f1652f59c2c5e1abfe7d88891cca0c43da979b351de0" +checksum = "3a5f8f85ba96698eab9a4782ed2215d0979b1981b99f1be0726c200ffdac22f5" dependencies = [ "arrayvec", "bytes", "cargo_metadata", "chrono", - "convert_case 0.6.0", - "elliptic-curve 0.13.2", + "elliptic-curve 0.13.4", "ethabi", "generic-array", - "getrandom 0.2.8", + "getrandom 0.2.9", "hex", - "k256 0.13.0", - "num_enum", + "k256 0.13.1", + "num_enum 0.6.1", "once_cell", "open-fastrlp", - "proc-macro2", "rand 0.8.5", "rlp", "serde", "serde_json", "strum", - "syn 1.0.109", + "syn 2.0.15", "tempfile", "thiserror", "tiny-keccak", @@ -2042,13 +2022,13 @@ dependencies = [ [[package]] name = "ethers-etherscan" -version = "2.0.2" +version = "2.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8920b59cf81e357df2c8102d6a9dc81c2d68f7409543ff3b6868851ecf007807" +checksum = "7cfc3d36be9e16bac241e1d59ec9ace00e8e4241c09f604a0f65158eb37d4878" dependencies = [ "ethers-core", "ethers-solc", - "getrandom 0.2.8", + "getrandom 0.2.9", "reqwest", "semver", "serde", @@ -2059,9 +2039,9 @@ dependencies = [ [[package]] name = "ethers-middleware" -version = "2.0.2" +version = "2.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c54b30f67c1883ed68bd38aedbdd321831382c12e1b95089c8261c79bb85e4da" +checksum = "1e6f3543b4f6679b2558901c4b323cecb06b19239439d2588fa8b489bac9675d" dependencies = [ "async-trait", "auto_impl", @@ -2086,9 +2066,9 @@ dependencies = [ [[package]] name = "ethers-providers" -version = "2.0.2" +version = "2.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c2fa0857eaad0c1678f982a2f4cfbe33ebd51d273cc93de0182b7c693f2a84a1" +checksum = "7c9d2cbed43cf618004dbe339e389e10dae46ea8e55872ab63a25fad25a6082a" dependencies = [ "async-trait", "auto_impl", @@ -2100,7 +2080,7 @@ dependencies = [ "futures-core", "futures-timer", "futures-util", - "getrandom 0.2.8", + "getrandom 0.2.9", "hashers", "hex", "http", @@ -2125,15 +2105,15 @@ dependencies = [ [[package]] name = "ethers-signers" -version = "2.0.2" +version = "2.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5caa7cad4f444931d0ed45818e609847781582399eff0be5c089e8666475c7fb" +checksum = "d56871f70b97cc5cced5c39c88a0196c206d8f7fb8e1e0952fbf1fb73c033219" dependencies = [ "async-trait", "coins-bip32", "coins-bip39", "coins-ledger", - "elliptic-curve 0.13.2", + "elliptic-curve 0.13.4", "eth-keystore", "ethers-core", "futures-executor", @@ -2153,16 +2133,16 @@ dependencies = [ [[package]] name = "ethers-solc" -version = "2.0.2" +version = "2.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "139542f51f4c405d0dd7e97c34232140a14e8744d1cf121777355567187259e4" +checksum = "6e967e60bca8fc83d640a7aebd1492d625c43e86b88a5a5bb08b1019472d5d6b" dependencies = [ "cfg-if", "dunce", "ethers-core", "fs_extra", "futures-util", - "getrandom 0.2.8", + "getrandom 0.2.9", "glob", "hex", "home", @@ -2250,13 +2230,13 @@ dependencies = [ [[package]] name = "fd-lock" -version = "3.0.11" +version = "3.0.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9799aefb4a2e4a01cc47610b1dd47c18ab13d991f27bbcaed9296f5a53d5cbad" +checksum = "39ae6b3d9530211fb3b12a95374b8b0823be812f53d09e18c5675c0146b09642" dependencies = [ "cfg-if", - "rustix 0.37.5", - "windows-sys 0.45.0", + "rustix", + "windows-sys 0.48.0", ] [[package]] @@ -2306,14 +2286,14 @@ dependencies = [ [[package]] name = "filetime" -version = "0.2.20" +version = "0.2.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a3de6e8d11b22ff9edc6d916f890800597d60f8b2da1caf2955c274638d6412" +checksum = "5cbc844cecaee9d4443931972e1289c8ff485cb4cc2767cb03ca139ed6885153" dependencies = [ "cfg-if", "libc", "redox_syscall 0.2.16", - "windows-sys 0.45.0", + "windows-sys 0.48.0", ] [[package]] @@ -2399,7 +2379,7 @@ version = "0.1.0" dependencies = [ "assert_matches", "auto_impl", - "clap 4.2.1", + "clap 4.2.2", "derive_more", "ethers-core", "ethers-solc", @@ -2434,6 +2414,8 @@ dependencies = [ "solang-parser", "thiserror", "toml 0.7.3", + "tracing", + "tracing-subscriber", ] [[package]] @@ -2468,14 +2450,14 @@ dependencies = [ "async-trait", "bytes", "cast 0.2.0", - "clap 4.2.1", + "clap 4.2.2", "clap_complete", "clap_complete_fig", "color-eyre", "comfy-table", "console 0.15.5", "criterion", - "dialoguer 0.10.3", + "dialoguer 0.10.4", "dotenvy", "dunce", "ethers", @@ -2550,7 +2532,7 @@ dependencies = [ name = "foundry-common" version = "0.1.0" dependencies = [ - "clap 4.2.1", + "clap 4.2.2", "comfy-table", "dunce", "ethers-core", @@ -2653,7 +2635,7 @@ version = "0.0.0" dependencies = [ "proc-macro2", "quote", - "syn 2.0.11", + "syn 2.0.15", ] [[package]] @@ -2729,9 +2711,9 @@ dependencies = [ [[package]] name = "futures" -version = "0.3.27" +version = "0.3.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "531ac96c6ff5fd7c62263c5e3c67a603af4fcaee2e1a0ae5565ba3a11e69e549" +checksum = "23342abe12aba583913b2e62f22225ff9c950774065e4bfb61a19cd9770fec40" dependencies = [ "futures-channel", "futures-core", @@ -2744,9 +2726,9 @@ dependencies = [ [[package]] name = "futures-channel" -version = "0.3.27" +version = "0.3.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "164713a5a0dcc3e7b4b1ed7d3b433cabc18025386f9339346e8daf15963cf7ac" +checksum = "955518d47e09b25bbebc7a18df10b81f0c766eaf4c4f1cccef2fca5f2a4fb5f2" dependencies = [ "futures-core", "futures-sink", @@ -2754,15 +2736,15 @@ dependencies = [ [[package]] name = "futures-core" -version = "0.3.27" +version = "0.3.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "86d7a0c1aa76363dac491de0ee99faf6941128376f1cf96f07db7603b7de69dd" +checksum = "4bca583b7e26f571124fe5b7561d49cb2868d79116cfa0eefce955557c6fee8c" [[package]] name = "futures-executor" -version = "0.3.27" +version = "0.3.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1997dd9df74cdac935c76252744c1ed5794fac083242ea4fe77ef3ed60ba0f83" +checksum = "ccecee823288125bd88b4d7f565c9e58e41858e47ab72e8ea2d64e93624386e0" dependencies = [ "futures-core", "futures-task", @@ -2771,9 +2753,9 @@ dependencies = [ [[package]] name = "futures-io" -version = "0.3.27" +version = "0.3.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89d422fa3cbe3b40dca574ab087abb5bc98258ea57eea3fd6f1fa7162c778b91" +checksum = "4fff74096e71ed47f8e023204cfd0aa1289cd54ae5430a9523be060cdb849964" [[package]] name = "futures-locks" @@ -2787,26 +2769,26 @@ dependencies = [ [[package]] name = "futures-macro" -version = "0.3.27" +version = "0.3.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3eb14ed937631bd8b8b8977f2c198443447a8355b6e3ca599f38c975e5a963b6" +checksum = "89ca545a94061b6365f2c7355b4b32bd20df3ff95f02da9329b34ccc3bd6ee72" dependencies = [ "proc-macro2", "quote", - "syn 1.0.109", + "syn 2.0.15", ] [[package]] name = "futures-sink" -version = "0.3.27" +version = "0.3.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec93083a4aecafb2a80a885c9de1f0ccae9dbd32c2bb54b0c3a65690e0b8d2f2" +checksum = "f43be4fe21a13b9781a69afa4985b0f6ee0e1afab2c6f454a8cf30e2b2237b6e" [[package]] name = "futures-task" -version = "0.3.27" +version = "0.3.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fd65540d33b37b16542a0438c12e6aeead10d4ac5d05bd3f805b8f35ab592879" +checksum = "76d3d132be6c0e6aa1534069c705a74a5997a356c0dc2f86a47765e5617c5b65" [[package]] name = "futures-timer" @@ -2820,9 +2802,9 @@ dependencies = [ [[package]] name = "futures-util" -version = "0.3.27" +version = "0.3.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3ef6b17e481503ec85211fed8f39d1970f128935ca1f814cd32ac4a6842e84ab" +checksum = "26b01e40b772d54cf6c6d721c1d1abd0647a0106a12ecaa1c186273392a69533" dependencies = [ "futures-channel", "futures-core", @@ -2869,9 +2851,9 @@ dependencies = [ [[package]] name = "getrandom" -version = "0.2.8" +version = "0.2.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c05aeb6a22b8f62540c194aac980f2115af067bfe15a0734d7277a768d396b31" +checksum = "c85e1d9ab2eadba7e5040d4e09cbd6d072b76a557ad64e797c2cb9d4da21d7e4" dependencies = [ "cfg-if", "js-sys", @@ -2909,7 +2891,7 @@ dependencies = [ "btoi", "gix-date", "itoa", - "nom 7.1.3", + "nom", "thiserror", ] @@ -2927,7 +2909,7 @@ dependencies = [ "gix-ref", "gix-sec", "memchr", - "nom 7.1.3", + "nom", "once_cell", "smallvec", "thiserror", @@ -2936,9 +2918,9 @@ dependencies = [ [[package]] name = "gix-config-value" -version = "0.10.1" +version = "0.10.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "693d4a4ba0531e46fe558459557a5b29fb86c3e4b2666c1c0861d93c7c678331" +checksum = "d09154c0c8677e4da0ec35e896f56ee3e338e741b9599fae06075edd83a4081c" dependencies = [ "bitflags", "bstr", @@ -2983,9 +2965,9 @@ dependencies = [ [[package]] name = "gix-hash" -version = "0.10.3" +version = "0.10.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c0c5a9f4d621d4f4ea046bb331df5c746ca735b8cae5b234cc2be70ee4dbef0" +checksum = "2a258595457bc192d1f1c59d0d168a1e34e2be9b97a614e14995416185de41a7" dependencies = [ "hex", "thiserror", @@ -3016,16 +2998,16 @@ dependencies = [ "gix-validate", "hex", "itoa", - "nom 7.1.3", + "nom", "smallvec", "thiserror", ] [[package]] name = "gix-path" -version = "0.7.2" +version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f6c104a66dec149cb8f7aaafc6ab797654cf82d67f050fd0cb7e7294e328354b" +checksum = "32370dce200bb951df013e03dff35b4233fc7a89458642b047629b91734a7e19" dependencies = [ "bstr", "thiserror", @@ -3046,7 +3028,7 @@ dependencies = [ "gix-tempfile", "gix-validate", "memmap2", - "nom 7.1.3", + "nom", "thiserror", ] @@ -3140,9 +3122,9 @@ dependencies = [ [[package]] name = "h2" -version = "0.3.16" +version = "0.3.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5be7b54589b581f624f566bf5d8eb2bab1db736c51528720b6bd36b96b55924d" +checksum = "66b91535aa35fea1523ad1b86cb6b53c28e0ae566ba4a460f4457e936cad7c6f" dependencies = [ "bytes", "fnv", @@ -3386,9 +3368,9 @@ checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4" [[package]] name = "hyper" -version = "0.14.25" +version = "0.14.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cc5e554ff619822309ffd57d8734d77cd5ce6238bc956f037ea06c58238c9899" +checksum = "ab302d72a6f11a3b910431ff93aae7e773078c769f0a3ef15fb9ec692ed147d4" dependencies = [ "bytes", "futures-channel", @@ -3438,16 +3420,16 @@ dependencies = [ [[package]] name = "iana-time-zone" -version = "0.1.55" +version = "0.1.56" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "716f12fbcfac6ffab0a5e9ec51d0a0ff70503742bb2dc7b99396394c9dc323f0" +checksum = "0722cd7114b7de04316e7ea5456a0bbb20e4adb46fd27a3697adb812cff0f37c" dependencies = [ "android_system_properties", "core-foundation-sys", "iana-time-zone-haiku", "js-sys", "wasm-bindgen", - "windows 0.47.0", + "windows 0.48.0", ] [[package]] @@ -3627,13 +3609,13 @@ dependencies = [ [[package]] name = "io-lifetimes" -version = "1.0.9" +version = "1.0.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09270fd4fa1111bc614ed2246c7ef56239a3063d5be0d1ec3b589c505d400aeb" +checksum = "9c66c74d2ae7e79a5a8f7ac924adbe38ee42a859c6539ad869eb51f0b52dc220" dependencies = [ "hermit-abi 0.3.1", "libc", - "windows-sys 0.45.0", + "windows-sys 0.48.0", ] [[package]] @@ -3644,14 +3626,14 @@ checksum = "12b6ee2129af8d4fb011108c73d99a1b83a85977f23b82460c0ae2e25bb4b57f" [[package]] name = "is-terminal" -version = "0.4.6" +version = "0.4.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "256017f749ab3117e93acb91063009e1f1bb56d03965b14c2c8df4eb02c524d8" +checksum = "adcf93614601c8129ddf72e2d5633df827ba6551541c6d8c59520a371475be1f" dependencies = [ "hermit-abi 0.3.1", "io-lifetimes", - "rustix 0.37.5", - "windows-sys 0.45.0", + "rustix", + "windows-sys 0.48.0", ] [[package]] @@ -3713,16 +3695,16 @@ dependencies = [ [[package]] name = "k256" -version = "0.13.0" +version = "0.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "955890845095ccf31ef83ad41a05aabb4d8cc23dc3cac5a9f5c89cf26dd0da75" +checksum = "cadb76004ed8e97623117f3df85b17aaa6626ab0b0831e6573f104df16cd1bcc" dependencies = [ "cfg-if", - "ecdsa 0.16.2", - "elliptic-curve 0.13.2", + "ecdsa 0.16.6", + "elliptic-curve 0.13.4", "once_cell", "sha2 0.10.6", - "signature 2.0.0", + "signature 2.1.0", ] [[package]] @@ -3808,9 +3790,9 @@ dependencies = [ [[package]] name = "libc" -version = "0.2.140" +version = "0.2.141" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "99227334921fae1a979cf0bfdfcc6b3e5ce376ef57e16fb6fb3ea2ed6095f80c" +checksum = "3304a64d199bb964be99741b7a14d26972741915b3649639149b2479bb46f4b5" [[package]] name = "libgit2-sys" @@ -3875,15 +3857,9 @@ dependencies = [ [[package]] name = "linux-raw-sys" -version = "0.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f051f77a7c8e6957c0696eac88f26b0117e54f52d3fc682ab19397a8812846a4" - -[[package]] -name = "linux-raw-sys" -version = "0.3.0" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd550e73688e6d578f0ac2119e32b797a327631a42f9433e59d02e139c8df60d" +checksum = "d59d8c75012853d2e872fb56bc8a2e53718e2cafe1a4c823143141c6d90c322f" [[package]] name = "lock_api" @@ -3980,7 +3956,7 @@ dependencies = [ "ammonia", "anyhow", "chrono", - "clap 4.2.1", + "clap 4.2.2", "clap_complete", "elasticlunr-rs", "env_logger", @@ -4045,9 +4021,9 @@ dependencies = [ [[package]] name = "miette" -version = "5.6.0" +version = "5.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07749fb52853e739208049fb513287c6f448de9103dfa78b05ae01f2fc5809bb" +checksum = "7abdc09c381c9336b9f2e9bd6067a9a5290d20e2d2e2296f275456121c33ae89" dependencies = [ "miette-derive", "once_cell", @@ -4057,13 +4033,13 @@ dependencies = [ [[package]] name = "miette-derive" -version = "5.6.0" +version = "5.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2a07ad93a80d1b92bb44cb42d7c49b49c9aab1778befefad49cceb5e4c5bf460" +checksum = "8842972f23939443013dfd3720f46772b743e86f1a81d120d4b6fb090f87de1c" dependencies = [ "proc-macro2", "quote", - "syn 1.0.109", + "syn 2.0.15", ] [[package]] @@ -4156,16 +4132,6 @@ dependencies = [ "static_assertions", ] -[[package]] -name = "nom" -version = "5.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ffb4262d26ed83a1c0a33a38fe2bb15797329c85770da05e6b828ddb782627af" -dependencies = [ - "memchr", - "version_check", -] - [[package]] name = "nom" version = "7.1.3" @@ -4303,7 +4269,16 @@ version = "0.5.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1f646caf906c20226733ed5b1374287eb97e3c2a5c227ce668c1f2ce20ae57c9" dependencies = [ - "num_enum_derive", + "num_enum_derive 0.5.11", +] + +[[package]] +name = "num_enum" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a015b430d3c108a207fd776d2e2196aaf8b1cf8cf93253e3a097ff3085076a1" +dependencies = [ + "num_enum_derive 0.6.1", ] [[package]] @@ -4318,6 +4293,18 @@ dependencies = [ "syn 1.0.109", ] +[[package]] +name = "num_enum_derive" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "96667db765a921f7b295ffee8b60472b686a51d4f21c2ee4ffdb94c7013b65a6" +dependencies = [ + "proc-macro-crate", + "proc-macro2", + "quote", + "syn 2.0.15", +] + [[package]] name = "num_threads" version = "0.1.6" @@ -4397,9 +4384,9 @@ dependencies = [ [[package]] name = "openssl" -version = "0.10.48" +version = "0.10.50" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "518915b97df115dd36109bfa429a48b8f737bd05508cf9588977b599648926d2" +checksum = "7e30d8bc91859781f0a943411186324d580f2bbeb71b452fe91ae344806af3f1" dependencies = [ "bitflags", "cfg-if", @@ -4412,13 +4399,13 @@ dependencies = [ [[package]] name = "openssl-macros" -version = "0.1.0" +version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b501e44f11665960c7e7fcf062c7d96a14ade4aa98116c004b2e37b5be7d736c" +checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" dependencies = [ "proc-macro2", "quote", - "syn 1.0.109", + "syn 2.0.15", ] [[package]] @@ -4429,11 +4416,10 @@ checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" [[package]] name = "openssl-sys" -version = "0.9.83" +version = "0.9.85" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "666416d899cf077260dac8698d60a60b435a46d57e82acb1be3d0dad87284e5b" +checksum = "0d3d193fb1488ad46ffe3aaabc912cc931d02ee8518fe2959aea8ef52718b0c0" dependencies = [ - "autocfg", "cc", "libc", "pkg-config", @@ -4623,7 +4609,7 @@ dependencies = [ "proc-macro2", "proc-macro2-diagnostics", "quote", - "syn 2.0.11", + "syn 2.0.15", ] [[package]] @@ -4634,9 +4620,9 @@ checksum = "478c572c3d73181ff3c2539045f6eb99e5491218eae919370993b890cdbdd98e" [[package]] name = "pest" -version = "2.5.6" +version = "2.5.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8cbd939b234e95d72bc393d51788aec68aeeb5d51e748ca08ff3aad58cb722f7" +checksum = "7b1403e8401ad5dedea73c626b99758535b342502f8d1e361f4a2dd952749122" dependencies = [ "thiserror", "ucd-trie", @@ -4644,9 +4630,9 @@ dependencies = [ [[package]] name = "pest_derive" -version = "2.5.6" +version = "2.5.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a81186863f3d0a27340815be8f2078dd8050b14cd71913db9fbda795e5f707d7" +checksum = "be99c4c1d2fc2769b1d00239431d711d08f6efedcecb8b6e30707160aee99c15" dependencies = [ "pest", "pest_generator", @@ -4654,22 +4640,22 @@ dependencies = [ [[package]] name = "pest_generator" -version = "2.5.6" +version = "2.5.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75a1ef20bf3193c15ac345acb32e26b3dc3223aff4d77ae4fc5359567683796b" +checksum = "e56094789873daa36164de2e822b3888c6ae4b4f9da555a1103587658c805b1e" dependencies = [ "pest", "pest_meta", "proc-macro2", "quote", - "syn 1.0.109", + "syn 2.0.15", ] [[package]] name = "pest_meta" -version = "2.5.6" +version = "2.5.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5e3b284b1f13a20dc5ebc90aff59a51b8d7137c221131b52a7260c08cbc1cc80" +checksum = "6733073c7cff3d8459fda0e42f13a047870242aed8b509fe98000928975f359e" dependencies = [ "once_cell", "pest", @@ -4826,11 +4812,11 @@ checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" [[package]] name = "pkcs8" -version = "0.10.1" +version = "0.10.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d2820d87d2b008616e5c27212dd9e0e694fb4c6b522de06094106813328cb49" +checksum = "f950b2377845cebe5cf8b5165cb3cc1a5e0fa5cfa3e1f7f55707d8fd82e0a7b7" dependencies = [ - "der 0.7.1", + "der 0.7.3", "spki", ] @@ -4900,12 +4886,12 @@ dependencies = [ [[package]] name = "prettyplease" -version = "0.1.25" +version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c8646e95016a7a6c4adea95bafa8a16baab64b583356217f2c85db4a39d9a86" +checksum = "1ceca8aaf45b5c46ec7ed39fff75f57290368c1846d33d24a122ca81416ab058" dependencies = [ "proc-macro2", - "syn 1.0.109", + "syn 2.0.15", ] [[package]] @@ -4958,9 +4944,9 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.54" +version = "1.0.56" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e472a104799c74b514a57226160104aa483546de37e839ec50e3c2e41dd87534" +checksum = "2b63bdb0cd06f1f4dedf69b254734f9b45af66e4a031e42a7480257d9898b435" dependencies = [ "unicode-ident", ] @@ -4973,7 +4959,7 @@ checksum = "606c4ba35817e2922a308af55ad51bab3645b59eae5c570d4a6cf07e36bd493b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.11", + "syn 2.0.15", "version_check", "yansi", ] @@ -5129,7 +5115,7 @@ version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" dependencies = [ - "getrandom 0.2.8", + "getrandom 0.2.9", ] [[package]] @@ -5196,7 +5182,7 @@ version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b033d837a7cf162d7993aded9304e30a83213c648b6e389db233191f891e5c2b" dependencies = [ - "getrandom 0.2.8", + "getrandom 0.2.9", "redox_syscall 0.2.16", "thiserror", ] @@ -5268,7 +5254,7 @@ dependencies = [ "pin-project-lite", "rustls", "rustls-native-certs", - "rustls-pemfile 1.0.2", + "rustls-pemfile", "serde", "serde_json", "serde_urlencoded", @@ -5295,7 +5281,7 @@ dependencies = [ "bytes", "hashbrown 0.13.2", "hex", - "num_enum", + "num_enum 0.5.11", "primitive-types", "revm_precompiles", "rlp", @@ -5526,30 +5512,16 @@ dependencies = [ [[package]] name = "rustix" -version = "0.36.11" +version = "0.37.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "db4165c9963ab29e422d6c26fbc1d37f15bace6b2810221f9d925023480fcf0e" +checksum = "85597d61f83914ddeba6a47b3b8ffe7365107221c2e557ed94426489fefb5f77" dependencies = [ "bitflags", - "errno 0.2.8", + "errno", "io-lifetimes", "libc", - "linux-raw-sys 0.1.4", - "windows-sys 0.45.0", -] - -[[package]] -name = "rustix" -version = "0.37.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0e78cc525325c06b4a7ff02db283472f3c042b7ff0c391f96c6d5ac6f4f91b75" -dependencies = [ - "bitflags", - "errno 0.3.0", - "io-lifetimes", - "libc", - "linux-raw-sys 0.3.0", - "windows-sys 0.45.0", + "linux-raw-sys", + "windows-sys 0.48.0", ] [[package]] @@ -5571,20 +5543,11 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0167bac7a9f490495f3c33013e7722b53cb087ecbe082fb0c6387c96f634ea50" dependencies = [ "openssl-probe", - "rustls-pemfile 1.0.2", + "rustls-pemfile", "schannel", "security-framework", ] -[[package]] -name = "rustls-pemfile" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5eebeaeb360c87bfb72e84abdb3447159c0eaececf1bef2aecd65a8be949d1c9" -dependencies = [ - "base64 0.13.1", -] - [[package]] name = "rustls-pemfile" version = "1.0.2" @@ -5747,12 +5710,12 @@ dependencies = [ [[package]] name = "sec1" -version = "0.7.1" +version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "48518a2b5775ba8ca5b46596aae011caa431e6ce7e4a67ead66d92f08884220e" +checksum = "f0aec48e813d6b90b15f0b8948af3c63483992dee44c03e9930b3eebdabe046e" dependencies = [ "base16ct 0.2.0", - "der 0.7.1", + "der 0.7.3", "generic-array", "pkcs8", "subtle", @@ -5823,29 +5786,29 @@ checksum = "cd0b0ec5f1c1ca621c432a25813d8d60c88abe6d3e08a3eb9cf37d97a0fe3d73" [[package]] name = "serde" -version = "1.0.159" +version = "1.0.160" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c04e8343c3daeec41f58990b9d77068df31209f2af111e059e9fe9646693065" +checksum = "bb2f3770c8bce3bcda7e149193a069a0f4365bda1fa5cd88e03bca26afc1216c" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.159" +version = "1.0.160" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c614d17805b093df4b147b51339e7e44bf05ef59fba1e45d83500bcfb4d8585" +checksum = "291a097c63d8497e00160b166a967a4a79c64f3facdd01cbd7502231688d77df" dependencies = [ "proc-macro2", "quote", - "syn 2.0.11", + "syn 2.0.15", ] [[package]] name = "serde_json" -version = "1.0.95" +version = "1.0.96" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d721eca97ac802aa7777b701877c8004d950fc142651367300d21c1cc0194744" +checksum = "057d394a50403bcac12672b2b18fb387ab6d289d957dab67dd201875391e52f1" dependencies = [ "indexmap", "itoa", @@ -5906,7 +5869,7 @@ checksum = "91d129178576168c589c9ec973feedf7d3126c01ac2bf08795109aa35b69fb8f" dependencies = [ "proc-macro2", "quote", - "syn 2.0.11", + "syn 2.0.15", ] [[package]] @@ -5963,9 +5926,9 @@ dependencies = [ [[package]] name = "sha3" -version = "0.10.6" +version = "0.10.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bdf0c33fae925bdc080598b84bc15c55e7b9a4a43b3c704da051f977469691c9" +checksum = "54c2bb1a323307527314a36bfb73f24febb08ce2b8a554bf4ffd6f51ad15198c" dependencies = [ "digest 0.10.6", "keccak", @@ -6034,9 +5997,9 @@ dependencies = [ [[package]] name = "signature" -version = "2.0.0" +version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8fe458c98333f9c8152221191a77e2a44e8325d0193484af2e9421a53019e57d" +checksum = "5e1788eed21689f9cf370582dfc467ef36ed9c707f073528ddafa8d83e3b8500" dependencies = [ "digest 0.10.6", "rand_core 0.6.4", @@ -6081,14 +6044,15 @@ dependencies = [ [[package]] name = "solang-parser" -version = "0.2.3" +version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ff87dae6cdccacdbf3b19e99b271083556e808de0f59c74a01482f64fdbc61fc" +checksum = "8c5ead679f39243782be98c2689e592fc0fc9489ca2e47c9e027bd30f948df31" dependencies = [ "itertools", "lalrpop", "lalrpop-util", "phf 0.11.1", + "thiserror", "unicode-xid", ] @@ -6100,12 +6064,12 @@ checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d" [[package]] name = "spki" -version = "0.7.0" +version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0445c905640145c7ea8c1993555957f65e7c46d0535b91ba501bc9bfc85522f" +checksum = "37a5be806ab6f127c3da44b7378837ebf01dadca8510a0e572460216b228bd0e" dependencies = [ "base64ct", - "der 0.7.1", + "der 0.7.3", ] [[package]] @@ -6250,9 +6214,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.11" +version = "2.0.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "21e3787bb71465627110e7d87ed4faaa36c1f61042ee67badb9e2ef173accc40" +checksum = "a34fcf3e8b60f57e6a14301a2e916d323af98b0ea63c599441eec8558660c822" dependencies = [ "proc-macro2", "quote", @@ -6292,7 +6256,7 @@ dependencies = [ "cfg-if", "fastrand", "redox_syscall 0.3.5", - "rustix 0.37.5", + "rustix", "windows-sys 0.45.0", ] @@ -6339,23 +6303,23 @@ dependencies = [ [[package]] name = "terminal_size" -version = "0.2.5" +version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c9afddd2cec1c0909f06b00ef33f94ab2cc0578c4a610aa208ddfec8aa2b43a" +checksum = "8e6bf6f19e9f8ed8d4048dc22981458ebcf406d67e94cd422e5ecd73d63b3237" dependencies = [ - "rustix 0.36.11", - "windows-sys 0.45.0", + "rustix", + "windows-sys 0.48.0", ] [[package]] name = "terminfo" -version = "0.7.5" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da31aef70da0f6352dbcb462683eb4dd2bfad01cf3fc96cf204547b9a839a585" +checksum = "666cd3a6681775d22b200409aad3b089c5b99fb11ecdd8a204d9d62f8148498f" dependencies = [ "dirs 4.0.0", "fnv", - "nom 5.1.2", + "nom", "phf 0.11.1", "phf_codegen 0.11.1", ] @@ -6383,7 +6347,7 @@ checksum = "f9456a42c5b0d803c8cd86e73dd7cc9edd429499f37a3550d286d5e86720569f" dependencies = [ "proc-macro2", "quote", - "syn 2.0.11", + "syn 2.0.15", ] [[package]] @@ -6497,7 +6461,7 @@ checksum = "61a573bdc87985e9d6ddeed1b3d864e8a302c847e40d647746df2f1de209d1ce" dependencies = [ "proc-macro2", "quote", - "syn 2.0.11", + "syn 2.0.15", ] [[package]] @@ -7023,7 +6987,7 @@ version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bc5cf98d8186244414c848017f0e2676b3fcb46807f6668a97dfe67359a3c4b7" dependencies = [ - "getrandom 0.2.8", + "getrandom 0.2.9", "serde", ] @@ -7041,9 +7005,9 @@ checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" [[package]] name = "vergen" -version = "8.1.0" +version = "8.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "00f9f3c0ac17bba2cce5ba26fc17a26cb93e099626b6c3260882cecb08a1e2b4" +checksum = "c1b86a8af1dedf089b1c78338678e4c7492b6045649042d94faf19690499d236" dependencies = [ "anyhow", "git2", @@ -7088,9 +7052,9 @@ dependencies = [ [[package]] name = "warp" -version = "0.3.3" +version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed7b8be92646fc3d18b06147664ebc5f48d222686cb11a8755e561a735aacc6d" +checksum = "27e1a710288f0f91a98dd8a74f05b76a10768db245ce183edf64dc1afdc3016c" dependencies = [ "bytes", "futures-channel", @@ -7103,14 +7067,14 @@ dependencies = [ "mime_guess", "percent-encoding", "pin-project", - "rustls-pemfile 0.2.1", + "rustls-pemfile", "scoped-tls", "serde", "serde_json", "serde_urlencoded", "tokio", "tokio-stream", - "tokio-tungstenite 0.17.2", + "tokio-tungstenite 0.18.0", "tokio-util", "tower-service", "tracing", @@ -7336,11 +7300,11 @@ dependencies = [ [[package]] name = "windows" -version = "0.47.0" +version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2649ff315bee4c98757f15dac226efe3d81927adbb6e882084bb1ee3e0c330a7" +checksum = "e686886bc078bc1b0b600cac0147aadb815089b6e4da64016cbd754b6342700f" dependencies = [ - "windows-targets 0.47.0", + "windows-targets 0.48.0", ] [[package]] @@ -7367,6 +7331,15 @@ dependencies = [ "windows-targets 0.42.2", ] +[[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.0", +] + [[package]] name = "windows-targets" version = "0.42.2" @@ -7384,17 +7357,17 @@ dependencies = [ [[package]] name = "windows-targets" -version = "0.47.0" +version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2f8996d3f43b4b2d44327cd71b7b0efd1284ab60e6e9d0e8b630e18555d87d3e" +checksum = "7b1eb6f0cd7c80c79759c929114ef071b87354ce476d9d94271031c0497adfd5" dependencies = [ - "windows_aarch64_gnullvm 0.47.0", - "windows_aarch64_msvc 0.47.0", - "windows_i686_gnu 0.47.0", - "windows_i686_msvc 0.47.0", - "windows_x86_64_gnu 0.47.0", - "windows_x86_64_gnullvm 0.47.0", - "windows_x86_64_msvc 0.47.0", + "windows_aarch64_gnullvm 0.48.0", + "windows_aarch64_msvc 0.48.0", + "windows_i686_gnu 0.48.0", + "windows_i686_msvc 0.48.0", + "windows_x86_64_gnu 0.48.0", + "windows_x86_64_gnullvm 0.48.0", + "windows_x86_64_msvc 0.48.0", ] [[package]] @@ -7405,9 +7378,9 @@ checksum = "597a5118570b68bc08d8d59125332c54f1ba9d9adeedeef5b99b02ba2b0698f8" [[package]] name = "windows_aarch64_gnullvm" -version = "0.47.0" +version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "831d567d53d4f3cb1db332b68e6e2b6260228eb4d99a777d8b2e8ed794027c90" +checksum = "91ae572e1b79dba883e0d315474df7305d12f569b400fcf90581b06062f7e1bc" [[package]] name = "windows_aarch64_msvc" @@ -7417,9 +7390,9 @@ checksum = "e08e8864a60f06ef0d0ff4ba04124db8b0fb3be5776a5cd47641e942e58c4d43" [[package]] name = "windows_aarch64_msvc" -version = "0.47.0" +version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a42d54a417c60ce4f0e31661eed628f0fa5aca73448c093ec4d45fab4c51cdf" +checksum = "b2ef27e0d7bdfcfc7b868b317c1d32c641a6fe4629c171b8928c7b08d98d7cf3" [[package]] name = "windows_i686_gnu" @@ -7429,9 +7402,9 @@ checksum = "c61d927d8da41da96a81f029489353e68739737d3beca43145c8afec9a31a84f" [[package]] name = "windows_i686_gnu" -version = "0.47.0" +version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c1925beafdbb22201a53a483db861a5644123157c1c3cee83323a2ed565d71e3" +checksum = "622a1962a7db830d6fd0a69683c80a18fda201879f0f447f065a3b7467daa241" [[package]] name = "windows_i686_msvc" @@ -7441,9 +7414,9 @@ checksum = "44d840b6ec649f480a41c8d80f9c65108b92d89345dd94027bfe06ac444d1060" [[package]] name = "windows_i686_msvc" -version = "0.47.0" +version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3a8ef8f2f1711b223947d9b69b596cf5a4e452c930fb58b6fc3fdae7d0ec6b31" +checksum = "4542c6e364ce21bf45d69fdd2a8e455fa38d316158cfd43b3ac1c5b1b19f8e00" [[package]] name = "windows_x86_64_gnu" @@ -7453,9 +7426,9 @@ checksum = "8de912b8b8feb55c064867cf047dda097f92d51efad5b491dfb98f6bbb70cb36" [[package]] name = "windows_x86_64_gnu" -version = "0.47.0" +version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7acaa0c2cf0d2ef99b61c308a0c3dbae430a51b7345dedec470bd8f53f5a3642" +checksum = "ca2b8a661f7628cbd23440e50b05d705db3686f894fc9580820623656af974b1" [[package]] name = "windows_x86_64_gnullvm" @@ -7465,9 +7438,9 @@ checksum = "26d41b46a36d453748aedef1486d5c7a85db22e56aff34643984ea85514e94a3" [[package]] name = "windows_x86_64_gnullvm" -version = "0.47.0" +version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e5a0628f71be1d11e17ca4a0e9e15b3a5180f6fbf1c2d55e3ba3f850378052c1" +checksum = "7896dbc1f41e08872e9d5e8f8baa8fdd2677f29468c4e156210174edc7f7b953" [[package]] name = "windows_x86_64_msvc" @@ -7477,9 +7450,9 @@ checksum = "9aec5da331524158c6d1a4ac0ab1541149c0b9505fde06423b02f5ef0106b9f0" [[package]] name = "windows_x86_64_msvc" -version = "0.47.0" +version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d6e62c256dc6d40b8c8707df17df8d774e60e39db723675241e7c15e910bce7" +checksum = "1a515f5799fe4961cb532f983ce2b23082366b898e52ffbce459c86f67c8378a" [[package]] name = "winnow" @@ -7586,9 +7559,9 @@ dependencies = [ [[package]] name = "zstd-sys" -version = "2.0.7+zstd.1.5.4" +version = "2.0.8+zstd.1.5.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94509c3ba2fe55294d752b79842c530ccfab760192521df74a081a78d2b3c7f5" +checksum = "5556e6ee25d32df2586c098bbfa278803692a20d0ab9565e049480d52707ec8c" dependencies = [ "cc", "libc", diff --git a/Cargo.toml b/Cargo.toml index b95ab0800e20..e48959400834 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -69,16 +69,14 @@ ethers-middleware = { version = "2", default-features = false } ethers-etherscan = { version = "2", default-features = false } ethers-solc = { version = "2", default-features = false } -# # Patch ethers-rs with a local checkout then run `cargo update -p ethers` -# [patch."https://github.com/gakonst/ethers-rs"] -# ethers = { path = "../ethers-rs" } +#[patch.crates-io] +# ethers = { path = "../ethers-rs/ethers" } # ethers-addressbook = { path = "../ethers-rs/ethers-addressbook" } -# ethers-core = { path = "../ethers-rs/ethers-core" } # ethers-contract = { path = "../ethers-rs/ethers-contract" } +# ethers-core = { path = "../ethers-rs/ethers-core" } +# ethers-etherscan = { path = "../ethers-rs/ethers-etherscan" } +# ethers-middleware = { path = "../ethers-rs/ethers-middleware" } # ethers-providers = { path = "../ethers-rs/ethers-providers" } # ethers-signers = { path = "../ethers-rs/ethers-signers" } -# ethers-etherscan = { path = "../ethers-rs/ethers-etherscan" } # ethers-solc = { path = "../ethers-rs/ethers-solc" } - -# [patch.crates-io] # revm = { path = "../revm/crates/revm" } diff --git a/chisel/Cargo.toml b/chisel/Cargo.toml index 1ce9f2d2013f..30769de4a033 100644 --- a/chisel/Cargo.toml +++ b/chisel/Cargo.toml @@ -37,7 +37,7 @@ reqwest = { version = "0.11", default-features = false, features = ["rustls"] } # misc clap = { version = "4.2", features = ["derive", "env", "wrap_help"] } rustyline = "11.0" -solang-parser = "=0.2.3" +solang-parser = "=0.2.4" yansi = "0.5" strum = { version = "0.24.1", features = ["derive"] } serde = "1.0.159" diff --git a/chisel/src/executor.rs b/chisel/src/executor.rs index 8bd221eac20e..881d4692a703 100644 --- a/chisel/src/executor.rs +++ b/chisel/src/executor.rs @@ -461,7 +461,7 @@ impl Type { pt::Expression::New(_, inner) | // new pt::Expression::UnaryPlus(_, inner) | // + // ops - pt::Expression::Complement(_, inner) | // ~ + pt::Expression::BitwiseNot(_, inner) | // ~ pt::Expression::ArraySlice(_, inner, _, _) | // [*start*:*end*] // assign ops pt::Expression::PreDecrement(_, inner) | // -- diff --git a/chisel/src/solidity_helper.rs b/chisel/src/solidity_helper.rs index b053be1e02ff..445c1b2644d4 100644 --- a/chisel/src/solidity_helper.rs +++ b/chisel/src/solidity_helper.rs @@ -103,7 +103,7 @@ impl SolidityHelper { /// Highlights a solidity source string pub fn highlight(input: &str) -> Cow { - if !Paint::is_enabled() || Self::skip_input(input) { + if !Paint::is_enabled() { return Cow::Borrowed(input) } @@ -150,11 +150,6 @@ impl SolidityHelper { /// Validate that a source snippet is closed (i.e., all braces and parenthesis are matched). fn validate_closed(input: &str) -> ValidationResult { - if Self::skip_input(input) { - let msg = Paint::red("\nInput must not start with `.`"); - return ValidationResult::Invalid(Some(msg.to_string())) - } - let mut bracket_depth = 0usize; let mut paren_depth = 0usize; let mut brace_depth = 0usize; @@ -218,14 +213,6 @@ impl SolidityHelper { Self::paint_unchecked(string, style, &mut out); out } - - /// Whether to skip parsing this input due to known errors or panics - #[inline] - fn skip_input(input: &str) -> bool { - // input.startsWith(/\.[0-9]/) - let mut chars = input.chars(); - chars.next() == Some('.') && chars.next().map(|c| c.is_ascii_digit()).unwrap_or_default() - } } impl Highlighter for SolidityHelper { diff --git a/cli/Cargo.toml b/cli/Cargo.toml index 2ade9164b68c..1991ed53226f 100644 --- a/cli/Cargo.toml +++ b/cli/Cargo.toml @@ -23,7 +23,7 @@ ui = { path = "../ui" } # eth ethers = { workspace = true, features = ["rustls"] } -solang-parser = "=0.2.3" +solang-parser = "=0.2.4" # cli clap = { version = "4.2", features = ["derive", "env", "unicode", "wrap_help"] } diff --git a/cli/src/cmd/forge/geiger/visitor.rs b/cli/src/cmd/forge/geiger/visitor.rs index 851b66ad7c1a..9a143680b19d 100644 --- a/cli/src/cmd/forge/geiger/visitor.rs +++ b/cli/src/cmd/forge/geiger/visitor.rs @@ -92,7 +92,7 @@ impl Visitor for CheatcodeVisitor { Expression::Not(_, expr) => { expr.visit(self)?; } - Expression::Complement(_, expr) => { + Expression::BitwiseNot(_, expr) => { expr.visit(self)?; } Expression::Delete(_, expr) => { diff --git a/doc/Cargo.toml b/doc/Cargo.toml index 6c5d4d72a062..e4a02461b18e 100644 --- a/doc/Cargo.toml +++ b/doc/Cargo.toml @@ -32,7 +32,7 @@ tokio = { version = "1.27", features = ["macros", "rt-multi-thread"] } futures-util = "0.3" # misc -solang-parser = "=0.2.3" +solang-parser = "=0.2.4" eyre = "0.6" thiserror = "1.0.40" rayon = "1.7" diff --git a/doc/src/lib.rs b/doc/src/lib.rs index a3025f5479ee..cfc5a107f675 100644 --- a/doc/src/lib.rs +++ b/doc/src/lib.rs @@ -35,4 +35,4 @@ pub use parser::{ pub use preprocessor::*; /// Traits for formatting items into doc output. -pub use writer::{AsDoc, AsDocResult, AsString, BufWriter, Markdown}; +pub use writer::{AsDoc, AsDocResult, BufWriter, Markdown}; diff --git a/doc/src/writer/as_doc.rs b/doc/src/writer/as_doc.rs index 8ee08857fa06..3aeb9311559e 100644 --- a/doc/src/writer/as_doc.rs +++ b/doc/src/writer/as_doc.rs @@ -4,7 +4,7 @@ use crate::{ document::{read_context, DocumentContent}, parser::ParseSource, writer::BufWriter, - AsString, CommentTag, Comments, CommentsRef, Document, Markdown, PreprocessorOutput, + CommentTag, Comments, CommentsRef, Document, Markdown, PreprocessorOutput, CONTRACT_INHERITANCE_ID, GIT_SOURCE_ID, INHERITDOC_ID, }; use forge_fmt::solang_ext::SafeUnwrap; @@ -91,7 +91,7 @@ impl AsDoc for Document { "({})", func.params .iter() - .map(|p| p.1.as_ref().map(|p| p.ty.as_string()).unwrap_or_default()) + .map(|p| p.1.as_ref().map(|p| p.ty.to_string()).unwrap_or_default()) .join(", ") )); } diff --git a/doc/src/writer/as_string.rs b/doc/src/writer/as_string.rs deleted file mode 100644 index 08c25e7562b2..000000000000 --- a/doc/src/writer/as_string.rs +++ /dev/null @@ -1,242 +0,0 @@ -use ethers_core::{types::H160, utils::to_checksum}; -use forge_fmt::solang_ext::{AttrSortKeyIteratorExt, Operator, OperatorComponents}; -use itertools::Itertools; -use solang_parser::pt::{Expression, FunctionAttribute, IdentifierPath, Loc, Parameter, Type}; -use std::str::FromStr; - -/// Trait for rendering parse tree items as strings. -#[auto_impl::auto_impl(&)] -pub trait AsString { - /// Render parse tree item as string. - fn as_string(&self) -> String; -} - -impl AsString for Expression { - fn as_string(&self) -> String { - match self { - Expression::Type(_, ty) => match ty { - Type::Address => "address".to_owned(), - Type::AddressPayable => "address payable".to_owned(), - Type::Payable => "payable".to_owned(), - Type::Bool => "bool".to_owned(), - Type::String => "string".to_owned(), - Type::Bytes(n) => format!("bytes{n}"), - Type::Rational => "rational".to_owned(), - Type::DynamicBytes => "bytes".to_owned(), - Type::Int(n) => format!("int{n}"), - Type::Uint(n) => format!("uint{n}"), - Type::Mapping { key, key_name, value, value_name, .. } => { - let mut key = key.as_string(); - if let Some(name) = key_name { - key.push(' '); - key.push_str(&name.to_string()); - } - let mut value = value.as_string(); - if let Some(name) = value_name { - value.push(' '); - value.push_str(&name.to_string()); - } - format!("mapping({key} => {value})") - } - Type::Function { params, attributes, returns } => { - let params = params.as_string(); - let mut attributes = attributes.as_string(); - if !attributes.is_empty() { - attributes.insert(0, ' '); - } - let mut returns_str = String::new(); - if let Some((params, _attrs)) = returns { - returns_str = params.as_string(); - if !returns_str.is_empty() { - returns_str = format!(" returns ({returns_str})") - } - } - format!("function ({params}){attributes}{returns_str}") - } - }, - Expression::Variable(ident) => ident.name.to_owned(), - Expression::ArraySubscript(_, expr1, expr2) => format!( - "{}[{}]", - expr1.as_string(), - expr2.as_ref().map(|expr| expr.as_string()).unwrap_or_default() - ), - Expression::MemberAccess(_, expr, ident) => { - format!("{}.{}", ident.name, expr.as_string()) - } - Expression::Parenthesis(_, expr) => { - format!("({})", expr.as_string()) - } - Expression::HexNumberLiteral(_, val, unit) => { - // ref: https://docs.soliditylang.org/en/latest/types.html?highlight=address%20literal#address-literals - let mut val = if val.len() == 42 { - to_checksum(&H160::from_str(val).expect(""), None) - } else { - val.to_owned() - }; - if let Some(unit) = unit { - val.push_str(&format!(" {}", unit.name)); - } - val - } - Expression::NumberLiteral(_, val, exp, unit) => { - let mut val = val.replace('_', ""); - if !exp.is_empty() { - val.push_str(&format!("e{}", exp.replace('_', ""))); - } - if let Some(unit) = unit { - val.push_str(&format!(" {}", unit.name)); - } - val - } - Expression::StringLiteral(vals) => vals - .iter() - .map(|val| { - format!("{}\"{}\"", if val.unicode { "unicode" } else { "" }, val.string) - }) - .join(" "), - Expression::BoolLiteral(_, bool) => { - let val = if *bool { "true" } else { "false" }; - val.to_owned() - } - Expression::HexLiteral(vals) => { - vals.iter().map(|val| format!("hex\"{}\"", val.hex)).join(" ") - } - Expression::ArrayLiteral(_, exprs) => { - format!("[{}]", exprs.iter().map(AsString::as_string).join(", ")) - } - Expression::RationalNumberLiteral(_, val, fraction, exp, unit) => { - let mut val = val.replace('_', ""); - if val.is_empty() { - val = "0".to_owned(); - } - let mut fraction = fraction.trim_end_matches('0').to_owned(); - if fraction.is_empty() { - fraction.push('0') - } - val.push_str(&format!(".{fraction}")); - if !exp.is_empty() { - val.push_str(&format!("e{}", exp.replace('_', ""))); - } - if let Some(unit) = unit { - val.push_str(&format!(" {}", unit.name)); - } - val - } - Expression::FunctionCall(_, expr, exprs) => { - format!( - "{}({})", - expr.as_string(), - exprs.iter().map(AsString::as_string).join(", ") - ) - } - Expression::PreIncrement(..) | - Expression::PostIncrement(..) | - Expression::PreDecrement(..) | - Expression::PostDecrement(..) | - Expression::Not(..) | - Expression::Complement(..) | - Expression::UnaryPlus(..) | - Expression::Add(..) | - Expression::Negate(..) | - Expression::Subtract(..) | - Expression::Power(..) | - Expression::Multiply(..) | - Expression::Divide(..) | - Expression::Modulo(..) | - Expression::ShiftLeft(..) | - Expression::ShiftRight(..) | - Expression::BitwiseAnd(..) | - Expression::BitwiseXor(..) | - Expression::BitwiseOr(..) | - Expression::Less(..) | - Expression::More(..) | - Expression::LessEqual(..) | - Expression::MoreEqual(..) | - Expression::And(..) | - Expression::Or(..) | - Expression::Equal(..) | - Expression::NotEqual(..) => { - let spaced = self.has_space_around(); - - let (left, right) = self.components(); - - let mut val = String::from(self.operator().unwrap()); - if let Some(left) = left { - if spaced { - val.insert(0, ' '); - } - val.insert_str(0, &left.as_string()); - } - if let Some(right) = right { - if spaced { - val.push(' '); - } - val.push_str(&right.as_string()) - } - - val - } - item => { - panic!("Attempted to format unsupported item: {item:?}") - } - } - } -} - -impl AsString for Parameter { - fn as_string(&self) -> String { - [ - Some(self.ty.as_string()), - self.storage.as_ref().map(|storage| storage.to_string()), - self.name.as_ref().map(|name| name.name.clone()), - ] - .into_iter() - .flatten() - .join(" ") - } -} - -impl AsString for Vec<(Loc, Option)> { - fn as_string(&self) -> String { - self.iter() - .map(|(_, param)| param.as_ref().map(AsString::as_string).unwrap_or_default()) - .join(", ") - } -} - -impl AsString for Vec { - fn as_string(&self) -> String { - self.iter().attr_sorted().map(|attr| attr.as_string()).join(" ") - } -} - -impl AsString for FunctionAttribute { - fn as_string(&self) -> String { - match self { - Self::Mutability(mutability) => mutability.to_string(), - Self::Visibility(visibility) => visibility.to_string(), - Self::Virtual(_) => "virtual".to_owned(), - Self::Immutable(_) => "immutable".to_owned(), - Self::Override(_, idents) => { - let mut val = "override".to_owned(); - if !idents.is_empty() { - val.push_str(&format!( - "({})", - idents.iter().map(AsString::as_string).join(", ") - )); - } - val - } - Self::BaseOrModifier(_, base) => { - base.name.identifiers.iter().map(|i| i.name.to_owned()).join(".") - } - Self::Error(_) => unreachable!(), - } - } -} - -impl AsString for IdentifierPath { - fn as_string(&self) -> String { - self.identifiers.iter().map(|ident| ident.name.to_owned()).join(".") - } -} diff --git a/doc/src/writer/buf_writer.rs b/doc/src/writer/buf_writer.rs index 8db5ac2271a3..4d1d4c7222ba 100644 --- a/doc/src/writer/buf_writer.rs +++ b/doc/src/writer/buf_writer.rs @@ -3,7 +3,7 @@ use once_cell::sync::Lazy; use solang_parser::pt::Parameter; use std::fmt::{self, Display, Write}; -use crate::{AsDoc, AsString, CommentTag, Comments, Markdown}; +use crate::{AsDoc, CommentTag, Comments, Markdown}; /// Solidity language name. const SOLIDITY: &str = "solidity"; @@ -152,7 +152,7 @@ impl BufWriter { let row = [ Markdown::Code(¶m_name.unwrap_or_else(|| "".to_owned())).as_doc()?, - Markdown::Code(¶m.ty.as_string()).as_doc()?, + Markdown::Code(¶m.ty.to_string()).as_doc()?, comment.unwrap_or_default().replace('\n', " "), ]; self.write_piped(&row.join("|"))?; diff --git a/doc/src/writer/mod.rs b/doc/src/writer/mod.rs index 3f7d9069ffad..47f497e0cc7d 100644 --- a/doc/src/writer/mod.rs +++ b/doc/src/writer/mod.rs @@ -1,11 +1,9 @@ //! The module for writing and formatting various parse tree items. mod as_doc; -mod as_string; mod buf_writer; mod markdown; pub use as_doc::{AsDoc, AsDocResult}; -pub use as_string::AsString; pub use buf_writer::BufWriter; pub use markdown::Markdown; diff --git a/fmt/Cargo.toml b/fmt/Cargo.toml index 208a12503f3a..008fd3084b70 100644 --- a/fmt/Cargo.toml +++ b/fmt/Cargo.toml @@ -16,15 +16,17 @@ foundry-config = { path = "../config" } ethers-core = { workspace = true } # parser -solang-parser = "=0.2.3" +solang-parser = "=0.2.4" # misc semver = "1.0.17" itertools = "0.10.5" thiserror = "1.0.40" ariadne = "0.2" +tracing = "0.1.37" [dev-dependencies] pretty_assertions = "1.3.0" itertools = "0.10.5" toml = "0.7" +tracing-subscriber = { version = "0.3.16", features = ["env-filter"] } diff --git a/fmt/src/buffer.rs b/fmt/src/buffer.rs index 35b5b12c3566..f6e5a85caf08 100644 --- a/fmt/src/buffer.rs +++ b/fmt/src/buffer.rs @@ -40,7 +40,7 @@ impl Default for WriteState { /// as information about the last `write_str` command if available. The formatter may also be /// restricted to a single line, in which case it will throw an error on a newline #[derive(Clone, Debug)] -pub struct FormatBuffer { +pub struct FormatBuffer { pub w: W, indents: Vec, base_indent_len: usize, @@ -51,7 +51,7 @@ pub struct FormatBuffer { state: WriteState, } -impl FormatBuffer { +impl FormatBuffer { pub fn new(w: W, tab_width: usize) -> Self { Self { w, diff --git a/fmt/src/comments.rs b/fmt/src/comments.rs index c48dd9fefad1..e19188598aa6 100644 --- a/fmt/src/comments.rs +++ b/fmt/src/comments.rs @@ -1,7 +1,4 @@ -use crate::{ - inline_config::{InlineConfigItem, InvalidInlineConfigItem}, - solang_ext::*, -}; +use crate::inline_config::{InlineConfigItem, InvalidInlineConfigItem}; use itertools::Itertools; use solang_parser::pt::*; use std::collections::VecDeque; diff --git a/fmt/src/formatter.rs b/fmt/src/formatter.rs index 258a6b465870..cc7cf09cf44d 100644 --- a/fmt/src/formatter.rs +++ b/fmt/src/formatter.rs @@ -7,7 +7,7 @@ use crate::{ CommentPosition, CommentState, CommentStringExt, CommentType, CommentWithMetadata, Comments, }, macros::*, - solang_ext::*, + solang_ext::{pt::*, *}, string::{QuoteState, QuotedStringExt}, visit::{Visitable, Visitor}, FormatterConfig, InlineConfig, IntTypes, NumberUnderscore, @@ -15,7 +15,6 @@ use crate::{ use ethers_core::{types::H160, utils::to_checksum}; use foundry_config::fmt::{MultilineFuncHeaderStyle, SingleLineBlockStyle}; use itertools::{Either, Itertools}; -use solang_parser::pt::*; use std::{fmt::Write, str::FromStr}; use thiserror::Error; @@ -82,7 +81,7 @@ struct Context { /// A Solidity formatter #[derive(Debug)] pub struct Formatter<'a, W> { - buf: FormatBuffer<&'a mut W>, + buf: FormatBuffer, source: &'a str, config: FormatterConfig, temp_bufs: Vec>, @@ -115,10 +114,10 @@ impl<'f, 'a, W: Write> Transaction<'f, 'a, W> { /// Create a new transaction from a callback fn new( fmt: &'f mut Formatter<'a, W>, - mut fun: impl FnMut(&mut Formatter<'a, W>) -> Result<()>, + fun: impl FnMut(&mut Formatter<'a, W>) -> Result<()>, ) -> Result { let mut comments = fmt.comments.clone(); - let buffer = fmt.with_temp_buf(|fmt| fun(fmt))?.w; + let buffer = fmt.with_temp_buf(fun)?.w; comments = std::mem::replace(&mut fmt.comments, comments); Ok(Self { fmt, buffer, comments }) } @@ -133,7 +132,7 @@ impl<'f, 'a, W: Write> Transaction<'f, 'a, W> { impl<'a, W: Write> Formatter<'a, W> { pub fn new( - w: &'a mut W, + w: W, source: &'a str, comments: Comments, inline_config: InlineConfig, @@ -152,10 +151,18 @@ impl<'a, W: Write> Formatter<'a, W> { /// Get the Write interface of the current temp buffer or the underlying Write fn buf(&mut self) -> &mut dyn Write { - if self.temp_bufs.is_empty() { - &mut self.buf as &mut dyn Write - } else { - self.temp_bufs.last_mut().unwrap() as &mut dyn Write + match &mut self.temp_bufs[..] { + [] => &mut self.buf as &mut dyn Write, + [.., buf] => buf as &mut dyn Write, + } + } + + /// Casts the current `W` writer as a `String` reference. Should only be used for debugging. + #[allow(dead_code)] + unsafe fn buf_contents(&self) -> &String { + match &self.temp_bufs[..] { + [] => unsafe { *(&self.buf.w as *const W as *const &mut String) }, + [.., buf] => &buf.w, } } @@ -395,10 +402,10 @@ impl<'a, W: Write> Formatter<'a, W> { fn items_to_chunks<'b>( &mut self, next_byte_offset: Option, - items: impl IntoIterator> + 'b, + items: impl Iterator + 'b, ) -> Result> { - let mut items = items.into_iter().collect::>>()?.into_iter().peekable(); - let mut out = Vec::new(); + let mut items = items.peekable(); + let mut out = Vec::with_capacity(items.size_hint().1.unwrap_or(0)); while let Some((loc, item)) = items.next() { let chunk_next_byte_offset = items.peek().map(|(loc, _)| loc.start()).or(next_byte_offset); @@ -411,25 +418,18 @@ impl<'a, W: Write> Formatter<'a, W> { fn items_to_chunks_sorted<'b>( &mut self, next_byte_offset: Option, - items: impl IntoIterator> + 'b, + items: impl Iterator + 'b, ) -> Result> { - let mut items = items - .into_iter() - .map_ok(|(loc, vis)| (vis.attr_sort_key(), loc, vis)) - .collect::>>()? - .into_iter() - .peekable(); - let mut out = Vec::new(); - while let Some((attr_sort_key, loc, item)) = items.next() { + let mut items = items.peekable(); + let mut out = Vec::with_capacity(items.size_hint().1.unwrap_or(0)); + while let Some(item) = items.next() { let chunk_next_byte_offset = - items.peek().map(|(_, loc, _)| loc.start()).or(next_byte_offset); - out.push(( - (attr_sort_key, loc), - self.visit_to_chunk(loc.start(), chunk_next_byte_offset, item)?, - )); + items.peek().map(|next| next.loc().start()).or(next_byte_offset); + let chunk = self.visit_to_chunk(item.loc().start(), chunk_next_byte_offset, item)?; + out.push((item, chunk)); } - out.sort_by_key(|(k, _)| *k); - Ok(out.into_iter().map(|(_, c)| c).collect_vec()) + out.sort_by(|(a, _), (b, _)| a.cmp(b)); + Ok(out.into_iter().map(|(_, c)| c).collect()) } /// Write a comment to the buffer formatted. @@ -934,7 +934,7 @@ impl<'a, W: Write> Formatter<'a, W> { ) -> Result<()> where I: Iterator + 'b, - V: Visitable + LineOfCode + 'b, + V: Visitable + CodeLocation + 'b, F: Fn(&V, &V) -> bool, { let mut items = items.collect::>(); @@ -987,6 +987,7 @@ impl<'a, W: Write> Formatter<'a, W> { let (unwritten_whitespace_loc, unwritten_whitespace) = unwritten_whitespace(last_byte_written, loc.start()); let ignore_whitespace = if self.inline_config.is_disabled(unwritten_whitespace_loc) { + trace!("Unwritten whitespace: {:?}", unwritten_whitespace); self.write_raw(unwritten_whitespace)?; true } else { @@ -1018,6 +1019,10 @@ impl<'a, W: Write> Formatter<'a, W> { if let Some(next_item) = items.last() { needs_space = needs_space_fn(item, next_item); } + trace!("Visiting {}", { + let n = std::any::type_name::(); + n.strip_prefix("solang_parser::pt::").unwrap_or(n) + },); item.visit(self)?; } } @@ -1083,7 +1088,7 @@ impl<'a, W: Write> Formatter<'a, W> { })?; if !fit_on_next_line { - self.indented_if(expr.unsplittable(), 1, |fmt| expr.visit(fmt))?; + self.indented_if(expr.is_unsplittable(), 1, |fmt| expr.visit(fmt))?; } Ok(()) @@ -1101,7 +1106,7 @@ impl<'a, W: Write> Formatter<'a, W> { paren_required: bool, ) -> Result<()> where - T: Visitable + LineOfCode, + T: Visitable + CodeLocation, { write_chunk!(self, "{}", prefix)?; let whitespace = if !prefix.is_empty() { " " } else { "" }; @@ -1120,10 +1125,8 @@ impl<'a, W: Write> Formatter<'a, W> { } else { write!(self.buf(), "{whitespace}(")?; self.surrounded(first_surrounding, last_surronding, |fmt, multiline| { - let args = fmt.items_to_chunks( - end_offset, - items.iter_mut().map(|arg| Ok((arg.loc(), arg))), - )?; + let args = + fmt.items_to_chunks(end_offset, items.iter_mut().map(|arg| (arg.loc(), arg)))?; let multiline = multiline && fmt.are_chunks_separated_multiline("{}", &args, ",")?; fmt.write_chunks_separated(&args, ",", multiline)?; @@ -1145,7 +1148,7 @@ impl<'a, W: Write> Formatter<'a, W> { attempt_omit_braces: bool, ) -> Result where - T: Visitable + LineOfCode, + T: Visitable + CodeLocation, { if attempt_single_line && statements.len() == 1 { let fits_on_single = self.try_on_single_line(|fmt| { @@ -1168,7 +1171,7 @@ impl<'a, W: Write> Formatter<'a, W> { if let Some(statement) = statements.first() { self.write_whitespace_separator(true)?; - self.write_postfix_comments_before(LineOfCode::loc(statement).start())?; + self.write_postfix_comments_before(CodeLocation::loc(statement).start())?; } self.indented(1, |fmt| { @@ -1208,7 +1211,7 @@ impl<'a, W: Write> Formatter<'a, W> { mut matcher: M, ) -> Result<()> where - T: LineOfCode + Visitable, + T: CodeLocation + Visitable, M: FnMut(&mut Self, &'b mut Box) -> Result, &'b mut Identifier)>>, { let chunk_member_access = |fmt: &mut Self, ident: &mut Identifier, expr: &mut Box| { @@ -1425,9 +1428,9 @@ impl<'a, W: Write> Formatter<'a, W> { |fmt, multiline| { let params = fmt.items_to_chunks( params_next_offset, - func.params.iter_mut().filter_map(|(loc, param)| { - param.as_mut().map(|param| Ok((*loc, param))) - }), + func.params + .iter_mut() + .filter_map(|(loc, param)| param.as_mut().map(|param| (*loc, param))), )?; let after_params = if !func.attributes.is_empty() || !func.returns.is_empty() { "" @@ -1468,10 +1471,8 @@ impl<'a, W: Write> Formatter<'a, W> { } else { fmt.write_postfix_comments_before(attrs_loc.start())?; fmt.write_whitespace_separator(multiline)?; - let attributes = fmt.items_to_chunks_sorted( - attrs_end, - func.attributes.iter_mut().map(|attr| Ok((attr.loc(), attr))), - )?; + let attributes = + fmt.items_to_chunks_sorted(attrs_end, func.attributes.iter_mut())?; fmt.indented(1, |fmt| { fmt.write_chunks_separated(&attributes, "", multiline)?; Ok(()) @@ -1488,9 +1489,9 @@ impl<'a, W: Write> Formatter<'a, W> { } else { let returns = fmt.items_to_chunks( returns_end, - func.returns.iter_mut().filter_map(|(loc, param)| { - param.as_mut().map(|param| Ok((*loc, param))) - }), + func.returns + .iter_mut() + .filter_map(|(loc, param)| param.as_mut().map(|param| (*loc, param))), )?; fmt.write_postfix_comments_before(returns_loc.start())?; fmt.write_whitespace_separator(multiline)?; @@ -1587,6 +1588,7 @@ impl<'a, W: Write> Formatter<'a, W> { impl<'a, W: Write> Visitor for Formatter<'a, W> { type Error = FormatterError; + #[instrument(name = "source", skip(self))] fn visit_source(&mut self, loc: Loc) -> Result<()> { let source = String::from_utf8(self.source.as_bytes()[loc.range()].to_vec()) .map_err(FormatterError::custom)?; @@ -1604,6 +1606,7 @@ impl<'a, W: Write> Visitor for Formatter<'a, W> { Ok(()) } + #[instrument(name = "SU", skip_all)] fn visit_source_unit(&mut self, source_unit: &mut SourceUnit) -> Result<()> { // TODO: do we need to put pragma and import directives at the top of the file? // source_unit.0.sort_by_key(|item| match item { @@ -1613,7 +1616,7 @@ impl<'a, W: Write> Visitor for Formatter<'a, W> { // }); let loc = Loc::File( source_unit - .loc() + .loc_opt() .or_else(|| self.comments.iter().next().map(|comment| comment.loc)) .map(|loc| loc.file_no()) .unwrap_or_default(), @@ -1651,6 +1654,7 @@ impl<'a, W: Write> Visitor for Formatter<'a, W> { Ok(()) } + #[instrument(name = "contract", skip_all)] fn visit_contract(&mut self, contract: &mut ContractDefinition) -> Result<()> { return_source_if_disabled!(self, contract.loc); @@ -1693,7 +1697,7 @@ impl<'a, W: Write> Visitor for Formatter<'a, W> { let base_end = contract.parts.first().map(|part| part.loc().start()); let bases = fmt.items_to_chunks( base_end, - contract.base.iter_mut().map(|base| Ok((base.loc, base))), + contract.base.iter_mut().map(|base| (base.loc, base)), )?; let multiline = fmt.are_chunks_separated_multiline("{}", &bases, ",")?; @@ -1771,6 +1775,7 @@ impl<'a, W: Write> Visitor for Formatter<'a, W> { Ok(()) } + #[instrument(name = "pragma", skip_all)] fn visit_pragma( &mut self, loc: Loc, @@ -1796,6 +1801,7 @@ impl<'a, W: Write> Visitor for Formatter<'a, W> { Ok(()) } + #[instrument(name = "import_plain", skip_all)] fn visit_import_plain(&mut self, loc: Loc, import: &mut StringLiteral) -> Result<()> { return_source_if_disabled!(self, loc, ';'); @@ -1808,6 +1814,7 @@ impl<'a, W: Write> Visitor for Formatter<'a, W> { Ok(()) } + #[instrument(name = "import_global", skip_all)] fn visit_import_global( &mut self, loc: Loc, @@ -1827,6 +1834,7 @@ impl<'a, W: Write> Visitor for Formatter<'a, W> { Ok(()) } + #[instrument(name = "import_renames", skip_all)] fn visit_import_renames( &mut self, loc: Loc, @@ -1895,6 +1903,7 @@ impl<'a, W: Write> Visitor for Formatter<'a, W> { Ok(()) } + #[instrument(name = "enum", skip_all)] fn visit_enum(&mut self, enumeration: &mut EnumDefinition) -> Result<()> { return_source_if_disabled!(self, enumeration.loc); @@ -1919,7 +1928,7 @@ impl<'a, W: Write> Visitor for Formatter<'a, W> { Some(enumeration.loc.end()), enumeration.values.iter_mut().map(|ident| { let ident = ident.safe_unwrap_mut(); - Ok((ident.loc, ident)) + (ident.loc, ident) }), )?; fmt.write_chunks_separated(&values, ",", true)?; @@ -1931,6 +1940,7 @@ impl<'a, W: Write> Visitor for Formatter<'a, W> { Ok(()) } + #[instrument(name = "expr", skip_all)] fn visit_expr(&mut self, loc: Loc, expr: &mut Expression) -> Result<()> { return_source_if_disabled!(self, loc); @@ -2091,7 +2101,7 @@ impl<'a, W: Write> Visitor for Formatter<'a, W> { write_chunk!(self, loc.start(), "[")?; let chunks = self.items_to_chunks( Some(loc.end()), - exprs.iter_mut().map(|expr| Ok((expr.loc(), expr))), + exprs.iter_mut().map(|expr| (expr.loc(), expr)), )?; let multiline = self.are_chunks_separated_multiline("{}]", &chunks, ",")?; self.indented_if(multiline, 1, |fmt| { @@ -2110,7 +2120,6 @@ impl<'a, W: Write> Visitor for Formatter<'a, W> { Expression::PreDecrement(..) | Expression::PostDecrement(..) | Expression::Not(..) | - Expression::Complement(..) | Expression::UnaryPlus(..) | Expression::Add(..) | Expression::Negate(..) | @@ -2121,6 +2130,7 @@ impl<'a, W: Write> Visitor for Formatter<'a, W> { Expression::Modulo(..) | Expression::ShiftLeft(..) | Expression::ShiftRight(..) | + Expression::BitwiseNot(..) | Expression::BitwiseAnd(..) | Expression::BitwiseXor(..) | Expression::BitwiseOr(..) | @@ -2228,7 +2238,7 @@ impl<'a, W: Write> Visitor for Formatter<'a, W> { |fmt, _| { let items = fmt.items_to_chunks( Some(loc.end()), - items.iter_mut().map(|item| Ok((item.0, &mut item.1))), + items.iter_mut().map(|(loc, item)| (*loc, item)), )?; let write_items = |fmt: &mut Self, multiline| { fmt.write_chunks_separated(&items, ",", multiline) @@ -2260,12 +2270,14 @@ impl<'a, W: Write> Visitor for Formatter<'a, W> { Ok(()) } + #[instrument(name = "ident", skip_all)] fn visit_ident(&mut self, loc: Loc, ident: &mut Identifier) -> Result<()> { return_source_if_disabled!(self, loc); write_chunk!(self, loc.end(), "{}", ident.name)?; Ok(()) } + #[instrument(name = "ident_path", skip_all)] fn visit_ident_path(&mut self, idents: &mut IdentifierPath) -> Result<(), Self::Error> { if idents.identifiers.is_empty() { return Ok(()) @@ -2279,7 +2291,7 @@ impl<'a, W: Write> Visitor for Formatter<'a, W> { }); let chunks = self.items_to_chunks( Some(idents.loc.end()), - idents.identifiers.iter_mut().map(|ident| Ok((ident.loc, ident))), + idents.identifiers.iter_mut().map(|ident| (ident.loc, ident)), )?; self.grouped(|fmt| { let multiline = fmt.are_chunks_separated_multiline("{}", &chunks, "")?; @@ -2288,6 +2300,7 @@ impl<'a, W: Write> Visitor for Formatter<'a, W> { Ok(()) } + #[instrument(name = "emit", skip_all)] fn visit_emit(&mut self, loc: Loc, event: &mut Expression) -> Result<()> { return_source_if_disabled!(self, loc); write_chunk!(self, loc.start(), "emit")?; @@ -2296,6 +2309,7 @@ impl<'a, W: Write> Visitor for Formatter<'a, W> { Ok(()) } + #[instrument(name = "var_declaration", skip_all)] fn visit_var_declaration( &mut self, var: &mut VariableDeclaration, @@ -2320,6 +2334,7 @@ impl<'a, W: Write> Visitor for Formatter<'a, W> { Ok(()) } + #[instrument(name = "break", skip_all)] fn visit_break(&mut self, loc: Loc, semicolon: bool) -> Result<()> { if semicolon { return_source_if_disabled!(self, loc, ';'); @@ -2329,6 +2344,7 @@ impl<'a, W: Write> Visitor for Formatter<'a, W> { write_chunk!(self, loc.start(), loc.end(), "break{}", if semicolon { ";" } else { "" }) } + #[instrument(name = "continue", skip_all)] fn visit_continue(&mut self, loc: Loc, semicolon: bool) -> Result<()> { if semicolon { return_source_if_disabled!(self, loc, ';'); @@ -2338,6 +2354,7 @@ impl<'a, W: Write> Visitor for Formatter<'a, W> { write_chunk!(self, loc.start(), loc.end(), "continue{}", if semicolon { ";" } else { "" }) } + #[instrument(name = "function", skip_all)] fn visit_function(&mut self, func: &mut FunctionDefinition) -> Result<()> { if func.body.is_some() { return_source_if_disabled!(self, func.loc()); @@ -2349,7 +2366,7 @@ impl<'a, W: Write> Visitor for Formatter<'a, W> { fmt.write_postfix_comments_before(func.loc.start())?; fmt.write_prefix_comments_before(func.loc.start())?; - let body_loc = func.body.as_ref().map(LineOfCode::loc); + let body_loc = func.body.as_ref().map(CodeLocation::loc); let mut attrs_multiline = false; let fits_on_single = fmt.try_on_single_line(|fmt| { fmt.write_function_header(func, body_loc, false)?; @@ -2362,7 +2379,7 @@ impl<'a, W: Write> Visitor for Formatter<'a, W> { // write function body match &mut func.body { Some(body) => { - let body_loc = body_loc.unwrap(); + let body_loc = body.loc(); let byte_offset = body_loc.start(); let body = fmt.visit_to_chunk(byte_offset, Some(body_loc.end()), body)?; fmt.write_whitespace_separator( @@ -2379,6 +2396,7 @@ impl<'a, W: Write> Visitor for Formatter<'a, W> { Ok(()) } + #[instrument(name = "function_attribute", skip_all)] fn visit_function_attribute(&mut self, attribute: &mut FunctionAttribute) -> Result<()> { return_source_if_disabled!(self, attribute.loc()); @@ -2388,7 +2406,7 @@ impl<'a, W: Write> Visitor for Formatter<'a, W> { } FunctionAttribute::Visibility(visibility) => { // Visibility will always have a location in a Function attribute - write_chunk!(self, visibility.loc().unwrap().end(), "{visibility}")? + write_chunk!(self, visibility.loc_opt().unwrap().end(), "{visibility}")? } FunctionAttribute::Virtual(loc) => write_chunk!(self, loc.end(), "virtual")?, FunctionAttribute::Immutable(loc) => write_chunk!(self, loc.end(), "immutable")?, @@ -2428,6 +2446,7 @@ impl<'a, W: Write> Visitor for Formatter<'a, W> { Ok(()) } + #[instrument(name = "base", skip_all)] fn visit_base(&mut self, base: &mut Base) -> Result<()> { return_source_if_disabled!(self, base.loc); @@ -2446,7 +2465,7 @@ impl<'a, W: Write> Visitor for Formatter<'a, W> { } let args = base.args.as_mut().unwrap(); - let args_start = LineOfCode::loc(args.first().unwrap()).start(); + let args_start = CodeLocation::loc(args.first().unwrap()).start(); name.content.push('('); let formatted_name = self.chunk_to_string(&name)?; @@ -2459,7 +2478,7 @@ impl<'a, W: Write> Visitor for Formatter<'a, W> { |fmt, multiline_hint| { let args = fmt.items_to_chunks( Some(base.loc.end()), - args.iter_mut().map(|arg| Ok((arg.loc(), arg))), + args.iter_mut().map(|arg| (arg.loc(), arg)), )?; let multiline = multiline || multiline_hint || @@ -2472,6 +2491,7 @@ impl<'a, W: Write> Visitor for Formatter<'a, W> { Ok(()) } + #[instrument(name = "parameter", skip_all)] fn visit_parameter(&mut self, parameter: &mut Parameter) -> Result<()> { return_source_if_disabled!(self, parameter.loc); self.grouped(|fmt| { @@ -2487,6 +2507,7 @@ impl<'a, W: Write> Visitor for Formatter<'a, W> { Ok(()) } + #[instrument(name = "struct", skip_all)] fn visit_struct(&mut self, structure: &mut StructDefinition) -> Result<()> { return_source_if_disabled!(self, structure.loc); self.grouped(|fmt| { @@ -2504,7 +2525,7 @@ impl<'a, W: Write> Visitor for Formatter<'a, W> { |fmt, _multiline| { let chunks = fmt.items_to_chunks( Some(structure.loc.end()), - structure.fields.iter_mut().map(|ident| Ok((ident.loc, ident))), + structure.fields.iter_mut().map(|ident| (ident.loc, ident)), )?; for mut chunk in chunks { chunk.content.push(';'); @@ -2519,12 +2540,13 @@ impl<'a, W: Write> Visitor for Formatter<'a, W> { Ok(()) } + #[instrument(name = "type_definition", skip_all)] fn visit_type_definition(&mut self, def: &mut TypeDefinition) -> Result<()> { return_source_if_disabled!(self, def.loc, ';'); self.grouped(|fmt| { write_chunk!(fmt, def.loc.start(), def.name.loc.start(), "type")?; def.name.visit(fmt)?; - write_chunk!(fmt, def.name.loc.end(), LineOfCode::loc(&def.ty).start(), "is")?; + write_chunk!(fmt, def.name.loc.end(), CodeLocation::loc(&def.ty).start(), "is")?; def.ty.visit(fmt)?; fmt.write_semicolon()?; Ok(()) @@ -2532,11 +2554,12 @@ impl<'a, W: Write> Visitor for Formatter<'a, W> { Ok(()) } + #[instrument(name = "stray_semicolon", skip_all)] fn visit_stray_semicolon(&mut self) -> Result<()> { - self.write_semicolon()?; - Ok(()) + self.write_semicolon() } + #[instrument(name = "block", skip_all)] fn visit_block( &mut self, loc: Loc, @@ -2552,21 +2575,25 @@ impl<'a, W: Write> Visitor for Formatter<'a, W> { Ok(()) } + #[instrument(name = "opening_paren", skip_all)] fn visit_opening_paren(&mut self) -> Result<()> { write_chunk!(self, "(")?; Ok(()) } + #[instrument(name = "closing_paren", skip_all)] fn visit_closing_paren(&mut self) -> Result<()> { write_chunk!(self, ")")?; Ok(()) } + #[instrument(name = "newline", skip_all)] fn visit_newline(&mut self) -> Result<()> { writeln_chunk!(self)?; Ok(()) } + #[instrument(name = "event", skip_all)] fn visit_event(&mut self, event: &mut EventDefinition) -> Result<()> { return_source_if_disabled!(self, event.loc, ';'); @@ -2586,10 +2613,8 @@ impl<'a, W: Write> Visitor for Formatter<'a, W> { SurroundingChunk::new(first_chunk, Some(byte_offset), None), SurroundingChunk::new(last_chunk, None, Some(event.loc.end())), |fmt, multiline| { - let params = fmt.items_to_chunks( - None, - event.fields.iter_mut().map(|arg| Ok((arg.loc, arg))), - )?; + let params = fmt + .items_to_chunks(None, event.fields.iter_mut().map(|arg| (arg.loc, arg)))?; let multiline = multiline && fmt.are_chunks_separated_multiline("{}", ¶ms, ",")?; @@ -2601,6 +2626,7 @@ impl<'a, W: Write> Visitor for Formatter<'a, W> { Ok(()) } + #[instrument(name = "event_parameter", skip_all)] fn visit_event_parameter(&mut self, param: &mut EventParameter) -> Result<()> { return_source_if_disabled!(self, param.loc); @@ -2617,6 +2643,7 @@ impl<'a, W: Write> Visitor for Formatter<'a, W> { Ok(()) } + #[instrument(name = "error", skip_all)] fn visit_error(&mut self, error: &mut ErrorDefinition) -> Result<()> { return_source_if_disabled!(self, error.loc, ';'); @@ -2633,6 +2660,7 @@ impl<'a, W: Write> Visitor for Formatter<'a, W> { Ok(()) } + #[instrument(name = "error_parameter", skip_all)] fn visit_error_parameter(&mut self, param: &mut ErrorParameter) -> Result<()> { return_source_if_disabled!(self, param.loc); self.grouped(|fmt| { @@ -2645,12 +2673,13 @@ impl<'a, W: Write> Visitor for Formatter<'a, W> { Ok(()) } + #[instrument(name = "using", skip_all)] fn visit_using(&mut self, using: &mut Using) -> Result<()> { return_source_if_disabled!(self, using.loc, ';'); write_chunk!(self, using.loc.start(), "using")?; - let ty_start = using.ty.as_mut().map(|ty| LineOfCode::loc(&ty).start()); + let ty_start = using.ty.as_mut().map(|ty| CodeLocation::loc(&ty).start()); let global_start = using.global.as_mut().map(|global| global.loc.start()); let loc_end = using.loc.end(); @@ -2673,7 +2702,7 @@ impl<'a, W: Write> Visitor for Formatter<'a, W> { } (false, chunks) } - UsingList::Error() => return self.visit_parser_error(using.loc), + UsingList::Error => return self.visit_parser_error(using.loc), }; let for_chunk = self.chunk_at( @@ -2747,6 +2776,7 @@ impl<'a, W: Write> Visitor for Formatter<'a, W> { Ok(()) } + #[instrument(name = "var_attribute", skip_all)] fn visit_var_attribute(&mut self, attribute: &mut VariableAttribute) -> Result<()> { return_source_if_disabled!(self, attribute.loc()); @@ -2770,6 +2800,7 @@ impl<'a, W: Write> Visitor for Formatter<'a, W> { Ok(()) } + #[instrument(name = "var_definition", skip_all)] fn visit_var_definition(&mut self, var: &mut VariableDefinition) -> Result<()> { return_source_if_disabled!(self, var.loc, ';'); @@ -2779,10 +2810,7 @@ impl<'a, W: Write> Visitor for Formatter<'a, W> { let var_name = var.name.safe_unwrap_mut(); let name_start = var_name.loc.start(); - let attrs = fmt.items_to_chunks_sorted( - Some(name_start), - var.attrs.iter_mut().map(|attr| Ok((attr.loc(), attr))), - )?; + let attrs = fmt.items_to_chunks_sorted(Some(name_start), var.attrs.iter_mut())?; if !fmt.try_on_single_line(|fmt| fmt.write_chunks_separated(&attrs, "", false))? { fmt.write_chunks_separated(&attrs, "", true)?; } @@ -2806,6 +2834,7 @@ impl<'a, W: Write> Visitor for Formatter<'a, W> { Ok(()) } + #[instrument(name = "var_definition_stmt", skip_all)] fn visit_var_definition_stmt( &mut self, loc: Loc, @@ -2835,6 +2864,7 @@ impl<'a, W: Write> Visitor for Formatter<'a, W> { Ok(()) } + #[instrument(name = "for", skip_all)] fn visit_for( &mut self, loc: Loc, @@ -2907,6 +2937,7 @@ impl<'a, W: Write> Visitor for Formatter<'a, W> { Ok(()) } + #[instrument(name = "while", skip_all)] fn visit_while( &mut self, loc: Loc, @@ -2930,6 +2961,7 @@ impl<'a, W: Write> Visitor for Formatter<'a, W> { Ok(()) } + #[instrument(name = "do_while", skip_all)] fn visit_do_while( &mut self, loc: Loc, @@ -2949,6 +2981,7 @@ impl<'a, W: Write> Visitor for Formatter<'a, W> { Ok(()) } + #[instrument(name = "if", skip_all)] fn visit_if( &mut self, loc: Loc, @@ -2974,6 +3007,7 @@ impl<'a, W: Write> Visitor for Formatter<'a, W> { }; Ok(()) })?; + if stmt_fits_on_single { tx.commit()?; } else { @@ -2985,6 +3019,7 @@ impl<'a, W: Write> Visitor for Formatter<'a, W> { Ok(()) } + #[instrument(name = "args", skip_all)] fn visit_args(&mut self, loc: Loc, args: &mut Vec) -> Result<(), Self::Error> { return_source_if_disabled!(self, loc); @@ -3031,6 +3066,7 @@ impl<'a, W: Write> Visitor for Formatter<'a, W> { Ok(()) } + #[instrument(name = "revert", skip_all)] fn visit_revert( &mut self, loc: Loc, @@ -3048,6 +3084,7 @@ impl<'a, W: Write> Visitor for Formatter<'a, W> { Ok(()) } + #[instrument(name = "revert_named_args", skip_all)] fn visit_revert_named_args( &mut self, loc: Loc, @@ -3078,6 +3115,7 @@ impl<'a, W: Write> Visitor for Formatter<'a, W> { Ok(()) } + #[instrument(name = "return", skip_all)] fn visit_return(&mut self, loc: Loc, expr: &mut Option) -> Result<(), Self::Error> { return_source_if_disabled!(self, loc, ';'); @@ -3133,7 +3171,7 @@ impl<'a, W: Write> Visitor for Formatter<'a, W> { Ok(()) } - #[allow(clippy::unused_peekable)] + #[instrument(name = "try", skip_all)] fn visit_try( &mut self, loc: Loc, @@ -3160,7 +3198,7 @@ impl<'a, W: Write> Visitor for Formatter<'a, W> { |fmt, _| { let chunks = fmt.items_to_chunks( Some(stmt.loc().start()), - params.iter_mut().map(|(loc, ref mut ident)| Ok((*loc, ident))), + params.iter_mut().map(|(loc, ref mut ident)| (*loc, ident)), )?; let multiline = fmt.are_chunks_separated_multiline("{})", &chunks, ",")?; fmt.write_chunks_separated(&chunks, ",", multiline)?; @@ -3243,6 +3281,7 @@ impl<'a, W: Write> Visitor for Formatter<'a, W> { Ok(()) } + #[instrument(name = "assembly", skip_all)] fn visit_assembly( &mut self, loc: Loc, @@ -3287,6 +3326,7 @@ impl<'a, W: Write> Visitor for Formatter<'a, W> { block.visit(self) } + #[instrument(name = "yul_block", skip_all)] fn visit_yul_block( &mut self, loc: Loc, @@ -3298,6 +3338,7 @@ impl<'a, W: Write> Visitor for Formatter<'a, W> { Ok(()) } + #[instrument(name = "yul_assignment", skip_all)] fn visit_yul_assignment( &mut self, loc: Loc, @@ -3305,13 +3346,13 @@ impl<'a, W: Write> Visitor for Formatter<'a, W> { expr: &mut Option<&mut YulExpression>, ) -> Result<(), Self::Error> where - T: Visitable + LineOfCode, + T: Visitable + CodeLocation, { return_source_if_disabled!(self, loc); self.grouped(|fmt| { let chunks = - fmt.items_to_chunks(None, exprs.iter_mut().map(|expr| Ok((expr.loc(), expr))))?; + fmt.items_to_chunks(None, exprs.iter_mut().map(|expr| (expr.loc(), expr)))?; let multiline = fmt.are_chunks_separated_multiline("{} := ", &chunks, ",")?; fmt.write_chunks_separated(&chunks, ",", multiline)?; @@ -3329,6 +3370,7 @@ impl<'a, W: Write> Visitor for Formatter<'a, W> { Ok(()) } + #[instrument(name = "yul_expr", skip_all)] fn visit_yul_expr(&mut self, expr: &mut YulExpression) -> Result<(), Self::Error> { return_source_if_disabled!(self, expr.loc()); @@ -3372,6 +3414,7 @@ impl<'a, W: Write> Visitor for Formatter<'a, W> { } } + #[instrument(name = "yul_for", skip_all)] fn visit_yul_for(&mut self, stmt: &mut YulFor) -> Result<(), Self::Error> { return_source_if_disabled!(self, stmt.loc); write_chunk!(self, stmt.loc.start(), "for")?; @@ -3382,17 +3425,20 @@ impl<'a, W: Write> Visitor for Formatter<'a, W> { Ok(()) } + #[instrument(name = "yul_function_call", skip_all)] fn visit_yul_function_call(&mut self, stmt: &mut YulFunctionCall) -> Result<(), Self::Error> { return_source_if_disabled!(self, stmt.loc); write_chunk!(self, stmt.loc.start(), "{}", stmt.id.name)?; self.visit_list("", &mut stmt.arguments, None, Some(stmt.loc.end()), true) } + #[instrument(name = "yul_typed_ident", skip_all)] fn visit_yul_typed_ident(&mut self, ident: &mut YulTypedIdentifier) -> Result<(), Self::Error> { return_source_if_disabled!(self, ident.loc); self.visit_yul_string_with_ident(ident.loc, &ident.id.name, &mut ident.ty) } + #[instrument(name = "yul_fun_def", skip_all)] fn visit_yul_fun_def(&mut self, stmt: &mut YulFunctionDefinition) -> Result<(), Self::Error> { return_source_if_disabled!(self, stmt.loc); @@ -3406,7 +3452,7 @@ impl<'a, W: Write> Visitor for Formatter<'a, W> { let chunks = fmt.items_to_chunks( Some(stmt.body.loc.start()), - stmt.returns.iter_mut().map(|param| Ok((param.loc, param))), + stmt.returns.iter_mut().map(|param| (param.loc, param)), )?; let multiline = fmt.are_chunks_separated_multiline("{}", &chunks, ",")?; fmt.write_chunks_separated(&chunks, ",", multiline)?; @@ -3422,6 +3468,7 @@ impl<'a, W: Write> Visitor for Formatter<'a, W> { Ok(()) } + #[instrument(name = "yul_if", skip_all)] fn visit_yul_if( &mut self, loc: Loc, @@ -3434,11 +3481,13 @@ impl<'a, W: Write> Visitor for Formatter<'a, W> { self.visit_yul_block(block.loc, &mut block.statements, true) } + #[instrument(name = "yul_leave", skip_all)] fn visit_yul_leave(&mut self, loc: Loc) -> Result<(), Self::Error> { return_source_if_disabled!(self, loc); write_chunk!(self, loc.start(), loc.end(), "leave") } + #[instrument(name = "yul_switch", skip_all)] fn visit_yul_switch(&mut self, stmt: &mut YulSwitch) -> Result<(), Self::Error> { return_source_if_disabled!(self, stmt.loc); @@ -3462,6 +3511,7 @@ impl<'a, W: Write> Visitor for Formatter<'a, W> { Ok(()) } + #[instrument(name = "yul_var_declaration", skip_all)] fn visit_yul_var_declaration( &mut self, loc: Loc, @@ -3477,6 +3527,7 @@ impl<'a, W: Write> Visitor for Formatter<'a, W> { } // Support extension for Solana/Substrate + #[instrument(name = "annotation", skip_all)] fn visit_annotation(&mut self, annotation: &mut Annotation) -> Result<()> { return_source_if_disabled!(self, annotation.loc); let id = self.simulate_to_string(|fmt| annotation.id.visit(fmt))?; @@ -3487,207 +3538,8 @@ impl<'a, W: Write> Visitor for Formatter<'a, W> { Ok(()) } + #[instrument(name = "parser_error", skip_all)] fn visit_parser_error(&mut self, loc: Loc) -> Result<()> { Err(FormatterError::InvalidParsedItem(loc)) } } - -#[cfg(test)] -mod tests { - use crate::{format, parse}; - use itertools::Itertools; - use std::{fs, path::PathBuf}; - - use super::*; - - fn test_directory(base_name: &str) { - let mut original = None; - - let tests = fs::read_dir( - PathBuf::from(env!("CARGO_MANIFEST_DIR")).join("testdata").join(base_name), - ) - .unwrap() - .filter_map(|path| { - let path = path.unwrap().path(); - let source = fs::read_to_string(&path).unwrap(); - - if let Some(filename) = path.file_name().and_then(|name| name.to_str()) { - if filename == "original.sol" { - original = Some(source); - } else if filename - .strip_suffix("fmt.sol") - .map(|filename| filename.strip_suffix('.')) - .is_some() - { - // The majority of the tests were written with the assumption - // that the default value for max line length is `80`. - // Preserve that to avoid rewriting test logic. - let default_config = FormatterConfig { line_length: 80, ..Default::default() }; - - let mut config = toml::Value::try_from(&default_config).unwrap(); - let config_table = config.as_table_mut().unwrap(); - let mut lines = source.split('\n').peekable(); - let mut line_num = 1; - while let Some(line) = lines.peek() { - let entry = line - .strip_prefix("//") - .and_then(|line| line.trim().strip_prefix("config:")) - .map(str::trim); - let entry = if let Some(entry) = entry { entry } else { break }; - - let values = match toml::from_str::(entry) { - Ok(toml::Value::Table(table)) => table, - _ => panic!("Invalid config item in {filename} at {line_num}"), - }; - config_table.extend(values); - - line_num += 1; - lines.next(); - } - let config = config - .try_into() - .unwrap_or_else(|err| panic!("Invalid config for {filename}: {err}")); - - return Some((filename.to_string(), config, lines.join("\n"))) - } - } - - None - }) - .collect::>(); - - for (filename, config, formatted) in tests { - test_formatter( - &filename, - config, - original.as_ref().expect("original.sol not found"), - &formatted, - ); - } - } - - fn assert_eof(content: &str) { - assert!(content.ends_with('\n') && !content.ends_with("\n\n")); - } - - fn test_formatter( - filename: &str, - config: FormatterConfig, - source: &str, - expected_source: &str, - ) { - #[derive(Eq)] - struct PrettyString(String); - - impl PartialEq for PrettyString { - fn eq(&self, other: &PrettyString) -> bool { - self.0.lines().eq(other.0.lines()) - } - } - - impl std::fmt::Debug for PrettyString { - fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { - f.write_str(&self.0) - } - } - - assert_eof(expected_source); - - let source_parsed = parse(source).unwrap(); - let expected_parsed = parse(expected_source).unwrap(); - - if !source_parsed.pt.ast_eq(&expected_parsed.pt) { - pretty_assertions::assert_eq!( - source_parsed.pt, - expected_parsed.pt, - "(formatted Parse Tree == expected Parse Tree) in {}", - filename - ); - } - - let expected = PrettyString(expected_source.to_string()); - - let mut source_formatted = String::new(); - format(&mut source_formatted, source_parsed, config.clone()).unwrap(); - assert_eof(&source_formatted); - - // println!("{}", source_formatted); - let source_formatted = PrettyString(source_formatted); - - pretty_assertions::assert_eq!( - source_formatted, - expected, - "(formatted == expected) in {}", - filename - ); - - let mut expected_formatted = String::new(); - format(&mut expected_formatted, expected_parsed, config).unwrap(); - assert_eof(&expected_formatted); - - let expected_formatted = PrettyString(expected_formatted); - - pretty_assertions::assert_eq!( - expected_formatted, - expected, - "(formatted == expected) in {}", - filename - ); - } - - macro_rules! test_directory { - ($dir:ident) => { - #[allow(non_snake_case)] - #[test] - fn $dir() { - test_directory(stringify!($dir)); - } - }; - } - - test_directory! { ConstructorDefinition } - test_directory! { ContractDefinition } - test_directory! { DocComments } - test_directory! { EnumDefinition } - test_directory! { ErrorDefinition } - test_directory! { EventDefinition } - test_directory! { FunctionDefinition } - test_directory! { FunctionType } - test_directory! { ImportDirective } - test_directory! { ModifierDefinition } - test_directory! { StatementBlock } - test_directory! { StructDefinition } - test_directory! { TypeDefinition } - test_directory! { UsingDirective } - test_directory! { VariableDefinition } - test_directory! { OperatorExpressions } - test_directory! { WhileStatement } - test_directory! { DoWhileStatement } - test_directory! { ForStatement } - test_directory! { IfStatement } - test_directory! { VariableAssignment } - test_directory! { FunctionCallArgsStatement } - test_directory! { RevertStatement } - test_directory! { RevertNamedArgsStatement } - test_directory! { ReturnStatement } - test_directory! { TryStatement } - test_directory! { ConditionalOperatorExpression } - test_directory! { NamedFunctionCallExpression } - test_directory! { ArrayExpressions } - test_directory! { UnitExpression } - test_directory! { ThisExpression } - test_directory! { SimpleComments } - test_directory! { LiteralExpression } - test_directory! { Yul } - test_directory! { YulStrings } - test_directory! { IntTypes } - test_directory! { InlineDisable } - test_directory! { NumberLiteralUnderscore } - test_directory! { FunctionCall } - test_directory! { TrailingComma } - test_directory! { PragmaDirective } - test_directory! { Annotation } - test_directory! { MappingType } - test_directory! { EmitStatement } - test_directory! { Repros } -} diff --git a/fmt/src/helpers.rs b/fmt/src/helpers.rs index 36161cad6d11..49b04c0a484e 100644 --- a/fmt/src/helpers.rs +++ b/fmt/src/helpers.rs @@ -5,7 +5,7 @@ use crate::{ use ariadne::{Color, Fmt, Label, Report, ReportKind, Source}; use itertools::Itertools; use solang_parser::{diagnostics::Diagnostic, pt::*}; -use std::path::PathBuf; +use std::{fmt::Write, path::PathBuf}; /// Result of parsing the source code #[derive(Debug)] @@ -33,11 +33,12 @@ pub fn parse(src: &str) -> Result> { } /// Format parsed code -pub fn format( - writer: &mut W, +pub fn format( + writer: W, mut parsed: Parsed, config: FormatterConfig, ) -> Result<(), FormatterError> { + trace!(?parsed, ?config, "Formatting"); let mut formatter = Formatter::new(writer, parsed.src, parsed.comments, parsed.inline_config, config); parsed.pt.visit(&mut formatter) diff --git a/fmt/src/lib.rs b/fmt/src/lib.rs index 3c32b28ebb1b..8ece42f8a7a1 100644 --- a/fmt/src/lib.rs +++ b/fmt/src/lib.rs @@ -1,5 +1,8 @@ #![doc = include_str!("../README.md")] +#[macro_use] +extern crate tracing; + mod buffer; pub mod chunk; mod comments; diff --git a/fmt/src/solang_ext/ast_eq.rs b/fmt/src/solang_ext/ast_eq.rs index 2a0761c248f4..f317530001ad 100644 --- a/fmt/src/solang_ext/ast_eq.rs +++ b/fmt/src/solang_ext/ast_eq.rs @@ -1,4 +1,3 @@ -use super::AttrSortKeyIteratorExt; use ethers_core::types::{H160, I256, U256}; use solang_parser::pt::*; use std::str::FromStr; @@ -52,25 +51,28 @@ impl AstEq for SourceUnit { impl AstEq for VariableDefinition { fn ast_eq(&self, other: &Self) -> bool { - let sort_attrs = - |def: &Self| def.attrs.clone().into_iter().attr_sorted().collect::>(); - let left_sorted_attrs = sort_attrs(self); - let right_sorted_attrs = sort_attrs(other); + let sorted_attrs = |def: &Self| { + let mut attrs = def.attrs.clone(); + attrs.sort(); + attrs + }; self.ty.ast_eq(&other.ty) && self.name.ast_eq(&other.name) && self.initializer.ast_eq(&other.initializer) && - left_sorted_attrs.ast_eq(&right_sorted_attrs) + sorted_attrs(self).ast_eq(&sorted_attrs(other)) } } impl AstEq for FunctionDefinition { fn ast_eq(&self, other: &Self) -> bool { // attributes - let sort_attrs = - |def: &Self| def.attributes.clone().into_iter().attr_sorted().collect::>(); - let left_sorted_attrs = sort_attrs(self); - let right_sorted_attrs = sort_attrs(other); + let sorted_attrs = |def: &Self| { + let mut attrs = def.attributes.clone(); + attrs.sort(); + attrs + }; + // params let left_params = filter_params(&self.params); let right_params = filter_params(&other.params); let left_returns = filter_params(&self.returns); @@ -82,7 +84,7 @@ impl AstEq for FunctionDefinition { self.return_not_returns.ast_eq(&other.return_not_returns) && left_returns.ast_eq(&right_returns) && self.body.ast_eq(&other.body) && - left_sorted_attrs.ast_eq(&right_sorted_attrs) + sorted_attrs(self).ast_eq(&sorted_attrs(other)) } } @@ -420,15 +422,15 @@ derive_ast_eq! { struct StructDefinition { loc, name, fields } } derive_ast_eq! { struct EnumDefinition { loc, name, values } } derive_ast_eq! { struct Annotation { loc, id, value } } derive_ast_eq! { enum UsingList { + Error, _ Library(expr), Functions(exprs), - Error(), _ }} derive_ast_eq! { enum UserDefinedOperator { BitwiseAnd, - Complement, + BitwiseNot, Negate, BitwiseOr, BitwiseXor, @@ -513,7 +515,7 @@ derive_ast_eq! { enum Expression { FunctionCallBlock(loc, expr1, stmt), NamedFunctionCall(loc, expr1, args), Not(loc, expr1), - Complement(loc, expr1), + BitwiseNot(loc, expr1), Delete(loc, expr1), PreIncrement(loc, expr1), PreDecrement(loc, expr1), diff --git a/fmt/src/solang_ext/attr_sort_key.rs b/fmt/src/solang_ext/attr_sort_key.rs deleted file mode 100644 index 78b3018f1853..000000000000 --- a/fmt/src/solang_ext/attr_sort_key.rs +++ /dev/null @@ -1,64 +0,0 @@ -use itertools::Itertools; -use solang_parser::pt::*; - -/// Describes the default sort of attributes -pub trait AttrSortKey { - fn attr_sort_key(&self) -> usize; -} - -impl AttrSortKey for VariableAttribute { - fn attr_sort_key(&self) -> usize { - match self { - VariableAttribute::Visibility(..) => 0, - VariableAttribute::Constant(..) => 1, - VariableAttribute::Immutable(..) => 2, - VariableAttribute::Override(..) => 3, - } - } -} - -impl AttrSortKey for FunctionAttribute { - fn attr_sort_key(&self) -> usize { - match self { - FunctionAttribute::Visibility(..) => 0, - FunctionAttribute::Mutability(..) => 1, - FunctionAttribute::Virtual(..) => 2, - FunctionAttribute::Immutable(..) => 3, - FunctionAttribute::Override(..) => 4, - FunctionAttribute::BaseOrModifier(..) => 5, - FunctionAttribute::Error(..) => 6, // supposed to be omitted even if sorted - } - } -} - -impl AttrSortKey for &T -where - T: AttrSortKey, -{ - fn attr_sort_key(&self) -> usize { - T::attr_sort_key(self) - } -} - -impl AttrSortKey for &mut T -where - T: AttrSortKey, -{ - fn attr_sort_key(&self) -> usize { - T::attr_sort_key(self) - } -} - -pub trait AttrSortKeyIteratorExt: Iterator { - fn attr_sorted(self) -> std::vec::IntoIter; -} - -impl AttrSortKeyIteratorExt for I -where - I: Iterator, - I::Item: AttrSortKey, -{ - fn attr_sorted(self) -> std::vec::IntoIter { - self.sorted_by_key(|item| item.attr_sort_key()) - } -} diff --git a/fmt/src/solang_ext/is_empty.rs b/fmt/src/solang_ext/is_empty.rs deleted file mode 100644 index b766e3115540..000000000000 --- a/fmt/src/solang_ext/is_empty.rs +++ /dev/null @@ -1,25 +0,0 @@ -use solang_parser::pt::*; - -/// Describes if a block is empty or not -pub trait IsEmpty { - fn is_empty(&self) -> bool; -} - -impl IsEmpty for Statement { - fn is_empty(&self) -> bool { - match self { - Statement::Block { statements, .. } => statements.is_empty(), - _ => false, - } - } -} - -impl IsEmpty for FunctionDefinition { - fn is_empty(&self) -> bool { - if let Some(body) = &self.body { - body.is_empty() - } else { - true - } - } -} diff --git a/fmt/src/solang_ext/loc.rs b/fmt/src/solang_ext/loc.rs index 63ed22be284d..e8b3184e8fa8 100644 --- a/fmt/src/solang_ext/loc.rs +++ b/fmt/src/solang_ext/loc.rs @@ -1,482 +1,147 @@ -use solang_parser::pt::*; +use solang_parser::pt; +use std::{borrow::Cow, rc::Rc, sync::Arc}; -/// Get the location of an Enum -pub trait LineOfCode { - fn loc(&self) -> Loc; +/// Returns the code location. +/// +/// Patched version of [`pt::CodeLocation`]: includes the block of a [`pt::FunctionDefinition`] in +/// its `loc`. +pub trait CodeLocationExt { + /// Returns the code location of `self`. + fn loc(&self) -> pt::Loc; } -/// Get the location of an Enum if it has one -pub trait OptionalLineOfCode { - fn loc(&self) -> Option; -} - -impl LineOfCode for Box -where - T: LineOfCode, -{ - fn loc(&self) -> Loc { - T::loc(self) - } -} - -impl LineOfCode for &T -where - T: LineOfCode, -{ - fn loc(&self) -> Loc { - T::loc(self) - } -} - -impl LineOfCode for &mut T -where - T: LineOfCode, -{ - fn loc(&self) -> Loc { - T::loc(self) - } -} - -impl OptionalLineOfCode for Box -where - T: OptionalLineOfCode, -{ - fn loc(&self) -> Option { - T::loc(self) - } -} - -impl OptionalLineOfCode for &T -where - T: OptionalLineOfCode, -{ - fn loc(&self) -> Option { - T::loc(self) - } -} - -impl OptionalLineOfCode for &mut T -where - T: OptionalLineOfCode, -{ - fn loc(&self) -> Option { - T::loc(self) - } -} - -impl LineOfCode for SourceUnitPart { - fn loc(&self) -> Loc { - match self { - SourceUnitPart::ContractDefinition(contract) => contract.loc, - SourceUnitPart::PragmaDirective(loc, _, _) | SourceUnitPart::StraySemicolon(loc) => { - *loc - } - SourceUnitPart::ImportDirective(import) => *match import { - Import::Plain(_, loc) => loc, - Import::GlobalSymbol(_, _, loc) => loc, - Import::Rename(_, _, loc) => loc, - }, - SourceUnitPart::EnumDefinition(enumeration) => enumeration.loc, - SourceUnitPart::StructDefinition(structure) => structure.loc, - SourceUnitPart::EventDefinition(event) => event.loc, - SourceUnitPart::ErrorDefinition(error) => error.loc, - SourceUnitPart::FunctionDefinition(function) => function.loc(), - SourceUnitPart::VariableDefinition(variable) => variable.loc, - SourceUnitPart::TypeDefinition(def) => def.loc, - SourceUnitPart::Using(using) => using.loc, - SourceUnitPart::Annotation(annotation) => annotation.loc, - } - } -} - -impl LineOfCode for ContractPart { - fn loc(&self) -> Loc { - match self { - ContractPart::StructDefinition(structure) => structure.loc, - ContractPart::EventDefinition(event) => event.loc, - ContractPart::ErrorDefinition(error) => error.loc, - ContractPart::EnumDefinition(enumeration) => enumeration.loc, - ContractPart::VariableDefinition(variable) => variable.loc, - ContractPart::FunctionDefinition(function) => function.loc(), - ContractPart::StraySemicolon(loc) => *loc, - ContractPart::Using(using) => using.loc, - ContractPart::TypeDefinition(def) => def.loc, - ContractPart::Annotation(annotation) => annotation.loc, - } +impl<'a, T: ?Sized + CodeLocationExt> CodeLocationExt for &'a T { + fn loc(&self) -> pt::Loc { + (**self).loc() } } -impl LineOfCode for YulStatement { - fn loc(&self) -> Loc { - match self { - YulStatement::Assign(loc, _, _) | - YulStatement::If(loc, _, _) | - YulStatement::Leave(loc) | - YulStatement::Break(loc) | - YulStatement::VariableDeclaration(loc, _, _) | - YulStatement::Continue(loc) => *loc, - YulStatement::For(f) => f.loc, - YulStatement::Block(b) => b.loc, - YulStatement::Switch(s) => s.loc, - YulStatement::FunctionDefinition(f) => f.loc, - YulStatement::FunctionCall(f) => f.loc, - YulStatement::Error(loc) => *loc, - } +impl<'a, T: ?Sized + CodeLocationExt> CodeLocationExt for &'a mut T { + fn loc(&self) -> pt::Loc { + (**self).loc() } } -impl LineOfCode for YulExpression { - fn loc(&self) -> Loc { - match self { - YulExpression::BoolLiteral(loc, _, _) | - YulExpression::NumberLiteral(loc, _, _, _) | - YulExpression::HexNumberLiteral(loc, _, _) | - YulExpression::SuffixAccess(loc, _, _) => *loc, - YulExpression::StringLiteral(literal, _) => literal.loc, - YulExpression::Variable(ident) => ident.loc, - YulExpression::FunctionCall(f) => f.loc, - YulExpression::HexStringLiteral(lit, _) => lit.loc, - } +impl<'a, T: ?Sized + ToOwned + CodeLocationExt> CodeLocationExt for Cow<'a, T> { + fn loc(&self) -> pt::Loc { + (**self).loc() } } -impl LineOfCode for FunctionDefinition { - fn loc(&self) -> Loc { - Loc::File( - self.loc.file_no(), - self.loc.start(), - self.body - .as_ref() - .map(|body| LineOfCode::loc(body).end()) - .unwrap_or_else(|| self.loc.end()), - ) +impl CodeLocationExt for Box { + fn loc(&self) -> pt::Loc { + (**self).loc() } } -impl LineOfCode for Statement { - fn loc(&self) -> Loc { - use Statement::*; - match self { - Block { loc, unchecked: _checked, statements: _statements } => *loc, - Assembly { loc, dialect: _dialect, block: _block, flags: _flags } => *loc, - Args(loc, _) => *loc, - If(loc, _, _, _) => *loc, - While(loc, _, _) => *loc, - Expression(_, expr) => LineOfCode::loc(&expr), - VariableDefinition(loc, _, _) => *loc, - For(loc, _, _, _, _) => *loc, - DoWhile(loc, _, _) => *loc, - Continue(loc) => *loc, - Break(loc) => *loc, - Return(loc, _) => *loc, - Revert(loc, _, _) => *loc, - RevertNamedArgs(loc, _, _) => *loc, - Emit(loc, _) => *loc, - Try(loc, _, _, _) => *loc, - Statement::Error(loc) => *loc, - } +impl CodeLocationExt for Rc { + fn loc(&self) -> pt::Loc { + (**self).loc() } } -impl LineOfCode for Expression { - fn loc(&self) -> Loc { - use Expression::*; - match self { - PostIncrement(loc, _) => *loc, - PostDecrement(loc, _) => *loc, - New(loc, _) => *loc, - ArraySubscript(loc, _, _) => *loc, - ArraySlice(loc, _, _, _) => *loc, - MemberAccess(loc, _, _) => *loc, - FunctionCall(loc, _, _) => *loc, - FunctionCallBlock(loc, left, right) => Loc::File( - loc.file_no(), - LineOfCode::loc(&left).start(), - LineOfCode::loc(&right).end(), - ), - NamedFunctionCall(loc, _, _) => *loc, - Not(loc, expr) => Loc::File(loc.file_no(), loc.start(), expr.loc().end()), - Complement(loc, expr) => Loc::File(loc.file_no(), loc.start(), expr.loc().end()), - Delete(loc, expr) => Loc::File(loc.file_no(), loc.start(), expr.loc().end()), - PreIncrement(loc, expr) => Loc::File(loc.file_no(), loc.start(), expr.loc().end()), - PreDecrement(loc, expr) => Loc::File(loc.file_no(), loc.start(), expr.loc().end()), - UnaryPlus(loc, _) => *loc, - Negate(loc, _) => *loc, - Power(loc, left, right) => Loc::File( - loc.file_no(), - LineOfCode::loc(&left).start(), - LineOfCode::loc(&right).end(), - ), - Multiply(loc, left, right) => Loc::File( - loc.file_no(), - LineOfCode::loc(&left).start(), - LineOfCode::loc(&right).end(), - ), - Divide(loc, left, right) => Loc::File( - loc.file_no(), - LineOfCode::loc(&left).start(), - LineOfCode::loc(&right).end(), - ), - Modulo(loc, left, right) => Loc::File( - loc.file_no(), - LineOfCode::loc(&left).start(), - LineOfCode::loc(&right).end(), - ), - Add(loc, left, right) => Loc::File( - loc.file_no(), - LineOfCode::loc(&left).start(), - LineOfCode::loc(&right).end(), - ), - Subtract(loc, left, right) => Loc::File( - loc.file_no(), - LineOfCode::loc(&left).start(), - LineOfCode::loc(&right).end(), - ), - ShiftLeft(loc, left, right) => Loc::File( - loc.file_no(), - LineOfCode::loc(&left).start(), - LineOfCode::loc(&right).end(), - ), - ShiftRight(loc, left, right) => Loc::File( - loc.file_no(), - LineOfCode::loc(&left).start(), - LineOfCode::loc(&right).end(), - ), - BitwiseAnd(loc, left, right) => Loc::File( - loc.file_no(), - LineOfCode::loc(&left).start(), - LineOfCode::loc(&right).end(), - ), - BitwiseXor(loc, left, right) => Loc::File( - loc.file_no(), - LineOfCode::loc(&left).start(), - LineOfCode::loc(&right).end(), - ), - BitwiseOr(loc, left, right) => Loc::File( - loc.file_no(), - LineOfCode::loc(&left).start(), - LineOfCode::loc(&right).end(), - ), - Less(loc, left, right) => Loc::File( - loc.file_no(), - LineOfCode::loc(&left).start(), - LineOfCode::loc(&right).end(), - ), - More(loc, left, right) => Loc::File( - loc.file_no(), - LineOfCode::loc(&left).start(), - LineOfCode::loc(&right).end(), - ), - LessEqual(loc, left, right) => Loc::File( - loc.file_no(), - LineOfCode::loc(&left).start(), - LineOfCode::loc(&right).end(), - ), - MoreEqual(loc, left, right) => Loc::File( - loc.file_no(), - LineOfCode::loc(&left).start(), - LineOfCode::loc(&right).end(), - ), - Equal(loc, left, right) => Loc::File( - loc.file_no(), - LineOfCode::loc(&left).start(), - LineOfCode::loc(&right).end(), - ), - NotEqual(loc, left, right) => Loc::File( - loc.file_no(), - LineOfCode::loc(&left).start(), - LineOfCode::loc(&right).end(), - ), - And(loc, left, right) => Loc::File( - loc.file_no(), - LineOfCode::loc(&left).start(), - LineOfCode::loc(&right).end(), - ), - Or(loc, left, right) => Loc::File( - loc.file_no(), - LineOfCode::loc(&left).start(), - LineOfCode::loc(&right).end(), - ), - ConditionalOperator(loc, left, _, right) => Loc::File( - loc.file_no(), - LineOfCode::loc(&left).start(), - LineOfCode::loc(&right).end(), - ), - Assign(loc, left, right) => Loc::File( - loc.file_no(), - LineOfCode::loc(&left).start(), - LineOfCode::loc(&right).end(), - ), - AssignOr(loc, left, right) => Loc::File( - loc.file_no(), - LineOfCode::loc(&left).start(), - LineOfCode::loc(&right).end(), - ), - AssignAnd(loc, left, right) => Loc::File( - loc.file_no(), - LineOfCode::loc(&left).start(), - LineOfCode::loc(&right).end(), - ), - AssignXor(loc, left, right) => Loc::File( - loc.file_no(), - LineOfCode::loc(&left).start(), - LineOfCode::loc(&right).end(), - ), - AssignShiftLeft(loc, left, right) => Loc::File( - loc.file_no(), - LineOfCode::loc(&left).start(), - LineOfCode::loc(&right).end(), - ), - AssignShiftRight(loc, left, right) => Loc::File( - loc.file_no(), - LineOfCode::loc(&left).start(), - LineOfCode::loc(&right).end(), - ), - AssignAdd(loc, left, right) => Loc::File( - loc.file_no(), - LineOfCode::loc(&left).start(), - LineOfCode::loc(&right).end(), - ), - AssignSubtract(loc, left, right) => Loc::File( - loc.file_no(), - LineOfCode::loc(&left).start(), - LineOfCode::loc(&right).end(), - ), - AssignMultiply(loc, left, right) => Loc::File( - loc.file_no(), - LineOfCode::loc(&left).start(), - LineOfCode::loc(&right).end(), - ), - AssignDivide(loc, left, right) => Loc::File( - loc.file_no(), - LineOfCode::loc(&left).start(), - LineOfCode::loc(&right).end(), - ), - AssignModulo(loc, left, right) => Loc::File( - loc.file_no(), - LineOfCode::loc(&left).start(), - LineOfCode::loc(&right).end(), - ), - BoolLiteral(loc, _) => *loc, - NumberLiteral(loc, _, _, _) => *loc, - RationalNumberLiteral(loc, _, _, _, _) => *loc, - HexNumberLiteral(loc, _, _) => *loc, - StringLiteral(literals) => { - let left_loc = literals.first().unwrap().loc; - Loc::File(left_loc.file_no(), left_loc.start(), literals.last().unwrap().loc.end()) - } - HexLiteral(literals) => { - let left_loc = literals.first().unwrap().loc; - Loc::File(left_loc.file_no(), left_loc.start(), literals.last().unwrap().loc.end()) - } - Type(loc, _) => *loc, - AddressLiteral(loc, _) => *loc, - Variable(ident) => ident.loc, - List(loc, _) => *loc, - ArrayLiteral(loc, _) => *loc, - This(loc) => *loc, - Parenthesis(loc, _) => *loc, - } +impl CodeLocationExt for Arc { + fn loc(&self) -> pt::Loc { + (**self).loc() } } -impl LineOfCode for Comment { - fn loc(&self) -> Loc { - match self { - Comment::Line(loc, _) => *loc, - Comment::Block(loc, _) => *loc, - Comment::DocLine(loc, _) => *loc, - Comment::DocBlock(loc, _) => *loc, +// FunctionDefinition patch +impl CodeLocationExt for pt::FunctionDefinition { + #[inline] + #[track_caller] + fn loc(&self) -> pt::Loc { + let mut loc = self.loc; + if let Some(ref body) = self.body { + loc.use_end_from(&pt::CodeLocation::loc(body)); } + loc } } -impl LineOfCode for FunctionAttribute { - fn loc(&self) -> Loc { +impl CodeLocationExt for pt::ContractPart { + #[inline] + #[track_caller] + fn loc(&self) -> pt::Loc { match self { - FunctionAttribute::Mutability(mutability) => mutability.loc(), - // visibility will always have a location in a function attribute - FunctionAttribute::Visibility(visibility) => visibility.loc().unwrap(), - FunctionAttribute::Virtual(loc) | - FunctionAttribute::Immutable(loc) | - FunctionAttribute::Override(loc, _) | - FunctionAttribute::BaseOrModifier(loc, _) | - FunctionAttribute::Error(loc) => *loc, + Self::FunctionDefinition(f) => f.loc(), + _ => pt::CodeLocation::loc(self), } } } -impl LineOfCode for VariableAttribute { - fn loc(&self) -> Loc { +impl CodeLocationExt for pt::SourceUnitPart { + #[inline] + #[track_caller] + fn loc(&self) -> pt::Loc { match self { - // visibility will always have a location in a function attribute - VariableAttribute::Visibility(visibility) => visibility.loc().unwrap(), - VariableAttribute::Constant(loc) | - VariableAttribute::Immutable(loc) | - VariableAttribute::Override(loc, _) => *loc, - } - } -} - -impl OptionalLineOfCode for Vec<(Loc, T)> { - fn loc(&self) -> Option { - if self.is_empty() { - return None + Self::FunctionDefinition(f) => f.loc(), + _ => pt::CodeLocation::loc(self), } - let mut locs = self.iter().map(|(loc, _)| loc).collect::>(); - locs.sort(); - let mut loc = **locs.first().unwrap(); - loc.use_end_from(locs.pop().unwrap()); - Some(loc) - } -} - -impl OptionalLineOfCode for SourceUnit { - fn loc(&self) -> Option { - self.0.get(0).map(|unit| *unit.loc()) } } -macro_rules! impl_loc { - ($type:ty) => { - impl LineOfCode for $type { - fn loc(&self) -> Loc { - self.loc +macro_rules! impl_delegate { + ($($t:ty),+ $(,)?) => {$( + impl CodeLocationExt for $t { + #[inline] + #[track_caller] + fn loc(&self) -> pt::Loc { + pt::CodeLocation::loc(self) } } - }; -} - -impl_loc! { IdentifierPath } -impl_loc! { YulTypedIdentifier } -impl_loc! { EventParameter } -impl_loc! { ErrorParameter } - -/// Extra helpers for Locs -pub trait LocExt { - fn with_start_from(self, other: &Self) -> Self; - fn with_end_from(self, other: &Self) -> Self; - fn with_start(self, start: usize) -> Self; - fn with_end(self, end: usize) -> Self; - fn range(self) -> std::ops::Range; -} - -impl LocExt for Loc { - fn with_start_from(mut self, other: &Self) -> Self { - self.use_start_from(other); - self - } - fn with_end_from(mut self, other: &Self) -> Self { - self.use_end_from(other); - self - } - fn with_start(self, start: usize) -> Self { - Loc::File(self.file_no(), start, self.end()) - } - fn with_end(self, end: usize) -> Self { - Loc::File(self.file_no(), self.start(), end) - } - fn range(self) -> std::ops::Range { - self.start()..self.end() - } + )+}; +} + +impl_delegate! { + pt::Annotation, + pt::Base, + pt::ContractDefinition, + pt::EnumDefinition, + pt::ErrorDefinition, + pt::ErrorParameter, + pt::EventDefinition, + pt::EventParameter, + // pt::FunctionDefinition, + pt::HexLiteral, + pt::Identifier, + pt::IdentifierPath, + pt::NamedArgument, + pt::Parameter, + // pt::SourceUnit, + pt::StringLiteral, + pt::StructDefinition, + pt::TypeDefinition, + pt::Using, + pt::UsingFunction, + pt::VariableDeclaration, + pt::VariableDefinition, + pt::YulBlock, + pt::YulFor, + pt::YulFunctionCall, + pt::YulFunctionDefinition, + pt::YulSwitch, + pt::YulTypedIdentifier, + + pt::CatchClause, + pt::Comment, + // pt::ContractPart, + pt::ContractTy, + pt::Expression, + pt::FunctionAttribute, + // pt::FunctionTy, + pt::Import, + pt::Loc, + pt::Mutability, + // pt::SourceUnitPart, + pt::Statement, + pt::StorageLocation, + // pt::Type, + // pt::UserDefinedOperator, + pt::UsingList, + pt::VariableAttribute, + // pt::Visibility, + pt::YulExpression, + pt::YulStatement, + pt::YulSwitchOptions, } diff --git a/fmt/src/solang_ext/mod.rs b/fmt/src/solang_ext/mod.rs index c44eb7d3a264..2a34c1a349b9 100644 --- a/fmt/src/solang_ext/mod.rs +++ b/fmt/src/solang_ext/mod.rs @@ -1,15 +1,28 @@ -#[cfg(test)] +//! Extension traits and modules to the [`solang_parser`] crate. + +/// Same as [`solang_parser::pt`], but with the patched `CodeLocation`. +pub mod pt { + #[doc(no_inline)] + pub use super::loc::CodeLocationExt as CodeLocation; + + #[doc(no_inline)] + pub use solang_parser::pt::{ + Annotation, Base, CatchClause, Comment, ContractDefinition, ContractPart, ContractTy, + EnumDefinition, ErrorDefinition, ErrorParameter, EventDefinition, EventParameter, + Expression, FunctionAttribute, FunctionDefinition, FunctionTy, HexLiteral, Identifier, + IdentifierPath, Import, Loc, Mutability, NamedArgument, OptionalCodeLocation, Parameter, + ParameterList, SourceUnit, SourceUnitPart, Statement, StorageLocation, StringLiteral, + StructDefinition, Type, TypeDefinition, UserDefinedOperator, Using, UsingFunction, + UsingList, VariableAttribute, VariableDeclaration, VariableDefinition, Visibility, + YulBlock, YulExpression, YulFor, YulFunctionCall, YulFunctionDefinition, YulStatement, + YulSwitch, YulSwitchOptions, YulTypedIdentifier, + }; +} + mod ast_eq; -mod attr_sort_key; -mod is_empty; mod loc; -mod operator; mod safe_unwrap; -#[cfg(test)] -pub use ast_eq::*; -pub use attr_sort_key::*; -pub use is_empty::*; -pub use loc::*; -pub use operator::*; +pub use ast_eq::AstEq; +pub use loc::CodeLocationExt; pub use safe_unwrap::SafeUnwrap; diff --git a/fmt/src/solang_ext/operator.rs b/fmt/src/solang_ext/operator.rs deleted file mode 100644 index 869964e18214..000000000000 --- a/fmt/src/solang_ext/operator.rs +++ /dev/null @@ -1,242 +0,0 @@ -use solang_parser::pt::*; - -/// Describes the precedence and the operator token of an Expression if it has one -pub trait Operator: Sized { - fn unsplittable(&self) -> bool; - fn operator(&self) -> Option<&'static str>; - fn has_space_around(&self) -> bool; -} - -/// Splits the iterator into components -pub trait OperatorComponents: Sized { - fn components(&self) -> (Option<&Self>, Option<&Self>); - fn components_mut(&mut self) -> (Option<&mut Self>, Option<&mut Self>); -} - -impl Operator for Expression { - fn unsplittable(&self) -> bool { - use Expression::*; - matches!( - self, - BoolLiteral(..) | - NumberLiteral(..) | - RationalNumberLiteral(..) | - HexNumberLiteral(..) | - StringLiteral(..) | - HexLiteral(..) | - AddressLiteral(..) | - Variable(..) | - This(..) - ) - } - - fn operator(&self) -> Option<&'static str> { - use Expression::*; - Some(match self { - PreIncrement(..) | PostIncrement(..) => "++", - PreDecrement(..) | PostDecrement(..) => "--", - New(..) => "new", - Not(..) => "!", - Complement(..) => "~", - Delete(..) => "delete", - UnaryPlus(..) | Add(..) => "+", - Negate(..) | Subtract(..) => "-", - Power(..) => "**", - Multiply(..) => "*", - Divide(..) => "/", - Modulo(..) => "%", - ShiftLeft(..) => "<<", - ShiftRight(..) => ">>", - BitwiseAnd(..) => "&", - BitwiseXor(..) => "^", - BitwiseOr(..) => "|", - Less(..) => "<", - More(..) => ">", - LessEqual(..) => "<=", - MoreEqual(..) => ">=", - And(..) => "&&", - Or(..) => "||", - Equal(..) => "==", - NotEqual(..) => "!=", - Assign(..) => "=", - AssignOr(..) => "|=", - AssignAnd(..) => "&=", - AssignXor(..) => "^=", - AssignShiftLeft(..) => "<<=", - AssignShiftRight(..) => ">>=", - AssignAdd(..) => "+=", - AssignSubtract(..) => "-=", - AssignMultiply(..) => "*=", - AssignDivide(..) => "/=", - AssignModulo(..) => "%=", - MemberAccess(..) | - ArraySubscript(..) | - ArraySlice(..) | - FunctionCall(..) | - FunctionCallBlock(..) | - NamedFunctionCall(..) | - ConditionalOperator(..) | - BoolLiteral(..) | - NumberLiteral(..) | - RationalNumberLiteral(..) | - HexNumberLiteral(..) | - StringLiteral(..) | - Type(..) | - HexLiteral(..) | - AddressLiteral(..) | - Variable(..) | - List(..) | - ArrayLiteral(..) | - This(..) | - Parenthesis(..) => return None, - }) - } - - fn has_space_around(&self) -> bool { - use Expression::*; - !matches!( - self, - PostIncrement(..) | - PreIncrement(..) | - PostDecrement(..) | - PreDecrement(..) | - Not(..) | - Complement(..) | - UnaryPlus(..) | - Negate(..) - ) - } -} - -impl OperatorComponents for Expression { - fn components(&self) -> (Option<&Self>, Option<&Self>) { - use Expression::*; - match self { - PostDecrement(_, expr) | PostIncrement(_, expr) => (Some(expr), None), - Not(_, expr) | - Complement(_, expr) | - New(_, expr) | - Delete(_, expr) | - UnaryPlus(_, expr) | - Negate(_, expr) | - PreDecrement(_, expr) | - Parenthesis(_, expr) | - PreIncrement(_, expr) => (None, Some(expr)), - Power(_, left, right) | - Multiply(_, left, right) | - Divide(_, left, right) | - Modulo(_, left, right) | - Add(_, left, right) | - Subtract(_, left, right) | - ShiftLeft(_, left, right) | - ShiftRight(_, left, right) | - BitwiseAnd(_, left, right) | - BitwiseXor(_, left, right) | - BitwiseOr(_, left, right) | - Less(_, left, right) | - More(_, left, right) | - LessEqual(_, left, right) | - MoreEqual(_, left, right) | - Equal(_, left, right) | - NotEqual(_, left, right) | - And(_, left, right) | - Or(_, left, right) | - Assign(_, left, right) | - AssignOr(_, left, right) | - AssignAnd(_, left, right) | - AssignXor(_, left, right) | - AssignShiftLeft(_, left, right) | - AssignShiftRight(_, left, right) | - AssignAdd(_, left, right) | - AssignSubtract(_, left, right) | - AssignMultiply(_, left, right) | - AssignDivide(_, left, right) | - AssignModulo(_, left, right) => (Some(left), Some(right)), - MemberAccess(..) | - ConditionalOperator(..) | - ArraySubscript(..) | - ArraySlice(..) | - FunctionCall(..) | - FunctionCallBlock(..) | - NamedFunctionCall(..) | - BoolLiteral(..) | - NumberLiteral(..) | - RationalNumberLiteral(..) | - HexNumberLiteral(..) | - StringLiteral(..) | - Type(..) | - HexLiteral(..) | - AddressLiteral(..) | - Variable(..) | - List(..) | - ArrayLiteral(..) | - This(..) => (None, None), - } - } - - fn components_mut(&mut self) -> (Option<&mut Self>, Option<&mut Self>) { - use Expression::*; - - match self { - PostDecrement(_, expr) | PostIncrement(_, expr) => (Some(expr.as_mut()), None), - Not(_, expr) | - Complement(_, expr) | - New(_, expr) | - Delete(_, expr) | - UnaryPlus(_, expr) | - Negate(_, expr) | - PreDecrement(_, expr) | - Parenthesis(_, expr) | - PreIncrement(_, expr) => (None, Some(expr.as_mut())), - Power(_, left, right) | - Multiply(_, left, right) | - Divide(_, left, right) | - Modulo(_, left, right) | - Add(_, left, right) | - Subtract(_, left, right) | - ShiftLeft(_, left, right) | - ShiftRight(_, left, right) | - BitwiseAnd(_, left, right) | - BitwiseXor(_, left, right) | - BitwiseOr(_, left, right) | - Less(_, left, right) | - More(_, left, right) | - LessEqual(_, left, right) | - MoreEqual(_, left, right) | - Equal(_, left, right) | - NotEqual(_, left, right) | - And(_, left, right) | - Or(_, left, right) | - Assign(_, left, right) | - AssignOr(_, left, right) | - AssignAnd(_, left, right) | - AssignXor(_, left, right) | - AssignShiftLeft(_, left, right) | - AssignShiftRight(_, left, right) | - AssignAdd(_, left, right) | - AssignSubtract(_, left, right) | - AssignMultiply(_, left, right) | - AssignDivide(_, left, right) | - AssignModulo(_, left, right) => (Some(left.as_mut()), Some(right.as_mut())), - MemberAccess(..) | - ConditionalOperator(..) | - ArraySubscript(..) | - ArraySlice(..) | - FunctionCall(..) | - FunctionCallBlock(..) | - NamedFunctionCall(..) | - BoolLiteral(..) | - NumberLiteral(..) | - RationalNumberLiteral(..) | - HexNumberLiteral(..) | - StringLiteral(..) | - Type(..) | - HexLiteral(..) | - AddressLiteral(..) | - Variable(..) | - List(..) | - ArrayLiteral(..) | - This(..) => (None, None), - } - } -} diff --git a/fmt/src/solang_ext/safe_unwrap.rs b/fmt/src/solang_ext/safe_unwrap.rs index 3d9a43437cc0..fe2810ad9705 100644 --- a/fmt/src/solang_ext/safe_unwrap.rs +++ b/fmt/src/solang_ext/safe_unwrap.rs @@ -1,18 +1,52 @@ -/// Unwraps optional parse tree items introduced in -/// https://github.com/hyperledger/solang/pull/1068. +use solang_parser::pt; + +/// Trait implemented to unwrap optional parse tree items initially introduced in +/// [hyperledger/solang#1068]. +/// +/// Note that the methods of this trait should only be used on parse tree items' fields, like +/// [pt::VariableDefinition] or [pt::EventDefinition], where the `name` field is `None` only when an +/// error occurred during parsing. /// -/// This unwrap is always safe when operating on a valid parse tree. +/// [hyperledger/solang#1068]: https://github.com/hyperledger/solang/pull/1068 pub trait SafeUnwrap { + /// See [SafeUnwrap]. fn safe_unwrap(&self) -> &T; + + /// See [SafeUnwrap]. fn safe_unwrap_mut(&mut self) -> &mut T; } -impl SafeUnwrap for Option { - fn safe_unwrap(&self) -> &T { - self.as_ref().expect("invalid parse tree") - } +#[inline(never)] +#[cold] +#[track_caller] +fn invalid() -> ! { + panic!("invalid parse tree") +} + +macro_rules! impl_ { + ($($t:ty),+ $(,)?) => { + $( + impl SafeUnwrap<$t> for Option<$t> { + #[inline] + #[track_caller] + fn safe_unwrap(&self) -> &$t { + match *self { + Some(ref x) => x, + None => invalid(), + } + } - fn safe_unwrap_mut(&mut self) -> &mut T { - self.as_mut().expect("invalid parse tree") - } + #[inline] + #[track_caller] + fn safe_unwrap_mut(&mut self) -> &mut $t { + match *self { + Some(ref mut x) => x, + None => invalid(), + } + } + } + )+ + }; } + +impl_!(pt::Identifier, pt::StringLiteral); diff --git a/fmt/src/visit.rs b/fmt/src/visit.rs index d5fcfd4c4921..138332ff3a99 100644 --- a/fmt/src/visit.rs +++ b/fmt/src/visit.rs @@ -1,7 +1,6 @@ -//! Visitor helpers to traverse the [solang](https://github.com/hyperledger-labs/solang) Solidity Parse Tree +//! Visitor helpers to traverse the [solang Solidity Parse Tree](solang_parser::pt). -use crate::solang_ext::*; -use solang_parser::pt::*; +use crate::solang_ext::pt::*; /// A trait that is invoked while traversing the Solidity Parse Tree. /// Each method of the [Visitor] trait is a hook that can be potentially overridden. @@ -341,7 +340,7 @@ pub trait Visitor { _expr: &mut Option<&mut YulExpression>, ) -> Result<(), Self::Error> where - T: Visitable + LineOfCode, + T: Visitable + CodeLocation, { self.visit_source(loc) } @@ -393,9 +392,9 @@ pub trait Visitor { } } -/// All `solang::pt::*` types, such as [Statement](solang::pt::Statement) should implement the -/// [Visitable] trait that accepts a trait [Visitor] implementation, which has various callback -/// handles for Solidity Parse Tree nodes. +/// All [`solang_parser::pt`] types, such as [Statement], should implement the [Visitable] trait +/// that accepts a trait [Visitor] implementation, which has various callback handles for Solidity +/// Parse Tree nodes. /// /// We want to take a `&mut self` to be able to implement some advanced features in the future such /// as modifying the Parse Tree before formatting it. @@ -576,7 +575,7 @@ impl Visitable for Expression { where V: Visitor, { - v.visit_expr(LineOfCode::loc(self), self) + v.visit_expr(self.loc(), self) } } diff --git a/fmt/testdata/IfStatement/fmt.sol b/fmt/testdata/IfStatement/fmt.sol index 4c43010823f3..cb2f8874f83d 100644 --- a/fmt/testdata/IfStatement/fmt.sol +++ b/fmt/testdata/IfStatement/fmt.sol @@ -104,9 +104,7 @@ contract IfStatement { execute(); } - if (condition && ((condition || anotherLongCondition))) { - execute(); - } + if (condition && ((condition || anotherLongCondition))) execute(); // if statement if (condition) execute(); diff --git a/fmt/testdata/IfStatement2/fmt.sol b/fmt/testdata/IfStatement2/fmt.sol new file mode 100644 index 000000000000..10ae43601d4a --- /dev/null +++ b/fmt/testdata/IfStatement2/fmt.sol @@ -0,0 +1,7 @@ +contract IfStatement { + function test() external { + bool anotherLongCondition; + + if (condition && ((condition || anotherLongCondition))) execute(); + } +} diff --git a/fmt/testdata/IfStatement2/original.sol b/fmt/testdata/IfStatement2/original.sol new file mode 100644 index 000000000000..df020c04bbe3 --- /dev/null +++ b/fmt/testdata/IfStatement2/original.sol @@ -0,0 +1,10 @@ +contract IfStatement { + + function test() external { + bool anotherLongCondition; + + if (condition && ((condition || anotherLongCondition) + ) + ) execute(); + } +} \ No newline at end of file diff --git a/fmt/tests/it/formatter.rs b/fmt/tests/it/formatter.rs new file mode 100644 index 000000000000..e736edebab87 --- /dev/null +++ b/fmt/tests/it/formatter.rs @@ -0,0 +1,202 @@ +use forge_fmt::{format, parse, solang_ext::AstEq, FormatterConfig}; +use itertools::Itertools; +use std::{fs, path::PathBuf}; +use tracing_subscriber::{EnvFilter, FmtSubscriber}; + +fn tracing() { + let subscriber = FmtSubscriber::builder() + .with_env_filter(EnvFilter::from_default_env()) + .with_test_writer() + .finish(); + let _ = tracing::subscriber::set_global_default(subscriber); +} + +fn test_directory(base_name: &str) { + tracing(); + let mut original = None; + + let tests = + fs::read_dir(PathBuf::from(env!("CARGO_MANIFEST_DIR")).join("testdata").join(base_name)) + .unwrap() + .filter_map(|path| { + let path = path.unwrap().path(); + let source = fs::read_to_string(&path).unwrap(); + + if let Some(filename) = path.file_name().and_then(|name| name.to_str()) { + if filename == "original.sol" { + original = Some(source); + } else if filename + .strip_suffix("fmt.sol") + .map(|filename| filename.strip_suffix('.')) + .is_some() + { + // The majority of the tests were written with the assumption + // that the default value for max line length is `80`. + // Preserve that to avoid rewriting test logic. + let default_config = + FormatterConfig { line_length: 80, ..Default::default() }; + + let mut config = toml::Value::try_from(&default_config).unwrap(); + let config_table = config.as_table_mut().unwrap(); + let mut lines = source.split('\n').peekable(); + let mut line_num = 1; + while let Some(line) = lines.peek() { + let entry = line + .strip_prefix("//") + .and_then(|line| line.trim().strip_prefix("config:")) + .map(str::trim); + let entry = if let Some(entry) = entry { entry } else { break }; + + let values = match toml::from_str::(entry) { + Ok(toml::Value::Table(table)) => table, + _ => panic!("Invalid config item in {filename} at {line_num}"), + }; + config_table.extend(values); + + line_num += 1; + lines.next(); + } + let config = config + .try_into() + .unwrap_or_else(|err| panic!("Invalid config for {filename}: {err}")); + + return Some((filename.to_string(), config, lines.join("\n"))) + } + } + + None + }) + .collect::>(); + + for (filename, config, formatted) in tests { + test_formatter( + &filename, + config, + original.as_ref().expect("original.sol not found"), + &formatted, + ); + } +} + +fn assert_eof(content: &str) { + assert!(content.ends_with('\n') && !content.ends_with("\n\n")); +} + +fn test_formatter(filename: &str, config: FormatterConfig, source: &str, expected_source: &str) { + #[derive(Eq)] + struct PrettyString(String); + + impl PartialEq for PrettyString { + fn eq(&self, other: &PrettyString) -> bool { + self.0.lines().eq(other.0.lines()) + } + } + + impl std::fmt::Debug for PrettyString { + fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { + f.write_str(&self.0) + } + } + + assert_eof(expected_source); + + let source_parsed = parse(source).unwrap(); + let expected_parsed = parse(expected_source).unwrap(); + + if !source_parsed.pt.ast_eq(&expected_parsed.pt) { + pretty_assertions::assert_eq!( + source_parsed.pt, + expected_parsed.pt, + "(formatted Parse Tree == expected Parse Tree) in {}", + filename + ); + } + + let expected = PrettyString(expected_source.to_string()); + + let mut source_formatted = String::new(); + format(&mut source_formatted, source_parsed, config.clone()).unwrap(); + assert_eof(&source_formatted); + + // println!("{}", source_formatted); + let source_formatted = PrettyString(source_formatted); + + pretty_assertions::assert_eq!( + source_formatted, + expected, + "(formatted == expected) in {}", + filename + ); + + let mut expected_formatted = String::new(); + format(&mut expected_formatted, expected_parsed, config).unwrap(); + assert_eof(&expected_formatted); + + let expected_formatted = PrettyString(expected_formatted); + + pretty_assertions::assert_eq!( + expected_formatted, + expected, + "(formatted == expected) in {}", + filename + ); +} + +macro_rules! test_directories { + ($($dir:ident),+ $(,)?) => {$( + #[allow(non_snake_case)] + #[test] + fn $dir() { + test_directory(stringify!($dir)); + } + )+}; +} + +test_directories! { + ConstructorDefinition, + ContractDefinition, + DocComments, + EnumDefinition, + ErrorDefinition, + EventDefinition, + FunctionDefinition, + FunctionType, + ImportDirective, + ModifierDefinition, + StatementBlock, + StructDefinition, + TypeDefinition, + UsingDirective, + VariableDefinition, + OperatorExpressions, + WhileStatement, + DoWhileStatement, + ForStatement, + IfStatement, + IfStatement2, + VariableAssignment, + FunctionCallArgsStatement, + RevertStatement, + RevertNamedArgsStatement, + ReturnStatement, + TryStatement, + ConditionalOperatorExpression, + NamedFunctionCallExpression, + ArrayExpressions, + UnitExpression, + ThisExpression, + SimpleComments, + LiteralExpression, + Yul, + YulStrings, + IntTypes, + InlineDisable, + NumberLiteralUnderscore, + FunctionCall, + TrailingComma, + PragmaDirective, + Annotation, + MappingType, + EmitStatement, + Repros, +} diff --git a/fmt/tests/it/main.rs b/fmt/tests/it/main.rs new file mode 100644 index 000000000000..eeaf3b9cfc84 --- /dev/null +++ b/fmt/tests/it/main.rs @@ -0,0 +1 @@ +mod formatter;