Перейти к основному содержимому

Линтеры и тестеры



Тема «Code style». Статический анализ кода


Инструмент для скриптов


Полезное:


Линтеры — это полезные инструменты, которые в пределах своих возможностей будут держать код «в чистоте». Чтобы они полностью раскрыли свой потенциал, нужно уделить время их дополнительной настройке.

ESLint​

ESLint. Он представляет собой инструмент статического анализа кода, написанного на любом выбранном стандарте JS. Поскольку он нужен только на этапе разработки кода, сохраняем его зависимости для разработки (devDependencies в package.json). Установка из npm:

npm install --save-dev eslint

Правила линтера описывают в конфиге .eslintrc.json. Можно использовать как JSON, так и JS:

{
"rules": {
"no-unused-vars": 2,
"max-len": [1, 100],
"max-params": [2, 3]
}
}

Правил очень много, полный список найдёте на сайте разработчиков. Настройка всего «под себя» может занять много времени, но будет полезно один раз это сделать. Так, например, с редактором Vim. Он заслужил славу очень сложного инструмента и стал предметом многих мемов, но если один раз настроить его, Vim станет значительно удобнее. Для быстрого старта или чтобы не тратить время команды, которой надо супербыстро запустить проект, — существуют готовые наборы правил, например eslint-config-airbnb:

npm install --save-dev eslint-config-airbnb

Правила можно не только наследовать, но и переопределять:

{
"extends": "airbnb", // Здесь вы указываете, что наследуетесь от набора правил
"rules": {
"max-len": [2, 100],
"max-params": [2, 3]
}
}

Наборы готовых конфигов можете найти в npm.

Бывают случаи, когда не нужно прогонять через линтер определённые файлы или папки. Варианты решения:

  • При запуске линтера явно указать, проверять или не проверять определённые папки, префиксы или расширения файлов;
  • Указать файл .eslintignore и прописать в нём, какие файлы или папки не трогать.

Например, не проверять node_modules, build или dist, минифицированные, собранные файлы:

/build
**/*.min.js
/node_modules

Иногда необходимо игнорировать правила в коде (одну или много строчек). Чтобы ESlint понимал, что именно пропустить, используйте комментарии:

function onError(err, req, res, next) {
/* eslint no-unused-vars: 0 */
/* eslint max-params: [2, 4] */

res.sendStatus(500);
}

Для начала процесса достаточно в консоли ввести команду запуска бинарного файла:

node_modules/.bin/eslint .

ESlint умеет не только находить ошибки, но и исправлять их. Например, во всём проекте нет точки с запятой в конце строк, решили поставить потом. Если поправить правило в конфиге и запустить линтер с определённым ключом, инструмент сам всё сделает как надо:

node_modules/.bin/eslint . --fix

Однако далеко не все правила fixable, то есть не все могут быть автоматически исправлены. В таких случаях придётся править вручную. ESlint отлично работает в VS Code и WebStorm.


ESLint и TypeScript​

На просторах интернета можно встретить библиотеку TSLint. Она уже давно deprecated, что говорит о необходимости использовать ESlint для всего: JS или TS-файлов.

ESlint умеет «дружить» с TypeScript. Существуют отдельные плагины для этого:

npm install --save-dev @typescript-eslint/parser
npm install --save-dev @typescript-eslint/eslint-plugin

Правила для TS пишутся точно так же, как и для JS:

{
"extends": "airbnb",
"parser": "@typescript-eslint/parser",
"plugins": ["@typescript-eslint"],
"rules": {
"max-len": [2, 100],
"@typescript-eslint/no-unused-vars": 2
}
}


ESLint - установка​

ESLint — это утилита, которая может анализировать написанный код. Фактически, это статический анализатор кода, и он может находить синтаксические ошибки, баги или неточности форматирования. В других языках, например, Go, это является неотъемлемой частью языка программирования.

1. Установить ESLint:​

npm i -g eslint - Глобально

npm i --save-dev - Локально


2. Инициализация:​

eslint --init

Ответить на вопросы:

> To check syntax and find problems
> JavaScript modules (import/export)
> React
> TypeScript
> Browser
> JSON

Автоматически установятся пакеты и создастся конфиг-файл .eslintrc.json


3. .vscode/settings.json (Нужно установить плагин в браузере ESLint)​

{
"editor.codeActionsOnSave": {
"source.fixAll.eslint": true
},
"eslint.validate": ["javascript"]
}

4. Установка конфига eslint-config-airbnb​

npm install --save-dev eslint-config-airbnb


5. .eslintignore​

Какие файлы не проверять (игнорировать)

/dist
**/*.min.js
/node_modules

6. Конфиг-файл .eslintrc.json​

Примерный конфиг

{
"env": {
"browser": true,
"es2021": true
},
"extends": [
"airbnb",
"eslint:recommended",
"plugin:@typescript-eslint/recommended"
],
"overrides": [],
"parser": "@typescript-eslint/parser",
"parserOptions": {
"ecmaVersion": "latest",
"sourceType": "module"
},
"plugins": ["@typescript-eslint"],
"rules": {
"quotes": ["error", "single"],
"semi": ["error", "always"],
"indent": ["error", 2],
"no-unused-vars": 2,
"max-len": [1, 100],
"max-params": [2, 3]
}
}

7. npm-cкрипты​

"lint": "eslint . ",
"lint:fix": "eslint . --fix"

Prettier​

1. Устоновить плагин для VSCode​


2. Конфиг .prettierrc​

{
"endOfLine": "auto",
"singleQuote": true,
"jsxSingleQuote": true,
"arrowParens": "avoid",
"semi": true,
"useTabs": false,
"trailingComma": "all",
"tabWidth": 2
}

3. .prettierignore​

Ignore artifacts:

node_modules
public
.next
.swc
yarn.lock
package-lock.json

4. Установка пакетов prettier, @types/prettier​

yarn add -D prettier @types/prettier

.prettierrc
{
"semi": false,
"singleQuote": true,
"jsxSingleQuote": true,
"arrowParens": "avoid",
"importorder": [
"<THIRD_PARTY_MODULES>" ,
"^@/components/(.*)$"
"^@/hooks/ (.*)$"
"^@/services/(.*)$",
"^@/assets/(.*)$",
"^@/providers/(.*)$",
"^@/providers/(.*)$",
"^ ../(.*)$",
"^./(.*)$"
],
"importOrderSeparation": true,
"importOrderSortSpecifiers": true
}

5. Npm-скрипты​

"prettier:check": "prettier --check .",
"prettier:fix": "prettier --write .",

6. Конфиг редактора VsCode​

settings.json
{
"typescript.tsdk": "node_modules/typescript/lib",
"editor.defaultFormatter": "esbenp.prettier-vscode",
"editor.formatOnSave": true,
"editor.formatOnPaste": false,
"prettier.singleQuote": true,
"[typescriptreact]": {
"editor.defaultFormatter": "esbenp.prettier-vscode"
},
"[typescript]": {
"editor.defaultFormatter": "esbenp.prettier-vscode"
},
"[scss]": {
"editor.defaultFormatter": "esbenp.prettier-vscode"
},
"[jsonc]": {
"editor.defaultFormatter": "esbenp.prettier-vscode"
},
"[json]": {
"editor.defaultFormatter": "esbenp.prettier-vscode"
}
}

7. Подружим с ESLint​

yarn add eslint-config-prettier

eslintrc.js
  ...
extends: ["plugin:react/recommended", "prettier"],
...

Husky​

Нужно для того, чтобы были проверки во время коммита. ЧТобы наличие ошибок не давало сделать коммит.

1. Установка husky и lint-staged​

  • npm install husky -D
  • npx husky install
  • npx husky add .husky/pre-commit "npx tsc --noEmit && npx eslint --fix . && npx prettier --write ."
  • npm install lint-staged -D

2. Конфиг для lint-staged​

lint-staged.config.js
module.exports = {
// this will check Typescript files
'**/*.(ts|tsx)': () => 'yarn tsc --noEmit',

// This will lint and format TypeScript and //JavaScript files
'**/*.(ts|tsx|js)': filenames => [
`yarn eslint --fix ${filenames.join(' ')}`,
`yarn prettier --write ${filenames.join(' ')}`,
],

// this will Format MarkDown and JSON
'**/*.(md|json)': filenames => `yarn prettier --write ${filenames.join(' ')}`,
};

3. Запись скрипта​

Go to the file under the .husky folder and open pre-commit and then replace the last line with . npx lint-staged


Stylelint​

Группировка css-стилей.

Линтинг — это не уникальный инструмент исключительно для JS- или TS-кода. Например, можно анализировать стили. Для этого есть специальный линтер, а именно stylelint. Устанавливается он так же легко, как и ESLint:

npm install --save-dev stylelint

Большой список правил и готовых наборов есть на сайте разработчиков утилиты. Конфиги очень похожи на ESLint. Прописывать их нужно в .stylelintrc.json:

{
"extends": "stylelint-config-standard",
"rules": {
"color-hex-case": "lower"
},
"ignoreFiles": ["build/*"]
}

Обратите внимание, что они похожи, но не идентичны, поскольку это всё-таки разные инструменты. Чтобы не ошибиться, лучше сверяться с документацией.

Stylelint «из коробки» умеет парсить не только CSS, но и SCSS, Sass, Less, SugarCSS. Также он поддерживает систему плагинов. Например, можно установить дополнительный плагин с набором правил именно для SCSS под названием stylelint-scss.

Линтер умеет работать с SCSS, но изначально он создавался именно как линтер для CSS. Плагин добавит больше специфических правил.

Пример конфига из документации плагина:

{
"plugins": [
"stylelint-scss"
],
"rules": {
// recommended rules
"at-rule-no-unknown": null,
"scss/at-rule-no-unknown": true,
...
...
// any other rules you'd want to change e.g.
"scss/dollar-variable-pattern": "^foo",
"scss/selector-no-redundant-nesting-selector": true,
}
}

editorconfig​

Также следует создать файл .editorconfig, где будут описаны табы или пробелы, размер отступов, кодировка и другие общие для всех файлов проекта правила. Он поддерживает большое количество IDE и редакторов кода, чтобы у всех коллег был единый общий стиль всех файлов:

Пример конфига:

[*]
indent_size = 4
indent_style = space

[*.json]
indent_size = 2

Нет «самого правильного стиля кода», есть то, что удобно всей команде. Если вы единственный разработчик на проекте, тогда речь только о вашем удобстве и «чувстве прекрасного», потому что договариваться ни с кем не нужно.

Одно из главных правил код-стайла — ваш код должен быть читаемым. Интерпретатор в JS готов многое простить, и браузеру обычно всё равно, как написан проект — главное, чтобы он работал. Внешний вид кода важен в первую очередь для людей. Не только для коллег или других разработчиков, которые будут пытаться в нём разобраться, но и для вас в будущем.

Всё учесть и продумать невозможно, поэтому существуют специальные инструменты, которые автоматизируют проверку код-стайла и не только. О них расскажем в следующих уроках этой темы.


Почему нужны линтеры и CodeStyle​

Код в проекте должен быть единообразен. Представьте, что вы читаете книгу на русском, а там на каждой странице текст написан по абсолютно разным правилам грамматики, орфографии и пунктуации. При чём часто эти правила ещё и взаимоисключающие. Вроде понять можно, но приходится на это тратить много усилий. Так и с кодом. Если от файла к файлу одно и то же писать по разному, это вызовет не только трудности в «чтении» такого проекта, но и станет причиной споров. Пример:

let foo = 1,
bar = 2,
baz = 3;

// vs

let foo = 1;
let bar = 2;
let baz = 3;

Или space против tab. Или использование let и const:

Посмотрите на обычный блок кода, который прислали на ревью:

exports.list = function (req, res) {
let notes = chats.findAll();
let data = {
chats: chats,
meta: req['meta'],
};

res.render('chats', data);
};

Однако после ревью встретим вот такие комментарии:

exports.list = function (req, res) {
// Используй стрелочные
let notes = chats.findAll(); // Используй const
let data = {
// И здесь
chats: chats, // Здесь можно просто `chats,`
meta: req['meta'], // Здесь можно так: req.meta
};

res.render('chats', data);
};

Подобное ревью максимально бесполезно. Оно отнимает много времени у коллег, которые будут друг другу писать одни и те же комментарии, не отличающиеся по смыслу. Определение единого код-стайла позволяет не только удобнее и проще поддерживать проект, но и уважать время коллег. Чем полезен код-стайл:

  • Упростит чтение кода всей команды;
  • Поможет избежать пустых конфликтов внутри;
  • Сделает код-ревью полезнее и быстрее;
  • Позволит избежать типичных ошибок в коде;
  • Сделает код качественнее.

Чтобы правила были описаны не только в конфиге инструментов линтера, в котором обычно много наследования от чужих конфигов, — стоит завести в проекте файл Codestyle.md, где описать свои правила как письменную договорённость в команде:


Тестеры​