├── .dir-locals.el ├── Aux └── swiftformat-project-settings.el ├── LICENSE ├── README.md ├── bin └── build ├── libsyntax.swift ├── swift-format.xcodeproj ├── project.pbxproj ├── project.xcworkspace │ └── contents.xcworkspacedata └── xcuserdata │ └── dave.xcuserdatad │ └── xcschemes │ └── xcschememanagement.plist └── swift-format └── main.swift /.dir-locals.el: -------------------------------------------------------------------------------- 1 | ;;; Directory Local Variables 2 | ;;; For more information see (info "(emacs) Directory Variables") 3 | 4 | ((nil 5 | (eval let* 6 | ((x (dir-locals-find-file default-directory)) 7 | (this-directory (if (listp x) (car x) (file-name-directory x)))) 8 | (unless (or (featurep 'swiftformat-project-settings) 9 | (and (fboundp 'tramp-tramp-file-p) 10 | (tramp-tramp-file-p this-directory))) 11 | (add-to-list 'load-path 12 | (concat this-directory "Aux") 13 | :append) 14 | (let ((swiftformat-project-directory this-directory)) 15 | (require 'swiftformat-project-settings))) 16 | (set (make-local-variable 'swiftformat-project-directory) 17 | this-directory) 18 | (make-local-variable 'before-save-hook) 19 | (add-hook 'before-save-hook 'delete-trailing-whitespace) 20 | ) 21 | (tab-width . 4) 22 | (fill-column . 80)) 23 | (c++-mode 24 | (whitespace-style face lines indentation:space)) 25 | (c-mode 26 | (whitespace-style face lines indentation:space)) 27 | (objc-mode 28 | (whitespace-style face lines indentation:space)) 29 | (prog-mode 30 | (eval add-hook 'prog-mode-hook 31 | (lambda nil 32 | (whitespace-mode 1)) 33 | (not :APPEND) 34 | :BUFFER-LOCAL)) 35 | (swift-mode 36 | (whitespace-style face lines indentation:space) 37 | (swift-basic-offset . 4) 38 | (tab-always-indent . t))) 39 | 40 | 41 | 42 | ;; Local Variables: 43 | ;; eval: (whitespace-mode -1) 44 | ;; End: 45 | -------------------------------------------------------------------------------- /Aux/swiftformat-project-settings.el: -------------------------------------------------------------------------------- 1 | ; 2 | ; swiftformat-project-settings.el 3 | ; Swiftformat 4 | ; 5 | ; Created by Dave Abrahams on 20/09/17 6 | ; Copyright © 2017 Apple Inc. All rights reserved. 7 | ; 8 | 9 | ;; Associate .swift files with swift-mode 10 | (setq auto-mode-alist 11 | (append '(("\\.swift$" . swift-mode) ("\\.gyb$" python-mode t)) auto-mode-alist)) 12 | 13 | ;; Try to ensure that swift-mode is in the load-path 14 | (add-to-list 'load-path (expand-file-name (concat (file-name-directory load-file-name) "/../../../s/swift/utils"))) 15 | (autoload 'swift-mode "swift-mode" 16 | "Major mode for editing SWIFT source files. 17 | \\{swift-mode-map} 18 | Runs swift-mode-hook on startup." 19 | :interactive 20 | ) 21 | 22 | (require 'cc-styles) 23 | 24 | ;; When this file is loaded in response to visiting a file in the project, it 25 | ;; won't have had its major mode set up according to the project settings yet. 26 | ;; For example, Swift files may come up in Fundamental mode unless we do 27 | ;; something. This hack causes the file to be re-mode-ed. 28 | (set-auto-mode) 29 | 30 | (defun swiftformat-project-comment-end () 31 | "If comment-end is non-empty returns it, stripped of leading whitespace. Returns nil otherwise" 32 | (replace-regexp-in-string 33 | "\\` +" "" 34 | (if (and comment-end (> (length comment-end) 0)) comment-end v1))) 35 | 36 | (define-skeleton swiftformat-header 37 | "Insert the Swiftformat header at the top of a file 38 | 39 | Note: this skeleton presently assumes that comment-start creates 40 | a comment until end-of-line. Handling paired comment syntax is 41 | possible, but more work, and someone needs to decide what such an 42 | Swiftformat header should look like. 43 | " 44 | ;; prompt 45 | nil 46 | 47 | ;; v1 is comment-start without trailing whitespace. Presumably 48 | ;; nobody is crazy enough to define a language where whitespace 49 | ;; determines whether something is a comment, but c++ mode and 50 | ;; friends have a space at the end of comment-start, which messes up 51 | ;; the Swiftformat header format. 52 | ;; 53 | ;; When there's no comment syntax defined, we use "#"; precedent is 54 | ;; in the project's README file. 55 | '(setq v1 (replace-regexp-in-string " +\\'" "" (or comment-start "#"))) 56 | 57 | ;; v2 is the name of the file 58 | '(setq v2 (file-name-nondirectory (buffer-file-name))) 59 | 60 | '(setq v3 user-full-name) 61 | 62 | '(setq v4 (format-time-string "%d/%m/%y")) 63 | 64 | '(setq v5 (format-time-string "%Y")) 65 | 66 | v1 "\n" 67 | v1 " " v2 "\n" 68 | v1 " Swiftformat\n" 69 | v1 "\n" 70 | v1 " Created by " v3 " on " v4 "\n" 71 | v1 " Copyright © " v5 " Apple Inc. All rights reserved.\n" 72 | v1 "\n" 73 | ) 74 | 75 | (defvar swiftformat-project-auto-insert-alist 76 | ;; Currently we match any file and insert the Swiftformat header. We can 77 | ;; make the regexp more specific or filter based on mode if this 78 | ;; doesn't work out. 79 | '((("" . "Swiftformat header") . swiftformat-header)) 80 | "auto-insert-alist entries that are just for the Swiftformat project" 81 | ) 82 | 83 | (defadvice auto-insert (around swiftformat-project-auto-insert activate) 84 | "Modify auto-insert so that swiftformat-project-auto-insert-alist 85 | takes precedence for files in the Swiftformat project" 86 | ;; Assume that files with c-file-style set to "swiftformat" are 87 | ;; part of the Swiftformat project. Because it's set in 88 | ;; .dir-locals.el, this will apply to all files, not just 89 | ;; those using cc-mode 90 | (if (and (boundp 'c-file-style) (equal c-file-style "swiftformat")) 91 | (let ((auto-insert-alist 92 | (append swiftformat-project-auto-insert-alist auto-insert-alist)) 93 | ;; The default is to ask when creating a new file. Inside 94 | ;; this project, we always want the Swiftformat header, so only 95 | ;; prompt if the user has set auto-insert to /always/ 96 | ;; prompt. 97 | (auto-insert-query (if (eq auto-insert-query 'function) nil auto-insert-query))) 98 | ad-do-it) 99 | ad-do-it)) 100 | 101 | (provide 'swiftformat-project-settings) 102 | ;; end of swiftformat-project-settings.el 103 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "[]" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright [yyyy] [name of copyright owner] 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Front-End for Formatting Swift Code (WIP) 2 | 3 | Uses [libSyntax](https://github.com/apple/swift/tree/master/lib/Syntax) to 4 | generate a token stream encoding a tree that can be consumed by a 5 | [PrettyPrint](../../../PrettyPrint)er. 6 | -------------------------------------------------------------------------------- /bin/build: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash -e -o pipefail 2 | DEFAULT_SWIFT_FORMAT="$HOME/src/swift-format" # What to build when invoked outside a git tree. 3 | top=$(git rev-parse --show-toplevel 2>/dev/null || echo "$DEFAULT_SWIFT_FORMAT") 4 | if [[ ! -e "${top}"/swift-format.xcodeproj ]] ; then top="$DEFAULT_SWIFT_FORMAT"; fi 5 | 6 | export TOOLCHAINS=org.swift.3020180130a 7 | xcrun swiftc -Onone -enforce-exclusivity=checked -DDEBUG -sdk $('xcrun' '--show-sdk-path' '--sdk' 'macosx') -g -swift-version 4 -j8 "$top"/swift-format/main.swift -o "$top"/tool 8 | "$top"/tool 9 | 10 | # -Xcc -I/Users/dave/Library/Developer/Xcode/DerivedData/swift-format-grgdlzwqhbdmeqeakuqrjtaxblaa/Build/Intermediates.noindex/swift-format.build/Debug/swift-format.build/swift-overrides.hmap -Xcc -iquote -Xcc /Users/dave/Library/Developer/Xcode/DerivedData/swift-format-grgdlzwqhbdmeqeakuqrjtaxblaa/Build/Intermediates.noindex/swift-format.build/Debug/swift-format.build/swift-format-generated-files.hmap -Xcc -I/Users/dave/Library/Developer/Xcode/DerivedData/swift-format-grgdlzwqhbdmeqeakuqrjtaxblaa/Build/Intermediates.noindex/swift-format.build/Debug/swift-format.build/swift-format-own-target-headers.hmap -Xcc -I/Users/dave/Library/Developer/Xcode/DerivedData/swift-format-grgdlzwqhbdmeqeakuqrjtaxblaa/Build/Intermediates.noindex/swift-format.build/Debug/swift-format.build/swift-format-all-target-headers.hmap -Xcc -iquote -Xcc /Users/dave/Library/Developer/Xcode/DerivedData/swift-format-grgdlzwqhbdmeqeakuqrjtaxblaa/Build/Intermediates.noindex/swift-format.build/Debug/swift-format.build/swift-format-project-headers.hmap -Xcc -I/Users/dave/Library/Developer/Xcode/DerivedData/swift-format-grgdlzwqhbdmeqeakuqrjtaxblaa/Build/Products/Debug/include -Xcc -I/Users/dave/Library/Developer/Xcode/DerivedData/swift-format-grgdlzwqhbdmeqeakuqrjtaxblaa/Build/Intermediates.noindex/swift-format.build/Debug/swift-format.build/DerivedSources/x86_64 -Xcc -I/Users/dave/Library/Developer/Xcode/DerivedData/swift-format-grgdlzwqhbdmeqeakuqrjtaxblaa/Build/Intermediates.noindex/swift-format.build/Debug/swift-format.build/DerivedSources -Xcc -DDEBUG=1 -emit-objc-header -emit-objc-header-path /Users/dave/Library/Developer/Xcode/DerivedData/swift-format-grgdlzwqhbdmeqeakuqrjtaxblaa/Build/Intermediates.noindex/swift-format.build/Debug/swift-format.build/Objects-normal/x86_64/swift_format-Swift.h -Xcc -working-directory/Users/dave/src/swift-format 11 | 12 | # xcodebuild build -toolchain org.swift.3020180130a -configuration Debug -sdk macosx10.13internal -project "${top}"/swift-format.xcodeproj -quiet -scheme swift-format 13 | -------------------------------------------------------------------------------- /swift-format.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 50; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 55D971C32023CCEF000FB327 /* main.swift in Sources */ = {isa = PBXBuildFile; fileRef = 55D971C22023CCEF000FB327 /* main.swift */; }; 11 | /* End PBXBuildFile section */ 12 | 13 | /* Begin PBXCopyFilesBuildPhase section */ 14 | 55D971BD2023CCEF000FB327 /* CopyFiles */ = { 15 | isa = PBXCopyFilesBuildPhase; 16 | buildActionMask = 2147483647; 17 | dstPath = /usr/share/man/man1/; 18 | dstSubfolderSpec = 0; 19 | files = ( 20 | ); 21 | runOnlyForDeploymentPostprocessing = 1; 22 | }; 23 | /* End PBXCopyFilesBuildPhase section */ 24 | 25 | /* Begin PBXFileReference section */ 26 | 55D971BF2023CCEF000FB327 /* swift-format */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = "swift-format"; sourceTree = BUILT_PRODUCTS_DIR; }; 27 | 55D971C22023CCEF000FB327 /* main.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = main.swift; sourceTree = ""; }; 28 | /* End PBXFileReference section */ 29 | 30 | /* Begin PBXFrameworksBuildPhase section */ 31 | 55D971BC2023CCEF000FB327 /* Frameworks */ = { 32 | isa = PBXFrameworksBuildPhase; 33 | buildActionMask = 2147483647; 34 | files = ( 35 | ); 36 | runOnlyForDeploymentPostprocessing = 0; 37 | }; 38 | /* End PBXFrameworksBuildPhase section */ 39 | 40 | /* Begin PBXGroup section */ 41 | 55D971B62023CCEF000FB327 = { 42 | isa = PBXGroup; 43 | children = ( 44 | 55D971C12023CCEF000FB327 /* swift-format */, 45 | 55D971C02023CCEF000FB327 /* Products */, 46 | ); 47 | sourceTree = ""; 48 | }; 49 | 55D971C02023CCEF000FB327 /* Products */ = { 50 | isa = PBXGroup; 51 | children = ( 52 | 55D971BF2023CCEF000FB327 /* swift-format */, 53 | ); 54 | name = Products; 55 | sourceTree = ""; 56 | }; 57 | 55D971C12023CCEF000FB327 /* swift-format */ = { 58 | isa = PBXGroup; 59 | children = ( 60 | 55D971C22023CCEF000FB327 /* main.swift */, 61 | ); 62 | path = "swift-format"; 63 | sourceTree = ""; 64 | }; 65 | /* End PBXGroup section */ 66 | 67 | /* Begin PBXNativeTarget section */ 68 | 55D971BE2023CCEF000FB327 /* swift-format */ = { 69 | isa = PBXNativeTarget; 70 | buildConfigurationList = 55D971C62023CCEF000FB327 /* Build configuration list for PBXNativeTarget "swift-format" */; 71 | buildPhases = ( 72 | 55D971BB2023CCEF000FB327 /* Sources */, 73 | 55D971BC2023CCEF000FB327 /* Frameworks */, 74 | 55D971BD2023CCEF000FB327 /* CopyFiles */, 75 | ); 76 | buildRules = ( 77 | ); 78 | dependencies = ( 79 | ); 80 | name = "swift-format"; 81 | productName = "swift-format"; 82 | productReference = 55D971BF2023CCEF000FB327 /* swift-format */; 83 | productType = "com.apple.product-type.tool"; 84 | }; 85 | /* End PBXNativeTarget section */ 86 | 87 | /* Begin PBXProject section */ 88 | 55D971B72023CCEF000FB327 /* Project object */ = { 89 | isa = PBXProject; 90 | attributes = { 91 | LastSwiftUpdateCheck = 0930; 92 | LastUpgradeCheck = 0930; 93 | ORGANIZATIONNAME = "Dave Abrahams"; 94 | TargetAttributes = { 95 | 55D971BE2023CCEF000FB327 = { 96 | CreatedOnToolsVersion = 9.3; 97 | }; 98 | }; 99 | }; 100 | buildConfigurationList = 55D971BA2023CCEF000FB327 /* Build configuration list for PBXProject "swift-format" */; 101 | compatibilityVersion = "Xcode 9.3"; 102 | developmentRegion = en; 103 | hasScannedForEncodings = 0; 104 | knownRegions = ( 105 | en, 106 | ); 107 | mainGroup = 55D971B62023CCEF000FB327; 108 | productRefGroup = 55D971C02023CCEF000FB327 /* Products */; 109 | projectDirPath = ""; 110 | projectRoot = ""; 111 | targets = ( 112 | 55D971BE2023CCEF000FB327 /* swift-format */, 113 | ); 114 | }; 115 | /* End PBXProject section */ 116 | 117 | /* Begin PBXSourcesBuildPhase section */ 118 | 55D971BB2023CCEF000FB327 /* Sources */ = { 119 | isa = PBXSourcesBuildPhase; 120 | buildActionMask = 2147483647; 121 | files = ( 122 | 55D971C32023CCEF000FB327 /* main.swift in Sources */, 123 | ); 124 | runOnlyForDeploymentPostprocessing = 0; 125 | }; 126 | /* End PBXSourcesBuildPhase section */ 127 | 128 | /* Begin XCBuildConfiguration section */ 129 | 55D971C42023CCEF000FB327 /* Debug */ = { 130 | isa = XCBuildConfiguration; 131 | buildSettings = { 132 | ALWAYS_SEARCH_USER_PATHS = NO; 133 | CLANG_ANALYZER_NONNULL = YES; 134 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 135 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; 136 | CLANG_CXX_LIBRARY = "libc++"; 137 | CLANG_ENABLE_MODULES = YES; 138 | CLANG_ENABLE_OBJC_ARC = YES; 139 | CLANG_ENABLE_OBJC_WEAK = YES; 140 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 141 | CLANG_WARN_BOOL_CONVERSION = YES; 142 | CLANG_WARN_COMMA = YES; 143 | CLANG_WARN_CONSTANT_CONVERSION = YES; 144 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 145 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 146 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 147 | CLANG_WARN_EMPTY_BODY = YES; 148 | CLANG_WARN_ENUM_CONVERSION = YES; 149 | CLANG_WARN_INFINITE_RECURSION = YES; 150 | CLANG_WARN_INT_CONVERSION = YES; 151 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 152 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 153 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 154 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 155 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 156 | CLANG_WARN_STRICT_PROTOTYPES = YES; 157 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 158 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 159 | CLANG_WARN_UNREACHABLE_CODE = YES; 160 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 161 | CODE_SIGN_IDENTITY = "Mac Developer"; 162 | COPY_PHASE_STRIP = NO; 163 | DEBUG_INFORMATION_FORMAT = dwarf; 164 | ENABLE_STRICT_OBJC_MSGSEND = YES; 165 | ENABLE_TESTABILITY = YES; 166 | GCC_C_LANGUAGE_STANDARD = gnu11; 167 | GCC_DYNAMIC_NO_PIC = NO; 168 | GCC_NO_COMMON_BLOCKS = YES; 169 | GCC_OPTIMIZATION_LEVEL = 0; 170 | GCC_PREPROCESSOR_DEFINITIONS = ( 171 | "DEBUG=1", 172 | "$(inherited)", 173 | ); 174 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 175 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 176 | GCC_WARN_UNDECLARED_SELECTOR = YES; 177 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 178 | GCC_WARN_UNUSED_FUNCTION = YES; 179 | GCC_WARN_UNUSED_VARIABLE = YES; 180 | LIBRARY_SEARCH_PATHS = "$(TOOLCHAIN_DIR)/usr/lib/swift/macosx"; 181 | MACOSX_DEPLOYMENT_TARGET = 10.13; 182 | MTL_ENABLE_DEBUG_INFO = YES; 183 | ONLY_ACTIVE_ARCH = YES; 184 | SDKROOT = macosx; 185 | SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; 186 | SWIFT_OPTIMIZATION_LEVEL = "-Onone"; 187 | }; 188 | name = Debug; 189 | }; 190 | 55D971C52023CCEF000FB327 /* Release */ = { 191 | isa = XCBuildConfiguration; 192 | buildSettings = { 193 | ALWAYS_SEARCH_USER_PATHS = NO; 194 | CLANG_ANALYZER_NONNULL = YES; 195 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 196 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; 197 | CLANG_CXX_LIBRARY = "libc++"; 198 | CLANG_ENABLE_MODULES = YES; 199 | CLANG_ENABLE_OBJC_ARC = YES; 200 | CLANG_ENABLE_OBJC_WEAK = YES; 201 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 202 | CLANG_WARN_BOOL_CONVERSION = YES; 203 | CLANG_WARN_COMMA = YES; 204 | CLANG_WARN_CONSTANT_CONVERSION = YES; 205 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 206 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 207 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 208 | CLANG_WARN_EMPTY_BODY = YES; 209 | CLANG_WARN_ENUM_CONVERSION = YES; 210 | CLANG_WARN_INFINITE_RECURSION = YES; 211 | CLANG_WARN_INT_CONVERSION = YES; 212 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 213 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 214 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 215 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 216 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 217 | CLANG_WARN_STRICT_PROTOTYPES = YES; 218 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 219 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 220 | CLANG_WARN_UNREACHABLE_CODE = YES; 221 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 222 | CODE_SIGN_IDENTITY = "Mac Developer"; 223 | COPY_PHASE_STRIP = NO; 224 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 225 | ENABLE_NS_ASSERTIONS = NO; 226 | ENABLE_STRICT_OBJC_MSGSEND = YES; 227 | GCC_C_LANGUAGE_STANDARD = gnu11; 228 | GCC_NO_COMMON_BLOCKS = YES; 229 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 230 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 231 | GCC_WARN_UNDECLARED_SELECTOR = YES; 232 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 233 | GCC_WARN_UNUSED_FUNCTION = YES; 234 | GCC_WARN_UNUSED_VARIABLE = YES; 235 | LIBRARY_SEARCH_PATHS = "$(TOOLCHAIN_DIR)/usr/lib/swift/macosx"; 236 | MACOSX_DEPLOYMENT_TARGET = 10.13; 237 | MTL_ENABLE_DEBUG_INFO = NO; 238 | SDKROOT = macosx; 239 | SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; 240 | }; 241 | name = Release; 242 | }; 243 | 55D971C72023CCEF000FB327 /* Debug */ = { 244 | isa = XCBuildConfiguration; 245 | buildSettings = { 246 | CODE_SIGN_STYLE = Automatic; 247 | DEVELOPMENT_TEAM = CCZP35X7F3; 248 | LD_RUNPATH_SEARCH_PATHS = "$(TOOLCHAIN_DIR)/usr/lib/swift/macosx"; 249 | PRODUCT_NAME = "$(TARGET_NAME)"; 250 | SWIFT_VERSION = 4.0; 251 | }; 252 | name = Debug; 253 | }; 254 | 55D971C82023CCEF000FB327 /* Release */ = { 255 | isa = XCBuildConfiguration; 256 | buildSettings = { 257 | CODE_SIGN_STYLE = Automatic; 258 | DEVELOPMENT_TEAM = CCZP35X7F3; 259 | LD_RUNPATH_SEARCH_PATHS = "$(TOOLCHAIN_DIR)/usr/lib/swift/macosx"; 260 | PRODUCT_NAME = "$(TARGET_NAME)"; 261 | SWIFT_VERSION = 4.0; 262 | }; 263 | name = Release; 264 | }; 265 | /* End XCBuildConfiguration section */ 266 | 267 | /* Begin XCConfigurationList section */ 268 | 55D971BA2023CCEF000FB327 /* Build configuration list for PBXProject "swift-format" */ = { 269 | isa = XCConfigurationList; 270 | buildConfigurations = ( 271 | 55D971C42023CCEF000FB327 /* Debug */, 272 | 55D971C52023CCEF000FB327 /* Release */, 273 | ); 274 | defaultConfigurationIsVisible = 0; 275 | defaultConfigurationName = Release; 276 | }; 277 | 55D971C62023CCEF000FB327 /* Build configuration list for PBXNativeTarget "swift-format" */ = { 278 | isa = XCConfigurationList; 279 | buildConfigurations = ( 280 | 55D971C72023CCEF000FB327 /* Debug */, 281 | 55D971C82023CCEF000FB327 /* Release */, 282 | ); 283 | defaultConfigurationIsVisible = 0; 284 | defaultConfigurationName = Release; 285 | }; 286 | /* End XCConfigurationList section */ 287 | }; 288 | rootObject = 55D971B72023CCEF000FB327 /* Project object */; 289 | } 290 | -------------------------------------------------------------------------------- /swift-format.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /swift-format.xcodeproj/xcuserdata/dave.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | swift-format.xcscheme 8 | 9 | orderHint 10 | 0 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /swift-format/main.swift: -------------------------------------------------------------------------------- 1 | // 2 | // main.swift 3 | // swift-format 4 | // 5 | // Created by Dave Abrahams on 2/1/18. 6 | // Copyright © 2018 Dave Abrahams. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | import SwiftSyntax 11 | 12 | struct X { 13 | func fubar() -> X { return self } 14 | var myself: X { return self } 15 | } 16 | 17 | func genericFunc(x: T, y: U) -> (T.Element?, U.Element?) 18 | where T.Index == U.Index, U.Iterator == IndexingIterator<[Int]> { 19 | _ = 3 * 4 + (5 * 6) 20 | _ = x.map { y->Int in 3 } 21 | _ = x.map { $0 } 22 | _ = X().fubar().fubar().fubar() // trailing comment 23 | _ = X().myself.myself 24 | _ = X().myself.fubar().myself.fubar() 25 | _ = X().fubar().myself.fubar().myself 26 | 27 | return (x.first, y.first) 28 | } 29 | 30 | func ascii16(_ x: UnicodeScalar) -> UTF16.CodeUnit { 31 | assert(x.isASCII) 32 | return UTF16.CodeUnit(x.value) 33 | } 34 | 35 | struct SourceLoc { 36 | var line = 0 37 | var column = 0 38 | 39 | mutating func traverse(_ text: String) { 40 | for c in text.utf16 { 41 | switch c { 42 | case 0xb, 0xc: line += 1// vertical linefeed, formfeed 43 | case ascii16("\n"): line += 1; column = 0 44 | case ascii16("\r"): column = 0 45 | default: column += 1 46 | } 47 | } 48 | } 49 | 50 | mutating func traverse(_ nonToken: TriviaPiece) { 51 | switch nonToken { 52 | case .spaces(let n), .tabs(let n), .backticks(let n): 53 | column += n 54 | 55 | case .verticalTabs(let n), .formfeeds(let n): 56 | line += n 57 | 58 | case .newlines(let n), .carriageReturnLineFeeds(let n): 59 | line += n 60 | column = 0 61 | 62 | case .carriageReturns(_): 63 | column = 0 64 | 65 | case .lineComment(let s), 66 | .blockComment(let s), 67 | .docLineComment(let s), 68 | .docBlockComment(let s), 69 | .garbageText(let s): 70 | 71 | traverse(s) 72 | } 73 | } 74 | 75 | mutating func traverseNonTrivia(_ token: TokenSyntax) { 76 | // DWA FIXME: this could be sped up by knowing the length of more tokens 77 | switch token.tokenKind { 78 | case .atSign, 79 | .colon, 80 | .semicolon, 81 | .comma, 82 | .period, 83 | .equal, 84 | .prefixPeriod, 85 | .leftParen, 86 | .rightParen, 87 | .leftBrace, 88 | .rightBrace, 89 | .leftSquareBracket, 90 | .rightSquareBracket, 91 | .leftAngle, 92 | .rightAngle, 93 | .prefixAmpersand, 94 | .postfixQuestionMark, 95 | .infixQuestionMark, 96 | .exclamationMark, 97 | .backslash, 98 | .stringQuote: 99 | column += 1 100 | case .arrow: 101 | column += 2 102 | default: traverse(token.text) 103 | } 104 | } 105 | } 106 | 107 | extension SourceLoc : CustomStringConvertible { 108 | var description: String { 109 | return "\(line + 1).\(column + 1)" 110 | } 111 | } 112 | 113 | extension SourceLoc : CustomDebugStringConvertible { 114 | var debugDescription: String { 115 | return "SourceLoc(line: \(line): column: \(column))" 116 | } 117 | } 118 | 119 | struct Node { 120 | init(_ x: T) { 121 | syntax = x 122 | id = x.id 123 | } 124 | 125 | var kind: Syntax.Type { 126 | return type(of: syntax) 127 | } 128 | 129 | let syntax: Syntax 130 | let id: Int 131 | } 132 | 133 | extension Node : Equatable { 134 | static func == (x: Node, y: Node) -> Bool { 135 | return x.id == y.id 136 | } 137 | } 138 | 139 | extension BidirectionalCollection where Element : Equatable { 140 | func ends(with s: S) -> Bool 141 | where S.Element == Self.Element 142 | { 143 | return self.reversed().starts(with: s.reversed()) 144 | } 145 | 146 | func droppingSuffix(_ s: S) -> SubSequence 147 | where S.Element == Self.Element 148 | { 149 | return self.ends(with: s) ? self.dropLast(s.count) : self[...] 150 | } 151 | } 152 | 153 | extension Node : CustomStringConvertible { 154 | var description: String { 155 | let syntaxCodeUnits = "Syntax".utf16 156 | let typeName = "\(kind)".utf16.split(separator: ".".utf16.first!).last! 157 | return String(typeName.droppingSuffix(syntaxCodeUnits))! 158 | } 159 | } 160 | 161 | extension TokenSyntax { 162 | /// True iff `self` might be mis-tokenized if placed next to an 'a' with no 163 | /// intervening whitespace. 164 | var isIdentifierLike: Bool { 165 | // DWA FIXME: This might be optimized by knowing more token kinds... 166 | if case .identifier(_) = tokenKind { return true } 167 | 168 | // ...but we should retain this fallback for resilience as the language 169 | // evolves. 170 | 171 | func isKnownIdentifierCodeUnit(_ c: UTF16.CodeUnit) -> Bool { 172 | switch c { 173 | case ascii16("_"), 174 | ascii16("a")...ascii16("z"), 175 | ascii16("A")...ascii16("Z"), 176 | ascii16("0")...ascii16("9"): return true 177 | default: return false 178 | } 179 | } 180 | 181 | let codeUnits = text.utf16 182 | 183 | if let first = codeUnits.first { 184 | if isKnownIdentifierCodeUnit(first) { return true } 185 | } 186 | if let last = codeUnits.last { 187 | if isKnownIdentifierCodeUnit(last) { return true } 188 | } 189 | return false 190 | } 191 | } 192 | 193 | struct Injection { 194 | var whitespaceRequired: Bool = false 195 | var newlineRequired: Bool = false 196 | var closeGroups: Int16 = 0 197 | var openGroups: Int16 = 0 198 | } 199 | 200 | enum OutputElement { 201 | case openGroup 202 | case closeGroup(matchingOpenIndex: Int) 203 | case whitespace 204 | case newline 205 | case token(syntax: TokenSyntax/*, location: SourceLoc, ancestors: [Node]*/) 206 | } 207 | 208 | typealias SyntaxID = Int 209 | 210 | extension Syntax where Self : Hashable { 211 | var id: SyntaxID { return hashValue } 212 | } 213 | 214 | protocol _StmtSyntax : StmtSyntax { 215 | var semicolon: SwiftSyntax.TokenSyntax? { get } 216 | var id: Int { get } 217 | } 218 | extension BreakStmtSyntax : _StmtSyntax {} 219 | extension ContinueStmtSyntax : _StmtSyntax {} 220 | extension DeclarationStmtSyntax : _StmtSyntax {} 221 | extension DeferStmtSyntax : _StmtSyntax {} 222 | extension DoStmtSyntax : _StmtSyntax {} 223 | extension ExpressionStmtSyntax : _StmtSyntax {} 224 | extension FallthroughStmtSyntax : _StmtSyntax {} 225 | extension ForInStmtSyntax : _StmtSyntax {} 226 | extension GuardStmtSyntax : _StmtSyntax {} 227 | extension IfStmtSyntax : _StmtSyntax {} 228 | extension RepeatWhileStmtSyntax : _StmtSyntax {} 229 | extension ReturnStmtSyntax : _StmtSyntax {} 230 | extension SwitchStmtSyntax : _StmtSyntax {} 231 | extension ThrowStmtSyntax : _StmtSyntax {} 232 | //extension UnknownStmtSyntax : _StmtSyntax {} 233 | extension WhileStmtSyntax : _StmtSyntax {} 234 | 235 | struct LazyDictionary { 236 | init(default: V) { 237 | defaultValue = { _ in `default` } 238 | } 239 | init(default: @escaping (K)->V) { 240 | defaultValue = `default` 241 | } 242 | 243 | subscript(key: K) -> V { 244 | get { 245 | return impl[key] ?? defaultValue(key) 246 | } 247 | set { 248 | impl[key] = newValue 249 | } 250 | } 251 | 252 | mutating func removeValue(forKey k: K) -> V? { 253 | return impl.removeValue(forKey: k) 254 | } 255 | 256 | var defaultValue: (K)->V 257 | var impl: [K : V] = [:] 258 | } 259 | 260 | final class Reparser : SyntaxVisitor { 261 | var content: [OutputElement] = [] 262 | 263 | /// A stack of openGroup indices that have not yet been matched by a 264 | /// closeGroup. 265 | var unmatchedOpenGroups: [Int] = [] 266 | 267 | var inputLocation = SourceLoc() 268 | var ancestors: [Node] = [] 269 | var previousToken: TokenSyntax? = nil 270 | typealias Injections = LazyDictionary 271 | 272 | var before = Injections(default: Injection()) 273 | var after = Injections(default: Injection()) 274 | 275 | var nestingLevel = 0 // just used for debug output 276 | 277 | func openGroup() { 278 | unmatchedOpenGroups.append(content.count) 279 | content.append(.openGroup) 280 | nestingLevel += 1 281 | } 282 | 283 | func closeGroup() { 284 | nestingLevel -= 1 285 | content.append( 286 | .closeGroup(matchingOpenIndex: unmatchedOpenGroups.removeLast())) 287 | } 288 | 289 | func apply(_ a: inout Injections, to s: T) { 290 | if let i = a.removeValue(forKey: s.id) { 291 | for _ in 0..( 301 | _ node: T, _ body: ()->R 302 | ) -> R { 303 | apply(&before, to: node) 304 | ancestors.append(Node(node)) 305 | let r = body() 306 | ancestors.removeLast() 307 | apply(&after, to: node) 308 | return r 309 | } 310 | 311 | func injectMandatoryNewlines(in statements: StmtListSyntax) { 312 | for s in statements.dropLast() { 313 | if (s as? _StmtSyntax)?.semicolon != nil { continue } 314 | after[(s as! AnyHashable).hashValue].newlineRequired = true 315 | } 316 | } 317 | 318 | override func visit(_ node: SwiftSyntax.UnknownDeclSyntax) { 319 | visitChildren(node) { super.visit(node) } 320 | } 321 | 322 | override func visit(_ node: SwiftSyntax.UnknownExprSyntax) { 323 | visitChildren(node) { super.visit(node) } 324 | } 325 | 326 | override func visit(_ node: SwiftSyntax.UnknownStmtSyntax) { 327 | visitChildren(node) { super.visit(node) } 328 | } 329 | 330 | override func visit(_ node: SwiftSyntax.UnknownTypeSyntax) { 331 | visitChildren(node) { super.visit(node) } 332 | } 333 | 334 | override func visit(_ node: SwiftSyntax.UnknownPatternSyntax) { 335 | visitChildren(node) { super.visit(node) } 336 | } 337 | 338 | override func visit(_ node: SwiftSyntax.InOutExprSyntax) { 339 | visitChildren(node) { super.visit(node) } 340 | } 341 | 342 | override func visit(_ node: SwiftSyntax.PoundColumnExprSyntax) { 343 | visitChildren(node) { super.visit(node) } 344 | } 345 | 346 | override func visit(_ node: SwiftSyntax.TryExprSyntax) { 347 | visitChildren(node) { super.visit(node) } 348 | } 349 | 350 | override func visit(_ node: SwiftSyntax.DeclNameArgumentSyntax) { 351 | visitChildren(node) { super.visit(node) } 352 | } 353 | 354 | override func visit(_ node: SwiftSyntax.DeclNameArgumentsSyntax) { 355 | after[node.leftParen.id].openGroups += 1 356 | before[node.rightParen.id].closeGroups += 1 357 | visitChildren(node) { super.visit(node) } 358 | } 359 | 360 | override func visit(_ node: SwiftSyntax.IdentifierExprSyntax) { 361 | visitChildren(node) { super.visit(node) } 362 | } 363 | 364 | override func visit(_ node: SwiftSyntax.SuperRefExprSyntax) { 365 | visitChildren(node) { super.visit(node) } 366 | } 367 | 368 | override func visit(_ node: SwiftSyntax.NilLiteralExprSyntax) { 369 | visitChildren(node) { super.visit(node) } 370 | } 371 | 372 | override func visit(_ node: SwiftSyntax.DiscardAssignmentExprSyntax) { 373 | visitChildren(node) { super.visit(node) } 374 | } 375 | 376 | override func visit(_ node: SwiftSyntax.AssignmentExprSyntax) { 377 | visitChildren(node) { super.visit(node) } 378 | } 379 | 380 | override func visit(_ node: SwiftSyntax.SequenceExprSyntax) { 381 | visitChildren(node) { super.visit(node) } 382 | } 383 | 384 | override func visit(_ node: SwiftSyntax.PoundLineExprSyntax) { 385 | visitChildren(node) { super.visit(node) } 386 | } 387 | 388 | override func visit(_ node: SwiftSyntax.PoundFileExprSyntax) { 389 | visitChildren(node) { super.visit(node) } 390 | } 391 | 392 | override func visit(_ node: SwiftSyntax.PoundFunctionExprSyntax) { 393 | visitChildren(node) { super.visit(node) } 394 | } 395 | 396 | override func visit(_ node: SwiftSyntax.PoundDsohandleExprSyntax) { 397 | visitChildren(node) { super.visit(node) } 398 | } 399 | 400 | override func visit(_ node: SwiftSyntax.SymbolicReferenceExprSyntax) { 401 | visitChildren(node) { super.visit(node) } 402 | } 403 | 404 | override func visit(_ node: SwiftSyntax.PrefixOperatorExprSyntax) { 405 | visitChildren(node) { super.visit(node) } 406 | } 407 | 408 | override func visit(_ node: SwiftSyntax.BinaryOperatorExprSyntax) { 409 | before[node.operatorToken.id].whitespaceRequired = true 410 | after[node.operatorToken.id].whitespaceRequired = true 411 | visitChildren(node) { super.visit(node) } 412 | } 413 | 414 | override func visit(_ node: SwiftSyntax.FloatLiteralExprSyntax) { 415 | visitChildren(node) { super.visit(node) } 416 | } 417 | 418 | override func visit(_ node: SwiftSyntax.TupleExprSyntax) { 419 | after[node.leftParen.id].openGroups += 1 420 | before[node.rightParen.id].closeGroups += 1 421 | visitChildren(node) { super.visit(node) } 422 | } 423 | 424 | override func visit(_ node: SwiftSyntax.ArrayExprSyntax) { 425 | after[node.leftSquare.id].openGroups += 1 426 | before[node.rightSquare.id].closeGroups += 1 427 | visitChildren(node) { super.visit(node) } 428 | } 429 | 430 | override func visit(_ node: SwiftSyntax.DictionaryExprSyntax) { 431 | after[node.leftSquare.id].openGroups += 1 432 | before[node.rightSquare.id].closeGroups += 1 433 | visitChildren(node) { super.visit(node) } 434 | } 435 | 436 | override func visit(_ node: SwiftSyntax.ImplicitMemberExprSyntax) { 437 | before[node.id].whitespaceRequired = true 438 | visitChildren(node) { super.visit(node) } 439 | } 440 | 441 | override func visit(_ node: SwiftSyntax.FunctionCallArgumentSyntax) { 442 | visitChildren(node) { super.visit(node) } 443 | } 444 | 445 | override func visit(_ node: SwiftSyntax.TupleElementSyntax) { 446 | visitChildren(node) { super.visit(node) } 447 | } 448 | 449 | override func visit(_ node: SwiftSyntax.ArrayElementSyntax) { 450 | visitChildren(node) { super.visit(node) } 451 | } 452 | 453 | override func visit(_ node: SwiftSyntax.DictionaryElementSyntax) { 454 | visitChildren(node) { super.visit(node) } 455 | } 456 | 457 | override func visit(_ node: SwiftSyntax.IntegerLiteralExprSyntax) { 458 | visitChildren(node) { super.visit(node) } 459 | } 460 | 461 | override func visit(_ node: SwiftSyntax.StringLiteralExprSyntax) { 462 | visitChildren(node) { super.visit(node) } 463 | } 464 | 465 | override func visit(_ node: SwiftSyntax.BooleanLiteralExprSyntax) { 466 | visitChildren(node) { super.visit(node) } 467 | } 468 | 469 | override func visit(_ node: SwiftSyntax.TernaryExprSyntax) { 470 | visitChildren(node) { super.visit(node) } 471 | } 472 | 473 | override func visit(_ node: SwiftSyntax.MemberAccessExprSyntax) { 474 | before[node.dot.id].openGroups += 1 475 | let top = ancestors.last! 476 | let closer = top.syntax is SwiftSyntax.FunctionCallExprSyntax 477 | ? top.id : node.id 478 | after[closer].closeGroups += 1 479 | 480 | visitChildren(node) { super.visit(node) } 481 | } 482 | 483 | override func visit(_ node: SwiftSyntax.DotSelfExprSyntax) { 484 | visitChildren(node) { super.visit(node) } 485 | } 486 | 487 | override func visit(_ node: SwiftSyntax.IsExprSyntax) { 488 | visitChildren(node) { super.visit(node) } 489 | } 490 | 491 | override func visit(_ node: SwiftSyntax.AsExprSyntax) { 492 | visitChildren(node) { super.visit(node) } 493 | } 494 | 495 | override func visit(_ node: SwiftSyntax.TypeExprSyntax) { 496 | visitChildren(node) { super.visit(node) } 497 | } 498 | 499 | override func visit(_ node: SwiftSyntax.ClosureCaptureItemSyntax) { 500 | visitChildren(node) { super.visit(node) } 501 | } 502 | 503 | override func visit(_ node: SwiftSyntax.ClosureCaptureSignatureSyntax) { 504 | after[node.leftSquare.id].openGroups += 1 505 | before[node.rightSquare.id].closeGroups += 1 506 | visitChildren(node) { super.visit(node) } 507 | } 508 | 509 | override func visit(_ node: SwiftSyntax.ClosureParamSyntax) { 510 | visitChildren(node) { super.visit(node) } 511 | } 512 | 513 | override func visit(_ node: SwiftSyntax.ClosureSignatureSyntax) { 514 | visitChildren(node) { super.visit(node) } 515 | } 516 | 517 | override func visit(_ node: SwiftSyntax.ClosureExprSyntax) { 518 | injectMandatoryNewlines(in: node.statements) 519 | after[node.signature.map { $0.id } ?? node.leftBrace.id].openGroups += 1 520 | after[node.leftBrace.id].whitespaceRequired = true 521 | before[node.rightBrace.id].closeGroups += 1 522 | before[node.rightBrace.id].whitespaceRequired = true 523 | visitChildren(node) { super.visit(node) } 524 | } 525 | 526 | override func visit(_ node: SwiftSyntax.UnresolvedPatternExprSyntax) { 527 | visitChildren(node) { super.visit(node) } 528 | } 529 | 530 | override func visit(_ node: SwiftSyntax.FunctionCallExprSyntax) { 531 | if let l = node.leftParen, let r = node.rightParen { 532 | after[l.id].openGroups += 1 533 | before[r.id].closeGroups += 1 534 | } 535 | visitChildren(node) { super.visit(node) } 536 | } 537 | 538 | override func visit(_ node: SwiftSyntax.SubscriptExprSyntax) { 539 | after[node.leftBracket.id].openGroups += 1 540 | before[node.rightBracket.id].closeGroups += 1 541 | visitChildren(node) { super.visit(node) } 542 | } 543 | 544 | override func visit(_ node: SwiftSyntax.OptionalChainingExprSyntax) { 545 | visitChildren(node) { super.visit(node) } 546 | } 547 | 548 | override func visit(_ node: SwiftSyntax.ForcedValueExprSyntax) { 549 | visitChildren(node) { super.visit(node) } 550 | } 551 | 552 | override func visit(_ node: SwiftSyntax.PostfixUnaryExprSyntax) { 553 | visitChildren(node) { super.visit(node) } 554 | } 555 | 556 | override func visit(_ node: SwiftSyntax.StringSegmentSyntax) { 557 | visitChildren(node) { super.visit(node) } 558 | } 559 | 560 | override func visit(_ node: SwiftSyntax.ExpressionSegmentSyntax) { 561 | after[node.leftParen.id].openGroups += 1 562 | before[node.rightParen.id].closeGroups += 1 563 | visitChildren(node) { super.visit(node) } 564 | } 565 | 566 | override func visit(_ node: SwiftSyntax.StringInterpolationExprSyntax) { 567 | visitChildren(node) { super.visit(node) } 568 | } 569 | 570 | override func visit(_ node: SwiftSyntax.KeyPathExprSyntax) { 571 | visitChildren(node) { super.visit(node) } 572 | } 573 | 574 | override func visit(_ node: SwiftSyntax.ObjcNamePieceSyntax) { 575 | visitChildren(node) { super.visit(node) } 576 | } 577 | 578 | override func visit(_ node: SwiftSyntax.ObjcKeyPathExprSyntax) { 579 | after[node.leftParen.id].openGroups += 1 580 | before[node.rightParen.id].closeGroups += 1 581 | visitChildren(node) { super.visit(node) } 582 | } 583 | 584 | override func visit(_ node: SwiftSyntax.EditorPlaceholderExprSyntax) { 585 | visitChildren(node) { super.visit(node) } 586 | } 587 | 588 | override func visit(_ node: SwiftSyntax.ObjectLiteralExprSyntax) { 589 | after[node.leftParen.id].openGroups += 1 590 | before[node.rightParen.id].closeGroups += 1 591 | visitChildren(node) { super.visit(node) } 592 | } 593 | 594 | override func visit(_ node: SwiftSyntax.TypeInitializerClauseSyntax) { 595 | visitChildren(node) { super.visit(node) } 596 | } 597 | 598 | override func visit(_ node: SwiftSyntax.TypealiasDeclSyntax) { 599 | visitChildren(node) { super.visit(node) } 600 | } 601 | 602 | override func visit(_ node: SwiftSyntax.ParameterClauseSyntax) { 603 | after[node.leftParen.id].openGroups += 1 604 | before[node.rightParen.id].closeGroups += 1 605 | visitChildren(node) { super.visit(node) } 606 | } 607 | 608 | override func visit(_ node: SwiftSyntax.ReturnClauseSyntax) { 609 | after[node.arrow.id].whitespaceRequired = true 610 | before[node.arrow.id].whitespaceRequired = true 611 | visitChildren(node) { super.visit(node) } 612 | } 613 | 614 | override func visit(_ node: SwiftSyntax.FunctionSignatureSyntax) { 615 | visitChildren(node) { super.visit(node) } 616 | } 617 | 618 | override func visit(_ node: SwiftSyntax.ElseifDirectiveClauseSyntax) { 619 | injectMandatoryNewlines(in: node.body) 620 | visitChildren(node) { super.visit(node) } 621 | } 622 | 623 | override func visit(_ node: SwiftSyntax.IfConfigDeclSyntax) { 624 | injectMandatoryNewlines(in: node.body) 625 | visitChildren(node) { super.visit(node) } 626 | } 627 | 628 | override func visit(_ node: SwiftSyntax.DeclModifierSyntax) { 629 | visitChildren(node) { super.visit(node) } 630 | } 631 | 632 | override func visit(_ node: SwiftSyntax.InheritedTypeSyntax) { 633 | visitChildren(node) { super.visit(node) } 634 | } 635 | 636 | override func visit(_ node: SwiftSyntax.TypeInheritanceClauseSyntax) { 637 | visitChildren(node) { super.visit(node) } 638 | } 639 | 640 | override func visit(_ node: SwiftSyntax.ClassDeclSyntax) { 641 | visitChildren(node) { super.visit(node) } 642 | } 643 | 644 | override func visit(_ node: SwiftSyntax.StructDeclSyntax) { 645 | visitChildren(node) { super.visit(node) } 646 | } 647 | 648 | override func visit(_ node: SwiftSyntax.ProtocolDeclSyntax) { 649 | visitChildren(node) { super.visit(node) } 650 | } 651 | 652 | override func visit(_ node: SwiftSyntax.ExtensionDeclSyntax) { 653 | visitChildren(node) { super.visit(node) } 654 | } 655 | 656 | override func visit(_ node: SwiftSyntax.MemberDeclBlockSyntax) { 657 | after[node.leftBrace.id].openGroups += 1 658 | after[node.leftBrace.id].whitespaceRequired = true 659 | before[node.leftBrace.id].whitespaceRequired = true 660 | before[node.rightBrace.id].closeGroups += 1 661 | before[node.rightBrace.id].whitespaceRequired = true 662 | visitChildren(node) { super.visit(node) } 663 | } 664 | 665 | override func visit(_ node: SwiftSyntax.SourceFileSyntax) { 666 | visitChildren(node) { super.visit(node) } 667 | } 668 | 669 | override func visit(_ node: SwiftSyntax.TopLevelCodeDeclSyntax) { 670 | injectMandatoryNewlines(in: node.body) 671 | visitChildren(node) { super.visit(node) } 672 | } 673 | 674 | override func visit(_ node: SwiftSyntax.InitializerClauseSyntax) { 675 | visitChildren(node) { super.visit(node) } 676 | } 677 | 678 | override func visit(_ node: SwiftSyntax.FunctionParameterSyntax) { 679 | visitChildren(node) { super.visit(node) } 680 | } 681 | 682 | override func visit(_ node: SwiftSyntax.FunctionDeclSyntax) { 683 | visitChildren(node) { super.visit(node) } 684 | } 685 | 686 | override func visit(_ node: SwiftSyntax.ElseDirectiveClauseSyntax) { 687 | injectMandatoryNewlines(in: node.body) 688 | visitChildren(node) { super.visit(node) } 689 | } 690 | 691 | override func visit(_ node: SwiftSyntax.AccessLevelModifierSyntax) { 692 | if let l = node.openParen, let r = node.closeParen { 693 | after[l.id].openGroups += 1 694 | before[r.id].closeGroups += 1 695 | } 696 | visitChildren(node) { super.visit(node) } 697 | } 698 | 699 | override func visit(_ node: SwiftSyntax.AccessPathComponentSyntax) { 700 | visitChildren(node) { super.visit(node) } 701 | } 702 | 703 | override func visit(_ node: SwiftSyntax.ImportDeclSyntax) { 704 | visitChildren(node) { super.visit(node) } 705 | } 706 | 707 | override func visit(_ node: SwiftSyntax.AccessorParameterSyntax) { 708 | after[node.leftParen.id].openGroups += 1 709 | before[node.rightParen.id].closeGroups += 1 710 | visitChildren(node) { super.visit(node) } 711 | } 712 | 713 | override func visit(_ node: SwiftSyntax.AccessorDeclSyntax) { 714 | visitChildren(node) { super.visit(node) } 715 | } 716 | 717 | override func visit(_ node: SwiftSyntax.AccessorBlockSyntax) { 718 | after[node.leftBrace.id].openGroups += 1 719 | after[node.leftBrace.id].whitespaceRequired = true 720 | before[node.rightBrace.id].closeGroups += 1 721 | before[node.rightBrace.id].whitespaceRequired = true 722 | visitChildren(node) { super.visit(node) } 723 | } 724 | 725 | override func visit(_ node: SwiftSyntax.PatternBindingSyntax) { 726 | visitChildren(node) { super.visit(node) } 727 | } 728 | 729 | override func visit(_ node: SwiftSyntax.VariableDeclSyntax) { 730 | visitChildren(node) { super.visit(node) } 731 | } 732 | 733 | override func visit(_ node: SwiftSyntax.AttributeSyntax) { 734 | visitChildren(node) { super.visit(node) } 735 | } 736 | 737 | override func visit(_ node: SwiftSyntax.ContinueStmtSyntax) { 738 | visitChildren(node) { super.visit(node) } 739 | } 740 | 741 | override func visit(_ node: SwiftSyntax.WhileStmtSyntax) { 742 | visitChildren(node) { super.visit(node) } 743 | } 744 | 745 | override func visit(_ node: SwiftSyntax.DeferStmtSyntax) { 746 | visitChildren(node) { super.visit(node) } 747 | } 748 | 749 | override func visit(_ node: SwiftSyntax.ExpressionStmtSyntax) { 750 | visitChildren(node) { super.visit(node) } 751 | } 752 | 753 | override func visit(_ node: SwiftSyntax.RepeatWhileStmtSyntax) { 754 | visitChildren(node) { super.visit(node) } 755 | } 756 | 757 | override func visit(_ node: SwiftSyntax.GuardStmtSyntax) { 758 | visitChildren(node) { super.visit(node) } 759 | } 760 | 761 | override func visit(_ node: SwiftSyntax.WhereClauseSyntax) { 762 | visitChildren(node) { super.visit(node) } 763 | } 764 | 765 | override func visit(_ node: SwiftSyntax.ForInStmtSyntax) { 766 | visitChildren(node) { super.visit(node) } 767 | } 768 | 769 | override func visit(_ node: SwiftSyntax.SwitchStmtSyntax) { 770 | visitChildren(node) { super.visit(node) } 771 | } 772 | 773 | override func visit(_ node: SwiftSyntax.DoStmtSyntax) { 774 | visitChildren(node) { super.visit(node) } 775 | } 776 | 777 | override func visit(_ node: SwiftSyntax.ReturnStmtSyntax) { 778 | visitChildren(node) { super.visit(node) } 779 | } 780 | 781 | override func visit(_ node: SwiftSyntax.FallthroughStmtSyntax) { 782 | visitChildren(node) { super.visit(node) } 783 | } 784 | 785 | override func visit(_ node: SwiftSyntax.BreakStmtSyntax) { 786 | visitChildren(node) { super.visit(node) } 787 | } 788 | 789 | override func visit(_ node: SwiftSyntax.CodeBlockSyntax) { 790 | injectMandatoryNewlines(in: node.statements) 791 | after[node.openBrace.id].openGroups += 1 792 | after[node.openBrace.id].whitespaceRequired = true 793 | before[node.openBrace.id].whitespaceRequired = true 794 | before[node.closeBrace.id].closeGroups += 1 795 | before[node.closeBrace.id].whitespaceRequired = true 796 | visitChildren(node) { super.visit(node) } 797 | } 798 | 799 | override func visit(_ node: SwiftSyntax.ConditionElementSyntax) { 800 | visitChildren(node) { super.visit(node) } 801 | } 802 | 803 | override func visit(_ node: SwiftSyntax.AvailabilityConditionSyntax) { 804 | visitChildren(node) { super.visit(node) } 805 | } 806 | 807 | override func visit(_ node: SwiftSyntax.MatchingPatternConditionSyntax) { 808 | visitChildren(node) { super.visit(node) } 809 | } 810 | 811 | override func visit(_ node: SwiftSyntax.OptionalBindingConditionSyntax) { 812 | visitChildren(node) { super.visit(node) } 813 | } 814 | 815 | override func visit(_ node: SwiftSyntax.DeclarationStmtSyntax) { 816 | visitChildren(node) { super.visit(node) } 817 | } 818 | 819 | override func visit(_ node: SwiftSyntax.ThrowStmtSyntax) { 820 | visitChildren(node) { super.visit(node) } 821 | } 822 | 823 | override func visit(_ node: SwiftSyntax.IfStmtSyntax) { 824 | visitChildren(node) { super.visit(node) } 825 | } 826 | 827 | override func visit(_ node: SwiftSyntax.ElseIfContinuationSyntax) { 828 | visitChildren(node) { super.visit(node) } 829 | } 830 | 831 | override func visit(_ node: SwiftSyntax.ElseBlockSyntax) { 832 | visitChildren(node) { super.visit(node) } 833 | } 834 | 835 | override func visit(_ node: SwiftSyntax.SwitchCaseSyntax) { 836 | injectMandatoryNewlines(in: node.body) 837 | visitChildren(node) { super.visit(node) } 838 | } 839 | 840 | override func visit(_ node: SwiftSyntax.SwitchDefaultLabelSyntax) { 841 | visitChildren(node) { super.visit(node) } 842 | } 843 | 844 | override func visit(_ node: SwiftSyntax.CaseItemSyntax) { 845 | visitChildren(node) { super.visit(node) } 846 | } 847 | 848 | override func visit(_ node: SwiftSyntax.SwitchCaseLabelSyntax) { 849 | visitChildren(node) { super.visit(node) } 850 | } 851 | 852 | override func visit(_ node: SwiftSyntax.CatchClauseSyntax) { 853 | visitChildren(node) { super.visit(node) } 854 | } 855 | 856 | override func visit(_ node: SwiftSyntax.GenericWhereClauseSyntax) { 857 | visitChildren(node) { super.visit(node) } 858 | } 859 | 860 | override func visit(_ node: SwiftSyntax.SameTypeRequirementSyntax) { 861 | visitChildren(node) { super.visit(node) } 862 | } 863 | 864 | override func visit(_ node: SwiftSyntax.GenericParameterSyntax) { 865 | visitChildren(node) { super.visit(node) } 866 | } 867 | 868 | override func visit(_ node: SwiftSyntax.GenericParameterClauseSyntax) { 869 | after[node.leftAngleBracket.id].openGroups += 1 870 | before[node.rightAngleBracket.id].closeGroups += 1 871 | visitChildren(node) { super.visit(node) } 872 | } 873 | 874 | override func visit(_ node: SwiftSyntax.ConformanceRequirementSyntax) { 875 | visitChildren(node) { super.visit(node) } 876 | } 877 | 878 | override func visit(_ node: SwiftSyntax.SimpleTypeIdentifierSyntax) { 879 | visitChildren(node) { super.visit(node) } 880 | } 881 | 882 | override func visit(_ node: SwiftSyntax.MemberTypeIdentifierSyntax) { 883 | visitChildren(node) { super.visit(node) } 884 | } 885 | 886 | override func visit(_ node: SwiftSyntax.ArrayTypeSyntax) { 887 | after[node.leftSquareBracket.id].openGroups += 1 888 | before[node.rightSquareBracket.id].closeGroups += 1 889 | visitChildren(node) { super.visit(node) } 890 | } 891 | 892 | override func visit(_ node: SwiftSyntax.DictionaryTypeSyntax) { 893 | after[node.leftSquareBracket.id].openGroups += 1 894 | before[node.rightSquareBracket.id].closeGroups += 1 895 | visitChildren(node) { super.visit(node) } 896 | } 897 | 898 | override func visit(_ node: SwiftSyntax.MetatypeTypeSyntax) { 899 | visitChildren(node) { super.visit(node) } 900 | } 901 | 902 | override func visit(_ node: SwiftSyntax.OptionalTypeSyntax) { 903 | visitChildren(node) { super.visit(node) } 904 | } 905 | 906 | override func visit(_ node: SwiftSyntax.ImplicitlyUnwrappedOptionalTypeSyntax) { 907 | visitChildren(node) { super.visit(node) } 908 | } 909 | 910 | override func visit(_ node: SwiftSyntax.CompositionTypeElementSyntax) { 911 | visitChildren(node) { super.visit(node) } 912 | } 913 | 914 | override func visit(_ node: SwiftSyntax.CompositionTypeSyntax) { 915 | visitChildren(node) { super.visit(node) } 916 | } 917 | 918 | override func visit(_ node: SwiftSyntax.TupleTypeElementSyntax) { 919 | visitChildren(node) { super.visit(node) } 920 | } 921 | 922 | override func visit(_ node: SwiftSyntax.TupleTypeSyntax) { 923 | after[node.leftParen.id].openGroups += 1 924 | before[node.rightParen.id].closeGroups += 1 925 | visitChildren(node) { super.visit(node) } 926 | } 927 | 928 | override func visit(_ node: SwiftSyntax.FunctionTypeSyntax) { 929 | after[node.leftParen.id].openGroups += 1 930 | before[node.rightParen.id].closeGroups += 1 931 | visitChildren(node) { super.visit(node) } 932 | } 933 | 934 | override func visit(_ node: SwiftSyntax.AttributedTypeSyntax) { 935 | visitChildren(node) { super.visit(node) } 936 | } 937 | 938 | override func visit(_ node: SwiftSyntax.GenericArgumentSyntax) { 939 | visitChildren(node) { super.visit(node) } 940 | } 941 | 942 | override func visit(_ node: SwiftSyntax.GenericArgumentClauseSyntax) { 943 | after[node.leftAngleBracket.id].openGroups += 1 944 | before[node.rightAngleBracket.id].closeGroups += 1 945 | visitChildren(node) { super.visit(node) } 946 | } 947 | 948 | override func visit(_ node: SwiftSyntax.TypeAnnotationSyntax) { 949 | visitChildren(node) { super.visit(node) } 950 | } 951 | 952 | override func visit(_ node: SwiftSyntax.EnumCasePatternSyntax) { 953 | visitChildren(node) { super.visit(node) } 954 | } 955 | 956 | override func visit(_ node: SwiftSyntax.IsTypePatternSyntax) { 957 | visitChildren(node) { super.visit(node) } 958 | } 959 | 960 | override func visit(_ node: SwiftSyntax.OptionalPatternSyntax) { 961 | visitChildren(node) { super.visit(node) } 962 | } 963 | 964 | override func visit(_ node: SwiftSyntax.IdentifierPatternSyntax) { 965 | visitChildren(node) { super.visit(node) } 966 | } 967 | 968 | override func visit(_ node: SwiftSyntax.AsTypePatternSyntax) { 969 | visitChildren(node) { super.visit(node) } 970 | } 971 | 972 | override func visit(_ node: SwiftSyntax.TuplePatternSyntax) { 973 | after[node.openParen.id].openGroups += 1 974 | before[node.closeParen.id].closeGroups += 1 975 | visitChildren(node) { super.visit(node) } 976 | } 977 | 978 | override func visit(_ node: SwiftSyntax.WildcardPatternSyntax) { 979 | visitChildren(node) { super.visit(node) } 980 | } 981 | 982 | override func visit(_ node: SwiftSyntax.TuplePatternElementSyntax) { 983 | visitChildren(node) { super.visit(node) } 984 | } 985 | 986 | override func visit(_ node: SwiftSyntax.ExpressionPatternSyntax) { 987 | visitChildren(node) { super.visit(node) } 988 | } 989 | 990 | override func visit(_ node: SwiftSyntax.ValueBindingPatternSyntax) { 991 | visitChildren(node) { super.visit(node) } 992 | } 993 | 994 | override func visit(_ tok: TokenSyntax) { 995 | apply(&before, to: tok) 996 | 997 | switch tok.tokenKind { 998 | case .rightParen, .rightBrace, .rightSquareBracket, .rightAngle: 999 | if ancestors.last!.syntax is UnknownStmtSyntax { closeGroup() } 1000 | 1001 | default: break 1002 | } 1003 | 1004 | // Inject mandatory whitespace where we would otherwise create long 1005 | // identifiers by jamming together things that should be separate. 1006 | if let p = previousToken, p.isIdentifierLike, tok.isIdentifierLike { 1007 | content.append(.whitespace) 1008 | } 1009 | 1010 | for t in tok.leadingTrivia { 1011 | inputLocation.traverse(t) 1012 | } 1013 | 1014 | let tokenLocation = inputLocation 1015 | inputLocation.traverseNonTrivia(tok) 1016 | #if false 1017 | /// Dump tokens and syntax 1018 | var endLocation = inputLocation 1019 | if endLocation.column > 0 { endLocation.column -= 1 } 1020 | print(""" 1021 | \(#file):\(tokenLocation)-\(endLocation):,\t\ 1022 | \(String(repeating: " ", count: nestingLevel)) \ 1023 | '\(tok.text)' \t\t -> \(ancestors) 1024 | """ 1025 | ) 1026 | #endif 1027 | content.append( 1028 | .token( 1029 | syntax: tok/*, 1030 | location: inputLocation, 1031 | ancestors: ancestors*/ 1032 | ) 1033 | ) 1034 | 1035 | for t in tok.trailingTrivia { 1036 | inputLocation.traverse(t) 1037 | } 1038 | 1039 | switch tok.tokenKind { 1040 | case .leftParen, .leftBrace, .leftSquareBracket, .leftAngle: 1041 | if ancestors.last!.syntax is UnknownStmtSyntax { openGroup() } 1042 | case .comma: 1043 | content.append(.whitespace) 1044 | default: break 1045 | } 1046 | 1047 | apply(&after, to: tok) 1048 | previousToken = tok 1049 | } 1050 | } 1051 | 1052 | let p = Reparser() 1053 | 1054 | // Parse a .swift file 1055 | let currentFile = URL(fileURLWithPath: #file) 1056 | do { 1057 | // let currentFileContents = try String(contentsOf: currentFile) 1058 | let parsed = try SourceFileSyntax.parse(currentFile) 1059 | p.visit(parsed) 1060 | } catch ParserError.swiftcFailed(let n, let message) { 1061 | print(message) 1062 | exit(n == 0 ? 1 : Int32(n)) 1063 | } 1064 | catch { 1065 | print(error) 1066 | exit(1) 1067 | } 1068 | 1069 | let indentSpaces = 4 1070 | let columnLimit = 70 1071 | 1072 | /// For each currently-open group, the indentation level of the line on which it 1073 | /// starts. 1074 | var groupIndentLevels = [0] 1075 | var lineBuffer = [OutputElement]() 1076 | var lineWidth = 0 1077 | /// The indentation at the beginning of this line 1078 | var bolIndentation = 0 1079 | /// The group nesting level at beginning of this line 1080 | var bolGrouping = groupIndentLevels.count 1081 | var whitespaceRequired = false 1082 | var lineUnmatchedIndices: [Int] = [] 1083 | 1084 | func outputLine() { 1085 | var b = String(repeating: " ", count: bolIndentation * indentSpaces) 1086 | var grouping = bolGrouping 1087 | 1088 | // flush through the first unmatched open grouping delimiter 1089 | let flushCount = lineUnmatchedIndices.first.map { $0 + 1 } ?? lineBuffer.count 1090 | for x in lineBuffer[.. bolGrouping { bolIndentation += 1 } 1119 | bolGrouping = grouping 1120 | whitespaceRequired = false 1121 | lineWidth = bolIndentation * indentSpaces 1122 | } 1123 | 1124 | func flushLineBuffer() { 1125 | while !lineBuffer.isEmpty { outputLine() } 1126 | } 1127 | 1128 | for x in p.content { 1129 | switch x { 1130 | case .openGroup: 1131 | lineUnmatchedIndices.append(lineBuffer.count) 1132 | lineBuffer.append(x) 1133 | case .closeGroup: 1134 | lineBuffer.append(x) 1135 | if !lineUnmatchedIndices.isEmpty { 1136 | lineUnmatchedIndices.removeLast() 1137 | } 1138 | if groupIndentLevels.count == bolGrouping { 1139 | flushLineBuffer() 1140 | } 1141 | case .whitespace: 1142 | if !lineBuffer.isEmpty { 1143 | whitespaceRequired = true 1144 | } 1145 | case .newline: 1146 | flushLineBuffer() 1147 | case .token(let t/*, _, _*/): 1148 | let s = whitespaceRequired ? 1 : 0 1149 | let w = t.text.count 1150 | if lineWidth + s + w > columnLimit { 1151 | outputLine() 1152 | } 1153 | else if whitespaceRequired { 1154 | lineBuffer.append(.whitespace) 1155 | lineWidth += 1 1156 | } 1157 | lineWidth += w 1158 | lineBuffer.append(x) 1159 | whitespaceRequired = false 1160 | } 1161 | } 1162 | flushLineBuffer() 1163 | --------------------------------------------------------------------------------