@sun-asterisk/sunlint 1.3.41 → 1.3.42
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/skill-assets/sunlint-code-quality/rules/dart/D001-recommended-lints.md +36 -0
- package/skill-assets/sunlint-code-quality/rules/dart/D002-dispose-resources.md +44 -0
- package/skill-assets/sunlint-code-quality/rules/dart/D003-prefer-widget-classes.md +53 -0
- package/skill-assets/sunlint-code-quality/rules/dart/D004-avoid-shrinkwrap.md +31 -0
- package/skill-assets/sunlint-code-quality/rules/dart/D005-widget-nesting.md +62 -0
- package/skill-assets/sunlint-code-quality/rules/dart/D006-large-callbacks.md +54 -0
- package/skill-assets/sunlint-code-quality/rules/dart/D007-lifecycle-order.md +44 -0
- package/skill-assets/sunlint-code-quality/rules/dart/D008-long-functions.md +37 -0
- package/skill-assets/sunlint-code-quality/rules/dart/D009-function-parameters.md +38 -0
- package/skill-assets/sunlint-code-quality/rules/dart/D010-cyclomatic-complexity.md +46 -0
- package/skill-assets/sunlint-code-quality/rules/dart/D011-named-parameters.md +31 -0
- package/skill-assets/sunlint-code-quality/rules/dart/D012-named-booleans.md +28 -0
- package/skill-assets/sunlint-code-quality/rules/dart/D013-single-public-class.md +34 -0
- package/skill-assets/sunlint-code-quality/rules/dart/D014-safe-collection-access.md +30 -0
- package/skill-assets/sunlint-code-quality/rules/dart/D015-copywith-consistency.md +52 -0
- package/skill-assets/sunlint-code-quality/rules/dart/D016-project-tests.md +32 -0
- package/skill-assets/sunlint-code-quality/rules/dart/D017-review-dependencies.md +24 -0
- package/skill-assets/sunlint-code-quality/rules/dart/D018-no-commented-code.md +34 -0
- package/skill-assets/sunlint-code-quality/rules/dart/D019-single-child-wrappers.md +31 -0
- package/skill-assets/sunlint-code-quality/rules/dart/D020-if-else-limit.md +41 -0
- package/skill-assets/sunlint-code-quality/rules/dart/D021-negated-booleans.md +26 -0
- package/skill-assets/sunlint-code-quality/rules/dart/D022-setstate-usage.md +35 -0
- package/skill-assets/sunlint-code-quality/rules/dart/D023-unnecessary-overrides.md +32 -0
- package/skill-assets/sunlint-code-quality/rules/dart/D024-avoid-unnecessary-statefulwidget.md +45 -0
- package/skill-assets/sunlint-code-quality/rules/dart/D025-nested-ternaries.md +35 -0
- package/skill-assets/sunlint-code-quality/rules/ruby/RB001-use-snake-case.md +30 -0
- package/skill-assets/sunlint-code-quality/rules/ruby/RB002-use-camel-case.md +38 -0
- package/skill-assets/sunlint-code-quality/rules/ruby/RB003-use-screaming-snake-case.md +26 -0
- package/skill-assets/sunlint-code-quality/rules/ruby/RB004-predicate-methods.md +36 -0
- package/skill-assets/sunlint-code-quality/rules/ruby/RB005-dangerous-methods.md +36 -0
- package/skill-assets/sunlint-code-quality/rules/ruby/RB006-indentation.md +32 -0
- package/skill-assets/sunlint-code-quality/rules/ruby/RB007-line-length.md +25 -0
- package/skill-assets/sunlint-code-quality/rules/ruby/RB008-rescue-exception.md +36 -0
- package/skill-assets/sunlint-code-quality/rules/ruby/RB009-save-bang.md +41 -0
- package/skill-assets/sunlint-code-quality/rules/ruby/RB010-avoid-n-plus-one.md +32 -0
- package/skill-assets/sunlint-code-quality/rules/ruby/RB011-use-find-each.md +30 -0
- package/skill-assets/sunlint-code-quality/rules/ruby/RB012-sql-injection.md +29 -0
- package/skill-assets/sunlint-code-quality/rules/ruby/RB013-prefer-has-many-through.md +35 -0
- package/skill-assets/sunlint-code-quality/rules/ruby/RB014-dependent-associations.md +28 -0
- package/skill-assets/sunlint-code-quality/rules/ruby/RB015-modern-validations.md +29 -0
- package/skill-assets/sunlint-code-quality/rules/ruby/RB016-thin-controllers.md +45 -0
- package/skill-assets/sunlint-code-quality/rules/ruby/RB017-avoid-fat-models.md +41 -0
- package/skill-assets/sunlint-code-quality/rules/ruby/RB018-service-objects.md +36 -0
- package/skill-assets/sunlint-code-quality/rules/ruby/RB019-avoid-metaprogramming.md +40 -0
- package/skill-assets/sunlint-code-quality/rules/ruby/RB020-use-pluck.md +29 -0
- package/skill-assets/sunlint-code-quality/rules/ruby/RB021-use-size.md +27 -0
- package/skill-assets/sunlint-code-quality/rules/ruby/RB022-order-by-timestamps.md +24 -0
- package/skill-assets/sunlint-code-quality/rules/ruby/RB023-where-missing.md +24 -0
- package/skill-assets/sunlint-code-quality/rules/ruby/RB024-method-length.md +41 -0
- package/skill-assets/sunlint-code-quality/rules/ruby/RB025-parameter-limits.md +28 -0
- package/skill-assets/sunlint-code-quality/rules/ruby/RB026-avoid-deep-nesting.md +38 -0
- package/skill-assets/sunlint-code-quality/rules/ruby/RB027-guard-clauses.md +37 -0
- package/skill-assets/sunlint-code-quality/rules/ruby/RB028-class-length.md +32 -0
- package/skill-assets/sunlint-code-quality/rules/ruby/RB029-meaningful-names.md +30 -0
- package/skill-assets/sunlint-code-quality/rules/ruby/RB030-dry-principle.md +37 -0
- package/skill-assets/sunlint-code-quality/rules/ruby/RB031-mvc-architecture.md +37 -0
- package/skill-assets/sunlint-code-quality/rules/ruby/RB032-use-concerns.md +31 -0
- package/skill-assets/sunlint-code-quality/rules/ruby/RB033-moderate-callbacks.md +31 -0
- package/skill-assets/sunlint-code-quality/rules/ruby/RB034-use-decorators.md +33 -0
- package/skill-assets/sunlint-code-quality/rules/ruby/RB035-comprehensive-tests.md +32 -0
- package/skill-assets/sunlint-code-quality/rules/ruby/RB036-frozen-string-literal.md +29 -0
- package/skill-assets/sunlint-code-quality/rules/ruby/RB037-it-parameter.md +25 -0
- package/skill-assets/sunlint-code-quality/rules/ruby/RB038-modern-enum-syntax.md +28 -0
- package/skill-assets/sunlint-code-quality/rules/ruby/RB039-solid-adapters.md +29 -0
- package/skill-assets/sunlint-code-quality/rules/ruby/RB040-rails-authentication.md +26 -0
- package/skill-assets/sunlint-code-quality/rules/ruby/RB041-async-query-loading.md +29 -0
- package/skill-assets/sunlint-code-quality/rules/ruby/RB042-hotwire-turbo.md +30 -0
- package/skill-assets/sunlint-code-quality/rules/ruby/RB043-use-propshaft.md +27 -0
- package/skill-assets/sunlint-code-quality/rules/ruby/RB044-structured-logging.md +35 -0
- package/skill-assets/sunlint-code-quality/rules/ruby/RB045-prism-parser.md +29 -0
- package/skill-assets/sunlint-code-quality/rules/swift/SW001-block-based-kvo.md +40 -0
- package/skill-assets/sunlint-code-quality/rules/swift/SW002-class-delegate-protocol.md +36 -0
- package/skill-assets/sunlint-code-quality/rules/swift/SW003-compiler-protocol-init.md +28 -0
- package/skill-assets/sunlint-code-quality/rules/swift/SW004-contains-over-filter-count.md +28 -0
- package/skill-assets/sunlint-code-quality/rules/swift/SW005-convenience-type.md +34 -0
- package/skill-assets/sunlint-code-quality/rules/swift/SW006-discarded-notification-center-observer.md +41 -0
- package/skill-assets/sunlint-code-quality/rules/swift/SW007-discouraged-direct-init.md +28 -0
- package/skill-assets/sunlint-code-quality/rules/swift/SW008-discouraged-optional-boolean.md +32 -0
- package/skill-assets/sunlint-code-quality/rules/swift/SW009-empty-count.md +30 -0
- package/skill-assets/sunlint-code-quality/rules/swift/SW010-empty-string.md +30 -0
- package/skill-assets/sunlint-code-quality/rules/swift/SW011-explicit-init.md +26 -0
- package/skill-assets/sunlint-code-quality/rules/swift/SW012-fatal-error-message.md +28 -0
- package/skill-assets/sunlint-code-quality/rules/swift/SW013-for-where.md +30 -0
- package/skill-assets/sunlint-code-quality/rules/swift/SW014-force-cast.md +26 -0
- package/skill-assets/sunlint-code-quality/rules/swift/SW015-force-try.md +30 -0
- package/skill-assets/sunlint-code-quality/rules/swift/SW016-force-unwrapping.md +32 -0
- package/skill-assets/sunlint-code-quality/rules/swift/SW017-function-parameter-count.md +37 -0
- package/skill-assets/sunlint-code-quality/rules/swift/SW018-large-tuple.md +41 -0
- package/skill-assets/sunlint-code-quality/rules/swift/SW019-legacy-constructor.md +28 -0
- package/skill-assets/sunlint-code-quality/rules/swift/SW020-nesting.md +38 -0
- package/skill-assets/sunlint-code-quality/rules/swift/SW021-no-extension-access-modifier.md +28 -0
- package/skill-assets/sunlint-code-quality/rules/swift/SW022-overridden-super-call.md +30 -0
- package/skill-assets/sunlint-code-quality/rules/swift/SW023-override-in-extension.md +32 -0
- package/skill-assets/sunlint-code-quality/rules/swift/SW024-private-over-fileprivate.md +28 -0
- package/skill-assets/sunlint-code-quality/rules/swift/SW025-private-unit-test.md +32 -0
- package/skill-assets/sunlint-code-quality/rules/swift/SW026-prohibited-super-call.md +29 -0
- package/skill-assets/sunlint-code-quality/rules/swift/SW027-sorted-first-last.md +28 -0
- package/skill-assets/sunlint-code-quality/rules/swift/SW028-syntactic-sugar.md +28 -0
- package/skill-assets/sunlint-code-quality/rules/swift/SW029-unused-closure-parameter.md +28 -0
- package/skill-assets/sunlint-code-quality/rules/swift/SW030-unused-enumerated.md +28 -0
- package/skill-assets/sunlint-code-quality/rules/swift/SW031-unused-optional-binding.md +26 -0
- package/skill-assets/sunlint-code-quality/rules/swift/SW032-valid-ibinspectable.md +26 -0
- package/skill-assets/sunlint-code-quality/rules/swift/SW033-vertical-parameter-alignment.md +36 -0
- package/skill-assets/sunlint-code-quality/rules/swift/SW034-void-return.md +28 -0
- package/skill-assets/sunlint-code-quality/rules/swift/SW035-weak-delegate.md +28 -0
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Cảnh báo tham số closure không được sử dụng
|
|
3
|
+
impact: MAJOR
|
|
4
|
+
impactDescription: Tránh cảnh báo của compiler và làm sạch code bằng cách loại bỏ các biến không dùng tới.
|
|
5
|
+
tags: swift, ios, closure, parameters, clean-code
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
## Cảnh báo tham số closure không được sử dụng
|
|
9
|
+
|
|
10
|
+
Nếu một closure nhận vào các tham số nhưng bạn không sử dụng chúng trong thân hàm, hãy sử dụng dấu gạch dưới `_` thay cho tên biến. Việc này giúp giảm bớt sự lộn xộn trong code và làm rõ cho người khác biết rằng tham số đó là cố tình bị bỏ qua.
|
|
11
|
+
|
|
12
|
+
**Incorrect (khai báo tên tham số nhưng không dùng):**
|
|
13
|
+
|
|
14
|
+
```swift
|
|
15
|
+
apiClient.fetchData { data, error in
|
|
16
|
+
print("Yêu cầu đã hoàn thành")
|
|
17
|
+
}
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
**Correct (dùng dấu gạch dưới cho tham số thừa):**
|
|
21
|
+
|
|
22
|
+
```swift
|
|
23
|
+
apiClient.fetchData { _, _ in
|
|
24
|
+
print("Yêu cầu đã hoàn thành")
|
|
25
|
+
}
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
**Tools:** SwiftLint (unused_closure_parameter)
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Tránh dùng enumerated() khi không cần index
|
|
3
|
+
impact: MAJOR
|
|
4
|
+
impactDescription: Loại bỏ các tính toán không cần thiết và làm mã nguồn gọn gàng hơn.
|
|
5
|
+
tags: swift, ios, loops, performance, enumeration
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
## Tránh dùng enumerated() khi không cần index
|
|
9
|
+
|
|
10
|
+
Chỉ sử dụng phương thức `.enumerated()` khi bạn thực sự cần cả `index` và giá trị phần tử `value` trong vòng lặp. Nếu bạn chỉ cần giá trị phần tử để xử lý, hãy duyệt trực tiếp qua tập hợp. Điều này giúp tối ưu hóa hiệu năng và làm code rõ ràng hơn.
|
|
11
|
+
|
|
12
|
+
**Incorrect (dùng enumerated chỉ để lấy item):**
|
|
13
|
+
|
|
14
|
+
```swift
|
|
15
|
+
for (index, item) in items.enumerated() {
|
|
16
|
+
print("Xử lý \(item)")
|
|
17
|
+
}
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
**Correct (duyệt trực tiếp):**
|
|
21
|
+
|
|
22
|
+
```swift
|
|
23
|
+
for item in items {
|
|
24
|
+
print("Xử lý \(item)")
|
|
25
|
+
}
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
**Tools:** SwiftLint (unused_enumerated)
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Không dùng optional binding chỉ để gọi hàm hoặc property
|
|
3
|
+
impact: CRITICAL
|
|
4
|
+
impactDescription: Tránh việc tạo ra các khối lồng nhau (deep nesting) không cần thiết, giúp code phẳng và dễ đọc hơn.
|
|
5
|
+
tags: swift, ios, optional, chaining, binding
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
## Không dùng optional binding chỉ để gọi hàm hoặc property
|
|
9
|
+
|
|
10
|
+
Tránh sử dụng `if let` hoặc `guard let` nếu mục đích duy nhất chỉ là để gọi một phương thức hoặc truy cập một thuộc tính của đối tượng optional. Thay vào đó, hãy sử dụng **Optional Chaining** (`?.`). Điều này giúp mã nguồn ngắn gọn và tránh lồng ghép nhiều cấp bậc.
|
|
11
|
+
|
|
12
|
+
**Incorrect (dùng binding cho một lần gọi duy nhất):**
|
|
13
|
+
|
|
14
|
+
```swift
|
|
15
|
+
if let navigationController = self.navigationController {
|
|
16
|
+
navigationController.popViewController(animated: true)
|
|
17
|
+
}
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
**Correct (dùng optional chaining):**
|
|
21
|
+
|
|
22
|
+
```swift
|
|
23
|
+
self.navigationController?.popViewController(animated: true)
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
**Tools:** SwiftLint (unused_optional_binding)
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Không dùng @IBInspectable với kiểu không hỗ trợ và const
|
|
3
|
+
impact: MAJOR
|
|
4
|
+
impactDescription: Tránh lỗi biên dịch hoặc các hành vi không xác định trong Interface Builder.
|
|
5
|
+
tags: swift, ios, uikit, interface-builder, ibinspectable
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
## Không dùng @IBInspectable với kiểu không hỗ trợ và const
|
|
9
|
+
|
|
10
|
+
`@IBInspectable` chỉ nên được sử dụng với các kiểu dữ liệu được Interface Builder hỗ trợ (Int, CGFloat, String, Bool, UIColor, v.v.). Ngoài ra, thuộc tính được đánh dấu `@IBInspectable` phải là biến (`var`) để có thể thay đổi giá trị từ Storyboard/XIB. Không sử dụng với hằng số `let`.
|
|
11
|
+
|
|
12
|
+
**Incorrect (dùng kiểu không hỗ trợ hoặc let):**
|
|
13
|
+
|
|
14
|
+
```swift
|
|
15
|
+
@IBInspectable let cornerRadius: CGFloat = 5.0 // Sai: Phải dùng var
|
|
16
|
+
@IBInspectable var customObject: MyObject? // Sai: Kiểu không được hỗ trợ
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
**Correct (dùng var với kiểu hợp lệ):**
|
|
20
|
+
|
|
21
|
+
```swift
|
|
22
|
+
@IBInspectable var cornerRadius: CGFloat = 5.0
|
|
23
|
+
@IBInspectable var isShadowEnabled: Bool = true
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
**Tools:** SwiftLint (valid_ibinspectable)
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Các parameter phải thẳng hàng khi gọi hàm
|
|
3
|
+
impact: LOW
|
|
4
|
+
impactDescription: Cải thiện khả năng đọc mã nguồn và duy trì phong cách viết code nhất quán trong dự án.
|
|
5
|
+
tags: swift, ios, formatting, style-guide, parameters
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
## Các parameter phải thẳng hàng khi gọi hàm
|
|
9
|
+
|
|
10
|
+
Khi gọi một hàm có nhiều tham số và bạn quyết định xuống dòng, mỗi tham số (parameter) nên nằm trên một dòng riêng biệt và phải được căn lề thẳng hàng với nhau hoặc theo chuẩn thụt lề của dự án. Điều này giúp người đọc dễ dàng quét qua danh sách đối số đang được truyền vào.
|
|
11
|
+
|
|
12
|
+
**Incorrect (căn lề không đồng nhất):**
|
|
13
|
+
|
|
14
|
+
```swift
|
|
15
|
+
animate(withDuration: 0.3, animations: {
|
|
16
|
+
// ...
|
|
17
|
+
}, completion: { _ in
|
|
18
|
+
// ...
|
|
19
|
+
})
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
**Correct (căn lề thẳng hàng hoặc xuống dòng rõ ràng):**
|
|
23
|
+
|
|
24
|
+
```swift
|
|
25
|
+
animate(
|
|
26
|
+
withDuration: 0.3,
|
|
27
|
+
animations: {
|
|
28
|
+
// ...
|
|
29
|
+
},
|
|
30
|
+
completion: { _ in
|
|
31
|
+
// ...
|
|
32
|
+
}
|
|
33
|
+
)
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
**Tools:** SwiftLint (vertical_parameter_alignment_on_call, vertical_parameter_alignment)
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Dùng -> Void thay vì -> () cho function type
|
|
3
|
+
impact: LOW
|
|
4
|
+
impactDescription: Tăng tính nhất quán và dễ đọc cho các khai báo closure hoặc function type.
|
|
5
|
+
tags: swift, ios, convention, void, function-type
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
## Dùng -> Void thay vì -> () cho function type
|
|
9
|
+
|
|
10
|
+
Swift Coding Convention ưu tiên sử dụng từ khóa `Void` thay cho cặp ngoặc đơn rỗng `()` khi định nghĩa kiểu trả về của một hàm (function type) hoặc closure. `Void` mang tính tường minh và dễ đọc hơn khi xuất hiện trong các khai báo phức tạp.
|
|
11
|
+
|
|
12
|
+
**Incorrect (dùng () cho kiểu trả về):**
|
|
13
|
+
|
|
14
|
+
```swift
|
|
15
|
+
let completion: () -> () = {
|
|
16
|
+
print("Xong")
|
|
17
|
+
}
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
**Correct (dùng Void):**
|
|
21
|
+
|
|
22
|
+
```swift
|
|
23
|
+
let completion: () -> Void = {
|
|
24
|
+
print("Xong")
|
|
25
|
+
}
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
**Tools:** SwiftLint (void_return)
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Delegate phải được đánh dấu là weak
|
|
3
|
+
impact: HIGH
|
|
4
|
+
impactDescription: Tránh giữ chặt đối tượng (strong reference) dẫn đến retain cycle và rò rỉ bộ nhớ (memory leak).
|
|
5
|
+
tags: swift, ios, delegate, weak, memory-leak
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
## Delegate phải được đánh dấu là weak
|
|
9
|
+
|
|
10
|
+
Trong mô hình Delegation, đối tượng nhận ủy quyền (delegate) thường sở hữu đối tượng thực hiện ủy quyền. Để tránh vòng lặp tham chiếu mạnh (retain cycle), thuộc tính `delegate` phải luôn được khai báo với từ khóa `weak`. Điều này đảm bảo rằng khi View Controller hoặc đối tượng chủ quản bị giải phóng, delegate cũng có thể được giải phóng theo.
|
|
11
|
+
|
|
12
|
+
**Incorrect (giữ tham chiếu mạnh):**
|
|
13
|
+
|
|
14
|
+
```swift
|
|
15
|
+
class MyView: UIView {
|
|
16
|
+
var delegate: MyViewDelegate? // Nguy cơ memory leak
|
|
17
|
+
}
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
**Correct (dùng tham chiếu yếu):**
|
|
21
|
+
|
|
22
|
+
```swift
|
|
23
|
+
class MyView: UIView {
|
|
24
|
+
weak var delegate: MyViewDelegate? // An toàn
|
|
25
|
+
}
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
**Tools:** SwiftLint (weak_delegate)
|