From 4d234fc6a0b9987d66c73da2e70b2b41df49ca51 Mon Sep 17 00:00:00 2001 From: Deadbeef Date: Fri, 26 May 2023 19:50:54 +0800 Subject: [PATCH 1/2] add direnv and flake.nix --- .envrc | 1 + .gitignore | 4 +++- flake.lock | 61 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ flake.nix | 18 ++++++++++++++++ 4 files changed, 83 insertions(+), 1 deletion(-) create mode 100644 .envrc create mode 100644 flake.lock create mode 100644 flake.nix diff --git a/.envrc b/.envrc new file mode 100644 index 0000000..3550a30 --- /dev/null +++ b/.envrc @@ -0,0 +1 @@ +use flake diff --git a/.gitignore b/.gitignore index c78d034..251a069 100644 --- a/.gitignore +++ b/.gitignore @@ -2,4 +2,6 @@ target /expanded.rs /expanded /invalid.rs -/invalid \ No newline at end of file +/invalid +.direnv/ +g \ No newline at end of file diff --git a/flake.lock b/flake.lock new file mode 100644 index 0000000..4fcac54 --- /dev/null +++ b/flake.lock @@ -0,0 +1,61 @@ +{ + "nodes": { + "flake-utils": { + "inputs": { + "systems": "systems" + }, + "locked": { + "lastModified": 1681202837, + "narHash": "sha256-H+Rh19JDwRtpVPAWp64F+rlEtxUWBAQW28eAi3SRSzg=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "cfacdce06f30d2b68473a46042957675eebb3401", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "flake-utils", + "type": "github" + } + }, + "nixpkgs": { + "locked": { + "lastModified": 1684935479, + "narHash": "sha256-6QMMsXMr2nhmOPHdti2j3KRHt+bai2zw+LJfdCl97Mk=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "f91ee3065de91a3531329a674a45ddcb3467a650", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixos-unstable", + "repo": "nixpkgs", + "type": "github" + } + }, + "root": { + "inputs": { + "flake-utils": "flake-utils", + "nixpkgs": "nixpkgs" + } + }, + "systems": { + "locked": { + "lastModified": 1681028828, + "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", + "owner": "nix-systems", + "repo": "default", + "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", + "type": "github" + }, + "original": { + "owner": "nix-systems", + "repo": "default", + "type": "github" + } + } + }, + "root": "root", + "version": 7 +} diff --git a/flake.nix b/flake.nix new file mode 100644 index 0000000..f8202b8 --- /dev/null +++ b/flake.nix @@ -0,0 +1,18 @@ +{ + inputs = { + nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable"; + flake-utils.url = "github:numtide/flake-utils"; + }; + + outputs = { self, nixpkgs, flake-utils, ... }: flake-utils.lib.eachDefaultSystem (system: + let + pkgs = import nixpkgs { inherit system; }; + in + { + devShells.default = pkgs.mkShell { + packages = with pkgs; [ + gcc + ]; + }; + }); +} \ No newline at end of file From 9467c55770138c01a4dbaf312c26c45463ef032d Mon Sep 17 00:00:00 2001 From: Deadbeef Date: Fri, 26 May 2023 19:56:45 +0800 Subject: [PATCH 2/2] use genemichaels for formatting --- Cargo.lock | 167 +++- Cargo.toml | 4 +- prettyplease-forked/.gitattributes | 2 - prettyplease-forked/.gitignore | 2 - prettyplease-forked/Cargo.toml | 25 - prettyplease-forked/LICENSE-APACHE | 201 ---- prettyplease-forked/LICENSE-MIT | 23 - prettyplease-forked/build.rs | 3 - prettyplease-forked/src/algorithm.rs | 377 -------- prettyplease-forked/src/attr.rs | 233 ----- prettyplease-forked/src/convenience.rs | 98 -- prettyplease-forked/src/data.rs | 95 -- prettyplease-forked/src/expr.rs | 1198 ------------------------ prettyplease-forked/src/file.rs | 17 - prettyplease-forked/src/generics.rs | 280 ------ prettyplease-forked/src/item.rs | 822 ---------------- prettyplease-forked/src/iter.rs | 46 - prettyplease-forked/src/lib.rs | 377 -------- prettyplease-forked/src/lifetime.rs | 9 - prettyplease-forked/src/lit.rs | 50 - prettyplease-forked/src/mac.rs | 220 ----- prettyplease-forked/src/pat.rs | 210 ----- prettyplease-forked/src/path.rs | 185 ---- prettyplease-forked/src/ring.rs | 81 -- prettyplease-forked/src/stmt.rs | 85 -- prettyplease-forked/src/token.rs | 80 -- prettyplease-forked/src/ty.rs | 232 ----- src/dylib_flag.rs | 2 +- src/formatting.rs | 7 + src/lib.rs | 1 + src/processor/mod.rs | 2 +- 31 files changed, 165 insertions(+), 4969 deletions(-) delete mode 100644 prettyplease-forked/.gitattributes delete mode 100644 prettyplease-forked/.gitignore delete mode 100644 prettyplease-forked/Cargo.toml delete mode 100644 prettyplease-forked/LICENSE-APACHE delete mode 100644 prettyplease-forked/LICENSE-MIT delete mode 100644 prettyplease-forked/build.rs delete mode 100644 prettyplease-forked/src/algorithm.rs delete mode 100644 prettyplease-forked/src/attr.rs delete mode 100644 prettyplease-forked/src/convenience.rs delete mode 100644 prettyplease-forked/src/data.rs delete mode 100644 prettyplease-forked/src/expr.rs delete mode 100644 prettyplease-forked/src/file.rs delete mode 100644 prettyplease-forked/src/generics.rs delete mode 100644 prettyplease-forked/src/item.rs delete mode 100644 prettyplease-forked/src/iter.rs delete mode 100644 prettyplease-forked/src/lib.rs delete mode 100644 prettyplease-forked/src/lifetime.rs delete mode 100644 prettyplease-forked/src/lit.rs delete mode 100644 prettyplease-forked/src/mac.rs delete mode 100644 prettyplease-forked/src/pat.rs delete mode 100644 prettyplease-forked/src/path.rs delete mode 100644 prettyplease-forked/src/ring.rs delete mode 100644 prettyplease-forked/src/stmt.rs delete mode 100644 prettyplease-forked/src/token.rs delete mode 100644 prettyplease-forked/src/ty.rs create mode 100644 src/formatting.rs diff --git a/Cargo.lock b/Cargo.lock index 86319a0..b8ec362 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -40,6 +40,16 @@ version = "1.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" +[[package]] +name = "cargo-manifest" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3ce38d2d1efbe0e7180766a872570bc07cd5430a42e713b01006d4afa89912fe" +dependencies = [ + "serde", + "toml", +] + [[package]] name = "cargo-minimize" version = "0.1.0" @@ -47,9 +57,9 @@ dependencies = [ "anyhow", "clap", "ctrlc", + "genemichaels", "libc", "owo-colors", - "prettyplease", "proc-macro2", "quote", "rustfix", @@ -112,6 +122,12 @@ dependencies = [ "os_str_bytes", ] +[[package]] +name = "convert_case" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6245d59a3e82a7fc217c5828a6692dbc6dfb63a0c8c90495621f7b9d79704a0e" + [[package]] name = "crossbeam-channel" version = "0.5.7" @@ -165,6 +181,19 @@ dependencies = [ "windows-sys 0.45.0", ] +[[package]] +name = "derive_more" +version = "0.99.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4fb810d30a7c1953f91334de7244731fc3f3c10d7fe163338a35b9f640960321" +dependencies = [ + "convert_case", + "proc-macro2", + "quote", + "rustc_version", + "syn", +] + [[package]] name = "either" version = "1.8.1" @@ -218,6 +247,31 @@ version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "42703706b716c37f96a77aea830392ad231f44c9e9a67872fa5548707e11b11c" +[[package]] +name = "genemichaels" +version = "0.1.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "17de1f67a3bc7d3609c396fc5377c3d0102b7042fab7be3e23b8b0708dfbfa0f" +dependencies = [ + "anyhow", + "cargo-manifest", + "clap", + "derive_more", + "markdown", + "proc-macro2", + "quote", + "structre", + "syn", + "threadpool", + "walkdir", +] + +[[package]] +name = "hashbrown" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" + [[package]] name = "heck" version = "0.4.0" @@ -242,6 +296,16 @@ dependencies = [ "libc", ] +[[package]] +name = "indexmap" +version = "1.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99" +dependencies = [ + "autocfg", + "hashbrown", +] + [[package]] name = "instant" version = "0.1.12" @@ -303,6 +367,15 @@ version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d59d8c75012853d2e872fb56bc8a2e53718e2cafe1a4c823143141c6d90c322f" +[[package]] +name = "litrs" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f9275e0933cf8bb20f008924c0cb07a0692fe54d8064996520bf998de9eb79aa" +dependencies = [ + "proc-macro2", +] + [[package]] name = "log" version = "0.4.17" @@ -312,6 +385,15 @@ dependencies = [ "cfg-if", ] +[[package]] +name = "markdown" +version = "1.0.0-alpha.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1c45dae11dd8af468c41201ace44dbbb3b1148215ac593cb8f0967b8d8d4b66c" +dependencies = [ + "unicode-id", +] + [[package]] name = "matchers" version = "0.1.0" @@ -398,14 +480,6 @@ version = "0.2.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e0a7ae3ac2f1173085d398531c705756c94a4c56843785df85a60c1a0afac116" -[[package]] -name = "prettyplease" -version = "0.1.19" -dependencies = [ - "proc-macro2", - "syn", -] - [[package]] name = "proc-macro-error" version = "1.0.4" @@ -432,9 +506,9 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.48" +version = "1.0.59" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e9d89e5dba24725ae5678020bf8f1357a9aa7ff10736b551adbcd3f8d17d766f" +checksum = "6aeca18b86b413c660b781aa319e4e2648a3e6f9eadc9b47e9038e6fe9f3451b" dependencies = [ "unicode-ident", ] @@ -505,6 +579,15 @@ version = "0.6.29" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1" +[[package]] +name = "rustc_version" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366" +dependencies = [ + "semver", +] + [[package]] name = "rustfix" version = "0.6.1" @@ -566,6 +649,12 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" +[[package]] +name = "semver" +version = "1.0.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bebd363326d05ec3e2f532ab7660680f3b02130d780c299bca73469d521bc0ed" + [[package]] name = "serde" version = "1.0.151" @@ -625,10 +714,35 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" [[package]] -name = "syn" -version = "1.0.106" +name = "structre" +version = "0.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09ee3a69cd2c7e06684677e5629b3878b253af05e4714964204279c6bc02cf0b" +checksum = "f31eab0dcebb0d631c93629c0da9fdce1448123aa15e5e4c08fcd71d4f4fd5f4" +dependencies = [ + "anyhow", + "once_cell", + "regex", + "structre_proc_macros", +] + +[[package]] +name = "structre_proc_macros" +version = "0.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "66e7698a9d57b3a475ce1d6cc37b1be9ee8ed188ec596603c863c06c9e06cf7e" +dependencies = [ + "litrs", + "proc-macro2", + "quote", + "regex-syntax", + "syn", +] + +[[package]] +name = "syn" +version = "1.0.109" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" dependencies = [ "proc-macro2", "quote", @@ -679,6 +793,25 @@ dependencies = [ "once_cell", ] +[[package]] +name = "threadpool" +version = "1.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d050e60b33d41c19108b32cea32164033a9013fe3b46cbd4457559bfbf77afaa" +dependencies = [ + "num_cpus", +] + +[[package]] +name = "toml" +version = "0.5.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f4f7f0dd8d50a853a531c426359045b1998f04219d88799810762cd4ad314234" +dependencies = [ + "indexmap", + "serde", +] + [[package]] name = "tracing" version = "0.1.37" @@ -754,6 +887,12 @@ dependencies = [ "tracing-subscriber", ] +[[package]] +name = "unicode-id" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d70b6494226b36008c8366c288d77190b3fad2eb4c10533139c1c1f461127f1a" + [[package]] name = "unicode-ident" version = "1.0.4" diff --git a/Cargo.toml b/Cargo.toml index 6e8360d..51609ba 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,5 +1,5 @@ [workspace] -members = ["./", "./prettyplease-forked", "./testsuite"] +members = ["./", "./testsuite"] exclude = ["test-cases/*", "full-tests/*"] [package] @@ -20,8 +20,8 @@ lto = "thin" anyhow = "1.0.65" clap = { version = "4.0.29", features = ["derive"] } ctrlc = "3.2.5" +genemichaels = "0.1.21" owo-colors = "3.5.0" -prettyplease = { path = "./prettyplease-forked", features = ["verbatim"]} proc-macro2 = { version = "1.0.48", features = ["span-locations"] } quote = "1.0.23" rustfix = "0.6.1" diff --git a/prettyplease-forked/.gitattributes b/prettyplease-forked/.gitattributes deleted file mode 100644 index 567c199..0000000 --- a/prettyplease-forked/.gitattributes +++ /dev/null @@ -1,2 +0,0 @@ -cargo-expand/*.rs linguist-generated -examples/*.rs linguist-generated diff --git a/prettyplease-forked/.gitignore b/prettyplease-forked/.gitignore deleted file mode 100644 index 96ef6c0..0000000 --- a/prettyplease-forked/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -/target -Cargo.lock diff --git a/prettyplease-forked/Cargo.toml b/prettyplease-forked/Cargo.toml deleted file mode 100644 index 76ca2cb..0000000 --- a/prettyplease-forked/Cargo.toml +++ /dev/null @@ -1,25 +0,0 @@ -[package] -name = "prettyplease" -version = "0.1.19" -authors = ["David Tolnay "] -autoexamples = false -categories = ["development-tools"] -description = "A minimal `syn` syntax tree pretty-printer" -documentation = "https://docs.rs/prettyplease" -edition = "2021" -exclude = ["cargo-expand"] -keywords = ["rustfmt"] -license = "MIT OR Apache-2.0" -links = "prettyplease01" -repository = "https://github.com/dtolnay/prettyplease" -rust-version = "1.56" - -[features] -verbatim = ["syn/parsing"] - -[dependencies] -proc-macro2 = { version = "1.0", default-features = false } -syn = { version = "1.0.90", default-features = false, features = ["full"] } - -[dev-dependencies] -syn = { version = "1.0.90", default-features = false, features = ["parsing"] } diff --git a/prettyplease-forked/LICENSE-APACHE b/prettyplease-forked/LICENSE-APACHE deleted file mode 100644 index 16fe87b..0000000 --- a/prettyplease-forked/LICENSE-APACHE +++ /dev/null @@ -1,201 +0,0 @@ - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - -TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - -1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - -2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - -3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - -4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - -5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - -6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - -7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - -8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - -9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - -END OF TERMS AND CONDITIONS - -APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "[]" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - -Copyright [yyyy] [name of copyright owner] - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. diff --git a/prettyplease-forked/LICENSE-MIT b/prettyplease-forked/LICENSE-MIT deleted file mode 100644 index 31aa793..0000000 --- a/prettyplease-forked/LICENSE-MIT +++ /dev/null @@ -1,23 +0,0 @@ -Permission is hereby granted, free of charge, to any -person obtaining a copy of this software and associated -documentation files (the "Software"), to deal in the -Software without restriction, including without -limitation the rights to use, copy, modify, merge, -publish, distribute, sublicense, and/or sell copies of -the Software, and to permit persons to whom the Software -is furnished to do so, subject to the following -conditions: - -The above copyright notice and this permission notice -shall be included in all copies or substantial portions -of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF -ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED -TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A -PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY -CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR -IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -DEALINGS IN THE SOFTWARE. diff --git a/prettyplease-forked/build.rs b/prettyplease-forked/build.rs deleted file mode 100644 index 52a6790..0000000 --- a/prettyplease-forked/build.rs +++ /dev/null @@ -1,3 +0,0 @@ -fn main() { - println!(concat!("cargo:VERSION=", env!("CARGO_PKG_VERSION"))); -} diff --git a/prettyplease-forked/src/algorithm.rs b/prettyplease-forked/src/algorithm.rs deleted file mode 100644 index 14b57c2..0000000 --- a/prettyplease-forked/src/algorithm.rs +++ /dev/null @@ -1,377 +0,0 @@ -// Adapted from https://github.com/rust-lang/rust/blob/1.57.0/compiler/rustc_ast_pretty/src/pp.rs. -// See "Algorithm notes" in the crate-level rustdoc. - -use crate::ring::RingBuffer; -use crate::{MARGIN, MIN_SPACE}; -use std::borrow::Cow; -use std::cmp; -use std::collections::VecDeque; -use std::iter; - -#[derive(Clone, Copy, PartialEq)] -pub enum Breaks { - Consistent, - Inconsistent, -} - -#[derive(Clone, Copy, Default)] -pub struct BreakToken { - pub offset: isize, - pub blank_space: usize, - pub pre_break: Option, - pub post_break: Option, - pub no_break: Option, - pub if_nonempty: bool, - pub never_break: bool, -} - -#[derive(Clone, Copy)] -pub struct BeginToken { - pub offset: isize, - pub breaks: Breaks, -} - -#[derive(Clone)] -pub enum Token { - String(Cow<'static, str>), - Break(BreakToken), - Begin(BeginToken), - End, -} - -#[derive(Copy, Clone)] -enum PrintFrame { - Fits(Breaks), - Broken(usize, Breaks), -} - -pub const SIZE_INFINITY: isize = 0xffff; - -pub struct Printer { - out: String, - // Number of spaces left on line - space: isize, - // Ring-buffer of tokens and calculated sizes - buf: RingBuffer, - // Total size of tokens already printed - left_total: isize, - // Total size of tokens enqueued, including printed and not yet printed - right_total: isize, - // Holds the ring-buffer index of the Begin that started the current block, - // possibly with the most recent Break after that Begin (if there is any) on - // top of it. Values are pushed and popped on the back of the queue using it - // like stack, and elsewhere old values are popped from the front of the - // queue as they become irrelevant due to the primary ring-buffer advancing. - scan_stack: VecDeque, - // Stack of blocks-in-progress being flushed by print - print_stack: Vec, - // Level of indentation of current line - indent: usize, - // Buffered indentation to avoid writing trailing whitespace - pending_indentation: usize, -} - -#[derive(Clone)] -struct BufEntry { - token: Token, - size: isize, -} - -impl Printer { - pub fn new() -> Self { - Printer { - out: String::new(), - space: MARGIN, - buf: RingBuffer::new(), - left_total: 0, - right_total: 0, - scan_stack: VecDeque::new(), - print_stack: Vec::new(), - indent: 0, - pending_indentation: 0, - } - } - - pub fn eof(mut self) -> String { - if !self.scan_stack.is_empty() { - self.check_stack(0); - self.advance_left(); - } - self.out - } - - pub fn scan_begin(&mut self, token: BeginToken) { - if self.scan_stack.is_empty() { - self.left_total = 1; - self.right_total = 1; - self.buf.clear(); - } - let right = self.buf.push(BufEntry { - token: Token::Begin(token), - size: -self.right_total, - }); - self.scan_stack.push_back(right); - } - - pub fn scan_end(&mut self) { - if self.scan_stack.is_empty() { - self.print_end(); - } else { - if !self.buf.is_empty() { - if let Token::Break(break_token) = self.buf.last().token { - if self.buf.len() >= 2 { - if let Token::Begin(_) = self.buf.second_last().token { - self.buf.pop_last(); - self.buf.pop_last(); - self.scan_stack.pop_back(); - self.scan_stack.pop_back(); - self.right_total -= break_token.blank_space as isize; - return; - } - } - if break_token.if_nonempty { - self.buf.pop_last(); - self.scan_stack.pop_back(); - self.right_total -= break_token.blank_space as isize; - } - } - } - let right = self.buf.push(BufEntry { - token: Token::End, - size: -1, - }); - self.scan_stack.push_back(right); - } - } - - pub fn scan_break(&mut self, token: BreakToken) { - if self.scan_stack.is_empty() { - self.left_total = 1; - self.right_total = 1; - self.buf.clear(); - } else { - self.check_stack(0); - } - let right = self.buf.push(BufEntry { - token: Token::Break(token), - size: -self.right_total, - }); - self.scan_stack.push_back(right); - self.right_total += token.blank_space as isize; - } - - pub fn scan_string(&mut self, string: Cow<'static, str>) { - if self.scan_stack.is_empty() { - self.print_string(string); - } else { - let len = string.len() as isize; - self.buf.push(BufEntry { - token: Token::String(string), - size: len, - }); - self.right_total += len; - self.check_stream(); - } - } - - pub fn offset(&mut self, offset: isize) { - match &mut self.buf.last_mut().token { - Token::Break(token) => token.offset += offset, - Token::Begin(_) => {} - Token::String(_) | Token::End => unreachable!(), - } - } - - pub fn end_with_max_width(&mut self, max: isize) { - let mut depth = 1; - for &index in self.scan_stack.iter().rev() { - let entry = &self.buf[index]; - match entry.token { - Token::Begin(_) => { - depth -= 1; - if depth == 0 { - if entry.size < 0 { - let actual_width = entry.size + self.right_total; - if actual_width > max { - self.buf.push(BufEntry { - token: Token::String(Cow::Borrowed("")), - size: SIZE_INFINITY, - }); - self.right_total += SIZE_INFINITY; - } - } - break; - } - } - Token::End => depth += 1, - Token::Break(_) => {} - Token::String(_) => unreachable!(), - } - } - self.scan_end(); - } - - fn check_stream(&mut self) { - while self.right_total - self.left_total > self.space { - if *self.scan_stack.front().unwrap() == self.buf.index_of_first() { - self.scan_stack.pop_front().unwrap(); - self.buf.first_mut().size = SIZE_INFINITY; - } - - self.advance_left(); - - if self.buf.is_empty() { - break; - } - } - } - - fn advance_left(&mut self) { - while self.buf.first().size >= 0 { - let left = self.buf.pop_first(); - - match left.token { - Token::String(string) => { - self.left_total += left.size; - self.print_string(string); - } - Token::Break(token) => { - self.left_total += token.blank_space as isize; - self.print_break(token, left.size); - } - Token::Begin(token) => self.print_begin(token, left.size), - Token::End => self.print_end(), - } - - if self.buf.is_empty() { - break; - } - } - } - - fn check_stack(&mut self, mut depth: usize) { - while let Some(&index) = self.scan_stack.back() { - let mut entry = &mut self.buf[index]; - match entry.token { - Token::Begin(_) => { - if depth == 0 { - break; - } - self.scan_stack.pop_back().unwrap(); - entry.size += self.right_total; - depth -= 1; - } - Token::End => { - self.scan_stack.pop_back().unwrap(); - entry.size = 1; - depth += 1; - } - Token::Break(_) => { - self.scan_stack.pop_back().unwrap(); - entry.size += self.right_total; - if depth == 0 { - break; - } - } - Token::String(_) => unreachable!(), - } - } - } - - fn get_top(&self) -> PrintFrame { - const OUTER: PrintFrame = PrintFrame::Broken(0, Breaks::Inconsistent); - self.print_stack.last().map_or(OUTER, PrintFrame::clone) - } - - fn print_begin(&mut self, token: BeginToken, size: isize) { - if cfg!(prettyplease_debug) { - self.out.push(match token.breaks { - Breaks::Consistent => '«', - Breaks::Inconsistent => '‹', - }); - if cfg!(prettyplease_debug_indent) { - self.out - .extend(token.offset.to_string().chars().map(|ch| match ch { - '0'..='9' => ['₀', '₁', '₂', '₃', '₄', '₅', '₆', '₇', '₈', '₉'] - [(ch as u8 - b'0') as usize] - as char, - '-' => '₋', - _ => unreachable!(), - })); - } - } - if size > self.space { - self.print_stack - .push(PrintFrame::Broken(self.indent, token.breaks)); - self.indent = usize::try_from(self.indent as isize + token.offset).unwrap(); - } else { - self.print_stack.push(PrintFrame::Fits(token.breaks)); - } - } - - fn print_end(&mut self) { - let breaks = match self.print_stack.pop().unwrap() { - PrintFrame::Broken(indent, breaks) => { - self.indent = indent; - breaks - } - PrintFrame::Fits(breaks) => breaks, - }; - if cfg!(prettyplease_debug) { - self.out.push(match breaks { - Breaks::Consistent => '»', - Breaks::Inconsistent => '›', - }); - } - } - - fn print_break(&mut self, token: BreakToken, size: isize) { - let fits = token.never_break - || match self.get_top() { - PrintFrame::Fits(..) => true, - PrintFrame::Broken(.., Breaks::Consistent) => false, - PrintFrame::Broken(.., Breaks::Inconsistent) => size <= self.space, - }; - if fits { - self.pending_indentation += token.blank_space; - self.space -= token.blank_space as isize; - if let Some(no_break) = token.no_break { - self.out.push(no_break); - self.space -= no_break.len_utf8() as isize; - } - if cfg!(prettyplease_debug) { - self.out.push('·'); - } - } else { - if let Some(pre_break) = token.pre_break { - self.print_indent(); - self.out.push(pre_break); - } - if cfg!(prettyplease_debug) { - self.out.push('·'); - } - self.out.push('\n'); - let indent = self.indent as isize + token.offset; - self.pending_indentation = usize::try_from(indent).unwrap(); - self.space = cmp::max(MARGIN - indent, MIN_SPACE); - if let Some(post_break) = token.post_break { - self.print_indent(); - self.out.push(post_break); - self.space -= post_break.len_utf8() as isize; - } - } - } - - fn print_string(&mut self, string: Cow<'static, str>) { - self.print_indent(); - self.out.push_str(&string); - self.space -= string.len() as isize; - } - - fn print_indent(&mut self) { - self.out.reserve(self.pending_indentation); - self.out - .extend(iter::repeat(' ').take(self.pending_indentation)); - self.pending_indentation = 0; - } -} diff --git a/prettyplease-forked/src/attr.rs b/prettyplease-forked/src/attr.rs deleted file mode 100644 index e77eb7b..0000000 --- a/prettyplease-forked/src/attr.rs +++ /dev/null @@ -1,233 +0,0 @@ -use crate::algorithm::Printer; -use crate::INDENT; -use proc_macro2::{Delimiter, TokenStream, TokenTree}; -use syn::{AttrStyle, Attribute, Lit, PathArguments}; - -impl Printer { - pub fn outer_attrs(&mut self, attrs: &[Attribute]) { - for attr in attrs { - if let AttrStyle::Outer = attr.style { - self.attr(attr); - } - } - } - - pub fn inner_attrs(&mut self, attrs: &[Attribute]) { - for attr in attrs { - if let AttrStyle::Inner(_) = attr.style { - self.attr(attr); - } - } - } - - fn attr(&mut self, attr: &Attribute) { - if let Some(mut doc) = value_of_attribute("doc", attr) { - if doc.contains('\n') { - trim_interior_trailing_spaces(&mut doc); - self.word(match attr.style { - AttrStyle::Outer => "/**", - AttrStyle::Inner(_) => "/*!", - }); - self.word(doc); - self.word("*/"); - } else { - trim_trailing_spaces(&mut doc); - self.word(match attr.style { - AttrStyle::Outer => "///", - AttrStyle::Inner(_) => "//!", - }); - self.word(doc); - } - self.hardbreak(); - } else if let Some(mut comment) = value_of_attribute("comment", attr) { - if comment.contains('\n') { - trim_interior_trailing_spaces(&mut comment); - self.word("/*"); - self.word(comment); - self.word("*/"); - } else { - trim_trailing_spaces(&mut comment); - self.word("//"); - self.word(comment); - } - self.hardbreak(); - } else { - self.word(match attr.style { - AttrStyle::Outer => "#", - AttrStyle::Inner(_) => "#!", - }); - self.word("["); - self.path(&attr.path); - self.attr_tokens(attr.tokens.clone()); - self.word("]"); - self.space(); - } - } - - fn attr_tokens(&mut self, tokens: TokenStream) { - let mut stack = Vec::new(); - stack.push((tokens.into_iter().peekable(), Delimiter::None)); - let mut space = Self::nbsp as fn(&mut Self); - - #[derive(PartialEq)] - enum State { - Word, - Punct, - TrailingComma, - } - - use State::*; - let mut state = Word; - - while let Some((tokens, delimiter)) = stack.last_mut() { - match tokens.next() { - Some(TokenTree::Ident(ident)) => { - if let Word = state { - space(self); - } - self.ident(&ident); - state = Word; - } - Some(TokenTree::Punct(punct)) => { - let ch = punct.as_char(); - if let (Word, '=') = (state, ch) { - self.nbsp(); - } - if ch == ',' && tokens.peek().is_none() { - self.trailing_comma(true); - state = TrailingComma; - } else { - self.token_punct(ch); - if ch == '=' { - self.nbsp(); - } else if ch == ',' { - space(self); - } - state = Punct; - } - } - Some(TokenTree::Literal(literal)) => { - if let Word = state { - space(self); - } - self.token_literal(&literal); - state = Word; - } - Some(TokenTree::Group(group)) => { - let delimiter = group.delimiter(); - let stream = group.stream(); - match delimiter { - Delimiter::Parenthesis => { - self.word("("); - self.cbox(INDENT); - self.zerobreak(); - state = Punct; - } - Delimiter::Brace => { - self.word("{"); - state = Punct; - } - Delimiter::Bracket => { - self.word("["); - state = Punct; - } - Delimiter::None => {} - } - stack.push((stream.into_iter().peekable(), delimiter)); - space = Self::space; - } - None => { - match delimiter { - Delimiter::Parenthesis => { - if state != TrailingComma { - self.zerobreak(); - } - self.offset(-INDENT); - self.end(); - self.word(")"); - state = Punct; - } - Delimiter::Brace => { - self.word("}"); - state = Punct; - } - Delimiter::Bracket => { - self.word("]"); - state = Punct; - } - Delimiter::None => {} - } - stack.pop(); - if stack.is_empty() { - space = Self::nbsp; - } - } - } - } - } -} - -fn value_of_attribute(requested: &str, attr: &Attribute) -> Option { - let is_doc = attr.path.leading_colon.is_none() - && attr.path.segments.len() == 1 - && matches!(attr.path.segments[0].arguments, PathArguments::None) - && attr.path.segments[0].ident == requested; - if !is_doc { - return None; - } - let mut tokens = attr.tokens.clone().into_iter(); - match tokens.next() { - Some(TokenTree::Punct(punct)) if punct.as_char() == '=' => {} - _ => return None, - } - let literal = match tokens.next() { - Some(TokenTree::Literal(literal)) => literal, - _ => return None, - }; - if tokens.next().is_some() { - return None; - } - match Lit::new(literal) { - Lit::Str(string) => Some(string.value()), - _ => None, - } -} - -pub fn has_outer(attrs: &[Attribute]) -> bool { - for attr in attrs { - if let AttrStyle::Outer = attr.style { - return true; - } - } - false -} - -pub fn has_inner(attrs: &[Attribute]) -> bool { - for attr in attrs { - if let AttrStyle::Inner(_) = attr.style { - return true; - } - } - false -} - -fn trim_trailing_spaces(doc: &mut String) { - doc.truncate(doc.trim_end_matches(' ').len()); -} - -fn trim_interior_trailing_spaces(doc: &mut String) { - if !doc.contains(" \n") { - return; - } - let mut trimmed = String::with_capacity(doc.len()); - let mut lines = doc.split('\n').peekable(); - while let Some(line) = lines.next() { - if lines.peek().is_some() { - trimmed.push_str(line.trim_end_matches(' ')); - trimmed.push('\n'); - } else { - trimmed.push_str(line); - } - } - *doc = trimmed; -} diff --git a/prettyplease-forked/src/convenience.rs b/prettyplease-forked/src/convenience.rs deleted file mode 100644 index bc4add6..0000000 --- a/prettyplease-forked/src/convenience.rs +++ /dev/null @@ -1,98 +0,0 @@ -use crate::algorithm::{self, BeginToken, BreakToken, Breaks, Printer}; -use std::borrow::Cow; - -impl Printer { - pub fn ibox(&mut self, indent: isize) { - self.scan_begin(BeginToken { - offset: indent, - breaks: Breaks::Inconsistent, - }); - } - - pub fn cbox(&mut self, indent: isize) { - self.scan_begin(BeginToken { - offset: indent, - breaks: Breaks::Consistent, - }); - } - - pub fn end(&mut self) { - self.scan_end(); - } - - pub fn word>>(&mut self, wrd: S) { - let s = wrd.into(); - self.scan_string(s); - } - - fn spaces(&mut self, n: usize) { - self.scan_break(BreakToken { - blank_space: n, - ..BreakToken::default() - }); - } - - pub fn zerobreak(&mut self) { - self.spaces(0); - } - - pub fn space(&mut self) { - self.spaces(1); - } - - pub fn nbsp(&mut self) { - self.word(" "); - } - - pub fn hardbreak(&mut self) { - self.spaces(algorithm::SIZE_INFINITY as usize); - } - - pub fn space_if_nonempty(&mut self) { - self.scan_break(BreakToken { - blank_space: 1, - if_nonempty: true, - ..BreakToken::default() - }); - } - - pub fn hardbreak_if_nonempty(&mut self) { - self.scan_break(BreakToken { - blank_space: algorithm::SIZE_INFINITY as usize, - if_nonempty: true, - ..BreakToken::default() - }); - } - - pub fn trailing_comma(&mut self, is_last: bool) { - if is_last { - self.scan_break(BreakToken { - pre_break: Some(','), - ..BreakToken::default() - }); - } else { - self.word(","); - self.space(); - } - } - - pub fn trailing_comma_or_space(&mut self, is_last: bool) { - if is_last { - self.scan_break(BreakToken { - blank_space: 1, - pre_break: Some(','), - ..BreakToken::default() - }); - } else { - self.word(","); - self.space(); - } - } - - pub fn neverbreak(&mut self) { - self.scan_break(BreakToken { - never_break: true, - ..BreakToken::default() - }); - } -} diff --git a/prettyplease-forked/src/data.rs b/prettyplease-forked/src/data.rs deleted file mode 100644 index 7767981..0000000 --- a/prettyplease-forked/src/data.rs +++ /dev/null @@ -1,95 +0,0 @@ -use crate::algorithm::Printer; -use crate::iter::IterDelimited; -use crate::INDENT; -use syn::{ - Field, Fields, FieldsUnnamed, PathArguments, Variant, VisCrate, VisPublic, VisRestricted, - Visibility, -}; - -impl Printer { - pub fn variant(&mut self, variant: &Variant) { - self.outer_attrs(&variant.attrs); - self.ident(&variant.ident); - match &variant.fields { - Fields::Named(fields) => { - self.nbsp(); - self.word("{"); - self.cbox(INDENT); - self.space(); - for field in fields.named.iter().delimited() { - self.field(&field); - self.trailing_comma_or_space(field.is_last); - } - self.offset(-INDENT); - self.end(); - self.word("}"); - } - Fields::Unnamed(fields) => { - self.cbox(INDENT); - self.fields_unnamed(fields); - self.end(); - } - Fields::Unit => {} - } - if let Some((_eq_token, discriminant)) = &variant.discriminant { - self.word(" = "); - self.expr(discriminant); - } - } - - pub fn fields_unnamed(&mut self, fields: &FieldsUnnamed) { - self.word("("); - self.zerobreak(); - for field in fields.unnamed.iter().delimited() { - self.field(&field); - self.trailing_comma(field.is_last); - } - self.offset(-INDENT); - self.word(")"); - } - - pub fn field(&mut self, field: &Field) { - self.outer_attrs(&field.attrs); - self.visibility(&field.vis); - if let Some(ident) = &field.ident { - self.ident(ident); - self.word(": "); - } - self.ty(&field.ty); - } - - pub fn visibility(&mut self, vis: &Visibility) { - match vis { - Visibility::Public(vis) => self.vis_public(vis), - Visibility::Crate(vis) => self.vis_crate(vis), - Visibility::Restricted(vis) => self.vis_restricted(vis), - Visibility::Inherited => {} - } - } - - fn vis_public(&mut self, vis: &VisPublic) { - let _ = vis; - self.word("pub "); - } - - fn vis_crate(&mut self, vis: &VisCrate) { - let _ = vis; - self.word("crate "); - } - - fn vis_restricted(&mut self, vis: &VisRestricted) { - self.word("pub("); - let omit_in = vis.path.leading_colon.is_none() - && vis.path.segments.len() == 1 - && matches!(vis.path.segments[0].arguments, PathArguments::None) - && matches!( - vis.path.segments[0].ident.to_string().as_str(), - "self" | "super" | "crate", - ); - if !omit_in { - self.word("in "); - } - self.path(&vis.path); - self.word(") "); - } -} diff --git a/prettyplease-forked/src/expr.rs b/prettyplease-forked/src/expr.rs deleted file mode 100644 index 500a79d..0000000 --- a/prettyplease-forked/src/expr.rs +++ /dev/null @@ -1,1198 +0,0 @@ -use crate::algorithm::{BreakToken, Printer}; -use crate::attr; -use crate::iter::IterDelimited; -use crate::stmt; -use crate::INDENT; -use proc_macro2::TokenStream; -use syn::punctuated::Punctuated; -use syn::{ - token, Arm, Attribute, BinOp, Block, Expr, ExprArray, ExprAssign, ExprAssignOp, ExprAsync, - ExprAwait, ExprBinary, ExprBlock, ExprBox, ExprBreak, ExprCall, ExprCast, ExprClosure, - ExprContinue, ExprField, ExprForLoop, ExprGroup, ExprIf, ExprIndex, ExprLet, ExprLit, ExprLoop, - ExprMacro, ExprMatch, ExprMethodCall, ExprParen, ExprPath, ExprRange, ExprReference, - ExprRepeat, ExprReturn, ExprStruct, ExprTry, ExprTryBlock, ExprTuple, ExprType, ExprUnary, - ExprUnsafe, ExprWhile, ExprYield, FieldValue, GenericMethodArgument, Index, Label, Member, - MethodTurbofish, PathArguments, QSelf, RangeLimits, ReturnType, Stmt, Token, UnOp, -}; - -impl Printer { - pub fn expr(&mut self, expr: &Expr) { - match expr { - Expr::Array(expr) => self.expr_array(expr), - Expr::Assign(expr) => self.expr_assign(expr), - Expr::AssignOp(expr) => self.expr_assign_op(expr), - Expr::Async(expr) => self.expr_async(expr), - Expr::Await(expr) => self.expr_await(expr, false), - Expr::Binary(expr) => self.expr_binary(expr), - Expr::Block(expr) => self.expr_block(expr), - Expr::Box(expr) => self.expr_box(expr), - Expr::Break(expr) => self.expr_break(expr), - Expr::Call(expr) => self.expr_call(expr, false), - Expr::Cast(expr) => self.expr_cast(expr), - Expr::Closure(expr) => self.expr_closure(expr), - Expr::Continue(expr) => self.expr_continue(expr), - Expr::Field(expr) => self.expr_field(expr, false), - Expr::ForLoop(expr) => self.expr_for_loop(expr), - Expr::Group(expr) => self.expr_group(expr), - Expr::If(expr) => self.expr_if(expr), - Expr::Index(expr) => self.expr_index(expr, false), - Expr::Let(expr) => self.expr_let(expr), - Expr::Lit(expr) => self.expr_lit(expr), - Expr::Loop(expr) => self.expr_loop(expr), - Expr::Macro(expr) => self.expr_macro(expr), - Expr::Match(expr) => self.expr_match(expr), - Expr::MethodCall(expr) => self.expr_method_call(expr, false), - Expr::Paren(expr) => self.expr_paren(expr), - Expr::Path(expr) => self.expr_path(expr), - Expr::Range(expr) => self.expr_range(expr), - Expr::Reference(expr) => self.expr_reference(expr), - Expr::Repeat(expr) => self.expr_repeat(expr), - Expr::Return(expr) => self.expr_return(expr), - Expr::Struct(expr) => self.expr_struct(expr), - Expr::Try(expr) => self.expr_try(expr, false), - Expr::TryBlock(expr) => self.expr_try_block(expr), - Expr::Tuple(expr) => self.expr_tuple(expr), - Expr::Type(expr) => self.expr_type(expr), - Expr::Unary(expr) => self.expr_unary(expr), - Expr::Unsafe(expr) => self.expr_unsafe(expr), - Expr::Verbatim(expr) => self.expr_verbatim(expr), - Expr::While(expr) => self.expr_while(expr), - Expr::Yield(expr) => self.expr_yield(expr), - #[cfg_attr(all(test, exhaustive), deny(non_exhaustive_omitted_patterns))] - _ => unimplemented!("unknown Expr"), - } - } - - pub fn expr_beginning_of_line(&mut self, expr: &Expr, beginning_of_line: bool) { - match expr { - Expr::Await(expr) => self.expr_await(expr, beginning_of_line), - Expr::Field(expr) => self.expr_field(expr, beginning_of_line), - Expr::Index(expr) => self.expr_index(expr, beginning_of_line), - Expr::MethodCall(expr) => self.expr_method_call(expr, beginning_of_line), - Expr::Try(expr) => self.expr_try(expr, beginning_of_line), - _ => self.expr(expr), - } - } - - fn subexpr(&mut self, expr: &Expr, beginning_of_line: bool) { - match expr { - Expr::Await(expr) => self.subexpr_await(expr, beginning_of_line), - Expr::Call(expr) => self.subexpr_call(expr), - Expr::Field(expr) => self.subexpr_field(expr, beginning_of_line), - Expr::Index(expr) => self.subexpr_index(expr, beginning_of_line), - Expr::MethodCall(expr) => self.subexpr_method_call(expr, beginning_of_line, false), - Expr::Try(expr) => self.subexpr_try(expr, beginning_of_line), - _ => { - self.cbox(-INDENT); - self.expr(expr); - self.end(); - } - } - } - - // If the given expression is a bare `ExprStruct`, wraps it in parenthesis - // before appending it to `TokenStream`. - fn wrap_exterior_struct(&mut self, expr: &Expr) { - let needs_paren = contains_exterior_struct_lit(expr); - if needs_paren { - self.word("("); - } - self.cbox(0); - self.expr(expr); - if needs_paren { - self.word(")"); - } - if needs_newline_if_wrap(expr) { - self.space(); - } else { - self.nbsp(); - } - self.end(); - } - - fn expr_array(&mut self, expr: &ExprArray) { - self.outer_attrs(&expr.attrs); - self.word("["); - self.cbox(INDENT); - self.zerobreak(); - for element in expr.elems.iter().delimited() { - self.expr(&element); - self.trailing_comma(element.is_last); - } - self.offset(-INDENT); - self.end(); - self.word("]"); - } - - fn expr_assign(&mut self, expr: &ExprAssign) { - self.outer_attrs(&expr.attrs); - self.ibox(0); - self.expr(&expr.left); - self.word(" = "); - self.expr(&expr.right); - self.end(); - } - - fn expr_assign_op(&mut self, expr: &ExprAssignOp) { - self.outer_attrs(&expr.attrs); - self.ibox(INDENT); - self.ibox(-INDENT); - self.expr(&expr.left); - self.end(); - self.space(); - self.binary_operator(&expr.op); - self.nbsp(); - self.expr(&expr.right); - self.end(); - } - - fn expr_async(&mut self, expr: &ExprAsync) { - self.outer_attrs(&expr.attrs); - self.word("async "); - if expr.capture.is_some() { - self.word("move "); - } - self.cbox(INDENT); - self.small_block(&expr.block, &expr.attrs); - self.end(); - } - - fn expr_await(&mut self, expr: &ExprAwait, beginning_of_line: bool) { - self.outer_attrs(&expr.attrs); - self.cbox(INDENT); - self.subexpr_await(expr, beginning_of_line); - self.end(); - } - - fn subexpr_await(&mut self, expr: &ExprAwait, beginning_of_line: bool) { - self.subexpr(&expr.base, beginning_of_line); - self.zerobreak_unless_short_ident(beginning_of_line, &expr.base); - self.word(".await"); - } - - fn expr_binary(&mut self, expr: &ExprBinary) { - self.outer_attrs(&expr.attrs); - self.ibox(INDENT); - self.ibox(-INDENT); - self.expr(&expr.left); - self.end(); - self.space(); - self.binary_operator(&expr.op); - self.nbsp(); - self.expr(&expr.right); - self.end(); - } - - pub fn expr_block(&mut self, expr: &ExprBlock) { - self.outer_attrs(&expr.attrs); - if let Some(label) = &expr.label { - self.label(label); - } - self.cbox(INDENT); - self.small_block(&expr.block, &expr.attrs); - self.end(); - } - - fn expr_box(&mut self, expr: &ExprBox) { - self.outer_attrs(&expr.attrs); - self.word("box "); - self.expr(&expr.expr); - } - - fn expr_break(&mut self, expr: &ExprBreak) { - self.outer_attrs(&expr.attrs); - self.word("break"); - if let Some(lifetime) = &expr.label { - self.nbsp(); - self.lifetime(lifetime); - } - if let Some(value) = &expr.expr { - self.nbsp(); - self.expr(value); - } - } - - fn expr_call(&mut self, expr: &ExprCall, beginning_of_line: bool) { - self.outer_attrs(&expr.attrs); - self.expr_beginning_of_line(&expr.func, beginning_of_line); - self.word("("); - self.call_args(&expr.args); - self.word(")"); - } - - fn subexpr_call(&mut self, expr: &ExprCall) { - self.subexpr(&expr.func, false); - self.word("("); - self.call_args(&expr.args); - self.word(")"); - } - - fn expr_cast(&mut self, expr: &ExprCast) { - self.outer_attrs(&expr.attrs); - self.ibox(INDENT); - self.ibox(-INDENT); - self.expr(&expr.expr); - self.end(); - self.space(); - self.word("as "); - self.ty(&expr.ty); - self.end(); - } - - fn expr_closure(&mut self, expr: &ExprClosure) { - self.outer_attrs(&expr.attrs); - self.ibox(0); - if expr.asyncness.is_some() { - self.word("async "); - } - if expr.movability.is_some() { - self.word("static "); - } - if expr.capture.is_some() { - self.word("move "); - } - self.cbox(INDENT); - self.word("|"); - for pat in expr.inputs.iter().delimited() { - if pat.is_first { - self.zerobreak(); - } - self.pat(&pat); - if !pat.is_last { - self.word(","); - self.space(); - } - } - match &expr.output { - ReturnType::Default => { - self.word("|"); - self.space(); - self.offset(-INDENT); - self.end(); - self.neverbreak(); - let wrap_in_brace = match &*expr.body { - Expr::Match(ExprMatch { attrs, .. }) | Expr::Call(ExprCall { attrs, .. }) => { - attr::has_outer(attrs) - } - body => !is_blocklike(body), - }; - if wrap_in_brace { - self.cbox(INDENT); - self.scan_break(BreakToken { - pre_break: Some('{'), - ..BreakToken::default() - }); - self.expr(&expr.body); - self.scan_break(BreakToken { - offset: -INDENT, - pre_break: stmt::add_semi(&expr.body).then(|| ';'), - post_break: Some('}'), - ..BreakToken::default() - }); - self.end(); - } else { - self.expr(&expr.body); - } - } - ReturnType::Type(_arrow, ty) => { - if !expr.inputs.is_empty() { - self.trailing_comma(true); - self.offset(-INDENT); - } - self.word("|"); - self.end(); - self.word(" -> "); - self.ty(ty); - self.nbsp(); - self.neverbreak(); - self.expr(&expr.body); - } - } - self.end(); - } - - fn expr_continue(&mut self, expr: &ExprContinue) { - self.outer_attrs(&expr.attrs); - self.word("continue"); - if let Some(lifetime) = &expr.label { - self.nbsp(); - self.lifetime(lifetime); - } - } - - fn expr_field(&mut self, expr: &ExprField, beginning_of_line: bool) { - self.outer_attrs(&expr.attrs); - self.cbox(INDENT); - self.subexpr_field(expr, beginning_of_line); - self.end(); - } - - fn subexpr_field(&mut self, expr: &ExprField, beginning_of_line: bool) { - self.subexpr(&expr.base, beginning_of_line); - self.zerobreak_unless_short_ident(beginning_of_line, &expr.base); - self.word("."); - self.member(&expr.member); - } - - fn expr_for_loop(&mut self, expr: &ExprForLoop) { - self.outer_attrs(&expr.attrs); - self.ibox(0); - if let Some(label) = &expr.label { - self.label(label); - } - self.word("for "); - self.pat(&expr.pat); - self.word(" in "); - self.neverbreak(); - self.wrap_exterior_struct(&expr.expr); - self.word("{"); - self.neverbreak(); - self.cbox(INDENT); - self.hardbreak_if_nonempty(); - self.inner_attrs(&expr.attrs); - for stmt in &expr.body.stmts { - self.stmt(stmt); - } - self.offset(-INDENT); - self.end(); - self.word("}"); - self.end(); - } - - fn expr_group(&mut self, expr: &ExprGroup) { - self.outer_attrs(&expr.attrs); - self.expr(&expr.expr); - } - - fn expr_if(&mut self, expr: &ExprIf) { - self.outer_attrs(&expr.attrs); - self.cbox(INDENT); - self.word("if "); - self.cbox(-INDENT); - self.wrap_exterior_struct(&expr.cond); - self.end(); - if let Some((_else_token, else_branch)) = &expr.else_branch { - let mut else_branch = &**else_branch; - self.small_block(&expr.then_branch, &[]); - loop { - self.word(" else "); - match else_branch { - Expr::If(expr) => { - self.word("if "); - self.cbox(-INDENT); - self.wrap_exterior_struct(&expr.cond); - self.end(); - self.small_block(&expr.then_branch, &[]); - if let Some((_else_token, next)) = &expr.else_branch { - else_branch = next; - continue; - } - } - Expr::Block(expr) => { - self.small_block(&expr.block, &[]); - } - // If not one of the valid expressions to exist in an else - // clause, wrap in a block. - other => { - self.word("{"); - self.space(); - self.ibox(INDENT); - self.expr(other); - self.end(); - self.space(); - self.offset(-INDENT); - self.word("}"); - } - } - break; - } - } else if expr.then_branch.stmts.is_empty() { - self.word("{}"); - } else { - self.word("{"); - self.hardbreak(); - for stmt in &expr.then_branch.stmts { - self.stmt(stmt); - } - self.offset(-INDENT); - self.word("}"); - } - self.end(); - } - - fn expr_index(&mut self, expr: &ExprIndex, beginning_of_line: bool) { - self.outer_attrs(&expr.attrs); - self.expr_beginning_of_line(&expr.expr, beginning_of_line); - self.word("["); - self.expr(&expr.index); - self.word("]"); - } - - fn subexpr_index(&mut self, expr: &ExprIndex, beginning_of_line: bool) { - self.subexpr(&expr.expr, beginning_of_line); - self.word("["); - self.expr(&expr.index); - self.word("]"); - } - - fn expr_let(&mut self, expr: &ExprLet) { - self.outer_attrs(&expr.attrs); - self.ibox(INDENT); - self.word("let "); - self.ibox(-INDENT); - self.pat(&expr.pat); - self.end(); - self.space(); - self.word("= "); - let needs_paren = contains_exterior_struct_lit(&expr.expr); - if needs_paren { - self.word("("); - } - self.expr(&expr.expr); - if needs_paren { - self.word(")"); - } - self.end(); - } - - pub fn expr_lit(&mut self, expr: &ExprLit) { - self.outer_attrs(&expr.attrs); - self.lit(&expr.lit); - } - - fn expr_loop(&mut self, expr: &ExprLoop) { - self.outer_attrs(&expr.attrs); - if let Some(label) = &expr.label { - self.label(label); - } - self.word("loop {"); - self.cbox(INDENT); - self.hardbreak_if_nonempty(); - self.inner_attrs(&expr.attrs); - for stmt in &expr.body.stmts { - self.stmt(stmt); - } - self.offset(-INDENT); - self.end(); - self.word("}"); - } - - fn expr_macro(&mut self, expr: &ExprMacro) { - self.outer_attrs(&expr.attrs); - self.mac(&expr.mac, None); - } - - fn expr_match(&mut self, expr: &ExprMatch) { - self.outer_attrs(&expr.attrs); - self.ibox(0); - self.word("match "); - self.wrap_exterior_struct(&expr.expr); - self.word("{"); - self.neverbreak(); - self.cbox(INDENT); - self.hardbreak_if_nonempty(); - self.inner_attrs(&expr.attrs); - for arm in &expr.arms { - self.arm(arm); - self.hardbreak(); - } - self.offset(-INDENT); - self.end(); - self.word("}"); - self.end(); - } - - fn expr_method_call(&mut self, expr: &ExprMethodCall, beginning_of_line: bool) { - self.outer_attrs(&expr.attrs); - self.cbox(INDENT); - let unindent_call_args = beginning_of_line && is_short_ident(&expr.receiver); - self.subexpr_method_call(expr, beginning_of_line, unindent_call_args); - self.end(); - } - - fn subexpr_method_call( - &mut self, - expr: &ExprMethodCall, - beginning_of_line: bool, - unindent_call_args: bool, - ) { - self.subexpr(&expr.receiver, beginning_of_line); - self.zerobreak_unless_short_ident(beginning_of_line, &expr.receiver); - self.word("."); - self.ident(&expr.method); - if let Some(turbofish) = &expr.turbofish { - self.method_turbofish(turbofish); - } - self.cbox(if unindent_call_args { -INDENT } else { 0 }); - self.word("("); - self.call_args(&expr.args); - self.word(")"); - self.end(); - } - - fn expr_paren(&mut self, expr: &ExprParen) { - self.outer_attrs(&expr.attrs); - self.word("("); - self.expr(&expr.expr); - self.word(")"); - } - - fn expr_path(&mut self, expr: &ExprPath) { - self.outer_attrs(&expr.attrs); - self.qpath(&expr.qself, &expr.path); - } - - fn expr_range(&mut self, expr: &ExprRange) { - self.outer_attrs(&expr.attrs); - if let Some(from) = &expr.from { - self.expr(from); - } - self.word(match expr.limits { - RangeLimits::HalfOpen(_) => "..", - RangeLimits::Closed(_) => "..=", - }); - if let Some(to) = &expr.to { - self.expr(to); - } - } - - fn expr_reference(&mut self, expr: &ExprReference) { - self.outer_attrs(&expr.attrs); - self.word("&"); - if expr.mutability.is_some() { - self.word("mut "); - } - self.expr(&expr.expr); - } - - fn expr_repeat(&mut self, expr: &ExprRepeat) { - self.outer_attrs(&expr.attrs); - self.word("["); - self.expr(&expr.expr); - self.word("; "); - self.expr(&expr.len); - self.word("]"); - } - - fn expr_return(&mut self, expr: &ExprReturn) { - self.outer_attrs(&expr.attrs); - self.word("return"); - if let Some(value) = &expr.expr { - self.nbsp(); - self.expr(value); - } - } - - fn expr_struct(&mut self, expr: &ExprStruct) { - self.expr_qualified_struct(&None, expr); - } - - fn expr_qualified_struct(&mut self, qself: &Option, expr: &ExprStruct) { - self.outer_attrs(&expr.attrs); - self.cbox(INDENT); - self.ibox(-INDENT); - self.qpath(qself, &expr.path); - self.end(); - self.word(" {"); - self.space_if_nonempty(); - for field_value in expr.fields.iter().delimited() { - self.field_value(&field_value); - self.trailing_comma_or_space(field_value.is_last && expr.rest.is_none()); - } - if let Some(rest) = &expr.rest { - self.word(".."); - self.expr(rest); - self.space(); - } - self.offset(-INDENT); - self.end_with_max_width(34); - self.word("}"); - } - - fn expr_try(&mut self, expr: &ExprTry, beginning_of_line: bool) { - self.outer_attrs(&expr.attrs); - self.expr_beginning_of_line(&expr.expr, beginning_of_line); - self.word("?"); - } - - fn subexpr_try(&mut self, expr: &ExprTry, beginning_of_line: bool) { - self.subexpr(&expr.expr, beginning_of_line); - self.word("?"); - } - - fn expr_try_block(&mut self, expr: &ExprTryBlock) { - self.outer_attrs(&expr.attrs); - self.word("try "); - self.cbox(INDENT); - self.small_block(&expr.block, &expr.attrs); - self.end(); - } - - fn expr_tuple(&mut self, expr: &ExprTuple) { - self.outer_attrs(&expr.attrs); - self.word("("); - self.cbox(INDENT); - self.zerobreak(); - for elem in expr.elems.iter().delimited() { - self.expr(&elem); - if expr.elems.len() == 1 { - self.word(","); - self.zerobreak(); - } else { - self.trailing_comma(elem.is_last); - } - } - self.offset(-INDENT); - self.end(); - self.word(")"); - } - - fn expr_type(&mut self, expr: &ExprType) { - self.outer_attrs(&expr.attrs); - self.ibox(INDENT); - self.ibox(-INDENT); - self.expr(&expr.expr); - self.end(); - self.space(); - self.word(": "); - self.ty(&expr.ty); - self.end(); - } - - fn expr_unary(&mut self, expr: &ExprUnary) { - self.outer_attrs(&expr.attrs); - self.unary_operator(&expr.op); - self.expr(&expr.expr); - } - - fn expr_unsafe(&mut self, expr: &ExprUnsafe) { - self.outer_attrs(&expr.attrs); - self.word("unsafe {"); - self.cbox(INDENT); - self.space_if_nonempty(); - self.inner_attrs(&expr.attrs); - for stmt in expr.block.stmts.iter().delimited() { - if stmt.is_first && stmt.is_last { - if let Stmt::Expr(expr) = &*stmt { - self.expr(expr); - self.space(); - continue; - } - } - self.stmt(&stmt); - } - self.offset(-INDENT); - self.end(); - self.word("}"); - } - - #[cfg(feature = "verbatim")] - fn expr_verbatim(&mut self, tokens: &TokenStream) { - use syn::parse::{Parse, ParseStream, Result}; - use syn::{braced, BoundLifetimes}; - - enum ExprVerbatim { - Empty, - Infer, - RawReference(RawReference), - ConstBlock(ConstBlock), - ClosureWithLifetimes(ClosureWithLifetimes), - QualifiedStruct(QualifiedStruct), - } - - struct RawReference { - mutable: bool, - expr: Expr, - } - - struct ConstBlock { - attrs: Vec, - block: Block, - } - - struct ClosureWithLifetimes { - lifetimes: BoundLifetimes, - closure: ExprClosure, - } - - struct QualifiedStruct { - qself: QSelf, - strct: ExprStruct, - } - - mod kw { - syn::custom_keyword!(raw); - } - - impl Parse for ExprVerbatim { - fn parse(input: ParseStream) -> Result { - let lookahead = input.lookahead1(); - if input.is_empty() { - Ok(ExprVerbatim::Empty) - } else if lookahead.peek(Token![_]) { - input.parse::()?; - Ok(ExprVerbatim::Infer) - } else if lookahead.peek(Token![&]) { - input.parse::()?; - input.parse::()?; - let mutable = input.parse::>()?.is_some(); - if !mutable { - input.parse::()?; - } - let expr: Expr = input.parse()?; - Ok(ExprVerbatim::RawReference(RawReference { mutable, expr })) - } else if lookahead.peek(Token![const]) { - input.parse::()?; - let content; - let brace_token = braced!(content in input); - let attrs = content.call(Attribute::parse_inner)?; - let stmts = content.call(Block::parse_within)?; - Ok(ExprVerbatim::ConstBlock(ConstBlock { - attrs, - block: Block { brace_token, stmts }, - })) - } else if lookahead.peek(Token![for]) { - let lifetimes = input.parse()?; - let closure = input.parse()?; - Ok(ExprVerbatim::ClosureWithLifetimes(ClosureWithLifetimes { - lifetimes, - closure, - })) - } else if lookahead.peek(Token![<]) { - let path: ExprPath = input.parse()?; - let content; - let mut expr = QualifiedStruct { - qself: path.qself.unwrap(), - strct: ExprStruct { - attrs: Vec::new(), - brace_token: braced!(content in input), - path: path.path, - fields: Punctuated::new(), - dot2_token: None, - rest: None, - }, - }; - while !content.is_empty() { - if content.peek(Token![..]) { - expr.strct.dot2_token = Some(content.parse()?); - if !content.is_empty() { - expr.strct.rest = Some(Box::new(content.parse()?)); - } - break; - } - expr.strct.fields.push(content.parse()?); - if content.is_empty() { - break; - } - let punct: Token![,] = content.parse()?; - expr.strct.fields.push_punct(punct); - } - Ok(ExprVerbatim::QualifiedStruct(expr)) - } else { - Err(lookahead.error()) - } - } - } - - let expr: ExprVerbatim = match syn::parse2(tokens.clone()) { - Ok(expr) => expr, - Err(_) => return self.word(tokens.to_string()), - }; - - match expr { - ExprVerbatim::Empty => {} - ExprVerbatim::Infer => { - self.word("_"); - } - ExprVerbatim::RawReference(expr) => { - self.word("&raw "); - self.word(if expr.mutable { "mut " } else { "const " }); - self.expr(&expr.expr); - } - ExprVerbatim::ConstBlock(expr) => { - self.outer_attrs(&expr.attrs); - self.cbox(INDENT); - self.word("const "); - self.small_block(&expr.block, &expr.attrs); - self.end(); - } - ExprVerbatim::ClosureWithLifetimes(expr) => { - self.bound_lifetimes(&expr.lifetimes); - self.expr_closure(&expr.closure); - } - ExprVerbatim::QualifiedStruct(expr) => { - self.expr_qualified_struct(&Some(expr.qself), &expr.strct); - } - } - } - - fn expr_while(&mut self, expr: &ExprWhile) { - self.outer_attrs(&expr.attrs); - if let Some(label) = &expr.label { - self.label(label); - } - self.word("while "); - self.wrap_exterior_struct(&expr.cond); - self.word("{"); - self.neverbreak(); - self.cbox(INDENT); - self.hardbreak_if_nonempty(); - self.inner_attrs(&expr.attrs); - for stmt in &expr.body.stmts { - self.stmt(stmt); - } - self.offset(-INDENT); - self.end(); - self.word("}"); - } - - fn expr_yield(&mut self, expr: &ExprYield) { - self.outer_attrs(&expr.attrs); - self.word("yield"); - if let Some(value) = &expr.expr { - self.nbsp(); - self.expr(value); - } - } - - fn label(&mut self, label: &Label) { - self.lifetime(&label.name); - self.word(": "); - } - - fn field_value(&mut self, field_value: &FieldValue) { - self.outer_attrs(&field_value.attrs); - self.member(&field_value.member); - if field_value.colon_token.is_some() { - self.word(": "); - self.ibox(0); - self.expr(&field_value.expr); - self.end(); - } - } - - fn arm(&mut self, arm: &Arm) { - self.outer_attrs(&arm.attrs); - self.ibox(0); - self.pat(&arm.pat); - if let Some((_if_token, guard)) = &arm.guard { - self.word(" if "); - self.expr(guard); - } - self.word(" =>"); - let empty_block; - let mut body = &*arm.body; - while let Expr::Block(expr) = body { - if expr.attrs.is_empty() && expr.label.is_none() { - let mut stmts = expr.block.stmts.iter(); - if let (Some(Stmt::Expr(inner)), None) = (stmts.next(), stmts.next()) { - body = inner; - continue; - } - } - break; - } - if let Expr::Tuple(expr) = body { - if expr.elems.is_empty() && expr.attrs.is_empty() { - empty_block = Expr::Block(ExprBlock { - attrs: Vec::new(), - label: None, - block: Block { - brace_token: token::Brace::default(), - stmts: Vec::new(), - }, - }); - body = &empty_block; - } - } - if let Expr::Block(body) = body { - self.nbsp(); - if let Some(label) = &body.label { - self.label(label); - } - self.word("{"); - self.neverbreak(); - self.cbox(INDENT); - self.hardbreak_if_nonempty(); - self.inner_attrs(&body.attrs); - for stmt in &body.block.stmts { - self.stmt(stmt); - } - self.offset(-INDENT); - self.end(); - self.word("}"); - self.end(); - } else { - self.nbsp(); - self.neverbreak(); - self.cbox(INDENT); - self.scan_break(BreakToken { - pre_break: Some('{'), - ..BreakToken::default() - }); - self.expr(body); - self.scan_break(BreakToken { - offset: -INDENT, - pre_break: stmt::add_semi(body).then(|| ';'), - post_break: Some('}'), - no_break: requires_terminator(body).then(|| ','), - ..BreakToken::default() - }); - self.end(); - self.end(); - } - } - - fn method_turbofish(&mut self, turbofish: &MethodTurbofish) { - self.word("::<"); - self.cbox(INDENT); - self.zerobreak(); - for arg in turbofish.args.iter().delimited() { - self.generic_method_argument(&arg); - self.trailing_comma(arg.is_last); - } - self.offset(-INDENT); - self.end(); - self.word(">"); - } - - fn generic_method_argument(&mut self, generic: &GenericMethodArgument) { - match generic { - GenericMethodArgument::Type(arg) => self.ty(arg), - GenericMethodArgument::Const(arg) => self.expr(arg), - } - } - - fn call_args(&mut self, args: &Punctuated) { - let mut iter = args.iter(); - match (iter.next(), iter.next()) { - (Some(expr), None) if is_blocklike(expr) => { - self.expr(expr); - } - _ => { - self.cbox(INDENT); - self.zerobreak(); - for arg in args.iter().delimited() { - self.expr(&arg); - self.trailing_comma(arg.is_last); - } - self.offset(-INDENT); - self.end(); - } - } - } - - fn small_block(&mut self, block: &Block, attrs: &[Attribute]) { - self.word("{"); - if attr::has_inner(attrs) || !block.stmts.is_empty() { - self.space(); - self.inner_attrs(attrs); - match (block.stmts.get(0), block.stmts.get(1)) { - (Some(Stmt::Expr(expr)), None) if stmt::break_after(expr) => { - self.ibox(0); - self.expr_beginning_of_line(expr, true); - self.end(); - self.space(); - } - _ => { - for stmt in &block.stmts { - self.stmt(stmt); - } - } - } - self.offset(-INDENT); - } - self.word("}"); - } - - pub fn member(&mut self, member: &Member) { - match member { - Member::Named(ident) => self.ident(ident), - Member::Unnamed(index) => self.index(index), - } - } - - fn index(&mut self, member: &Index) { - self.word(member.index.to_string()); - } - - fn binary_operator(&mut self, op: &BinOp) { - self.word(match op { - BinOp::Add(_) => "+", - BinOp::Sub(_) => "-", - BinOp::Mul(_) => "*", - BinOp::Div(_) => "/", - BinOp::Rem(_) => "%", - BinOp::And(_) => "&&", - BinOp::Or(_) => "||", - BinOp::BitXor(_) => "^", - BinOp::BitAnd(_) => "&", - BinOp::BitOr(_) => "|", - BinOp::Shl(_) => "<<", - BinOp::Shr(_) => ">>", - BinOp::Eq(_) => "==", - BinOp::Lt(_) => "<", - BinOp::Le(_) => "<=", - BinOp::Ne(_) => "!=", - BinOp::Ge(_) => ">=", - BinOp::Gt(_) => ">", - BinOp::AddEq(_) => "+=", - BinOp::SubEq(_) => "-=", - BinOp::MulEq(_) => "*=", - BinOp::DivEq(_) => "/=", - BinOp::RemEq(_) => "%=", - BinOp::BitXorEq(_) => "^=", - BinOp::BitAndEq(_) => "&=", - BinOp::BitOrEq(_) => "|=", - BinOp::ShlEq(_) => "<<=", - BinOp::ShrEq(_) => ">>=", - }); - } - - fn unary_operator(&mut self, op: &UnOp) { - self.word(match op { - UnOp::Deref(_) => "*", - UnOp::Not(_) => "!", - UnOp::Neg(_) => "-", - }); - } - - fn zerobreak_unless_short_ident(&mut self, beginning_of_line: bool, expr: &Expr) { - if beginning_of_line && is_short_ident(expr) { - return; - } - self.zerobreak(); - } -} - -pub fn requires_terminator(expr: &Expr) -> bool { - // see https://github.com/rust-lang/rust/blob/2679c38fc/src/librustc_ast/util/classify.rs#L7-L25 - match expr { - Expr::Unsafe(_) - | Expr::Block(_) - | Expr::If(_) - | Expr::Match(_) - | Expr::While(_) - | Expr::Loop(_) - | Expr::ForLoop(_) - | Expr::Async(_) - | Expr::TryBlock(_) => false, - _ => true, - } -} - -// Expressions that syntactically contain an "exterior" struct literal i.e. not -// surrounded by any parens or other delimiters. For example `X { y: 1 }`, `X { -// y: 1 }.method()`, `foo == X { y: 1 }` and `X { y: 1 } == foo` all do, but `(X -// { y: 1 }) == foo` does not. -fn contains_exterior_struct_lit(expr: &Expr) -> bool { - match expr { - Expr::Struct(_) => true, - - Expr::Assign(ExprAssign { left, right, .. }) - | Expr::AssignOp(ExprAssignOp { left, right, .. }) - | Expr::Binary(ExprBinary { left, right, .. }) => { - // X { y: 1 } + X { y: 2 } - contains_exterior_struct_lit(left) || contains_exterior_struct_lit(right) - } - - Expr::Await(ExprAwait { base: e, .. }) - | Expr::Box(ExprBox { expr: e, .. }) - | Expr::Cast(ExprCast { expr: e, .. }) - | Expr::Field(ExprField { base: e, .. }) - | Expr::Index(ExprIndex { expr: e, .. }) - | Expr::MethodCall(ExprMethodCall { receiver: e, .. }) - | Expr::Reference(ExprReference { expr: e, .. }) - | Expr::Type(ExprType { expr: e, .. }) - | Expr::Unary(ExprUnary { expr: e, .. }) => { - // &X { y: 1 }, X { y: 1 }.y - contains_exterior_struct_lit(e) - } - - _ => false, - } -} - -fn needs_newline_if_wrap(expr: &Expr) -> bool { - match expr { - Expr::Array(_) - | Expr::Async(_) - | Expr::Block(_) - | Expr::Break(ExprBreak { expr: None, .. }) - | Expr::Closure(_) - | Expr::Continue(_) - | Expr::ForLoop(_) - | Expr::If(_) - | Expr::Lit(_) - | Expr::Loop(_) - | Expr::Macro(_) - | Expr::Match(_) - | Expr::Path(_) - | Expr::Range(ExprRange { to: None, .. }) - | Expr::Repeat(_) - | Expr::Return(ExprReturn { expr: None, .. }) - | Expr::Struct(_) - | Expr::TryBlock(_) - | Expr::Tuple(_) - | Expr::Unsafe(_) - | Expr::Verbatim(_) - | Expr::While(_) - | Expr::Yield(ExprYield { expr: None, .. }) => false, - - Expr::Assign(_) - | Expr::AssignOp(_) - | Expr::Await(_) - | Expr::Binary(_) - | Expr::Cast(_) - | Expr::Field(_) - | Expr::Index(_) - | Expr::MethodCall(_) - | Expr::Type(_) => true, - - Expr::Box(ExprBox { expr: e, .. }) - | Expr::Break(ExprBreak { expr: Some(e), .. }) - | Expr::Call(ExprCall { func: e, .. }) - | Expr::Group(ExprGroup { expr: e, .. }) - | Expr::Let(ExprLet { expr: e, .. }) - | Expr::Paren(ExprParen { expr: e, .. }) - | Expr::Range(ExprRange { to: Some(e), .. }) - | Expr::Reference(ExprReference { expr: e, .. }) - | Expr::Return(ExprReturn { expr: Some(e), .. }) - | Expr::Try(ExprTry { expr: e, .. }) - | Expr::Unary(ExprUnary { expr: e, .. }) - | Expr::Yield(ExprYield { expr: Some(e), .. }) => needs_newline_if_wrap(e), - - #[cfg_attr(all(test, exhaustive), deny(non_exhaustive_omitted_patterns))] - _ => false, - } -} - -fn is_short_ident(expr: &Expr) -> bool { - if let Expr::Path(expr) = expr { - if expr.attrs.is_empty() - && expr.qself.is_none() - && expr.path.leading_colon.is_none() - && expr.path.segments.len() == 1 - && expr.path.segments[0].ident.to_string().len() as isize <= INDENT - { - if let PathArguments::None = expr.path.segments[0].arguments { - return true; - } - } - } - false -} - -fn is_blocklike(expr: &Expr) -> bool { - match expr { - Expr::Array(ExprArray { attrs, .. }) - | Expr::Async(ExprAsync { attrs, .. }) - | Expr::Block(ExprBlock { attrs, .. }) - | Expr::Closure(ExprClosure { attrs, .. }) - | Expr::Struct(ExprStruct { attrs, .. }) - | Expr::TryBlock(ExprTryBlock { attrs, .. }) - | Expr::Tuple(ExprTuple { attrs, .. }) - | Expr::Unsafe(ExprUnsafe { attrs, .. }) => !attr::has_outer(attrs), - _ => false, - } -} diff --git a/prettyplease-forked/src/file.rs b/prettyplease-forked/src/file.rs deleted file mode 100644 index e23bd12..0000000 --- a/prettyplease-forked/src/file.rs +++ /dev/null @@ -1,17 +0,0 @@ -use crate::algorithm::Printer; -use syn::File; - -impl Printer { - pub fn file(&mut self, file: &File) { - self.cbox(0); - if let Some(shebang) = &file.shebang { - self.word(shebang.clone()); - self.hardbreak(); - } - self.inner_attrs(&file.attrs); - for item in &file.items { - self.item(item); - } - self.end(); - } -} diff --git a/prettyplease-forked/src/generics.rs b/prettyplease-forked/src/generics.rs deleted file mode 100644 index 2714854..0000000 --- a/prettyplease-forked/src/generics.rs +++ /dev/null @@ -1,280 +0,0 @@ -use crate::algorithm::Printer; -use crate::iter::IterDelimited; -use crate::INDENT; -use syn::{ - BoundLifetimes, ConstParam, GenericParam, Generics, LifetimeDef, PredicateEq, - PredicateLifetime, PredicateType, TraitBound, TraitBoundModifier, TypeParam, TypeParamBound, - WhereClause, WherePredicate, -}; - -impl Printer { - pub fn generics(&mut self, generics: &Generics) { - if generics.params.is_empty() { - return; - } - - self.word("<"); - self.cbox(0); - self.zerobreak(); - - // Print lifetimes before types and consts, regardless of their - // order in self.params. - // - // TODO: ordering rules for const parameters vs type parameters have - // not been settled yet. https://github.com/rust-lang/rust/issues/44580 - for param in generics.params.iter().delimited() { - if let GenericParam::Lifetime(_) = *param { - self.generic_param(¶m); - self.trailing_comma(param.is_last); - } - } - for param in generics.params.iter().delimited() { - match *param { - GenericParam::Type(_) | GenericParam::Const(_) => { - self.generic_param(¶m); - self.trailing_comma(param.is_last); - } - GenericParam::Lifetime(_) => {} - } - } - - self.offset(-INDENT); - self.end(); - self.word(">"); - } - - fn generic_param(&mut self, generic_param: &GenericParam) { - match generic_param { - GenericParam::Type(type_param) => self.type_param(type_param), - GenericParam::Lifetime(lifetime_def) => self.lifetime_def(lifetime_def), - GenericParam::Const(const_param) => self.const_param(const_param), - } - } - - pub fn bound_lifetimes(&mut self, bound_lifetimes: &BoundLifetimes) { - self.word("for<"); - for lifetime_def in bound_lifetimes.lifetimes.iter().delimited() { - self.lifetime_def(&lifetime_def); - if !lifetime_def.is_last { - self.word(", "); - } - } - self.word("> "); - } - - fn lifetime_def(&mut self, lifetime_def: &LifetimeDef) { - self.outer_attrs(&lifetime_def.attrs); - self.lifetime(&lifetime_def.lifetime); - for lifetime in lifetime_def.bounds.iter().delimited() { - if lifetime.is_first { - self.word(": "); - } else { - self.word(" + "); - } - self.lifetime(&lifetime); - } - } - - fn type_param(&mut self, type_param: &TypeParam) { - self.outer_attrs(&type_param.attrs); - self.ident(&type_param.ident); - self.ibox(INDENT); - for type_param_bound in type_param.bounds.iter().delimited() { - if type_param_bound.is_first { - self.word(": "); - } else { - self.space(); - self.word("+ "); - } - self.type_param_bound(&type_param_bound); - } - if let Some(default) = &type_param.default { - self.space(); - self.word("= "); - self.ty(default); - } - self.end(); - } - - pub fn type_param_bound(&mut self, type_param_bound: &TypeParamBound) { - match type_param_bound { - TypeParamBound::Trait(trait_bound) => self.trait_bound(trait_bound), - TypeParamBound::Lifetime(lifetime) => self.lifetime(lifetime), - } - } - - fn trait_bound(&mut self, trait_bound: &TraitBound) { - if trait_bound.paren_token.is_some() { - self.word("("); - } - let skip = match trait_bound.path.segments.first() { - Some(segment) if segment.ident == "const" => { - self.word("~const "); - 1 - } - _ => 0, - }; - self.trait_bound_modifier(&trait_bound.modifier); - if let Some(bound_lifetimes) = &trait_bound.lifetimes { - self.bound_lifetimes(bound_lifetimes); - } - for segment in trait_bound.path.segments.iter().skip(skip).delimited() { - if !segment.is_first || trait_bound.path.leading_colon.is_some() { - self.word("::"); - } - self.path_segment(&segment); - } - if trait_bound.paren_token.is_some() { - self.word(")"); - } - } - - fn trait_bound_modifier(&mut self, trait_bound_modifier: &TraitBoundModifier) { - match trait_bound_modifier { - TraitBoundModifier::None => {} - TraitBoundModifier::Maybe(_question_mark) => self.word("?"), - } - } - - fn const_param(&mut self, const_param: &ConstParam) { - self.outer_attrs(&const_param.attrs); - self.word("const "); - self.ident(&const_param.ident); - self.word(": "); - self.ty(&const_param.ty); - if let Some(default) = &const_param.default { - self.word(" = "); - self.expr(default); - } - } - - pub fn where_clause_for_body(&mut self, where_clause: &Option) { - let hardbreaks = true; - let semi = false; - self.where_clause_impl(where_clause, hardbreaks, semi); - } - - pub fn where_clause_semi(&mut self, where_clause: &Option) { - let hardbreaks = true; - let semi = true; - self.where_clause_impl(where_clause, hardbreaks, semi); - } - - pub fn where_clause_oneline(&mut self, where_clause: &Option) { - let hardbreaks = false; - let semi = false; - self.where_clause_impl(where_clause, hardbreaks, semi); - } - - pub fn where_clause_oneline_semi(&mut self, where_clause: &Option) { - let hardbreaks = false; - let semi = true; - self.where_clause_impl(where_clause, hardbreaks, semi); - } - - fn where_clause_impl( - &mut self, - where_clause: &Option, - hardbreaks: bool, - semi: bool, - ) { - let where_clause = match where_clause { - Some(where_clause) if !where_clause.predicates.is_empty() => where_clause, - _ => { - if semi { - self.word(";"); - } else { - self.nbsp(); - } - return; - } - }; - if hardbreaks { - self.hardbreak(); - self.offset(-INDENT); - self.word("where"); - self.hardbreak(); - for predicate in where_clause.predicates.iter().delimited() { - self.where_predicate(&predicate); - if predicate.is_last && semi { - self.word(";"); - } else { - self.word(","); - self.hardbreak(); - } - } - if !semi { - self.offset(-INDENT); - } - } else { - self.space(); - self.offset(-INDENT); - self.word("where"); - self.space(); - for predicate in where_clause.predicates.iter().delimited() { - self.where_predicate(&predicate); - if predicate.is_last && semi { - self.word(";"); - } else { - self.trailing_comma_or_space(predicate.is_last); - } - } - if !semi { - self.offset(-INDENT); - } - } - } - - fn where_predicate(&mut self, predicate: &WherePredicate) { - match predicate { - WherePredicate::Type(predicate) => self.predicate_type(predicate), - WherePredicate::Lifetime(predicate) => self.predicate_lifetime(predicate), - WherePredicate::Eq(predicate) => self.predicate_eq(predicate), - } - } - - fn predicate_type(&mut self, predicate: &PredicateType) { - if let Some(bound_lifetimes) = &predicate.lifetimes { - self.bound_lifetimes(bound_lifetimes); - } - self.ty(&predicate.bounded_ty); - self.word(":"); - if predicate.bounds.len() == 1 { - self.ibox(0); - } else { - self.ibox(INDENT); - } - for type_param_bound in predicate.bounds.iter().delimited() { - if type_param_bound.is_first { - self.nbsp(); - } else { - self.space(); - self.word("+ "); - } - self.type_param_bound(&type_param_bound); - } - self.end(); - } - - fn predicate_lifetime(&mut self, predicate: &PredicateLifetime) { - self.lifetime(&predicate.lifetime); - self.word(":"); - self.ibox(INDENT); - for lifetime in predicate.bounds.iter().delimited() { - if lifetime.is_first { - self.nbsp(); - } else { - self.space(); - self.word("+ "); - } - self.lifetime(&lifetime); - } - self.end(); - } - - fn predicate_eq(&mut self, predicate: &PredicateEq) { - self.ty(&predicate.lhs_ty); - self.word(" = "); - self.ty(&predicate.rhs_ty); - } -} diff --git a/prettyplease-forked/src/item.rs b/prettyplease-forked/src/item.rs deleted file mode 100644 index f046642..0000000 --- a/prettyplease-forked/src/item.rs +++ /dev/null @@ -1,822 +0,0 @@ -use crate::algorithm::Printer; -use crate::iter::IterDelimited; -use crate::INDENT; -use proc_macro2::TokenStream; -use syn::{ - Fields, FnArg, ForeignItem, ForeignItemFn, ForeignItemMacro, ForeignItemStatic, - ForeignItemType, ImplItem, ImplItemConst, ImplItemMacro, ImplItemMethod, ImplItemType, Item, - ItemConst, ItemEnum, ItemExternCrate, ItemFn, ItemForeignMod, ItemImpl, ItemMacro, ItemMacro2, - ItemMod, ItemStatic, ItemStruct, ItemTrait, ItemTraitAlias, ItemType, ItemUnion, ItemUse, Pat, - Receiver, Signature, Stmt, TraitItem, TraitItemConst, TraitItemMacro, TraitItemMethod, - TraitItemType, Type, UseGlob, UseGroup, UseName, UsePath, UseRename, UseTree, -}; - -impl Printer { - pub fn item(&mut self, item: &Item) { - match item { - Item::Const(item) => self.item_const(item), - Item::Enum(item) => self.item_enum(item), - Item::ExternCrate(item) => self.item_extern_crate(item), - Item::Fn(item) => self.item_fn(item), - Item::ForeignMod(item) => self.item_foreign_mod(item), - Item::Impl(item) => self.item_impl(item), - Item::Macro(item) => self.item_macro(item), - Item::Macro2(item) => self.item_macro2(item), - Item::Mod(item) => self.item_mod(item), - Item::Static(item) => self.item_static(item), - Item::Struct(item) => self.item_struct(item), - Item::Trait(item) => self.item_trait(item), - Item::TraitAlias(item) => self.item_trait_alias(item), - Item::Type(item) => self.item_type(item), - Item::Union(item) => self.item_union(item), - Item::Use(item) => self.item_use(item), - Item::Verbatim(item) => self.item_verbatim(item), - #[cfg_attr(all(test, exhaustive), deny(non_exhaustive_omitted_patterns))] - _ => unimplemented!("unknown Item"), - } - } - - fn item_const(&mut self, item: &ItemConst) { - self.outer_attrs(&item.attrs); - self.cbox(0); - self.visibility(&item.vis); - self.word("const "); - self.ident(&item.ident); - self.word(": "); - self.ty(&item.ty); - self.word(" = "); - self.neverbreak(); - self.expr(&item.expr); - self.word(";"); - self.end(); - self.hardbreak(); - } - - fn item_enum(&mut self, item: &ItemEnum) { - self.outer_attrs(&item.attrs); - self.cbox(INDENT); - self.visibility(&item.vis); - self.word("enum "); - self.ident(&item.ident); - self.generics(&item.generics); - self.where_clause_for_body(&item.generics.where_clause); - self.word("{"); - self.hardbreak_if_nonempty(); - for variant in &item.variants { - self.variant(variant); - self.word(","); - self.hardbreak(); - } - self.offset(-INDENT); - self.end(); - self.word("}"); - self.hardbreak(); - } - - fn item_extern_crate(&mut self, item: &ItemExternCrate) { - self.outer_attrs(&item.attrs); - self.visibility(&item.vis); - self.word("extern crate "); - self.ident(&item.ident); - if let Some((_as_token, rename)) = &item.rename { - self.word(" as "); - self.ident(rename); - } - self.word(";"); - self.hardbreak(); - } - - fn item_fn(&mut self, item: &ItemFn) { - self.outer_attrs(&item.attrs); - self.cbox(INDENT); - self.visibility(&item.vis); - self.signature(&item.sig); - self.where_clause_for_body(&item.sig.generics.where_clause); - self.word("{"); - self.hardbreak_if_nonempty(); - self.inner_attrs(&item.attrs); - for stmt in &item.block.stmts { - self.stmt(stmt); - } - self.offset(-INDENT); - self.end(); - self.word("}"); - self.hardbreak(); - } - - fn item_foreign_mod(&mut self, item: &ItemForeignMod) { - self.outer_attrs(&item.attrs); - self.cbox(INDENT); - self.abi(&item.abi); - self.word("{"); - self.hardbreak_if_nonempty(); - self.inner_attrs(&item.attrs); - for foreign_item in &item.items { - self.foreign_item(foreign_item); - } - self.offset(-INDENT); - self.end(); - self.word("}"); - self.hardbreak(); - } - - fn item_impl(&mut self, item: &ItemImpl) { - self.outer_attrs(&item.attrs); - self.cbox(INDENT); - self.ibox(-INDENT); - self.cbox(INDENT); - if item.defaultness.is_some() { - self.word("default "); - } - if item.unsafety.is_some() { - self.word("unsafe "); - } - self.word("impl"); - self.generics(&item.generics); - self.end(); - self.nbsp(); - if let Some((negative_polarity, path, _for_token)) = &item.trait_ { - if negative_polarity.is_some() { - self.word("!"); - } - self.path(path); - self.space(); - self.word("for "); - } - self.ty(&item.self_ty); - self.end(); - self.where_clause_for_body(&item.generics.where_clause); - self.word("{"); - self.hardbreak_if_nonempty(); - self.inner_attrs(&item.attrs); - for impl_item in &item.items { - self.impl_item(impl_item); - } - self.offset(-INDENT); - self.end(); - self.word("}"); - self.hardbreak(); - } - - fn item_macro(&mut self, item: &ItemMacro) { - self.outer_attrs(&item.attrs); - self.mac(&item.mac, item.ident.as_ref()); - self.mac_semi_if_needed(&item.mac.delimiter); - self.hardbreak(); - } - - fn item_macro2(&mut self, item: &ItemMacro2) { - unimplemented!("Item::Macro2 `macro {} {}`", item.ident, item.rules); - } - - fn item_mod(&mut self, item: &ItemMod) { - self.outer_attrs(&item.attrs); - self.cbox(INDENT); - self.visibility(&item.vis); - self.word("mod "); - self.ident(&item.ident); - if let Some((_brace, items)) = &item.content { - self.word(" {"); - self.hardbreak_if_nonempty(); - self.inner_attrs(&item.attrs); - for item in items { - self.item(item); - } - self.offset(-INDENT); - self.end(); - self.word("}"); - } else { - self.word(";"); - self.end(); - } - self.hardbreak(); - } - - fn item_static(&mut self, item: &ItemStatic) { - self.outer_attrs(&item.attrs); - self.cbox(0); - self.visibility(&item.vis); - self.word("static "); - if item.mutability.is_some() { - self.word("mut "); - } - self.ident(&item.ident); - self.word(": "); - self.ty(&item.ty); - self.word(" = "); - self.neverbreak(); - self.expr(&item.expr); - self.word(";"); - self.end(); - self.hardbreak(); - } - - fn item_struct(&mut self, item: &ItemStruct) { - self.outer_attrs(&item.attrs); - self.cbox(INDENT); - self.visibility(&item.vis); - self.word("struct "); - self.ident(&item.ident); - self.generics(&item.generics); - match &item.fields { - Fields::Named(fields) => { - self.where_clause_for_body(&item.generics.where_clause); - self.word("{"); - self.hardbreak_if_nonempty(); - for field in &fields.named { - self.field(field); - self.word(","); - self.hardbreak(); - } - self.offset(-INDENT); - self.end(); - self.word("}"); - } - Fields::Unnamed(fields) => { - self.fields_unnamed(fields); - self.where_clause_semi(&item.generics.where_clause); - self.end(); - } - Fields::Unit => { - self.where_clause_semi(&item.generics.where_clause); - self.end(); - } - } - self.hardbreak(); - } - - fn item_trait(&mut self, item: &ItemTrait) { - self.outer_attrs(&item.attrs); - self.cbox(INDENT); - self.visibility(&item.vis); - if item.unsafety.is_some() { - self.word("unsafe "); - } - if item.auto_token.is_some() { - self.word("auto "); - } - self.word("trait "); - self.ident(&item.ident); - self.generics(&item.generics); - for supertrait in item.supertraits.iter().delimited() { - if supertrait.is_first { - self.word(": "); - } else { - self.word(" + "); - } - self.type_param_bound(&supertrait); - } - self.where_clause_for_body(&item.generics.where_clause); - self.word("{"); - self.hardbreak_if_nonempty(); - self.inner_attrs(&item.attrs); - for trait_item in &item.items { - self.trait_item(trait_item); - } - self.offset(-INDENT); - self.end(); - self.word("}"); - self.hardbreak(); - } - - fn item_trait_alias(&mut self, item: &ItemTraitAlias) { - self.outer_attrs(&item.attrs); - self.cbox(INDENT); - self.visibility(&item.vis); - self.word("trait "); - self.ident(&item.ident); - self.generics(&item.generics); - self.word(" = "); - self.neverbreak(); - for bound in item.bounds.iter().delimited() { - if !bound.is_first { - self.space(); - self.word("+ "); - } - self.type_param_bound(&bound); - } - self.where_clause_semi(&item.generics.where_clause); - self.end(); - self.hardbreak(); - } - - fn item_type(&mut self, item: &ItemType) { - self.outer_attrs(&item.attrs); - self.cbox(INDENT); - self.visibility(&item.vis); - self.word("type "); - self.ident(&item.ident); - self.generics(&item.generics); - self.where_clause_oneline(&item.generics.where_clause); - self.word("= "); - self.neverbreak(); - self.ibox(-INDENT); - self.ty(&item.ty); - self.end(); - self.word(";"); - self.end(); - self.hardbreak(); - } - - fn item_union(&mut self, item: &ItemUnion) { - self.outer_attrs(&item.attrs); - self.cbox(INDENT); - self.visibility(&item.vis); - self.word("union "); - self.ident(&item.ident); - self.generics(&item.generics); - self.where_clause_for_body(&item.generics.where_clause); - self.word("{"); - self.hardbreak_if_nonempty(); - for field in &item.fields.named { - self.field(field); - self.word(","); - self.hardbreak(); - } - self.offset(-INDENT); - self.end(); - self.word("}"); - self.hardbreak(); - } - - fn item_use(&mut self, item: &ItemUse) { - self.outer_attrs(&item.attrs); - self.visibility(&item.vis); - self.word("use "); - if item.leading_colon.is_some() { - self.word("::"); - } - self.use_tree(&item.tree); - self.word(";"); - self.hardbreak(); - } - - #[cfg(feature = "verbatim")] - fn item_verbatim(&mut self, tokens: &TokenStream) { - use syn::parse::{Parse, ParseStream, Result}; - use syn::{Attribute, Token}; - - enum ItemVerbatim { - Empty, - UnsafeForeignMod(ItemForeignMod), - } - - impl Parse for ItemVerbatim { - fn parse(input: ParseStream) -> Result { - if input.is_empty() { - Ok(ItemVerbatim::Empty) - } else { - let attrs = input.call(Attribute::parse_outer)?; - input.parse::()?; - let module: ItemForeignMod = input.parse()?; - Ok(ItemVerbatim::UnsafeForeignMod(ItemForeignMod { - attrs, - ..module - })) - } - } - } - - let item: ItemVerbatim = match syn::parse2(tokens.clone()) { - Ok(item) => item, - Err(_) => return self.word(tokens.to_string()), - }; - - match item { - ItemVerbatim::Empty => {} - ItemVerbatim::UnsafeForeignMod(item) => { - self.outer_attrs(&item.attrs); - self.cbox(INDENT); - self.word("unsafe "); - self.abi(&item.abi); - self.word("{"); - self.hardbreak_if_nonempty(); - self.inner_attrs(&item.attrs); - for foreign_item in &item.items { - self.foreign_item(foreign_item); - } - self.offset(-INDENT); - self.end(); - self.word("}"); - } - } - - self.hardbreak(); - } - - fn use_tree(&mut self, use_tree: &UseTree) { - match use_tree { - UseTree::Path(use_path) => self.use_path(use_path), - UseTree::Name(use_name) => self.use_name(use_name), - UseTree::Rename(use_rename) => self.use_rename(use_rename), - UseTree::Glob(use_glob) => self.use_glob(use_glob), - UseTree::Group(use_group) => self.use_group(use_group), - } - } - - fn use_path(&mut self, use_path: &UsePath) { - self.ident(&use_path.ident); - self.word("::"); - self.use_tree(&use_path.tree); - } - - fn use_name(&mut self, use_name: &UseName) { - self.ident(&use_name.ident); - } - - fn use_rename(&mut self, use_rename: &UseRename) { - self.ident(&use_rename.ident); - self.word(" as "); - self.ident(&use_rename.rename); - } - - fn use_glob(&mut self, use_glob: &UseGlob) { - let _ = use_glob; - self.word("*"); - } - - fn use_group(&mut self, use_group: &UseGroup) { - if use_group.items.is_empty() { - self.word("{}"); - } else if use_group.items.len() == 1 { - self.use_tree(&use_group.items[0]); - } else { - self.cbox(INDENT); - self.word("{"); - self.zerobreak(); - self.ibox(0); - for use_tree in use_group.items.iter().delimited() { - self.use_tree(&use_tree); - if !use_tree.is_last { - self.word(","); - let mut use_tree = *use_tree; - while let UseTree::Path(use_path) = use_tree { - use_tree = &use_path.tree; - } - if let UseTree::Group(_) = use_tree { - self.hardbreak(); - } else { - self.space(); - } - } - } - self.end(); - self.trailing_comma(true); - self.offset(-INDENT); - self.word("}"); - self.end(); - } - } - - fn foreign_item(&mut self, foreign_item: &ForeignItem) { - match foreign_item { - ForeignItem::Fn(item) => self.foreign_item_fn(item), - ForeignItem::Static(item) => self.foreign_item_static(item), - ForeignItem::Type(item) => self.foreign_item_type(item), - ForeignItem::Macro(item) => self.foreign_item_macro(item), - ForeignItem::Verbatim(item) => self.foreign_item_verbatim(item), - #[cfg_attr(all(test, exhaustive), deny(non_exhaustive_omitted_patterns))] - _ => unimplemented!("unknown ForeignItem"), - } - } - - fn foreign_item_fn(&mut self, foreign_item: &ForeignItemFn) { - self.outer_attrs(&foreign_item.attrs); - self.cbox(INDENT); - self.visibility(&foreign_item.vis); - self.signature(&foreign_item.sig); - self.where_clause_semi(&foreign_item.sig.generics.where_clause); - self.end(); - self.hardbreak(); - } - - fn foreign_item_static(&mut self, foreign_item: &ForeignItemStatic) { - self.outer_attrs(&foreign_item.attrs); - self.cbox(0); - self.visibility(&foreign_item.vis); - self.word("static "); - if foreign_item.mutability.is_some() { - self.word("mut "); - } - self.ident(&foreign_item.ident); - self.word(": "); - self.ty(&foreign_item.ty); - self.word(";"); - self.end(); - self.hardbreak(); - } - - fn foreign_item_type(&mut self, foreign_item: &ForeignItemType) { - self.outer_attrs(&foreign_item.attrs); - self.cbox(0); - self.visibility(&foreign_item.vis); - self.word("type "); - self.ident(&foreign_item.ident); - self.word(";"); - self.end(); - self.hardbreak(); - } - - fn foreign_item_macro(&mut self, foreign_item: &ForeignItemMacro) { - self.outer_attrs(&foreign_item.attrs); - self.mac(&foreign_item.mac, None); - self.mac_semi_if_needed(&foreign_item.mac.delimiter); - self.hardbreak(); - } - - #[cfg(feature = "verbatim")] - fn foreign_item_verbatim(&mut self, tokens: &TokenStream) { - use syn::parse::{Parse, ParseStream, Result}; - - enum ForeignItemVerbatim { - TypeAlias(ItemType), - } - - impl Parse for ForeignItemVerbatim { - fn parse(input: ParseStream) -> Result { - input.parse().map(ForeignItemVerbatim::TypeAlias) - } - } - - let foreign_item: ForeignItemVerbatim = match syn::parse2(tokens.clone()) { - Ok(foreign_item) => foreign_item, - Err(_) => { - self.word(tokens.to_string()); - self.hardbreak(); - return; - } - }; - - match foreign_item { - ForeignItemVerbatim::TypeAlias(item) => self.item_type(&item), - } - } - - fn trait_item(&mut self, trait_item: &TraitItem) { - match trait_item { - TraitItem::Const(item) => self.trait_item_const(item), - TraitItem::Method(item) => self.trait_item_method(item), - TraitItem::Type(item) => self.trait_item_type(item), - TraitItem::Macro(item) => self.trait_item_macro(item), - TraitItem::Verbatim(item) => self.trait_item_verbatim(item), - #[cfg_attr(all(test, exhaustive), deny(non_exhaustive_omitted_patterns))] - _ => unimplemented!("unknown TraitItem"), - } - } - - fn trait_item_const(&mut self, trait_item: &TraitItemConst) { - self.outer_attrs(&trait_item.attrs); - self.cbox(0); - self.word("const "); - self.ident(&trait_item.ident); - self.word(": "); - self.ty(&trait_item.ty); - if let Some((_eq_token, default)) = &trait_item.default { - self.word(" = "); - self.neverbreak(); - self.expr(default); - } - self.word(";"); - self.end(); - self.hardbreak(); - } - - fn trait_item_method(&mut self, trait_item: &TraitItemMethod) { - self.outer_attrs(&trait_item.attrs); - self.cbox(INDENT); - self.signature(&trait_item.sig); - if let Some(block) = &trait_item.default { - self.where_clause_for_body(&trait_item.sig.generics.where_clause); - self.word("{"); - self.hardbreak_if_nonempty(); - self.inner_attrs(&trait_item.attrs); - for stmt in &block.stmts { - self.stmt(stmt); - } - self.offset(-INDENT); - self.end(); - self.word("}"); - } else { - self.where_clause_semi(&trait_item.sig.generics.where_clause); - self.end(); - } - self.hardbreak(); - } - - fn trait_item_type(&mut self, trait_item: &TraitItemType) { - self.outer_attrs(&trait_item.attrs); - self.cbox(INDENT); - self.word("type "); - self.ident(&trait_item.ident); - self.generics(&trait_item.generics); - for bound in trait_item.bounds.iter().delimited() { - if bound.is_first { - self.word(": "); - } else { - self.space(); - self.word("+ "); - } - self.type_param_bound(&bound); - } - if let Some((_eq_token, default)) = &trait_item.default { - self.where_clause_oneline(&trait_item.generics.where_clause); - self.word("= "); - self.neverbreak(); - self.ty(default); - } else { - self.where_clause_oneline_semi(&trait_item.generics.where_clause); - } - self.end(); - self.hardbreak(); - } - - fn trait_item_macro(&mut self, trait_item: &TraitItemMacro) { - self.outer_attrs(&trait_item.attrs); - self.mac(&trait_item.mac, None); - self.mac_semi_if_needed(&trait_item.mac.delimiter); - self.hardbreak(); - } - - fn trait_item_verbatim(&mut self, trait_item: &TokenStream) { - self.word(trait_item.to_string()); - self.hardbreak(); - } - - fn impl_item(&mut self, impl_item: &ImplItem) { - match impl_item { - ImplItem::Const(item) => self.impl_item_const(item), - ImplItem::Method(item) => self.impl_item_method(item), - ImplItem::Type(item) => self.impl_item_type(item), - ImplItem::Macro(item) => self.impl_item_macro(item), - ImplItem::Verbatim(item) => self.impl_item_verbatim(item), - #[cfg_attr(all(test, exhaustive), deny(non_exhaustive_omitted_patterns))] - _ => unimplemented!("unknown ImplItem"), - } - } - - fn impl_item_const(&mut self, impl_item: &ImplItemConst) { - self.outer_attrs(&impl_item.attrs); - self.cbox(0); - self.visibility(&impl_item.vis); - if impl_item.defaultness.is_some() { - self.word("default "); - } - self.word("const "); - self.ident(&impl_item.ident); - self.word(": "); - self.ty(&impl_item.ty); - self.word(" = "); - self.neverbreak(); - self.expr(&impl_item.expr); - self.word(";"); - self.end(); - self.hardbreak(); - } - - fn impl_item_method(&mut self, impl_item: &ImplItemMethod) { - self.outer_attrs(&impl_item.attrs); - self.cbox(INDENT); - self.visibility(&impl_item.vis); - if impl_item.defaultness.is_some() { - self.word("default "); - } - self.signature(&impl_item.sig); - if impl_item.block.stmts.len() == 1 { - if let Stmt::Item(Item::Verbatim(verbatim)) = &impl_item.block.stmts[0] { - if verbatim.to_string() == ";" { - self.where_clause_semi(&impl_item.sig.generics.where_clause); - self.end(); - self.hardbreak(); - return; - } - } - } - self.where_clause_for_body(&impl_item.sig.generics.where_clause); - self.word("{"); - self.hardbreak_if_nonempty(); - self.inner_attrs(&impl_item.attrs); - for stmt in &impl_item.block.stmts { - self.stmt(stmt); - } - self.offset(-INDENT); - self.end(); - self.word("}"); - self.hardbreak(); - } - - fn impl_item_type(&mut self, impl_item: &ImplItemType) { - self.outer_attrs(&impl_item.attrs); - self.cbox(INDENT); - self.visibility(&impl_item.vis); - if impl_item.defaultness.is_some() { - self.word("default "); - } - self.word("type "); - self.ident(&impl_item.ident); - self.generics(&impl_item.generics); - self.where_clause_oneline(&impl_item.generics.where_clause); - self.word("= "); - self.neverbreak(); - self.ibox(-INDENT); - self.ty(&impl_item.ty); - self.end(); - self.word(";"); - self.end(); - self.hardbreak(); - } - - fn impl_item_macro(&mut self, impl_item: &ImplItemMacro) { - self.outer_attrs(&impl_item.attrs); - self.mac(&impl_item.mac, None); - self.mac_semi_if_needed(&impl_item.mac.delimiter); - self.hardbreak(); - } - - fn impl_item_verbatim(&mut self, impl_item: &TokenStream) { - self.word(impl_item.to_string()); - self.hardbreak(); - } - - fn maybe_variadic(&mut self, arg: &FnArg) -> bool { - let pat_type = match arg { - FnArg::Typed(pat_type) => pat_type, - FnArg::Receiver(receiver) => { - self.receiver(receiver); - return false; - } - }; - - match pat_type.ty.as_ref() { - Type::Verbatim(ty) if ty.to_string() == "..." => { - match pat_type.pat.as_ref() { - Pat::Verbatim(pat) if pat.to_string() == "..." => { - self.outer_attrs(&pat_type.attrs); - self.word("..."); - } - _ => self.pat_type(pat_type), - } - true - } - _ => { - self.pat_type(pat_type); - false - } - } - } - - fn signature(&mut self, signature: &Signature) { - if signature.constness.is_some() { - self.word("const "); - } - if signature.asyncness.is_some() { - self.word("async "); - } - if signature.unsafety.is_some() { - self.word("unsafe "); - } - if let Some(abi) = &signature.abi { - self.abi(abi); - } - self.word("fn "); - self.ident(&signature.ident); - self.generics(&signature.generics); - self.word("("); - self.neverbreak(); - self.cbox(0); - self.zerobreak(); - let mut last_is_variadic = false; - for input in signature.inputs.iter().delimited() { - last_is_variadic = self.maybe_variadic(&input); - if last_is_variadic { - self.zerobreak(); - } else { - self.trailing_comma(input.is_last); - } - } - if signature.variadic.is_some() && !last_is_variadic { - self.word("..."); - self.zerobreak(); - } - self.offset(-INDENT); - self.end(); - self.word(")"); - self.cbox(-INDENT); - self.return_type(&signature.output); - self.end(); - } - - fn receiver(&mut self, receiver: &Receiver) { - self.outer_attrs(&receiver.attrs); - if let Some((_ampersand, lifetime)) = &receiver.reference { - self.word("&"); - if let Some(lifetime) = lifetime { - self.lifetime(lifetime); - self.nbsp(); - } - } - if receiver.mutability.is_some() { - self.word("mut "); - } - self.word("self"); - } -} diff --git a/prettyplease-forked/src/iter.rs b/prettyplease-forked/src/iter.rs deleted file mode 100644 index 702c653..0000000 --- a/prettyplease-forked/src/iter.rs +++ /dev/null @@ -1,46 +0,0 @@ -use std::iter::Peekable; -use std::ops::Deref; - -pub struct Delimited { - is_first: bool, - iter: Peekable, -} - -pub trait IterDelimited: Iterator + Sized { - fn delimited(self) -> Delimited { - Delimited { - is_first: true, - iter: self.peekable(), - } - } -} - -impl IterDelimited for I {} - -pub struct IteratorItem { - value: T, - pub is_first: bool, - pub is_last: bool, -} - -impl Iterator for Delimited { - type Item = IteratorItem; - - fn next(&mut self) -> Option { - let item = IteratorItem { - value: self.iter.next()?, - is_first: self.is_first, - is_last: self.iter.peek().is_none(), - }; - self.is_first = false; - Some(item) - } -} - -impl Deref for IteratorItem { - type Target = T; - - fn deref(&self) -> &Self::Target { - &self.value - } -} diff --git a/prettyplease-forked/src/lib.rs b/prettyplease-forked/src/lib.rs deleted file mode 100644 index 7dd479f..0000000 --- a/prettyplease-forked/src/lib.rs +++ /dev/null @@ -1,377 +0,0 @@ -//! [![github]](https://github.com/dtolnay/prettyplease) [![crates-io]](https://crates.io/crates/prettyplease) [![docs-rs]](https://docs.rs/prettyplease) -//! -//! [github]: https://img.shields.io/badge/github-8da0cb?style=for-the-badge&labelColor=555555&logo=github -//! [crates-io]: https://img.shields.io/badge/crates.io-fc8d62?style=for-the-badge&labelColor=555555&logo=rust -//! [docs-rs]: https://img.shields.io/badge/docs.rs-66c2a5?style=for-the-badge&labelColor=555555&logo=docs.rs -//! -//!
-//! -//! **prettyplease::unparse** — a minimal `syn` syntax tree pretty-printer -//! -//!
-//! -//! # Overview -//! -//! This is a pretty-printer to turn a `syn` syntax tree into a `String` of -//! well-formatted source code. In contrast to rustfmt, this library is intended -//! to be suitable for arbitrary generated code. -//! -//! Rustfmt prioritizes high-quality output that is impeccable enough that you'd -//! be comfortable spending your career staring at its output — but that -//! means some heavyweight algorithms, and it has a tendency to bail out on code -//! that is hard to format (for example [rustfmt#3697], and there are dozens -//! more issues like it). That's not necessarily a big deal for human-generated -//! code because when code gets highly nested, the human will naturally be -//! inclined to refactor into more easily formattable code. But for generated -//! code, having the formatter just give up leaves it totally unreadable. -//! -//! [rustfmt#3697]: https://github.com/rust-lang/rustfmt/issues/3697 -//! -//! This library is designed using the simplest possible algorithm and data -//! structures that can deliver about 95% of the quality of rustfmt-formatted -//! output. In my experience testing real-world code, approximately 97-98% of -//! output lines come out identical between rustfmt's formatting and this -//! crate's. The rest have slightly different linebreak decisions, but still -//! clearly follow the dominant modern Rust style. -//! -//! The tradeoffs made by this crate are a good fit for generated code that you -//! will *not* spend your career staring at. For example, the output of -//! `bindgen`, or the output of `cargo-expand`. In those cases it's more -//! important that the whole thing be formattable without the formatter giving -//! up, than that it be flawless. -//! -//!
-//! -//! # Feature matrix -//! -//! Here are a few superficial comparisons of this crate against the AST -//! pretty-printer built into rustc, and rustfmt. The sections below go into -//! more detail comparing the output of each of these libraries. -//! -//! | | prettyplease | rustc | rustfmt | -//! |:---|:---:|:---:|:---:| -//! | non-pathological behavior on big or generated code | 💚 | ❌ | ❌ | -//! | idiomatic modern formatting ("locally indistinguishable from rustfmt") | 💚 | ❌ | 💚 | -//! | throughput | 60 MB/s | 39 MB/s | 2.8 MB/s | -//! | number of dependencies | 3 | 72 | 66 | -//! | compile time including dependencies | 2.4 sec | 23.1 sec | 29.8 sec | -//! | buildable using a stable Rust compiler | 💚 | ❌ | ❌ | -//! | published to crates.io | 💚 | ❌ | ❌ | -//! | extensively configurable output | ❌ | ❌ | 💚 | -//! | intended to accommodate hand-maintained source code | ❌ | ❌ | 💚 | -//! -//!
-//! -//! # Comparison to rustfmt -//! -//! - [input.rs](https://github.com/dtolnay/prettyplease/blob/0.1.0/examples/input.rs) -//! - [output.prettyplease.rs](https://github.com/dtolnay/prettyplease/blob/0.1.0/examples/output.prettyplease.rs) -//! - [output.rustfmt.rs](https://github.com/dtolnay/prettyplease/blob/0.1.0/examples/output.rustfmt.rs) -//! -//! If you weren't told which output file is which, it would be practically -//! impossible to tell — **except** for line 435 in the rustfmt output, -//! which is more than 1000 characters long because rustfmt just gave up -//! formatting that part of the file: -//! -//! ``` -//! # const _: &str = stringify! {{{ -//! match segments[5] { -//! 0 => write!(f, "::{}", ipv4), -//! 0xffff => write!(f, "::ffff:{}", ipv4), -//! _ => unreachable!(), -//! } -//! } else { # [derive (Copy , Clone , Default)] struct Span { start : usize , len : usize , } let zeroes = { let mut longest = Span :: default () ; let mut current = Span :: default () ; for (i , & segment) in segments . iter () . enumerate () { if segment == 0 { if current . len == 0 { current . start = i ; } current . len += 1 ; if current . len > longest . len { longest = current ; } } else { current = Span :: default () ; } } longest } ; # [doc = " Write a colon-separated part of the address"] # [inline] fn fmt_subslice (f : & mut fmt :: Formatter < '_ > , chunk : & [u16]) -> fmt :: Result { if let Some ((first , tail)) = chunk . split_first () { write ! (f , "{:x}" , first) ? ; for segment in tail { f . write_char (':') ? ; write ! (f , "{:x}" , segment) ? ; } } Ok (()) } if zeroes . len > 1 { fmt_subslice (f , & segments [.. zeroes . start]) ? ; f . write_str ("::") ? ; fmt_subslice (f , & segments [zeroes . start + zeroes . len ..]) } else { fmt_subslice (f , & segments) } } -//! } else { -//! const IPV6_BUF_LEN: usize = (4 * 8) + 7; -//! let mut buf = [0u8; IPV6_BUF_LEN]; -//! let mut buf_slice = &mut buf[..]; -//! # }}; -//! ``` -//! -//! This is a pretty typical manifestation of rustfmt bailing out in generated -//! code — a chunk of the input ends up on one line. The other -//! manifestation is that you're working on some code, running rustfmt on save -//! like a conscientious developer, but after a while notice it isn't doing -//! anything. You introduce an intentional formatting issue, like a stray indent -//! or semicolon, and run rustfmt to check your suspicion. Nope, it doesn't get -//! cleaned up — rustfmt is just not formatting the part of the file you -//! are working on. -//! -//! The prettyplease library is designed to have no pathological cases that -//! force a bail out; the entire input you give it will get formatted in some -//! "good enough" form. -//! -//! Separately, rustfmt can be problematic to integrate into projects. It's -//! written using rustc's internal syntax tree, so it can't be built by a stable -//! compiler. Its releases are not regularly published to crates.io, so in Cargo -//! builds you'd need to depend on it as a git dependency, which precludes -//! publishing your crate to crates.io also. You can shell out to a `rustfmt` -//! binary, but that'll be whatever rustfmt version is installed on each -//! developer's system (if any), which can lead to spurious diffs in checked-in -//! generated code formatted by different versions. In contrast prettyplease is -//! designed to be easy to pull in as a library, and compiles fast. -//! -//!
-//! -//! # Comparison to rustc_ast_pretty -//! -//! - [input.rs](https://github.com/dtolnay/prettyplease/blob/0.1.0/examples/input.rs) -//! - [output.prettyplease.rs](https://github.com/dtolnay/prettyplease/blob/0.1.0/examples/output.prettyplease.rs) -//! - [output.rustc.rs](https://github.com/dtolnay/prettyplease/blob/0.1.0/examples/output.rustc.rs) -//! -//! This is the pretty-printer that gets used when rustc prints source code, -//! such as `rustc -Zunpretty=expanded`. It's used also by the standard -//! library's `stringify!` when stringifying an interpolated macro_rules AST -//! fragment, like an $:expr, and transitively by `dbg!` and many macros in the -//! ecosystem. -//! -//! Rustc's formatting is mostly okay, but does not hew closely to the dominant -//! contemporary style of Rust formatting. Some things wouldn't ever be written -//! on one line, like this `match` expression, and certainly not with a comma in -//! front of the closing brace: -//! -//! ``` -//! # const _: &str = stringify! { -//! fn eq(&self, other: &IpAddr) -> bool { -//! match other { IpAddr::V4(v4) => self == v4, IpAddr::V6(_) => false, } -//! } -//! # }; -//! ``` -//! -//! Some places use non-multiple-of-4 indentation, which is definitely not the -//! norm: -//! -//! ``` -//! # const _: &str = stringify! { -//! pub const fn to_ipv6_mapped(&self) -> Ipv6Addr { -//! let [a, b, c, d] = self.octets(); -//! Ipv6Addr{inner: -//! c::in6_addr{s6_addr: -//! [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xFF, -//! 0xFF, a, b, c, d],},} -//! } -//! # }; -//! ``` -//! -//! And although there isn't an egregious example of it in the link because the -//! input code is pretty tame, in general rustc_ast_pretty has pathological -//! behavior on generated code. It has a tendency to use excessive horizontal -//! indentation and rapidly run out of width: -//! -//! ``` -//! # const _: &str = stringify! { -//! ::std::io::_print(::core::fmt::Arguments::new_v1(&[""], -//! &match (&msg,) { -//! _args => -//! [::core::fmt::ArgumentV1::new(_args.0, -//! ::core::fmt::Display::fmt)], -//! })); -//! # }; -//! ``` -//! -//! The snippets above are clearly different from modern rustfmt style. In -//! contrast, prettyplease is designed to have output that is practically -//! indistinguishable from rustfmt-formatted code. -//! -//!
-//! -//! # Example -//! -//! ``` -//! // [dependencies] -//! // prettyplease = "0.1" -//! // syn = { version = "1", default-features = false, features = ["full", "parsing"] } -//! -//! const INPUT: &str = stringify! { -//! use crate::{ -//! lazy::{Lazy, SyncLazy, SyncOnceCell}, panic, -//! sync::{ atomic::{AtomicUsize, Ordering::SeqCst}, -//! mpsc::channel, Mutex, }, -//! thread, -//! }; -//! impl Into for T where U: From { -//! fn into(self) -> U { U::from(self) } -//! } -//! }; -//! -//! fn main() { -//! let syntax_tree = syn::parse_file(INPUT).unwrap(); -//! let formatted = prettyplease::unparse(&syntax_tree); -//! print!("{}", formatted); -//! } -//! ``` -//! -//!
-//! -//! # Algorithm notes -//! -//! The approach and terminology used in the implementation are derived from -//! [*Derek C. Oppen, "Pretty Printing" (1979)*][paper], on which -//! rustc_ast_pretty is also based, and from rustc_ast_pretty's implementation -//! written by Graydon Hoare in 2011 (and modernized over the years by dozens of -//! volunteer maintainers). -//! -//! [paper]: http://i.stanford.edu/pub/cstr/reports/cs/tr/79/770/CS-TR-79-770.pdf -//! -//! The paper describes two language-agnostic interacting procedures `Scan()` -//! and `Print()`. Language-specific code decomposes an input data structure -//! into a stream of `string` and `break` tokens, and `begin` and `end` tokens -//! for grouping. Each `begin`–`end` range may be identified as either -//! "consistent breaking" or "inconsistent breaking". If a group is consistently -//! breaking, then if the whole contents do not fit on the line, *every* `break` -//! token in the group will receive a linebreak. This is appropriate, for -//! example, for Rust struct literals, or arguments of a function call. If a -//! group is inconsistently breaking, then the `string` tokens in the group are -//! greedily placed on the line until out of space, and linebroken only at those -//! `break` tokens for which the next string would not fit. For example, this is -//! appropriate for the contents of a braced `use` statement in Rust. -//! -//! Scan's job is to efficiently accumulate sizing information about groups and -//! breaks. For every `begin` token we compute the distance to the matched `end` -//! token, and for every `break` we compute the distance to the next `break`. -//! The algorithm uses a ringbuffer to hold tokens whose size is not yet -//! ascertained. The maximum size of the ringbuffer is bounded by the target -//! line length and does not grow indefinitely, regardless of deep nesting in -//! the input stream. That's because once a group is sufficiently big, the -//! precise size can no longer make a difference to linebreak decisions and we -//! can effectively treat it as "infinity". -//! -//! Print's job is to use the sizing information to efficiently assign a -//! "broken" or "not broken" status to every `begin` token. At that point the -//! output is easily constructed by concatenating `string` tokens and breaking -//! at `break` tokens contained within a broken group. -//! -//! Leveraging these primitives (i.e. cleverly placing the all-or-nothing -//! consistent breaks and greedy inconsistent breaks) to yield -//! rustfmt-compatible formatting for all of Rust's syntax tree nodes is a fun -//! challenge. -//! -//! Here is a visualization of some Rust tokens fed into the pretty printing -//! algorithm. Consistently breaking `begin`—`end` pairs are represented -//! by `«`⁠`»`, inconsistently breaking by `‹`⁠`›`, `break` by `·`, -//! and the rest of the non-whitespace are `string`. -//! -//! ```text -//! use crate::«{· -//! ‹ lazy::«{·‹Lazy,· SyncLazy,· SyncOnceCell›·}»,· -//! panic,· -//! sync::«{· -//! ‹ atomic::«{·‹AtomicUsize,· Ordering::SeqCst›·}»,· -//! mpsc::channel,· Mutex›,· -//! }»,· -//! thread›,· -//! }»;· -//! «‹«impl<«·T‹›,· U‹›·»>» Into<«·U·»>· for T›· -//! where· -//! U:‹ From<«·T·»>›,· -//! {· -//! « fn into(·«·self·») -> U {· -//! ‹ U::from(«·self·»)›· -//! » }· -//! »}· -//! ``` -//! -//! The algorithm described in the paper is not quite sufficient for producing -//! well-formatted Rust code that is locally indistinguishable from rustfmt's -//! style. The reason is that in the paper, the complete non-whitespace contents -//! are assumed to be independent of linebreak decisions, with Scan and Print -//! being only in control of the whitespace (spaces and line breaks). In Rust as -//! idiomatically formattted by rustfmt, that is not the case. Trailing commas -//! are one example; the punctuation is only known *after* the broken vs -//! non-broken status of the surrounding group is known: -//! -//! ``` -//! # struct Struct { x: u64, y: bool } -//! # let xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx = 0; -//! # let yyyyyyyyyyyyyyyyyyyyyyyyyyyyyy = true; -//! # -//! let _ = Struct { x: 0, y: true }; -//! -//! let _ = Struct { -//! x: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx, -//! y: yyyyyyyyyyyyyyyyyyyyyyyyyyyyyy, //<- trailing comma if the expression wrapped -//! }; -//! ``` -//! -//! The formatting of `match` expressions is another case; we want small arms on -//! the same line as the pattern, and big arms wrapped in a brace. The presence -//! of the brace punctuation, comma, and semicolon are all dependent on whether -//! the arm fits on the line: -//! -//! ``` -//! # struct Entry { nanos: u32 } -//! # let total_nanos = 0u64; -//! # let mut total_secs = 0u64; -//! # let tmp; -//! # let entry = Entry { nanos: 0 }; -//! # const NANOS_PER_SEC: u32 = 1_000_000_000; -//! # -//! match total_nanos.checked_add(entry.nanos as u64) { -//! Some(n) => tmp = n, //<- small arm, inline with comma -//! None => { -//! total_secs = total_secs -//! .checked_add(total_nanos / NANOS_PER_SEC as u64) -//! .expect("overflow in iter::sum over durations"); -//! } //<- big arm, needs brace added, and also semicolon^ -//! } -//! ``` -//! -//! The printing algorithm implementation in this crate accommodates all of -//! these situations with conditional punctuation tokens whose selection can be -//! deferred and populated after it's known that the group is or is not broken. - -#![allow( - clippy::cast_possible_wrap, - clippy::cast_sign_loss, - clippy::derive_partial_eq_without_eq, - clippy::doc_markdown, - clippy::enum_glob_use, - clippy::items_after_statements, - clippy::match_like_matches_macro, - clippy::match_same_arms, - clippy::module_name_repetitions, - clippy::must_use_candidate, - clippy::needless_pass_by_value, - clippy::similar_names, - clippy::too_many_lines, - clippy::unused_self, - clippy::vec_init_then_push -)] -#![cfg_attr(all(test, exhaustive), feature(non_exhaustive_omitted_patterns_lint))] - -mod algorithm; -mod attr; -mod convenience; -mod data; -mod expr; -mod file; -mod generics; -mod item; -mod iter; -mod lifetime; -mod lit; -mod mac; -mod pat; -mod path; -mod ring; -mod stmt; -mod token; -mod ty; - -use crate::algorithm::Printer; -use syn::File; - -// Target line width. -const MARGIN: isize = 89; - -// Number of spaces increment at each level of block indentation. -const INDENT: isize = 4; - -// Every line is allowed at least this much space, even if highly indented. -const MIN_SPACE: isize = 60; - -pub fn unparse(file: &File) -> String { - let mut p = Printer::new(); - p.file(file); - p.eof() -} diff --git a/prettyplease-forked/src/lifetime.rs b/prettyplease-forked/src/lifetime.rs deleted file mode 100644 index 665caa3..0000000 --- a/prettyplease-forked/src/lifetime.rs +++ /dev/null @@ -1,9 +0,0 @@ -use crate::algorithm::Printer; -use syn::Lifetime; - -impl Printer { - pub fn lifetime(&mut self, lifetime: &Lifetime) { - self.word("'"); - self.ident(&lifetime.ident); - } -} diff --git a/prettyplease-forked/src/lit.rs b/prettyplease-forked/src/lit.rs deleted file mode 100644 index c64b8a1..0000000 --- a/prettyplease-forked/src/lit.rs +++ /dev/null @@ -1,50 +0,0 @@ -use crate::algorithm::Printer; -use proc_macro2::Literal; -use syn::{Lit, LitBool, LitByte, LitByteStr, LitChar, LitFloat, LitInt, LitStr}; - -impl Printer { - pub fn lit(&mut self, lit: &Lit) { - match lit { - Lit::Str(lit) => self.lit_str(lit), - Lit::ByteStr(lit) => self.lit_byte_str(lit), - Lit::Byte(lit) => self.lit_byte(lit), - Lit::Char(lit) => self.lit_char(lit), - Lit::Int(lit) => self.lit_int(lit), - Lit::Float(lit) => self.lit_float(lit), - Lit::Bool(lit) => self.lit_bool(lit), - Lit::Verbatim(lit) => self.lit_verbatim(lit), - } - } - - pub fn lit_str(&mut self, lit: &LitStr) { - self.word(lit.token().to_string()); - } - - fn lit_byte_str(&mut self, lit: &LitByteStr) { - self.word(lit.token().to_string()); - } - - fn lit_byte(&mut self, lit: &LitByte) { - self.word(lit.token().to_string()); - } - - fn lit_char(&mut self, lit: &LitChar) { - self.word(lit.token().to_string()); - } - - fn lit_int(&mut self, lit: &LitInt) { - self.word(lit.token().to_string()); - } - - fn lit_float(&mut self, lit: &LitFloat) { - self.word(lit.token().to_string()); - } - - fn lit_bool(&mut self, lit: &LitBool) { - self.word(if lit.value { "true" } else { "false" }); - } - - fn lit_verbatim(&mut self, token: &Literal) { - self.word(token.to_string()); - } -} diff --git a/prettyplease-forked/src/mac.rs b/prettyplease-forked/src/mac.rs deleted file mode 100644 index 9c4c119..0000000 --- a/prettyplease-forked/src/mac.rs +++ /dev/null @@ -1,220 +0,0 @@ -use crate::algorithm::Printer; -use crate::token::Token; -use crate::INDENT; -use proc_macro2::{Delimiter, Spacing, TokenStream}; -use syn::{Ident, Macro, MacroDelimiter, PathArguments}; - -impl Printer { - pub fn mac(&mut self, mac: &Macro, ident: Option<&Ident>) { - let is_macro_rules = mac.path.leading_colon.is_none() - && mac.path.segments.len() == 1 - && matches!(mac.path.segments[0].arguments, PathArguments::None) - && mac.path.segments[0].ident == "macro_rules"; - if is_macro_rules { - if let Some(ident) = ident { - self.macro_rules(ident, &mac.tokens); - return; - } - } - self.path(&mac.path); - self.word("!"); - if let Some(ident) = ident { - self.nbsp(); - self.ident(ident); - } - let (open, close, delimiter_break) = match mac.delimiter { - MacroDelimiter::Paren(_) => ("(", ")", Self::zerobreak as fn(&mut Self)), - MacroDelimiter::Brace(_) => (" {", "}", Self::hardbreak as fn(&mut Self)), - MacroDelimiter::Bracket(_) => ("[", "]", Self::zerobreak as fn(&mut Self)), - }; - self.word(open); - self.cbox(INDENT); - delimiter_break(self); - self.ibox(0); - self.macro_rules_tokens(mac.tokens.clone(), false); - self.end(); - delimiter_break(self); - self.offset(-INDENT); - self.end(); - self.word(close); - } - - pub fn mac_semi_if_needed(&mut self, delimiter: &MacroDelimiter) { - match delimiter { - MacroDelimiter::Paren(_) | MacroDelimiter::Bracket(_) => self.word(";"), - MacroDelimiter::Brace(_) => {} - } - } - - fn macro_rules(&mut self, name: &Ident, rules: &TokenStream) { - enum State { - Start, - Matcher, - Equal, - Greater, - Expander, - } - - use State::*; - - self.word("macro_rules! "); - self.ident(name); - self.word(" {"); - self.cbox(INDENT); - self.hardbreak_if_nonempty(); - let mut state = State::Start; - for tt in rules.clone() { - let token = Token::from(tt); - match (state, token) { - (Start, Token::Group(delimiter, stream)) => { - self.delimiter_open(delimiter); - if !stream.is_empty() { - self.cbox(INDENT); - self.zerobreak(); - self.ibox(0); - self.macro_rules_tokens(stream, true); - self.end(); - self.zerobreak(); - self.offset(-INDENT); - self.end(); - } - self.delimiter_close(delimiter); - state = Matcher; - } - (Matcher, Token::Punct('=', Spacing::Joint)) => { - self.word(" ="); - state = Equal; - } - (Equal, Token::Punct('>', Spacing::Alone)) => { - self.word(">"); - state = Greater; - } - (Greater, Token::Group(_delimiter, stream)) => { - self.word(" {"); - self.neverbreak(); - if !stream.is_empty() { - self.cbox(INDENT); - self.hardbreak(); - self.ibox(0); - self.macro_rules_tokens(stream, false); - self.end(); - self.hardbreak(); - self.offset(-INDENT); - self.end(); - } - self.word("}"); - state = Expander; - } - (Expander, Token::Punct(';', Spacing::Alone)) => { - self.word(";"); - self.hardbreak(); - state = Start; - } - _ => unimplemented!("bad macro_rules syntax"), - } - } - match state { - Start => {} - Expander => { - self.word(";"); - self.hardbreak(); - } - _ => self.hardbreak(), - } - self.offset(-INDENT); - self.end(); - self.word("}"); - } - - fn macro_rules_tokens(&mut self, stream: TokenStream, matcher: bool) { - #[derive(PartialEq)] - enum State { - Start, - Dollar, - DollarIdent, - DollarIdentColon, - DollarParen, - DollarParenSep, - Pound, - PoundBang, - Dot, - Colon, - Colon2, - Ident, - IdentBang, - Delim, - Other, - } - - use State::*; - - let mut state = Start; - let mut previous_is_joint = true; - for tt in stream { - let token = Token::from(tt); - let (needs_space, next_state) = match (&state, &token) { - (Dollar, Token::Ident(_)) => (false, if matcher { DollarIdent } else { Other }), - (DollarIdent, Token::Punct(':', Spacing::Alone)) => (false, DollarIdentColon), - (DollarIdentColon, Token::Ident(_)) => (false, Other), - (DollarParen, Token::Punct('+' | '*' | '?', Spacing::Alone)) => (false, Other), - (DollarParen, Token::Ident(_) | Token::Literal(_)) => (false, DollarParenSep), - (DollarParen, Token::Punct(_, Spacing::Joint)) => (false, DollarParen), - (DollarParen, Token::Punct(_, Spacing::Alone)) => (false, DollarParenSep), - (DollarParenSep, Token::Punct('+' | '*', _)) => (false, Other), - (Pound, Token::Punct('!', _)) => (false, PoundBang), - (Dollar, Token::Group(Delimiter::Parenthesis, _)) => (false, DollarParen), - (Pound | PoundBang, Token::Group(Delimiter::Bracket, _)) => (false, Other), - (Ident, Token::Group(Delimiter::Parenthesis | Delimiter::Bracket, _)) => { - (false, Delim) - } - (Ident, Token::Punct('!', Spacing::Alone)) => (false, IdentBang), - (IdentBang, Token::Group(Delimiter::Parenthesis | Delimiter::Bracket, _)) => { - (false, Other) - } - (Colon, Token::Punct(':', _)) => (false, Colon2), - (_, Token::Group(Delimiter::Parenthesis | Delimiter::Bracket, _)) => (true, Delim), - (_, Token::Group(Delimiter::Brace | Delimiter::None, _)) => (true, Other), - (_, Token::Ident(ident)) if !is_keyword(ident) => { - (state != Dot && state != Colon2, Ident) - } - (_, Token::Literal(_)) => (state != Dot, Ident), - (_, Token::Punct(',' | ';', _)) => (false, Other), - (_, Token::Punct('.', _)) if !matcher => (state != Ident && state != Delim, Dot), - (_, Token::Punct(':', Spacing::Joint)) => (state != Ident, Colon), - (_, Token::Punct('$', _)) => (true, Dollar), - (_, Token::Punct('#', _)) => (true, Pound), - (_, _) => (true, Other), - }; - if !previous_is_joint { - if needs_space { - self.space(); - } else if let Token::Punct('.', _) = token { - self.zerobreak(); - } - } - previous_is_joint = match token { - Token::Punct(_, Spacing::Joint) | Token::Punct('$', _) => true, - _ => false, - }; - self.single_token( - token, - if matcher { - |printer, stream| printer.macro_rules_tokens(stream, true) - } else { - |printer, stream| printer.macro_rules_tokens(stream, false) - }, - ); - state = next_state; - } - } -} - -fn is_keyword(ident: &Ident) -> bool { - match ident.to_string().as_str() { - "as" | "box" | "break" | "const" | "continue" | "crate" | "else" | "enum" | "extern" - | "fn" | "for" | "if" | "impl" | "in" | "let" | "loop" | "macro" | "match" | "mod" - | "move" | "mut" | "pub" | "ref" | "return" | "static" | "struct" | "trait" | "type" - | "unsafe" | "use" | "where" | "while" | "yield" => true, - _ => false, - } -} diff --git a/prettyplease-forked/src/pat.rs b/prettyplease-forked/src/pat.rs deleted file mode 100644 index d5c6fe4..0000000 --- a/prettyplease-forked/src/pat.rs +++ /dev/null @@ -1,210 +0,0 @@ -use crate::algorithm::Printer; -use crate::iter::IterDelimited; -use crate::INDENT; -use proc_macro2::TokenStream; -use syn::{ - FieldPat, Pat, PatBox, PatIdent, PatLit, PatMacro, PatOr, PatPath, PatRange, PatReference, - PatRest, PatSlice, PatStruct, PatTuple, PatTupleStruct, PatType, PatWild, RangeLimits, -}; - -impl Printer { - pub fn pat(&mut self, pat: &Pat) { - match pat { - Pat::Box(pat) => self.pat_box(pat), - Pat::Ident(pat) => self.pat_ident(pat), - Pat::Lit(pat) => self.pat_lit(pat), - Pat::Macro(pat) => self.pat_macro(pat), - Pat::Or(pat) => self.pat_or(pat), - Pat::Path(pat) => self.pat_path(pat), - Pat::Range(pat) => self.pat_range(pat), - Pat::Reference(pat) => self.pat_reference(pat), - Pat::Rest(pat) => self.pat_rest(pat), - Pat::Slice(pat) => self.pat_slice(pat), - Pat::Struct(pat) => self.pat_struct(pat), - Pat::Tuple(pat) => self.pat_tuple(pat), - Pat::TupleStruct(pat) => self.pat_tuple_struct(pat), - Pat::Type(pat) => self.pat_type(pat), - Pat::Verbatim(pat) => self.pat_verbatim(pat), - Pat::Wild(pat) => self.pat_wild(pat), - #[cfg_attr(all(test, exhaustive), deny(non_exhaustive_omitted_patterns))] - _ => unimplemented!("unknown Pat"), - } - } - - fn pat_box(&mut self, pat: &PatBox) { - self.outer_attrs(&pat.attrs); - self.word("box "); - self.pat(&pat.pat); - } - - fn pat_ident(&mut self, pat: &PatIdent) { - self.outer_attrs(&pat.attrs); - if pat.by_ref.is_some() { - self.word("ref "); - } - if pat.mutability.is_some() { - self.word("mut "); - } - self.ident(&pat.ident); - if let Some((_at_token, subpat)) = &pat.subpat { - self.word(" @ "); - self.pat(subpat); - } - } - - fn pat_lit(&mut self, pat: &PatLit) { - self.outer_attrs(&pat.attrs); - self.expr(&pat.expr); - } - - fn pat_macro(&mut self, pat: &PatMacro) { - self.outer_attrs(&pat.attrs); - self.mac(&pat.mac, None); - } - - fn pat_or(&mut self, pat: &PatOr) { - self.outer_attrs(&pat.attrs); - let mut consistent_break = false; - for case in &pat.cases { - match case { - Pat::Lit(_) | Pat::Wild(_) => {} - _ => { - consistent_break = true; - break; - } - } - } - if consistent_break { - self.cbox(0); - } else { - self.ibox(0); - } - for case in pat.cases.iter().delimited() { - if !case.is_first { - self.space(); - self.word("| "); - } - self.pat(&case); - } - self.end(); - } - - fn pat_path(&mut self, pat: &PatPath) { - self.outer_attrs(&pat.attrs); - self.qpath(&pat.qself, &pat.path); - } - - fn pat_range(&mut self, pat: &PatRange) { - self.outer_attrs(&pat.attrs); - self.expr(&pat.lo); - match &pat.limits { - RangeLimits::HalfOpen(_) => self.word(".."), - RangeLimits::Closed(_) => self.word("..="), - } - self.expr(&pat.hi); - } - - fn pat_reference(&mut self, pat: &PatReference) { - self.outer_attrs(&pat.attrs); - self.word("&"); - if pat.mutability.is_some() { - self.word("mut "); - } - self.pat(&pat.pat); - } - - fn pat_rest(&mut self, pat: &PatRest) { - self.outer_attrs(&pat.attrs); - self.word(".."); - } - - fn pat_slice(&mut self, pat: &PatSlice) { - self.outer_attrs(&pat.attrs); - self.word("["); - for elem in pat.elems.iter().delimited() { - self.pat(&elem); - self.trailing_comma(elem.is_last); - } - self.word("]"); - } - - fn pat_struct(&mut self, pat: &PatStruct) { - self.outer_attrs(&pat.attrs); - self.cbox(INDENT); - self.path(&pat.path); - self.word(" {"); - self.space_if_nonempty(); - for field in pat.fields.iter().delimited() { - self.field_pat(&field); - self.trailing_comma_or_space(field.is_last && pat.dot2_token.is_none()); - } - if pat.dot2_token.is_some() { - self.word(".."); - self.space(); - } - self.offset(-INDENT); - self.end(); - self.word("}"); - } - - fn pat_tuple(&mut self, pat: &PatTuple) { - self.outer_attrs(&pat.attrs); - self.word("("); - self.cbox(INDENT); - self.zerobreak(); - for elem in pat.elems.iter().delimited() { - self.pat(&elem); - if pat.elems.len() == 1 { - if pat.elems.trailing_punct() { - self.word(","); - } - self.zerobreak(); - } else { - self.trailing_comma(elem.is_last); - } - } - self.offset(-INDENT); - self.end(); - self.word(")"); - } - - fn pat_tuple_struct(&mut self, pat: &PatTupleStruct) { - self.outer_attrs(&pat.attrs); - self.path(&pat.path); - self.word("("); - self.cbox(INDENT); - self.zerobreak(); - for elem in pat.pat.elems.iter().delimited() { - self.pat(&elem); - self.trailing_comma(elem.is_last); - } - self.offset(-INDENT); - self.end(); - self.word(")"); - } - - pub fn pat_type(&mut self, pat: &PatType) { - self.outer_attrs(&pat.attrs); - self.pat(&pat.pat); - self.word(": "); - self.ty(&pat.ty); - } - - fn pat_verbatim(&mut self, pat: &TokenStream) { - self.word(pat.to_string()); - } - - fn pat_wild(&mut self, pat: &PatWild) { - self.outer_attrs(&pat.attrs); - self.word("_"); - } - - fn field_pat(&mut self, field_pat: &FieldPat) { - self.outer_attrs(&field_pat.attrs); - if field_pat.colon_token.is_some() { - self.member(&field_pat.member); - self.word(": "); - } - self.pat(&field_pat.pat); - } -} diff --git a/prettyplease-forked/src/path.rs b/prettyplease-forked/src/path.rs deleted file mode 100644 index 16ca927..0000000 --- a/prettyplease-forked/src/path.rs +++ /dev/null @@ -1,185 +0,0 @@ -use crate::algorithm::Printer; -use crate::iter::IterDelimited; -use crate::INDENT; -use syn::{ - AngleBracketedGenericArguments, Binding, Constraint, Expr, GenericArgument, - ParenthesizedGenericArguments, Path, PathArguments, PathSegment, QSelf, -}; - -impl Printer { - pub fn path(&mut self, path: &Path) { - assert!(!path.segments.is_empty()); - for segment in path.segments.iter().delimited() { - if !segment.is_first || path.leading_colon.is_some() { - self.word("::"); - } - self.path_segment(&segment); - } - } - - pub fn path_segment(&mut self, segment: &PathSegment) { - self.ident(&segment.ident); - self.path_arguments(&segment.arguments); - } - - fn path_arguments(&mut self, arguments: &PathArguments) { - match arguments { - PathArguments::None => {} - PathArguments::AngleBracketed(arguments) => { - self.angle_bracketed_generic_arguments(arguments); - } - PathArguments::Parenthesized(arguments) => { - self.parenthesized_generic_arguments(arguments); - } - } - } - - fn generic_argument(&mut self, arg: &GenericArgument) { - match arg { - GenericArgument::Lifetime(lifetime) => self.lifetime(lifetime), - GenericArgument::Type(ty) => self.ty(ty), - GenericArgument::Binding(binding) => self.binding(binding), - GenericArgument::Constraint(constraint) => self.constraint(constraint), - GenericArgument::Const(expr) => { - match expr { - Expr::Lit(expr) => self.expr_lit(expr), - Expr::Block(expr) => self.expr_block(expr), - // ERROR CORRECTION: Add braces to make sure that the - // generated code is valid. - _ => { - self.word("{"); - self.expr(expr); - self.word("}"); - } - } - } - } - } - - fn angle_bracketed_generic_arguments(&mut self, generic: &AngleBracketedGenericArguments) { - if generic.args.is_empty() { - return; - } - - if generic.colon2_token.is_some() { - self.word("::"); - } - self.word("<"); - self.cbox(INDENT); - self.zerobreak(); - - // Print lifetimes before types and consts, all before bindings, - // regardless of their order in self.args. - // - // TODO: ordering rules for const arguments vs type arguments have - // not been settled yet. https://github.com/rust-lang/rust/issues/44580 - for arg in generic.args.iter().delimited() { - match *arg { - GenericArgument::Lifetime(_) => { - self.generic_argument(&arg); - self.trailing_comma(arg.is_last); - } - GenericArgument::Type(_) - | GenericArgument::Binding(_) - | GenericArgument::Constraint(_) - | GenericArgument::Const(_) => {} - } - } - for arg in generic.args.iter().delimited() { - match *arg { - GenericArgument::Type(_) | GenericArgument::Const(_) => { - self.generic_argument(&arg); - self.trailing_comma(arg.is_last); - } - GenericArgument::Lifetime(_) - | GenericArgument::Binding(_) - | GenericArgument::Constraint(_) => {} - } - } - for arg in generic.args.iter().delimited() { - match *arg { - GenericArgument::Binding(_) | GenericArgument::Constraint(_) => { - self.generic_argument(&arg); - self.trailing_comma(arg.is_last); - } - GenericArgument::Lifetime(_) - | GenericArgument::Type(_) - | GenericArgument::Const(_) => {} - } - } - - self.offset(-INDENT); - self.end(); - self.word(">"); - } - - fn binding(&mut self, binding: &Binding) { - self.ident(&binding.ident); - self.word(" = "); - self.ty(&binding.ty); - } - - fn constraint(&mut self, constraint: &Constraint) { - self.ident(&constraint.ident); - self.ibox(INDENT); - for bound in constraint.bounds.iter().delimited() { - if bound.is_first { - self.word(": "); - } else { - self.space(); - self.word("+ "); - } - self.type_param_bound(&bound); - } - self.end(); - } - - fn parenthesized_generic_arguments(&mut self, arguments: &ParenthesizedGenericArguments) { - self.cbox(INDENT); - self.word("("); - self.zerobreak(); - for ty in arguments.inputs.iter().delimited() { - self.ty(&ty); - self.trailing_comma(ty.is_last); - } - self.offset(-INDENT); - self.word(")"); - self.return_type(&arguments.output); - self.end(); - } - - pub fn qpath(&mut self, qself: &Option, path: &Path) { - let qself = match qself { - Some(qself) => qself, - None => { - self.path(path); - return; - } - }; - - assert!(qself.position < path.segments.len()); - - self.word("<"); - self.ty(&qself.ty); - - let mut segments = path.segments.iter(); - if qself.position > 0 { - self.word(" as "); - for segment in segments.by_ref().take(qself.position).delimited() { - if !segment.is_first || path.leading_colon.is_some() { - self.word("::"); - } - self.path_segment(&segment); - if segment.is_last { - self.word(">"); - } - } - } else { - self.word(">"); - } - for segment in segments { - self.word("::"); - self.path_segment(segment); - } - } -} diff --git a/prettyplease-forked/src/ring.rs b/prettyplease-forked/src/ring.rs deleted file mode 100644 index aff9258..0000000 --- a/prettyplease-forked/src/ring.rs +++ /dev/null @@ -1,81 +0,0 @@ -use std::collections::VecDeque; -use std::ops::{Index, IndexMut}; - -pub struct RingBuffer { - data: VecDeque, - // Abstract index of data[0] in infinitely sized queue - offset: usize, -} - -impl RingBuffer { - pub fn new() -> Self { - RingBuffer { - data: VecDeque::new(), - offset: 0, - } - } - - pub fn is_empty(&self) -> bool { - self.data.is_empty() - } - - pub fn len(&self) -> usize { - self.data.len() - } - - pub fn push(&mut self, value: T) -> usize { - let index = self.offset + self.data.len(); - self.data.push_back(value); - index - } - - pub fn clear(&mut self) { - self.data.clear(); - } - - pub fn index_of_first(&self) -> usize { - self.offset - } - - pub fn first(&self) -> &T { - &self.data[0] - } - - pub fn first_mut(&mut self) -> &mut T { - &mut self.data[0] - } - - pub fn pop_first(&mut self) -> T { - self.offset += 1; - self.data.pop_front().unwrap() - } - - pub fn last(&self) -> &T { - self.data.back().unwrap() - } - - pub fn last_mut(&mut self) -> &mut T { - self.data.back_mut().unwrap() - } - - pub fn second_last(&self) -> &T { - &self.data[self.data.len() - 2] - } - - pub fn pop_last(&mut self) { - self.data.pop_back().unwrap(); - } -} - -impl Index for RingBuffer { - type Output = T; - fn index(&self, index: usize) -> &Self::Output { - &self.data[index.checked_sub(self.offset).unwrap()] - } -} - -impl IndexMut for RingBuffer { - fn index_mut(&mut self, index: usize) -> &mut Self::Output { - &mut self.data[index.checked_sub(self.offset).unwrap()] - } -} diff --git a/prettyplease-forked/src/stmt.rs b/prettyplease-forked/src/stmt.rs deleted file mode 100644 index a127b57..0000000 --- a/prettyplease-forked/src/stmt.rs +++ /dev/null @@ -1,85 +0,0 @@ -use crate::algorithm::Printer; -use syn::{Expr, Stmt}; - -impl Printer { - pub fn stmt(&mut self, stmt: &Stmt) { - match stmt { - Stmt::Local(local) => { - self.outer_attrs(&local.attrs); - self.ibox(0); - self.word("let "); - self.pat(&local.pat); - if let Some((_eq, init)) = &local.init { - self.word(" = "); - self.neverbreak(); - self.expr(init); - } - self.word(";"); - self.end(); - self.hardbreak(); - } - Stmt::Item(item) => self.item(item), - Stmt::Expr(expr) => { - if break_after(expr) { - self.ibox(0); - self.expr_beginning_of_line(expr, true); - if add_semi(expr) { - self.word(";"); - } - self.end(); - self.hardbreak(); - } else { - self.expr_beginning_of_line(expr, true); - } - } - Stmt::Semi(expr, _semi) => { - if let Expr::Verbatim(tokens) = expr { - if tokens.is_empty() { - return; - } - } - self.ibox(0); - self.expr_beginning_of_line(expr, true); - if !remove_semi(expr) { - self.word(";"); - } - self.end(); - self.hardbreak(); - } - } - } -} - -pub fn add_semi(expr: &Expr) -> bool { - match expr { - Expr::Assign(_) - | Expr::AssignOp(_) - | Expr::Break(_) - | Expr::Continue(_) - | Expr::Return(_) - | Expr::Yield(_) => true, - Expr::Group(group) => add_semi(&group.expr), - _ => false, - } -} - -pub fn break_after(expr: &Expr) -> bool { - if let Expr::Group(group) = expr { - if let Expr::Verbatim(verbatim) = group.expr.as_ref() { - return !verbatim.is_empty(); - } - } - true -} - -fn remove_semi(expr: &Expr) -> bool { - match expr { - Expr::ForLoop(_) | Expr::While(_) => true, - Expr::Group(group) => remove_semi(&group.expr), - Expr::If(expr) => match &expr.else_branch { - Some((_else_token, else_branch)) => remove_semi(else_branch), - None => true, - }, - _ => false, - } -} diff --git a/prettyplease-forked/src/token.rs b/prettyplease-forked/src/token.rs deleted file mode 100644 index e41fd72..0000000 --- a/prettyplease-forked/src/token.rs +++ /dev/null @@ -1,80 +0,0 @@ -use crate::algorithm::Printer; -use proc_macro2::{Delimiter, Ident, Literal, Spacing, TokenStream, TokenTree}; - -impl Printer { - pub fn single_token(&mut self, token: Token, group_contents: fn(&mut Self, TokenStream)) { - match token { - Token::Group(delimiter, stream) => self.token_group(delimiter, stream, group_contents), - Token::Ident(ident) => self.ident(&ident), - Token::Punct(ch, _spacing) => self.token_punct(ch), - Token::Literal(literal) => self.token_literal(&literal), - } - } - - fn token_group( - &mut self, - delimiter: Delimiter, - stream: TokenStream, - group_contents: fn(&mut Self, TokenStream), - ) { - self.delimiter_open(delimiter); - if !stream.is_empty() { - if delimiter == Delimiter::Brace { - self.space(); - } - group_contents(self, stream); - if delimiter == Delimiter::Brace { - self.space(); - } - } - self.delimiter_close(delimiter); - } - - pub fn ident(&mut self, ident: &Ident) { - self.word(ident.to_string()); - } - - pub fn token_punct(&mut self, ch: char) { - self.word(ch.to_string()); - } - - pub fn token_literal(&mut self, literal: &Literal) { - self.word(literal.to_string()); - } - - pub fn delimiter_open(&mut self, delimiter: Delimiter) { - self.word(match delimiter { - Delimiter::Parenthesis => "(", - Delimiter::Brace => "{", - Delimiter::Bracket => "[", - Delimiter::None => return, - }); - } - - pub fn delimiter_close(&mut self, delimiter: Delimiter) { - self.word(match delimiter { - Delimiter::Parenthesis => ")", - Delimiter::Brace => "}", - Delimiter::Bracket => "]", - Delimiter::None => return, - }); - } -} - -pub enum Token { - Group(Delimiter, TokenStream), - Ident(Ident), - Punct(char, Spacing), - Literal(Literal), -} - -impl From for Token { - fn from(tt: TokenTree) -> Self { - match tt { - TokenTree::Group(group) => Token::Group(group.delimiter(), group.stream()), - TokenTree::Ident(ident) => Token::Ident(ident), - TokenTree::Punct(punct) => Token::Punct(punct.as_char(), punct.spacing()), - TokenTree::Literal(literal) => Token::Literal(literal), - } - } -} diff --git a/prettyplease-forked/src/ty.rs b/prettyplease-forked/src/ty.rs deleted file mode 100644 index 0c1fb47..0000000 --- a/prettyplease-forked/src/ty.rs +++ /dev/null @@ -1,232 +0,0 @@ -use crate::algorithm::Printer; -use crate::iter::IterDelimited; -use crate::INDENT; -use proc_macro2::TokenStream; -use syn::{ - Abi, BareFnArg, ReturnType, Type, TypeArray, TypeBareFn, TypeGroup, TypeImplTrait, TypeInfer, - TypeMacro, TypeNever, TypeParen, TypePath, TypePtr, TypeReference, TypeSlice, TypeTraitObject, - TypeTuple, Variadic, -}; - -impl Printer { - pub fn ty(&mut self, ty: &Type) { - match ty { - Type::Array(ty) => self.type_array(ty), - Type::BareFn(ty) => self.type_bare_fn(ty), - Type::Group(ty) => self.type_group(ty), - Type::ImplTrait(ty) => self.type_impl_trait(ty), - Type::Infer(ty) => self.type_infer(ty), - Type::Macro(ty) => self.type_macro(ty), - Type::Never(ty) => self.type_never(ty), - Type::Paren(ty) => self.type_paren(ty), - Type::Path(ty) => self.type_path(ty), - Type::Ptr(ty) => self.type_ptr(ty), - Type::Reference(ty) => self.type_reference(ty), - Type::Slice(ty) => self.type_slice(ty), - Type::TraitObject(ty) => self.type_trait_object(ty), - Type::Tuple(ty) => self.type_tuple(ty), - Type::Verbatim(ty) => self.type_verbatim(ty), - #[cfg_attr(all(test, exhaustive), deny(non_exhaustive_omitted_patterns))] - _ => unimplemented!("unknown Type"), - } - } - - fn type_array(&mut self, ty: &TypeArray) { - self.word("["); - self.ty(&ty.elem); - self.word("; "); - self.expr(&ty.len); - self.word("]"); - } - - fn type_bare_fn(&mut self, ty: &TypeBareFn) { - if let Some(bound_lifetimes) = &ty.lifetimes { - self.bound_lifetimes(bound_lifetimes); - } - if ty.unsafety.is_some() { - self.word("unsafe "); - } - if let Some(abi) = &ty.abi { - self.abi(abi); - } - self.word("fn("); - self.cbox(INDENT); - self.zerobreak(); - for bare_fn_arg in ty.inputs.iter().delimited() { - self.bare_fn_arg(&bare_fn_arg); - self.trailing_comma(bare_fn_arg.is_last && ty.variadic.is_none()); - } - if let Some(variadic) = &ty.variadic { - self.variadic(variadic); - self.zerobreak(); - } - self.offset(-INDENT); - self.end(); - self.word(")"); - self.return_type(&ty.output); - } - - fn type_group(&mut self, ty: &TypeGroup) { - self.ty(&ty.elem); - } - - fn type_impl_trait(&mut self, ty: &TypeImplTrait) { - self.word("impl "); - for type_param_bound in ty.bounds.iter().delimited() { - if !type_param_bound.is_first { - self.word(" + "); - } - self.type_param_bound(&type_param_bound); - } - } - - fn type_infer(&mut self, ty: &TypeInfer) { - let _ = ty; - self.word("_"); - } - - fn type_macro(&mut self, ty: &TypeMacro) { - self.mac(&ty.mac, None); - } - - fn type_never(&mut self, ty: &TypeNever) { - let _ = ty; - self.word("!"); - } - - fn type_paren(&mut self, ty: &TypeParen) { - self.word("("); - self.ty(&ty.elem); - self.word(")"); - } - - fn type_path(&mut self, ty: &TypePath) { - self.qpath(&ty.qself, &ty.path); - } - - fn type_ptr(&mut self, ty: &TypePtr) { - self.word("*"); - if ty.mutability.is_some() { - self.word("mut "); - } else { - self.word("const "); - } - self.ty(&ty.elem); - } - - fn type_reference(&mut self, ty: &TypeReference) { - self.word("&"); - if let Some(lifetime) = &ty.lifetime { - self.lifetime(lifetime); - self.nbsp(); - } - if ty.mutability.is_some() { - self.word("mut "); - } - self.ty(&ty.elem); - } - - fn type_slice(&mut self, ty: &TypeSlice) { - self.word("["); - self.ty(&ty.elem); - self.word("]"); - } - - fn type_trait_object(&mut self, ty: &TypeTraitObject) { - self.word("dyn "); - for type_param_bound in ty.bounds.iter().delimited() { - if !type_param_bound.is_first { - self.word(" + "); - } - self.type_param_bound(&type_param_bound); - } - } - - fn type_tuple(&mut self, ty: &TypeTuple) { - self.word("("); - self.cbox(INDENT); - self.zerobreak(); - for elem in ty.elems.iter().delimited() { - self.ty(&elem); - if ty.elems.len() == 1 { - self.word(","); - self.zerobreak(); - } else { - self.trailing_comma(elem.is_last); - } - } - self.offset(-INDENT); - self.end(); - self.word(")"); - } - - #[cfg(feature = "verbatim")] - fn type_verbatim(&mut self, tokens: &TokenStream) { - use syn::parse::{Parse, ParseStream, Result}; - use syn::{token, ExprBlock, Lit}; - - enum TypeVerbatim { - Lit(Lit), - Block(ExprBlock), - } - - impl Parse for TypeVerbatim { - fn parse(input: ParseStream) -> Result { - let lookahead = input.lookahead1(); - if lookahead.peek(Lit) { - input.parse().map(TypeVerbatim::Lit) - } else if lookahead.peek(token::Brace) { - input.parse().map(TypeVerbatim::Block) - } else { - Err(lookahead.error()) - } - } - } - - let ty: TypeVerbatim = match syn::parse2(tokens.clone()) { - Ok(ty) => ty, - Err(_) => return self.word(tokens.to_string()), - }; - - match ty { - TypeVerbatim::Lit(lit) => { - self.lit(&lit); - } - TypeVerbatim::Block(block) => { - self.expr_block(&block); - } - } - } - - pub fn return_type(&mut self, ty: &ReturnType) { - match ty { - ReturnType::Default => {} - ReturnType::Type(_arrow, ty) => { - self.word(" -> "); - self.ty(ty); - } - } - } - - fn bare_fn_arg(&mut self, bare_fn_arg: &BareFnArg) { - self.outer_attrs(&bare_fn_arg.attrs); - if let Some((name, _colon)) = &bare_fn_arg.name { - self.ident(name); - self.word(": "); - } - self.ty(&bare_fn_arg.ty); - } - - fn variadic(&mut self, variadic: &Variadic) { - self.outer_attrs(&variadic.attrs); - self.word("..."); - } - - pub fn abi(&mut self, abi: &Abi) { - self.word("extern "); - if let Some(name) = &abi.name { - self.lit_str(name); - self.nbsp(); - } - } -} diff --git a/src/dylib_flag.rs b/src/dylib_flag.rs index 97870d5..18d9f15 100644 --- a/src/dylib_flag.rs +++ b/src/dylib_flag.rs @@ -79,7 +79,7 @@ fn wrap_func_body(func: &str) -> Result { } }; - Ok(prettyplease::unparse(&syn_file)) + crate::formatting::format(syn_file) } impl RustFunction { diff --git a/src/formatting.rs b/src/formatting.rs new file mode 100644 index 0000000..5cc313a --- /dev/null +++ b/src/formatting.rs @@ -0,0 +1,7 @@ +use std::collections::HashMap; + +use genemichaels::FormatConfig; + +pub fn format(file: syn::File) -> anyhow::Result { + Ok(genemichaels::format_ast(file, &FormatConfig::default(), HashMap::new())?.rendered) +} diff --git a/src/lib.rs b/src/lib.rs index 1bd29fa..515cbc6 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -9,6 +9,7 @@ use std::{ mod build; mod dylib_flag; +mod formatting; mod passes; mod processor; diff --git a/src/processor/mod.rs b/src/processor/mod.rs index 9036ffd..28776c6 100644 --- a/src/processor/mod.rs +++ b/src/processor/mod.rs @@ -196,7 +196,7 @@ impl Minimizer { match has_made_change { ProcessState::Changed | ProcessState::FileInvalidated => { - let result = prettyplease::unparse(&krate); + let result = crate::formatting::format(krate)?; change.write(&result)?;