A tool for Swift code modification intermediating between code generation and formatting.

Overview

swift-mod

A tool for Swift code modification intermediating between code generation and formatting.

Swift5 Release Swift Package Manager CocoaPods CI Status Lincense


Overview

swift-mod is a tool for Swift code modification that intermediating between code generator and formatter built on top of apple/SwiftSyntax.
It can generates boilerplate code, such as access control or memberwise initializers in modularized source code, taking into account the state of the AST.
You can improve your productivity for writing more advanced Swift codes with introducing swift-mod.

Example

  • Before
struct Avenger {
    var heroName: String
    internal var realName: String?
}

let avengers = [
    Avenger(heroName: "Iron Man", realName: "Tony Stark"),
    Avenger(heroName: "Captain America", realName: "Steve Rogers"),
    Avenger(heroName: "Thor"),
]
  • After
+ public struct Avenger {
+     public var heroName: String
    internal var realName: String?

+     public init(
+         heroName: String,
+         realName: String? = nil
+     ) {
+         self.heroName = heroName
+         self.realName = realName
+     }
}

+ public let avengers = [
    Avenger(heroName: "Iron Man", realName: "Tony Stark"),
    Avenger(heroName: "Captain America", realName: "Steve Rogers"),
    Avenger(heroName: "Thor"),
]

Getting Started

  1. Install swift-mod.

  2. Generates configuration file.

swift-mod init
  1. Check the all modification rules.
swift-mod rules
swift-mod rules --detail [RULE IDENTIFIER] # Display more detailed rule description
  1. Edit your configuration file with an editor you like, refering to the documentation.

  2. Run

swift-mod

Command Usage

swift-mod [COMMAND] [OPTIONS]

All commands can be display a usage by option -h/--help.

  • run (or not specified): Modifies Swift source code by rules.

    OPTION SHORT USAGE
    --configuration -c The path to a configuration Yaml file
    --target -t The target name to be run partially
    --dry-run Run without actually changing any files
    --check Dry run that an error occurs if the any files should be changed
  • init: Generates a modify configuration file.

    OPTION SHORT USAGE
    --output -o Path where the modify configuration should be generated
  • rules: Display the list of rules and overview.

    OPTION SHORT USAGE
    --detail -d A rule identifier to displaying detailed description

Configuration

Modification rules and targets are defines with YAML-formatted file. By default, it's searched by name .swift-mod.yml.
Any file name is allowed with passing with option like follows:

swift-mod --configuration your-config-file.yml

Example

format:
  indent: 4
  lineBreakBeforeEachArgument: true
targets:
  main:
    paths:
      - "**/main.swift"
    excludedPaths:
      - Modules/
    rules:
      defaultAccessLevel:
        accessLevel: internal
        implicitInternal: true
  module:
    paths:
      - Modules/
    rules:
      defaultAccessLevel:
        accessLevel: openOrPublic
        implicitInternal: true
      defaultMemberwiseInitializer:
        enabled: true

Format

Determines the format setting in all rules.
Format according to this setting only when changes occur.

KEY VALUE REQUIREMENT DEFAULT
indent The number of spaces, or tab by text Optional 4
lineBreakBeforeEachArgument Indicating whether to insert new lines before each function argument Optional true

Targets

Defines the several targets by name key that defines different paths or rules to apply.
Glob paths are allowed for paths and excludedPaths.
Each target can runs partially by command with option like follows:

swift-mod --target [TARGET NAME]
KEY VALUE REQUIREMENT DEFAULT
paths The file names or paths to be applied rules. The directory is recursively lookup. Required
excludedPaths The file name or paths to be ecluded from resolved paths Optional None
rules The set of rules to be applied Required

Rules

Defines a modification rules enabled and its settings.
All rules are opt-in.
Rules where all settings are optional can specify only Boolean value indicating whether it's enabled by key enabled.

Default Access Level

IDENTIFIER OVERVIEW
defaultAccessLevel Assigns the suitable access level to all declaration syntaxes if not present
KEY VALUE REQUIREMENT DEFAULT
accessLevel |openOrPublic|public|internal|fileprivate|private| Required
implicitInternal Indicating whether to omit the internal access level Optional true
struct Avenger {
    var heroName: String
    internal var realName: String?
}
+ public struct Avenger {
+    public var heroName: String
    internal var realName: String?
}

Default Memberwise Initializer

IDENTIFIER OVERVIEW
defaultMemberwiseInitializer Defines a memberwise initializer according to the access level in the type declaration if not present
KEY VALUE REQUIREMENT DEFAULT
implicitInitializer Indicating whether to omit the internal initializer in struct decalaration Optional false
implicitInternal Indicating whether to omit the internal access level Optional true
ignoreClassesWithInheritance Indicating whether to skip the classes having inheritance including protocol Optional false
struct Avenger {
    var heroName: String
    internal var realName: String?
}
struct Avenger {
    var heroName: String
    internal var realName: String?

+    init(
+        heroName: String,
+        realName: String? = nil
+    ) {
+        self.heroName = heroName
+        self.realName = realName
+    }
}

Ignoring Rules

swift-mod allows users to suppress modification for node and its children by comment like below.

  • Ignore all rules

// swift-mod-ignore

// swift-mod-ignore
struct Avenger {
    var heroName: String
    internal var realName: String?
}
  • Ignore specific rule(s)

// swift-mod-ignore: [COMMA DELIMITED RULE IDENTIFIERS]

// swift-mod-ignore: defaultAccessLevel, defaultMemberwiseInitializer
struct Avenger {
    var heroName: String
    internal var realName: String?
}

Installation

swift-mod doesn't support HomeBrew because it's hard to keep backward compatibility due to depended on the version of Swift toolchain you are using.

Using Swift Package Manager

Add the following to the dependencies of your Package.swift:

dependencies: [
    .package(url: "https://github.com/ra1028/swift-mod.git", from: "swift-mod version"),
]

Run command:

swift run -c release swift-mod [COMMAND] [OPTIONS]

Using Mint

Install with Mint by following command:

mint install ra1028/swift-mod

Run command:

mint run ra1028/swift-mod [COMMAND] [OPTIONS]

Using CocoaPods

Add the following to your Podfile:

pod 'swift-mod'

Run command:

Pods/swift-mod/swift-mod [COMMAND] [OPTIONS]

* If you have changed the name of Xcode.app used in toolchain (xcode-select -p), swift-mod via CocoaPods can't be excuted. Please set the Xcode name to Xcode.app. (See: https://forums.swift.org/t/swiftsyntax-with-swift-5-1/29051)

Swift Version Support

swift-mod depends on SwiftSyntax that the version in use must match the toolchain version.
So you should use swift-mod version that built with compatible version of Swift you are using.

Swift Version Last Supported swift-mod Release
5.1 0.0.2
5.2 latest

Issue on macOS Before 10.14.4

Swift tool binary that works with static-stdlib can't running on macOS before 10.14.4.
You need to update macOS or install the Swift 5 Runtime Support for Command Line Tools.


Development

Pull requests, bug reports and feature requests are welcome πŸš€ .
See CONTRIBUTING.md file to learn how to contribute to swift-mod.

Please validate and test your code before you submit your changes by following commands:

 make autocorrect # Modifying, formatting, linting codes and generating Linux XCTest manifests.  
 make test

In addition, swift-mod supports running on Linux, so you should test by installing Docker and following command:

make docker-test

Known Issue

Currently, swift-mod doesn't works properly with builds in debug configuration.
It may due to stack overflow with tail recursion in the method that enumerating the Swift file paths.
swift-mod works with optimizing tail recursion by builds in release configuration.


License

swift-mod is released under the Apache 2.0 License.

Comments
  • Update swift-syntax version which compatible with Swift5.4

    Update swift-syntax version which compatible with Swift5.4

    Checklist

    • [x] All tests are passed.
    • [ ] Added tests.
    • [x] Searched existing issues to make sure not duplicated.

    Motivation and Context

    To use this with Xcode12.5.1, swift-syntax version should be updated to compatible one.

    Description

    • Update swift-syntax version which compatible with Swift5.4

    Related Issue

    Impact on Existing Code

    opened by kagemiku 3
  • Bump cocoapods-downloader from 1.5.1 to 1.6.3

    Bump cocoapods-downloader from 1.5.1 to 1.6.3

    Bumps cocoapods-downloader from 1.5.1 to 1.6.3.

    Release notes

    Sourced from cocoapods-downloader's releases.

    1.6.3

    Enhancements
    • None.
    Bug Fixes
    • None.

    1.6.2

    Enhancements
    • None.
    Bug Fixes
    • None.

    1.6.1

    Enhancements
    • None.
    Bug Fixes
    • None.

    1.6.0

    Enhancements
    • None.
    Bug Fixes
    • Adds a check for command injections in the input for hg and git.
      orta #124
    Changelog

    Sourced from cocoapods-downloader's changelog.

    1.6.3 (2022-04-01)

    Enhancements
    • None.
    Bug Fixes
    • None.

    1.6.2 (2022-03-28)

    Enhancements
    • None.
    Bug Fixes
    • None.

    1.6.1 (2022-03-23)

    Enhancements
    • None.
    Bug Fixes
    • None.

    1.6.0 (2022-03-22)

    Enhancements
    • None.
    Bug Fixes
    • Adds a check for command injections in the input for hg and git.
      orta #124
    Commits
    • c03e2ed Release 1.6.3
    • f75bccc Disable Bazaar tests due to macOS 12.3 not including python2
    • 52a0d54 Merge pull request #128 from CocoaPods/validate_before_dl
    • d27c983 Ensure that the git pre-processor doesn't accidentally bail also
    • 3adfe1f [CHANGELOG] Add empty Master section
    • 591167a Release 1.6.2
    • d2564c3 Merge pull request #127 from CocoaPods/validate_before_dl
    • 99fec61 Switches where we check for invalid input, to move it inside the download fun...
    • 96679f2 [CHANGELOG] Add empty Master section
    • 3a7c54b Release 1.6.1
    • Additional commits viewable in compare view

    Dependabot compatibility score

    Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting @dependabot rebase.


    Dependabot commands and options

    You can trigger Dependabot actions by commenting on this PR:

    • @dependabot rebase will rebase this PR
    • @dependabot recreate will recreate this PR, overwriting any edits that have been made to it
    • @dependabot merge will merge this PR after your CI passes on it
    • @dependabot squash and merge will squash and merge this PR after your CI passes on it
    • @dependabot cancel merge will cancel a previously requested merge and block automerging
    • @dependabot reopen will reopen this PR if it is closed
    • @dependabot close will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually
    • @dependabot ignore this major version will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself)
    • @dependabot ignore this minor version will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself)
    • @dependabot ignore this dependency will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
    • @dependabot use these labels will set the current labels as the default for future PRs for this repo and language
    • @dependabot use these reviewers will set the current reviewers as the default for future PRs for this repo and language
    • @dependabot use these assignees will set the current assignees as the default for future PRs for this repo and language
    • @dependabot use this milestone will set the current milestone as the default for future PRs for this repo and language

    You can disable automated security fix PRs for this repo from the Security Alerts page.

    dependencies 
    opened by dependabot[bot] 2
  • Updates for Xcode 14

    Updates for Xcode 14

    Checklist

    • [x] All tests are passed.
    • [ ] Added tests.
    • [x] Searched existing issues to make sure not duplicated.

    Motivation and Context

    Description

    Related Issue

    Impact on Existing Code

    opened by thii 0
  • chore: Drop support for CocoaPods

    chore: Drop support for CocoaPods

    Checklist

    • [x] All tests are passed.
    • [x] Added tests.
    • [x] Searched existing issues to make sure not duplicated.

    Description

    Stop supporting CocoaPods for maintenance ease.

    opened by ra1028 0
  • feat: Support filelist parameter via command line

    feat: Support filelist parameter via command line

    Checklist

    • [x] All tests are passed.
    • [x] Added tests.
    • [x] Searched existing issues to make sure not duplicated.

    Description

    • Support for specifying an input file list from the command line.
    • Drop support to configure input files with configuration.
    • Re-structure the configuration file.
    • Re-write command line with swift-argument-parser
    opened by ra1028 0
  • Add @loader_path to rpaths

    Add @loader_path to rpaths

    Checklist

    • [x] All tests are passed.
    • [ ] Added tests.
    • [x] Searched existing issues to make sure not duplicated.

    Motivation and Context

    This makes the tool searchs for lib_InternalSwiftSyntaxParser.dylib in the current directory first.

    opened by thii 0
  • Package lib_InternalSwiftSyntaxParser.dylib with the tool binary

    Package lib_InternalSwiftSyntaxParser.dylib with the tool binary

    Checklist

    • [x] All tests are passed.
    • [ ] Added tests.
    • [x] Searched existing issues to make sure not duplicated.

    Motivation and Context

    This allows tool consumers to use it independently with Xcode path.

    Also make the release binary a universal binary.

    opened by thii 0
  • chore: Update version file

    chore: Update version file

    Checklist

    • [x] All tests are passed.
    • [ ] Added tests.
    • [x] Searched existing issues to make sure not duplicated.

    Motivation and Context

    Description

    Related Issue

    Impact on Existing Code

    opened by ra1028 0
  • Swift5 2

    Swift5 2

    Checklist

    • [x] All tests are passed.
    • [x] Added tests.
    • [x] Searched existing issues to make sure not duplicated.

    Description

    • Swift 5.2 migration
    • Allow ignoring class implicit (synthesized) initializer

    Related Issue

    N/A

    Impact on Existing Code

    • Swift 5.1 is now supported lower or equal tag 0.0.2
    • if implicitInitializer is true
      class Class {}
      

      before

      class Class {
           init() {}
      }
      

      after

      class Class {}
      
    opened by ra1028 0
  • Fix rpath of the binary installed via CocoaPods

    Fix rpath of the binary installed via CocoaPods

    Checklist

    • [ ] All tests are passed.
    • [ ] Added tests.
    • [x] Searched existing issues to make sure not duplicated.

    Motivation and Context

    Fix a bug that can't execute swift-mod installed via CocoaPods.

    Description

    Fix rpath of the binary installed via CocoaPods. rpath is checked by command otool -l [BIN]. The name of Xcode.app in toolchain path had changed in my local machine and CI environment.

    SeeAlso: https://forums.swift.org/t/swiftsyntax-with-swift-5-1/29051

    opened by ra1028 0
  • Remove swift-format from main Package.swift

    Remove swift-format from main Package.swift

    Checklist

    • [x] All tests are passed.
    • [ ] Added tests.
    • [x] Searched existing issues to make sure not duplicated.

    Description

    Fix install failure with SPM.

    opened by ra1028 0
Releases(0.1.1)
Owner
Ryo Aoyama
β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘ β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–€β–„β–‘β–‘β–‘β–„β–€β–‘β–‘β–‘β–‘β–‘β–‘β–‘ β–‘β–‘β–‘β–‘β–‘β–„β–ˆβ–€β–ˆβ–ˆβ–ˆβ–€β–ˆβ–„β–‘β–‘β–‘β–‘β–‘ β–‘β–‘β–‘β–ˆβ–€β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–€β–ˆβ–‘β–‘β–‘ β–‘β–‘β–‘β–ˆβ–‘β–ˆβ–€β–€β–€β–€β–€β–€β–€β–ˆβ–‘β–ˆβ–‘β–‘β–‘ β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–€β–€β–‘β–‘β–‘β–€β–€β–‘β–‘β–‘β–‘β–‘β–‘β–‘ β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘
Ryo Aoyama
A static source code analysis tool to improve quality and reduce defects for C, C++ and Objective-C

OCLint - https://oclint.org OCLint is a static code analysis tool for improving quality and reducing defects by inspecting C, C++ and Objective-C code

The OCLint Static Code Analysis Tool 3.6k Dec 29, 2022
decoupling between modules in your iOS Project. iOSζ¨‘ε—εŒ–θΏ‡η¨‹δΈ­ζ¨‘ε—ι—΄θ§£θ€¦ζ–Ήζ‘ˆ

DecouplingKit δΈ­ζ–‡readme Podfile platform :ios, '7.0' pod 'DecouplingKit', '~> 0.0.2' DecouplingKit, decoupling between modules in your iOS Project. D

coderyi 139 Aug 23, 2022
A tool to enforce Swift style and conventions.

SwiftLint A tool to enforce Swift style and conventions, loosely based on the now archived GitHub Swift Style Guide. SwiftLint enforces the style guid

Realm 16.9k Jan 9, 2023
Simple iOS app blackbox assessment tool. Powered by frida.re and vuejs.

Discontinued Project This project has been discontinued. Please use the new Grapefruit #74 frida@14 compatibility issues frida@14 introduces lots of b

Chaitin Tech 1.6k Dec 16, 2022
A linter tool for Interface Builder

IBLinter A linter tool to normalize .xib and .storyboard files. Inspired by realm/SwiftLint Installation Using Homebrew $ brew install iblinter Using

IBDecodable 945 Nov 11, 2022
iOS tool that helps with profiling iOS Memory usage.

FBMemoryProfiler An iOS library providing developer tools for browsing objects in memory over time, using FBAllocationTracker and FBRetainCycleDetecto

Facebook Archive 3.4k Dec 7, 2022
Measure Swift code metrics and get reports in Xcode, Jenkins and other CI platforms.

Taylor ⚠️ Taylor is DEPRECATED. Use SwiftLint instead. A tool aimed to increase Swift code quality, by checking for conformance to code metrics. Taylo

YOPESO 301 Dec 24, 2022
An Xcode formatter plug-in to format your swift code.

Swimat Swimat is an Xcode plug-in to format your Swift code. Preview Installation There are three way to install. Install via homebrew-cask # Homebrew

Jintin 1.6k Jan 7, 2023
SwiftCop is a validation library fully written in Swift and inspired by the clarity of Ruby On Rails Active Record validations.

SwiftCop is a validation library fully written in Swift and inspired by the clarity of Ruby On Rails Active Record validations. Objective Build a stan

Andres Canal 542 Sep 17, 2022
Cross-platform static analyzer and linter for Swift.

Wiki β€’ Installation β€’ Usage β€’ Features β€’ Developers β€’ License Tailor is a cross-platform static analysis and lint tool for source code written in Appl

Sleekbyte 1.4k Dec 19, 2022
Type-safe observable values and collections in Swift

GlueKit ⚠️ WARNING ⚠️ This project is in a prerelease state. There is active work going on that will result in API changes that can/will break code wh

null 361 Oct 12, 2022
Trackable is a simple analytics integration helper library. It’s especially designed for easy and comfortable integration with existing projects.

Trackable Trackable is a simple analytics integration helper library. It’s especially designed for easy and comfortable integration with existing proj

Vojta Stavik 145 Apr 14, 2022
Makes it easier to support older versions of iOS by fixing things and adding missing methods

PSTModernizer PSTModernizer carefully applies patches to UIKit and related Apple frameworks to fix known radars with the least impact. The current set

PSPDFKit Labs 217 Aug 9, 2022
Find common xib and storyboard-related problems without running your app or writing unit tests.

IBAnalyzer Find common xib and storyboard-related problems without running your app or writing unit tests. Usage Pass a path to your project to ibanal

Arek Holko 955 Oct 15, 2022
Skredvarsel app - an iOS, iPadOS, and macOS application that provides daily avalanche warnings from the Norwegian Avalanche Warning Service API

Skredvarsel (Avalanche warning) app is an iOS, iPadOS, and macOS application that provides daily avalanche warnings from the Norwegian Avalanche Warning Service API

Jonas FollesΓΈ 8 Dec 15, 2022
Exclude files and folders from Alfred’s search results

Ignore in Alfred Alfred Workflow Exclude files and folders from Alfred’s search results – Download Workflow About The macOS metadata search API only a

Alfred 10 Dec 13, 2022
Lint anything by combining the power of Swift & regular expressions.

Installation β€’ Getting Started β€’ Configuration β€’ Xcode Build Script β€’ Donation β€’ Issues β€’ Regex Cheat Sheet β€’ License AnyLint Lint any project in any

Flinesoft 116 Sep 24, 2022
πŸ’Š Syntactic sugar for Swift do-try-catch

Fallback Syntactic sugar for Swift do-try-catch. At a Glance value = try fallback( try get("A"), try get("B"), try get("C"), try get("D") ) is

Suyeol Jeon 43 May 25, 2020
A Swift micro-framework to easily deal with weak references to self inside closures

WeakableSelf Context Closures are one of Swift must-have features, and Swift developers are aware of how tricky they can be when they capture the refe

Vincent Pradeilles 72 Sep 1, 2022