Skip to content

Commit 66e2bfe

Browse files
committed
[CI] Add SwiftLint and Periphery for code style and dead code check
1 parent 73a5bd6 commit 66e2bfe

15 files changed

+151
-22
lines changed

.github/workflows/commit-ci.yml

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@ on:
33
push:
44
branches:
55
- '*'
6+
paths:
7+
- 'sources/**'
68
jobs:
79
build:
810
runs-on: macos-14
@@ -12,13 +14,25 @@ jobs:
1214
with:
1315
submodules: true
1416

17+
- name: Install SwiftLint
18+
run: brew install swiftlint
19+
20+
- name: Lint
21+
run: swiftlint
22+
1523
- name: Configure build environment
1624
run: |
1725
echo git_ref_name="$(git describe --always)" >> $GITHUB_ENV
1826
1927
- name: Build Squirrel
2028
run: ./action-build.sh package
2129

30+
- name: Install periphery
31+
run: brew install peripheryapp/periphery/periphery
32+
33+
- name: Check Unused Code
34+
run: periphery scan
35+
2236
- name: Upload Squirrel artifact
2337
uses: actions/upload-artifact@v4
2438
with:

.github/workflows/pull-request-ci.yml

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,13 +9,25 @@ jobs:
99
with:
1010
submodules: true
1111

12+
- name: Install SwiftLint
13+
run: brew install swiftlint
14+
15+
- name: Lint
16+
run: swiftlint
17+
1218
- name: Configure build environment
1319
run: |
1420
echo git_ref_name="$(git describe --always)" >> $GITHUB_ENV
1521
1622
- name: Build Squirrel
1723
run: ./action-build.sh package
1824

25+
- name: Install periphery
26+
run: brew install peripheryapp/periphery/periphery
27+
28+
- name: Check Unused Code
29+
run: periphery scan
30+
1931
- name: Upload Squirrel artifact
2032
uses: actions/upload-artifact@v4
2133
with:

.github/workflows/release-ci.yml

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@ on:
55
- '*'
66
branches:
77
- master
8+
paths:
9+
- 'sources/**'
810
workflow_dispatch:
911

1012
jobs:
@@ -19,9 +21,21 @@ jobs:
1921
fetch-depth: 0
2022
submodules: true
2123

24+
- name: Install SwiftLint
25+
run: brew install swiftlint
26+
27+
- name: Lint
28+
run: swiftlint
29+
2230
- name: Build Squirrel
2331
run: ./action-build.sh archive
2432

33+
- name: Install periphery
34+
run: brew install peripheryapp/periphery/periphery
35+
36+
- name: Check Unused Code
37+
run: periphery scan
38+
2539
- name: Build changelog
2640
id: release_log
2741
run: |

.periphery.yml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
project: Squirrel.xcodeproj
2+
schemes:
3+
- Squirrel
4+
targets:
5+
- Squirrel

.swiftlint.yml

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
# By default, SwiftLint uses a set of sensible default rules you can adjust:
2+
disabled_rules: # rule identifiers turned on by default to exclude from running
3+
- force_cast
4+
- force_try
5+
- todo
6+
opt_in_rules: # some rules are turned off by default, so you need to opt-in
7+
8+
# Alternatively, specify all rules explicitly by uncommenting this option:
9+
# only_rules: # delete `disabled_rules` & `opt_in_rules` if using this
10+
# - empty_parameters
11+
# - vertical_whitespace
12+
13+
analyzer_rules: # rules run by `swiftlint analyze`
14+
- explicit_self
15+
16+
included: # case-sensitive paths to include during linting. `--path` is ignored if present
17+
- sources
18+
excluded: # case-sensitive paths to ignore during linting. Takes precedence over `included`
19+
20+
# If true, SwiftLint will not fail if no lintable files are found.
21+
allow_zero_lintable_files: false
22+
23+
# If true, SwiftLint will treat all warnings as errors.
24+
strict: false
25+
26+
# rules that have both warning and error levels, can set just the warning level
27+
# implicitly
28+
line_length: 200
29+
function_body_length: 200
30+
# they can set both implicitly with an array
31+
type_body_length:
32+
- 300 # warning
33+
- 400 # error
34+
# or they can set both explicitly
35+
file_length:
36+
warning: 800
37+
error: 1200
38+
# naming rules can set warnings/errors for min_length and max_length
39+
# additionally they can set excluded names
40+
type_name:
41+
min_length: 4 # only warning
42+
max_length: # warning and error
43+
warning: 40
44+
error: 50
45+
excluded: # excluded via string
46+
allowed_symbols: ["_"] # these are allowed in type names
47+
identifier_name:
48+
min_length: # only min_length
49+
warning: 3
50+
error: 2
51+
excluded: [i, URL, of, by] # excluded via string array
52+
large_tuple:
53+
warning: 3
54+
error: 5
55+
reporter: "github-actions-logging" # reporter type (xcode, json, csv, checkstyle, codeclimate, junit, html, emoji, sonarqube, markdown, github-actions-logging, summary)
56+

sources/BridgingFunctions.swift

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,8 @@
88
import Foundation
99

1010
protocol DataSizeable {
11-
var data_size: Int32 { get set }
11+
// swiftlint:disable:next identifier_name
12+
var data_size: Int32 { get set }
1213
}
1314

1415
extension RimeContext_stdbool: DataSizeable {}
@@ -37,19 +38,21 @@ extension DataSizeable {
3738
let mutableCStr = strdup(cStr)
3839
// Free the existing string if there is one
3940
if let existing = self[keyPath: keypath] {
40-
free(UnsafeMutableRawPointer(mutating: existing))
41+
free(UnsafeMutableRawPointer(mutating: existing))
4142
}
4243
self[keyPath: keypath] = UnsafePointer(mutableCStr)
4344
}
4445
}
4546
}
4647

4748
infix operator ?= : AssignmentPrecedence
49+
// swiftlint:disable:next operator_whitespace
4850
func ?=<T>(left: inout T, right: T?) {
4951
if let right = right {
5052
left = right
5153
}
5254
}
55+
// swiftlint:disable:next operator_whitespace
5356
func ?=<T>(left: inout T?, right: T?) {
5457
if let right = right {
5558
left = right

sources/InputSource.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -80,8 +80,8 @@ final class SquirrelInstaller {
8080
}
8181
for (mode, inputSource) in getInputSource(modes: [modeToSelect]) {
8282
if let enabled = getBool(for: inputSource, key: kTISPropertyInputSourceIsEnabled),
83-
let selectable = getBool(for: inputSource, key: kTISPropertyInputSourceIsSelectCapable),
84-
let selected = getBool(for: inputSource, key: kTISPropertyInputSourceIsSelected),
83+
let selectable = getBool(for: inputSource, key: kTISPropertyInputSourceIsSelectCapable),
84+
let selected = getBool(for: inputSource, key: kTISPropertyInputSourceIsSelected),
8585
enabled && selectable && !selected {
8686
let error = TISSelectInputSource(inputSource)
8787
print("Selection \(error == noErr ? "succeeds" : "fails") for input source: \(mode.rawValue)")

sources/MacOSKeyCodes.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
//
2-
// MacOSKeyCOdes.swift
2+
// MacOSKeyCodes.swift
33
// Squirrel
44
//
55
// Created by Leo Liu on 5/9/24.

sources/Main.swift

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,15 +10,16 @@ import InputMethodKit
1010

1111
@main
1212
struct SquirrelApp {
13-
static let userDir = if let pw = getpwuid(getuid()) {
14-
URL(fileURLWithFileSystemRepresentation: pw.pointee.pw_dir, isDirectory: true, relativeTo: nil).appending(components: "Library", "Rime")
13+
static let userDir = if let pwuid = getpwuid(getuid()) {
14+
URL(fileURLWithFileSystemRepresentation: pwuid.pointee.pw_dir, isDirectory: true, relativeTo: nil).appending(components: "Library", "Rime")
1515
} else {
1616
try! FileManager.default.url(for: .libraryDirectory, in: .userDomainMask, appropriateFor: nil, create: false).appendingPathComponent("Rime", isDirectory: true)
1717
}
1818
static let appDir = "/Library/Input Library/Squirrel.app".withCString { dir in
1919
URL(fileURLWithFileSystemRepresentation: dir, isDirectory: false, relativeTo: nil)
2020
}
2121

22+
// swiftlint:disable:next cyclomatic_complexity
2223
static func main() {
2324
let rimeAPI: RimeApi_stdbool = rime_get_api_stdbool().pointee
2425

sources/SquirrelApplicationDelegate.swift

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@ final class SquirrelApplicationDelegate: NSObject, NSApplicationDelegate, SPUSta
5858
}
5959

6060
func applicationWillTerminate(_ notification: Notification) {
61+
// swiftlint:disable:next notification_center_detachment
6162
NotificationCenter.default.removeObserver(self)
6263
DistributedNotificationCenter.default().removeObserver(self)
6364
panel?.hide()
@@ -132,8 +133,10 @@ final class SquirrelApplicationDelegate: NSObject, NSApplicationDelegate, SPUSta
132133
print("Error creating user data directory: \(userDataDir.path())")
133134
}
134135
}
136+
// swiftlint:disable identifier_name
135137
let notification_handler: @convention(c) (UnsafeMutableRawPointer?, RimeSessionId, UnsafePointer<CChar>?, UnsafePointer<CChar>?) -> Void = notificationHandler
136138
let context_object = Unmanaged.passUnretained(self).toOpaque()
139+
// swiftlint:enable identifier_name
137140
rimeAPI.set_notification_handler(notification_handler, context_object)
138141

139142
var squirrelTraits = RimeTraits.rimeStructInit()

0 commit comments

Comments
 (0)