Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/inamiy/SwiftRewriter
π Swift code formatter using SwiftSyntax.
https://github.com/inamiy/SwiftRewriter
code-formatter swift swiftsyntax
Last synced: 6 days ago
JSON representation
π Swift code formatter using SwiftSyntax.
- Host: GitHub
- URL: https://github.com/inamiy/SwiftRewriter
- Owner: inamiy
- License: mit
- Created: 2018-12-11T00:00:21.000Z (almost 6 years ago)
- Default Branch: master
- Last Pushed: 2019-10-16T13:58:37.000Z (about 5 years ago)
- Last Synced: 2024-10-15T21:08:02.391Z (26 days ago)
- Topics: code-formatter, swift, swiftsyntax
- Language: Swift
- Homepage:
- Size: 125 KB
- Stars: 825
- Watchers: 19
- Forks: 28
- Open Issues: 7
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
# π SwiftRewriter
[![Swift 5.1](https://img.shields.io/badge/swift-5.1-orange.svg?style=flat)](https://swift.org/download/)
[![Build Status](https://travis-ci.org/inamiy/SwiftRewriter.svg?branch=master)](https://travis-ci.org/inamiy/SwiftRewriter)Swift code formatter using [SwiftSyntax](https://github.com/apple/swift-syntax).
**Requirements:** Swift 5.1 (Xcode 11.0) + SwiftSyntax 0.50100.0
See also my [iOSConf SG 2019](https://2019.iosconf.sg) talk for more detail:
- Slide: [Making your own Code Formatter in Swift \- Speaker Deck](https://speakerdeck.com/inamiy/making-your-own-code-formatter-in-swift)
- 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/)## Overview
1. **`SwiftRewriter`**: Collection of reusable & composable `SyntaxRewriter`s
2. **`swift-rewriter`**: Simple command-line executable## How to use
```bash
$ swift build
$ swift run swift-rewriter helpAvailable commands:
help Display general or command-specific help
print-ast print AST from file or string
run Auto-correct code in the file or directory# Auto-correct code in the directory
$ swift run swift-rewriter run --path /path/to/file-or-directory
```### Configuration
In `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).
- [rewriter.swift](Sources/swift-rewriter/rewriter.swift)
Please change the configuration as you like (you can make your own rewriter and combine!), and `swift build & run`.
```swift
// rewriter.swiftimport SwiftRewriter
var rewriter: Rewriter {
// Comment
HeaderCopyrightTrimmer()// Move
>>> ImportSorter()
// >>> ExtensionIniter() // not useful for everyone// Token
>>> DecimalLiteralUnderscorer()
>>> SemicolonTrimmer()// Newline (whitespace)
// >>> ExtraNewliner() // not useful for everyone
>>> ElseNewliner(newline: false)
>>> MethodChainNewliner()// Indent (whitespace)
>>> Indenter(.init(
perIndent: .spaces(4),
shouldIndentSwitchCase: false,
shouldIndentIfConfig: false,
skipsCommentedLine: true
))// Space (whitespace)
// >>> ExtraSpaceTrimmer() // may disturb manually-aligned code>>> ColonSpacer(spaceBefore: false, spaceAfter: true)
>>> TernaryExprSpacer()
>>> BinaryOperatorSpacer(spacesAround: true)// Ignore to not distrub user-aligned multiple assignments
// TODO: Improve multiple assignment alignment
// >>> EqualSpacer(spacesAround: true)>>> ArrowSpacer(spaceBefore: true, spaceAfter: true)
>>> LeftBraceSpacer(spaceBefore: true)
>>> LeftParenSpacer(spaceBefore: true)
>>> TrailingSpaceTrimmer()
}
```## `Rewriter` examples
### `Indenter`
#### Better right-brace position
```diff
@@ β1,6 +1,6 @@
βlets
β .code {
β }
β .format {
-} // this!!!
+ } // this!!!
```P.S. This is the primary goal of making `SwiftRewriter`.
#### First-item-aware indent
```swift
struct Foo {
init(bool: Bool,
int: Int) {
self.bool = bool
if true {
print()
}run { x in
print(x,
y,
z)
}
}
}
```will be:
```swift
struct Foo {
init(bool: Bool,
int: Int) {
self.bool = bool
if true {
print()
}run { x in
print(x,
y,
z)
}
}
}
```### `HeaderCopyrightTrimmer`
```diff
@@ β1,10 +1,2 @@
-//
-// example.swift
-// SwiftRewriter
-//
-// Created by Yasuhiro Inami on 2018-12-09.
-// Copyright Β© 2018 Yasuhiro Inami. All rights reserved.
-//
-
β// All your code are belong to us.
```### `ImportSorter`
```swift
import C
import Bfunc foo() {}
import A
import D
```will be:
```swift
import A
import B
import C
import Dfunc foo() {}
```### `ExtensionIniter`
This rewriter moves the code to enable `struct`'s [memberwise initializer](https://docs.swift.org/swift-book/LanguageGuide/Initialization.html).
```swift
struct Foo {
let int: Int
init(int: Int) {
self.int = int
}
init() {
self.int = 0
}
}
``````diff
@@ β1,9 +1,12 @@
βstruct Foo {
β let int: Int
+}
+
+extension Foo {
β init(int: Int) {
β self.int = int
β }
β init() {
β self.int = 0
β }
β}
```### `ExtraNewliner` **(Work in Progress)**
This rewriter adds a newline when code is too dense.
```swift
import Foundation
var computed1: Int = 1
var computed2: Int = { return 2 }
/// doc
var computed3: Int = { return 3 }
/// doc
var computedBlock: String {
return ""
}
func send() -> Observable {
return apiSession
.send(request)
.do(onError: { [weak self] error in
guard let me = self else { return }
me.doSomething()
})
.do(onError: { [weak self] error in
guard let me = self else { return }
me.doSomething()
me.doSomething()
})
}
```will be:
```swift
import Foundationvar computed1: Int = 1
var computed2: Int = { return 2 }/// doc
var computed3: Int = { return 3 }/// doc
var computedBlock: String {
return ""
}func send() -> Observable {
return apiSession
.send(request)
.do(onError: { [weak self] error in
guard let me = self else { return }
me.doSomething()
})
.do(onError: { [weak self] error in
guard let me = self else { return }me.doSomething()
me.doSomething()
})
}
```## Roadmap / TODO
- [ ] Add configuration file support
- [ ] Automatic code folding
- [ ] Move properties above method (for "states" readability)
- [ ] Move inner types to `extension` scope (for "states" readability)
- [ ] Align multiline `=` assignments
- [ ] \(Your idea comes here π‘\)## Acknowledgement
- [Improving Swift Tools with libSyntax](https://academy.realm.io/posts/improving-swift-tools-with-libsyntax-try-swift-haskin-2017/) by @harlanhaskins
- [Creating Refactoring Transformations for Swift](https://www.skilled.io/u/swiftsummit/creating-refactoring-transformations-for-swift) by @nkcsgexi
- [try! Swift Tokyo 2018 - AST Meta-programming](https://www.youtube.com/watch?v=XG3yxw8lRJc) by @kishikawakatsumi
- [swiftfmt](https://github.com/kishikawakatsumi/swiftfmt)
- [swift-ast-explorer-playground](https://github.com/kishikawakatsumi/swift-ast-explorer-playground)
- [SwiftSyntax - NSHipster](https://nshipster.com/swiftsyntax/) by @mattt
- [SwiftLint](https://github.com/realm/SwiftLint) and [SwiftSyntax benchmarking](https://twitter.com/simjp/status/1066572820715462658) by @jpsim et al.
- [Evaluating SwiftSyntax for use in SwiftLint - JP Simard - Swift Developer](https://www.jpsim.com/evaluating-swiftsyntax-for-use-in-swiftlint/)
- [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)## License
[MIT](LICENSE)