SwiftLint — чистота і порядок в iOS проекті

image

Думаю, всі знають, як буває непросто підтримувати дотримання code style і угод в iOS-проекті. Сьогодні поговоримо про те, як автоматизувати цей процес за допомогою утиліти SwiftLint.

SwiftLint — це утиліта від розробників Realm для автоматичної перевірки Swift-коду. Утиліта містить набір правил, заснованих на GitHub's Swift Style Guide і здоровому глузді. Зрозуміло можна додавати свої правила. SwiftLint підтримує інтеграцію з Xcode, Appcode, Atom.

Установка і настройка
Викачуємо і встановлюємо найсвіжіший реліз з репозиторію.

Або встановлюємо через термінал:

$ brew update
$ brew install swiftlint

Оновити утиліту можна так:

$ brew update
$ brew upgrade swiftlint

Переключитися на іншу версію:

$ brew switch swiftlint <номер версії>

Дізнатися поточну версію:

swiftlint version

Заходимо в налаштування проекту, Build Phases і додаємо в секцію Run Script:

if which swiftlint >/dev/null; then
swiftlint
else
echo "error: SwiftLint does not exist, download it from https://github.com/realm/SwiftLint"
exit 1
fi

Порада: вкрай рекомендується використовувати команду «exit 1» — це гарантує встановлення SwiftLint усіма членами команди.
Перший запуск
Тепер, коли SwiftLint встановлено, що в кінці кожної складання проекту відбуватиметься перевірка коду. Після першого запуску ви, найімовірніше, побачите щось типу:



Не варто сильно переживати, більшість помилок і попереджень досить прості і легко поправні. Не поспішайте виправляти їх вручну, оскільки SwiftLint має чудову функцію автокорекції, вона досить безпечна. Для її використання в терміналі заходимо в каталог проекту і виконуємо команду:

swiftlint autocorrect

Збираємо проект заново: кількість помилок зменшилась, але решту доведеться виправляти вручну.
Порада: не додавайте автоматичне виправлення в Run Script, інакше програмісти звикнуть не думати або навіть не будуть знати про деяких угодах.
Правила
Список встановлених правил можна побачити, виконавши команду:

swiftlint rules



У кожного правила є опис і набір параметрів:

  • opt-in — є правило опціональним (вимкнуто за промовчанням);
  • correctable — можливо настроювати правило;
  • enabled in your config — включено в проекті;
  • configuration — параметри.
Також можна подивитися исходники правил для більшого розуміння.

Окремо хочеться виділити кілька дуже корисних правил:

  • сyclomatic_сomplexity — правило обмежує цикломатическую складність;
  • nesting — рівень вкладеності класів і функцій;
  • file_lenght — кількість рядків у файлі;
  • function_body_lenght — кількість рядків у функції;
  • force_try/cast/unwrapping — наявність операцій, потенційно призводять до крешу;
  • weak_delegate — перевірка того, що делегат тримається слабкою посиланням;
  • missing_docs — написані коментарі до публічних функцій/властивостями.
Конфігурація
Найімовірніше вам потрібно відключити, змінити або додати які-небудь правила. Для цього в корені проекту потрібно створити файл .swiftlint.yml.

Доступні параметри конфігурації:

Список правил, які необхідно відключити:

disabled_rules:
- colon
- comma
- control_statement

Список опціональних правил, які необхідно включити (за замовчуванням):

opt_in_rules:
- empty_count
- missing_docs

Виключити підкаталоги або файли:

excluded: 
- Carthage
- Pods
- Source/ExcludedFolder
- Source/ExcludedFile.swift

Включити підкаталоги або файли (альтернатива excluded):

included: 
- MyProject
- MyProjectKeyboard
- MyProjectTests

Параметри правил (доступні варіанти можна знайти в списку правил):

file_length:
warning: 500
error: 600

Тип звіту (доступні параметри: xcode, json, csv, checkstyle, junit):

reporter: xcode

Максимально допустима кількість попереджень:

warning_threshold: 15

Порада: обов'язково додайте у файл конфігурації warning_threshold, щоб кількість попереджень не збільшувалася.
Вкладені конфігурації
Ви можете створювати кілька файлів конфігурацій (.swiftlint.yml) для різних підкаталогів. SwiftLint буде автоматично використовувати конфігурацію розташовану в папці з перевіреними файлами. Параметри excluded і included для вкладених конфігурацій будуть ігноруватися.

Додавання своїх правил
SwiftLint дозволяє додавати свої правила на основі регулярних виразів. Для цього необхідно у файлі .swiftlint.yml додати секцію custom_rules. У правила можна вказати наступні параметри:

  • identifer — ідентифікатор (обов'язково);
  • regexp — умова знаходження (обов'язково);
  • name — ім'я правила, відображається у тексті помилки (необов'язково);
  • message — опис помилки (обов'язково);
  • match_kinds — у яких сутності шукати входження, доступні значення (можна вказувати декілька): comment, identifier, number, parameter, string, повний список доступний в документації (обов'язково);
  • severity — тип: попередження (warning) або помилка (error) (необов'язково, за замовчуванням — warning);
  • included — які файли необхідно перевіряти (необов'язково
Правило, яке перевіряє іменування з суфіксом -id. (наприклад: userId — вірно, userID — невірно):

custom_rules:
id_suffix_naming:
name: "Wrong name"
regex: "(ID)"
match_kinds:
- comment
- identifier
message: "Use 'Id' instead 'ID'"
severity: error



Відключення правил в коді
Якщо хочете відключити перевірку в частині коду, використовуйте наступну конструкцію:

// swiftlint:disable <rule1> [<rule2> <rule3>...]
.........
// swiftlint:enable <rule1> [<rule2> <rule3>...]

func printName() {
// swiftlint:disable force_cast
let name = loadName() as! String
// swiftlint:enable force_cast
print(name)
}

Швидкість складання проекту
Очевидно, що використання SwiftLint вимагає додаткового часу при складанні проекту. Якщо швидкість збірки помітно просідає, варто задуматися про перевірку тільки змінених файлів. Для цього потрібно замінити скрипт перевірки Build Phases на:

Скрипт

count=0
for file_path in $(git ls-files -om --exclude-from=.gitignore | grep ".swift$"); do
export SCRIPT_INPUT_FILE_$count=$file_path
count=$((count + 1))
done
for file_path in $(git diff --cached --name-only | grep ".swift$"); do
export SCRIPT_INPUT_FILE_$count=$file_path
count=$((count + 1))
done
export SCRIPT_INPUT_FILE_COUNT=$count
swiftlint lint --use-script-input-files


Кілька прикладів конфігурацій SwiftLint у відомих компаніях:

Kickstarter
disabled_rules:
- function_parameter_count
- nesting
- variable_name
- weak_delegate
- trailing_comma
opt_in_rules:
- empty_count
- force_unwrapping
- private_outlet
line_length: 110
type_body_length:
warning: 300
error:400
excluded:
- Carthage/
- Frameworks/
- Kickstarter-iOS.playground/
- Kickstarter-tvOS.playground/
- Library/Strings.swift
- bin/strings.swift
reporter: "xcode"
custom_rules:
localized_lensing:
name: "Localized Lensing"
regex: "\.~\s+Strings\s*\."
message: "Capture calls to `Strings` functions using `%~ { _ in Strings... }`"
severity: error


Firefox
disabled_rules: # rule identifiers to exclude from running
- legacy_constructor
- variable_name
- legacy_cggeometry_functions
- legacy_constant
- todo
- trailing_newline
- empty_count
- force_cast
- type_name
- function_body_length
- missing_docs
- conditional_binding_cascade
- valid_docs
- cyclomatic_complexity
- type_body_length
- function_parameter_count
- force_try
- control_statement
- trailing_whitespace
- leading_whitespace
- operator_whitespace
- file_length
- mark
opt_in_rules: # some rules are only opt-in
- closing_brace
- opening_brace
- return_arrow_whitespace
- trailing_semicolon
- statement_position
# Find all the available rules by running:
# swiftlint rules
included: # paths to include during linting. `--path` is ignored if present.
excluded: # paths to ignore during linting. Takes precedence over `included`.
- Carthage
- Pods
- Source/ExcludedFolder
- Source/ExcludedFile.swift
- ThirdParty
- FxA
- FxAClient
- build

# configurable rules can be customized from this configuration file
# binary rules can set their severity level
trailing_semicolon: error
empty_count: error
closing_brace: error
opening_brace: error
return_arrow_whitespace: error
statement_position: error
colon: error
comma: error

line_length: 1000

reporter: "json" # reporter type (xcode, json, csv, checkstyle)


Realm

included:
- Realm/ObjectServerTests
- RealmSwift
- Realm/Swift
variable_name:
min_length: # not possible to disable this partial rule, so set it to zero
warning: 0
error: 0
disabled_rules:
- file_length
- force_cast
- force_try
- function_body_length
- todo
- type_body_length
- line_length
- vertical_whitespace
- syntactic_sugar


Тинькоффwarning_threshold: 15

excluded:
— Pods
— MBUITest

disabled_rules:
— trailing_whitespace

line_length:
warning: 150

function_parameter_count:
warning: 10
error: 15

file_length:
warning: 500

type_body_length:
warning: 400
error: 450

SwiftLint дозволив нашій команді розробників ios витрачати менше часу на код-рев'ю, дотримуватися єдиного code style і підвищити якість коду. Якщо ви ще не використовуєте SwiftLint у своєму проекті, то обов'язково спробуйте.

Корисні посилання:

» Репозиторій SwiftLint
» Список правил SwiftLint
» Про перевірку тільки змінених файлів
» GitHub's Swift Style Guide
» Tailor — альтернатива SwiftLint
Джерело: Хабрахабр

0 коментарів

Тільки зареєстровані та авторизовані користувачі можуть залишати коментарі.