Статический анализ кода

Как заставить компьютер проверять ваш код.

Время чтения: меньше 5 мин

Кратко

Секция статьи "Кратко"

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

Самый популярный линтер для JavaScript — это ESLint. Он находит участки кода, которые могут потенциально привести к ошибкам, и сообщает об этом.

Как пользоваться

Секция статьи "Как пользоваться"

Чтобы воспользоваться ESLint, нужно установить его через менеджер зависимостей в папке проекта:

        
          
          npm install --save-dev eslint
          npm install --save-dev eslint

        
        
          
        
      

После установки нужно инициализировать конфигурационный файл .eslintrc.json:

        
          
          npx eslint --init
          npx eslint --init

        
        
          
        
      

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

        
          
          {  // ...  "extends": "eslint:recommended",  // ...}
          {
  // ...
  "extends": "eslint:recommended",
  // ...
}

        
        
          
        
      

Теперь можно добавить в package.json новый скрипт, который будет запускать статический анализ:

        
          
          {  // ...  "scripts": {    "lint": "eslint ./**/*.js"  }  // ...}
          {
  // ...
  "scripts": {
    "lint": "eslint ./**/*.js"
  }
  // ...
}

        
        
          
        
      

После запуска линтера командой npm run lint, в консоли появится результат его работы.

Для наглядности положим в папку проекта JavaScript-файл с ошибками, которые ESLint способен отловить.

        
          
          // script.jsconst x = 12// Сравнения с -0 запрещены стандартной конфигурацией ESLint// При запуске он выведет ошибкуif (x === -0) {  console.log('Hello!')}
          // script.js

const x = 12

// Сравнения с -0 запрещены стандартной конфигурацией ESLint
// При запуске он выведет ошибку
if (x === -0) {
  console.log('Hello!')
}

        
        
          
        
      

Как понять

Секция статьи "Как понять"

Линтер — это программа, которая разбирает исходный код на стандартизированные кусочки, а потом даёт эти кусочки на проверку специальным плагинам. Плагин получает разобранный участок кода и проверяет его на корректность по ряду правил, которые определены в этом плагине.

Советы линтера — это не абсолютная истина. Скорее подсветка спорных моментов, на которые стоит обратить внимание.

Типичные проблемы, которые отлавливают линтеры:

Например, функцию parseFiles():

        
          
          async function parseFiles(files) {  const data = []  // parseFile будет вызываться последовательно  // сначала будет обработан первый файл  // потом второй, третий и так далее  for (const file of files) {    const parsed = await parseFile(file)    data.push(parsed)  }  return data}
          async function parseFiles(files) {
  const data = []

  // parseFile будет вызываться последовательно
  // сначала будет обработан первый файл
  // потом второй, третий и так далее
  for (const file of files) {
    const parsed = await parseFile(file)
    data.push(parsed)
  }

  return data
}

        
        
          
        
      

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

        
          
          async function parseFiles(files) {  // parseFile вызовется для всех файлов почти одновременно  const data = await Promise.all(files.map((file) => parseFile(file)))  return data}
          async function parseFiles(files) {
  // parseFile вызовется для всех файлов почти одновременно
  const data = await Promise.all(files.map((file) => parseFile(file)))

  return data
}

        
        
          
        
      

Подобные исправления не всегда будут корректны, иногда разработчику правда нужно обрабатывать файлы последовательно. Но чаще всего, это не так. Статический анализатор обратит внимание программиста на это место, а программист уже решит — актуальна ли эта проблема для конкретного кейса.

Статический анализатор работает только с исходными текстами программы, но никогда не запускает само приложение. Поэтому, не все проблемы можно отловить линтингом. Статический анализ — это отличное дополнение к другим способам проверки кода: код-ревью, юнит и интеграционным тестам.

На практике

Секция статьи "На практике"

Игорь Камышев советует

Секция статьи "Игорь Камышев советует"

Линтер для CSS

Секция статьи "Линтер для CSS"

На самом деле, статически проанализировать можно почти любой язык программирования. Поэтому, при разработке веб-приложений часто не останавливаются на использовании ESLint, а добавляют ещё Stylelint — линтер для стилей. Он умеет работать не только с CSS, но и почти с любым языком описания стилей, например, CSS-in-JS, SCSS или Stylus.

Автоматический запуск

Секция статьи "Автоматический запуск"

Не хочется нагружать голову разработчика необходимостью запускать линтер самостоятельно, и это автоматизируют:

  • запускают линтер на серверах и показывают результат программисту, этот подход называют CI, он широко применяется в индустрии;
  • добавляют автоматический вызов линтера при создании нового коммита в репозитории;
  • интегрируют статический анализ в среду разработки, так можно получать рекомендации прямо во время написания кода и сразу на них реагировать.