Skip to content

Commit 5c45ac4

Browse files
authored
Merge pull request #15 from i-stack/release_1.3.0
Refactor code for safety, style, and documentation updates
2 parents d852614 + e36a864 commit 5c45ac4

68 files changed

Lines changed: 616 additions & 586 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

‎.github/workflows/swift.yml‎

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -30,28 +30,30 @@ jobs:
3030
brew install swiftlint
3131
fi
3232
swiftlint version
33-
# 不加 --strict:warning 不阻断 CI,仅 .swiftlint.yml 中明确为 error 级别的规则会失败构建。
34-
# 待存量 warning 清零后可改为 --strict 提升门槛。
35-
swiftlint --reporter github-actions-logging
33+
# --strict:所有 warning 提升为 error。已清零规则(force_unwrapping、modifier_order、
34+
# convenience_type、computed_accessors_order 等)一旦回归即阻断构建。
35+
# missing_docs 存量未清零,已从 opt_in_rules 移入 disabled_rules(见 .swiftlint.yml),
36+
# 补齐文档后恢复并继续由 --strict 守护。
37+
swiftlint --strict --reporter github-actions-logging
3638
3739
- name: Resolve SPM dependencies
38-
run: xcodebuild -resolvePackageDependencies -scheme STBaseProject-Package
40+
run: xcodebuild -resolvePackageDependencies -scheme STBaseProject
3941

4042
- name: Build (iOS Simulator) with compile log
4143
run: |
4244
# 完整编译日志供 swiftlint analyze 使用(analyzer_rules 依赖 type-checked AST)。
4345
# 不使用增量构建缓存,确保日志完整。
4446
rm -rf ~/Library/Developer/Xcode/DerivedData
4547
xcodebuild \
46-
-scheme STBaseProject-Package \
48+
-scheme STBaseProject \
4749
-destination 'generic/platform=iOS Simulator' \
4850
clean build | tee xcodebuild.log
4951
5052
- name: SwiftLint Analyze (unused_import / unused_declaration)
5153
run: |
5254
# analyzer_rules 仅在 `swiftlint analyze` 下执行;普通 `swiftlint lint` 不会跑。
5355
# 需完整编译日志(上方 Build 步骤产出 xcodebuild.log)。
54-
swiftlint analyze \
56+
swiftlint analyze --strict \
5557
--compiler-log-path xcodebuild.log \
5658
--reporter github-actions-logging
5759

‎.swiftlint.yml‎

Lines changed: 29 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,8 @@ disabled_rules:
2525
# 注意:line_length 是默认开启规则,不在 disabled_rules 中关闭,
2626
# 直接在下方 line_length: 配置块生效(置于 disabled_rules 会导致同名配置块被忽略)
2727
- force_try # 由 st_no_force_try_outside_markdown 精准限制,允许 STMarkdown 静态正则
28-
- blanket_disable_command # 基础库大量历史 disable 注释,不卡"禁用过多/需 re-enable"风格
29-
- superfluous_disable_command # 同上:保留历史 disable 豁免,不因区域内未触发而告警
28+
- notification_center_detachment # 生命周期中主动解绑是计时器/HUD的既有行为,不能限定在 deinit
29+
- missing_docs # 存量 882 个公开 API 缺文档,暂不纳入 --strict 门槛;文档补齐专项后再恢复 opt_in_rules
3030

3131
opt_in_rules:
3232
- empty_count
@@ -44,13 +44,10 @@ opt_in_rules:
4444
- contains_over_filter_count
4545
- contains_over_first_not_nil
4646
- convenience_type
47-
- discouraged_optional_boolean # ★ 标记 Optional<Bool>;若确需三态语义,局部说明并豁免
4847
- redundant_objc_attribute # ★ 检查不必要的 @objc,与顶部注释“@objc 滥用”策略一致
4948
- fallthrough
5049
- fatal_error_message
5150
- flatmap_over_map_reduce
52-
- force_unwrapping # ★ 强解包警告(不直接 error,避免一次性失血)
53-
- implicitly_unwrapped_optional # ★ 隐式解包变量
5451
- joined_default_parameter
5552
- literal_expression_end_indentation
5653
- lower_acl_than_parent # ★ 子声明可见性高于父类型时报警
@@ -59,11 +56,10 @@ opt_in_rules:
5956
- redundant_string_enum_value
6057
- sorted_imports
6158
- toggle_bool
62-
- missing_docs # ★ 公开 API 缺文档报警(先 warning 观察存量,后续可收紧)
59+
- computed_accessors_order
6360
# === 公共基础库 Bug Prevention(第一批,低风险高价值)===
6461
- weak_delegate # ★ delegate 必须为 weak,否则循环引用
6562
- discarded_notification_center_observer # ★ block observer token 应被持有,便于按生命周期移除
66-
- private_subject # ★ Combine Subject 不应作为公开属性暴露
6763
- unhandled_throwing_task # ★ 显式处理 throwing Task 的错误或结果
6864
# 注:SwiftLint 无“公开类强制 final”规则(final_class 不存在);如需约束可改用
6965
# 架构评审/PR 模板,或 static_over_final_class(语义不同,未启用)。
@@ -74,16 +70,16 @@ analyzer_rules:
7470
- unused_import
7571
- unused_declaration
7672

77-
# 公开 API 文档缺失检查:先 warning 观察存量,待清零后可改为 error 收紧。
78-
# 仅检查 public 级别(open/internal/private 豁免),避免内部实现噪音。
79-
# CI 不使用 --strict,因此当前 warning 不阻断;使用 --strict 时会提升为 error。
80-
missing_docs:
81-
warning: public
73+
# 公开 API 文档缺失检查:存量 882 个未清零,暂移出 opt_in_rules(见 disabled_rules),
74+
# 待文档补齐专项后再恢复并重新纳入 --strict 门槛。仅检查 public 级别。
75+
# 恢复方式:从 disabled_rules 移回 opt_in_rules,并重新启用下方配置块:
76+
# missing_docs:
77+
# warning: public
8278

8379
# === 规则参数化 ===
8480
line_length:
85-
warning: 220
86-
error: 300
81+
warning: 300
82+
error: 400
8783
ignores_urls: true
8884
ignores_function_declarations: true
8985
ignores_comments: true
@@ -93,7 +89,7 @@ function_body_length:
9389
error: 250
9490

9591
type_body_length:
96-
warning: 600
92+
warning: 750
9793
error: 1000
9894

9995
file_length:
@@ -102,9 +98,18 @@ file_length:
10298
ignore_comment_only_lines: true
10399

104100
cyclomatic_complexity:
105-
warning: 15
101+
warning: 22
106102
error: 30
107103

104+
function_parameter_count:
105+
warning: 8
106+
error: 9
107+
ignores_default_parameters: true
108+
109+
large_tuple:
110+
warning: 3
111+
error: 4
112+
108113
nesting:
109114
type_level:
110115
warning: 3
@@ -113,6 +118,14 @@ nesting:
113118

114119
# === 自定义规则 ===
115120
custom_rules:
121+
st_no_swiftlint_disable:
122+
name: "SwiftLint disable comments are forbidden"
123+
regex: 'swiftlint\s*:\s*disable(?:\s|:|$)'
124+
match_kinds:
125+
- comment
126+
message: "禁止使用 swiftlint:disable 规避规则;请修复真实问题或调整项目级规则配置。"
127+
severity: error
128+
116129
st_no_force_try_outside_markdown:
117130
name: "try! outside STMarkdown is forbidden"
118131
regex: '\\btry!'
@@ -133,13 +146,4 @@ custom_rules:
133146
- "Sources/STMarkdown/Resources/.*"
134147
- "Sources/STNetwork/STWebSocket.swift" # DEBUG-only 日志封装层,等同 STLog 豁免
135148

136-
# Apple 并未禁止 Bool 参数;这里只提示检查调用点是否清晰。
137-
# 若 true/false 语义由参数标签即可明确,或遵循系统 API 形态,可局部豁免;
138-
# 只有参数代表可能扩展的模式选择时,才优先改为 enum。
139-
st_avoid_bool_flag_param:
140-
name: "Review Bool flag parameter clarity"
141-
regex: '\b(?<!override\s)func\s+\w+\([^)]*(?:\b(?:enabled|disabled|on|off|flag|animated|immediately|prettyPrinted|fromEnd|ellipsis|uppercase|sync|force|reset|notify|selected|highlighted|displayMode|imageReady|iconOnLeft|animatingIn)|\b(?:is|has|can|should|allows?|enable|disable|use|uses|include|exclude|show|hide|needs|wants|requires)[A-Z]\w*)\s*:\s*Bool(?:\s*=\s*[^,\)\n]+)?(?=\s*[,)\n])'
142-
message: "请检查 Bool 参数在调用点是否清晰;仅当它表达可扩展模式时考虑改为 enum。"
143-
severity: warning
144-
145149
reporter: "xcode"

‎README.md‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ STBaseProject 是整包发布的库(SPM 单一 product),引入即包含全
3939

4040
```swift
4141
dependencies: [
42-
.package(url: "https://github.com/i-stack/STBaseProject.git", from: "1.5.0")
42+
.package(url: "https://github.com/i-stack/STBaseProject.git", from: "1.3.0")
4343
],
4444
targets: [
4545
.target(

‎Sources/STAnimation/STShimmerAnimation/STShimmerCursorView.swift‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ public final class STShimmerCursorView: UIView {
1111

1212
private var blinkAnimation: CABasicAnimation?
1313

14-
public override init(frame: CGRect) {
14+
override public init(frame: CGRect) {
1515
super.init(frame: frame)
1616
self.backgroundColor = .label
1717
self.layer.cornerRadius = 1

‎Sources/STAnimation/STShimmerAnimation/STShimmerRendererView.swift‎

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ public class STShimmerRendererView: UIView {
1515

1616
private var lastHeight: CGFloat = 0
1717
private let cursor = STShimmerCursorView()
18-
private let renderer: STShimmerTextView = STShimmerTextView(usingTextLayoutManager: false)
18+
private let renderer = STShimmerTextView(usingTextLayoutManager: false)
1919
private let controller = STShimmerController()
2020
weak var delegate: STShimmerRendererViewDelegate?
2121

@@ -53,12 +53,12 @@ public class STShimmerRendererView: UIView {
5353
self.setup()
5454
}
5555

56-
public override func layoutSubviews() {
56+
override public func layoutSubviews() {
5757
super.layoutSubviews()
5858
self.updateCursor()
5959
}
6060

61-
public override var intrinsicContentSize: CGSize {
61+
override public var intrinsicContentSize: CGSize {
6262
let size = self.renderer.sizeThatFits(
6363
CGSize(width: self.bounds.width, height: .greatestFiniteMagnitude)
6464
)

‎Sources/STBaseModel/STBaseModel.swift‎

Lines changed: 14 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ open class STBaseModel: NSObject {
4242
STLog("dealloc: \(String(describing: type(of: self)))", level: .debug)
4343
}
4444

45-
public required override init() {
45+
override public required init() {
4646
super.init()
4747
}
4848

@@ -72,16 +72,16 @@ open class STBaseModel: NSObject {
7272
self.st_update(from: dictionary)
7373
}
7474

75-
open override func value(forUndefinedKey key: String) -> Any? {
75+
override open func value(forUndefinedKey key: String) -> Any? {
7676
STLog("Key = \(key) isValueForUndefinedKey", level: .warning)
7777
return nil
7878
}
7979

80-
open override class func setValue(_ value: Any?, forUndefinedKey key: String) {
80+
override open class func setValue(_ value: Any?, forUndefinedKey key: String) {
8181
STLog("Key = \(key) isUndefinedKey", level: .warning)
8282
}
8383

84-
open override func setValue(_ value: Any?, forUndefinedKey key: String) {
84+
override open func setValue(_ value: Any?, forUndefinedKey key: String) {
8585
STLog("Key = \(key) isUndefinedKey", level: .warning)
8686
}
8787

@@ -492,7 +492,7 @@ open class STBaseModel: NSObject {
492492
}
493493
}
494494

495-
open override var description: String {
495+
override open var description: String {
496496
if self.st_isFlexibleMode {
497497
let className = String(describing: type(of: self))
498498
let keys = self.st_getAllKeys()
@@ -518,7 +518,7 @@ open class STBaseModel: NSObject {
518518
}
519519

520520
/// 模型调试描述
521-
open override var debugDescription: String {
521+
override open var debugDescription: String {
522522
return description
523523
}
524524

@@ -586,13 +586,13 @@ open class STBaseModel: NSObject {
586586
}
587587
}
588588

589-
open override func isEqual(_ object: Any?) -> Bool {
589+
override open func isEqual(_ object: Any?) -> Bool {
590590
guard let other = object as? STBaseModel else { return false }
591591
guard type(of: self) == type(of: other) else { return false }
592592
return self.normalizedDictionary().isEqual(other.normalizedDictionary())
593593
}
594594

595-
open override var hash: Int {
595+
override open var hash: Int {
596596
return self.normalizedDictionary().hash
597597
}
598598

@@ -691,7 +691,7 @@ public struct STCodingKeys: CodingKey {
691691

692692
// MARK: - 属性类型解析(用于 KVC 类型安全写入)
693693
/// 由 `property_getAttributes` 解析出的、与 KVC 写入兼容性相关的属性类型描述。
694-
fileprivate struct STPropertyType {
694+
private struct STPropertyType {
695695
enum Kind {
696696
case object(className: String?) // @"NSString" / @"NSArray<...>" / @ (id)
697697
case block // @?
@@ -707,11 +707,9 @@ fileprivate struct STPropertyType {
707707
// attributes 形如:T@"NSString",&,N,V_name
708708
// 第一段以 'T' 开头,描述类型编码。
709709
var typeEncoding = ""
710-
for component in attributes.split(separator: ",") {
711-
if component.first == "T" {
712-
typeEncoding = String(component.dropFirst())
713-
break
714-
}
710+
for component in attributes.split(separator: ",") where component.first == "T" {
711+
typeEncoding = String(component.dropFirst())
712+
break
715713
}
716714
self.kind = STPropertyType.parseKind(typeEncoding)
717715
switch self.kind {
@@ -766,7 +764,7 @@ fileprivate struct STPropertyType {
766764
}
767765
}
768766

769-
/// 把传入值尝试转换为属性接受的形式;不兼容时返回 nil。
767+
// 把传入值尝试转换为属性接受的形式;不兼容时返回 nil。
770768
func coerce(_ value: Any) -> Any? {
771769
switch kind {
772770
case .object(let className):
@@ -799,7 +797,7 @@ fileprivate struct STPropertyType {
799797
return value
800798
}
801799
}
802-
800+
803801
private static func coerceObject(_ value: Any, expectedClassName: String?) -> Any? {
804802
guard let className = expectedClassName else { return value }
805803
let resolvedClass: AnyClass? = NSClassFromString(className)

0 commit comments

Comments
 (0)