Server-Side Swift Vaporでrealm/SwiftLintを導入する

Last Updated on 2024年5月19日 by lemonade

概要

今までapple/swift-formatを使用してformatterだけ入れていたのですが、強いLinterも最近欲しくなってきたので探したところ、realm/SwiftLintが良さそうとなりました。

この記事では、realm/SwiftLintをSwift Package Managerのプロジェクトでのインストール方法を紹介します。

手順

SPMのdependenciesにSwiftLintを入れる

// swift-tools-version:5.10
import PackageDescription

let package = Package(
    name: "event-sourcing-api-design",
    platforms: [
       .macOS(.v13)
    ],
    dependencies: [
        // 💧 A server-side Swift web framework.
        .package(url: "https://github.com/vapor/vapor.git", from: "4.99.3"),
        // 🗄 An ORM for SQL and NoSQL databases.
        .package(url: "https://github.com/vapor/fluent.git", from: "4.9.0"),
        // 🐘 Fluent driver for Postgres.
        .package(url: "https://github.com/vapor/fluent-postgres-driver.git", from: "2.8.0"),
        // 🔵 Non-blocking, event-driven networking for Swift. Used for custom executors
        .package(url: "https://github.com/apple/swift-nio.git", from: "2.65.0"),
        // 追加
        .package(url: "https://github.com/realm/SwiftLint.git", from: "0.55.1"),
    ],
    targets: [
        ...
    ]
)

var swiftSettings: [SwiftSetting] { [
    .enableUpcomingFeature("DisableOutwardActorInference"),
    .enableExperimentalFeature("StrictConcurrency"),
] }

各targetのpluginsに設定する

// swift-tools-version:5.10
import PackageDescription

let package = Package(
    name: "event-sourcing-api-design",
    platforms: [...],
    dependencies: [...],
    targets: [
        .executableTarget(
            name: "App",
            dependencies: [
                .product(name: "Fluent", package: "fluent"),
                .product(name: "FluentPostgresDriver", package: "fluent-postgres-driver"),
                .product(name: "Vapor", package: "vapor"),
                .product(name: "NIOCore", package: "swift-nio"),
                .product(name: "NIOPosix", package: "swift-nio"),
            ],
            swiftSettings: swiftSettings,
            plugins: [.plugin(name: "SwiftLintBuildToolPlugin", package: "SwiftLint")] // 追加
        ),
        .testTarget(
            name: "AppTests",
            dependencies: [
                .target(name: "App"),
                .product(name: "XCTVapor", package: "vapor"),
            ],
            swiftSettings: swiftSettings,
            plugins: [.plugin(name: "SwiftLintBuildToolPlugin", package: "SwiftLint")] // 追加
        )
    ]
)

var swiftSettings: [SwiftSetting] { [
    .enableUpcomingFeature("DisableOutwardActorInference"),
    .enableExperimentalFeature("StrictConcurrency"),
] }

.swiftlint.ymlを追加する

今回はとりあえずデフォルトでオフになっているルールだけ一つ一つ確認して取捨選択してみました。これを.swiftlint.ymlというファイル名でプロジェクトルートに追加します。

opt_in_rules:
  - anyobject_protocol
  - array_init
  - closure_spacing
  - collection_alignment
  - comma_inheritance
  - contains_over_filter_count
  - contains_over_filter_is_empty
  - contains_over_first_not_nil
  - contains_over_range_nil_comparison
  - direct_return
  - discouraged_assert
  - discouraged_optional_boolean
  - discouraged_optional_collection
  - empty_collection_literal
  - empty_count
  - empty_string
  - enum_case_associated_values_count
  - expiring_todo
  - explicit_init
  - extension_access_modifier
  - fallthrough
  - fatal_error_message
  - file_name_no_space
  - first_where
  - flatmap_over_map_reduce
  - joined_default_parameter
  - last_where
  - multiline_arguments
  - multiline_arguments_brackets
  - period_spacing
  - prefer_self_in_static_references
  - prefer_self_type_over_type_of_self
  - redundant_nil_coalescing
  - redundant_self_in_closure
  - redundant_type_annotation
  - return_value_from_void_function
  - sorted_imports
  - static_operator
  - toggle_bool
  - unneeded_parentheses_in_closure_argument
  - vertical_parameter_alignment_on_call
analyzer_rules:
  - unused_declaration
  - capture_variable
  - unused_import
included:
  - Sources
strict: true
line_length: 120
reporter: "xcode"

Xcodeで開いて実行する

この状態でXcodeで開いて実行するとLinterが実行され、Xcode上にエラーが表示されます。

SwiftLint Analyzeを使用する

unused_importunused_declarationを検知するには実行だけでなくCLI上でanalyzeを行う必要があります。

Homebrewでswiftlintをインストールする

SwiftLintのCLIをHomebrewでインストールします。

brew install swiftlint

analyze用のMakefileを作成する

以下のMakefileをプロジェクトルートディレクトリに配置してください 。

.PHONE: analyze
analyze:
	rm -rf ./DerivedData
	xcodebuild -workspace ./.swiftpm/xcode/package.xcworkspace -derivedDataPath ./DerivedData -scheme swift-testing-example -destination "platform=macOS,arch=arm64" > xcodebuild.log
	swiftlint analyze --compiler-log-path xcodebuild.log
	rm -f xcodebuild.log

.PHONE: fix
fix:
	swiftlint lint --fix --format

Xcodeでプロジェクトを1度開くと./.swiftpm/Xcode/package.xcworkspaceが生成されます。<scheme名>を実行するスキーム名に変更してください。

DerivedDataを消してい流のは解析にはbuild時のログファイルを用いるのですがインクリメンタルビルドのログでは解析が行えないため、DerivedDataを消してからbuildする必要があるからです。

make analyzeで実行してください。

最後に

Discordのswift-developers-japanbeginner-helpチャンネルで私の質問に回答いただいたshimastripeさんのおかげで解析をすることができました。日曜日にわざわざ丁寧にご回答いただきありがとうございました。

Leave a Comment

CAPTCHA