{"id":17146192,"url":"https://github.com/inamiy/swiftrewriter","last_synced_at":"2025-04-04T18:06:16.223Z","repository":{"id":63912172,"uuid":"161252402","full_name":"inamiy/SwiftRewriter","owner":"inamiy","description":"📝 Swift code formatter using SwiftSyntax.","archived":false,"fork":false,"pushed_at":"2019-10-16T13:58:37.000Z","size":128,"stargazers_count":825,"open_issues_count":7,"forks_count":28,"subscribers_count":19,"default_branch":"master","last_synced_at":"2024-10-15T21:08:02.391Z","etag":null,"topics":["code-formatter","swift","swiftsyntax"],"latest_commit_sha":null,"homepage":"","language":"Swift","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/inamiy.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2018-12-11T00:00:21.000Z","updated_at":"2024-08-30T07:41:13.000Z","dependencies_parsed_at":"2023-01-14T13:15:35.721Z","dependency_job_id":null,"html_url":"https://github.com/inamiy/SwiftRewriter","commit_stats":null,"previous_names":[],"tags_count":3,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/inamiy%2FSwiftRewriter","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/inamiy%2FSwiftRewriter/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/inamiy%2FSwiftRewriter/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/inamiy%2FSwiftRewriter/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/inamiy","download_url":"https://codeload.github.com/inamiy/SwiftRewriter/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247226213,"owners_count":20904465,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["code-formatter","swift","swiftsyntax"],"created_at":"2024-10-14T21:08:03.589Z","updated_at":"2025-04-04T18:06:16.207Z","avatar_url":"https://github.com/inamiy.png","language":"Swift","readme":"# 📝 SwiftRewriter\n\n[![Swift 5.1](https://img.shields.io/badge/swift-5.1-orange.svg?style=flat)](https://swift.org/download/)\n[![Build Status](https://travis-ci.org/inamiy/SwiftRewriter.svg?branch=master)](https://travis-ci.org/inamiy/SwiftRewriter)\n\nSwift code formatter using [SwiftSyntax](https://github.com/apple/swift-syntax).\n\n**Requirements:** Swift 5.1 (Xcode 11.0) + SwiftSyntax 0.50100.0\n\nSee also my [iOSConf SG 2019](https://2019.iosconf.sg) talk for more detail:\n\n- Slide: [Making your own Code Formatter in Swift \\- Speaker Deck](https://speakerdeck.com/inamiy/making-your-own-code-formatter-in-swift)\n- Video: [Make your own code formatter in Swift – iOS Conf SG 2019 – Learn Talks](https://learntalks.com/2019/01/make-your-own-code-formatter-in-swift-ios-conf-sg-2019/)\n\n## Overview\n\n1. **`SwiftRewriter`**: Collection of reusable \u0026 composable `SyntaxRewriter`s\n2. **`swift-rewriter`**: Simple command-line executable\n\n## How to use\n\n```bash\n$ swift build\n$ swift run swift-rewriter help\n\nAvailable commands:\n\n   help        Display general or command-specific help\n   print-ast   print AST from file or string\n   run         Auto-correct code in the file or directory\n\n# Auto-correct code in the directory\n$ swift run swift-rewriter run --path /path/to/file-or-directory\n```\n\n### Configuration\n\nIn `swift-rewriter` CLI tool, rewriting rules are configured in [rewriter.swift](Sources/swift-rewriter/rewriter.swift) (configuration file e.g. yaml or json is not supported yet).\n\n- [rewriter.swift](Sources/swift-rewriter/rewriter.swift)\n\nPlease change the configuration as you like (you can make your own rewriter and combine!), and `swift build \u0026 run`.\n\n```swift\n// rewriter.swift\n\nimport SwiftRewriter\n\nvar rewriter: Rewriter {\n    // Comment\n    HeaderCopyrightTrimmer()\n\n        // Move\n        \u003e\u003e\u003e ImportSorter()\n//        \u003e\u003e\u003e ExtensionIniter() // not useful for everyone\n\n        // Token\n        \u003e\u003e\u003e DecimalLiteralUnderscorer()\n        \u003e\u003e\u003e SemicolonTrimmer()\n\n        // Newline (whitespace)\n//        \u003e\u003e\u003e ExtraNewliner()   // not useful for everyone\n        \u003e\u003e\u003e ElseNewliner(newline: false)\n        \u003e\u003e\u003e MethodChainNewliner()\n\n        // Indent (whitespace)\n        \u003e\u003e\u003e Indenter(.init(\n            perIndent: .spaces(4),\n            shouldIndentSwitchCase: false,\n            shouldIndentIfConfig: false,\n            skipsCommentedLine: true\n            ))\n\n        // Space (whitespace)\n//        \u003e\u003e\u003e ExtraSpaceTrimmer()   // may disturb manually-aligned code\n\n        \u003e\u003e\u003e ColonSpacer(spaceBefore: false, spaceAfter: true)\n        \u003e\u003e\u003e TernaryExprSpacer()\n        \u003e\u003e\u003e BinaryOperatorSpacer(spacesAround: true)\n\n        // Ignore to not distrub user-aligned multiple assignments\n        // TODO: Improve multiple assignment alignment\n//        \u003e\u003e\u003e EqualSpacer(spacesAround: true)\n\n        \u003e\u003e\u003e ArrowSpacer(spaceBefore: true, spaceAfter: true)\n        \u003e\u003e\u003e LeftBraceSpacer(spaceBefore: true)\n        \u003e\u003e\u003e LeftParenSpacer(spaceBefore: true)\n        \u003e\u003e\u003e TrailingSpaceTrimmer()\n}\n```\n\n## `Rewriter` examples\n\n### `Indenter`\n\n#### Better right-brace position\n\n```diff\n@@ −1,6 +1,6 @@\n lets\n     .code {\n     }\n     .format {\n-} // this!!!\n+    } // this!!!\n```\n\nP.S. This is the primary goal of making `SwiftRewriter`.\n\n#### First-item-aware indent\n\n```swift\n    struct Foo {\n                         init(bool: Bool,\n              int: Int) {\n                              self.bool = bool\n                           if true {\n                     print()\n                  }\n\n                   run { x in\n                            print(x,\n                                      y,\n                                          z)\n                }\n                        }\n            }\n```\n\nwill be:\n\n```swift\nstruct Foo {\n    init(bool: Bool,\n         int: Int) {\n        self.bool = bool\n        if true {\n            print()\n        }\n\n        run { x in\n            print(x,\n                  y,\n                  z)\n        }\n    }\n}\n```\n\n### `HeaderCopyrightTrimmer`\n\n```diff\n@@ −1,10 +1,2 @@\n-//\n-//  example.swift\n-//  SwiftRewriter\n-//\n-//  Created by Yasuhiro Inami on 2018-12-09.\n-//  Copyright © 2018 Yasuhiro Inami. All rights reserved.\n-//\n-\n // All your code are belong to us.\n```\n\n### `ImportSorter`\n\n```swift\nimport C\nimport B\n\nfunc foo() {}\n\nimport A\nimport D\n```\n\nwill be:\n\n```swift\nimport A\nimport B\nimport C\nimport D\n\nfunc foo() {}\n```\n\n### `ExtensionIniter`\n\nThis rewriter moves the code to enable `struct`'s [memberwise initializer](https://docs.swift.org/swift-book/LanguageGuide/Initialization.html).\n\n```swift\nstruct Foo {\n    let int: Int\n    init(int: Int) {\n        self.int = int\n    }\n    init() {\n        self.int = 0\n    }\n}\n```\n\n```diff\n@@ −1,9 +1,12 @@\n struct Foo {\n     let int: Int\n+}\n+\n+extension Foo {\n     init(int: Int) {\n         self.int = int\n     }\n     init() {\n         self.int = 0\n     }\n }\n```\n\n### `ExtraNewliner` **(Work in Progress)**\n\nThis rewriter adds a newline when code is too dense.\n\n```swift\nimport Foundation\nvar computed1: Int = 1\nvar computed2: Int = { return 2 }\n/// doc\nvar computed3: Int = { return 3 }\n/// doc\nvar computedBlock: String {\n    return \"\"\n}\nfunc send() -\u003e Observable\u003cVoid\u003e {\n    return apiSession\n        .send(request)\n        .do(onError: { [weak self] error in\n            guard let me = self else { return }\n            me.doSomething()\n        })\n        .do(onError: { [weak self] error in\n            guard let me = self else { return }\n            me.doSomething()\n            me.doSomething()\n        })\n}\n```\n\nwill be:\n\n```swift\nimport Foundation\n\nvar computed1: Int = 1\nvar computed2: Int = { return 2 }\n\n/// doc\nvar computed3: Int = { return 3 }\n\n/// doc\nvar computedBlock: String {\n    return \"\"\n}\n\nfunc send() -\u003e Observable\u003cVoid\u003e {\n    return apiSession\n        .send(request)\n        .do(onError: { [weak self] error in\n            guard let me = self else { return }\n            me.doSomething()\n        })\n        .do(onError: { [weak self] error in\n            guard let me = self else { return }\n\n            me.doSomething()\n            me.doSomething()\n        })\n}\n```\n\n## Roadmap / TODO\n\n- [ ] Add configuration file support\n- [ ] Automatic code folding\n- [ ] Move properties above method (for \"states\" readability)\n- [ ] Move inner types to `extension` scope (for \"states\" readability)\n- [ ] Align multiline `=` assignments\n- [ ] \\(Your idea comes here 💡\\)\n\n## Acknowledgement\n\n- [Improving Swift Tools with libSyntax](https://academy.realm.io/posts/improving-swift-tools-with-libsyntax-try-swift-haskin-2017/) by @harlanhaskins\n- [Creating Refactoring Transformations for Swift](https://www.skilled.io/u/swiftsummit/creating-refactoring-transformations-for-swift) by @nkcsgexi\n- [try! Swift Tokyo 2018 - AST Meta-programming](https://www.youtube.com/watch?v=XG3yxw8lRJc) by @kishikawakatsumi\n\t- [swiftfmt](https://github.com/kishikawakatsumi/swiftfmt)\n\t- [swift-ast-explorer-playground](https://github.com/kishikawakatsumi/swift-ast-explorer-playground)\n- [SwiftSyntax - NSHipster](https://nshipster.com/swiftsyntax/) by @mattt\n- [SwiftLint](https://github.com/realm/SwiftLint) and [SwiftSyntax benchmarking](https://twitter.com/simjp/status/1066572820715462658) by @jpsim et al.\n\t- [Evaluating SwiftSyntax for use in SwiftLint - JP Simard - Swift Developer](https://www.jpsim.com/evaluating-swiftsyntax-for-use-in-swiftlint/)\n\t- [Speeding up SwiftSyntax by using the parser directly - Development / Compiler - Swift Forums](https://forums.swift.org/t/speeding-up-swiftsyntax-by-using-the-parser-directly/18493)\n\n## License\n\n[MIT](LICENSE)\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Finamiy%2Fswiftrewriter","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Finamiy%2Fswiftrewriter","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Finamiy%2Fswiftrewriter/lists"}