Tích hợp SwiftLint vào dự án Swift
Bài đăng này đã không được cập nhật trong 3 năm
Giới thiệu
SwiftLint là công cụ thực thi mã nguồn tuân theo theo phong cách và quy tắc của ngôn ngữ Swift.
Nó sẽ tích hợp trong Source Kit framework của Apple để phân tích mã nguồn của dự án và đảm bảo cú pháp và phong cách của mã nguồn tuân theo các quy ước đã thống nhất trong dự án.
Các bước tích hợp SwiftLint
Để tích hợp SwiftLint vào dự án ta cần thực hiện các bước dưới đây:
- Cài đặt SwiftLint
- Tích hợp với XCode
- Kiểm chứng quá trình tích hợp
- Cấu hình các luật và quy tắc
Bước 1: Cài đặt SwiftLint
Ta có thể cài đặt SwiftLint bằng nhiều cách
Cài đặt qua Brew
brew install swiftlint
Cài đặt qua CocoaPods
Ta sẽ phải theo dòng dưới đây vào trong file Podfile
pod 'SwiftLint'
Nó sẽ cho phép ta tải về mã nguồn và các gói cần thiết của SwiftLint khi chạy lệnh pod install và khi chạy script ${PODS_ROOT}/SwiftLint/swiftlint trong build phase
Cài đặt qua Mint
$ mint install realm/SwiftLint
Cài đặt sử dụng pre-build package
Ta có thể tải và cài đặt pre-build package SwiftLint.pkg trên Github Quá trình cài đặt có thể xuất hiện thông báo dưới đây
Ta cần cấp quyền thực thi cho file SwiftLint.pkg bằng cách Menu > System Preferences... > Security & Privacy > General sau đó click nút Open Anyway
Tích hợp với XCode
Ta sẽ cần tích hợp với Xcode để SwiftLint phân tích code và hiển thị các cảnh báo và lỗi trên IDE khi build code. Ta sẽ thêm "“Run Script Phase” với nội dung như sau:
if which swiftlint >/dev/null; then
swiftlint
else
echo "warning: SwiftLint not installed, download from https://github.com/realm/SwiftLint"
fi
Kiểm chứng quá trình tích hợp
Để kiểm tra việc tích hợp đã thành công hay chưa? Ta chỉ cần thực hiện build dự án Product > Build (⌘B), nếu ta nhìn thấy nhiều cảnh báo, hay lỗi liên quan tới cú pháp và style của code thì có nghĩa là quá trình tích hợp đã thành công
Cấu hình các luật
SwiftLint bundle bao gồm hơn 75 luật cơ bản và không phải lúc nào chúng ta cũng sử dụng các luật này. Do đó ta sẽ cấu hình những luật sẽ sử dụng trong dự án thông qua file .swiftlint.yml
$ touch .swiftlint.yml
$ open .swiftlint.yml
Ta thử cấu hình theo nội dung sau:
disabled_rules:
- force_cast
- force_unwrapping
line_length:
warning: 200
error: 250
ignores_function_declarations: true
ignores_comments: true
ignores_urls: true
Với cấu hình trên ta sẽ nhận được cảnh báo khi một dòng code dài trên 200 ký tự, nhận được thông báo lỗi khi một dòng code dài trên 250 ký tự. Không hiển thị cảnh báo khi force_cast và force_unwrapping
Cấu hình luật bao gồm:
- disabled_rules: danh sách các luật không sử dụng
- opt_in_rules: danh sách các luật sử sụng
- analyzer_rules: các luật cho bộ phân tích cú pháp
Ta có thể tham khảo file cấu hình dưới đây cho dự án của mình
reporter: "xcode" # reporter type (xcode, json, csv, checkstyle, junit, html, emoji)
excluded: # paths to ignore during linting. Takes precedence over `included`.
- Carthage
- Pods
disabled_rules: # rule identifiers to exclude from running
- trailing_whitespace
- force_cast
- force_unwrapping
- force_try
- empty_enum_arguments
- overridden_super_call
- sorted_imports
# - colon # Default configuration: warning, flexible_right_spacing: false, apply_to_dictionaries: true
# - comma # Default configuration: warning
# - opening_brace
# - todo
# - empty_parentheses_with_trailing_closure
# - empty_string
# - unused_closure_parameter
# - unused_setter_value
# - unused_optional_binding
# - redundant_void_return
# - void_return
# - redundant_string_enum_value
# - redundant_objc_attribute
# - closure_parameter_position
# - control_statement
# - notification_center_detachment
# - legacy_constructor
# - for_where
# - unneeded_break_in_switch
# - implicit_getter
# - duplicate_imports
# - trailing_newline
opt_in_rules: # some rules are only opt-in
# - missing_docs
- yoda_condition # Default configuration: warning
- empty_count # Default configuration: error, only_after_dot: false
- empty_string # Default configuration: warning
- closure_end_indentation # Default configuration: warning
- closure_spacing # Default configuration: warning
- explicit_init # Default configuration: warning
- first_where # Default configuration: warning
- number_separator # Default configuration: warning, minimum_length: 0
- explicit_failure_calls
- fatal_error_message
# - extension_access_modifier
# - implicitly_unwrapped_optional
# - operator_usage_whitespace
- vertical_parameter_alignment_on_call
- multiline_parameters
# - multiple_empty_lines # Defined into custom roles
- nesting
- private_outlet
- prohibited_super_call
- protocol_property_accessors_order
- redundant_nil_coalescing
- syntactic_sugar
- comments_space
- comments_capitalized_ignore_possible_code
- comments_capitalized_find_possible_code
line_length:
warning: 200
error: 250
ignores_function_declarations: true
ignores_comments: true
ignores_urls: true
function_body_length:
warning: 80
error: 150
function_parameter_count:
warning: 4
error: 6
type_name: # class name
min_length: 3
max_length:
warning: 60
error: 80
type_body_length:
warning: 300
error: 500
file_length:
warning: 500
error: 800
ignore_comment_only_lines: true
identifier_name: # Variable name
allowed_symbols: "_"
min_length: 1
max_length:
warning: 60
error: 80
excluded:
- id
- URL
- GlobalAPIKey
vertical_whitespace: # warning, max_empty_lines: 1
max_empty_lines: 3
large_tuple:
warning: 4
error: 5
private_outlet:
allow_private_set: true
#nesting:
# type_level:
# warning: 3
# error: 6
# statement_level:
# warning: 5
# error: 10
number_separator:
minimum_length: 8
#cyclomatic complexity below 4 is considered good;
#cyclomatic complexity between 5 and 7 is considered medium complexity,
#between 8 and 10 is high complexity,
#and above that is extreme complexity.
cyclomatic_complexity:
ignores_case_statements: true
warning: 7
error: 11
custom_rules:
comments_space: # From https://github.com/brandenr/swiftlintconfig
name: "Space After Comment"
regex: '(^ *//\w+)'
message: "There should be a space after //"
severity: warning
comments_capitalized_ignore_possible_code:
name: "Capitalize First Word In Comment"
regex: "(^ +// +(?!swiftlint)[a-z]+)"
message: "The first word of a comment should be capitalized"
severity: warning
explicit_failure_calls:
name: “Avoid asserting ‘false’”
regex: ‘((assert|precondition)\(false)’
message: “Use assertionFailure() or preconditionFailure() instead.”
severity: warning
multiple_empty_lines:
name: "Multiple Empty Lines"
regex: '((?:\s*\n){3,})'
message: "There are too many line breaks"
severity: error
force_https: # From https://github.com/Twigz/Game
name: "Force HTTPS over HTTP"
regex: "((?i)http(?!s))"
match_kinds: string
message: "HTTPS should be favored over HTTP"
severity: warning
already_true:
regex: "== true"
message: "Don't compare to true, just use the bool value."
already_bool:
regex: "== false"
message: "Don't compare to false, just use !value."
Nguồn tham khảo
All rights reserved