Skip to content

Commit

Permalink
[CI] Add SwiftLint and Periphery for code style and dead code check
Browse files Browse the repository at this point in the history
Linting
  • Loading branch information
LEOYoon-Tsaw committed May 28, 2024
1 parent 0fb0ed1 commit 4a8d6f1
Show file tree
Hide file tree
Showing 18 changed files with 560 additions and 448 deletions.
12 changes: 12 additions & 0 deletions .github/workflows/commit-ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,25 @@ jobs:
with:
submodules: true

- name: Install SwiftLint
run: brew install swiftlint

- name: Lint
run: swiftlint

- name: Configure build environment
run: |
echo git_ref_name="$(git describe --always)" >> $GITHUB_ENV
- name: Build Squirrel
run: ./action-build.sh package

- name: Install periphery
run: brew install peripheryapp/periphery/periphery

- name: Check Unused Code
run: periphery scan --skip-build --index-store-path build/Index.noindex/DataStore

- name: Upload Squirrel artifact
uses: actions/upload-artifact@v4
with:
Expand Down
12 changes: 12 additions & 0 deletions .github/workflows/pull-request-ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,25 @@ jobs:
with:
submodules: true

- name: Install SwiftLint
run: brew install swiftlint

- name: Lint
run: swiftlint

- name: Configure build environment
run: |
echo git_ref_name="$(git describe --always)" >> $GITHUB_ENV
- name: Build Squirrel
run: ./action-build.sh package

- name: Install periphery
run: brew install peripheryapp/periphery/periphery

- name: Check Unused Code
run: periphery scan --skip-build --index-store-path build/Index.noindex/DataStore

- name: Upload Squirrel artifact
uses: actions/upload-artifact@v4
with:
Expand Down
14 changes: 14 additions & 0 deletions .github/workflows/release-ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ on:
- '*'
branches:
- master
paths:
- 'sources/**'
workflow_dispatch:

jobs:
Expand All @@ -19,9 +21,21 @@ jobs:
fetch-depth: 0
submodules: true

- name: Install SwiftLint
run: brew install swiftlint

- name: Lint
run: swiftlint

- name: Build Squirrel
run: ./action-build.sh archive

- name: Install periphery
run: brew install peripheryapp/periphery/periphery

- name: Check Unused Code
run: periphery scan --skip-build --index-store-path build/Index.noindex/DataStore

- name: Build changelog
id: release_log
run: |
Expand Down
5 changes: 5 additions & 0 deletions .periphery.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
project: Squirrel.xcodeproj
schemes:
- Squirrel
targets:
- Squirrel
56 changes: 56 additions & 0 deletions .swiftlint.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
# By default, SwiftLint uses a set of sensible default rules you can adjust:
disabled_rules: # rule identifiers turned on by default to exclude from running
- force_cast
- force_try
- todo
opt_in_rules: # some rules are turned off by default, so you need to opt-in

# Alternatively, specify all rules explicitly by uncommenting this option:
# only_rules: # delete `disabled_rules` & `opt_in_rules` if using this
# - empty_parameters
# - vertical_whitespace

analyzer_rules: # rules run by `swiftlint analyze`
- explicit_self

included: # case-sensitive paths to include during linting. `--path` is ignored if present
- sources
excluded: # case-sensitive paths to ignore during linting. Takes precedence over `included`

# If true, SwiftLint will not fail if no lintable files are found.
allow_zero_lintable_files: false

# If true, SwiftLint will treat all warnings as errors.
strict: false

# rules that have both warning and error levels, can set just the warning level
# implicitly
line_length: 200
function_body_length: 200
# they can set both implicitly with an array
type_body_length:
- 300 # warning
- 400 # error
# or they can set both explicitly
file_length:
warning: 800
error: 1200
# naming rules can set warnings/errors for min_length and max_length
# additionally they can set excluded names
type_name:
min_length: 4 # only warning
max_length: # warning and error
warning: 40
error: 50
excluded: # excluded via string
allowed_symbols: ["_"] # these are allowed in type names
identifier_name:
min_length: # only min_length
warning: 3
error: 2
excluded: [i, URL, of, by] # excluded via string array
large_tuple:
warning: 3
error: 5
reporter: "github-actions-logging" # reporter type (xcode, json, csv, checkstyle, codeclimate, junit, html, emoji, sonarqube, markdown, github-actions-logging, summary)

17 changes: 11 additions & 6 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ install: install-release

RIME_BIN_DIR = librime/dist/bin
RIME_LIB_DIR = librime/dist/lib
DERIVED_DATA_PATH = build

RIME_LIBRARY_FILE_NAME = librime.1.dylib
RIME_LIBRARY = lib/$(RIME_LIBRARY_FILE_NAME)
Expand Down Expand Up @@ -95,13 +96,17 @@ ifdef MACOSX_DEPLOYMENT_TARGET
BUILD_SETTINGS += MACOSX_DEPLOYMENT_TARGET="$(MACOSX_DEPLOYMENT_TARGET)"
endif

BUILD_SETTINGS += COMPILER_INDEX_STORE_ENABLE=YES

release: $(DEPS_CHECK)
mkdir -p $(DERIVED_DATA_PATH)
bash package/add_data_files
xcodebuild -project Squirrel.xcodeproj -configuration Release $(BUILD_SETTINGS) build
xcodebuild -project Squirrel.xcodeproj -configuration Release -scheme Squirrel -derivedDataPath $(DERIVED_DATA_PATH) $(BUILD_SETTINGS) build

debug: $(DEPS_CHECK)
mkdir -p $(DERIVED_DATA_PATH)
bash package/add_data_files
xcodebuild -project Squirrel.xcodeproj -configuration Debug $(BUILD_SETTINGS) build
xcodebuild -project Squirrel.xcodeproj -configuration Debug -scheme Squirrel -derivedDataPath $(DERIVED_DATA_PATH) $(BUILD_SETTINGS) build

.PHONY: sparkle copy-sparkle-framework

Expand All @@ -127,9 +132,9 @@ clean-sparkle:

package: release
ifdef DEV_ID
bash package/sign_app $(DEV_ID)
bash package/sign_app "$(DEV_ID)" "$(DERIVED_DATA_PATH)"
endif
bash package/make_package
bash package/make_package "$(DERIVED_DATA_PATH)"
ifdef DEV_ID
productsign --sign "Developer ID Installer: $(DEV_ID)" package/Squirrel.pkg package/Squirrel-signed.pkg
rm package/Squirrel.pkg
Expand All @@ -151,12 +156,12 @@ permission-check:

install-debug: debug permission-check
rm -rf "$(SQUIRREL_APP_ROOT)"
cp -R build/Debug/Squirrel.app "$(DSTROOT)"
cp -R $(DERIVED_DATA_PATH)/Build/Products/Debug/Squirrel.app "$(DSTROOT)"
DSTROOT="$(DSTROOT)" RIME_NO_PREBUILD=1 bash scripts/postinstall

install-release: release permission-check
rm -rf "$(SQUIRREL_APP_ROOT)"
cp -R build/Release/Squirrel.app "$(DSTROOT)"
cp -R $(DERIVED_DATA_PATH)/Build/Products/Release/Squirrel.app "$(DSTROOT)"
DSTROOT="$(DSTROOT)" bash scripts/postinstall

.PHONY: clean clean-deps
Expand Down
3 changes: 2 additions & 1 deletion package/make_package
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
#!/bin/bash

DERIVED_DATA_PATH=$1
BUNDLE_IDENTIFIER='im.rime.inputmethod.Squirrel'
INSTALL_LOCATION='/Library/Input Methods'

Expand All @@ -8,7 +9,7 @@ source common.sh

pkgbuild \
--info PackageInfo \
--root "${PROJECT_ROOT}/build/Release" \
--root "${PROJECT_ROOT}/${DERIVED_DATA_PATH}/Build/Products/Release" \
--filter '.*\.swiftmodule$' \
--component-plist Squirrel-component.plist \
--identifier "${BUNDLE_IDENTIFIER}" \
Expand Down
6 changes: 4 additions & 2 deletions package/sign_app
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
#! /bin/bash
# enconding: utf-8

appDir="build/Release/Squirrel.app"
DEV_ID=$1
DERIVED_DATA_PATH=$2
appDir="${DERIVED_DATA_PATH}/Build/Products/Release/Squirrel.app"
entitlement="resources/Squirrel.entitlements"

codesign --deep --force --options runtime --timestamp --sign "Developer ID Application: $1" --entitlements "$entitlement" --verbose "$appDir";
codesign --deep --force --options runtime --timestamp --sign "Developer ID Application: ${DEV_ID}" --entitlements "$entitlement" --verbose "$appDir";

spctl -a -vv "$appDir";
9 changes: 6 additions & 3 deletions sources/BridgingFunctions.swift
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@
import Foundation

protocol DataSizeable {
var data_size: Int32 { get set }
// swiftlint:disable:next identifier_name
var data_size: Int32 { get set }
}

extension RimeContext_stdbool: DataSizeable {}
Expand All @@ -30,26 +31,28 @@ extension DataSizeable {
value.data_size = Int32(MemoryLayout<Self>.size - offset)
return value
}

mutating func setCString(_ swiftString: String, to keypath: WritableKeyPath<Self, UnsafePointer<CChar>?>) {
swiftString.withCString { cStr in
// Duplicate the string to create a persisting C string
let mutableCStr = strdup(cStr)
// Free the existing string if there is one
if let existing = self[keyPath: keypath] {
free(UnsafeMutableRawPointer(mutating: existing))
free(UnsafeMutableRawPointer(mutating: existing))
}
self[keyPath: keypath] = UnsafePointer(mutableCStr)
}
}
}

infix operator ?= : AssignmentPrecedence
// swiftlint:disable:next operator_whitespace
func ?=<T>(left: inout T, right: T?) {
if let right = right {
left = right
}
}
// swiftlint:disable:next operator_whitespace
func ?=<T>(left: inout T?, right: T?) {
if let right = right {
left = right
Expand Down
20 changes: 10 additions & 10 deletions sources/InputSource.swift
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ final class SquirrelInstaller {
}
return inputSources
}()

func enabledModes() -> [InputMode] {
var enabledModes = Set<InputMode>()
for (mode, inputSource) in getInputSource(modes: InputMode.allCases) {
Expand All @@ -39,7 +39,7 @@ final class SquirrelInstaller {
}
return Array(enabledModes)
}

func register() {
let enabledInputModes = enabledModes()
if !enabledInputModes.isEmpty {
Expand All @@ -50,7 +50,7 @@ final class SquirrelInstaller {
TISRegisterInputSource(SquirrelApp.appDir as CFURL)
print("Registered input source from \(SquirrelApp.appDir)")
}

func enable(modes: [InputMode] = []) {
let enabledInputModes = enabledModes()
if !enabledInputModes.isEmpty && modes.isEmpty {
Expand All @@ -62,11 +62,11 @@ final class SquirrelInstaller {
for (mode, inputSource) in getInputSource(modes: modesToEnable) {
if let enabled = getBool(for: inputSource, key: kTISPropertyInputSourceIsEnabled), !enabled {
let error = TISEnableInputSource(inputSource)
print("Enable \(error == noErr ? "succeeds" : "fails") for input source: \(mode.rawValue)");
print("Enable \(error == noErr ? "succeeds" : "fails") for input source: \(mode.rawValue)")
}
}
}

func select(mode: InputMode? = nil) {
let enabledInputModes = enabledModes()
let modeToSelect = mode ?? .primary
Expand All @@ -80,8 +80,8 @@ final class SquirrelInstaller {
}
for (mode, inputSource) in getInputSource(modes: [modeToSelect]) {
if let enabled = getBool(for: inputSource, key: kTISPropertyInputSourceIsEnabled),
let selectable = getBool(for: inputSource, key: kTISPropertyInputSourceIsSelectCapable),
let selected = getBool(for: inputSource, key: kTISPropertyInputSourceIsSelected),
let selectable = getBool(for: inputSource, key: kTISPropertyInputSourceIsSelectCapable),
let selected = getBool(for: inputSource, key: kTISPropertyInputSourceIsSelected),
enabled && selectable && !selected {
let error = TISSelectInputSource(inputSource)
print("Selection \(error == noErr ? "succeeds" : "fails") for input source: \(mode.rawValue)")
Expand All @@ -90,7 +90,7 @@ final class SquirrelInstaller {
}
}
}

func disable(modes: [InputMode] = []) {
let modesToDisable = modes.isEmpty ? InputMode.allCases : modes
for (mode, inputSource) in getInputSource(modes: modesToDisable) {
Expand All @@ -100,7 +100,7 @@ final class SquirrelInstaller {
}
}
}

private func getInputSource(modes: [InputMode]) -> [InputMode: TISInputSource] {
var matchingSources = [InputMode: TISInputSource]()
for mode in modes {
Expand All @@ -110,7 +110,7 @@ final class SquirrelInstaller {
}
return matchingSources
}

private func getBool(for inputSource: TISInputSource, key: CFString!) -> Bool? {
let enabledRef = TISGetInputSourceProperty(inputSource, key)
guard let enabled = unsafeBitCast(enabledRef, to: CFBoolean?.self) else { return nil }
Expand Down
Loading

0 comments on commit 4a8d6f1

Please sign in to comment.